diff --git a/CREDITS b/CREDITS
index 206d0fc..33a2f2d 100644
--- a/CREDITS
+++ b/CREDITS
@@ -637,14 +637,13 @@ S: 14509 NE 39th Street #1096
 S: Bellevue, Washington 98007
 S: USA
 
-N: Christopher L. Cheney
-E: ccheney@debian.org
-E: ccheney@cheney.cx
-W: http://www.cheney.cx
+N: Chris Cheney
+E: chris.cheney@gmail.com
+E: ccheney@redhat.com
 P: 1024D/8E384AF2 2D31 1927 87D7 1F24 9FF9  1BC5 D106 5AB3 8E38 4AF2
 D: Vista Imaging usb webcam driver
-S: 314 Prince of Wales
-S: Conroe, TX 77304
+S: 2308 Therrell Way
+S: McKinney, TX 75070
 S: USA
 
 N: Stuart Cheshire
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index dda81ff..45ae709 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -351,6 +351,7 @@ Description:
 		6kohm_to_gnd: connected to ground via a 6kOhm resistor,
 		20kohm_to_gnd: connected to ground via a 20kOhm resistor,
 		100kohm_to_gnd: connected to ground via an 100kOhm resistor,
+		500kohm_to_gnd: connected to ground via a 500kOhm resistor,
 		three_state: left floating.
 		For a list of available output power down options read
 		outX_powerdown_mode_available. If Y is not present the
@@ -792,3 +793,11 @@ Contact:	linux-iio@vger.kernel.org
 Description:
 		This attribute is used to read the amount of quadrature error
 		present in the device at a given time.
+
+What:		/sys/bus/iio/devices/iio:deviceX/store_eeprom
+KernelVersion:	3.4.0
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Writing '1' stores the current device configuration into
+		on-chip EEPROM. After power-up or chip reset the device will
+		automatically load the saved configuration.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 b/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
index 2ce9c3f..a91aeab 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
+++ b/Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
@@ -18,14 +18,6 @@ Description:
 		Reading returns either '1' or '0'. '1' means that the
 		pllY is locked.
 
-What:		/sys/bus/iio/devices/iio:deviceX/store_eeprom
-KernelVersion:	3.4.0
-Contact:	linux-iio@vger.kernel.org
-Description:
-		Writing '1' stores the current device configuration into
-		on-chip EEPROM. After power-up or chip reset the device will
-		automatically load the saved configuration.
-
 What:		/sys/bus/iio/devices/iio:deviceX/sync_dividers
 KernelVersion:	3.4.0
 Contact:	linux-iio@vger.kernel.org
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 b/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
index d89aded..1254457 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
+++ b/Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
@@ -18,4 +18,4 @@ Description:
 		adjust the reference frequency accordingly.
 		The value written has no effect until out_altvoltageY_frequency
 		is updated. Consider to use out_altvoltageY_powerdown to power
-		down the PLL and it's RFOut buffers during REFin changes.
+		down the PLL and its RFOut buffers during REFin changes.
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
new file mode 100644
index 0000000..31942ef
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -0,0 +1,26 @@
+What:		/sys/fs/f2fs/<disk>/gc_max_sleep_time
+Date:		July 2013
+Contact:	"Namjae Jeon" <namjae.jeon@samsung.com>
+Description:
+		 Controls the maximun sleep time for gc_thread. Time
+		 is in milliseconds.
+
+What:		/sys/fs/f2fs/<disk>/gc_min_sleep_time
+Date:		July 2013
+Contact:	"Namjae Jeon" <namjae.jeon@samsung.com>
+Description:
+		 Controls the minimum sleep time for gc_thread. Time
+		 is in milliseconds.
+
+What:		/sys/fs/f2fs/<disk>/gc_no_gc_sleep_time
+Date:		July 2013
+Contact:	"Namjae Jeon" <namjae.jeon@samsung.com>
+Description:
+		 Controls the default sleep time for gc_thread. Time
+		 is in milliseconds.
+
+What:		/sys/fs/f2fs/<disk>/gc_idle
+Date:		July 2013
+Contact:	"Namjae Jeon" <namjae.jeon@samsung.com>
+Description:
+		 Controls the victim selection policy for garbage collection.
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 7d1278e..87e22ec 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -2212,6 +2212,12 @@ void intel_crt_init(struct drm_device *dev)
 !Iinclude/drm/drm_rect.h
 !Edrivers/gpu/drm/drm_rect.c
     </sect2>
+    <sect2>
+      <title>VMA Offset Manager</title>
+!Pdrivers/gpu/drm/drm_vma_manager.c vma offset manager
+!Edrivers/gpu/drm/drm_vma_manager.c
+!Iinclude/drm/drm_vma_manager.h
+    </sect2>
   </sect1>
 
   <!-- Internals: kms properties -->
diff --git a/Documentation/DocBook/media/v4l/lirc_device_interface.xml b/Documentation/DocBook/media/v4l/lirc_device_interface.xml
index 8d7eb6b..34cada2 100644
--- a/Documentation/DocBook/media/v4l/lirc_device_interface.xml
+++ b/Documentation/DocBook/media/v4l/lirc_device_interface.xml
@@ -46,7 +46,9 @@ describing an IR signal are read from the chardev.</para>
 values. Pulses and spaces are only marked implicitly by their position. The
 data must start and end with a pulse, therefore, the data must always include
 an uneven number of samples. The write function must block until the data has
-been transmitted by the hardware.</para>
+been transmitted by the hardware. If more data is provided than the hardware
+can send, the driver returns EINVAL.</para>
+
 </section>
 
 <section id="lirc_ioctl">
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml b/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
index 4874849..098ff48 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
@@ -92,8 +92,8 @@ to add them.</para>
 	    <entry>int</entry>
 	    <entry><structfield>quality</structfield></entry>
 	    <entry>Deprecated. If <link linkend="jpeg-quality-control"><constant>
-	    V4L2_CID_JPEG_IMAGE_QUALITY</constant></link> control is exposed by
-	    a driver applications should use it instead and ignore this field.
+	    V4L2_CID_JPEG_COMPRESSION_QUALITY</constant></link> control is exposed
+	    by a driver applications should use it instead and ignore this field.
 	    </entry>
 	  </row>
 	  <row>
diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl
index 6a8b715..9c92bb8 100644
--- a/Documentation/DocBook/media_api.tmpl
+++ b/Documentation/DocBook/media_api.tmpl
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
 <!ENTITY % media-entities SYSTEM "./media-entities.tmpl"> %media-entities;
 <!ENTITY media-indices SYSTEM "./media-indices.tmpl">
 
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index fe122d6..a248f42 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -1224,8 +1224,6 @@ in this page</entry>
 #define NAND_BBT_CREATE		0x00000200
 /* Search good / bad pattern through all pages of a block */
 #define NAND_BBT_SCANALLPAGES	0x00000400
-/* Scan block empty during good / bad block scan */
-#define NAND_BBT_SCANEMPTY	0x00000800
 /* Write bbt if neccecary */
 #define NAND_BBT_WRITE		0x00001000
 /* Read and write back block contents when writing bbt */
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 7f40c72..350be9a 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -39,7 +39,7 @@ in read-mostly situations.  This algorithm does take pains to avoid
 write-side contention and parallelize the other write-side overheads by
 providing a fine-grained locking design, however, it would be interesting
 to see how much of the performance advantage reported in 1990 remains
-in 2004.
+in 2004 (to say nothing of 2013).
 
 At about this same time, Adams [Adams91] described ``chaotic relaxation'',
 where the normal barriers between successive iterations of convergent
@@ -86,9 +86,9 @@ DYNIX/ptx kernel.  The corresponding conference paper appeared in 1998
 [McKenney98].
 
 In 1999, the Tornado and K42 groups described their "generations"
-mechanism, which quite similar to RCU [Gamsa99].  These operating systems
-made pervasive use of RCU in place of "existence locks", which greatly
-simplifies locking hierarchies.
+mechanism, which is quite similar to RCU [Gamsa99].  These operating
+systems made pervasive use of RCU in place of "existence locks", which
+greatly simplifies locking hierarchies and helps avoid deadlocks.
 
 2001 saw the first RCU presentation involving Linux [McKenney01a]
 at OLS.  The resulting abundance of RCU patches was presented the
@@ -106,8 +106,11 @@ these techniques still impose significant read-side overhead in the
 form of memory barriers.  Researchers at Sun worked along similar lines
 in the same timeframe [HerlihyLM02].  These techniques can be thought
 of as inside-out reference counts, where the count is represented by the
-number of hazard pointers referencing a given data structure (rather than
-the more conventional counter field within the data structure itself).
+number of hazard pointers referencing a given data structure rather than
+the more conventional counter field within the data structure itself.
+The key advantage of inside-out reference counts is that they can be
+stored in immortal variables, thus allowing races between access and
+deletion to be avoided.
 
 By the same token, RCU can be thought of as a "bulk reference count",
 where some form of reference counter covers all reference by a given CPU
@@ -179,7 +182,25 @@ tree using software transactional memory to protect concurrent updates
 (strange, but true!) [PhilHoward2011RCUTMRBTree], yet another variant of
 RCU-protected resizeable hash tables [Triplett:2011:RPHash], the 3.0 RCU
 trainwreck [PaulEMcKenney2011RCU3.0trainwreck], and Neil Brown's "Meet the
-Lockers" LWN article [NeilBrown2011MeetTheLockers].
+Lockers" LWN article [NeilBrown2011MeetTheLockers].  Some academic
+work looked at debugging uses of RCU [Seyster:2011:RFA:2075416.2075425].
+
+In 2012, Josh Triplett received his Ph.D. with his dissertation
+covering RCU-protected resizable hash tables and the relationship
+between memory barriers and read-side traversal order:  If the updater
+is making changes in the opposite direction from the read-side traveral
+order, the updater need only execute a memory-barrier instruction,
+but if in the same direction, the updater needs to wait for a grace
+period between the individual updates [JoshTriplettPhD].  Also in 2012,
+after seventeen years of attempts, an RCU paper made it into a top-flight
+academic journal, IEEE Transactions on Parallel and Distributed Systems
+[MathieuDesnoyers2012URCU].  A group of researchers in Spain applied
+user-level RCU to crowd simulation [GuillermoVigueras2012RCUCrowd], and
+another group of researchers in Europe produced a formal description of
+RCU based on separation logic [AlexeyGotsman2012VerifyGraceExtended],
+which was published in the 2013 European Symposium on Programming
+[AlexeyGotsman2013ESOPRCU].
+
 
 
 Bibtex Entries
@@ -193,13 +214,12 @@ Bibtex Entries
 ,volume="5"
 ,number="3"
 ,pages="354-382"
-,note="Available:
-\url{http://portal.acm.org/citation.cfm?id=320619&dl=GUIDE,}
-[Viewed December 3, 2007]"
 ,annotation={
 	Use garbage collector to clean up data after everyone is done with it.
 	.
 	Oldest use of something vaguely resembling RCU that I have found.
+	http://portal.acm.org/citation.cfm?id=320619&dl=GUIDE,
+	[Viewed December 3, 2007]
 }
 }
 
@@ -309,7 +329,7 @@ for Programming Languages and Operating Systems}"
 ,doi = {http://doi.acm.org/10.1145/42392.42399}
 ,publisher = {ACM}
 ,address = {New York, NY, USA}
-,annotation= {
+,annotation={
 	At the top of page 307: "Conflicts with deposits and withdrawals
 	are necessary if the reported total is to be up to date.  They
 	could be avoided by having total return a sum that is slightly
@@ -346,8 +366,9 @@ for Programming Languages and Operating Systems}"
 }
 }
 
-@Book{Adams91
-,Author="Gregory R. Adams"
+# Was Adams91, see also syncrefs.bib.
+@Book{Andrews91textbook
+,Author="Gregory R. Andrews"
 ,title="Concurrent Programming, Principles, and Practices"
 ,Publisher="Benjamin Cummins"
 ,Year="1991"
@@ -398,39 +419,39 @@ for Programming Languages and Operating Systems}"
 }
 }
 
-@conference{Pu95a,
-Author = "Calton Pu and Tito Autrey and Andrew Black and Charles Consel and
+@conference{Pu95a
+,Author = "Calton Pu and Tito Autrey and Andrew Black and Charles Consel and
 Crispin Cowan and Jon Inouye and Lakshmi Kethana and Jonathan Walpole and
-Ke Zhang",
-Title = "Optimistic Incremental Specialization: Streamlining a Commercial
-Operating System",
-Booktitle = "15\textsuperscript{th} ACM Symposium on
-Operating Systems Principles (SOSP'95)",
-address = "Copper Mountain, CO",
-month="December",
-year="1995",
-pages="314-321",
-annotation="
+Ke Zhang"
+,Title = "Optimistic Incremental Specialization: Streamlining a Commercial
+,Operating System"
+,Booktitle = "15\textsuperscript{th} ACM Symposium on
+,Operating Systems Principles (SOSP'95)"
+,address = "Copper Mountain, CO"
+,month="December"
+,year="1995"
+,pages="314-321"
+,annotation={
 	Uses a replugger, but with a flag to signal when people are
 	using the resource at hand.  Only one reader at a time.
-"
-}
-
-@conference{Cowan96a,
-Author = "Crispin Cowan and Tito Autrey and Charles Krasic and
-Calton Pu and Jonathan Walpole",
-Title = "Fast Concurrent Dynamic Linking for an Adaptive Operating System",
-Booktitle = "International Conference on Configurable Distributed Systems
-(ICCDS'96)",
-address = "Annapolis, MD",
-month="May",
-year="1996",
-pages="108",
-isbn="0-8186-7395-8",
-annotation="
+}
+}
+
+@conference{Cowan96a
+,Author = "Crispin Cowan and Tito Autrey and Charles Krasic and
+,Calton Pu and Jonathan Walpole"
+,Title = "Fast Concurrent Dynamic Linking for an Adaptive Operating System"
+,Booktitle = "International Conference on Configurable Distributed Systems
+(ICCDS'96)"
+,address = "Annapolis, MD"
+,month="May"
+,year="1996"
+,pages="108"
+,isbn="0-8186-7395-8"
+,annotation={
 	Uses a replugger, but with a counter to signal when people are
 	using the resource at hand.  Allows multiple readers.
-"
+}
 }
 
 @techreport{Slingwine95
@@ -493,14 +514,13 @@ Problems"
 ,Year="1998"
 ,pages="509-518"
 ,Address="Las Vegas, NV"
-,note="Available:
-\url{http://www.rdrop.com/users/paulmck/RCU/rclockpdcsproof.pdf}
-[Viewed December 3, 2007]"
 ,annotation={
 	Describes and analyzes RCU mechanism in DYNIX/ptx.  Describes
 	application to linked list update and log-buffer flushing.
 	Defines 'quiescent state'.  Includes both measured and analytic
 	evaluation.
+	http://www.rdrop.com/users/paulmck/RCU/rclockpdcsproof.pdf
+	[Viewed December 3, 2007]
 }
 }
 
@@ -514,13 +534,12 @@ Operating System Design and Implementation}"
 ,Year="1999"
 ,pages="87-100"
 ,Address="New Orleans, LA"
-,note="Available:
-\url{http://www.usenix.org/events/osdi99/full_papers/gamsa/gamsa.pdf}
-[Viewed August 30, 2006]"
 ,annotation={
 	Use of RCU-like facility in K42/Tornado.  Another independent
 	invention of RCU.
 	See especially pages 7-9 (Section 5).
+	http://www.usenix.org/events/osdi99/full_papers/gamsa/gamsa.pdf
+	[Viewed August 30, 2006]
 }
 }
 
@@ -611,9 +630,9 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=100259266316456&w=2}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Memory-barrier and Alpha thread.  100 messages, not too bad...
-"
+}
 }
 
 @unpublished{Spraul01
@@ -624,10 +643,10 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=100264675012867&w=2}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Suggested burying memory barriers in Linux's list-manipulation
 	primitives.
-"
+}
 }
 
 @unpublished{LinusTorvalds2001a
@@ -638,6 +657,8 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 ,note="Available:
 \url{http://lkml.org/lkml/2001/10/13/105}
 [Viewed August 21, 2004]"
+,annotation={
+}
 }
 
 @unpublished{Blanchard02a
@@ -657,10 +678,10 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 ,Month="June"
 ,Year="2002"
 ,pages="289-300"
-,annotation="
+,annotation={
 	Measured scalability of Linux 2.4 kernel's directory-entry cache
 	(dcache), and measured some scalability enhancements.
-"
+}
 }
 
 @Conference{McKenney02a
@@ -674,10 +695,10 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="Available:
 \url{http://www.linux.org.uk/~ajh/ols2002_proceedings.pdf.gz}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Presented and compared a number of RCU implementations for the
 	Linux kernel.
-"
+}
 }
 
 @unpublished{Sarma02a
@@ -688,9 +709,9 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=102645767914212&w=2}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Compare fastwalk and RCU for dcache.  RCU won.
-"
+}
 }
 
 @unpublished{Barbieri02
@@ -701,9 +722,9 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=103082050621241&w=2}
 [Viewed: June 23, 2004]"
-,annotation="
+,annotation={
 	Suggested RCU for vfs\_shared\_cred.
-"
+}
 }
 
 @unpublished{Dickins02a
@@ -722,10 +743,10 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=103462075416638&w=2}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Performance of dcache RCU on kernbench for 16x NUMA-Q and 1x,
 	2x, and 4x systems.  RCU does no harm, and helps on 16x.
-"
+}
 }
 
 @unpublished{LinusTorvalds2003a
@@ -736,14 +757,14 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="Available:
 \url{http://lkml.org/lkml/2003/3/9/205}
 [Viewed March 13, 2006]"
-,annotation="
+,annotation={
 	Linus suggests replacing brlock with RCU and/or seqlocks:
 	.
 	'It's entirely possible that the current user could be replaced
 	by RCU and/or seqlocks, and we could get rid of brlocks entirely.'
 	.
 	Steve Hemminger responds by replacing them with RCU.
-"
+}
 }
 
 @article{Appavoo03a
@@ -758,9 +779,9 @@ B. Rosenburg and M. Stumm and J. Xenidis"
 ,volume="42"
 ,number="1"
 ,pages="60-76"
-,annotation="
+,annotation={
 	Use of RCU to enable hot-swapping for autonomic behavior in K42.
-"
+}
 }
 
 @unpublished{Seigh03
@@ -769,9 +790,9 @@ B. Rosenburg and M. Stumm and J. Xenidis"
 ,Year="2003"
 ,Month="March"
 ,note="email correspondence"
-,annotation="
+,annotation={
 	Described the relationship of the VM/XA passive serialization to RCU.
-"
+}
 }
 
 @Conference{Arcangeli03
@@ -785,14 +806,12 @@ Dipankar Sarma"
 ,year="2003"
 ,month="June"
 ,pages="297-310"
-,note="Available:
-\url{http://www.rdrop.com/users/paulmck/RCU/rcu.FREENIX.2003.06.14.pdf}
-[Viewed November 21, 2007]"
-,annotation="
+,annotation={
 	Compared updated RCU implementations for the Linux kernel, and
 	described System V IPC use of RCU, including order-of-magnitude
 	performance improvements.
-"
+	http://www.rdrop.com/users/paulmck/RCU/rcu.FREENIX.2003.06.14.pdf
+}
 }
 
 @Conference{Soules03a
@@ -820,10 +839,10 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,note="Available:
 \url{http://www.linuxjournal.com/article/6993}
 [Viewed November 14, 2007]"
-,annotation="
+,annotation={
 	Reader-friendly intro to RCU, with the infamous old-man-and-brat
 	cartoon.
-"
+}
 }
 
 @unpublished{Sarma03a
@@ -832,7 +851,9 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,month="December"
 ,year="2003"
 ,note="Message ID: 20031222180114.GA2248@in.ibm.com"
-,annotation="dipankar/ct.2004.03.27/RCUll.2003.12.22.patch"
+,annotation={
+	dipankar/ct.2004.03.27/RCUll.2003.12.22.patch
+}
 }
 
 @techreport{Friedberg03a
@@ -844,11 +865,11 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,number="US Patent 6,662,184"
 ,month="December"
 ,pages="112"
-,annotation="
+,annotation={
 	Applies RCU to a wildcard-search Patricia tree in order to permit
 	synchronization-free lookup.  RCU is used to retain removed nodes
 	for a grace period before freeing them.
-"
+}
 }
 
 @article{McKenney04a
@@ -860,12 +881,11 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,volume="1"
 ,number="118"
 ,pages="38-46"
-,note="Available:
-\url{http://www.linuxjournal.com/node/7124}
-[Viewed December 26, 2010]"
-,annotation="
+,annotation={
 	Reader friendly intro to dcache and RCU.
-"
+	http://www.linuxjournal.com/node/7124
+	[Viewed December 26, 2010]
+}
 }
 
 @Conference{McKenney04b
@@ -879,10 +899,10 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 \url{http://www.linux.org.au/conf/2004/abstracts.html#90}
 \url{http://www.rdrop.com/users/paulmck/RCU/lockperf.2004.01.17a.pdf}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Compares performance of RCU to that of other locking primitives
 	over a number of CPUs (x86, Opteron, Itanium, and PPC).
-"
+}
 }
 
 @unpublished{Sarma04a
@@ -891,7 +911,9 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,month="March"
 ,year="2004"
 ,note="\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=108003746402892&w=2}"
-,annotation="Head of thread: dipankar/2004.03.23/rcu-low-lat.1.patch"
+,annotation={
+	Head of thread: dipankar/2004.03.23/rcu-low-lat.1.patch
+}
 }
 
 @unpublished{Sarma04b
@@ -900,7 +922,9 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,month="March"
 ,year="2004"
 ,note="\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=108016474829546&w=2}"
-,annotation="dipankar/rcuth.2004.03.24/rcu-throttle.patch"
+,annotation={
+	dipankar/rcuth.2004.03.24/rcu-throttle.patch
+}
 }
 
 @unpublished{Spraul04a
@@ -911,9 +935,9 @@ Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=108546407726602&w=2}
 [Viewed June 23, 2004]"
-,annotation="
+,annotation={
 	Hierarchical-bitmap patch for RCU infrastructure.
-"
+}
 }
 
 @unpublished{Steiner04a
@@ -950,10 +974,12 @@ Realtime Applications"
 ,year="2004"
 ,month="June"
 ,pages="182-191"
-,annotation="
+,annotation={
 	Describes and compares a number of modifications to the Linux RCU
 	implementation that make it friendly to realtime applications.
-"
+	https://www.usenix.org/conference/2004-usenix-annual-technical-conference/making-rcu-safe-deep-sub-millisecond-response
+	[Viewed July 26, 2012]
+}
 }
 
 @phdthesis{PaulEdwardMcKenneyPhD
@@ -964,14 +990,13 @@ in Operating System Kernels"
 ,school="OGI School of Science and Engineering at
 Oregon Health and Sciences University"
 ,year="2004"
-,note="Available:
-\url{http://www.rdrop.com/users/paulmck/RCU/RCUdissertation.2004.07.14e1.pdf}
-[Viewed October 15, 2004]"
-,annotation="
+,annotation={
 	Describes RCU implementations and presents design patterns
 	corresponding to common uses of RCU in several operating-system
 	kernels.
-"
+	http://www.rdrop.com/users/paulmck/RCU/RCUdissertation.2004.07.14e1.pdf
+	[Viewed October 15, 2004]
+}
 }
 
 @unpublished{PaulEMcKenney2004rcu:dereference
@@ -982,9 +1007,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://lkml.org/lkml/2004/8/6/237}
 [Viewed June 8, 2010]"
-,annotation="
+,annotation={
 	Introduce rcu_dereference().
-"
+}
 }
 
 @unpublished{JimHouston04a
@@ -995,11 +1020,11 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://lkml.org/lkml/2004/8/30/87}
 [Viewed February 17, 2005]"
-,annotation="
+,annotation={
 	Uses active code in rcu_read_lock() and rcu_read_unlock() to
 	make RCU happen, allowing RCU to function on CPUs that do not
 	receive a scheduling-clock interrupt.
-"
+}
 }
 
 @unpublished{TomHart04a
@@ -1010,9 +1035,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://www.cs.toronto.edu/~tomhart/masters_thesis.html}
 [Viewed October 15, 2004]"
-,annotation="
+,annotation={
 	Proposes comparing RCU to lock-free methods for the Linux kernel.
-"
+}
 }
 
 @unpublished{Vaddagiri04a
@@ -1023,9 +1048,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?t=109395731700004&r=1&w=2}
 [Viewed October 18, 2004]"
-,annotation="
+,annotation={
 	Srivatsa's RCU patch for tcp_ehash lookup.
-"
+}
 }
 
 @unpublished{Thirumalai04a
@@ -1036,9 +1061,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?t=109144217400003&r=1&w=2}
 [Viewed October 18, 2004]"
-,annotation="
+,annotation={
 	Ravikiran's lockfree FD patch.
-"
+}
 }
 
 @unpublished{Thirumalai04b
@@ -1049,9 +1074,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://marc.theaimsgroup.com/?l=linux-kernel&m=109152521410459&w=2}
 [Viewed October 18, 2004]"
-,annotation="
+,annotation={
 	Ravikiran's lockfree FD patch.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2004rcu:assign:pointer
@@ -1062,9 +1087,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://lkml.org/lkml/2004/10/23/241}
 [Viewed June 8, 2010]"
-,annotation="
+,annotation={
 	Introduce rcu_assign_pointer().
-"
+}
 }
 
 @unpublished{JamesMorris04a
@@ -1073,12 +1098,12 @@ Oregon Health and Sciences University"
 ,day="15"
 ,month="November"
 ,year="2004"
-,note="Available:
-\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=110054979416004&w=2}
-[Viewed December 10, 2004]"
-,annotation="
+,note="\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=110054979416004&w=2}"
+,annotation={
 	James Morris posts Kaigai Kohei's patch to LKML.
-"
+	[Viewed December 10, 2004]
+	Kaigai's patch is at https://lkml.org/lkml/2004/9/27/52
+}
 }
 
 @unpublished{JamesMorris04b
@@ -1089,9 +1114,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://www.livejournal.com/users/james_morris/2153.html}
 [Viewed December 10, 2004]"
-,annotation="
+,annotation={
 	RCU helps SELinux performance.  ;-)  Made LWN.
-"
+}
 }
 
 @unpublished{PaulMcKenney2005RCUSemantics
@@ -1103,9 +1128,9 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/rcu-semantics.2005.01.30a.pdf}
 [Viewed December 6, 2009]"
-,annotation="
+,annotation={
 	Early derivation of RCU semantics.
-"
+}
 }
 
 @unpublished{PaulMcKenney2005e
@@ -1117,10 +1142,10 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://lkml.org/lkml/2005/3/17/199}
 [Viewed September 5, 2005]"
-,annotation="
+,annotation={
 	First posting showing how RCU can be safely adapted for
 	preemptable RCU read side critical sections.
-"
+}
 }
 
 @unpublished{EsbenNeilsen2005a
@@ -1132,12 +1157,12 @@ Oregon Health and Sciences University"
 ,note="Available:
 \url{http://lkml.org/lkml/2005/3/18/122}
 [Viewed March 30, 2006]"
-,annotation="
+,annotation={
 	Esben Neilsen suggests read-side suppression of grace-period
 	processing for crude-but-workable realtime RCU.  The downside
-	is indefinite grace periods...But this is OK for experimentation
+	is indefinite grace periods...  But this is OK for experimentation
 	and testing.
-"
+}
 }
 
 @unpublished{TomHart05a
@@ -1149,10 +1174,10 @@ Data Structures"
 ,note="Available:
 \url{ftp://ftp.cs.toronto.edu/csrg-technical-reports/515/}
 [Viewed March 4, 2005]"
-,annotation="
+,annotation={
 	Comparison of RCU, QBSR, and EBSR.  RCU wins for read-mostly
 	workloads.  ;-)
-"
+}
 }
 
 @unpublished{JonCorbet2005DeprecateSyncKernel
@@ -1164,10 +1189,10 @@ Data Structures"
 ,note="Available:
 \url{http://lwn.net/Articles/134484/}
 [Viewed May 3, 2005]"
-,annotation="
+,annotation={
 	Jon Corbet describes deprecation of synchronize_kernel()
 	in favor of synchronize_rcu() and synchronize_sched().
-"
+}
 }
 
 @unpublished{PaulMcKenney05a
@@ -1178,10 +1203,10 @@ Data Structures"
 ,note="Available:
 \url{http://lkml.org/lkml/2005/5/9/185}
 [Viewed May 13, 2005]"
-,annotation="
+,annotation={
 	First publication of working lock-based deferred free patches
 	for the CONFIG_PREEMPT_RT environment.
-"
+}
 }
 
 @conference{PaulMcKenney05b
@@ -1194,10 +1219,10 @@ Data Structures"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/realtimeRCU.2005.04.23a.pdf}
 [Viewed May 13, 2005]"
-,annotation="
+,annotation={
 	Realtime turns into making RCU yet more realtime friendly.
 	http://lca2005.linux.org.au/Papers/Paul%20McKenney/Towards%20Hard%20Realtime%20Response%20from%20the%20Linux%20Kernel/LKS.2005.04.22a.pdf
-"
+}
 }
 
 @unpublished{PaulEMcKenneyHomePage
@@ -1208,9 +1233,9 @@ Data Structures"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/}
 [Viewed May 25, 2005]"
-,annotation="
+,annotation={
 	Paul McKenney's home page.
-"
+}
 }
 
 @unpublished{PaulEMcKenneyRCUPage
@@ -1221,9 +1246,9 @@ Data Structures"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU}
 [Viewed May 25, 2005]"
-,annotation="
+,annotation={
 	Paul McKenney's RCU page.
-"
+}
 }
 
 @unpublished{JosephSeigh2005a
@@ -1232,10 +1257,10 @@ Data Structures"
 ,month="July"
 ,year="2005"
 ,note="Personal communication"
-,annotation="
+,annotation={
 	Joe Seigh announcing his atomic-ptr-plus project.
 	http://sourceforge.net/projects/atomic-ptr-plus/
-"
+}
 }
 
 @unpublished{JosephSeigh2005b
@@ -1247,9 +1272,9 @@ Data Structures"
 ,note="Available:
 \url{http://sourceforge.net/projects/atomic-ptr-plus/}
 [Viewed August 8, 2005]"
-,annotation="
+,annotation={
 	Joe Seigh's atomic-ptr-plus project.
-"
+}
 }
 
 @unpublished{PaulMcKenney2005c
@@ -1261,9 +1286,9 @@ Data Structures"
 ,note="Available:
 \url{http://lkml.org/lkml/2005/8/1/155}
 [Viewed March 14, 2006]"
-,annotation="
+,annotation={
 	First operating counter-based realtime RCU patch posted to LKML.
-"
+}
 }
 
 @unpublished{PaulMcKenney2005d
@@ -1275,11 +1300,11 @@ Data Structures"
 ,note="Available:
 \url{http://lkml.org/lkml/2005/8/8/108}
 [Viewed March 14, 2006]"
-,annotation="
+,annotation={
 	First operating counter-based realtime RCU patch posted to LKML,
 	but fixed so that various unusual combinations of configuration
 	parameters all function properly.
-"
+}
 }
 
 @unpublished{PaulMcKenney2005rcutorture
@@ -1291,9 +1316,25 @@ Data Structures"
 ,note="Available:
 \url{http://lkml.org/lkml/2005/10/1/70}
 [Viewed March 14, 2006]"
-,annotation="
+,annotation={
 	First rcutorture patch.
-"
+}
+}
+
+@unpublished{DavidSMiller2006HashedLocking
+,Author="David S. Miller"
+,Title="Re: [{PATCH}, {RFC}] {RCU} : {OOM} avoidance and lower latency"
+,month="January"
+,day="6"
+,year="2006"
+,note="Available:
+\url{https://lkml.org/lkml/2006/1/7/22}
+[Viewed February 29, 2012]"
+,annotation={
+	David Miller's view on hashed arrays of locks: used to really
+	like it, but time he saw an opportunity for this technique,
+	something else always proved superior.  Partitioning or RCU.  ;-)
+}
 }
 
 @conference{ThomasEHart2006a
@@ -1309,10 +1350,10 @@ Distributed Processing Symposium"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/hart_ipdps06.pdf}
 [Viewed April 28, 2008]"
-,annotation="
+,annotation={
 	Compares QSBR, HPBR, EBR, and lock-free reference counting.
 	http://www.cs.toronto.edu/~tomhart/perflab/ipdps06.tgz
-"
+}
 }
 
 @unpublished{NickPiggin2006radixtree
@@ -1324,9 +1365,9 @@ Distributed Processing Symposium"
 ,note="Available:
 \url{http://lkml.org/lkml/2006/6/20/238}
 [Viewed March 25, 2008]"
-,annotation="
+,annotation={
 	RCU-protected radix tree.
-"
+}
 }
 
 @Conference{PaulEMcKenney2006b
@@ -1341,9 +1382,9 @@ Suparna Bhattacharya"
 \url{http://www.linuxsymposium.org/2006/view_abstract.php?content_key=184}
 \url{http://www.rdrop.com/users/paulmck/RCU/OLSrtRCU.2006.08.11a.pdf}
 [Viewed January 1, 2007]"
-,annotation="
+,annotation={
 	Described how to improve the -rt implementation of realtime RCU.
-"
+}
 }
 
 @unpublished{WikipediaRCU
@@ -1354,12 +1395,11 @@ Canis Rufus and Zoicon5 and Anome and Hal Eisen"
 ,month="July"
 ,day="8"
 ,year="2006"
-,note="Available:
-\url{http://en.wikipedia.org/wiki/Read-copy-update}
-[Viewed August 21, 2006]"
-,annotation="
+,note="\url{http://en.wikipedia.org/wiki/Read-copy-update}"
+,annotation={
 	Wikipedia RCU page as of July 8 2006.
-"
+	[Viewed August 21, 2006]
+}
 }
 
 @Conference{NickPiggin2006LocklessPageCache
@@ -1372,9 +1412,9 @@ Canis Rufus and Zoicon5 and Anome and Hal Eisen"
 ,note="Available:
 \url{http://www.linuxsymposium.org/2006/view_abstract.php?content_key=184}
 [Viewed January 11, 2009]"
-,annotation="
+,annotation={
 	Uses RCU-protected radix tree for a lockless page cache.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2006c
@@ -1388,9 +1428,9 @@ Canis Rufus and Zoicon5 and Anome and Hal Eisen"
 Revised:
 \url{http://www.rdrop.com/users/paulmck/RCU/srcu.2007.01.14a.pdf}
 [Viewed August 21, 2006]"
-,annotation="
+,annotation={
 	LWN article introducing SRCU.
-"
+}
 }
 
 @unpublished{RobertOlsson2006a
@@ -1399,12 +1439,11 @@ Revised:
 ,month="August"
 ,day="18"
 ,year="2006"
-,note="Available:
-\url{http://www.nada.kth.se/~snilsson/publications/TRASH/trash.pdf}
-[Viewed March 4, 2011]"
-,annotation="
+,note="\url{http://www.nada.kth.se/~snilsson/publications/TRASH/trash.pdf}"
+,annotation={
 	RCU-protected dynamic trie-hash combination.
-"
+	[Viewed March 4, 2011]
+}
 }
 
 @unpublished{ChristophHellwig2006RCU2SRCU
@@ -1426,10 +1465,10 @@ Revised:
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/linuxusage.html}
 [Viewed January 14, 2007]"
-,annotation="
+,annotation={
 	Paul McKenney's RCU page showing graphs plotting Linux-kernel
 	usage of RCU.
-"
+}
 }
 
 @unpublished{PaulEMcKenneyRCUusageRawDataPage
@@ -1440,10 +1479,10 @@ Revised:
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html}
 [Viewed January 14, 2007]"
-,annotation="
+,annotation={
 	Paul McKenney's RCU page showing Linux usage of RCU in tabular
 	form, with links to corresponding cscope databases.
-"
+}
 }
 
 @unpublished{GauthamShenoy2006RCUrwlock
@@ -1455,13 +1494,13 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2006/10/26/73}
 [Viewed January 26, 2009]"
-,annotation="
+,annotation={
 	RCU-based reader-writer lock that allows readers to proceed with
 	no memory barriers or atomic instruction in absence of writers.
 	If writer do show up, readers must of course wait as required by
 	the semantics of reader-writer locking.  This is a recursive
 	lock.
-"
+}
 }
 
 @unpublished{JensAxboe2006SlowSRCU
@@ -1474,11 +1513,11 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2006/11/17/56}
 [Viewed May 28, 2007]"
-,annotation="
+,annotation={
 	SRCU's grace periods are too slow for Jens, even after a
 	factor-of-three speedup.
 	Sped-up version of SRCU at http://lkml.org/lkml/2006/11/17/359.
-"
+}
 }
 
 @unpublished{OlegNesterov2006QRCU
@@ -1491,10 +1530,10 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2006/11/19/69}
 [Viewed May 28, 2007]"
-,annotation="
+,annotation={
 	First cut of QRCU.  Expanded/corrected versions followed.
 	Used to be OlegNesterov2007QRCU, now time-corrected.
-"
+}
 }
 
 @unpublished{OlegNesterov2006aQRCU
@@ -1506,10 +1545,10 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2006/11/29/330}
 [Viewed November 26, 2008]"
-,annotation="
+,annotation={
 	Expanded/corrected version of QRCU.
 	Used to be OlegNesterov2007aQRCU, now time-corrected.
-"
+}
 }
 
 @unpublished{EvgeniyPolyakov2006RCUslowdown
@@ -1521,10 +1560,10 @@ Revised:
 ,note="Available:
 \url{http://www.ioremap.net/node/41}
 [Viewed October 28, 2008]"
-,annotation="
+,annotation={
 	Using RCU as a pure delay leads to a 2.5x slowdown in skbs in
 	the Linux kernel.
-"
+}
 }
 
 @inproceedings{ChrisMatthews2006ClusteredObjectsRCU
@@ -1541,7 +1580,8 @@ Revised:
 ,annotation={
 	Uses K42's RCU-like functionality to manage clustered-object
 	lifetimes.
-}}
+}
+}
 
 @article{DilmaDaSilva2006K42
 ,author = {Silva, Dilma Da and Krieger, Orran and Wisniewski, Robert W. and Waterland, Amos and Tam, David and Baumann, Andrew}
@@ -1557,7 +1597,8 @@ Revised:
 ,address = {New York, NY, USA}
 ,annotation={
 	Describes relationship of K42 generations to RCU.
-}}
+}
+}
 
 # CoreyMinyard2007list_splice_rcu
 @unpublished{CoreyMinyard2007list:splice:rcu
@@ -1569,9 +1610,9 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2007/1/3/112}
 [Viewed May 28, 2007]"
-,annotation="
+,annotation={
 	Patch for list_splice_rcu().
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007rcubarrier
@@ -1583,9 +1624,9 @@ Revised:
 ,note="Available:
 \url{http://lwn.net/Articles/217484/}
 [Viewed November 22, 2007]"
-,annotation="
+,annotation={
 	LWN article introducing the rcu_barrier() primitive.
-"
+}
 }
 
 @unpublished{PeterZijlstra2007SyncBarrier
@@ -1597,10 +1638,10 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2007/1/28/34}
 [Viewed March 27, 2008]"
-,annotation="
+,annotation={
 	RCU-like implementation for frequent updaters and rare readers(!).
 	Subsumed into QRCU.  Maybe...
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007BoostRCU
@@ -1609,14 +1650,13 @@ Revised:
 ,month="February"
 ,day="5"
 ,year="2007"
-,note="Available:
-\url{http://lwn.net/Articles/220677/}
-Revised:
-\url{http://www.rdrop.com/users/paulmck/RCU/RCUbooststate.2007.04.16a.pdf}
-[Viewed September 7, 2007]"
-,annotation="
+,note="\url{http://lwn.net/Articles/220677/}"
+,annotation={
 	LWN article introducing RCU priority boosting.
-"
+	Revised:
+	http://www.rdrop.com/users/paulmck/RCU/RCUbooststate.2007.04.16a.pdf
+	[Viewed September 7, 2007]
+}
 }
 
 @unpublished{PaulMcKenney2007QRCUpatch
@@ -1628,9 +1668,9 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2007/2/25/18}
 [Viewed March 27, 2008]"
-,annotation="
+,annotation={
 	Patch for QRCU supplying lock-free fast path.
-"
+}
 }
 
 @article{JonathanAppavoo2007K42RCU
@@ -1647,7 +1687,8 @@ Revised:
 ,address = {New York, NY, USA}
 ,annotation={
 	Role of RCU in K42.
-}}
+}
+}
 
 @conference{RobertOlsson2007Trash
 ,Author="Robert Olsson and Stefan Nilsson"
@@ -1658,9 +1699,9 @@ Revised:
 ,note="Available:
 \url{http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=4281239}
 [Viewed October 1, 2010]"
-,annotation="
+,annotation={
 	RCU-protected dynamic trie-hash combination.
-"
+}
 }
 
 @conference{PeterZijlstra2007ConcurrentPagecacheRCU
@@ -1673,10 +1714,10 @@ Revised:
 ,note="Available:
 \url{http://ols.108.redhat.com/2007/Reprints/zijlstra-Reprint.pdf}
 [Viewed April 14, 2008]"
-,annotation="
+,annotation={
 	Page-cache modifications permitting RCU readers and concurrent
 	updates.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007whatisRCU
@@ -1701,11 +1742,11 @@ Revised:
 ,note="Available:
 \url{http://lwn.net/Articles/243851/}
 [Viewed September 8, 2007]"
-,annotation="
+,annotation={
 	LWN article describing Promela and spin, and also using Oleg
 	Nesterov's QRCU as an example (with Paul McKenney's fastpath).
 	Merged patch at: http://lkml.org/lkml/2007/2/25/18
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007WG21DDOatomics
@@ -1714,12 +1755,12 @@ Revised:
 ,month="August"
 ,day="3"
 ,year="2007"
-,note="Preprint:
+,note="Available:
 \url{http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm}
 [Viewed December 7, 2009]"
-,annotation="
+,annotation={
 	RCU for C++, parts 1 and 2.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007WG21DDOannotation
@@ -1728,12 +1769,12 @@ Revised:
 ,month="September"
 ,day="18"
 ,year="2008"
-,note="Preprint:
+,note="Available:
 \url{http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2782.htm}
 [Viewed December 7, 2009]"
-,annotation="
+,annotation={
 	RCU for C++, part 2, updated many times.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007PreemptibleRCUPatch
@@ -1745,10 +1786,10 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2007/9/10/213}
 [Viewed October 25, 2007]"
-,annotation="
+,annotation={
 	Final patch for preemptable RCU to -rt.  (Later patches were
 	to mainline, eventually incorporated.)
-"
+}
 }
 
 @unpublished{PaulEMcKenney2007PreemptibleRCU
@@ -1760,9 +1801,9 @@ Revised:
 ,note="Available:
 \url{http://lwn.net/Articles/253651/}
 [Viewed October 25, 2007]"
-,annotation="
+,annotation={
 	LWN article describing the design of preemptible RCU.
-"
+}
 }
 
 @article{ThomasEHart2007a
@@ -1783,6 +1824,7 @@ Revised:
 }
 }
 
+# MathieuDesnoyers2007call_rcu_schedNeeded
 @unpublished{MathieuDesnoyers2007call:rcu:schedNeeded
 ,Author="Mathieu Desnoyers"
 ,Title="Re: [patch 1/2] {Linux} Kernel Markers - Support Multiple Probes"
@@ -1792,9 +1834,9 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2007/12/20/244}
 [Viewed March 27, 2008]"
-,annotation="
+,annotation={
 	Request for call_rcu_sched() and rcu_barrier_sched().
-"
+}
 }
 
 
@@ -1815,11 +1857,11 @@ Revised:
 ,note="Available:
 \url{http://lwn.net/Articles/262464/}
 [Viewed December 27, 2007]"
-,annotation="
+,annotation={
 	Lays out the three basic components of RCU: (1) publish-subscribe,
 	(2) wait for pre-existing readers to complete, and (2) maintain
 	multiple versions.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2008WhatIsRCUUsage
@@ -1831,7 +1873,7 @@ Revised:
 ,note="Available:
 \url{http://lwn.net/Articles/263130/}
 [Viewed January 4, 2008]"
-,annotation="
+,annotation={
 	Lays out six uses of RCU:
 	1. RCU is a Reader-Writer Lock Replacement
 	2. RCU is a Restricted Reference-Counting Mechanism
@@ -1839,7 +1881,7 @@ Revised:
 	4. RCU is a Poor Man's Garbage Collector
 	5. RCU is a Way of Providing Existence Guarantees
 	6. RCU is a Way of Waiting for Things to Finish
-"
+}
 }
 
 @unpublished{PaulEMcKenney2008WhatIsRCUAPI
@@ -1851,10 +1893,10 @@ Revised:
 ,note="Available:
 \url{http://lwn.net/Articles/264090/}
 [Viewed January 10, 2008]"
-,annotation="
+,annotation={
 	Gives an overview of the Linux-kernel RCU API and a brief annotated RCU
 	bibliography.
-"
+}
 }
 
 #
@@ -1872,10 +1914,10 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2008/1/29/208}
 [Viewed March 27, 2008]"
-,annotation="
+,annotation={
 	Patch that prevents preemptible RCU from unnecessarily waking
 	up dynticks-idle CPUs.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2008LKMLDependencyOrdering
@@ -1887,9 +1929,9 @@ Revised:
 ,note="Available:
 \url{http://lkml.org/lkml/2008/2/2/255}
 [Viewed October 18, 2008]"
-,annotation="
+,annotation={
 	Explanation of compilers violating dependency ordering.
-"
+}
 }
 
 @Conference{PaulEMcKenney2008Beijing
@@ -1916,24 +1958,26 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lwn.net/Articles/279077/}
 [Viewed April 24, 2008]"
-,annotation="
+,annotation={
 	Describes use of Promela and Spin to validate (and fix!) the
 	dynticks/RCU interface.
-"
+}
 }
 
 @article{DinakarGuniguntala2008IBMSysJ
 ,author="D. Guniguntala and P. E. McKenney and J. Triplett and J. Walpole"
 ,title="The read-copy-update mechanism for supporting real-time applications on shared-memory multiprocessor systems with {Linux}"
 ,Year="2008"
-,Month="April-June"
+,Month="May"
 ,journal="IBM Systems Journal"
 ,volume="47"
 ,number="2"
 ,pages="221-236"
-,annotation="
+,annotation={
 	RCU, realtime RCU, sleepable RCU, performance.
-"
+	http://www.research.ibm.com/journal/sj/472/guniguntala.pdf
+	[Viewed April 24, 2008]
+}
 }
 
 @unpublished{LaiJiangshan2008NewClassicAlgorithm
@@ -1945,11 +1989,11 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2008/6/2/539}
 [Viewed December 10, 2008]"
-,annotation="
+,annotation={
 	Updated RCU classic algorithm.  Introduced multi-tailed list
 	for RCU callbacks and also pulling common code into
 	__call_rcu().
-"
+}
 }
 
 @article{PaulEMcKenney2008RCUOSR
@@ -1966,6 +2010,7 @@ lot of {Linux} into your technology!!!"
 ,address="New York, NY, USA"
 ,annotation={
 	Linux changed RCU to a far greater degree than RCU has changed Linux.
+	http://portal.acm.org/citation.cfm?doid=1400097.1400099
 }
 }
 
@@ -1978,10 +2023,10 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2008/8/21/336}
 [Viewed December 8, 2008]"
-,annotation="
+,annotation={
 	State-based RCU.  One key thing that this patch does is to
 	separate the dynticks handling of NMIs and IRQs.
-"
+}
 }
 
 @unpublished{ManfredSpraul2008dyntickIRQNMI
@@ -1993,12 +2038,13 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2008/9/6/86}
 [Viewed December 8, 2008]"
-,annotation="
+,annotation={
 	Manfred notes a fix required to my attempt to separate irq
 	and NMI processing for hierarchical RCU's dynticks interface.
-"
+}
 }
 
+# Was PaulEMcKenney2011cyclicRCU
 @techreport{PaulEMcKenney2008cyclicRCU
 ,author="Paul E. McKenney"
 ,title="Efficient Support of Consistent Cyclic Search With Read-Copy Update"
@@ -2008,11 +2054,11 @@ lot of {Linux} into your technology!!!"
 ,number="US Patent 7,426,511"
 ,month="September"
 ,pages="23"
-,annotation="
+,annotation={
 	Maintains an additional level of indirection to allow
 	readers to confine themselves to the desired snapshot of the
 	data structure.  Only permits one update at a time.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2008HierarchicalRCU
@@ -2021,13 +2067,12 @@ lot of {Linux} into your technology!!!"
 ,month="November"
 ,day="3"
 ,year="2008"
-,note="Available:
-\url{http://lwn.net/Articles/305782/}
-[Viewed November 6, 2008]"
-,annotation="
+,note="\url{http://lwn.net/Articles/305782/}"
+,annotation={
 	RCU with combining-tree-based grace-period detection,
 	permitting it to handle thousands of CPUs.
-"
+	[Viewed November 6, 2008]
+}
 }
 
 @unpublished{PaulEMcKenney2009BloatwatchRCU
@@ -2039,10 +2084,10 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2009/1/14/449}
 [Viewed January 15, 2009]"
-,annotation="
+,annotation={
 	Small-footprint implementation of RCU for uniprocessor
 	embedded applications -- and also for exposition purposes.
-"
+}
 }
 
 @conference{PaulEMcKenney2009MaliciousURCU
@@ -2055,9 +2100,9 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/urcutorture.2009.01.22a.pdf}
 [Viewed February 2, 2009]"
-,annotation="
+,annotation={
 	Realtime RCU and torture-testing RCU uses.
-"
+}
 }
 
 @unpublished{MathieuDesnoyers2009URCU
@@ -2066,16 +2111,14 @@ lot of {Linux} into your technology!!!"
 ,month="February"
 ,day="5"
 ,year="2009"
-,note="Available:
-\url{http://lkml.org/lkml/2009/2/5/572}
-\url{http://lttng.org/urcu}
-[Viewed February 20, 2009]"
-,annotation="
+,note="\url{http://lttng.org/urcu}"
+,annotation={
 	Mathieu Desnoyers's user-space RCU implementation.
 	git://lttng.org/userspace-rcu.git
 	http://lttng.org/cgi-bin/gitweb.cgi?p=userspace-rcu.git
 	http://lttng.org/urcu
-"
+	http://lkml.org/lkml/2009/2/5/572
+}
 }
 
 @unpublished{PaulEMcKenney2009LWNBloatWatchRCU
@@ -2087,9 +2130,24 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lwn.net/Articles/323929/}
 [Viewed March 20, 2009]"
-,annotation="
+,annotation={
 	Uniprocessor assumptions allow simplified RCU implementation.
-"
+}
+}
+
+@unpublished{EvgeniyPolyakov2009EllipticsNetwork
+,Author="Evgeniy Polyakov"
+,Title="The Elliptics Network"
+,month="April"
+,day="17"
+,year="2009"
+,note="Available:
+\url{http://www.ioremap.net/projects/elliptics}
+[Viewed April 30, 2009]"
+,annotation={
+	Distributed hash table with transactions, using elliptic
+	hash functions to distribute data.
+}
 }
 
 @unpublished{PaulEMcKenney2009expeditedRCU
@@ -2101,9 +2159,9 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2009/6/25/306}
 [Viewed August 16, 2009]"
-,annotation="
+,annotation={
 	First posting of expedited RCU to be accepted into -tip.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2009fastRTRCU
@@ -2115,21 +2173,21 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2009/7/23/294}
 [Viewed August 15, 2009]"
-,annotation="
+,annotation={
 	First posting of simple and fast preemptable RCU.
-"
+}
 }
 
-@InProceedings{JoshTriplett2009RPHash
+@unpublished{JoshTriplett2009RPHash
 ,Author="Josh Triplett"
 ,Title="Scalable concurrent hash tables via relativistic programming"
 ,month="September"
 ,year="2009"
-,booktitle="Linux Plumbers Conference 2009"
-,annotation="
+,note="Linux Plumbers Conference presentation"
+,annotation={
 	RP fun with hash tables.
-	See also JoshTriplett2010RPHash
-"
+	Superseded by JoshTriplett2010RPHash
+}
 }
 
 @phdthesis{MathieuDesnoyersPhD
@@ -2154,9 +2212,9 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://wiki.cs.pdx.edu/rp/}
 [Viewed December 9, 2009]"
-,annotation="
+,annotation={
 	Main Relativistic Programming Wiki.
-"
+}
 }
 
 @conference{PaulEMcKenney2009DeterministicRCU
@@ -2180,9 +2238,9 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://paulmck.livejournal.com/14639.html}
 [Viewed June 4, 2010]"
-,annotation="
+,annotation={
 	Day-one bug in Tree RCU that took forever to track down.
-"
+}
 }
 
 @unpublished{MathieuDesnoyers2009defer:rcu
@@ -2193,10 +2251,10 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://lkml.org/lkml/2009/10/18/129}
 [Viewed December 29, 2009]"
-,annotation="
+,annotation={
 	Mathieu proposed defer_rcu() with fixed-size per-thread pool
 	of RCU callbacks.
-"
+}
 }
 
 @unpublished{MathieuDesnoyers2009VerifPrePub
@@ -2205,10 +2263,10 @@ lot of {Linux} into your technology!!!"
 ,month="December"
 ,year="2009"
 ,note="Submitted to IEEE TPDS"
-,annotation="
+,annotation={
 	OOMem model for Mathieu's user-level RCU mechanical proof of
 	correctness.
-"
+}
 }
 
 @unpublished{MathieuDesnoyers2009URCUPrePub
@@ -2216,15 +2274,15 @@ lot of {Linux} into your technology!!!"
 ,Title="User-Level Implementations of Read-Copy Update"
 ,month="December"
 ,year="2010"
-,url=\url{http://www.computer.org/csdl/trans/td/2012/02/ttd2012020375-abs.html}
-,annotation="
+,url={\url{http://www.computer.org/csdl/trans/td/2012/02/ttd2012020375-abs.html}}
+,annotation={
 	RCU overview, desiderata, semi-formal semantics, user-level RCU
 	usage scenarios, three classes of RCU implementation, wait-free
 	RCU updates, RCU grace-period batching, update overhead,
 	http://www.rdrop.com/users/paulmck/RCU/urcu-main-accepted.2011.08.30a.pdf
 	http://www.rdrop.com/users/paulmck/RCU/urcu-supp-accepted.2011.08.30a.pdf
 	Superseded by MathieuDesnoyers2012URCU.
-"
+}
 }
 
 @inproceedings{HariKannan2009DynamicAnalysisRCU
@@ -2240,7 +2298,8 @@ lot of {Linux} into your technology!!!"
 ,address = {New York, NY, USA}
 ,annotation={
 	Uses RCU to protect metadata used in dynamic analysis.
-}}
+}
+}
 
 @conference{PaulEMcKenney2010SimpleOptRCU
 ,Author="Paul E. McKenney"
@@ -2252,10 +2311,10 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://www.rdrop.com/users/paulmck/RCU/SimplicityThruOptimization.2010.01.21f.pdf}
 [Viewed October 10, 2010]"
-,annotation="
+,annotation={
 	TREE_PREEMPT_RCU optimizations greatly simplified the old
 	PREEMPT_RCU implementation.
-"
+}
 }
 
 @unpublished{PaulEMcKenney2010LockdepRCU
@@ -2264,12 +2323,11 @@ lot of {Linux} into your technology!!!"
 ,month="February"
 ,year="2010"
 ,day="1"
-,note="Available:
-\url{https://lwn.net/Articles/371986/}
-[Viewed June 4, 2010]"
-,annotation="
+,note="\url{https://lwn.net/Articles/371986/}"
+,annotation={
 	CONFIG_PROVE_RCU, or at least an early version.
-"
+	[Viewed June 4, 2010]
+}
 }
 
 @unpublished{AviKivity2010KVM2RCU
@@ -2280,10 +2338,10 @@ lot of {Linux} into your technology!!!"
 ,note="Available:
 \url{http://www.mail-archive.com/kvm@vger.kernel.org/msg28640.html}
 [Viewed March 20, 2010]"
-,annotation="
+,annotation={
 	Use of RCU permits KVM to increase the size of guest OSes from
 	16 CPUs to 64 CPUs.
-"
+}
 }
 
 @unpublished{HerbertXu2010RCUResizeHash
@@ -2297,7 +2355,19 @@ lot of {Linux} into your technology!!!"
 ,annotation={
 	Use a pair of list_head structures to support RCU-protected
 	resizable hash tables.
-}}
+}
+}
+
+@mastersthesis{AbhinavDuggal2010Masters
+,author="Abhinav Duggal"
+,title="Stopping Data Races Using Redflag"
+,school="Stony Brook University"
+,year="2010"
+,annotation={
+	Data-race detector incorporating RCU.
+	http://www.filesystems.org/docs/abhinav-thesis/abhinav_thesis.pdf
+}
+}
 
 @article{JoshTriplett2010RPHash
 ,author="Josh Triplett and Paul E. McKenney and Jonathan Walpole"
@@ -2310,7 +2380,8 @@ lot of {Linux} into your technology!!!"
 ,annotation={
 	RP fun with hash tables.
 	http://portal.acm.org/citation.cfm?id=1842733.1842750
-}}
+}
+}
 
 @unpublished{PaulEMcKenney2010RCUAPI
 ,Author="Paul E. McKenney"
@@ -2318,12 +2389,11 @@ lot of {Linux} into your technology!!!"
 ,month="December"
 ,day="8"
 ,year="2010"
-,note="Available:
-\url{http://lwn.net/Articles/418853/}
-[Viewed December 8, 2010]"
-,annotation="
+,note="\url{http://lwn.net/Articles/418853/}"
+,annotation={
 	Includes updated software-engineering features.
-"
+	[Viewed December 8, 2010]
+}
 }
 
 @mastersthesis{AndrejPodzimek2010masters
@@ -2338,7 +2408,8 @@ lot of {Linux} into your technology!!!"
 	Reviews RCU implementations and creates a few for OpenSolaris.
 	Drives quiescent-state detection from RCU read-side primitives,
 	in a manner roughly similar to that of Jim Houston.
-}}
+}
+}
 
 @unpublished{LinusTorvalds2011Linux2:6:38:rc1:NPigginVFS
 ,Author="Linus Torvalds"
@@ -2358,7 +2429,8 @@ lot of {Linux} into your technology!!!"
 	of the most expensive parts of path component lookup, which was the
 	d_lock on every component lookup. So I'm seeing improvements of 30-50%
 	on some seriously pathname-lookup intensive loads."
-}}
+}
+}
 
 @techreport{JoshTriplett2011RPScalableCorrectOrdering
 ,author = {Josh Triplett and Philip W. Howard and Paul E. McKenney and Jonathan Walpole}
@@ -2392,12 +2464,12 @@ lot of {Linux} into your technology!!!"
 ,number="US Patent 7,953,778"
 ,month="May"
 ,pages="34"
-,annotation="
+,annotation={
 	Maintains an array of generation numbers to track in-flight
 	updates and keeps an additional level of indirection to allow
 	readers to confine themselves to the desired snapshot of the
 	data structure.
-"
+}
 }
 
 @inproceedings{Triplett:2011:RPHash
@@ -2408,7 +2480,7 @@ lot of {Linux} into your technology!!!"
 ,year = {2011}
 ,pages = {145--158}
 ,numpages = {14}
-,url={http://www.usenix.org/event/atc11/tech/final_files/atc11_proceedings.pdf}
+,url={http://www.usenix.org/event/atc11/tech/final_files/Triplett.pdf}
 ,publisher = {The USENIX Association}
 ,address = {Portland, OR USA}
 }
@@ -2419,27 +2491,52 @@ lot of {Linux} into your technology!!!"
 ,month="July"
 ,day="27"
 ,year="2011"
-,note="Available:
-\url{http://lwn.net/Articles/453002/}
-[Viewed July 27, 2011]"
-,annotation="
+,note="\url{http://lwn.net/Articles/453002/}"
+,annotation={
 	Analysis of the RCU trainwreck in Linux kernel 3.0.
-"
+	[Viewed July 27, 2011]
+}
 }
 
 @unpublished{NeilBrown2011MeetTheLockers
 ,Author="Neil Brown"
-,Title="Meet the Lockers"
+,Title="Meet the {Lockers}"
 ,month="August"
 ,day="3"
 ,year="2011"
 ,note="Available:
 \url{http://lwn.net/Articles/453685/}
 [Viewed September 2, 2011]"
-,annotation="
+,annotation={
 	The Locker family as an analogy for locking, reference counting,
 	RCU, and seqlock.
-"
+}
+}
+
+@inproceedings{Seyster:2011:RFA:2075416.2075425
+,author = {Seyster, Justin and Radhakrishnan, Prabakar and Katoch, Samriti and Duggal, Abhinav and Stoller, Scott D. and Zadok, Erez}
+,title = {Redflag: a framework for analysis of Kernel-level concurrency}
+,booktitle = {Proceedings of the 11th international conference on Algorithms and architectures for parallel processing - Volume Part I}
+,series = {ICA3PP'11}
+,year = {2011}
+,isbn = {978-3-642-24649-4}
+,location = {Melbourne, Australia}
+,pages = {66--79}
+,numpages = {14}
+,url = {http://dl.acm.org/citation.cfm?id=2075416.2075425}
+,acmid = {2075425}
+,publisher = {Springer-Verlag}
+,address = {Berlin, Heidelberg}
+}
+
+@phdthesis{JoshTriplettPhD
+,author="Josh Triplett"
+,title="Relativistic Causal Ordering A Memory Model for Scalable Concurrent Data Structures"
+,school="Portland State University"
+,year="2012"
+,annotation={
+	RCU-protected hash tables, barriers vs. read-side traversal order.
+}
 }
 
 @article{MathieuDesnoyers2012URCU
@@ -2459,5 +2556,153 @@ lot of {Linux} into your technology!!!"
 	RCU updates, RCU grace-period batching, update overhead,
 	http://www.rdrop.com/users/paulmck/RCU/urcu-main-accepted.2011.08.30a.pdf
 	http://www.rdrop.com/users/paulmck/RCU/urcu-supp-accepted.2011.08.30a.pdf
+	http://www.computer.org/cms/Computer.org/dl/trans/td/2012/02/extras/ttd2012020375s.pdf
+}
+}
+
+@inproceedings{AustinClements2012RCULinux:mmapsem
+,author = {Austin Clements and Frans Kaashoek and Nickolai Zeldovich}
+,title = {Scalable Address Spaces Using {RCU} Balanced Trees}
+,booktitle = {Architectural Support for Programming Languages and Operating Systems (ASPLOS 2012)}
+,month = {March}
+,year = {2012}
+,pages = {199--210}
+,numpages = {12}
+,publisher = {ACM}
+,address = {London, UK}
+,url="http://people.csail.mit.edu/nickolai/papers/clements-bonsai.pdf"
+}
+
+@unpublished{PaulEMcKenney2012ELCbattery
+,Author="Paul E. McKenney"
+,Title="Making {RCU} Safe For Battery-Powered Devices"
+,month="February"
+,day="15"
+,year="2012"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/RCUdynticks.2012.02.15b.pdf}
+[Viewed March 1, 2012]"
+,annotation={
+	RCU_FAST_NO_HZ, round 2.
+}
+}
+
+@article{GuillermoVigueras2012RCUCrowd
+,author = {Vigueras, Guillermo and Ordu\~{n}a, Juan M. and Lozano, Miguel}
+,citeulike-article-id = {10632151}
+,citeulike-linkout-0 = {http://dx.doi.org/10.1007/s11227-012-0766-x}
+,citeulike-linkout-1 = {http://www.springerlink.com/content/25762r0874163570}
+,day = {25}
+,doi = {10.1007/s11227-012-0766-x}
+,issn = {0920-8542}
+,journal = {The Journal of Supercomputing}
+,keywords = {linux, simulation}
+,month = apr
+,posted-at = {2012-05-03 09:12:04}
+,priority = {2}
+,title = {{A Read-Copy Update based parallel server for distributed crowd simulations}}
+,url = {http://dx.doi.org/10.1007/s11227-012-0766-x}
+,year = {2012}
+}
+
+
+@unpublished{JonCorbet2012ACCESS:ONCE
+,Author="Jon Corbet"
+,Title="{ACCESS\_ONCE()}"
+,month="August"
+,day="1"
+,year="2012"
+,note="\url{http://lwn.net/Articles/508991/}"
+,annotation={
+	A couple of simple specific compiler optimizations that motivate
+	ACCESS_ONCE().
+}
+}
+
+@unpublished{AlexeyGotsman2012VerifyGraceExtended
+,Author="Alexey Gotsman and Noam Rinetzky and Hongseok Yang"
+,Title="Verifying Highly Concurrent Algorithms with Grace (extended version)"
+,month="July"
+,day="10"
+,year="2012"
+,note="\url{http://software.imdea.org/~gotsman/papers/recycling-esop13-ext.pdf}"
+,annotation={
+	Separation-logic formulation of RCU uses.
+}
+}
+
+@unpublished{PaulMcKenney2012RCUUsage
+,Author="Paul E. McKenney and Silas Boyd-Wickizer and Jonathan Walpole"
+,Title="{RCU} Usage In the Linux Kernel: One Decade Later"
+,month="September"
+,day="17"
+,year="2012"
+,url=http://rdrop.com/users/paulmck/techreports/survey.2012.09.17a.pdf
+,note="Technical report paulmck.2012.09.17"
+,annotation={
+	Overview of the first variant of no-CBs CPUs for RCU.
+}
+}
+
+@unpublished{JonCorbet2012NOCB
+,Author="Jon Corbet"
+,Title="Relocating RCU callbacks"
+,month="October"
+,day="31"
+,year="2012"
+,note="\url{http://lwn.net/Articles/522262/}"
+,annotation={
+	Overview of the first variant of no-CBs CPUs for RCU.
+}
+}
+
+@phdthesis{JustinSeyster2012PhD
+,author="Justin Seyster"
+,title="Runtime Verification of Kernel-Level Concurrency Using Compiler-Based Instrumentation"
+,school="Stony Brook University"
+,year="2012"
+,annotation={
+	Looking for data races, including those involving RCU.
+	Proposal:
+	http://www.fsl.cs.sunysb.edu/docs/jseyster-proposal/redflag.pdf
+	Dissertation:
+	http://www.fsl.cs.sunysb.edu/docs/jseyster-dissertation/redflag.pdf
+}
+}
+
+@unpublished{PaulEMcKenney2013RCUUsage
+,Author="Paul E. McKenney and Silas Boyd-Wickizer and Jonathan Walpole"
+,Title="{RCU} Usage in the {Linux} Kernel: One Decade Later"
+,month="February"
+,day="24"
+,year="2013"
+,note="\url{http://rdrop.com/users/paulmck/techreports/RCUUsage.2013.02.24a.pdf}"
+,annotation={
+	Usage of RCU within the Linux kernel.
+}
+}
+
+@inproceedings{AlexeyGotsman2013ESOPRCU
+,author = {Alexey Gotsman and Noam Rinetzky and Hongseok Yang}
+,title = {Verifying concurrent memory reclamation algorithms with grace}
+,booktitle = {ESOP'13: European Symposium on Programming}
+,year = {2013}
+,pages = {249--269}
+,publisher = {Springer}
+,address = {Rome, Italy}
+,annotation={
+	http://software.imdea.org/~gotsman/papers/recycling-esop13.pdf
+}
+}
+
+@unpublished{PaulEMcKenney2013NoTinyPreempt
+,Author="Paul E. McKenney"
+,Title="Simplifying RCU"
+,month="March"
+,day="6"
+,year="2013"
+,note="\url{http://lwn.net/Articles/541037/}"
+,annotation={
+	Getting rid of TINY_PREEMPT_RCU.
 }
 }
diff --git a/Documentation/RCU/rcubarrier.txt b/Documentation/RCU/rcubarrier.txt
index 2e319d1..b10cfe7 100644
--- a/Documentation/RCU/rcubarrier.txt
+++ b/Documentation/RCU/rcubarrier.txt
@@ -70,10 +70,14 @@ in realtime kernels in order to avoid excessive scheduling latencies.
 
 rcu_barrier()
 
-We instead need the rcu_barrier() primitive. This primitive is similar
-to synchronize_rcu(), but instead of waiting solely for a grace
-period to elapse, it also waits for all outstanding RCU callbacks to
-complete. Pseudo-code using rcu_barrier() is as follows:
+We instead need the rcu_barrier() primitive.  Rather than waiting for
+a grace period to elapse, rcu_barrier() waits for all outstanding RCU
+callbacks to complete.  Please note that rcu_barrier() does -not- imply
+synchronize_rcu(), in particular, if there are no RCU callbacks queued
+anywhere, rcu_barrier() is within its rights to return immediately,
+without waiting for a grace period to elapse.
+
+Pseudo-code using rcu_barrier() is as follows:
 
    1. Prevent any new RCU callbacks from being posted.
    2. Execute rcu_barrier().
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index d8a5023..dac02a6 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -42,6 +42,16 @@ fqs_holdoff	Holdoff time (in microseconds) between consecutive calls
 fqs_stutter	Wait time (in seconds) between consecutive bursts
 		of calls to force_quiescent_state().
 
+gp_normal	Make the fake writers use normal synchronous grace-period
+		primitives.
+
+gp_exp		Make the fake writers use expedited synchronous grace-period
+		primitives.  If both gp_normal and gp_exp are set, or
+		if neither gp_normal nor gp_exp are set, then randomly
+		choose the primitive so that about 50% are normal and
+		50% expedited.  By default, neither are set, which
+		gives best overall test coverage.
+
 irqreader	Says to invoke RCU readers from irq level.  This is currently
 		done via timers.  Defaults to "1" for variants of RCU that
 		permit this.  (Or, more accurately, variants of RCU that do
diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
index 9012bb0..4ae915a 100644
--- a/Documentation/arm/OMAP/omap_pm
+++ b/Documentation/arm/OMAP/omap_pm
@@ -78,7 +78,7 @@ to NULL.  Drivers should use the following idiom:
 The most common usage of these functions will probably be to specify
 the maximum time from when an interrupt occurs, to when the device
 becomes accessible.  To accomplish this, driver writers should use the
-set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
+set_max_mpu_wakeup_lat() function to constrain the MPU wakeup
 latency, and the set_max_dev_wakeup_lat() function to constrain the
 device wakeup latency (from clk_enable() to accessibility).  For
 example,
diff --git a/Documentation/block/blockconsole.txt b/Documentation/block/blockconsole.txt
new file mode 100644
index 0000000..2b45516
--- /dev/null
+++ b/Documentation/block/blockconsole.txt
@@ -0,0 +1,94 @@
+started by Jörn Engel <joern@logfs.org> 2012.03.17
+
+Blocksonsole for the impatient
+==============================
+
+1. Find an unused USB stick and prepare it for blockconsole by writing
+   the blockconsole signature to it:
+   $ ./mkblockconsole /dev/<usb_stick>
+
+2. USB stick is ready for use, replug it so that the kernel can start
+   logging to it.
+
+3. After you've done logging, read out the logs from it like this:
+   $ ./bcon_tail
+
+   This creates a file called /var/log/bcon.<UUID> which contains the
+   last 16M of the logs.  Open it with a sane editor like vim which
+   can display zeroed gaps as a single line and start staring at the
+   logs.
+   For the really impatient, use:
+   $ vi `./bcon_tail`
+
+Introduction:
+=============
+
+This module logs kernel printk messages to block devices, e.g. usb
+sticks.  It allows after-the-fact debugging when the main
+disk/filesystem fails and serial consoles and netconsole are
+impractical.
+
+It can currently only be used built-in.  Blockconsole hooks into the
+partition scanning code and will bring up configured block devices as
+soon as possible.  While this doesn't allow capture of early kernel
+panics, it does capture most of the boot process.
+
+Block device configuration:
+==================================
+
+Blockconsole has no configuration parameter.  In order to use a block
+device for logging, the blockconsole header has to be written to the
+device in question.  Logging to partitions is not supported.
+
+The example program mkblockconsole can be used to generate such a
+header on a device.
+
+Header format:
+==============
+
+A legal header looks like this:
+
+Linux blockconsole version 1.1
+818cf322
+00000000
+00000000
+
+It consists of a newline, the "Linux blockconsole version 1.1" string
+plus three numbers on separate lines each.  Numbers are all 32bit,
+represented as 8-byte hex strings, with letters in lowercase.  The
+first number is a uuid for this particular console device.  Just pick
+a random number when generating the device.  The second number is a
+wrap counter and unlikely to ever increment.  The third is a tile
+counter, with a tile being one megabyte in size.
+
+Miscellaneous notes:
+====================
+
+Blockconsole will write a new header for every tile or once every
+megabyte.  The header starts with a newline in order to ensure the
+"Linux blockconsole...' string always ends up at the beginning of a
+line if you read the blockconsole in a text editor.
+
+The blockconsole header is constructed such that opening the log
+device in a text editor, ignoring memory constraints due to large
+devices, should just work and be reasonably non-confusing to readers.
+However, the example program bcon_tail can be used to copy the last 16
+tiles of the log device to /var/log/bcon.<uuid>, which should be much
+easier to handle.
+
+The wrap counter is used by blockconsole to determine where to
+continue logging after a reboot.  New logs will be written to the
+first tile that wasn't written to by the last instance of
+blockconsole.  Similarly bcon_tail is doing a binary search to find
+the end of the log.
+
+Writing to the log device is strictly circular.  This should give
+optimal performance and reliability on cheap devices, like usb sticks.
+
+Writing to block devices has to happen in sector granularity, while
+kernel logging happens in byte granularity.  In order not to lose
+messages in important cases like kernel crashes, a timer will write
+out partial sectors if no new messages appear for a while.  The
+unwritten part of the sector will be filled with spaces and a single
+newline.  In a quiet system, these empty lines can make up the bulk of
+the log.
diff --git a/Documentation/block/blockconsole/bcon_tail b/Documentation/block/blockconsole/bcon_tail
new file mode 100755
index 0000000..70926c6
--- /dev/null
+++ b/Documentation/block/blockconsole/bcon_tail
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+TAIL_LEN=16
+TEMPLATE=/tmp/bcon_template
+BUF=/tmp/bcon_buf
+
+if [ $(whoami) != "root" ]; then
+	echo "You need to be root to run this."
+	exit 1
+fi
+
+if [ -z "$(which lsscsi)" ]; then
+	echo "You need to install the lsscsi package on your distro."
+	exit 1
+fi
+
+if [ -z "$(which hdparm)" ]; then
+	echo "You need to install the hdparm package on your distro."
+	exit 1
+fi
+
+end_of_log() {
+	DEV=$1
+	UUID=`head -c40 $DEV|tail -c8`
+	LOGFILE=/var/log/bcon.$UUID
+	SECTORS=`hdparm -g $DEV|grep sectors|sed 's/.*sectors = \([0-9]*\).*/\1/'`
+	#MSIZE=`expr $SECTORS / 2048`
+	dd if=$DEV iflag=direct bs=512 2>/dev/null|head -c50 > $TEMPLATE
+	#START, MIDDLE and END are in sectors
+	START=0
+	MIDDLE=$SECTORS
+	END=$SECTORS
+	while true; do
+		MIDDLE=`expr \( \( $END + $START \) / 4096 \) \* 2048`
+		if [ $MIDDLE -eq $START ]; then
+			break
+		fi
+		dd if=$DEV iflag=direct bs=512 count=1 skip=$MIDDLE 2>/dev/null|head -c50 > $BUF
+		if diff -q $BUF $TEMPLATE > /dev/null; then
+			START=$MIDDLE
+		else
+			END=$MIDDLE
+		fi
+	done
+	#switch to megabytes
+	END=`expr $END / 2048`
+	START=`expr $START / 2048`
+	if [ $START -lt $TAIL_LEN ]; then
+		START=0
+	else
+		START=`expr $START - $TAIL_LEN + 1`
+	fi
+	LEN=`expr $END - $START`
+	dd if=$DEV iflag=direct bs=1M count=$LEN skip=$START >$LOGFILE 2>/dev/null
+	echo $LOGFILE
+}
+
+# HEADER contains a newline, so the funny quoting is necessary
+HEADER='
+Linux blockconsole version 1.1'
+
+DEV="$1"
+if [ -n "$DEV" ]; then
+	if [ ! -b "$DEV" ]; then
+		echo "bcon_tail: No block device file $DEV"
+		exit 1
+	fi
+	if [ "`head -c32 $DEV`" != "$HEADER" ]; then
+		echo "bcon_tail: Invalid device file $DEV"
+		exit 1
+	fi
+	end_of_log $DEV
+	exit 0
+fi
+
+CANDIDATES=`lsscsi |sed 's|.*/dev|/dev|'`
+
+for DEV in $CANDIDATES; do
+	if [ "`head -c32 $DEV`" == "$HEADER" ]; then
+		end_of_log $DEV
+	fi
+done
diff --git a/Documentation/block/blockconsole/mkblockconsole b/Documentation/block/blockconsole/mkblockconsole
new file mode 100755
index 0000000..c48f995
--- /dev/null
+++ b/Documentation/block/blockconsole/mkblockconsole
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# handle the case when using files for logging instead of
+# real devices (with kvm, for example)
+DD_OPTS="conv=notrunc"
+
+if [ ! $# -eq 1 ]; then
+	echo "Usage: $0 <dev>"
+	exit 1
+elif mount|fgrep -q $1; then
+	echo Device appears to be mounted - aborting
+	exit 1
+else
+	dd if=/dev/zero of=$1 bs=1M count=1 $DD_OPTS
+	# The funky formatting is actually needed!
+	UUID=`head -c4 /dev/urandom |hexdump -e '/4 "%08x"'`
+	echo > /tmp/$UUID
+	echo 'Linux blockconsole version 1.1' >> /tmp/$UUID
+	echo "$UUID" >> /tmp/$UUID
+	echo 00000000 >> /tmp/$UUID
+	echo 00000000 >> /tmp/$UUID
+	for i in `seq 452`; do echo -n " " >> /tmp/$UUID; done
+	echo >> /tmp/$UUID
+
+	dd if=/tmp/$UUID of=$1 $DD_OPTS
+	rm /tmp/$UUID
+	sync
+	exit 0
+fi
diff --git a/Documentation/block/cfq-iosched.txt b/Documentation/block/cfq-iosched.txt
index 9887f04..f3bc729 100644
--- a/Documentation/block/cfq-iosched.txt
+++ b/Documentation/block/cfq-iosched.txt
@@ -69,7 +69,7 @@ one, this value should be decreased relative to fifo_expire_async.
 group_idle
 -----------
 This parameter forces idling at the CFQ group level instead of CFQ
-queue level. This was introduced after after a bottleneck was observed
+queue level. This was introduced after a bottleneck was observed
 in higher end storage due to idle on sequential queue and allow dispatch
 from a single queue. The idea with this parameter is that it can be run with
 slice_idle=0 and group_idle=8, so that idling does not happen on individual
diff --git a/Documentation/block/cmdline-partition.txt b/Documentation/block/cmdline-partition.txt
new file mode 100644
index 0000000..651863d
--- /dev/null
+++ b/Documentation/block/cmdline-partition.txt
@@ -0,0 +1,40 @@
+Embedded device command line partition
+=====================================================================
+
+Read block device partition table from command line.
+The partition used for fixed block device (eMMC) embedded device.
+It is no MBR, save storage space. Bootloader can be easily accessed
+by absolute address of data on the block device.
+Users can easily change the partition.
+
+The format for the command line is just like mtdparts:
+
+blkdevparts=<blkdev-def>[;<blkdev-def>]
+  <blkdev-def> := <blkdev-id>:<partdef>[,<partdef>]
+    <partdef> := <size>[@<offset>](part-name)
+
+<blkdev-id>
+    block device disk name, embedded device used fixed block device,
+    it's disk name also fixed. such as: mmcblk0, mmcblk1, mmcblk0boot0.
+
+<size>
+    partition size, in bytes, such as: 512, 1m, 1G.
+
+<offset>
+    partition start address, in bytes.
+
+(part-name)
+    partition name, kernel send uevent with "PARTNAME". application can create
+    a link to block device partition with the name "PARTNAME".
+    user space application can access partition by partition name.
+
+Example:
+    eMMC disk name is "mmcblk0" and "mmcblk0boot0"
+
+  bootargs:
+    'blkdevparts=mmcblk0:1G(data0),1G(data1),-;mmcblk0boot0:1m(boot),-(kernel)'
+
+  dmesg:
+    mmcblk0: p1(data0) p2(data1) p3()
+    mmcblk0boot0: p1(boot) p2(kernel)
+
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
index 19fa98e..40282e6 100644
--- a/Documentation/cpu-freq/cpu-drivers.txt
+++ b/Documentation/cpu-freq/cpu-drivers.txt
@@ -50,8 +50,6 @@ What shall this struct cpufreq_driver contain?
 
 cpufreq_driver.name -		The name of this driver.
 
-cpufreq_driver.owner -		THIS_MODULE;
-
 cpufreq_driver.init -		A pointer to the per-CPU initialization 
 				function.
 
diff --git a/Documentation/development-process/2.Process b/Documentation/development-process/2.Process
index 4823577..2e06179 100644
--- a/Documentation/development-process/2.Process
+++ b/Documentation/development-process/2.Process
@@ -276,7 +276,7 @@ mainline get there via -mm.
 The current -mm patch is available in the "mmotm" (-mm of the moment)
 directory at:
 
-	http://userweb.kernel.org/~akpm/mmotm/
+	http://www.ozlabs.org/~akpm/mmotm/
 
 Use of the MMOTM tree is likely to be a frustrating experience, though;
 there is a definite chance that it will not even compile.
@@ -287,7 +287,7 @@ the mainline is expected to look like after the next merge window closes.
 Linux-next trees are announced on the linux-kernel and linux-next mailing
 lists when they are assembled; they can be downloaded from:
 
-	http://www.kernel.org/pub/linux/kernel/people/sfr/linux-next/
+	http://www.kernel.org/pub/linux/kernel/next/
 
 Some information about linux-next has been gathered at:
 
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
index 61df564..d74091a 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
@@ -4,6 +4,8 @@ Marvell Armada 370 and Armada XP Interrupt Controller
 Required properties:
 - compatible: Should be "marvell,mpic"
 - interrupt-controller: Identifies the node as an interrupt controller.
+- msi-controller: Identifies the node as an PCI Message Signaled
+  Interrupt controller.
 - #interrupt-cells: The number of cells to define the interrupts. Should be 1.
   The cell is the IRQ number
 
@@ -24,6 +26,7 @@ Example:
               #address-cells = <1>;
               #size-cells = <1>;
               interrupt-controller;
+              msi-controller;
               reg = <0xd0020a00 0x1d0>,
                     <0xd0021070 0x58>;
         };
diff --git a/Documentation/devicetree/bindings/arm/ste-u300.txt b/Documentation/devicetree/bindings/arm/ste-u300.txt
index 69b5ab0..d11d800 100644
--- a/Documentation/devicetree/bindings/arm/ste-u300.txt
+++ b/Documentation/devicetree/bindings/arm/ste-u300.txt
@@ -22,7 +22,7 @@ This contains the board-specific information.
 - compatible: must be "stericsson,s365".
 - vana15-supply: the regulator supplying the 1.5V to drive the
   board.
-- syscon: a pointer to the syscon node so we can acccess the
+- syscon: a pointer to the syscon node so we can access the
   syscon registers to set the board as self-powered.
 
 Example:
diff --git a/Documentation/devicetree/bindings/arm/vexpress-scc.txt b/Documentation/devicetree/bindings/arm/vexpress-scc.txt
new file mode 100644
index 0000000..f25849d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vexpress-scc.txt
@@ -0,0 +1,37 @@
+* ARM Versatile Express Serial Configuration Controller device tree bindings
+
+Latest ARM development boards implement a serial configuration interface (SCC)
+that can be used to retrieve temperature sensors, energy/voltage/current
+probes and oscillators values through the SYS configuration protocol defined
+for versatile express motherboards.
+It also provides a power management interface (serial power controller - SPC)
+that is capable of managing power/voltage and operating points transitions,
+wake-up IRQs and resume addresses for ARM multiprocessor testchips.
+
+The SCC DT bindings are defined as follows:
+
+- scc node
+
+	- compatible:
+		Usage: required
+		Value type: <stringlist>
+		Definition: must be
+			    "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc"
+	- reg:
+		Usage: required
+		Value type: <prop-encode-array>
+		Definition: A standard property that specifies the base address
+			    and the size of the SCC address space
+	- interrupts:
+		Usage: required
+		Value type: <prop-encoded-array>
+		Definition:  SCC interrupt configuration. A standard property
+			     that follows ePAPR interrupts specifications
+
+Example:
+
+scc: scc@7fff0000 {
+	compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
+	reg = <0x7fff0000 0x1000>;
+	interrupts = <0 95 4>;
+};
diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
index 9cf3f25..5580e9c 100644
--- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
@@ -32,8 +32,8 @@ numbers - see motherboard's TRM for more details.
 The node describing a config device must refer to the sysreg node via
 "arm,vexpress,config-bridge" phandle (can be also defined in the node's
 parent) and relies on the board topology properties - see main vexpress
-node documentation for more details. It must must also define the
-following property:
+node documentation for more details. It must also define the following
+property:
 - arm,vexpress-sysreg,func : must contain two cells:
   - first cell defines function number (eg. 1 for clock generator,
     2 for voltage regulators etc.)
diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt
index cedc2a9..0fd76c4 100644
--- a/Documentation/devicetree/bindings/bus/imx-weim.txt
+++ b/Documentation/devicetree/bindings/bus/imx-weim.txt
@@ -8,7 +8,7 @@ The actual devices are instantiated from the child nodes of a WEIM node.
 
 Required properties:
 
- - compatible:		Should be set to "fsl,imx6q-weim"
+ - compatible:		Should be set to "fsl,<soc>-weim"
  - reg:			A resource specifier for the register space
 			(see the example below)
  - clocks:		the clock, see the example below.
@@ -21,11 +21,18 @@ Required properties:
 
 Timing property for child nodes. It is mandatory, not optional.
 
- - fsl,weim-cs-timing:	The timing array, contains 6 timing values for the
+ - fsl,weim-cs-timing:	The timing array, contains timing values for the
 			child node. We can get the CS index from the child
-			node's "reg" property. This property contains the values
-			for the registers EIM_CSnGCR1, EIM_CSnGCR2, EIM_CSnRCR1,
-			EIM_CSnRCR2, EIM_CSnWCR1, EIM_CSnWCR2 in this order.
+			node's "reg" property. The number of registers depends
+			on the selected chip.
+			For i.MX1, i.MX21 ("fsl,imx1-weim") there are two
+			registers: CSxU, CSxL.
+			For i.MX25, i.MX27, i.MX31 and i.MX35 ("fsl,imx27-weim")
+			there are three registers: CSCRxU, CSCRxL, CSCRxA.
+			For i.MX50, i.MX53 ("fsl,imx50-weim"),
+			i.MX51 ("fsl,imx51-weim") and i.MX6Q ("fsl,imx6q-weim")
+			there are six registers: CSxGCR1, CSxGCR2, CSxRCR1,
+			CSxRCR2, CSxWCR1, CSxWCR2.
 
 Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM:
 
diff --git a/Documentation/devicetree/bindings/bus/mvebu-mbus.txt b/Documentation/devicetree/bindings/bus/mvebu-mbus.txt
new file mode 100644
index 0000000..7586fb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/mvebu-mbus.txt
@@ -0,0 +1,276 @@
+
+* Marvell MBus
+
+Required properties:
+
+- compatible:	 Should be set to one of the following:
+		 marvell,armada370-mbus
+		 marvell,armadaxp-mbus
+		 marvell,armada370-mbus
+		 marvell,armadaxp-mbus
+		 marvell,kirkwood-mbus
+		 marvell,dove-mbus
+		 marvell,orion5x-88f5281-mbus
+		 marvell,orion5x-88f5182-mbus
+		 marvell,orion5x-88f5181-mbus
+		 marvell,orion5x-88f6183-mbus
+		 marvell,mv78xx0-mbus
+
+- address-cells: Must be '2'. The first cell for the MBus ID encoding,
+                 the second cell for the address offset within the window.
+
+- size-cells:    Must be '1'.
+
+- ranges:        Must be set up to provide a proper translation for each child.
+	         See the examples below.
+
+- controller:    Contains a single phandle referring to the MBus controller
+                 node. This allows to specify the node that contains the
+		 registers that control the MBus, which is typically contained
+		 within the internal register window (see below).
+
+Optional properties:
+
+- pcie-mem-aperture:	This optional property contains the aperture for
+			the memory region of the PCIe driver.
+			If it's defined, it must encode the base address and
+			size for the address decoding windows allocated for
+			the PCIe memory region.
+
+- pcie-io-aperture:	Just as explained for the above property, this
+			optional property contains the aperture for the
+			I/O region of the PCIe driver.
+
+* Marvell MBus controller
+
+Required properties:
+
+- compatible:	Should be set to "marvell,mbus-controller".
+
+- reg:          Device's register space.
+		Two entries are expected (see the examples below):
+		the first one controls the devices decoding window and
+		the second one controls the SDRAM decoding window.
+
+Example:
+
+	soc {
+		compatible = "marvell,armada370-mbus", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		pcie-mem-aperture = <0xe0000000 0x8000000>;
+		pcie-io-aperture  = <0xe8000000 0x100000>;
+
+		internal-regs {
+			compatible = "simple-bus";
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			/* more children ...*/
+		};
+	};
+
+** MBus address decoding window specification
+
+The MBus children address space is comprised of two cells: the first one for
+the window ID and the second one for the offset within the window.
+In order to allow to describe valid and non-valid window entries, the
+following encoding is used:
+
+  0xSIAA0000 0x00oooooo
+
+Where:
+
+  S = 0x0 for a MBus valid window
+  S = 0xf for a non-valid window (see below)
+
+If S = 0x0, then:
+
+   I = 4-bit window target ID
+  AA = windpw attribute
+
+If S = 0xf, then:
+
+   I = don't care
+   AA = 1 for internal register
+
+Following the above encoding, for each ranges entry for a MBus valid window
+(S = 0x0), an address decoding window is allocated. On the other side,
+entries for translation that do not correspond to valid windows (S = 0xf)
+are skipped.
+
+	soc {
+		compatible = "marvell,armada370-mbus", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+
+		ranges = <0xf0010000 0 0 0xd0000000 0x100000
+			  0x01e00000 0 0 0xfff00000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <0x01e00000 0 0x100000>;
+		};
+
+		/* other children */
+		...
+
+		internal-regs {
+			compatible = "simple-bus";
+			ranges = <0 0xf0010000 0 0x100000>;
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			/* more children ...*/
+		};
+	};
+
+In the shown example, the translation entry in the 'ranges' property is what
+makes the MBus driver create a static decoding window for the corresponding
+given child device. Note that the binding does not require child nodes to be
+present. Of course, child nodes are needed to probe the devices.
+
+Since each window is identified by its target ID and attribute ID there's
+a special macro that can be use to simplify the translation entries:
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+Using this macro, the above example would be:
+
+	soc {
+		compatible = "marvell,armada370-mbus", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+
+		ranges = < MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+			   MBUS_ID(0x01, 0xe0) 0 0 0xfff00000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0xe0) 0 0x100000>;
+		};
+
+		/* other children */
+		...
+
+		internal-regs {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			/* other children */
+			...
+		};
+	};
+
+
+** About the window base address
+
+Remember the MBus controller allows a great deal of flexibility for choosing
+the decoding window base address. When planning the device tree layout it's
+possible to choose any address as the base address, provided of course there's
+a region large enough available, and with the required alignment.
+
+Yet in other words: there's nothing preventing us from setting a base address
+of 0xf0000000, or 0xd0000000 for the NOR device shown above, if such region is
+unused.
+
+** Window allocation policy
+
+The mbus-node ranges property defines a set of mbus windows that are expected
+to be set by the operating system and that are guaranteed to be free of overlaps
+with one another or with the system memory ranges.
+
+Each entry in the property refers to exactly one window. If the operating system
+choses to use a different set of mbus windows, it must ensure that any address
+translations performed from downstream devices are adapted accordingly.
+
+The operating system may insert additional mbus windows that do not conflict
+with the ones listed in the ranges, e.g. for mapping PCIe devices.
+As a special case, the internal register window must be set up by the boot
+loader at the address listed in the ranges property, since access to that region
+is needed to set up the other windows.
+
+** Example
+
+See the example below, where a more complete device tree is shown:
+
+	soc {
+		compatible = "marvell,armadaxp-mbus", "simple-bus";
+		controller = <&mbusc>;
+
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000   /* internal-regs */
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
+		};
+
+		devbus-bootcs {
+			status = "okay";
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0x8000000>;
+
+			/* NOR */
+			nor {
+				compatible = "cfi-flash";
+				reg = <0 0x8000000>;
+				bank-width = <2>;
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-xp-pcie";
+			status = "okay";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
+				0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
+				0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+				0x82000800 0 0xe0000000 MBUS_ID(0x04, 0xe8) 0xe0000000 0 0x08000000 /* Port 0.0 MEM */
+				0x81000800 0 0          MBUS_ID(0x04, 0xe0) 0xe8000000 0 0x00100000 /* Port 0.0 IO */>;
+
+
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		internal-regs {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			mbusc: mbus-controller@20000 {
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			interrupt-controller@20000 {
+			      reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
index a120180..75e2e19 100644
--- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
+++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
@@ -2,7 +2,7 @@
 
 The Samsung Audio Subsystem clock controller generates and supplies clocks
 to Audio Subsystem block available in the S5PV210 and Exynos SoCs. The clock
-binding described here is applicable to all SoC's in Exynos family.
+binding described here is applicable to all SoCs in Exynos family.
 
 Required Properties:
 
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
index 14d5c2a..c6bf8a6 100644
--- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
@@ -236,6 +236,7 @@ Exynos4 SoC and this is specified where applicable.
   spi0_isp_sclk       380     Exynos4x12
   spi1_isp_sclk       381     Exynos4x12
   uart_isp_sclk       382     Exynos4x12
+  tmu_apbif           383
 
 		[Mux Clocks]
 
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
index 781a627..24765c1 100644
--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
@@ -59,6 +59,9 @@ clock which they consume.
   sclk_spi0		154
   sclk_spi1		155
   sclk_spi2		156
+  div_i2s1		157
+  div_i2s2		158
+  sclk_hdmiphy		159
 
 
    [Peripheral Clock Gates]
@@ -154,7 +157,16 @@ clock which they consume.
   dsim0			341
   dp			342
   mixer			343
-  hdmi			345
+  hdmi			344
+  g2d			345
+
+
+   [Clock Muxes]
+
+  Clock			ID
+  ----------------------------
+  mout_hdmi		1024
+
 
 Example 1: An example of a clock controller node is listed below.
 
diff --git a/Documentation/devicetree/bindings/clock/imx5-clock.txt b/Documentation/devicetree/bindings/clock/imx5-clock.txt
index f46f562..4c029a8 100644
--- a/Documentation/devicetree/bindings/clock/imx5-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx5-clock.txt
@@ -197,6 +197,7 @@ clocks and IDs.
 	spdif0_gate		183
 	spdif1_gate		184
 	spdif_ipg_gate		185
+	ocram			186
 
 Examples (for mx53):
 
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index a0e104f..5a90a72 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -209,6 +209,12 @@ clocks and IDs.
 	pll5_post_div		194
 	pll5_video_div		195
 	eim_slow      		196
+	spdif      		197
+	cko2_sel      		198
+	cko2_podf      		199
+	cko2      		200
+	cko      		201
+	vdoa      		202
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/dma/atmel-dma.txt b/Documentation/devicetree/bindings/dma/atmel-dma.txt
index c280a0e..e1f343c 100644
--- a/Documentation/devicetree/bindings/dma/atmel-dma.txt
+++ b/Documentation/devicetree/bindings/dma/atmel-dma.txt
@@ -18,14 +18,14 @@ dma0: dma@ffffec00 {
 
 DMA clients connected to the Atmel DMA controller must use the format
 described in the dma.txt file, using a three-cell specifier for each channel:
-a phandle plus two interger cells.
+a phandle plus two integer cells.
 The three cells in order are:
 
 1. A phandle pointing to the DMA controller.
 2. The memory interface (16 most significant bits), the peripheral interface
 (16 less significant bits).
 3. Parameters for the at91 DMA configuration register which are device
-dependant:
+dependent:
   - bit 7-0: peripheral identifier for the hardware handshaking interface. The
   identifier can be different for tx and rx.
   - bit 11-8: FIFO configuration. 0 for half FIFO, 1 for ALAP, 1 for ASAP.
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt
index 2717ecb..7bd8847 100644
--- a/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt
@@ -34,7 +34,7 @@ Clients have to specify the DMA requests with phandles in a list.
 Required properties:
 - dmas: List of one or more DMA request specifiers. One DMA request specifier
     consists of a phandle to the DMA controller followed by the integer
-    specifiying the request line.
+    specifying the request line.
 - dma-names: List of string identifiers for the DMA requests. For the correct
     names, have a look at the specific client driver.
 
diff --git a/Documentation/devicetree/bindings/dma/ste-dma40.txt b/Documentation/devicetree/bindings/dma/ste-dma40.txt
index bea5b73..a8c21c2 100644
--- a/Documentation/devicetree/bindings/dma/ste-dma40.txt
+++ b/Documentation/devicetree/bindings/dma/ste-dma40.txt
@@ -37,14 +37,14 @@ Each dmas request consists of 4 cells:
   1. A phandle pointing to the DMA controller
   2. Device Type
   3. The DMA request line number (only when 'use fixed channel' is set)
-  4. A 32bit mask specifying; mode, direction and endianess [NB: This list will grow]
+  4. A 32bit mask specifying; mode, direction and endianness [NB: This list will grow]
         0x00000001: Mode:
                 Logical channel when unset
                 Physical channel when set
         0x00000002: Direction:
                 Memory to Device when unset
                 Device to Memory when set
-        0x00000004: Endianess:
+        0x00000004: Endianness:
                 Little endian when unset
                 Big endian when set
         0x00000008: Use fixed channel:
diff --git a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
new file mode 100644
index 0000000..7dab6a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
@@ -0,0 +1,15 @@
+EXTCON FOR PALMAS/TWL CHIPS
+
+PALMAS USB COMPARATOR
+Required Properties:
+ - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb"
+
+Optional Properties:
+ - ti,wakeup : To enable the wakeup comparator in probe
+ - ti,enable-id-detection: Perform ID detection.
+ - ti,enable-vbus-detection: Perform VBUS detection.
+
+palmas-usb {
+       compatible = "ti,twl6035-usb", "ti,palmas-usb";
+       ti,wakeup;
+};
diff --git a/Documentation/devicetree/bindings/extcon/extcon-twl.txt b/Documentation/devicetree/bindings/extcon/extcon-twl.txt
deleted file mode 100644
index 58f531a..0000000
--- a/Documentation/devicetree/bindings/extcon/extcon-twl.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-EXTCON FOR TWL CHIPS
-
-PALMAS USB COMPARATOR
-Required Properties:
- - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb"
- - vbus-supply : phandle to the regulator device tree node.
-
-Optional Properties:
- - ti,wakeup : To enable the wakeup comparator in probe
-
-palmas-usb {
-       compatible = "ti,twl6035-usb", "ti,palmas-usb";
-       vbus-supply = <&smps10_reg>;
-       ti,wakeup;
-};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-palmas.txt b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
new file mode 100644
index 0000000..08b5b52
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
@@ -0,0 +1,27 @@
+Palmas GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "ti,palams-gpio" for palma series of the GPIO controller
+  - "ti,tps80036-gpio" for Palma series device TPS80036.
+  - "ti,tps65913-gpio" for palma series device TPS65913.
+  - "ti,tps65914-gpio" for palma series device TPS65914.
+- #gpio-cells : Should be two.
+  - first cell is the gpio pin number
+  - second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+- gpio-controller : Marks the device node as a GPIO controller.
+
+Note: This gpio node will be sub node of palmas node.
+
+Example:
+	palmas: tps65913@58 {
+		:::::::::::
+		palmas_gpio: palmas_gpio {
+			compatible = "ti,palmas-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+		:::::::::::
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt
new file mode 100644
index 0000000..1fd98ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt
@@ -0,0 +1,45 @@
+ImgTec TZ1090 PDC GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "img,tz1090-pdc-gpio".
+
+- reg: Physical base address of the controller and length of memory mapped
+  region. This starts at and cover the SOC_GPIO_CONTROL registers.
+
+- gpio-controller: Specifies that the node is a gpio controller.
+
+- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
+  nodes should have the following values.
+     <[phandle of the gpio controller node]
+      [PDC gpio number]
+      [gpio flags]>
+
+  Values for gpio specifier:
+  - GPIO number: a value in the range 0 to 6.
+  - GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
+    Only the following flags are supported:
+      GPIO_ACTIVE_HIGH
+      GPIO_ACTIVE_LOW
+
+Optional properties:
+- gpio-ranges: Mapping to pin controller pins (as described in
+  Documentation/devicetree/bindings/gpio/gpio.txt)
+
+- interrupts: Individual syswake interrupts (other GPIOs cannot interrupt)
+
+
+Example:
+
+	pdc_gpios: gpio-controller@02006500 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		compatible = "img,tz1090-pdc-gpio";
+		reg = <0x02006500 0x100>;
+
+		interrupt-parent = <&pdc>;
+		interrupts =	<8  IRQ_TYPE_NONE>,	/* Syswake 0 */
+				<9  IRQ_TYPE_NONE>,	/* Syswake 1 */
+				<10 IRQ_TYPE_NONE>;	/* Syswake 2 */
+		gpio-ranges = <&pdc_pinctrl 0 0 7>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt
new file mode 100644
index 0000000..174cdf3
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt
@@ -0,0 +1,88 @@
+ImgTec TZ1090 GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "img,tz1090-gpio".
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- #address-cells: Should be 1 (for bank subnodes)
+
+- #size-cells: Should be 0 (for bank subnodes)
+
+- Each bank of GPIOs should have a subnode to represent it.
+
+  Bank subnode required properties:
+  - reg: Index of bank in the range 0 to 2.
+
+  - gpio-controller: Specifies that the node is a gpio controller.
+
+  - #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
+    nodes should have the following values.
+       <[phandle of the gpio controller node]
+        [gpio number within the gpio bank]
+        [gpio flags]>
+
+    Values for gpio specifier:
+    - GPIO number: a value in the range 0 to 29.
+    - GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
+      Only the following flags are supported:
+        GPIO_ACTIVE_HIGH
+        GPIO_ACTIVE_LOW
+
+  Bank subnode optional properties:
+  - gpio-ranges: Mapping to pin controller pins (as described in
+    Documentation/devicetree/bindings/gpio/gpio.txt)
+
+  - interrupts: Interrupt for the entire bank
+
+  - interrupt-controller: Specifies that the node is an interrupt controller
+
+  - #interrupt-cells: Should be 2. The syntax of the interrupt specifier used by
+    client nodes should have the following values.
+       <[phandle of the interurupt controller]
+        [gpio number within the gpio bank]
+        [irq flags]>
+
+    Values for irq specifier:
+    - GPIO number: a value in the range 0 to 29
+    - IRQ flags: value to describe edge and level triggering, as defined in
+      <dt-bindings/interrupt-controller/irq.h>. Only the following flags are
+      supported:
+        IRQ_TYPE_EDGE_RISING
+        IRQ_TYPE_EDGE_FALLING
+        IRQ_TYPE_EDGE_BOTH
+        IRQ_TYPE_LEVEL_HIGH
+        IRQ_TYPE_LEVEL_LOW
+
+
+
+Example:
+
+	gpios: gpio-controller@02005800 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "img,tz1090-gpio";
+		reg = <0x02005800 0x90>;
+
+		/* bank 0 with an interrupt */
+		gpios0: bank@0 {
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+			reg = <0>;
+			interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			gpio-ranges = <&pinctrl 0 0 30>;
+			interrupt-controller;
+		};
+
+		/* bank 2 without interrupt */
+		gpios2: bank@2 {
+			#gpio-cells = <2>;
+			reg = <2>;
+			gpio-controller;
+			gpio-ranges = <&pinctrl 0 60 30>;
+		};
+	};
+
+
diff --git a/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt b/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
index 9b3f1d4..6641626 100644
--- a/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
@@ -10,8 +10,9 @@ Required properties:
   There're three gpio interrupts in arch-pxa, and they're gpio0,
   gpio1 and gpio_mux. There're only one gpio interrupt in arch-mmp,
   gpio_mux.
-- interrupt-name : Should be the name of irq resource. Each interrupt
-  binds its interrupt-name.
+- interrupt-names : Should be the names of irq resources. Each interrupt
+  uses its own interrupt name, so there should be as many interrupt names
+  as referenced interrups.
 - interrupt-controller : Identifies the node as an interrupt controller.
 - #interrupt-cells: Specifies the number of cells needed to encode an
   interrupt source.
@@ -24,7 +25,7 @@ Example:
 		compatible = "marvell,mmp-gpio";
 		reg = <0xd4019000 0x1000>;
 		interrupts = <49>;
-		interrupt-name = "gpio_mux";
+		interrupt-names = "gpio_mux";
 		gpio-controller;
 		#gpio-cells = <1>;
 		interrupt-controller;
diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
index cb3dc7b..8655df9 100644
--- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
+++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
@@ -23,6 +23,10 @@ Required Properties:
 Please refer to gpio.txt in this directory for details of gpio-ranges property
 and the common GPIO bindings used by client devices.
 
+The GPIO controller also acts as an interrupt controller. It uses the default
+two cells specifier as described in Documentation/devicetree/bindings/
+interrupt-controller/interrupts.txt.
+
 Example: R8A7779 (R-Car H1) GPIO controller nodes
 
 	gpio0: gpio@ffc40000 {
@@ -33,6 +37,8 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes
 		#gpio-cells = <2>;
 		gpio-controller;
 		gpio-ranges = <&pfc 0 0 32>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 	};
 	...
 	gpio6: gpio@ffc46000 {
@@ -43,4 +49,6 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes
 		#gpio-cells = <2>;
 		gpio-controller;
 		gpio-ranges = <&pfc 0 192 9>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 	};
diff --git a/Documentation/devicetree/bindings/gpu/samsung-g2d.txt b/Documentation/devicetree/bindings/gpu/samsung-g2d.txt
index 3f454ff..c4f358d 100644
--- a/Documentation/devicetree/bindings/gpu/samsung-g2d.txt
+++ b/Documentation/devicetree/bindings/gpu/samsung-g2d.txt
@@ -11,8 +11,11 @@ Required properties:
 
   - interrupts : G2D interrupt number to the CPU.
   - clocks : from common clock binding: handle to G2D clocks.
-  - clock-names : from common clock binding: must contain "sclk_fimg2d" and
-		  "fimg2d", corresponding to entries in the clocks property.
+  - clock-names : names of clocks listed in clocks property, in the same
+		  order, depending on SoC type:
+		  - for S5PV210 and Exynos4 based SoCs: "fimg2d" and
+		    "sclk_fimg2d"
+		  - for Exynos5250 SoC: "fimg2d".
 
 Example:
 	g2d@12800000 {
diff --git a/Documentation/devicetree/bindings/hid/hid-over-i2c.txt b/Documentation/devicetree/bindings/hid/hid-over-i2c.txt
new file mode 100644
index 0000000..488edcb
--- /dev/null
+++ b/Documentation/devicetree/bindings/hid/hid-over-i2c.txt
@@ -0,0 +1,28 @@
+* HID over I2C Device-Tree bindings
+
+HID over I2C provides support for various Human Interface Devices over the
+I2C bus. These devices can be for example touchpads, keyboards, touch screens
+or sensors.
+
+The specification has been written by Microsoft and is currently available here:
+http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx
+
+If this binding is used, the kernel module i2c-hid will handle the communication
+with the device and the generic hid core layer will handle the protocol.
+
+Required properties:
+- compatible: must be "hid-over-i2c"
+- reg: i2c slave address
+- hid-descr-addr: HID descriptor address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: interrupt line
+
+Example:
+
+	i2c-hid-dev@2c {
+		compatible = "hid-over-i2c";
+		reg = <0x2c>;
+		hid-descr-addr = <0x0020>;
+		interrupt-parent = <&gpx3>;
+		interrupts = <3 2>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
index a1ee681..9ab408f 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
@@ -4,7 +4,9 @@
 Required properties :
 
  - reg             : Offset and length of the register set for the device
- - compatible      : Should be "marvell,mv64xxx-i2c"
+ - compatible      : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c"
+                     or "marvell,mv7230-i2c" for controller which support
+                     the I2C Transaction Generator
  - interrupts      : The interrupt number
 
 Optional properties :
@@ -20,3 +22,13 @@ Examples:
 		interrupts = <29>;
 		clock-frequency = <100000>;
 	};
+
+For a controller which support the I2C Transaction Generator:
+
+	i2c@11000 {
+		compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+		reg = <0x11000 0x100>;
+		compatible = "marvell,mv64xxx-i2c";
+		interrupts = <29>;
+		clock-frequency = <100000>;
+	};
diff --git a/Documentation/devicetree/bindings/iio/adc/nuvoton-nau7802.txt b/Documentation/devicetree/bindings/iio/adc/nuvoton-nau7802.txt
new file mode 100644
index 0000000..e9582e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/nuvoton-nau7802.txt
@@ -0,0 +1,18 @@
+* Nuvoton NAU7802 Analog to Digital Converter (ADC)
+
+Required properties:
+  - compatible: Should be "nuvoton,nau7802"
+  - reg: Should contain the ADC I2C address
+
+Optional properties:
+  - nuvoton,vldo: Internal reference voltage in millivolts to be
+    configured valid values are between 2400 mV and 4500 mV.
+  - interrupts: IRQ line for the ADC. If not used the driver will use
+    polling.
+
+Example:
+adc2: nau7802@2a {
+	compatible = "nuvoton,nau7802";
+	reg = <0x2a>;
+	nuvoton,vldo = <3000>;
+};
diff --git a/Documentation/devicetree/bindings/iio/light/apds9300.txt b/Documentation/devicetree/bindings/iio/light/apds9300.txt
new file mode 100644
index 0000000..d6f66c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/apds9300.txt
@@ -0,0 +1,22 @@
+* Avago APDS9300 ambient light sensor
+
+http://www.avagotech.com/docs/AV02-1077EN
+
+Required properties:
+
+  - compatible : should be "avago,apds9300"
+  - reg : the I2C address of the sensor
+
+Optional properties:
+
+  - interrupt-parent : should be the phandle for the interrupt controller
+  - interrupts : interrupt mapping for GPIO IRQ
+
+Example:
+
+apds9300@39 {
+	compatible = "avago,apds9300";
+	reg = <0x39>;
+	interrupt-parent = <&gpio2>;
+	interrupts = <29 8>;
+};
diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
index d517688..a61727f 100644
--- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
@@ -1,7 +1,7 @@
 Binding for TI/National Semiconductor LP55xx Led Drivers
 
 Required properties:
-- compatible: "national,lp5521" or "national,lp5523" or "ti,lp5562"
+- compatible: "national,lp5521" or "national,lp5523" or "ti,lp5562" or "ti,lp8501"
 - reg: I2C slave address
 - clock-mode: Input clock mode, (0: automode, 1: internal, 2: external)
 
@@ -11,6 +11,11 @@ Each child has own specific current settings
 
 Optional properties:
 - label: Used for naming LEDs
+- pwr-sel: LP8501 specific property. Power selection for output channels.
+         0: D1~9 are connected to VDD
+         1: D1~6 with VDD, D7~9 with VOUT
+         2: D1~6 with VOUT, D7~9 with VDD
+         3: D1~9 are connected to VOUT
 
 Alternatively, each child can have specific channel name
 - chan-name: Name of each channel name
@@ -145,3 +150,68 @@ lp5562@30 {
 		max-cur = /bits/ 8 <0x60>;
 	};
 };
+
+example 4) LP8501
+9 channels are defined. The 'pwr-sel' is LP8501 specific property.
+Others are same as LP5523.
+
+lp8501@32 {
+	compatible = "ti,lp8501";
+	reg = <0x32>;
+	clock-mode = /bits/ 8 <2>;
+	pwr-sel = /bits/ 8 <3>;	/* D1~9 connected to VOUT */
+
+	chan0 {
+		chan-name = "d1";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan1 {
+		chan-name = "d2";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan2 {
+		chan-name = "d3";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan3 {
+		chan-name = "d4";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan4 {
+		chan-name = "d5";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan5 {
+		chan-name = "d6";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan6 {
+		chan-name = "d7";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan7 {
+		chan-name = "d8";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+
+	chan8 {
+		chan-name = "d9";
+		led-cur = /bits/ 8 <0x14>;
+		max-cur = /bits/ 8 <0x20>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/leds/pca9633.txt b/Documentation/devicetree/bindings/leds/pca9633.txt
new file mode 100644
index 0000000..6d9e1a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/pca9633.txt
@@ -0,0 +1,46 @@
+LEDs connected to pca9633 or pca9632
+
+Required properties:
+- compatible : should be : "nxp,pca963x"
+
+Optional properties:
+- nxp,totem-pole : use totem pole (push-pull) instead of default open-drain
+- nxp,hw-blink : use hardware blinking instead of software blinking
+
+Each led is represented as a sub-node of the nxp,pca9633 device.
+
+LED sub-node properties:
+- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
+- reg : number of LED line (could be from 0 to 4)
+- linux,default-trigger : (optional)
+   see Documentation/devicetree/bindings/leds/common.txt
+
+Examples:
+
+pca9632: pca9632 {
+	compatible = "nxp,pca9632", "nxp,pca963x";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x62>;
+
+	red@0 {
+		label = "red";
+		reg = <0>;
+		linux,default-trigger = "none";
+	};
+	green@1 {
+		label = "green";
+		reg = <1>;
+		linux,default-trigger = "none";
+	};
+	blue@2 {
+		label = "blue";
+		reg = <2>;
+		linux,default-trigger = "none";
+	};
+	unused@3 {
+		label = "unused";
+		reg = <3>;
+		linux,default-trigger = "none";
+	};
+};
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7343.txt b/Documentation/devicetree/bindings/media/i2c/adv7343.txt
new file mode 100644
index 0000000..5653bc2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/adv7343.txt
@@ -0,0 +1,48 @@
+* Analog Devices adv7343 video encoder
+
+The ADV7343 are high speed, digital-to-analog video encoders in a 64-lead LQFP
+package. Six high speed, 3.3 V, 11-bit video DACs provide support for composite
+(CVBS), S-Video (Y-C), and component (YPrPb/RGB) analog outputs in standard
+definition (SD), enhanced definition (ED), or high definition (HD) video
+formats.
+
+Required Properties :
+- compatible: Must be "adi,adv7343"
+
+Optional Properties :
+- adi,power-mode-sleep-mode: on enable the current consumption is reduced to
+			      micro ampere level. All DACs and the internal PLL
+			      circuit are disabled.
+- adi,power-mode-pll-ctrl: PLL and oversampling control. This control allows
+			   internal PLL 1 circuit to be powered down and the
+			   oversampling to be switched off.
+- ad,adv7343-power-mode-dac: array configuring the power on/off DAC's 1..6,
+			      0 = OFF and 1 = ON, Default value when this
+			      property is not specified is <0 0 0 0 0 0>.
+- ad,adv7343-sd-config-dac-out: array configure SD DAC Output's 1 and 2, 0 = OFF
+				 and 1 = ON, Default value when this property is
+				 not specified is <0 0>.
+
+Example:
+
+i2c0@1c22000 {
+	...
+	...
+
+	adv7343@2a {
+		compatible = "adi,adv7343";
+		reg = <0x2a>;
+
+		port {
+			adv7343_1: endpoint {
+					adi,power-mode-sleep-mode;
+					adi,power-mode-pll-ctrl;
+					/* Use DAC1..3, DAC6 */
+					adi,dac-enable = <1 1 1 0 0 1>;
+					/* Use SD DAC output 1 */
+					adi,sd-dac-enable = <1 0>;
+			};
+		};
+	};
+	...
+};
diff --git a/Documentation/devicetree/bindings/media/i2c/ths8200.txt b/Documentation/devicetree/bindings/media/i2c/ths8200.txt
new file mode 100644
index 0000000..285f6ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ths8200.txt
@@ -0,0 +1,19 @@
+* Texas Instruments THS8200 video encoder
+
+The ths8200 device is a digital to analog converter used in DVD players, video
+recorders, set-top boxes.
+
+Required Properties :
+- compatible : value must be "ti,ths8200"
+
+Example:
+
+	i2c0@1c22000 {
+		...
+		...
+		ths8200@5c {
+			compatible = "ti,ths8200";
+			reg = <0x5c>;
+		};
+		...
+	};
diff --git a/Documentation/devicetree/bindings/mfd/cros-ec.txt b/Documentation/devicetree/bindings/mfd/cros-ec.txt
index e0e59c5..5f229c5 100644
--- a/Documentation/devicetree/bindings/mfd/cros-ec.txt
+++ b/Documentation/devicetree/bindings/mfd/cros-ec.txt
@@ -4,7 +4,7 @@ Google's ChromeOS EC is a Cortex-M device which talks to the AP and
 implements various function such as keyboard and battery charging.
 
 The EC can be connect through various means (I2C, SPI, LPC) and the
-compatible string used depends on the inteface. Each connection method has
+compatible string used depends on the interface. Each connection method has
 its own driver which connects to the top level interface-agnostic EC driver.
 Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to
 the top-level driver.
diff --git a/Documentation/devicetree/bindings/mfd/palmas.txt b/Documentation/devicetree/bindings/mfd/palmas.txt
index 892537d..e5f0f83 100644
--- a/Documentation/devicetree/bindings/mfd/palmas.txt
+++ b/Documentation/devicetree/bindings/mfd/palmas.txt
@@ -5,6 +5,7 @@ twl6035 (palmas)
 twl6037 (palmas)
 tps65913 (palmas)
 tps65914 (palmas)
+tps659038
 
 Required properties:
 - compatible : Should be from the list
@@ -14,6 +15,7 @@ Required properties:
   ti,tps65913
   ti,tps65914
   ti,tps80036
+  ti,tps659038
 and also the generic series names
   ti,palmas
 - interrupt-controller : palmas has its own internal IRQs
diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt
new file mode 100644
index 0000000..36e051b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -0,0 +1,89 @@
+
+* Samsung S2MPS11 Voltage and Current Regulator
+
+The Samsung S2MP211 is a multi-function device which includes voltage and
+current regulators, RTC, charger controller and other sub-blocks. It is
+interfaced to the host controller using a I2C interface. Each sub-block is
+addressed by the host system using different I2C slave address.
+
+Required properties:
+- compatible: Should be "samsung,s2mps11-pmic".
+- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from s2mps11 are delivered to.
+- interrupts: Interrupt specifiers for interrupt sources.
+
+Optional nodes:
+- regulators: The regulators of s2mps11 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+	regulator_name {
+		[standard regulator constraints....];
+	};
+
+ regulator-ramp-delay for BUCKs = [6250/12500/25000(default)/50000] uV/us
+
+ BUCK[2/3/4/6] supports disabling ramp delay on hardware, so explictly
+ regulator-ramp-delay = <0> can be used for them to disable ramp delay.
+ In absence of regulator-ramp-delay property, default ramp delay will be used.
+
+NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
+for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
+Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
+BUCK[3, 4], and BUCK[7, 8, 10]
+
+The regulator constraints inside the regulator nodes use the standard regulator
+bindings which are documented elsewhere.
+
+The following are the names of the regulators that the s2mps11 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of s2mps11.
+
+	- LDOn
+		  - valid values for n are 1 to 28
+		  - Example: LDO0, LD01, LDO28
+	- BUCKn
+		  - valid values for n are 1 to 9.
+		  - Example: BUCK1, BUCK2, BUCK9
+
+Example:
+
+	s2mps11_pmic@66 {
+		compatible = "samsung,s2mps11-pmic";
+		reg = <0x66>;
+
+		regulators {
+			ldo1_reg: LDO1 {
+				regulator-name = "VDD_ABB_3.3V";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "VDD_ALIVE_1.1V";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-always-on;
+			};
+
+			buck1_reg: BUCK1 {
+				regulator-name = "vdd_mif";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-ramp-delay = <50000>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
index 38e51ad..a45ae08 100644
--- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt
+++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -7,9 +7,30 @@ Required properties:
 - reg: Should contain SSC registers location and length
 - interrupts: Should contain SSC interrupt
 
-Example:
+
+Required properties for devices compatible with "atmel,at91sam9g45-ssc":
+- dmas: DMA specifier, consisting of a phandle to DMA controller node,
+  the memory interface and SSC DMA channel ID (for tx and rx).
+  See Documentation/devicetree/bindings/dma/atmel-dma.txt for details.
+- dma-names: Must be "tx", "rx".
+
+Examples:
+- PDC transfer:
 ssc0: ssc@fffbc000 {
 	compatible = "atmel,at91rm9200-ssc";
 	reg = <0xfffbc000 0x4000>;
 	interrupts = <14 4 5>;
 };
+
+- DMA transfer:
+ssc0: ssc@f0010000 {
+      compatible = "atmel,at91sam9g45-ssc";
+      reg = <0xf0010000 0x4000>;
+      interrupts = <28 4 5>;
+      dmas = <&dma0 1 13>,
+	     <&dma0 1 14>;
+      dma-names = "tx", "rx";
+      pinctrl-names = "default";
+      pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+      status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index d555421..c472883 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -15,6 +15,7 @@ Required properties:
   optional gpio and may be set to 0 if not present.
 
 Optional properties:
+- atmel,nand-has-dma : boolean to support dma transfer for nand read/write.
 - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
   Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
   "soft_bch".
@@ -29,6 +30,14 @@ Optional properties:
   sector size 1024.
 - nand-bus-width : 8 or 16 bus width if not present 8
 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
+- Nand Flash Controller(NFC) is a slave driver under Atmel nand flash
+  - Required properties:
+    - compatible : "atmel,sama5d3-nfc".
+    - reg : should specify the address and size used for NFC command registers,
+            NFC registers and NFC Sram. NFC Sram address and size can be absent
+            if don't want to use it.
+  - Optional properties:
+    - atmel,write-by-sram: boolean to enable NFC write by sram.
 
 Examples:
 nand0: nand@40000000,0 {
@@ -77,3 +86,22 @@ nand0: nand@40000000 {
 		...
 	};
 };
+
+/* for NFC supported chips */
+nand0: nand@40000000 {
+	compatible = "atmel,at91rm9200-nand";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+        ...
+        nfc@70000000 {
+		compatible = "atmel,sama5d3-nfc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <
+			0x70000000 0x10000000	/* NFC Command Registers */
+			0xffffc000 0x00000070	/* NFC HSMC regs */
+			0x00200000 0x00100000	/* NFC SRAM banks */
+		>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
index 2240ac0..ec42935 100644
--- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
@@ -1,4 +1,5 @@
-* FSMC NAND
+ST Microelectronics Flexible Static Memory Controller (FSMC)
+NAND Interface
 
 Required properties:
 - compatible : "st,spear600-fsmc-nand", "stericsson,fsmc-nand"
@@ -9,6 +10,26 @@ Optional properties:
 - bank-width : Width (in bytes) of the device.  If not present, the width
   defaults to 1 byte
 - nand-skip-bbtscan: Indicates the the BBT scanning should be skipped
+- timings: array of 6 bytes for NAND timings. The meanings of these bytes
+  are:
+  byte 0 TCLR  : CLE to RE delay in number of AHB clock cycles, only 4 bits
+                 are valid. Zero means one clockcycle, 15 means 16 clock
+                 cycles.
+  byte 1 TAR   : ALE to RE delay, 4 bits are valid. Same format as TCLR.
+  byte 2 THIZ  : number of HCLK clock cycles during which the data bus is
+                 kept in Hi-Z (tristate) after the start of a write access.
+                 Only valid for write transactions. Zero means zero cycles,
+                 255 means 255 cycles.
+  byte 3 THOLD : number of HCLK clock cycles to hold the address (and data
+                 when writing) after the command deassertation. Zero means
+                 one cycle, 255 means 256 cycles.
+  byte 4 TWAIT : number of HCLK clock cycles to assert the command to the
+                 NAND flash in response to SMWAITn. Zero means 1 cycle,
+                 255 means 256 cycles.
+  byte 5 TSET  : number of HCLK clock cycles to assert the address before the
+                 command is asserted. Zero means one cycle, 255 means 256
+                 cycles.
+- bank: default NAND bank to use (0-3 are valid, 0 is the default).
 
 Example:
 
@@ -24,6 +45,8 @@ Example:
 
 		bank-width = <1>;
 		nand-skip-bbtscan;
+		timings = /bits/ 8 <0 0 0 2 3 0>;
+		bank = <1>;
 
 		partition@0 {
 			...
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
index 9315ac9..8e5557d 100644
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ b/Documentation/devicetree/bindings/mtd/partition.txt
@@ -4,6 +4,7 @@ Partitions can be represented by sub-nodes of an mtd device. This can be used
 on platforms which have strong conventions about which portions of a flash are
 used for what purposes, but which don't use an on-flash partition table such
 as RedBoot.
+NOTE: if the sub-node has a compatible string, then it is not a partition.
 
 #address-cells & #size-cells must both be present in the mtd device. There are
 two valid values for both:
diff --git a/Documentation/devicetree/bindings/net/can/sja1000.txt b/Documentation/devicetree/bindings/net/can/sja1000.txt
index c2dbcec..f2105a4 100644
--- a/Documentation/devicetree/bindings/net/can/sja1000.txt
+++ b/Documentation/devicetree/bindings/net/can/sja1000.txt
@@ -37,7 +37,7 @@ Optional properties:
 	If not specified or if the specified value is 0, the CLKOUT pin
 	will be disabled.
 
-- nxp,no-comparator-bypass : Allows to disable the CAN input comperator.
+- nxp,no-comparator-bypass : Allows to disable the CAN input comparator.
 
 For further information, please have a look to the SJA1000 data sheet.
 
diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index f8d4058..638673a 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -1,6 +1,7 @@
 * Marvell EBU PCIe interfaces
 
 Mandatory properties:
+
 - compatible: one of the following values:
     marvell,armada-370-pcie
     marvell,armada-xp-pcie
@@ -10,11 +11,51 @@ Mandatory properties:
 - #interrupt-cells, set to <1>
 - bus-range: PCI bus numbers covered
 - device_type, set to "pci"
-- ranges: ranges for the PCI memory and I/O regions, as well as the
-  MMIO registers to control the PCIe interfaces.
+- ranges: ranges describing the MMIO registers to control the PCIe
+  interfaces, and ranges describing the MBus windows needed to access
+  the memory and I/O regions of each PCIe interface.
+- msi-parent: Link to the hardware entity that serves as the Message
+  Signaled Interrupt controller for this PCI controller.
+
+The ranges describing the MMIO registers have the following layout:
+
+    0x82000000 0 r MBUS_ID(0xf0, 0x01) r 0 s
+
+where:
+
+  * r is a 32-bits value that gives the offset of the MMIO
+  registers of this PCIe interface, from the base of the internal
+  registers.
+
+  * s is a 32-bits value that give the size of this MMIO
+  registers area. This range entry translates the '0x82000000 0 r' PCI
+  address into the 'MBUS_ID(0xf0, 0x01) r' CPU address, which is part
+  of the internal register window (as identified by MBUS_ID(0xf0,
+  0x01)).
+
+The ranges describing the MBus windows have the following layout:
+
+    0x8t000000 s 0     MBUS_ID(w, a) 0 1 0
+
+where:
+
+   * t is the type of the MBus window (as defined by the standard PCI DT
+   bindings), 1 for I/O and 2 for memory.
 
-In addition, the Device Tree node must have sub-nodes describing each
+   * s is the PCI slot that corresponds to this PCIe interface
+
+   * w is the 'target ID' value for the MBus window
+
+   * a the 'attribute' value for the MBus window.
+
+Since the location and size of the different MBus windows is not fixed in
+hardware, and only determined in runtime, those ranges cover the full first
+4 GB of the physical address space, and do not translate into a valid CPU
+address.
+
+In addition, the device tree node must have sub-nodes describing each
 PCIe interface, having the following mandatory properties:
+
 - reg: used only for interrupt mapping, so only the first four bytes
   are used to refer to the correct bus number and device number.
 - assigned-addresses: reference to the MMIO registers used to control
@@ -26,7 +67,8 @@ PCIe interface, having the following mandatory properties:
 - #address-cells, set to <3>
 - #size-cells, set to <2>
 - #interrupt-cells, set to <1>
-- ranges, empty property.
+- ranges, translating the MBus windows ranges of the parent node into
+  standard PCI addresses.
 - interrupt-map-mask and interrupt-map, standard PCI properties to
   define the mapping of the PCIe interface to interrupt numbers.
 
@@ -46,28 +88,52 @@ pcie-controller {
 	#size-cells = <2>;
 
 	bus-range = <0x00 0xff>;
+	msi-parent = <&mpic>;
 
-	ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000   /* Port 0.0 registers */
-		  0x82000000 0 0xd0042000 0xd0042000 0 0x00002000   /* Port 2.0 registers */
-		  0x82000000 0 0xd0044000 0xd0044000 0 0x00002000   /* Port 0.1 registers */
-		  0x82000000 0 0xd0048000 0xd0048000 0 0x00002000   /* Port 0.2 registers */
-		  0x82000000 0 0xd004c000 0xd004c000 0 0x00002000   /* Port 0.3 registers */
-		  0x82000000 0 0xd0080000 0xd0080000 0 0x00002000   /* Port 1.0 registers */
-		  0x82000000 0 0xd0082000 0xd0082000 0 0x00002000   /* Port 3.0 registers */
-		  0x82000000 0 0xd0084000 0xd0084000 0 0x00002000   /* Port 1.1 registers */
-		  0x82000000 0 0xd0088000 0xd0088000 0 0x00002000   /* Port 1.2 registers */
-		  0x82000000 0 0xd008c000 0xd008c000 0 0x00002000   /* Port 1.3 registers */
-		  0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-		  0x81000000 0 0	  0xe8000000 0 0x00100000>; /* downstream I/O */
+	ranges =
+	       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000	/* Port 0.0 registers */
+		0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000	/* Port 2.0 registers */
+		0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000	/* Port 0.1 registers */
+		0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000	/* Port 0.2 registers */
+		0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000	/* Port 0.3 registers */
+		0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000	/* Port 1.0 registers */
+		0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000	/* Port 3.0 registers */
+		0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000	/* Port 1.1 registers */
+		0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000	/* Port 1.2 registers */
+		0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000	/* Port 1.3 registers */
+		0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+		0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
+		0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
+		0x81000000 0x2 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 0.1 IO  */
+		0x82000000 0x3 0     MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 0.2 MEM */
+		0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
+		0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
+		0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
+
+		0x82000000 0x5 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+		0x81000000 0x5 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+		0x82000000 0x6 0     MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
+		0x81000000 0x6 0     MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO  */
+		0x82000000 0x7 0     MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
+		0x81000000 0x7 0     MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO  */
+		0x82000000 0x8 0     MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
+		0x81000000 0x8 0     MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO  */
+
+		0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+		0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */
+
+		0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
+		0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
 
 	pcie@1,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>;
+		assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
 		reg = <0x0800 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+			  0x81000000 0 0 0x81000000 0x1 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 58>;
 		marvell,pcie-port = <0>;
@@ -78,12 +144,13 @@ pcie-controller {
 
 	pcie@2,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82001000 0 0xd0044000 0 0x2000>;
+		assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
 		reg = <0x1000 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+			  0x81000000 0 0 0x81000000 0x2 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 59>;
 		marvell,pcie-port = <0>;
@@ -94,12 +161,13 @@ pcie-controller {
 
 	pcie@3,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82001800 0 0xd0048000 0 0x2000>;
+		assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
 		reg = <0x1800 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+			  0x81000000 0 0 0x81000000 0x3 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 60>;
 		marvell,pcie-port = <0>;
@@ -110,12 +178,13 @@ pcie-controller {
 
 	pcie@4,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82002000 0 0xd004c000 0 0x2000>;
+		assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
 		reg = <0x2000 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+			  0x81000000 0 0 0x81000000 0x4 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 61>;
 		marvell,pcie-port = <0>;
@@ -126,12 +195,13 @@ pcie-controller {
 
 	pcie@5,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82002800 0 0xd0080000 0 0x2000>;
+		assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
 		reg = <0x2800 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+			  0x81000000 0 0 0x81000000 0x5 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 62>;
 		marvell,pcie-port = <1>;
@@ -142,12 +212,13 @@ pcie-controller {
 
 	pcie@6,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82003000 0 0xd0084000 0 0x2000>;
+		assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
 		reg = <0x3000 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
+			  0x81000000 0 0 0x81000000 0x6 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 63>;
 		marvell,pcie-port = <1>;
@@ -158,12 +229,13 @@ pcie-controller {
 
 	pcie@7,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82003800 0 0xd0088000 0 0x2000>;
+		assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
 		reg = <0x3800 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
+			  0x81000000 0 0 0x81000000 0x7 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 64>;
 		marvell,pcie-port = <1>;
@@ -174,12 +246,13 @@ pcie-controller {
 
 	pcie@8,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82004000 0 0xd008c000 0 0x2000>;
+		assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
 		reg = <0x4000 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
+			  0x81000000 0 0 0x81000000 0x8 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 65>;
 		marvell,pcie-port = <1>;
@@ -187,14 +260,16 @@ pcie-controller {
 		clocks = <&gateclk 12>;
 		status = "disabled";
 	};
+
 	pcie@9,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82004800 0 0xd0042000 0 0x2000>;
+		assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
 		reg = <0x4800 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+			  0x81000000 0 0 0x81000000 0x9 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 99>;
 		marvell,pcie-port = <2>;
@@ -205,12 +280,13 @@ pcie-controller {
 
 	pcie@10,0 {
 		device_type = "pci";
-		assigned-addresses = <0x82005000 0 0xd0082000 0 0x2000>;
+		assigned-addresses = <0x82005000 0 0x82000 0 0x2000>;
 		reg = <0x5000 0 0 0 0>;
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
-		ranges;
+		ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
+			  0x81000000 0 0 0x81000000 0xa 0 1 0>;
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0 0 0 0 &mpic 103>;
 		marvell,pcie-port = <3>;
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
index 648d60e..7ccae49 100644
--- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
@@ -37,7 +37,7 @@ Bank: 3 (A, B and C)
   0xffffffff 0x7fff3ccf  /* pioB */
   0xffffffff 0x007fffff  /* pioC */
 
-For each peripheral/bank we will descibe in a u32 if a pin can can be
+For each peripheral/bank we will descibe in a u32 if a pin can be
 configured in it by putting 1 to the pin bit (1 << pin)
 
 Let's take the pioA on peripheral B
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt
index e204d00..fb70856 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt
@@ -80,6 +80,17 @@ Valid values for pin and group names are:
     dbg, sdio3, spi, uaa, uab, uart2, uart3, sdio1, ddc, gma, gme, gmf, gmg,
     gmh, owr, uda.
 
+Valid values for nvidia,functions are:
+
+  blink, cec, cldvfs, clk12, cpu, dap, dap1, dap2, dev3, displaya,
+  displaya_alt, displayb, dtv, emc_dll, extperiph1, extperiph2,
+  extperiph3, gmi, gmi_alt, hda, hsi, i2c1, i2c2, i2c3, i2c4, i2cpwr,
+  i2s0, i2s1, i2s2, i2s3, i2s4, irda, kbc, nand, nand_alt, owr, pmi,
+  pwm0, pwm1, pwm2, pwm3, pwron, reset_out_n, rsvd1, rsvd2, rsvd3,
+  rsvd4, sdmmc1, sdmmc2, sdmmc3, sdmmc4, soc, spdif, spi1, spi2, spi3,
+  spi4, spi5, spi6, sysclk, trace, uarta, uartb, uartc, uartd, ulpi,
+  usb, vgp1, vgp2, vgp3, vgp4, vgp5, vgp6, vi, vi_alt1, vi_alt3
+
 Example:
 
 	pinmux: pinmux {
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
index 683fde9..61e73cd 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
@@ -103,6 +103,17 @@ Valid values for pin and group names are:
     drive_gma, drive_gmb, drive_gmc, drive_gmd, drive_gme, drive_owr,
     drive_uda.
 
+Valid values for nvidia,functions are:
+
+  ahb_clk, apb_clk, audio_sync, crt, dap1, dap2, dap3, dap4, dap5,
+  displaya, displayb, emc_test0_dll, emc_test1_dll, gmi, gmi_int,
+  hdmi, i2cp, i2c1, i2c2, i2c3, ide, irda, kbc, mio, mipi_hs, nand,
+  osc, owr, pcie, plla_out, pllc_out1, pllm_out1, pllp_out2, pllp_out3,
+  pllp_out4, pwm, pwr_intr, pwr_on, rsvd1, rsvd2, rsvd3, rsvd4, rtck,
+  sdio1, sdio2, sdio3, sdio4, sflash, spdif, spi1, spi2, spi2_alt,
+  spi3, spi4, trace, twc, uarta, uartb, uartc, uartd, uarte, ulpi,
+  vi, vi_sensor_clk, xio
+
 Example:
 
 	pinctrl@70000000 {
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
index 6f426ed..0e6354c 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
@@ -91,6 +91,18 @@ Valid values for pin and group names are:
     gmh, gpv, lcd1, lcd2, owr, sdio1, sdio2, sdio3, spi, uaa, uab, uart2,
     uart3, uda, vi1.
 
+Valid values for nvidia,functions are:
+
+  blink, cec, clk_12m_out, clk_32k_in, core_pwr_req, cpu_pwr_req, crt,
+  dap, ddr, dev3, displaya, displayb, dtv, extperiph1, extperiph2,
+  extperiph3, gmi, gmi_alt, hda, hdcp, hdmi, hsi, i2c1, i2c2, i2c3,
+  i2c4, i2cpwr, i2s0, i2s1, i2s2, i2s3, i2s4, invalid, kbc, mio, nand,
+  nand_alt, owr, pcie, pwm0, pwm1, pwm2, pwm3, pwr_int_n, rsvd1, rsvd2,
+  rsvd3, rsvd4, rtck, sata, sdmmc1, sdmmc2, sdmmc3, sdmmc4, spdif, spi1,
+  spi2, spi2_alt, spi3, spi4, spi5, spi6, sysclk, test, trace, uarta,
+  uartb, uartc, uartd, uarte, ulpi, vgp1, vgp2, vgp3, vgp4, vgp5, vgp6,
+  vi, vi_alt1, vi_alt2, vi_alt3
+
 Example:
 
 	pinctrl@70000000 {
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
index aeb3c99..1958ca9 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -127,21 +127,20 @@ whether there is any interaction between the child and intermediate parent
 nodes, is again defined entirely by the binding for the individual pin
 controller device.
 
-== Using generic pinconfig options ==
+== Generic pin configuration node content ==
 
-Generic pinconfig parameters can be used by defining a separate node containing
-the applicable parameters (and optional values), like:
+Many data items that are represented in a pin configuration node are common
+and generic. Pin control bindings should use the properties defined below
+where they are applicable; not all of these properties are relevant or useful
+for all hardware or binding structures. Each individual binding document
+should state which of these generic properties, if any, are used, and the
+structure of the DT nodes that contain these properties.
 
-pcfg_pull_up: pcfg_pull_up {
-	bias-pull-up;
-	drive-strength = <20>;
-};
-
-This node should then be referenced in the appropriate pinctrl node as a phandle
-and parsed in the driver using the pinconf_generic_parse_dt_config function.
-
-Supported configuration parameters are:
+Supported generic properties are:
 
+pins			- the list of pins that properties in the node
+			  apply to
+function		- the mux function to select
 bias-disable		- disable any pin bias
 bias-high-impedance	- high impedance mode ("third-state", "floating")
 bias-bus-hold		- latch weakly
@@ -160,7 +159,21 @@ low-power-disable	- disable low power mode
 output-low		- set the pin to output mode with low level
 output-high		- set the pin to output mode with high level
 
-Arguments for parameters:
+Some of the generic properties take arguments. For those that do, the
+arguments are described below.
+
+- pins takes a list of pin names or IDs as a required argument. The specific
+  binding for the hardware defines:
+  - Whether the entries are integers or strings, and their meaning.
+
+- function takes a list of function names/IDs as a required argument. The
+  specific binding for the hardware defines:
+  - Whether the entries are integers or strings, and their meaning.
+  - Whether only a single entry is allowed (which is applied to all entries
+    in the pins property), or whether there may alternatively be one entry per
+    entry in the pins property, in which case the list lengths must match, and
+    for each list index i, the function at list index i is applied to the pin
+    at list index i.
 
 - bias-pull-up, -down and -pin-default take as optional argument on hardware
   supporting it the pull strength in Ohm. bias-disable will disable the pull.
@@ -170,7 +183,5 @@ Arguments for parameters:
 - input-debounce takes the debounce time in usec as argument
   or 0 to disable debouncing
 
-All parameters not listed here, do not take an argument.
-
 More in-depth documentation on these parameters can be found in
 <include/linux/pinctrl/pinconfig-generic.h>
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt b/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt
deleted file mode 100644
index 5ff76c9..0000000
--- a/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-Freescale Synchronous Serial Interface
-
-The SSI is a serial device that communicates with audio codecs.  It can
-be programmed in AC97, I2S, left-justified, or right-justified modes.
-
-Required properties:
-- compatible:       Compatible list, contains "fsl,ssi".
-- cell-index:       The SSI, <0> = SSI1, <1> = SSI2, and so on.
-- reg:              Offset and length of the register set for the device.
-- interrupts:       <a b> where a is the interrupt number and b is a
-                    field that represents an encoding of the sense and
-                    level information for the interrupt.  This should be
-                    encoded based on the information in section 2)
-                    depending on the type of interrupt controller you
-                    have.
-- interrupt-parent: The phandle for the interrupt controller that
-                    services interrupts for this device.
-- fsl,mode:         The operating mode for the SSI interface.
-                    "i2s-slave" - I2S mode, SSI is clock slave
-                    "i2s-master" - I2S mode, SSI is clock master
-                    "lj-slave" - left-justified mode, SSI is clock slave
-                    "lj-master" - l.j. mode, SSI is clock master
-                    "rj-slave" - right-justified mode, SSI is clock slave
-                    "rj-master" - r.j., SSI is clock master
-                    "ac97-slave" - AC97 mode, SSI is clock slave
-                    "ac97-master" - AC97 mode, SSI is clock master
-- fsl,playback-dma: Phandle to a node for the DMA channel to use for
-                    playback of audio.  This is typically dictated by SOC
-                    design.  See the notes below.
-- fsl,capture-dma:  Phandle to a node for the DMA channel to use for
-                    capture (recording) of audio.  This is typically dictated
-                    by SOC design.  See the notes below.
-- fsl,fifo-depth:   The number of elements in the transmit and receive FIFOs.
-                    This number is the maximum allowed value for SFCSR[TFWM0].
-- fsl,ssi-asynchronous:
-                    If specified, the SSI is to be programmed in asynchronous
-                    mode.  In this mode, pins SRCK, STCK, SRFS, and STFS must
-                    all be connected to valid signals.  In synchronous mode,
-                    SRCK and SRFS are ignored.  Asynchronous mode allows
-                    playback and capture to use different sample sizes and
-                    sample rates.  Some drivers may require that SRCK and STCK
-                    be connected together, and SRFS and STFS be connected
-                    together.  This would still allow different sample sizes,
-                    but not different sample rates.
-
-Optional properties:
-- codec-handle:     Phandle to a 'codec' node that defines an audio
-                    codec connected to this SSI.  This node is typically
-                    a child of an I2C or other control node.
-
-Child 'codec' node required properties:
-- compatible:       Compatible list, contains the name of the codec
-
-Child 'codec' node optional properties:
-- clock-frequency:  The frequency of the input clock, which typically comes
-                    from an on-board dedicated oscillator.
-
-Notes on fsl,playback-dma and fsl,capture-dma:
-
-On SOCs that have an SSI, specific DMA channels are hard-wired for playback
-and capture.  On the MPC8610, for example, SSI1 must use DMA channel 0 for
-playback and DMA channel 1 for capture.  SSI2 must use DMA channel 2 for
-playback and DMA channel 3 for capture.  The developer can choose which
-DMA controller to use, but the channels themselves are hard-wired.  The
-purpose of these two properties is to represent this hardware design.
-
-The device tree nodes for the DMA channels that are referenced by
-"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with
-"fsl,ssi-dma-channel".  The SOC-specific compatible string (e.g.
-"fsl,mpc8610-dma-channel") can remain.  If these nodes are left as
-"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA
-drivers (fsldma) will attempt to use them, and it will conflict with the
-sound drivers.
diff --git a/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt b/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt
index de0eaed..8031148 100644
--- a/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/atmel-tcb-pwm.txt
@@ -2,11 +2,9 @@ Atmel TCB PWM controller
 
 Required properties:
 - compatible: should be "atmel,tcb-pwm"
-- #pwm-cells: Should be 3.  The first cell specifies the per-chip index
-  of the PWM to use, the second cell is the period in nanoseconds and
-  bit 0 in the third cell is used to encode the polarity of PWM output.
-  Set bit 0 of the third cell in PWM specifier to 1 for inverse polarity &
-  set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+  the cells format. The only third cell flag supported by this binding is
+  PWM_POLARITY_INVERTED.
 - tc-block: The Timer Counter block to use as a PWM chip.
 
 Example:
diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.txt b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
index 8522bfb..b50d7a6d 100644
--- a/Documentation/devicetree/bindings/pwm/imx-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
@@ -3,8 +3,8 @@ Freescale i.MX PWM controller
 Required properties:
 - compatible: should be "fsl,<soc>-pwm"
 - reg: physical base address and length of the controller's registers
-- #pwm-cells: should be 2.  The first cell specifies the per-chip index
-  of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+  the cells format.
 - interrupts: The interrupt for the pwm controller
 
 Example:
diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
index 9e3f8f1..96cdde5 100644
--- a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
@@ -3,8 +3,8 @@ Freescale MXS PWM controller
 Required properties:
 - compatible: should be "fsl,imx23-pwm"
 - reg: physical base address and length of the controller's registers
-- #pwm-cells: should be 2.  The first cell specifies the per-chip index
-  of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+  the cells format.
 - fsl,pwm-number: the number of PWM devices
 
 Example:
diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
index 01438ec..c3fc57a 100644
--- a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
@@ -5,9 +5,8 @@ Required properties:
   - "nvidia,tegra20-pwm"
   - "nvidia,tegra30-pwm"
 - reg: physical base address and length of the controller's registers
-- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The
-  first cell specifies the per-chip index of the PWM to use and the second
-  cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+  the cells format.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt b/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt
index 1e3dfe7..f84ec9d 100644
--- a/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt
@@ -3,8 +3,8 @@ NXP PCA9685 16-channel 12-bit PWM LED controller
 
 Required properties:
   - compatible: "nxp,pca9685-pwm"
-  - #pwm-cells: should be 2. The first cell specifies the per-chip index
-    of the PWM to use and the second cell is the period in nanoseconds.
+  - #pwm-cells: Should be 2. See pwm.txt in this directory for a description of
+    the cells format.
     The index 16 is the ALLCALL channel, that sets all PWM channels at the same
     time.
 
diff --git a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
index ac67c68..4caa1a7 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
@@ -19,13 +19,9 @@ Required properties:
 - reg: base address and size of register area
 - interrupts: list of timer interrupts (one interrupt per timer, starting at
   timer 0)
-- #pwm-cells: number of cells used for PWM specifier - must be 3
-   the specifier format is as follows:
-     - phandle to PWM controller node
-     - index of PWM channel (from 0 to 4)
-     - PWM signal period in nanoseconds
-     - bitmask of optional PWM flags:
-        0x1 - invert PWM signal
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+  the cells format. The only third cell flag supported by this binding is
+  PWM_POLARITY_INVERTED.
 
 Optional properties:
 - samsung,pwm-outputs: list of PWM channels used as PWM outputs on particular
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
index 681afad..fb81179 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -4,11 +4,9 @@ Required properties:
 - compatible: Must be "ti,<soc>-ecap".
   for am33xx - compatible = "ti,am33xx-ecap";
   for da850  - compatible = "ti,da850-ecap", "ti,am33xx-ecap";
-- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
-  First cell specifies the per-chip index of the PWM to use, the second
-  cell is the period in nanoseconds and bit 0 in the third cell is used to
-  encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
-  to 1 for inverse polarity & set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+  the cells format. The PWM channel index ranges from 0 to 4. The only third
+  cell flag supported by this binding is PWM_POLARITY_INVERTED.
 - reg: physical base address and size of the registers map.
 
 Optional properties:
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
index 337c6fc..9c100b2 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -4,11 +4,9 @@ Required properties:
 - compatible: Must be "ti,<soc>-ehrpwm".
   for am33xx - compatible = "ti,am33xx-ehrpwm";
   for da850  - compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
-- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
-  First cell specifies the per-chip index of the PWM to use, the second
-  cell is the period in nanoseconds and bit 0 in the third cell is used to
-  encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
-  to 1 for inverse polarity & set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+  the cells format. The only third cell flag supported by this binding is
+  PWM_POLARITY_INVERTED.
 - reg: physical base address and size of the registers map.
 
 Optional properties:
diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt
index 06e6724..8556263 100644
--- a/Documentation/devicetree/bindings/pwm/pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm.txt
@@ -43,13 +43,14 @@ because the name "backlight" would be used as fallback anyway.
 pwm-specifier typically encodes the chip-relative PWM number and the PWM
 period in nanoseconds.
 
-Optionally, the pwm-specifier can encode a number of flags in a third cell:
-- bit 0: PWM signal polarity (0: normal polarity, 1: inverse polarity)
+Optionally, the pwm-specifier can encode a number of flags (defined in
+<dt-bindings/pwm/pwm.h>) in a third cell:
+- PWM_POLARITY_INVERTED: invert the PWM signal polarity
 
 Example with optional PWM specifier for inverse polarity
 
 	bl: backlight {
-		pwms = <&pwm 0 5000000 1>;
+		pwms = <&pwm 0 5000000 PWM_POLARITY_INVERTED>;
 		pwm-names = "backlight";
 	};
 
diff --git a/Documentation/devicetree/bindings/pwm/spear-pwm.txt b/Documentation/devicetree/bindings/pwm/spear-pwm.txt
index 3ac779d..b486de2 100644
--- a/Documentation/devicetree/bindings/pwm/spear-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/spear-pwm.txt
@@ -5,9 +5,8 @@ Required properties:
   - "st,spear320-pwm"
   - "st,spear1340-pwm"
 - reg: physical base address and length of the controller's registers
-- #pwm-cells: number of cells used to specify PWM which is fixed to 2 on
-  SPEAr. The first cell specifies the per-chip index of the PWM to use and
-  the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+  the cells format.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt b/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt
index 2943ee5..4e32bee 100644
--- a/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt
@@ -6,8 +6,8 @@ On TWL6030 series: PWM0 and PWM1
 
 Required properties:
 - compatible: "ti,twl4030-pwm" or "ti,twl6030-pwm"
-- #pwm-cells: should be 2.  The first cell specifies the per-chip index
-  of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+  the cells format.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt b/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt
index cb64f3a..9f4b460 100644
--- a/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt
+++ b/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt
@@ -6,8 +6,8 @@ On TWL6030 series: LED PWM (mainly used as charging indicator LED)
 
 Required properties:
 - compatible: "ti,twl4030-pwmled" or "ti,twl6030-pwmled"
-- #pwm-cells: should be 2.  The first cell specifies the per-chip index
-  of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+  the cells format.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt
index d21d82d..a76390e 100644
--- a/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt
@@ -3,11 +3,9 @@ VIA/Wondermedia VT8500/WM8xxx series SoC PWM controller
 Required properties:
 - compatible: should be "via,vt8500-pwm"
 - reg: physical base address and length of the controller's registers
-- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
-  First cell specifies the per-chip index of the PWM to use, the second
-  cell is the period in nanoseconds and bit 0 in the third cell is used to
-  encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
-  to 1 for inverse polarity & set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+  the cells format. The only third cell flag supported by this binding is
+  PWM_POLARITY_INVERTED.
 - clocks: phandle to the PWM source clock
 
 Example:
diff --git a/Documentation/devicetree/bindings/regulator/88pm800.txt b/Documentation/devicetree/bindings/regulator/88pm800.txt
new file mode 100644
index 0000000..e8a54c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/88pm800.txt
@@ -0,0 +1,38 @@
+Marvell 88PM800 regulator
+
+Required properties:
+- compatible: "marvell,88pm800"
+- reg: I2C slave address
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+The valid names for regulators are:
+
+  buck1, buck2, buck3, buck4, buck5, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7,
+  ldo8, ldo9, ldo10, ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, ldo19
+
+Example:
+
+	pmic: 88pm800@31 {
+		compatible = "marvell,88pm800";
+		reg = <0x31>;
+
+		regulators {
+			buck1 {
+			        regulator-min-microvolt = <600000>;
+			        regulator-max-microvolt = <3950000>;
+			        regulator-boot-on;
+			        regulator-always-on;
+			};
+			ldo1 {
+			        regulator-min-microvolt = <600000>;
+			        regulator-max-microvolt = <15000000>;
+			        regulator-boot-on;
+			        regulator-always-on;
+			};
+...
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/max8660.txt b/Documentation/devicetree/bindings/regulator/max8660.txt
new file mode 100644
index 0000000..8ba994d
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8660.txt
@@ -0,0 +1,47 @@
+Maxim MAX8660 voltage regulator
+
+Required properties:
+- compatible: must be one of "maxim,max8660", "maxim,max8661"
+- reg: I2C slave address, usually 0x34
+- any required generic properties defined in regulator.txt
+
+Example:
+
+	i2c_master {
+		max8660@34 {
+			compatible = "maxim,max8660";
+			reg = <0x34>;
+
+			regulators {
+				regulator@0 {
+					regulator-compatible= "V3(DCDC)";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@1 {
+					regulator-compatible= "V4(DCDC)";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@2 {
+					regulator-compatible= "V5(LDO)";
+					regulator-min-microvolt = <1700000>;
+					regulator-max-microvolt = <2000000>;
+				};
+
+				regulator@3 {
+					regulator-compatible= "V6(LDO)";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@4 {
+					regulator-compatible= "V7(LDO)";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+				};
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
index d5a3086..30b0581 100644
--- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
+++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
@@ -31,9 +31,8 @@ Optional nodes:
 	       Optional sub-node properties:
 	       ti,warm-reset - maintain voltage during warm reset(boolean)
 	       ti,roof-floor - control voltage selection by pin(boolean)
-	       ti,sleep-mode - mode to adopt in pmic sleep 0 - off, 1 - auto,
+	       ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto,
 	       2 - eco, 3 - forced pwm
-	       ti,tstep - slope control 0 - Jump, 1 10mV/us, 2 5mV/us, 3 2.5mV/us
 	       ti,smps-range - OTP has the wrong range set for the hardware so override
 	       0 - low range, 1 - high range.
 
@@ -59,7 +58,6 @@ pmic {
 			ti,warm-reset;
 			ti,roof-floor;
 			ti,mode-sleep = <0>;
-			ti,tstep = <0>;
 			ti,smps-range = <1>;
 		};
 
diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt b/Documentation/devicetree/bindings/regulator/pfuze100.txt
new file mode 100644
index 0000000..fc989b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt
@@ -0,0 +1,115 @@
+PFUZE100 family of regulators
+
+Required properties:
+- compatible: "fsl,pfuze100"
+- reg: I2C slave address
+
+Required child node:
+- regulators: This is the list of child nodes that specify the regulator
+  initialization data for defined regulators. Please refer to below doc
+  Documentation/devicetree/bindings/regulator/regulator.txt.
+
+  The valid names for regulators are:
+  sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6
+
+Each regulator is defined using the standard binding for regulators.
+
+Example:
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index 48a3b8e..2bd8f09 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -12,6 +12,8 @@ Optional properties:
 - regulator-allow-bypass: allow the regulator to go into bypass mode
 - <name>-supply: phandle to the parent supply/regulator node
 - regulator-ramp-delay: ramp delay for regulator(in uV/uS)
+  For hardwares which support disabling ramp rate, it should be explicitly
+  intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt b/Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt
new file mode 100644
index 0000000..c9d3ac1
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt
@@ -0,0 +1,17 @@
+MOXA ART real-time clock
+
+Required properties:
+
+- compatible : Should be "moxa,moxart-rtc"
+- gpio-rtc-sclk : RTC sclk gpio, with zero flags
+- gpio-rtc-data : RTC data gpio, with zero flags
+- gpio-rtc-reset : RTC reset gpio, with zero flags
+
+Example:
+
+	rtc: rtc {
+		compatible = "moxa,moxart-rtc";
+		gpio-rtc-sclk = <&gpio 5 0>;
+		gpio-rtc-data = <&gpio 6 0>;
+		gpio-rtc-reset = <&gpio 7 0>;
+	};
diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
index b47aa41..5a0f02d 100644
--- a/Documentation/devicetree/bindings/rtc/rtc-omap.txt
+++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
@@ -1,7 +1,11 @@
 TI Real Time Clock
 
 Required properties:
-- compatible: "ti,da830-rtc"
+- compatible:
+	- "ti,da830-rtc"  - for RTC IP used similar to that on DA8xx SoC family.
+	- "ti,am3352-rtc" - for RTC IP used similar to that on AM335x SoC family.
+			    This RTC IP has special WAKE-EN Register to enable
+			    Wakeup generation for event Alarm.
 - reg: Address range of rtc register set
 - interrupts: rtc timer, alarm interrupts in order
 - interrupt-parent: phandle for the interrupt controller
diff --git a/Documentation/devicetree/bindings/sound/ak4554.c b/Documentation/devicetree/bindings/sound/ak4554.c
new file mode 100644
index 0000000..934fa02
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ak4554.c
@@ -0,0 +1,11 @@
+AK4554 ADC/DAC
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak4554"
+
+Example:
+
+ak4554-adc-dac {
+	compatible = "asahi-kasei,ak4554";
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt
new file mode 100644
index 0000000..0720857
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt
@@ -0,0 +1,35 @@
+* Atmel at91sam9x5ek wm8731 audio complex
+
+Required properties:
+  - compatible: "atmel,sam9x5-wm8731-audio"
+  - atmel,model: The user-visible name of this sound complex.
+  - atmel,ssc-controller: The phandle of the SSC controller
+  - atmel,audio-codec: The phandle of the WM8731 audio codec
+  - atmel,audio-routing: A list of the connections between audio components.
+    Each entry is a pair of strings, the first being the connection's sink,
+    the second being the connection's source.
+
+Available audio endpoints for the audio-routing table:
+
+Board connectors:
+ * Headphone Jack
+ * Line In Jack
+
+wm8731 pins:
+cf Documentation/devicetree/bindings/sound/wm8731.txt
+
+Example:
+sound {
+	compatible = "atmel,sam9x5-wm8731-audio";
+
+	atmel,model = "wm8731 @ AT91SAM9X5EK";
+
+	atmel,audio-routing =
+		"Headphone Jack", "RHPOUT",
+		"Headphone Jack", "LHPOUT",
+		"LLINEIN", "Line In Jack",
+		"RLINEIN", "Line In Jack";
+
+	atmel,ssc-controller = <&ssc0>;
+	atmel,audio-codec = <&wm8731>;
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-wm8904.txt b/Documentation/devicetree/bindings/sound/atmel-wm8904.txt
new file mode 100644
index 0000000..8bbe50c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-wm8904.txt
@@ -0,0 +1,55 @@
+Atmel ASoC driver with wm8904 audio codec complex
+
+Required properties:
+  - compatible: "atmel,asoc-wm8904"
+  - atmel,model: The user-visible name of this sound complex.
+  - atmel,audio-routing: A list of the connections between audio components.
+    Each entry is a pair of strings, the first being the connection's sink,
+    the second being the connection's source. Valid names for sources and
+    sinks are the WM8904's pins, and the jacks on the board:
+
+    WM8904 pins:
+
+    * IN1L
+    * IN1R
+    * IN2L
+    * IN2R
+    * IN3L
+    * IN3R
+    * HPOUTL
+    * HPOUTR
+    * LINEOUTL
+    * LINEOUTR
+    * MICBIAS
+
+    Board connectors:
+
+    * Headphone Jack
+    * Line In Jack
+    * Mic
+
+  - atmel,ssc-controller: The phandle of the SSC controller
+  - atmel,audio-codec: The phandle of the WM8904 audio codec
+
+Optional properties:
+  - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
+
+Example:
+sound {
+	compatible = "atmel,asoc-wm8904";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+	atmel,model = "wm8904 @ AT91SAM9N12EK";
+
+	atmel,audio-routing =
+		"Headphone Jack", "HPOUTL",
+		"Headphone Jack", "HPOUTR",
+		"IN2L", "Line In Jack",
+		"IN2R", "Line In Jack",
+		"Mic", "MICBIAS",
+		"IN1L", "Mic";
+
+	atmel,ssc-controller = <&ssc0>;
+	atmel,audio-codec = <&wm8904>;
+};
diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
new file mode 100644
index 0000000..088a2c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
@@ -0,0 +1,81 @@
+Freescale Synchronous Serial Interface
+
+The SSI is a serial device that communicates with audio codecs.  It can
+be programmed in AC97, I2S, left-justified, or right-justified modes.
+
+Required properties:
+- compatible:       Compatible list, contains "fsl,ssi".
+- cell-index:       The SSI, <0> = SSI1, <1> = SSI2, and so on.
+- reg:              Offset and length of the register set for the device.
+- interrupts:       <a b> where a is the interrupt number and b is a
+                    field that represents an encoding of the sense and
+                    level information for the interrupt.  This should be
+                    encoded based on the information in section 2)
+                    depending on the type of interrupt controller you
+                    have.
+- interrupt-parent: The phandle for the interrupt controller that
+                    services interrupts for this device.
+- fsl,mode:         The operating mode for the SSI interface.
+                    "i2s-slave" - I2S mode, SSI is clock slave
+                    "i2s-master" - I2S mode, SSI is clock master
+                    "lj-slave" - left-justified mode, SSI is clock slave
+                    "lj-master" - l.j. mode, SSI is clock master
+                    "rj-slave" - right-justified mode, SSI is clock slave
+                    "rj-master" - r.j., SSI is clock master
+                    "ac97-slave" - AC97 mode, SSI is clock slave
+                    "ac97-master" - AC97 mode, SSI is clock master
+- fsl,playback-dma: Phandle to a node for the DMA channel to use for
+                    playback of audio.  This is typically dictated by SOC
+                    design.  See the notes below.
+- fsl,capture-dma:  Phandle to a node for the DMA channel to use for
+                    capture (recording) of audio.  This is typically dictated
+                    by SOC design.  See the notes below.
+- fsl,fifo-depth:   The number of elements in the transmit and receive FIFOs.
+                    This number is the maximum allowed value for SFCSR[TFWM0].
+- fsl,ssi-asynchronous:
+                    If specified, the SSI is to be programmed in asynchronous
+                    mode.  In this mode, pins SRCK, STCK, SRFS, and STFS must
+                    all be connected to valid signals.  In synchronous mode,
+                    SRCK and SRFS are ignored.  Asynchronous mode allows
+                    playback and capture to use different sample sizes and
+                    sample rates.  Some drivers may require that SRCK and STCK
+                    be connected together, and SRFS and STFS be connected
+                    together.  This would still allow different sample sizes,
+                    but not different sample rates.
+
+Optional properties:
+- codec-handle:     Phandle to a 'codec' node that defines an audio
+                    codec connected to this SSI.  This node is typically
+                    a child of an I2C or other control node.
+- fsl,fiq-stream-filter: Bool property. Disabled DMA and use FIQ instead to
+		    filter the codec stream. This is necessary for some boards
+		    where an incompatible codec is connected to this SSI, e.g.
+		    on pca100 and pcm043.
+- dmas:		    Generic dma devicetree binding as described in
+		    Documentation/devicetree/bindings/dma/dma.txt.
+- dma-names:	    Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq
+		    is not defined.
+
+Child 'codec' node required properties:
+- compatible:       Compatible list, contains the name of the codec
+
+Child 'codec' node optional properties:
+- clock-frequency:  The frequency of the input clock, which typically comes
+                    from an on-board dedicated oscillator.
+
+Notes on fsl,playback-dma and fsl,capture-dma:
+
+On SOCs that have an SSI, specific DMA channels are hard-wired for playback
+and capture.  On the MPC8610, for example, SSI1 must use DMA channel 0 for
+playback and DMA channel 1 for capture.  SSI2 must use DMA channel 2 for
+playback and DMA channel 3 for capture.  The developer can choose which
+DMA controller to use, but the channels themselves are hard-wired.  The
+purpose of these two properties is to represent this hardware design.
+
+The device tree nodes for the DMA channels that are referenced by
+"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with
+"fsl,ssi-dma-channel".  The SOC-specific compatible string (e.g.
+"fsl,mpc8610-dma-channel") can remain.  If these nodes are left as
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA
+drivers (fsldma) will attempt to use them, and it will conflict with the
+sound drivers.
diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt
index 215aa98..f88a00e 100644
--- a/Documentation/devicetree/bindings/sound/imx-audmux.txt
+++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt
@@ -5,6 +5,15 @@ Required properties:
   or "fsl,imx31-audmux" for the version firstly used on i.MX31.
 - reg : Should contain AUDMUX registers location and length
 
+An initial configuration can be setup using child nodes.
+
+Required properties of optional child nodes:
+- fsl,audmux-port : Integer of the audmux port that is configured by this
+  child node.
+- fsl,port-config : List of configuration options for the specific port. For
+  imx31-audmux and above, it is a list of tuples <ptcr pdcr>. For
+  imx21-audmux it is a list of pcr values.
+
 Example:
 
 audmux@021d8000 {
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
index 3bf722d..4b44dfb 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
@@ -11,28 +11,8 @@ Required properties:
 - nvidia,audio-routing : A list of the connections between audio components.
   Each entry is a pair of strings, the first being the connection's sink,
   the second being the connection's source. Valid names for sources and
-  sinks are the WM8903's pins, and the jacks on the board:
-
-  WM8903 pins:
-
-  * IN1L
-  * IN1R
-  * IN2L
-  * IN2R
-  * IN3L
-  * IN3R
-  * DMICDAT
-  * HPOUTL
-  * HPOUTR
-  * LINEOUTL
-  * LINEOUTR
-  * LOP
-  * LON
-  * ROP
-  * RON
-  * MICBIAS
-
-  Board connectors:
+  sinks are the WM8903's pins (documented in the WM8903 binding document),
+  and the jacks on the board:
 
   * Headphone Jack
   * Int Spk
diff --git a/Documentation/devicetree/bindings/sound/pcm1792a.txt b/Documentation/devicetree/bindings/sound/pcm1792a.txt
new file mode 100644
index 0000000..970ba1e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/pcm1792a.txt
@@ -0,0 +1,18 @@
+Texas Instruments pcm1792a DT bindings
+
+This driver supports the SPI bus.
+
+Required properties:
+
+ - compatible: "ti,pcm1792a"
+
+For required properties on SPI, please consult
+Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Examples:
+
+	codec_spi: 1792a@0 {
+		compatible = "ti,pcm1792a";
+		spi-max-frequency = <600000>;
+	};
+
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm1681.txt b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt
new file mode 100644
index 0000000..4df1718
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt
@@ -0,0 +1,15 @@
+Texas Instruments PCM1681 8-channel PWM Processor
+
+Required properties:
+
+ - compatible:		Should contain "ti,pcm1681".
+ - reg:			The i2c address. Should contain <0x4c>.
+
+Examples:
+
+	i2c_bus {
+		pcm1681@4c {
+			compatible = "ti,pcm1681";
+			reg = <0x4c>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
index f47c3f5..705a6b1 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -3,7 +3,14 @@ Texas Instruments - tlv320aic3x Codec module
 The tlv320aic3x serial control bus communicates through I2C protocols
 
 Required properties:
-- compatible - "string" -  "ti,tlv320aic3x"
+
+- compatible - "string" - One of:
+    "ti,tlv320aic3x" - Generic TLV320AIC3x device
+    "ti,tlv320aic33" - TLV320AIC33
+    "ti,tlv320aic3007" - TLV320AIC3007
+    "ti,tlv320aic3106" - TLV320AIC3106
+
+
 - reg - <int> -  I2C slave address
 
 
diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt
index 15f7004..236690e 100644
--- a/Documentation/devicetree/bindings/sound/wm8731.txt
+++ b/Documentation/devicetree/bindings/sound/wm8731.txt
@@ -16,3 +16,12 @@ codec: wm8731@1a {
 	compatible = "wlf,wm8731";
 	reg = <0x1a>;
 };
+
+Available audio endpoints for an audio-routing table:
+ * LOUT: Left Channel Line Output
+ * ROUT: Right Channel Line Output
+ * LHPOUT: Left Channel Headphone Output
+ * RHPOUT: Right Channel Headphone Output
+ * LLINEIN: Left Channel Line Input
+ * RLINEIN: Right Channel Line Input
+ * MICIN: Microphone Input
diff --git a/Documentation/devicetree/bindings/sound/wm8903.txt b/Documentation/devicetree/bindings/sound/wm8903.txt
index f102cbc..94ec32c 100644
--- a/Documentation/devicetree/bindings/sound/wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/wm8903.txt
@@ -28,6 +28,25 @@ Optional properties:
     performed. If any entry has the value 0xffffffff, that GPIO's
     configuration will not be modified.
 
+Pins on the device (for linking into audio routes):
+
+  * IN1L
+  * IN1R
+  * IN2L
+  * IN2R
+  * IN3L
+  * IN3R
+  * DMICDAT
+  * HPOUTL
+  * HPOUTR
+  * LINEOUTL
+  * LINEOUTR
+  * LOP
+  * LON
+  * ROP
+  * RON
+  * MICBIAS
+
 Example:
 
 codec: wm8903@1a {
diff --git a/Documentation/devicetree/bindings/sound/wm8994.txt b/Documentation/devicetree/bindings/sound/wm8994.txt
index f2f3e80..e045e90 100644
--- a/Documentation/devicetree/bindings/sound/wm8994.txt
+++ b/Documentation/devicetree/bindings/sound/wm8994.txt
@@ -32,6 +32,10 @@ Optional properties:
     The second cell is the flags, encoded as the trigger masks from
     Documentation/devicetree/bindings/interrupts.txt
 
+  - clocks : A list of up to two phandle and clock specifier pairs
+  - clock-names : A list of clock names sorted in the same order as clocks.
+                  Valid clock names are "MCLK1" and "MCLK2".
+
   - wlf,gpio-cfg : A list of GPIO configuration register values. If absent,
     no configuration of these registers is performed. If any value is
     over 0xffff then the register will be left as default. If present 11
diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
new file mode 100644
index 0000000..77c4cfa
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
@@ -0,0 +1,17 @@
+MOXA ART timer
+
+Required properties:
+
+- compatible : Should be "moxa,moxart-timer"
+- reg : Should contain registers location and length
+- interrupts : Should contain the timer interrupt number
+- clocks : Should contain phandle for APB clock "clkapb"
+
+Example:
+
+	timer: timer@98400000 {
+		compatible = "moxa,moxart-timer";
+		reg = <0x98400000 0x42>;
+		interrupts = <19 1>;
+		clocks = <&clkapb>;
+	};
diff --git a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
index a49d9a1..2191dcb 100644
--- a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
@@ -10,13 +10,18 @@ Required properties:
 Optional properties:
 - atmel,use-dma-rx: use of PDC or DMA for receiving data
 - atmel,use-dma-tx: use of PDC or DMA for transmitting data
+- add dma bindings for dma transfer:
+	- dmas: DMA specifier, consisting of a phandle to DMA controller node,
+		memory peripheral interface and USART DMA channel ID, FIFO configuration.
+		Refer to dma.txt and atmel-dma.txt for details.
+	- dma-names: "rx" for RX channel, "tx" for TX channel.
 
 <chip> compatible description:
 - at91rm9200:  legacy USART support
 - at91sam9260: generic USART implementation for SAM9 SoCs
 
 Example:
-
+- use PDC:
 	usart0: serial@fff8c000 {
 		compatible = "atmel,at91sam9260-usart";
 		reg = <0xfff8c000 0x4000>;
@@ -25,3 +30,14 @@ Example:
 		atmel,use-dma-tx;
 	};
 
+- use DMA:
+	usart0: serial@f001c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xf001c000 0x100>;
+		interrupts = <12 4 5>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+		dmas = <&dma0 2 0x3>,
+		       <&dma0 2 0x204>;
+		dma-names = "tx", "rx";
+	};
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
index 2c00ec6..59a40f1 100644
--- a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
@@ -10,6 +10,10 @@ Required properties:
   Refer to dma.txt and fsl-mxs-dma.txt for details.
 - dma-names: "rx" for RX channel, "tx" for TX channel.
 
+Optional properties:
+- fsl,uart-has-rtscts : Indicate the UART has RTS and CTS lines,
+	it also means you enable the DMA support for this UART.
+
 Example:
 auart0: serial@8006a000 {
 	compatible = "fsl,imx28-auart", "fsl,imx23-auart";
diff --git a/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
new file mode 100644
index 0000000..6ad1adf
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
@@ -0,0 +1,53 @@
+* Renesas SH-Mobile Serial Communication Interface
+
+Required properties:
+- compatible : Should be "renesas,sci-<port type>-uart", where <port type> may be
+  SCI, SCIF, IRDA, SCIFA or SCIFB.
+- reg : Address and length of the register set for the device
+- interrupts : Should contain the following IRQs: ERI, RXI, TXI and BRI.
+- cell-index : The device id.
+- renesas,scscr : Should contain a bitfield used by the Serial Control Register.
+  b7 = SCSCR_TIE
+  b6 = SCSCR_RIE
+  b5 = SCSCR_TE
+  b4 = SCSCR_RE
+  b3 = SCSCR_REIE
+  b2 = SCSCR_TOIE
+  b1 = SCSCR_CKE1
+  b0 = SCSCR_CKE0
+- renesas,scbrr-algo-id : Algorithm ID for the Bit Rate Register
+  1 = SCBRR_ALGO_1 ((clk + 16 * bps) / (16 * bps) - 1)
+  2 = SCBRR_ALGO_2 ((clk + 16 * bps) / (32 * bps) - 1)
+  3 = SCBRR_ALGO_3 (((clk * 2) + 16 * bps) / (16 * bps) - 1)
+  4 = SCBRR_ALGO_4 (((clk * 2) + 16 * bps) / (32 * bps) - 1)
+  5 = SCBRR_ALGO_5 (((clk * 1000 / 32) / bps) - 1)
+
+Optional properties:
+- renesas,autoconf : Set if device is capable of auto configuration
+- renesas,regtype : Overwrite the register layout. In most cases you can rely
+  on auto-probing (omit this property or set to 0) but some legacy devices
+  use a non-default register layout. Possible layouts are
+  0 = SCIx_PROBE_REGTYPE (default)
+  1 = SCIx_SCI_REGTYPE
+  2 = SCIx_IRDA_REGTYPE
+  3 = SCIx_SCIFA_REGTYPE
+  4 = SCIx_SCIFB_REGTYPE
+  5 = SCIx_SH2_SCIF_FIFODATA_REGTYPE
+  6 = SCIx_SH3_SCIF_REGTYPE
+  7 = SCIx_SH4_SCIF_REGTYPE
+  8 = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE
+  9 = SCIx_SH4_SCIF_FIFODATA_REGTYPE
+ 10 = SCIx_SH7705_SCIF_REGTYPE
+
+
+Example:
+	sci@0xe6c50000 {
+		compatible = "renesas,sci-SCIFA-uart";
+		interrupt-parent = <&intca>;
+		reg = <0xe6c50000 0x100>;
+		interrupts = <0x0c20>, <0x0c20>, <0x0c20>, <0x0c20>;
+		cell-index = <1>;
+		renesas,scscr = <0x30>;
+		renesas,scbrr-algo-id = <4>;
+		renesas,autoconf;
+	};
diff --git a/Documentation/devicetree/bindings/tty/serial/st-asc.txt b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
new file mode 100644
index 0000000..75d877f
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
@@ -0,0 +1,18 @@
+*st-asc(Serial Port)
+
+Required properties:
+- compatible : Should be "st,asc".
+- reg, reg-names, interrupts, interrupt-names	: Standard way to define device
+			resources with names. look in
+			Documentation/devicetree/bindings/resource-names.txt
+
+Optional properties:
+- st,hw-flow-ctrl	bool flag to enable hardware flow control.
+- st,force-m1		bool flat to force asc to be in Mode-1 recommeded
+			for high bit rates (above 19.2K)
+Example:
+serial@fe440000{
+    compatible    = "st,asc";
+    reg         = <0xfe440000 0x2c>;
+    interrupts     =  <0 209 0>;
+};
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 7a95c65..3a64e20 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -3,7 +3,7 @@ synopsys DWC3 CORE
 DWC3- USB3 CONTROLLER
 
 Required properties:
- - compatible: must be "synopsys,dwc3"
+ - compatible: must be "snps,dwc3"
  - reg : Address and length of the register set for the device
  - interrupts: Interrupts used by the dwc3 controller.
  - usb-phy : array of phandle for the PHY device
@@ -14,7 +14,7 @@ Optional properties:
 This is usually a subnode to DWC3 glue to which it is connected.
 
 dwc3@4a030000 {
-	compatible = "synopsys,dwc3";
+	compatible = "snps,dwc3";
 	reg = <0x4a030000 0xcfff>;
 	interrupts = <0 92 4>
 	usb-phy = <&usb2_phy>, <&usb3,phy>;
diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
new file mode 100644
index 0000000..477d5bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -0,0 +1,24 @@
+Generic USB Properties
+
+Optional properties:
+ - maximum-speed: tells USB controllers we want to work up to a certain
+			speed. Valid arguments are "super-speed", "high-speed",
+			"full-speed" and "low-speed". In case this isn't passed
+			via DT, USB controllers should default to their maximum
+			HW capability.
+ - dr_mode: tells Dual-Role USB controllers that we want to work on a
+			particular mode. Valid arguments are "host",
+			"peripheral" and "otg". In case this attribute isn't
+			passed via DT, USB DRD controllers should default to
+			OTG.
+
+This is an attribute to a USB controller such as:
+
+dwc3@4a030000 {
+	compatible = "synopsys,dwc3";
+	reg = <0x4a030000 0xcfff>;
+	interrupts = <0 92 4>
+	usb-phy = <&usb2_phy>, <&usb3,phy>;
+	maximum-speed = "super-speed";
+	dr_mode = "otg";
+};
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
index c4c9e9e..4c8ade8 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
@@ -48,5 +48,5 @@ Optional properties:
       peripheral means it is device controller
       otg means it can operate as either ("on the go")
 
-Required properties for dr_mode == otg:
+VBUS control (required for dr_mode == otg, optional for dr_mode == host):
   - vbus-supply: regulator for VBUS
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 57e71f6..9088ab0 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -53,6 +53,11 @@ OMAP DWC3 GLUE
    It should be set to "1" for HW mode and "2" for SW mode.
  - ranges: the child address space are mapped 1:1 onto the parent address space
 
+Optional Properties:
+ - extcon : phandle for the extcon device omap dwc3 uses to detect
+   connect/disconnect events.
+ - vbus-supply : phandle to the regulator device tree node if needed.
+
 Sub-nodes:
 The dwc3 core should be added as subnode to omap dwc3 glue.
 - dwc3 :
diff --git a/Documentation/devicetree/bindings/usb/samsung-hsotg.txt b/Documentation/devicetree/bindings/usb/samsung-hsotg.txt
new file mode 100644
index 0000000..b83d428
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/samsung-hsotg.txt
@@ -0,0 +1,40 @@
+Samsung High Speed USB OTG controller
+-----------------------------
+
+The Samsung HSOTG IP can be found on Samsung SoCs, from S3C6400 onwards.
+It gives functionality of OTG-compliant USB 2.0 host and device with
+support for USB 2.0 high-speed (480Mbps) and full-speed (12 Mbps)
+operation.
+
+Currently only device mode is supported.
+
+Binding details
+-----
+
+Required properties:
+- compatible: "samsung,s3c6400-hsotg" should be used for all currently
+    supported SoC,
+- interrupt-parent: phandle for the interrupt controller to which the
+    interrupt signal of the HSOTG block is routed,
+- interrupts: specifier of interrupt signal of interrupt controller,
+    according to bindings of interrupt controller,
+- clocks: contains an array of clock specifiers:
+    - first entry: OTG clock
+- clock-names: contains array of clock names:
+    - first entry: must be "otg"
+- vusb_d-supply: phandle to voltage regulator of digital section,
+- vusb_a-supply: phandle to voltage regulator of analog section.
+
+Example
+-----
+
+	hsotg@12480000 {
+		compatible = "samsung,s3c6400-hsotg";
+		reg = <0x12480000 0x20000>;
+		interrupts = <0 71 0>;
+		clocks = <&clock 305>;
+		clock-names = "otg";
+		vusb_d-supply = <&vusb_reg>;
+		vusb_a-supply = <&vusbdac_reg>;
+	};
+
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 366ce9b..ec4d713 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -11,6 +11,7 @@ amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
 apm	Applied Micro Circuits Corporation (APM)
 arm	ARM Ltd.
 atmel	Atmel Corporation
+avago	Avago Technologies
 bosch	Bosch Sensortec GmbH
 brcm	Broadcom Corporation
 cavium	Cavium, Inc.
diff --git a/Documentation/devicetree/bindings/video/atmel,lcdc.txt b/Documentation/devicetree/bindings/video/atmel,lcdc.txt
new file mode 100644
index 0000000..1ec175e
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/atmel,lcdc.txt
@@ -0,0 +1,75 @@
+Atmel LCDC Framebuffer
+-----------------------------------------------------
+
+Required properties:
+- compatible :
+	"atmel,at91sam9261-lcdc" , 
+	"atmel,at91sam9263-lcdc" ,
+	"atmel,at91sam9g10-lcdc" ,
+	"atmel,at91sam9g45-lcdc" ,
+	"atmel,at91sam9g45es-lcdc" ,
+	"atmel,at91sam9rl-lcdc" ,
+	"atmel,at32ap-lcdc"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : framebuffer controller interrupt
+- display: a phandle pointing to the display node
+
+Required nodes:
+- display: a display node is required to initialize the lcd panel
+	This should be in the board dts.
+- default-mode: a videomode within the display with timing parameters
+	as specified below.
+
+Example:
+
+	fb0: fb@0x00500000 {
+		compatible = "atmel,at91sam9g45-lcdc";
+		reg = <0x00500000 0x1000>;
+		interrupts = <23 3 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_fb>;
+		display = <&display0>;
+		status = "okay";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+	};
+
+Atmel LCDC Display
+-----------------------------------------------------
+Required properties (as per of_videomode_helper):
+
+ - atmel,dmacon: dma controler configuration
+ - atmel,lcdcon2: lcd controler configuration
+ - atmel,guard-time: lcd guard time (Delay in frame periods)
+ - bits-per-pixel: lcd panel bit-depth.
+
+Optional properties (as per of_videomode_helper):
+ - atmel,lcdcon-backlight: enable backlight
+ - atmel,lcd-wiring-mode: lcd wiring mode "RGB" or "BRG"
+ - atmel,power-control-gpio: gpio to power on or off the LCD (as many as needed)
+
+Example:
+	display0: display {
+		bits-per-pixel = <32>;
+		atmel,lcdcon-backlight;
+		atmel,dmacon = <0x1>;
+		atmel,lcdcon2 = <0x80008002>;
+		atmel,guard-time = <9>;
+		atmel,lcd-wiring-mode = <1>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: timing0 {
+				clock-frequency = <9000000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <1>;
+				hfront-porch = <1>;
+				vback-porch = <40>;
+				vfront-porch = <1>;
+				hsync-len = <45>;
+				vsync-len = <1>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/video/simple-framebuffer.txt b/Documentation/devicetree/bindings/video/simple-framebuffer.txt
index 3ea4605..70c26f3 100644
--- a/Documentation/devicetree/bindings/video/simple-framebuffer.txt
+++ b/Documentation/devicetree/bindings/video/simple-framebuffer.txt
@@ -12,6 +12,7 @@ Required properties:
 - stride: The number of bytes in each line of the framebuffer.
 - format: The format of the framebuffer surface. Valid values are:
   - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b).
+  - a8b8g8r8 (32-bit pixels, d[31:24]=a, d[23:16]=b, d[15:8]=g, d[7:0]=r).
 
 Example:
 
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt
index 0b23261..e31a2a9 100644
--- a/Documentation/dma-buf-sharing.txt
+++ b/Documentation/dma-buf-sharing.txt
@@ -321,7 +321,7 @@ Access to a dma_buf from the kernel context involves three steps:
 
    When the importer is done accessing the range specified in begin_cpu_access,
    it needs to announce this to the exporter (to facilitate cache flushing and
-   unpinning of any pinned resources). The result of of any dma_buf kmap calls
+   unpinning of any pinned resources). The result of any dma_buf kmap calls
    after end_cpu_access is undefined.
 
    Interface:
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index b467145..1d32332 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -237,6 +237,10 @@ MEM
   devm_kzalloc()
   devm_kfree()
 
+IIO
+  devm_iio_device_alloc()
+  devm_iio_device_free()
+
 IO region
   devm_request_region()
   devm_request_mem_region()
diff --git a/Documentation/fb/fbcon.txt b/Documentation/fb/fbcon.txt
index 99ea58e..4a9739a 100644
--- a/Documentation/fb/fbcon.txt
+++ b/Documentation/fb/fbcon.txt
@@ -150,7 +150,7 @@ C. Boot options
 
 C. Attaching, Detaching and Unloading
 
-Before going on on how to attach, detach and unload the framebuffer console, an
+Before going on how to attach, detach and unload the framebuffer console, an
 illustration of the dependencies may help.
 
 The console layer, as with most subsystems, needs a driver that interfaces with
diff --git a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt
index 444e34b..1cb2462 100644
--- a/Documentation/fb/viafb.txt
+++ b/Documentation/fb/viafb.txt
@@ -32,7 +32,7 @@
     Start viafb with default settings:
         #modprobe viafb
 
-    Start viafb with with user options:
+    Start viafb with user options:
         #modprobe viafb viafb_mode=800x600 viafb_bpp=16 viafb_refresh=60
                   viafb_active_dev=CRT+DVI viafb_dvi_port=DVP1
                   viafb_mode1=1024x768 viafb_bpp=16 viafb_refresh1=60
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 293855e..7ed0d17 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -26,11 +26,12 @@ journal=inum		When a journal already exists, this option is ignored.
 			Otherwise, it specifies the number of the inode which
 			will represent the ext3 file system's journal file.
 
+journal_path=path
 journal_dev=devnum	When the external journal device's major/minor numbers
-			have changed, this option allows the user to specify
+			have changed, these options allow the user to specify
 			the new journal location.  The journal device is
-			identified through its new major/minor numbers encoded
-			in devnum.
+			identified through either its new major/minor numbers
+			encoded in devnum, or via a path to the device.
 
 norecovery		Don't load the journal on mounting. Note that this forces
 noload			mount of inconsistent filesystem, which can lead to
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index f7cbf57..a92c5aa 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -2,7 +2,7 @@
 Ext4 Filesystem
 ===============
 
-Ext4 is an an advanced level of the ext3 filesystem which incorporates
+Ext4 is an advanced level of the ext3 filesystem which incorporates
 scalability and reliability enhancements for supporting large filesystems
 (64 bit) in keeping with increasing disk capacities and state-of-the-art
 feature requirements.
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index b91e2f2..3cd27be 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -18,8 +18,8 @@ according to its internal geometry or flash memory management scheme, namely FTL
 F2FS and its tools support various parameters not only for configuring on-disk
 layout, but also for selecting allocation and cleaning algorithms.
 
-The file system formatting tool, "mkfs.f2fs", is available from the following
-git tree:
+The following git tree provides the file system formatting tool (mkfs.f2fs),
+a consistency checking tool (fsck.f2fs), and a debugging tool (dump.f2fs).
 >> git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git
 
 For reporting bugs and sending patches, please use the following mailing list:
@@ -133,6 +133,38 @@ f2fs. Each file shows the whole f2fs information.
  - current memory footprint consumed by f2fs.
 
 ================================================================================
+SYSFS ENTRIES
+================================================================================
+
+Information about mounted f2f2 file systems can be found in
+/sys/fs/f2fs.  Each mounted filesystem will have a directory in
+/sys/fs/f2fs based on its device name (i.e., /sys/fs/f2fs/sda).
+The files in each per-device directory are shown in table below.
+
+Files in /sys/fs/f2fs/<devname>
+(see also Documentation/ABI/testing/sysfs-fs-f2fs)
+..............................................................................
+ File                         Content
+
+ gc_max_sleep_time            This tuning parameter controls the maximum sleep
+                              time for the garbage collection thread. Time is
+                              in milliseconds.
+
+ gc_min_sleep_time            This tuning parameter controls the minimum sleep
+                              time for the garbage collection thread. Time is
+                              in milliseconds.
+
+ gc_no_gc_sleep_time          This tuning parameter controls the default sleep
+                              time for the garbage collection thread. Time is
+                              in milliseconds.
+
+ gc_idle                      This parameter controls the selection of victim
+                              policy for garbage collection. Setting gc_idle = 0
+                              (default) will disable this option. Setting
+                              gc_idle = 1 will select the Cost Benefit approach
+                              & setting gc_idle = 2 will select the greedy aproach.
+
+================================================================================
 USAGE
 ================================================================================
 
@@ -149,8 +181,12 @@ USAGE
  # mkfs.f2fs -l label /dev/block_device
  # mount -t f2fs /dev/block_device /mnt/f2fs
 
-Format options
---------------
+mkfs.f2fs
+---------
+The mkfs.f2fs is for the use of formatting a partition as the f2fs filesystem,
+which builds a basic on-disk layout.
+
+The options consist of:
 -l [label]   : Give a volume label, up to 512 unicode name.
 -a [0 or 1]  : Split start location of each area for heap-based allocation.
                1 is set by default, which performs this.
@@ -164,6 +200,37 @@ Format options
 -t [0 or 1]  : Disable discard command or not.
                1 is set by default, which conducts discard.
 
+fsck.f2fs
+---------
+The fsck.f2fs is a tool to check the consistency of an f2fs-formatted
+partition, which examines whether the filesystem metadata and user-made data
+are cross-referenced correctly or not.
+Note that, initial version of the tool does not fix any inconsistency.
+
+The options consist of:
+  -d debug level [default:0]
+
+dump.f2fs
+---------
+The dump.f2fs shows the information of specific inode and dumps SSA and SIT to
+file. Each file is dump_ssa and dump_sit.
+
+The dump.f2fs is used to debug on-disk data structures of the f2fs filesystem.
+It shows on-disk inode information reconized by a given inode number, and is
+able to dump all the SSA and SIT entries into predefined files, ./dump_ssa and
+./dump_sit respectively.
+
+The options consist of:
+  -d debug level [default:0]
+  -i inode no (hex)
+  -s [SIT dump segno from #1~#2 (decimal), for all 0~-1]
+  -a [SSA dump segno from #1~#2 (decimal), for all 0~-1]
+
+Examples:
+# dump.f2fs -i [ino] /dev/sdx
+# dump.f2fs -s 0~-1 /dev/sdx (SIT dump)
+# dump.f2fs -a 0~-1 /dev/sdx (SSA dump)
+
 ================================================================================
 DESIGN
 ================================================================================
diff --git a/Documentation/filesystems/nfs/pnfs.txt b/Documentation/filesystems/nfs/pnfs.txt
index 52ae07f..adc81a3 100644
--- a/Documentation/filesystems/nfs/pnfs.txt
+++ b/Documentation/filesystems/nfs/pnfs.txt
@@ -12,7 +12,7 @@ struct pnfs_layout_hdr
 ----------------------
 The on-the-wire command LAYOUTGET corresponds to struct
 pnfs_layout_segment, usually referred to by the variable name lseg.
-Each nfs_inode may hold a pointer to a cache of of these layout
+Each nfs_inode may hold a pointer to a cache of these layout
 segments in nfsi->layout, of type struct pnfs_layout_hdr.
 
 We reference the header for the inode pointing to it, across each
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
index 59b4a09..b176928 100644
--- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
@@ -79,6 +79,10 @@ to just make sure certain lists can't become empty.
 Most systems just mount another filesystem over rootfs and ignore it.  The
 amount of space an empty instance of ramfs takes up is tiny.
 
+If CONFIG_TMPFS is enabled, rootfs will use tmpfs instead of ramfs by
+default.  To force ramfs, add "rootfstype=ramfs" to the kernel command
+line.
+
 What is initramfs?
 ------------------
 
diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt
index 510b722..33e2f36 100644
--- a/Documentation/filesystems/relay.txt
+++ b/Documentation/filesystems/relay.txt
@@ -31,7 +31,7 @@ Semantics
 
 Each relay channel has one buffer per CPU, each buffer has one or more
 sub-buffers.  Messages are written to the first sub-buffer until it is
-too full to contain a new message, in which case it it is written to
+too full to contain a new message, in which case it is written to
 the next (if available).  Messages are never split across sub-buffers.
 At this point, userspace can be notified so it empties the first
 sub-buffer, while the kernel continues writing to the next.
diff --git a/Documentation/filesystems/sysfs-tagging.txt b/Documentation/filesystems/sysfs-tagging.txt
index caaaf12..eb843e4 100644
--- a/Documentation/filesystems/sysfs-tagging.txt
+++ b/Documentation/filesystems/sysfs-tagging.txt
@@ -24,7 +24,7 @@ flag between KOBJ_NS_TYPE_NONE and KOBJ_NS_TYPES, and s_ns will
 point to the namespace to which it belongs.
 
 Each sysfs superblock's sysfs_super_info contains an array void
-*ns[KOBJ_NS_TYPES].  When a a task in a tagging namespace
+*ns[KOBJ_NS_TYPES].  When a task in a tagging namespace
 kobj_nstype first mounts sysfs, a new superblock is created.  It
 will be differentiated from other sysfs mounts by having its
 s_fs_info->ns[kobj_nstype] set to the new namespace.  Note that
diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt
index 3c74121..dc35a2b 100644
--- a/Documentation/hid/uhid.txt
+++ b/Documentation/hid/uhid.txt
@@ -149,11 +149,13 @@ needs. Only UHID_OUTPUT and UHID_OUTPUT_EV have payloads.
   is of type "struct uhid_data_req".
   This may be received even though you haven't received UHID_OPEN, yet.
 
-  UHID_OUTPUT_EV:
+  UHID_OUTPUT_EV (obsolete):
   Same as UHID_OUTPUT but this contains a "struct input_event" as payload. This
   is called for force-feedback, LED or similar events which are received through
   an input device by the HID subsystem. You should convert this into raw reports
   and send them to your device similar to events of type UHID_OUTPUT.
+  This is no longer sent by newer kernels. Instead, HID core converts it into a
+  raw output report and sends it via UHID_OUTPUT.
 
   UHID_FEATURE:
   This event is sent if the kernel driver wants to perform a feature request as
diff --git a/Documentation/hwmon/ads1015 b/Documentation/hwmon/ads1015
index f6fe9c2..063b80d 100644
--- a/Documentation/hwmon/ads1015
+++ b/Documentation/hwmon/ads1015
@@ -6,6 +6,10 @@ Supported chips:
     Prefix: 'ads1015'
     Datasheet: Publicly available at the Texas Instruments website :
                http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+  * Texas Instruments ADS1115
+    Prefix: 'ads1115'
+    Datasheet: Publicly available at the Texas Instruments website :
+               http://focus.ti.com/lit/ds/symlink/ads1115.pdf
 
 Authors:
         Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
@@ -13,9 +17,9 @@ Authors:
 Description
 -----------
 
-This driver implements support for the Texas Instruments ADS1015.
+This driver implements support for the Texas Instruments ADS1015/ADS1115.
 
-This device is a 12-bit A-D converter with 4 inputs.
+This device is a 12/16-bit A-D converter with 4 inputs.
 
 The inputs can be used single ended or in certain differential combinations.
 
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
index 90387c3..f4021a2 100644
--- a/Documentation/hwmon/w83791d
+++ b/Documentation/hwmon/w83791d
@@ -17,7 +17,7 @@ Credits:
     Philip Edelbrock <phil@netroedge.com>,
     and Mark Studebaker <mdsxyz123@yahoo.com>
   w83792d.c:
-    Chunhao Huang <DZShen@Winbond.com.tw>,
+    Shane Huang (Winbond),
     Rudolf Marek <r.marek@assembler.cz>
 
 Additional contributors:
diff --git a/Documentation/hwmon/w83792d b/Documentation/hwmon/w83792d
index 8a023ce..53f7b68 100644
--- a/Documentation/hwmon/w83792d
+++ b/Documentation/hwmon/w83792d
@@ -7,8 +7,7 @@ Supported chips:
     Addresses scanned: I2C 0x2c - 0x2f
     Datasheet: http://www.winbond.com.tw
 
-Author: Chunhao Huang
-Contact: DZShen <DZShen@Winbond.com.tw>
+Author: Shane Huang (Winbond)
 
 
 Module Parameters
diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients
index d699162..8e5fbd8 100644
--- a/Documentation/i2c/upgrading-clients
+++ b/Documentation/i2c/upgrading-clients
@@ -196,8 +196,8 @@ static int example_probe(struct i2c_client *i2c_client,
 
 Update the detach method, by changing the name to _remove and
 to delete the i2c_detach_client call. It is possible that you
-can also remove the ret variable as it is not not needed for
-any of the core functions.
+can also remove the ret variable as it is not needed for any
+of the core functions.
 
 - static int example_detach(struct i2c_client *client)
 + static int example_remove(struct i2c_client *client)
diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt
index e349f29..8ef6dbb 100644
--- a/Documentation/kbuild/kconfig.txt
+++ b/Documentation/kbuild/kconfig.txt
@@ -175,11 +175,9 @@ Searching in menuconfig:
 		/^hotplug
 
 	When searching, symbols are sorted thus:
-	  - exact match first: an exact match is when the search matches
-	    the complete symbol name;
-	  - alphabetical order: when two symbols do not match exactly,
-	    they are sorted in alphabetical order (in the user's current
-	    locale).
+	  - first, exact matches, sorted alphabetically (an exact match
+	    is when the search matches the complete symbol name);
+	  - then, other matches, sorted alphabetically.
 	For example: ^ATH.K matches:
 	    ATH5K ATH9K ATH5K_AHB ATH5K_DEBUG [...] ATH6KL ATH6KL_DEBUG
 	    [...] ATH9K_AHB ATH9K_BTCOEX_SUPPORT ATH9K_COMMON [...]
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 15356ac..f6209af 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -235,10 +235,61 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			Format: To spoof as Windows 98: ="Microsoft Windows"
 
 	acpi_osi=	[HW,ACPI] Modify list of supported OS interface strings
-			acpi_osi="string1"	# add string1 -- only one string
-			acpi_osi="!string2"	# remove built-in string2
+			acpi_osi="string1"	# add string1
+			acpi_osi="!string2"	# remove string2
+			acpi_osi=!*		# remove all strings
+			acpi_osi=!		# disable all built-in OS vendor
+						  strings
 			acpi_osi=		# disable all strings
 
+			'acpi_osi=!' can be used in combination with single or
+			multiple 'acpi_osi="string1"' to support specific OS
+			vendor string(s).  Note that such command can only
+			affect the default state of the OS vendor strings, thus
+			it cannot affect the default state of the feature group
+			strings and the current state of the OS vendor strings,
+			specifying it multiple times through kernel command line
+			is meaningless.  This command is useful when one do not
+			care about the state of the feature group strings which
+			should be controlled by the OSPM.
+			Examples:
+			  1. 'acpi_osi=! acpi_osi="Windows 2000"' is equivalent
+			     to 'acpi_osi="Windows 2000" acpi_osi=!', they all
+			     can make '_OSI("Windows 2000")' TRUE.
+
+			'acpi_osi=' cannot be used in combination with other
+			'acpi_osi=' command lines, the _OSI method will not
+			exist in the ACPI namespace.  NOTE that such command can
+			only affect the _OSI support state, thus specifying it
+			multiple times through kernel command line is also
+			meaningless.
+			Examples:
+			  1. 'acpi_osi=' can make 'CondRefOf(_OSI, Local1)'
+			     FALSE.
+
+			'acpi_osi=!*' can be used in combination with single or
+			multiple 'acpi_osi="string1"' to support specific
+			string(s).  Note that such command can affect the
+			current state of both the OS vendor strings and the
+			feature group strings, thus specifying it multiple times
+			through kernel command line is meaningful.  But it may
+			still not able to affect the final state of a string if
+			there are quirks related to this string.  This command
+			is useful when one want to control the state of the
+			feature group strings to debug BIOS issues related to
+			the OSPM features.
+			Examples:
+			  1. 'acpi_osi="Module Device" acpi_osi=!*' can make
+			     '_OSI("Module Device")' FALSE.
+			  2. 'acpi_osi=!* acpi_osi="Module Device"' can make
+			     '_OSI("Module Device")' TRUE.
+			  3. 'acpi_osi=! acpi_osi=!* acpi_osi="Windows 2000"' is
+			     equivalent to
+			     'acpi_osi=!* acpi_osi=! acpi_osi="Windows 2000"'
+			     and
+			     'acpi_osi=!* acpi_osi="Windows 2000" acpi_osi=!',
+			     they all will make '_OSI("Windows 2000")' TRUE.
+
 	acpi_pm_good	[X86]
 			Override the pmtimer bug detection: force the kernel
 			to assume that this machine's pmtimer latches its value
@@ -3322,6 +3373,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			            them quite hard to use for exploits but
 			            might break your system.
 
+	vt.color=	[VT] Default text color.
+			Format: 0xYX, X = foreground, Y = background.
+			Default: 0x07 = light gray on black.
+
 	vt.cur_default=	[VT] Default cursor shape.
 			Format: 0xCCBBAA, where AA, BB, and CC are the same as
 			the parameters of the <Esc>[?A;B;Cc escape sequence;
@@ -3361,6 +3416,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			overridden by individual drivers. 0 will hide
 			cursors, 1 will display them.
 
+	vt.italic=	[VT] Default color for italic text; 0-15.
+			Default: 2 = green.
+
+	vt.underline=	[VT] Default color for underlined text; 0-15.
+			Default: 3 = cyan.
+
 	watchdog timers	[HW,WDT] For information on watchdog timers,
 			see Documentation/watchdog/watchdog-parameters.txt
 			or other driver-specific files in the
diff --git a/Documentation/laptops/asus-laptop.txt b/Documentation/laptops/asus-laptop.txt
index 69f9fb3..79a1bc6 100644
--- a/Documentation/laptops/asus-laptop.txt
+++ b/Documentation/laptops/asus-laptop.txt
@@ -8,8 +8,8 @@ http://acpi4asus.sf.net/
 
  This driver provides support for extra features of ACPI-compatible ASUS laptops.
  It may also support some MEDION, JVC or VICTOR laptops (such as MEDION 9675 or
- VICTOR XP7210 for example). It makes all the extra buttons generate standard
- ACPI events that go through /proc/acpi/events and input events (like keyboards).
+ VICTOR XP7210 for example). It makes all the extra buttons generate input
+ events (like keyboards).
  On some models adds support for changing the display brightness and output,
  switching the LCD backlight on and off, and most importantly, allows you to
  blink those fancy LEDs intended for reporting mail and wireless status.
@@ -55,8 +55,8 @@ Usage
   DSDT) to me.
 
   That's all, now, all the events generated by the hotkeys of your laptop
-  should be reported in your /proc/acpi/event entry. You can check with
-  "acpi_listen".
+  should be reported via netlink events. You can check with
+  "acpi_genl monitor" (part of the acpica project).
 
   Hotkeys are also reported as input keys (like keyboards) you can check
   which key are supported using "xev" under X11.
diff --git a/Documentation/laptops/sony-laptop.txt b/Documentation/laptops/sony-laptop.txt
index 0d5ac7f..978b1e6 100644
--- a/Documentation/laptops/sony-laptop.txt
+++ b/Documentation/laptops/sony-laptop.txt
@@ -12,10 +12,10 @@ Fn keys (hotkeys):
 ------------------
 Some models report hotkeys through the SNC or SPIC devices, such events are
 reported both through the ACPI subsystem as acpi events and through the INPUT
-subsystem. See the logs of acpid or /proc/acpi/event and
-/proc/bus/input/devices to find out what those events are and which input
-devices are created by the driver. Additionally, loading the driver with the
-debug option will report all events in the kernel log.
+subsystem. See the logs of /proc/bus/input/devices to find out what those
+events are and which input devices are created by the driver.
+Additionally, loading the driver with the debug option will report all events
+in the kernel log.
 
 The "scancodes" passed to the input system (that can be remapped with udev)
 are indexes to the table "sony_laptop_input_keycode_map" in the sony-laptop.c
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index cf7bc6c..86c5236 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -329,20 +329,6 @@ sysfs notes:
 
 		This attribute has poll()/select() support.
 
-	hotkey_report_mode:
-		Returns the state of the procfs ACPI event report mode
-		filter for hot keys.  If it is set to 1 (the default),
-		all hot key presses are reported both through the input
-		layer and also as ACPI events through procfs (but not
-		through netlink).  If it is set to 2, hot key presses
-		are reported only through the input layer.
-
-		This attribute is read-only in kernels 2.6.23 or later,
-		and read-write on earlier kernels.
-
-		May return -EPERM (write access locked out by module
-		parameter) or -EACCES (read-only).
-
 	wakeup_reason:
 		Set to 1 if the system is waking up because the user
 		requested a bay ejection.  Set to 2 if the system is
@@ -518,24 +504,21 @@ SW_TABLET_MODE	Tablet ThinkPads HKEY events 0x5009 and 0x500A
 Non hotkey ACPI HKEY event map:
 -------------------------------
 
-Events that are not propagated by the driver, except for legacy
-compatibility purposes when hotkey_report_mode is set to 1:
-
-0x5001		Lid closed
-0x5002		Lid opened
-0x5009		Tablet swivel: switched to tablet mode
-0x500A		Tablet swivel: switched to normal mode
-0x7000		Radio Switch may have changed state
-
 Events that are never propagated by the driver:
 
 0x2304		System is waking up from suspend to undock
 0x2305		System is waking up from suspend to eject bay
 0x2404		System is waking up from hibernation to undock
 0x2405		System is waking up from hibernation to eject bay
+0x5001		Lid closed
+0x5002		Lid opened
+0x5009		Tablet swivel: switched to tablet mode
+0x500A		Tablet swivel: switched to normal mode
 0x5010		Brightness level changed/control event
 0x6000		KEYBOARD: Numlock key pressed
 0x6005		KEYBOARD: Fn key pressed (TO BE VERIFIED)
+0x7000		Radio Switch may have changed state
+
 
 Events that are propagated by the driver to userspace:
 
@@ -574,50 +557,6 @@ operating system is to force either an immediate suspend or hibernate
 cycle, or a system shutdown.  Obviously, something is very wrong if this
 happens.
 
-Compatibility notes:
-
-ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never
-supported the input layer, and sent events over the procfs ACPI event
-interface.
-
-To avoid sending duplicate events over the input layer and the ACPI
-event interface, thinkpad-acpi 0.16 implements a module parameter
-(hotkey_report_mode), and also a sysfs device attribute with the same
-name.
-
-Make no mistake here: userspace is expected to switch to using the input
-layer interface of thinkpad-acpi, together with the ACPI netlink event
-interface in kernels 2.6.23 and later, or with the ACPI procfs event
-interface in kernels 2.6.22 and earlier.
-
-If no hotkey_report_mode module parameter is specified (or it is set to
-zero), the driver defaults to mode 1 (see below), and on kernels 2.6.22
-and earlier, also allows one to change the hotkey_report_mode through
-sysfs.  In kernels 2.6.23 and later, where the netlink ACPI event
-interface is available, hotkey_report_mode cannot be changed through
-sysfs (it is read-only).
-
-If the hotkey_report_mode module parameter is set to 1 or 2, it cannot
-be changed later through sysfs (any writes will return -EPERM to signal
-that hotkey_report_mode was locked.  On 2.6.23 and later, where
-hotkey_report_mode cannot be changed at all, writes will return -EACCES).
-
-hotkey_report_mode set to 1 makes the driver export through the procfs
-ACPI event interface all hot key presses (which are *also* sent to the
-input layer).  This is a legacy compatibility behaviour, and it is also
-the default mode of operation for the driver.
-
-hotkey_report_mode set to 2 makes the driver filter out the hot key
-presses from the procfs ACPI event interface, so these events will only
-be sent through the input layer.  Userspace that has been updated to use
-the thinkpad-acpi input layer interface should set hotkey_report_mode to
-2.
-
-Hot key press events are never sent to the ACPI netlink event interface.
-Really up-to-date userspace under kernel 2.6.23 and later is to use the
-netlink interface and the input layer interface, and don't bother at all
-with hotkey_report_mode.
-
 
 Brightness hotkey notes:
 
diff --git a/Documentation/leds/leds-lp55xx.txt b/Documentation/leds/leds-lp55xx.txt
index eec8fa2..82713ff 100644
--- a/Documentation/leds/leds-lp55xx.txt
+++ b/Documentation/leds/leds-lp55xx.txt
@@ -1,11 +1,11 @@
-LP5521/LP5523/LP55231 Common Driver
-===================================
+LP5521/LP5523/LP55231/LP5562/LP8501 Common Driver
+=================================================
 
 Authors: Milo(Woogyom) Kim <milo.kim@ti.com>
 
 Description
 -----------
-LP5521, LP5523/55231 and LP5562 have common features as below.
+LP5521, LP5523/55231, LP5562 and LP8501 have common features as below.
 
   Register access via the I2C
   Device initialization/deinitialization
@@ -109,6 +109,30 @@ As soon as 'loading' is set to 0, registered callback is called.
 Inside the callback, the selected engine is loaded and memory is updated.
 To run programmed pattern, 'run_engine' attribute should be enabled.
 
+The pattern sqeuence of LP8501 is same as LP5523.
+However pattern data is specific.
+Ex 1) Engine 1 is used
+echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
+echo 1 > /sys/class/firmware/lp8501/loading
+echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
+echo 0 > /sys/class/firmware/lp8501/loading
+echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+Ex 2) Engine 2 and 3 are used at the same time
+echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
+sleep 1
+echo 1 > /sys/class/firmware/lp8501/loading
+echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
+echo 0 > /sys/class/firmware/lp8501/loading
+sleep 1
+echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
+sleep 1
+echo 1 > /sys/class/firmware/lp8501/loading
+echo "9d0340ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
+echo 0 > /sys/class/firmware/lp8501/loading
+sleep 1
+echo 1 > /sys/class/leds/d1/device/run_engine
+
 ( 'run_engine' and 'firmware_cb' )
 The sequence of running the program data is common.
 But each device has own specific register addresses for commands.
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index fa5d8a9..c8c42e6 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -531,9 +531,10 @@ dependency barrier to make it work correctly.  Consider the following bit of
 code:
 
 	q = &a;
-	if (p)
+	if (p) {
+		<data dependency barrier>
 		q = &b;
-	<data dependency barrier>
+	}
 	x = *q;
 
 This will not have the desired effect because there is no actual data
@@ -542,9 +543,10 @@ attempting to predict the outcome in advance.  In such a case what's actually
 required is:
 
 	q = &a;
-	if (p)
+	if (p) {
+		<read barrier>
 		q = &b;
-	<read barrier>
+	}
 	x = *q;
 
 
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 8e5eacb..8fd254c 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -210,13 +210,15 @@ If memory device is found, memory hotplug code will be called.
 
 4.2 Notify memory hot-add event by hand
 ------------
-In some environments, especially virtualized environment, firmware will not
-notify memory hotplug event to the kernel. For such environment, "probe"
-interface is supported. This interface depends on CONFIG_ARCH_MEMORY_PROBE.
-
-Now, CONFIG_ARCH_MEMORY_PROBE is supported only by powerpc but it does not
-contain highly architecture codes. Please add config if you need "probe"
-interface.
+On powerpc, the firmware does not notify a memory hotplug event to the kernel.
+Therefore, "probe" interface is supported to notify the event to the kernel.
+This interface depends on CONFIG_ARCH_MEMORY_PROBE.
+
+CONFIG_ARCH_MEMORY_PROBE is supported on powerpc only. On x86, this config
+option is disabled by default since ACPI notifies a memory hotplug event to
+the kernel, which performs its hotplug operation as the result. Please
+enable this option if you need the "probe" interface for testing purposes
+on x86.
 
 Probe interface is located at
 /sys/devices/system/memory/probe
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 32dfbd9..18b64b2 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -124,6 +124,8 @@ multiqueue.txt
 	- HOWTO for multiqueue network device support.
 netconsole.txt
 	- The network console module netconsole.ko: configuration and notes.
+netdev-FAQ.txt
+	- FAQ describing how to submit net changes to netdev mailing list.
 netdev-features.txt
 	- Network interface features API description.
 netdevices.txt
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 1074290..36be26b 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -440,6 +440,10 @@ tcp_syncookies - BOOLEAN
 	SYN flood warnings in logs not being really flooded, your server
 	is seriously misconfigured.
 
+	If you want to test which effects syncookies have to your
+	network connections you can set this knob to 2 to enable
+	unconditionally generation of syncookies.
+
 tcp_fastopen - INTEGER
 	Enable TCP Fast Open feature (draft-ietf-tcpm-fastopen) to send data
 	in the opening SYN packet. To use this feature, the client application
@@ -516,6 +520,19 @@ tcp_wmem - vector of 3 INTEGERs: min, default, max
 	this value is ignored.
 	Default: between 64K and 4MB, depending on RAM size.
 
+tcp_notsent_lowat - UNSIGNED INTEGER
+	A TCP socket can control the amount of unsent bytes in its write queue,
+	thanks to TCP_NOTSENT_LOWAT socket option. poll()/select()/epoll()
+	reports POLLOUT events if the amount of unsent bytes is below a per
+	socket value, and if the write queue is not full. sendmsg() will
+	also not add new buffers if the limit is hit.
+
+	This global variable controls the amount of unsent data for
+	sockets not using TCP_NOTSENT_LOWAT. For these sockets, a change
+	to the global variable has immediate effect.
+
+	Default: UINT_MAX (0xFFFFFFFF)
+
 tcp_workaround_signed_windows - BOOLEAN
 	If set, assume no receipt of a window scaling option means the
 	remote TCP is broken and treats the window as a signed quantity.
diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index a5d574a..0af2e04 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -59,9 +59,7 @@ address.
 The remote host has several options to receive the kernel messages,
 for example:
 
-1) syslogd
-
-2) netcat
+1) netcat
 
    On distributions using a BSD-based netcat version (e.g. Fedora,
    openSUSE and Ubuntu) the listening port must be specified without
@@ -70,10 +68,20 @@ for example:
    'nc -u -l -p <port>' / 'nc -u -l <port>' or
    'netcat -u -l -p <port>' / 'netcat -u -l <port>'
 
-3) socat
+2) socat
 
    'socat udp-recv:<port> -'
 
+3) cancd
+
+   A daemon written specifically for netconsole that is good at capturing
+   output from many machines.  Using netcat for several machines either
+   interleaves output from all machines or requires the use of per-machine
+   ports.
+
+   https://git.kernel.org/cgit/linux/kernel/git/joern/cancd.git/
+   https://oss.oracle.com/projects/cancd/
+
 Dynamic reconfiguration:
 ========================
 
diff --git a/Documentation/networking/netdev-FAQ.txt b/Documentation/networking/netdev-FAQ.txt
new file mode 100644
index 0000000..d9112f0
--- /dev/null
+++ b/Documentation/networking/netdev-FAQ.txt
@@ -0,0 +1,224 @@
+
+Information you need to know about netdev
+-----------------------------------------
+
+Q: What is netdev?
+
+A: It is a mailing list for all network related linux stuff.  This includes
+   anything found under net/  (i.e. core code like IPv6) and drivers/net
+   (i.e. hardware specific drivers) in the linux source tree.
+
+   Note that some subsystems (e.g. wireless drivers) which have a high volume
+   of traffic have their own specific mailing lists.
+
+   The netdev list is managed (like many other linux mailing lists) through
+   VGER ( http://vger.kernel.org/ ) and archives can be found below:
+
+	http://marc.info/?l=linux-netdev
+	http://www.spinics.net/lists/netdev/
+
+   Aside from subsystems like that mentioned above, all network related linux
+   development (i.e. RFC, review, comments, etc) takes place on netdev.
+
+Q: How do the changes posted to netdev make their way into linux?
+
+A: There are always two trees (git repositories) in play.  Both are driven
+   by David Miller, the main network maintainer.  There is the "net" tree,
+   and the "net-next" tree.  As you can probably guess from the names, the
+   net tree is for fixes to existing code already in the mainline tree from
+   Linus, and net-next is where the new code goes for the future release.
+   You can find the trees here:
+
+	http://git.kernel.org/?p=linux/kernel/git/davem/net.git
+	http://git.kernel.org/?p=linux/kernel/git/davem/net-next.git
+
+Q: How often do changes from these trees make it to the mainline Linus tree?
+
+A: To understand this, you need to know a bit of background information
+   on the cadence of linux development.  Each new release starts off with
+   a two week "merge window" where the main maintainers feed their new
+   stuff to Linus for merging into the mainline tree.  After the two weeks,
+   the merge window is closed, and it is called/tagged "-rc1".  No new
+   features get mainlined after this -- only fixes to the rc1 content
+   are expected.  After roughly a week of collecting fixes to the rc1
+   content, rc2 is released.  This repeats on a roughly weekly basis
+   until rc7 (typically; sometimes rc6 if things are quiet, or rc8 if
+   things are in a state of churn), and a week after the last vX.Y-rcN
+   was done, the official "vX.Y" is released.
+
+   Relating that to netdev:  At the beginning of the 2 week merge window,
+   the net-next tree will be closed - no new changes/features.  The
+   accumulated new content of the past ~10 weeks will be passed onto
+   mainline/Linus via a pull request for vX.Y -- at the same time,
+   the "net" tree will start accumulating fixes for this pulled content
+   relating to vX.Y
+
+   An announcement indicating when net-next has been closed is usually
+   sent to netdev, but knowing the above, you can predict that in advance.
+
+   IMPORTANT:  Do not send new net-next content to netdev during the
+   period during which net-next tree is closed.
+
+   Shortly after the two weeks have passed, (and vX.Y-rc1 is released) the
+   tree for net-next reopens to collect content for the next (vX.Y+1) release.
+
+   If you aren't subscribed to netdev and/or are simply unsure if net-next
+   has re-opened yet, simply check the net-next git repository link above for
+   any new networking related commits.
+
+   The "net" tree continues to collect fixes for the vX.Y content, and
+   is fed back to Linus at regular (~weekly) intervals.  Meaning that the
+   focus for "net" is on stablilization and bugfixes.
+
+   Finally, the vX.Y gets released, and the whole cycle starts over.
+
+Q: So where are we now in this cycle?
+
+A: Load the mainline (Linus) page here:
+
+	http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git
+
+   and note the top of the "tags" section.  If it is rc1, it is early
+   in the dev cycle.  If it was tagged rc7 a week ago, then a release
+   is probably imminent.
+
+Q: How do I indicate which tree (net vs. net-next) my patch should be in?
+
+A: Firstly, think whether you have a bug fix or new "next-like" content.
+   Then once decided, assuming that you use git, use the prefix flag, i.e.
+
+	git format-patch --subject-prefix='PATCH net-next' start..finish
+
+   Use "net" instead of "net-next" (always lower case) in the above for
+   bug-fix net content.  If you don't use git, then note the only magic in
+   the above is just the subject text of the outgoing e-mail, and you can
+   manually change it yourself with whatever MUA you are comfortable with.
+
+Q: I sent a patch and I'm wondering what happened to it.  How can I tell
+   whether it got merged?
+
+A: Start by looking at the main patchworks queue for netdev:
+
+	http://patchwork.ozlabs.org/project/netdev/list/
+
+   The "State" field will tell you exactly where things are at with
+   your patch.
+
+Q: The above only says "Under Review".  How can I find out more?
+
+A: Generally speaking, the patches get triaged quickly (in less than 48h).
+   So be patient.  Asking the maintainer for status updates on your
+   patch is a good way to ensure your patch is ignored or pushed to
+   the bottom of the priority list.
+
+Q: How can I tell what patches are queued up for backporting to the
+   various stable releases?
+
+A: Normally Greg Kroah-Hartman collects stable commits himself, but
+   for networking, Dave collects up patches he deems critical for the
+   networking subsystem, and then hands them off to Greg.
+
+   There is a patchworks queue that you can see here:
+	http://patchwork.ozlabs.org/bundle/davem/stable/?state=*
+
+   It contains the patches which Dave has selected, but not yet handed
+   off to Greg.  If Greg already has the patch, then it will be here:
+	http://git.kernel.org/cgit/linux/kernel/git/stable/stable-queue.git
+
+   A quick way to find whether the patch is in this stable-queue is
+   to simply clone the repo, and then git grep the mainline commit ID, e.g.
+
+	stable-queue$ git grep -l 284041ef21fdf2e
+	releases/3.0.84/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
+	releases/3.4.51/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
+	releases/3.9.8/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
+	stable/stable-queue$
+
+Q: I see a network patch and I think it should be backported to stable.
+   Should I request it via "stable@vger.kernel.org" like the references in
+   the kernel's Documentation/stable_kernel_rules.txt file say?
+
+A: No, not for networking.  Check the stable queues as per above 1st to see
+   if it is already queued.  If not, then send a mail to netdev, listing
+   the upstream commit ID and why you think it should be a stable candidate.
+
+   Before you jump to go do the above, do note that the normal stable rules
+   in Documentation/stable_kernel_rules.txt still apply.  So you need to
+   explicitly indicate why it is a critical fix and exactly what users are
+   impacted.  In addition, you need to convince yourself that you _really_
+   think it has been overlooked, vs. having been considered and rejected.
+
+   Generally speaking, the longer it has had a chance to "soak" in mainline,
+   the better the odds that it is an OK candidate for stable.  So scrambling
+   to request a commit be added the day after it appears should be avoided.
+
+Q: I have created a network patch and I think it should be backported to
+   stable.  Should I add a "Cc: stable@vger.kernel.org" like the references
+   in the kernel's Documentation/ directory say?
+
+A: No.  See above answer.  In short, if you think it really belongs in
+   stable, then ensure you write a decent commit log that describes who
+   gets impacted by the bugfix and how it manifests itself, and when the
+   bug was introduced.  If you do that properly, then the commit will
+   get handled appropriately and most likely get put in the patchworks
+   stable queue if it really warrants it.
+
+   If you think there is some valid information relating to it being in
+   stable that does _not_ belong in the commit log, then use the three
+   dash marker line as described in Documentation/SubmittingPatches to
+   temporarily embed that information into the patch that you send.
+
+Q: Someone said that the comment style and coding convention is different
+   for the networking content.  Is this true?
+
+A: Yes, in a largely trivial way.  Instead of this:
+
+	/*
+	 * foobar blah blah blah
+	 * another line of text
+	 */
+
+   it is requested that you make it look like this:
+
+	/* foobar blah blah blah
+	 * another line of text
+	 */
+
+Q: I am working in existing code that has the former comment style and not the
+   latter.  Should I submit new code in the former style or the latter?
+
+A: Make it the latter style, so that eventually all code in the domain of
+   netdev is of this format.
+
+Q: I found a bug that might have possible security implications or similar.
+   Should I mail the main netdev maintainer off-list?
+
+A: No. The current netdev maintainer has consistently requested that people
+   use the mailing lists and not reach out directly.  If you aren't OK with
+   that, then perhaps consider mailing "security@kernel.org" or reading about
+   http://oss-security.openwall.org/wiki/mailing-lists/distros
+   as possible alternative mechanisms.
+
+Q: What level of testing is expected before I submit my change?
+
+A: If your changes are against net-next, the expectation is that you
+   have tested by layering your changes on top of net-next.  Ideally you
+   will have done run-time testing specific to your change, but at a
+   minimum, your changes should survive an "allyesconfig" and an
+   "allmodconfig" build without new warnings or failures.
+
+Q: Any other tips to help ensure my net/net-next patch gets OK'd?
+
+A: Attention to detail.  Re-read your own work as if you were the
+   reviewer.  You can start with using checkpatch.pl, perhaps even
+   with the "--strict" flag.  But do not be mindlessly robotic in
+   doing so.  If your change is a bug-fix, make sure your commit log
+   indicates the end-user visible symptom, the underlying reason as
+   to why it happens, and then if necessary, explain why the fix proposed
+   is the best way to get things done.   Don't mangle whitespace, and as
+   is common, don't mis-indent function arguments that span multiple lines.
+   If it is your 1st patch, mail it to yourself so you can test apply
+   it to an unpatched tree to confirm infrastructure didn't mangle it.
+
+   Finally, go back and read Documentation/SubmittingPatches to be
+   sure you are not repeating some common mistake documented there.
diff --git a/Documentation/networking/sctp.txt b/Documentation/networking/sctp.txt
index 0c790a7..97b810c 100644
--- a/Documentation/networking/sctp.txt
+++ b/Documentation/networking/sctp.txt
@@ -19,7 +19,6 @@ of SCTP that is RFC 2960 compliant and provides an programming interface
 referred to as the  UDP-style API of the Sockets Extensions for SCTP, as 
 proposed in IETF Internet-Drafts.    
 
-
 Caveats:  
 
 -lksctp can be built as statically or as a module.  However, be aware that 
@@ -33,6 +32,4 @@ For more information, please visit the lksctp project website:
    http://www.sf.net/projects/lksctp
 
 Or contact the lksctp developers through the mailing list:
-   <lksctp-developers@lists.sourceforge.net> 
-
-
+   <linux-sctp@vger.kernel.org>
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 052e13a..d2d7fc0 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -795,18 +795,97 @@ special GPIO-handler is registered.
 GPIO mode pitfalls
 ==================
 
-Sometime the developer may be confused by a datasheet talking about a pin
-being possible to set into "GPIO mode". It appears that what hardware
-engineers mean with "GPIO mode" is not necessarily the use case that is
-implied in the kernel interface <linux/gpio.h>: a pin that you grab from
-kernel code and then either listen for input or drive high/low to
-assert/deassert some external line.
+Due to the naming conventions used by hardware engineers, where "GPIO"
+is taken to mean different things than what the kernel does, the developer
+may be confused by a datasheet talking about a pin being possible to set
+into "GPIO mode". It appears that what hardware engineers mean with
+"GPIO mode" is not necessarily the use case that is implied in the kernel
+interface <linux/gpio.h>: a pin that you grab from kernel code and then
+either listen for input or drive high/low to assert/deassert some
+external line.
 
 Rather hardware engineers think that "GPIO mode" means that you can
 software-control a few electrical properties of the pin that you would
 not be able to control if the pin was in some other mode, such as muxed in
 for a device.
 
+The GPIO portions of a pin and its relation to a certain pin controller
+configuration and muxing logic can be constructed in several ways. Here
+are two examples:
+
+(A)
+                       pin config
+                       logic regs
+                       |               +- SPI
+     Physical pins --- pad --- pinmux -+- I2C
+                               |       +- mmc
+                               |       +- GPIO
+                               pin
+                               multiplex
+                               logic regs
+
+Here some electrical properties of the pin can be configured no matter
+whether the pin is used for GPIO or not. If you multiplex a GPIO onto a
+pin, you can also drive it high/low from "GPIO" registers.
+Alternatively, the pin can be controlled by a certain peripheral, while
+still applying desired pin config properties. GPIO functionality is thus
+orthogonal to any other device using the pin.
+
+In this arrangement the registers for the GPIO portions of the pin controller,
+or the registers for the GPIO hardware module are likely to reside in a
+separate memory range only intended for GPIO driving, and the register
+range dealing with pin config and pin multiplexing get placed into a
+different memory range and a separate section of the data sheet.
+
+(B)
+
+                       pin config
+                       logic regs
+                       |               +- SPI
+     Physical pins --- pad --- pinmux -+- I2C
+                       |       |       +- mmc
+                       |       |
+                       GPIO    pin
+                               multiplex
+                               logic regs
+
+In this arrangement, the GPIO functionality can always be enabled, such that
+e.g. a GPIO input can be used to "spy" on the SPI/I2C/MMC signal while it is
+pulsed out. It is likely possible to disrupt the traffic on the pin by doing
+wrong things on the GPIO block, as it is never really disconnected. It is
+possible that the GPIO, pin config and pin multiplex registers are placed into
+the same memory range and the same section of the data sheet, although that
+need not be the case.
+
+From a kernel point of view, however, these are different aspects of the
+hardware and shall be put into different subsystems:
+
+- Registers (or fields within registers) that control electrical
+  properties of the pin such as biasing and drive strength should be
+  exposed through the pinctrl subsystem, as "pin configuration" settings.
+
+- Registers (or fields within registers) that control muxing of signals
+  from various other HW blocks (e.g. I2C, MMC, or GPIO) onto pins should
+  be exposed through the pinctrl subssytem, as mux functions.
+
+- Registers (or fields within registers) that control GPIO functionality
+  such as setting a GPIO's output value, reading a GPIO's input value, or
+  setting GPIO pin direction should be exposed through the GPIO subsystem,
+  and if they also support interrupt capabilities, through the irqchip
+  abstraction.
+
+Depending on the exact HW register design, some functions exposed by the
+GPIO subsystem may call into the pinctrl subsystem in order to
+co-ordinate register settings across HW modules. In particular, this may
+be needed for HW with separate GPIO and pin controller HW modules, where
+e.g. GPIO direction is determined by a register in the pin controller HW
+module rather than the GPIO HW module.
+
+Electrical properties of the pin such as biasing and drive strength
+may be placed at some pin-specific register in all cases or as part
+of the GPIO register in case (B) especially. This doesn't mean that such
+properties necessarily pertain to what the Linux kernel calls "GPIO".
+
 Example: a pin is usually muxed in to be used as a UART TX line. But during
 system sleep, we need to put this pin into "GPIO mode" and ground it.
 
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 3e8cb73..22b4bc5 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -97,7 +97,7 @@ IPv4 addresses:
 
 	%pI4	1.2.3.4
 	%pi4	001.002.003.004
-	%p[Ii][hnbl]
+	%p[Ii]4[hnbl]
 
 	For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4'
 	specifiers result in a printed address with ('i4') or without ('I4')
diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt
index 717f5aa..28fbd87 100644
--- a/Documentation/rapidio/rapidio.txt
+++ b/Documentation/rapidio/rapidio.txt
@@ -300,7 +300,7 @@ initialization.
 -------------------------------------------
 
 RapidIO subsystem code organization allows addition of new enumeration/discovery
-methods as new configuration options without significant impact to to the core
+methods as new configuration options without significant impact to the core
 RapidIO code.
 
 A new enumeration/discovery method has to be attached to one or more mport
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 809d72b..a46ddb8 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -244,6 +244,7 @@ STAC9227/9228/9229/927x
   5stack-no-fp	D965 5stack without front panel
   dell-3stack	Dell Dimension E520
   dell-bios	Fixes with Dell BIOS setup
+  dell-bios-amic Fixes with Dell BIOS setup including analog mic
   volknob	Fixes with volume-knob widget 0x24
   auto		BIOS setup (default)
 
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index c3c912d..42a0a39 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -454,6 +454,8 @@ The generic parser supports the following hints:
 - need_dac_fix (bool): limits the DACs depending on the channel count
 - primary_hp (bool): probe headphone jacks as the primary outputs;
   default true
+- multi_io (bool): try probing multi-I/O config (e.g. shared
+  line-in/surround, mic/clfe jacks)
 - multi_cap_vol (bool): provide multiple capture volumes
 - inv_dmic_split (bool): provide split internal mic volume/switch for
   phase-inverted digital mics
diff --git a/Documentation/sound/alsa/compress_offload.txt b/Documentation/sound/alsa/compress_offload.txt
index 0bcc551..ac8d20b 100644
--- a/Documentation/sound/alsa/compress_offload.txt
+++ b/Documentation/sound/alsa/compress_offload.txt
@@ -73,7 +73,7 @@ The main requirements are:
 
 Design
 
-The new API shares a number of concepts with with the PCM API for flow
+The new API shares a number of concepts with the PCM API for flow
 control. Start, pause, resume, drain and stop commands have the same
 semantics no matter what the content is.
 
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 2331eb2..f21edb9 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -215,7 +215,7 @@ So for example arch/.../mach-*/board-*.c files might have code like:
 	/* if your mach-* infrastructure doesn't support kernels that can
 	 * run on multiple boards, pdata wouldn't benefit from "__init".
 	 */
-	static struct mysoc_spi_data __initdata pdata = { ... };
+	static struct mysoc_spi_data pdata __initdata = { ... };
 
 	static __init board_init(void)
 	{
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
index c1a1fd6..a5f985e 100644
--- a/Documentation/sysfs-rules.txt
+++ b/Documentation/sysfs-rules.txt
@@ -47,7 +47,7 @@ versions of the sysfs interface.
         at device creation and removal
       - the unique key to the device at that point in time
       - the kernel's path to the device directory without the leading
-        /sys, and always starting with with a slash
+        /sys, and always starting with a slash
       - all elements of a devpath must be real directories. Symlinks
         pointing to /sys/devices must always be resolved to their real
         target and the target path must be used to access the device.
diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py
index 3fe0d81..54d29c1 100755
--- a/Documentation/target/tcm_mod_builder.py
+++ b/Documentation/target/tcm_mod_builder.py
@@ -300,7 +300,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	int ret;\n\n"
 	buf += "	if (strstr(name, \"tpgt_\") != name)\n"
 	buf += "		return ERR_PTR(-EINVAL);\n"
-	buf += "	if (strict_strtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)\n"
+	buf += "	if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)\n"
 	buf += "		return ERR_PTR(-EINVAL);\n\n"
 	buf += "	tpg = kzalloc(sizeof(struct " + fabric_mod_name + "_tpg), GFP_KERNEL);\n"
 	buf += "	if (!tpg) {\n"
diff --git a/Documentation/timers/NO_HZ.txt b/Documentation/timers/NO_HZ.txt
index 8869758..cca122f 100644
--- a/Documentation/timers/NO_HZ.txt
+++ b/Documentation/timers/NO_HZ.txt
@@ -24,8 +24,8 @@ There are three main ways of managing scheduling-clock interrupts
 	workloads, you will normally -not- want this option.
 
 These three cases are described in the following three sections, followed
-by a third section on RCU-specific considerations and a fourth and final
-section listing known issues.
+by a third section on RCU-specific considerations, a fourth section
+discussing testing, and a fifth and final section listing known issues.
 
 
 NEVER OMIT SCHEDULING-CLOCK TICKS
@@ -121,14 +121,15 @@ boot parameter specifies the adaptive-ticks CPUs.  For example,
 "nohz_full=1,6-8" says that CPUs 1, 6, 7, and 8 are to be adaptive-ticks
 CPUs.  Note that you are prohibited from marking all of the CPUs as
 adaptive-tick CPUs:  At least one non-adaptive-tick CPU must remain
-online to handle timekeeping tasks in order to ensure that system calls
-like gettimeofday() returns accurate values on adaptive-tick CPUs.
-(This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no
-running user processes to observe slight drifts in clock rate.)
-Therefore, the boot CPU is prohibited from entering adaptive-ticks
-mode.  Specifying a "nohz_full=" mask that includes the boot CPU will
-result in a boot-time error message, and the boot CPU will be removed
-from the mask.
+online to handle timekeeping tasks in order to ensure that system
+calls like gettimeofday() returns accurate values on adaptive-tick CPUs.
+(This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running
+user processes to observe slight drifts in clock rate.)  Therefore, the
+boot CPU is prohibited from entering adaptive-ticks mode.  Specifying a
+"nohz_full=" mask that includes the boot CPU will result in a boot-time
+error message, and the boot CPU will be removed from the mask.  Note that
+this means that your system must have at least two CPUs in order for
+CONFIG_NO_HZ_FULL=y to do anything for you.
 
 Alternatively, the CONFIG_NO_HZ_FULL_ALL=y Kconfig parameter specifies
 that all CPUs other than the boot CPU are adaptive-ticks CPUs.  This
@@ -232,6 +233,29 @@ scheduler will decide where to run them, which might or might not be
 where you want them to run.
 
 
+TESTING
+
+So you enable all the OS-jitter features described in this document,
+but do not see any change in your workload's behavior.  Is this because
+your workload isn't affected that much by OS jitter, or is it because
+something else is in the way?  This section helps answer this question
+by providing a simple OS-jitter test suite, which is available on branch
+master of the following git archive:
+
+git://git.kernel.org/pub/scm/linux/kernel/git/frederic/dynticks-testing.git
+
+Clone this archive and follow the instructions in the README file.
+This test procedure will produce a trace that will allow you to evaluate
+whether or not you have succeeded in removing OS jitter from your system.
+If this trace shows that you have removed OS jitter as much as is
+possible, then you can conclude that your workload is not all that
+sensitive to OS jitter.
+
+Note: this test requires that your system have at least two CPUs.
+We do not currently have a good way to remove OS jitter from single-CPU
+systems.
+
+
 KNOWN ISSUES
 
 o	Dyntick-idle slows transitions to and from idle slightly.
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index b937c6e..ea2d35d 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -735,7 +735,7 @@ Here are the available options:
 		 function as well as the function being traced.
 
   print-parent:
-   bash-4000  [01]  1477.606694: simple_strtoul <-strict_strtoul
+   bash-4000  [01]  1477.606694: simple_strtoul <-kstrtoul
 
   noprint-parent:
    bash-4000  [01]  1477.606694: simple_strtoul
@@ -759,7 +759,7 @@ Here are the available options:
             latency-format option is enabled.
 
     bash  4000 1 0 00000000 00010a95 [58127d26] 1720.415ms \
-    (+0.000ms): simple_strtoul (strict_strtoul)
+    (+0.000ms): simple_strtoul (kstrtoul)
 
   raw - This will display raw numbers. This option is best for
 	use with user applications that can translate the raw
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index ef925ea..858aecf 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -53,7 +53,7 @@ incompatible change are allowed.  However, there is an extension
 facility that allows backward-compatible extensions to the API to be
 queried and used.
 
-The extension mechanism is not based on on the Linux version number.
+The extension mechanism is not based on the Linux version number.
 Instead, kvm defines extension identifiers and a facility to query
 whether a particular extension identifier is available.  If it is, a
 set of ioctls is available for application use.
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt
index a6ab4b6..67113f6 100644
--- a/Documentation/workqueue.txt
+++ b/Documentation/workqueue.txt
@@ -100,8 +100,8 @@ Subsystems and drivers can create and queue work items through special
 workqueue API functions as they see fit. They can influence some
 aspects of the way the work items are executed by setting flags on the
 workqueue they are putting the work item on. These flags include
-things like CPU locality, reentrancy, concurrency limits, priority and
-more.  To get a detailed overview refer to the API description of
+things like CPU locality, concurrency limits, priority and more.  To
+get a detailed overview refer to the API description of
 alloc_workqueue() below.
 
 When a work item is queued to a workqueue, the target gcwq and
@@ -166,16 +166,6 @@ resources, scheduled and executed.
 
 @flags:
 
-  WQ_NON_REENTRANT
-
-	By default, a wq guarantees non-reentrance only on the same
-	CPU.  A work item may not be executed concurrently on the same
-	CPU by multiple workers but is allowed to be executed
-	concurrently on multiple CPUs.  This flag makes sure
-	non-reentrance is enforced across all CPUs.  Work items queued
-	to a non-reentrant wq are guaranteed to be executed by at most
-	one worker system-wide at any given time.
-
   WQ_UNBOUND
 
 	Work items queued to an unbound wq are served by a special
@@ -233,6 +223,10 @@ resources, scheduled and executed.
 
 	This flag is meaningless for unbound wq.
 
+Note that the flag WQ_NON_REENTRANT no longer exists as all workqueues
+are now non-reentrant - any work item is guaranteed to be executed by
+at most one worker system-wide at any given time.
+
 @max_active:
 
 @max_active determines the maximum number of execution contexts per
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index fc66d42..f4f268c 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -58,7 +58,7 @@ Protocol 2.11:	(Kernel 3.6) Added a field for offset of EFI handover
 		protocol entry point.
 
 Protocol 2.12:	(Kernel 3.8) Added the xloadflags field and extension fields
-	 	to struct boot_params for for loading bzImage and ramdisk
+	 	to struct boot_params for loading bzImage and ramdisk
 		above 4G in 64bit.
 
 **** MEMORY LAYOUT
diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
index e9e8ddb..1228b22 100644
--- a/Documentation/x86/x86_64/boot-options.txt
+++ b/Documentation/x86/x86_64/boot-options.txt
@@ -176,6 +176,11 @@ ACPI
 
   acpi=noirq	Don't route interrupts
 
+  acpi=nocmcff	Disable firmware first mode for corrected errors. This
+		disables parsing the HEST CMC error source to check if
+		firmware has set the FF flag. This may result in
+		duplicate corrected error reports.
+
 PCI
 
   pci=off		Don't use PCI
diff --git a/MAINTAINERS b/MAINTAINERS
index defc053..cd1b287 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -813,7 +813,7 @@ F:	arch/arm/mach-prima2/
 F:	drivers/dma/sirf-dma.c
 F:	drivers/i2c/busses/i2c-sirf.c
 F:	drivers/mmc/host/sdhci-sirf.c
-F:	drivers/pinctrl/pinctrl-sirf.c
+F:	drivers/pinctrl/sirf/
 F:	drivers/spi/spi-sirf.c
 
 ARM/EBSA110 MACHINE SUPPORT
@@ -965,6 +965,12 @@ M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 
+ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
+M:	Santosh Shilimkar <santosh.shilimkar@ti.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-keystone/
+
 ARM/LOGICPD PXA270 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1003,7 +1009,7 @@ F:	arch/arm/mach-orion5x/ts78xx-*
 ARM/MICREL KS8695 ARCHITECTURE
 M:	Greg Ungerer <gerg@uclinux.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-F:	arch/arm/mach-ks8695
+F:	arch/arm/mach-ks8695/
 S:	Odd Fixes
 
 ARM/MIOA701 MACHINE SUPPORT
@@ -1023,7 +1029,6 @@ M:	STEricsson <STEricsson_nomadik_linux@list.st.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-nomadik/
-F:	arch/arm/plat-nomadik/
 F:	drivers/i2c/busses/i2c-nomadik.c
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
 
@@ -1045,7 +1050,7 @@ F:	drivers/mmc/host/msm_sdcc.h
 F:	drivers/tty/serial/msm_serial.h
 F:	drivers/tty/serial/msm_serial.c
 F:	drivers/*/pm8???-*
-F:	drivers/ssbi/
+F:	drivers/mfd/ssbi/
 F:	include/linux/mfd/pm8xxx/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
 S:	Maintained
@@ -1131,7 +1136,6 @@ L:	linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 W:	http://www.fluff.org/ben/linux/
 S:	Maintained
 F:	arch/arm/plat-samsung/
-F:	arch/arm/plat-s3c24xx/
 F:	arch/arm/mach-s3c24*/
 F:	arch/arm/mach-s3c64xx/
 F:	drivers/*/*s3c2410*
@@ -1154,8 +1158,6 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-s5pv210/mach-aquila.c
 F:	arch/arm/mach-s5pv210/mach-goni.c
-F:	arch/arm/mach-exynos/mach-universal_c210.c
-F:	arch/arm/mach-exynos/mach-nuri.c
 
 ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
 M:	Kyungmin Park <kyungmin.park@samsung.com>
@@ -1259,7 +1261,6 @@ F:	drivers/rtc/rtc-coh901331.c
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
 ARM/Ux500 ARM ARCHITECTURE
-M:	Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
 M:	Linus Walleij <linus.walleij@linaro.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
@@ -1296,13 +1297,12 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-vt8500/
 F:	drivers/clocksource/vt8500_timer.c
-F:	drivers/gpio/gpio-vt8500.c
 F:	drivers/i2c/busses/i2c-wmt.c
 F:	drivers/mmc/host/wmt-sdmmc.c
 F:	drivers/pwm/pwm-vt8500.c
 F:	drivers/rtc/rtc-vt8500.c
 F:	drivers/tty/serial/vt8500_serial.c
-F:	drivers/usb/host/ehci-vt8500.c
+F:	drivers/usb/host/ehci-platform.c
 F:	drivers/usb/host/uhci-platform.c
 F:	drivers/video/vt8500lcdfb.*
 F:	drivers/video/wm8505fb*
@@ -1785,6 +1785,17 @@ L:	netdev@vger.kernel.org
 S:	Supported
 F:	drivers/net/ethernet/broadcom/bnx2x/
 
+BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
+M:	Christian Daudt <csd@broadcom.com>
+T:	git git://git.github.com/broadcom/bcm11351
+S:	Maintained
+F:	arch/arm/mach-bcm/
+F:	arch/arm/boot/dts/bcm113*
+F:	arch/arm/boot/dts/bcm281*
+F:	arch/arm/configs/bcm_defconfig
+F:	drivers/mmc/host/sdhci_bcm_kona.c
+F:	drivers/clocksource/bcm_kona_timer.c
+
 BROADCOM BCM2835 ARM ARCHICTURE
 M:	Stephen Warren <swarren@wwwdotorg.org>
 L:	linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1999,10 +2010,10 @@ W:	http://ceph.com/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
 S:	Supported
 F:	Documentation/filesystems/ceph.txt
-F:	fs/ceph
-F:	net/ceph
-F:	include/linux/ceph
-F:	include/linux/crush
+F:	fs/ceph/
+F:	net/ceph/
+F:	include/linux/ceph/
+F:	include/linux/crush/
 
 CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
 L:	linux-usb@vger.kernel.org
@@ -2107,6 +2118,13 @@ M:	Russell King <linux@arm.linux.org.uk>
 S:	Maintained
 F:	include/linux/clk.h
 
+CLOCKSOURCE, CLOCKEVENT DRIVERS
+M:	Daniel Lezcano <daniel.lezcano@linaro.org>
+M:	Thomas Gleixner <tglx@linutronix.de>
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
+S:	Supported
+F:	drivers/clocksource
+
 CISCO FCOE HBA DRIVER
 M:	Hiral Patel <hiralpat@cisco.com>
 M:	Suma Ramars <sramars@cisco.com>
@@ -2282,7 +2300,7 @@ CPU POWER MONITORING SUBSYSTEM
 M:	Dominik Brodowski <linux@dominikbrodowski.net>
 M:	Thomas Renninger <trenn@suse.de>
 S:	Maintained
-F:	tools/power/cpupower
+F:	tools/power/cpupower/
 
 CPUSETS
 M:	Li Zefan <lizefan@huawei.com>
@@ -2720,7 +2738,7 @@ L:	intel-gfx@lists.freedesktop.org
 L:	dri-devel@lists.freedesktop.org
 T:	git git://people.freedesktop.org/~danvet/drm-intel
 S:	Supported
-F:	drivers/gpu/drm/i915
+F:	drivers/gpu/drm/i915/
 F:	include/drm/i915*
 F:	include/uapi/drm/i915*
 
@@ -2732,7 +2750,7 @@ M:	Kyungmin Park <kyungmin.park@samsung.com>
 L:	dri-devel@lists.freedesktop.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
 S:	Supported
-F:	drivers/gpu/drm/exynos
+F:	drivers/gpu/drm/exynos/
 F:	include/drm/exynos*
 F:	include/uapi/drm/exynos*
 
@@ -2985,7 +3003,7 @@ M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
-F:	drivers/edac/ghes-edac.c
+F:	drivers/edac/ghes_edac.c
 
 EDAC-I82443BXGX
 M:	Tim Small <tim@buttersideup.com>
@@ -3591,8 +3609,8 @@ M:	Arnd Bergmann <arnd@arndb.de>
 L:	linux-arch@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
 S:	Maintained
-F:	include/asm-generic
-F:	include/uapi/asm-generic
+F:	include/asm-generic/
+F:	include/uapi/asm-generic/
 
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
@@ -3634,7 +3652,8 @@ GRE DEMULTIPLEXER DRIVER
 M:	Dmitry Kozlov <xeb@mail.ru>
 L:	netdev@vger.kernel.org
 S:	Maintained
-F:	net/ipv4/gre.c
+F:	net/ipv4/gre_demux.c
+F:	net/ipv4/gre_offload.c
 F:	include/net/gre.h
 
 GRETH 10/100/1G Ethernet MAC device driver
@@ -3712,7 +3731,7 @@ L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
 S:	Odd Fixes
-F:	drivers/media/usb/hdpvr
+F:	drivers/media/usb/hdpvr/
 
 HWPOISON MEMORY FAILURE HANDLING
 M:	Andi Kleen <andi@firstfloor.org>
@@ -4360,7 +4379,7 @@ F:	drivers/net/wireless/iwlegacy/
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
 M:	Johannes Berg <johannes.berg@intel.com>
-M:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
+M:	Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 M:	Intel Linux Wireless <ilw@linux.intel.com>
 L:	linux-wireless@vger.kernel.org
 W:	http://intellinuxwireless.org
@@ -4513,7 +4532,7 @@ S:	Supported
 W:	http://www.openfabrics.org
 W:	www.open-iscsi.org
 Q:	http://patchwork.kernel.org/project/linux-rdma/list/
-F:	drivers/infiniband/ulp/iser
+F:	drivers/infiniband/ulp/iser/
 
 ISDN SUBSYSTEM
 M:	Karsten Keil <isdn@linux-pingi.de>
@@ -4567,7 +4586,7 @@ W:	http://palosaari.fi/linux/
 Q:	http://patchwork.linuxtv.org/project/linux-media/list/
 T:	git git://linuxtv.org/anttip/media_tree.git
 S:	Maintained
-F:	drivers/media/tuners/it913x*
+F:	drivers/media/tuners/tuner_it913x*
 
 IVTV VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
@@ -5391,6 +5410,7 @@ F:	drivers/watchdog/mena21_wdt.c
 
 METAG ARCHITECTURE
 M:	James Hogan <james.hogan@imgtec.com>
+L:	linux-metag@vger.kernel.org
 S:	Supported
 F:	arch/metag/
 F:	Documentation/metag/
@@ -5900,15 +5920,12 @@ S:	Maintained
 F:	arch/arm/*omap*/*pm*
 F:	drivers/cpufreq/omap-cpufreq.c
 
-OMAP POWERDOMAIN/CLOCKDOMAIN SOC ADAPTATION LAYER SUPPORT
+OMAP POWERDOMAIN SOC ADAPTATION LAYER SUPPORT
 M:	Rajendra Nayak <rnayak@ti.com>
 M:	Paul Walmsley <paul@pwsan.com>
 L:	linux-omap@vger.kernel.org
 S:	Maintained
-F:	arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
-F:	arch/arm/mach-omap2/powerdomain44xx.c
-F:	arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
-F:	arch/arm/mach-omap2/clockdomain44xx.c
+F:	arch/arm/mach-omap2/prm*
 
 OMAP AUDIO SUPPORT
 M:	Peter Ujfalusi <peter.ujfalusi@ti.com>
@@ -6074,7 +6091,7 @@ W:	http://openrisc.net
 L:	linux@lists.openrisc.net (moderated for non-subscribers)
 S:	Maintained
 T:	git git://openrisc.net/~jonas/linux
-F:	arch/openrisc
+F:	arch/openrisc/
 
 OPENVSWITCH
 M:	Jesse Gross <jesse@nicira.com>
@@ -6358,7 +6375,7 @@ M:	Jamie Iles <jamie@jamieiles.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:	git git://github.com/jamieiles/linux-2.6-ji.git
 S:	Supported
-F:	arch/arm/mach-picoxcell
+F:	arch/arm/mach-picoxcell/
 F:	drivers/*/picoxcell*
 F:	drivers/*/*/picoxcell*
 
@@ -6631,7 +6648,7 @@ F:	drivers/spi/spi-pxa2xx*
 F:	drivers/usb/gadget/pxa2*
 F:	include/sound/pxa2xx-lib.h
 F:	sound/arm/pxa*
-F:	sound/soc/pxa
+F:	sound/soc/pxa/
 
 MMP SUPPORT
 M:	Eric Miao <eric.y.miao@gmail.com>
@@ -7076,7 +7093,7 @@ SAMSUNG AUDIO (ASoC) DRIVERS
 M:	Sangbeom Kim <sbkim73@samsung.com>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Supported
-F:	sound/soc/samsung
+F:	sound/soc/samsung/
 
 SAMSUNG FRAMEBUFFER DRIVER
 M:	Jingoo Han <jg1.han@samsung.com>
@@ -7122,10 +7139,11 @@ SERIAL DRIVERS
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:	linux-serial@vger.kernel.org
 S:	Maintained
-F:	drivers/tty/serial
+F:	drivers/tty/serial/
 
 SYNOPSYS DESIGNWARE DMAC DRIVER
 M:	Viresh Kumar <viresh.linux@gmail.com>
+M:	Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 S:	Maintained
 F:	include/linux/dw_dmac.h
 F:	drivers/dma/dw/
@@ -7138,7 +7156,7 @@ S:	Maintained
 F:	include/linux/mmc/dw_mmc.h
 F:	drivers/mmc/host/dw_mmc*
 
-TIMEKEEPING, NTP
+TIMEKEEPING, CLOCKSOURCE CORE, NTP
 M:	John Stultz <john.stultz@linaro.org>
 M:	Thomas Gleixner <tglx@linutronix.de>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
@@ -7151,13 +7169,12 @@ F:	include/uapi/linux/timex.h
 F:	kernel/time/clocksource.c
 F:	kernel/time/time*.c
 F:	kernel/time/ntp.c
-F:	drivers/clocksource
 
 TLG2300 VIDEO4LINUX-2 DRIVER
 M:	Huang Shijie <shijie8@gmail.com>
 M:	Hans Verkuil <hverkuil@xs4all.nl>
 S:	Odd Fixes
-F:	drivers/media/usb/tlg2300
+F:	drivers/media/usb/tlg2300/
 
 SC1200 WDT DRIVER
 M:	Zwane Mwaikambo <zwane@arm.linux.org.uk>
@@ -7231,6 +7248,7 @@ W:	http://lksctp.sourceforge.net
 S:	Maintained
 F:	Documentation/networking/sctp.txt
 F:	include/linux/sctp.h
+F:	include/uapi/linux/sctp.h
 F:	include/net/sctp/
 F:	net/sctp/
 
@@ -7417,7 +7435,7 @@ L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
 S:	Odd Fixes
-F:	drivers/media/radio/radio-si4713.h
+F:	drivers/media/radio/radio-si4713.c
 
 SIANO DVB DRIVER
 M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
@@ -7426,9 +7444,9 @@ W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
 S:	Odd fixes
 F:	drivers/media/common/siano/
-F:	drivers/media/dvb/siano/
 F:	drivers/media/usb/siano/
-F:	drivers/media/mmc/siano
+F:	drivers/media/usb/siano/
+F:	drivers/media/mmc/siano/
 
 SH_VEU V4L2 MEM2MEM DRIVER
 M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
@@ -7466,9 +7484,9 @@ P:	Vincent Sanders <vince@simtec.co.uk>
 M:	Simtec Linux Team <linux@simtec.co.uk>
 W:	http://www.simtec.co.uk/products/EB2410ITX/
 S:	Supported
-F:	arch/arm/mach-s3c2410/mach-bast.c
-F:	arch/arm/mach-s3c2410/bast-ide.c
-F:	arch/arm/mach-s3c2410/bast-irq.c
+F:	arch/arm/mach-s3c24xx/mach-bast.c
+F:	arch/arm/mach-s3c24xx/bast-ide.c
+F:	arch/arm/mach-s3c24xx/bast-irq.c
 
 TI DAVINCI MACHINE SUPPORT
 M:	Sekhar Nori <nsekhar@ti.com>
@@ -7477,7 +7495,7 @@ L:	davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers
 T:	git git://gitorious.org/linux-davinci/linux-davinci.git
 Q:	http://patchwork.kernel.org/project/linux-davinci/list/
 S:	Supported
-F:	arch/arm/mach-davinci
+F:	arch/arm/mach-davinci/
 F:	drivers/i2c/busses/i2c-davinci.c
 
 TI DAVINCI SERIES MEDIA DRIVER
@@ -7554,7 +7572,7 @@ SMIA AND SMIA++ IMAGE SENSOR DRIVER
 M:	Sakari Ailus <sakari.ailus@iki.fi>
 L:	linux-media@vger.kernel.org
 S:	Maintained
-F:	drivers/media/i2c/smiapp
+F:	drivers/media/i2c/smiapp/
 F:	include/media/smiapp.h
 F:	drivers/media/i2c/smiapp-pll.c
 F:	drivers/media/i2c/smiapp-pll.h
@@ -7657,6 +7675,11 @@ W:	http://tifmxx.berlios.de/
 S:	Maintained
 F:	drivers/memstick/host/tifm_ms.c
 
+SONY MEMORYSTICK STANDARD SUPPORT
+M:	Maxim Levitsky <maximlevitsky@gmail.com>
+S:	Maintained
+F:	drivers/memstick/core/ms_block.*
+
 SOUND
 M:	Jaroslav Kysela <perex@perex.cz>
 M:	Takashi Iwai <tiwai@suse.de>
@@ -7721,35 +7744,7 @@ L:	spear-devel@list.st.com
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:	http://www.st.com/spear
 S:	Maintained
-F:	arch/arm/plat-spear/
-
-SPEAR13XX MACHINE SUPPORT
-M:	Viresh Kumar <viresh.linux@gmail.com>
-M:	Shiraz Hashim <shiraz.hashim@st.com>
-L:	spear-devel@list.st.com
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.st.com/spear
-S:	Maintained
-F:	arch/arm/mach-spear13xx/
-
-SPEAR3XX MACHINE SUPPORT
-M:	Viresh Kumar <viresh.linux@gmail.com>
-M:	Shiraz Hashim <shiraz.hashim@st.com>
-L:	spear-devel@list.st.com
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.st.com/spear
-S:	Maintained
-F:	arch/arm/mach-spear3xx/
-
-SPEAR6XX MACHINE SUPPORT
-M:	Rajeev Kumar <rajeev-dlh.kumar@st.com>
-M:	Shiraz Hashim <shiraz.hashim@st.com>
-M:	Viresh Kumar <viresh.linux@gmail.com>
-L:	spear-devel@list.st.com
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.st.com/spear
-S:	Maintained
-F:	arch/arm/mach-spear6xx/
+F:	arch/arm/mach-spear/
 
 SPEAR CLOCK FRAMEWORK SUPPORT
 M:	Viresh Kumar <viresh.linux@gmail.com>
@@ -8012,7 +8007,7 @@ M:	Vineet Gupta <vgupta@synopsys.com>
 S:	Supported
 F:	arch/arc/
 F:	Documentation/devicetree/bindings/arc/
-F:	drivers/tty/serial/arc-uart.c
+F:	drivers/tty/serial/arc_uart.c
 
 SYSV FILESYSTEM
 M:	Christoph Hellwig <hch@infradead.org>
@@ -8302,9 +8297,13 @@ M:	Chris Metcalf <cmetcalf@tilera.com>
 W:	http://www.tilera.com/scm/
 S:	Supported
 F:	arch/tile/
-F:	drivers/tty/hvc/hvc_tile.c
-F:	drivers/net/ethernet/tile/
+F:	drivers/char/tile-srom.c
 F:	drivers/edac/tile_edac.c
+F:	drivers/net/ethernet/tile/
+F:	drivers/rtc/rtc-tile.c
+F:	drivers/tty/hvc/hvc_tile.c
+F:	drivers/usb/host/*-tilegx.c
+F:	include/linux/usb/tilegx.h
 
 TLAN NETWORK DRIVER
 M:	Samuel Chessman <chessman@tux.org>
@@ -8664,6 +8663,11 @@ T:	git git://git.alsa-project.org/alsa-kernel.git
 S:	Maintained
 F:	sound/usb/midi.*
 
+USB NETWORKING DRIVERS
+L:	linux-usb@vger.kernel.org
+S:	Odd Fixes
+F:	drivers/net/usb/
+
 USB OHCI DRIVER
 M:	Alan Stern <stern@rowland.harvard.edu>
 L:	linux-usb@vger.kernel.org
@@ -8692,7 +8696,6 @@ L:	linux-usb@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:	Maintained
 F:	drivers/usb/phy/
-F:	drivers/usb/otg/
 
 USB PRINTER DRIVER (usblp)
 M:	Pete Zaitcev <zaitcev@redhat.com>
@@ -8793,7 +8796,6 @@ W:	http://www.linux-usb.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
 S:	Supported
 F:	Documentation/usb/
-F:	drivers/net/usb/
 F:	drivers/usb/
 F:	include/linux/usb.h
 F:	include/linux/usb/
@@ -9218,7 +9220,7 @@ M:	Matthew Garrett <matthew.garrett@nebula.com>
 L:	platform-driver-x86@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
 S:	Maintained
-F:	drivers/platform/x86
+F:	drivers/platform/x86/
 
 X86 MCE INFRASTRUCTURE
 M:	Tony Luck <tony.luck@intel.com>
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 0000000..3090409
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,224 @@
+Name		SHA1
+----		----
+origin		6c2580c501c660fdfb506061e016d84570fceba1
+fixes		b3a3a9c441e2c8f6b6760de9331023a7906a4ac6
+kbuild-current	ad81f0545ef01ea651886dddac4bef6cec930092
+arc-current	c095ba7224d8edc71dcef0d655911399a8bd4a3f
+arm-current	e35ac62d2202e31307c0f9b278a61e484c4727f2
+m68k-current	ad81f0545ef01ea651886dddac4bef6cec930092
+metag-fixes	dfe248b18fe29ce5a59c60364a4c27e88cb65b0e
+powerpc-merge	fe956a1d4081ce1a959f87df397a15e252201f10
+sparc		1c2696cdaad84580545a2e9c0879ff597880b1a9
+net		75848d338cdecec206018e8b49fe081c624c200d
+ipsec		01cb71d2d47b78354358e4bb938bb06323e17498
+sound-current	57e6dae1087bbaa6b33d3dd8a8e90b63888939a3
+pci-current	36dd1f3e02a4aed850a7b7318d7abd4f4d50528c
+wireless	5a6e0cf70743f30c17ccb5f228db9a124b0e7477
+driver-core.current	5ae90d8e467e625e447000cb4335c4db973b1095
+tty.current	c095ba7224d8edc71dcef0d655911399a8bd4a3f
+usb.current	444ce9d44d00969479aa1d2675f305a779369194
+staging.current	cefe8a32f2a5887246ed250115e34bee6ecc8d61
+char-misc.current	5ae90d8e467e625e447000cb4335c4db973b1095
+input-current	88ce3c3ca3df754e8a2a63b01c38bd1667fcae70
+md-current	f94c0b6658c7edea8bc19d13be321e3860a3fa54
+audit-current	c158a35c8a681cf68d36f22f058f9f5466386c71
+crypto-current	e70308ec0e4bff344fcfdf160de40e1150552c5f
+ide		6d128e1e72bf082542e85f72e6b7ddd704193588
+dwmw2		5950f0803ca9d396ab79b7fe6789351f96e1d8d5
+sh-current	44033109e99cf584d6285226ed521098f5ef7250
+devicetree-current	cf9e2368655d86cd800e4d9fe65a407b39d29373
+rr-fixes	aa52aeea2725839bdd3dcce394486e9a043065e0
+mfd-fixes	5649d8f9e335f2b093751fcc2bdd5953f79f66ef
+vfio-fixes	d24cdbfd28b7e0ffecb1e281d73e73c03a57f734
+drm-intel-fixes	3f577573cd5482a32f85bd131e52f7cb4b9ac518
+asm-generic	fb9de7ebc3a2eb7ddb83c92e288447a0c313bced
+arc		a00b92e08e7591b12634201cffec458b7596b5fd
+arm		bb32e3d4491fe1837595dc8787bdc2de7f03a4e3
+arm-perf	ad81f0545ef01ea651886dddac4bef6cec930092
+davinci		fe0d42203cb5616eeff68b14576a0f7e2dd56625
+xilinx		b028161fbba178ccd35aa69051c04d7673fe9d80
+arm64		845ad05ec31e0f3872a321e10dbeaf872022632c
+blackfin	eb043d36ace4b4720020fdef9e94854c549adda7
+c6x		f934af05cb1bf20558542185299394a69060b829
+cris		32ade6a282a36aae1803b190bae452f1e46f6b6c
+hexagon		de44443a45e36b7467af2518d3bf7ec6ec909549
+ia64		9c510f75fd453b101cb165c95ccfb45c4cac7d56
+m68k		ad81f0545ef01ea651886dddac4bef6cec930092
+m68knommu	5fbed81f0e0fee9ce9b03e33e8c753628d5ccdaf
+metag		8a697827540d54443f343b058b8dac695c847f9f
+microblaze	a9b9d229cdeb627f0954049c4a57ce57bd25c166
+mips		3e7522bfd44b298f3e5d58e69c613bfe8d34e430
+openrisc	6af609515d788bd4c94116344f00601b058f75a6
+parisc		6c700d71f7faecb540b3fa4303edb5323a2768c1
+parisc-hd	9f0f4fb0de4be2adde060167b0effa54264f184f
+powerpc		3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b
+4xx		2074b1d9d53ae696dd3f49482bad43254f40f01d
+mpc5xxx		dd0120dea601de654a5a6d959da3a632a02200f0
+galak		9e2ecdbba3b0745f9ed454ab86961e3ccf9dc224
+s390		6d7e8d898cde867941204d48b805bd1d1776e1e0
+sh		37284bd93103ae36b5ea274a985d688fb16f7a38
+sparc-next	f8ce1faf55955de62e0a12e330c6d9a526071f65
+tile		bb94fb98cf8c8d8564daa8f0789569d5fd6fbc31
+unicore32	c284464658acab50c67ff65ff3dc9215a0231ad2
+xtensa		3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b
+btrfs		cbacd76bb3d2295478aa13015fdd302757297e88
+ceph		71b43258fca50da88f9d800c7f05ccc742dc7937
+cifs		757c4f6260febff982276818bb946df89c1105aa
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	07bc9dc1b01bad7084fed3d2659e5d83317869bc
+ext3		e729eac6f65e11c5f03b09adcc84bd5bcb230467
+ext4		533ec0ed5bac34233087f0c10c698d20095d6628
+f2fs		c2d715d144af7209d035d0fe0b20a7a591c22c21
+fscache		bcd7351e83728859833e3c5b8aae9a2816914e4b
+fuse		c7263bcdc4d150e3c718b711a5f6fad496d9f662
+gfs2		7f59503f567c1ea89515fd91d41ad401241b6e64
+jfs		eb8630d7d2fd13589e6a7a3ae2fe1f75f867fbed
+logfs		339466142b3f58fe0ee4dea7e8c5f3d33099e89c
+nfs		44c6a84d158be801548bd20e353db596b84f7fc4
+nfsd		df66e75395c839c3a373bae897dbb1248f741b45
+ocfs2		4538df64655dcfe17b33080b219dc783161a262e
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	4b0180a49f08dd1c681cdc99edc9e0cec0a833fa
+v9fs		b3f8ab4b7953b4719aaa00c22c1de5d9161f57f5
+ubifs		beadadfa5467e09e36891f39cae1f5d8d3bbf17e
+xfs		7a378c9aeab3782a5f998c17313bc7027cee3454
+vfs		d405be48a4c3f37f7a8e5648a5db204738272c61
+pci		e3ec221b9370e964b9e001788bc68766469191a5
+hid		920dea824041827c9ae786180fae0e63d5c13d31
+i2c		2806914f5d027c225c7562a0f2dd7e20c3ba8beb
+jdelvare-hwmon	6f7e0b6faf221b03c410d13a6f81c054530b3bd3
+hwmon-staging	abb749c1889004a82fb00f088518908db2112d1e
+v4l-dvb		e5c914639583b386d42e5407ca7acc0384ace289
+kbuild		8de6aeb7b3c83a870078fcbf561923c268690168
+kconfig		4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb
+libata		3ea47c0bdde8f74b864456802eda89d15f4b3e7e
+pstore		bd08ec33b5c23833581e5a36b2a69ccae6b39a28
+pm		38fcf542987398ef56e13e49fa70baf720343dfb
+idle		5c99726b5faaf1ba4ca80c39d319f419c227f803
+apm		fb9d78aca709b7a6389c79d6211fb384c69bb79f
+cpupowerutils	f16603386b38c28979f4df1cafdc2fe73fa87d37
+thermal		ace120dcf23b3bbba00d797a898481997381052f
+ieee1394	0a41981803fcd4107fff4e943afb72940ba653d2
+ubi		83ff59a066637a6c28844bbf43009459408240f4
+dlm		ededf305a8d843c12038ae48eb68529016b3e91f
+swiotlb		af51a9f1848ff50079a10def56a2c064f326af22
+slave-dma	2194971ca44cc567815ba0224a66559eb90c503c
+dmaengine	41ef2d5678d83af030125550329b6ae8b74618fa
+net-next	09effa67a18d893fc4e6f81a3659fc9efef1445e
+ipsec-next	af83fde7513b6c4acd869ad4fb93893704439470
+wireless-next	2952f6ef5195ea76279f7370f0a6571867e54438
+bluetooth	473c13179c5828f7123a4d9fe449d8bd79fae254
+infiniband	569935db80fd5338005d977ffc3428d43aad84ba
+mtd		e79265ba6bdb31437bd4c3e7911950f9d1262a07
+l2-mtd		a789b9a602d63634dd7cd4bc9a72036a3a9b485c
+crypto		032c8cacc702da8a53c24d24a4e3c3a572a34078
+drm		00fd78e5279aec3aa504307ff2db892d3efb555d
+drm-intel	6d2b888569d366beb4be72cacfde41adee2c25e1
+drm-tegra	ebae30b1fbcc2cc991ce705cc82e16d1e5ddbf51
+sound		663819fb7d7e21f45431db1a2c0180bf2388ed2f
+sound-asoc	49ca8bb5e49362b1f5cc48e0f36d6e767e9c2b35
+modules		ad81f0545ef01ea651886dddac4bef6cec930092
+virtio		3f0d0c9b47e09d47fcb755fed786a1ee88e110b5
+input		46146e7d4b383d5b34014d072553498c7cd52821
+input-mt	ad81f0545ef01ea651886dddac4bef6cec930092
+cgroup		f00eaaaae47646ccc1c9b11c1727a81b01c3eda2
+block		3fe9649223d270a8eb2f649fa119b1995fe6b53d
+device-mapper	ad81f0545ef01ea651886dddac4bef6cec930092
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		80af9e6d7ae633309cc5bca96aee6a45117e7c98
+mmc		6d1d6b4759112acf4c079eb3a0dd296bdbf61cf5
+kgdb		6bedf31c25dd93c4f70a28e9ab94a239a5fb592c
+slab		0450b0ceeaffa02e4436cdd5c890f52560f97023
+uclinux		6dbe51c251a327e012439c4772097a13df43c5b8
+md		5ad58b4cd0391ea9a6905c8d986a31cf809d5320
+mfd		38c4faaea4ca71c69584ef71cca8d0735d5361c1
+mfd-lj		ec10436556ab2378ed54a6805f3f1711c05426b4
+battery		5a6c2208455f25b3e6f939adc2da59aa00d4806e
+fbdev		5e8be022fb5b8badb033940cb807dff0112042b6
+viafb		838ac785d521e091bd8b5f6a2b545166f5f32b77
+omap_dss2	fb52566873ca8c7006948b9d51c7f3fbcc0b1116
+regulator	4dc3ef73176f6163257ec3424a2a8b421e4c899d
+security	9548906b2bb7ff09e12c013a55d669bef2c8e121
+selinux		2be4d74f2fd45460d70d4fe65cc1972ef45bf849
+lblnet		07bc9dc1b01bad7084fed3d2659e5d83317869bc
+watchdog	b3a3a9c441e2c8f6b6760de9331023a7906a4ac6
+dwmw2-iommu	6491d4d02893d9787ba67279595990217177b351
+iommu		01ce784acfa69a171afe6ec3f85a959546f2d18a
+vfio		6cdd97821322352b94bb92f271b4466ad38a2468
+osd		861d66601acda6d7a2038fb3c95f68009128003a
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+trivial		ccb7cc00774457ee0064c278a1bed4b9685364d3
+audit		dcd6c92267155e70a94b3927bce681ce74b80d1f
+fsnotify	1ca39ab9d21ac93f94b9e3eb364ea9a5cf2aba06
+edac		de4772c621487fd4cadb4138f2481297c8e0cb0d
+edac-amd	f0a56c480196a98479760862468cc95879df3de0
+devicetree	245d9641909aee2e73fc773cea708eb7bc51a524
+dt-rh		d683b96b072dc4680fc74964eca77e6a23d1fa6e
+spi		300f53d0f683b78310f0bc8173388406f407c057
+tip		ef85938077674b176ae9bbe605fcf9dcc62428bc
+ftrace		9457158bbc0ee04ecef76862d73eecd8076e9c7b
+rcu		4cd7ecca0cf6b3e81c8606fa0e5d943040021abe
+cputime		c3e0ef9a298e028a82ada28101ccd5cf64d209ee
+uprobes		0326f5a94ddea33fa331b2519f4172f4fb387baa
+kvm		bf640876e21fe603f7f52b0c27d66b7716da0384
+kvm-arm		8bd4ffd6b3a98f00267051dc095076ea2ff06ea8
+kvm-ppc		20f7462aac0b220c56231a15abec9ab99e897136
+oprofile	f722406faae2d073cc1d01063d1123c35425939e
+fw-nohz		74876a98a87a115254b3a66a14b27320b7f0acaa
+xen-tip		85e5d6e384a7eee1e9425311a252372d37bd1b84
+percpu		a4244454df1296e90cc961c1b636b1176ef0d9a0
+workqueues	b84acfba1fce5fdbd1ccd88d8dea1f4222b7379f
+drivers-x86	de91b53dcc25f5f3255f3ea124bec293344fd402
+hwpoison	46e387bbd82d438b9131e237e6e2cb55a825da49
+sysctl		4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
+regmap		9851d62d23d31700c3906a0fcd3147648b73a6e7
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+leds		519220ad4784b934b79cf863cabb779dbda99fda
+driver-core	e70b0915124942204dec8064bb25756e8723b81a
+tty		16cf48a6d3e8f9ebe3c3231c12cbe4b0c4ed4d24
+usb		5b146f7e016a8727a98b3d48e4f4e128d3624cd5
+usb-gadget	941ea3616c747545d0278fc432fb7919b6d0d8f0
+staging		98f62b7a082e1e9eb762c7329a704316f6e07698
+char-misc	d3b688c6622334e8460e808755d7d9c4a78c3ae5
+scsi		959823b521454a045711c6c9bf62e6d363064640
+target-updates	ca40d24eb8fc3c194b4439493ecf6b2d703812b8
+target-merge	317ddd256b9c24b0d78fa8018f80f1e495481a10
+ibft		935a9fee51c945b8942be2d7b4bae069167b4886
+isci		6734092e66011def7875bd67beef889d0fee1cc9
+bcon		e284f3493206d4268267db4557c7ee6f89ed2314
+tmem		8f0d8163b50e01f398b14bcd4dc039ac5ab18d64
+writeback	8bb495e3f02401ee6f76d1b1d77f3ac9f079e376
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		0979714aae7a4c40e7d15f1e2de400c59c42b667
+vhost		8c325eed6438d5262e6e74df32eb40b1e657a967
+memblock	7bd0b0f0da3b1ec11cbcc798eb0ef747a1184077
+remoteproc	b9777859ec015a78dae1476e317d04f851bfdd0d
+rpmsg		397944df3290ddc46dcc6a08cd71fb560700431b
+gpio		b0305e947608c04031fec24f50e0d9cec56ba650
+arm-soc		8d015b73e1561faa6e3893af58e76e10ae1fc857
+bcm2835		7d132055814ef17a6c7b69f342244c410a5e000f
+cortex		3ad87ac5ac98d951bc51d1c815c533b65e072f45
+ep93xx		9c59be78d1ee4a717ca2f85b54356f8fed7f439c
+imx-mxs		d2adb329a566242014609a0494c8ae25fb2000ba
+ixp4xx		19f949f52599ba7c3f67a5897ac6be14bfcb1200
+msm		8fb0bf121867e2f3087368c9eef028e5d6305422
+mvebu		97a28fb4bc90a491327189b2046c30eccd2c5e83
+renesas		8a8c6f79c0a61a83b454e2a8e60467b82d026ed9
+samsung		45fd387b65d0b65be4f437f43ccfb061e4c3d60f
+tegra		718d93210da900c18edf4cfd60ae07a8f9f00a01
+dma-mapping	f7d8f1e9cb44e6ee1602586dbf7f2bed637a2b4e
+pwm		6d0cf4d38fd3e234e333a7343132b4c1d441eeb0
+dma-buf		8bb495e3f02401ee6f76d1b1d77f3ac9f079e376
+userns		78008c404acd8e731d1e06618cc5995961e847a6
+ktest		df5f7c66013c46cec9aa8156af257bc5eb29b5c5
+signal		20b4fb485227404329e41ad15588afad3df23050
+clk		d2127ac4518d81fa5edcaf922fdd34b54a2888a7
+random		b980955236922ae6106774511c5c05003d3ad225
+lzo-update	42b775abafafdf811ef300e869a4e1480ef1cf95
+arm64-hugepages	af07484863e0c20796081e57093886c22dc16705
+ptr-ret		ad151d544475df40ee0d18be7d5c945e29c1b545
+aio		f30d704fe1244c44a984d3d1f47bc648bcc6c9f7
+scsi-post-merge	65112dccf8a113737684366349d7f9ec373ddc47
+akpm-current	7f9cfd111409ee3b02629a15a976eafaf4f2ff62
+akpm		89b1cb86ea7e19ab3ee12ff51ef2ed00d89a0230
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 0000000..506fbc0
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,226 @@
+Trees included into this release:
+
+Name		Type	URL
+----		----	---
+origin		git	git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git#master
+fixes		git	git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes.git#master
+kbuild-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#rc-fixes
+arc-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git#for-curr
+arm-current	git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#fixes
+m68k-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-linus
+metag-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git#fixes
+powerpc-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#merge
+sparc		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git#master
+net		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git#master
+ipsec		git	git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git#master
+sound-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-linus
+pci-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#for-linus
+wireless	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git#master
+driver-core.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-linus
+tty.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus
+usb.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-linus
+staging.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-linus
+char-misc.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-linus
+input-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#for-linus
+md-current	git	git://neil.brown.name/md#for-linus
+audit-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-linus
+crypto-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git#master
+ide		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide.git#master
+dwmw2		git	git://git.infradead.org/users/dwmw2/random-2.6.git#master
+sh-current	git	git://github.com/pmundt/linux-sh.git#sh-fixes-for-linus
+devicetree-current	git	git://git.secretlab.ca/git/linux-2.6#devicetree/merge
+rr-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#fixes
+mfd-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git#master
+vfio-fixes	git	git://github.com/awilliam/linux-vfio.git#for-linus
+drm-intel-fixes	git	git://people.freedesktop.org/~danvet/drm-intel#drm-intel-fixes
+asm-generic	git	git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git#master
+arc		git	git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git#for-next
+arm		git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#for-next
+arm-perf	git	git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git#for-next/perf
+davinci		git	git://gitorious.org/linux-davinci/linux-davinci.git#davinci-next
+xilinx		git	git://git.xilinx.com/linux-xlnx.git#arm-next
+arm64		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64.git#upstream
+blackfin	git	http://git.kernel.org/pub/scm/linux/kernel/git/realmz6/blackfin-linux.git#for-linus
+c6x		git	git://linux-c6x.org/git/projects/linux-c6x-upstreaming.git#for-linux-next
+cris		git	git://www.jni.nu/cris.git#for-next
+hexagon		git	git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel.git#linux-next
+ia64		git	git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git#next
+m68k		git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-next
+m68knommu	git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git#for-next
+metag		git	git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git#for-next
+microblaze	git	git://git.monstr.eu/linux-2.6-microblaze.git#next
+mips		git	git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git#mips-for-linux-next
+openrisc	git	git://openrisc.net/jonas/linux#for-upstream
+parisc		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git#for-next
+parisc-hd	git	git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git#for-next
+powerpc		git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#next
+4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git#next
+mpc5xxx		git	git://git.denx.de/linux-2.6-agust.git#next
+galak		git	git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git#next
+s390		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#features
+sh		git	git://github.com/pmundt/linux-sh.git#sh-latest
+sparc-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git#master
+tile		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git#master
+unicore32	git	git://github.com/gxt/linux.git#unicore32
+xtensa		git	git://github.com/czankel/xtensa-linux.git#for_next
+btrfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git#next
+ceph		git	git://github.com/ceph/ceph-client.git#master
+cifs		git	git://git.samba.org/sfrench/cifs-2.6.git#for-next
+configfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git#linux-next
+ecryptfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git#next
+ext3		git	git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git#for_next
+ext4		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git#dev
+f2fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git#dev
+fscache		git	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git#fscache
+fuse		git	git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git#for-next
+gfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git#master
+jfs		git	git://github.com/kleikamp/linux-shaggy.git#jfs-next
+logfs		git	git://github.com/prasad-joshi/logfs_upstream.git#master
+nfs		git	git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git#linux-next
+nfsd		git	git://git.linux-nfs.org/~bfields/linux.git#nfsd-next
+ocfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git#linux-next
+omfs		git	git://github.com/bcopeland/omfs.git#for-next
+squashfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next.git#master
+v9fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git#for-next
+ubifs		git	git://git.infradead.org/ubifs-2.6.git#linux-next
+xfs		git	git://oss.sgi.com/xfs/xfs.git#for-next
+vfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6.git#for-next
+pci		git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#next
+hid		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git#for-next
+i2c		git	git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git#i2c/for-next
+jdelvare-hwmon	quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-hwmon/
+hwmon-staging	git	git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git#hwmon-next
+v4l-dvb		git	git://linuxtv.org/mchehab/media-next.git#master
+kbuild		git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#for-next
+kconfig		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-kconfig.git#for-next
+libata		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git#for-next
+pstore		git	git://git.infradead.org/users/cbou/linux-pstore.git#master
+pm		git	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git#linux-next
+idle		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git#next
+apm		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git#for-next
+cpupowerutils	git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/cpupowerutils.git#master
+thermal		git	git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git#next
+ieee1394	git	git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git#for-next
+ubi		git	git://git.infradead.org/ubi-2.6.git#linux-next
+dlm		git	git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git#next
+swiotlb		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git#linux-next
+slave-dma	git	git://git.infradead.org/users/vkoul/slave-dma.git#next
+dmaengine	git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/dmaengine.git#next
+net-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git#master
+ipsec-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git#master
+wireless-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git#master
+bluetooth	git	git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git#master
+infiniband	git	git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git#for-next
+mtd		git	git://git.infradead.org/mtd-2.6.git#master
+l2-mtd		git	git://git.infradead.org/users/dedekind/l2-mtd-2.6.git#master
+crypto		git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git#master
+drm		git	git://people.freedesktop.org/~airlied/linux.git#drm-next
+drm-intel	git	git://people.freedesktop.org/~danvet/drm-intel#for-linux-next
+drm-tegra	git	git://anongit.freedesktop.org/tegra/linux.git#drm/for-next
+sound		git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-next
+sound-asoc	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git#for-next
+modules		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#modules-next
+virtio		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#virtio-next
+input		git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#next
+input-mt	git	git://github.com/rydberg/linux.git#for-next
+cgroup		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git#for-next
+block		git	git://git.kernel.dk/linux-block.git#for-next
+device-mapper	quilt	http://people.redhat.com/agk/patches/linux/editing/
+embedded	git	git://git.infradead.org/embedded-2.6.git#master
+firmware	git	git://git.infradead.org/users/dwmw2/firmware-2.6.git#master
+pcmcia		git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git#master
+mmc		git	git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git#mmc-next
+kgdb		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git#kgdb-next
+slab		git	git://github.com/penberg/linux.git#for-next
+uclinux		git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/uclinux.git#for-next
+md		git	git://neil.brown.name/md#for-next
+mfd		git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git#master
+mfd-lj		git	git://git.linaro.org/people/ljones/mfd.git#for-mfd-next
+battery		git	git://git.infradead.org/battery-2.6.git#master
+fbdev		git	git://git.kernel.org/pub/scm/linux/kernel/git/plagnioj/linux-fbdev.git#for-next
+viafb		git	git://github.com/schandinat/linux-2.6.git#viafb-next
+omap_dss2	git	git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git#for-next
+regulator	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git#for-next
+security	git	git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git#next
+selinux		git	git://git.infradead.org/users/eparis/selinux.git#master
+lblnet		git	git://git.infradead.org/users/pcmoore/lblnet-2.6_next#master
+watchdog	git	git://www.linux-watchdog.org/linux-watchdog-next.git#master
+dwmw2-iommu	git	git://git.infradead.org/iommu-2.6.git#master
+iommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git#next
+vfio		git	git://github.com/awilliam/linux-vfio.git#next
+osd		git	git://git.open-osd.org/linux-open-osd.git#linux-next
+jc_docs		git	git://git.lwn.net/linux-2.6.git#docs-next
+trivial		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git#for-next
+audit		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-next
+fsnotify	git	git://git.infradead.org/users/eparis/notify.git#for-next
+edac		git	git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git#linux_next
+edac-amd	git	git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git#for-next
+devicetree	git	git://git.secretlab.ca/git/linux-2.6#devicetree/next
+dt-rh		git	git://sources.calxeda.com/kernel/linux.git#for-next
+spi		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git#for-next
+tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git#auto-latest
+ftrace		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git#for-next
+rcu		git	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git#rcu/next
+cputime		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#cputime
+uprobes		git	git://github.com/srikard/linux.git#for-next
+kvm		git	git://git.kernel.org/pub/scm/virt/kvm/kvm.git#linux-next
+kvm-arm		git	git://github.com/columbia/linux-kvm-arm.git#kvm-arm-next
+kvm-ppc		git	git://github.com/agraf/linux-2.6.git#kvm-ppc-next
+oprofile	git	git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile.git#for-next
+fw-nohz		git	git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks.git#nohz/next
+xen-tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git#linux-next
+percpu		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git#for-next
+workqueues	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git#for-next
+drivers-x86	git	git://cavan.codon.org.uk/platform-drivers-x86.git#linux-next
+hwpoison	git	git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git#hwpoison
+sysctl		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl.git#master
+regmap		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git#for-next
+hsi		git	git://gitorious.org/kernel-hsi/kernel-hsi.git#for-next
+leds		git	git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git#for-next
+driver-core	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-next
+tty		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-next
+usb		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-next
+usb-gadget	git	git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git#next
+staging		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-next
+char-misc	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-next
+scsi		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git#for-next
+target-updates	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next
+target-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next-merge
+ibft		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft.git#linux-next
+isci		git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git#all
+bcon		git	git://git.kernel.org/pub/scm/linux/kernel/git/joern/bcon2.git#master
+tmem		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm.git#linux-next
+writeback	git	git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux.git#writeback-for-next
+hwspinlock	git	git://github.com/ohadbc/hwspinlock-next.git#linux-next
+pinctrl		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git#for-next
+vhost		git	git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git#linux-next
+memblock	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git#memblock-kill-early_node_map
+remoteproc	git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git#for-next
+rpmsg		git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg.git#for-next
+gpio		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git#for-next
+arm-soc		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git#for-next
+bcm2835		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git#for-next
+cortex		git	git://git.pengutronix.de/git/ukl/linux-2.6.git#for-next
+ep93xx		git	git://github.com/RyanMallon/linux-ep93xx.git#ep93xx-for-next
+imx-mxs		git	git://git.linaro.org/people/shawnguo/linux-2.6.git#for-next
+ixp4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux.git#next
+msm		git	git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git#for-next
+mvebu		git	git://git.infradead.org/linux-mvebu.git#for-next
+renesas		git	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git#next
+samsung		git	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git#for-next
+tegra		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git#for-next
+dma-mapping	git	git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git#dma-mapping-next
+pwm		git	git://gitorious.org/linux-pwm/linux-pwm.git#for-next
+dma-buf		git	git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git#for-next
+userns		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git#for-next
+ktest		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest.git#for-next
+signal		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal.git#for-next
+clk		git	git://git.linaro.org/people/mturquette/linux.git#clk-next
+random		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random.git#dev
+lzo-update	git	git://github.com/markus-oberhumer/linux.git#lzo-update
+arm64-hugepages	git	git://git.linaro.org/people/stevecapper/linux.git#for-next/hugepages
+ptr-ret		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#PTR_RET
+aio		git	git://git.kvack.org/~bcrl/aio-next.git#master
+scsi-post-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6.git#master
+akpm-current	mmotm	http://www.ozlabs.org/~akpm/mmotm/
+akpm		mmotm	http://www.ozlabs.org/~akpm/mmotm/
diff --git a/Next/merge.log b/Next/merge.log
new file mode 100644
index 0000000..2346a21
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,6017 @@
+$ date
+Friday 9 August  10:16:20 EST 2013
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at b7bc9e7 Merge tag 'trace-fixes-3.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
+Merging origin/master (6c2580c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/egtvedt/linux-avr32)
+$ git merge --no-ff origin/master
+Removing arch/arm/mach-msm/gpiomux-v1.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/regulator/palmas-pmic.txt  |  4 +-
+ MAINTAINERS                                        |  7 +-
+ arch/arm/boot/dts/msm8960-cdp.dts                  |  4 +-
+ arch/arm/boot/dts/omap5-uevm.dts                   | 78 ++++++++++++++--------
+ arch/arm/boot/dts/stih41x.dtsi                     |  2 +
+ arch/arm/boot/dts/tegra20-colibri-512.dtsi         |  1 +
+ arch/arm/mach-msm/Kconfig                          |  3 +-
+ arch/arm/mach-msm/gpiomux-v1.c                     | 33 ---------
+ arch/arm/mach-msm/gpiomux.h                        | 10 ---
+ arch/arm/mach-omap2/omap_device.c                  | 18 +++++
+ arch/arm/mach-omap2/omap_hwmod.c                   |  2 +-
+ arch/arm/mach-omap2/omap_hwmod.h                   | 50 ++++++++++++++
+ arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |  6 +-
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c         |  3 +-
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |  9 +--
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |  5 +-
+ arch/arm/mach-omap2/omap_hwmod_54xx_data.c         |  3 +-
+ arch/arm/mach-omap2/serial.c                       | 11 ---
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |  3 -
+ arch/arm/mach-shmobile/board-bockw.c               |  8 ++-
+ arch/arm/mach-shmobile/board-lager.c               |  2 +-
+ arch/arm/mach-sti/headsmp.S                        |  2 -
+ arch/avr32/boards/atngw100/mrmt.c                  |  1 -
+ drivers/base/regmap/regcache.c                     |  3 +-
+ drivers/char/virtio_console.c                      | 70 +++++++++++++------
+ drivers/dma/sh/shdma.c                             |  4 +-
+ drivers/scsi/virtio_scsi.c                         |  2 +-
+ drivers/spi/spi-davinci.c                          |  2 +-
+ fs/ext4/extents.c                                  |  2 +-
+ fs/ext4/ialloc.c                                   | 10 +--
+ fs/ext4/inode.c                                    | 39 +++++------
+ fs/ext4/super.c                                    |  1 +
+ include/linux/regmap.h                             |  1 +
+ include/linux/user_namespace.h                     |  1 +
+ kernel/user_namespace.c                            |  4 ++
+ mm/slub.c                                          |  3 -
+ security/smack/smack_lsm.c                         | 24 +++----
+ 37 files changed, 249 insertions(+), 182 deletions(-)
+ delete mode 100644 arch/arm/mach-msm/gpiomux-v1.c
+Merging fixes/master (b3a3a9c Merge tag 'trace-3.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace)
+$ git merge --no-ff fixes/master
+Already up-to-date.
+Merging kbuild-current/rc-fixes (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff kbuild-current/rc-fixes
+Already up-to-date.
+Merging arc-current/for-curr (c095ba7 Linux 3.11-rc4)
+$ git merge --no-ff arc-current/for-curr
+Already up-to-date.
+Merging arm-current/fixes (e35ac62 Merge branch 'security-fixes' into fixes)
+$ git merge --no-ff arm-current/fixes
+Already up-to-date.
+Merging m68k-current/for-linus (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff m68k-current/for-linus
+Already up-to-date.
+Merging metag-fixes/fixes (dfe248b MAINTAINERS: add linux-metag mailing list)
+$ git merge --no-ff metag-fixes/fixes
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS | 1 +
+ 1 file changed, 1 insertion(+)
+Merging powerpc-merge/merge (fe956a1 powerpc/windfarm: Fix noisy slots-fan on Xserve (rm31))
+$ git merge --no-ff powerpc-merge/merge
+Already up-to-date.
+Merging sparc/master (1c2696c sparc64: Fix ITLB handler of null page)
+$ git merge --no-ff sparc/master
+Merge made by the 'recursive' strategy.
+ arch/sparc/include/asm/switch_to_64.h |  4 ++--
+ arch/sparc/kernel/cpumap.c            |  1 +
+ arch/sparc/kernel/entry.S             |  2 +-
+ arch/sparc/kernel/kgdb_64.c           |  4 ++--
+ arch/sparc/kernel/ktlb.S              |  3 +--
+ arch/sparc/kernel/ptrace_64.c         |  2 +-
+ arch/sparc/kernel/setup_64.c          | 12 ++++++++----
+ arch/sparc/kernel/syscalls.S          | 12 ++++++------
+ drivers/scsi/esp_scsi.c               | 14 ++++++++------
+ drivers/scsi/esp_scsi.h               |  1 +
+ 10 files changed, 31 insertions(+), 24 deletions(-)
+Merging net/master (75848d3 Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless)
+$ git merge --no-ff net/master
+Merge made by the 'recursive' strategy.
+ drivers/net/bonding/bond_main.c                  |  8 ++-
+ drivers/net/ethernet/marvell/skge.c              | 62 +++++++++++++++++++-----
+ drivers/net/ethernet/mellanox/mlx5/core/health.c | 29 +----------
+ drivers/net/macvlan.c                            |  4 ++
+ drivers/net/wireless/cw1200/sta.c                |  7 +--
+ drivers/net/wireless/iwlegacy/4965-mac.c         | 16 +++---
+ drivers/net/wireless/iwlegacy/common.c           |  1 +
+ include/linux/mlx5/driver.h                      |  3 --
+ include/net/busy_poll.h                          |  5 --
+ net/8021q/vlan_core.c                            |  7 ++-
+ net/bridge/br_multicast.c                        |  2 +-
+ net/bridge/br_sysfs_br.c                         |  2 +-
+ net/core/neighbour.c                             | 10 ++--
+ net/ipv4/esp4.c                                  |  2 +-
+ net/ipv4/fib_trie.c                              |  5 +-
+ net/ipv4/tcp_cubic.c                             | 12 +++--
+ net/ipv6/esp6.c                                  |  2 +-
+ net/ipv6/ip6_fib.c                               | 16 ++++--
+ net/mac80211/mlme.c                              | 54 ++++++++++++++-------
+ net/sched/sch_generic.c                          |  7 ++-
+ net/vmw_vsock/af_vsock.c                         |  2 +-
+ net/wireless/core.c                              |  1 +
+ net/wireless/nl80211.c                           |  6 ++-
+ 23 files changed, 156 insertions(+), 107 deletions(-)
+Merging ipsec/master (01cb71d net_sched: restore "overhead xxx" handling)
+$ git merge --no-ff ipsec/master
+Already up-to-date.
+Merging sound-current/for-linus (57e6dae ALSA: usb-audio: do not trust too-big wMaxPacketSize values)
+$ git merge --no-ff sound-current/for-linus
+Merge made by the 'recursive' strategy.
+ sound/usb/6fire/comm.c | 38 +++++++++++++++++++++++++++++++++-----
+ sound/usb/6fire/comm.h |  2 +-
+ sound/usb/endpoint.c   | 13 ++++++-------
+ 3 files changed, 40 insertions(+), 13 deletions(-)
+Merging pci-current/for-linus (36dd1f3 PCI: mvebu: Disable prefetchable memory support in PCI-to-PCI bridge)
+$ git merge --no-ff pci-current/for-linus
+Already up-to-date.
+Merging wireless/master (5a6e0cf cw1200: Fix spurious BUG_ON() trigger when starting AP mode.)
+$ git merge --no-ff wireless/master
+Already up-to-date.
+Merging driver-core.current/driver-core-linus (5ae90d8 Linux 3.11-rc3)
+$ git merge --no-ff driver-core.current/driver-core-linus
+Already up-to-date.
+Merging tty.current/tty-linus (c095ba7 Linux 3.11-rc4)
+$ git merge --no-ff tty.current/tty-linus
+Already up-to-date.
+Merging usb.current/usb-linus (444ce9d MAINTAINERS: Add separate section for USB NETWORKING DRIVERS)
+$ git merge --no-ff usb.current/usb-linus
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                 | 5 +++++
+ drivers/usb/core/hub.c      | 5 +++--
+ drivers/usb/host/xhci-mem.c | 1 +
+ drivers/usb/host/xhci.c     | 1 +
+ 4 files changed, 10 insertions(+), 2 deletions(-)
+Merging staging.current/staging-linus (cefe8a3 Merge tag 'iio-fixes-for-3.11b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus)
+$ git merge --no-ff staging.current/staging-linus
+Merge made by the 'recursive' strategy.
+ drivers/iio/adc/ti_am335x_adc.c      | 30 ++++++++++++++++++++++--------
+ drivers/iio/industrialio-trigger.c   | 34 ++++++++++++++++++++++------------
+ drivers/staging/zcache/zcache-main.c |  6 ++++--
+ include/linux/iio/trigger.h          |  3 ++-
+ include/linux/mfd/ti_am335x_tscadc.h | 16 ++++++++++++++++
+ 5 files changed, 66 insertions(+), 23 deletions(-)
+Merging char-misc.current/char-misc-linus (5ae90d8 Linux 3.11-rc3)
+$ git merge --no-ff char-misc.current/char-misc-linus
+Already up-to-date.
+Merging input-current/for-linus (88ce3c3 Merge branch 'next' into for-linus)
+$ git merge --no-ff input-current/for-linus
+Already up-to-date.
+Merging md-current/for-linus (f94c0b6 md/raid5: fix interaction of 'replace' and 'recovery'.)
+$ git merge --no-ff md-current/for-linus
+Already up-to-date.
+Merging audit-current/for-linus (c158a35 audit: no leading space in audit_log_d_path prefix)
+$ git merge --no-ff audit-current/for-linus
+Already up-to-date.
+Merging crypto-current/master (e70308e Revert "crypto: crct10dif - Wrap crc_t10dif function all to use crypto transform framework")
+$ git merge --no-ff crypto-current/master
+Already up-to-date.
+Merging ide/master (6d128e1 Revert "Makefile: Fix install error with make -j option")
+$ git merge --no-ff ide/master
+Already up-to-date.
+Merging dwmw2/master (5950f08 pcmcia: remove RPX board stuff)
+$ git merge --no-ff dwmw2/master
+Already up-to-date.
+Merging sh-current/sh-fixes-for-linus (4403310 SH: Convert out[bwl] macros to inline functions)
+$ git merge --no-ff sh-current/sh-fixes-for-linus
+Already up-to-date.
+Merging devicetree-current/devicetree/merge (cf9e236 of/irq: init struct resource to 0 in of_irq_to_resource())
+$ git merge --no-ff devicetree-current/devicetree/merge
+Already up-to-date.
+Merging rr-fixes/fixes (aa52aee virtio-scsi: Fix virtqueue affinity setup)
+$ git merge --no-ff rr-fixes/fixes
+Already up-to-date.
+Merging mfd-fixes/master (5649d8f mfd: ab8500-sysctrl: Let sysctrl driver work without pdata)
+$ git merge --no-ff mfd-fixes/master
+Already up-to-date.
+Merging vfio-fixes/for-linus (d24cdbf vfio-pci: Avoid deadlock on remove)
+$ git merge --no-ff vfio-fixes/for-linus
+Already up-to-date.
+Merging drm-intel-fixes/drm-intel-fixes (3f57757 drm/i915: do not disable backlight on vgaswitcheroo switch off)
+$ git merge --no-ff drm-intel-fixes/drm-intel-fixes
+Merge made by the 'recursive' strategy.
+ drivers/gpu/drm/i915/i915_reg.h      | 12 +++++++++---
+ drivers/gpu/drm/i915/intel_display.c |  4 +++-
+ drivers/gpu/drm/i915/intel_panel.c   | 18 ++++++++++++++++--
+ drivers/gpu/drm/i915/intel_pm.c      | 18 ++++++++++++++++++
+ 4 files changed, 46 insertions(+), 6 deletions(-)
+Merging asm-generic/master (fb9de7e xtensa: Use generic asm/mmu.h for nommu)
+$ git merge --no-ff asm-generic/master
+Already up-to-date.
+Merging arc/for-next (a00b92e ARC: [ASID] Optimize the threads-of-process switching case)
+$ git merge --no-ff arc/for-next
+Merge made by the 'recursive' strategy.
+ arch/arc/boot/.gitignore           |   1 +
+ arch/arc/include/asm/entry.h       |  24 ++++-
+ arch/arc/include/asm/irqflags.h    |   7 --
+ arch/arc/include/asm/mmu.h         |   7 +-
+ arch/arc/include/asm/mmu_context.h | 193 +++++++++++++++----------------------
+ arch/arc/include/asm/pgtable.h     |  61 +++++-------
+ arch/arc/include/asm/ptrace.h      |  36 ++-----
+ arch/arc/include/asm/tlbflush.h    |  11 ++-
+ arch/arc/kernel/.gitignore         |   1 +
+ arch/arc/kernel/entry.S            |  66 ++++---------
+ arch/arc/kernel/smp.c              |   1 +
+ arch/arc/mm/Makefile               |   1 +
+ arch/arc/mm/tlb.c                  | 150 ++++++++++++++--------------
+ arch/arc/mm/tlbex.S                | 186 +++++++++++++++++------------------
+ arch/arc/mm/tlbflush.c             |  85 ++++++++++++++++
+ 15 files changed, 415 insertions(+), 415 deletions(-)
+ create mode 100644 arch/arc/boot/.gitignore
+ create mode 100644 arch/arc/kernel/.gitignore
+ create mode 100644 arch/arc/mm/tlbflush.c
+Merging arm/for-next (bb32e3d Merge branch 'devel-stable' into for-next)
+$ git merge --no-ff arm/for-next
+Auto-merging arch/arm/mm/mmu.c
+Removing arch/arm/mach-versatile/include/mach/debug-macro.S
+Removing arch/arm/mach-spear/include/mach/debug-macro.S
+Removing arch/arm/mach-rpc/include/mach/debug-macro.S
+Removing arch/arm/mach-realview/include/mach/debug-macro.S
+Removing arch/arm/mach-orion5x/include/mach/debug-macro.S
+Removing arch/arm/mach-mv78xx0/include/mach/debug-macro.S
+Removing arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+Removing arch/arm/mach-kirkwood/include/mach/debug-macro.S
+Removing arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+Removing arch/arm/mach-iop33x/include/mach/debug-macro.S
+Removing arch/arm/mach-iop32x/include/mach/debug-macro.S
+Removing arch/arm/mach-iop13xx/include/mach/debug-macro.S
+Removing arch/arm/mach-integrator/include/mach/debug-macro.S
+Removing arch/arm/mach-gemini/include/mach/debug-macro.S
+Removing arch/arm/mach-ep93xx/include/mach/debug-macro.S
+Removing arch/arm/mach-ebsa110/include/mach/debug-macro.S
+Removing arch/arm/mach-dove/include/mach/debug-macro.S
+Removing arch/arm/mach-davinci/include/mach/debug-macro.S
+Removing arch/arm/include/debug/u300.S
+Removing arch/arm/include/debug/sunxi.S
+Removing arch/arm/include/debug/socfpga.S
+Removing arch/arm/include/debug/rockchip.S
+Removing arch/arm/include/debug/pxa.S
+Auto-merging arch/arm/include/debug/pl01x.S
+Removing arch/arm/include/debug/picoxcell.S
+Removing arch/arm/include/debug/nspire.S
+Removing arch/arm/include/debug/nomadik.S
+Removing arch/arm/include/debug/mxs.S
+Removing arch/arm/include/debug/mvebu.S
+Removing arch/arm/include/debug/keystone.S
+Removing arch/arm/include/debug/highbank.S
+Removing arch/arm/include/debug/cns3xxx.S
+Removing arch/arm/include/debug/bcm2835.S
+Removing arch/arm/include/debug/8250_32.S
+Removing arch/arm/include/asm/hardware/debug-8250.S
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/arm/Kconfig                                   |  50 +-
+ arch/arm/Kconfig.debug                             | 553 +++++++++++++++------
+ arch/arm/include/asm/hardware/debug-8250.S         |  29 --
+ arch/arm/include/asm/mach/arch.h                   |   4 +-
+ arch/arm/include/asm/memblock.h                    |   3 +-
+ arch/arm/include/asm/neon.h                        |  36 ++
+ arch/arm/include/asm/prom.h                        |   4 +-
+ arch/arm/include/asm/xor.h                         |  73 +++
+ arch/arm/include/debug/8250.S                      |  54 ++
+ arch/arm/include/debug/8250_32.S                   |  27 -
+ arch/arm/include/debug/bcm2835.S                   |  22 -
+ arch/arm/include/debug/cns3xxx.S                   |  19 -
+ arch/arm/include/debug/highbank.S                  |  17 -
+ arch/arm/include/debug/keystone.S                  |  43 --
+ arch/arm/include/debug/mvebu.S                     |  30 --
+ arch/arm/include/debug/mxs.S                       |  27 -
+ arch/arm/include/debug/nomadik.S                   |  20 -
+ arch/arm/include/debug/nspire.S                    |  28 --
+ arch/arm/include/debug/picoxcell.S                 |  19 -
+ .../{asm/hardware/debug-pl01x.S => debug/pl01x.S}  |   9 +-
+ arch/arm/include/debug/pxa.S                       |  33 --
+ arch/arm/include/debug/rockchip.S                  |  42 --
+ arch/arm/include/debug/socfpga.S                   |  21 -
+ arch/arm/include/debug/sunxi.S                     |  27 -
+ arch/arm/include/debug/u300.S                      |  18 -
+ arch/arm/include/debug/ux500.S                     |   2 +-
+ arch/arm/include/debug/vexpress.S                  |  48 +-
+ arch/arm/kernel/atags.h                            |   5 +-
+ arch/arm/kernel/atags_parse.c                      |   6 +-
+ arch/arm/kernel/devtree.c                          |   6 +-
+ arch/arm/kernel/setup.c                            |  12 +-
+ arch/arm/lib/Makefile                              |   6 +
+ arch/arm/lib/xor-neon.c                            |  42 ++
+ arch/arm/mach-davinci/include/mach/debug-macro.S   |  65 ---
+ arch/arm/mach-dove/include/mach/debug-macro.S      |  19 -
+ arch/arm/mach-ebsa110/include/mach/debug-macro.S   |  22 -
+ arch/arm/mach-ep93xx/Kconfig                       |  14 -
+ arch/arm/mach-ep93xx/include/mach/debug-macro.S    |  21 -
+ arch/arm/mach-ep93xx/include/mach/uncompress.h     |  14 +-
+ .../arm/mach-footbridge/include/mach/debug-macro.S |  15 -
+ arch/arm/mach-gemini/include/mach/debug-macro.S    |  21 -
+ .../arm/mach-integrator/include/mach/debug-macro.S |  20 -
+ arch/arm/mach-iop13xx/include/mach/debug-macro.S   |  24 -
+ arch/arm/mach-iop32x/include/mach/debug-macro.S    |  21 -
+ arch/arm/mach-iop33x/include/mach/debug-macro.S    |  22 -
+ arch/arm/mach-ixp4xx/include/mach/debug-macro.S    |  26 -
+ arch/arm/mach-kirkwood/include/mach/debug-macro.S  |  19 -
+ arch/arm/mach-lpc32xx/include/mach/debug-macro.S   |  29 --
+ arch/arm/mach-mv78xx0/include/mach/debug-macro.S   |  19 -
+ arch/arm/mach-orion5x/include/mach/debug-macro.S   |  21 -
+ arch/arm/mach-realview/include/mach/debug-macro.S  |  29 --
+ arch/arm/mach-rpc/include/mach/debug-macro.S       |  23 -
+ arch/arm/mach-spear/include/mach/debug-macro.S     |  36 --
+ arch/arm/mach-spear/include/mach/spear.h           |   2 -
+ arch/arm/mach-versatile/include/mach/debug-macro.S |  21 -
+ arch/arm/mm/hugetlbpage.c                          |  43 --
+ arch/arm/mm/init.c                                 |   5 +-
+ arch/arm/mm/mmu.c                                  |   4 +-
+ arch/arm/mm/nommu.c                                |   2 +-
+ arch/arm/vfp/vfphw.S                               |   5 +
+ arch/arm/vfp/vfpmodule.c                           |  69 ++-
+ include/linux/raid/pq.h                            |   5 +
+ lib/raid6/.gitignore                               |   1 +
+ lib/raid6/Makefile                                 |  40 ++
+ lib/raid6/algos.c                                  |   6 +
+ lib/raid6/neon.c                                   |  58 +++
+ lib/raid6/neon.uc                                  |  80 +++
+ lib/raid6/test/Makefile                            |  26 +-
+ 68 files changed, 978 insertions(+), 1204 deletions(-)
+ delete mode 100644 arch/arm/include/asm/hardware/debug-8250.S
+ create mode 100644 arch/arm/include/asm/neon.h
+ create mode 100644 arch/arm/include/debug/8250.S
+ delete mode 100644 arch/arm/include/debug/8250_32.S
+ delete mode 100644 arch/arm/include/debug/bcm2835.S
+ delete mode 100644 arch/arm/include/debug/cns3xxx.S
+ delete mode 100644 arch/arm/include/debug/highbank.S
+ delete mode 100644 arch/arm/include/debug/keystone.S
+ delete mode 100644 arch/arm/include/debug/mvebu.S
+ delete mode 100644 arch/arm/include/debug/mxs.S
+ delete mode 100644 arch/arm/include/debug/nomadik.S
+ delete mode 100644 arch/arm/include/debug/nspire.S
+ delete mode 100644 arch/arm/include/debug/picoxcell.S
+ rename arch/arm/include/{asm/hardware/debug-pl01x.S => debug/pl01x.S} (78%)
+ delete mode 100644 arch/arm/include/debug/pxa.S
+ delete mode 100644 arch/arm/include/debug/rockchip.S
+ delete mode 100644 arch/arm/include/debug/socfpga.S
+ delete mode 100644 arch/arm/include/debug/sunxi.S
+ delete mode 100644 arch/arm/include/debug/u300.S
+ create mode 100644 arch/arm/lib/xor-neon.c
+ delete mode 100644 arch/arm/mach-davinci/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-dove/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-ebsa110/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-ep93xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-gemini/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-integrator/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-iop13xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-iop32x/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-iop33x/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-kirkwood/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-mv78xx0/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-orion5x/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-realview/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-rpc/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-spear/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-versatile/include/mach/debug-macro.S
+ create mode 100644 lib/raid6/neon.c
+ create mode 100644 lib/raid6/neon.uc
+Merging arm-perf/for-next/perf (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff arm-perf/for-next/perf
+Already up-to-date.
+Merging davinci/davinci-next (fe0d422 Linux 3.0-rc6)
+$ git merge --no-ff davinci/davinci-next
+Already up-to-date.
+Merging xilinx/arm-next (b028161 Merge branch 'for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup)
+$ git merge --no-ff xilinx/arm-next
+Already up-to-date.
+Merging arm64/upstream (845ad05 arm64: Change kernel stack size to 16K)
+$ git merge --no-ff arm64/upstream
+Already up-to-date.
+Merging blackfin/for-linus (eb043d3 smp: blackfin: fix check error, using atomic_ops to handle atomic_t type)
+$ git merge --no-ff blackfin/for-linus
+Merge made by the 'recursive' strategy.
+Merging c6x/for-linux-next (f934af0 add memory barrier to arch_local_irq_restore)
+$ git merge --no-ff c6x/for-linux-next
+Already up-to-date.
+Merging cris/for-next (32ade6a CRIS: Add kvm_para.h which includes generic file)
+$ git merge --no-ff cris/for-next
+Resolved 'arch/cris/arch-v32/drivers/Kconfig' using previous resolution.
+Auto-merging arch/cris/include/asm/processor.h
+Auto-merging arch/cris/arch-v32/drivers/Kconfig
+CONFLICT (content): Merge conflict in arch/cris/arch-v32/drivers/Kconfig
+Auto-merging arch/cris/arch-v10/drivers/Kconfig
+Auto-merging arch/cris/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master d57f387] Merge remote-tracking branch 'cris/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/cris/Kconfig                     |  81 -------
+ arch/cris/arch-v10/drivers/Kconfig    |  70 ------
+ arch/cris/arch-v10/drivers/Makefile   |   2 -
+ arch/cris/arch-v32/drivers/Kconfig    | 394 ----------------------------------
+ arch/cris/arch-v32/mach-a3/Kconfig    |   4 -
+ arch/cris/include/asm/processor.h     |   1 -
+ arch/cris/include/uapi/asm/kvm_para.h |   1 +
+ 7 files changed, 1 insertion(+), 552 deletions(-)
+ create mode 100644 arch/cris/include/uapi/asm/kvm_para.h
+Merging hexagon/linux-next (de44443 HEXAGON: Remove non existent reference to GENERIC_KERNEL_EXECVE & GENERIC_KERNEL_THREAD)
+$ git merge --no-ff hexagon/linux-next
+Already up-to-date.
+Merging ia64/next (9c510f7 [IA64] dmi.h: Make dmi_alloc use kzalloc)
+$ git merge --no-ff ia64/next
+Resolved 'arch/ia64/configs/generic_defconfig' using previous resolution.
+Resolved 'arch/ia64/configs/gensparse_defconfig' using previous resolution.
+Resolved 'arch/ia64/configs/tiger_defconfig' using previous resolution.
+Resolved 'arch/ia64/configs/xen_domu_defconfig' using previous resolution.
+Auto-merging arch/ia64/configs/xen_domu_defconfig
+CONFLICT (content): Merge conflict in arch/ia64/configs/xen_domu_defconfig
+Auto-merging arch/ia64/configs/tiger_defconfig
+CONFLICT (content): Merge conflict in arch/ia64/configs/tiger_defconfig
+Auto-merging arch/ia64/configs/gensparse_defconfig
+CONFLICT (content): Merge conflict in arch/ia64/configs/gensparse_defconfig
+Auto-merging arch/ia64/configs/generic_defconfig
+CONFLICT (content): Merge conflict in arch/ia64/configs/generic_defconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 2d2304e] Merge remote-tracking branch 'ia64/next'
+$ git diff -M --stat --summary HEAD^..
+ arch/ia64/configs/generic_defconfig   | 2 +-
+ arch/ia64/configs/gensparse_defconfig | 2 +-
+ arch/ia64/configs/tiger_defconfig     | 2 +-
+ arch/ia64/configs/xen_domu_defconfig  | 2 +-
+ arch/ia64/include/asm/dmi.h           | 2 +-
+ 5 files changed, 5 insertions(+), 5 deletions(-)
+Merging m68k/for-next (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff m68k/for-next
+Already up-to-date.
+Merging m68knommu/for-next (5fbed81 m68k: remove 16 unused boards in Kconfig.machine)
+$ git merge --no-ff m68knommu/for-next
+Merge made by the 'recursive' strategy.
+ arch/m68k/Kconfig                   |   2 +-
+ arch/m68k/Kconfig.machine           | 134 ------------------------------------
+ arch/m68k/include/asm/io_no.h       |   1 +
+ arch/m68k/include/asm/page.h        |   3 +
+ arch/m68k/include/asm/page_mm.h     |   3 -
+ arch/m68k/kernel/setup_no.c         |   2 +-
+ arch/m68k/kernel/signal.c           |   8 +++
+ arch/m68k/platform/68000/m68328.c   |   3 +-
+ arch/m68k/platform/68000/m68EZ328.c |   3 +-
+ arch/m68k/platform/68000/m68VZ328.c |   9 +--
+ arch/m68k/platform/68360/commproc.c |   3 +-
+ arch/m68k/platform/68360/config.c   |   3 +-
+ 12 files changed, 27 insertions(+), 147 deletions(-)
+Merging metag/for-next (8a69782 metag: tz1090: instantiate gpio-tz1090-pdc)
+$ git merge --no-ff metag/for-next
+Merge made by the 'recursive' strategy.
+ arch/metag/Kconfig.soc          |  2 ++
+ arch/metag/boot/dts/tz1090.dtsi | 67 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 69 insertions(+)
+Merging microblaze/next (a9b9d22 of/pci: Use of_pci_range_parser)
+$ git merge --no-ff microblaze/next
+Merge made by the 'recursive' strategy.
+ arch/microblaze/pci/pci-common.c | 106 ++++++++++++++-------------------------
+ 1 file changed, 38 insertions(+), 68 deletions(-)
+Merging mips/mips-for-linux-next (3e7522b Merge branch '3.11-fixes' into mips-for-linux-next)
+$ git merge --no-ff mips/mips-for-linux-next
+Removing arch/mips/include/uapi/asm/ipcbuf.h
+Removing arch/mips/include/uapi/asm/auxvec.h
+Removing arch/mips/include/asm/xor.h
+Removing arch/mips/include/asm/ucontext.h
+Removing arch/mips/include/asm/serial.h
+Removing arch/mips/include/asm/segment.h
+Removing arch/mips/include/asm/sections.h
+Removing arch/mips/include/asm/scatterlist.h
+Removing arch/mips/include/asm/percpu.h
+Removing arch/mips/include/asm/parport.h
+Removing arch/mips/include/asm/mutex.h
+Removing arch/mips/include/asm/local64.h
+Removing arch/mips/include/asm/emergency-restart.h
+Removing arch/mips/include/asm/current.h
+Removing arch/mips/include/asm/cputime.h
+Merge made by the 'recursive' strategy.
+ arch/mips/cavium-octeon/setup.c           | 28 ++++++++++++++++
+ arch/mips/include/asm/Kbuild              | 13 +++++++
+ arch/mips/include/asm/bmips.h             | 56 +++++++++++++------------------
+ arch/mips/include/asm/cpu.h               |  5 ++-
+ arch/mips/include/asm/cputime.h           |  6 ----
+ arch/mips/include/asm/current.h           |  1 -
+ arch/mips/include/asm/emergency-restart.h |  6 ----
+ arch/mips/include/asm/local64.h           |  1 -
+ arch/mips/include/asm/mutex.h             |  9 -----
+ arch/mips/include/asm/parport.h           |  1 -
+ arch/mips/include/asm/percpu.h            |  6 ----
+ arch/mips/include/asm/scatterlist.h       |  6 ----
+ arch/mips/include/asm/sections.h          |  6 ----
+ arch/mips/include/asm/segment.h           |  6 ----
+ arch/mips/include/asm/serial.h            |  1 -
+ arch/mips/include/asm/ucontext.h          |  1 -
+ arch/mips/include/asm/xor.h               |  1 -
+ arch/mips/include/uapi/asm/Kbuild         |  5 +--
+ arch/mips/include/uapi/asm/auxvec.h       |  4 ---
+ arch/mips/include/uapi/asm/ipcbuf.h       |  1 -
+ arch/mips/kernel/cpu-probe.c              |  7 ++++
+ arch/mips/kernel/idle.c                   |  1 +
+ arch/mips/mm/c-octeon.c                   | 14 ++++++++
+ arch/mips/mm/tlb-funcs.S                  |  2 ++
+ arch/mips/mm/tlbex.c                      |  2 ++
+ arch/mips/netlogic/xlp/usb-init.c         |  3 +-
+ arch/mips/pci/pci-octeon.c                |  9 ++---
+ scripts/package/buildtar                  | 21 ++++++++++++
+ 28 files changed, 124 insertions(+), 98 deletions(-)
+ delete mode 100644 arch/mips/include/asm/cputime.h
+ delete mode 100644 arch/mips/include/asm/current.h
+ delete mode 100644 arch/mips/include/asm/emergency-restart.h
+ delete mode 100644 arch/mips/include/asm/local64.h
+ delete mode 100644 arch/mips/include/asm/mutex.h
+ delete mode 100644 arch/mips/include/asm/parport.h
+ delete mode 100644 arch/mips/include/asm/percpu.h
+ delete mode 100644 arch/mips/include/asm/scatterlist.h
+ delete mode 100644 arch/mips/include/asm/sections.h
+ delete mode 100644 arch/mips/include/asm/segment.h
+ delete mode 100644 arch/mips/include/asm/serial.h
+ delete mode 100644 arch/mips/include/asm/ucontext.h
+ delete mode 100644 arch/mips/include/asm/xor.h
+ delete mode 100644 arch/mips/include/uapi/asm/auxvec.h
+ delete mode 100644 arch/mips/include/uapi/asm/ipcbuf.h
+Merging openrisc/for-upstream (6af6095 openrisc: remove HAVE_VIRT_TO_BUS)
+$ git merge --no-ff openrisc/for-upstream
+Already up-to-date.
+Merging parisc/for-next (6c700d7 [PARISC] hpux: Remove obsolete regs parameter from do_execve() in hpux_execve())
+$ git merge --no-ff parisc/for-next
+Already up-to-date.
+Merging parisc-hd/for-next (9f0f4fb parisc: add generic 32- and 64-bit defconfigs)
+$ git merge --no-ff parisc-hd/for-next
+Merge made by the 'recursive' strategy.
+ arch/parisc/configs/generic-32bit_defconfig | 340 +++++++++++++++++++++++++++
+ arch/parisc/configs/generic-64bit_defconfig | 350 ++++++++++++++++++++++++++++
+ 2 files changed, 690 insertions(+)
+ create mode 100644 arch/parisc/configs/generic-32bit_defconfig
+ create mode 100644 arch/parisc/configs/generic-64bit_defconfig
+Merging powerpc/next (3b2f64d Linux 3.11-rc2)
+$ git merge --no-ff powerpc/next
+Already up-to-date.
+Merging 4xx/next (2074b1d powerpc: Fix irq distribution)
+$ git merge --no-ff 4xx/next
+Already up-to-date.
+Merging mpc5xxx/next (dd0120d powerpc/mpc512x: enable USB support in defconfig)
+$ git merge --no-ff mpc5xxx/next
+Already up-to-date.
+Merging galak/next (9e2ecdb powerpc/fsl-booke: add the reg prop for pci bridge device node for T4/B4)
+$ git merge --no-ff galak/next
+Already up-to-date.
+Merging s390/features (6d7e8d8 s390/time: clock comparator revalidation)
+$ git merge --no-ff s390/features
+Removing arch/s390/pci/pci_msi.c
+Merge made by the 'recursive' strategy.
+ arch/s390/Kconfig                |  11 +
+ arch/s390/include/asm/airq.h     |  67 ++++++
+ arch/s390/include/asm/hardirq.h  |   5 +
+ arch/s390/include/asm/hugetlb.h  | 135 +++---------
+ arch/s390/include/asm/hw_irq.h   |  17 +-
+ arch/s390/include/asm/irq.h      |  35 +--
+ arch/s390/include/asm/page.h     |  10 -
+ arch/s390/include/asm/pci.h      |  22 +-
+ arch/s390/include/asm/pci_insn.h |  12 +-
+ arch/s390/include/asm/pci_io.h   |  10 +-
+ arch/s390/include/asm/pgtable.h  | 306 +++++++++++++-------------
+ arch/s390/include/asm/serial.h   |   6 +
+ arch/s390/kernel/entry.S         |  12 +-
+ arch/s390/kernel/entry64.S       |   9 +-
+ arch/s390/kernel/irq.c           | 160 +++++---------
+ arch/s390/kernel/nmi.c           |   5 +-
+ arch/s390/kernel/ptrace.c        |   2 +-
+ arch/s390/kernel/vdso.c          |   6 +-
+ arch/s390/lib/uaccess_pt.c       |  16 +-
+ arch/s390/mm/dump_pagetables.c   |  18 +-
+ arch/s390/mm/gup.c               |   6 +-
+ arch/s390/mm/hugetlbpage.c       | 104 ++++++++-
+ arch/s390/mm/pageattr.c          |   2 +-
+ arch/s390/mm/pgtable.c           |  59 ++---
+ arch/s390/mm/vmem.c              |  14 +-
+ arch/s390/pci/Makefile           |   2 +-
+ arch/s390/pci/pci.c              | 456 +++++++++++++++------------------------
+ arch/s390/pci/pci_dma.c          |   4 +-
+ arch/s390/pci/pci_insn.c         |  18 +-
+ arch/s390/pci/pci_msi.c          | 142 ------------
+ drivers/s390/block/dasd_devmap.c |   8 +-
+ drivers/s390/block/dasd_erp.c    |   6 +-
+ drivers/s390/char/sclp_config.c  |   2 +-
+ drivers/s390/cio/airq.c          | 174 ++++++++++++++-
+ drivers/s390/cio/ccwgroup.c      |   2 +-
+ drivers/s390/cio/cio.c           |  46 ++--
+ drivers/s390/cio/cio.h           |   3 -
+ drivers/s390/cio/cmf.c           |   2 +-
+ drivers/s390/cio/css.c           |   2 +-
+ drivers/s390/cio/device.c        |   2 +-
+ drivers/s390/net/qeth_l3_sys.c   |   2 +-
+ 41 files changed, 938 insertions(+), 982 deletions(-)
+ create mode 100644 arch/s390/include/asm/serial.h
+ delete mode 100644 arch/s390/pci/pci_msi.c
+Merging sh/sh-latest (37284bd Merge branches 'sh/hw-breakpoints' and 'sh/serial-of' into sh-latest)
+$ git merge --no-ff sh/sh-latest
+Resolved 'arch/sh/kernel/cpu/sh2a/Makefile' using previous resolution.
+Resolved 'include/linux/serial_sci.h' using previous resolution.
+Auto-merging include/linux/serial_sci.h
+CONFLICT (content): Merge conflict in include/linux/serial_sci.h
+Auto-merging drivers/tty/serial/sh-sci.c
+Auto-merging arch/sh/kernel/cpu/sh2a/Makefile
+CONFLICT (content): Merge conflict in arch/sh/kernel/cpu/sh2a/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master e5440f8] Merge remote-tracking branch 'sh/sh-latest'
+$ git diff -M --stat --summary HEAD^..
+ .../bindings/tty/serial/renesas,sci-serial.txt     |  53 +++++++
+ arch/sh/include/asm/hw_breakpoint.h                |  12 +-
+ arch/sh/include/cpu-common/cpu/ubc.h               |  17 +++
+ arch/sh/include/cpu-sh2a/cpu/ubc.h                 |  14 ++
+ arch/sh/kernel/cpu/sh2a/Makefile                   |   1 +
+ arch/sh/kernel/cpu/sh2a/ubc.c                      | 154 +++++++++++++++++++++
+ arch/sh/kernel/hw_breakpoint.c                     |   8 ++
+ drivers/tty/serial/sh-sci.c                        | 127 ++++++++++++++++-
+ include/linux/serial_sci.h                         |   4 +
+ 9 files changed, 375 insertions(+), 15 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
+ create mode 100644 arch/sh/include/cpu-common/cpu/ubc.h
+ create mode 100644 arch/sh/include/cpu-sh2a/cpu/ubc.h
+ create mode 100644 arch/sh/kernel/cpu/sh2a/ubc.c
+Merging sparc-next/master (f8ce1fa Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux)
+$ git merge --no-ff sparc-next/master
+Already up-to-date.
+Merging tile/master (bb94fb9 arch/tile: provide traceability for hypervisor calls)
+$ git merge --no-ff tile/master
+Auto-merging mm/swap.c
+Auto-merging kernel/workqueue.c
+Auto-merging arch/tile/kernel/time.c
+Auto-merging arch/tile/kernel/smpboot.c
+Auto-merging arch/tile/kernel/setup.c
+Auto-merging arch/tile/kernel/irq.c
+Removing arch/tile/kernel/hvglue.lds
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                           |    8 +-
+ arch/tile/Kconfig                     |   18 +
+ arch/tile/Kconfig.debug               |    8 +
+ arch/tile/gxio/iorpc_trio.c           |   23 +
+ arch/tile/include/arch/trio.h         |   39 +
+ arch/tile/include/asm/cacheflush.h    |   44 +-
+ arch/tile/include/asm/cmpxchg.h       |    6 +
+ arch/tile/include/asm/dma-mapping.h   |   14 +-
+ arch/tile/include/asm/elf.h           |    5 +
+ arch/tile/include/asm/homecache.h     |    8 -
+ arch/tile/include/asm/io.h            |  126 ++-
+ arch/tile/include/asm/irqflags.h      |   21 +-
+ arch/tile/include/asm/mmu.h           |    1 +
+ arch/tile/include/asm/page.h          |    8 +-
+ arch/tile/include/asm/pci.h           |   17 +-
+ arch/tile/include/asm/processor.h     |   15 +-
+ arch/tile/include/asm/ptrace.h        |    3 +-
+ arch/tile/include/asm/sections.h      |    8 +-
+ arch/tile/include/asm/setup.h         |    3 +-
+ arch/tile/include/asm/string.h        |    2 +
+ arch/tile/include/asm/thread_info.h   |    6 +
+ arch/tile/include/asm/traps.h         |   11 +
+ arch/tile/include/asm/uaccess.h       |   31 -
+ arch/tile/include/asm/unaligned.h     |   14 +-
+ arch/tile/include/asm/vdso.h          |   49 +
+ arch/tile/include/gxio/iorpc_trio.h   |    5 +
+ arch/tile/include/hv/drv_trio_intf.h  |    8 +-
+ arch/tile/include/hv/hypervisor.h     |   45 +-
+ arch/tile/include/uapi/asm/auxvec.h   |    3 +-
+ arch/tile/include/uapi/asm/cachectl.h |    4 +-
+ arch/tile/kernel/Makefile             |    8 +-
+ arch/tile/kernel/asm-offsets.c        |   36 +-
+ arch/tile/kernel/compat_signal.c      |    3 +-
+ arch/tile/kernel/early_printk.c       |   47 +-
+ arch/tile/kernel/entry.S              |   16 -
+ arch/tile/kernel/hardwall.c           |   28 +-
+ arch/tile/kernel/head_32.S            |   10 +-
+ arch/tile/kernel/head_64.S            |   34 +-
+ arch/tile/kernel/hvglue.S             |   74 ++
+ arch/tile/kernel/hvglue.lds           |   59 --
+ arch/tile/kernel/hvglue_trace.c       |  266 ++++++
+ arch/tile/kernel/intvec_32.S          |   32 +-
+ arch/tile/kernel/intvec_64.S          |  254 +++++-
+ arch/tile/kernel/irq.c                |    1 +
+ arch/tile/kernel/pci-dma.c            |   67 +-
+ arch/tile/kernel/pci.c                |   33 +-
+ arch/tile/kernel/pci_gx.c             |  710 ++++++++-------
+ arch/tile/kernel/proc.c               |    2 -
+ arch/tile/kernel/process.c            |   64 +-
+ arch/tile/kernel/ptrace.c             |    4 +-
+ arch/tile/kernel/reboot.c             |    2 -
+ arch/tile/kernel/setup.c              |   89 +-
+ arch/tile/kernel/signal.c             |    3 +-
+ arch/tile/kernel/single_step.c        |  119 +--
+ arch/tile/kernel/smp.c                |    2 +-
+ arch/tile/kernel/smpboot.c            |    8 +-
+ arch/tile/kernel/stack.c              |   39 +-
+ arch/tile/kernel/sys.c                |    4 +-
+ arch/tile/kernel/time.c               |   37 +-
+ arch/tile/kernel/traps.c              |   25 +-
+ arch/tile/kernel/unaligned.c          | 1609 +++++++++++++++++++++++++++++++++
+ arch/tile/kernel/vdso.c               |  212 +++++
+ arch/tile/kernel/vdso/Makefile        |  118 +++
+ arch/tile/kernel/vdso/vdso.S          |   28 +
+ arch/tile/kernel/vdso/vdso.lds.S      |   87 ++
+ arch/tile/kernel/vdso/vdso32.S        |   28 +
+ arch/tile/kernel/vdso/vgettimeofday.c |  107 +++
+ arch/tile/kernel/vdso/vrt_sigreturn.S |   30 +
+ arch/tile/kernel/vmlinux.lds.S        |    5 +-
+ arch/tile/lib/Makefile                |    2 +-
+ arch/tile/lib/cacheflush.c            |   13 +-
+ arch/tile/lib/exports.c               |    1 -
+ arch/tile/lib/memchr_64.c             |    2 +-
+ arch/tile/lib/memcpy_64.c             |  261 ++++--
+ arch/tile/lib/memcpy_tile64.c         |   12 +-
+ arch/tile/lib/memset_32.c             |    5 +-
+ arch/tile/lib/memset_64.c             |    9 +-
+ arch/tile/lib/strchr_32.c             |    2 -
+ arch/tile/lib/strchr_64.c             |    2 +-
+ arch/tile/lib/string-endian.h         |   13 +-
+ arch/tile/lib/strlen_32.c             |    2 -
+ arch/tile/lib/strnlen_32.c            |   47 +
+ arch/tile/lib/strnlen_64.c            |   48 +
+ arch/tile/lib/usercopy_32.S           |   19 -
+ arch/tile/lib/usercopy_64.S           |   19 -
+ arch/tile/mm/elf.c                    |   99 +-
+ arch/tile/mm/fault.c                  |   49 +-
+ arch/tile/mm/highmem.c                |    2 -
+ arch/tile/mm/homecache.c              |    4 +-
+ arch/tile/mm/hugetlbpage.c            |   38 +-
+ arch/tile/mm/migrate_32.S             |    4 +-
+ arch/tile/mm/migrate_64.S             |    4 +-
+ arch/tile/mm/pgtable.c                |    2 +-
+ drivers/edac/tile_edac.c              |    1 -
+ drivers/tty/hvc/hvc_tile.c            |  149 ++-
+ include/linux/workqueue.h             |    3 +
+ kernel/workqueue.c                    |   36 +-
+ mm/swap.c                             |   37 +-
+ 98 files changed, 4738 insertions(+), 1000 deletions(-)
+ create mode 100644 arch/tile/include/asm/vdso.h
+ create mode 100644 arch/tile/kernel/hvglue.S
+ delete mode 100644 arch/tile/kernel/hvglue.lds
+ create mode 100644 arch/tile/kernel/hvglue_trace.c
+ create mode 100644 arch/tile/kernel/unaligned.c
+ create mode 100644 arch/tile/kernel/vdso.c
+ create mode 100644 arch/tile/kernel/vdso/Makefile
+ create mode 100644 arch/tile/kernel/vdso/vdso.S
+ create mode 100644 arch/tile/kernel/vdso/vdso.lds.S
+ create mode 100644 arch/tile/kernel/vdso/vdso32.S
+ create mode 100644 arch/tile/kernel/vdso/vgettimeofday.c
+ create mode 100644 arch/tile/kernel/vdso/vrt_sigreturn.S
+ create mode 100644 arch/tile/lib/strnlen_32.c
+ create mode 100644 arch/tile/lib/strnlen_64.c
+Merging unicore32/unicore32 (c284464 arch/unicore32: remove CONFIG_EXPERIMENTAL)
+$ git merge --no-ff unicore32/unicore32
+Already up-to-date.
+Merging xtensa/for_next (3b2f64d Linux 3.11-rc2)
+$ git merge --no-ff xtensa/for_next
+Already up-to-date.
+Merging btrfs/next (cbacd76 Merge branch 'for-chris' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next into next)
+$ git merge --no-ff btrfs/next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging ceph/master (71b4325 ceph: wake up writer if vmtruncate work get blocked)
+$ git merge --no-ff ceph/master
+Auto-merging fs/ceph/inode.c
+Auto-merging fs/ceph/dir.c
+Merge made by the 'recursive' strategy.
+ fs/ceph/dir.c         | 2 ++
+ fs/ceph/inode.c       | 9 ++++++++-
+ fs/ceph/ioctl.c       | 4 +++-
+ net/ceph/osd_client.c | 3 ++-
+ 4 files changed, 15 insertions(+), 3 deletions(-)
+Merging cifs/for-next (757c4f6 cifs: don't instantiate new dentries in readdir for inodes that need to be revalidated immediately)
+$ git merge --no-ff cifs/for-next
+Merge made by the 'recursive' strategy.
+ fs/cifs/cifsencrypt.c   | 14 ++++++---
+ fs/cifs/cifsfs.c        | 11 +++----
+ fs/cifs/cifsglob.h      |  4 +++
+ fs/cifs/cifsproto.h     |  4 ++-
+ fs/cifs/connect.c       |  7 +++--
+ fs/cifs/file.c          |  1 +
+ fs/cifs/link.c          | 84 +++++++++++++++++++++++++++++++------------------
+ fs/cifs/readdir.c       |  8 +++++
+ fs/cifs/sess.c          |  6 ++--
+ fs/cifs/smb1ops.c       |  1 +
+ fs/cifs/smb2transport.c |  9 ++++--
+ 11 files changed, 98 insertions(+), 51 deletions(-)
+Merging configfs/linux-next (b930c26 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs)
+$ git merge --no-ff configfs/linux-next
+Already up-to-date.
+Merging ecryptfs/next (07bc9dc Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc)
+$ git merge --no-ff ecryptfs/next
+Already up-to-date.
+Merging ext3/for_next (e729eac udf: Refuse RW mount of the filesystem instead of making it RO)
+$ git merge --no-ff ext3/for_next
+Merge made by the 'recursive' strategy.
+ Documentation/filesystems/ext3.txt |   7 +-
+ fs/ext3/super.c                    |  43 +++++
+ fs/isofs/inode.c                   |  16 +-
+ fs/udf/super.c                     | 342 ++++++++++++++++++++++---------------
+ include/linux/jbd.h                |   2 +-
+ 5 files changed, 260 insertions(+), 150 deletions(-)
+Merging ext4/dev (533ec0e ext4: avoid reusing recently deleted inodes in no journal mode)
+$ git merge --no-ff ext4/dev
+Merge made by the 'recursive' strategy.
+ fs/ext4/ext4.h              |  19 +++-
+ fs/ext4/extents.c           | 259 +++++++++++++++++++++++++++++---------------
+ fs/ext4/extents_status.c    |  98 ++++++++++++++---
+ fs/ext4/extents_status.h    |  50 +++++----
+ fs/ext4/ialloc.c            |  51 +++++++++
+ fs/ext4/inode.c             |   6 +-
+ fs/ext4/ioctl.c             |   3 +
+ fs/ext4/migrate.c           |   2 +-
+ fs/ext4/move_extent.c       |   2 +-
+ fs/ext4/namei.c             |  35 +++---
+ include/trace/events/ext4.h |  28 +++--
+ 11 files changed, 400 insertions(+), 153 deletions(-)
+Merging f2fs/dev (c2d715d f2fs: fix a build failure due to missing the kobject header)
+$ git merge --no-ff f2fs/dev
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-fs-f2fs |  26 +++++
+ Documentation/filesystems/f2fs.txt      |  75 +++++++++++++-
+ fs/f2fs/checkpoint.c                    |  18 ++--
+ fs/f2fs/data.c                          |   9 +-
+ fs/f2fs/debug.c                         |  34 +++----
+ fs/f2fs/dir.c                           |  19 +++-
+ fs/f2fs/f2fs.h                          |  33 +++++--
+ fs/f2fs/file.c                          |  19 ++--
+ fs/f2fs/gc.c                            |  41 +++++---
+ fs/f2fs/gc.h                            |  36 ++++---
+ fs/f2fs/inode.c                         |   6 +-
+ fs/f2fs/namei.c                         |  20 +++-
+ fs/f2fs/node.c                          |  10 +-
+ fs/f2fs/node.h                          |  40 +++-----
+ fs/f2fs/recovery.c                      |   6 +-
+ fs/f2fs/segment.c                       |  29 ++++--
+ fs/f2fs/super.c                         | 170 ++++++++++++++++++++++++++++++++
+ 17 files changed, 465 insertions(+), 126 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-fs-f2fs
+Merging fscache/fscache (bcd7351 Merge tag 'fscache-20130702' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs)
+$ git merge --no-ff fscache/fscache
+Already up-to-date.
+Merging fuse/for-next (c7263bc fuse: readdirplus: cleanup)
+$ git merge --no-ff fuse/for-next
+Already up-to-date.
+Merging gfs2/master (7f59503 GFS2: don't overrun reserved revokes)
+$ git merge --no-ff gfs2/master
+Merge made by the 'recursive' strategy.
+ fs/gfs2/glops.c   | 18 +++++++++++++-----
+ fs/gfs2/inode.c   |  2 +-
+ fs/gfs2/lops.c    | 18 ++++++++++++++++++
+ fs/gfs2/main.c    |  2 +-
+ fs/gfs2/meta_io.c | 18 ------------------
+ fs/gfs2/meta_io.h | 26 +++++++++++---------------
+ 6 files changed, 44 insertions(+), 40 deletions(-)
+Merging jfs/jfs-next (eb8630d jfs: Update jfs_error)
+$ git merge --no-ff jfs/jfs-next
+Already up-to-date.
+Merging logfs/master (3394661 Fix the call to BUG() caused by no free segment found)
+$ git merge --no-ff logfs/master
+Auto-merging fs/logfs/super.c
+Merge made by the 'recursive' strategy.
+ fs/logfs/dev_mtd.c | 2 +-
+ fs/logfs/super.c   | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+Merging nfs/linux-next (44c6a84 Merge branch 'bugfixes' into linux-next)
+$ git merge --no-ff nfs/linux-next
+Merge made by the 'recursive' strategy.
+ fs/lockd/clntlock.c          |  13 +++--
+ fs/lockd/clntproc.c          |   5 +-
+ fs/nfs/client.c              |   6 +--
+ fs/nfs/dir.c                 |   4 ++
+ fs/nfs/inode.c               |  11 ++--
+ fs/nfs/internal.h            |   5 +-
+ fs/nfs/nfs4_fs.h             |   4 +-
+ fs/nfs/nfs4client.c          |   3 +-
+ fs/nfs/nfs4proc.c            |  42 +++++++++------
+ fs/nfs/nfs4session.c         |   2 +-
+ fs/nfs/nfs4session.h         |   2 +-
+ fs/nfs/nfs4state.c           |  78 ++++++++++-----------------
+ fs/nfs/nfs4xdr.c             | 125 ++++++++++++++++++-------------------------
+ fs/nfs/super.c               |  16 ++++++
+ include/linux/nfs_xdr.h      |   2 +-
+ include/linux/sunrpc/sched.h |   1 +
+ net/sunrpc/clnt.c            |   4 ++
+ net/sunrpc/netns.h           |   1 +
+ net/sunrpc/rpc_pipe.c        |  19 +------
+ net/sunrpc/rpcb_clnt.c       |  48 ++++++++++++-----
+ 20 files changed, 196 insertions(+), 195 deletions(-)
+Merging nfsd/nfsd-next (df66e75 nfsd: nfs4_file_get_access: need to be more careful with O_RDWR)
+$ git merge --no-ff nfsd/nfsd-next
+Merge made by the 'recursive' strategy.
+ fs/nfsd/nfs4state.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+Merging ocfs2/linux-next (4538df6 ocfs2: Don't spam on -EDQUOT.)
+$ git merge --no-ff ocfs2/linux-next
+Auto-merging fs/ocfs2/dlm/dlmrecovery.c
+Auto-merging fs/ocfs2/dlm/dlmmaster.c
+Auto-merging fs/ocfs2/cluster/heartbeat.c
+Merge made by the 'recursive' strategy.
+ fs/ocfs2/cluster/heartbeat.c | 40 +++++++++-------------------------------
+ fs/ocfs2/cluster/masklog.h   |  3 ++-
+ fs/ocfs2/dlm/dlmmaster.c     |  8 +++++++-
+ fs/ocfs2/dlm/dlmrecovery.c   |  7 +++++++
+ 4 files changed, 25 insertions(+), 33 deletions(-)
+Merging omfs/for-next (976d167 Linux 3.1-rc9)
+$ git merge --no-ff omfs/for-next
+Already up-to-date.
+Merging squashfs/master (4b0180a Squashfs: add mount time sanity check for block_size and block_log match)
+$ git merge --no-ff squashfs/master
+Already up-to-date.
+Merging v9fs/for-next (b3f8ab4 fs: 9p: use strlcpy instead of strncpy)
+$ git merge --no-ff v9fs/for-next
+Merge made by the 'recursive' strategy.
+ fs/9p/vfs_inode.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+Merging ubifs/linux-next (beadadf UBIFS: correct mount message)
+$ git merge --no-ff ubifs/linux-next
+Already up-to-date.
+Merging xfs/for-next (7a378c9 xfs: WQ_NON_REENTRANT is meaningless and going away)
+$ git merge --no-ff xfs/for-next
+Merge made by the 'recursive' strategy.
+ fs/xfs/xfs_aops.c        | 15 ++++++++-
+ fs/xfs/xfs_log.c         |  2 +-
+ fs/xfs/xfs_mount.c       | 80 +++++++++++++++++++++++++++++++++++++++++++-----
+ fs/xfs/xfs_qm.c          | 72 ++++++++++++++++++++++++++++++++-----------
+ fs/xfs/xfs_qm_syscalls.c | 35 ++++++++++++++++++---
+ fs/xfs/xfs_sb.h          | 13 ++++++--
+ fs/xfs/xfs_super.c       | 25 +++++++--------
+ 7 files changed, 194 insertions(+), 48 deletions(-)
+Merging vfs/for-next (d405be4 ext4: ->tmpfile() support)
+$ git merge --no-ff vfs/for-next
+Resolved 'fs/ext4/namei.c' using previous resolution.
+Resolved 'mm/shmem.c' using previous resolution.
+Auto-merging mm/shmem.c
+CONFLICT (content): Merge conflict in mm/shmem.c
+Auto-merging fs/ext4/namei.c
+CONFLICT (content): Merge conflict in fs/ext4/namei.c
+Auto-merging fs/coredump.c
+Auto-merging fs/binfmt_elf.c
+Auto-merging fs/binfmt_aout.c
+Auto-merging arch/x86/ia32/ia32_aout.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 5af7cf3] Merge remote-tracking branch 'vfs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/ia64/kernel/elfcore.c                   | 13 ++---
+ arch/powerpc/include/asm/spu.h               |  3 +-
+ arch/powerpc/platforms/cell/spu_syscalls.c   |  4 +-
+ arch/powerpc/platforms/cell/spufs/coredump.c | 64 ++++----------------
+ arch/powerpc/platforms/cell/spufs/spufs.h    |  2 +-
+ arch/x86/ia32/ia32_aout.c                    | 20 +++----
+ arch/x86/um/elfcore.c                        | 16 ++---
+ fs/binfmt_aout.c                             |  9 ++-
+ fs/binfmt_elf.c                              | 84 +++++++++++----------------
+ fs/binfmt_elf_fdpic.c                        | 87 ++++++++++------------------
+ fs/coredump.c                                | 62 ++++++++++++--------
+ include/linux/binfmts.h                      |  1 +
+ include/linux/coredump.h                     |  5 +-
+ include/linux/elf.h                          |  7 ++-
+ include/linux/elfcore.h                      |  5 +-
+ kernel/elfcore.c                             |  6 +-
+ 16 files changed, 152 insertions(+), 236 deletions(-)
+Merging pci/next (e3ec221 Merge branch 'pci/wei-resource-cleanups' into next)
+$ git merge --no-ff pci/next
+Auto-merging drivers/pci/setup-bus.c
+Auto-merging drivers/pci/pcie/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/frv/mb93090-mb00/pci-vdk.c |  2 +-
+ arch/x86/pci/mmconfig-shared.c  |  7 +--
+ arch/x86/pci/mrst.c             | 41 ++++++++++--------
+ drivers/pci/iov.c               | 23 ++++++----
+ drivers/pci/pci-sysfs.c         | 32 +++++++++-----
+ drivers/pci/pci.c               | 95 +++++++++++++++++++++++++++++++++--------
+ drivers/pci/pci.h               |  2 +-
+ drivers/pci/pcie/Kconfig        |  2 +-
+ drivers/pci/probe.c             |  2 +-
+ drivers/pci/quirks.c            | 50 ++++++++++++++++++++++
+ drivers/pci/setup-bus.c         | 25 +++++------
+ 11 files changed, 203 insertions(+), 78 deletions(-)
+Merging hid/for-next (920dea8 Merge branch 'for-3.12/wiimote' into for-next)
+$ git merge --no-ff hid/for-next
+Auto-merging net/bluetooth/hidp/core.c
+Auto-merging drivers/hid/hid-sony.c
+Auto-merging drivers/hid/hid-logitech-dj.c
+Auto-merging drivers/hid/hid-ids.h
+Auto-merging drivers/hid/hid-core.c
+Auto-merging drivers/hid/hid-apple.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/hid/hid-over-i2c.txt       | 28 ++++++++
+ Documentation/hid/uhid.txt                         |  4 +-
+ drivers/hid/Kconfig                                |  8 +++
+ drivers/hid/Makefile                               |  1 +
+ drivers/hid/hid-a4tech.c                           | 21 ++----
+ drivers/hid/hid-apple.c                            | 16 +----
+ drivers/hid/hid-core.c                             | 23 ++++++-
+ drivers/hid/hid-holtekff.c                         |  2 +-
+ drivers/hid/hid-ids.h                              |  4 ++
+ drivers/hid/hid-input.c                            | 80 +++++++++++++++++++++-
+ drivers/hid/hid-kye.c                              | 45 +++++++-----
+ drivers/hid/hid-logitech-dj.c                      | 22 ++++--
+ drivers/hid/hid-magicmouse.c                       | 19 ++---
+ drivers/hid/hid-multitouch.c                       | 71 +++++++------------
+ drivers/hid/hid-ntrig.c                            | 12 ++--
+ drivers/hid/hid-picolcd_debugfs.c                  | 23 ++++---
+ drivers/hid/hid-roccat-arvo.c                      |  6 +-
+ drivers/hid/hid-roccat-isku.c                      |  2 +-
+ drivers/hid/hid-roccat-kone.c                      |  4 +-
+ drivers/hid/hid-roccat-koneplus.c                  |  2 +-
+ drivers/hid/hid-roccat-kovaplus.c                  |  2 +-
+ drivers/hid/hid-sony.c                             |  9 +--
+ drivers/hid/hid-wiimote-core.c                     | 10 +--
+ drivers/hid/hid-xinmo.c                            | 72 +++++++++++++++++++
+ drivers/hid/hid-zydacron.c                         | 19 +----
+ drivers/hid/i2c-hid/i2c-hid.c                      | 72 +++++++++++--------
+ drivers/hid/uhid.c                                 | 25 -------
+ drivers/hid/usbhid/hid-core.c                      | 72 ++-----------------
+ drivers/hid/usbhid/usbhid.h                        |  3 -
+ include/linux/hid.h                                |  3 +-
+ include/linux/i2c/i2c-hid.h                        |  3 +-
+ include/uapi/linux/uhid.h                          |  4 +-
+ net/bluetooth/hidp/core.c                          | 15 ++--
+ 33 files changed, 400 insertions(+), 302 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/hid/hid-over-i2c.txt
+ create mode 100644 drivers/hid/hid-xinmo.c
+Merging i2c/i2c/for-next (2806914 drivers/i2c/busses: don't check resource with devm_ioremap_resource)
+$ git merge --no-ff i2c/i2c/for-next
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/i2c/i2c-mv64xxx.txt        |  2 +-
+ drivers/i2c/busses/i2c-designware-core.c           | 14 +++++
+ drivers/i2c/busses/i2c-kempld.c                    |  4 +-
+ drivers/i2c/busses/i2c-mpc.c                       |  5 +-
+ drivers/i2c/busses/i2c-mxs.c                       |  2 +-
+ drivers/i2c/busses/i2c-omap.c                      | 13 -----
+ drivers/i2c/busses/i2c-pxa.c                       | 64 +++++++++++++++++++++-
+ drivers/i2c/busses/i2c-stu300.c                    |  3 -
+ drivers/i2c/i2c-core.c                             |  3 +-
+ include/linux/i2c.h                                |  2 +
+ include/linux/i2c/pxa-i2c.h                        |  3 +
+ 11 files changed, 92 insertions(+), 23 deletions(-)
+Merging jdelvare-hwmon/master (6f7e0b6 hwmon: (w83792d) Update module author)
+$ git merge --no-ff jdelvare-hwmon/master
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/w83791d | 2 +-
+ Documentation/hwmon/w83792d | 3 +--
+ drivers/hwmon/w83792d.c     | 4 ++--
+ 3 files changed, 4 insertions(+), 5 deletions(-)
+Merging hwmon-staging/hwmon-next (abb749c hwmon: (acpi_power_meter) Fix incorrect placement of __initdata)
+$ git merge --no-ff hwmon-staging/hwmon-next
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/ads1015      |    8 +-
+ drivers/hwmon/Kconfig            |    4 +-
+ drivers/hwmon/acpi_power_meter.c |    2 +-
+ drivers/hwmon/ads1015.c          |   27 +-
+ drivers/hwmon/ads7828.c          |    2 +-
+ drivers/hwmon/adt7470.c          |    2 +-
+ drivers/hwmon/coretemp.c         |   14 +-
+ drivers/hwmon/ds620.c            |    2 +-
+ drivers/hwmon/emc6w201.c         |    2 +-
+ drivers/hwmon/f71805f.c          |    2 +-
+ drivers/hwmon/f71882fg.c         |    2 +-
+ drivers/hwmon/f75375s.c          |    3 +-
+ drivers/hwmon/g762.c             |    2 +-
+ drivers/hwmon/gpio-fan.c         |    2 +-
+ drivers/hwmon/ina2xx.c           |    4 +-
+ drivers/hwmon/it87.c             |    6 +-
+ drivers/hwmon/lm87.c             |    4 +-
+ drivers/hwmon/max197.c           |    2 +-
+ drivers/hwmon/max6639.c          |    2 +-
+ drivers/hwmon/mcp3021.c          |    7 +-
+ drivers/hwmon/nct6775.c          | 2531 +++++++++++++++++++-------------------
+ drivers/hwmon/ntc_thermistor.c   |    2 +-
+ drivers/hwmon/pc87427.c          |    4 +-
+ drivers/hwmon/pmbus/pmbus_core.c |    2 +-
+ drivers/hwmon/s3c-hwmon.c        |    6 +-
+ drivers/hwmon/sht15.c            |    4 +-
+ drivers/hwmon/smsc47m1.c         |    4 +-
+ drivers/hwmon/w83627ehf.c        |   22 +-
+ drivers/hwmon/w83627hf.c         |    6 +-
+ 29 files changed, 1344 insertions(+), 1336 deletions(-)
+Merging v4l-dvb/master (e5c9146 Merge /home/v4l/v4l/patchwork)
+$ git merge --no-ff v4l-dvb/master
+Merge made by the 'recursive' strategy.
+ .../DocBook/media/v4l/lirc_device_interface.xml    |    4 +-
+ .../DocBook/media/v4l/vidioc-g-jpegcomp.xml        |    4 +-
+ Documentation/DocBook/media_api.tmpl               |    4 +-
+ .../devicetree/bindings/media/i2c/adv7343.txt      |   48 +
+ .../devicetree/bindings/media/i2c/ths8200.txt      |   19 +
+ arch/arm/mach-davinci/board-da850-evm.c            |    6 +-
+ drivers/media/dvb-core/dvb-usb-ids.h               |    2 +
+ drivers/media/i2c/adv7343.c                        |   89 +-
+ drivers/media/i2c/ml86v7667.c                      |    7 +-
+ drivers/media/i2c/ths8200.c                        |   18 +-
+ drivers/media/i2c/tvp514x.c                        |   20 +-
+ drivers/media/i2c/tvp7002.c                        |    6 +
+ drivers/media/pci/bt8xx/bttv-cards.c               |   26 +-
+ drivers/media/pci/bt8xx/bttvp.h                    |    3 +
+ drivers/media/pci/cx23885/cx23885-av.c             |   13 +
+ drivers/media/pci/cx23885/cx23885-dvb.c            |    4 +
+ drivers/media/pci/cx23885/cx23885-video.c          |    5 +-
+ drivers/media/pci/cx23885/cx23885-video.h          |   26 +
+ drivers/media/platform/coda.c                      | 1471 +++++++++++++++++---
+ drivers/media/platform/coda.h                      |  107 +-
+ drivers/media/platform/davinci/vpbe_display.c      |   23 +-
+ drivers/media/platform/davinci/vpbe_osd.c          |   45 +-
+ drivers/media/platform/davinci/vpbe_venc.c         |   97 +-
+ drivers/media/platform/davinci/vpif_capture.c      |  151 +-
+ drivers/media/platform/davinci/vpif_capture.h      |    2 +
+ drivers/media/platform/davinci/vpif_display.c      |  210 +--
+ drivers/media/platform/davinci/vpif_display.h      |    3 +-
+ drivers/media/platform/davinci/vpss.c              |   62 +-
+ drivers/media/platform/marvell-ccic/cafe-driver.c  |    4 +-
+ drivers/media/platform/marvell-ccic/mcam-core.c    |  325 ++++-
+ drivers/media/platform/marvell-ccic/mcam-core.h    |   50 +-
+ drivers/media/platform/marvell-ccic/mmp-driver.c   |  274 +++-
+ drivers/media/platform/s5p-g2d/g2d.c               |    1 +
+ drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |   79 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |   46 +-
+ .../platform/soc_camera/sh_mobile_ceu_camera.c     |    6 +-
+ drivers/media/platform/soc_camera/soc_camera.c     |    4 +-
+ drivers/media/radio/radio-aztech.c                 |   81 +-
+ drivers/media/radio/radio-maxiradio.c              |   13 +-
+ drivers/media/rc/ene_ir.c                          |   30 +-
+ drivers/media/rc/ene_ir.h                          |    2 +-
+ drivers/media/rc/iguanair.c                        |    4 +-
+ drivers/media/rc/ir-lirc-codec.c                   |   12 +-
+ drivers/media/rc/lirc_dev.c                        |   10 +
+ drivers/media/rc/rc-main.c                         |   46 +-
+ drivers/media/rc/redrat3.c                         |   34 +-
+ drivers/media/usb/dvb-usb-v2/Kconfig               |    2 +-
+ drivers/media/usb/dvb-usb/dib0700_devices.c        |   12 +-
+ drivers/media/usb/dvb-usb/m920x.c                  |    2 +-
+ drivers/media/usb/em28xx/em28xx-i2c.c              |    2 +-
+ drivers/media/usb/em28xx/em28xx-video.c            |    1 +
+ drivers/media/usb/hdpvr/hdpvr-core.c               |   11 +-
+ drivers/media/usb/s2255/s2255drv.c                 |    9 +-
+ drivers/media/usb/stk1160/Kconfig                  |   16 +-
+ drivers/media/usb/stk1160/stk1160-v4l.c            |    6 +-
+ drivers/media/usb/tlg2300/pd-main.c                |   37 +-
+ drivers/media/usb/usbtv/Kconfig                    |    2 +-
+ drivers/media/usb/usbtv/usbtv.c                    |  151 +-
+ drivers/media/v4l2-core/v4l2-async.c               |  106 +-
+ drivers/media/v4l2-core/v4l2-mem2mem.c             |   10 +-
+ drivers/staging/media/lirc/lirc_igorplugusb.c      |   56 +-
+ include/media/adv7343.h                            |   20 +-
+ include/media/davinci/vpif_types.h                 |    4 +
+ include/media/lirc_dev.h                           |    1 +
+ include/media/rc-core.h                            |    4 +
+ include/media/v4l2-async.h                         |   36 +-
+ include/media/v4l2-ctrls.h                         |    1 +
+ include/media/v4l2-mem2mem.h                       |   13 +
+ include/media/v4l2-subdev.h                        |   13 +-
+ include/sound/tea575x-tuner.h                      |    1 +
+ sound/i2c/other/tea575x-tuner.c                    |   19 +-
+ 71 files changed, 2976 insertions(+), 1055 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7343.txt
+ create mode 100644 Documentation/devicetree/bindings/media/i2c/ths8200.txt
+ create mode 100644 drivers/media/pci/cx23885/cx23885-video.h
+Merging kbuild/for-next (8de6aeb Merge branches 'kbuild/kconfig' and 'kbuild/misc' into kbuild/for-next)
+$ git merge --no-ff kbuild/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/kbuild/kconfig.txt |  8 ++--
+ scripts/kconfig/mconf.c          |  4 +-
+ scripts/kconfig/nconf.c          |  4 +-
+ scripts/kconfig/symbol.c         | 49 +++++++++------------
+ scripts/package/builddeb         | 92 +++++++++++++++++++++++++++++++++-------
+ scripts/package/mkspec           | 46 +++++++++++++++++---
+ 6 files changed, 144 insertions(+), 59 deletions(-)
+Merging kconfig/for-next (4eae518 localmodconfig: Fix localyesconfig to set to 'y' not 'm')
+$ git merge --no-ff kconfig/for-next
+Already up-to-date.
+Merging libata/for-next (3ea47c0 Merge branch 'for-3.12' into for-next)
+$ git merge --no-ff libata/for-next
+Merge made by the 'recursive' strategy.
+ drivers/ata/libata.h          |   4 --
+ drivers/ata/pata_at32.c       |   2 +-
+ drivers/ata/pata_at91.c       |   2 +-
+ drivers/ata/pata_ixp4xx_cf.c  |   4 +-
+ drivers/ata/pata_octeon_cf.c  |   2 +-
+ drivers/ata/pata_platform.c   |   2 +-
+ drivers/ata/pata_pxa.c        |   2 +-
+ drivers/ata/pata_samsung_cf.c |   4 +-
+ drivers/ata/sata_mv.c         |  26 ++++-------
+ include/linux/ata.h           | 102 ------------------------------------------
+ include/linux/libata.h        | 102 ++++++++++++++++++++++++++++++++++++++++++
+ 11 files changed, 119 insertions(+), 133 deletions(-)
+Merging pstore/master (bd08ec3 pstore/ram: Restore ecc information block)
+$ git merge --no-ff pstore/master
+Already up-to-date.
+Merging pm/linux-next (38fcf54 Merge branch 'acpi-assorted-next' into linux-next)
+$ git merge --no-ff pm/linux-next
+Auto-merging drivers/cpuidle/cpuidle-ux500.c
+Removing drivers/cpufreq/mperf.h
+Removing drivers/cpufreq/mperf.c
+Merge made by the 'recursive' strategy.
+ Documentation/cpu-freq/cpu-drivers.txt             |    2 -
+ Documentation/kernel-parameters.txt                |   55 +-
+ Documentation/laptops/asus-laptop.txt              |    8 +-
+ Documentation/laptops/sony-laptop.txt              |    8 +-
+ Documentation/laptops/thinkpad-acpi.txt            |   73 +-
+ arch/arm/mach-davinci/cpuidle.c                    |    2 +-
+ arch/arm/mach-ux500/Makefile                       |    1 -
+ arch/x86/include/asm/processor.h                   |   29 -
+ arch/x86/kernel/tboot.c                            |   10 +
+ arch/x86/pci/i386.c                                |    4 +
+ drivers/acpi/Kconfig                               |   18 -
+ drivers/acpi/ac.c                                  |    1 -
+ drivers/acpi/acpi_pad.c                            |    1 -
+ drivers/acpi/acpi_platform.c                       |   24 +-
+ drivers/acpi/acpi_processor.c                      |    3 +-
+ drivers/acpi/acpica/aclocal.h                      |    3 +
+ drivers/acpi/acpica/actables.h                     |    5 +
+ drivers/acpi/acpica/acutils.h                      |    4 +-
+ drivers/acpi/acpica/evgpeinit.c                    |   11 -
+ drivers/acpi/acpica/exdump.c                       |    6 +-
+ drivers/acpi/acpica/hwesleep.c                     |    9 +
+ drivers/acpi/acpica/nsxfname.c                     |   11 +-
+ drivers/acpi/acpica/tbxfroot.c                     |    4 +-
+ drivers/acpi/acpica/uteval.c                       |    8 +-
+ drivers/acpi/acpica/utosi.c                        |   77 +-
+ drivers/acpi/acpica/utstring.c                     |    5 +-
+ drivers/acpi/acpica/utxface.c                      |   29 +
+ drivers/acpi/battery.c                             |   21 +-
+ drivers/acpi/blacklist.c                           |   14 +
+ drivers/acpi/bus.c                                 |  142 +--
+ drivers/acpi/button.c                              |    2 -
+ drivers/acpi/device_pm.c                           |   34 +-
+ drivers/acpi/dock.c                                |  398 +++-----
+ drivers/acpi/ec.c                                  |    6 +-
+ drivers/acpi/event.c                               |  106 --
+ drivers/acpi/fan.c                                 |    4 +-
+ drivers/acpi/glue.c                                |  212 ++--
+ drivers/acpi/internal.h                            |    1 +
+ drivers/acpi/osl.c                                 |   46 +-
+ drivers/acpi/pci_slot.c                            |   14 +-
+ drivers/acpi/power.c                               |    6 +-
+ drivers/acpi/proc.c                                |    8 +
+ drivers/acpi/processor_core.c                      |    2 +-
+ drivers/acpi/processor_driver.c                    |    4 -
+ drivers/acpi/processor_perflib.c                   |   22 +-
+ drivers/acpi/resource.c                            |    4 +-
+ drivers/acpi/sbs.c                                 |   15 +-
+ drivers/acpi/scan.c                                |  223 ++---
+ drivers/acpi/sleep.c                               |    9 +-
+ drivers/acpi/thermal.c                             |   21 +-
+ drivers/acpi/utils.c                               |   70 ++
+ drivers/acpi/video.c                               |  248 ++---
+ drivers/acpi/video_detect.c                        |   19 +-
+ drivers/ata/libata-acpi.c                          |    4 +-
+ drivers/base/power/main.c                          |   77 +-
+ drivers/base/power/opp.c                           |    1 +
+ drivers/char/sonypi.c                              |    5 -
+ drivers/cpufreq/Makefile                           |    2 +-
+ drivers/cpufreq/acpi-cpufreq.c                     |   10 +-
+ drivers/cpufreq/at32ap-cpufreq.c                   |    1 -
+ drivers/cpufreq/blackfin-cpufreq.c                 |    1 -
+ drivers/cpufreq/cpufreq-nforce2.c                  |    1 -
+ drivers/cpufreq/cpufreq.c                          |  721 ++++++++------
+ drivers/cpufreq/cpufreq_conservative.c             |   34 +-
+ drivers/cpufreq/cpufreq_governor.c                 |   24 +-
+ drivers/cpufreq/cpufreq_governor.h                 |   12 +-
+ drivers/cpufreq/cpufreq_ondemand.c                 |   83 +-
+ drivers/cpufreq/cpufreq_performance.c              |    3 +-
+ drivers/cpufreq/cpufreq_powersave.c                |    3 +-
+ drivers/cpufreq/cpufreq_stats.c                    |   31 +-
+ drivers/cpufreq/cris-artpec3-cpufreq.c             |    1 -
+ drivers/cpufreq/cris-etraxfs-cpufreq.c             |    1 -
+ drivers/cpufreq/e_powersaver.c                     |    5 +-
+ drivers/cpufreq/elanfreq.c                         |    1 -
+ drivers/cpufreq/exynos-cpufreq.c                   |    2 +-
+ drivers/cpufreq/freq_table.c                       |    4 +-
+ drivers/cpufreq/gx-suspmod.c                       |    3 +-
+ drivers/cpufreq/ia64-acpi-cpufreq.c                |    5 +-
+ drivers/cpufreq/intel_pstate.c                     |    1 -
+ drivers/cpufreq/kirkwood-cpufreq.c                 |    1 -
+ drivers/cpufreq/longhaul.c                         |    1 -
+ drivers/cpufreq/longrun.c                          |    1 -
+ drivers/cpufreq/loongson2_cpufreq.c                |   12 +-
+ drivers/cpufreq/maple-cpufreq.c                    |    1 -
+ drivers/cpufreq/mperf.c                            |   51 -
+ drivers/cpufreq/mperf.h                            |    9 -
+ drivers/cpufreq/p4-clockmod.c                      |    1 -
+ drivers/cpufreq/pasemi-cpufreq.c                   |    1 -
+ drivers/cpufreq/pcc-cpufreq.c                      |    1 -
+ drivers/cpufreq/pmac32-cpufreq.c                   |    1 -
+ drivers/cpufreq/pmac64-cpufreq.c                   |    6 +-
+ drivers/cpufreq/powernow-k6.c                      |    1 -
+ drivers/cpufreq/powernow-k7.c                      |   14 +-
+ drivers/cpufreq/powernow-k8.c                      |    7 +-
+ drivers/cpufreq/ppc-corenet-cpufreq.c              |    1 -
+ drivers/cpufreq/ppc_cbe_cpufreq.c                  |    1 -
+ drivers/cpufreq/s3c2416-cpufreq.c                  |    1 -
+ drivers/cpufreq/s3c24xx-cpufreq.c                  |    6 +-
+ drivers/cpufreq/s3c64xx-cpufreq.c                  |    1 -
+ drivers/cpufreq/sc520_freq.c                       |    1 -
+ drivers/cpufreq/sh-cpufreq.c                       |    1 -
+ drivers/cpufreq/sparc-us2e-cpufreq.c               |    6 +-
+ drivers/cpufreq/sparc-us3-cpufreq.c                |    6 +-
+ drivers/cpufreq/speedstep-centrino.c               |    1 -
+ drivers/cpufreq/speedstep-ich.c                    |    1 -
+ drivers/cpufreq/speedstep-smi.c                    |    1 -
+ drivers/cpuidle/Kconfig                            |   20 +-
+ drivers/cpuidle/Kconfig.arm                        |   29 +
+ drivers/cpuidle/Makefile                           |    9 +-
+ .../cpuidle.c => drivers/cpuidle/cpuidle-ux500.c   |   19 +-
+ drivers/cpuidle/cpuidle.c                          |   94 +-
+ drivers/cpuidle/governors/ladder.c                 |   12 +-
+ drivers/cpuidle/governors/menu.c                   |   12 +-
+ drivers/cpuidle/sysfs.c                            |  101 +-
+ drivers/ide/ide-acpi.c                             |    5 +-
+ drivers/mfd/db8500-prcmu.c                         |    4 +
+ drivers/pci/hotplug/acpiphp.h                      |   55 +-
+ drivers/pci/hotplug/acpiphp_core.c                 |   18 +-
+ drivers/pci/hotplug/acpiphp_glue.c                 | 1031 ++++++++------------
+ drivers/pci/hotplug/acpiphp_ibm.c                  |    3 +-
+ drivers/pci/pci-acpi.c                             |   33 +-
+ drivers/platform/x86/asus-laptop.c                 |    1 -
+ drivers/platform/x86/eeepc-laptop.c                |    1 -
+ drivers/platform/x86/fujitsu-laptop.c              |    4 -
+ drivers/platform/x86/panasonic-laptop.c            |    3 -
+ drivers/platform/x86/sony-laptop.c                 |    4 -
+ drivers/platform/x86/thinkpad_acpi.c               |   40 -
+ drivers/pnp/driver.c                               |   21 +-
+ drivers/pnp/pnpacpi/core.c                         |    6 +-
+ drivers/xen/acpi.c                                 |   41 +-
+ include/acpi/acpi_bus.h                            |   39 +-
+ include/acpi/acpi_drivers.h                        |   14 +-
+ include/acpi/acpixf.h                              |    4 +-
+ include/acpi/actypes.h                             |   21 +-
+ include/linux/acpi.h                               |    7 +
+ include/linux/cpufreq.h                            |  388 ++++----
+ include/linux/cpuidle.h                            |    9 +-
+ include/linux/pci-acpi.h                           |   10 +-
+ include/trace/events/power.h                       |   37 +
+ include/xen/acpi.h                                 |    8 +-
+ include/xen/interface/platform.h                   |    7 +-
+ kernel/power/suspend.c                             |    4 +-
+ 142 files changed, 2390 insertions(+), 2957 deletions(-)
+ delete mode 100644 drivers/cpufreq/mperf.c
+ delete mode 100644 drivers/cpufreq/mperf.h
+ create mode 100644 drivers/cpuidle/Kconfig.arm
+ rename arch/arm/mach-ux500/cpuidle.c => drivers/cpuidle/cpuidle-ux500.c (90%)
+Merging idle/next (5c99726b Merge branch 'fspin' into next)
+$ git merge --no-ff idle/next
+Merge made by the 'recursive' strategy.
+ tools/power/fspin/Makefile |  21 +++
+ tools/power/fspin/fspin.1  |  68 +++++++
+ tools/power/fspin/fspin.c  | 443 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 532 insertions(+)
+ create mode 100644 tools/power/fspin/Makefile
+ create mode 100644 tools/power/fspin/fspin.1
+ create mode 100644 tools/power/fspin/fspin.c
+Merging apm/for-next (fb9d78a Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm)
+$ git merge --no-ff apm/for-next
+Already up-to-date.
+Merging cpupowerutils/master (f166033 cpupower tools: add install target to the debug tools' makefiles)
+$ git merge --no-ff cpupowerutils/master
+Already up-to-date.
+Merging thermal/next (ace120d Thermal: Fix lockup of cpu_down())
+$ git merge --no-ff thermal/next
+Already up-to-date.
+Merging ieee1394/for-next (0a41981 firewire: core: typecast from gfp_t to bool more safely)
+$ git merge --no-ff ieee1394/for-next
+Merge made by the 'recursive' strategy.
+ drivers/firewire/core-cdev.c        | 2 +-
+ drivers/firewire/core-transaction.c | 3 +--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+Merging ubi/linux-next (83ff59a UBI: support ubi_num on mtd.ubi command line)
+$ git merge --no-ff ubi/linux-next
+Already up-to-date.
+Merging dlm/next (ededf30 dlm: WQ_NON_REENTRANT is meaningless and going away)
+$ git merge --no-ff dlm/next
+Merge made by the 'recursive' strategy.
+ fs/dlm/ast.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+Merging swiotlb/linux-next (af51a9f swiotlb: Do not export swiotlb_bounce since there are no external consumers)
+$ git merge --no-ff swiotlb/linux-next
+Already up-to-date.
+Merging slave-dma/next (2194971 Merge branch 'for-linus' into next)
+$ git merge --no-ff slave-dma/next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                   |  1 +
+ drivers/dma/acpi-dma.c        |  2 +-
+ drivers/dma/dw/core.c         | 39 ++++++++++++++++++-----------
+ drivers/dma/dw/platform.c     |  1 +
+ drivers/dma/edma.c            |  2 --
+ drivers/dma/ep93xx_dma.c      | 10 +-------
+ drivers/dma/fsldma.c          | 10 +-------
+ drivers/dma/imx-sdma.c        |  9 +++----
+ drivers/dma/ipu/ipu_idmac.c   |  5 +---
+ drivers/dma/mmp_pdma.c        | 58 ++++++++++++++++++++++++-------------------
+ drivers/dma/mmp_tdma.c        |  3 ++-
+ drivers/dma/mpc512x_dma.c     | 10 +-------
+ drivers/dma/mxs-dma.c         |  4 +--
+ drivers/dma/pch_dma.c         |  9 +------
+ drivers/dma/pl330.c           | 27 ++++++++++++++++++++
+ drivers/dma/tegra20-apb-dma.c |  8 +++---
+ drivers/dma/txx9dmac.c        | 13 +++++-----
+ include/linux/dmaengine.h     | 44 ++++++++++++++++++++++++++++++++
+ 18 files changed, 151 insertions(+), 104 deletions(-)
+Merging dmaengine/next (41ef2d5 Linux 3.9-rc7)
+$ git merge --no-ff dmaengine/next
+Already up-to-date.
+Merging net-next/master (09effa6 packet: Revert recent header parsing changes.)
+$ git merge --no-ff net-next/master
+Auto-merging net/vmw_vsock/af_vsock.c
+Auto-merging net/ipv6/ip6_fib.c
+Auto-merging drivers/pci/probe.c
+Auto-merging drivers/pci/pci.h
+Auto-merging drivers/pci/pci.c
+Auto-merging drivers/net/macvlan.c
+Auto-merging drivers/net/bonding/bond_main.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/networking/00-INDEX                  |    2 +
+ Documentation/networking/ip-sysctl.txt             |   17 +
+ Documentation/networking/netdev-FAQ.txt            |  224 ++++
+ Documentation/networking/sctp.txt                  |    5 +-
+ MAINTAINERS                                        |    1 +
+ arch/tile/gxio/iorpc_mpipe.c                       |   66 ++
+ arch/tile/gxio/iorpc_mpipe_info.c                  |   18 +
+ arch/tile/gxio/mpipe.c                             |   43 +-
+ arch/tile/include/gxio/iorpc_mpipe.h               |   14 +-
+ arch/tile/include/gxio/iorpc_mpipe_info.h          |    4 +
+ arch/tile/include/gxio/mpipe.h                     |  143 ++-
+ arch/tile/include/hv/drv_mpipe_intf.h              |    3 +
+ drivers/isdn/hardware/mISDN/hfcpci.c               |   12 +-
+ drivers/net/bonding/bond_3ad.c                     |   44 +-
+ drivers/net/bonding/bond_alb.c                     |   57 +-
+ drivers/net/bonding/bond_main.c                    |  603 ++++-------
+ drivers/net/bonding/bond_procfs.c                  |   12 +-
+ drivers/net/bonding/bond_sysfs.c                   |   83 +-
+ drivers/net/bonding/bonding.h                      |   85 +-
+ drivers/net/can/flexcan.c                          |   81 +-
+ drivers/net/ethernet/8390/ax88796.c                |    4 +-
+ drivers/net/ethernet/amd/pcnet32.c                 |    6 +-
+ drivers/net/ethernet/broadcom/bnx2.c               |  308 +++---
+ drivers/net/ethernet/broadcom/bnx2.h               |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |   16 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h    |    1 +
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |   56 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c     |  299 +++++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h     |   16 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c  |   10 +-
+ drivers/net/ethernet/broadcom/cnic.c               |   91 +-
+ drivers/net/ethernet/broadcom/cnic.h               |    2 +-
+ drivers/net/ethernet/broadcom/cnic_defs.h          |    6 +-
+ drivers/net/ethernet/broadcom/cnic_if.h            |   12 +-
+ drivers/net/ethernet/broadcom/tg3.c                |  103 +-
+ drivers/net/ethernet/broadcom/tg3.h                |   12 +-
+ drivers/net/ethernet/brocade/bna/bna_tx_rx.c       |   10 +-
+ drivers/net/ethernet/cisco/enic/Makefile           |    3 +-
+ drivers/net/ethernet/cisco/enic/enic.h             |   48 +
+ drivers/net/ethernet/cisco/enic/enic_dev.h         |    1 +
+ drivers/net/ethernet/cisco/enic/enic_ethtool.c     |  257 +++++
+ drivers/net/ethernet/cisco/enic/enic_main.c        |  270 +----
+ drivers/net/ethernet/dec/tulip/tulip_core.c        |    8 +-
+ drivers/net/ethernet/emulex/benet/be.h             |    2 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.c        |  156 ++-
+ drivers/net/ethernet/emulex/benet/be_cmds.h        |   18 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |  234 ++--
+ drivers/net/ethernet/emulex/benet/be_roce.c        |    6 +-
+ drivers/net/ethernet/freescale/fec_main.c          |  110 +-
+ drivers/net/ethernet/freescale/gianfar.c           |  101 +-
+ drivers/net/ethernet/freescale/gianfar.h           |    4 +-
+ drivers/net/ethernet/i825xx/sun3_82586.h           |    4 +-
+ drivers/net/ethernet/intel/e100.c                  |   15 +-
+ drivers/net/ethernet/intel/e1000e/82571.c          |    1 +
+ drivers/net/ethernet/intel/e1000e/e1000.h          |    3 -
+ drivers/net/ethernet/intel/e1000e/ethtool.c        |  105 +-
+ drivers/net/ethernet/intel/e1000e/hw.h             |   10 +-
+ drivers/net/ethernet/intel/e1000e/ich8lan.c        |  140 ++-
+ drivers/net/ethernet/intel/e1000e/ich8lan.h        |    6 +
+ drivers/net/ethernet/intel/e1000e/netdev.c         |   38 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe.h           |    7 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c     |   34 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c     |  240 ++++-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.c    |   90 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h    |    2 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c   |   94 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |  167 ++-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c       |  470 ++++++---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h       |   41 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c       |   12 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c     |  101 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h      |   12 +
+ drivers/net/ethernet/marvell/mvneta.c              |   61 +-
+ drivers/net/ethernet/mellanox/mlx4/cmd.c           |   22 +-
+ drivers/net/ethernet/mellanox/mlx4/en_tx.c         |   61 +-
+ drivers/net/ethernet/mellanox/mlx4/eq.c            |    9 +
+ drivers/net/ethernet/mellanox/mlx4/fw.c            |  104 ++
+ drivers/net/ethernet/mellanox/mlx4/fw.h            |    1 +
+ drivers/net/ethernet/mellanox/mlx4/main.c          |   35 +-
+ drivers/net/ethernet/mellanox/mlx4/mcg.c           |   11 -
+ drivers/net/ethernet/mellanox/mlx4/mlx4.h          |   13 +
+ drivers/net/ethernet/micrel/ks8842.c               |   10 +-
+ drivers/net/ethernet/micrel/ks8851_mll.c           |    2 +-
+ drivers/net/ethernet/myricom/myri10ge/myri10ge.c   |    2 +-
+ drivers/net/ethernet/nuvoton/w90p910_ether.c       |    4 +-
+ drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h    |   15 +
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |   51 +-
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c    |   98 ++
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h    |    1 +
+ drivers/net/ethernet/pasemi/pasemi_mac.c           |   13 +-
+ drivers/net/ethernet/pasemi/pasemi_mac.h           |    2 +-
+ drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c |    4 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |   59 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |  615 ++++++++---
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |   27 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |   83 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c    |    6 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c     |    6 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   18 +-
+ .../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c   |  146 +--
+ drivers/net/ethernet/qlogic/qlge/qlge.h            |    2 +-
+ drivers/net/ethernet/renesas/Kconfig               |    2 +-
+ drivers/net/ethernet/renesas/sh_eth.c              |   26 +
+ drivers/net/ethernet/renesas/sh_eth.h              |    2 +
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    3 -
+ drivers/net/ethernet/ti/cpsw.c                     |  233 +++-
+ drivers/net/ethernet/tile/Kconfig                  |   11 +
+ drivers/net/ethernet/tile/tilegx.c                 | 1114 +++++++++++++-------
+ drivers/net/ethernet/tile/tilepro.c                |  241 ++---
+ drivers/net/ethernet/via/via-velocity.c            |   20 +
+ drivers/net/macvlan.c                              |    3 +
+ drivers/net/macvtap.c                              |  103 --
+ drivers/net/phy/mdio-mux-mmioreg.c                 |    2 +-
+ drivers/net/phy/micrel.c                           |    2 +-
+ drivers/net/team/team.c                            |  201 +++-
+ drivers/net/tun.c                                  |  157 +--
+ drivers/net/usb/asix_devices.c                     |    3 +
+ drivers/net/usb/ax88179_178a.c                     |   24 +-
+ drivers/net/usb/usbnet.c                           |   54 +-
+ drivers/net/virtio_net.c                           |   42 +-
+ drivers/net/vxlan.c                                |   54 +-
+ drivers/pci/pci.c                                  |   43 +
+ drivers/pci/pci.h                                  |    3 +
+ drivers/pci/probe.c                                |    4 +-
+ drivers/scsi/bnx2i/57xx_iscsi_hsi.h                |   12 +-
+ drivers/scsi/bnx2i/bnx2i_init.c                    |   12 +-
+ include/linux/dm9000.h                             |    4 +-
+ include/linux/fs_enet_pd.h                         |    3 +-
+ include/linux/ieee80211.h                          |   59 +-
+ include/linux/if_team.h                            |   14 +-
+ include/linux/igmp.h                               |    1 -
+ include/linux/mlx4/cmd.h                           |    1 +
+ include/linux/mlx4/device.h                        |   12 +-
+ include/linux/mlx4/qp.h                            |    5 +-
+ include/linux/mv643xx_eth.h                        |    3 +-
+ include/linux/netdevice.h                          |   24 +-
+ include/linux/pci.h                                |   15 +
+ include/linux/pci_hotplug.h                        |   13 -
+ include/linux/sh_eth.h                             |    3 +-
+ include/linux/skbuff.h                             |   13 +-
+ include/linux/smsc911x.h                           |    3 +-
+ include/linux/socket.h                             |    2 +
+ include/linux/tcp.h                                |    2 +-
+ include/linux/usb/usbnet.h                         |    3 +
+ include/linux/uwb/spec.h                           |    5 +-
+ include/media/tveeprom.h                           |    4 +-
+ include/net/9p/transport.h                         |    3 -
+ include/net/act_api.h                              |   60 +-
+ include/net/addrconf.h                             |  160 ++-
+ include/net/af_rxrpc.h                             |   35 +-
+ include/net/af_unix.h                              |   16 +-
+ {net/vmw_vsock => include/net}/af_vsock.h          |    0
+ include/net/arp.h                                  |   30 +-
+ include/net/ax25.h                                 |  215 ++--
+ include/net/cfg80211.h                             |   34 +-
+ include/net/checksum.h                             |   10 +-
+ include/net/cls_cgroup.h                           |    2 +-
+ include/net/fib_rules.h                            |   14 +-
+ include/net/ip_tunnels.h                           |    4 +-
+ include/net/irda/irlan_common.h                    |    3 +-
+ include/net/mac80211.h                             |   16 +-
+ include/net/neighbour.h                            |   98 +-
+ include/net/net_namespace.h                        |   37 +-
+ include/net/netns/ipv4.h                           |    1 +
+ include/net/netns/ipv6.h                           |    1 +
+ include/net/netprio_cgroup.h                       |    2 +-
+ include/net/pkt_cls.h                              |   42 +-
+ include/net/pkt_sched.h                            |   50 +-
+ include/net/sch_generic.h                          |   53 +-
+ include/net/sctp/auth.h                            |    2 +-
+ include/net/sctp/checksum.h                        |   17 +-
+ include/net/sctp/constants.h                       |    2 +-
+ include/net/sctp/sctp.h                            |    4 +-
+ include/net/sctp/sm.h                              |    2 +-
+ include/net/sctp/structs.h                         |    3 +-
+ include/net/sctp/tsnmap.h                          |    2 +-
+ include/net/sctp/ulpevent.h                        |    2 +-
+ include/net/sctp/ulpqueue.h                        |    2 +-
+ include/net/sock.h                                 |   24 +-
+ include/net/tcp.h                                  |   28 +-
+ include/net/udp.h                                  |    1 +
+ {net/vmw_vsock => include/net}/vsock_addr.h        |    0
+ include/uapi/linux/dn.h                            |    3 +-
+ include/uapi/linux/fib_rules.h                     |    4 +-
+ include/uapi/linux/if_bridge.h                     |    3 +-
+ include/uapi/linux/if_link.h                       |    1 +
+ include/uapi/linux/if_tun.h                        |    3 +
+ include/uapi/linux/netfilter_bridge/ebt_802_3.h    |    5 +-
+ include/uapi/linux/netfilter_ipv4/ipt_CLUSTERIP.h  |    3 +-
+ include/uapi/linux/sctp.h                          |    2 +-
+ include/uapi/linux/tcp.h                           |    1 +
+ include/uapi/linux/virtio_net.h                    |    6 +-
+ include/uapi/linux/wimax/i2400m.h                  |    4 +-
+ net/8021q/vlan.c                                   |   13 +-
+ net/8021q/vlan_dev.c                               |    6 +-
+ net/9p/client.c                                    |    9 +-
+ net/9p/trans_rdma.c                                |   11 -
+ net/Kconfig                                        |    2 +-
+ net/bridge/br_device.c                             |   12 +-
+ net/bridge/br_if.c                                 |    3 +-
+ net/bridge/br_mdb.c                                |    3 +-
+ net/bridge/br_notify.c                             |    5 +
+ net/bridge/br_private.h                            |   12 +-
+ net/ceph/messenger.c                               |    2 +-
+ net/core/datagram.c                                |   72 ++
+ net/core/dev.c                                     |   20 +-
+ net/core/fib_rules.c                               |   25 +
+ net/core/flow_dissector.c                          |    6 +-
+ net/core/iovec.c                                   |   24 +
+ net/core/net-sysfs.c                               |   22 +
+ net/core/pktgen.c                                  |   61 +-
+ net/core/rtnetlink.c                               |   25 +-
+ net/core/sock.c                                    |   66 ++
+ net/core/stream.c                                  |    2 +-
+ net/dccp/proto.c                                   |    4 +-
+ net/ipv4/devinet.c                                 |    5 +-
+ net/ipv4/fib_rules.c                               |   25 +
+ net/ipv4/igmp.c                                    |   49 +-
+ net/ipv4/ip_tunnel.c                               |   13 +-
+ net/ipv4/ip_vti.c                                  |  528 +---------
+ net/ipv4/ipmr.c                                    |   15 +-
+ net/ipv4/route.c                                   |   16 +-
+ net/ipv4/sysctl_net_ipv4.c                         |    7 +
+ net/ipv4/tcp.c                                     |   15 +-
+ net/ipv4/tcp_input.c                               |  115 +-
+ net/ipv4/tcp_ipv4.c                                |    8 +-
+ net/ipv4/tcp_minisocks.c                           |    8 +-
+ net/ipv4/tcp_output.c                              |    3 +
+ net/ipv4/udp.c                                     |    3 +-
+ net/ipv6/addrconf.c                                |    1 +
+ net/ipv6/af_inet6.c                                |    1 +
+ net/ipv6/fib6_rules.c                              |   37 +-
+ net/ipv6/ip6_fib.c                                 |   16 +-
+ net/ipv6/ip6mr.c                                   |   11 +-
+ net/ipv6/mcast.c                                   |    4 +-
+ net/ipv6/raw.c                                     |    9 +-
+ net/ipv6/route.c                                   |    5 +-
+ net/ipv6/tcp_ipv6.c                                |    6 +-
+ net/irda/irttp.c                                   |   50 +-
+ net/netfilter/ipvs/ip_vs_proto_sctp.c              |   23 +-
+ net/netfilter/nf_nat_proto_sctp.c                  |    8 +-
+ net/netlink/af_netlink.c                           |    4 +-
+ net/packet/af_packet.c                             |   48 +-
+ net/sched/sch_netem.c                              |    5 +-
+ net/sctp/associola.c                               |    2 +-
+ net/sctp/auth.c                                    |    2 +-
+ net/sctp/bind_addr.c                               |    2 +-
+ net/sctp/chunk.c                                   |    2 +-
+ net/sctp/command.c                                 |    2 +-
+ net/sctp/debug.c                                   |    2 +-
+ net/sctp/endpointola.c                             |    2 +-
+ net/sctp/input.c                                   |   12 +-
+ net/sctp/inqueue.c                                 |    2 +-
+ net/sctp/ipv6.c                                    |    4 +-
+ net/sctp/objcnt.c                                  |    2 +-
+ net/sctp/output.c                                  |    2 +-
+ net/sctp/outqueue.c                                |    2 +-
+ net/sctp/primitive.c                               |    2 +-
+ net/sctp/proc.c                                    |    2 +-
+ net/sctp/protocol.c                                |    4 +-
+ net/sctp/sm_make_chunk.c                           |    2 +-
+ net/sctp/sm_sideeffect.c                           |    2 +-
+ net/sctp/sm_statefuns.c                            |    2 +-
+ net/sctp/sm_statetable.c                           |    2 +-
+ net/sctp/socket.c                                  |    2 +-
+ net/sctp/ssnmap.c                                  |    2 +-
+ net/sctp/sysctl.c                                  |    2 +-
+ net/sctp/transport.c                               |    2 +-
+ net/sctp/tsnmap.c                                  |    2 +-
+ net/sctp/ulpevent.c                                |    2 +-
+ net/sctp/ulpqueue.c                                |    2 +-
+ net/sunrpc/svcsock.c                               |    2 +-
+ net/sunrpc/xprtsock.c                              |    2 +-
+ net/vmw_vsock/af_vsock.c                           |    3 +-
+ net/vmw_vsock/vmci_transport.c                     |    2 +-
+ net/vmw_vsock/vmci_transport.h                     |    4 +-
+ net/vmw_vsock/vsock_addr.c                         |    3 +-
+ net/xfrm/xfrm_policy.c                             |    8 +-
+ security/selinux/include/xfrm.h                    |    7 +-
+ 280 files changed, 7486 insertions(+), 4390 deletions(-)
+ create mode 100644 Documentation/networking/netdev-FAQ.txt
+ create mode 100644 drivers/net/ethernet/cisco/enic/enic_ethtool.c
+ rename {net/vmw_vsock => include/net}/af_vsock.h (100%)
+ rename {net/vmw_vsock => include/net}/vsock_addr.h (100%)
+Merging ipsec-next/master (af83fde xfrm: Remove rebundant address family checking)
+$ git merge --no-ff ipsec-next/master
+Merge made by the 'recursive' strategy.
+ include/net/xfrm.h     |  2 +-
+ net/key/af_key.c       | 14 +++-----------
+ net/xfrm/xfrm_policy.c |  2 +-
+ net/xfrm/xfrm_state.c  | 12 +++++++-----
+ 4 files changed, 12 insertions(+), 18 deletions(-)
+Merging wireless-next/master (2952f6e ath9k: Add more PCI IDs for WB225 cards)
+$ git merge --no-ff wireless-next/master
+Resolved 'drivers/net/ethernet/broadcom/Kconfig' using previous resolution.
+Auto-merging net/wireless/nl80211.c
+Auto-merging net/wireless/core.c
+Auto-merging net/mac80211/mlme.c
+Auto-merging include/net/mac80211.h
+Auto-merging include/net/cfg80211.h
+Auto-merging drivers/net/wireless/mwifiex/sta_ioctl.c
+Auto-merging drivers/net/wireless/mwifiex/sdio.c
+Auto-merging drivers/net/wireless/mwifiex/join.c
+Auto-merging drivers/net/wireless/mwifiex/cfp.c
+Auto-merging drivers/net/wireless/mwifiex/cfg80211.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/trans.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/rx.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/drv.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/sta.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/scan.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/mac80211.c
+Auto-merging drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+Auto-merging drivers/net/wireless/iwlwifi/mvm/d3.c
+Auto-merging drivers/net/wireless/iwlegacy/4965-mac.c
+Auto-merging drivers/net/ethernet/broadcom/Kconfig
+CONFLICT (content): Merge conflict in drivers/net/ethernet/broadcom/Kconfig
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 987c985] Merge remote-tracking branch 'wireless-next/master'
+$ git diff -M --stat --summary HEAD^..
+ MAINTAINERS                                     |    2 +-
+ drivers/bcma/Kconfig                            |   10 +-
+ drivers/bcma/main.c                             |    2 +-
+ drivers/bcma/scan.c                             |   28 +-
+ drivers/net/ethernet/broadcom/Kconfig           |    2 +-
+ drivers/net/wireless/ath/ath.h                  |    2 +-
+ drivers/net/wireless/ath/ath10k/bmi.c           |   12 +-
+ drivers/net/wireless/ath/ath10k/bmi.h           |    1 +
+ drivers/net/wireless/ath/ath10k/ce.c            |    2 +-
+ drivers/net/wireless/ath/ath10k/core.c          |  321 +++--
+ drivers/net/wireless/ath/ath10k/core.h          |   50 +-
+ drivers/net/wireless/ath/ath10k/debug.c         |   87 +-
+ drivers/net/wireless/ath/ath10k/hif.h           |   49 +-
+ drivers/net/wireless/ath/ath10k/htc.c           |   61 +-
+ drivers/net/wireless/ath/ath10k/htc.h           |    8 +-
+ drivers/net/wireless/ath/ath10k/htt.c           |   27 +-
+ drivers/net/wireless/ath/ath10k/htt.h           |    3 +-
+ drivers/net/wireless/ath/ath10k/htt_rx.c        |    3 +-
+ drivers/net/wireless/ath/ath10k/htt_tx.c        |   12 +-
+ drivers/net/wireless/ath/ath10k/mac.c           |  409 +++++-
+ drivers/net/wireless/ath/ath10k/mac.h           |    1 +
+ drivers/net/wireless/ath/ath10k/pci.c           |  304 ++---
+ drivers/net/wireless/ath/ath10k/pci.h           |    4 +-
+ drivers/net/wireless/ath/ath10k/wmi.c           |   40 +-
+ drivers/net/wireless/ath/ath10k/wmi.h           |   19 +
+ drivers/net/wireless/ath/ath9k/Kconfig          |   10 +
+ drivers/net/wireless/ath/ath9k/antenna.c        |  672 +++++-----
+ drivers/net/wireless/ath/ath9k/ar9002_phy.c     |   60 +
+ drivers/net/wireless/ath/ath9k/ar9002_phy.h     |   10 +-
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.c  |   26 +-
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.h  |    2 +
+ drivers/net/wireless/ath/ath9k/ar9003_phy.c     |  177 ++-
+ drivers/net/wireless/ath/ath9k/ar9003_phy.h     |    5 -
+ drivers/net/wireless/ath/ath9k/ath9k.h          |   29 +-
+ drivers/net/wireless/ath/ath9k/debug.c          |  159 ++-
+ drivers/net/wireless/ath/ath9k/debug.h          |   29 +-
+ drivers/net/wireless/ath/ath9k/eeprom_4k.c      |   19 +
+ drivers/net/wireless/ath/ath9k/hw-ops.h         |    7 +-
+ drivers/net/wireless/ath/ath9k/hw.c             |   96 +-
+ drivers/net/wireless/ath/ath9k/hw.h             |    6 +-
+ drivers/net/wireless/ath/ath9k/init.c           |   32 +-
+ drivers/net/wireless/ath/ath9k/main.c           |    5 +-
+ drivers/net/wireless/ath/ath9k/pci.c            |   90 +-
+ drivers/net/wireless/ath/ath9k/phy.h            |    7 +
+ drivers/net/wireless/ath/ath9k/rc.c             |    2 +
+ drivers/net/wireless/ath/ath9k/xmit.c           |   36 +-
+ drivers/net/wireless/ath/wil6210/Makefile       |    3 -
+ drivers/net/wireless/ath/wil6210/debugfs.c      |    4 +-
+ drivers/net/wireless/ath/wil6210/netdev.c       |    2 +
+ drivers/net/wireless/ath/wil6210/trace.h        |   22 +-
+ drivers/net/wireless/ath/wil6210/txrx.c         |  160 ++-
+ drivers/net/wireless/ath/wil6210/txrx.h         |   20 +-
+ drivers/net/wireless/ath/wil6210/wil6210.h      |   27 +-
+ drivers/net/wireless/ath/wil6210/wmi.c          |   20 +-
+ drivers/net/wireless/brcm80211/brcmsmac/ampdu.c |    6 +-
+ drivers/net/wireless/brcm80211/brcmsmac/main.c  |    4 +-
+ drivers/net/wireless/cw1200/wsm.h               |    2 +-
+ drivers/net/wireless/hostap/hostap_main.c       |    4 +-
+ drivers/net/wireless/iwlegacy/3945-rs.c         |    1 +
+ drivers/net/wireless/iwlegacy/3945.c            |   31 +-
+ drivers/net/wireless/iwlegacy/4965-mac.c        |   18 +-
+ drivers/net/wireless/iwlegacy/4965-rs.c         |    1 +
+ drivers/net/wireless/iwlwifi/Kconfig            |   17 -
+ drivers/net/wireless/iwlwifi/dvm/agn.h          |    6 -
+ drivers/net/wireless/iwlwifi/dvm/debugfs.c      |   15 -
+ drivers/net/wireless/iwlwifi/dvm/dev.h          |    7 -
+ drivers/net/wireless/iwlwifi/dvm/mac80211.c     |  172 +--
+ drivers/net/wireless/iwlwifi/dvm/main.c         |   62 -
+ drivers/net/wireless/iwlwifi/dvm/rs.c           |    6 +-
+ drivers/net/wireless/iwlwifi/dvm/rxon.c         |    6 +-
+ drivers/net/wireless/iwlwifi/dvm/scan.c         |  105 +-
+ drivers/net/wireless/iwlwifi/dvm/tx.c           |   19 -
+ drivers/net/wireless/iwlwifi/iwl-7000.c         |   11 +
+ drivers/net/wireless/iwlwifi/iwl-config.h       |    4 +
+ drivers/net/wireless/iwlwifi/iwl-fw.h           |   19 +-
+ drivers/net/wireless/iwlwifi/iwl-io.c           |   67 +
+ drivers/net/wireless/iwlwifi/iwl-io.h           |    3 +
+ drivers/net/wireless/iwlwifi/iwl-nvm-parse.c    |    8 +-
+ drivers/net/wireless/iwlwifi/mvm/Makefile       |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/bt-coex.c      |  162 ++-
+ drivers/net/wireless/iwlwifi/mvm/constants.h    |   71 ++
+ drivers/net/wireless/iwlwifi/mvm/d3.c           |   66 +-
+ drivers/net/wireless/iwlwifi/mvm/debugfs.c      |  116 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h    |   49 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-power.h |  143 ++-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h  |    5 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h    |    2 -
+ drivers/net/wireless/iwlwifi/mvm/fw-api.h       |   27 +-
+ drivers/net/wireless/iwlwifi/mvm/fw.c           |   55 -
+ drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c     |    3 +-
+ drivers/net/wireless/iwlwifi/mvm/mac80211.c     |   40 +-
+ drivers/net/wireless/iwlwifi/mvm/mvm.h          |   83 +-
+ drivers/net/wireless/iwlwifi/mvm/ops.c          |   56 +-
+ drivers/net/wireless/iwlwifi/mvm/power.c        |  198 ++-
+ drivers/net/wireless/iwlwifi/mvm/power_legacy.c |  319 +++++
+ drivers/net/wireless/iwlwifi/mvm/quota.c        |   16 +-
+ drivers/net/wireless/iwlwifi/mvm/rs.c           |   15 +-
+ drivers/net/wireless/iwlwifi/mvm/rs.h           |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/rx.c           |   78 +-
+ drivers/net/wireless/iwlwifi/mvm/scan.c         |    2 +
+ drivers/net/wireless/iwlwifi/mvm/sta.c          |    3 +-
+ drivers/net/wireless/iwlwifi/mvm/tt.c           |   32 +-
+ drivers/net/wireless/iwlwifi/mvm/tx.c           |    2 +
+ drivers/net/wireless/iwlwifi/mvm/utils.c        |   23 +
+ drivers/net/wireless/iwlwifi/pcie/drv.c         |    6 +-
+ drivers/net/wireless/iwlwifi/pcie/internal.h    |    1 -
+ drivers/net/wireless/iwlwifi/pcie/rx.c          |    2 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c       |   95 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c          |    5 +-
+ drivers/net/wireless/mac80211_hwsim.c           |   10 +-
+ drivers/net/wireless/mwifiex/11n_aggr.c         |    4 +-
+ drivers/net/wireless/mwifiex/cfg80211.c         |   28 +-
+ drivers/net/wireless/mwifiex/cfp.c              |   42 +-
+ drivers/net/wireless/mwifiex/decl.h             |    3 +-
+ drivers/net/wireless/mwifiex/fw.h               |   44 +-
+ drivers/net/wireless/mwifiex/ie.c               |    2 +-
+ drivers/net/wireless/mwifiex/init.c             |   14 +-
+ drivers/net/wireless/mwifiex/join.c             |    1 +
+ drivers/net/wireless/mwifiex/main.c             |   96 +-
+ drivers/net/wireless/mwifiex/main.h             |    8 +-
+ drivers/net/wireless/mwifiex/pcie.c             |   39 +-
+ drivers/net/wireless/mwifiex/scan.c             |   63 +-
+ drivers/net/wireless/mwifiex/sdio.c             |  213 ++--
+ drivers/net/wireless/mwifiex/sta_cmd.c          |    5 +-
+ drivers/net/wireless/mwifiex/sta_event.c        |   10 +
+ drivers/net/wireless/mwifiex/sta_ioctl.c        |   11 +-
+ drivers/net/wireless/mwifiex/uap_cmd.c          |  130 +-
+ drivers/net/wireless/mwifiex/uap_txrx.c         |   70 +-
+ drivers/net/wireless/mwifiex/usb.c              |    8 +
+ drivers/net/wireless/mwifiex/wmm.c              |   16 +-
+ drivers/net/wireless/rt2x00/Kconfig             |    6 +
+ drivers/net/wireless/rt2x00/rt2800.h            |  274 +++-
+ drivers/net/wireless/rt2x00/rt2800lib.c         | 1524 +++++++++++++++++++++--
+ drivers/net/wireless/rt2x00/rt2800usb.c         |   39 +-
+ drivers/net/wireless/rt2x00/rt2x00.h            |    1 +
+ drivers/net/wireless/rtlwifi/rc.c               |    1 +
+ drivers/net/wireless/rtlwifi/rtl8192cu/hw.h     |    3 +
+ drivers/net/wireless/rtlwifi/rtl8192cu/sw.h     |    3 -
+ drivers/net/wireless/ti/wlcore/main.c           |   10 +-
+ drivers/ssb/Kconfig                             |    2 +-
+ drivers/ssb/driver_chipcommon_sflash.c          |    8 +-
+ include/linux/bcma/bcma.h                       |   17 +
+ include/net/cfg80211.h                          |  164 ++-
+ include/net/ieee80211_radiotap.h                |    4 +
+ include/net/mac80211.h                          |   30 +-
+ include/uapi/linux/nl80211.h                    |  153 ++-
+ net/mac80211/cfg.c                              |   45 +-
+ net/mac80211/ht.c                               |   53 +-
+ net/mac80211/ibss.c                             |  154 ++-
+ net/mac80211/ieee80211_i.h                      |   49 +-
+ net/mac80211/iface.c                            |    2 +-
+ net/mac80211/main.c                             |   15 +-
+ net/mac80211/mesh.c                             |    7 +-
+ net/mac80211/mesh_plink.c                       |    2 +-
+ net/mac80211/mlme.c                             |   98 +-
+ net/mac80211/rate.c                             |   46 +-
+ net/mac80211/rate.h                             |   22 +-
+ net/mac80211/rc80211_minstrel.c                 |   33 +-
+ net/mac80211/rc80211_minstrel_ht.c              |   15 +-
+ net/mac80211/rc80211_pid_algo.c                 |    1 +
+ net/mac80211/rx.c                               |   97 +-
+ net/mac80211/scan.c                             |   72 +-
+ net/mac80211/status.c                           |   18 +-
+ net/mac80211/tx.c                               |   29 +-
+ net/mac80211/util.c                             |  216 +++-
+ net/wireless/core.c                             |    9 +
+ net/wireless/core.h                             |    2 +
+ net/wireless/mesh.c                             |    5 +-
+ net/wireless/nl80211.c                          |  358 +++++-
+ net/wireless/nl80211.h                          |    2 +
+ net/wireless/scan.c                             |   31 +-
+ net/wireless/trace.h                            |   12 +-
+ net/wireless/util.c                             |   14 +-
+ 173 files changed, 7148 insertions(+), 2786 deletions(-)
+ create mode 100644 drivers/net/wireless/iwlwifi/mvm/constants.h
+ create mode 100644 drivers/net/wireless/iwlwifi/mvm/power_legacy.c
+Merging bluetooth/master (473c131 Bluetooth: replace strict_strtol() with kstrtol())
+$ git merge --no-ff bluetooth/master
+Auto-merging net/bluetooth/hidp/core.c
+Auto-merging net/bluetooth/hci_core.c
+Merge made by the 'recursive' strategy.
+ drivers/bluetooth/btmrvl_debugfs.c |  6 +++---
+ include/net/bluetooth/hci.h        |  6 ++++++
+ net/bluetooth/hci_core.c           |  2 +-
+ net/bluetooth/hci_event.c          | 22 ++++++++++++---------
+ net/bluetooth/hidp/core.c          | 40 +++++++++++++++++++++++++-------------
+ net/bluetooth/l2cap_core.c         |  3 ++-
+ 6 files changed, 51 insertions(+), 28 deletions(-)
+Merging infiniband/for-next (569935d Merge branches 'cma', 'cxgb3', 'cxgb4', 'ipoib', 'misc', 'mlx4', 'mlx5', 'nes', 'ocrdma' and 'qib' into for-next)
+$ git merge --no-ff infiniband/for-next
+Already up-to-date.
+Merging mtd/master (e79265b mtd: ofpart: add compatible check for child nodes)
+$ git merge --no-ff mtd/master
+Removing drivers/mtd/maps/vmax301.c
+Removing drivers/mtd/maps/octagon-5066.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/mtd/atmel-nand.txt         |  28 +
+ .../devicetree/bindings/mtd/fsmc-nand.txt          |  25 +-
+ .../devicetree/bindings/mtd/partition.txt          |   1 +
+ arch/avr32/mach-at32ap/at32ap700x.c                |   3 +
+ arch/mips/bcm63xx/nvram.c                          |  11 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h |   2 +
+ drivers/mtd/bcm63xxpart.c                          |   9 +-
+ drivers/mtd/chips/cfi_cmdset_0002.c                |   4 +-
+ drivers/mtd/chips/gen_probe.c                      |   4 +-
+ drivers/mtd/chips/jedec_probe.c                    |  13 +-
+ drivers/mtd/devices/Kconfig                        |  55 --
+ drivers/mtd/devices/bcm47xxsflash.c                |  68 ++
+ drivers/mtd/devices/bcm47xxsflash.h                |   2 +
+ drivers/mtd/devices/block2mtd.c                    |  58 +-
+ drivers/mtd/devices/elm.c                          | 124 ++-
+ drivers/mtd/devices/m25p80.c                       |  46 +-
+ drivers/mtd/devices/mtd_dataflash.c                |   8 +-
+ drivers/mtd/devices/spear_smi.c                    |  11 +-
+ drivers/mtd/devices/sst25l.c                       |   6 +-
+ drivers/mtd/maps/Kconfig                           |  18 -
+ drivers/mtd/maps/Makefile                          |   2 -
+ drivers/mtd/maps/ixp4xx.c                          |   2 -
+ drivers/mtd/maps/latch-addr-flash.c                |   1 -
+ drivers/mtd/maps/octagon-5066.c                    | 246 ------
+ drivers/mtd/maps/physmap.c                         |   1 -
+ drivers/mtd/maps/plat-ram.c                        |   2 -
+ drivers/mtd/maps/pxa2xx-flash.c                    |   2 -
+ drivers/mtd/maps/rbtx4939-flash.c                  |   1 -
+ drivers/mtd/maps/sa1100-flash.c                    |   1 -
+ drivers/mtd/maps/vmax301.c                         | 196 -----
+ drivers/mtd/nand/Kconfig                           |   2 +-
+ drivers/mtd/nand/ams-delta.c                       |   1 -
+ drivers/mtd/nand/atmel_nand.c                      | 915 ++++++++++++++++-----
+ drivers/mtd/nand/atmel_nand_nfc.h                  |  98 +++
+ drivers/mtd/nand/bf5xx_nand.c                      |   3 -
+ drivers/mtd/nand/davinci_nand.c                    |  13 +-
+ drivers/mtd/nand/diskonchip.c                      |   4 +-
+ drivers/mtd/nand/docg4.c                           |   2 -
+ drivers/mtd/nand/fsl_ifc_nand.c                    |   3 +-
+ drivers/mtd/nand/fsmc_nand.c                       |  26 +-
+ drivers/mtd/nand/gpio.c                            | 227 ++---
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |  23 +-
+ drivers/mtd/nand/jz4740_nand.c                     |   2 -
+ drivers/mtd/nand/lpc32xx_mlc.c                     |   2 -
+ drivers/mtd/nand/lpc32xx_slc.c                     |   2 -
+ drivers/mtd/nand/mxc_nand.c                        |   7 -
+ drivers/mtd/nand/nand_base.c                       |  51 +-
+ drivers/mtd/nand/nandsim.c                         |  35 +-
+ drivers/mtd/nand/nuc900_nand.c                     |   2 -
+ drivers/mtd/nand/omap2.c                           |   1 -
+ drivers/mtd/nand/orion_nand.c                      |   1 -
+ drivers/mtd/nand/plat_nand.c                       |   1 -
+ drivers/mtd/nand/pxa3xx_nand.c                     | 110 ++-
+ drivers/mtd/nand/r852.c                            |   5 +-
+ drivers/mtd/nand/s3c2410.c                         |   2 -
+ drivers/mtd/nand/sharpsl.c                         |   3 -
+ drivers/mtd/nand/txx9ndfmc.c                       |   1 -
+ drivers/mtd/ofpart.c                               |  14 +-
+ drivers/mtd/onenand/generic.c                      |   2 -
+ drivers/mtd/onenand/omap2.c                        |   1 -
+ drivers/mtd/onenand/samsung.c                      |   1 -
+ drivers/mtd/tests/mtd_oobtest.c                    |  12 +-
+ drivers/mtd/tests/mtd_pagetest.c                   |  20 +-
+ drivers/mtd/tests/mtd_readtest.c                   |  12 +-
+ drivers/mtd/tests/mtd_speedtest.c                  |   8 +-
+ drivers/mtd/tests/mtd_stresstest.c                 |   8 +-
+ drivers/mtd/tests/mtd_subpagetest.c                |  12 +-
+ include/linux/mtd/fsmc.h                           |   1 +
+ include/linux/mtd/nand.h                           |   9 +-
+ include/linux/platform_data/atmel.h                |   4 +
+ 70 files changed, 1409 insertions(+), 1187 deletions(-)
+ delete mode 100644 drivers/mtd/maps/octagon-5066.c
+ delete mode 100644 drivers/mtd/maps/vmax301.c
+ create mode 100644 drivers/mtd/nand/atmel_nand_nfc.h
+Merging l2-mtd/master (a789b9a mtd: gpmi: set the BCH's geometry with the ecc info)
+$ git merge --no-ff l2-mtd/master
+Auto-merging drivers/mtd/tests/torturetest.c
+Auto-merging drivers/mtd/tests/subpagetest.c
+Auto-merging drivers/mtd/tests/stresstest.c
+Auto-merging drivers/mtd/tests/speedtest.c
+Auto-merging drivers/mtd/tests/readtest.c
+Auto-merging drivers/mtd/tests/pagetest.c
+Auto-merging drivers/mtd/tests/oobtest.c
+Auto-merging drivers/mtd/tests/nandbiterrs.c
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/mtdnand.tmpl                 |   2 -
+ drivers/mtd/devices/m25p80.c                       |   2 +-
+ drivers/mtd/devices/mtd_dataflash.c                |   2 +-
+ drivers/mtd/devices/sst25l.c                       |   2 +-
+ drivers/mtd/maps/bfin-async-flash.c                |   2 +-
+ drivers/mtd/maps/gpio-addr-flash.c                 |   2 +-
+ drivers/mtd/maps/ixp4xx.c                          |   4 +-
+ drivers/mtd/maps/latch-addr-flash.c                |   4 +-
+ drivers/mtd/maps/physmap.c                         |   6 +-
+ drivers/mtd/maps/plat-ram.c                        |   4 +-
+ drivers/mtd/maps/pxa2xx-flash.c                    |   2 +-
+ drivers/mtd/maps/rbtx4939-flash.c                  |   4 +-
+ drivers/mtd/maps/sa1100-flash.c                    |   4 +-
+ drivers/mtd/nand/atmel_nand.c                      |  12 +-
+ drivers/mtd/nand/au1550nd.c                        |   2 +-
+ drivers/mtd/nand/bf5xx_nand.c                      |   2 +-
+ drivers/mtd/nand/davinci_nand.c                    |   6 +-
+ drivers/mtd/nand/denali.c                          |   2 +-
+ drivers/mtd/nand/docg4.c                           |   6 -
+ drivers/mtd/nand/gpio.c                            |   6 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c             | 190 ++++++++++++++----
+ drivers/mtd/nand/jz4740_nand.c                     |   4 +-
+ drivers/mtd/nand/lpc32xx_mlc.c                     |   2 +-
+ drivers/mtd/nand/lpc32xx_slc.c                     |   2 +-
+ drivers/mtd/nand/mxc_nand.c                        |   3 +-
+ drivers/mtd/nand/nand_base.c                       | 213 +++++++++++++++------
+ drivers/mtd/nand/nand_bbt.c                        | 194 ++++++++++---------
+ drivers/mtd/nand/nand_ids.c                        |   8 +-
+ drivers/mtd/nand/omap2.c                           |   4 +-
+ drivers/mtd/nand/orion_nand.c                      |   5 +-
+ drivers/mtd/nand/plat_nand.c                       |   4 +-
+ drivers/mtd/nand/pxa3xx_nand.c                     |  14 +-
+ drivers/mtd/nand/s3c2410.c                         |   2 +-
+ drivers/mtd/nand/sh_flctl.c                        |   4 +-
+ drivers/mtd/nand/sharpsl.c                         |   2 +-
+ drivers/mtd/nand/sm_common.c                       |   9 +-
+ drivers/mtd/nand/tmio_nand.c                       |   2 +-
+ drivers/mtd/nand/txx9ndfmc.c                       |   8 +-
+ drivers/mtd/onenand/generic.c                      |   2 +-
+ drivers/mtd/onenand/omap2.c                        |   2 +-
+ drivers/mtd/onenand/onenand_bbt.c                  |   1 -
+ drivers/mtd/onenand/samsung.c                      |   2 +-
+ drivers/mtd/tests/Makefile                         |   9 +
+ drivers/mtd/tests/mtd_test.c                       | 110 +++++++++++
+ drivers/mtd/tests/mtd_test.h                       |  11 ++
+ .../mtd/tests/{mtd_nandbiterrs.c => nandbiterrs.c} |  39 +---
+ drivers/mtd/tests/{mtd_oobtest.c => oobtest.c}     |  92 ++-------
+ drivers/mtd/tests/{mtd_pagetest.c => pagetest.c}   | 199 ++++++-------------
+ drivers/mtd/tests/{mtd_readtest.c => readtest.c}   |  49 +----
+ drivers/mtd/tests/{mtd_speedtest.c => speedtest.c} | 180 ++++-------------
+ .../mtd/tests/{mtd_stresstest.c => stresstest.c}   |  86 ++-------
+ .../mtd/tests/{mtd_subpagetest.c => subpagetest.c} |  87 +--------
+ .../mtd/tests/{mtd_torturetest.c => torturetest.c} |  66 +------
+ include/linux/mtd/bbm.h                            |   2 -
+ include/linux/mtd/nand.h                           |  74 ++++++-
+ 55 files changed, 837 insertions(+), 920 deletions(-)
+ create mode 100644 drivers/mtd/tests/mtd_test.c
+ create mode 100644 drivers/mtd/tests/mtd_test.h
+ rename drivers/mtd/tests/{mtd_nandbiterrs.c => nandbiterrs.c} (94%)
+ rename drivers/mtd/tests/{mtd_oobtest.c => oobtest.c} (91%)
+ rename drivers/mtd/tests/{mtd_pagetest.c => pagetest.c} (74%)
+ rename drivers/mtd/tests/{mtd_readtest.c => readtest.c} (87%)
+ rename drivers/mtd/tests/{mtd_speedtest.c => speedtest.c} (75%)
+ rename drivers/mtd/tests/{mtd_stresstest.c => stresstest.c} (79%)
+ rename drivers/mtd/tests/{mtd_subpagetest.c => subpagetest.c} (88%)
+ rename drivers/mtd/tests/{mtd_torturetest.c => torturetest.c} (90%)
+Merging crypto/master (032c8ca crypto: testmgr - remove double execution of the same test suite)
+$ git merge --no-ff crypto/master
+Auto-merging drivers/crypto/caam/caamhash.c
+Auto-merging crypto/testmgr.c
+Merge made by the 'recursive' strategy.
+ crypto/testmgr.c                      |   2 +-
+ drivers/char/hw_random/mxc-rnga.c     |   4 +-
+ drivers/crypto/Kconfig                |  11 +-
+ drivers/crypto/caam/caamalg.c         |   2 -
+ drivers/crypto/caam/caamhash.c        |   2 -
+ drivers/crypto/caam/ctrl.c            |  77 +++--
+ drivers/crypto/caam/desc_constr.h     |   1 +
+ drivers/crypto/caam/intern.h          |   5 -
+ drivers/crypto/caam/jr.c              |  67 ----
+ drivers/crypto/caam/jr.h              |   2 -
+ drivers/crypto/caam/regs.h            |  12 +-
+ drivers/crypto/omap-sham.c            | 314 ++++++++++++++----
+ drivers/crypto/ux500/hash/hash_core.c | 586 ++++++++++++++++------------------
+ include/linux/module.h                |   5 +
+ 14 files changed, 598 insertions(+), 492 deletions(-)
+Merging drm/drm-next (00fd78e drm: provide agp dummies for CONFIG_AGP=n)
+$ git merge --no-ff drm/drm-next
+Resolved 'drivers/gpu/drm/i915/i915_dma.c' using previous resolution.
+Resolved 'drivers/gpu/drm/i915/intel_pm.c' using previous resolution.
+Resolved 'drivers/gpu/drm/qxl/qxl_release.c' using previous resolution.
+Auto-merging drivers/gpu/drm/radeon/si.c
+Auto-merging drivers/gpu/drm/radeon/r600.c
+Auto-merging drivers/gpu/drm/radeon/atombios_dp.c
+Auto-merging drivers/gpu/drm/qxl/qxl_release.c
+CONFLICT (content): Merge conflict in drivers/gpu/drm/qxl/qxl_release.c
+Auto-merging drivers/gpu/drm/qxl/qxl_object.h
+Auto-merging drivers/gpu/drm/qxl/qxl_ioctl.c
+Auto-merging drivers/gpu/drm/qxl/qxl_drv.h
+Auto-merging drivers/gpu/drm/i915/intel_pm.c
+CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/intel_pm.c
+Auto-merging drivers/gpu/drm/i915/intel_hdmi.c
+Auto-merging drivers/gpu/drm/i915/intel_display.c
+Auto-merging drivers/gpu/drm/i915/i915_reg.h
+Auto-merging drivers/gpu/drm/i915/i915_drv.h
+Auto-merging drivers/gpu/drm/i915/i915_dma.c
+CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/i915_dma.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master cf2e8a4] Merge remote-tracking branch 'drm/drm-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/drm.tmpl                   |    6 +
+ drivers/gpu/drm/Makefile                         |    2 +-
+ drivers/gpu/drm/ast/ast_drv.c                    |    2 +-
+ drivers/gpu/drm/ast/ast_drv.h                    |    3 -
+ drivers/gpu/drm/ast/ast_main.c                   |    9 +-
+ drivers/gpu/drm/cirrus/cirrus_drv.c              |    2 +-
+ drivers/gpu/drm/cirrus/cirrus_drv.h              |    3 -
+ drivers/gpu/drm/cirrus/cirrus_main.c             |    9 +-
+ drivers/gpu/drm/drm_agpsupport.c                 |   51 +
+ drivers/gpu/drm/drm_bufs.c                       |   41 +-
+ drivers/gpu/drm/drm_context.c                    |    8 -
+ drivers/gpu/drm/drm_drv.c                        |   40 +-
+ drivers/gpu/drm/drm_fops.c                       |   10 -
+ drivers/gpu/drm/drm_gem.c                        |  123 +-
+ drivers/gpu/drm/drm_gem_cma_helper.c             |   26 +-
+ drivers/gpu/drm/drm_mm.c                         |  226 +---
+ drivers/gpu/drm/drm_pci.c                        |   16 +-
+ drivers/gpu/drm/drm_scatter.c                    |   13 +-
+ drivers/gpu/drm/drm_stub.c                       |    9 +-
+ drivers/gpu/drm/drm_vma_manager.c                |  281 +++++
+ drivers/gpu/drm/exynos/exynos_drm_drv.c          |    6 +-
+ drivers/gpu/drm/exynos/exynos_drm_gem.c          |   34 +-
+ drivers/gpu/drm/exynos/exynos_drm_gem.h          |    9 -
+ drivers/gpu/drm/gma500/framebuffer.c             |    6 +-
+ drivers/gpu/drm/gma500/gem.c                     |   39 +-
+ drivers/gpu/drm/gma500/psb_drv.c                 |    4 +-
+ drivers/gpu/drm/gma500/psb_drv.h                 |    2 -
+ drivers/gpu/drm/i810/i810_dma.c                  |    2 +-
+ drivers/gpu/drm/i810/i810_drv.h                  |    2 +-
+ drivers/gpu/drm/i915/Makefile                    |    2 +
+ drivers/gpu/drm/i915/dvo_ch7xxx.c                |    2 +-
+ drivers/gpu/drm/i915/i915_debugfs.c              |  836 +++++--------
+ drivers/gpu/drm/i915/i915_dma.c                  |   73 +-
+ drivers/gpu/drm/i915/i915_drv.c                  |  297 +----
+ drivers/gpu/drm/i915/i915_drv.h                  |  416 ++++---
+ drivers/gpu/drm/i915/i915_gem.c                  |  323 +++---
+ drivers/gpu/drm/i915/i915_gem_context.c          |   25 +-
+ drivers/gpu/drm/i915/i915_gem_debug.c            |    2 +-
+ drivers/gpu/drm/i915/i915_gem_dmabuf.c           |    7 +-
+ drivers/gpu/drm/i915/i915_gem_evict.c            |   34 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c       |   37 +-
+ drivers/gpu/drm/i915/i915_gem_gtt.c              |  265 +++--
+ drivers/gpu/drm/i915/i915_gem_stolen.c           |  202 ++--
+ drivers/gpu/drm/i915/i915_gem_tiling.c           |   14 +-
+ drivers/gpu/drm/i915/i915_gpu_error.c            |  973 ++++++++++++++++
+ drivers/gpu/drm/i915/i915_irq.c                  | 1354 ++++++----------------
+ drivers/gpu/drm/i915/i915_reg.h                  |  110 +-
+ drivers/gpu/drm/i915/i915_sysfs.c                |   71 ++
+ drivers/gpu/drm/i915/i915_trace.h                |   16 +-
+ drivers/gpu/drm/i915/intel_crt.c                 |    4 +
+ drivers/gpu/drm/i915/intel_ddi.c                 |    2 +
+ drivers/gpu/drm/i915/intel_display.c             | 1025 ++++++++++------
+ drivers/gpu/drm/i915/intel_dp.c                  |  418 ++++++-
+ drivers/gpu/drm/i915/intel_drv.h                 |   34 +-
+ drivers/gpu/drm/i915/intel_dvo.c                 |    5 +-
+ drivers/gpu/drm/i915/intel_fb.c                  |    8 +-
+ drivers/gpu/drm/i915/intel_hdmi.c                |    3 +
+ drivers/gpu/drm/i915/intel_lvds.c                |   24 +-
+ drivers/gpu/drm/i915/intel_overlay.c             |   22 +-
+ drivers/gpu/drm/i915/intel_pm.c                  |  437 ++-----
+ drivers/gpu/drm/i915/intel_ringbuffer.c          |   43 +-
+ drivers/gpu/drm/i915/intel_ringbuffer.h          |    5 +-
+ drivers/gpu/drm/i915/intel_sdvo.c                |   30 +-
+ drivers/gpu/drm/i915/intel_sprite.c              |    8 +-
+ drivers/gpu/drm/i915/intel_tv.c                  |    4 +
+ drivers/gpu/drm/i915/intel_uncore.c              |  595 ++++++++++
+ drivers/gpu/drm/mga/mga_drv.h                    |    2 +-
+ drivers/gpu/drm/mga/mga_state.c                  |    2 +-
+ drivers/gpu/drm/mgag200/mgag200_drv.c            |    2 +-
+ drivers/gpu/drm/mgag200/mgag200_drv.h            |    3 -
+ drivers/gpu/drm/mgag200/mgag200_main.c           |    9 +-
+ drivers/gpu/drm/nouveau/core/engine/disp/dport.c |    2 +-
+ drivers/gpu/drm/nouveau/nouveau_display.c        |    9 +-
+ drivers/gpu/drm/nouveau/nouveau_display.h        |    2 -
+ drivers/gpu/drm/nouveau/nouveau_drm.c            |    9 +-
+ drivers/gpu/drm/nouveau/nouveau_gem.c            |    2 +-
+ drivers/gpu/drm/omapdrm/omap_drv.c               |    4 +-
+ drivers/gpu/drm/omapdrm/omap_drv.h               |    2 -
+ drivers/gpu/drm/omapdrm/omap_gem.c               |   46 +-
+ drivers/gpu/drm/omapdrm/omap_gem_helpers.c       |   49 +-
+ drivers/gpu/drm/qxl/qxl_drv.c                    |    2 +-
+ drivers/gpu/drm/qxl/qxl_drv.h                    |    5 +-
+ drivers/gpu/drm/qxl/qxl_dumb.c                   |    7 -
+ drivers/gpu/drm/qxl/qxl_ioctl.c                  |    2 +-
+ drivers/gpu/drm/qxl/qxl_object.h                 |    2 +-
+ drivers/gpu/drm/qxl/qxl_release.c                |    2 +-
+ drivers/gpu/drm/r128/r128_cce.c                  |    2 +-
+ drivers/gpu/drm/r128/r128_drv.h                  |    2 +-
+ drivers/gpu/drm/r128/r128_state.c                |    2 +-
+ drivers/gpu/drm/radeon/atombios_dp.c             |    2 +-
+ drivers/gpu/drm/radeon/cik.c                     |   14 +-
+ drivers/gpu/drm/radeon/evergreen.c               |    4 +-
+ drivers/gpu/drm/radeon/ni.c                      |    6 +-
+ drivers/gpu/drm/radeon/r100.c                    |    2 +-
+ drivers/gpu/drm/radeon/r600.c                    |   14 +-
+ drivers/gpu/drm/radeon/r600_cp.c                 |    6 +-
+ drivers/gpu/drm/radeon/radeon.h                  |    3 -
+ drivers/gpu/drm/radeon/radeon_cp.c               |    6 +-
+ drivers/gpu/drm/radeon/radeon_drv.c              |   14 +-
+ drivers/gpu/drm/radeon/radeon_gem.c              |    7 -
+ drivers/gpu/drm/radeon/radeon_kms.c              |   12 +-
+ drivers/gpu/drm/radeon/radeon_object.h           |    5 +-
+ drivers/gpu/drm/radeon/si.c                      |   14 +-
+ drivers/gpu/drm/rcar-du/rcar_du_drv.c            |    2 +-
+ drivers/gpu/drm/savage/savage_bci.c              |    2 +-
+ drivers/gpu/drm/savage/savage_drv.h              |    2 +-
+ drivers/gpu/drm/shmobile/shmob_drm_drv.c         |    2 +-
+ drivers/gpu/drm/sis/sis_drv.h                    |    2 +-
+ drivers/gpu/drm/sis/sis_mm.c                     |    8 +-
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c              |    2 +-
+ drivers/gpu/drm/ttm/ttm_bo.c                     |  102 +-
+ drivers/gpu/drm/ttm/ttm_bo_manager.c             |   41 +-
+ drivers/gpu/drm/ttm/ttm_bo_util.c                |    3 +-
+ drivers/gpu/drm/ttm/ttm_bo_vm.c                  |   81 +-
+ drivers/gpu/drm/udl/udl_drv.c                    |    2 +-
+ drivers/gpu/drm/udl/udl_drv.h                    |    2 -
+ drivers/gpu/drm/udl/udl_gem.c                    |   19 +-
+ drivers/gpu/drm/udl/udl_main.c                   |    4 +-
+ drivers/gpu/drm/via/via_dma.c                    |    2 +-
+ drivers/gpu/drm/via/via_drv.h                    |    2 +-
+ drivers/gpu/drm/via/via_mm.c                     |    4 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c              |    4 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c         |    4 +-
+ drivers/gpu/host1x/drm/drm.c                     |    4 +-
+ drivers/gpu/host1x/drm/gem.c                     |   11 +-
+ drivers/gpu/host1x/drm/gem.h                     |    2 -
+ drivers/staging/imx-drm/imx-drm-core.c           |    4 +-
+ include/drm/drmP.h                               |  103 +-
+ include/drm/drm_agpsupport.h                     |  194 ++++
+ include/drm/drm_dp_helper.h                      |   31 +-
+ include/drm/drm_gem_cma_helper.h                 |    8 -
+ include/drm/drm_mm.h                             |  142 +--
+ include/drm/drm_vma_manager.h                    |  224 ++++
+ include/drm/ttm/ttm_bo_api.h                     |   15 +-
+ include/drm/ttm/ttm_bo_driver.h                  |   10 +-
+ include/uapi/drm/drm.h                           |    2 +-
+ include/uapi/drm/i915_drm.h                      |   24 +
+ 137 files changed, 5684 insertions(+), 4368 deletions(-)
+ create mode 100644 drivers/gpu/drm/drm_vma_manager.c
+ create mode 100644 drivers/gpu/drm/i915/i915_gpu_error.c
+ create mode 100644 drivers/gpu/drm/i915/intel_uncore.c
+ create mode 100644 include/drm/drm_agpsupport.h
+ create mode 100644 include/drm/drm_vma_manager.h
+Merging drm-intel/for-linux-next (6d2b888 drm/i915: List objects allocated from stolen memory in debugfs)
+$ git merge --no-ff drm-intel/for-linux-next
+Auto-merging drivers/gpu/drm/i915/intel_pm.c
+Auto-merging drivers/gpu/drm/i915/intel_panel.c
+Auto-merging drivers/gpu/drm/i915/intel_hdmi.c
+Auto-merging drivers/gpu/drm/i915/intel_display.c
+Auto-merging drivers/gpu/drm/i915/i915_reg.h
+Auto-merging drivers/gpu/drm/i915/i915_gem_stolen.c
+Auto-merging drivers/gpu/drm/i915/i915_gem.c
+Auto-merging drivers/gpu/drm/i915/i915_drv.h
+Auto-merging drivers/gpu/drm/i915/i915_dma.c
+Merge made by the 'recursive' strategy.
+ drivers/gpu/drm/drm_edid.c                 |   6 +-
+ drivers/gpu/drm/i915/i915_debugfs.c        | 135 +++++-
+ drivers/gpu/drm/i915/i915_dma.c            |   4 -
+ drivers/gpu/drm/i915/i915_drv.h            | 171 ++++---
+ drivers/gpu/drm/i915/i915_gem.c            | 354 ++++++++++-----
+ drivers/gpu/drm/i915/i915_gem_context.c    |   9 +-
+ drivers/gpu/drm/i915/i915_gem_evict.c      |  55 +--
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c |  81 ++--
+ drivers/gpu/drm/i915/i915_gem_gtt.c        |  67 +--
+ drivers/gpu/drm/i915/i915_gem_stolen.c     |  10 +-
+ drivers/gpu/drm/i915/i915_gem_tiling.c     |   9 +-
+ drivers/gpu/drm/i915/i915_gpu_error.c      | 115 +++--
+ drivers/gpu/drm/i915/i915_reg.h            |   9 -
+ drivers/gpu/drm/i915/i915_trace.h          |  37 +-
+ drivers/gpu/drm/i915/intel_acpi.c          |  14 +-
+ drivers/gpu/drm/i915/intel_crt.c           |  34 +-
+ drivers/gpu/drm/i915/intel_ddi.c           |  67 +--
+ drivers/gpu/drm/i915/intel_display.c       |  71 ++-
+ drivers/gpu/drm/i915/intel_dp.c            |  94 ++--
+ drivers/gpu/drm/i915/intel_drv.h           |  94 +---
+ drivers/gpu/drm/i915/intel_dvo.c           |  56 ++-
+ drivers/gpu/drm/i915/intel_fb.c            |  15 +-
+ drivers/gpu/drm/i915/intel_hdmi.c          | 253 ++++++-----
+ drivers/gpu/drm/i915/intel_lvds.c          |  16 +-
+ drivers/gpu/drm/i915/intel_overlay.c       |   2 +-
+ drivers/gpu/drm/i915/intel_panel.c         |   3 -
+ drivers/gpu/drm/i915/intel_pm.c            | 689 ++++++++++++++++++++---------
+ drivers/gpu/drm/i915/intel_ringbuffer.c    |   8 +-
+ drivers/gpu/drm/i915/intel_sdvo.c          |  61 +--
+ drivers/gpu/drm/i915/intel_sprite.c        |  51 ++-
+ drivers/gpu/drm/i915/intel_tv.c            |  27 +-
+ drivers/video/hdmi.c                       |  57 ++-
+ include/linux/hdmi.h                       |  20 +
+ 33 files changed, 1659 insertions(+), 1035 deletions(-)
+Merging drm-tegra/drm/for-next (ebae30b gpu: host1x: Rework CPU syncpoint increment)
+$ git merge --no-ff drm-tegra/drm/for-next
+Already up-to-date.
+Merging sound/for-next (663819f ALSA: don't push static constants on stack for %*ph)
+$ git merge --no-ff sound/for-next
+Auto-merging sound/usb/endpoint.c
+Auto-merging sound/soc/soc-core.c
+Auto-merging sound/soc/omap/mcbsp.c
+Auto-merging sound/pci/hda/patch_sigmatel.c
+Merge made by the 'recursive' strategy.
+ Documentation/sound/alsa/HD-Audio-Models.txt |    1 +
+ Documentation/sound/alsa/HD-Audio.txt        |    2 +
+ sound/drivers/dummy.c                        |    2 +-
+ sound/firewire/speakers.c                    |    4 +-
+ sound/isa/gus/interwave.c                    |    3 +-
+ sound/pci/hda/hda_codec.c                    |    6 +-
+ sound/pci/hda/hda_generic.c                  |   22 +-
+ sound/pci/hda/hda_generic.h                  |    1 +
+ sound/pci/hda/hda_hwdep.c                    |    6 +-
+ sound/pci/hda/hda_intel.c                    |   32 +-
+ sound/pci/hda/hda_jack.c                     |   22 +-
+ sound/pci/hda/hda_jack.h                     |   13 +-
+ sound/pci/hda/patch_analog.c                 | 4662 ++------------------------
+ sound/pci/hda/patch_conexant.c               |   79 +-
+ sound/pci/hda/patch_realtek.c                |   80 +-
+ sound/pci/hda/patch_sigmatel.c               |   14 +-
+ sound/pci/hda/patch_via.c                    |    2 +-
+ sound/pci/rme9652/hdspm.c                    |  767 +++--
+ sound/soc/codecs/wm8962.c                    |    2 +-
+ sound/soc/omap/mcbsp.c                       |    2 +-
+ sound/soc/soc-core.c                         |    8 +-
+ sound/usb/6fire/firmware.c                   |    4 +-
+ sound/usb/endpoint.c                         |    3 +
+ sound/usb/pcm.c                              |  243 +-
+ sound/usb/usx2y/usbusx2y.c                   |    8 +-
+ 25 files changed, 1180 insertions(+), 4808 deletions(-)
+Merging sound-asoc/for-next (49ca8bb Merge remote-tracking branch 'asoc/topic/wm8994' into asoc-next)
+$ git merge --no-ff sound-asoc/for-next
+Auto-merging sound/soc/soc-core.c
+Auto-merging sound/soc/codecs/wm8962.c
+Removing include/linux/platform_data/omap-abe-twl6040.h
+Auto-merging Documentation/devicetree/bindings/sound/fsl,ssi.txt
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/misc/atmel-ssc.txt         |  23 +-
+ Documentation/devicetree/bindings/sound/ak4554.c   |  11 +
+ .../bindings/sound/atmel-sam9x5-wm8731-audio.txt   |  35 +
+ .../devicetree/bindings/sound/atmel-wm8904.txt     |  55 ++
+ .../{powerpc/fsl/ssi.txt => sound/fsl,ssi.txt}     |   8 +
+ .../devicetree/bindings/sound/imx-audmux.txt       |   9 +
+ .../bindings/sound/nvidia,tegra-audio-wm8903.txt   |  24 +-
+ .../devicetree/bindings/sound/pcm1792a.txt         |  18 +
+ .../devicetree/bindings/sound/ti,pcm1681.txt       |  15 +
+ .../devicetree/bindings/sound/tlv320aic3x.txt      |   9 +-
+ Documentation/devicetree/bindings/sound/wm8731.txt |   9 +
+ Documentation/devicetree/bindings/sound/wm8903.txt |  19 +
+ Documentation/devicetree/bindings/sound/wm8994.txt |   4 +
+ arch/arm/mach-dove/common.c                        |   4 +-
+ arch/arm/mach-kirkwood/common.c                    |  24 +-
+ include/linux/atmel-ssc.h                          |   2 +-
+ include/linux/mfd/arizona/gpio.h                   |  96 +++
+ include/linux/platform_data/omap-abe-twl6040.h     |  49 --
+ include/sound/rcar_snd.h                           |  84 ++
+ include/sound/soc-dapm.h                           | 199 +++--
+ include/sound/soc-dpcm.h                           |   2 +-
+ include/sound/soc.h                                |  31 +-
+ sound/soc/atmel/Kconfig                            |  21 +
+ sound/soc/atmel/Makefile                           |   4 +
+ sound/soc/atmel/atmel-pcm-dma.c                    | 118 +--
+ sound/soc/atmel/atmel_ssc_dai.c                    |  36 +-
+ sound/soc/atmel/atmel_wm8904.c                     | 254 ++++++
+ sound/soc/atmel/sam9x5_wm8731.c                    | 208 +++++
+ sound/soc/au1x/db1200.c                            |   4 +
+ sound/soc/au1x/psc-ac97.c                          |   3 -
+ sound/soc/blackfin/bf5xx-ac97.h                    |   1 -
+ sound/soc/cirrus/ep93xx-ac97.c                     |   3 -
+ sound/soc/cirrus/ep93xx-i2s.c                      |   3 -
+ sound/soc/codecs/Kconfig                           |  13 +
+ sound/soc/codecs/Makefile                          |   6 +
+ sound/soc/codecs/ad1980.c                          |  43 +
+ sound/soc/codecs/adau1701.c                        |   5 +-
+ sound/soc/codecs/adav80x.c                         |  13 +-
+ sound/soc/codecs/ak4554.c                          |  86 ++
+ sound/soc/codecs/arizona.c                         |  56 ++
+ sound/soc/codecs/arizona.h                         |   2 +
+ sound/soc/codecs/cs42l52.c                         |   5 +-
+ sound/soc/codecs/hdmi.c                            |  11 +
+ sound/soc/codecs/lm4857.c                          | 107 +--
+ sound/soc/codecs/max98090.c                        |  10 +-
+ sound/soc/codecs/mc13783.c                         |   1 -
+ sound/soc/codecs/pcm1681.c                         | 313 ++++++++
+ sound/soc/codecs/pcm1792a.c                        | 243 ++++++
+ sound/soc/codecs/pcm1792a.h                        |  26 +
+ sound/soc/codecs/pcm3008.c                         | 108 +--
+ sound/soc/codecs/rt5640.c                          |  26 -
+ sound/soc/codecs/sgtl5000.c                        |  28 +-
+ sound/soc/codecs/spdif_receiver.c                  |   2 +
+ sound/soc/codecs/spdif_transmitter.c               |  18 +-
+ sound/soc/codecs/sta32x.c                          |  10 +-
+ sound/soc/codecs/tlv320aic26.c                     |  11 +-
+ sound/soc/codecs/tlv320aic3x.c                     |  56 +-
+ sound/soc/codecs/twl4030.c                         |   2 -
+ sound/soc/codecs/twl6040.c                         |   7 +-
+ sound/soc/codecs/uda134x.c                         |  88 ++-
+ sound/soc/codecs/wm0010.c                          |  12 +-
+ sound/soc/codecs/wm5102.c                          |   6 +
+ sound/soc/codecs/wm5110.c                          |  21 +-
+ sound/soc/codecs/wm8350.c                          |   6 +-
+ sound/soc/codecs/wm8731.c                          |  60 +-
+ sound/soc/codecs/wm8753.c                          |   5 +-
+ sound/soc/codecs/wm8903.c                          |   4 +-
+ sound/soc/codecs/wm8904.c                          |   2 +-
+ sound/soc/codecs/wm8962.c                          |   7 +-
+ sound/soc/codecs/wm8994.c                          |  39 +-
+ sound/soc/codecs/wm8995.c                          |   5 +-
+ sound/soc/codecs/wm_adsp.c                         | 124 +--
+ sound/soc/codecs/wm_adsp.h                         |   3 +-
+ sound/soc/codecs/wm_hubs.c                         |   8 +-
+ sound/soc/fsl/Kconfig                              |   8 +-
+ sound/soc/fsl/fsl_ssi.c                            | 161 ++--
+ sound/soc/fsl/imx-audmux.c                         |  78 +-
+ sound/soc/fsl/imx-mc13783.c                        |   1 +
+ sound/soc/fsl/imx-pcm-dma.c                        |   1 -
+ sound/soc/fsl/imx-pcm-fiq.c                        |  18 +-
+ sound/soc/fsl/imx-pcm.h                            |  26 +-
+ sound/soc/fsl/imx-sgtl5000.c                       |   4 +-
+ sound/soc/fsl/imx-ssi.c                            |  11 +-
+ sound/soc/fsl/imx-ssi.h                            |   1 +
+ sound/soc/fsl/imx-wm8962.c                         |   3 +-
+ sound/soc/kirkwood/Kconfig                         |  11 +-
+ sound/soc/kirkwood/Makefile                        |   4 +-
+ sound/soc/kirkwood/kirkwood-dma.c                  | 108 +--
+ sound/soc/kirkwood/kirkwood-i2s.c                  |  67 +-
+ sound/soc/kirkwood/kirkwood-openrd.c               |   6 +-
+ sound/soc/kirkwood/kirkwood-t5325.c                |   6 +-
+ sound/soc/kirkwood/kirkwood.h                      |  11 +-
+ sound/soc/mxs/Kconfig                              |   3 +-
+ sound/soc/mxs/mxs-saif.c                           |   1 -
+ sound/soc/mxs/mxs-sgtl5000.c                       |  30 +-
+ sound/soc/nuc900/nuc900-ac97.c                     |   3 -
+ sound/soc/omap/Kconfig                             |   6 +-
+ sound/soc/omap/omap-abe-twl6040.c                  | 133 +---
+ sound/soc/omap/omap-mcbsp.c                        |   5 +
+ sound/soc/pxa/brownstone.c                         |   1 +
+ sound/soc/pxa/mmp-sspa.c                           |   3 -
+ sound/soc/pxa/ttc-dkb.c                            |   1 +
+ sound/soc/samsung/i2s-regs.h                       |  36 +-
+ sound/soc/samsung/i2s.c                            |  60 +-
+ sound/soc/samsung/smdk_wm8994.c                    |  58 +-
+ sound/soc/samsung/spdif.c                          |   8 +-
+ sound/soc/sh/Kconfig                               |   7 +
+ sound/soc/sh/Makefile                              |   3 +
+ sound/soc/sh/rcar/Makefile                         |   2 +
+ sound/soc/sh/rcar/adg.c                            | 234 ++++++
+ sound/soc/sh/rcar/core.c                           | 861 +++++++++++++++++++++
+ sound/soc/sh/rcar/gen.c                            | 280 +++++++
+ sound/soc/sh/rcar/rsnd.h                           | 302 ++++++++
+ sound/soc/sh/rcar/scu.c                            | 236 ++++++
+ sound/soc/sh/rcar/ssi.c                            | 728 +++++++++++++++++
+ sound/soc/soc-compress.c                           |   8 +-
+ sound/soc/soc-core.c                               |  16 +
+ sound/soc/soc-dapm.c                               | 804 ++++++++++---------
+ sound/soc/soc-jack.c                               |   2 +-
+ sound/soc/soc-pcm.c                                |  15 +-
+ sound/soc/tegra/Kconfig                            |  14 +-
+ sound/soc/tegra/tegra20_ac97.c                     |   2 -
+ sound/soc/tegra/tegra_alc5632.c                    |   2 -
+ sound/soc/tegra/tegra_wm8753.c                     |   2 -
+ sound/soc/tegra/trimslice.c                        |   2 -
+ sound/soc/txx9/txx9aclc-ac97.c                     |   3 -
+ sound/soc/ux500/mop500.c                           |   1 +
+ 127 files changed, 5860 insertions(+), 1520 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/sound/ak4554.c
+ create mode 100644 Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/atmel-wm8904.txt
+ rename Documentation/devicetree/bindings/{powerpc/fsl/ssi.txt => sound/fsl,ssi.txt} (90%)
+ create mode 100644 Documentation/devicetree/bindings/sound/pcm1792a.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/ti,pcm1681.txt
+ create mode 100644 include/linux/mfd/arizona/gpio.h
+ delete mode 100644 include/linux/platform_data/omap-abe-twl6040.h
+ create mode 100644 include/sound/rcar_snd.h
+ create mode 100644 sound/soc/atmel/atmel_wm8904.c
+ create mode 100644 sound/soc/atmel/sam9x5_wm8731.c
+ create mode 100644 sound/soc/codecs/ak4554.c
+ create mode 100644 sound/soc/codecs/pcm1681.c
+ create mode 100644 sound/soc/codecs/pcm1792a.c
+ create mode 100644 sound/soc/codecs/pcm1792a.h
+ create mode 100644 sound/soc/sh/rcar/Makefile
+ create mode 100644 sound/soc/sh/rcar/adg.c
+ create mode 100644 sound/soc/sh/rcar/core.c
+ create mode 100644 sound/soc/sh/rcar/gen.c
+ create mode 100644 sound/soc/sh/rcar/rsnd.h
+ create mode 100644 sound/soc/sh/rcar/scu.c
+ create mode 100644 sound/soc/sh/rcar/ssi.c
+Merging modules/modules-next (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff modules/modules-next
+Already up-to-date.
+Merging virtio/virtio-next (3f0d0c9 virtio: console: cleanup an error message)
+$ git merge --no-ff virtio/virtio-next
+Auto-merging drivers/char/virtio_console.c
+Merge made by the 'recursive' strategy.
+ arch/x86/lguest/boot.c        |  3 +--
+ drivers/char/virtio_console.c | 24 +++++++++++++++---------
+ tools/lguest/lguest.c         |  6 ++++++
+ tools/virtio/.gitignore       |  3 +++
+ 4 files changed, 25 insertions(+), 11 deletions(-)
+ create mode 100644 tools/virtio/.gitignore
+Merging input/next (46146e7 Input: nspire-keypad - replace magic offset with define)
+$ git merge --no-ff input/next
+Already up-to-date.
+Merging input-mt/for-next (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff input-mt/for-next
+Already up-to-date.
+Merging cgroup/for-next (f00eaaa Merge branch 'for-3.12' into for-next)
+$ git merge --no-ff cgroup/for-next
+Auto-merging kernel/cgroup.c
+Merge made by the 'recursive' strategy.
+ include/linux/cgroup.h |  34 +++-
+ kernel/cgroup.c        | 475 ++++++++++++++++++++++++-------------------------
+ kernel/cpuset.c        |  29 ++-
+ 3 files changed, 274 insertions(+), 264 deletions(-)
+Merging block/for-next (3fe9649 Merge branch 'for-3.11/drivers' into for-next)
+$ git merge --no-ff block/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging device-mapper/master (ad81f05 Linux 3.11-rc1)
+$ git merge --no-ff device-mapper/master
+Already up-to-date.
+Merging embedded/master (4744b43 embedded: fix vc_translate operator precedence)
+$ git merge --no-ff embedded/master
+Already up-to-date.
+Merging firmware/master (6e03a20 firmware: speed up request_firmware(), v3)
+$ git merge --no-ff firmware/master
+Already up-to-date.
+Merging pcmcia/master (80af9e6 pcmcia at91_cf: fix raw gpio number usage)
+$ git merge --no-ff pcmcia/master
+Already up-to-date.
+Merging mmc/mmc-next (6d1d6b4 mmc: tmio: fix compiler warning)
+$ git merge --no-ff mmc/mmc-next
+Merge made by the 'recursive' strategy.
+ drivers/mmc/host/tmio_mmc_pio.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+Merging kgdb/kgdb-next (6bedf31 kdb: Remove unhandled ssb command)
+$ git merge --no-ff kgdb/kgdb-next
+Merge made by the 'recursive' strategy.
+Merging slab/for-next (0450b0c Merge branch 'slab/next' into for-next)
+$ git merge --no-ff slab/for-next
+Auto-merging mm/slub.c
+Merge made by the 'recursive' strategy.
+ mm/slub.c | 98 +++++++++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 57 insertions(+), 41 deletions(-)
+Merging uclinux/for-next (6dbe51c Linux 3.9-rc1)
+$ git merge --no-ff uclinux/for-next
+Already up-to-date.
+Merging md/for-next (5ad58b4 md/raid5: make release_stripe lockless)
+$ git merge --no-ff md/for-next
+Merge made by the 'recursive' strategy.
+ drivers/md/md.c    |  13 +-
+ drivers/md/md.h    |   8 +
+ drivers/md/raid5.c | 459 ++++++++++++++++++++++++++++++++++++++++++++++++++---
+ drivers/md/raid5.h |  22 +++
+ 4 files changed, 471 insertions(+), 31 deletions(-)
+Merging mfd/master (38c4faa mfd: ucb1x00: Explicitely include linux/device.h)
+$ git merge --no-ff mfd/master
+Auto-merging include/linux/mfd/ti_am335x_tscadc.h
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/mfd/palmas.txt  |  2 +
+ Documentation/devicetree/bindings/mfd/s2mps11.txt | 89 ++++++++++++++++++++++
+ drivers/mfd/Kconfig                               |  2 +-
+ drivers/mfd/da9055-core.c                         |  5 ++
+ drivers/mfd/da9055-i2c.c                          |  2 +-
+ drivers/mfd/sec-core.c                            | 34 +++++++++
+ drivers/mfd/syscon.c                              |  8 +-
+ drivers/mfd/ti_am335x_tscadc.c                    | 24 +++---
+ drivers/mfd/twl6040.c                             | 90 +++++++----------------
+ drivers/mfd/wm8994-core.c                         | 44 +----------
+ include/linux/mfd/mcp.h                           |  2 +
+ include/linux/mfd/samsung/s2mps11.h               |  6 +-
+ include/linux/mfd/ti_am335x_tscadc.h              |  1 -
+ include/linux/mfd/twl6040.h                       |  1 +
+ include/linux/mfd/ucb1x00.h                       |  1 +
+ 15 files changed, 182 insertions(+), 129 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mfd/s2mps11.txt
+Merging mfd-lj/for-mfd-next (ec10436 mfd: wm5110: Set FX_CTRL2 to volatile)
+$ git merge --no-ff mfd-lj/for-mfd-next
+Merge made by the 'recursive' strategy.
+ drivers/mfd/88pm800.c          |  2 +-
+ drivers/mfd/88pm805.c          |  2 +-
+ drivers/mfd/88pm860x-core.c    |  2 +-
+ drivers/mfd/aat2870-core.c     |  2 +-
+ drivers/mfd/ab3100-core.c      |  2 +-
+ drivers/mfd/ab8500-gpadc.c     |  4 ++++
+ drivers/mfd/adp5520.c          |  2 +-
+ drivers/mfd/arizona-core.c     |  2 +-
+ drivers/mfd/as3711.c           |  2 +-
+ drivers/mfd/asic3.c            |  2 +-
+ drivers/mfd/da903x.c           |  2 +-
+ drivers/mfd/da9052-core.c      |  2 +-
+ drivers/mfd/da9055-core.c      |  2 +-
+ drivers/mfd/dm355evm_msp.c     |  4 ++--
+ drivers/mfd/ezx-pcap.c         |  6 +++---
+ drivers/mfd/htc-egpio.c        |  2 +-
+ drivers/mfd/htc-i2cpld.c       | 10 +++++-----
+ drivers/mfd/htc-pasic3.c       |  2 +-
+ drivers/mfd/intel_msic.c       |  4 ++--
+ drivers/mfd/kempld-core.c      | 12 ++++++------
+ drivers/mfd/lm3533-core.c      |  8 ++++----
+ drivers/mfd/lp8788.c           |  2 +-
+ drivers/mfd/lpc_ich.c          |  2 +-
+ drivers/mfd/max77686.c         |  2 +-
+ drivers/mfd/max77693.c         |  2 +-
+ drivers/mfd/max8925-i2c.c      |  2 +-
+ drivers/mfd/max8997.c          |  4 ++--
+ drivers/mfd/max8998.c          |  2 +-
+ drivers/mfd/mcp-sa11x0.c       |  2 +-
+ drivers/mfd/menelaus.c         |  6 +++---
+ drivers/mfd/omap-usb-host.c    |  4 ++--
+ drivers/mfd/pcf50633-core.c    |  2 +-
+ drivers/mfd/pm8921-core.c      |  2 +-
+ drivers/mfd/rc5t583.c          |  2 +-
+ drivers/mfd/sec-core.c         |  2 +-
+ drivers/mfd/si476x-i2c.c       |  2 +-
+ drivers/mfd/sm501.c            |  6 +++---
+ drivers/mfd/sta2x11-mfd.c      |  4 ++--
+ drivers/mfd/stmpe.c            |  3 ++-
+ drivers/mfd/t7l66xb.c          |  8 ++++----
+ drivers/mfd/tc3589x.c          |  2 +-
+ drivers/mfd/tc6387xb.c         |  6 +++---
+ drivers/mfd/tc6393xb.c         |  8 ++++----
+ drivers/mfd/ti-ssp.c           |  2 +-
+ drivers/mfd/ti_am335x_tscadc.c |  4 ++--
+ drivers/mfd/tps6105x.c         |  2 +-
+ drivers/mfd/tps65010.c         |  4 ++--
+ drivers/mfd/tps65090.c         |  2 +-
+ drivers/mfd/tps6586x.c         |  2 +-
+ drivers/mfd/tps65912-core.c    |  2 +-
+ drivers/mfd/tps80031.c         |  2 +-
+ drivers/mfd/twl-core.c         |  2 +-
+ drivers/mfd/twl4030-audio.c    |  2 +-
+ drivers/mfd/twl4030-madc.c     |  2 +-
+ drivers/mfd/twl4030-power.c    |  8 ++++----
+ drivers/mfd/ucb1400_core.c     |  2 +-
+ drivers/mfd/ucb1x00-core.c     |  6 ++++--
+ drivers/mfd/wl1273-core.c      |  2 +-
+ drivers/mfd/wm5110-tables.c    | 18 ++++++++++++++++++
+ drivers/mfd/wm831x-core.c      |  2 +-
+ drivers/mfd/wm831x-irq.c       |  2 +-
+ drivers/mfd/wm831x-spi.c       |  1 -
+ drivers/mfd/wm8350-i2c.c       |  3 ++-
+ drivers/mfd/wm8400-core.c      |  2 +-
+ drivers/mfd/wm8994-irq.c       |  2 +-
+ 65 files changed, 125 insertions(+), 100 deletions(-)
+Merging battery/master (5a6c220 charger-manager: Fix regulator_get() return check)
+$ git merge --no-ff battery/master
+Already up-to-date.
+Merging fbdev/for-next (5e8be02 video: atmel_lcdfb: add device tree suport)
+$ git merge --no-ff fbdev/for-next
+Auto-merging arch/avr32/mach-at32ap/at32ap700x.c
+Auto-merging arch/avr32/boards/atngw100/mrmt.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/video/atmel,lcdc.txt       |  75 +++++
+ arch/arm/mach-at91/at91sam9261_devices.c           |   6 +-
+ arch/arm/mach-at91/at91sam9263_devices.c           |   6 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |   6 +-
+ arch/arm/mach-at91/at91sam9rl_devices.c            |   6 +-
+ arch/arm/mach-at91/board-sam9261ek.c               |  10 +-
+ arch/arm/mach-at91/board-sam9263ek.c               |   6 +-
+ arch/arm/mach-at91/board-sam9m10g45ek.c            |   4 +-
+ arch/arm/mach-at91/board-sam9rlek.c                |   6 +-
+ arch/arm/mach-at91/board.h                         |   4 +-
+ arch/avr32/boards/atngw100/evklcd10x.c             |   8 +-
+ arch/avr32/boards/atngw100/mrmt.c                  |   4 +-
+ arch/avr32/boards/atstk1000/atstk1000.h            |   2 +-
+ arch/avr32/boards/atstk1000/setup.c                |   2 +-
+ arch/avr32/boards/favr-32/setup.c                  |   2 +-
+ arch/avr32/boards/hammerhead/setup.c               |   2 +-
+ arch/avr32/boards/merisc/display.c                 |   2 +-
+ arch/avr32/boards/mimc200/setup.c                  |   4 +-
+ arch/avr32/mach-at32ap/at32ap700x.c                |   8 +-
+ arch/avr32/mach-at32ap/include/mach/board.h        |   4 +-
+ drivers/video/Kconfig                              |   2 +
+ drivers/video/atmel_lcdfb.c                        | 343 +++++++++++++++++----
+ include/video/atmel_lcdc.h                         |  25 +-
+ 23 files changed, 402 insertions(+), 135 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/video/atmel,lcdc.txt
+Merging viafb/viafb-next (838ac78 viafb: avoid refresh and mode lookup in set_par)
+$ git merge --no-ff viafb/viafb-next
+Already up-to-date.
+Merging omap_dss2/for-next (fb52566 fb: backlight: HX8357: Add HX8369 support)
+$ git merge --no-ff omap_dss2/for-next
+Auto-merging drivers/video/Kconfig
+Merge made by the 'recursive' strategy.
+ .../bindings/video/simple-framebuffer.txt          |   1 +
+ drivers/video/Kconfig                              |   7 -
+ drivers/video/backlight/hx8357.c                   | 269 ++++++++++++++++++---
+ drivers/video/backlight/lp855x_bl.c                |   2 +-
+ drivers/video/matrox/matroxfb_base.c               |   3 +-
+ drivers/video/mxsfb.c                              |   8 -
+ drivers/video/output.c                             |  20 +-
+ drivers/video/simplefb.c                           |   1 +
+ 8 files changed, 248 insertions(+), 63 deletions(-)
+Merging regulator/for-next (4dc3ef7 Merge remote-tracking branch 'regulator/topic/tps65912' into regulator-next)
+$ git merge --no-ff regulator/for-next
+Auto-merging include/linux/mfd/samsung/s2mps11.h
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/regulator/88pm800.txt      |  38 ++
+ .../devicetree/bindings/regulator/max8660.txt      |  47 +++
+ .../devicetree/bindings/regulator/pfuze100.txt     | 115 ++++++
+ .../devicetree/bindings/regulator/regulator.txt    |   2 +
+ drivers/mmc/core/core.c                            |   2 +-
+ drivers/mmc/host/dw_mmc.c                          |   2 +-
+ drivers/mmc/host/pxamci.c                          |   2 +-
+ drivers/mmc/host/sdhci.c                           |   4 +-
+ drivers/regulator/88pm800.c                        | 380 ++++++++++++++++++
+ drivers/regulator/88pm8607.c                       |   2 +-
+ drivers/regulator/Kconfig                          | 272 +++++++------
+ drivers/regulator/Makefile                         |   7 +-
+ drivers/regulator/aat2870-regulator.c              |   2 +-
+ drivers/regulator/ab3100.c                         |   2 +-
+ drivers/regulator/ad5398.c                         |   2 +-
+ drivers/regulator/as3711-regulator.c               | 163 ++------
+ drivers/regulator/core.c                           | 424 ++++++--------------
+ drivers/regulator/da903x.c                         |  47 +--
+ drivers/regulator/da9052-regulator.c               |   2 +-
+ drivers/regulator/da9055-regulator.c               |   2 +-
+ drivers/regulator/da9210-regulator.c               | 197 +++++++++
+ drivers/regulator/da9210-regulator.h               | 288 +++++++++++++
+ drivers/regulator/fan53555.c                       |   2 +-
+ drivers/regulator/fixed.c                          |   2 +-
+ drivers/regulator/gpio-regulator.c                 |   2 +-
+ drivers/regulator/helpers.c                        | 361 +++++++++++++++++
+ drivers/regulator/isl6271a-regulator.c             |   2 +-
+ drivers/regulator/lp3971.c                         |   2 +-
+ drivers/regulator/lp3972.c                         |   2 +-
+ drivers/regulator/lp872x.c                         |  11 +-
+ drivers/regulator/lp8755.c                         |   3 +-
+ drivers/regulator/max1586.c                        |   2 +-
+ drivers/regulator/max8649.c                        |   2 +-
+ drivers/regulator/max8660.c                        | 108 ++++-
+ drivers/regulator/max8925-regulator.c              |   2 +-
+ drivers/regulator/max8952.c                        |   2 +-
+ drivers/regulator/max8973-regulator.c              |   2 +-
+ drivers/regulator/of_regulator.c                   |  12 +-
+ drivers/regulator/palmas-regulator.c               |   2 +-
+ drivers/regulator/pcap-regulator.c                 |   2 +-
+ drivers/regulator/pcf50633-regulator.c             |   2 +-
+ drivers/regulator/pfuze100-regulator.c             | 445 +++++++++++++++++++++
+ drivers/regulator/s2mps11.c                        | 241 ++++++++---
+ drivers/regulator/tps51632-regulator.c             |   2 +-
+ drivers/regulator/tps62360-regulator.c             |   2 +-
+ drivers/regulator/tps65023-regulator.c             |   2 +-
+ drivers/regulator/tps6524x-regulator.c             |   2 +-
+ drivers/regulator/tps65912-regulator.c             |  39 +-
+ drivers/regulator/twl-regulator.c                  |   2 +-
+ drivers/regulator/userspace-consumer.c             |   2 +-
+ drivers/regulator/virtual.c                        |   2 +-
+ drivers/regulator/wm831x-dcdc.c                    |   8 +-
+ drivers/regulator/wm831x-isink.c                   |   2 +-
+ drivers/regulator/wm831x-ldo.c                     | 110 ++---
+ drivers/regulator/wm8350-regulator.c               |  57 +--
+ drivers/regulator/wm8400-regulator.c               |  52 +--
+ drivers/regulator/wm8994-regulator.c               |   2 +-
+ include/linux/mfd/samsung/s2mps11.h                |  11 +
+ include/linux/regulator/consumer.h                 |  30 +-
+ include/linux/regulator/driver.h                   |  25 ++
+ include/linux/regulator/fan53555.h                 |   1 +
+ include/linux/regulator/machine.h                  |   1 +
+ include/linux/regulator/max8660.h                  |   2 +-
+ include/linux/regulator/pfuze100.h                 |  44 ++
+ 64 files changed, 2734 insertions(+), 875 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/regulator/88pm800.txt
+ create mode 100644 Documentation/devicetree/bindings/regulator/max8660.txt
+ create mode 100644 Documentation/devicetree/bindings/regulator/pfuze100.txt
+ create mode 100644 drivers/regulator/88pm800.c
+ create mode 100644 drivers/regulator/da9210-regulator.c
+ create mode 100644 drivers/regulator/da9210-regulator.h
+ create mode 100644 drivers/regulator/helpers.c
+ create mode 100644 drivers/regulator/pfuze100-regulator.c
+ create mode 100644 include/linux/regulator/pfuze100.h
+Merging security/next (9548906 xattr: Constify ->name member of "struct xattr".)
+$ git merge --no-ff security/next
+Auto-merging security/smack/smack_lsm.c
+Merge made by the 'recursive' strategy.
+ fs/ocfs2/xattr.h                    |  2 +-
+ include/linux/security.h            |  8 ++++----
+ include/linux/xattr.h               |  2 +-
+ include/uapi/linux/reiserfs_xattr.h |  2 +-
+ security/capability.c               |  2 +-
+ security/integrity/evm/evm_main.c   |  2 +-
+ security/security.c                 |  8 +++-----
+ security/selinux/hooks.c            | 17 ++++++-----------
+ security/smack/smack_lsm.c          |  9 +++------
+ 9 files changed, 21 insertions(+), 31 deletions(-)
+Merging selinux/master (2be4d74 Add SELinux policy capability for always checking packet and peer classes.)
+$ git merge --no-ff selinux/master
+Resolved 'security/selinux/hooks.c' using previous resolution.
+Auto-merging security/selinux/ss/policydb.c
+Auto-merging security/selinux/include/xfrm.h
+Auto-merging security/selinux/include/security.h
+Auto-merging security/selinux/hooks.c
+CONFLICT (content): Merge conflict in security/selinux/hooks.c
+Auto-merging security/security.c
+Auto-merging security/capability.c
+Auto-merging include/linux/security.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master edf3992] Merge remote-tracking branch 'selinux/master'
+$ git diff -M --stat --summary HEAD^..
+ include/linux/security.h            |  26 ++-
+ security/capability.c               |  15 +-
+ security/security.c                 |  13 +-
+ security/selinux/hooks.c            | 109 ++++++---
+ security/selinux/include/objsec.h   |   4 +-
+ security/selinux/include/security.h |  15 +-
+ security/selinux/include/xfrm.h     |  45 ++--
+ security/selinux/netnode.c          |   2 +
+ security/selinux/selinuxfs.c        |   4 +-
+ security/selinux/ss/ebitmap.c       |  20 +-
+ security/selinux/ss/ebitmap.h       |  10 +-
+ security/selinux/ss/mls.c           |  22 +-
+ security/selinux/ss/mls_types.h     |   2 +-
+ security/selinux/ss/policydb.c      |   3 +-
+ security/selinux/ss/services.c      |  24 +-
+ security/selinux/xfrm.c             | 453 ++++++++++++++++--------------------
+ 16 files changed, 389 insertions(+), 378 deletions(-)
+Merging lblnet/master (07bc9dc Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc)
+$ git merge --no-ff lblnet/master
+Already up-to-date.
+Merging watchdog/master (b3a3a9c Merge tag 'trace-3.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace)
+$ git merge --no-ff watchdog/master
+Already up-to-date.
+Merging dwmw2-iommu/master (6491d4d intel-iommu: Free old page tables before creating superpage)
+$ git merge --no-ff dwmw2-iommu/master
+Already up-to-date.
+Merging iommu/next (01ce784 Merge branches 'x86/vt-d', 'arm/omap', 'core', 'x86/amd' and 'arm/smmu' into next)
+$ git merge --no-ff iommu/next
+Already up-to-date.
+Merging vfio/next (6cdd978 vfio: add external user support)
+$ git merge --no-ff vfio/next
+Merge made by the 'recursive' strategy.
+ drivers/vfio/vfio.c  | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/vfio.h |  7 ++++++
+ 2 files changed, 69 insertions(+)
+Merging osd/linux-next (861d666 exofs: don't leak io_state and pages on read error)
+$ git merge --no-ff osd/linux-next
+Already up-to-date.
+Merging jc_docs/docs-next (5c050fb docs: update the development process document)
+$ git merge --no-ff jc_docs/docs-next
+Already up-to-date.
+Merging trivial/for-next (ccb7cc0 credits: update contact information for Chris Cheney)
+$ git merge --no-ff trivial/for-next
+Merge made by the 'recursive' strategy.
+ CREDITS                                            | 11 ++++-----
+ Documentation/arm/OMAP/omap_pm                     |  2 +-
+ Documentation/block/cfq-iosched.txt                |  2 +-
+ Documentation/development-process/2.Process        |  4 ++--
+ Documentation/devicetree/bindings/arm/ste-u300.txt |  2 +-
+ .../devicetree/bindings/arm/vexpress-sysreg.txt    |  4 ++--
+ .../devicetree/bindings/clock/clk-exynos-audss.txt |  2 +-
+ .../devicetree/bindings/dma/atmel-dma.txt          |  4 ++--
+ .../devicetree/bindings/dma/fsl-imx-dma.txt        |  2 +-
+ .../devicetree/bindings/dma/ste-dma40.txt          |  4 ++--
+ Documentation/devicetree/bindings/mfd/cros-ec.txt  |  2 +-
+ .../bindings/pinctrl/atmel,at91-pinctrl.txt        |  2 +-
+ Documentation/dma-buf-sharing.txt                  |  2 +-
+ Documentation/fb/fbcon.txt                         |  2 +-
+ Documentation/fb/viafb.txt                         |  2 +-
+ Documentation/filesystems/ext4.txt                 |  2 +-
+ Documentation/filesystems/nfs/pnfs.txt             |  2 +-
+ Documentation/filesystems/relay.txt                |  2 +-
+ Documentation/filesystems/sysfs-tagging.txt        |  2 +-
+ Documentation/i2c/upgrading-clients                |  4 ++--
+ Documentation/printk-formats.txt                   |  2 +-
+ Documentation/rapidio/rapidio.txt                  |  2 +-
+ Documentation/sound/alsa/compress_offload.txt      |  2 +-
+ Documentation/sysfs-rules.txt                      |  2 +-
+ Documentation/virtual/kvm/api.txt                  |  2 +-
+ Documentation/x86/boot.txt                         |  2 +-
+ drivers/media/usb/gspca/vicam.c                    |  2 +-
+ include/linux/coda.h                               |  1 -
+ include/linux/ktime.h                              | 28 ++++++++++++----------
+ 29 files changed, 51 insertions(+), 51 deletions(-)
+Merging audit/for-next (dcd6c92 Linux 3.3-rc1)
+$ git merge --no-ff audit/for-next
+Already up-to-date.
+Merging fsnotify/for-next (1ca39ab inotify: automatically restart syscalls)
+$ git merge --no-ff fsnotify/for-next
+Already up-to-date.
+Merging edac/linux_next (de4772c edac: sb_edac.c should not require prescence of IMC_DDRIO device)
+$ git merge --no-ff edac/linux_next
+Already up-to-date.
+Merging edac-amd/for-next (f0a56c4 amd64_edac: Fix single-channel setups)
+$ git merge --no-ff edac-amd/for-next
+Auto-merging drivers/edac/edac_mc_sysfs.c
+Merge made by the 'recursive' strategy.
+ drivers/edac/amd64_edac.c    | 9 ++++++++-
+ drivers/edac/edac_mc_sysfs.c | 6 ++++--
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+Merging devicetree/devicetree/next (245d964 of/platform: Staticize of_platform_device_create_pdata())
+$ git merge --no-ff devicetree/devicetree/next
+Auto-merging arch/arm/mm/init.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/net/can/sja1000.txt        |  2 +-
+ arch/arc/mm/init.c                                 |  5 ++-
+ arch/arm/mm/init.c                                 |  2 +-
+ arch/arm64/mm/init.c                               |  3 +-
+ arch/c6x/kernel/devicetree.c                       |  3 +-
+ arch/metag/mm/init.c                               |  5 ++-
+ arch/microblaze/kernel/prom.c                      |  3 +-
+ arch/mips/kernel/prom.c                            |  3 +-
+ arch/openrisc/kernel/prom.c                        |  3 +-
+ arch/powerpc/kernel/prom.c                         |  3 +-
+ arch/x86/kernel/devicetree.c                       |  3 +-
+ arch/xtensa/kernel/setup.c                         |  3 +-
+ drivers/of/fdt.c                                   | 10 +++---
+ drivers/of/platform.c                              |  2 +-
+ include/linux/of.h                                 | 39 +++++++++++++---------
+ include/linux/of_fdt.h                             |  3 +-
+ 16 files changed, 46 insertions(+), 46 deletions(-)
+Merging dt-rh/for-next (d683b96 Linux 3.10-rc4)
+$ git merge --no-ff dt-rh/for-next
+Already up-to-date.
+Merging spi/for-next (300f53d Merge remote-tracking branch 'spi/topic/xilinx' into spi-next)
+$ git merge --no-ff spi/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/spi/spi-summary    |   2 +-
+ drivers/spi/Kconfig              |  41 +-
+ drivers/spi/Makefile             |   1 +
+ drivers/spi/spi-atmel.c          |  36 +-
+ drivers/spi/spi-bcm2835.c        |   8 +-
+ drivers/spi/spi-bcm63xx.c        |  21 +-
+ drivers/spi/spi-bfin-v3.c        | 973 +++++++++++++++++++++++++++++++++++++++
+ drivers/spi/spi-bitbang.c        | 261 +++++------
+ drivers/spi/spi-clps711x.c       |   6 -
+ drivers/spi/spi-coldfire-qspi.c  |  21 +-
+ drivers/spi/spi-ep93xx.c         | 353 ++++----------
+ drivers/spi/spi-imx.c            |  76 ++-
+ drivers/spi/spi-mxs.c            |  28 +-
+ drivers/spi/spi-octeon.c         |  10 +-
+ drivers/spi/spi-omap-100k.c      | 276 ++++-------
+ drivers/spi/spi-omap2-mcspi.c    |  20 +-
+ drivers/spi/spi-orion.c          |  23 +-
+ drivers/spi/spi-pl022.c          |  21 +-
+ drivers/spi/spi-pxa2xx.c         |  21 +-
+ drivers/spi/spi-rspi.c           |   7 +-
+ drivers/spi/spi-s3c64xx.c        |  45 +-
+ drivers/spi/spi-sh-hspi.c        |  20 +-
+ drivers/spi/spi-sh-msiof.c       |  18 -
+ drivers/spi/spi-sirf.c           | 181 +++++++-
+ drivers/spi/spi-tegra114.c       |  11 +-
+ drivers/spi/spi-tegra20-sflash.c |   8 +-
+ drivers/spi/spi-tegra20-slink.c  |   8 +-
+ drivers/spi/spi-tle62x0.c        |   3 +-
+ drivers/spi/spi-txx9.c           |   2 +-
+ drivers/spi/spi-xilinx.c         | 172 +++----
+ drivers/spi/spi.c                |  29 ++
+ include/linux/spi/spi.h          |  14 +-
+ include/linux/spi/spi_bitbang.h  |   5 -
+ 33 files changed, 1645 insertions(+), 1076 deletions(-)
+ create mode 100644 drivers/spi/spi-bfin-v3.c
+Merging tip/auto-latest (ef85938 Merge branch 'x86/urgent')
+$ git merge --no-ff tip/auto-latest
+Auto-merging kernel/time/tick-sched.c
+Auto-merging include/linux/sched.h
+Auto-merging arch/powerpc/include/asm/perf_event_server.h
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ .../bindings/timer/moxa,moxart-timer.txt           |  17 +
+ Documentation/memory-hotplug.txt                   |  16 +-
+ Documentation/x86/x86_64/boot-options.txt          |   5 +
+ MAINTAINERS                                        |  10 +-
+ arch/powerpc/include/asm/perf_event_server.h       |   4 +-
+ arch/powerpc/perf/power7-events-list.h             | 548 +++++++++++++++
+ arch/powerpc/perf/power7-pmu.c                     | 148 +----
+ arch/x86/Kconfig                                   |  11 +-
+ arch/x86/ia32/ia32entry.S                          |   2 +-
+ arch/x86/include/asm/acpi.h                        |   2 +
+ arch/x86/include/asm/alternative.h                 |  14 +-
+ arch/x86/include/asm/bitops.h                      |  46 +-
+ arch/x86/include/asm/cpufeature.h                  |  17 +-
+ arch/x86/include/asm/mce.h                         |   3 +
+ arch/x86/include/asm/mmu_context.h                 |  20 +-
+ arch/x86/include/asm/mutex_64.h                    |  30 +
+ arch/x86/include/asm/sync_bitops.h                 |  24 +-
+ arch/x86/include/asm/tsc.h                         |   1 +
+ arch/x86/kernel/acpi/boot.c                        |  20 +-
+ arch/x86/kernel/alternative.c                      | 155 +++--
+ arch/x86/kernel/apic/apic.c                        |   7 +-
+ arch/x86/kernel/cpu/mcheck/mce-internal.h          |   3 +
+ arch/x86/kernel/cpu/mcheck/mce.c                   |  28 +
+ arch/x86/kernel/cpu/mcheck/mce_intel.c             |  42 +-
+ arch/x86/kernel/cpu/perf_event.c                   |   6 +
+ arch/x86/kernel/head_32.S                          |   2 +-
+ arch/x86/kernel/jump_label.c                       |  16 +-
+ arch/x86/kernel/kprobes/common.h                   |   5 -
+ arch/x86/kernel/kprobes/core.c                     |   2 +-
+ arch/x86/kernel/kprobes/opt.c                      | 110 +---
+ arch/x86/kernel/traps.c                            |   4 +
+ arch/x86/kernel/tsc.c                              |   6 +
+ drivers/acpi/apei/erst.c                           |  51 +-
+ drivers/acpi/apei/ghes.c                           |  38 +-
+ drivers/acpi/apei/hest.c                           |  38 ++
+ drivers/clocksource/Makefile                       |   1 +
+ drivers/clocksource/cadence_ttc_timer.c            |  13 +-
+ drivers/clocksource/moxart_timer.c                 | 164 +++++
+ drivers/clocksource/sun4i_timer.c                  | 110 +++-
+ drivers/clocksource/time-orion.c                   |   2 +-
+ include/linux/lockdep.h                            |  92 +--
+ include/linux/mm.h                                 |   1 +
+ include/linux/nodemask.h                           |  11 +-
+ include/linux/sched.h                              |   9 +
+ include/uapi/linux/perf_event.h                    |  46 +-
+ kernel/events/callchain.c                          |   2 +
+ kernel/events/core.c                               | 313 +++++----
+ kernel/hung_task.c                                 |  13 +-
+ kernel/lglock.c                                    |  12 +-
+ kernel/mutex.c                                     |  47 +-
+ kernel/sched/core.c                                |  91 ++-
+ kernel/sched/cpupri.c                              |   4 +-
+ kernel/sched/fair.c                                | 123 ++--
+ kernel/sched/sched.h                               |   8 +-
+ kernel/smp.c                                       |  14 +-
+ kernel/time/tick-sched.c                           |   5 +-
+ kernel/watchdog.c                                  |   8 -
+ mm/memory-failure.c                                |   5 +-
+ tools/lib/traceevent/Makefile                      |  18 +-
+ tools/lib/traceevent/event-parse.c                 |   7 +-
+ tools/lib/traceevent/event-parse.h                 |  15 +-
+ tools/lib/traceevent/kbuffer-parse.c               | 732 +++++++++++++++++++++
+ tools/lib/traceevent/kbuffer.h                     |  67 ++
+ tools/lib/traceevent/trace-seq.c                   |  13 +
+ tools/perf/Documentation/perf-diff.txt             |  79 ++-
+ tools/perf/Documentation/perf-list.txt             |   4 +-
+ tools/perf/Documentation/perf-report.txt           |  13 +-
+ tools/perf/Documentation/perf-top.txt              |   5 +
+ tools/perf/Makefile                                |  11 +-
+ tools/perf/arch/x86/Makefile                       |   2 +
+ tools/perf/arch/x86/util/tsc.c                     |  59 ++
+ tools/perf/arch/x86/util/tsc.h                     |  20 +
+ tools/perf/bench/mem-memcpy.c                      |   2 +
+ tools/perf/builtin-diff.c                          | 662 +++++++++++++++----
+ tools/perf/builtin-inject.c                        |  45 +-
+ tools/perf/builtin-kmem.c                          |   2 +-
+ tools/perf/builtin-list.c                          |   3 +
+ tools/perf/builtin-record.c                        |  13 -
+ tools/perf/builtin-report.c                        |  79 ++-
+ tools/perf/builtin-sched.c                         |  53 +-
+ tools/perf/builtin-script.c                        |   8 +-
+ tools/perf/builtin-timechart.c                     | 176 ++---
+ tools/perf/builtin-top.c                           |  15 +-
+ tools/perf/builtin-trace.c                         |   6 +-
+ tools/perf/config/Makefile                         |   5 +-
+ tools/perf/tests/builtin-test.c                    |   6 +
+ tools/perf/tests/dso-data.c                        |   8 -
+ tools/perf/tests/evsel-tp-sched.c                  |   4 +-
+ tools/perf/tests/make                              |  67 +-
+ tools/perf/tests/parse-events.c                    |  22 +-
+ tools/perf/tests/perf-time-to-tsc.c                | 177 +++++
+ tools/perf/tests/tests.h                           |   9 +
+ tools/perf/tests/vmlinux-kallsyms.c                |  15 +-
+ tools/perf/ui/browsers/hists.c                     |  18 +-
+ tools/perf/ui/gtk/hists.c                          | 126 +++-
+ tools/perf/ui/hist.c                               | 258 +-------
+ tools/perf/ui/setup.c                              |   1 -
+ tools/perf/ui/stdio/hist.c                         |  45 +-
+ tools/perf/util/callchain.c                        |   7 +-
+ tools/perf/util/callchain.h                        |   6 +
+ tools/perf/util/cpumap.h                           |   2 +-
+ tools/perf/util/event.c                            |   2 +-
+ tools/perf/util/event.h                            |   2 +-
+ tools/perf/util/evlist.c                           |  38 +-
+ tools/perf/util/evsel.c                            |  10 +-
+ tools/perf/util/header.c                           | 150 +----
+ tools/perf/util/header.h                           |  40 +-
+ tools/perf/util/hist.c                             |   4 +-
+ tools/perf/util/hist.h                             |  26 +-
+ tools/perf/util/include/linux/string.h             |   1 +
+ tools/perf/util/machine.c                          |  46 +-
+ tools/perf/util/machine.h                          |   8 +-
+ tools/perf/util/parse-events.c                     | 112 ++--
+ tools/perf/util/parse-events.h                     |  11 +-
+ tools/perf/util/parse-events.y                     |  62 +-
+ tools/perf/util/pmu.c                              |  87 ++-
+ tools/perf/util/pmu.h                              |   5 +-
+ .../perf/util/scripting-engines/trace-event-perl.c |  14 +-
+ .../util/scripting-engines/trace-event-python.c    |   9 +-
+ tools/perf/util/session.c                          |  45 +-
+ tools/perf/util/session.h                          |   1 -
+ tools/perf/util/sort.c                             |  12 +-
+ tools/perf/util/sort.h                             |  13 +-
+ tools/perf/util/string.c                           |  24 +
+ tools/perf/util/symbol.c                           |   7 +-
+ tools/perf/util/thread.c                           |  10 +-
+ tools/perf/util/thread.h                           |  14 +-
+ tools/perf/util/tool.h                             |  10 +-
+ tools/perf/util/trace-event-info.c                 |  96 +--
+ tools/perf/util/trace-event-parse.c                |   6 -
+ tools/perf/util/trace-event-read.c                 |  52 +-
+ tools/perf/util/trace-event-scripting.c            |   3 +-
+ tools/perf/util/trace-event.h                      |  21 +-
+ tools/perf/util/util.c                             |  59 ++
+ tools/perf/util/util.h                             |   3 +
+ 135 files changed, 4507 insertions(+), 1926 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
+ create mode 100644 arch/powerpc/perf/power7-events-list.h
+ create mode 100644 drivers/clocksource/moxart_timer.c
+ create mode 100644 tools/lib/traceevent/kbuffer-parse.c
+ create mode 100644 tools/lib/traceevent/kbuffer.h
+ create mode 100644 tools/perf/arch/x86/util/tsc.c
+ create mode 100644 tools/perf/arch/x86/util/tsc.h
+ create mode 100644 tools/perf/tests/perf-time-to-tsc.c
+Merging ftrace/for-next (9457158 tracing: Fix reset of time stamps during trace_clock changes)
+$ git merge --no-ff ftrace/for-next
+Already up-to-date.
+Merging rcu/rcu/next (4cd7ecc rcu: NFI: add diagnostics to RCU's grace-period kthread)
+$ git merge --no-ff rcu/rcu/next
+Auto-merging kernel/rcutree_plugin.h
+Auto-merging kernel/rcutree.h
+Auto-merging kernel/rcutree.c
+Auto-merging kernel/rcutorture.c
+Merge made by the 'recursive' strategy.
+ Documentation/RCU/RTFP.txt        | 855 ++++++++++++++++++++++++--------------
+ Documentation/RCU/rcubarrier.txt  |  12 +-
+ Documentation/RCU/torture.txt     |  10 +
+ Documentation/memory-barriers.txt |  10 +-
+ Documentation/timers/NO_HZ.txt    |  44 +-
+ include/linux/debugobjects.h      |   6 +-
+ include/linux/jiffies.h           |   8 +-
+ include/linux/rculist.h           |   5 +-
+ include/linux/rcupdate.h          |  22 +-
+ init/Kconfig                      |   1 +
+ kernel/rcu.h                      |  10 +-
+ kernel/rcupdate.c                 | 100 -----
+ kernel/rcutorture.c               | 334 ++++++---------
+ kernel/rcutree.c                  | 181 +++++---
+ kernel/rcutree.h                  |  17 +
+ kernel/rcutree_plugin.h           | 423 ++++++++++++++++++-
+ kernel/time/Kconfig               |  23 +
+ lib/debugobjects.c                |  20 +-
+ mm/mlock.c                        |   1 +
+ 19 files changed, 1371 insertions(+), 711 deletions(-)
+Merging cputime/cputime (c3e0ef9 [S390] fix cputime overflow in uptime_proc_show)
+$ git merge --no-ff cputime/cputime
+Already up-to-date.
+Merging uprobes/for-next (0326f5a uprobes/core: Handle breakpoint and singlestep exceptions)
+$ git merge --no-ff uprobes/for-next
+Already up-to-date.
+Merging kvm/linux-next (bf64087 KVM: s390: Make KVM_HVA_ERR_BAD usable on s390)
+$ git merge --no-ff kvm/linux-next
+Auto-merging kernel/sched/core.c
+Auto-merging include/linux/sched.h
+Auto-merging arch/s390/mm/pgtable.c
+Auto-merging arch/s390/include/asm/processor.h
+Auto-merging arch/s390/include/asm/pgtable.h
+Merge made by the 'recursive' strategy.
+ arch/arm/kvm/arm.c                  |   4 +
+ arch/ia64/kvm/kvm-ia64.c            |   4 +
+ arch/mips/kvm/kvm_mips.c            |   4 +
+ arch/powerpc/kvm/powerpc.c          |   4 +
+ arch/s390/include/asm/kvm_host.h    |   8 ++
+ arch/s390/include/asm/mmu.h         |   2 -
+ arch/s390/include/asm/mmu_context.h |  19 +---
+ arch/s390/include/asm/pgtable.h     |  11 ++
+ arch/s390/include/asm/processor.h   |   2 +
+ arch/s390/kvm/diag.c                |  17 +++-
+ arch/s390/kvm/kvm-s390.c            |  27 +++--
+ arch/s390/kvm/kvm-s390.h            |  10 ++
+ arch/s390/kvm/priv.c                |  32 +++---
+ arch/s390/mm/pgtable.c              | 183 +++++++++++++++++++++------------
+ arch/x86/include/asm/kvm_host.h     |   5 +-
+ arch/x86/include/asm/pvclock.h      |   1 -
+ arch/x86/kernel/pvclock.c           |  44 --------
+ arch/x86/kvm/lapic.c                |  33 ++----
+ arch/x86/kvm/mmu.c                  |   7 +-
+ arch/x86/kvm/pmu.c                  |  25 ++++-
+ arch/x86/kvm/vmx.c                  | 195 +++++++++++++++++++++++-------------
+ arch/x86/kvm/x86.c                  | 128 +++++++++++++++++++++--
+ arch/x86/vdso/vclock_gettime.c      |  16 +--
+ include/linux/kvm_host.h            |  13 +++
+ include/linux/sched.h               |   8 --
+ kernel/sched/core.c                 |  15 ---
+ virt/kvm/kvm_main.c                 | 126 +++++++++++++++++++----
+ 27 files changed, 614 insertions(+), 329 deletions(-)
+Merging kvm-arm/kvm-arm-next (8bd4ffd ARM: kvm: don't include drivers/virtio/Kconfig)
+$ git merge --no-ff kvm-arm/kvm-arm-next
+Already up-to-date.
+Merging kvm-ppc/kvm-ppc-next (20f7462 Merge remote-tracking branch 'cmadma/for-v3.12-cma-dma' into kvm-ppc-next)
+$ git merge --no-ff kvm-ppc/kvm-ppc-next
+Resolved 'mm/Kconfig' using previous resolution.
+Auto-merging mm/Kconfig
+CONFLICT (content): Merge conflict in mm/Kconfig
+Auto-merging drivers/base/Makefile
+Auto-merging arch/arm/mm/dma-mapping.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master da4ee64] Merge remote-tracking branch 'kvm-ppc/kvm-ppc-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/include/asm/dma-contiguous.h |  2 +-
+ arch/arm/mm/dma-mapping.c             |  6 +++---
+ drivers/base/Kconfig                  | 20 ++++----------------
+ drivers/base/Makefile                 |  2 +-
+ include/linux/dma-contiguous.h        |  2 +-
+ mm/Kconfig                            | 24 ++++++++++++++++++++++++
+ 6 files changed, 34 insertions(+), 22 deletions(-)
+Merging oprofile/for-next (f722406 Linux 3.10-rc1)
+$ git merge --no-ff oprofile/for-next
+Already up-to-date.
+Merging fw-nohz/nohz/next (74876a9 printk: Wake up klogd using irq_work)
+$ git merge --no-ff fw-nohz/nohz/next
+Already up-to-date.
+Merging xen-tip/linux-next (85e5d6e Merge remote branch 'xentip/stable/for-linus-3.11' into xentip-linux-next)
+$ git merge --no-ff xen-tip/linux-next
+Auto-merging arch/arm/xen/enlighten.c
+Merge made by the 'recursive' strategy.
+ arch/arm/xen/enlighten.c | 1 +
+ 1 file changed, 1 insertion(+)
+Merging percpu/for-next (a424445 percpu-refcount: use RCU-sched insted of normal RCU)
+$ git merge --no-ff percpu/for-next
+Already up-to-date.
+Merging workqueues/for-next (b84acfb Merge branch 'for-3.11-fixes' into for-next)
+$ git merge --no-ff workqueues/for-next
+Auto-merging include/linux/workqueue.h
+Merge made by the 'recursive' strategy.
+ Documentation/workqueue.txt | 18 ++++++------------
+ include/linux/workqueue.h   |  7 ++++++-
+ 2 files changed, 12 insertions(+), 13 deletions(-)
+Merging drivers-x86/linux-next (de91b53 x86 platform drivers: fix gpio leak)
+$ git merge --no-ff drivers-x86/linux-next
+Merge made by the 'recursive' strategy.
+Merging hwpoison/hwpoison (46e387b Merge branch 'hwpoison-hugepages' into hwpoison)
+$ git merge --no-ff hwpoison/hwpoison
+Already up-to-date.
+Merging sysctl/master (4e474a0 sysctl: protect poll() in entries that may go away)
+$ git merge --no-ff sysctl/master
+Already up-to-date.
+Merging regmap/for-next (9851d62 Merge remote-tracking branch 'regmap/topic/sparse' into regmap-next)
+$ git merge --no-ff regmap/for-next
+Merge made by the 'recursive' strategy.
+ drivers/base/regmap/regmap-irq.c | 25 +++++++++++++++++++++++++
+ drivers/base/regmap/regmap.c     | 23 ++++++++++++++---------
+ include/linux/regmap.h           | 10 +++++++---
+ 3 files changed, 46 insertions(+), 12 deletions(-)
+Merging hsi/for-next (43139a6 HSI: hsi_char: Update ioctl-number.txt)
+$ git merge --no-ff hsi/for-next
+Already up-to-date.
+Merging leds/for-next (519220a leds: ss4200: Fix incorrect placement of __initdata)
+$ git merge --no-ff leds/for-next
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/leds/leds-lp55xx.txt       |  72 +++-
+ Documentation/devicetree/bindings/leds/pca9633.txt |  46 +++
+ Documentation/leds/leds-lp55xx.txt                 |  30 +-
+ drivers/leds/Kconfig                               |  25 +-
+ drivers/leds/Makefile                              |   1 +
+ drivers/leds/leds-88pm860x.c                       |   2 +-
+ drivers/leds/leds-adp5520.c                        |   6 +-
+ drivers/leds/leds-asic3.c                          |   4 +-
+ drivers/leds/leds-atmel-pwm.c                      |   4 +-
+ drivers/leds/leds-bd2802.c                         |   2 +-
+ drivers/leds/leds-clevo-mail.c                     |   2 +-
+ drivers/leds/leds-da903x.c                         |   2 +-
+ drivers/leds/leds-da9052.c                         |   4 +-
+ drivers/leds/leds-gpio.c                           |   2 +-
+ drivers/leds/leds-lm3530.c                         |   2 +-
+ drivers/leds/leds-lm3533.c                         |   2 +-
+ drivers/leds/leds-lm355x.c                         |   2 +-
+ drivers/leds/leds-lm3642.c                         |   2 +-
+ drivers/leds/leds-lp3944.c                         |   7 +-
+ drivers/leds/leds-lp5521.c                         |   4 +-
+ drivers/leds/leds-lp5523.c                         |   4 +-
+ drivers/leds/leds-lp5562.c                         |   4 +-
+ drivers/leds/leds-lp55xx-common.c                  |   3 +
+ drivers/leds/leds-lp8501.c                         | 410 +++++++++++++++++++++
+ drivers/leds/leds-lt3593.c                         |   4 +-
+ drivers/leds/leds-netxbig.c                        |   6 +-
+ drivers/leds/leds-ns2.c                            |   2 +-
+ drivers/leds/leds-pca9532.c                        |   3 +-
+ drivers/leds/leds-pca955x.c                        |   2 +-
+ drivers/leds/leds-pca9633.c                        | 209 ++++++++++-
+ drivers/leds/leds-pwm.c                            |   2 +-
+ drivers/leds/leds-regulator.c                      |   3 +-
+ drivers/leds/leds-renesas-tpu.c                    |  12 +-
+ drivers/leds/leds-s3c24xx.c                        |   2 +-
+ drivers/leds/leds-ss4200.c                         |   4 +-
+ drivers/leds/leds-tca6507.c                        |   2 +-
+ drivers/leds/leds-wm831x-status.c                  |   4 +-
+ drivers/leds/leds-wm8350.c                         |   2 +-
+ include/linux/platform_data/leds-lp55xx.h          |  10 +
+ include/linux/platform_data/leds-pca9633.h         |   6 +
+ 40 files changed, 848 insertions(+), 67 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/leds/pca9633.txt
+ create mode 100644 drivers/leds/leds-lp8501.c
+Merging driver-core/driver-core-next (e70b091 tile / cpu topology: remove stale Macro arch_provides_topology_pointers)
+$ git merge --no-ff driver-core/driver-core-next
+Resolved 'net/core/net-sysfs.c' using previous resolution.
+Auto-merging net/core/net-sysfs.c
+CONFLICT (content): Merge conflict in net/core/net-sysfs.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 6d00798] Merge remote-tracking branch 'driver-core/driver-core-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/tile/include/asm/topology.h     |   3 -
+ arch/x86/include/asm/topology.h      |   3 -
+ drivers/base/core.c                  |  28 +++---
+ drivers/base/memory.c                |   4 +-
+ drivers/base/power/sysfs.c           |   2 +-
+ drivers/base/regmap/regmap-debugfs.c |   2 +-
+ drivers/base/topology.c              |  20 ----
+ drivers/char/bsr.c                   |  18 ++--
+ drivers/char/tile-srom.c             |  28 +++---
+ drivers/dma/dmaengine.c              |  26 +++--
+ drivers/extcon/extcon-class.c        |  13 ++-
+ drivers/isdn/mISDN/core.c            |  64 +++++++------
+ drivers/leds/led-class.c             |  38 ++++++--
+ drivers/misc/c2port/core.c           |  83 ++++++++--------
+ drivers/misc/enclosure.c             |  29 +++---
+ drivers/ptp/ptp_clock.c              |   2 +-
+ drivers/ptp/ptp_private.h            |   2 +-
+ drivers/ptp/ptp_sysfs.c              |  51 +++++-----
+ drivers/rtc/rtc-sysfs.c              |  48 +++++-----
+ drivers/scsi/osd/osd_uld.c           |  13 ++-
+ drivers/staging/comedi/comedi_fops.c |  39 ++++----
+ drivers/uio/uio.c                    |  22 +++--
+ drivers/video/backlight/backlight.c  |  44 +++++----
+ drivers/video/backlight/lcd.c        |  26 ++---
+ fs/fuse/cuse.c                       |  13 ++-
+ include/linux/kobject.h              |   4 +
+ lib/Kconfig.debug                    |  19 ++++
+ lib/kobject.c                        |  22 ++++-
+ net/core/net-sysfs.c                 | 181 +++++++++++++++++++----------------
+ net/ieee802154/wpan-class.c          |  23 +++--
+ net/rfkill/core.c                    |  90 ++++++++---------
+ net/wireless/sysfs.c                 |  25 ++---
+ 32 files changed, 540 insertions(+), 445 deletions(-)
+Merging tty/tty-next (16cf48a register_console: prevent adding the same console twice)
+$ git merge --no-ff tty/tty-next
+Resolved 'drivers/tty/serial/sh-sci.c' using previous resolution.
+Auto-merging drivers/tty/serial/sh-sci.c
+CONFLICT (content): Merge conflict in drivers/tty/serial/sh-sci.c
+Auto-merging Documentation/kernel-parameters.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 2d657f4] Merge remote-tracking branch 'tty/tty-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/tty/serial/atmel-usart.txt |   18 +-
+ .../bindings/tty/serial/fsl-mxs-auart.txt          |    4 +
+ .../devicetree/bindings/tty/serial/st-asc.txt      |   18 +
+ Documentation/kernel-parameters.txt                |   10 +
+ arch/arm/boot/dts/imx28-evk.dts                    |    1 +
+ arch/mips/sni/a20r.c                               |    1 -
+ drivers/net/irda/irtty-sir.c                       |    8 +-
+ drivers/staging/comedi/comedidev.h                 |    1 -
+ drivers/staging/dgrp/dgrp_tty.c                    |    2 +
+ drivers/tty/hvc/hvc_console.c                      |   11 +-
+ drivers/tty/hvc/hvc_console.h                      |    3 +
+ drivers/tty/hvc/hvc_iucv.c                         |   64 +-
+ drivers/tty/n_gsm.c                                |   29 +-
+ drivers/tty/n_tty.c                                | 1401 ++++++++++++--------
+ drivers/tty/pty.c                                  |   18 +-
+ drivers/tty/serial/8250/8250_core.c                |    2 +-
+ drivers/tty/serial/8250/8250_em.c                  |   27 +-
+ drivers/tty/serial/8250/8250_pci.c                 |   15 +-
+ drivers/tty/serial/8250/Kconfig                    |    2 +
+ drivers/tty/serial/Kconfig                         |   26 +-
+ drivers/tty/serial/Makefile                        |    1 +
+ drivers/tty/serial/altera_jtaguart.c               |    3 +-
+ drivers/tty/serial/altera_uart.c                   |    2 +-
+ drivers/tty/serial/amba-pl010.c                    |    2 +-
+ drivers/tty/serial/amba-pl011.c                    |   14 +-
+ drivers/tty/serial/ar933x_uart.c                   |    3 +-
+ drivers/tty/serial/arc_uart.c                      |   33 +-
+ drivers/tty/serial/atmel_serial.c                  |  857 +++++++++---
+ drivers/tty/serial/bcm63xx_uart.c                  |    1 -
+ drivers/tty/serial/bfin_sport_uart.c               |    7 +-
+ drivers/tty/serial/bfin_uart.c                     |   15 +-
+ drivers/tty/serial/clps711x.c                      |   11 +-
+ drivers/tty/serial/efm32-uart.c                    |   25 +-
+ drivers/tty/serial/fsl_lpuart.c                    |    7 +-
+ drivers/tty/serial/ifx6x60.c                       |    2 +-
+ drivers/tty/serial/imx.c                           |  517 +++++++-
+ drivers/tty/serial/max3100.c                       |    2 +-
+ drivers/tty/serial/max310x.c                       |  991 +++++++-------
+ drivers/tty/serial/mcf.c                           |    3 +-
+ drivers/tty/serial/mpsc.c                          |    4 +-
+ drivers/tty/serial/msm_serial.c                    |  184 +--
+ drivers/tty/serial/msm_serial.h                    |   19 +-
+ drivers/tty/serial/msm_serial_hs.c                 |    2 +-
+ drivers/tty/serial/mxs-auart.c                     |   16 +-
+ drivers/tty/serial/netx-serial.c                   |    2 -
+ drivers/tty/serial/omap-serial.c                   |   47 +-
+ drivers/tty/serial/pch_uart.c                      |   82 +-
+ drivers/tty/serial/pmac_zilog.c                    |    1 -
+ drivers/tty/serial/pnx8xxx_uart.c                  |    2 -
+ drivers/tty/serial/pxa.c                           |    2 -
+ drivers/tty/serial/sa1100.c                        |    2 -
+ drivers/tty/serial/samsung.c                       |    4 +-
+ drivers/tty/serial/sc26xx.c                        |    2 +-
+ drivers/tty/serial/sccnxp.c                        |  339 +++--
+ drivers/tty/serial/serial_core.c                   |    4 +-
+ drivers/tty/serial/serial_txx9.c                   |    2 +-
+ drivers/tty/serial/sh-sci.c                        |    4 +-
+ drivers/tty/serial/sirfsoc_uart.c                  |    3 +-
+ drivers/tty/serial/st-asc.c                        |  939 +++++++++++++
+ drivers/tty/serial/vr41xx_siu.c                    |    2 +-
+ drivers/tty/serial/vt8500_serial.c                 |    1 -
+ drivers/tty/synclink.c                             |  130 +-
+ drivers/tty/tty_buffer.c                           |  417 +++---
+ drivers/tty/tty_io.c                               |   33 +-
+ drivers/tty/tty_ioctl.c                            |   90 +-
+ drivers/tty/tty_ldisc.c                            |  461 +++----
+ drivers/tty/vt/keyboard.c                          |   21 +-
+ drivers/tty/vt/selection.c                         |    8 +-
+ drivers/tty/vt/vt.c                                |    8 +-
+ include/linux/atmel_serial.h                       |    2 +
+ include/linux/kbd_kern.h                           |    3 +-
+ include/linux/llist.h                              |   23 +
+ include/linux/pci_ids.h                            |    4 +-
+ include/linux/platform_data/max310x.h              |    9 +-
+ include/linux/platform_data/serial-sccnxp.h        |    3 -
+ include/linux/tty.h                                |   66 +-
+ include/linux/tty_flip.h                           |    8 +-
+ include/linux/tty_ldisc.h                          |   16 +-
+ include/uapi/linux/serial_core.h                   |    3 +
+ include/uapi/linux/serial_reg.h                    |    1 +
+ kernel/printk/printk.c                             |    7 +
+ 81 files changed, 4686 insertions(+), 2447 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt
+ create mode 100644 drivers/tty/serial/st-asc.c
+Merging usb/usb-next (5b146f7 Merge 3.11-rc4 into usb-next)
+$ git merge --no-ff usb/usb-next
+Auto-merging drivers/usb/host/xhci.c
+Auto-merging drivers/usb/core/hub.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                           |    1 -
+ drivers/usb/Makefile                  |    1 +
+ drivers/usb/atm/Makefile              |    3 -
+ drivers/usb/atm/speedtch.c            |    2 +-
+ drivers/usb/atm/usbatm.c              |   49 +-
+ drivers/usb/atm/usbatm.h              |   35 +-
+ drivers/usb/c67x00/c67x00-drv.c       |    4 +-
+ drivers/usb/class/cdc-acm.c           |    2 +-
+ drivers/usb/class/usbtmc.c            |   46 +-
+ drivers/usb/core/buffer.c             |    5 +-
+ drivers/usb/core/devio.c              |    6 +-
+ drivers/usb/core/driver.c             |   22 +-
+ drivers/usb/core/endpoint.c           |    1 -
+ drivers/usb/core/file.c               |    2 +-
+ drivers/usb/core/hcd-pci.c            |    2 +
+ drivers/usb/core/hcd.c                |   37 +-
+ drivers/usb/core/hub.c                |  195 +-
+ drivers/usb/core/message.c            |   62 +-
+ drivers/usb/core/urb.c                |   42 +-
+ drivers/usb/core/usb.c                |   60 +-
+ drivers/usb/gadget/storage_common.c   |    2 +-
+ drivers/usb/host/Kconfig              |   12 +
+ drivers/usb/host/Makefile             |    1 +
+ drivers/usb/host/ehci-fsl.c           |   14 +-
+ drivers/usb/host/ehci-grlib.c         |   11 +-
+ drivers/usb/host/ehci-hub.c           |   63 +-
+ drivers/usb/host/ehci-mv.c            |    2 +-
+ drivers/usb/host/ehci-mxc.c           |   14 +-
+ drivers/usb/host/ehci-omap.c          |   14 +-
+ drivers/usb/host/ehci-orion.c         |    2 +-
+ drivers/usb/host/ehci-pci.c           |   42 -
+ drivers/usb/host/ehci-platform.c      |   12 +-
+ drivers/usb/host/ehci-ppc-of.c        |   11 +-
+ drivers/usb/host/ehci-s5p.c           |   12 +-
+ drivers/usb/host/ehci-sh.c            |    2 +-
+ drivers/usb/host/ehci-tegra.c         |    2 +-
+ drivers/usb/host/ehci-tilegx.c        |    4 +-
+ drivers/usb/host/ehci-xilinx-of.c     |   17 +-
+ drivers/usb/host/fotg210-hcd.c        | 6049 +++++++++++++++++++++++++++++++++
+ drivers/usb/host/fotg210.h            |  750 ++++
+ drivers/usb/host/fsl-mph-dr-of.c      |    4 +-
+ drivers/usb/host/imx21-hcd.c          |    2 +-
+ drivers/usb/host/isp116x-hcd.c        |    2 +-
+ drivers/usb/host/isp116x.h            |   13 +-
+ drivers/usb/host/isp1362-hcd.c        |   85 +-
+ drivers/usb/host/isp1362.h            |   53 +-
+ drivers/usb/host/isp1760-if.c         |    2 +-
+ drivers/usb/host/ohci-at91.c          |   35 +-
+ drivers/usb/host/ohci-da8xx.c         |    8 +-
+ drivers/usb/host/ohci-ep93xx.c        |  137 +-
+ drivers/usb/host/ohci-exynos.c        |    2 +-
+ drivers/usb/host/ohci-hcd.c           |    2 +-
+ drivers/usb/host/ohci-omap.c          |    4 +-
+ drivers/usb/host/ohci-omap3.c         |   10 +-
+ drivers/usb/host/ohci-platform.c      |   10 +-
+ drivers/usb/host/ohci-ppc-of.c        |   11 +-
+ drivers/usb/host/ohci-pxa27x.c        |    8 +-
+ drivers/usb/host/ohci-s3c2410.c       |   11 +-
+ drivers/usb/host/ohci-tilegx.c        |    4 +-
+ drivers/usb/host/pci-quirks.c         |   48 +-
+ drivers/usb/host/pci-quirks.h         |    3 +-
+ drivers/usb/host/r8a66597-hcd.c       |    2 +-
+ drivers/usb/host/sl811-hcd.c          |  109 +-
+ drivers/usb/host/sl811.h              |   21 +-
+ drivers/usb/host/u132-hcd.c           |    6 +-
+ drivers/usb/host/xhci-hub.c           |  221 +-
+ drivers/usb/host/xhci-pci.c           |   14 +-
+ drivers/usb/host/xhci-plat.c          |   26 +
+ drivers/usb/host/xhci.c               |   10 +-
+ drivers/usb/misc/Kconfig              |   13 +
+ drivers/usb/misc/Makefile             |    4 +-
+ drivers/usb/misc/adutux.c             |  200 +-
+ drivers/usb/misc/ehset.c              |  134 +
+ drivers/usb/misc/ldusb.c              |   31 +-
+ drivers/usb/misc/legousbtower.c       |  124 +-
+ drivers/usb/misc/usb3503.c            |    2 +-
+ drivers/usb/misc/usbtest.c            |    9 +-
+ drivers/usb/musb/musb_core.c          |    1 -
+ drivers/usb/phy/Kconfig               |    2 +
+ drivers/usb/phy/Makefile              |    3 -
+ drivers/usb/phy/phy-fsl-usb.c         |    6 +-
+ drivers/usb/phy/phy-fsm-usb.h         |   11 +-
+ drivers/usb/phy/phy-isp1301-omap.c    |    6 +-
+ drivers/usb/renesas_usbhs/common.c    |    4 +-
+ drivers/usb/serial/console.c          |   27 +-
+ drivers/usb/serial/cp210x.c           |    3 -
+ drivers/usb/serial/cypress_m8.c       |    4 +-
+ drivers/usb/serial/f81232.c           |    3 +-
+ drivers/usb/serial/ftdi_sio.c         |   52 +-
+ drivers/usb/serial/generic.c          |   13 +-
+ drivers/usb/serial/io_edgeport.c      |    2 -
+ drivers/usb/serial/io_ti.c            |   71 +-
+ drivers/usb/serial/mos7840.c          |   48 -
+ drivers/usb/serial/oti6858.c          |   10 +-
+ drivers/usb/serial/pl2303.c           |  179 +-
+ drivers/usb/serial/safe_serial.c      |   51 +-
+ drivers/usb/serial/spcp8x5.c          |    4 +-
+ drivers/usb/serial/ti_usb_3410_5052.c |  103 +-
+ drivers/usb/serial/usb-serial.c       |   14 +-
+ drivers/usb/usb-skeleton.c            |    3 +-
+ include/linux/usb.h                   |   26 +-
+ 101 files changed, 8039 insertions(+), 1600 deletions(-)
+ create mode 100644 drivers/usb/host/fotg210-hcd.c
+ create mode 100644 drivers/usb/host/fotg210.h
+ create mode 100644 drivers/usb/misc/ehset.c
+Merging usb-gadget/next (941ea36 usb: dwc3: use dev_get_platdata())
+$ git merge --no-ff usb-gadget/next
+Resolved 'drivers/usb/gadget/udc-core.c' using previous resolution.
+Resolved 'drivers/usb/host/ehci-tegra.c' using previous resolution.
+Resolved 'drivers/usb/musb/omap2430.c' using previous resolution.
+Resolved 'drivers/usb/musb/tusb6010.c' using previous resolution.
+Removing include/linux/platform_data/tegra_usb.h
+Auto-merging drivers/usb/phy/phy-fsl-usb.c
+Auto-merging drivers/usb/phy/Kconfig
+Auto-merging drivers/usb/musb/tusb6010.c
+CONFLICT (content): Merge conflict in drivers/usb/musb/tusb6010.c
+Auto-merging drivers/usb/musb/omap2430.c
+CONFLICT (content): Merge conflict in drivers/usb/musb/omap2430.c
+Auto-merging drivers/usb/musb/musb_core.c
+Auto-merging drivers/usb/host/ehci-tegra.c
+CONFLICT (content): Merge conflict in drivers/usb/host/ehci-tegra.c
+Auto-merging drivers/usb/host/Kconfig
+Auto-merging drivers/usb/gadget/udc-core.c
+CONFLICT (content): Merge conflict in drivers/usb/gadget/udc-core.c
+Removing drivers/usb/gadget/imx_udc.h
+Removing drivers/usb/gadget/imx_udc.c
+Auto-merging drivers/usb/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master b2be704] Merge remote-tracking branch 'usb-gadget/next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/usb/dwc3.txt     |    4 +-
+ Documentation/devicetree/bindings/usb/generic.txt  |   24 +
+ .../bindings/usb/nvidia,tegra20-usb-phy.txt        |    2 +-
+ .../devicetree/bindings/usb/samsung-hsotg.txt      |   40 +
+ arch/arm/boot/dts/omap5.dtsi                       |    2 +-
+ arch/arm/boot/dts/tegra20-seaboard.dts             |    1 -
+ arch/arm/boot/dts/tegra20-trimslice.dts            |    1 -
+ arch/arm/boot/dts/tegra20-whistler.dts             |    2 -
+ arch/arm/boot/dts/tegra20.dtsi                     |   28 +-
+ arch/arm/mach-tegra/tegra.c                        |   38 +-
+ drivers/usb/Makefile                               |    2 +-
+ drivers/usb/dwc3/Kconfig                           |   32 +
+ drivers/usb/dwc3/Makefile                          |   13 +-
+ drivers/usb/dwc3/core.c                            |  193 ++-
+ drivers/usb/dwc3/core.h                            |   53 +-
+ drivers/usb/dwc3/debug.h                           |   34 +-
+ drivers/usb/dwc3/debugfs.c                         |   34 +-
+ drivers/usb/dwc3/dwc3-exynos.c                     |   14 +-
+ drivers/usb/dwc3/dwc3-omap.c                       |   44 +-
+ drivers/usb/dwc3/dwc3-pci.c                        |   36 +-
+ drivers/usb/dwc3/ep0.c                             |   49 +-
+ drivers/usb/dwc3/gadget.c                          |  257 ++--
+ drivers/usb/dwc3/gadget.h                          |   34 +-
+ drivers/usb/dwc3/host.c                            |   34 +-
+ drivers/usb/dwc3/io.h                              |   34 +-
+ drivers/usb/dwc3/platform_data.h                   |   27 +
+ drivers/usb/gadget/Kconfig                         |   17 -
+ drivers/usb/gadget/Makefile                        |    1 -
+ drivers/usb/gadget/at91_udc.c                      |    4 +-
+ drivers/usb/gadget/atmel_usba_udc.c                |   30 +-
+ drivers/usb/gadget/bcm63xx_udc.c                   |    2 +-
+ drivers/usb/gadget/fsl_mxc_udc.c                   |    4 +-
+ drivers/usb/gadget/fsl_udc_core.c                  |    6 +-
+ drivers/usb/gadget/hid.c                           |    2 +-
+ drivers/usb/gadget/imx_udc.c                       | 1544 --------------------
+ drivers/usb/gadget/imx_udc.h                       |  351 -----
+ drivers/usb/gadget/m66592-udc.c                    |    4 +-
+ drivers/usb/gadget/mv_u3d_core.c                   |   12 +-
+ drivers/usb/gadget/mv_udc_core.c                   |    4 +-
+ drivers/usb/gadget/omap_udc.c                      |    2 +-
+ drivers/usb/gadget/pxa25x_udc.c                    |    2 +-
+ drivers/usb/gadget/pxa27x_udc.c                    |    2 +-
+ drivers/usb/gadget/r8a66597-udc.c                  |    2 +-
+ drivers/usb/gadget/s3c-hsotg.c                     |   14 +-
+ drivers/usb/gadget/s3c-hsudc.c                     |    4 +-
+ drivers/usb/gadget/s3c2410_udc.c                   |    2 +-
+ drivers/usb/gadget/udc-core.c                      |   12 +-
+ drivers/usb/host/Kconfig                           |    5 +-
+ drivers/usb/host/ehci-tegra.c                      |   71 +-
+ drivers/usb/musb/am35x.c                           |   14 +-
+ drivers/usb/musb/blackfin.c                        |    2 +-
+ drivers/usb/musb/cppi_dma.c                        |   18 +-
+ drivers/usb/musb/da8xx.c                           |    2 +-
+ drivers/usb/musb/davinci.c                         |    2 +-
+ drivers/usb/musb/musb_core.c                       |   30 +-
+ drivers/usb/musb/musb_core.h                       |    8 -
+ drivers/usb/musb/musb_dma.h                        |   19 +-
+ drivers/usb/musb/musb_dsps.c                       |   38 +-
+ drivers/usb/musb/musb_gadget.c                     |    5 +-
+ drivers/usb/musb/musbhsdma.c                       |   17 +-
+ drivers/usb/musb/omap2430.c                        |    8 +-
+ drivers/usb/musb/tusb6010.c                        |    2 +-
+ drivers/usb/musb/tusb6010_omap.c                   |   24 -
+ drivers/usb/musb/ux500.c                           |    2 +-
+ drivers/usb/musb/ux500_dma.c                       |   21 +-
+ drivers/usb/phy/Kconfig                            |   36 +-
+ drivers/usb/phy/phy-fsl-usb.c                      |    6 +-
+ drivers/usb/phy/phy-gpio-vbus-usb.c                |   10 +-
+ drivers/usb/phy/phy-msm-usb.c                      |    4 +-
+ drivers/usb/phy/phy-mv-u3d-usb.c                   |    2 +-
+ drivers/usb/phy/phy-mv-usb.c                       |    2 +-
+ drivers/usb/phy/phy-mxs-usb.c                      |   13 +-
+ drivers/usb/phy/phy-nop.c                          |    3 +-
+ drivers/usb/phy/phy-omap-control.c                 |    3 +-
+ drivers/usb/phy/phy-omap-usb3.c                    |   87 +-
+ drivers/usb/phy/phy-rcar-usb.c                     |    9 +-
+ drivers/usb/phy/phy-samsung-usb2.c                 |    2 +-
+ drivers/usb/phy/phy-samsung-usb3.c                 |    2 +-
+ drivers/usb/phy/phy-tegra-usb.c                    |  254 ++--
+ drivers/usb/phy/phy-twl4030-usb.c                  |    2 +-
+ drivers/usb/phy/phy-twl6030-usb.c                  |    2 +-
+ drivers/usb/renesas_usbhs/mod_gadget.c             |    6 +-
+ drivers/usb/renesas_usbhs/mod_host.c               |    6 +-
+ drivers/usb/renesas_usbhs/pipe.h                   |    6 +-
+ drivers/usb/usb-common.c                           |   49 +-
+ include/linux/platform_data/tegra_usb.h            |   32 -
+ include/linux/usb/gadget.h                         |    4 +
+ include/linux/usb/of.h                             |   10 +-
+ include/linux/usb/phy.h                            |   18 +-
+ include/linux/usb/tegra_usb_phy.h                  |   17 +-
+ 90 files changed, 902 insertions(+), 3024 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/usb/generic.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/samsung-hsotg.txt
+ create mode 100644 drivers/usb/dwc3/platform_data.h
+ delete mode 100644 drivers/usb/gadget/imx_udc.c
+ delete mode 100644 drivers/usb/gadget/imx_udc.h
+ delete mode 100644 include/linux/platform_data/tegra_usb.h
+Merging staging/staging-next (98f62b7 staging/zcache: Fix memory leak while dropping an o2net_sock_container object)
+$ git merge --no-ff staging/staging-next
+Removing drivers/staging/ozwpan/oztrace.h
+Removing drivers/staging/ozwpan/oztrace.c
+Removing drivers/staging/ozwpan/ozconfig.h
+Auto-merging drivers/staging/ozwpan/Makefile
+Removing drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c
+Removing drivers/staging/lustre/lustre/libcfs/watchdog.c
+Removing drivers/staging/lustre/lustre/include/lustre_mdt.h
+Removing drivers/staging/lustre/lustre/fld/fld_index.c
+Removing drivers/staging/lustre/lustre/fld/fld_handler.c
+Removing drivers/staging/lustre/lustre/fid/fid_store.c
+Removing drivers/staging/lustre/lustre/fid/fid_handler.c
+Removing drivers/staging/lustre/lnet/lnet/api-errno.c
+Auto-merging drivers/staging/imx-drm/imx-drm-core.c
+Removing drivers/staging/iio/gyro/adis16260_platform_data.h
+Removing drivers/staging/iio/gyro/adis16260.h
+Removing drivers/staging/comedi/drivers/addi_apci_1710.c
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+Auto-merging drivers/staging/comedi/comedidev.h
+Auto-merging drivers/staging/comedi/comedi_fops.c
+Removing drivers/staging/asus_oled/zig.txt
+Removing drivers/staging/asus_oled/tux_r2.txt
+Removing drivers/staging/asus_oled/tux_r.txt
+Removing drivers/staging/asus_oled/tux.txt
+Removing drivers/staging/asus_oled/linux_fr.txt
+Removing drivers/staging/asus_oled/linux_f.txt
+Removing drivers/staging/asus_oled/linux.txt
+Removing drivers/staging/asus_oled/asus_oled.c
+Removing drivers/staging/asus_oled/TODO
+Removing drivers/staging/asus_oled/README
+Removing drivers/staging/asus_oled/Makefile
+Removing drivers/staging/asus_oled/Kconfig
+Auto-merging drivers/iio/gyro/adis16260.c
+Auto-merging drivers/iio/adc/ti_am335x_adc.c
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-bus-iio            |    9 +
+ .../ABI/testing/sysfs-bus-iio-frequency-ad9523     |    8 -
+ .../ABI/testing/sysfs-bus-iio-frequency-adf4350    |    2 +-
+ .../bindings/iio/adc/nuvoton-nau7802.txt           |   18 +
+ .../devicetree/bindings/iio/light/apds9300.txt     |   22 +
+ .../devicetree/bindings/vendor-prefixes.txt        |    1 +
+ Documentation/driver-model/devres.txt              |    4 +
+ drivers/iio/Kconfig                                |    7 +-
+ drivers/iio/accel/Kconfig                          |   20 +-
+ drivers/iio/accel/Makefile                         |    4 +-
+ drivers/iio/accel/hid-sensor-accel-3d.c            |   35 +-
+ drivers/iio/accel/kxsd9.c                          |   17 +-
+ drivers/iio/accel/st_accel.h                       |   11 +-
+ drivers/iio/accel/st_accel_core.c                  |   28 +-
+ drivers/iio/accel/st_accel_i2c.c                   |   17 +-
+ drivers/iio/accel/st_accel_spi.c                   |   17 +-
+ drivers/iio/adc/Kconfig                            |   47 +-
+ drivers/iio/adc/Makefile                           |    2 +
+ drivers/iio/adc/ad7266.c                           |   16 +-
+ drivers/iio/adc/ad7298.c                           |   24 +-
+ drivers/iio/adc/ad7476.c                           |   26 +-
+ drivers/iio/adc/ad7791.c                           |   19 +-
+ drivers/iio/adc/ad7793.c                           |   23 +-
+ drivers/iio/adc/ad7887.c                           |   23 +-
+ drivers/iio/adc/ad7923.c                           |   20 +-
+ drivers/iio/adc/at91_adc.c                         |   23 +-
+ drivers/iio/adc/exynos_adc.c                       |   23 +-
+ drivers/iio/adc/lp8788_adc.c                       |    7 +-
+ drivers/iio/adc/max1363.c                          |   15 +-
+ drivers/iio/adc/mcp320x.c                          |   18 +-
+ drivers/iio/adc/nau7802.c                          |  581 +++
+ drivers/iio/adc/ti-adc081c.c                       |   18 +-
+ drivers/iio/adc/ti_am335x_adc.c                    |   13 +-
+ drivers/iio/adc/viperboard_adc.c                   |    9 +-
+ drivers/iio/amplifiers/Kconfig                     |    2 +
+ drivers/iio/amplifiers/Makefile                    |    1 +
+ drivers/iio/amplifiers/ad8366.c                    |   13 +-
+ drivers/iio/common/Makefile                        |    1 +
+ drivers/iio/common/st_sensors/st_sensors_core.c    |   41 +-
+ drivers/iio/dac/Kconfig                            |   44 +-
+ drivers/iio/dac/Makefile                           |    1 +
+ drivers/iio/dac/mcp4725.c                          |  177 +-
+ drivers/iio/frequency/Kconfig                      |    1 +
+ drivers/iio/frequency/Makefile                     |    1 +
+ drivers/iio/frequency/ad9523.c                     |   17 +-
+ drivers/iio/frequency/adf4350.c                    |   31 +-
+ drivers/iio/gyro/Kconfig                           |   18 +-
+ drivers/iio/gyro/Makefile                          |    2 +
+ .../gyro/adis16260_core.c => iio/gyro/adis16260.c} |  305 +-
+ drivers/iio/gyro/hid-sensor-gyro-3d.c              |   16 +-
+ drivers/iio/gyro/st_gyro.h                         |   11 +-
+ drivers/iio/gyro/st_gyro_core.c                    |   13 +-
+ drivers/iio/gyro/st_gyro_i2c.c                     |    3 +-
+ drivers/iio/gyro/st_gyro_spi.c                     |    3 +-
+ drivers/iio/iio_core_trigger.h                     |    7 +-
+ drivers/iio/imu/Kconfig                            |    2 +
+ drivers/iio/imu/Makefile                           |    1 +
+ drivers/iio/imu/adis16400_core.c                   |   10 +-
+ drivers/iio/imu/adis16480.c                        |   10 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_core.c         |   29 +-
+ drivers/iio/industrialio-core.c                    |   51 +-
+ drivers/iio/light/Kconfig                          |   34 +-
+ drivers/iio/light/Makefile                         |    4 +-
+ drivers/iio/light/adjd_s311.c                      |   15 +-
+ drivers/iio/light/apds9300.c                       |  512 ++
+ drivers/iio/light/hid-sensor-als.c                 |   33 +-
+ drivers/iio/light/lm3533-als.c                     |    7 +-
+ drivers/iio/light/tsl2563.c                        |   25 +-
+ drivers/iio/light/vcnl4000.c                       |   16 +-
+ drivers/iio/magnetometer/Kconfig                   |    6 +-
+ drivers/iio/magnetometer/Makefile                  |    1 +
+ drivers/iio/magnetometer/hid-sensor-magn-3d.c      |   35 +-
+ drivers/iio/magnetometer/st_magn.h                 |    3 +-
+ drivers/iio/magnetometer/st_magn_core.c            |    6 +-
+ drivers/iio/magnetometer/st_magn_i2c.c             |   17 +-
+ drivers/iio/magnetometer/st_magn_spi.c             |   17 +-
+ drivers/iio/pressure/Kconfig                       |   14 +-
+ drivers/iio/pressure/Makefile                      |    1 +
+ drivers/iio/pressure/st_pressure.h                 |   11 +-
+ drivers/iio/pressure/st_pressure_core.c            |   21 +-
+ drivers/iio/pressure/st_pressure_i2c.c             |   17 +-
+ drivers/iio/pressure/st_pressure_spi.c             |   17 +-
+ drivers/iio/trigger/Kconfig                        |    4 +-
+ drivers/iio/trigger/Makefile                       |    1 +
+ drivers/staging/Kconfig                            |    6 +-
+ drivers/staging/Makefile                           |    3 +-
+ drivers/staging/android/binder.c                   |   32 +-
+ drivers/staging/android/binder.h                   |   48 +-
+ drivers/staging/asus_oled/Kconfig                  |    6 -
+ drivers/staging/asus_oled/Makefile                 |    1 -
+ drivers/staging/asus_oled/README                   |  156 -
+ drivers/staging/asus_oled/TODO                     |   10 -
+ drivers/staging/asus_oled/asus_oled.c              |  847 ---
+ drivers/staging/asus_oled/linux.txt                |   33 -
+ drivers/staging/asus_oled/linux_f.txt              |   18 -
+ drivers/staging/asus_oled/linux_fr.txt             |   33 -
+ drivers/staging/asus_oled/tux.txt                  |   33 -
+ drivers/staging/asus_oled/tux_r.txt                |   33 -
+ drivers/staging/asus_oled/tux_r2.txt               |   33 -
+ drivers/staging/asus_oled/zig.txt                  |   33 -
+ drivers/staging/bcm/LeakyBucket.c                  |  262 +-
+ drivers/staging/bcm/Qos.c                          |  538 +-
+ drivers/staging/comedi/Kconfig                     |   44 +-
+ drivers/staging/comedi/comedi_buf.c                |    2 +
+ drivers/staging/comedi/comedi_fops.c               |    1 -
+ drivers/staging/comedi/comedi_internal.h           |    1 +
+ drivers/staging/comedi/comedidev.h                 |   18 +-
+ drivers/staging/comedi/drivers.c                   |   54 +-
+ drivers/staging/comedi/drivers/8255.c              |    3 +-
+ drivers/staging/comedi/drivers/8255_pci.c          |    4 +-
+ drivers/staging/comedi/drivers/Makefile            |    3 +-
+ .../comedi/drivers/addi-data/APCI1710_82x54.c      | 1068 ----
+ .../comedi/drivers/addi-data/APCI1710_Chrono.c     | 2050 --------
+ .../comedi/drivers/addi-data/APCI1710_Dig_io.c     | 1037 ----
+ .../comedi/drivers/addi-data/APCI1710_INCCPT.c     | 5461 --------------------
+ .../comedi/drivers/addi-data/APCI1710_Inp_cpt.c    |  866 ----
+ .../comedi/drivers/addi-data/APCI1710_Pwm.c        | 3582 -------------
+ .../comedi/drivers/addi-data/APCI1710_Ssi.c        |  845 ---
+ .../comedi/drivers/addi-data/APCI1710_Tor.c        | 2065 --------
+ .../comedi/drivers/addi-data/APCI1710_Ttl.c        | 1044 ----
+ .../staging/comedi/drivers/addi-data/addi_common.c |    3 +-
+ .../staging/comedi/drivers/addi-data/addi_common.h |  169 -
+ .../staging/comedi/drivers/addi-data/addi_eeprom.c |    2 +
+ .../comedi/drivers/addi-data/hwdrv_APCI1710.c      | 1314 -----
+ .../comedi/drivers/addi-data/hwdrv_apci3120.c      |    2 +
+ drivers/staging/comedi/drivers/addi_apci_035.c     |    1 +
+ drivers/staging/comedi/drivers/addi_apci_1032.c    |    4 +-
+ drivers/staging/comedi/drivers/addi_apci_1500.c    |    1 +
+ drivers/staging/comedi/drivers/addi_apci_1516.c    |    4 +-
+ drivers/staging/comedi/drivers/addi_apci_1564.c    |    1 +
+ drivers/staging/comedi/drivers/addi_apci_16xx.c    |    1 +
+ drivers/staging/comedi/drivers/addi_apci_1710.c    |   99 -
+ drivers/staging/comedi/drivers/addi_apci_2032.c    |    2 +
+ drivers/staging/comedi/drivers/addi_apci_2200.c    |    1 +
+ drivers/staging/comedi/drivers/addi_apci_3120.c    |    4 +-
+ drivers/staging/comedi/drivers/addi_apci_3200.c    |    1 +
+ drivers/staging/comedi/drivers/addi_apci_3501.c    |    4 +-
+ drivers/staging/comedi/drivers/addi_apci_3xxx.c    |    4 +-
+ drivers/staging/comedi/drivers/addi_watchdog.c     |    1 +
+ drivers/staging/comedi/drivers/adl_pci6208.c       |    4 +-
+ drivers/staging/comedi/drivers/adl_pci7x3x.c       |    1 +
+ drivers/staging/comedi/drivers/adl_pci8164.c       |    1 +
+ drivers/staging/comedi/drivers/adl_pci9111.c       |    4 +-
+ drivers/staging/comedi/drivers/adl_pci9118.c       |    7 +-
+ drivers/staging/comedi/drivers/adq12b.c            |    6 +-
+ drivers/staging/comedi/drivers/adv_pci1710.c       |    4 +-
+ drivers/staging/comedi/drivers/adv_pci1723.c       |    4 +-
+ drivers/staging/comedi/drivers/adv_pci1724.c       |   11 +-
+ drivers/staging/comedi/drivers/adv_pci_dio.c       |    4 +-
+ drivers/staging/comedi/drivers/aio_aio12_8.c       |    5 +-
+ drivers/staging/comedi/drivers/aio_iiro_16.c       |    2 +-
+ drivers/staging/comedi/drivers/amplc_dio200.c      |    6 +-
+ .../staging/comedi/drivers/amplc_dio200_common.c   |    2 +-
+ drivers/staging/comedi/drivers/amplc_dio200_pci.c  |    5 +-
+ drivers/staging/comedi/drivers/amplc_pc236.c       |    7 +-
+ drivers/staging/comedi/drivers/amplc_pc263.c       |    1 +
+ drivers/staging/comedi/drivers/amplc_pci224.c      |    7 +-
+ drivers/staging/comedi/drivers/amplc_pci230.c      |    4 +-
+ drivers/staging/comedi/drivers/amplc_pci263.c      |    1 +
+ drivers/staging/comedi/drivers/c6xdigio.c          |    2 -
+ drivers/staging/comedi/drivers/cb_das16_cs.c       |    5 +-
+ drivers/staging/comedi/drivers/cb_pcidas.c         |    4 +-
+ drivers/staging/comedi/drivers/cb_pcidas64.c       |    4 +-
+ drivers/staging/comedi/drivers/cb_pcidda.c         |    4 +-
+ drivers/staging/comedi/drivers/cb_pcimdas.c        |    5 +-
+ drivers/staging/comedi/drivers/cb_pcimdda.c        |    4 +-
+ drivers/staging/comedi/drivers/comedi_bond.c       |    4 +-
+ drivers/staging/comedi/drivers/comedi_fc.c         |    1 +
+ drivers/staging/comedi/drivers/comedi_parport.c    |    5 +-
+ drivers/staging/comedi/drivers/comedi_test.c       |    4 +-
+ drivers/staging/comedi/drivers/contec_pci_dio.c    |    1 +
+ drivers/staging/comedi/drivers/daqboard2000.c      |    4 +-
+ drivers/staging/comedi/drivers/das08.c             |    2 +-
+ drivers/staging/comedi/drivers/das08_cs.c          |    6 +-
+ drivers/staging/comedi/drivers/das08_isa.c         |    4 +-
+ drivers/staging/comedi/drivers/das08_pci.c         |    4 +-
+ drivers/staging/comedi/drivers/das16.c             | 2028 +++-----
+ drivers/staging/comedi/drivers/das16m1.c           |    5 +-
+ drivers/staging/comedi/drivers/das1800.c           |    5 +-
+ drivers/staging/comedi/drivers/das6402.c           |    6 +-
+ drivers/staging/comedi/drivers/das800.c            |    5 +-
+ drivers/staging/comedi/drivers/dmm32at.c           |    6 +-
+ drivers/staging/comedi/drivers/dt2801.c            |    5 +-
+ drivers/staging/comedi/drivers/dt2811.c            |    6 +-
+ drivers/staging/comedi/drivers/dt2814.c            |    5 +-
+ drivers/staging/comedi/drivers/dt2815.c            |    5 +-
+ drivers/staging/comedi/drivers/dt2817.c            |    3 +-
+ drivers/staging/comedi/drivers/dt282x.c            |    8 +-
+ drivers/staging/comedi/drivers/dt3000.c            |    4 +-
+ drivers/staging/comedi/drivers/dt9812.c            |   27 +-
+ drivers/staging/comedi/drivers/dyna_pci10xx.c      |    5 +-
+ drivers/staging/comedi/drivers/fl512.c             |    5 +-
+ drivers/staging/comedi/drivers/gsc_hpdi.c          |    4 +-
+ drivers/staging/comedi/drivers/icp_multi.c         |    4 +-
+ drivers/staging/comedi/drivers/ii_pci20kc.c        | 1004 ++--
+ drivers/staging/comedi/drivers/jr3_pci.c           |    4 +-
+ drivers/staging/comedi/drivers/ke_counter.c        |    1 +
+ drivers/staging/comedi/drivers/me4000.c            |    4 +-
+ drivers/staging/comedi/drivers/me_daq.c            |    4 +-
+ drivers/staging/comedi/drivers/mite.c              |    1 +
+ drivers/staging/comedi/drivers/mite.h              |    1 +
+ drivers/staging/comedi/drivers/mpc624.c            |    5 +-
+ drivers/staging/comedi/drivers/multiq3.c           |    6 +-
+ drivers/staging/comedi/drivers/ni_6527.c           |    4 +-
+ drivers/staging/comedi/drivers/ni_65xx.c           |    5 +-
+ drivers/staging/comedi/drivers/ni_660x.c           |    4 +-
+ drivers/staging/comedi/drivers/ni_670x.c           |    5 +-
+ drivers/staging/comedi/drivers/ni_at_a2150.c       |    7 +-
+ drivers/staging/comedi/drivers/ni_at_ao.c          |    6 +-
+ drivers/staging/comedi/drivers/ni_atmio.c          |    2 +-
+ drivers/staging/comedi/drivers/ni_atmio16d.c       |    6 +-
+ drivers/staging/comedi/drivers/ni_daq_700.c        |    4 +-
+ drivers/staging/comedi/drivers/ni_daq_dio24.c      |    1 +
+ drivers/staging/comedi/drivers/ni_labpc.c          |  283 +-
+ drivers/staging/comedi/drivers/ni_labpc_cs.c       |    5 +-
+ drivers/staging/comedi/drivers/ni_labpc_isadma.c   |  226 +
+ drivers/staging/comedi/drivers/ni_labpc_isadma.h   |   57 +
+ drivers/staging/comedi/drivers/ni_labpc_pci.c      |    5 +-
+ drivers/staging/comedi/drivers/ni_labpc_regs.h     |   75 +
+ drivers/staging/comedi/drivers/ni_mio_common.c     |    4 +-
+ drivers/staging/comedi/drivers/ni_mio_cs.c         |    1 +
+ drivers/staging/comedi/drivers/ni_pcidio.c         |    4 +-
+ drivers/staging/comedi/drivers/ni_pcimio.c         |    1 +
+ drivers/staging/comedi/drivers/ni_tio.c            |    3 +
+ drivers/staging/comedi/drivers/ni_tiocmd.c         |    1 +
+ drivers/staging/comedi/drivers/pcl711.c            |    5 +-
+ drivers/staging/comedi/drivers/pcl724.c            |   13 +-
+ drivers/staging/comedi/drivers/pcl726.c            |    6 +-
+ drivers/staging/comedi/drivers/pcl730.c            |    3 +-
+ drivers/staging/comedi/drivers/pcl812.c            |    5 +-
+ drivers/staging/comedi/drivers/pcl816.c            |    5 +-
+ drivers/staging/comedi/drivers/pcl818.c            |    5 +-
+ drivers/staging/comedi/drivers/pcm3724.c           |    7 +-
+ drivers/staging/comedi/drivers/pcmad.c             |    1 +
+ drivers/staging/comedi/drivers/pcmda12.c           |    4 +-
+ drivers/staging/comedi/drivers/pcmmio.c            |    4 +-
+ drivers/staging/comedi/drivers/pcmuio.c            |    4 +-
+ drivers/staging/comedi/drivers/poc.c               |    6 +-
+ drivers/staging/comedi/drivers/quatech_daqp_cs.c   |    4 +-
+ drivers/staging/comedi/drivers/rtd520.c            |    4 +-
+ drivers/staging/comedi/drivers/rti800.c            |    7 +-
+ drivers/staging/comedi/drivers/rti802.c            |    6 +-
+ drivers/staging/comedi/drivers/s526.c              |    5 +-
+ drivers/staging/comedi/drivers/s626.c              |    5 +-
+ drivers/staging/comedi/drivers/s626.h              |    2 -
+ drivers/staging/comedi/drivers/serial2002.c        |    5 +-
+ drivers/staging/comedi/drivers/skel.c              |    7 +-
+ drivers/staging/comedi/drivers/ssv_dnp.c           |    1 +
+ drivers/staging/comedi/drivers/unioxx5.c           |    4 +-
+ drivers/staging/comedi/drivers/usbdux.c            | 2476 ++++-----
+ drivers/staging/comedi/drivers/usbduxfast.c        |    3 +-
+ drivers/staging/comedi/drivers/usbduxsigma.c       |  297 +-
+ drivers/staging/comedi/drivers/vmk80xx.c           |    3 +-
+ .../staging/comedi/kcomedilib/kcomedilib_main.c    |    2 -
+ drivers/staging/comedi/proc.c                      |    2 +
+ drivers/staging/comedi/range.c                     |   43 +-
+ drivers/staging/dgnc/Kconfig                       |    6 +
+ drivers/staging/dgnc/Makefile                      |    7 +
+ drivers/staging/dgnc/Makefile.inc                  |  133 +
+ drivers/staging/dgnc/dgnc_cls.c                    | 1411 +++++
+ drivers/staging/dgnc/dgnc_cls.h                    |   90 +
+ drivers/staging/dgnc/dgnc_driver.c                 | 1028 ++++
+ drivers/staging/dgnc/dgnc_driver.h                 |  565 ++
+ drivers/staging/dgnc/dgnc_kcompat.h                |   93 +
+ drivers/staging/dgnc/dgnc_mgmt.c                   |  312 ++
+ drivers/staging/dgnc/dgnc_mgmt.h                   |   37 +
+ drivers/staging/dgnc/dgnc_neo.c                    | 1976 +++++++
+ drivers/staging/dgnc/dgnc_neo.h                    |  157 +
+ drivers/staging/dgnc/dgnc_pci.h                    |   77 +
+ drivers/staging/dgnc/dgnc_proc.c                   | 1550 ++++++
+ drivers/staging/dgnc/dgnc_proc.h                   |  147 +
+ drivers/staging/dgnc/dgnc_sysfs.c                  |  760 +++
+ drivers/staging/dgnc/dgnc_sysfs.h                  |   49 +
+ drivers/staging/dgnc/dgnc_trace.c                  |  186 +
+ drivers/staging/dgnc/dgnc_trace.h                  |   45 +
+ drivers/staging/dgnc/dgnc_tty.c                    | 3648 +++++++++++++
+ drivers/staging/dgnc/dgnc_tty.h                    |   42 +
+ drivers/staging/dgnc/dgnc_types.h                  |   36 +
+ drivers/staging/dgnc/digi.h                        |  419 ++
+ drivers/staging/dgnc/dpacompat.h                   |  115 +
+ drivers/staging/dwc2/Kconfig                       |    1 -
+ drivers/staging/dwc2/core.c                        |   51 +-
+ drivers/staging/dwc2/core.h                        |   13 +-
+ drivers/staging/dwc2/hcd.c                         |  133 +-
+ drivers/staging/dwc2/hcd.h                         |    4 +-
+ drivers/staging/dwc2/hcd_ddma.c                    |   23 +-
+ drivers/staging/dwc2/hcd_intr.c                    |   86 +-
+ drivers/staging/dwc2/hcd_queue.c                   |   20 +-
+ drivers/staging/dwc2/hw.h                          |    4 +
+ drivers/staging/dwc2/pci.c                         |    2 +-
+ drivers/staging/gdm724x/Kconfig                    |   15 +
+ drivers/staging/gdm724x/Makefile                   |    7 +
+ drivers/staging/gdm724x/TODO                       |   16 +
+ drivers/staging/gdm724x/gdm_endian.c               |   67 +
+ drivers/staging/gdm724x/gdm_endian.h               |   49 +
+ drivers/staging/gdm724x/gdm_lte.c                  |  877 ++++
+ drivers/staging/gdm724x/gdm_lte.h                  |   81 +
+ drivers/staging/gdm724x/gdm_mux.c                  |  698 +++
+ drivers/staging/gdm724x/gdm_mux.h                  |   87 +
+ drivers/staging/gdm724x/gdm_tty.c                  |  366 ++
+ drivers/staging/gdm724x/gdm_tty.h                  |   59 +
+ drivers/staging/gdm724x/gdm_usb.c                  | 1049 ++++
+ drivers/staging/gdm724x/gdm_usb.h                  |  109 +
+ drivers/staging/gdm724x/hci.h                      |   55 +
+ drivers/staging/gdm724x/hci_packet.h               |   93 +
+ drivers/staging/gdm724x/netlink_k.c                |  163 +
+ drivers/staging/gdm724x/netlink_k.h                |   25 +
+ drivers/staging/iio/Documentation/device.txt       |    4 +-
+ drivers/staging/iio/adc/mxs-lradc.c                |   33 +-
+ drivers/staging/iio/adc/spear_adc.c                |   30 +-
+ drivers/staging/iio/addac/adt7316.c                |   27 -
+ drivers/staging/iio/gyro/Kconfig                   |   12 -
+ drivers/staging/iio/gyro/Makefile                  |    3 -
+ drivers/staging/iio/gyro/adis16260.h               |   98 -
+ drivers/staging/iio/gyro/adis16260_platform_data.h |   19 -
+ drivers/staging/iio/light/isl29018.c               |   16 +-
+ drivers/staging/iio/light/isl29028.c               |   13 +-
+ drivers/staging/iio/magnetometer/hmc5843.c         |   71 +-
+ drivers/staging/iio/meter/ade7753.c                |   18 -
+ drivers/staging/iio/meter/ade7754.c                |   19 -
+ drivers/staging/iio/meter/ade7758_core.c           |   18 -
+ drivers/staging/iio/meter/ade7758_ring.c           |    2 +-
+ drivers/staging/iio/meter/ade7759.c                |   18 -
+ drivers/staging/iio/meter/ade7854.c                |   19 -
+ drivers/staging/iio/resolver/ad2s1210.c            |   18 -
+ drivers/staging/imx-drm/Kconfig                    |    4 +-
+ drivers/staging/imx-drm/TODO                       |    1 -
+ drivers/staging/imx-drm/imx-drm-core.c             |   21 +-
+ drivers/staging/imx-drm/imx-ldb.c                  |    2 +-
+ drivers/staging/imx-drm/imx-tve.c                  |    7 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        |   17 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-dp.c            |   13 +-
+ drivers/staging/lustre/Makefile                    |    2 +-
+ .../staging/lustre/include/linux/libcfs/bitmap.h   |    4 +-
+ .../staging/lustre/include/linux/libcfs/curproc.h  |    2 -
+ .../staging/lustre/include/linux/libcfs/libcfs.h   |   46 -
+ .../lustre/include/linux/libcfs/libcfs_cpu.h       |   46 +-
+ .../lustre/include/linux/libcfs/libcfs_debug.h     |   68 -
+ .../lustre/include/linux/libcfs/libcfs_prim.h      |   24 +-
+ .../lustre/include/linux/libcfs/libcfs_private.h   |    5 -
+ .../lustre/include/linux/libcfs/linux/kp30.h       |   49 -
+ .../lustre/include/linux/libcfs/linux/libcfs.h     |    3 -
+ .../lustre/include/linux/libcfs/linux/linux-cpu.h  |    9 -
+ .../lustre/include/linux/libcfs/linux/linux-mem.h  |    4 +-
+ .../lustre/include/linux/libcfs/linux/linux-prim.h |  158 -
+ .../include/linux/libcfs/linux/linux-tcpip.h       |   15 -
+ .../lustre/include/linux/libcfs/linux/linux-time.h |    1 -
+ .../include/linux/libcfs/linux/portals_compat25.h  |   15 -
+ .../staging/lustre/include/linux/libcfs/lucache.h  |    2 +-
+ .../lustre/include/linux/libcfs/params_tree.h      |    4 +-
+ drivers/staging/lustre/lnet/Makefile               |    2 +-
+ .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c    |   10 +-
+ .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h    |    1 -
+ .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c |   14 +-
+ .../lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c  |    2 +-
+ .../staging/lustre/lnet/klnds/socklnd/socklnd.c    |   54 +-
+ .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c |  108 +-
+ .../lustre/lnet/klnds/socklnd/socklnd_lib-linux.c  |   11 +-
+ .../lustre/lnet/klnds/socklnd/socklnd_lib-linux.h  |    3 -
+ .../lustre/lnet/klnds/socklnd/socklnd_proto.c      |   60 +-
+ drivers/staging/lustre/lnet/lnet/Makefile          |    2 +-
+ drivers/staging/lustre/lnet/lnet/acceptor.c        |   62 +-
+ drivers/staging/lustre/lnet/lnet/api-errno.c       |   39 -
+ drivers/staging/lustre/lnet/lnet/api-ni.c          |    7 +-
+ drivers/staging/lustre/lnet/lnet/lib-eq.c          |   14 +-
+ drivers/staging/lustre/lnet/lnet/lib-msg.c         |    3 -
+ drivers/staging/lustre/lnet/lnet/module.c          |    9 +-
+ drivers/staging/lustre/lnet/lnet/router_proc.c     |    2 +-
+ drivers/staging/lustre/lnet/selftest/console.c     |    2 +-
+ drivers/staging/lustre/lnet/selftest/module.c      |    4 +-
+ drivers/staging/lustre/lnet/selftest/rpc.c         |    4 +-
+ drivers/staging/lustre/lnet/selftest/timer.c       |    2 +-
+ drivers/staging/lustre/lustre/Kconfig              |   13 +-
+ drivers/staging/lustre/lustre/Makefile             |    4 +-
+ drivers/staging/lustre/lustre/fid/Makefile         |    2 +-
+ drivers/staging/lustre/lustre/fid/fid_handler.c    |  661 ---
+ drivers/staging/lustre/lustre/fid/fid_internal.h   |   36 +-
+ drivers/staging/lustre/lustre/fid/fid_lib.c        |   14 +-
+ drivers/staging/lustre/lustre/fid/fid_request.c    |  164 +-
+ drivers/staging/lustre/lustre/fid/fid_store.c      |  259 -
+ drivers/staging/lustre/lustre/fid/lproc_fid.c      |   28 +-
+ drivers/staging/lustre/lustre/fld/Makefile         |    2 +-
+ drivers/staging/lustre/lustre/fld/fld_cache.c      |   45 +-
+ drivers/staging/lustre/lustre/fld/fld_handler.c    |  447 --
+ drivers/staging/lustre/lustre/fld/fld_index.c      |  426 --
+ drivers/staging/lustre/lustre/fld/fld_internal.h   |   31 +-
+ drivers/staging/lustre/lustre/fld/fld_request.c    |   90 +-
+ drivers/staging/lustre/lustre/fld/lproc_fld.c      |  217 +-
+ drivers/staging/lustre/lustre/include/cl_object.h  |   18 +-
+ .../lustre/lustre/include/linux/lprocfs_status.h   |    1 -
+ .../lustre/lustre/include/linux/lustre_compat25.h  |  103 -
+ .../lustre/lustre/include/linux/lustre_fsfilt.h    |   12 +-
+ .../lustre/lustre/include/linux/lustre_handles.h   |    1 -
+ .../lustre/lustre/include/linux/lustre_lite.h      |    2 -
+ .../lustre/lustre/include/linux/lustre_net.h       |    1 -
+ .../lustre/include/linux/lustre_patchless_compat.h |    2 +-
+ .../lustre/lustre/include/linux/lustre_quota.h     |    1 -
+ .../lustre/lustre/include/linux/lustre_user.h      |   19 +-
+ drivers/staging/lustre/lustre/include/linux/lvfs.h |    8 +-
+ drivers/staging/lustre/lustre/include/linux/obd.h  |    5 +-
+ .../staging/lustre/lustre/include/lprocfs_status.h |   73 +-
+ drivers/staging/lustre/lustre/include/lu_object.h  |   25 +-
+ drivers/staging/lustre/lustre/include/lu_ref.h     |   14 +-
+ .../lustre/lustre/include/lustre/lustre_errno.h    |  215 +
+ .../lustre/lustre/include/lustre/lustre_idl.h      |   82 +-
+ .../lustre/lustre/include/lustre/lustre_user.h     |   12 +
+ drivers/staging/lustre/lustre/include/lustre_cfg.h |   30 +-
+ .../staging/lustre/lustre/include/lustre_disk.h    |   56 +-
+ drivers/staging/lustre/lustre/include/lustre_dlm.h |  204 +-
+ .../lustre/lustre/include/lustre_dlm_flags.h       |  460 ++
+ drivers/staging/lustre/lustre/include/lustre_fid.h |  125 +-
+ drivers/staging/lustre/lustre/include/lustre_fld.h |   45 +-
+ .../staging/lustre/lustre/include/lustre_idmap.h   |    4 +-
+ .../staging/lustre/lustre/include/lustre_import.h  |    2 +
+ drivers/staging/lustre/lustre/include/lustre_lib.h |    5 +-
+ drivers/staging/lustre/lustre/include/lustre_log.h |   32 +-
+ drivers/staging/lustre/lustre/include/lustre_mdc.h |   12 +-
+ drivers/staging/lustre/lustre/include/lustre_mdt.h |   84 -
+ drivers/staging/lustre/lustre/include/lustre_net.h |   47 +-
+ .../staging/lustre/lustre/include/lustre_quota.h   |    2 +-
+ drivers/staging/lustre/lustre/include/lustre_sec.h |    2 +-
+ drivers/staging/lustre/lustre/include/md_object.h  |    7 +-
+ drivers/staging/lustre/lustre/include/obd.h        |  185 +-
+ drivers/staging/lustre/lustre/include/obd_class.h  |  392 +-
+ drivers/staging/lustre/lustre/include/obd_lov.h    |   10 -
+ .../staging/lustre/lustre/include/obd_support.h    |    1 +
+ drivers/staging/lustre/lustre/lclient/glimpse.c    |   19 +-
+ drivers/staging/lustre/lustre/lclient/lcommon_cl.c |   43 +-
+ .../staging/lustre/lustre/lclient/lcommon_misc.c   |    8 +-
+ drivers/staging/lustre/lustre/ldlm/interval_tree.c |   50 +-
+ drivers/staging/lustre/lustre/ldlm/l_lock.c        |    8 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_extent.c   |   10 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_flock.c    |   66 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_internal.h |   49 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_lib.c      |   79 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_lock.c     |  394 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c    |  120 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_pool.c     |  137 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_request.c  |  181 +-
+ drivers/staging/lustre/lustre/ldlm/ldlm_resource.c |   95 +-
+ drivers/staging/lustre/lustre/libcfs/Makefile      |    2 +-
+ drivers/staging/lustre/lustre/libcfs/debug.c       |   19 +-
+ drivers/staging/lustre/lustre/libcfs/hash.c        |   24 +-
+ .../lustre/lustre/libcfs/kernel_user_comm.c        |   15 +-
+ drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c  |    3 -
+ drivers/staging/lustre/lustre/libcfs/libcfs_lock.c |    3 -
+ drivers/staging/lustre/lustre/libcfs/libcfs_mem.c  |    3 -
+ .../staging/lustre/lustre/libcfs/libcfs_string.c   |   49 -
+ .../staging/lustre/lustre/libcfs/linux/linux-cpu.c |   46 +-
+ .../lustre/lustre/libcfs/linux/linux-crypto.c      |    2 +
+ .../lustre/lustre/libcfs/linux/linux-curproc.c     |   21 +-
+ .../lustre/lustre/libcfs/linux/linux-debug.c       |   69 +-
+ .../lustre/lustre/libcfs/linux/linux-module.c      |   31 +-
+ .../lustre/lustre/libcfs/linux/linux-prim.c        |   21 +-
+ .../lustre/lustre/libcfs/linux/linux-proc.c        |    4 +-
+ .../lustre/lustre/libcfs/linux/linux-tcpip.c       |    5 +-
+ .../lustre/lustre/libcfs/linux/linux-tracefile.c   |   16 +-
+ drivers/staging/lustre/lustre/libcfs/module.c      |   28 +-
+ drivers/staging/lustre/lustre/libcfs/nidstrings.c  |   14 +-
+ drivers/staging/lustre/lustre/libcfs/tracefile.c   |    8 +-
+ .../staging/lustre/lustre/libcfs/upcall_cache.c    |   22 +-
+ drivers/staging/lustre/lustre/libcfs/watchdog.c    |  516 --
+ drivers/staging/lustre/lustre/libcfs/workitem.c    |    3 +-
+ drivers/staging/lustre/lustre/llite/Makefile       |    2 +-
+ drivers/staging/lustre/lustre/llite/dcache.c       |   80 +-
+ drivers/staging/lustre/lustre/llite/dir.c          |  251 +-
+ drivers/staging/lustre/lustre/llite/file.c         |  454 +-
+ drivers/staging/lustre/lustre/llite/llite_capa.c   |   26 +-
+ drivers/staging/lustre/lustre/llite/llite_close.c  |   23 +-
+ .../staging/lustre/lustre/llite/llite_internal.h   |   32 +-
+ drivers/staging/lustre/lustre/llite/llite_lib.c    |  172 +-
+ drivers/staging/lustre/lustre/llite/llite_mmap.c   |   67 +-
+ drivers/staging/lustre/lustre/llite/llite_nfs.c    |   76 +-
+ drivers/staging/lustre/lustre/llite/lloop.c        |   15 +-
+ drivers/staging/lustre/lustre/llite/lproc_llite.c  |   38 +-
+ drivers/staging/lustre/lustre/llite/namei.c        |   97 +-
+ drivers/staging/lustre/lustre/llite/remote_perm.c  |   27 +-
+ drivers/staging/lustre/lustre/llite/rw.c           |   44 +-
+ drivers/staging/lustre/lustre/llite/rw26.c         |   35 +-
+ drivers/staging/lustre/lustre/llite/statahead.c    |   88 +-
+ drivers/staging/lustre/lustre/llite/super25.c      |    3 +-
+ drivers/staging/lustre/lustre/llite/symlink.c      |   16 +-
+ drivers/staging/lustre/lustre/llite/vvp_dev.c      |    5 +-
+ drivers/staging/lustre/lustre/llite/vvp_io.c       |   59 +-
+ drivers/staging/lustre/lustre/llite/vvp_lock.c     |    3 +-
+ drivers/staging/lustre/lustre/llite/vvp_object.c   |    8 +-
+ drivers/staging/lustre/lustre/llite/vvp_page.c     |   10 +-
+ drivers/staging/lustre/lustre/llite/xattr.c        |   48 +-
+ drivers/staging/lustre/lustre/lmv/lmv_fld.c        |    7 +-
+ drivers/staging/lustre/lustre/lmv/lmv_intent.c     |   38 +-
+ drivers/staging/lustre/lustre/lmv/lmv_obd.c        |  634 ++-
+ drivers/staging/lustre/lustre/lmv/lproc_lmv.c      |    1 -
+ .../staging/lustre/lustre/lov/lov_cl_internal.h    |   13 +-
+ drivers/staging/lustre/lustre/lov/lov_dev.c        |   33 +-
+ drivers/staging/lustre/lustre/lov/lov_ea.c         |   23 +-
+ drivers/staging/lustre/lustre/lov/lov_io.c         |  111 +-
+ drivers/staging/lustre/lustre/lov/lov_lock.c       |   69 +-
+ drivers/staging/lustre/lustre/lov/lov_log.c        |   16 +-
+ drivers/staging/lustre/lustre/lov/lov_merge.c      |   10 +-
+ drivers/staging/lustre/lustre/lov/lov_obd.c        |  300 +-
+ drivers/staging/lustre/lustre/lov/lov_object.c     |  112 +-
+ drivers/staging/lustre/lustre/lov/lov_offset.c     |    5 +-
+ drivers/staging/lustre/lustre/lov/lov_pack.c       |   82 +-
+ drivers/staging/lustre/lustre/lov/lov_page.c       |   13 +-
+ drivers/staging/lustre/lustre/lov/lov_pool.c       |   40 +-
+ drivers/staging/lustre/lustre/lov/lov_request.c    |  157 +-
+ drivers/staging/lustre/lustre/lov/lovsub_dev.c     |   12 +-
+ drivers/staging/lustre/lustre/lov/lovsub_lock.c    |   31 +-
+ drivers/staging/lustre/lustre/lov/lovsub_object.c  |   14 +-
+ drivers/staging/lustre/lustre/lov/lovsub_page.c    |    3 +-
+ drivers/staging/lustre/lustre/lov/lproc_lov.c      |    1 -
+ drivers/staging/lustre/lustre/lvfs/fsfilt.c        |    5 +-
+ drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c   |    1 -
+ drivers/staging/lustre/lustre/lvfs/lvfs_linux.c    |   15 +-
+ drivers/staging/lustre/lustre/mdc/lproc_mdc.c      |   10 +-
+ drivers/staging/lustre/lustre/mdc/mdc_lib.c        |   29 +-
+ drivers/staging/lustre/lustre/mdc/mdc_locks.c      |  151 +-
+ drivers/staging/lustre/lustre/mdc/mdc_reint.c      |   46 +-
+ drivers/staging/lustre/lustre/mdc/mdc_request.c    |  324 +-
+ drivers/staging/lustre/lustre/mgc/libmgc.c         |   19 +-
+ drivers/staging/lustre/lustre/mgc/lproc_mgc.c      |    1 -
+ drivers/staging/lustre/lustre/mgc/mgc_request.c    |  169 +-
+ drivers/staging/lustre/lustre/obdclass/Makefile    |    2 +-
+ drivers/staging/lustre/lustre/obdclass/acl.c       |   29 +-
+ drivers/staging/lustre/lustre/obdclass/capa.c      |   61 +-
+ drivers/staging/lustre/lustre/obdclass/cl_io.c     |  152 +-
+ drivers/staging/lustre/lustre/obdclass/cl_lock.c   |  144 +-
+ drivers/staging/lustre/lustre/obdclass/cl_object.c |   21 +-
+ drivers/staging/lustre/lustre/obdclass/cl_page.c   |  108 +-
+ drivers/staging/lustre/lustre/obdclass/class_obd.c |   35 +-
+ drivers/staging/lustre/lustre/obdclass/dt_object.c |   28 +-
+ drivers/staging/lustre/lustre/obdclass/genops.c    |   79 +-
+ drivers/staging/lustre/lustre/obdclass/idmap.c     |   21 +-
+ .../lustre/lustre/obdclass/linux/linux-module.c    |   48 +-
+ .../lustre/lustre/obdclass/linux/linux-obdo.c      |    4 +-
+ .../lustre/lustre/obdclass/linux/linux-sysctl.c    |   10 +-
+ drivers/staging/lustre/lustre/obdclass/llog.c      |  124 +-
+ drivers/staging/lustre/lustre/obdclass/llog_cat.c  |   92 +-
+ .../staging/lustre/lustre/obdclass/llog_ioctl.c    |   79 +-
+ drivers/staging/lustre/lustre/obdclass/llog_lvfs.c |   99 +-
+ drivers/staging/lustre/lustre/obdclass/llog_obd.c  |   37 +-
+ drivers/staging/lustre/lustre/obdclass/llog_osd.c  |  121 +-
+ drivers/staging/lustre/lustre/obdclass/llog_swab.c |   28 +-
+ drivers/staging/lustre/lustre/obdclass/llog_test.c |   89 +-
+ .../staging/lustre/lustre/obdclass/local_storage.c |   46 +-
+ .../lustre/lustre/obdclass/lprocfs_jobstats.c      |  562 --
+ .../lustre/lustre/obdclass/lprocfs_status.c        |   61 +-
+ drivers/staging/lustre/lustre/obdclass/lu_object.c |   46 +-
+ drivers/staging/lustre/lustre/obdclass/lu_ucred.c  |    8 +-
+ .../lustre/lustre/obdclass/lustre_handles.c        |    8 +-
+ .../staging/lustre/lustre/obdclass/lustre_peer.c   |    3 +-
+ drivers/staging/lustre/lustre/obdclass/md_attrs.c  |   17 +-
+ .../staging/lustre/lustre/obdclass/obd_config.c    |  148 +-
+ drivers/staging/lustre/lustre/obdclass/obd_mount.c |  134 +-
+ drivers/staging/lustre/lustre/obdclass/obdo.c      |   16 +-
+ drivers/staging/lustre/lustre/obdecho/echo.c       |   47 +-
+ .../staging/lustre/lustre/obdecho/echo_client.c    |  248 +-
+ drivers/staging/lustre/lustre/osc/lproc_osc.c      |    3 +-
+ drivers/staging/lustre/lustre/osc/osc_cache.c      |  141 +-
+ .../staging/lustre/lustre/osc/osc_cl_internal.h    |    4 +-
+ drivers/staging/lustre/lustre/osc/osc_dev.c        |   11 +-
+ drivers/staging/lustre/lustre/osc/osc_io.c         |   28 +-
+ drivers/staging/lustre/lustre/osc/osc_lock.c       |  146 +-
+ drivers/staging/lustre/lustre/osc/osc_object.c     |    3 +-
+ drivers/staging/lustre/lustre/osc/osc_page.c       |   28 +-
+ drivers/staging/lustre/lustre/osc/osc_quota.c      |   31 +-
+ drivers/staging/lustre/lustre/osc/osc_request.c    |  326 +-
+ drivers/staging/lustre/lustre/ptlrpc/Makefile      |    1 +
+ drivers/staging/lustre/lustre/ptlrpc/client.c      |  161 +-
+ drivers/staging/lustre/lustre/ptlrpc/connection.c  |   24 +-
+ drivers/staging/lustre/lustre/ptlrpc/errno.c       |  380 ++
+ drivers/staging/lustre/lustre/ptlrpc/events.c      |   12 -
+ drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h |    2 +-
+ .../staging/lustre/lustre/ptlrpc/gss/gss_bulk.c    |   54 +-
+ .../lustre/lustre/ptlrpc/gss/gss_cli_upcall.c      |   27 +-
+ .../staging/lustre/lustre/ptlrpc/gss/gss_keyring.c |   47 +-
+ .../lustre/lustre/ptlrpc/gss/gss_krb5_mech.c       |  124 +-
+ .../staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c  |   53 +-
+ .../staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c  |    2 +-
+ .../lustre/lustre/ptlrpc/gss/gss_svc_upcall.c      |   12 +-
+ .../staging/lustre/lustre/ptlrpc/gss/lproc_gss.c   |    6 +-
+ drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c |  219 +-
+ drivers/staging/lustre/lustre/ptlrpc/import.c      |   61 +-
+ drivers/staging/lustre/lustre/ptlrpc/llog_client.c |   11 +-
+ drivers/staging/lustre/lustre/ptlrpc/llog_net.c    |    3 +-
+ drivers/staging/lustre/lustre/ptlrpc/llog_server.c |   46 +-
+ .../staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c    |   15 +-
+ drivers/staging/lustre/lustre/ptlrpc/niobuf.c      |   38 +-
+ drivers/staging/lustre/lustre/ptlrpc/nrs.c         |  105 +-
+ .../staging/lustre/lustre/ptlrpc/pack_generic.c    |   34 +-
+ drivers/staging/lustre/lustre/ptlrpc/pinger.c      |   82 +-
+ .../staging/lustre/lustre/ptlrpc/ptlrpc_module.c   |   11 +-
+ drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c     |   37 +-
+ drivers/staging/lustre/lustre/ptlrpc/recover.c     |   23 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec.c         |  123 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c    |    4 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec_config.c  |   47 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec_gc.c      |    2 +-
+ drivers/staging/lustre/lustre/ptlrpc/sec_plain.c   |   90 +-
+ drivers/staging/lustre/lustre/ptlrpc/service.c     |  170 +-
+ drivers/staging/nvec/nvec.c                        |    5 -
+ drivers/staging/octeon-usb/Kconfig                 |    2 +-
+ drivers/staging/octeon-usb/cvmx-usb.c              | 5339 ++++++++++---------
+ drivers/staging/octeon-usb/cvmx-usb.h              | 1157 ++---
+ drivers/staging/octeon-usb/cvmx-usbcx-defs.h       |   23 -
+ drivers/staging/octeon-usb/cvmx-usbnx-defs.h       |    2 -
+ drivers/staging/octeon-usb/octeon-hcd.c            |   33 +-
+ drivers/staging/olpc_dcon/Kconfig                  |   11 +-
+ drivers/staging/olpc_dcon/TODO                     |    1 -
+ drivers/staging/olpc_dcon/olpc_dcon.c              |    4 +-
+ drivers/staging/ozwpan/{Kbuild => Makefile}        |    6 +-
+ drivers/staging/ozwpan/ozcdev.c                    |   67 +-
+ drivers/staging/ozwpan/ozconfig.h                  |   26 -
+ drivers/staging/ozwpan/ozdbg.h                     |   54 +
+ drivers/staging/ozwpan/ozeltbuf.c                  |   32 +-
+ drivers/staging/ozwpan/ozhcd.c                     |  365 +-
+ drivers/staging/ozwpan/ozmain.c                    |    7 +-
+ drivers/staging/ozwpan/ozpd.c                      |  107 +-
+ drivers/staging/ozwpan/ozpd.h                      |   20 +-
+ drivers/staging/ozwpan/ozproto.c                   |  434 +-
+ drivers/staging/ozwpan/ozproto.h                   |   30 +-
+ drivers/staging/ozwpan/oztrace.c                   |   36 -
+ drivers/staging/ozwpan/oztrace.h                   |   35 -
+ drivers/staging/ozwpan/ozurbparanoia.c             |   13 +-
+ drivers/staging/ozwpan/ozurbparanoia.h             |    4 +-
+ drivers/staging/ozwpan/ozusbsvc.c                  |   39 +-
+ drivers/staging/ozwpan/ozusbsvc1.c                 |   19 +-
+ drivers/staging/rtl8192e/rtllib_module.c           |    3 +-
+ .../staging/rtl8192u/ieee80211/ieee80211_module.c  |    3 +-
+ drivers/staging/rtl8192u/r819xU_cmdpkt.c           |  609 +--
+ drivers/staging/rtl8712/rtl871x_ioctl_linux.c      |    8 +-
+ drivers/staging/silicom/bpctl_mod.c                |  582 ++-
+ drivers/staging/usbip/userspace/src/usbipd.c       |   80 +-
+ drivers/staging/vt6655/device_main.c               |    4 +-
+ drivers/staging/vt6656/baseband.c                  |    1 -
+ drivers/staging/vt6656/device.h                    |    6 -
+ drivers/staging/vt6656/device_cfg.h                |   14 -
+ drivers/staging/vt6656/dpc.c                       |    6 -
+ drivers/staging/vt6656/main_usb.c                  |    2 -
+ drivers/staging/vt6656/rxtx.c                      |    7 -
+ drivers/staging/vt6656/usbpipe.c                   |    1 -
+ drivers/staging/vt6656/wmgr.c                      |    2 -
+ drivers/staging/winbond/wb35reg.c                  |   31 +-
+ drivers/staging/xgifb/XGI_main_26.c                |   12 +-
+ drivers/staging/xgifb/vb_init.c                    |   36 +-
+ drivers/staging/xgifb/vb_setmode.c                 |  333 +-
+ drivers/staging/xgifb/vb_setmode.h                 |    9 +-
+ drivers/staging/xillybus/Kconfig                   |   32 +
+ drivers/staging/xillybus/Makefile                  |    7 +
+ drivers/staging/xillybus/README                    |  403 ++
+ drivers/staging/xillybus/TODO                      |    5 +
+ drivers/staging/xillybus/xillybus.h                |  183 +
+ drivers/staging/xillybus/xillybus_core.c           | 2345 +++++++++
+ drivers/staging/xillybus/xillybus_of.c             |  212 +
+ drivers/staging/xillybus/xillybus_pcie.c           |  262 +
+ drivers/staging/zcache/ramster/tcp.c               |    3 +
+ drivers/staging/zram/zram_drv.c                    |   18 +-
+ drivers/staging/zsmalloc/zsmalloc-main.c           |    4 +-
+ include/linux/iio/common/st_sensors.h              |   14 +-
+ include/linux/iio/iio.h                            |   25 +
+ include/linux/iio/sysfs.h                          |    5 -
+ include/linux/platform_data/st_sensors_pdata.h     |   24 +
+ 662 files changed, 36585 insertions(+), 43205 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/iio/adc/nuvoton-nau7802.txt
+ create mode 100644 Documentation/devicetree/bindings/iio/light/apds9300.txt
+ create mode 100644 drivers/iio/adc/nau7802.c
+ rename drivers/{staging/iio/gyro/adis16260_core.c => iio/gyro/adis16260.c} (53%)
+ create mode 100644 drivers/iio/light/apds9300.c
+ delete mode 100644 drivers/staging/asus_oled/Kconfig
+ delete mode 100644 drivers/staging/asus_oled/Makefile
+ delete mode 100644 drivers/staging/asus_oled/README
+ delete mode 100644 drivers/staging/asus_oled/TODO
+ delete mode 100644 drivers/staging/asus_oled/asus_oled.c
+ delete mode 100644 drivers/staging/asus_oled/linux.txt
+ delete mode 100644 drivers/staging/asus_oled/linux_f.txt
+ delete mode 100644 drivers/staging/asus_oled/linux_fr.txt
+ delete mode 100644 drivers/staging/asus_oled/tux.txt
+ delete mode 100644 drivers/staging/asus_oled/tux_r.txt
+ delete mode 100644 drivers/staging/asus_oled/tux_r2.txt
+ delete mode 100644 drivers/staging/asus_oled/zig.txt
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi_apci_1710.c
+ create mode 100644 drivers/staging/comedi/drivers/ni_labpc_isadma.c
+ create mode 100644 drivers/staging/comedi/drivers/ni_labpc_isadma.h
+ create mode 100644 drivers/staging/comedi/drivers/ni_labpc_regs.h
+ create mode 100644 drivers/staging/dgnc/Kconfig
+ create mode 100644 drivers/staging/dgnc/Makefile
+ create mode 100644 drivers/staging/dgnc/Makefile.inc
+ create mode 100644 drivers/staging/dgnc/dgnc_cls.c
+ create mode 100644 drivers/staging/dgnc/dgnc_cls.h
+ create mode 100644 drivers/staging/dgnc/dgnc_driver.c
+ create mode 100644 drivers/staging/dgnc/dgnc_driver.h
+ create mode 100644 drivers/staging/dgnc/dgnc_kcompat.h
+ create mode 100644 drivers/staging/dgnc/dgnc_mgmt.c
+ create mode 100644 drivers/staging/dgnc/dgnc_mgmt.h
+ create mode 100644 drivers/staging/dgnc/dgnc_neo.c
+ create mode 100644 drivers/staging/dgnc/dgnc_neo.h
+ create mode 100644 drivers/staging/dgnc/dgnc_pci.h
+ create mode 100644 drivers/staging/dgnc/dgnc_proc.c
+ create mode 100644 drivers/staging/dgnc/dgnc_proc.h
+ create mode 100644 drivers/staging/dgnc/dgnc_sysfs.c
+ create mode 100644 drivers/staging/dgnc/dgnc_sysfs.h
+ create mode 100644 drivers/staging/dgnc/dgnc_trace.c
+ create mode 100644 drivers/staging/dgnc/dgnc_trace.h
+ create mode 100644 drivers/staging/dgnc/dgnc_tty.c
+ create mode 100644 drivers/staging/dgnc/dgnc_tty.h
+ create mode 100644 drivers/staging/dgnc/dgnc_types.h
+ create mode 100644 drivers/staging/dgnc/digi.h
+ create mode 100644 drivers/staging/dgnc/dpacompat.h
+ create mode 100644 drivers/staging/gdm724x/Kconfig
+ create mode 100644 drivers/staging/gdm724x/Makefile
+ create mode 100644 drivers/staging/gdm724x/TODO
+ create mode 100644 drivers/staging/gdm724x/gdm_endian.c
+ create mode 100644 drivers/staging/gdm724x/gdm_endian.h
+ create mode 100644 drivers/staging/gdm724x/gdm_lte.c
+ create mode 100644 drivers/staging/gdm724x/gdm_lte.h
+ create mode 100644 drivers/staging/gdm724x/gdm_mux.c
+ create mode 100644 drivers/staging/gdm724x/gdm_mux.h
+ create mode 100644 drivers/staging/gdm724x/gdm_tty.c
+ create mode 100644 drivers/staging/gdm724x/gdm_tty.h
+ create mode 100644 drivers/staging/gdm724x/gdm_usb.c
+ create mode 100644 drivers/staging/gdm724x/gdm_usb.h
+ create mode 100644 drivers/staging/gdm724x/hci.h
+ create mode 100644 drivers/staging/gdm724x/hci_packet.h
+ create mode 100644 drivers/staging/gdm724x/netlink_k.c
+ create mode 100644 drivers/staging/gdm724x/netlink_k.h
+ delete mode 100644 drivers/staging/iio/gyro/adis16260.h
+ delete mode 100644 drivers/staging/iio/gyro/adis16260_platform_data.h
+ delete mode 100644 drivers/staging/lustre/lnet/lnet/api-errno.c
+ delete mode 100644 drivers/staging/lustre/lustre/fid/fid_handler.c
+ delete mode 100644 drivers/staging/lustre/lustre/fid/fid_store.c
+ delete mode 100644 drivers/staging/lustre/lustre/fld/fld_handler.c
+ delete mode 100644 drivers/staging/lustre/lustre/fld/fld_index.c
+ create mode 100644 drivers/staging/lustre/lustre/include/lustre/lustre_errno.h
+ create mode 100644 drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
+ delete mode 100644 drivers/staging/lustre/lustre/include/lustre_mdt.h
+ delete mode 100644 drivers/staging/lustre/lustre/libcfs/watchdog.c
+ delete mode 100644 drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c
+ create mode 100644 drivers/staging/lustre/lustre/ptlrpc/errno.c
+ rename drivers/staging/ozwpan/{Kbuild => Makefile} (93%)
+ delete mode 100644 drivers/staging/ozwpan/ozconfig.h
+ create mode 100644 drivers/staging/ozwpan/ozdbg.h
+ delete mode 100644 drivers/staging/ozwpan/oztrace.c
+ delete mode 100644 drivers/staging/ozwpan/oztrace.h
+ create mode 100644 drivers/staging/xillybus/Kconfig
+ create mode 100644 drivers/staging/xillybus/Makefile
+ create mode 100644 drivers/staging/xillybus/README
+ create mode 100644 drivers/staging/xillybus/TODO
+ create mode 100644 drivers/staging/xillybus/xillybus.h
+ create mode 100644 drivers/staging/xillybus/xillybus_core.c
+ create mode 100644 drivers/staging/xillybus/xillybus_of.c
+ create mode 100644 drivers/staging/xillybus/xillybus_pcie.c
+ create mode 100644 include/linux/platform_data/st_sensors_pdata.h
+Merging char-misc/char-misc-next (d3b688c Tools: hv: check return value of system in hv_kvp_daemon)
+$ git merge --no-ff char-misc/char-misc-next
+Removing include/linux/usb/dwc3-omap.h
+Auto-merging drivers/usb/dwc3/dwc3-omap.c
+Auto-merging drivers/usb/dwc3/Kconfig
+Removing drivers/uio/uio_pdrv.c
+Auto-merging drivers/extcon/extcon-class.c
+Auto-merging Documentation/devicetree/bindings/extcon/extcon-palmas.txt
+Merge made by the 'recursive' strategy.
+ .../extcon/{extcon-twl.txt => extcon-palmas.txt}   |   6 +-
+ Documentation/devicetree/bindings/usb/omap-usb.txt |   5 +
+ drivers/char/pcmcia/synclink_cs.c                  |  26 ++--
+ drivers/extcon/Kconfig                             |   4 +
+ drivers/extcon/Makefile                            |   2 +
+ drivers/extcon/extcon-adc-jack.c                   |   3 +-
+ drivers/extcon/extcon-arizona.c                    |  25 ++--
+ drivers/extcon/extcon-class.c                      |   3 +-
+ drivers/extcon/extcon-gpio.c                       |   2 +-
+ drivers/extcon/extcon-palmas.c                     | 134 ++++++++++++++-------
+ drivers/extcon/of_extcon.c                         |  64 ++++++++++
+ drivers/fmc/fmc-chardev.c                          |   9 +-
+ drivers/hid/hid-hyperv.c                           |   1 -
+ drivers/hv/channel_mgmt.c                          |  75 ++++++++----
+ drivers/hv/hv_balloon.c                            |   5 +-
+ drivers/hv/hv_kvp.c                                |  26 +++-
+ drivers/hv/hv_snapshot.c                           |  18 +--
+ drivers/hv/hv_util.c                               |  22 +++-
+ drivers/hv/vmbus_drv.c                             |   1 -
+ drivers/misc/atmel-ssc.c                           |   8 --
+ drivers/misc/lkdtm.c                               |  63 +++++++++-
+ drivers/misc/mei/amthif.c                          |  14 ++-
+ drivers/misc/mei/bus.c                             |   4 +-
+ drivers/misc/mei/client.c                          |  15 +--
+ drivers/misc/mei/client.h                          |   9 +-
+ drivers/misc/mei/init.c                            |  11 +-
+ drivers/misc/mei/main.c                            |  22 ++--
+ drivers/misc/sram.c                                |   3 +-
+ drivers/net/hyperv/netvsc_drv.c                    |   2 -
+ drivers/scsi/storvsc_drv.c                         |   1 -
+ drivers/uio/Kconfig                                |   7 --
+ drivers/uio/Makefile                               |   1 -
+ drivers/uio/uio_pdrv.c                             | 113 -----------------
+ drivers/usb/dwc3/Kconfig                           |   1 +
+ drivers/usb/dwc3/dwc3-omap.c                       | 125 ++++++++++++++++---
+ drivers/video/hyperv_fb.c                          |   1 -
+ include/linux/extcon/of_extcon.h                   |  31 +++++
+ include/linux/hyperv.h                             |  31 ++---
+ include/linux/mfd/palmas.h                         |   8 +-
+ include/linux/usb/dwc3-omap.h                      |  30 -----
+ tools/hv/hv_kvp_daemon.c                           |  27 +++--
+ tools/hv/hv_vss_daemon.c                           |  42 +++++--
+ 42 files changed, 624 insertions(+), 376 deletions(-)
+ rename Documentation/devicetree/bindings/extcon/{extcon-twl.txt => extcon-palmas.txt} (67%)
+ create mode 100644 drivers/extcon/of_extcon.c
+ delete mode 100644 drivers/uio/uio_pdrv.c
+ create mode 100644 include/linux/extcon/of_extcon.h
+ delete mode 100644 include/linux/usb/dwc3-omap.h
+Merging scsi/for-next (959823b Merge branch 'fixes' into for-next)
+$ git merge --no-ff scsi/for-next
+Merge made by the 'recursive' strategy.
+ drivers/scsi/fnic/fnic.h                  |   2 +-
+ drivers/scsi/fnic/fnic_main.c             |  22 ++---
+ drivers/scsi/megaraid/megaraid_sas_base.c |  20 +++-
+ drivers/scsi/scsi.c                       |   3 +
+ drivers/scsi/sd.c                         | 149 +++++++++++++++---------------
+ drivers/scsi/st.c                         |  27 +++---
+ 6 files changed, 119 insertions(+), 104 deletions(-)
+Merging target-updates/for-next (ca40d24 iser-target: Ignore non TEXT + LOGOUT opcodes for discovery)
+$ git merge --no-ff target-updates/for-next
+Already up-to-date.
+Merging target-merge/for-next-merge (317ddd2 Linux 3.10-rc5)
+$ git merge --no-ff target-merge/for-next-merge
+Already up-to-date.
+Merging ibft/linux-next (935a9fe ibft: Fix finding IBFT ACPI table on UEFI)
+$ git merge --no-ff ibft/linux-next
+Already up-to-date.
+Merging isci/all (6734092 isci: add a couple __iomem annotations)
+$ git merge --no-ff isci/all
+Already up-to-date.
+Merging bcon/master (e284f34 netconsole: s/syslogd/cancd/ in documentation)
+$ git merge --no-ff bcon/master
+Resolved 'drivers/block/Kconfig' using previous resolution.
+Auto-merging kernel/printk/printk.c
+Auto-merging init/do_mounts.c
+Auto-merging include/linux/mount.h
+Auto-merging include/linux/console.h
+Auto-merging drivers/net/netconsole.c
+Auto-merging drivers/block/Makefile
+Auto-merging drivers/block/Kconfig
+CONFLICT (content): Merge conflict in drivers/block/Kconfig
+Auto-merging block/partitions/check.h
+Auto-merging block/partitions/check.c
+Auto-merging block/partitions/Makefile
+Auto-merging Documentation/networking/netconsole.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master ad92d15] Merge remote-tracking branch 'bcon/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/block/blockconsole.txt            |  94 ++++
+ Documentation/block/blockconsole/bcon_tail      |  82 ++++
+ Documentation/block/blockconsole/mkblockconsole |  29 ++
+ Documentation/networking/netconsole.txt         |  16 +-
+ block/partitions/Makefile                       |   1 +
+ block/partitions/blockconsole.c                 |  22 +
+ block/partitions/check.c                        |   3 +
+ block/partitions/check.h                        |   3 +
+ drivers/block/Kconfig                           |   6 +
+ drivers/block/Makefile                          |   1 +
+ drivers/block/blockconsole.c                    | 618 ++++++++++++++++++++++++
+ drivers/net/netconsole.c                        |   2 +-
+ include/linux/blockconsole.h                    |   7 +
+ include/linux/console.h                         |   1 +
+ include/linux/mount.h                           |   2 +-
+ init/do_mounts.c                                |   2 +-
+ kernel/printk/printk.c                          |   5 +-
+ 17 files changed, 885 insertions(+), 9 deletions(-)
+ create mode 100644 Documentation/block/blockconsole.txt
+ create mode 100755 Documentation/block/blockconsole/bcon_tail
+ create mode 100755 Documentation/block/blockconsole/mkblockconsole
+ create mode 100644 block/partitions/blockconsole.c
+ create mode 100644 drivers/block/blockconsole.c
+ create mode 100644 include/linux/blockconsole.h
+Merging tmem/linux-next (8f0d816 Linux 3.7-rc3)
+$ git merge --no-ff tmem/linux-next
+Already up-to-date.
+Merging writeback/writeback-for-next (8bb495e Linux 3.10)
+$ git merge --no-ff writeback/writeback-for-next
+Already up-to-date.
+Merging hwspinlock/linux-next (8b37fcf hwspinlock: add MAINTAINERS entries)
+$ git merge --no-ff hwspinlock/linux-next
+Already up-to-date.
+Merging pinctrl/for-next (0979714 Merge branch 'devel' into for-next)
+$ git merge --no-ff pinctrl/for-next
+Merge made by the 'recursive' strategy.
+ .../bindings/pinctrl/pinctrl-bindings.txt          |   41 +-
+ Documentation/pinctrl.txt                          |   91 +-
+ drivers/pinctrl/Kconfig                            |    2 +-
+ drivers/pinctrl/core.c                             |   55 +-
+ drivers/pinctrl/pinconf.c                          |   31 +-
+ drivers/pinctrl/pinctrl-at91.c                     |   16 +-
+ drivers/pinctrl/pinctrl-baytrail.c                 |   41 +-
+ drivers/pinctrl/pinctrl-imx.c                      |   37 +-
+ drivers/pinctrl/pinctrl-nomadik.c                  |  295 ----
+ drivers/pinctrl/pinctrl-rockchip.c                 |    7 +-
+ drivers/pinctrl/pinctrl-st.c                       |   16 +-
+ drivers/pinctrl/pinctrl-sunxi.c                    |   68 +-
+ drivers/pinctrl/pinctrl-sunxi.h                    |    2 +
+ drivers/pinctrl/pinctrl-u300.c                     |    3 -
+ drivers/pinctrl/sh-pfc/core.c                      |   99 +-
+ drivers/pinctrl/sh-pfc/core.h                      |   10 +-
+ drivers/pinctrl/sh-pfc/gpio.c                      |   45 +-
+ drivers/pinctrl/sh-pfc/pfc-r8a73a4.c               |  158 +-
+ drivers/pinctrl/sh-pfc/pfc-r8a7740.c               |   48 +-
+ drivers/pinctrl/sh-pfc/pfc-r8a7778.c               |   55 +-
+ drivers/pinctrl/sh-pfc/pfc-r8a7779.c               |  168 +-
+ drivers/pinctrl/sh-pfc/pfc-r8a7790.c               | 1724 ++++++++++++--------
+ drivers/pinctrl/sh-pfc/pfc-sh7203.c                |  202 ++-
+ drivers/pinctrl/sh-pfc/pfc-sh7264.c                |  246 ++-
+ drivers/pinctrl/sh-pfc/pfc-sh7269.c                |  285 ++--
+ drivers/pinctrl/sh-pfc/pfc-sh7372.c                |   57 +-
+ drivers/pinctrl/sh-pfc/pfc-sh73a0.c                |  172 +-
+ drivers/pinctrl/sh-pfc/pfc-sh7720.c                |  701 ++++----
+ drivers/pinctrl/sh-pfc/pfc-sh7722.c                |  747 ++++-----
+ drivers/pinctrl/sh-pfc/pfc-sh7723.c                |  381 +++--
+ drivers/pinctrl/sh-pfc/pfc-sh7724.c                | 1093 ++++++-------
+ drivers/pinctrl/sh-pfc/pfc-sh7734.c                |   60 +-
+ drivers/pinctrl/sh-pfc/pfc-sh7757.c                |  709 ++++----
+ drivers/pinctrl/sh-pfc/pfc-sh7785.c                |  700 ++++----
+ drivers/pinctrl/sh-pfc/pfc-sh7786.c                |  383 ++---
+ drivers/pinctrl/sh-pfc/pfc-shx3.c                  |  423 +++--
+ drivers/pinctrl/sh-pfc/pinctrl.c                   |   49 +-
+ drivers/pinctrl/sh-pfc/sh_pfc.h                    |  277 ++--
+ drivers/pinctrl/sirf/pinctrl-sirf.c                |   10 +-
+ include/linux/platform_data/pinctrl-nomadik.h      |   24 -
+ 40 files changed, 4728 insertions(+), 4803 deletions(-)
+Merging vhost/linux-next (8c325ee vhost: wake up worker outside spin_lock)
+$ git merge --no-ff vhost/linux-next
+Merge made by the 'recursive' strategy.
+ drivers/vhost/vhost.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+Merging memblock/memblock-kill-early_node_map (7bd0b0f memblock: Reimplement memblock allocation using reverse free area iterator)
+$ git merge --no-ff memblock/memblock-kill-early_node_map
+Already up-to-date.
+Merging remoteproc/for-next (b977785 remoteproc: fix kconfig dependencies for VIRTIO)
+$ git merge --no-ff remoteproc/for-next
+Already up-to-date.
+Merging rpmsg/for-next (397944d rpmsg: fix kconfig dependencies for VIRTIO)
+$ git merge --no-ff rpmsg/for-next
+Already up-to-date.
+Merging gpio/for-next (b0305e9 Merge branch 'devel' into for-next)
+$ git merge --no-ff gpio/for-next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/gpio/gpio-palmas.txt       |  27 +
+ .../devicetree/bindings/gpio/gpio-tz1090-pdc.txt   |  45 ++
+ .../devicetree/bindings/gpio/gpio-tz1090.txt       |  88 +++
+ .../devicetree/bindings/gpio/mrvl-gpio.txt         |   7 +-
+ .../devicetree/bindings/gpio/renesas,gpio-rcar.txt |   8 +
+ MAINTAINERS                                        |   1 -
+ drivers/gpio/Kconfig                               |  27 +
+ drivers/gpio/Makefile                              |   3 +
+ drivers/gpio/gpio-em.c                             |  25 +
+ drivers/gpio/gpio-kempld.c                         | 225 ++++++++
+ drivers/gpio/gpio-mxc.c                            |  37 +-
+ drivers/gpio/gpio-palmas.c                         |  12 +-
+ drivers/gpio/gpio-pxa.c                            |  13 +-
+ drivers/gpio/gpio-twl6040.c                        |   6 +-
+ drivers/gpio/gpio-tz1090-pdc.c                     | 243 +++++++++
+ drivers/gpio/gpio-tz1090.c                         | 606 +++++++++++++++++++++
+ drivers/gpio/gpiolib.c                             |   8 +-
+ include/linux/platform_data/gpio-em.h              |   1 +
+ 18 files changed, 1330 insertions(+), 52 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-palmas.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-tz1090.txt
+ create mode 100644 drivers/gpio/gpio-kempld.c
+ create mode 100644 drivers/gpio/gpio-tz1090-pdc.c
+ create mode 100644 drivers/gpio/gpio-tz1090.c
+Merging arm-soc/for-next (8d015b7 Merge branch 'next/fixes-non-critical' into for-next)
+$ git merge --no-ff arm-soc/for-next
+Removing arch/arm/mach-shmobile/include/mach/dma.h
+Removing arch/arm/include/asm/localtimer.h
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/vexpress-scc.txt       |  37 ++
+ arch/arm/Kconfig                                   |  12 +-
+ arch/arm/arm-soc-for-next-contents.txt             |  44 +++
+ arch/arm/boot/compressed/head-shmobile.S           |  43 ++-
+ arch/arm/boot/dts/Makefile                         |   1 +
+ arch/arm/boot/dts/emev2-kzm9d-reference.dts        |  57 ++++
+ arch/arm/boot/dts/emev2-kzm9d.dts                  |   2 +-
+ arch/arm/boot/dts/emev2.dtsi                       |  59 ++++
+ arch/arm/boot/dts/keystone.dts                     |  29 +-
+ arch/arm/boot/dts/r8a73a4-ape6evm.dts              |  22 ++
+ arch/arm/boot/dts/r8a73a4.dtsi                     | 126 +++++++
+ arch/arm/boot/dts/r8a7790.dtsi                     |  54 +++
+ arch/arm/include/asm/localtimer.h                  |  34 --
+ arch/arm/kernel/smp.c                              |  87 -----
+ arch/arm/kernel/smp_twd.c                          |  64 ++--
+ arch/arm/mach-dove/mpp.c                           |   2 +-
+ arch/arm/mach-highbank/Kconfig                     |   2 +-
+ arch/arm/mach-imx/Kconfig                          |   2 +-
+ arch/arm/mach-keystone/Kconfig                     |   1 -
+ arch/arm/mach-keystone/platsmp.c                   |   1 -
+ arch/arm/mach-keystone/smc.S                       |   5 +-
+ arch/arm/mach-msm/timer.c                          | 124 ++++---
+ arch/arm/mach-omap2/Kconfig                        |   3 +-
+ arch/arm/mach-omap2/timer.c                        |   6 +-
+ arch/arm/mach-realview/Kconfig                     |   8 +-
+ arch/arm/mach-shmobile/Kconfig                     |  12 +
+ arch/arm/mach-shmobile/Makefile                    |   1 +
+ arch/arm/mach-shmobile/Makefile.boot               |   1 +
+ arch/arm/mach-shmobile/board-ag5evm.c              |  65 +---
+ arch/arm/mach-shmobile/board-ape6evm.c             |   2 -
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |   9 -
+ arch/arm/mach-shmobile/board-kzm9d-reference.c     |  46 +++
+ arch/arm/mach-shmobile/board-kzm9d.c               |   4 +-
+ arch/arm/mach-shmobile/board-kzm9g-reference.c     |   2 -
+ arch/arm/mach-shmobile/board-lager.c               |   2 -
+ arch/arm/mach-shmobile/board-mackerel.c            |  34 +-
+ arch/arm/mach-shmobile/clock-emev2.c               |   2 +-
+ arch/arm/mach-shmobile/clock-r8a7740.c             |   2 +-
+ arch/arm/mach-shmobile/headsmp-scu.S               |   4 +-
+ arch/arm/mach-shmobile/headsmp.S                   |   6 +-
+ arch/arm/mach-shmobile/include/mach/dma.h          |   1 -
+ arch/arm/mach-shmobile/include/mach/emev2.h        |   3 +-
+ arch/arm/mach-shmobile/include/mach/r8a7778.h      |   1 -
+ arch/arm/mach-shmobile/include/mach/zboot.h        |   2 -
+ arch/arm/mach-shmobile/setup-emev2.c               | 376 ++++-----------------
+ arch/arm/mach-shmobile/setup-r8a73a4.c             |   2 -
+ arch/arm/mach-shmobile/setup-r8a7740.c             |  16 +-
+ arch/arm/mach-shmobile/setup-r8a7778.c             |  72 ++--
+ arch/arm/mach-shmobile/setup-r8a7779.c             |   7 +-
+ arch/arm/mach-shmobile/setup-r8a7790.c             |   7 -
+ arch/arm/mach-shmobile/setup-sh7372.c              |   7 +-
+ arch/arm/mach-shmobile/setup-sh73a0.c              |  34 +-
+ arch/arm/mach-shmobile/sleep-sh7372.S              |   2 +
+ arch/arm/mach-shmobile/smp-emev2.c                 |  17 +-
+ arch/arm/mach-spear/Kconfig                        |   2 +-
+ arch/arm/mach-tegra/Kconfig                        |   2 +-
+ arch/arm/mach-ux500/Kconfig                        |   2 +-
+ arch/arm/mach-vexpress/Kconfig                     |  11 +-
+ arch/arm/mach-vexpress/Makefile                    |   1 +
+ arch/arm/mach-vexpress/dcscb.c                     |  58 ++--
+ arch/arm/mach-vexpress/spc.c                       | 249 ++++++++++++++
+ arch/arm/mach-vexpress/spc.h                       |  25 ++
+ arch/arm/mach-vexpress/tc2_pm.c                    | 305 +++++++++++++++++
+ arch/arm/mach-zynq/Kconfig                         |   2 +-
+ arch/sh/boards/mach-ecovec24/setup.c               |  37 +-
+ arch/sh/boards/mach-kfr2r09/lcd_wqvga.c            |  48 ---
+ arch/sh/boards/mach-kfr2r09/setup.c                |  19 +-
+ arch/sh/include/mach-kfr2r09/mach/kfr2r09.h        |   2 -
+ drivers/clocksource/exynos_mct.c                   |  58 +++-
+ drivers/clocksource/time-armada-370-xp.c           |  92 +++--
+ drivers/clocksource/timer-marco.c                  |  98 +++---
+ drivers/platform/Kconfig                           |   1 -
+ drivers/video/backlight/Kconfig                    |  19 ++
+ drivers/video/backlight/Makefile                   |   3 +
+ drivers/video/backlight/bd6107.c                   | 213 ++++++++++++
+ drivers/video/backlight/gpio_backlight.c           | 133 ++++++++
+ drivers/video/backlight/lv5207lp.c                 | 171 ++++++++++
+ include/linux/platform_data/bd6107.h               |  19 ++
+ include/linux/platform_data/gpio_backlight.h       |  21 ++
+ include/linux/platform_data/lv5207lp.h             |  19 ++
+ include/linux/time-armada-370-xp.h                 |   4 +-
+ 81 files changed, 2200 insertions(+), 978 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/vexpress-scc.txt
+ create mode 100644 arch/arm/arm-soc-for-next-contents.txt
+ create mode 100644 arch/arm/boot/dts/emev2-kzm9d-reference.dts
+ delete mode 100644 arch/arm/include/asm/localtimer.h
+ create mode 100644 arch/arm/mach-shmobile/board-kzm9d-reference.c
+ delete mode 100644 arch/arm/mach-shmobile/include/mach/dma.h
+ create mode 100644 arch/arm/mach-vexpress/spc.c
+ create mode 100644 arch/arm/mach-vexpress/spc.h
+ create mode 100644 arch/arm/mach-vexpress/tc2_pm.c
+ create mode 100644 drivers/video/backlight/bd6107.c
+ create mode 100644 drivers/video/backlight/gpio_backlight.c
+ create mode 100644 drivers/video/backlight/lv5207lp.c
+ create mode 100644 include/linux/platform_data/bd6107.h
+ create mode 100644 include/linux/platform_data/gpio_backlight.h
+ create mode 100644 include/linux/platform_data/lv5207lp.h
+Merging bcm2835/for-next (7d13205 Linux 3.10-rc6)
+$ git merge --no-ff bcm2835/for-next
+Already up-to-date.
+Merging cortex/for-next (3ad87ac ARM: ARMv7-M: Fix name of NVIC handler function)
+$ git merge --no-ff cortex/for-next
+Merge made by the 'recursive' strategy.
+Merging ep93xx/ep93xx-for-next (9c59be7 Merge branch 'ep93xx-devel' into ep93xx-for-next)
+$ git merge --no-ff ep93xx/ep93xx-for-next
+Auto-merging arch/arm/mach-ep93xx/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-ep93xx/Kconfig                 |   1 +
+ arch/arm/mach-ep93xx/core.c                  | 108 ++++++++++++++++++++++++++-
+ arch/arm/mach-ep93xx/include/mach/platform.h |   3 +-
+ 3 files changed, 110 insertions(+), 2 deletions(-)
+Merging imx-mxs/for-next (d2adb32 Merge branches 'mxs/soc' and 'mxs/dt' into for-next)
+$ git merge --no-ff imx-mxs/for-next
+Resolved 'arch/arm/Kconfig.debug' using previous resolution.
+Auto-merging arch/arm/mach-imx/Kconfig
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig.debug
+CONFLICT (content): Merge conflict in arch/arm/Kconfig.debug
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 99252fb] Merge remote-tracking branch 'imx-mxs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/bus/imx-weim.txt |   17 +-
+ .../devicetree/bindings/clock/imx5-clock.txt       |    1 +
+ .../devicetree/bindings/clock/imx6q-clock.txt      |    6 +
+ arch/arm/Kconfig.debug                             |    8 +
+ arch/arm/boot/dts/Makefile                         |    5 +
+ arch/arm/boot/dts/imx23-evk.dts                    |   15 +
+ arch/arm/boot/dts/imx23-olinuxino.dts              |    4 +
+ arch/arm/boot/dts/imx23.dtsi                       |   17 +-
+ arch/arm/boot/dts/imx25.dtsi                       |   35 +-
+ arch/arm/boot/dts/imx27-apf27dev.dts               |    5 +
+ arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts   |   93 +
+ arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts   |   44 +
+ arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts     |   13 +
+ arch/arm/boot/dts/imx27-phytec-phycore-som.dts     |  120 +-
+ arch/arm/boot/dts/imx27.dtsi                       |  119 +-
+ arch/arm/boot/dts/imx28-cfa10036.dts               |    7 +-
+ arch/arm/boot/dts/imx28-cfa10037.dts               |   19 +-
+ arch/arm/boot/dts/imx28-cfa10049.dts               |   73 +-
+ arch/arm/boot/dts/imx28-cfa10055.dts               |   38 +-
+ arch/arm/boot/dts/imx28-cfa10056.dts               |  119 ++
+ arch/arm/boot/dts/imx28-cfa10057.dts               |   23 +-
+ arch/arm/boot/dts/imx28-cfa10058.dts               |  141 ++
+ arch/arm/boot/dts/imx28-m28evk.dts                 |   13 +
+ arch/arm/boot/dts/imx28.dtsi                       |   52 +-
+ arch/arm/boot/dts/imx31.dtsi                       |   17 +
+ arch/arm/boot/dts/imx51-apf51.dts                  |    4 -
+ arch/arm/boot/dts/imx51-babbage.dts                |    5 +
+ arch/arm/boot/dts/imx51.dtsi                       |  105 +-
+ arch/arm/boot/dts/imx53-qsb.dts                    |   18 +-
+ arch/arm/boot/dts/imx53.dtsi                       |   56 +-
+ arch/arm/boot/dts/imx6dl-pinfunc.h                 | 2138 ++++++++++----------
+ arch/arm/boot/dts/imx6dl-sabreauto.dts             |   22 -
+ arch/arm/boot/dts/imx6dl-sabresd.dts               |   19 -
+ arch/arm/boot/dts/imx6dl-wandboard.dts             |   24 +-
+ arch/arm/boot/dts/imx6dl.dtsi                      |  254 +--
+ arch/arm/boot/dts/imx6q-arm2.dts                   |   14 +-
+ arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi         |  112 +-
+ arch/arm/boot/dts/imx6q-pinfunc.h                  | 2050 +++++++++----------
+ arch/arm/boot/dts/imx6q-sabreauto.dts              |   22 +-
+ arch/arm/boot/dts/imx6q-sabrelite.dts              |   22 +-
+ arch/arm/boot/dts/imx6q-sabresd.dts                |   19 +-
+ arch/arm/boot/dts/imx6q-wandboard.dts              |   26 +
+ arch/arm/boot/dts/imx6q.dtsi                       |  393 +---
+ arch/arm/boot/dts/imx6qdl-sabreauto.dtsi           |   22 +
+ arch/arm/boot/dts/imx6qdl-sabresd.dtsi             |   80 +-
+ arch/arm/boot/dts/imx6qdl-wandboard.dtsi           |  137 ++
+ arch/arm/boot/dts/imx6qdl.dtsi                     |  770 ++++++-
+ arch/arm/boot/dts/imx6sl.dtsi                      |   35 +-
+ arch/arm/configs/imx_v4_v5_defconfig               |   20 +-
+ arch/arm/configs/imx_v6_v7_defconfig               |   52 +-
+ arch/arm/configs/mxs_defconfig                     |   19 +-
+ arch/arm/include/debug/vf.S                        |   26 +
+ arch/arm/mach-imx/Kconfig                          |    3 +-
+ arch/arm/mach-imx/Makefile                         |    3 +-
+ arch/arm/mach-imx/clk-fixup-div.c                  |  129 ++
+ arch/arm/mach-imx/clk-fixup-mux.c                  |  107 +
+ arch/arm/mach-imx/clk-imx51-imx53.c                |    3 +-
+ arch/arm/mach-imx/clk-imx6q.c                      |   57 +-
+ arch/arm/mach-imx/clk-imx6sl.c                     |   20 +-
+ arch/arm/mach-imx/clk-pllv3.c                      |   15 +-
+ arch/arm/mach-imx/clk.c                            |   26 +
+ arch/arm/mach-imx/clk.h                            |   10 +
+ arch/arm/mach-imx/common.h                         |   12 +-
+ arch/arm/mach-imx/mach-imx6q.c                     |  153 +-
+ arch/arm/mach-imx/mach-imx6sl.c                    |    3 +-
+ arch/arm/mach-imx/mm-imx5.c                        |    4 +-
+ arch/arm/mach-imx/pm-imx5.c                        |    7 +-
+ arch/arm/mach-imx/system.c                         |   33 +
+ arch/arm/mach-mxs/mach-mxs.c                       |   60 +-
+ arch/arm/mach-mxs/pm.c                             |    1 +
+ drivers/bus/Kconfig                                |    3 +-
+ drivers/bus/imx-weim.c                             |  129 +-
+ 72 files changed, 4954 insertions(+), 3292 deletions(-)
+ create mode 100644 arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
+ create mode 100644 arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts
+ create mode 100644 arch/arm/boot/dts/imx28-cfa10056.dts
+ create mode 100644 arch/arm/boot/dts/imx28-cfa10058.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-wandboard.dts
+ create mode 100644 arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+ create mode 100644 arch/arm/include/debug/vf.S
+ create mode 100644 arch/arm/mach-imx/clk-fixup-div.c
+ create mode 100644 arch/arm/mach-imx/clk-fixup-mux.c
+Merging ixp4xx/next (19f949f Linux 3.8)
+$ git merge --no-ff ixp4xx/next
+Already up-to-date.
+Merging msm/for-next (8fb0bf1 Merge branch 'for-3.12/msm-cleanup2' into for-next)
+$ git merge --no-ff msm/for-next
+Resolved 'arch/arm/Kconfig.debug' using previous resolution.
+Auto-merging arch/arm/mach-msm/timer.c
+Removing arch/arm/mach-msm/include/mach/uncompress.h
+Removing arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+Removing arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+Removing arch/arm/mach-msm/include/mach/board.h
+Removing arch/arm/mach-msm/devices-iommu.c
+Auto-merging arch/arm/include/debug/msm.S
+Auto-merging arch/arm/Kconfig.debug
+CONFLICT (content): Merge conflict in arch/arm/Kconfig.debug
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 049bbf6b] Merge remote-tracking branch 'msm/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/Kconfig                                   |   1 +
+ arch/arm/Kconfig.debug                             |   9 +-
+ .../mach/debug-macro.S => include/debug/msm.S}     |  32 +-
+ arch/arm/mach-msm/Makefile                         |   9 +-
+ arch/arm/mach-msm/board-dt-8660.c                  |   4 +-
+ arch/arm/mach-msm/board-dt-8960.c                  |   3 +-
+ arch/arm/mach-msm/board-halibut.c                  |   1 -
+ arch/arm/mach-msm/board-mahimahi.c                 |   2 +-
+ arch/arm/mach-msm/board-msm7x30.c                  |   1 -
+ arch/arm/mach-msm/board-qsd8x50.c                  |   1 -
+ arch/arm/mach-msm/board-sapphire.c                 |   2 +-
+ arch/arm/mach-msm/board-trout.c                    |   1 -
+ arch/arm/mach-msm/board-trout.h                    |   2 +-
+ arch/arm/mach-msm/common.h                         |  18 +-
+ arch/arm/mach-msm/devices-iommu.c                  | 912 ---------------------
+ arch/arm/mach-msm/devices-msm7x30.c                |   2 +-
+ arch/arm/mach-msm/devices-qsd8x50.c                |   2 +-
+ arch/arm/mach-msm/include/mach/board.h             |  38 -
+ arch/arm/mach-msm/include/mach/msm_iomap-8960.h    |  46 --
+ arch/arm/mach-msm/include/mach/msm_iomap-8x60.h    |  53 --
+ arch/arm/mach-msm/include/mach/msm_iomap.h         |  17 -
+ arch/arm/mach-msm/include/mach/uncompress.h        |  63 --
+ arch/arm/mach-msm/io.c                             |  67 +-
+ arch/arm/mach-msm/timer.c                          |  17 +-
+ drivers/iommu/msm_iommu.c                          |   4 +-
+ .../mach/iommu.h => drivers/iommu/msm_iommu.h      |   0
+ drivers/iommu/msm_iommu_dev.c                      |   4 +-
+ .../iommu/msm_iommu_hw-8xxx.h                      |   0
+ drivers/video/msm/msm_fb.c                         |   1 -
+ 29 files changed, 93 insertions(+), 1219 deletions(-)
+ rename arch/arm/{mach-msm/include/mach/debug-macro.S => include/debug/msm.S} (61%)
+ delete mode 100644 arch/arm/mach-msm/devices-iommu.c
+ delete mode 100644 arch/arm/mach-msm/include/mach/board.h
+ delete mode 100644 arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+ delete mode 100644 arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+ delete mode 100644 arch/arm/mach-msm/include/mach/uncompress.h
+ rename arch/arm/mach-msm/include/mach/iommu.h => drivers/iommu/msm_iommu.h (100%)
+ rename arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h => drivers/iommu/msm_iommu_hw-8xxx.h (100%)
+Merging mvebu/for-next (97a28fb Merge branch 'mvebu/msi_mvebu' into for-next)
+$ git merge --no-ff mvebu/for-next
+Resolved 'Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt' using previous resolution.
+Auto-merging include/linux/pci.h
+Auto-merging drivers/pci/probe.c
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/tile/Kconfig
+Auto-merging arch/s390/include/asm/pci.h
+Auto-merging arch/s390/Kconfig
+Removing arch/arm/mach-kirkwood/sheevaplug-setup.c
+Removing arch/arm/mach-kirkwood/netspace_v2-setup.c
+Removing arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+Removing arch/arm/mach-kirkwood/guruplug-setup.c
+Removing arch/arm/mach-kirkwood/dockstar-setup.c
+Auto-merging arch/arm/mach-kirkwood/common.c
+Removing arch/arm/mach-kirkwood/board-usi_topkick.c
+Removing arch/arm/mach-kirkwood/board-ts219.c
+Removing arch/arm/mach-kirkwood/board-sheevaplug.c
+Removing arch/arm/mach-kirkwood/board-readynas.c
+Removing arch/arm/mach-kirkwood/board-openblocks_a6.c
+Removing arch/arm/mach-kirkwood/board-ns2.c
+Removing arch/arm/mach-kirkwood/board-mplcec4.c
+Removing arch/arm/mach-kirkwood/board-lsxl.c
+Removing arch/arm/mach-kirkwood/board-km_kirkwood.c
+Removing arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+Removing arch/arm/mach-kirkwood/board-iconnect.c
+Removing arch/arm/mach-kirkwood/board-ib62x0.c
+Removing arch/arm/mach-kirkwood/board-guruplug.c
+Removing arch/arm/mach-kirkwood/board-goflexnet.c
+Removing arch/arm/mach-kirkwood/board-dreamplug.c
+Removing arch/arm/mach-kirkwood/board-dockstar.c
+Removing arch/arm/mach-kirkwood/board-db88f628x-bp.c
+Auto-merging arch/arm/mach-dove/common.c
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig
+Auto-merging Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+CONFLICT (content): Merge conflict in Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 14dbf22] Merge remote-tracking branch 'mvebu/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/armada-370-xp-mpic.txt |   3 +
+ .../devicetree/bindings/bus/mvebu-mbus.txt         | 276 ++++++++
+ .../devicetree/bindings/i2c/i2c-mv64xxx.txt        |  12 +
+ .../devicetree/bindings/pci/mvebu-pci.txt          | 148 +++--
+ arch/arm/Kconfig                                   |   1 -
+ arch/arm/boot/dts/Makefile                         |   5 +
+ arch/arm/boot/dts/armada-370-db.dts                |   5 +-
+ arch/arm/boot/dts/armada-370-mirabox.dts           |  37 +-
+ arch/arm/boot/dts/armada-370-netgear-rn102.dts     | 179 ++++++
+ arch/arm/boot/dts/armada-370-rd.dts                |   5 +-
+ arch/arm/boot/dts/armada-370-xp.dtsi               | 114 ++--
+ arch/arm/boot/dts/armada-370.dtsi                  | 127 ++--
+ arch/arm/boot/dts/armada-xp-axpwifiap.dts          | 164 +++++
+ arch/arm/boot/dts/armada-xp-db.dts                 | 131 ++--
+ arch/arm/boot/dts/armada-xp-gp.dts                 | 107 ++--
+ arch/arm/boot/dts/armada-xp-mv78230.dtsi           | 229 +++----
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi           | 270 ++++----
+ arch/arm/boot/dts/armada-xp-mv78460.dtsi           | 418 +++++++------
+ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts   |  88 ++-
+ arch/arm/boot/dts/armada-xp.dtsi                   |  19 +-
+ arch/arm/boot/dts/dove-cm-a510.dts                 |   2 +-
+ arch/arm/boot/dts/dove-cubox.dts                   |  39 +-
+ arch/arm/boot/dts/dove-d2plug.dts                  |  69 ++
+ arch/arm/boot/dts/dove-dove-db.dts                 |   2 +-
+ arch/arm/boot/dts/dove.dtsi                        | 691 ++++++++++++++-------
+ arch/arm/boot/dts/kirkwood-6281.dtsi               |  66 +-
+ arch/arm/boot/dts/kirkwood-6282.dtsi               | 102 +--
+ arch/arm/boot/dts/kirkwood-cloudbox.dts            |  20 +-
+ arch/arm/boot/dts/kirkwood-db-88f6281.dts          |   7 +-
+ arch/arm/boot/dts/kirkwood-db-88f6282.dts          |   7 +-
+ arch/arm/boot/dts/kirkwood-db.dtsi                 |  22 +-
+ arch/arm/boot/dts/kirkwood-dns320.dts              |   2 +-
+ arch/arm/boot/dts/kirkwood-dns325.dts              |   2 +-
+ arch/arm/boot/dts/kirkwood-dnskw.dtsi              |  20 +-
+ arch/arm/boot/dts/kirkwood-dockstar.dts            |  21 +-
+ arch/arm/boot/dts/kirkwood-dreamplug.dts           |  32 +-
+ arch/arm/boot/dts/kirkwood-goflexnet.dts           |  20 +-
+ .../arm/boot/dts/kirkwood-guruplug-server-plus.dts |  34 +-
+ arch/arm/boot/dts/kirkwood-ib62x0.dts              |  20 +-
+ arch/arm/boot/dts/kirkwood-iconnect.dts            |  39 +-
+ arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts      |  28 +-
+ arch/arm/boot/dts/kirkwood-is2.dts                 |   4 +-
+ arch/arm/boot/dts/kirkwood-km_kirkwood.dts         |  20 +-
+ arch/arm/boot/dts/kirkwood-lschlv2.dts             |   2 +-
+ arch/arm/boot/dts/kirkwood-lsxhl.dts               |   2 +-
+ arch/arm/boot/dts/kirkwood-lsxl.dtsi               |  32 +-
+ arch/arm/boot/dts/kirkwood-mplcec4.dts             |  50 +-
+ arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts     | 125 ++++
+ .../boot/dts/kirkwood-netgear_readynas_duo_v2.dts  |  59 +-
+ arch/arm/boot/dts/kirkwood-ns2-common.dtsi         |  20 +-
+ arch/arm/boot/dts/kirkwood-ns2.dts                 |   4 +-
+ arch/arm/boot/dts/kirkwood-ns2lite.dts             |   4 +-
+ arch/arm/boot/dts/kirkwood-ns2max.dts              |   4 +-
+ arch/arm/boot/dts/kirkwood-ns2mini.dts             |   4 +-
+ arch/arm/boot/dts/kirkwood-nsa310-common.dtsi      | 107 ++++
+ arch/arm/boot/dts/kirkwood-nsa310.dts              | 111 +---
+ arch/arm/boot/dts/kirkwood-nsa310a.dts             | 165 +++++
+ arch/arm/boot/dts/kirkwood-openblocks_a6.dts       |  20 +-
+ arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi  |  20 +-
+ arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts    |   2 +-
+ arch/arm/boot/dts/kirkwood-sheevaplug.dts          |   2 +-
+ arch/arm/boot/dts/kirkwood-topkick.dts             |  20 +-
+ arch/arm/boot/dts/kirkwood-ts219-6281.dts          |  10 +-
+ arch/arm/boot/dts/kirkwood-ts219-6282.dts          |  29 +-
+ arch/arm/boot/dts/kirkwood-ts219.dtsi              |  31 +-
+ arch/arm/boot/dts/kirkwood.dtsi                    | 102 ++-
+ .../dts/orion5x-lacie-ethernet-disk-mini-v2.dts    |  17 +
+ arch/arm/boot/dts/orion5x.dtsi                     |  34 +-
+ arch/arm/boot/dts/skeleton64.dtsi                  |   2 +-
+ arch/arm/configs/kirkwood_defconfig                |  33 +-
+ arch/arm/configs/mvebu_defconfig                   |   2 +
+ arch/arm/include/asm/mach/pci.h                    |   4 +
+ arch/arm/kernel/bios32.c                           |  16 +
+ arch/arm/mach-dove/Kconfig                         |   2 +
+ arch/arm/mach-dove/Makefile                        |   4 +-
+ arch/arm/mach-dove/board-dt.c                      |  26 +-
+ arch/arm/mach-dove/common.c                        |  68 +-
+ arch/arm/mach-kirkwood/Kconfig                     | 232 +------
+ arch/arm/mach-kirkwood/Makefile                    |  35 +-
+ arch/arm/mach-kirkwood/board-db88f628x-bp.c        |  24 -
+ arch/arm/mach-kirkwood/board-dnskw.c               |   7 -
+ arch/arm/mach-kirkwood/board-dockstar.c            |  32 -
+ arch/arm/mach-kirkwood/board-dreamplug.c           |  35 --
+ arch/arm/mach-kirkwood/board-dt.c                  | 115 +---
+ arch/arm/mach-kirkwood/board-goflexnet.c           |  34 -
+ arch/arm/mach-kirkwood/board-guruplug.c            |  33 -
+ arch/arm/mach-kirkwood/board-ib62x0.c              |  29 -
+ arch/arm/mach-kirkwood/board-iconnect.c            |  24 -
+ arch/arm/mach-kirkwood/board-iomega_ix2_200.c      |  34 -
+ arch/arm/mach-kirkwood/board-km_kirkwood.c         |  44 --
+ arch/arm/mach-kirkwood/board-lsxl.c                |  36 --
+ arch/arm/mach-kirkwood/board-mplcec4.c             |  35 --
+ arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c     |  50 ++
+ arch/arm/mach-kirkwood/board-ns2.c                 |  35 --
+ arch/arm/mach-kirkwood/board-openblocks_a6.c       |  26 -
+ arch/arm/mach-kirkwood/board-readynas.c            |  27 -
+ arch/arm/mach-kirkwood/board-sheevaplug.c          |  27 -
+ arch/arm/mach-kirkwood/board-ts219.c               |  40 --
+ arch/arm/mach-kirkwood/board-usi_topkick.c         |  29 -
+ arch/arm/mach-kirkwood/common.c                    |  26 +-
+ arch/arm/mach-kirkwood/common.h                    | 109 +---
+ arch/arm/mach-kirkwood/dockstar-setup.c            | 111 ----
+ arch/arm/mach-kirkwood/guruplug-setup.c            | 133 ----
+ arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c     | 172 -----
+ arch/arm/mach-kirkwood/netspace_v2-setup.c         | 293 ---------
+ arch/arm/mach-kirkwood/pcie.c                      |  40 +-
+ arch/arm/mach-kirkwood/sheevaplug-setup.c          | 161 -----
+ arch/arm/mach-mv78xx0/pcie.c                       |  23 +-
+ arch/arm/mach-mvebu/armada-370-xp.c                |  34 +-
+ arch/arm/mach-mvebu/platsmp.c                      |  25 +-
+ arch/arm/mach-orion5x/common.c                     |  36 +-
+ arch/arm/mach-orion5x/common.h                     |  17 +
+ arch/arm/mach-orion5x/d2net-setup.c                |   6 +-
+ arch/arm/mach-orion5x/db88f5281-setup.c            |  24 +-
+ arch/arm/mach-orion5x/dns323-setup.c               |   6 +-
+ arch/arm/mach-orion5x/edmini_v2-setup.c            |  17 +-
+ arch/arm/mach-orion5x/kurobox_pro-setup.c          |  12 +-
+ arch/arm/mach-orion5x/ls-chl-setup.c               |   6 +-
+ arch/arm/mach-orion5x/ls_hgl-setup.c               |   6 +-
+ arch/arm/mach-orion5x/lsmini-setup.c               |   6 +-
+ arch/arm/mach-orion5x/mss2-setup.c                 |   6 +-
+ arch/arm/mach-orion5x/mv2120-setup.c               |   6 +-
+ arch/arm/mach-orion5x/net2big-setup.c              |   6 +-
+ arch/arm/mach-orion5x/pci.c                        |   9 +-
+ arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c       |   6 +-
+ arch/arm/mach-orion5x/rd88f5181l-ge-setup.c        |   6 +-
+ arch/arm/mach-orion5x/rd88f5182-setup.c            |  13 +-
+ arch/arm/mach-orion5x/terastation_pro2-setup.c     |   6 +-
+ arch/arm/mach-orion5x/ts209-setup.c                |   6 +-
+ arch/arm/mach-orion5x/ts409-setup.c                |   6 +-
+ arch/arm/mach-orion5x/wnr854t-setup.c              |   6 +-
+ arch/arm/mach-orion5x/wrt350n-v2-setup.c           |   6 +-
+ arch/arm/plat-orion/irq.c                          |   2 +-
+ arch/ia64/Kconfig                                  |   1 -
+ arch/mips/Kconfig                                  |   2 -
+ arch/mips/include/asm/pci.h                        |   5 -
+ arch/powerpc/Kconfig                               |   1 -
+ arch/powerpc/include/asm/pci.h                     |   5 -
+ arch/s390/Kconfig                                  |   1 -
+ arch/s390/include/asm/pci.h                        |   4 -
+ arch/sparc/Kconfig                                 |   1 -
+ arch/tile/Kconfig                                  |   1 -
+ arch/x86/Kconfig                                   |   1 -
+ arch/x86/include/asm/pci.h                         |  28 -
+ arch/x86/kernel/x86_init.c                         |  21 +
+ drivers/bus/mvebu-mbus.c                           | 441 +++++++------
+ drivers/irqchip/irq-armada-370-xp.c                | 158 ++++-
+ drivers/memory/mvebu-devbus.c                      |  64 +-
+ drivers/pci/Kconfig                                |   4 -
+ drivers/pci/host/pci-mvebu.c                       | 146 ++++-
+ drivers/pci/msi.c                                  |  69 +-
+ drivers/pci/probe.c                                |   1 +
+ include/linux/irqdomain.h                          |  62 +-
+ include/linux/mbus.h                               |  16 +-
+ include/linux/msi.h                                |  19 +-
+ include/linux/pci.h                                |   1 +
+ kernel/irq/irqdomain.c                             |  89 ++-
+ 157 files changed, 4454 insertions(+), 3757 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/bus/mvebu-mbus.txt
+ create mode 100644 arch/arm/boot/dts/armada-370-netgear-rn102.dts
+ create mode 100644 arch/arm/boot/dts/armada-xp-axpwifiap.dts
+ create mode 100644 arch/arm/boot/dts/dove-d2plug.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-nsa310a.dts
+ delete mode 100644 arch/arm/mach-kirkwood/board-db88f628x-bp.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-dockstar.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-dreamplug.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-goflexnet.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-guruplug.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-ib62x0.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-iconnect.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-km_kirkwood.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-lsxl.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-mplcec4.c
+ create mode 100644 arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-ns2.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-openblocks_a6.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-readynas.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-sheevaplug.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-ts219.c
+ delete mode 100644 arch/arm/mach-kirkwood/board-usi_topkick.c
+ delete mode 100644 arch/arm/mach-kirkwood/dockstar-setup.c
+ delete mode 100644 arch/arm/mach-kirkwood/guruplug-setup.c
+ delete mode 100644 arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+ delete mode 100644 arch/arm/mach-kirkwood/netspace_v2-setup.c
+ delete mode 100644 arch/arm/mach-kirkwood/sheevaplug-setup.c
+Merging renesas/next (8a8c6f7 Merge tag 'renesas-defconfig-for-v3.12' into next)
+$ git merge --no-ff renesas/next
+Resolved 'arch/arm/Makefile' using previous resolution.
+Removing include/linux/platform_data/leds-renesas-tpu.h
+CONFLICT (modify/delete): drivers/leds/leds-renesas-tpu.c deleted in renesas/next and modified in HEAD. Version HEAD of drivers/leds/leds-renesas-tpu.c left in tree.
+Auto-merging drivers/leds/Makefile
+Auto-merging drivers/leds/Kconfig
+Removing arch/arm/mach-shmobile/intc-r8a7779.c
+Removing arch/arm/mach-shmobile/intc-r8a7740.c
+Removing arch/arm/mach-shmobile/include/mach/hardware.h
+Removing arch/arm/mach-shmobile/board-kota2.c
+Removing arch/arm/mach-shmobile/board-ag5evm.c
+Auto-merging arch/arm/configs/lager_defconfig
+Removing arch/arm/configs/ag5evm_defconfig
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Makefile
+CONFLICT (content): Merge conflict in arch/arm/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/leds/leds-renesas-tpu.c
+drivers/leds/leds-renesas-tpu.c: needs merge
+rm 'drivers/leds/leds-renesas-tpu.c'
+$ git commit -v -a
+[master abe8e8f] Merge remote-tracking branch 'renesas/next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/Makefile                                  |   1 +
+ arch/arm/boot/dts/Makefile                         |   5 +
+ arch/arm/boot/dts/emev2-kzm9d-reference.dts        |   2 +-
+ arch/arm/boot/dts/emev2-kzm9d.dts                  |   2 +-
+ arch/arm/boot/dts/emev2.dtsi                       |   6 +
+ arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts    |  65 +++
+ arch/arm/boot/dts/r8a73a4-ape6evm.dts              |   2 +-
+ arch/arm/boot/dts/r8a73a4.dtsi                     |   7 +
+ .../boot/dts/r8a7740-armadillo800eva-reference.dts |  36 +-
+ arch/arm/boot/dts/r8a7740-armadillo800eva.dts      |   2 +-
+ arch/arm/boot/dts/r8a7740.dtsi                     |  20 +
+ arch/arm/boot/dts/r8a7778-bockw-reference.dts      |  32 ++
+ arch/arm/boot/dts/r8a7778-bockw.dts                |   2 +-
+ arch/arm/boot/dts/r8a7778.dtsi                     |  66 +++
+ arch/arm/boot/dts/r8a7779-marzen-reference.dts     |  51 +-
+ arch/arm/boot/dts/r8a7779-marzen.dts               |  27 +
+ arch/arm/boot/dts/r8a7779.dtsi                     |  98 +++-
+ arch/arm/boot/dts/r8a7790-lager-reference.dts      |  45 ++
+ arch/arm/boot/dts/r8a7790-lager.dts                |   2 +-
+ arch/arm/boot/dts/r8a7790.dtsi                     |  78 +++
+ arch/arm/boot/dts/sh7372.dtsi                      |   8 +
+ arch/arm/boot/dts/sh73a0-kzm9g-reference.dts       |  92 ++-
+ arch/arm/boot/dts/sh73a0-kzm9g.dts                 |   2 +-
+ arch/arm/boot/dts/sh73a0.dtsi                      |  14 +
+ arch/arm/configs/ag5evm_defconfig                  |  83 ---
+ arch/arm/configs/ape6evm_defconfig                 |   6 +-
+ .../configs/{kota2_defconfig => lager_defconfig}   | 111 ++--
+ arch/arm/configs/marzen_defconfig                  |   1 +
+ arch/arm/mach-shmobile/Kconfig                     | 107 +++-
+ arch/arm/mach-shmobile/Makefile                    |  52 +-
+ arch/arm/mach-shmobile/Makefile.boot               |   5 +-
+ arch/arm/mach-shmobile/board-ag5evm.c              | 639 ---------------------
+ arch/arm/mach-shmobile/board-ape6evm-reference.c   |  63 ++
+ arch/arm/mach-shmobile/board-ape6evm.c             | 147 ++++-
+ .../board-armadillo800eva-reference.c              |  23 +-
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |  58 +-
+ arch/arm/mach-shmobile/board-bockw-reference.c     |  61 ++
+ arch/arm/mach-shmobile/board-bockw.c               |  49 +-
+ arch/arm/mach-shmobile/board-kota2.c               | 553 ------------------
+ arch/arm/mach-shmobile/board-kzm9d-reference.c     |   3 +-
+ arch/arm/mach-shmobile/board-kzm9g-reference.c     |  48 --
+ arch/arm/mach-shmobile/board-kzm9g.c               |  16 +-
+ arch/arm/mach-shmobile/board-lager-reference.c     |  45 ++
+ arch/arm/mach-shmobile/board-lager.c               |  61 ++
+ arch/arm/mach-shmobile/board-marzen-reference.c    |  29 -
+ arch/arm/mach-shmobile/board-marzen.c              |  36 +-
+ arch/arm/mach-shmobile/clock-emev2.c               |  18 -
+ arch/arm/mach-shmobile/clock-r8a73a4.c             | 199 ++++++-
+ arch/arm/mach-shmobile/clock-r8a7740.c             |   1 +
+ arch/arm/mach-shmobile/clock-r8a7790.c             |  27 +-
+ arch/arm/mach-shmobile/clock-sh73a0.c              |  12 +-
+ arch/arm/mach-shmobile/headsmp.S                   |  49 ++
+ arch/arm/mach-shmobile/include/mach/common.h       |  10 +-
+ arch/arm/mach-shmobile/include/mach/emev2.h        |   1 -
+ arch/arm/mach-shmobile/include/mach/hardware.h     |   4 -
+ arch/arm/mach-shmobile/include/mach/r8a73a4.h      |   2 +
+ arch/arm/mach-shmobile/include/mach/r8a7740.h      |   3 +-
+ arch/arm/mach-shmobile/include/mach/r8a7778.h      |   9 +-
+ arch/arm/mach-shmobile/include/mach/r8a7779.h      |   3 -
+ arch/arm/mach-shmobile/include/mach/r8a7790.h      |   5 +
+ arch/arm/mach-shmobile/include/mach/sh73a0.h       | 373 ------------
+ arch/arm/mach-shmobile/intc-r8a7740.c              |  68 ---
+ arch/arm/mach-shmobile/intc-r8a7779.c              | 131 -----
+ arch/arm/mach-shmobile/platsmp-scu.c               |  81 +++
+ arch/arm/mach-shmobile/platsmp.c                   |  18 +
+ arch/arm/mach-shmobile/setup-emev2.c               |   4 +-
+ arch/arm/mach-shmobile/setup-r8a73a4.c             |  40 +-
+ arch/arm/mach-shmobile/setup-r8a7740.c             |  43 +-
+ arch/arm/mach-shmobile/setup-r8a7778.c             |  71 +--
+ arch/arm/mach-shmobile/setup-r8a7779.c             | 102 +++-
+ arch/arm/mach-shmobile/setup-r8a7790.c             | 116 +++-
+ arch/arm/mach-shmobile/setup-sh7372.c              |   1 -
+ arch/arm/mach-shmobile/setup-sh73a0.c              |   1 -
+ arch/arm/mach-shmobile/smp-emev2.c                 |  28 +-
+ arch/arm/mach-shmobile/smp-r8a7779.c               |  70 +--
+ arch/arm/mach-shmobile/smp-sh73a0.c                |  72 +--
+ arch/arm/mach-shmobile/timer.c                     |   4 -
+ drivers/clocksource/em_sti.c                       |  49 +-
+ drivers/clocksource/sh_cmt.c                       |  50 +-
+ drivers/leds/Kconfig                               |  12 -
+ drivers/leds/Makefile                              |   1 -
+ drivers/leds/leds-renesas-tpu.c                    | 337 -----------
+ include/linux/platform_data/leds-renesas-tpu.h     |  14 -
+ 83 files changed, 2106 insertions(+), 2784 deletions(-)
+ create mode 100644 arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
+ create mode 100644 arch/arm/boot/dts/r8a7778-bockw-reference.dts
+ create mode 100644 arch/arm/boot/dts/r8a7779-marzen.dts
+ create mode 100644 arch/arm/boot/dts/r8a7790-lager-reference.dts
+ delete mode 100644 arch/arm/configs/ag5evm_defconfig
+ rename arch/arm/configs/{kota2_defconfig => lager_defconfig} (55%)
+ delete mode 100644 arch/arm/mach-shmobile/board-ag5evm.c
+ create mode 100644 arch/arm/mach-shmobile/board-ape6evm-reference.c
+ create mode 100644 arch/arm/mach-shmobile/board-bockw-reference.c
+ delete mode 100644 arch/arm/mach-shmobile/board-kota2.c
+ create mode 100644 arch/arm/mach-shmobile/board-lager-reference.c
+ delete mode 100644 arch/arm/mach-shmobile/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-shmobile/intc-r8a7740.c
+ delete mode 100644 arch/arm/mach-shmobile/intc-r8a7779.c
+ create mode 100644 arch/arm/mach-shmobile/platsmp-scu.c
+ delete mode 100644 drivers/leds/leds-renesas-tpu.c
+ delete mode 100644 include/linux/platform_data/leds-renesas-tpu.h
+Merging samsung/for-next (45fd387 Merge branch 'v3.12-next/cleanup-samsung' into for-next)
+$ git merge --no-ff samsung/for-next
+Removing arch/arm/configs/exynos4_defconfig
+Auto-merging arch/arm/boot/dts/Makefile
+Merge made by the 'recursive' strategy.
+ arch/arm/boot/dts/Makefile                |   5 +-
+ arch/arm/boot/dts/exynos4.dtsi            | 100 +++++-
+ arch/arm/boot/dts/exynos4210-pinctrl.dtsi |  23 ++
+ arch/arm/boot/dts/exynos4210-trats.dts    | 100 +++++-
+ arch/arm/boot/dts/exynos4210.dtsi         |  32 +-
+ arch/arm/boot/dts/exynos4412-trats2.dts   | 579 ++++++++++++++++++++++++++++++
+ arch/arm/boot/dts/exynos4x12-pinctrl.dtsi |  61 +++-
+ arch/arm/boot/dts/exynos4x12.dtsi         | 105 +++++-
+ arch/arm/boot/dts/exynos5250-arndale.dts  |  83 ++++-
+ arch/arm/boot/dts/exynos5250.dtsi         |  22 +-
+ arch/arm/boot/dts/exynos5420.dtsi         |   2 +-
+ arch/arm/boot/dts/exynos5440.dtsi         |  29 +-
+ arch/arm/configs/exynos4_defconfig        |  68 ----
+ arch/arm/configs/exynos5440_defconfig     | 138 +++++++
+ arch/arm/mach-exynos/Kconfig              |   7 +-
+ arch/arm/mach-exynos/common.h             |  43 ---
+ arch/arm/plat-samsung/init.c              |   5 +-
+ drivers/irqchip/exynos-combiner.c         |  44 +--
+ 18 files changed, 1235 insertions(+), 211 deletions(-)
+ create mode 100644 arch/arm/boot/dts/exynos4412-trats2.dts
+ delete mode 100644 arch/arm/configs/exynos4_defconfig
+ create mode 100644 arch/arm/configs/exynos5440_defconfig
+Merging tegra/for-next (718d932 Merge branch for-3.12/defconfig into for-next)
+$ git merge --no-ff tegra/for-next
+Auto-merging arch/arm/mach-tegra/pm.c
+Auto-merging arch/arm/mach-tegra/platsmp.c
+Auto-merging arch/arm/mach-tegra/Kconfig
+Auto-merging arch/arm/boot/dts/tegra20-trimslice.dts
+Auto-merging arch/arm/boot/dts/tegra20-seaboard.dts
+Removing arch/arm/boot/dts/tegra114-pluto.dts
+Auto-merging arch/arm/boot/dts/Makefile
+Merge made by the 'recursive' strategy.
+ .../bindings/pinctrl/nvidia,tegra114-pinmux.txt    |  11 +
+ .../bindings/pinctrl/nvidia,tegra20-pinmux.txt     |  11 +
+ .../bindings/pinctrl/nvidia,tegra30-pinmux.txt     |  12 ++
+ arch/arm/boot/dts/Makefile                         |   3 +-
+ arch/arm/boot/dts/tegra114-dalmore.dts             | 222 ++++++++++++++++++++-
+ arch/arm/boot/dts/tegra114-pluto.dts               |  33 ---
+ arch/arm/boot/dts/tegra20-seaboard.dts             |   2 +-
+ arch/arm/boot/dts/tegra20-trimslice.dts            |   2 +-
+ arch/arm/boot/dts/tegra30-cardhu.dtsi              |  33 +--
+ arch/arm/configs/tegra_defconfig                   |   3 +
+ arch/arm/mach-tegra/Kconfig                        |  22 +-
+ arch/arm/mach-tegra/common.h                       |   1 -
+ arch/arm/mach-tegra/cpuidle-tegra114.c             |  51 ++++-
+ arch/arm/mach-tegra/flowctrl.c                     |   2 +
+ arch/arm/mach-tegra/flowctrl.h                     |   9 +
+ arch/arm/mach-tegra/headsmp.S                      |   3 +-
+ arch/arm/mach-tegra/hotplug.c                      |  13 +-
+ arch/arm/mach-tegra/irq.c                          |  40 ++++
+ arch/arm/mach-tegra/platsmp.c                      |   1 -
+ arch/arm/mach-tegra/pm.c                           |   8 +-
+ arch/arm/mach-tegra/pmc.c                          |  16 +-
+ arch/arm/mach-tegra/reset-handler.S                |   8 +-
+ arch/arm/mach-tegra/sleep-tegra20.S                |   1 +
+ arch/arm/mach-tegra/sleep-tegra30.S                |   9 +-
+ arch/arm/mach-tegra/sleep.S                        |  29 ++-
+ arch/arm/mach-tegra/sleep.h                        |   6 +-
+ drivers/clk/tegra/clk-tegra114.c                   |  26 +++
+ 27 files changed, 484 insertions(+), 93 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/tegra114-pluto.dts
+Merging dma-mapping/dma-mapping-next (f7d8f1e Merge remote-tracking branch 'dma-public/for-v3.12-cma-dma' into for-next)
+$ git merge --no-ff dma-mapping/dma-mapping-next
+Merge made by the 'recursive' strategy.
+Merging pwm/for-next (6d0cf4d ARM: dts: Use the PWM polarity flags)
+$ git merge --no-ff pwm/for-next
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/pwm/atmel-tcb-pwm.txt       |  8 +++-----
+ Documentation/devicetree/bindings/pwm/imx-pwm.txt   |  4 ++--
+ Documentation/devicetree/bindings/pwm/mxs-pwm.txt   |  4 ++--
+ .../devicetree/bindings/pwm/nvidia,tegra20-pwm.txt  |  5 ++---
+ .../devicetree/bindings/pwm/nxp,pca9685-pwm.txt     |  4 ++--
+ .../devicetree/bindings/pwm/pwm-samsung.txt         | 10 +++-------
+ .../devicetree/bindings/pwm/pwm-tiecap.txt          |  8 +++-----
+ .../devicetree/bindings/pwm/pwm-tiehrpwm.txt        |  8 +++-----
+ Documentation/devicetree/bindings/pwm/pwm.txt       |  7 ++++---
+ Documentation/devicetree/bindings/pwm/spear-pwm.txt |  5 ++---
+ .../devicetree/bindings/pwm/ti,twl-pwm.txt          |  4 ++--
+ .../devicetree/bindings/pwm/ti,twl-pwmled.txt       |  4 ++--
+ .../devicetree/bindings/pwm/vt8500-pwm.txt          |  8 +++-----
+ arch/arm/boot/dts/am335x-evmsk.dts                  |  3 ++-
+ arch/arm/boot/dts/wm8850-w70v2.dts                  |  3 ++-
+ drivers/pwm/core.c                                  |  7 +++----
+ drivers/pwm/pwm-mxs.c                               |  8 +++++++-
+ drivers/pwm/sysfs.c                                 | 21 ++++++++++++---------
+ include/dt-bindings/pwm/pwm.h                       | 14 ++++++++++++++
+ 19 files changed, 73 insertions(+), 62 deletions(-)
+ create mode 100644 include/dt-bindings/pwm/pwm.h
+Merging dma-buf/for-next (8bb495e Linux 3.10)
+$ git merge --no-ff dma-buf/for-next
+Already up-to-date.
+Merging userns/for-next (78008c4 proc: Restrict mounting the proc filesystem)
+$ git merge --no-ff userns/for-next
+Auto-merging fs/proc/root.c
+Merge made by the 'recursive' strategy.
+ fs/proc/root.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+Merging ktest/for-next (df5f7c6 ktest: Reset grub menu cache with different machines)
+$ git merge --no-ff ktest/for-next
+Already up-to-date.
+Merging signal/for-next (20b4fb4 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs)
+$ git merge --no-ff signal/for-next
+Already up-to-date.
+Merging clk/clk-next (d2127ac clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC)
+$ git merge --no-ff clk/clk-next
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/clock/exynos4-clock.txt    |   1 +
+ .../devicetree/bindings/clock/exynos5250-clock.txt |  14 +-
+ .../devicetree/bindings/gpu/samsung-g2d.txt        |   7 +-
+ drivers/clk/Kconfig                                |   2 +-
+ drivers/clk/clk.c                                  |  13 +-
+ drivers/clk/samsung/clk-exynos-audss.c             |   2 +-
+ drivers/clk/samsung/clk-exynos4.c                  |  86 +++---
+ drivers/clk/samsung/clk-exynos5250.c               | 129 ++++++--
+ drivers/clk/samsung/clk-exynos5420.c               | 100 +++---
+ drivers/clk/samsung/clk-exynos5440.c               |  14 +-
+ drivers/clk/samsung/clk-pll.c                      | 339 ++++++++++++++++-----
+ drivers/clk/samsung/clk-pll.h                      |  38 ++-
+ drivers/clk/samsung/clk.h                          |  53 ++++
+ 13 files changed, 596 insertions(+), 202 deletions(-)
+Merging random/dev (b980955 random: fix locking dependency with the tasklist_lock)
+$ git merge --no-ff random/dev
+Already up-to-date.
+Merging lzo-update/lzo-update (42b775a lib/lzo: huge LZO decompression speedup on ARM by using unaligned access)
+$ git merge --no-ff lzo-update/lzo-update
+Merge made by the 'recursive' strategy.
+ lib/lzo/lzo1x_decompress_safe.c | 4 ++++
+ lib/lzo/lzodefs.h               | 6 ++++++
+ 2 files changed, 10 insertions(+)
+Merging arm64-hugepages/for-next/hugepages (af07484 ARM64: mm: THP support.)
+$ git merge --no-ff arm64-hugepages/for-next/hugepages
+Already up-to-date.
+Merging ptr-ret/PTR_RET (ad151d5 GFS2: Replace PTR_RET with PTR_ERR_OR_ZERO)
+$ git merge --no-ff ptr-ret/PTR_RET
+Auto-merging drivers/staging/zcache/zcache-main.c
+Auto-merging drivers/regulator/fan53555.c
+Auto-merging drivers/infiniband/core/cma.c
+Auto-merging drivers/gpu/drm/drm_gem_cma_helper.c
+Auto-merging drivers/char/tile-srom.c
+Auto-merging drivers/acpi/acpi_pad.c
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-omap2/i2c.c                         |  2 +-
+ arch/m68k/amiga/platform.c                        |  2 +-
+ arch/m68k/kernel/time.c                           |  2 +-
+ arch/m68k/q40/config.c                            |  2 +-
+ arch/powerpc/kernel/iommu.c                       |  2 +-
+ arch/powerpc/kernel/time.c                        |  2 +-
+ arch/powerpc/platforms/ps3/time.c                 |  2 +-
+ arch/powerpc/sysdev/rtc_cmos_setup.c              |  2 +-
+ arch/s390/hypfs/hypfs_dbfs.c                      |  2 +-
+ arch/s390/kvm/gaccess.h                           | 12 ++++++++----
+ drivers/acpi/acpi_pad.c                           | 13 ++++++++-----
+ drivers/base/dma-buf.c                            |  2 +-
+ drivers/char/tile-srom.c                          |  2 +-
+ drivers/gpu/drm/drm_gem_cma_helper.c              |  2 +-
+ drivers/infiniband/core/cma.c                     |  2 +-
+ drivers/media/platform/sh_veu.c                   |  2 +-
+ drivers/net/appletalk/cops.c                      |  2 +-
+ drivers/net/appletalk/ltpc.c                      |  2 +-
+ drivers/net/ethernet/amd/atarilance.c             |  2 +-
+ drivers/net/ethernet/amd/mvme147.c                |  2 +-
+ drivers/net/ethernet/amd/ni65.c                   |  2 +-
+ drivers/net/ethernet/amd/sun3lance.c              |  2 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c |  2 +-
+ drivers/net/wireless/brcm80211/brcmsmac/debug.c   |  2 +-
+ drivers/pinctrl/mvebu/pinctrl-dove.c              |  2 +-
+ drivers/platform/x86/samsung-q10.c                |  2 +-
+ drivers/regulator/fan53555.c                      |  2 +-
+ drivers/remoteproc/da8xx_remoteproc.c             |  2 +-
+ drivers/rtc/rtc-da9052.c                          |  2 +-
+ drivers/rtc/rtc-isl12022.c                        |  2 +-
+ drivers/rtc/rtc-m48t35.c                          |  2 +-
+ drivers/rtc/rtc-pcf8563.c                         |  2 +-
+ drivers/rtc/rtc-pcf8583.c                         |  2 +-
+ drivers/spi/spi-fsl-spi.c                         |  2 +-
+ drivers/spi/spidev.c                              |  2 +-
+ drivers/staging/zcache/zcache-main.c              |  2 +-
+ drivers/video/omap2/dss/core.c                    |  2 +-
+ fs/btrfs/dev-replace.c                            |  2 +-
+ fs/btrfs/inode.c                                  |  2 +-
+ fs/btrfs/volumes.c                                |  2 +-
+ include/linux/err.h                               |  5 ++++-
+ mm/oom_kill.c                                     |  6 +++---
+ net/bluetooth/hci_sysfs.c                         |  2 +-
+ net/bridge/netfilter/ebtable_broute.c             |  2 +-
+ net/bridge/netfilter/ebtable_filter.c             |  2 +-
+ net/bridge/netfilter/ebtable_nat.c                |  2 +-
+ net/ipv4/netfilter/arptable_filter.c              |  2 +-
+ net/ipv4/netfilter/iptable_filter.c               |  2 +-
+ net/ipv4/netfilter/iptable_mangle.c               |  2 +-
+ net/ipv4/netfilter/iptable_nat.c                  |  2 +-
+ net/ipv4/netfilter/iptable_raw.c                  |  2 +-
+ net/ipv4/netfilter/iptable_security.c             |  2 +-
+ net/ipv6/netfilter/ip6table_filter.c              |  2 +-
+ net/ipv6/netfilter/ip6table_mangle.c              |  2 +-
+ net/ipv6/netfilter/ip6table_nat.c                 |  2 +-
+ net/ipv6/netfilter/ip6table_raw.c                 |  2 +-
+ net/ipv6/netfilter/ip6table_security.c            |  2 +-
+ scripts/coccinelle/api/ptr_ret.cocci              | 10 +++++-----
+ sound/soc/soc-io.c                                |  2 +-
+ 59 files changed, 82 insertions(+), 72 deletions(-)
+Merging aio/master (f30d704 aio: table lookup: verify ctx pointer)
+$ git merge --no-ff aio/master
+Auto-merging net/socket.c
+Auto-merging kernel/fork.c
+Auto-merging drivers/staging/lustre/lustre/llite/file.c
+Auto-merging drivers/staging/android/logger.c
+Merge made by the 'recursive' strategy.
+ drivers/staging/android/logger.c           |   2 +-
+ drivers/staging/lustre/lustre/llite/file.c |   4 +-
+ drivers/usb/gadget/inode.c                 |   9 +-
+ fs/aio.c                                   | 718 ++++++++++++++++++-----------
+ fs/anon_inodes.c                           |  66 +++
+ fs/block_dev.c                             |   2 +-
+ fs/nfs/direct.c                            |   1 -
+ fs/ocfs2/file.c                            |   6 +-
+ fs/read_write.c                            |   3 -
+ fs/udf/file.c                              |   2 +-
+ include/linux/aio.h                        |  21 +-
+ include/linux/anon_inodes.h                |   3 +
+ include/linux/migrate.h                    |   3 +
+ include/linux/mm_types.h                   |   5 +-
+ kernel/fork.c                              |   2 +-
+ mm/migrate.c                               |   2 +-
+ mm/page_io.c                               |   1 -
+ net/socket.c                               |  15 +-
+ 18 files changed, 552 insertions(+), 313 deletions(-)
+Merging scsi-post-merge/merge-base:master (65112dc Merge git://git.samba.org/sfrench/cifs-2.6)
+Merging akpm-current/current (7f9cfd1 lz4: fix compression/decompression signedness mismatch)
+$ git merge akpm-current/current
+Auto-merging net/socket.c
+Auto-merging mm/slub.c
+Auto-merging mm/oom_kill.c
+Auto-merging lib/Kconfig.debug
+Auto-merging kernel/watchdog.c
+Auto-merging kernel/smp.c
+Auto-merging kernel/fork.c
+Auto-merging init/do_mounts.c
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/mm.h
+Auto-merging include/linux/binfmts.h
+Auto-merging fs/ocfs2/file.c
+Auto-merging fs/ocfs2/dlm/dlmrecovery.c
+Auto-merging fs/ocfs2/dlm/dlmmaster.c
+Auto-merging fs/ocfs2/cluster/heartbeat.c
+Auto-merging fs/binfmt_elf.c
+Auto-merging drivers/isdn/mISDN/core.c
+Auto-merging block/partitions/check.c
+Auto-merging block/partitions/Makefile
+Auto-merging arch/tile/mm/fault.c
+Auto-merging arch/s390/Kconfig
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/block/cmdline-partition.txt          |   40 +
+ .../devicetree/bindings/rtc/moxa,moxart-rtc.txt    |   17 +
+ Documentation/devicetree/bindings/rtc/rtc-omap.txt |    6 +-
+ .../filesystems/ramfs-rootfs-initramfs.txt         |    4 +
+ Documentation/target/tcm_mod_builder.py            |    2 +-
+ Documentation/trace/ftrace.txt                     |    4 +-
+ MAINTAINERS                                        |  127 +-
+ arch/Kconfig                                       |    6 +
+ arch/alpha/lib/csum_partial_copy.c                 |    5 +
+ arch/alpha/mm/fault.c                              |    7 +-
+ arch/arc/mm/fault.c                                |   11 +-
+ arch/arm/mm/fault.c                                |   23 +-
+ arch/arm64/mm/fault.c                              |   31 +-
+ arch/avr32/mm/fault.c                              |    4 +-
+ arch/cris/mm/fault.c                               |    6 +-
+ arch/frv/mm/fault.c                                |   10 +-
+ arch/hexagon/Kconfig                               |    1 +
+ arch/hexagon/mm/vm_fault.c                         |    6 +-
+ arch/ia64/mm/fault.c                               |    6 +-
+ arch/m32r/mm/fault.c                               |   10 +-
+ arch/m68k/mm/fault.c                               |    2 +
+ arch/metag/mm/fault.c                              |    6 +-
+ arch/microblaze/Kconfig                            |    2 +-
+ arch/microblaze/mm/fault.c                         |    7 +-
+ arch/mips/mm/fault.c                               |    8 +-
+ arch/mn10300/mm/fault.c                            |    2 +
+ arch/openrisc/Kconfig                              |    1 +
+ arch/openrisc/mm/fault.c                           |    1 +
+ arch/parisc/mm/fault.c                             |    7 +-
+ arch/powerpc/mm/fault.c                            |    7 +-
+ arch/s390/Kconfig                                  |    3 +-
+ arch/s390/include/asm/sclp.h                       |    1 +
+ arch/s390/kernel/crash_dump.c                      |  219 +-
+ arch/s390/mm/fault.c                               |    2 +
+ arch/score/Kconfig                                 |    2 +
+ arch/score/mm/fault.c                              |   13 +-
+ arch/sh/kernel/process_64.c                        |    4 +-
+ arch/sh/mm/fault.c                                 |    9 +-
+ arch/sparc/kernel/sys_sparc32.c                    |   12 +-
+ arch/sparc/mm/fault_32.c                           |   12 +-
+ arch/sparc/mm/fault_64.c                           |    6 +-
+ arch/tile/mm/fault.c                               |   13 +-
+ arch/um/kernel/trap.c                              |   22 +-
+ arch/unicore32/mm/fault.c                          |   22 +-
+ arch/x86/include/asm/e820.h                        |    2 +
+ arch/x86/include/asm/pgtable-2level.h              |   48 +-
+ arch/x86/include/asm/pgtable-3level.h              |    3 +
+ arch/x86/include/asm/pgtable.h                     |   30 +
+ arch/x86/include/asm/pgtable_types.h               |   17 +-
+ arch/x86/include/asm/tlbflush.h                    |   37 +-
+ arch/x86/kernel/cpu/mtrr/generic.c                 |    2 +
+ arch/x86/kernel/e820.c                             |   72 +-
+ arch/x86/kernel/sys_x86_64.c                       |    2 +-
+ arch/x86/mm/fault.c                                |   43 +-
+ arch/x86/mm/mmap.c                                 |    2 +-
+ arch/x86/mm/tlb.c                                  |   14 +-
+ arch/x86/platform/efi/efi.c                        |   15 +-
+ arch/xtensa/mm/fault.c                             |    2 +
+ block/blk-ioc.c                                    |    2 +-
+ block/blk-sysfs.c                                  |    2 +-
+ block/compat_ioctl.c                               |    2 +-
+ block/genhd.c                                      |    2 +-
+ block/partitions/Kconfig                           |    6 +
+ block/partitions/Makefile                          |    1 +
+ block/partitions/check.c                           |    4 +
+ block/partitions/cmdline.c                         |  326 +++
+ block/partitions/cmdline.h                         |    2 +
+ drivers/atm/he.c                                   |   13 +-
+ drivers/base/node.c                                |    6 -
+ drivers/block/aoe/aoe.h                            |    4 +-
+ drivers/block/aoe/aoeblk.c                         |  101 +-
+ drivers/block/aoe/aoecmd.c                         |   17 +-
+ drivers/block/aoe/aoedev.c                         |   16 +-
+ drivers/block/osdblk.c                             |    2 +-
+ drivers/block/pktcdvd.c                            |  278 +--
+ drivers/block/rbd.c                                |    2 +-
+ drivers/block/xen-blkback/xenbus.c                 |    2 +-
+ drivers/firmware/dmi_scan.c                        |   73 +-
+ drivers/firmware/google/gsmi.c                     |    2 +-
+ drivers/gpu/drm/cirrus/cirrus_mode.c               |    4 +-
+ drivers/gpu/drm/drm_fb_helper.c                    |    8 +
+ drivers/gpu/drm/nouveau/nouveau_acpi.c             |    5 +
+ drivers/infiniband/core/cm.c                       |    5 +-
+ drivers/isdn/hisax/amd7930_fn.c                    |    4 +-
+ drivers/isdn/hisax/avm_pci.c                       |    4 +-
+ drivers/isdn/hisax/config.c                        |    2 +-
+ drivers/isdn/hisax/diva.c                          |    4 +-
+ drivers/isdn/hisax/elsa.c                          |    2 +-
+ drivers/isdn/hisax/elsa_ser.c                      |    2 +-
+ drivers/isdn/hisax/hfc_pci.c                       |    2 +-
+ drivers/isdn/hisax/hfc_sx.c                        |    2 +-
+ drivers/isdn/hisax/hscx_irq.c                      |    4 +-
+ drivers/isdn/hisax/icc.c                           |    4 +-
+ drivers/isdn/hisax/ipacx.c                         |    8 +-
+ drivers/isdn/hisax/isac.c                          |    4 +-
+ drivers/isdn/hisax/isar.c                          |    6 +-
+ drivers/isdn/hisax/jade.c                          |   18 +-
+ drivers/isdn/hisax/jade_irq.c                      |    4 +-
+ drivers/isdn/hisax/l3_1tr6.c                       |   50 +-
+ drivers/isdn/hisax/netjet.c                        |    2 +-
+ drivers/isdn/hisax/q931.c                          |    6 +-
+ drivers/isdn/hisax/w6692.c                         |    8 +-
+ drivers/isdn/mISDN/core.c                          |    6 +
+ drivers/isdn/mISDN/core.h                          |    1 +
+ drivers/isdn/mISDN/socket.c                        |    9 +
+ drivers/memstick/core/Kconfig                      |   12 +
+ drivers/memstick/core/Makefile                     |    2 +-
+ drivers/memstick/core/ms_block.c                   | 2385 ++++++++++++++++++++
+ drivers/memstick/core/ms_block.h                   |  290 +++
+ drivers/misc/ti-st/st_core.c                       |    2 +-
+ drivers/net/ethernet/ibm/ehea/ehea_main.c          |   14 +-
+ drivers/net/irda/donauboe.c                        |   15 +-
+ drivers/pcmcia/pd6729.c                            |   13 +-
+ drivers/pcmcia/yenta_socket.c                      |   16 +-
+ drivers/rtc/Kconfig                                |    9 +
+ drivers/rtc/Makefile                               |    1 +
+ drivers/rtc/rtc-hid-sensor-time.c                  |   16 +-
+ drivers/rtc/rtc-moxart.c                           |  330 +++
+ drivers/rtc/rtc-omap.c                             |   60 +-
+ drivers/rtc/rtc-pcf2127.c                          |    6 -
+ drivers/s390/char/zcore.c                          |    6 +-
+ drivers/scsi/a100u2w.c                             |   12 +-
+ drivers/scsi/dc395x.c                              |   24 +-
+ drivers/scsi/dmx3191d.c                            |   13 +-
+ drivers/scsi/initio.c                              |   13 +-
+ drivers/scsi/mvumi.c                               |   20 +-
+ drivers/video/acornfb.c                            |  266 +--
+ drivers/video/acornfb.h                            |   29 -
+ drivers/video/cyber2000fb.c                        |    3 +
+ drivers/w1/w1.c                                    |   12 +-
+ drivers/watchdog/hpwdt.c                           |    6 +-
+ fs/autofs4/autofs_i.h                              |    4 +-
+ fs/autofs4/dev-ioctl.c                             |   16 +-
+ fs/autofs4/inode.c                                 |   33 +-
+ fs/autofs4/waitq.c                                 |   16 +-
+ fs/binfmt_elf.c                                    |   21 +-
+ fs/eventpoll.c                                     |   34 +-
+ fs/exec.c                                          |  120 +-
+ fs/fat/file.c                                      |  108 +-
+ fs/fat/inode.c                                     |   54 +
+ fs/file_table.c                                    |    3 +-
+ fs/fscache/page.c                                  |    2 +-
+ fs/hfsplus/Kconfig                                 |   18 +
+ fs/hfsplus/Makefile                                |    2 +
+ fs/hfsplus/acl.h                                   |   30 +
+ fs/hfsplus/dir.c                                   |    4 +
+ fs/hfsplus/hfsplus_fs.h                            |    1 +
+ fs/hfsplus/inode.c                                 |   11 +
+ fs/hfsplus/posix_acl.c                             |  274 +++
+ fs/hfsplus/xattr.c                                 |   62 +-
+ fs/hfsplus/xattr.h                                 |   33 +-
+ fs/hfsplus/xattr_security.c                        |   13 +
+ fs/namespace.c                                     |    2 +-
+ fs/ocfs2/acl.c                                     |    4 -
+ fs/ocfs2/alloc.c                                   |    2 +-
+ fs/ocfs2/aops.c                                    |    2 +-
+ fs/ocfs2/cluster/heartbeat.c                       |   14 +-
+ fs/ocfs2/cluster/tcp.c                             |   10 +-
+ fs/ocfs2/dir.c                                     |    6 +-
+ fs/ocfs2/dlm/dlmast.c                              |    8 +-
+ fs/ocfs2/dlm/dlmcommon.h                           |    4 +-
+ fs/ocfs2/dlm/dlmconvert.c                          |   11 +-
+ fs/ocfs2/dlm/dlmdebug.c                            |   15 +-
+ fs/ocfs2/dlm/dlmdomain.c                           |   20 +-
+ fs/ocfs2/dlm/dlmlock.c                             |    9 +-
+ fs/ocfs2/dlm/dlmmaster.c                           |   17 +-
+ fs/ocfs2/dlm/dlmrecovery.c                         |    5 +-
+ fs/ocfs2/dlm/dlmthread.c                           |   19 +-
+ fs/ocfs2/dlm/dlmunlock.c                           |    4 +-
+ fs/ocfs2/extent_map.c                              |   10 +-
+ fs/ocfs2/file.c                                    |   66 +-
+ fs/ocfs2/ioctl.c                                   |    2 +-
+ fs/ocfs2/journal.c                                 |   43 +-
+ fs/ocfs2/journal.h                                 |   11 +
+ fs/ocfs2/localalloc.c                              |    4 +-
+ fs/ocfs2/move_extents.c                            |    3 +-
+ fs/ocfs2/namei.c                                   |   12 +-
+ fs/ocfs2/ocfs2_trace.h                             |    2 +
+ fs/ocfs2/quota_global.c                            |    6 +-
+ fs/ocfs2/quota_local.c                             |   12 +-
+ fs/ocfs2/refcounttree.c                            |   10 +-
+ fs/proc/fd.c                                       |    2 -
+ fs/proc/meminfo.c                                  |    6 -
+ fs/proc/task_mmu.c                                 |   23 +-
+ fs/proc/vmcore.c                                   |  154 +-
+ fs/ramfs/inode.c                                   |   26 +-
+ include/asm-generic/pgtable.h                      |   30 +
+ include/linux/binfmts.h                            |    2 +-
+ include/linux/crash_dump.h                         |    9 +
+ include/linux/crc64_ecma.h                         |   56 +
+ include/linux/hardirq.h                            |    5 +
+ include/linux/huge_mm.h                            |    3 -
+ include/linux/init.h                               |    1 +
+ include/linux/interrupt.h                          |   23 +-
+ include/linux/ipc_namespace.h                      |    2 +-
+ include/linux/lz4.h                                |    8 +-
+ include/linux/memcontrol.h                         |  119 +-
+ include/linux/mempolicy.h                          |    9 +-
+ include/linux/mm.h                                 |    4 +-
+ include/linux/mmzone.h                             |    1 +
+ include/linux/page-flags.h                         |    4 +-
+ include/linux/pagemap.h                            |    1 +
+ include/linux/radix-tree.h                         |    1 +
+ include/linux/ramfs.h                              |    2 +-
+ include/linux/rbtree.h                             |   22 +
+ include/linux/res_counter.h                        |    2 +-
+ include/linux/sched.h                              |   16 +-
+ include/linux/smp.h                                |   85 +-
+ include/linux/swap.h                               |   52 +-
+ include/linux/swapops.h                            |    2 +
+ include/linux/syscalls.h                           |    5 +
+ include/linux/vm_event_item.h                      |    6 +
+ include/linux/vmstat.h                             |    3 +-
+ include/trace/events/kmem.h                        |   10 +-
+ init/do_mounts.c                                   |   45 +
+ ipc/msg.c                                          |   25 +-
+ ipc/namespace.c                                    |    7 +-
+ ipc/sem.c                                          |   24 +-
+ ipc/shm.c                                          |  255 ++-
+ ipc/util.c                                         |   82 +-
+ ipc/util.h                                         |   14 +-
+ kernel/fork.c                                      |   15 +-
+ kernel/gcov/fs.c                                   |    2 +-
+ kernel/hrtimer.c                                   |    2 +
+ kernel/kexec.c                                     |    5 +-
+ kernel/ksysfs.c                                    |    2 +-
+ kernel/modsign_pubkey.c                            |    6 +-
+ kernel/panic.c                                     |    8 +-
+ kernel/params.c                                    |   14 +-
+ kernel/res_counter.c                               |   25 +-
+ kernel/signal.c                                    |    4 +-
+ kernel/smp.c                                       |   18 +-
+ kernel/spinlock.c                                  |   14 +
+ kernel/time/timer_list.c                           |   41 +-
+ kernel/up.c                                        |   58 +-
+ kernel/watchdog.c                                  |   70 +-
+ lib/Kconfig                                        |    7 +
+ lib/Kconfig.debug                                  |    2 +-
+ lib/Makefile                                       |    1 +
+ lib/crc32.c                                        |   17 +-
+ lib/crc64_ecma.c                                   |  341 +++
+ lib/decompress_inflate.c                           |    2 +-
+ lib/genalloc.c                                     |    1 -
+ lib/lz4/lz4_decompress.c                           |    8 +-
+ lib/radix-tree.c                                   |   41 +-
+ lib/rbtree.c                                       |   40 +
+ lib/rbtree_test.c                                  |   12 +
+ mm/filemap.c                                       |   73 +-
+ mm/fremap.c                                        |   11 +-
+ mm/huge_memory.c                                   |  131 +-
+ mm/hugetlb.c                                       |  247 +-
+ mm/kmemleak.c                                      |    2 +-
+ mm/ksm.c                                           |    6 +-
+ mm/madvise.c                                       |   14 +-
+ mm/memcontrol.c                                    |  825 +++----
+ mm/memory.c                                        |   89 +-
+ mm/mempolicy.c                                     |   27 +-
+ mm/mmap.c                                          |   46 +-
+ mm/oom_kill.c                                      |    7 +-
+ mm/page-writeback.c                                |    3 -
+ mm/page_alloc.c                                    |  255 ++-
+ mm/pgtable-generic.c                               |   24 +
+ mm/rmap.c                                          |   32 +-
+ mm/shmem.c                                         |   17 +-
+ mm/slub.c                                          |    8 +-
+ mm/swap_state.c                                    |   67 +-
+ mm/swapfile.c                                      |  615 +++--
+ mm/util.c                                          |    5 +-
+ mm/vmalloc.c                                       |   17 +-
+ mm/vmscan.c                                        |   85 +-
+ mm/vmstat.c                                        |   89 +-
+ mm/zswap.c                                         |   18 +-
+ net/ipv4/tcp_memcontrol.c                          |   10 +-
+ net/socket.c                                       |   50 +-
+ scripts/checkpatch.pl                              |  227 +-
+ scripts/sortextable.c                              |   24 +
+ scripts/sortextable.h                              |   26 +-
+ tools/testing/selftests/Makefile                   |    1 +
+ tools/testing/selftests/powerpc/Makefile           |   39 +
+ tools/testing/selftests/powerpc/harness.c          |  105 +
+ tools/testing/selftests/powerpc/pmu/Makefile       |   23 +
+ .../selftests/powerpc/pmu/count_instructions.c     |  135 ++
+ tools/testing/selftests/powerpc/pmu/event.c        |  105 +
+ tools/testing/selftests/powerpc/pmu/event.h        |   39 +
+ tools/testing/selftests/powerpc/pmu/loop.S         |   46 +
+ tools/testing/selftests/powerpc/subunit.h          |   47 +
+ tools/testing/selftests/powerpc/utils.h            |   34 +
+ 287 files changed, 9293 insertions(+), 3035 deletions(-)
+ create mode 100644 Documentation/block/cmdline-partition.txt
+ create mode 100644 Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt
+ create mode 100644 block/partitions/cmdline.c
+ create mode 100644 block/partitions/cmdline.h
+ create mode 100644 drivers/memstick/core/ms_block.c
+ create mode 100644 drivers/memstick/core/ms_block.h
+ create mode 100644 drivers/rtc/rtc-moxart.c
+ create mode 100644 fs/hfsplus/acl.h
+ create mode 100644 fs/hfsplus/posix_acl.c
+ create mode 100644 include/linux/crc64_ecma.h
+ create mode 100644 lib/crc64_ecma.c
+ create mode 100644 tools/testing/selftests/powerpc/Makefile
+ create mode 100644 tools/testing/selftests/powerpc/harness.c
+ create mode 100644 tools/testing/selftests/powerpc/pmu/Makefile
+ create mode 100644 tools/testing/selftests/powerpc/pmu/count_instructions.c
+ create mode 100644 tools/testing/selftests/powerpc/pmu/event.c
+ create mode 100644 tools/testing/selftests/powerpc/pmu/event.h
+ create mode 100644 tools/testing/selftests/powerpc/pmu/loop.S
+ create mode 100644 tools/testing/selftests/powerpc/subunit.h
+ create mode 100644 tools/testing/selftests/powerpc/utils.h
+$ git clone -s -l -n -q . ../rebase-tmp
+$ cd ../rebase-tmp
+$ git checkout -b akpm remotes/origin/akpm/master
+Switched to a new branch 'akpm'
+$ git rebase --onto master remotes/origin/akpm/master-base
+First, rewinding head to replay your work on top of it...
+Applying: revert "SELinux: do not handle seclabel as a special flag"
+Applying: fs: bump inode and dentry counters to long
+Applying: super: fix calculation of shrinkable objects for small numbers
+Applying: dcache: convert dentry_stat.nr_unused to per-cpu counters
+Applying: dentry: move to per-sb LRU locks
+Applying: dcache: remove dentries from LRU before putting on dispose list
+Applying: mm: new shrinker API
+Applying: shrinker: convert superblock shrinkers to new API
+Applying: shrinker-convert-superblock-shrinkers-to-new-api-fix
+Applying: list: add a new LRU list type
+Applying: inode: convert inode lru list to generic lru list code.
+Applying: inode: move inode to a different list inside lock
+Applying: dcache: convert to use new lru list infrastructure
+Applying: list_lru: per-node list infrastructure
+Applying: list_lru: per-node list infrastructure fix
+Applying: list_lru: fix broken LRU_RETRY behaviour
+Applying: list_lru: per-node API
+Applying: list_lru: remove special case function list_lru_dispose_all.
+Applying: shrinker: add node awareness
+Applying: vmscan: per-node deferred work
+Applying: fs: convert inode and dentry shrinking to be node aware
+Applying: xfs: convert buftarg LRU to generic code
+Applying: xfs-convert-buftarg-lru-to-generic-code-fix
+Applying: xfs: rework buffer dispose list tracking
+Applying: xfs: convert dquot cache lru to list_lru
+Applying: xfs-convert-dquot-cache-lru-to-list_lru-fix
+Applying: xfs: fix dquot isolation hang
+Applying: fs: convert fs shrinkers to new scan/count API
+Applying: fs-convert-fs-shrinkers-to-new-scan-count-api-fix
+Applying: UBIFS: signedness bug in ubifs_shrink_count()
+Applying: drivers: convert shrinkers to new count/scan API
+Applying: drivers-convert-shrinkers-to-new-count-scan-api-fix
+Applying: drivers-convert-shrinkers-to-new-count-scan-api-fix-2
+Applying: i915: bail out earlier when shrinker cannot acquire mutex
+Applying: shrinker: convert remaining shrinkers to count/scan API
+Applying: shrinker-convert-remaining-shrinkers-to-count-scan-api-fix
+Applying: hugepage: convert huge zero page shrinker to new shrinker API
+Applying: hugepage-convert-huge-zero-page-shrinker-to-new-shrinker-api-fix
+Applying: shrinker: Kill old ->shrink API.
+Applying: shrinker-kill-old-shrink-api-fix
+Applying: list_lru: dynamically adjust node arrays
+Applying: super: fix for destroy lrus
+Applying: staging/lustre/ldlm: convert to shrinkers to count/scan API
+Applying: staging/lustre/obdclass: convert lu_object shrinker to count/scan API
+Applying: staging/lustre/ptlrpc: convert to new shrinker API
+Applying: staging/lustre/libcfs: cleanup linux-mem.h
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm/master
+From ../rebase-tmp
+ + 07928e8...89b1cb8 akpm       -> akpm/master  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm/master (89b1cb8 staging/lustre/libcfs: cleanup linux-mem.h)
+$ git merge --no-ff akpm/master
+Merge made by the 'recursive' strategy.
+ arch/x86/kvm/mmu.c                                 |  25 +-
+ drivers/gpu/drm/i915/i915_dma.c                    |   4 +-
+ drivers/gpu/drm/i915/i915_gem.c                    |  82 ++++--
+ drivers/gpu/drm/ttm/ttm_page_alloc.c               |  44 ++--
+ drivers/gpu/drm/ttm/ttm_page_alloc_dma.c           |  51 ++--
+ drivers/md/bcache/btree.c                          |  43 +--
+ drivers/md/bcache/sysfs.c                          |   2 +-
+ drivers/md/dm-bufio.c                              |  64 +++--
+ drivers/staging/android/ashmem.c                   |  44 ++--
+ drivers/staging/android/lowmemorykiller.c          |  43 +--
+ .../lustre/include/linux/libcfs/linux/linux-mem.h  |  38 ---
+ drivers/staging/lustre/lustre/ldlm/ldlm_pool.c     | 148 ++++++-----
+ drivers/staging/lustre/lustre/obdclass/lu_object.c |  98 +++----
+ drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c    |  76 +++---
+ drivers/staging/zcache/zcache-main.c               |  29 ++-
+ fs/dcache.c                                        | 279 ++++++++++++--------
+ fs/drop_caches.c                                   |   1 +
+ fs/ext4/extents_status.c                           |  25 +-
+ fs/gfs2/glock.c                                    |  30 ++-
+ fs/gfs2/main.c                                     |   3 +-
+ fs/gfs2/quota.c                                    |  18 +-
+ fs/gfs2/quota.h                                    |   6 +-
+ fs/inode.c                                         | 193 ++++++--------
+ fs/internal.h                                      |   6 +-
+ fs/mbcache.c                                       |  49 ++--
+ fs/nfs/dir.c                                       |  16 +-
+ fs/nfs/internal.h                                  |   6 +-
+ fs/nfs/super.c                                     |   3 +-
+ fs/nfsd/nfscache.c                                 |  32 ++-
+ fs/quota/dquot.c                                   |  34 +--
+ fs/super.c                                         | 111 +++++---
+ fs/ubifs/shrinker.c                                |  29 ++-
+ fs/ubifs/super.c                                   |   3 +-
+ fs/ubifs/ubifs.h                                   |   5 +-
+ fs/xfs/xfs_buf.c                                   | 253 +++++++++---------
+ fs/xfs/xfs_buf.h                                   |  17 +-
+ fs/xfs/xfs_dquot.c                                 |   7 +-
+ fs/xfs/xfs_icache.c                                |   4 +-
+ fs/xfs/xfs_icache.h                                |   2 +-
+ fs/xfs/xfs_qm.c                                    | 287 +++++++++++----------
+ fs/xfs/xfs_qm.h                                    |   4 +-
+ fs/xfs/xfs_super.c                                 |  12 +-
+ include/linux/dcache.h                             |  14 +-
+ include/linux/fs.h                                 |  25 +-
+ include/linux/list_lru.h                           | 131 ++++++++++
+ include/linux/shrinker.h                           |  54 +++-
+ include/trace/events/vmscan.h                      |   4 +-
+ include/uapi/linux/fs.h                            |   6 +-
+ kernel/sysctl.c                                    |   6 +-
+ mm/Makefile                                        |   2 +-
+ mm/huge_memory.c                                   |  17 +-
+ mm/list_lru.c                                      | 139 ++++++++++
+ mm/memory-failure.c                                |   2 +
+ mm/vmscan.c                                        | 241 +++++++++--------
+ net/sunrpc/auth.c                                  |  41 ++-
+ security/selinux/hooks.c                           |   3 +
+ security/selinux/include/security.h                |   2 +-
+ 57 files changed, 1773 insertions(+), 1140 deletions(-)
+ create mode 100644 include/linux/list_lru.h
+ create mode 100644 mm/list_lru.c
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 0000000..227af12
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,4 @@
+Importing jdelvare-hwmon based on 496322bc91e35007ed754184dcd447a02b6dd685
+Unchanged quilt series jdelvare-hwmon
+Importing device-mapper based on v3.11-rc1
+Unchanged quilt series device-mapper
diff --git a/arch/Kconfig b/arch/Kconfig
index 8d2ae24..1feb169 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -407,6 +407,12 @@ config CLONE_BACKWARDS2
 	help
 	  Architecture has the first two arguments of clone(2) swapped.
 
+config CLONE_BACKWARDS3
+	bool
+	help
+	  Architecture has tls passed as the 3rd argument of clone(2),
+	  not the 5th one.
+
 config ODD_RT_SIGACTION
 	bool
 	help
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index 40736da..ffb19b7 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -338,6 +338,11 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len,
 	unsigned long doff = 7 & (unsigned long) dst;
 
 	if (len) {
+		if (!access_ok(VERIFY_READ, src, len)) {
+			*errp = -EFAULT;
+			memset(dst, 0, len);
+			return sum;
+		}
 		if (!doff) {
 			if (!soff)
 				checksum = csum_partial_cfu_aligned(
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 0c4132d..98838a0 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -89,8 +89,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
 	const struct exception_table_entry *fixup;
 	int fault, si_code = SEGV_MAPERR;
 	siginfo_t info;
-	unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-			      (cause > 0 ? FAULT_FLAG_WRITE : 0));
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	/* As of EV6, a load into $31/$f31 is a prefetch, and never faults
 	   (or is suppressed by the PALcode).  Support that for older CPUs
@@ -115,7 +114,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
 	if (address >= TASK_SIZE)
 		goto vmalloc_fault;
 #endif
-
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -142,6 +142,7 @@ retry:
 	} else {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	}
 
 	/* If for any reason at all we couldn't handle the fault,
diff --git a/arch/arc/boot/.gitignore b/arch/arc/boot/.gitignore
new file mode 100644
index 0000000..5d65b54
--- /dev/null
+++ b/arch/arc/boot/.gitignore
@@ -0,0 +1 @@
+*.dtb*
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index df57611..8840810 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -365,7 +365,7 @@
  * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
  *
  * Before saving the full regfile - this reg is restored back, only
- * to be saved again on kernel mode stack, as part of ptregs.
+ * to be saved again on kernel mode stack, as part of pt_regs.
  *-------------------------------------------------------------*/
 .macro EXCPN_PROLOG_FREEUP_REG	reg
 #ifdef CONFIG_SMP
@@ -384,6 +384,28 @@
 .endm
 
 /*--------------------------------------------------------------
+ * Exception Entry prologue
+ * -Switches stack to K mode (if not already)
+ * -Saves the register file
+ *
+ * After this it is safe to call the "C" handlers
+ *-------------------------------------------------------------*/
+.macro EXCEPTION_PROLOGUE
+
+	/* Need at least 1 reg to code the early exception prologue */
+	EXCPN_PROLOG_FREEUP_REG r9
+
+	/* U/K mode at time of exception (stack not switched if already K) */
+	lr  r9, [erstatus]
+
+	/* ARC700 doesn't provide auto-stack switching */
+	SWITCH_TO_KERNEL_STK
+
+	/* save the regfile */
+	SAVE_ALL_SYS
+.endm
+
+/*--------------------------------------------------------------
  * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc)
  * Requires SP to be already switched to kernel mode Stack
  * sp points to the next free element on the stack at exit of this macro.
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
index d99f79b..b68b53f 100644
--- a/arch/arc/include/asm/irqflags.h
+++ b/arch/arc/include/asm/irqflags.h
@@ -157,13 +157,6 @@ static inline void arch_unmask_irq(unsigned int irq)
 	flag	\scratch
 .endm
 
-.macro IRQ_DISABLE_SAVE  scratch, save
-	lr	\scratch, [status32]
-	mov	\save, \scratch		/* Make a copy */
-	bic	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
-	flag	\scratch
-.endm
-
 .macro IRQ_ENABLE  scratch
 	lr	\scratch, [status32]
 	or	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h
index 7c03fe6..baf923f 100644
--- a/arch/arc/include/asm/mmu.h
+++ b/arch/arc/include/asm/mmu.h
@@ -32,6 +32,8 @@
 /* Error code if probe fails */
 #define TLB_LKUP_ERR		0x80000000
 
+#define TLB_DUP_ERR	(TLB_LKUP_ERR | 0x00000001)
+
 /* TLB Commands */
 #define TLBWrite    0x1
 #define TLBRead     0x2
@@ -46,10 +48,7 @@
 #ifndef __ASSEMBLY__
 
 typedef struct {
-	unsigned long asid;	/* Pvt Addr-Space ID for mm */
-#ifdef CONFIG_ARC_TLB_DBG
-	struct task_struct *tsk;
-#endif
+	unsigned long asid[NR_CPUS];	/* Hw PID + Generation cycle */
 } mm_context_t;
 
 #ifdef CONFIG_ARC_DBG_TLB_PARANOIA
diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h
index 0d71fb1..97949e7 100644
--- a/arch/arc/include/asm/mmu_context.h
+++ b/arch/arc/include/asm/mmu_context.h
@@ -30,99 +30,67 @@
  * "Fast Context Switch" i.e. no TLB flush on ctxt-switch
  *
  * Linux assigns each task a unique ASID. A simple round-robin allocation
- * of H/w ASID is done using software tracker @asid_cache.
+ * of H/w ASID is done using software tracker @asid_cpu.
  * When it reaches max 255, the allocation cycle starts afresh by flushing
  * the entire TLB and wrapping ASID back to zero.
  *
- * For book-keeping, Linux uses a couple of data-structures:
- *  -mm_struct has an @asid field to keep a note of task's ASID (needed at the
- *   time of say switch_mm( )
- *  -An array of mm structs @asid_mm_map[] for asid->mm the reverse mapping,
- *  given an ASID, finding the mm struct associated.
- *
- * The round-robin allocation algorithm allows for ASID stealing.
- * If asid tracker is at "x-1", a new req will allocate "x", even if "x" was
- * already assigned to another (switched-out) task. Obviously the prev owner
- * is marked with an invalid ASID to make it request for a new ASID when it
- * gets scheduled next time. However its TLB entries (with ASID "x") could
- * exist, which must be cleared before the same ASID is used by the new owner.
- * Flushing them would be plausible but costly solution. Instead we force a
- * allocation policy quirk, which ensures that a stolen ASID won't have any
- * TLB entries associates, alleviating the need to flush.
- * The quirk essentially is not allowing ASID allocated in prev cycle
- * to be used past a roll-over in the next cycle.
- * When this happens (i.e. task ASID > asid tracker), task needs to refresh
- * its ASID, aligning it to current value of tracker. If the task doesn't get
- * scheduled past a roll-over, hence its ASID is not yet realigned with
- * tracker, such ASID is anyways safely reusable because it is
- * gauranteed that TLB entries with that ASID wont exist.
+ * A new allocation cycle, post rollover, could potentially reassign an ASID
+ * to a different task. Thus the rule is to refresh the ASID in a new cycle.
+ * The 32 bit @asid_cpu (and mm->asid) have 8 bits MMU PID and rest 24 bits
+ * serve as cycle/generation indicator and natural 32 bit unsigned math
+ * automagically increments the generation when lower 8 bits rollover.
  */
 
-#define FIRST_ASID  0
-#define MAX_ASID    255			/* 8 bit PID field in PID Aux reg */
-#define NO_ASID     (MAX_ASID + 1)	/* ASID Not alloc to mmu ctxt */
-#define NUM_ASID    ((MAX_ASID - FIRST_ASID) + 1)
+#define MM_CTXT_ASID_MASK	0x000000ff /* MMU PID reg :8 bit PID */
+#define MM_CTXT_CYCLE_MASK	(~MM_CTXT_ASID_MASK)
+
+#define MM_CTXT_FIRST_CYCLE	(MM_CTXT_ASID_MASK + 1)
+#define MM_CTXT_NO_ASID		0UL
 
-/* ASID to mm struct mapping */
-extern struct mm_struct *asid_mm_map[NUM_ASID + 1];
+#define asid_mm(mm, cpu)	mm->context.asid[cpu]
+#define hw_pid(mm, cpu)		(asid_mm(mm, cpu) & MM_CTXT_ASID_MASK)
 
-extern int asid_cache;
+DECLARE_PER_CPU(unsigned int, asid_cache);
+#define asid_cpu(cpu)		per_cpu(asid_cache, cpu)
 
 /*
- * Assign a new ASID to task. If the task already has an ASID, it is
- * relinquished.
+ * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle)
+ * Also set the MMU PID register to existing/updated ASID
  */
 static inline void get_new_mmu_context(struct mm_struct *mm)
 {
-	struct mm_struct *prev_owner;
+	const unsigned int cpu = smp_processor_id();
 	unsigned long flags;
 
 	local_irq_save(flags);
 
 	/*
-	 * Relinquish the currently owned ASID (if any).
-	 * Doing unconditionally saves a cmp-n-branch; for already unused
-	 * ASID slot, the value was/remains NULL
+	 * Move to new ASID if it was not from current alloc cycle/generation.
+	 * Callers needing new ASID unconditionally, independent of alloc-cycle
+	 * (local_flush_tlb_mm() for forking  parent) first need to destroy the
+	 * context, setting it to invalid value, which the check below would
+	 * catch too
 	 */
-	asid_mm_map[mm->context.asid] = (struct mm_struct *)NULL;
+	if (!((asid_mm(mm, cpu) ^ asid_cpu(cpu)) & MM_CTXT_CYCLE_MASK))
+		goto set_hw;
 
 	/* move to new ASID */
-	if (++asid_cache > MAX_ASID) {	/* ASID roll-over */
-		asid_cache = FIRST_ASID;
-		flush_tlb_all();
+	if (!(++asid_cpu(cpu) & MM_CTXT_ASID_MASK)) {	/* ASID roll-over */
+		local_flush_tlb_all();
 	}
 
-	/*
-	 * Is next ASID already owned by some-one else (we are stealing it).
-	 * If so, let the orig owner be aware of this, so when it runs, it
-	 * asks for a brand new ASID. This would only happen for a long-lived
-	 * task with ASID from prev allocation cycle (before ASID roll-over).
-	 *
-	 * This might look wrong - if we are re-using some other task's ASID,
-	 * won't we use it's stale TLB entries too. Actually switch_mm( ) takes
-	 * care of such a case: it ensures that task with ASID from prev alloc
-	 * cycle, when scheduled will refresh it's ASID: see switch_mm( ) below
-	 * The stealing scenario described here will only happen if that task
-	 * didn't get a chance to refresh it's ASID - implying stale entries
-	 * won't exist.
+	/* Above was rollover of 8 bit ASID in 32 bit container.
+	 * If the container itself wrapped around, set it to a non zero
+	 * "generation" to distinguish from no context
 	 */
-	prev_owner = asid_mm_map[asid_cache];
-	if (prev_owner)
-		prev_owner->context.asid = NO_ASID;
+	if (!asid_cpu(cpu))
+		asid_cpu(cpu) = MM_CTXT_FIRST_CYCLE;
 
 	/* Assign new ASID to tsk */
-	asid_mm_map[asid_cache] = mm;
-	mm->context.asid = asid_cache;
-
-#ifdef CONFIG_ARC_TLB_DBG
-	pr_info("ARC_TLB_DBG: NewMM=0x%x OldMM=0x%x task_struct=0x%x Task: %s,"
-	       " pid:%u, assigned asid:%lu\n",
-	       (unsigned int)mm, (unsigned int)prev_owner,
-	       (unsigned int)(mm->context.tsk), (mm->context.tsk)->comm,
-	       (mm->context.tsk)->pid, mm->context.asid);
-#endif
+	asid_mm(mm, cpu) = asid_cpu(cpu);
 
-	write_aux_reg(ARC_REG_PID, asid_cache | MMU_ENABLE);
+set_hw:
+	write_aux_reg(ARC_REG_PID, hw_pid(mm, cpu) | MMU_ENABLE);
 
 	local_irq_restore(flags);
 }
@@ -134,60 +102,66 @@ static inline void get_new_mmu_context(struct mm_struct *mm)
 static inline int
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
-	mm->context.asid = NO_ASID;
-#ifdef CONFIG_ARC_TLB_DBG
-	mm->context.tsk = tsk;
-#endif
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		asid_mm(mm, i) = MM_CTXT_NO_ASID;
+
 	return 0;
 }
 
+static inline void destroy_context(struct mm_struct *mm)
+{
+	asid_mm(mm, smp_processor_id()) = MM_CTXT_NO_ASID;
+}
+
 /* Prepare the MMU for task: setup PID reg with allocated ASID
     If task doesn't have an ASID (never alloc or stolen, get a new ASID)
 */
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk)
 {
-#ifndef CONFIG_SMP
-	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
-	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
-#endif
+	int migrating = 0;
+
+#ifdef CONFIG_SMP
+	const int cpu = smp_processor_id();
 
 	/*
-	 * Get a new ASID if task doesn't have a valid one. Possible when
-	 *  -task never had an ASID (fresh after fork)
-	 *  -it's ASID was stolen - past an ASID roll-over.
-	 *  -There's a third obscure scenario (if this task is running for the
-	 *   first time afer an ASID rollover), where despite having a valid
-	 *   ASID, we force a get for new ASID - see comments at top.
-	 *
-	 * Both the non-alloc scenario and first-use-after-rollover can be
-	 * detected using the single condition below:  NO_ASID = 256
-	 * while asid_cache is always a valid ASID value (0-255).
+	 * If @next is migrating to a different CPU, force an ASID refresh (by
+	 * 	relinquishing current value as required by new implementation
+	 * 	of get_new_mmu_context()
+	 * Use Case:
+	 *	Task t1 migrates to a different core, forks, migrates back to
+	 *	orig core. COW semantics requires it to have a new ASID now
+	 *	so that pre-fork TLB entries can't be used.
 	 */
-	if (next->context.asid > asid_cache) {
-		get_new_mmu_context(next);
-	} else {
-		/*
-		 * XXX: This will never happen given the chks above
-		 * BUG_ON(next->context.asid > MAX_ASID);
-		 */
-		write_aux_reg(ARC_REG_PID, next->context.asid | MMU_ENABLE);
-	}
-
-}
-
-static inline void destroy_context(struct mm_struct *mm)
-{
-	unsigned long flags;
+	cpumask_clear_cpu(cpu, mm_cpumask(prev));
+	migrating = !cpumask_test_and_set_cpu(cpu, mm_cpumask(next));
+	if (migrating)
+		destroy_context(next);
+#endif
 
-	local_irq_save(flags);
+	/* threads of same process (and not migrating cores in SMP) */
+	if ((prev == next) && !migrating)
+		return;
 
-	asid_mm_map[mm->context.asid] = NULL;
-	mm->context.asid = NO_ASID;
+#ifndef CONFIG_SMP
+	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
+	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
+#endif
 
-	local_irq_restore(flags);
+	get_new_mmu_context(next);
 }
 
+/*
+ * Called at the time of execve() to get a new ASID
+ * Note the subtlety here: get_new_mmu_context() behaves differently here
+ * vs. in switch_mm(). Here it always returns a new ASID, because mm has
+ * an unallocated "initial" value, while in latter, it moves to a new ASID,
+ * only if it was unallocated
+ */
+#define activate_mm(prev, next)		switch_mm(prev, next, NULL)
+
 /* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping
  * for retiring-mm. However destroy_context( ) still needs to do that because
  * between mm_release( ) = >deactive_mm( ) and
@@ -197,17 +171,6 @@ static inline void destroy_context(struct mm_struct *mm)
  */
 #define deactivate_mm(tsk, mm)   do { } while (0)
 
-static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
-{
-#ifndef CONFIG_SMP
-	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
-#endif
-
-	/* Unconditionally get a new ASID */
-	get_new_mmu_context(next);
-
-}
-
 #define enter_lazy_tlb(mm, tsk)
 
 #endif /* __ASM_ARC_MMU_CONTEXT_H */
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 4749a0e..6b0b7f7e 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -57,43 +57,31 @@
 
 #define _PAGE_ACCESSED      (1<<1)	/* Page is accessed (S) */
 #define _PAGE_CACHEABLE     (1<<2)	/* Page is cached (H) */
-#define _PAGE_U_EXECUTE     (1<<3)	/* Page has user execute perm (H) */
-#define _PAGE_U_WRITE       (1<<4)	/* Page has user write perm (H) */
-#define _PAGE_U_READ        (1<<5)	/* Page has user read perm (H) */
-#define _PAGE_K_EXECUTE     (1<<6)	/* Page has kernel execute perm (H) */
-#define _PAGE_K_WRITE       (1<<7)	/* Page has kernel write perm (H) */
-#define _PAGE_K_READ        (1<<8)	/* Page has kernel perm (H) */
-#define _PAGE_GLOBAL        (1<<9)	/* Page is global (H) */
-#define _PAGE_MODIFIED      (1<<10)	/* Page modified (dirty) (S) */
-#define _PAGE_FILE          (1<<10)	/* page cache/ swap (S) */
-#define _PAGE_PRESENT       (1<<11)	/* TLB entry is valid (H) */
+#define _PAGE_EXECUTE       (1<<3)	/* Page has user execute perm (H) */
+#define _PAGE_WRITE         (1<<4)	/* Page has user write perm (H) */
+#define _PAGE_READ          (1<<5)	/* Page has user read perm (H) */
+#define _PAGE_MODIFIED      (1<<6)	/* Page modified (dirty) (S) */
+#define _PAGE_FILE          (1<<7)	/* page cache/ swap (S) */
+#define _PAGE_GLOBAL        (1<<8)	/* Page is global (H) */
+#define _PAGE_PRESENT       (1<<10)	/* TLB entry is valid (H) */
 
-#else
+#else	/* MMU v3 onwards */
 
-/* PD1 */
 #define _PAGE_CACHEABLE     (1<<0)	/* Page is cached (H) */
-#define _PAGE_U_EXECUTE     (1<<1)	/* Page has user execute perm (H) */
-#define _PAGE_U_WRITE       (1<<2)	/* Page has user write perm (H) */
-#define _PAGE_U_READ        (1<<3)	/* Page has user read perm (H) */
-#define _PAGE_K_EXECUTE     (1<<4)	/* Page has kernel execute perm (H) */
-#define _PAGE_K_WRITE       (1<<5)	/* Page has kernel write perm (H) */
-#define _PAGE_K_READ        (1<<6)	/* Page has kernel perm (H) */
-#define _PAGE_ACCESSED      (1<<7)	/* Page is accessed (S) */
-
-/* PD0 */
+#define _PAGE_EXECUTE       (1<<1)	/* Page has user execute perm (H) */
+#define _PAGE_WRITE         (1<<2)	/* Page has user write perm (H) */
+#define _PAGE_READ          (1<<3)	/* Page has user read perm (H) */
+#define _PAGE_ACCESSED      (1<<4)	/* Page is accessed (S) */
+#define _PAGE_MODIFIED      (1<<5)	/* Page modified (dirty) (S) */
+#define _PAGE_FILE          (1<<6)	/* page cache/ swap (S) */
 #define _PAGE_GLOBAL        (1<<8)	/* Page is global (H) */
 #define _PAGE_PRESENT       (1<<9)	/* TLB entry is valid (H) */
-#define _PAGE_SHARED_CODE   (1<<10)	/* Shared Code page with cmn vaddr
+#define _PAGE_SHARED_CODE   (1<<11)	/* Shared Code page with cmn vaddr
 					   usable for shared TLB entries (H) */
-
-#define _PAGE_MODIFIED      (1<<11)	/* Page modified (dirty) (S) */
-#define _PAGE_FILE          (1<<12)	/* page cache/ swap (S) */
-
-#define _PAGE_SHARED_CODE_H (1<<31)	/* Hardware counterpart of above */
 #endif
 
-/* Kernel allowed all permissions for all pages */
-#define _K_PAGE_PERMS  (_PAGE_K_EXECUTE | _PAGE_K_WRITE | _PAGE_K_READ | \
+/* vmalloc permissions */
+#define _K_PAGE_PERMS  (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ | \
 			_PAGE_GLOBAL | _PAGE_PRESENT)
 
 #ifdef CONFIG_ARC_CACHE_PAGES
@@ -109,10 +97,6 @@
  */
 #define ___DEF (_PAGE_PRESENT | _PAGE_DEF_CACHEABLE)
 
-#define _PAGE_READ	(_PAGE_U_READ    | _PAGE_K_READ)
-#define _PAGE_WRITE	(_PAGE_U_WRITE   | _PAGE_K_WRITE)
-#define _PAGE_EXECUTE	(_PAGE_U_EXECUTE | _PAGE_K_EXECUTE)
-
 /* Set of bits not changed in pte_modify */
 #define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED)
 
@@ -126,8 +110,8 @@
 
 #define PAGE_SHARED	PAGE_U_W_R
 
-/* While kernel runs out of unstrslated space, vmalloc/modules use a chunk of
- * kernel vaddr space - visible in all addr spaces, but kernel mode only
+/* While kernel runs out of unstranslated space, vmalloc/modules use a chunk of
+ * user vaddr space - visible in all addr spaces, but kernel mode only
  * Thus Global, all-kernel-access, no-user-access, cached
  */
 #define PAGE_KERNEL          __pgprot(_K_PAGE_PERMS | _PAGE_DEF_CACHEABLE)
@@ -136,10 +120,9 @@
 #define PAGE_KERNEL_NO_CACHE __pgprot(_K_PAGE_PERMS)
 
 /* Masks for actual TLB "PD"s */
-#define PTE_BITS_IN_PD0	(_PAGE_GLOBAL | _PAGE_PRESENT)
-#define PTE_BITS_IN_PD1	(PAGE_MASK | _PAGE_CACHEABLE | \
-			 _PAGE_U_EXECUTE | _PAGE_U_WRITE | _PAGE_U_READ | \
-			 _PAGE_K_EXECUTE | _PAGE_K_WRITE | _PAGE_K_READ)
+#define PTE_BITS_IN_PD0		(_PAGE_GLOBAL | _PAGE_PRESENT)
+#define PTE_BITS_RWX		(_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
+#define PTE_BITS_NON_RWX_IN_PD1	(PAGE_MASK | _PAGE_CACHEABLE)
 
 /**************************************************************************
  * Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index c9938e7..1bfeec2 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -20,27 +20,17 @@ struct pt_regs {
 
 	/* Real registers */
 	long bta;	/* bta_l1, bta_l2, erbta */
-	long lp_start;
-	long lp_end;
-	long lp_count;
+
+	long lp_start, lp_end, lp_count;
+
 	long status32;	/* status32_l1, status32_l2, erstatus */
 	long ret;	/* ilink1, ilink2 or eret */
 	long blink;
 	long fp;
 	long r26;	/* gp */
-	long r12;
-	long r11;
-	long r10;
-	long r9;
-	long r8;
-	long r7;
-	long r6;
-	long r5;
-	long r4;
-	long r3;
-	long r2;
-	long r1;
-	long r0;
+
+	long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
+
 	long sp;	/* user/kernel sp depending on where we came from  */
 	long orig_r0;
 
@@ -70,19 +60,7 @@ struct pt_regs {
 /* Callee saved registers - need to be saved only when you are scheduled out */
 
 struct callee_regs {
-	long r25;
-	long r24;
-	long r23;
-	long r22;
-	long r21;
-	long r20;
-	long r19;
-	long r18;
-	long r17;
-	long r16;
-	long r15;
-	long r14;
-	long r13;
+	long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
 };
 
 #define instruction_pointer(regs)	((regs)->ret)
diff --git a/arch/arc/include/asm/tlbflush.h b/arch/arc/include/asm/tlbflush.h
index b2f9bc7..71c7b2e 100644
--- a/arch/arc/include/asm/tlbflush.h
+++ b/arch/arc/include/asm/tlbflush.h
@@ -18,11 +18,18 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
 void local_flush_tlb_range(struct vm_area_struct *vma,
 			   unsigned long start, unsigned long end);
 
-/* XXX: Revisit for SMP */
+#ifndef CONFIG_SMP
 #define flush_tlb_range(vma, s, e)	local_flush_tlb_range(vma, s, e)
 #define flush_tlb_page(vma, page)	local_flush_tlb_page(vma, page)
 #define flush_tlb_kernel_range(s, e)	local_flush_tlb_kernel_range(s, e)
 #define flush_tlb_all()			local_flush_tlb_all()
 #define flush_tlb_mm(mm)		local_flush_tlb_mm(mm)
-
+#else
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+							 unsigned long end);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+#endif /* CONFIG_SMP */
 #endif
diff --git a/arch/arc/kernel/.gitignore b/arch/arc/kernel/.gitignore
new file mode 100644
index 0000000..c5f676c
--- /dev/null
+++ b/arch/arc/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 1d71651..b908dde 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -267,12 +267,7 @@ ARC_EXIT handle_interrupt_level1
 
 ARC_ENTRY instr_service
 
-	EXCPN_PROLOG_FREEUP_REG r9
-
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	lr  r0, [efa]
 	mov r1, sp
@@ -289,15 +284,13 @@ ARC_EXIT instr_service
 
 ARC_ENTRY mem_service
 
-	EXCPN_PROLOG_FREEUP_REG r9
-
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	lr  r0, [efa]
 	mov r1, sp
+
+	FAKE_RET_FROM_EXCPN r9
+
 	bl  do_memory_error
 	b   ret_from_exception
 ARC_EXIT mem_service
@@ -308,11 +301,7 @@ ARC_EXIT mem_service
 
 ARC_ENTRY EV_MachineCheck
 
-	EXCPN_PROLOG_FREEUP_REG r9
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	lr  r2, [ecr]
 	lr  r0, [efa]
@@ -342,13 +331,7 @@ ARC_EXIT EV_MachineCheck
 
 ARC_ENTRY EV_TLBProtV
 
-	EXCPN_PROLOG_FREEUP_REG r9
-
-	;Which mode (user/kernel) was the system in when Exception occured
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	;---------(3) Save some more regs-----------------
 	;  vineetg: Mar 6th: Random Seg Fault issue #1
@@ -406,12 +389,7 @@ ARC_EXIT EV_TLBProtV
 ; ---------------------------------------------
 ARC_ENTRY EV_PrivilegeV
 
-	EXCPN_PROLOG_FREEUP_REG r9
-
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	lr  r0, [efa]
 	mov r1, sp
@@ -427,14 +405,13 @@ ARC_EXIT EV_PrivilegeV
 ; ---------------------------------------------
 ARC_ENTRY EV_Extension
 
-	EXCPN_PROLOG_FREEUP_REG r9
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	lr  r0, [efa]
 	mov r1, sp
+
+	FAKE_RET_FROM_EXCPN r9
+
 	bl  do_extension_fault
 	b   ret_from_exception
 ARC_EXIT EV_Extension
@@ -526,14 +503,7 @@ trap_with_param:
 
 ARC_ENTRY EV_Trap
 
-	; Need at least 1 reg to code the early exception prolog
-	EXCPN_PROLOG_FREEUP_REG r9
-
-	;Which mode (user/kernel) was the system in when intr occured
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	;------- (4) What caused the Trap --------------
 	lr     r12, [ecr]
@@ -642,6 +612,9 @@ resume_kernel_mode:
 
 #ifdef CONFIG_PREEMPT
 
+	; This is a must for preempt_schedule_irq()
+	IRQ_DISABLE	r9
+
 	; Can't preempt if preemption disabled
 	GET_CURR_THR_INFO_FROM_SP   r10
 	ld  r8, [r10, THREAD_INFO_PREEMPT_COUNT]
@@ -651,8 +624,6 @@ resume_kernel_mode:
 	ld  r9, [r10, THREAD_INFO_FLAGS]
 	bbit0  r9, TIF_NEED_RESCHED, restore_regs
 
-	IRQ_DISABLE	r9
-
 	; Invoke PREEMPTION
 	bl      preempt_schedule_irq
 
@@ -665,12 +636,11 @@ resume_kernel_mode:
 ;
 ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
 ; IRQ shd definitely not happen between now and rtie
+; All 2 entry points to here already disable interrupts
 
 restore_regs :
 
-	; Disable Interrupts while restoring reg-file back
-	; XXX can this be optimised out
-	IRQ_DISABLE_SAVE    r9, r10	;@r10 has prisitine (pre-disable) copy
+	lr	r10, [status32]
 
 	; Restore REG File. In case multiple Events outstanding,
 	; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index bca3052..482a42b 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -128,6 +128,7 @@ void start_kernel_secondary(void)
 	atomic_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
diff --git a/arch/arc/mm/Makefile b/arch/arc/mm/Makefile
index ac95cc2..6185612 100644
--- a/arch/arc/mm/Makefile
+++ b/arch/arc/mm/Makefile
@@ -8,3 +8,4 @@
 
 obj-y	:= extable.o ioremap.o dma.o fault.o init.o
 obj-y	+= tlb.o tlbex.o cache_arc700.o mmap.o
+obj-$(CONFIG_SMP)		+= tlbflush.o
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index 0fd1f0d..d63f3de 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -60,8 +60,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address)
 	siginfo_t info;
 	int fault, ret;
 	int write = regs->ecr_cause & ECR_C_PROTV_STORE;  /* ST/EX */
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				(write ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	/*
 	 * We fault-in kernel-space virtual memory on-demand. The
@@ -89,6 +88,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address)
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -117,12 +118,12 @@ good_area:
 	if (write) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
 
-survive:
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
@@ -201,10 +202,6 @@ no_context:
 	die("Oops", regs, address);
 
 out_of_memory:
-	if (is_global_init(tsk)) {
-		yield();
-		goto survive;
-	}
 	up_read(&mm->mmap_sem);
 
 	if (user_mode(regs)) {
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index a08ce71..81279ec 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -127,9 +127,8 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
 #endif
 
 #ifdef CONFIG_OF_FLATTREE
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
-	pr_err("%s(%lx, %lx)\n", __func__, start, end);
+	pr_err("%s(%llx, %llx)\n", __func__, start, end);
 }
 #endif /* CONFIG_OF_FLATTREE */
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 7957dc4..8fed015 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -52,6 +52,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/bug.h>
 #include <asm/arcregs.h>
 #include <asm/setup.h>
 #include <asm/mmu_context.h>
@@ -99,48 +100,45 @@
 
 
 /* A copy of the ASID from the PID reg is kept in asid_cache */
-int asid_cache = FIRST_ASID;
-
-/* ASID to mm struct mapping. We have one extra entry corresponding to
- * NO_ASID to save us a compare when clearing the mm entry for old asid
- * see get_new_mmu_context (asm-arc/mmu_context.h)
- */
-struct mm_struct *asid_mm_map[NUM_ASID + 1];
+DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE;
 
 /*
  * Utility Routine to erase a J-TLB entry
- * The procedure is to look it up in the MMU. If found, ERASE it by
- *  issuing a TlbWrite CMD with PD0 = PD1 = 0
+ * Caller needs to setup Index Reg (manually or via getIndex)
  */
-
-static void __tlb_entry_erase(void)
+static inline void __tlb_entry_erase(void)
 {
 	write_aux_reg(ARC_REG_TLBPD1, 0);
 	write_aux_reg(ARC_REG_TLBPD0, 0);
 	write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
 }
 
-static void tlb_entry_erase(unsigned int vaddr_n_asid)
+static inline unsigned int tlb_entry_lkup(unsigned long vaddr_n_asid)
 {
 	unsigned int idx;
 
-	/* Locate the TLB entry for this vaddr + ASID */
 	write_aux_reg(ARC_REG_TLBPD0, vaddr_n_asid);
+
 	write_aux_reg(ARC_REG_TLBCOMMAND, TLBProbe);
 	idx = read_aux_reg(ARC_REG_TLBINDEX);
 
+	return idx;
+}
+
+static void tlb_entry_erase(unsigned int vaddr_n_asid)
+{
+	unsigned int idx;
+
+	/* Locate the TLB entry for this vaddr + ASID */
+	idx = tlb_entry_lkup(vaddr_n_asid);
+
 	/* No error means entry found, zero it out */
 	if (likely(!(idx & TLB_LKUP_ERR))) {
 		__tlb_entry_erase();
-	} else {		/* Some sort of Error */
-
+	} else {
 		/* Duplicate entry error */
-		if (idx & 0x1) {
-			/* TODO we need to handle this case too */
-			pr_emerg("unhandled Duplicate flush for %x\n",
-			       vaddr_n_asid);
-		}
-		/* else entry not found so nothing to do */
+		WARN(idx == TLB_DUP_ERR, "Probe returned Dup PD for %x\n",
+					   vaddr_n_asid);
 	}
 }
 
@@ -159,7 +157,7 @@ static void utlb_invalidate(void)
 {
 #if (CONFIG_ARC_MMU_VER >= 2)
 
-#if (CONFIG_ARC_MMU_VER < 3)
+#if (CONFIG_ARC_MMU_VER == 2)
 	/* MMU v2 introduced the uTLB Flush command.
 	 * There was however an obscure hardware bug, where uTLB flush would
 	 * fail when a prior probe for J-TLB (both totally unrelated) would
@@ -182,6 +180,37 @@ static void utlb_invalidate(void)
 
 }
 
+static void tlb_entry_insert(unsigned int pd0, unsigned int pd1)
+{
+	unsigned int idx;
+
+	/*
+	 * First verify if entry for this vaddr+ASID already exists
+	 * This also sets up PD0 (vaddr, ASID..) for final commit
+	 */
+	idx = tlb_entry_lkup(pd0);
+
+	/*
+	 * If Not already present get a free slot from MMU.
+	 * Otherwise, Probe would have located the entry and set INDEX Reg
+	 * with existing location. This will cause Write CMD to over-write
+	 * existing entry with new PD0 and PD1
+	 */
+	if (likely(idx & TLB_LKUP_ERR))
+		write_aux_reg(ARC_REG_TLBCOMMAND, TLBGetIndex);
+
+	/* setup the other half of TLB entry (pfn, rwx..) */
+	write_aux_reg(ARC_REG_TLBPD1, pd1);
+
+	/*
+	 * Commit the Entry to MMU
+	 * It doesnt sound safe to use the TLBWriteNI cmd here
+	 * which doesn't flush uTLBs. I'd rather be safe than sorry.
+	 */
+	write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
+}
+
+
 /*
  * Un-conditionally (without lookup) erase the entire MMU contents
  */
@@ -224,13 +253,14 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm)
 		return;
 
 	/*
-	 * Workaround for Android weirdism:
-	 * A binder VMA could end up in a task such that vma->mm != tsk->mm
-	 * old code would cause h/w - s/w ASID to get out of sync
+	 * - Move to a new ASID, but only if the mm is still wired in
+	 *   (Android Binders ended up calling this for vma->mm != tsk->mm,
+	 *    causing h/w - s/w ASID to get out of sync)
+	 * - Also get_new_mmu_context() new implementation allocates a new
+	 *   ASID only if it is not allocated already - so unallocate first
 	 */
-	if (current->mm != mm)
-		destroy_context(mm);
-	else
+	destroy_context(mm);
+	if (current->mm == mm)
 		get_new_mmu_context(mm);
 }
 
@@ -245,8 +275,8 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm)
 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			   unsigned long end)
 {
+	const unsigned int cpu = smp_processor_id();
 	unsigned long flags;
-	unsigned int asid;
 
 	/* If range @start to @end is more than 32 TLB entries deep,
 	 * its better to move to a new ASID rather than searching for
@@ -268,11 +298,10 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 	start &= PAGE_MASK;
 
 	local_irq_save(flags);
-	asid = vma->vm_mm->context.asid;
 
-	if (asid != NO_ASID) {
+	if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) {
 		while (start < end) {
-			tlb_entry_erase(start | (asid & 0xff));
+			tlb_entry_erase(start | hw_pid(vma->vm_mm, cpu));
 			start += PAGE_SIZE;
 		}
 	}
@@ -319,6 +348,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
+	const unsigned int cpu = smp_processor_id();
 	unsigned long flags;
 
 	/* Note that it is critical that interrupts are DISABLED between
@@ -326,9 +356,8 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 	 */
 	local_irq_save(flags);
 
-	if (vma->vm_mm->context.asid != NO_ASID) {
-		tlb_entry_erase((page & PAGE_MASK) |
-				(vma->vm_mm->context.asid & 0xff));
+	if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) {
+		tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm, cpu));
 		utlb_invalidate();
 	}
 
@@ -341,8 +370,8 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
 	unsigned long flags;
-	unsigned int idx, asid_or_sasid;
-	unsigned long pd0_flags;
+	unsigned int asid_or_sasid, rwx;
+	unsigned long pd0, pd1;
 
 	/*
 	 * create_tlb() assumes that current->mm == vma->mm, since
@@ -374,47 +403,30 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 
 	local_irq_save(flags);
 
-	tlb_paranoid_check(vma->vm_mm->context.asid, address);
+	tlb_paranoid_check(hw_pid(vma->vm_mm), address);
 
 	address &= PAGE_MASK;
 
 	/* update this PTE credentials */
 	pte_val(*ptep) |= (_PAGE_PRESENT | _PAGE_ACCESSED);
 
-	/* Create HW TLB entry Flags (in PD0) from PTE Flags */
-#if (CONFIG_ARC_MMU_VER <= 2)
-	pd0_flags = ((pte_val(*ptep) & PTE_BITS_IN_PD0) >> 1);
-#else
-	pd0_flags = ((pte_val(*ptep) & PTE_BITS_IN_PD0));
-#endif
+	/* Create HW TLB(PD0,PD1) from PTE  */
 
 	/* ASID for this task */
 	asid_or_sasid = read_aux_reg(ARC_REG_PID) & 0xff;
 
-	write_aux_reg(ARC_REG_TLBPD0, address | pd0_flags | asid_or_sasid);
+	pd0 = address | asid_or_sasid | (pte_val(*ptep) & PTE_BITS_IN_PD0);
 
-	/* Load remaining info in PD1 (Page Frame Addr and Kx/Kw/Kr Flags) */
-	write_aux_reg(ARC_REG_TLBPD1, (pte_val(*ptep) & PTE_BITS_IN_PD1));
+	rwx = pte_val(*ptep) & PTE_BITS_RWX;
 
-	/* First verify if entry for this vaddr+ASID already exists */
-	write_aux_reg(ARC_REG_TLBCOMMAND, TLBProbe);
-	idx = read_aux_reg(ARC_REG_TLBINDEX);
+	if (pte_val(*ptep) & _PAGE_GLOBAL)
+		rwx <<= 3;		/* r w x => Kr Kw Kx 0 0 0 */
+	else
+		rwx |= (rwx << 3);	/* r w x => Kr Kw Kx Ur Uw Ux */
 
-	/*
-	 * If Not already present get a free slot from MMU.
-	 * Otherwise, Probe would have located the entry and set INDEX Reg
-	 * with existing location. This will cause Write CMD to over-write
-	 * existing entry with new PD0 and PD1
-	 */
-	if (likely(idx & TLB_LKUP_ERR))
-		write_aux_reg(ARC_REG_TLBCOMMAND, TLBGetIndex);
+	pd1 = rwx | (pte_val(*ptep) & PTE_BITS_NON_RWX_IN_PD1);
 
-	/*
-	 * Commit the Entry to MMU
-	 * It doesnt sound safe to use the TLBWriteNI cmd here
-	 * which doesn't flush uTLBs. I'd rather be safe than sorry.
-	 */
-	write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
+	tlb_entry_insert(pd0, pd1);
 
 	local_irq_restore(flags);
 }
@@ -553,11 +565,6 @@ void arc_mmu_init(void)
 	if (mmu->pg_sz != PAGE_SIZE)
 		panic("MMU pg size != PAGE_SIZE (%luk)\n", TO_KB(PAGE_SIZE));
 
-	/*
-	 * ASID mgmt data structures are compile time init
-	 *  asid_cache = FIRST_ASID and asid_mm_map[] all zeroes
-	 */
-
 	local_flush_tlb_all();
 
 	/* Enable the MMU */
@@ -674,7 +681,7 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
 void print_asid_mismatch(int is_fast_path)
 {
 	int pid_sw, pid_hw;
-	pid_sw = current->active_mm->context.asid;
+	pid_sw = hw_pid(current->active_mm, smp_processor_id());
 	pid_hw = read_aux_reg(ARC_REG_PID) & 0xff;
 
 	pr_emerg("ASID Mismatch in %s Path Handler: sw-pid=0x%x hw-pid=0x%x\n",
@@ -689,7 +696,8 @@ void tlb_paranoid_check(unsigned int pid_sw, unsigned long addr)
 
 	pid_hw = read_aux_reg(ARC_REG_PID) & 0xff;
 
-	if (addr < 0x70000000 && ((pid_hw != pid_sw) || (pid_sw == NO_ASID)))
+	if (addr < 0x70000000 && ((pid_hw != pid_sw) ||
+	    (pid_sw == MM_CTXT_NO_ASID)))
 		print_asid_mismatch(0);
 }
 #endif
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index 5c5bb23..50e83ca 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -44,17 +44,36 @@
 #include <asm/arcregs.h>
 #include <asm/cache.h>
 #include <asm/processor.h>
-#if (CONFIG_ARC_MMU_VER == 1)
 #include <asm/tlb-mmu1.h>
-#endif
 
-;--------------------------------------------------------------------------
-; scratch memory to save the registers (r0-r3) used to code TLB refill Handler
-; For details refer to comments before TLBMISS_FREEUP_REGS below
+;-----------------------------------------------------------------
+; ARC700 Exception Handling doesn't auto-switch stack and it only provides
+; ONE scratch AUX reg "ARC_REG_SCRATCH_DATA0"
+;
+; For Non-SMP, the scratch AUX reg is repurposed to cache task PGD, so a
+; "global" is used to free-up FIRST core reg to be able to code the rest of
+; exception prologue (IRQ auto-disabled on Exceptions, so it's IRQ-safe).
+; Since the Fast Path TLB Miss handler is coded with 4 regs, the remaining 3
+; need to be saved as well by extending the "global" to be 4 words. Hence
+;	".size   ex_saved_reg1, 16"
+; [All of this dance is to avoid stack switching for each TLB Miss, since we
+; only need to save only a handful of regs, as opposed to complete reg file]
+;
+; For ARC700 SMP, the "global" obviously can't be used for free up the FIRST
+; core reg as it will not be SMP safe.
+; Thus scratch AUX reg is used (and no longer used to cache task PGD).
+; To save the rest of 3 regs - per cpu, the global is made "per-cpu".
+; Epilogue thus has to locate the "per-cpu" storage for regs.
+; To avoid cache line bouncing the per-cpu global is aligned/sized per
+; L1_CACHE_SHIFT, despite fundamentally needing to be 12 bytes only. Hence
+;	".size   ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT)"
+
+; As simple as that....
 ;--------------------------------------------------------------------------
 
+; scratch memory to save [r0-r3] used to code TLB refill Handler
 ARCFP_DATA ex_saved_reg1
-	.align 1 << L1_CACHE_SHIFT	; IMP: Must be Cache Line aligned
+	.align 1 << L1_CACHE_SHIFT
 	.type   ex_saved_reg1, @object
 #ifdef CONFIG_SMP
 	.size   ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT)
@@ -66,6 +85,44 @@ ex_saved_reg1:
 	.zero 16
 #endif
 
+.macro TLBMISS_FREEUP_REGS
+#ifdef CONFIG_SMP
+	sr  r0, [ARC_REG_SCRATCH_DATA0]	; freeup r0 to code with
+	GET_CPU_ID  r0			; get to per cpu scratch mem,
+	lsl r0, r0, L1_CACHE_SHIFT	; cache line wide per cpu
+	add r0, @ex_saved_reg1, r0
+#else
+	st    r0, [@ex_saved_reg1]
+	mov_s r0, @ex_saved_reg1
+#endif
+	st_s  r1, [r0, 4]
+	st_s  r2, [r0, 8]
+	st_s  r3, [r0, 12]
+
+	; VERIFY if the ASID in MMU-PID Reg is same as
+	; one in Linux data structures
+
+	DBG_ASID_MISMATCH
+.endm
+
+.macro TLBMISS_RESTORE_REGS
+#ifdef CONFIG_SMP
+	GET_CPU_ID  r0			; get to per cpu scratch mem
+	lsl r0, r0, L1_CACHE_SHIFT	; each is cache line wide
+	add r0, @ex_saved_reg1, r0
+	ld_s  r3, [r0,12]
+	ld_s  r2, [r0, 8]
+	ld_s  r1, [r0, 4]
+	lr    r0, [ARC_REG_SCRATCH_DATA0]
+#else
+	mov_s r0, @ex_saved_reg1
+	ld_s  r3, [r0,12]
+	ld_s  r2, [r0, 8]
+	ld_s  r1, [r0, 4]
+	ld_s  r0, [r0]
+#endif
+.endm
+
 ;============================================================================
 ;  Troubleshooting Stuff
 ;============================================================================
@@ -161,13 +218,17 @@ ex_saved_reg1:
 ; IN: r0 = PTE, r1 = ptr to PTE
 
 .macro CONV_PTE_TO_TLB
-	and r3, r0, PTE_BITS_IN_PD1 ; Extract permission flags+PFN from PTE
-	sr  r3, [ARC_REG_TLBPD1]    ; these go in PD1
+	and    r3, r0, PTE_BITS_RWX	;       r w x
+	lsl    r2, r3, 3		; r w x 0 0 0
+	and.f  0,  r0, _PAGE_GLOBAL
+	or.z   r2, r2, r3		; r w x r w x
+
+	and r3, r0, PTE_BITS_NON_RWX_IN_PD1 ; Extract PFN+cache bits from PTE
+	or  r3, r3, r2
+
+	sr  r3, [ARC_REG_TLBPD1]    	; these go in PD1
 
 	and r2, r0, PTE_BITS_IN_PD0 ; Extract other PTE flags: (V)alid, (G)lb
-#if (CONFIG_ARC_MMU_VER <= 2)   /* Neednot be done with v3 onwards */
-	lsr r2, r2                  ; shift PTE flags to match layout in PD0
-#endif
 
 	lr  r3,[ARC_REG_TLBPD0]     ; MMU prepares PD0 with vaddr and asid
 
@@ -191,68 +252,6 @@ ex_saved_reg1:
 #endif
 .endm
 
-;-----------------------------------------------------------------
-; ARC700 Exception Handling doesn't auto-switch stack and it only provides
-; ONE scratch AUX reg "ARC_REG_SCRATCH_DATA0"
-;
-; For Non-SMP, the scratch AUX reg is repurposed to cache task PGD, so a
-; "global" is used to free-up FIRST core reg to be able to code the rest of
-; exception prologue (IRQ auto-disabled on Exceptions, so it's IRQ-safe).
-; Since the Fast Path TLB Miss handler is coded with 4 regs, the remaining 3
-; need to be saved as well by extending the "global" to be 4 words. Hence
-;	".size   ex_saved_reg1, 16"
-; [All of this dance is to avoid stack switching for each TLB Miss, since we
-; only need to save only a handful of regs, as opposed to complete reg file]
-;
-; For ARC700 SMP, the "global" obviously can't be used for free up the FIRST
-; core reg as it will not be SMP safe.
-; Thus scratch AUX reg is used (and no longer used to cache task PGD).
-; To save the rest of 3 regs - per cpu, the global is made "per-cpu".
-; Epilogue thus has to locate the "per-cpu" storage for regs.
-; To avoid cache line bouncing the per-cpu global is aligned/sized per
-; L1_CACHE_SHIFT, despite fundamentally needing to be 12 bytes only. Hence
-;	".size   ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT)"
-
-; As simple as that....
-
-.macro TLBMISS_FREEUP_REGS
-#ifdef CONFIG_SMP
-	sr  r0, [ARC_REG_SCRATCH_DATA0]	; freeup r0 to code with
-	GET_CPU_ID  r0			; get to per cpu scratch mem,
-	lsl r0, r0, L1_CACHE_SHIFT	; cache line wide per cpu
-	add r0, @ex_saved_reg1, r0
-#else
-	st    r0, [@ex_saved_reg1]
-	mov_s r0, @ex_saved_reg1
-#endif
-	st_s  r1, [r0, 4]
-	st_s  r2, [r0, 8]
-	st_s  r3, [r0, 12]
-
-	; VERIFY if the ASID in MMU-PID Reg is same as
-	; one in Linux data structures
-
-	DBG_ASID_MISMATCH
-.endm
-
-;-----------------------------------------------------------------
-.macro TLBMISS_RESTORE_REGS
-#ifdef CONFIG_SMP
-	GET_CPU_ID  r0			; get to per cpu scratch mem
-	lsl r0, r0, L1_CACHE_SHIFT	; each is cache line wide
-	add r0, @ex_saved_reg1, r0
-	ld_s  r3, [r0,12]
-	ld_s  r2, [r0, 8]
-	ld_s  r1, [r0, 4]
-	lr    r0, [ARC_REG_SCRATCH_DATA0]
-#else
-	mov_s r0, @ex_saved_reg1
-	ld_s  r3, [r0,12]
-	ld_s  r2, [r0, 8]
-	ld_s  r1, [r0, 4]
-	ld_s  r0, [r0]
-#endif
-.endm
 
 ARCFP_CODE	;Fast Path Code, candidate for ICCM
 
@@ -277,8 +276,8 @@ ARC_ENTRY EV_TLBMissI
 	;----------------------------------------------------------------
 	; VERIFY_PTE: Check if PTE permissions approp for executing code
 	cmp_s   r2, VMALLOC_START
-	mov.lo  r2, (_PAGE_PRESENT | _PAGE_U_EXECUTE)
-	mov.hs  r2, (_PAGE_PRESENT | _PAGE_K_EXECUTE)
+	mov_s   r2, (_PAGE_PRESENT | _PAGE_EXECUTE)
+	or.hs   r2, r2, _PAGE_GLOBAL
 
 	and     r3, r0, r2  ; Mask out NON Flag bits from PTE
 	xor.f   r3, r3, r2  ; check ( ( pte & flags_test ) == flags_test )
@@ -317,26 +316,21 @@ ARC_ENTRY EV_TLBMissD
 	;----------------------------------------------------------------
 	; VERIFY_PTE: Chk if PTE permissions approp for data access (R/W/R+W)
 
-	mov_s   r2, 0
+	cmp_s	r2, VMALLOC_START
+	mov_s   r2, _PAGE_PRESENT	; common bit for K/U PTE
+	or.hs	r2, r2, _PAGE_GLOBAL	; kernel PTE only
+
+	; Linux PTE [RWX] bits are semantically overloaded:
+	; -If PAGE_GLOBAL set, they refer to kernel-only flags (vmalloc)
+	; -Otherwise they are user-mode permissions, and those are exactly
+	;  same for kernel mode as well (e.g. copy_(to|from)_user)
+
 	lr      r3, [ecr]
 	btst_s  r3, ECR_C_BIT_DTLB_LD_MISS	; Read Access
-	or.nz   r2, r2, _PAGE_U_READ      	; chk for Read flag in PTE
+	or.nz   r2, r2, _PAGE_READ      	; chk for Read flag in PTE
 	btst_s  r3, ECR_C_BIT_DTLB_ST_MISS	; Write Access
-	or.nz   r2, r2, _PAGE_U_WRITE     	; chk for Write flag in PTE
-	; Above laddering takes care of XCHG access
-	;   which is both Read and Write
-
-	; If kernel mode access, ; make _PAGE_xx flags as _PAGE_K_xx
-	; For copy_(to|from)_user, despite exception taken in kernel mode,
-	; this code is not hit, because EFA would still be the user mode
-	; address (EFA < 0x6000_0000).
-	; This code is for legit kernel mode faults, vmalloc specifically
-	; (EFA: 0x7000_0000 to 0x7FFF_FFFF)
-
-	lr      r3, [efa]
-	cmp     r3, VMALLOC_START - 1   ; If kernel mode access
-	asl.hi  r2, r2, 3               ; make _PAGE_xx flags as _PAGE_K_xx
-	or      r2, r2, _PAGE_PRESENT   ; Common flag for K/U mode
+	or.nz   r2, r2, _PAGE_WRITE     	; chk for Write flag in PTE
+	; Above laddering takes care of XCHG access (both R and W)
 
 	; By now, r2 setup with all the Flags we need to check in PTE
 	and     r3, r0, r2              ; Mask out NON Flag bits from PTE
@@ -371,13 +365,7 @@ do_slow_path_pf:
 
 	; Slow path TLB Miss handled as a regular ARC Exception
 	; (stack switching / save the complete reg-file).
-	; That requires freeing up r9
-	EXCPN_PROLOG_FREEUP_REG r9
-
-	lr  r9, [erstatus]
-
-	SWITCH_TO_KERNEL_STK
-	SAVE_ALL_SYS
+	EXCEPTION_PROLOGUE
 
 	; ------- setup args for Linux Page fault Hanlder ---------
 	mov_s r0, sp
diff --git a/arch/arc/mm/tlbflush.c b/arch/arc/mm/tlbflush.c
new file mode 100644
index 0000000..a0abe48
--- /dev/null
+++ b/arch/arc/mm/tlbflush.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/sched.h>
+#include <asm/tlbflush.h>
+
+struct tlb_args {
+       struct vm_area_struct *ta_vma;
+       unsigned long ta_start;
+       unsigned long ta_end;
+};
+
+static inline void ipi_flush_tlb_all(void *ignored)
+{
+       local_flush_tlb_all();
+}
+
+static inline void ipi_flush_tlb_mm(void *arg)
+{
+       struct mm_struct *mm = (struct mm_struct *)arg;
+
+       local_flush_tlb_mm(mm);
+}
+
+static inline void ipi_flush_tlb_page(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_range(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+
+static inline void ipi_flush_tlb_kernel_range(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
+}
+
+void flush_tlb_all(void)
+{
+       on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+       struct tlb_args ta;
+       ta.ta_vma = vma;
+       ta.ta_start = uaddr;
+       on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page, &ta, 1);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+                     unsigned long start, unsigned long end)
+{
+       struct tlb_args ta;
+       ta.ta_vma = vma;
+       ta.ta_start = start;
+       ta.ta_end = end;
+       on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range, &ta, 1);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       struct tlb_args ta;
+       ta.ta_start = start;
+       ta.ta_end = end;
+       on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+}
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 43594d5..98f945d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -441,7 +441,6 @@ config ARCH_NETX
 config ARCH_IOP13XX
 	bool "IOP13xx-based"
 	depends on MMU
-	select ARCH_SUPPORTS_MSI
 	select CPU_XSC3
 	select NEED_MACH_MEMORY_H
 	select NEED_RET_TO_USER
@@ -630,6 +629,7 @@ config ARCH_MSM
 	bool "Qualcomm MSM"
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_OF if OF
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	help
@@ -645,7 +645,7 @@ config ARCH_SHMOBILE
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_CLK
 	select HAVE_MACH_CLKDEV
 	select HAVE_SMP
@@ -1584,16 +1584,6 @@ config ARM_PSCI
 	  0022A ("Power State Coordination Interface System Software on
 	  ARM processors").
 
-config LOCAL_TIMERS
-	bool "Use local timer interrupts"
-	depends on SMP
-	default y
-	help
-	  Enable support for local timers on SMP platforms, rather then the
-	  legacy IPI broadcast method.  Local timers allows the system
-	  accounting to be spread across the timer interval, preventing a
-	  "thundering herd" at every timer tick.
-
 # The GPIO number here must be sorted by descending number. In case of
 # a multiplatform kernel, we just want the highest value required by the
 # selected platforms.
@@ -1613,13 +1603,49 @@ config ARCH_NR_GPIO
 
 source kernel/Kconfig.preempt
 
-config HZ
+config HZ_FIXED
 	int
 	default 200 if ARCH_EBSA110 || ARCH_S3C24XX || ARCH_S5P64X0 || \
 		ARCH_S5PV210 || ARCH_EXYNOS4
 	default AT91_TIMER_HZ if ARCH_AT91
 	default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE
-	default 100
+
+choice
+	depends on !HZ_FIXED
+	prompt "Timer frequency"
+
+config HZ_100
+	bool "100 Hz"
+
+config HZ_200
+	bool "200 Hz"
+
+config HZ_250
+	bool "250 Hz"
+
+config HZ_300
+	bool "300 Hz"
+
+config HZ_500
+	bool "500 Hz"
+
+config HZ_1000
+	bool "1000 Hz"
+
+endchoice
+
+config HZ
+	int
+	default HZ_FIXED if HZ_FIXED
+	default 100 if HZ_100
+	default 200 if HZ_200
+	default 250 if HZ_250
+	default 300 if HZ_300
+	default 500 if HZ_500
+	default 1000
+
+config SCHED_HRTICK
+	def_bool HIGH_RES_TIMERS
 
 config SCHED_HRTICK
 	def_bool HIGH_RES_TIMERS
@@ -1756,6 +1782,9 @@ config HAVE_ARCH_TRANSPARENT_HUGEPAGE
        def_bool y
        depends on ARM_LPAE
 
+config ARCH_WANT_GENERAL_HUGETLB
+	def_bool y
+
 source "mm/Kconfig"
 
 config FORCE_MAX_ZONEORDER
@@ -2175,6 +2204,13 @@ config NEON
 	  Say Y to include support code for NEON, the ARMv7 Advanced SIMD
 	  Extension.
 
+config KERNEL_MODE_NEON
+	bool "Support for NEON in kernel mode"
+	default n
+	depends on NEON
+	help
+	  Say Y to include support for NEON in kernel mode.
+
 endmenu
 
 menu "Userspace binary formats"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 583f4a0..af5d084 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -92,6 +92,7 @@ choice
 	config DEBUG_BCM2835
 		bool "Kernel low-level debugging on BCM2835 PL011 UART"
 		depends on ARCH_BCM2835
+		select DEBUG_UART_PL01X
 
 	config DEBUG_CLPS711X_UART1
 		bool "Kernel low-level debugging messages via UART1"
@@ -110,6 +111,7 @@ choice
 	config DEBUG_CNS3XXX
 		bool "Kernel Kernel low-level debugging on Cavium Networks CNS3xxx"
 		depends on ARCH_CNS3XXX
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want the debug print routines to direct
                   their output to the CNS3xxx UART0.
@@ -117,6 +119,7 @@ choice
 	config DEBUG_DAVINCI_DA8XX_UART1
 		bool "Kernel low-level debugging on DaVinci DA8XX using UART1"
 		depends on ARCH_DAVINCI_DA8XX
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART1 serial port on DaVinci DA8XX devices.
@@ -124,6 +127,7 @@ choice
 	config DEBUG_DAVINCI_DA8XX_UART2
 		bool "Kernel low-level debugging on DaVinci DA8XX using UART2"
 		depends on ARCH_DAVINCI_DA8XX
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART2 serial port on DaVinci DA8XX devices.
@@ -131,6 +135,7 @@ choice
 	config DEBUG_DAVINCI_DMx_UART0
 		bool "Kernel low-level debugging on DaVinci DMx using UART0"
 		depends on ARCH_DAVINCI_DMx
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART0 serial port on DaVinci DMx devices.
@@ -138,6 +143,7 @@ choice
 	config DEBUG_DAVINCI_TNETV107X_UART1
 		bool "Kernel low-level debugging on DaVinci TNETV107x using UART1"
 		depends on ARCH_DAVINCI_TNETV107X
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART1 serial port on DaVinci TNETV107X
@@ -177,6 +183,7 @@ choice
 	config DEBUG_HIGHBANK_UART
 		bool "Kernel low-level debugging messages via Highbank UART"
 		depends on ARCH_HIGHBANK
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to the UART on Highbank based devices.
@@ -191,6 +198,7 @@ choice
 	config DEBUG_IMX23_UART
 		bool "i.MX23 Debug UART"
 		depends on SOC_IMX23
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX23.
@@ -212,6 +220,7 @@ choice
 	config DEBUG_IMX28_UART
 		bool "i.MX28 Debug UART"
 		depends on SOC_IMX28
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX28.
@@ -261,6 +270,7 @@ choice
 	config DEBUG_KEYSTONE_UART0
 		bool "Kernel low-level debugging on KEYSTONE2 using UART0"
 		depends on ARCH_KEYSTONE
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART0 serial port on KEYSTONE2 devices.
@@ -268,6 +278,7 @@ choice
 	config DEBUG_KEYSTONE_UART1
 		bool "Kernel low-level debugging on KEYSTONE2 using UART1"
 		depends on ARCH_KEYSTONE
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART1 serial port on KEYSTONE2 devices.
@@ -275,6 +286,7 @@ choice
 	config DEBUG_MMP_UART2
 		bool "Kernel low-level debugging message via MMP UART2"
 		depends on ARCH_MMP
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on MMP UART2.
@@ -282,6 +294,7 @@ choice
 	config DEBUG_MMP_UART3
 		bool "Kernel low-level debugging message via MMP UART3"
 		depends on ARCH_MMP
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on MMP UART3.
@@ -326,6 +339,7 @@ choice
 	config DEBUG_MVEBU_UART
 		bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)"
 		depends on ARCH_MVEBU
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on MVEBU based platforms.
@@ -344,6 +358,7 @@ choice
 	config DEBUG_MVEBU_UART_ALTERNATE
 		bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)"
 		depends on ARCH_MVEBU
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on MVEBU based platforms.
@@ -355,9 +370,17 @@ choice
 		  when u-boot hands over to the kernel, the system
 		  silently crashes, with no serial output at all.
 
+	config DEBUG_VF_UART
+		bool "Vybrid UART"
+		depends on SOC_VF610
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Vybrid based platforms.
+
 	config DEBUG_NOMADIK_UART
 		bool "Kernel low-level debugging messages via NOMADIK UART"
 		depends on ARCH_NOMADIK
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on NOMADIK based platforms.
@@ -365,6 +388,7 @@ choice
 	config DEBUG_NSPIRE_CLASSIC_UART
 		bool "Kernel low-level debugging via TI-NSPIRE 8250 UART"
 		depends on ARCH_NSPIRE
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on TI-NSPIRE classic models.
@@ -372,20 +396,82 @@ choice
 	config DEBUG_NSPIRE_CX_UART
 		bool "Kernel low-level debugging via TI-NSPIRE PL011 UART"
 		depends on ARCH_NSPIRE
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on TI-NSPIRE CX models.
 
-	config DEBUG_OMAP2PLUS_UART
-		bool "Kernel low-level debugging messages via OMAP2PLUS UART"
+	config DEBUG_OMAP2UART1
+		bool "OMAP2/3/4 UART1 (omap2/3 sdp boards and some omap3 boards)"
 		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
 		help
-		  Say Y here if you want kernel low-level debugging support
-		  on OMAP2PLUS based platforms.
+		  This covers at least h4, 2430sdp, 3430sdp, 3630sdp,
+		  omap3 torpedo and 3530 lv som.
+
+	config DEBUG_OMAP2UART2
+		bool "Kernel low-level debugging messages via OMAP2/3/4 UART2"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_OMAP2UART3
+		bool "Kernel low-level debugging messages via OMAP2 UART3 (n8x0)"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_OMAP3UART3
+		bool "Kernel low-level debugging messages via OMAP3 UART3 (most omap3 boards)"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+		help
+		  This covers at least cm_t3x, beagle, crane, devkit8000,
+		  igep00x0, ldp, n900, n9(50), pandora, overo, touchbook,
+		  and 3517evm.
+
+	config DEBUG_OMAP4UART3
+		bool "Kernel low-level debugging messages via OMAP4/5 UART3 (omap4 blaze, panda, omap5 sevm)"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_OMAP3UART4
+		bool "Kernel low-level debugging messages via OMAP36XX UART4"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_OMAP4UART4
+		bool "Kernel low-level debugging messages via OMAP4/5 UART4"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_TI81XXUART1
+		bool "Kernel low-level debugging messages via TI81XX UART1 (ti8148evm)"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_TI81XXUART2
+		bool "Kernel low-level debugging messages via TI81XX UART2"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_TI81XXUART3
+		bool "Kernel low-level debugging messages via TI81XX UART3 (ti8168evm)"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_AM33XXUART1
+		bool "Kernel low-level debugging messages via AM33XX UART1"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
+
+	config DEBUG_ZOOM_UART
+		bool "Kernel low-level debugging messages via Zoom2/3 UART"
+		depends on ARCH_OMAP2PLUS
+		select DEBUG_OMAP2PLUS_UART
 
 	config DEBUG_PICOXCELL_UART
 		depends on ARCH_PICOXCELL
 		bool "Use PicoXcell UART for low-level debug"
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on PicoXcell based platforms.
@@ -393,6 +479,7 @@ choice
 	config DEBUG_PXA_UART1
 		depends on ARCH_PXA
 		bool "Use PXA UART1 for low-level debug"
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on PXA UART1.
@@ -400,6 +487,7 @@ choice
 	config DEBUG_REALVIEW_STD_PORT
 		bool "RealView Default UART"
 		depends on ARCH_REALVIEW
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to the serial port on RealView EB, PB11MP, PBA8
@@ -408,14 +496,64 @@ choice
 	config DEBUG_REALVIEW_PB1176_PORT
 		bool "RealView PB1176 UART"
 		depends on MACH_REALVIEW_PB1176
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to the standard serial port on the RealView
 		  PB1176 platform.
 
-	config DEBUG_ROCKCHIP_UART
-		bool "Kernel low-level debugging messages via Rockchip UART"
+	config DEBUG_RK29_UART0
+		bool "Kernel low-level debugging messages via Rockchip RK29 UART0"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
+	config DEBUG_RK29_UART1
+		bool "Kernel low-level debugging messages via Rockchip RK29 UART1"
 		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
+	config DEBUG_RK29_UART2
+		bool "Kernel low-level debugging messages via Rockchip RK29 UART2"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
+	config DEBUG_RK3X_UART0
+		bool "Kernel low-level debugging messages via Rockchip RK3X UART0"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
+	config DEBUG_RK3X_UART1
+		bool "Kernel low-level debugging messages via Rockchip RK3X UART1"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
+	config DEBUG_RK3X_UART2
+		bool "Kernel low-level debugging messages via Rockchip RK3X UART2"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
+	config DEBUG_RK3X_UART3
+		bool "Kernel low-level debugging messages via Rockchip RK3X UART3"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on Rockchip based platforms.
@@ -471,6 +609,7 @@ choice
 	config DEBUG_SOCFPGA_UART
 		depends on ARCH_SOCFPGA
 		bool "Use SOCFPGA UART for low-level debug"
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on SOCFPGA based platforms.
@@ -478,6 +617,7 @@ choice
 	config DEBUG_SUNXI_UART0
 		bool "Kernel low-level debugging messages via sunXi UART0"
 		depends on ARCH_SUNXI
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on Allwinner A1X based platforms on the UART0.
@@ -485,13 +625,59 @@ choice
 	config DEBUG_SUNXI_UART1
 		bool "Kernel low-level debugging messages via sunXi UART1"
 		depends on ARCH_SUNXI
+		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on Allwinner A1X based platforms on the UART1.
 
-	config DEBUG_TEGRA_UART
+	config TEGRA_DEBUG_UART_AUTO_ODMDATA
+		bool "Kernel low-level debugging messages via Tegra UART via ODMDATA"
+		depends on ARCH_TEGRA
+		select DEBUG_TEGRA_UART
+		help
+		  Automatically determines which UART to use for low-level
+		  debug based on the ODMDATA value. This value is part of
+		  the BCT, and is written to the boot memory device using
+		  nvflash, or other flashing tool.  When bits 19:18 are 3,
+		  then bits 17:15 indicate which UART to use; 0/1/2/3/4
+		  are UART A/B/C/D/E.
+
+	config TEGRA_DEBUG_UARTA
+		bool "Kernel low-level debugging messages via Tegra UART A"
+		depends on ARCH_TEGRA
+		select DEBUG_TEGRA_UART
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Tegra based platforms.
+
+	config TEGRA_DEBUG_UARTB
+		bool "Kernel low-level debugging messages via Tegra UART B"
+		depends on ARCH_TEGRA
+		select DEBUG_TEGRA_UART
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Tegra based platforms.
+
+	config TEGRA_DEBUG_UARTC
+		bool "Kernel low-level debugging messages via Tegra UART C"
+		depends on ARCH_TEGRA
+		select DEBUG_TEGRA_UART
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Tegra based platforms.
+
+	config TEGRA_DEBUG_UARTD
+		bool "Kernel low-level debugging messages via Tegra UART D"
+		depends on ARCH_TEGRA
+		select DEBUG_TEGRA_UART
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Tegra based platforms.
+
+	config TEGRA_DEBUG_UARTE
+		bool "Kernel low-level debugging messages via Tegra UART E"
 		depends on ARCH_TEGRA
-		bool "Use Tegra UART for low-level debug"
+		select DEBUG_TEGRA_UART
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on Tegra based platforms.
@@ -510,19 +696,32 @@ choice
 		  Say Y here if you want the debug print routines to direct
 		  their output to the uart1 port on SiRFmarco devices.
 
-	config DEBUG_STI_UART
+	config STIH41X_DEBUG_ASC2
+		bool "Use StiH415/416 ASC2 UART for low-level debug"
+		depends on ARCH_STI
+		select DEBUG_STI_UART
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on STiH415/416 based platforms like b2000, which has
+		  default UART wired up to ASC2.
+
+		  If unsure, say N.
+
+	config STIH41X_DEBUG_SBC_ASC1
+		bool "Use StiH415/416 SBC ASC1 UART for low-level debug"
 		depends on ARCH_STI
-		bool "Use StiH415/416 ASC for low-level debug"
+		select DEBUG_STI_UART
 		help
 		  Say Y here if you want kernel low-level debugging support
-		  on StiH415/416 based platforms like B2000, B2020.
-		  It support UART2 and SBC_UART1.
+		  on STiH415/416 based platforms like b2020. which has
+		  default UART wired up to SBC ASC1.
 
 		  If unsure, say N.
 
 	config DEBUG_U300_UART
 		bool "Kernel low-level debugging messages via U300 UART0"
 		depends on ARCH_U300
+		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to the uart port on U300 devices.
@@ -548,6 +747,7 @@ choice
 	config DEBUG_VEXPRESS_UART0_CA9
 		bool "Use PL011 UART0 at 0x10009000 (V2P-CA9 core tile)"
 		depends on ARCH_VEXPRESS
+		select DEBUG_UART_PL01X
 		help
 		  This option selects UART0 at 0x10009000. Except for custom models,
 		  this applies only to the V2P-CA9 tile.
@@ -555,6 +755,7 @@ choice
 	config DEBUG_VEXPRESS_UART0_RS1
 		bool "Use PL011 UART0 at 0x1c090000 (RS1 complaint tiles)"
 		depends on ARCH_VEXPRESS
+		select DEBUG_UART_PL01X
 		help
 		  This option selects UART0 at 0x1c090000. This applies to most
 		  of the tiles using the RS1 memory map, including all new A-class
@@ -563,6 +764,7 @@ choice
 	config DEBUG_VEXPRESS_UART0_CRX
 		bool "Use PL011 UART0 at 0xb0090000 (Cortex-R compliant tiles)"
 		depends on ARCH_VEXPRESS && !MMU
+		select DEBUG_UART_PL01X
 		help
 		  This option selects UART0 at 0xb0090000. This is appropriate for
 		  Cortex-R series tiles and SMMs, such as Cortex-R5 and Cortex-R7
@@ -579,7 +781,7 @@ choice
 		depends on !ARCH_MULTIPLATFORM
 		help
 		  Say Y here if your platform doesn't provide a UART option
-		  below. This relies on your platform choosing the right UART
+		  above. This relies on your platform choosing the right UART
 		  definition internally in order for low-level debugging to
 		  work.
 
@@ -610,11 +812,41 @@ choice
 		  For more details about semihosting, please see
 		  chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd.
 
+	config DEBUG_LL_UART_8250
+		bool "Kernel low-level debugging via 8250 UART"
+		help
+		  Say Y here if you wish the debug print routes to direct
+		  their output to an 8250 UART.  You can use this option
+		  to provide the parameters for the 8250 UART rather than
+		  selecting one of the platform specific options above if
+		  you know the parameters for the port.
+
+		  This option is preferred over the platform specific
+		  options; the platform specific options are deprecated
+		  and will be soon removed.
+
+	config DEBUG_LL_UART_PL01X
+		bool "Kernel low-level debugging via ARM Ltd PL01x Primecell UART"
+		help
+		  Say Y here if you wish the debug print routes to direct
+		  their output to a PL01x Primecell UART.  You can use
+		  this option to provide the parameters for the UART
+		  rather than selecting one of the platform specific
+		  options above if you know the parameters for the port.
+
+		  This option is preferred over the platform specific
+		  options; the platform specific options are deprecated
+		  and will be soon removed.
+
 endchoice
 
 config DEBUG_EXYNOS_UART
 	bool
 
+config DEBUG_OMAP2PLUS_UART
+	bool
+	depends on ARCH_OMAP2PLUS
+
 config DEBUG_IMX_UART_PORT
 	int "i.MX Debug UART Port Selection" if DEBUG_IMX1_UART || \
 						DEBUG_IMX25_UART || \
@@ -631,140 +863,19 @@ config DEBUG_IMX_UART_PORT
 	  Choose UART port on which kernel low-level debug messages
 	  should be output.
 
-choice
-	prompt "Low-level debug console UART"
-	depends on DEBUG_OMAP2PLUS_UART
-
-	config DEBUG_OMAP2UART1
-		bool "OMAP2/3/4 UART1 (omap2/3 sdp boards and some omap3 boards)"
-		help
-		  This covers at least h4, 2430sdp, 3430sdp, 3630sdp,
-		  omap3 torpedo and 3530 lv som.
-
-	config DEBUG_OMAP2UART2
-		bool "OMAP2/3/4 UART2"
-
-	config DEBUG_OMAP2UART3
-		bool "OMAP2 UART3 (n8x0)"
-
-	config DEBUG_OMAP3UART3
-		bool "OMAP3 UART3 (most omap3 boards)"
-		help
-		  This covers at least cm_t3x, beagle, crane, devkit8000,
-		  igep00x0, ldp, n900, n9(50), pandora, overo, touchbook,
-		  and 3517evm.
-
-	config DEBUG_OMAP4UART3
-		bool "OMAP4/5 UART3 (omap4 blaze, panda, omap5 sevm)"
-
-	config DEBUG_OMAP3UART4
-		bool "OMAP36XX UART4"
-
-	config DEBUG_OMAP4UART4
-		bool "OMAP4/5 UART4"
-
-	config DEBUG_TI81XXUART1
-		bool "TI81XX UART1 (ti8148evm)"
-
-	config DEBUG_TI81XXUART2
-		bool "TI81XX UART2"
-
-	config DEBUG_TI81XXUART3
-		bool "TI81XX UART3 (ti8168evm)"
-
-	config DEBUG_AM33XXUART1
-		bool "AM33XX UART1"
-
-	config DEBUG_ZOOM_UART
-		bool "Zoom2/3 UART"
-endchoice
-
-choice
-	prompt "Low-level debug console UART"
-	depends on DEBUG_ROCKCHIP_UART
-
-	config DEBUG_RK29_UART0
-		bool "RK29 UART0"
-
-	config DEBUG_RK29_UART1
-		bool "RK29 UART1"
-
-	config DEBUG_RK29_UART2
-		bool "RK29 UART2"
-
-	config DEBUG_RK3X_UART0
-		bool "RK3X UART0"
-
-	config DEBUG_RK3X_UART1
-		bool "RK3X UART1"
-
-	config DEBUG_RK3X_UART2
-		bool "RK3X UART2"
-
-	config DEBUG_RK3X_UART3
-		bool "RK3X UART3"
-endchoice
-
-choice
-	prompt "Low-level debug console UART"
-	depends on DEBUG_LL && DEBUG_TEGRA_UART
-
-	config TEGRA_DEBUG_UART_AUTO_ODMDATA
-	bool "Via ODMDATA"
-	help
-	  Automatically determines which UART to use for low-level debug based
-	  on the ODMDATA value. This value is part of the BCT, and is written
-	  to the boot memory device using nvflash, or other flashing tool.
-	  When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
-	  0/1/2/3/4 are UART A/B/C/D/E.
-
-	config TEGRA_DEBUG_UARTA
-		bool "UART A"
-
-	config TEGRA_DEBUG_UARTB
-		bool "UART B"
-
-	config TEGRA_DEBUG_UARTC
-		bool "UART C"
-
-	config TEGRA_DEBUG_UARTD
-		bool "UART D"
-
-	config TEGRA_DEBUG_UARTE
-		bool "UART E"
-
-endchoice
-
-choice
-	prompt "Low-level debug console UART"
-	depends on DEBUG_LL && DEBUG_STI_UART
-
-	config STIH41X_DEBUG_ASC2
-		bool "ASC2 UART"
-		help
-		  Say Y here if you want kernel low-level debugging support
-		  on STiH415/416 based platforms like b2000, which has
-		  default UART wired up to ASC2.
-
-		  If unsure, say N.
-
-	config STIH41X_DEBUG_SBC_ASC1
-		bool "SBC ASC1 UART"
-		help
-		  Say Y here if you want kernel low-level debugging support
-		  on STiH415/416 based platforms like b2020. which has
-		  default UART wired up to SBC ASC1.
-
-		  If unsure, say N.
+config DEBUG_TEGRA_UART
+	bool
+	depends on ARCH_TEGRA
 
-endchoice
+config DEBUG_STI_UART
+	bool
+	depends on ARCH_STI
 
 config DEBUG_LL_INCLUDE
 	string
-	default "debug/bcm2835.S" if DEBUG_BCM2835
-	default "debug/cns3xxx.S" if DEBUG_CNS3XXX
+	default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
 	default "debug/exynos.S" if DEBUG_EXYNOS_UART
-	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
 	default "debug/icedcc.S" if DEBUG_ICEDCC
 	default "debug/imx.S" if DEBUG_IMX1_UART || \
 				 DEBUG_IMX25_UART || \
@@ -775,36 +886,171 @@ config DEBUG_LL_INCLUDE
 				 DEBUG_IMX53_UART ||\
 				 DEBUG_IMX6Q_UART || \
 				 DEBUG_IMX6SL_UART
-	default "debug/keystone.S" if DEBUG_KEYSTONE_UART0 || \
-				      DEBUG_KEYSTONE_UART1
-	default "debug/mvebu.S" if DEBUG_MVEBU_UART || \
-				   DEBUG_MVEBU_UART_ALTERNATE
-	default "debug/mxs.S" if DEBUG_IMX23_UART || DEBUG_IMX28_UART
-	default "debug/nomadik.S" if DEBUG_NOMADIK_UART
-	default "debug/nspire.S" if 	DEBUG_NSPIRE_CX_UART || \
-					DEBUG_NSPIRE_CLASSIC_UART
+	default "debug/msm.S" if DEBUG_MSM_UART1 || \
+				 DEBUG_MSM_UART2 || \
+				 DEBUG_MSM_UART3 || \
+				 DEBUG_MSM8660_UART || \
+				 DEBUG_MSM8960_UART
 	default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
-	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
-	default "debug/pxa.S" if DEBUG_PXA_UART1 || DEBUG_MMP_UART2 || \
-				 DEBUG_MMP_UART3
-	default "debug/rockchip.S" if DEBUG_ROCKCHIP_UART
 	default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
-	default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
 	default "debug/sti.S" if DEBUG_STI_UART
-	default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
-	default "debug/u300.S" if DEBUG_U300_UART
 	default "debug/ux500.S" if DEBUG_UX500_UART
-	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
-		DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 || \
-		DEBUG_VEXPRESS_UART0_CRX
+	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
+	default "debug/vf.S" if DEBUG_VF_UART
 	default "debug/vt8500.S" if DEBUG_VT8500_UART0
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "mach/debug-macro.S"
 
+# Compatibility options for PL01x
+config DEBUG_UART_PL01X
+	def_bool ARCH_EP93XX || \
+		ARCH_INTEGRATOR || \
+		ARCH_SPEAR3XX || \
+		ARCH_SPEAR6XX || \
+		ARCH_SPEAR13XX || \
+		ARCH_VERSATILE
+
+# Compatibility options for 8250
+config DEBUG_UART_8250
+	def_bool ARCH_DOVE || ARCH_EBSA110 || \
+		(FOOTBRIDGE && !DEBUG_DC21285_PORT) || \
+		ARCH_GEMINI || ARCH_IOP13XX || ARCH_IOP32X || \
+		ARCH_IOP33X || ARCH_IXP4XX || ARCH_KIRKWOOD || \
+		ARCH_LPC32XX || ARCH_MV78XX0 || ARCH_ORION5X || ARCH_RPC
+
+config DEBUG_UART_PHYS
+	hex "Physical base address of debug UART"
+	default 0x01c20000 if DEBUG_DAVINCI_DMx_UART0
+	default 0x01c28000 if DEBUG_SUNXI_UART0
+	default 0x01c28400 if DEBUG_SUNXI_UART1
+	default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
+	default 0x01d0d000 if DEBUG_DAVINCI_DA8XX_UART2
+	default 0x02530c00 if DEBUG_KEYSTONE_UART0
+	default 0x02531000 if DEBUG_KEYSTONE_UART1
+	default 0x03010fe0 if ARCH_RPC
+	default 0x08108300 if DEBUG_DAVINCI_TNETV107X_UART1
+	default 0x10009000 if DEBUG_REALVIEW_STD_PORT || DEBUG_CNS3XXX || \
+				DEBUG_VEXPRESS_UART0_CA9
+	default 0x1010c000 if DEBUG_REALVIEW_PB1176_PORT
+	default 0x10124000 if DEBUG_RK3X_UART0
+	default 0x10126000 if DEBUG_RK3X_UART1
+	default 0x101f1000 if ARCH_VERSATILE
+	default 0x101fb000 if DEBUG_NOMADIK_UART
+	default 0x16000000 if ARCH_INTEGRATOR
+	default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
+	default 0x20060000 if DEBUG_RK29_UART0
+	default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
+	default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
+	default 0x20201000 if DEBUG_BCM2835
+	default 0x40090000 if ARCH_LPC32XX
+	default 0x40100000 if DEBUG_PXA_UART1
+	default 0x42000000 if ARCH_GEMINI
+	default 0x7c0003f8 if FOOTBRIDGE
+	default 0x80230000 if DEBUG_PICOXCELL_UART
+	default 0x80070000 if DEBUG_IMX23_UART
+	default 0x80074000 if DEBUG_IMX28_UART
+	default 0x808c0000 if ARCH_EP93XX
+	default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
+	default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX
+	default 0xc0013000 if DEBUG_U300_UART
+	default 0xc8000000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
+	default 0xc8000003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
+	default 0xd0000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
+	default 0xd0012000 if DEBUG_MVEBU_UART
+	default 0xd4017000 if DEBUG_MMP_UART2
+	default 0xd4018000 if DEBUG_MMP_UART3
+	default 0xe0000000 if ARCH_SPEAR13XX
+	default 0xf0000be0 if ARCH_EBSA110
+	default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
+	default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
+				ARCH_ORION5X
+	default 0xfe800000 if ARCH_IOP32X
+	default 0xffc02000 if DEBUG_SOCFPGA_UART
+	default 0xffd82340 if ARCH_IOP13XX
+	default 0xfff36000 if DEBUG_HIGHBANK_UART
+	default 0xfffff700 if ARCH_IOP33X
+	depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
+		DEBUG_UART_8250 || DEBUG_UART_PL01X
+
+config DEBUG_UART_VIRT
+	hex "Virtual base address of debug UART"
+	default 0xe0010fe0 if ARCH_RPC
+	default 0xf0000be0 if ARCH_EBSA110
+	default 0xf0009000 if DEBUG_CNS3XXX
+	default 0xf01fb000 if DEBUG_NOMADIK_UART
+	default 0xf0201000 if DEBUG_BCM2835
+	default 0xf11f1000 if ARCH_VERSATILE
+	default 0xf1600000 if ARCH_INTEGRATOR
+	default 0xf1c28000 if DEBUG_SUNXI_UART0
+	default 0xf1c28400 if DEBUG_SUNXI_UART1
+	default 0xf2100000 if DEBUG_PXA_UART1
+	default 0xf4090000 if ARCH_LPC32XX
+	default 0xf4200000 if ARCH_GEMINI
+	default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9
+	default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1
+	default 0xfb009000 if DEBUG_REALVIEW_STD_PORT
+	default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT
+	default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
+	default 0xfd000000 if ARCH_SPEAR13XX
+	default 0xfd012000 if ARCH_MV78XX0
+	default 0xfde12000 if ARCH_DOVE
+	default 0xfe012000 if ARCH_ORION5X
+	default 0xfe017000 if DEBUG_MMP_UART2
+	default 0xfe018000 if DEBUG_MMP_UART3
+	default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
+	default 0xfe230000 if DEBUG_PICOXCELL_UART
+	default 0xfe800000 if ARCH_IOP32X
+	default 0xfeb24000 if DEBUG_RK3X_UART0
+	default 0xfeb26000 if DEBUG_RK3X_UART1
+	default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
+	default 0xfeb31000 if DEBUG_KEYSTONE_UART1
+	default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
+	default 0xfed60000 if DEBUG_RK29_UART0
+	default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
+	default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
+	default 0xfec02000 if DEBUG_SOCFPGA_UART
+	default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
+	default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
+	default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
+	default 0xfed12000 if ARCH_KIRKWOOD
+	default 0xfedc0000 if ARCH_EP93XX
+	default 0xfee003f8 if FOOTBRIDGE
+	default 0xfee08300 if DEBUG_DAVINCI_TNETV107X_UART1
+	default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
+	default 0xfee36000 if DEBUG_HIGHBANK_UART
+	default 0xfee82340 if ARCH_IOP13XX
+	default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
+	default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
+	default 0xfefff700 if ARCH_IOP33X
+	default 0xff003000 if DEBUG_U300_UART
+	default DEBUG_UART_PHYS if !MMU
+	depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
+		DEBUG_UART_8250 || DEBUG_UART_PL01X
+
+config DEBUG_UART_8250_SHIFT
+	int "Register offset shift for the 8250 debug UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	default 0 if FOOTBRIDGE || ARCH_IOP32X
+	default 2
+
+config DEBUG_UART_8250_WORD
+	bool "Use 32-bit accesses for 8250 UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	depends on DEBUG_UART_8250_SHIFT >= 2
+	default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART || \
+		ARCH_KEYSTONE || \
+		DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
+		DEBUG_DAVINCI_DA8XX_UART2 || DEBUG_DAVINCI_TNETV107X_UART1
+
+config DEBUG_UART_8250_FLOW_CONTROL
+	bool "Enable flow control for 8250 UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	default y if ARCH_EBSA110 || FOOTBRIDGE || ARCH_GEMINI || ARCH_RPC
+
 config DEBUG_UNCOMPRESS
 	bool
-	depends on ARCH_MULTIPLATFORM
+	depends on ARCH_MULTIPLATFORM || ARCH_MSM
 	default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
 		     !DEBUG_TEGRA_UART
 	help
@@ -820,7 +1066,7 @@ config DEBUG_UNCOMPRESS
 
 config UNCOMPRESS_INCLUDE
 	string
-	default "debug/uncompress.h" if ARCH_MULTIPLATFORM
+	default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM
 	default "mach/uncompress.h"
 
 config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6fd2cea..a37a50f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -190,6 +190,7 @@ machine-$(CONFIG_ARCH_S5PV210)		+= s5pv210
 machine-$(CONFIG_ARCH_SA1100)		+= sa1100
 machine-$(CONFIG_ARCH_SHARK)		+= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	+= shmobile
+machine-$(CONFIG_ARCH_SHMOBILE_MULTI) 	+= shmobile
 machine-$(CONFIG_ARCH_SIRF)		+= prima2
 machine-$(CONFIG_ARCH_SOCFPGA)		+= socfpga
 machine-$(CONFIG_ARCH_STI)		+= sti
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644
index 0000000..19c9d65
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,44 @@
+for-next contents for 3.12: 
+Format is a little different from before in an attempt to make it easier to read:
+
+<next/* branch>
+	<topic branch>
+		<contents>
+		<...>
+	<...>
+
+
+next/fixes-non-critical
+	renesas/fixes-for-3.12
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-fixes-for-v3.12
+	mvebu/fixes-non-critical
+		git://git.infradead.org/linux-mvebu.git tags/fixes-non-3.12
+	keystone/fixes-non-critical
+		git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git tags/keystone-fixes-non-critical
+
+next/cleanup
+	localtimer/removal
+		git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git tags/remove-local-timers
+	patch
+		ARM: OMAP2+: Fix fallout from localtimer divorce and SMP=n
+		ARM: imx: fix mismerge of localtimer code
+	renesas/cleanup
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-cleanup-for-v3.12
+
+next/boards
+	renesas/backlight
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-backlight-for-v3.12
+
+next/dt
+	renesas/dt
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-dt-for-v3.12
+		based on renesas/cleanup
+
+olof/vexpress -- unstable branch for vexpress mcpm/spc patches
+	vexpress/mcpm
+		git://git.linaro.org/people/nico/linux mcpm+tc2
+	patches
+		Documentation: devicetree: arm: rename SPC device tree bindings to SCC
+		ARM: vexpress: move spc driver back under mach-vexpress
+		ARM: vexpress: make spc code TC2-only
+		ARM: vexpress: don't print virtual address in dmesg
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
index e2d6363..e7f8092 100644
--- a/arch/arm/boot/compressed/head-shmobile.S
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -55,12 +55,47 @@ __tmp_stack:
 __continue:
 #endif /* CONFIG_ZBOOT_ROM_MMC || CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI */
 
-	/* Set board ID necessary for boot */
-	ldr	r7, 1f				@ Set machine type register
-	mov	r8, #0				@ pass null pointer as atag
+	adr	r0, dtb_info
+	ldmia	r0, {r1, r3, r4, r5, r7}
+
+	sub	r0, r0, r1		@ calculate the delta offset
+	add	r5, r5, r0		@ _edata
+
+	ldr	lr, [r5, #0]		@ check if valid DTB is present
+	cmp	lr, r3
+	bne	0f
+
+	add	r9, r7, #31		@ rounded up to a multiple
+	bic	r9, r9, #31		@ ... of 32 bytes
+
+	add	r6, r9, r5		@ copy from _edata
+	add	r9, r9, r4		@ to MEMORY_START
+
+1:	ldmdb	r6!, {r0 - r3, r10 - r12, lr}
+	cmp	r6, r5
+	stmdb	r9!, {r0 - r3, r10 - r12, lr}
+	bhi	1b
+
+	/* Success: Zero board ID, pointer to start of memory for atag/dtb */
+	mov	r7, #0
+	mov	r8, r4
 	b	2f
 
-1 :	.long MACH_TYPE
+	.align	2
+dtb_info:
+	.word	dtb_info
+#ifndef __ARMEB__
+	.word	0xedfe0dd0		@ sig is 0xd00dfeed big endian
+#else
+	.word	0xd00dfeed
+#endif
+	.word	MEMORY_START
+	.word	_edata
+	.word	0x4000			@ maximum DTB size
+0:
+	/* Failure: Zero board ID, NULL atag/dtb */
+	mov 	r7, #0
+	mov	r8, #0			@ pass null pointer as atag
 2 :
 
 #endif /* CONFIG_ZBOOT_ROM */
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 641b3c9..5052c29 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -47,19 +47,21 @@ dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
 	da850-evm.dtb
 dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
 	dove-cubox.dtb \
+	dove-d2plug.dtb \
 	dove-dove-db.dtb
 dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos4210-smdkv310.dtb \
 	exynos4210-trats.dtb \
 	exynos4210-universal_c210.dtb \
 	exynos4412-odroidx.dtb \
-	exynos4412-smdk4412.dtb \
 	exynos4412-origen.dtb \
+	exynos4412-smdk4412.dtb \
+	exynos4412-trats2.dtb \
 	exynos5250-arndale.dtb \
-	exynos5440-sd5v1.dtb \
 	exynos5250-smdk5250.dtb \
 	exynos5250-snow.dtb \
 	exynos5420-smdk5420.dtb \
+	exynos5440-sd5v1.dtb \
 	exynos5440-ssdk5440.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
 	ecx-2000.dtb
@@ -83,12 +85,14 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \
 	kirkwood-lschlv2.dtb \
 	kirkwood-lsxhl.dtb \
 	kirkwood-mplcec4.dtb \
+	kirkwood-mv88f6281gtw-ge.dtb \
 	kirkwood-netgear_readynas_duo_v2.dtb \
 	kirkwood-ns2.dtb \
 	kirkwood-ns2lite.dtb \
 	kirkwood-ns2max.dtb \
 	kirkwood-ns2mini.dtb \
 	kirkwood-nsa310.dtb \
+	kirkwood-nsa310a.dtb \
 	kirkwood-sheevaplug.dtb \
 	kirkwood-sheevaplug-esata.dtb \
 	kirkwood-topkick.dtb \
@@ -100,7 +104,9 @@ dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
 	msm8960-cdp.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
 	armada-370-mirabox.dtb \
+	armada-370-netgear-rn102.dtb \
 	armada-370-rd.dtb \
+	armada-xp-axpwifiap.dtb \
 	armada-xp-db.dtb \
 	armada-xp-gp.dtb \
 	armada-xp-openblocks-ax3-4.dtb
@@ -112,6 +118,8 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx27-pdk.dtb \
 	imx27-phytec-phycore-som.dtb \
 	imx27-phytec-phycore-rdk.dtb \
+	imx27-phytec-phycard-s-som.dtb \
+	imx27-phytec-phycard-s-rdk.dtb \
 	imx31-bug.dtb \
 	imx51-apf51.dtb \
 	imx51-apf51dev.dtb \
@@ -131,6 +139,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx6q-sabrelite.dtb \
 	imx6q-sabresd.dtb \
 	imx6q-sbc6x.dtb \
+	imx6q-wandboard.dtb \
 	imx6sl-evk.dtb \
 	vf610-twr.dtb
 dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
@@ -143,7 +152,9 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
 	imx28-cfa10037.dtb \
 	imx28-cfa10049.dtb \
 	imx28-cfa10055.dtb \
+	imx28-cfa10056.dtb \
 	imx28-cfa10057.dtb \
+	imx28-cfa10058.dtb \
 	imx28-evk.dtb \
 	imx28-m28evk.dtb \
 	imx28-sps1.dtb \
@@ -183,15 +194,21 @@ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
 	ccu9540.dtb
 dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
+	emev2-kzm9d-reference.dtb \
 	r8a7740-armadillo800eva.dtb \
 	r8a7778-bockw.dtb \
+	r8a7778-bockw-reference.dtb \
 	r8a7740-armadillo800eva-reference.dtb \
+	r8a7779-marzen.dtb \
 	r8a7779-marzen-reference.dtb \
 	r8a7790-lager.dtb \
+	r8a7790-lager-reference.dtb \
 	sh73a0-kzm9g.dtb \
 	sh73a0-kzm9g-reference.dtb \
 	r8a73a4-ape6evm.dtb \
+	r8a73a4-ape6evm-reference.dtb \
 	sh7372-mackerel.dtb
+dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d-reference.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb \
 	socfpga_vt.dtb
 dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
@@ -224,8 +241,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
 	tegra30-beaver.dtb \
 	tegra30-cardhu-a02.dtb \
 	tegra30-cardhu-a04.dtb \
-	tegra114-dalmore.dtb \
-	tegra114-pluto.dtb
+	tegra114-dalmore.dtb
 dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \
 	versatile-pb.dtb
 dtb-$(CONFIG_ARCH_U300) += ste-u300.dtb
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 0c8ad17..62124c7 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
 
 / {
 	model = "TI AM335x EVM-SK";
@@ -298,7 +299,7 @@
 
 	backlight {
 		compatible = "pwm-backlight";
-		pwms = <&ecap2 0 50000 1>;
+		pwms = <&ecap2 0 50000 PWM_POLARITY_INVERTED>;
 		brightness-levels = <0 58 61 66 75 90 125 170 255>;
 		default-brightness-level = <8>;
 	};
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index beee169..90ce29d 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -14,7 +14,7 @@
  */
 
 /dts-v1/;
-/include/ "armada-370.dtsi"
+#include "armada-370.dtsi"
 
 / {
 	model = "Marvell Armada 370 Evaluation Board";
@@ -30,6 +30,9 @@
 	};
 
 	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
+
 		internal-regs {
 			serial@12000 {
 				clock-frequency = <200000000>;
diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts
index 45b1077..2471d9d 100644
--- a/arch/arm/boot/dts/armada-370-mirabox.dts
+++ b/arch/arm/boot/dts/armada-370-mirabox.dts
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "armada-370.dtsi"
+#include "armada-370.dtsi"
 
 / {
 	model = "Globalscale Mirabox";
@@ -25,6 +25,25 @@
 	};
 
 	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
+
+		pcie-controller {
+			status = "okay";
+
+			/* Internal mini-PCIe connector */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			/* Connected on the PCB to a USB 3.0 XHCI controller */
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+		};
+
 		internal-regs {
 			serial@12000 {
 				clock-frequency = <200000000>;
@@ -120,22 +139,6 @@
 					reg = <0x25>;
 				};
 			};
-
-			pcie-controller {
-				status = "okay";
-
-				/* Internal mini-PCIe connector */
-				pcie@1,0 {
-					/* Port 0, Lane 0 */
-					status = "okay";
-				};
-
-				/* Connected on the PCB to a USB 3.0 XHCI controller */
-				pcie@2,0 {
-					/* Port 1, Lane 0 */
-					status = "okay";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
new file mode 100644
index 0000000..05e4485
--- /dev/null
+++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
@@ -0,0 +1,179 @@
+/*
+ * Device Tree file for NETGEAR ReadyNAS 102
+ *
+ * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.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.
+ */
+
+/dts-v1/;
+
+#include "armada-370.dtsi"
+
+/ {
+	model = "NETGEAR ReadyNAS 102";
+	compatible = "netgear,readynas-102", "marvell,armada370", "marvell,armada-370-xp";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>; /* 512 MB */
+	};
+
+	soc {
+		internal-regs {
+			serial@12000 {
+				clock-frequency = <200000000>;
+				status = "okay";
+			};
+
+			sata@a0000 {
+				nr-ports = <2>;
+				status = "okay";
+			};
+
+			pinctrl {
+				power_led_pin: power-led-pin {
+					marvell,pins = "mpp57";
+					marvell,function = "gpio";
+				};
+				sata1_led_pin: sata1-led-pin {
+					marvell,pins = "mpp15";
+					marvell,function = "gpio";
+				};
+
+				sata2_led_pin: sata2-led-pin {
+					marvell,pins = "mpp14";
+					marvell,function = "gpio";
+				};
+
+				backup_led_pin: backup-led-pin {
+					marvell,pins = "mpp56";
+					marvell,function = "gpio";
+				};
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 {
+					reg = <0>;
+				};
+			};
+
+			ethernet@74000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+
+			usb@50000 {
+				status = "okay";
+			};
+
+			i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				clock-frequency = <100000>;
+				status = "okay";
+
+				g762: g762@3e {
+					compatible = "gmt,g762";
+					reg = <0x3e>;
+					clocks = <&g762_clk>; /* input clock */
+					fan_gear_mode = <0>;
+					fan_startv = <1>;
+					pwm_polarity = <0>;
+				};
+			};
+
+			pcie-controller {
+				status = "okay";
+
+				/* Connected to Marvell SATA controller */
+				pcie@1,0 {
+					/* Port 0, Lane 0 */
+					status = "okay";
+				};
+
+				/* Connected to FL1009 USB 3.0 controller */
+				pcie@2,0 {
+					/* Port 1, Lane 0 */
+					status = "okay";
+				};
+			};
+		};
+	};
+
+	clocks {
+	       #address-cells = <1>;
+	       #size-cells = <0>;
+
+	       g762_clk: fixedclk {
+			 compatible = "fixed-clock";
+			 #clock-cells = <0>;
+			 clock-frequency = <8192>;
+	       };
+	};
+
+	gpio_leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = < &power_led_pin
+			      &sata1_led_pin
+			      &sata2_led_pin
+			      &backup_led_pin >;
+		pinctrl-names = "default";
+
+		blue_power_led {
+			label = "rn102:blue:pwr";
+			gpios = <&gpio1 25 1>;  /* GPIO 57 Active Low */
+			linux,default-trigger = "heartbeat";
+		};
+
+		green_sata1_led {
+			label = "rn102:green:sata1";
+			gpios = <&gpio0 15 1>;  /* GPIO 15 Active Low */
+			default-state = "on";
+		};
+
+		green_sata2_led {
+			label = "rn102:green:sata2";
+			gpios = <&gpio0 14 1>;   /* GPIO 14 Active Low */
+			default-state = "on";
+		};
+
+		green_backup_led {
+			label = "rn102:green:backup";
+			gpios = <&gpio1 24 1>;   /* GPIO 56 Active Low */
+			default-state = "on";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@1 {
+			label = "Power Button";
+			linux,code = <116>;     /* KEY_POWER */
+			gpios = <&gpio1 30 1>;
+		};
+
+		button@2 {
+			label = "Reset Button";
+			linux,code = <0x198>;   /* KEY_RESTART */
+			gpios = <&gpio0 6 1>;
+		};
+
+		button@3 {
+			label = "Backup Button";
+			linux,code = <133>;     /* KEY_COPY */
+			gpios = <&gpio1 26 1>;
+		};
+	};
+
+};
diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts
index a3a2fed..0b3acf3 100644
--- a/arch/arm/boot/dts/armada-370-rd.dts
+++ b/arch/arm/boot/dts/armada-370-rd.dts
@@ -12,7 +12,7 @@
  */
 
 /dts-v1/;
-/include/ "armada-370.dtsi"
+#include "armada-370.dtsi"
 
 / {
 	model = "Marvell Armada 370 Reference Design";
@@ -28,6 +28,9 @@
 	};
 
 	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
+
 		internal-regs {
 			serial@12000 {
 				clock-frequency = <200000000>;
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 90b1176..0032616 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -18,6 +18,8 @@
 
 /include/ "skeleton64.dtsi"
 
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
 / {
 	model = "Marvell Armada 370 and XP SoC";
 	compatible = "marvell,armada-370-xp";
@@ -38,24 +40,80 @@
 	};
 
 	soc {
-		#address-cells = <1>;
+		#address-cells = <2>;
 		#size-cells = <1>;
-		compatible = "simple-bus";
+		controller = <&mbusc>;
 		interrupt-parent = <&mpic>;
-		ranges = <0          0 0xd0000000 0x0100000 /* internal registers */
-			  0xe0000000 0 0xe0000000 0x8100000 /* PCIe */>;
+		pcie-mem-aperture = <0xe0000000 0x8000000>;
+		pcie-io-aperture  = <0xe8000000 0x100000>;
+
+		devbus-bootcs {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs0 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs1 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs2 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs3 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
 
 		internal-regs {
 			compatible = "simple-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
-			ranges;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
 
 			mpic: interrupt-controller@20000 {
 				compatible = "marvell,mpic";
 				#interrupt-cells = <1>;
 				#size-cells = <1>;
 				interrupt-controller;
+				msi-controller;
 			};
 
 			coherency-fabric@20200 {
@@ -121,7 +179,6 @@
 
 			i2c0: i2c@11000 {
 				compatible = "marvell,mv64xxx-i2c";
-				reg = <0x11000 0x20>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				interrupts = <31>;
@@ -132,7 +189,6 @@
 
 			i2c1: i2c@11100 {
 				compatible = "marvell,mv64xxx-i2c";
-				reg = <0x11100 0x20>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				interrupts = <32>;
@@ -195,50 +251,6 @@
 				status = "disabled";
 			};
 
-			devbus-bootcs@10400 {
-				compatible = "marvell,mvebu-devbus";
-				reg = <0x10400 0x8>;
-				#address-cells = <1>;
-				#size-cells = <1>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
-
-			devbus-cs0@10408 {
-				compatible = "marvell,mvebu-devbus";
-				reg = <0x10408 0x8>;
-				#address-cells = <1>;
-				#size-cells = <1>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
-
-			devbus-cs1@10410 {
-				compatible = "marvell,mvebu-devbus";
-				reg = <0x10410 0x8>;
-				#address-cells = <1>;
-				#size-cells = <1>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
-
-			devbus-cs2@10418 {
-				compatible = "marvell,mvebu-devbus";
-				reg = <0x10418 0x8>;
-				#address-cells = <1>;
-				#size-cells = <1>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
-
-			devbus-cs3@10420 {
-				compatible = "marvell,mvebu-devbus";
-				reg = <0x10420 0x8>;
-				#address-cells = <1>;
-				#size-cells = <1>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
 		};
 	};
  };
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index fa3dfc6..6297e6e 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -15,7 +15,7 @@
  * common to all Armada SoCs.
  */
 
-/include/ "armada-370-xp.dtsi"
+#include "armada-370-xp.dtsi"
 /include/ "skeleton.dtsi"
 
 / {
@@ -29,8 +29,67 @@
 	};
 
 	soc {
-		ranges = <0          0xd0000000 0x0100000 /* internal registers */
-			  0xe0000000 0xe0000000 0x8100000 /* PCIe */>;
+		compatible = "marvell,armada370-mbus", "simple-bus";
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0xe0) 0 0x100000>;
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0       1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0       1 0 /* Port 0.0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x08, 0xe8) 0       1 0 /* Port 1.0 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x08, 0xe0) 0       1 0 /* Port 1.0 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+                                ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+                                          0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 58>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+                                ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+                                          0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 62>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 9>;
+				status = "disabled";
+			};
+		};
+
 		internal-regs {
 			system-controller@18200 {
 				compatible = "marvell,armada-370-xp-system-controller";
@@ -78,7 +137,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
 			};
 
@@ -89,7 +148,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>, <90>;
 			};
 
@@ -100,7 +159,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <91>;
 			};
 
@@ -155,6 +214,14 @@
 				};
 			};
 
+			i2c0: i2c@11000 {
+				reg = <0x11000 0x20>;
+			};
+
+			i2c1: i2c@11100 {
+				reg = <0x11100 0x20>;
+			};
+
 			usb@50000 {
 				clocks = <&coreclk 0>;
 			};
@@ -169,54 +236,6 @@
 					0x18304 0x4>;
 				status = "okay";
 			};
-
-			pcie-controller {
-				compatible = "marvell,armada-370-pcie";
-				status = "disabled";
-				device_type = "pci";
-
-				#address-cells = <3>;
-				#size-cells = <2>;
-
-				bus-range = <0x00 0xff>;
-
-				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
-					0x82000000 0 0x80000 0x80000 0 0x00002000   /* Port 1.0 registers */
-					0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-					0x81000000 0 0          0xe8000000 0 0x00100000>; /* downstream I/O */
-
-				pcie@1,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
-					reg = <0x0800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 58>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 5>;
-					status = "disabled";
-				};
-
-				pcie@2,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
-					reg = <0x1000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 62>;
-					marvell,pcie-port = <1>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 9>;
-					status = "disabled";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-axpwifiap.dts b/arch/arm/boot/dts/armada-xp-axpwifiap.dts
new file mode 100644
index 0000000..c5fe572
--- /dev/null
+++ b/arch/arm/boot/dts/armada-xp-axpwifiap.dts
@@ -0,0 +1,164 @@
+/*
+ * Device Tree file for Marvell RD-AXPWiFiAP.
+ *
+ * Note: this board is shipped with a new generation boot loader that
+ * remaps internal registers at 0xf1000000. Therefore, if earlyprintk
+ * is used, the CONFIG_DEBUG_MVEBU_UART_ALTERNATE option should be
+ * used.
+ *
+ * Copyright (C) 2013 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+	model = "Marvell RD-AXPWiFiAP";
+	compatible = "marvell,rd-axpwifiap", "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x40000000>; /* 1GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+		pcie-controller {
+			status = "okay";
+
+			/* First mini-PCIe port */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			/* Second mini-PCIe port */
+			pcie@2,0 {
+				/* Port 0, Lane 1 */
+				status = "okay";
+			};
+
+			/* Renesas uPD720202 USB 3.0 controller */
+			pcie@3,0 {
+				/* Port 0, Lane 3 */
+				status = "okay";
+			};
+		};
+
+		internal-regs {
+			pinctrl {
+				pinctrl-0 = <&pmx_phy_int>;
+				pinctrl-names = "default";
+
+				pmx_ge0: pmx-ge0 {
+					marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
+						       "mpp4", "mpp5", "mpp6", "mpp7",
+						       "mpp8", "mpp9", "mpp10", "mpp11";
+					marvell,function = "ge0";
+				};
+
+				pmx_ge1: pmx-ge1 {
+					marvell,pins = "mpp12", "mpp13", "mpp14", "mpp15",
+						       "mpp16", "mpp17", "mpp18", "mpp19",
+						       "mpp20", "mpp21", "mpp22", "mpp23";
+					marvell,function = "ge1";
+				};
+
+				pmx_keys: pmx-keys {
+					marvell,pins = "mpp33";
+					marvell,function = "gpio";
+				};
+
+				pmx_spi: pmx-spi {
+					marvell,pins = "mpp36", "mpp37", "mpp38", "mpp39";
+					marvell,function = "spi";
+				};
+
+				pmx_phy_int: pmx-phy-int {
+					marvell,pins = "mpp32";
+					marvell,function = "gpio";
+				};
+			};
+
+			serial@12000 {
+				clock-frequency = <250000000>;
+				status = "okay";
+			};
+
+			serial@12100 {
+				clock-frequency = <250000000>;
+				status = "okay";
+			};
+
+			sata@a0000 {
+				nr-ports = <1>;
+				status = "okay";
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 {
+					reg = <0>;
+				};
+
+				phy1: ethernet-phy@1 {
+					reg = <1>;
+				};
+			};
+
+			ethernet@70000 {
+				pinctrl-0 = <&pmx_ge0>;
+				pinctrl-names = "default";
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+			ethernet@74000 {
+				pinctrl-0 = <&pmx_ge1>;
+				pinctrl-names = "default";
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "rgmii-id";
+			};
+
+			spi0: spi@10600 {
+				status = "okay";
+				pinctrl-0 = <&pmx_spi>;
+				pinctrl-names = "default";
+
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a13";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_keys>;
+		pinctrl-names = "default";
+
+		button@1 {
+			label = "Factory Reset Button";
+			linux,code = <141>; /* KEY_SETUP */
+			gpios = <&gpio1 1 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
index e28e68f..bcf6d79 100644
--- a/arch/arm/boot/dts/armada-xp-db.dts
+++ b/arch/arm/boot/dts/armada-xp-db.dts
@@ -14,7 +14,7 @@
  */
 
 /dts-v1/;
-/include/ "armada-xp-mv78460.dtsi"
+#include "armada-xp-mv78460.dtsi"
 
 / {
 	model = "Marvell Armada XP Evaluation Board";
@@ -30,9 +30,70 @@
 	};
 
 	soc {
-		ranges = <0          0 0xd0000000 0x100000	/* Internal registers 1MiB */
-			  0xe0000000 0 0xe0000000 0x8100000     /* PCIe */
-			  0xf0000000 0 0xf0000000 0x1000000>;	/* Device Bus, NOR 16MiB   */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000>;
+
+		devbus-bootcs {
+			status = "okay";
+
+			/* Device Bus parameters are required */
+
+			/* Read parameters */
+			devbus,bus-width    = <8>;
+			devbus,turn-off-ps  = <60000>;
+			devbus,badr-skew-ps = <0>;
+			devbus,acc-first-ps = <124000>;
+			devbus,acc-next-ps  = <248000>;
+			devbus,rd-setup-ps  = <0>;
+			devbus,rd-hold-ps   = <0>;
+
+			/* Write parameters */
+			devbus,sync-enable = <0>;
+			devbus,wr-high-ps  = <60000>;
+			devbus,wr-low-ps   = <60000>;
+			devbus,ale-wr-ps   = <60000>;
+
+			/* NOR 16 MiB */
+			nor@0 {
+				compatible = "cfi-flash";
+				reg = <0 0x1000000>;
+				bank-width = <2>;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			/*
+			 * All 6 slots are physically present as
+			 * standard PCIe slots on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+			pcie@2,0 {
+				/* Port 0, Lane 1 */
+				status = "okay";
+			};
+			pcie@3,0 {
+				/* Port 0, Lane 2 */
+				status = "okay";
+			};
+			pcie@4,0 {
+				/* Port 0, Lane 3 */
+				status = "okay";
+			};
+			pcie@9,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+			pcie@10,0 {
+				/* Port 3, Lane 0 */
+				status = "okay";
+			};
+		};
 
 		internal-regs {
 			serial@12000 {
@@ -127,68 +188,6 @@
 					spi-max-frequency = <20000000>;
 				};
 			};
-
-			pcie-controller {
-				status = "okay";
-
-				/*
-				 * All 6 slots are physically present as
-				 * standard PCIe slots on the board.
-				 */
-				pcie@1,0 {
-					/* Port 0, Lane 0 */
-					status = "okay";
-				};
-				pcie@2,0 {
-					/* Port 0, Lane 1 */
-					status = "okay";
-				};
-				pcie@3,0 {
-					/* Port 0, Lane 2 */
-					status = "okay";
-				};
-				pcie@4,0 {
-					/* Port 0, Lane 3 */
-					status = "okay";
-				};
-				pcie@9,0 {
-					/* Port 2, Lane 0 */
-					status = "okay";
-				};
-				pcie@10,0 {
-					/* Port 3, Lane 0 */
-					status = "okay";
-				};
-			};
-
-			devbus-bootcs@10400 {
-				status = "okay";
-				ranges = <0 0xf0000000 0x1000000>;
-
-				/* Device Bus parameters are required */
-
-				/* Read parameters */
-				devbus,bus-width    = <8>;
-				devbus,turn-off-ps  = <60000>;
-				devbus,badr-skew-ps = <0>;
-				devbus,acc-first-ps = <124000>;
-				devbus,acc-next-ps  = <248000>;
-				devbus,rd-setup-ps  = <0>;
-				devbus,rd-hold-ps   = <0>;
-
-				/* Write parameters */
-				devbus,sync-enable = <0>;
-				devbus,wr-high-ps  = <60000>;
-				devbus,wr-low-ps   = <60000>;
-				devbus,ale-wr-ps   = <60000>;
-
-				/* NOR 16 MiB */
-				nor@0 {
-					compatible = "cfi-flash";
-					reg = <0 0x1000000>;
-					bank-width = <2>;
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts
index c87b2de..2298e4a 100644
--- a/arch/arm/boot/dts/armada-xp-gp.dts
+++ b/arch/arm/boot/dts/armada-xp-gp.dts
@@ -14,7 +14,7 @@
  */
 
 /dts-v1/;
-/include/ "armada-xp-mv78460.dtsi"
+#include "armada-xp-mv78460.dtsi"
 
 / {
 	model = "Marvell Armada XP Development Board DB-MV784MP-GP";
@@ -39,9 +39,58 @@
 	};
 
 	soc {
-		ranges = <0          0 0xd0000000 0x100000  /* Internal registers 1MiB */
-			  0xe0000000 0 0xe0000000 0x8100000 /* PCIe */
-			  0xf0000000 0 0xf0000000 0x1000000 /* Device Bus, NOR 16MiB  */>;
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000>;
+
+		devbus-bootcs {
+			status = "okay";
+
+			/* Device Bus parameters are required */
+
+			/* Read parameters */
+			devbus,bus-width    = <8>;
+			devbus,turn-off-ps  = <60000>;
+			devbus,badr-skew-ps = <0>;
+			devbus,acc-first-ps = <124000>;
+			devbus,acc-next-ps  = <248000>;
+			devbus,rd-setup-ps  = <0>;
+			devbus,rd-hold-ps   = <0>;
+
+			/* Write parameters */
+			devbus,sync-enable = <0>;
+			devbus,wr-high-ps  = <60000>;
+			devbus,wr-low-ps   = <60000>;
+			devbus,ale-wr-ps   = <60000>;
+
+			/* NOR 16 MiB */
+			nor@0 {
+				compatible = "cfi-flash";
+				reg = <0 0x1000000>;
+				bank-width = <2>;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			/*
+			 * The 3 slots are physically present as
+			 * standard PCIe slots on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+			pcie@9,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+			pcie@10,0 {
+				/* Port 3, Lane 0 */
+				status = "okay";
+			};
+		};
 
 		internal-regs {
 			serial@12000 {
@@ -126,56 +175,6 @@
 					spi-max-frequency = <108000000>;
 				};
 			};
-
-			devbus-bootcs@10400 {
-				status = "okay";
-				ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf000000, size 0x1000000 */
-
-				/* Device Bus parameters are required */
-
-				/* Read parameters */
-				devbus,bus-width    = <8>;
-				devbus,turn-off-ps  = <60000>;
-				devbus,badr-skew-ps = <0>;
-				devbus,acc-first-ps = <124000>;
-				devbus,acc-next-ps  = <248000>;
-				devbus,rd-setup-ps  = <0>;
-				devbus,rd-hold-ps   = <0>;
-
-				/* Write parameters */
-				devbus,sync-enable = <0>;
-				devbus,wr-high-ps  = <60000>;
-				devbus,wr-low-ps   = <60000>;
-				devbus,ale-wr-ps   = <60000>;
-
-				/* NOR 16 MiB */
-				nor@0 {
-					compatible = "cfi-flash";
-					reg = <0 0x1000000>;
-					bank-width = <2>;
-				};
-			};
-
-			pcie-controller {
-				status = "okay";
-
-				/*
-				 * The 3 slots are physically present as
-				 * standard PCIe slots on the board.
-				 */
-				pcie@1,0 {
-					/* Port 0, Lane 0 */
-					status = "okay";
-				};
-				pcie@9,0 {
-					/* Port 2, Lane 0 */
-					status = "okay";
-				};
-				pcie@10,0 {
-					/* Port 3, Lane 0 */
-					status = "okay";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index f8eaa38..3f5e612 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -13,7 +13,7 @@
  * common to all Armada XP SoCs.
  */
 
-/include/ "armada-xp.dtsi"
+#include "armada-xp.dtsi"
 
 / {
 	model = "Marvell Armada XP MV78230 SoC";
@@ -44,6 +44,125 @@
 	};
 
 	soc {
+		/*
+		 * MV78230 has 2 PCIe units Gen2.0: One unit can be
+		 * configured as x4 or quad x1 lanes. One unit is
+		 * x4/x1.
+		 */
+		pcie-controller {
+			compatible = "marvell,armada-xp-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
+				0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
+				0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+				0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
+				0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
+				0x81000000 0x2 0       MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 0.1 IO  */
+				0x82000000 0x3 0       MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 0.2 MEM */
+				0x81000000 0x3 0       MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
+				0x82000000 0x4 0       MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
+				0x81000000 0x4 0       MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
+				0x82000000 0x9 0       MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+				0x81000000 0x9 0       MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 58>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 59>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <1>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				reg = <0x1800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 60>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <2>;
+				clocks = <&gateclk 7>;
+				status = "disabled";
+			};
+
+			pcie@4,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
+				reg = <0x2000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 61>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <3>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			pcie@9,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+				reg = <0x4800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+					  0x81000000 0 0 0x81000000 0x9 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 99>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 26>;
+				status = "disabled";
+			};
+		};
+
 		internal-regs {
 			pinctrl {
 				compatible = "marvell,mv78230-pinctrl";
@@ -63,7 +182,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
 			};
 
@@ -74,113 +193,9 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>;
 			};
-
-			/*
-			 * MV78230 has 2 PCIe units Gen2.0: One unit can be
-			 * configured as x4 or quad x1 lanes. One unit is
-			 * x4/x1.
-			 */
-			pcie-controller {
-				compatible = "marvell,armada-xp-pcie";
-				status = "disabled";
-				device_type = "pci";
-
-#address-cells = <3>;
-#size-cells = <2>;
-
-				bus-range = <0x00 0xff>;
-
-				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
-					0x82000000 0 0x42000 0x42000 0 0x00002000   /* Port 2.0 registers */
-					0x82000000 0 0x44000 0x44000 0 0x00002000   /* Port 0.1 registers */
-					0x82000000 0 0x48000 0x48000 0 0x00002000   /* Port 0.2 registers */
-					0x82000000 0 0x4c000 0x4c000 0 0x00002000   /* Port 0.3 registers */
-					0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-					0x81000000 0 0	  0xe8000000 0 0x00100000>; /* downstream I/O */
-
-				pcie@1,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
-					reg = <0x0800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 58>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 5>;
-					status = "disabled";
-				};
-
-				pcie@2,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
-					reg = <0x1000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 59>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <1>;
-					clocks = <&gateclk 6>;
-					status = "disabled";
-				};
-
-				pcie@3,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
-					reg = <0x1800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 60>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <2>;
-					clocks = <&gateclk 7>;
-					status = "disabled";
-				};
-
-				pcie@4,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
-					reg = <0x2000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 61>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <3>;
-					clocks = <&gateclk 8>;
-					status = "disabled";
-				};
-
-				pcie@9,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-					reg = <0x4800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 99>;
-					marvell,pcie-port = <2>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 26>;
-					status = "disabled";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 2d9335d..3e9fd13 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -13,7 +13,7 @@
  * common to all Armada XP SoCs.
  */
 
-/include/ "armada-xp.dtsi"
+#include "armada-xp.dtsi"
 
 / {
 	model = "Marvell Armada XP MV78260 SoC";
@@ -45,6 +45,146 @@
 	};
 
 	soc {
+		/*
+		 * MV78260 has 3 PCIe units Gen2.0: Two units can be
+		 * configured as x4 or quad x1 lanes. One unit is
+		 * x4/x1.
+		 */
+		pcie-controller {
+			compatible = "marvell,armada-xp-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
+				0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
+				0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+				0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
+				0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000   /* Port 3.0 registers */
+				0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 0.1 IO  */
+				0x82000000 0x3 0     MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 0.2 MEM */
+				0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
+				0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
+				0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
+				0x82000000 0x9 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+				0x81000000 0x9 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+				0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
+				0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 58>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+                                ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+                                          0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 59>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <1>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				reg = <0x1800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 60>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <2>;
+				clocks = <&gateclk 7>;
+				status = "disabled";
+			};
+
+			pcie@4,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
+				reg = <0x2000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 61>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <3>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			pcie@9,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+				reg = <0x4800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+					  0x81000000 0 0 0x81000000 0x9 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 99>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 26>;
+				status = "disabled";
+			};
+
+			pcie@10,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
+				reg = <0x5000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
+					  0x81000000 0 0 0x81000000 0xa 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 103>;
+				marvell,pcie-port = <3>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 27>;
+				status = "disabled";
+			};
+		};
+
 		internal-regs {
 			pinctrl {
 				compatible = "marvell,mv78260-pinctrl";
@@ -64,7 +204,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
 			};
 
@@ -75,7 +215,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>, <90>;
 			};
 
@@ -86,7 +226,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <91>;
 			};
 
@@ -97,128 +237,6 @@
 				clocks = <&gateclk 1>;
 				status = "disabled";
 			};
-
-			/*
-			 * MV78260 has 3 PCIe units Gen2.0: Two units can be
-			 * configured as x4 or quad x1 lanes. One unit is
-			 * x4/x1.
-			 */
-			pcie-controller {
-				compatible = "marvell,armada-xp-pcie";
-				status = "disabled";
-				device_type = "pci";
-
-				#address-cells = <3>;
-				#size-cells = <2>;
-
-				bus-range = <0x00 0xff>;
-
-				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
-					0x82000000 0 0x42000 0x42000 0 0x00002000   /* Port 2.0 registers */
-					0x82000000 0 0x44000 0x44000 0 0x00002000   /* Port 0.1 registers */
-					0x82000000 0 0x48000 0x48000 0 0x00002000   /* Port 0.2 registers */
-					0x82000000 0 0x4c000 0x4c000 0 0x00002000   /* Port 0.3 registers */
-					0x82000000 0 0x80000 0x80000 0 0x00002000   /* Port 1.0 registers */
-					0x82000000 0 0x82000 0x82000 0 0x00002000   /* Port 3.0 registers */
-					0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-					0x81000000 0 0	  0xe8000000 0 0x00100000>; /* downstream I/O */
-
-				pcie@1,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
-					reg = <0x0800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 58>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 5>;
-					status = "disabled";
-				};
-
-				pcie@2,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
-					reg = <0x1000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 59>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <1>;
-					clocks = <&gateclk 6>;
-					status = "disabled";
-				};
-
-				pcie@3,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
-					reg = <0x1800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 60>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <2>;
-					clocks = <&gateclk 7>;
-					status = "disabled";
-				};
-
-				pcie@4,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
-					reg = <0x2000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 61>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <3>;
-					clocks = <&gateclk 8>;
-					status = "disabled";
-				};
-
-				pcie@9,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-					reg = <0x4800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 99>;
-					marvell,pcie-port = <2>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 26>;
-					status = "disabled";
-				};
-
-				pcie@10,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
-					reg = <0x5000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 103>;
-					marvell,pcie-port = <3>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 27>;
-					status = "disabled";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index c7b1f4d..31ba6d8 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -13,7 +13,7 @@
  * common to all Armada XP SoCs.
  */
 
-/include/ "armada-xp.dtsi"
+#include "armada-xp.dtsi"
 
 / {
 	model = "Marvell Armada XP MV78460 SoC";
@@ -61,6 +61,228 @@
 	};
 
 	soc {
+		/*
+		 * MV78460 has 4 PCIe units Gen2.0: Two units can be
+		 * configured as x4 or quad x1 lanes. Two units are
+		 * x4/x1.
+		 */
+		pcie-controller {
+			compatible = "marvell,armada-xp-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
+				0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
+				0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+				0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
+				0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000   /* Port 3.0 registers */
+				0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000   /* Port 1.1 registers */
+				0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000   /* Port 1.2 registers */
+				0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000   /* Port 1.3 registers */
+				0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 0.1 IO  */
+				0x82000000 0x3 0     MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 0.2 MEM */
+				0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
+				0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
+				0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
+
+				0x82000000 0x5 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+				0x81000000 0x5 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+				0x82000000 0x6 0     MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
+				0x81000000 0x6 0     MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO  */
+				0x82000000 0x7 0     MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
+				0x81000000 0x7 0     MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO  */
+				0x82000000 0x8 0     MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
+				0x81000000 0x8 0     MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO  */
+
+				0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+				0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */
+
+				0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
+				0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 58>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 59>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <1>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
+				reg = <0x1800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 60>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <2>;
+				clocks = <&gateclk 7>;
+				status = "disabled";
+			};
+
+			pcie@4,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
+				reg = <0x2000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 61>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <3>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			pcie@5,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+				reg = <0x2800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+					  0x81000000 0 0 0x81000000 0x5 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 62>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 9>;
+				status = "disabled";
+			};
+
+			pcie@6,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
+				reg = <0x3000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
+					  0x81000000 0 0 0x81000000 0x6 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 63>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <1>;
+				clocks = <&gateclk 10>;
+				status = "disabled";
+			};
+
+			pcie@7,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
+				reg = <0x3800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
+					  0x81000000 0 0 0x81000000 0x7 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 64>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <2>;
+				clocks = <&gateclk 11>;
+				status = "disabled";
+			};
+
+			pcie@8,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
+				reg = <0x4000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
+					  0x81000000 0 0 0x81000000 0x8 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 65>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <3>;
+				clocks = <&gateclk 12>;
+				status = "disabled";
+			};
+
+			pcie@9,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
+				reg = <0x4800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+					  0x81000000 0 0 0x81000000 0x9 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 99>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 26>;
+				status = "disabled";
+			};
+
+			pcie@10,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82005000 0 0x82000 0 0x2000>;
+				reg = <0x5000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
+					  0x81000000 0 0 0x81000000 0xa 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 103>;
+				marvell,pcie-port = <3>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 27>;
+				status = "disabled";
+			};
+		};
+
 		internal-regs {
 			pinctrl {
 				compatible = "marvell,mv78460-pinctrl";
@@ -80,7 +302,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
 			};
 
@@ -91,7 +313,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>, <90>;
 			};
 
@@ -102,7 +324,7 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 				interrupt-controller;
-				#interrupts-cells = <2>;
+				#interrupt-cells = <2>;
 				interrupts = <91>;
 			};
 
@@ -113,194 +335,6 @@
 				clocks = <&gateclk 1>;
 				status = "disabled";
 			};
-
-			/*
-			 * MV78460 has 4 PCIe units Gen2.0: Two units can be
-			 * configured as x4 or quad x1 lanes. Two units are
-			 * x4/x1.
-			 */
-			pcie-controller {
-				compatible = "marvell,armada-xp-pcie";
-				status = "disabled";
-				device_type = "pci";
-
-				#address-cells = <3>;
-				#size-cells = <2>;
-
-				bus-range = <0x00 0xff>;
-
-				ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000   /* Port 0.0 registers */
-					0x82000000 0 0x42000 0x42000 0 0x00002000   /* Port 2.0 registers */
-					0x82000000 0 0x44000 0x44000 0 0x00002000   /* Port 0.1 registers */
-					0x82000000 0 0x48000 0x48000 0 0x00002000   /* Port 0.2 registers */
-					0x82000000 0 0x4c000 0x4c000 0 0x00002000   /* Port 0.3 registers */
-					0x82000000 0 0x80000 0x80000 0 0x00002000   /* Port 1.0 registers */
-					0x82000000 0 0x82000 0x82000 0 0x00002000   /* Port 3.0 registers */
-					0x82000000 0 0x84000 0x84000 0 0x00002000   /* Port 1.1 registers */
-					0x82000000 0 0x88000 0x88000 0 0x00002000   /* Port 1.2 registers */
-					0x82000000 0 0x8c000 0x8c000 0 0x00002000   /* Port 1.3 registers */
-					0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-					0x81000000 0 0	  0xe8000000 0 0x00100000>; /* downstream I/O */
-
-				pcie@1,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
-					reg = <0x0800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 58>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 5>;
-					status = "disabled";
-				};
-
-				pcie@2,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
-					reg = <0x1000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 59>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <1>;
-					clocks = <&gateclk 6>;
-					status = "disabled";
-				};
-
-				pcie@3,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
-					reg = <0x1800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 60>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <2>;
-					clocks = <&gateclk 7>;
-					status = "disabled";
-				};
-
-				pcie@4,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
-					reg = <0x2000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 61>;
-					marvell,pcie-port = <0>;
-					marvell,pcie-lane = <3>;
-					clocks = <&gateclk 8>;
-					status = "disabled";
-				};
-
-				pcie@5,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
-					reg = <0x2800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 62>;
-					marvell,pcie-port = <1>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 9>;
-					status = "disabled";
-				};
-
-				pcie@6,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
-					reg = <0x3000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 63>;
-					marvell,pcie-port = <1>;
-					marvell,pcie-lane = <1>;
-					clocks = <&gateclk 10>;
-					status = "disabled";
-				};
-
-				pcie@7,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
-					reg = <0x3800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 64>;
-					marvell,pcie-port = <1>;
-					marvell,pcie-lane = <2>;
-					clocks = <&gateclk 11>;
-					status = "disabled";
-				};
-
-				pcie@8,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
-					reg = <0x4000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 65>;
-					marvell,pcie-port = <1>;
-					marvell,pcie-lane = <3>;
-					clocks = <&gateclk 12>;
-					status = "disabled";
-				};
-				pcie@9,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
-					reg = <0x4800 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 99>;
-					marvell,pcie-port = <2>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 26>;
-					status = "disabled";
-				};
-
-				pcie@10,0 {
-					device_type = "pci";
-					assigned-addresses = <0x82005000 0 0x82000 0 0x2000>;
-					reg = <0x5000 0 0 0 0>;
-					#address-cells = <3>;
-					#size-cells = <2>;
-					#interrupt-cells = <1>;
-					ranges;
-					interrupt-map-mask = <0 0 0 0>;
-					interrupt-map = <0 0 0 0 &mpic 103>;
-					marvell,pcie-port = <3>;
-					marvell,pcie-lane = <0>;
-					clocks = <&gateclk 27>;
-					status = "disabled";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
index 8f51045..5695afc 100644
--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
@@ -11,7 +11,7 @@
  */
 
 /dts-v1/;
-/include/ "armada-xp-mv78260.dtsi"
+#include "armada-xp-mv78260.dtsi"
 
 / {
 	model = "PlatHome OpenBlocks AX3-4 board";
@@ -27,9 +27,46 @@
 	};
 
 	soc {
-		ranges = <0          0 0xd0000000 0x100000	/* Internal registers 1MiB */
-			  0xe0000000 0 0xe0000000 0x8100000     /* PCIe */
-			  0xf0000000 0 0xf0000000 0x8000000     /* Device Bus, NOR 128MiB   */>;
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>;
+
+		devbus-bootcs {
+			status = "okay";
+
+			/* Device Bus parameters are required */
+
+			/* Read parameters */
+			devbus,bus-width    = <8>;
+			devbus,turn-off-ps  = <60000>;
+			devbus,badr-skew-ps = <0>;
+			devbus,acc-first-ps = <124000>;
+			devbus,acc-next-ps  = <248000>;
+			devbus,rd-setup-ps  = <0>;
+			devbus,rd-hold-ps   = <0>;
+
+			/* Write parameters */
+			devbus,sync-enable = <0>;
+			devbus,wr-high-ps  = <60000>;
+			devbus,wr-low-ps   = <60000>;
+			devbus,ale-wr-ps   = <60000>;
+
+			/* NOR 128 MiB */
+			nor@0 {
+				compatible = "cfi-flash";
+				reg = <0 0x8000000>;
+				bank-width = <2>;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/* Internal mini-PCIe connector */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+		};
 
 		internal-regs {
 			serial@12000 {
@@ -148,49 +185,6 @@
 			usb@51000 {
 				status = "okay";
 			};
-
-			/* USB interface in the mini-PCIe connector */
-			usb@52000 {
-				status = "okay";
-			};
-
-			devbus-bootcs@10400 {
-				status = "okay";
-				ranges = <0 0xf0000000 0x8000000>; /* @addr 0xf000000, size 0x8000000 */
-
-				/* Device Bus parameters are required */
-
-				/* Read parameters */
-				devbus,bus-width    = <8>;
-				devbus,turn-off-ps  = <60000>;
-				devbus,badr-skew-ps = <0>;
-				devbus,acc-first-ps = <124000>;
-				devbus,acc-next-ps  = <248000>;
-				devbus,rd-setup-ps  = <0>;
-				devbus,rd-hold-ps   = <0>;
-
-				/* Write parameters */
-				devbus,sync-enable = <0>;
-				devbus,wr-high-ps  = <60000>;
-				devbus,wr-low-ps   = <60000>;
-				devbus,ale-wr-ps   = <60000>;
-
-				/* NOR 128 MiB */
-				nor@0 {
-					compatible = "cfi-flash";
-					reg = <0 0x8000000>;
-					bank-width = <2>;
-				};
-			};
-
-			pcie-controller {
-				status = "okay";
-				/* Internal mini-PCIe connector */
-				pcie@1,0 {
-					/* Port 0, Lane 0 */
-					status = "okay";
-				};
-			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 416eb94..8815c5b 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -16,7 +16,7 @@
  * common to all Armada SoCs.
  */
 
-/include/ "armada-370-xp.dtsi"
+#include "armada-370-xp.dtsi"
 
 / {
 	model = "Marvell Armada XP family SoC";
@@ -27,6 +27,13 @@
 	};
 
 	soc {
+		compatible = "marvell,armadaxp-mbus", "simple-bus";
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
+		};
+
 		internal-regs {
 			L2: l2-cache {
 				compatible = "marvell,aurora-system-cache";
@@ -138,6 +145,16 @@
 				};
 			};
 
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x100>;
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+				reg = <0x11100 0x100>;
+			};
+
 			usb@50000 {
 				clocks = <&gateclk 18>;
 			};
diff --git a/arch/arm/boot/dts/dove-cm-a510.dts b/arch/arm/boot/dts/dove-cm-a510.dts
index 61a8062..50c0d69 100644
--- a/arch/arm/boot/dts/dove-cm-a510.dts
+++ b/arch/arm/boot/dts/dove-cm-a510.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "Compulab CM-A510";
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index 5cae2ab..4af59b6 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "SolidRun CuBox";
@@ -42,6 +42,8 @@
 			regulator-always-on;
 			regulator-boot-on;
 			gpio = <&gpio0 1 0>;
+			pinctrl-0 = <&pmx_gpio_1>;
+			pinctrl-names = "default";
 		};
 	};
 
@@ -53,10 +55,24 @@
 			clock-frequency = <25000000>;
 		};
 	};
+
+	ir_recv: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio0 19 1>;
+		pinctrl-0 = <&pmx_gpio_19>;
+		pinctrl-names = "default";
+	};
 };
 
 &uart0 { status = "okay"; };
 &sata0 { status = "okay"; };
+&mdio { status = "okay"; };
+&eth { status = "okay"; };
+
+&ethphy {
+	compatible = "marvell,88e1310";
+	reg = <1>;
+};
 
 &i2c0 {
 	status = "okay";
@@ -103,6 +119,7 @@
 	status = "okay";
 	/* sdio0 card detect is connected to wrong pin on CuBox */
 	cd-gpios = <&gpio0 12 1>;
+	pinctrl-0 = <&pmx_sdio0 &pmx_gpio_12>;
 };
 
 &spi0 {
@@ -115,23 +132,3 @@
 		reg = <0>;
 	};
 };
-
-&pinctrl {
-	pinctrl-0 = <&pmx_gpio_1 &pmx_gpio_12>;
-	pinctrl-names = "default";
-
-	pmx_gpio_1: pmx-gpio-1 {
-		marvell,pins = "mpp1";
-		marvell,function = "gpio";
-	};
-
-	pmx_gpio_12: pmx-gpio-12 {
-		marvell,pins = "mpp12";
-		marvell,function = "gpio";
-	};
-
-	pmx_gpio_18: pmx-gpio-18 {
-		marvell,pins = "mpp18";
-		marvell,function = "gpio";
-	};
-};
diff --git a/arch/arm/boot/dts/dove-d2plug.dts b/arch/arm/boot/dts/dove-d2plug.dts
new file mode 100644
index 0000000..c11d363
--- /dev/null
+++ b/arch/arm/boot/dts/dove-d2plug.dts
@@ -0,0 +1,69 @@
+/dts-v1/;
+
+#include "dove.dtsi"
+
+/ {
+	model = "Globalscale D2Plug";
+	compatible = "globalscale,d2plug", "marvell,dove";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_gpio_0 &pmx_gpio_1 &pmx_gpio_2>;
+		pinctrl-names = "default";
+
+		wlan-ap {
+			label = "wlan-ap";
+			gpios = <&gpio0 0 1>;
+		};
+
+		wlan-act {
+			label = "wlan-act";
+			gpios = <&gpio0 1 1>;
+		};
+
+		bluetooth-act {
+			label = "bt-act";
+			gpios = <&gpio0 2 1>;
+		};
+	};
+};
+
+&uart0 { status = "okay"; };
+&sata0 { status = "okay"; };
+&i2c0 { status = "okay"; };
+&mdio { status = "okay"; };
+&eth { status = "okay"; };
+
+/* Samsung M8G2F eMMC */
+&sdio0 {
+	status = "okay";
+	non-removable;
+	bus-width = <4>;
+};
+
+/* Marvell SD8787 WLAN/BT */
+&sdio1 {
+	status = "okay";
+	non-removable;
+	bus-width = <4>;
+};
+
+&spi0 {
+	status = "okay";
+
+	/* spi0.0: 4M Flash Macronix MX25L3205D */
+	spi-flash@0 {
+		compatible = "st,m25l3205d";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
diff --git a/arch/arm/boot/dts/dove-dove-db.dts b/arch/arm/boot/dts/dove-dove-db.dts
index e5a920b..bb725dc 100644
--- a/arch/arm/boot/dts/dove-dove-db.dts
+++ b/arch/arm/boot/dts/dove-dove-db.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "Marvell DB-MV88AP510-BP Development Board";
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 6cab468..867b945 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -1,8 +1,11 @@
 /include/ "skeleton.dtsi"
 
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
 / {
 	compatible = "marvell,dove";
 	model = "Marvell Armada 88AP510 SoC";
+	interrupt-parent = <&intc>;
 
 	aliases {
 		gpio0 = &gpio0;
@@ -10,252 +13,510 @@
 		gpio2 = &gpio2;
 	};
 
-	soc@f1000000 {
-		compatible = "simple-bus";
+	cpus {
 		#address-cells = <1>;
-		#size-cells = <1>;
-		interrupt-parent = <&intc>;
-
-		ranges = <0xc8000000 0xc8000000 0x0100000   /* CESA SRAM   1M */
-		          0xe0000000 0xe0000000 0x8000000   /* PCIe0 Mem 128M */
-		          0xe8000000 0xe8000000 0x8000000   /* PCIe1 Mem 128M */
-		          0xf0000000 0xf0000000 0x0100000   /* ScratchPad  1M */
-		          0x00000000 0xf1000000 0x1000000   /* SB/NB regs 16M */
-		          0xf2000000 0xf2000000 0x0100000   /* PCIe0 I/O   1M */
-		          0xf2100000 0xf2100000 0x0100000   /* PCIe0 I/O   1M */
-		          0xf8000000 0xf8000000 0x8000000>; /* BootROM   128M */
-
-		l2: l2-cache {
-			compatible = "marvell,tauros2-cache";
-			marvell,tauros2-cache-features = <0>;
-		};
+		#size-cells = <0>;
 
-		intc: interrupt-controller {
-			compatible = "marvell,orion-intc";
-			interrupt-controller;
-			#interrupt-cells = <1>;
-			reg = <0x20204 0x04>, <0x20214 0x04>;
+		cpu0: cpu@0 {
+			compatible = "marvell,pj4a", "marvell,sheeva-v7";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <0>;
 		};
+	};
 
-		core_clk: core-clocks@d0214 {
-			compatible = "marvell,dove-core-clock";
-			reg = <0xd0214 0x4>;
-			#clock-cells = <1>;
-		};
+	l2: l2-cache {
+		compatible = "marvell,tauros2-cache";
+		marvell,tauros2-cache-features = <0>;
+	};
 
-		gate_clk: clock-gating-control@d0038 {
-			compatible = "marvell,dove-gating-clock";
-			reg = <0xd0038 0x4>;
-			clocks = <&core_clk 0>;
-			#clock-cells = <1>;
-		};
+	mbus {
+		compatible = "marvell,dove-mbus", "marvell,mbus", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		pcie-mem-aperture = <0xe0000000 0x10000000>; /* 256M MEM space */
+		pcie-io-aperture  = <0xf2000000 0x00200000>; /*   2M I/O space */
 
-		thermal: thermal@d001c {
-			compatible = "marvell,dove-thermal";
-			reg = <0xd001c 0x0c>, <0xd005c 0x08>;
-		};
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x0100000   /* MBUS regs  1M */
+			  MBUS_ID(0xf0, 0x02) 0 0xf1800000 0x1000000   /* AXI  regs 16M */
+			  MBUS_ID(0x01, 0xfd) 0 0xf8000000 0x8000000   /* BootROM  128M */
+			  MBUS_ID(0x03, 0x01) 0 0xc8000000 0x0100000   /* CESA SRAM  1M */
+			  MBUS_ID(0x0d, 0x00) 0 0xf0000000 0x0100000>; /* PMU  SRAM  1M */
 
-		uart0: serial@12000 {
-			compatible = "ns16550a";
-			reg = <0x12000 0x100>;
-			reg-shift = <2>;
-			interrupts = <7>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+		internal-regs {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 MBUS_ID(0xf0, 0x01) 0 0x0100000   /* MBUS regs  1M */
+				  0x00800000 MBUS_ID(0xf0, 0x02) 0 0x1000000   /* AXI  regs 16M */
+				  0xffffe000 MBUS_ID(0x03, 0x01) 0 0x0000800   /* CESA SRAM  2k */
+				  0xfffff000 MBUS_ID(0x0d, 0x00) 0 0x0000800>; /* PMU  SRAM  2k */
+
+			mbusc: mbus-ctrl@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x80>, <0x800100 0x8>;
+			};
 
-		uart1: serial@12100 {
-			compatible = "ns16550a";
-			reg = <0x12100 0x100>;
-			reg-shift = <2>;
-			interrupts = <8>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			timer: timer@20300 {
+				compatible = "marvell,orion-timer";
+				reg = <0x20300 0x20>;
+				interrupt-parent = <&bridge_intc>;
+				interrupts = <1>, <2>;
+				clocks = <&core_clk 0>;
+			};
 
-		uart2: serial@12200 {
-			compatible = "ns16550a";
-			reg = <0x12000 0x100>;
-			reg-shift = <2>;
-			interrupts = <9>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			intc: main-interrupt-ctrl@20200 {
+				compatible = "marvell,orion-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x20200 0x10>, <0x20210 0x10>;
+			};
 
-		uart3: serial@12300 {
-			compatible = "ns16550a";
-			reg = <0x12100 0x100>;
-			reg-shift = <2>;
-			interrupts = <10>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			bridge_intc: bridge-interrupt-ctrl@20110 {
+				compatible = "marvell,orion-bridge-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x20110 0x8>;
+				interrupts = <0>;
+				marvell,#interrupts = <5>;
+			};
 
-		gpio0: gpio@d0400 {
-			compatible = "marvell,orion-gpio";
-			#gpio-cells = <2>;
-			gpio-controller;
-			reg = <0xd0400 0x20>;
-			ngpios = <32>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <12>, <13>, <14>, <60>;
-		};
+			core_clk: core-clocks@d0214 {
+				compatible = "marvell,dove-core-clock";
+				reg = <0xd0214 0x4>;
+				#clock-cells = <1>;
+			};
 
-		gpio1: gpio@d0420 {
-			compatible = "marvell,orion-gpio";
-			#gpio-cells = <2>;
-			gpio-controller;
-			reg = <0xd0420 0x20>;
-			ngpios = <32>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <61>;
-		};
+			gate_clk: clock-gating-ctrl@d0038 {
+				compatible = "marvell,dove-gating-clock";
+				reg = <0xd0038 0x4>;
+				clocks = <&core_clk 0>;
+				#clock-cells = <1>;
+			};
 
-		gpio2: gpio@e8400 {
-			compatible = "marvell,orion-gpio";
-			#gpio-cells = <2>;
-			gpio-controller;
-			reg = <0xe8400 0x0c>;
-			ngpios = <8>;
-		};
+			thermal: thermal-diode@d001c {
+				compatible = "marvell,dove-thermal";
+				reg = <0xd001c 0x0c>, <0xd005c 0x08>;
+			};
 
-		pinctrl: pinctrl@d0200 {
-			compatible = "marvell,dove-pinctrl";
-			reg = <0xd0200 0x10>;
-			clocks = <&gate_clk 22>;
-		};
+			uart0: serial@12000 {
+				compatible = "ns16550a";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <7>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
 
-		spi0: spi@10600 {
-			compatible = "marvell,orion-spi";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			interrupts = <6>;
-			reg = <0x10600 0x28>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			uart1: serial@12100 {
+				compatible = "ns16550a";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <8>;
+				clocks = <&core_clk 0>;
+				pinctrl-0 = <&pmx_uart1>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
 
-		spi1: spi@14600 {
-			compatible = "marvell,orion-spi";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <1>;
-			interrupts = <5>;
-			reg = <0x14600 0x28>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			uart2: serial@12200 {
+				compatible = "ns16550a";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <9>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
 
-		i2c0: i2c@11000 {
-			compatible = "marvell,mv64xxx-i2c";
-			reg = <0x11000 0x20>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <11>;
-			clock-frequency = <400000>;
-			timeout-ms = <1000>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			uart3: serial@12300 {
+				compatible = "ns16550a";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
 
-		ehci0: usb-host@50000 {
-			compatible = "marvell,orion-ehci";
-			reg = <0x50000 0x1000>;
-			interrupts = <24>;
-			clocks = <&gate_clk 0>;
-			status = "okay";
-		};
+			gpio0: gpio-ctrl@d0400 {
+				compatible = "marvell,orion-gpio";
+				#gpio-cells = <2>;
+				gpio-controller;
+				reg = <0xd0400 0x20>;
+				ngpios = <32>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <12>, <13>, <14>, <60>;
+			};
 
-		ehci1: usb-host@51000 {
-			compatible = "marvell,orion-ehci";
-			reg = <0x51000 0x1000>;
-			interrupts = <25>;
-			clocks = <&gate_clk 1>;
-			status = "okay";
-		};
+			gpio1: gpio-ctrl@d0420 {
+				compatible = "marvell,orion-gpio";
+				#gpio-cells = <2>;
+				gpio-controller;
+				reg = <0xd0420 0x20>;
+				ngpios = <32>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <61>;
+			};
 
-		sdio0: sdio@92000 {
-			compatible = "marvell,dove-sdhci";
-			reg = <0x92000 0x100>;
-			interrupts = <35>, <37>;
-			clocks = <&gate_clk 8>;
-			status = "disabled";
-		};
+			gpio2: gpio-ctrl@e8400 {
+				compatible = "marvell,orion-gpio";
+				#gpio-cells = <2>;
+				gpio-controller;
+				reg = <0xe8400 0x0c>;
+				ngpios = <8>;
+			};
 
-		sdio1: sdio@90000 {
-			compatible = "marvell,dove-sdhci";
-			reg = <0x90000 0x100>;
-			interrupts = <36>, <38>;
-			clocks = <&gate_clk 9>;
-			status = "disabled";
-		};
+			pinctrl: pin-ctrl@d0200 {
+				compatible = "marvell,dove-pinctrl";
+				reg = <0xd0200 0x10>;
+				clocks = <&gate_clk 22>;
+
+				pmx_gpio_0: pmx-gpio-0 {
+					marvell,pins = "mpp0";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_1: pmx-gpio-1 {
+					marvell,pins = "mpp1";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_2: pmx-gpio-2 {
+					marvell,pins = "mpp2";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_3: pmx-gpio-3 {
+					marvell,pins = "mpp3";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_4: pmx-gpio-4 {
+					marvell,pins = "mpp4";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_5: pmx-gpio-5 {
+					marvell,pins = "mpp5";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_6: pmx-gpio-6 {
+					marvell,pins = "mpp6";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_7: pmx-gpio-7 {
+					marvell,pins = "mpp7";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_8: pmx-gpio-8 {
+					marvell,pins = "mpp8";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_9: pmx-gpio-9 {
+					marvell,pins = "mpp9";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_10: pmx-gpio-10 {
+					marvell,pins = "mpp10";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_11: pmx-gpio-11 {
+					marvell,pins = "mpp11";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_12: pmx-gpio-12 {
+					marvell,pins = "mpp12";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_13: pmx-gpio-13 {
+					marvell,pins = "mpp13";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_14: pmx-gpio-14 {
+					marvell,pins = "mpp14";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_15: pmx-gpio-15 {
+					marvell,pins = "mpp15";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_16: pmx-gpio-16 {
+					marvell,pins = "mpp16";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_17: pmx-gpio-17 {
+					marvell,pins = "mpp17";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_18: pmx-gpio-18 {
+					marvell,pins = "mpp18";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_19: pmx-gpio-19 {
+					marvell,pins = "mpp19";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_20: pmx-gpio-20 {
+					marvell,pins = "mpp20";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_21: pmx-gpio-21 {
+					marvell,pins = "mpp21";
+					marvell,function = "gpio";
+				};
+
+				pmx_camera: pmx-camera {
+					marvell,pins = "mpp_camera";
+					marvell,function = "camera";
+				};
+
+				pmx_camera_gpio: pmx-camera-gpio {
+					marvell,pins = "mpp_camera";
+					marvell,function = "gpio";
+				};
+
+				pmx_sdio0: pmx-sdio0 {
+					marvell,pins = "mpp_sdio0";
+					marvell,function = "sdio0";
+				};
+
+				pmx_sdio0_gpio: pmx-sdio0-gpio {
+					marvell,pins = "mpp_sdio0";
+					marvell,function = "gpio";
+				};
+
+				pmx_sdio1: pmx-sdio1 {
+					marvell,pins = "mpp_sdio1";
+					marvell,function = "sdio1";
+				};
+
+				pmx_sdio1_gpio: pmx-sdio1-gpio {
+					marvell,pins = "mpp_sdio1";
+					marvell,function = "gpio";
+				};
+
+				pmx_audio1_gpio: pmx-audio1-gpio {
+					marvell,pins = "mpp_audio1";
+					marvell,function = "gpio";
+				};
+
+				pmx_spi0: pmx-spi0 {
+					marvell,pins = "mpp_spi0";
+					marvell,function = "spi0";
+				};
+
+				pmx_spi0_gpio: pmx-spi0-gpio {
+					marvell,pins = "mpp_spi0";
+					marvell,function = "gpio";
+				};
+
+				pmx_uart1: pmx-uart1 {
+					marvell,pins = "mpp_uart1";
+					marvell,function = "uart1";
+				};
+
+				pmx_uart1_gpio: pmx-uart1-gpio {
+					marvell,pins = "mpp_uart1";
+					marvell,function = "gpio";
+				};
+
+				pmx_nand: pmx-nand {
+					marvell,pins = "mpp_nand";
+					marvell,function = "nand";
+				};
+
+				pmx_nand_gpo: pmx-nand-gpo {
+					marvell,pins = "mpp_nand";
+					marvell,function = "gpo";
+				};
+			};
 
-		sata0: sata@a0000 {
-			compatible = "marvell,orion-sata";
-			reg = <0xa0000 0x2400>;
-			interrupts = <62>;
-			clocks = <&gate_clk 3>;
-			nr-ports = <1>;
-			status = "disabled";
-		};
+			spi0: spi-ctrl@10600 {
+				compatible = "marvell,orion-spi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <6>;
+				reg = <0x10600 0x28>;
+				clocks = <&core_clk 0>;
+				pinctrl-0 = <&pmx_spi0>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
 
-		rtc@d8500 {
-			compatible = "marvell,orion-rtc";
-			reg = <0xd8500 0x20>;
-		};
+			spi1: spi-ctrl@14600 {
+				compatible = "marvell,orion-spi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <5>;
+				reg = <0x14600 0x28>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
 
-		crypto: crypto@30000 {
-			compatible = "marvell,orion-crypto";
-			reg = <0x30000 0x10000>,
-			      <0xc8000000 0x800>;
-			reg-names = "regs", "sram";
-			interrupts = <31>;
-			clocks = <&gate_clk 15>;
-			status = "okay";
-		};
+			i2c0: i2c-ctrl@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <11>;
+				clock-frequency = <400000>;
+				timeout-ms = <1000>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
 
-		xor0: dma-engine@60800 {
-			compatible = "marvell,orion-xor";
-			reg = <0x60800 0x100
-			       0x60a00 0x100>;
-			clocks = <&gate_clk 23>;
-			status = "okay";
-
-			channel0 {
-				interrupts = <39>;
-				dmacap,memcpy;
-				dmacap,xor;
+			ehci0: usb-host@50000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x50000 0x1000>;
+				interrupts = <24>;
+				clocks = <&gate_clk 0>;
+				status = "okay";
 			};
 
-			channel1 {
-				interrupts = <40>;
-				dmacap,memset;
-				dmacap,memcpy;
-				dmacap,xor;
+			ehci1: usb-host@51000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x51000 0x1000>;
+				interrupts = <25>;
+				clocks = <&gate_clk 1>;
+				status = "okay";
+			};
+
+			sdio0: sdio-host@92000 {
+				compatible = "marvell,dove-sdhci";
+				reg = <0x92000 0x100>;
+				interrupts = <35>, <37>;
+				clocks = <&gate_clk 8>;
+				pinctrl-0 = <&pmx_sdio0>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			sdio1: sdio-host@90000 {
+				compatible = "marvell,dove-sdhci";
+				reg = <0x90000 0x100>;
+				interrupts = <36>, <38>;
+				clocks = <&gate_clk 9>;
+				pinctrl-0 = <&pmx_sdio1>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			sata0: sata-host@a0000 {
+				compatible = "marvell,orion-sata";
+				reg = <0xa0000 0x2400>;
+				interrupts = <62>;
+				clocks = <&gate_clk 3>;
+				nr-ports = <1>;
+				status = "disabled";
+			};
+
+			rtc: real-time-clock@d8500 {
+				compatible = "marvell,orion-rtc";
+				reg = <0xd8500 0x20>;
+			};
+
+			crypto: crypto-engine@30000 {
+				compatible = "marvell,orion-crypto";
+				reg = <0x30000 0x10000>,
+				      <0xffffe000 0x800>;
+				reg-names = "regs", "sram";
+				interrupts = <31>;
+				clocks = <&gate_clk 15>;
+				status = "okay";
+			};
+
+			xor0: dma-engine@60800 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60800 0x100
+				       0x60a00 0x100>;
+				clocks = <&gate_clk 23>;
+				status = "okay";
+
+				channel0 {
+					interrupts = <39>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+
+				channel1 {
+					interrupts = <40>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+			};
+
+			xor1: dma-engine@60900 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+				clocks = <&gate_clk 24>;
+				status = "okay";
+
+				channel0 {
+					interrupts = <42>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+
+				channel1 {
+					interrupts = <43>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
 			};
-		};
 
-		xor1: dma-engine@60900 {
-			compatible = "marvell,orion-xor";
-			reg = <0x60900 0x100
-			       0x60b00 0x100>;
-			clocks = <&gate_clk 24>;
-			status = "okay";
-
-			channel0 {
-				interrupts = <42>;
-				dmacap,memcpy;
-				dmacap,xor;
+			mdio: mdio-bus@72004 {
+				compatible = "marvell,orion-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x72004 0x84>;
+				interrupts = <30>;
+				clocks = <&gate_clk 2>;
+				status = "disabled";
+
+				ethphy: ethernet-phy {
+					device-type = "ethernet-phy";
+					/* set phy address in board file */
+				};
 			};
 
-			channel1 {
-				interrupts = <43>;
-				dmacap,memset;
-				dmacap,memcpy;
-				dmacap,xor;
+			eth: ethernet-ctrl@72000 {
+				compatible = "marvell,orion-eth";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x72000 0x4000>;
+				clocks = <&gate_clk 2>;
+				marvell,tx-checksum-limit = <1600>;
+				status = "disabled";
+
+				ethernet-port@0 {
+					device_type = "network";
+					compatible = "marvell,orion-eth-port";
+					reg = <0>;
+					interrupts = <29>;
+					/* overwrite MAC address in bootloader */
+					local-mac-address = [00 00 00 00 00 00];
+					phy-handle = <&ethphy>;
+				};
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/emev2-kzm9d-reference.dts b/arch/arm/boot/dts/emev2-kzm9d-reference.dts
new file mode 100644
index 0000000..cceefda
--- /dev/null
+++ b/arch/arm/boot/dts/emev2-kzm9d-reference.dts
@@ -0,0 +1,57 @@
+/*
+ * Device Tree Source for the KZM9D board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+/dts-v1/;
+
+/include/ "emev2.dtsi"
+
+/ {
+	model = "EMEV2 KZM9D Board";
+	compatible = "renesas,kzm9d-reference", "renesas,emev2";
+
+	memory {
+		device_type = "memory";
+		reg = <0x40000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp";
+	};
+
+	reg_1p8v: regulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	reg_3p3v: regulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	lan9220@20000000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x20000000 0x10000>;
+		phy-mode = "mii";
+		interrupt-parent = <&gpio0>;
+		interrupts = <1 1>;	/* active high */
+		reg-io-width = <4>;
+		smsc,irq-active-high;
+		smsc,irq-push-pull;
+		vddvario-supply = <&reg_1p8v>;
+		vdd33a-supply = <&reg_3p3v>;
+	};
+};
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
index b9b3241..f92e812 100644
--- a/arch/arm/boot/dts/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -21,6 +21,6 @@
 	};
 
 	chosen {
-		bootargs = "console=tty0 console=ttyS1,115200n81 earlyprintk=serial8250-em.1,115200n81 mem=128M@0x40000000 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096";
+		bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp";
 	};
 };
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
index c8a8c08..9063a44 100644
--- a/arch/arm/boot/dts/emev2.dtsi
+++ b/arch/arm/boot/dts/emev2.dtsi
@@ -14,6 +14,14 @@
 	compatible = "renesas,emev2";
 	interrupt-parent = <&gic>;
 
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		gpio4 = &gpio4;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -38,6 +46,12 @@
 		      <0xe0020000 0x0100>;
 	};
 
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts = <0 120 4>,
+			     <0 121 4>;
+	};
+
 	sti@e0180000 {
 		compatible = "renesas,em-sti";
 		reg = <0xe0180000 0x54>;
@@ -67,4 +81,55 @@
 		reg = <0xe1050000 0x38>;
 		interrupts = <0 11 0>;
 	};
+
+	gpio0: gpio@e0050000 {
+		compatible = "renesas,em-gio";
+		reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
+		interrupts = <0 67 0>, <0 68 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <32>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+	gpio1: gpio@e0050080 {
+		compatible = "renesas,em-gio";
+		reg = <0xe0050080 0x2c>, <0xe00500c0 0x20>;
+		interrupts = <0 69 0>, <0 70 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <32>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+	gpio2: gpio@e0050100 {
+		compatible = "renesas,em-gio";
+		reg = <0xe0050100 0x2c>, <0xe0050140 0x20>;
+		interrupts = <0 71 0>, <0 72 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <32>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+	gpio3: gpio@e0050180 {
+		compatible = "renesas,em-gio";
+		reg = <0xe0050180 0x2c>, <0xe00501c0 0x20>;
+		interrupts = <0 73 0>, <0 74 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <32>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+	gpio4: gpio@e0050200 {
+		compatible = "renesas,em-gio";
+		reg = <0xe0050200 0x2c>, <0xe0050240 0x20>;
+		interrupts = <0 75 0>, <0 76 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <31>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 3f94fe8..597cfcf 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -36,6 +36,12 @@
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
 		i2c7 = &i2c_7;
+		csis0 = &csis_0;
+		csis1 = &csis_1;
+		fimc0 = &fimc_0;
+		fimc1 = &fimc_1;
+		fimc2 = &fimc_2;
+		fimc3 = &fimc_3;
 	};
 
 	chipid@10000000 {
@@ -92,6 +98,88 @@
 		reg = <0x10010000 0x400>;
 	};
 
+	camera {
+		compatible = "samsung,fimc", "simple-bus";
+		status = "disabled";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clock_cam: clock-controller {
+			 #clock-cells = <1>;
+		};
+
+		fimc_0: fimc@11800000 {
+			compatible = "samsung,exynos4210-fimc";
+			reg = <0x11800000 0x1000>;
+			interrupts = <0 84 0>;
+			clocks = <&clock 256>, <&clock 128>;
+			clock-names = "fimc", "sclk_fimc";
+			samsung,power-domain = <&pd_cam>;
+			samsung,sysreg = <&sys_reg>;
+			status = "disabled";
+		};
+
+		fimc_1: fimc@11810000 {
+			compatible = "samsung,exynos4210-fimc";
+			reg = <0x11810000 0x1000>;
+			interrupts = <0 85 0>;
+			clocks = <&clock 257>, <&clock 129>;
+			clock-names = "fimc", "sclk_fimc";
+			samsung,power-domain = <&pd_cam>;
+			samsung,sysreg = <&sys_reg>;
+			status = "disabled";
+		};
+
+		fimc_2: fimc@11820000 {
+			compatible = "samsung,exynos4210-fimc";
+			reg = <0x11820000 0x1000>;
+			interrupts = <0 86 0>;
+			clocks = <&clock 258>, <&clock 130>;
+			clock-names = "fimc", "sclk_fimc";
+			samsung,power-domain = <&pd_cam>;
+			samsung,sysreg = <&sys_reg>;
+			status = "disabled";
+		};
+
+		fimc_3: fimc@11830000 {
+			compatible = "samsung,exynos4210-fimc";
+			reg = <0x11830000 0x1000>;
+			interrupts = <0 87 0>;
+			clocks = <&clock 259>, <&clock 131>;
+			clock-names = "fimc", "sclk_fimc";
+			samsung,power-domain = <&pd_cam>;
+			samsung,sysreg = <&sys_reg>;
+			status = "disabled";
+		};
+
+		csis_0: csis@11880000 {
+			compatible = "samsung,exynos4210-csis";
+			reg = <0x11880000 0x4000>;
+			interrupts = <0 78 0>;
+			clocks = <&clock 260>, <&clock 134>;
+			clock-names = "csis", "sclk_csis";
+			bus-width = <4>;
+			samsung,power-domain = <&pd_cam>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		csis_1: csis@11890000 {
+			compatible = "samsung,exynos4210-csis";
+			reg = <0x11890000 0x4000>;
+			interrupts = <0 80 0>;
+			clocks = <&clock 261>, <&clock 135>;
+			clock-names = "csis", "sclk_csis";
+			bus-width = <2>;
+			samsung,power-domain = <&pd_cam>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
 	watchdog@10060000 {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x10060000 0x100>;
@@ -297,8 +385,8 @@
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x13920000 0x100>;
 		interrupts = <0 66 0>;
-		tx-dma-channel = <&pdma0 7>; /* preliminary */
-		rx-dma-channel = <&pdma0 6>; /* preliminary */
+		dmas = <&pdma0 7>, <&pdma0 6>;
+		dma-names = "tx", "rx";
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&clock 327>, <&clock 159>;
@@ -312,8 +400,8 @@
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x13930000 0x100>;
 		interrupts = <0 67 0>;
-		tx-dma-channel = <&pdma1 7>; /* preliminary */
-		rx-dma-channel = <&pdma1 6>; /* preliminary */
+		dmas = <&pdma1 7>, <&pdma1 6>;
+		dma-names = "tx", "rx";
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&clock 328>, <&clock 160>;
@@ -327,8 +415,8 @@
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x13940000 0x100>;
 		interrupts = <0 68 0>;
-		tx-dma-channel = <&pdma0 9>; /* preliminary */
-		rx-dma-channel = <&pdma0 8>; /* preliminary */
+		dmas = <&pdma0 9>, <&pdma0 8>;
+		dma-names = "tx", "rx";
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&clock 329>, <&clock 161>;
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
index 553bcea..a7c2128 100644
--- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -797,6 +797,29 @@
 			samsung,pin-pud = <0>;
 			samsung,pin-drv = <0>;
 		};
+
+		cam_port_a_io: cam-port-a-io {
+			samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
+					"gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
+					"gpj1-0", "gpj1-1", "gpj1-2", "gpj1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		cam_port_a_clk_active: cam-port-a-clk-active {
+			samsung,pins = "gpj1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		cam_port_a_clk_idle: cam-port-a-clk-idle {
+			samsung,pins = "gpj1-3";
+			samsung,pin-function = <0>;
+			samsung,pin-pud = <1>;
+			samsung,pin-drv = <0>;
+		};
 	};
 
 	pinctrl@03860000 {
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 94eebff..1c164f2 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -30,13 +30,62 @@
 		bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
 	};
 
-	vemmc_reg: voltage-regulator@0 {
-	        compatible = "regulator-fixed";
-		regulator-name = "VMEM_VDD_2.8V";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&gpk0 2 0>;
-		enable-active-high;
+	regulators {
+		compatible = "simple-bus";
+
+		vemmc_reg: regulator-0 {
+			compatible = "regulator-fixed";
+			regulator-name = "VMEM_VDD_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpk0 2 0>;
+			enable-active-high;
+		};
+
+		tsp_reg: regulator-1 {
+			compatible = "regulator-fixed";
+			regulator-name = "TSP_FIXED_VOLTAGES";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpl0 3 0>;
+			enable-active-high;
+		};
+
+		cam_af_28v_reg: regulator-2 {
+			compatible = "regulator-fixed";
+			regulator-name = "8M_AF_2.8V_EN";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpk1 1 0>;
+			enable-active-high;
+		};
+
+		cam_io_en_reg: regulator-3 {
+			compatible = "regulator-fixed";
+			regulator-name = "CAM_IO_EN";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpe2 1 0>;
+			enable-active-high;
+		};
+
+		cam_io_12v_reg: regulator-4 {
+			compatible = "regulator-fixed";
+			regulator-name = "8M_1.2V_EN";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			gpio = <&gpe2 5 0>;
+			enable-active-high;
+		};
+
+		vt_core_15v_reg: regulator-5 {
+			compatible = "regulator-fixed";
+			regulator-name = "VT_CORE_1.5V";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			gpio = <&gpe2 2 0>;
+			enable-active-high;
+		};
 	};
 
 	sdhci_emmc: sdhci@12510000 {
@@ -97,15 +146,6 @@
 		};
 	};
 
-	tsp_reg: voltage-regulator {
-		compatible = "regulator-fixed";
-		regulator-name = "TSP_FIXED_VOLTAGES";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&gpl0 3 0>;
-		enable-active-high;
-	};
-
 	i2c@13890000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-slave-addr = <0x10>;
@@ -218,6 +258,12 @@
 				     regulator-always-on;
 				};
 
+				vtcam_reg: LDO12 {
+				     regulator-name = "VT_CAM_1.8V";
+				     regulator-min-microvolt = <1800000>;
+				     regulator-max-microvolt = <1800000>;
+				};
+
 				vcclcd_reg: LDO13 {
 				     regulator-name = "VCC_3.3V_LCD";
 				     regulator-min-microvolt = <3300000>;
@@ -301,4 +347,26 @@
 			clock-frequency = <24000000>;
 		};
 	};
+
+	camera {
+		pinctrl-names = "default";
+		pinctrl-0 = <>;
+		status = "okay";
+
+		fimc_0: fimc@11800000 {
+			status = "okay";
+		};
+
+		fimc_1: fimc@11810000 {
+			status = "okay";
+		};
+
+		fimc_2: fimc@11820000 {
+			status = "okay";
+		};
+
+		fimc_3: fimc@11830000 {
+			status = "okay";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index b7f358a..057d682 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -72,7 +72,7 @@
 		};
 	};
 
-	clock: clock-controller@0x10030000 {
+	clock: clock-controller@10030000 {
 		compatible = "samsung,exynos4210-clock";
 		reg = <0x10030000 0x20000>;
 		#clock-cells = <1>;
@@ -125,4 +125,34 @@
 		clock-names = "sclk_fimg2d", "fimg2d";
 		status = "disabled";
 	};
+
+	camera {
+		clocks = <&clock 132>, <&clock 133>, <&clock 351>, <&clock 352>;
+		clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", "pxl_async1";
+
+		fimc_0: fimc@11800000 {
+			samsung,pix-limits = <4224 8192 1920 4224>;
+			samsung,mainscaler-ext;
+			samsung,cam-if;
+		};
+
+		fimc_1: fimc@11810000 {
+			samsung,pix-limits = <4224 8192 1920 4224>;
+			samsung,mainscaler-ext;
+			samsung,cam-if;
+		};
+
+		fimc_2: fimc@11820000 {
+			samsung,pix-limits = <4224 8192 1920 4224>;
+			samsung,mainscaler-ext;
+			samsung,lcd-wb;
+		};
+
+		fimc_3: fimc@11830000 {
+			samsung,pix-limits = <1920 8192 1366 1920>;
+			samsung,rotators = <0>;
+			samsung,mainscaler-ext;
+			samsung,lcd-wb;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
new file mode 100644
index 0000000..fb7b9ae
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -0,0 +1,579 @@
+/*
+ * Samsung's Exynos4412 based Trats 2 board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Device tree source file for Samsung's Trats 2 board which is based on
+ * Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+#include "exynos4412.dtsi"
+
+/ {
+	model = "Samsung Trats 2 based on Exynos4412";
+	compatible = "samsung,trats2", "samsung,exynos4412";
+
+	aliases {
+		i2c8 = &i2c_ak8975;
+	};
+
+	memory {
+		reg =  <0x40000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
+	};
+
+	firmware@0204F000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x0204F000 0x1000>;
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vemmc_reg: regulator-0 {
+			compatible = "regulator-fixed";
+			regulator-name = "VMEM_VDD_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpk0 2 0>;
+			enable-active-high;
+		};
+
+		cam_io_reg: voltage-regulator-1 {
+			compatible = "regulator-fixed";
+			regulator-name = "CAM_SENSOR_A";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpm0 2 0>;
+			enable-active-high;
+		};
+
+		/* More to come */
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		key-down {
+			interrupt-parent = <&gpj1>;
+			interrupts = <2 0>;
+			gpios = <&gpj1 2 1>;
+			linux,code = <114>;
+			label = "volume down";
+			debounce-interval = <10>;
+		};
+
+		key-up {
+			interrupt-parent = <&gpj1>;
+			interrupts = <1 0>;
+			gpios = <&gpj1 1 1>;
+			linux,code = <115>;
+			label = "volume up";
+			debounce-interval = <10>;
+		};
+
+		key-power {
+			interrupt-parent = <&gpx2>;
+			interrupts = <7 0>;
+			gpios = <&gpx2 7 1>;
+			linux,code = <116>;
+			label = "power";
+			debounce-interval = <10>;
+			gpio-key,wakeup;
+		};
+	};
+
+	i2c@13890000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-slave-addr = <0x10>;
+		samsung,i2c-max-bus-freq = <400000>;
+		pinctrl-0 = <&i2c3_bus>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		mms114-touchscreen@48 {
+			compatible = "melfas,mms114";
+			reg = <0x48>;
+			interrupt-parent = <&gpm2>;
+			interrupts = <3 2>;
+			x-size = <720>;
+			y-size = <1280>;
+			avdd-supply = <&ldo23_reg>;
+			vdd-supply = <&ldo24_reg>;
+		};
+	};
+
+	i2c@138D0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-slave-addr = <0x10>;
+		samsung,i2c-max-bus-freq = <100000>;
+		pinctrl-0 = <&i2c7_bus>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		max77686_pmic@09 {
+			compatible = "maxim,max77686";
+			interrupt-parent = <&gpx0>;
+			interrupts = <7 0>;
+			reg = <0x09>;
+
+			voltage-regulators {
+				ldo1_reg: ldo1 {
+					regulator-compatible = "LDO1";
+					regulator-name = "VALIVE_1.0V_AP";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo2_reg: ldo2 {
+					regulator-compatible = "LDO2";
+					regulator-name = "VM1M2_1.2V_AP";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo3_reg: ldo3 {
+					regulator-compatible = "LDO3";
+					regulator-name = "VCC_1.8V_AP";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo4_reg: ldo4 {
+					regulator-compatible = "LDO4";
+					regulator-name = "VCC_2.8V_AP";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo5_reg: ldo5 {
+					regulator-compatible = "LDO5";
+					regulator-name = "VCC_1.8V_IO";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo6_reg: ldo6 {
+					regulator-compatible = "LDO6";
+					regulator-name = "VMPLL_1.0V_AP";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo7_reg: ldo7 {
+					regulator-compatible = "LDO7";
+					regulator-name = "VPLL_1.0V_AP";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-mem-on;
+				};
+
+				ldo8_reg: ldo8 {
+					regulator-compatible = "LDO8";
+					regulator-name = "VMIPI_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-mem-off;
+				};
+
+				ldo9_reg: ldo9 {
+					regulator-compatible = "LDO9";
+					regulator-name = "CAM_ISP_MIPI_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-mem-idle;
+				};
+
+				ldo10_reg: ldo10 {
+					regulator-compatible = "LDO10";
+					regulator-name = "VMIPI_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-off;
+				};
+
+				ldo11_reg: ldo11 {
+					regulator-compatible = "LDO11";
+					regulator-name = "VABB1_1.95V";
+					regulator-min-microvolt = <1950000>;
+					regulator-max-microvolt = <1950000>;
+					regulator-always-on;
+					regulator-mem-off;
+				};
+
+				ldo12_reg: ldo12 {
+					regulator-compatible = "LDO12";
+					regulator-name = "VUOTG_3.0V";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-mem-off;
+				};
+
+				ldo13_reg: ldo13 {
+					regulator-compatible = "LDO13";
+					regulator-name = "NFC_AVDD_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-idle;
+				};
+
+				ldo14_reg: ldo14 {
+					regulator-compatible = "LDO14";
+					regulator-name = "VABB2_1.95V";
+					regulator-min-microvolt = <1950000>;
+					regulator-max-microvolt = <1950000>;
+					regulator-always-on;
+					regulator-mem-off;
+				};
+
+				ldo15_reg: ldo15 {
+					regulator-compatible = "LDO15";
+					regulator-name = "VHSIC_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-mem-off;
+				};
+
+				ldo16_reg: ldo16 {
+					regulator-compatible = "LDO16";
+					regulator-name = "VHSIC_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-off;
+				};
+
+				ldo17_reg: ldo17 {
+					regulator-compatible = "LDO17";
+					regulator-name = "CAM_SENSOR_CORE_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-mem-idle;
+				};
+
+				ldo18_reg: ldo18 {
+					regulator-compatible = "LDO18";
+					regulator-name = "CAM_ISP_SEN_IO_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-idle;
+				};
+
+				ldo19_reg: ldo19 {
+					regulator-compatible = "LDO19";
+					regulator-name = "VT_CAM_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-idle;
+				};
+
+				ldo20_reg: ldo20 {
+					regulator-compatible = "LDO20";
+					regulator-name = "VDDQ_PRE_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-idle;
+				};
+
+				ldo21_reg: ldo21 {
+					regulator-compatible = "LDO21";
+					regulator-name = "VTF_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-mem-idle;
+				};
+
+				ldo22_reg: ldo22 {
+					regulator-compatible = "LDO22";
+					regulator-name = "VMEM_VDD_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					regulator-mem-off;
+				};
+
+				ldo23_reg: ldo23 {
+					regulator-compatible = "LDO23";
+					regulator-name = "TSP_AVDD_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-mem-idle;
+				};
+
+				ldo24_reg: ldo24 {
+					regulator-compatible = "LDO24";
+					regulator-name = "TSP_VDD_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-mem-idle;
+				};
+
+				ldo25_reg: ldo25 {
+					regulator-compatible = "LDO25";
+					regulator-name = "LCD_VCC_3.3V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-mem-idle;
+				};
+
+				ldo26_reg: ldo26 {
+					regulator-compatible = "LDO26";
+					regulator-name = "MOTOR_VCC_3.0V";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-mem-idle;
+				};
+
+				buck1_reg: buck1 {
+					regulator-compatible = "BUCK1";
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+					regulator-mem-off;
+				};
+
+				buck2_reg: buck2 {
+					regulator-compatible = "BUCK2";
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					regulator-mem-off;
+				};
+
+				buck3_reg: buck3 {
+					regulator-compatible = "BUCK3";
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-always-on;
+					regulator-boot-on;
+					regulator-mem-off;
+				};
+
+				buck4_reg: buck4 {
+					regulator-compatible = "BUCK4";
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-boot-on;
+					regulator-mem-off;
+				};
+
+				buck5_reg: buck5 {
+					regulator-compatible = "BUCK5";
+					regulator-name = "VMEM_1.2V_AP";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				buck6_reg: buck6 {
+					regulator-compatible = "BUCK6";
+					regulator-name = "VCC_SUB_1.35V";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+				};
+
+				buck7_reg: buck7 {
+					regulator-compatible = "BUCK7";
+					regulator-name = "VCC_SUB_2.0V";
+					regulator-min-microvolt = <2000000>;
+					regulator-max-microvolt = <2000000>;
+					regulator-always-on;
+				};
+
+				buck8_reg: buck8 {
+					regulator-compatible = "BUCK8";
+					regulator-name = "VMEM_VDDF_3.0V";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+					regulator-mem-off;
+				};
+
+				buck9_reg: buck9 {
+					regulator-compatible = "BUCK9";
+					regulator-name = "CAM_ISP_CORE_1.2V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-mem-off;
+				};
+			};
+		};
+	};
+
+	sdhci@12510000 {
+		bus-width = <8>;
+		non-removable;
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>;
+		pinctrl-names = "default";
+		vmmc-supply = <&vemmc_reg>;
+		status = "okay";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
+		status = "okay";
+	};
+
+	i2c_ak8975: i2c-gpio-0 {
+		compatible = "i2c-gpio";
+		gpios = <&gpy2 4 0>, <&gpy2 5 0>;
+		i2c-gpio,delay-us = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "okay";
+
+		ak8975@0c {
+			compatible = "ak,ak8975";
+			reg = <0x0c>;
+			gpios = <&gpj0 7 0>;
+		};
+	};
+
+	spi_1: spi@13930000 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_bus>;
+		status = "okay";
+
+		s5c73m3_spi: s5c73m3 {
+			compatible = "samsung,s5c73m3";
+			spi-max-frequency = <50000000>;
+			reg = <0>;
+			controller-data {
+				cs-gpio = <&gpb 5 0>;
+				samsung,spi-feedback-delay = <2>;
+			};
+		};
+	};
+
+	camera {
+		pinctrl-0 = <&cam_port_b_clk_active>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		fimc_0: fimc@11800000 {
+			status = "okay";
+		};
+
+		fimc_1: fimc@11810000 {
+			status = "okay";
+		};
+
+		fimc_2: fimc@11820000 {
+			status = "okay";
+		};
+
+		fimc_3: fimc@11830000 {
+			status = "okay";
+		};
+
+		csis_1: csis@11890000 {
+			vddcore-supply = <&ldo8_reg>;
+			vddio-supply = <&ldo10_reg>;
+			clock-frequency = <160000000>;
+			status = "okay";
+
+			/* Camera D (4) MIPI CSI-2 (CSIS1) */
+			port@4 {
+				reg = <4>;
+				csis1_ep: endpoint {
+					remote-endpoint = <&is_s5k6a3_ep>;
+					data-lanes = <1>;
+					samsung,csis-hs-settle = <18>;
+					samsung,csis-wclk;
+				};
+			};
+		};
+
+		fimc_lite_0: fimc-lite@12390000 {
+			status = "okay";
+		};
+
+		fimc_lite_1: fimc-lite@123A0000 {
+			status = "okay";
+		};
+
+		fimc-is@12000000 {
+			pinctrl-0 = <&fimc_is_uart>;
+			pinctrl-names = "default";
+			status = "okay";
+
+			i2c1_isp: i2c-isp@12140000 {
+				pinctrl-0 = <&fimc_is_i2c1>;
+				pinctrl-names = "default";
+
+				s5k6a3@10 {
+					compatible = "samsung,s5k6a3";
+					reg = <0x10>;
+					svdda-supply = <&cam_io_reg>;
+					svddio-supply = <&ldo19_reg>;
+					clock-frequency = <24000000>;
+					/* CAM_B_CLKOUT */
+					clocks = <&clock_cam 1>;
+					clock-names = "mclk";
+					samsung,camclk-out = <1>;
+					gpios = <&gpm1 6 0>;
+
+					port {
+						is_s5k6a3_ep: endpoint {
+							remote-endpoint = <&csis1_ep>;
+							data-lanes = <1>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
index 704290f..99b26df 100644
--- a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
@@ -401,13 +401,26 @@
 			samsung,pin-drv = <0>;
 		};
 
-		cam_port_a: cam-port-a {
+		cam_port_a_io: cam-port-a-io {
 			samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
 					"gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
-					"gpj1-0", "gpj1-1", "gpj1-2", "gpj1-3",
-					"gpj1-4";
+					"gpj1-0", "gpj1-1", "gpj1-2", "gpj1-4";
 			samsung,pin-function = <2>;
-			samsung,pin-pud = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		cam_port_a_clk_active: cam-port-a-clk-active {
+			samsung,pins = "gpj1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		cam_port_a_clk_idle: cam-port-a-clk-idle {
+			samsung,pins = "gpj1-3";
+			samsung,pin-function = <0>;
+			samsung,pin-pud = <1>;
 			samsung,pin-drv = <0>;
 		};
 	};
@@ -778,16 +791,29 @@
 			samsung,pin-drv = <3>;
 		};
 
-		cam_port_b: cam-port-b {
+		cam_port_b_io: cam-port-b-io {
 			samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3",
 					"gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7",
-					"gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1",
-					"gpm2-2";
+					"gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
 			samsung,pin-drv = <0>;
 		};
 
+		cam_port_b_clk_active: cam-port-b-clk-active {
+			samsung,pins = "gpm2-2";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		cam_port_b_clk_idle: cam-port-b-clk-idle {
+			samsung,pins = "gpm2-2";
+			samsung,pin-function = <0>;
+			samsung,pin-pud = <1>;
+			samsung,pin-drv = <0>;
+		};
+
 		eint0: ext-int0 {
 			samsung,pins = "gpx0-0";
 			samsung,pin-function = <0xf>;
@@ -822,6 +848,27 @@
 			samsung,pin-pud = <0>;
 			samsung,pin-drv = <0>;
 		};
+
+		fimc_is_i2c0: fimc-is-i2c0 {
+			samsung,pins = "gpm4-0", "gpm4-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		fimc_is_i2c1: fimc-is-i2c1 {
+			samsung,pins = "gpm4-2", "gpm4-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		fimc_is_uart: fimc-is-uart {
+			samsung,pins = "gpm3-5", "gpm3-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
 	};
 
 	pinctrl@03860000 {
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 01da194..ad531fe 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -26,9 +26,16 @@
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
+		fimc-lite0 = &fimc_lite_0;
+		fimc-lite1 = &fimc_lite_1;
 	};
 
-	clock: clock-controller@0x10030000 {
+	pd_isp: isp-power-domain@10023CA0 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023CA0 0x20>;
+	};
+
+	clock: clock-controller@10030000 {
 		compatible = "samsung,exynos4412-clock";
 		reg = <0x10030000 0x20000>;
 		#clock-cells = <1>;
@@ -73,4 +80,100 @@
 		clock-names = "sclk_fimg2d", "fimg2d";
 		status = "disabled";
 	};
+
+	camera {
+		clocks = <&clock 132>, <&clock 133>, <&clock 351>, <&clock 352>;
+		clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", "pxl_async1";
+
+		fimc_0: fimc@11800000 {
+			compatible = "samsung,exynos4212-fimc";
+			samsung,pix-limits = <4224 8192 1920 4224>;
+			samsung,mainscaler-ext;
+			samsung,isp-wb;
+			samsung,cam-if;
+		};
+
+		fimc_1: fimc@11810000 {
+			compatible = "samsung,exynos4212-fimc";
+			samsung,pix-limits = <4224 8192 1920 4224>;
+			samsung,mainscaler-ext;
+			samsung,isp-wb;
+			samsung,cam-if;
+		};
+
+		fimc_2: fimc@11820000 {
+			compatible = "samsung,exynos4212-fimc";
+			samsung,pix-limits = <4224 8192 1920 4224>;
+			samsung,mainscaler-ext;
+			samsung,isp-wb;
+			samsung,lcd-wb;
+			samsung,cam-if;
+		};
+
+		fimc_3: fimc@11830000 {
+			compatible = "samsung,exynos4212-fimc";
+			samsung,pix-limits = <1920 8192 1366 1920>;
+			samsung,rotators = <0>;
+			samsung,mainscaler-ext;
+			samsung,isp-wb;
+			samsung,lcd-wb;
+		};
+
+		fimc_lite_0: fimc-lite@12390000 {
+			compatible = "samsung,exynos4212-fimc-lite";
+			reg = <0x12390000 0x1000>;
+			interrupts = <0 105 0>;
+			samsung,power-domain = <&pd_isp>;
+			clocks = <&clock 353>;
+			clock-names = "flite";
+			status = "disabled";
+		};
+
+		fimc_lite_1: fimc-lite@123A0000 {
+			compatible = "samsung,exynos4212-fimc-lite";
+			reg = <0x123A0000 0x1000>;
+			interrupts = <0 106 0>;
+			samsung,power-domain = <&pd_isp>;
+			clocks = <&clock 354>;
+			clock-names = "flite";
+			status = "disabled";
+		};
+
+		fimc_is: fimc-is@12000000 {
+			compatible = "samsung,exynos4212-fimc-is", "simple-bus";
+			reg = <0x12000000 0x260000>;
+			interrupts = <0 90 0>, <0 95 0>;
+			samsung,power-domain = <&pd_isp>;
+			clocks = <&clock 353>, <&clock 354>, <&clock 355>,
+				<&clock 356>, <&clock 17>, <&clock 357>,
+				<&clock 358>, <&clock 359>, <&clock 360>,
+				<&clock 450>,<&clock 451>, <&clock 452>,
+				<&clock 453>, <&clock 176>, <&clock 13>,
+				<&clock 454>, <&clock 395>, <&clock 455>;
+			clock-names = "lite0", "lite1", "ppmuispx",
+				      "ppmuispmx", "mpll", "isp",
+				      "drc", "fd", "mcuisp",
+				      "ispdiv0", "ispdiv1", "mcuispdiv0",
+				      "mcuispdiv1", "uart", "aclk200",
+				      "div_aclk200", "aclk400mcuisp",
+				      "div_aclk400mcuisp";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			status = "disabled";
+
+			pmu {
+				reg = <0x10020000 0x3000>;
+			};
+
+			i2c1_isp: i2c-isp@12140000 {
+				compatible = "samsung,exynos4212-i2c-isp";
+				reg = <0x12140000 0x100>;
+				clocks = <&clock 370>;
+				clock-names = "i2c_isp";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index abc7272..96d528d 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -11,6 +11,7 @@
 
 /dts-v1/;
 #include "exynos5250.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	model = "Insignal Arndale evaluation board based on EXYNOS5250";
@@ -37,6 +38,28 @@
 		s5m8767_pmic@66 {
 			compatible = "samsung,s5m8767-pmic";
 			reg = <0x66>;
+			interrupt-parent = <&gpx3>;
+			interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+			vinb1-supply = <&main_dc_reg>;
+			vinb2-supply = <&main_dc_reg>;
+			vinb3-supply = <&main_dc_reg>;
+			vinb4-supply = <&main_dc_reg>;
+			vinb5-supply = <&main_dc_reg>;
+			vinb6-supply = <&main_dc_reg>;
+			vinb7-supply = <&main_dc_reg>;
+			vinb8-supply = <&main_dc_reg>;
+			vinb9-supply = <&main_dc_reg>;
+
+			vinl1-supply = <&buck7_reg>;
+			vinl2-supply = <&buck7_reg>;
+			vinl3-supply = <&buck7_reg>;
+			vinl4-supply = <&main_dc_reg>;
+			vinl5-supply = <&main_dc_reg>;
+			vinl6-supply = <&main_dc_reg>;
+			vinl7-supply = <&main_dc_reg>;
+			vinl8-supply = <&buck8_reg>;
+			vinl9-supply = <&buck8_reg>;
 
 			s5m8767,pmic-buck2-dvs-voltage = <1300000>;
 			s5m8767,pmic-buck3-dvs-voltage = <1100000>;
@@ -276,6 +299,16 @@
 					op_mode = <1>;
 				};
 
+				buck7_reg: BUCK7 {
+					regulator-name = "PVDD_BUCK7";
+					regulator-always-on;
+				};
+
+				buck8_reg: BUCK8 {
+					regulator-name = "PVDD_BUCK8";
+					regulator-always-on;
+				};
+
 				buck9_reg: BUCK9 {
 					regulator-name = "VDD_33_OFF_EXT1";
 					regulator-min-microvolt = <750000>;
@@ -295,7 +328,22 @@
 	};
 
 	i2c@12C90000 {
-		status = "disabled";
+		wm1811a@1a {
+			compatible = "wlf,wm1811";
+			reg = <0x1a>;
+
+			AVDD2-supply = <&main_dc_reg>;
+			CPVDD-supply = <&main_dc_reg>;
+			DBVDD1-supply = <&main_dc_reg>;
+			DBVDD2-supply = <&main_dc_reg>;
+			DBVDD3-supply = <&main_dc_reg>;
+			LDO1VDD-supply = <&main_dc_reg>;
+			SPKVDD1-supply = <&main_dc_reg>;
+			SPKVDD2-supply = <&main_dc_reg>;
+
+			wlf,ldo1ena = <&gpb0 0 0>;
+			wlf,ldo2ena = <&gpb0 1 0>;
+		};
 	};
 
 	i2c@12CA0000 {
@@ -429,18 +477,29 @@
 		vdd-supply = <&ldo8_reg>;
 	};
 
-	mmc_reg: voltage-regulator {
-		compatible = "regulator-fixed";
-		regulator-name = "VDD_33ON_2.8V";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&gpx1 1 1>;
-		enable-active-high;
-	};
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		main_dc_reg: fixedregulator@1 {
+			compatible = "regulator-fixed";
+			regulator-name = "MAIN_DC";
+		};
 
-	reg_hdmi_en: fixedregulator@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "hdmi-en";
+		mmc_reg: voltage-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "VDD_33ON_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpx1 1 1>;
+			enable-active-high;
+		};
+
+		reg_hdmi_en: fixedregulator@0 {
+			compatible = "regulator-fixed";
+			regulator-name = "hdmi-en";
+		};
 	};
 
 	fixed-rate-clocks {
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index ef57277..88589b7 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -68,17 +68,17 @@
 		};
 	};
 
-	pd_gsc: gsc-power-domain@0x10044000 {
+	pd_gsc: gsc-power-domain@10044000 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10044000 0x20>;
 	};
 
-	pd_mfc: mfc-power-domain@0x10044040 {
+	pd_mfc: mfc-power-domain@10044040 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10044040 0x20>;
 	};
 
-	clock: clock-controller@0x10010000 {
+	clock: clock-controller@10010000 {
 		compatible = "samsung,exynos5250-clock";
 		reg = <0x10010000 0x30000>;
 		#clock-cells = <1>;
@@ -163,6 +163,14 @@
 		clock-names = "watchdog";
 	};
 
+	g2d@10850000 {
+		compatible = "samsung,exynos5250-g2d";
+		reg = <0x10850000 0x1000>;
+		interrupts = <0 91 0>;
+		clocks = <&clock 345>;
+		clock-names = "fimg2d";
+	};
+
 	codec@11000000 {
 		compatible = "samsung,mfc-v6";
 		reg = <0x11000000 0x10000>;
@@ -562,7 +570,7 @@
 		};
 	};
 
-	gsc_0:  gsc@0x13e00000 {
+	gsc_0:  gsc@13e00000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e00000 0x1000>;
 		interrupts = <0 85 0>;
@@ -571,7 +579,7 @@
 		clock-names = "gscl";
 	};
 
-	gsc_1:  gsc@0x13e10000 {
+	gsc_1:  gsc@13e10000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e10000 0x1000>;
 		interrupts = <0 86 0>;
@@ -580,7 +588,7 @@
 		clock-names = "gscl";
 	};
 
-	gsc_2:  gsc@0x13e20000 {
+	gsc_2:  gsc@13e20000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e20000 0x1000>;
 		interrupts = <0 87 0>;
@@ -589,7 +597,7 @@
 		clock-names = "gscl";
 	};
 
-	gsc_3:  gsc@0x13e30000 {
+	gsc_3:  gsc@13e30000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e30000 0x1000>;
 		interrupts = <0 88 0>;
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8c54c4b..9e90d1e 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -59,7 +59,7 @@
 		};
 	};
 
-	clock: clock-controller@0x10010000 {
+	clock: clock-controller@10010000 {
 		compatible = "samsung,exynos5420-clock";
 		reg = <0x10010000 0x30000>;
 		#clock-cells = <1>;
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index ff7f5d8..be49894 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -18,9 +18,12 @@
 
 	aliases {
 		spi0 = &spi_0;
+		tmuctrl0 = &tmuctrl_0;
+		tmuctrl1 = &tmuctrl_1;
+		tmuctrl2 = &tmuctrl_2;
 	};
 
-	clock: clock-controller@0x160000 {
+	clock: clock-controller@160000 {
 		compatible = "samsung,exynos5440-clock";
 		reg = <0x160000 0x1000>;
 		#clock-cells = <1>;
@@ -207,6 +210,30 @@
 		clock-names = "rtc";
 	};
 
+	tmuctrl_0: tmuctrl@160118 {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x160118 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
+
+	tmuctrl_1: tmuctrl@16011C {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x16011C 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
+
+	tmuctrl_2: tmuctrl@160120 {
+		compatible = "samsung,exynos5440-tmu";
+		reg = <0x160120 0x230>, <0x160368 0x10>;
+		interrupts = <0 58 0>;
+		clocks = <&clock 21>;
+		clock-names = "tmu_apbif";
+	};
+
 	sata@210000 {
 		compatible = "snps,exynos5440-ahci";
 		reg = <0x210000 0x10000>;
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index da0588a..185c7c0 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -90,6 +90,11 @@
 		};
 
 		apbx@80040000 {
+			lradc@80050000 {
+				status = "okay";
+				fsl,lradc-touchscreen-wires = <4>;
+			};
+
 			pwm: pwm@80064000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&pwm2_pins_a>;
@@ -107,6 +112,16 @@
 				pinctrl-0 = <&duart_pins_a>;
 				status = "okay";
 			};
+
+			usbphy0: usbphy@8007c000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb0: usb@80080000 {
+			status = "okay";
 		};
 	};
 
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index d107c4a..fc766ae 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -69,6 +69,10 @@
 		};
 
 		apbx@80040000 {
+			lradc@80050000 {
+				status = "okay";
+			};
+
 			duart: serial@80070000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&duart_pins_a>;
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 587ceef..28b5ce2 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -20,6 +20,8 @@
 		gpio2 = &gpio2;
 		serial0 = &auart0;
 		serial1 = &auart1;
+		spi0 = &ssp0;
+		spi1 = &ssp1;
 	};
 
 	cpus {
@@ -76,23 +78,21 @@
 				#size-cells = <1>;
 				reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>;
 				reg-names = "gpmi-nand", "bch";
-				interrupts = <13>, <56>;
-				interrupt-names = "gpmi-dma", "bch";
+				interrupts = <56>;
+				interrupt-names = "bch";
 				clocks = <&clks 34>;
 				clock-names = "gpmi_io";
 				dmas = <&dma_apbh 4>;
 				dma-names = "rx-tx";
-				fsl,gpmi-dma-channel = <4>;
 				status = "disabled";
 			};
 
 			ssp0: ssp@80010000 {
 				reg = <0x80010000 0x2000>;
-				interrupts = <15 14>;
+				interrupts = <15>;
 				clocks = <&clks 33>;
 				dmas = <&dma_apbh 1>;
 				dma-names = "rx-tx";
-				fsl,ssp-dma-channel = <1>;
 				status = "disabled";
 			};
 
@@ -366,11 +366,10 @@
 
 			ssp1: ssp@80034000 {
 				reg = <0x80034000 0x2000>;
-				interrupts = <2 20>;
+				interrupts = <2>;
 				clocks = <&clks 33>;
 				dmas = <&dma_apbh 2>;
 				dma-names = "rx-tx";
-				fsl,ssp-dma-channel = <2>;
 				status = "disabled";
 			};
 
@@ -472,7 +471,7 @@
 			auart0: serial@8006c000 {
 				compatible = "fsl,imx23-auart";
 				reg = <0x8006c000 0x2000>;
-				interrupts = <24 25 23>;
+				interrupts = <24>;
 				clocks = <&clks 32>;
 				dmas = <&dma_apbx 6>, <&dma_apbx 7>;
 				dma-names = "rx", "tx";
@@ -482,7 +481,7 @@
 			auart1: serial@8006e000 {
 				compatible = "fsl,imx23-auart";
 				reg = <0x8006e000 0x2000>;
-				interrupts = <59 60 58>;
+				interrupts = <59>;
 				clocks = <&clks 32>;
 				dmas = <&dma_apbx 8>, <&dma_apbx 9>;
 				dma-names = "rx", "tx";
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index 7011539..737ed5d 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -13,19 +13,35 @@
 
 / {
 	aliases {
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
 		serial3 = &uart4;
 		serial4 = &uart5;
-		gpio0 = &gpio1;
-		gpio1 = &gpio2;
-		gpio2 = &gpio3;
-		gpio3 = &gpio4;
+		spi0 = &spi1;
+		spi1 = &spi2;
+		spi2 = &spi3;
 		usb0 = &usbotg;
 		usb1 = &usbhost1;
 	};
 
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			compatible = "arm,arm926ej-s";
+			device_type = "cpu";
+		};
+	};
+
 	asic: asic-interrupt-controller@68000000 {
 		compatible = "fsl,imx25-asic", "fsl,avic";
 		interrupt-controller;
@@ -377,7 +393,8 @@
 				status = "disabled";
 			};
 
-			lcdc@53fbc000 {
+			lcdc: lcdc@53fbc000 {
+				compatible = "fsl,imx25-fb", "fsl,imx21-fb";
 				reg = <0x53fbc000 0x4000>;
 				interrupts = <39>;
 				clocks = <&clks 103>, <&clks 66>, <&clks 49>;
@@ -424,6 +441,7 @@
 				reg = <0x53fd4000 0x4000>;
 				clocks = <&clks 112>, <&clks 68>;
 				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
 				interrupts = <34>;
 			};
 
@@ -444,6 +462,13 @@
 				interrupts = <26>;
 			};
 
+			iim: iim@53ff0000 {
+				compatible = "fsl,imx25-iim", "fsl,imx27-iim";
+				reg = <0x53ff0000 0x4000>;
+				interrupts = <19>;
+				clocks = <&clks 99>;
+			};
+
 			usbphy1: usbphy@1 {
 				compatible = "nop-usbphy";
 				status = "disabled";
diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts
index 66b8e1c..2a377ca 100644
--- a/arch/arm/boot/dts/imx27-apf27dev.dts
+++ b/arch/arm/boot/dts/imx27-apf27dev.dts
@@ -53,6 +53,11 @@
 &i2c1 {
 	clock-frequency = <400000>;
 	status = "okay";
+
+	rtc@68 {
+		compatible = "dallas,ds1374";
+		reg = <0x68>;
+	};
 };
 
 &i2c2 {
diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
new file mode 100644
index 0000000..5a31c77
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012 Markus Pargmann, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx27-phytec-phycard-s-som.dts"
+
+/ {
+	model = "Phytec pca100 rapid development kit";
+	compatible = "phytec,imx27-pca100-rdk", "phytec,imx27-pca100", "fsl,imx27";
+
+	display: display {
+		model = "Primeview-PD050VL1";
+		native-mode = <&timing0>;
+		bits-per-pixel = <16>;  /* non-standard but required */
+		fsl,pcr = <0xf0c88080>;	/* non-standard but required */
+		display-timings {
+			timing0: 640x480 {
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <112>;
+				hfront-porch = <36>;
+				hsync-len = <32>;
+				vback-porch = <33>;
+				vfront-porch = <33>;
+				vsync-len = <2>;
+				clock-frequency = <25000000>;
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3v3: 3v3 {
+			compatible = "regulator-fixed";
+			regulator-name = "3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&fb {
+	display = <&display>;
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+
+	rtc@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+
+	adc@64 {
+		compatible = "maxim,max1037";
+		vcc-supply = <&reg_3v3>;
+		reg = <0x64>;
+	};
+};
+
+&owire {
+	status = "okay";
+};
+
+&sdhci2 {
+	cd-gpios = <&gpio3 29 0>;
+	status = "okay";
+};
+
+&uart1 {
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart2 {
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart3 {
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts b/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts
new file mode 100644
index 0000000..c8d57d1
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Sascha Hauer, Uwe Kleine-König, Steffen Trumtrar
+ * and Markus Pargmann, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx27.dtsi"
+
+/ {
+	model = "Phytec pca100";
+	compatible = "phytec,imx27-pca100", "fsl,imx27";
+
+	memory {
+		reg = <0xa0000000 0x08000000>; /* 128MB */
+	};
+};
+
+&cspi1 {
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio4 28 0>,
+		<&gpio4 27 0>;
+	status = "okay";
+};
+
+&fec {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+
+	at24@52 {
+		compatible = "at,24c32";
+		pagesize = <32>;
+		reg = <0x52>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
index e7ed978..0fc6551 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
@@ -35,3 +35,16 @@
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
+
+&weim {
+	can@d4000000 {
+		compatible = "nxp,sja1000";
+		reg = <4 0x00000000 0x00000100>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <19 0x2>;
+		nxp,external-clock-frequency = <16000000>;
+		nxp,tx-output-config = <0x16>;
+		nxp,no-comparator-bypass;
+		fsl,weim-cs-timing = <0x0000dcf6 0x444a0301 0x44443302>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-som.dts b/arch/arm/boot/dts/imx27-phytec-phycore-som.dts
index f010565..aa70ad7 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-som.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-som.dts
@@ -17,49 +17,7 @@
 	compatible = "phytec,imx27-pcm038", "fsl,imx27";
 
 	memory {
-		reg = <0x0 0x0>;
-	};
-
-	soc {
-		aipi@10000000 { /* aipi1 */
-			serial@1000a000 {
-				status = "okay";
-			};
-
-			i2c@1001d000 {
-				clock-frequency = <400000>;
-				status = "okay";
-				at24@52 {
-					compatible = "at,24c32";
-					pagesize = <32>;
-					reg = <0x52>;
-				};
-				pcf8563@51 {
-					compatible = "nxp,pcf8563";
-					reg = <0x51>;
-				};
-				lm75@4a {
-					compatible = "national,lm75";
-					reg = <0x4a>;
-				};
-			};
-		};
-
-		aipi@10020000 { /* aipi2 */
-			ethernet@1002b000 {
-				phy-reset-gpios = <&gpio3 30 0>;
-				status = "okay";
-			};
-		};
-	};
-
-	nor_flash@c0000000 {
-		compatible = "cfi-flash";
-		bank-width = <2>;
-		reg = <0xc0000000 0x02000000>;
-		linux,mtd-name = "physmap-flash.0";
-		#address-cells = <1>;
-		#size-cells = <1>;
+		reg = <0xa0000000 0x08000000>;
 	};
 };
 
@@ -80,28 +38,16 @@
 		fsl,mc13xxx-uses-rtc;
 
 		regulators {
-			sw1a_reg: sw1a {
+			/* SW1A and SW1B joined operation */
+			sw1_reg: sw1a {
 				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <1200000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			sw1b_reg: sw1b {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <1200000>;
-				regulator-always-on;
-				regulator-boot-on;
-			};
-
-			sw2a_reg: sw2a {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
+				regulator-max-microvolt = <1520000>;
 				regulator-always-on;
 				regulator-boot-on;
 			};
 
-			sw2b_reg: sw2b {
+			/* SW2A and SW2B joined operation */
+			sw2_reg: sw2a {
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
 				regulator-always-on;
@@ -172,8 +118,62 @@
 	};
 };
 
+&fec {
+	phy-reset-gpios = <&gpio3 30 0>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	at24@52 {
+		compatible = "at,24c32";
+		pagesize = <32>;
+		reg = <0x52>;
+	};
+
+	pcf8563@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+
+	lm75@4a {
+		compatible = "national,lm75";
+		reg = <0x4a>;
+	};
+};
+
 &nfc {
 	nand-bus-width = <8>;
 	nand-ecc-mode = "hw";
 	status = "okay";
 };
+
+&uart1 {
+	status = "okay";
+};
+
+&weim {
+	status = "okay";
+
+	nor: nor@c0000000 {
+		compatible = "cfi-flash";
+		reg = <0 0x00000000 0x02000000>;
+		bank-width = <2>;
+		linux,mtd-name = "physmap-flash.0";
+		fsl,weim-cs-timing = <0x22c2cf00 0x75000d01 0x00000900>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	sram: sram@c8000000 {
+		compatible = "mtd-ram";
+		reg = <1 0x00000000 0x00800000>;
+		bank-width = <2>;
+		linux,mtd-name = "mtd-ram.0";
+		fsl,weim-cs-timing = <0x0000d843 0x22252521 0x22220a00>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 0695264..76cd89f 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -13,25 +13,27 @@
 
 / {
 	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-		serial5 = &uart6;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
 		gpio3 = &gpio4;
 		gpio4 = &gpio5;
 		gpio5 = &gpio6;
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &uart6;
 		spi0 = &cspi1;
 		spi1 = &cspi2;
 		spi2 = &cspi3;
 	};
 
-	avic: avic-interrupt-controller@e0000000 {
-		compatible = "fsl,imx27-avic", "fsl,avic";
+	aitc: aitc-interrupt-controller@e0000000 {
+		compatible = "fsl,imx27-aitc", "fsl,avic";
 		interrupt-controller;
 		#interrupt-cells = <1>;
 		reg = <0x10040000 0x1000>;
@@ -47,11 +49,29 @@
 		};
 	};
 
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			operating-points = <
+				/* kHz uV */
+				266000 1300000
+				399000 1450000
+			>;
+			clock-latency = <62500>;
+			clocks = <&clks 18>;
+			voltage-tolerance = <5>;
+		};
+	};
+
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
-		interrupt-parent = <&avic>;
+		interrupt-parent = <&aitc>;
 		ranges;
 
 		aipi@10000000 { /* AIPI1 */
@@ -75,7 +95,7 @@
 				compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
 				reg = <0x10002000 0x1000>;
 				interrupts = <27>;
-				clocks = <&clks 0>;
+				clocks = <&clks 74>;
 			};
 
 			gpt1: timer@10003000 {
@@ -102,7 +122,7 @@
 				clock-names = "ipg", "per";
 			};
 
-			pwm0: pwm@10006000 {
+			pwm: pwm@10006000 {
 				compatible = "fsl,imx27-pwm";
 				reg = <0x10006000 0x1000>;
 				interrupts = <23>;
@@ -110,6 +130,21 @@
 				clock-names = "ipg", "per";
 			};
 
+			kpp: kpp@10008000 {
+				compatible = "fsl,imx27-kpp", "fsl,imx21-kpp";
+				reg = <0x10008000 0x1000>;
+				interrupts = <21>;
+				clocks = <&clks 37>;
+				status = "disabled";
+			};
+
+			owire: owire@10009000 {
+				compatible = "fsl,imx27-owire", "fsl,imx21-owire";
+				reg = <0x10009000 0x1000>;
+				clocks = <&clks 35>;
+				status = "disabled";
+			};
+
 			uart1: serial@1000a000 {
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1000a000 0x1000>;
@@ -260,6 +295,13 @@
 				#interrupt-cells = <2>;
 			};
 
+			audmux: audmux@10016000 {
+				compatible = "fsl,imx27-audmux", "fsl,imx21-audmux";
+				reg = <0x10016000 0x1000>;
+				clocks = <&clks 0>;
+				clock-names = "audmux";
+			};
+
 			cspi3: cspi@10017000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -342,6 +384,15 @@
 			reg = <0x10020000 0x20000>;
 			ranges;
 
+			fb: fb@10021000 {
+				compatible = "fsl,imx27-fb", "fsl,imx21-fb";
+				interrupts = <61>;
+				reg = <0x10021000 0x1000>;
+				clocks = <&clks 36>, <&clks 65>, <&clks 59>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
 			coda: coda@10023000 {
 				compatible = "fsl,imx27-vpu";
 				reg = <0x10023000 0x0200>;
@@ -351,27 +402,37 @@
 				iram = <&iram>;
 			};
 
+			sahara2: sahara@10025000 {
+				compatible = "fsl,imx27-sahara";
+				reg = <0x10025000 0x1000>;
+				interrupts = <59>;
+				clocks = <&clks 32>, <&clks 64>;
+				clock-names = "ipg", "ahb";
+			};
+
 			clks: ccm@10027000{
 				compatible = "fsl,imx27-ccm";
 				reg = <0x10027000 0x1000>;
 				#clock-cells = <1>;
 			};
 
+			iim: iim@10028000 {
+				compatible = "fsl,imx27-iim";
+				reg = <0x10028000 0x1000>;
+				interrupts = <62>;
+				clocks = <&clks 38>;
+			};
+
 			fec: ethernet@1002b000 {
 				compatible = "fsl,imx27-fec";
 				reg = <0x1002b000 0x4000>;
 				interrupts = <50>;
-				clocks = <&clks 48>, <&clks 67>, <&clks 0>;
-				clock-names = "ipg", "ahb", "ptp";
+				clocks = <&clks 48>, <&clks 67>;
+				clock-names = "ipg", "ahb";
 				status = "disabled";
 			};
 		};
 
-		iram: iram@ffff4c00 {
-			compatible = "mmio-sram";
-			reg = <0xffff4c00 0xb400>;
-		};
-
 		nfc: nand@d8000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -381,5 +442,27 @@
 			clocks = <&clks 54>;
 			status = "disabled";
 		};
+
+		weim: weim@d8002000 {
+			#address-cells = <2>;
+			#size-cells = <1>;
+			compatible = "fsl,imx27-weim";
+			reg = <0xd8002000 0x1000>;
+			clocks = <&clks 0>;
+			ranges = <
+				0 0 0xc0000000 0x08000000
+				1 0 0xc8000000 0x08000000
+				2 0 0xd0000000 0x02000000
+				3 0 0xd2000000 0x02000000
+				4 0 0xd4000000 0x02000000
+				5 0 0xd6000000 0x02000000
+			>;
+			status = "disabled";
+		};
+
+		iram: iram@ffff4c00 {
+			compatible = "mmio-sram";
+			reg = <0xffff4c00 0xb400>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index 94c4476..1ec8c94 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -23,10 +23,7 @@
 	apb@80000000 {
 		apbh@80000000 {
 			pinctrl@80018000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&hog_pins_cfa10036>;
-
-				hog_pins_cfa10036: hog-10036@0 {
+				ssd1306_cfa10036: ssd1306-10036@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x2073 /* MX28_PAD_SSP0_D7__GPIO_2_7 */
@@ -83,6 +80,8 @@
 
 				ssd1306: oled@3c {
 					compatible = "solomon,ssd1306fb-i2c";
+					pinctrl-names = "default";
+					pinctrl-0 = <&ssd1306_cfa10036>;
 					reg = <0x3c>;
 					reset-gpios = <&gpio2 7 0>;
 					solomon,height = <32>;
diff --git a/arch/arm/boot/dts/imx28-cfa10037.dts b/arch/arm/boot/dts/imx28-cfa10037.dts
index c2ef3a3..182b99f 100644
--- a/arch/arm/boot/dts/imx28-cfa10037.dts
+++ b/arch/arm/boot/dts/imx28-cfa10037.dts
@@ -22,13 +22,19 @@
 	apb@80000000 {
 		apbh@80000000 {
 			pinctrl@80018000 {
-				pinctrl-names = "default", "default";
-				pinctrl-1 = <&hog_pins_cfa10037>;
-
-				hog_pins_cfa10037: hog-10037@0 {
+				usb_pins_cfa10037: usb-10037@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				mac0_pins_cfa10037: mac0-10037@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
 						0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
 					>;
 					fsl,drive-strength = <0>;
@@ -56,7 +62,8 @@
 		mac0: ethernet@800f0000 {
 			phy-mode = "rmii";
 			pinctrl-names = "default";
-			pinctrl-0 = <&mac0_pins_a>;
+			pinctrl-0 = <&mac0_pins_a
+				&mac0_pins_cfa10037>;
 			phy-reset-gpios = <&gpio2 21 0>;
 			phy-reset-duration = <100>;
 			status = "okay";
@@ -68,6 +75,8 @@
 
 		reg_usb1_vbus: usb1_vbus {
 			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&usb_pins_cfa10037>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 04b2f76..06e4cfa 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -22,32 +22,62 @@
 	apb@80000000 {
 		apbh@80000000 {
 			pinctrl@80018000 {
-				pinctrl-names = "default", "default";
-				pinctrl-1 = <&hog_pins_cfa10049
-					&hog_pins_cfa10049_pullup>;
-
-				hog_pins_cfa10049: hog-10049@0 {
+				usb_pins_cfa10049: usb-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				i2cmux_pins_cfa10049: i2cmux-10049@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
 						0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
 						0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				mac0_pins_cfa10049: mac0-10049@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
 						0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
 					>;
 					fsl,drive-strength = <0>;
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
 
-				hog_pins_cfa10049_pullup: hog-10049-pullup@0 {
+				pca_pins_cfa10049: pca-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x2133 /* MX28_PAD_SSP2_D3__GPIO_2_19 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
+				rotary_pins_cfa10049: rotary-10049@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
 						0x3183 /* MX28_PAD_I2C0_SCL__GPIO_3_24 */
 						0x3193 /* MX28_PAD_I2C0_SDA__GPIO_3_25 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
+				rotary_btn_pins_cfa10049: rotary-btn-10049@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
 						0x31a3 /* MX28_PAD_SAIF_SDATA0__GPIO_3_26 */
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
 					>;
 					fsl,drive-strength = <0>;
 					fsl,voltage = <1>;
@@ -60,6 +90,7 @@
 						0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
 						0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
 						0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
+						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
 					>;
 					fsl,drive-strength = <1>;
 					fsl,voltage = <1>;
@@ -120,6 +151,16 @@
 					fsl,pull-up = <0>;
 				};
 
+				lcdif_pins_cfa10049_pullup: lcdif-10049-pullup@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
 				w1_gpio_pins: w1-gpio@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -134,7 +175,8 @@
 			lcdif@80030000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_18bit_pins_cfa10049
-					     &lcdif_pins_cfa10049>;
+					     &lcdif_pins_cfa10049
+					     &lcdif_pins_cfa10049_pullup>;
 				display = <&display>;
 				status = "okay";
 
@@ -181,6 +223,8 @@
 				compatible = "i2c-mux-gpio";
 				#address-cells = <1>;
 				#size-cells = <0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2cmux_pins_cfa10049>;
 				mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
 				i2c-parent = <&i2c1>;
 
@@ -203,6 +247,8 @@
 
 					pca9555: pca9555@20 {
 						compatible = "nxp,pca9555";
+						pinctrl-names = "default";
+						pinctrl-0 = <&pca_pins_cfa10049>;
 						interrupt-parent = <&gpio2>;
 						interrupts = <19 0x2>;
 						gpio-controller;
@@ -239,6 +285,8 @@
 
 		reg_usb1_vbus: usb1_vbus {
 			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&usb_pins_cfa10049>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -250,7 +298,8 @@
 		mac0: ethernet@800f0000 {
 			phy-mode = "rmii";
 			pinctrl-names = "default";
-			pinctrl-0 = <&mac0_pins_a>;
+			pinctrl-0 = <&mac0_pins_a
+				&mac0_pins_cfa10049>;
 			phy-reset-gpios = <&gpio2 21 0>;
 			phy-reset-duration = <100>;
 			status = "okay";
@@ -320,6 +369,8 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&rotary_btn_pins_cfa10049>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 
@@ -333,6 +384,8 @@
 
 	rotary {
 		compatible = "rotary-encoder";
+		pinctrl-names = "default";
+		pinctrl-0 = <&rotary_pins_cfa10049>;
 		gpios = <&gpio3 24 1>, <&gpio3 25 1>;
 		linux,axis = <1>; /* REL_Y */
 		rotary-encoder,relative-axis;
diff --git a/arch/arm/boot/dts/imx28-cfa10055.dts b/arch/arm/boot/dts/imx28-cfa10055.dts
index 1581112..171bcbe 100644
--- a/arch/arm/boot/dts/imx28-cfa10055.dts
+++ b/arch/arm/boot/dts/imx28-cfa10055.dts
@@ -23,36 +23,13 @@
 	apb@80000000 {
 		apbh@80000000 {
 			pinctrl@80018000 {
-				pinctrl-names = "default", "default";
-				pinctrl-1 = <&hog_pins_cfa10055
-					&hog_pins_cfa10055_pullup>;
-
-				hog_pins_cfa10055: hog-10055@0 {
-					reg = <0>;
-					fsl,pinmux-ids = <
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
-					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
-				};
-
-				hog_pins_cfa10055_pullup: hog-10055-pullup@0 {
-					reg = <0>;
-					fsl,pinmux-ids = <
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
-					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
-				};
-
 				spi2_pins_cfa10055: spi2-cfa10055@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
 						0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
 						0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
+						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
 					>;
 					fsl,drive-strength = <1>;
 					fsl,voltage = <1>;
@@ -98,12 +75,23 @@
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
+
+				lcdif_pins_cfa10055_pullup: lcdif-10055-pullup@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
 			};
 
 			lcdif@80030000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_18bit_pins_cfa10055
-					     &lcdif_pins_cfa10055>;
+					     &lcdif_pins_cfa10055
+					     &lcdif_pins_cfa10055_pullup>;
 				display = <&display>;
 				status = "okay";
 
diff --git a/arch/arm/boot/dts/imx28-cfa10056.dts b/arch/arm/boot/dts/imx28-cfa10056.dts
new file mode 100644
index 0000000..b45dd0e
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-cfa10056.dts
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2013 Free Electrons
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * The CFA-10055 is an expansion board for the CFA-10036 module and
+ * CFA-10037, thus we need to include the CFA-10037 DTS.
+ */
+/include/ "imx28-cfa10037.dts"
+
+/ {
+	model = "Crystalfontz CFA-10056 Board";
+	compatible = "crystalfontz,cfa10056", "crystalfontz,cfa10037", "crystalfontz,cfa10036", "fsl,imx28";
+
+	apb@80000000 {
+		apbh@80000000 {
+			pinctrl@80018000 {
+				spi2_pins_cfa10056: spi2-cfa10056@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
+						0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
+						0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
+						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
+				lcdif_pins_cfa10056: lcdif-10056@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				lcdif_pins_cfa10056_pullup: lcdif-10056-pullup@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+			};
+
+			lcdif@80030000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&lcdif_24bit_pins_a
+						&lcdif_pins_cfa10056
+						&lcdif_pins_cfa10056_pullup >;
+				display = <&display>;
+				status = "okay";
+
+				display: display {
+					bits-per-pixel = <32>;
+					bus-width = <24>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <32000000>;
+							hactive = <480>;
+							vactive = <800>;
+							hback-porch = <2>;
+							hfront-porch = <2>;
+							vback-porch = <2>;
+							vfront-porch = <2>;
+							hsync-len = <5>;
+							vsync-len = <5>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <1>;
+						};
+					};
+				};
+			};
+		};
+	};
+
+	spi2 {
+		compatible = "spi-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_pins_cfa10056>;
+		status = "okay";
+		gpio-sck = <&gpio2 16 0>;
+		gpio-mosi = <&gpio2 17 0>;
+		gpio-miso = <&gpio2 18 0>;
+		cs-gpios = <&gpio3 5 0>;
+		num-chipselects = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		hx8369: hx8369@0 {
+			compatible = "himax,hx8369a", "himax,hx8369";
+			reg = <0>;
+			spi-max-frequency = <100000>;
+			spi-cpol;
+			spi-cpha;
+			gpios-reset = <&gpio3 30 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-cfa10057.dts b/arch/arm/boot/dts/imx28-cfa10057.dts
index 2da713c..0333c05 100644
--- a/arch/arm/boot/dts/imx28-cfa10057.dts
+++ b/arch/arm/boot/dts/imx28-cfa10057.dts
@@ -23,35 +23,16 @@
 	apb@80000000 {
 		apbh@80000000 {
 			pinctrl@80018000 {
-				pinctrl-names = "default", "default";
-				pinctrl-1 = <&hog_pins_cfa10057
-					&hog_pins_cfa10057_pullup>;
-
-				hog_pins_cfa10057: hog-10057@0 {
+				usb_pins_cfa10057: usb-10057@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
 					>;
 					fsl,drive-strength = <0>;
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
 
-				hog_pins_cfa10057_pullup: hog-10057-pullup@0 {
-					reg = <0>;
-					fsl,pinmux-ids = <
-						0x2133 /* MX28_PAD_SSP2_D3__GPIO_2_19 */
-						0x3183 /* MX28_PAD_I2C0_SCL__GPIO_3_24 */
-						0x3193 /* MX28_PAD_I2C0_SDA__GPIO_3_25 */
-						0x31a3 /* MX28_PAD_SAIF_SDATA0__GPIO_3_26 */
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
-					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
-				};
-
 				lcdif_18bit_pins_cfa10057: lcdif-18bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -164,6 +145,8 @@
 
 		reg_usb1_vbus: usb1_vbus {
 			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&usb_pins_cfa10057>;
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-cfa10058.dts b/arch/arm/boot/dts/imx28-cfa10058.dts
new file mode 100644
index 0000000..64c64c5
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-cfa10058.dts
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2013 Crystalfontz America, Inc.
+ * Copyright 2013 Free Electrons
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * The CFA-10058 is an expansion board for the CFA-10036 module, thus we
+ * need to include the CFA-10036 DTS.
+ */
+/include/ "imx28-cfa10036.dts"
+
+/ {
+	model = "Crystalfontz CFA-10058 Board";
+	compatible = "crystalfontz,cfa10058", "crystalfontz,cfa10036", "fsl,imx28";
+
+	apb@80000000 {
+		apbh@80000000 {
+			pinctrl@80018000 {
+				usb_pins_cfa10058: usb-10058@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				lcdif_pins_cfa10058: lcdif-10058@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+			};
+
+			lcdif@80030000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&lcdif_24bit_pins_a
+						 &lcdif_pins_cfa10058>;
+				display = <&display>;
+				status = "okay";
+
+				display: display {
+					bits-per-pixel = <32>;
+					bus-width = <24>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <30000000>;
+							hactive = <800>;
+							vactive = <480>;
+							hback-porch = <40>;
+							hfront-porch = <40>;
+							vback-porch = <13>;
+							vfront-porch = <29>;
+							hsync-len = <8>;
+							vsync-len = <8>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <1>;
+						};
+					};
+				};
+			};
+		};
+
+		apbx@80040000 {
+			lradc@80050000 {
+				fsl,lradc-touchscreen-wires = <4>;
+				status = "okay";
+			};
+
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm3_pins_b>;
+				status = "okay";
+			};
+
+			usbphy1: usbphy@8007e000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb1: usb@80090000 {
+			vbus-supply = <&reg_usb1_vbus>;
+			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-names = "default";
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb1_vbus: usb1_vbus {
+			pinctrl-names = "default";
+			pinctrl-0 = <&usb_pins_cfa10058>;
+			compatible = "regulator-fixed";
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio0 7 1>;
+		};
+	};
+
+	ahb@80080000 {
+		mac0: ethernet@800f0000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac0_pins_a>;
+			phy-reset-gpios = <&gpio2 21 0>;
+			phy-reset-duration = <100>;
+			status = "okay";
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 3 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index e035f46..15715d9 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -220,6 +220,7 @@
 			auart0: serial@8006a000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&auart0_pins_a>;
+				fsl,uart-has-rtscts;
 				status = "okay";
 			};
 
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 44d9da5..0d322a2 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -235,6 +235,12 @@
 				pinctrl-0 = <&auart2_2pins_b>;
 				status = "okay";
 			};
+
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm4_pins_a>;
+				status = "okay";
+			};
 		};
 	};
 
@@ -270,6 +276,13 @@
 		};
 	};
 
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 4 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 9524a05..47fc5ef 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -15,6 +15,8 @@
 	interrupt-parent = <&icoll>;
 
 	aliases {
+		ethernet0 = &mac0;
+		ethernet1 = &mac1;
 		gpio0 = &gpio0;
 		gpio1 = &gpio1;
 		gpio2 = &gpio2;
@@ -27,8 +29,8 @@
 		serial2 = &auart2;
 		serial3 = &auart3;
 		serial4 = &auart4;
-		ethernet0 = &mac0;
-		ethernet1 = &mac1;
+		spi0 = &ssp1;
+		spi1 = &ssp2;
 	};
 
 	cpus {
@@ -64,7 +66,7 @@
 
 			hsadc@80002000 {
 				reg = <0x80002000 0x2000>;
-				interrupts = <13 87>;
+				interrupts = <13>;
 				dmas = <&dma_apbh 12>;
 				dma-names = "rx";
 				status = "disabled";
@@ -98,13 +100,12 @@
 				#size-cells = <1>;
 				reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>;
 				reg-names = "gpmi-nand", "bch";
-				interrupts = <88>, <41>;
-				interrupt-names = "gpmi-dma", "bch";
+				interrupts = <41>;
+				interrupt-names = "bch";
 				clocks = <&clks 50>;
 				clock-names = "gpmi_io";
 				dmas = <&dma_apbh 4>;
 				dma-names = "rx-tx";
-				fsl,gpmi-dma-channel = <4>;
 				status = "disabled";
 			};
 
@@ -112,11 +113,10 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0x80010000 0x2000>;
-				interrupts = <96 82>;
+				interrupts = <96>;
 				clocks = <&clks 46>;
 				dmas = <&dma_apbh 0>;
 				dma-names = "rx-tx";
-				fsl,ssp-dma-channel = <0>;
 				status = "disabled";
 			};
 
@@ -124,11 +124,10 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0x80012000 0x2000>;
-				interrupts = <97 83>;
+				interrupts = <97>;
 				clocks = <&clks 47>;
 				dmas = <&dma_apbh 1>;
 				dma-names = "rx-tx";
-				fsl,ssp-dma-channel = <1>;
 				status = "disabled";
 			};
 
@@ -136,11 +135,10 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0x80014000 0x2000>;
-				interrupts = <98 84>;
+				interrupts = <98>;
 				clocks = <&clks 48>;
 				dmas = <&dma_apbh 2>;
 				dma-names = "rx-tx";
-				fsl,ssp-dma-channel = <2>;
 				status = "disabled";
 			};
 
@@ -148,11 +146,10 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0x80016000 0x2000>;
-				interrupts = <99 85>;
+				interrupts = <99>;
 				clocks = <&clks 49>;
 				dmas = <&dma_apbh 3>;
 				dma-names = "rx-tx";
-				fsl,ssp-dma-channel = <3>;
 				status = "disabled";
 			};
 
@@ -759,7 +756,7 @@
 			lcdif@80030000 {
 				compatible = "fsl,imx28-lcdif";
 				reg = <0x80030000 0x2000>;
-				interrupts = <38 86>;
+				interrupts = <38>;
 				clocks = <&clks 55>;
 				dmas = <&dma_apbh 13>;
 				dma-names = "rx";
@@ -836,12 +833,11 @@
 			saif0: saif@80042000 {
 				compatible = "fsl,imx28-saif";
 				reg = <0x80042000 0x2000>;
-				interrupts = <59 80>;
+				interrupts = <59>;
 				#clock-cells = <0>;
 				clocks = <&clks 53>;
 				dmas = <&dma_apbx 4>;
 				dma-names = "rx-tx";
-				fsl,saif-dma-channel = <4>;
 				status = "disabled";
 			};
 
@@ -853,11 +849,10 @@
 			saif1: saif@80046000 {
 				compatible = "fsl,imx28-saif";
 				reg = <0x80046000 0x2000>;
-				interrupts = <58 81>;
+				interrupts = <58>;
 				clocks = <&clks 54>;
 				dmas = <&dma_apbx 5>;
 				dma-names = "rx-tx";
-				fsl,saif-dma-channel = <5>;
 				status = "disabled";
 			};
 
@@ -871,7 +866,7 @@
 
 			spdif@80054000 {
 				reg = <0x80054000 0x2000>;
-				interrupts = <45 66>;
+				interrupts = <45>;
 				dmas = <&dma_apbx 2>;
 				dma-names = "tx";
 				status = "disabled";
@@ -888,11 +883,10 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx28-i2c";
 				reg = <0x80058000 0x2000>;
-				interrupts = <111 68>;
+				interrupts = <111>;
 				clock-frequency = <100000>;
 				dmas = <&dma_apbx 6>;
 				dma-names = "rx-tx";
-				fsl,i2c-dma-channel = <6>;
 				status = "disabled";
 			};
 
@@ -901,11 +895,10 @@
 				#size-cells = <0>;
 				compatible = "fsl,imx28-i2c";
 				reg = <0x8005a000 0x2000>;
-				interrupts = <110 69>;
+				interrupts = <110>;
 				clock-frequency = <100000>;
 				dmas = <&dma_apbx 7>;
 				dma-names = "rx-tx";
-				fsl,i2c-dma-channel = <7>;
 				status = "disabled";
 			};
 
@@ -928,10 +921,9 @@
 			auart0: serial@8006a000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006a000 0x2000>;
-				interrupts = <112 70 71>;
+				interrupts = <112>;
 				dmas = <&dma_apbx 8>, <&dma_apbx 9>;
 				dma-names = "rx", "tx";
-				fsl,auart-dma-channel = <8 9>;
 				clocks = <&clks 45>;
 				status = "disabled";
 			};
@@ -939,7 +931,7 @@
 			auart1: serial@8006c000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006c000 0x2000>;
-				interrupts = <113 72 73>;
+				interrupts = <113>;
 				dmas = <&dma_apbx 10>, <&dma_apbx 11>;
 				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
@@ -949,7 +941,7 @@
 			auart2: serial@8006e000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006e000 0x2000>;
-				interrupts = <114 74 75>;
+				interrupts = <114>;
 				dmas = <&dma_apbx 12>, <&dma_apbx 13>;
 				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
@@ -959,7 +951,7 @@
 			auart3: serial@80070000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x80070000 0x2000>;
-				interrupts = <115 76 77>;
+				interrupts = <115>;
 				dmas = <&dma_apbx 14>, <&dma_apbx 15>;
 				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
@@ -969,7 +961,7 @@
 			auart4: serial@80072000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x80072000 0x2000>;
-				interrupts = <116 78 79>;
+				interrupts = <116>;
 				dmas = <&dma_apbx 0>, <&dma_apbx 1>;
 				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
index c544925..c34f825 100644
--- a/arch/arm/boot/dts/imx31.dtsi
+++ b/arch/arm/boot/dts/imx31.dtsi
@@ -20,6 +20,16 @@
 		serial4 = &uart5;
 	};
 
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			compatible = "arm,arm1136";
+			device_type = "cpu";
+		};
+	};
+
 	avic: avic-interrupt-controller@60000000 {
 		compatible = "fsl,imx31-avic", "fsl,avic";
 		interrupt-controller;
@@ -94,6 +104,13 @@
 				status = "disabled";
 			};
 
+			iim: iim@5001c000 {
+				compatible = "fsl,imx31-iim", "fsl,imx27-iim";
+				reg = <0x5001c000 0x1000>;
+				interrupts = <19>;
+				clocks = <&clks 25>;
+			};
+
 			clks: ccm@53f80000{
 				compatible = "fsl,imx31-ccm";
 				reg = <0x53f80000 0x4000>;
diff --git a/arch/arm/boot/dts/imx51-apf51.dts b/arch/arm/boot/dts/imx51-apf51.dts
index 8f7f9ac..b360699 100644
--- a/arch/arm/boot/dts/imx51-apf51.dts
+++ b/arch/arm/boot/dts/imx51-apf51.dts
@@ -26,10 +26,6 @@
 	};
 
 	clocks {
-		ckih1 {
-			clock-frequency = <0>;
-		};
-
 		osc {
 			clock-frequency = <33554432>;
 		};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index ad3471c..1d337d9 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -63,6 +63,10 @@
 	};
 
 	clocks {
+		ckih1 {
+			clock-frequency = <22579200>;
+		};
+
 		clk_26M: codec_clock {
 			compatible = "fixed-clock";
 			reg=<0>;
@@ -108,6 +112,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,mc13892";
 		spi-max-frequency = <6000000>;
+		spi-cs-high;
 		reg = <0>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <8 0x4>;
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 25764b5..f0b25c9 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -15,13 +15,18 @@
 
 / {
 	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
 		gpio3 = &gpio4;
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		spi0 = &ecspi1;
+		spi1 = &ecspi2;
+		spi2 = &cspi;
 	};
 
 	tzic: tz-interrupt-controller@e0000000 {
@@ -42,7 +47,7 @@
 
 		ckih1 {
 			compatible = "fsl,imx-ckih1", "fixed-clock";
-			clock-frequency = <22579200>;
+			clock-frequency = <0>;
 		};
 
 		ckih2 {
@@ -149,6 +154,9 @@
 					reg = <0x70014000 0x4000>;
 					interrupts = <30>;
 					clocks = <&clks 49>;
+					dmas = <&sdma 24 1 0>,
+					       <&sdma 25 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
@@ -481,6 +489,21 @@
 					};
 				};
 
+				kpp {
+					pinctrl_kpp_1: kppgrp-1 {
+						fsl,pins = <
+							MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
+							MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
+							MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
+							MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
+							MX51_PAD_KEY_COL0__KEY_COL0 0xe8
+							MX51_PAD_KEY_COL1__KEY_COL1 0xe8
+							MX51_PAD_KEY_COL2__KEY_COL2 0xe8
+							MX51_PAD_KEY_COL3__KEY_COL3 0xe8
+						>;
+					};
+				};
+
 				pata {
 					pinctrl_pata_1: patagrp-1 {
 						fsl,pins = <
@@ -555,17 +578,40 @@
 					};
 				};
 
-				kpp {
-					pinctrl_kpp_1: kppgrp-1 {
+				usbh1 {
+					pinctrl_usbh1_1: usbh1grp-1 {
 						fsl,pins = <
-							MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
-							MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
-							MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
-							MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
-							MX51_PAD_KEY_COL0__KEY_COL0 0xe8
-							MX51_PAD_KEY_COL1__KEY_COL1 0xe8
-							MX51_PAD_KEY_COL2__KEY_COL2 0xe8
-							MX51_PAD_KEY_COL3__KEY_COL3 0xe8
+							MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
+							MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
+							MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
+							MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
+							MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
+							MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
+							MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
+							MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
+							MX51_PAD_USBH1_CLK__USBH1_CLK 0x1e5
+							MX51_PAD_USBH1_DIR__USBH1_DIR 0x1e5
+							MX51_PAD_USBH1_NXT__USBH1_NXT 0x1e5
+							MX51_PAD_USBH1_STP__USBH1_STP 0x1e5
+						>;
+					};
+				};
+
+				usbh2 {
+					pinctrl_usbh2_1: usbh2grp-1 {
+						fsl,pins = <
+							MX51_PAD_EIM_D16__USBH2_DATA0 0x1e5
+							MX51_PAD_EIM_D17__USBH2_DATA1 0x1e5
+							MX51_PAD_EIM_D18__USBH2_DATA2 0x1e5
+							MX51_PAD_EIM_D19__USBH2_DATA3 0x1e5
+							MX51_PAD_EIM_D20__USBH2_DATA4 0x1e5
+							MX51_PAD_EIM_D21__USBH2_DATA5 0x1e5
+							MX51_PAD_EIM_D22__USBH2_DATA6 0x1e5
+							MX51_PAD_EIM_D23__USBH2_DATA7 0x1e5
+							MX51_PAD_EIM_A24__USBH2_CLK 0x1e5
+							MX51_PAD_EIM_A25__USBH2_DIR 0x1e5
+							MX51_PAD_EIM_A27__USBH2_NXT 0x1e5
+							MX51_PAD_EIM_A26__USBH2_STP 0x1e5
 						>;
 					};
 				};
@@ -628,6 +674,13 @@
 			reg = <0x80000000 0x10000000>;
 			ranges;
 
+			iim: iim@83f98000 {
+				compatible = "fsl,imx51-iim", "fsl,imx27-iim";
+				reg = <0x83f98000 0x4000>;
+				interrupts = <69>;
+				clocks = <&clks 107>;
+			};
+
 			ecspi2: ecspi@83fac000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -645,6 +698,7 @@
 				interrupts = <6>;
 				clocks = <&clks 56>, <&clks 56>;
 				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
 			};
 
@@ -684,6 +738,9 @@
 				reg = <0x83fcc000 0x4000>;
 				interrupts = <29>;
 				clocks = <&clks 48>;
+				dmas = <&sdma 28 0 0>,
+				       <&sdma 29 0 0>;
+				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
@@ -695,6 +752,23 @@
 				status = "disabled";
 			};
 
+			weim: weim@83fda000 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				compatible = "fsl,imx51-weim";
+				reg = <0x83fda000 0x1000>;
+				clocks = <&clks 57>;
+				ranges = <
+					0 0 0xb0000000 0x08000000
+					1 0 0xb8000000 0x08000000
+					2 0 0xc0000000 0x08000000
+					3 0 0xc8000000 0x04000000
+					4 0 0xcc000000 0x02000000
+					5 0 0xce000000 0x02000000
+				>;
+				status = "disabled";
+			};
+
 			nfc: nand@83fdb000 {
 				compatible = "fsl,imx51-nand";
 				reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
@@ -716,6 +790,9 @@
 				reg = <0x83fe8000 0x4000>;
 				interrupts = <96>;
 				clocks = <&clks 50>;
+				dmas = <&sdma 46 0 0>,
+				       <&sdma 47 0 0>;
+				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 512a1f60..e97ddae 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -93,6 +93,15 @@
 			regulator-max-microvolt = <3200000>;
 			regulator-always-on;
 		};
+
+		reg_usb_vbus: usb_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio7 8 0>;
+			enable-active-high;
+		};
 	};
 
 	sound {
@@ -145,6 +154,7 @@
 				MX53_PAD_EIM_DA12__GPIO3_12       0x80000000
 				MX53_PAD_EIM_DA13__GPIO3_13       0x80000000
 				MX53_PAD_PATA_DA_0__GPIO7_6       0x80000000
+				MX53_PAD_PATA_DA_2__GPIO7_8	  0x80000000
 				MX53_PAD_GPIO_16__GPIO7_11        0x80000000
 			>;
 		};
@@ -297,8 +307,14 @@
 	status = "okay";
 };
 
+&vpu {
+	status = "okay";
+};
+
 &usbh1 {
-       status = "okay";
+	vbus-supply = <&reg_usb_vbus>;
+	phy_type = "utmi";
+	status = "okay";
 };
 
 &usbotg {
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 569aa9f..4307e80 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -15,11 +15,6 @@
 
 / {
 	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -30,6 +25,24 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		spi0 = &ecspi1;
+		spi1 = &ecspi2;
+		spi2 = &cspi;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a8";
+			reg = <0x0>;
+		};
 	};
 
 	tzic: tz-interrupt-controller@0fffc000 {
@@ -140,6 +153,9 @@
 					reg = <0x50014000 0x4000>;
 					interrupts = <30>;
 					clocks = <&clks 49>;
+					dmas = <&sdma 24 1 0>,
+					       <&sdma 25 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
@@ -957,6 +973,13 @@
 			reg = <0x60000000 0x10000000>;
 			ranges;
 
+			iim: iim@63f98000 {
+				compatible = "fsl,imx53-iim", "fsl,imx27-iim";
+				reg = <0x63f98000 0x4000>;
+				interrupts = <69>;
+				clocks = <&clks 107>;
+			};
+
 			uart5: serial@63f90000 {
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x63f90000 0x4000>;
@@ -990,6 +1013,7 @@
 				interrupts = <6>;
 				clocks = <&clks 56>, <&clks 56>;
 				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
 			};
 
@@ -1029,6 +1053,9 @@
 				reg = <0x63fcc000 0x4000>;
 				interrupts = <29>;
 				clocks = <&clks 48>;
+				dmas = <&sdma 28 0 0>,
+				       <&sdma 29 0 0>;
+				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
@@ -1053,6 +1080,9 @@
 				reg = <0x63fe8000 0x4000>;
 				interrupts = <96>;
 				clocks = <&clks 50>;
+				dmas = <&sdma 46 0 0>,
+				       <&sdma 47 0 0>;
+				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <47 46 45 44>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
@@ -1076,6 +1106,22 @@
 				crtcs = <&ipu 1>;
 				status = "disabled";
 			};
+
+			vpu: vpu@63ff4000 {
+				compatible = "fsl,imx53-vpu";
+				reg = <0x63ff4000 0x1000>;
+				interrupts = <9>;
+				clocks = <&clks 63>, <&clks 63>;
+				clock-names = "per", "ahb";
+				iram = <&ocram>;
+				status = "disabled";
+			};
+		};
+
+		ocram: sram@f8000000 {
+			compatible = "mmio-sram";
+			reg = <0xf8000000 0x20000>;
+			clocks = <&clks 186>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx6dl-pinfunc.h b/arch/arm/boot/dts/imx6dl-pinfunc.h
index 9aab950..b81a7a4 100644
--- a/arch/arm/boot/dts/imx6dl-pinfunc.h
+++ b/arch/arm/boot/dts/imx6dl-pinfunc.h
@@ -14,1072 +14,1076 @@
  * The pin function ID is a tuple of
  * <mux_reg conf_reg input_reg mux_mode input_val>
  */
-#define MX6DL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10     0x04c 0x360 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT10__AUD3_RXC             0x04c 0x360 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT10__ECSPI2_MISO          0x04c 0x360 0x7f8 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT10__UART1_TX_DATA        0x04c 0x360 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT10__UART1_RX_DATA        0x04c 0x360 0x8fc 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT10__GPIO5_IO28           0x04c 0x360 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT10__ARM_TRACE07          0x04c 0x360 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11     0x050 0x364 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT11__AUD3_RXFS            0x050 0x364 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT11__ECSPI2_SS0           0x050 0x364 0x800 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT11__UART1_RX_DATA        0x050 0x364 0x8fc 0x3 0x1
-#define MX6DL_PAD_CSI0_DAT11__UART1_TX_DATA        0x050 0x364 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT11__GPIO5_IO29           0x050 0x364 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT11__ARM_TRACE08          0x050 0x364 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12     0x054 0x368 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT12__EIM_DATA08           0x054 0x368 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT12__UART4_TX_DATA        0x054 0x368 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT12__UART4_RX_DATA        0x054 0x368 0x914 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT12__GPIO5_IO30           0x054 0x368 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT12__ARM_TRACE09          0x054 0x368 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13     0x058 0x36c 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT13__EIM_DATA09           0x058 0x36c 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT13__UART4_RX_DATA        0x058 0x36c 0x914 0x3 0x1
-#define MX6DL_PAD_CSI0_DAT13__UART4_TX_DATA        0x058 0x36c 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT13__GPIO5_IO31           0x058 0x36c 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT13__ARM_TRACE10          0x058 0x36c 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14     0x05c 0x370 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT14__EIM_DATA10           0x05c 0x370 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT14__UART5_TX_DATA        0x05c 0x370 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT14__UART5_RX_DATA        0x05c 0x370 0x91c 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT14__GPIO6_IO00           0x05c 0x370 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT14__ARM_TRACE11          0x05c 0x370 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15     0x060 0x374 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT15__EIM_DATA11           0x060 0x374 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT15__UART5_RX_DATA        0x060 0x374 0x91c 0x3 0x1
-#define MX6DL_PAD_CSI0_DAT15__UART5_TX_DATA        0x060 0x374 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT15__GPIO6_IO01           0x060 0x374 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT15__ARM_TRACE12          0x060 0x374 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16     0x064 0x378 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT16__EIM_DATA12           0x064 0x378 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT16__UART4_RTS_B          0x064 0x378 0x910 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT16__UART4_CTS_B          0x064 0x378 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT16__GPIO6_IO02           0x064 0x378 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT16__ARM_TRACE13          0x064 0x378 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17     0x068 0x37c 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT17__EIM_DATA13           0x068 0x37c 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT17__UART4_CTS_B          0x068 0x37c 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT17__UART4_RTS_B          0x068 0x37c 0x910 0x3 0x1
-#define MX6DL_PAD_CSI0_DAT17__GPIO6_IO03           0x068 0x37c 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT17__ARM_TRACE14          0x068 0x37c 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18     0x06c 0x380 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT18__EIM_DATA14           0x06c 0x380 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT18__UART5_RTS_B          0x06c 0x380 0x918 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT18__UART5_CTS_B          0x06c 0x380 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT18__GPIO6_IO04           0x06c 0x380 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT18__ARM_TRACE15          0x06c 0x380 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19     0x070 0x384 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT19__EIM_DATA15           0x070 0x384 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT19__UART5_CTS_B          0x070 0x384 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT19__UART5_RTS_B          0x070 0x384 0x918 0x3 0x1
-#define MX6DL_PAD_CSI0_DAT19__GPIO6_IO05           0x070 0x384 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04      0x074 0x388 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT4__EIM_DATA02            0x074 0x388 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT4__ECSPI1_SCLK           0x074 0x388 0x7d8 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT4__KEY_COL5              0x074 0x388 0x8c0 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT4__AUD3_TXC              0x074 0x388 0x000 0x4 0x0
-#define MX6DL_PAD_CSI0_DAT4__GPIO5_IO22            0x074 0x388 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT4__ARM_TRACE01           0x074 0x388 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05      0x078 0x38c 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT5__EIM_DATA03            0x078 0x38c 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT5__ECSPI1_MOSI           0x078 0x38c 0x7e0 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT5__KEY_ROW5              0x078 0x38c 0x8cc 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT5__AUD3_TXD              0x078 0x38c 0x000 0x4 0x0
-#define MX6DL_PAD_CSI0_DAT5__GPIO5_IO23            0x078 0x38c 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT5__ARM_TRACE02           0x078 0x38c 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06      0x07c 0x390 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT6__EIM_DATA04            0x07c 0x390 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT6__ECSPI1_MISO           0x07c 0x390 0x7dc 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT6__KEY_COL6              0x07c 0x390 0x8c4 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT6__AUD3_TXFS             0x07c 0x390 0x000 0x4 0x0
-#define MX6DL_PAD_CSI0_DAT6__GPIO5_IO24            0x07c 0x390 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT6__ARM_TRACE03           0x07c 0x390 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07      0x080 0x394 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT7__EIM_DATA05            0x080 0x394 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT7__ECSPI1_SS0            0x080 0x394 0x7e4 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT7__KEY_ROW6              0x080 0x394 0x8d0 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT7__AUD3_RXD              0x080 0x394 0x000 0x4 0x0
-#define MX6DL_PAD_CSI0_DAT7__GPIO5_IO25            0x080 0x394 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT7__ARM_TRACE04           0x080 0x394 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08      0x084 0x398 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT8__EIM_DATA06            0x084 0x398 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT8__ECSPI2_SCLK           0x084 0x398 0x7f4 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT8__KEY_COL7              0x084 0x398 0x8c8 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT8__I2C1_SDA              0x084 0x398 0x86c 0x4 0x0
-#define MX6DL_PAD_CSI0_DAT8__GPIO5_IO26            0x084 0x398 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT8__ARM_TRACE05           0x084 0x398 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09      0x088 0x39c 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DAT9__EIM_DATA07            0x088 0x39c 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DAT9__ECSPI2_MOSI           0x088 0x39c 0x7fc 0x2 0x0
-#define MX6DL_PAD_CSI0_DAT9__KEY_ROW7              0x088 0x39c 0x8d4 0x3 0x0
-#define MX6DL_PAD_CSI0_DAT9__I2C1_SCL              0x088 0x39c 0x868 0x4 0x0
-#define MX6DL_PAD_CSI0_DAT9__GPIO5_IO27            0x088 0x39c 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DAT9__ARM_TRACE06           0x088 0x39c 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN  0x08c 0x3a0 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_DATA_EN__EIM_DATA00         0x08c 0x3a0 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_DATA_EN__GPIO5_IO20         0x08c 0x3a0 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_DATA_EN__ARM_TRACE_CLK      0x08c 0x3a0 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC       0x090 0x3a4 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_MCLK__CCM_CLKO1             0x090 0x3a4 0x000 0x3 0x0
-#define MX6DL_PAD_CSI0_MCLK__GPIO5_IO19            0x090 0x3a4 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_MCLK__ARM_TRACE_CTL         0x090 0x3a4 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK    0x094 0x3a8 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_PIXCLK__GPIO5_IO18          0x094 0x3a8 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_PIXCLK__ARM_EVENTO          0x094 0x3a8 0x000 0x7 0x0
-#define MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC      0x098 0x3ac 0x000 0x0 0x0
-#define MX6DL_PAD_CSI0_VSYNC__EIM_DATA01           0x098 0x3ac 0x000 0x1 0x0
-#define MX6DL_PAD_CSI0_VSYNC__GPIO5_IO21           0x098 0x3ac 0x000 0x5 0x0
-#define MX6DL_PAD_CSI0_VSYNC__ARM_TRACE00          0x098 0x3ac 0x000 0x7 0x0
-#define MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK  0x09c 0x3b0 0x000 0x0 0x0
-#define MX6DL_PAD_DI0_DISP_CLK__LCD_CLK            0x09c 0x3b0 0x000 0x1 0x0
-#define MX6DL_PAD_DI0_DISP_CLK__GPIO4_IO16         0x09c 0x3b0 0x000 0x5 0x0
-#define MX6DL_PAD_DI0_DISP_CLK__LCD_WR_RWN         0x09c 0x3b0 0x000 0x8 0x0
-#define MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15        0x0a0 0x3b4 0x000 0x0 0x0
-#define MX6DL_PAD_DI0_PIN15__LCD_ENABLE            0x0a0 0x3b4 0x000 0x1 0x0
-#define MX6DL_PAD_DI0_PIN15__AUD6_TXC              0x0a0 0x3b4 0x000 0x2 0x0
-#define MX6DL_PAD_DI0_PIN15__GPIO4_IO17            0x0a0 0x3b4 0x000 0x5 0x0
-#define MX6DL_PAD_DI0_PIN15__LCD_RD_E              0x0a0 0x3b4 0x000 0x8 0x0
-#define MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN02         0x0a4 0x3b8 0x000 0x0 0x0
-#define MX6DL_PAD_DI0_PIN2__LCD_HSYNC              0x0a4 0x3b8 0x8d8 0x1 0x0
-#define MX6DL_PAD_DI0_PIN2__AUD6_TXD               0x0a4 0x3b8 0x000 0x2 0x0
-#define MX6DL_PAD_DI0_PIN2__GPIO4_IO18             0x0a4 0x3b8 0x000 0x5 0x0
-#define MX6DL_PAD_DI0_PIN2__LCD_RS                 0x0a4 0x3b8 0x000 0x8 0x0
-#define MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN03         0x0a8 0x3bc 0x000 0x0 0x0
-#define MX6DL_PAD_DI0_PIN3__LCD_VSYNC              0x0a8 0x3bc 0x000 0x1 0x0
-#define MX6DL_PAD_DI0_PIN3__AUD6_TXFS              0x0a8 0x3bc 0x000 0x2 0x0
-#define MX6DL_PAD_DI0_PIN3__GPIO4_IO19             0x0a8 0x3bc 0x000 0x5 0x0
-#define MX6DL_PAD_DI0_PIN3__LCD_CS                 0x0a8 0x3bc 0x000 0x8 0x0
-#define MX6DL_PAD_DI0_PIN4__IPU1_DI0_PIN04         0x0ac 0x3c0 0x000 0x0 0x0
-#define MX6DL_PAD_DI0_PIN4__LCD_BUSY               0x0ac 0x3c0 0x8d8 0x1 0x1
-#define MX6DL_PAD_DI0_PIN4__AUD6_RXD               0x0ac 0x3c0 0x000 0x2 0x0
-#define MX6DL_PAD_DI0_PIN4__SD1_WP                 0x0ac 0x3c0 0x92c 0x3 0x0
-#define MX6DL_PAD_DI0_PIN4__GPIO4_IO20             0x0ac 0x3c0 0x000 0x5 0x0
-#define MX6DL_PAD_DI0_PIN4__LCD_RESET              0x0ac 0x3c0 0x000 0x8 0x0
-#define MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00    0x0b0 0x3c4 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT0__LCD_DATA00           0x0b0 0x3c4 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT0__ECSPI3_SCLK          0x0b0 0x3c4 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT0__GPIO4_IO21           0x0b0 0x3c4 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01    0x0b4 0x3c8 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT1__LCD_DATA01           0x0b4 0x3c8 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT1__ECSPI3_MOSI          0x0b4 0x3c8 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT1__GPIO4_IO22           0x0b4 0x3c8 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10   0x0b8 0x3cc 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT10__LCD_DATA10          0x0b8 0x3cc 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT10__GPIO4_IO31          0x0b8 0x3cc 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11   0x0bc 0x3d0 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT11__LCD_DATA11          0x0bc 0x3d0 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT11__GPIO5_IO05          0x0bc 0x3d0 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12   0x0c0 0x3d4 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT12__LCD_DATA12          0x0c0 0x3d4 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT12__GPIO5_IO06          0x0c0 0x3d4 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13   0x0c4 0x3d8 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT13__LCD_DATA13          0x0c4 0x3d8 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT13__AUD5_RXFS           0x0c4 0x3d8 0x7bc 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT13__GPIO5_IO07          0x0c4 0x3d8 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14   0x0c8 0x3dc 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT14__LCD_DATA14          0x0c8 0x3dc 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT14__AUD5_RXC            0x0c8 0x3dc 0x7b8 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT14__GPIO5_IO08          0x0c8 0x3dc 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15   0x0cc 0x3e0 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT15__LCD_DATA15          0x0cc 0x3e0 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT15__ECSPI1_SS1          0x0cc 0x3e0 0x7e8 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT15__ECSPI2_SS1          0x0cc 0x3e0 0x804 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT15__GPIO5_IO09          0x0cc 0x3e0 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16   0x0d0 0x3e4 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT16__LCD_DATA16          0x0d0 0x3e4 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT16__ECSPI2_MOSI         0x0d0 0x3e4 0x7fc 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT16__AUD5_TXC            0x0d0 0x3e4 0x7c0 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT16__SDMA_EXT_EVENT0     0x0d0 0x3e4 0x8e8 0x4 0x0
-#define MX6DL_PAD_DISP0_DAT16__GPIO5_IO10          0x0d0 0x3e4 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17   0x0d4 0x3e8 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT17__LCD_DATA17          0x0d4 0x3e8 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT17__ECSPI2_MISO         0x0d4 0x3e8 0x7f8 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT17__AUD5_TXD            0x0d4 0x3e8 0x7b4 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT17__SDMA_EXT_EVENT1     0x0d4 0x3e8 0x8ec 0x4 0x0
-#define MX6DL_PAD_DISP0_DAT17__GPIO5_IO11          0x0d4 0x3e8 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18   0x0d8 0x3ec 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT18__LCD_DATA18          0x0d8 0x3ec 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT18__ECSPI2_SS0          0x0d8 0x3ec 0x800 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT18__AUD5_TXFS           0x0d8 0x3ec 0x7c4 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT18__AUD4_RXFS           0x0d8 0x3ec 0x7a4 0x4 0x0
-#define MX6DL_PAD_DISP0_DAT18__GPIO5_IO12          0x0d8 0x3ec 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT18__EIM_CS2_B           0x0d8 0x3ec 0x000 0x7 0x0
-#define MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19   0x0dc 0x3f0 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT19__LCD_DATA19          0x0dc 0x3f0 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT19__ECSPI2_SCLK         0x0dc 0x3f0 0x7f4 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT19__AUD5_RXD            0x0dc 0x3f0 0x7b0 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT19__AUD4_RXC            0x0dc 0x3f0 0x7a0 0x4 0x0
-#define MX6DL_PAD_DISP0_DAT19__GPIO5_IO13          0x0dc 0x3f0 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT19__EIM_CS3_B           0x0dc 0x3f0 0x000 0x7 0x0
-#define MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02    0x0e0 0x3f4 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT2__LCD_DATA02           0x0e0 0x3f4 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT2__ECSPI3_MISO          0x0e0 0x3f4 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT2__GPIO4_IO23           0x0e0 0x3f4 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20   0x0e4 0x3f8 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT20__LCD_DATA20          0x0e4 0x3f8 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT20__ECSPI1_SCLK         0x0e4 0x3f8 0x7d8 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT20__AUD4_TXC            0x0e4 0x3f8 0x7a8 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT20__GPIO5_IO14          0x0e4 0x3f8 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21   0x0e8 0x3fc 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT21__LCD_DATA21          0x0e8 0x3fc 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT21__ECSPI1_MOSI         0x0e8 0x3fc 0x7e0 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT21__AUD4_TXD            0x0e8 0x3fc 0x79c 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT21__GPIO5_IO15          0x0e8 0x3fc 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22   0x0ec 0x400 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT22__LCD_DATA22          0x0ec 0x400 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT22__ECSPI1_MISO         0x0ec 0x400 0x7dc 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT22__AUD4_TXFS           0x0ec 0x400 0x7ac 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT22__GPIO5_IO16          0x0ec 0x400 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23   0x0f0 0x404 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT23__LCD_DATA23          0x0f0 0x404 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT23__ECSPI1_SS0          0x0f0 0x404 0x7e4 0x2 0x1
-#define MX6DL_PAD_DISP0_DAT23__AUD4_RXD            0x0f0 0x404 0x798 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT23__GPIO5_IO17          0x0f0 0x404 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03    0x0f4 0x408 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT3__LCD_DATA03           0x0f4 0x408 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT3__ECSPI3_SS0           0x0f4 0x408 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT3__GPIO4_IO24           0x0f4 0x408 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04    0x0f8 0x40c 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT4__LCD_DATA04           0x0f8 0x40c 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT4__ECSPI3_SS1           0x0f8 0x40c 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT4__GPIO4_IO25           0x0f8 0x40c 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05    0x0fc 0x410 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT5__LCD_DATA05           0x0fc 0x410 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT5__ECSPI3_SS2           0x0fc 0x410 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT5__AUD6_RXFS            0x0fc 0x410 0x000 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT5__GPIO4_IO26           0x0fc 0x410 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06    0x100 0x414 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT6__LCD_DATA06           0x100 0x414 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT6__ECSPI3_SS3           0x100 0x414 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT6__AUD6_RXC             0x100 0x414 0x000 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT6__GPIO4_IO27           0x100 0x414 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07    0x104 0x418 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT7__LCD_DATA07           0x104 0x418 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT7__ECSPI3_RDY           0x104 0x418 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT7__GPIO4_IO28           0x104 0x418 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08    0x108 0x41c 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT8__LCD_DATA08           0x108 0x41c 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT8__PWM1_OUT             0x108 0x41c 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT8__WDOG1_B              0x108 0x41c 0x000 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT8__GPIO4_IO29           0x108 0x41c 0x000 0x5 0x0
-#define MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09    0x10c 0x420 0x000 0x0 0x0
-#define MX6DL_PAD_DISP0_DAT9__LCD_DATA09           0x10c 0x420 0x000 0x1 0x0
-#define MX6DL_PAD_DISP0_DAT9__PWM2_OUT             0x10c 0x420 0x000 0x2 0x0
-#define MX6DL_PAD_DISP0_DAT9__WDOG2_B              0x10c 0x420 0x000 0x3 0x0
-#define MX6DL_PAD_DISP0_DAT9__GPIO4_IO30           0x10c 0x420 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A16__EIM_ADDR16              0x110 0x4e0 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A16__IPU1_DI1_DISP_CLK       0x110 0x4e0 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A16__IPU1_CSI1_PIXCLK        0x110 0x4e0 0x8b8 0x2 0x0
-#define MX6DL_PAD_EIM_A16__GPIO2_IO22              0x110 0x4e0 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A16__SRC_BOOT_CFG16          0x110 0x4e0 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A16__EPDC_DATA00             0x110 0x4e0 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A17__EIM_ADDR17              0x114 0x4e4 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A17__IPU1_DISP1_DATA12       0x114 0x4e4 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A17__IPU1_CSI1_DATA12        0x114 0x4e4 0x890 0x2 0x0
-#define MX6DL_PAD_EIM_A17__GPIO2_IO21              0x114 0x4e4 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A17__SRC_BOOT_CFG17          0x114 0x4e4 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A17__EPDC_PWR_STAT           0x114 0x4e4 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A18__EIM_ADDR18              0x118 0x4e8 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A18__IPU1_DISP1_DATA13       0x118 0x4e8 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A18__IPU1_CSI1_DATA13        0x118 0x4e8 0x894 0x2 0x0
-#define MX6DL_PAD_EIM_A18__GPIO2_IO20              0x118 0x4e8 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A18__SRC_BOOT_CFG18          0x118 0x4e8 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A18__EPDC_PWR_CTRL0          0x118 0x4e8 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A19__EIM_ADDR19              0x11c 0x4ec 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A19__IPU1_DISP1_DATA14       0x11c 0x4ec 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A19__IPU1_CSI1_DATA14        0x11c 0x4ec 0x898 0x2 0x0
-#define MX6DL_PAD_EIM_A19__GPIO2_IO19              0x11c 0x4ec 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A19__SRC_BOOT_CFG19          0x11c 0x4ec 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A19__EPDC_PWR_CTRL1          0x11c 0x4ec 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A20__EIM_ADDR20              0x120 0x4f0 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A20__IPU1_DISP1_DATA15       0x120 0x4f0 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A20__IPU1_CSI1_DATA15        0x120 0x4f0 0x89c 0x2 0x0
-#define MX6DL_PAD_EIM_A20__GPIO2_IO18              0x120 0x4f0 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A20__SRC_BOOT_CFG20          0x120 0x4f0 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A20__EPDC_PWR_CTRL2          0x120 0x4f0 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A21__EIM_ADDR21              0x124 0x4f4 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A21__IPU1_DISP1_DATA16       0x124 0x4f4 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A21__IPU1_CSI1_DATA16        0x124 0x4f4 0x8a0 0x2 0x0
-#define MX6DL_PAD_EIM_A21__GPIO2_IO17              0x124 0x4f4 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A21__SRC_BOOT_CFG21          0x124 0x4f4 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A21__EPDC_GDCLK              0x124 0x4f4 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A22__EIM_ADDR22              0x128 0x4f8 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A22__IPU1_DISP1_DATA17       0x128 0x4f8 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A22__IPU1_CSI1_DATA17        0x128 0x4f8 0x8a4 0x2 0x0
-#define MX6DL_PAD_EIM_A22__GPIO2_IO16              0x128 0x4f8 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A22__SRC_BOOT_CFG22          0x128 0x4f8 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A22__EPDC_GDSP               0x128 0x4f8 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A23__EIM_ADDR23              0x12c 0x4fc 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A23__IPU1_DISP1_DATA18       0x12c 0x4fc 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A23__IPU1_CSI1_DATA18        0x12c 0x4fc 0x8a8 0x2 0x0
-#define MX6DL_PAD_EIM_A23__IPU1_SISG3              0x12c 0x4fc 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_A23__GPIO6_IO06              0x12c 0x4fc 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A23__SRC_BOOT_CFG23          0x12c 0x4fc 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A23__EPDC_GDOE               0x12c 0x4fc 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A24__EIM_ADDR24              0x130 0x500 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A24__IPU1_DISP1_DATA19       0x130 0x500 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A24__IPU1_CSI1_DATA19        0x130 0x500 0x8ac 0x2 0x0
-#define MX6DL_PAD_EIM_A24__IPU1_SISG2              0x130 0x500 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_A24__GPIO5_IO04              0x130 0x500 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A24__SRC_BOOT_CFG24          0x130 0x500 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_A24__EPDC_GDRL               0x130 0x500 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A25__EIM_ADDR25              0x134 0x504 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_A25__ECSPI4_SS1              0x134 0x504 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_A25__ECSPI2_RDY              0x134 0x504 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_A25__IPU1_DI1_PIN12          0x134 0x504 0x000 0x3 0x0
-#define MX6DL_PAD_EIM_A25__IPU1_DI0_D1_CS          0x134 0x504 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_A25__GPIO5_IO02              0x134 0x504 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE        0x134 0x504 0x85c 0x6 0x0
-#define MX6DL_PAD_EIM_A25__EPDC_DATA15             0x134 0x504 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_A25__EIM_ACLK_FREERUN        0x134 0x504 0x000 0x9 0x0
-#define MX6DL_PAD_EIM_BCLK__EIM_BCLK               0x138 0x508 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_BCLK__IPU1_DI1_PIN16         0x138 0x508 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_BCLK__GPIO6_IO31             0x138 0x508 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_BCLK__EPDC_SDCE9             0x138 0x508 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_CS0__EIM_CS0_B               0x13c 0x50c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_CS0__IPU1_DI1_PIN05          0x13c 0x50c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_CS0__ECSPI2_SCLK             0x13c 0x50c 0x7f4 0x2 0x2
-#define MX6DL_PAD_EIM_CS0__GPIO2_IO23              0x13c 0x50c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_CS0__EPDC_DATA06             0x13c 0x50c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_CS1__EIM_CS1_B               0x140 0x510 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_CS1__IPU1_DI1_PIN06          0x140 0x510 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_CS1__ECSPI2_MOSI             0x140 0x510 0x7fc 0x2 0x2
-#define MX6DL_PAD_EIM_CS1__GPIO2_IO24              0x140 0x510 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_CS1__EPDC_DATA08             0x140 0x510 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D16__EIM_DATA16              0x144 0x514 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D16__ECSPI1_SCLK             0x144 0x514 0x7d8 0x1 0x2
-#define MX6DL_PAD_EIM_D16__IPU1_DI0_PIN05          0x144 0x514 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D16__IPU1_CSI1_DATA18        0x144 0x514 0x8a8 0x3 0x1
-#define MX6DL_PAD_EIM_D16__HDMI_TX_DDC_SDA         0x144 0x514 0x864 0x4 0x0
-#define MX6DL_PAD_EIM_D16__GPIO3_IO16              0x144 0x514 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D16__I2C2_SDA                0x144 0x514 0x874 0x6 0x0
-#define MX6DL_PAD_EIM_D16__EPDC_DATA10             0x144 0x514 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D17__EIM_DATA17              0x148 0x518 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D17__ECSPI1_MISO             0x148 0x518 0x7dc 0x1 0x2
-#define MX6DL_PAD_EIM_D17__IPU1_DI0_PIN06          0x148 0x518 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D17__IPU1_CSI1_PIXCLK        0x148 0x518 0x8b8 0x3 0x1
-#define MX6DL_PAD_EIM_D17__DCIC1_OUT               0x148 0x518 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D17__GPIO3_IO17              0x148 0x518 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D17__I2C3_SCL                0x148 0x518 0x878 0x6 0x0
-#define MX6DL_PAD_EIM_D17__EPDC_VCOM0              0x148 0x518 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D18__EIM_DATA18              0x14c 0x51c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D18__ECSPI1_MOSI             0x14c 0x51c 0x7e0 0x1 0x2
-#define MX6DL_PAD_EIM_D18__IPU1_DI0_PIN07          0x14c 0x51c 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D18__IPU1_CSI1_DATA17        0x14c 0x51c 0x8a4 0x3 0x1
-#define MX6DL_PAD_EIM_D18__IPU1_DI1_D0_CS          0x14c 0x51c 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D18__GPIO3_IO18              0x14c 0x51c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D18__I2C3_SDA                0x14c 0x51c 0x87c 0x6 0x0
-#define MX6DL_PAD_EIM_D18__EPDC_VCOM1              0x14c 0x51c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D19__EIM_DATA19              0x150 0x520 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D19__ECSPI1_SS1              0x150 0x520 0x7e8 0x1 0x1
-#define MX6DL_PAD_EIM_D19__IPU1_DI0_PIN08          0x150 0x520 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D19__IPU1_CSI1_DATA16        0x150 0x520 0x8a0 0x3 0x1
-#define MX6DL_PAD_EIM_D19__UART1_CTS_B             0x150 0x520 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D19__UART1_RTS_B             0x150 0x520 0x8f8 0x4 0x0
-#define MX6DL_PAD_EIM_D19__GPIO3_IO19              0x150 0x520 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D19__EPIT1_OUT               0x150 0x520 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D19__EPDC_DATA12             0x150 0x520 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D20__EIM_DATA20              0x154 0x524 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D20__ECSPI4_SS0              0x154 0x524 0x808 0x1 0x0
-#define MX6DL_PAD_EIM_D20__IPU1_DI0_PIN16          0x154 0x524 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D20__IPU1_CSI1_DATA15        0x154 0x524 0x89c 0x3 0x1
-#define MX6DL_PAD_EIM_D20__UART1_RTS_B             0x154 0x524 0x8f8 0x4 0x1
-#define MX6DL_PAD_EIM_D20__UART1_CTS_B             0x154 0x524 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D20__GPIO3_IO20              0x154 0x524 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D20__EPIT2_OUT               0x154 0x524 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D21__EIM_DATA21              0x158 0x528 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D21__ECSPI4_SCLK             0x158 0x528 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D21__IPU1_DI0_PIN17          0x158 0x528 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D21__IPU1_CSI1_DATA11        0x158 0x528 0x88c 0x3 0x0
-#define MX6DL_PAD_EIM_D21__USB_OTG_OC              0x158 0x528 0x920 0x4 0x0
-#define MX6DL_PAD_EIM_D21__GPIO3_IO21              0x158 0x528 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D21__I2C1_SCL                0x158 0x528 0x868 0x6 0x1
-#define MX6DL_PAD_EIM_D21__SPDIF_IN                0x158 0x528 0x8f0 0x7 0x0
-#define MX6DL_PAD_EIM_D22__EIM_DATA22              0x15c 0x52c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D22__ECSPI4_MISO             0x15c 0x52c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D22__IPU1_DI0_PIN01          0x15c 0x52c 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D22__IPU1_CSI1_DATA10        0x15c 0x52c 0x888 0x3 0x0
-#define MX6DL_PAD_EIM_D22__USB_OTG_PWR             0x15c 0x52c 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D22__GPIO3_IO22              0x15c 0x52c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D22__SPDIF_OUT               0x15c 0x52c 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D22__EPDC_SDCE6              0x15c 0x52c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D23__EIM_DATA23              0x160 0x530 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D23__IPU1_DI0_D0_CS          0x160 0x530 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D23__UART3_CTS_B             0x160 0x530 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D23__UART3_RTS_B             0x160 0x530 0x908 0x2 0x0
-#define MX6DL_PAD_EIM_D23__UART1_DCD_B             0x160 0x530 0x000 0x3 0x0
-#define MX6DL_PAD_EIM_D23__IPU1_CSI1_DATA_EN       0x160 0x530 0x8b0 0x4 0x0
-#define MX6DL_PAD_EIM_D23__GPIO3_IO23              0x160 0x530 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D23__IPU1_DI1_PIN02          0x160 0x530 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D23__IPU1_DI1_PIN14          0x160 0x530 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D23__EPDC_DATA11             0x160 0x530 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D24__EIM_DATA24              0x164 0x534 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D24__ECSPI4_SS2              0x164 0x534 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D24__UART3_TX_DATA           0x164 0x534 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D24__UART3_RX_DATA           0x164 0x534 0x90c 0x2 0x0
-#define MX6DL_PAD_EIM_D24__ECSPI1_SS2              0x164 0x534 0x7ec 0x3 0x0
-#define MX6DL_PAD_EIM_D24__ECSPI2_SS2              0x164 0x534 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D24__GPIO3_IO24              0x164 0x534 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D24__AUD5_RXFS               0x164 0x534 0x7bc 0x6 0x1
-#define MX6DL_PAD_EIM_D24__UART1_DTR_B             0x164 0x534 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D24__EPDC_SDCE7              0x164 0x534 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D25__EIM_DATA25              0x168 0x538 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D25__ECSPI4_SS3              0x168 0x538 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D25__UART3_RX_DATA           0x168 0x538 0x90c 0x2 0x1
-#define MX6DL_PAD_EIM_D25__UART3_TX_DATA           0x168 0x538 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D25__ECSPI1_SS3              0x168 0x538 0x7f0 0x3 0x0
-#define MX6DL_PAD_EIM_D25__ECSPI2_SS3              0x168 0x538 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D25__GPIO3_IO25              0x168 0x538 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D25__AUD5_RXC                0x168 0x538 0x7b8 0x6 0x1
-#define MX6DL_PAD_EIM_D25__UART1_DSR_B             0x168 0x538 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D25__EPDC_SDCE8              0x168 0x538 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D26__EIM_DATA26              0x16c 0x53c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D26__IPU1_DI1_PIN11          0x16c 0x53c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D26__IPU1_CSI0_DATA01        0x16c 0x53c 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D26__IPU1_CSI1_DATA14        0x16c 0x53c 0x898 0x3 0x1
-#define MX6DL_PAD_EIM_D26__UART2_TX_DATA           0x16c 0x53c 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D26__UART2_RX_DATA           0x16c 0x53c 0x904 0x4 0x0
-#define MX6DL_PAD_EIM_D26__GPIO3_IO26              0x16c 0x53c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D26__IPU1_SISG2              0x16c 0x53c 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D26__IPU1_DISP1_DATA22       0x16c 0x53c 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D26__EPDC_SDOED              0x16c 0x53c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D27__EIM_DATA27              0x170 0x540 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D27__IPU1_DI1_PIN13          0x170 0x540 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D27__IPU1_CSI0_DATA00        0x170 0x540 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D27__IPU1_CSI1_DATA13        0x170 0x540 0x894 0x3 0x1
-#define MX6DL_PAD_EIM_D27__UART2_RX_DATA           0x170 0x540 0x904 0x4 0x1
-#define MX6DL_PAD_EIM_D27__UART2_TX_DATA           0x170 0x540 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D27__GPIO3_IO27              0x170 0x540 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D27__IPU1_SISG3              0x170 0x540 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D27__IPU1_DISP1_DATA23       0x170 0x540 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D27__EPDC_SDOE               0x170 0x540 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D28__EIM_DATA28              0x174 0x544 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D28__I2C1_SDA                0x174 0x544 0x86c 0x1 0x1
-#define MX6DL_PAD_EIM_D28__ECSPI4_MOSI             0x174 0x544 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D28__IPU1_CSI1_DATA12        0x174 0x544 0x890 0x3 0x1
-#define MX6DL_PAD_EIM_D28__UART2_CTS_B             0x174 0x544 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D28__UART2_RTS_B             0x174 0x544 0x900 0x4 0x0
-#define MX6DL_PAD_EIM_D28__GPIO3_IO28              0x174 0x544 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D28__IPU1_EXT_TRIG           0x174 0x544 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D28__IPU1_DI0_PIN13          0x174 0x544 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D28__EPDC_PWR_CTRL3          0x174 0x544 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D29__EIM_DATA29              0x178 0x548 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D29__IPU1_DI1_PIN15          0x178 0x548 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D29__ECSPI4_SS0              0x178 0x548 0x808 0x2 0x1
-#define MX6DL_PAD_EIM_D29__UART2_RTS_B             0x178 0x548 0x900 0x4 0x1
-#define MX6DL_PAD_EIM_D29__UART2_CTS_B             0x178 0x548 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D29__GPIO3_IO29              0x178 0x548 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D29__IPU1_CSI1_VSYNC         0x178 0x548 0x8bc 0x6 0x0
-#define MX6DL_PAD_EIM_D29__IPU1_DI0_PIN14          0x178 0x548 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_D29__EPDC_PWR_WAKE           0x178 0x548 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D30__EIM_DATA30              0x17c 0x54c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D30__IPU1_DISP1_DATA21       0x17c 0x54c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D30__IPU1_DI0_PIN11          0x17c 0x54c 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D30__IPU1_CSI0_DATA03        0x17c 0x54c 0x000 0x3 0x0
-#define MX6DL_PAD_EIM_D30__UART3_CTS_B             0x17c 0x54c 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D30__UART3_RTS_B             0x17c 0x54c 0x908 0x4 0x1
-#define MX6DL_PAD_EIM_D30__GPIO3_IO30              0x17c 0x54c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D30__USB_H1_OC               0x17c 0x54c 0x924 0x6 0x0
-#define MX6DL_PAD_EIM_D30__EPDC_SDOEZ              0x17c 0x54c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D31__EIM_DATA31              0x180 0x550 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_D31__IPU1_DISP1_DATA20       0x180 0x550 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_D31__IPU1_DI0_PIN12          0x180 0x550 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_D31__IPU1_CSI0_DATA02        0x180 0x550 0x000 0x3 0x0
-#define MX6DL_PAD_EIM_D31__UART3_RTS_B             0x180 0x550 0x908 0x4 0x2
-#define MX6DL_PAD_EIM_D31__UART3_CTS_B             0x180 0x550 0x000 0x4 0x0
-#define MX6DL_PAD_EIM_D31__GPIO3_IO31              0x180 0x550 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_D31__USB_H1_PWR              0x180 0x550 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_D31__EPDC_SDCLK_P            0x180 0x550 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_D31__EIM_ACLK_FREERUN        0x180 0x550 0x000 0x9 0x0
-#define MX6DL_PAD_EIM_DA0__EIM_AD00                0x184 0x554 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA0__IPU1_DISP1_DATA09       0x184 0x554 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA0__IPU1_CSI1_DATA09        0x184 0x554 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA0__GPIO3_IO00              0x184 0x554 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA0__SRC_BOOT_CFG00          0x184 0x554 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA0__EPDC_SDCLK_N            0x184 0x554 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA1__EIM_AD01                0x188 0x558 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA1__IPU1_DISP1_DATA08       0x188 0x558 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA1__IPU1_CSI1_DATA08        0x188 0x558 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA1__GPIO3_IO01              0x188 0x558 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA1__SRC_BOOT_CFG01          0x188 0x558 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA1__EPDC_SDLE               0x188 0x558 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA10__EIM_AD10               0x18c 0x55c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA10__IPU1_DI1_PIN15         0x18c 0x55c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA10__IPU1_CSI1_DATA_EN      0x18c 0x55c 0x8b0 0x2 0x1
-#define MX6DL_PAD_EIM_DA10__GPIO3_IO10             0x18c 0x55c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA10__SRC_BOOT_CFG10         0x18c 0x55c 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA10__EPDC_DATA01            0x18c 0x55c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA11__EIM_AD11               0x190 0x560 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA11__IPU1_DI1_PIN02         0x190 0x560 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA11__IPU1_CSI1_HSYNC        0x190 0x560 0x8b4 0x2 0x0
-#define MX6DL_PAD_EIM_DA11__GPIO3_IO11             0x190 0x560 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA11__SRC_BOOT_CFG11         0x190 0x560 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA11__EPDC_DATA03            0x190 0x560 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA12__EIM_AD12               0x194 0x564 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA12__IPU1_DI1_PIN03         0x194 0x564 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA12__IPU1_CSI1_VSYNC        0x194 0x564 0x8bc 0x2 0x1
-#define MX6DL_PAD_EIM_DA12__GPIO3_IO12             0x194 0x564 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA12__SRC_BOOT_CFG12         0x194 0x564 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA12__EPDC_DATA02            0x194 0x564 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA13__EIM_AD13               0x198 0x568 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA13__IPU1_DI1_D0_CS         0x198 0x568 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA13__GPIO3_IO13             0x198 0x568 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA13__SRC_BOOT_CFG13         0x198 0x568 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA13__EPDC_DATA13            0x198 0x568 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA14__EIM_AD14               0x19c 0x56c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA14__IPU1_DI1_D1_CS         0x19c 0x56c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA14__GPIO3_IO14             0x19c 0x56c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA14__SRC_BOOT_CFG14         0x19c 0x56c 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA14__EPDC_DATA14            0x19c 0x56c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA15__EIM_AD15               0x1a0 0x570 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA15__IPU1_DI1_PIN01         0x1a0 0x570 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA15__IPU1_DI1_PIN04         0x1a0 0x570 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA15__GPIO3_IO15             0x1a0 0x570 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA15__SRC_BOOT_CFG15         0x1a0 0x570 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA15__EPDC_DATA09            0x1a0 0x570 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA2__EIM_AD02                0x1a4 0x574 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA2__IPU1_DISP1_DATA07       0x1a4 0x574 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA2__IPU1_CSI1_DATA07        0x1a4 0x574 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA2__GPIO3_IO02              0x1a4 0x574 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA2__SRC_BOOT_CFG02          0x1a4 0x574 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA2__EPDC_BDR0               0x1a4 0x574 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA3__EIM_AD03                0x1a8 0x578 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA3__IPU1_DISP1_DATA06       0x1a8 0x578 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA3__IPU1_CSI1_DATA06        0x1a8 0x578 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA3__GPIO3_IO03              0x1a8 0x578 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA3__SRC_BOOT_CFG03          0x1a8 0x578 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA3__EPDC_BDR1               0x1a8 0x578 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA4__EIM_AD04                0x1ac 0x57c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA4__IPU1_DISP1_DATA05       0x1ac 0x57c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA4__IPU1_CSI1_DATA05        0x1ac 0x57c 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA4__GPIO3_IO04              0x1ac 0x57c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA4__SRC_BOOT_CFG04          0x1ac 0x57c 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA4__EPDC_SDCE0              0x1ac 0x57c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA5__EIM_AD05                0x1b0 0x580 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA5__IPU1_DISP1_DATA04       0x1b0 0x580 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA5__IPU1_CSI1_DATA04        0x1b0 0x580 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA5__GPIO3_IO05              0x1b0 0x580 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA5__SRC_BOOT_CFG05          0x1b0 0x580 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA5__EPDC_SDCE1              0x1b0 0x580 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA6__EIM_AD06                0x1b4 0x584 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA6__IPU1_DISP1_DATA03       0x1b4 0x584 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA6__IPU1_CSI1_DATA03        0x1b4 0x584 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA6__GPIO3_IO06              0x1b4 0x584 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA6__SRC_BOOT_CFG06          0x1b4 0x584 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA6__EPDC_SDCE2              0x1b4 0x584 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA7__EIM_AD07                0x1b8 0x588 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA7__IPU1_DISP1_DATA02       0x1b8 0x588 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA7__IPU1_CSI1_DATA02        0x1b8 0x588 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA7__GPIO3_IO07              0x1b8 0x588 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA7__SRC_BOOT_CFG07          0x1b8 0x588 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA7__EPDC_SDCE3              0x1b8 0x588 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA8__EIM_AD08                0x1bc 0x58c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA8__IPU1_DISP1_DATA01       0x1bc 0x58c 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA8__IPU1_CSI1_DATA01        0x1bc 0x58c 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA8__GPIO3_IO08              0x1bc 0x58c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA8__SRC_BOOT_CFG08          0x1bc 0x58c 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA8__EPDC_SDCE4              0x1bc 0x58c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_DA9__EIM_AD09                0x1c0 0x590 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_DA9__IPU1_DISP1_DATA00       0x1c0 0x590 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_DA9__IPU1_CSI1_DATA00        0x1c0 0x590 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_DA9__GPIO3_IO09              0x1c0 0x590 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_DA9__SRC_BOOT_CFG09          0x1c0 0x590 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_DA9__EPDC_SDCE5              0x1c0 0x590 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_EB0__EIM_EB0_B               0x1c4 0x594 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_EB0__IPU1_DISP1_DATA11       0x1c4 0x594 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_EB0__IPU1_CSI1_DATA11        0x1c4 0x594 0x88c 0x2 0x1
-#define MX6DL_PAD_EIM_EB0__CCM_PMIC_READY          0x1c4 0x594 0x7d4 0x4 0x0
-#define MX6DL_PAD_EIM_EB0__GPIO2_IO28              0x1c4 0x594 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_EB0__SRC_BOOT_CFG27          0x1c4 0x594 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_EB0__EPDC_PWR_COM            0x1c4 0x594 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_EB1__EIM_EB1_B               0x1c8 0x598 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_EB1__IPU1_DISP1_DATA10       0x1c8 0x598 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_EB1__IPU1_CSI1_DATA10        0x1c8 0x598 0x888 0x2 0x1
-#define MX6DL_PAD_EIM_EB1__GPIO2_IO29              0x1c8 0x598 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_EB1__SRC_BOOT_CFG28          0x1c8 0x598 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_EB1__EPDC_SDSHR              0x1c8 0x598 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_EB2__EIM_EB2_B               0x1cc 0x59c 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_EB2__ECSPI1_SS0              0x1cc 0x59c 0x7e4 0x1 0x2
-#define MX6DL_PAD_EIM_EB2__IPU1_CSI1_DATA19        0x1cc 0x59c 0x8ac 0x3 0x1
-#define MX6DL_PAD_EIM_EB2__HDMI_TX_DDC_SCL         0x1cc 0x59c 0x860 0x4 0x0
-#define MX6DL_PAD_EIM_EB2__GPIO2_IO30              0x1cc 0x59c 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_EB2__I2C2_SCL                0x1cc 0x59c 0x870 0x6 0x0
-#define MX6DL_PAD_EIM_EB2__SRC_BOOT_CFG30          0x1cc 0x59c 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_EB2__EPDC_DATA05             0x1cc 0x59c 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_EB3__EIM_EB3_B               0x1d0 0x5a0 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_EB3__ECSPI4_RDY              0x1d0 0x5a0 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_EB3__UART3_RTS_B             0x1d0 0x5a0 0x908 0x2 0x3
-#define MX6DL_PAD_EIM_EB3__UART3_CTS_B             0x1d0 0x5a0 0x000 0x2 0x0
-#define MX6DL_PAD_EIM_EB3__UART1_RI_B              0x1d0 0x5a0 0x000 0x3 0x0
-#define MX6DL_PAD_EIM_EB3__IPU1_CSI1_HSYNC         0x1d0 0x5a0 0x8b4 0x4 0x1
-#define MX6DL_PAD_EIM_EB3__GPIO2_IO31              0x1d0 0x5a0 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_EB3__IPU1_DI1_PIN03          0x1d0 0x5a0 0x000 0x6 0x0
-#define MX6DL_PAD_EIM_EB3__SRC_BOOT_CFG31          0x1d0 0x5a0 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_EB3__EPDC_SDCE0              0x1d0 0x5a0 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_EB3__EIM_ACLK_FREERUN        0x1d0 0x5a0 0x000 0x9 0x0
-#define MX6DL_PAD_EIM_LBA__EIM_LBA_B               0x1d4 0x5a4 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_LBA__IPU1_DI1_PIN17          0x1d4 0x5a4 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_LBA__ECSPI2_SS1              0x1d4 0x5a4 0x804 0x2 0x1
-#define MX6DL_PAD_EIM_LBA__GPIO2_IO27              0x1d4 0x5a4 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_LBA__SRC_BOOT_CFG26          0x1d4 0x5a4 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_LBA__EPDC_DATA04             0x1d4 0x5a4 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_OE__EIM_OE_B                 0x1d8 0x5a8 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_OE__IPU1_DI1_PIN07           0x1d8 0x5a8 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_OE__ECSPI2_MISO              0x1d8 0x5a8 0x7f8 0x2 0x2
-#define MX6DL_PAD_EIM_OE__GPIO2_IO25               0x1d8 0x5a8 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_OE__EPDC_PWR_IRQ             0x1d8 0x5a8 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_RW__EIM_RW                   0x1dc 0x5ac 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_RW__IPU1_DI1_PIN08           0x1dc 0x5ac 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_RW__ECSPI2_SS0               0x1dc 0x5ac 0x800 0x2 0x2
-#define MX6DL_PAD_EIM_RW__GPIO2_IO26               0x1dc 0x5ac 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_RW__SRC_BOOT_CFG29           0x1dc 0x5ac 0x000 0x7 0x0
-#define MX6DL_PAD_EIM_RW__EPDC_DATA07              0x1dc 0x5ac 0x000 0x8 0x0
-#define MX6DL_PAD_EIM_WAIT__EIM_WAIT_B             0x1e0 0x5b0 0x000 0x0 0x0
-#define MX6DL_PAD_EIM_WAIT__EIM_DTACK_B            0x1e0 0x5b0 0x000 0x1 0x0
-#define MX6DL_PAD_EIM_WAIT__GPIO5_IO00             0x1e0 0x5b0 0x000 0x5 0x0
-#define MX6DL_PAD_EIM_WAIT__SRC_BOOT_CFG25         0x1e0 0x5b0 0x000 0x7 0x0
-#define MX6DL_PAD_ENET_CRS_DV__ENET_RX_EN          0x1e4 0x5b4 0x828 0x1 0x0
-#define MX6DL_PAD_ENET_CRS_DV__ESAI_TX_CLK         0x1e4 0x5b4 0x840 0x2 0x0
-#define MX6DL_PAD_ENET_CRS_DV__SPDIF_EXT_CLK       0x1e4 0x5b4 0x8f4 0x3 0x0
-#define MX6DL_PAD_ENET_CRS_DV__GPIO1_IO25          0x1e4 0x5b4 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_MDC__MLB_DATA               0x1e8 0x5b8 0x8e0 0x0 0x0
-#define MX6DL_PAD_ENET_MDC__ENET_MDC               0x1e8 0x5b8 0x000 0x1 0x0
-#define MX6DL_PAD_ENET_MDC__ESAI_TX5_RX0           0x1e8 0x5b8 0x858 0x2 0x0
-#define MX6DL_PAD_ENET_MDC__ENET_1588_EVENT1_IN    0x1e8 0x5b8 0x000 0x4 0x0
-#define MX6DL_PAD_ENET_MDC__GPIO1_IO31             0x1e8 0x5b8 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_MDIO__ENET_MDIO             0x1ec 0x5bc 0x810 0x1 0x0
-#define MX6DL_PAD_ENET_MDIO__ESAI_RX_CLK           0x1ec 0x5bc 0x83c 0x2 0x0
-#define MX6DL_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT  0x1ec 0x5bc 0x000 0x4 0x0
-#define MX6DL_PAD_ENET_MDIO__GPIO1_IO22            0x1ec 0x5bc 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_MDIO__SPDIF_LOCK            0x1ec 0x5bc 0x000 0x6 0x0
-#define MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK        0x1f0 0x5c0 0x000 0x1 0x0
-#define MX6DL_PAD_ENET_REF_CLK__ESAI_RX_FS         0x1f0 0x5c0 0x82c 0x2 0x0
-#define MX6DL_PAD_ENET_REF_CLK__GPIO1_IO23         0x1f0 0x5c0 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_REF_CLK__SPDIF_SR_CLK       0x1f0 0x5c0 0x000 0x6 0x0
-#define MX6DL_PAD_ENET_RX_ER__USB_OTG_ID           0x1f4 0x5c4 0x790 0x0 0x0
-#define MX6DL_PAD_ENET_RX_ER__ENET_RX_ER           0x1f4 0x5c4 0x000 0x1 0x0
-#define MX6DL_PAD_ENET_RX_ER__ESAI_RX_HF_CLK       0x1f4 0x5c4 0x834 0x2 0x0
-#define MX6DL_PAD_ENET_RX_ER__SPDIF_IN             0x1f4 0x5c4 0x8f0 0x3 0x1
-#define MX6DL_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT 0x1f4 0x5c4 0x000 0x4 0x0
-#define MX6DL_PAD_ENET_RX_ER__GPIO1_IO24           0x1f4 0x5c4 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_RXD0__ENET_RX_DATA0         0x1f8 0x5c8 0x818 0x1 0x0
-#define MX6DL_PAD_ENET_RXD0__ESAI_TX_HF_CLK        0x1f8 0x5c8 0x838 0x2 0x0
-#define MX6DL_PAD_ENET_RXD0__SPDIF_OUT             0x1f8 0x5c8 0x000 0x3 0x0
-#define MX6DL_PAD_ENET_RXD0__GPIO1_IO27            0x1f8 0x5c8 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_RXD1__MLB_SIG               0x1fc 0x5cc 0x8e4 0x0 0x0
-#define MX6DL_PAD_ENET_RXD1__ENET_RX_DATA1         0x1fc 0x5cc 0x81c 0x1 0x0
-#define MX6DL_PAD_ENET_RXD1__ESAI_TX_FS            0x1fc 0x5cc 0x830 0x2 0x0
-#define MX6DL_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT  0x1fc 0x5cc 0x000 0x4 0x0
-#define MX6DL_PAD_ENET_RXD1__GPIO1_IO26            0x1fc 0x5cc 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_TX_EN__ENET_TX_EN           0x200 0x5d0 0x000 0x1 0x0
-#define MX6DL_PAD_ENET_TX_EN__ESAI_TX3_RX2         0x200 0x5d0 0x850 0x2 0x0
-#define MX6DL_PAD_ENET_TX_EN__GPIO1_IO28           0x200 0x5d0 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_TX_EN__I2C4_SCL             0x200 0x5d0 0x880 0x9 0x0
-#define MX6DL_PAD_ENET_TXD0__ENET_TX_DATA0         0x204 0x5d4 0x000 0x1 0x0
-#define MX6DL_PAD_ENET_TXD0__ESAI_TX4_RX1          0x204 0x5d4 0x854 0x2 0x0
-#define MX6DL_PAD_ENET_TXD0__GPIO1_IO30            0x204 0x5d4 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_TXD1__MLB_CLK               0x208 0x5d8 0x8dc 0x0 0x0
-#define MX6DL_PAD_ENET_TXD1__ENET_TX_DATA1         0x208 0x5d8 0x000 0x1 0x0
-#define MX6DL_PAD_ENET_TXD1__ESAI_TX2_RX3          0x208 0x5d8 0x84c 0x2 0x0
-#define MX6DL_PAD_ENET_TXD1__ENET_1588_EVENT0_IN   0x208 0x5d8 0x000 0x4 0x0
-#define MX6DL_PAD_ENET_TXD1__GPIO1_IO29            0x208 0x5d8 0x000 0x5 0x0
-#define MX6DL_PAD_ENET_TXD1__I2C4_SDA              0x208 0x5d8 0x884 0x9 0x0
-#define MX6DL_PAD_GPIO_0__CCM_CLKO1                0x20c 0x5dc 0x000 0x0 0x0
-#define MX6DL_PAD_GPIO_0__KEY_COL5                 0x20c 0x5dc 0x8c0 0x2 0x1
-#define MX6DL_PAD_GPIO_0__ASRC_EXT_CLK             0x20c 0x5dc 0x794 0x3 0x0
-#define MX6DL_PAD_GPIO_0__EPIT1_OUT                0x20c 0x5dc 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_0__GPIO1_IO00               0x20c 0x5dc 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_0__USB_H1_PWR               0x20c 0x5dc 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_0__SNVS_VIO_5               0x20c 0x5dc 0x000 0x7 0x0
-#define MX6DL_PAD_GPIO_1__ESAI_RX_CLK              0x210 0x5e0 0x83c 0x0 0x1
-#define MX6DL_PAD_GPIO_1__WDOG2_B                  0x210 0x5e0 0x000 0x1 0x0
-#define MX6DL_PAD_GPIO_1__KEY_ROW5                 0x210 0x5e0 0x8cc 0x2 0x1
-#define MX6DL_PAD_GPIO_1__USB_OTG_ID               0x210 0x5e0 0x790 0x3 0x1
-#define MX6DL_PAD_GPIO_1__PWM2_OUT                 0x210 0x5e0 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_1__GPIO1_IO01               0x210 0x5e0 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_1__SD1_CD_B                 0x210 0x5e0 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_16__ESAI_TX3_RX2            0x214 0x5e4 0x850 0x0 0x1
-#define MX6DL_PAD_GPIO_16__ENET_1588_EVENT2_IN     0x214 0x5e4 0x000 0x1 0x0
-#define MX6DL_PAD_GPIO_16__ENET_REF_CLK            0x214 0x5e4 0x80c 0x2 0x0
-#define MX6DL_PAD_GPIO_16__SD1_LCTL                0x214 0x5e4 0x000 0x3 0x0
-#define MX6DL_PAD_GPIO_16__SPDIF_IN                0x214 0x5e4 0x8f0 0x4 0x2
-#define MX6DL_PAD_GPIO_16__GPIO7_IO11              0x214 0x5e4 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_16__I2C3_SDA                0x214 0x5e4 0x87c 0x6 0x1
-#define MX6DL_PAD_GPIO_16__JTAG_DE_B               0x214 0x5e4 0x000 0x7 0x0
-#define MX6DL_PAD_GPIO_17__ESAI_TX0                0x218 0x5e8 0x844 0x0 0x0
-#define MX6DL_PAD_GPIO_17__ENET_1588_EVENT3_IN     0x218 0x5e8 0x000 0x1 0x0
-#define MX6DL_PAD_GPIO_17__CCM_PMIC_READY          0x218 0x5e8 0x7d4 0x2 0x1
-#define MX6DL_PAD_GPIO_17__SDMA_EXT_EVENT0         0x218 0x5e8 0x8e8 0x3 0x1
-#define MX6DL_PAD_GPIO_17__SPDIF_OUT               0x218 0x5e8 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_17__GPIO7_IO12              0x218 0x5e8 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_18__ESAI_TX1                0x21c 0x5ec 0x848 0x0 0x0
-#define MX6DL_PAD_GPIO_18__ENET_RX_CLK             0x21c 0x5ec 0x814 0x1 0x0
-#define MX6DL_PAD_GPIO_18__SD3_VSELECT             0x21c 0x5ec 0x000 0x2 0x0
-#define MX6DL_PAD_GPIO_18__SDMA_EXT_EVENT1         0x21c 0x5ec 0x8ec 0x3 0x1
-#define MX6DL_PAD_GPIO_18__ASRC_EXT_CLK            0x21c 0x5ec 0x794 0x4 0x1
-#define MX6DL_PAD_GPIO_18__GPIO7_IO13              0x21c 0x5ec 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_18__SNVS_VIO_5_CTL          0x21c 0x5ec 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_19__KEY_COL5                0x220 0x5f0 0x8c0 0x0 0x2
-#define MX6DL_PAD_GPIO_19__ENET_1588_EVENT0_OUT    0x220 0x5f0 0x000 0x1 0x0
-#define MX6DL_PAD_GPIO_19__SPDIF_OUT               0x220 0x5f0 0x000 0x2 0x0
-#define MX6DL_PAD_GPIO_19__CCM_CLKO1               0x220 0x5f0 0x000 0x3 0x0
-#define MX6DL_PAD_GPIO_19__ECSPI1_RDY              0x220 0x5f0 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_19__GPIO4_IO05              0x220 0x5f0 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_19__ENET_TX_ER              0x220 0x5f0 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_2__ESAI_TX_FS               0x224 0x5f4 0x830 0x0 0x1
-#define MX6DL_PAD_GPIO_2__KEY_ROW6                 0x224 0x5f4 0x8d0 0x2 0x1
-#define MX6DL_PAD_GPIO_2__GPIO1_IO02               0x224 0x5f4 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_2__SD2_WP                   0x224 0x5f4 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_2__MLB_DATA                 0x224 0x5f4 0x8e0 0x7 0x1
-#define MX6DL_PAD_GPIO_3__ESAI_RX_HF_CLK           0x228 0x5f8 0x834 0x0 0x1
-#define MX6DL_PAD_GPIO_3__I2C3_SCL                 0x228 0x5f8 0x878 0x2 0x1
-#define MX6DL_PAD_GPIO_3__XTALOSC_REF_CLK_24M      0x228 0x5f8 0x000 0x3 0x0
-#define MX6DL_PAD_GPIO_3__CCM_CLKO2                0x228 0x5f8 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_3__GPIO1_IO03               0x228 0x5f8 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_3__USB_H1_OC                0x228 0x5f8 0x924 0x6 0x1
-#define MX6DL_PAD_GPIO_3__MLB_CLK                  0x228 0x5f8 0x8dc 0x7 0x1
-#define MX6DL_PAD_GPIO_4__ESAI_TX_HF_CLK           0x22c 0x5fc 0x838 0x0 0x1
-#define MX6DL_PAD_GPIO_4__KEY_COL7                 0x22c 0x5fc 0x8c8 0x2 0x1
-#define MX6DL_PAD_GPIO_4__GPIO1_IO04               0x22c 0x5fc 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_4__SD2_CD_B                 0x22c 0x5fc 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_5__ESAI_TX2_RX3             0x230 0x600 0x84c 0x0 0x1
-#define MX6DL_PAD_GPIO_5__KEY_ROW7                 0x230 0x600 0x8d4 0x2 0x1
-#define MX6DL_PAD_GPIO_5__CCM_CLKO1                0x230 0x600 0x000 0x3 0x0
-#define MX6DL_PAD_GPIO_5__GPIO1_IO05               0x230 0x600 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_5__I2C3_SCL                 0x230 0x600 0x878 0x6 0x2
-#define MX6DL_PAD_GPIO_5__ARM_EVENTI               0x230 0x600 0x000 0x7 0x0
-#define MX6DL_PAD_GPIO_6__ESAI_TX_CLK              0x234 0x604 0x840 0x0 0x1
-#define MX6DL_PAD_GPIO_6__I2C3_SDA                 0x234 0x604 0x87c 0x2 0x2
-#define MX6DL_PAD_GPIO_6__GPIO1_IO06               0x234 0x604 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_6__SD2_LCTL                 0x234 0x604 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_6__MLB_SIG                  0x234 0x604 0x8e4 0x7 0x1
-#define MX6DL_PAD_GPIO_7__ESAI_TX4_RX1             0x238 0x608 0x854 0x0 0x1
-#define MX6DL_PAD_GPIO_7__EPIT1_OUT                0x238 0x608 0x000 0x2 0x0
-#define MX6DL_PAD_GPIO_7__FLEXCAN1_TX              0x238 0x608 0x000 0x3 0x0
-#define MX6DL_PAD_GPIO_7__UART2_TX_DATA            0x238 0x608 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_7__UART2_RX_DATA            0x238 0x608 0x904 0x4 0x2
-#define MX6DL_PAD_GPIO_7__GPIO1_IO07               0x238 0x608 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_7__SPDIF_LOCK               0x238 0x608 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_7__USB_OTG_HOST_MODE        0x238 0x608 0x000 0x7 0x0
-#define MX6DL_PAD_GPIO_7__I2C4_SCL                 0x238 0x608 0x880 0x8 0x1
-#define MX6DL_PAD_GPIO_8__ESAI_TX5_RX0             0x23c 0x60c 0x858 0x0 0x1
-#define MX6DL_PAD_GPIO_8__XTALOSC_REF_CLK_32K      0x23c 0x60c 0x000 0x1 0x0
-#define MX6DL_PAD_GPIO_8__EPIT2_OUT                0x23c 0x60c 0x000 0x2 0x0
-#define MX6DL_PAD_GPIO_8__FLEXCAN1_RX              0x23c 0x60c 0x7c8 0x3 0x0
-#define MX6DL_PAD_GPIO_8__UART2_RX_DATA            0x23c 0x60c 0x904 0x4 0x3
-#define MX6DL_PAD_GPIO_8__UART2_TX_DATA            0x23c 0x60c 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_8__GPIO1_IO08               0x23c 0x60c 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_8__SPDIF_SR_CLK             0x23c 0x60c 0x000 0x6 0x0
-#define MX6DL_PAD_GPIO_8__USB_OTG_PWR_CTL_WAKE     0x23c 0x60c 0x000 0x7 0x0
-#define MX6DL_PAD_GPIO_8__I2C4_SDA                 0x23c 0x60c 0x884 0x8 0x1
-#define MX6DL_PAD_GPIO_9__ESAI_RX_FS               0x240 0x610 0x82c 0x0 0x1
-#define MX6DL_PAD_GPIO_9__WDOG1_B                  0x240 0x610 0x000 0x1 0x0
-#define MX6DL_PAD_GPIO_9__KEY_COL6                 0x240 0x610 0x8c4 0x2 0x1
-#define MX6DL_PAD_GPIO_9__CCM_REF_EN_B             0x240 0x610 0x000 0x3 0x0
-#define MX6DL_PAD_GPIO_9__PWM1_OUT                 0x240 0x610 0x000 0x4 0x0
-#define MX6DL_PAD_GPIO_9__GPIO1_IO09               0x240 0x610 0x000 0x5 0x0
-#define MX6DL_PAD_GPIO_9__SD1_WP                   0x240 0x610 0x92c 0x6 0x1
-#define MX6DL_PAD_KEY_COL0__ECSPI1_SCLK            0x244 0x62c 0x7d8 0x0 0x3
-#define MX6DL_PAD_KEY_COL0__ENET_RX_DATA3          0x244 0x62c 0x824 0x1 0x0
-#define MX6DL_PAD_KEY_COL0__AUD5_TXC               0x244 0x62c 0x7c0 0x2 0x1
-#define MX6DL_PAD_KEY_COL0__KEY_COL0               0x244 0x62c 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_COL0__UART4_TX_DATA          0x244 0x62c 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_COL0__UART4_RX_DATA          0x244 0x62c 0x914 0x4 0x2
-#define MX6DL_PAD_KEY_COL0__GPIO4_IO06             0x244 0x62c 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_COL0__DCIC1_OUT              0x244 0x62c 0x000 0x6 0x0
-#define MX6DL_PAD_KEY_COL1__ECSPI1_MISO            0x248 0x630 0x7dc 0x0 0x3
-#define MX6DL_PAD_KEY_COL1__ENET_MDIO              0x248 0x630 0x810 0x1 0x1
-#define MX6DL_PAD_KEY_COL1__AUD5_TXFS              0x248 0x630 0x7c4 0x2 0x1
-#define MX6DL_PAD_KEY_COL1__KEY_COL1               0x248 0x630 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_COL1__UART5_TX_DATA          0x248 0x630 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_COL1__UART5_RX_DATA          0x248 0x630 0x91c 0x4 0x2
-#define MX6DL_PAD_KEY_COL1__GPIO4_IO08             0x248 0x630 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_COL1__SD1_VSELECT            0x248 0x630 0x000 0x6 0x0
-#define MX6DL_PAD_KEY_COL2__ECSPI1_SS1             0x24c 0x634 0x7e8 0x0 0x2
-#define MX6DL_PAD_KEY_COL2__ENET_RX_DATA2          0x24c 0x634 0x820 0x1 0x0
-#define MX6DL_PAD_KEY_COL2__FLEXCAN1_TX            0x24c 0x634 0x000 0x2 0x0
-#define MX6DL_PAD_KEY_COL2__KEY_COL2               0x24c 0x634 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_COL2__ENET_MDC               0x24c 0x634 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_COL2__GPIO4_IO10             0x24c 0x634 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_COL2__USB_H1_PWR_CTL_WAKE    0x24c 0x634 0x000 0x6 0x0
-#define MX6DL_PAD_KEY_COL3__ECSPI1_SS3             0x250 0x638 0x7f0 0x0 0x1
-#define MX6DL_PAD_KEY_COL3__ENET_CRS               0x250 0x638 0x000 0x1 0x0
-#define MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL        0x250 0x638 0x860 0x2 0x1
-#define MX6DL_PAD_KEY_COL3__KEY_COL3               0x250 0x638 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_COL3__I2C2_SCL               0x250 0x638 0x870 0x4 0x1
-#define MX6DL_PAD_KEY_COL3__GPIO4_IO12             0x250 0x638 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_COL3__SPDIF_IN               0x250 0x638 0x8f0 0x6 0x3
-#define MX6DL_PAD_KEY_COL4__FLEXCAN2_TX            0x254 0x63c 0x000 0x0 0x0
-#define MX6DL_PAD_KEY_COL4__IPU1_SISG4             0x254 0x63c 0x000 0x1 0x0
-#define MX6DL_PAD_KEY_COL4__USB_OTG_OC             0x254 0x63c 0x920 0x2 0x1
-#define MX6DL_PAD_KEY_COL4__KEY_COL4               0x254 0x63c 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_COL4__UART5_RTS_B            0x254 0x63c 0x918 0x4 0x2
-#define MX6DL_PAD_KEY_COL4__UART5_CTS_B            0x254 0x63c 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_COL4__GPIO4_IO14             0x254 0x63c 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_ROW0__ECSPI1_MOSI            0x258 0x640 0x7e0 0x0 0x3
-#define MX6DL_PAD_KEY_ROW0__ENET_TX_DATA3          0x258 0x640 0x000 0x1 0x0
-#define MX6DL_PAD_KEY_ROW0__AUD5_TXD               0x258 0x640 0x7b4 0x2 0x1
-#define MX6DL_PAD_KEY_ROW0__KEY_ROW0               0x258 0x640 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_ROW0__UART4_RX_DATA          0x258 0x640 0x914 0x4 0x3
-#define MX6DL_PAD_KEY_ROW0__UART4_TX_DATA          0x258 0x640 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_ROW0__GPIO4_IO07             0x258 0x640 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_ROW0__DCIC2_OUT              0x258 0x640 0x000 0x6 0x0
-#define MX6DL_PAD_KEY_ROW1__ECSPI1_SS0             0x25c 0x644 0x7e4 0x0 0x3
-#define MX6DL_PAD_KEY_ROW1__ENET_COL               0x25c 0x644 0x000 0x1 0x0
-#define MX6DL_PAD_KEY_ROW1__AUD5_RXD               0x25c 0x644 0x7b0 0x2 0x1
-#define MX6DL_PAD_KEY_ROW1__KEY_ROW1               0x25c 0x644 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_ROW1__UART5_RX_DATA          0x25c 0x644 0x91c 0x4 0x3
-#define MX6DL_PAD_KEY_ROW1__UART5_TX_DATA          0x25c 0x644 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_ROW1__GPIO4_IO09             0x25c 0x644 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_ROW1__SD2_VSELECT            0x25c 0x644 0x000 0x6 0x0
-#define MX6DL_PAD_KEY_ROW2__ECSPI1_SS2             0x260 0x648 0x7ec 0x0 0x1
-#define MX6DL_PAD_KEY_ROW2__ENET_TX_DATA2          0x260 0x648 0x000 0x1 0x0
-#define MX6DL_PAD_KEY_ROW2__FLEXCAN1_RX            0x260 0x648 0x7c8 0x2 0x1
-#define MX6DL_PAD_KEY_ROW2__KEY_ROW2               0x260 0x648 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_ROW2__SD2_VSELECT            0x260 0x648 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_ROW2__GPIO4_IO11             0x260 0x648 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE       0x260 0x648 0x85c 0x6 0x1
-#define MX6DL_PAD_KEY_ROW3__ASRC_EXT_CLK           0x264 0x64c 0x794 0x1 0x2
-#define MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA        0x264 0x64c 0x864 0x2 0x1
-#define MX6DL_PAD_KEY_ROW3__KEY_ROW3               0x264 0x64c 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_ROW3__I2C2_SDA               0x264 0x64c 0x874 0x4 0x1
-#define MX6DL_PAD_KEY_ROW3__GPIO4_IO13             0x264 0x64c 0x000 0x5 0x0
-#define MX6DL_PAD_KEY_ROW3__SD1_VSELECT            0x264 0x64c 0x000 0x6 0x0
-#define MX6DL_PAD_KEY_ROW4__FLEXCAN2_RX            0x268 0x650 0x7cc 0x0 0x0
-#define MX6DL_PAD_KEY_ROW4__IPU1_SISG5             0x268 0x650 0x000 0x1 0x0
-#define MX6DL_PAD_KEY_ROW4__USB_OTG_PWR            0x268 0x650 0x000 0x2 0x0
-#define MX6DL_PAD_KEY_ROW4__KEY_ROW4               0x268 0x650 0x000 0x3 0x0
-#define MX6DL_PAD_KEY_ROW4__UART5_CTS_B            0x268 0x650 0x000 0x4 0x0
-#define MX6DL_PAD_KEY_ROW4__UART5_RTS_B            0x268 0x650 0x918 0x4 0x3
-#define MX6DL_PAD_KEY_ROW4__GPIO4_IO15             0x268 0x650 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_ALE__NAND_ALE              0x26c 0x654 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_ALE__SD4_RESET             0x26c 0x654 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_ALE__GPIO6_IO08            0x26c 0x654 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_CLE__NAND_CLE              0x270 0x658 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_CLE__GPIO6_IO07            0x270 0x658 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_CS0__NAND_CE0_B            0x274 0x65c 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_CS0__GPIO6_IO11            0x274 0x65c 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_CS1__NAND_CE1_B            0x278 0x660 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_CS1__SD4_VSELECT           0x278 0x660 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_CS1__SD3_VSELECT           0x278 0x660 0x000 0x2 0x0
-#define MX6DL_PAD_NANDF_CS1__GPIO6_IO14            0x278 0x660 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_CS2__NAND_CE2_B            0x27c 0x664 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_CS2__IPU1_SISG0            0x27c 0x664 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_CS2__ESAI_TX0              0x27c 0x664 0x844 0x2 0x1
-#define MX6DL_PAD_NANDF_CS2__EIM_CRE               0x27c 0x664 0x000 0x3 0x0
-#define MX6DL_PAD_NANDF_CS2__CCM_CLKO2             0x27c 0x664 0x000 0x4 0x0
-#define MX6DL_PAD_NANDF_CS2__GPIO6_IO15            0x27c 0x664 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_CS3__NAND_CE3_B            0x280 0x668 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_CS3__IPU1_SISG1            0x280 0x668 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_CS3__ESAI_TX1              0x280 0x668 0x848 0x2 0x1
-#define MX6DL_PAD_NANDF_CS3__EIM_ADDR26            0x280 0x668 0x000 0x3 0x0
-#define MX6DL_PAD_NANDF_CS3__GPIO6_IO16            0x280 0x668 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_CS3__I2C4_SDA              0x280 0x668 0x884 0x9 0x2
-#define MX6DL_PAD_NANDF_D0__NAND_DATA00            0x284 0x66c 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D0__SD1_DATA4              0x284 0x66c 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D0__GPIO2_IO00             0x284 0x66c 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D1__NAND_DATA01            0x288 0x670 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D1__SD1_DATA5              0x288 0x670 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D1__GPIO2_IO01             0x288 0x670 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D2__NAND_DATA02            0x28c 0x674 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D2__SD1_DATA6              0x28c 0x674 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D2__GPIO2_IO02             0x28c 0x674 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D3__NAND_DATA03            0x290 0x678 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D3__SD1_DATA7              0x290 0x678 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D3__GPIO2_IO03             0x290 0x678 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D4__NAND_DATA04            0x294 0x67c 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D4__SD2_DATA4              0x294 0x67c 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D4__GPIO2_IO04             0x294 0x67c 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D5__NAND_DATA05            0x298 0x680 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D5__SD2_DATA5              0x298 0x680 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D5__GPIO2_IO05             0x298 0x680 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D6__NAND_DATA06            0x29c 0x684 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D6__SD2_DATA6              0x29c 0x684 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D6__GPIO2_IO06             0x29c 0x684 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_D7__NAND_DATA07            0x2a0 0x688 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_D7__SD2_DATA7              0x2a0 0x688 0x000 0x1 0x0
-#define MX6DL_PAD_NANDF_D7__GPIO2_IO07             0x2a0 0x688 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_RB0__NAND_READY_B          0x2a4 0x68c 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_RB0__GPIO6_IO10            0x2a4 0x68c 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_WP_B__NAND_WP_B            0x2a8 0x690 0x000 0x0 0x0
-#define MX6DL_PAD_NANDF_WP_B__GPIO6_IO09           0x2a8 0x690 0x000 0x5 0x0
-#define MX6DL_PAD_NANDF_WP_B__I2C4_SCL             0x2a8 0x690 0x880 0x9 0x2
-#define MX6DL_PAD_RGMII_RD0__HSI_RX_READY          0x2ac 0x694 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_RD0__RGMII_RD0             0x2ac 0x694 0x818 0x1 0x1
-#define MX6DL_PAD_RGMII_RD0__GPIO6_IO25            0x2ac 0x694 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_RD1__HSI_TX_FLAG           0x2b0 0x698 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_RD1__RGMII_RD1             0x2b0 0x698 0x81c 0x1 0x1
-#define MX6DL_PAD_RGMII_RD1__GPIO6_IO27            0x2b0 0x698 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_RD2__HSI_TX_DATA           0x2b4 0x69c 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_RD2__RGMII_RD2             0x2b4 0x69c 0x820 0x1 0x1
-#define MX6DL_PAD_RGMII_RD2__GPIO6_IO28            0x2b4 0x69c 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_RD3__HSI_TX_WAKE           0x2b8 0x6a0 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_RD3__RGMII_RD3             0x2b8 0x6a0 0x824 0x1 0x1
-#define MX6DL_PAD_RGMII_RD3__GPIO6_IO29            0x2b8 0x6a0 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_RX_CTL__USB_H3_DATA        0x2bc 0x6a4 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_RX_CTL__RGMII_RX_CTL       0x2bc 0x6a4 0x828 0x1 0x1
-#define MX6DL_PAD_RGMII_RX_CTL__GPIO6_IO24         0x2bc 0x6a4 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_RXC__USB_H3_STROBE         0x2c0 0x6a8 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_RXC__RGMII_RXC             0x2c0 0x6a8 0x814 0x1 0x1
-#define MX6DL_PAD_RGMII_RXC__GPIO6_IO30            0x2c0 0x6a8 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TD0__HSI_TX_READY          0x2c4 0x6ac 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_TD0__RGMII_TD0             0x2c4 0x6ac 0x000 0x1 0x0
-#define MX6DL_PAD_RGMII_TD0__GPIO6_IO20            0x2c4 0x6ac 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TD1__HSI_RX_FLAG           0x2c8 0x6b0 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_TD1__RGMII_TD1             0x2c8 0x6b0 0x000 0x1 0x0
-#define MX6DL_PAD_RGMII_TD1__GPIO6_IO21            0x2c8 0x6b0 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TD2__HSI_RX_DATA           0x2cc 0x6b4 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_TD2__RGMII_TD2             0x2cc 0x6b4 0x000 0x1 0x0
-#define MX6DL_PAD_RGMII_TD2__GPIO6_IO22            0x2cc 0x6b4 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TD3__HSI_RX_WAKE           0x2d0 0x6b8 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_TD3__RGMII_TD3             0x2d0 0x6b8 0x000 0x1 0x0
-#define MX6DL_PAD_RGMII_TD3__GPIO6_IO23            0x2d0 0x6b8 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TX_CTL__USB_H2_STROBE      0x2d4 0x6bc 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_TX_CTL__RGMII_TX_CTL       0x2d4 0x6bc 0x000 0x1 0x0
-#define MX6DL_PAD_RGMII_TX_CTL__GPIO6_IO26         0x2d4 0x6bc 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TX_CTL__ENET_REF_CLK       0x2d4 0x6bc 0x80c 0x7 0x1
-#define MX6DL_PAD_RGMII_TXC__USB_H2_DATA           0x2d8 0x6c0 0x000 0x0 0x0
-#define MX6DL_PAD_RGMII_TXC__RGMII_TXC             0x2d8 0x6c0 0x000 0x1 0x0
-#define MX6DL_PAD_RGMII_TXC__SPDIF_EXT_CLK         0x2d8 0x6c0 0x8f4 0x2 0x1
-#define MX6DL_PAD_RGMII_TXC__GPIO6_IO19            0x2d8 0x6c0 0x000 0x5 0x0
-#define MX6DL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x2d8 0x6c0 0x000 0x7 0x0
-#define MX6DL_PAD_SD1_CLK__SD1_CLK                 0x2dc 0x6c4 0x928 0x0 0x1
-#define MX6DL_PAD_SD1_CLK__GPT_CLKIN               0x2dc 0x6c4 0x000 0x3 0x0
-#define MX6DL_PAD_SD1_CLK__GPIO1_IO20              0x2dc 0x6c4 0x000 0x5 0x0
-#define MX6DL_PAD_SD1_CMD__SD1_CMD                 0x2e0 0x6c8 0x000 0x0 0x0
-#define MX6DL_PAD_SD1_CMD__PWM4_OUT                0x2e0 0x6c8 0x000 0x2 0x0
-#define MX6DL_PAD_SD1_CMD__GPT_COMPARE1            0x2e0 0x6c8 0x000 0x3 0x0
-#define MX6DL_PAD_SD1_CMD__GPIO1_IO18              0x2e0 0x6c8 0x000 0x5 0x0
-#define MX6DL_PAD_SD1_DAT0__SD1_DATA0              0x2e4 0x6cc 0x000 0x0 0x0
-#define MX6DL_PAD_SD1_DAT0__GPT_CAPTURE1           0x2e4 0x6cc 0x000 0x3 0x0
-#define MX6DL_PAD_SD1_DAT0__GPIO1_IO16             0x2e4 0x6cc 0x000 0x5 0x0
-#define MX6DL_PAD_SD1_DAT1__SD1_DATA1              0x2e8 0x6d0 0x000 0x0 0x0
-#define MX6DL_PAD_SD1_DAT1__PWM3_OUT               0x2e8 0x6d0 0x000 0x2 0x0
-#define MX6DL_PAD_SD1_DAT1__GPT_CAPTURE2           0x2e8 0x6d0 0x000 0x3 0x0
-#define MX6DL_PAD_SD1_DAT1__GPIO1_IO17             0x2e8 0x6d0 0x000 0x5 0x0
-#define MX6DL_PAD_SD1_DAT2__SD1_DATA2              0x2ec 0x6d4 0x000 0x0 0x0
-#define MX6DL_PAD_SD1_DAT2__GPT_COMPARE2           0x2ec 0x6d4 0x000 0x2 0x0
-#define MX6DL_PAD_SD1_DAT2__PWM2_OUT               0x2ec 0x6d4 0x000 0x3 0x0
-#define MX6DL_PAD_SD1_DAT2__WDOG1_B                0x2ec 0x6d4 0x000 0x4 0x0
-#define MX6DL_PAD_SD1_DAT2__GPIO1_IO19             0x2ec 0x6d4 0x000 0x5 0x0
-#define MX6DL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x2ec 0x6d4 0x000 0x6 0x0
-#define MX6DL_PAD_SD1_DAT3__SD1_DATA3              0x2f0 0x6d8 0x000 0x0 0x0
-#define MX6DL_PAD_SD1_DAT3__GPT_COMPARE3           0x2f0 0x6d8 0x000 0x2 0x0
-#define MX6DL_PAD_SD1_DAT3__PWM1_OUT               0x2f0 0x6d8 0x000 0x3 0x0
-#define MX6DL_PAD_SD1_DAT3__WDOG2_B                0x2f0 0x6d8 0x000 0x4 0x0
-#define MX6DL_PAD_SD1_DAT3__GPIO1_IO21             0x2f0 0x6d8 0x000 0x5 0x0
-#define MX6DL_PAD_SD1_DAT3__WDOG2_RESET_B_DEB      0x2f0 0x6d8 0x000 0x6 0x0
-#define MX6DL_PAD_SD2_CLK__SD2_CLK                 0x2f4 0x6dc 0x930 0x0 0x1
-#define MX6DL_PAD_SD2_CLK__KEY_COL5                0x2f4 0x6dc 0x8c0 0x2 0x3
-#define MX6DL_PAD_SD2_CLK__AUD4_RXFS               0x2f4 0x6dc 0x7a4 0x3 0x1
-#define MX6DL_PAD_SD2_CLK__GPIO1_IO10              0x2f4 0x6dc 0x000 0x5 0x0
-#define MX6DL_PAD_SD2_CMD__SD2_CMD                 0x2f8 0x6e0 0x000 0x0 0x0
-#define MX6DL_PAD_SD2_CMD__KEY_ROW5                0x2f8 0x6e0 0x8cc 0x2 0x2
-#define MX6DL_PAD_SD2_CMD__AUD4_RXC                0x2f8 0x6e0 0x7a0 0x3 0x1
-#define MX6DL_PAD_SD2_CMD__GPIO1_IO11              0x2f8 0x6e0 0x000 0x5 0x0
-#define MX6DL_PAD_SD2_DAT0__SD2_DATA0              0x2fc 0x6e4 0x000 0x0 0x0
-#define MX6DL_PAD_SD2_DAT0__AUD4_RXD               0x2fc 0x6e4 0x798 0x3 0x1
-#define MX6DL_PAD_SD2_DAT0__KEY_ROW7               0x2fc 0x6e4 0x8d4 0x4 0x2
-#define MX6DL_PAD_SD2_DAT0__GPIO1_IO15             0x2fc 0x6e4 0x000 0x5 0x0
-#define MX6DL_PAD_SD2_DAT0__DCIC2_OUT              0x2fc 0x6e4 0x000 0x6 0x0
-#define MX6DL_PAD_SD2_DAT1__SD2_DATA1              0x300 0x6e8 0x000 0x0 0x0
-#define MX6DL_PAD_SD2_DAT1__EIM_CS2_B              0x300 0x6e8 0x000 0x2 0x0
-#define MX6DL_PAD_SD2_DAT1__AUD4_TXFS              0x300 0x6e8 0x7ac 0x3 0x1
-#define MX6DL_PAD_SD2_DAT1__KEY_COL7               0x300 0x6e8 0x8c8 0x4 0x2
-#define MX6DL_PAD_SD2_DAT1__GPIO1_IO14             0x300 0x6e8 0x000 0x5 0x0
-#define MX6DL_PAD_SD2_DAT2__SD2_DATA2              0x304 0x6ec 0x000 0x0 0x0
-#define MX6DL_PAD_SD2_DAT2__EIM_CS3_B              0x304 0x6ec 0x000 0x2 0x0
-#define MX6DL_PAD_SD2_DAT2__AUD4_TXD               0x304 0x6ec 0x79c 0x3 0x1
-#define MX6DL_PAD_SD2_DAT2__KEY_ROW6               0x304 0x6ec 0x8d0 0x4 0x2
-#define MX6DL_PAD_SD2_DAT2__GPIO1_IO13             0x304 0x6ec 0x000 0x5 0x0
-#define MX6DL_PAD_SD2_DAT3__SD2_DATA3              0x308 0x6f0 0x000 0x0 0x0
-#define MX6DL_PAD_SD2_DAT3__KEY_COL6               0x308 0x6f0 0x8c4 0x2 0x2
-#define MX6DL_PAD_SD2_DAT3__AUD4_TXC               0x308 0x6f0 0x7a8 0x3 0x1
-#define MX6DL_PAD_SD2_DAT3__GPIO1_IO12             0x308 0x6f0 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_CLK__SD3_CLK                 0x30c 0x6f4 0x934 0x0 0x1
-#define MX6DL_PAD_SD3_CLK__UART2_RTS_B             0x30c 0x6f4 0x900 0x1 0x2
-#define MX6DL_PAD_SD3_CLK__UART2_CTS_B             0x30c 0x6f4 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_CLK__FLEXCAN1_RX             0x30c 0x6f4 0x7c8 0x2 0x2
-#define MX6DL_PAD_SD3_CLK__GPIO7_IO03              0x30c 0x6f4 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_CMD__SD3_CMD                 0x310 0x6f8 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_CMD__UART2_CTS_B             0x310 0x6f8 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_CMD__UART2_RTS_B             0x310 0x6f8 0x900 0x1 0x3
-#define MX6DL_PAD_SD3_CMD__FLEXCAN1_TX             0x310 0x6f8 0x000 0x2 0x0
-#define MX6DL_PAD_SD3_CMD__GPIO7_IO02              0x310 0x6f8 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT0__SD3_DATA0              0x314 0x6fc 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT0__UART1_CTS_B            0x314 0x6fc 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT0__UART1_RTS_B            0x314 0x6fc 0x8f8 0x1 0x2
-#define MX6DL_PAD_SD3_DAT0__FLEXCAN2_TX            0x314 0x6fc 0x000 0x2 0x0
-#define MX6DL_PAD_SD3_DAT0__GPIO7_IO04             0x314 0x6fc 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT1__SD3_DATA1              0x318 0x700 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT1__UART1_RTS_B            0x318 0x700 0x8f8 0x1 0x3
-#define MX6DL_PAD_SD3_DAT1__UART1_CTS_B            0x318 0x700 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT1__FLEXCAN2_RX            0x318 0x700 0x7cc 0x2 0x1
-#define MX6DL_PAD_SD3_DAT1__GPIO7_IO05             0x318 0x700 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT2__SD3_DATA2              0x31c 0x704 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT2__GPIO7_IO06             0x31c 0x704 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT3__SD3_DATA3              0x320 0x708 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT3__UART3_CTS_B            0x320 0x708 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT3__UART3_RTS_B            0x320 0x708 0x908 0x1 0x4
-#define MX6DL_PAD_SD3_DAT3__GPIO7_IO07             0x320 0x708 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT4__SD3_DATA4              0x324 0x70c 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT4__UART2_RX_DATA          0x324 0x70c 0x904 0x1 0x4
-#define MX6DL_PAD_SD3_DAT4__UART2_TX_DATA          0x324 0x70c 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT4__GPIO7_IO01             0x324 0x70c 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT5__SD3_DATA5              0x328 0x710 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT5__UART2_TX_DATA          0x328 0x710 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT5__UART2_RX_DATA          0x328 0x710 0x904 0x1 0x5
-#define MX6DL_PAD_SD3_DAT5__GPIO7_IO00             0x328 0x710 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT6__SD3_DATA6              0x32c 0x714 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT6__UART1_RX_DATA          0x32c 0x714 0x8fc 0x1 0x2
-#define MX6DL_PAD_SD3_DAT6__UART1_TX_DATA          0x32c 0x714 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT6__GPIO6_IO18             0x32c 0x714 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_DAT7__SD3_DATA7              0x330 0x718 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_DAT7__UART1_TX_DATA          0x330 0x718 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_DAT7__UART1_RX_DATA          0x330 0x718 0x8fc 0x1 0x3
-#define MX6DL_PAD_SD3_DAT7__GPIO6_IO17             0x330 0x718 0x000 0x5 0x0
-#define MX6DL_PAD_SD3_RST__SD3_RESET               0x334 0x71c 0x000 0x0 0x0
-#define MX6DL_PAD_SD3_RST__UART3_RTS_B             0x334 0x71c 0x908 0x1 0x5
-#define MX6DL_PAD_SD3_RST__UART3_CTS_B             0x334 0x71c 0x000 0x1 0x0
-#define MX6DL_PAD_SD3_RST__GPIO7_IO08              0x334 0x71c 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_CLK__SD4_CLK                 0x338 0x720 0x938 0x0 0x1
-#define MX6DL_PAD_SD4_CLK__NAND_WE_B               0x338 0x720 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_CLK__UART3_RX_DATA           0x338 0x720 0x90c 0x2 0x2
-#define MX6DL_PAD_SD4_CLK__UART3_TX_DATA           0x338 0x720 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_CLK__GPIO7_IO10              0x338 0x720 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_CMD__SD4_CMD                 0x33c 0x724 0x000 0x0 0x0
-#define MX6DL_PAD_SD4_CMD__NAND_RE_B               0x33c 0x724 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_CMD__UART3_TX_DATA           0x33c 0x724 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_CMD__UART3_RX_DATA           0x33c 0x724 0x90c 0x2 0x3
-#define MX6DL_PAD_SD4_CMD__GPIO7_IO09              0x33c 0x724 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT0__SD4_DATA0              0x340 0x728 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT0__NAND_DQS               0x340 0x728 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT0__GPIO2_IO08             0x340 0x728 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT1__SD4_DATA1              0x344 0x72c 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT1__PWM3_OUT               0x344 0x72c 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT1__GPIO2_IO09             0x344 0x72c 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT2__SD4_DATA2              0x348 0x730 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT2__PWM4_OUT               0x348 0x730 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT2__GPIO2_IO10             0x348 0x730 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT3__SD4_DATA3              0x34c 0x734 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT3__GPIO2_IO11             0x34c 0x734 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT4__SD4_DATA4              0x350 0x738 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT4__UART2_RX_DATA          0x350 0x738 0x904 0x2 0x6
-#define MX6DL_PAD_SD4_DAT4__UART2_TX_DATA          0x350 0x738 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT4__GPIO2_IO12             0x350 0x738 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT5__SD4_DATA5              0x354 0x73c 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT5__UART2_RTS_B            0x354 0x73c 0x900 0x2 0x4
-#define MX6DL_PAD_SD4_DAT5__UART2_CTS_B            0x354 0x73c 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT5__GPIO2_IO13             0x354 0x73c 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT6__SD4_DATA6              0x358 0x740 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT6__UART2_CTS_B            0x358 0x740 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT6__UART2_RTS_B            0x358 0x740 0x900 0x2 0x5
-#define MX6DL_PAD_SD4_DAT6__GPIO2_IO14             0x358 0x740 0x000 0x5 0x0
-#define MX6DL_PAD_SD4_DAT7__SD4_DATA7              0x35c 0x744 0x000 0x1 0x0
-#define MX6DL_PAD_SD4_DAT7__UART2_TX_DATA          0x35c 0x744 0x000 0x2 0x0
-#define MX6DL_PAD_SD4_DAT7__UART2_RX_DATA          0x35c 0x744 0x904 0x2 0x7
-#define MX6DL_PAD_SD4_DAT7__GPIO2_IO15             0x35c 0x744 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10     0x04c 0x360 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT10__AUD3_RXC             0x04c 0x360 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO          0x04c 0x360 0x7f8 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA        0x04c 0x360 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT10__UART1_RX_DATA        0x04c 0x360 0x8fc 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28           0x04c 0x360 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT10__ARM_TRACE07          0x04c 0x360 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11     0x050 0x364 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT11__AUD3_RXFS            0x050 0x364 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT11__ECSPI2_SS0           0x050 0x364 0x800 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA        0x050 0x364 0x8fc 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT11__UART1_TX_DATA        0x050 0x364 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29           0x050 0x364 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT11__ARM_TRACE08          0x050 0x364 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12     0x054 0x368 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT12__EIM_DATA08           0x054 0x368 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA        0x054 0x368 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT12__UART4_RX_DATA        0x054 0x368 0x914 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30           0x054 0x368 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT12__ARM_TRACE09          0x054 0x368 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13     0x058 0x36c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT13__EIM_DATA09           0x058 0x36c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA        0x058 0x36c 0x914 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT13__UART4_TX_DATA        0x058 0x36c 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31           0x058 0x36c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT13__ARM_TRACE10          0x058 0x36c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14     0x05c 0x370 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT14__EIM_DATA10           0x05c 0x370 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA        0x05c 0x370 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT14__UART5_RX_DATA        0x05c 0x370 0x91c 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00           0x05c 0x370 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT14__ARM_TRACE11          0x05c 0x370 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15     0x060 0x374 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT15__EIM_DATA11           0x060 0x374 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA        0x060 0x374 0x91c 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT15__UART5_TX_DATA        0x060 0x374 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01           0x060 0x374 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT15__ARM_TRACE12          0x060 0x374 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16     0x064 0x378 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT16__EIM_DATA12           0x064 0x378 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B          0x064 0x378 0x910 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT16__UART4_CTS_B          0x064 0x378 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02           0x064 0x378 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT16__ARM_TRACE13          0x064 0x378 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17     0x068 0x37c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT17__EIM_DATA13           0x068 0x37c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B          0x068 0x37c 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT17__UART4_RTS_B          0x068 0x37c 0x910 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03           0x068 0x37c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT17__ARM_TRACE14          0x068 0x37c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18     0x06c 0x380 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT18__EIM_DATA14           0x06c 0x380 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT18__UART5_RTS_B          0x06c 0x380 0x918 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT18__UART5_CTS_B          0x06c 0x380 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04           0x06c 0x380 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT18__ARM_TRACE15          0x06c 0x380 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19     0x070 0x384 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT19__EIM_DATA15           0x070 0x384 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT19__UART5_CTS_B          0x070 0x384 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT19__UART5_RTS_B          0x070 0x384 0x918 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05           0x070 0x384 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04      0x074 0x388 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT4__EIM_DATA02            0x074 0x388 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT4__ECSPI1_SCLK           0x074 0x388 0x7d8 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT4__KEY_COL5              0x074 0x388 0x8c0 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT4__AUD3_TXC              0x074 0x388 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT4__GPIO5_IO22            0x074 0x388 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT4__ARM_TRACE01           0x074 0x388 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05      0x078 0x38c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT5__EIM_DATA03            0x078 0x38c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT5__ECSPI1_MOSI           0x078 0x38c 0x7e0 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT5__KEY_ROW5              0x078 0x38c 0x8cc 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT5__AUD3_TXD              0x078 0x38c 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23            0x078 0x38c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT5__ARM_TRACE02           0x078 0x38c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06      0x07c 0x390 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT6__EIM_DATA04            0x07c 0x390 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT6__ECSPI1_MISO           0x07c 0x390 0x7dc 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT6__KEY_COL6              0x07c 0x390 0x8c4 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS             0x07c 0x390 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT6__GPIO5_IO24            0x07c 0x390 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT6__ARM_TRACE03           0x07c 0x390 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07      0x080 0x394 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT7__EIM_DATA05            0x080 0x394 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT7__ECSPI1_SS0            0x080 0x394 0x7e4 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT7__KEY_ROW6              0x080 0x394 0x8d0 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT7__AUD3_RXD              0x080 0x394 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT7__GPIO5_IO25            0x080 0x394 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT7__ARM_TRACE04           0x080 0x394 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08      0x084 0x398 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT8__EIM_DATA06            0x084 0x398 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK           0x084 0x398 0x7f4 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT8__KEY_COL7              0x084 0x398 0x8c8 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT8__I2C1_SDA              0x084 0x398 0x86c 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26            0x084 0x398 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT8__ARM_TRACE05           0x084 0x398 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09      0x088 0x39c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT9__EIM_DATA07            0x088 0x39c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI           0x088 0x39c 0x7fc 0x2 0x0
+#define MX6QDL_PAD_CSI0_DAT9__KEY_ROW7              0x088 0x39c 0x8d4 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT9__I2C1_SCL              0x088 0x39c 0x868 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27            0x088 0x39c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT9__ARM_TRACE06           0x088 0x39c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN  0x08c 0x3a0 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__EIM_DATA00         0x08c 0x3a0 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20         0x08c 0x3a0 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__ARM_TRACE_CLK      0x08c 0x3a0 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC       0x090 0x3a4 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_MCLK__CCM_CLKO1             0x090 0x3a4 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19            0x090 0x3a4 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_MCLK__ARM_TRACE_CTL         0x090 0x3a4 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK    0x094 0x3a8 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18          0x094 0x3a8 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_PIXCLK__ARM_EVENTO          0x094 0x3a8 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC      0x098 0x3ac 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__EIM_DATA01           0x098 0x3ac 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21           0x098 0x3ac 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__ARM_TRACE00          0x098 0x3ac 0x000 0x7 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK  0x09c 0x3b0 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__LCD_CLK            0x09c 0x3b0 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__GPIO4_IO16         0x09c 0x3b0 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__LCD_WR_RWN         0x09c 0x3b0 0x000 0x8 0x0
+#define MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15        0x0a0 0x3b4 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN15__LCD_ENABLE            0x0a0 0x3b4 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN15__AUD6_TXC              0x0a0 0x3b4 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN15__GPIO4_IO17            0x0a0 0x3b4 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN15__LCD_RD_E              0x0a0 0x3b4 0x000 0x8 0x0
+#define MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02         0x0a4 0x3b8 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN2__LCD_HSYNC              0x0a4 0x3b8 0x8d8 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN2__AUD6_TXD               0x0a4 0x3b8 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN2__GPIO4_IO18             0x0a4 0x3b8 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN2__LCD_RS                 0x0a4 0x3b8 0x000 0x8 0x0
+#define MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03         0x0a8 0x3bc 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN3__LCD_VSYNC              0x0a8 0x3bc 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN3__AUD6_TXFS              0x0a8 0x3bc 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN3__GPIO4_IO19             0x0a8 0x3bc 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN3__LCD_CS                 0x0a8 0x3bc 0x000 0x8 0x0
+#define MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04         0x0ac 0x3c0 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN4__LCD_BUSY               0x0ac 0x3c0 0x8d8 0x1 0x1
+#define MX6QDL_PAD_DI0_PIN4__AUD6_RXD               0x0ac 0x3c0 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN4__SD1_WP                 0x0ac 0x3c0 0x92c 0x3 0x0
+#define MX6QDL_PAD_DI0_PIN4__GPIO4_IO20             0x0ac 0x3c0 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN4__LCD_RESET              0x0ac 0x3c0 0x000 0x8 0x0
+#define MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00    0x0b0 0x3c4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT0__LCD_DATA00           0x0b0 0x3c4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK          0x0b0 0x3c4 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21           0x0b0 0x3c4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01    0x0b4 0x3c8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT1__LCD_DATA01           0x0b4 0x3c8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI          0x0b4 0x3c8 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT1__GPIO4_IO22           0x0b4 0x3c8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10   0x0b8 0x3cc 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT10__LCD_DATA10          0x0b8 0x3cc 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT10__GPIO4_IO31          0x0b8 0x3cc 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11   0x0bc 0x3d0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT11__LCD_DATA11          0x0bc 0x3d0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05          0x0bc 0x3d0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12   0x0c0 0x3d4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT12__LCD_DATA12          0x0c0 0x3d4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06          0x0c0 0x3d4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13   0x0c4 0x3d8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT13__LCD_DATA13          0x0c4 0x3d8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT13__AUD5_RXFS           0x0c4 0x3d8 0x7bc 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07          0x0c4 0x3d8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14   0x0c8 0x3dc 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT14__LCD_DATA14          0x0c8 0x3dc 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT14__AUD5_RXC            0x0c8 0x3dc 0x7b8 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08          0x0c8 0x3dc 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15   0x0cc 0x3e0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT15__LCD_DATA15          0x0cc 0x3e0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT15__ECSPI1_SS1          0x0cc 0x3e0 0x7e8 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT15__ECSPI2_SS1          0x0cc 0x3e0 0x804 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09          0x0cc 0x3e0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16   0x0d0 0x3e4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT16__LCD_DATA16          0x0d0 0x3e4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI         0x0d0 0x3e4 0x7fc 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT16__AUD5_TXC            0x0d0 0x3e4 0x7c0 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT16__SDMA_EXT_EVENT0     0x0d0 0x3e4 0x8e8 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10          0x0d0 0x3e4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17   0x0d4 0x3e8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT17__LCD_DATA17          0x0d4 0x3e8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO         0x0d4 0x3e8 0x7f8 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT17__AUD5_TXD            0x0d4 0x3e8 0x7b4 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT17__SDMA_EXT_EVENT1     0x0d4 0x3e8 0x8ec 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11          0x0d4 0x3e8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18   0x0d8 0x3ec 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT18__LCD_DATA18          0x0d8 0x3ec 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT18__ECSPI2_SS0          0x0d8 0x3ec 0x800 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS           0x0d8 0x3ec 0x7c4 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT18__AUD4_RXFS           0x0d8 0x3ec 0x7a4 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12          0x0d8 0x3ec 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT18__EIM_CS2_B           0x0d8 0x3ec 0x000 0x7 0x0
+#define MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19   0x0dc 0x3f0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT19__LCD_DATA19          0x0dc 0x3f0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK         0x0dc 0x3f0 0x7f4 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT19__AUD5_RXD            0x0dc 0x3f0 0x7b0 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT19__AUD4_RXC            0x0dc 0x3f0 0x7a0 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13          0x0dc 0x3f0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT19__EIM_CS3_B           0x0dc 0x3f0 0x000 0x7 0x0
+#define MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02    0x0e0 0x3f4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT2__LCD_DATA02           0x0e0 0x3f4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO          0x0e0 0x3f4 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT2__GPIO4_IO23           0x0e0 0x3f4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20   0x0e4 0x3f8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT20__LCD_DATA20          0x0e4 0x3f8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT20__ECSPI1_SCLK         0x0e4 0x3f8 0x7d8 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT20__AUD4_TXC            0x0e4 0x3f8 0x7a8 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14          0x0e4 0x3f8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21   0x0e8 0x3fc 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT21__LCD_DATA21          0x0e8 0x3fc 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT21__ECSPI1_MOSI         0x0e8 0x3fc 0x7e0 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT21__AUD4_TXD            0x0e8 0x3fc 0x79c 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15          0x0e8 0x3fc 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22   0x0ec 0x400 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT22__LCD_DATA22          0x0ec 0x400 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT22__ECSPI1_MISO         0x0ec 0x400 0x7dc 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS           0x0ec 0x400 0x7ac 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16          0x0ec 0x400 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23   0x0f0 0x404 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT23__LCD_DATA23          0x0f0 0x404 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT23__ECSPI1_SS0          0x0f0 0x404 0x7e4 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT23__AUD4_RXD            0x0f0 0x404 0x798 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17          0x0f0 0x404 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03    0x0f4 0x408 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT3__LCD_DATA03           0x0f4 0x408 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT3__ECSPI3_SS0           0x0f4 0x408 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24           0x0f4 0x408 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04    0x0f8 0x40c 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT4__LCD_DATA04           0x0f8 0x40c 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT4__ECSPI3_SS1           0x0f8 0x40c 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25           0x0f8 0x40c 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05    0x0fc 0x410 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT5__LCD_DATA05           0x0fc 0x410 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT5__ECSPI3_SS2           0x0fc 0x410 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT5__AUD6_RXFS            0x0fc 0x410 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26           0x0fc 0x410 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06    0x100 0x414 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT6__LCD_DATA06           0x100 0x414 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT6__ECSPI3_SS3           0x100 0x414 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT6__AUD6_RXC             0x100 0x414 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27           0x100 0x414 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07    0x104 0x418 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT7__LCD_DATA07           0x104 0x418 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT7__ECSPI3_RDY           0x104 0x418 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT7__GPIO4_IO28           0x104 0x418 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08    0x108 0x41c 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT8__LCD_DATA08           0x108 0x41c 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT8__PWM1_OUT             0x108 0x41c 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT8__WDOG1_B              0x108 0x41c 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29           0x108 0x41c 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09    0x10c 0x420 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT9__LCD_DATA09           0x10c 0x420 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT9__PWM2_OUT             0x10c 0x420 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT9__WDOG2_B              0x10c 0x420 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30           0x10c 0x420 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A16__EIM_ADDR16              0x110 0x4e0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A16__IPU1_DI1_DISP_CLK       0x110 0x4e0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A16__IPU1_CSI1_PIXCLK        0x110 0x4e0 0x8b8 0x2 0x0
+#define MX6QDL_PAD_EIM_A16__GPIO2_IO22              0x110 0x4e0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A16__SRC_BOOT_CFG16          0x110 0x4e0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A16__EPDC_DATA00             0x110 0x4e0 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A17__EIM_ADDR17              0x114 0x4e4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A17__IPU1_DISP1_DATA12       0x114 0x4e4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A17__IPU1_CSI1_DATA12        0x114 0x4e4 0x890 0x2 0x0
+#define MX6QDL_PAD_EIM_A17__GPIO2_IO21              0x114 0x4e4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A17__SRC_BOOT_CFG17          0x114 0x4e4 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A17__EPDC_PWR_STAT           0x114 0x4e4 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A18__EIM_ADDR18              0x118 0x4e8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A18__IPU1_DISP1_DATA13       0x118 0x4e8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A18__IPU1_CSI1_DATA13        0x118 0x4e8 0x894 0x2 0x0
+#define MX6QDL_PAD_EIM_A18__GPIO2_IO20              0x118 0x4e8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A18__SRC_BOOT_CFG18          0x118 0x4e8 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A18__EPDC_PWR_CTRL0          0x118 0x4e8 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A19__EIM_ADDR19              0x11c 0x4ec 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A19__IPU1_DISP1_DATA14       0x11c 0x4ec 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A19__IPU1_CSI1_DATA14        0x11c 0x4ec 0x898 0x2 0x0
+#define MX6QDL_PAD_EIM_A19__GPIO2_IO19              0x11c 0x4ec 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A19__SRC_BOOT_CFG19          0x11c 0x4ec 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A19__EPDC_PWR_CTRL1          0x11c 0x4ec 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A20__EIM_ADDR20              0x120 0x4f0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A20__IPU1_DISP1_DATA15       0x120 0x4f0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A20__IPU1_CSI1_DATA15        0x120 0x4f0 0x89c 0x2 0x0
+#define MX6QDL_PAD_EIM_A20__GPIO2_IO18              0x120 0x4f0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A20__SRC_BOOT_CFG20          0x120 0x4f0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A20__EPDC_PWR_CTRL2          0x120 0x4f0 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A21__EIM_ADDR21              0x124 0x4f4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A21__IPU1_DISP1_DATA16       0x124 0x4f4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A21__IPU1_CSI1_DATA16        0x124 0x4f4 0x8a0 0x2 0x0
+#define MX6QDL_PAD_EIM_A21__GPIO2_IO17              0x124 0x4f4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A21__SRC_BOOT_CFG21          0x124 0x4f4 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A21__EPDC_GDCLK              0x124 0x4f4 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A22__EIM_ADDR22              0x128 0x4f8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A22__IPU1_DISP1_DATA17       0x128 0x4f8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A22__IPU1_CSI1_DATA17        0x128 0x4f8 0x8a4 0x2 0x0
+#define MX6QDL_PAD_EIM_A22__GPIO2_IO16              0x128 0x4f8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A22__SRC_BOOT_CFG22          0x128 0x4f8 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A22__EPDC_GDSP               0x128 0x4f8 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A23__EIM_ADDR23              0x12c 0x4fc 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A23__IPU1_DISP1_DATA18       0x12c 0x4fc 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A23__IPU1_CSI1_DATA18        0x12c 0x4fc 0x8a8 0x2 0x0
+#define MX6QDL_PAD_EIM_A23__IPU1_SISG3              0x12c 0x4fc 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_A23__GPIO6_IO06              0x12c 0x4fc 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A23__SRC_BOOT_CFG23          0x12c 0x4fc 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A23__EPDC_GDOE               0x12c 0x4fc 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A24__EIM_ADDR24              0x130 0x500 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A24__IPU1_DISP1_DATA19       0x130 0x500 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A24__IPU1_CSI1_DATA19        0x130 0x500 0x8ac 0x2 0x0
+#define MX6QDL_PAD_EIM_A24__IPU1_SISG2              0x130 0x500 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_A24__GPIO5_IO04              0x130 0x500 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A24__SRC_BOOT_CFG24          0x130 0x500 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A24__EPDC_GDRL               0x130 0x500 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A25__EIM_ADDR25              0x134 0x504 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A25__ECSPI4_SS1              0x134 0x504 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A25__ECSPI2_RDY              0x134 0x504 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_A25__IPU1_DI1_PIN12          0x134 0x504 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_A25__IPU1_DI0_D1_CS          0x134 0x504 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_A25__GPIO5_IO02              0x134 0x504 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE        0x134 0x504 0x85c 0x6 0x0
+#define MX6QDL_PAD_EIM_A25__EPDC_DATA15             0x134 0x504 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_A25__EIM_ACLK_FREERUN        0x134 0x504 0x000 0x9 0x0
+#define MX6QDL_PAD_EIM_BCLK__EIM_BCLK               0x138 0x508 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_BCLK__IPU1_DI1_PIN16         0x138 0x508 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_BCLK__GPIO6_IO31             0x138 0x508 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_BCLK__EPDC_SDCE9             0x138 0x508 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_CS0__EIM_CS0_B               0x13c 0x50c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_CS0__IPU1_DI1_PIN05          0x13c 0x50c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK             0x13c 0x50c 0x7f4 0x2 0x2
+#define MX6QDL_PAD_EIM_CS0__GPIO2_IO23              0x13c 0x50c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_CS0__EPDC_DATA06             0x13c 0x50c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_CS1__EIM_CS1_B               0x140 0x510 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_CS1__IPU1_DI1_PIN06          0x140 0x510 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI             0x140 0x510 0x7fc 0x2 0x2
+#define MX6QDL_PAD_EIM_CS1__GPIO2_IO24              0x140 0x510 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_CS1__EPDC_DATA08             0x140 0x510 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D16__EIM_DATA16              0x144 0x514 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D16__ECSPI1_SCLK             0x144 0x514 0x7d8 0x1 0x2
+#define MX6QDL_PAD_EIM_D16__IPU1_DI0_PIN05          0x144 0x514 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D16__IPU1_CSI1_DATA18        0x144 0x514 0x8a8 0x3 0x1
+#define MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA         0x144 0x514 0x864 0x4 0x0
+#define MX6QDL_PAD_EIM_D16__GPIO3_IO16              0x144 0x514 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D16__I2C2_SDA                0x144 0x514 0x874 0x6 0x0
+#define MX6QDL_PAD_EIM_D16__EPDC_DATA10             0x144 0x514 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D17__EIM_DATA17              0x148 0x518 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D17__ECSPI1_MISO             0x148 0x518 0x7dc 0x1 0x2
+#define MX6QDL_PAD_EIM_D17__IPU1_DI0_PIN06          0x148 0x518 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D17__IPU1_CSI1_PIXCLK        0x148 0x518 0x8b8 0x3 0x1
+#define MX6QDL_PAD_EIM_D17__DCIC1_OUT               0x148 0x518 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D17__GPIO3_IO17              0x148 0x518 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D17__I2C3_SCL                0x148 0x518 0x878 0x6 0x0
+#define MX6QDL_PAD_EIM_D17__EPDC_VCOM0              0x148 0x518 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D18__EIM_DATA18              0x14c 0x51c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D18__ECSPI1_MOSI             0x14c 0x51c 0x7e0 0x1 0x2
+#define MX6QDL_PAD_EIM_D18__IPU1_DI0_PIN07          0x14c 0x51c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D18__IPU1_CSI1_DATA17        0x14c 0x51c 0x8a4 0x3 0x1
+#define MX6QDL_PAD_EIM_D18__IPU1_DI1_D0_CS          0x14c 0x51c 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D18__GPIO3_IO18              0x14c 0x51c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D18__I2C3_SDA                0x14c 0x51c 0x87c 0x6 0x0
+#define MX6QDL_PAD_EIM_D18__EPDC_VCOM1              0x14c 0x51c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D19__EIM_DATA19              0x150 0x520 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D19__ECSPI1_SS1              0x150 0x520 0x7e8 0x1 0x1
+#define MX6QDL_PAD_EIM_D19__IPU1_DI0_PIN08          0x150 0x520 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D19__IPU1_CSI1_DATA16        0x150 0x520 0x8a0 0x3 0x1
+#define MX6QDL_PAD_EIM_D19__UART1_CTS_B             0x150 0x520 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D19__UART1_RTS_B             0x150 0x520 0x8f8 0x4 0x0
+#define MX6QDL_PAD_EIM_D19__GPIO3_IO19              0x150 0x520 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D19__EPIT1_OUT               0x150 0x520 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D19__EPDC_DATA12             0x150 0x520 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D20__EIM_DATA20              0x154 0x524 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D20__ECSPI4_SS0              0x154 0x524 0x808 0x1 0x0
+#define MX6QDL_PAD_EIM_D20__IPU1_DI0_PIN16          0x154 0x524 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D20__IPU1_CSI1_DATA15        0x154 0x524 0x89c 0x3 0x1
+#define MX6QDL_PAD_EIM_D20__UART1_RTS_B             0x154 0x524 0x8f8 0x4 0x1
+#define MX6QDL_PAD_EIM_D20__UART1_CTS_B             0x154 0x524 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D20__GPIO3_IO20              0x154 0x524 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D20__EPIT2_OUT               0x154 0x524 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D21__EIM_DATA21              0x158 0x528 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D21__ECSPI4_SCLK             0x158 0x528 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D21__IPU1_DI0_PIN17          0x158 0x528 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D21__IPU1_CSI1_DATA11        0x158 0x528 0x88c 0x3 0x0
+#define MX6QDL_PAD_EIM_D21__USB_OTG_OC              0x158 0x528 0x920 0x4 0x0
+#define MX6QDL_PAD_EIM_D21__GPIO3_IO21              0x158 0x528 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D21__I2C1_SCL                0x158 0x528 0x868 0x6 0x1
+#define MX6QDL_PAD_EIM_D21__SPDIF_IN                0x158 0x528 0x8f0 0x7 0x0
+#define MX6QDL_PAD_EIM_D22__EIM_DATA22              0x15c 0x52c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D22__ECSPI4_MISO             0x15c 0x52c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D22__IPU1_DI0_PIN01          0x15c 0x52c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D22__IPU1_CSI1_DATA10        0x15c 0x52c 0x888 0x3 0x0
+#define MX6QDL_PAD_EIM_D22__USB_OTG_PWR             0x15c 0x52c 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D22__GPIO3_IO22              0x15c 0x52c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D22__SPDIF_OUT               0x15c 0x52c 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D22__EPDC_SDCE6              0x15c 0x52c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D23__EIM_DATA23              0x160 0x530 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_DI0_D0_CS          0x160 0x530 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D23__UART3_CTS_B             0x160 0x530 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D23__UART3_RTS_B             0x160 0x530 0x908 0x2 0x0
+#define MX6QDL_PAD_EIM_D23__UART1_DCD_B             0x160 0x530 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_CSI1_DATA_EN       0x160 0x530 0x8b0 0x4 0x0
+#define MX6QDL_PAD_EIM_D23__GPIO3_IO23              0x160 0x530 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_DI1_PIN02          0x160 0x530 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_DI1_PIN14          0x160 0x530 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D23__EPDC_DATA11             0x160 0x530 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D24__EIM_DATA24              0x164 0x534 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D24__ECSPI4_SS2              0x164 0x534 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D24__UART3_TX_DATA           0x164 0x534 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D24__UART3_RX_DATA           0x164 0x534 0x90c 0x2 0x0
+#define MX6QDL_PAD_EIM_D24__ECSPI1_SS2              0x164 0x534 0x7ec 0x3 0x0
+#define MX6QDL_PAD_EIM_D24__ECSPI2_SS2              0x164 0x534 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D24__GPIO3_IO24              0x164 0x534 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D24__AUD5_RXFS               0x164 0x534 0x7bc 0x6 0x1
+#define MX6QDL_PAD_EIM_D24__UART1_DTR_B             0x164 0x534 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D24__EPDC_SDCE7              0x164 0x534 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D25__EIM_DATA25              0x168 0x538 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D25__ECSPI4_SS3              0x168 0x538 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D25__UART3_RX_DATA           0x168 0x538 0x90c 0x2 0x1
+#define MX6QDL_PAD_EIM_D25__UART3_TX_DATA           0x168 0x538 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D25__ECSPI1_SS3              0x168 0x538 0x7f0 0x3 0x0
+#define MX6QDL_PAD_EIM_D25__ECSPI2_SS3              0x168 0x538 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D25__GPIO3_IO25              0x168 0x538 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D25__AUD5_RXC                0x168 0x538 0x7b8 0x6 0x1
+#define MX6QDL_PAD_EIM_D25__UART1_DSR_B             0x168 0x538 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D25__EPDC_SDCE8              0x168 0x538 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D26__EIM_DATA26              0x16c 0x53c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_DI1_PIN11          0x16c 0x53c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_CSI0_DATA01        0x16c 0x53c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_CSI1_DATA14        0x16c 0x53c 0x898 0x3 0x1
+#define MX6QDL_PAD_EIM_D26__UART2_TX_DATA           0x16c 0x53c 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D26__UART2_RX_DATA           0x16c 0x53c 0x904 0x4 0x0
+#define MX6QDL_PAD_EIM_D26__GPIO3_IO26              0x16c 0x53c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_SISG2              0x16c 0x53c 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_DISP1_DATA22       0x16c 0x53c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D26__EPDC_SDOED              0x16c 0x53c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D27__EIM_DATA27              0x170 0x540 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_DI1_PIN13          0x170 0x540 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_CSI0_DATA00        0x170 0x540 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_CSI1_DATA13        0x170 0x540 0x894 0x3 0x1
+#define MX6QDL_PAD_EIM_D27__UART2_RX_DATA           0x170 0x540 0x904 0x4 0x1
+#define MX6QDL_PAD_EIM_D27__UART2_TX_DATA           0x170 0x540 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D27__GPIO3_IO27              0x170 0x540 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_SISG3              0x170 0x540 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_DISP1_DATA23       0x170 0x540 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D27__EPDC_SDOE               0x170 0x540 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D28__EIM_DATA28              0x174 0x544 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D28__I2C1_SDA                0x174 0x544 0x86c 0x1 0x1
+#define MX6QDL_PAD_EIM_D28__ECSPI4_MOSI             0x174 0x544 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D28__IPU1_CSI1_DATA12        0x174 0x544 0x890 0x3 0x1
+#define MX6QDL_PAD_EIM_D28__UART2_CTS_B             0x174 0x544 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_RTS_B             0x174 0x544 0x900 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B         0x174 0x544 0x900 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_DTE_RTS_B         0x174 0x544 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__GPIO3_IO28              0x174 0x544 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D28__IPU1_EXT_TRIG           0x174 0x544 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D28__IPU1_DI0_PIN13          0x174 0x544 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D28__EPDC_PWR_CTRL3          0x174 0x544 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D29__EIM_DATA29              0x178 0x548 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D29__IPU1_DI1_PIN15          0x178 0x548 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D29__ECSPI4_SS0              0x178 0x548 0x808 0x2 0x1
+#define MX6QDL_PAD_EIM_D29__UART2_RTS_B             0x178 0x548 0x900 0x4 0x1
+#define MX6QDL_PAD_EIM_D29__UART2_CTS_B             0x178 0x548 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B         0x178 0x548 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D29__UART2_DTE_CTS_B         0x178 0x548 0x900 0x4 0x1
+#define MX6QDL_PAD_EIM_D29__GPIO3_IO29              0x178 0x548 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D29__IPU1_CSI1_VSYNC         0x178 0x548 0x8bc 0x6 0x0
+#define MX6QDL_PAD_EIM_D29__IPU1_DI0_PIN14          0x178 0x548 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D29__EPDC_PWR_WAKE           0x178 0x548 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D30__EIM_DATA30              0x17c 0x54c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D30__IPU1_DISP1_DATA21       0x17c 0x54c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D30__IPU1_DI0_PIN11          0x17c 0x54c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D30__IPU1_CSI0_DATA03        0x17c 0x54c 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_D30__UART3_CTS_B             0x17c 0x54c 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D30__UART3_RTS_B             0x17c 0x54c 0x908 0x4 0x1
+#define MX6QDL_PAD_EIM_D30__GPIO3_IO30              0x17c 0x54c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D30__USB_H1_OC               0x17c 0x54c 0x924 0x6 0x0
+#define MX6QDL_PAD_EIM_D30__EPDC_SDOEZ              0x17c 0x54c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D31__EIM_DATA31              0x180 0x550 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D31__IPU1_DISP1_DATA20       0x180 0x550 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D31__IPU1_DI0_PIN12          0x180 0x550 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D31__IPU1_CSI0_DATA02        0x180 0x550 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_D31__UART3_RTS_B             0x180 0x550 0x908 0x4 0x2
+#define MX6QDL_PAD_EIM_D31__UART3_CTS_B             0x180 0x550 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D31__GPIO3_IO31              0x180 0x550 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D31__USB_H1_PWR              0x180 0x550 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D31__EPDC_SDCLK_P            0x180 0x550 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_D31__EIM_ACLK_FREERUN        0x180 0x550 0x000 0x9 0x0
+#define MX6QDL_PAD_EIM_DA0__EIM_AD00                0x184 0x554 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA0__IPU1_DISP1_DATA09       0x184 0x554 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA0__IPU1_CSI1_DATA09        0x184 0x554 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA0__GPIO3_IO00              0x184 0x554 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA0__SRC_BOOT_CFG00          0x184 0x554 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA0__EPDC_SDCLK_N            0x184 0x554 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA1__EIM_AD01                0x188 0x558 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA1__IPU1_DISP1_DATA08       0x188 0x558 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA1__IPU1_CSI1_DATA08        0x188 0x558 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA1__GPIO3_IO01              0x188 0x558 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA1__SRC_BOOT_CFG01          0x188 0x558 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA1__EPDC_SDLE               0x188 0x558 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA10__EIM_AD10               0x18c 0x55c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA10__IPU1_DI1_PIN15         0x18c 0x55c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA10__IPU1_CSI1_DATA_EN      0x18c 0x55c 0x8b0 0x2 0x1
+#define MX6QDL_PAD_EIM_DA10__GPIO3_IO10             0x18c 0x55c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA10__SRC_BOOT_CFG10         0x18c 0x55c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA10__EPDC_DATA01            0x18c 0x55c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA11__EIM_AD11               0x190 0x560 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA11__IPU1_DI1_PIN02         0x190 0x560 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA11__IPU1_CSI1_HSYNC        0x190 0x560 0x8b4 0x2 0x0
+#define MX6QDL_PAD_EIM_DA11__GPIO3_IO11             0x190 0x560 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA11__SRC_BOOT_CFG11         0x190 0x560 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA11__EPDC_DATA03            0x190 0x560 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA12__EIM_AD12               0x194 0x564 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA12__IPU1_DI1_PIN03         0x194 0x564 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA12__IPU1_CSI1_VSYNC        0x194 0x564 0x8bc 0x2 0x1
+#define MX6QDL_PAD_EIM_DA12__GPIO3_IO12             0x194 0x564 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA12__SRC_BOOT_CFG12         0x194 0x564 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA12__EPDC_DATA02            0x194 0x564 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA13__EIM_AD13               0x198 0x568 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA13__IPU1_DI1_D0_CS         0x198 0x568 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA13__GPIO3_IO13             0x198 0x568 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA13__SRC_BOOT_CFG13         0x198 0x568 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA13__EPDC_DATA13            0x198 0x568 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA14__EIM_AD14               0x19c 0x56c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA14__IPU1_DI1_D1_CS         0x19c 0x56c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA14__GPIO3_IO14             0x19c 0x56c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA14__SRC_BOOT_CFG14         0x19c 0x56c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA14__EPDC_DATA14            0x19c 0x56c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA15__EIM_AD15               0x1a0 0x570 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA15__IPU1_DI1_PIN01         0x1a0 0x570 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA15__IPU1_DI1_PIN04         0x1a0 0x570 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA15__GPIO3_IO15             0x1a0 0x570 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA15__SRC_BOOT_CFG15         0x1a0 0x570 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA15__EPDC_DATA09            0x1a0 0x570 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA2__EIM_AD02                0x1a4 0x574 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA2__IPU1_DISP1_DATA07       0x1a4 0x574 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA2__IPU1_CSI1_DATA07        0x1a4 0x574 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA2__GPIO3_IO02              0x1a4 0x574 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA2__SRC_BOOT_CFG02          0x1a4 0x574 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA2__EPDC_BDR0               0x1a4 0x574 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA3__EIM_AD03                0x1a8 0x578 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA3__IPU1_DISP1_DATA06       0x1a8 0x578 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA3__IPU1_CSI1_DATA06        0x1a8 0x578 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA3__GPIO3_IO03              0x1a8 0x578 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA3__SRC_BOOT_CFG03          0x1a8 0x578 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA3__EPDC_BDR1               0x1a8 0x578 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA4__EIM_AD04                0x1ac 0x57c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA4__IPU1_DISP1_DATA05       0x1ac 0x57c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA4__IPU1_CSI1_DATA05        0x1ac 0x57c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA4__GPIO3_IO04              0x1ac 0x57c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA4__SRC_BOOT_CFG04          0x1ac 0x57c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA4__EPDC_SDCE0              0x1ac 0x57c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA5__EIM_AD05                0x1b0 0x580 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA5__IPU1_DISP1_DATA04       0x1b0 0x580 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA5__IPU1_CSI1_DATA04        0x1b0 0x580 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA5__GPIO3_IO05              0x1b0 0x580 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA5__SRC_BOOT_CFG05          0x1b0 0x580 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA5__EPDC_SDCE1              0x1b0 0x580 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA6__EIM_AD06                0x1b4 0x584 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA6__IPU1_DISP1_DATA03       0x1b4 0x584 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA6__IPU1_CSI1_DATA03        0x1b4 0x584 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA6__GPIO3_IO06              0x1b4 0x584 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA6__SRC_BOOT_CFG06          0x1b4 0x584 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA6__EPDC_SDCE2              0x1b4 0x584 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA7__EIM_AD07                0x1b8 0x588 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA7__IPU1_DISP1_DATA02       0x1b8 0x588 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA7__IPU1_CSI1_DATA02        0x1b8 0x588 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA7__GPIO3_IO07              0x1b8 0x588 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA7__SRC_BOOT_CFG07          0x1b8 0x588 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA7__EPDC_SDCE3              0x1b8 0x588 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA8__EIM_AD08                0x1bc 0x58c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA8__IPU1_DISP1_DATA01       0x1bc 0x58c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA8__IPU1_CSI1_DATA01        0x1bc 0x58c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA8__GPIO3_IO08              0x1bc 0x58c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA8__SRC_BOOT_CFG08          0x1bc 0x58c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA8__EPDC_SDCE4              0x1bc 0x58c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_DA9__EIM_AD09                0x1c0 0x590 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA9__IPU1_DISP1_DATA00       0x1c0 0x590 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA9__IPU1_CSI1_DATA00        0x1c0 0x590 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA9__GPIO3_IO09              0x1c0 0x590 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA9__SRC_BOOT_CFG09          0x1c0 0x590 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA9__EPDC_SDCE5              0x1c0 0x590 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_EB0__EIM_EB0_B               0x1c4 0x594 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB0__IPU1_DISP1_DATA11       0x1c4 0x594 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_EB0__IPU1_CSI1_DATA11        0x1c4 0x594 0x88c 0x2 0x1
+#define MX6QDL_PAD_EIM_EB0__CCM_PMIC_READY          0x1c4 0x594 0x7d4 0x4 0x0
+#define MX6QDL_PAD_EIM_EB0__GPIO2_IO28              0x1c4 0x594 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB0__SRC_BOOT_CFG27          0x1c4 0x594 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB0__EPDC_PWR_COM            0x1c4 0x594 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_EB1__EIM_EB1_B               0x1c8 0x598 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB1__IPU1_DISP1_DATA10       0x1c8 0x598 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_EB1__IPU1_CSI1_DATA10        0x1c8 0x598 0x888 0x2 0x1
+#define MX6QDL_PAD_EIM_EB1__GPIO2_IO29              0x1c8 0x598 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB1__SRC_BOOT_CFG28          0x1c8 0x598 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB1__EPDC_SDSHR              0x1c8 0x598 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_EB2__EIM_EB2_B               0x1cc 0x59c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB2__ECSPI1_SS0              0x1cc 0x59c 0x7e4 0x1 0x2
+#define MX6QDL_PAD_EIM_EB2__IPU1_CSI1_DATA19        0x1cc 0x59c 0x8ac 0x3 0x1
+#define MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL         0x1cc 0x59c 0x860 0x4 0x0
+#define MX6QDL_PAD_EIM_EB2__GPIO2_IO30              0x1cc 0x59c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB2__I2C2_SCL                0x1cc 0x59c 0x870 0x6 0x0
+#define MX6QDL_PAD_EIM_EB2__SRC_BOOT_CFG30          0x1cc 0x59c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB2__EPDC_DATA05             0x1cc 0x59c 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_EB3__EIM_EB3_B               0x1d0 0x5a0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB3__ECSPI4_RDY              0x1d0 0x5a0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_EB3__UART3_RTS_B             0x1d0 0x5a0 0x908 0x2 0x3
+#define MX6QDL_PAD_EIM_EB3__UART3_CTS_B             0x1d0 0x5a0 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_EB3__UART1_RI_B              0x1d0 0x5a0 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_EB3__IPU1_CSI1_HSYNC         0x1d0 0x5a0 0x8b4 0x4 0x1
+#define MX6QDL_PAD_EIM_EB3__GPIO2_IO31              0x1d0 0x5a0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB3__IPU1_DI1_PIN03          0x1d0 0x5a0 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_EB3__SRC_BOOT_CFG31          0x1d0 0x5a0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB3__EPDC_SDCE0              0x1d0 0x5a0 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_EB3__EIM_ACLK_FREERUN        0x1d0 0x5a0 0x000 0x9 0x0
+#define MX6QDL_PAD_EIM_LBA__EIM_LBA_B               0x1d4 0x5a4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_LBA__IPU1_DI1_PIN17          0x1d4 0x5a4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_LBA__ECSPI2_SS1              0x1d4 0x5a4 0x804 0x2 0x1
+#define MX6QDL_PAD_EIM_LBA__GPIO2_IO27              0x1d4 0x5a4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_LBA__SRC_BOOT_CFG26          0x1d4 0x5a4 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_LBA__EPDC_DATA04             0x1d4 0x5a4 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_OE__EIM_OE_B                 0x1d8 0x5a8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_OE__IPU1_DI1_PIN07           0x1d8 0x5a8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_OE__ECSPI2_MISO              0x1d8 0x5a8 0x7f8 0x2 0x2
+#define MX6QDL_PAD_EIM_OE__GPIO2_IO25               0x1d8 0x5a8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_OE__EPDC_PWR_IRQ             0x1d8 0x5a8 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_RW__EIM_RW                   0x1dc 0x5ac 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_RW__IPU1_DI1_PIN08           0x1dc 0x5ac 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_RW__ECSPI2_SS0               0x1dc 0x5ac 0x800 0x2 0x2
+#define MX6QDL_PAD_EIM_RW__GPIO2_IO26               0x1dc 0x5ac 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_RW__SRC_BOOT_CFG29           0x1dc 0x5ac 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_RW__EPDC_DATA07              0x1dc 0x5ac 0x000 0x8 0x0
+#define MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B             0x1e0 0x5b0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_WAIT__EIM_DTACK_B            0x1e0 0x5b0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_WAIT__GPIO5_IO00             0x1e0 0x5b0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_WAIT__SRC_BOOT_CFG25         0x1e0 0x5b0 0x000 0x7 0x0
+#define MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN          0x1e4 0x5b4 0x828 0x1 0x0
+#define MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK         0x1e4 0x5b4 0x840 0x2 0x0
+#define MX6QDL_PAD_ENET_CRS_DV__SPDIF_EXT_CLK       0x1e4 0x5b4 0x8f4 0x3 0x0
+#define MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25          0x1e4 0x5b4 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_MDC__MLB_DATA               0x1e8 0x5b8 0x8e0 0x0 0x0
+#define MX6QDL_PAD_ENET_MDC__ENET_MDC               0x1e8 0x5b8 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0           0x1e8 0x5b8 0x858 0x2 0x0
+#define MX6QDL_PAD_ENET_MDC__ENET_1588_EVENT1_IN    0x1e8 0x5b8 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_MDC__GPIO1_IO31             0x1e8 0x5b8 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_MDIO__ENET_MDIO             0x1ec 0x5bc 0x810 0x1 0x0
+#define MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK           0x1ec 0x5bc 0x83c 0x2 0x0
+#define MX6QDL_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT  0x1ec 0x5bc 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_MDIO__GPIO1_IO22            0x1ec 0x5bc 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_MDIO__SPDIF_LOCK            0x1ec 0x5bc 0x000 0x6 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK        0x1f0 0x5c0 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__ESAI_RX_FS         0x1f0 0x5c0 0x82c 0x2 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23         0x1f0 0x5c0 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__SPDIF_SR_CLK       0x1f0 0x5c0 0x000 0x6 0x0
+#define MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID           0x1f4 0x5c4 0x790 0x0 0x0
+#define MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER           0x1f4 0x5c4 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_RX_ER__ESAI_RX_HF_CLK       0x1f4 0x5c4 0x834 0x2 0x0
+#define MX6QDL_PAD_ENET_RX_ER__SPDIF_IN             0x1f4 0x5c4 0x8f0 0x3 0x1
+#define MX6QDL_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT 0x1f4 0x5c4 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24           0x1f4 0x5c4 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0         0x1f8 0x5c8 0x818 0x1 0x0
+#define MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK        0x1f8 0x5c8 0x838 0x2 0x0
+#define MX6QDL_PAD_ENET_RXD0__SPDIF_OUT             0x1f8 0x5c8 0x000 0x3 0x0
+#define MX6QDL_PAD_ENET_RXD0__GPIO1_IO27            0x1f8 0x5c8 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_RXD1__MLB_SIG               0x1fc 0x5cc 0x8e4 0x0 0x0
+#define MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1         0x1fc 0x5cc 0x81c 0x1 0x0
+#define MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS            0x1fc 0x5cc 0x830 0x2 0x0
+#define MX6QDL_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT  0x1fc 0x5cc 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_RXD1__GPIO1_IO26            0x1fc 0x5cc 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN           0x200 0x5d0 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2         0x200 0x5d0 0x850 0x2 0x0
+#define MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28           0x200 0x5d0 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TX_EN__I2C4_SCL             0x200 0x5d0 0x880 0x9 0x0
+#define MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0         0x204 0x5d4 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1          0x204 0x5d4 0x854 0x2 0x0
+#define MX6QDL_PAD_ENET_TXD0__GPIO1_IO30            0x204 0x5d4 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TXD1__MLB_CLK               0x208 0x5d8 0x8dc 0x0 0x0
+#define MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1         0x208 0x5d8 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3          0x208 0x5d8 0x84c 0x2 0x0
+#define MX6QDL_PAD_ENET_TXD1__ENET_1588_EVENT0_IN   0x208 0x5d8 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_TXD1__GPIO1_IO29            0x208 0x5d8 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TXD1__I2C4_SDA              0x208 0x5d8 0x884 0x9 0x0
+#define MX6QDL_PAD_GPIO_0__CCM_CLKO1                0x20c 0x5dc 0x000 0x0 0x0
+#define MX6QDL_PAD_GPIO_0__KEY_COL5                 0x20c 0x5dc 0x8c0 0x2 0x1
+#define MX6QDL_PAD_GPIO_0__ASRC_EXT_CLK             0x20c 0x5dc 0x794 0x3 0x0
+#define MX6QDL_PAD_GPIO_0__EPIT1_OUT                0x20c 0x5dc 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_0__GPIO1_IO00               0x20c 0x5dc 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_0__USB_H1_PWR               0x20c 0x5dc 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_0__SNVS_VIO_5               0x20c 0x5dc 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_1__ESAI_RX_CLK              0x210 0x5e0 0x83c 0x0 0x1
+#define MX6QDL_PAD_GPIO_1__WDOG2_B                  0x210 0x5e0 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_1__KEY_ROW5                 0x210 0x5e0 0x8cc 0x2 0x1
+#define MX6QDL_PAD_GPIO_1__USB_OTG_ID               0x210 0x5e0 0x790 0x3 0x1
+#define MX6QDL_PAD_GPIO_1__PWM2_OUT                 0x210 0x5e0 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_1__GPIO1_IO01               0x210 0x5e0 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_1__SD1_CD_B                 0x210 0x5e0 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_16__ESAI_TX3_RX2            0x214 0x5e4 0x850 0x0 0x1
+#define MX6QDL_PAD_GPIO_16__ENET_1588_EVENT2_IN     0x214 0x5e4 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_16__ENET_REF_CLK            0x214 0x5e4 0x80c 0x2 0x0
+#define MX6QDL_PAD_GPIO_16__SD1_LCTL                0x214 0x5e4 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_16__SPDIF_IN                0x214 0x5e4 0x8f0 0x4 0x2
+#define MX6QDL_PAD_GPIO_16__GPIO7_IO11              0x214 0x5e4 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_16__I2C3_SDA                0x214 0x5e4 0x87c 0x6 0x1
+#define MX6QDL_PAD_GPIO_16__JTAG_DE_B               0x214 0x5e4 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_17__ESAI_TX0                0x218 0x5e8 0x844 0x0 0x0
+#define MX6QDL_PAD_GPIO_17__ENET_1588_EVENT3_IN     0x218 0x5e8 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_17__CCM_PMIC_READY          0x218 0x5e8 0x7d4 0x2 0x1
+#define MX6QDL_PAD_GPIO_17__SDMA_EXT_EVENT0         0x218 0x5e8 0x8e8 0x3 0x1
+#define MX6QDL_PAD_GPIO_17__SPDIF_OUT               0x218 0x5e8 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_17__GPIO7_IO12              0x218 0x5e8 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_18__ESAI_TX1                0x21c 0x5ec 0x848 0x0 0x0
+#define MX6QDL_PAD_GPIO_18__ENET_RX_CLK             0x21c 0x5ec 0x814 0x1 0x0
+#define MX6QDL_PAD_GPIO_18__SD3_VSELECT             0x21c 0x5ec 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_18__SDMA_EXT_EVENT1         0x21c 0x5ec 0x8ec 0x3 0x1
+#define MX6QDL_PAD_GPIO_18__ASRC_EXT_CLK            0x21c 0x5ec 0x794 0x4 0x1
+#define MX6QDL_PAD_GPIO_18__GPIO7_IO13              0x21c 0x5ec 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_18__SNVS_VIO_5_CTL          0x21c 0x5ec 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_19__KEY_COL5                0x220 0x5f0 0x8c0 0x0 0x2
+#define MX6QDL_PAD_GPIO_19__ENET_1588_EVENT0_OUT    0x220 0x5f0 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_19__SPDIF_OUT               0x220 0x5f0 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_19__CCM_CLKO1               0x220 0x5f0 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_19__ECSPI1_RDY              0x220 0x5f0 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_19__GPIO4_IO05              0x220 0x5f0 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_19__ENET_TX_ER              0x220 0x5f0 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_2__ESAI_TX_FS               0x224 0x5f4 0x830 0x0 0x1
+#define MX6QDL_PAD_GPIO_2__KEY_ROW6                 0x224 0x5f4 0x8d0 0x2 0x1
+#define MX6QDL_PAD_GPIO_2__GPIO1_IO02               0x224 0x5f4 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_2__SD2_WP                   0x224 0x5f4 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_2__MLB_DATA                 0x224 0x5f4 0x8e0 0x7 0x1
+#define MX6QDL_PAD_GPIO_3__ESAI_RX_HF_CLK           0x228 0x5f8 0x834 0x0 0x1
+#define MX6QDL_PAD_GPIO_3__I2C3_SCL                 0x228 0x5f8 0x878 0x2 0x1
+#define MX6QDL_PAD_GPIO_3__XTALOSC_REF_CLK_24M      0x228 0x5f8 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_3__CCM_CLKO2                0x228 0x5f8 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_3__GPIO1_IO03               0x228 0x5f8 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_3__USB_H1_OC                0x228 0x5f8 0x924 0x6 0x1
+#define MX6QDL_PAD_GPIO_3__MLB_CLK                  0x228 0x5f8 0x8dc 0x7 0x1
+#define MX6QDL_PAD_GPIO_4__ESAI_TX_HF_CLK           0x22c 0x5fc 0x838 0x0 0x1
+#define MX6QDL_PAD_GPIO_4__KEY_COL7                 0x22c 0x5fc 0x8c8 0x2 0x1
+#define MX6QDL_PAD_GPIO_4__GPIO1_IO04               0x22c 0x5fc 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_4__SD2_CD_B                 0x22c 0x5fc 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3             0x230 0x600 0x84c 0x0 0x1
+#define MX6QDL_PAD_GPIO_5__KEY_ROW7                 0x230 0x600 0x8d4 0x2 0x1
+#define MX6QDL_PAD_GPIO_5__CCM_CLKO1                0x230 0x600 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_5__GPIO1_IO05               0x230 0x600 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_5__I2C3_SCL                 0x230 0x600 0x878 0x6 0x2
+#define MX6QDL_PAD_GPIO_5__ARM_EVENTI               0x230 0x600 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK              0x234 0x604 0x840 0x0 0x1
+#define MX6QDL_PAD_GPIO_6__I2C3_SDA                 0x234 0x604 0x87c 0x2 0x2
+#define MX6QDL_PAD_GPIO_6__GPIO1_IO06               0x234 0x604 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_6__SD2_LCTL                 0x234 0x604 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_6__MLB_SIG                  0x234 0x604 0x8e4 0x7 0x1
+#define MX6QDL_PAD_GPIO_7__ESAI_TX4_RX1             0x238 0x608 0x854 0x0 0x1
+#define MX6QDL_PAD_GPIO_7__EPIT1_OUT                0x238 0x608 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_7__FLEXCAN1_TX              0x238 0x608 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_7__UART2_TX_DATA            0x238 0x608 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_7__UART2_RX_DATA            0x238 0x608 0x904 0x4 0x2
+#define MX6QDL_PAD_GPIO_7__GPIO1_IO07               0x238 0x608 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_7__SPDIF_LOCK               0x238 0x608 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_7__USB_OTG_HOST_MODE        0x238 0x608 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_7__I2C4_SCL                 0x238 0x608 0x880 0x8 0x1
+#define MX6QDL_PAD_GPIO_8__ESAI_TX5_RX0             0x23c 0x60c 0x858 0x0 0x1
+#define MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K      0x23c 0x60c 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_8__EPIT2_OUT                0x23c 0x60c 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_8__FLEXCAN1_RX              0x23c 0x60c 0x7c8 0x3 0x0
+#define MX6QDL_PAD_GPIO_8__UART2_RX_DATA            0x23c 0x60c 0x904 0x4 0x3
+#define MX6QDL_PAD_GPIO_8__UART2_TX_DATA            0x23c 0x60c 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_8__GPIO1_IO08               0x23c 0x60c 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_8__SPDIF_SR_CLK             0x23c 0x60c 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_8__USB_OTG_PWR_CTL_WAKE     0x23c 0x60c 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_8__I2C4_SDA                 0x23c 0x60c 0x884 0x8 0x1
+#define MX6QDL_PAD_GPIO_9__ESAI_RX_FS               0x240 0x610 0x82c 0x0 0x1
+#define MX6QDL_PAD_GPIO_9__WDOG1_B                  0x240 0x610 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_9__KEY_COL6                 0x240 0x610 0x8c4 0x2 0x1
+#define MX6QDL_PAD_GPIO_9__CCM_REF_EN_B             0x240 0x610 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_9__PWM1_OUT                 0x240 0x610 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_9__GPIO1_IO09               0x240 0x610 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_9__SD1_WP                   0x240 0x610 0x92c 0x6 0x1
+#define MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK            0x244 0x62c 0x7d8 0x0 0x3
+#define MX6QDL_PAD_KEY_COL0__ENET_RX_DATA3          0x244 0x62c 0x824 0x1 0x0
+#define MX6QDL_PAD_KEY_COL0__AUD5_TXC               0x244 0x62c 0x7c0 0x2 0x1
+#define MX6QDL_PAD_KEY_COL0__KEY_COL0               0x244 0x62c 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL0__UART4_TX_DATA          0x244 0x62c 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL0__UART4_RX_DATA          0x244 0x62c 0x914 0x4 0x2
+#define MX6QDL_PAD_KEY_COL0__GPIO4_IO06             0x244 0x62c 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL0__DCIC1_OUT              0x244 0x62c 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_COL1__ECSPI1_MISO            0x248 0x630 0x7dc 0x0 0x3
+#define MX6QDL_PAD_KEY_COL1__ENET_MDIO              0x248 0x630 0x810 0x1 0x1
+#define MX6QDL_PAD_KEY_COL1__AUD5_TXFS              0x248 0x630 0x7c4 0x2 0x1
+#define MX6QDL_PAD_KEY_COL1__KEY_COL1               0x248 0x630 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL1__UART5_TX_DATA          0x248 0x630 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL1__UART5_RX_DATA          0x248 0x630 0x91c 0x4 0x2
+#define MX6QDL_PAD_KEY_COL1__GPIO4_IO08             0x248 0x630 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL1__SD1_VSELECT            0x248 0x630 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_COL2__ECSPI1_SS1             0x24c 0x634 0x7e8 0x0 0x2
+#define MX6QDL_PAD_KEY_COL2__ENET_RX_DATA2          0x24c 0x634 0x820 0x1 0x0
+#define MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX            0x24c 0x634 0x000 0x2 0x0
+#define MX6QDL_PAD_KEY_COL2__KEY_COL2               0x24c 0x634 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL2__ENET_MDC               0x24c 0x634 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL2__GPIO4_IO10             0x24c 0x634 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL2__USB_H1_PWR_CTL_WAKE    0x24c 0x634 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_COL3__ECSPI1_SS3             0x250 0x638 0x7f0 0x0 0x1
+#define MX6QDL_PAD_KEY_COL3__ENET_CRS               0x250 0x638 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL        0x250 0x638 0x860 0x2 0x1
+#define MX6QDL_PAD_KEY_COL3__KEY_COL3               0x250 0x638 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL3__I2C2_SCL               0x250 0x638 0x870 0x4 0x1
+#define MX6QDL_PAD_KEY_COL3__GPIO4_IO12             0x250 0x638 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL3__SPDIF_IN               0x250 0x638 0x8f0 0x6 0x3
+#define MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX            0x254 0x63c 0x000 0x0 0x0
+#define MX6QDL_PAD_KEY_COL4__IPU1_SISG4             0x254 0x63c 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_COL4__USB_OTG_OC             0x254 0x63c 0x920 0x2 0x1
+#define MX6QDL_PAD_KEY_COL4__KEY_COL4               0x254 0x63c 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL4__UART5_RTS_B            0x254 0x63c 0x918 0x4 0x2
+#define MX6QDL_PAD_KEY_COL4__UART5_CTS_B            0x254 0x63c 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL4__GPIO4_IO14             0x254 0x63c 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI            0x258 0x640 0x7e0 0x0 0x3
+#define MX6QDL_PAD_KEY_ROW0__ENET_TX_DATA3          0x258 0x640 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW0__AUD5_TXD               0x258 0x640 0x7b4 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW0__KEY_ROW0               0x258 0x640 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA          0x258 0x640 0x914 0x4 0x3
+#define MX6QDL_PAD_KEY_ROW0__UART4_TX_DATA          0x258 0x640 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW0__GPIO4_IO07             0x258 0x640 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW0__DCIC2_OUT              0x258 0x640 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_ROW1__ECSPI1_SS0             0x25c 0x644 0x7e4 0x0 0x3
+#define MX6QDL_PAD_KEY_ROW1__ENET_COL               0x25c 0x644 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW1__AUD5_RXD               0x25c 0x644 0x7b0 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW1__KEY_ROW1               0x25c 0x644 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA          0x25c 0x644 0x91c 0x4 0x3
+#define MX6QDL_PAD_KEY_ROW1__UART5_TX_DATA          0x25c 0x644 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW1__GPIO4_IO09             0x25c 0x644 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW1__SD2_VSELECT            0x25c 0x644 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_ROW2__ECSPI1_SS2             0x260 0x648 0x7ec 0x0 0x1
+#define MX6QDL_PAD_KEY_ROW2__ENET_TX_DATA2          0x260 0x648 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX            0x260 0x648 0x7c8 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW2__KEY_ROW2               0x260 0x648 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW2__SD2_VSELECT            0x260 0x648 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW2__GPIO4_IO11             0x260 0x648 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE       0x260 0x648 0x85c 0x6 0x1
+#define MX6QDL_PAD_KEY_ROW3__ASRC_EXT_CLK           0x264 0x64c 0x794 0x1 0x2
+#define MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA        0x264 0x64c 0x864 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW3__KEY_ROW3               0x264 0x64c 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW3__I2C2_SDA               0x264 0x64c 0x874 0x4 0x1
+#define MX6QDL_PAD_KEY_ROW3__GPIO4_IO13             0x264 0x64c 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW3__SD1_VSELECT            0x264 0x64c 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX            0x268 0x650 0x7cc 0x0 0x0
+#define MX6QDL_PAD_KEY_ROW4__IPU1_SISG5             0x268 0x650 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW4__USB_OTG_PWR            0x268 0x650 0x000 0x2 0x0
+#define MX6QDL_PAD_KEY_ROW4__KEY_ROW4               0x268 0x650 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW4__UART5_CTS_B            0x268 0x650 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW4__UART5_RTS_B            0x268 0x650 0x918 0x4 0x3
+#define MX6QDL_PAD_KEY_ROW4__GPIO4_IO15             0x268 0x650 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_ALE__NAND_ALE              0x26c 0x654 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_ALE__SD4_RESET             0x26c 0x654 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_ALE__GPIO6_IO08            0x26c 0x654 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CLE__NAND_CLE              0x270 0x658 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CLE__GPIO6_IO07            0x270 0x658 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS0__NAND_CE0_B            0x274 0x65c 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS0__GPIO6_IO11            0x274 0x65c 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS1__NAND_CE1_B            0x278 0x660 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS1__SD4_VSELECT           0x278 0x660 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CS1__SD3_VSELECT           0x278 0x660 0x000 0x2 0x0
+#define MX6QDL_PAD_NANDF_CS1__GPIO6_IO14            0x278 0x660 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS2__NAND_CE2_B            0x27c 0x664 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS2__IPU1_SISG0            0x27c 0x664 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CS2__ESAI_TX0              0x27c 0x664 0x844 0x2 0x1
+#define MX6QDL_PAD_NANDF_CS2__EIM_CRE               0x27c 0x664 0x000 0x3 0x0
+#define MX6QDL_PAD_NANDF_CS2__CCM_CLKO2             0x27c 0x664 0x000 0x4 0x0
+#define MX6QDL_PAD_NANDF_CS2__GPIO6_IO15            0x27c 0x664 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS3__NAND_CE3_B            0x280 0x668 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS3__IPU1_SISG1            0x280 0x668 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CS3__ESAI_TX1              0x280 0x668 0x848 0x2 0x1
+#define MX6QDL_PAD_NANDF_CS3__EIM_ADDR26            0x280 0x668 0x000 0x3 0x0
+#define MX6QDL_PAD_NANDF_CS3__GPIO6_IO16            0x280 0x668 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS3__I2C4_SDA              0x280 0x668 0x884 0x9 0x2
+#define MX6QDL_PAD_NANDF_D0__NAND_DATA00            0x284 0x66c 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D0__SD1_DATA4              0x284 0x66c 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D0__GPIO2_IO00             0x284 0x66c 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D1__NAND_DATA01            0x288 0x670 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D1__SD1_DATA5              0x288 0x670 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D1__GPIO2_IO01             0x288 0x670 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D2__NAND_DATA02            0x28c 0x674 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D2__SD1_DATA6              0x28c 0x674 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D2__GPIO2_IO02             0x28c 0x674 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D3__NAND_DATA03            0x290 0x678 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D3__SD1_DATA7              0x290 0x678 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D3__GPIO2_IO03             0x290 0x678 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D4__NAND_DATA04            0x294 0x67c 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D4__SD2_DATA4              0x294 0x67c 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D4__GPIO2_IO04             0x294 0x67c 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D5__NAND_DATA05            0x298 0x680 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D5__SD2_DATA5              0x298 0x680 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D5__GPIO2_IO05             0x298 0x680 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D6__NAND_DATA06            0x29c 0x684 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D6__SD2_DATA6              0x29c 0x684 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D6__GPIO2_IO06             0x29c 0x684 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D7__NAND_DATA07            0x2a0 0x688 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D7__SD2_DATA7              0x2a0 0x688 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D7__GPIO2_IO07             0x2a0 0x688 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_RB0__NAND_READY_B          0x2a4 0x68c 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_RB0__GPIO6_IO10            0x2a4 0x68c 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_WP_B__NAND_WP_B            0x2a8 0x690 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09           0x2a8 0x690 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_WP_B__I2C4_SCL             0x2a8 0x690 0x880 0x9 0x2
+#define MX6QDL_PAD_RGMII_RD0__HSI_RX_READY          0x2ac 0x694 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD0__RGMII_RD0             0x2ac 0x694 0x818 0x1 0x1
+#define MX6QDL_PAD_RGMII_RD0__GPIO6_IO25            0x2ac 0x694 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RD1__HSI_TX_FLAG           0x2b0 0x698 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD1__RGMII_RD1             0x2b0 0x698 0x81c 0x1 0x1
+#define MX6QDL_PAD_RGMII_RD1__GPIO6_IO27            0x2b0 0x698 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RD2__HSI_TX_DATA           0x2b4 0x69c 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD2__RGMII_RD2             0x2b4 0x69c 0x820 0x1 0x1
+#define MX6QDL_PAD_RGMII_RD2__GPIO6_IO28            0x2b4 0x69c 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RD3__HSI_TX_WAKE           0x2b8 0x6a0 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD3__RGMII_RD3             0x2b8 0x6a0 0x824 0x1 0x1
+#define MX6QDL_PAD_RGMII_RD3__GPIO6_IO29            0x2b8 0x6a0 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA        0x2bc 0x6a4 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL       0x2bc 0x6a4 0x828 0x1 0x1
+#define MX6QDL_PAD_RGMII_RX_CTL__GPIO6_IO24         0x2bc 0x6a4 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE         0x2c0 0x6a8 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RXC__RGMII_RXC             0x2c0 0x6a8 0x814 0x1 0x1
+#define MX6QDL_PAD_RGMII_RXC__GPIO6_IO30            0x2c0 0x6a8 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD0__HSI_TX_READY          0x2c4 0x6ac 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD0__RGMII_TD0             0x2c4 0x6ac 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD0__GPIO6_IO20            0x2c4 0x6ac 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD1__HSI_RX_FLAG           0x2c8 0x6b0 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD1__RGMII_TD1             0x2c8 0x6b0 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD1__GPIO6_IO21            0x2c8 0x6b0 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD2__HSI_RX_DATA           0x2cc 0x6b4 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD2__RGMII_TD2             0x2cc 0x6b4 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD2__GPIO6_IO22            0x2cc 0x6b4 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD3__HSI_RX_WAKE           0x2d0 0x6b8 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD3__RGMII_TD3             0x2d0 0x6b8 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD3__GPIO6_IO23            0x2d0 0x6b8 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE      0x2d4 0x6bc 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL       0x2d4 0x6bc 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__GPIO6_IO26         0x2d4 0x6bc 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__ENET_REF_CLK       0x2d4 0x6bc 0x80c 0x7 0x1
+#define MX6QDL_PAD_RGMII_TXC__USB_H2_DATA           0x2d8 0x6c0 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TXC__RGMII_TXC             0x2d8 0x6c0 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TXC__SPDIF_EXT_CLK         0x2d8 0x6c0 0x8f4 0x2 0x1
+#define MX6QDL_PAD_RGMII_TXC__GPIO6_IO19            0x2d8 0x6c0 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x2d8 0x6c0 0x000 0x7 0x0
+#define MX6QDL_PAD_SD1_CLK__SD1_CLK                 0x2dc 0x6c4 0x928 0x0 0x1
+#define MX6QDL_PAD_SD1_CLK__GPT_CLKIN               0x2dc 0x6c4 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_CLK__GPIO1_IO20              0x2dc 0x6c4 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_CMD__SD1_CMD                 0x2e0 0x6c8 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_CMD__PWM4_OUT                0x2e0 0x6c8 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_CMD__GPT_COMPARE1            0x2e0 0x6c8 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_CMD__GPIO1_IO18              0x2e0 0x6c8 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT0__SD1_DATA0              0x2e4 0x6cc 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT0__GPT_CAPTURE1           0x2e4 0x6cc 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT0__GPIO1_IO16             0x2e4 0x6cc 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT1__SD1_DATA1              0x2e8 0x6d0 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT1__PWM3_OUT               0x2e8 0x6d0 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_DAT1__GPT_CAPTURE2           0x2e8 0x6d0 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT1__GPIO1_IO17             0x2e8 0x6d0 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT2__SD1_DATA2              0x2ec 0x6d4 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT2__GPT_COMPARE2           0x2ec 0x6d4 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_DAT2__PWM2_OUT               0x2ec 0x6d4 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT2__WDOG1_B                0x2ec 0x6d4 0x000 0x4 0x0
+#define MX6QDL_PAD_SD1_DAT2__GPIO1_IO19             0x2ec 0x6d4 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x2ec 0x6d4 0x000 0x6 0x0
+#define MX6QDL_PAD_SD1_DAT3__SD1_DATA3              0x2f0 0x6d8 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT3__GPT_COMPARE3           0x2f0 0x6d8 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_DAT3__PWM1_OUT               0x2f0 0x6d8 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT3__WDOG2_B                0x2f0 0x6d8 0x000 0x4 0x0
+#define MX6QDL_PAD_SD1_DAT3__GPIO1_IO21             0x2f0 0x6d8 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT3__WDOG2_RESET_B_DEB      0x2f0 0x6d8 0x000 0x6 0x0
+#define MX6QDL_PAD_SD2_CLK__SD2_CLK                 0x2f4 0x6dc 0x930 0x0 0x1
+#define MX6QDL_PAD_SD2_CLK__KEY_COL5                0x2f4 0x6dc 0x8c0 0x2 0x3
+#define MX6QDL_PAD_SD2_CLK__AUD4_RXFS               0x2f4 0x6dc 0x7a4 0x3 0x1
+#define MX6QDL_PAD_SD2_CLK__GPIO1_IO10              0x2f4 0x6dc 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_CMD__SD2_CMD                 0x2f8 0x6e0 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_CMD__KEY_ROW5                0x2f8 0x6e0 0x8cc 0x2 0x2
+#define MX6QDL_PAD_SD2_CMD__AUD4_RXC                0x2f8 0x6e0 0x7a0 0x3 0x1
+#define MX6QDL_PAD_SD2_CMD__GPIO1_IO11              0x2f8 0x6e0 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT0__SD2_DATA0              0x2fc 0x6e4 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT0__AUD4_RXD               0x2fc 0x6e4 0x798 0x3 0x1
+#define MX6QDL_PAD_SD2_DAT0__KEY_ROW7               0x2fc 0x6e4 0x8d4 0x4 0x2
+#define MX6QDL_PAD_SD2_DAT0__GPIO1_IO15             0x2fc 0x6e4 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT0__DCIC2_OUT              0x2fc 0x6e4 0x000 0x6 0x0
+#define MX6QDL_PAD_SD2_DAT1__SD2_DATA1              0x300 0x6e8 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT1__EIM_CS2_B              0x300 0x6e8 0x000 0x2 0x0
+#define MX6QDL_PAD_SD2_DAT1__AUD4_TXFS              0x300 0x6e8 0x7ac 0x3 0x1
+#define MX6QDL_PAD_SD2_DAT1__KEY_COL7               0x300 0x6e8 0x8c8 0x4 0x2
+#define MX6QDL_PAD_SD2_DAT1__GPIO1_IO14             0x300 0x6e8 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT2__SD2_DATA2              0x304 0x6ec 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT2__EIM_CS3_B              0x304 0x6ec 0x000 0x2 0x0
+#define MX6QDL_PAD_SD2_DAT2__AUD4_TXD               0x304 0x6ec 0x79c 0x3 0x1
+#define MX6QDL_PAD_SD2_DAT2__KEY_ROW6               0x304 0x6ec 0x8d0 0x4 0x2
+#define MX6QDL_PAD_SD2_DAT2__GPIO1_IO13             0x304 0x6ec 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT3__SD2_DATA3              0x308 0x6f0 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT3__KEY_COL6               0x308 0x6f0 0x8c4 0x2 0x2
+#define MX6QDL_PAD_SD2_DAT3__AUD4_TXC               0x308 0x6f0 0x7a8 0x3 0x1
+#define MX6QDL_PAD_SD2_DAT3__GPIO1_IO12             0x308 0x6f0 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_CLK__SD3_CLK                 0x30c 0x6f4 0x934 0x0 0x1
+#define MX6QDL_PAD_SD3_CLK__UART2_RTS_B             0x30c 0x6f4 0x900 0x1 0x2
+#define MX6QDL_PAD_SD3_CLK__UART2_CTS_B             0x30c 0x6f4 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX             0x30c 0x6f4 0x7c8 0x2 0x2
+#define MX6QDL_PAD_SD3_CLK__GPIO7_IO03              0x30c 0x6f4 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_CMD__SD3_CMD                 0x310 0x6f8 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_CMD__UART2_CTS_B             0x310 0x6f8 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_CMD__UART2_RTS_B             0x310 0x6f8 0x900 0x1 0x3
+#define MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX             0x310 0x6f8 0x000 0x2 0x0
+#define MX6QDL_PAD_SD3_CMD__GPIO7_IO02              0x310 0x6f8 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT0__SD3_DATA0              0x314 0x6fc 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT0__UART1_CTS_B            0x314 0x6fc 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT0__UART1_RTS_B            0x314 0x6fc 0x8f8 0x1 0x2
+#define MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX            0x314 0x6fc 0x000 0x2 0x0
+#define MX6QDL_PAD_SD3_DAT0__GPIO7_IO04             0x314 0x6fc 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT1__SD3_DATA1              0x318 0x700 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT1__UART1_RTS_B            0x318 0x700 0x8f8 0x1 0x3
+#define MX6QDL_PAD_SD3_DAT1__UART1_CTS_B            0x318 0x700 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX            0x318 0x700 0x7cc 0x2 0x1
+#define MX6QDL_PAD_SD3_DAT1__GPIO7_IO05             0x318 0x700 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT2__SD3_DATA2              0x31c 0x704 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT2__GPIO7_IO06             0x31c 0x704 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT3__SD3_DATA3              0x320 0x708 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT3__UART3_CTS_B            0x320 0x708 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT3__UART3_RTS_B            0x320 0x708 0x908 0x1 0x4
+#define MX6QDL_PAD_SD3_DAT3__GPIO7_IO07             0x320 0x708 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT4__SD3_DATA4              0x324 0x70c 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT4__UART2_RX_DATA          0x324 0x70c 0x904 0x1 0x4
+#define MX6QDL_PAD_SD3_DAT4__UART2_TX_DATA          0x324 0x70c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT4__GPIO7_IO01             0x324 0x70c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT5__SD3_DATA5              0x328 0x710 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT5__UART2_TX_DATA          0x328 0x710 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT5__UART2_RX_DATA          0x328 0x710 0x904 0x1 0x5
+#define MX6QDL_PAD_SD3_DAT5__GPIO7_IO00             0x328 0x710 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT6__SD3_DATA6              0x32c 0x714 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA          0x32c 0x714 0x8fc 0x1 0x2
+#define MX6QDL_PAD_SD3_DAT6__UART1_TX_DATA          0x32c 0x714 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT6__GPIO6_IO18             0x32c 0x714 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT7__SD3_DATA7              0x330 0x718 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA          0x330 0x718 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT7__UART1_RX_DATA          0x330 0x718 0x8fc 0x1 0x3
+#define MX6QDL_PAD_SD3_DAT7__GPIO6_IO17             0x330 0x718 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_RST__SD3_RESET               0x334 0x71c 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_RST__UART3_RTS_B             0x334 0x71c 0x908 0x1 0x5
+#define MX6QDL_PAD_SD3_RST__UART3_CTS_B             0x334 0x71c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_RST__GPIO7_IO08              0x334 0x71c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_CLK__SD4_CLK                 0x338 0x720 0x938 0x0 0x1
+#define MX6QDL_PAD_SD4_CLK__NAND_WE_B               0x338 0x720 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_CLK__UART3_RX_DATA           0x338 0x720 0x90c 0x2 0x2
+#define MX6QDL_PAD_SD4_CLK__UART3_TX_DATA           0x338 0x720 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_CLK__GPIO7_IO10              0x338 0x720 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_CMD__SD4_CMD                 0x33c 0x724 0x000 0x0 0x0
+#define MX6QDL_PAD_SD4_CMD__NAND_RE_B               0x33c 0x724 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_CMD__UART3_TX_DATA           0x33c 0x724 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_CMD__UART3_RX_DATA           0x33c 0x724 0x90c 0x2 0x3
+#define MX6QDL_PAD_SD4_CMD__GPIO7_IO09              0x33c 0x724 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT0__SD4_DATA0              0x340 0x728 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT0__NAND_DQS               0x340 0x728 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT0__GPIO2_IO08             0x340 0x728 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT1__SD4_DATA1              0x344 0x72c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT1__PWM3_OUT               0x344 0x72c 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT1__GPIO2_IO09             0x344 0x72c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT2__SD4_DATA2              0x348 0x730 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT2__PWM4_OUT               0x348 0x730 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT2__GPIO2_IO10             0x348 0x730 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT3__SD4_DATA3              0x34c 0x734 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT3__GPIO2_IO11             0x34c 0x734 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT4__SD4_DATA4              0x350 0x738 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA          0x350 0x738 0x904 0x2 0x6
+#define MX6QDL_PAD_SD4_DAT4__UART2_TX_DATA          0x350 0x738 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT4__GPIO2_IO12             0x350 0x738 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT5__SD4_DATA5              0x354 0x73c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT5__UART2_RTS_B            0x354 0x73c 0x900 0x2 0x4
+#define MX6QDL_PAD_SD4_DAT5__UART2_CTS_B            0x354 0x73c 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT5__GPIO2_IO13             0x354 0x73c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT6__SD4_DATA6              0x358 0x740 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT6__UART2_CTS_B            0x358 0x740 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT6__UART2_RTS_B            0x358 0x740 0x900 0x2 0x5
+#define MX6QDL_PAD_SD4_DAT6__GPIO2_IO14             0x358 0x740 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT7__SD4_DATA7              0x35c 0x744 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA          0x35c 0x744 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT7__UART2_RX_DATA          0x35c 0x744 0x904 0x2 0x7
+#define MX6QDL_PAD_SD4_DAT7__GPIO2_IO15             0x35c 0x744 0x000 0x5 0x0
 
 #endif /* __DTS_IMX6DL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto.dts b/arch/arm/boot/dts/imx6dl-sabreauto.dts
index 95da711..a6ce7b4 100644
--- a/arch/arm/boot/dts/imx6dl-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6dl-sabreauto.dts
@@ -15,25 +15,3 @@
 	model = "Freescale i.MX6 DualLite/Solo SABRE Automotive Board";
 	compatible = "fsl,imx6dl-sabreauto", "fsl,imx6dl";
 };
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6DL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
-				MX6DL_PAD_SD2_DAT2__GPIO1_IO13  0x80000000
-			>;
-		};
-	};
-
-	ecspi1 {
-		pinctrl_ecspi1_sabreauto: ecspi1-sabreauto {
-			fsl,pins = <
-				MX6DL_PAD_EIM_D19__GPIO3_IO19  0x80000000
-			>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd.dts b/arch/arm/boot/dts/imx6dl-sabresd.dts
index 8989df2..1e45f2f 100644
--- a/arch/arm/boot/dts/imx6dl-sabresd.dts
+++ b/arch/arm/boot/dts/imx6dl-sabresd.dts
@@ -15,22 +15,3 @@
 	model = "Freescale i.MX6 DualLite SABRE Smart Device Board";
 	compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl";
 };
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6DL_PAD_GPIO_4__GPIO1_IO04   0x80000000
-				MX6DL_PAD_GPIO_5__GPIO1_IO05   0x80000000
-				MX6DL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
-				MX6DL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
-				MX6DL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
-				MX6DL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
-				MX6DL_PAD_GPIO_0__CCM_CLKO1    0x130b0
-			>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx6dl-wandboard.dts b/arch/arm/boot/dts/imx6dl-wandboard.dts
index bfc59c3..e672891 100644
--- a/arch/arm/boot/dts/imx6dl-wandboard.dts
+++ b/arch/arm/boot/dts/imx6dl-wandboard.dts
@@ -10,6 +10,7 @@
  */
 /dts-v1/;
 #include "imx6dl.dtsi"
+#include "imx6qdl-wandboard.dtsi"
 
 / {
 	model = "Wandboard i.MX6 Dual Lite Board";
@@ -19,26 +20,3 @@
 		reg = <0x10000000 0x40000000>;
 	};
 };
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
-	phy-mode = "rgmii";
-	status = "okay";
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&usbh1 {
-	status = "okay";
-};
-
-&usdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_2>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 2b3ecd6..9e8ae11 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -8,8 +8,8 @@
  *
  */
 
-#include "imx6qdl.dtsi"
 #include "imx6dl-pinfunc.h"
+#include "imx6qdl.dtsi"
 
 / {
 	cpus {
@@ -32,238 +32,15 @@
 	};
 
 	soc {
+		ocram: sram@00900000 {
+			compatible = "mmio-sram";
+			reg = <0x00900000 0x20000>;
+			clocks = <&clks 142>;
+		};
+
 		aips1: aips-bus@02000000 {
 			iomuxc: iomuxc@020e0000 {
 				compatible = "fsl,imx6dl-iomuxc";
-				reg = <0x020e0000 0x4000>;
-
-				audmux {
-					pinctrl_audmux_2: audmux-2 {
-						fsl,pins = <
-							MX6DL_PAD_CSI0_DAT7__AUD3_RXD  0x80000000
-							MX6DL_PAD_CSI0_DAT4__AUD3_TXC  0x80000000
-							MX6DL_PAD_CSI0_DAT5__AUD3_TXD  0x80000000
-							MX6DL_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							MX6DL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
-							MX6DL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
-							MX6DL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
-						>;
-					};
-				};
-
-				enet {
-					pinctrl_enet_1: enetgrp-1 {
-						fsl,pins = <
-							MX6DL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-							MX6DL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-							MX6DL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							MX6DL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-							MX6DL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-							MX6DL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-							MX6DL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-							MX6DL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-							MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6DL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6DL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6DL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6DL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6DL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6DL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-							MX6DL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
-						>;
-					};
-
-					pinctrl_enet_2: enetgrp-2 {
-						fsl,pins = <
-							MX6DL_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
-							MX6DL_PAD_KEY_COL2__ENET_MDC         0x1b0b0
-							MX6DL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							MX6DL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-							MX6DL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-							MX6DL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-							MX6DL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-							MX6DL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-							MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6DL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6DL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6DL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6DL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6DL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6DL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-						>;
-					};
-				};
-
-				gpmi-nand {
-					pinctrl_gpmi_nand_1: gpmi-nand-1 {
-						fsl,pins = <
-							MX6DL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
-							MX6DL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
-							MX6DL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
-							MX6DL_PAD_NANDF_RB0__NAND_READY_B 0xb000
-							MX6DL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
-							MX6DL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
-							MX6DL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
-							MX6DL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
-							MX6DL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
-							MX6DL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
-							MX6DL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
-							MX6DL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
-							MX6DL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
-							MX6DL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
-							MX6DL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
-							MX6DL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
-							MX6DL_PAD_SD4_DAT0__NAND_DQS      0x00b1
-						>;
-					};
-				};
-
-				i2c1 {
-					pinctrl_i2c1_2: i2c1grp-2 {
-						fsl,pins = <
-							MX6DL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
-							MX6DL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							MX6DL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
-							MX6DL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				uart4 {
-					pinctrl_uart4_1: uart4grp-1 {
-						fsl,pins = <
-							MX6DL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
-							MX6DL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				usbotg {
-					pinctrl_usbotg_2: usbotggrp-2 {
-						fsl,pins = <
-							MX6DL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
-						>;
-					};
-				};
-
-				usdhc2 {
-					pinctrl_usdhc2_1: usdhc2grp-1 {
-						fsl,pins = <
-							MX6DL_PAD_SD2_CMD__SD2_CMD    0x17059
-							MX6DL_PAD_SD2_CLK__SD2_CLK    0x10059
-							MX6DL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-							MX6DL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-							MX6DL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-							MX6DL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-							MX6DL_PAD_NANDF_D4__SD2_DATA4 0x17059
-							MX6DL_PAD_NANDF_D5__SD2_DATA5 0x17059
-							MX6DL_PAD_NANDF_D6__SD2_DATA6 0x17059
-							MX6DL_PAD_NANDF_D7__SD2_DATA7 0x17059
-						>;
-					};
-				};
-
-				usdhc3 {
-					pinctrl_usdhc3_1: usdhc3grp-1 {
-						fsl,pins = <
-							MX6DL_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6DL_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6DL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6DL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6DL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6DL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-							MX6DL_PAD_SD3_DAT4__SD3_DATA4 0x17059
-							MX6DL_PAD_SD3_DAT5__SD3_DATA5 0x17059
-							MX6DL_PAD_SD3_DAT6__SD3_DATA6 0x17059
-							MX6DL_PAD_SD3_DAT7__SD3_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc3_2: usdhc3grp_2 {
-						fsl,pins = <
-							MX6DL_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6DL_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6DL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6DL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6DL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6DL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-						>;
-					};
-				};
-
-				weim {
-					pinctrl_weim_cs0_1: weim_cs0grp-1 {
-						fsl,pins = <
-							MX6DL_PAD_EIM_CS0__EIM_CS0_B   0xb0b1
-						>;
-					};
-
-					pinctrl_weim_nor_1: weim_norgrp-1 {
-						fsl,pins = <
-							MX6DL_PAD_EIM_OE__EIM_OE_B     0xb0b1
-							MX6DL_PAD_EIM_RW__EIM_RW       0xb0b1
-							MX6DL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
-							/* data */
-							MX6DL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
-							MX6DL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
-							MX6DL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
-							MX6DL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
-							MX6DL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
-							MX6DL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
-							MX6DL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
-							MX6DL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
-							MX6DL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
-							MX6DL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
-							MX6DL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
-							MX6DL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
-							MX6DL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
-							MX6DL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
-							MX6DL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
-							MX6DL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
-							/* address */
-							MX6DL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
-							MX6DL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
-							MX6DL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
-							MX6DL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
-							MX6DL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
-							MX6DL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
-							MX6DL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
-							MX6DL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
-							MX6DL_PAD_EIM_DA15__EIM_AD15  0xb0b1
-							MX6DL_PAD_EIM_DA14__EIM_AD14  0xb0b1
-							MX6DL_PAD_EIM_DA13__EIM_AD13  0xb0b1
-							MX6DL_PAD_EIM_DA12__EIM_AD12  0xb0b1
-							MX6DL_PAD_EIM_DA11__EIM_AD11  0xb0b1
-							MX6DL_PAD_EIM_DA10__EIM_AD10  0xb0b1
-							MX6DL_PAD_EIM_DA9__EIM_AD09   0xb0b1
-							MX6DL_PAD_EIM_DA8__EIM_AD08   0xb0b1
-							MX6DL_PAD_EIM_DA7__EIM_AD07   0xb0b1
-							MX6DL_PAD_EIM_DA6__EIM_AD06   0xb0b1
-							MX6DL_PAD_EIM_DA5__EIM_AD05   0xb0b1
-							MX6DL_PAD_EIM_DA4__EIM_AD04   0xb0b1
-							MX6DL_PAD_EIM_DA3__EIM_AD03   0xb0b1
-							MX6DL_PAD_EIM_DA2__EIM_AD02   0xb0b1
-							MX6DL_PAD_EIM_DA1__EIM_AD01   0xb0b1
-							MX6DL_PAD_EIM_DA0__EIM_AD00   0xb0b1
-						>;
-					};
-
-				};
-
 			};
 
 			pxp: pxp@020f0000 {
@@ -294,3 +71,20 @@
 		};
 	};
 };
+
+&ldb {
+	clocks = <&clks 33>, <&clks 34>,
+		 <&clks 39>, <&clks 40>,
+		 <&clks 135>, <&clks 136>;
+	clock-names = "di0_pll", "di1_pll",
+		      "di0_sel", "di1_sel",
+		      "di0", "di1";
+
+	lvds-channel@0 {
+		crtcs = <&ipu1 0>, <&ipu1 1>;
+	};
+
+	lvds-channel@1 {
+		crtcs = <&ipu1 0>, <&ipu1 1>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts
index 4e54fde..edf1bd9 100644
--- a/arch/arm/boot/dts/imx6q-arm2.dts
+++ b/arch/arm/boot/dts/imx6q-arm2.dts
@@ -57,7 +57,7 @@
 	hog {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
-				MX6Q_PAD_EIM_D25__GPIO3_IO25 0x80000000
+				MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
 			>;
 		};
 	};
@@ -65,8 +65,8 @@
 	arm2 {
 		pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
 			fsl,pins = <
-				MX6Q_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
-				MX6Q_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
+				MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
 			>;
 		};
 	};
@@ -97,6 +97,14 @@
 	status = "okay";
 };
 
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_2>;
+	fsl,dte-mode;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart4_1>;
diff --git a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
index f5e1981..1a3b50d 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
@@ -20,6 +20,110 @@
 	};
 };
 
+&ecspi3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3_1>;
+	status = "okay";
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 24 0>;
+
+	flash@0 {
+		compatible = "m25p80";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_1>;
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "atmel,24c32";
+		reg = <0x50>;
+	};
+
+	pmic@58 {
+		compatible = "dialog,da9063";
+		reg = <0x58>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <17 0x8>; /* active-low GPIO4_17 */
+
+		regulators {
+			vddcore_reg: bcore1 {
+				regulator-min-microvolt = <730000>;
+				regulator-max-microvolt = <1380000>;
+				regulator-always-on;
+			};
+
+			vddsoc_reg: bcore2 {
+				regulator-min-microvolt = <730000>;
+				regulator-max-microvolt = <1380000>;
+				regulator-always-on;
+			};
+
+			vdd_ddr3_reg: bpro {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+			};
+
+			vdd_3v3_reg: bperi {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_buckmem_reg: bmem {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_eth_reg: bio {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vdd_eth_io_reg: ldo4 {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-always-on;
+			};
+
+			vdd_mx6_snvs_reg: ldo5 {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			vdd_3v3_pmic_io_reg: ldo6 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_sd0_reg: ldo9 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vdd_sd1_reg: ldo10 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vdd_mx6_high_reg: ldo11 {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -27,7 +131,9 @@
 	hog {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
-				MX6Q_PAD_EIM_D23__GPIO3_IO23    0x80000000
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
+				MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
+				MX6QDL_PAD_DI0_PIN15__GPIO4_IO17  0x80000000 /* PMIC interrupt */
 			>;
 		};
 	};
@@ -35,8 +141,8 @@
 	pfla02 {
 		pinctrl_usdhc3_pfla02: usdhc3grp-pfla02 {
 			fsl,pins = <
-				MX6Q_PAD_ENET_RXD0__GPIO1_IO27  0x80000000
-				MX6Q_PAD_ENET_TXD1__GPIO1_IO29  0x80000000
+				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
 			>;
 		};
 	};
diff --git a/arch/arm/boot/dts/imx6q-pinfunc.h b/arch/arm/boot/dts/imx6q-pinfunc.h
index faea6e1..c0e38a4 100644
--- a/arch/arm/boot/dts/imx6q-pinfunc.h
+++ b/arch/arm/boot/dts/imx6q-pinfunc.h
@@ -14,1028 +14,1032 @@
  * The pin function ID is a tuple of
  * <mux_reg conf_reg input_reg mux_mode input_val>
  */
-#define MX6Q_PAD_SD2_DAT1__SD2_DATA1              0x04c 0x360 0x000 0x0 0x0
-#define MX6Q_PAD_SD2_DAT1__ECSPI5_SS0             0x04c 0x360 0x834 0x1 0x0
-#define MX6Q_PAD_SD2_DAT1__EIM_CS2_B              0x04c 0x360 0x000 0x2 0x0
-#define MX6Q_PAD_SD2_DAT1__AUD4_TXFS              0x04c 0x360 0x7c8 0x3 0x0
-#define MX6Q_PAD_SD2_DAT1__KEY_COL7               0x04c 0x360 0x8f0 0x4 0x0
-#define MX6Q_PAD_SD2_DAT1__GPIO1_IO14             0x04c 0x360 0x000 0x5 0x0
-#define MX6Q_PAD_SD2_DAT2__SD2_DATA2              0x050 0x364 0x000 0x0 0x0
-#define MX6Q_PAD_SD2_DAT2__ECSPI5_SS1             0x050 0x364 0x838 0x1 0x0
-#define MX6Q_PAD_SD2_DAT2__EIM_CS3_B              0x050 0x364 0x000 0x2 0x0
-#define MX6Q_PAD_SD2_DAT2__AUD4_TXD               0x050 0x364 0x7b8 0x3 0x0
-#define MX6Q_PAD_SD2_DAT2__KEY_ROW6               0x050 0x364 0x8f8 0x4 0x0
-#define MX6Q_PAD_SD2_DAT2__GPIO1_IO13             0x050 0x364 0x000 0x5 0x0
-#define MX6Q_PAD_SD2_DAT0__SD2_DATA0              0x054 0x368 0x000 0x0 0x0
-#define MX6Q_PAD_SD2_DAT0__ECSPI5_MISO            0x054 0x368 0x82c 0x1 0x0
-#define MX6Q_PAD_SD2_DAT0__AUD4_RXD               0x054 0x368 0x7b4 0x3 0x0
-#define MX6Q_PAD_SD2_DAT0__KEY_ROW7               0x054 0x368 0x8fc 0x4 0x0
-#define MX6Q_PAD_SD2_DAT0__GPIO1_IO15             0x054 0x368 0x000 0x5 0x0
-#define MX6Q_PAD_SD2_DAT0__DCIC2_OUT              0x054 0x368 0x000 0x6 0x0
-#define MX6Q_PAD_RGMII_TXC__USB_H2_DATA           0x058 0x36c 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_TXC__RGMII_TXC             0x058 0x36c 0x000 0x1 0x0
-#define MX6Q_PAD_RGMII_TXC__SPDIF_EXT_CLK         0x058 0x36c 0x918 0x2 0x0
-#define MX6Q_PAD_RGMII_TXC__GPIO6_IO19            0x058 0x36c 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x058 0x36c 0x000 0x7 0x0
-#define MX6Q_PAD_RGMII_TD0__HSI_TX_READY          0x05c 0x370 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_TD0__RGMII_TD0             0x05c 0x370 0x000 0x1 0x0
-#define MX6Q_PAD_RGMII_TD0__GPIO6_IO20            0x05c 0x370 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_TD1__HSI_RX_FLAG           0x060 0x374 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_TD1__RGMII_TD1             0x060 0x374 0x000 0x1 0x0
-#define MX6Q_PAD_RGMII_TD1__GPIO6_IO21            0x060 0x374 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_TD2__HSI_RX_DATA           0x064 0x378 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_TD2__RGMII_TD2             0x064 0x378 0x000 0x1 0x0
-#define MX6Q_PAD_RGMII_TD2__GPIO6_IO22            0x064 0x378 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_TD3__HSI_RX_WAKE           0x068 0x37c 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_TD3__RGMII_TD3             0x068 0x37c 0x000 0x1 0x0
-#define MX6Q_PAD_RGMII_TD3__GPIO6_IO23            0x068 0x37c 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_RX_CTL__USB_H3_DATA        0x06c 0x380 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL       0x06c 0x380 0x858 0x1 0x0
-#define MX6Q_PAD_RGMII_RX_CTL__GPIO6_IO24         0x06c 0x380 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_RD0__HSI_RX_READY          0x070 0x384 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_RD0__RGMII_RD0             0x070 0x384 0x848 0x1 0x0
-#define MX6Q_PAD_RGMII_RD0__GPIO6_IO25            0x070 0x384 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_TX_CTL__USB_H2_STROBE      0x074 0x388 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL       0x074 0x388 0x000 0x1 0x0
-#define MX6Q_PAD_RGMII_TX_CTL__GPIO6_IO26         0x074 0x388 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_TX_CTL__ENET_REF_CLK       0x074 0x388 0x83c 0x7 0x0
-#define MX6Q_PAD_RGMII_RD1__HSI_TX_FLAG           0x078 0x38c 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_RD1__RGMII_RD1             0x078 0x38c 0x84c 0x1 0x0
-#define MX6Q_PAD_RGMII_RD1__GPIO6_IO27            0x078 0x38c 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_RD2__HSI_TX_DATA           0x07c 0x390 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_RD2__RGMII_RD2             0x07c 0x390 0x850 0x1 0x0
-#define MX6Q_PAD_RGMII_RD2__GPIO6_IO28            0x07c 0x390 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_RD3__HSI_TX_WAKE           0x080 0x394 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_RD3__RGMII_RD3             0x080 0x394 0x854 0x1 0x0
-#define MX6Q_PAD_RGMII_RD3__GPIO6_IO29            0x080 0x394 0x000 0x5 0x0
-#define MX6Q_PAD_RGMII_RXC__USB_H3_STROBE         0x084 0x398 0x000 0x0 0x0
-#define MX6Q_PAD_RGMII_RXC__RGMII_RXC             0x084 0x398 0x844 0x1 0x0
-#define MX6Q_PAD_RGMII_RXC__GPIO6_IO30            0x084 0x398 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A25__EIM_ADDR25              0x088 0x39c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A25__ECSPI4_SS1              0x088 0x39c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A25__ECSPI2_RDY              0x088 0x39c 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12          0x088 0x39c 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS          0x088 0x39c 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_A25__GPIO5_IO02              0x088 0x39c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE        0x088 0x39c 0x88c 0x6 0x0
-#define MX6Q_PAD_EIM_EB2__EIM_EB2_B               0x08c 0x3a0 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_EB2__ECSPI1_SS0              0x08c 0x3a0 0x800 0x1 0x0
-#define MX6Q_PAD_EIM_EB2__IPU2_CSI1_DATA19        0x08c 0x3a0 0x8d4 0x3 0x0
-#define MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL         0x08c 0x3a0 0x890 0x4 0x0
-#define MX6Q_PAD_EIM_EB2__GPIO2_IO30              0x08c 0x3a0 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_EB2__I2C2_SCL                0x08c 0x3a0 0x8a0 0x6 0x0
-#define MX6Q_PAD_EIM_EB2__SRC_BOOT_CFG30          0x08c 0x3a0 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D16__EIM_DATA16              0x090 0x3a4 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D16__ECSPI1_SCLK             0x090 0x3a4 0x7f4 0x1 0x0
-#define MX6Q_PAD_EIM_D16__IPU1_DI0_PIN05          0x090 0x3a4 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D16__IPU2_CSI1_DATA18        0x090 0x3a4 0x8d0 0x3 0x0
-#define MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA         0x090 0x3a4 0x894 0x4 0x0
-#define MX6Q_PAD_EIM_D16__GPIO3_IO16              0x090 0x3a4 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D16__I2C2_SDA                0x090 0x3a4 0x8a4 0x6 0x0
-#define MX6Q_PAD_EIM_D17__EIM_DATA17              0x094 0x3a8 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D17__ECSPI1_MISO             0x094 0x3a8 0x7f8 0x1 0x0
-#define MX6Q_PAD_EIM_D17__IPU1_DI0_PIN06          0x094 0x3a8 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK        0x094 0x3a8 0x8e0 0x3 0x0
-#define MX6Q_PAD_EIM_D17__DCIC1_OUT               0x094 0x3a8 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D17__GPIO3_IO17              0x094 0x3a8 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D17__I2C3_SCL                0x094 0x3a8 0x8a8 0x6 0x0
-#define MX6Q_PAD_EIM_D18__EIM_DATA18              0x098 0x3ac 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D18__ECSPI1_MOSI             0x098 0x3ac 0x7fc 0x1 0x0
-#define MX6Q_PAD_EIM_D18__IPU1_DI0_PIN07          0x098 0x3ac 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D18__IPU2_CSI1_DATA17        0x098 0x3ac 0x8cc 0x3 0x0
-#define MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS          0x098 0x3ac 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D18__GPIO3_IO18              0x098 0x3ac 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D18__I2C3_SDA                0x098 0x3ac 0x8ac 0x6 0x0
-#define MX6Q_PAD_EIM_D19__EIM_DATA19              0x09c 0x3b0 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D19__ECSPI1_SS1              0x09c 0x3b0 0x804 0x1 0x0
-#define MX6Q_PAD_EIM_D19__IPU1_DI0_PIN08          0x09c 0x3b0 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D19__IPU2_CSI1_DATA16        0x09c 0x3b0 0x8c8 0x3 0x0
-#define MX6Q_PAD_EIM_D19__UART1_CTS_B             0x09c 0x3b0 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D19__UART1_RTS_B             0x09c 0x3b0 0x91c 0x4 0x0
-#define MX6Q_PAD_EIM_D19__GPIO3_IO19              0x09c 0x3b0 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D19__EPIT1_OUT               0x09c 0x3b0 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D20__EIM_DATA20              0x0a0 0x3b4 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D20__ECSPI4_SS0              0x0a0 0x3b4 0x824 0x1 0x0
-#define MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16          0x0a0 0x3b4 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D20__IPU2_CSI1_DATA15        0x0a0 0x3b4 0x8c4 0x3 0x0
-#define MX6Q_PAD_EIM_D20__UART1_RTS_B             0x0a0 0x3b4 0x91c 0x4 0x1
-#define MX6Q_PAD_EIM_D20__UART1_CTS_B             0x0a0 0x3b4 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D20__GPIO3_IO20              0x0a0 0x3b4 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D20__EPIT2_OUT               0x0a0 0x3b4 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D21__EIM_DATA21              0x0a4 0x3b8 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D21__ECSPI4_SCLK             0x0a4 0x3b8 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17          0x0a4 0x3b8 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D21__IPU2_CSI1_DATA11        0x0a4 0x3b8 0x8b4 0x3 0x0
-#define MX6Q_PAD_EIM_D21__USB_OTG_OC              0x0a4 0x3b8 0x944 0x4 0x0
-#define MX6Q_PAD_EIM_D21__GPIO3_IO21              0x0a4 0x3b8 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D21__I2C1_SCL                0x0a4 0x3b8 0x898 0x6 0x0
-#define MX6Q_PAD_EIM_D21__SPDIF_IN                0x0a4 0x3b8 0x914 0x7 0x0
-#define MX6Q_PAD_EIM_D22__EIM_DATA22              0x0a8 0x3bc 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D22__ECSPI4_MISO             0x0a8 0x3bc 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D22__IPU1_DI0_PIN01          0x0a8 0x3bc 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D22__IPU2_CSI1_DATA10        0x0a8 0x3bc 0x8b0 0x3 0x0
-#define MX6Q_PAD_EIM_D22__USB_OTG_PWR             0x0a8 0x3bc 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D22__GPIO3_IO22              0x0a8 0x3bc 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D22__SPDIF_OUT               0x0a8 0x3bc 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D23__EIM_DATA23              0x0ac 0x3c0 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS          0x0ac 0x3c0 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D23__UART3_CTS_B             0x0ac 0x3c0 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D23__UART3_RTS_B             0x0ac 0x3c0 0x92c 0x2 0x0
-#define MX6Q_PAD_EIM_D23__UART1_DCD_B             0x0ac 0x3c0 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN       0x0ac 0x3c0 0x8d8 0x4 0x0
-#define MX6Q_PAD_EIM_D23__GPIO3_IO23              0x0ac 0x3c0 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D23__IPU1_DI1_PIN02          0x0ac 0x3c0 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14          0x0ac 0x3c0 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_EB3__EIM_EB3_B               0x0b0 0x3c4 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_EB3__ECSPI4_RDY              0x0b0 0x3c4 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_EB3__UART3_RTS_B             0x0b0 0x3c4 0x92c 0x2 0x1
-#define MX6Q_PAD_EIM_EB3__UART3_CTS_B             0x0b0 0x3c4 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_EB3__UART1_RI_B              0x0b0 0x3c4 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC         0x0b0 0x3c4 0x8dc 0x4 0x0
-#define MX6Q_PAD_EIM_EB3__GPIO2_IO31              0x0b0 0x3c4 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN03          0x0b0 0x3c4 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_EB3__SRC_BOOT_CFG31          0x0b0 0x3c4 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D24__EIM_DATA24              0x0b4 0x3c8 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D24__ECSPI4_SS2              0x0b4 0x3c8 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D24__UART3_TX_DATA           0x0b4 0x3c8 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D24__UART3_RX_DATA           0x0b4 0x3c8 0x930 0x2 0x0
-#define MX6Q_PAD_EIM_D24__ECSPI1_SS2              0x0b4 0x3c8 0x808 0x3 0x0
-#define MX6Q_PAD_EIM_D24__ECSPI2_SS2              0x0b4 0x3c8 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D24__GPIO3_IO24              0x0b4 0x3c8 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D24__AUD5_RXFS               0x0b4 0x3c8 0x7d8 0x6 0x0
-#define MX6Q_PAD_EIM_D24__UART1_DTR_B             0x0b4 0x3c8 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D25__EIM_DATA25              0x0b8 0x3cc 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D25__ECSPI4_SS3              0x0b8 0x3cc 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D25__UART3_RX_DATA           0x0b8 0x3cc 0x930 0x2 0x1
-#define MX6Q_PAD_EIM_D25__UART3_TX_DATA           0x0b8 0x3cc 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D25__ECSPI1_SS3              0x0b8 0x3cc 0x80c 0x3 0x0
-#define MX6Q_PAD_EIM_D25__ECSPI2_SS3              0x0b8 0x3cc 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D25__GPIO3_IO25              0x0b8 0x3cc 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D25__AUD5_RXC                0x0b8 0x3cc 0x7d4 0x6 0x0
-#define MX6Q_PAD_EIM_D25__UART1_DSR_B             0x0b8 0x3cc 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D26__EIM_DATA26              0x0bc 0x3d0 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11          0x0bc 0x3d0 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D26__IPU1_CSI0_DATA01        0x0bc 0x3d0 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D26__IPU2_CSI1_DATA14        0x0bc 0x3d0 0x8c0 0x3 0x0
-#define MX6Q_PAD_EIM_D26__UART2_TX_DATA           0x0bc 0x3d0 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D26__UART2_RX_DATA           0x0bc 0x3d0 0x928 0x4 0x0
-#define MX6Q_PAD_EIM_D26__GPIO3_IO26              0x0bc 0x3d0 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D26__IPU1_SISG2              0x0bc 0x3d0 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D26__IPU1_DISP1_DATA22       0x0bc 0x3d0 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D27__EIM_DATA27              0x0c0 0x3d4 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13          0x0c0 0x3d4 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D27__IPU1_CSI0_DATA00        0x0c0 0x3d4 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D27__IPU2_CSI1_DATA13        0x0c0 0x3d4 0x8bc 0x3 0x0
-#define MX6Q_PAD_EIM_D27__UART2_RX_DATA           0x0c0 0x3d4 0x928 0x4 0x1
-#define MX6Q_PAD_EIM_D27__UART2_TX_DATA           0x0c0 0x3d4 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D27__GPIO3_IO27              0x0c0 0x3d4 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D27__IPU1_SISG3              0x0c0 0x3d4 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D27__IPU1_DISP1_DATA23       0x0c0 0x3d4 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D28__EIM_DATA28              0x0c4 0x3d8 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D28__I2C1_SDA                0x0c4 0x3d8 0x89c 0x1 0x0
-#define MX6Q_PAD_EIM_D28__ECSPI4_MOSI             0x0c4 0x3d8 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D28__IPU2_CSI1_DATA12        0x0c4 0x3d8 0x8b8 0x3 0x0
-#define MX6Q_PAD_EIM_D28__UART2_CTS_B             0x0c4 0x3d8 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D28__UART2_RTS_B             0x0c4 0x3d8 0x924 0x4 0x0
-#define MX6Q_PAD_EIM_D28__GPIO3_IO28              0x0c4 0x3d8 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG           0x0c4 0x3d8 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13          0x0c4 0x3d8 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D29__EIM_DATA29              0x0c8 0x3dc 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15          0x0c8 0x3dc 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D29__ECSPI4_SS0              0x0c8 0x3dc 0x824 0x2 0x1
-#define MX6Q_PAD_EIM_D29__UART2_RTS_B             0x0c8 0x3dc 0x924 0x4 0x1
-#define MX6Q_PAD_EIM_D29__UART2_CTS_B             0x0c8 0x3dc 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D29__GPIO3_IO29              0x0c8 0x3dc 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC         0x0c8 0x3dc 0x8e4 0x6 0x0
-#define MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14          0x0c8 0x3dc 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_D30__EIM_DATA30              0x0cc 0x3e0 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D30__IPU1_DISP1_DATA21       0x0cc 0x3e0 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11          0x0cc 0x3e0 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D30__IPU1_CSI0_DATA03        0x0cc 0x3e0 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_D30__UART3_CTS_B             0x0cc 0x3e0 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D30__UART3_RTS_B             0x0cc 0x3e0 0x92c 0x4 0x2
-#define MX6Q_PAD_EIM_D30__GPIO3_IO30              0x0cc 0x3e0 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D30__USB_H1_OC               0x0cc 0x3e0 0x948 0x6 0x0
-#define MX6Q_PAD_EIM_D31__EIM_DATA31              0x0d0 0x3e4 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_D31__IPU1_DISP1_DATA20       0x0d0 0x3e4 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12          0x0d0 0x3e4 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_D31__IPU1_CSI0_DATA02        0x0d0 0x3e4 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_D31__UART3_RTS_B             0x0d0 0x3e4 0x92c 0x4 0x3
-#define MX6Q_PAD_EIM_D31__UART3_CTS_B             0x0d0 0x3e4 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_D31__GPIO3_IO31              0x0d0 0x3e4 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_D31__USB_H1_PWR              0x0d0 0x3e4 0x000 0x6 0x0
-#define MX6Q_PAD_EIM_A24__EIM_ADDR24              0x0d4 0x3e8 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A24__IPU1_DISP1_DATA19       0x0d4 0x3e8 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A24__IPU2_CSI1_DATA19        0x0d4 0x3e8 0x8d4 0x2 0x1
-#define MX6Q_PAD_EIM_A24__IPU2_SISG2              0x0d4 0x3e8 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_A24__IPU1_SISG2              0x0d4 0x3e8 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_A24__GPIO5_IO04              0x0d4 0x3e8 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A24__SRC_BOOT_CFG24          0x0d4 0x3e8 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A23__EIM_ADDR23              0x0d8 0x3ec 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A23__IPU1_DISP1_DATA18       0x0d8 0x3ec 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A23__IPU2_CSI1_DATA18        0x0d8 0x3ec 0x8d0 0x2 0x1
-#define MX6Q_PAD_EIM_A23__IPU2_SISG3              0x0d8 0x3ec 0x000 0x3 0x0
-#define MX6Q_PAD_EIM_A23__IPU1_SISG3              0x0d8 0x3ec 0x000 0x4 0x0
-#define MX6Q_PAD_EIM_A23__GPIO6_IO06              0x0d8 0x3ec 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A23__SRC_BOOT_CFG23          0x0d8 0x3ec 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A22__EIM_ADDR22              0x0dc 0x3f0 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A22__IPU1_DISP1_DATA17       0x0dc 0x3f0 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A22__IPU2_CSI1_DATA17        0x0dc 0x3f0 0x8cc 0x2 0x1
-#define MX6Q_PAD_EIM_A22__GPIO2_IO16              0x0dc 0x3f0 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A22__SRC_BOOT_CFG22          0x0dc 0x3f0 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A21__EIM_ADDR21              0x0e0 0x3f4 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A21__IPU1_DISP1_DATA16       0x0e0 0x3f4 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A21__IPU2_CSI1_DATA16        0x0e0 0x3f4 0x8c8 0x2 0x1
-#define MX6Q_PAD_EIM_A21__GPIO2_IO17              0x0e0 0x3f4 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A21__SRC_BOOT_CFG21          0x0e0 0x3f4 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A20__EIM_ADDR20              0x0e4 0x3f8 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A20__IPU1_DISP1_DATA15       0x0e4 0x3f8 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A20__IPU2_CSI1_DATA15        0x0e4 0x3f8 0x8c4 0x2 0x1
-#define MX6Q_PAD_EIM_A20__GPIO2_IO18              0x0e4 0x3f8 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A20__SRC_BOOT_CFG20          0x0e4 0x3f8 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A19__EIM_ADDR19              0x0e8 0x3fc 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A19__IPU1_DISP1_DATA14       0x0e8 0x3fc 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A19__IPU2_CSI1_DATA14        0x0e8 0x3fc 0x8c0 0x2 0x1
-#define MX6Q_PAD_EIM_A19__GPIO2_IO19              0x0e8 0x3fc 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A19__SRC_BOOT_CFG19          0x0e8 0x3fc 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A18__EIM_ADDR18              0x0ec 0x400 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A18__IPU1_DISP1_DATA13       0x0ec 0x400 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A18__IPU2_CSI1_DATA13        0x0ec 0x400 0x8bc 0x2 0x1
-#define MX6Q_PAD_EIM_A18__GPIO2_IO20              0x0ec 0x400 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A18__SRC_BOOT_CFG18          0x0ec 0x400 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A17__EIM_ADDR17              0x0f0 0x404 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A17__IPU1_DISP1_DATA12       0x0f0 0x404 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A17__IPU2_CSI1_DATA12        0x0f0 0x404 0x8b8 0x2 0x1
-#define MX6Q_PAD_EIM_A17__GPIO2_IO21              0x0f0 0x404 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A17__SRC_BOOT_CFG17          0x0f0 0x404 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_A16__EIM_ADDR16              0x0f4 0x408 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK       0x0f4 0x408 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK        0x0f4 0x408 0x8e0 0x2 0x1
-#define MX6Q_PAD_EIM_A16__GPIO2_IO22              0x0f4 0x408 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_A16__SRC_BOOT_CFG16          0x0f4 0x408 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_CS0__EIM_CS0_B               0x0f8 0x40c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN05          0x0f8 0x40c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_CS0__ECSPI2_SCLK             0x0f8 0x40c 0x810 0x2 0x0
-#define MX6Q_PAD_EIM_CS0__GPIO2_IO23              0x0f8 0x40c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_CS1__EIM_CS1_B               0x0fc 0x410 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN06          0x0fc 0x410 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_CS1__ECSPI2_MOSI             0x0fc 0x410 0x818 0x2 0x0
-#define MX6Q_PAD_EIM_CS1__GPIO2_IO24              0x0fc 0x410 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_OE__EIM_OE_B                 0x100 0x414 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_OE__IPU1_DI1_PIN07           0x100 0x414 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_OE__ECSPI2_MISO              0x100 0x414 0x814 0x2 0x0
-#define MX6Q_PAD_EIM_OE__GPIO2_IO25               0x100 0x414 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_RW__EIM_RW                   0x104 0x418 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_RW__IPU1_DI1_PIN08           0x104 0x418 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_RW__ECSPI2_SS0               0x104 0x418 0x81c 0x2 0x0
-#define MX6Q_PAD_EIM_RW__GPIO2_IO26               0x104 0x418 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_RW__SRC_BOOT_CFG29           0x104 0x418 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_LBA__EIM_LBA_B               0x108 0x41c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17          0x108 0x41c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_LBA__ECSPI2_SS1              0x108 0x41c 0x820 0x2 0x0
-#define MX6Q_PAD_EIM_LBA__GPIO2_IO27              0x108 0x41c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_LBA__SRC_BOOT_CFG26          0x108 0x41c 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_EB0__EIM_EB0_B               0x10c 0x420 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_EB0__IPU1_DISP1_DATA11       0x10c 0x420 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_EB0__IPU2_CSI1_DATA11        0x10c 0x420 0x8b4 0x2 0x1
-#define MX6Q_PAD_EIM_EB0__CCM_PMIC_READY          0x10c 0x420 0x7f0 0x4 0x0
-#define MX6Q_PAD_EIM_EB0__GPIO2_IO28              0x10c 0x420 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_EB0__SRC_BOOT_CFG27          0x10c 0x420 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_EB1__EIM_EB1_B               0x110 0x424 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_EB1__IPU1_DISP1_DATA10       0x110 0x424 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_EB1__IPU2_CSI1_DATA10        0x110 0x424 0x8b0 0x2 0x1
-#define MX6Q_PAD_EIM_EB1__GPIO2_IO29              0x110 0x424 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_EB1__SRC_BOOT_CFG28          0x110 0x424 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA0__EIM_AD00                0x114 0x428 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA0__IPU1_DISP1_DATA09       0x114 0x428 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA0__IPU2_CSI1_DATA09        0x114 0x428 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA0__GPIO3_IO00              0x114 0x428 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA0__SRC_BOOT_CFG00          0x114 0x428 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA1__EIM_AD01                0x118 0x42c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA1__IPU1_DISP1_DATA08       0x118 0x42c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA1__IPU2_CSI1_DATA08        0x118 0x42c 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA1__GPIO3_IO01              0x118 0x42c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA1__SRC_BOOT_CFG01          0x118 0x42c 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA2__EIM_AD02                0x11c 0x430 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA2__IPU1_DISP1_DATA07       0x11c 0x430 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA2__IPU2_CSI1_DATA07        0x11c 0x430 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA2__GPIO3_IO02              0x11c 0x430 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA2__SRC_BOOT_CFG02          0x11c 0x430 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA3__EIM_AD03                0x120 0x434 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA3__IPU1_DISP1_DATA06       0x120 0x434 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA3__IPU2_CSI1_DATA06        0x120 0x434 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA3__GPIO3_IO03              0x120 0x434 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA3__SRC_BOOT_CFG03          0x120 0x434 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA4__EIM_AD04                0x124 0x438 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA4__IPU1_DISP1_DATA05       0x124 0x438 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA4__IPU2_CSI1_DATA05        0x124 0x438 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA4__GPIO3_IO04              0x124 0x438 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA4__SRC_BOOT_CFG04          0x124 0x438 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA5__EIM_AD05                0x128 0x43c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA5__IPU1_DISP1_DATA04       0x128 0x43c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA5__IPU2_CSI1_DATA04        0x128 0x43c 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA5__GPIO3_IO05              0x128 0x43c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA5__SRC_BOOT_CFG05          0x128 0x43c 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA6__EIM_AD06                0x12c 0x440 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA6__IPU1_DISP1_DATA03       0x12c 0x440 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA6__IPU2_CSI1_DATA03        0x12c 0x440 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA6__GPIO3_IO06              0x12c 0x440 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA6__SRC_BOOT_CFG06          0x12c 0x440 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA7__EIM_AD07                0x130 0x444 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA7__IPU1_DISP1_DATA02       0x130 0x444 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA7__IPU2_CSI1_DATA02        0x130 0x444 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA7__GPIO3_IO07              0x130 0x444 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA7__SRC_BOOT_CFG07          0x130 0x444 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA8__EIM_AD08                0x134 0x448 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA8__IPU1_DISP1_DATA01       0x134 0x448 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA8__IPU2_CSI1_DATA01        0x134 0x448 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA8__GPIO3_IO08              0x134 0x448 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA8__SRC_BOOT_CFG08          0x134 0x448 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA9__EIM_AD09                0x138 0x44c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA9__IPU1_DISP1_DATA00       0x138 0x44c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA9__IPU2_CSI1_DATA00        0x138 0x44c 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA9__GPIO3_IO09              0x138 0x44c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA9__SRC_BOOT_CFG09          0x138 0x44c 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA10__EIM_AD10               0x13c 0x450 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15         0x13c 0x450 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN      0x13c 0x450 0x8d8 0x2 0x1
-#define MX6Q_PAD_EIM_DA10__GPIO3_IO10             0x13c 0x450 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA10__SRC_BOOT_CFG10         0x13c 0x450 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA11__EIM_AD11               0x140 0x454 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN02         0x140 0x454 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC        0x140 0x454 0x8dc 0x2 0x1
-#define MX6Q_PAD_EIM_DA11__GPIO3_IO11             0x140 0x454 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA11__SRC_BOOT_CFG11         0x140 0x454 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA12__EIM_AD12               0x144 0x458 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN03         0x144 0x458 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC        0x144 0x458 0x8e4 0x2 0x1
-#define MX6Q_PAD_EIM_DA12__GPIO3_IO12             0x144 0x458 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA12__SRC_BOOT_CFG12         0x144 0x458 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA13__EIM_AD13               0x148 0x45c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS         0x148 0x45c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA13__GPIO3_IO13             0x148 0x45c 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA13__SRC_BOOT_CFG13         0x148 0x45c 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA14__EIM_AD14               0x14c 0x460 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS         0x14c 0x460 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA14__GPIO3_IO14             0x14c 0x460 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA14__SRC_BOOT_CFG14         0x14c 0x460 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_DA15__EIM_AD15               0x150 0x464 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN01         0x150 0x464 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN04         0x150 0x464 0x000 0x2 0x0
-#define MX6Q_PAD_EIM_DA15__GPIO3_IO15             0x150 0x464 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_DA15__SRC_BOOT_CFG15         0x150 0x464 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_WAIT__EIM_WAIT_B             0x154 0x468 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_WAIT__EIM_DTACK_B            0x154 0x468 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_WAIT__GPIO5_IO00             0x154 0x468 0x000 0x5 0x0
-#define MX6Q_PAD_EIM_WAIT__SRC_BOOT_CFG25         0x154 0x468 0x000 0x7 0x0
-#define MX6Q_PAD_EIM_BCLK__EIM_BCLK               0x158 0x46c 0x000 0x0 0x0
-#define MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16         0x158 0x46c 0x000 0x1 0x0
-#define MX6Q_PAD_EIM_BCLK__GPIO6_IO31             0x158 0x46c 0x000 0x5 0x0
-#define MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK  0x15c 0x470 0x000 0x0 0x0
-#define MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DISP_CLK  0x15c 0x470 0x000 0x1 0x0
-#define MX6Q_PAD_DI0_DISP_CLK__GPIO4_IO16         0x15c 0x470 0x000 0x5 0x0
-#define MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15        0x160 0x474 0x000 0x0 0x0
-#define MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15        0x160 0x474 0x000 0x1 0x0
-#define MX6Q_PAD_DI0_PIN15__AUD6_TXC              0x160 0x474 0x000 0x2 0x0
-#define MX6Q_PAD_DI0_PIN15__GPIO4_IO17            0x160 0x474 0x000 0x5 0x0
-#define MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN02         0x164 0x478 0x000 0x0 0x0
-#define MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN02         0x164 0x478 0x000 0x1 0x0
-#define MX6Q_PAD_DI0_PIN2__AUD6_TXD               0x164 0x478 0x000 0x2 0x0
-#define MX6Q_PAD_DI0_PIN2__GPIO4_IO18             0x164 0x478 0x000 0x5 0x0
-#define MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN03         0x168 0x47c 0x000 0x0 0x0
-#define MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN03         0x168 0x47c 0x000 0x1 0x0
-#define MX6Q_PAD_DI0_PIN3__AUD6_TXFS              0x168 0x47c 0x000 0x2 0x0
-#define MX6Q_PAD_DI0_PIN3__GPIO4_IO19             0x168 0x47c 0x000 0x5 0x0
-#define MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN04         0x16c 0x480 0x000 0x0 0x0
-#define MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN04         0x16c 0x480 0x000 0x1 0x0
-#define MX6Q_PAD_DI0_PIN4__AUD6_RXD               0x16c 0x480 0x000 0x2 0x0
-#define MX6Q_PAD_DI0_PIN4__SD1_WP                 0x16c 0x480 0x94c 0x3 0x0
-#define MX6Q_PAD_DI0_PIN4__GPIO4_IO20             0x16c 0x480 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DATA00    0x170 0x484 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DATA00    0x170 0x484 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK          0x170 0x484 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT0__GPIO4_IO21           0x170 0x484 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DATA01    0x174 0x488 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DATA01    0x174 0x488 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI          0x174 0x488 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT1__GPIO4_IO22           0x174 0x488 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DATA02    0x178 0x48c 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DATA02    0x178 0x48c 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO          0x178 0x48c 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT2__GPIO4_IO23           0x178 0x48c 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DATA03    0x17c 0x490 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DATA03    0x17c 0x490 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0           0x17c 0x490 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT3__GPIO4_IO24           0x17c 0x490 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DATA04    0x180 0x494 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DATA04    0x180 0x494 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1           0x180 0x494 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT4__GPIO4_IO25           0x180 0x494 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DATA05    0x184 0x498 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DATA05    0x184 0x498 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2           0x184 0x498 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT5__AUD6_RXFS            0x184 0x498 0x000 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT5__GPIO4_IO26           0x184 0x498 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DATA06    0x188 0x49c 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DATA06    0x188 0x49c 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3           0x188 0x49c 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT6__AUD6_RXC             0x188 0x49c 0x000 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT6__GPIO4_IO27           0x188 0x49c 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DATA07    0x18c 0x4a0 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DATA07    0x18c 0x4a0 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY           0x18c 0x4a0 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT7__GPIO4_IO28           0x18c 0x4a0 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DATA08    0x190 0x4a4 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DATA08    0x190 0x4a4 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT8__PWM1_OUT             0x190 0x4a4 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT8__WDOG1_B              0x190 0x4a4 0x000 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT8__GPIO4_IO29           0x190 0x4a4 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DATA09    0x194 0x4a8 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DATA09    0x194 0x4a8 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT9__PWM2_OUT             0x194 0x4a8 0x000 0x2 0x0
-#define MX6Q_PAD_DISP0_DAT9__WDOG2_B              0x194 0x4a8 0x000 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT9__GPIO4_IO30           0x194 0x4a8 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DATA10   0x198 0x4ac 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DATA10   0x198 0x4ac 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT10__GPIO4_IO31          0x198 0x4ac 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DATA11   0x19c 0x4b0 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DATA11   0x19c 0x4b0 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT11__GPIO5_IO05          0x19c 0x4b0 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DATA12   0x1a0 0x4b4 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DATA12   0x1a0 0x4b4 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT12__GPIO5_IO06          0x1a0 0x4b4 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DATA13   0x1a4 0x4b8 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DATA13   0x1a4 0x4b8 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT13__AUD5_RXFS           0x1a4 0x4b8 0x7d8 0x3 0x1
-#define MX6Q_PAD_DISP0_DAT13__GPIO5_IO07          0x1a4 0x4b8 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DATA14   0x1a8 0x4bc 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DATA14   0x1a8 0x4bc 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT14__AUD5_RXC            0x1a8 0x4bc 0x7d4 0x3 0x1
-#define MX6Q_PAD_DISP0_DAT14__GPIO5_IO08          0x1a8 0x4bc 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DATA15   0x1ac 0x4c0 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DATA15   0x1ac 0x4c0 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1          0x1ac 0x4c0 0x804 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1          0x1ac 0x4c0 0x820 0x3 0x1
-#define MX6Q_PAD_DISP0_DAT15__GPIO5_IO09          0x1ac 0x4c0 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DATA16   0x1b0 0x4c4 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DATA16   0x1b0 0x4c4 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI         0x1b0 0x4c4 0x818 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT16__AUD5_TXC            0x1b0 0x4c4 0x7dc 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT0     0x1b0 0x4c4 0x90c 0x4 0x0
-#define MX6Q_PAD_DISP0_DAT16__GPIO5_IO10          0x1b0 0x4c4 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DATA17   0x1b4 0x4c8 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DATA17   0x1b4 0x4c8 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO         0x1b4 0x4c8 0x814 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT17__AUD5_TXD            0x1b4 0x4c8 0x7d0 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT1     0x1b4 0x4c8 0x910 0x4 0x0
-#define MX6Q_PAD_DISP0_DAT17__GPIO5_IO11          0x1b4 0x4c8 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DATA18   0x1b8 0x4cc 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DATA18   0x1b8 0x4cc 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0          0x1b8 0x4cc 0x81c 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT18__AUD5_TXFS           0x1b8 0x4cc 0x7e0 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT18__AUD4_RXFS           0x1b8 0x4cc 0x7c0 0x4 0x0
-#define MX6Q_PAD_DISP0_DAT18__GPIO5_IO12          0x1b8 0x4cc 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT18__EIM_CS2_B           0x1b8 0x4cc 0x000 0x7 0x0
-#define MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DATA19   0x1bc 0x4d0 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DATA19   0x1bc 0x4d0 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK         0x1bc 0x4d0 0x810 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT19__AUD5_RXD            0x1bc 0x4d0 0x7cc 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT19__AUD4_RXC            0x1bc 0x4d0 0x7bc 0x4 0x0
-#define MX6Q_PAD_DISP0_DAT19__GPIO5_IO13          0x1bc 0x4d0 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT19__EIM_CS3_B           0x1bc 0x4d0 0x000 0x7 0x0
-#define MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DATA20   0x1c0 0x4d4 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DATA20   0x1c0 0x4d4 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK         0x1c0 0x4d4 0x7f4 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT20__AUD4_TXC            0x1c0 0x4d4 0x7c4 0x3 0x0
-#define MX6Q_PAD_DISP0_DAT20__GPIO5_IO14          0x1c0 0x4d4 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DATA21   0x1c4 0x4d8 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DATA21   0x1c4 0x4d8 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI         0x1c4 0x4d8 0x7fc 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT21__AUD4_TXD            0x1c4 0x4d8 0x7b8 0x3 0x1
-#define MX6Q_PAD_DISP0_DAT21__GPIO5_IO15          0x1c4 0x4d8 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DATA22   0x1c8 0x4dc 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DATA22   0x1c8 0x4dc 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO         0x1c8 0x4dc 0x7f8 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT22__AUD4_TXFS           0x1c8 0x4dc 0x7c8 0x3 0x1
-#define MX6Q_PAD_DISP0_DAT22__GPIO5_IO16          0x1c8 0x4dc 0x000 0x5 0x0
-#define MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DATA23   0x1cc 0x4e0 0x000 0x0 0x0
-#define MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DATA23   0x1cc 0x4e0 0x000 0x1 0x0
-#define MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0          0x1cc 0x4e0 0x800 0x2 0x1
-#define MX6Q_PAD_DISP0_DAT23__AUD4_RXD            0x1cc 0x4e0 0x7b4 0x3 0x1
-#define MX6Q_PAD_DISP0_DAT23__GPIO5_IO17          0x1cc 0x4e0 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_MDIO__ENET_MDIO             0x1d0 0x4e4 0x840 0x1 0x0
-#define MX6Q_PAD_ENET_MDIO__ESAI_RX_CLK           0x1d0 0x4e4 0x86c 0x2 0x0
-#define MX6Q_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT  0x1d0 0x4e4 0x000 0x4 0x0
-#define MX6Q_PAD_ENET_MDIO__GPIO1_IO22            0x1d0 0x4e4 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_MDIO__SPDIF_LOCK            0x1d0 0x4e4 0x000 0x6 0x0
-#define MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK        0x1d4 0x4e8 0x000 0x1 0x0
-#define MX6Q_PAD_ENET_REF_CLK__ESAI_RX_FS         0x1d4 0x4e8 0x85c 0x2 0x0
-#define MX6Q_PAD_ENET_REF_CLK__GPIO1_IO23         0x1d4 0x4e8 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_REF_CLK__SPDIF_SR_CLK       0x1d4 0x4e8 0x000 0x6 0x0
-#define MX6Q_PAD_ENET_RX_ER__USB_OTG_ID           0x1d8 0x4ec 0x000 0x0 0x0
-#define MX6Q_PAD_ENET_RX_ER__ENET_RX_ER           0x1d8 0x4ec 0x000 0x1 0x0
-#define MX6Q_PAD_ENET_RX_ER__ESAI_RX_HF_CLK       0x1d8 0x4ec 0x864 0x2 0x0
-#define MX6Q_PAD_ENET_RX_ER__SPDIF_IN             0x1d8 0x4ec 0x914 0x3 0x1
-#define MX6Q_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT 0x1d8 0x4ec 0x000 0x4 0x0
-#define MX6Q_PAD_ENET_RX_ER__GPIO1_IO24           0x1d8 0x4ec 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN          0x1dc 0x4f0 0x858 0x1 0x1
-#define MX6Q_PAD_ENET_CRS_DV__ESAI_TX_CLK         0x1dc 0x4f0 0x870 0x2 0x0
-#define MX6Q_PAD_ENET_CRS_DV__SPDIF_EXT_CLK       0x1dc 0x4f0 0x918 0x3 0x1
-#define MX6Q_PAD_ENET_CRS_DV__GPIO1_IO25          0x1dc 0x4f0 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_RXD1__MLB_SIG               0x1e0 0x4f4 0x908 0x0 0x0
-#define MX6Q_PAD_ENET_RXD1__ENET_RX_DATA1         0x1e0 0x4f4 0x84c 0x1 0x1
-#define MX6Q_PAD_ENET_RXD1__ESAI_TX_FS            0x1e0 0x4f4 0x860 0x2 0x0
-#define MX6Q_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT  0x1e0 0x4f4 0x000 0x4 0x0
-#define MX6Q_PAD_ENET_RXD1__GPIO1_IO26            0x1e0 0x4f4 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_RXD0__ENET_RX_DATA0         0x1e4 0x4f8 0x848 0x1 0x1
-#define MX6Q_PAD_ENET_RXD0__ESAI_TX_HF_CLK        0x1e4 0x4f8 0x868 0x2 0x0
-#define MX6Q_PAD_ENET_RXD0__SPDIF_OUT             0x1e4 0x4f8 0x000 0x3 0x0
-#define MX6Q_PAD_ENET_RXD0__GPIO1_IO27            0x1e4 0x4f8 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_TX_EN__ENET_TX_EN           0x1e8 0x4fc 0x000 0x1 0x0
-#define MX6Q_PAD_ENET_TX_EN__ESAI_TX3_RX2         0x1e8 0x4fc 0x880 0x2 0x0
-#define MX6Q_PAD_ENET_TX_EN__GPIO1_IO28           0x1e8 0x4fc 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_TXD1__MLB_CLK               0x1ec 0x500 0x900 0x0 0x0
-#define MX6Q_PAD_ENET_TXD1__ENET_TX_DATA1         0x1ec 0x500 0x000 0x1 0x0
-#define MX6Q_PAD_ENET_TXD1__ESAI_TX2_RX3          0x1ec 0x500 0x87c 0x2 0x0
-#define MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN   0x1ec 0x500 0x000 0x4 0x0
-#define MX6Q_PAD_ENET_TXD1__GPIO1_IO29            0x1ec 0x500 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_TXD0__ENET_TX_DATA0         0x1f0 0x504 0x000 0x1 0x0
-#define MX6Q_PAD_ENET_TXD0__ESAI_TX4_RX1          0x1f0 0x504 0x884 0x2 0x0
-#define MX6Q_PAD_ENET_TXD0__GPIO1_IO30            0x1f0 0x504 0x000 0x5 0x0
-#define MX6Q_PAD_ENET_MDC__MLB_DATA               0x1f4 0x508 0x904 0x0 0x0
-#define MX6Q_PAD_ENET_MDC__ENET_MDC               0x1f4 0x508 0x000 0x1 0x0
-#define MX6Q_PAD_ENET_MDC__ESAI_TX5_RX0           0x1f4 0x508 0x888 0x2 0x0
-#define MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN    0x1f4 0x508 0x000 0x4 0x0
-#define MX6Q_PAD_ENET_MDC__GPIO1_IO31             0x1f4 0x508 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_COL0__ECSPI1_SCLK            0x1f8 0x5c8 0x7f4 0x0 0x2
-#define MX6Q_PAD_KEY_COL0__ENET_RX_DATA3          0x1f8 0x5c8 0x854 0x1 0x1
-#define MX6Q_PAD_KEY_COL0__AUD5_TXC               0x1f8 0x5c8 0x7dc 0x2 0x1
-#define MX6Q_PAD_KEY_COL0__KEY_COL0               0x1f8 0x5c8 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_COL0__UART4_TX_DATA          0x1f8 0x5c8 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_COL0__UART4_RX_DATA          0x1f8 0x5c8 0x938 0x4 0x0
-#define MX6Q_PAD_KEY_COL0__GPIO4_IO06             0x1f8 0x5c8 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_COL0__DCIC1_OUT              0x1f8 0x5c8 0x000 0x6 0x0
-#define MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI            0x1fc 0x5cc 0x7fc 0x0 0x2
-#define MX6Q_PAD_KEY_ROW0__ENET_TX_DATA3          0x1fc 0x5cc 0x000 0x1 0x0
-#define MX6Q_PAD_KEY_ROW0__AUD5_TXD               0x1fc 0x5cc 0x7d0 0x2 0x1
-#define MX6Q_PAD_KEY_ROW0__KEY_ROW0               0x1fc 0x5cc 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_ROW0__UART4_RX_DATA          0x1fc 0x5cc 0x938 0x4 0x1
-#define MX6Q_PAD_KEY_ROW0__UART4_TX_DATA          0x1fc 0x5cc 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_ROW0__GPIO4_IO07             0x1fc 0x5cc 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_ROW0__DCIC2_OUT              0x1fc 0x5cc 0x000 0x6 0x0
-#define MX6Q_PAD_KEY_COL1__ECSPI1_MISO            0x200 0x5d0 0x7f8 0x0 0x2
-#define MX6Q_PAD_KEY_COL1__ENET_MDIO              0x200 0x5d0 0x840 0x1 0x1
-#define MX6Q_PAD_KEY_COL1__AUD5_TXFS              0x200 0x5d0 0x7e0 0x2 0x1
-#define MX6Q_PAD_KEY_COL1__KEY_COL1               0x200 0x5d0 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_COL1__UART5_TX_DATA          0x200 0x5d0 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_COL1__UART5_RX_DATA          0x200 0x5d0 0x940 0x4 0x0
-#define MX6Q_PAD_KEY_COL1__GPIO4_IO08             0x200 0x5d0 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_COL1__SD1_VSELECT            0x200 0x5d0 0x000 0x6 0x0
-#define MX6Q_PAD_KEY_ROW1__ECSPI1_SS0             0x204 0x5d4 0x800 0x0 0x2
-#define MX6Q_PAD_KEY_ROW1__ENET_COL               0x204 0x5d4 0x000 0x1 0x0
-#define MX6Q_PAD_KEY_ROW1__AUD5_RXD               0x204 0x5d4 0x7cc 0x2 0x1
-#define MX6Q_PAD_KEY_ROW1__KEY_ROW1               0x204 0x5d4 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_ROW1__UART5_RX_DATA          0x204 0x5d4 0x940 0x4 0x1
-#define MX6Q_PAD_KEY_ROW1__UART5_TX_DATA          0x204 0x5d4 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_ROW1__GPIO4_IO09             0x204 0x5d4 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_ROW1__SD2_VSELECT            0x204 0x5d4 0x000 0x6 0x0
-#define MX6Q_PAD_KEY_COL2__ECSPI1_SS1             0x208 0x5d8 0x804 0x0 0x2
-#define MX6Q_PAD_KEY_COL2__ENET_RX_DATA2          0x208 0x5d8 0x850 0x1 0x1
-#define MX6Q_PAD_KEY_COL2__FLEXCAN1_TX            0x208 0x5d8 0x000 0x2 0x0
-#define MX6Q_PAD_KEY_COL2__KEY_COL2               0x208 0x5d8 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_COL2__ENET_MDC               0x208 0x5d8 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_COL2__GPIO4_IO10             0x208 0x5d8 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_COL2__USB_H1_PWR_CTL_WAKE    0x208 0x5d8 0x000 0x6 0x0
-#define MX6Q_PAD_KEY_ROW2__ECSPI1_SS2             0x20c 0x5dc 0x808 0x0 0x1
-#define MX6Q_PAD_KEY_ROW2__ENET_TX_DATA2          0x20c 0x5dc 0x000 0x1 0x0
-#define MX6Q_PAD_KEY_ROW2__FLEXCAN1_RX            0x20c 0x5dc 0x7e4 0x2 0x0
-#define MX6Q_PAD_KEY_ROW2__KEY_ROW2               0x20c 0x5dc 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_ROW2__SD2_VSELECT            0x20c 0x5dc 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_ROW2__GPIO4_IO11             0x20c 0x5dc 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE       0x20c 0x5dc 0x88c 0x6 0x1
-#define MX6Q_PAD_KEY_COL3__ECSPI1_SS3             0x210 0x5e0 0x80c 0x0 0x1
-#define MX6Q_PAD_KEY_COL3__ENET_CRS               0x210 0x5e0 0x000 0x1 0x0
-#define MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL        0x210 0x5e0 0x890 0x2 0x1
-#define MX6Q_PAD_KEY_COL3__KEY_COL3               0x210 0x5e0 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_COL3__I2C2_SCL               0x210 0x5e0 0x8a0 0x4 0x1
-#define MX6Q_PAD_KEY_COL3__GPIO4_IO12             0x210 0x5e0 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_COL3__SPDIF_IN               0x210 0x5e0 0x914 0x6 0x2
-#define MX6Q_PAD_KEY_ROW3__ASRC_EXT_CLK           0x214 0x5e4 0x7b0 0x1 0x0
-#define MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA        0x214 0x5e4 0x894 0x2 0x1
-#define MX6Q_PAD_KEY_ROW3__KEY_ROW3               0x214 0x5e4 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_ROW3__I2C2_SDA               0x214 0x5e4 0x8a4 0x4 0x1
-#define MX6Q_PAD_KEY_ROW3__GPIO4_IO13             0x214 0x5e4 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_ROW3__SD1_VSELECT            0x214 0x5e4 0x000 0x6 0x0
-#define MX6Q_PAD_KEY_COL4__FLEXCAN2_TX            0x218 0x5e8 0x000 0x0 0x0
-#define MX6Q_PAD_KEY_COL4__IPU1_SISG4             0x218 0x5e8 0x000 0x1 0x0
-#define MX6Q_PAD_KEY_COL4__USB_OTG_OC             0x218 0x5e8 0x944 0x2 0x1
-#define MX6Q_PAD_KEY_COL4__KEY_COL4               0x218 0x5e8 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_COL4__UART5_RTS_B            0x218 0x5e8 0x93c 0x4 0x0
-#define MX6Q_PAD_KEY_COL4__UART5_CTS_B            0x218 0x5e8 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_COL4__GPIO4_IO14             0x218 0x5e8 0x000 0x5 0x0
-#define MX6Q_PAD_KEY_ROW4__FLEXCAN2_RX            0x21c 0x5ec 0x7e8 0x0 0x0
-#define MX6Q_PAD_KEY_ROW4__IPU1_SISG5             0x21c 0x5ec 0x000 0x1 0x0
-#define MX6Q_PAD_KEY_ROW4__USB_OTG_PWR            0x21c 0x5ec 0x000 0x2 0x0
-#define MX6Q_PAD_KEY_ROW4__KEY_ROW4               0x21c 0x5ec 0x000 0x3 0x0
-#define MX6Q_PAD_KEY_ROW4__UART5_CTS_B            0x21c 0x5ec 0x000 0x4 0x0
-#define MX6Q_PAD_KEY_ROW4__UART5_RTS_B            0x21c 0x5ec 0x93c 0x4 0x1
-#define MX6Q_PAD_KEY_ROW4__GPIO4_IO15             0x21c 0x5ec 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_0__CCM_CLKO1                0x220 0x5f0 0x000 0x0 0x0
-#define MX6Q_PAD_GPIO_0__KEY_COL5                 0x220 0x5f0 0x8e8 0x2 0x0
-#define MX6Q_PAD_GPIO_0__ASRC_EXT_CLK             0x220 0x5f0 0x7b0 0x3 0x1
-#define MX6Q_PAD_GPIO_0__EPIT1_OUT                0x220 0x5f0 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_0__GPIO1_IO00               0x220 0x5f0 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_0__USB_H1_PWR               0x220 0x5f0 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_0__SNVS_VIO_5               0x220 0x5f0 0x000 0x7 0x0
-#define MX6Q_PAD_GPIO_1__ESAI_RX_CLK              0x224 0x5f4 0x86c 0x0 0x1
-#define MX6Q_PAD_GPIO_1__WDOG2_B                  0x224 0x5f4 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_1__KEY_ROW5                 0x224 0x5f4 0x8f4 0x2 0x0
-#define MX6Q_PAD_GPIO_1__USB_OTG_ID               0x224 0x5f4 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_1__PWM2_OUT                 0x224 0x5f4 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_1__GPIO1_IO01               0x224 0x5f4 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_1__SD1_CD_B                 0x224 0x5f4 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_9__ESAI_RX_FS               0x228 0x5f8 0x85c 0x0 0x1
-#define MX6Q_PAD_GPIO_9__WDOG1_B                  0x228 0x5f8 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_9__KEY_COL6                 0x228 0x5f8 0x8ec 0x2 0x0
-#define MX6Q_PAD_GPIO_9__CCM_REF_EN_B             0x228 0x5f8 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_9__PWM1_OUT                 0x228 0x5f8 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_9__GPIO1_IO09               0x228 0x5f8 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_9__SD1_WP                   0x228 0x5f8 0x94c 0x6 0x1
-#define MX6Q_PAD_GPIO_3__ESAI_RX_HF_CLK           0x22c 0x5fc 0x864 0x0 0x1
-#define MX6Q_PAD_GPIO_3__I2C3_SCL                 0x22c 0x5fc 0x8a8 0x2 0x1
-#define MX6Q_PAD_GPIO_3__XTALOSC_REF_CLK_24M      0x22c 0x5fc 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_3__CCM_CLKO2                0x22c 0x5fc 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_3__GPIO1_IO03               0x22c 0x5fc 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_3__USB_H1_OC                0x22c 0x5fc 0x948 0x6 0x1
-#define MX6Q_PAD_GPIO_3__MLB_CLK                  0x22c 0x5fc 0x900 0x7 0x1
-#define MX6Q_PAD_GPIO_6__ESAI_TX_CLK              0x230 0x600 0x870 0x0 0x1
-#define MX6Q_PAD_GPIO_6__I2C3_SDA                 0x230 0x600 0x8ac 0x2 0x1
-#define MX6Q_PAD_GPIO_6__GPIO1_IO06               0x230 0x600 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_6__SD2_LCTL                 0x230 0x600 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_6__MLB_SIG                  0x230 0x600 0x908 0x7 0x1
-#define MX6Q_PAD_GPIO_2__ESAI_TX_FS               0x234 0x604 0x860 0x0 0x1
-#define MX6Q_PAD_GPIO_2__KEY_ROW6                 0x234 0x604 0x8f8 0x2 0x1
-#define MX6Q_PAD_GPIO_2__GPIO1_IO02               0x234 0x604 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_2__SD2_WP                   0x234 0x604 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_2__MLB_DATA                 0x234 0x604 0x904 0x7 0x1
-#define MX6Q_PAD_GPIO_4__ESAI_TX_HF_CLK           0x238 0x608 0x868 0x0 0x1
-#define MX6Q_PAD_GPIO_4__KEY_COL7                 0x238 0x608 0x8f0 0x2 0x1
-#define MX6Q_PAD_GPIO_4__GPIO1_IO04               0x238 0x608 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_4__SD2_CD_B                 0x238 0x608 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_5__ESAI_TX2_RX3             0x23c 0x60c 0x87c 0x0 0x1
-#define MX6Q_PAD_GPIO_5__KEY_ROW7                 0x23c 0x60c 0x8fc 0x2 0x1
-#define MX6Q_PAD_GPIO_5__CCM_CLKO1                0x23c 0x60c 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_5__GPIO1_IO05               0x23c 0x60c 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_5__I2C3_SCL                 0x23c 0x60c 0x8a8 0x6 0x2
-#define MX6Q_PAD_GPIO_5__ARM_EVENTI               0x23c 0x60c 0x000 0x7 0x0
-#define MX6Q_PAD_GPIO_7__ESAI_TX4_RX1             0x240 0x610 0x884 0x0 0x1
-#define MX6Q_PAD_GPIO_7__ECSPI5_RDY               0x240 0x610 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_7__EPIT1_OUT                0x240 0x610 0x000 0x2 0x0
-#define MX6Q_PAD_GPIO_7__FLEXCAN1_TX              0x240 0x610 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_7__UART2_TX_DATA            0x240 0x610 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_7__UART2_RX_DATA            0x240 0x610 0x928 0x4 0x2
-#define MX6Q_PAD_GPIO_7__GPIO1_IO07               0x240 0x610 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_7__SPDIF_LOCK               0x240 0x610 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_7__USB_OTG_HOST_MODE        0x240 0x610 0x000 0x7 0x0
-#define MX6Q_PAD_GPIO_8__ESAI_TX5_RX0             0x244 0x614 0x888 0x0 0x1
-#define MX6Q_PAD_GPIO_8__XTALOSC_REF_CLK_32K      0x244 0x614 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_8__EPIT2_OUT                0x244 0x614 0x000 0x2 0x0
-#define MX6Q_PAD_GPIO_8__FLEXCAN1_RX              0x244 0x614 0x7e4 0x3 0x1
-#define MX6Q_PAD_GPIO_8__UART2_RX_DATA            0x244 0x614 0x928 0x4 0x3
-#define MX6Q_PAD_GPIO_8__UART2_TX_DATA            0x244 0x614 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_8__GPIO1_IO08               0x244 0x614 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_8__SPDIF_SR_CLK             0x244 0x614 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_8__USB_OTG_PWR_CTL_WAKE     0x244 0x614 0x000 0x7 0x0
-#define MX6Q_PAD_GPIO_16__ESAI_TX3_RX2            0x248 0x618 0x880 0x0 0x1
-#define MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN     0x248 0x618 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_16__ENET_REF_CLK            0x248 0x618 0x83c 0x2 0x1
-#define MX6Q_PAD_GPIO_16__SD1_LCTL                0x248 0x618 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_16__SPDIF_IN                0x248 0x618 0x914 0x4 0x3
-#define MX6Q_PAD_GPIO_16__GPIO7_IO11              0x248 0x618 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_16__I2C3_SDA                0x248 0x618 0x8ac 0x6 0x2
-#define MX6Q_PAD_GPIO_16__JTAG_DE_B               0x248 0x618 0x000 0x7 0x0
-#define MX6Q_PAD_GPIO_17__ESAI_TX0                0x24c 0x61c 0x874 0x0 0x0
-#define MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN     0x24c 0x61c 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_17__CCM_PMIC_READY          0x24c 0x61c 0x7f0 0x2 0x1
-#define MX6Q_PAD_GPIO_17__SDMA_EXT_EVENT0         0x24c 0x61c 0x90c 0x3 0x1
-#define MX6Q_PAD_GPIO_17__SPDIF_OUT               0x24c 0x61c 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_17__GPIO7_IO12              0x24c 0x61c 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_18__ESAI_TX1                0x250 0x620 0x878 0x0 0x0
-#define MX6Q_PAD_GPIO_18__ENET_RX_CLK             0x250 0x620 0x844 0x1 0x1
-#define MX6Q_PAD_GPIO_18__SD3_VSELECT             0x250 0x620 0x000 0x2 0x0
-#define MX6Q_PAD_GPIO_18__SDMA_EXT_EVENT1         0x250 0x620 0x910 0x3 0x1
-#define MX6Q_PAD_GPIO_18__ASRC_EXT_CLK            0x250 0x620 0x7b0 0x4 0x2
-#define MX6Q_PAD_GPIO_18__GPIO7_IO13              0x250 0x620 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_18__SNVS_VIO_5_CTL          0x250 0x620 0x000 0x6 0x0
-#define MX6Q_PAD_GPIO_19__KEY_COL5                0x254 0x624 0x8e8 0x0 0x1
-#define MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT    0x254 0x624 0x000 0x1 0x0
-#define MX6Q_PAD_GPIO_19__SPDIF_OUT               0x254 0x624 0x000 0x2 0x0
-#define MX6Q_PAD_GPIO_19__CCM_CLKO1               0x254 0x624 0x000 0x3 0x0
-#define MX6Q_PAD_GPIO_19__ECSPI1_RDY              0x254 0x624 0x000 0x4 0x0
-#define MX6Q_PAD_GPIO_19__GPIO4_IO05              0x254 0x624 0x000 0x5 0x0
-#define MX6Q_PAD_GPIO_19__ENET_TX_ER              0x254 0x624 0x000 0x6 0x0
-#define MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK    0x258 0x628 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_PIXCLK__GPIO5_IO18          0x258 0x628 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_PIXCLK__ARM_EVENTO          0x258 0x628 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC       0x25c 0x62c 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_MCLK__CCM_CLKO1             0x25c 0x62c 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_MCLK__GPIO5_IO19            0x25c 0x62c 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_MCLK__ARM_TRACE_CTL         0x25c 0x62c 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN  0x260 0x630 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DATA_EN__EIM_DATA00         0x260 0x630 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DATA_EN__GPIO5_IO20         0x260 0x630 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DATA_EN__ARM_TRACE_CLK      0x260 0x630 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC      0x264 0x634 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_VSYNC__EIM_DATA01           0x264 0x634 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_VSYNC__GPIO5_IO21           0x264 0x634 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_VSYNC__ARM_TRACE00          0x264 0x634 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_DATA04      0x268 0x638 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT4__EIM_DATA02            0x268 0x638 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK           0x268 0x638 0x7f4 0x2 0x3
-#define MX6Q_PAD_CSI0_DAT4__KEY_COL5              0x268 0x638 0x8e8 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT4__AUD3_TXC              0x268 0x638 0x000 0x4 0x0
-#define MX6Q_PAD_CSI0_DAT4__GPIO5_IO22            0x268 0x638 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT4__ARM_TRACE01           0x268 0x638 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_DATA05      0x26c 0x63c 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT5__EIM_DATA03            0x26c 0x63c 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI           0x26c 0x63c 0x7fc 0x2 0x3
-#define MX6Q_PAD_CSI0_DAT5__KEY_ROW5              0x26c 0x63c 0x8f4 0x3 0x1
-#define MX6Q_PAD_CSI0_DAT5__AUD3_TXD              0x26c 0x63c 0x000 0x4 0x0
-#define MX6Q_PAD_CSI0_DAT5__GPIO5_IO23            0x26c 0x63c 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT5__ARM_TRACE02           0x26c 0x63c 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_DATA06      0x270 0x640 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT6__EIM_DATA04            0x270 0x640 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO           0x270 0x640 0x7f8 0x2 0x3
-#define MX6Q_PAD_CSI0_DAT6__KEY_COL6              0x270 0x640 0x8ec 0x3 0x1
-#define MX6Q_PAD_CSI0_DAT6__AUD3_TXFS             0x270 0x640 0x000 0x4 0x0
-#define MX6Q_PAD_CSI0_DAT6__GPIO5_IO24            0x270 0x640 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT6__ARM_TRACE03           0x270 0x640 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_DATA07      0x274 0x644 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT7__EIM_DATA05            0x274 0x644 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0            0x274 0x644 0x800 0x2 0x3
-#define MX6Q_PAD_CSI0_DAT7__KEY_ROW6              0x274 0x644 0x8f8 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT7__AUD3_RXD              0x274 0x644 0x000 0x4 0x0
-#define MX6Q_PAD_CSI0_DAT7__GPIO5_IO25            0x274 0x644 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT7__ARM_TRACE04           0x274 0x644 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_DATA08      0x278 0x648 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT8__EIM_DATA06            0x278 0x648 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK           0x278 0x648 0x810 0x2 0x2
-#define MX6Q_PAD_CSI0_DAT8__KEY_COL7              0x278 0x648 0x8f0 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT8__I2C1_SDA              0x278 0x648 0x89c 0x4 0x1
-#define MX6Q_PAD_CSI0_DAT8__GPIO5_IO26            0x278 0x648 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT8__ARM_TRACE05           0x278 0x648 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_DATA09      0x27c 0x64c 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT9__EIM_DATA07            0x27c 0x64c 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI           0x27c 0x64c 0x818 0x2 0x2
-#define MX6Q_PAD_CSI0_DAT9__KEY_ROW7              0x27c 0x64c 0x8fc 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT9__I2C1_SCL              0x27c 0x64c 0x898 0x4 0x1
-#define MX6Q_PAD_CSI0_DAT9__GPIO5_IO27            0x27c 0x64c 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT9__ARM_TRACE06           0x27c 0x64c 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_DATA10     0x280 0x650 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT10__AUD3_RXC             0x280 0x650 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO          0x280 0x650 0x814 0x2 0x2
-#define MX6Q_PAD_CSI0_DAT10__UART1_TX_DATA        0x280 0x650 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT10__UART1_RX_DATA        0x280 0x650 0x920 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT10__GPIO5_IO28           0x280 0x650 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT10__ARM_TRACE07          0x280 0x650 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_DATA11     0x284 0x654 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT11__AUD3_RXFS            0x284 0x654 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0           0x284 0x654 0x81c 0x2 0x2
-#define MX6Q_PAD_CSI0_DAT11__UART1_RX_DATA        0x284 0x654 0x920 0x3 0x1
-#define MX6Q_PAD_CSI0_DAT11__UART1_TX_DATA        0x284 0x654 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT11__GPIO5_IO29           0x284 0x654 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT11__ARM_TRACE08          0x284 0x654 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_DATA12     0x288 0x658 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT12__EIM_DATA08           0x288 0x658 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT12__UART4_TX_DATA        0x288 0x658 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT12__UART4_RX_DATA        0x288 0x658 0x938 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT12__GPIO5_IO30           0x288 0x658 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT12__ARM_TRACE09          0x288 0x658 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_DATA13     0x28c 0x65c 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT13__EIM_DATA09           0x28c 0x65c 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT13__UART4_RX_DATA        0x28c 0x65c 0x938 0x3 0x3
-#define MX6Q_PAD_CSI0_DAT13__UART4_TX_DATA        0x28c 0x65c 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT13__GPIO5_IO31           0x28c 0x65c 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT13__ARM_TRACE10          0x28c 0x65c 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_DATA14     0x290 0x660 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT14__EIM_DATA10           0x290 0x660 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT14__UART5_TX_DATA        0x290 0x660 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT14__UART5_RX_DATA        0x290 0x660 0x940 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT14__GPIO6_IO00           0x290 0x660 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT14__ARM_TRACE11          0x290 0x660 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_DATA15     0x294 0x664 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT15__EIM_DATA11           0x294 0x664 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT15__UART5_RX_DATA        0x294 0x664 0x940 0x3 0x3
-#define MX6Q_PAD_CSI0_DAT15__UART5_TX_DATA        0x294 0x664 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT15__GPIO6_IO01           0x294 0x664 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT15__ARM_TRACE12          0x294 0x664 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_DATA16     0x298 0x668 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT16__EIM_DATA12           0x298 0x668 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT16__UART4_RTS_B          0x298 0x668 0x934 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT16__UART4_CTS_B          0x298 0x668 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT16__GPIO6_IO02           0x298 0x668 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT16__ARM_TRACE13          0x298 0x668 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_DATA17     0x29c 0x66c 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT17__EIM_DATA13           0x29c 0x66c 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT17__UART4_CTS_B          0x29c 0x66c 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT17__UART4_RTS_B          0x29c 0x66c 0x934 0x3 0x1
-#define MX6Q_PAD_CSI0_DAT17__GPIO6_IO03           0x29c 0x66c 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT17__ARM_TRACE14          0x29c 0x66c 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_DATA18     0x2a0 0x670 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT18__EIM_DATA14           0x2a0 0x670 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT18__UART5_RTS_B          0x2a0 0x670 0x93c 0x3 0x2
-#define MX6Q_PAD_CSI0_DAT18__UART5_CTS_B          0x2a0 0x670 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT18__GPIO6_IO04           0x2a0 0x670 0x000 0x5 0x0
-#define MX6Q_PAD_CSI0_DAT18__ARM_TRACE15          0x2a0 0x670 0x000 0x7 0x0
-#define MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_DATA19     0x2a4 0x674 0x000 0x0 0x0
-#define MX6Q_PAD_CSI0_DAT19__EIM_DATA15           0x2a4 0x674 0x000 0x1 0x0
-#define MX6Q_PAD_CSI0_DAT19__UART5_CTS_B          0x2a4 0x674 0x000 0x3 0x0
-#define MX6Q_PAD_CSI0_DAT19__UART5_RTS_B          0x2a4 0x674 0x93c 0x3 0x3
-#define MX6Q_PAD_CSI0_DAT19__GPIO6_IO05           0x2a4 0x674 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT7__SD3_DATA7              0x2a8 0x690 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT7__UART1_TX_DATA          0x2a8 0x690 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT7__UART1_RX_DATA          0x2a8 0x690 0x920 0x1 0x2
-#define MX6Q_PAD_SD3_DAT7__GPIO6_IO17             0x2a8 0x690 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT6__SD3_DATA6              0x2ac 0x694 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT6__UART1_RX_DATA          0x2ac 0x694 0x920 0x1 0x3
-#define MX6Q_PAD_SD3_DAT6__UART1_TX_DATA          0x2ac 0x694 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT6__GPIO6_IO18             0x2ac 0x694 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT5__SD3_DATA5              0x2b0 0x698 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT5__UART2_TX_DATA          0x2b0 0x698 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT5__UART2_RX_DATA          0x2b0 0x698 0x928 0x1 0x4
-#define MX6Q_PAD_SD3_DAT5__GPIO7_IO00             0x2b0 0x698 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT4__SD3_DATA4              0x2b4 0x69c 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT4__UART2_RX_DATA          0x2b4 0x69c 0x928 0x1 0x5
-#define MX6Q_PAD_SD3_DAT4__UART2_TX_DATA          0x2b4 0x69c 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT4__GPIO7_IO01             0x2b4 0x69c 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_CMD__SD3_CMD                 0x2b8 0x6a0 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_CMD__UART2_CTS_B             0x2b8 0x6a0 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_CMD__UART2_RTS_B             0x2b8 0x6a0 0x924 0x1 0x2
-#define MX6Q_PAD_SD3_CMD__FLEXCAN1_TX             0x2b8 0x6a0 0x000 0x2 0x0
-#define MX6Q_PAD_SD3_CMD__GPIO7_IO02              0x2b8 0x6a0 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_CLK__SD3_CLK                 0x2bc 0x6a4 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_CLK__UART2_RTS_B             0x2bc 0x6a4 0x924 0x1 0x3
-#define MX6Q_PAD_SD3_CLK__UART2_CTS_B             0x2bc 0x6a4 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_CLK__FLEXCAN1_RX             0x2bc 0x6a4 0x7e4 0x2 0x2
-#define MX6Q_PAD_SD3_CLK__GPIO7_IO03              0x2bc 0x6a4 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT0__SD3_DATA0              0x2c0 0x6a8 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT0__UART1_CTS_B            0x2c0 0x6a8 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT0__UART1_RTS_B            0x2c0 0x6a8 0x91c 0x1 0x2
-#define MX6Q_PAD_SD3_DAT0__FLEXCAN2_TX            0x2c0 0x6a8 0x000 0x2 0x0
-#define MX6Q_PAD_SD3_DAT0__GPIO7_IO04             0x2c0 0x6a8 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT1__SD3_DATA1              0x2c4 0x6ac 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT1__UART1_RTS_B            0x2c4 0x6ac 0x91c 0x1 0x3
-#define MX6Q_PAD_SD3_DAT1__UART1_CTS_B            0x2c4 0x6ac 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT1__FLEXCAN2_RX            0x2c4 0x6ac 0x7e8 0x2 0x1
-#define MX6Q_PAD_SD3_DAT1__GPIO7_IO05             0x2c4 0x6ac 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT2__SD3_DATA2              0x2c8 0x6b0 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT2__GPIO7_IO06             0x2c8 0x6b0 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_DAT3__SD3_DATA3              0x2cc 0x6b4 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_DAT3__UART3_CTS_B            0x2cc 0x6b4 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_DAT3__UART3_RTS_B            0x2cc 0x6b4 0x92c 0x1 0x4
-#define MX6Q_PAD_SD3_DAT3__GPIO7_IO07             0x2cc 0x6b4 0x000 0x5 0x0
-#define MX6Q_PAD_SD3_RST__SD3_RESET               0x2d0 0x6b8 0x000 0x0 0x0
-#define MX6Q_PAD_SD3_RST__UART3_RTS_B             0x2d0 0x6b8 0x92c 0x1 0x5
-#define MX6Q_PAD_SD3_RST__UART3_CTS_B             0x2d0 0x6b8 0x000 0x1 0x0
-#define MX6Q_PAD_SD3_RST__GPIO7_IO08              0x2d0 0x6b8 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_CLE__NAND_CLE              0x2d4 0x6bc 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_CLE__IPU2_SISG4            0x2d4 0x6bc 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_CLE__GPIO6_IO07            0x2d4 0x6bc 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_ALE__NAND_ALE              0x2d8 0x6c0 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_ALE__SD4_RESET             0x2d8 0x6c0 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_ALE__GPIO6_IO08            0x2d8 0x6c0 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_WP_B__NAND_WP_B            0x2dc 0x6c4 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_WP_B__IPU2_SISG5           0x2dc 0x6c4 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_WP_B__GPIO6_IO09           0x2dc 0x6c4 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_RB0__NAND_READY_B          0x2e0 0x6c8 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN01        0x2e0 0x6c8 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_RB0__GPIO6_IO10            0x2e0 0x6c8 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_CS0__NAND_CE0_B            0x2e4 0x6cc 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_CS0__GPIO6_IO11            0x2e4 0x6cc 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_CS1__NAND_CE1_B            0x2e8 0x6d0 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_CS1__SD4_VSELECT           0x2e8 0x6d0 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_CS1__SD3_VSELECT           0x2e8 0x6d0 0x000 0x2 0x0
-#define MX6Q_PAD_NANDF_CS1__GPIO6_IO14            0x2e8 0x6d0 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_CS2__NAND_CE2_B            0x2ec 0x6d4 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_CS2__IPU1_SISG0            0x2ec 0x6d4 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_CS2__ESAI_TX0              0x2ec 0x6d4 0x874 0x2 0x1
-#define MX6Q_PAD_NANDF_CS2__EIM_CRE               0x2ec 0x6d4 0x000 0x3 0x0
-#define MX6Q_PAD_NANDF_CS2__CCM_CLKO2             0x2ec 0x6d4 0x000 0x4 0x0
-#define MX6Q_PAD_NANDF_CS2__GPIO6_IO15            0x2ec 0x6d4 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_CS2__IPU2_SISG0            0x2ec 0x6d4 0x000 0x6 0x0
-#define MX6Q_PAD_NANDF_CS3__NAND_CE3_B            0x2f0 0x6d8 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_CS3__IPU1_SISG1            0x2f0 0x6d8 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_CS3__ESAI_TX1              0x2f0 0x6d8 0x878 0x2 0x1
-#define MX6Q_PAD_NANDF_CS3__EIM_ADDR26            0x2f0 0x6d8 0x000 0x3 0x0
-#define MX6Q_PAD_NANDF_CS3__GPIO6_IO16            0x2f0 0x6d8 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_CS3__IPU2_SISG1            0x2f0 0x6d8 0x000 0x6 0x0
-#define MX6Q_PAD_SD4_CMD__SD4_CMD                 0x2f4 0x6dc 0x000 0x0 0x0
-#define MX6Q_PAD_SD4_CMD__NAND_RE_B               0x2f4 0x6dc 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_CMD__UART3_TX_DATA           0x2f4 0x6dc 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_CMD__UART3_RX_DATA           0x2f4 0x6dc 0x930 0x2 0x2
-#define MX6Q_PAD_SD4_CMD__GPIO7_IO09              0x2f4 0x6dc 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_CLK__SD4_CLK                 0x2f8 0x6e0 0x000 0x0 0x0
-#define MX6Q_PAD_SD4_CLK__NAND_WE_B               0x2f8 0x6e0 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_CLK__UART3_RX_DATA           0x2f8 0x6e0 0x930 0x2 0x3
-#define MX6Q_PAD_SD4_CLK__UART3_TX_DATA           0x2f8 0x6e0 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_CLK__GPIO7_IO10              0x2f8 0x6e0 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D0__NAND_DATA00            0x2fc 0x6e4 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D0__SD1_DATA4              0x2fc 0x6e4 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D0__GPIO2_IO00             0x2fc 0x6e4 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D1__NAND_DATA01            0x300 0x6e8 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D1__SD1_DATA5              0x300 0x6e8 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D1__GPIO2_IO01             0x300 0x6e8 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D2__NAND_DATA02            0x304 0x6ec 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D2__SD1_DATA6              0x304 0x6ec 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D2__GPIO2_IO02             0x304 0x6ec 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D3__NAND_DATA03            0x308 0x6f0 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D3__SD1_DATA7              0x308 0x6f0 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D3__GPIO2_IO03             0x308 0x6f0 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D4__NAND_DATA04            0x30c 0x6f4 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D4__SD2_DATA4              0x30c 0x6f4 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D4__GPIO2_IO04             0x30c 0x6f4 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D5__NAND_DATA05            0x310 0x6f8 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D5__SD2_DATA5              0x310 0x6f8 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D5__GPIO2_IO05             0x310 0x6f8 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D6__NAND_DATA06            0x314 0x6fc 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D6__SD2_DATA6              0x314 0x6fc 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D6__GPIO2_IO06             0x314 0x6fc 0x000 0x5 0x0
-#define MX6Q_PAD_NANDF_D7__NAND_DATA07            0x318 0x700 0x000 0x0 0x0
-#define MX6Q_PAD_NANDF_D7__SD2_DATA7              0x318 0x700 0x000 0x1 0x0
-#define MX6Q_PAD_NANDF_D7__GPIO2_IO07             0x318 0x700 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT0__SD4_DATA0              0x31c 0x704 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT0__NAND_DQS               0x31c 0x704 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT0__GPIO2_IO08             0x31c 0x704 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT1__SD4_DATA1              0x320 0x708 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT1__PWM3_OUT               0x320 0x708 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT1__GPIO2_IO09             0x320 0x708 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT2__SD4_DATA2              0x324 0x70c 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT2__PWM4_OUT               0x324 0x70c 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT2__GPIO2_IO10             0x324 0x70c 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT3__SD4_DATA3              0x328 0x710 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT3__GPIO2_IO11             0x328 0x710 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT4__SD4_DATA4              0x32c 0x714 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT4__UART2_RX_DATA          0x32c 0x714 0x928 0x2 0x6
-#define MX6Q_PAD_SD4_DAT4__UART2_TX_DATA          0x32c 0x714 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT4__GPIO2_IO12             0x32c 0x714 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT5__SD4_DATA5              0x330 0x718 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT5__UART2_RTS_B            0x330 0x718 0x924 0x2 0x4
-#define MX6Q_PAD_SD4_DAT5__UART2_CTS_B            0x330 0x718 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT5__GPIO2_IO13             0x330 0x718 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT6__SD4_DATA6              0x334 0x71c 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT6__UART2_CTS_B            0x334 0x71c 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT6__UART2_RTS_B            0x334 0x71c 0x924 0x2 0x5
-#define MX6Q_PAD_SD4_DAT6__GPIO2_IO14             0x334 0x71c 0x000 0x5 0x0
-#define MX6Q_PAD_SD4_DAT7__SD4_DATA7              0x338 0x720 0x000 0x1 0x0
-#define MX6Q_PAD_SD4_DAT7__UART2_TX_DATA          0x338 0x720 0x000 0x2 0x0
-#define MX6Q_PAD_SD4_DAT7__UART2_RX_DATA          0x338 0x720 0x928 0x2 0x7
-#define MX6Q_PAD_SD4_DAT7__GPIO2_IO15             0x338 0x720 0x000 0x5 0x0
-#define MX6Q_PAD_SD1_DAT1__SD1_DATA1              0x33c 0x724 0x000 0x0 0x0
-#define MX6Q_PAD_SD1_DAT1__ECSPI5_SS0             0x33c 0x724 0x834 0x1 0x1
-#define MX6Q_PAD_SD1_DAT1__PWM3_OUT               0x33c 0x724 0x000 0x2 0x0
-#define MX6Q_PAD_SD1_DAT1__GPT_CAPTURE2           0x33c 0x724 0x000 0x3 0x0
-#define MX6Q_PAD_SD1_DAT1__GPIO1_IO17             0x33c 0x724 0x000 0x5 0x0
-#define MX6Q_PAD_SD1_DAT0__SD1_DATA0              0x340 0x728 0x000 0x0 0x0
-#define MX6Q_PAD_SD1_DAT0__ECSPI5_MISO            0x340 0x728 0x82c 0x1 0x1
-#define MX6Q_PAD_SD1_DAT0__GPT_CAPTURE1           0x340 0x728 0x000 0x3 0x0
-#define MX6Q_PAD_SD1_DAT0__GPIO1_IO16             0x340 0x728 0x000 0x5 0x0
-#define MX6Q_PAD_SD1_DAT3__SD1_DATA3              0x344 0x72c 0x000 0x0 0x0
-#define MX6Q_PAD_SD1_DAT3__ECSPI5_SS2             0x344 0x72c 0x000 0x1 0x0
-#define MX6Q_PAD_SD1_DAT3__GPT_COMPARE3           0x344 0x72c 0x000 0x2 0x0
-#define MX6Q_PAD_SD1_DAT3__PWM1_OUT               0x344 0x72c 0x000 0x3 0x0
-#define MX6Q_PAD_SD1_DAT3__WDOG2_B                0x344 0x72c 0x000 0x4 0x0
-#define MX6Q_PAD_SD1_DAT3__GPIO1_IO21             0x344 0x72c 0x000 0x5 0x0
-#define MX6Q_PAD_SD1_DAT3__WDOG2_RESET_B_DEB      0x344 0x72c 0x000 0x6 0x0
-#define MX6Q_PAD_SD1_CMD__SD1_CMD                 0x348 0x730 0x000 0x0 0x0
-#define MX6Q_PAD_SD1_CMD__ECSPI5_MOSI             0x348 0x730 0x830 0x1 0x0
-#define MX6Q_PAD_SD1_CMD__PWM4_OUT                0x348 0x730 0x000 0x2 0x0
-#define MX6Q_PAD_SD1_CMD__GPT_COMPARE1            0x348 0x730 0x000 0x3 0x0
-#define MX6Q_PAD_SD1_CMD__GPIO1_IO18              0x348 0x730 0x000 0x5 0x0
-#define MX6Q_PAD_SD1_DAT2__SD1_DATA2              0x34c 0x734 0x000 0x0 0x0
-#define MX6Q_PAD_SD1_DAT2__ECSPI5_SS1             0x34c 0x734 0x838 0x1 0x1
-#define MX6Q_PAD_SD1_DAT2__GPT_COMPARE2           0x34c 0x734 0x000 0x2 0x0
-#define MX6Q_PAD_SD1_DAT2__PWM2_OUT               0x34c 0x734 0x000 0x3 0x0
-#define MX6Q_PAD_SD1_DAT2__WDOG1_B                0x34c 0x734 0x000 0x4 0x0
-#define MX6Q_PAD_SD1_DAT2__GPIO1_IO19             0x34c 0x734 0x000 0x5 0x0
-#define MX6Q_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x34c 0x734 0x000 0x6 0x0
-#define MX6Q_PAD_SD1_CLK__SD1_CLK                 0x350 0x738 0x000 0x0 0x0
-#define MX6Q_PAD_SD1_CLK__ECSPI5_SCLK             0x350 0x738 0x828 0x1 0x0
-#define MX6Q_PAD_SD1_CLK__GPT_CLKIN               0x350 0x738 0x000 0x3 0x0
-#define MX6Q_PAD_SD1_CLK__GPIO1_IO20              0x350 0x738 0x000 0x5 0x0
-#define MX6Q_PAD_SD2_CLK__SD2_CLK                 0x354 0x73c 0x000 0x0 0x0
-#define MX6Q_PAD_SD2_CLK__ECSPI5_SCLK             0x354 0x73c 0x828 0x1 0x1
-#define MX6Q_PAD_SD2_CLK__KEY_COL5                0x354 0x73c 0x8e8 0x2 0x3
-#define MX6Q_PAD_SD2_CLK__AUD4_RXFS               0x354 0x73c 0x7c0 0x3 0x1
-#define MX6Q_PAD_SD2_CLK__GPIO1_IO10              0x354 0x73c 0x000 0x5 0x0
-#define MX6Q_PAD_SD2_CMD__SD2_CMD                 0x358 0x740 0x000 0x0 0x0
-#define MX6Q_PAD_SD2_CMD__ECSPI5_MOSI             0x358 0x740 0x830 0x1 0x1
-#define MX6Q_PAD_SD2_CMD__KEY_ROW5                0x358 0x740 0x8f4 0x2 0x2
-#define MX6Q_PAD_SD2_CMD__AUD4_RXC                0x358 0x740 0x7bc 0x3 0x1
-#define MX6Q_PAD_SD2_CMD__GPIO1_IO11              0x358 0x740 0x000 0x5 0x0
-#define MX6Q_PAD_SD2_DAT3__SD2_DATA3              0x35c 0x744 0x000 0x0 0x0
-#define MX6Q_PAD_SD2_DAT3__ECSPI5_SS3             0x35c 0x744 0x000 0x1 0x0
-#define MX6Q_PAD_SD2_DAT3__KEY_COL6               0x35c 0x744 0x8ec 0x2 0x2
-#define MX6Q_PAD_SD2_DAT3__AUD4_TXC               0x35c 0x744 0x7c4 0x3 0x1
-#define MX6Q_PAD_SD2_DAT3__GPIO1_IO12             0x35c 0x744 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT1__SD2_DATA1              0x04c 0x360 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT1__ECSPI5_SS0             0x04c 0x360 0x834 0x1 0x0
+#define MX6QDL_PAD_SD2_DAT1__EIM_CS2_B              0x04c 0x360 0x000 0x2 0x0
+#define MX6QDL_PAD_SD2_DAT1__AUD4_TXFS              0x04c 0x360 0x7c8 0x3 0x0
+#define MX6QDL_PAD_SD2_DAT1__KEY_COL7               0x04c 0x360 0x8f0 0x4 0x0
+#define MX6QDL_PAD_SD2_DAT1__GPIO1_IO14             0x04c 0x360 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT2__SD2_DATA2              0x050 0x364 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT2__ECSPI5_SS1             0x050 0x364 0x838 0x1 0x0
+#define MX6QDL_PAD_SD2_DAT2__EIM_CS3_B              0x050 0x364 0x000 0x2 0x0
+#define MX6QDL_PAD_SD2_DAT2__AUD4_TXD               0x050 0x364 0x7b8 0x3 0x0
+#define MX6QDL_PAD_SD2_DAT2__KEY_ROW6               0x050 0x364 0x8f8 0x4 0x0
+#define MX6QDL_PAD_SD2_DAT2__GPIO1_IO13             0x050 0x364 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT0__SD2_DATA0              0x054 0x368 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT0__ECSPI5_MISO            0x054 0x368 0x82c 0x1 0x0
+#define MX6QDL_PAD_SD2_DAT0__AUD4_RXD               0x054 0x368 0x7b4 0x3 0x0
+#define MX6QDL_PAD_SD2_DAT0__KEY_ROW7               0x054 0x368 0x8fc 0x4 0x0
+#define MX6QDL_PAD_SD2_DAT0__GPIO1_IO15             0x054 0x368 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT0__DCIC2_OUT              0x054 0x368 0x000 0x6 0x0
+#define MX6QDL_PAD_RGMII_TXC__USB_H2_DATA           0x058 0x36c 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TXC__RGMII_TXC             0x058 0x36c 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TXC__SPDIF_EXT_CLK         0x058 0x36c 0x918 0x2 0x0
+#define MX6QDL_PAD_RGMII_TXC__GPIO6_IO19            0x058 0x36c 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x058 0x36c 0x000 0x7 0x0
+#define MX6QDL_PAD_RGMII_TD0__HSI_TX_READY          0x05c 0x370 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD0__RGMII_TD0             0x05c 0x370 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD0__GPIO6_IO20            0x05c 0x370 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD1__HSI_RX_FLAG           0x060 0x374 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD1__RGMII_TD1             0x060 0x374 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD1__GPIO6_IO21            0x060 0x374 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD2__HSI_RX_DATA           0x064 0x378 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD2__RGMII_TD2             0x064 0x378 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD2__GPIO6_IO22            0x064 0x378 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TD3__HSI_RX_WAKE           0x068 0x37c 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TD3__RGMII_TD3             0x068 0x37c 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TD3__GPIO6_IO23            0x068 0x37c 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA        0x06c 0x380 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL       0x06c 0x380 0x858 0x1 0x0
+#define MX6QDL_PAD_RGMII_RX_CTL__GPIO6_IO24         0x06c 0x380 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RD0__HSI_RX_READY          0x070 0x384 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD0__RGMII_RD0             0x070 0x384 0x848 0x1 0x0
+#define MX6QDL_PAD_RGMII_RD0__GPIO6_IO25            0x070 0x384 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE      0x074 0x388 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL       0x074 0x388 0x000 0x1 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__GPIO6_IO26         0x074 0x388 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_TX_CTL__ENET_REF_CLK       0x074 0x388 0x83c 0x7 0x0
+#define MX6QDL_PAD_RGMII_RD1__HSI_TX_FLAG           0x078 0x38c 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD1__RGMII_RD1             0x078 0x38c 0x84c 0x1 0x0
+#define MX6QDL_PAD_RGMII_RD1__GPIO6_IO27            0x078 0x38c 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RD2__HSI_TX_DATA           0x07c 0x390 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD2__RGMII_RD2             0x07c 0x390 0x850 0x1 0x0
+#define MX6QDL_PAD_RGMII_RD2__GPIO6_IO28            0x07c 0x390 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RD3__HSI_TX_WAKE           0x080 0x394 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RD3__RGMII_RD3             0x080 0x394 0x854 0x1 0x0
+#define MX6QDL_PAD_RGMII_RD3__GPIO6_IO29            0x080 0x394 0x000 0x5 0x0
+#define MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE         0x084 0x398 0x000 0x0 0x0
+#define MX6QDL_PAD_RGMII_RXC__RGMII_RXC             0x084 0x398 0x844 0x1 0x0
+#define MX6QDL_PAD_RGMII_RXC__GPIO6_IO30            0x084 0x398 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A25__EIM_ADDR25              0x088 0x39c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A25__ECSPI4_SS1              0x088 0x39c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A25__ECSPI2_RDY              0x088 0x39c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_A25__IPU1_DI1_PIN12          0x088 0x39c 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_A25__IPU1_DI0_D1_CS          0x088 0x39c 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_A25__GPIO5_IO02              0x088 0x39c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE        0x088 0x39c 0x88c 0x6 0x0
+#define MX6QDL_PAD_EIM_EB2__EIM_EB2_B               0x08c 0x3a0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB2__ECSPI1_SS0              0x08c 0x3a0 0x800 0x1 0x0
+#define MX6QDL_PAD_EIM_EB2__IPU2_CSI1_DATA19        0x08c 0x3a0 0x8d4 0x3 0x0
+#define MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL         0x08c 0x3a0 0x890 0x4 0x0
+#define MX6QDL_PAD_EIM_EB2__GPIO2_IO30              0x08c 0x3a0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB2__I2C2_SCL                0x08c 0x3a0 0x8a0 0x6 0x0
+#define MX6QDL_PAD_EIM_EB2__SRC_BOOT_CFG30          0x08c 0x3a0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D16__EIM_DATA16              0x090 0x3a4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D16__ECSPI1_SCLK             0x090 0x3a4 0x7f4 0x1 0x0
+#define MX6QDL_PAD_EIM_D16__IPU1_DI0_PIN05          0x090 0x3a4 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D16__IPU2_CSI1_DATA18        0x090 0x3a4 0x8d0 0x3 0x0
+#define MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA         0x090 0x3a4 0x894 0x4 0x0
+#define MX6QDL_PAD_EIM_D16__GPIO3_IO16              0x090 0x3a4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D16__I2C2_SDA                0x090 0x3a4 0x8a4 0x6 0x0
+#define MX6QDL_PAD_EIM_D17__EIM_DATA17              0x094 0x3a8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D17__ECSPI1_MISO             0x094 0x3a8 0x7f8 0x1 0x0
+#define MX6QDL_PAD_EIM_D17__IPU1_DI0_PIN06          0x094 0x3a8 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D17__IPU2_CSI1_PIXCLK        0x094 0x3a8 0x8e0 0x3 0x0
+#define MX6QDL_PAD_EIM_D17__DCIC1_OUT               0x094 0x3a8 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D17__GPIO3_IO17              0x094 0x3a8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D17__I2C3_SCL                0x094 0x3a8 0x8a8 0x6 0x0
+#define MX6QDL_PAD_EIM_D18__EIM_DATA18              0x098 0x3ac 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D18__ECSPI1_MOSI             0x098 0x3ac 0x7fc 0x1 0x0
+#define MX6QDL_PAD_EIM_D18__IPU1_DI0_PIN07          0x098 0x3ac 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D18__IPU2_CSI1_DATA17        0x098 0x3ac 0x8cc 0x3 0x0
+#define MX6QDL_PAD_EIM_D18__IPU1_DI1_D0_CS          0x098 0x3ac 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D18__GPIO3_IO18              0x098 0x3ac 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D18__I2C3_SDA                0x098 0x3ac 0x8ac 0x6 0x0
+#define MX6QDL_PAD_EIM_D19__EIM_DATA19              0x09c 0x3b0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D19__ECSPI1_SS1              0x09c 0x3b0 0x804 0x1 0x0
+#define MX6QDL_PAD_EIM_D19__IPU1_DI0_PIN08          0x09c 0x3b0 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D19__IPU2_CSI1_DATA16        0x09c 0x3b0 0x8c8 0x3 0x0
+#define MX6QDL_PAD_EIM_D19__UART1_CTS_B             0x09c 0x3b0 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D19__UART1_RTS_B             0x09c 0x3b0 0x91c 0x4 0x0
+#define MX6QDL_PAD_EIM_D19__GPIO3_IO19              0x09c 0x3b0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D19__EPIT1_OUT               0x09c 0x3b0 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D20__EIM_DATA20              0x0a0 0x3b4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D20__ECSPI4_SS0              0x0a0 0x3b4 0x824 0x1 0x0
+#define MX6QDL_PAD_EIM_D20__IPU1_DI0_PIN16          0x0a0 0x3b4 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D20__IPU2_CSI1_DATA15        0x0a0 0x3b4 0x8c4 0x3 0x0
+#define MX6QDL_PAD_EIM_D20__UART1_RTS_B             0x0a0 0x3b4 0x91c 0x4 0x1
+#define MX6QDL_PAD_EIM_D20__UART1_CTS_B             0x0a0 0x3b4 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D20__GPIO3_IO20              0x0a0 0x3b4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D20__EPIT2_OUT               0x0a0 0x3b4 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D21__EIM_DATA21              0x0a4 0x3b8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D21__ECSPI4_SCLK             0x0a4 0x3b8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D21__IPU1_DI0_PIN17          0x0a4 0x3b8 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D21__IPU2_CSI1_DATA11        0x0a4 0x3b8 0x8b4 0x3 0x0
+#define MX6QDL_PAD_EIM_D21__USB_OTG_OC              0x0a4 0x3b8 0x944 0x4 0x0
+#define MX6QDL_PAD_EIM_D21__GPIO3_IO21              0x0a4 0x3b8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D21__I2C1_SCL                0x0a4 0x3b8 0x898 0x6 0x0
+#define MX6QDL_PAD_EIM_D21__SPDIF_IN                0x0a4 0x3b8 0x914 0x7 0x0
+#define MX6QDL_PAD_EIM_D22__EIM_DATA22              0x0a8 0x3bc 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D22__ECSPI4_MISO             0x0a8 0x3bc 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D22__IPU1_DI0_PIN01          0x0a8 0x3bc 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D22__IPU2_CSI1_DATA10        0x0a8 0x3bc 0x8b0 0x3 0x0
+#define MX6QDL_PAD_EIM_D22__USB_OTG_PWR             0x0a8 0x3bc 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D22__GPIO3_IO22              0x0a8 0x3bc 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D22__SPDIF_OUT               0x0a8 0x3bc 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D23__EIM_DATA23              0x0ac 0x3c0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_DI0_D0_CS          0x0ac 0x3c0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D23__UART3_CTS_B             0x0ac 0x3c0 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D23__UART3_RTS_B             0x0ac 0x3c0 0x92c 0x2 0x0
+#define MX6QDL_PAD_EIM_D23__UART1_DCD_B             0x0ac 0x3c0 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_D23__IPU2_CSI1_DATA_EN       0x0ac 0x3c0 0x8d8 0x4 0x0
+#define MX6QDL_PAD_EIM_D23__GPIO3_IO23              0x0ac 0x3c0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_DI1_PIN02          0x0ac 0x3c0 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D23__IPU1_DI1_PIN14          0x0ac 0x3c0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB3__EIM_EB3_B               0x0b0 0x3c4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB3__ECSPI4_RDY              0x0b0 0x3c4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_EB3__UART3_RTS_B             0x0b0 0x3c4 0x92c 0x2 0x1
+#define MX6QDL_PAD_EIM_EB3__UART3_CTS_B             0x0b0 0x3c4 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_EB3__UART1_RI_B              0x0b0 0x3c4 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_EB3__IPU2_CSI1_HSYNC         0x0b0 0x3c4 0x8dc 0x4 0x0
+#define MX6QDL_PAD_EIM_EB3__GPIO2_IO31              0x0b0 0x3c4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB3__IPU1_DI1_PIN03          0x0b0 0x3c4 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_EB3__SRC_BOOT_CFG31          0x0b0 0x3c4 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D24__EIM_DATA24              0x0b4 0x3c8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D24__ECSPI4_SS2              0x0b4 0x3c8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D24__UART3_TX_DATA           0x0b4 0x3c8 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D24__UART3_RX_DATA           0x0b4 0x3c8 0x930 0x2 0x0
+#define MX6QDL_PAD_EIM_D24__ECSPI1_SS2              0x0b4 0x3c8 0x808 0x3 0x0
+#define MX6QDL_PAD_EIM_D24__ECSPI2_SS2              0x0b4 0x3c8 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D24__GPIO3_IO24              0x0b4 0x3c8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D24__AUD5_RXFS               0x0b4 0x3c8 0x7d8 0x6 0x0
+#define MX6QDL_PAD_EIM_D24__UART1_DTR_B             0x0b4 0x3c8 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D25__EIM_DATA25              0x0b8 0x3cc 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D25__ECSPI4_SS3              0x0b8 0x3cc 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D25__UART3_RX_DATA           0x0b8 0x3cc 0x930 0x2 0x1
+#define MX6QDL_PAD_EIM_D25__UART3_TX_DATA           0x0b8 0x3cc 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D25__ECSPI1_SS3              0x0b8 0x3cc 0x80c 0x3 0x0
+#define MX6QDL_PAD_EIM_D25__ECSPI2_SS3              0x0b8 0x3cc 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D25__GPIO3_IO25              0x0b8 0x3cc 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D25__AUD5_RXC                0x0b8 0x3cc 0x7d4 0x6 0x0
+#define MX6QDL_PAD_EIM_D25__UART1_DSR_B             0x0b8 0x3cc 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D26__EIM_DATA26              0x0bc 0x3d0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_DI1_PIN11          0x0bc 0x3d0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_CSI0_DATA01        0x0bc 0x3d0 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D26__IPU2_CSI1_DATA14        0x0bc 0x3d0 0x8c0 0x3 0x0
+#define MX6QDL_PAD_EIM_D26__UART2_TX_DATA           0x0bc 0x3d0 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D26__UART2_RX_DATA           0x0bc 0x3d0 0x928 0x4 0x0
+#define MX6QDL_PAD_EIM_D26__GPIO3_IO26              0x0bc 0x3d0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_SISG2              0x0bc 0x3d0 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D26__IPU1_DISP1_DATA22       0x0bc 0x3d0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D27__EIM_DATA27              0x0c0 0x3d4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_DI1_PIN13          0x0c0 0x3d4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_CSI0_DATA00        0x0c0 0x3d4 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D27__IPU2_CSI1_DATA13        0x0c0 0x3d4 0x8bc 0x3 0x0
+#define MX6QDL_PAD_EIM_D27__UART2_RX_DATA           0x0c0 0x3d4 0x928 0x4 0x1
+#define MX6QDL_PAD_EIM_D27__UART2_TX_DATA           0x0c0 0x3d4 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D27__GPIO3_IO27              0x0c0 0x3d4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_SISG3              0x0c0 0x3d4 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D27__IPU1_DISP1_DATA23       0x0c0 0x3d4 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D28__EIM_DATA28              0x0c4 0x3d8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D28__I2C1_SDA                0x0c4 0x3d8 0x89c 0x1 0x0
+#define MX6QDL_PAD_EIM_D28__ECSPI4_MOSI             0x0c4 0x3d8 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D28__IPU2_CSI1_DATA12        0x0c4 0x3d8 0x8b8 0x3 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_CTS_B             0x0c4 0x3d8 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_RTS_B             0x0c4 0x3d8 0x924 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B         0x0c4 0x3d8 0x924 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__UART2_DTE_RTS_B         0x0c4 0x3d8 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D28__GPIO3_IO28              0x0c4 0x3d8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D28__IPU1_EXT_TRIG           0x0c4 0x3d8 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_D28__IPU1_DI0_PIN13          0x0c4 0x3d8 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D29__EIM_DATA29              0x0c8 0x3dc 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D29__IPU1_DI1_PIN15          0x0c8 0x3dc 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D29__ECSPI4_SS0              0x0c8 0x3dc 0x824 0x2 0x1
+#define MX6QDL_PAD_EIM_D29__UART2_RTS_B             0x0c8 0x3dc 0x924 0x4 0x1
+#define MX6QDL_PAD_EIM_D29__UART2_CTS_B             0x0c8 0x3dc 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B         0x0c4 0x3dc 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D29__UART2_DTE_CTS_B         0x0c4 0x3dc 0x924 0x4 0x1
+#define MX6QDL_PAD_EIM_D29__GPIO3_IO29              0x0c8 0x3dc 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D29__IPU2_CSI1_VSYNC         0x0c8 0x3dc 0x8e4 0x6 0x0
+#define MX6QDL_PAD_EIM_D29__IPU1_DI0_PIN14          0x0c8 0x3dc 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_D30__EIM_DATA30              0x0cc 0x3e0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D30__IPU1_DISP1_DATA21       0x0cc 0x3e0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D30__IPU1_DI0_PIN11          0x0cc 0x3e0 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D30__IPU1_CSI0_DATA03        0x0cc 0x3e0 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_D30__UART3_CTS_B             0x0cc 0x3e0 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D30__UART3_RTS_B             0x0cc 0x3e0 0x92c 0x4 0x2
+#define MX6QDL_PAD_EIM_D30__GPIO3_IO30              0x0cc 0x3e0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D30__USB_H1_OC               0x0cc 0x3e0 0x948 0x6 0x0
+#define MX6QDL_PAD_EIM_D31__EIM_DATA31              0x0d0 0x3e4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_D31__IPU1_DISP1_DATA20       0x0d0 0x3e4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_D31__IPU1_DI0_PIN12          0x0d0 0x3e4 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_D31__IPU1_CSI0_DATA02        0x0d0 0x3e4 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_D31__UART3_RTS_B             0x0d0 0x3e4 0x92c 0x4 0x3
+#define MX6QDL_PAD_EIM_D31__UART3_CTS_B             0x0d0 0x3e4 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D31__GPIO3_IO31              0x0d0 0x3e4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_D31__USB_H1_PWR              0x0d0 0x3e4 0x000 0x6 0x0
+#define MX6QDL_PAD_EIM_A24__EIM_ADDR24              0x0d4 0x3e8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A24__IPU1_DISP1_DATA19       0x0d4 0x3e8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A24__IPU2_CSI1_DATA19        0x0d4 0x3e8 0x8d4 0x2 0x1
+#define MX6QDL_PAD_EIM_A24__IPU2_SISG2              0x0d4 0x3e8 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_A24__IPU1_SISG2              0x0d4 0x3e8 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_A24__GPIO5_IO04              0x0d4 0x3e8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A24__SRC_BOOT_CFG24          0x0d4 0x3e8 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A23__EIM_ADDR23              0x0d8 0x3ec 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A23__IPU1_DISP1_DATA18       0x0d8 0x3ec 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A23__IPU2_CSI1_DATA18        0x0d8 0x3ec 0x8d0 0x2 0x1
+#define MX6QDL_PAD_EIM_A23__IPU2_SISG3              0x0d8 0x3ec 0x000 0x3 0x0
+#define MX6QDL_PAD_EIM_A23__IPU1_SISG3              0x0d8 0x3ec 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_A23__GPIO6_IO06              0x0d8 0x3ec 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A23__SRC_BOOT_CFG23          0x0d8 0x3ec 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A22__EIM_ADDR22              0x0dc 0x3f0 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A22__IPU1_DISP1_DATA17       0x0dc 0x3f0 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A22__IPU2_CSI1_DATA17        0x0dc 0x3f0 0x8cc 0x2 0x1
+#define MX6QDL_PAD_EIM_A22__GPIO2_IO16              0x0dc 0x3f0 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A22__SRC_BOOT_CFG22          0x0dc 0x3f0 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A21__EIM_ADDR21              0x0e0 0x3f4 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A21__IPU1_DISP1_DATA16       0x0e0 0x3f4 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A21__IPU2_CSI1_DATA16        0x0e0 0x3f4 0x8c8 0x2 0x1
+#define MX6QDL_PAD_EIM_A21__GPIO2_IO17              0x0e0 0x3f4 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A21__SRC_BOOT_CFG21          0x0e0 0x3f4 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A20__EIM_ADDR20              0x0e4 0x3f8 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A20__IPU1_DISP1_DATA15       0x0e4 0x3f8 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A20__IPU2_CSI1_DATA15        0x0e4 0x3f8 0x8c4 0x2 0x1
+#define MX6QDL_PAD_EIM_A20__GPIO2_IO18              0x0e4 0x3f8 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A20__SRC_BOOT_CFG20          0x0e4 0x3f8 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A19__EIM_ADDR19              0x0e8 0x3fc 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A19__IPU1_DISP1_DATA14       0x0e8 0x3fc 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A19__IPU2_CSI1_DATA14        0x0e8 0x3fc 0x8c0 0x2 0x1
+#define MX6QDL_PAD_EIM_A19__GPIO2_IO19              0x0e8 0x3fc 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A19__SRC_BOOT_CFG19          0x0e8 0x3fc 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A18__EIM_ADDR18              0x0ec 0x400 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A18__IPU1_DISP1_DATA13       0x0ec 0x400 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A18__IPU2_CSI1_DATA13        0x0ec 0x400 0x8bc 0x2 0x1
+#define MX6QDL_PAD_EIM_A18__GPIO2_IO20              0x0ec 0x400 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A18__SRC_BOOT_CFG18          0x0ec 0x400 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A17__EIM_ADDR17              0x0f0 0x404 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A17__IPU1_DISP1_DATA12       0x0f0 0x404 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A17__IPU2_CSI1_DATA12        0x0f0 0x404 0x8b8 0x2 0x1
+#define MX6QDL_PAD_EIM_A17__GPIO2_IO21              0x0f0 0x404 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A17__SRC_BOOT_CFG17          0x0f0 0x404 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_A16__EIM_ADDR16              0x0f4 0x408 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_A16__IPU1_DI1_DISP_CLK       0x0f4 0x408 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_A16__IPU2_CSI1_PIXCLK        0x0f4 0x408 0x8e0 0x2 0x1
+#define MX6QDL_PAD_EIM_A16__GPIO2_IO22              0x0f4 0x408 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_A16__SRC_BOOT_CFG16          0x0f4 0x408 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_CS0__EIM_CS0_B               0x0f8 0x40c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_CS0__IPU1_DI1_PIN05          0x0f8 0x40c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK             0x0f8 0x40c 0x810 0x2 0x0
+#define MX6QDL_PAD_EIM_CS0__GPIO2_IO23              0x0f8 0x40c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_CS1__EIM_CS1_B               0x0fc 0x410 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_CS1__IPU1_DI1_PIN06          0x0fc 0x410 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI             0x0fc 0x410 0x818 0x2 0x0
+#define MX6QDL_PAD_EIM_CS1__GPIO2_IO24              0x0fc 0x410 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_OE__EIM_OE_B                 0x100 0x414 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_OE__IPU1_DI1_PIN07           0x100 0x414 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_OE__ECSPI2_MISO              0x100 0x414 0x814 0x2 0x0
+#define MX6QDL_PAD_EIM_OE__GPIO2_IO25               0x100 0x414 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_RW__EIM_RW                   0x104 0x418 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_RW__IPU1_DI1_PIN08           0x104 0x418 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_RW__ECSPI2_SS0               0x104 0x418 0x81c 0x2 0x0
+#define MX6QDL_PAD_EIM_RW__GPIO2_IO26               0x104 0x418 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_RW__SRC_BOOT_CFG29           0x104 0x418 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_LBA__EIM_LBA_B               0x108 0x41c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_LBA__IPU1_DI1_PIN17          0x108 0x41c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_LBA__ECSPI2_SS1              0x108 0x41c 0x820 0x2 0x0
+#define MX6QDL_PAD_EIM_LBA__GPIO2_IO27              0x108 0x41c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_LBA__SRC_BOOT_CFG26          0x108 0x41c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB0__EIM_EB0_B               0x10c 0x420 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB0__IPU1_DISP1_DATA11       0x10c 0x420 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_EB0__IPU2_CSI1_DATA11        0x10c 0x420 0x8b4 0x2 0x1
+#define MX6QDL_PAD_EIM_EB0__CCM_PMIC_READY          0x10c 0x420 0x7f0 0x4 0x0
+#define MX6QDL_PAD_EIM_EB0__GPIO2_IO28              0x10c 0x420 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB0__SRC_BOOT_CFG27          0x10c 0x420 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_EB1__EIM_EB1_B               0x110 0x424 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_EB1__IPU1_DISP1_DATA10       0x110 0x424 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_EB1__IPU2_CSI1_DATA10        0x110 0x424 0x8b0 0x2 0x1
+#define MX6QDL_PAD_EIM_EB1__GPIO2_IO29              0x110 0x424 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_EB1__SRC_BOOT_CFG28          0x110 0x424 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA0__EIM_AD00                0x114 0x428 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA0__IPU1_DISP1_DATA09       0x114 0x428 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA0__IPU2_CSI1_DATA09        0x114 0x428 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA0__GPIO3_IO00              0x114 0x428 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA0__SRC_BOOT_CFG00          0x114 0x428 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA1__EIM_AD01                0x118 0x42c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA1__IPU1_DISP1_DATA08       0x118 0x42c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA1__IPU2_CSI1_DATA08        0x118 0x42c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA1__GPIO3_IO01              0x118 0x42c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA1__SRC_BOOT_CFG01          0x118 0x42c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA2__EIM_AD02                0x11c 0x430 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA2__IPU1_DISP1_DATA07       0x11c 0x430 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA2__IPU2_CSI1_DATA07        0x11c 0x430 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA2__GPIO3_IO02              0x11c 0x430 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA2__SRC_BOOT_CFG02          0x11c 0x430 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA3__EIM_AD03                0x120 0x434 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA3__IPU1_DISP1_DATA06       0x120 0x434 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA3__IPU2_CSI1_DATA06        0x120 0x434 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA3__GPIO3_IO03              0x120 0x434 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA3__SRC_BOOT_CFG03          0x120 0x434 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA4__EIM_AD04                0x124 0x438 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA4__IPU1_DISP1_DATA05       0x124 0x438 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA4__IPU2_CSI1_DATA05        0x124 0x438 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA4__GPIO3_IO04              0x124 0x438 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA4__SRC_BOOT_CFG04          0x124 0x438 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA5__EIM_AD05                0x128 0x43c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA5__IPU1_DISP1_DATA04       0x128 0x43c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA5__IPU2_CSI1_DATA04        0x128 0x43c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA5__GPIO3_IO05              0x128 0x43c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA5__SRC_BOOT_CFG05          0x128 0x43c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA6__EIM_AD06                0x12c 0x440 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA6__IPU1_DISP1_DATA03       0x12c 0x440 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA6__IPU2_CSI1_DATA03        0x12c 0x440 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA6__GPIO3_IO06              0x12c 0x440 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA6__SRC_BOOT_CFG06          0x12c 0x440 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA7__EIM_AD07                0x130 0x444 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA7__IPU1_DISP1_DATA02       0x130 0x444 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA7__IPU2_CSI1_DATA02        0x130 0x444 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA7__GPIO3_IO07              0x130 0x444 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA7__SRC_BOOT_CFG07          0x130 0x444 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA8__EIM_AD08                0x134 0x448 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA8__IPU1_DISP1_DATA01       0x134 0x448 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA8__IPU2_CSI1_DATA01        0x134 0x448 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA8__GPIO3_IO08              0x134 0x448 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA8__SRC_BOOT_CFG08          0x134 0x448 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA9__EIM_AD09                0x138 0x44c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA9__IPU1_DISP1_DATA00       0x138 0x44c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA9__IPU2_CSI1_DATA00        0x138 0x44c 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA9__GPIO3_IO09              0x138 0x44c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA9__SRC_BOOT_CFG09          0x138 0x44c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA10__EIM_AD10               0x13c 0x450 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA10__IPU1_DI1_PIN15         0x13c 0x450 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA10__IPU2_CSI1_DATA_EN      0x13c 0x450 0x8d8 0x2 0x1
+#define MX6QDL_PAD_EIM_DA10__GPIO3_IO10             0x13c 0x450 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA10__SRC_BOOT_CFG10         0x13c 0x450 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA11__EIM_AD11               0x140 0x454 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA11__IPU1_DI1_PIN02         0x140 0x454 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA11__IPU2_CSI1_HSYNC        0x140 0x454 0x8dc 0x2 0x1
+#define MX6QDL_PAD_EIM_DA11__GPIO3_IO11             0x140 0x454 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA11__SRC_BOOT_CFG11         0x140 0x454 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA12__EIM_AD12               0x144 0x458 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA12__IPU1_DI1_PIN03         0x144 0x458 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA12__IPU2_CSI1_VSYNC        0x144 0x458 0x8e4 0x2 0x1
+#define MX6QDL_PAD_EIM_DA12__GPIO3_IO12             0x144 0x458 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA12__SRC_BOOT_CFG12         0x144 0x458 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA13__EIM_AD13               0x148 0x45c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA13__IPU1_DI1_D0_CS         0x148 0x45c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA13__GPIO3_IO13             0x148 0x45c 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA13__SRC_BOOT_CFG13         0x148 0x45c 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA14__EIM_AD14               0x14c 0x460 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA14__IPU1_DI1_D1_CS         0x14c 0x460 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA14__GPIO3_IO14             0x14c 0x460 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA14__SRC_BOOT_CFG14         0x14c 0x460 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_DA15__EIM_AD15               0x150 0x464 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_DA15__IPU1_DI1_PIN01         0x150 0x464 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_DA15__IPU1_DI1_PIN04         0x150 0x464 0x000 0x2 0x0
+#define MX6QDL_PAD_EIM_DA15__GPIO3_IO15             0x150 0x464 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_DA15__SRC_BOOT_CFG15         0x150 0x464 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B             0x154 0x468 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_WAIT__EIM_DTACK_B            0x154 0x468 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_WAIT__GPIO5_IO00             0x154 0x468 0x000 0x5 0x0
+#define MX6QDL_PAD_EIM_WAIT__SRC_BOOT_CFG25         0x154 0x468 0x000 0x7 0x0
+#define MX6QDL_PAD_EIM_BCLK__EIM_BCLK               0x158 0x46c 0x000 0x0 0x0
+#define MX6QDL_PAD_EIM_BCLK__IPU1_DI1_PIN16         0x158 0x46c 0x000 0x1 0x0
+#define MX6QDL_PAD_EIM_BCLK__GPIO6_IO31             0x158 0x46c 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK  0x15c 0x470 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__IPU2_DI0_DISP_CLK  0x15c 0x470 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_DISP_CLK__GPIO4_IO16         0x15c 0x470 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15        0x160 0x474 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN15__IPU2_DI0_PIN15        0x160 0x474 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN15__AUD6_TXC              0x160 0x474 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN15__GPIO4_IO17            0x160 0x474 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02         0x164 0x478 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN2__IPU2_DI0_PIN02         0x164 0x478 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN2__AUD6_TXD               0x164 0x478 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN2__GPIO4_IO18             0x164 0x478 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03         0x168 0x47c 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN3__IPU2_DI0_PIN03         0x168 0x47c 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN3__AUD6_TXFS              0x168 0x47c 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN3__GPIO4_IO19             0x168 0x47c 0x000 0x5 0x0
+#define MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04         0x16c 0x480 0x000 0x0 0x0
+#define MX6QDL_PAD_DI0_PIN4__IPU2_DI0_PIN04         0x16c 0x480 0x000 0x1 0x0
+#define MX6QDL_PAD_DI0_PIN4__AUD6_RXD               0x16c 0x480 0x000 0x2 0x0
+#define MX6QDL_PAD_DI0_PIN4__SD1_WP                 0x16c 0x480 0x94c 0x3 0x0
+#define MX6QDL_PAD_DI0_PIN4__GPIO4_IO20             0x16c 0x480 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00    0x170 0x484 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT0__IPU2_DISP0_DATA00    0x170 0x484 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK          0x170 0x484 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21           0x170 0x484 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01    0x174 0x488 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT1__IPU2_DISP0_DATA01    0x174 0x488 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI          0x174 0x488 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT1__GPIO4_IO22           0x174 0x488 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02    0x178 0x48c 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT2__IPU2_DISP0_DATA02    0x178 0x48c 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO          0x178 0x48c 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT2__GPIO4_IO23           0x178 0x48c 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03    0x17c 0x490 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT3__IPU2_DISP0_DATA03    0x17c 0x490 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT3__ECSPI3_SS0           0x17c 0x490 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24           0x17c 0x490 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04    0x180 0x494 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT4__IPU2_DISP0_DATA04    0x180 0x494 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT4__ECSPI3_SS1           0x180 0x494 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25           0x180 0x494 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05    0x184 0x498 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT5__IPU2_DISP0_DATA05    0x184 0x498 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT5__ECSPI3_SS2           0x184 0x498 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT5__AUD6_RXFS            0x184 0x498 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26           0x184 0x498 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06    0x188 0x49c 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT6__IPU2_DISP0_DATA06    0x188 0x49c 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT6__ECSPI3_SS3           0x188 0x49c 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT6__AUD6_RXC             0x188 0x49c 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27           0x188 0x49c 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07    0x18c 0x4a0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT7__IPU2_DISP0_DATA07    0x18c 0x4a0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT7__ECSPI3_RDY           0x18c 0x4a0 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT7__GPIO4_IO28           0x18c 0x4a0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08    0x190 0x4a4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT8__IPU2_DISP0_DATA08    0x190 0x4a4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT8__PWM1_OUT             0x190 0x4a4 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT8__WDOG1_B              0x190 0x4a4 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29           0x190 0x4a4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09    0x194 0x4a8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT9__IPU2_DISP0_DATA09    0x194 0x4a8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT9__PWM2_OUT             0x194 0x4a8 0x000 0x2 0x0
+#define MX6QDL_PAD_DISP0_DAT9__WDOG2_B              0x194 0x4a8 0x000 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30           0x194 0x4a8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10   0x198 0x4ac 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT10__IPU2_DISP0_DATA10   0x198 0x4ac 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT10__GPIO4_IO31          0x198 0x4ac 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11   0x19c 0x4b0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT11__IPU2_DISP0_DATA11   0x19c 0x4b0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05          0x19c 0x4b0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12   0x1a0 0x4b4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT12__IPU2_DISP0_DATA12   0x1a0 0x4b4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06          0x1a0 0x4b4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13   0x1a4 0x4b8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT13__IPU2_DISP0_DATA13   0x1a4 0x4b8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT13__AUD5_RXFS           0x1a4 0x4b8 0x7d8 0x3 0x1
+#define MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07          0x1a4 0x4b8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14   0x1a8 0x4bc 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT14__IPU2_DISP0_DATA14   0x1a8 0x4bc 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT14__AUD5_RXC            0x1a8 0x4bc 0x7d4 0x3 0x1
+#define MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08          0x1a8 0x4bc 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15   0x1ac 0x4c0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT15__IPU2_DISP0_DATA15   0x1ac 0x4c0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT15__ECSPI1_SS1          0x1ac 0x4c0 0x804 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT15__ECSPI2_SS1          0x1ac 0x4c0 0x820 0x3 0x1
+#define MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09          0x1ac 0x4c0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16   0x1b0 0x4c4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT16__IPU2_DISP0_DATA16   0x1b0 0x4c4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI         0x1b0 0x4c4 0x818 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT16__AUD5_TXC            0x1b0 0x4c4 0x7dc 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT16__SDMA_EXT_EVENT0     0x1b0 0x4c4 0x90c 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10          0x1b0 0x4c4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17   0x1b4 0x4c8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT17__IPU2_DISP0_DATA17   0x1b4 0x4c8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO         0x1b4 0x4c8 0x814 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT17__AUD5_TXD            0x1b4 0x4c8 0x7d0 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT17__SDMA_EXT_EVENT1     0x1b4 0x4c8 0x910 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11          0x1b4 0x4c8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18   0x1b8 0x4cc 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT18__IPU2_DISP0_DATA18   0x1b8 0x4cc 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT18__ECSPI2_SS0          0x1b8 0x4cc 0x81c 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS           0x1b8 0x4cc 0x7e0 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT18__AUD4_RXFS           0x1b8 0x4cc 0x7c0 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12          0x1b8 0x4cc 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT18__EIM_CS2_B           0x1b8 0x4cc 0x000 0x7 0x0
+#define MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19   0x1bc 0x4d0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT19__IPU2_DISP0_DATA19   0x1bc 0x4d0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK         0x1bc 0x4d0 0x810 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT19__AUD5_RXD            0x1bc 0x4d0 0x7cc 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT19__AUD4_RXC            0x1bc 0x4d0 0x7bc 0x4 0x0
+#define MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13          0x1bc 0x4d0 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT19__EIM_CS3_B           0x1bc 0x4d0 0x000 0x7 0x0
+#define MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20   0x1c0 0x4d4 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT20__IPU2_DISP0_DATA20   0x1c0 0x4d4 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT20__ECSPI1_SCLK         0x1c0 0x4d4 0x7f4 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT20__AUD4_TXC            0x1c0 0x4d4 0x7c4 0x3 0x0
+#define MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14          0x1c0 0x4d4 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21   0x1c4 0x4d8 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT21__IPU2_DISP0_DATA21   0x1c4 0x4d8 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT21__ECSPI1_MOSI         0x1c4 0x4d8 0x7fc 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT21__AUD4_TXD            0x1c4 0x4d8 0x7b8 0x3 0x1
+#define MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15          0x1c4 0x4d8 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22   0x1c8 0x4dc 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT22__IPU2_DISP0_DATA22   0x1c8 0x4dc 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT22__ECSPI1_MISO         0x1c8 0x4dc 0x7f8 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS           0x1c8 0x4dc 0x7c8 0x3 0x1
+#define MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16          0x1c8 0x4dc 0x000 0x5 0x0
+#define MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23   0x1cc 0x4e0 0x000 0x0 0x0
+#define MX6QDL_PAD_DISP0_DAT23__IPU2_DISP0_DATA23   0x1cc 0x4e0 0x000 0x1 0x0
+#define MX6QDL_PAD_DISP0_DAT23__ECSPI1_SS0          0x1cc 0x4e0 0x800 0x2 0x1
+#define MX6QDL_PAD_DISP0_DAT23__AUD4_RXD            0x1cc 0x4e0 0x7b4 0x3 0x1
+#define MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17          0x1cc 0x4e0 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_MDIO__ENET_MDIO             0x1d0 0x4e4 0x840 0x1 0x0
+#define MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK           0x1d0 0x4e4 0x86c 0x2 0x0
+#define MX6QDL_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT  0x1d0 0x4e4 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_MDIO__GPIO1_IO22            0x1d0 0x4e4 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_MDIO__SPDIF_LOCK            0x1d0 0x4e4 0x000 0x6 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK        0x1d4 0x4e8 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__ESAI_RX_FS         0x1d4 0x4e8 0x85c 0x2 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23         0x1d4 0x4e8 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_REF_CLK__SPDIF_SR_CLK       0x1d4 0x4e8 0x000 0x6 0x0
+#define MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID           0x1d8 0x4ec 0x000 0x0 0x0
+#define MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER           0x1d8 0x4ec 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_RX_ER__ESAI_RX_HF_CLK       0x1d8 0x4ec 0x864 0x2 0x0
+#define MX6QDL_PAD_ENET_RX_ER__SPDIF_IN             0x1d8 0x4ec 0x914 0x3 0x1
+#define MX6QDL_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT 0x1d8 0x4ec 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24           0x1d8 0x4ec 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN          0x1dc 0x4f0 0x858 0x1 0x1
+#define MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK         0x1dc 0x4f0 0x870 0x2 0x0
+#define MX6QDL_PAD_ENET_CRS_DV__SPDIF_EXT_CLK       0x1dc 0x4f0 0x918 0x3 0x1
+#define MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25          0x1dc 0x4f0 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_RXD1__MLB_SIG               0x1e0 0x4f4 0x908 0x0 0x0
+#define MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1         0x1e0 0x4f4 0x84c 0x1 0x1
+#define MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS            0x1e0 0x4f4 0x860 0x2 0x0
+#define MX6QDL_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT  0x1e0 0x4f4 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_RXD1__GPIO1_IO26            0x1e0 0x4f4 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0         0x1e4 0x4f8 0x848 0x1 0x1
+#define MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK        0x1e4 0x4f8 0x868 0x2 0x0
+#define MX6QDL_PAD_ENET_RXD0__SPDIF_OUT             0x1e4 0x4f8 0x000 0x3 0x0
+#define MX6QDL_PAD_ENET_RXD0__GPIO1_IO27            0x1e4 0x4f8 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN           0x1e8 0x4fc 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2         0x1e8 0x4fc 0x880 0x2 0x0
+#define MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28           0x1e8 0x4fc 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TXD1__MLB_CLK               0x1ec 0x500 0x900 0x0 0x0
+#define MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1         0x1ec 0x500 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3          0x1ec 0x500 0x87c 0x2 0x0
+#define MX6QDL_PAD_ENET_TXD1__ENET_1588_EVENT0_IN   0x1ec 0x500 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_TXD1__GPIO1_IO29            0x1ec 0x500 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0         0x1f0 0x504 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1          0x1f0 0x504 0x884 0x2 0x0
+#define MX6QDL_PAD_ENET_TXD0__GPIO1_IO30            0x1f0 0x504 0x000 0x5 0x0
+#define MX6QDL_PAD_ENET_MDC__MLB_DATA               0x1f4 0x508 0x904 0x0 0x0
+#define MX6QDL_PAD_ENET_MDC__ENET_MDC               0x1f4 0x508 0x000 0x1 0x0
+#define MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0           0x1f4 0x508 0x888 0x2 0x0
+#define MX6QDL_PAD_ENET_MDC__ENET_1588_EVENT1_IN    0x1f4 0x508 0x000 0x4 0x0
+#define MX6QDL_PAD_ENET_MDC__GPIO1_IO31             0x1f4 0x508 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK            0x1f8 0x5c8 0x7f4 0x0 0x2
+#define MX6QDL_PAD_KEY_COL0__ENET_RX_DATA3          0x1f8 0x5c8 0x854 0x1 0x1
+#define MX6QDL_PAD_KEY_COL0__AUD5_TXC               0x1f8 0x5c8 0x7dc 0x2 0x1
+#define MX6QDL_PAD_KEY_COL0__KEY_COL0               0x1f8 0x5c8 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL0__UART4_TX_DATA          0x1f8 0x5c8 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL0__UART4_RX_DATA          0x1f8 0x5c8 0x938 0x4 0x0
+#define MX6QDL_PAD_KEY_COL0__GPIO4_IO06             0x1f8 0x5c8 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL0__DCIC1_OUT              0x1f8 0x5c8 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI            0x1fc 0x5cc 0x7fc 0x0 0x2
+#define MX6QDL_PAD_KEY_ROW0__ENET_TX_DATA3          0x1fc 0x5cc 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW0__AUD5_TXD               0x1fc 0x5cc 0x7d0 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW0__KEY_ROW0               0x1fc 0x5cc 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA          0x1fc 0x5cc 0x938 0x4 0x1
+#define MX6QDL_PAD_KEY_ROW0__UART4_TX_DATA          0x1fc 0x5cc 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW0__GPIO4_IO07             0x1fc 0x5cc 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW0__DCIC2_OUT              0x1fc 0x5cc 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_COL1__ECSPI1_MISO            0x200 0x5d0 0x7f8 0x0 0x2
+#define MX6QDL_PAD_KEY_COL1__ENET_MDIO              0x200 0x5d0 0x840 0x1 0x1
+#define MX6QDL_PAD_KEY_COL1__AUD5_TXFS              0x200 0x5d0 0x7e0 0x2 0x1
+#define MX6QDL_PAD_KEY_COL1__KEY_COL1               0x200 0x5d0 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL1__UART5_TX_DATA          0x200 0x5d0 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL1__UART5_RX_DATA          0x200 0x5d0 0x940 0x4 0x0
+#define MX6QDL_PAD_KEY_COL1__GPIO4_IO08             0x200 0x5d0 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL1__SD1_VSELECT            0x200 0x5d0 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_ROW1__ECSPI1_SS0             0x204 0x5d4 0x800 0x0 0x2
+#define MX6QDL_PAD_KEY_ROW1__ENET_COL               0x204 0x5d4 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW1__AUD5_RXD               0x204 0x5d4 0x7cc 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW1__KEY_ROW1               0x204 0x5d4 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA          0x204 0x5d4 0x940 0x4 0x1
+#define MX6QDL_PAD_KEY_ROW1__UART5_TX_DATA          0x204 0x5d4 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW1__GPIO4_IO09             0x204 0x5d4 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW1__SD2_VSELECT            0x204 0x5d4 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_COL2__ECSPI1_SS1             0x208 0x5d8 0x804 0x0 0x2
+#define MX6QDL_PAD_KEY_COL2__ENET_RX_DATA2          0x208 0x5d8 0x850 0x1 0x1
+#define MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX            0x208 0x5d8 0x000 0x2 0x0
+#define MX6QDL_PAD_KEY_COL2__KEY_COL2               0x208 0x5d8 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL2__ENET_MDC               0x208 0x5d8 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL2__GPIO4_IO10             0x208 0x5d8 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL2__USB_H1_PWR_CTL_WAKE    0x208 0x5d8 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_ROW2__ECSPI1_SS2             0x20c 0x5dc 0x808 0x0 0x1
+#define MX6QDL_PAD_KEY_ROW2__ENET_TX_DATA2          0x20c 0x5dc 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX            0x20c 0x5dc 0x7e4 0x2 0x0
+#define MX6QDL_PAD_KEY_ROW2__KEY_ROW2               0x20c 0x5dc 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW2__SD2_VSELECT            0x20c 0x5dc 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW2__GPIO4_IO11             0x20c 0x5dc 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE       0x20c 0x5dc 0x88c 0x6 0x1
+#define MX6QDL_PAD_KEY_COL3__ECSPI1_SS3             0x210 0x5e0 0x80c 0x0 0x1
+#define MX6QDL_PAD_KEY_COL3__ENET_CRS               0x210 0x5e0 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL        0x210 0x5e0 0x890 0x2 0x1
+#define MX6QDL_PAD_KEY_COL3__KEY_COL3               0x210 0x5e0 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL3__I2C2_SCL               0x210 0x5e0 0x8a0 0x4 0x1
+#define MX6QDL_PAD_KEY_COL3__GPIO4_IO12             0x210 0x5e0 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_COL3__SPDIF_IN               0x210 0x5e0 0x914 0x6 0x2
+#define MX6QDL_PAD_KEY_ROW3__ASRC_EXT_CLK           0x214 0x5e4 0x7b0 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA        0x214 0x5e4 0x894 0x2 0x1
+#define MX6QDL_PAD_KEY_ROW3__KEY_ROW3               0x214 0x5e4 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW3__I2C2_SDA               0x214 0x5e4 0x8a4 0x4 0x1
+#define MX6QDL_PAD_KEY_ROW3__GPIO4_IO13             0x214 0x5e4 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW3__SD1_VSELECT            0x214 0x5e4 0x000 0x6 0x0
+#define MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX            0x218 0x5e8 0x000 0x0 0x0
+#define MX6QDL_PAD_KEY_COL4__IPU1_SISG4             0x218 0x5e8 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_COL4__USB_OTG_OC             0x218 0x5e8 0x944 0x2 0x1
+#define MX6QDL_PAD_KEY_COL4__KEY_COL4               0x218 0x5e8 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_COL4__UART5_RTS_B            0x218 0x5e8 0x93c 0x4 0x0
+#define MX6QDL_PAD_KEY_COL4__UART5_CTS_B            0x218 0x5e8 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_COL4__GPIO4_IO14             0x218 0x5e8 0x000 0x5 0x0
+#define MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX            0x21c 0x5ec 0x7e8 0x0 0x0
+#define MX6QDL_PAD_KEY_ROW4__IPU1_SISG5             0x21c 0x5ec 0x000 0x1 0x0
+#define MX6QDL_PAD_KEY_ROW4__USB_OTG_PWR            0x21c 0x5ec 0x000 0x2 0x0
+#define MX6QDL_PAD_KEY_ROW4__KEY_ROW4               0x21c 0x5ec 0x000 0x3 0x0
+#define MX6QDL_PAD_KEY_ROW4__UART5_CTS_B            0x21c 0x5ec 0x000 0x4 0x0
+#define MX6QDL_PAD_KEY_ROW4__UART5_RTS_B            0x21c 0x5ec 0x93c 0x4 0x1
+#define MX6QDL_PAD_KEY_ROW4__GPIO4_IO15             0x21c 0x5ec 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_0__CCM_CLKO1                0x220 0x5f0 0x000 0x0 0x0
+#define MX6QDL_PAD_GPIO_0__KEY_COL5                 0x220 0x5f0 0x8e8 0x2 0x0
+#define MX6QDL_PAD_GPIO_0__ASRC_EXT_CLK             0x220 0x5f0 0x7b0 0x3 0x1
+#define MX6QDL_PAD_GPIO_0__EPIT1_OUT                0x220 0x5f0 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_0__GPIO1_IO00               0x220 0x5f0 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_0__USB_H1_PWR               0x220 0x5f0 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_0__SNVS_VIO_5               0x220 0x5f0 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_1__ESAI_RX_CLK              0x224 0x5f4 0x86c 0x0 0x1
+#define MX6QDL_PAD_GPIO_1__WDOG2_B                  0x224 0x5f4 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_1__KEY_ROW5                 0x224 0x5f4 0x8f4 0x2 0x0
+#define MX6QDL_PAD_GPIO_1__USB_OTG_ID               0x224 0x5f4 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_1__PWM2_OUT                 0x224 0x5f4 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_1__GPIO1_IO01               0x224 0x5f4 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_1__SD1_CD_B                 0x224 0x5f4 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_9__ESAI_RX_FS               0x228 0x5f8 0x85c 0x0 0x1
+#define MX6QDL_PAD_GPIO_9__WDOG1_B                  0x228 0x5f8 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_9__KEY_COL6                 0x228 0x5f8 0x8ec 0x2 0x0
+#define MX6QDL_PAD_GPIO_9__CCM_REF_EN_B             0x228 0x5f8 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_9__PWM1_OUT                 0x228 0x5f8 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_9__GPIO1_IO09               0x228 0x5f8 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_9__SD1_WP                   0x228 0x5f8 0x94c 0x6 0x1
+#define MX6QDL_PAD_GPIO_3__ESAI_RX_HF_CLK           0x22c 0x5fc 0x864 0x0 0x1
+#define MX6QDL_PAD_GPIO_3__I2C3_SCL                 0x22c 0x5fc 0x8a8 0x2 0x1
+#define MX6QDL_PAD_GPIO_3__XTALOSC_REF_CLK_24M      0x22c 0x5fc 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_3__CCM_CLKO2                0x22c 0x5fc 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_3__GPIO1_IO03               0x22c 0x5fc 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_3__USB_H1_OC                0x22c 0x5fc 0x948 0x6 0x1
+#define MX6QDL_PAD_GPIO_3__MLB_CLK                  0x22c 0x5fc 0x900 0x7 0x1
+#define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK              0x230 0x600 0x870 0x0 0x1
+#define MX6QDL_PAD_GPIO_6__I2C3_SDA                 0x230 0x600 0x8ac 0x2 0x1
+#define MX6QDL_PAD_GPIO_6__GPIO1_IO06               0x230 0x600 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_6__SD2_LCTL                 0x230 0x600 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_6__MLB_SIG                  0x230 0x600 0x908 0x7 0x1
+#define MX6QDL_PAD_GPIO_2__ESAI_TX_FS               0x234 0x604 0x860 0x0 0x1
+#define MX6QDL_PAD_GPIO_2__KEY_ROW6                 0x234 0x604 0x8f8 0x2 0x1
+#define MX6QDL_PAD_GPIO_2__GPIO1_IO02               0x234 0x604 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_2__SD2_WP                   0x234 0x604 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_2__MLB_DATA                 0x234 0x604 0x904 0x7 0x1
+#define MX6QDL_PAD_GPIO_4__ESAI_TX_HF_CLK           0x238 0x608 0x868 0x0 0x1
+#define MX6QDL_PAD_GPIO_4__KEY_COL7                 0x238 0x608 0x8f0 0x2 0x1
+#define MX6QDL_PAD_GPIO_4__GPIO1_IO04               0x238 0x608 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_4__SD2_CD_B                 0x238 0x608 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3             0x23c 0x60c 0x87c 0x0 0x1
+#define MX6QDL_PAD_GPIO_5__KEY_ROW7                 0x23c 0x60c 0x8fc 0x2 0x1
+#define MX6QDL_PAD_GPIO_5__CCM_CLKO1                0x23c 0x60c 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_5__GPIO1_IO05               0x23c 0x60c 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_5__I2C3_SCL                 0x23c 0x60c 0x8a8 0x6 0x2
+#define MX6QDL_PAD_GPIO_5__ARM_EVENTI               0x23c 0x60c 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_7__ESAI_TX4_RX1             0x240 0x610 0x884 0x0 0x1
+#define MX6QDL_PAD_GPIO_7__ECSPI5_RDY               0x240 0x610 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_7__EPIT1_OUT                0x240 0x610 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_7__FLEXCAN1_TX              0x240 0x610 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_7__UART2_TX_DATA            0x240 0x610 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_7__UART2_RX_DATA            0x240 0x610 0x928 0x4 0x2
+#define MX6QDL_PAD_GPIO_7__GPIO1_IO07               0x240 0x610 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_7__SPDIF_LOCK               0x240 0x610 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_7__USB_OTG_HOST_MODE        0x240 0x610 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_8__ESAI_TX5_RX0             0x244 0x614 0x888 0x0 0x1
+#define MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K      0x244 0x614 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_8__EPIT2_OUT                0x244 0x614 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_8__FLEXCAN1_RX              0x244 0x614 0x7e4 0x3 0x1
+#define MX6QDL_PAD_GPIO_8__UART2_RX_DATA            0x244 0x614 0x928 0x4 0x3
+#define MX6QDL_PAD_GPIO_8__UART2_TX_DATA            0x244 0x614 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_8__GPIO1_IO08               0x244 0x614 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_8__SPDIF_SR_CLK             0x244 0x614 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_8__USB_OTG_PWR_CTL_WAKE     0x244 0x614 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_16__ESAI_TX3_RX2            0x248 0x618 0x880 0x0 0x1
+#define MX6QDL_PAD_GPIO_16__ENET_1588_EVENT2_IN     0x248 0x618 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_16__ENET_REF_CLK            0x248 0x618 0x83c 0x2 0x1
+#define MX6QDL_PAD_GPIO_16__SD1_LCTL                0x248 0x618 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_16__SPDIF_IN                0x248 0x618 0x914 0x4 0x3
+#define MX6QDL_PAD_GPIO_16__GPIO7_IO11              0x248 0x618 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_16__I2C3_SDA                0x248 0x618 0x8ac 0x6 0x2
+#define MX6QDL_PAD_GPIO_16__JTAG_DE_B               0x248 0x618 0x000 0x7 0x0
+#define MX6QDL_PAD_GPIO_17__ESAI_TX0                0x24c 0x61c 0x874 0x0 0x0
+#define MX6QDL_PAD_GPIO_17__ENET_1588_EVENT3_IN     0x24c 0x61c 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_17__CCM_PMIC_READY          0x24c 0x61c 0x7f0 0x2 0x1
+#define MX6QDL_PAD_GPIO_17__SDMA_EXT_EVENT0         0x24c 0x61c 0x90c 0x3 0x1
+#define MX6QDL_PAD_GPIO_17__SPDIF_OUT               0x24c 0x61c 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_17__GPIO7_IO12              0x24c 0x61c 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_18__ESAI_TX1                0x250 0x620 0x878 0x0 0x0
+#define MX6QDL_PAD_GPIO_18__ENET_RX_CLK             0x250 0x620 0x844 0x1 0x1
+#define MX6QDL_PAD_GPIO_18__SD3_VSELECT             0x250 0x620 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_18__SDMA_EXT_EVENT1         0x250 0x620 0x910 0x3 0x1
+#define MX6QDL_PAD_GPIO_18__ASRC_EXT_CLK            0x250 0x620 0x7b0 0x4 0x2
+#define MX6QDL_PAD_GPIO_18__GPIO7_IO13              0x250 0x620 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_18__SNVS_VIO_5_CTL          0x250 0x620 0x000 0x6 0x0
+#define MX6QDL_PAD_GPIO_19__KEY_COL5                0x254 0x624 0x8e8 0x0 0x1
+#define MX6QDL_PAD_GPIO_19__ENET_1588_EVENT0_OUT    0x254 0x624 0x000 0x1 0x0
+#define MX6QDL_PAD_GPIO_19__SPDIF_OUT               0x254 0x624 0x000 0x2 0x0
+#define MX6QDL_PAD_GPIO_19__CCM_CLKO1               0x254 0x624 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_19__ECSPI1_RDY              0x254 0x624 0x000 0x4 0x0
+#define MX6QDL_PAD_GPIO_19__GPIO4_IO05              0x254 0x624 0x000 0x5 0x0
+#define MX6QDL_PAD_GPIO_19__ENET_TX_ER              0x254 0x624 0x000 0x6 0x0
+#define MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK    0x258 0x628 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18          0x258 0x628 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_PIXCLK__ARM_EVENTO          0x258 0x628 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC       0x25c 0x62c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_MCLK__CCM_CLKO1             0x25c 0x62c 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19            0x25c 0x62c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_MCLK__ARM_TRACE_CTL         0x25c 0x62c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN  0x260 0x630 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__EIM_DATA00         0x260 0x630 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20         0x260 0x630 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DATA_EN__ARM_TRACE_CLK      0x260 0x630 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC      0x264 0x634 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__EIM_DATA01           0x264 0x634 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21           0x264 0x634 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_VSYNC__ARM_TRACE00          0x264 0x634 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04      0x268 0x638 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT4__EIM_DATA02            0x268 0x638 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT4__ECSPI1_SCLK           0x268 0x638 0x7f4 0x2 0x3
+#define MX6QDL_PAD_CSI0_DAT4__KEY_COL5              0x268 0x638 0x8e8 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT4__AUD3_TXC              0x268 0x638 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT4__GPIO5_IO22            0x268 0x638 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT4__ARM_TRACE01           0x268 0x638 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05      0x26c 0x63c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT5__EIM_DATA03            0x26c 0x63c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT5__ECSPI1_MOSI           0x26c 0x63c 0x7fc 0x2 0x3
+#define MX6QDL_PAD_CSI0_DAT5__KEY_ROW5              0x26c 0x63c 0x8f4 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT5__AUD3_TXD              0x26c 0x63c 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23            0x26c 0x63c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT5__ARM_TRACE02           0x26c 0x63c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06      0x270 0x640 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT6__EIM_DATA04            0x270 0x640 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT6__ECSPI1_MISO           0x270 0x640 0x7f8 0x2 0x3
+#define MX6QDL_PAD_CSI0_DAT6__KEY_COL6              0x270 0x640 0x8ec 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS             0x270 0x640 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT6__GPIO5_IO24            0x270 0x640 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT6__ARM_TRACE03           0x270 0x640 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07      0x274 0x644 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT7__EIM_DATA05            0x274 0x644 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT7__ECSPI1_SS0            0x274 0x644 0x800 0x2 0x3
+#define MX6QDL_PAD_CSI0_DAT7__KEY_ROW6              0x274 0x644 0x8f8 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT7__AUD3_RXD              0x274 0x644 0x000 0x4 0x0
+#define MX6QDL_PAD_CSI0_DAT7__GPIO5_IO25            0x274 0x644 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT7__ARM_TRACE04           0x274 0x644 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08      0x278 0x648 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT8__EIM_DATA06            0x278 0x648 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK           0x278 0x648 0x810 0x2 0x2
+#define MX6QDL_PAD_CSI0_DAT8__KEY_COL7              0x278 0x648 0x8f0 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT8__I2C1_SDA              0x278 0x648 0x89c 0x4 0x1
+#define MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26            0x278 0x648 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT8__ARM_TRACE05           0x278 0x648 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09      0x27c 0x64c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT9__EIM_DATA07            0x27c 0x64c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI           0x27c 0x64c 0x818 0x2 0x2
+#define MX6QDL_PAD_CSI0_DAT9__KEY_ROW7              0x27c 0x64c 0x8fc 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT9__I2C1_SCL              0x27c 0x64c 0x898 0x4 0x1
+#define MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27            0x27c 0x64c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT9__ARM_TRACE06           0x27c 0x64c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10     0x280 0x650 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT10__AUD3_RXC             0x280 0x650 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO          0x280 0x650 0x814 0x2 0x2
+#define MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA        0x280 0x650 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT10__UART1_RX_DATA        0x280 0x650 0x920 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28           0x280 0x650 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT10__ARM_TRACE07          0x280 0x650 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11     0x284 0x654 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT11__AUD3_RXFS            0x284 0x654 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT11__ECSPI2_SS0           0x284 0x654 0x81c 0x2 0x2
+#define MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA        0x284 0x654 0x920 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT11__UART1_TX_DATA        0x284 0x654 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29           0x284 0x654 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT11__ARM_TRACE08          0x284 0x654 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12     0x288 0x658 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT12__EIM_DATA08           0x288 0x658 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA        0x288 0x658 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT12__UART4_RX_DATA        0x288 0x658 0x938 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30           0x288 0x658 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT12__ARM_TRACE09          0x288 0x658 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13     0x28c 0x65c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT13__EIM_DATA09           0x28c 0x65c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA        0x28c 0x65c 0x938 0x3 0x3
+#define MX6QDL_PAD_CSI0_DAT13__UART4_TX_DATA        0x28c 0x65c 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31           0x28c 0x65c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT13__ARM_TRACE10          0x28c 0x65c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14     0x290 0x660 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT14__EIM_DATA10           0x290 0x660 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA        0x290 0x660 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT14__UART5_RX_DATA        0x290 0x660 0x940 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00           0x290 0x660 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT14__ARM_TRACE11          0x290 0x660 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15     0x294 0x664 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT15__EIM_DATA11           0x294 0x664 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA        0x294 0x664 0x940 0x3 0x3
+#define MX6QDL_PAD_CSI0_DAT15__UART5_TX_DATA        0x294 0x664 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01           0x294 0x664 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT15__ARM_TRACE12          0x294 0x664 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16     0x298 0x668 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT16__EIM_DATA12           0x298 0x668 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B          0x298 0x668 0x934 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT16__UART4_CTS_B          0x298 0x668 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02           0x298 0x668 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT16__ARM_TRACE13          0x298 0x668 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17     0x29c 0x66c 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT17__EIM_DATA13           0x29c 0x66c 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B          0x29c 0x66c 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT17__UART4_RTS_B          0x29c 0x66c 0x934 0x3 0x1
+#define MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03           0x29c 0x66c 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT17__ARM_TRACE14          0x29c 0x66c 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18     0x2a0 0x670 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT18__EIM_DATA14           0x2a0 0x670 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT18__UART5_RTS_B          0x2a0 0x670 0x93c 0x3 0x2
+#define MX6QDL_PAD_CSI0_DAT18__UART5_CTS_B          0x2a0 0x670 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04           0x2a0 0x670 0x000 0x5 0x0
+#define MX6QDL_PAD_CSI0_DAT18__ARM_TRACE15          0x2a0 0x670 0x000 0x7 0x0
+#define MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19     0x2a4 0x674 0x000 0x0 0x0
+#define MX6QDL_PAD_CSI0_DAT19__EIM_DATA15           0x2a4 0x674 0x000 0x1 0x0
+#define MX6QDL_PAD_CSI0_DAT19__UART5_CTS_B          0x2a4 0x674 0x000 0x3 0x0
+#define MX6QDL_PAD_CSI0_DAT19__UART5_RTS_B          0x2a4 0x674 0x93c 0x3 0x3
+#define MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05           0x2a4 0x674 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT7__SD3_DATA7              0x2a8 0x690 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA          0x2a8 0x690 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT7__UART1_RX_DATA          0x2a8 0x690 0x920 0x1 0x2
+#define MX6QDL_PAD_SD3_DAT7__GPIO6_IO17             0x2a8 0x690 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT6__SD3_DATA6              0x2ac 0x694 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA          0x2ac 0x694 0x920 0x1 0x3
+#define MX6QDL_PAD_SD3_DAT6__UART1_TX_DATA          0x2ac 0x694 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT6__GPIO6_IO18             0x2ac 0x694 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT5__SD3_DATA5              0x2b0 0x698 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT5__UART2_TX_DATA          0x2b0 0x698 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT5__UART2_RX_DATA          0x2b0 0x698 0x928 0x1 0x4
+#define MX6QDL_PAD_SD3_DAT5__GPIO7_IO00             0x2b0 0x698 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT4__SD3_DATA4              0x2b4 0x69c 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT4__UART2_RX_DATA          0x2b4 0x69c 0x928 0x1 0x5
+#define MX6QDL_PAD_SD3_DAT4__UART2_TX_DATA          0x2b4 0x69c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT4__GPIO7_IO01             0x2b4 0x69c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_CMD__SD3_CMD                 0x2b8 0x6a0 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_CMD__UART2_CTS_B             0x2b8 0x6a0 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_CMD__UART2_RTS_B             0x2b8 0x6a0 0x924 0x1 0x2
+#define MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX             0x2b8 0x6a0 0x000 0x2 0x0
+#define MX6QDL_PAD_SD3_CMD__GPIO7_IO02              0x2b8 0x6a0 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_CLK__SD3_CLK                 0x2bc 0x6a4 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_CLK__UART2_RTS_B             0x2bc 0x6a4 0x924 0x1 0x3
+#define MX6QDL_PAD_SD3_CLK__UART2_CTS_B             0x2bc 0x6a4 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX             0x2bc 0x6a4 0x7e4 0x2 0x2
+#define MX6QDL_PAD_SD3_CLK__GPIO7_IO03              0x2bc 0x6a4 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT0__SD3_DATA0              0x2c0 0x6a8 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT0__UART1_CTS_B            0x2c0 0x6a8 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT0__UART1_RTS_B            0x2c0 0x6a8 0x91c 0x1 0x2
+#define MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX            0x2c0 0x6a8 0x000 0x2 0x0
+#define MX6QDL_PAD_SD3_DAT0__GPIO7_IO04             0x2c0 0x6a8 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT1__SD3_DATA1              0x2c4 0x6ac 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT1__UART1_RTS_B            0x2c4 0x6ac 0x91c 0x1 0x3
+#define MX6QDL_PAD_SD3_DAT1__UART1_CTS_B            0x2c4 0x6ac 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX            0x2c4 0x6ac 0x7e8 0x2 0x1
+#define MX6QDL_PAD_SD3_DAT1__GPIO7_IO05             0x2c4 0x6ac 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT2__SD3_DATA2              0x2c8 0x6b0 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT2__GPIO7_IO06             0x2c8 0x6b0 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_DAT3__SD3_DATA3              0x2cc 0x6b4 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_DAT3__UART3_CTS_B            0x2cc 0x6b4 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_DAT3__UART3_RTS_B            0x2cc 0x6b4 0x92c 0x1 0x4
+#define MX6QDL_PAD_SD3_DAT3__GPIO7_IO07             0x2cc 0x6b4 0x000 0x5 0x0
+#define MX6QDL_PAD_SD3_RST__SD3_RESET               0x2d0 0x6b8 0x000 0x0 0x0
+#define MX6QDL_PAD_SD3_RST__UART3_RTS_B             0x2d0 0x6b8 0x92c 0x1 0x5
+#define MX6QDL_PAD_SD3_RST__UART3_CTS_B             0x2d0 0x6b8 0x000 0x1 0x0
+#define MX6QDL_PAD_SD3_RST__GPIO7_IO08              0x2d0 0x6b8 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CLE__NAND_CLE              0x2d4 0x6bc 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CLE__IPU2_SISG4            0x2d4 0x6bc 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CLE__GPIO6_IO07            0x2d4 0x6bc 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_ALE__NAND_ALE              0x2d8 0x6c0 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_ALE__SD4_RESET             0x2d8 0x6c0 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_ALE__GPIO6_IO08            0x2d8 0x6c0 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_WP_B__NAND_WP_B            0x2dc 0x6c4 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_WP_B__IPU2_SISG5           0x2dc 0x6c4 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09           0x2dc 0x6c4 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_RB0__NAND_READY_B          0x2e0 0x6c8 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_RB0__IPU2_DI0_PIN01        0x2e0 0x6c8 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_RB0__GPIO6_IO10            0x2e0 0x6c8 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS0__NAND_CE0_B            0x2e4 0x6cc 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS0__GPIO6_IO11            0x2e4 0x6cc 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS1__NAND_CE1_B            0x2e8 0x6d0 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS1__SD4_VSELECT           0x2e8 0x6d0 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CS1__SD3_VSELECT           0x2e8 0x6d0 0x000 0x2 0x0
+#define MX6QDL_PAD_NANDF_CS1__GPIO6_IO14            0x2e8 0x6d0 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS2__NAND_CE2_B            0x2ec 0x6d4 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS2__IPU1_SISG0            0x2ec 0x6d4 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CS2__ESAI_TX0              0x2ec 0x6d4 0x874 0x2 0x1
+#define MX6QDL_PAD_NANDF_CS2__EIM_CRE               0x2ec 0x6d4 0x000 0x3 0x0
+#define MX6QDL_PAD_NANDF_CS2__CCM_CLKO2             0x2ec 0x6d4 0x000 0x4 0x0
+#define MX6QDL_PAD_NANDF_CS2__GPIO6_IO15            0x2ec 0x6d4 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS2__IPU2_SISG0            0x2ec 0x6d4 0x000 0x6 0x0
+#define MX6QDL_PAD_NANDF_CS3__NAND_CE3_B            0x2f0 0x6d8 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_CS3__IPU1_SISG1            0x2f0 0x6d8 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_CS3__ESAI_TX1              0x2f0 0x6d8 0x878 0x2 0x1
+#define MX6QDL_PAD_NANDF_CS3__EIM_ADDR26            0x2f0 0x6d8 0x000 0x3 0x0
+#define MX6QDL_PAD_NANDF_CS3__GPIO6_IO16            0x2f0 0x6d8 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_CS3__IPU2_SISG1            0x2f0 0x6d8 0x000 0x6 0x0
+#define MX6QDL_PAD_SD4_CMD__SD4_CMD                 0x2f4 0x6dc 0x000 0x0 0x0
+#define MX6QDL_PAD_SD4_CMD__NAND_RE_B               0x2f4 0x6dc 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_CMD__UART3_TX_DATA           0x2f4 0x6dc 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_CMD__UART3_RX_DATA           0x2f4 0x6dc 0x930 0x2 0x2
+#define MX6QDL_PAD_SD4_CMD__GPIO7_IO09              0x2f4 0x6dc 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_CLK__SD4_CLK                 0x2f8 0x6e0 0x000 0x0 0x0
+#define MX6QDL_PAD_SD4_CLK__NAND_WE_B               0x2f8 0x6e0 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_CLK__UART3_RX_DATA           0x2f8 0x6e0 0x930 0x2 0x3
+#define MX6QDL_PAD_SD4_CLK__UART3_TX_DATA           0x2f8 0x6e0 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_CLK__GPIO7_IO10              0x2f8 0x6e0 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D0__NAND_DATA00            0x2fc 0x6e4 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D0__SD1_DATA4              0x2fc 0x6e4 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D0__GPIO2_IO00             0x2fc 0x6e4 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D1__NAND_DATA01            0x300 0x6e8 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D1__SD1_DATA5              0x300 0x6e8 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D1__GPIO2_IO01             0x300 0x6e8 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D2__NAND_DATA02            0x304 0x6ec 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D2__SD1_DATA6              0x304 0x6ec 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D2__GPIO2_IO02             0x304 0x6ec 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D3__NAND_DATA03            0x308 0x6f0 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D3__SD1_DATA7              0x308 0x6f0 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D3__GPIO2_IO03             0x308 0x6f0 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D4__NAND_DATA04            0x30c 0x6f4 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D4__SD2_DATA4              0x30c 0x6f4 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D4__GPIO2_IO04             0x30c 0x6f4 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D5__NAND_DATA05            0x310 0x6f8 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D5__SD2_DATA5              0x310 0x6f8 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D5__GPIO2_IO05             0x310 0x6f8 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D6__NAND_DATA06            0x314 0x6fc 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D6__SD2_DATA6              0x314 0x6fc 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D6__GPIO2_IO06             0x314 0x6fc 0x000 0x5 0x0
+#define MX6QDL_PAD_NANDF_D7__NAND_DATA07            0x318 0x700 0x000 0x0 0x0
+#define MX6QDL_PAD_NANDF_D7__SD2_DATA7              0x318 0x700 0x000 0x1 0x0
+#define MX6QDL_PAD_NANDF_D7__GPIO2_IO07             0x318 0x700 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT0__SD4_DATA0              0x31c 0x704 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT0__NAND_DQS               0x31c 0x704 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT0__GPIO2_IO08             0x31c 0x704 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT1__SD4_DATA1              0x320 0x708 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT1__PWM3_OUT               0x320 0x708 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT1__GPIO2_IO09             0x320 0x708 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT2__SD4_DATA2              0x324 0x70c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT2__PWM4_OUT               0x324 0x70c 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT2__GPIO2_IO10             0x324 0x70c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT3__SD4_DATA3              0x328 0x710 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT3__GPIO2_IO11             0x328 0x710 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT4__SD4_DATA4              0x32c 0x714 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA          0x32c 0x714 0x928 0x2 0x6
+#define MX6QDL_PAD_SD4_DAT4__UART2_TX_DATA          0x32c 0x714 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT4__GPIO2_IO12             0x32c 0x714 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT5__SD4_DATA5              0x330 0x718 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT5__UART2_RTS_B            0x330 0x718 0x924 0x2 0x4
+#define MX6QDL_PAD_SD4_DAT5__UART2_CTS_B            0x330 0x718 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT5__GPIO2_IO13             0x330 0x718 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT6__SD4_DATA6              0x334 0x71c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT6__UART2_CTS_B            0x334 0x71c 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT6__UART2_RTS_B            0x334 0x71c 0x924 0x2 0x5
+#define MX6QDL_PAD_SD4_DAT6__GPIO2_IO14             0x334 0x71c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD4_DAT7__SD4_DATA7              0x338 0x720 0x000 0x1 0x0
+#define MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA          0x338 0x720 0x000 0x2 0x0
+#define MX6QDL_PAD_SD4_DAT7__UART2_RX_DATA          0x338 0x720 0x928 0x2 0x7
+#define MX6QDL_PAD_SD4_DAT7__GPIO2_IO15             0x338 0x720 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT1__SD1_DATA1              0x33c 0x724 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT1__ECSPI5_SS0             0x33c 0x724 0x834 0x1 0x1
+#define MX6QDL_PAD_SD1_DAT1__PWM3_OUT               0x33c 0x724 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_DAT1__GPT_CAPTURE2           0x33c 0x724 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT1__GPIO1_IO17             0x33c 0x724 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT0__SD1_DATA0              0x340 0x728 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO            0x340 0x728 0x82c 0x1 0x1
+#define MX6QDL_PAD_SD1_DAT0__GPT_CAPTURE1           0x340 0x728 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT0__GPIO1_IO16             0x340 0x728 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT3__SD1_DATA3              0x344 0x72c 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT3__ECSPI5_SS2             0x344 0x72c 0x000 0x1 0x0
+#define MX6QDL_PAD_SD1_DAT3__GPT_COMPARE3           0x344 0x72c 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_DAT3__PWM1_OUT               0x344 0x72c 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT3__WDOG2_B                0x344 0x72c 0x000 0x4 0x0
+#define MX6QDL_PAD_SD1_DAT3__GPIO1_IO21             0x344 0x72c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT3__WDOG2_RESET_B_DEB      0x344 0x72c 0x000 0x6 0x0
+#define MX6QDL_PAD_SD1_CMD__SD1_CMD                 0x348 0x730 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI             0x348 0x730 0x830 0x1 0x0
+#define MX6QDL_PAD_SD1_CMD__PWM4_OUT                0x348 0x730 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_CMD__GPT_COMPARE1            0x348 0x730 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_CMD__GPIO1_IO18              0x348 0x730 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT2__SD1_DATA2              0x34c 0x734 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_DAT2__ECSPI5_SS1             0x34c 0x734 0x838 0x1 0x1
+#define MX6QDL_PAD_SD1_DAT2__GPT_COMPARE2           0x34c 0x734 0x000 0x2 0x0
+#define MX6QDL_PAD_SD1_DAT2__PWM2_OUT               0x34c 0x734 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_DAT2__WDOG1_B                0x34c 0x734 0x000 0x4 0x0
+#define MX6QDL_PAD_SD1_DAT2__GPIO1_IO19             0x34c 0x734 0x000 0x5 0x0
+#define MX6QDL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x34c 0x734 0x000 0x6 0x0
+#define MX6QDL_PAD_SD1_CLK__SD1_CLK                 0x350 0x738 0x000 0x0 0x0
+#define MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK             0x350 0x738 0x828 0x1 0x0
+#define MX6QDL_PAD_SD1_CLK__GPT_CLKIN               0x350 0x738 0x000 0x3 0x0
+#define MX6QDL_PAD_SD1_CLK__GPIO1_IO20              0x350 0x738 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_CLK__SD2_CLK                 0x354 0x73c 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_CLK__ECSPI5_SCLK             0x354 0x73c 0x828 0x1 0x1
+#define MX6QDL_PAD_SD2_CLK__KEY_COL5                0x354 0x73c 0x8e8 0x2 0x3
+#define MX6QDL_PAD_SD2_CLK__AUD4_RXFS               0x354 0x73c 0x7c0 0x3 0x1
+#define MX6QDL_PAD_SD2_CLK__GPIO1_IO10              0x354 0x73c 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_CMD__SD2_CMD                 0x358 0x740 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_CMD__ECSPI5_MOSI             0x358 0x740 0x830 0x1 0x1
+#define MX6QDL_PAD_SD2_CMD__KEY_ROW5                0x358 0x740 0x8f4 0x2 0x2
+#define MX6QDL_PAD_SD2_CMD__AUD4_RXC                0x358 0x740 0x7bc 0x3 0x1
+#define MX6QDL_PAD_SD2_CMD__GPIO1_IO11              0x358 0x740 0x000 0x5 0x0
+#define MX6QDL_PAD_SD2_DAT3__SD2_DATA3              0x35c 0x744 0x000 0x0 0x0
+#define MX6QDL_PAD_SD2_DAT3__ECSPI5_SS3             0x35c 0x744 0x000 0x1 0x0
+#define MX6QDL_PAD_SD2_DAT3__KEY_COL6               0x35c 0x744 0x8ec 0x2 0x2
+#define MX6QDL_PAD_SD2_DAT3__AUD4_TXC               0x35c 0x744 0x7c4 0x3 0x1
+#define MX6QDL_PAD_SD2_DAT3__GPIO1_IO12             0x35c 0x744 0x000 0x5 0x0
 
 #endif /* __DTS_IMX6Q_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
index 09a7580..334b924 100644
--- a/arch/arm/boot/dts/imx6q-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -20,24 +20,6 @@
 	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
 };
 
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6Q_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
-				MX6Q_PAD_SD2_DAT2__GPIO1_IO13  0x80000000
-			>;
-		};
-	};
-
-	ecspi1 {
-		pinctrl_ecspi1_sabreauto: ecspi1-sabreauto {
-			fsl,pins = <
-				MX6Q_PAD_EIM_D19__GPIO3_IO19  0x80000000
-			>;
-		};
-	};
+&sata {
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
index 6a00066..3530280 100644
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -65,6 +65,10 @@
 	};
 };
 
+&sata {
+	status = "okay";
+};
+
 &ecspi1 {
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio3 19 0>;
@@ -91,14 +95,14 @@
 	hog {
 		pinctrl_hog: hoggrp {
 			fsl,pins = <
-				MX6Q_PAD_NANDF_D6__GPIO2_IO06 0x80000000
-				MX6Q_PAD_NANDF_D7__GPIO2_IO07 0x80000000
-				MX6Q_PAD_EIM_D19__GPIO3_IO19  0x80000000
-				MX6Q_PAD_EIM_D22__GPIO3_IO22  0x80000000
-				MX6Q_PAD_EIM_D23__GPIO3_IO23  0x80000000
-				MX6Q_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
-				MX6Q_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0
-				MX6Q_PAD_GPIO_0__CCM_CLKO1    0x80000000
+				MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000
+				MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x80000000
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19  0x80000000
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x80000000
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23  0x80000000
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
+				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x80000000
 			>;
 		};
 	};
@@ -163,7 +167,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 169>;
+		clocks = <&clks 201>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 0038228..9cbdfe7 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -20,21 +20,6 @@
 	compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
 };
 
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6Q_PAD_GPIO_4__GPIO1_IO04   0x80000000
-				MX6Q_PAD_GPIO_5__GPIO1_IO05   0x80000000
-				MX6Q_PAD_NANDF_D0__GPIO2_IO00 0x80000000
-				MX6Q_PAD_NANDF_D1__GPIO2_IO01 0x80000000
-				MX6Q_PAD_NANDF_D2__GPIO2_IO02 0x80000000
-				MX6Q_PAD_NANDF_D3__GPIO2_IO03 0x80000000
-				MX6Q_PAD_GPIO_0__CCM_CLKO1    0x130b0
-			>;
-		};
-	};
+&sata {
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-wandboard.dts b/arch/arm/boot/dts/imx6q-wandboard.dts
new file mode 100644
index 0000000..36be17f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-wandboard.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-wandboard.dtsi"
+
+/ {
+	model = "Wandboard i.MX6 Quad Board";
+	compatible = "wand,imx6q-wandboard", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index ba09dc3..f024ef2 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -8,8 +8,8 @@
  *
  */
 
-#include "imx6qdl.dtsi"
 #include "imx6q-pinfunc.h"
+#include "imx6qdl.dtsi"
 
 / {
 	cpus {
@@ -61,6 +61,12 @@
 	};
 
 	soc {
+		ocram: sram@00900000 {
+			compatible = "mmio-sram";
+			reg = <0x00900000 0x40000>;
+			clocks = <&clks 142>;
+		};
+
 		aips-bus@02000000 { /* AIPS1 */
 			spba-bus@02000000 {
 				ecspi5: ecspi@02018000 {
@@ -77,357 +83,54 @@
 
 			iomuxc: iomuxc@020e0000 {
 				compatible = "fsl,imx6q-iomuxc";
-				reg = <0x020e0000 0x4000>;
-
-				/* shared pinctrl settings */
-				audmux {
-					pinctrl_audmux_1: audmux-1 {
-						fsl,pins = <
-							MX6Q_PAD_SD2_DAT0__AUD4_RXD  0x80000000
-							MX6Q_PAD_SD2_DAT3__AUD4_TXC  0x80000000
-							MX6Q_PAD_SD2_DAT2__AUD4_TXD  0x80000000
-							MX6Q_PAD_SD2_DAT1__AUD4_TXFS 0x80000000
-						>;
-					};
-
-					pinctrl_audmux_2: audmux-2 {
-						fsl,pins = <
-							MX6Q_PAD_CSI0_DAT7__AUD3_RXD  0x80000000
-							MX6Q_PAD_CSI0_DAT4__AUD3_TXC  0x80000000
-							MX6Q_PAD_CSI0_DAT5__AUD3_TXD  0x80000000
-							MX6Q_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_D17__ECSPI1_MISO 0x100b1
-							MX6Q_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
-							MX6Q_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
-						>;
-					};
-				};
-
-				ecspi3 {
-					pinctrl_ecspi3_1: ecspi3grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
-							MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
-							MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
-						>;
-					};
-				};
-
-				enet {
-					pinctrl_enet_1: enetgrp-1 {
-						fsl,pins = <
-							MX6Q_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-							MX6Q_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-							MX6Q_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							MX6Q_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-							MX6Q_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-							MX6Q_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-							MX6Q_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-							MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-							MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6Q_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6Q_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6Q_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6Q_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6Q_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-							MX6Q_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
-						>;
-					};
-
-					pinctrl_enet_2: enetgrp-2 {
-						fsl,pins = <
-							MX6Q_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
-							MX6Q_PAD_KEY_COL2__ENET_MDC         0x1b0b0
-							MX6Q_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							MX6Q_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-							MX6Q_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-							MX6Q_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-							MX6Q_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-							MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-							MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6Q_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6Q_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6Q_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6Q_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6Q_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-						>;
-					};
-
-					pinctrl_enet_3: enetgrp-3 {
-						fsl,pins = <
-							MX6Q_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-							MX6Q_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-							MX6Q_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-							MX6Q_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-							MX6Q_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-							MX6Q_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-							MX6Q_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-							MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-							MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-							MX6Q_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-							MX6Q_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-							MX6Q_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-							MX6Q_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-							MX6Q_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-							MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-							MX6Q_PAD_ENET_TX_EN__ENET_TX_EN     0x1b0b0
-						>;
-					};
-				};
-
-				gpmi-nand {
-					pinctrl_gpmi_nand_1: gpmi-nand-1 {
-						fsl,pins = <
-							MX6Q_PAD_NANDF_CLE__NAND_CLE     0xb0b1
-							MX6Q_PAD_NANDF_ALE__NAND_ALE     0xb0b1
-							MX6Q_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
-							MX6Q_PAD_NANDF_RB0__NAND_READY_B 0xb000
-							MX6Q_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
-							MX6Q_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
-							MX6Q_PAD_SD4_CMD__NAND_RE_B      0xb0b1
-							MX6Q_PAD_SD4_CLK__NAND_WE_B      0xb0b1
-							MX6Q_PAD_NANDF_D0__NAND_DATA00   0xb0b1
-							MX6Q_PAD_NANDF_D1__NAND_DATA01   0xb0b1
-							MX6Q_PAD_NANDF_D2__NAND_DATA02   0xb0b1
-							MX6Q_PAD_NANDF_D3__NAND_DATA03   0xb0b1
-							MX6Q_PAD_NANDF_D4__NAND_DATA04   0xb0b1
-							MX6Q_PAD_NANDF_D5__NAND_DATA05   0xb0b1
-							MX6Q_PAD_NANDF_D6__NAND_DATA06   0xb0b1
-							MX6Q_PAD_NANDF_D7__NAND_DATA07   0xb0b1
-							MX6Q_PAD_SD4_DAT0__NAND_DQS      0x00b1
-						>;
-					};
-				};
-
-				i2c1 {
-					pinctrl_i2c1_1: i2c1grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
-							MX6Q_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
-						>;
-					};
 
-					pinctrl_i2c1_2: i2c1grp-2 {
-						fsl,pins = <
-							MX6Q_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
-							MX6Q_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
-						>;
-					};
-				};
-
-				i2c2 {
-					pinctrl_i2c2_1: i2c2grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
-							MX6Q_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+				ipu2 {
+					pinctrl_ipu2_1: ipu2grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_DI0_DISP_CLK__IPU2_DI0_DISP_CLK 0x10
+							MX6QDL_PAD_DI0_PIN15__IPU2_DI0_PIN15       0x10
+							MX6QDL_PAD_DI0_PIN2__IPU2_DI0_PIN02        0x10
+							MX6QDL_PAD_DI0_PIN3__IPU2_DI0_PIN03        0x10
+							MX6QDL_PAD_DI0_PIN4__IPU2_DI0_PIN04        0x80000000
+							MX6QDL_PAD_DISP0_DAT0__IPU2_DISP0_DATA00   0x10
+							MX6QDL_PAD_DISP0_DAT1__IPU2_DISP0_DATA01   0x10
+							MX6QDL_PAD_DISP0_DAT2__IPU2_DISP0_DATA02   0x10
+							MX6QDL_PAD_DISP0_DAT3__IPU2_DISP0_DATA03   0x10
+							MX6QDL_PAD_DISP0_DAT4__IPU2_DISP0_DATA04   0x10
+							MX6QDL_PAD_DISP0_DAT5__IPU2_DISP0_DATA05   0x10
+							MX6QDL_PAD_DISP0_DAT6__IPU2_DISP0_DATA06   0x10
+							MX6QDL_PAD_DISP0_DAT7__IPU2_DISP0_DATA07   0x10
+							MX6QDL_PAD_DISP0_DAT8__IPU2_DISP0_DATA08   0x10
+							MX6QDL_PAD_DISP0_DAT9__IPU2_DISP0_DATA09   0x10
+							MX6QDL_PAD_DISP0_DAT10__IPU2_DISP0_DATA10  0x10
+							MX6QDL_PAD_DISP0_DAT11__IPU2_DISP0_DATA11  0x10
+							MX6QDL_PAD_DISP0_DAT12__IPU2_DISP0_DATA12  0x10
+							MX6QDL_PAD_DISP0_DAT13__IPU2_DISP0_DATA13  0x10
+							MX6QDL_PAD_DISP0_DAT14__IPU2_DISP0_DATA14  0x10
+							MX6QDL_PAD_DISP0_DAT15__IPU2_DISP0_DATA15  0x10
+							MX6QDL_PAD_DISP0_DAT16__IPU2_DISP0_DATA16  0x10
+							MX6QDL_PAD_DISP0_DAT17__IPU2_DISP0_DATA17  0x10
+							MX6QDL_PAD_DISP0_DAT18__IPU2_DISP0_DATA18  0x10
+							MX6QDL_PAD_DISP0_DAT19__IPU2_DISP0_DATA19  0x10
+							MX6QDL_PAD_DISP0_DAT20__IPU2_DISP0_DATA20  0x10
+							MX6QDL_PAD_DISP0_DAT21__IPU2_DISP0_DATA21  0x10
+							MX6QDL_PAD_DISP0_DAT22__IPU2_DISP0_DATA22  0x10
+							MX6QDL_PAD_DISP0_DAT23__IPU2_DISP0_DATA23  0x10
 						>;
 					};
 				};
-
-				i2c3 {
-					pinctrl_i2c3_1: i2c3grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
-							MX6Q_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
-							MX6Q_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				uart2 {
-					pinctrl_uart2_1: uart2grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
-							MX6Q_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				uart4 {
-					pinctrl_uart4_1: uart4grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
-							MX6Q_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
-						>;
-					};
-				};
-
-				usbotg {
-					pinctrl_usbotg_1: usbotggrp-1 {
-						fsl,pins = <
-							MX6Q_PAD_GPIO_1__USB_OTG_ID 0x17059
-						>;
-					};
-
-					pinctrl_usbotg_2: usbotggrp-2 {
-						fsl,pins = <
-							MX6Q_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
-						>;
-					};
-				};
-
-				usdhc2 {
-					pinctrl_usdhc2_1: usdhc2grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_SD2_CMD__SD2_CMD    0x17059
-							MX6Q_PAD_SD2_CLK__SD2_CLK    0x10059
-							MX6Q_PAD_SD2_DAT0__SD2_DATA0 0x17059
-							MX6Q_PAD_SD2_DAT1__SD2_DATA1 0x17059
-							MX6Q_PAD_SD2_DAT2__SD2_DATA2 0x17059
-							MX6Q_PAD_SD2_DAT3__SD2_DATA3 0x17059
-							MX6Q_PAD_NANDF_D4__SD2_DATA4 0x17059
-							MX6Q_PAD_NANDF_D5__SD2_DATA5 0x17059
-							MX6Q_PAD_NANDF_D6__SD2_DATA6 0x17059
-							MX6Q_PAD_NANDF_D7__SD2_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc2_2: usdhc2grp-2 {
-						fsl,pins = <
-							MX6Q_PAD_SD2_CMD__SD2_CMD    0x17059
-							MX6Q_PAD_SD2_CLK__SD2_CLK    0x10059
-							MX6Q_PAD_SD2_DAT0__SD2_DATA0 0x17059
-							MX6Q_PAD_SD2_DAT1__SD2_DATA1 0x17059
-							MX6Q_PAD_SD2_DAT2__SD2_DATA2 0x17059
-							MX6Q_PAD_SD2_DAT3__SD2_DATA3 0x17059
-						>;
-					};
-				};
-
-				usdhc3 {
-					pinctrl_usdhc3_1: usdhc3grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6Q_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6Q_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6Q_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6Q_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6Q_PAD_SD3_DAT3__SD3_DATA3 0x17059
-							MX6Q_PAD_SD3_DAT4__SD3_DATA4 0x17059
-							MX6Q_PAD_SD3_DAT5__SD3_DATA5 0x17059
-							MX6Q_PAD_SD3_DAT6__SD3_DATA6 0x17059
-							MX6Q_PAD_SD3_DAT7__SD3_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc3_2: usdhc3grp-2 {
-						fsl,pins = <
-							MX6Q_PAD_SD3_CMD__SD3_CMD    0x17059
-							MX6Q_PAD_SD3_CLK__SD3_CLK    0x10059
-							MX6Q_PAD_SD3_DAT0__SD3_DATA0 0x17059
-							MX6Q_PAD_SD3_DAT1__SD3_DATA1 0x17059
-							MX6Q_PAD_SD3_DAT2__SD3_DATA2 0x17059
-							MX6Q_PAD_SD3_DAT3__SD3_DATA3 0x17059
-						>;
-					};
-				};
-
-				usdhc4 {
-					pinctrl_usdhc4_1: usdhc4grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_SD4_CMD__SD4_CMD    0x17059
-							MX6Q_PAD_SD4_CLK__SD4_CLK    0x10059
-							MX6Q_PAD_SD4_DAT0__SD4_DATA0 0x17059
-							MX6Q_PAD_SD4_DAT1__SD4_DATA1 0x17059
-							MX6Q_PAD_SD4_DAT2__SD4_DATA2 0x17059
-							MX6Q_PAD_SD4_DAT3__SD4_DATA3 0x17059
-							MX6Q_PAD_SD4_DAT4__SD4_DATA4 0x17059
-							MX6Q_PAD_SD4_DAT5__SD4_DATA5 0x17059
-							MX6Q_PAD_SD4_DAT6__SD4_DATA6 0x17059
-							MX6Q_PAD_SD4_DAT7__SD4_DATA7 0x17059
-						>;
-					};
-
-					pinctrl_usdhc4_2: usdhc4grp-2 {
-						fsl,pins = <
-							MX6Q_PAD_SD4_CMD__SD4_CMD    0x17059
-							MX6Q_PAD_SD4_CLK__SD4_CLK    0x10059
-							MX6Q_PAD_SD4_DAT0__SD4_DATA0 0x17059
-							MX6Q_PAD_SD4_DAT1__SD4_DATA1 0x17059
-							MX6Q_PAD_SD4_DAT2__SD4_DATA2 0x17059
-							MX6Q_PAD_SD4_DAT3__SD4_DATA3 0x17059
-						>;
-					};
-				};
-
-				weim {
-					pinctrl_weim_cs0_1: weim_cs0grp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_CS0__EIM_CS0_B   0xb0b1
-						>;
-					};
-
-					pinctrl_weim_nor_1: weimnorgrp-1 {
-						fsl,pins = <
-							MX6Q_PAD_EIM_OE__EIM_OE_B     0xb0b1
-							MX6Q_PAD_EIM_RW__EIM_RW       0xb0b1
-							MX6Q_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
-							/* data */
-							MX6Q_PAD_EIM_D16__EIM_DATA16 0x1b0b0
-							MX6Q_PAD_EIM_D17__EIM_DATA17 0x1b0b0
-							MX6Q_PAD_EIM_D18__EIM_DATA18 0x1b0b0
-							MX6Q_PAD_EIM_D19__EIM_DATA19 0x1b0b0
-							MX6Q_PAD_EIM_D20__EIM_DATA20 0x1b0b0
-							MX6Q_PAD_EIM_D21__EIM_DATA21 0x1b0b0
-							MX6Q_PAD_EIM_D22__EIM_DATA22 0x1b0b0
-							MX6Q_PAD_EIM_D23__EIM_DATA23 0x1b0b0
-							MX6Q_PAD_EIM_D24__EIM_DATA24 0x1b0b0
-							MX6Q_PAD_EIM_D25__EIM_DATA25 0x1b0b0
-							MX6Q_PAD_EIM_D26__EIM_DATA26 0x1b0b0
-							MX6Q_PAD_EIM_D27__EIM_DATA27 0x1b0b0
-							MX6Q_PAD_EIM_D28__EIM_DATA28 0x1b0b0
-							MX6Q_PAD_EIM_D29__EIM_DATA29 0x1b0b0
-							MX6Q_PAD_EIM_D30__EIM_DATA30 0x1b0b0
-							MX6Q_PAD_EIM_D31__EIM_DATA31 0x1b0b0
-							/* address */
-							MX6Q_PAD_EIM_A23__EIM_ADDR23 0xb0b1
-							MX6Q_PAD_EIM_A22__EIM_ADDR22 0xb0b1
-							MX6Q_PAD_EIM_A21__EIM_ADDR21 0xb0b1
-							MX6Q_PAD_EIM_A20__EIM_ADDR20 0xb0b1
-							MX6Q_PAD_EIM_A19__EIM_ADDR19 0xb0b1
-							MX6Q_PAD_EIM_A18__EIM_ADDR18 0xb0b1
-							MX6Q_PAD_EIM_A17__EIM_ADDR17 0xb0b1
-							MX6Q_PAD_EIM_A16__EIM_ADDR16 0xb0b1
-							MX6Q_PAD_EIM_DA15__EIM_AD15  0xb0b1
-							MX6Q_PAD_EIM_DA14__EIM_AD14  0xb0b1
-							MX6Q_PAD_EIM_DA13__EIM_AD13  0xb0b1
-							MX6Q_PAD_EIM_DA12__EIM_AD12  0xb0b1
-							MX6Q_PAD_EIM_DA11__EIM_AD11  0xb0b1
-							MX6Q_PAD_EIM_DA10__EIM_AD10  0xb0b1
-							MX6Q_PAD_EIM_DA9__EIM_AD09   0xb0b1
-							MX6Q_PAD_EIM_DA8__EIM_AD08   0xb0b1
-							MX6Q_PAD_EIM_DA7__EIM_AD07   0xb0b1
-							MX6Q_PAD_EIM_DA6__EIM_AD06   0xb0b1
-							MX6Q_PAD_EIM_DA5__EIM_AD05   0xb0b1
-							MX6Q_PAD_EIM_DA4__EIM_AD04   0xb0b1
-							MX6Q_PAD_EIM_DA3__EIM_AD03   0xb0b1
-							MX6Q_PAD_EIM_DA2__EIM_AD02   0xb0b1
-							MX6Q_PAD_EIM_DA1__EIM_AD01   0xb0b1
-							MX6Q_PAD_EIM_DA0__EIM_AD00   0xb0b1
-						>;
-					};
-
-				};
 			};
 		};
 
+		sata: sata@02200000 {
+			compatible = "fsl,imx6q-ahci";
+			reg = <0x02200000 0x4000>;
+			interrupts = <0 39 0x04>;
+			clocks =  <&clks 154>, <&clks 187>, <&clks 105>;
+			clock-names = "sata", "sata_ref", "ahb";
+			status = "disabled";
+		};
+
 		ipu2: ipu@02800000 {
 			#crtc-cells = <1>;
 			compatible = "fsl,imx6q-ipu";
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index e994011..1cbbc51 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -45,6 +45,28 @@
 	status = "okay";
 };
 
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
+				MX6QDL_PAD_SD2_DAT2__GPIO1_IO13  0x80000000
+			>;
+		};
+	};
+
+	ecspi1 {
+		pinctrl_ecspi1_sabreauto: ecspi1-sabreauto {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
+			>;
+		};
+	};
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart4_1>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 6e5dfdb..9bfdf62 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -41,12 +41,14 @@
 		volume-up {
 			label = "Volume Up";
 			gpios = <&gpio1 4 0>;
+			gpio-key,wakeup;
 			linux,code = <115>; /* KEY_VOLUMEUP */
 		};
 
 		volume-down {
 			label = "Volume Down";
 			gpios = <&gpio1 5 0>;
+			gpio-key,wakeup;
 			linux,code = <114>; /* KEY_VOLUMEDOWN */
 		};
 	};
@@ -77,6 +79,22 @@
 	status = "okay";
 };
 
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 9 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_2>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p32";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
 &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet_1>;
@@ -93,7 +111,7 @@
 	codec: wm8962@1a {
 		compatible = "wlf,wm8962";
 		reg = <0x1a>;
-		clocks = <&clks 169>;
+		clocks = <&clks 201>;
 		DCVDD-supply = <&reg_audio>;
 		DBVDD-supply = <&reg_audio>;
 		AVDD-supply = <&reg_audio>;
@@ -113,6 +131,66 @@
        };
 };
 
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3_2>;
+	status = "okay";
+
+	egalax_ts@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <7 2>;
+		wakeup-gpios = <&gpio6 7 0>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04   0x80000000
+				MX6QDL_PAD_GPIO_5__GPIO1_IO05   0x80000000
+				MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+				MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
+				MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
+				MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x130b0
+				MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
 &ssi2 {
 	fsl,mode = "i2s-slave";
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
new file mode 100644
index 0000000..a55113e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/ {
+	regulators {
+		compatible = "simple-bus";
+
+		reg_2p5v: 2p5v {
+			compatible = "regulator-fixed";
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6-wandboard-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6-wandboard-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <3>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux_2>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_2>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 201>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1 	 0x130b0
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02	 0x80000000
+				MX6QDL_PAD_EIM_DA9__GPIO3_IO09	 0x80000000
+				MX6QDL_PAD_EIM_EB1__GPIO2_IO29   0x80000000 /* WL_REF_ON */
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02   0x80000000 /* WL_RST_N */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* WL_REG_ON */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
+			>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_1>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_2>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1_2>;
+	cd-gpios = <&gpio1 2 0>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2_2>;
+	non-removable;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	cd-gpios = <&gpio3 9 0>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index f21d259..ccd55c2 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -14,11 +14,6 @@
 
 / {
 	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -26,6 +21,18 @@
 		gpio4 = &gpio5;
 		gpio5 = &gpio6;
 		gpio6 = &gpio7;
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		spi0 = &ecspi1;
+		spi1 = &ecspi2;
+		spi2 = &ecspi3;
+		spi3 = &ecspi4;
 	};
 
 	intc: interrupt-controller@00a01000 {
@@ -81,15 +88,14 @@
 			#size-cells = <1>;
 			reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
 			reg-names = "gpmi-nand", "bch";
-			interrupts = <0 13 0x04>, <0 15 0x04>;
-			interrupt-names = "gpmi-dma", "bch";
+			interrupts = <0 15 0x04>;
+			interrupt-names = "bch";
 			clocks = <&clks 152>, <&clks 153>, <&clks 151>,
 				 <&clks 150>, <&clks 149>;
 			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
 				      "gpmi_bch_apb", "per1_bch";
 			dmas = <&dma_apbh 0>;
 			dma-names = "rx-tx";
-			fsl,gpmi-dma-channel = <0>;
 			status = "disabled";
 		};
 
@@ -184,6 +190,8 @@
 					interrupts = <0 26 0x04>;
 					clocks = <&clks 160>, <&clks 161>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
@@ -197,6 +205,9 @@
 					reg = <0x02028000 0x4000>;
 					interrupts = <0 46 0x04>;
 					clocks = <&clks 178>;
+					dmas = <&sdma 37 1 0>,
+					       <&sdma 38 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <38 37>;
 					status = "disabled";
@@ -207,6 +218,9 @@
 					reg = <0x0202c000 0x4000>;
 					interrupts = <0 47 0x04>;
 					clocks = <&clks 179>;
+					dmas = <&sdma 41 1 0>,
+					       <&sdma 42 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <42 41>;
 					status = "disabled";
@@ -217,6 +231,9 @@
 					reg = <0x02030000 0x4000>;
 					interrupts = <0 48 0x04>;
 					clocks = <&clks 180>;
+					dmas = <&sdma 45 1 0>,
+					       <&sdma 46 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <46 45>;
 					status = "disabled";
@@ -278,17 +295,23 @@
 			};
 
 			can1: flexcan@02090000 {
+				compatible = "fsl,imx6q-flexcan";
 				reg = <0x02090000 0x4000>;
 				interrupts = <0 110 0x04>;
+				clocks = <&clks 108>, <&clks 109>;
+				clock-names = "ipg", "per";
 			};
 
 			can2: flexcan@02094000 {
+				compatible = "fsl,imx6q-flexcan";
 				reg = <0x02094000 0x4000>;
 				interrupts = <0 111 0x04>;
+				clocks = <&clks 110>, <&clks 111>;
+				clock-names = "ipg", "per";
 			};
 
 			gpt: gpt@02098000 {
-				compatible = "fsl,imx6q-gpt";
+				compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <0 55 0x04>;
 				clocks = <&clks 119>, <&clks 120>;
@@ -491,6 +514,13 @@
 				};
 			};
 
+			tempmon: tempmon {
+				compatible = "fsl,imx6q-tempmon";
+				interrupts = <0 49 0x04>;
+				fsl,tempmon = <&anatop>;
+				fsl,tempmon-data = <&ocotp>;
+			};
+
 			usbphy1: usbphy@020c9000 {
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020c9000 0x1000>;
@@ -546,6 +576,713 @@
 				reg = <0x020e0000 0x38>;
 			};
 
+			iomuxc: iomuxc@020e0000 {
+				compatible = "fsl,imx6dl-iomuxc", "fsl,imx6q-iomuxc";
+				reg = <0x020e0000 0x4000>;
+
+				audmux {
+					pinctrl_audmux_1: audmux-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD2_DAT0__AUD4_RXD  0x80000000
+							MX6QDL_PAD_SD2_DAT3__AUD4_TXC  0x80000000
+							MX6QDL_PAD_SD2_DAT2__AUD4_TXD  0x80000000
+							MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x80000000
+						>;
+					};
+
+					pinctrl_audmux_2: audmux-2 {
+						fsl,pins = <
+							MX6QDL_PAD_CSI0_DAT7__AUD3_RXD  0x80000000
+							MX6QDL_PAD_CSI0_DAT4__AUD3_TXC  0x80000000
+							MX6QDL_PAD_CSI0_DAT5__AUD3_TXD  0x80000000
+							MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000
+						>;
+					};
+
+					pinctrl_audmux_3: audmux-3 {
+						fsl,pins = <
+							MX6QDL_PAD_DISP0_DAT16__AUD5_TXC  0x80000000
+							MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x80000000
+							MX6QDL_PAD_DISP0_DAT19__AUD5_RXD  0x80000000
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+							MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+							MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+						>;
+					};
+
+					pinctrl_ecspi1_2: ecspi1grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
+							MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
+							MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
+						>;
+					};
+				};
+
+				ecspi3 {
+					pinctrl_ecspi3_1: ecspi3grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+							MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+							MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+						>;
+					};
+				};
+
+				enet {
+					pinctrl_enet_1: enetgrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
+							MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
+							MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
+							MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
+							MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
+							MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
+							MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
+							MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+							MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+							MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+							MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+							MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+							MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+							MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+							MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+							MX6QDL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
+						>;
+					};
+
+					pinctrl_enet_2: enetgrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
+							MX6QDL_PAD_KEY_COL2__ENET_MDC         0x1b0b0
+							MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
+							MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
+							MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
+							MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
+							MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
+							MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+							MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+							MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+							MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+							MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+							MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+							MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+							MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+						>;
+					};
+
+					pinctrl_enet_3: enetgrp-3 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
+							MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
+							MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
+							MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
+							MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
+							MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
+							MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
+							MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+							MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+							MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+							MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+							MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+							MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+							MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+							MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+							MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN     0x1b0b0
+						>;
+					};
+				};
+
+				esai {
+					pinctrl_esai_1: esaigrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK 0x1b030
+							MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK  0x1b030
+							MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS     0x1b030
+							MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2  0x1b030
+							MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3   0x1b030
+							MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1   0x1b030
+							MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0    0x1b030
+							MX6QDL_PAD_NANDF_CS2__ESAI_TX0       0x1b030
+							MX6QDL_PAD_NANDF_CS3__ESAI_TX1       0x1b030
+						>;
+					};
+
+					pinctrl_esai_2: esaigrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
+							MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS    0x1b030
+							MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
+							MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3     0x1b030
+							MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1  0x1b030
+							MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0   0x1b030
+							MX6QDL_PAD_GPIO_17__ESAI_TX0        0x1b030
+							MX6QDL_PAD_NANDF_CS3__ESAI_TX1      0x1b030
+							MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK   0x1b030
+							MX6QDL_PAD_GPIO_9__ESAI_RX_FS       0x1b030
+						>;
+					};
+				};
+
+				flexcan1 {
+					pinctrl_flexcan1_1: flexcan1grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
+							MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
+						>;
+					};
+
+					pinctrl_flexcan1_2: flexcan1grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_7__FLEXCAN1_TX   0x80000000
+							MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
+						>;
+					};
+				};
+
+				flexcan2 {
+					pinctrl_flexcan2_1: flexcan2grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000
+							MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000
+						>;
+					};
+				};
+
+				gpmi-nand {
+					pinctrl_gpmi_nand_1: gpmi-nand-1 {
+						fsl,pins = <
+							MX6QDL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
+							MX6QDL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
+							MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
+							MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+							MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
+							MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
+							MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
+							MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
+							MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
+							MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
+							MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
+							MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
+							MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
+							MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
+							MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
+							MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
+							MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
+						>;
+					};
+				};
+
+				hdmi_hdcp {
+					pinctrl_hdmi_hdcp_1: hdmihdcpgrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
+							MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_hdmi_hdcp_2: hdmihdcpgrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
+							MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_hdmi_hdcp_3: hdmihdcpgrp-3 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL  0x4001b8b1
+							MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
+						>;
+					};
+				};
+
+				hdmi_cec {
+					pinctrl_hdmi_cec_1: hdmicecgrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
+						>;
+					};
+
+					pinctrl_hdmi_cec_2: hdmicecgrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+						>;
+					};
+				};
+
+				i2c1 {
+					pinctrl_i2c1_1: i2c1grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+							MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_i2c1_2: i2c1grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+							MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+						>;
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2_1: i2c2grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+							MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_i2c2_2: i2c2grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+							MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_i2c2_3: i2c2grp-3 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_EB2__I2C2_SCL  0x4001b8b1
+							MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+						>;
+					};
+				};
+
+				i2c3 {
+					pinctrl_i2c3_1: i2c3grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+							MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_i2c3_2: i2c3grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+							MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_i2c3_3: i2c3grp-3 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_5__I2C3_SCL  0x4001b8b1
+							MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+						>;
+					};
+
+					pinctrl_i2c3_4: i2c3grp-4 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_3__I2C3_SCL  0x4001b8b1
+							MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+						>;
+					};
+				};
+
+				ipu1 {
+					pinctrl_ipu1_1: ipu1grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+							MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
+							MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
+							MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
+							MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04        0x80000000
+							MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
+							MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
+							MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
+							MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
+							MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
+							MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
+							MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
+							MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
+							MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
+							MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
+							MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
+							MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
+							MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
+							MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
+							MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
+							MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
+							MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
+							MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
+							MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
+							MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
+							MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
+							MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
+							MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
+							MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
+						>;
+					};
+
+					pinctrl_ipu1_2: ipu1grp-2 { /* parallel camera */
+						fsl,pins = <
+							MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12    0x80000000
+							MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13    0x80000000
+							MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14    0x80000000
+							MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15    0x80000000
+							MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16    0x80000000
+							MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17    0x80000000
+							MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18    0x80000000
+							MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19    0x80000000
+							MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000
+							MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK   0x80000000
+							MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC      0x80000000
+							MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC     0x80000000
+						>;
+					};
+
+					pinctrl_ipu1_3: ipu1grp-3 { /* parallel port 16-bit */
+						fsl,pins = <
+							MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04   0x80000000
+							MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05   0x80000000
+							MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06   0x80000000
+							MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07   0x80000000
+							MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08   0x80000000
+							MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09   0x80000000
+							MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10  0x80000000
+							MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11  0x80000000
+							MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12  0x80000000
+							MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13  0x80000000
+							MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14  0x80000000
+							MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15  0x80000000
+							MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16  0x80000000
+							MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17  0x80000000
+							MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18  0x80000000
+							MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19  0x80000000
+							MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
+							MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC    0x80000000
+							MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC   0x80000000
+						>;
+					};
+				};
+
+				mlb {
+					pinctrl_mlb_1: mlbgrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_3__MLB_CLK  0x71
+							MX6QDL_PAD_GPIO_6__MLB_SIG  0x71
+							MX6QDL_PAD_GPIO_2__MLB_DATA 0x71
+						>;
+					};
+
+					pinctrl_mlb_2: mlbgrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_TXD1__MLB_CLK 0x71
+							MX6QDL_PAD_GPIO_6__MLB_SIG    0x71
+							MX6QDL_PAD_GPIO_2__MLB_DATA   0x71
+						>;
+					};
+				};
+
+				pwm0 {
+					pinctrl_pwm0_1: pwm0grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+						>;
+					};
+				};
+
+				pwm3 {
+					pinctrl_pwm3_1: pwm3grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
+						>;
+					};
+				};
+
+				spdif {
+					pinctrl_spdif_1: spdifgrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
+						>;
+					};
+
+					pinctrl_spdif_2: spdifgrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_16__SPDIF_IN  0x1b0b0
+							MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+							MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+						>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+							MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+						>;
+					};
+
+					pinctrl_uart2_2: uart2grp-2 { /* DTE mode */
+						fsl,pins = <
+							MX6QDL_PAD_EIM_D26__UART2_RX_DATA   0x1b0b1
+							MX6QDL_PAD_EIM_D27__UART2_TX_DATA   0x1b0b1
+							MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
+							MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
+						>;
+					};
+				};
+
+				uart3 {
+					pinctrl_uart3_1: uart3grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1
+							MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1
+							MX6QDL_PAD_EIM_D30__UART3_CTS_B   0x1b0b1
+							MX6QDL_PAD_EIM_EB3__UART3_RTS_B   0x1b0b1
+						>;
+					};
+
+					pinctrl_uart3_2: uart3grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+							MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+							MX6QDL_PAD_EIM_D23__UART3_CTS_B	  0x1b0b1
+							MX6QDL_PAD_EIM_EB3__UART3_RTS_B	  0x1b0b1
+						>;
+					};
+				};
+
+				uart4 {
+					pinctrl_uart4_1: uart4grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+							MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+						>;
+					};
+				};
+
+				usbotg {
+					pinctrl_usbotg_1: usbotggrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+						>;
+					};
+
+					pinctrl_usbotg_2: usbotggrp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+						>;
+					};
+				};
+
+				usbh2 {
+					pinctrl_usbh2_1: usbh2grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_RGMII_TXC__USB_H2_DATA      0x40013030
+							MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40013030
+						>;
+					};
+
+					pinctrl_usbh2_2: usbh2grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40017030
+						>;
+					};
+				};
+
+				usbh3 {
+					pinctrl_usbh3_1: usbh3grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA 0x40013030
+							MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE  0x40013030
+						>;
+					};
+
+					pinctrl_usbh3_2: usbh3grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40017030
+						>;
+					};
+				};
+
+				usdhc1 {
+					pinctrl_usdhc1_1: usdhc1grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
+							MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
+							MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+							MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+							MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+							MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+							MX6QDL_PAD_NANDF_D0__SD1_DATA4 0x17059
+							MX6QDL_PAD_NANDF_D1__SD1_DATA5 0x17059
+							MX6QDL_PAD_NANDF_D2__SD1_DATA6 0x17059
+							MX6QDL_PAD_NANDF_D3__SD1_DATA7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc1_2: usdhc1grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
+							MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
+							MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+							MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+							MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+							MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+						>;
+					};
+				};
+
+				usdhc2 {
+					pinctrl_usdhc2_1: usdhc2grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
+							MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
+							MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+							MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+							MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+							MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+							MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
+							MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
+							MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
+							MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc2_2: usdhc2grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
+							MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
+							MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+							MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+							MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+							MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+						>;
+					};
+				};
+
+				usdhc3 {
+					pinctrl_usdhc3_1: usdhc3grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
+							MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
+							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+							MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+							MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+							MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+							MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc3_2: usdhc3grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
+							MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
+							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+						>;
+					};
+				};
+
+				usdhc4 {
+					pinctrl_usdhc4_1: usdhc4grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
+							MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
+							MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+							MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+							MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+							MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+							MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+							MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+							MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+							MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc4_2: usdhc4grp-2 {
+						fsl,pins = <
+							MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
+							MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
+							MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+							MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+							MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+							MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+						>;
+					};
+				};
+
+				weim {
+					pinctrl_weim_cs0_1: weim_cs0grp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_CS0__EIM_CS0_B   0xb0b1
+						>;
+					};
+
+					pinctrl_weim_nor_1: weim_norgrp-1 {
+						fsl,pins = <
+							MX6QDL_PAD_EIM_OE__EIM_OE_B     0xb0b1
+							MX6QDL_PAD_EIM_RW__EIM_RW       0xb0b1
+							MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
+							/* data */
+							MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
+							MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
+							MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
+							MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
+							MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
+							MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
+							MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
+							MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
+							MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
+							MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
+							MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
+							MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
+							MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
+							MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
+							MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
+							MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
+							/* address */
+							MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
+							MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
+							MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
+							MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
+							MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
+							MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
+							MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
+							MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
+							MX6QDL_PAD_EIM_DA15__EIM_AD15  0xb0b1
+							MX6QDL_PAD_EIM_DA14__EIM_AD14  0xb0b1
+							MX6QDL_PAD_EIM_DA13__EIM_AD13  0xb0b1
+							MX6QDL_PAD_EIM_DA12__EIM_AD12  0xb0b1
+							MX6QDL_PAD_EIM_DA11__EIM_AD11  0xb0b1
+							MX6QDL_PAD_EIM_DA10__EIM_AD10  0xb0b1
+							MX6QDL_PAD_EIM_DA9__EIM_AD09   0xb0b1
+							MX6QDL_PAD_EIM_DA8__EIM_AD08   0xb0b1
+							MX6QDL_PAD_EIM_DA7__EIM_AD07   0xb0b1
+							MX6QDL_PAD_EIM_DA6__EIM_AD06   0xb0b1
+							MX6QDL_PAD_EIM_DA5__EIM_AD05   0xb0b1
+							MX6QDL_PAD_EIM_DA4__EIM_AD04   0xb0b1
+							MX6QDL_PAD_EIM_DA3__EIM_AD03   0xb0b1
+							MX6QDL_PAD_EIM_DA2__EIM_AD02   0xb0b1
+							MX6QDL_PAD_EIM_DA1__EIM_AD01   0xb0b1
+							MX6QDL_PAD_EIM_DA0__EIM_AD00   0xb0b1
+						>;
+					};
+				};
+			};
+
 			ldb: ldb@020e0008 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -555,13 +1292,11 @@
 
 				lvds-channel@0 {
 					reg = <0>;
-					crtcs = <&ipu1 0>;
 					status = "disabled";
 				};
 
 				lvds-channel@1 {
 					reg = <1>;
-					crtcs = <&ipu1 1>;
 					status = "disabled";
 				};
 			};
@@ -582,6 +1317,7 @@
 				interrupts = <0 2 0x04>;
 				clocks = <&clks 155>, <&clks 155>;
 				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
 			};
 		};
@@ -751,8 +1487,8 @@
 				clocks = <&clks 196>;
 			};
 
-			ocotp@021bc000 {
-				compatible = "fsl,imx6q-ocotp";
+			ocotp: ocotp@021bc000 {
+				compatible = "fsl,imx6q-ocotp", "syscon";
 				reg = <0x021bc000 0x4000>;
 			};
 
@@ -791,6 +1527,8 @@
 				interrupts = <0 27 0x04>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -800,6 +1538,8 @@
 				interrupts = <0 28 0x04>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -809,6 +1549,8 @@
 				interrupts = <0 29 0x04>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -818,6 +1560,8 @@
 				interrupts = <0 30 0x04>;
 				clocks = <&clks 160>, <&clks 161>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index c5e5da0..c46651e 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -152,32 +152,41 @@
 				};
 
 				uart5: serial@02018000 {
-					compatible = "fsl,imx6sl-uart", "fsl,imx21-uart";
+					compatible = "fsl,imx6sl-uart",
+						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02018000 0x4000>;
 					interrupts = <0 30 0x04>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
 				uart1: serial@02020000 {
-					compatible = "fsl,imx6sl-uart", "fsl,imx21-uart";
+					compatible = "fsl,imx6sl-uart",
+						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02020000 0x4000>;
 					interrupts = <0 26 0x04>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
 				uart2: serial@02024000 {
-					compatible = "fsl,imx6sl-uart", "fsl,imx21-uart";
+					compatible = "fsl,imx6sl-uart",
+						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02024000 0x4000>;
 					interrupts = <0 27 0x04>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
@@ -186,6 +195,9 @@
 					reg = <0x02028000 0x4000>;
 					interrupts = <0 46 0x04>;
 					clocks = <&clks IMX6SL_CLK_SSI1>;
+					dmas = <&sdma 37 1 0>,
+					       <&sdma 38 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					status = "disabled";
 				};
@@ -195,6 +207,9 @@
 					reg = <0x0202c000 0x4000>;
 					interrupts = <0 47 0x04>;
 					clocks = <&clks IMX6SL_CLK_SSI2>;
+					dmas = <&sdma 41 1 0>,
+					       <&sdma 42 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					status = "disabled";
 				};
@@ -204,27 +219,36 @@
 					reg = <0x02030000 0x4000>;
 					interrupts = <0 48 0x04>;
 					clocks = <&clks IMX6SL_CLK_SSI3>;
+					dmas = <&sdma 45 1 0>,
+					       <&sdma 46 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
 					status = "disabled";
 				};
 
 				uart3: serial@02034000 {
-					compatible = "fsl,imx6sl-uart", "fsl,imx21-uart";
+					compatible = "fsl,imx6sl-uart",
+						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02034000 0x4000>;
 					interrupts = <0 28 0x04>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 
 				uart4: serial@02038000 {
-					compatible = "fsl,imx6sl-uart", "fsl,imx21-uart";
+					compatible = "fsl,imx6sl-uart",
+						   "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02038000 0x4000>;
 					interrupts = <0 29 0x04>;
 					clocks = <&clks IMX6SL_CLK_UART>,
 						 <&clks IMX6SL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
+					dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+					dma-names = "rx", "tx";
 					status = "disabled";
 				};
 			};
@@ -594,6 +618,7 @@
 				clocks = <&clks IMX6SL_CLK_SDMA>,
 					 <&clks IMX6SL_CLK_SDMA>;
 				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6sl.bin";
 			};
 
diff --git a/arch/arm/boot/dts/keystone.dts b/arch/arm/boot/dts/keystone.dts
index 1334b42..a68e34b 100644
--- a/arch/arm/boot/dts/keystone.dts
+++ b/arch/arm/boot/dts/keystone.dts
@@ -7,7 +7,9 @@
  */
 
 /dts-v1/;
-/include/ "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
 
 / {
 	model = "Texas Instruments Keystone 2 SoC";
@@ -67,18 +69,23 @@
 
 	timer {
 		compatible = "arm,armv7-timer";
-		interrupts = <1 13 0xf08>,
-			     <1 14 0xf08>,
-			     <1 11 0xf08>,
-			     <1 10 0x308>;
+		interrupts =
+			<GIC_PPI 13
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			<GIC_PPI 14
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			<GIC_PPI 11
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			<GIC_PPI 10
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupts = <0 20 0xf01>,
-			     <0 21 0xf01>,
-			     <0 22 0xf01>,
-			     <0 23 0xf01>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 23 IRQ_TYPE_EDGE_RISING>;
 	};
 
 	soc {
@@ -100,7 +107,7 @@
 			reg-io-width = <4>;
 			reg = <0x02530c00 0x100>;
 			clock-frequency = <133120000>;
-			interrupts = <0 277 0xf01>;
+			interrupts = <GIC_SPI 277 IRQ_TYPE_EDGE_RISING>;
 		};
 
 		uart1:	serial@02531000 {
@@ -110,7 +117,7 @@
 			reg-io-width = <4>;
 			reg = <0x02531000 0x100>;
 			clock-frequency = <133120000>;
-			interrupts = <0 280 0xf01>;
+			interrupts = <GIC_SPI 280 IRQ_TYPE_EDGE_RISING>;
 		};
 
 	};
diff --git a/arch/arm/boot/dts/kirkwood-6281.dtsi b/arch/arm/boot/dts/kirkwood-6281.dtsi
index 1e5bef0..650ef30 100644
--- a/arch/arm/boot/dts/kirkwood-6281.dtsi
+++ b/arch/arm/boot/dts/kirkwood-6281.dtsi
@@ -1,4 +1,39 @@
 / {
+	mbus {
+		pcie-controller {
+			compatible = "marvell,kirkwood-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0       1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0       1 0 /* Port 0.0 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x00040000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &intc 9>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gate_clk 2>;
+				status = "disabled";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		pinctrl: pinctrl@10000 {
 			compatible = "marvell,88f6281-pinctrl";
@@ -41,37 +76,6 @@
 			};
 		};
 
-		pcie-controller {
-			compatible = "marvell,kirkwood-pcie";
-			status = "disabled";
-			device_type = "pci";
-
-			#address-cells = <3>;
-			#size-cells = <2>;
-
-			bus-range = <0x00 0xff>;
-
-			ranges = <0x82000000 0 0x00040000 0x00040000 0 0x00002000   /* Port 0.0 registers */
-				  0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-			          0x81000000 0 0          0xe8000000 0 0x00100000>; /* downstream I/O */
-
-			pcie@1,0 {
-				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x00040000 0 0x2000>;
-				reg = <0x0800 0 0 0 0>;
-				#address-cells = <3>;
-				#size-cells = <2>;
-				#interrupt-cells = <1>;
-				ranges;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &intc 9>;
-				marvell,pcie-port = <0>;
-				marvell,pcie-lane = <0>;
-				clocks = <&gate_clk 2>;
-				status = "disabled";
-			};
-		};
-
 		rtc@10300 {
 			compatible = "marvell,kirkwood-rtc", "marvell,orion-rtc";
 			reg = <0x10300 0x20>;
diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi
index a63a111..3933a33 100644
--- a/arch/arm/boot/dts/kirkwood-6282.dtsi
+++ b/arch/arm/boot/dts/kirkwood-6282.dtsi
@@ -1,4 +1,59 @@
 / {
+	mbus {
+		pcie-controller {
+			compatible = "marvell,kirkwood-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+			        0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0       1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0       1 0 /* Port 0.0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0       1 0 /* Port 1.0 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xd0) 0       1 0 /* Port 1.0 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x00040000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &intc 9>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gate_clk 2>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82001000 0 0x00044000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &intc 10>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gate_clk 18>;
+				status = "disabled";
+			};
+		};
+	};
 	ocp@f1000000 {
 
 		pinctrl: pinctrl@10000 {
@@ -94,52 +149,5 @@
 			status = "disabled";
 		};
 
-		pcie-controller {
-			compatible = "marvell,kirkwood-pcie";
-			status = "disabled";
-			device_type = "pci";
-
-			#address-cells = <3>;
-			#size-cells = <2>;
-
-			bus-range = <0x00 0xff>;
-
-			ranges = <0x82000000 0 0x00040000 0x00040000 0 0x00002000   /* Port 0.0 registers */
-			          0x82000000 0 0x00044000 0x00044000 0 0x00002000   /* Port 1.0 registers */
-				  0x82000000 0 0xe0000000 0xe0000000 0 0x08000000   /* non-prefetchable memory */
-			          0x81000000 0 0          0xe8000000 0 0x00100000>; /* downstream I/O */
-
-			pcie@1,0 {
-				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x00040000 0 0x2000>;
-				reg = <0x0800 0 0 0 0>;
-				#address-cells = <3>;
-				#size-cells = <2>;
-				#interrupt-cells = <1>;
-				ranges;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &intc 9>;
-				marvell,pcie-port = <0>;
-				marvell,pcie-lane = <0>;
-				clocks = <&gate_clk 2>;
-				status = "disabled";
-			};
-
-			pcie@2,0 {
-				device_type = "pci";
-				assigned-addresses = <0x82001000 0 0x00044000 0 0x2000>;
-				reg = <0x1000 0 0 0 0>;
-				#address-cells = <3>;
-				#size-cells = <2>;
-				#interrupt-cells = <1>;
-				ranges;
-				interrupt-map-mask = <0 0 0 0>;
-				interrupt-map = <0 0 0 0 &intc 10>;
-				marvell,pcie-port = <1>;
-				marvell,pcie-lane = <0>;
-				clocks = <&gate_clk 18>;
-				status = "disabled";
-			};
-		};
 	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-cloudbox.dts b/arch/arm/boot/dts/kirkwood-cloudbox.dts
index 00c48d2..142b9cd 100644
--- a/arch/arm/boot/dts/kirkwood-cloudbox.dts
+++ b/arch/arm/boot/dts/kirkwood-cloudbox.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "LaCie CloudBox";
@@ -89,3 +89,19 @@
 		gpios = <&gpio0 17 0>;
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-db-88f6281.dts b/arch/arm/boot/dts/kirkwood-db-88f6281.dts
index 9d777ed..72c4b0a 100644
--- a/arch/arm/boot/dts/kirkwood-db-88f6281.dts
+++ b/arch/arm/boot/dts/kirkwood-db-88f6281.dts
@@ -11,14 +11,15 @@
 
 /dts-v1/;
 
-/include/ "kirkwood-db.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood-db.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Marvell DB-88F6281-BP Development Board";
 	compatible = "marvell,db-88f6281-bp", "marvell,kirkwood-88f6281", "marvell,kirkwood";
 
-	ocp@f1000000 {
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-db-88f6282.dts b/arch/arm/boot/dts/kirkwood-db-88f6282.dts
index f4c8528..36c411d 100644
--- a/arch/arm/boot/dts/kirkwood-db-88f6282.dts
+++ b/arch/arm/boot/dts/kirkwood-db-88f6282.dts
@@ -11,14 +11,15 @@
 
 /dts-v1/;
 
-/include/ "kirkwood-db.dtsi"
-/include/ "kirkwood-6282.dtsi"
+#include "kirkwood-db.dtsi"
+#include "kirkwood-6282.dtsi"
 
 / {
 	model = "Marvell DB-88F6282-BP Development Board";
 	compatible = "marvell,db-88f6282-bp", "marvell,kirkwood-88f6282", "marvell,kirkwood";
 
-	ocp@f1000000 {
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-db.dtsi b/arch/arm/boot/dts/kirkwood-db.dtsi
index c87cfb8..c0e2a58 100644
--- a/arch/arm/boot/dts/kirkwood-db.dtsi
+++ b/arch/arm/boot/dts/kirkwood-db.dtsi
@@ -12,7 +12,7 @@
  * and 6282 variants of the Marvell Kirkwood Development Board.
  */
 
-/include/ "kirkwood.dtsi"
+#include "kirkwood.dtsi"
 
 / {
 	memory {
@@ -77,13 +77,21 @@
 			cd-gpios = <&gpio1 6 0>;
 			status = "okay";
 		};
+	};
+};
 
-		pcie-controller {
-			status = "okay";
+&mdio {
+	status = "okay";
 
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
+	ethphy0: ethernet-phy@8 {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
 	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-dns320.dts b/arch/arm/boot/dts/kirkwood-dns320.dts
index 14d4cee..e112ca6 100644
--- a/arch/arm/boot/dts/kirkwood-dns320.dts
+++ b/arch/arm/boot/dts/kirkwood-dns320.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-dnskw.dtsi"
+#include "kirkwood-dnskw.dtsi"
 
 / {
 	model = "D-Link DNS-320 NAS (Rev A1)";
diff --git a/arch/arm/boot/dts/kirkwood-dns325.dts b/arch/arm/boot/dts/kirkwood-dns325.dts
index 6387257..5119fb8 100644
--- a/arch/arm/boot/dts/kirkwood-dns325.dts
+++ b/arch/arm/boot/dts/kirkwood-dns325.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-dnskw.dtsi"
+#include "kirkwood-dnskw.dtsi"
 
 / {
 	model = "D-Link DNS-325 NAS (Rev A1)";
diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
index 0afe1d0..d544f77 100644
--- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
@@ -1,5 +1,5 @@
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "D-Link DNS NASes (kirkwood-based)";
@@ -219,3 +219,19 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@8 {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
index 7714742..59a2117 100644
--- a/arch/arm/boot/dts/kirkwood-dockstar.dts
+++ b/arch/arm/boot/dts/kirkwood-dockstar.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Seagate FreeAgent Dockstar";
@@ -90,3 +90,20 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		compatible = "marvell,88e1116";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts
index 36c7ba3..6f62af9 100644
--- a/arch/arm/boot/dts/kirkwood-dreamplug.dts
+++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Globalscale Technologies Dreamplug";
@@ -99,3 +99,31 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		device_type = "ethernet-phy";
+		reg = <1>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-goflexnet.dts b/arch/arm/boot/dts/kirkwood-goflexnet.dts
index 31caa64..6f7c7d7 100644
--- a/arch/arm/boot/dts/kirkwood-goflexnet.dts
+++ b/arch/arm/boot/dts/kirkwood-goflexnet.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Seagate GoFlex Net";
@@ -170,3 +170,19 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
index 1e642f3..6548b9d 100644
--- a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
+++ b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Globalscale Technologies Guruplug Server Plus";
@@ -96,3 +96,33 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		compatible = "marvell,88e1121";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		device_type = "ethernet-phy";
+		compatible = "marvell,88e1121";
+		reg = <1>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts
index 20c4b08..cb711a3 100644
--- a/arch/arm/boot/dts/kirkwood-ib62x0.dts
+++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "RaidSonic ICY BOX IB-NAS62x0 (Rev B)";
@@ -122,3 +122,19 @@
 
 
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@8 {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index 441204e..0323f01 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Iomega Iconnect";
@@ -18,6 +18,17 @@
 		linux,initrd-end   = <0x4800000>;
 	};
 
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		pinctrl: pinctrl@10000 {
 			pmx_button_reset: pmx-button-reset {
@@ -101,14 +112,6 @@
 				reg = <0x980000 0x1f400000>;
 			};
 		};
-
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
 	};
 
 	gpio-leds {
@@ -176,3 +179,19 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@11 {
+		device_type = "ethernet-phy";
+		reg = <11>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
index 00a7bfe..df84474 100644
--- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
+++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "Iomega StorCenter ix2-200";
@@ -194,3 +194,27 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy1: ethernet-phy@11 {
+		device_type = "ethernet-phy";
+		reg = <11>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		speed = <1000>;
+		duplex = <1>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-is2.dts b/arch/arm/boot/dts/kirkwood-is2.dts
index c3f036b..da674bb 100644
--- a/arch/arm/boot/dts/kirkwood-is2.dts
+++ b/arch/arm/boot/dts/kirkwood-is2.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-ns2-common.dtsi"
+#include "kirkwood-ns2-common.dtsi"
 
 / {
 	model = "LaCie Internet Space v2";
@@ -30,3 +30,5 @@
 		};
 	};
 };
+
+&ethphy0 { reg = <8>; };
diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
index 5d9f5ea..6899408 100644
--- a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
+++ b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-98dx4122.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-98dx4122.dtsi"
 
 / {
 	model = "Keymile Kirkwood Reference Design";
@@ -50,3 +50,19 @@
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-lschlv2.dts b/arch/arm/boot/dts/kirkwood-lschlv2.dts
index 9f55d95..e2fa368 100644
--- a/arch/arm/boot/dts/kirkwood-lschlv2.dts
+++ b/arch/arm/boot/dts/kirkwood-lschlv2.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-lsxl.dtsi"
+#include "kirkwood-lsxl.dtsi"
 
 / {
 	model = "Buffalo Linkstation LS-CHLv2";
diff --git a/arch/arm/boot/dts/kirkwood-lsxhl.dts b/arch/arm/boot/dts/kirkwood-lsxhl.dts
index 5c84c11..8d89cdf 100644
--- a/arch/arm/boot/dts/kirkwood-lsxhl.dts
+++ b/arch/arm/boot/dts/kirkwood-lsxhl.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-lsxl.dtsi"
+#include "kirkwood-lsxl.dtsi"
 
 / {
 	model = "Buffalo Linkstation LS-XHL";
diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi
index 31b17f5..4e8f9e4 100644
--- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi
+++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi
@@ -1,5 +1,5 @@
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	chosen {
@@ -207,3 +207,31 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@8 {
+		device_type = "ethernet-phy";
+		reg = <8>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts
index 6179333..ce2b94b 100644
--- a/arch/arm/boot/dts/kirkwood-mplcec4.dts
+++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	model = "MPL CEC4";
@@ -16,6 +16,17 @@
                 bootargs = "console=ttyS0,115200n8 earlyprintk";
         };
 
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		pinctrl: pinctrl@10000 {
 			pmx_led_health: pmx-led-health {
@@ -134,14 +145,6 @@
 			cd-gpios = <&gpio1 15 1>;
 			/* No WP GPIO */
 		};
-
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
 	};
 
 	gpio-leds {
@@ -191,3 +194,30 @@
 	};
 };
 
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@1 {
+		device_type = "ethernet-phy";
+		reg = <1>;
+	};
+
+	ethphy1: ethernet-phy@2 {
+		device_type = "ethernet-phy";
+		reg = <2>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
new file mode 100644
index 0000000..6317e1d
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
@@ -0,0 +1,125 @@
+/*
+ * Marvell 88F6281 GTW GE Board
+ *
+ * Lennert Buytenhek <buytenh@marvell.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This file contains the definitions that are common between the 6281
+ * and 6282 variants of the Marvell Kirkwood Development Board.
+ */
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	model = "Marvell 88F6281 GTW GE Board";
+	compatible = "marvell,mv88f6281gtw-ge", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>; /* 512 MB */
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		pinctrl@10000 {
+			pmx_usb_led: pmx-usb-led {
+				marvell,pins = "mpp12";
+				marvell,function = "gpo";
+			};
+
+			pmx_leds: pmx-leds {
+				marvell,pins = "mpp20", "mpp21";
+				marvell,function = "gpio";
+			};
+
+			pmx_keys: pmx-keys {
+				marvell,pins = "mpp46", "mpp47";
+				marvell,function = "gpio";
+			};
+		};
+
+		spi@10600 {
+			pinctrl-0 = <&pmx_spi>;
+			pinctrl-names = "default";
+			status = "okay";
+
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "mx25l12805d";
+				reg = <0>;
+				spi-max-frequency = <50000000>;
+				mode = <0>;
+			};
+		};
+
+		serial@12000 {
+			pinctrl-0 = <&pmx_uart0>;
+			pinctrl-names = "default";
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		ehci@50000 {
+			status = "okay";
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_leds &pmx_usb_led>;
+		pinctrl-names = "default";
+
+		green-status {
+			label = "gtw:green:Status";
+			gpios = <&gpio0 20 0>;
+		};
+
+		red-status {
+			label = "gtw:red:Status";
+			gpios = <&gpio0 21 0>;
+		};
+
+		green-usb {
+			label = "gtw:green:USB";
+			gpios = <&gpio0 12 0>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_keys>;
+		pinctrl-names = "default";
+
+		button@1 {
+			label = "SWR Button";
+			linux,code = <0x198>; /* KEY_RESTART */
+			gpios = <&gpio1 15 1>;
+		};
+		button@2 {
+			label = "WPS Button";
+			linux,code = <0x211>; /* KEY_WPS_BUTTON */
+			gpios = <&gpio1 14 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
index ad6ade7..874857e 100644
--- a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
+++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6282.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
 
 / {
 	model = "NETGEAR ReadyNAS Duo v2";
@@ -16,6 +16,17 @@
 		bootargs = "console=ttyS0,115200n8 earlyprintk";
 	};
 
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		pinctrl: pinctrl@10000 {
 			pmx_button_power: pmx-button-power {
@@ -52,6 +63,17 @@
 			};
 		};
 
+		clocks {
+		       #address-cells = <1>;
+		       #size-cells = <0>;
+
+		       g762_clk: fixedclk {
+				 compatible = "fixed-clock";
+				 #clock-cells = <0>;
+				 clock-frequency = <8192>;
+		       };
+		};
+
 		i2c@11000 {
 			status = "okay";
 
@@ -59,6 +81,15 @@
 				compatible = "ricoh,rs5c372a";
 				reg = <0x32>;
 			};
+
+			g762: g762@3e {
+				compatible = "gmt,g762";
+				reg = <0x3e>;
+				clocks = <&g762_clk>; /* input clock */
+				fan_gear_mode = <0>;
+				fan_startv = <1>;
+				pwm_polarity = <0>;
+			};
 		};
 
 		serial@12000 {
@@ -101,14 +132,6 @@
 			status = "okay";
 			nr-ports = <2>;
 		};
-
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
 	};
 
 	gpio-leds {
@@ -184,3 +207,19 @@
                 };
         };
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
index 2afac04..2fcb82e 100644
--- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
@@ -1,5 +1,5 @@
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	chosen {
@@ -84,3 +84,19 @@
 	};
 
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy {
+		device_type = "ethernet-phy";
+                /* overwrite reg property in board file */
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ns2.dts b/arch/arm/boot/dts/kirkwood-ns2.dts
index b50e93d..53368d1 100644
--- a/arch/arm/boot/dts/kirkwood-ns2.dts
+++ b/arch/arm/boot/dts/kirkwood-ns2.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-ns2-common.dtsi"
+#include "kirkwood-ns2-common.dtsi"
 
 / {
 	model = "LaCie Network Space v2";
@@ -30,3 +30,5 @@
 		};
 	};
 };
+
+&ethphy0 { reg = <8>; };
diff --git a/arch/arm/boot/dts/kirkwood-ns2lite.dts b/arch/arm/boot/dts/kirkwood-ns2lite.dts
index af8259f..2796070 100644
--- a/arch/arm/boot/dts/kirkwood-ns2lite.dts
+++ b/arch/arm/boot/dts/kirkwood-ns2lite.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-ns2-common.dtsi"
+#include "kirkwood-ns2-common.dtsi"
 
 / {
 	model = "LaCie Network Space Lite v2";
@@ -30,3 +30,5 @@
 		};
 	};
 };
+
+&ethphy0 { reg = <0>; };
diff --git a/arch/arm/boot/dts/kirkwood-ns2max.dts b/arch/arm/boot/dts/kirkwood-ns2max.dts
index 85f24d2..defdc77 100644
--- a/arch/arm/boot/dts/kirkwood-ns2max.dts
+++ b/arch/arm/boot/dts/kirkwood-ns2max.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-ns2-common.dtsi"
+#include "kirkwood-ns2-common.dtsi"
 
 / {
 	model = "LaCie Network Space Max v2";
@@ -49,3 +49,5 @@
 		};
 	};
 };
+
+&ethphy0 { reg = <8>; };
diff --git a/arch/arm/boot/dts/kirkwood-ns2mini.dts b/arch/arm/boot/dts/kirkwood-ns2mini.dts
index 329e530..adbafdd 100644
--- a/arch/arm/boot/dts/kirkwood-ns2mini.dts
+++ b/arch/arm/boot/dts/kirkwood-ns2mini.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "kirkwood-ns2-common.dtsi"
+#include "kirkwood-ns2-common.dtsi"
 
 / {
 	/* This machine is embedded in the first LaCie CloudBox product. */
@@ -50,3 +50,5 @@
 		};
 	};
 };
+
+&ethphy0 { reg = <0>; };
diff --git a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
new file mode 100644
index 0000000..06267a9
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
@@ -0,0 +1,107 @@
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	model = "ZyXEL NSA310";
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pmx_usb_power_off: pmx-usb-power-off {
+				marvell,pins = "mpp21";
+				marvell,function = "gpio";
+			};
+			pmx_pwr_off: pmx-pwr-off {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+
+		};
+
+		serial@12000 {
+			status = "ok";
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+
+		nand@3000000 {
+			status = "okay";
+			chip-delay = <35>;
+
+			partition@0 {
+				label = "uboot";
+				reg = <0x0000000 0x0100000>;
+				read-only;
+			};
+			partition@100000 {
+				label = "uboot_env";
+				reg = <0x0100000 0x0080000>;
+			};
+			partition@180000 {
+				label = "key_store";
+				reg = <0x0180000 0x0080000>;
+			};
+			partition@200000 {
+				label = "info";
+				reg = <0x0200000 0x0080000>;
+			};
+			partition@280000 {
+				label = "etc";
+				reg = <0x0280000 0x0a00000>;
+			};
+			partition@c80000 {
+				label = "kernel_1";
+				reg = <0x0c80000 0x0a00000>;
+			};
+			partition@1680000 {
+				label = "rootfs1";
+				reg = <0x1680000 0x2fc0000>;
+			};
+			partition@4640000 {
+				label = "kernel_2";
+				reg = <0x4640000 0x0a00000>;
+			};
+			partition@5040000 {
+				label = "rootfs2";
+				reg = <0x5040000 0x2fc0000>;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		pinctrl-0 = <&pmx_pwr_off>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 16 0>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_usb_power_off>;
+		pinctrl-names = "default";
+
+		usb0_power_off: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "USB Power Off";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 21 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts
index 6900359..7aeae0c 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310.dts
@@ -1,10 +1,8 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood-nsa310-common.dtsi"
 
 / {
-	model = "ZyXEL NSA310";
 	compatible = "zyxel,nsa310", "marvell,kirkwood-88f6281", "marvell,kirkwood";
 
 	memory {
@@ -16,6 +14,17 @@
 		bootargs = "console=ttyS0,115200";
 	};
 
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		pinctrl: pinctrl@10000 {
 			pinctrl-0 = <&pmx_unknown>;
@@ -41,11 +50,6 @@
 				marvell,function = "gpio";
 			};
 
-			pmx_usb_power_off: pmx-usb-power-off {
-				marvell,pins = "mpp21";
-				marvell,function = "gpio";
-			};
-
 			pmx_led_sys_green: pmx-led-sys-green {
 				marvell,pins = "mpp28";
 				marvell,function = "gpio";
@@ -95,20 +99,6 @@
 				marvell,pins = "mpp46";
 				marvell,function = "gpio";
 			};
-
-			pmx_pwr_off: pmx-pwr-off {
-				marvell,pins = "mpp48";
-				marvell,function = "gpio";
-			};
-		};
-
-		serial@12000 {
-			status = "ok";
-		};
-
-		sata@80000 {
-			status = "okay";
-			nr-ports = <2>;
 		};
 
 		i2c@11000 {
@@ -119,57 +109,6 @@
 				reg = <0x2e>;
 			};
 		};
-
-		nand@3000000 {
-			status = "okay";
-			chip-delay = <35>;
-
-			partition@0 {
-				label = "uboot";
-				reg = <0x0000000 0x0100000>;
-				read-only;
-			};
-			partition@100000 {
-				label = "uboot_env";
-				reg = <0x0100000 0x0080000>;
-			};
-			partition@180000 {
-				label = "key_store";
-				reg = <0x0180000 0x0080000>;
-			};
-			partition@200000 {
-				label = "info";
-				reg = <0x0200000 0x0080000>;
-			};
-			partition@280000 {
-				label = "etc";
-				reg = <0x0280000 0x0a00000>;
-			};
-			partition@c80000 {
-				label = "kernel_1";
-				reg = <0x0c80000 0x0a00000>;
-			};
-			partition@1680000 {
-				label = "rootfs1";
-				reg = <0x1680000 0x2fc0000>;
-			};
-			partition@4640000 {
-				label = "kernel_2";
-				reg = <0x4640000 0x0a00000>;
-			};
-			partition@5040000 {
-				label = "rootfs2";
-				reg = <0x5040000 0x2fc0000>;
-			};
-		};
-
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
 	};
 
 	gpio_keys {
@@ -246,30 +185,4 @@
 			gpios = <&gpio1 8 0>;
 		};
 	};
-
-	gpio_poweroff {
-		compatible = "gpio-poweroff";
-		pinctrl-0 = <&pmx_pwr_off>;
-		pinctrl-names = "default";
-		gpios = <&gpio1 16 0>;
-	};
-
-	regulators {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		pinctrl-0 = <&pmx_usb_power_off>;
-		pinctrl-names = "default";
-
-		usb0_power_off: regulator@1 {
-			compatible = "regulator-fixed";
-			reg = <1>;
-			regulator-name = "USB Power Off";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			regulator-always-on;
-			regulator-boot-on;
-			gpio = <&gpio0 21 0>;
-		};
-	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-nsa310a.dts b/arch/arm/boot/dts/kirkwood-nsa310a.dts
new file mode 100644
index 0000000..ab0212b
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-nsa310a.dts
@@ -0,0 +1,165 @@
+/dts-v1/;
+
+#include "kirkwood-nsa310-common.dtsi"
+
+/*
+ * There are at least two different NSA310 designs. This variant does
+ * not have the red USB Led.
+ */
+
+/ {
+	compatible = "zyxel,nsa310a", "zyxel,nsa310", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pinctrl-names = "default";
+
+			pmx_led_esata_green: pmx-led-esata-green {
+				marvell,pins = "mpp12";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_esata_red: pmx-led-esata-red {
+				marvell,pins = "mpp13";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_usb_green: pmx-led-usb-green {
+				marvell,pins = "mpp15";
+				marvell,function = "gpio";
+			};
+
+			pmx_usb_power_off: pmx-usb-power-off {
+				marvell,pins = "mpp21";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_sys_green: pmx-led-sys-green {
+				marvell,pins = "mpp28";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_sys_red: pmx-led-sys-red {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+
+			pmx_btn_reset: pmx-btn-reset {
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+
+			pmx_btn_copy: pmx-btn-copy {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_copy_green: pmx-led-copy-green {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_copy_red: pmx-led-copy-red {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_hdd_green: pmx-led-hdd-green {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_hdd_red: pmx-led-hdd-red {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+
+			pmx_btn_power: pmx-btn-power {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+
+		};
+
+		i2c@11000 {
+			status = "okay";
+
+			lm85: lm85@2e {
+				compatible = "lm85";
+				reg = <0x2e>;
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@1 {
+			label = "Power Button";
+			linux,code = <116>;
+			gpios = <&gpio1 14 0>;
+		};
+		button@2 {
+			label = "Copy Button";
+			linux,code = <133>;
+			gpios = <&gpio1 5 1>;
+		};
+		button@3 {
+			label = "Reset Button";
+			linux,code = <0x198>;
+			gpios = <&gpio1 4 1>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green-sys {
+			label = "nsa310:green:sys";
+			gpios = <&gpio0 28 0>;
+		};
+		red-sys {
+			label = "nsa310:red:sys";
+			gpios = <&gpio0 29 0>;
+		};
+		green-hdd {
+			label = "nsa310:green:hdd";
+			gpios = <&gpio1 9 0>;
+		};
+		red-hdd {
+			label = "nsa310:red:hdd";
+			gpios = <&gpio1 10 0>;
+		};
+		green-esata {
+			label = "nsa310:green:esata";
+			gpios = <&gpio0 12 0>;
+		};
+		red-esata {
+			label = "nsa310:red:esata";
+			gpios = <&gpio0 13 0>;
+		};
+		green-usb {
+			label = "nsa310:green:usb";
+			gpios = <&gpio0 15 0>;
+		};
+		green-copy {
+			label = "nsa310:green:copy";
+			gpios = <&gpio1 7 0>;
+		};
+		red-copy {
+			label = "nsa310:red:copy";
+			gpios = <&gpio1 8 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
index 38dc851..85ccf8d 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6282.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
 
 / {
 	model = "Plat'Home OpenBlocksA6";
@@ -166,3 +166,19 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi b/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
index f7143f1..5696b63 100644
--- a/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
@@ -6,8 +6,8 @@
  * Licensed under GPLv2
  */
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
 
 / {
 	memory {
@@ -91,3 +91,19 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts b/arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts
index f620ce4..eac6a21 100644
--- a/arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts
+++ b/arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts
@@ -8,7 +8,7 @@
 
 /dts-v1/;
 
-/include/ "kirkwood-sheevaplug-common.dtsi"
+#include "kirkwood-sheevaplug-common.dtsi"
 
 / {
 	model = "Globalscale Technologies eSATA SheevaPlug";
diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug.dts b/arch/arm/boot/dts/kirkwood-sheevaplug.dts
index bf1dff2..bb61918 100644
--- a/arch/arm/boot/dts/kirkwood-sheevaplug.dts
+++ b/arch/arm/boot/dts/kirkwood-sheevaplug.dts
@@ -8,7 +8,7 @@
 
 /dts-v1/;
 
-/include/ "kirkwood-sheevaplug-common.dtsi"
+#include "kirkwood-sheevaplug-common.dtsi"
 
 / {
 	model = "Globalscale Technologies SheevaPlug";
diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts
index f2052d7..30842b4 100644
--- a/arch/arm/boot/dts/kirkwood-topkick.dts
+++ b/arch/arm/boot/dts/kirkwood-topkick.dts
@@ -1,7 +1,7 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6282.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
 
 / {
 	model = "Univeral Scientific Industrial Co. Topkick-1281P2";
@@ -203,3 +203,19 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6281.dts b/arch/arm/boot/dts/kirkwood-ts219-6281.dts
index 6dd1038..f755bc1 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6281.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6281.dts
@@ -1,8 +1,8 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6281.dtsi"
-/include/ "kirkwood-ts219.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-ts219.dtsi"
 
 / {
 	ocp@f1000000 {
@@ -50,4 +50,6 @@
 			gpios = <&gpio0 16 1>;
 		};
 	};
-};
\ No newline at end of file
+};
+
+&ethphy0 { reg = <8>; };
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
index 6fdc5ff..9efcd2d 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6282.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
@@ -1,10 +1,21 @@
 /dts-v1/;
 
-/include/ "kirkwood.dtsi"
-/include/ "kirkwood-6282.dtsi"
-/include/ "kirkwood-ts219.dtsi"
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+#include "kirkwood-ts219.dtsi"
 
 / {
+	mbus {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
+		pcie-controller {
+			status = "okay";
+
+			pcie@2,0 {
+				status = "okay";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		pinctrl: pinctrl@10000 {
 
@@ -30,14 +41,6 @@
 				marvell,function = "gpio";
 			};
 		};
-		pcie-controller {
-			status = "okay";
-
-			pcie@2,0 {
-				status = "okay";
-			};
-		};
-
 	};
 
 	gpio_keys {
@@ -58,4 +61,6 @@
 			gpios = <&gpio1 5 1>;
 		};
 	};
-};
\ No newline at end of file
+};
+
+&ethphy0 { reg = <0>; };
diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/kirkwood-ts219.dtsi
index 0c9a94c..39158cf 100644
--- a/arch/arm/boot/dts/kirkwood-ts219.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ts219.dtsi
@@ -11,6 +11,16 @@
 		bootargs = "console=ttyS0,115200n8";
 	};
 
+	mbus {
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				status = "okay";
+			};
+		};
+	};
+
 	ocp@f1000000 {
 		i2c@11000 {
 			status = "okay";
@@ -87,12 +97,21 @@
 			status = "okay";
 			nr-ports = <2>;
 		};
-		pcie-controller {
-			status = "okay";
+	};
+};
 
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy {
+		device_type = "ethernet-phy";
+                /* overwrite reg property in board file */
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
 	};
 };
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 9809fc1..6489b98 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -1,5 +1,7 @@
 /include/ "skeleton.dtsi"
 
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
 / {
 	compatible = "marvell,kirkwood";
 	interrupt-parent = <&intc>;
@@ -20,23 +22,53 @@
 	       gpio0 = &gpio0;
 	       gpio1 = &gpio1;
 	};
-	intc: interrupt-controller {
-		compatible = "marvell,orion-intc", "marvell,intc";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0xf1020204 0x04>,
-		      <0xf1020214 0x04>;
+
+	mbus {
+		compatible = "marvell,kirkwood-mbus", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		pcie-mem-aperture = <0xe0000000 0x10000000>; /* 256 MiB memory space */
+		pcie-io-aperture  = <0xf2000000 0x100000>;   /*   1 MiB    I/O space */
 	};
 
 	ocp@f1000000 {
 		compatible = "simple-bus";
 		ranges = <0x00000000 0xf1000000 0x0100000
-		          0xe0000000 0xe0000000 0x8100000 /* PCIE */
 		          0xf4000000 0xf4000000 0x0000400
 		          0xf5000000 0xf5000000 0x0000400>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		timer: timer@20300 {
+			compatible = "marvell,orion-timer";
+			reg = <0x20300 0x20>;
+			interrupt-parent = <&bridge_intc>;
+			interrupts = <1>, <2>;
+			clocks = <&core_clk 0>;
+		};
+
+		intc: main-interrupt-ctrl@20200 {
+			compatible = "marvell,orion-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x20200 0x10>, <0x20210 0x10>;
+		};
+
+		bridge_intc: bridge-interrupt-ctrl@20110 {
+			compatible = "marvell,orion-bridge-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x20110 0x8>;
+			interrupts = <1>;
+			marvell,#interrupts = <6>;
+		};
+
+		mbusc: mbus-controller@20000 {
+			compatible = "marvell,mbus-controller";
+			reg = <0x20000 0x80>, <0x1500 0x20>;
+		};
+
 		core_clk: core-clocks@10030 {
 			compatible = "marvell,kirkwood-core-clock";
 			reg = <0x10030 0x4>;
@@ -103,9 +135,11 @@
 			#clock-cells = <1>;
 		};
 
-		wdt@20300 {
+		wdt: watchdog-timer@20300 {
 			compatible = "marvell,orion-wdt";
 			reg = <0x20300 0x28>;
+			interrupt-parent = <&bridge_intc>;
+			interrupts = <3>;
 			clocks = <&gate_clk 7>;
 			status = "okay";
 		};
@@ -192,5 +226,57 @@
 			clocks = <&gate_clk 17>;
 			status = "okay";
 		};
+
+		mdio: mdio-bus@72004 {
+			compatible = "marvell,orion-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x72004 0x84>;
+			interrupts = <46>;
+			clocks = <&gate_clk 0>;
+			status = "disabled";
+
+			/* add phy nodes in board file */
+		};
+
+		eth0: ethernet-controller@72000 {
+			compatible = "marvell,kirkwood-eth";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x72000 0x4000>;
+			clocks = <&gate_clk 0>;
+			marvell,tx-checksum-limit = <1600>;
+			status = "disabled";
+
+			ethernet0-port@0 {
+				device_type = "network";
+				compatible = "marvell,kirkwood-eth-port";
+				reg = <0>;
+				interrupts = <11>;
+				/* overwrite MAC address in bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+				/* set phy-handle property in board file */
+			};
+		};
+
+		eth1: ethernet-controller@76000 {
+			compatible = "marvell,kirkwood-eth";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x76000 0x4000>;
+			clocks = <&gate_clk 19>;
+			marvell,tx-checksum-limit = <1600>;
+			status = "disabled";
+
+			ethernet1-port@0 {
+				device_type = "network";
+				compatible = "marvell,kirkwood-eth-port";
+				reg = <0>;
+				interrupts = <15>;
+				/* overwrite MAC address in bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+				/* set phy-handle property in board file */
+			};
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts
index db2060c..9c1167b0 100644
--- a/arch/arm/boot/dts/msm8960-cdp.dts
+++ b/arch/arm/boot/dts/msm8960-cdp.dts
@@ -26,7 +26,7 @@
 		cpu-offset = <0x80000>;
 	};
 
-	msmgpio: gpio@fd510000 {
+	msmgpio: gpio@800000 {
 		compatible = "qcom,msm-gpio";
 		gpio-controller;
 		#gpio-cells = <2>;
@@ -34,7 +34,7 @@
 		interrupts = <0 32 0x4>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		reg = <0xfd510000 0x4000>;
+		reg = <0x800000 0x4000>;
 	};
 
 	serial@16440000 {
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
index 08b7267..65d7b60 100644
--- a/arch/arm/boot/dts/omap5-uevm.dts
+++ b/arch/arm/boot/dts/omap5-uevm.dts
@@ -235,7 +235,7 @@
 };
 
 &mmc1 {
-	vmmc-supply = <&vmmcsd_fixed>;
+	vmmc-supply = <&ldo9_reg>;
 	bus-width = <4>;
 };
 
@@ -282,6 +282,7 @@
 
 			regulators {
 				smps123_reg: smps123 {
+					/* VDD_OPP_MPU */
 					regulator-name = "smps123";
 					regulator-min-microvolt = < 600000>;
 					regulator-max-microvolt = <1500000>;
@@ -290,6 +291,7 @@
 				};
 
 				smps45_reg: smps45 {
+					/* VDD_OPP_MM */
 					regulator-name = "smps45";
 					regulator-min-microvolt = < 600000>;
 					regulator-max-microvolt = <1310000>;
@@ -298,6 +300,7 @@
 				};
 
 				smps6_reg: smps6 {
+					/* VDD_DDR3 - over VDD_SMPS6 */
 					regulator-name = "smps6";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
@@ -306,6 +309,7 @@
 				};
 
 				smps7_reg: smps7 {
+					/* VDDS_1v8_OMAP over VDDS_1v8_MAIN */
 					regulator-name = "smps7";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -314,6 +318,7 @@
 				};
 
 				smps8_reg: smps8 {
+					/* VDD_OPP_CORE */
 					regulator-name = "smps8";
 					regulator-min-microvolt = < 600000>;
 					regulator-max-microvolt = <1310000>;
@@ -322,15 +327,15 @@
 				};
 
 				smps9_reg: smps9 {
+					/* VDDA_2v1_AUD over VDD_2v1 */
 					regulator-name = "smps9";
 					regulator-min-microvolt = <2100000>;
 					regulator-max-microvolt = <2100000>;
-					regulator-always-on;
-					regulator-boot-on;
 					ti,smps-range = <0x80>;
 				};
 
 				smps10_reg: smps10 {
+					/* VBUS_5V_OTG */
 					regulator-name = "smps10";
 					regulator-min-microvolt = <5000000>;
 					regulator-max-microvolt = <5000000>;
@@ -339,38 +344,40 @@
 				};
 
 				ldo1_reg: ldo1 {
+					/* VDDAPHY_CAM: vdda_csiport */
 					regulator-name = "ldo1";
-					regulator-min-microvolt = <2800000>;
-					regulator-max-microvolt = <2800000>;
-					regulator-always-on;
-					regulator-boot-on;
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1800000>;
 				};
 
 				ldo2_reg: ldo2 {
+					/* VCC_2V8_DISP: Does not go anywhere */
 					regulator-name = "ldo2";
-					regulator-min-microvolt = <2900000>;
-					regulator-max-microvolt = <2900000>;
-					regulator-always-on;
-					regulator-boot-on;
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					/* Unused */
+					status = "disabled";
 				};
 
 				ldo3_reg: ldo3 {
+					/* VDDAPHY_MDM: vdda_lli */
 					regulator-name = "ldo3";
-					regulator-min-microvolt = <3000000>;
-					regulator-max-microvolt = <3000000>;
-					regulator-always-on;
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
 					regulator-boot-on;
+					/* Only if Modem is used */
+					status = "disabled";
 				};
 
 				ldo4_reg: ldo4 {
+					/* VDDAPHY_DISP: vdda_dsiport/hdmi */
 					regulator-name = "ldo4";
-					regulator-min-microvolt = <2200000>;
-					regulator-max-microvolt = <2200000>;
-					regulator-always-on;
-					regulator-boot-on;
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1800000>;
 				};
 
 				ldo5_reg: ldo5 {
+					/* VDDA_1V8_PHY: usb/sata/hdmi.. */
 					regulator-name = "ldo5";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -379,38 +386,43 @@
 				};
 
 				ldo6_reg: ldo6 {
+					/* VDDS_1V2_WKUP: hsic/ldo_emu_wkup */
 					regulator-name = "ldo6";
-					regulator-min-microvolt = <1500000>;
-					regulator-max-microvolt = <1500000>;
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
 
 				ldo7_reg: ldo7 {
+					/* VDD_VPP: vpp1 */
 					regulator-name = "ldo7";
-					regulator-min-microvolt = <1500000>;
-					regulator-max-microvolt = <1500000>;
-					regulator-always-on;
-					regulator-boot-on;
+					regulator-min-microvolt = <2000000>;
+					regulator-max-microvolt = <2000000>;
+					/* Only for efuse reprograming! */
+					status = "disabled";
 				};
 
 				ldo8_reg: ldo8 {
+					/* VDD_3v0: Does not go anywhere */
 					regulator-name = "ldo8";
-					regulator-min-microvolt = <1500000>;
-					regulator-max-microvolt = <1500000>;
-					regulator-always-on;
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
 					regulator-boot-on;
+					/* Unused */
+					status = "disabled";
 				};
 
 				ldo9_reg: ldo9 {
+					/* VCC_DV_SDIO: vdds_sdcard */
 					regulator-name = "ldo9";
 					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-always-on;
+					regulator-max-microvolt = <3000000>;
 					regulator-boot-on;
 				};
 
 				ldoln_reg: ldoln {
+					/* VDDA_1v8_REF: vdds_osc/mm_l4per.. */
 					regulator-name = "ldoln";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -419,12 +431,20 @@
 				};
 
 				ldousb_reg: ldousb {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
 					regulator-name = "ldousb";
 					regulator-min-microvolt = <3250000>;
 					regulator-max-microvolt = <3250000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
+
+				regen3_reg: regen3 {
+					/* REGEN3 controls LDO9 supply to card */
+					regulator-name = "regen3";
+					regulator-always-on;
+					regulator-boot-on;
+				};
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index e643620..07be2cd 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -644,7 +644,7 @@
 			utmi-mode = <2>;
 			ranges;
 			dwc3@4a030000 {
-				compatible = "synopsys,dwc3";
+				compatible = "snps,dwc3";
 				reg = <0x4a030000 0x1000>;
 				interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
 				usb-phy = <&usb2_phy>, <&usb3_phy>;
diff --git a/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts b/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
index 0077fc8..aed83de 100644
--- a/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
+++ b/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
@@ -53,3 +53,20 @@
 		};
 	};
 };
+
+&mdio {
+	status = "okay";
+
+	ethphy: ethernet-phy {
+		device-type = "ethernet-phy";
+		reg = <8>;
+	};
+};
+
+&eth {
+	status = "okay";
+
+	ethernet-port@0 {
+		phy-handle = <&ethphy>;
+	};
+};
diff --git a/arch/arm/boot/dts/orion5x.dtsi b/arch/arm/boot/dts/orion5x.dtsi
index 892c64e..e06c37e 100644
--- a/arch/arm/boot/dts/orion5x.dtsi
+++ b/arch/arm/boot/dts/orion5x.dtsi
@@ -16,11 +16,12 @@
 	aliases {
 		gpio0 = &gpio0;
 	};
+
 	intc: interrupt-controller {
-		compatible = "marvell,orion-intc", "marvell,intc";
+		compatible = "marvell,orion-intc";
 		interrupt-controller;
 		#interrupt-cells = <1>;
-		reg = <0xf1020204 0x04>;
+		reg = <0xf1020200 0x08>;
 	};
 
 	ocp@f1000000 {
@@ -132,5 +133,34 @@
 			interrupts = <28>;
 			status = "okay";
 		};
+
+		mdio: mdio-bus@72004 {
+			compatible = "marvell,orion-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x72004 0x84>;
+			interrupts = <22>;
+			status = "disabled";
+
+			/* add phy nodes in board file */
+		};
+
+		eth: ethernet-controller@72000 {
+			compatible = "marvell,orion-eth";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x72000 0x4000>;
+			marvell,tx-checksum-limit = <1600>;
+			status = "disabled";
+
+			ethernet-port@0 {
+				device_type = "network";
+				compatible = "marvell,orion-eth-port";
+				reg = <0>;
+				/* overwrite MAC address in bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+				/* set phy-handle property in board file */
+			};
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
new file mode 100644
index 0000000..f444624
--- /dev/null
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
@@ -0,0 +1,65 @@
+/*
+ * Device Tree Source for the APE6EVM board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r8a73a4.dtsi"
+
+/ {
+	model = "APE6EVM";
+	compatible = "renesas,ape6evm-reference", "renesas,r8a73a4";
+
+	chosen {
+		bootargs = "console=ttySC0,115200 ignore_loglevel rw";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x40000000>;
+	};
+
+	lbsc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0x80000000>;
+	};
+};
+
+&i2c5 {
+	vdd_dvfs: max8973@1b {
+		compatible = "maxim,max8973";
+		reg = <0x1b>;
+
+		regulator-min-microvolt = <935000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_dvfs>;
+	operating-points = <
+		/* kHz  uV */
+		1950000 1115000
+		1462500  995000
+	>;
+	voltage-tolerance = <1>; /* 1% */
+};
+
+&pfc {
+	pinctrl-0 = <&scifa0_pins>;
+	pinctrl-names = "default";
+
+	scifa0_pins: scifa0 {
+		renesas,groups = "scifa0_data";
+		renesas,function = "scifa0";
+	};
+};
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
index f603c69..72f867e 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
@@ -16,7 +16,7 @@
 	compatible = "renesas,ape6evm", "renesas,r8a73a4";
 
 	chosen {
-		bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp";
+		bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
 	};
 
 	memory@40000000 {
@@ -50,3 +50,25 @@
 		};
 	};
 };
+
+&i2c5 {
+	vdd_dvfs: max8973@1b {
+		compatible = "maxim,max8973";
+		reg = <0x1b>;
+
+		regulator-min-microvolt = <935000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_dvfs>;
+	operating-points = <
+		/* kHz  uV */
+		1950000 1115000
+		1462500  995000
+	>;
+	voltage-tolerance = <1>; /* 1% */
+};
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index 4ff2019..e344b10 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -85,4 +85,137 @@
 		interrupt-parent = <&gic>;
 		interrupts = <0 69 4>;
 	};
+
+	i2c0: i2c@e6500000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6500000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 174 0x4>;
+	};
+
+	i2c1: i2c@e6510000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6510000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 175 0x4>;
+	};
+
+	i2c2: i2c@e6520000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6520000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 176 0x4>;
+	};
+
+	i2c3: i2c@e6530000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6530000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 177 0x4>;
+	};
+
+	i2c4: i2c@e6540000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6540000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 178 0x4>;
+	};
+
+	i2c5: i2c@e60b0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe60b0000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 179 0x4>;
+	};
+
+	i2c6: i2c@e6550000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6550000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 184 0x4>;
+	};
+
+	i2c7: i2c@e6560000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6560000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 185 0x4>;
+	};
+
+	i2c8: i2c@e6570000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0 0xe6570000 0 0x428>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 173 0x4>;
+	};
+
+	mmcif0: mmcif@ee200000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0 0xee200000 0 0x80>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 169 0x4>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	mmcif1: mmcif@ee220000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0 0xee220000 0 0x80>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 170 0x4>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	sdhi0: sdhi@ee100000 {
+		compatible = "renesas,r8a73a4-sdhi";
+		reg = <0 0xee100000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 165 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	sdhi1: sdhi@ee120000 {
+		compatible = "renesas,r8a73a4-sdhi";
+		reg = <0 0xee120000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 166 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	sdhi2: sdhi@ee140000 {
+		compatible = "renesas,r8a73a4-sdhi";
+		reg = <0 0xee140000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 167 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	pfc: pfc@e6050000 {
+		compatible = "renesas,pfc-r8a73a4";
+		reg = <0 0xe6050000 0 0x9000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
index 09ea22c..c638e4a 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
@@ -10,13 +10,14 @@
 
 /dts-v1/;
 /include/ "r8a7740.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "armadillo 800 eva reference";
 	compatible = "renesas,armadillo800eva-reference", "renesas,r8a7740";
 
 	chosen {
-		bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw";
+		bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
 	};
 
 	memory {
@@ -33,6 +34,21 @@
 		regulator-boot-on;
 	};
 
+	leds {
+		compatible = "gpio-leds";
+		led1 {
+			gpios = <&pfc 102 GPIO_ACTIVE_HIGH>;
+		};
+		led2 {
+			gpios = <&pfc 111 GPIO_ACTIVE_HIGH>;
+		};
+		led3 {
+			gpios = <&pfc 110 GPIO_ACTIVE_HIGH>;
+		};
+		led4 {
+			gpios = <&pfc 177 GPIO_ACTIVE_HIGH>;
+		};
+	};
 };
 
 &i2c0 {
@@ -41,5 +57,23 @@
 		reg = <0x55>;
 		interrupt-parent = <&irqpin1>;
 		interrupts = <2 0>; /* IRQ10: hwirq 2 on irqpin1 */
+		pinctrl-0 = <&st1232_pins>;
+		pinctrl-names = "default";
+		gpios = <&pfc 166 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&pfc {
+	pinctrl-0 = <&scifa1_pins>;
+	pinctrl-names = "default";
+
+	scifa1_pins: scifa1 {
+		renesas,groups = "scifa1_data";
+		renesas,function = "scifa1";
+	};
+
+	st1232_pins: st1232 {
+		renesas,groups = "intc_irq10";
+		renesas,function = "intc";
 	};
 };
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
index 93da655..426cd9c 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
@@ -16,7 +16,7 @@
 	compatible = "renesas,armadillo800eva";
 
 	chosen {
-		bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw";
+		bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
 	};
 
 	memory {
diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 24e9306..44d3d52 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -32,6 +32,11 @@
 		      <0xc2000000 0x1000>;
 	};
 
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts = <0 83 4>;
+	};
+
 	/* irqpin0: IRQ0 - IRQ7 */
 	irqpin0: irqpin@e6900000 {
 		compatible = "renesas,intc-irqpin";
@@ -139,4 +144,19 @@
 			      0 72 0x4
 			      0 73 0x4>;
 	};
+
+	pfc: pfc@e6050000 {
+		compatible = "renesas,pfc-r8a7740";
+		reg = <0xe6050000 0x8000>,
+		      <0xe605800c 0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	tpu: pwm@e6600000 {
+		compatible = "renesas,tpu-r8a7740", "renesas,tpu";
+		reg = <0xe6600000 0x100>;
+		status = "disabled";
+		#pwm-cells = <3>;
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
new file mode 100644
index 0000000..9bb903a
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
@@ -0,0 +1,32 @@
+/*
+ * Reference Device Tree Source for the Bock-W board
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on r8a7779
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r8a7778.dtsi"
+
+/ {
+	model = "bockw";
+	compatible = "renesas,bockw-reference", "renesas,r8a7778";
+
+	chosen {
+		bootargs = "console=ttySC0,115200 ignore_loglevel rw";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x10000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/r8a7778-bockw.dts
index 0076b1e..12bbebc 100644
--- a/arch/arm/boot/dts/r8a7778-bockw.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw.dts
@@ -22,7 +22,7 @@
 	compatible = "renesas,bockw", "renesas,r8a7778";
 
 	chosen {
-		bootargs = "console=ttySC0,115200 ignore_loglevel ip=dhcp root=/dev/nfs";
+		bootargs = "console=ttySC0,115200 ignore_loglevel ip=dhcp root=/dev/nfs rw";
 	};
 
 	memory {
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index 4743735..45ac404 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -32,4 +32,70 @@
 		reg = <0xfe438000 0x1000>,
 		      <0xfe430000 0x100>;
 	};
+
+	gpio0: gpio@ffc40000 {
+		compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
+		reg = <0xffc40000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 103 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 0 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio1: gpio@ffc41000 {
+		compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
+		reg = <0xffc41000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 103 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 32 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio2: gpio@ffc42000 {
+		compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
+		reg = <0xffc42000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 103 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 64 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio3: gpio@ffc43000 {
+		compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
+		reg = <0xffc43000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 103 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 96 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio4: gpio@ffc44000 {
+		compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
+		reg = <0xffc44000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 103 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 128 27>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	pfc: pfc@fffc0000 {
+		compatible = "renesas,pfc-r8a7778";
+		reg = <0xfffc000 0x118>;
+		#gpio-range-cells = <3>;
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7779-marzen-reference.dts b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
index 72be4c8..6d55083 100644
--- a/arch/arm/boot/dts/r8a7779-marzen-reference.dts
+++ b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
@@ -11,13 +11,14 @@
 
 /dts-v1/;
 /include/ "r8a7779.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "marzen";
 	compatible = "renesas,marzen-reference", "renesas,r8a7779";
 
 	chosen {
-		bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on";
+		bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on rw";
 	};
 
 	memory {
@@ -37,6 +38,9 @@
 	lan0@18000000 {
 		compatible = "smsc,lan9220", "smsc,lan9115";
 		reg = <0x18000000 0x100>;
+		pinctrl-0 = <&lan0_pins>;
+		pinctrl-names = "default";
+
 		phy-mode = "mii";
 		interrupt-parent = <&gic>;
 		interrupts = <0 28 0x4>;
@@ -44,4 +48,49 @@
 		vddvario-supply = <&fixedregulator3v3>;
 		vdd33a-supply = <&fixedregulator3v3>;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		led2 {
+			gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+		};
+		led3 {
+			gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+		};
+		led4 {
+			gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&pfc {
+	pinctrl-0 = <&scif2_pins &scif4_pins &sdhi0_pins>;
+	pinctrl-names = "default";
+
+	lan0_pins: lan0 {
+		intc {
+			renesas,groups = "intc_irq1_b";
+			renesas,function = "intc";
+		};
+		lbsc {
+			renesas,groups = "lbsc_ex_cs0";
+			renesas,function = "lbsc";
+		};
+	};
+
+	scif2_pins: scif2 {
+		renesas,groups = "scif2_data_c";
+		renesas,function = "scif2";
+	};
+
+	scif4_pins: scif4 {
+		renesas,groups = "scif4_data";
+		renesas,function = "scif4";
+	};
+
+	sdhi0_pins: sdhi0 {
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd",
+				 "sdhi0_wp";
+		renesas,function = "sdhi0";
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts
new file mode 100644
index 0000000..f3f7f79
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7779-marzen.dts
@@ -0,0 +1,27 @@
+/*
+ * Device Tree Source for the Marzen board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r8a7779.dtsi"
+
+/ {
+	model = "marzen";
+	compatible = "renesas,marzen", "renesas,r8a7779";
+
+	chosen {
+		bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x40000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index 7f146c6..23a6244 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -48,6 +48,90 @@
                       <0xf0000100 0x100>;
         };
 
+	gpio0: gpio@ffc40000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc40000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 141 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 0 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio1: gpio@ffc41000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc41000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 142 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 32 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio2: gpio@ffc42000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc42000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 143 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 64 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio3: gpio@ffc43000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc43000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 144 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 96 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio4: gpio@ffc44000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc44000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 145 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 128 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio5: gpio@ffc45000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc45000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 146 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 160 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio6: gpio@ffc46000 {
+		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
+		reg = <0xffc46000 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 147 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 192 9>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
 	irqpin0: irqpin@fe780010 {
 		compatible = "renesas,intc-irqpin";
 		#interrupt-cells = <2>;
@@ -65,7 +149,7 @@
 		sense-bitfield-width = <2>;
 	};
 
-	i2c0: i2c@0xffc70000 {
+	i2c0: i2c@ffc70000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "renesas,rmobile-iic";
@@ -74,7 +158,7 @@
 		interrupts = <0 79 0x4>;
 	};
 
-	i2c1: i2c@0xffc71000 {
+	i2c1: i2c@ffc71000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "renesas,rmobile-iic";
@@ -83,7 +167,7 @@
 		interrupts = <0 82 0x4>;
 	};
 
-	i2c2: i2c@0xffc72000 {
+	i2c2: i2c@ffc72000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "renesas,rmobile-iic";
@@ -92,7 +176,7 @@
 		interrupts = <0 80 0x4>;
 	};
 
-	i2c3: i2c@0xffc73000 {
+	i2c3: i2c@ffc73000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "renesas,rmobile-iic";
@@ -101,6 +185,12 @@
 		interrupts = <0 81 0x4>;
 	};
 
+	pfc: pfc@fffc0000 {
+		compatible = "renesas,pfc-r8a7779";
+		reg = <0xfffc0000 0x23c>;
+		#gpio-range-cells = <3>;
+	};
+
 	thermal@ffc48000 {
 		compatible = "renesas,rcar-thermal";
 		reg = <0xffc48000 0x38>;
diff --git a/arch/arm/boot/dts/r8a7790-lager-reference.dts b/arch/arm/boot/dts/r8a7790-lager-reference.dts
new file mode 100644
index 0000000..c462ef1
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7790-lager-reference.dts
@@ -0,0 +1,45 @@
+/*
+ * Device Tree Source for the Lager board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r8a7790.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Lager";
+	compatible = "renesas,lager-reference", "renesas,r8a7790";
+
+	chosen {
+		bootargs = "console=ttySC6,115200 ignore_loglevel rw";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x80000000>;
+	};
+
+	lbsc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led6 {
+			gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+		};
+		led7 {
+			gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>;
+		};
+		led8 {
+			gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 09a84fc..203bd08 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -16,7 +16,7 @@
 	compatible = "renesas,lager", "renesas,r8a7790";
 
 	chosen {
-		bootargs = "console=ttySC6,115200 ignore_loglevel";
+		bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
 	};
 
 	memory@40000000 {
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 339d9b1..ab0582c 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -38,6 +38,78 @@
 		interrupts = <1 9 0xf04>;
 	};
 
+	gpio0: gpio@ffc40000 {
+		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
+		reg = <0 0xffc40000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 4 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 0 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio1: gpio@ffc41000 {
+		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
+		reg = <0 0xffc41000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 5 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 32 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio2: gpio@ffc42000 {
+		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
+		reg = <0 0xffc42000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 6 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 64 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio3: gpio@ffc43000 {
+		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
+		reg = <0 0xffc43000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 7 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 96 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio4: gpio@ffc44000 {
+		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
+		reg = <0 0xffc44000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 8 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 128 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	gpio5: gpio@ffc45000 {
+		compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
+		reg = <0 0xffc45000 0 0x2c>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 9 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-ranges = <&pfc 0 160 32>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <1 13 0xf08>,
@@ -54,4 +126,64 @@
 		interrupt-parent = <&gic>;
 		interrupts = <0 0 4>, <0 1 4>, <0 2 4>,	<0 3 4>;
 	};
+
+	mmcif0: mmcif@ee200000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0 0xee200000 0 0x80>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 169 0x4>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	mmcif1: mmcif@ee220000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0 0xee220000 0 0x80>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 170 0x4>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	sdhi0: sdhi@ee100000 {
+		compatible = "renesas,r8a7790-sdhi";
+		reg = <0 0xee100000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 165 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	sdhi1: sdhi@ee120000 {
+		compatible = "renesas,r8a7790-sdhi";
+		reg = <0 0xee120000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 166 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	sdhi2: sdhi@ee140000 {
+		compatible = "renesas,r8a7790-sdhi";
+		reg = <0 0xee140000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 167 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	sdhi3: sdhi@ee160000 {
+		compatible = "renesas,r8a7790-sdhi";
+		reg = <0 0xee160000 0 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 168 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	pfc: pfc@e6060000 {
+		compatible = "renesas,pfc-r8a7790";
+		reg = <0 0xe6060000 0 0x250>;
+		#gpio-range-cells = <3>;
+	};
 };
diff --git a/arch/arm/boot/dts/sh7372.dtsi b/arch/arm/boot/dts/sh7372.dtsi
index 7bf020e..249f65be2 100644
--- a/arch/arm/boot/dts/sh7372.dtsi
+++ b/arch/arm/boot/dts/sh7372.dtsi
@@ -23,4 +23,12 @@
 			reg = <0x0>;
 		};
 	};
+
+	pfc: pfc@e6050000 {
+		compatible = "renesas,pfc-sh7372";
+		reg = <0xe6050000 0x8000>,
+		      <0xe605801c 0x1c>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
 };
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
index b6f759e..2122306 100644
--- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
+++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
@@ -13,6 +13,7 @@
 
 /dts-v1/;
 /include/ "sh73a0.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "KZM-A9-GT";
@@ -32,7 +33,7 @@
 	};
 
 	chosen {
-		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200";
+		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200 rw";
 	};
 
 	memory {
@@ -58,6 +59,24 @@
 		regulator-boot-on;
 	};
 
+	vmmc_sdhi0: regulator@2 {
+	        compatible = "regulator-fixed";
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&pfc 15 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vmmc_sdhi2: regulator@3 {
+	        compatible = "regulator-fixed";
+		regulator-name = "SDHI2 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&pfc 14 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 	lan9220@10000000 {
 		compatible = "smsc,lan9220", "smsc,lan9115";
 		reg = <0x10000000 0x100>;
@@ -70,6 +89,22 @@
 		vddvario-supply = <&reg_1p8v>;
 		vdd33a-supply = <&reg_3p3v>;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		led1 {
+			gpios = <&pfc 20 GPIO_ACTIVE_LOW>;
+		};
+		led2 {
+			gpios = <&pfc 21 GPIO_ACTIVE_LOW>;
+		};
+		led3 {
+			gpios = <&pfc 22 GPIO_ACTIVE_LOW>;
+		};
+		led4 {
+			gpios = <&pfc 23 GPIO_ACTIVE_LOW>;
+		};
+	};
 };
 
 &i2c0 {
@@ -145,20 +180,71 @@
 	};
 };
 
+&i2c3 {
+	pinctrl-0 = <&i2c3_pins>;
+	pinctrl-names = "default";
+};
+
 &mmcif {
+	pinctrl-0 = <&mmcif_pins>;
+	pinctrl-names = "default";
+
 	bus-width = <8>;
 	vmmc-supply = <&reg_1p8v>;
 	status = "okay";
 };
 
+&pfc {
+	pinctrl-0 = <&scifa4_pins>;
+	pinctrl-names = "default";
+
+	i2c3_pins: i2c3 {
+		renesas,groups = "i2c3_1";
+		renesas,function = "i2c3";
+	};
+
+	mmcif_pins: mmcif {
+		mux {
+			renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
+			renesas,function = "mmc0";
+		};
+		cfg {
+			renesas,groups = "mmc0_data8_0";
+			renesas,pins = "PORT279";
+			bias-pull-up;
+		};
+	};
+
+	scifa4_pins: scifa4 {
+		renesas,groups = "scifa4_data", "scifa4_ctrl";
+		renesas,function = "scifa4";
+	};
+
+	sdhi0_pins: sdhi0 {
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp";
+		renesas,function = "sdhi0";
+	};
+
+	sdhi2_pins: sdhi2 {
+		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
+		renesas,function = "sdhi2";
+	};
+};
+
 &sdhi0 {
-	vmmc-supply = <&reg_3p3v>;
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vmmc_sdhi0>;
 	bus-width = <4>;
 	status = "okay";
 };
 
 &sdhi2 {
-	vmmc-supply = <&reg_3p3v>;
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vmmc_sdhi2>;
 	bus-width = <4>;
 	broken-cd;
 	status = "okay";
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts
index 7c4071e..0f1ca77 100644
--- a/arch/arm/boot/dts/sh73a0-kzm9g.dts
+++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts
@@ -16,7 +16,7 @@
 	compatible = "renesas,kzm9g", "renesas,sh73a0";
 
 	chosen {
-		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200";
+		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200 rw";
 	};
 
 	memory {
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index b977502..ba59a58 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -38,6 +38,12 @@
 		      <0xf0000100 0x100>;
 	};
 
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts = <0 55 4>,
+			     <0 56 4>;
+	};
+
 	irqpin0: irqpin@e6900000 {
 		compatible = "renesas,intc-irqpin";
 		#interrupt-cells = <2>;
@@ -222,4 +228,12 @@
 		cap-sd-highspeed;
 		status = "disabled";
 	};
+
+	pfc: pfc@e6050000 {
+		compatible = "renesas,pfc-sh73a0";
+		reg = <0xe6050000 0x8000>,
+		      <0xe605801c 0x1c>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
 };
diff --git a/arch/arm/boot/dts/skeleton64.dtsi b/arch/arm/boot/dts/skeleton64.dtsi
index 1599415..b5d7f36 100644
--- a/arch/arm/boot/dts/skeleton64.dtsi
+++ b/arch/arm/boot/dts/skeleton64.dtsi
@@ -9,5 +9,5 @@
 	#size-cells = <2>;
 	chosen { };
 	aliases { };
-	memory { device_type = "memory"; reg = <0 0>; };
+	memory { device_type = "memory"; reg = <0 0 0 0>; };
 };
diff --git a/arch/arm/boot/dts/stih41x.dtsi b/arch/arm/boot/dts/stih41x.dtsi
index 7321403..f5b9898 100644
--- a/arch/arm/boot/dts/stih41x.dtsi
+++ b/arch/arm/boot/dts/stih41x.dtsi
@@ -6,10 +6,12 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		cpu@0 {
+			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 		};
 		cpu@1 {
+			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
 		};
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index cb640eb..b5a42f0 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -791,7 +791,7 @@
 					regulator-boot-on;
 				};
 
-				dcdc3 {
+				tps65090_dcdc3_reg: dcdc3 {
 					regulator-name = "vdd-ao";
 					regulator-always-on;
 					regulator-boot-on;
@@ -836,6 +836,180 @@
 				};
 			};
 		};
+
+		palmas: tps65913 {
+			compatible = "ti,palmas";
+			reg = <0x58>;
+			interrupts = <0 86 IRQ_TYPE_LEVEL_LOW>;
+
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			palmas_gpio: gpio {
+				compatible = "ti,palmas-gpio";
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			pmic {
+				compatible = "ti,tps65913-pmic", "ti,palmas-pmic";
+				smps1-in-supply = <&tps65090_dcdc3_reg>;
+				smps3-in-supply = <&tps65090_dcdc3_reg>;
+				smps4-in-supply = <&tps65090_dcdc2_reg>;
+				smps7-in-supply = <&tps65090_dcdc2_reg>;
+				smps8-in-supply = <&tps65090_dcdc2_reg>;
+				smps9-in-supply = <&tps65090_dcdc2_reg>;
+				ldo1-in-supply = <&tps65090_dcdc2_reg>;
+				ldo2-in-supply = <&tps65090_dcdc2_reg>;
+				ldo3-in-supply = <&palmas_smps3_reg>;
+				ldo4-in-supply = <&tps65090_dcdc2_reg>;
+				ldo5-in-supply = <&vdd_ac_bat_reg>;
+				ldo6-in-supply = <&tps65090_dcdc2_reg>;
+				ldo7-in-supply = <&tps65090_dcdc2_reg>;
+				ldo8-in-supply = <&tps65090_dcdc3_reg>;
+				ldo9-in-supply = <&palmas_smps9_reg>;
+				ldoln-in-supply = <&tps65090_dcdc1_reg>;
+				ldousb-in-supply = <&tps65090_dcdc1_reg>;
+
+				regulators {
+					smps12 {
+						regulator-name = "vddio-ddr";
+						regulator-min-microvolt = <1350000>;
+						regulator-max-microvolt = <1350000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					palmas_smps3_reg: smps3 {
+						regulator-name = "vddio-1v8";
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					smps45 {
+						regulator-name = "vdd-core";
+						regulator-min-microvolt = <900000>;
+						regulator-max-microvolt = <1400000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					smps457 {
+						regulator-name = "vdd-core";
+						regulator-min-microvolt = <900000>;
+						regulator-max-microvolt = <1400000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					smps8 {
+						regulator-name = "avdd-pll";
+						regulator-min-microvolt = <1050000>;
+						regulator-max-microvolt = <1050000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					palmas_smps9_reg: smps9 {
+						regulator-name = "sdhci-vdd-sd-slot";
+						regulator-min-microvolt = <2800000>;
+						regulator-max-microvolt = <2800000>;
+						regulator-always-on;
+					};
+
+					ldo1 {
+						regulator-name = "avdd-cam1";
+						regulator-min-microvolt = <2800000>;
+						regulator-max-microvolt = <2800000>;
+					};
+
+					ldo2 {
+						regulator-name = "avdd-cam2";
+						regulator-min-microvolt = <2800000>;
+						regulator-max-microvolt = <2800000>;
+					};
+
+					ldo3 {
+						regulator-name = "avdd-dsi-csi";
+						regulator-min-microvolt = <1200000>;
+						regulator-max-microvolt = <1200000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					ldo4 {
+						regulator-name = "vpp-fuse";
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+					};
+
+					ldo6 {
+						regulator-name = "vdd-sensor-2v85";
+						regulator-min-microvolt = <2850000>;
+						regulator-max-microvolt = <2850000>;
+					};
+
+					ldo7 {
+						regulator-name = "vdd-af-cam1";
+						regulator-min-microvolt = <2800000>;
+						regulator-max-microvolt = <2800000>;
+					};
+
+					ldo8 {
+						regulator-name = "vdd-rtc";
+						regulator-min-microvolt = <900000>;
+						regulator-max-microvolt = <900000>;
+						regulator-always-on;
+						regulator-boot-on;
+						ti,enable-ldo8-tracking;
+					};
+
+					ldo9 {
+						regulator-name = "vddio-sdmmc-2";
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <3300000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					ldoln {
+						regulator-name = "hvdd-usb";
+						regulator-min-microvolt = <3300000>;
+						regulator-max-microvolt = <3300000>;
+					};
+
+					ldousb {
+						regulator-name = "avdd-usb";
+						regulator-min-microvolt = <3300000>;
+						regulator-max-microvolt = <3300000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					regen1 {
+						regulator-name = "rail-3v3";
+						regulator-max-microvolt = <3300000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					regen2 {
+						regulator-name = "rail-5v0";
+						regulator-max-microvolt = <5000000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+				};
+			};
+
+			rtc {
+				compatible = "ti,palmas-rtc";
+				interrupt-parent = <&palmas>;
+				interrupts = <8 0>;
+			};
+		};
 	};
 
 	spi@7000da00 {
@@ -850,6 +1024,13 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <500>;
+		nvidia,cpu-pwr-off-time = <300>;
+		nvidia,core-pwr-good-time = <641 3845>;
+		nvidia,core-pwr-off-time = <61036>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	ahub {
@@ -883,6 +1064,35 @@
 		};
 	};
 
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		home {
+			label = "Home";
+			gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+			linux,code = <102>; /* KEY_HOME */
+		};
+
+		power {
+			label = "Power";
+			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+
+		volume_down {
+			label = "Volume Down";
+			gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_LOW>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+
+		volume_up {
+			label = "Volume Up";
+			gpios = <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_LOW>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -951,6 +1161,16 @@
 			gpio = <&gpio TEGRA_GPIO(K, 1) GPIO_ACTIVE_HIGH>;
 			vin-supply = <&tps65090_dcdc1_reg>;
 		};
+
+		vdd_cam_1v8_reg: regulator@6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "vdd_cam_1v8_reg";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			enable-active-high;
+			gpio = <&palmas_gpio 6 0>;
+		};
 	};
 
 	sound {
diff --git a/arch/arm/boot/dts/tegra114-pluto.dts b/arch/arm/boot/dts/tegra114-pluto.dts
deleted file mode 100644
index d5f8d3e..0000000
--- a/arch/arm/boot/dts/tegra114-pluto.dts
+++ /dev/null
@@ -1,33 +0,0 @@
-/dts-v1/;
-
-#include "tegra114.dtsi"
-
-/ {
-	model = "NVIDIA Tegra114 Pluto evaluation board";
-	compatible = "nvidia,pluto", "nvidia,tegra114";
-
-	memory {
-		reg = <0x80000000 0x40000000>;
-	};
-
-	serial@70006300 {
-		status = "okay";
-	};
-
-	pmc {
-		nvidia,invert-interrupt;
-	};
-
-	clocks {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		clk32k_in: clock {
-			compatible = "fixed-clock";
-			reg=<0>;
-			#clock-cells = <0>;
-			clock-frequency = <32768>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
index 2fcb3f2..5592be6 100644
--- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
@@ -457,6 +457,7 @@
 	};
 
 	usb-phy@c5004000 {
+		status = "okay";
 		nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1)
 			GPIO_ACTIVE_LOW>;
 	};
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 365760b..60137f5 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -566,7 +566,6 @@
 
 	usb@c5000000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
 		dr_mode = "otg";
 	};
 
@@ -829,7 +828,7 @@
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			enable-active-high;
-			gpio = <&gpio 24 0>; /* PD0 */
+			gpio = <&gpio TEGRA_GPIO(D, 0) 0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index ed4b901..906e07f 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -312,7 +312,6 @@
 
 	usb@c5000000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb-phy@c5000000 {
@@ -411,7 +410,7 @@
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			enable-active-high;
-			gpio = <&gpio 170 0>; /* PV2 */
+			gpio = <&gpio TEGRA_GPIO(V, 2) 0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index ab67c94..a6b1b5b 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -509,7 +509,6 @@
 
 	usb@c5000000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&tca6416 0 GPIO_ACTIVE_HIGH>;
 	};
 
 	usb-phy@c5000000 {
@@ -519,7 +518,6 @@
 
 	usb@c5008000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&tca6416 1 GPIO_ACTIVE_HIGH>;
 	};
 
 	usb-phy@c5008000 {
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 9653fd8..e457083 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -477,13 +477,13 @@
 			 <&tegra_car TEGRA20_CLK_USBD>;
 		clock-names = "reg", "pll_u", "timer", "utmi-pads";
 		nvidia,has-legacy-mode;
-		hssync_start_delay = <9>;
-		idle_wait_delay = <17>;
-		elastic_limit = <16>;
-		term_range_adj = <6>;
-		xcvr_setup = <9>;
-		xcvr_lsfslew = <1>;
-		xcvr_lsrslew = <1>;
+		nvidia,hssync-start-delay = <9>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <1>;
+		nvidia,xcvr-lsrslew = <1>;
 		status = "disabled";
 	};
 
@@ -527,13 +527,13 @@
 			 <&tegra_car TEGRA20_CLK_CLK_M>,
 			 <&tegra_car TEGRA20_CLK_USBD>;
 		clock-names = "reg", "pll_u", "timer", "utmi-pads";
-		hssync_start_delay = <9>;
-		idle_wait_delay = <17>;
-		elastic_limit = <16>;
-		term_range_adj = <6>;
-		xcvr_setup = <9>;
-		xcvr_lsfslew = <2>;
-		xcvr_lsrslew = <2>;
+		nvidia,hssync-start-delay = <9>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <2>;
+		nvidia,xcvr-lsrslew = <2>;
 		status = "disabled";
 	};
 
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index f65b53d..c011b67 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -173,19 +173,6 @@
 			gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
 		};
 
-		tps62361 {
-			compatible = "ti,tps62361";
-			reg = <0x60>;
-
-			regulator-name = "tps62361-vout";
-			regulator-min-microvolt = <500000>;
-			regulator-max-microvolt = <1500000>;
-			regulator-boot-on;
-			regulator-always-on;
-			ti,vsel0-state-high;
-			ti,vsel1-state-high;
-		};
-
 		pmic: tps65911@2d {
 			compatible = "ti,tps65911";
 			reg = <0x2d>;
@@ -286,6 +273,26 @@
 				};
 			};
 		};
+
+		nct1008 {
+			compatible = "onnn,nct1008";
+			reg = <0x4c>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_LEVEL_LOW>;
+		};
+
+		tps62361 {
+			compatible = "ti,tps62361";
+			reg = <0x60>;
+
+			regulator-name = "tps62361-vout";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-boot-on;
+			regulator-always-on;
+			ti,vsel0-state-high;
+			ti,vsel1-state-high;
+		};
 	};
 
 	spi@7000da00 {
diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/wm8850-w70v2.dts
index 90e913f..7a563d2 100644
--- a/arch/arm/boot/dts/wm8850-w70v2.dts
+++ b/arch/arm/boot/dts/wm8850-w70v2.dts
@@ -11,13 +11,14 @@
 
 /dts-v1/;
 /include/ "wm8850.dtsi"
+#include <dt-bindings/pwm/pwm.h>
 
 / {
 	model = "Wondermedia WM8850-W70v2 Tablet";
 
 	backlight {
 		compatible = "pwm-backlight";
-		pwms = <&pwm 0 50000 1>;	/* duty inverted */
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
 
 		brightness-levels = <0 40 60 80 100 130 190 255>;
 		default-brightness-level = <5>;
diff --git a/arch/arm/configs/ag5evm_defconfig b/arch/arm/configs/ag5evm_defconfig
deleted file mode 100644
index 212ead3..0000000
--- a/arch/arm/configs/ag5evm_defconfig
+++ /dev/null
@@ -1,83 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
-CONFIG_ARCH_SH73A0=y
-CONFIG_MACH_AG5EVM=y
-CONFIG_MEMORY_SIZE=0x10000000
-CONFIG_CPU_BPREDICT_DISABLE=y
-CONFIG_ARM_ERRATA_430973=y
-CONFIG_ARM_ERRATA_458693=y
-CONFIG_NO_HZ=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_HIGHMEM=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=tty0 console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
-CONFIG_CMDLINE_FORCE=y
-CONFIG_KEXEC=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM=y
-# CONFIG_SUSPEND is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_BLK_DEV is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_SPARSEKMAP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=9
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_SH_MOBILE=y
-# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-CONFIG_FB=y
-CONFIG_FB_SH_MOBILE_LCDC=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_FTRACE is not set
diff --git a/arch/arm/configs/ape6evm_defconfig b/arch/arm/configs/ape6evm_defconfig
index dab5a7d..1ce3994 100644
--- a/arch/arm/configs/ape6evm_defconfig
+++ b/arch/arm/configs/ape6evm_defconfig
@@ -54,7 +54,8 @@ CONFIG_NETDEVICES=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 # CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 CONFIG_SERIAL_NONSTANDARD=y
@@ -71,6 +72,9 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
deleted file mode 100644
index bffe68e..0000000
--- a/arch/arm/configs/exynos4_defconfig
+++ /dev/null
@@ -1,68 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_EXYNOS=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
-CONFIG_MACH_SMDKC210=y
-CONFIG_MACH_ARMLEX4210=y
-CONFIG_MACH_UNIVERSAL_C210=y
-CONFIG_MACH_NURI=y
-CONFIG_MACH_ORIGEN=y
-CONFIG_MACH_SMDK4412=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CRAMFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/exynos5440_defconfig b/arch/arm/configs/exynos5440_defconfig
new file mode 100644
index 0000000..53daf04
--- /dev/null
+++ b/arch/arm/configs/exynos5440_defconfig
@@ -0,0 +1,138 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PERF_EVENTS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_EXYNOS=y
+# CONFIG_ARCH_EXYNOS4 is not set
+CONFIG_ARCH_EXYNOS5=y
+# CONFIG_SOC_EXYNOS5250 is not set
+CONFIG_ARM_LPAE=y
+CONFIG_PCI=y
+CONFIG_PCI_EXYNOS=y
+CONFIG_SMP=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CMDLINE="root=/dev/sda2 rw rootwait ignore_loglevel early_printk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_APM_EMULATION=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IPV6=y
+CONFIG_RFKILL_REGULATOR=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=10240
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+# CONFIG_ATA_SFF is not set
+CONFIG_NETDEVICES=y
+CONFIG_SMSC911X=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_DA=y
+CONFIG_MARVELL_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_S3C2410=y
+CONFIG_SPI=y
+CONFIG_SPI_S3C64XX=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_EXYNOS_THERMAL_CORE=y
+CONFIG_WATCHDOG=y
+CONFIG_S3C2410_WATCHDOG=y
+CONFIG_MFD_TPS65090=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRC_CCITT=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index f07a847..6cc94a7 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -17,16 +16,18 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
 CONFIG_ARCH_MULTI_V4T=y
 CONFIG_ARCH_MULTI_V5=y
 # CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_MXC=y
+CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_ARCH_MX1ADS=y
 CONFIG_MACH_SCB9328=y
 CONFIG_MACH_APF9328=y
 CONFIG_MACH_MX21ADS=y
 CONFIG_MACH_MX25_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX25SD=y
+CONFIG_MACH_IMX25_DT=y
 CONFIG_MACH_MX27ADS=y
 CONFIG_MACH_PCM038=y
 CONFIG_MACH_CPUIMX27=y
@@ -39,8 +40,6 @@ CONFIG_MACH_PCA100=y
 CONFIG_MACH_MXT_TD60=y
 CONFIG_MACH_IMX27IPCAM=y
 CONFIG_MACH_IMX27_DT=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -67,7 +66,6 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
@@ -123,24 +121,20 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
-CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX2=y
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_CODA=y
+CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_FB=y
 CONFIG_FB_IMX=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
@@ -152,12 +146,10 @@ CONFIG_SND_SOC_MX27VIS_AIC32X4=y
 CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
-CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB_HID=m
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -198,3 +190,5 @@ CONFIG_NLS_CODEPAGE_850=m
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 06686e7..577f054 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_KERNEL_LZO=y
 CONFIG_SYSVIPC=y
@@ -17,10 +16,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
 CONFIG_ARCH_MULTI_V6=y
-CONFIG_ARCH_MULTI_V7=y
-CONFIG_MACH_IMX31_DT=y
+CONFIG_ARCH_MXC=y
 CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
@@ -30,6 +27,7 @@ CONFIG_MACH_MX31MOBOARD=y
 CONFIG_MACH_QONG=y
 CONFIG_MACH_ARMADILLO5X0=y
 CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_IMX31_DT=y
 CONFIG_MACH_PCM043=y
 CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_VPR200=y
@@ -39,7 +37,6 @@ CONFIG_SOC_IMX53=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_SOC_IMX6SL=y
 CONFIG_SOC_VF610=y
-CONFIG_MXC_PWM=y
 CONFIG_SMP=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -64,20 +61,24 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_NETFILTER=y
-# CONFIG_WIRELESS is not set
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
+CONFIG_IMX_WEIM=y
 CONFIG_CONNECTOR=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_JEDECPROBE=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SST25L=y
@@ -88,6 +89,7 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SRAM=y
 CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
 # CONFIG_SCSI_PROC_FS is not set
@@ -98,10 +100,11 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_IMX=y
 CONFIG_PATA_IMX=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
 CONFIG_CS89x0=y
 CONFIG_CS89x0_PLATFORM=y
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -115,7 +118,7 @@ CONFIG_SMC91X=y
 CONFIG_SMC911X=y
 CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_WLAN is not set
+CONFIG_BRCMFMAC=m
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
@@ -124,6 +127,7 @@ CONFIG_KEYBOARD_IMX=y
 CONFIG_MOUSE_PS2=m
 CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_EGALAX=y
 CONFIG_TOUCHSCREEN_MC13783=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
@@ -133,13 +137,13 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MXC_RNGA=y
-CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_ALGOBIT=m
 CONFIG_I2C_ALGOPCF=m
 CONFIG_I2C_ALGOPCA=m
 CONFIG_I2C_IMX=y
@@ -155,30 +159,26 @@ CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_MFD_MC13XXX_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_DA9052=y
 CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_DA9052=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
+CONFIG_VIDEO_MX3=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_CODA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_DRM=y
-CONFIG_VIDEO_MX3=y
-CONFIG_FB=y
-CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
@@ -188,15 +188,15 @@ CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
 CONFIG_SND_SOC_IMX_WM8962=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
-CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_PHY=y
+CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_MXS_PHY=y
-CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -213,9 +213,10 @@ CONFIG_IMX_SDMA=y
 CONFIG_MXS_DMA=y
 CONFIG_STAGING=y
 CONFIG_DRM_IMX=y
-CONFIG_DRM_IMX_TVE=y
 CONFIG_DRM_IMX_FB_HELPER=y
 CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
+CONFIG_DRM_IMX_TVE=y
+CONFIG_DRM_IMX_LDB=y
 CONFIG_DRM_IMX_IPUV3_CORE=y
 CONFIG_DRM_IMX_IPUV3=y
 CONFIG_COMMON_CLK_DEBUG=y
@@ -269,3 +270,6 @@ CONFIG_CRC_CCITT=m
 CONFIG_CRC_T10DIF=y
 CONFIG_CRC7=m
 CONFIG_LIBCRC32C=m
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 0f2aa61..19e0f2f 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -29,30 +29,7 @@ CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_T5325=y
 CONFIG_MACH_TS219=y
 CONFIG_MACH_TS41X=y
-CONFIG_MACH_CLOUDBOX_DT=y
-CONFIG_MACH_DB88F628X_BP_DT=y
 CONFIG_MACH_DLINK_KIRKWOOD_DT=y
-CONFIG_MACH_DOCKSTAR_DT=y
-CONFIG_MACH_DREAMPLUG_DT=y
-CONFIG_MACH_GOFLEXNET_DT=y
-CONFIG_MACH_GURUPLUG_DT=y
-CONFIG_MACH_IB62X0_DT=y
-CONFIG_MACH_ICONNECT_DT=y
-CONFIG_MACH_INETSPACE_V2_DT=y
-CONFIG_MACH_IOMEGA_IX2_200_DT=y
-CONFIG_MACH_KM_KIRKWOOD_DT=y
-CONFIG_MACH_LSXL_DT=y
-CONFIG_MACH_MPLCEC4_DT=y
-CONFIG_MACH_NETSPACE_LITE_V2_DT=y
-CONFIG_MACH_NETSPACE_MAX_V2_DT=y
-CONFIG_MACH_NETSPACE_MINI_V2_DT=y
-CONFIG_MACH_NETSPACE_V2_DT=y
-CONFIG_MACH_NSA310_DT=y
-CONFIG_MACH_OPENBLOCKS_A6_DT=y
-CONFIG_MACH_READYNAS_DT=y
-CONFIG_MACH_SHEEVAPLUG_DT=y
-CONFIG_MACH_TOPKICK_DT=y
-CONFIG_MACH_TS219_DT=y
 # CONFIG_CPU_FEROCEON_OLD_ID is not set
 CONFIG_PCI_MVEBU=y
 CONFIG_PREEMPT=y
@@ -92,6 +69,7 @@ CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
+CONFIG_EEPROM_AT24=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -103,6 +81,7 @@ CONFIG_NETDEVICES=y
 CONFIG_MII=y
 CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_MV643XX_ETH=y
+CONFIG_R8169=y
 CONFIG_MARVELL_PHY=y
 CONFIG_LIBERTAS=y
 CONFIG_LIBERTAS_SDIO=y
@@ -123,7 +102,10 @@ CONFIG_I2C_MV64XXX=y
 CONFIG_SPI=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_LM63=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_LM85=y
 CONFIG_THERMAL=y
 CONFIG_KIRKWOOD_THERMAL=y
 CONFIG_WATCHDOG=y
@@ -164,6 +146,8 @@ CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_S35390A=y
 CONFIG_RTC_DRV_MV=y
 CONFIG_DMADEVICES=y
@@ -171,6 +155,7 @@ CONFIG_MV_XOR=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
diff --git a/arch/arm/configs/kota2_defconfig b/arch/arm/configs/kota2_defconfig
deleted file mode 100644
index 57ad3d4..0000000
--- a/arch/arm/configs/kota2_defconfig
+++ /dev/null
@@ -1,121 +0,0 @@
-# CONFIG_ARM_PATCH_PHYS_VIRT is not set
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_CGROUPS=y
-CONFIG_CPUSETS=y
-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_SYSCTL_SYSCALL=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
-CONFIG_KEYBOARD_GPIO_POLLED=y
-CONFIG_ARCH_SH73A0=y
-CONFIG_MACH_KOTA2=y
-CONFIG_MEMORY_SIZE=0x1e000000
-# CONFIG_SH_TIMER_TMU is not set
-# CONFIG_SWP_EMULATE is not set
-CONFIG_CPU_BPREDICT_DISABLE=y
-CONFIG_ARM_ERRATA_460075=y
-CONFIG_ARM_ERRATA_742230=y
-CONFIG_ARM_ERRATA_742231=y
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_ARM_ERRATA_720789=y
-CONFIG_PL310_ERRATA_727915=y
-CONFIG_ARM_ERRATA_743622=y
-CONFIG_ARM_ERRATA_751472=y
-CONFIG_PL310_ERRATA_753970=y
-CONFIG_ARM_ERRATA_754322=y
-CONFIG_PL310_ERRATA_769419=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_HIGHMEM=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
-CONFIG_CMDLINE_FORCE=y
-CONFIG_KEXEC=y
-CONFIG_CPU_IDLE=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_CFG80211=y
-CONFIG_WIRELESS_EXT_SYSFS=y
-CONFIG_MAC80211=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_BLK_DEV is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-CONFIG_SMSC911X=y
-# CONFIG_NET_VENDOR_STMICRO is not set
-CONFIG_B43=y
-CONFIG_B43_PHY_N=y
-CONFIG_B43_DEBUG=y
-CONFIG_INPUT_SPARSEKMAP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_KEYBOARD_SH_KEYSC=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=9
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C_SH_MOBILE=y
-# CONFIG_HWMON is not set
-CONFIG_BCMA=y
-CONFIG_BCMA_DEBUG=y
-CONFIG_FB=y
-CONFIG_FB_SH_MOBILE_LCDC=y
-CONFIG_LCD_PLATFORM=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_SDHI=y
-CONFIG_MMC_SH_MMCIF=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_RENESAS_TPU=y
-CONFIG_LEDS_TRIGGERS=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_INFO_REDUCED=y
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig
new file mode 100644
index 0000000..e777ef2
--- /dev/null
+++ b/arch/arm/configs/lager_defconfig
@@ -0,0 +1,120 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_R8A7790=y
+CONFIG_MACH_LAGER=y
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_458693=y
+CONFIG_ARM_ERRATA_460075=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_KEXEC=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CORE is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_SH_ETH=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=10
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_SH_MOBILE=y
+CONFIG_GPIO_SH_PFC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_RCAR=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_RCAR_THERMAL=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
+CONFIG_MMC_SH_MMCIF=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_SH_DMAE=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index 494e70a..82e4040 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -29,6 +29,7 @@ CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
 CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_KEXEC=y
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index 731814e..594d706 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -39,6 +39,8 @@ CONFIG_MVNETA=y
 CONFIG_MARVELL_PHY=y
 CONFIG_MWIFIEX=y
 CONFIG_MWIFIEX_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_I2C=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 1d6d8fb..4555c02 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -27,7 +26,6 @@ CONFIG_ARCH_MXS=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
-CONFIG_AUTO_ZRELADDR=y
 CONFIG_FPE_NWFPE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -43,8 +41,6 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_CAN=m
-CONFIG_CAN_RAW=m
-CONFIG_CAN_BCM=m
 CONFIG_CAN_FLEXCAN=m
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
@@ -52,7 +48,6 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
@@ -67,12 +62,12 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_ENC28J60=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_NET_SMSC95XX=y
 CONFIG_SMSC_PHY=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_REALTEK_PHY=y
 CONFIG_MICREL_PHY=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -110,7 +105,6 @@ CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
@@ -119,9 +113,9 @@ CONFIG_SND_MXS_SOC=y
 CONFIG_SND_SOC_MXS_SGTL5000=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_STORAGE=y
 CONFIG_USB_PHY=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_MMC=y
@@ -143,9 +137,9 @@ CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
 CONFIG_STAGING=y
 CONFIG_MXS_LRADC=y
-CONFIG_IIO_SYSFS_TRIGGER=y
 CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_IIO=y
+CONFIG_IIO_SYSFS_TRIGGER=y
 CONFIG_PWM=y
 CONFIG_PWM_MXS=y
 CONFIG_EXT2_FS=y
@@ -173,14 +167,14 @@ CONFIG_NLS_CODEPAGE_850=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=y
 CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
 CONFIG_FRAME_WARN=2048
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_TIMER_STATS=y
 CONFIG_PROVE_LOCKING=y
-CONFIG_DEBUG_INFO=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_STRICT_DEVMEM=y
 CONFIG_DEBUG_USER=y
@@ -188,3 +182,4 @@ CONFIG_DEBUG_USER=y
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_ITU_T=m
 CONFIG_CRC7=m
+CONFIG_FONTS=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 1effb43..36ad70c 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -1,3 +1,4 @@
+CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
@@ -91,6 +92,7 @@ CONFIG_ISL29003=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
@@ -105,6 +107,7 @@ CONFIG_RT2800USB=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_TEGRA=y
+CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
 # CONFIG_LEGACY_PTYS is not set
diff --git a/arch/arm/include/asm/dma-contiguous.h b/arch/arm/include/asm/dma-contiguous.h
index 3ed37b4..e072bb2 100644
--- a/arch/arm/include/asm/dma-contiguous.h
+++ b/arch/arm/include/asm/dma-contiguous.h
@@ -2,7 +2,7 @@
 #define ASMARM_DMA_CONTIGUOUS_H
 
 #ifdef __KERNEL__
-#ifdef CONFIG_CMA
+#ifdef CONFIG_DMA_CMA
 
 #include <linux/types.h>
 #include <asm-generic/dma-contiguous.h>
diff --git a/arch/arm/include/asm/hardware/debug-8250.S b/arch/arm/include/asm/hardware/debug-8250.S
deleted file mode 100644
index 22c6892..0000000
--- a/arch/arm/include/asm/hardware/debug-8250.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * arch/arm/include/asm/hardware/debug-8250.S
- *
- *  Copyright (C) 1994-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/serial_reg.h>
-
-		.macro	senduart,rd,rx
-		strb	\rd, [\rx, #UART_TX << UART_SHIFT]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldrb	\rd, [\rx, #UART_LSR << UART_SHIFT]
-		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
-		bne	1002b
-		.endm
-
-		.macro	waituart,rd,rx
-#ifdef FLOW_CONTROL
-1001:		ldrb	\rd, [\rx, #UART_MSR << UART_SHIFT]
-		tst	\rd, #UART_MSR_CTS
-		beq	1001b
-#endif
-		.endm
diff --git a/arch/arm/include/asm/hardware/debug-pl01x.S b/arch/arm/include/asm/hardware/debug-pl01x.S
deleted file mode 100644
index f9fd083..0000000
--- a/arch/arm/include/asm/hardware/debug-pl01x.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/* arch/arm/include/asm/hardware/debug-pl01x.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-#include <linux/amba/serial.h>
-
-		.macro	senduart,rd,rx
-		strb	\rd, [\rx, #UART01x_DR]
-		.endm
-
-		.macro	waituart,rd,rx
-1001:		ldr	\rd, [\rx, #UART01x_FR]
-		tst	\rd, #UART01x_FR_TXFF
-		bne	1001b
-		.endm
-
-		.macro	busyuart,rd,rx
-1001:		ldr	\rd, [\rx, #UART01x_FR]
-		tst	\rd, #UART01x_FR_BUSY
-		bne	1001b
-		.endm
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
deleted file mode 100644
index f77ffc1..0000000
--- a/arch/arm/include/asm/localtimer.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  arch/arm/include/asm/localtimer.h
- *
- *  Copyright (C) 2004-2005 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_ARM_LOCALTIMER_H
-#define __ASM_ARM_LOCALTIMER_H
-
-#include <linux/errno.h>
-
-struct clock_event_device;
-
-struct local_timer_ops {
-	int  (*setup)(struct clock_event_device *);
-	void (*stop)(struct clock_event_device *);
-};
-
-#ifdef CONFIG_LOCAL_TIMERS
-/*
- * Register a local timer driver
- */
-int local_timer_register(struct local_timer_ops *);
-#else
-static inline int local_timer_register(struct local_timer_ops *ops)
-{
-	return -ENXIO;
-}
-#endif
-
-#endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 441efc4..69b879a 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -65,12 +65,12 @@ struct machine_desc {
 /*
  * Current machine - only accessible during boot.
  */
-extern struct machine_desc *machine_desc;
+extern const struct machine_desc *machine_desc;
 
 /*
  * Machine type table - also only accessible during boot
  */
-extern struct machine_desc __arch_info_begin[], __arch_info_end[];
+extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
 #define for_each_machine_desc(p)			\
 	for (p = __arch_info_begin; p < __arch_info_end; p++)
 
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index a1c90d7..454d642 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -36,6 +36,8 @@ struct hw_pci {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void		(*add_bus)(struct pci_bus *bus);
+	void		(*remove_bus)(struct pci_bus *bus);
 };
 
 /*
@@ -63,6 +65,8 @@ struct pci_sys_data {
 					  resource_size_t start,
 					  resource_size_t size,
 					  resource_size_t align);
+	void		(*add_bus)(struct pci_bus *bus);
+	void		(*remove_bus)(struct pci_bus *bus);
 	void		*private_data;	/* platform controller private data	*/
 };
 
diff --git a/arch/arm/include/asm/memblock.h b/arch/arm/include/asm/memblock.h
index 00ca5f9..c2f5102 100644
--- a/arch/arm/include/asm/memblock.h
+++ b/arch/arm/include/asm/memblock.h
@@ -4,8 +4,7 @@
 struct meminfo;
 struct machine_desc;
 
-extern void arm_memblock_init(struct meminfo *, struct machine_desc *);
-
+void arm_memblock_init(struct meminfo *, const struct machine_desc *);
 phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align);
 
 #endif
diff --git a/arch/arm/include/asm/neon.h b/arch/arm/include/asm/neon.h
new file mode 100644
index 0000000..8f730fe
--- /dev/null
+++ b/arch/arm/include/asm/neon.h
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/include/asm/neon.h
+ *
+ * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/hwcap.h>
+
+#define cpu_has_neon()		(!!(elf_hwcap & HWCAP_NEON))
+
+#ifdef __ARM_NEON__
+
+/*
+ * If you are affected by the BUILD_BUG below, it probably means that you are
+ * using NEON code /and/ calling the kernel_neon_begin() function from the same
+ * compilation unit. To prevent issues that may arise from GCC reordering or
+ * generating(1) NEON instructions outside of these begin/end functions, the
+ * only supported way of using NEON code in the kernel is by isolating it in a
+ * separate compilation unit, and calling it from another unit from inside a
+ * kernel_neon_begin/kernel_neon_end pair.
+ *
+ * (1) Current GCC (4.7) might generate NEON instructions at O3 level if
+ *     -mpfu=neon is set.
+ */
+
+#define kernel_neon_begin() \
+	BUILD_BUG_ON_MSG(1, "kernel_neon_begin() called from NEON code")
+
+#else
+void kernel_neon_begin(void);
+#endif
+void kernel_neon_end(void);
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index a219227..4a2985e 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -15,13 +15,13 @@
 
 #ifdef CONFIG_OF
 
-extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
+extern const struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 extern void __init arm_dt_init_cpu_maps(void);
 
 #else /* CONFIG_OF */
 
-static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
+static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
 {
 	return NULL;
 }
diff --git a/arch/arm/include/asm/xor.h b/arch/arm/include/asm/xor.h
index 7604673..4ffb26d 100644
--- a/arch/arm/include/asm/xor.h
+++ b/arch/arm/include/asm/xor.h
@@ -7,7 +7,10 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/hardirq.h>
 #include <asm-generic/xor.h>
+#include <asm/hwcap.h>
+#include <asm/neon.h>
 
 #define __XOR(a1, a2) a1 ^= a2
 
@@ -138,4 +141,74 @@ static struct xor_block_template xor_block_arm4regs = {
 		xor_speed(&xor_block_arm4regs);	\
 		xor_speed(&xor_block_8regs);	\
 		xor_speed(&xor_block_32regs);	\
+		NEON_TEMPLATES;			\
 	} while (0)
+
+#ifdef CONFIG_KERNEL_MODE_NEON
+
+extern struct xor_block_template const xor_block_neon_inner;
+
+static void
+xor_neon_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+	if (in_interrupt()) {
+		xor_arm4regs_2(bytes, p1, p2);
+	} else {
+		kernel_neon_begin();
+		xor_block_neon_inner.do_2(bytes, p1, p2);
+		kernel_neon_end();
+	}
+}
+
+static void
+xor_neon_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3)
+{
+	if (in_interrupt()) {
+		xor_arm4regs_3(bytes, p1, p2, p3);
+	} else {
+		kernel_neon_begin();
+		xor_block_neon_inner.do_3(bytes, p1, p2, p3);
+		kernel_neon_end();
+	}
+}
+
+static void
+xor_neon_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3, unsigned long *p4)
+{
+	if (in_interrupt()) {
+		xor_arm4regs_4(bytes, p1, p2, p3, p4);
+	} else {
+		kernel_neon_begin();
+		xor_block_neon_inner.do_4(bytes, p1, p2, p3, p4);
+		kernel_neon_end();
+	}
+}
+
+static void
+xor_neon_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+	if (in_interrupt()) {
+		xor_arm4regs_5(bytes, p1, p2, p3, p4, p5);
+	} else {
+		kernel_neon_begin();
+		xor_block_neon_inner.do_5(bytes, p1, p2, p3, p4, p5);
+		kernel_neon_end();
+	}
+}
+
+static struct xor_block_template xor_block_neon = {
+	.name	= "neon",
+	.do_2	= xor_neon_2,
+	.do_3	= xor_neon_3,
+	.do_4	= xor_neon_4,
+	.do_5	= xor_neon_5
+};
+
+#define NEON_TEMPLATES	\
+	do { if (cpu_has_neon()) xor_speed(&xor_block_neon); } while (0)
+#else
+#define NEON_TEMPLATES
+#endif
diff --git a/arch/arm/include/debug/8250.S b/arch/arm/include/debug/8250.S
new file mode 100644
index 0000000..7a2baf9
--- /dev/null
+++ b/arch/arm/include/debug/8250.S
@@ -0,0 +1,54 @@
+/*
+ * arch/arm/include/debug/8250.S
+ *
+ *  Copyright (C) 1994-2013 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/serial_reg.h>
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, =CONFIG_DEBUG_UART_PHYS
+		ldr	\rv, =CONFIG_DEBUG_UART_VIRT
+		.endm
+
+#ifdef CONFIG_DEBUG_UART_8250_WORD
+		.macro	store, rd, rx:vararg
+		str	\rd, \rx
+		.endm
+
+		.macro	load, rd, rx:vararg
+		ldr	\rd, \rx
+		.endm
+#else
+		.macro	store, rd, rx:vararg
+		strb	\rd, \rx
+		.endm
+
+		.macro	load, rd, rx:vararg
+		ldrb	\rd, \rx
+		.endm
+#endif
+
+#define UART_SHIFT CONFIG_DEBUG_UART_8250_SHIFT
+
+		.macro	senduart,rd,rx
+		store	\rd, [\rx, #UART_TX << UART_SHIFT]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		load	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+#ifdef CONFIG_DEBUG_UART_8250_FLOW_CONTROL
+1001:		load	\rd, [\rx, #UART_MSR << UART_SHIFT]
+		tst	\rd, #UART_MSR_CTS
+		beq	1001b
+#endif
+		.endm
diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S
deleted file mode 100644
index 8db01ee..0000000
--- a/arch/arm/include/debug/8250_32.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
- * accesses to the 8250.
- */
-
-#include <linux/serial_reg.h>
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #UART_TX << UART_SHIFT]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
-		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
-		bne	1002b
-		.endm
-
-		/* The UART's don't have any flow control IO's wired up. */
-		.macro	waituart,rd,rx
-		.endm
diff --git a/arch/arm/include/debug/bcm2835.S b/arch/arm/include/debug/bcm2835.S
deleted file mode 100644
index aed9199..0000000
--- a/arch/arm/include/debug/bcm2835.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Debugging macro include header
- *
- * Copyright (C) 2010 Broadcom
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#define BCM2835_DEBUG_PHYS 0x20201000
-#define BCM2835_DEBUG_VIRT 0xf0201000
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =BCM2835_DEBUG_PHYS
-	ldr	\rv, =BCM2835_DEBUG_VIRT
-	.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/cns3xxx.S b/arch/arm/include/debug/cns3xxx.S
deleted file mode 100644
index d04c150..0000000
--- a/arch/arm/include/debug/cns3xxx.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Debugging macro include header
- *
- * Copyright 1994-1999 Russell King
- * Copyright 2008 Cavium Networks
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-		.macro	addruart,rp,rv,tmp
-		mov	\rp, #0x00009000
-		orr	\rv, \rp, #0xf0000000	@ virtual base
-		orr	\rp, \rp, #0x10000000
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/highbank.S b/arch/arm/include/debug/highbank.S
deleted file mode 100644
index 8cad432..0000000
--- a/arch/arm/include/debug/highbank.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-		.macro	addruart,rp,rv,tmp
-		ldr	\rv, =0xfee36000
-		ldr	\rp, =0xfff36000
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/keystone.S b/arch/arm/include/debug/keystone.S
deleted file mode 100644
index 9aef9ba..0000000
--- a/arch/arm/include/debug/keystone.S
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Early serial debug output macro for Keystone SOCs
- *
- * Copyright 2013 Texas Instruments, Inc.
- *	Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * Based on RMKs low level debug code.
- *  Copyright (C) 1994-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/serial_reg.h>
-
-#define UART_SHIFT 2
-#if defined(CONFIG_DEBUG_KEYSTONE_UART0)
-#define UART_PHYS		0x02530c00
-#define UART_VIRT		0xfeb30c00
-#elif defined(CONFIG_DEBUG_KEYSTONE_UART1)
-#define UART_PHYS		0x02531000
-#define UART_VIRT		0xfeb31000
-#endif
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rv, =UART_VIRT			@ physical base address
-	ldr	\rp, =UART_PHYS			@ virtual base address
-	.endm
-
-	.macro	senduart,rd,rx
-	str	\rd, [\rx, #UART_TX << UART_SHIFT]
-	.endm
-
-	.macro	busyuart,rd,rx
-1002:	ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
-	and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-	teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
-	bne	1002b
-	.endm
-
-	.macro	waituart,rd,rx
-	.endm
diff --git a/arch/arm/include/debug/msm.S b/arch/arm/include/debug/msm.S
new file mode 100644
index 0000000..9166e1b
--- /dev/null
+++ b/arch/arm/include/debug/msm.S
@@ -0,0 +1,93 @@
+/*
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_QSD8X50)
+#define MSM_UART1_PHYS        0xA9A00000
+#define MSM_UART2_PHYS        0xA9B00000
+#define MSM_UART3_PHYS        0xA9C00000
+#elif defined(CONFIG_ARCH_MSM7X30)
+#define MSM_UART1_PHYS        0xACA00000
+#define MSM_UART2_PHYS        0xACB00000
+#define MSM_UART3_PHYS        0xACC00000
+#endif
+
+#if defined(CONFIG_DEBUG_MSM_UART1)
+#define MSM_DEBUG_UART_BASE	0xE1000000
+#define MSM_DEBUG_UART_PHYS	MSM_UART1_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART2)
+#define MSM_DEBUG_UART_BASE	0xE1000000
+#define MSM_DEBUG_UART_PHYS	MSM_UART2_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART3)
+#define MSM_DEBUG_UART_BASE	0xE1000000
+#define MSM_DEBUG_UART_PHYS	MSM_UART3_PHYS
+#endif
+
+#ifdef CONFIG_DEBUG_MSM8660_UART
+#define MSM_DEBUG_UART_BASE	0xF0040000
+#define MSM_DEBUG_UART_PHYS	0x19C40000
+#endif
+
+#ifdef CONFIG_DEBUG_MSM8960_UART
+#define MSM_DEBUG_UART_BASE	0xF0040000
+#define MSM_DEBUG_UART_PHYS	0x16440000
+#endif
+
+	.macro	addruart, rp, rv, tmp
+#ifdef MSM_DEBUG_UART_PHYS
+	ldr	\rp, =MSM_DEBUG_UART_PHYS
+	ldr	\rv, =MSM_DEBUG_UART_BASE
+#endif
+	.endm
+
+	.macro	senduart, rd, rx
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
+	@ Write the 1 character to UARTDM_TF
+	str	\rd, [\rx, #0x70]
+#else
+	str	\rd, [\rx, #0x0C]
+#endif
+	.endm
+
+	.macro	waituart, rd, rx
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
+	@ check for TX_EMT in UARTDM_SR
+	ldr	\rd, [\rx, #0x08]
+	tst	\rd, #0x08
+	bne	1002f
+	@ wait for TXREADY in UARTDM_ISR
+1001:	ldr	\rd, [\rx, #0x14]
+	tst	\rd, #0x80
+	beq 	1001b
+1002:
+	@ Clear TX_READY by writing to the UARTDM_CR register
+	mov	\rd, #0x300
+	str	\rd, [\rx, #0x10]
+	@ Write 0x1 to NCF register
+	mov 	\rd, #0x1
+	str	\rd, [\rx, #0x40]
+	@ UARTDM reg. Read to induce delay
+	ldr	\rd, [\rx, #0x08]
+#else
+	@ wait for TX_READY
+1001:	ldr	\rd, [\rx, #0x08]
+	tst	\rd, #0x04
+	beq	1001b
+#endif
+	.endm
+
+	.macro	busyuart, rd, rx
+	.endm
diff --git a/arch/arm/include/debug/mvebu.S b/arch/arm/include/debug/mvebu.S
deleted file mode 100644
index 6517311..0000000
--- a/arch/arm/include/debug/mvebu.S
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Early serial output macro for Marvell  SoC
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- * Gregory Clement <gregory.clement@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_DEBUG_MVEBU_UART_ALTERNATE
-#define ARMADA_370_XP_REGS_PHYS_BASE	0xf1000000
-#else
-#define ARMADA_370_XP_REGS_PHYS_BASE	0xd0000000
-#endif
-
-#define ARMADA_370_XP_REGS_VIRT_BASE	0xfec00000
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =ARMADA_370_XP_REGS_PHYS_BASE
-	ldr	\rv, =ARMADA_370_XP_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/include/debug/mxs.S b/arch/arm/include/debug/mxs.S
deleted file mode 100644
index d869515..0000000
--- a/arch/arm/include/debug/mxs.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/* arch/arm/mach-mxs/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifdef CONFIG_DEBUG_IMX23_UART
-#define UART_PADDR	0x80070000
-#elif defined (CONFIG_DEBUG_IMX28_UART)
-#define UART_PADDR	0x80074000
-#endif
-
-#define UART_VADDR	0xfe100000
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rp, =UART_PADDR	@ physical
-		ldr	\rv, =UART_VADDR	@ virtual
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/nomadik.S b/arch/arm/include/debug/nomadik.S
deleted file mode 100644
index 7354179..0000000
--- a/arch/arm/include/debug/nomadik.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x00100000
-		add	\rp, \rp, #0x000fb000
-		add	\rv, \rp, #0xf0000000	@ virtual base
-		add	\rp, \rp, #0x10000000	@ physical base address
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/nspire.S b/arch/arm/include/debug/nspire.S
deleted file mode 100644
index 886fd27..0000000
--- a/arch/arm/include/debug/nspire.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *	linux/arch/arm/include/debug/nspire.S
- *
- *	Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- */
-
-#define NSPIRE_EARLY_UART_PHYS_BASE	   0x90020000
-#define NSPIRE_EARLY_UART_VIRT_BASE	   0xfee20000
-
-.macro	addruart, rp, rv, tmp
-	ldr \rp, =(NSPIRE_EARLY_UART_PHYS_BASE)		@ physical base address
-	ldr \rv, =(NSPIRE_EARLY_UART_VIRT_BASE)		@ virtual base address
-.endm
-
-
-#ifdef CONFIG_DEBUG_NSPIRE_CX_UART
-#include <asm/hardware/debug-pl01x.S>
-#endif
-
-#ifdef CONFIG_DEBUG_NSPIRE_CLASSIC_UART
-#define UART_SHIFT 2
-#include <asm/hardware/debug-8250.S>
-#endif
diff --git a/arch/arm/include/debug/picoxcell.S b/arch/arm/include/debug/picoxcell.S
deleted file mode 100644
index bc1f07c..0000000
--- a/arch/arm/include/debug/picoxcell.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#define UART_SHIFT 2
-#define PICOXCELL_UART1_BASE		0x80230000
-#define PHYS_TO_IO(x)			(((x) & 0x00ffffff) | 0xfe000000)
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
-		ldr	\rp, =PICOXCELL_UART1_BASE
-		.endm
-
-#include "8250_32.S"
diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
new file mode 100644
index 0000000..37c6895b
--- /dev/null
+++ b/arch/arm/include/debug/pl01x.S
@@ -0,0 +1,36 @@
+/* arch/arm/include/debug/pl01x.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+#include <linux/amba/serial.h>
+
+#ifdef CONFIG_DEBUG_UART_PHYS
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, =CONFIG_DEBUG_UART_PHYS
+		ldr	\rv, =CONFIG_DEBUG_UART_VIRT
+		.endm
+#endif
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx, #UART01x_DR]
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #UART01x_FR]
+		tst	\rd, #UART01x_FR_TXFF
+		bne	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #UART01x_FR]
+		tst	\rd, #UART01x_FR_BUSY
+		bne	1001b
+		.endm
diff --git a/arch/arm/include/debug/pxa.S b/arch/arm/include/debug/pxa.S
deleted file mode 100644
index e1e795a..0000000
--- a/arch/arm/include/debug/pxa.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Early serial output macro for Marvell PXA/MMP SoC
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * Copyright (C) 2013 Haojian Zhuang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#if defined(CONFIG_DEBUG_PXA_UART1)
-#define PXA_UART_REG_PHYS_BASE	0x40100000
-#define PXA_UART_REG_VIRT_BASE	0xf2100000
-#elif defined(CONFIG_DEBUG_MMP_UART2)
-#define PXA_UART_REG_PHYS_BASE	0xd4017000
-#define PXA_UART_REG_VIRT_BASE	0xfe017000
-#elif defined(CONFIG_DEBUG_MMP_UART3)
-#define PXA_UART_REG_PHYS_BASE	0xd4018000
-#define PXA_UART_REG_VIRT_BASE	0xfe018000
-#else
-#error "Select uart for DEBUG_LL"
-#endif
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =PXA_UART_REG_PHYS_BASE
-	ldr	\rv, =PXA_UART_REG_VIRT_BASE
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/include/debug/rockchip.S b/arch/arm/include/debug/rockchip.S
deleted file mode 100644
index cfd883e..0000000
--- a/arch/arm/include/debug/rockchip.S
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Early serial output macro for Rockchip SoCs
- *
- * Copyright (C) 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#if defined(CONFIG_DEBUG_RK29_UART0)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20060000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed60000
-#elif defined(CONFIG_DEBUG_RK29_UART1)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20064000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed64000
-#elif defined(CONFIG_DEBUG_RK29_UART2)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20068000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed68000
-#elif defined(CONFIG_DEBUG_RK3X_UART0)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x10124000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfeb24000
-#elif defined(CONFIG_DEBUG_RK3X_UART1)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x10126000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfeb26000
-#elif defined(CONFIG_DEBUG_RK3X_UART2)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20064000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed64000
-#elif defined(CONFIG_DEBUG_RK3X_UART3)
-#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20068000
-#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed68000
-#endif
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =ROCKCHIP_UART_DEBUG_PHYS_BASE
-	ldr	\rv, =ROCKCHIP_UART_DEBUG_VIRT_BASE
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/include/debug/socfpga.S b/arch/arm/include/debug/socfpga.S
deleted file mode 100644
index 966b2f9..0000000
--- a/arch/arm/include/debug/socfpga.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define UART_SHIFT 2
-#define DEBUG_LL_UART_OFFSET	0x00002000
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET
-		orr	\rp, \rp, #0x00c00000
-		orr	\rv, \rp, #0xfe000000	@ virtual base
-		orr	\rp, \rp, #0xff000000	@ physical base
-		.endm
-
-#include "8250_32.S"
-
diff --git a/arch/arm/include/debug/sunxi.S b/arch/arm/include/debug/sunxi.S
deleted file mode 100644
index 04eb56d..0000000
--- a/arch/arm/include/debug/sunxi.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Early serial output macro for Allwinner A1X SoCs
- *
- * Copyright (C) 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#if defined(CONFIG_DEBUG_SUNXI_UART0)
-#define SUNXI_UART_DEBUG_PHYS_BASE 0x01c28000
-#define SUNXI_UART_DEBUG_VIRT_BASE 0xf1c28000
-#elif defined(CONFIG_DEBUG_SUNXI_UART1)
-#define SUNXI_UART_DEBUG_PHYS_BASE 0x01c28400
-#define SUNXI_UART_DEBUG_VIRT_BASE 0xf1c28400
-#endif
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =SUNXI_UART_DEBUG_PHYS_BASE
-	ldr	\rv, =SUNXI_UART_DEBUG_VIRT_BASE
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/include/debug/u300.S b/arch/arm/include/debug/u300.S
deleted file mode 100644
index 6f04f08..0000000
--- a/arch/arm/include/debug/u300.S
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2006-2013 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * Debugging macro include header.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-#define U300_SLOW_PER_PHYS_BASE		0xc0010000
-#define U300_SLOW_PER_VIRT_BASE		0xff000000
-
-	.macro	addruart, rp, rv, tmp
-	/* If we move the address using MMU, use this. */
-	ldr	\rp,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
-	ldr	\rv,	  = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
-	orr	\rp, \rp, #0x00003000
-	orr	\rv, \rv, #0x00003000
-	.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/ux500.S b/arch/arm/include/debug/ux500.S
index fbd24be..aa7f63a 100644
--- a/arch/arm/include/debug/ux500.S
+++ b/arch/arm/include/debug/ux500.S
@@ -45,4 +45,4 @@
 	ldr	\rv, =UART_VIRT_BASE		@ yes, virtual address
 	.endm
 
-#include <asm/hardware/debug-pl01x.S>
+#include <debug/pl01x.S>
diff --git a/arch/arm/include/debug/vexpress.S b/arch/arm/include/debug/vexpress.S
index acafb22..524acd5 100644
--- a/arch/arm/include/debug/vexpress.S
+++ b/arch/arm/include/debug/vexpress.S
@@ -47,51 +47,5 @@
 
 		.endm
 
-#include <asm/hardware/debug-pl01x.S>
-
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
-
-		.macro	addruart,rp,rv,tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET
-		orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
-		orr	\rp, \rp, #DEBUG_LL_PHYS_BASE
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
-
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
-
-		.macro	addruart,rp,rv,tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET_RS1
-		orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
-		orr	\rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
-
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CRX)
-
-		.macro	addruart,rp,tmp,tmp2
-		ldr	\rp, =DEBUG_LL_UART_PHYS_CRX
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
-
-#else /* CONFIG_DEBUG_LL_UART_NONE */
-
-		.macro	addruart, rp, rv, tmp
-		/* Safe dummy values */
-		mov	\rp, #0
-		mov	\rv, #DEBUG_LL_VIRT_BASE
-		.endm
-
-		.macro	senduart,rd,rx
-		.endm
-
-		.macro	waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-		.endm
-
+#include <debug/pl01x.S>
 #endif
diff --git a/arch/arm/include/debug/vf.S b/arch/arm/include/debug/vf.S
new file mode 100644
index 0000000..ba12cc4
--- /dev/null
+++ b/arch/arm/include/debug/vf.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =0x40028000	@ physical
+	ldr	\rv, =0xfe028000	@ virtual
+	.endm
+
+	.macro	senduart, rd, rx
+	strb	\rd, [\rx, #0x7]	@ Data Register
+	.endm
+
+	.macro	busyuart, rd, rx
+1001:	ldrb	\rd, [\rx, #0x4]	@ Status Register 1
+	tst	\rd, #1 << 6		@ TC
+	beq	1001b			@ wait until transmit done
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
index 9edc969..ec4164d 100644
--- a/arch/arm/kernel/atags.h
+++ b/arch/arm/kernel/atags.h
@@ -7,9 +7,10 @@ static inline void save_atags(struct tag *tags) { }
 void convert_to_tag_list(struct tag *tags);
 
 #ifdef CONFIG_ATAGS
-struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr);
+const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer,
+	unsigned int machine_nr);
 #else
-static inline struct machine_desc *
+static inline const struct machine_desc *
 setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
 {
 	early_print("no ATAGS support: can't continue\n");
diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c
index 14512e6..8c14de8 100644
--- a/arch/arm/kernel/atags_parse.c
+++ b/arch/arm/kernel/atags_parse.c
@@ -178,11 +178,11 @@ static void __init squash_mem_tags(struct tag *tag)
 			tag->hdr.tag = ATAG_NONE;
 }
 
-struct machine_desc * __init setup_machine_tags(phys_addr_t __atags_pointer,
-						unsigned int machine_nr)
+const struct machine_desc * __init
+setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
 {
 	struct tag *tags = (struct tag *)&default_tags;
-	struct machine_desc *mdesc = NULL, *p;
+	const struct machine_desc *mdesc = NULL, *p;
 	char *from = default_command_line;
 
 	default_tags.mem.start = PHYS_OFFSET;
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 261fcc8..1ec9c87 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -363,6 +363,20 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->add_bus)
+		sys->add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	if (sys->remove_bus)
+		sys->remove_bus(bus);
+}
+
 /*
  * Swizzle the device pin each time we cross a bridge.  If a platform does
  * not provide a swizzle function, we perform the standard PCI swizzling.
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
+		sys->add_bus = hw->add_bus;
+		sys->remove_bus = hw->remove_bus;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 5859c8b..eae1976 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -176,10 +176,10 @@ void __init arm_dt_init_cpu_maps(void)
  * If a dtb was passed to the kernel in r2, then use it to choose the
  * correct machine_desc and to setup the system.
  */
-struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
+const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 {
 	struct boot_param_header *devtree;
-	struct machine_desc *mdesc, *mdesc_best = NULL;
+	const struct machine_desc *mdesc, *mdesc_best = NULL;
 	unsigned int score, mdesc_score = ~1;
 	unsigned long dt_root;
 	const char *model;
@@ -188,7 +188,7 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 	DT_MACHINE_START(GENERIC_DT, "Generic DT based system")
 	MACHINE_END
 
-	mdesc_best = (struct machine_desc *)&__mach_desc_GENERIC_DT;
+	mdesc_best = &__mach_desc_GENERIC_DT;
 #endif
 
 	if (!dt_phys)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index afc2489..7b31e63 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -72,10 +72,10 @@ static int __init fpe_setup(char *line)
 __setup("fpe=", fpe_setup);
 #endif
 
-extern void paging_init(struct machine_desc *desc);
+extern void paging_init(const struct machine_desc *desc);
 extern void sanity_check_meminfo(void);
 extern enum reboot_mode reboot_mode;
-extern void setup_dma_zone(struct machine_desc *desc);
+extern void setup_dma_zone(const struct machine_desc *desc);
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
@@ -139,7 +139,7 @@ EXPORT_SYMBOL(elf_platform);
 static const char *cpu_name;
 static const char *machine_name;
 static char __initdata cmd_line[COMMAND_LINE_SIZE];
-struct machine_desc *machine_desc __initdata;
+const struct machine_desc *machine_desc __initdata;
 
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 #define ENDIANNESS ((char)endian_test.l)
@@ -607,7 +607,7 @@ static void __init setup_processor(void)
 
 void __init dump_machine_table(void)
 {
-	struct machine_desc *p;
+	const struct machine_desc *p;
 
 	early_print("Available machine support:\n\nID (hex)\tNAME\n");
 	for_each_machine_desc(p)
@@ -694,7 +694,7 @@ static int __init early_mem(char *p)
 }
 early_param("mem", early_mem);
 
-static void __init request_standard_resources(struct machine_desc *mdesc)
+static void __init request_standard_resources(const struct machine_desc *mdesc)
 {
 	struct memblock_region *region;
 	struct resource *res;
@@ -852,7 +852,7 @@ void __init hyp_mode_check(void)
 
 void __init setup_arch(char **cmdline_p)
 {
-	struct machine_desc *mdesc;
+	const struct machine_desc *mdesc;
 
 	setup_processor();
 	mdesc = setup_machine_fdt(__atags_pointer);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index c2b4f8f..3a98192 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -41,7 +41,6 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
-#include <asm/localtimer.h>
 #include <asm/smp_plat.h>
 #include <asm/virt.h>
 #include <asm/mach/arch.h>
@@ -146,8 +145,6 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void percpu_timer_stop(void);
-
 static int platform_cpu_kill(unsigned int cpu)
 {
 	if (smp_ops.cpu_kill)
@@ -191,11 +188,6 @@ int __cpu_disable(void)
 	migrate_irqs();
 
 	/*
-	 * Stop the local timer for this CPU.
-	 */
-	percpu_timer_stop();
-
-	/*
 	 * Flush user cache and TLB mappings, and then remove this CPU
 	 * from the vm mask set of all processes.
 	 *
@@ -316,8 +308,6 @@ static void smp_store_cpu_info(unsigned int cpuid)
 	store_cpu_topology(cpuid);
 }
 
-static void percpu_timer_setup(void);
-
 /*
  * This is the secondary CPU boot entry.  We're using this CPUs
  * idle thread stack, but a set of temporary page tables.
@@ -372,11 +362,6 @@ asmlinkage void secondary_start_kernel(void)
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
-	/*
-	 * Setup the percpu timer for this CPU.
-	 */
-	percpu_timer_setup();
-
 	local_irq_enable();
 	local_fiq_enable();
 
@@ -423,12 +408,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 		max_cpus = ncores;
 	if (ncores > 1 && max_cpus) {
 		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-
-		/*
 		 * Initialise the present map, which describes the set of CPUs
 		 * actually populated at the present time. A platform should
 		 * re-initialize the map in the platforms smp_prepare_cpus()
@@ -504,11 +483,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 	return sum;
 }
 
-/*
- * Timer (local or broadcast) support
- */
-static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 void tick_broadcast(const struct cpumask *mask)
 {
@@ -516,67 +490,6 @@ void tick_broadcast(const struct cpumask *mask)
 }
 #endif
 
-static void broadcast_timer_set_mode(enum clock_event_mode mode,
-	struct clock_event_device *evt)
-{
-}
-
-static void broadcast_timer_setup(struct clock_event_device *evt)
-{
-	evt->name	= "dummy_timer";
-	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
-			  CLOCK_EVT_FEAT_PERIODIC |
-			  CLOCK_EVT_FEAT_DUMMY;
-	evt->rating	= 100;
-	evt->mult	= 1;
-	evt->set_mode	= broadcast_timer_set_mode;
-
-	clockevents_register_device(evt);
-}
-
-static struct local_timer_ops *lt_ops;
-
-#ifdef CONFIG_LOCAL_TIMERS
-int local_timer_register(struct local_timer_ops *ops)
-{
-	if (!is_smp() || !setup_max_cpus)
-		return -ENXIO;
-
-	if (lt_ops)
-		return -EBUSY;
-
-	lt_ops = ops;
-	return 0;
-}
-#endif
-
-static void percpu_timer_setup(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-
-	evt->cpumask = cpumask_of(cpu);
-
-	if (!lt_ops || lt_ops->setup(evt))
-		broadcast_timer_setup(evt);
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * The generic clock events code purposely does not stop the local timer
- * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
- * manually here.
- */
-static void percpu_timer_stop(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-
-	if (lt_ops)
-		lt_ops->stop(evt);
-}
-#endif
-
 static DEFINE_RAW_SPINLOCK(stop_lock);
 
 /*
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 2595620..2985c9f 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -24,7 +25,6 @@
 
 #include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
-#include <asm/localtimer.h>
 
 /* set up by the platform code */
 static void __iomem *twd_base;
@@ -33,7 +33,7 @@ static struct clk *twd_clk;
 static unsigned long twd_timer_rate;
 static DEFINE_PER_CPU(bool, percpu_setup_called);
 
-static struct clock_event_device __percpu **twd_evt;
+static struct clock_event_device __percpu *twd_evt;
 static int twd_ppi;
 
 static void twd_set_mode(enum clock_event_mode mode,
@@ -90,8 +90,10 @@ static int twd_timer_ack(void)
 	return 0;
 }
 
-static void twd_timer_stop(struct clock_event_device *clk)
+static void twd_timer_stop(void)
 {
+	struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
+
 	twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
 	disable_percpu_irq(clk->irq);
 }
@@ -106,7 +108,7 @@ static void twd_update_frequency(void *new_rate)
 {
 	twd_timer_rate = *((unsigned long *) new_rate);
 
-	clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+	clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
 }
 
 static int twd_rate_change(struct notifier_block *nb,
@@ -132,7 +134,7 @@ static struct notifier_block twd_clk_nb = {
 
 static int twd_clk_init(void)
 {
-	if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+	if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
 		return clk_notifier_register(twd_clk, &twd_clk_nb);
 
 	return 0;
@@ -151,7 +153,7 @@ static void twd_update_frequency(void *data)
 {
 	twd_timer_rate = clk_get_rate(twd_clk);
 
-	clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+	clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
 }
 
 static int twd_cpufreq_transition(struct notifier_block *nb,
@@ -177,7 +179,7 @@ static struct notifier_block twd_cpufreq_nb = {
 
 static int twd_cpufreq_init(void)
 {
-	if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+	if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
 		return cpufreq_register_notifier(&twd_cpufreq_nb,
 			CPUFREQ_TRANSITION_NOTIFIER);
 
@@ -228,7 +230,7 @@ static void twd_calibrate_rate(void)
 
 static irqreturn_t twd_handler(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+	struct clock_event_device *evt = dev_id;
 
 	if (twd_timer_ack()) {
 		evt->event_handler(evt);
@@ -265,9 +267,9 @@ static void twd_get_clock(struct device_node *np)
 /*
  * Setup the local clock events for a CPU.
  */
-static int twd_timer_setup(struct clock_event_device *clk)
+static void twd_timer_setup(void)
 {
-	struct clock_event_device **this_cpu_clk;
+	struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
 	int cpu = smp_processor_id();
 
 	/*
@@ -276,9 +278,9 @@ static int twd_timer_setup(struct clock_event_device *clk)
 	 */
 	if (per_cpu(percpu_setup_called, cpu)) {
 		__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-		clockevents_register_device(*__this_cpu_ptr(twd_evt));
+		clockevents_register_device(clk);
 		enable_percpu_irq(clk->irq, 0);
-		return 0;
+		return;
 	}
 	per_cpu(percpu_setup_called, cpu) = true;
 
@@ -297,27 +299,37 @@ static int twd_timer_setup(struct clock_event_device *clk)
 	clk->set_mode = twd_set_mode;
 	clk->set_next_event = twd_set_next_event;
 	clk->irq = twd_ppi;
-
-	this_cpu_clk = __this_cpu_ptr(twd_evt);
-	*this_cpu_clk = clk;
+	clk->cpumask = cpumask_of(cpu);
 
 	clockevents_config_and_register(clk, twd_timer_rate,
 					0xf, 0xffffffff);
 	enable_percpu_irq(clk->irq, 0);
+}
 
-	return 0;
+static int twd_timer_cpu_notify(struct notifier_block *self,
+				unsigned long action, void *hcpu)
+{
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		twd_timer_setup();
+		break;
+	case CPU_DYING:
+		twd_timer_stop();
+		break;
+	}
+
+	return NOTIFY_OK;
 }
 
-static struct local_timer_ops twd_lt_ops = {
-	.setup	= twd_timer_setup,
-	.stop	= twd_timer_stop,
+static struct notifier_block twd_timer_cpu_nb = {
+	.notifier_call = twd_timer_cpu_notify,
 };
 
 static int __init twd_local_timer_common_register(struct device_node *np)
 {
 	int err;
 
-	twd_evt = alloc_percpu(struct clock_event_device *);
+	twd_evt = alloc_percpu(struct clock_event_device);
 	if (!twd_evt) {
 		err = -ENOMEM;
 		goto out_free;
@@ -329,12 +341,22 @@ static int __init twd_local_timer_common_register(struct device_node *np)
 		goto out_free;
 	}
 
-	err = local_timer_register(&twd_lt_ops);
+	err = register_cpu_notifier(&twd_timer_cpu_nb);
 	if (err)
 		goto out_irq;
 
 	twd_get_clock(np);
 
+	/*
+	 * Immediately configure the timer on the boot CPU, unless we need
+	 * jiffies to be incrementing to calibrate the rate in which case
+	 * setup the timer in late_time_init.
+	 */
+	if (twd_timer_rate)
+		twd_timer_setup();
+	else
+		late_time_init = twd_timer_setup;
+
 	return 0;
 
 out_irq:
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 741f66a..9c697db 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -219,6 +219,10 @@ long kvm_arch_dev_ioctl(struct file *filp,
 	return -EINVAL;
 }
 
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   struct kvm_memory_slot *memslot,
 				   struct kvm_userspace_memory_region *mem,
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index af72969..aaf3a87 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -45,3 +45,9 @@ lib-$(CONFIG_ARCH_SHARK)	+= io-shark.o
 
 $(obj)/csumpartialcopy.o:	$(obj)/csumpartialcopygeneric.S
 $(obj)/csumpartialcopyuser.o:	$(obj)/csumpartialcopygeneric.S
+
+ifeq ($(CONFIG_KERNEL_MODE_NEON),y)
+  NEON_FLAGS			:= -mfloat-abi=softfp -mfpu=neon
+  CFLAGS_xor-neon.o		+= $(NEON_FLAGS)
+  lib-$(CONFIG_XOR_BLOCKS)	+= xor-neon.o
+endif
diff --git a/arch/arm/lib/xor-neon.c b/arch/arm/lib/xor-neon.c
new file mode 100644
index 0000000..f485e5a
--- /dev/null
+++ b/arch/arm/lib/xor-neon.c
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/arm/lib/xor-neon.c
+ *
+ * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/raid/xor.h>
+
+#ifndef __ARM_NEON__
+#error You should compile this file with '-mfloat-abi=softfp -mfpu=neon'
+#endif
+
+/*
+ * Pull in the reference implementations while instructing GCC (through
+ * -ftree-vectorize) to attempt to exploit implicit parallelism and emit
+ * NEON instructions.
+ */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC optimize "tree-vectorize"
+#else
+/*
+ * While older versions of GCC do not generate incorrect code, they fail to
+ * recognize the parallel nature of these functions, and emit plain ARM code,
+ * which is known to be slower than the optimized ARM code in asm-arm/xor.h.
+ */
+#warning This code requires at least version 4.6 of GCC
+#endif
+
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#include <asm-generic/xor.h>
+
+struct xor_block_template const xor_block_neon_inner = {
+	.name	= "__inner_neon__",
+	.do_2	= xor_8regs_2,
+	.do_3	= xor_8regs_3,
+	.do_4	= xor_8regs_4,
+	.do_5	= xor_8regs_5,
+};
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 629ea5f..b2a3474 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -465,7 +465,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
 
 #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
 static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
 
 static struct resource lcdc_resources[] = {
 	[0] = {
@@ -498,7 +498,7 @@ static struct platform_device at91_lcdc_device = {
 	.num_resources	= ARRAY_SIZE(lcdc_resources),
 };
 
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
 {
 	if (!data) {
 		return;
@@ -559,7 +559,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 	platform_device_register(&at91_lcdc_device);
 }
 #else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
 #endif
 
 
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 858c8aa..4aeaddd 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -832,7 +832,7 @@ void __init at91_add_device_can(struct at91_can_data *data) {}
 
 #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
 static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
 
 static struct resource lcdc_resources[] = {
 	[0] = {
@@ -859,7 +859,7 @@ static struct platform_device at91_lcdc_device = {
 	.num_resources	= ARRAY_SIZE(lcdc_resources),
 };
 
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
 {
 	if (!data)
 		return;
@@ -891,7 +891,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 	platform_device_register(&at91_lcdc_device);
 }
 #else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
 #endif
 
 
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index acb703e..cb36fa8 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -965,7 +965,7 @@ void __init at91_add_device_isi(struct isi_platform_data *data,
 
 #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
 static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
 
 static struct resource lcdc_resources[] = {
 	[0] = {
@@ -991,7 +991,7 @@ static struct platform_device at91_lcdc_device = {
 	.num_resources	= ARRAY_SIZE(lcdc_resources),
 };
 
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
 {
 	if (!data)
 		return;
@@ -1037,7 +1037,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 	platform_device_register(&at91_lcdc_device);
 }
 #else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
 #endif
 
 
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 352468f..a698bda 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -498,7 +498,7 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
 
 #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
 static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
 
 static struct resource lcdc_resources[] = {
 	[0] = {
@@ -525,7 +525,7 @@ static struct platform_device at91_lcdc_device = {
 	.num_resources	= ARRAY_SIZE(lcdc_resources),
 };
 
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
 {
 	if (!data) {
 		return;
@@ -557,7 +557,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 	platform_device_register(&at91_lcdc_device);
 }
 #else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
 #endif
 
 
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index d343762..473546b 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -389,7 +389,7 @@ static struct fb_monspecs at91fb_default_stn_monspecs = {
 					| ATMEL_LCDC_IFWIDTH_4 \
 					| ATMEL_LCDC_SCANMOD_SINGLE)
 
-static void at91_lcdc_stn_power_control(int on)
+static void at91_lcdc_stn_power_control(struct atmel_lcdfb_pdata *pdata, int on)
 {
 	/* backlight */
 	if (on) {	/* power up */
@@ -401,7 +401,7 @@ static void at91_lcdc_stn_power_control(int on)
 	}
 }
 
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
 	.default_bpp			= 1,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
 	.default_lcdcon2		= AT91SAM9261_DEFAULT_STN_LCDCON2,
@@ -445,7 +445,7 @@ static struct fb_monspecs at91fb_default_tft_monspecs = {
 					| ATMEL_LCDC_DISTYPE_TFT    \
 					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
 
-static void at91_lcdc_tft_power_control(int on)
+static void at91_lcdc_tft_power_control(struct atmel_lcdfb_pdata *pdata, int on)
 {
 	if (on)
 		at91_set_gpio_value(AT91_PIN_PA12, 0);	/* power up */
@@ -453,7 +453,7 @@ static void at91_lcdc_tft_power_control(int on)
 		at91_set_gpio_value(AT91_PIN_PA12, 1);	/* power down */
 }
 
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
 	.lcdcon_is_backlight		= true,
 	.default_bpp			= 16,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
@@ -465,7 +465,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
 #endif
 
 #else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
 #endif
 
 
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 3284df0..8b4942c 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -275,13 +275,13 @@ static struct fb_monspecs at91fb_default_monspecs = {
 					| ATMEL_LCDC_DISTYPE_TFT \
 					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
 
-static void at91_lcdc_power_control(int on)
+static void at91_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
 {
 	at91_set_gpio_value(AT91_PIN_PA30, on);
 }
 
 /* Driver datas */
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
 	.lcdcon_is_backlight		= true,
 	.default_bpp			= 16,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
@@ -292,7 +292,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
 };
 
 #else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
 #endif
 
 
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 2a94896..ef39078 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -284,7 +284,7 @@ static struct fb_monspecs at91fb_default_monspecs = {
 					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
 
 /* Driver datas */
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
 	.lcdcon_is_backlight		= true,
 	.default_bpp			= 32,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
@@ -295,7 +295,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
 };
 
 #else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
 #endif
 
 
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index aa265dc..604eecf 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -170,7 +170,7 @@ static struct fb_monspecs at91fb_default_monspecs = {
 					| ATMEL_LCDC_DISTYPE_TFT \
 					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
 
-static void at91_lcdc_power_control(int on)
+static void at91_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
 {
 	if (on)
 		at91_set_gpio_value(AT91_PIN_PC1, 0);	/* power up */
@@ -179,7 +179,7 @@ static void at91_lcdc_power_control(int on)
 }
 
 /* Driver datas */
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
 	.lcdcon_is_backlight            = true,
 	.default_bpp			= 16,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
@@ -191,7 +191,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
 };
 
 #else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
 #endif
 
 
diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h
index 4a234fb..6c08b34 100644
--- a/arch/arm/mach-at91/board.h
+++ b/arch/arm/mach-at91/board.h
@@ -107,8 +107,8 @@ extern void __init at91_add_device_pwm(u32 mask);
 extern void __init at91_add_device_ssc(unsigned id, unsigned pins);
 
  /* LCD Controller */
-struct atmel_lcdfb_info;
-extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
+struct atmel_lcdfb_pdata;
+extern void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data);
 
  /* AC97 */
 extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index bea6793..9f09f45 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1249,12 +1249,10 @@ static struct vpif_capture_config da850_vpif_capture_config = {
 
 static struct adv7343_platform_data adv7343_pdata = {
 	.mode_config = {
-		.dac_3 = 1,
-		.dac_2 = 1,
-		.dac_1 = 1,
+		.dac = { 1, 1, 1 },
 	},
 	.sd_config = {
-		.sd_dac_out1 = 1,
+		.sd_dac_out = { 1 },
 	},
 };
 
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index 36aef3a..f1ac1c9 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = {
 	.states[1]		= {
 		.enter			= davinci_enter_idle,
 		.exit_latency		= 10,
-		.target_residency	= 100000,
+		.target_residency	= 10000,
 		.flags			= CPUIDLE_FLAG_TIME_VALID,
 		.name			= "DDR SR",
 		.desc			= "WFI and DDR Self Refresh",
diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S
deleted file mode 100644
index b18b8eb..0000000
--- a/arch/arm/mach-davinci/include/mach/debug-macro.S
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Debugging macro for DaVinci
- *
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/* Modifications
- * Jan 2009	Chaithrika U S	Added senduart, busyuart, waituart
- *				macros, based on debug-8250.S file
- *				but using 32-bit accesses required for
- *                              some davinci devices.
- */
-
-#include <linux/serial_reg.h>
-
-#include <mach/serial.h>
-
-#define UART_SHIFT	2
-
-#if defined(CONFIG_DEBUG_DAVINCI_DMx_UART0)
-#define UART_BASE	DAVINCI_UART0_BASE
-#elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART1)
-#define UART_BASE	DA8XX_UART1_BASE
-#elif defined(CONFIG_DEBUG_DAVINCI_DA8XX_UART2)
-#define UART_BASE	DA8XX_UART2_BASE
-#elif defined(CONFIG_DEBUG_DAVINCI_TNETV107X_UART1)
-#define UART_BASE	TNETV107X_UART2_BASE
-#define UART_VIRTBASE	TNETV107X_UART2_VIRT
-#else
-#error "Select a specifc port for DEBUG_LL"
-#endif
-
-#ifndef UART_VIRTBASE
-#define UART_VIRTBASE	IO_ADDRESS(UART_BASE)
-#endif
-
-		.macro addruart, rp, rv, tmp
-		ldr	\rp, =UART_BASE
-		ldr	\rv, =UART_VIRTBASE
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #UART_TX << UART_SHIFT]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
-		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
-		bne	1002b
-		.endm
-
-		.macro	waituart,rd,rx
-#ifdef FLOW_CONTROL
-1001:		ldr	\rd, [\rx, #UART_MSR << UART_SHIFT]
-		tst	\rd, #UART_MSR_CTS
-		beq	1001b
-#endif
-		.endm
-
diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig
index dff7b2f..0bc7cdf 100644
--- a/arch/arm/mach-dove/Kconfig
+++ b/arch/arm/mach-dove/Kconfig
@@ -23,6 +23,8 @@ config MACH_CM_A510
 config MACH_DOVE_DT
 	bool "Marvell Dove Flattened Device Tree"
 	select DOVE_CLK
+	select ORION_IRQCHIP
+	select ORION_TIMER
 	select REGULATOR
 	select REGULATOR_FIXED_VOLTAGE
 	select USE_OF
diff --git a/arch/arm/mach-dove/Makefile b/arch/arm/mach-dove/Makefile
index 4d9d2ff..cbc5c06 100644
--- a/arch/arm/mach-dove/Makefile
+++ b/arch/arm/mach-dove/Makefile
@@ -1,5 +1,5 @@
-obj-y				+= common.o irq.o
-obj-$(CONFIG_DOVE_LEGACY)	+= mpp.o
+obj-y				+= common.o
+obj-$(CONFIG_DOVE_LEGACY)	+= irq.o mpp.o
 obj-$(CONFIG_PCI)		+= pcie.o
 obj-$(CONFIG_MACH_DOVE_DB)	+= dove-db-setup.o
 obj-$(CONFIG_MACH_DOVE_DT)	+= board-dt.o
diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c
index f3755ac..1efbe1d 100644
--- a/arch/arm/mach-dove/board-dt.c
+++ b/arch/arm/mach-dove/board-dt.c
@@ -10,11 +10,14 @@
 
 #include <linux/init.h>
 #include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/usb-ehci-orion.h>
 #include <asm/hardware/cache-tauros2.h>
 #include <asm/mach/arch.h>
+#include <mach/dove.h>
 #include <mach/pm.h>
 #include <plat/common.h>
 #include <plat/irq.h>
@@ -33,10 +36,6 @@ static void __init dove_legacy_clk_init(void)
 	clkspec.np = np;
 	clkspec.args_count = 1;
 
-	clkspec.args[0] = CLOCK_GATING_BIT_GBE;
-	orion_clkdev_add(NULL, "mv643xx_eth_port.0",
-			 of_clk_get_from_provider(&clkspec));
-
 	clkspec.args[0] = CLOCK_GATING_BIT_PCIE0;
 	orion_clkdev_add("0", "pcie",
 			 of_clk_get_from_provider(&clkspec));
@@ -46,16 +45,12 @@ static void __init dove_legacy_clk_init(void)
 			 of_clk_get_from_provider(&clkspec));
 }
 
-static void __init dove_of_clk_init(void)
+static void __init dove_dt_time_init(void)
 {
 	of_clk_init(NULL);
-	dove_legacy_clk_init();
+	clocksource_of_init();
 }
 
-static struct mv643xx_eth_platform_data dove_dt_ge00_data = {
-	.phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT,
-};
-
 static void __init dove_dt_init(void)
 {
 	pr_info("Dove 88AP510 SoC\n");
@@ -63,13 +58,12 @@ static void __init dove_dt_init(void)
 #ifdef CONFIG_CACHE_TAUROS2
 	tauros2_init(0);
 #endif
-	dove_setup_cpu_wins();
+	BUG_ON(mvebu_mbus_dt_init());
 
-	/* Setup root of clk tree */
-	dove_of_clk_init();
+	/* Setup clocks for legacy devices */
+	dove_legacy_clk_init();
 
 	/* Internal devices not ported to DT yet */
-	dove_ge00_init(&dove_dt_ge00_data);
 	dove_pcie_init(1, 1);
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -82,9 +76,7 @@ static const char * const dove_dt_board_compat[] = {
 
 DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)")
 	.map_io		= dove_map_io,
-	.init_early	= dove_init_early,
-	.init_irq	= orion_dt_init_irq,
-	.init_time	= dove_timer_init,
+	.init_time	= dove_dt_time_init,
 	.init_machine	= dove_dt_init,
 	.restart	= dove_restart,
 	.dt_compat	= dove_dt_board_compat,
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 00247c7..c122bcf 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -27,6 +27,22 @@
 #include <plat/time.h>
 #include "common.h"
 
+/* These can go away once Dove uses the mvebu-mbus DT binding */
+#define DOVE_MBUS_PCIE0_MEM_TARGET    0x4
+#define DOVE_MBUS_PCIE0_MEM_ATTR      0xe8
+#define DOVE_MBUS_PCIE0_IO_TARGET     0x4
+#define DOVE_MBUS_PCIE0_IO_ATTR       0xe0
+#define DOVE_MBUS_PCIE1_MEM_TARGET    0x8
+#define DOVE_MBUS_PCIE1_MEM_ATTR      0xe8
+#define DOVE_MBUS_PCIE1_IO_TARGET     0x8
+#define DOVE_MBUS_PCIE1_IO_ATTR       0xe0
+#define DOVE_MBUS_CESA_TARGET         0x3
+#define DOVE_MBUS_CESA_ATTR           0x1
+#define DOVE_MBUS_BOOTROM_TARGET      0x1
+#define DOVE_MBUS_BOOTROM_ATTR        0xfd
+#define DOVE_MBUS_SCRATCHPAD_TARGET   0xd
+#define DOVE_MBUS_SCRATCHPAD_ATTR     0x0
+
 /*****************************************************************************
  * I/O Address Mapping
  ****************************************************************************/
@@ -108,8 +124,8 @@ static void __init dove_clk_init(void)
 	orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
 	orion_clkdev_add(NULL, "orion_nand", nand);
 	orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
-	orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0);
-	orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1);
+	orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
+	orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
 	orion_clkdev_add(NULL, "mv_crypto", crypto);
 	orion_clkdev_add(NULL, "dove-ac97", ac97);
 	orion_clkdev_add(NULL, "dove-pdma", pdma);
@@ -332,34 +348,40 @@ void __init dove_setup_cpu_wins(void)
 {
 	/*
 	 * The PCIe windows will no longer be statically allocated
-	 * here once Dove is migrated to the pci-mvebu driver.
+	 * here once Dove is migrated to the pci-mvebu driver. The
+	 * non-PCIe windows will no longer be created here once Dove
+	 * fully moves to DT.
 	 */
-	mvebu_mbus_add_window_remap_flags("pcie0.0",
+	mvebu_mbus_add_window_remap_by_id(DOVE_MBUS_PCIE0_IO_TARGET,
+					  DOVE_MBUS_PCIE0_IO_ATTR,
 					  DOVE_PCIE0_IO_PHYS_BASE,
 					  DOVE_PCIE0_IO_SIZE,
-					  DOVE_PCIE0_IO_BUS_BASE,
-					  MVEBU_MBUS_PCI_IO);
-	mvebu_mbus_add_window_remap_flags("pcie1.0",
+					  DOVE_PCIE0_IO_BUS_BASE);
+	mvebu_mbus_add_window_remap_by_id(DOVE_MBUS_PCIE1_IO_TARGET,
+					  DOVE_MBUS_PCIE1_IO_ATTR,
 					  DOVE_PCIE1_IO_PHYS_BASE,
 					  DOVE_PCIE1_IO_SIZE,
-					  DOVE_PCIE1_IO_BUS_BASE,
-					  MVEBU_MBUS_PCI_IO);
-	mvebu_mbus_add_window_remap_flags("pcie0.0",
-					  DOVE_PCIE0_MEM_PHYS_BASE,
-					  DOVE_PCIE0_MEM_SIZE,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
-	mvebu_mbus_add_window_remap_flags("pcie1.0",
-					  DOVE_PCIE1_MEM_PHYS_BASE,
-					  DOVE_PCIE1_MEM_SIZE,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
-	mvebu_mbus_add_window("cesa", DOVE_CESA_PHYS_BASE,
-			      DOVE_CESA_SIZE);
-	mvebu_mbus_add_window("bootrom", DOVE_BOOTROM_PHYS_BASE,
-			      DOVE_BOOTROM_SIZE);
-	mvebu_mbus_add_window("scratchpad", DOVE_SCRATCHPAD_PHYS_BASE,
-			      DOVE_SCRATCHPAD_SIZE);
+					  DOVE_PCIE1_IO_BUS_BASE);
+	mvebu_mbus_add_window_by_id(DOVE_MBUS_PCIE0_MEM_TARGET,
+				    DOVE_MBUS_PCIE0_MEM_ATTR,
+				    DOVE_PCIE0_MEM_PHYS_BASE,
+				    DOVE_PCIE0_MEM_SIZE);
+	mvebu_mbus_add_window_by_id(DOVE_MBUS_PCIE1_MEM_TARGET,
+				    DOVE_MBUS_PCIE1_MEM_ATTR,
+				    DOVE_PCIE1_MEM_PHYS_BASE,
+				    DOVE_PCIE1_MEM_SIZE);
+	mvebu_mbus_add_window_by_id(DOVE_MBUS_CESA_TARGET,
+				    DOVE_MBUS_CESA_ATTR,
+				    DOVE_CESA_PHYS_BASE,
+				    DOVE_CESA_SIZE);
+	mvebu_mbus_add_window_by_id(DOVE_MBUS_BOOTROM_TARGET,
+				    DOVE_MBUS_BOOTROM_ATTR,
+				    DOVE_BOOTROM_PHYS_BASE,
+				    DOVE_BOOTROM_SIZE);
+	mvebu_mbus_add_window_by_id(DOVE_MBUS_SCRATCHPAD_TARGET,
+				    DOVE_MBUS_SCRATCHPAD_ATTR,
+				    DOVE_SCRATCHPAD_PHYS_BASE,
+				    DOVE_SCRATCHPAD_SIZE);
 }
 
 void __init dove_init(void)
diff --git a/arch/arm/mach-dove/include/mach/debug-macro.S b/arch/arm/mach-dove/include/mach/debug-macro.S
deleted file mode 100644
index 5929cbc..0000000
--- a/arch/arm/mach-dove/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <mach/bridge-regs.h>
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =DOVE_SB_REGS_PHYS_BASE
-	ldr	\rv, =DOVE_SB_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-dove/mpp.c b/arch/arm/mach-dove/mpp.c
index 60bd729..8a433a5 100644
--- a/arch/arm/mach-dove/mpp.c
+++ b/arch/arm/mach-dove/mpp.c
@@ -47,7 +47,7 @@ static const struct dove_mpp_grp dove_mpp_grp[] = {
 
 /* Enable gpio for a range of pins. mode should be a combination of
    GPIO_OUTPUT_OK | GPIO_INPUT_OK */
-static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
+static void __init dove_mpp_gpio_mode(int start, int end, int gpio_mode)
 {
 	int i;
 
diff --git a/arch/arm/mach-ebsa110/include/mach/debug-macro.S b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
deleted file mode 100644
index bb02c05..0000000
--- a/arch/arm/mach-ebsa110/include/mach/debug-macro.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/* arch/arm/mach-ebsa110/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-**/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0xf0000000
-		orr	\rp, \rp, #0x00000be0
-		mov	\rp, \rv
-		.endm
-
-#define UART_SHIFT	2
-#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index fe3c1fa..bec570a 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -5,6 +5,7 @@ menu "Cirrus EP93xx Implementation Options"
 config EP93XX_SOC_COMMON
 	bool
 	default y
+	select SOC_BUS
 	select LEDS_GPIO_REGISTER
 
 config CRUNCH
@@ -194,20 +195,6 @@ config MACH_VISION_EP9307
 	  Say 'Y' here if you want your kernel to support the
 	  Vision Engraving Systems EP9307 SoM.
 
-choice
-	prompt "Select a UART for early kernel messages"
-
-config EP93XX_EARLY_UART1
-	bool "UART1"
-
-config EP93XX_EARLY_UART2
-	bool "UART2"
-
-config EP93XX_EARLY_UART3
-	bool "UART3"
-
-endchoice
-
 endmenu
 
 endif
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index df8612f..cefc26e 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
+#include <linux/sys_soc.h>
 #include <linux/timex.h>
 #include <linux/irq.h>
 #include <linux/io.h>
@@ -43,6 +44,7 @@
 #include <linux/platform_data/spi-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
+#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
@@ -896,8 +898,108 @@ void ep93xx_ide_release_gpio(struct platform_device *pdev)
 }
 EXPORT_SYMBOL(ep93xx_ide_release_gpio);
 
-void __init ep93xx_init_devices(void)
+/*************************************************************************
+ * EP93xx Security peripheral
+ *************************************************************************/
+
+/*
+ * The Maverick Key is 256 bits of micro fuses blown at the factory during
+ * manufacturing to uniquely identify a part.
+ *
+ * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key
+ */
+#define EP93XX_SECURITY_REG(x)		(EP93XX_SECURITY_BASE + (x))
+#define EP93XX_SECURITY_SECFLG		EP93XX_SECURITY_REG(0x2400)
+#define EP93XX_SECURITY_FUSEFLG		EP93XX_SECURITY_REG(0x2410)
+#define EP93XX_SECURITY_UNIQID		EP93XX_SECURITY_REG(0x2440)
+#define EP93XX_SECURITY_UNIQCHK		EP93XX_SECURITY_REG(0x2450)
+#define EP93XX_SECURITY_UNIQVAL		EP93XX_SECURITY_REG(0x2460)
+#define EP93XX_SECURITY_SECID1		EP93XX_SECURITY_REG(0x2500)
+#define EP93XX_SECURITY_SECID2		EP93XX_SECURITY_REG(0x2504)
+#define EP93XX_SECURITY_SECCHK1		EP93XX_SECURITY_REG(0x2520)
+#define EP93XX_SECURITY_SECCHK2		EP93XX_SECURITY_REG(0x2524)
+#define EP93XX_SECURITY_UNIQID2		EP93XX_SECURITY_REG(0x2700)
+#define EP93XX_SECURITY_UNIQID3		EP93XX_SECURITY_REG(0x2704)
+#define EP93XX_SECURITY_UNIQID4		EP93XX_SECURITY_REG(0x2708)
+#define EP93XX_SECURITY_UNIQID5		EP93XX_SECURITY_REG(0x270c)
+
+static char ep93xx_soc_id[33];
+
+static const char __init *ep93xx_get_soc_id(void)
 {
+	unsigned int id, id2, id3, id4, id5;
+
+	if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1)
+		return "bad Hamming code";
+
+	id = __raw_readl(EP93XX_SECURITY_UNIQID);
+	id2 = __raw_readl(EP93XX_SECURITY_UNIQID2);
+	id3 = __raw_readl(EP93XX_SECURITY_UNIQID3);
+	id4 = __raw_readl(EP93XX_SECURITY_UNIQID4);
+	id5 = __raw_readl(EP93XX_SECURITY_UNIQID5);
+
+	if (id != id2)
+		return "invalid";
+
+	snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id),
+		 "%08x%08x%08x%08x", id2, id3, id4, id5);
+
+	return ep93xx_soc_id;
+}
+
+static const char __init *ep93xx_get_soc_rev(void)
+{
+	int rev = ep93xx_chip_revision();
+
+	switch (rev) {
+	case EP93XX_CHIP_REV_D0:
+		return "D0";
+	case EP93XX_CHIP_REV_D1:
+		return "D1";
+	case EP93XX_CHIP_REV_E0:
+		return "E0";
+	case EP93XX_CHIP_REV_E1:
+		return "E1";
+	case EP93XX_CHIP_REV_E2:
+		return "E2";
+	default:
+		return "unknown";
+	}
+}
+
+static const char __init *ep93xx_get_machine_name(void)
+{
+	return kasprintf(GFP_KERNEL,"%s", machine_desc->name);
+}
+
+static struct device __init *ep93xx_init_soc(void)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return NULL;
+
+	soc_dev_attr->machine = ep93xx_get_machine_name();
+	soc_dev_attr->family = "Cirrus Logic EP93xx";
+	soc_dev_attr->revision = ep93xx_get_soc_rev();
+	soc_dev_attr->soc_id = ep93xx_get_soc_id();
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev)) {
+		kfree(soc_dev_attr->machine);
+		kfree(soc_dev_attr);
+		return NULL;
+	}
+
+	return soc_device_to_device(soc_dev);
+}
+
+struct device __init *ep93xx_init_devices(void)
+{
+	struct device *parent;
+
 	/* Disallow access to MaverickCrunch initially */
 	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
 
@@ -908,6 +1010,8 @@ void __init ep93xx_init_devices(void)
 			       EP93XX_SYSCON_DEVCFG_GONIDE |
 			       EP93XX_SYSCON_DEVCFG_HONIDE);
 
+	parent = ep93xx_init_soc();
+
 	/* Get the GPIO working early, other devices need it */
 	platform_device_register(&ep93xx_gpio_device);
 
@@ -920,6 +1024,8 @@ void __init ep93xx_init_devices(void)
 	platform_device_register(&ep93xx_wdt_device);
 
 	gpio_led_register_device(-1, &ep93xx_led_data);
+
+	return parent;
 }
 
 void ep93xx_restart(enum reboot_mode mode, const char *cmd)
diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
deleted file mode 100644
index af54e43..0000000
--- a/arch/arm/mach-ep93xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/debug-macro.S
- * Debugging macro include header
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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 <mach/ep93xx-regs.h>
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rp, =EP93XX_APB_PHYS_BASE	@ Physical base
-		ldr	\rv, =EP93XX_APB_VIRT_BASE	@ virtual base
-		orr	\rp, \rp, #0x000c0000
-		orr	\rv, \rv, #0x000c0000
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index e256e0b..4c0bbd9 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -6,6 +6,7 @@
 
 #include <linux/reboot.h>
 
+struct device;
 struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct spi_board_info;
@@ -54,7 +55,7 @@ void ep93xx_register_ide(void);
 int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
 void ep93xx_ide_release_gpio(struct platform_device *pdev);
 
-void ep93xx_init_devices(void);
+struct device *ep93xx_init_devices(void);
 extern void ep93xx_timer_init(void);
 
 void ep93xx_restart(enum reboot_mode, const char *);
diff --git a/arch/arm/mach-ep93xx/include/mach/uncompress.h b/arch/arm/mach-ep93xx/include/mach/uncompress.h
index b5cc77d..03c42e5 100644
--- a/arch/arm/mach-ep93xx/include/mach/uncompress.h
+++ b/arch/arm/mach-ep93xx/include/mach/uncompress.h
@@ -31,18 +31,8 @@ static void __raw_writel(unsigned int value, unsigned int ptr)
 	*((volatile unsigned int *)ptr) = value;
 }
 
-#if defined(CONFIG_EP93XX_EARLY_UART1)
-#define UART_BASE		EP93XX_UART1_PHYS_BASE
-#elif defined(CONFIG_EP93XX_EARLY_UART2)
-#define UART_BASE		EP93XX_UART2_PHYS_BASE
-#elif defined(CONFIG_EP93XX_EARLY_UART3)
-#define UART_BASE		EP93XX_UART3_PHYS_BASE
-#else
-#define UART_BASE		EP93XX_UART1_PHYS_BASE
-#endif
-
-#define PHYS_UART_DATA		(UART_BASE + 0x00)
-#define PHYS_UART_FLAG		(UART_BASE + 0x18)
+#define PHYS_UART_DATA		(CONFIG_DEBUG_UART_PHYS + 0x00)
+#define PHYS_UART_FLAG		(CONFIG_DEBUG_UART_PHYS + 0x18)
 #define UART_FLAG_TXFF		0x20
 
 static inline void putc(int c)
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 5952e68..5c9ab97 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -36,6 +36,7 @@ config CPU_EXYNOS4210
 	bool "SAMSUNG EXYNOS4210"
 	default y
 	depends on ARCH_EXYNOS4
+	select ARCH_HAS_BANDGAP
 	select ARM_CPU_SUSPEND if PM
 	select PINCTRL_EXYNOS
 	select PM_GENERIC_DOMAINS if PM
@@ -49,6 +50,7 @@ config SOC_EXYNOS4212
 	bool "SAMSUNG EXYNOS4212"
 	default y
 	depends on ARCH_EXYNOS4
+	select ARCH_HAS_BANDGAP
 	select PINCTRL_EXYNOS
 	select S5P_PM if PM
 	select S5P_SLEEP if PM
@@ -60,6 +62,7 @@ config SOC_EXYNOS4412
 	bool "SAMSUNG EXYNOS4412"
 	default y
 	depends on ARCH_EXYNOS4
+	select ARCH_HAS_BANDGAP
 	select PINCTRL_EXYNOS
 	select SAMSUNG_DMADEV
 	help
@@ -69,6 +72,7 @@ config SOC_EXYNOS5250
 	bool "SAMSUNG EXYNOS5250"
 	default y
 	depends on ARCH_EXYNOS5
+	select ARCH_HAS_BANDGAP
 	select PINCTRL_EXYNOS
 	select PM_GENERIC_DOMAINS if PM
 	select S5P_PM if PM
@@ -93,9 +97,10 @@ config SOC_EXYNOS5440
 	default y
 	depends on ARCH_EXYNOS5
 	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+	select ARCH_HAS_BANDGAP
 	select ARCH_HAS_OPP
-	select HAVE_ARM_ARCH_TIMER
 	select AUTO_ZRELADDR
+	select HAVE_ARM_ARCH_TIMER
 	select MIGHT_HAVE_PCI
 	select PCI_DOMAINS if PCI
 	select PINCTRL_EXYNOS5440
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 972490f..8646a14 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -17,7 +17,6 @@
 
 void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
 void exynos_init_time(void);
-extern unsigned long xxti_f, xusbxti_f;
 
 struct map_desc;
 void exynos_init_io(void);
@@ -25,56 +24,14 @@ void exynos4_restart(enum reboot_mode mode, const char *cmd);
 void exynos5_restart(enum reboot_mode mode, const char *cmd);
 void exynos_init_late(void);
 
-/* ToDo: remove these after migrating legacy exynos4 platforms to dt */
-void exynos4_clk_init(struct device_node *np, int is_exynos4210, void __iomem *reg_base, unsigned long xom);
-void exynos4_clk_register_fixed_ext(unsigned long, unsigned long);
-
 void exynos_firmware_init(void);
 
-void exynos_set_timer_source(u8 channels);
-
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
 static inline int exynos_pm_late_initcall(void) { return 0; }
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS4
-void exynos4_register_clocks(void);
-void exynos4_setup_clocks(void);
-
-#else
-#define exynos4_register_clocks()
-#define exynos4_setup_clocks()
-#endif
-
-#ifdef CONFIG_ARCH_EXYNOS5
-void exynos5_register_clocks(void);
-void exynos5_setup_clocks(void);
-
-#else
-#define exynos5_register_clocks()
-#define exynos5_setup_clocks()
-#endif
-
-#ifdef CONFIG_CPU_EXYNOS4210
-void exynos4210_register_clocks(void);
-
-#else
-#define exynos4210_register_clocks()
-#endif
-
-#ifdef CONFIG_SOC_EXYNOS4212
-void exynos4212_register_clocks(void);
-
-#else
-#define exynos4212_register_clocks()
-#endif
-
-struct device_node;
-void combiner_init(void __iomem *combiner_base, struct device_node *np,
-			unsigned int max_nr, int irq_base);
-
 extern struct smp_operations exynos_smp_ops;
 
 extern void exynos_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S
index c169f0c..02247f3 100644
--- a/arch/arm/mach-footbridge/include/mach/debug-macro.S
+++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S
@@ -13,20 +13,6 @@
 
 #include <asm/hardware/dec21285.h>
 
-#ifndef CONFIG_DEBUG_DC21285_PORT
-	/* For NetWinder debugging */
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x000003f8
-		orr	\rv, \rp, #0xfe000000	@ virtual
-		orr	\rv, \rv, #0x00e00000	@ virtual
-		orr	\rp, \rp, #0x7c000000	@ physical
-		.endm
-
-#define UART_SHIFT	0
-#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.S>
-
-#else
 #include <mach/hardware.h>
 	/* For EBSA285 debugging */
 		.equ	dc21285_high, ARMCSR_BASE & 0xff000000
@@ -54,4 +40,3 @@
 
 		.macro	waituart,rd,rx
 		.endm
-#endif
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S
deleted file mode 100644
index 8376707..0000000
--- a/arch/arm/mach-gemini/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <mach/hardware.h>
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =GEMINI_UART_BASE			@ physical
-	ldr	\rv, =IO_ADDRESS(GEMINI_UART_BASE)	@ virtual
-	.endm
-
-#define UART_SHIFT	2
-#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index cd9fcb1..6acbdab 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -12,7 +12,7 @@ config ARCH_HIGHBANK
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select MAILBOX
 	select PL320_MBOX
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index f546560..29a8af6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,6 +1,7 @@
 config ARCH_MXC
 	bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
 	select ARCH_REQUIRE_GPIOLIB
+	select ARM_CPU_SUSPEND if PM
 	select ARM_PATCH_PHYS_VIRT
 	select AUTO_ZRELADDR if !ZBOOT_ROM
 	select CLKDEV_LOOKUP
@@ -8,6 +9,7 @@ config ARCH_MXC
 	select GENERIC_ALLOCATOR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
+	select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
 	select MULTI_IRQ_HANDLER
 	select SPARSE_IRQ
 	select USE_OF
@@ -785,7 +787,6 @@ config SOC_IMX6Q
 	bool "i.MX6 Quad/DualLite support"
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_OPP
-	select ARM_CPU_SUSPEND if PM
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_764369 if SMP
 	select ARM_ERRATA_775420
@@ -793,7 +794,7 @@ config SOC_IMX6Q
 	select COMMON_CLK
 	select CPU_V7
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_IMX_ANATOP
 	select HAVE_IMX_GPC
 	select HAVE_IMX_MMDC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e20f22d..5383c58 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -15,7 +15,8 @@ imx5-pm-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y)
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
-			    clk-pfd.o clk-busy.o clk.o
+			    clk-pfd.o clk-busy.o clk.o \
+			    clk-fixup-div.o clk-fixup-mux.o
 
 obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
diff --git a/arch/arm/mach-imx/clk-fixup-div.c b/arch/arm/mach-imx/clk-fixup-div.c
new file mode 100644
index 0000000..21db020
--- /dev/null
+++ b/arch/arm/mach-imx/clk-fixup-div.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "clk.h"
+
+#define to_clk_div(_hw) container_of(_hw, struct clk_divider, hw)
+#define div_mask(d)	((1 << (d->width)) - 1)
+
+/**
+ * struct clk_fixup_div - imx integer fixup divider clock
+ * @divider: the parent class
+ * @ops: pointer to clk_ops of parent class
+ * @fixup: a hook to fixup the write value
+ *
+ * The imx fixup divider clock is a subclass of basic clk_divider
+ * with an addtional fixup hook.
+ */
+struct clk_fixup_div {
+	struct clk_divider divider;
+	const struct clk_ops *ops;
+	void (*fixup)(u32 *val);
+};
+
+static inline struct clk_fixup_div *to_clk_fixup_div(struct clk_hw *hw)
+{
+	struct clk_divider *divider = to_clk_div(hw);
+
+	return container_of(divider, struct clk_fixup_div, divider);
+}
+
+static unsigned long clk_fixup_div_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);
+
+	return fixup_div->ops->recalc_rate(&fixup_div->divider.hw, parent_rate);
+}
+
+static long clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *prate)
+{
+	struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);
+
+	return fixup_div->ops->round_rate(&fixup_div->divider.hw, rate, prate);
+}
+
+static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);
+	struct clk_divider *div = to_clk_div(hw);
+	unsigned int divider, value;
+	unsigned long flags = 0;
+	u32 val;
+
+	divider = parent_rate / rate;
+
+	/* Zero based divider */
+	value = divider - 1;
+
+	if (value > div_mask(div))
+		value = div_mask(div);
+
+	spin_lock_irqsave(div->lock, flags);
+
+	val = readl(div->reg);
+	val &= ~(div_mask(div) << div->shift);
+	val |= value << div->shift;
+	fixup_div->fixup(&val);
+	writel(val, div->reg);
+
+	spin_unlock_irqrestore(div->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops clk_fixup_div_ops = {
+	.recalc_rate = clk_fixup_div_recalc_rate,
+	.round_rate = clk_fixup_div_round_rate,
+	.set_rate = clk_fixup_div_set_rate,
+};
+
+struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
+				  void __iomem *reg, u8 shift, u8 width,
+				  void (*fixup)(u32 *val))
+{
+	struct clk_fixup_div *fixup_div;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	if (!fixup)
+		return ERR_PTR(-EINVAL);
+
+	fixup_div = kzalloc(sizeof(*fixup_div), GFP_KERNEL);
+	if (!fixup_div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_fixup_div_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent ? &parent : NULL;
+	init.num_parents = parent ? 1 : 0;
+
+	fixup_div->divider.reg = reg;
+	fixup_div->divider.shift = shift;
+	fixup_div->divider.width = width;
+	fixup_div->divider.lock = &imx_ccm_lock;
+	fixup_div->divider.hw.init = &init;
+	fixup_div->ops = &clk_divider_ops;
+	fixup_div->fixup = fixup;
+
+	clk = clk_register(NULL, &fixup_div->divider.hw);
+	if (IS_ERR(clk))
+		kfree(fixup_div);
+
+	return clk;
+}
diff --git a/arch/arm/mach-imx/clk-fixup-mux.c b/arch/arm/mach-imx/clk-fixup-mux.c
new file mode 100644
index 0000000..deb4b80
--- /dev/null
+++ b/arch/arm/mach-imx/clk-fixup-mux.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "clk.h"
+
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+
+/**
+ * struct clk_fixup_mux - imx integer fixup multiplexer clock
+ * @mux: the parent class
+ * @ops: pointer to clk_ops of parent class
+ * @fixup: a hook to fixup the write value
+ *
+ * The imx fixup multiplexer clock is a subclass of basic clk_mux
+ * with an addtional fixup hook.
+ */
+struct clk_fixup_mux {
+	struct clk_mux mux;
+	const struct clk_ops *ops;
+	void (*fixup)(u32 *val);
+};
+
+static inline struct clk_fixup_mux *to_clk_fixup_mux(struct clk_hw *hw)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+
+	return container_of(mux, struct clk_fixup_mux, mux);
+}
+
+static u8 clk_fixup_mux_get_parent(struct clk_hw *hw)
+{
+	struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw);
+
+	return fixup_mux->ops->get_parent(&fixup_mux->mux.hw);
+}
+
+static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw);
+	struct clk_mux *mux = to_clk_mux(hw);
+	unsigned long flags = 0;
+	u32 val;
+
+	spin_lock_irqsave(mux->lock, flags);
+
+	val = readl(mux->reg);
+	val &= ~(mux->mask << mux->shift);
+	val |= index << mux->shift;
+	fixup_mux->fixup(&val);
+	writel(val, mux->reg);
+
+	spin_unlock_irqrestore(mux->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops clk_fixup_mux_ops = {
+	.get_parent = clk_fixup_mux_get_parent,
+	.set_parent = clk_fixup_mux_set_parent,
+};
+
+struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
+			      u8 shift, u8 width, const char **parents,
+			      int num_parents, void (*fixup)(u32 *val))
+{
+	struct clk_fixup_mux *fixup_mux;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	if (!fixup)
+		return ERR_PTR(-EINVAL);
+
+	fixup_mux = kzalloc(sizeof(*fixup_mux), GFP_KERNEL);
+	if (!fixup_mux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_fixup_mux_ops;
+	init.parent_names = parents;
+	init.num_parents = num_parents;
+
+	fixup_mux->mux.reg = reg;
+	fixup_mux->mux.shift = shift;
+	fixup_mux->mux.mask = BIT(width) - 1;
+	fixup_mux->mux.lock = &imx_ccm_lock;
+	fixup_mux->mux.hw.init = &init;
+	fixup_mux->ops = &clk_mux_ops;
+	fixup_mux->fixup = fixup;
+
+	clk = clk_register(NULL, &fixup_mux->mux.hw);
+	if (IS_ERR(clk))
+		kfree(fixup_mux);
+
+	return clk;
+}
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 9afac26..1a56a33 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -119,7 +119,7 @@ enum imx5_clks {
 	srtc_gate, pata_gate, sata_gate, spdif_xtal_sel, spdif0_sel,
 	spdif1_sel, spdif0_pred, spdif0_podf, spdif1_pred, spdif1_podf,
 	spdif0_com_s, spdif1_com_sel, spdif0_gate, spdif1_gate, spdif_ipg_gate,
-	clk_max
+	ocram, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -506,6 +506,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 				mx53_can_sel, ARRAY_SIZE(mx53_can_sel));
 	clk[can1_serial_gate] = imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22);
 	clk[can1_ipg_gate] = imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20);
+	clk[ocram] = imx_clk_gate2("ocram", "ahb", MXC_CCM_CCGR6, 2);
 	clk[can2_serial_gate] = imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8);
 	clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
 	clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 86567d9..9181a24 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -206,6 +206,17 @@ static const char *vpu_axi_sels[]	= { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m",
 static const char *cko1_sels[]	= { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
 				    "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
 				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", };
+static const char *cko2_sels[] = {
+	"mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
+	"gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
+	"usdhc3", "dummy", "arm", "ipu1",
+	"ipu2", "vdo_axi", "osc", "gpu2d_core",
+	"gpu3d_core", "usdhc2", "ssi1", "ssi2",
+	"ssi3", "gpu3d_shader", "vpu_axi", "can_root",
+	"ldb_di0", "ldb_di1", "esai", "eim_slow",
+	"uart_serial", "spdif", "asrc", "hsi_tx",
+};
+static const char *cko_sels[] = { "cko1", "cko2", };
 
 enum mx6q_clks {
 	dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -239,7 +250,8 @@ enum mx6q_clks {
 	pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
 	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
 	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
-	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, clk_max
+	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
+	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -276,6 +288,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	struct device_node *np;
 	void __iomem *base;
 	int i, irq;
+	int ret;
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[ckil] = imx_obtain_fixed_clock("ckil", 0);
@@ -384,19 +397,21 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[ipu2_di1_sel]     = imx_clk_mux("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels));
 	clk[hsi_tx_sel]       = imx_clk_mux("hsi_tx_sel",       base + 0x30, 28, 1, hsi_tx_sels,       ARRAY_SIZE(hsi_tx_sels));
 	clk[pcie_axi_sel]     = imx_clk_mux("pcie_axi_sel",     base + 0x18, 10, 1, pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
-	clk[ssi1_sel]         = imx_clk_mux("ssi1_sel",         base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-	clk[ssi2_sel]         = imx_clk_mux("ssi2_sel",         base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-	clk[ssi3_sel]         = imx_clk_mux("ssi3_sel",         base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-	clk[usdhc1_sel]       = imx_clk_mux("usdhc1_sel",       base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clk[usdhc2_sel]       = imx_clk_mux("usdhc2_sel",       base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clk[usdhc3_sel]       = imx_clk_mux("usdhc3_sel",       base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clk[usdhc4_sel]       = imx_clk_mux("usdhc4_sel",       base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+	clk[ssi1_sel]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
+	clk[ssi2_sel]         = imx_clk_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
+	clk[ssi3_sel]         = imx_clk_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
+	clk[usdhc1_sel]       = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
+	clk[usdhc2_sel]       = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
+	clk[usdhc3_sel]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
+	clk[usdhc4_sel]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
 	clk[enfc_sel]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
-	clk[emi_sel]          = imx_clk_mux("emi_sel",          base + 0x1c, 27, 2, emi_sels,          ARRAY_SIZE(emi_sels));
-	clk[emi_slow_sel]     = imx_clk_mux("emi_slow_sel",     base + 0x1c, 29, 2, emi_slow_sels,     ARRAY_SIZE(emi_slow_sels));
+	clk[emi_sel]          = imx_clk_fixup_mux("emi_sel",      base + 0x1c, 27, 2, emi_sels,        ARRAY_SIZE(emi_sels),          imx_cscmr1_fixup);
+	clk[emi_slow_sel]     = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels,   ARRAY_SIZE(emi_slow_sels),     imx_cscmr1_fixup);
 	clk[vdo_axi_sel]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
 	clk[vpu_axi_sel]      = imx_clk_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
 	clk[cko1_sel]         = imx_clk_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
+	clk[cko2_sel]         = imx_clk_mux("cko2_sel",         base + 0x60, 16, 5, cko2_sels,         ARRAY_SIZE(cko2_sels));
+	clk[cko]              = imx_clk_mux("cko",              base + 0x60, 8, 1,  cko_sels,          ARRAY_SIZE(cko_sels));
 
 	/*                              name         reg      shift width busy: reg, shift parent_names  num_parents */
 	clk[periph]  = imx_clk_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
@@ -406,7 +421,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[periph_clk2]      = imx_clk_divider("periph_clk2",      "periph_clk2_sel",   base + 0x14, 27, 3);
 	clk[periph2_clk2]     = imx_clk_divider("periph2_clk2",     "periph2_clk2_sel",  base + 0x14, 0,  3);
 	clk[ipg]              = imx_clk_divider("ipg",              "ahb",               base + 0x14, 8,  2);
-	clk[ipg_per]          = imx_clk_divider("ipg_per",          "ipg",               base + 0x1c, 0,  6);
+	clk[ipg_per]          = imx_clk_fixup_divider("ipg_per",    "ipg",               base + 0x1c, 0,  6, imx_cscmr1_fixup);
 	clk[esai_pred]        = imx_clk_divider("esai_pred",        "esai_sel",          base + 0x28, 9,  3);
 	clk[esai_podf]        = imx_clk_divider("esai_podf",        "esai_pred",         base + 0x28, 25, 3);
 	clk[asrc_pred]        = imx_clk_divider("asrc_pred",        "asrc_sel",          base + 0x30, 12, 3);
@@ -442,10 +457,11 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[usdhc4_podf]      = imx_clk_divider("usdhc4_podf",      "usdhc4_sel",        base + 0x24, 22, 3);
 	clk[enfc_pred]        = imx_clk_divider("enfc_pred",        "enfc_sel",          base + 0x2c, 18, 3);
 	clk[enfc_podf]        = imx_clk_divider("enfc_podf",        "enfc_pred",         base + 0x2c, 21, 6);
-	clk[emi_podf]         = imx_clk_divider("emi_podf",         "emi_sel",           base + 0x1c, 20, 3);
-	clk[emi_slow_podf]    = imx_clk_divider("emi_slow_podf",    "emi_slow_sel",      base + 0x1c, 23, 3);
+	clk[emi_podf]         = imx_clk_fixup_divider("emi_podf",   "emi_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
+	clk[emi_slow_podf]    = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
 	clk[vpu_axi_podf]     = imx_clk_divider("vpu_axi_podf",     "vpu_axi_sel",       base + 0x24, 25, 3);
 	clk[cko1_podf]        = imx_clk_divider("cko1_podf",        "cko1_sel",          base + 0x60, 4,  3);
+	clk[cko2_podf]        = imx_clk_divider("cko2_podf",        "cko2_sel",          base + 0x60, 21, 3);
 
 	/*                                            name                 parent_name    reg        shift width busy: reg, shift */
 	clk[axi]               = imx_clk_busy_divider("axi",               "axi_sel",     base + 0x14, 16,  3,   base + 0x48, 0);
@@ -486,6 +502,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[i2c3]         = imx_clk_gate2("i2c3",          "ipg_per",           base + 0x70, 10);
 	clk[iim]          = imx_clk_gate2("iim",           "ipg",               base + 0x70, 12);
 	clk[enfc]         = imx_clk_gate2("enfc",          "enfc_podf",         base + 0x70, 14);
+	clk[vdoa]         = imx_clk_gate2("vdoa",          "vdo_axi",           base + 0x70, 26);
 	clk[ipu1]         = imx_clk_gate2("ipu1",          "ipu1_podf",         base + 0x74, 0);
 	clk[ipu1_di0]     = imx_clk_gate2("ipu1_di0",      "ipu1_di0_sel",      base + 0x74, 2);
 	clk[ipu1_di1]     = imx_clk_gate2("ipu1_di1",      "ipu1_di1_sel",      base + 0x74, 4);
@@ -521,6 +538,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[sata]         = imx_clk_gate2("sata",          "ipg",               base + 0x7c, 4);
 	clk[sdma]         = imx_clk_gate2("sdma",          "ahb",               base + 0x7c, 6);
 	clk[spba]         = imx_clk_gate2("spba",          "ipg",               base + 0x7c, 12);
+	clk[spdif]        = imx_clk_gate2("spdif",         "spdif_podf",    	base + 0x7c, 14);
 	clk[ssi1_ipg]     = imx_clk_gate2("ssi1_ipg",      "ipg",               base + 0x7c, 18);
 	clk[ssi2_ipg]     = imx_clk_gate2("ssi2_ipg",      "ipg",               base + 0x7c, 20);
 	clk[ssi3_ipg]     = imx_clk_gate2("ssi3_ipg",      "ipg",               base + 0x7c, 22);
@@ -535,6 +553,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[vdo_axi]      = imx_clk_gate2("vdo_axi",       "vdo_axi_sel",       base + 0x80, 12);
 	clk[vpu_axi]      = imx_clk_gate2("vpu_axi",       "vpu_axi_podf",      base + 0x80, 14);
 	clk[cko1]         = imx_clk_gate("cko1",           "cko1_podf",         base + 0x60, 7);
+	clk[cko2]         = imx_clk_gate("cko2",           "cko2_podf",         base + 0x60, 24);
 
 	for (i = 0; i < ARRAY_SIZE(clk); i++)
 		if (IS_ERR(clk[i]))
@@ -554,7 +573,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL);
 	clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL);
 
-	if (imx6q_revision() != IMX_CHIP_REVISION_1_0) {
+	if ((imx6q_revision() != IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) {
 		clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
 		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
 	}
@@ -574,6 +593,16 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 		clk_prepare_enable(clk[usbphy2_gate]);
 	}
 
+	/*
+	 * Let's initially set up CLKO with OSC24M, since this configuration
+	 * is widely used by imx6q board designs to clock audio codec.
+	 */
+	ret = clk_set_parent(clk[cko2_sel], clk[osc]);
+	if (!ret)
+		ret = clk_set_parent(clk[cko], clk[cko2]);
+	if (ret)
+		pr_warn("failed to set up CLKO: %d\n", ret);
+
 	/* Set initial power mode */
 	imx6q_set_lpm(WAIT_CLOCKED);
 
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index a307ac2..a5c3c5d 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -138,14 +138,14 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	clks[IMX6SL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
 	clks[IMX6SL_CLK_CSI_SEL]          = imx_clk_mux("csi_sel",          base + 0x3c, 9,  2, csi_lcdif_sels,    ARRAY_SIZE(csi_lcdif_sels));
 	clks[IMX6SL_CLK_LCDIF_AXI_SEL]    = imx_clk_mux("lcdif_axi_sel",    base + 0x3c, 14, 2, csi_lcdif_sels,    ARRAY_SIZE(csi_lcdif_sels));
-	clks[IMX6SL_CLK_USDHC1_SEL]       = imx_clk_mux("usdhc1_sel",       base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clks[IMX6SL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel",       base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clks[IMX6SL_CLK_USDHC3_SEL]       = imx_clk_mux("usdhc3_sel",       base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clks[IMX6SL_CLK_USDHC4_SEL]       = imx_clk_mux("usdhc4_sel",       base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clks[IMX6SL_CLK_SSI1_SEL]         = imx_clk_mux("ssi1_sel",         base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-	clks[IMX6SL_CLK_SSI2_SEL]         = imx_clk_mux("ssi2_sel",         base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-	clks[IMX6SL_CLK_SSI3_SEL]         = imx_clk_mux("ssi3_sel",         base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-	clks[IMX6SL_CLK_PERCLK_SEL]       = imx_clk_mux("perclk_sel",       base + 0x1c, 6,  1, perclk_sels,       ARRAY_SIZE(perclk_sels));
+	clks[IMX6SL_CLK_USDHC1_SEL]       = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_USDHC2_SEL]       = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_USDHC3_SEL]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_USDHC4_SEL]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_SSI1_SEL]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_SSI2_SEL]         = imx_clk_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_SSI3_SEL]         = imx_clk_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
+	clks[IMX6SL_CLK_PERCLK_SEL]       = imx_clk_fixup_mux("perclk_sel", base + 0x1c, 6,  1, perclk_sels,       ARRAY_SIZE(perclk_sels), imx_cscmr1_fixup);
 	clks[IMX6SL_CLK_PXP_AXI_SEL]      = imx_clk_mux("pxp_axi_sel",      base + 0x34, 6,  3, epdc_pxp_sels,     ARRAY_SIZE(epdc_pxp_sels));
 	clks[IMX6SL_CLK_EPDC_AXI_SEL]     = imx_clk_mux("epdc_axi_sel",     base + 0x34, 15, 3, epdc_pxp_sels,     ARRAY_SIZE(epdc_pxp_sels));
 	clks[IMX6SL_CLK_GPU2D_OVG_SEL]    = imx_clk_mux("gpu2d_ovg_sel",    base + 0x18, 4,  2, gpu2d_ovg_sels,    ARRAY_SIZE(gpu2d_ovg_sels));
@@ -179,14 +179,14 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	clks[IMX6SL_CLK_SSI2_PODF]         = imx_clk_divider("ssi2_podf",         "ssi2_pred",         base + 0x2c, 0,  6);
 	clks[IMX6SL_CLK_SSI3_PRED]         = imx_clk_divider("ssi3_pred",         "ssi3_sel",          base + 0x28, 22, 3);
 	clks[IMX6SL_CLK_SSI3_PODF]         = imx_clk_divider("ssi3_podf",         "ssi3_pred",         base + 0x28, 16, 6);
-	clks[IMX6SL_CLK_PERCLK]            = imx_clk_divider("perclk",            "perclk_sel",        base + 0x1c, 0,  6);
+	clks[IMX6SL_CLK_PERCLK]            = imx_clk_fixup_divider("perclk",      "perclk_sel",        base + 0x1c, 0,  6, imx_cscmr1_fixup);
 	clks[IMX6SL_CLK_PXP_AXI_PODF]      = imx_clk_divider("pxp_axi_podf",      "pxp_axi_sel",       base + 0x34, 3,  3);
 	clks[IMX6SL_CLK_EPDC_AXI_PODF]     = imx_clk_divider("epdc_axi_podf",     "epdc_axi_sel",      base + 0x34, 12, 3);
 	clks[IMX6SL_CLK_GPU2D_OVG_PODF]    = imx_clk_divider("gpu2d_ovg_podf",    "gpu2d_ovg_sel",     base + 0x18, 26, 3);
 	clks[IMX6SL_CLK_GPU2D_PODF]        = imx_clk_divider("gpu2d_podf",        "gpu2d_sel",         base + 0x18, 29, 3);
 	clks[IMX6SL_CLK_LCDIF_PIX_PRED]    = imx_clk_divider("lcdif_pix_pred",    "lcdif_pix_sel",     base + 0x38, 3,  3);
 	clks[IMX6SL_CLK_EPDC_PIX_PRED]     = imx_clk_divider("epdc_pix_pred",     "epdc_pix_sel",      base + 0x38, 12, 3);
-	clks[IMX6SL_CLK_LCDIF_PIX_PODF]    = imx_clk_divider("lcdif_pix_podf",    "lcdif_pix_pred",    base + 0x1c, 20, 3);
+	clks[IMX6SL_CLK_LCDIF_PIX_PODF]    = imx_clk_fixup_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3, imx_cscmr1_fixup);
 	clks[IMX6SL_CLK_EPDC_PIX_PODF]     = imx_clk_divider("epdc_pix_podf",     "epdc_pix_pred",     base + 0x18, 23, 3);
 	clks[IMX6SL_CLK_SPDIF0_PRED]       = imx_clk_divider("spdif0_pred",       "spdif0_sel",        base + 0x30, 25, 3);
 	clks[IMX6SL_CLK_SPDIF0_PODF]       = imx_clk_divider("spdif0_podf",       "spdif0_pred",       base + 0x30, 22, 3);
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index a9fad5f..f6640b6 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -48,7 +48,7 @@ struct clk_pllv3 {
 static int clk_pllv3_prepare(struct clk_hw *hw)
 {
 	struct clk_pllv3 *pll = to_clk_pllv3(hw);
-	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+	unsigned long timeout;
 	u32 val;
 
 	val = readl_relaxed(pll->base);
@@ -59,12 +59,19 @@ static int clk_pllv3_prepare(struct clk_hw *hw)
 		val &= ~BM_PLL_POWER;
 	writel_relaxed(val, pll->base);
 
+	timeout = jiffies + msecs_to_jiffies(10);
 	/* Wait for PLL to lock */
-	while (!(readl_relaxed(pll->base) & BM_PLL_LOCK))
+	do {
+		if (readl_relaxed(pll->base) & BM_PLL_LOCK)
+			break;
 		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
+			break;
+	} while (1);
 
-	return 0;
+	if (readl_relaxed(pll->base) & BM_PLL_LOCK)
+		return 0;
+	else
+		return -ETIMEDOUT;
 }
 
 static void clk_pllv3_unprepare(struct clk_hw *hw)
diff --git a/arch/arm/mach-imx/clk.c b/arch/arm/mach-imx/clk.c
index 55bc80a..edc35df 100644
--- a/arch/arm/mach-imx/clk.c
+++ b/arch/arm/mach-imx/clk.c
@@ -37,3 +37,29 @@ struct clk * __init imx_obtain_fixed_clock(
 		clk = imx_clk_fixed(name, rate);
 	return clk;
 }
+
+/*
+ * This fixups the register CCM_CSCMR1 write value.
+ * The write/read/divider values of the aclk_podf field
+ * of that register have the relationship described by
+ * the following table:
+ *
+ * write value       read value        divider
+ * 3b'000            3b'110            7
+ * 3b'001            3b'111            8
+ * 3b'010            3b'100            5
+ * 3b'011            3b'101            6
+ * 3b'100            3b'010            3
+ * 3b'101            3b'011            4
+ * 3b'110            3b'000            1
+ * 3b'111            3b'001            2(default)
+ *
+ * That's why we do the xor operation below.
+ */
+#define CSCMR1_FIXUP	0x00600000
+
+void imx_cscmr1_fixup(u32 *val)
+{
+	*val ^= CSCMR1_FIXUP;
+	return;
+}
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 0e4e8bb..3451f1f 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -6,6 +6,8 @@
 
 extern spinlock_t imx_ccm_lock;
 
+extern void imx_cscmr1_fixup(u32 *val);
+
 struct clk *imx_clk_pllv1(const char *name, const char *parent,
 		void __iomem *base);
 
@@ -49,6 +51,14 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 			     u8 width, void __iomem *busy_reg, u8 busy_shift,
 			     const char **parent_names, int num_parents);
 
+struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
+				  void __iomem *reg, u8 shift, u8 width,
+				  void (*fixup)(u32 *val));
+
+struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
+			      u8 shift, u8 width, const char **parents,
+			      int num_parents, void (*fixup)(u32 *val));
+
 static inline struct clk *imx_clk_fixed(const char *name, int rate)
 {
 	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cb6c838..cdc9288 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -147,12 +147,10 @@ extern int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
-extern void imx51_pm_init(void);
-extern void imx53_pm_init(void);
+extern void imx5_pm_init(void);
 #else
 static inline void imx6q_pm_init(void) {}
-static inline void imx51_pm_init(void) {}
-static inline void imx53_pm_init(void) {}
+static inline void imx5_pm_init(void) {}
 #endif
 
 #ifdef CONFIG_NEON
@@ -161,6 +159,12 @@ extern int mx51_neon_fixup(void);
 static inline int mx51_neon_fixup(void) { return 0; }
 #endif
 
+#ifdef CONFIG_CACHE_L2X0
+extern void imx_init_l2cache(void);
+#else
+static inline void imx_init_l2cache(void) {}
+#endif
+
 extern struct smp_operations imx_smp_ops;
 
 #endif
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 7be13f8..2460d49 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -31,7 +31,7 @@
 #include <linux/regmap.h>
 #include <linux/micrel_phy.h>
 #include <linux/mfd/syscon.h>
-#include <asm/hardware/cache-l2x0.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
@@ -115,75 +115,62 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
 	return 0;
 }
 
-static void __init imx6q_sabrelite_cko1_setup(void)
+static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
 {
-	struct clk *cko1_sel, *ahb, *cko1;
-	unsigned long rate;
-
-	cko1_sel = clk_get_sys(NULL, "cko1_sel");
-	ahb = clk_get_sys(NULL, "ahb");
-	cko1 = clk_get_sys(NULL, "cko1");
-	if (IS_ERR(cko1_sel) || IS_ERR(ahb) || IS_ERR(cko1)) {
-		pr_err("cko1 setup failed!\n");
-		goto put_clk;
-	}
-	clk_set_parent(cko1_sel, ahb);
-	rate = clk_round_rate(cko1, 16000000);
-	clk_set_rate(cko1, rate);
-put_clk:
-	if (!IS_ERR(cko1_sel))
-		clk_put(cko1_sel);
-	if (!IS_ERR(ahb))
-		clk_put(ahb);
-	if (!IS_ERR(cko1))
-		clk_put(cko1);
+	phy_write(dev, 0x0d, device);
+	phy_write(dev, 0x0e, reg);
+	phy_write(dev, 0x0d, (1 << 14) | device);
+	phy_write(dev, 0x0e, val);
 }
 
-static void __init imx6q_sabrelite_init(void)
+static int ksz9031rn_phy_fixup(struct phy_device *dev)
 {
-	if (IS_BUILTIN(CONFIG_PHYLIB))
-		phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
-				ksz9021rn_phy_fixup);
-	imx6q_sabrelite_cko1_setup();
+	/*
+	 * min rx data delay, max rx/tx clock delay,
+	 * min rx/tx control delay
+	 */
+	mmd_write_reg(dev, 2, 4, 0);
+	mmd_write_reg(dev, 2, 5, 0);
+	mmd_write_reg(dev, 2, 8, 0x003ff);
+
+	return 0;
 }
 
-static void __init imx6q_sabresd_cko1_setup(void)
+static int ar8031_phy_fixup(struct phy_device *dev)
 {
-	struct clk *cko1_sel, *pll4, *pll4_post, *cko1;
-	unsigned long rate;
-
-	cko1_sel = clk_get_sys(NULL, "cko1_sel");
-	pll4 = clk_get_sys(NULL, "pll4_audio");
-	pll4_post = clk_get_sys(NULL, "pll4_post_div");
-	cko1 = clk_get_sys(NULL, "cko1");
-	if (IS_ERR(cko1_sel) || IS_ERR(pll4)
-			|| IS_ERR(pll4_post) || IS_ERR(cko1)) {
-		pr_err("cko1 setup failed!\n");
-		goto put_clk;
-	}
-	/*
-	 * Setting pll4 at 768MHz (24MHz * 32)
-	 * So its child clock can get 24MHz easily
-	 */
-	clk_set_rate(pll4, 768000000);
-
-	clk_set_parent(cko1_sel, pll4_post);
-	rate = clk_round_rate(cko1, 24000000);
-	clk_set_rate(cko1, rate);
-put_clk:
-	if (!IS_ERR(cko1_sel))
-		clk_put(cko1_sel);
-	if (!IS_ERR(pll4_post))
-		clk_put(pll4_post);
-	if (!IS_ERR(pll4))
-		clk_put(pll4);
-	if (!IS_ERR(cko1))
-		clk_put(cko1);
+	u16 val;
+
+	/* To enable AR8031 output a 125MHz clk from CLK_25M */
+	phy_write(dev, 0xd, 0x7);
+	phy_write(dev, 0xe, 0x8016);
+	phy_write(dev, 0xd, 0x4007);
+
+	val = phy_read(dev, 0xe);
+	val &= 0xffe3;
+	val |= 0x18;
+	phy_write(dev, 0xe, val);
+
+	/* introduce tx clock delay */
+	phy_write(dev, 0x1d, 0x5);
+	val = phy_read(dev, 0x1e);
+	val |= 0x0100;
+	phy_write(dev, 0x1e, val);
+
+	return 0;
 }
 
-static void __init imx6q_sabresd_init(void)
+#define PHY_ID_AR8031	0x004dd074
+
+static void __init imx6q_enet_phy_init(void)
 {
-	imx6q_sabresd_cko1_setup();
+	if (IS_BUILTIN(CONFIG_PHYLIB)) {
+		phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
+				ksz9021rn_phy_fixup);
+		phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
+				ksz9031rn_phy_fixup);
+		phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
+				ar8031_phy_fixup);
+	}
 }
 
 static void __init imx6q_1588_init(void)
@@ -192,7 +179,9 @@ static void __init imx6q_1588_init(void)
 
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
-		regmap_update_bits(gpr, 0x4, 1 << 21, 1 << 21);
+		regmap_update_bits(gpr, IOMUXC_GPR1,
+				IMX6Q_GPR1_ENET_CLK_SEL_MASK,
+				IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
 	else
 		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
 
@@ -204,11 +193,7 @@ static void __init imx6q_usb_init(void)
 
 static void __init imx6q_init_machine(void)
 {
-	if (of_machine_is_compatible("fsl,imx6q-sabrelite"))
-		imx6q_sabrelite_init();
-	else if (of_machine_is_compatible("fsl,imx6q-sabresd") ||
-			of_machine_is_compatible("fsl,imx6dl-sabresd"))
-		imx6q_sabresd_init();
+	imx6q_enet_phy_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
@@ -297,44 +282,10 @@ static void __init imx6q_map_io(void)
 	imx_scu_map_io();
 }
 
-#ifdef CONFIG_CACHE_L2X0
-static void __init imx6q_init_l2cache(void)
-{
-	void __iomem *l2x0_base;
-	struct device_node *np;
-	unsigned int val;
-
-	np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
-	if (!np)
-		goto out;
-
-	l2x0_base = of_iomap(np, 0);
-	if (!l2x0_base) {
-		of_node_put(np);
-		goto out;
-	}
-
-	/* Configure the L2 PREFETCH and POWER registers */
-	val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
-	val |= 0x70800000;
-	writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL);
-	val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
-	writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL);
-
-	iounmap(l2x0_base);
-	of_node_put(np);
-
-out:
-	l2x0_of_init(0, ~0UL);
-}
-#else
-static inline void imx6q_init_l2cache(void) {}
-#endif
-
 static void __init imx6q_init_irq(void)
 {
 	imx6q_init_revision();
-	imx6q_init_l2cache();
+	imx_init_l2cache();
 	imx_src_init();
 	imx_gpc_init();
 	irqchip_init();
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 132db26..0d75dc5 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -11,7 +11,6 @@
 #include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
@@ -26,7 +25,7 @@ static void __init imx6sl_init_machine(void)
 
 static void __init imx6sl_init_irq(void)
 {
-	l2x0_of_init(0, ~0UL);
+	imx_init_l2cache();
 	imx_src_init();
 	imx_gpc_init();
 	irqchip_init();
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index cf193d8..a8229b7 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -153,10 +153,10 @@ void __init imx51_soc_init(void)
 void __init imx51_init_late(void)
 {
 	mx51_neon_fixup();
-	imx51_pm_init();
+	imx5_pm_init();
 }
 
 void __init imx53_init_late(void)
 {
-	imx53_pm_init();
+	imx5_pm_init();
 }
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index 82e79c6..58aeaf5 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -169,14 +169,9 @@ static int __init imx5_pm_common_init(void)
 	return imx5_cpuidle_init();
 }
 
-void __init imx51_pm_init(void)
+void __init imx5_pm_init(void)
 {
 	int ret = imx5_pm_common_init();
 	if (!ret)
 		suspend_set_ops(&mx5_suspend_ops);
 }
-
-void __init imx53_pm_init(void)
-{
-	imx5_pm_common_init();
-}
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
index 6fe81bb..64ff37e 100644
--- a/arch/arm/mach-imx/system.c
+++ b/arch/arm/mach-imx/system.c
@@ -27,6 +27,7 @@
 #include <asm/system_misc.h>
 #include <asm/proc-fns.h>
 #include <asm/mach-types.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #include "common.h"
 #include "hardware.h"
@@ -95,3 +96,35 @@ void __init mxc_arch_reset_init_dt(void)
 
 	clk_prepare(wdog_clk);
 }
+
+#ifdef CONFIG_CACHE_L2X0
+void __init imx_init_l2cache(void)
+{
+	void __iomem *l2x0_base;
+	struct device_node *np;
+	unsigned int val;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
+	if (!np)
+		goto out;
+
+	l2x0_base = of_iomap(np, 0);
+	if (!l2x0_base) {
+		of_node_put(np);
+		goto out;
+	}
+
+	/* Configure the L2 PREFETCH and POWER registers */
+	val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
+	val |= 0x70800000;
+	writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL);
+	val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
+	writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL);
+
+	iounmap(l2x0_base);
+	of_node_put(np);
+
+out:
+	l2x0_of_init(0, ~0UL);
+}
+#endif
diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S
deleted file mode 100644
index 411b116..0000000
--- a/arch/arm/mach-integrator/include/mach/debug-macro.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/* arch/arm/mach-integrator/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x16000000	@ physical base address
-		mov	\rv, #0xf0000000	@ virtual base
-		add	\rv, \rv, #0x16000000 >> 4
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-iop13xx/include/mach/debug-macro.S b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
deleted file mode 100644
index d869a6f..0000000
--- a/arch/arm/mach-iop13xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/arm/mach-iop13xx/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-	.macro	addruart, rp, rv, tmp
-	mov	\rp, #0x00002300
-	orr	\rp, \rp, #0x00000040
-	orr	\rv, \rp, #0xfe000000	@ virtual
-	orr	\rv, \rv, #0x00e80000
-	orr	\rp, \rp, #0xff000000	@ physical
-	orr	\rp, \rp, #0x00d80000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-iop32x/include/mach/debug-macro.S b/arch/arm/mach-iop32x/include/mach/debug-macro.S
deleted file mode 100644
index 363bdf9..0000000
--- a/arch/arm/mach-iop32x/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-iop32x/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0xfe000000	@ physical as well as virtual
-		orr	\rp, \rp, #0x00800000	@ location of the UART
-		mov	\rv, \rp
-		.endm
-
-#define UART_SHIFT	0
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-iop33x/include/mach/debug-macro.S b/arch/arm/mach-iop33x/include/mach/debug-macro.S
deleted file mode 100644
index 361be1f..0000000
--- a/arch/arm/mach-iop33x/include/mach/debug-macro.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x00ff0000
-		orr	\rp, \rp, #0x0000f700
-		orr	\rv, #0xfe000000	@ virtual
-		orr	\rp, #0xff000000	@ physical
-		.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
deleted file mode 100644
index ff686cb..0000000
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/* arch/arm/mach-ixp4xx/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-                .macro  addruart, rp, rv, tmp
-#ifdef __ARMEB__
-                mov     \rp, #3         @ Uart regs are at off set of 3 if
-					@ byte writes used - Big Endian.
-#else
-		mov	\rp, #0
-#endif
-		orr	\rv, \rp, #0xfe000000	@ virtual
-		orr	\rv, \rv, #0x00f00000
-                orr     \rp, \rp, #0xc8000000	@ physical
-                .endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 51a50e9..366d1a3 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -7,7 +7,6 @@ config ARCH_KEYSTONE
 	select HAVE_SMP
 	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
-	select HAVE_SCHED_CLOCK
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_ERRATA_798181 if SMP
 	help
diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c
index 14378e3..c122961 100644
--- a/arch/arm/mach-keystone/platsmp.c
+++ b/arch/arm/mach-keystone/platsmp.c
@@ -38,6 +38,5 @@ static int keystone_smp_boot_secondary(unsigned int cpu,
 }
 
 struct smp_operations keystone_smp_ops __initdata = {
-	.smp_init_cpus		= arm_dt_init_cpu_maps,
 	.smp_boot_secondary	= keystone_smp_boot_secondary,
 };
diff --git a/arch/arm/mach-keystone/smc.S b/arch/arm/mach-keystone/smc.S
index 9b9e4f7..d15de81 100644
--- a/arch/arm/mach-keystone/smc.S
+++ b/arch/arm/mach-keystone/smc.S
@@ -22,8 +22,7 @@
  * Return: Non zero value on failure
  */
 ENTRY(keystone_cpu_smc)
-	stmfd   sp!, {r4-r12, lr}
+	stmfd   sp!, {r4-r11, lr}
 	smc	#0
-	dsb
-	ldmfd   sp!, {r4-r12, pc}
+	ldmfd   sp!, {r4-r11, pc}
 ENDPROC(keystone_cpu_smc)
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index b634f96..780bca0 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -2,67 +2,32 @@ if ARCH_KIRKWOOD
 
 menu "Marvell Kirkwood Implementations"
 
+config KIRKWOOD_LEGACY
+	bool
+
 config MACH_D2NET_V2
 	bool "LaCie d2 Network v2 NAS Board"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  LaCie d2 Network v2 NAS.
 
-config MACH_DOCKSTAR
-	bool "Seagate FreeAgent DockStar"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Seagate FreeAgent DockStar.
-
-config MACH_ESATA_SHEEVAPLUG
-	bool "Marvell eSATA SheevaPlug Reference Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell eSATA SheevaPlug Reference Board.
-
-config MACH_GURUPLUG
-	bool "Marvell GuruPlug Reference Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell GuruPlug Reference Board.
-
-config MACH_INETSPACE_V2
-	bool "LaCie Internet Space v2 NAS Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  LaCie Internet Space v2 NAS.
-
-config MACH_MV88F6281GTW_GE
-	bool "Marvell 88F6281 GTW GE Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell 88F6281 GTW GE Board.
-
 config MACH_NET2BIG_V2
 	bool "LaCie 2Big Network v2 NAS Board"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  LaCie 2Big Network v2 NAS.
 
 config MACH_NET5BIG_V2
 	bool "LaCie 5Big Network v2 NAS Board"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  LaCie 5Big Network v2 NAS.
 
-config MACH_NETSPACE_MAX_V2
-	bool "LaCie Network Space Max v2 NAS Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  LaCie Network Space Max v2 NAS.
-
-config MACH_NETSPACE_V2
-	bool "LaCie Network Space v2 NAS Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  LaCie Network Space v2 NAS.
-
 config MACH_OPENRD
+	select KIRKWOOD_LEGACY
         bool
 
 config MACH_OPENRD_BASE
@@ -88,30 +53,28 @@ config MACH_OPENRD_ULTIMATE
 
 config MACH_RD88F6192_NAS
 	bool "Marvell RD-88F6192-NAS Reference Board"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell RD-88F6192-NAS Reference Board.
 
 config MACH_RD88F6281
 	bool "Marvell RD-88F6281 Reference Board"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell RD-88F6281 Reference Board.
 
-config MACH_SHEEVAPLUG
-	bool "Marvell SheevaPlug Reference Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell SheevaPlug Reference Board.
-
 config MACH_T5325
 	bool "HP t5325 Thin Client"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  HP t5325 Thin Client.
 
 config MACH_TS219
 	bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
@@ -119,6 +82,7 @@ config MACH_TS219
 
 config MACH_TS41X
 	bool "QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo NAS"
+	select KIRKWOOD_LEGACY
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo
@@ -129,6 +93,8 @@ comment "Device tree entries"
 config ARCH_KIRKWOOD_DT
 	bool "Marvell Kirkwood Flattened Device Tree"
 	select KIRKWOOD_CLK
+	select ORION_IRQCHIP
+	select ORION_TIMER
 	select POWER_SUPPLY
 	select POWER_RESET
 	select POWER_RESET_GPIO
@@ -139,20 +105,6 @@ config ARCH_KIRKWOOD_DT
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell Kirkwood using flattened device tree.
 
-config MACH_CLOUDBOX_DT
-	bool "LaCie CloudBox NAS (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the LaCie
-	  CloudBox NAS, using Flattened Device Tree.
-
-config MACH_DB88F628X_BP_DT
-	bool "Marvell DB-88F628x-BP Development Board (Flattened Device Tree)"
-	help
-	  Say 'Y' here if you want your kernel to support the Marvell
-	  DB-88F6281-BP and DB-88F6282-BP Development Board (Flattened
-	  Device Tree).
-
 config MACH_DLINK_KIRKWOOD_DT
 	bool "D-Link Kirkwood-based NAS (Flattened Device Tree)"
 	select ARCH_KIRKWOOD_DT
@@ -161,162 +113,12 @@ config MACH_DLINK_KIRKWOOD_DT
 	  Kirkwood-based D-Link NASes such as DNS-320 & DNS-325,
 	  using Flattened Device Tree.
 
-config MACH_DOCKSTAR_DT
-	bool "Seagate FreeAgent Dockstar (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Seagate FreeAgent Dockstar (Flattened Device Tree).
-
-config MACH_DREAMPLUG_DT
-	bool "Marvell DreamPlug (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell DreamPlug (Flattened Device Tree).
-
-config MACH_GOFLEXNET_DT
-	bool "Seagate GoFlex Net (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Seagate GoFlex Net (Flattened Device Tree).
-
-config MACH_GURUPLUG_DT
-	bool "Marvell GuruPlug Reference Board (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell GuruPlug Reference Board (Flattened Device Tree).
-
-config MACH_IB62X0_DT
-	bool "RaidSonic IB-NAS6210, IB-NAS6220 (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  RaidSonic IB-NAS6210 & IB-NAS6220 devices, using
-	  Flattened Device Tree.
-
-config MACH_ICONNECT_DT
-	bool "Iomega Iconnect (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here to enable Iomega Iconnect support.
-
-config MACH_INETSPACE_V2_DT
-	bool "LaCie Internet Space v2 NAS (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the LaCie
-	  Internet Space v2 NAS, using Flattened Device Tree.
-
-config MACH_IOMEGA_IX2_200_DT
-	bool "Iomega StorCenter ix2-200 (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Iomega StorCenter ix2-200 (Flattened Device Tree).
-
-config MACH_KM_KIRKWOOD_DT
-	bool "Keymile Kirkwood Reference Design (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
-
-config MACH_LSXL_DT
-	bool "Buffalo Linkstation LS-XHL, LS-CHLv2 (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	select POWER_RESET_RESTART
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Buffalo Linkstation LS-XHL & LS-CHLv2 devices, using
-	  Flattened Device Tree.
-
-config MACH_MPLCEC4_DT
-	bool "MPL CEC4 (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  MPL CEC4 (Flattened Device Tree).
-
-config MACH_NETSPACE_LITE_V2_DT
-	bool "LaCie Network Space Lite v2 NAS (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the LaCie
-	  Network Space Lite v2 NAS, using Flattened Device Tree.
-
-config MACH_NETSPACE_MAX_V2_DT
-	bool "LaCie Network Space Max v2 NAS (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the LaCie
-	  Network Space Max v2 NAS, using Flattened Device Tree.
-
-config MACH_NETSPACE_MINI_V2_DT
-	bool "LaCie Network Space Mini v2 NAS (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the LaCie
-	  Network Space Mini v2 NAS using Flattened Device Tree.
-
-	  This board is embedded in a product named CloudBox, which
-	  provides automatic backup on a 100GB cloud storage. This
-	  should not confused with a more recent LaCie NAS also named
-	  CloudBox. For this last, the disk capacity is 1TB or above.
-
-config MACH_NETSPACE_V2_DT
-	bool "LaCie Network Space v2 NAS (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the LaCie
-	  Network Space v2 NAS, using Flattened Device Tree.
-
-config MACH_OPENBLOCKS_A6_DT
-	bool "Plat'Home OpenBlocks A6 (Flattened Device Tree)"
+config MACH_MV88F6281GTW_GE_DT
+	bool "Marvell 88F6281 GTW GE Board (Flattened Device Tree)"
 	select ARCH_KIRKWOOD_DT
 	help
 	  Say 'Y' here if you want your kernel to support the
-	  Plat'Home OpenBlocks A6 (Flattened Device Tree).
-
-config MACH_READYNAS_DT
-	bool "NETGEAR ReadyNAS Duo v2 (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	select ARM_APPENDED_DTB
-	select ARM_ATAG_DTB_COMPAT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  NETGEAR ReadyNAS Duo v2 using Fattened Device Tree.
-
-config MACH_SHEEVAPLUG_DT
-	bool "Marvell (eSATA) SheevaPlug (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell (eSATA) SheevaPlug (Flattened Device Tree).
-
-config MACH_TOPKICK_DT
-	bool "USI Topkick (Flattened Device Tree)"
-	select ARCH_KIRKWOOD_DT
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  USI Topkick, using Flattened Device Tree
-
-config MACH_TS219_DT
-	bool "Device Tree for QNAP TS-11X, TS-21X NAS"
-	select ARCH_KIRKWOOD_DT
-	select ARM_APPENDED_DTB
-	select ARM_ATAG_DTB_COMPAT
-	select POWER_RESET_QNAP
-	help
-	  Say 'Y' here if you want your kernel to support the QNAP
-	  TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
-	  TS-219P+ Turbo NAS devices using Fattened Device Tree.
-	  There are two different Device Tree descriptions, depending
-	  on if the device is based on an if the board uses the MV6281
-	  or MV6282. If you have the wrong one, the buttons will not
-	  work.
+	  Marvell 88F6281 GTW GE Board (Flattened Device Tree).
 
 endmenu
 
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index ac4cd75..937d4e1 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -1,44 +1,15 @@
-obj-y				+= common.o irq.o pcie.o mpp.o
-
+obj-y				+= common.o pcie.o
+obj-$(CONFIG_KIRKWOOD_LEGACY)	+= irq.o mpp.o
 obj-$(CONFIG_MACH_D2NET_V2)		+= d2net_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_DOCKSTAR)		+= dockstar-setup.o
-obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG)	+= sheevaplug-setup.o
-obj-$(CONFIG_MACH_GURUPLUG)		+= guruplug-setup.o
-obj-$(CONFIG_MACH_INETSPACE_V2)		+= netspace_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_MV88F6281GTW_GE)	+= mv88f6281gtw_ge-setup.o
 obj-$(CONFIG_MACH_NET2BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_NET5BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_NETSPACE_MAX_V2)	+= netspace_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_NETSPACE_V2)		+= netspace_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_OPENRD)		+= openrd-setup.o
 obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
 obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
-obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
 obj-$(CONFIG_MACH_T5325)		+= t5325-setup.o
 obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
 
 obj-$(CONFIG_ARCH_KIRKWOOD_DT)		+= board-dt.o
-obj-$(CONFIG_MACH_CLOUDBOX_DT)		+= board-ns2.o
-obj-$(CONFIG_MACH_DB88F628X_BP_DT)	+= board-db88f628x-bp.o
 obj-$(CONFIG_MACH_DLINK_KIRKWOOD_DT)	+= board-dnskw.o
-obj-$(CONFIG_MACH_DOCKSTAR_DT)		+= board-dockstar.o
-obj-$(CONFIG_MACH_DREAMPLUG_DT)		+= board-dreamplug.o
-obj-$(CONFIG_MACH_GOFLEXNET_DT)		+= board-goflexnet.o
-obj-$(CONFIG_MACH_GURUPLUG_DT)		+= board-guruplug.o
-obj-$(CONFIG_MACH_IB62X0_DT)		+= board-ib62x0.o
-obj-$(CONFIG_MACH_ICONNECT_DT)		+= board-iconnect.o
-obj-$(CONFIG_MACH_INETSPACE_V2_DT)	+= board-ns2.o
-obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT)	+= board-iomega_ix2_200.o
-obj-$(CONFIG_MACH_KM_KIRKWOOD_DT)	+= board-km_kirkwood.o
-obj-$(CONFIG_MACH_LSXL_DT)		+= board-lsxl.o
-obj-$(CONFIG_MACH_MPLCEC4_DT)		+= board-mplcec4.o
-obj-$(CONFIG_MACH_NETSPACE_LITE_V2_DT)	+= board-ns2.o
-obj-$(CONFIG_MACH_NETSPACE_MAX_V2_DT)	+= board-ns2.o
-obj-$(CONFIG_MACH_NETSPACE_MINI_V2_DT)	+= board-ns2.o
-obj-$(CONFIG_MACH_NETSPACE_V2_DT)	+= board-ns2.o
-obj-$(CONFIG_MACH_OPENBLOCKS_A6_DT)	+= board-openblocks_a6.o
-obj-$(CONFIG_MACH_READYNAS_DT)		+= board-readynas.o
-obj-$(CONFIG_MACH_SHEEVAPLUG_DT)	+= board-sheevaplug.o
-obj-$(CONFIG_MACH_TOPKICK_DT)		+= board-usi_topkick.o
-obj-$(CONFIG_MACH_TS219_DT)		+= board-ts219.o tsx1x-common.o
+obj-$(CONFIG_MACH_MV88F6281GTW_GE_DT)	+= board-mv88f6281gtw_ge.o
diff --git a/arch/arm/mach-kirkwood/board-db88f628x-bp.c b/arch/arm/mach-kirkwood/board-db88f628x-bp.c
deleted file mode 100644
index 2f574bc..0000000
--- a/arch/arm/mach-kirkwood/board-db88f628x-bp.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Saeed Bishara <saeed@marvell.com>
- *
- * Marvell DB-88F628{1,2}-BP Development Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data db88f628x_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-void __init db88f628x_init(void)
-{
-	kirkwood_ge00_init(&db88f628x_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-dnskw.c b/arch/arm/mach-kirkwood/board-dnskw.c
index a1aa87f..2af7a95 100644
--- a/arch/arm/mach-kirkwood/board-dnskw.c
+++ b/arch/arm/mach-kirkwood/board-dnskw.c
@@ -14,14 +14,9 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mv643xx_eth.h>
 #include <linux/gpio.h>
 #include "common.h"
 
-static struct mv643xx_eth_platform_data dnskw_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
 /* Register any GPIO for output and set the value */
 static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
 {
@@ -36,8 +31,6 @@ static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
 
 void __init dnskw_init(void)
 {
-	kirkwood_ge00_init(&dnskw_ge00_data);
-
 	/* Set NAS to turn back on after a power failure */
 	dnskw_gpio_register(37, "dnskw:power:recover", 1);
 }
diff --git a/arch/arm/mach-kirkwood/board-dockstar.c b/arch/arm/mach-kirkwood/board-dockstar.c
deleted file mode 100644
index d7196db..0000000
--- a/arch/arm/mach-kirkwood/board-dockstar.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/board-dockstar.c
- *
- * Seagate FreeAgent Dockstar Board Init for drivers not converted to
- * flattened device tree yet.
- *
- * 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.
- *
- * Copied and modified for Seagate GoFlex Net support by
- * Joshua Coombs <josh.coombs@gmail.com> based on ArchLinux ARM's
- * GoFlex kernel patches.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data dockstar_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init dockstar_dt_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&dockstar_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c
deleted file mode 100644
index 0903242..0000000
--- a/arch/arm/mach-kirkwood/board-dreamplug.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
- *
- * arch/arm/mach-kirkwood/board-dreamplug.c
- *
- * Marvell DreamPlug Reference Board Init for drivers not converted to
- * flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data dreamplug_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv643xx_eth_platform_data dreamplug_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(1),
-};
-
-void __init dreamplug_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&dreamplug_ge00_data);
-	kirkwood_ge01_init(&dreamplug_ge01_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index 6e122ed..713be4f 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -15,6 +15,9 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/dma-mapping.h>
+#include <linux/irqchip.h>
 #include <linux/kexec.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -49,10 +52,6 @@ static void __init kirkwood_legacy_clk_init(void)
 	orion_clkdev_add("1", "pcie",
 			 of_clk_get_from_provider(&clkspec));
 
-	clkspec.args[0] = CGC_BIT_SDIO;
-	orion_clkdev_add(NULL, "mvsdio",
-			 of_clk_get_from_provider(&clkspec));
-
 	/*
 	 * The ethernet interfaces forget the MAC address assigned by
 	 * u-boot if the clocks are turned off. Until proper DT support
@@ -60,19 +59,24 @@ static void __init kirkwood_legacy_clk_init(void)
 	 */
 	clkspec.args[0] = CGC_BIT_GE0;
 	clk = of_clk_get_from_provider(&clkspec);
-	orion_clkdev_add(NULL, "mv643xx_eth_port.0", clk);
 	clk_prepare_enable(clk);
 
 	clkspec.args[0] = CGC_BIT_GE1;
 	clk = of_clk_get_from_provider(&clkspec);
-	orion_clkdev_add(NULL, "mv643xx_eth_port.1", clk);
 	clk_prepare_enable(clk);
 }
 
-static void __init kirkwood_of_clk_init(void)
+static void __init kirkwood_dt_time_init(void)
 {
 	of_clk_init(NULL);
-	kirkwood_legacy_clk_init();
+	clocksource_of_init();
+}
+
+static void __init kirkwood_dt_init_early(void)
+{
+	mvebu_mbus_init("marvell,kirkwood-mbus",
+			BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
+			DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ);
 }
 
 static void __init kirkwood_dt_init(void)
@@ -87,14 +91,15 @@ static void __init kirkwood_dt_init(void)
 	 */
 	writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
 
+	BUG_ON(mvebu_mbus_dt_init());
 	kirkwood_setup_wins();
 
 	kirkwood_l2_init();
 
 	kirkwood_cpufreq_init();
 
-	/* Setup root of clk tree */
-	kirkwood_of_clk_init();
+	/* Setup clocks for legacy devices */
+	kirkwood_legacy_clk_init();
 
 	kirkwood_cpuidle_init();
 
@@ -102,105 +107,25 @@ static void __init kirkwood_dt_init(void)
 	kexec_reinit = kirkwood_enable_pcie;
 #endif
 
-	if (of_machine_is_compatible("globalscale,dreamplug"))
-		dreamplug_init();
-
-	if (of_machine_is_compatible("globalscale,guruplug"))
-		guruplug_dt_init();
-
-	if (of_machine_is_compatible("globalscale,sheevaplug"))
-		sheevaplug_dt_init();
-
 	if (of_machine_is_compatible("dlink,dns-kirkwood"))
 		dnskw_init();
 
-	if (of_machine_is_compatible("iom,iconnect"))
-		iconnect_init();
-
-	if (of_machine_is_compatible("raidsonic,ib-nas62x0"))
-		ib62x0_init();
-
-	if (of_machine_is_compatible("qnap,ts219"))
-		qnap_dt_ts219_init();
-
-	if (of_machine_is_compatible("seagate,dockstar"))
-		dockstar_dt_init();
-
-	if (of_machine_is_compatible("seagate,goflexnet"))
-		goflexnet_init();
-
-	if (of_machine_is_compatible("buffalo,lsxl"))
-		lsxl_init();
-
-	if (of_machine_is_compatible("iom,ix2-200"))
-		iomega_ix2_200_init();
-
-	if (of_machine_is_compatible("keymile,km_kirkwood"))
-		km_kirkwood_init();
-
-	if (of_machine_is_compatible("lacie,cloudbox") ||
-	    of_machine_is_compatible("lacie,inetspace_v2") ||
-	    of_machine_is_compatible("lacie,netspace_lite_v2") ||
-	    of_machine_is_compatible("lacie,netspace_max_v2") ||
-	    of_machine_is_compatible("lacie,netspace_mini_v2") ||
-	    of_machine_is_compatible("lacie,netspace_v2"))
-		ns2_init();
-
-	if (of_machine_is_compatible("marvell,db-88f6281-bp") ||
-	    of_machine_is_compatible("marvell,db-88f6282-bp"))
-		db88f628x_init();
-
-	if (of_machine_is_compatible("mpl,cec4"))
-		mplcec4_init();
-
-	if (of_machine_is_compatible("netgear,readynas-duo-v2"))
-		netgear_readynas_init();
-
-	if (of_machine_is_compatible("plathome,openblocks-a6"))
-		openblocks_a6_init();
-
-	if (of_machine_is_compatible("usi,topkick"))
-		usi_topkick_init();
+	if (of_machine_is_compatible("marvell,mv88f6281gtw-ge"))
+		mv88f6281gtw_ge_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const kirkwood_dt_board_compat[] = {
-	"globalscale,dreamplug",
-	"globalscale,guruplug",
-	"globalscale,sheevaplug",
-	"dlink,dns-320",
-	"dlink,dns-325",
-	"iom,iconnect",
-	"raidsonic,ib-nas62x0",
-	"qnap,ts219",
-	"seagate,dockstar",
-	"seagate,goflexnet",
-	"buffalo,lsxl",
-	"iom,ix2-200",
-	"keymile,km_kirkwood",
-	"lacie,cloudbox",
-	"lacie,inetspace_v2",
-	"lacie,netspace_lite_v2",
-	"lacie,netspace_max_v2",
-	"lacie,netspace_mini_v2",
-	"lacie,netspace_v2",
-	"marvell,db-88f6281-bp",
-	"marvell,db-88f6282-bp",
-	"mpl,cec4",
-	"netgear,readynas-duo-v2",
-	"plathome,openblocks-a6",
-	"usi,topkick",
-	"zyxel,nsa310",
+	"marvell,kirkwood",
 	NULL
 };
 
 DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
 	/* Maintainer: Jason Cooper <jason@lakedaemon.net> */
 	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= orion_dt_init_irq,
-	.init_time	= kirkwood_timer_init,
+	.init_early	= kirkwood_dt_init_early,
+	.init_time	= kirkwood_dt_time_init,
 	.init_machine	= kirkwood_dt_init,
 	.restart	= kirkwood_restart,
 	.dt_compat	= kirkwood_dt_board_compat,
diff --git a/arch/arm/mach-kirkwood/board-goflexnet.c b/arch/arm/mach-kirkwood/board-goflexnet.c
deleted file mode 100644
index 9db979a..0000000
--- a/arch/arm/mach-kirkwood/board-goflexnet.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
- *
- * arch/arm/mach-kirkwood/board-goflexnet.c
- *
- * Seagate GoFlext Net Board Init for drivers not converted to
- * flattened device tree yet.
- *
- * 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.
- *
- * Copied and modified for Seagate GoFlex Net support by
- * Joshua Coombs <josh.coombs@gmail.com> based on ArchLinux ARM's
- * GoFlex kernel patches.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data goflexnet_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init goflexnet_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&goflexnet_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-guruplug.c b/arch/arm/mach-kirkwood/board-guruplug.c
deleted file mode 100644
index a857163..0000000
--- a/arch/arm/mach-kirkwood/board-guruplug.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/board-guruplug.c
- *
- * Marvell Guruplug Reference Board Init for drivers not converted to
- * flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data guruplug_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv643xx_eth_platform_data guruplug_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(1),
-};
-
-void __init guruplug_dt_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&guruplug_ge00_data);
-	kirkwood_ge01_init(&guruplug_ge01_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-ib62x0.c b/arch/arm/mach-kirkwood/board-ib62x0.c
deleted file mode 100644
index 9a857ae..0000000
--- a/arch/arm/mach-kirkwood/board-ib62x0.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012 (C), Simon Baatz <gmbnomis@gmail.com>
- *
- * arch/arm/mach-kirkwood/board-ib62x0.c
- *
- * RaidSonic ICY BOX IB-NAS6210 & IB-NAS6220 init for drivers not
- * converted to flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data ib62x0_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-void __init ib62x0_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&ib62x0_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c
deleted file mode 100644
index 98b5ad1..0000000
--- a/arch/arm/mach-kirkwood/board-iconnect.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/board-iconnect.c
- *
- * Iomega i-connect Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data iconnect_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(11),
-};
-
-void __init iconnect_init(void)
-{
-	kirkwood_ge00_init(&iconnect_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
deleted file mode 100644
index e5f7041..0000000
--- a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/board-iomega_ix2_200.c
- *
- * Iomega StorCenter ix2-200
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ethtool.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
-	.phy_addr       = MV643XX_ETH_PHY_NONE,
-	.speed          = SPEED_1000,
-	.duplex         = DUPLEX_FULL,
-};
-
-static struct mv643xx_eth_platform_data iomega_ix2_200_ge01_data = {
-        .phy_addr       = MV643XX_ETH_PHY_ADDR(11),
-};
-
-void __init iomega_ix2_200_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&iomega_ix2_200_ge00_data);
-	kirkwood_ge01_init(&iomega_ix2_200_ge01_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-km_kirkwood.c b/arch/arm/mach-kirkwood/board-km_kirkwood.c
deleted file mode 100644
index 44e4605..0000000
--- a/arch/arm/mach-kirkwood/board-km_kirkwood.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 2012 KEYMILE AG, CH-3097 Bern
- * Valentin Longchamp <valentin.longchamp@keymile.com>
- *
- * arch/arm/mach-kirkwood/board-km_kirkwood.c
- *
- * Keymile km_kirkwood Reference Desing Init for drivers not converted to
- * flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/clk.h>
-#include <linux/clk-private.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data km_kirkwood_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init km_kirkwood_init(void)
-{
-	struct clk *sata_clk;
-	/*
-	 * Our variant of kirkwood (integrated in the Bobcat) hangs on accessing
-	 * SATA bits (14-15) of the Clock Gating Control Register. Since these
-	 * devices are also not present in this variant, their clocks get
-	 * disabled because unused when clk_disable_unused() gets called.
-	 * That's why we change the flags to these clocks to CLK_IGNORE_UNUSED
-	 */
-	sata_clk = clk_get_sys("sata_mv.0", "0");
-	if (!IS_ERR(sata_clk))
-		sata_clk->flags |= CLK_IGNORE_UNUSED;
-	sata_clk = clk_get_sys("sata_mv.0", "1");
-	if (!IS_ERR(sata_clk))
-		sata_clk->flags |= CLK_IGNORE_UNUSED;
-
-	kirkwood_ge00_init(&km_kirkwood_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-lsxl.c b/arch/arm/mach-kirkwood/board-lsxl.c
deleted file mode 100644
index 3483952..0000000
--- a/arch/arm/mach-kirkwood/board-lsxl.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 (C), Michael Walle <michael@walle.cc>
- *
- * arch/arm/mach-kirkwood/board-lsxl.c
- *
- * Buffalo Linkstation LS-XHL and LS-CHLv2 init for drivers not
- * converted to flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data lsxl_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv643xx_eth_platform_data lsxl_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-void __init lsxl_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-
-	kirkwood_ge00_init(&lsxl_ge00_data);
-	kirkwood_ge01_init(&lsxl_ge01_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-mplcec4.c b/arch/arm/mach-kirkwood/board-mplcec4.c
deleted file mode 100644
index 938712e..0000000
--- a/arch/arm/mach-kirkwood/board-mplcec4.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2012 MPL AG, Switzerland
- * Stefan Peter <s.peter@mpl.ch>
- *
- * arch/arm/mach-kirkwood/board-mplcec4.c
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data mplcec4_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(1),
-};
-
-static struct mv643xx_eth_platform_data mplcec4_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(2),
-};
-
-void __init mplcec4_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&mplcec4_ge00_data);
-	kirkwood_ge01_init(&mplcec4_ge01_data);
-}
-
-
-
diff --git a/arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c b/arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
new file mode 100644
index 0000000..ee5eea6
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
@@ -0,0 +1,50 @@
+/*
+ * arch/arm/mach-kirkwood/board-mv88f6281gtw_ge.c
+ *
+ * Marvell 88F6281 GTW GE Board Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/timer.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ethtool.h>
+#include <linux/gpio.h>
+#include <net/dsa.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/pci.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+
+static struct mv643xx_eth_platform_data mv88f6281gtw_ge_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_NONE,
+	.speed		= SPEED_1000,
+	.duplex		= DUPLEX_FULL,
+};
+
+static struct dsa_chip_data mv88f6281gtw_ge_switch_chip_data = {
+	.port_names[0]	= "lan1",
+	.port_names[1]	= "lan2",
+	.port_names[2]	= "lan3",
+	.port_names[3]	= "lan4",
+	.port_names[4]	= "wan",
+	.port_names[5]	= "cpu",
+};
+
+static struct dsa_platform_data mv88f6281gtw_ge_switch_plat_data = {
+	.nr_chips	= 1,
+	.chip		= &mv88f6281gtw_ge_switch_chip_data,
+};
+
+void __init mv88f6281gtw_ge_init(void)
+{
+	kirkwood_ge00_init(&mv88f6281gtw_ge_ge00_data);
+	kirkwood_ge00_switch_init(&mv88f6281gtw_ge_switch_plat_data, NO_IRQ);
+}
diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c
deleted file mode 100644
index f8f6605..0000000
--- a/arch/arm/mach-kirkwood/board-ns2.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012 (C), Simon Guinot <simon.guinot@sequanux.org>
- *
- * arch/arm/mach-kirkwood/board-ns2.c
- *
- * LaCie Network Space v2 board (and parents) initialization for drivers
- * not converted to flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/of.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data ns2_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-void __init ns2_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	if (of_machine_is_compatible("lacie,cloudbox") ||
-	    of_machine_is_compatible("lacie,netspace_lite_v2") ||
-	    of_machine_is_compatible("lacie,netspace_mini_v2"))
-		ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
-	kirkwood_ge00_init(&ns2_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-openblocks_a6.c b/arch/arm/mach-kirkwood/board-openblocks_a6.c
deleted file mode 100644
index b11d8fd..0000000
--- a/arch/arm/mach-kirkwood/board-openblocks_a6.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2012 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
- *
- * arch/arm/mach-kirkwood/board-openblocks_a6.c
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data openblocks_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init openblocks_a6_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&openblocks_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-readynas.c b/arch/arm/mach-kirkwood/board-readynas.c
deleted file mode 100644
index 341b82d..0000000
--- a/arch/arm/mach-kirkwood/board-readynas.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * NETGEAR ReadyNAS Duo v2 Board setup for drivers not already
- * converted to DT.
- *
- * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.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/init.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx_eth.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data netgear_readynas_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init netgear_readynas_init(void)
-{
-	kirkwood_ge00_init(&netgear_readynas_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-sheevaplug.c b/arch/arm/mach-kirkwood/board-sheevaplug.c
deleted file mode 100644
index fa38937..0000000
--- a/arch/arm/mach-kirkwood/board-sheevaplug.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/board-sheevaplug.c
- *
- * Marvell Sheevaplug Reference Board Init for drivers not converted to
- * flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data sheevaplug_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init sheevaplug_dt_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&sheevaplug_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-ts219.c b/arch/arm/mach-kirkwood/board-ts219.c
deleted file mode 100644
index 860f44a..0000000
--- a/arch/arm/mach-kirkwood/board-ts219.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * QNAP TS-11x/TS-21x Turbo NAS Board Setup via DT
- *
- * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
- *
- * Based on the board file ts219-setup.c:
- *
- * Copyright (C) 2009  Martin Michlmayr <tbm@cyrius.com>
- * Copyright (C) 2008  Byron Bradley <byron.bbradley@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx_eth.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-void __init qnap_dt_ts219_init(void)
-{
-	u32 dev, rev;
-
-	kirkwood_pcie_id(&dev, &rev);
-	if (dev == MV88F6282_DEV_ID)
-		qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
-
-	kirkwood_ge00_init(&qnap_ts219_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/board-usi_topkick.c b/arch/arm/mach-kirkwood/board-usi_topkick.c
deleted file mode 100644
index 1cc04ec..0000000
--- a/arch/arm/mach-kirkwood/board-usi_topkick.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
- *
- * arch/arm/mach-kirkwood/board-usi_topkick.c
- *
- * USI Topkick Init for drivers not converted to flattened device tree yet.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include "common.h"
-
-static struct mv643xx_eth_platform_data topkick_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-void __init usi_topkick_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_ge00_init(&topkick_ge00_data);
-}
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index e9238b5..1767611 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -37,6 +37,12 @@
 #include <linux/platform_data/dma-mv_xor.h>
 #include "common.h"
 
+/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
+#define KIRKWOOD_MBUS_NAND_TARGET 0x01
+#define KIRKWOOD_MBUS_NAND_ATTR   0x2f
+#define KIRKWOOD_MBUS_SRAM_TARGET 0x03
+#define KIRKWOOD_MBUS_SRAM_ATTR   0x01
+
 /*****************************************************************************
  * I/O Address Mapping
  ****************************************************************************/
@@ -264,7 +270,7 @@ void __init kirkwood_clk_init(void)
 	orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
 	orion_clkdev_add("0", "pcie", pex0);
 	orion_clkdev_add("1", "pcie", pex1);
-	orion_clkdev_add(NULL, "kirkwood-i2s", audio);
+	orion_clkdev_add(NULL, "mvebu-audio", audio);
 	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
 	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
 
@@ -528,10 +534,6 @@ void __init kirkwood_cpuidle_init(void)
 void __init kirkwood_init_early(void)
 {
 	orion_time_set_base(TIMER_VIRT_BASE);
-
-	mvebu_mbus_init("marvell,kirkwood-mbus",
-			BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
-			DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ);
 }
 
 int kirkwood_tclk;
@@ -560,7 +562,7 @@ void __init kirkwood_timer_init(void)
 /*****************************************************************************
  * Audio
  ****************************************************************************/
-static struct resource kirkwood_i2s_resources[] = {
+static struct resource kirkwood_audio_resources[] = {
 	[0] = {
 		.start  = AUDIO_PHYS_BASE,
 		.end    = AUDIO_PHYS_BASE + SZ_16K - 1,
@@ -573,29 +575,23 @@ static struct resource kirkwood_i2s_resources[] = {
 	},
 };
 
-static struct kirkwood_asoc_platform_data kirkwood_i2s_data = {
+static struct kirkwood_asoc_platform_data kirkwood_audio_data = {
 	.burst       = 128,
 };
 
-static struct platform_device kirkwood_i2s_device = {
-	.name		= "kirkwood-i2s",
+static struct platform_device kirkwood_audio_device = {
+	.name		= "mvebu-audio",
 	.id		= -1,
-	.num_resources	= ARRAY_SIZE(kirkwood_i2s_resources),
-	.resource	= kirkwood_i2s_resources,
+	.num_resources	= ARRAY_SIZE(kirkwood_audio_resources),
+	.resource	= kirkwood_audio_resources,
 	.dev		= {
-		.platform_data	= &kirkwood_i2s_data,
+		.platform_data	= &kirkwood_audio_data,
 	},
 };
 
-static struct platform_device kirkwood_pcm_device = {
-	.name		= "kirkwood-pcm-audio",
-	.id		= -1,
-};
-
 void __init kirkwood_audio_init(void)
 {
-	platform_device_register(&kirkwood_i2s_device);
-	platform_device_register(&kirkwood_pcm_device);
+	platform_device_register(&kirkwood_audio_device);
 }
 
 /*****************************************************************************
@@ -672,10 +668,14 @@ char * __init kirkwood_id(void)
 
 void __init kirkwood_setup_wins(void)
 {
-	mvebu_mbus_add_window("nand", KIRKWOOD_NAND_MEM_PHYS_BASE,
-			      KIRKWOOD_NAND_MEM_SIZE);
-	mvebu_mbus_add_window("sram", KIRKWOOD_SRAM_PHYS_BASE,
-			      KIRKWOOD_SRAM_SIZE);
+	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_NAND_TARGET,
+				    KIRKWOOD_MBUS_NAND_ATTR,
+				    KIRKWOOD_NAND_MEM_PHYS_BASE,
+				    KIRKWOOD_NAND_MEM_SIZE);
+	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_SRAM_TARGET,
+				    KIRKWOOD_MBUS_SRAM_ATTR,
+				    KIRKWOOD_SRAM_PHYS_BASE,
+				    KIRKWOOD_SRAM_SIZE);
 }
 
 void __init kirkwood_l2_init(void)
@@ -703,6 +703,10 @@ void __init kirkwood_init(void)
 	 */
 	writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
 
+	BUG_ON(mvebu_mbus_init("marvell,kirkwood-mbus",
+			BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
+			DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ));
+
 	kirkwood_setup_wins();
 
 	kirkwood_l2_init();
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index fcf3ba6..cc639bb 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -59,119 +59,16 @@ void kirkwood_restart(enum reboot_mode, const char *);
 void kirkwood_clk_init(void);
 
 /* board init functions for boards not fully converted to fdt */
-#ifdef CONFIG_MACH_DREAMPLUG_DT
-void dreamplug_init(void);
-#else
-static inline void dreamplug_init(void) {};
-#endif
-#ifdef CONFIG_MACH_GURUPLUG_DT
-void guruplug_dt_init(void);
-#else
-static inline void guruplug_dt_init(void) {};
-#endif
-#ifdef CONFIG_MACH_SHEEVAPLUG_DT
-void sheevaplug_dt_init(void);
-#else
-static inline void sheevaplug_dt_init(void) {};
-#endif
-#ifdef CONFIG_MACH_TS219_DT
-void qnap_dt_ts219_init(void);
-#else
-static inline void qnap_dt_ts219_init(void) {};
-#endif
-
 #ifdef CONFIG_MACH_DLINK_KIRKWOOD_DT
 void dnskw_init(void);
 #else
 static inline void dnskw_init(void) {};
 #endif
 
-#ifdef CONFIG_MACH_ICONNECT_DT
-void iconnect_init(void);
-#else
-static inline void iconnect_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_IB62X0_DT
-void ib62x0_init(void);
-#else
-static inline void ib62x0_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_DOCKSTAR_DT
-void dockstar_dt_init(void);
-#else
-static inline void dockstar_dt_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_GOFLEXNET_DT
-void goflexnet_init(void);
-#else
-static inline void goflexnet_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_LSXL_DT
-void lsxl_init(void);
-#else
-static inline void lsxl_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_IOMEGA_IX2_200_DT
-void iomega_ix2_200_init(void);
-#else
-static inline void iomega_ix2_200_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_KM_KIRKWOOD_DT
-void km_kirkwood_init(void);
-#else
-static inline void km_kirkwood_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_DB88F628X_BP_DT
-void db88f628x_init(void);
-#else
-static inline void db88f628x_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_MPLCEC4_DT
-void mplcec4_init(void);
-#else
-static inline void mplcec4_init(void) {};
-#endif
-
-#if defined(CONFIG_MACH_INETSPACE_V2_DT) || \
-	defined(CONFIG_MACH_NETSPACE_V2_DT) || \
-	defined(CONFIG_MACH_NETSPACE_MAX_V2_DT) || \
-	defined(CONFIG_MACH_NETSPACE_LITE_V2_DT) || \
-	defined(CONFIG_MACH_NETSPACE_MINI_V2_DT)
-void ns2_init(void);
-#else
-static inline void ns2_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_OPENBLOCKS_A6_DT
-void openblocks_a6_init(void);
-#else
-static inline void openblocks_a6_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_READYNAS_DT
-void netgear_readynas_init(void);
-#else
-static inline void netgear_readynas_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_TOPKICK_DT
-void usi_topkick_init(void);
-#else
-static inline void usi_topkick_init(void) {};
-#endif
-
-#ifdef CONFIG_MACH_CLOUDBOX_DT
-void cloudbox_init(void);
+#ifdef CONFIG_MACH_MV88F6281GTW_GE_DT
+void mv88f6281gtw_ge_init(void);
 #else
-static inline void cloudbox_init(void) {};
+static inline void mv88f6281gtw_ge_init(void) {};
 #endif
 
 /* early init functions not converted to fdt yet */
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
deleted file mode 100644
index 060ccf9..0000000
--- a/arch/arm/mach-kirkwood/dockstar-setup.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/dockstar-setup.c
- *
- * Seagate FreeAgent DockStar Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition dockstar_nand_parts[] = {
-	{
-		.name = "u-boot",
-		.offset = 0,
-		.size = SZ_1M
-	}, {
-		.name = "uImage",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = SZ_4M
-	}, {
-		.name = "root",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = MTDPART_SIZ_FULL
-	},
-};
-
-static struct mv643xx_eth_platform_data dockstar_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct gpio_led dockstar_led_pins[] = {
-	{
-		.name			= "dockstar:green:health",
-		.default_trigger	= "default-on",
-		.gpio			= 46,
-		.active_low		= 1,
-	},
-	{
-		.name			= "dockstar:orange:misc",
-		.default_trigger	= "none",
-		.gpio			= 47,
-		.active_low		= 1,
-	},
-};
-
-static struct gpio_led_platform_data dockstar_led_data = {
-	.leds		= dockstar_led_pins,
-	.num_leds	= ARRAY_SIZE(dockstar_led_pins),
-};
-
-static struct platform_device dockstar_leds = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &dockstar_led_data,
-	}
-};
-
-static unsigned int dockstar_mpp_config[] __initdata = {
-	MPP29_GPIO,	/* USB Power Enable */
-	MPP46_GPIO,	/* LED green */
-	MPP47_GPIO,	/* LED orange */
-	0
-};
-
-static void __init dockstar_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-
-	/* setup gpio pin select */
-	kirkwood_mpp_conf(dockstar_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_nand_init(ARRAY_AND_SIZE(dockstar_nand_parts), 25);
-
-	if (gpio_request(29, "USB Power Enable") != 0 ||
-	    gpio_direction_output(29, 1) != 0)
-		pr_err("can't set up GPIO 29 (USB Power Enable)\n");
-	kirkwood_ehci_init();
-
-	kirkwood_ge00_init(&dockstar_ge00_data);
-
-	platform_device_register(&dockstar_leds);
-}
-
-MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
-	.atag_offset	= 0x100,
-	.init_machine	= dockstar_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
deleted file mode 100644
index 08dd739..0000000
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/guruplug-setup.c
- *
- * Marvell GuruPlug Reference Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition guruplug_nand_parts[] = {
-	{
-		.name = "u-boot",
-		.offset = 0,
-		.size = SZ_1M
-	}, {
-		.name = "uImage",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = SZ_4M
-	}, {
-		.name = "root",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = MTDPART_SIZ_FULL
-	},
-};
-
-static struct mv643xx_eth_platform_data guruplug_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv643xx_eth_platform_data guruplug_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(1),
-};
-
-static struct mv_sata_platform_data guruplug_sata_data = {
-	.n_ports	= 1,
-};
-
-static struct mvsdio_platform_data guruplug_mvsdio_data = {
-	/* unfortunately the CD signal has not been connected */
-	.gpio_card_detect = -1,
-	.gpio_write_protect = -1,
-};
-
-static struct gpio_led guruplug_led_pins[] = {
-	{
-		.name			= "guruplug:red:health",
-		.gpio			= 46,
-		.active_low		= 1,
-	},
-	{
-		.name			= "guruplug:green:health",
-		.gpio			= 47,
-		.active_low		= 1,
-	},
-	{
-		.name			= "guruplug:red:wmode",
-		.gpio			= 48,
-		.active_low		= 1,
-	},
-	{
-		.name			= "guruplug:green:wmode",
-		.gpio			= 49,
-		.active_low		= 1,
-	},
-};
-
-static struct gpio_led_platform_data guruplug_led_data = {
-	.leds		= guruplug_led_pins,
-	.num_leds	= ARRAY_SIZE(guruplug_led_pins),
-};
-
-static struct platform_device guruplug_leds = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &guruplug_led_data,
-	}
-};
-
-static unsigned int guruplug_mpp_config[] __initdata = {
-	MPP46_GPIO,	/* M_RLED */
-	MPP47_GPIO,	/* M_GLED */
-	MPP48_GPIO,	/* B_RLED */
-	MPP49_GPIO,	/* B_GLED */
-	0
-};
-
-static void __init guruplug_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(guruplug_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_nand_init(ARRAY_AND_SIZE(guruplug_nand_parts), 25);
-
-	kirkwood_ehci_init();
-	kirkwood_ge00_init(&guruplug_ge00_data);
-	kirkwood_ge01_init(&guruplug_ge01_data);
-	kirkwood_sata_init(&guruplug_sata_data);
-	kirkwood_sdio_init(&guruplug_mvsdio_data);
-
-	platform_device_register(&guruplug_leds);
-}
-
-MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
-	/* Maintainer: Siddarth Gore <gores@marvell.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= guruplug_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/include/mach/debug-macro.S b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
deleted file mode 100644
index f785d40..0000000
--- a/arch/arm/mach-kirkwood/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <mach/bridge-regs.h>
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =KIRKWOOD_REGS_PHYS_BASE
-	ldr	\rv, =KIRKWOOD_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
deleted file mode 100644
index ba384b9..0000000
--- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
- *
- * Marvell 88F6281 GTW GE Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/mtd/physmap.h>
-#include <linux/timer.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ethtool.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <net/dsa.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mv643xx_eth_platform_data mv88f6281gtw_ge_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_NONE,
-	.speed		= SPEED_1000,
-	.duplex		= DUPLEX_FULL,
-};
-
-static struct dsa_chip_data mv88f6281gtw_ge_switch_chip_data = {
-	.port_names[0]	= "lan1",
-	.port_names[1]	= "lan2",
-	.port_names[2]	= "lan3",
-	.port_names[3]	= "lan4",
-	.port_names[4]	= "wan",
-	.port_names[5]	= "cpu",
-};
-
-static struct dsa_platform_data mv88f6281gtw_ge_switch_plat_data = {
-	.nr_chips	= 1,
-	.chip		= &mv88f6281gtw_ge_switch_chip_data,
-};
-
-static const struct flash_platform_data mv88f6281gtw_ge_spi_slave_data = {
-	.type		= "mx25l12805d",
-};
-
-static struct spi_board_info __initdata mv88f6281gtw_ge_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &mv88f6281gtw_ge_spi_slave_data,
-		.irq		= -1,
-		.max_speed_hz	= 50000000,
-		.bus_num	= 0,
-		.chip_select	= 0,
-	},
-};
-
-static struct gpio_keys_button mv88f6281gtw_ge_button_pins[] = {
-	{
-		.code		= KEY_RESTART,
-		.gpio		= 47,
-		.desc		= "SWR Button",
-		.active_low	= 1,
-	}, {
-		.code		= KEY_WPS_BUTTON,
-		.gpio		= 46,
-		.desc		= "WPS Button",
-		.active_low	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data mv88f6281gtw_ge_button_data = {
-	.buttons	= mv88f6281gtw_ge_button_pins,
-	.nbuttons	= ARRAY_SIZE(mv88f6281gtw_ge_button_pins),
-};
-
-static struct platform_device mv88f6281gtw_ge_buttons = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &mv88f6281gtw_ge_button_data,
-	},
-};
-
-static struct gpio_led mv88f6281gtw_ge_led_pins[] = {
-	{
-		.name		= "gtw:green:Status",
-		.gpio		= 20,
-		.active_low	= 0,
-	}, {
-		.name		= "gtw:red:Status",
-		.gpio		= 21,
-		.active_low	= 0,
-	}, {
-		.name		= "gtw:green:USB",
-		.gpio		= 12,
-		.active_low	= 0,
-	},
-};
-
-static struct gpio_led_platform_data mv88f6281gtw_ge_led_data = {
-	.leds		= mv88f6281gtw_ge_led_pins,
-	.num_leds	= ARRAY_SIZE(mv88f6281gtw_ge_led_pins),
-};
-
-static struct platform_device mv88f6281gtw_ge_leds = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &mv88f6281gtw_ge_led_data,
-	},
-};
-
-static unsigned int mv88f6281gtw_ge_mpp_config[] __initdata = {
-	MPP12_GPO,	/* Status#_USB pin  */
-	MPP20_GPIO,	/* Status#_GLED pin */
-	MPP21_GPIO,	/* Status#_RLED pin */
-	MPP46_GPIO,	/* WPS_Switch pin   */
-	MPP47_GPIO,	/* SW_Init pin      */
-	0
-};
-
-static void __init mv88f6281gtw_ge_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(mv88f6281gtw_ge_mpp_config);
-
-	kirkwood_ehci_init();
-	kirkwood_ge00_init(&mv88f6281gtw_ge_ge00_data);
-	kirkwood_ge00_switch_init(&mv88f6281gtw_ge_switch_plat_data, NO_IRQ);
-	spi_register_board_info(mv88f6281gtw_ge_spi_slave_info,
-				ARRAY_SIZE(mv88f6281gtw_ge_spi_slave_info));
-	kirkwood_spi_init();
-	kirkwood_uart0_init();
-	platform_device_register(&mv88f6281gtw_ge_leds);
-	platform_device_register(&mv88f6281gtw_ge_buttons);
-}
-
-static int __init mv88f6281gtw_ge_pci_init(void)
-{
-	if (machine_is_mv88f6281gtw_ge())
-		kirkwood_pcie_init(KW_PCIE0);
-
-	return 0;
-}
-subsys_initcall(mv88f6281gtw_ge_pci_init);
-
-MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
-	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= mv88f6281gtw_ge_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
deleted file mode 100644
index 3b70661..0000000
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/netspace_v2-setup.c
- *
- * LaCie Network Space v2 board setup
- *
- * Copyright (C) 2009 Simon Guinot <sguinot@lacie.com>
- * Copyright (C) 2009 BenoÃ®t Canet <benoit.canet@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/leds.h>
-#include <linux/gpio-fan.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/leds-kirkwood-ns2.h>
-#include "common.h"
-#include "mpp.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data netspace_v2_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-
-static struct mv_sata_platform_data netspace_v2_sata_data = {
-	.n_ports	= 2,
-};
-
-/*****************************************************************************
- * GPIO keys
- ****************************************************************************/
-
-#define NETSPACE_V2_PUSH_BUTTON		32
-
-static struct gpio_keys_button netspace_v2_buttons[] = {
-	[0] = {
-		.code		= KEY_POWER,
-		.gpio		= NETSPACE_V2_PUSH_BUTTON,
-		.desc		= "Power push button",
-		.active_low	= 0,
-	},
-};
-
-static struct gpio_keys_platform_data netspace_v2_button_data = {
-	.buttons	= netspace_v2_buttons,
-	.nbuttons	= ARRAY_SIZE(netspace_v2_buttons),
-};
-
-static struct platform_device netspace_v2_gpio_buttons = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &netspace_v2_button_data,
-	},
-};
-
-/*****************************************************************************
- * GPIO LEDs
- ****************************************************************************/
-
-#define NETSPACE_V2_GPIO_RED_LED	12
-
-static struct gpio_led netspace_v2_gpio_led_pins[] = {
-	{
-		.name	= "ns_v2:red:fail",
-		.gpio	= NETSPACE_V2_GPIO_RED_LED,
-	},
-};
-
-static struct gpio_led_platform_data netspace_v2_gpio_leds_data = {
-	.num_leds	= ARRAY_SIZE(netspace_v2_gpio_led_pins),
-	.leds		= netspace_v2_gpio_led_pins,
-};
-
-static struct platform_device netspace_v2_gpio_leds = {
-	.name		= "leds-gpio",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &netspace_v2_gpio_leds_data,
-	},
-};
-
-/*****************************************************************************
- * Dual-GPIO CPLD LEDs
- ****************************************************************************/
-
-#define NETSPACE_V2_GPIO_BLUE_LED_SLOW	29
-#define NETSPACE_V2_GPIO_BLUE_LED_CMD	30
-
-static struct ns2_led netspace_v2_led_pins[] = {
-	{
-		.name	= "ns_v2:blue:sata",
-		.cmd	= NETSPACE_V2_GPIO_BLUE_LED_CMD,
-		.slow	= NETSPACE_V2_GPIO_BLUE_LED_SLOW,
-	},
-};
-
-static struct ns2_led_platform_data netspace_v2_leds_data = {
-	.num_leds	= ARRAY_SIZE(netspace_v2_led_pins),
-	.leds		= netspace_v2_led_pins,
-};
-
-static struct platform_device netspace_v2_leds = {
-	.name		= "leds-ns2",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &netspace_v2_leds_data,
-	},
-};
-
-/*****************************************************************************
- * GPIO fan
- ****************************************************************************/
-
-/* Designed for fan 40x40x16: ADDA AD0412LB-D50 6000rpm@12v */
-static struct gpio_fan_speed netspace_max_v2_fan_speed[] = {
-	{    0,  0 },
-	{ 1500,	15 },
-	{ 1700,	14 },
-	{ 1800,	13 },
-	{ 2100,	12 },
-	{ 3100,	11 },
-	{ 3300,	10 },
-	{ 4300,	 9 },
-	{ 5500,	 8 },
-};
-
-static unsigned netspace_max_v2_fan_ctrl[] = { 22, 7, 33, 23 };
-
-static struct gpio_fan_alarm netspace_max_v2_fan_alarm = {
-	.gpio		= 25,
-	.active_low	= 1,
-};
-
-static struct gpio_fan_platform_data netspace_max_v2_fan_data = {
-	.num_ctrl	= ARRAY_SIZE(netspace_max_v2_fan_ctrl),
-	.ctrl		= netspace_max_v2_fan_ctrl,
-	.alarm		= &netspace_max_v2_fan_alarm,
-	.num_speed	= ARRAY_SIZE(netspace_max_v2_fan_speed),
-	.speed		= netspace_max_v2_fan_speed,
-};
-
-static struct platform_device netspace_max_v2_gpio_fan = {
-	.name	= "gpio-fan",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &netspace_max_v2_fan_data,
-	},
-};
-
-/*****************************************************************************
- * General Setup
- ****************************************************************************/
-
-static unsigned int netspace_v2_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP4_NF_IO6,
-	MPP5_NF_IO7,
-	MPP6_SYSRST_OUTn,
-	MPP7_GPO,		/* Fan speed (bit 1) */
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP12_GPO,		/* Red led */
-	MPP14_GPIO,		/* USB fuse */
-	MPP16_GPIO,		/* SATA 0 power */
-	MPP17_GPIO,		/* SATA 1 power */
-	MPP18_NF_IO0,
-	MPP19_NF_IO1,
-	MPP20_SATA1_ACTn,
-	MPP21_SATA0_ACTn,
-	MPP22_GPIO,		/* Fan speed (bit 0) */
-	MPP23_GPIO,		/* Fan power */
-	MPP24_GPIO,		/* USB mode select */
-	MPP25_GPIO,		/* Fan rotation fail */
-	MPP26_GPIO,		/* USB device vbus */
-	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* Blue led (slow register) */
-	MPP30_GPIO,		/* Blue led (command register) */
-	MPP31_GPIO,		/* Board power off */
-	MPP32_GPIO,		/* Power button (0 = Released, 1 = Pushed) */
-	MPP33_GPO,		/* Fan speed (bit 2) */
-	0
-};
-
-#define NETSPACE_V2_GPIO_POWER_OFF	31
-
-static void netspace_v2_power_off(void)
-{
-	gpio_set_value(NETSPACE_V2_GPIO_POWER_OFF, 1);
-}
-
-static void __init netspace_v2_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(netspace_v2_mpp_config);
-
-	if (machine_is_netspace_max_v2())
-		lacie_v2_hdd_power_init(2);
-	else
-		lacie_v2_hdd_power_init(1);
-
-	kirkwood_ehci_init();
-	kirkwood_ge00_init(&netspace_v2_ge00_data);
-	kirkwood_sata_init(&netspace_v2_sata_data);
-	kirkwood_uart0_init();
-	lacie_v2_register_flash();
-	lacie_v2_register_i2c_devices();
-
-	platform_device_register(&netspace_v2_leds);
-	platform_device_register(&netspace_v2_gpio_leds);
-	platform_device_register(&netspace_v2_gpio_buttons);
-	if (machine_is_netspace_max_v2())
-		platform_device_register(&netspace_max_v2_gpio_fan);
-
-	if (gpio_request(NETSPACE_V2_GPIO_POWER_OFF, "power-off") == 0 &&
-	    gpio_direction_output(NETSPACE_V2_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = netspace_v2_power_off;
-	else
-		pr_err("netspace_v2: failed to configure power-off GPIO\n");
-}
-
-#ifdef CONFIG_MACH_NETSPACE_V2
-MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
-	.atag_offset	= 0x100,
-	.init_machine	= netspace_v2_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_INETSPACE_V2
-MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
-	.atag_offset	= 0x100,
-	.init_machine	= netspace_v2_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_NETSPACE_MAX_V2
-MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
-	.atag_offset	= 0x100,
-	.init_machine	= netspace_v2_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index ddcb09f..12d86f3 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -20,6 +20,16 @@
 #include <mach/bridge-regs.h>
 #include "common.h"
 
+/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
+#define KIRKWOOD_MBUS_PCIE0_MEM_TARGET    0x4
+#define KIRKWOOD_MBUS_PCIE0_MEM_ATTR      0xe8
+#define KIRKWOOD_MBUS_PCIE0_IO_TARGET     0x4
+#define KIRKWOOD_MBUS_PCIE0_IO_ATTR       0xe0
+#define KIRKWOOD_MBUS_PCIE1_MEM_TARGET    0x4
+#define KIRKWOOD_MBUS_PCIE1_MEM_ATTR      0xd8
+#define KIRKWOOD_MBUS_PCIE1_IO_TARGET     0x4
+#define KIRKWOOD_MBUS_PCIE1_IO_ATTR       0xd0
+
 static void kirkwood_enable_pcie_clk(const char *port)
 {
 	struct clk *clk;
@@ -254,26 +264,24 @@ static void __init add_pcie_port(int index, void __iomem *base)
 
 void __init kirkwood_pcie_init(unsigned int portmask)
 {
-	mvebu_mbus_add_window_remap_flags("pcie0.0",
+	mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE0_IO_TARGET,
+					  KIRKWOOD_MBUS_PCIE0_IO_ATTR,
 					  KIRKWOOD_PCIE_IO_PHYS_BASE,
 					  KIRKWOOD_PCIE_IO_SIZE,
-					  KIRKWOOD_PCIE_IO_BUS_BASE,
-					  MVEBU_MBUS_PCI_IO);
-	mvebu_mbus_add_window_remap_flags("pcie0.0",
-					  KIRKWOOD_PCIE_MEM_PHYS_BASE,
-					  KIRKWOOD_PCIE_MEM_SIZE,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
-	mvebu_mbus_add_window_remap_flags("pcie1.0",
+					  KIRKWOOD_PCIE_IO_BUS_BASE);
+	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE0_MEM_TARGET,
+				    KIRKWOOD_MBUS_PCIE0_MEM_ATTR,
+				    KIRKWOOD_PCIE_MEM_PHYS_BASE,
+				    KIRKWOOD_PCIE_MEM_SIZE);
+	mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE1_IO_TARGET,
+					  KIRKWOOD_MBUS_PCIE1_IO_ATTR,
 					  KIRKWOOD_PCIE1_IO_PHYS_BASE,
 					  KIRKWOOD_PCIE1_IO_SIZE,
-					  KIRKWOOD_PCIE1_IO_BUS_BASE,
-					  MVEBU_MBUS_PCI_IO);
-	mvebu_mbus_add_window_remap_flags("pcie1.0",
-					  KIRKWOOD_PCIE1_MEM_PHYS_BASE,
-					  KIRKWOOD_PCIE1_MEM_SIZE,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
+					  KIRKWOOD_PCIE1_IO_BUS_BASE);
+	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE1_MEM_TARGET,
+				    KIRKWOOD_MBUS_PCIE1_MEM_ATTR,
+				    KIRKWOOD_PCIE1_MEM_PHYS_BASE,
+				    KIRKWOOD_PCIE1_MEM_SIZE);
 
 	vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
 
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
deleted file mode 100644
index 55b68fa..0000000
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/sheevaplug-setup.c
- *
- * Marvell SheevaPlug Reference Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition sheevaplug_nand_parts[] = {
-	{
-		.name = "u-boot",
-		.offset = 0,
-		.size = SZ_1M
-	}, {
-		.name = "uImage",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = SZ_4M
-	}, {
-		.name = "root",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = MTDPART_SIZ_FULL
-	},
-};
-
-static struct mv643xx_eth_platform_data sheevaplug_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv_sata_platform_data sheeva_esata_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
-	/* unfortunately the CD signal has not been connected */
-};
-
-static struct mvsdio_platform_data sheeva_esata_mvsdio_data = {
-	.gpio_write_protect = 44, /* MPP44 used as SD write protect */
-	.gpio_card_detect = 47,	  /* MPP47 used as SD card detect */
-};
-
-static struct gpio_led sheevaplug_led_pins[] = {
-	{
-		.name			= "plug:red:misc",
-		.default_trigger	= "none",
-		.gpio			= 46,
-		.active_low		= 1,
-	},
-	{
-		.name			= "plug:green:health",
-		.default_trigger	= "default-on",
-		.gpio			= 49,
-		.active_low		= 1,
-	},
-};
-
-static struct gpio_led_platform_data sheevaplug_led_data = {
-	.leds		= sheevaplug_led_pins,
-	.num_leds	= ARRAY_SIZE(sheevaplug_led_pins),
-};
-
-static struct platform_device sheevaplug_leds = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &sheevaplug_led_data,
-	}
-};
-
-static unsigned int sheevaplug_mpp_config[] __initdata = {
-	MPP29_GPIO,	/* USB Power Enable */
-	MPP46_GPIO,	/* LED Red */
-	MPP49_GPIO,	/* LED */
-	0
-};
-
-static unsigned int sheeva_esata_mpp_config[] __initdata = {
-	MPP29_GPIO,	/* USB Power Enable */
-	MPP44_GPIO,	/* SD Write Protect */
-	MPP47_GPIO,	/* SD Card Detect */
-	MPP49_GPIO,	/* LED Green */
-	0
-};
-
-static void __init sheevaplug_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-
-	/* setup gpio pin select */
-	if (machine_is_esata_sheevaplug())
-		kirkwood_mpp_conf(sheeva_esata_mpp_config);
-	else
-		kirkwood_mpp_conf(sheevaplug_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_nand_init(ARRAY_AND_SIZE(sheevaplug_nand_parts), 25);
-
-	if (gpio_request(29, "USB Power Enable") != 0 ||
-	    gpio_direction_output(29, 1) != 0)
-		pr_err("can't set up GPIO 29 (USB Power Enable)\n");
-	kirkwood_ehci_init();
-
-	kirkwood_ge00_init(&sheevaplug_ge00_data);
-
-	/* honor lower power consumption for plugs with out eSATA */
-	if (machine_is_esata_sheevaplug())
-		kirkwood_sata_init(&sheeva_esata_sata_data);
-
-	/* enable sd wp and sd cd on plugs with esata */
-	if (machine_is_esata_sheevaplug())
-		kirkwood_sdio_init(&sheeva_esata_mvsdio_data);
-	else
-		kirkwood_sdio_init(&sheevaplug_mvsdio_data);
-
-	platform_device_register(&sheevaplug_leds);
-}
-
-#ifdef CONFIG_MACH_SHEEVAPLUG
-MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
-	/* Maintainer: shadi Ammouri <shadi@marvell.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= sheevaplug_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
-MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
-	.atag_offset	= 0x100,
-	.init_machine	= sheevaplug_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
deleted file mode 100644
index 351bd6c..0000000
--- a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/debug-macro.S
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/*
- * Debug output is hardcoded to standard UART 5
-*/
-
-	.macro	addruart, rp, rv, tmp
-	ldreq	\rp, =0x40090000
-	ldrne	\rv, =0xF4090000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 614e41e..905efc8 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -121,8 +121,7 @@ config MSM_SMD
 	bool
 
 config MSM_GPIOMUX
-	depends on !(ARCH_MSM8X60 || ARCH_MSM8960)
-	bool "MSM V1 TLMM GPIOMUX architecture"
+	bool
 	help
 	  Support for MSM V1 TLMM GPIOMUX architecture.
 
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d257ff4..d872634 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,17 +1,16 @@
-obj-y += io.o timer.o
+obj-y += timer.o
 obj-y += clock.o
 
 obj-$(CONFIG_MSM_VIC) += irq-vic.o
-obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o
 
 obj-$(CONFIG_ARCH_MSM7X00A) += irq.o
 obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
 
 obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
 
-obj-$(CONFIG_ARCH_MSM7X00A) += dma.o
-obj-$(CONFIG_ARCH_MSM7X30) += dma.o
-obj-$(CONFIG_ARCH_QSD8X50) += dma.o
+obj-$(CONFIG_ARCH_MSM7X00A) += dma.o io.o
+obj-$(CONFIG_ARCH_MSM7X30) += dma.o io.o
+obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o
 
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
diff --git a/arch/arm/mach-msm/board-dt-8660.c b/arch/arm/mach-msm/board-dt-8660.c
index 492f5cd..c294689 100644
--- a/arch/arm/mach-msm/board-dt-8660.c
+++ b/arch/arm/mach-msm/board-dt-8660.c
@@ -15,8 +15,8 @@
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 
-#include <mach/board.h>
 #include "common.h"
 
 static void __init msm8x60_init_late(void)
@@ -42,9 +42,7 @@ static const char *msm8x60_fluid_match[] __initdata = {
 
 DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
 	.smp = smp_ops(msm_smp_ops),
-	.map_io = msm_map_msm8x60_io,
 	.init_machine = msm8x60_dt_init,
 	.init_late = msm8x60_init_late,
-	.init_time	= msm_dt_timer_init,
 	.dt_compat = msm8x60_fluid_match,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-dt-8960.c b/arch/arm/mach-msm/board-dt-8960.c
index bb55309..d4ca52c 100644
--- a/arch/arm/mach-msm/board-dt-8960.c
+++ b/arch/arm/mach-msm/board-dt-8960.c
@@ -14,6 +14,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 
 #include "common.h"
 
@@ -29,8 +30,6 @@ static const char * const msm8960_dt_match[] __initconst = {
 
 DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)")
 	.smp = smp_ops(msm_smp_ops),
-	.map_io = msm_map_msm8960_io,
-	.init_time	= msm_dt_timer_init,
 	.init_machine = msm_dt_init,
 	.dt_compat = msm8960_dt_match,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 803651a..a775298 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -29,7 +29,6 @@
 #include <asm/setup.h>
 
 #include <mach/irqs.h>
-#include <mach/board.h>
 #include <mach/msm_iomap.h>
 
 #include <linux/mtd/nand.h>
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index 30c3496..7d9981c 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -28,12 +28,12 @@
 #include <asm/mach/map.h>
 #include <asm/setup.h>
 
-#include <mach/board.h>
 #include <mach/hardware.h>
 
 #include "board-mahimahi.h"
 #include "devices.h"
 #include "proc_comm.h"
+#include "common.h"
 
 static uint debug_uart;
 
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index db3d8c0..f9af5a4 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -30,7 +30,6 @@
 #include <asm/memory.h>
 #include <asm/setup.h>
 
-#include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
 
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index f14a73d..5f933bc 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 
-#include <mach/board.h>
 #include <mach/irqs.h>
 #include <mach/sirc.h>
 #include <mach/vreg.h>
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index 7073011..3276051 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -28,7 +28,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <mach/vreg.h>
-#include <mach/board.h>
 
 #include <asm/io.h>
 #include <asm/delay.h>
@@ -41,6 +40,7 @@
 #include "board-sapphire.h"
 #include "proc_comm.h"
 #include "devices.h"
+#include "common.h"
 
 void msm_init_irq(void);
 void msm_init_gpio(void);
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 64a46eb..ccf6621 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -25,7 +25,6 @@
 #include <asm/mach/map.h>
 #include <asm/setup.h>
 
-#include <mach/board.h>
 #include <mach/hardware.h>
 #include <mach/msm_iomap.h>
 
diff --git a/arch/arm/mach-msm/board-trout.h b/arch/arm/mach-msm/board-trout.h
index 651851c..b2379ed 100644
--- a/arch/arm/mach-msm/board-trout.h
+++ b/arch/arm/mach-msm/board-trout.h
@@ -4,7 +4,7 @@
 #ifndef __ARCH_ARM_MACH_MSM_BOARD_TROUT_H
 #define __ARCH_ARM_MACH_MSM_BOARD_TROUT_H
 
-#include <mach/board.h>
+#include "common.h"
 
 #define MSM_SMI_BASE		0x00000000
 #define MSM_SMI_SIZE		0x00800000
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h
index 421cf77..33c7725 100644
--- a/arch/arm/mach-msm/common.h
+++ b/arch/arm/mach-msm/common.h
@@ -14,13 +14,10 @@
 
 extern void msm7x01_timer_init(void);
 extern void msm7x30_timer_init(void);
-extern void msm_dt_timer_init(void);
 extern void qsd8x50_timer_init(void);
 
 extern void msm_map_common_io(void);
 extern void msm_map_msm7x30_io(void);
-extern void msm_map_msm8x60_io(void);
-extern void msm_map_msm8960_io(void);
 extern void msm_map_qsd8x50_io(void);
 
 extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
@@ -29,4 +26,19 @@ extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
 extern struct smp_operations msm_smp_ops;
 extern void msm_cpu_die(unsigned int cpu);
 
+struct msm_mmc_platform_data;
+
+extern void msm_add_devices(void);
+extern void msm_init_irq(void);
+extern void msm_init_gpio(void);
+extern int msm_add_sdcc(unsigned int controller,
+			struct msm_mmc_platform_data *plat,
+			unsigned int stat_irq, unsigned long stat_irq_flags);
+
+#if defined(CONFIG_MSM_SMD) && defined(CONFIG_DEBUG_FS)
+extern int smd_debugfs_init(void);
+#else
+static inline int smd_debugfs_init(void) { return 0; }
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
deleted file mode 100644
index 0fb7a17..0000000
--- a/arch/arm/mach-msm/devices-iommu.c
+++ /dev/null
@@ -1,912 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/bootmem.h>
-#include <linux/module.h>
-#include <mach/irqs.h>
-#include <mach/iommu.h>
-
-static struct resource msm_iommu_jpegd_resources[] = {
-	{
-		.start = 0x07300000,
-		.end   = 0x07300000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
-		.end   = SMMU_JPEGD_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vpe_resources[] = {
-	{
-		.start = 0x07400000,
-		.end   = 0x07400000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VPE_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VPE_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_mdp0_resources[] = {
-	{
-		.start = 0x07500000,
-		.end   = 0x07500000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_MDP0_CB_SC_SECURE_IRQ,
-		.end   = SMMU_MDP0_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_mdp1_resources[] = {
-	{
-		.start = 0x07600000,
-		.end   = 0x07600000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_MDP1_CB_SC_SECURE_IRQ,
-		.end   = SMMU_MDP1_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_rot_resources[] = {
-	{
-		.start = 0x07700000,
-		.end   = 0x07700000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_ROT_CB_SC_SECURE_IRQ,
-		.end   = SMMU_ROT_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_ijpeg_resources[] = {
-	{
-		.start = 0x07800000,
-		.end   = 0x07800000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
-		.end   = SMMU_IJPEG_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vfe_resources[] = {
-	{
-		.start = 0x07900000,
-		.end   = 0x07900000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VFE_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VFE_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vcodec_a_resources[] = {
-	{
-		.start = 0x07A00000,
-		.end   = 0x07A00000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vcodec_b_resources[] = {
-	{
-		.start = 0x07B00000,
-		.end   = 0x07B00000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx3d_resources[] = {
-	{
-		.start = 0x07C00000,
-		.end   = 0x07C00000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX3D_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx2d0_resources[] = {
-	{
-		.start = 0x07D00000,
-		.end   = 0x07D00000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx2d1_resources[] = {
-	{
-		.start = 0x07E00000,
-		.end   = 0x07E00000 + SZ_1M - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device msm_root_iommu_dev = {
-	.name = "msm_iommu",
-	.id = -1,
-};
-
-static struct msm_iommu_dev jpegd_iommu = {
-	.name = "jpegd",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev vpe_iommu = {
-	.name = "vpe",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev mdp0_iommu = {
-	.name = "mdp0",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev mdp1_iommu = {
-	.name = "mdp1",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev rot_iommu = {
-	.name = "rot",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev ijpeg_iommu = {
-	.name = "ijpeg",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev vfe_iommu = {
-	.name = "vfe",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev vcodec_a_iommu = {
-	.name = "vcodec_a",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev vcodec_b_iommu = {
-	.name = "vcodec_b",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev gfx3d_iommu = {
-	.name = "gfx3d",
-	.ncb = 3,
-};
-
-static struct msm_iommu_dev gfx2d0_iommu = {
-	.name = "gfx2d0",
-	.ncb = 2,
-};
-
-static struct msm_iommu_dev gfx2d1_iommu = {
-	.name = "gfx2d1",
-	.ncb = 2,
-};
-
-static struct platform_device msm_device_iommu_jpegd = {
-	.name = "msm_iommu",
-	.id = 0,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
-	.resource = msm_iommu_jpegd_resources,
-};
-
-static struct platform_device msm_device_iommu_vpe = {
-	.name = "msm_iommu",
-	.id = 1,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
-	.resource = msm_iommu_vpe_resources,
-};
-
-static struct platform_device msm_device_iommu_mdp0 = {
-	.name = "msm_iommu",
-	.id = 2,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
-	.resource = msm_iommu_mdp0_resources,
-};
-
-static struct platform_device msm_device_iommu_mdp1 = {
-	.name = "msm_iommu",
-	.id = 3,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
-	.resource = msm_iommu_mdp1_resources,
-};
-
-static struct platform_device msm_device_iommu_rot = {
-	.name = "msm_iommu",
-	.id = 4,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
-	.resource = msm_iommu_rot_resources,
-};
-
-static struct platform_device msm_device_iommu_ijpeg = {
-	.name = "msm_iommu",
-	.id = 5,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
-	.resource = msm_iommu_ijpeg_resources,
-};
-
-static struct platform_device msm_device_iommu_vfe = {
-	.name = "msm_iommu",
-	.id = 6,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
-	.resource = msm_iommu_vfe_resources,
-};
-
-static struct platform_device msm_device_iommu_vcodec_a = {
-	.name = "msm_iommu",
-	.id = 7,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
-	.resource = msm_iommu_vcodec_a_resources,
-};
-
-static struct platform_device msm_device_iommu_vcodec_b = {
-	.name = "msm_iommu",
-	.id = 8,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
-	.resource = msm_iommu_vcodec_b_resources,
-};
-
-static struct platform_device msm_device_iommu_gfx3d = {
-	.name = "msm_iommu",
-	.id = 9,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
-	.resource = msm_iommu_gfx3d_resources,
-};
-
-static struct platform_device msm_device_iommu_gfx2d0 = {
-	.name = "msm_iommu",
-	.id = 10,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
-	.resource = msm_iommu_gfx2d0_resources,
-};
-
-struct platform_device msm_device_iommu_gfx2d1 = {
-	.name = "msm_iommu",
-	.id = 11,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
-	.resource = msm_iommu_gfx2d1_resources,
-};
-
-static struct msm_iommu_ctx_dev jpegd_src_ctx = {
-	.name = "jpegd_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
-	.name = "jpegd_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev vpe_src_ctx = {
-	.name = "vpe_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev vpe_dst_ctx = {
-	.name = "vpe_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
-	.name = "mdp_vg1",
-	.num = 0,
-	.mids = {0, 2, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
-	.name = "mdp_rgb1",
-	.num = 1,
-	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
-	.name = "mdp_vg2",
-	.num = 0,
-	.mids = {0, 2, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
-	.name = "mdp_rgb2",
-	.num = 1,
-	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
-};
-
-static struct msm_iommu_ctx_dev rot_src_ctx = {
-	.name = "rot_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev rot_dst_ctx = {
-	.name = "rot_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
-	.name = "ijpeg_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
-	.name = "ijpeg_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
-	.name = "vfe_imgwr",
-	.num = 0,
-	.mids = {2, 3, 4, 5, 6, 7, 8, -1}
-};
-
-static struct msm_iommu_ctx_dev vfe_misc_ctx = {
-	.name = "vfe_misc",
-	.num = 1,
-	.mids = {0, 1, 9, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
-	.name = "vcodec_a_stream",
-	.num = 0,
-	.mids = {2, 5, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
-	.name = "vcodec_a_mm1",
-	.num = 1,
-	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
-	.name = "vcodec_b_mm2",
-	.num = 0,
-	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_user_ctx = {
-	.name = "gfx3d_user",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_priv_ctx = {
-	.name = "gfx3d_priv",
-	.num = 1,
-	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
-		 31, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
-	.name = "gfx2d0_2d0",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
-	.name = "gfx2d1_2d1",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct platform_device msm_device_jpegd_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 0,
-	.dev = {
-		.parent = &msm_device_iommu_jpegd.dev,
-	},
-};
-
-static struct platform_device msm_device_jpegd_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 1,
-	.dev = {
-		.parent = &msm_device_iommu_jpegd.dev,
-	},
-};
-
-static struct platform_device msm_device_vpe_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 2,
-	.dev = {
-		.parent = &msm_device_iommu_vpe.dev,
-	},
-};
-
-static struct platform_device msm_device_vpe_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 3,
-	.dev = {
-		.parent = &msm_device_iommu_vpe.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_vg1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 4,
-	.dev = {
-		.parent = &msm_device_iommu_mdp0.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_rgb1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 5,
-	.dev = {
-		.parent = &msm_device_iommu_mdp0.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_vg2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 6,
-	.dev = {
-		.parent = &msm_device_iommu_mdp1.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_rgb2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 7,
-	.dev = {
-		.parent = &msm_device_iommu_mdp1.dev,
-	},
-};
-
-static struct platform_device msm_device_rot_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 8,
-	.dev = {
-		.parent = &msm_device_iommu_rot.dev,
-	},
-};
-
-static struct platform_device msm_device_rot_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 9,
-	.dev = {
-		.parent = &msm_device_iommu_rot.dev,
-	},
-};
-
-static struct platform_device msm_device_ijpeg_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 10,
-	.dev = {
-		.parent = &msm_device_iommu_ijpeg.dev,
-	},
-};
-
-static struct platform_device msm_device_ijpeg_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 11,
-	.dev = {
-		.parent = &msm_device_iommu_ijpeg.dev,
-	},
-};
-
-static struct platform_device msm_device_vfe_imgwr_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 12,
-	.dev = {
-		.parent = &msm_device_iommu_vfe.dev,
-	},
-};
-
-static struct platform_device msm_device_vfe_misc_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 13,
-	.dev = {
-		.parent = &msm_device_iommu_vfe.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_a_stream_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 14,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_a.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_a_mm1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 15,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_a.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_b_mm2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 16,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_b.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx3d_user_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 17,
-	.dev = {
-		.parent = &msm_device_iommu_gfx3d.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx3d_priv_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 18,
-	.dev = {
-		.parent = &msm_device_iommu_gfx3d.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d0_2d0_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 19,
-	.dev = {
-		.parent = &msm_device_iommu_gfx2d0.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d1_2d1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 20,
-	.dev = {
-		.parent = &msm_device_iommu_gfx2d1.dev,
-	},
-};
-
-static struct platform_device *msm_iommu_devs[] = {
-	&msm_device_iommu_jpegd,
-	&msm_device_iommu_vpe,
-	&msm_device_iommu_mdp0,
-	&msm_device_iommu_mdp1,
-	&msm_device_iommu_rot,
-	&msm_device_iommu_ijpeg,
-	&msm_device_iommu_vfe,
-	&msm_device_iommu_vcodec_a,
-	&msm_device_iommu_vcodec_b,
-	&msm_device_iommu_gfx3d,
-	&msm_device_iommu_gfx2d0,
-	&msm_device_iommu_gfx2d1,
-};
-
-static struct msm_iommu_dev *msm_iommu_data[] = {
-	&jpegd_iommu,
-	&vpe_iommu,
-	&mdp0_iommu,
-	&mdp1_iommu,
-	&rot_iommu,
-	&ijpeg_iommu,
-	&vfe_iommu,
-	&vcodec_a_iommu,
-	&vcodec_b_iommu,
-	&gfx3d_iommu,
-	&gfx2d0_iommu,
-	&gfx2d1_iommu,
-};
-
-static struct platform_device *msm_iommu_ctx_devs[] = {
-	&msm_device_jpegd_src_ctx,
-	&msm_device_jpegd_dst_ctx,
-	&msm_device_vpe_src_ctx,
-	&msm_device_vpe_dst_ctx,
-	&msm_device_mdp_vg1_ctx,
-	&msm_device_mdp_rgb1_ctx,
-	&msm_device_mdp_vg2_ctx,
-	&msm_device_mdp_rgb2_ctx,
-	&msm_device_rot_src_ctx,
-	&msm_device_rot_dst_ctx,
-	&msm_device_ijpeg_src_ctx,
-	&msm_device_ijpeg_dst_ctx,
-	&msm_device_vfe_imgwr_ctx,
-	&msm_device_vfe_misc_ctx,
-	&msm_device_vcodec_a_stream_ctx,
-	&msm_device_vcodec_a_mm1_ctx,
-	&msm_device_vcodec_b_mm2_ctx,
-	&msm_device_gfx3d_user_ctx,
-	&msm_device_gfx3d_priv_ctx,
-	&msm_device_gfx2d0_2d0_ctx,
-	&msm_device_gfx2d1_2d1_ctx,
-};
-
-static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
-	&jpegd_src_ctx,
-	&jpegd_dst_ctx,
-	&vpe_src_ctx,
-	&vpe_dst_ctx,
-	&mdp_vg1_ctx,
-	&mdp_rgb1_ctx,
-	&mdp_vg2_ctx,
-	&mdp_rgb2_ctx,
-	&rot_src_ctx,
-	&rot_dst_ctx,
-	&ijpeg_src_ctx,
-	&ijpeg_dst_ctx,
-	&vfe_imgwr_ctx,
-	&vfe_misc_ctx,
-	&vcodec_a_stream_ctx,
-	&vcodec_a_mm1_ctx,
-	&vcodec_b_mm2_ctx,
-	&gfx3d_user_ctx,
-	&gfx3d_priv_ctx,
-	&gfx2d0_2d0_ctx,
-	&gfx2d1_2d1_ctx,
-};
-
-static int __init msm8x60_iommu_init(void)
-{
-	int ret, i;
-
-	ret = platform_device_register(&msm_root_iommu_dev);
-	if (ret != 0) {
-		pr_err("Failed to register root IOMMU device!\n");
-		goto failure;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_devs[i],
-					       msm_iommu_data[i],
-					       sizeof(struct msm_iommu_dev));
-		if (ret != 0) {
-			pr_err("platform_device_add_data failed, "
-			       "i = %d\n", i);
-			goto failure_unwind;
-		}
-
-		ret = platform_device_register(msm_iommu_devs[i]);
-
-		if (ret != 0) {
-			pr_err("platform_device_register iommu failed, "
-			       "i = %d\n", i);
-			goto failure_unwind;
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_ctx_devs[i],
-					       msm_iommu_ctx_data[i],
-					       sizeof(*msm_iommu_ctx_devs[i]));
-		if (ret != 0) {
-			pr_err("platform_device_add_data iommu failed, "
-			       "i = %d\n", i);
-			goto failure_unwind2;
-		}
-
-		ret = platform_device_register(msm_iommu_ctx_devs[i]);
-		if (ret != 0) {
-			pr_err("platform_device_register ctx failed, "
-			       "i = %d\n", i);
-			goto failure_unwind2;
-		}
-	}
-	return 0;
-
-failure_unwind2:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
-failure_unwind:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_devs[i]);
-
-	platform_device_unregister(&msm_root_iommu_dev);
-failure:
-	return ret;
-}
-
-static void __exit msm8x60_iommu_exit(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
-		platform_device_unregister(msm_iommu_devs[i]);
-
-	platform_device_unregister(&msm_root_iommu_dev);
-}
-
-subsys_initcall(msm8x60_iommu_init);
-module_exit(msm8x60_iommu_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index d4db75a..6b0e984 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -21,10 +21,10 @@
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
-#include <mach/board.h>
 
 #include "devices.h"
 #include "smd_private.h"
+#include "common.h"
 
 #include <asm/mach/flash.h>
 
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index f551811..c1c45ad 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -21,9 +21,9 @@
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
-#include <mach/board.h>
 
 #include "devices.h"
+#include "common.h"
 
 #include <asm/mach/flash.h>
 
diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c
deleted file mode 100644
index 27de2ab..0000000
--- a/arch/arm/mach-msm/gpiomux-v1.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/kernel.h>
-#include "gpiomux.h"
-#include "proc_comm.h"
-
-void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
-{
-	unsigned tlmm_config  = (val & ~GPIOMUX_CTL_MASK) |
-				((gpio & 0x3ff) << 4);
-	unsigned tlmm_disable = 0;
-	int rc;
-
-	rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
-			   &tlmm_config, &tlmm_disable);
-	if (rc)
-		pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
-		       __func__, rc, tlmm_config, tlmm_disable);
-}
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
index 8e82f41..4410d77 100644
--- a/arch/arm/mach-msm/gpiomux.h
+++ b/arch/arm/mach-msm/gpiomux.h
@@ -73,16 +73,6 @@ extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
 int msm_gpiomux_write(unsigned gpio,
 		      gpiomux_config_t active,
 		      gpiomux_config_t suspended);
-
-/* Architecture-internal function for use by the framework only.
- * This function can assume the following:
- * - the gpio value has passed a bounds-check
- * - the gpiomux spinlock has been obtained
- *
- * This function is not for public consumption.  External users
- * should use msm_gpiomux_write.
- */
-void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
 #else
 static inline int msm_gpiomux_write(unsigned gpio,
 				    gpiomux_config_t active,
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
deleted file mode 100644
index c34e246..0000000
--- a/arch/arm/mach-msm/include/mach/board.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* arch/arm/mach-msm/include/mach/board.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_BOARD_H
-#define __ASM_ARCH_MSM_BOARD_H
-
-#include <linux/types.h>
-#include <linux/platform_data/mmc-msm_sdcc.h>
-
-/* common init routines for use by arch/arm/mach-msm/board-*.c */
-
-void __init msm_add_devices(void);
-void __init msm_init_irq(void);
-void __init msm_init_gpio(void);
-int __init msm_add_sdcc(unsigned int controller,
-			struct msm_mmc_platform_data *plat,
-			unsigned int stat_irq, unsigned long stat_irq_flags);
-
-#if defined(CONFIG_MSM_SMD) && defined(CONFIG_DEBUG_FS)
-int smd_debugfs_init(void);
-#else
-static inline int smd_debugfs_init(void) { return 0; }
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
deleted file mode 100644
index 0e05f88..0000000
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <mach/hardware.h>
-#include <mach/msm_iomap.h>
-
-	.macro	addruart, rp, rv, tmp
-#ifdef MSM_DEBUG_UART_PHYS
-	ldr	\rp, =MSM_DEBUG_UART_PHYS
-	ldr	\rv, =MSM_DEBUG_UART_BASE
-#endif
-	.endm
-
-	.macro	senduart, rd, rx
-#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
-	@ Write the 1 character to UARTDM_TF
-	str	\rd, [\rx, #0x70]
-#else
-	str	\rd, [\rx, #0x0C]
-#endif
-	.endm
-
-	.macro	waituart, rd, rx
-#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
-	@ check for TX_EMT in UARTDM_SR
-	ldr	\rd, [\rx, #0x08]
-	tst	\rd, #0x08
-	bne	1002f
-	@ wait for TXREADY in UARTDM_ISR
-1001:	ldr	\rd, [\rx, #0x14]
-	tst	\rd, #0x80
-	beq 	1001b
-1002:
-	@ Clear TX_READY by writing to the UARTDM_CR register
-	mov	\rd, #0x300
-	str	\rd, [\rx, #0x10]
-	@ Write 0x1 to NCF register
-	mov 	\rd, #0x1
-	str	\rd, [\rx, #0x40]
-	@ UARTDM reg. Read to induce delay
-	ldr	\rd, [\rx, #0x08]
-#else
-	@ wait for TX_READY
-1001:	ldr	\rd, [\rx, #0x08]
-	tst	\rd, #0x04
-	beq	1001b
-#endif
-	.endm
-
-	.macro	busyuart, rd, rx
-	.endm
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
deleted file mode 100644
index 5c7c955..0000000
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef MSM_IOMMU_H
-#define MSM_IOMMU_H
-
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-
-/* Sharability attributes of MSM IOMMU mappings */
-#define MSM_IOMMU_ATTR_NON_SH		0x0
-#define MSM_IOMMU_ATTR_SH		0x4
-
-/* Cacheability attributes of MSM IOMMU mappings */
-#define MSM_IOMMU_ATTR_NONCACHED	0x0
-#define MSM_IOMMU_ATTR_CACHED_WB_WA	0x1
-#define MSM_IOMMU_ATTR_CACHED_WB_NWA	0x2
-#define MSM_IOMMU_ATTR_CACHED_WT	0x3
-
-/* Mask for the cache policy attribute */
-#define MSM_IOMMU_CP_MASK		0x03
-
-/* Maximum number of Machine IDs that we are allowing to be mapped to the same
- * context bank. The number of MIDs mapped to the same CB does not affect
- * performance, but there is a practical limit on how many distinct MIDs may
- * be present. These mappings are typically determined at design time and are
- * not expected to change at run time.
- */
-#define MAX_NUM_MIDS	32
-
-/**
- * struct msm_iommu_dev - a single IOMMU hardware instance
- * name		Human-readable name given to this IOMMU HW instance
- * ncb		Number of context banks present on this IOMMU HW instance
- */
-struct msm_iommu_dev {
-	const char *name;
-	int ncb;
-};
-
-/**
- * struct msm_iommu_ctx_dev - an IOMMU context bank instance
- * name		Human-readable name given to this context bank
- * num		Index of this context bank within the hardware
- * mids		List of Machine IDs that are to be mapped into this context
- *		bank, terminated by -1. The MID is a set of signals on the
- *		AXI bus that identifies the function associated with a specific
- *		memory request. (See ARM spec).
- */
-struct msm_iommu_ctx_dev {
-	const char *name;
-	int num;
-	int mids[MAX_NUM_MIDS];
-};
-
-
-/**
- * struct msm_iommu_drvdata - A single IOMMU hardware instance
- * @base:	IOMMU config port base address (VA)
- * @ncb		The number of contexts on this IOMMU
- * @irq:	Interrupt number
- * @clk:	The bus clock for this IOMMU hardware instance
- * @pclk:	The clock for the IOMMU bus interconnect
- *
- * A msm_iommu_drvdata holds the global driver data about a single piece
- * of an IOMMU hardware instance.
- */
-struct msm_iommu_drvdata {
-	void __iomem *base;
-	int irq;
-	int ncb;
-	struct clk *clk;
-	struct clk *pclk;
-};
-
-/**
- * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
- * @num:		Hardware context number of this context
- * @pdev:		Platform device associated wit this HW instance
- * @attached_elm:	List element for domains to track which devices are
- *			attached to them
- *
- * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
- * within each IOMMU hardware instance
- */
-struct msm_iommu_ctx_drvdata {
-	int num;
-	struct platform_device *pdev;
-	struct list_head attached_elm;
-};
-
-/*
- * Look up an IOMMU context device by its context name. NULL if none found.
- * Useful for testing and drivers that do not yet fully have IOMMU stuff in
- * their platform devices.
- */
-struct device *msm_iommu_get_ctx(const char *ctx_name);
-
-/*
- * Interrupt handler for the IOMMU context fault interrupt. Hooking the
- * interrupt is not supported in the API yet, but this will print an error
- * message and dump useful IOMMU registers.
- */
-irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
deleted file mode 100644
index fc16010..0000000
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ /dev/null
@@ -1,1865 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
-#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
-
-#define CTX_SHIFT 12
-
-#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg)))
-#define GET_CTX_REG(reg, base, ctx) \
-				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
-
-#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
-
-#define SET_CTX_REG(reg, base, ctx, val) \
-			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
-
-/* Wrappers for numbered registers */
-#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
-#define GET_GLOBAL_REG_N(b, n, r)    GET_GLOBAL_REG(b, ((r) + (n << 2)))
-
-/* Field wrappers */
-#define GET_GLOBAL_FIELD(b, r, F)    GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT)
-#define GET_CONTEXT_FIELD(b, c, r, F)	\
-	GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT)
-
-#define SET_GLOBAL_FIELD(b, r, F, v) \
-	SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v))
-#define SET_CONTEXT_FIELD(b, c, r, F, v)	\
-	SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
-
-#define GET_FIELD(addr, mask, shift)  ((readl(addr) >> (shift)) & (mask))
-
-#define SET_FIELD(addr, mask, shift, v) \
-do { \
-	int t = readl(addr); \
-	writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
-} while (0)
-
-
-#define NUM_FL_PTE	4096
-#define NUM_SL_PTE	256
-#define NUM_TEX_CLASS	8
-
-/* First-level page table bits */
-#define FL_BASE_MASK		0xFFFFFC00
-#define FL_TYPE_TABLE		(1 << 0)
-#define FL_TYPE_SECT		(2 << 0)
-#define FL_SUPERSECTION		(1 << 18)
-#define FL_AP_WRITE		(1 << 10)
-#define FL_AP_READ		(1 << 11)
-#define FL_SHARED		(1 << 16)
-#define FL_BUFFERABLE		(1 << 2)
-#define FL_CACHEABLE		(1 << 3)
-#define FL_TEX0			(1 << 12)
-#define FL_OFFSET(va)		(((va) & 0xFFF00000) >> 20)
-#define FL_NG			(1 << 17)
-
-/* Second-level page table bits */
-#define SL_BASE_MASK_LARGE	0xFFFF0000
-#define SL_BASE_MASK_SMALL	0xFFFFF000
-#define SL_TYPE_LARGE		(1 << 0)
-#define SL_TYPE_SMALL		(2 << 0)
-#define SL_AP0			(1 << 4)
-#define SL_AP1			(2 << 4)
-#define SL_SHARED		(1 << 10)
-#define SL_BUFFERABLE		(1 << 2)
-#define SL_CACHEABLE		(1 << 3)
-#define SL_TEX0			(1 << 6)
-#define SL_OFFSET(va)		(((va) & 0xFF000) >> 12)
-#define SL_NG			(1 << 11)
-
-/* Memory type and cache policy attributes */
-#define MT_SO			0
-#define MT_DEV			1
-#define MT_NORMAL		2
-#define CP_NONCACHED		0
-#define CP_WB_WA		1
-#define CP_WT			2
-#define CP_WB_NWA		3
-
-/* Global register setters / getters */
-#define SET_M2VCBR_N(b, N, v)	 SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
-#define SET_CBACR_N(b, N, v)	 SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
-#define SET_TLBRSW(b, v)	 SET_GLOBAL_REG(TLBRSW, (b), (v))
-#define SET_TLBTR0(b, v)	 SET_GLOBAL_REG(TLBTR0, (b), (v))
-#define SET_TLBTR1(b, v)	 SET_GLOBAL_REG(TLBTR1, (b), (v))
-#define SET_TLBTR2(b, v)	 SET_GLOBAL_REG(TLBTR2, (b), (v))
-#define SET_TESTBUSCR(b, v)	 SET_GLOBAL_REG(TESTBUSCR, (b), (v))
-#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v))
-#define SET_TLBIVMID(b, v)	 SET_GLOBAL_REG(TLBIVMID, (b), (v))
-#define SET_CR(b, v)		 SET_GLOBAL_REG(CR, (b), (v))
-#define SET_EAR(b, v)		 SET_GLOBAL_REG(EAR, (b), (v))
-#define SET_ESR(b, v)		 SET_GLOBAL_REG(ESR, (b), (v))
-#define SET_ESRRESTORE(b, v)	 SET_GLOBAL_REG(ESRRESTORE, (b), (v))
-#define SET_ESYNR0(b, v)	 SET_GLOBAL_REG(ESYNR0, (b), (v))
-#define SET_ESYNR1(b, v)	 SET_GLOBAL_REG(ESYNR1, (b), (v))
-#define SET_RPU_ACR(b, v)	 SET_GLOBAL_REG(RPU_ACR, (b), (v))
-
-#define GET_M2VCBR_N(b, N)	 GET_GLOBAL_REG_N(M2VCBR_N, N, (b))
-#define GET_CBACR_N(b, N)	 GET_GLOBAL_REG_N(CBACR_N, N, (b))
-#define GET_TLBTR0(b)		 GET_GLOBAL_REG(TLBTR0, (b))
-#define GET_TLBTR1(b)		 GET_GLOBAL_REG(TLBTR1, (b))
-#define GET_TLBTR2(b)		 GET_GLOBAL_REG(TLBTR2, (b))
-#define GET_TESTBUSCR(b)	 GET_GLOBAL_REG(TESTBUSCR, (b))
-#define GET_GLOBAL_TLBIALL(b)	 GET_GLOBAL_REG(GLOBAL_TLBIALL, (b))
-#define GET_TLBIVMID(b)		 GET_GLOBAL_REG(TLBIVMID, (b))
-#define GET_CR(b)		 GET_GLOBAL_REG(CR, (b))
-#define GET_EAR(b)		 GET_GLOBAL_REG(EAR, (b))
-#define GET_ESR(b)		 GET_GLOBAL_REG(ESR, (b))
-#define GET_ESRRESTORE(b)	 GET_GLOBAL_REG(ESRRESTORE, (b))
-#define GET_ESYNR0(b)		 GET_GLOBAL_REG(ESYNR0, (b))
-#define GET_ESYNR1(b)		 GET_GLOBAL_REG(ESYNR1, (b))
-#define GET_REV(b)		 GET_GLOBAL_REG(REV, (b))
-#define GET_IDR(b)		 GET_GLOBAL_REG(IDR, (b))
-#define GET_RPU_ACR(b)		 GET_GLOBAL_REG(RPU_ACR, (b))
-
-
-/* Context register setters/getters */
-#define SET_SCTLR(b, c, v)	 SET_CTX_REG(SCTLR, (b), (c), (v))
-#define SET_ACTLR(b, c, v)	 SET_CTX_REG(ACTLR, (b), (c), (v))
-#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
-#define SET_TTBR0(b, c, v)	 SET_CTX_REG(TTBR0, (b), (c), (v))
-#define SET_TTBR1(b, c, v)	 SET_CTX_REG(TTBR1, (b), (c), (v))
-#define SET_TTBCR(b, c, v)	 SET_CTX_REG(TTBCR, (b), (c), (v))
-#define SET_PAR(b, c, v)	 SET_CTX_REG(PAR, (b), (c), (v))
-#define SET_FSR(b, c, v)	 SET_CTX_REG(FSR, (b), (c), (v))
-#define SET_FSRRESTORE(b, c, v)	 SET_CTX_REG(FSRRESTORE, (b), (c), (v))
-#define SET_FAR(b, c, v)	 SET_CTX_REG(FAR, (b), (c), (v))
-#define SET_FSYNR0(b, c, v)	 SET_CTX_REG(FSYNR0, (b), (c), (v))
-#define SET_FSYNR1(b, c, v)	 SET_CTX_REG(FSYNR1, (b), (c), (v))
-#define SET_PRRR(b, c, v)	 SET_CTX_REG(PRRR, (b), (c), (v))
-#define SET_NMRR(b, c, v)	 SET_CTX_REG(NMRR, (b), (c), (v))
-#define SET_TLBLKCR(b, c, v)	 SET_CTX_REG(TLBLCKR, (b), (c), (v))
-#define SET_V2PSR(b, c, v)	 SET_CTX_REG(V2PSR, (b), (c), (v))
-#define SET_TLBFLPTER(b, c, v)	 SET_CTX_REG(TLBFLPTER, (b), (c), (v))
-#define SET_TLBSLPTER(b, c, v)	 SET_CTX_REG(TLBSLPTER, (b), (c), (v))
-#define SET_BFBCR(b, c, v)	 SET_CTX_REG(BFBCR, (b), (c), (v))
-#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v))
-#define SET_TLBIASID(b, c, v)	 SET_CTX_REG(TLBIASID, (b), (c), (v))
-#define SET_TLBIVA(b, c, v)	 SET_CTX_REG(TLBIVA, (b), (c), (v))
-#define SET_TLBIVAA(b, c, v)	 SET_CTX_REG(TLBIVAA, (b), (c), (v))
-#define SET_V2PPR(b, c, v)	 SET_CTX_REG(V2PPR, (b), (c), (v))
-#define SET_V2PPW(b, c, v)	 SET_CTX_REG(V2PPW, (b), (c), (v))
-#define SET_V2PUR(b, c, v)	 SET_CTX_REG(V2PUR, (b), (c), (v))
-#define SET_V2PUW(b, c, v)	 SET_CTX_REG(V2PUW, (b), (c), (v))
-#define SET_RESUME(b, c, v)	 SET_CTX_REG(RESUME, (b), (c), (v))
-
-#define GET_SCTLR(b, c)		 GET_CTX_REG(SCTLR, (b), (c))
-#define GET_ACTLR(b, c)		 GET_CTX_REG(ACTLR, (b), (c))
-#define GET_CONTEXTIDR(b, c)	 GET_CTX_REG(CONTEXTIDR, (b), (c))
-#define GET_TTBR0(b, c)		 GET_CTX_REG(TTBR0, (b), (c))
-#define GET_TTBR1(b, c)		 GET_CTX_REG(TTBR1, (b), (c))
-#define GET_TTBCR(b, c)		 GET_CTX_REG(TTBCR, (b), (c))
-#define GET_PAR(b, c)		 GET_CTX_REG(PAR, (b), (c))
-#define GET_FSR(b, c)		 GET_CTX_REG(FSR, (b), (c))
-#define GET_FSRRESTORE(b, c)	 GET_CTX_REG(FSRRESTORE, (b), (c))
-#define GET_FAR(b, c)		 GET_CTX_REG(FAR, (b), (c))
-#define GET_FSYNR0(b, c)	 GET_CTX_REG(FSYNR0, (b), (c))
-#define GET_FSYNR1(b, c)	 GET_CTX_REG(FSYNR1, (b), (c))
-#define GET_PRRR(b, c)		 GET_CTX_REG(PRRR, (b), (c))
-#define GET_NMRR(b, c)		 GET_CTX_REG(NMRR, (b), (c))
-#define GET_TLBLCKR(b, c)	 GET_CTX_REG(TLBLCKR, (b), (c))
-#define GET_V2PSR(b, c)		 GET_CTX_REG(V2PSR, (b), (c))
-#define GET_TLBFLPTER(b, c)	 GET_CTX_REG(TLBFLPTER, (b), (c))
-#define GET_TLBSLPTER(b, c)	 GET_CTX_REG(TLBSLPTER, (b), (c))
-#define GET_BFBCR(b, c)		 GET_CTX_REG(BFBCR, (b), (c))
-#define GET_CTX_TLBIALL(b, c)	 GET_CTX_REG(CTX_TLBIALL, (b), (c))
-#define GET_TLBIASID(b, c)	 GET_CTX_REG(TLBIASID, (b), (c))
-#define GET_TLBIVA(b, c)	 GET_CTX_REG(TLBIVA, (b), (c))
-#define GET_TLBIVAA(b, c)	 GET_CTX_REG(TLBIVAA, (b), (c))
-#define GET_V2PPR(b, c)		 GET_CTX_REG(V2PPR, (b), (c))
-#define GET_V2PPW(b, c)		 GET_CTX_REG(V2PPW, (b), (c))
-#define GET_V2PUR(b, c)		 GET_CTX_REG(V2PUR, (b), (c))
-#define GET_V2PUW(b, c)		 GET_CTX_REG(V2PUW, (b), (c))
-#define GET_RESUME(b, c)	 GET_CTX_REG(RESUME, (b), (c))
-
-
-/* Global field setters / getters */
-/* Global Field Setters: */
-/* CBACR_N */
-#define SET_RWVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v)
-#define SET_RWE(b, n, v)      SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v)
-#define SET_RWGE(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v)
-#define SET_CBVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v)
-#define SET_IRPTNDX(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v)
-
-
-/* M2VCBR_N */
-#define SET_VMID(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v)
-#define SET_CBNDX(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v)
-#define SET_BYPASSD(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v)
-#define SET_BPRCOSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v)
-#define SET_BPRCISH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v)
-#define SET_BPRCNSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v)
-#define SET_BPSHCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v)
-#define SET_NSCFG(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v)
-#define SET_BPMTCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v)
-#define SET_BPMEMTYPE(b, n, v) \
-	SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v)
-
-
-/* CR */
-#define SET_RPUE(b, v)		 SET_GLOBAL_FIELD(b, CR, RPUE, v)
-#define SET_RPUERE(b, v)	 SET_GLOBAL_FIELD(b, CR, RPUERE, v)
-#define SET_RPUEIE(b, v)	 SET_GLOBAL_FIELD(b, CR, RPUEIE, v)
-#define SET_DCDEE(b, v)		 SET_GLOBAL_FIELD(b, CR, DCDEE, v)
-#define SET_CLIENTPD(b, v)       SET_GLOBAL_FIELD(b, CR, CLIENTPD, v)
-#define SET_STALLD(b, v)	 SET_GLOBAL_FIELD(b, CR, STALLD, v)
-#define SET_TLBLKCRWE(b, v)      SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v)
-#define SET_CR_TLBIALLCFG(b, v)  SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v)
-#define SET_TLBIVMIDCFG(b, v)    SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v)
-#define SET_CR_HUME(b, v)        SET_GLOBAL_FIELD(b, CR, CR_HUME, v)
-
-
-/* ESR */
-#define SET_CFG(b, v)		 SET_GLOBAL_FIELD(b, ESR, CFG, v)
-#define SET_BYPASS(b, v)	 SET_GLOBAL_FIELD(b, ESR, BYPASS, v)
-#define SET_ESR_MULTI(b, v)      SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v)
-
-
-/* ESYNR0 */
-#define SET_ESYNR0_AMID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v)
-#define SET_ESYNR0_APID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v)
-#define SET_ESYNR0_ABID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v)
-#define SET_ESYNR0_AVMID(b, v)   SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v)
-#define SET_ESYNR0_ATID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v)
-
-
-/* ESYNR1 */
-#define SET_ESYNR1_AMEMTYPE(b, v) \
-			SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v)
-#define SET_ESYNR1_ASHARED(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v)
-#define SET_ESYNR1_AINNERSHARED(b, v) \
-			SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v)
-#define SET_ESYNR1_APRIV(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v)
-#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v)
-#define SET_ESYNR1_AINST(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v)
-#define SET_ESYNR1_AWRITE(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v)
-#define SET_ESYNR1_ABURST(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v)
-#define SET_ESYNR1_ALEN(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v)
-#define SET_ESYNR1_ASIZE(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v)
-#define SET_ESYNR1_ALOCK(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v)
-#define SET_ESYNR1_AOOO(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v)
-#define SET_ESYNR1_AFULL(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v)
-#define SET_ESYNR1_AC(b, v)      SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v)
-#define SET_ESYNR1_DCD(b, v)     SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v)
-
-
-/* TESTBUSCR */
-#define SET_TBE(b, v)		 SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v)
-#define SET_SPDMBE(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v)
-#define SET_WGSEL(b, v)		 SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v)
-#define SET_TBLSEL(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v)
-#define SET_TBHSEL(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v)
-#define SET_SPDM0SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v)
-#define SET_SPDM1SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v)
-#define SET_SPDM2SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v)
-#define SET_SPDM3SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v)
-
-
-/* TLBIVMID */
-#define SET_TLBIVMID_VMID(b, v)  SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v)
-
-
-/* TLBRSW */
-#define SET_TLBRSW_INDEX(b, v)   SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v)
-#define SET_TLBBFBS(b, v)	 SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v)
-
-
-/* TLBTR0 */
-#define SET_PR(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, PR, v)
-#define SET_PW(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, PW, v)
-#define SET_UR(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, UR, v)
-#define SET_UW(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, UW, v)
-#define SET_XN(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, XN, v)
-#define SET_NSDESC(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v)
-#define SET_ISH(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, ISH, v)
-#define SET_SH(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, SH, v)
-#define SET_MT(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, MT, v)
-#define SET_DPSIZR(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v)
-#define SET_DPSIZC(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v)
-
-
-/* TLBTR1 */
-#define SET_TLBTR1_VMID(b, v)    SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v)
-#define SET_TLBTR1_PA(b, v)      SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v)
-
-
-/* TLBTR2 */
-#define SET_TLBTR2_ASID(b, v)    SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v)
-#define SET_TLBTR2_V(b, v)       SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v)
-#define SET_TLBTR2_NSTID(b, v)   SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v)
-#define SET_TLBTR2_NV(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v)
-#define SET_TLBTR2_VA(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v)
-
-
-/* Global Field Getters */
-/* CBACR_N */
-#define GET_RWVMID(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID)
-#define GET_RWE(b, n)		 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE)
-#define GET_RWGE(b, n)		 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE)
-#define GET_CBVMID(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID)
-#define GET_IRPTNDX(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX)
-
-
-/* M2VCBR_N */
-#define GET_VMID(b, n)       GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID)
-#define GET_CBNDX(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX)
-#define GET_BYPASSD(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD)
-#define GET_BPRCOSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH)
-#define GET_BPRCISH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH)
-#define GET_BPRCNSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH)
-#define GET_BPSHCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG)
-#define GET_NSCFG(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG)
-#define GET_BPMTCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG)
-#define GET_BPMEMTYPE(b, n)  GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE)
-
-
-/* CR */
-#define GET_RPUE(b)		 GET_GLOBAL_FIELD(b, CR, RPUE)
-#define GET_RPUERE(b)		 GET_GLOBAL_FIELD(b, CR, RPUERE)
-#define GET_RPUEIE(b)		 GET_GLOBAL_FIELD(b, CR, RPUEIE)
-#define GET_DCDEE(b)		 GET_GLOBAL_FIELD(b, CR, DCDEE)
-#define GET_CLIENTPD(b)		 GET_GLOBAL_FIELD(b, CR, CLIENTPD)
-#define GET_STALLD(b)		 GET_GLOBAL_FIELD(b, CR, STALLD)
-#define GET_TLBLKCRWE(b)	 GET_GLOBAL_FIELD(b, CR, TLBLKCRWE)
-#define GET_CR_TLBIALLCFG(b)	 GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG)
-#define GET_TLBIVMIDCFG(b)	 GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG)
-#define GET_CR_HUME(b)		 GET_GLOBAL_FIELD(b, CR, CR_HUME)
-
-
-/* ESR */
-#define GET_CFG(b)		 GET_GLOBAL_FIELD(b, ESR, CFG)
-#define GET_BYPASS(b)		 GET_GLOBAL_FIELD(b, ESR, BYPASS)
-#define GET_ESR_MULTI(b)	 GET_GLOBAL_FIELD(b, ESR, ESR_MULTI)
-
-
-/* ESYNR0 */
-#define GET_ESYNR0_AMID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID)
-#define GET_ESYNR0_APID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID)
-#define GET_ESYNR0_ABID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID)
-#define GET_ESYNR0_AVMID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID)
-#define GET_ESYNR0_ATID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID)
-
-
-/* ESYNR1 */
-#define GET_ESYNR1_AMEMTYPE(b)   GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE)
-#define GET_ESYNR1_ASHARED(b)    GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED)
-#define GET_ESYNR1_AINNERSHARED(b) \
-			GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED)
-#define GET_ESYNR1_APRIV(b)      GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV)
-#define GET_ESYNR1_APROTNS(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS)
-#define GET_ESYNR1_AINST(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST)
-#define GET_ESYNR1_AWRITE(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE)
-#define GET_ESYNR1_ABURST(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST)
-#define GET_ESYNR1_ALEN(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN)
-#define GET_ESYNR1_ASIZE(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE)
-#define GET_ESYNR1_ALOCK(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK)
-#define GET_ESYNR1_AOOO(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO)
-#define GET_ESYNR1_AFULL(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL)
-#define GET_ESYNR1_AC(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC)
-#define GET_ESYNR1_DCD(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD)
-
-
-/* IDR */
-#define GET_NM2VCBMT(b)		 GET_GLOBAL_FIELD(b, IDR, NM2VCBMT)
-#define GET_HTW(b)		 GET_GLOBAL_FIELD(b, IDR, HTW)
-#define GET_HUM(b)		 GET_GLOBAL_FIELD(b, IDR, HUM)
-#define GET_TLBSIZE(b)		 GET_GLOBAL_FIELD(b, IDR, TLBSIZE)
-#define GET_NCB(b)		 GET_GLOBAL_FIELD(b, IDR, NCB)
-#define GET_NIRPT(b)		 GET_GLOBAL_FIELD(b, IDR, NIRPT)
-
-
-/* REV */
-#define GET_MAJOR(b)		 GET_GLOBAL_FIELD(b, REV, MAJOR)
-#define GET_MINOR(b)		 GET_GLOBAL_FIELD(b, REV, MINOR)
-
-
-/* TESTBUSCR */
-#define GET_TBE(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBE)
-#define GET_SPDMBE(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE)
-#define GET_WGSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL)
-#define GET_TBLSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL)
-#define GET_TBHSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL)
-#define GET_SPDM0SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL)
-#define GET_SPDM1SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL)
-#define GET_SPDM2SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL)
-#define GET_SPDM3SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL)
-
-
-/* TLBIVMID */
-#define GET_TLBIVMID_VMID(b)	 GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID)
-
-
-/* TLBTR0 */
-#define GET_PR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, PR)
-#define GET_PW(b)		 GET_GLOBAL_FIELD(b, TLBTR0, PW)
-#define GET_UR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, UR)
-#define GET_UW(b)		 GET_GLOBAL_FIELD(b, TLBTR0, UW)
-#define GET_XN(b)		 GET_GLOBAL_FIELD(b, TLBTR0, XN)
-#define GET_NSDESC(b)		 GET_GLOBAL_FIELD(b, TLBTR0, NSDESC)
-#define GET_ISH(b)		 GET_GLOBAL_FIELD(b, TLBTR0, ISH)
-#define GET_SH(b)		 GET_GLOBAL_FIELD(b, TLBTR0, SH)
-#define GET_MT(b)		 GET_GLOBAL_FIELD(b, TLBTR0, MT)
-#define GET_DPSIZR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR)
-#define GET_DPSIZC(b)		 GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC)
-
-
-/* TLBTR1 */
-#define GET_TLBTR1_VMID(b)	 GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID)
-#define GET_TLBTR1_PA(b)	 GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA)
-
-
-/* TLBTR2 */
-#define GET_TLBTR2_ASID(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID)
-#define GET_TLBTR2_V(b)		 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V)
-#define GET_TLBTR2_NSTID(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID)
-#define GET_TLBTR2_NV(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV)
-#define GET_TLBTR2_VA(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA)
-
-
-/* Context Register setters / getters */
-/* Context Register setters */
-/* ACTLR */
-#define SET_CFERE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v)
-#define SET_CFEIE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v)
-#define SET_PTSHCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v)
-#define SET_RCOSH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v)
-#define SET_RCISH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v)
-#define SET_RCNSH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v)
-#define SET_PRIVCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v)
-#define SET_DNA(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v)
-#define SET_DNLV2PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v)
-#define SET_TLBMCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v)
-#define SET_CFCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v)
-#define SET_TIPCF(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v)
-#define SET_V2PCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v)
-#define SET_HUME(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v)
-#define SET_PTMTCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v)
-#define SET_PTMEMTYPE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v)
-
-
-/* BFBCR */
-#define SET_BFBDFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v)
-#define SET_BFBSFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v)
-#define SET_SFVS(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v)
-#define SET_FLVIC(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v)
-#define SET_SLVIC(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v)
-
-
-/* CONTEXTIDR */
-#define SET_CONTEXTIDR_ASID(b, c, v)   \
-		SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v)
-#define SET_CONTEXTIDR_PROCID(b, c, v) \
-		SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v)
-
-
-/* FSR */
-#define SET_TF(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, TF, v)
-#define SET_AFF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, AFF, v)
-#define SET_APF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, APF, v)
-#define SET_TLBMF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v)
-#define SET_HTWDEEF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v)
-#define SET_HTWSEEF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v)
-#define SET_MHF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, MHF, v)
-#define SET_SL(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, SL, v)
-#define SET_SS(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, SS, v)
-#define SET_MULTI(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, MULTI, v)
-
-
-/* FSYNR0 */
-#define SET_AMID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v)
-#define SET_APID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v)
-#define SET_ABID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v)
-#define SET_ATID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v)
-
-
-/* FSYNR1 */
-#define SET_AMEMTYPE(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v)
-#define SET_ASHARED(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v)
-#define SET_AINNERSHARED(b, c, v)  \
-				SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v)
-#define SET_APRIV(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v)
-#define SET_APROTNS(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v)
-#define SET_AINST(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v)
-#define SET_AWRITE(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v)
-#define SET_ABURST(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v)
-#define SET_ALEN(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v)
-#define SET_FSYNR1_ASIZE(b, c, v) \
-				SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v)
-#define SET_ALOCK(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v)
-#define SET_AFULL(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v)
-
-
-/* NMRR */
-#define SET_ICPC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v)
-#define SET_ICPC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v)
-#define SET_ICPC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v)
-#define SET_ICPC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v)
-#define SET_ICPC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v)
-#define SET_ICPC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v)
-#define SET_ICPC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v)
-#define SET_ICPC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v)
-#define SET_OCPC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v)
-#define SET_OCPC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v)
-#define SET_OCPC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v)
-#define SET_OCPC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v)
-#define SET_OCPC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v)
-#define SET_OCPC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v)
-#define SET_OCPC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v)
-#define SET_OCPC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v)
-
-
-/* PAR */
-#define SET_FAULT(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT, v)
-
-#define SET_FAULT_TF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v)
-#define SET_FAULT_AFF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v)
-#define SET_FAULT_APF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v)
-#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v)
-#define SET_FAULT_HTWDEEF(b, c, v) \
-				SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v)
-#define SET_FAULT_HTWSEEF(b, c, v) \
-				SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v)
-#define SET_FAULT_MHF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v)
-#define SET_FAULT_SL(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v)
-#define SET_FAULT_SS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v)
-
-#define SET_NOFAULT_SS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v)
-#define SET_NOFAULT_MT(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v)
-#define SET_NOFAULT_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v)
-#define SET_NOFAULT_NS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v)
-#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v)
-#define SET_NPFAULT_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v)
-
-
-/* PRRR */
-#define SET_MTC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v)
-#define SET_MTC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v)
-#define SET_MTC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v)
-#define SET_MTC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v)
-#define SET_MTC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v)
-#define SET_MTC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v)
-#define SET_MTC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v)
-#define SET_MTC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v)
-#define SET_SHDSH0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v)
-#define SET_SHDSH1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v)
-#define SET_SHNMSH0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v)
-#define SET_SHNMSH1(b, c, v)     SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v)
-#define SET_NOS0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v)
-#define SET_NOS1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v)
-#define SET_NOS2(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v)
-#define SET_NOS3(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v)
-#define SET_NOS4(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v)
-#define SET_NOS5(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v)
-#define SET_NOS6(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v)
-#define SET_NOS7(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v)
-
-
-/* RESUME */
-#define SET_TNR(b, c, v)	 SET_CONTEXT_FIELD(b, c, RESUME, TNR, v)
-
-
-/* SCTLR */
-#define SET_M(b, c, v)		 SET_CONTEXT_FIELD(b, c, SCTLR, M, v)
-#define SET_TRE(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v)
-#define SET_AFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v)
-#define SET_HAF(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v)
-#define SET_BE(b, c, v)		 SET_CONTEXT_FIELD(b, c, SCTLR, BE, v)
-#define SET_AFFD(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v)
-
-
-/* TLBLKCR */
-#define SET_LKE(b, c, v)	   SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v)
-#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \
-			SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v)
-#define SET_TLBIASIDCFG(b, c, v) \
-			SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v)
-#define SET_TLBIVAACFG(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v)
-#define SET_FLOOR(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v)
-#define SET_VICTIM(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v)
-
-
-/* TTBCR */
-#define SET_N(b, c, v)	         SET_CONTEXT_FIELD(b, c, TTBCR, N, v)
-#define SET_PD0(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v)
-#define SET_PD1(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v)
-
-
-/* TTBR0 */
-#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v)
-#define SET_TTBR0_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v)
-#define SET_TTBR0_ORGN(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v)
-#define SET_TTBR0_NOS(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v)
-#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v)
-#define SET_TTBR0_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v)
-
-
-/* TTBR1 */
-#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v)
-#define SET_TTBR1_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v)
-#define SET_TTBR1_ORGN(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v)
-#define SET_TTBR1_NOS(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v)
-#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v)
-#define SET_TTBR1_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v)
-
-
-/* V2PSR */
-#define SET_HIT(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v)
-#define SET_INDEX(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v)
-
-
-/* Context Register getters */
-/* ACTLR */
-#define GET_CFERE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFERE)
-#define GET_CFEIE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE)
-#define GET_PTSHCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG)
-#define GET_RCOSH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH)
-#define GET_RCISH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCISH)
-#define GET_RCNSH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH)
-#define GET_PRIVCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG)
-#define GET_DNA(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, DNA)
-#define GET_DNLV2PA(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA)
-#define GET_TLBMCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG)
-#define GET_CFCFG(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG)
-#define GET_TIPCF(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF)
-#define GET_V2PCFG(b, c)        GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG)
-#define GET_HUME(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, HUME)
-#define GET_PTMTCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG)
-#define GET_PTMEMTYPE(b, c)     GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE)
-
-/* BFBCR */
-#define GET_BFBDFE(b, c)	GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE)
-#define GET_BFBSFE(b, c)	GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE)
-#define GET_SFVS(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, SFVS)
-#define GET_FLVIC(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC)
-#define GET_SLVIC(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC)
-
-
-/* CONTEXTIDR */
-#define GET_CONTEXTIDR_ASID(b, c) \
-			GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID)
-#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID)
-
-
-/* FSR */
-#define GET_TF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, TF)
-#define GET_AFF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, AFF)
-#define GET_APF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, APF)
-#define GET_TLBMF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, TLBMF)
-#define GET_HTWDEEF(b, c)	GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF)
-#define GET_HTWSEEF(b, c)	GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF)
-#define GET_MHF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, MHF)
-#define GET_SL(b, c)		GET_CONTEXT_FIELD(b, c, FSR, SL)
-#define GET_SS(b, c)		GET_CONTEXT_FIELD(b, c, FSR, SS)
-#define GET_MULTI(b, c)		GET_CONTEXT_FIELD(b, c, FSR, MULTI)
-
-
-/* FSYNR0 */
-#define GET_AMID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, AMID)
-#define GET_APID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, APID)
-#define GET_ABID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, ABID)
-#define GET_ATID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, ATID)
-
-
-/* FSYNR1 */
-#define GET_AMEMTYPE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE)
-#define GET_ASHARED(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED)
-#define GET_AINNERSHARED(b, c)  GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED)
-#define GET_APRIV(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV)
-#define GET_APROTNS(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS)
-#define GET_AINST(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, AINST)
-#define GET_AWRITE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE)
-#define GET_ABURST(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST)
-#define GET_ALEN(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN)
-#define GET_FSYNR1_ASIZE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE)
-#define GET_ALOCK(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK)
-#define GET_AFULL(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL)
-
-
-/* NMRR */
-#define GET_ICPC0(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC0)
-#define GET_ICPC1(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC1)
-#define GET_ICPC2(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC2)
-#define GET_ICPC3(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC3)
-#define GET_ICPC4(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC4)
-#define GET_ICPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC5)
-#define GET_ICPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC6)
-#define GET_ICPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC7)
-#define GET_OCPC0(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC0)
-#define GET_OCPC1(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC1)
-#define GET_OCPC2(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC2)
-#define GET_OCPC3(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC3)
-#define GET_OCPC4(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC4)
-#define GET_OCPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC5)
-#define GET_OCPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC6)
-#define GET_OCPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC7)
-#define NMRR_ICP(nmrr, n)	(((nmrr) & (3 << ((n) * 2))) >> ((n) * 2))
-#define NMRR_OCP(nmrr, n)	(((nmrr) & (3 << ((n) * 2 + 16))) >> \
-								((n) * 2 + 16))
-
-/* PAR */
-#define GET_FAULT(b, c)		GET_CONTEXT_FIELD(b, c, PAR, FAULT)
-
-#define GET_FAULT_TF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF)
-#define GET_FAULT_AFF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF)
-#define GET_FAULT_APF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF)
-#define GET_FAULT_TLBMF(b, c)   GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF)
-#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF)
-#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF)
-#define GET_FAULT_MHF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF)
-#define GET_FAULT_SL(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL)
-#define GET_FAULT_SS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS)
-
-#define GET_NOFAULT_SS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS)
-#define GET_NOFAULT_MT(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT)
-#define GET_NOFAULT_SH(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH)
-#define GET_NOFAULT_NS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS)
-#define GET_NOFAULT_NOS(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS)
-#define GET_NPFAULT_PA(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA)
-
-
-/* PRRR */
-#define GET_MTC0(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC0)
-#define GET_MTC1(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC1)
-#define GET_MTC2(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC2)
-#define GET_MTC3(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC3)
-#define GET_MTC4(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC4)
-#define GET_MTC5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC5)
-#define GET_MTC6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC6)
-#define GET_MTC7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC7)
-#define GET_SHDSH0(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0)
-#define GET_SHDSH1(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1)
-#define GET_SHNMSH0(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0)
-#define GET_SHNMSH1(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1)
-#define GET_NOS0(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS0)
-#define GET_NOS1(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS1)
-#define GET_NOS2(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS2)
-#define GET_NOS3(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS3)
-#define GET_NOS4(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS4)
-#define GET_NOS5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS5)
-#define GET_NOS6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS6)
-#define GET_NOS7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS7)
-#define PRRR_NOS(prrr, n)	 ((prrr) & (1 << ((n) + 24)) ? 1 : 0)
-#define PRRR_MT(prrr, n)	 ((((prrr) & (3 << ((n) * 2))) >> ((n) * 2)))
-
-
-/* RESUME */
-#define GET_TNR(b, c)		GET_CONTEXT_FIELD(b, c, RESUME, TNR)
-
-
-/* SCTLR */
-#define GET_M(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, M)
-#define GET_TRE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, TRE)
-#define GET_AFE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, AFE)
-#define GET_HAF(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, HAF)
-#define GET_BE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, BE)
-#define GET_AFFD(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, AFFD)
-
-
-/* TLBLKCR */
-#define GET_LKE(b, c)		GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE)
-#define GET_TLBLCKR_TLBIALLCFG(b, c) \
-			GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG)
-#define GET_TLBIASIDCFG(b, c)   GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG)
-#define GET_TLBIVAACFG(b, c)	GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG)
-#define GET_FLOOR(b, c)		GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR)
-#define GET_VICTIM(b, c)	GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM)
-
-
-/* TTBCR */
-#define GET_N(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, N)
-#define GET_PD0(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, PD0)
-#define GET_PD1(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, PD1)
-
-
-/* TTBR0 */
-#define GET_TTBR0_IRGNH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH)
-#define GET_TTBR0_SH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH)
-#define GET_TTBR0_ORGN(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN)
-#define GET_TTBR0_NOS(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS)
-#define GET_TTBR0_IRGNL(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL)
-#define GET_TTBR0_PA(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA)
-
-
-/* TTBR1 */
-#define GET_TTBR1_IRGNH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH)
-#define GET_TTBR1_SH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH)
-#define GET_TTBR1_ORGN(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN)
-#define GET_TTBR1_NOS(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS)
-#define GET_TTBR1_IRGNL(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL)
-#define GET_TTBR1_PA(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA)
-
-
-/* V2PSR */
-#define GET_HIT(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, HIT)
-#define GET_INDEX(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, INDEX)
-
-
-/* Global Registers */
-#define M2VCBR_N	(0xFF000)
-#define CBACR_N		(0xFF800)
-#define TLBRSW		(0xFFE00)
-#define TLBTR0		(0xFFE80)
-#define TLBTR1		(0xFFE84)
-#define TLBTR2		(0xFFE88)
-#define TESTBUSCR	(0xFFE8C)
-#define GLOBAL_TLBIALL	(0xFFF00)
-#define TLBIVMID	(0xFFF04)
-#define CR		(0xFFF80)
-#define EAR		(0xFFF84)
-#define ESR		(0xFFF88)
-#define ESRRESTORE	(0xFFF8C)
-#define ESYNR0		(0xFFF90)
-#define ESYNR1		(0xFFF94)
-#define REV		(0xFFFF4)
-#define IDR		(0xFFFF8)
-#define RPU_ACR		(0xFFFFC)
-
-
-/* Context Bank Registers */
-#define SCTLR		(0x000)
-#define ACTLR		(0x004)
-#define CONTEXTIDR	(0x008)
-#define TTBR0		(0x010)
-#define TTBR1		(0x014)
-#define TTBCR		(0x018)
-#define PAR		(0x01C)
-#define FSR		(0x020)
-#define FSRRESTORE	(0x024)
-#define FAR		(0x028)
-#define FSYNR0		(0x02C)
-#define FSYNR1		(0x030)
-#define PRRR		(0x034)
-#define NMRR		(0x038)
-#define TLBLCKR		(0x03C)
-#define V2PSR		(0x040)
-#define TLBFLPTER	(0x044)
-#define TLBSLPTER	(0x048)
-#define BFBCR		(0x04C)
-#define CTX_TLBIALL	(0x800)
-#define TLBIASID	(0x804)
-#define TLBIVA		(0x808)
-#define TLBIVAA		(0x80C)
-#define V2PPR		(0x810)
-#define V2PPW		(0x814)
-#define V2PUR		(0x818)
-#define V2PUW		(0x81C)
-#define RESUME		(0x820)
-
-
-/* Global Register Fields */
-/* CBACRn */
-#define RWVMID        (RWVMID_MASK       << RWVMID_SHIFT)
-#define RWE           (RWE_MASK          << RWE_SHIFT)
-#define RWGE          (RWGE_MASK         << RWGE_SHIFT)
-#define CBVMID        (CBVMID_MASK       << CBVMID_SHIFT)
-#define IRPTNDX       (IRPTNDX_MASK      << IRPTNDX_SHIFT)
-
-
-/* CR */
-#define RPUE          (RPUE_MASK          << RPUE_SHIFT)
-#define RPUERE        (RPUERE_MASK        << RPUERE_SHIFT)
-#define RPUEIE        (RPUEIE_MASK        << RPUEIE_SHIFT)
-#define DCDEE         (DCDEE_MASK         << DCDEE_SHIFT)
-#define CLIENTPD      (CLIENTPD_MASK      << CLIENTPD_SHIFT)
-#define STALLD        (STALLD_MASK        << STALLD_SHIFT)
-#define TLBLKCRWE     (TLBLKCRWE_MASK     << TLBLKCRWE_SHIFT)
-#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT)
-#define TLBIVMIDCFG   (TLBIVMIDCFG_MASK   << TLBIVMIDCFG_SHIFT)
-#define CR_HUME       (CR_HUME_MASK       << CR_HUME_SHIFT)
-
-
-/* ESR */
-#define CFG           (CFG_MASK          << CFG_SHIFT)
-#define BYPASS        (BYPASS_MASK       << BYPASS_SHIFT)
-#define ESR_MULTI     (ESR_MULTI_MASK    << ESR_MULTI_SHIFT)
-
-
-/* ESYNR0 */
-#define ESYNR0_AMID   (ESYNR0_AMID_MASK  << ESYNR0_AMID_SHIFT)
-#define ESYNR0_APID   (ESYNR0_APID_MASK  << ESYNR0_APID_SHIFT)
-#define ESYNR0_ABID   (ESYNR0_ABID_MASK  << ESYNR0_ABID_SHIFT)
-#define ESYNR0_AVMID  (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT)
-#define ESYNR0_ATID   (ESYNR0_ATID_MASK  << ESYNR0_ATID_SHIFT)
-
-
-/* ESYNR1 */
-#define ESYNR1_AMEMTYPE      (ESYNR1_AMEMTYPE_MASK    << ESYNR1_AMEMTYPE_SHIFT)
-#define ESYNR1_ASHARED       (ESYNR1_ASHARED_MASK     << ESYNR1_ASHARED_SHIFT)
-#define ESYNR1_AINNERSHARED  (ESYNR1_AINNERSHARED_MASK<< \
-						ESYNR1_AINNERSHARED_SHIFT)
-#define ESYNR1_APRIV         (ESYNR1_APRIV_MASK       << ESYNR1_APRIV_SHIFT)
-#define ESYNR1_APROTNS       (ESYNR1_APROTNS_MASK     << ESYNR1_APROTNS_SHIFT)
-#define ESYNR1_AINST         (ESYNR1_AINST_MASK       << ESYNR1_AINST_SHIFT)
-#define ESYNR1_AWRITE        (ESYNR1_AWRITE_MASK      << ESYNR1_AWRITE_SHIFT)
-#define ESYNR1_ABURST        (ESYNR1_ABURST_MASK      << ESYNR1_ABURST_SHIFT)
-#define ESYNR1_ALEN          (ESYNR1_ALEN_MASK        << ESYNR1_ALEN_SHIFT)
-#define ESYNR1_ASIZE         (ESYNR1_ASIZE_MASK       << ESYNR1_ASIZE_SHIFT)
-#define ESYNR1_ALOCK         (ESYNR1_ALOCK_MASK       << ESYNR1_ALOCK_SHIFT)
-#define ESYNR1_AOOO          (ESYNR1_AOOO_MASK        << ESYNR1_AOOO_SHIFT)
-#define ESYNR1_AFULL         (ESYNR1_AFULL_MASK       << ESYNR1_AFULL_SHIFT)
-#define ESYNR1_AC            (ESYNR1_AC_MASK          << ESYNR1_AC_SHIFT)
-#define ESYNR1_DCD           (ESYNR1_DCD_MASK         << ESYNR1_DCD_SHIFT)
-
-
-/* IDR */
-#define NM2VCBMT      (NM2VCBMT_MASK     << NM2VCBMT_SHIFT)
-#define HTW           (HTW_MASK          << HTW_SHIFT)
-#define HUM           (HUM_MASK          << HUM_SHIFT)
-#define TLBSIZE       (TLBSIZE_MASK      << TLBSIZE_SHIFT)
-#define NCB           (NCB_MASK          << NCB_SHIFT)
-#define NIRPT         (NIRPT_MASK        << NIRPT_SHIFT)
-
-
-/* M2VCBRn */
-#define VMID          (VMID_MASK         << VMID_SHIFT)
-#define CBNDX         (CBNDX_MASK        << CBNDX_SHIFT)
-#define BYPASSD       (BYPASSD_MASK      << BYPASSD_SHIFT)
-#define BPRCOSH       (BPRCOSH_MASK      << BPRCOSH_SHIFT)
-#define BPRCISH       (BPRCISH_MASK      << BPRCISH_SHIFT)
-#define BPRCNSH       (BPRCNSH_MASK      << BPRCNSH_SHIFT)
-#define BPSHCFG       (BPSHCFG_MASK      << BPSHCFG_SHIFT)
-#define NSCFG         (NSCFG_MASK        << NSCFG_SHIFT)
-#define BPMTCFG       (BPMTCFG_MASK      << BPMTCFG_SHIFT)
-#define BPMEMTYPE     (BPMEMTYPE_MASK    << BPMEMTYPE_SHIFT)
-
-
-/* REV */
-#define IDR_MINOR     (MINOR_MASK        << MINOR_SHIFT)
-#define IDR_MAJOR     (MAJOR_MASK        << MAJOR_SHIFT)
-
-
-/* TESTBUSCR */
-#define TBE           (TBE_MASK          << TBE_SHIFT)
-#define SPDMBE        (SPDMBE_MASK       << SPDMBE_SHIFT)
-#define WGSEL         (WGSEL_MASK        << WGSEL_SHIFT)
-#define TBLSEL        (TBLSEL_MASK       << TBLSEL_SHIFT)
-#define TBHSEL        (TBHSEL_MASK       << TBHSEL_SHIFT)
-#define SPDM0SEL      (SPDM0SEL_MASK     << SPDM0SEL_SHIFT)
-#define SPDM1SEL      (SPDM1SEL_MASK     << SPDM1SEL_SHIFT)
-#define SPDM2SEL      (SPDM2SEL_MASK     << SPDM2SEL_SHIFT)
-#define SPDM3SEL      (SPDM3SEL_MASK     << SPDM3SEL_SHIFT)
-
-
-/* TLBIVMID */
-#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT)
-
-
-/* TLBRSW */
-#define TLBRSW_INDEX  (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT)
-#define TLBBFBS       (TLBBFBS_MASK      << TLBBFBS_SHIFT)
-
-
-/* TLBTR0 */
-#define PR            (PR_MASK           << PR_SHIFT)
-#define PW            (PW_MASK           << PW_SHIFT)
-#define UR            (UR_MASK           << UR_SHIFT)
-#define UW            (UW_MASK           << UW_SHIFT)
-#define XN            (XN_MASK           << XN_SHIFT)
-#define NSDESC        (NSDESC_MASK       << NSDESC_SHIFT)
-#define ISH           (ISH_MASK          << ISH_SHIFT)
-#define SH            (SH_MASK           << SH_SHIFT)
-#define MT            (MT_MASK           << MT_SHIFT)
-#define DPSIZR        (DPSIZR_MASK       << DPSIZR_SHIFT)
-#define DPSIZC        (DPSIZC_MASK       << DPSIZC_SHIFT)
-
-
-/* TLBTR1 */
-#define TLBTR1_VMID   (TLBTR1_VMID_MASK  << TLBTR1_VMID_SHIFT)
-#define TLBTR1_PA     (TLBTR1_PA_MASK    << TLBTR1_PA_SHIFT)
-
-
-/* TLBTR2 */
-#define TLBTR2_ASID   (TLBTR2_ASID_MASK  << TLBTR2_ASID_SHIFT)
-#define TLBTR2_V      (TLBTR2_V_MASK     << TLBTR2_V_SHIFT)
-#define TLBTR2_NSTID  (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT)
-#define TLBTR2_NV     (TLBTR2_NV_MASK    << TLBTR2_NV_SHIFT)
-#define TLBTR2_VA     (TLBTR2_VA_MASK    << TLBTR2_VA_SHIFT)
-
-
-/* Context Register Fields */
-/* ACTLR */
-#define CFERE              (CFERE_MASK              << CFERE_SHIFT)
-#define CFEIE              (CFEIE_MASK              << CFEIE_SHIFT)
-#define PTSHCFG            (PTSHCFG_MASK            << PTSHCFG_SHIFT)
-#define RCOSH              (RCOSH_MASK              << RCOSH_SHIFT)
-#define RCISH              (RCISH_MASK              << RCISH_SHIFT)
-#define RCNSH              (RCNSH_MASK              << RCNSH_SHIFT)
-#define PRIVCFG            (PRIVCFG_MASK            << PRIVCFG_SHIFT)
-#define DNA                (DNA_MASK                << DNA_SHIFT)
-#define DNLV2PA            (DNLV2PA_MASK            << DNLV2PA_SHIFT)
-#define TLBMCFG            (TLBMCFG_MASK            << TLBMCFG_SHIFT)
-#define CFCFG              (CFCFG_MASK              << CFCFG_SHIFT)
-#define TIPCF              (TIPCF_MASK              << TIPCF_SHIFT)
-#define V2PCFG             (V2PCFG_MASK             << V2PCFG_SHIFT)
-#define HUME               (HUME_MASK               << HUME_SHIFT)
-#define PTMTCFG            (PTMTCFG_MASK            << PTMTCFG_SHIFT)
-#define PTMEMTYPE          (PTMEMTYPE_MASK          << PTMEMTYPE_SHIFT)
-
-
-/* BFBCR */
-#define BFBDFE             (BFBDFE_MASK             << BFBDFE_SHIFT)
-#define BFBSFE             (BFBSFE_MASK             << BFBSFE_SHIFT)
-#define SFVS               (SFVS_MASK               << SFVS_SHIFT)
-#define FLVIC              (FLVIC_MASK              << FLVIC_SHIFT)
-#define SLVIC              (SLVIC_MASK              << SLVIC_SHIFT)
-
-
-/* CONTEXTIDR */
-#define CONTEXTIDR_ASID    (CONTEXTIDR_ASID_MASK    << CONTEXTIDR_ASID_SHIFT)
-#define PROCID             (PROCID_MASK             << PROCID_SHIFT)
-
-
-/* FSR */
-#define TF                 (TF_MASK                 << TF_SHIFT)
-#define AFF                (AFF_MASK                << AFF_SHIFT)
-#define APF                (APF_MASK                << APF_SHIFT)
-#define TLBMF              (TLBMF_MASK              << TLBMF_SHIFT)
-#define HTWDEEF            (HTWDEEF_MASK            << HTWDEEF_SHIFT)
-#define HTWSEEF            (HTWSEEF_MASK            << HTWSEEF_SHIFT)
-#define MHF                (MHF_MASK                << MHF_SHIFT)
-#define SL                 (SL_MASK                 << SL_SHIFT)
-#define SS                 (SS_MASK                 << SS_SHIFT)
-#define MULTI              (MULTI_MASK              << MULTI_SHIFT)
-
-
-/* FSYNR0 */
-#define AMID               (AMID_MASK               << AMID_SHIFT)
-#define APID               (APID_MASK               << APID_SHIFT)
-#define ABID               (ABID_MASK               << ABID_SHIFT)
-#define ATID               (ATID_MASK               << ATID_SHIFT)
-
-
-/* FSYNR1 */
-#define AMEMTYPE           (AMEMTYPE_MASK           << AMEMTYPE_SHIFT)
-#define ASHARED            (ASHARED_MASK            << ASHARED_SHIFT)
-#define AINNERSHARED       (AINNERSHARED_MASK       << AINNERSHARED_SHIFT)
-#define APRIV              (APRIV_MASK              << APRIV_SHIFT)
-#define APROTNS            (APROTNS_MASK            << APROTNS_SHIFT)
-#define AINST              (AINST_MASK              << AINST_SHIFT)
-#define AWRITE             (AWRITE_MASK             << AWRITE_SHIFT)
-#define ABURST             (ABURST_MASK             << ABURST_SHIFT)
-#define ALEN               (ALEN_MASK               << ALEN_SHIFT)
-#define FSYNR1_ASIZE       (FSYNR1_ASIZE_MASK       << FSYNR1_ASIZE_SHIFT)
-#define ALOCK              (ALOCK_MASK              << ALOCK_SHIFT)
-#define AFULL              (AFULL_MASK              << AFULL_SHIFT)
-
-
-/* NMRR */
-#define ICPC0              (ICPC0_MASK              << ICPC0_SHIFT)
-#define ICPC1              (ICPC1_MASK              << ICPC1_SHIFT)
-#define ICPC2              (ICPC2_MASK              << ICPC2_SHIFT)
-#define ICPC3              (ICPC3_MASK              << ICPC3_SHIFT)
-#define ICPC4              (ICPC4_MASK              << ICPC4_SHIFT)
-#define ICPC5              (ICPC5_MASK              << ICPC5_SHIFT)
-#define ICPC6              (ICPC6_MASK              << ICPC6_SHIFT)
-#define ICPC7              (ICPC7_MASK              << ICPC7_SHIFT)
-#define OCPC0              (OCPC0_MASK              << OCPC0_SHIFT)
-#define OCPC1              (OCPC1_MASK              << OCPC1_SHIFT)
-#define OCPC2              (OCPC2_MASK              << OCPC2_SHIFT)
-#define OCPC3              (OCPC3_MASK              << OCPC3_SHIFT)
-#define OCPC4              (OCPC4_MASK              << OCPC4_SHIFT)
-#define OCPC5              (OCPC5_MASK              << OCPC5_SHIFT)
-#define OCPC6              (OCPC6_MASK              << OCPC6_SHIFT)
-#define OCPC7              (OCPC7_MASK              << OCPC7_SHIFT)
-
-
-/* PAR */
-#define FAULT              (FAULT_MASK              << FAULT_SHIFT)
-/* If a fault is present, these are the
-same as the fault fields in the FAR */
-#define FAULT_TF           (FAULT_TF_MASK           << FAULT_TF_SHIFT)
-#define FAULT_AFF          (FAULT_AFF_MASK          << FAULT_AFF_SHIFT)
-#define FAULT_APF          (FAULT_APF_MASK          << FAULT_APF_SHIFT)
-#define FAULT_TLBMF        (FAULT_TLBMF_MASK        << FAULT_TLBMF_SHIFT)
-#define FAULT_HTWDEEF      (FAULT_HTWDEEF_MASK      << FAULT_HTWDEEF_SHIFT)
-#define FAULT_HTWSEEF      (FAULT_HTWSEEF_MASK      << FAULT_HTWSEEF_SHIFT)
-#define FAULT_MHF          (FAULT_MHF_MASK          << FAULT_MHF_SHIFT)
-#define FAULT_SL           (FAULT_SL_MASK           << FAULT_SL_SHIFT)
-#define FAULT_SS           (FAULT_SS_MASK           << FAULT_SS_SHIFT)
-
-/* If NO fault is present, the following fields are in effect */
-/* (FAULT remains as before) */
-#define PAR_NOFAULT_SS     (PAR_NOFAULT_SS_MASK     << PAR_NOFAULT_SS_SHIFT)
-#define PAR_NOFAULT_MT     (PAR_NOFAULT_MT_MASK     << PAR_NOFAULT_MT_SHIFT)
-#define PAR_NOFAULT_SH     (PAR_NOFAULT_SH_MASK     << PAR_NOFAULT_SH_SHIFT)
-#define PAR_NOFAULT_NS     (PAR_NOFAULT_NS_MASK     << PAR_NOFAULT_NS_SHIFT)
-#define PAR_NOFAULT_NOS    (PAR_NOFAULT_NOS_MASK    << PAR_NOFAULT_NOS_SHIFT)
-#define PAR_NPFAULT_PA     (PAR_NPFAULT_PA_MASK     << PAR_NPFAULT_PA_SHIFT)
-
-
-/* PRRR */
-#define MTC0               (MTC0_MASK               << MTC0_SHIFT)
-#define MTC1               (MTC1_MASK               << MTC1_SHIFT)
-#define MTC2               (MTC2_MASK               << MTC2_SHIFT)
-#define MTC3               (MTC3_MASK               << MTC3_SHIFT)
-#define MTC4               (MTC4_MASK               << MTC4_SHIFT)
-#define MTC5               (MTC5_MASK               << MTC5_SHIFT)
-#define MTC6               (MTC6_MASK               << MTC6_SHIFT)
-#define MTC7               (MTC7_MASK               << MTC7_SHIFT)
-#define SHDSH0             (SHDSH0_MASK             << SHDSH0_SHIFT)
-#define SHDSH1             (SHDSH1_MASK             << SHDSH1_SHIFT)
-#define SHNMSH0            (SHNMSH0_MASK            << SHNMSH0_SHIFT)
-#define SHNMSH1            (SHNMSH1_MASK            << SHNMSH1_SHIFT)
-#define NOS0               (NOS0_MASK               << NOS0_SHIFT)
-#define NOS1               (NOS1_MASK               << NOS1_SHIFT)
-#define NOS2               (NOS2_MASK               << NOS2_SHIFT)
-#define NOS3               (NOS3_MASK               << NOS3_SHIFT)
-#define NOS4               (NOS4_MASK               << NOS4_SHIFT)
-#define NOS5               (NOS5_MASK               << NOS5_SHIFT)
-#define NOS6               (NOS6_MASK               << NOS6_SHIFT)
-#define NOS7               (NOS7_MASK               << NOS7_SHIFT)
-
-
-/* RESUME */
-#define TNR                (TNR_MASK                << TNR_SHIFT)
-
-
-/* SCTLR */
-#define M                  (M_MASK                  << M_SHIFT)
-#define TRE                (TRE_MASK                << TRE_SHIFT)
-#define AFE                (AFE_MASK                << AFE_SHIFT)
-#define HAF                (HAF_MASK                << HAF_SHIFT)
-#define BE                 (BE_MASK                 << BE_SHIFT)
-#define AFFD               (AFFD_MASK               << AFFD_SHIFT)
-
-
-/* TLBIASID */
-#define TLBIASID_ASID      (TLBIASID_ASID_MASK      << TLBIASID_ASID_SHIFT)
-
-
-/* TLBIVA */
-#define TLBIVA_ASID        (TLBIVA_ASID_MASK        << TLBIVA_ASID_SHIFT)
-#define TLBIVA_VA          (TLBIVA_VA_MASK          << TLBIVA_VA_SHIFT)
-
-
-/* TLBIVAA */
-#define TLBIVAA_VA         (TLBIVAA_VA_MASK         << TLBIVAA_VA_SHIFT)
-
-
-/* TLBLCKR */
-#define LKE                (LKE_MASK                << LKE_SHIFT)
-#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT)
-#define TLBIASIDCFG        (TLBIASIDCFG_MASK        << TLBIASIDCFG_SHIFT)
-#define TLBIVAACFG         (TLBIVAACFG_MASK         << TLBIVAACFG_SHIFT)
-#define FLOOR              (FLOOR_MASK              << FLOOR_SHIFT)
-#define VICTIM             (VICTIM_MASK             << VICTIM_SHIFT)
-
-
-/* TTBCR */
-#define N                  (N_MASK                  << N_SHIFT)
-#define PD0                (PD0_MASK                << PD0_SHIFT)
-#define PD1                (PD1_MASK                << PD1_SHIFT)
-
-
-/* TTBR0 */
-#define TTBR0_IRGNH        (TTBR0_IRGNH_MASK        << TTBR0_IRGNH_SHIFT)
-#define TTBR0_SH           (TTBR0_SH_MASK           << TTBR0_SH_SHIFT)
-#define TTBR0_ORGN         (TTBR0_ORGN_MASK         << TTBR0_ORGN_SHIFT)
-#define TTBR0_NOS          (TTBR0_NOS_MASK          << TTBR0_NOS_SHIFT)
-#define TTBR0_IRGNL        (TTBR0_IRGNL_MASK        << TTBR0_IRGNL_SHIFT)
-#define TTBR0_PA           (TTBR0_PA_MASK           << TTBR0_PA_SHIFT)
-
-
-/* TTBR1 */
-#define TTBR1_IRGNH        (TTBR1_IRGNH_MASK        << TTBR1_IRGNH_SHIFT)
-#define TTBR1_SH           (TTBR1_SH_MASK           << TTBR1_SH_SHIFT)
-#define TTBR1_ORGN         (TTBR1_ORGN_MASK         << TTBR1_ORGN_SHIFT)
-#define TTBR1_NOS          (TTBR1_NOS_MASK          << TTBR1_NOS_SHIFT)
-#define TTBR1_IRGNL        (TTBR1_IRGNL_MASK        << TTBR1_IRGNL_SHIFT)
-#define TTBR1_PA           (TTBR1_PA_MASK           << TTBR1_PA_SHIFT)
-
-
-/* V2PSR */
-#define HIT                (HIT_MASK                << HIT_SHIFT)
-#define INDEX              (INDEX_MASK              << INDEX_SHIFT)
-
-
-/* V2Pxx */
-#define V2Pxx_INDEX        (V2Pxx_INDEX_MASK        << V2Pxx_INDEX_SHIFT)
-#define V2Pxx_VA           (V2Pxx_VA_MASK           << V2Pxx_VA_SHIFT)
-
-
-/* Global Register Masks */
-/* CBACRn */
-#define RWVMID_MASK               0x1F
-#define RWE_MASK                  0x01
-#define RWGE_MASK                 0x01
-#define CBVMID_MASK               0x1F
-#define IRPTNDX_MASK              0xFF
-
-
-/* CR */
-#define RPUE_MASK                 0x01
-#define RPUERE_MASK               0x01
-#define RPUEIE_MASK               0x01
-#define DCDEE_MASK                0x01
-#define CLIENTPD_MASK             0x01
-#define STALLD_MASK               0x01
-#define TLBLKCRWE_MASK            0x01
-#define CR_TLBIALLCFG_MASK        0x01
-#define TLBIVMIDCFG_MASK          0x01
-#define CR_HUME_MASK              0x01
-
-
-/* ESR */
-#define CFG_MASK                  0x01
-#define BYPASS_MASK               0x01
-#define ESR_MULTI_MASK            0x01
-
-
-/* ESYNR0 */
-#define ESYNR0_AMID_MASK          0xFF
-#define ESYNR0_APID_MASK          0x1F
-#define ESYNR0_ABID_MASK          0x07
-#define ESYNR0_AVMID_MASK         0x1F
-#define ESYNR0_ATID_MASK          0xFF
-
-
-/* ESYNR1 */
-#define ESYNR1_AMEMTYPE_MASK             0x07
-#define ESYNR1_ASHARED_MASK              0x01
-#define ESYNR1_AINNERSHARED_MASK         0x01
-#define ESYNR1_APRIV_MASK                0x01
-#define ESYNR1_APROTNS_MASK              0x01
-#define ESYNR1_AINST_MASK                0x01
-#define ESYNR1_AWRITE_MASK               0x01
-#define ESYNR1_ABURST_MASK               0x01
-#define ESYNR1_ALEN_MASK                 0x0F
-#define ESYNR1_ASIZE_MASK                0x01
-#define ESYNR1_ALOCK_MASK                0x03
-#define ESYNR1_AOOO_MASK                 0x01
-#define ESYNR1_AFULL_MASK                0x01
-#define ESYNR1_AC_MASK                   0x01
-#define ESYNR1_DCD_MASK                  0x01
-
-
-/* IDR */
-#define NM2VCBMT_MASK             0x1FF
-#define HTW_MASK                  0x01
-#define HUM_MASK                  0x01
-#define TLBSIZE_MASK              0x0F
-#define NCB_MASK                  0xFF
-#define NIRPT_MASK                0xFF
-
-
-/* M2VCBRn */
-#define VMID_MASK                 0x1F
-#define CBNDX_MASK                0xFF
-#define BYPASSD_MASK              0x01
-#define BPRCOSH_MASK              0x01
-#define BPRCISH_MASK              0x01
-#define BPRCNSH_MASK              0x01
-#define BPSHCFG_MASK              0x03
-#define NSCFG_MASK                0x03
-#define BPMTCFG_MASK              0x01
-#define BPMEMTYPE_MASK            0x07
-
-
-/* REV */
-#define MINOR_MASK                0x0F
-#define MAJOR_MASK                0x0F
-
-
-/* TESTBUSCR */
-#define TBE_MASK                  0x01
-#define SPDMBE_MASK               0x01
-#define WGSEL_MASK                0x03
-#define TBLSEL_MASK               0x03
-#define TBHSEL_MASK               0x03
-#define SPDM0SEL_MASK             0x0F
-#define SPDM1SEL_MASK             0x0F
-#define SPDM2SEL_MASK             0x0F
-#define SPDM3SEL_MASK             0x0F
-
-
-/* TLBIMID */
-#define TLBIVMID_VMID_MASK        0x1F
-
-
-/* TLBRSW */
-#define TLBRSW_INDEX_MASK         0xFF
-#define TLBBFBS_MASK              0x03
-
-
-/* TLBTR0 */
-#define PR_MASK                   0x01
-#define PW_MASK                   0x01
-#define UR_MASK                   0x01
-#define UW_MASK                   0x01
-#define XN_MASK                   0x01
-#define NSDESC_MASK               0x01
-#define ISH_MASK                  0x01
-#define SH_MASK                   0x01
-#define MT_MASK                   0x07
-#define DPSIZR_MASK               0x07
-#define DPSIZC_MASK               0x07
-
-
-/* TLBTR1 */
-#define TLBTR1_VMID_MASK          0x1F
-#define TLBTR1_PA_MASK            0x000FFFFF
-
-
-/* TLBTR2 */
-#define TLBTR2_ASID_MASK          0xFF
-#define TLBTR2_V_MASK             0x01
-#define TLBTR2_NSTID_MASK         0x01
-#define TLBTR2_NV_MASK            0x01
-#define TLBTR2_VA_MASK            0x000FFFFF
-
-
-/* Global Register Shifts */
-/* CBACRn */
-#define RWVMID_SHIFT             0
-#define RWE_SHIFT                8
-#define RWGE_SHIFT               9
-#define CBVMID_SHIFT             16
-#define IRPTNDX_SHIFT            24
-
-
-/* CR */
-#define RPUE_SHIFT               0
-#define RPUERE_SHIFT             1
-#define RPUEIE_SHIFT             2
-#define DCDEE_SHIFT              3
-#define CLIENTPD_SHIFT           4
-#define STALLD_SHIFT             5
-#define TLBLKCRWE_SHIFT          6
-#define CR_TLBIALLCFG_SHIFT      7
-#define TLBIVMIDCFG_SHIFT        8
-#define CR_HUME_SHIFT            9
-
-
-/* ESR */
-#define CFG_SHIFT                0
-#define BYPASS_SHIFT             1
-#define ESR_MULTI_SHIFT          31
-
-
-/* ESYNR0 */
-#define ESYNR0_AMID_SHIFT        0
-#define ESYNR0_APID_SHIFT        8
-#define ESYNR0_ABID_SHIFT        13
-#define ESYNR0_AVMID_SHIFT       16
-#define ESYNR0_ATID_SHIFT        24
-
-
-/* ESYNR1 */
-#define ESYNR1_AMEMTYPE_SHIFT           0
-#define ESYNR1_ASHARED_SHIFT            3
-#define ESYNR1_AINNERSHARED_SHIFT       4
-#define ESYNR1_APRIV_SHIFT              5
-#define ESYNR1_APROTNS_SHIFT            6
-#define ESYNR1_AINST_SHIFT              7
-#define ESYNR1_AWRITE_SHIFT             8
-#define ESYNR1_ABURST_SHIFT             10
-#define ESYNR1_ALEN_SHIFT               12
-#define ESYNR1_ASIZE_SHIFT              16
-#define ESYNR1_ALOCK_SHIFT              20
-#define ESYNR1_AOOO_SHIFT               22
-#define ESYNR1_AFULL_SHIFT              24
-#define ESYNR1_AC_SHIFT                 30
-#define ESYNR1_DCD_SHIFT                31
-
-
-/* IDR */
-#define NM2VCBMT_SHIFT           0
-#define HTW_SHIFT                9
-#define HUM_SHIFT                10
-#define TLBSIZE_SHIFT            12
-#define NCB_SHIFT                16
-#define NIRPT_SHIFT              24
-
-
-/* M2VCBRn */
-#define VMID_SHIFT               0
-#define CBNDX_SHIFT              8
-#define BYPASSD_SHIFT            16
-#define BPRCOSH_SHIFT            17
-#define BPRCISH_SHIFT            18
-#define BPRCNSH_SHIFT            19
-#define BPSHCFG_SHIFT            20
-#define NSCFG_SHIFT              22
-#define BPMTCFG_SHIFT            24
-#define BPMEMTYPE_SHIFT          25
-
-
-/* REV */
-#define MINOR_SHIFT              0
-#define MAJOR_SHIFT              4
-
-
-/* TESTBUSCR */
-#define TBE_SHIFT                0
-#define SPDMBE_SHIFT             1
-#define WGSEL_SHIFT              8
-#define TBLSEL_SHIFT             12
-#define TBHSEL_SHIFT             14
-#define SPDM0SEL_SHIFT           16
-#define SPDM1SEL_SHIFT           20
-#define SPDM2SEL_SHIFT           24
-#define SPDM3SEL_SHIFT           28
-
-
-/* TLBIMID */
-#define TLBIVMID_VMID_SHIFT      0
-
-
-/* TLBRSW */
-#define TLBRSW_INDEX_SHIFT       0
-#define TLBBFBS_SHIFT            8
-
-
-/* TLBTR0 */
-#define PR_SHIFT                 0
-#define PW_SHIFT                 1
-#define UR_SHIFT                 2
-#define UW_SHIFT                 3
-#define XN_SHIFT                 4
-#define NSDESC_SHIFT             6
-#define ISH_SHIFT                7
-#define SH_SHIFT                 8
-#define MT_SHIFT                 9
-#define DPSIZR_SHIFT             16
-#define DPSIZC_SHIFT             20
-
-
-/* TLBTR1 */
-#define TLBTR1_VMID_SHIFT        0
-#define TLBTR1_PA_SHIFT          12
-
-
-/* TLBTR2 */
-#define TLBTR2_ASID_SHIFT        0
-#define TLBTR2_V_SHIFT           8
-#define TLBTR2_NSTID_SHIFT       9
-#define TLBTR2_NV_SHIFT          10
-#define TLBTR2_VA_SHIFT          12
-
-
-/* Context Register Masks */
-/* ACTLR */
-#define CFERE_MASK                       0x01
-#define CFEIE_MASK                       0x01
-#define PTSHCFG_MASK                     0x03
-#define RCOSH_MASK                       0x01
-#define RCISH_MASK                       0x01
-#define RCNSH_MASK                       0x01
-#define PRIVCFG_MASK                     0x03
-#define DNA_MASK                         0x01
-#define DNLV2PA_MASK                     0x01
-#define TLBMCFG_MASK                     0x03
-#define CFCFG_MASK                       0x01
-#define TIPCF_MASK                       0x01
-#define V2PCFG_MASK                      0x03
-#define HUME_MASK                        0x01
-#define PTMTCFG_MASK                     0x01
-#define PTMEMTYPE_MASK                   0x07
-
-
-/* BFBCR */
-#define BFBDFE_MASK                      0x01
-#define BFBSFE_MASK                      0x01
-#define SFVS_MASK                        0x01
-#define FLVIC_MASK                       0x0F
-#define SLVIC_MASK                       0x0F
-
-
-/* CONTEXTIDR */
-#define CONTEXTIDR_ASID_MASK             0xFF
-#define PROCID_MASK                      0x00FFFFFF
-
-
-/* FSR */
-#define TF_MASK                          0x01
-#define AFF_MASK                         0x01
-#define APF_MASK                         0x01
-#define TLBMF_MASK                       0x01
-#define HTWDEEF_MASK                     0x01
-#define HTWSEEF_MASK                     0x01
-#define MHF_MASK                         0x01
-#define SL_MASK                          0x01
-#define SS_MASK                          0x01
-#define MULTI_MASK                       0x01
-
-
-/* FSYNR0 */
-#define AMID_MASK                        0xFF
-#define APID_MASK                        0x1F
-#define ABID_MASK                        0x07
-#define ATID_MASK                        0xFF
-
-
-/* FSYNR1 */
-#define AMEMTYPE_MASK                    0x07
-#define ASHARED_MASK                     0x01
-#define AINNERSHARED_MASK                0x01
-#define APRIV_MASK                       0x01
-#define APROTNS_MASK                     0x01
-#define AINST_MASK                       0x01
-#define AWRITE_MASK                      0x01
-#define ABURST_MASK                      0x01
-#define ALEN_MASK                        0x0F
-#define FSYNR1_ASIZE_MASK                0x07
-#define ALOCK_MASK                       0x03
-#define AFULL_MASK                       0x01
-
-
-/* NMRR */
-#define ICPC0_MASK                       0x03
-#define ICPC1_MASK                       0x03
-#define ICPC2_MASK                       0x03
-#define ICPC3_MASK                       0x03
-#define ICPC4_MASK                       0x03
-#define ICPC5_MASK                       0x03
-#define ICPC6_MASK                       0x03
-#define ICPC7_MASK                       0x03
-#define OCPC0_MASK                       0x03
-#define OCPC1_MASK                       0x03
-#define OCPC2_MASK                       0x03
-#define OCPC3_MASK                       0x03
-#define OCPC4_MASK                       0x03
-#define OCPC5_MASK                       0x03
-#define OCPC6_MASK                       0x03
-#define OCPC7_MASK                       0x03
-
-
-/* PAR */
-#define FAULT_MASK                       0x01
-/* If a fault is present, these are the
-same as the fault fields in the FAR */
-#define FAULT_TF_MASK                    0x01
-#define FAULT_AFF_MASK                   0x01
-#define FAULT_APF_MASK                   0x01
-#define FAULT_TLBMF_MASK                 0x01
-#define FAULT_HTWDEEF_MASK               0x01
-#define FAULT_HTWSEEF_MASK               0x01
-#define FAULT_MHF_MASK                   0x01
-#define FAULT_SL_MASK                    0x01
-#define FAULT_SS_MASK                    0x01
-
-/* If NO fault is present, the following
- * fields are in effect
- * (FAULT remains as before) */
-#define PAR_NOFAULT_SS_MASK              0x01
-#define PAR_NOFAULT_MT_MASK              0x07
-#define PAR_NOFAULT_SH_MASK              0x01
-#define PAR_NOFAULT_NS_MASK              0x01
-#define PAR_NOFAULT_NOS_MASK             0x01
-#define PAR_NPFAULT_PA_MASK              0x000FFFFF
-
-
-/* PRRR */
-#define MTC0_MASK                        0x03
-#define MTC1_MASK                        0x03
-#define MTC2_MASK                        0x03
-#define MTC3_MASK                        0x03
-#define MTC4_MASK                        0x03
-#define MTC5_MASK                        0x03
-#define MTC6_MASK                        0x03
-#define MTC7_MASK                        0x03
-#define SHDSH0_MASK                      0x01
-#define SHDSH1_MASK                      0x01
-#define SHNMSH0_MASK                     0x01
-#define SHNMSH1_MASK                     0x01
-#define NOS0_MASK                        0x01
-#define NOS1_MASK                        0x01
-#define NOS2_MASK                        0x01
-#define NOS3_MASK                        0x01
-#define NOS4_MASK                        0x01
-#define NOS5_MASK                        0x01
-#define NOS6_MASK                        0x01
-#define NOS7_MASK                        0x01
-
-
-/* RESUME */
-#define TNR_MASK                         0x01
-
-
-/* SCTLR */
-#define M_MASK                           0x01
-#define TRE_MASK                         0x01
-#define AFE_MASK                         0x01
-#define HAF_MASK                         0x01
-#define BE_MASK                          0x01
-#define AFFD_MASK                        0x01
-
-
-/* TLBIASID */
-#define TLBIASID_ASID_MASK               0xFF
-
-
-/* TLBIVA */
-#define TLBIVA_ASID_MASK                 0xFF
-#define TLBIVA_VA_MASK                   0x000FFFFF
-
-
-/* TLBIVAA */
-#define TLBIVAA_VA_MASK                  0x000FFFFF
-
-
-/* TLBLCKR */
-#define LKE_MASK                         0x01
-#define TLBLCKR_TLBIALLCFG_MASK          0x01
-#define TLBIASIDCFG_MASK                 0x01
-#define TLBIVAACFG_MASK                  0x01
-#define FLOOR_MASK                       0xFF
-#define VICTIM_MASK                      0xFF
-
-
-/* TTBCR */
-#define N_MASK                           0x07
-#define PD0_MASK                         0x01
-#define PD1_MASK                         0x01
-
-
-/* TTBR0 */
-#define TTBR0_IRGNH_MASK                 0x01
-#define TTBR0_SH_MASK                    0x01
-#define TTBR0_ORGN_MASK                  0x03
-#define TTBR0_NOS_MASK                   0x01
-#define TTBR0_IRGNL_MASK                 0x01
-#define TTBR0_PA_MASK                    0x0003FFFF
-
-
-/* TTBR1 */
-#define TTBR1_IRGNH_MASK                 0x01
-#define TTBR1_SH_MASK                    0x01
-#define TTBR1_ORGN_MASK                  0x03
-#define TTBR1_NOS_MASK                   0x01
-#define TTBR1_IRGNL_MASK                 0x01
-#define TTBR1_PA_MASK                    0x0003FFFF
-
-
-/* V2PSR */
-#define HIT_MASK                         0x01
-#define INDEX_MASK                       0xFF
-
-
-/* V2Pxx */
-#define V2Pxx_INDEX_MASK                 0xFF
-#define V2Pxx_VA_MASK                    0x000FFFFF
-
-
-/* Context Register Shifts */
-/* ACTLR */
-#define CFERE_SHIFT                    0
-#define CFEIE_SHIFT                    1
-#define PTSHCFG_SHIFT                  2
-#define RCOSH_SHIFT                    4
-#define RCISH_SHIFT                    5
-#define RCNSH_SHIFT                    6
-#define PRIVCFG_SHIFT                  8
-#define DNA_SHIFT                      10
-#define DNLV2PA_SHIFT                  11
-#define TLBMCFG_SHIFT                  12
-#define CFCFG_SHIFT                    14
-#define TIPCF_SHIFT                    15
-#define V2PCFG_SHIFT                   16
-#define HUME_SHIFT                     18
-#define PTMTCFG_SHIFT                  20
-#define PTMEMTYPE_SHIFT                21
-
-
-/* BFBCR */
-#define BFBDFE_SHIFT                   0
-#define BFBSFE_SHIFT                   1
-#define SFVS_SHIFT                     2
-#define FLVIC_SHIFT                    4
-#define SLVIC_SHIFT                    8
-
-
-/* CONTEXTIDR */
-#define CONTEXTIDR_ASID_SHIFT          0
-#define PROCID_SHIFT                   8
-
-
-/* FSR */
-#define TF_SHIFT                       1
-#define AFF_SHIFT                      2
-#define APF_SHIFT                      3
-#define TLBMF_SHIFT                    4
-#define HTWDEEF_SHIFT                  5
-#define HTWSEEF_SHIFT                  6
-#define MHF_SHIFT                      7
-#define SL_SHIFT                       16
-#define SS_SHIFT                       30
-#define MULTI_SHIFT                    31
-
-
-/* FSYNR0 */
-#define AMID_SHIFT                     0
-#define APID_SHIFT                     8
-#define ABID_SHIFT                     13
-#define ATID_SHIFT                     24
-
-
-/* FSYNR1 */
-#define AMEMTYPE_SHIFT                 0
-#define ASHARED_SHIFT                  3
-#define AINNERSHARED_SHIFT             4
-#define APRIV_SHIFT                    5
-#define APROTNS_SHIFT                  6
-#define AINST_SHIFT                    7
-#define AWRITE_SHIFT                   8
-#define ABURST_SHIFT                   10
-#define ALEN_SHIFT                     12
-#define FSYNR1_ASIZE_SHIFT             16
-#define ALOCK_SHIFT                    20
-#define AFULL_SHIFT                    24
-
-
-/* NMRR */
-#define ICPC0_SHIFT                    0
-#define ICPC1_SHIFT                    2
-#define ICPC2_SHIFT                    4
-#define ICPC3_SHIFT                    6
-#define ICPC4_SHIFT                    8
-#define ICPC5_SHIFT                    10
-#define ICPC6_SHIFT                    12
-#define ICPC7_SHIFT                    14
-#define OCPC0_SHIFT                    16
-#define OCPC1_SHIFT                    18
-#define OCPC2_SHIFT                    20
-#define OCPC3_SHIFT                    22
-#define OCPC4_SHIFT                    24
-#define OCPC5_SHIFT                    26
-#define OCPC6_SHIFT                    28
-#define OCPC7_SHIFT                    30
-
-
-/* PAR */
-#define FAULT_SHIFT                    0
-/* If a fault is present, these are the
-same as the fault fields in the FAR */
-#define FAULT_TF_SHIFT                 1
-#define FAULT_AFF_SHIFT                2
-#define FAULT_APF_SHIFT                3
-#define FAULT_TLBMF_SHIFT              4
-#define FAULT_HTWDEEF_SHIFT            5
-#define FAULT_HTWSEEF_SHIFT            6
-#define FAULT_MHF_SHIFT                7
-#define FAULT_SL_SHIFT                 16
-#define FAULT_SS_SHIFT                 30
-
-/* If NO fault is present, the following
- * fields are in effect
- * (FAULT remains as before) */
-#define PAR_NOFAULT_SS_SHIFT           1
-#define PAR_NOFAULT_MT_SHIFT           4
-#define PAR_NOFAULT_SH_SHIFT           7
-#define PAR_NOFAULT_NS_SHIFT           9
-#define PAR_NOFAULT_NOS_SHIFT          10
-#define PAR_NPFAULT_PA_SHIFT           12
-
-
-/* PRRR */
-#define MTC0_SHIFT                     0
-#define MTC1_SHIFT                     2
-#define MTC2_SHIFT                     4
-#define MTC3_SHIFT                     6
-#define MTC4_SHIFT                     8
-#define MTC5_SHIFT                     10
-#define MTC6_SHIFT                     12
-#define MTC7_SHIFT                     14
-#define SHDSH0_SHIFT                   16
-#define SHDSH1_SHIFT                   17
-#define SHNMSH0_SHIFT                  18
-#define SHNMSH1_SHIFT                  19
-#define NOS0_SHIFT                     24
-#define NOS1_SHIFT                     25
-#define NOS2_SHIFT                     26
-#define NOS3_SHIFT                     27
-#define NOS4_SHIFT                     28
-#define NOS5_SHIFT                     29
-#define NOS6_SHIFT                     30
-#define NOS7_SHIFT                     31
-
-
-/* RESUME */
-#define TNR_SHIFT                      0
-
-
-/* SCTLR */
-#define M_SHIFT                        0
-#define TRE_SHIFT                      1
-#define AFE_SHIFT                      2
-#define HAF_SHIFT                      3
-#define BE_SHIFT                       4
-#define AFFD_SHIFT                     5
-
-
-/* TLBIASID */
-#define TLBIASID_ASID_SHIFT            0
-
-
-/* TLBIVA */
-#define TLBIVA_ASID_SHIFT              0
-#define TLBIVA_VA_SHIFT                12
-
-
-/* TLBIVAA */
-#define TLBIVAA_VA_SHIFT               12
-
-
-/* TLBLCKR */
-#define LKE_SHIFT                      0
-#define TLBLCKR_TLBIALLCFG_SHIFT       1
-#define TLBIASIDCFG_SHIFT              2
-#define TLBIVAACFG_SHIFT               3
-#define FLOOR_SHIFT                    8
-#define VICTIM_SHIFT                   8
-
-
-/* TTBCR */
-#define N_SHIFT                        3
-#define PD0_SHIFT                      4
-#define PD1_SHIFT                      5
-
-
-/* TTBR0 */
-#define TTBR0_IRGNH_SHIFT              0
-#define TTBR0_SH_SHIFT                 1
-#define TTBR0_ORGN_SHIFT               3
-#define TTBR0_NOS_SHIFT                5
-#define TTBR0_IRGNL_SHIFT              6
-#define TTBR0_PA_SHIFT                 14
-
-
-/* TTBR1 */
-#define TTBR1_IRGNH_SHIFT              0
-#define TTBR1_SH_SHIFT                 1
-#define TTBR1_ORGN_SHIFT               3
-#define TTBR1_NOS_SHIFT                5
-#define TTBR1_IRGNL_SHIFT              6
-#define TTBR1_PA_SHIFT                 14
-
-
-/* V2PSR */
-#define HIT_SHIFT                      0
-#define INDEX_SHIFT                    8
-
-
-/* V2Pxx */
-#define V2Pxx_INDEX_SHIFT              0
-#define V2Pxx_VA_SHIFT                 12
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
deleted file mode 100644
index 7bca8d7..0000000
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * The MSM peripherals are spread all over across 768MB of physical
- * space, which makes just having a simple IO_ADDRESS macro to slide
- * them into the right virtual location rough.  Instead, we will
- * provide a master phys->virt mapping for peripherals here.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IOMAP_8960_H
-#define __ASM_ARCH_MSM_IOMAP_8960_H
-
-/* Physical base address and size of peripherals.
- * Ordered by the virtual base addresses they will be mapped at.
- *
- * If you add or remove entries here, you'll want to edit the
- * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
- * changes.
- *
- */
-
-#define MSM8960_TMR_PHYS	0x0200A000
-#define MSM8960_TMR_SIZE	SZ_4K
-
-#define MSM8960_TMR0_PHYS	0x0208A000
-#define MSM8960_TMR0_SIZE	SZ_4K
-
-#ifdef CONFIG_DEBUG_MSM8960_UART
-#define MSM_DEBUG_UART_BASE	0xF0040000
-#define MSM_DEBUG_UART_PHYS	0x16440000
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
deleted file mode 100644
index 75a7b62..0000000
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * The MSM peripherals are spread all over across 768MB of physical
- * space, which makes just having a simple IO_ADDRESS macro to slide
- * them into the right virtual location rough.  Instead, we will
- * provide a master phys->virt mapping for peripherals here.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IOMAP_8X60_H
-#define __ASM_ARCH_MSM_IOMAP_8X60_H
-
-/* Physical base address and size of peripherals.
- * Ordered by the virtual base addresses they will be mapped at.
- *
- * MSM_VIC_BASE must be an value that can be loaded via a "mov"
- * instruction, otherwise entry-macro.S will not compile.
- *
- * If you add or remove entries here, you'll want to edit the
- * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
- * changes.
- *
- */
-
-#define MSM_TLMM_BASE		IOMEM(0xF0004000)
-#define MSM_TLMM_PHYS		0x00800000
-#define MSM_TLMM_SIZE		SZ_16K
-
-#define MSM8X60_TMR_PHYS	0x02000000
-#define MSM8X60_TMR_SIZE	SZ_4K
-
-#define MSM8X60_TMR0_PHYS	0x02040000
-#define MSM8X60_TMR0_SIZE	SZ_4K
-
-#ifdef CONFIG_DEBUG_MSM8660_UART
-#define MSM_DEBUG_UART_BASE	0xF0040000
-#define MSM_DEBUG_UART_PHYS	0x19C40000
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index c56e81f..0e4f491 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -45,25 +45,8 @@
 #include "msm_iomap-7x00.h"
 #endif
 
-#include "msm_iomap-8x60.h"
-#include "msm_iomap-8960.h"
-
-#define MSM_DEBUG_UART_SIZE	SZ_4K
-#if defined(CONFIG_DEBUG_MSM_UART1)
-#define MSM_DEBUG_UART_BASE	0xE1000000
-#define MSM_DEBUG_UART_PHYS	MSM_UART1_PHYS
-#elif defined(CONFIG_DEBUG_MSM_UART2)
-#define MSM_DEBUG_UART_BASE	0xE1000000
-#define MSM_DEBUG_UART_PHYS	MSM_UART2_PHYS
-#elif defined(CONFIG_DEBUG_MSM_UART3)
-#define MSM_DEBUG_UART_BASE	0xE1000000
-#define MSM_DEBUG_UART_PHYS	MSM_UART3_PHYS
-#endif
-
 /* Virtual addresses shared across all MSM targets. */
 #define MSM_CSR_BASE		IOMEM(0xE0001000)
-#define MSM_TMR_BASE		IOMEM(0xF0200000)
-#define MSM_TMR0_BASE		IOMEM(0xF0201000)
 #define MSM_GPIO1_BASE		IOMEM(0xE0003000)
 #define MSM_GPIO2_BASE		IOMEM(0xE0004000)
 
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
deleted file mode 100644
index 9432487..0000000
--- a/arch/arm/mach-msm/include/mach/uncompress.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_UNCOMPRESS_H
-#define __ASM_ARCH_MSM_UNCOMPRESS_H
-
-#include <asm/barrier.h>
-#include <asm/processor.h>
-#include <mach/msm_iomap.h>
-
-#define UART_CSR      (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08))
-#define UART_TF       (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x0c))
-
-#define UART_DM_SR    (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08)))
-#define UART_DM_CR    (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x10)))
-#define UART_DM_ISR   (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x14)))
-#define UART_DM_NCHAR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x40)))
-#define UART_DM_TF    (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x70)))
-
-static void putc(int c)
-{
-#if defined(MSM_DEBUG_UART_PHYS)
-#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
-	/*
-	 * Wait for TX_READY to be set; but skip it if we have a
-	 * TX underrun.
-	 */
-	if (!(UART_DM_SR & 0x08))
-		while (!(UART_DM_ISR & 0x80))
-			cpu_relax();
-
-	UART_DM_CR = 0x300;
-	UART_DM_NCHAR = 0x1;
-	UART_DM_TF = c;
-#else
-	while (!(UART_CSR & 0x04))
-		cpu_relax();
-	UART_TF = c;
-#endif
-#endif
-}
-
-static inline void flush(void)
-{
-}
-
-static inline void arch_decomp_setup(void)
-{
-}
-
-#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 3dc04cc..adc8971 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/export.h>
@@ -27,8 +28,6 @@
 #include <mach/msm_iomap.h>
 #include <asm/mach/map.h>
 
-#include <mach/board.h>
-
 #include "common.h"
 
 #define MSM_CHIP_DEVICE_TYPE(name, chip, mem_type) {			      \
@@ -52,26 +51,38 @@ static struct map_desc msm_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE_TYPE(GPIO1, MSM7X00, MT_DEVICE_NONSHARED),
 	MSM_CHIP_DEVICE_TYPE(GPIO2, MSM7X00, MT_DEVICE_NONSHARED),
 	MSM_DEVICE_TYPE(CLK_CTL, MT_DEVICE_NONSHARED),
-#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
-	defined(CONFIG_DEBUG_MSM_UART3)
-	MSM_DEVICE_TYPE(DEBUG_UART, MT_DEVICE_NONSHARED),
-#endif
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
 		.length =   MSM_SHARED_RAM_SIZE,
 		.type =     MT_DEVICE,
 	},
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+		defined(CONFIG_DEBUG_MSM_UART3)
+	{
+		/* Must be last: virtual and pfn filled in by debug_ll_addr() */
+		.length = SZ_4K,
+		.type = MT_DEVICE_NONSHARED,
+	}
+#endif
 };
 
 void __init msm_map_common_io(void)
 {
+	size_t size = ARRAY_SIZE(msm_io_desc);
+
 	/* Make sure the peripheral register window is closed, since
 	 * we will use PTE flags (TEX[1]=1,B=0,C=1) to determine which
 	 * pages are peripheral interface or not.
 	 */
 	asm("mcr p15, 0, %0, c15, c2, 4" : : "r" (0));
-	iotable_init(msm_io_desc, ARRAY_SIZE(msm_io_desc));
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+		defined(CONFIG_DEBUG_MSM_UART3)
+	debug_ll_addr(&msm_io_desc[size - 1].pfn,
+		      &msm_io_desc[size - 1].virtual);
+	msm_io_desc[size - 1].pfn = __phys_to_pfn(msm_io_desc[size - 1].pfn);
+#endif
+	iotable_init(msm_io_desc, size);
 }
 #endif
 
@@ -87,10 +98,6 @@ static struct map_desc qsd8x50_io_desc[] __initdata = {
 	MSM_DEVICE(SCPLL),
 	MSM_DEVICE(AD5),
 	MSM_DEVICE(MDC),
-#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
-	defined(CONFIG_DEBUG_MSM_UART3)
-	MSM_DEVICE(DEBUG_UART),
-#endif
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
@@ -101,40 +108,11 @@ static struct map_desc qsd8x50_io_desc[] __initdata = {
 
 void __init msm_map_qsd8x50_io(void)
 {
+	debug_ll_io_init();
 	iotable_init(qsd8x50_io_desc, ARRAY_SIZE(qsd8x50_io_desc));
 }
 #endif /* CONFIG_ARCH_QSD8X50 */
 
-#ifdef CONFIG_ARCH_MSM8X60
-static struct map_desc msm8x60_io_desc[] __initdata = {
-	MSM_CHIP_DEVICE(TMR, MSM8X60),
-	MSM_CHIP_DEVICE(TMR0, MSM8X60),
-#ifdef CONFIG_DEBUG_MSM8660_UART
-	MSM_DEVICE(DEBUG_UART),
-#endif
-};
-
-void __init msm_map_msm8x60_io(void)
-{
-	iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc));
-}
-#endif /* CONFIG_ARCH_MSM8X60 */
-
-#ifdef CONFIG_ARCH_MSM8960
-static struct map_desc msm8960_io_desc[] __initdata = {
-	MSM_CHIP_DEVICE(TMR, MSM8960),
-	MSM_CHIP_DEVICE(TMR0, MSM8960),
-#ifdef CONFIG_DEBUG_MSM8960_UART
-	MSM_DEVICE(DEBUG_UART),
-#endif
-};
-
-void __init msm_map_msm8960_io(void)
-{
-	iotable_init(msm8960_io_desc, ARRAY_SIZE(msm8960_io_desc));
-}
-#endif /* CONFIG_ARCH_MSM8960 */
-
 #ifdef CONFIG_ARCH_MSM7X30
 static struct map_desc msm7x30_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
@@ -150,10 +128,6 @@ static struct map_desc msm7x30_io_desc[] __initdata = {
 	MSM_DEVICE(SAW),
 	MSM_DEVICE(GCC),
 	MSM_DEVICE(TCSR),
-#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
-	defined(CONFIG_DEBUG_MSM_UART3)
-	MSM_DEVICE(DEBUG_UART),
-#endif
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
@@ -164,10 +138,12 @@ static struct map_desc msm7x30_io_desc[] __initdata = {
 
 void __init msm_map_msm7x30_io(void)
 {
+	debug_ll_io_init();
 	iotable_init(msm7x30_io_desc, ARRAY_SIZE(msm7x30_io_desc));
 }
 #endif /* CONFIG_ARCH_MSM7X30 */
 
+#ifdef CONFIG_ARCH_MSM7X00A
 void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
 				   unsigned int mtype, void *caller)
 {
@@ -182,3 +158,4 @@ void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
 
 	return __arm_ioremap_caller(phys_addr, size, mtype, caller);
 }
+#endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 8697cfc..696fb73 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -16,6 +16,7 @@
 
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/cpu.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -26,7 +27,6 @@
 #include <linux/sched_clock.h>
 
 #include <asm/mach/time.h>
-#include <asm/localtimer.h>
 
 #include "common.h"
 
@@ -49,7 +49,7 @@ static void __iomem *sts_base;
 
 static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+	struct clock_event_device *evt = dev_id;
 	/* Stop the timer tick */
 	if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
 		u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
@@ -101,18 +101,7 @@ static void msm_timer_set_mode(enum clock_event_mode mode,
 	writel_relaxed(ctrl, event_base + TIMER_ENABLE);
 }
 
-static struct clock_event_device msm_clockevent = {
-	.name		= "gp_timer",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= msm_timer_set_next_event,
-	.set_mode	= msm_timer_set_mode,
-};
-
-static union {
-	struct clock_event_device *evt;
-	struct clock_event_device * __percpu *percpu_evt;
-} msm_evt;
+static struct clock_event_device __percpu *msm_evt;
 
 static void __iomem *source_base;
 
@@ -138,23 +127,34 @@ static struct clocksource msm_clocksource = {
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#ifdef CONFIG_LOCAL_TIMERS
+static int msm_timer_irq;
+static int msm_timer_has_ppi;
+
 static int msm_local_timer_setup(struct clock_event_device *evt)
 {
-	/* Use existing clock_event for cpu 0 */
-	if (!smp_processor_id())
-		return 0;
-
-	evt->irq = msm_clockevent.irq;
-	evt->name = "local_timer";
-	evt->features = msm_clockevent.features;
-	evt->rating = msm_clockevent.rating;
+	int cpu = smp_processor_id();
+	int err;
+
+	evt->irq = msm_timer_irq;
+	evt->name = "msm_timer";
+	evt->features = CLOCK_EVT_FEAT_ONESHOT;
+	evt->rating = 200;
 	evt->set_mode = msm_timer_set_mode;
 	evt->set_next_event = msm_timer_set_next_event;
+	evt->cpumask = cpumask_of(cpu);
+
+	clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff);
+
+	if (msm_timer_has_ppi) {
+		enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
+	} else {
+		err = request_irq(evt->irq, msm_timer_interrupt,
+				IRQF_TIMER | IRQF_NOBALANCING |
+				IRQF_TRIGGER_RISING, "gp_timer", evt);
+		if (err)
+			pr_err("request_irq failed\n");
+	}
 
-	*__this_cpu_ptr(msm_evt.percpu_evt) = evt;
-	clockevents_config_and_register(evt, GPT_HZ, 4, 0xf0000000);
-	enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
 	return 0;
 }
 
@@ -164,11 +164,28 @@ static void msm_local_timer_stop(struct clock_event_device *evt)
 	disable_percpu_irq(evt->irq);
 }
 
-static struct local_timer_ops msm_local_timer_ops = {
-	.setup	= msm_local_timer_setup,
-	.stop	= msm_local_timer_stop,
+static int msm_timer_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		msm_local_timer_setup(this_cpu_ptr(msm_evt));
+		break;
+	case CPU_DYING:
+		msm_local_timer_stop(this_cpu_ptr(msm_evt));
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block msm_timer_cpu_nb = {
+	.notifier_call = msm_timer_cpu_notify,
 };
-#endif /* CONFIG_LOCAL_TIMERS */
 
 static notrace u32 msm_sched_clock_read(void)
 {
@@ -178,38 +195,35 @@ static notrace u32 msm_sched_clock_read(void)
 static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
 				  bool percpu)
 {
-	struct clock_event_device *ce = &msm_clockevent;
 	struct clocksource *cs = &msm_clocksource;
-	int res;
+	int res = 0;
+
+	msm_timer_irq = irq;
+	msm_timer_has_ppi = percpu;
+
+	msm_evt = alloc_percpu(struct clock_event_device);
+	if (!msm_evt) {
+		pr_err("memory allocation failed for clockevents\n");
+		goto err;
+	}
 
-	ce->cpumask = cpumask_of(0);
-	ce->irq = irq;
+	if (percpu)
+		res = request_percpu_irq(irq, msm_timer_interrupt,
+					 "gp_timer", msm_evt);
 
-	clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff);
-	if (percpu) {
-		msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *);
-		if (!msm_evt.percpu_evt) {
-			pr_err("memory allocation failed for %s\n", ce->name);
+	if (res) {
+		pr_err("request_percpu_irq failed\n");
+	} else {
+		res = register_cpu_notifier(&msm_timer_cpu_nb);
+		if (res) {
+			free_percpu_irq(irq, msm_evt);
 			goto err;
 		}
-		*__this_cpu_ptr(msm_evt.percpu_evt) = ce;
-		res = request_percpu_irq(ce->irq, msm_timer_interrupt,
-					 ce->name, msm_evt.percpu_evt);
-		if (!res) {
-			enable_percpu_irq(ce->irq, IRQ_TYPE_EDGE_RISING);
-#ifdef CONFIG_LOCAL_TIMERS
-			local_timer_register(&msm_local_timer_ops);
-#endif
-		}
-	} else {
-		msm_evt.evt = ce;
-		res = request_irq(ce->irq, msm_timer_interrupt,
-				  IRQF_TIMER | IRQF_NOBALANCING |
-				  IRQF_TRIGGER_RISING, ce->name, &msm_evt.evt);
+
+		/* Immediately configure the timer on the boot CPU */
+		msm_local_timer_setup(__this_cpu_ptr(msm_evt));
 	}
 
-	if (res)
-		pr_err("request_irq failed for %s\n", ce->name);
 err:
 	writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
 	res = clocksource_register_hz(cs, dgt_hz);
@@ -219,15 +233,8 @@ err:
 }
 
 #ifdef CONFIG_OF
-static const struct of_device_id msm_timer_match[] __initconst = {
-	{ .compatible = "qcom,kpss-timer" },
-	{ .compatible = "qcom,scss-timer" },
-	{ },
-};
-
-void __init msm_dt_timer_init(void)
+static void __init msm_dt_timer_init(struct device_node *np)
 {
-	struct device_node *np;
 	u32 freq;
 	int irq;
 	struct resource res;
@@ -235,12 +242,6 @@ void __init msm_dt_timer_init(void)
 	void __iomem *base;
 	void __iomem *cpu0_base;
 
-	np = of_find_matching_node(NULL, msm_timer_match);
-	if (!np) {
-		pr_err("Can't find msm timer DT node\n");
-		return;
-	}
-
 	base = of_iomap(np, 0);
 	if (!base) {
 		pr_err("Failed to map event base\n");
@@ -283,6 +284,8 @@ void __init msm_dt_timer_init(void)
 
 	msm_timer_init(freq, 32, irq, !!percpu_offset);
 }
+CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
+CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
 #endif
 
 static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
diff --git a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
deleted file mode 100644
index a7df02b..0000000
--- a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-mv78xx0/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <mach/mv78xx0.h>
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =MV78XX0_REGS_PHYS_BASE
-	ldr	\rv, =MV78XX0_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index dc26a65..445e553 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -18,6 +18,11 @@
 #include <mach/mv78xx0.h>
 #include "common.h"
 
+#define MV78XX0_MBUS_PCIE_MEM_TARGET(port, lane) ((port) ? 8 : 4)
+#define MV78XX0_MBUS_PCIE_MEM_ATTR(port, lane)   (0xf8 & ~(0x10 << (lane)))
+#define MV78XX0_MBUS_PCIE_IO_TARGET(port, lane)  ((port) ? 8 : 4)
+#define MV78XX0_MBUS_PCIE_IO_ATTR(port, lane)    (0xf0 & ~(0x10 << (lane)))
+
 struct pcie_port {
 	u8			maj;
 	u8			min;
@@ -71,7 +76,6 @@ static void __init mv78xx0_pcie_preinit(void)
 	start = MV78XX0_PCIE_MEM_PHYS_BASE;
 	for (i = 0; i < num_pcie_ports; i++) {
 		struct pcie_port *pp = pcie_port + i;
-		char winname[MVEBU_MBUS_MAX_WINNAME_SZ];
 
 		snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
 			"PCIe %d.%d MEM", pp->maj, pp->min);
@@ -85,17 +89,12 @@ static void __init mv78xx0_pcie_preinit(void)
 		if (request_resource(&iomem_resource, &pp->res))
 			panic("can't allocate PCIe MEM sub-space");
 
-		snprintf(winname, sizeof(winname), "pcie%d.%d",
-			 pp->maj, pp->min);
-
-		mvebu_mbus_add_window_remap_flags(winname,
-						  pp->res.start,
-						  resource_size(&pp->res),
-						  MVEBU_MBUS_NO_REMAP,
-						  MVEBU_MBUS_PCI_MEM);
-		mvebu_mbus_add_window_remap_flags(winname,
-						  i * SZ_64K, SZ_64K,
-						  0, MVEBU_MBUS_PCI_IO);
+		mvebu_mbus_add_window_by_id(MV78XX0_MBUS_PCIE_MEM_TARGET(pp->maj, pp->min),
+					    MV78XX0_MBUS_PCIE_MEM_ATTR(pp->maj, pp->min),
+					    pp->res.start, resource_size(&pp->res));
+		mvebu_mbus_add_window_remap_by_id(MV78XX0_MBUS_PCIE_IO_TARGET(pp->maj, pp->min),
+						  MV78XX0_MBUS_PCIE_IO_ATTR(pp->maj, pp->min),
+						  i * SZ_64K, SZ_64K, 0);
 	}
 }
 
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 97cbb80..829b573 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -34,44 +34,12 @@ static void __init armada_370_xp_map_io(void)
 	debug_ll_io_init();
 }
 
-/*
- * This initialization will be replaced by a DT-based
- * initialization once the mvebu-mbus driver gains DT support.
- */
-
-#define ARMADA_370_XP_MBUS_WINS_OFFS   0x20000
-#define ARMADA_370_XP_MBUS_WINS_SIZE   0x100
-#define ARMADA_370_XP_SDRAM_WINS_OFFS  0x20180
-#define ARMADA_370_XP_SDRAM_WINS_SIZE  0x20
-
-static void __init armada_370_xp_mbus_init(void)
-{
-	char *mbus_soc_name;
-	struct device_node *dn;
-	const __be32 mbus_wins_offs = cpu_to_be32(ARMADA_370_XP_MBUS_WINS_OFFS);
-	const __be32 sdram_wins_offs = cpu_to_be32(ARMADA_370_XP_SDRAM_WINS_OFFS);
-
-	if (of_machine_is_compatible("marvell,armada370"))
-		mbus_soc_name = "marvell,armada370-mbus";
-	else
-		mbus_soc_name = "marvell,armadaxp-mbus";
-
-	dn = of_find_node_by_name(NULL, "internal-regs");
-	BUG_ON(!dn);
-
-	mvebu_mbus_init(mbus_soc_name,
-			of_translate_address(dn, &mbus_wins_offs),
-			ARMADA_370_XP_MBUS_WINS_SIZE,
-			of_translate_address(dn, &sdram_wins_offs),
-			ARMADA_370_XP_SDRAM_WINS_SIZE);
-}
-
 static void __init armada_370_xp_timer_and_clk_init(void)
 {
 	of_clk_init(NULL);
 	armada_370_xp_timer_init();
 	coherency_init();
-	armada_370_xp_mbus_init();
+	BUG_ON(mvebu_mbus_dt_init());
 #ifdef CONFIG_CACHE_L2X0
 	l2x0_of_init(0, ~0UL);
 #endif
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
index ce81d30..c6b00fc 100644
--- a/arch/arm/mach-mvebu/platsmp.c
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 #include <linux/clk.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/mbus.h>
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
@@ -29,6 +30,9 @@
 #include "pmsu.h"
 #include "coherency.h"
 
+#define AXP_BOOTROM_BASE 0xfff00000
+#define AXP_BOOTROM_SIZE 0x100000
+
 void __init set_secondary_cpus_clock(void)
 {
 	int thiscpu;
@@ -114,10 +118,29 @@ static void __init armada_xp_smp_init_cpus(void)
 
 void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
 {
+	struct device_node *node;
+	struct resource res;
+	int err;
+
 	set_secondary_cpus_clock();
 	flush_cache_all();
 	set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
-	mvebu_mbus_add_window("bootrom", 0xfff00000, SZ_1M);
+
+	/*
+	 * In order to boot the secondary CPUs we need to ensure
+	 * the bootROM is mapped at the correct address.
+	 */
+	node = of_find_compatible_node(NULL, NULL, "marvell,bootrom");
+	if (!node)
+		panic("Cannot find 'marvell,bootrom' compatible node");
+
+	err = of_address_to_resource(node, 0, &res);
+	if (err < 0)
+		panic("Cannot get 'bootrom' node address");
+
+	if (res.start != AXP_BOOTROM_BASE ||
+	    resource_size(&res) != AXP_BOOTROM_SIZE)
+		panic("The address for the BootROM is incorrect");
 }
 
 struct smp_operations armada_xp_smp_ops __initdata = {
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 4ce27b53..2d7ad51 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -14,6 +14,7 @@
 #include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
 #include <linux/clocksource.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
@@ -61,6 +62,8 @@
 static u32 chipid;
 static u32 socid;
 
+static void __iomem *reset_addr;
+
 static inline void __mxs_setl(u32 mask, void __iomem *reg)
 {
 	__raw_writel(mask, reg + MXS_SET_ADDR);
@@ -399,6 +402,27 @@ static const char __init *mxs_get_revision(void)
 		return kasprintf(GFP_KERNEL, "%s", "Unknown");
 }
 
+#define MX23_CLKCTRL_RESET_OFFSET	0x120
+#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
+
+static int __init mxs_restart_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
+	reset_addr = of_iomap(np, 0);
+	if (!reset_addr)
+		return -ENODEV;
+
+	if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
+		reset_addr += MX23_CLKCTRL_RESET_OFFSET;
+	else
+		reset_addr += MX28_CLKCTRL_RESET_OFFSET;
+	of_node_put(np);
+
+	return 0;
+}
+
 static void __init mxs_machine_init(void)
 {
 	struct device_node *root;
@@ -433,21 +457,18 @@ static void __init mxs_machine_init(void)
 		imx28_evk_init();
 	else if (of_machine_is_compatible("bluegiga,apx4devkit"))
 		apx4devkit_init();
-	else if (of_machine_is_compatible("crystalfontz,cfa10037") ||
-		 of_machine_is_compatible("crystalfontz,cfa10049") ||
-		 of_machine_is_compatible("crystalfontz,cfa10055") ||
-		 of_machine_is_compatible("crystalfontz,cfa10057"))
+	else if (of_machine_is_compatible("crystalfontz,cfa10036"))
 		crystalfontz_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     NULL, parent);
 
+	mxs_restart_init();
+
 	if (of_machine_is_compatible("karo,tx28"))
 		tx28_post_init();
 }
 
-#define MX23_CLKCTRL_RESET_OFFSET	0x120
-#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
 #define MXS_CLKCTRL_RESET_CHIP		(1 << 1)
 
 /*
@@ -455,28 +476,16 @@ static void __init mxs_machine_init(void)
  */
 static void mxs_restart(enum reboot_mode mode, const char *cmd)
 {
-	struct device_node *np;
-	void __iomem *reset_addr;
+	if (reset_addr) {
+		/* reset the chip */
+		__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
-	reset_addr = of_iomap(np, 0);
-	if (!reset_addr)
-		goto soft;
+		pr_err("Failed to assert the chip reset\n");
 
-	if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
-		reset_addr += MX23_CLKCTRL_RESET_OFFSET;
-	else
-		reset_addr += MX28_CLKCTRL_RESET_OFFSET;
-
-	/* reset the chip */
-	__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
-
-	pr_err("Failed to assert the chip reset\n");
-
-	/* Delay to allow the serial port to show the message */
-	mdelay(50);
+		/* Delay to allow the serial port to show the message */
+		mdelay(50);
+	}
 
-soft:
 	/* We'll take a jump through zero as a poor second */
 	soft_restart(0);
 }
@@ -487,6 +496,7 @@ static void __init mxs_timer_init(void)
 		mx23_clocks_init();
 	else
 		mx28_clocks_init();
+	of_clk_init(NULL);
 	clocksource_of_init();
 }
 
diff --git a/arch/arm/mach-mxs/pm.c b/arch/arm/mach-mxs/pm.c
index b2494d2..0170e99 100644
--- a/arch/arm/mach-mxs/pm.c
+++ b/arch/arm/mach-mxs/pm.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/suspend.h>
 #include <linux/io.h>
+#include "pm.h"
 
 static int mxs_suspend_enter(suspend_state_t state)
 {
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 3eed000..76170dd 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -37,9 +37,8 @@ config ARCH_OMAP4
 	select CACHE_L2X0
 	select CPU_V7
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
-	select LOCAL_TIMERS if SMP
 	select OMAP_INTERCONNECT
 	select PL310_ERRATA_588369
 	select PL310_ERRATA_727915
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index d940e53..b456b44 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -181,7 +181,7 @@ int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
 				 sizeof(struct omap_i2c_bus_platform_data));
 	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 
-	return PTR_RET(pdev);
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 static  int __init omap_i2c_cmdline(void)
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 5cc9287..f99f68e 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -129,6 +129,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	const char *oh_name;
 	int oh_cnt, i, ret = 0;
+	bool device_active = false;
 
 	oh_cnt = of_property_count_strings(node, "ti,hwmods");
 	if (oh_cnt <= 0) {
@@ -152,6 +153,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 			goto odbfd_exit1;
 		}
 		hwmods[i] = oh;
+		if (oh->flags & HWMOD_INIT_NO_IDLE)
+			device_active = true;
 	}
 
 	od = omap_device_alloc(pdev, hwmods, oh_cnt);
@@ -172,6 +175,11 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 
 	pdev->dev.pm_domain = &omap_device_pm_domain;
 
+	if (device_active) {
+		omap_device_enable(pdev);
+		pm_runtime_set_active(&pdev->dev);
+	}
+
 odbfd_exit1:
 	kfree(hwmods);
 odbfd_exit:
@@ -842,6 +850,7 @@ static int __init omap_device_late_idle(struct device *dev, void *data)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
+	int i;
 
 	if (!od)
 		return 0;
@@ -850,6 +859,15 @@ static int __init omap_device_late_idle(struct device *dev, void *data)
 	 * If omap_device state is enabled, but has no driver bound,
 	 * idle it.
 	 */
+
+	/*
+	 * Some devices (like memory controllers) are always kept
+	 * enabled, and should not be idled even with no drivers.
+	 */
+	for (i = 0; i < od->hwmods_cnt; i++)
+		if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE)
+			return 0;
+
 	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
 		if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
 			dev_warn(dev, "%s: enabled but no driver.  Idling\n",
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 7341eff..7f4db12 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2386,7 +2386,7 @@ static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)
 
 		np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
 		if (np)
-			va_start = of_iomap(np, 0);
+			va_start = of_iomap(np, oh->mpu_rt_idx);
 	} else {
 		va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
 	}
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index aab33fd..e1482a9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -95,6 +95,54 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3;
 #define MODULEMODE_HWCTRL		1
 #define MODULEMODE_SWCTRL		2
 
+#define DEBUG_OMAP2UART1_FLAGS	0
+#define DEBUG_OMAP2UART2_FLAGS	0
+#define DEBUG_OMAP2UART3_FLAGS	0
+#define DEBUG_OMAP3UART3_FLAGS	0
+#define DEBUG_OMAP3UART4_FLAGS	0
+#define DEBUG_OMAP4UART3_FLAGS	0
+#define DEBUG_OMAP4UART4_FLAGS	0
+#define DEBUG_TI81XXUART1_FLAGS	0
+#define DEBUG_TI81XXUART2_FLAGS	0
+#define DEBUG_TI81XXUART3_FLAGS	0
+#define DEBUG_AM33XXUART1_FLAGS	0
+
+#define DEBUG_OMAPUART_FLAGS	(HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET)
+
+#if defined(CONFIG_DEBUG_OMAP2UART1)
+#undef DEBUG_OMAP2UART1_FLAGS
+#define DEBUG_OMAP2UART1_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_OMAP2UART2)
+#undef DEBUG_OMAP2UART2_FLAGS
+#define DEBUG_OMAP2UART2_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_OMAP2UART3)
+#undef DEBUG_OMAP2UART3_FLAGS
+#define DEBUG_OMAP2UART3_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_OMAP3UART3)
+#undef DEBUG_OMAP3UART3_FLAGS
+#define DEBUG_OMAP3UART3_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_OMAP3UART4)
+#undef DEBUG_OMAP3UART4_FLAGS
+#define DEBUG_OMAP3UART4_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_OMAP4UART3)
+#undef DEBUG_OMAP4UART3_FLAGS
+#define DEBUG_OMAP4UART3_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_OMAP4UART4)
+#undef DEBUG_OMAP4UART4_FLAGS
+#define DEBUG_OMAP4UART4_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_TI81XXUART1)
+#undef DEBUG_TI81XXUART1_FLAGS
+#define DEBUG_TI81XXUART1_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_TI81XXUART2)
+#undef DEBUG_TI81XXUART2_FLAGS
+#define DEBUG_TI81XXUART2_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_TI81XXUART3)
+#undef DEBUG_TI81XXUART3_FLAGS
+#define DEBUG_TI81XXUART3_FLAGS DEBUG_OMAPUART_FLAGS
+#elif defined(CONFIG_DEBUG_AM33XXUART1)
+#undef DEBUG_AM33XXUART1_FLAGS
+#define DEBUG_AM33XXUART1_FLAGS DEBUG_OMAPUART_FLAGS
+#endif
 
 /**
  * struct omap_hwmod_mux_info - hwmod specific mux configuration
@@ -568,6 +616,7 @@ struct omap_hwmod_link {
  * @voltdm: pointer to voltage domain (filled in at runtime)
  * @dev_attr: arbitrary device attributes that can be passed to the driver
  * @_sysc_cache: internal-use hwmod flags
+ * @mpu_rt_idx: index of device address space for register target (for DT boot)
  * @_mpu_rt_va: cached register target start address (internal use)
  * @_mpu_port: cached MPU register target slave (internal use)
  * @opt_clks_cnt: number of @opt_clks
@@ -617,6 +666,7 @@ struct omap_hwmod {
 	struct list_head		node;
 	struct omap_hwmod_ocp_if	*_mpu_port;
 	u16				flags;
+	u8				mpu_rt_idx;
 	u8				response_lat;
 	u8				rst_lines_cnt;
 	u8				opt_clks_cnt;
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index d05fc7b..56cebb0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -512,7 +512,7 @@ struct omap_hwmod omap2xxx_uart1_hwmod = {
 	.mpu_irqs	= omap2_uart1_mpu_irqs,
 	.sdma_reqs	= omap2_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP2UART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = CORE_MOD,
@@ -532,7 +532,7 @@ struct omap_hwmod omap2xxx_uart2_hwmod = {
 	.mpu_irqs	= omap2_uart2_mpu_irqs,
 	.sdma_reqs	= omap2_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP2UART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = CORE_MOD,
@@ -552,7 +552,7 @@ struct omap_hwmod omap2xxx_uart3_hwmod = {
 	.mpu_irqs	= omap2_uart3_mpu_irqs,
 	.sdma_reqs	= omap2_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP2UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = CORE_MOD,
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index 28bbd56..eb2f3b9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -562,6 +562,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
 	.clkdm_name	= "cpsw_125mhz_clkdm",
 	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
 	.main_clk	= "cpsw_125mhz_gclk",
+	.mpu_rt_idx	= 1,
 	.prcm		= {
 		.omap4	= {
 			.clkctrl_offs	= AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET,
@@ -1512,7 +1513,7 @@ static struct omap_hwmod am33xx_uart1_hwmod = {
 	.name		= "uart1",
 	.class		= &uart_class,
 	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
 	.prcm		= {
 		.omap4	= {
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index f7a3df2..0c3a427 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -490,7 +490,7 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	.mpu_irqs	= omap2_uart1_mpu_irqs,
 	.sdma_reqs	= omap2_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_TI81XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = CORE_MOD,
@@ -509,7 +509,7 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	.mpu_irqs	= omap2_uart2_mpu_irqs,
 	.sdma_reqs	= omap2_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_TI81XXUART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = CORE_MOD,
@@ -528,7 +528,8 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	.mpu_irqs	= omap2_uart3_mpu_irqs,
 	.sdma_reqs	= omap2_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP3UART3_FLAGS | DEBUG_TI81XXUART3_FLAGS |
+				HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = OMAP3430_PER_MOD,
@@ -558,7 +559,7 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
 	.mpu_irqs	= uart4_mpu_irqs,
 	.sdma_reqs	= uart4_sdma_reqs,
 	.main_clk	= "uart4_fck",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP3UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.prcm		= {
 		.omap2 = {
 			.module_offs = OMAP3430_PER_MOD,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index d04b5e6..9c3b504 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2858,8 +2858,7 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
 	.name		= "uart3",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET |
-				HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP4UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
@@ -2875,7 +2874,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
 	.name		= "uart4",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.flags		= DEBUG_OMAP4UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
 	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
index f37ae96..3c70f5c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
@@ -1375,7 +1375,7 @@ static struct omap_hwmod omap54xx_uart3_hwmod = {
 	.name		= "uart3",
 	.class		= &omap54xx_uart_hwmod_class,
 	.clkdm_name	= "l4per_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= DEBUG_OMAP4UART3_FLAGS,
 	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
@@ -1391,6 +1391,7 @@ static struct omap_hwmod omap54xx_uart4_hwmod = {
 	.name		= "uart4",
 	.class		= &omap54xx_uart_hwmod_class,
 	.clkdm_name	= "l4per_clkdm",
+	.flags		= DEBUG_OMAP4UART4_FLAGS,
 	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 3a674de..a388f8c 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -208,17 +208,6 @@ static int __init omap_serial_early_init(void)
 				pr_info("%s used as console in debug mode: uart%d clocks will not be gated",
 					uart_name, uart->num);
 			}
-
-			/*
-			 * omap-uart can be used for earlyprintk logs
-			 * So if omap-uart is used as console then prevent
-			 * uart reset and idle to get logs from omap-uart
-			 * until uart console driver is available to take
-			 * care for console messages.
-			 * Idling or resetting omap-uart while printing logs
-			 * early boot logs can stall the boot-up.
-			 */
-			oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
 		}
 	} while (1);
 
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index b37e1fc..5a9ee0b 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -600,7 +600,7 @@ static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon",
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-#ifdef CONFIG_LOCAL_TIMERS
+#ifdef CONFIG_HAVE_ARM_TWD
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
 void __init omap4_local_timer_init(void)
 {
@@ -619,12 +619,12 @@ void __init omap4_local_timer_init(void)
 			pr_err("twd_local_timer_register failed %d\n", err);
 	}
 }
-#else /* CONFIG_LOCAL_TIMERS */
+#else
 void __init omap4_local_timer_init(void)
 {
 	omap4_sync32k_timer_init();
 }
-#endif /* CONFIG_LOCAL_TIMERS */
+#endif /* CONFIG_HAVE_ARM_TWD */
 #endif /* CONFIG_ARCH_OMAP4 */
 
 #ifdef CONFIG_SOC_OMAP5
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index b41599f..91a5852 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -174,8 +174,10 @@ void __init orion5x_xor_init(void)
  ****************************************************************************/
 static void __init orion5x_crypto_init(void)
 {
-	mvebu_mbus_add_window("sram", ORION5X_SRAM_PHYS_BASE,
-			      ORION5X_SRAM_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_SRAM_TARGET,
+				    ORION_MBUS_SRAM_ATTR,
+				    ORION5X_SRAM_PHYS_BASE,
+				    ORION5X_SRAM_SIZE);
 	orion_crypto_init(ORION5X_CRYPTO_PHYS_BASE, ORION5X_SRAM_PHYS_BASE,
 			  SZ_8K, IRQ_ORION5X_CESA);
 }
@@ -222,22 +224,24 @@ void orion5x_setup_wins(void)
 	 * The PCIe windows will no longer be statically allocated
 	 * here once Orion5x is migrated to the pci-mvebu driver.
 	 */
-	mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_IO_PHYS_BASE,
+	mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCIE_IO_TARGET,
+					  ORION_MBUS_PCIE_IO_ATTR,
+					  ORION5X_PCIE_IO_PHYS_BASE,
 					  ORION5X_PCIE_IO_SIZE,
-					  ORION5X_PCIE_IO_BUS_BASE,
-					  MVEBU_MBUS_PCI_IO);
-	mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_MEM_PHYS_BASE,
-					  ORION5X_PCIE_MEM_SIZE,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
-	mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_IO_PHYS_BASE,
+					  ORION5X_PCIE_IO_BUS_BASE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_PCIE_MEM_TARGET,
+				    ORION_MBUS_PCIE_MEM_ATTR,
+				    ORION5X_PCIE_MEM_PHYS_BASE,
+				    ORION5X_PCIE_MEM_SIZE);
+	mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCI_IO_TARGET,
+					  ORION_MBUS_PCI_IO_ATTR,
+					  ORION5X_PCI_IO_PHYS_BASE,
 					  ORION5X_PCI_IO_SIZE,
-					  ORION5X_PCI_IO_BUS_BASE,
-					  MVEBU_MBUS_PCI_IO);
-	mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_MEM_PHYS_BASE,
-					  ORION5X_PCI_MEM_SIZE,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
+					  ORION5X_PCI_IO_BUS_BASE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_PCI_MEM_TARGET,
+				    ORION_MBUS_PCI_MEM_ATTR,
+				    ORION5X_PCI_MEM_PHYS_BASE,
+				    ORION5X_PCI_MEM_SIZE);
 }
 
 int orion5x_tclk;
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index a909afb..f565f99 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -7,6 +7,23 @@ struct dsa_platform_data;
 struct mv643xx_eth_platform_data;
 struct mv_sata_platform_data;
 
+#define ORION_MBUS_PCIE_MEM_TARGET    0x04
+#define ORION_MBUS_PCIE_MEM_ATTR      0x59
+#define ORION_MBUS_PCIE_IO_TARGET     0x04
+#define ORION_MBUS_PCIE_IO_ATTR       0x51
+#define ORION_MBUS_PCIE_WA_TARGET     0x04
+#define ORION_MBUS_PCIE_WA_ATTR       0x79
+#define ORION_MBUS_PCI_MEM_TARGET     0x03
+#define ORION_MBUS_PCI_MEM_ATTR       0x59
+#define ORION_MBUS_PCI_IO_TARGET      0x03
+#define ORION_MBUS_PCI_IO_ATTR        0x51
+#define ORION_MBUS_DEVBUS_BOOT_TARGET 0x01
+#define ORION_MBUS_DEVBUS_BOOT_ATTR   0x0f
+#define ORION_MBUS_DEVBUS_TARGET(cs)  0x01
+#define ORION_MBUS_DEVBUS_ATTR(cs)    (~(1 << cs))
+#define ORION_MBUS_SRAM_TARGET        0x00
+#define ORION_MBUS_SRAM_ATTR          0x00
+
 /*
  * Basic Orion init functions used early by machine-setup.
  */
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index 16c88bb..8f68b74 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -317,8 +317,10 @@ static void __init d2net_init(void)
 	d2net_sata_power_init();
 	orion5x_sata_init(&d2net_sata_data);
 
-	mvebu_mbus_add_window("devbus-boot", D2NET_NOR_BOOT_BASE,
-			      D2NET_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    D2NET_NOR_BOOT_BASE,
+				    D2NET_NOR_BOOT_SIZE);
 	platform_device_register(&d2net_nor_flash);
 
 	platform_device_register(&d2net_gpio_buttons);
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index 4e1263d..4b2aefd 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -340,19 +340,27 @@ static void __init db88f5281_init(void)
 	orion5x_uart0_init();
 	orion5x_uart1_init();
 
-	mvebu_mbus_add_window("devbus-boot", DB88F5281_NOR_BOOT_BASE,
-			      DB88F5281_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    DB88F5281_NOR_BOOT_BASE,
+				    DB88F5281_NOR_BOOT_SIZE);
 	platform_device_register(&db88f5281_boot_flash);
 
-	mvebu_mbus_add_window("devbus-cs0", DB88F5281_7SEG_BASE,
-			      DB88F5281_7SEG_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(0),
+				    ORION_MBUS_DEVBUS_ATTR(0),
+				    DB88F5281_7SEG_BASE,
+				    DB88F5281_7SEG_SIZE);
 
-	mvebu_mbus_add_window("devbus-cs1", DB88F5281_NOR_BASE,
-			      DB88F5281_NOR_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(1),
+				    ORION_MBUS_DEVBUS_ATTR(1),
+				    DB88F5281_NOR_BASE,
+				    DB88F5281_NOR_SIZE);
 	platform_device_register(&db88f5281_nor_flash);
 
-	mvebu_mbus_add_window("devbus-cs2", DB88F5281_NAND_BASE,
-			      DB88F5281_NAND_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(2),
+				    ORION_MBUS_DEVBUS_ATTR(2),
+				    DB88F5281_NAND_BASE,
+				    DB88F5281_NAND_SIZE);
 	platform_device_register(&db88f5281_nand_flash);
 
 	i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 9e6baf5..7097473 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -611,8 +611,10 @@ static void __init dns323_init(void)
 	/* setup flash mapping
 	 * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
 	 */
-	mvebu_mbus_add_window("devbus-boot", DNS323_NOR_BOOT_BASE,
-			      DNS323_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    DNS323_NOR_BOOT_BASE,
+				    DNS323_NOR_BOOT_SIZE);
 	platform_device_register(&dns323_nor_flash);
 
 	/* Sort out LEDs, Buttons and i2c devices */
diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c
index 1476155..f66c1b2 100644
--- a/arch/arm/mach-orion5x/edmini_v2-setup.c
+++ b/arch/arm/mach-orion5x/edmini_v2-setup.c
@@ -23,8 +23,8 @@
 #include <linux/platform_device.h>
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <linux/mbus.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mv643xx_eth.h>
 #include <linux/leds.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
@@ -96,14 +96,6 @@ static struct platform_device edmini_v2_nor_flash = {
 };
 
 /*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data edmini_v2_eth_data = {
-	.phy_addr	= 8,
-};
-
-/*****************************************************************************
  * RTC 5C372a on I2C bus
  ****************************************************************************/
 
@@ -152,10 +144,11 @@ void __init edmini_v2_init(void)
 	 * Configure peripherals.
 	 */
 	orion5x_ehci0_init();
-	orion5x_eth_init(&edmini_v2_eth_data);
 
-	mvebu_mbus_add_window("devbus-boot", EDMINI_V2_NOR_BOOT_BASE,
-			      EDMINI_V2_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    EDMINI_V2_NOR_BOOT_BASE,
+				    EDMINI_V2_NOR_BOOT_SIZE);
 	platform_device_register(&edmini_v2_nor_flash);
 
 	pr_notice("edmini_v2: USB device port, flash write and power-off "
diff --git a/arch/arm/mach-orion5x/include/mach/debug-macro.S b/arch/arm/mach-orion5x/include/mach/debug-macro.S
deleted file mode 100644
index f340ed8..0000000
--- a/arch/arm/mach-orion5x/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <mach/orion5x.h>
-
-	.macro  addruart, rp, rv, tmp
-	ldr	\rp, =ORION5X_REGS_PHYS_BASE
-	ldr	\rv, =ORION5X_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index aae10e4..fe6a48a 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -359,13 +359,17 @@ static void __init kurobox_pro_init(void)
 	orion5x_uart1_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", KUROBOX_PRO_NOR_BOOT_BASE,
-			      KUROBOX_PRO_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    KUROBOX_PRO_NOR_BOOT_BASE,
+				    KUROBOX_PRO_NOR_BOOT_SIZE);
 	platform_device_register(&kurobox_pro_nor_flash);
 
 	if (machine_is_kurobox_pro()) {
-		mvebu_mbus_add_window("devbus-cs0", KUROBOX_PRO_NAND_BASE,
-				      KUROBOX_PRO_NAND_SIZE);
+		mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(0),
+					    ORION_MBUS_DEVBUS_ATTR(0),
+					    KUROBOX_PRO_NAND_BASE,
+					    KUROBOX_PRO_NAND_SIZE);
 		platform_device_register(&kurobox_pro_nand_flash);
 	}
 
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
index 6234977..028ea03 100644
--- a/arch/arm/mach-orion5x/ls-chl-setup.c
+++ b/arch/arm/mach-orion5x/ls-chl-setup.c
@@ -294,8 +294,10 @@ static void __init lschl_init(void)
 	orion5x_uart0_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", LSCHL_NOR_BOOT_BASE,
-			      LSCHL_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    LSCHL_NOR_BOOT_BASE,
+				    LSCHL_NOR_BOOT_SIZE);
 	platform_device_register(&lschl_nor_flash);
 
 	platform_device_register(&lschl_leds);
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index fe04c4b..32b7129 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -243,8 +243,10 @@ static void __init ls_hgl_init(void)
 	orion5x_uart0_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", LS_HGL_NOR_BOOT_BASE,
-			      LS_HGL_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    LS_HGL_NOR_BOOT_BASE,
+				    LS_HGL_NOR_BOOT_SIZE);
 	platform_device_register(&ls_hgl_nor_flash);
 
 	platform_device_register(&ls_hgl_button_device);
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index ca4dbe9..a6493e7 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -244,8 +244,10 @@ static void __init lsmini_init(void)
 	orion5x_uart0_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", LSMINI_NOR_BOOT_BASE,
-			      LSMINI_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    LSMINI_NOR_BOOT_BASE,
+				    LSMINI_NOR_BOOT_SIZE);
 	platform_device_register(&lsmini_nor_flash);
 
 	platform_device_register(&lsmini_button_device);
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 827acba..e105130 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -241,8 +241,10 @@ static void __init mss2_init(void)
 	orion5x_uart0_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", MSS2_NOR_BOOT_BASE,
-			      MSS2_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    MSS2_NOR_BOOT_BASE,
+				    MSS2_NOR_BOOT_SIZE);
 	platform_device_register(&mss2_nor_flash);
 
 	platform_device_register(&mss2_button_device);
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index 92600ae..e032f01 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -204,8 +204,10 @@ static void __init mv2120_init(void)
 	orion5x_uart0_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", MV2120_NOR_BOOT_BASE,
-			      MV2120_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    MV2120_NOR_BOOT_BASE,
+				    MV2120_NOR_BOOT_SIZE);
 	platform_device_register(&mv2120_nor_flash);
 
 	platform_device_register(&mv2120_button_device);
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index dd0641a..ba73dc7 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -397,8 +397,10 @@ static void __init net2big_init(void)
 	net2big_sata_power_init();
 	orion5x_sata_init(&net2big_sata_data);
 
-	mvebu_mbus_add_window("devbus-boot", NET2BIG_NOR_BOOT_BASE,
-			      NET2BIG_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    NET2BIG_NOR_BOOT_BASE,
+				    NET2BIG_NOR_BOOT_SIZE);
 	platform_device_register(&net2big_nor_flash);
 
 	platform_device_register(&net2big_gpio_buttons);
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index 5033680..7fab670 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -157,11 +157,10 @@ static int __init pcie_setup(struct pci_sys_data *sys)
 	if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
 		printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
 				   "read transaction workaround\n");
-		mvebu_mbus_add_window_remap_flags("pcie0.0",
-						  ORION5X_PCIE_WA_PHYS_BASE,
-						  ORION5X_PCIE_WA_SIZE,
-						  MVEBU_MBUS_NO_REMAP,
-						  MVEBU_MBUS_PCI_WA);
+		mvebu_mbus_add_window_by_id(ORION_MBUS_PCIE_WA_TARGET,
+					    ORION_MBUS_PCIE_WA_ATTR,
+					    ORION5X_PCIE_WA_PHYS_BASE,
+					    ORION5X_PCIE_WA_SIZE);
 		pcie_ops.read = pcie_rd_conf_wa;
 	}
 
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 1c4498b..213b3e1 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -123,8 +123,10 @@ static void __init rd88f5181l_fxo_init(void)
 	orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data, NO_IRQ);
 	orion5x_uart0_init();
 
-	mvebu_mbus_add_window("devbus-boot", RD88F5181L_FXO_NOR_BOOT_BASE,
-			      RD88F5181L_FXO_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    RD88F5181L_FXO_NOR_BOOT_BASE,
+				    RD88F5181L_FXO_NOR_BOOT_SIZE);
 	platform_device_register(&rd88f5181l_fxo_nor_boot_flash);
 }
 
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index adabe34..594800e 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -130,8 +130,10 @@ static void __init rd88f5181l_ge_init(void)
 	orion5x_i2c_init();
 	orion5x_uart0_init();
 
-	mvebu_mbus_add_window("devbus-boot", RD88F5181L_GE_NOR_BOOT_BASE,
-			      RD88F5181L_GE_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    RD88F5181L_GE_NOR_BOOT_BASE,
+				    RD88F5181L_GE_NOR_BOOT_SIZE);
 	platform_device_register(&rd88f5181l_ge_nor_boot_flash);
 
 	i2c_register_board_info(0, &rd88f5181l_ge_i2c_rtc, 1);
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index 66e77ec..b1cf684 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -264,11 +264,14 @@ static void __init rd88f5182_init(void)
 	orion5x_uart0_init();
 	orion5x_xor_init();
 
-	mvebu_mbus_add_window("devbus-boot", RD88F5182_NOR_BOOT_BASE,
-			      RD88F5182_NOR_BOOT_SIZE);
-
-	mvebu_mbus_add_window("devbus-cs1", RD88F5182_NOR_BASE,
-			      RD88F5182_NOR_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    RD88F5182_NOR_BOOT_BASE,
+				    RD88F5182_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(1),
+				    ORION_MBUS_DEVBUS_ATTR(1),
+				    RD88F5182_NOR_BASE,
+				    RD88F5182_NOR_SIZE);
 	platform_device_register(&rd88f5182_nor_flash);
 	platform_device_register(&rd88f5182_gpio_leds);
 
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index a0bfa53..7e90648 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -329,8 +329,10 @@ static void __init tsp2_init(void)
 	/*
 	 * Configure peripherals.
 	 */
-	mvebu_mbus_add_window("devbus-boot", TSP2_NOR_BOOT_BASE,
-			      TSP2_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    TSP2_NOR_BOOT_BASE,
+				    TSP2_NOR_BOOT_SIZE);
 	platform_device_register(&tsp2_nor_flash);
 
 	orion5x_ehci0_init();
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 80174f0..e90c061 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -286,8 +286,10 @@ static void __init qnap_ts209_init(void)
 	/*
 	 * Configure peripherals.
 	 */
-	mvebu_mbus_add_window("devbus-boot", QNAP_TS209_NOR_BOOT_BASE,
-			      QNAP_TS209_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    QNAP_TS209_NOR_BOOT_BASE,
+				    QNAP_TS209_NOR_BOOT_SIZE);
 	platform_device_register(&qnap_ts209_nor_flash);
 
 	orion5x_ehci0_init();
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index 9259279..5c079d3 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -277,8 +277,10 @@ static void __init qnap_ts409_init(void)
 	/*
 	 * Configure peripherals.
 	 */
-	mvebu_mbus_add_window("devbus-boot", QNAP_TS409_NOR_BOOT_BASE,
-			      QNAP_TS409_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    QNAP_TS409_NOR_BOOT_BASE,
+				    QNAP_TS409_NOR_BOOT_SIZE);
 	platform_device_register(&qnap_ts409_nor_flash);
 
 	orion5x_ehci0_init();
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 6b84863..80a56ee 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -127,8 +127,10 @@ static void __init wnr854t_init(void)
 	orion5x_eth_switch_init(&wnr854t_switch_plat_data, NO_IRQ);
 	orion5x_uart0_init();
 
-	mvebu_mbus_add_window("devbus-boot", WNR854T_NOR_BOOT_BASE,
-			      WNR854T_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    WNR854T_NOR_BOOT_BASE,
+				    WNR854T_NOR_BOOT_SIZE);
 	platform_device_register(&wnr854t_nor_flash);
 }
 
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index fae684b..670e30d 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -213,8 +213,10 @@ static void __init wrt350n_v2_init(void)
 	orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data, NO_IRQ);
 	orion5x_uart0_init();
 
-	mvebu_mbus_add_window("devbus-boot", WRT350N_V2_NOR_BOOT_BASE,
-			      WRT350N_V2_NOR_BOOT_SIZE);
+	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
+				    ORION_MBUS_DEVBUS_BOOT_ATTR,
+				    WRT350N_V2_NOR_BOOT_BASE,
+				    WRT350N_V2_NOR_BOOT_SIZE);
 	platform_device_register(&wrt350n_v2_nor_flash);
 	platform_device_register(&wrt350n_v2_leds);
 	platform_device_register(&wrt350n_v2_button_device);
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index d210c0f..9db2029 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -13,7 +13,7 @@ config REALVIEW_EB_A9MP
 	depends on MACH_REALVIEW_EB
 	select CPU_V7
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	help
@@ -26,7 +26,7 @@ config REALVIEW_EB_ARM11MP
 	select ARCH_HAS_BARRIERS if SMP
 	select CPU_V6K
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	help
@@ -48,7 +48,7 @@ config MACH_REALVIEW_PB11MP
 	select ARM_GIC
 	select CPU_V6K
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_PATA_PLATFORM
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
@@ -92,7 +92,7 @@ config MACH_REALVIEW_PBX
 	select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
 	select ARM_GIC
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_PATA_PLATFORM
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S
deleted file mode 100644
index 8cc372d..0000000
--- a/arch/arm/mach-realview/include/mach/debug-macro.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/* arch/arm/mach-realview/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifdef CONFIG_DEBUG_REALVIEW_STD_PORT
-#define DEBUG_LL_UART_OFFSET	0x00009000
-#elif defined(CONFIG_DEBUG_REALVIEW_PB1176_PORT)
-#define DEBUG_LL_UART_OFFSET	0x0010c000
-#endif
-
-#ifndef DEBUG_LL_UART_OFFSET
-#error "Unknown RealView platform"
-#endif
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET
-		orr	\rv, \rp, #0xfb000000	@ virtual base
-		orr	\rp, \rp, #0x10000000	@ physical base
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-rpc/include/mach/debug-macro.S b/arch/arm/mach-rpc/include/mach/debug-macro.S
deleted file mode 100644
index 6d28cc9..0000000
--- a/arch/arm/mach-rpc/include/mach/debug-macro.S
+++ /dev/null
@@ -1,23 +0,0 @@
-/* arch/arm/mach-rpc/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x00010000
-		orr	\rp, \rp, #0x00000fe0
-		orr	\rv, \rp, #0xe0000000	@ virtual
-		orr	\rp, \rp, #0x03000000	@ physical
-		.endm
-
-#define UART_SHIFT	2
-#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 3912ce9..1f94c31 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -1,3 +1,41 @@
+config ARCH_SHMOBILE_MULTI
+	bool "SH-Mobile Series" if ARCH_MULTI_V7
+	depends on MMU
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_SMP
+	select ARM_GIC
+	select MIGHT_HAVE_CACHE_L2X0
+	select NO_IOPORT
+	select PINCTRL
+	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
+
+if ARCH_SHMOBILE_MULTI
+
+comment "SH-Mobile System Type"
+
+config ARCH_EMEV2
+	bool "Emma Mobile EV2"
+
+comment "SH-Mobile Board Type"
+
+config MACH_KZM9D_REFERENCE
+	bool "KZM9D board - Reference Device Tree Implementation"
+	depends on ARCH_EMEV2
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	---help---
+	   Use reference implementation of KZM9D board support
+	   which makes a greater use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
+
+comment "SH-Mobile System Configuration"
+endif
+
 if ARCH_SHMOBILE
 
 comment "SH-Mobile System Type"
@@ -23,9 +61,10 @@ config ARCH_R8A73A4
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_GIC
 	select CPU_V7
-	select HAVE_ARM_ARCH_TIMER
 	select SH_CLK_CPG
 	select RENESAS_IRQC
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 
 config ARCH_R8A7740
 	bool "R-Mobile A1 (R8A77400)"
@@ -59,7 +98,6 @@ config ARCH_R8A7790
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_GIC
 	select CPU_V7
-	select HAVE_ARM_ARCH_TIMER
 	select SH_CLK_CPG
 	select RENESAS_IRQC
 
@@ -71,18 +109,22 @@ config ARCH_EMEV2
 
 comment "SH-Mobile Board Type"
 
-config MACH_AG5EVM
-	bool "AG5EVM board"
-	depends on ARCH_SH73A0
-	select ARCH_REQUIRE_GPIOLIB
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	select SH_LCD_MIPI_DSI
-
 config MACH_APE6EVM
 	bool "APE6EVM board"
 	depends on ARCH_R8A73A4
 	select USE_OF
 
+config MACH_APE6EVM_REFERENCE
+	bool "APE6EVM board - Reference Device Tree Implementation"
+	depends on ARCH_R8A73A4
+	select USE_OF
+	---help---
+	   Use reference implementation of APE6EVM board support
+	   which makes a greater use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
+
 config MACH_MACKEREL
 	bool "mackerel board"
 	depends on ARCH_SH7372
@@ -91,12 +133,6 @@ config MACH_MACKEREL
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
 	select USE_OF
 
-config MACH_KOTA2
-	bool "KOTA2 board"
-	depends on ARCH_SH73A0
-	select ARCH_REQUIRE_GPIOLIB
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-
 config MACH_ARMADILLO800EVA
 	bool "Armadillo-800 EVA board"
 	depends on ARCH_R8A7740
@@ -124,13 +160,29 @@ config MACH_BOCKW
 	depends on ARCH_R8A7778
 	select ARCH_REQUIRE_GPIOLIB
 	select RENESAS_INTC_IRQPIN
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select USE_OF
+
+config MACH_BOCKW_REFERENCE
+	bool "BOCK-W  - Reference Device Tree Implementation"
+	depends on ARCH_R8A7778
+	select ARCH_REQUIRE_GPIOLIB
+	select RENESAS_INTC_IRQPIN
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select USE_OF
+	---help---
+	   Use reference implementation of BockW board support
+	   which makes use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
 
 config MACH_MARZEN
 	bool "MARZEN board"
 	depends on ARCH_R8A7779
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select USE_OF
 
 config MACH_MARZEN_REFERENCE
 	bool "MARZEN board - Reference Device Tree Implementation"
@@ -150,12 +202,35 @@ config MACH_LAGER
 	depends on ARCH_R8A7790
 	select USE_OF
 
+config MACH_LAGER_REFERENCE
+	bool "Lager board - Reference Device Tree Implementation"
+	depends on ARCH_R8A7790
+	select USE_OF
+	---help---
+	   Use reference implementation of Lager board support
+	   which makes use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
+
 config MACH_KZM9D
 	bool "KZM9D board"
 	depends on ARCH_EMEV2
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select USE_OF
 
+config MACH_KZM9D_REFERENCE
+	bool "KZM9D board - Reference Device Tree Implementation"
+	depends on ARCH_EMEV2
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select USE_OF
+	---help---
+	   Use reference implementation of KZM9D board support
+	   which makes a greater use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
+
 config MACH_KZM9G
 	bool "KZM-A9-GT board"
 	depends on ARCH_SH73A0
@@ -186,6 +261,15 @@ config CPU_HAS_INTEVT
         bool
 	default y
 
+config SH_CLK_CPG
+	bool
+
+source "drivers/sh/Kconfig"
+
+endif
+
+if ARCH_SHMOBILE || ARCH_SHMOBILE_MULTI
+
 menu "Timer and clock configuration"
 
 config SHMOBILE_TIMER_HZ
@@ -220,9 +304,4 @@ config EM_TIMER_STI
 
 endmenu
 
-config SH_CLK_CPG
-	bool
-
-source "drivers/sh/Kconfig"
-
 endif
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 6165a51..2705bfa 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -2,50 +2,65 @@
 # Makefile for the linux kernel.
 #
 
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/arch/arm/mach-shmobile/include
+
 # Common objects
-obj-y				:= timer.o console.o clock.o
+obj-y				:= timer.o console.o
 
 # CPU objects
-obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o clock-sh7372.o intc-sh7372.o
-obj-$(CONFIG_ARCH_SH73A0)	+= setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
-obj-$(CONFIG_ARCH_R8A73A4)	+= setup-r8a73a4.o clock-r8a73a4.o
-obj-$(CONFIG_ARCH_R8A7740)	+= setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
-obj-$(CONFIG_ARCH_R8A7778)	+= setup-r8a7778.o clock-r8a7778.o
-obj-$(CONFIG_ARCH_R8A7779)	+= setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
-obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o clock-r8a7790.o
-obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o clock-emev2.o
+obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o intc-sh7372.o
+obj-$(CONFIG_ARCH_SH73A0)	+= setup-sh73a0.o intc-sh73a0.o
+obj-$(CONFIG_ARCH_R8A73A4)	+= setup-r8a73a4.o
+obj-$(CONFIG_ARCH_R8A7740)	+= setup-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7778)	+= setup-r8a7778.o
+obj-$(CONFIG_ARCH_R8A7779)	+= setup-r8a7779.o
+obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o
+obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o
+
+# Clock objects
+ifndef CONFIG_COMMON_CLK
+obj-y				+= clock.o
+obj-$(CONFIG_ARCH_SH7372)	+= clock-sh7372.o
+obj-$(CONFIG_ARCH_SH73A0)	+= clock-sh73a0.o
+obj-$(CONFIG_ARCH_R8A73A4)	+= clock-r8a73a4.o
+obj-$(CONFIG_ARCH_R8A7740)	+= clock-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7778)	+= clock-r8a7778.o
+obj-$(CONFIG_ARCH_R8A7779)	+= clock-r8a7779.o
+obj-$(CONFIG_ARCH_R8A7790)	+= clock-r8a7790.o
+obj-$(CONFIG_ARCH_EMEV2)	+= clock-emev2.o
+endif
 
 # SMP objects
 smp-y				:= platsmp.o headsmp.o
-smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-scu.o
-smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o headsmp-scu.o
-smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o headsmp-scu.o
+smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o headsmp-scu.o platsmp-scu.o
 
 # IRQ objects
 obj-$(CONFIG_ARCH_SH7372)	+= entry-intc.o
-obj-$(CONFIG_ARCH_R8A7740)	+= entry-intc.o
 
 # PM objects
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
-obj-$(CONFIG_ARCH_SHMOBILE)	+= pm-rmobile.o
-obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o
-obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o
-obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
+obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o pm-rmobile.o
 obj-$(CONFIG_ARCH_SH73A0)	+= pm-sh73a0.o
+obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o pm-rmobile.o
+obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
 
 # Board objects
-obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
 obj-$(CONFIG_MACH_APE6EVM)	+= board-ape6evm.o
+obj-$(CONFIG_MACH_APE6EVM_REFERENCE)	+= board-ape6evm-reference.o
 obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
-obj-$(CONFIG_MACH_KOTA2)	+= board-kota2.o
 obj-$(CONFIG_MACH_BOCKW)	+= board-bockw.o
+obj-$(CONFIG_MACH_BOCKW_REFERENCE)	+= board-bockw-reference.o
 obj-$(CONFIG_MACH_MARZEN)	+= board-marzen.o
 obj-$(CONFIG_MACH_MARZEN_REFERENCE)	+= board-marzen-reference.o
 obj-$(CONFIG_MACH_LAGER)	+= board-lager.o
+obj-$(CONFIG_MACH_LAGER_REFERENCE)	+= board-lager-reference.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA)	+= board-armadillo800eva.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE)	+= board-armadillo800eva-reference.o
 obj-$(CONFIG_MACH_KZM9D)	+= board-kzm9d.o
+obj-$(CONFIG_MACH_KZM9D_REFERENCE)	+= board-kzm9d-reference.o
 obj-$(CONFIG_MACH_KZM9G)	+= board-kzm9g.o
 obj-$(CONFIG_MACH_KZM9G_REFERENCE)	+= board-kzm9g-reference.o
 
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
index 84c6868..6a504fe 100644
--- a/arch/arm/mach-shmobile/Makefile.boot
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -1,15 +1,17 @@
 # per-board load address for uImage
 loadaddr-y	:=
-loadaddr-$(CONFIG_MACH_AG5EVM) += 0x40008000
 loadaddr-$(CONFIG_MACH_APE6EVM) += 0x40008000
+loadaddr-$(CONFIG_MACH_APE6EVM_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_ARMADILLO800EVA) += 0x40008000
 loadaddr-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000
-loadaddr-$(CONFIG_MACH_KOTA2) += 0x41008000
+loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000
 loadaddr-$(CONFIG_MACH_KZM9D) += 0x40008000
+loadaddr-$(CONFIG_MACH_KZM9D_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
 loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
 loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
+loadaddr-$(CONFIG_MACH_LAGER_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000
 loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000
 loadaddr-$(CONFIG_MACH_MARZEN_REFERENCE) += 0x60008000
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
deleted file mode 100644
index c754071..0000000
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * arch/arm/mach-shmobile/board-ag5evm.c
- *
- * Copyright (C) 2010  Takashi Yoshii <yoshii.takashi.zj@renesas.com>
- * Copyright (C) 2009  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/serial_sci.h>
-#include <linux/smsc911x.h>
-#include <linux/gpio.h>
-#include <linux/videodev2.h>
-#include <linux/input.h>
-#include <linux/input/sh_keysc.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mmcif.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
-#include <linux/mfd/tmio.h>
-#include <linux/sh_clk.h>
-#include <linux/irqchip/arm-gic.h>
-#include <video/sh_mobile_lcdc.h>
-#include <video/sh_mipi_dsi.h>
-#include <sound/sh_fsi.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/traps.h>
-
-/* Dummy supplies, where voltage doesn't matter */
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vddvario", "smsc911x"),
-	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-};
-
-static struct resource smsc9220_resources[] = {
-	[0] = {
-		.start		= 0x14000000,
-		.end		= 0x14000000 + SZ_64K - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= SH73A0_PINT0_IRQ(2), /* PINTA2 */
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct smsc911x_platform_config smsc9220_platdata = {
-	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-};
-
-static struct platform_device eth_device = {
-	.name		= "smsc911x",
-	.id		= 0,
-	.dev  = {
-		.platform_data = &smsc9220_platdata,
-	},
-	.resource	= smsc9220_resources,
-	.num_resources	= ARRAY_SIZE(smsc9220_resources),
-};
-
-static struct sh_keysc_info keysc_platdata = {
-	.mode		= SH_KEYSC_MODE_6,
-	.scan_timing	= 3,
-	.delay		= 100,
-	.keycodes	= {
-		KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
-		KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N,
-		KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
-		KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_HOME, KEY_SLEEP,
-		KEY_SPACE, KEY_9, KEY_6, KEY_3, KEY_WAKEUP, KEY_RIGHT, \
-		KEY_COFFEE,
-		KEY_0, KEY_8, KEY_5, KEY_2, KEY_DOWN, KEY_ENTER, KEY_UP,
-		KEY_KPASTERISK, KEY_7, KEY_4, KEY_1, KEY_STOP, KEY_LEFT, \
-		KEY_COMPUTER,
-	},
-};
-
-static struct resource keysc_resources[] = {
-	[0] = {
-		.name	= "KEYSC",
-		.start	= 0xe61b0000,
-		.end	= 0xe61b0098 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(71),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device keysc_device = {
-	.name		= "sh_keysc",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(keysc_resources),
-	.resource	= keysc_resources,
-	.dev		= {
-		.platform_data	= &keysc_platdata,
-	},
-};
-
-/* FSI A */
-static struct resource fsi_resources[] = {
-	[0] = {
-		.name	= "FSI",
-		.start	= 0xEC230000,
-		.end	= 0xEC230400 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = gic_spi(146),
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device fsi_device = {
-	.name		= "sh_fsi2",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(fsi_resources),
-	.resource	= fsi_resources,
-};
-
-/* Fixed 1.8V regulator to be used by MMCIF */
-static struct regulator_consumer_supply fixed1v8_power_consumers[] =
-{
-	REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"),
-};
-
-static struct resource sh_mmcif_resources[] = {
-	[0] = {
-		.name	= "MMCIF",
-		.start	= 0xe6bd0000,
-		.end	= 0xe6bd00ff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(141),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= gic_spi(140),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct sh_mmcif_plat_data sh_mmcif_platdata = {
-	.sup_pclk	= 0,
-	.ocr		= MMC_VDD_165_195,
-	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
-	.slave_id_tx	= SHDMA_SLAVE_MMCIF_TX,
-	.slave_id_rx	= SHDMA_SLAVE_MMCIF_RX,
-};
-
-static struct platform_device mmc_device = {
-	.name		= "sh_mmcif",
-	.id		= 0,
-	.dev		= {
-		.dma_mask		= NULL,
-		.coherent_dma_mask	= 0xffffffff,
-		.platform_data		= &sh_mmcif_platdata,
-	},
-	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),
-	.resource	= sh_mmcif_resources,
-};
-
-/* IrDA */
-static struct resource irda_resources[] = {
-	[0] = {
-		.start	= 0xE6D00000,
-		.end	= 0xE6D01FD4 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(95),
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device irda_device = {
-	.name           = "sh_irda",
-	.id		= 0,
-	.resource       = irda_resources,
-	.num_resources  = ARRAY_SIZE(irda_resources),
-};
-
-/* MIPI-DSI */
-static struct resource mipidsi0_resources[] = {
-	[0] = {
-		.name	= "DSI0",
-		.start  = 0xfeab0000,
-		.end    = 0xfeab3fff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= "DSI0",
-		.start  = 0xfeab4000,
-		.end    = 0xfeab7fff,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static int sh_mipi_set_dot_clock(struct platform_device *pdev,
-				 void __iomem *base,
-				 int enable)
-{
-	struct clk *pck, *phy;
-	int ret;
-
-	pck = clk_get(&pdev->dev, "dsip_clk");
-	if (IS_ERR(pck)) {
-		ret = PTR_ERR(pck);
-		goto sh_mipi_set_dot_clock_pck_err;
-	}
-
-	phy = clk_get(&pdev->dev, "dsiphy_clk");
-	if (IS_ERR(phy)) {
-		ret = PTR_ERR(phy);
-		goto sh_mipi_set_dot_clock_phy_err;
-	}
-
-	if (enable) {
-		clk_set_rate(pck, clk_round_rate(pck,  24000000));
-		clk_set_rate(phy, clk_round_rate(pck, 510000000));
-		clk_enable(pck);
-		clk_enable(phy);
-	} else {
-		clk_disable(pck);
-		clk_disable(phy);
-	}
-
-	ret = 0;
-
-	clk_put(phy);
-sh_mipi_set_dot_clock_phy_err:
-	clk_put(pck);
-sh_mipi_set_dot_clock_pck_err:
-	return ret;
-}
-
-static struct sh_mipi_dsi_info mipidsi0_info = {
-	.data_format	= MIPI_RGB888,
-	.channel	= LCDC_CHAN_MAINLCD,
-	.lane		= 2,
-	.vsynw_offset	= 20,
-	.clksrc		= 1,
-	.flags		= SH_MIPI_DSI_HSABM		|
-			  SH_MIPI_DSI_SYNC_PULSES_MODE	|
-			  SH_MIPI_DSI_HSbyteCLK,
-	.set_dot_clock	= sh_mipi_set_dot_clock,
-};
-
-static struct platform_device mipidsi0_device = {
-	.name           = "sh-mipi-dsi",
-	.num_resources  = ARRAY_SIZE(mipidsi0_resources),
-	.resource       = mipidsi0_resources,
-	.id             = 0,
-	.dev	= {
-		.platform_data	= &mipidsi0_info,
-	},
-};
-
-static unsigned char lcd_backlight_seq[3][2] = {
-	{ 0x04, 0x07 },
-	{ 0x23, 0x80 },
-	{ 0x03, 0x01 },
-};
-
-static int lcd_backlight_set_brightness(int brightness)
-{
-	struct i2c_adapter *adap;
-	struct i2c_msg msg;
-	unsigned int i;
-	int ret;
-
-	if (brightness == 0) {
-		/* Reset the chip */
-		gpio_set_value(235, 0);
-		mdelay(24);
-		gpio_set_value(235, 1);
-		return 0;
-	}
-
-	adap = i2c_get_adapter(1);
-	if (adap == NULL)
-		return -ENODEV;
-
-	for (i = 0; i < ARRAY_SIZE(lcd_backlight_seq); i++) {
-		msg.addr = 0x6d;
-		msg.buf = &lcd_backlight_seq[i][0];
-		msg.len = 2;
-		msg.flags = 0;
-
-		ret = i2c_transfer(adap, &msg, 1);
-		if (ret < 0)
-			break;
-	}
-
-	i2c_put_adapter(adap);
-	return ret < 0 ? ret : 0;
-}
-
-/* LCDC0 */
-static const struct fb_videomode lcdc0_modes[] = {
-	{
-		.name		= "R63302(QHD)",
-		.xres		= 544,
-		.yres		= 961,
-		.left_margin	= 72,
-		.right_margin	= 600,
-		.hsync_len	= 16,
-		.upper_margin	= 8,
-		.lower_margin	= 8,
-		.vsync_len	= 2,
-		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-	},
-};
-
-static struct sh_mobile_lcdc_info lcdc0_info = {
-	.clock_source = LCDC_CLK_PERIPHERAL,
-	.ch[0] = {
-		.chan = LCDC_CHAN_MAINLCD,
-		.interface_type = RGB24,
-		.clock_divider = 1,
-		.flags = LCDC_FLAGS_DWPOL,
-		.fourcc = V4L2_PIX_FMT_RGB565,
-		.lcd_modes = lcdc0_modes,
-		.num_modes = ARRAY_SIZE(lcdc0_modes),
-		.panel_cfg = {
-			.width = 44,
-			.height = 79,
-		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = lcd_backlight_set_brightness,
-		},
-		.tx_dev = &mipidsi0_device,
-	}
-};
-
-static struct resource lcdc0_resources[] = {
-	[0] = {
-		.name	= "LCDC0",
-		.start	= 0xfe940000, /* P4-only space */
-		.end	= 0xfe943fff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= intcs_evt2irq(0x580),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device lcdc0_device = {
-	.name		= "sh_mobile_lcdc_fb",
-	.num_resources	= ARRAY_SIZE(lcdc0_resources),
-	.resource	= lcdc0_resources,
-	.id             = 0,
-	.dev	= {
-		.platform_data	= &lcdc0_info,
-		.coherent_dma_mask = ~0,
-	},
-};
-
-/* Fixed 2.8V regulators to be used by SDHI0 */
-static struct regulator_consumer_supply fixed2v8_power_consumers[] =
-{
-	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
-};
-
-/* SDHI0 */
-static struct sh_mobile_sdhi_info sdhi0_info = {
-	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
-	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
-	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
-	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
-	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
-	.cd_gpio	= 251,
-};
-
-static struct resource sdhi0_resources[] = {
-	[0] = {
-		.name	= "SDHI0",
-		.start	= 0xee100000,
-		.end	= 0xee1000ff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
-		.start	= gic_spi(83),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
-		.start	= gic_spi(84),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
-		.start	= gic_spi(85),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sdhi0_device = {
-	.name		= "sh_mobile_sdhi",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(sdhi0_resources),
-	.resource	= sdhi0_resources,
-	.dev	= {
-		.platform_data	= &sdhi0_info,
-	},
-};
-
-/* Fixed 3.3V regulator to be used by SDHI1 */
-static struct regulator_consumer_supply cn4_power_consumers[] =
-{
-	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
-};
-
-static struct regulator_init_data cn4_power_init_data = {
-	.constraints = {
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = ARRAY_SIZE(cn4_power_consumers),
-	.consumer_supplies      = cn4_power_consumers,
-};
-
-static struct fixed_voltage_config cn4_power_info = {
-	.supply_name = "CN4 SD/MMC Vdd",
-	.microvolts = 3300000,
-	.gpio = 114,
-	.enable_high = 1,
-	.init_data = &cn4_power_init_data,
-};
-
-static struct platform_device cn4_power = {
-	.name = "reg-fixed-voltage",
-	.id   = 2,
-	.dev  = {
-		.platform_data = &cn4_power_info,
-	},
-};
-
-static void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
-{
-	static int power_gpio = -EINVAL;
-
-	if (power_gpio < 0) {
-		int ret = gpio_request_one(114, GPIOF_OUT_INIT_LOW,
-					   "sdhi1_power");
-		if (!ret)
-			power_gpio = 114;
-	}
-
-	/*
-	 * If requesting the GPIO above failed, it means, that the regulator got
-	 * probed and grabbed the GPIO, but we don't know, whether the sdhi
-	 * driver already uses the regulator. If it doesn't, we have to toggle
-	 * the GPIO ourselves, even though it is now owned by the fixed
-	 * regulator driver. We have to live with the race in case the driver
-	 * gets unloaded and the GPIO freed between these two steps.
-	 */
-	gpio_set_value(114, state);
-}
-
-static struct sh_mobile_sdhi_info sh_sdhi1_info = {
-	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
-	.tmio_caps	= MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
-	.tmio_ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.set_pwr	= ag5evm_sdhi1_set_pwr,
-};
-
-static struct resource sdhi1_resources[] = {
-	[0] = {
-		.name	= "SDHI1",
-		.start	= 0xee120000,
-		.end	= 0xee1200ff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
-		.start	= gic_spi(87),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
-		.start	= gic_spi(88),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
-		.start	= gic_spi(89),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sdhi1_device = {
-	.name		= "sh_mobile_sdhi",
-	.id		= 1,
-	.dev		= {
-		.platform_data	= &sh_sdhi1_info,
-	},
-	.num_resources	= ARRAY_SIZE(sdhi1_resources),
-	.resource	= sdhi1_resources,
-};
-
-static struct platform_device *ag5evm_devices[] __initdata = {
-	&cn4_power,
-	&eth_device,
-	&keysc_device,
-	&fsi_device,
-	&mmc_device,
-	&irda_device,
-	&mipidsi0_device,
-	&lcdc0_device,
-	&sdhi0_device,
-	&sdhi1_device,
-};
-
-static unsigned long pin_pullup_conf[] = {
-	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
-};
-
-static const struct pinctrl_map ag5evm_pinctrl_map[] = {
-	/* FSIA */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
-				  "fsia_mclk_in", "fsia"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
-				  "fsia_sclk_in", "fsia"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
-				  "fsia_data_in", "fsia"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
-				  "fsia_data_out", "fsia"),
-	/* I2C2 & I2C3 */
-	PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.2", "pfc-sh73a0",
-				  "i2c2_0", "i2c2"),
-	PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.3", "pfc-sh73a0",
-				  "i2c3_0", "i2c3"),
-	/* IrDA */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_irda.0", "pfc-sh73a0",
-				  "irda_0", "irda"),
-	/* KEYSC */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_in8", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out04", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out5", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out6_0", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out7_0", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out8_0", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out9_2", "keysc"),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				      "keysc_in8", pin_pullup_conf),
-	/* MMCIF */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				  "mmc0_data8_0", "mmc0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				  "mmc0_ctrl_0", "mmc0"),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				    "PORT279", pin_pullup_conf),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				      "mmc0_data8_0", pin_pullup_conf),
-	/* SCIFA2 */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
-				  "scifa2_data_0", "scifa2"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
-				  "scifa2_ctrl_0", "scifa2"),
-	/* SDHI0 (CN15 [SD I/F]) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				  "sdhi0_data4", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				  "sdhi0_ctrl", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				  "sdhi0_wp", "sdhi0"),
-	/* SDHI1 (CN4 [WLAN I/F]) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				  "sdhi1_data4", "sdhi1"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				  "sdhi1_ctrl", "sdhi1"),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				      "sdhi1_data4", pin_pullup_conf),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				    "PORT263", pin_pullup_conf),
-};
-
-static void __init ag5evm_init(void)
-{
-	regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
-				     ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
-	regulator_register_always_on(1, "fixed-2.8V", fixed2v8_power_consumers,
-				     ARRAY_SIZE(fixed2v8_power_consumers), 3300000);
-	regulator_register_fixed(3, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-	pinctrl_register_mappings(ag5evm_pinctrl_map,
-				  ARRAY_SIZE(ag5evm_pinctrl_map));
-	sh73a0_pinmux_init();
-
-	/* enable MMCIF */
-	gpio_request_one(208, GPIOF_OUT_INIT_HIGH, NULL); /* Reset */
-
-	/* enable SMSC911X */
-	gpio_request_one(144, GPIOF_IN, NULL); /* PINTA2 */
-	gpio_request_one(145, GPIOF_OUT_INIT_HIGH, NULL); /* RESET */
-
-	/* LCD panel */
-	gpio_request_one(217, GPIOF_OUT_INIT_LOW, NULL); /* RESET */
-	mdelay(1);
-	gpio_set_value(217, 1);
-	mdelay(100);
-
-	/* LCD backlight controller */
-	gpio_request_one(235, GPIOF_OUT_INIT_LOW, NULL); /* RESET */
-	lcd_backlight_set_brightness(0);
-
-#ifdef CONFIG_CACHE_L2X0
-	/* Shared attribute override enable, 64K*8way */
-	l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff);
-#endif
-	sh73a0_add_standard_devices();
-	platform_add_devices(ag5evm_devices, ARRAY_SIZE(ag5evm_devices));
-}
-
-MACHINE_START(AG5EVM, "ag5evm")
-	.smp		= smp_ops(sh73a0_smp_ops),
-	.map_io		= sh73a0_map_io,
-	.init_early	= sh73a0_add_early_devices,
-	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= sh73a0_init_irq,
-	.init_machine	= ag5evm_init,
-	.init_late	= shmobile_init_late,
-	.init_time	= sh73a0_earlytimer_init,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ape6evm-reference.c b/arch/arm/mach-shmobile/board-ape6evm-reference.c
new file mode 100644
index 0000000..a23fa71
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-ape6evm-reference.c
@@ -0,0 +1,63 @@
+/*
+ * APE6EVM board support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/sh_clk.h>
+#include <mach/common.h>
+#include <mach/r8a73a4.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init ape6evm_add_standard_devices(void)
+{
+
+	struct clk *parent;
+	struct clk *mp;
+
+	r8a73a4_clock_init();
+
+	/* MP clock parent = extal2 */
+	parent      = clk_get(NULL, "extal2");
+	mp          = clk_get(NULL, "mp");
+	BUG_ON(IS_ERR(parent) || IS_ERR(mp));
+
+	clk_set_parent(mp, parent);
+	clk_put(parent);
+	clk_put(mp);
+
+	r8a73a4_add_dt_devices();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
+}
+
+static const char *ape6evm_boards_compat_dt[] __initdata = {
+	"renesas,ape6evm-reference",
+	NULL,
+};
+
+DT_MACHINE_START(APE6EVM_DT, "ape6evm")
+	.init_early	= r8a73a4_init_delay,
+	.init_machine	= ape6evm_add_standard_devices,
+	.dt_compat	= ape6evm_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
index 5eb0caa..24b87eea 100644
--- a/arch/arm/mach-shmobile/board-ape6evm.c
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -19,9 +19,14 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
 #include <linux/interrupt.h>
-#include <linux/irqchip.h>
 #include <linux/kernel.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/fixed.h>
@@ -34,6 +39,58 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+/* LEDS */
+static struct gpio_led ape6evm_leds[] = {
+	{
+		.name		= "gnss-en",
+		.gpio		= 28,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	}, {
+		.name		= "nfc-nrst",
+		.gpio		= 126,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	}, {
+		.name		= "gnss-nrst",
+		.gpio		= 132,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	}, {
+		.name		= "bt-wakeup",
+		.gpio		= 232,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	}, {
+		.name		= "strobe",
+		.gpio		= 250,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	}, {
+		.name		= "bbresetout",
+		.gpio		= 288,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	},
+};
+
+static __initdata struct gpio_led_platform_data ape6evm_leds_pdata = {
+	.leds		= ape6evm_leds,
+	.num_leds	= ARRAY_SIZE(ape6evm_leds),
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d, ...) \
+	{ .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+	GPIO_KEY(KEY_0,			324,	"S16"),
+	GPIO_KEY(KEY_MENU,		325,	"S17"),
+	GPIO_KEY(KEY_HOME,		326,	"S18"),
+	GPIO_KEY(KEY_BACK,		327,	"S19"),
+	GPIO_KEY(KEY_VOLUMEUP,		328,	"S20"),
+	GPIO_KEY(KEY_VOLUMEDOWN,	329,	"S21"),
+};
+
+static struct __initdata gpio_keys_platform_data ape6evm_keys_pdata = {
+	.buttons	= gpio_buttons,
+	.nbuttons	= ARRAY_SIZE(gpio_buttons),
+};
+
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x"),
@@ -41,7 +98,7 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 };
 
 /* SMSC LAN9220 */
-static const struct resource lan9220_res[] = {
+static const struct resource lan9220_res[] __initconst = {
 	DEFINE_RES_MEM(0x08000000, 0x1000),
 	{
 		.start	= irq_pin(40), /* IRQ40 */
@@ -49,19 +106,83 @@ static const struct resource lan9220_res[] = {
 	},
 };
 
-static const struct smsc911x_platform_config lan9220_data = {
+static const struct smsc911x_platform_config lan9220_data __initconst = {
 	.flags		= SMSC911X_USE_32BIT,
 	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
 	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
 };
 
-static const struct pinctrl_map ape6evm_pinctrl_map[] = {
+/*
+ * On APE6EVM power is supplied to MMCIF by a tps80032 regulator. For now we
+ * model a VDD supply to MMCIF, using a fixed 3.3V regulator. Also use the
+ * static power supply for SDHI0 and SDHI1, whereas SDHI0's VccQ is also
+ * supplied by the same tps80032 regulator and thus can also be adjusted
+ * dynamically.
+ */
+static struct regulator_consumer_supply fixed3v3_power_consumers[] =
+{
+	REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
+	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
+};
+
+/* MMCIF */
+static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = {
+	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static const struct resource mmcif0_resources[] __initconst = {
+	DEFINE_RES_MEM_NAMED(0xee200000, 0x100, "MMCIF0"),
+	DEFINE_RES_IRQ(gic_spi(169)),
+};
+
+/* SDHI0 */
+static const struct sh_mobile_sdhi_info sdhi0_pdata __initconst = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+};
+
+static const struct resource sdhi0_resources[] __initconst = {
+	DEFINE_RES_MEM_NAMED(0xee100000, 0x100, "SDHI0"),
+	DEFINE_RES_IRQ(gic_spi(165)),
+};
+
+/* SDHI1 */
+static const struct sh_mobile_sdhi_info sdhi1_pdata __initconst = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_NEEDS_POLL,
+};
+
+static const struct resource sdhi1_resources[] __initconst = {
+	DEFINE_RES_MEM_NAMED(0xee120000, 0x100, "SDHI1"),
+	DEFINE_RES_IRQ(gic_spi(166)),
+};
+
+static const struct pinctrl_map ape6evm_pinctrl_map[] __initconst = {
 	/* SCIFA0 console */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a73a4",
 				  "scifa0_data", "scifa0"),
 	/* SMSC */
 	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a73a4",
 				  "irqc_irq40", "irqc"),
+	/* MMCIF0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a73a4",
+				  "mmc0_data8", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a73a4",
+				  "mmc0_ctrl", "mmc0"),
+	/* SDHI0: uSD: no WP */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
+				  "sdhi0_cd", "sdhi0"),
+	/* SDHI1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a73a4",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a73a4",
+				  "sdhi1_ctrl", "sdhi1"),
 };
 
 static void __init ape6evm_add_standard_devices(void)
@@ -94,6 +215,23 @@ static void __init ape6evm_add_standard_devices(void)
 	platform_device_register_resndata(&platform_bus, "smsc911x", -1,
 					  lan9220_res, ARRAY_SIZE(lan9220_res),
 					  &lan9220_data, sizeof(lan9220_data));
+	regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
+				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+	platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
+					  mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
+					  &mmcif0_pdata, sizeof(mmcif0_pdata));
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
+					  &sdhi0_pdata, sizeof(sdhi0_pdata));
+	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+					  sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
+					  &sdhi1_pdata, sizeof(sdhi1_pdata));
+	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+				      &ape6evm_keys_pdata,
+				      sizeof(ape6evm_keys_pdata));
+	platform_device_register_data(&platform_bus, "leds-gpio", -1,
+				      &ape6evm_leds_pdata,
+				      sizeof(ape6evm_leds_pdata));
 }
 
 static const char *ape6evm_boards_compat_dt[] __initdata = {
@@ -102,8 +240,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
 };
 
 DT_MACHINE_START(APE6EVM_DT, "ape6evm")
-	.init_irq	= irqchip_init,
-	.init_time	= shmobile_timer_init,
+	.init_early	= r8a73a4_init_delay,
 	.init_machine	= ape6evm_add_standard_devices,
 	.dt_compat	= ape6evm_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
index 03b85fe..57d1a78 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
@@ -24,7 +24,6 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
-#include <linux/pinctrl/machine.h>
 #include <mach/common.h>
 #include <mach/r8a7740.h>
 #include <asm/mach/arch.h>
@@ -119,12 +118,6 @@
  *	usbhsf_power_ctrl()
  */
 
-static const struct pinctrl_map eva_pinctrl_map[] = {
-	/* SCIFA1 */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.1", "pfc-r8a7740",
-				  "scifa1_data", "scifa1"),
-};
-
 static void __init eva_clock_init(void)
 {
 	struct clk *system	= clk_get(NULL, "system_clk");
@@ -165,35 +158,26 @@ clock_error:
  */
 static void __init eva_init(void)
 {
-
 	r8a7740_clock_init(MD_CK0 | MD_CK2);
 	eva_clock_init();
 
-	pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
-	r8a7740_pinmux_init();
-
 	r8a7740_meram_workaround();
 
-	/*
-	 * Touchscreen
-	 * TODO: Move reset GPIO over to .dts when we can reference it
-	 */
-	gpio_request_one(166, GPIOF_OUT_INIT_HIGH, NULL); /* TP_RST_B */
-
 #ifdef CONFIG_CACHE_L2X0
 	/* Early BRESP enable, Shared attribute override enable, 32K*8way */
 	l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
 #endif
 
 	r8a7740_add_standard_devices_dt();
+
 	r8a7740_pm_init();
 }
 
 #define RESCNT2 IOMEM(0xe6188020)
-static void eva_restart(char mode, const char *cmd)
+static void eva_restart(enum reboot_mode mode, const char *cmd)
 {
 	/* Do soft power on reset */
-	writel((1 << 31), RESCNT2);
+	writel(1 << 31, RESCNT2);
 }
 
 static const char *eva_boards_compat_dt[] __initdata = {
@@ -206,7 +190,6 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva-reference")
 	.init_early	= r8a7740_init_delay,
 	.init_irq	= r8a7740_init_irq_of,
 	.init_machine	= eva_init,
-	.init_time	= shmobile_timer_init,
 	.init_late	= shmobile_init_late,
 	.dt_compat	= eva_boards_compat_dt,
 	.restart	= eva_restart,
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index e115f67..da58332 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -31,6 +31,8 @@
 #include <linux/gpio_keys.h>
 #include <linux/regulator/driver.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pwm-renesas-tpu.h>
+#include <linux/pwm_backlight.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/machine.h>
@@ -387,7 +389,50 @@ static struct platform_device sh_eth_device = {
 	.num_resources = ARRAY_SIZE(sh_eth_resources),
 };
 
-/* LCDC */
+/* PWM */
+static struct resource pwm_resources[] = {
+	[0] = {
+		.start = 0xe6600000,
+		.end = 0xe66000ff,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct tpu_pwm_platform_data pwm_device_data = {
+	.channels[2] = {
+		.polarity = PWM_POLARITY_INVERSED,
+	}
+};
+
+static struct platform_device pwm_device = {
+	.name = "renesas-tpu-pwm",
+	.id = -1,
+	.dev = {
+		.platform_data = &pwm_device_data,
+	},
+	.num_resources = ARRAY_SIZE(pwm_resources),
+	.resource = pwm_resources,
+};
+
+static struct pwm_lookup pwm_lookup[] = {
+	PWM_LOOKUP("renesas-tpu-pwm", 2, "pwm-backlight.0", NULL),
+};
+
+/* LCDC and backlight */
+static struct platform_pwm_backlight_data pwm_backlight_data = {
+	.lth_brightness = 50,
+	.max_brightness = 255,
+	.dft_brightness = 255,
+	.pwm_period_ns = 33333, /* 30kHz */
+};
+
+static struct platform_device pwm_backlight_device = {
+	.name = "pwm-backlight",
+	.dev = {
+		.platform_data = &pwm_backlight_data,
+	},
+};
+
 static struct fb_videomode lcdc0_mode = {
 	.name		= "AMPIER/AM-800480",
 	.xres		= 800,
@@ -679,15 +724,6 @@ static struct platform_device vcc_sdhi1 = {
 };
 
 /* SDHI0 */
-/*
- * FIXME
- *
- * It use polling mode here, since
- * CD (= Card Detect) pin is not connected to SDHI0_CD.
- * We can use IRQ31 as card detect irq,
- * but it needs chattering removal operation
- */
-#define IRQ31	irq_pin(31)
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
@@ -788,6 +824,8 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
 	.caps		= MMC_CAP_4_BIT_DATA |
 			  MMC_CAP_8_BIT_DATA |
 			  MMC_CAP_NONREMOVABLE,
+	.slave_id_tx	= SHDMA_SLAVE_MMCIF_TX,
+	.slave_id_rx	= SHDMA_SLAVE_MMCIF_RX,
 };
 
 static struct resource sh_mmcif_resources[] = {
@@ -1030,6 +1068,8 @@ static struct i2c_board_info i2c2_devices[] = {
  */
 static struct platform_device *eva_devices[] __initdata = {
 	&lcdc0_device,
+	&pwm_device,
+	&pwm_backlight_device,
 	&gpio_keys_device,
 	&sh_eth_device,
 	&vcc_sdhi0,
@@ -1101,6 +1141,9 @@ static const struct pinctrl_map eva_pinctrl_map[] = {
 	/* ST1232 */
 	PIN_MAP_MUX_GROUP_DEFAULT("0-0055", "pfc-r8a7740",
 				  "intc_irq10", "intc"),
+	/* TPU0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("renesas-tpu-pwm", "pfc-r8a7740",
+				  "tpu0_to2_1", "tpu0"),
 	/* USBHS */
 	PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7740",
 				  "intc_irq7_1", "intc"),
@@ -1154,16 +1197,13 @@ static void __init eva_init(void)
 				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
 
 	pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
+	pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
 
 	r8a7740_pinmux_init();
 	r8a7740_meram_workaround();
 
 	/* LCDC0 */
 	gpio_request_one(61, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
-	gpio_request_one(202, GPIOF_OUT_INIT_LOW, NULL); /* LCD0_LED_CONT */
-
-	/* Touchscreen */
-	gpio_request_one(166, GPIOF_OUT_INIT_HIGH, NULL); /* TP_RST_B */
 
 	/* GETHER */
 	gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */
@@ -1274,7 +1314,7 @@ static const char *eva_boards_compat_dt[] __initdata = {
 DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
 	.map_io		= r8a7740_map_io,
 	.init_early	= eva_add_early_devices,
-	.init_irq	= r8a7740_init_irq,
+	.init_irq	= r8a7740_init_irq_of,
 	.init_machine	= eva_init,
 	.init_late	= shmobile_init_late,
 	.init_time	= eva_earlytimer_init,
diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c
new file mode 100644
index 0000000..1a7c893
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-bockw-reference.c
@@ -0,0 +1,61 @@
+/*
+ * Bock-W board support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/of_platform.h>
+#include <linux/pinctrl/machine.h>
+#include <mach/common.h>
+#include <mach/r8a7778.h>
+#include <asm/mach/arch.h>
+
+/*
+ *	see board-bock.c for checking detail of dip-switch
+ */
+
+static const struct pinctrl_map bockw_pinctrl_map[] = {
+	/* SCIF0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
+				  "scif0_data_a", "scif0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
+				  "scif0_ctrl", "scif0"),
+};
+
+static void __init bockw_init(void)
+{
+	r8a7778_clock_init();
+
+	pinctrl_register_mappings(bockw_pinctrl_map,
+				  ARRAY_SIZE(bockw_pinctrl_map));
+	r8a7778_pinmux_init();
+	r8a7778_add_dt_devices();
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *bockw_boards_compat_dt[] __initdata = {
+	"renesas,bockw-reference",
+	NULL,
+};
+
+DT_MACHINE_START(BOCKW_DT, "bockw")
+	.init_early	= r8a7778_init_delay,
+	.init_irq	= r8a7778_init_irq_dt,
+	.init_machine	= bockw_init,
+	.dt_compat	= bockw_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index d555464..255e97e 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -20,8 +20,11 @@
 
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mmc/sh_mmcif.h>
 #include <linux/mtd/partitions.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/usb-rcar-phy.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
@@ -64,28 +67,38 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
 };
 
-static struct smsc911x_platform_config smsc911x_data = {
+static struct smsc911x_platform_config smsc911x_data __initdata = {
 	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
 	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
 	.flags		= SMSC911X_USE_32BIT,
 	.phy_interface	= PHY_INTERFACE_MODE_MII,
 };
 
-static struct resource smsc911x_resources[] = {
+static struct resource smsc911x_resources[] __initdata = {
 	DEFINE_RES_MEM(0x18300000, 0x1000),
 	DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */
 };
 
 /* USB */
+static struct resource usb_phy_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffe70800, 0x100),
+	DEFINE_RES_MEM(0xffe76000, 0x100),
+};
+
 static struct rcar_phy_platform_data usb_phy_platform_data __initdata;
 
 /* SDHI */
-static struct sh_mobile_sdhi_info sdhi0_info = {
+static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
 	.tmio_ocr_mask	= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
 };
 
+static struct resource sdhi0_resources[] __initdata = {
+	DEFINE_RES_MEM(0xFFE4C000, 0x100),
+	DEFINE_RES_IRQ(gic_iid(0x77)),
+};
+
 static struct sh_eth_plat_data ether_platform_data __initdata = {
 	.phy		= 0x01,
 	.edmac_endian	= EDMAC_LITTLE_ENDIAN,
@@ -135,7 +148,12 @@ static struct spi_board_info spi_board_info[] __initdata = {
 };
 
 /* MMC */
-static struct sh_mmcif_plat_data sh_mmcif_plat = {
+static struct resource mmc_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffe4e000, 0x100),
+	DEFINE_RES_IRQ(gic_iid(0x5d)),
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat __initdata = {
 	.sup_pclk	= 0,
 	.ocr		= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
 	.caps		= MMC_CAP_4_BIT_DATA |
@@ -167,7 +185,13 @@ static const struct pinctrl_map bockw_pinctrl_map[] = {
 				  "usb1", "usb1"),
 	/* SDHI0 */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
-				  "sdhi0", "sdhi0"),
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+				  "sdhi0_wp", "sdhi0"),
 };
 
 #define FPGA	0x18200000
@@ -181,11 +205,7 @@ static void __init bockw_init(void)
 	r8a7778_clock_init();
 	r8a7778_init_irq_extpin(1);
 	r8a7778_add_standard_devices();
-	r8a7778_add_usb_phy_device(&usb_phy_platform_data);
 	r8a7778_add_ether_device(&ether_platform_data);
-	r8a7778_add_i2c_device(0);
-	r8a7778_add_hspi_device(0);
-	r8a7778_add_mmc_device(&sh_mmcif_plat);
 
 	i2c_register_board_info(0, i2c0_devices,
 				ARRAY_SIZE(i2c0_devices));
@@ -195,6 +215,19 @@ static void __init bockw_init(void)
 				  ARRAY_SIZE(bockw_pinctrl_map));
 	r8a7778_pinmux_init();
 
+	platform_device_register_resndata(
+		&platform_bus, "sh_mmcif", -1,
+		mmc_resources, ARRAY_SIZE(mmc_resources),
+		&sh_mmcif_plat, sizeof(struct sh_mmcif_plat_data));
+
+	platform_device_register_resndata(
+		&platform_bus, "rcar_usb_phy", -1,
+		usb_phy_resources,
+		ARRAY_SIZE(usb_phy_resources),
+		&usb_phy_platform_data,
+		sizeof(struct rcar_phy_platform_data));
+
+
 	/* for SMSC */
 	base = ioremap_nocache(FPGA, SZ_1M);
 	if (base) {
@@ -230,7 +263,10 @@ static void __init bockw_init(void)
 		iowrite32(ioread32(base + PUPR4) | (3 << 26), base + PUPR4);
 		iounmap(base);
 
-		r8a7778_sdhi_init(0, &sdhi0_info);
+		platform_device_register_resndata(
+			&platform_bus, "sh_mobile_sdhi", 0,
+			sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
+			&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
 	}
 }
 
@@ -243,7 +279,6 @@ DT_MACHINE_START(BOCKW_DT, "bockw")
 	.init_early	= r8a7778_init_delay,
 	.init_irq	= r8a7778_init_irq_dt,
 	.init_machine	= bockw_init,
-	.init_time	= shmobile_timer_init,
 	.dt_compat	= bockw_boards_compat_dt,
 	.init_late      = r8a7778_init_late,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
deleted file mode 100644
index ef5ca0e..0000000
--- a/arch/arm/mach-shmobile/board-kota2.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * kota2 board support
- *
- * Copyright (C) 2011  Renesas Solutions Corp.
- * Copyright (C) 2011  Magnus Damm
- * Copyright (C) 2010  Takashi Yoshii <yoshii.takashi.zj@renesas.com>
- * Copyright (C) 2009  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/smsc911x.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/input/sh_keysc.h>
-#include <linux/gpio_keys.h>
-#include <linux/leds.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/platform_data/leds-renesas-tpu.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mmcif.h>
-#include <linux/mfd/tmio.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/traps.h>
-
-/* Dummy supplies, where voltage doesn't matter */
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vddvario", "smsc911x"),
-	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-};
-
-/* SMSC 9220 */
-static struct resource smsc9220_resources[] = {
-	[0] = {
-		.start		= 0x14000000, /* CS5A */
-		.end		= 0x140000ff, /* A1->A7 */
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= SH73A0_PINT0_IRQ(2), /* PINTA2 */
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct smsc911x_platform_config smsc9220_platdata = {
-	.flags		= SMSC911X_USE_32BIT, /* 32-bit SW on 16-bit HW bus */
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-};
-
-static struct platform_device eth_device = {
-	.name		= "smsc911x",
-	.id		= 0,
-	.dev  = {
-		.platform_data = &smsc9220_platdata,
-	},
-	.resource	= smsc9220_resources,
-	.num_resources	= ARRAY_SIZE(smsc9220_resources),
-};
-
-/* KEYSC */
-static struct sh_keysc_info keysc_platdata = {
-	.mode		= SH_KEYSC_MODE_6,
-	.scan_timing	= 3,
-	.delay		= 100,
-	.keycodes	= {
-		KEY_NUMERIC_STAR, KEY_NUMERIC_0, KEY_NUMERIC_POUND,
-		0, 0, 0, 0, 0,
-		KEY_NUMERIC_7, KEY_NUMERIC_8, KEY_NUMERIC_9,
-		0, KEY_DOWN, 0, 0, 0,
-		KEY_NUMERIC_4, KEY_NUMERIC_5, KEY_NUMERIC_6,
-		KEY_LEFT, KEY_ENTER, KEY_RIGHT, 0, 0,
-		KEY_NUMERIC_1, KEY_NUMERIC_2, KEY_NUMERIC_3,
-		0, KEY_UP, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 0,
-	},
-};
-
-static struct resource keysc_resources[] = {
-	[0] = {
-		.name	= "KEYSC",
-		.start	= 0xe61b0000,
-		.end	= 0xe61b0098 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(71),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device keysc_device = {
-	.name		= "sh_keysc",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(keysc_resources),
-	.resource	= keysc_resources,
-	.dev		= {
-		.platform_data	= &keysc_platdata,
-	},
-};
-
-/* GPIO KEY */
-#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-
-static struct gpio_keys_button gpio_buttons[] = {
-	GPIO_KEY(KEY_VOLUMEUP, 56, "+"), /* S2: VOL+ [IRQ9] */
-	GPIO_KEY(KEY_VOLUMEDOWN, 54, "-"), /* S3: VOL- [IRQ10] */
-	GPIO_KEY(KEY_MENU, 27, "Menu"), /* S4: MENU [IRQ30] */
-	GPIO_KEY(KEY_HOMEPAGE, 26, "Home"), /* S5: HOME [IRQ31] */
-	GPIO_KEY(KEY_BACK, 11, "Back"), /* S6: BACK [IRQ0] */
-	GPIO_KEY(KEY_PHONE, 238, "Tel"), /* S7: TEL [IRQ11] */
-	GPIO_KEY(KEY_POWER, 239, "C1"), /* S8: CAM [IRQ13] */
-	GPIO_KEY(KEY_MAIL, 224, "Mail"), /* S9: MAIL [IRQ3] */
-	/* Omitted button "C3?": 223 - S10: CUST [IRQ8] */
-	GPIO_KEY(KEY_CAMERA, 164, "C2"), /* S11: CAM_HALF [IRQ25] */
-	/* Omitted button "?": 152 - S12: CAM_FULL [No IRQ] */
-};
-
-static struct gpio_keys_platform_data gpio_key_info = {
-	.buttons        = gpio_buttons,
-	.nbuttons       = ARRAY_SIZE(gpio_buttons),
-};
-
-static struct platform_device gpio_keys_device = {
-	.name   = "gpio-keys",
-	.id     = -1,
-	.dev    = {
-		.platform_data  = &gpio_key_info,
-	},
-};
-
-/* GPIO LED */
-#define GPIO_LED(n, g) { .name = n, .gpio = g }
-
-static struct gpio_led gpio_leds[] = {
-	GPIO_LED("G", 20), /* PORT20 [GPO0] -> LED7 -> "G" */
-	GPIO_LED("H", 21), /* PORT21 [GPO1] -> LED8 -> "H" */
-	GPIO_LED("J", 22), /* PORT22 [GPO2] -> LED9 -> "J" */
-};
-
-static struct gpio_led_platform_data gpio_leds_info = {
-	.leds		= gpio_leds,
-	.num_leds	= ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device gpio_leds_device = {
-	.name   = "leds-gpio",
-	.id     = -1,
-	.dev    = {
-		.platform_data  = &gpio_leds_info,
-	},
-};
-
-/* TPU LED */
-static struct led_renesas_tpu_config led_renesas_tpu12_pdata = {
-	.name		= "V2513",
-	.pin_gpio_fn	= GPIO_FN_TPU1TO2,
-	.pin_gpio	= 153,
-	.channel_offset = 0x90,
-	.timer_bit = 2,
-	.max_brightness = 1000,
-};
-
-static struct resource tpu12_resources[] = {
-	[0] = {
-		.name	= "TPU12",
-		.start	= 0xe6610090,
-		.end	= 0xe66100b5,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device leds_tpu12_device = {
-	.name = "leds-renesas-tpu",
-	.id = 12,
-	.dev = {
-		.platform_data  = &led_renesas_tpu12_pdata,
-	},
-	.num_resources	= ARRAY_SIZE(tpu12_resources),
-	.resource	= tpu12_resources,
-};
-
-static struct led_renesas_tpu_config led_renesas_tpu41_pdata = {
-	.name		= "V2514",
-	.pin_gpio_fn	= GPIO_FN_TPU4TO1,
-	.pin_gpio	= 199,
-	.channel_offset = 0x50,
-	.timer_bit = 1,
-	.max_brightness = 1000,
-};
-
-static struct resource tpu41_resources[] = {
-	[0] = {
-		.name	= "TPU41",
-		.start	= 0xe6640050,
-		.end	= 0xe6640075,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device leds_tpu41_device = {
-	.name = "leds-renesas-tpu",
-	.id = 41,
-	.dev = {
-		.platform_data  = &led_renesas_tpu41_pdata,
-	},
-	.num_resources	= ARRAY_SIZE(tpu41_resources),
-	.resource	= tpu41_resources,
-};
-
-static struct led_renesas_tpu_config led_renesas_tpu21_pdata = {
-	.name		= "V2515",
-	.pin_gpio_fn	= GPIO_FN_TPU2TO1,
-	.pin_gpio	= 197,
-	.channel_offset = 0x50,
-	.timer_bit = 1,
-	.max_brightness = 1000,
-};
-
-static struct resource tpu21_resources[] = {
-	[0] = {
-		.name	= "TPU21",
-		.start	= 0xe6620050,
-		.end	= 0xe6620075,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device leds_tpu21_device = {
-	.name = "leds-renesas-tpu",
-	.id = 21,
-	.dev = {
-		.platform_data  = &led_renesas_tpu21_pdata,
-	},
-	.num_resources	= ARRAY_SIZE(tpu21_resources),
-	.resource	= tpu21_resources,
-};
-
-static struct led_renesas_tpu_config led_renesas_tpu30_pdata = {
-	.name		= "KEYLED",
-	.pin_gpio_fn	= GPIO_FN_TPU3TO0,
-	.pin_gpio	= 163,
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.max_brightness = 1000,
-};
-
-static struct resource tpu30_resources[] = {
-	[0] = {
-		.name	= "TPU30",
-		.start	= 0xe6630010,
-		.end	= 0xe6630035,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device leds_tpu30_device = {
-	.name = "leds-renesas-tpu",
-	.id = 30,
-	.dev = {
-		.platform_data  = &led_renesas_tpu30_pdata,
-	},
-	.num_resources	= ARRAY_SIZE(tpu30_resources),
-	.resource	= tpu30_resources,
-};
-
-/* Fixed 1.8V regulator to be used by MMCIF */
-static struct regulator_consumer_supply fixed1v8_power_consumers[] =
-{
-	REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"),
-};
-
-/* MMCIF */
-static struct resource mmcif_resources[] = {
-	[0] = {
-		.name   = "MMCIF",
-		.start  = 0xe6bd0000,
-		.end    = 0xe6bd00ff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = gic_spi(140),
-		.flags  = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start  = gic_spi(141),
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct sh_mmcif_plat_data mmcif_info = {
-	.ocr            = MMC_VDD_165_195,
-	.caps           = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
-};
-
-static struct platform_device mmcif_device = {
-	.name           = "sh_mmcif",
-	.id             = 0,
-	.dev            = {
-		.platform_data          = &mmcif_info,
-	},
-	.num_resources  = ARRAY_SIZE(mmcif_resources),
-	.resource       = mmcif_resources,
-};
-
-/* Fixed 3.3V regulator to be used by SDHI0 and SDHI1 */
-static struct regulator_consumer_supply fixed3v3_power_consumers[] =
-{
-	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
-	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
-};
-
-/* SDHI0 */
-static struct sh_mobile_sdhi_info sdhi0_info = {
-	.tmio_caps      = MMC_CAP_SD_HIGHSPEED,
-	.tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
-};
-
-static struct resource sdhi0_resources[] = {
-	[0] = {
-		.name   = "SDHI0",
-		.start  = 0xee100000,
-		.end    = 0xee1000ff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = gic_spi(83),
-		.flags  = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start  = gic_spi(84),
-		.flags  = IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= gic_spi(85),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sdhi0_device = {
-	.name           = "sh_mobile_sdhi",
-	.id             = 0,
-	.num_resources  = ARRAY_SIZE(sdhi0_resources),
-	.resource       = sdhi0_resources,
-	.dev    = {
-		.platform_data  = &sdhi0_info,
-	},
-};
-
-/* SDHI1 */
-static struct sh_mobile_sdhi_info sdhi1_info = {
-	.tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
-	.tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
-};
-
-static struct resource sdhi1_resources[] = {
-	[0] = {
-		.name   = "SDHI1",
-		.start  = 0xee120000,
-		.end    = 0xee1200ff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = gic_spi(87),
-		.flags  = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start  = gic_spi(88),
-		.flags  = IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= gic_spi(89),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sdhi1_device = {
-	.name           = "sh_mobile_sdhi",
-	.id             = 1,
-	.num_resources  = ARRAY_SIZE(sdhi1_resources),
-	.resource       = sdhi1_resources,
-	.dev    = {
-		.platform_data  = &sdhi1_info,
-	},
-};
-
-static struct platform_device *kota2_devices[] __initdata = {
-	&eth_device,
-	&keysc_device,
-	&gpio_keys_device,
-	&gpio_leds_device,
-	&leds_tpu12_device,
-	&leds_tpu41_device,
-	&leds_tpu21_device,
-	&leds_tpu30_device,
-	&mmcif_device,
-	&sdhi0_device,
-	&sdhi1_device,
-};
-
-static unsigned long pin_pullup_conf[] = {
-	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
-};
-
-static const struct pinctrl_map kota2_pinctrl_map[] = {
-	/* KEYSC */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_in8", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out04", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out5", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out6_0", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out7_0", "keysc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				  "keysc_out8_0", "keysc"),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
-				      "keysc_in8", pin_pullup_conf),
-	/* MMCIF */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				  "mmc0_data8_0", "mmc0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				  "mmc0_ctrl_0", "mmc0"),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				    "PORT279", pin_pullup_conf),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
-				      "mmc0_data8_0", pin_pullup_conf),
-	/* SCIFA2 (UART2) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
-				  "scifa2_data_0", "scifa2"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
-				  "scifa2_ctrl_0", "scifa2"),
-	/* SCIFA4 (UART1) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
-				  "scifa4_data", "scifa4"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
-				  "scifa4_ctrl", "scifa4"),
-	/* SCIFB (BT) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.8", "pfc-sh73a0",
-				  "scifb_data_0", "scifb"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.8", "pfc-sh73a0",
-				  "scifb_clk_0", "scifb"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.8", "pfc-sh73a0",
-				  "scifb_ctrl_0", "scifb"),
-	/* SDHI0 (microSD) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				  "sdhi0_data4", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				  "sdhi0_ctrl", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				  "sdhi0_cd", "sdhi0"),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				      "sdhi0_data4", pin_pullup_conf),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				    "PORT256", pin_pullup_conf),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
-				    "PORT251", pin_pullup_conf),
-	/* SDHI1 (BCM4330) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				  "sdhi1_data4", "sdhi1"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				  "sdhi1_ctrl", "sdhi1"),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				      "sdhi1_data4", pin_pullup_conf),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
-				    "PORT263", pin_pullup_conf),
-	/* SMSC911X */
-	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
-				  "bsc_data_0_7", "bsc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
-				  "bsc_data_8_15", "bsc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
-				  "bsc_cs5_a", "bsc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
-				  "bsc_we0", "bsc"),
-};
-
-static void __init kota2_init(void)
-{
-	regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
-				     ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
-	regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
-				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
-	regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-	pinctrl_register_mappings(kota2_pinctrl_map,
-				  ARRAY_SIZE(kota2_pinctrl_map));
-	sh73a0_pinmux_init();
-
-	/* SMSC911X */
-	gpio_request_one(144, GPIOF_IN, NULL); /* PINTA2 */
-	gpio_request_one(145, GPIOF_OUT_INIT_HIGH, NULL); /* RESET */
-
-	/* MMCIF */
-	gpio_request_one(208, GPIOF_OUT_INIT_HIGH, NULL); /* Reset */
-
-#ifdef CONFIG_CACHE_L2X0
-	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
-	l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
-#endif
-	sh73a0_add_standard_devices();
-	platform_add_devices(kota2_devices, ARRAY_SIZE(kota2_devices));
-}
-
-MACHINE_START(KOTA2, "kota2")
-	.smp		= smp_ops(sh73a0_smp_ops),
-	.map_io		= sh73a0_map_io,
-	.init_early	= sh73a0_add_early_devices,
-	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= sh73a0_init_irq,
-	.init_machine	= kota2_init,
-	.init_late	= shmobile_init_late,
-	.init_time	= sh73a0_earlytimer_init,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9d-reference.c b/arch/arm/mach-shmobile/board-kzm9d-reference.c
new file mode 100644
index 0000000..8f8bb2f
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kzm9d-reference.c
@@ -0,0 +1,47 @@
+/*
+ * kzm9d board support - Reference DT implementation
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <mach/emev2.h>
+#include <mach/common.h>
+#include <asm/mach/arch.h>
+
+static void __init kzm9d_add_standard_devices(void)
+{
+	if (!IS_ENABLED(CONFIG_COMMON_CLK))
+		emev2_clock_init();
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *kzm9d_boards_compat_dt[] __initdata = {
+	"renesas,kzm9d-reference",
+	NULL,
+};
+
+DT_MACHINE_START(KZM9D_DT, "kzm9d")
+	.smp		= smp_ops(emev2_smp_ops),
+	.map_io		= emev2_map_io,
+	.init_early	= emev2_init_delay,
+	.init_machine	= kzm9d_add_standard_devices,
+	.init_late	= shmobile_init_late,
+	.dt_compat	= kzm9d_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
index 4368000..30c2cc6 100644
--- a/arch/arm/mach-shmobile/board-kzm9d.c
+++ b/arch/arm/mach-shmobile/board-kzm9d.c
@@ -85,9 +85,7 @@ static const char *kzm9d_boards_compat_dt[] __initdata = {
 DT_MACHINE_START(KZM9D_DT, "kzm9d")
 	.smp		= smp_ops(emev2_smp_ops),
 	.map_io		= emev2_map_io,
-	.init_early	= emev2_add_early_devices,
-	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= emev2_init_irq,
+	.init_early	= emev2_init_delay,
 	.init_machine	= kzm9d_add_standard_devices,
 	.init_late	= shmobile_init_late,
 	.dt_compat	= kzm9d_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c
index 44055fe..598e324 100644
--- a/arch/arm/mach-shmobile/board-kzm9g-reference.c
+++ b/arch/arm/mach-shmobile/board-kzm9g-reference.c
@@ -21,67 +21,19 @@
  */
 
 #include <linux/delay.h>
-#include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <linux/irqchip.h>
 #include <linux/input.h>
 #include <linux/of_platform.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf-generic.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-static unsigned long pin_pullup_conf[] = {
-	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
-};
-
-static const struct pinctrl_map kzm_pinctrl_map[] = {
-	PIN_MAP_MUX_GROUP_DEFAULT("e6826000.i2c", "pfc-sh73a0",
-				  "i2c3_1", "i2c3"),
-	/* MMCIF */
-	PIN_MAP_MUX_GROUP_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
-				  "mmc0_data8_0", "mmc0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
-				  "mmc0_ctrl_0", "mmc0"),
-	PIN_MAP_CONFIGS_PIN_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
-				    "PORT279", pin_pullup_conf),
-	PIN_MAP_CONFIGS_GROUP_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
-				      "mmc0_data8_0", pin_pullup_conf),
-	/* SCIFA4 */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
-				  "scifa4_data", "scifa4"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
-				  "scifa4_ctrl", "scifa4"),
-	/* SDHI0 */
-	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
-				  "sdhi0_data4", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
-				  "sdhi0_ctrl", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
-				  "sdhi0_cd", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
-				  "sdhi0_wp", "sdhi0"),
-	/* SDHI2 */
-	PIN_MAP_MUX_GROUP_DEFAULT("ee140000.sdhi", "pfc-sh73a0",
-				  "sdhi2_data4", "sdhi2"),
-	PIN_MAP_MUX_GROUP_DEFAULT("ee140000.sdhi", "pfc-sh73a0",
-				  "sdhi2_ctrl", "sdhi2"),
-};
-
 static void __init kzm_init(void)
 {
 	sh73a0_add_standard_devices_dt();
-	pinctrl_register_mappings(kzm_pinctrl_map, ARRAY_SIZE(kzm_pinctrl_map));
-	sh73a0_pinmux_init();
-
-	/* enable SD */
-	gpio_request_one(15, GPIOF_OUT_INIT_HIGH, NULL); /* power */
-
-	gpio_request_one(14, GPIOF_OUT_INIT_HIGH, NULL); /* power */
 
 #ifdef CONFIG_CACHE_L2X0
 	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
@@ -99,8 +51,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g-reference")
 	.map_io		= sh73a0_map_io,
 	.init_early	= sh73a0_init_delay,
 	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= irqchip_init,
 	.init_machine	= kzm_init,
-	.init_time	= shmobile_timer_init,
 	.dt_compat	= kzm9g_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 1068120..f199496 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -54,14 +54,14 @@
 /*
  * external GPIO
  */
-#define GPIO_PCF8575_BASE	(GPIO_NR)
-#define GPIO_PCF8575_PORT10	(GPIO_NR + 8)
-#define GPIO_PCF8575_PORT11	(GPIO_NR + 9)
-#define GPIO_PCF8575_PORT12	(GPIO_NR + 10)
-#define GPIO_PCF8575_PORT13	(GPIO_NR + 11)
-#define GPIO_PCF8575_PORT14	(GPIO_NR + 12)
-#define GPIO_PCF8575_PORT15	(GPIO_NR + 13)
-#define GPIO_PCF8575_PORT16	(GPIO_NR + 14)
+#define GPIO_PCF8575_BASE	(310)
+#define GPIO_PCF8575_PORT10	(GPIO_PCF8575_BASE + 8)
+#define GPIO_PCF8575_PORT11	(GPIO_PCF8575_BASE + 9)
+#define GPIO_PCF8575_PORT12	(GPIO_PCF8575_BASE + 10)
+#define GPIO_PCF8575_PORT13	(GPIO_PCF8575_BASE + 11)
+#define GPIO_PCF8575_PORT14	(GPIO_PCF8575_BASE + 12)
+#define GPIO_PCF8575_PORT15	(GPIO_PCF8575_BASE + 13)
+#define GPIO_PCF8575_PORT16	(GPIO_PCF8575_BASE + 14)
 
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
new file mode 100644
index 0000000..9c316a1
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -0,0 +1,45 @@
+/*
+ * Lager board support - Reference DT implementation
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Simon Horman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <mach/r8a7790.h>
+#include <asm/mach/arch.h>
+
+static void __init lager_add_standard_devices(void)
+{
+	/* clocks are setup late during boot in the case of DT */
+	r8a7790_clock_init();
+
+	r8a7790_add_dt_devices();
+        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *lager_boards_compat_dt[] __initdata = {
+	"renesas,lager-reference",
+	NULL,
+};
+
+DT_MACHINE_START(LAGER_DT, "lager")
+	.init_early	= r8a7790_init_delay,
+	.init_machine	= lager_add_standard_devices,
+	.init_time	= r8a7790_timer_init,
+	.dt_compat	= lager_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index d73e21d..4872939 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -22,13 +22,18 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
-#include <linux/irqchip.h>
 #include <linux/kernel.h>
 #include <linux/leds.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/sh_eth.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/r8a7790.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -59,7 +64,7 @@ static __initdata struct gpio_led_platform_data lager_leds_pdata = {
 #define GPIO_KEY(c, g, d, ...) \
 	{ .code = c, .gpio = g, .desc = d, .active_low = 1 }
 
-static __initdata struct gpio_keys_button gpio_buttons[] = {
+static struct gpio_keys_button gpio_buttons[] = {
 	GPIO_KEY(KEY_4,		RCAR_GP_PIN(1, 28),	"SW2-pin4"),
 	GPIO_KEY(KEY_3,		RCAR_GP_PIN(1, 26),	"SW2-pin3"),
 	GPIO_KEY(KEY_2,		RCAR_GP_PIN(1, 24),	"SW2-pin2"),
@@ -71,6 +76,36 @@ static __initdata struct gpio_keys_platform_data lager_keys_pdata = {
 	.nbuttons	= ARRAY_SIZE(gpio_buttons),
 };
 
+/* Fixed 3.3V regulator to be used by MMCIF */
+static struct regulator_consumer_supply fixed3v3_power_consumers[] =
+{
+	REGULATOR_SUPPLY("vmmc", "sh_mmcif.1"),
+};
+
+/* MMCIF */
+static struct sh_mmcif_plat_data mmcif1_pdata __initdata = {
+	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static struct resource mmcif1_resources[] __initdata = {
+	DEFINE_RES_MEM_NAMED(0xee220000, 0x80, "MMCIF1"),
+	DEFINE_RES_IRQ(gic_spi(170)),
+};
+
+/* Ether */
+static struct sh_eth_plat_data ether_pdata __initdata = {
+	.phy			= 0x1,
+	.edmac_endian		= EDMAC_LITTLE_ENDIAN,
+	.register_type		= SH_ETH_REG_FAST_RCAR,
+	.phy_interface		= PHY_INTERFACE_MODE_RMII,
+	.ether_link_active_low	= 1,
+};
+
+static struct resource ether_resources[] __initdata = {
+	DEFINE_RES_MEM(0xee700000, 0x400),
+	DEFINE_RES_IRQ(gic_spi(162)),
+};
+
 static const struct pinctrl_map lager_pinctrl_map[] = {
 	/* SCIF0 (CN19: DEBUG SERIAL0) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790",
@@ -78,6 +113,20 @@ static const struct pinctrl_map lager_pinctrl_map[] = {
 	/* SCIF1 (CN20: DEBUG SERIAL1) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7790",
 				  "scif1_data", "scif1"),
+	/* MMCIF1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790",
+				  "mmc1_data8", "mmc1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790",
+				  "mmc1_ctrl", "mmc1"),
+	/* Ether */
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790",
+				  "eth_link", "eth"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790",
+				  "eth_mdio", "eth"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790",
+				  "eth_rmii", "eth"),
+	PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790",
+				  "intc_irq0", "intc"),
 };
 
 static void __init lager_add_standard_devices(void)
@@ -95,6 +144,16 @@ static void __init lager_add_standard_devices(void)
 	platform_device_register_data(&platform_bus, "gpio-keys", -1,
 				      &lager_keys_pdata,
 				      sizeof(lager_keys_pdata));
+	regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
+				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+	platform_device_register_resndata(&platform_bus, "sh_mmcif", 1,
+					  mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
+					  &mmcif1_pdata, sizeof(mmcif1_pdata));
+
+	platform_device_register_resndata(&platform_bus, "r8a7790-ether", -1,
+					  ether_resources,
+					  ARRAY_SIZE(ether_resources),
+					  &ether_pdata, sizeof(ether_pdata));
 }
 
 static const char *lager_boards_compat_dt[] __initdata = {
@@ -103,7 +162,7 @@ static const char *lager_boards_compat_dt[] __initdata = {
 };
 
 DT_MACHINE_START(LAGER_DT, "lager")
-	.init_irq	= irqchip_init,
+	.init_early	= r8a7790_init_delay,
 	.init_time	= r8a7790_timer_init,
 	.init_machine	= lager_add_standard_devices,
 	.dt_compat	= lager_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 85f51a8..af06753 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -41,6 +41,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/gpio_backlight.h>
 #include <linux/pm_clock.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
@@ -49,7 +50,6 @@
 #include <linux/tca6416_keypad.h>
 #include <linux/usb/renesas_usbhs.h>
 #include <linux/dma-mapping.h>
-
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
@@ -346,7 +346,7 @@ static struct platform_device meram_device = {
 	},
 };
 
-/* LCDC */
+/* LCDC and backlight */
 static struct fb_videomode mackerel_lcdc_modes[] = {
 	{
 		.name		= "WVGA Panel",
@@ -362,13 +362,6 @@ static struct fb_videomode mackerel_lcdc_modes[] = {
 	},
 };
 
-static int mackerel_set_brightness(int brightness)
-{
-	gpio_set_value(31, brightness);
-
-	return 0;
-}
-
 static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
 	.icb[0] = {
 		.meram_size     = 0x40,
@@ -393,11 +386,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.width		= 152,
 			.height		= 91,
 		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = mackerel_set_brightness,
-		},
 		.meram_cfg = &lcd_meram_cfg,
 	}
 };
@@ -425,6 +413,20 @@ static struct platform_device lcdc_device = {
 	},
 };
 
+static struct gpio_backlight_platform_data gpio_backlight_data = {
+	.fbdev = &lcdc_device.dev,
+	.gpio = 31,
+	.def_value = 1,
+	.name = "backlight",
+};
+
+static struct platform_device gpio_backlight_device = {
+	.name = "gpio-backlight",
+	.dev = {
+		.platform_data = &gpio_backlight_data,
+	},
+};
+
 /* HDMI */
 static struct sh_mobile_hdmi_info hdmi_info = {
 	.flags		= HDMI_SND_SRC_SPDIF,
@@ -1231,6 +1233,7 @@ static struct platform_device *mackerel_devices[] __initdata = {
 	&nor_flash_device,
 	&smc911x_device,
 	&lcdc_device,
+	&gpio_backlight_device,
 	&usbhs0_device,
 	&usbhs1_device,
 	&leds_device,
@@ -1441,9 +1444,6 @@ static void __init mackerel_init(void)
 				  ARRAY_SIZE(mackerel_pinctrl_map));
 	sh7372_pinmux_init();
 
-	/* backlight, off by default */
-	gpio_request_one(31, GPIOF_OUT_INIT_LOW, NULL);
-
 	gpio_request_one(151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
 
 	/* USBHS0 */
diff --git a/arch/arm/mach-shmobile/board-marzen-reference.c b/arch/arm/mach-shmobile/board-marzen-reference.c
index 480d882..3f4250a 100644
--- a/arch/arm/mach-shmobile/board-marzen-reference.c
+++ b/arch/arm/mach-shmobile/board-marzen-reference.c
@@ -19,42 +19,14 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/pinctrl/machine.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 
-static const struct pinctrl_map marzen_pinctrl_map[] = {
-	/* SCIF2 (CN18: DEBUG0) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-r8a7779",
-				  "scif2_data_c", "scif2"),
-	/* SCIF4 (CN19: DEBUG1) */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-r8a7779",
-				  "scif4_data", "scif4"),
-	/* SDHI0 */
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
-				  "sdhi0_data4", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
-				  "sdhi0_ctrl", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
-				  "sdhi0_cd", "sdhi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
-				  "sdhi0_wp", "sdhi0"),
-	/* SMSC */
-	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
-				  "intc_irq1_b", "intc"),
-	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
-				  "lbsc_ex_cs0", "lbsc"),
-};
-
 static void __init marzen_init(void)
 {
-	pinctrl_register_mappings(marzen_pinctrl_map,
-				  ARRAY_SIZE(marzen_pinctrl_map));
-	r8a7779_pinmux_init();
-
 	r8a7779_add_standard_devices_dt();
 }
 
@@ -70,6 +42,5 @@ DT_MACHINE_START(MARZEN, "marzen")
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= r8a7779_init_irq_dt,
 	.init_machine	= marzen_init,
-	.init_time	= shmobile_timer_init,
 	.dt_compat	= marzen_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index a7d1010..3551b54 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -29,6 +29,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/usb-rcar-phy.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
@@ -37,7 +38,6 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
-#include <mach/hardware.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
@@ -57,7 +57,26 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
 };
 
-static struct rcar_phy_platform_data usb_phy_platform_data __initdata;
+/* USB PHY */
+static struct resource usb_phy_resources[] = {
+	[0] = {
+		.start		= 0xffe70800,
+		.end		= 0xffe70900 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct rcar_phy_platform_data usb_phy_platform_data;
+
+static struct platform_device usb_phy = {
+	.name		= "rcar_usb_phy",
+	.id		= -1,
+	.dev  = {
+		.platform_data = &usb_phy_platform_data,
+	},
+	.resource	= usb_phy_resources,
+	.num_resources	= ARRAY_SIZE(usb_phy_resources),
+};
 
 /* SMSC LAN89218 */
 static struct resource smsc911x_resources[] = {
@@ -184,6 +203,7 @@ static struct platform_device *marzen_devices[] __initdata = {
 	&thermal_device,
 	&hspi_device,
 	&leds_device,
+	&usb_phy,
 };
 
 static const struct pinctrl_map marzen_pinctrl_map[] = {
@@ -234,17 +254,21 @@ static void __init marzen_init(void)
 	r8a7779_init_irq_extpin(1); /* IRQ1 as individual interrupt */
 
 	r8a7779_add_standard_devices();
-	r8a7779_add_usb_phy_device(&usb_phy_platform_data);
 	platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 }
 
-MACHINE_START(MARZEN, "marzen")
+static const char *marzen_boards_compat_dt[] __initdata = {
+        "renesas,marzen",
+        NULL,
+};
+
+DT_MACHINE_START(MARZEN, "marzen")
 	.smp		= smp_ops(r8a7779_smp_ops),
 	.map_io		= r8a7779_map_io,
 	.init_early	= r8a7779_add_early_devices,
-	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= r8a7779_init_irq,
+	.init_irq	= r8a7779_init_irq_dt,
 	.init_machine	= marzen_init,
 	.init_late	= r8a7779_init_late,
+	.dt_compat	= marzen_boards_compat_dt,
 	.init_time	= r8a7779_earlytimer_init,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
index 4710f18..5ac13ba 100644
--- a/arch/arm/mach-shmobile/clock-emev2.c
+++ b/arch/arm/mach-shmobile/clock-emev2.c
@@ -40,7 +40,6 @@
 #define USIB2SCLKDIV 0x65c
 #define USIB3SCLKDIV 0x660
 #define STI_CLKSEL 0x688
-#define SMU_GENERAL_REG0 0x7c0
 
 /* not pretty, but hey */
 static void __iomem *smu_base;
@@ -51,11 +50,6 @@ static void emev2_smu_write(unsigned long value, int offs)
 	iowrite32(value, smu_base + offs);
 }
 
-void emev2_set_boot_vector(unsigned long value)
-{
-	emev2_smu_write(value, SMU_GENERAL_REG0);
-}
-
 static struct clk_mapping smu_mapping = {
 	.phys	= EMEV2_SMU_BASE,
 	.len	= PAGE_SIZE,
@@ -205,23 +199,11 @@ static struct clk_lookup lookups[] = {
 void __init emev2_clock_init(void)
 {
 	int k, ret = 0;
-	static int is_setup;
-
-	/* yuck, this is ugly as hell, but the non-smp case of clocks
-	 * code is now designed to rely on ioremap() instead of static
-	 * entity maps. in the case of smp we need access to the SMU
-	 * register earlier than ioremap() is actually working without
-	 * any static maps. to enable SMP in ugly but with dynamic
-	 * mappings we have to call emev2_clock_init() from different
-	 * places depending on UP and SMP...
-	 */
-	if (is_setup++)
-		return;
 
 	smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
 	BUG_ON(!smu_base);
 
-	/* setup STI timer to run on 37.768 kHz and deassert reset */
+	/* setup STI timer to run on 32.768 kHz and deassert reset */
 	emev2_smu_write(0, STI_CLKSEL);
 	emev2_smu_write(1, STI_RSTCTRL);
 
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
index 5f7fe62..8ea5ef6 100644
--- a/arch/arm/mach-shmobile/clock-r8a73a4.c
+++ b/arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -30,10 +30,12 @@
 
 #define SMSTPCR2 0xe6150138
 #define SMSTPCR3 0xe615013c
+#define SMSTPCR4 0xe6150140
 #define SMSTPCR5 0xe6150144
 
 #define FRQCRA		0xE6150000
 #define FRQCRB		0xE6150004
+#define FRQCRC		0xE61500E0
 #define VCLKCR1		0xE6150008
 #define VCLKCR2		0xE615000C
 #define VCLKCR3		0xE615001C
@@ -52,6 +54,7 @@
 #define HSICKCR		0xE615026C
 #define M4CKCR		0xE6150098
 #define PLLECR		0xE61500D0
+#define PLL0CR		0xE61500D8
 #define PLL1CR		0xE6150028
 #define PLL2CR		0xE615002C
 #define PLL2SCR		0xE61501F4
@@ -177,6 +180,7 @@ static struct sh_clk_ops pll_clk_ops = {
 		.mapping	= &cpg_mapping,		\
 	}
 
+PLL_CLOCK(pll0_clk,  &main_clk,      pll_parent_main,      1, 20, PLL0CR,  0);
 PLL_CLOCK(pll1_clk,  &main_clk,      pll_parent_main,       1, 7, PLL1CR,  1);
 PLL_CLOCK(pll2_clk,  &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2CR,  2);
 PLL_CLOCK(pll2s_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2SCR, 4);
@@ -184,6 +188,157 @@ PLL_CLOCK(pll2h_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2HCR, 5);
 
 SH_FIXED_RATIO_CLK(pll1_div2_clk,	pll1_clk,	div2);
 
+static atomic_t frqcr_lock;
+
+/* Several clocks need to access FRQCRB, have to lock */
+static bool frqcr_kick_check(struct clk *clk)
+{
+	return !(ioread32(CPG_MAP(FRQCRB)) & BIT(31));
+}
+
+static int frqcr_kick_do(struct clk *clk)
+{
+	int i;
+
+	/* set KICK bit in FRQCRB to update hardware setting, check success */
+	iowrite32(ioread32(CPG_MAP(FRQCRB)) | BIT(31), CPG_MAP(FRQCRB));
+	for (i = 1000; i; i--)
+		if (ioread32(CPG_MAP(FRQCRB)) & BIT(31))
+			cpu_relax();
+		else
+			return 0;
+
+	return -ETIMEDOUT;
+}
+
+static int zclk_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *frqcrc;
+	int ret;
+	unsigned long step, p_rate;
+	u32 val;
+
+	if (!clk->parent || !__clk_get(clk->parent))
+		return -ENODEV;
+
+	if (!atomic_inc_and_test(&frqcr_lock) || !frqcr_kick_check(clk)) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	/*
+	 * Users are supposed to first call clk_set_rate() only with
+	 * clk_round_rate() results. So, we don't fix wrong rates here, but
+	 * guard against them anyway
+	 */
+
+	p_rate = clk_get_rate(clk->parent);
+	if (rate == p_rate) {
+		val = 0;
+	} else {
+		step = DIV_ROUND_CLOSEST(p_rate, 32);
+
+		if (rate > p_rate || rate < step) {
+			ret = -EINVAL;
+			goto done;
+		}
+
+		val = 32 - rate / step;
+	}
+
+	frqcrc = clk->mapped_reg + (FRQCRC - (u32)clk->enable_reg);
+
+	iowrite32((ioread32(frqcrc) & ~(clk->div_mask << clk->enable_bit)) |
+		  (val << clk->enable_bit), frqcrc);
+
+	ret = frqcr_kick_do(clk);
+
+done:
+	atomic_dec(&frqcr_lock);
+	__clk_put(clk->parent);
+	return ret;
+}
+
+static long zclk_round_rate(struct clk *clk, unsigned long rate)
+{
+	/*
+	 * theoretical rate = parent rate * multiplier / 32,
+	 * where 1 <= multiplier <= 32. Therefore we should do
+	 * multiplier = rate * 32 / parent rate
+	 * rounded rate = parent rate * multiplier / 32.
+	 * However, multiplication before division won't fit in 32 bits, so
+	 * we sacrifice some precision by first dividing and then multiplying.
+	 * To find the nearest divisor we calculate both and pick up the best
+	 * one. This avoids 64-bit arithmetics.
+	 */
+	unsigned long step, mul_min, mul_max, rate_min, rate_max;
+
+	rate_max = clk_get_rate(clk->parent);
+
+	/* output freq <= parent */
+	if (rate >= rate_max)
+		return rate_max;
+
+	step = DIV_ROUND_CLOSEST(rate_max, 32);
+	/* output freq >= parent / 32 */
+	if (step >= rate)
+		return step;
+
+	mul_min = rate / step;
+	mul_max = DIV_ROUND_UP(rate, step);
+	rate_min = step * mul_min;
+	if (mul_max == mul_min)
+		return rate_min;
+
+	rate_max = step * mul_max;
+
+	if (rate_max - rate <  rate - rate_min)
+		return rate_max;
+
+	return rate_min;
+}
+
+static unsigned long zclk_recalc(struct clk *clk)
+{
+	void __iomem *frqcrc = FRQCRC - (u32)clk->enable_reg + clk->mapped_reg;
+	unsigned int max = clk->div_mask + 1;
+	unsigned long val = ((ioread32(frqcrc) >> clk->enable_bit) &
+			     clk->div_mask);
+
+	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), max) *
+		(max - val);
+}
+
+static struct sh_clk_ops zclk_ops = {
+	.recalc = zclk_recalc,
+	.set_rate = zclk_set_rate,
+	.round_rate = zclk_round_rate,
+};
+
+static struct clk z_clk = {
+	.parent = &pll0_clk,
+	.div_mask = 0x1f,
+	.enable_bit = 8,
+	/* We'll need to access FRQCRB and FRQCRC */
+	.enable_reg = (void __iomem *)FRQCRB,
+	.ops = &zclk_ops,
+};
+
+/*
+ * It seems only 1/2 divider is usable in manual mode. 1/2 / 2/3
+ * switching is only available in auto-DVFS mode
+ */
+SH_FIXED_RATIO_CLK(pll0_div2_clk,	pll0_clk,		div2);
+
+static struct clk z2_clk = {
+	.parent = &pll0_div2_clk,
+	.div_mask = 0x1f,
+	.enable_bit = 0,
+	/* We'll need to access FRQCRB and FRQCRC */
+	.enable_reg = (void __iomem *)FRQCRB,
+	.ops = &zclk_ops,
+};
+
 static struct clk *main_clks[] = {
 	&extalr_clk,
 	&extal1_clk,
@@ -195,22 +350,23 @@ static struct clk *main_clks[] = {
 	&main_div2_clk,
 	&fsiack_clk,
 	&fsibck_clk,
+	&pll0_clk,
 	&pll1_clk,
 	&pll1_div2_clk,
 	&pll2_clk,
 	&pll2s_clk,
 	&pll2h_clk,
+	&z_clk,
+	&pll0_div2_clk,
+	&z2_clk,
 };
 
 /* DIV4 */
 static void div4_kick(struct clk *clk)
 {
-	unsigned long value;
-
-	/* set KICK bit in FRQCRB to update hardware setting */
-	value = ioread32(CPG_MAP(FRQCRB));
-	value |= (1 << 31);
-	iowrite32(value, CPG_MAP(FRQCRB));
+	if (!WARN(!atomic_inc_and_test(&frqcr_lock), "FRQCR* lock broken!\n"))
+		frqcr_kick_do(clk);
+	atomic_dec(&frqcr_lock);
 }
 
 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10};
@@ -349,8 +505,10 @@ static struct clk div6_clks[DIV6_NR] = {
 /* MSTP */
 enum {
 	MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
-	MSTP315, MSTP314, MSTP313, MSTP312, MSTP305,
-	MSTP522,
+	MSTP329, MSTP323, MSTP318, MSTP317, MSTP316,
+	MSTP315, MSTP314, MSTP313, MSTP312, MSTP305, MSTP300,
+	MSTP411, MSTP410, MSTP409,
+	MSTP522, MSTP515,
 	MSTP_NR
 };
 
@@ -361,12 +519,22 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 7, 0), /* SCIFB1 */
 	[MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 16, 0), /* SCIFB2 */
 	[MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 17, 0), /* SCIFB3 */
+	[MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 0, 0), /* IIC2 */
 	[MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1],SMSTPCR3, 5, 0), /* MMCIF1 */
 	[MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI2],SMSTPCR3, 12, 0), /* SDHI2 */
 	[MSTP313] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI1],SMSTPCR3, 13, 0), /* SDHI1 */
 	[MSTP314] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI0],SMSTPCR3, 14, 0), /* SDHI0 */
 	[MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0],SMSTPCR3, 15, 0), /* MMCIF0 */
+	[MSTP316] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 16, 0), /* IIC6 */
+	[MSTP317] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 17, 0), /* IIC7 */
+	[MSTP318] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 18, 0), /* IIC0 */
+	[MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 23, 0), /* IIC1 */
+	[MSTP329] = SH_CLK_MSTP32(&extalr_clk, SMSTPCR3, 29, 0), /* CMT10 */
+	[MSTP409] = SH_CLK_MSTP32(&main_div2_clk,	SMSTPCR4, 9, 0), /* IIC5 */
+	[MSTP410] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR4, 10, 0), /* IIC4 */
+	[MSTP411] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR4, 11, 0), /* IIC3 */
 	[MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */
+	[MSTP515] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR5, 15, 0), /* IIC8 */
 };
 
 static struct clk_lookup lookups[] = {
@@ -386,6 +554,9 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("pll2s",			&pll2s_clk),
 	CLKDEV_CON_ID("pll2h",			&pll2h_clk),
 
+	/* CPU clock */
+	CLKDEV_DEV_ID("cpufreq-cpu0",		&z_clk),
+
 	/* DIV6 */
 	CLKDEV_CON_ID("zb",			&div6_clks[DIV6_ZB]),
 	CLKDEV_CON_ID("vck1",			&div6_clks[DIV6_VCK1]),
@@ -408,6 +579,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
+	CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
 	CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
 	CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
@@ -418,6 +590,15 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
 	CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
+	CLKDEV_DEV_ID("e6550000.i2c", &mstp_clks[MSTP316]),
+	CLKDEV_DEV_ID("e6560000.i2c", &mstp_clks[MSTP317]),
+	CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
+	CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
+	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
+	CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
+	CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
+	CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
+	CLKDEV_DEV_ID("e6570000.i2c", &mstp_clks[MSTP515]),
 
 	/* for DT */
 	CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
@@ -429,6 +610,8 @@ void __init r8a73a4_clock_init(void)
 	int k, ret = 0;
 	u32 ckscr;
 
+	atomic_set(&frqcr_lock, -1);
+
 	reg = ioremap_nocache(CKSCR, PAGE_SIZE);
 	BUG_ON(!reg);
 	ckscr = ioread32(reg);
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index de10fd7..c826bca 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -596,7 +596,8 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6bd0000.mmcif",         &mstp_clks[MSTP312]),
 	CLKDEV_DEV_ID("r8a7740-gether",		&mstp_clks[MSTP309]),
 	CLKDEV_DEV_ID("e9a00000.sh-eth",	&mstp_clks[MSTP309]),
-	CLKDEV_DEV_ID("renesas_tpu_pwm",	&mstp_clks[MSTP304]),
+	CLKDEV_DEV_ID("renesas-tpu-pwm",	&mstp_clks[MSTP304]),
+	CLKDEV_DEV_ID("e6600000.pwm",		&mstp_clks[MSTP304]),
 
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2",	&mstp_clks[MSTP415]),
 	CLKDEV_DEV_ID("e6870000.sdhi",          &mstp_clks[MSTP415]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index 5d71313..fc36d3d 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -24,6 +24,7 @@
 #include <linux/clkdev.h>
 #include <mach/clock.h>
 #include <mach/common.h>
+#include <mach/r8a7790.h>
 
 /*
  *   MD		EXTAL		PLL0	PLL1	PLL3
@@ -42,16 +43,16 @@
  *	see "p1 / 2" on R8A7790_CLOCK_ROOT() below
  */
 
-#define MD(nr)	(1 << nr)
-
 #define CPG_BASE 0xe6150000
 #define CPG_LEN 0x1000
 
+#define SMSTPCR1 0xe6150134
 #define SMSTPCR2 0xe6150138
 #define SMSTPCR3 0xe615013c
+#define SMSTPCR5 0xe6150144
 #define SMSTPCR7 0xe615014c
+#define SMSTPCR8 0xe6150990
 
-#define MODEMR		0xE6160060
 #define SDCKCR		0xE6150074
 #define SD2CKCR		0xE6150078
 #define SD3CKCR		0xE615007C
@@ -180,16 +181,23 @@ static struct clk div6_clks[DIV6_NR] = {
 
 /* MSTP */
 enum {
+	MSTP813,
 	MSTP721, MSTP720,
 	MSTP717, MSTP716,
+	MSTP522,
 	MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
 	MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202,
+	MSTP124,
 	MSTP_NR
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */
 	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
 	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
+	[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
+	[MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
+	[MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */
 	[MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, 0), /* MMC0 */
 	[MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_SD0], SMSTPCR3, 14, 0), /* SDHI0 */
 	[MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_SD1], SMSTPCR3, 13, 0), /* SDHI1 */
@@ -203,8 +211,7 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
 	[MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
 	[MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
-	[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
-	[MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
+	[MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */
 };
 
 static struct clk_lookup lookups[] = {
@@ -254,6 +261,8 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
 	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]),
 	CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]),
+	CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]),
+	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
 	CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
 	CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
@@ -266,6 +275,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]),
 	CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
 	CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
+	CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
 };
 
 #define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31)		\
@@ -280,14 +290,9 @@ static struct clk_lookup lookups[] = {
 
 void __init r8a7790_clock_init(void)
 {
-	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
-	u32 mode;
+	u32 mode = r8a7790_read_mode_pins();
 	int k, ret = 0;
 
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-
 	switch (mode & (MD(14) | MD(13))) {
 	case 0:
 		R8A7790_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index d9fd033..1942eae 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -555,7 +555,7 @@ enum { MSTP001,
 	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
 	MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP322,
 	MSTP314, MSTP313, MSTP312, MSTP311,
-	MSTP303, MSTP302, MSTP301, MSTP300,
+	MSTP304, MSTP303, MSTP302, MSTP301, MSTP300,
 	MSTP411, MSTP410, MSTP403,
 	MSTP_NR };
 
@@ -593,6 +593,7 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
 	[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
 	[MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */
+	[MSTP304] = MSTP(&main_div2_clk, SMSTPCR3, 4, 0), /* TPU0 */
 	[MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */
 	[MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */
 	[MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */
@@ -669,10 +670,11 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
 	CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP311]), /* SDHI2 */
-	CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
-	CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
-	CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
-	CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */
+	CLKDEV_DEV_ID("renesas-tpu-pwm.0", &mstp_clks[MSTP304]), /* TPU0 */
+	CLKDEV_DEV_ID("renesas-tpu-pwm.1", &mstp_clks[MSTP303]), /* TPU1 */
+	CLKDEV_DEV_ID("renesas-tpu-pwm.2", &mstp_clks[MSTP302]), /* TPU2 */
+	CLKDEV_DEV_ID("renesas-tpu-pwm.3", &mstp_clks[MSTP301]), /* TPU3 */
+	CLKDEV_DEV_ID("renesas-tpu-pwm.4", &mstp_clks[MSTP300]), /* TPU4 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
 	CLKDEV_DEV_ID("e6826000.i2c", &mstp_clks[MSTP411]), /* I2C3 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S
index bfd9200..f45dde7 100644
--- a/arch/arm/mach-shmobile/headsmp-scu.S
+++ b/arch/arm/mach-shmobile/headsmp-scu.S
@@ -37,13 +37,15 @@ ENTRY(shmobile_boot_scu)
 	lsl	r1, r1, #3		@ we will shift by cpu_id * 8 bits
 	ldr	r2, [r0, #8]		@ SCU Power Status Register
 	mov	r3, #3
-	bic	r2, r2, r3, lsl r1	@ Clear bits of our CPU (Run Mode)
+	lsl	r3, r3, r1
+	bic	r2, r2, r3		@ Clear bits of our CPU (Run Mode)
 	str	r2, [r0, #8]		@ write back
 
 	b	shmobile_invalidate_start
 ENDPROC(shmobile_boot_scu)
 
 	.text
+	.align	2
 	.globl	shmobile_scu_base
 shmobile_scu_base:
 	.space	4
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index a9d2124..f93751c 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -24,15 +24,68 @@ ENDPROC(shmobile_invalidate_start)
  * This will be mapped at address 0 by SBAR register.
  * We need _long_ jump to the physical address.
  */
+	.arm
 	.align  12
 ENTRY(shmobile_boot_vector)
 	ldr     r0, 2f
-	ldr     pc, 1f
+	ldr     r1, 1f
+	bx	r1
+
 ENDPROC(shmobile_boot_vector)
 
+	.align	2
 	.globl	shmobile_boot_fn
 shmobile_boot_fn:
 1:	.space	4
 	.globl	shmobile_boot_arg
 shmobile_boot_arg:
 2:	.space	4
+
+/*
+ * Per-CPU SMP boot function/argument selection code based on MPIDR
+ */
+
+ENTRY(shmobile_smp_boot)
+						@ r0 = MPIDR_HWID_BITMASK
+	mrc	p15, 0, r1, c0, c0, 5		@ r1 = MPIDR
+	and	r0, r1, r0			@ r0 = cpu_logical_map() value
+	mov	r1, #0				@ r1 = CPU index
+	adr	r5, 1f				@ array of per-cpu mpidr values
+	adr	r6, 2f				@ array of per-cpu functions
+	adr	r7, 3f				@ array of per-cpu arguments
+
+shmobile_smp_boot_find_mpidr:
+	ldr	r8, [r5, r1, lsl #2]
+	cmp	r8, r0
+	bne	shmobile_smp_boot_next
+
+	ldr	r9, [r6, r1, lsl #2]
+	cmp	r9, #0
+	bne	shmobile_smp_boot_found
+
+shmobile_smp_boot_next:
+	add	r1, r1, #1
+	cmp	r1, #CONFIG_NR_CPUS
+	blo	shmobile_smp_boot_find_mpidr
+
+	b	shmobile_smp_sleep
+
+shmobile_smp_boot_found:
+	ldr	r0, [r7, r1, lsl #2]
+	mov	pc, r9
+ENDPROC(shmobile_smp_boot)
+
+ENTRY(shmobile_smp_sleep)
+	wfi
+	b	shmobile_smp_boot
+ENDPROC(shmobile_smp_sleep)
+
+	.globl	shmobile_smp_mpidr
+shmobile_smp_mpidr:
+1:	.space	CONFIG_NR_CPUS * 4
+	.globl	shmobile_smp_fn
+shmobile_smp_fn:
+2:	.space	CONFIG_NR_CPUS * 4
+	.globl	shmobile_smp_arg
+shmobile_smp_arg:
+3:	.space	CONFIG_NR_CPUS * 4
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index e818f02..7b93868 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -2,7 +2,6 @@
 #define __ARCH_MACH_COMMON_H
 
 extern void shmobile_earlytimer_init(void);
-extern void shmobile_timer_init(void);
 extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 			 unsigned int mult, unsigned int div);
 struct twd_local_timer;
@@ -10,7 +9,16 @@ extern void shmobile_setup_console(void);
 extern void shmobile_boot_vector(void);
 extern unsigned long shmobile_boot_fn;
 extern unsigned long shmobile_boot_arg;
+extern void shmobile_smp_boot(void);
+extern void shmobile_smp_sleep(void);
+extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
+			      unsigned long arg);
 extern void shmobile_boot_scu(void);
+extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
+extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
+					   struct task_struct *idle);
+extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
diff --git a/arch/arm/mach-shmobile/include/mach/dma.h b/arch/arm/mach-shmobile/include/mach/dma.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-shmobile/include/mach/dma.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
index ac37517..c2eb756 100644
--- a/arch/arm/mach-shmobile/include/mach/emev2.h
+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
@@ -2,11 +2,9 @@
 #define __ASM_EMEV2_H__
 
 extern void emev2_map_io(void);
-extern void emev2_init_irq(void);
-extern void emev2_add_early_devices(void);
+extern void emev2_init_delay(void);
 extern void emev2_add_standard_devices(void);
 extern void emev2_clock_init(void);
-extern void emev2_set_boot_vector(unsigned long value);
 
 #define EMEV2_GPIO_BASE 200
 #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
diff --git a/arch/arm/mach-shmobile/include/mach/hardware.h b/arch/arm/mach-shmobile/include/mach/hardware.h
deleted file mode 100644
index 99264a5..0000000
--- a/arch/arm/mach-shmobile/include/mach/hardware.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASM_MACH_HARDWARE_H
-#define __ASM_MACH_HARDWARE_H
-
-#endif /* __ASM_MACH_HARDWARE_H */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
index f043103..f3a9b70 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a73a4.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
@@ -2,7 +2,9 @@
 #define __ASM_R8A73A4_H__
 
 void r8a73a4_add_standard_devices(void);
+void r8a73a4_add_dt_devices(void);
 void r8a73a4_clock_init(void);
 void r8a73a4_pinmux_init(void);
+void r8a73a4_init_delay(void);
 
 #endif /* __ASM_R8A73A4_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
index b34d19b..d07932f 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
@@ -42,11 +42,12 @@ enum {
 	SHDMA_SLAVE_FSIB_TX,
 	SHDMA_SLAVE_USBHS_TX,
 	SHDMA_SLAVE_USBHS_RX,
+	SHDMA_SLAVE_MMCIF_TX,
+	SHDMA_SLAVE_MMCIF_RX,
 };
 
 extern void r8a7740_meram_workaround(void);
 extern void r8a7740_init_delay(void);
-extern void r8a7740_init_irq(void);
 extern void r8a7740_init_irq_of(void);
 extern void r8a7740_map_io(void);
 extern void r8a7740_add_early_devices(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h
index 851d027..41fd6da 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7778.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h
@@ -18,26 +18,18 @@
 #ifndef __ASM_R8A7778_H__
 #define __ASM_R8A7778_H__
 
-#include <linux/mmc/sh_mmcif.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/sh_eth.h>
-#include <linux/platform_data/usb-rcar-phy.h>
 
 extern void r8a7778_add_standard_devices(void);
 extern void r8a7778_add_standard_devices_dt(void);
 extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata);
-extern void r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
-extern void r8a7778_add_i2c_device(int id);
-extern void r8a7778_add_hspi_device(int id);
-extern void r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info);
+extern void r8a7778_add_dt_devices(void);
 
 extern void r8a7778_init_late(void);
 extern void r8a7778_init_delay(void);
-extern void r8a7778_init_irq(void);
 extern void r8a7778_init_irq_dt(void);
 extern void r8a7778_clock_init(void);
 extern void r8a7778_init_irq_extpin(int irlm);
 extern void r8a7778_pinmux_init(void);
-extern void r8a7778_sdhi_init(int id, struct sh_mobile_sdhi_info *info);
 
 #endif /* __ASM_R8A7778_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index fc47073..f08d6ec 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -4,7 +4,6 @@
 #include <linux/sh_clk.h>
 #include <linux/pm_domain.h>
 #include <linux/sh_eth.h>
-#include <linux/platform_data/usb-rcar-phy.h>
 
 struct platform_device;
 
@@ -25,7 +24,6 @@ static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d)
 }
 
 extern void r8a7779_init_delay(void);
-extern void r8a7779_init_irq(void);
 extern void r8a7779_init_irq_extpin(int irlm);
 extern void r8a7779_init_irq_dt(void);
 extern void r8a7779_map_io(void);
@@ -34,7 +32,6 @@ extern void r8a7779_add_early_devices(void);
 extern void r8a7779_add_standard_devices(void);
 extern void r8a7779_add_standard_devices_dt(void);
 extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata);
-extern void r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
 extern void r8a7779_init_late(void);
 extern void r8a7779_clock_init(void);
 extern void r8a7779_pinmux_init(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 2e919e6..788d559 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -2,8 +2,13 @@
 #define __ASM_R8A7790_H__
 
 void r8a7790_add_standard_devices(void);
+void r8a7790_add_dt_devices(void);
 void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
+void r8a7790_init_delay(void);
 void r8a7790_timer_init(void);
 
+#define MD(nr) BIT(nr)
+u32 r8a7790_read_mode_pins(void);
+
 #endif /* __ASM_R8A7790_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
index eb7a432..359b582 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -1,379 +1,6 @@
 #ifndef __ASM_SH73A0_H__
 #define __ASM_SH73A0_H__
 
-/* Pin Function Controller:
- * GPIO_FN_xx - GPIO used to select pin function and MSEL switch
- * GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
- */
-enum {
-	/* Hardware manual Table 25-1 (GPIO) */
-	GPIO_PORT0, GPIO_PORT1, GPIO_PORT2, GPIO_PORT3, GPIO_PORT4,
-	GPIO_PORT5, GPIO_PORT6, GPIO_PORT7, GPIO_PORT8, GPIO_PORT9,
-
-	GPIO_PORT10, GPIO_PORT11, GPIO_PORT12, GPIO_PORT13, GPIO_PORT14,
-	GPIO_PORT15, GPIO_PORT16, GPIO_PORT17, GPIO_PORT18, GPIO_PORT19,
-
-	GPIO_PORT20, GPIO_PORT21, GPIO_PORT22, GPIO_PORT23, GPIO_PORT24,
-	GPIO_PORT25, GPIO_PORT26, GPIO_PORT27, GPIO_PORT28, GPIO_PORT29,
-
-	GPIO_PORT30, GPIO_PORT31, GPIO_PORT32, GPIO_PORT33, GPIO_PORT34,
-	GPIO_PORT35, GPIO_PORT36, GPIO_PORT37, GPIO_PORT38, GPIO_PORT39,
-
-	GPIO_PORT40, GPIO_PORT41, GPIO_PORT42, GPIO_PORT43, GPIO_PORT44,
-	GPIO_PORT45, GPIO_PORT46, GPIO_PORT47, GPIO_PORT48, GPIO_PORT49,
-
-	GPIO_PORT50, GPIO_PORT51, GPIO_PORT52, GPIO_PORT53, GPIO_PORT54,
-	GPIO_PORT55, GPIO_PORT56, GPIO_PORT57, GPIO_PORT58, GPIO_PORT59,
-
-	GPIO_PORT60, GPIO_PORT61, GPIO_PORT62, GPIO_PORT63, GPIO_PORT64,
-	GPIO_PORT65, GPIO_PORT66, GPIO_PORT67, GPIO_PORT68, GPIO_PORT69,
-
-	GPIO_PORT70, GPIO_PORT71, GPIO_PORT72, GPIO_PORT73, GPIO_PORT74,
-	GPIO_PORT75, GPIO_PORT76, GPIO_PORT77, GPIO_PORT78, GPIO_PORT79,
-
-	GPIO_PORT80, GPIO_PORT81, GPIO_PORT82, GPIO_PORT83, GPIO_PORT84,
-	GPIO_PORT85, GPIO_PORT86, GPIO_PORT87, GPIO_PORT88, GPIO_PORT89,
-
-	GPIO_PORT90, GPIO_PORT91, GPIO_PORT92, GPIO_PORT93, GPIO_PORT94,
-	GPIO_PORT95, GPIO_PORT96, GPIO_PORT97, GPIO_PORT98, GPIO_PORT99,
-
-	GPIO_PORT100, GPIO_PORT101, GPIO_PORT102, GPIO_PORT103, GPIO_PORT104,
-	GPIO_PORT105, GPIO_PORT106, GPIO_PORT107, GPIO_PORT108, GPIO_PORT109,
-
-	GPIO_PORT110, GPIO_PORT111, GPIO_PORT112, GPIO_PORT113, GPIO_PORT114,
-	GPIO_PORT115, GPIO_PORT116, GPIO_PORT117, GPIO_PORT118,
-
-	GPIO_PORT128, GPIO_PORT129,
-
-	GPIO_PORT130, GPIO_PORT131, GPIO_PORT132, GPIO_PORT133, GPIO_PORT134,
-	GPIO_PORT135, GPIO_PORT136, GPIO_PORT137, GPIO_PORT138, GPIO_PORT139,
-
-	GPIO_PORT140, GPIO_PORT141, GPIO_PORT142, GPIO_PORT143, GPIO_PORT144,
-	GPIO_PORT145, GPIO_PORT146, GPIO_PORT147, GPIO_PORT148, GPIO_PORT149,
-
-	GPIO_PORT150, GPIO_PORT151, GPIO_PORT152, GPIO_PORT153, GPIO_PORT154,
-	GPIO_PORT155, GPIO_PORT156, GPIO_PORT157, GPIO_PORT158, GPIO_PORT159,
-
-	GPIO_PORT160, GPIO_PORT161, GPIO_PORT162, GPIO_PORT163, GPIO_PORT164,
-
-	GPIO_PORT192, GPIO_PORT193, GPIO_PORT194,
-	GPIO_PORT195, GPIO_PORT196, GPIO_PORT197, GPIO_PORT198, GPIO_PORT199,
-
-	GPIO_PORT200, GPIO_PORT201, GPIO_PORT202, GPIO_PORT203, GPIO_PORT204,
-	GPIO_PORT205, GPIO_PORT206, GPIO_PORT207, GPIO_PORT208, GPIO_PORT209,
-
-	GPIO_PORT210, GPIO_PORT211, GPIO_PORT212, GPIO_PORT213, GPIO_PORT214,
-	GPIO_PORT215, GPIO_PORT216, GPIO_PORT217, GPIO_PORT218, GPIO_PORT219,
-
-	GPIO_PORT220, GPIO_PORT221, GPIO_PORT222, GPIO_PORT223, GPIO_PORT224,
-	GPIO_PORT225, GPIO_PORT226, GPIO_PORT227, GPIO_PORT228, GPIO_PORT229,
-
-	GPIO_PORT230, GPIO_PORT231, GPIO_PORT232, GPIO_PORT233, GPIO_PORT234,
-	GPIO_PORT235, GPIO_PORT236, GPIO_PORT237, GPIO_PORT238, GPIO_PORT239,
-
-	GPIO_PORT240, GPIO_PORT241, GPIO_PORT242, GPIO_PORT243, GPIO_PORT244,
-	GPIO_PORT245, GPIO_PORT246, GPIO_PORT247, GPIO_PORT248, GPIO_PORT249,
-
-	GPIO_PORT250, GPIO_PORT251, GPIO_PORT252, GPIO_PORT253, GPIO_PORT254,
-	GPIO_PORT255, GPIO_PORT256, GPIO_PORT257, GPIO_PORT258, GPIO_PORT259,
-
-	GPIO_PORT260, GPIO_PORT261, GPIO_PORT262, GPIO_PORT263, GPIO_PORT264,
-	GPIO_PORT265, GPIO_PORT266, GPIO_PORT267, GPIO_PORT268, GPIO_PORT269,
-
-	GPIO_PORT270, GPIO_PORT271, GPIO_PORT272, GPIO_PORT273, GPIO_PORT274,
-	GPIO_PORT275, GPIO_PORT276, GPIO_PORT277, GPIO_PORT278, GPIO_PORT279,
-
-	GPIO_PORT280, GPIO_PORT281, GPIO_PORT282,
-
-	GPIO_PORT288, GPIO_PORT289,
-
-	GPIO_PORT290, GPIO_PORT291, GPIO_PORT292, GPIO_PORT293, GPIO_PORT294,
-	GPIO_PORT295, GPIO_PORT296, GPIO_PORT297, GPIO_PORT298, GPIO_PORT299,
-
-	GPIO_PORT300, GPIO_PORT301, GPIO_PORT302, GPIO_PORT303, GPIO_PORT304,
-	GPIO_PORT305, GPIO_PORT306, GPIO_PORT307, GPIO_PORT308, GPIO_PORT309,
-
-	/* Table 25-1 (Function 0-7) */
-	GPIO_FN_GPI0 = 310,
-	GPIO_FN_GPI1,
-	GPIO_FN_GPI2,
-	GPIO_FN_GPI3,
-	GPIO_FN_GPI4,
-	GPIO_FN_GPI5,
-	GPIO_FN_GPI6,
-	GPIO_FN_GPI7,
-	GPIO_FN_GPO7, GPIO_FN_MFG0_OUT2,
-	GPIO_FN_GPO6, GPIO_FN_MFG1_OUT2,
-	GPIO_FN_GPO5,
-	GPIO_FN_PORT16_VIO_CKOR,
-	GPIO_FN_PORT19_VIO_CKO2,
-	GPIO_FN_GPO0,
-	GPIO_FN_GPO1,
-	GPIO_FN_GPO2, GPIO_FN_STATUS0,
-	GPIO_FN_GPO3, GPIO_FN_STATUS1,
-	GPIO_FN_GPO4, GPIO_FN_STATUS2,
-	GPIO_FN_VINT,
-	GPIO_FN_TCKON,
-	GPIO_FN_XDVFS1,
-	GPIO_FN_MFG0_OUT1, GPIO_FN_PORT27_IROUT,
-	GPIO_FN_XDVFS2,
-	GPIO_FN_PORT28_TPU1TO1,
-	GPIO_FN_SIM_RST, GPIO_FN_PORT29_TPU1TO1,
-	GPIO_FN_SIM_CLK, GPIO_FN_PORT30_VIO_CKOR,
-	GPIO_FN_SIM_D, GPIO_FN_PORT31_IROUT,
-	GPIO_FN_XWUP,
-	GPIO_FN_VACK,
-	GPIO_FN_XTAL1L,
-	GPIO_FN_PORT49_IROUT,
-	GPIO_FN_BBIF2_TSYNC2, GPIO_FN_TPU2TO2,
-
-	GPIO_FN_BBIF2_TSCK2, GPIO_FN_TPU2TO3,
-	GPIO_FN_BBIF2_TXD2,
-	GPIO_FN_TPU3TO3,
-	GPIO_FN_TPU3TO2,
-	GPIO_FN_TPU0TO0,
-	GPIO_FN_A0, GPIO_FN_BS_,
-	GPIO_FN_A12, GPIO_FN_TPU4TO2,
-	GPIO_FN_A13, GPIO_FN_TPU0TO1,
-	GPIO_FN_A14,
-	GPIO_FN_A15,
-	GPIO_FN_A16, GPIO_FN_MSIOF0_SS1,
-	GPIO_FN_A17, GPIO_FN_MSIOF0_TSYNC,
-	GPIO_FN_A18, GPIO_FN_MSIOF0_TSCK,
-	GPIO_FN_A19, GPIO_FN_MSIOF0_TXD,
-	GPIO_FN_A20, GPIO_FN_MSIOF0_RSCK,
-	GPIO_FN_A21, GPIO_FN_MSIOF0_RSYNC,
-	GPIO_FN_A22, GPIO_FN_MSIOF0_MCK0,
-	GPIO_FN_A23, GPIO_FN_MSIOF0_MCK1,
-	GPIO_FN_A24, GPIO_FN_MSIOF0_RXD,
-	GPIO_FN_A25, GPIO_FN_MSIOF0_SS2,
-	GPIO_FN_A26,
-	GPIO_FN_FCE1_,
-	GPIO_FN_DACK0,
-	GPIO_FN_FCE0_,
-	GPIO_FN_WAIT_, GPIO_FN_DREQ0,
-	GPIO_FN_FRB,
-	GPIO_FN_CKO,
-	GPIO_FN_NBRSTOUT_,
-	GPIO_FN_NBRST_,
-	GPIO_FN_BBIF2_TXD,
-	GPIO_FN_BBIF2_RXD,
-	GPIO_FN_BBIF2_SYNC,
-	GPIO_FN_BBIF2_SCK,
-	GPIO_FN_MFG3_IN2,
-	GPIO_FN_MFG3_IN1,
-	GPIO_FN_BBIF1_SS2, GPIO_FN_MFG3_OUT1,
-	GPIO_FN_HSI_RX_DATA, GPIO_FN_BBIF1_RXD,
-	GPIO_FN_HSI_TX_WAKE, GPIO_FN_BBIF1_TSCK,
-	GPIO_FN_HSI_TX_DATA, GPIO_FN_BBIF1_TSYNC,
-	GPIO_FN_HSI_TX_READY, GPIO_FN_BBIF1_TXD,
-	GPIO_FN_HSI_RX_READY, GPIO_FN_BBIF1_RSCK,
-	GPIO_FN_HSI_RX_WAKE, GPIO_FN_BBIF1_RSYNC,
-	GPIO_FN_HSI_RX_FLAG, GPIO_FN_BBIF1_SS1, GPIO_FN_BBIF1_FLOW,
-	GPIO_FN_HSI_TX_FLAG,
-	GPIO_FN_VIO_VD, GPIO_FN_VIO2_VD,
-
-	GPIO_FN_VIO_HD,
-	GPIO_FN_VIO2_HD,
-	GPIO_FN_VIO_D0, GPIO_FN_PORT130_MSIOF2_RXD,
-	GPIO_FN_VIO_D1, GPIO_FN_PORT131_MSIOF2_SS1,
-	GPIO_FN_VIO_D2, GPIO_FN_PORT132_MSIOF2_SS2,
-	GPIO_FN_VIO_D3, GPIO_FN_MSIOF2_TSYNC,
-	GPIO_FN_VIO_D4, GPIO_FN_MSIOF2_TXD,
-	GPIO_FN_VIO_D5, GPIO_FN_MSIOF2_TSCK,
-	GPIO_FN_VIO_D6,
-	GPIO_FN_VIO_D7,
-	GPIO_FN_VIO_D8, GPIO_FN_VIO2_D0,
-	GPIO_FN_VIO_D9, GPIO_FN_VIO2_D1,
-	GPIO_FN_VIO_D10, GPIO_FN_TPU0TO2, GPIO_FN_VIO2_D2,
-	GPIO_FN_VIO_D11, GPIO_FN_TPU0TO3, GPIO_FN_VIO2_D3,
-	GPIO_FN_VIO_D12, GPIO_FN_VIO2_D4,
-	GPIO_FN_VIO_D13,
-	GPIO_FN_VIO2_D5,
-	GPIO_FN_VIO_D14, GPIO_FN_VIO2_D6,
-	GPIO_FN_VIO_D15, GPIO_FN_TPU1TO3,
-	GPIO_FN_VIO2_D7,
-	GPIO_FN_VIO_CLK,
-	GPIO_FN_VIO2_CLK,
-	GPIO_FN_VIO_FIELD, GPIO_FN_VIO2_FIELD,
-	GPIO_FN_VIO_CKO,
-	GPIO_FN_A27, GPIO_FN_MFG0_IN1,
-	GPIO_FN_MFG0_IN2,
-	GPIO_FN_TS_SPSYNC3, GPIO_FN_MSIOF2_RSCK,
-	GPIO_FN_TS_SDAT3, GPIO_FN_MSIOF2_RSYNC,
-	GPIO_FN_TPU1TO2, GPIO_FN_TS_SDEN3, GPIO_FN_PORT153_MSIOF2_SS1,
-	GPIO_FN_MSIOF2_MCK0,
-	GPIO_FN_MSIOF2_MCK1,
-	GPIO_FN_PORT156_MSIOF2_SS2,
-	GPIO_FN_PORT157_MSIOF2_RXD,
-	GPIO_FN_DINT_, GPIO_FN_TS_SCK3,
-	GPIO_FN_NMI,
-	GPIO_FN_TPU3TO0,
-	GPIO_FN_BBIF2_TSYNC1,
-	GPIO_FN_BBIF2_TSCK1,
-	GPIO_FN_BBIF2_TXD1,
-	GPIO_FN_MFG2_OUT2,
-	GPIO_FN_TPU2TO1,
-	GPIO_FN_TPU4TO1, GPIO_FN_MFG4_OUT2,
-	GPIO_FN_D16,
-	GPIO_FN_D17,
-	GPIO_FN_D18,
-	GPIO_FN_D19,
-	GPIO_FN_D20,
-	GPIO_FN_D21,
-	GPIO_FN_D22,
-	GPIO_FN_PORT207_MSIOF0L_SS1, GPIO_FN_D23,
-	GPIO_FN_PORT208_MSIOF0L_SS2, GPIO_FN_D24,
-	GPIO_FN_D25,
-	GPIO_FN_DREQ2, GPIO_FN_PORT210_MSIOF0L_SS1, GPIO_FN_D26,
-	GPIO_FN_PORT211_MSIOF0L_SS2, GPIO_FN_D27,
-	GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0, GPIO_FN_D28,
-	GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1, GPIO_FN_D29,
-	GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_RSCK, GPIO_FN_D30,
-	GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_RSYNC, GPIO_FN_D31,
-	GPIO_FN_DACK2,
-	GPIO_FN_MSIOF0L_TSYNC, GPIO_FN_VIO2_FIELD3,
-	GPIO_FN_DACK3,
-	GPIO_FN_PORT218_VIO_CKOR,
-	GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_TSCK, GPIO_FN_VIO2_CLK3, \
-	GPIO_FN_DREQ1,
-	GPIO_FN_PWEN, GPIO_FN_MSIOF0L_RXD, GPIO_FN_VIO2_HD3, \
-	GPIO_FN_DACK1, GPIO_FN_OVCN,
-	GPIO_FN_MSIOF0L_TXD, GPIO_FN_VIO2_VD3,
-
-	GPIO_FN_OVCN2,
-	GPIO_FN_EXTLP, GPIO_FN_PORT226_VIO_CKO2,
-	GPIO_FN_IDIN,
-	GPIO_FN_MFG1_IN1,
-	GPIO_FN_MSIOF1_TXD,
-	GPIO_FN_MSIOF1_TSYNC,
-	GPIO_FN_MSIOF1_TSCK,
-	GPIO_FN_MSIOF1_RXD,
-	GPIO_FN_MSIOF1_RSCK, GPIO_FN_VIO2_CLK2,
-	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_MFG1_IN2, GPIO_FN_VIO2_VD2, \
-	GPIO_FN_MSIOF1_MCK0,
-	GPIO_FN_MSIOF1_MCK1,
-	GPIO_FN_MSIOF1_SS1, GPIO_FN_VIO2_FIELD2,
-	GPIO_FN_MSIOF1_SS2, GPIO_FN_VIO2_HD2,
-	GPIO_FN_PORT241_IROUT, GPIO_FN_MFG4_OUT1, \
-	GPIO_FN_TPU4TO0,
-	GPIO_FN_MFG4_IN2,
-	GPIO_FN_PORT243_VIO_CKO2,
-	GPIO_FN_MFG2_IN1,
-	GPIO_FN_MSIOF2R_RXD,
-	GPIO_FN_MFG2_IN2,
-	GPIO_FN_MSIOF2R_TXD,
-	GPIO_FN_MFG1_OUT1,
-	GPIO_FN_TPU1TO0,
-	GPIO_FN_MFG3_OUT2,
-	GPIO_FN_TPU3TO1,
-	GPIO_FN_MFG2_OUT1,
-	GPIO_FN_TPU2TO0,
-	GPIO_FN_MSIOF2R_TSCK,
-	GPIO_FN_PORT249_IROUT, GPIO_FN_MFG4_IN1, \
-	GPIO_FN_MSIOF2R_TSYNC,
-	GPIO_FN_SDHICLK0,
-	GPIO_FN_SDHICD0,
-	GPIO_FN_SDHID0_0,
-	GPIO_FN_SDHID0_1,
-	GPIO_FN_SDHID0_2,
-	GPIO_FN_SDHID0_3,
-	GPIO_FN_SDHICMD0,
-	GPIO_FN_SDHIWP0,
-	GPIO_FN_SDHICLK1,
-	GPIO_FN_SDHID1_0, GPIO_FN_TS_SPSYNC2,
-	GPIO_FN_SDHID1_1, GPIO_FN_TS_SDAT2,
-	GPIO_FN_SDHID1_2, GPIO_FN_TS_SDEN2,
-	GPIO_FN_SDHID1_3, GPIO_FN_TS_SCK2,
-	GPIO_FN_SDHICMD1,
-	GPIO_FN_SDHICLK2,
-	GPIO_FN_SDHID2_0, GPIO_FN_TS_SPSYNC4,
-	GPIO_FN_SDHID2_1, GPIO_FN_TS_SDAT4,
-	GPIO_FN_SDHID2_2, GPIO_FN_TS_SDEN4,
-	GPIO_FN_SDHID2_3, GPIO_FN_TS_SCK4,
-	GPIO_FN_SDHICMD2,
-	GPIO_FN_MMCCLK0,
-	GPIO_FN_MMCD0_0,
-	GPIO_FN_MMCD0_1,
-	GPIO_FN_MMCD0_2,
-	GPIO_FN_MMCD0_3,
-	GPIO_FN_MMCD0_4, GPIO_FN_TS_SPSYNC5,
-	GPIO_FN_MMCD0_5, GPIO_FN_TS_SDAT5,
-	GPIO_FN_MMCD0_6, GPIO_FN_TS_SDEN5,
-	GPIO_FN_MMCD0_7, GPIO_FN_TS_SCK5,
-	GPIO_FN_MMCCMD0,
-	GPIO_FN_RESETOUTS_, GPIO_FN_EXTAL2OUT,
-	GPIO_FN_MCP_WAIT__MCP_FRB,
-	GPIO_FN_MCP_CKO, GPIO_FN_MMCCLK1,
-	GPIO_FN_MCP_D15_MCP_NAF15,
-	GPIO_FN_MCP_D14_MCP_NAF14,
-	GPIO_FN_MCP_D13_MCP_NAF13,
-	GPIO_FN_MCP_D12_MCP_NAF12,
-	GPIO_FN_MCP_D11_MCP_NAF11,
-	GPIO_FN_MCP_D10_MCP_NAF10,
-	GPIO_FN_MCP_D9_MCP_NAF9,
-	GPIO_FN_MCP_D8_MCP_NAF8, GPIO_FN_MMCCMD1,
-	GPIO_FN_MCP_D7_MCP_NAF7, GPIO_FN_MMCD1_7,
-
-	GPIO_FN_MCP_D6_MCP_NAF6, GPIO_FN_MMCD1_6,
-	GPIO_FN_MCP_D5_MCP_NAF5, GPIO_FN_MMCD1_5,
-	GPIO_FN_MCP_D4_MCP_NAF4, GPIO_FN_MMCD1_4,
-	GPIO_FN_MCP_D3_MCP_NAF3, GPIO_FN_MMCD1_3,
-	GPIO_FN_MCP_D2_MCP_NAF2, GPIO_FN_MMCD1_2,
-	GPIO_FN_MCP_D1_MCP_NAF1, GPIO_FN_MMCD1_1,
-	GPIO_FN_MCP_D0_MCP_NAF0, GPIO_FN_MMCD1_0,
-	GPIO_FN_MCP_NBRSTOUT_,
-	GPIO_FN_MCP_WE0__MCP_FWE, GPIO_FN_MCP_RDWR_MCP_FWE,
-
-	/* MSEL2 special case */
-	GPIO_FN_TSIF2_TS_XX1,
-	GPIO_FN_TSIF2_TS_XX2,
-	GPIO_FN_TSIF2_TS_XX3,
-	GPIO_FN_TSIF2_TS_XX4,
-	GPIO_FN_TSIF2_TS_XX5,
-	GPIO_FN_TSIF1_TS_XX1,
-	GPIO_FN_TSIF1_TS_XX2,
-	GPIO_FN_TSIF1_TS_XX3,
-	GPIO_FN_TSIF1_TS_XX4,
-	GPIO_FN_TSIF1_TS_XX5,
-	GPIO_FN_TSIF0_TS_XX1,
-	GPIO_FN_TSIF0_TS_XX2,
-	GPIO_FN_TSIF0_TS_XX3,
-	GPIO_FN_TSIF0_TS_XX4,
-	GPIO_FN_TSIF0_TS_XX5,
-	GPIO_FN_MST1_TS_XX1,
-	GPIO_FN_MST1_TS_XX2,
-	GPIO_FN_MST1_TS_XX3,
-	GPIO_FN_MST1_TS_XX4,
-	GPIO_FN_MST1_TS_XX5,
-	GPIO_FN_MST0_TS_XX1,
-	GPIO_FN_MST0_TS_XX2,
-	GPIO_FN_MST0_TS_XX3,
-	GPIO_FN_MST0_TS_XX4,
-	GPIO_FN_MST0_TS_XX5,
-
-	/* MSEL3 special cases */
-	GPIO_FN_SDHI0_VCCQ_MC0_ON,
-	GPIO_FN_SDHI0_VCCQ_MC0_OFF,
-	GPIO_FN_DEBUG_MON_VIO,
-	GPIO_FN_DEBUG_MON_LCDD,
-	GPIO_FN_LCDC_LCDC0,
-	GPIO_FN_LCDC_LCDC1,
-
-	/* MSEL4 special cases */
-	GPIO_FN_IRQ9_MEM_INT,
-	GPIO_FN_IRQ9_MCP_INT,
-	GPIO_FN_A11,
-	GPIO_FN_TPU4TO3,
-	GPIO_FN_RESETA_N_PU_ON,
-	GPIO_FN_RESETA_N_PU_OFF,
-	GPIO_FN_EDBGREQ_PD,
-	GPIO_FN_EDBGREQ_PU,
-
-	/* end of GPIO */
-	GPIO_NR,
-};
-
 /* DMA slave IDs */
 enum {
 	SHDMA_SLAVE_INVALID,
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
index f2d8744..c3c4669 100644
--- a/arch/arm/mach-shmobile/include/mach/zboot.h
+++ b/arch/arm/mach-shmobile/include/mach/zboot.h
@@ -1,7 +1,6 @@
 #ifndef ZBOOT_H
 #define ZBOOT_H
 
-#include <asm/mach-types.h>
 #include <mach/zboot_macros.h>
 
 /**************************************************
@@ -11,7 +10,6 @@
  **************************************************/
 
 #ifdef CONFIG_MACH_MACKEREL
-#define MACH_TYPE	MACH_TYPE_MACKEREL
 #define MEMORY_START	0x40000000
 #include "mach/head-mackerel.txt"
 #else
diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c
deleted file mode 100644
index 8871f77..0000000
--- a/arch/arm/mach-shmobile/intc-r8a7740.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * R8A7740 processor support
- *
- * Copyright (C) 2011  Renesas Solutions Corp.
- * Copyright (C) 2011  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/irqchip.h>
-#include <linux/irqchip/arm-gic.h>
-
-static void __init r8a7740_init_irq_common(void)
-{
-	void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10);
-	void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10);
-	void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4);
-
-	/* route signals to GIC */
-	iowrite32(0x0, pfc_inta_ctrl);
-
-	/*
-	 * To mask the shared interrupt to SPI 149 we must ensure to set
-	 * PRIO *and* MASK. Else we run into IRQ floods when registering
-	 * the intc_irqpin devices
-	 */
-	iowrite32(0x0, intc_prio_base + 0x0);
-	iowrite32(0x0, intc_prio_base + 0x4);
-	iowrite32(0x0, intc_prio_base + 0x8);
-	iowrite32(0x0, intc_prio_base + 0xc);
-	iowrite8(0xff, intc_msk_base + 0x0);
-	iowrite8(0xff, intc_msk_base + 0x4);
-	iowrite8(0xff, intc_msk_base + 0x8);
-	iowrite8(0xff, intc_msk_base + 0xc);
-
-	iounmap(intc_prio_base);
-	iounmap(intc_msk_base);
-	iounmap(pfc_inta_ctrl);
-}
-
-void __init r8a7740_init_irq_of(void)
-{
-	irqchip_init();
-	r8a7740_init_irq_common();
-}
-
-void __init r8a7740_init_irq(void)
-{
-	void __iomem *gic_dist_base = ioremap_nocache(0xc2800000, 0x1000);
-	void __iomem *gic_cpu_base = ioremap_nocache(0xc2000000, 0x1000);
-
-	/* initialize the Generic Interrupt Controller PL390 r0p0 */
-	gic_init(0, 29, gic_dist_base, gic_cpu_base);
-	r8a7740_init_irq_common();
-}
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
deleted file mode 100644
index b86dc89..0000000
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * r8a7779 processor support - INTC hardware block
- *
- * Copyright (C) 2011  Renesas Solutions Corp.
- * Copyright (C) 2011  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/platform_data/irq-renesas-intc-irqpin.h>
-#include <linux/irqchip.h>
-#include <mach/common.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
-#include <mach/r8a7779.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#define INT2SMSKCR0 IOMEM(0xfe7822a0)
-#define INT2SMSKCR1 IOMEM(0xfe7822a4)
-#define INT2SMSKCR2 IOMEM(0xfe7822a8)
-#define INT2SMSKCR3 IOMEM(0xfe7822ac)
-#define INT2SMSKCR4 IOMEM(0xfe7822b0)
-
-#define INT2NTSR0 IOMEM(0xfe700060)
-#define INT2NTSR1 IOMEM(0xfe700064)
-
-static struct renesas_intc_irqpin_config irqpin0_platform_data = {
-	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
-	.sense_bitfield_width = 2,
-};
-
-static struct resource irqpin0_resources[] = {
-	DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
-	DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
-	DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
-	DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
-	DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
-	DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
-	DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
-	DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
-	DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
-};
-
-static struct platform_device irqpin0_device = {
-	.name		= "renesas_intc_irqpin",
-	.id		= 0,
-	.resource	= irqpin0_resources,
-	.num_resources	= ARRAY_SIZE(irqpin0_resources),
-	.dev		= {
-		.platform_data	= &irqpin0_platform_data,
-	},
-};
-
-void __init r8a7779_init_irq_extpin(int irlm)
-{
-	void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
-	unsigned long tmp;
-
-	if (icr0) {
-		tmp = ioread32(icr0);
-		if (irlm)
-			tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
-		else
-			tmp &= ~(1 << 23); /* IRL mode - not supported */
-		tmp |= (1 << 21); /* LVLMODE = 1 */
-		iowrite32(tmp, icr0);
-		iounmap(icr0);
-
-		if (irlm)
-			platform_device_register(&irqpin0_device);
-	} else
-		pr_warn("r8a7779: unable to setup external irq pin mode\n");
-}
-
-static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
-{
-	return 0; /* always allow wakeup */
-}
-
-static void __init r8a7779_init_irq_common(void)
-{
-	gic_arch_extn.irq_set_wake = r8a7779_set_wake;
-
-	/* route all interrupts to ARM */
-	__raw_writel(0xffffffff, INT2NTSR0);
-	__raw_writel(0x3fffffff, INT2NTSR1);
-
-	/* unmask all known interrupts in INTCS2 */
-	__raw_writel(0xfffffff0, INT2SMSKCR0);
-	__raw_writel(0xfff7ffff, INT2SMSKCR1);
-	__raw_writel(0xfffbffdf, INT2SMSKCR2);
-	__raw_writel(0xbffffffc, INT2SMSKCR3);
-	__raw_writel(0x003fee3f, INT2SMSKCR4);
-}
-
-void __init r8a7779_init_irq(void)
-{
-	void __iomem *gic_dist_base = IOMEM(0xf0001000);
-	void __iomem *gic_cpu_base = IOMEM(0xf0000100);
-
-	/* use GIC to handle interrupts */
-	gic_init(0, 29, gic_dist_base, gic_cpu_base);
-
-	r8a7779_init_irq_common();
-}
-
-#ifdef CONFIG_OF
-void __init r8a7779_init_irq_dt(void)
-{
-	irqchip_init();
-	r8a7779_init_irq_common();
-}
-#endif
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
new file mode 100644
index 0000000..c96f501
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-scu.c
@@ -0,0 +1,81 @@
+/*
+ * SMP support for SoCs with SCU covered by mach-shmobile
+ *
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include <mach/common.h>
+
+void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
+{
+	/* install boot code shared by all CPUs */
+	shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
+	shmobile_boot_arg = MPIDR_HWID_BITMASK;
+
+	/* enable SCU and cache coherency on booting CPU */
+	scu_enable(shmobile_scu_base);
+	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
+}
+
+int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	/* For this particular CPU register SCU boot vector */
+	shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
+			  (unsigned long)shmobile_scu_base);
+	return 0;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void shmobile_smp_scu_cpu_die(unsigned int cpu)
+{
+	/* For this particular CPU deregister boot vector */
+	shmobile_smp_hook(cpu, 0, 0);
+
+	dsb();
+	flush_cache_all();
+
+	/* disable cache coherency */
+	scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
+
+	/* jump to shared mach-shmobile sleep / reset code */
+	shmobile_smp_sleep();
+}
+
+static int shmobile_smp_scu_psr_core_disabled(int cpu)
+{
+	unsigned long mask = SCU_PM_POWEROFF << (cpu * 8);
+
+	if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
+		return 1;
+
+	return 0;
+}
+
+int shmobile_smp_scu_cpu_kill(unsigned int cpu)
+{
+	int k;
+
+	/* this function is running on another CPU than the offline target,
+	 * here we need wait for shutdown code in platform_cpu_die() to
+	 * finish before asking SoC-specific code to power off the CPU core.
+	 */
+	for (k = 0; k < 1000; k++) {
+		if (shmobile_smp_scu_psr_core_disabled(cpu))
+			return 1;
+
+		mdelay(1);
+	}
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index 1f958d7..d4ae616 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -12,6 +12,9 @@
  */
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <mach/common.h>
 
 void __init shmobile_smp_init_cpus(unsigned int ncores)
 {
@@ -26,3 +29,18 @@ void __init shmobile_smp_init_cpus(unsigned int ncores)
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
 }
+
+extern unsigned long shmobile_smp_fn[];
+extern unsigned long shmobile_smp_arg[];
+extern unsigned long shmobile_smp_mpidr[];
+
+void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
+{
+	shmobile_smp_fn[cpu] = 0;
+	flush_cache_all();
+
+	shmobile_smp_mpidr[cpu] = cpu_logical_map(cpu);
+	shmobile_smp_fn[cpu] = fn;
+	shmobile_smp_arg[cpu] = arg;
+	flush_cache_all();
+}
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index 1ccddd2..3ad531c 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/irqchip.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/gpio-em.h>
 #include <linux/of_platform.h>
@@ -28,7 +27,6 @@
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/irqchip/arm-gic.h>
-#include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/emev2.h>
 #include <mach/irqs.h>
@@ -39,13 +37,6 @@
 
 static struct map_desc emev2_io_desc[] __initdata = {
 #ifdef CONFIG_SMP
-	/* 128K entity map for 0xe0100000 (SMU) */
-	{
-		.virtual	= 0xe0100000,
-		.pfn		= __phys_to_pfn(0xe0100000),
-		.length		= SZ_128K,
-		.type		= MT_DEVICE
-	},
 	/* 2M mapping for SCU + L2 controller */
 	{
 		.virtual	= 0xf0000000,
@@ -63,102 +54,40 @@ void __init emev2_map_io(void)
 
 /* UART */
 static struct resource uart0_resources[] = {
-	[0]	= {
-		.start	= 0xe1020000,
-		.end	= 0xe1020037,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1]	= {
-		.start	= 40,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device uart0_device = {
-	.name		= "serial8250-em",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-	.resource	= uart0_resources,
+	DEFINE_RES_MEM(0xe1020000, 0x38),
+	DEFINE_RES_IRQ(40),
 };
 
 static struct resource uart1_resources[] = {
-	[0]	= {
-		.start	= 0xe1030000,
-		.end	= 0xe1030037,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1]	= {
-		.start	= 41,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device uart1_device = {
-	.name		= "serial8250-em",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-	.resource	= uart1_resources,
+	DEFINE_RES_MEM(0xe1030000, 0x38),
+	DEFINE_RES_IRQ(41),
 };
 
 static struct resource uart2_resources[] = {
-	[0]	= {
-		.start	= 0xe1040000,
-		.end	= 0xe1040037,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1]	= {
-		.start	= 42,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device uart2_device = {
-	.name		= "serial8250-em",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-	.resource	= uart2_resources,
+	DEFINE_RES_MEM(0xe1040000, 0x38),
+	DEFINE_RES_IRQ(42),
 };
 
 static struct resource uart3_resources[] = {
-	[0]	= {
-		.start	= 0xe1050000,
-		.end	= 0xe1050037,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1]	= {
-		.start	= 43,
-		.flags	= IORESOURCE_IRQ,
-	}
+	DEFINE_RES_MEM(0xe1050000, 0x38),
+	DEFINE_RES_IRQ(43),
 };
 
-static struct platform_device uart3_device = {
-	.name		= "serial8250-em",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
-	.resource	= uart3_resources,
-};
+#define emev2_register_uart(idx)					\
+	platform_device_register_simple("serial8250-em", idx,		\
+					uart##idx##_resources,		\
+					ARRAY_SIZE(uart##idx##_resources))
 
 /* STI */
 static struct resource sti_resources[] = {
-	[0] = {
-		.name	= "STI",
-		.start	= 0xe0180000,
-		.end	= 0xe0180053,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 157,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sti_device = {
-	.name		= "em_sti",
-	.id		= 0,
-	.resource	= sti_resources,
-	.num_resources	= ARRAY_SIZE(sti_resources),
+	DEFINE_RES_MEM(0xe0180000, 0x54),
+	DEFINE_RES_IRQ(157),
 };
 
+#define emev2_register_sti()					\
+	platform_device_register_simple("em_sti", 0,		\
+					sti_resources,		\
+					ARRAY_SIZE(sti_resources))
 
 /* GIO */
 static struct gpio_em_config gio0_config = {
@@ -168,36 +97,10 @@ static struct gpio_em_config gio0_config = {
 };
 
 static struct resource gio0_resources[] = {
-	[0] = {
-		.name	= "GIO_000",
-		.start	= 0xe0050000,
-		.end	= 0xe005002b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= "GIO_000",
-		.start	= 0xe0050040,
-		.end	= 0xe005005f,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= 99,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= 100,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device gio0_device = {
-	.name		= "em_gio",
-	.id		= 0,
-	.resource	= gio0_resources,
-	.num_resources	= ARRAY_SIZE(gio0_resources),
-	.dev		= {
-		.platform_data	= &gio0_config,
-	},
+	DEFINE_RES_MEM(0xe0050000, 0x2c),
+	DEFINE_RES_MEM(0xe0050040, 0x20),
+	DEFINE_RES_IRQ(99),
+	DEFINE_RES_IRQ(100),
 };
 
 static struct gpio_em_config gio1_config = {
@@ -207,36 +110,10 @@ static struct gpio_em_config gio1_config = {
 };
 
 static struct resource gio1_resources[] = {
-	[0] = {
-		.name	= "GIO_032",
-		.start	= 0xe0050080,
-		.end	= 0xe00500ab,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= "GIO_032",
-		.start	= 0xe00500c0,
-		.end	= 0xe00500df,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= 101,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= 102,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device gio1_device = {
-	.name		= "em_gio",
-	.id		= 1,
-	.resource	= gio1_resources,
-	.num_resources	= ARRAY_SIZE(gio1_resources),
-	.dev		= {
-		.platform_data	= &gio1_config,
-	},
+	DEFINE_RES_MEM(0xe0050080, 0x2c),
+	DEFINE_RES_MEM(0xe00500c0, 0x20),
+	DEFINE_RES_IRQ(101),
+	DEFINE_RES_IRQ(102),
 };
 
 static struct gpio_em_config gio2_config = {
@@ -246,36 +123,10 @@ static struct gpio_em_config gio2_config = {
 };
 
 static struct resource gio2_resources[] = {
-	[0] = {
-		.name	= "GIO_064",
-		.start	= 0xe0050100,
-		.end	= 0xe005012b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= "GIO_064",
-		.start	= 0xe0050140,
-		.end	= 0xe005015f,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= 103,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= 104,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device gio2_device = {
-	.name		= "em_gio",
-	.id		= 2,
-	.resource	= gio2_resources,
-	.num_resources	= ARRAY_SIZE(gio2_resources),
-	.dev		= {
-		.platform_data	= &gio2_config,
-	},
+	DEFINE_RES_MEM(0xe0050100, 0x2c),
+	DEFINE_RES_MEM(0xe0050140, 0x20),
+	DEFINE_RES_IRQ(103),
+	DEFINE_RES_IRQ(104),
 };
 
 static struct gpio_em_config gio3_config = {
@@ -285,36 +136,10 @@ static struct gpio_em_config gio3_config = {
 };
 
 static struct resource gio3_resources[] = {
-	[0] = {
-		.name	= "GIO_096",
-		.start	= 0xe0050180,
-		.end	= 0xe00501ab,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= "GIO_096",
-		.start	= 0xe00501c0,
-		.end	= 0xe00501df,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= 105,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= 106,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device gio3_device = {
-	.name		= "em_gio",
-	.id		= 3,
-	.resource	= gio3_resources,
-	.num_resources	= ARRAY_SIZE(gio3_resources),
-	.dev		= {
-		.platform_data	= &gio3_config,
-	},
+	DEFINE_RES_MEM(0xe0050180, 0x2c),
+	DEFINE_RES_MEM(0xe00501c0, 0x20),
+	DEFINE_RES_IRQ(105),
+	DEFINE_RES_IRQ(106),
 };
 
 static struct gpio_em_config gio4_config = {
@@ -324,126 +149,53 @@ static struct gpio_em_config gio4_config = {
 };
 
 static struct resource gio4_resources[] = {
-	[0] = {
-		.name	= "GIO_128",
-		.start	= 0xe0050200,
-		.end	= 0xe005022b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= "GIO_128",
-		.start	= 0xe0050240,
-		.end	= 0xe005025f,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= 107,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= 108,
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0xe0050200, 0x2c),
+	DEFINE_RES_MEM(0xe0050240, 0x20),
+	DEFINE_RES_IRQ(107),
+	DEFINE_RES_IRQ(108),
 };
 
-static struct platform_device gio4_device = {
-	.name		= "em_gio",
-	.id		= 4,
-	.resource	= gio4_resources,
-	.num_resources	= ARRAY_SIZE(gio4_resources),
-	.dev		= {
-		.platform_data	= &gio4_config,
-	},
-};
+#define emev2_register_gio(idx)						\
+	platform_device_register_resndata(&platform_bus, "em_gio",	\
+					  idx, gio##idx##_resources,	\
+					  ARRAY_SIZE(gio##idx##_resources), \
+					  &gio##idx##_config,		\
+					  sizeof(struct gpio_em_config))
 
 static struct resource pmu_resources[] = {
-	[0] = {
-		.start	= 152,
-		.end	= 152,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= 153,
-		.end	= 153,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device pmu_device = {
-	.name		= "arm-pmu",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(pmu_resources),
-	.resource	= pmu_resources,
+	DEFINE_RES_IRQ(152),
+	DEFINE_RES_IRQ(153),
 };
 
-static struct platform_device *emev2_early_devices[] __initdata = {
-	&uart0_device,
-	&uart1_device,
-	&uart2_device,
-	&uart3_device,
-};
-
-static struct platform_device *emev2_late_devices[] __initdata = {
-	&sti_device,
-	&gio0_device,
-	&gio1_device,
-	&gio2_device,
-	&gio3_device,
-	&gio4_device,
-	&pmu_device,
-};
+#define emev2_register_pmu()					\
+	platform_device_register_simple("arm-pmu", -1,		\
+					pmu_resources,		\
+					ARRAY_SIZE(pmu_resources))
 
 void __init emev2_add_standard_devices(void)
 {
-	emev2_clock_init();
-
-	platform_add_devices(emev2_early_devices,
-			     ARRAY_SIZE(emev2_early_devices));
-
-	platform_add_devices(emev2_late_devices,
-			     ARRAY_SIZE(emev2_late_devices));
+	if (!IS_ENABLED(CONFIG_COMMON_CLK))
+		emev2_clock_init();
+
+	emev2_register_uart(0);
+	emev2_register_uart(1);
+	emev2_register_uart(2);
+	emev2_register_uart(3);
+	emev2_register_sti();
+	emev2_register_gio(0);
+	emev2_register_gio(1);
+	emev2_register_gio(2);
+	emev2_register_gio(3);
+	emev2_register_gio(4);
+	emev2_register_pmu();
 }
 
-static void __init emev2_init_delay(void)
+void __init emev2_init_delay(void)
 {
 	shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
 }
 
-void __init emev2_add_early_devices(void)
-{
-	emev2_init_delay();
-
-	early_platform_add_devices(emev2_early_devices,
-				   ARRAY_SIZE(emev2_early_devices));
-
-	/* setup early console here as well */
-	shmobile_setup_console();
-}
-
-void __init emev2_init_irq(void)
-{
-	void __iomem *gic_dist_base;
-	void __iomem *gic_cpu_base;
-
-	/* Static mappings, never released */
-	gic_dist_base = ioremap(0xe0028000, PAGE_SIZE);
-	gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE);
-	BUG_ON(!gic_dist_base || !gic_cpu_base);
-
-	/* Use GIC to handle interrupts */
-	gic_init(0, 29, gic_dist_base, gic_cpu_base);
-}
-
 #ifdef CONFIG_USE_OF
-static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
-	{ }
-};
-
-static void __init emev2_add_standard_devices_dt(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     emev2_auxdata_lookup, NULL);
-}
 
 static const char *emev2_boards_compat_dt[] __initdata = {
 	"renesas,emev2",
@@ -452,10 +204,8 @@ static const char *emev2_boards_compat_dt[] __initdata = {
 
 DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
 	.smp		= smp_ops(emev2_smp_ops),
+	.map_io		= emev2_map_io,
 	.init_early	= emev2_init_delay,
-	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= irqchip_init,
-	.init_machine	= emev2_add_standard_devices_dt,
 	.dt_compat	= emev2_boards_compat_dt,
 MACHINE_END
 
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index 7f45c2e..8949170 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -18,11 +18,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/irq.h>
-#include <linux/irqchip.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/irq-renesas-irqc.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a73a4.h>
@@ -169,7 +169,26 @@ static const struct resource thermal0_resources[] = {
 					thermal0_resources,		\
 					ARRAY_SIZE(thermal0_resources))
 
-void __init r8a73a4_add_standard_devices(void)
+static struct sh_timer_config cmt10_platform_data = {
+	.name = "CMT10",
+	.timer_bit = 0,
+	.clockevent_rating = 80,
+};
+
+static struct resource cmt10_resources[] = {
+	DEFINE_RES_MEM(0xe6130010, 0x0c),
+	DEFINE_RES_MEM(0xe6130000, 0x04),
+	DEFINE_RES_IRQ(gic_spi(120)), /* CMT1_0 */
+};
+
+#define r8a7790_register_cmt(idx)					\
+	platform_device_register_resndata(&platform_bus, "sh_cmt",	\
+					  idx, cmt##idx##_resources,	\
+					  ARRAY_SIZE(cmt##idx##_resources), \
+					  &cmt##idx##_platform_data,	\
+					  sizeof(struct sh_timer_config))
+
+void __init r8a73a4_add_dt_devices(void)
 {
 	r8a73a4_register_scif(SCIFA0);
 	r8a73a4_register_scif(SCIFA1);
@@ -177,26 +196,33 @@ void __init r8a73a4_add_standard_devices(void)
 	r8a73a4_register_scif(SCIFB1);
 	r8a73a4_register_scif(SCIFB2);
 	r8a73a4_register_scif(SCIFB3);
+	r8a7790_register_cmt(10);
+}
+
+void __init r8a73a4_add_standard_devices(void)
+{
+	r8a73a4_add_dt_devices();
 	r8a73a4_register_irqc(0);
 	r8a73a4_register_irqc(1);
 	r8a73a4_register_thermal();
 }
 
-#ifdef CONFIG_USE_OF
-void __init r8a73a4_add_standard_devices_dt(void)
+void __init r8a73a4_init_delay(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+#ifndef CONFIG_ARM_ARCH_TIMER
+	shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
+#endif
 }
 
+#ifdef CONFIG_USE_OF
+
 static const char *r8a73a4_boards_compat_dt[] __initdata = {
 	"renesas,r8a73a4",
 	NULL,
 };
 
 DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
-	.init_irq	= irqchip_init,
-	.init_machine	= r8a73a4_add_standard_devices_dt,
-	.init_time	= shmobile_timer_init,
+	.init_early	= r8a73a4_init_delay,
 	.dt_compat	= r8a73a4_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 00c5a70..b7d4b2c 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
@@ -588,6 +590,16 @@ static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
 		.addr		= 0xfe1f0064,
 		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
 		.mid_rid	= 0xb5,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF_TX,
+		.addr		= 0xe6bd0034,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd1,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF_RX,
+		.addr		= 0xe6bd0034,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd2,
 	},
 };
 
@@ -986,16 +998,22 @@ void __init r8a7740_add_early_devices(void)
 
 #ifdef CONFIG_USE_OF
 
-static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = {
-	{ }
-};
+void __init r8a7740_add_early_devices_dt(void)
+{
+	shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
+
+	early_platform_add_devices(r8a7740_early_devices,
+				   ARRAY_SIZE(r8a7740_early_devices));
+
+	/* setup early console here as well */
+	shmobile_setup_console();
+}
 
 void __init r8a7740_add_standard_devices_dt(void)
 {
 	platform_add_devices(r8a7740_devices_dt,
 			    ARRAY_SIZE(r8a7740_devices_dt));
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     r8a7740_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 void __init r8a7740_init_delay(void)
@@ -1003,6 +1021,36 @@ void __init r8a7740_init_delay(void)
 	shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
 };
 
+void __init r8a7740_init_irq_of(void)
+{
+	void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10);
+	void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10);
+	void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4);
+
+	irqchip_init();
+
+	/* route signals to GIC */
+	iowrite32(0x0, pfc_inta_ctrl);
+
+	/*
+	 * To mask the shared interrupt to SPI 149 we must ensure to set
+	 * PRIO *and* MASK. Else we run into IRQ floods when registering
+	 * the intc_irqpin devices
+	 */
+	iowrite32(0x0, intc_prio_base + 0x0);
+	iowrite32(0x0, intc_prio_base + 0x4);
+	iowrite32(0x0, intc_prio_base + 0x8);
+	iowrite32(0x0, intc_prio_base + 0xc);
+	iowrite8(0xff, intc_msk_base + 0x0);
+	iowrite8(0xff, intc_msk_base + 0x4);
+	iowrite8(0xff, intc_msk_base + 0x8);
+	iowrite8(0xff, intc_msk_base + 0xc);
+
+	iounmap(intc_prio_base);
+	iounmap(intc_msk_base);
+	iounmap(pfc_inta_ctrl);
+}
+
 static void __init r8a7740_generic_init(void)
 {
 	r8a7740_clock_init(0);
@@ -1019,7 +1067,6 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
 	.init_early	= r8a7740_init_delay,
 	.init_irq	= r8a7740_init_irq_of,
 	.init_machine	= r8a7740_generic_init,
-	.init_time	= shmobile_timer_init,
 	.dt_compat	= r8a7740_boards_compat_dt,
 MACHINE_END
 
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index 80c2039..604cf36 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -53,7 +53,7 @@
 	.irqs		= SCIx_IRQ_MUXED(irq),			\
 }
 
-static struct plat_sci_port scif_platform_data[] = {
+static struct plat_sci_port scif_platform_data[] __initdata = {
 	SCIF_INFO(0xffe40000, gic_iid(0x66)),
 	SCIF_INFO(0xffe41000, gic_iid(0x67)),
 	SCIF_INFO(0xffe42000, gic_iid(0x68)),
@@ -63,24 +63,24 @@ static struct plat_sci_port scif_platform_data[] = {
 };
 
 /* TMU */
-static struct resource sh_tmu0_resources[] = {
+static struct resource sh_tmu0_resources[] __initdata = {
 	DEFINE_RES_MEM(0xffd80008, 12),
 	DEFINE_RES_IRQ(gic_iid(0x40)),
 };
 
-static struct sh_timer_config sh_tmu0_platform_data = {
+static struct sh_timer_config sh_tmu0_platform_data __initdata = {
 	.name			= "TMU00",
 	.channel_offset		= 0x4,
 	.timer_bit		= 0,
 	.clockevent_rating	= 200,
 };
 
-static struct resource sh_tmu1_resources[] = {
+static struct resource sh_tmu1_resources[] __initdata = {
 	DEFINE_RES_MEM(0xffd80014, 12),
 	DEFINE_RES_IRQ(gic_iid(0x41)),
 };
 
-static struct sh_timer_config sh_tmu1_platform_data = {
+static struct sh_timer_config sh_tmu1_platform_data __initdata = {
 	.name			= "TMU01",
 	.channel_offset		= 0x10,
 	.timer_bit		= 1,
@@ -95,20 +95,6 @@ static struct sh_timer_config sh_tmu1_platform_data = {
 		&sh_tmu##idx##_platform_data,		\
 		sizeof(sh_tmu##idx##_platform_data))
 
-/* USB PHY */
-static struct resource usb_phy_resources[] __initdata = {
-	DEFINE_RES_MEM(0xffe70800, 0x100),
-	DEFINE_RES_MEM(0xffe76000, 0x100),
-};
-
-void __init r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
-{
-	platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1,
-					  usb_phy_resources,
-					  ARRAY_SIZE(usb_phy_resources),
-					  pdata, sizeof(*pdata));
-}
-
 /* USB */
 static struct usb_phy *phy;
 
@@ -189,7 +175,7 @@ USB_PLATFORM_INFO(ehci);
 USB_PLATFORM_INFO(ohci);
 
 /* Ether */
-static struct resource ether_resources[] = {
+static struct resource ether_resources[] __initdata = {
 	DEFINE_RES_MEM(0xfde00000, 0x400),
 	DEFINE_RES_IRQ(gic_iid(0x89)),
 };
@@ -203,17 +189,17 @@ void __init r8a7778_add_ether_device(struct sh_eth_plat_data *pdata)
 }
 
 /* PFC/GPIO */
-static struct resource pfc_resources[] = {
+static struct resource pfc_resources[] __initdata = {
 	DEFINE_RES_MEM(0xfffc0000, 0x118),
 };
 
 #define R8A7778_GPIO(idx)						\
-static struct resource r8a7778_gpio##idx##_resources[] = {		\
+static struct resource r8a7778_gpio##idx##_resources[] __initdata = {	\
 	DEFINE_RES_MEM(0xffc40000 + 0x1000 * (idx), 0x30),		\
 	DEFINE_RES_IRQ(gic_iid(0x87)),					\
 };									\
 									\
-static struct gpio_rcar_config r8a7778_gpio##idx##_platform_data = {	\
+static struct gpio_rcar_config r8a7778_gpio##idx##_platform_data __initdata = { \
 	.gpio_base	= 32 * (idx),					\
 	.irq_base	= GPIO_IRQ_BASE(idx),				\
 	.number_of_pins	= 32,						\
@@ -248,30 +234,6 @@ void __init r8a7778_pinmux_init(void)
 	r8a7778_register_gpio(4);
 };
 
-/* SDHI */
-static struct resource sdhi_resources[] = {
-	/* SDHI0 */
-	DEFINE_RES_MEM(0xFFE4C000, 0x100),
-	DEFINE_RES_IRQ(gic_iid(0x77)),
-	/* SDHI1 */
-	DEFINE_RES_MEM(0xFFE4D000, 0x100),
-	DEFINE_RES_IRQ(gic_iid(0x78)),
-	/* SDHI2 */
-	DEFINE_RES_MEM(0xFFE4F000, 0x100),
-	DEFINE_RES_IRQ(gic_iid(0x76)),
-};
-
-void __init r8a7778_sdhi_init(int id,
-			      struct sh_mobile_sdhi_info *info)
-{
-	BUG_ON(id < 0 || id > 2);
-
-	platform_device_register_resndata(
-		&platform_bus, "sh_mobile_sdhi", id,
-		sdhi_resources + (2 * id), 2,
-		info, sizeof(*info));
-}
-
 /* I2C */
 static struct resource i2c_resources[] __initdata = {
 	/* I2C0 */
@@ -288,7 +250,7 @@ static struct resource i2c_resources[] __initdata = {
 	DEFINE_RES_IRQ(gic_iid(0x6d)),
 };
 
-void __init r8a7778_add_i2c_device(int id)
+static void __init r8a7778_register_i2c(int id)
 {
 	BUG_ON(id < 0 || id > 3);
 
@@ -310,7 +272,7 @@ static struct resource hspi_resources[] __initdata = {
 	DEFINE_RES_IRQ(gic_iid(0x75)),
 };
 
-void __init r8a7778_add_hspi_device(int id)
+void __init r8a7778_register_hspi(int id)
 {
 	BUG_ON(id < 0 || id > 2);
 
@@ -319,21 +281,7 @@ void __init r8a7778_add_hspi_device(int id)
 		hspi_resources + (2 * id), 2);
 }
 
-/* MMC */
-static struct resource mmc_resources[] __initdata = {
-	DEFINE_RES_MEM(0xffe4e000, 0x100),
-	DEFINE_RES_IRQ(gic_iid(0x5d)),
-};
-
-void __init r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info)
-{
-	platform_device_register_resndata(
-		&platform_bus, "sh_mmcif", -1,
-		mmc_resources, ARRAY_SIZE(mmc_resources),
-		info, sizeof(*info));
-}
-
-void __init r8a7778_add_standard_devices(void)
+void __init r8a7778_add_dt_devices(void)
 {
 	int i;
 
@@ -357,6 +305,18 @@ void __init r8a7778_add_standard_devices(void)
 	r8a7778_register_tmu(1);
 }
 
+void __init r8a7778_add_standard_devices(void)
+{
+	r8a7778_add_dt_devices();
+	r8a7778_register_i2c(0);
+	r8a7778_register_i2c(1);
+	r8a7778_register_i2c(2);
+	r8a7778_register_i2c(3);
+	r8a7778_register_hspi(0);
+	r8a7778_register_hspi(1);
+	r8a7778_register_hspi(2);
+}
+
 void __init r8a7778_init_late(void)
 {
 	phy = usb_get_phy(USB_PHY_TYPE_USB2);
@@ -365,12 +325,12 @@ void __init r8a7778_init_late(void)
 	platform_device_register_full(&ohci_info);
 }
 
-static struct renesas_intc_irqpin_config irqpin_platform_data = {
+static struct renesas_intc_irqpin_config irqpin_platform_data __initdata = {
 	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
 	.sense_bitfield_width = 2,
 };
 
-static struct resource irqpin_resources[] = {
+static struct resource irqpin_resources[] __initdata = {
 	DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
 	DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
 	DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
@@ -408,17 +368,25 @@ void __init r8a7778_init_irq_extpin(int irlm)
 			&irqpin_platform_data, sizeof(irqpin_platform_data));
 }
 
+void __init r8a7778_init_delay(void)
+{
+	shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
+}
+
+#ifdef CONFIG_USE_OF
 #define INT2SMSKCR0	0x82288 /* 0xfe782288 */
 #define INT2SMSKCR1	0x8228c /* 0xfe78228c */
 
 #define INT2NTSR0	0x00018 /* 0xfe700018 */
 #define INT2NTSR1	0x0002c /* 0xfe70002c */
-static void __init r8a7778_init_irq_common(void)
+void __init r8a7778_init_irq_dt(void)
 {
 	void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000);
 
 	BUG_ON(!base);
 
+	irqchip_init();
+
 	/* route all interrupts to ARM */
 	__raw_writel(0x73ffffff, base + INT2NTSR0);
 	__raw_writel(0xffffffff, base + INT2NTSR1);
@@ -430,43 +398,6 @@ static void __init r8a7778_init_irq_common(void)
 	iounmap(base);
 }
 
-void __init r8a7778_init_irq(void)
-{
-	void __iomem *gic_dist_base;
-	void __iomem *gic_cpu_base;
-
-	gic_dist_base = ioremap_nocache(0xfe438000, PAGE_SIZE);
-	gic_cpu_base  = ioremap_nocache(0xfe430000, PAGE_SIZE);
-	BUG_ON(!gic_dist_base || !gic_cpu_base);
-
-	/* use GIC to handle interrupts */
-	gic_init(0, 29, gic_dist_base, gic_cpu_base);
-
-	r8a7778_init_irq_common();
-}
-
-void __init r8a7778_init_delay(void)
-{
-	shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
-}
-
-#ifdef CONFIG_USE_OF
-void __init r8a7778_init_irq_dt(void)
-{
-	irqchip_init();
-	r8a7778_init_irq_common();
-}
-
-static const struct of_dev_auxdata r8a7778_auxdata_lookup[] __initconst = {
-	{},
-};
-
-void __init r8a7778_add_standard_devices_dt(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     r8a7778_auxdata_lookup, NULL);
-}
-
 static const char *r8a7778_compat_dt[] __initdata = {
 	"renesas,r8a7778",
 	NULL,
@@ -475,8 +406,6 @@ static const char *r8a7778_compat_dt[] __initdata = {
 DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
 	.init_early	= r8a7778_init_delay,
 	.init_irq	= r8a7778_init_irq_dt,
-	.init_machine	= r8a7778_add_standard_devices_dt,
-	.init_time	= shmobile_timer_init,
 	.dt_compat	= r8a7778_compat_dt,
 	.init_late      = r8a7778_init_late,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index 3986877..6a99333 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -22,14 +22,16 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
-#include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/otg.h>
@@ -37,7 +39,6 @@
 #include <linux/usb/ehci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/pm_runtime.h>
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
@@ -69,6 +70,60 @@ void __init r8a7779_map_io(void)
 	iotable_init(r8a7779_io_desc, ARRAY_SIZE(r8a7779_io_desc));
 }
 
+/* IRQ */
+#define INT2SMSKCR0 IOMEM(0xfe7822a0)
+#define INT2SMSKCR1 IOMEM(0xfe7822a4)
+#define INT2SMSKCR2 IOMEM(0xfe7822a8)
+#define INT2SMSKCR3 IOMEM(0xfe7822ac)
+#define INT2SMSKCR4 IOMEM(0xfe7822b0)
+
+#define INT2NTSR0 IOMEM(0xfe700060)
+#define INT2NTSR1 IOMEM(0xfe700064)
+
+static struct renesas_intc_irqpin_config irqpin0_platform_data __initdata = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+	.sense_bitfield_width = 2,
+};
+
+static struct resource irqpin0_resources[] __initdata = {
+	DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+	DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+	DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+	DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+	DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+	DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
+};
+
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+	void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+	u32 tmp;
+
+	if (!icr0) {
+		pr_warn("r8a7779: unable to setup external irq pin mode\n");
+		return;
+	}
+
+	tmp = ioread32(icr0);
+	if (irlm)
+		tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+	else
+		tmp &= ~(1 << 23); /* IRL mode - not supported */
+	tmp |= (1 << 21); /* LVLMODE = 1 */
+	iowrite32(tmp, icr0);
+	iounmap(icr0);
+
+	if (irlm)
+		platform_device_register_resndata(
+			&platform_bus, "renesas_intc_irqpin", -1,
+			irqpin0_resources, ARRAY_SIZE(irqpin0_resources),
+			&irqpin0_platform_data, sizeof(irqpin0_platform_data));
+}
+
+/* PFC/GPIO */
 static struct resource r8a7779_pfc_resources[] = {
 	DEFINE_RES_MEM(0xfffc0000, 0x023c),
 };
@@ -388,15 +443,6 @@ static struct platform_device sata_device = {
 	},
 };
 
-/* USB PHY */
-static struct resource usb_phy_resources[] __initdata = {
-	[0] = {
-		.start		= 0xffe70800,
-		.end		= 0xffe70900 - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
 /* USB */
 static struct usb_phy *phy;
 
@@ -548,7 +594,7 @@ static struct platform_device ohci1_device = {
 };
 
 /* Ether */
-static struct resource ether_resources[] = {
+static struct resource ether_resources[] __initdata = {
 	{
 		.start	= 0xfde00000,
 		.end	= 0xfde003ff,
@@ -602,14 +648,6 @@ void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
 					  pdata, sizeof(*pdata));
 }
 
-void __init r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
-{
-	platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1,
-					  usb_phy_resources,
-					  ARRAY_SIZE(usb_phy_resources),
-					  pdata, sizeof(*pdata));
-}
-
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak r8a7779_register_twd(void) { }
 
@@ -660,15 +698,34 @@ void __init r8a7779_init_late(void)
 }
 
 #ifdef CONFIG_USE_OF
+static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
+{
+	return 0; /* always allow wakeup */
+}
+
+void __init r8a7779_init_irq_dt(void)
+{
+	gic_arch_extn.irq_set_wake = r8a7779_set_wake;
+
+	irqchip_init();
+
+	/* route all interrupts to ARM */
+	__raw_writel(0xffffffff, INT2NTSR0);
+	__raw_writel(0x3fffffff, INT2NTSR1);
+
+	/* unmask all known interrupts in INTCS2 */
+	__raw_writel(0xfffffff0, INT2SMSKCR0);
+	__raw_writel(0xfff7ffff, INT2SMSKCR1);
+	__raw_writel(0xfffbffdf, INT2SMSKCR2);
+	__raw_writel(0xbffffffc, INT2SMSKCR3);
+	__raw_writel(0x003fee3f, INT2SMSKCR4);
+}
+
 void __init r8a7779_init_delay(void)
 {
 	shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
 }
 
-static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = {
-	{},
-};
-
 void __init r8a7779_add_standard_devices_dt(void)
 {
 	/* clocks are setup late during boot in the case of DT */
@@ -676,8 +733,7 @@ void __init r8a7779_add_standard_devices_dt(void)
 
 	platform_add_devices(r8a7779_devices_dt,
 			     ARRAY_SIZE(r8a7779_devices_dt));
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     r8a7779_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *r8a7779_compat_dt[] __initdata = {
@@ -691,7 +747,6 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= r8a7779_init_irq_dt,
 	.init_machine	= r8a7779_add_standard_devices_dt,
-	.init_time	= shmobile_timer_init,
 	.init_late	= r8a7779_init_late,
 	.dt_compat	= r8a7779_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index 28f9475..d0f5c9f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -18,13 +18,14 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clocksource.h>
 #include <linux/irq.h>
-#include <linux/irqchip.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
-#include <linux/serial_sci.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/irq-renesas-irqc.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a7790.h>
@@ -149,7 +150,37 @@ static struct resource irqc0_resources[] __initdata = {
 					  &irqc##idx##_data,		\
 					  sizeof(struct renesas_irqc_config))
 
-void __init r8a7790_add_standard_devices(void)
+static struct resource thermal_resources[] __initdata = {
+	DEFINE_RES_MEM(0xe61f0000, 0x14),
+	DEFINE_RES_MEM(0xe61f0100, 0x38),
+	DEFINE_RES_IRQ(gic_spi(69)),
+};
+
+#define r8a7790_register_thermal()					\
+	platform_device_register_simple("rcar_thermal", -1,		\
+					thermal_resources,		\
+					ARRAY_SIZE(thermal_resources))
+
+static struct sh_timer_config cmt00_platform_data __initdata = {
+	.name = "CMT00",
+	.timer_bit = 0,
+	.clockevent_rating = 80,
+};
+
+static struct resource cmt00_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffca0510, 0x0c),
+	DEFINE_RES_MEM(0xffca0500, 0x04),
+	DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
+};
+
+#define r8a7790_register_cmt(idx)					\
+	platform_device_register_resndata(&platform_bus, "sh_cmt",	\
+					  idx, cmt##idx##_resources,	\
+					  ARRAY_SIZE(cmt##idx##_resources), \
+					  &cmt##idx##_platform_data,	\
+					  sizeof(struct sh_timer_config))
+
+void __init r8a7790_add_dt_devices(void)
 {
 	r8a7790_register_scif(SCIFA0);
 	r8a7790_register_scif(SCIFA1);
@@ -161,35 +192,97 @@ void __init r8a7790_add_standard_devices(void)
 	r8a7790_register_scif(SCIF1);
 	r8a7790_register_scif(HSCIF0);
 	r8a7790_register_scif(HSCIF1);
+	r8a7790_register_cmt(00);
+}
+
+void __init r8a7790_add_standard_devices(void)
+{
+	r8a7790_add_dt_devices();
 	r8a7790_register_irqc(0);
+	r8a7790_register_thermal();
 }
 
+#define MODEMR 0xe6160060
+
+u32 __init r8a7790_read_mode_pins(void)
+{
+	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+	u32 mode;
+
+	BUG_ON(!modemr);
+	mode = ioread32(modemr);
+	iounmap(modemr);
+
+	return mode;
+}
+
+#define CNTCR 0
+#define CNTFID0 0x20
+
 void __init r8a7790_timer_init(void)
 {
-	void __iomem *cntcr;
+#ifdef CONFIG_ARM_ARCH_TIMER
+	u32 mode = r8a7790_read_mode_pins();
+	void __iomem *base;
+	int extal_mhz = 0;
+	u32 freq;
+
+	/* At Linux boot time the r8a7790 arch timer comes up
+	 * with the counter disabled. Moreover, it may also report
+	 * a potentially incorrect fixed 13 MHz frequency. To be
+	 * correct these registers need to be updated to use the
+	 * frequency EXTAL / 2 which can be determined by the MD pins.
+	 */
 
-	/* make sure arch timer is started by setting bit 0 of CNTCT */
-	cntcr = ioremap(0xe6080000, PAGE_SIZE);
-	iowrite32(1, cntcr);
-	iounmap(cntcr);
+	switch (mode & (MD(14) | MD(13))) {
+	case 0:
+		extal_mhz = 15;
+		break;
+	case MD(13):
+		extal_mhz = 20;
+		break;
+	case MD(14):
+		extal_mhz = 26;
+		break;
+	case MD(13) | MD(14):
+		extal_mhz = 30;
+		break;
+	}
 
-	shmobile_timer_init();
+	/* The arch timer frequency equals EXTAL / 2 */
+	freq = extal_mhz * (1000000 / 2);
+
+	/* Remap "armgcnt address map" space */
+	base = ioremap(0xe6080000, PAGE_SIZE);
+
+	/* Update registers with correct frequency */
+	iowrite32(freq, base + CNTFID0);
+	asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
+
+	/* make sure arch timer is started by setting bit 0 of CNTCR */
+	iowrite32(1, base + CNTCR);
+	iounmap(base);
+#endif /* CONFIG_ARM_ARCH_TIMER */
+
+	clocksource_of_init();
 }
 
-#ifdef CONFIG_USE_OF
-void __init r8a7790_add_standard_devices_dt(void)
+void __init r8a7790_init_delay(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+#ifndef CONFIG_ARM_ARCH_TIMER
+	shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
+#endif
 }
 
+#ifdef CONFIG_USE_OF
+
 static const char *r8a7790_boards_compat_dt[] __initdata = {
 	"renesas,r8a7790",
 	NULL,
 };
 
 DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
-	.init_irq	= irqchip_init,
-	.init_machine	= r8a7790_add_standard_devices_dt,
+	.init_early	= r8a7790_init_delay,
 	.init_time	= r8a7790_timer_init,
 	.dt_compat	= r8a7790_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 5502d62..3118783 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -35,7 +35,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/sh_ipmmu.h>
 #include <mach/dma-register.h>
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/sh7372.h>
 #include <mach/common.h>
@@ -1147,10 +1146,6 @@ void __init sh7372_add_early_devices_dt(void)
 	shmobile_setup_console();
 }
 
-static const struct of_dev_auxdata sh7372_auxdata_lookup[] __initconst = {
-	{ }
-};
-
 void __init sh7372_add_standard_devices_dt(void)
 {
 	/* clocks are setup late during boot in the case of DT */
@@ -1159,8 +1154,7 @@ void __init sh7372_add_standard_devices_dt(void)
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     sh7372_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *sh7372_boards_compat_dt[] __initdata = {
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 96e7ca1..22de174 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/irqchip.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
@@ -35,7 +34,6 @@
 #include <linux/platform_data/sh_ipmmu.h>
 #include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <mach/dma-register.h>
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
@@ -61,29 +59,16 @@ void __init sh73a0_map_io(void)
 	iotable_init(sh73a0_io_desc, ARRAY_SIZE(sh73a0_io_desc));
 }
 
-static struct resource sh73a0_pfc_resources[] = {
-	[0] = {
-		.start	= 0xe6050000,
-		.end	= 0xe6057fff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 0xe605801c,
-		.end	= 0xe6058027,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device sh73a0_pfc_device = {
-	.name		= "pfc-sh73a0",
-	.id		= -1,
-	.resource	= sh73a0_pfc_resources,
-	.num_resources	= ARRAY_SIZE(sh73a0_pfc_resources),
+/* PFC */
+static struct resource pfc_resources[] __initdata = {
+	DEFINE_RES_MEM(0xe6050000, 0x8000),
+	DEFINE_RES_MEM(0xe605801c, 0x000c),
 };
 
 void __init sh73a0_pinmux_init(void)
 {
-	platform_device_register(&sh73a0_pfc_device);
+	platform_device_register_simple("pfc-sh73a0", -1, pfc_resources,
+					ARRAY_SIZE(pfc_resources));
 }
 
 static struct plat_sci_port scif0_platform_data = {
@@ -958,10 +943,6 @@ void __init sh73a0_add_early_devices(void)
 
 #ifdef CONFIG_USE_OF
 
-static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
-	{},
-};
-
 void __init sh73a0_add_standard_devices_dt(void)
 {
 	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", .id = -1, };
@@ -971,8 +952,7 @@ void __init sh73a0_add_standard_devices_dt(void)
 
 	platform_add_devices(sh73a0_devices_dt,
 			     ARRAY_SIZE(sh73a0_devices_dt));
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     sh73a0_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
 	/* Instantiate cpufreq-cpu0 */
 	platform_device_register_full(&devinfo);
@@ -988,7 +968,6 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
 	.map_io		= sh73a0_map_io,
 	.init_early	= sh73a0_init_delay,
 	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= irqchip_init,
 	.init_machine	= sh73a0_add_standard_devices_dt,
 	.dt_compat	= sh73a0_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S
index 53f4840..9782862 100644
--- a/arch/arm/mach-shmobile/sleep-sh7372.S
+++ b/arch/arm/mach-shmobile/sleep-sh7372.S
@@ -41,6 +41,7 @@
 sh7372_resume_core_standby_sysc:
 	ldr     pc, 1f
 
+	.align	2
 	.globl	sh7372_cpu_resume
 sh7372_cpu_resume:
 1:	.space	4
@@ -96,6 +97,7 @@ sh7372_do_idle_sysc:
 1:
 	b      1b
 
+	.align	2
 kernel_flush:
 	.word v7_flush_dcache_all
 #endif
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 22a05a8..522de5e 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -29,41 +29,38 @@
 #include <asm/smp_scu.h>
 
 #define EMEV2_SCU_BASE 0x1e000000
+#define EMEV2_SMU_BASE 0xe0110000
+#define SMU_GENERAL_REG0 0x7c0
 
 static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
+	int ret;
+
+	ret = shmobile_smp_scu_boot_secondary(cpu, idle);
+	if (ret)
+		return ret;
+
 	arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
 	return 0;
 }
 
 static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
 {
-	scu_enable(shmobile_scu_base);
-
-	/* Tell ROM loader about our vector (in headsmp-scu.S, headsmp.S) */
-	emev2_set_boot_vector(__pa(shmobile_boot_vector));
-	shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
-	shmobile_boot_arg = (unsigned long)shmobile_scu_base;
-
-	/* enable cache coherency on booting CPU */
-	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
-}
+	void __iomem *smu;
 
-static void __init emev2_smp_init_cpus(void)
-{
-	unsigned int ncores;
+	/* Tell ROM loader about our vector (in headsmp.S) */
+	smu = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
+	if (smu) {
+		iowrite32(__pa(shmobile_boot_vector), smu + SMU_GENERAL_REG0);
+		iounmap(smu);
+	}
 
-	/* setup EMEV2 specific SCU base */
+	/* setup EMEV2 specific SCU bits */
 	shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
-	emev2_clock_init(); /* need ioremapped SMU */
-
-	ncores = shmobile_scu_base ? scu_get_core_count(shmobile_scu_base) : 1;
-
-	shmobile_smp_init_cpus(ncores);
+	shmobile_smp_scu_prepare_cpus(max_cpus);
 }
 
 struct smp_operations emev2_smp_ops __initdata = {
-	.smp_init_cpus		= emev2_smp_init_cpus,
 	.smp_prepare_cpus	= emev2_smp_prepare_cpus,
 	.smp_boot_secondary	= emev2_boot_secondary,
 };
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 9bdf810..0f05e9f 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -84,30 +84,34 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
 static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	struct r8a7779_pm_ch *ch = NULL;
-	int ret = -EIO;
+	unsigned int lcpu = cpu_logical_map(cpu);
+	int ret;
 
-	cpu = cpu_logical_map(cpu);
+	ret = shmobile_smp_scu_boot_secondary(cpu, idle);
+	if (ret)
+		return ret;
 
-	if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
-		ch = r8a7779_ch_cpu[cpu];
+	if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
+		ch = r8a7779_ch_cpu[lcpu];
 
 	if (ch)
 		ret = r8a7779_sysc_power_up(ch);
+	else
+		ret = -EIO;
 
 	return ret;
 }
 
 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
-	scu_enable(shmobile_scu_base);
-
 	/* Map the reset vector (in headsmp-scu.S, headsmp.S) */
 	__raw_writel(__pa(shmobile_boot_vector), AVECR);
 	shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
 	shmobile_boot_arg = (unsigned long)shmobile_scu_base;
 
-	/* enable cache coherency on booting CPU */
-	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
+	/* setup r8a7779 specific SCU bits */
+	shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
+	shmobile_smp_scu_prepare_cpus(max_cpus);
 
 	r8a7779_pm_init();
 
@@ -117,56 +121,15 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 	r8a7779_platform_cpu_kill(3);
 }
 
-static void __init r8a7779_smp_init_cpus(void)
-{
-	/* setup r8a7779 specific SCU base */
-	shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
-
-	shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
-static int r8a7779_scu_psr_core_disabled(int cpu)
-{
-	unsigned long mask = 3 << (cpu * 8);
-
-	if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
-		return 1;
-
-	return 0;
-}
-
 static int r8a7779_cpu_kill(unsigned int cpu)
 {
-	int k;
-
-	/* this function is running on another CPU than the offline target,
-	 * here we need wait for shutdown code in platform_cpu_die() to
-	 * finish before asking SoC-specific code to power off the CPU core.
-	 */
-	for (k = 0; k < 1000; k++) {
-		if (r8a7779_scu_psr_core_disabled(cpu))
-			return r8a7779_platform_cpu_kill(cpu);
-
-		mdelay(1);
-	}
+	if (shmobile_smp_scu_cpu_kill(cpu))
+		return r8a7779_platform_cpu_kill(cpu);
 
 	return 0;
 }
 
-static void r8a7779_cpu_die(unsigned int cpu)
-{
-	dsb();
-	flush_cache_all();
-
-	/* disable cache coherency */
-	scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
-
-	/* Endless loop until power off from r8a7779_cpu_kill() */
-	while (1)
-		cpu_do_idle();
-}
-
 static int r8a7779_cpu_disable(unsigned int cpu)
 {
 	/* only CPU1->3 have power domains, do not allow hotplug of CPU0 */
@@ -175,12 +138,11 @@ static int r8a7779_cpu_disable(unsigned int cpu)
 #endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations r8a7779_smp_ops  __initdata = {
-	.smp_init_cpus		= r8a7779_smp_init_cpus,
 	.smp_prepare_cpus	= r8a7779_smp_prepare_cpus,
 	.smp_boot_secondary	= r8a7779_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
-	.cpu_kill		= r8a7779_cpu_kill,
-	.cpu_die		= r8a7779_cpu_die,
 	.cpu_disable		= r8a7779_cpu_disable,
+	.cpu_die		= shmobile_smp_scu_cpu_die,
+	.cpu_kill		= r8a7779_cpu_kill,
 #endif
 };
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index d5fc3ed..0baa244 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -20,14 +20,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <mach/common.h>
-#include <asm/cacheflush.h>
-#include <asm/smp_plat.h>
 #include <mach/sh73a0.h>
-#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
 
 #define WUPCR		IOMEM(0xe6151010)
@@ -36,8 +33,6 @@
 #define SBAR		IOMEM(0xe6180020)
 #define APARMBAREA	IOMEM(0xe6f10020)
 
-#define PSTR_SHUTDOWN_MODE	3
-
 #define SH73A0_SCU_BASE 0xf0000000
 
 #ifdef CONFIG_HAVE_ARM_TWD
@@ -50,69 +45,33 @@ void __init sh73a0_register_twd(void)
 
 static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	cpu = cpu_logical_map(cpu);
+	unsigned int lcpu = cpu_logical_map(cpu);
+	int ret;
 
-	if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
-		__raw_writel(1 << cpu, WUPCR);	/* wake up */
+	ret = shmobile_smp_scu_boot_secondary(cpu, idle);
+	if (ret)
+		return ret;
+
+	if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
+		__raw_writel(1 << lcpu, WUPCR);	/* wake up */
 	else
-		__raw_writel(1 << cpu, SRESCR);	/* reset */
+		__raw_writel(1 << lcpu, SRESCR);	/* reset */
 
 	return 0;
 }
 
 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
-	scu_enable(shmobile_scu_base);
-
-	/* Map the reset vector (in headsmp-scu.S, headsmp.S) */
+	/* Map the reset vector (in headsmp.S) */
 	__raw_writel(0, APARMBAREA);      /* 4k */
 	__raw_writel(__pa(shmobile_boot_vector), SBAR);
-	shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
-	shmobile_boot_arg = (unsigned long)shmobile_scu_base;
 
-	/* enable cache coherency on booting CPU */
-	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
-}
-
-static void __init sh73a0_smp_init_cpus(void)
-{
-	/* setup sh73a0 specific SCU base */
+	/* setup sh73a0 specific SCU bits */
 	shmobile_scu_base = IOMEM(SH73A0_SCU_BASE);
-
-	shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
+	shmobile_smp_scu_prepare_cpus(max_cpus);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int sh73a0_cpu_kill(unsigned int cpu)
-{
-
-	int k;
-	u32 pstr;
-
-	/*
-	 * wait until the power status register confirms the shutdown of the
-	 * offline target
-	 */
-	for (k = 0; k < 1000; k++) {
-		pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3;
-		if (pstr == PSTR_SHUTDOWN_MODE)
-			return 1;
-
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-static void sh73a0_cpu_die(unsigned int cpu)
-{
-	/* Set power off mode. This takes the CPU out of the MP cluster */
-	scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
-
-	/* Enter shutdown mode */
-	cpu_do_idle();
-}
-
 static int sh73a0_cpu_disable(unsigned int cpu)
 {
 	return 0; /* CPU0 and CPU1 supported */
@@ -120,12 +79,11 @@ static int sh73a0_cpu_disable(unsigned int cpu)
 #endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations sh73a0_smp_ops __initdata = {
-	.smp_init_cpus		= sh73a0_smp_init_cpus,
 	.smp_prepare_cpus	= sh73a0_smp_prepare_cpus,
 	.smp_boot_secondary	= sh73a0_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
-	.cpu_kill		= sh73a0_cpu_kill,
-	.cpu_die		= sh73a0_cpu_die,
 	.cpu_disable		= sh73a0_cpu_disable,
+	.cpu_die		= shmobile_smp_scu_cpu_die,
+	.cpu_kill		= shmobile_smp_scu_cpu_kill,
 #endif
 };
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index f321dbe..62d7052 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -59,7 +59,3 @@ void __init shmobile_earlytimer_init(void)
 	late_time_init = shmobile_late_time_init;
 }
 
-void __init shmobile_timer_init(void)
-{
-	clocksource_of_init();
-}
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
index 442917e..df0d59a 100644
--- a/arch/arm/mach-spear/Kconfig
+++ b/arch/arm/mach-spear/Kconfig
@@ -23,7 +23,7 @@ config ARCH_SPEAR13XX
 	select CPU_V7
 	select GPIO_SPEAR_SPICS
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
diff --git a/arch/arm/mach-spear/include/mach/debug-macro.S b/arch/arm/mach-spear/include/mach/debug-macro.S
deleted file mode 100644
index 75b05ad..0000000
--- a/arch/arm/mach-spear/include/mach/debug-macro.S
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/debug-macro.S
- *
- * Debugging macro include header for spear platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/amba/serial.h>
-#include <mach/spear.h>
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
-		mov	\rv, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
-		.endm
-
-		.macro	senduart, rd, rx
-		strb	\rd, [\rx, #UART01x_DR]			@ ASC_TX_BUFFER
-		.endm
-
-		.macro	waituart, rd, rx
-1001:		ldr	\rd, [\rx, #UART01x_FR]			@ FLAG REGISTER
-		tst	\rd, #UART01x_FR_TXFF			@ TX_FULL
-		bne	1001b
-		.endm
-
-		.macro	busyuart, rd, rx
-1002:		ldr	\rd, [\rx, #UART01x_FR]			@ FLAG REGISTER
-		tst	\rd, #UART011_FR_TXFE			@ TX_EMPTY
-		beq	1002b
-		.endm
diff --git a/arch/arm/mach-spear/include/mach/spear.h b/arch/arm/mach-spear/include/mach/spear.h
index cf3a536..5cdc53d 100644
--- a/arch/arm/mach-spear/include/mach/spear.h
+++ b/arch/arm/mach-spear/include/mach/spear.h
@@ -39,7 +39,6 @@
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR_ICM1_UART_BASE
-#define VA_SPEAR_DBG_UART_BASE		VA_SPEAR_ICM1_UART_BASE
 
 /* Sysctl base for spear platform */
 #define SPEAR_SYS_CTRL_BASE		SPEAR_ICM3_SYS_CTRL_BASE
@@ -86,7 +85,6 @@
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE			UART_BASE
-#define VA_SPEAR_DBG_UART_BASE			VA_UART_BASE
 
 #endif /* SPEAR13XX */
 
diff --git a/arch/arm/mach-sti/headsmp.S b/arch/arm/mach-sti/headsmp.S
index 78ebc75..4c09bae 100644
--- a/arch/arm/mach-sti/headsmp.S
+++ b/arch/arm/mach-sti/headsmp.S
@@ -16,8 +16,6 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
-	__INIT
-
 /*
  * ST specific entry point for secondary CPUs.  This provides
  * a "holding pen" into which all secondary cores are held until we're
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index ef3a8da..50db6bf 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -2,18 +2,24 @@ config ARCH_TEGRA
 	bool "NVIDIA Tegra" if ARCH_MULTI_V7
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
+	select ARM_GIC
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select CLKSRC_OF
 	select COMMON_CLK
+	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_CLK
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
+	select PINCTRL
 	select SOC_BUS
 	select SPARSE_IRQ
+	select USB_ARCH_HAS_EHCI if USB_SUPPORT
+	select USB_ULPI if USB_PHY
+	select USB_ULPI_VIEWPORT if USB_PHY
 	select USE_OF
 	help
 	  This enables support for NVIDIA Tegra based systems.
@@ -27,15 +33,9 @@ config ARCH_TEGRA_2x_SOC
 	select ARM_ERRATA_720789
 	select ARM_ERRATA_754327 if SMP
 	select ARM_ERRATA_764369 if SMP
-	select ARM_GIC
-	select CPU_V7
-	select PINCTRL
 	select PINCTRL_TEGRA20
 	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
-	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select USB_ULPI if USB_PHY
-	select USB_ULPI_VIEWPORT if USB_PHY
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -44,14 +44,8 @@ config ARCH_TEGRA_3x_SOC
 	bool "Enable support for Tegra30 family"
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_764369 if SMP
-	select ARM_GIC
-	select CPU_V7
-	select PINCTRL
 	select PINCTRL_TEGRA30
 	select PL310_ERRATA_769419 if CACHE_L2X0
-	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select USB_ULPI if USB_PHY
-	select USB_ULPI_VIEWPORT if USB_PHY
 	help
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -59,10 +53,8 @@ config ARCH_TEGRA_3x_SOC
 config ARCH_TEGRA_114_SOC
 	bool "Enable support for Tegra114 family"
 	select HAVE_ARM_ARCH_TIMER
-	select ARM_GIC
+	select ARM_ERRATA_798181
 	select ARM_L1_CACHE_SHIFT_6
-	select CPU_V7
-	select PINCTRL
 	select PINCTRL_TEGRA114
 	help
 	  Support for NVIDIA Tegra T114 processor family, based on the
diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h
index 32f8eb3..5900cc4 100644
--- a/arch/arm/mach-tegra/common.h
+++ b/arch/arm/mach-tegra/common.h
@@ -2,4 +2,3 @@ extern struct smp_operations tegra_smp_ops;
 
 extern int tegra_cpu_kill(unsigned int cpu);
 extern void tegra_cpu_die(unsigned int cpu);
-extern int tegra_cpu_disable(unsigned int cpu);
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
index 1d1c602..e0b8730 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -17,15 +17,64 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/clockchips.h>
 
 #include <asm/cpuidle.h>
+#include <asm/suspend.h>
+#include <asm/smp_plat.h>
+
+#include "pm.h"
+#include "sleep.h"
+
+#ifdef CONFIG_PM_SLEEP
+#define TEGRA114_MAX_STATES 2
+#else
+#define TEGRA114_MAX_STATES 1
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra114_idle_power_down(struct cpuidle_device *dev,
+				    struct cpuidle_driver *drv,
+				    int index)
+{
+	local_fiq_disable();
+
+	tegra_set_cpu_in_lp2();
+	cpu_pm_enter();
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+
+	cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+
+	cpu_pm_exit();
+	tegra_clear_cpu_in_lp2();
+
+	local_fiq_enable();
+
+	return index;
+}
+#endif
 
 static struct cpuidle_driver tegra_idle_driver = {
 	.name = "tegra_idle",
 	.owner = THIS_MODULE,
-	.state_count = 1,
+	.state_count = TEGRA114_MAX_STATES,
 	.states = {
 		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+#ifdef CONFIG_PM_SLEEP
+		[1] = {
+			.enter			= tegra114_idle_power_down,
+			.exit_latency		= 500,
+			.target_residency	= 1000,
+			.power_usage		= 0,
+			.flags			= CPUIDLE_FLAG_TIME_VALID,
+			.name			= "powered-down",
+			.desc			= "CPU power gated",
+		},
+#endif
 	},
 };
 
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index b477ef3..5348543 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -86,6 +86,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
 		reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
 		break;
 	case TEGRA30:
+	case TEGRA114:
 		/* clear wfe bitmap */
 		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
 		/* clear wfi bitmap */
@@ -123,6 +124,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
 		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
 		break;
 	case TEGRA30:
+	case TEGRA114:
 		/* clear wfe bitmap */
 		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
 		/* clear wfi bitmap */
diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h
index 7a29bae..c89aac6 100644
--- a/arch/arm/mach-tegra/flowctrl.h
+++ b/arch/arm/mach-tegra/flowctrl.h
@@ -28,9 +28,18 @@
 #define FLOW_CTRL_SCLK_RESUME		(1 << 27)
 #define FLOW_CTRL_HALT_CPU_IRQ		(1 << 10)
 #define	FLOW_CTRL_HALT_CPU_FIQ		(1 << 8)
+#define FLOW_CTRL_HALT_LIC_IRQ		(1 << 11)
+#define FLOW_CTRL_HALT_LIC_FIQ		(1 << 10)
+#define FLOW_CTRL_HALT_GIC_IRQ		(1 << 9)
+#define FLOW_CTRL_HALT_GIC_FIQ		(1 << 8)
 #define FLOW_CTRL_CPU0_CSR		0x8
 #define	FLOW_CTRL_CSR_INTR_FLAG		(1 << 15)
 #define FLOW_CTRL_CSR_EVENT_FLAG	(1 << 14)
+#define FLOW_CTRL_CSR_ENABLE_EXT_CRAIL	(1 << 13)
+#define FLOW_CTRL_CSR_ENABLE_EXT_NCPU	(1 << 12)
+#define FLOW_CTRL_CSR_ENABLE_EXT_MASK ( \
+		FLOW_CTRL_CSR_ENABLE_EXT_NCPU | \
+		FLOW_CTRL_CSR_ENABLE_EXT_CRAIL)
 #define FLOW_CTRL_CSR_ENABLE		(1 << 0)
 #define FLOW_CTRL_HALT_CPU1_EVENTS	0x14
 #define FLOW_CTRL_CPU1_CSR		0x18
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 045c16f..2072e73 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -6,6 +6,7 @@
         .section ".text.head", "ax"
 
 ENTRY(tegra_secondary_startup)
-        bl      v7_invalidate_l1
+        check_cpu_part_num 0xc09, r8, r9
+        bleq    v7_invalidate_l1
         b       secondary_startup
 ENDPROC(tegra_secondary_startup)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index a52c10e..04de2e8 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -37,7 +37,7 @@ int tegra_cpu_kill(unsigned cpu)
 void __ref tegra_cpu_die(unsigned int cpu)
 {
 	/* Clean L1 data cache */
-	tegra_disable_clean_inv_dcache();
+	tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
 
 	/* Shut down the current CPU. */
 	tegra_hotplug_shutdown();
@@ -46,17 +46,6 @@ void __ref tegra_cpu_die(unsigned int cpu)
 	BUG();
 }
 
-int tegra_cpu_disable(unsigned int cpu)
-{
-	switch (tegra_chip_id) {
-	case TEGRA20:
-	case TEGRA30:
-		return cpu == 0 ? -EPERM : 0;
-	default:
-		return 0;
-	}
-}
-
 void __init tegra_hotplug_init(void)
 {
 	if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 0de4eed..1a74d56 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -18,10 +18,12 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/cpu_pm.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/syscore_ops.h>
 
@@ -65,6 +67,7 @@ static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
 static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
 
 static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+static void __iomem *tegra_gic_cpu_base;
 #endif
 
 bool tegra_pending_sgi(void)
@@ -213,8 +216,43 @@ int tegra_legacy_irq_syscore_init(void)
 
 	return 0;
 }
+
+static int tegra_gic_notifier(struct notifier_block *self,
+			      unsigned long cmd, void *v)
+{
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		writel_relaxed(0x1E0, tegra_gic_cpu_base + GIC_CPU_CTRL);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block tegra_gic_notifier_block = {
+	.notifier_call = tegra_gic_notifier,
+};
+
+static const struct of_device_id tegra114_dt_gic_match[] __initconst = {
+	{ .compatible = "arm,cortex-a15-gic" },
+	{ }
+};
+
+static void tegra114_gic_cpu_pm_registration(void)
+{
+	struct device_node *dn;
+
+	dn = of_find_matching_node(NULL, tegra114_dt_gic_match);
+	if (!dn)
+		return;
+
+	tegra_gic_cpu_base = of_iomap(dn, 1);
+
+	cpu_pm_register_notifier(&tegra_gic_notifier_block);
+}
 #else
 #define tegra_set_wake NULL
+static void tegra114_gic_cpu_pm_registration(void) { }
 #endif
 
 void __init tegra_init_irq(void)
@@ -252,4 +290,6 @@ void __init tegra_init_irq(void)
 	if (!of_have_populated_dt())
 		gic_init(0, 29, distbase,
 			IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+
+	tegra114_gic_cpu_pm_registration();
 }
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 97b33a2..2d02036 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -196,6 +196,5 @@ struct smp_operations tegra_smp_ops __initdata = {
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_kill		= tegra_cpu_kill,
 	.cpu_die		= tegra_cpu_die,
-	.cpu_disable		= tegra_cpu_disable,
 #endif
 };
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 261fec1..5792872 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -52,7 +52,9 @@ static void tegra_tear_down_cpu_init(void)
 			tegra_tear_down_cpu = tegra20_tear_down_cpu;
 		break;
 	case TEGRA30:
-		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
+	case TEGRA114:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
 			tegra_tear_down_cpu = tegra30_tear_down_cpu;
 		break;
 	}
@@ -171,10 +173,6 @@ void tegra_idle_lp2_last(void)
 enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 				enum tegra_suspend_mode mode)
 {
-	/* Tegra114 didn't support any suspending mode yet. */
-	if (tegra_chip_id == TEGRA114)
-		return TEGRA_SUSPEND_NONE;
-
 	/*
 	 * The Tegra devices only support suspending to LP2 currently.
 	 */
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index eb3fa4a..8345fcd 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+#include "flowctrl.h"
 #include "fuse.h"
 #include "pm.h"
 #include "pmc.h"
@@ -195,13 +196,26 @@ enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
 
 void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
 {
-	u32 reg;
+	u32 reg, csr_reg;
 	unsigned long rate = 0;
 
 	reg = tegra_pmc_readl(PMC_CTRL);
 	reg |= TEGRA_POWER_CPU_PWRREQ_OE;
 	reg &= ~TEGRA_POWER_EFFECT_LP0;
 
+	switch (tegra_chip_id) {
+	case TEGRA20:
+	case TEGRA30:
+		break;
+	default:
+		/* Turn off CRAIL */
+		csr_reg = flowctrl_read_cpu_csr(0);
+		csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
+		csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+		flowctrl_write_cpu_csr(0, csr_reg);
+		break;
+	}
+
 	switch (mode) {
 	case TEGRA_SUSPEND_LP2:
 		rate = clk_get_rate(tegra_pclk);
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 39dc9e7..34614bd 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -40,9 +40,12 @@
  *	  re-enabling sdram.
  *
  *	r6: SoC ID
+ *	r8: CPU part number
  */
 ENTRY(tegra_resume)
-	bl	v7_invalidate_l1
+	check_cpu_part_num 0xc09, r8, r9
+	bleq	v7_invalidate_l1
+	blne	tegra_init_l2_for_a15
 
 	cpu_id	r0
 	tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
@@ -70,7 +73,8 @@ no_cpu0_chk:
 	str	r1, [r2]
 1:
 
-	check_cpu_part_num 0xc09, r8, r9
+	mov32	r9, 0xc09
+	cmp	r8, r9
 	bne	not_ca9
 #ifdef CONFIG_HAVE_ARM_SCU
 	/* enable SCU */
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index e3f2417..f87721d 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -191,6 +191,7 @@ ENTRY(tegra20_sleep_cpu_secondary_finish)
 	mrc	p15, 0, r11, c1, c0, 1  @ save actlr before exiting coherency
 
 	/* Flush and disable the L1 data cache */
+	mov	r0, #TEGRA_FLUSH_CACHE_LOUIS
 	bl	tegra_disable_clean_inv_dcache
 
 	mov32	r0, TEGRA_PMC_VIRT + PMC_SCRATCH41
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index ada8821..ecad4ea 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -99,6 +99,8 @@ flow_ctrl_setting_for_lp2:
 	cmp	r10, #TEGRA30
 	moveq   r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT	@ For LP2
 	movne	r3, #FLOW_CTRL_WAITEVENT
+	orrne	r3, r3, #FLOW_CTRL_HALT_GIC_IRQ
+	orrne	r3, r3, #FLOW_CTRL_HALT_GIC_FIQ
 flow_ctrl_done:
 	cmp	r10, #TEGRA30
 	str	r3, [r2]
@@ -135,6 +137,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish)
 	mov	r7, lr
 
 	/* Flush and disable the L1 data cache */
+	mov 	r0, #TEGRA_FLUSH_CACHE_LOUIS
 	bl	tegra_disable_clean_inv_dcache
 
 	/* Powergate this CPU. */
@@ -172,8 +175,12 @@ tegra30_enter_sleep:
 	orr	r0, r0, #FLOW_CTRL_CSR_ENABLE
 	str	r0, [r6, r2]
 
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r10
+	cmp	r10, #TEGRA30
 	mov	r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
-	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
+	orreq	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
+	orrne   r0, r0, #FLOW_CTRL_HALT_LIC_IRQ | FLOW_CTRL_HALT_LIC_FIQ
+
 	cpu_to_halt_reg r2, r1
 	str	r0, [r6, r2]
 	dsb
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 9daaef2..8388113 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -56,7 +56,9 @@ ENTRY(tegra_disable_clean_inv_dcache)
 	isb
 
 	/* Flush the D-cache */
-	bl	v7_flush_dcache_louis
+	cmp	r0, #TEGRA_FLUSH_CACHE_ALL
+	blne	v7_flush_dcache_louis
+	bleq	v7_flush_dcache_all
 
 	/* Trun off coherency */
 	exit_smp r4, r5
@@ -67,15 +69,40 @@ ENDPROC(tegra_disable_clean_inv_dcache)
 
 #ifdef CONFIG_PM_SLEEP
 /*
+ * tegra_init_l2_for_a15
+ *
+ * set up the correct L2 cache data RAM latency
+ */
+ENTRY(tegra_init_l2_for_a15)
+	mrc	p15, 0, r0, c0, c0, 5
+	ubfx	r0, r0, #8, #4
+	tst	r0, #1				@ only need for cluster 0
+	bne	_exit_init_l2_a15
+
+	mrc	p15, 0x1, r0, c9, c0, 2
+	and	r0, r0, #7
+	cmp	r0, #2
+	bicne	r0, r0, #7
+	orrne	r0, r0, #2
+	mcrne	p15, 0x1, r0, c9, c0, 2
+_exit_init_l2_a15:
+
+	mov	pc, lr
+ENDPROC(tegra_init_l2_for_a15)
+
+/*
  * tegra_sleep_cpu_finish(unsigned long v2p)
  *
  * enters suspend in LP2 by turning off the mmu and jumping to
  * tegra?_tear_down_cpu
  */
 ENTRY(tegra_sleep_cpu_finish)
+	mov	r4, r0
 	/* Flush and disable the L1 data cache */
+	mov	r0, #TEGRA_FLUSH_CACHE_ALL
 	bl	tegra_disable_clean_inv_dcache
 
+	mov	r0, r4
 	mov32	r6, tegra_tear_down_cpu
 	ldr	r1, [r6]
 	add	r1, r1, r0
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 98b7da6..e907e40 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -41,6 +41,10 @@
 #define CPU_NOT_RESETTABLE	0
 #endif
 
+/* flag of tegra_disable_clean_inv_dcache to do LoUIS or all */
+#define TEGRA_FLUSH_CACHE_LOUIS	0
+#define TEGRA_FLUSH_CACHE_ALL	1
+
 #ifdef __ASSEMBLY__
 /* returns the offset of the flow controller halt register for a cpu */
 .macro cpu_to_halt_reg rd, rcpu
@@ -144,7 +148,7 @@ void tegra_pen_lock(void);
 void tegra_pen_unlock(void);
 void tegra_resume(void);
 int tegra_sleep_cpu_finish(unsigned long);
-void tegra_disable_clean_inv_dcache(void);
+void tegra_disable_clean_inv_dcache(u32 flag);
 
 #ifdef CONFIG_HOTPLUG_CPU
 void tegra20_hotplug_shutdown(void);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 0d1e412..fc97cfd 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -29,7 +29,6 @@
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/pda_power.h>
-#include <linux/platform_data/tegra_usb.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
@@ -46,40 +45,6 @@
 #include "fuse.h"
 #include "iomap.h"
 
-static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
-	.operating_mode = TEGRA_USB_OTG,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
-	.reset_gpio = -1,
-	.clk = "cdev2",
-};
-
-static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
-	.phy_config = &tegra_ehci2_ulpi_phy_config,
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
-		       &tegra_ehci1_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
-		       &tegra_ehci2_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
-		       &tegra_ehci3_pdata),
-	{}
-};
-
 static void __init tegra_dt_init(void)
 {
 	struct soc_device_attribute *soc_dev_attr;
@@ -112,8 +77,7 @@ static void __init tegra_dt_init(void)
 	 * devices
 	 */
 out:
-	of_platform_populate(NULL, of_default_bus_match_table,
-				tegra20_auxdata_lookup, parent);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 }
 
 static void __init trimslice_init(void)
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index b19b072..99a28d6 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -8,7 +8,7 @@ config ARCH_U8500
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	help
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index bf9b6be..fe1f3e2 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -4,7 +4,6 @@
 
 obj-y				:= cpu.o devices.o devices-common.o \
 				   id.o usb.o timer.o pm.o
-obj-$(CONFIG_CPU_IDLE)          += cpuidle.o
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_MOP500)	+= board-mop500.o board-mop500-sdi.o \
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
deleted file mode 100644
index a45dd09..0000000
--- a/arch/arm/mach-ux500/cpuidle.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM)
- *
- * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com>
- * and Jonas Aaberg <jonas.aberg@stericsson.com>.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/cpuidle.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-#include <linux/smp.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include <linux/platform_data/arm-ux500-pm.h>
-
-#include <asm/cpuidle.h>
-#include <asm/proc-fns.h>
-
-#include "db8500-regs.h"
-#include "id.h"
-
-static atomic_t master = ATOMIC_INIT(0);
-static DEFINE_SPINLOCK(master_lock);
-
-static inline int ux500_enter_idle(struct cpuidle_device *dev,
-				   struct cpuidle_driver *drv, int index)
-{
-	int this_cpu = smp_processor_id();
-	bool recouple = false;
-
-	if (atomic_inc_return(&master) == num_online_cpus()) {
-
-		/* With this lock, we prevent the other cpu to exit and enter
-		 * this function again and become the master */
-		if (!spin_trylock(&master_lock))
-			goto wfi;
-
-		/* decouple the gic from the A9 cores */
-		if (prcmu_gic_decouple()) {
-			spin_unlock(&master_lock);
-			goto out;
-		}
-
-		/* If an error occur, we will have to recouple the gic
-		 * manually */
-		recouple = true;
-
-		/* At this state, as the gic is decoupled, if the other
-		 * cpu is in WFI, we have the guarantee it won't be wake
-		 * up, so we can safely go to retention */
-		if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1))
-			goto out;
-
-		/* The prcmu will be in charge of watching the interrupts
-		 * and wake up the cpus */
-		if (prcmu_copy_gic_settings())
-			goto out;
-
-		/* Check in the meantime an interrupt did
-		 * not occur on the gic ... */
-		if (prcmu_gic_pending_irq())
-			goto out;
-
-		/* ... and the prcmu */
-		if (prcmu_pending_irq())
-			goto out;
-
-		/* Go to the retention state, the prcmu will wait for the
-		 * cpu to go WFI and this is what happens after exiting this
-		 * 'master' critical section */
-		if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
-			goto out;
-
-		/* When we switch to retention, the prcmu is in charge
-		 * of recoupling the gic automatically */
-		recouple = false;
-
-		spin_unlock(&master_lock);
-	}
-wfi:
-	cpu_do_idle();
-out:
-	atomic_dec(&master);
-
-	if (recouple) {
-		prcmu_gic_recouple();
-		spin_unlock(&master_lock);
-	}
-
-	return index;
-}
-
-static struct cpuidle_driver ux500_idle_driver = {
-	.name = "ux500_idle",
-	.owner = THIS_MODULE,
-	.states = {
-		ARM_CPUIDLE_WFI_STATE,
-		{
-			.enter		  = ux500_enter_idle,
-			.exit_latency	  = 70,
-			.target_residency = 260,
-			.flags		  = CPUIDLE_FLAG_TIME_VALID |
-			                    CPUIDLE_FLAG_TIMER_STOP,
-			.name		  = "ApIdle",
-			.desc		  = "ARM Retention",
-		},
-	},
-	.safe_state_index = 0,
-	.state_count = 2,
-};
-
-int __init ux500_idle_init(void)
-{
-	if (!(cpu_is_u8500_family() || cpu_is_ux540_family()))
-		return -ENODEV;
-
-	/* Configure wake up reasons */
-	prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
-			     PRCMU_WAKEUP(ABB));
-
-	return cpuidle_register(&ux500_idle_driver, NULL);
-}
-
-device_initcall(ux500_idle_init);
diff --git a/arch/arm/mach-versatile/include/mach/debug-macro.S b/arch/arm/mach-versatile/include/mach/debug-macro.S
deleted file mode 100644
index d0fbd7f..0000000
--- a/arch/arm/mach-versatile/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-versatile/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp,      #0x001F0000
-		orr	\rp, \rp, #0x00001000
-		orr	\rv, \rp, #0xf1000000	@ virtual base
-		orr	\rp, \rp,  #0x10000000	@ physical base
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index b8bbabe..4b5690f 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -10,7 +10,7 @@ config ARCH_VEXPRESS
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_CLK
 	select HAVE_PATA_PLATFORM
 	select HAVE_SMP
@@ -66,4 +66,13 @@ config ARCH_VEXPRESS_DCSCB
 	  This is needed to provide CPU and cluster power management
 	  on RTSM implementing big.LITTLE.
 
+config ARCH_VEXPRESS_TC2_PM
+	bool "Versatile Express TC2 power management"
+	depends on MCPM
+	select VEXPRESS_SPC
+	select ARM_CCI
+	help
+	  Support for CPU and cluster power management on Versatile Express
+	  with a TC2 (A15x2 A7x3) big.LITTLE core tile.
+
 endmenu
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 48ba89a..36ea824 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -7,5 +7,6 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
 obj-y					:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
 obj-$(CONFIG_ARCH_VEXPRESS_DCSCB)	+= dcscb.o	dcscb_setup.o
+obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM)	+= tc2_pm.o spc.o
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
diff --git a/arch/arm/mach-vexpress/dcscb.c b/arch/arm/mach-vexpress/dcscb.c
index 16d57a8..85fffa7 100644
--- a/arch/arm/mach-vexpress/dcscb.c
+++ b/arch/arm/mach-vexpress/dcscb.c
@@ -136,14 +136,29 @@ static void dcscb_power_down(void)
 		/*
 		 * Flush all cache levels for this cluster.
 		 *
-		 * A15/A7 can hit in the cache with SCTLR.C=0, so we don't need
-		 * a preliminary flush here for those CPUs.  At least, that's
-		 * the theory -- without the extra flush, Linux explodes on
-		 * RTSM (to be investigated).
+		 * To do so we do:
+		 * - Clear the SCTLR.C bit to prevent further cache allocations
+		 * - Flush the whole cache
+		 * - Clear the ACTLR "SMP" bit to disable local coherency
+		 *
+		 * Let's do it in the safest possible way i.e. with
+		 * no memory access within the following sequence
+		 * including to the stack.
 		 */
-		flush_cache_all();
-		set_cr(get_cr() & ~CR_C);
-		flush_cache_all();
+		asm volatile(
+		"mrc	p15, 0, r0, c1, c0, 0	@ get CR \n\t"
+		"bic	r0, r0, #"__stringify(CR_C)" \n\t"
+		"mcr	p15, 0, r0, c1, c0, 0	@ set CR \n\t"
+		"isb	\n\t"
+		"bl	v7_flush_dcache_all \n\t"
+		"clrex	\n\t"
+		"mrc	p15, 0, r0, c1, c0, 1	@ get AUXCR \n\t"
+		"bic	r0, r0, #(1 << 6)	@ disable local coherency \n\t"
+		"mcr	p15, 0, r0, c1, c0, 1	@ set AUXCR \n\t"
+		"isb	\n\t"
+		"dsb	"
+		: : : "r0","r1","r2","r3","r4","r5","r6","r7",
+		      "r9","r10","r11","lr","memory");
 
 		/*
 		 * This is a harmless no-op.  On platforms with a real
@@ -152,9 +167,6 @@ static void dcscb_power_down(void)
 		 */
 		outer_flush_all();
 
-		/* Disable local coherency by clearing the ACTLR "SMP" bit: */
-		set_auxcr(get_auxcr() & ~(1 << 6));
-
 		/*
 		 * Disable cluster-level coherency by masking
 		 * incoming snoops and DVM messages:
@@ -167,18 +179,22 @@ static void dcscb_power_down(void)
 
 		/*
 		 * Flush the local CPU cache.
-		 *
-		 * A15/A7 can hit in the cache with SCTLR.C=0, so we don't need
-		 * a preliminary flush here for those CPUs.  At least, that's
-		 * the theory -- without the extra flush, Linux explodes on
-		 * RTSM (to be investigated).
+		 * Let's do it in the safest possible way as above.
 		 */
-		flush_cache_louis();
-		set_cr(get_cr() & ~CR_C);
-		flush_cache_louis();
-
-		/* Disable local coherency by clearing the ACTLR "SMP" bit: */
-		set_auxcr(get_auxcr() & ~(1 << 6));
+		asm volatile(
+		"mrc	p15, 0, r0, c1, c0, 0	@ get CR \n\t"
+		"bic	r0, r0, #"__stringify(CR_C)" \n\t"
+		"mcr	p15, 0, r0, c1, c0, 0	@ set CR \n\t"
+		"isb	\n\t"
+		"bl	v7_flush_dcache_louis \n\t"
+		"clrex	\n\t"
+		"mrc	p15, 0, r0, c1, c0, 1	@ get AUXCR \n\t"
+		"bic	r0, r0, #(1 << 6)	@ disable local coherency \n\t"
+		"mcr	p15, 0, r0, c1, c0, 1	@ set AUXCR \n\t"
+		"isb	\n\t"
+		"dsb	"
+		: : : "r0","r1","r2","r3","r4","r5","r6","r7",
+		      "r9","r10","r11","lr","memory");
 	}
 
 	__mcpm_cpu_down(cpu, cluster);
diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
new file mode 100644
index 0000000..6c18225
--- /dev/null
+++ b/arch/arm/mach-vexpress/spc.c
@@ -0,0 +1,249 @@
+/*
+ * Versatile Express Serial Power Controller (SPC) support
+ *
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * Authors: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+ *          Achin Gupta           <achin.gupta@arm.com>
+ *          Lorenzo Pieralisi     <lorenzo.pieralisi@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/vexpress.h>
+
+#include <asm/cacheflush.h>
+
+#define SPCLOG "vexpress-spc: "
+
+/* SCC conf registers */
+#define A15_CONF		0x400
+#define SYS_INFO		0x700
+
+/* SPC registers base */
+#define SPC_BASE		0xB00
+
+/* SPC wake-up IRQs status and mask */
+#define WAKE_INT_MASK		(SPC_BASE + 0x24)
+#define WAKE_INT_RAW		(SPC_BASE + 0x28)
+#define WAKE_INT_STAT		(SPC_BASE + 0x2c)
+/* SPC power down registers */
+#define A15_PWRDN_EN		(SPC_BASE + 0x30)
+#define A7_PWRDN_EN		(SPC_BASE + 0x34)
+/* SPC per-CPU mailboxes */
+#define A15_BX_ADDR0		(SPC_BASE + 0x68)
+#define A7_BX_ADDR0		(SPC_BASE + 0x78)
+
+/* wake-up interrupt masks */
+#define GBL_WAKEUP_INT_MSK	(0x3 << 10)
+
+/* TC2 static dual-cluster configuration */
+#define MAX_CLUSTERS		2
+
+struct ve_spc_drvdata {
+	void __iomem *baseaddr;
+	/*
+	 * A15s cluster identifier
+	 * It corresponds to A15 processors MPIDR[15:8] bitfield
+	 */
+	u32 a15_clusid;
+};
+
+static struct ve_spc_drvdata *info;
+
+static inline bool cluster_is_a15(u32 cluster)
+{
+	return cluster == info->a15_clusid;
+}
+
+/**
+ * ve_spc_global_wakeup_irq()
+ *
+ * Function to set/clear global wakeup IRQs. Not protected by locking since
+ * it might be used in code paths where normal cacheable locks are not
+ * working. Locking must be provided by the caller to ensure atomicity.
+ *
+ * @set: if true, global wake-up IRQs are set, if false they are cleared
+ */
+void ve_spc_global_wakeup_irq(bool set)
+{
+	u32 reg;
+
+	reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
+
+	if (set)
+		reg |= GBL_WAKEUP_INT_MSK;
+	else
+		reg &= ~GBL_WAKEUP_INT_MSK;
+
+	writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
+}
+
+/**
+ * ve_spc_cpu_wakeup_irq()
+ *
+ * Function to set/clear per-CPU wake-up IRQs. Not protected by locking since
+ * it might be used in code paths where normal cacheable locks are not
+ * working. Locking must be provided by the caller to ensure atomicity.
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ * @cpu: mpidr[7:0] bitfield describing cpu affinity level
+ * @set: if true, wake-up IRQs are set, if false they are cleared
+ */
+void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set)
+{
+	u32 mask, reg;
+
+	if (cluster >= MAX_CLUSTERS)
+		return;
+
+	mask = 1 << cpu;
+
+	if (!cluster_is_a15(cluster))
+		mask <<= 4;
+
+	reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
+
+	if (set)
+		reg |= mask;
+	else
+		reg &= ~mask;
+
+	writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
+}
+
+/**
+ * ve_spc_set_resume_addr() - set the jump address used for warm boot
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ * @cpu: mpidr[7:0] bitfield describing cpu affinity level
+ * @addr: physical resume address
+ */
+void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr)
+{
+	void __iomem *baseaddr;
+
+	if (cluster >= MAX_CLUSTERS)
+		return;
+
+	if (cluster_is_a15(cluster))
+		baseaddr = info->baseaddr + A15_BX_ADDR0 + (cpu << 2);
+	else
+		baseaddr = info->baseaddr + A7_BX_ADDR0 + (cpu << 2);
+
+	writel_relaxed(addr, baseaddr);
+}
+
+/**
+ * ve_spc_get_nr_cpus() - get number of cpus in a cluster
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ *
+ * Return: > 0 number of cpus in the cluster
+ *         or 0 if cluster number invalid
+ */
+u32 ve_spc_get_nr_cpus(u32 cluster)
+{
+	u32 val;
+
+	if (cluster >= MAX_CLUSTERS)
+		return 0;
+
+	val = readl_relaxed(info->baseaddr + SYS_INFO);
+	val = cluster_is_a15(cluster) ? (val >> 16) : (val >> 20);
+	return val & 0xf;
+}
+
+/**
+ * ve_spc_powerdown()
+ *
+ * Function to enable/disable cluster powerdown. Not protected by locking
+ * since it might be used in code paths where normal cacheable locks are not
+ * working. Locking must be provided by the caller to ensure atomicity.
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ * @enable: if true enables powerdown, if false disables it
+ */
+void ve_spc_powerdown(u32 cluster, bool enable)
+{
+	u32 pwdrn_reg;
+
+	if (cluster >= MAX_CLUSTERS)
+		return;
+
+	pwdrn_reg = cluster_is_a15(cluster) ? A15_PWRDN_EN : A7_PWRDN_EN;
+	writel_relaxed(enable, info->baseaddr + pwdrn_reg);
+}
+
+static int __init ve_spc_probe(void)
+{
+	int ret;
+	struct device_node *dn;
+
+	dn = of_find_compatible_node(NULL, NULL,
+				     "arm,vexpress-scc,v2p-ca15_a7");
+
+	if (!dn)
+		return -ENODEV;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		pr_err(SPCLOG "unable to allocate mem\n");
+		return -ENOMEM;
+	}
+
+	info->baseaddr = of_iomap(dn, 0);
+	if (!info->baseaddr) {
+		pr_err(SPCLOG "unable to ioremap memory\n");
+		ret = -ENXIO;
+		goto mem_free;
+	}
+
+	info->a15_clusid = readl_relaxed(info->baseaddr + A15_CONF) & 0xf;
+
+	/*
+	 * Multi-cluster systems may need this data when non-coherent, during
+	 * cluster power-up/power-down. Make sure driver info reaches main
+	 * memory.
+	 */
+	sync_cache_w(info);
+	sync_cache_w(&info);
+
+	return 0;
+
+mem_free:
+	kfree(info);
+	return ret;
+}
+
+/**
+ * ve_spc_init()
+ *
+ * Function exported to manage pre early_initcall initialization.
+ * SPC code is needed very early in the boot process to bring CPUs out of
+ * reset and initialize power management back-end so an init interface is
+ * provided to platform code to allow early initialization. The init
+ * interface can be removed as soon as the DT layer and platform bus allow
+ * platform device creation and probing before SMP boot.
+ */
+int __init ve_spc_init(void)
+{
+	static int ve_spc_init_status __initdata = -EAGAIN;
+
+	if (ve_spc_init_status == -EAGAIN)
+		ve_spc_init_status = ve_spc_probe();
+
+	return ve_spc_init_status;
+}
diff --git a/arch/arm/mach-vexpress/spc.h b/arch/arm/mach-vexpress/spc.h
new file mode 100644
index 0000000..f6b87fc
--- /dev/null
+++ b/arch/arm/mach-vexpress/spc.h
@@ -0,0 +1,25 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+
+#ifndef __SPC_H_
+#define __SPC_H_
+
+int __init ve_spc_init(void);
+void ve_spc_global_wakeup_irq(bool set);
+void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
+void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
+u32 ve_spc_get_nr_cpus(u32 cluster);
+void ve_spc_powerdown(u32 cluster, bool enable);
+
+#endif
diff --git a/arch/arm/mach-vexpress/tc2_pm.c b/arch/arm/mach-vexpress/tc2_pm.c
new file mode 100644
index 0000000..79cf4bc
--- /dev/null
+++ b/arch/arm/mach-vexpress/tc2_pm.c
@@ -0,0 +1,305 @@
+/*
+ * arch/arm/mach-vexpress/tc2_pm.c - TC2 power management support
+ *
+ * Created by:	Nicolas Pitre, October 2012
+ * Copyright:	(C) 2012-2013  Linaro Limited
+ *
+ * Some portions of this file were originally written by Achin Gupta
+ * Copyright:   (C) 2012  ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+
+#include <asm/mcpm.h>
+#include <asm/proc-fns.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/cp15.h>
+
+#include <linux/arm-cci.h>
+
+#include "spc.h"
+
+/*
+ * We can't use regular spinlocks. In the switcher case, it is possible
+ * for an outbound CPU to call power_down() after its inbound counterpart
+ * is already live using the same logical CPU number which trips lockdep
+ * debugging.
+ */
+static arch_spinlock_t tc2_pm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+
+#define TC2_CLUSTERS			2
+#define TC2_MAX_CPUS_PER_CLUSTER	3
+
+/* Keep per-cpu usage count to cope with unordered up/down requests */
+static int tc2_pm_use_count[TC2_MAX_CPUS_PER_CLUSTER][TC2_CLUSTERS];
+
+#define tc2_cluster_unused(cluster) \
+	(!tc2_pm_use_count[0][cluster] && \
+	 !tc2_pm_use_count[1][cluster] && \
+	 !tc2_pm_use_count[2][cluster])
+
+static int tc2_pm_power_up(unsigned int cpu, unsigned int cluster)
+{
+	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+	if (cluster >= TC2_CLUSTERS || cpu >= ve_spc_get_nr_cpus(cluster))
+		return -EINVAL;
+
+	/*
+	 * Since this is called with IRQs enabled, and no arch_spin_lock_irq
+	 * variant exists, we need to disable IRQs manually here.
+	 */
+	local_irq_disable();
+	arch_spin_lock(&tc2_pm_lock);
+
+	if (tc2_cluster_unused(cluster))
+		ve_spc_powerdown(cluster, false);
+
+	tc2_pm_use_count[cpu][cluster]++;
+	if (tc2_pm_use_count[cpu][cluster] == 1) {
+		ve_spc_set_resume_addr(cluster, cpu,
+				       virt_to_phys(mcpm_entry_point));
+		ve_spc_cpu_wakeup_irq(cluster, cpu, true);
+	} else if (tc2_pm_use_count[cpu][cluster] != 2) {
+		/*
+		 * The only possible values are:
+		 * 0 = CPU down
+		 * 1 = CPU (still) up
+		 * 2 = CPU requested to be up before it had a chance
+		 *     to actually make itself down.
+		 * Any other value is a bug.
+		 */
+		BUG();
+	}
+
+	arch_spin_unlock(&tc2_pm_lock);
+	local_irq_enable();
+
+	return 0;
+}
+
+static void tc2_pm_down(u64 residency)
+{
+	unsigned int mpidr, cpu, cluster;
+	bool last_man = false, skip_wfi = false;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+	BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
+
+	__mcpm_cpu_going_down(cpu, cluster);
+
+	arch_spin_lock(&tc2_pm_lock);
+	BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
+	tc2_pm_use_count[cpu][cluster]--;
+	if (tc2_pm_use_count[cpu][cluster] == 0) {
+		ve_spc_cpu_wakeup_irq(cluster, cpu, true);
+		if (tc2_cluster_unused(cluster)) {
+			ve_spc_powerdown(cluster, true);
+			ve_spc_global_wakeup_irq(true);
+			last_man = true;
+		}
+	} else if (tc2_pm_use_count[cpu][cluster] == 1) {
+		/*
+		 * A power_up request went ahead of us.
+		 * Even if we do not want to shut this CPU down,
+		 * the caller expects a certain state as if the WFI
+		 * was aborted.  So let's continue with cache cleaning.
+		 */
+		skip_wfi = true;
+	} else
+		BUG();
+
+	if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
+		arch_spin_unlock(&tc2_pm_lock);
+
+		if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A15) {
+			/*
+			 * On the Cortex-A15 we need to disable
+			 * L2 prefetching before flushing the cache.
+			 */
+			asm volatile(
+			"mcr	p15, 1, %0, c15, c0, 3 \n\t"
+			"isb	\n\t"
+			"dsb	"
+			: : "r" (0x400) );
+		}
+
+		/*
+		 * We need to disable and flush the whole (L1 and L2) cache.
+		 * Let's do it in the safest possible way i.e. with
+		 * no memory access within the following sequence
+		 * including the stack.
+		 */
+		asm volatile(
+		"mrc	p15, 0, r0, c1, c0, 0	@ get CR \n\t"
+		"bic	r0, r0, #"__stringify(CR_C)" \n\t"
+		"mcr	p15, 0, r0, c1, c0, 0	@ set CR \n\t"
+		"isb	\n\t"
+		"bl	v7_flush_dcache_all \n\t"
+		"clrex	\n\t"
+		"mrc	p15, 0, r0, c1, c0, 1	@ get AUXCR \n\t"
+		"bic	r0, r0, #(1 << 6)	@ disable local coherency \n\t"
+		"mcr	p15, 0, r0, c1, c0, 1	@ set AUXCR \n\t"
+		"isb	\n\t"
+		"dsb	"
+		: : : "r0","r1","r2","r3","r4","r5","r6","r7",
+		      "r9","r10","r11","lr","memory");
+
+		cci_disable_port_by_cpu(mpidr);
+
+		__mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+	} else {
+		/*
+		 * If last man then undo any setup done previously.
+		 */
+		if (last_man) {
+			ve_spc_powerdown(cluster, false);
+			ve_spc_global_wakeup_irq(false);
+		}
+
+		arch_spin_unlock(&tc2_pm_lock);
+
+		/*
+		 * We need to disable and flush only the L1 cache.
+		 * Let's do it in the safest possible way as above.
+		 */
+		asm volatile(
+		"mrc	p15, 0, r0, c1, c0, 0	@ get CR \n\t"
+		"bic	r0, r0, #"__stringify(CR_C)" \n\t"
+		"mcr	p15, 0, r0, c1, c0, 0	@ set CR \n\t"
+		"isb	\n\t"
+		"bl	v7_flush_dcache_louis \n\t"
+		"clrex	\n\t"
+		"mrc	p15, 0, r0, c1, c0, 1	@ get AUXCR \n\t"
+		"bic	r0, r0, #(1 << 6)	@ disable local coherency \n\t"
+		"mcr	p15, 0, r0, c1, c0, 1	@ set AUXCR \n\t"
+		"isb	\n\t"
+		"dsb	"
+		: : : "r0","r1","r2","r3","r4","r5","r6","r7",
+		      "r9","r10","r11","lr","memory");
+	}
+
+	__mcpm_cpu_down(cpu, cluster);
+
+	/* Now we are prepared for power-down, do it: */
+	if (!skip_wfi)
+		wfi();
+
+	/* Not dead at this point?  Let our caller cope. */
+}
+
+static void tc2_pm_power_down(void)
+{
+	tc2_pm_down(0);
+}
+
+static void tc2_pm_suspend(u64 residency)
+{
+	unsigned int mpidr, cpu, cluster;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+	ve_spc_set_resume_addr(cluster, cpu, virt_to_phys(mcpm_entry_point));
+	tc2_pm_down(residency);
+}
+
+static void tc2_pm_powered_up(void)
+{
+	unsigned int mpidr, cpu, cluster;
+	unsigned long flags;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+	BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
+
+	local_irq_save(flags);
+	arch_spin_lock(&tc2_pm_lock);
+
+	if (tc2_cluster_unused(cluster)) {
+		ve_spc_powerdown(cluster, false);
+		ve_spc_global_wakeup_irq(false);
+	}
+
+	if (!tc2_pm_use_count[cpu][cluster])
+		tc2_pm_use_count[cpu][cluster] = 1;
+
+	ve_spc_cpu_wakeup_irq(cluster, cpu, false);
+	ve_spc_set_resume_addr(cluster, cpu, 0);
+
+	arch_spin_unlock(&tc2_pm_lock);
+	local_irq_restore(flags);
+}
+
+static const struct mcpm_platform_ops tc2_pm_power_ops = {
+	.power_up	= tc2_pm_power_up,
+	.power_down	= tc2_pm_power_down,
+	.suspend	= tc2_pm_suspend,
+	.powered_up	= tc2_pm_powered_up,
+};
+
+static bool __init tc2_pm_usage_count_init(void)
+{
+	unsigned int mpidr, cpu, cluster;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+	if (cluster >= TC2_CLUSTERS || cpu >= ve_spc_get_nr_cpus(cluster)) {
+		pr_err("%s: boot CPU is out of bound!\n", __func__);
+		return false;
+	}
+	tc2_pm_use_count[cpu][cluster] = 1;
+	return true;
+}
+
+/*
+ * Enable cluster-level coherency, in preparation for turning on the MMU.
+ */
+static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
+{
+	asm volatile (" \n"
+"	cmp	r0, #1 \n"
+"	bxne	lr \n"
+"	b	cci_enable_port_for_self ");
+}
+
+static int __init tc2_pm_init(void)
+{
+	int ret;
+
+	ret = ve_spc_init();
+	if (ret)
+		return ret;
+
+	if (!cci_probed())
+		return -ENODEV;
+
+	if (!tc2_pm_usage_count_init())
+		return -EINVAL;
+
+	ret = mcpm_platform_register(&tc2_pm_power_ops);
+	if (!ret) {
+		mcpm_sync_init(tc2_pm_power_up_setup);
+		pr_info("TC2 power management initialized\n");
+	}
+	return ret;
+}
+
+early_initcall(tc2_pm_init);
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index c1d61f2..04f8a4a 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -6,7 +6,7 @@ config ARCH_ZYNQ
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select ICST
 	select MIGHT_HAVE_CACHE_L2X0
 	select USE_OF
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 7f9b179..dbddc07 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -358,7 +358,7 @@ static int __init atomic_pool_init(void)
 	if (!pages)
 		goto no_pages;
 
-	if (IS_ENABLED(CONFIG_CMA))
+	if (IS_ENABLED(CONFIG_DMA_CMA))
 		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
 					      atomic_pool_init);
 	else
@@ -670,7 +670,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 		addr = __alloc_simple_buffer(dev, size, gfp, &page);
 	else if (!(gfp & __GFP_WAIT))
 		addr = __alloc_from_pool(size, &page);
-	else if (!IS_ENABLED(CONFIG_CMA))
+	else if (!IS_ENABLED(CONFIG_DMA_CMA))
 		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
 	else
 		addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -759,7 +759,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		__dma_free_buffer(page, size);
 	} else if (__free_from_pool(cpu_addr, size)) {
 		return;
-	} else if (!IS_ENABLED(CONFIG_CMA)) {
+	} else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
 		__dma_free_remap(cpu_addr, size);
 		__dma_free_buffer(page, size);
 	} else {
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index c97f794..eb8830a 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -261,9 +261,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	int fault, sig, code;
-	int write = fsr & FSR_WRITE;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				(write ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	if (notify_page_fault(regs, fsr))
 		return 0;
@@ -282,6 +280,11 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+	if (fsr & FSR_WRITE)
+		flags |= FAULT_FLAG_WRITE;
+
 	/*
 	 * As per x86, we may deadlock here.  However, since the kernel only
 	 * validly references user space from well defined areas of the code,
@@ -349,6 +352,13 @@ retry:
 	if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
 		return 0;
 
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (!user_mode(regs))
+		goto no_context;
+
 	if (fault & VM_FAULT_OOM) {
 		/*
 		 * We ran out of memory, call the OOM killer, and return to
@@ -359,13 +369,6 @@ retry:
 		return 0;
 	}
 
-	/*
-	 * If we are in kernel mode at this point, we
-	 * have no context to handle this fault with.
-	 */
-	if (!user_mode(regs))
-		goto no_context;
-
 	if (fault & VM_FAULT_SIGBUS) {
 		/*
 		 * We had some memory, but were unable to
diff --git a/arch/arm/mm/hugetlbpage.c b/arch/arm/mm/hugetlbpage.c
index 3d1e4a2..66781bf 100644
--- a/arch/arm/mm/hugetlbpage.c
+++ b/arch/arm/mm/hugetlbpage.c
@@ -36,22 +36,6 @@
  * of type casting from pmd_t * to pte_t *.
  */
 
-pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd = NULL;
-
-	pgd = pgd_offset(mm, addr);
-	if (pgd_present(*pgd)) {
-		pud = pud_offset(pgd, addr);
-		if (pud_present(*pud))
-			pmd = pmd_offset(pud, addr);
-	}
-
-	return (pte_t *)pmd;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
 			      int write)
 {
@@ -68,33 +52,6 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
 	return 0;
 }
 
-pte_t *huge_pte_alloc(struct mm_struct *mm,
-			unsigned long addr, unsigned long sz)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pte_t *pte = NULL;
-
-	pgd = pgd_offset(mm, addr);
-	pud = pud_alloc(mm, pgd, addr);
-	if (pud)
-		pte = (pte_t *)pmd_alloc(mm, pud, addr);
-
-	return pte;
-}
-
-struct page *
-follow_huge_pmd(struct mm_struct *mm, unsigned long address,
-		pmd_t *pmd, int write)
-{
-	struct page *page;
-
-	page = pte_page(*(pte_t *)pmd);
-	if (page)
-		page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
-	return page;
-}
-
 int pmd_huge(pmd_t pmd)
 {
 	return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 15225d8..0d3f0d8 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -77,7 +77,7 @@ static int __init parse_tag_initrd2(const struct tag *tag)
 __tagtable(ATAG_INITRD2, parse_tag_initrd2);
 
 #ifdef CONFIG_OF_FLATTREE
-void __init early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	phys_initrd_start = start;
 	phys_initrd_size = end - start;
@@ -231,7 +231,7 @@ static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
 }
 #endif
 
-void __init setup_dma_zone(struct machine_desc *mdesc)
+void __init setup_dma_zone(const struct machine_desc *mdesc)
 {
 #ifdef CONFIG_ZONE_DMA
 	if (mdesc->dma_zone_size) {
@@ -335,7 +335,8 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
 	return phys;
 }
 
-void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
+void __init arm_memblock_init(struct meminfo *mi,
+	const struct machine_desc *mdesc)
 {
 	int i;
 
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 53cdbd3..b1d17ee 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1186,7 +1186,7 @@ void __init arm_mm_memblock_reserve(void)
  * called function.  This means you can't use any function or debugging
  * method which may touch any device, otherwise the kernel _will_ crash.
  */
-static void __init devicemaps_init(struct machine_desc *mdesc)
+static void __init devicemaps_init(const struct machine_desc *mdesc)
 {
 	struct map_desc map;
 	unsigned long addr;
@@ -1319,7 +1319,7 @@ static void __init map_lowmem(void)
  * paging_init() sets up the page tables, initialises the zone memory
  * maps, and sets up the zero page, bad page and bad page tables.
  */
-void __init paging_init(struct machine_desc *mdesc)
+void __init paging_init(const struct machine_desc *mdesc)
 {
 	void *zero_page;
 
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 1fa5010..34d4ab2 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -299,7 +299,7 @@ void __init sanity_check_meminfo(void)
  * paging_init() sets up the page tables, initialises the zone memory
  * maps, and sets up the zero page, bad page and bad page tables.
  */
-void __init paging_init(struct machine_desc *mdesc)
+void __init paging_init(const struct machine_desc *mdesc)
 {
 	early_trap_init((void *)CONFIG_VECTORS_BASE);
 	mpu_setup();
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
index 8db0b98..c492e1b 100644
--- a/arch/arm/plat-orion/irq.c
+++ b/arch/arm/plat-orion/irq.c
@@ -47,7 +47,7 @@ static int __init orion_add_irq_domain(struct device_node *np,
 	do {
 		base = of_iomap(np, i);
 		if (base) {
-			orion_irq_init(i * 32, base);
+			orion_irq_init(i * 32, base + 0x04);
 			i++;
 		}
 	} while (base);
diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c
index 3e5c461..50a3ea0 100644
--- a/arch/arm/plat-samsung/init.c
+++ b/arch/arm/plat-samsung/init.c
@@ -55,12 +55,13 @@ void __init s3c_init_cpu(unsigned long idcode,
 
 	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
 
-	if (cpu->map_io == NULL || cpu->init == NULL) {
+	if (cpu->init == NULL) {
 		printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
 		panic("Unsupported Samsung CPU");
 	}
 
-	cpu->map_io();
+	if (cpu->map_io)
+		cpu->map_io();
 }
 
 /* s3c24xx_init_clocks
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 8d10dc8..3e5d311 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -78,6 +78,11 @@
 ENTRY(vfp_support_entry)
 	DBGSTR3	"instr %08x pc %08x state %p", r0, r2, r10
 
+	ldr	r3, [sp, #S_PSR]	@ Neither lazy restore nor FP exceptions
+	and	r3, r3, #MODE_MASK	@ are supported in kernel mode
+	teq	r3, #USR_MODE
+	bne	vfp_kmode_exception	@ Returns through lr
+
 	VFPFMRX	r1, FPEXC		@ Is the VFP enabled?
 	DBGSTR1	"fpexc %08x", r1
 	tst	r1, #FPEXC_EN
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 5dfbb0b..52b8f40 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/uaccess.h>
 #include <linux/user.h>
+#include <linux/export.h>
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
@@ -648,6 +649,72 @@ static int vfp_hotplug(struct notifier_block *b, unsigned long action,
 	return NOTIFY_OK;
 }
 
+void vfp_kmode_exception(void)
+{
+	/*
+	 * If we reach this point, a floating point exception has been raised
+	 * while running in kernel mode. If the NEON/VFP unit was enabled at the
+	 * time, it means a VFP instruction has been issued that requires
+	 * software assistance to complete, something which is not currently
+	 * supported in kernel mode.
+	 * If the NEON/VFP unit was disabled, and the location pointed to below
+	 * is properly preceded by a call to kernel_neon_begin(), something has
+	 * caused the task to be scheduled out and back in again. In this case,
+	 * rebuilding and running with CONFIG_DEBUG_ATOMIC_SLEEP enabled should
+	 * be helpful in localizing the problem.
+	 */
+	if (fmrx(FPEXC) & FPEXC_EN)
+		pr_crit("BUG: unsupported FP instruction in kernel mode\n");
+	else
+		pr_crit("BUG: FP instruction issued in kernel mode with FP unit disabled\n");
+}
+
+#ifdef CONFIG_KERNEL_MODE_NEON
+
+/*
+ * Kernel-side NEON support functions
+ */
+void kernel_neon_begin(void)
+{
+	struct thread_info *thread = current_thread_info();
+	unsigned int cpu;
+	u32 fpexc;
+
+	/*
+	 * Kernel mode NEON is only allowed outside of interrupt context
+	 * with preemption disabled. This will make sure that the kernel
+	 * mode NEON register contents never need to be preserved.
+	 */
+	BUG_ON(in_interrupt());
+	cpu = get_cpu();
+
+	fpexc = fmrx(FPEXC) | FPEXC_EN;
+	fmxr(FPEXC, fpexc);
+
+	/*
+	 * Save the userland NEON/VFP state. Under UP,
+	 * the owner could be a task other than 'current'
+	 */
+	if (vfp_state_in_hw(cpu, thread))
+		vfp_save_state(&thread->vfpstate, fpexc);
+#ifndef CONFIG_SMP
+	else if (vfp_current_hw_state[cpu] != NULL)
+		vfp_save_state(vfp_current_hw_state[cpu], fpexc);
+#endif
+	vfp_current_hw_state[cpu] = NULL;
+}
+EXPORT_SYMBOL(kernel_neon_begin);
+
+void kernel_neon_end(void)
+{
+	/* Disable the NEON/VFP unit. */
+	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
+	put_cpu();
+}
+EXPORT_SYMBOL(kernel_neon_end);
+
+#endif /* CONFIG_KERNEL_MODE_NEON */
+
 /*
  * VFP support code initialisation.
  */
@@ -731,4 +798,4 @@ static int __init vfp_init(void)
 	return 0;
 }
 
-late_initcall(vfp_init);
+core_initcall(vfp_init);
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index c9770ba..8a6295c 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -170,6 +170,7 @@ static void __init xen_percpu_init(void *unused)
 	per_cpu(xen_vcpu, cpu) = vcpup;
 
 	enable_percpu_irq(xen_events_irq, 0);
+	put_cpu();
 }
 
 static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 6c8ba25..6d6acf1 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -199,13 +199,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC;
 	unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
-	if (esr & ESR_LNX_EXEC) {
-		vm_flags = VM_EXEC;
-	} else if ((esr & ESR_WRITE) && !(esr & ESR_CM)) {
-		vm_flags = VM_WRITE;
-		mm_flags |= FAULT_FLAG_WRITE;
-	}
-
 	tsk = current;
 	mm  = tsk->mm;
 
@@ -220,6 +213,16 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		mm_flags |= FAULT_FLAG_USER;
+
+	if (esr & ESR_LNX_EXEC) {
+		vm_flags = VM_EXEC;
+	} else if ((esr & ESR_WRITE) && !(esr & ESR_CM)) {
+		vm_flags = VM_WRITE;
+		mm_flags |= FAULT_FLAG_WRITE;
+	}
+
 	/*
 	 * As per x86, we may deadlock here. However, since the kernel only
 	 * validly references user space from well defined areas of the code,
@@ -288,6 +291,13 @@ retry:
 			      VM_FAULT_BADACCESS))))
 		return 0;
 
+	/*
+	 * If we are in kernel mode at this point, we have no context to
+	 * handle this fault with.
+	 */
+	if (!user_mode(regs))
+		goto no_context;
+
 	if (fault & VM_FAULT_OOM) {
 		/*
 		 * We ran out of memory, call the OOM killer, and return to
@@ -298,13 +308,6 @@ retry:
 		return 0;
 	}
 
-	/*
-	 * If we are in kernel mode at this point, we have no context to
-	 * handle this fault with.
-	 */
-	if (!user_mode(regs))
-		goto no_context;
-
 	if (fault & VM_FAULT_SIGBUS) {
 		/*
 		 * We had some memory, but were unable to successfully fix up
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 67e8d7c..de2de5d 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -44,8 +44,7 @@ static unsigned long phys_initrd_size __initdata = 0;
 
 phys_addr_t memstart_addr __read_mostly = 0;
 
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	phys_initrd_start = start;
 	phys_initrd_size = end - start;
diff --git a/arch/avr32/boards/atngw100/evklcd10x.c b/arch/avr32/boards/atngw100/evklcd10x.c
index 2038875..64919b0 100644
--- a/arch/avr32/boards/atngw100/evklcd10x.c
+++ b/arch/avr32/boards/atngw100/evklcd10x.c
@@ -58,7 +58,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
 	.dclkmax		= 28330000,
 };
 
-static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = {
 	.default_bpp		= 16,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
@@ -96,7 +96,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
 	.dclkmax		= 7000000,
 };
 
-static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = {
 	.default_bpp		= 16,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
@@ -134,7 +134,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
 	.dclkmax		= 6400000,
 };
 
-static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = {
 	.default_bpp		= 16,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
@@ -145,7 +145,7 @@ static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
 };
 #endif
 
-static void atevklcd10x_lcdc_power_control(int on)
+static void atevklcd10x_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
 {
 	gpio_set_value(GPIO_PIN_PB(15), on);
 }
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c
index f914319..1ba09e4 100644
--- a/arch/avr32/boards/atngw100/mrmt.c
+++ b/arch/avr32/boards/atngw100/mrmt.c
@@ -83,7 +83,7 @@ static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
 	.dclkmax		= 9260000,
 };
 
-static struct atmel_lcdfb_info __initdata rmt_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = {
 	.default_bpp		= 24,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
@@ -126,7 +126,7 @@ static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
 	.dclkmax		= 9260000,
 };
 
-static struct atmel_lcdfb_info __initdata rmt_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = {
 	.default_bpp		= 24,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
@@ -150,7 +150,6 @@ static struct ac97c_platform_data __initdata ac97c0_data = {
 static struct platform_device rmt_ts_device = {
 	.name	= "ucb1400_ts",
 	.id	= -1,
-	}
 };
 #endif
 
diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h
index 9392d32..653cc09 100644
--- a/arch/avr32/boards/atstk1000/atstk1000.h
+++ b/arch/avr32/boards/atstk1000/atstk1000.h
@@ -10,7 +10,7 @@
 #ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
 #define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
 
-extern struct atmel_lcdfb_info atstk1000_lcdc_data;
+extern struct atmel_lcdfb_pdata atstk1000_lcdc_data;
 
 void atstk1000_setup_j2_leds(void);
 
diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c
index 2d6b560..b6b88f5 100644
--- a/arch/avr32/boards/atstk1000/setup.c
+++ b/arch/avr32/boards/atstk1000/setup.c
@@ -55,7 +55,7 @@ static struct fb_monspecs __initdata atstk1000_default_monspecs = {
 	.dclkmax		= 30000000,
 };
 
-struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata atstk1000_lcdc_data = {
 	.default_bpp		= 24,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 27bd6fb..7b1f2cd 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -125,7 +125,7 @@ static struct fb_monspecs __initdata favr32_default_monspecs = {
 	.dclkmax		= 28000000,
 };
 
-struct atmel_lcdfb_info __initdata favr32_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata favr32_lcdc_data = {
 	.default_bpp		= 16,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/hammerhead/setup.c b/arch/avr32/boards/hammerhead/setup.c
index 9d1efd1..dc0e317 100644
--- a/arch/avr32/boards/hammerhead/setup.c
+++ b/arch/avr32/boards/hammerhead/setup.c
@@ -77,7 +77,7 @@ static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = {
 	.dclkmax		= 10000000,
 };
 
-struct atmel_lcdfb_info __initdata hammerhead_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata hammerhead_lcdc_data = {
 	.default_bpp		= 24,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/merisc/display.c b/arch/avr32/boards/merisc/display.c
index 85a543c..e7683ee 100644
--- a/arch/avr32/boards/merisc/display.c
+++ b/arch/avr32/boards/merisc/display.c
@@ -45,7 +45,7 @@ static struct fb_monspecs merisc_fb_monspecs = {
 	.dclkmax	= 30000000,
 };
 
-struct atmel_lcdfb_info merisc_lcdc_data = {
+struct atmel_lcdfb_pdata merisc_lcdc_data = {
 	.default_bpp		= 24,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c
index 05358aa..1cb8e9c 100644
--- a/arch/avr32/boards/mimc200/setup.c
+++ b/arch/avr32/boards/mimc200/setup.c
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-extern struct atmel_lcdfb_info mimc200_lcdc_data;
+extern struct atmel_lcdfb_pdata mimc200_lcdc_data;
 
 #include <linux/clk.h>
 #include <linux/etherdevice.h>
@@ -71,7 +71,7 @@ static struct fb_monspecs __initdata mimc200_default_monspecs = {
 	.dclkmax		= 25200000,
 };
 
-struct atmel_lcdfb_info __initdata mimc200_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata mimc200_lcdc_data = {
 	.default_bpp		= 16,
 	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
 	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 7f8759a..a1f4d1e 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1439,7 +1439,7 @@ fail:
  *  LCDC
  * -------------------------------------------------------------------- */
 #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
-static struct atmel_lcdfb_info atmel_lcdfb0_data;
+static struct atmel_lcdfb_pdata atmel_lcdfb0_data;
 static struct resource atmel_lcdfb0_resource[] = {
 	{
 		.start		= 0xff000000,
@@ -1467,12 +1467,12 @@ static struct clk atmel_lcdfb0_pixclk = {
 };
 
 struct platform_device *__init
-at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data,
 		     unsigned long fbmem_start, unsigned long fbmem_len,
 		     u64 pin_mask)
 {
 	struct platform_device *pdev;
-	struct atmel_lcdfb_info *info;
+	struct atmel_lcdfb_pdata *info;
 	struct fb_monspecs *monspecs;
 	struct fb_videomode *modedb;
 	unsigned int modedb_size;
@@ -1529,7 +1529,7 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
 	}
 
 	info = pdev->dev.platform_data;
-	memcpy(info, data, sizeof(struct atmel_lcdfb_info));
+	memcpy(info, data, sizeof(struct atmel_lcdfb_pdata));
 	info->default_monspecs = monspecs;
 
 	pdev->name = "at32ap-lcdfb";
@@ -1983,6 +1983,9 @@ at32_add_device_nand(unsigned int id, struct atmel_nand_data *data)
 				ARRAY_SIZE(smc_cs3_resource)))
 		goto fail;
 
+	/* For at32ap7000, we use the reset workaround for nand driver */
+	data->need_reset_workaround = true;
+
 	if (platform_device_add_data(pdev, data,
 				sizeof(struct atmel_nand_data)))
 		goto fail;
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
index d485b03..f1a316d 100644
--- a/arch/avr32/mach-at32ap/include/mach/board.h
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -44,9 +44,9 @@ struct platform_device *
 at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
 void at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n);
 
-struct atmel_lcdfb_info;
+struct atmel_lcdfb_pdata;
 struct platform_device *
-at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data,
 		     unsigned long fbmem_start, unsigned long fbmem_len,
 		     u64 pin_mask);
 
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index b2f2d2d..0eca933 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -86,6 +86,8 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
 
 	local_irq_enable();
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 
@@ -228,9 +230,9 @@ no_context:
 	 */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	pagefault_out_of_memory();
 	if (!user_mode(regs))
 		goto no_context;
+	pagefault_out_of_memory();
 	return;
 
 do_sigbus:
diff --git a/arch/c6x/kernel/devicetree.c b/arch/c6x/kernel/devicetree.c
index bdb56f0..287d0e6 100644
--- a/arch/c6x/kernel/devicetree.c
+++ b/arch/c6x/kernel/devicetree.c
@@ -33,8 +33,7 @@ void __init early_init_devtree(void *params)
 
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-		unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (unsigned long)__va(start);
 	initrd_end = (unsigned long)__va(end);
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 3201ddb..c699d32 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -99,9 +99,6 @@ config ETRAX_KMALLOCED_MODULES
 	help
 	  Enable module allocation with kmalloc instead of vmalloc.
 
-config OOM_REBOOT
-       bool "Enable reboot at out of memory"
-
 source "kernel/Kconfig.preempt"
 
 source mm/Kconfig
@@ -175,12 +172,6 @@ config ETRAX_FLASH_BUSWIDTH
 	help
 	  Width in bytes of the NOR Flash bus (1, 2 or 4). Is usually 2.
 
-config ETRAX_NANDFLASH_BUSWIDTH
-	int "Buswidth of NAND flash in bytes"
-	default "1"
-	help
-	  Width in bytes of the NAND flash (1 or 2).
-
 config ETRAX_FLASH1_SIZE
        int "FLASH1 size (dec, in MB. 0 = Unknown)"
        default "0"
@@ -272,38 +263,6 @@ config ETRAX_AXISFLASHMAP
 	  This option enables MTD mapping of flash devices.  Needed to use
 	  flash memories.  If unsure, say Y.
 
-config ETRAX_RTC
-	bool "Real Time Clock support"
-	depends on ETRAX_I2C
-	help
-	  Enables drivers for the Real-Time Clock battery-backed chips on
-	  some products. The kernel reads the time when booting, and
-	  the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
-	  rtc_time struct (see <file:arch/cris/include/asm/rtc.h>) on the
-	  /dev/rtc device.  You can check the time with cat /proc/rtc, but
-	  normal time reading should be done using libc function time and
-	  friends.
-
-choice
-	prompt "RTC chip"
-	depends on ETRAX_RTC
-	default ETRAX_DS1302
-
-config ETRAX_DS1302
-	depends on ETRAX_ARCH_V10
-	bool "DS1302"
-	help
-	  Enables the driver for the DS1302 Real-Time Clock battery-backed
-	  chip on some products.
-
-config ETRAX_PCF8563
-	bool "PCF8563"
-	help
-	  Enables the driver for the PCF8563 Real-Time Clock battery-backed
-	  chip on some products.
-
-endchoice
-
 config ETRAX_SYNCHRONOUS_SERIAL
 	bool "Synchronous serial-port support"
 	help
@@ -578,26 +537,6 @@ config ETRAX_SERIAL_PORT3_DMA5_IN
 	depends on ETRAX_ARCH_V10
 	bool "DMA 5"
 
-config ETRAX_SERIAL_PORT3_DMA9_IN
-	bool "Ser3 uses DMA9 for input"
-	depends on ETRAXFS
-	help
-	  Enables the DMA9 input channel for ser3 (ttyS3).
-	  If you do not enable DMA, an interrupt for each character will be
-	  used when receiving data.
-	  Normally you want to use DMA, unless you use the DMA channel for
-	  something else.
-
-config ETRAX_SERIAL_PORT3_DMA3_IN
-	bool "Ser3 uses DMA3 for input"
-	depends on CRIS_MACH_ARTPEC3
-	help
-	  Enables the DMA3 input channel for ser3 (ttyS3).
-	  If you do not enable DMA, an interrupt for each character will be
-	  used when receiving data.
-	  Normally you want to use DMA, unless you use the DMA channel for
-	  something else.
-
 endchoice
 
 choice
@@ -615,26 +554,6 @@ config ETRAX_SERIAL_PORT3_DMA4_OUT
 	depends on ETRAX_ARCH_V10
 	bool "DMA 4"
 
-config ETRAX_SERIAL_PORT3_DMA8_OUT
-	bool "Ser3 uses DMA8 for output"
-	depends on ETRAXFS
-	help
-	  Enables the DMA8 output channel for ser3 (ttyS3).
-	  If you do not enable DMA, an interrupt for each character will be
-	  used when transmitting data.
-	  Normally you want to use DMA, unless you use the DMA channel for
-	  something else.
-
-config ETRAX_SERIAL_PORT3_DMA2_OUT
-	bool "Ser3 uses DMA2 for output"
-	depends on CRIS_MACH_ARTPEC3
-	help
-	  Enables the DMA2 output channel for ser3 (ttyS3).
-	  If you do not enable DMA, an interrupt for each character will be
-	  used when transmitting data.
-	  Normally you want to use DMA, unless you use the DMA channel for
-	  something else.
-
 endchoice
 
 endmenu
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index daf5f19..239dab0 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -417,16 +417,6 @@ config ETRAX_USB_HOST
 	   for CTRL and BULK traffic only, INTR traffic may work as well
 	   however (depending on the requirements of timeliness).
 
-config ETRAX_USB_HOST_PORT1
-	bool "USB port 1 enabled"
-	depends on ETRAX_USB_HOST
-	default n
-
-config ETRAX_USB_HOST_PORT2
-	bool "USB port 2 enabled"
-	depends on ETRAX_USB_HOST
-	default n
-
 config ETRAX_PTABLE_SECTOR
 	int "Byte-offset of partition table sector"
 	depends on ETRAX_AXISFLASHMAP
@@ -527,19 +517,6 @@ config ETRAX_GPIO
 	  Remember that you need to setup the port directions appropriately in
 	  the General configuration.
 
-config ETRAX_PA_BUTTON_BITMASK
-	hex "PA-buttons bitmask"
-	depends on ETRAX_GPIO
-	default "02"
-	help
-	  This is a bitmask with information about what bits on PA that
-	  are used for buttons.
-	  Most products has a so called TEST button on PA1, if that's true
-	  use 02 here.
-	  Use 00 if there are no buttons on PA.
-	  If the bitmask is <> 00 a button driver will be included in the gpio
-	  driver. ETRAX general I/O support must be enabled.
-
 config ETRAX_PA_CHANGEABLE_DIR
 	hex "PA user changeable dir mask"
 	depends on ETRAX_GPIO
@@ -580,51 +557,4 @@ config ETRAX_PB_CHANGEABLE_BITS
 	  Bit set = changeable.
 	  You probably want 00 here.
 
-config ETRAX_DS1302_RST_ON_GENERIC_PORT
-	bool "DS1302 RST on Generic Port"
-	depends on ETRAX_DS1302
-	help
-	  If your product has the RST signal line for the DS1302 RTC on the
-	  Generic Port then say Y here, otherwise leave it as N in which
-	  case the RST signal line is assumed to be connected to Port PB
-	  (just like the SCL and SDA lines).
-
-config ETRAX_DS1302_RSTBIT
-	int "DS1302 RST bit number"
-	depends on ETRAX_DS1302
-	default "2"
-	help
-	  This is the bit number for the RST signal line of the DS1302 RTC on
-	  the selected port. If you have selected the generic port then it
-	  should be bit 27, otherwise your best bet is bit 5.
-
-config ETRAX_DS1302_SCLBIT
-	int "DS1302 SCL bit number"
-	depends on ETRAX_DS1302
-	default "1"
-	help
-	  This is the bit number for the SCL signal line of the DS1302 RTC on
-	  Port PB. This is probably best left at 3.
-
-config ETRAX_DS1302_SDABIT
-	int "DS1302 SDA bit number"
-	depends on ETRAX_DS1302
-	default "0"
-	help
-	  This is the bit number for the SDA signal line of the DS1302 RTC on
-	  Port PB. This is probably best left at 2.
-
-config ETRAX_DS1302_TRICKLE_CHARGE
-	int "DS1302 Trickle charger value"
-	depends on ETRAX_DS1302
-	default "0"
-	help
-	  This controls the initial value of the trickle charge register.
-	  0 = disabled (use this if you are unsure or have a non rechargeable battery)
-	  Otherwise the following values can be OR:ed together to control the
-	  charge current:
-	  1 = 2kohm, 2 = 4kohm, 3 = 4kohm
-	  4 = 1 diode, 8 = 2 diodes
-	  Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
-
 endif
diff --git a/arch/cris/arch-v10/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile
index 44bf2e8..e5c1318 100644
--- a/arch/cris/arch-v10/drivers/Makefile
+++ b/arch/cris/arch-v10/drivers/Makefile
@@ -6,7 +6,5 @@ obj-$(CONFIG_ETRAX_AXISFLASHMAP)	+= axisflashmap.o
 obj-$(CONFIG_ETRAX_I2C)			+= i2c.o
 obj-$(CONFIG_ETRAX_I2C_EEPROM)		+= eeprom.o
 obj-$(CONFIG_ETRAX_GPIO)		+= gpio.o
-obj-$(CONFIG_ETRAX_DS1302)		+= ds1302.o
-obj-$(CONFIG_ETRAX_PCF8563)		+= pcf8563.o
 obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL)	+= sync_serial.o
 
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 1d866d3..6792503 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -19,64 +19,6 @@ config ETRAX_NO_PHY
 	  switch. This option should normally be disabled. If enabled,
 	  speed and duplex will be locked to 100 Mbit and full duplex.
 
-config ETRAX_ETHERNET_IFACE0
-	depends on ETRAX_ETHERNET
-	bool "Enable network interface 0"
-
-config ETRAX_ETHERNET_IFACE1
-	depends on (ETRAX_ETHERNET && ETRAXFS)
-	bool "Enable network interface 1 (uses DMA6 and DMA7)"
-
-config ETRAX_ETHERNET_GBIT
-	depends on (ETRAX_ETHERNET && CRIS_MACH_ARTPEC3)
-	bool "Enable gigabit Ethernet support"
-
-choice
-	prompt "Eth0 led group"
-	depends on ETRAX_ETHERNET_IFACE0
-	default ETRAX_ETH0_USE_LEDGRP0
-
-config ETRAX_ETH0_USE_LEDGRP0
-	bool "Use LED grp 0"
-	depends on ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO
-	help
-	  Use LED grp 0 for eth0
-
-config ETRAX_ETH0_USE_LEDGRP1
-	bool "Use LED grp 1"
-	depends on ETRAX_NBR_LED_GRP_TWO
-	help
-	  Use LED grp 1 for eth0
-
-config ETRAX_ETH0_USE_LEDGRPNULL
-	bool "Use no LEDs for eth0"
-	help
-	  Use no LEDs for eth0
-endchoice
-
-choice
-	prompt "Eth1 led group"
-	depends on ETRAX_ETHERNET_IFACE1
-	default ETRAX_ETH1_USE_LEDGRP1
-
-config ETRAX_ETH1_USE_LEDGRP0
-	bool "Use LED grp 0"
-	depends on ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO
-	help
-	  Use LED grp 0 for eth1
-
-config ETRAX_ETH1_USE_LEDGRP1
-	bool "Use LED grp 1"
-	depends on ETRAX_NBR_LED_GRP_TWO
-	help
-	  Use LED grp 1 for eth1
-
-config ETRAX_ETH1_USE_LEDGRPNULL
-	bool "Use no LEDs for eth1"
-	help
-	  Use no LEDs for eth1
-endchoice
-
 config ETRAXFS_SERIAL
 	bool "Serial-port support"
 	depends on ETRAX_ARCH_V32
@@ -108,261 +50,24 @@ config ETRAX_SERIAL_PORT0
 	  if you do not need DMA to something else.
 	  ser0 can use dma4 or dma6 for output and dma5 or dma7 for input.
 
-choice
-	prompt "Ser0 default port type "
-	depends on ETRAX_SERIAL_PORT0
-	default ETRAX_SERIAL_PORT0_TYPE_232
-	help
-	  Type of serial port.
-
-config ETRAX_SERIAL_PORT0_TYPE_232
-	bool "Ser0 is a RS-232 port"
-	help
-	  Configure serial port 0 to be a RS-232 port.
-
-config ETRAX_SERIAL_PORT0_TYPE_485HD
-	bool "Ser0 is a half duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 0 to be a half duplex (two wires) RS-485 port.
-
-config ETRAX_SERIAL_PORT0_TYPE_485FD
-	bool "Ser0 is a full duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 0 to be a full duplex (four wires) RS-485 port.
-endchoice
-
-config ETRAX_SER0_DTR_BIT
-	string "Ser 0 DTR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT0
-
-config ETRAX_SER0_RI_BIT
-	string "Ser 0 RI bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT0
-
-config ETRAX_SER0_DSR_BIT
-	string "Ser 0 DSR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT0
-
-config ETRAX_SER0_CD_BIT
-	string "Ser 0 CD bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT0
-
 config ETRAX_SERIAL_PORT1
 	bool "Serial port 1 enabled"
 	depends on ETRAXFS_SERIAL
 	help
 	  Enables the ETRAX FS serial driver for ser1 (ttyS1).
 
-choice
-	prompt "Ser1 default port type"
-	depends on ETRAX_SERIAL_PORT1
-	default ETRAX_SERIAL_PORT1_TYPE_232
-	help
-	  Type of serial port.
-
-config ETRAX_SERIAL_PORT1_TYPE_232
-	bool "Ser1 is a RS-232 port"
-	help
-	  Configure serial port 1 to be a RS-232 port.
-
-config ETRAX_SERIAL_PORT1_TYPE_485HD
-	bool "Ser1 is a half duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 1 to be a half duplex (two wires) RS-485 port.
-
-config ETRAX_SERIAL_PORT1_TYPE_485FD
-	bool "Ser1 is a full duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 1 to be a full duplex (four wires) RS-485 port.
-endchoice
-
-config ETRAX_SER1_DTR_BIT
-	string "Ser 1 DTR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT1
-
-config ETRAX_SER1_RI_BIT
-	string "Ser 1 RI bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT1
-
-config ETRAX_SER1_DSR_BIT
-	string "Ser 1 DSR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT1
-
-config ETRAX_SER1_CD_BIT
-	string "Ser 1 CD bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT1
-
 config ETRAX_SERIAL_PORT2
 	bool "Serial port 2 enabled"
 	depends on ETRAXFS_SERIAL
 	help
 	  Enables the ETRAX FS serial driver for ser2 (ttyS2).
 
-choice
-	prompt "Ser2 default port type"
-	depends on ETRAX_SERIAL_PORT2
-	default ETRAX_SERIAL_PORT2_TYPE_232
-	help
-	  What DMA channel to use for ser2
-
-config ETRAX_SERIAL_PORT2_TYPE_232
-	bool "Ser2 is a RS-232 port"
-	help
-	  Configure serial port 2 to be a RS-232 port.
-
-config ETRAX_SERIAL_PORT2_TYPE_485HD
-	bool "Ser2 is a half duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 2 to be a half duplex (two wires) RS-485 port.
-
-config ETRAX_SERIAL_PORT2_TYPE_485FD
-	bool "Ser2 is a full duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 2 to be a full duplex (four wires) RS-485 port.
-endchoice
-
-
-config ETRAX_SER2_DTR_BIT
-	string "Ser 2 DTR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT2
-
-config ETRAX_SER2_RI_BIT
-	string "Ser 2 RI bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT2
-
-config ETRAX_SER2_DSR_BIT
-	string "Ser 2 DSR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT2
-
-config ETRAX_SER2_CD_BIT
-	string "Ser 2 CD bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT2
-
 config ETRAX_SERIAL_PORT3
 	bool "Serial port 3 enabled"
 	depends on ETRAXFS_SERIAL
 	help
 	  Enables the ETRAX FS serial driver for ser3 (ttyS3).
 
-choice
-	prompt "Ser3 default port type"
-	depends on ETRAX_SERIAL_PORT3
-	default ETRAX_SERIAL_PORT3_TYPE_232
-	help
-	  What DMA channel to use for ser3.
-
-config ETRAX_SERIAL_PORT3_TYPE_232
-	bool "Ser3 is a RS-232 port"
-	help
-	  Configure serial port 3 to be a RS-232 port.
-
-config ETRAX_SERIAL_PORT3_TYPE_485HD
-	bool "Ser3 is a half duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 3 to be a half duplex (two wires) RS-485 port.
-
-config ETRAX_SERIAL_PORT3_TYPE_485FD
-	bool "Ser3 is a full duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 3 to be a full duplex (four wires) RS-485 port.
-endchoice
-
-config ETRAX_SER3_DTR_BIT
-	string "Ser 3 DTR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT3
-
-config ETRAX_SER3_RI_BIT
-	string "Ser 3 RI bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT3
-
-config ETRAX_SER3_DSR_BIT
-	string "Ser 3 DSR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT3
-
-config ETRAX_SER3_CD_BIT
-	string "Ser 3 CD bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT3
-
-config ETRAX_SERIAL_PORT4
-	bool "Serial port 4 enabled"
-	depends on ETRAXFS_SERIAL && CRIS_MACH_ARTPEC3
-	help
-	  Enables the ETRAX FS serial driver for ser4 (ttyS4).
-
-choice
-	prompt "Ser4 default port type"
-	depends on ETRAX_SERIAL_PORT4
-	default ETRAX_SERIAL_PORT4_TYPE_232
-	help
-	  What DMA channel to use for ser4.
-
-config ETRAX_SERIAL_PORT4_TYPE_232
-	bool "Ser4 is a RS-232 port"
-	help
-	  Configure serial port 4 to be a RS-232 port.
-
-config ETRAX_SERIAL_PORT4_TYPE_485HD
-	bool "Ser4 is a half duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 4 to be a half duplex (two wires) RS-485 port.
-
-config ETRAX_SERIAL_PORT4_TYPE_485FD
-	bool "Ser4 is a full duplex RS-485 port"
-	depends on ETRAX_RS485
-	help
-	  Configure serial port 4 to be a full duplex (four wires) RS-485 port.
-endchoice
-
-choice
-	prompt "Ser4 DMA in channel "
-	depends on ETRAX_SERIAL_PORT4
-	default ETRAX_SERIAL_PORT4_NO_DMA_IN
-	help
-	  What DMA channel to use for ser4.
-
-
-config ETRAX_SERIAL_PORT4_NO_DMA_IN
-	bool "Ser4 uses no DMA for input"
-	help
-	  Do not use DMA for ser4 input.
-
-config ETRAX_SERIAL_PORT4_DMA9_IN
-	bool "Ser4 uses DMA9 for input"
-	depends on ETRAX_SERIAL_PORT4
-	help
-	  Enables the DMA9 input channel for ser4 (ttyS4).
-	  If you do not enable DMA, an interrupt for each character will be
-	  used when receiving data.
-	  Normally you want to use DMA, unless you use the DMA channel for
-	  something else.
-
-endchoice
-
-config ETRAX_SER4_DTR_BIT
-	string "Ser 4 DTR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT4
-
-config ETRAX_SER4_RI_BIT
-	string "Ser 4 RI bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT4
-
-config ETRAX_SER4_DSR_BIT
-	string "Ser 4 DSR bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT4
-
-config ETRAX_SER4_CD_BIT
-	string "Ser 4 CD bit (empty = not used)"
-	depends on ETRAX_SERIAL_PORT4
-
 config ETRAX_SYNCHRONOUS_SERIAL
 	bool "Synchronous serial-port support"
 	depends on ETRAX_ARCH_V32
@@ -703,32 +408,6 @@ config ETRAX_SPI_SSER0
 	  want to build it as a module, which will be named spi_crisv32_sser.
 	  (You need to select MMC separately.)
 
-config ETRAX_SPI_SSER0_DMA
-	bool "DMA for SPI on sser0 enabled"
-	depends on ETRAX_SPI_SSER0
-	depends on !ETRAX_SERIAL_PORT1_DMA4_OUT && !ETRAX_SERIAL_PORT1_DMA5_IN
-	default y
-	help
-	  Say Y if using DMA (dma4/dma5) for SPI on synchronous serial port 0.
-
-config ETRAX_SPI_MMC_CD_SSER0_PIN
-	string "MMC/SD card detect pin for SPI on sser0"
-	depends on ETRAX_SPI_SSER0 && MMC_SPI
-	default "pd11"
-	help
-	  The pin to use for SD/MMC card detect.  This pin should be pulled up
-	  and grounded when a card is present.  If defined as " " (space), no
-	  pin is selected.  A card must then always be inserted for proper
-	  action.
-
-config ETRAX_SPI_MMC_WP_SSER0_PIN
-	string "MMC/SD card write-protect pin for SPI on sser0"
-	depends on ETRAX_SPI_SSER0 && MMC_SPI
-	default "pd10"
-	help
-	  The pin to use for the SD/MMC write-protect signal for a memory
-	  card.  If defined as " " (space), the card is considered writable.
-
 config ETRAX_SPI_SSER1
 	tristate "SPI using synchronous serial port 1 (sser1)"
 	depends on ETRAX_SPI_MMC
@@ -742,32 +421,6 @@ config ETRAX_SPI_SSER1
 	  want to build it as a module, which will be named spi_crisv32_sser.
 	  (You need to select MMC separately.)
 
-config ETRAX_SPI_SSER1_DMA
-	bool "DMA for SPI on sser1 enabled"
-	depends on ETRAX_SPI_SSER1 && !ETRAX_ETHERNET_IFACE1
-	depends on !ETRAX_SERIAL_PORT0_DMA6_OUT && !ETRAX_SERIAL_PORT0_DMA7_IN
-	default y
-	help
-	  Say Y if using DMA (dma6/dma7) for SPI on synchronous serial port 1.
-
-config ETRAX_SPI_MMC_CD_SSER1_PIN
-	string "MMC/SD card detect pin for SPI on sser1"
-	depends on ETRAX_SPI_SSER1 && MMC_SPI
-	default "pd12"
-	help
-	  The pin to use for SD/MMC card detect.  This pin should be pulled up
-	  and grounded when a card is present.  If defined as " " (space), no
-	  pin is selected.  A card must then always be inserted for proper
-	  action.
-
-config ETRAX_SPI_MMC_WP_SSER1_PIN
-	string "MMC/SD card write-protect pin for SPI on sser1"
-	depends on ETRAX_SPI_SSER1 && MMC_SPI
-	default "pd9"
-	help
-	  The pin to use for the SD/MMC write-protect signal for a memory
-	  card.  If defined as " " (space), the card is considered writable.
-
 config ETRAX_SPI_GPIO
 	tristate "Bitbanged SPI using gpio pins"
 	depends on ETRAX_SPI_MMC
@@ -782,51 +435,4 @@ config ETRAX_SPI_GPIO
 	  Say m to build it as a module, which will be called spi_crisv32_gpio.
 	  (You need to select MMC separately.)
 
-# The default match that of sser0, only because that's how it was tested.
-config ETRAX_SPI_CS_PIN
-	string "SPI chip select pin"
-	depends on ETRAX_SPI_GPIO
-	default "pc3"
-	help
-	  The pin to use for SPI chip select.
-
-config ETRAX_SPI_CLK_PIN
-	string "SPI clock pin"
-	depends on ETRAX_SPI_GPIO
-	default "pc1"
-	help
-	  The pin to use for the SPI clock.
-
-config ETRAX_SPI_DATAIN_PIN
-	string "SPI MISO (data in) pin"
-	depends on ETRAX_SPI_GPIO
-	default "pc16"
-	help
-	  The pin to use for SPI data in from the device.
-
-config ETRAX_SPI_DATAOUT_PIN
-	string "SPI MOSI (data out) pin"
-	depends on ETRAX_SPI_GPIO
-	default "pc0"
-	help
-	  The pin to use for SPI data out to the device.
-
-config ETRAX_SPI_MMC_CD_GPIO_PIN
-	string "MMC/SD card detect pin for SPI using gpio (space for none)"
-	depends on ETRAX_SPI_GPIO && MMC_SPI
-	default "pd11"
-	help
-	  The pin to use for SD/MMC card detect.  This pin should be pulled up
-	  and grounded when a card is present.  If defined as " " (space), no
-	  pin is selected.  A card must then always be inserted for proper
-	  action.
-
-config ETRAX_SPI_MMC_WP_GPIO_PIN
-	string "MMC/SD card write-protect pin for SPI using gpio (space for none)"
-	depends on ETRAX_SPI_GPIO && MMC_SPI
-	default "pd10"
-	help
-	  The pin to use for the SD/MMC write-protect signal for a memory
-	  card.  If defined as " " (space), the card is considered writable.
-
 endif
diff --git a/arch/cris/arch-v32/mach-a3/Kconfig b/arch/cris/arch-v32/mach-a3/Kconfig
index 7796aaf..8754727 100644
--- a/arch/cris/arch-v32/mach-a3/Kconfig
+++ b/arch/cris/arch-v32/mach-a3/Kconfig
@@ -15,10 +15,6 @@ config ETRAX_SERIAL_PORTS
        int
        default 5
 
-config ETRAX_DDR
-       bool
-       default y
-
 config ETRAX_DDR2_MRS
 	hex "DDR2 MRS"
 	default "0"
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h
index c0a29b9..15b815d 100644
--- a/arch/cris/include/asm/processor.h
+++ b/arch/cris/include/asm/processor.h
@@ -47,7 +47,6 @@ struct task_struct;
  */
 
 #define task_pt_regs(task) user_regs(task_thread_info(task))
-#define current_regs() task_pt_regs(current)
 
 unsigned long get_wchan(struct task_struct *p);
 
diff --git a/arch/cris/include/uapi/asm/kvm_para.h b/arch/cris/include/uapi/asm/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/arch/cris/include/uapi/asm/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
index 73312ab..1790f22 100644
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -58,8 +58,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
 	struct vm_area_struct * vma;
 	siginfo_t info;
 	int fault;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				((writeaccess & 1) ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	D(printk(KERN_DEBUG
 		 "Page fault for %lX on %X at %lX, prot %d write %d\n",
@@ -117,6 +116,8 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -155,6 +156,7 @@ retry:
 	} else if (writeaccess == 1) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index 0aa35f0..deb6784 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -320,7 +320,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
  *  are examined.
  */
 
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
 #if 0
 	printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c
index 331c1e2..9a66372 100644
--- a/arch/frv/mm/fault.c
+++ b/arch/frv/mm/fault.c
@@ -34,11 +34,11 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
 	struct vm_area_struct *vma;
 	struct mm_struct *mm;
 	unsigned long _pme, lrai, lrad, fixup;
+	unsigned long flags = 0;
 	siginfo_t info;
 	pgd_t *pge;
 	pud_t *pue;
 	pte_t *pte;
-	int write;
 	int fault;
 
 #if 0
@@ -81,6 +81,9 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(__frame))
+		flags |= FAULT_FLAG_USER;
+
 	down_read(&mm->mmap_sem);
 
 	vma = find_vma(mm, ear0);
@@ -129,7 +132,6 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
  */
  good_area:
 	info.si_code = SEGV_ACCERR;
-	write = 0;
 	switch (esr0 & ESR0_ATXC) {
 	default:
 		/* handle write to write protected page */
@@ -140,7 +142,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
 #endif
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
-		write = 1;
+		flags |= FAULT_FLAG_WRITE;
 		break;
 
 		 /* handle read from protected page */
@@ -162,7 +164,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, ear0, write ? FAULT_FLAG_WRITE : 0);
+	fault = handle_mm_fault(mm, vma, ear0, flags);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 33a9792..77d442a 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -158,6 +158,7 @@ source "kernel/Kconfig.hz"
 endmenu
 
 source "init/Kconfig"
+source "kernel/Kconfig.freezer"
 source "drivers/Kconfig"
 source "fs/Kconfig"
 
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
index 1bd276d..8704c93 100644
--- a/arch/hexagon/mm/vm_fault.c
+++ b/arch/hexagon/mm/vm_fault.c
@@ -53,8 +53,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
 	int si_code = SEGV_MAPERR;
 	int fault;
 	const struct exception_table_entry *fixup;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				 (cause > 0 ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	/*
 	 * If we're in an interrupt or have no user context,
@@ -65,6 +64,8 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
 
 	local_irq_enable();
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -96,6 +97,7 @@ good_area:
 	case FLT_STORE:
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 		break;
 	}
 
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 5a768ad..098602b 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -9,7 +9,6 @@ config IA64
 	select PCI if (!IA64_HP_SIM)
 	select ACPI if (!IA64_HP_SIM)
 	select PM if (!IA64_HP_SIM)
-	select ARCH_SUPPORTS_MSI
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index efbd292..9a21142 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -32,7 +32,7 @@ CONFIG_ACPI_DOCK=y
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_CONTAINER=m
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index f64980d..ea42ec5 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -26,7 +26,7 @@ CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_CONTAINER=m
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 0f4e9e4..0e98343 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -32,7 +32,7 @@ CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_CONTAINER=m
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig
index b025acf..8baf2e6 100644
--- a/arch/ia64/configs/xen_domu_defconfig
+++ b/arch/ia64/configs/xen_domu_defconfig
@@ -33,7 +33,7 @@ CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_CONTAINER=m
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff --git a/arch/ia64/include/asm/dmi.h b/arch/ia64/include/asm/dmi.h
index 1ed4c8f..185d3d1 100644
--- a/arch/ia64/include/asm/dmi.h
+++ b/arch/ia64/include/asm/dmi.h
@@ -7,6 +7,6 @@
 /* Use normal IO mappings for DMI */
 #define dmi_ioremap ioremap
 #define dmi_iounmap(x,l) iounmap(x)
-#define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
+#define dmi_alloc(l) kzalloc(l, GFP_ATOMIC)
 
 #endif
diff --git a/arch/ia64/kernel/elfcore.c b/arch/ia64/kernel/elfcore.c
index bac1639..314458b 100644
--- a/arch/ia64/kernel/elfcore.c
+++ b/arch/ia64/kernel/elfcore.c
@@ -11,8 +11,7 @@ Elf64_Half elf_core_extra_phdrs(void)
 	return GATE_EHDR->e_phnum;
 }
 
-int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-			       unsigned long limit)
+int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
 {
 	const struct elf_phdr *const gate_phdrs =
 		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
@@ -35,15 +34,13 @@ int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
 			phdr.p_offset += ofs;
 		}
 		phdr.p_paddr = 0; /* match other core phdrs */
-		*size += sizeof(phdr);
-		if (*size > limit || !dump_write(file, &phdr, sizeof(phdr)))
+		if (!dump_emit(cprm, &phdr, sizeof(phdr)))
 			return 0;
 	}
 	return 1;
 }
 
-int elf_core_write_extra_data(struct file *file, size_t *size,
-			      unsigned long limit)
+int elf_core_write_extra_data(struct coredump_params *cprm)
 {
 	const struct elf_phdr *const gate_phdrs =
 		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
@@ -53,9 +50,7 @@ int elf_core_write_extra_data(struct file *file, size_t *size,
 		if (gate_phdrs[i].p_type == PT_LOAD) {
 			void *addr = (void *)gate_phdrs[i].p_vaddr;
 			size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz);
-
-			*size += memsz;
-			if (*size > limit || !dump_write(file, addr, memsz))
+			if (!dump_emit(cprm, addr, memsz))
 				return 0;
 			break;
 		}
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 5b2dc0d..bdfd878 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1560,6 +1560,10 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 	return 0;
 }
 
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 		struct kvm_memory_slot *memslot,
 		struct kvm_userspace_memory_region *mem,
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 6cf0341..7225dad 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -90,8 +90,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
 	mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
 		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
 
-	flags |= ((mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
-
 	/* mmap_sem is performance critical.... */
 	prefetchw(&mm->mmap_sem);
 
@@ -119,6 +117,10 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
 	if (notify_page_fault(regs, TRAP_BRKPT))
 		return;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+	if (mask & VM_WRITE)
+		flags |= FAULT_FLAG_WRITE;
 retry:
 	down_read(&mm->mmap_sem);
 
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index 3cdfa9c..e9c6a80 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -78,7 +78,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
 	unsigned long page, addr;
-	int write;
+	unsigned long flags = 0;
 	int fault;
 	siginfo_t info;
 
@@ -117,6 +117,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
 	if (in_atomic() || !mm)
 		goto bad_area_nosemaphore;
 
+	if (error_code & ACE_USERMODE)
+		flags |= FAULT_FLAG_USER;
+
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
 	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
@@ -166,14 +169,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
  */
 good_area:
 	info.si_code = SEGV_ACCERR;
-	write = 0;
 	switch (error_code & (ACE_WRITE|ACE_PROTECTION)) {
 		default:	/* 3: write, present */
 			/* fall through */
 		case ACE_WRITE:	/* write, not present */
 			if (!(vma->vm_flags & VM_WRITE))
 				goto bad_area;
-			write++;
+			flags |= FAULT_FLAG_WRITE;
 			break;
 		case ACE_PROTECTION:	/* read, present */
 		case 0:		/* read, not present */
@@ -194,7 +196,7 @@ good_area:
 	 */
 	addr = (address & PAGE_MASK);
 	set_thread_fault_code(error_code);
-	fault = handle_mm_fault(mm, vma, addr, write ? FAULT_FLAG_WRITE : 0);
+	fault = handle_mm_fault(mm, vma, addr, flags);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 821170e..c3cda41 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -11,6 +11,7 @@ config M68K
 	select VIRT_TO_BUS
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 	select GENERIC_CPU_DEVICES
+	select GENERIC_IOMAP
 	select GENERIC_STRNCPY_FROM_USER if MMU
 	select GENERIC_STRNLEN_USER if MMU
 	select FPU if MMU
@@ -72,7 +73,6 @@ source "kernel/Kconfig.freezer"
 config MMU
 	bool "MMU-based Paged Memory Management Support"
 	default y
-	select GENERIC_IOMAP
 	help
 	  Select if you want MMU-based virtualised addressing space
 	  support by paged memory management. If unsure, say 'Y'.
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index b9ab0a6..61dc643 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -150,18 +150,6 @@ config XCOPILOT_BUGS
 	help
 	  Support the bugs of Xcopilot.
 
-config UC5272
-	bool "Arcturus Networks uC5272 dimm board support"
-	depends on M5272
-	help
-	  Support for the Arcturus Networks uC5272 dimm board.
-
-config UC5282
-	bool "Arcturus Networks uC5282 board support"
-	depends on M528x
-	help
-	  Support for the Arcturus Networks uC5282 dimm board.
-
 config UCSIMM
 	bool "uCsimm module support"
 	depends on M68EZ328
@@ -205,23 +193,15 @@ config UCQUICC
 	help
 	  Support for the Lineo uCquicc board.
 
-config ARNEWSH
-	bool
-
 config ARN5206
 	bool "Arnewsh 5206 board support"
 	depends on M5206
-	select ARNEWSH
 	help
 	  Support for the Arnewsh 5206 board.
 
-config FREESCALE
-	bool
-
 config M5206eC3
 	bool "Motorola M5206eC3 board support"
 	depends on M5206e
-	select FREESCALE
 	help
 	  Support for the Motorola M5206eC3 board.
 
@@ -231,88 +211,24 @@ config ELITE
 	help
 	  Support for the Motorola M5206eLITE board.
 
-config M5208EVB
-	bool "Freescale M5208EVB board support"
-	depends on M520x
-	select FREESCALE
-	help
-	  Support for the Freescale Coldfire M5208EVB.
-
 config M5235EVB
 	bool "Freescale M5235EVB support"
 	depends on M523x
-	select FREESCALE
 	help
 	  Support for the Freescale M5235EVB board.
 
 config M5249C3
 	bool "Motorola M5249C3 board support"
 	depends on M5249
-	select FREESCALE
 	help
 	  Support for the Motorola M5249C3 board.
 
-config M5271EVB
-	bool "Freescale (Motorola) M5271EVB board support"
-	depends on M5271
-	select FREESCALE
-	help
-	  Support for the Freescale (Motorola) M5271EVB board.
-
-config M5275EVB
-	bool "Freescale (Motorola) M5275EVB board support"
-	depends on M5275
-	select FREESCALE
-	help
-	  Support for the Freescale (Motorola) M5275EVB board.
-
 config M5272C3
 	bool "Motorola M5272C3 board support"
 	depends on M5272
-	select FREESCALE
 	help
 	  Support for the Motorola M5272C3 board.
 
-config senTec
-	bool
-
-config COBRA5272
-	bool "senTec COBRA5272 board support"
-	depends on M5272
-	select senTec
-	help
-	  Support for the senTec COBRA5272 board.
-
-config AVNET
-	bool
-
-config AVNET5282
-	bool "Avnet 5282 board support"
-	depends on M528x
-	select AVNET
-	help
-	  Support for the Avnet 5282 board.
-
-config M5282EVB
-	bool "Motorola M5282EVB board support"
-	depends on M528x
-	select FREESCALE
-	help
-	  Support for the Motorola M5282EVB board.
-
-config COBRA5282
-	bool "senTec COBRA5282 board support"
-	depends on M528x
-	select senTec
-	help
-	  Support for the senTec COBRA5282 board.
-
-config SOM5282EM
-	bool "EMAC.Inc SOM5282EM board support"
-	depends on M528x
-	help
-	  Support for the EMAC.Inc SOM5282EM module.
-
 config WILDFIRE
 	bool "Intec Automation Inc. WildFire board support"
 	depends on M528x
@@ -328,14 +244,12 @@ config WILDFIREMOD
 config ARN5307
 	bool "Arnewsh 5307 board support"
 	depends on M5307
-	select ARNEWSH
 	help
 	  Support for the Arnewsh 5307 board.
 
 config M5307C3
 	bool "Motorola M5307C3 board support"
 	depends on M5307
-	select FREESCALE
 	help
 	  Support for the Motorola M5307C3 board.
 
@@ -345,30 +259,9 @@ config SECUREEDGEMP3
 	help
 	  Support for the SnapGear SecureEdge/MP3 platform.
 
-config M5329EVB
-	bool "Freescale (Motorola) M5329EVB board support"
-	depends on M532x
-	select FREESCALE
-	help
-	  Support for the Freescale (Motorola) M5329EVB board.
-
-config COBRA5329
-	bool "senTec COBRA5329 board support"
-	depends on M532x
-	help
-	  Support for the senTec COBRA5329 board.
-
-config M5373EVB
-	bool "Freescale M5373EVB board support"
-	depends on M537x
-	select FREESCALE
-	help
-	  Support for the Freescale M5373EVB board.
-
 config M5407C3
 	bool "Motorola M5407C3 board support"
 	depends on M5407
-	select FREESCALE
 	help
 	  Support for the Motorola M5407C3 board.
 
@@ -402,39 +295,12 @@ config NETtel
 	help
 	  Support for the SnapGear NETtel/SecureEdge/SnapGear boards.
 
-config SNAPGEAR
-	bool "SnapGear router board support"
-	depends on NETtel
-	help
-	  Special additional support for SnapGear router boards.
-
-config SNEHA
-	bool
-
-config CPU16B
-	bool "Sneha Technologies S.L. Sarasvati board support"
-	depends on M5272
-	select SNEHA
-	help
-	  Support for the SNEHA CPU16B board.
-
 config MOD5272
 	bool "Netburner MOD-5272 board support"
 	depends on M5272
 	help
 	  Support for the Netburner MOD-5272 board.
 
-config SAVANT
-	bool
-
-config SAVANTrosie1
-	bool "Savant Rosie1 board support"
-	depends on M523x
-	select SAVANT
-	help
-	  Support for the Savant Rosie1 board.
-
-
 if !MMU || COLDFIRE
 
 comment "Machine Options"
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c
index 6083088..dacd9f9 100644
--- a/arch/m68k/amiga/platform.c
+++ b/arch/m68k/amiga/platform.c
@@ -56,7 +56,7 @@ static int __init amiga_init_bus(void)
 	n = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
 	pdev = platform_device_register_simple("amiga-zorro", -1,
 					       zorro_resources, n);
-	return PTR_RET(pdev);
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 subsys_initcall(amiga_init_bus);
diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h
index 353bf75..e153478 100644
--- a/arch/m68k/include/asm/io_no.h
+++ b/arch/m68k/include/asm/io_no.h
@@ -4,6 +4,7 @@
 #ifdef __KERNEL__
 
 #include <asm/virtconvert.h>
+#include <asm-generic/iomap.h>
 
 /*
  * These are for ISA/PCI shared memory _only_ and should never be used
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
index 7c360da..38b024a 100644
--- a/arch/m68k/include/asm/page.h
+++ b/arch/m68k/include/asm/page.h
@@ -48,6 +48,9 @@ extern unsigned long _ramend;
 #include <asm/page_no.h>
 #endif
 
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
 #include <asm-generic/getorder.h>
 
 #endif /* _M68K_PAGE_H */
diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h
index 89f2014..5029f73 100644
--- a/arch/m68k/include/asm/page_mm.h
+++ b/arch/m68k/include/asm/page_mm.h
@@ -173,7 +173,4 @@ static inline __attribute_const__ int __virt_to_node_shift(void)
 
 #endif /* __ASSEMBLY__ */
 
-#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
-				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
 #endif /* _M68K_PAGE_MM_H */
diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c
index 911ba47..5b16f5d 100644
--- a/arch/m68k/kernel/setup_no.c
+++ b/arch/m68k/kernel/setup_no.c
@@ -118,7 +118,7 @@ void (*mach_power_off)(void);
  *
  * Returns:
  */
-void parse_uboot_commandline(char *commandp, int size)
+static void __init parse_uboot_commandline(char *commandp, int size)
 {
 	extern unsigned long _init_sp;
 	unsigned long *sp;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 2a16df3..57fd286 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -50,6 +50,7 @@
 #include <asm/pgtable.h>
 #include <asm/traps.h>
 #include <asm/ucontext.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_MMU
 
@@ -181,6 +182,13 @@ static inline void push_cache (unsigned long vaddr)
 		asm volatile ("movec %0,%%caar\n\t"
 			      "movec %1,%%cacr"
 			      : : "r" (vaddr + 4), "r" (temp));
+	} else {
+		/* CPU_IS_COLDFIRE */
+#if defined(CONFIG_CACHE_COPYBACK)
+		flush_cf_dcache(0, DCACHE_MAX_ADDR);
+#endif
+		/* Invalidate instruction cache for the pushed bytes */
+		clear_cf_icache(vaddr, vaddr + 8);
 	}
 }
 
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index bea6bcf..7eb9792 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -90,7 +90,7 @@ static int __init rtc_init(void)
 		return -ENODEV;
 
 	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
-	return PTR_RET(pdev);
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 module_init(rtc_init);
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index a563727..eb1d61f 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -88,6 +88,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 
diff --git a/arch/m68k/platform/68000/m68328.c b/arch/m68k/platform/68000/m68328.c
index a86eb66..e53caf4 100644
--- a/arch/m68k/platform/68000/m68328.c
+++ b/arch/m68k/platform/68000/m68328.c
@@ -15,6 +15,7 @@
 
 /***************************************************************************/
 
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rtc.h>
@@ -42,7 +43,7 @@ void m68328_reset (void)
 
 /***************************************************************************/
 
-void config_BSP(char *command, int len)
+void __init config_BSP(char *command, int len)
 {
   printk(KERN_INFO "\n68328 support D. Jeff Dionne <jeff@uclinux.org>\n");
   printk(KERN_INFO "68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
diff --git a/arch/m68k/platform/68000/m68EZ328.c b/arch/m68k/platform/68000/m68EZ328.c
index a6eb72d..332b5e8 100644
--- a/arch/m68k/platform/68000/m68EZ328.c
+++ b/arch/m68k/platform/68000/m68EZ328.c
@@ -13,6 +13,7 @@
 
 /***************************************************************************/
 
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rtc.h>
@@ -52,7 +53,7 @@ _bsc1(unsigned char *, gethwaddr, int, a)
 _bsc1(char *, getbenv, char *, a)
 #endif
 
-void config_BSP(char *command, int len)
+void __init config_BSP(char *command, int len)
 {
   unsigned char *p;
 
diff --git a/arch/m68k/platform/68000/m68VZ328.c b/arch/m68k/platform/68000/m68VZ328.c
index eb6964f..fd66583 100644
--- a/arch/m68k/platform/68000/m68VZ328.c
+++ b/arch/m68k/platform/68000/m68VZ328.c
@@ -14,6 +14,7 @@
 
 /***************************************************************************/
 
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/kd.h>
@@ -59,7 +60,7 @@ static void m68vz328_reset(void)
 	);
 }
 
-static void init_hardware(char *command, int size)
+static void __init init_hardware(char *command, int size)
 {
 #ifdef CONFIG_DIRECT_IO_ACCESS
 	SCR = 0x10;					/* allow user access to internal registers */
@@ -145,7 +146,7 @@ _bsc0(char *, getserialnum)
 _bsc1(unsigned char *, gethwaddr, int, a)
 _bsc1(char *, getbenv, char *, a)
 
-static void init_hardware(char *command, int size)
+static void __init init_hardware(char *command, int size)
 {
 	char *p;
 
@@ -167,7 +168,7 @@ static void m68vz328_reset(void)
 {
 }
 
-static void init_hardware(char *command, int size)
+static void __init init_hardware(char *command, int size)
 {
 }
 
@@ -175,7 +176,7 @@ static void init_hardware(char *command, int size)
 #endif
 /***************************************************************************/
 
-void config_BSP(char *command, int size)
+void __init config_BSP(char *command, int size)
 {
 	printk(KERN_INFO "68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
 
diff --git a/arch/m68k/platform/68360/commproc.c b/arch/m68k/platform/68360/commproc.c
index 8e4e10c..315727b 100644
--- a/arch/m68k/platform/68360/commproc.c
+++ b/arch/m68k/platform/68360/commproc.c
@@ -31,6 +31,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
@@ -77,7 +78,7 @@ void m360_cpm_reset(void);
 
 
 
-void m360_cpm_reset()
+void __init m360_cpm_reset()
 {
 /* 	pte_t		   *pte; */
 
diff --git a/arch/m68k/platform/68360/config.c b/arch/m68k/platform/68360/config.c
index 9877cef..0570741 100644
--- a/arch/m68k/platform/68360/config.c
+++ b/arch/m68k/platform/68360/config.c
@@ -11,6 +11,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -140,7 +141,7 @@ _bsc1(char *, getbenv, char *, a)
 #endif
 
 
-void config_BSP(char *command, int len)
+void __init config_BSP(char *command, int len)
 {
   unsigned char *p;
 
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 658542b..078bb74 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -338,6 +338,6 @@ static __init int q40_add_kbd_device(void)
 		return -ENODEV;
 
 	pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
-	return PTR_RET(pdev);
+	return PTR_ERR_OR_ZERO(pdev);
 }
 arch_initcall(q40_add_kbd_device);
diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc
index 2a3c860..973640f 100644
--- a/arch/metag/Kconfig.soc
+++ b/arch/metag/Kconfig.soc
@@ -16,6 +16,8 @@ config META21_FPGA
 
 config SOC_TZ1090
 	bool "Toumaz Xenif TZ1090 SoC (Comet)"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select IMGPDC_IRQ
 	select METAG_LNKGET_AROUND_CACHE
 	select METAG_META21
 	select METAG_SMP_WRITE_REORDERING
diff --git a/arch/metag/boot/dts/tz1090.dtsi b/arch/metag/boot/dts/tz1090.dtsi
index 8537446..24ea7d2 100644
--- a/arch/metag/boot/dts/tz1090.dtsi
+++ b/arch/metag/boot/dts/tz1090.dtsi
@@ -8,6 +8,8 @@
 
 #include "skeleton.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
 	compatible = "toumaz,tz1090", "img,meta";
 
@@ -26,6 +28,22 @@
 		#size-cells = <1>;
 		ranges;
 
+		pdc: pdc@0x02006000 {
+			interrupt-controller;
+			#interrupt-cells = <2>;
+
+			reg = <0x02006000 0x1000>;
+			compatible = "img,pdc-intc";
+
+			num-perips = <3>;
+			num-syswakes = <3>;
+
+			interrupts = <18 IRQ_TYPE_LEVEL_HIGH>, /* Syswakes */
+			             <30 IRQ_TYPE_LEVEL_HIGH>, /* Perip 0 (RTC) */
+			             <29 IRQ_TYPE_LEVEL_HIGH>, /* Perip 1 (IR) */
+			             <31 IRQ_TYPE_LEVEL_HIGH>; /* Perip 2 (WDT) */
+		};
+
 		pinctrl: pinctrl@02005800 {
 			#gpio-range-cells = <3>;
 			compatible = "img,tz1090-pinctrl";
@@ -37,5 +55,54 @@
 			compatible = "img,tz1090-pdc-pinctrl";
 			reg = <0x02006500 0x100>;
 		};
+
+		gpios: gpios@02005800 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "img,tz1090-gpio";
+			reg = <0x02005800 0x90>;
+
+			gpios0: bank@0 {
+				gpio-controller;
+				interrupt-controller;
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				reg = <0>;
+				interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-ranges = <&pinctrl 0 0 30>;
+			};
+			gpios1: bank@1 {
+				gpio-controller;
+				interrupt-controller;
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				reg = <1>;
+				interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-ranges = <&pinctrl 0 30 30>;
+			};
+			gpios2: bank@2 {
+				gpio-controller;
+				interrupt-controller;
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				reg = <2>;
+				interrupts = <15 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-ranges = <&pinctrl 0 60 30>;
+			};
+		};
+
+		pdc_gpios: gpios@02006500 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			compatible = "img,tz1090-pdc-gpio";
+			reg = <0x02006500 0x100>;
+
+			interrupt-parent = <&pdc>;
+			interrupts =	<8  IRQ_TYPE_NONE>,
+					<9  IRQ_TYPE_NONE>,
+					<10 IRQ_TYPE_NONE>;
+			gpio-ranges = <&pdc_pinctrl 0 0 7>;
+		};
 	};
 };
diff --git a/arch/metag/mm/fault.c b/arch/metag/mm/fault.c
index 8fddf46..332680e 100644
--- a/arch/metag/mm/fault.c
+++ b/arch/metag/mm/fault.c
@@ -53,8 +53,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
 	struct vm_area_struct *vma, *prev_vma;
 	siginfo_t info;
 	int fault;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				(write_access ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	tsk = current;
 
@@ -109,6 +108,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 
@@ -121,6 +122,7 @@ good_area:
 	if (write_access) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 			goto bad_area;
diff --git a/arch/metag/mm/init.c b/arch/metag/mm/init.c
index 28813f1..1239195 100644
--- a/arch/metag/mm/init.c
+++ b/arch/metag/mm/init.c
@@ -407,10 +407,9 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 #endif
 
 #ifdef CONFIG_OF_FLATTREE
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
-	pr_err("%s(%lx, %lx)\n",
+	pr_err("%s(%llx, %llx)\n",
 	       __func__, start, end);
 }
 #endif /* CONFIG_OF_FLATTREE */
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index d22a4ec..4fab522 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -28,7 +28,7 @@ config MICROBLAZE
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IDLE_POLL_SETUP
 	select MODULES_USE_ELF_RELA
-	select CLONE_BACKWARDS
+	select CLONE_BACKWARDS3
 
 config SWAP
 	def_bool n
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 0a2c68f..62e2e8f 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -136,8 +136,7 @@ void __init early_init_devtree(void *params)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-		unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (unsigned long)__va(start);
 	initrd_end = (unsigned long)__va(end);
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
index 731f739..fa4cf52 100644
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -92,8 +92,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
 	int code = SEGV_MAPERR;
 	int is_write = error_code & ESR_S;
 	int fault;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-					 (is_write ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	regs->ear = address;
 	regs->esr = error_code;
@@ -121,6 +120,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
 		die("Weird page fault", regs, SIGSEGV);
 	}
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
 	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
@@ -199,6 +201,7 @@ good_area:
 	if (unlikely(is_write)) {
 		if (unlikely(!(vma->vm_flags & VM_WRITE)))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	/* a read */
 	} else {
 		/* protection fault */
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index bdb8ea1..1b93bf0 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -657,67 +657,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
 void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 				  struct device_node *dev, int primary)
 {
-	const u32 *ranges;
-	int rlen;
-	int pna = of_n_addr_cells(dev);
-	int np = pna + 5;
 	int memno = 0, isa_hole = -1;
-	u32 pci_space;
-	unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
 	unsigned long long isa_mb = 0;
 	struct resource *res;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
 
 	pr_info("PCI host bridge %s %s ranges:\n",
 	       dev->full_name, primary ? "(primary)" : "");
 
-	/* Get ranges property */
-	ranges = of_get_property(dev, "ranges", &rlen);
-	if (ranges == NULL)
+	/* Check for ranges property */
+	if (of_pci_range_parser_init(&parser, dev))
 		return;
 
-	/* Parse it */
 	pr_debug("Parsing ranges property...\n");
-	while ((rlen -= np * 4) >= 0) {
+	for_each_of_pci_range(&parser, &range) {
 		/* Read next ranges element */
-		pci_space = ranges[0];
-		pci_addr = of_read_number(ranges + 1, 2);
-		cpu_addr = of_translate_address(dev, ranges + 3);
-		size = of_read_number(ranges + pna + 3, 2);
-
 		pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
-				pci_space, pci_addr);
+				range.pci_space, range.pci_addr);
 		pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
-					cpu_addr, size);
-
-		ranges += np;
+					range.cpu_addr, range.size);
 
 		/* If we failed translation or got a zero-sized region
 		 * (some FW try to feed us with non sensical zero sized regions
 		 * such as power3 which look like some kind of attempt
 		 * at exposing the VGA memory hole)
 		 */
-		if (cpu_addr == OF_BAD_ADDR || size == 0)
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
 			continue;
 
-		/* Now consume following elements while they are contiguous */
-		for (; rlen >= np * sizeof(u32);
-		     ranges += np, rlen -= np * 4) {
-			if (ranges[0] != pci_space)
-				break;
-			pci_next = of_read_number(ranges + 1, 2);
-			cpu_next = of_translate_address(dev, ranges + 3);
-			if (pci_next != pci_addr + size ||
-			    cpu_next != cpu_addr + size)
-				break;
-			size += of_read_number(ranges + pna + 3, 2);
-		}
-
 		/* Act based on address space type */
 		res = NULL;
-		switch ((pci_space >> 24) & 0x3) {
-		case 1:		/* PCI IO space */
+		switch (range.flags & IORESOURCE_TYPE_BITS) {
+		case IORESOURCE_IO:
 			pr_info("  IO 0x%016llx..0x%016llx -> 0x%016llx\n",
-			       cpu_addr, cpu_addr + size - 1, pci_addr);
+				range.cpu_addr, range.cpu_addr + range.size - 1,
+				range.pci_addr);
 
 			/* We support only one IO range */
 			if (hose->pci_io_size) {
@@ -725,11 +700,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 				continue;
 			}
 			/* On 32 bits, limit I/O space to 16MB */
-			if (size > 0x01000000)
-				size = 0x01000000;
+			if (range.size > 0x01000000)
+				range.size = 0x01000000;
 
 			/* 32 bits needs to map IOs here */
-			hose->io_base_virt = ioremap(cpu_addr, size);
+			hose->io_base_virt = ioremap(range.cpu_addr,
+						range.size);
 
 			/* Expect trouble if pci_addr is not 0 */
 			if (primary)
@@ -738,19 +714,20 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 			/* pci_io_size and io_base_phys always represent IO
 			 * space starting at 0 so we factor in pci_addr
 			 */
-			hose->pci_io_size = pci_addr + size;
-			hose->io_base_phys = cpu_addr - pci_addr;
+			hose->pci_io_size = range.pci_addr + range.size;
+			hose->io_base_phys = range.cpu_addr - range.pci_addr;
 
 			/* Build resource */
 			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = pci_addr;
+			range.cpu_addr = range.pci_addr;
+
 			break;
-		case 2:		/* PCI Memory space */
-		case 3:		/* PCI 64 bits Memory space */
+		case IORESOURCE_MEM:
 			pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
-			       cpu_addr, cpu_addr + size - 1, pci_addr,
-			       (pci_space & 0x40000000) ? "Prefetch" : "");
+				range.cpu_addr, range.cpu_addr + range.size - 1,
+				range.pci_addr,
+				(range.pci_space & 0x40000000) ?
+				"Prefetch" : "");
 
 			/* We support only 3 memory ranges */
 			if (memno >= 3) {
@@ -758,13 +735,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 				continue;
 			}
 			/* Handles ISA memory hole space here */
-			if (pci_addr == 0) {
-				isa_mb = cpu_addr;
+			if (range.pci_addr == 0) {
+				isa_mb = range.cpu_addr;
 				isa_hole = memno;
 				if (primary || isa_mem_base == 0)
-					isa_mem_base = cpu_addr;
-				hose->isa_mem_phys = cpu_addr;
-				hose->isa_mem_size = size;
+					isa_mem_base = range.cpu_addr;
+				hose->isa_mem_phys = range.cpu_addr;
+				hose->isa_mem_size = range.size;
 			}
 
 			/* We get the PCI/Mem offset from the first range or
@@ -772,30 +749,23 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 			 * hole. If they don't match, bugger.
 			 */
 			if (memno == 0 ||
-			    (isa_hole >= 0 && pci_addr != 0 &&
+			    (isa_hole >= 0 && range.pci_addr != 0 &&
 			     hose->pci_mem_offset == isa_mb))
-				hose->pci_mem_offset = cpu_addr - pci_addr;
-			else if (pci_addr != 0 &&
-				 hose->pci_mem_offset != cpu_addr - pci_addr) {
+				hose->pci_mem_offset = range.cpu_addr -
+							range.pci_addr;
+			else if (range.pci_addr != 0 &&
+				 hose->pci_mem_offset != range.cpu_addr -
+							range.pci_addr) {
 				pr_info(" \\--> Skipped (offset mismatch) !\n");
 				continue;
 			}
 
 			/* Build resource */
 			res = &hose->mem_resources[memno++];
-			res->flags = IORESOURCE_MEM;
-			if (pci_space & 0x40000000)
-				res->flags |= IORESOURCE_PREFETCH;
-			res->start = cpu_addr;
 			break;
 		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
+		if (res != NULL)
+			of_pci_range_to_resource(&range, dev, res);
 	}
 
 	/* If there's an ISA hole and the pci_mem_offset is -not- matching
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e12764c..1e31fcb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -727,7 +727,6 @@ config CAVIUM_OCTEON_SOC
 	select SYS_HAS_CPU_CAVIUM_OCTEON
 	select SWAP_IO_SPACE
 	select HW_HAS_PCI
-	select ARCH_SUPPORTS_MSI
 	select ZONE_DMA32
 	select USB_ARCH_HAS_OHCI
 	select USB_ARCH_HAS_EHCI
@@ -763,7 +762,6 @@ config NLM_XLR_BOARD
 	select CEVT_R4K
 	select CSRC_R4K
 	select IRQ_CPU
-	select ARCH_SUPPORTS_MSI
 	select ZONE_DMA32 if 64BIT
 	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
index e652e57..4b50d40 100644
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -35,6 +35,8 @@ struct bcm963xx_nvram {
 	u32	checksum_high;
 };
 
+#define BCM63XX_DEFAULT_PSI_SIZE	64
+
 static struct bcm963xx_nvram nvram;
 static int mac_addr_used;
 
@@ -114,3 +116,12 @@ int bcm63xx_nvram_get_mac_address(u8 *mac)
 	return 0;
 }
 EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
+
+int bcm63xx_nvram_get_psi_size(void)
+{
+	if (nvram.psi_size > 0)
+		return nvram.psi_size;
+
+	return BCM63XX_DEFAULT_PSI_SIZE;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 48b08eb..b212ae1 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -8,6 +8,7 @@
  *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/compiler.h>
+#include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
@@ -1139,3 +1140,30 @@ static int __init edac_devinit(void)
 	return err;
 }
 device_initcall(edac_devinit);
+
+static void __initdata *octeon_dummy_iospace;
+
+static int __init octeon_no_pci_init(void)
+{
+	/*
+	 * Initially assume there is no PCI. The PCI/PCIe platform code will
+	 * later re-initialize these to correct values if they are present.
+	 */
+	octeon_dummy_iospace = vzalloc(IO_SPACE_LIMIT);
+	set_io_port_base((unsigned long)octeon_dummy_iospace);
+	ioport_resource.start = MAX_RESOURCE;
+	ioport_resource.end = 0;
+	return 0;
+}
+core_initcall(octeon_no_pci_init);
+
+static int __init octeon_no_pci_release(void)
+{
+	/*
+	 * Release the allocated memory if a real IO space is there.
+	 */
+	if ((unsigned long)octeon_dummy_iospace != mips_io_port_base)
+		vfree(octeon_dummy_iospace);
+	return 0;
+}
+late_initcall(octeon_no_pci_release);
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9b54b7a..454ddf9 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -1,2 +1,15 @@
 # MIPS headers
+generic-y += cputime.h
+generic-y += current.h
+generic-y += emergency-restart.h
+generic-y += local64.h
+generic-y += mutex.h
+generic-y += parport.h
+generic-y += percpu.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += serial.h
 generic-y += trace_clock.h
+generic-y += ucontext.h
+generic-y += xor.h
diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h
index 552a65a..4ea23ae 100644
--- a/arch/mips/include/asm/bmips.h
+++ b/arch/mips/include/asm/bmips.h
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <asm/addrspace.h>
+#include <asm/r4kcache.h>
 #include <asm/mipsregs.h>
 #include <asm/hazards.h>
 
@@ -65,44 +66,33 @@ static inline unsigned long bmips_read_zscm_reg(unsigned int offset)
 {
 	unsigned long ret;
 
-	__asm__ __volatile__(
-		".set push\n"
-		".set noreorder\n"
-		"cache %1, 0(%2)\n"
-		"sync\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"mfc0 %0, $28, 3\n"
-		"_ssnop\n"
-		".set pop\n"
-		: "=&r" (ret)
-		: "i" (Index_Load_Tag_S), "r" (ZSCM_REG_BASE + offset)
-		: "memory");
+	barrier();
+	cache_op(Index_Load_Tag_S, ZSCM_REG_BASE + offset);
+	__sync();
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	ret = read_c0_ddatalo();
+	_ssnop();
+
 	return ret;
 }
 
 static inline void bmips_write_zscm_reg(unsigned int offset, unsigned long data)
 {
-	__asm__ __volatile__(
-		".set push\n"
-		".set noreorder\n"
-		"mtc0 %0, $28, 3\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"cache %1, 0(%2)\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		"_ssnop\n"
-		: /* no outputs */
-		: "r" (data),
-		  "i" (Index_Store_Tag_S), "r" (ZSCM_REG_BASE + offset)
-		: "memory");
+	write_c0_ddatalo(data);
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	cache_op(Index_Store_Tag_S, ZSCM_REG_BASE + offset);
+	_ssnop();
+	_ssnop();
+	_ssnop();
+	barrier();
 }
 
 #endif /* !defined(__ASSEMBLY__) */
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 1dc0860..fa44f3e 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -17,6 +17,8 @@
 #define current_cpu_type()	current_cpu_data.cputype
 #endif
 
+#define boot_cpu_type()		cpu_data[0].cputype
+
 /*
  * SMP assumption: Options of CPU 0 are a superset of all processors.
  * This is true for all known MIPS systems.
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 632bbe5..c198615 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -141,6 +141,9 @@
 #define PRID_IMP_CAVIUM_CN68XX 0x9100
 #define PRID_IMP_CAVIUM_CN66XX 0x9200
 #define PRID_IMP_CAVIUM_CN61XX 0x9300
+#define PRID_IMP_CAVIUM_CNF71XX 0x9400
+#define PRID_IMP_CAVIUM_CN78XX 0x9500
+#define PRID_IMP_CAVIUM_CN70XX 0x9600
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
@@ -272,7 +275,7 @@ enum cpu_type_enum {
 	 */
 	CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
 	CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
-	CPU_XLR, CPU_XLP,
+	CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
 
 	CPU_LAST
 };
diff --git a/arch/mips/include/asm/cputime.h b/arch/mips/include/asm/cputime.h
deleted file mode 100644
index c00eacb..0000000
--- a/arch/mips/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MIPS_CPUTIME_H
-#define __MIPS_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __MIPS_CPUTIME_H */
diff --git a/arch/mips/include/asm/current.h b/arch/mips/include/asm/current.h
deleted file mode 100644
index 4c51401..0000000
--- a/arch/mips/include/asm/current.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/current.h>
diff --git a/arch/mips/include/asm/emergency-restart.h b/arch/mips/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c4..0000000
--- a/arch/mips/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/mips/include/asm/local64.h b/arch/mips/include/asm/local64.h
deleted file mode 100644
index 36c93b5..0000000
--- a/arch/mips/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
index 4e0b6bc..348df49 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
@@ -30,4 +30,6 @@ u8 *bcm63xx_nvram_get_name(void);
  */
 int bcm63xx_nvram_get_mac_address(u8 *mac);
 
+int bcm63xx_nvram_get_psi_size(void);
+
 #endif /* BCM63XX_NVRAM_H */
diff --git a/arch/mips/include/asm/mutex.h b/arch/mips/include/asm/mutex.h
deleted file mode 100644
index 458c1f7..0000000
--- a/arch/mips/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/mips/include/asm/parport.h b/arch/mips/include/asm/parport.h
deleted file mode 100644
index cf252af..0000000
--- a/arch/mips/include/asm/parport.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/parport.h>
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index fa8e0aa..f194c08 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -136,11 +136,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 	return channel ? 15 : 14;
 }
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-/* MSI arch hook for OCTEON */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#endif
-
 extern char * (*pcibios_plat_setup)(char *str);
 
 #ifdef CONFIG_OF
diff --git a/arch/mips/include/asm/percpu.h b/arch/mips/include/asm/percpu.h
deleted file mode 100644
index 844e763..0000000
--- a/arch/mips/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_PERCPU_H
-#define __ASM_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ASM_PERCPU_H */
diff --git a/arch/mips/include/asm/scatterlist.h b/arch/mips/include/asm/scatterlist.h
deleted file mode 100644
index 7ee0e64..0000000
--- a/arch/mips/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_SCATTERLIST_H
-#define __ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* __ASM_SCATTERLIST_H */
diff --git a/arch/mips/include/asm/sections.h b/arch/mips/include/asm/sections.h
deleted file mode 100644
index b7e3726..0000000
--- a/arch/mips/include/asm/sections.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SECTIONS_H
-#define _ASM_SECTIONS_H
-
-#include <asm-generic/sections.h>
-
-#endif /* _ASM_SECTIONS_H */
diff --git a/arch/mips/include/asm/segment.h b/arch/mips/include/asm/segment.h
deleted file mode 100644
index 92ac001..0000000
--- a/arch/mips/include/asm/segment.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SEGMENT_H
-#define _ASM_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif /* _ASM_SEGMENT_H */
diff --git a/arch/mips/include/asm/serial.h b/arch/mips/include/asm/serial.h
deleted file mode 100644
index a0cb0ca..0000000
--- a/arch/mips/include/asm/serial.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/serial.h>
diff --git a/arch/mips/include/asm/ucontext.h b/arch/mips/include/asm/ucontext.h
deleted file mode 100644
index 9bc07b9..0000000
--- a/arch/mips/include/asm/ucontext.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ucontext.h>
diff --git a/arch/mips/include/asm/xor.h b/arch/mips/include/asm/xor.h
deleted file mode 100644
index c82eb12..0000000
--- a/arch/mips/include/asm/xor.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild
index 350cccc..be7196e 100644
--- a/arch/mips/include/uapi/asm/Kbuild
+++ b/arch/mips/include/uapi/asm/Kbuild
@@ -1,7 +1,9 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += auxvec.h
+generic-y += auxvec.h
+generic-y += ipcbuf.h
+
 header-y += bitsperlong.h
 header-y += break.h
 header-y += byteorder.h
@@ -11,7 +13,6 @@ header-y += fcntl.h
 header-y += inst.h
 header-y += ioctl.h
 header-y += ioctls.h
-header-y += ipcbuf.h
 header-y += kvm_para.h
 header-y += mman.h
 header-y += msgbuf.h
diff --git a/arch/mips/include/uapi/asm/auxvec.h b/arch/mips/include/uapi/asm/auxvec.h
deleted file mode 100644
index 7cf7f2d..0000000
--- a/arch/mips/include/uapi/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef _ASM_AUXVEC_H
-#define _ASM_AUXVEC_H
-
-#endif /* _ASM_AUXVEC_H */
diff --git a/arch/mips/include/uapi/asm/ipcbuf.h b/arch/mips/include/uapi/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51..0000000
--- a/arch/mips/include/uapi/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 4c6167a..8e8feb8 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -852,10 +852,17 @@ platform:
 	case PRID_IMP_CAVIUM_CN63XX:
 	case PRID_IMP_CAVIUM_CN66XX:
 	case PRID_IMP_CAVIUM_CN68XX:
+	case PRID_IMP_CAVIUM_CNF71XX:
 		c->cputype = CPU_CAVIUM_OCTEON2;
 		__cpu_name[cpu] = "Cavium Octeon II";
 		set_elf_platform(cpu, "octeon2");
 		break;
+	case PRID_IMP_CAVIUM_CN70XX:
+	case PRID_IMP_CAVIUM_CN78XX:
+		c->cputype = CPU_CAVIUM_OCTEON3;
+		__cpu_name[cpu] = "Cavium Octeon III";
+		set_elf_platform(cpu, "octeon3");
+		break;
 	default:
 		printk(KERN_INFO "Unknown Octeon chip!\n");
 		c->cputype = CPU_UNKNOWN;
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 0c655de..42f8875 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -166,6 +166,7 @@ void __init check_wait(void)
 	case CPU_CAVIUM_OCTEON:
 	case CPU_CAVIUM_OCTEON_PLUS:
 	case CPU_CAVIUM_OCTEON2:
+	case CPU_CAVIUM_OCTEON3:
 	case CPU_JZRISC:
 	case CPU_LOONGSON1:
 	case CPU_XLR:
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index 7e95404..0fa0b69 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -58,8 +58,7 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (unsigned long)__va(start);
 	initrd_end = (unsigned long)__va(end);
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 159abc8..126da74 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -66,6 +66,8 @@ static void __init bmips_smp_setup(void)
 	int i, cpu = 1, boot_cpu = 0;
 
 #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
+	int cpu_hw_intr;
+
 	/* arbitration priority */
 	clear_c0_brcm_cmt_ctrl(0x30);
 
@@ -80,8 +82,12 @@ static void __init bmips_smp_setup(void)
 	 * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
 	 * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
 	 */
-	change_c0_brcm_cmt_intr(0xf8018000,
-					(0x02 << 27) | (0x03 << 15));
+	if (boot_cpu == 0)
+		cpu_hw_intr = 0x02;
+	else
+		cpu_hw_intr = 0x1d;
+
+	change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15));
 
 	/* single core, 2 threads (2 pipelines) */
 	max_cpus = 2;
diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c
index dd203e5..a7b0445 100644
--- a/arch/mips/kvm/kvm_mips.c
+++ b/arch/mips/kvm/kvm_mips.c
@@ -208,6 +208,10 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 	return 0;
 }
 
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                 struct kvm_memory_slot *memslot,
                                 struct kvm_userspace_memory_region *mem,
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index a0bcdbb..729e770 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -224,6 +224,20 @@ static void probe_octeon(void)
 		c->options |= MIPS_CPU_PREFETCH;
 		break;
 
+	case CPU_CAVIUM_OCTEON3:
+		c->icache.linesz = 128;
+		c->icache.sets = 16;
+		c->icache.ways = 39;
+		c->icache.flags |= MIPS_CACHE_VTAG;
+		icache_size = c->icache.sets * c->icache.ways * c->icache.linesz;
+
+		c->dcache.linesz = 128;
+		c->dcache.ways = 32;
+		c->dcache.sets = 8;
+		dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz;
+		c->options |= MIPS_CPU_PREFETCH;
+		break;
+
 	default:
 		panic("Unsupported Cavium Networks CPU type");
 		break;
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 85df1cd..becc42b 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -42,8 +42,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
 	const int field = sizeof(unsigned long) * 2;
 	siginfo_t info;
 	int fault;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-						 (write ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 #if 0
 	printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
@@ -93,6 +92,8 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
 	if (in_atomic() || !mm)
 		goto bad_area_nosemaphore;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -114,6 +115,7 @@ good_area:
 	if (write) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (cpu_has_rixi) {
 			if (address == regs->cp0_epc && !(vma->vm_flags & VM_EXEC)) {
@@ -241,6 +243,8 @@ out_of_memory:
 	 * (which will retry the fault, or kill us if we got oom-killed).
 	 */
 	up_read(&mm->mmap_sem);
+	if (!user_mode(regs))
+		goto no_context;
 	pagefault_out_of_memory();
 	return;
 
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index 30a494d..79bca31 100644
--- a/arch/mips/mm/tlb-funcs.S
+++ b/arch/mips/mm/tlb-funcs.S
@@ -16,10 +16,12 @@
 
 #define FASTPATH_SIZE	128
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 LEAF(tlbmiss_handler_setup_pgd)
 	.space		16 * 4
 END(tlbmiss_handler_setup_pgd)
 EXPORT(tlbmiss_handler_setup_pgd_end)
+#endif
 
 LEAF(handle_tlbm)
 	.space		FASTPATH_SIZE * 4
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 556cb48..821b451 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -85,6 +85,7 @@ static int use_bbit_insns(void)
 	case CPU_CAVIUM_OCTEON:
 	case CPU_CAVIUM_OCTEON_PLUS:
 	case CPU_CAVIUM_OCTEON2:
+	case CPU_CAVIUM_OCTEON3:
 		return 1;
 	default:
 		return 0;
@@ -95,6 +96,7 @@ static int use_lwx_insns(void)
 {
 	switch (current_cpu_type()) {
 	case CPU_CAVIUM_OCTEON2:
+	case CPU_CAVIUM_OCTEON3:
 		return 1;
 	default:
 		return 0;
diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c
index ef3897e..d5378ef 100644
--- a/arch/mips/netlogic/xlp/usb-init.c
+++ b/arch/mips/netlogic/xlp/usb-init.c
@@ -75,8 +75,7 @@ static void nlm_usb_intr_en(int node, int port)
 	port_addr = nlm_get_usb_regbase(node, port);
 	val = nlm_read_usb_reg(port_addr, USB_INT_EN);
 	val = USB_CTRL_INTERRUPT_EN  | USB_OHCI_INTERRUPT_EN |
-		USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN	|
-		USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN;
+		USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN;
 	nlm_write_usb_reg(port_addr, USB_INT_EN, val);
 }
 
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index e4b1140..3a2b6e9 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -166,7 +166,7 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
 			reg.control[i] |= M_PERFCTL_USER;
 		if (ctr[i].exl)
 			reg.control[i] |= M_PERFCTL_EXL;
-		if (current_cpu_type() == CPU_XLR)
+		if (boot_cpu_type() == CPU_XLR)
 			reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
 		reg.counter[i] = 0x80000000 - ctr[i].count;
 	}
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
index 95c2ea8..59cccd9 100644
--- a/arch/mips/pci/pci-octeon.c
+++ b/arch/mips/pci/pci-octeon.c
@@ -586,15 +586,16 @@ static int __init octeon_pci_setup(void)
 	else
 		octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
 
-	/* PCI I/O and PCI MEM values */
-	set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
-	ioport_resource.start = 0;
-	ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1;
 	if (!octeon_is_pci_host()) {
 		pr_notice("Not in host mode, PCI Controller not initialized\n");
 		return 0;
 	}
 
+	/* PCI I/O and PCI MEM values */
+	set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
+	ioport_resource.start = 0;
+	ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1;
+
 	pr_notice("%s Octeon big bar support\n",
 		  (octeon_dma_bar_type ==
 		  OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling");
diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c
index d22dc0d..2b7e837 100644
--- a/arch/mips/pnx833x/common/platform.c
+++ b/arch/mips/pnx833x/common/platform.c
@@ -206,11 +206,13 @@ static struct resource pnx833x_ethernet_resources[] = {
 		.end   = PNX8335_IP3902_PORTS_END,
 		.flags = IORESOURCE_MEM,
 	},
+#ifdef CONFIG_SOC_PNX8335
 	[1] = {
 		.start = PNX8335_PIC_ETHERNET_INT,
 		.end   = PNX8335_PIC_ETHERNET_INT,
 		.flags = IORESOURCE_IRQ,
 	},
+#endif
 };
 
 static struct platform_device pnx833x_ethernet_device = {
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index dd0ab98..f9407e1 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -122,7 +122,6 @@ static struct resource sc26xx_rsrc[] = {
 
 static struct sccnxp_pdata sccnxp_data = {
 	.reg_shift	= 2,
-	.frequency	= 3686400,
 	.mctrl_cfg[0]	= MCTRL_SIG(DTR_OP, LINE_OP7) |
 			  MCTRL_SIG(RTS_OP, LINE_OP3) |
 			  MCTRL_SIG(DSR_IP, LINE_IP5) |
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
index 8a2e6de..3516cbd 100644
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -171,6 +171,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 99dbab1..d60bf98 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -55,6 +55,7 @@ config GENERIC_CSUM
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
 
 menu "Processor type and features"
 
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
index 5869e3f..150215a 100644
--- a/arch/openrisc/kernel/prom.c
+++ b/arch/openrisc/kernel/prom.c
@@ -96,8 +96,7 @@ void __init early_init_devtree(void *params)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-		unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (unsigned long)__va(start);
 	initrd_end = (unsigned long)__va(end);
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
index 4a41f84..0703acf 100644
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
 	if (user_mode(regs)) {
 		/* Exception was in userspace: reenable interrupts */
 		local_irq_enable();
+		flags |= FAULT_FLAG_USER;
 	} else {
 		/* If exception was in a syscall, then IRQ's may have
 		 * been enabled or disabled.  If they were enabled,
diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig
new file mode 100644
index 0000000..7f03614
--- /dev/null
+++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -0,0 +1,340 @@
+CONFIG_LOCALVERSION="-32bit"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_EXPERT=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PA7100LC=y
+CONFIG_SMP=y
+CONFIG_HZ_100=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_PCCARD=m
+CONFIG_YENTA=m
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_PDC_CHASSIS is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# 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=m
+CONFIG_LLC2=m
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_1284=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_LASI700=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_DH=y
+CONFIG_ATA=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_FUJITSU is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_LASI_82596=y
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_XIRCOM is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_POLLDEV=y
+CONFIG_KEYBOARD_HIL_OLD=m
+CONFIG_KEYBOARD_HIL=m
+CONFIG_MOUSE_SERIAL=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_PRINTER=m
+CONFIG_PPDEV=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_HWMON is not set
+CONFIG_AGP=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_VOODOO1=m
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_AD1889=m
+# CONFIG_SND_PCMCIA is not set
+CONFIG_SND_HARMONY=m
+CONFIG_HIDRAW=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_DRAGONRISE=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=m
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_DMADEVICES=y
+CONFIG_AUXDISPLAY=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_NFS_FS=m
+# CONFIG_NFS_V2 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_RT_MUTEX_TESTER=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_LATENCYTOP=y
+CONFIG_LKDTM=m
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_FONTS=y
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
new file mode 100644
index 0000000..6952cb5
--- /dev/null
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -0,0 +1,350 @@
+CONFIG_LOCALVERSION="-64bit"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_DEV_INTEGRITY=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_PA8X00=y
+CONFIG_MLONGCALLS=y
+CONFIG_64BIT=y
+CONFIG_SMP=y
+# CONFIG_COMPACTION is not set
+CONFIG_HPPB=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_PCI=y
+CONFIG_PCI_STUB=m
+CONFIG_PCI_IOV=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_DCB=y
+CONFIG_AF_RXRPC=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_IDE=y
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATAPI=y
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SRP_ATTRS=y
+CONFIG_ISCSI_BOOT_SYSFS=y
+CONFIG_SCSI_MPT2SAS=y
+CONFIG_SCSI_LASI700=m
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_DH=y
+CONFIG_ATA=y
+CONFIG_ATA_GENERIC=y
+CONFIG_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_RAID=m
+CONFIG_DM_UEVENT=y
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_SAS=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+CONFIG_HP100=m
+CONFIG_E1000=y
+CONFIG_LASI_82596=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+CONFIG_QLA3XXX=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_HIL_OLD is not set
+# CONFIG_KEYBOARD_HIL is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_HP_SDC_RTC=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_HP_SDC=m
+CONFIG_HIL_MLC=m
+CONFIG_SERIO_RAW=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_NOZOMI=m
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_JSM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+CONFIG_PTP_1588_CLOCK=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_WATCHDOG=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_SSB=m
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_HTC_PASIC3=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_SM501=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_AGP=y
+CONFIG_AGP_PARISC=y
+CONFIG_DRM=y
+CONFIG_DRM_RADEON=y
+CONFIG_DRM_RADEON_UMS=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_KYE=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_TWINHAN=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_HID_NTRIG=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_USB_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB_CBAF=m
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+CONFIG_UIO_PCI_GENERIC=m
+CONFIG_STAGING=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=y
+CONFIG_UDF_FS=y
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_SYSV_FS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V4=m
+CONFIG_NFS_V4_1=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V4=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_LIBCRC32C=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index f247a34..d10d27a 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -180,6 +180,10 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+	if (acc_type & VM_WRITE)
+		flags |= FAULT_FLAG_WRITE;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma_prev(mm, address, &prev_vma);
@@ -203,8 +207,7 @@ good_area:
 	 * fault.
 	 */
 
-	fault = handle_mm_fault(mm, vma, address,
-			flags | ((acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0));
+	fault = handle_mm_fault(mm, vma, address, flags);
 
 	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
 		return;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3bf72cd..183a165 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -727,7 +727,6 @@ config PCI
 	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
 		&& !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
-	select ARCH_SUPPORTS_MSI
 	select GENERIC_PCI_IOMAP
 	help
 	  Find out whether your system includes a PCI bus. PCI is the name of
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 6653f27..95145a1 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -113,11 +113,6 @@ extern int pci_domain_nr(struct pci_bus *bus);
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#define arch_teardown_msi_irqs arch_teardown_msi_irqs
-#define arch_msi_check_device arch_msi_check_device
-
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 8b24926..3fd2f1b 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -138,11 +138,11 @@ extern ssize_t power_events_sysfs_show(struct device *dev,
 #define	EVENT_PTR(_id, _suffix)		&EVENT_VAR(_id, _suffix).attr.attr
 
 #define	EVENT_ATTR(_name, _id, _suffix)					\
-	PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_PM_##_id,	\
+	PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_##_id,	\
 			power_events_sysfs_show)
 
 #define	GENERIC_EVENT_ATTR(_name, _id)	EVENT_ATTR(_name, _id, _g)
 #define	GENERIC_EVENT_PTR(_id)		EVENT_PTR(_id, _g)
 
-#define	POWER_EVENT_ATTR(_name, _id)	EVENT_ATTR(PM_##_name, _id, _p)
+#define	POWER_EVENT_ATTR(_name, _id)	EVENT_ATTR(_name, _id, _p)
 #define	POWER_EVENT_PTR(_id)		EVENT_PTR(_id, _p)
diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h
index 93f280e..37b7ca3 100644
--- a/arch/powerpc/include/asm/spu.h
+++ b/arch/powerpc/include/asm/spu.h
@@ -235,6 +235,7 @@ extern long spu_sys_callback(struct spu_syscall_block *s);
 
 /* syscalls implemented in spufs */
 struct file;
+struct coredump_params;
 struct spufs_calls {
 	long (*create_thread)(const char __user *name,
 					unsigned int flags, umode_t mode,
@@ -242,7 +243,7 @@ struct spufs_calls {
 	long (*spu_run)(struct file *filp, __u32 __user *unpc,
 						__u32 __user *ustatus);
 	int (*coredump_extra_notes_size)(void);
-	int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset);
+	int (*coredump_extra_notes_write)(struct coredump_params *cprm);
 	void (*notify_spus_active)(void);
 	struct module *owner;
 };
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index b20ff17..0adab06 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -105,7 +105,7 @@ static int __init fail_iommu_debugfs(void)
 	struct dentry *dir = fault_create_debugfs_attr("fail_iommu",
 						       NULL, &fail_iommu);
 
-	return PTR_RET(dir);
+	return PTR_ERR_OR_ZERO(dir);
 }
 late_initcall(fail_iommu_debugfs);
 
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index eb23ac9..67d18da 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -550,8 +550,7 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-		unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (unsigned long)__va(start);
 	initrd_end = (unsigned long)__va(end);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 65ab9e9..cdcc156 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -1049,7 +1049,7 @@ static int __init rtc_init(void)
 
 	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
 
-	return PTR_RET(pdev);
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 module_init(rtc_init);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 6316ee3..ae63ae4 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -420,6 +420,10 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 	return kvmppc_core_create_memslot(slot, npages);
 }
 
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   struct kvm_memory_slot *memslot,
 				   struct kvm_userspace_memory_region *mem,
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 8726779..d9196c9 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -223,9 +223,6 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 	is_write = error_code & ESR_DST;
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
 
-	if (is_write)
-		flags |= FAULT_FLAG_WRITE;
-
 #ifdef CONFIG_PPC_ICSWX
 	/*
 	 * we need to do this early because this "data storage
@@ -280,6 +277,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 
 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
 	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
@@ -408,6 +408,7 @@ good_area:
 	} else if (is_write) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	/* a read */
 	} else {
 		/* protection fault */
diff --git a/arch/powerpc/perf/power7-events-list.h b/arch/powerpc/perf/power7-events-list.h
new file mode 100644
index 0000000..687790a
--- /dev/null
+++ b/arch/powerpc/perf/power7-events-list.h
@@ -0,0 +1,548 @@
+/*
+ * Performance counter support for POWER7 processors.
+ *
+ * Copyright 2013 Runzhen Wang, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+EVENT(PM_IC_DEMAND_L2_BR_ALL,                 0x04898)
+EVENT(PM_GCT_UTIL_7_TO_10_SLOTS,              0x020a0)
+EVENT(PM_PMC2_SAVED,                          0x10022)
+EVENT(PM_CMPLU_STALL_DFU,                     0x2003c)
+EVENT(PM_VSU0_16FLOP,                         0x0a0a4)
+EVENT(PM_MRK_LSU_DERAT_MISS,                  0x3d05a)
+EVENT(PM_MRK_ST_CMPL,                         0x10034)
+EVENT(PM_NEST_PAIR3_ADD,                      0x40881)
+EVENT(PM_L2_ST_DISP,                          0x46180)
+EVENT(PM_L2_CASTOUT_MOD,                      0x16180)
+EVENT(PM_ISEG,                                0x020a4)
+EVENT(PM_MRK_INST_TIMEO,                      0x40034)
+EVENT(PM_L2_RCST_DISP_FAIL_ADDR,              0x36282)
+EVENT(PM_LSU1_DC_PREF_STREAM_CONFIRM,         0x0d0b6)
+EVENT(PM_IERAT_WR_64K,                        0x040be)
+EVENT(PM_MRK_DTLB_MISS_16M,                   0x4d05e)
+EVENT(PM_IERAT_MISS,                          0x100f6)
+EVENT(PM_MRK_PTEG_FROM_LMEM,                  0x4d052)
+EVENT(PM_FLOP,                                0x100f4)
+EVENT(PM_THRD_PRIO_4_5_CYC,                   0x040b4)
+EVENT(PM_BR_PRED_TA,                          0x040aa)
+EVENT(PM_CMPLU_STALL_FXU,                     0x20014)
+EVENT(PM_EXT_INT,                             0x200f8)
+EVENT(PM_VSU_FSQRT_FDIV,                      0x0a888)
+EVENT(PM_MRK_LD_MISS_EXPOSED_CYC,             0x1003e)
+EVENT(PM_LSU1_LDF,                            0x0c086)
+EVENT(PM_IC_WRITE_ALL,                        0x0488c)
+EVENT(PM_LSU0_SRQ_STFWD,                      0x0c0a0)
+EVENT(PM_PTEG_FROM_RL2L3_MOD,                 0x1c052)
+EVENT(PM_MRK_DATA_FROM_L31_SHR,               0x1d04e)
+EVENT(PM_DATA_FROM_L21_MOD,                   0x3c046)
+EVENT(PM_VSU1_SCAL_DOUBLE_ISSUED,             0x0b08a)
+EVENT(PM_VSU0_8FLOP,                          0x0a0a0)
+EVENT(PM_POWER_EVENT1,                        0x1006e)
+EVENT(PM_DISP_CLB_HELD_BAL,                   0x02092)
+EVENT(PM_VSU1_2FLOP,                          0x0a09a)
+EVENT(PM_LWSYNC_HELD,                         0x0209a)
+EVENT(PM_PTEG_FROM_DL2L3_SHR,                 0x3c054)
+EVENT(PM_INST_FROM_L21_MOD,                   0x34046)
+EVENT(PM_IERAT_XLATE_WR_16MPLUS,              0x040bc)
+EVENT(PM_IC_REQ_ALL,                          0x04888)
+EVENT(PM_DSLB_MISS,                           0x0d090)
+EVENT(PM_L3_MISS,                             0x1f082)
+EVENT(PM_LSU0_L1_PREF,                        0x0d0b8)
+EVENT(PM_VSU_SCALAR_SINGLE_ISSUED,            0x0b884)
+EVENT(PM_LSU1_DC_PREF_STREAM_CONFIRM_STRIDE,  0x0d0be)
+EVENT(PM_L2_INST,                             0x36080)
+EVENT(PM_VSU0_FRSP,                           0x0a0b4)
+EVENT(PM_FLUSH_DISP,                          0x02082)
+EVENT(PM_PTEG_FROM_L2MISS,                    0x4c058)
+EVENT(PM_VSU1_DQ_ISSUED,                      0x0b09a)
+EVENT(PM_CMPLU_STALL_LSU,                     0x20012)
+EVENT(PM_MRK_DATA_FROM_DMEM,                  0x1d04a)
+EVENT(PM_LSU_FLUSH_ULD,                       0x0c8b0)
+EVENT(PM_PTEG_FROM_LMEM,                      0x4c052)
+EVENT(PM_MRK_DERAT_MISS_16M,                  0x3d05c)
+EVENT(PM_THRD_ALL_RUN_CYC,                    0x2000c)
+EVENT(PM_MEM0_PREFETCH_DISP,                  0x20083)
+EVENT(PM_MRK_STALL_CMPLU_CYC_COUNT,           0x3003f)
+EVENT(PM_DATA_FROM_DL2L3_MOD,                 0x3c04c)
+EVENT(PM_VSU_FRSP,                            0x0a8b4)
+EVENT(PM_MRK_DATA_FROM_L21_MOD,               0x3d046)
+EVENT(PM_PMC1_OVERFLOW,                       0x20010)
+EVENT(PM_VSU0_SINGLE,                         0x0a0a8)
+EVENT(PM_MRK_PTEG_FROM_L3MISS,                0x2d058)
+EVENT(PM_MRK_PTEG_FROM_L31_SHR,               0x2d056)
+EVENT(PM_VSU0_VECTOR_SP_ISSUED,               0x0b090)
+EVENT(PM_VSU1_FEST,                           0x0a0ba)
+EVENT(PM_MRK_INST_DISP,                       0x20030)
+EVENT(PM_VSU0_COMPLEX_ISSUED,                 0x0b096)
+EVENT(PM_LSU1_FLUSH_UST,                      0x0c0b6)
+EVENT(PM_INST_CMPL,                           0x00002)
+EVENT(PM_FXU_IDLE,                            0x1000e)
+EVENT(PM_LSU0_FLUSH_ULD,                      0x0c0b0)
+EVENT(PM_MRK_DATA_FROM_DL2L3_MOD,             0x3d04c)
+EVENT(PM_LSU_LMQ_SRQ_EMPTY_ALL_CYC,           0x3001c)
+EVENT(PM_LSU1_REJECT_LMQ_FULL,                0x0c0a6)
+EVENT(PM_INST_PTEG_FROM_L21_MOD,              0x3e056)
+EVENT(PM_INST_FROM_RL2L3_MOD,                 0x14042)
+EVENT(PM_SHL_CREATED,                         0x05082)
+EVENT(PM_L2_ST_HIT,                           0x46182)
+EVENT(PM_DATA_FROM_DMEM,                      0x1c04a)
+EVENT(PM_L3_LD_MISS,                          0x2f082)
+EVENT(PM_FXU1_BUSY_FXU0_IDLE,                 0x4000e)
+EVENT(PM_DISP_CLB_HELD_RES,                   0x02094)
+EVENT(PM_L2_SN_SX_I_DONE,                     0x36382)
+EVENT(PM_GRP_CMPL,                            0x30004)
+EVENT(PM_STCX_CMPL,                           0x0c098)
+EVENT(PM_VSU0_2FLOP,                          0x0a098)
+EVENT(PM_L3_PREF_MISS,                        0x3f082)
+EVENT(PM_LSU_SRQ_SYNC_CYC,                    0x0d096)
+EVENT(PM_LSU_REJECT_ERAT_MISS,                0x20064)
+EVENT(PM_L1_ICACHE_MISS,                      0x200fc)
+EVENT(PM_LSU1_FLUSH_SRQ,                      0x0c0be)
+EVENT(PM_LD_REF_L1_LSU0,                      0x0c080)
+EVENT(PM_VSU0_FEST,                           0x0a0b8)
+EVENT(PM_VSU_VECTOR_SINGLE_ISSUED,            0x0b890)
+EVENT(PM_FREQ_UP,                             0x4000c)
+EVENT(PM_DATA_FROM_LMEM,                      0x3c04a)
+EVENT(PM_LSU1_LDX,                            0x0c08a)
+EVENT(PM_PMC3_OVERFLOW,                       0x40010)
+EVENT(PM_MRK_BR_MPRED,                        0x30036)
+EVENT(PM_SHL_MATCH,                           0x05086)
+EVENT(PM_MRK_BR_TAKEN,                        0x10036)
+EVENT(PM_CMPLU_STALL_BRU,                     0x4004e)
+EVENT(PM_ISLB_MISS,                           0x0d092)
+EVENT(PM_CYC,                                 0x0001e)
+EVENT(PM_DISP_HELD_THERMAL,                   0x30006)
+EVENT(PM_INST_PTEG_FROM_RL2L3_SHR,            0x2e054)
+EVENT(PM_LSU1_SRQ_STFWD,                      0x0c0a2)
+EVENT(PM_GCT_NOSLOT_BR_MPRED,                 0x4001a)
+EVENT(PM_1PLUS_PPC_CMPL,                      0x100f2)
+EVENT(PM_PTEG_FROM_DMEM,                      0x2c052)
+EVENT(PM_VSU_2FLOP,                           0x0a898)
+EVENT(PM_GCT_FULL_CYC,                        0x04086)
+EVENT(PM_MRK_DATA_FROM_L3_CYC,                0x40020)
+EVENT(PM_LSU_SRQ_S0_ALLOC,                    0x0d09d)
+EVENT(PM_MRK_DERAT_MISS_4K,                   0x1d05c)
+EVENT(PM_BR_MPRED_TA,                         0x040ae)
+EVENT(PM_INST_PTEG_FROM_L2MISS,               0x4e058)
+EVENT(PM_DPU_HELD_POWER,                      0x20006)
+EVENT(PM_RUN_INST_CMPL,                       0x400fa)
+EVENT(PM_MRK_VSU_FIN,                         0x30032)
+EVENT(PM_LSU_SRQ_S0_VALID,                    0x0d09c)
+EVENT(PM_GCT_EMPTY_CYC,                       0x20008)
+EVENT(PM_IOPS_DISP,                           0x30014)
+EVENT(PM_RUN_SPURR,                           0x10008)
+EVENT(PM_PTEG_FROM_L21_MOD,                   0x3c056)
+EVENT(PM_VSU0_1FLOP,                          0x0a080)
+EVENT(PM_SNOOP_TLBIE,                         0x0d0b2)
+EVENT(PM_DATA_FROM_L3MISS,                    0x2c048)
+EVENT(PM_VSU_SINGLE,                          0x0a8a8)
+EVENT(PM_DTLB_MISS_16G,                       0x1c05e)
+EVENT(PM_CMPLU_STALL_VECTOR,                  0x2001c)
+EVENT(PM_FLUSH,                               0x400f8)
+EVENT(PM_L2_LD_HIT,                           0x36182)
+EVENT(PM_NEST_PAIR2_AND,                      0x30883)
+EVENT(PM_VSU1_1FLOP,                          0x0a082)
+EVENT(PM_IC_PREF_REQ,                         0x0408a)
+EVENT(PM_L3_LD_HIT,                           0x2f080)
+EVENT(PM_GCT_NOSLOT_IC_MISS,                  0x2001a)
+EVENT(PM_DISP_HELD,                           0x10006)
+EVENT(PM_L2_LD,                               0x16080)
+EVENT(PM_LSU_FLUSH_SRQ,                       0x0c8bc)
+EVENT(PM_BC_PLUS_8_CONV,                      0x040b8)
+EVENT(PM_MRK_DATA_FROM_L31_MOD_CYC,           0x40026)
+EVENT(PM_CMPLU_STALL_VECTOR_LONG,             0x4004a)
+EVENT(PM_L2_RCST_BUSY_RC_FULL,                0x26282)
+EVENT(PM_TB_BIT_TRANS,                        0x300f8)
+EVENT(PM_THERMAL_MAX,                         0x40006)
+EVENT(PM_LSU1_FLUSH_ULD,                      0x0c0b2)
+EVENT(PM_LSU1_REJECT_LHS,                     0x0c0ae)
+EVENT(PM_LSU_LRQ_S0_ALLOC,                    0x0d09f)
+EVENT(PM_L3_CO_L31,                           0x4f080)
+EVENT(PM_POWER_EVENT4,                        0x4006e)
+EVENT(PM_DATA_FROM_L31_SHR,                   0x1c04e)
+EVENT(PM_BR_UNCOND,                           0x0409e)
+EVENT(PM_LSU1_DC_PREF_STREAM_ALLOC,           0x0d0aa)
+EVENT(PM_PMC4_REWIND,                         0x10020)
+EVENT(PM_L2_RCLD_DISP,                        0x16280)
+EVENT(PM_THRD_PRIO_2_3_CYC,                   0x040b2)
+EVENT(PM_MRK_PTEG_FROM_L2MISS,                0x4d058)
+EVENT(PM_IC_DEMAND_L2_BHT_REDIRECT,           0x04098)
+EVENT(PM_LSU_DERAT_MISS,                      0x200f6)
+EVENT(PM_IC_PREF_CANCEL_L2,                   0x04094)
+EVENT(PM_MRK_FIN_STALL_CYC_COUNT,             0x1003d)
+EVENT(PM_BR_PRED_CCACHE,                      0x040a0)
+EVENT(PM_GCT_UTIL_1_TO_2_SLOTS,               0x0209c)
+EVENT(PM_MRK_ST_CMPL_INT,                     0x30034)
+EVENT(PM_LSU_TWO_TABLEWALK_CYC,               0x0d0a6)
+EVENT(PM_MRK_DATA_FROM_L3MISS,                0x2d048)
+EVENT(PM_GCT_NOSLOT_CYC,                      0x100f8)
+EVENT(PM_LSU_SET_MPRED,                       0x0c0a8)
+EVENT(PM_FLUSH_DISP_TLBIE,                    0x0208a)
+EVENT(PM_VSU1_FCONV,                          0x0a0b2)
+EVENT(PM_DERAT_MISS_16G,                      0x4c05c)
+EVENT(PM_INST_FROM_LMEM,                      0x3404a)
+EVENT(PM_IC_DEMAND_L2_BR_REDIRECT,            0x0409a)
+EVENT(PM_CMPLU_STALL_SCALAR_LONG,             0x20018)
+EVENT(PM_INST_PTEG_FROM_L2,                   0x1e050)
+EVENT(PM_PTEG_FROM_L2,                        0x1c050)
+EVENT(PM_MRK_DATA_FROM_L21_SHR_CYC,           0x20024)
+EVENT(PM_MRK_DTLB_MISS_4K,                    0x2d05a)
+EVENT(PM_VSU0_FPSCR,                          0x0b09c)
+EVENT(PM_VSU1_VECT_DOUBLE_ISSUED,             0x0b082)
+EVENT(PM_MRK_PTEG_FROM_RL2L3_MOD,             0x1d052)
+EVENT(PM_MEM0_RQ_DISP,                        0x10083)
+EVENT(PM_L2_LD_MISS,                          0x26080)
+EVENT(PM_VMX_RESULT_SAT_1,                    0x0b0a0)
+EVENT(PM_L1_PREF,                             0x0d8b8)
+EVENT(PM_MRK_DATA_FROM_LMEM_CYC,              0x2002c)
+EVENT(PM_GRP_IC_MISS_NONSPEC,                 0x1000c)
+EVENT(PM_PB_NODE_PUMP,                        0x10081)
+EVENT(PM_SHL_MERGED,                          0x05084)
+EVENT(PM_NEST_PAIR1_ADD,                      0x20881)
+EVENT(PM_DATA_FROM_L3,                        0x1c048)
+EVENT(PM_LSU_FLUSH,                           0x0208e)
+EVENT(PM_LSU_SRQ_SYNC_COUNT,                  0x0d097)
+EVENT(PM_PMC2_OVERFLOW,                       0x30010)
+EVENT(PM_LSU_LDF,                             0x0c884)
+EVENT(PM_POWER_EVENT3,                        0x3006e)
+EVENT(PM_DISP_WT,                             0x30008)
+EVENT(PM_CMPLU_STALL_REJECT,                  0x40016)
+EVENT(PM_IC_BANK_CONFLICT,                    0x04082)
+EVENT(PM_BR_MPRED_CR_TA,                      0x048ae)
+EVENT(PM_L2_INST_MISS,                        0x36082)
+EVENT(PM_CMPLU_STALL_ERAT_MISS,               0x40018)
+EVENT(PM_NEST_PAIR2_ADD,                      0x30881)
+EVENT(PM_MRK_LSU_FLUSH,                       0x0d08c)
+EVENT(PM_L2_LDST,                             0x16880)
+EVENT(PM_INST_FROM_L31_SHR,                   0x1404e)
+EVENT(PM_VSU0_FIN,                            0x0a0bc)
+EVENT(PM_LARX_LSU,                            0x0c894)
+EVENT(PM_INST_FROM_RMEM,                      0x34042)
+EVENT(PM_DISP_CLB_HELD_TLBIE,                 0x02096)
+EVENT(PM_MRK_DATA_FROM_DMEM_CYC,              0x2002e)
+EVENT(PM_BR_PRED_CR,                          0x040a8)
+EVENT(PM_LSU_REJECT,                          0x10064)
+EVENT(PM_GCT_UTIL_3_TO_6_SLOTS,               0x0209e)
+EVENT(PM_CMPLU_STALL_END_GCT_NOSLOT,          0x10028)
+EVENT(PM_LSU0_REJECT_LMQ_FULL,                0x0c0a4)
+EVENT(PM_VSU_FEST,                            0x0a8b8)
+EVENT(PM_NEST_PAIR0_AND,                      0x10883)
+EVENT(PM_PTEG_FROM_L3,                        0x2c050)
+EVENT(PM_POWER_EVENT2,                        0x2006e)
+EVENT(PM_IC_PREF_CANCEL_PAGE,                 0x04090)
+EVENT(PM_VSU0_FSQRT_FDIV,                     0x0a088)
+EVENT(PM_MRK_GRP_CMPL,                        0x40030)
+EVENT(PM_VSU0_SCAL_DOUBLE_ISSUED,             0x0b088)
+EVENT(PM_GRP_DISP,                            0x3000a)
+EVENT(PM_LSU0_LDX,                            0x0c088)
+EVENT(PM_DATA_FROM_L2,                        0x1c040)
+EVENT(PM_MRK_DATA_FROM_RL2L3_MOD,             0x1d042)
+EVENT(PM_LD_REF_L1,                           0x0c880)
+EVENT(PM_VSU0_VECT_DOUBLE_ISSUED,             0x0b080)
+EVENT(PM_VSU1_2FLOP_DOUBLE,                   0x0a08e)
+EVENT(PM_THRD_PRIO_6_7_CYC,                   0x040b6)
+EVENT(PM_BC_PLUS_8_RSLV_TAKEN,                0x040ba)
+EVENT(PM_BR_MPRED_CR,                         0x040ac)
+EVENT(PM_L3_CO_MEM,                           0x4f082)
+EVENT(PM_LD_MISS_L1,                          0x400f0)
+EVENT(PM_DATA_FROM_RL2L3_MOD,                 0x1c042)
+EVENT(PM_LSU_SRQ_FULL_CYC,                    0x1001a)
+EVENT(PM_TABLEWALK_CYC,                       0x10026)
+EVENT(PM_MRK_PTEG_FROM_RMEM,                  0x3d052)
+EVENT(PM_LSU_SRQ_STFWD,                       0x0c8a0)
+EVENT(PM_INST_PTEG_FROM_RMEM,                 0x3e052)
+EVENT(PM_FXU0_FIN,                            0x10004)
+EVENT(PM_LSU1_L1_SW_PREF,                     0x0c09e)
+EVENT(PM_PTEG_FROM_L31_MOD,                   0x1c054)
+EVENT(PM_PMC5_OVERFLOW,                       0x10024)
+EVENT(PM_LD_REF_L1_LSU1,                      0x0c082)
+EVENT(PM_INST_PTEG_FROM_L21_SHR,              0x4e056)
+EVENT(PM_CMPLU_STALL_THRD,                    0x1001c)
+EVENT(PM_DATA_FROM_RMEM,                      0x3c042)
+EVENT(PM_VSU0_SCAL_SINGLE_ISSUED,             0x0b084)
+EVENT(PM_BR_MPRED_LSTACK,                     0x040a6)
+EVENT(PM_MRK_DATA_FROM_RL2L3_MOD_CYC,         0x40028)
+EVENT(PM_LSU0_FLUSH_UST,                      0x0c0b4)
+EVENT(PM_LSU_NCST,                            0x0c090)
+EVENT(PM_BR_TAKEN,                            0x20004)
+EVENT(PM_INST_PTEG_FROM_LMEM,                 0x4e052)
+EVENT(PM_GCT_NOSLOT_BR_MPRED_IC_MISS,         0x4001c)
+EVENT(PM_DTLB_MISS_4K,                        0x2c05a)
+EVENT(PM_PMC4_SAVED,                          0x30022)
+EVENT(PM_VSU1_PERMUTE_ISSUED,                 0x0b092)
+EVENT(PM_SLB_MISS,                            0x0d890)
+EVENT(PM_LSU1_FLUSH_LRQ,                      0x0c0ba)
+EVENT(PM_DTLB_MISS,                           0x300fc)
+EVENT(PM_VSU1_FRSP,                           0x0a0b6)
+EVENT(PM_VSU_VECTOR_DOUBLE_ISSUED,            0x0b880)
+EVENT(PM_L2_CASTOUT_SHR,                      0x16182)
+EVENT(PM_DATA_FROM_DL2L3_SHR,                 0x3c044)
+EVENT(PM_VSU1_STF,                            0x0b08e)
+EVENT(PM_ST_FIN,                              0x200f0)
+EVENT(PM_PTEG_FROM_L21_SHR,                   0x4c056)
+EVENT(PM_L2_LOC_GUESS_WRONG,                  0x26480)
+EVENT(PM_MRK_STCX_FAIL,                       0x0d08e)
+EVENT(PM_LSU0_REJECT_LHS,                     0x0c0ac)
+EVENT(PM_IC_PREF_CANCEL_HIT,                  0x04092)
+EVENT(PM_L3_PREF_BUSY,                        0x4f080)
+EVENT(PM_MRK_BRU_FIN,                         0x2003a)
+EVENT(PM_LSU1_NCLD,                           0x0c08e)
+EVENT(PM_INST_PTEG_FROM_L31_MOD,              0x1e054)
+EVENT(PM_LSU_NCLD,                            0x0c88c)
+EVENT(PM_LSU_LDX,                             0x0c888)
+EVENT(PM_L2_LOC_GUESS_CORRECT,                0x16480)
+EVENT(PM_THRESH_TIMEO,                        0x10038)
+EVENT(PM_L3_PREF_ST,                          0x0d0ae)
+EVENT(PM_DISP_CLB_HELD_SYNC,                  0x02098)
+EVENT(PM_VSU_SIMPLE_ISSUED,                   0x0b894)
+EVENT(PM_VSU1_SINGLE,                         0x0a0aa)
+EVENT(PM_DATA_TABLEWALK_CYC,                  0x3001a)
+EVENT(PM_L2_RC_ST_DONE,                       0x36380)
+EVENT(PM_MRK_PTEG_FROM_L21_MOD,               0x3d056)
+EVENT(PM_LARX_LSU1,                           0x0c096)
+EVENT(PM_MRK_DATA_FROM_RMEM,                  0x3d042)
+EVENT(PM_DISP_CLB_HELD,                       0x02090)
+EVENT(PM_DERAT_MISS_4K,                       0x1c05c)
+EVENT(PM_L2_RCLD_DISP_FAIL_ADDR,              0x16282)
+EVENT(PM_SEG_EXCEPTION,                       0x028a4)
+EVENT(PM_FLUSH_DISP_SB,                       0x0208c)
+EVENT(PM_L2_DC_INV,                           0x26182)
+EVENT(PM_PTEG_FROM_DL2L3_MOD,                 0x4c054)
+EVENT(PM_DSEG,                                0x020a6)
+EVENT(PM_BR_PRED_LSTACK,                      0x040a2)
+EVENT(PM_VSU0_STF,                            0x0b08c)
+EVENT(PM_LSU_FX_FIN,                          0x10066)
+EVENT(PM_DERAT_MISS_16M,                      0x3c05c)
+EVENT(PM_MRK_PTEG_FROM_DL2L3_MOD,             0x4d054)
+EVENT(PM_GCT_UTIL_11_PLUS_SLOTS,              0x020a2)
+EVENT(PM_INST_FROM_L3,                        0x14048)
+EVENT(PM_MRK_IFU_FIN,                         0x3003a)
+EVENT(PM_ITLB_MISS,                           0x400fc)
+EVENT(PM_VSU_STF,                             0x0b88c)
+EVENT(PM_LSU_FLUSH_UST,                       0x0c8b4)
+EVENT(PM_L2_LDST_MISS,                        0x26880)
+EVENT(PM_FXU1_FIN,                            0x40004)
+EVENT(PM_SHL_DEALLOCATED,                     0x05080)
+EVENT(PM_L2_SN_M_WR_DONE,                     0x46382)
+EVENT(PM_LSU_REJECT_SET_MPRED,                0x0c8a8)
+EVENT(PM_L3_PREF_LD,                          0x0d0ac)
+EVENT(PM_L2_SN_M_RD_DONE,                     0x46380)
+EVENT(PM_MRK_DERAT_MISS_16G,                  0x4d05c)
+EVENT(PM_VSU_FCONV,                           0x0a8b0)
+EVENT(PM_ANY_THRD_RUN_CYC,                    0x100fa)
+EVENT(PM_LSU_LMQ_FULL_CYC,                    0x0d0a4)
+EVENT(PM_MRK_LSU_REJECT_LHS,                  0x0d082)
+EVENT(PM_MRK_LD_MISS_L1_CYC,                  0x4003e)
+EVENT(PM_MRK_DATA_FROM_L2_CYC,                0x20020)
+EVENT(PM_INST_IMC_MATCH_DISP,                 0x30016)
+EVENT(PM_MRK_DATA_FROM_RMEM_CYC,              0x4002c)
+EVENT(PM_VSU0_SIMPLE_ISSUED,                  0x0b094)
+EVENT(PM_CMPLU_STALL_DIV,                     0x40014)
+EVENT(PM_MRK_PTEG_FROM_RL2L3_SHR,             0x2d054)
+EVENT(PM_VSU_FMA_DOUBLE,                      0x0a890)
+EVENT(PM_VSU_4FLOP,                           0x0a89c)
+EVENT(PM_VSU1_FIN,                            0x0a0be)
+EVENT(PM_NEST_PAIR1_AND,                      0x20883)
+EVENT(PM_INST_PTEG_FROM_RL2L3_MOD,            0x1e052)
+EVENT(PM_RUN_CYC,                             0x200f4)
+EVENT(PM_PTEG_FROM_RMEM,                      0x3c052)
+EVENT(PM_LSU_LRQ_S0_VALID,                    0x0d09e)
+EVENT(PM_LSU0_LDF,                            0x0c084)
+EVENT(PM_FLUSH_COMPLETION,                    0x30012)
+EVENT(PM_ST_MISS_L1,                          0x300f0)
+EVENT(PM_L2_NODE_PUMP,                        0x36480)
+EVENT(PM_INST_FROM_DL2L3_SHR,                 0x34044)
+EVENT(PM_MRK_STALL_CMPLU_CYC,                 0x3003e)
+EVENT(PM_VSU1_DENORM,                         0x0a0ae)
+EVENT(PM_MRK_DATA_FROM_L31_SHR_CYC,           0x20026)
+EVENT(PM_NEST_PAIR0_ADD,                      0x10881)
+EVENT(PM_INST_FROM_L3MISS,                    0x24048)
+EVENT(PM_EE_OFF_EXT_INT,                      0x02080)
+EVENT(PM_INST_PTEG_FROM_DMEM,                 0x2e052)
+EVENT(PM_INST_FROM_DL2L3_MOD,                 0x3404c)
+EVENT(PM_PMC6_OVERFLOW,                       0x30024)
+EVENT(PM_VSU_2FLOP_DOUBLE,                    0x0a88c)
+EVENT(PM_TLB_MISS,                            0x20066)
+EVENT(PM_FXU_BUSY,                            0x2000e)
+EVENT(PM_L2_RCLD_DISP_FAIL_OTHER,             0x26280)
+EVENT(PM_LSU_REJECT_LMQ_FULL,                 0x0c8a4)
+EVENT(PM_IC_RELOAD_SHR,                       0x04096)
+EVENT(PM_GRP_MRK,                             0x10031)
+EVENT(PM_MRK_ST_NEST,                         0x20034)
+EVENT(PM_VSU1_FSQRT_FDIV,                     0x0a08a)
+EVENT(PM_LSU0_FLUSH_LRQ,                      0x0c0b8)
+EVENT(PM_LARX_LSU0,                           0x0c094)
+EVENT(PM_IBUF_FULL_CYC,                       0x04084)
+EVENT(PM_MRK_DATA_FROM_DL2L3_SHR_CYC,         0x2002a)
+EVENT(PM_LSU_DC_PREF_STREAM_ALLOC,            0x0d8a8)
+EVENT(PM_GRP_MRK_CYC,                         0x10030)
+EVENT(PM_MRK_DATA_FROM_RL2L3_SHR_CYC,         0x20028)
+EVENT(PM_L2_GLOB_GUESS_CORRECT,               0x16482)
+EVENT(PM_LSU_REJECT_LHS,                      0x0c8ac)
+EVENT(PM_MRK_DATA_FROM_LMEM,                  0x3d04a)
+EVENT(PM_INST_PTEG_FROM_L3,                   0x2e050)
+EVENT(PM_FREQ_DOWN,                           0x3000c)
+EVENT(PM_PB_RETRY_NODE_PUMP,                  0x30081)
+EVENT(PM_INST_FROM_RL2L3_SHR,                 0x1404c)
+EVENT(PM_MRK_INST_ISSUED,                     0x10032)
+EVENT(PM_PTEG_FROM_L3MISS,                    0x2c058)
+EVENT(PM_RUN_PURR,                            0x400f4)
+EVENT(PM_MRK_GRP_IC_MISS,                     0x40038)
+EVENT(PM_MRK_DATA_FROM_L3,                    0x1d048)
+EVENT(PM_CMPLU_STALL_DCACHE_MISS,             0x20016)
+EVENT(PM_PTEG_FROM_RL2L3_SHR,                 0x2c054)
+EVENT(PM_LSU_FLUSH_LRQ,                       0x0c8b8)
+EVENT(PM_MRK_DERAT_MISS_64K,                  0x2d05c)
+EVENT(PM_INST_PTEG_FROM_DL2L3_MOD,            0x4e054)
+EVENT(PM_L2_ST_MISS,                          0x26082)
+EVENT(PM_MRK_PTEG_FROM_L21_SHR,               0x4d056)
+EVENT(PM_LWSYNC,                              0x0d094)
+EVENT(PM_LSU0_DC_PREF_STREAM_CONFIRM_STRIDE,  0x0d0bc)
+EVENT(PM_MRK_LSU_FLUSH_LRQ,                   0x0d088)
+EVENT(PM_INST_IMC_MATCH_CMPL,                 0x100f0)
+EVENT(PM_NEST_PAIR3_AND,                      0x40883)
+EVENT(PM_PB_RETRY_SYS_PUMP,                   0x40081)
+EVENT(PM_MRK_INST_FIN,                        0x30030)
+EVENT(PM_MRK_PTEG_FROM_DL2L3_SHR,             0x3d054)
+EVENT(PM_INST_FROM_L31_MOD,                   0x14044)
+EVENT(PM_MRK_DTLB_MISS_64K,                   0x3d05e)
+EVENT(PM_LSU_FIN,                             0x30066)
+EVENT(PM_MRK_LSU_REJECT,                      0x40064)
+EVENT(PM_L2_CO_FAIL_BUSY,                     0x16382)
+EVENT(PM_MEM0_WQ_DISP,                        0x40083)
+EVENT(PM_DATA_FROM_L31_MOD,                   0x1c044)
+EVENT(PM_THERMAL_WARN,                        0x10016)
+EVENT(PM_VSU0_4FLOP,                          0x0a09c)
+EVENT(PM_BR_MPRED_CCACHE,                     0x040a4)
+EVENT(PM_CMPLU_STALL_IFU,                     0x4004c)
+EVENT(PM_L1_DEMAND_WRITE,                     0x0408c)
+EVENT(PM_FLUSH_BR_MPRED,                      0x02084)
+EVENT(PM_MRK_DTLB_MISS_16G,                   0x1d05e)
+EVENT(PM_MRK_PTEG_FROM_DMEM,                  0x2d052)
+EVENT(PM_L2_RCST_DISP,                        0x36280)
+EVENT(PM_CMPLU_STALL,                         0x4000a)
+EVENT(PM_LSU_PARTIAL_CDF,                     0x0c0aa)
+EVENT(PM_DISP_CLB_HELD_SB,                    0x020a8)
+EVENT(PM_VSU0_FMA_DOUBLE,                     0x0a090)
+EVENT(PM_FXU0_BUSY_FXU1_IDLE,                 0x3000e)
+EVENT(PM_IC_DEMAND_CYC,                       0x10018)
+EVENT(PM_MRK_DATA_FROM_L21_SHR,               0x3d04e)
+EVENT(PM_MRK_LSU_FLUSH_UST,                   0x0d086)
+EVENT(PM_INST_PTEG_FROM_L3MISS,               0x2e058)
+EVENT(PM_VSU_DENORM,                          0x0a8ac)
+EVENT(PM_MRK_LSU_PARTIAL_CDF,                 0x0d080)
+EVENT(PM_INST_FROM_L21_SHR,                   0x3404e)
+EVENT(PM_IC_PREF_WRITE,                       0x0408e)
+EVENT(PM_BR_PRED,                             0x0409c)
+EVENT(PM_INST_FROM_DMEM,                      0x1404a)
+EVENT(PM_IC_PREF_CANCEL_ALL,                  0x04890)
+EVENT(PM_LSU_DC_PREF_STREAM_CONFIRM,          0x0d8b4)
+EVENT(PM_MRK_LSU_FLUSH_SRQ,                   0x0d08a)
+EVENT(PM_MRK_FIN_STALL_CYC,                   0x1003c)
+EVENT(PM_L2_RCST_DISP_FAIL_OTHER,             0x46280)
+EVENT(PM_VSU1_DD_ISSUED,                      0x0b098)
+EVENT(PM_PTEG_FROM_L31_SHR,                   0x2c056)
+EVENT(PM_DATA_FROM_L21_SHR,                   0x3c04e)
+EVENT(PM_LSU0_NCLD,                           0x0c08c)
+EVENT(PM_VSU1_4FLOP,                          0x0a09e)
+EVENT(PM_VSU1_8FLOP,                          0x0a0a2)
+EVENT(PM_VSU_8FLOP,                           0x0a8a0)
+EVENT(PM_LSU_LMQ_SRQ_EMPTY_CYC,               0x2003e)
+EVENT(PM_DTLB_MISS_64K,                       0x3c05e)
+EVENT(PM_THRD_CONC_RUN_INST,                  0x300f4)
+EVENT(PM_MRK_PTEG_FROM_L2,                    0x1d050)
+EVENT(PM_PB_SYS_PUMP,                         0x20081)
+EVENT(PM_VSU_FIN,                             0x0a8bc)
+EVENT(PM_MRK_DATA_FROM_L31_MOD,               0x1d044)
+EVENT(PM_THRD_PRIO_0_1_CYC,                   0x040b0)
+EVENT(PM_DERAT_MISS_64K,                      0x2c05c)
+EVENT(PM_PMC2_REWIND,                         0x30020)
+EVENT(PM_INST_FROM_L2,                        0x14040)
+EVENT(PM_GRP_BR_MPRED_NONSPEC,                0x1000a)
+EVENT(PM_INST_DISP,                           0x200f2)
+EVENT(PM_MEM0_RD_CANCEL_TOTAL,                0x30083)
+EVENT(PM_LSU0_DC_PREF_STREAM_CONFIRM,         0x0d0b4)
+EVENT(PM_L1_DCACHE_RELOAD_VALID,              0x300f6)
+EVENT(PM_VSU_SCALAR_DOUBLE_ISSUED,            0x0b888)
+EVENT(PM_L3_PREF_HIT,                         0x3f080)
+EVENT(PM_MRK_PTEG_FROM_L31_MOD,               0x1d054)
+EVENT(PM_CMPLU_STALL_STORE,                   0x2004a)
+EVENT(PM_MRK_FXU_FIN,                         0x20038)
+EVENT(PM_PMC4_OVERFLOW,                       0x10010)
+EVENT(PM_MRK_PTEG_FROM_L3,                    0x2d050)
+EVENT(PM_LSU0_LMQ_LHR_MERGE,                  0x0d098)
+EVENT(PM_BTAC_HIT,                            0x0508a)
+EVENT(PM_L3_RD_BUSY,                          0x4f082)
+EVENT(PM_LSU0_L1_SW_PREF,                     0x0c09c)
+EVENT(PM_INST_FROM_L2MISS,                    0x44048)
+EVENT(PM_LSU0_DC_PREF_STREAM_ALLOC,           0x0d0a8)
+EVENT(PM_L2_ST,                               0x16082)
+EVENT(PM_VSU0_DENORM,                         0x0a0ac)
+EVENT(PM_MRK_DATA_FROM_DL2L3_SHR,             0x3d044)
+EVENT(PM_BR_PRED_CR_TA,                       0x048aa)
+EVENT(PM_VSU0_FCONV,                          0x0a0b0)
+EVENT(PM_MRK_LSU_FLUSH_ULD,                   0x0d084)
+EVENT(PM_BTAC_MISS,                           0x05088)
+EVENT(PM_MRK_LD_MISS_EXPOSED_CYC_COUNT,       0x1003f)
+EVENT(PM_MRK_DATA_FROM_L2,                    0x1d040)
+EVENT(PM_LSU_DCACHE_RELOAD_VALID,             0x0d0a2)
+EVENT(PM_VSU_FMA,                             0x0a884)
+EVENT(PM_LSU0_FLUSH_SRQ,                      0x0c0bc)
+EVENT(PM_LSU1_L1_PREF,                        0x0d0ba)
+EVENT(PM_IOPS_CMPL,                           0x10014)
+EVENT(PM_L2_SYS_PUMP,                         0x36482)
+EVENT(PM_L2_RCLD_BUSY_RC_FULL,                0x46282)
+EVENT(PM_LSU_LMQ_S0_ALLOC,                    0x0d0a1)
+EVENT(PM_FLUSH_DISP_SYNC,                     0x02088)
+EVENT(PM_MRK_DATA_FROM_DL2L3_MOD_CYC,         0x4002a)
+EVENT(PM_L2_IC_INV,                           0x26180)
+EVENT(PM_MRK_DATA_FROM_L21_MOD_CYC,           0x40024)
+EVENT(PM_L3_PREF_LDST,                        0x0d8ac)
+EVENT(PM_LSU_SRQ_EMPTY_CYC,                   0x40008)
+EVENT(PM_LSU_LMQ_S0_VALID,                    0x0d0a0)
+EVENT(PM_FLUSH_PARTIAL,                       0x02086)
+EVENT(PM_VSU1_FMA_DOUBLE,                     0x0a092)
+EVENT(PM_1PLUS_PPC_DISP,                      0x400f2)
+EVENT(PM_DATA_FROM_L2MISS,                    0x200fe)
+EVENT(PM_SUSPENDED,                           0x00000)
+EVENT(PM_VSU0_FMA,                            0x0a084)
+EVENT(PM_CMPLU_STALL_SCALAR,                  0x40012)
+EVENT(PM_STCX_FAIL,                           0x0c09a)
+EVENT(PM_VSU0_FSQRT_FDIV_DOUBLE,              0x0a094)
+EVENT(PM_DC_PREF_DST,                         0x0d0b0)
+EVENT(PM_VSU1_SCAL_SINGLE_ISSUED,             0x0b086)
+EVENT(PM_L3_HIT,                              0x1f080)
+EVENT(PM_L2_GLOB_GUESS_WRONG,                 0x26482)
+EVENT(PM_MRK_DFU_FIN,                         0x20032)
+EVENT(PM_INST_FROM_L1,                        0x04080)
+EVENT(PM_BRU_FIN,                             0x10068)
+EVENT(PM_IC_DEMAND_REQ,                       0x04088)
+EVENT(PM_VSU1_FSQRT_FDIV_DOUBLE,              0x0a096)
+EVENT(PM_VSU1_FMA,                            0x0a086)
+EVENT(PM_MRK_LD_MISS_L1,                      0x20036)
+EVENT(PM_VSU0_2FLOP_DOUBLE,                   0x0a08c)
+EVENT(PM_LSU_DC_PREF_STRIDED_STREAM_CONFIRM,  0x0d8bc)
+EVENT(PM_INST_PTEG_FROM_L31_SHR,              0x2e056)
+EVENT(PM_MRK_LSU_REJECT_ERAT_MISS,            0x30064)
+EVENT(PM_MRK_DATA_FROM_L2MISS,                0x4d048)
+EVENT(PM_DATA_FROM_RL2L3_SHR,                 0x1c04c)
+EVENT(PM_INST_FROM_PREF,                      0x14046)
+EVENT(PM_VSU1_SQ,                             0x0b09e)
+EVENT(PM_L2_LD_DISP,                          0x36180)
+EVENT(PM_L2_DISP_ALL,                         0x46080)
+EVENT(PM_THRD_GRP_CMPL_BOTH_CYC,              0x10012)
+EVENT(PM_VSU_FSQRT_FDIV_DOUBLE,               0x0a894)
+EVENT(PM_BR_MPRED,                            0x400f6)
+EVENT(PM_INST_PTEG_FROM_DL2L3_SHR,            0x3e054)
+EVENT(PM_VSU_1FLOP,                           0x0a880)
+EVENT(PM_HV_CYC,                              0x2000a)
+EVENT(PM_MRK_LSU_FIN,                         0x40032)
+EVENT(PM_MRK_DATA_FROM_RL2L3_SHR,             0x1d04c)
+EVENT(PM_DTLB_MISS_16M,                       0x4c05e)
+EVENT(PM_LSU1_LMQ_LHR_MERGE,                  0x0d09a)
+EVENT(PM_IFU_FIN,                             0x40066)
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index d1821b8..56c67bc 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -53,37 +53,13 @@
 /*
  * Power7 event codes.
  */
-#define	PME_PM_CYC			0x1e
-#define	PME_PM_GCT_NOSLOT_CYC		0x100f8
-#define	PME_PM_CMPLU_STALL		0x4000a
-#define	PME_PM_INST_CMPL		0x2
-#define	PME_PM_LD_REF_L1		0xc880
-#define	PME_PM_LD_MISS_L1		0x400f0
-#define	PME_PM_BRU_FIN			0x10068
-#define	PME_PM_BR_MPRED			0x400f6
-
-#define PME_PM_CMPLU_STALL_FXU			0x20014
-#define PME_PM_CMPLU_STALL_DIV			0x40014
-#define PME_PM_CMPLU_STALL_SCALAR		0x40012
-#define PME_PM_CMPLU_STALL_SCALAR_LONG		0x20018
-#define PME_PM_CMPLU_STALL_VECTOR		0x2001c
-#define PME_PM_CMPLU_STALL_VECTOR_LONG		0x4004a
-#define PME_PM_CMPLU_STALL_LSU			0x20012
-#define PME_PM_CMPLU_STALL_REJECT		0x40016
-#define PME_PM_CMPLU_STALL_ERAT_MISS		0x40018
-#define PME_PM_CMPLU_STALL_DCACHE_MISS		0x20016
-#define PME_PM_CMPLU_STALL_STORE		0x2004a
-#define PME_PM_CMPLU_STALL_THRD			0x1001c
-#define PME_PM_CMPLU_STALL_IFU			0x4004c
-#define PME_PM_CMPLU_STALL_BRU			0x4004e
-#define PME_PM_GCT_NOSLOT_IC_MISS		0x2001a
-#define PME_PM_GCT_NOSLOT_BR_MPRED		0x4001a
-#define PME_PM_GCT_NOSLOT_BR_MPRED_IC_MISS	0x4001c
-#define PME_PM_GRP_CMPL				0x30004
-#define PME_PM_1PLUS_PPC_CMPL			0x100f2
-#define PME_PM_CMPLU_STALL_DFU			0x2003c
-#define PME_PM_RUN_CYC				0x200f4
-#define PME_PM_RUN_INST_CMPL			0x400fa
+#define EVENT(_name, _code) \
+	PME_##_name = _code,
+
+enum {
+#include "power7-events-list.h"
+};
+#undef EVENT
 
 /*
  * Layout of constraint bits:
@@ -398,96 +374,36 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 };
 
 
-GENERIC_EVENT_ATTR(cpu-cycles,			CYC);
-GENERIC_EVENT_ATTR(stalled-cycles-frontend,	GCT_NOSLOT_CYC);
-GENERIC_EVENT_ATTR(stalled-cycles-backend,	CMPLU_STALL);
-GENERIC_EVENT_ATTR(instructions,		INST_CMPL);
-GENERIC_EVENT_ATTR(cache-references,		LD_REF_L1);
-GENERIC_EVENT_ATTR(cache-misses,		LD_MISS_L1);
-GENERIC_EVENT_ATTR(branch-instructions,		BRU_FIN);
-GENERIC_EVENT_ATTR(branch-misses,		BR_MPRED);
-
-POWER_EVENT_ATTR(CYC,				CYC);
-POWER_EVENT_ATTR(GCT_NOSLOT_CYC,		GCT_NOSLOT_CYC);
-POWER_EVENT_ATTR(CMPLU_STALL,			CMPLU_STALL);
-POWER_EVENT_ATTR(INST_CMPL,			INST_CMPL);
-POWER_EVENT_ATTR(LD_REF_L1,			LD_REF_L1);
-POWER_EVENT_ATTR(LD_MISS_L1,			LD_MISS_L1);
-POWER_EVENT_ATTR(BRU_FIN,			BRU_FIN)
-POWER_EVENT_ATTR(BR_MPRED,			BR_MPRED);
-
-POWER_EVENT_ATTR(CMPLU_STALL_FXU,		CMPLU_STALL_FXU);
-POWER_EVENT_ATTR(CMPLU_STALL_DIV,		CMPLU_STALL_DIV);
-POWER_EVENT_ATTR(CMPLU_STALL_SCALAR,		CMPLU_STALL_SCALAR);
-POWER_EVENT_ATTR(CMPLU_STALL_SCALAR_LONG,	CMPLU_STALL_SCALAR_LONG);
-POWER_EVENT_ATTR(CMPLU_STALL_VECTOR,		CMPLU_STALL_VECTOR);
-POWER_EVENT_ATTR(CMPLU_STALL_VECTOR_LONG,	CMPLU_STALL_VECTOR_LONG);
-POWER_EVENT_ATTR(CMPLU_STALL_LSU,		CMPLU_STALL_LSU);
-POWER_EVENT_ATTR(CMPLU_STALL_REJECT,		CMPLU_STALL_REJECT);
-
-POWER_EVENT_ATTR(CMPLU_STALL_ERAT_MISS,		CMPLU_STALL_ERAT_MISS);
-POWER_EVENT_ATTR(CMPLU_STALL_DCACHE_MISS,	CMPLU_STALL_DCACHE_MISS);
-POWER_EVENT_ATTR(CMPLU_STALL_STORE,		CMPLU_STALL_STORE);
-POWER_EVENT_ATTR(CMPLU_STALL_THRD,		CMPLU_STALL_THRD);
-POWER_EVENT_ATTR(CMPLU_STALL_IFU,		CMPLU_STALL_IFU);
-POWER_EVENT_ATTR(CMPLU_STALL_BRU,		CMPLU_STALL_BRU);
-POWER_EVENT_ATTR(GCT_NOSLOT_IC_MISS,		GCT_NOSLOT_IC_MISS);
-
-POWER_EVENT_ATTR(GCT_NOSLOT_BR_MPRED,		GCT_NOSLOT_BR_MPRED);
-POWER_EVENT_ATTR(GCT_NOSLOT_BR_MPRED_IC_MISS,	GCT_NOSLOT_BR_MPRED_IC_MISS);
-POWER_EVENT_ATTR(GRP_CMPL,			GRP_CMPL);
-POWER_EVENT_ATTR(1PLUS_PPC_CMPL,		1PLUS_PPC_CMPL);
-POWER_EVENT_ATTR(CMPLU_STALL_DFU,		CMPLU_STALL_DFU);
-POWER_EVENT_ATTR(RUN_CYC,			RUN_CYC);
-POWER_EVENT_ATTR(RUN_INST_CMPL,			RUN_INST_CMPL);
+GENERIC_EVENT_ATTR(cpu-cycles,			PM_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-frontend,	PM_GCT_NOSLOT_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-backend,	PM_CMPLU_STALL);
+GENERIC_EVENT_ATTR(instructions,		PM_INST_CMPL);
+GENERIC_EVENT_ATTR(cache-references,		PM_LD_REF_L1);
+GENERIC_EVENT_ATTR(cache-misses,		PM_LD_MISS_L1);
+GENERIC_EVENT_ATTR(branch-instructions,		PM_BRU_FIN);
+GENERIC_EVENT_ATTR(branch-misses,		PM_BR_MPRED);
+
+#define EVENT(_name, _code)     POWER_EVENT_ATTR(_name, _name);
+#include "power7-events-list.h"
+#undef EVENT
+
+#define EVENT(_name, _code)     POWER_EVENT_PTR(_name),
 
 static struct attribute *power7_events_attr[] = {
-	GENERIC_EVENT_PTR(CYC),
-	GENERIC_EVENT_PTR(GCT_NOSLOT_CYC),
-	GENERIC_EVENT_PTR(CMPLU_STALL),
-	GENERIC_EVENT_PTR(INST_CMPL),
-	GENERIC_EVENT_PTR(LD_REF_L1),
-	GENERIC_EVENT_PTR(LD_MISS_L1),
-	GENERIC_EVENT_PTR(BRU_FIN),
-	GENERIC_EVENT_PTR(BR_MPRED),
-
-	POWER_EVENT_PTR(CYC),
-	POWER_EVENT_PTR(GCT_NOSLOT_CYC),
-	POWER_EVENT_PTR(CMPLU_STALL),
-	POWER_EVENT_PTR(INST_CMPL),
-	POWER_EVENT_PTR(LD_REF_L1),
-	POWER_EVENT_PTR(LD_MISS_L1),
-	POWER_EVENT_PTR(BRU_FIN),
-	POWER_EVENT_PTR(BR_MPRED),
-
-	POWER_EVENT_PTR(CMPLU_STALL_FXU),
-	POWER_EVENT_PTR(CMPLU_STALL_DIV),
-	POWER_EVENT_PTR(CMPLU_STALL_SCALAR),
-	POWER_EVENT_PTR(CMPLU_STALL_SCALAR_LONG),
-	POWER_EVENT_PTR(CMPLU_STALL_VECTOR),
-	POWER_EVENT_PTR(CMPLU_STALL_VECTOR_LONG),
-	POWER_EVENT_PTR(CMPLU_STALL_LSU),
-	POWER_EVENT_PTR(CMPLU_STALL_REJECT),
-
-	POWER_EVENT_PTR(CMPLU_STALL_ERAT_MISS),
-	POWER_EVENT_PTR(CMPLU_STALL_DCACHE_MISS),
-	POWER_EVENT_PTR(CMPLU_STALL_STORE),
-	POWER_EVENT_PTR(CMPLU_STALL_THRD),
-	POWER_EVENT_PTR(CMPLU_STALL_IFU),
-	POWER_EVENT_PTR(CMPLU_STALL_BRU),
-	POWER_EVENT_PTR(GCT_NOSLOT_IC_MISS),
-	POWER_EVENT_PTR(GCT_NOSLOT_BR_MPRED),
-
-	POWER_EVENT_PTR(GCT_NOSLOT_BR_MPRED_IC_MISS),
-	POWER_EVENT_PTR(GRP_CMPL),
-	POWER_EVENT_PTR(1PLUS_PPC_CMPL),
-	POWER_EVENT_PTR(CMPLU_STALL_DFU),
-	POWER_EVENT_PTR(RUN_CYC),
-	POWER_EVENT_PTR(RUN_INST_CMPL),
+	GENERIC_EVENT_PTR(PM_CYC),
+	GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
+	GENERIC_EVENT_PTR(PM_CMPLU_STALL),
+	GENERIC_EVENT_PTR(PM_INST_CMPL),
+	GENERIC_EVENT_PTR(PM_LD_REF_L1),
+	GENERIC_EVENT_PTR(PM_LD_MISS_L1),
+	GENERIC_EVENT_PTR(PM_BRU_FIN),
+	GENERIC_EVENT_PTR(PM_BR_MPRED),
+
+	#include "power7-events-list.h"
+	#undef EVENT
 	NULL
 };
 
-
 static struct attribute_group power7_pmu_events_group = {
 	.name = "events",
 	.attrs = power7_events_attr,
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index db4e638..a238bc3 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -126,7 +126,7 @@ int elf_coredump_extra_notes_size(void)
 	return ret;
 }
 
-int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
+int elf_coredump_extra_notes_write(struct coredump_params *cprm)
 {
 	struct spufs_calls *calls;
 	int ret;
@@ -135,7 +135,7 @@ int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
 	if (!calls)
 		return 0;
 
-	ret = calls->coredump_extra_notes_write(file, foffset);
+	ret = calls->coredump_extra_notes_write(cprm);
 
 	spufs_calls_put(calls);
 
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index c9500ea..8011c61 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -27,6 +27,7 @@
 #include <linux/gfp.h>
 #include <linux/list.h>
 #include <linux/syscalls.h>
+#include <linux/coredump.h>
 
 #include <asm/uaccess.h>
 
@@ -48,44 +49,6 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
 	return ++ret; /* count trailing NULL */
 }
 
-/*
- * These are the only things you should do on a core-file: use only these
- * functions to write out all the necessary info.
- */
-static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
-{
-	unsigned long limit = rlimit(RLIMIT_CORE);
-	ssize_t written;
-
-	if (*foffset + nr > limit)
-		return -EIO;
-
-	written = file->f_op->write(file, addr, nr, &file->f_pos);
-	*foffset += written;
-
-	if (written != nr)
-		return -EIO;
-
-	return 0;
-}
-
-static int spufs_dump_align(struct file *file, char *buf, loff_t new_off,
-			    loff_t *foffset)
-{
-	int rc, size;
-
-	size = min((loff_t)PAGE_SIZE, new_off - *foffset);
-	memset(buf, 0, size);
-
-	rc = 0;
-	while (rc == 0 && new_off > *foffset) {
-		size = min((loff_t)PAGE_SIZE, new_off - *foffset);
-		rc = spufs_dump_write(file, buf, size, foffset);
-	}
-
-	return rc;
-}
-
 static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
 {
 	int i, sz, total = 0;
@@ -165,7 +128,7 @@ int spufs_coredump_extra_notes_size(void)
 }
 
 static int spufs_arch_write_note(struct spu_context *ctx, int i,
-				  struct file *file, int dfd, loff_t *foffset)
+				  struct coredump_params *cprm, int dfd)
 {
 	loff_t pos = 0;
 	int sz, rc, nread, total = 0;
@@ -186,23 +149,20 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
 	en.n_descsz = sz;
 	en.n_type = NT_SPU;
 
-	rc = spufs_dump_write(file, &en, sizeof(en), foffset);
-	if (rc)
+	rc = -EIO;
+	if (!dump_emit(cprm, &en, sizeof(en)))
 		goto out;
 
-	rc = spufs_dump_write(file, fullname, en.n_namesz, foffset);
-	if (rc)
+	if (!dump_emit(cprm, fullname, en.n_namesz))
 		goto out;
 
-	rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset);
-	if (rc)
+	if (!dump_align(cprm, 4))
 		goto out;
 
 	do {
 		nread = do_coredump_read(i, ctx, buf, bufsz, &pos);
 		if (nread > 0) {
-			rc = spufs_dump_write(file, buf, nread, foffset);
-			if (rc)
+			if (!dump_emit(cprm, buf, nread))
 				goto out;
 			total += nread;
 		}
@@ -213,15 +173,15 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
 		goto out;
 	}
 
-	rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4),
-			      foffset);
-
+	if (!dump_align(cprm, 4))
+		goto out;
+	rc = 0;
 out:
 	free_page((unsigned long)buf);
 	return rc;
 }
 
-int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
+int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
 {
 	struct spu_context *ctx;
 	int fd, j, rc;
@@ -233,7 +193,7 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
 			return rc;
 
 		for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
-			rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
+			rc = spufs_arch_write_note(ctx, j, cprm, fd);
 			if (rc) {
 				spu_release_saved(ctx);
 				return rc;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 67852ad..28b8973 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -252,7 +252,7 @@ long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
 			umode_t mode, struct file *filp);
 /* ELF coredump callbacks for writing SPU ELF notes */
 extern int spufs_coredump_extra_notes_size(void);
-extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset);
+extern int spufs_coredump_extra_notes_write(struct coredump_params *);
 
 extern const struct file_operations spufs_context_fops;
 
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index cba1e6b..ce73ce8 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -90,7 +90,7 @@ static int __init ps3_rtc_init(void)
 
 	pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
 
-	return PTR_RET(pdev);
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 module_init(ps3_rtc_init);
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
index af79e1e..af0f9be 100644
--- a/arch/powerpc/sysdev/rtc_cmos_setup.c
+++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
@@ -62,7 +62,7 @@ static int  __init add_rtc(void)
 	pd = platform_device_register_simple("rtc_cmos", -1,
 					     &res[0], num_res);
 
-	return PTR_RET(pd);
+	return PTR_ERR_OR_ZERO(pd);
 }
 fs_initcall(add_rtc);
 
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 22f75b5..8d9da40 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -116,8 +116,10 @@ config S390
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	select HAVE_GENERIC_HARDIRQS
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_LZ4
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_XZ
@@ -227,11 +229,12 @@ config MARCH_Z196
 	  not work on older machines.
 
 config MARCH_ZEC12
-	bool "IBM zEC12"
+	bool "IBM zBC12 and zEC12"
 	select HAVE_MARCH_ZEC12_FEATURES if 64BIT
 	help
-	  Select this to enable optimizations for IBM zEC12 (2827 series). The
-	  kernel will be slightly faster but will not work on older machines.
+	  Select this to enable optimizations for IBM zBC12 and zEC12 (2828 and
+	  2827 series). The kernel will be slightly faster but will not work on
+	  older machines.
 
 endchoice
 
@@ -428,7 +431,6 @@ menuconfig PCI
 	bool "PCI support"
 	default n
 	depends on 64BIT
-	select ARCH_SUPPORTS_MSI
 	select PCI_MSI
 	help
 	  Enable PCI support.
@@ -443,6 +445,16 @@ config PCI_NR_FUNCTIONS
 	  This allows you to specify the maximum number of PCI functions which
 	  this kernel will support.
 
+config PCI_NR_MSI
+	int "Maximum number of MSI interrupts (64-32768)"
+	range 64 32768
+	default "256"
+	help
+	  This defines the number of virtual interrupts the kernel will
+	  provide for MSI interrupts. If you configure your system to have
+	  too few drivers will fail to allocate MSI interrupts for all
+	  PCI devices.
+
 source "drivers/pci/Kconfig"
 source "drivers/pci/pcie/Kconfig"
 source "drivers/pci/hotplug/Kconfig"
@@ -514,6 +526,7 @@ config CRASH_DUMP
 	bool "kernel crash dumps"
 	depends on 64BIT && SMP
 	select KEXEC
+	select ZFCPDUMP
 	help
 	  Generate crash dump after being started by kexec.
 	  Crash dump kernels are loaded in the main kernel with kexec-tools
@@ -524,7 +537,7 @@ config CRASH_DUMP
 config ZFCPDUMP
 	def_bool n
 	prompt "zfcpdump support"
-	select SMP
+	depends on SMP
 	help
 	  Select this option if you want to build an zfcpdump enabled kernel.
 	  Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
@@ -709,6 +722,7 @@ config S390_GUEST
 	def_bool y
 	prompt "s390 support for virtio devices"
 	depends on 64BIT
+	select TTY
 	select VIRTUALIZATION
 	select VIRTIO
 	select VIRTIO_CONSOLE
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile
index 3ad8f61..866ecbe 100644
--- a/arch/s390/boot/compressed/Makefile
+++ b/arch/s390/boot/compressed/Makefile
@@ -6,9 +6,9 @@
 
 BITS := $(if $(CONFIG_64BIT),64,31)
 
-targets	:= vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \
-	   vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \
-	   sizes.h head$(BITS).o
+targets	:= vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2
+targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4
+targets += misc.o piggy.o sizes.h head$(BITS).o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
@@ -48,6 +48,7 @@ vmlinux.bin.all-y := $(obj)/vmlinux.bin
 
 suffix-$(CONFIG_KERNEL_GZIP)  := gz
 suffix-$(CONFIG_KERNEL_BZIP2) := bz2
+suffix-$(CONFIG_KERNEL_LZ4)  := lz4
 suffix-$(CONFIG_KERNEL_LZMA)  := lzma
 suffix-$(CONFIG_KERNEL_LZO)  := lzo
 suffix-$(CONFIG_KERNEL_XZ)  := xz
@@ -56,6 +57,8 @@ $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y)
 	$(call if_changed,gzip)
 $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y)
 	$(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y)
+	$(call if_changed,lz4)
 $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y)
 	$(call if_changed,lzma)
 $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y)
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c
index c4c6a1c..57cbaff 100644
--- a/arch/s390/boot/compressed/misc.c
+++ b/arch/s390/boot/compressed/misc.c
@@ -47,6 +47,10 @@ static unsigned long free_mem_end_ptr;
 #include "../../../../lib/decompress_bunzip2.c"
 #endif
 
+#ifdef CONFIG_KERNEL_LZ4
+#include "../../../../lib/decompress_unlz4.c"
+#endif
+
 #ifdef CONFIG_KERNEL_LZMA
 #include "../../../../lib/decompress_unlzma.c"
 #endif
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c
index bb5dd49..17ab8b7 100644
--- a/arch/s390/hypfs/hypfs_dbfs.c
+++ b/arch/s390/hypfs/hypfs_dbfs.c
@@ -105,7 +105,7 @@ void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
 int hypfs_dbfs_init(void)
 {
 	dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
-	return PTR_RET(dbfs_dir);
+	return PTR_ERR_OR_ZERO(dbfs_dir);
 }
 
 void hypfs_dbfs_exit(void)
diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h
index 4066cee..4bbb595 100644
--- a/arch/s390/include/asm/airq.h
+++ b/arch/s390/include/asm/airq.h
@@ -9,6 +9,8 @@
 #ifndef _ASM_S390_AIRQ_H
 #define _ASM_S390_AIRQ_H
 
+#include <linux/bit_spinlock.h>
+
 struct airq_struct {
 	struct hlist_node list;		/* Handler queueing. */
 	void (*handler)(struct airq_struct *);	/* Thin-interrupt handler */
@@ -23,4 +25,69 @@ struct airq_struct {
 int register_adapter_interrupt(struct airq_struct *airq);
 void unregister_adapter_interrupt(struct airq_struct *airq);
 
+/* Adapter interrupt bit vector */
+struct airq_iv {
+	unsigned long *vector;	/* Adapter interrupt bit vector */
+	unsigned long *avail;	/* Allocation bit mask for the bit vector */
+	unsigned long *bitlock;	/* Lock bit mask for the bit vector */
+	unsigned long *ptr;	/* Pointer associated with each bit */
+	unsigned int *data;	/* 32 bit value associated with each bit */
+	unsigned long bits;	/* Number of bits in the vector */
+	unsigned long end;	/* Number of highest allocated bit + 1 */
+	spinlock_t lock;	/* Lock to protect alloc & free */
+};
+
+#define AIRQ_IV_ALLOC	1	/* Use an allocation bit mask */
+#define AIRQ_IV_BITLOCK	2	/* Allocate the lock bit mask */
+#define AIRQ_IV_PTR	4	/* Allocate the ptr array */
+#define AIRQ_IV_DATA	8	/* Allocate the data array */
+
+struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags);
+void airq_iv_release(struct airq_iv *iv);
+unsigned long airq_iv_alloc_bit(struct airq_iv *iv);
+void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit);
+unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
+			   unsigned long end);
+
+static inline unsigned long airq_iv_end(struct airq_iv *iv)
+{
+	return iv->end;
+}
+
+static inline void airq_iv_lock(struct airq_iv *iv, unsigned long bit)
+{
+	const unsigned long be_to_le = BITS_PER_LONG - 1;
+	bit_spin_lock(bit ^ be_to_le, iv->bitlock);
+}
+
+static inline void airq_iv_unlock(struct airq_iv *iv, unsigned long bit)
+{
+	const unsigned long be_to_le = BITS_PER_LONG - 1;
+	bit_spin_unlock(bit ^ be_to_le, iv->bitlock);
+}
+
+static inline void airq_iv_set_data(struct airq_iv *iv, unsigned long bit,
+				    unsigned int data)
+{
+	iv->data[bit] = data;
+}
+
+static inline unsigned int airq_iv_get_data(struct airq_iv *iv,
+					    unsigned long bit)
+{
+	return iv->data[bit];
+}
+
+static inline void airq_iv_set_ptr(struct airq_iv *iv, unsigned long bit,
+				   unsigned long ptr)
+{
+	iv->ptr[bit] = ptr;
+}
+
+static inline unsigned long airq_iv_get_ptr(struct airq_iv *iv,
+					    unsigned long bit)
+{
+	return iv->ptr[bit];
+}
+
 #endif /* _ASM_S390_AIRQ_H */
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 4d8604e..7d46767 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -693,7 +693,7 @@ static inline int find_next_bit_left(const unsigned long *addr,
 	size -= offset;
 	p = addr + offset / BITS_PER_LONG;
 	if (bit) {
-		set = __flo_word(0, *p & (~0UL << bit));
+		set = __flo_word(0, *p & (~0UL >> bit));
 		if (set >= size)
 			return size + offset;
 		if (set < BITS_PER_LONG)
diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h
index 0c82ba8..a908d29 100644
--- a/arch/s390/include/asm/hardirq.h
+++ b/arch/s390/include/asm/hardirq.h
@@ -20,4 +20,9 @@
 
 #define HARDIRQ_BITS	8
 
+static inline void ack_bad_irq(unsigned int irq)
+{
+	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
+}
+
 #endif /* __ASM_HARDIRQ_H */
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index bd90359..11eae5f 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -17,6 +17,9 @@
 
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 		     pte_t *ptep, pte_t pte);
+pte_t huge_ptep_get(pte_t *ptep);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+			      unsigned long addr, pte_t *ptep);
 
 /*
  * If the arch doesn't supply something else, assume that hugepage
@@ -38,147 +41,75 @@ static inline int prepare_hugepage_range(struct file *file,
 int arch_prepare_hugepage(struct page *page);
 void arch_release_hugepage(struct page *page);
 
-static inline pte_t huge_pte_wrprotect(pte_t pte)
+static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
+				  pte_t *ptep)
 {
-	pte_val(pte) |= _PAGE_RO;
-	return pte;
+	pte_val(*ptep) = _SEGMENT_ENTRY_EMPTY;
 }
 
-static inline int huge_pte_none(pte_t pte)
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+					 unsigned long address, pte_t *ptep)
 {
-	return (pte_val(pte) & _SEGMENT_ENTRY_INV) &&
-		!(pte_val(pte) & _SEGMENT_ENTRY_RO);
+	huge_ptep_get_and_clear(vma->vm_mm, address, ptep);
 }
 
-static inline pte_t huge_ptep_get(pte_t *ptep)
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+					     unsigned long addr, pte_t *ptep,
+					     pte_t pte, int dirty)
 {
-	pte_t pte = *ptep;
-	unsigned long mask;
-
-	if (!MACHINE_HAS_HPAGE) {
-		ptep = (pte_t *) (pte_val(pte) & _SEGMENT_ENTRY_ORIGIN);
-		if (ptep) {
-			mask = pte_val(pte) &
-				(_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
-			pte = pte_mkhuge(*ptep);
-			pte_val(pte) |= mask;
-		}
+	int changed = !pte_same(huge_ptep_get(ptep), pte);
+	if (changed) {
+		huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
+		set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
 	}
-	return pte;
+	return changed;
 }
 
-static inline void __pmd_csp(pmd_t *pmdp)
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+					   unsigned long addr, pte_t *ptep)
 {
-	register unsigned long reg2 asm("2") = pmd_val(*pmdp);
-	register unsigned long reg3 asm("3") = pmd_val(*pmdp) |
-					       _SEGMENT_ENTRY_INV;
-	register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5;
-
-	asm volatile(
-		"	csp %1,%3"
-		: "=m" (*pmdp)
-		: "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc");
+	pte_t pte = huge_ptep_get_and_clear(mm, addr, ptep);
+	set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
 }
 
-static inline void huge_ptep_invalidate(struct mm_struct *mm,
-					unsigned long address, pte_t *ptep)
-{
-	pmd_t *pmdp = (pmd_t *) ptep;
-
-	if (MACHINE_HAS_IDTE)
-		__pmd_idte(address, pmdp);
-	else
-		__pmd_csp(pmdp);
-	pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
-}
-
-static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
-					    unsigned long addr, pte_t *ptep)
-{
-	pte_t pte = huge_ptep_get(ptep);
-
-	huge_ptep_invalidate(mm, addr, ptep);
-	return pte;
-}
-
-#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
-({									    \
-	int __changed = !pte_same(huge_ptep_get(__ptep), __entry);	    \
-	if (__changed) {						    \
-		huge_ptep_invalidate((__vma)->vm_mm, __addr, __ptep);	    \
-		set_huge_pte_at((__vma)->vm_mm, __addr, __ptep, __entry);   \
-	}								    \
-	__changed;							    \
-})
-
-#define huge_ptep_set_wrprotect(__mm, __addr, __ptep)			\
-({									\
-	pte_t __pte = huge_ptep_get(__ptep);				\
-	if (huge_pte_write(__pte)) {					\
-		huge_ptep_invalidate(__mm, __addr, __ptep);		\
-		set_huge_pte_at(__mm, __addr, __ptep,			\
-				huge_pte_wrprotect(__pte));		\
-	}								\
-})
-
-static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
-					 unsigned long address, pte_t *ptep)
+static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
 {
-	huge_ptep_invalidate(vma->vm_mm, address, ptep);
+	return mk_pte(page, pgprot);
 }
 
-static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
+static inline int huge_pte_none(pte_t pte)
 {
-	pte_t pte;
-	pmd_t pmd;
-
-	pmd = mk_pmd_phys(page_to_phys(page), pgprot);
-	pte_val(pte) = pmd_val(pmd);
-	return pte;
+	return pte_none(pte);
 }
 
 static inline int huge_pte_write(pte_t pte)
 {
-	pmd_t pmd;
-
-	pmd_val(pmd) = pte_val(pte);
-	return pmd_write(pmd);
+	return pte_write(pte);
 }
 
 static inline int huge_pte_dirty(pte_t pte)
 {
-	/* No dirty bit in the segment table entry. */
-	return 0;
+	return pte_dirty(pte);
 }
 
 static inline pte_t huge_pte_mkwrite(pte_t pte)
 {
-	pmd_t pmd;
-
-	pmd_val(pmd) = pte_val(pte);
-	pte_val(pte) = pmd_val(pmd_mkwrite(pmd));
-	return pte;
+	return pte_mkwrite(pte);
 }
 
 static inline pte_t huge_pte_mkdirty(pte_t pte)
 {
-	/* No dirty bit in the segment table entry. */
-	return pte;
+	return pte_mkdirty(pte);
 }
 
-static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t huge_pte_wrprotect(pte_t pte)
 {
-	pmd_t pmd;
-
-	pmd_val(pmd) = pte_val(pte);
-	pte_val(pte) = pmd_val(pmd_modify(pmd, newprot));
-	return pte;
+	return pte_wrprotect(pte);
 }
 
-static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
-				  pte_t *ptep)
+static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
 {
-	pmd_clear((pmd_t *) ptep);
+	return pte_modify(pte, newprot);
 }
 
 #endif /* _ASM_S390_HUGETLB_H */
diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h
index 7e3d258..ee96a8b 100644
--- a/arch/s390/include/asm/hw_irq.h
+++ b/arch/s390/include/asm/hw_irq.h
@@ -4,19 +4,8 @@
 #include <linux/msi.h>
 #include <linux/pci.h>
 
-static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
-{
-	return __irq_get_msi_desc(irq);
-}
-
-/* Must be called with msi map lock held */
-static inline int irq_set_msi_desc(unsigned int irq, struct msi_desc *msi)
-{
-	if (!msi)
-		return -EINVAL;
-
-	msi->irq = irq;
-	return 0;
-}
+void __init init_airq_interrupts(void);
+void __init init_cio_interrupts(void);
+void __init init_ext_interrupts(void);
 
 #endif
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 87c17bf..1eaa362 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -1,17 +1,28 @@
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
+#define EXT_INTERRUPT	1
+#define IO_INTERRUPT	2
+#define THIN_INTERRUPT	3
+
+#define NR_IRQS_BASE	4
+
+#ifdef CONFIG_PCI_NR_MSI
+# define NR_IRQS	(NR_IRQS_BASE + CONFIG_PCI_NR_MSI)
+#else
+# define NR_IRQS	NR_IRQS_BASE
+#endif
+
+/* This number is used when no interrupt has been assigned */
+#define NO_IRQ		0
+
+#ifndef __ASSEMBLY__
+
 #include <linux/hardirq.h>
 #include <linux/percpu.h>
 #include <linux/cache.h>
 #include <linux/types.h>
 
-enum interruption_main_class {
-	EXTERNAL_INTERRUPT,
-	IO_INTERRUPT,
-	NR_IRQS
-};
-
 enum interruption_class {
 	IRQEXT_CLK,
 	IRQEXT_EXC,
@@ -72,14 +83,8 @@ void service_subclass_irq_unregister(void);
 void measurement_alert_subclass_register(void);
 void measurement_alert_subclass_unregister(void);
 
-#ifdef CONFIG_LOCKDEP
-#  define disable_irq_nosync_lockdep(irq)	disable_irq_nosync(irq)
-#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
-						disable_irq_nosync(irq)
-#  define disable_irq_lockdep(irq)		disable_irq(irq)
-#  define enable_irq_lockdep(irq)		enable_irq(irq)
-#  define enable_irq_lockdep_irqrestore(irq, flags) \
-						enable_irq(irq)
-#endif
+#define irq_canonicalize(irq)  (irq)
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_IRQ_H */
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 3238d40..e87ecaa 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -274,6 +274,14 @@ struct kvm_arch{
 	int css_support;
 };
 
+#define KVM_HVA_ERR_BAD		(-1UL)
+#define KVM_HVA_ERR_RO_BAD	(-2UL)
+
+static inline bool kvm_is_error_hva(unsigned long addr)
+{
+	return IS_ERR_VALUE(addr);
+}
+
 extern int sie64a(struct kvm_s390_sie_block *, u64 *);
 extern char sie_exit;
 #endif
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index 6340178..ff132ac 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -12,8 +12,6 @@ typedef struct {
 	unsigned long asce_bits;
 	unsigned long asce_limit;
 	unsigned long vdso_base;
-	/* Cloned contexts will be created with extended page tables. */
-	unsigned int alloc_pgste:1;
 	/* The mmu context has extended page tables. */
 	unsigned int has_pgste:1;
 } mm_context_t;
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 084e775..4fb67a0 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -21,24 +21,7 @@ static inline int init_new_context(struct task_struct *tsk,
 #ifdef CONFIG_64BIT
 	mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #endif
-	if (current->mm && current->mm->context.alloc_pgste) {
-		/*
-		 * alloc_pgste indicates, that any NEW context will be created
-		 * with extended page tables. The old context is unchanged. The
-		 * page table allocation and the page table operations will
-		 * look at has_pgste to distinguish normal and extended page
-		 * tables. The only way to create extended page tables is to
-		 * set alloc_pgste and then create a new context (e.g. dup_mm).
-		 * The page table allocation is called after init_new_context
-		 * and if has_pgste is set, it will create extended page
-		 * tables.
-		 */
-		mm->context.has_pgste = 1;
-		mm->context.alloc_pgste = 1;
-	} else {
-		mm->context.has_pgste = 0;
-		mm->context.alloc_pgste = 0;
-	}
+	mm->context.has_pgste = 0;
 	mm->context.asce_limit = STACK_TOP_MAX;
 	crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
 	return 0;
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 5d64fb7..27f0480 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -32,16 +32,6 @@
 
 void storage_key_init_range(unsigned long start, unsigned long end);
 
-static inline unsigned long pfmf(unsigned long function, unsigned long address)
-{
-	asm volatile(
-		"	.insn	rre,0xb9af0000,%[function],%[address]"
-		: [address] "+a" (address)
-		: [function] "d" (function)
-		: "memory");
-	return address;
-}
-
 static inline void clear_page(void *page)
 {
 	register unsigned long reg1 asm ("1") = 0;
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 6e577ba..5b8120a 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -21,10 +21,6 @@ void pci_iounmap(struct pci_dev *, void __iomem *);
 int pci_domain_nr(struct pci_bus *);
 int pci_proc_domain(struct pci_bus *);
 
-/* MSI arch hooks */
-#define arch_setup_msi_irqs	arch_setup_msi_irqs
-#define arch_teardown_msi_irqs	arch_teardown_msi_irqs
-
 #define ZPCI_BUS_NR			0	/* default bus number */
 #define ZPCI_DEVFN			0	/* default device number */
 
@@ -53,14 +49,9 @@ struct zpci_fmb {
 	atomic64_t unmapped_pages;
 } __packed __aligned(16);
 
-struct msi_map {
-	unsigned long irq;
-	struct msi_desc *msi;
-	struct hlist_node msi_chain;
-};
-
-#define ZPCI_NR_MSI_VECS	64
-#define ZPCI_MSI_MASK		(ZPCI_NR_MSI_VECS - 1)
+#define ZPCI_MSI_VEC_BITS	11
+#define ZPCI_MSI_VEC_MAX	(1 << ZPCI_MSI_VEC_BITS)
+#define ZPCI_MSI_VEC_MASK	(ZPCI_MSI_VEC_MAX - 1)
 
 enum zpci_state {
 	ZPCI_FN_STATE_RESERVED,
@@ -91,8 +82,7 @@ struct zpci_dev {
 
 	/* IRQ stuff */
 	u64		msi_addr;	/* MSI address */
-	struct zdev_irq_map *irq_map;
-	struct msi_map *msi_map[ZPCI_NR_MSI_VECS];
+	struct airq_iv *aibv;		/* adapter interrupt bit vector */
 	unsigned int	aisb;		/* number of the summary bit */
 
 	/* DMA stuff */
@@ -151,14 +141,6 @@ int clp_add_pci_device(u32, u32, int);
 int clp_enable_fh(struct zpci_dev *, u8);
 int clp_disable_fh(struct zpci_dev *);
 
-/* MSI */
-struct msi_desc *__irq_get_msi_desc(unsigned int);
-int zpci_msi_set_mask_bits(struct msi_desc *, u32, u32);
-int zpci_setup_msi_irq(struct zpci_dev *, struct msi_desc *, unsigned int, int);
-void zpci_teardown_msi_irq(struct zpci_dev *, struct msi_desc *);
-int zpci_msihash_init(void);
-void zpci_msihash_exit(void);
-
 #ifdef CONFIG_PCI
 /* Error handling and recovery */
 void zpci_event_error(void *);
diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
index e6a2bdd..df6eac9 100644
--- a/arch/s390/include/asm/pci_insn.h
+++ b/arch/s390/include/asm/pci_insn.h
@@ -79,11 +79,11 @@ struct zpci_fib {
 } __packed;
 
 
-int s390pci_mod_fc(u64 req, struct zpci_fib *fib);
-int s390pci_refresh_trans(u64 fn, u64 addr, u64 range);
-int s390pci_load(u64 *data, u64 req, u64 offset);
-int s390pci_store(u64 data, u64 req, u64 offset);
-int s390pci_store_block(const u64 *data, u64 req, u64 offset);
-void set_irq_ctrl(u16 ctl, char *unused, u8 isc);
+int zpci_mod_fc(u64 req, struct zpci_fib *fib);
+int zpci_refresh_trans(u64 fn, u64 addr, u64 range);
+int zpci_load(u64 *data, u64 req, u64 offset);
+int zpci_store(u64 data, u64 req, u64 offset);
+int zpci_store_block(const u64 *data, u64 req, u64 offset);
+void zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc);
 
 #endif
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h
index 83a9caa..d194d54 100644
--- a/arch/s390/include/asm/pci_io.h
+++ b/arch/s390/include/asm/pci_io.h
@@ -36,7 +36,7 @@ static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)	\
 	u64 data;								\
 	int rc;									\
 										\
-	rc = s390pci_load(&data, req, ZPCI_OFFSET(addr));			\
+	rc = zpci_load(&data, req, ZPCI_OFFSET(addr));				\
 	if (rc)									\
 		data = -1ULL;							\
 	return (RETTYPE) data;							\
@@ -50,7 +50,7 @@ static inline void zpci_write_##VALTYPE(VALTYPE val,				\
 	u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH);		\
 	u64 data = (VALTYPE) val;						\
 										\
-	s390pci_store(data, req, ZPCI_OFFSET(addr));				\
+	zpci_store(data, req, ZPCI_OFFSET(addr));				\
 }
 
 zpci_read(8, u64)
@@ -83,7 +83,7 @@ static inline int zpci_write_single(u64 req, const u64 *data, u64 offset, u8 len
 		val = 0;		/* let FW report error */
 		break;
 	}
-	return s390pci_store(val, req, offset);
+	return zpci_store(val, req, offset);
 }
 
 static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
@@ -91,7 +91,7 @@ static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
 	u64 data;
 	int cc;
 
-	cc = s390pci_load(&data, req, offset);
+	cc = zpci_load(&data, req, offset);
 	if (cc)
 		goto out;
 
@@ -115,7 +115,7 @@ out:
 
 static inline int zpci_write_block(u64 req, const u64 *data, u64 offset)
 {
-	return s390pci_store_block(data, req, offset);
+	return zpci_store_block(data, req, offset);
 }
 
 static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 75fb726..5a1ab3d 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -217,63 +217,50 @@ extern unsigned long MODULES_END;
 
 /* Hardware bits in the page table entry */
 #define _PAGE_CO	0x100		/* HW Change-bit override */
-#define _PAGE_RO	0x200		/* HW read-only bit  */
+#define _PAGE_PROTECT	0x200		/* HW read-only bit  */
 #define _PAGE_INVALID	0x400		/* HW invalid bit    */
+#define _PAGE_LARGE	0x800		/* Bit to mark a large pte */
 
 /* Software bits in the page table entry */
-#define _PAGE_SWT	0x001		/* SW pte type bit t */
-#define _PAGE_SWX	0x002		/* SW pte type bit x */
-#define _PAGE_SWC	0x004		/* SW pte changed bit */
-#define _PAGE_SWR	0x008		/* SW pte referenced bit */
-#define _PAGE_SWW	0x010		/* SW pte write bit */
+#define _PAGE_PRESENT	0x001		/* SW pte present bit */
+#define _PAGE_TYPE	0x002		/* SW pte type bit */
+#define _PAGE_DIRTY	0x004		/* SW pte dirty bit */
+#define _PAGE_YOUNG	0x008		/* SW pte young bit */
+#define _PAGE_WRITE	0x010		/* SW pte write bit */
 #define _PAGE_SPECIAL	0x020		/* SW associated with special page */
 #define __HAVE_ARCH_PTE_SPECIAL
 
 /* Set of bits not changed in pte_modify */
 #define _PAGE_CHG_MASK		(PAGE_MASK | _PAGE_SPECIAL | _PAGE_CO | \
-				 _PAGE_SWC | _PAGE_SWR)
-
-/* Six different types of pages. */
-#define _PAGE_TYPE_EMPTY	0x400
-#define _PAGE_TYPE_NONE		0x401
-#define _PAGE_TYPE_SWAP		0x403
-#define _PAGE_TYPE_FILE		0x601	/* bit 0x002 is used for offset !! */
-#define _PAGE_TYPE_RO		0x200
-#define _PAGE_TYPE_RW		0x000
-
-/*
- * Only four types for huge pages, using the invalid bit and protection bit
- * of a segment table entry.
- */
-#define _HPAGE_TYPE_EMPTY	0x020	/* _SEGMENT_ENTRY_INV */
-#define _HPAGE_TYPE_NONE	0x220
-#define _HPAGE_TYPE_RO		0x200	/* _SEGMENT_ENTRY_RO  */
-#define _HPAGE_TYPE_RW		0x000
+				 _PAGE_DIRTY | _PAGE_YOUNG)
 
 /*
- * PTE type bits are rather complicated. handle_pte_fault uses pte_present,
- * pte_none and pte_file to find out the pte type WITHOUT holding the page
- * table lock. ptep_clear_flush on the other hand uses ptep_clear_flush to
- * invalidate a given pte. ipte sets the hw invalid bit and clears all tlbs
- * for the page. The page table entry is set to _PAGE_TYPE_EMPTY afterwards.
- * This change is done while holding the lock, but the intermediate step
- * of a previously valid pte with the hw invalid bit set can be observed by
- * handle_pte_fault. That makes it necessary that all valid pte types with
- * the hw invalid bit set must be distinguishable from the four pte types
- * empty, none, swap and file.
+ * handle_pte_fault uses pte_present, pte_none and pte_file to find out the
+ * pte type WITHOUT holding the page table lock. The _PAGE_PRESENT bit
+ * is used to distinguish present from not-present ptes. It is changed only
+ * with the page table lock held.
  *
- *			irxt  ipte  irxt
- * _PAGE_TYPE_EMPTY	1000   ->   1000
- * _PAGE_TYPE_NONE	1001   ->   1001
- * _PAGE_TYPE_SWAP	1011   ->   1011
- * _PAGE_TYPE_FILE	11?1   ->   11?1
- * _PAGE_TYPE_RO	0100   ->   1100
- * _PAGE_TYPE_RW	0000   ->   1000
+ * The following table gives the different possible bit combinations for
+ * the pte hardware and software bits in the last 12 bits of a pte:
  *
- * pte_none is true for bits combinations 1000, 1010, 1100, 1110
- * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001
- * pte_file is true for bits combinations 1101, 1111
- * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
+ *			842100000000
+ *			000084210000
+ *			000000008421
+ *			.IR....wdytp
+ * empty		.10....00000
+ * swap			.10....xxx10
+ * file			.11....xxxx0
+ * prot-none, clean	.10....00x01
+ * prot-none, dirty	.10....01x01
+ * read-only, clean	.01....00x01
+ * read-only, dirty	.01....01x01
+ * read-write, clean	.01....10x01
+ * read-write, dirty	.00....11x01
+ *
+ * pte_present is true for the bit pattern .xx...xxxxx1, (pte & 0x001) == 0x001
+ * pte_none    is true for the bit pattern .10...xxxx00, (pte & 0x603) == 0x400
+ * pte_file    is true for the bit pattern .11...xxxxx0, (pte & 0x601) == 0x600
+ * pte_swap    is true for the bit pattern .10...xxxx10, (pte & 0x603) == 0x402
  */
 
 #ifndef CONFIG_64BIT
@@ -287,13 +274,13 @@ extern unsigned long MODULES_END;
 
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN	0x7fffffc0UL	/* page table origin	    */
-#define _SEGMENT_ENTRY_RO	0x200	/* page protection bit		    */
-#define _SEGMENT_ENTRY_INV	0x20	/* invalid segment table entry	    */
+#define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */
+#define _SEGMENT_ENTRY_INVALID	0x20	/* invalid segment table entry	    */
 #define _SEGMENT_ENTRY_COMMON	0x10	/* common segment bit		    */
 #define _SEGMENT_ENTRY_PTL	0x0f	/* page table length		    */
 
 #define _SEGMENT_ENTRY		(_SEGMENT_ENTRY_PTL)
-#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INV)
+#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)
 
 /* Page status table bits for virtualization */
 #define PGSTE_ACC_BITS	0xf0000000UL
@@ -324,8 +311,8 @@ extern unsigned long MODULES_END;
 
 /* Bits in the region table entry */
 #define _REGION_ENTRY_ORIGIN	~0xfffUL/* region/segment table origin	    */
-#define _REGION_ENTRY_RO	0x200	/* region protection bit	    */
-#define _REGION_ENTRY_INV	0x20	/* invalid region table entry	    */
+#define _REGION_ENTRY_PROTECT	0x200	/* region protection bit	    */
+#define _REGION_ENTRY_INVALID	0x20	/* invalid region table entry	    */
 #define _REGION_ENTRY_TYPE_MASK	0x0c	/* region/segment table type mask   */
 #define _REGION_ENTRY_TYPE_R1	0x0c	/* region first table type	    */
 #define _REGION_ENTRY_TYPE_R2	0x08	/* region second table type	    */
@@ -333,11 +320,11 @@ extern unsigned long MODULES_END;
 #define _REGION_ENTRY_LENGTH	0x03	/* region third length		    */
 
 #define _REGION1_ENTRY		(_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_LENGTH)
-#define _REGION1_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INV)
+#define _REGION1_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID)
 #define _REGION2_ENTRY		(_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
-#define _REGION2_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INV)
+#define _REGION2_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID)
 #define _REGION3_ENTRY		(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
-#define _REGION3_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
+#define _REGION3_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID)
 
 #define _REGION3_ENTRY_LARGE	0x400	/* RTTE-format control, large page  */
 #define _REGION3_ENTRY_RO	0x200	/* page protection bit		    */
@@ -346,16 +333,17 @@ extern unsigned long MODULES_END;
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address	    */
 #define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */
-#define _SEGMENT_ENTRY_RO	0x200	/* page protection bit		    */
-#define _SEGMENT_ENTRY_INV	0x20	/* invalid segment table entry	    */
+#define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */
+#define _SEGMENT_ENTRY_INVALID	0x20	/* invalid segment table entry	    */
 
 #define _SEGMENT_ENTRY		(0)
-#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INV)
+#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)
 
 #define _SEGMENT_ENTRY_LARGE	0x400	/* STE-format control, large page   */
 #define _SEGMENT_ENTRY_CO	0x100	/* change-recording override   */
+#define _SEGMENT_ENTRY_SPLIT	0x001	/* THP splitting bit */
+
 #define _SEGMENT_ENTRY_SPLIT_BIT 0	/* THP splitting bit number */
-#define _SEGMENT_ENTRY_SPLIT	(1UL << _SEGMENT_ENTRY_SPLIT_BIT)
 
 /* Set of bits not changed in pmd_modify */
 #define _SEGMENT_CHG_MASK	(_SEGMENT_ENTRY_ORIGIN | _SEGMENT_ENTRY_LARGE \
@@ -386,14 +374,13 @@ extern unsigned long MODULES_END;
 /*
  * Page protection definitions.
  */
-#define PAGE_NONE	__pgprot(_PAGE_TYPE_NONE)
-#define PAGE_RO		__pgprot(_PAGE_TYPE_RO)
-#define PAGE_RW		__pgprot(_PAGE_TYPE_RO | _PAGE_SWW)
-#define PAGE_RWC	__pgprot(_PAGE_TYPE_RW | _PAGE_SWW | _PAGE_SWC)
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_INVALID)
+#define PAGE_READ	__pgprot(_PAGE_PRESENT | _PAGE_PROTECT)
+#define PAGE_WRITE	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_PROTECT)
 
-#define PAGE_KERNEL	PAGE_RWC
-#define PAGE_SHARED	PAGE_KERNEL
-#define PAGE_COPY	PAGE_RO
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_DIRTY)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_DIRTY)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_PROTECT)
 
 /*
  * On s390 the page table entry has an invalid bit and a read-only bit.
@@ -402,29 +389,30 @@ extern unsigned long MODULES_END;
  */
          /*xwr*/
 #define __P000	PAGE_NONE
-#define __P001	PAGE_RO
-#define __P010	PAGE_RO
-#define __P011	PAGE_RO
-#define __P100	PAGE_RO
-#define __P101	PAGE_RO
-#define __P110	PAGE_RO
-#define __P111	PAGE_RO
+#define __P001	PAGE_READ
+#define __P010	PAGE_READ
+#define __P011	PAGE_READ
+#define __P100	PAGE_READ
+#define __P101	PAGE_READ
+#define __P110	PAGE_READ
+#define __P111	PAGE_READ
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_RO
-#define __S010	PAGE_RW
-#define __S011	PAGE_RW
-#define __S100	PAGE_RO
-#define __S101	PAGE_RO
-#define __S110	PAGE_RW
-#define __S111	PAGE_RW
+#define __S001	PAGE_READ
+#define __S010	PAGE_WRITE
+#define __S011	PAGE_WRITE
+#define __S100	PAGE_READ
+#define __S101	PAGE_READ
+#define __S110	PAGE_WRITE
+#define __S111	PAGE_WRITE
 
 /*
  * Segment entry (large page) protection definitions.
  */
-#define SEGMENT_NONE	__pgprot(_HPAGE_TYPE_NONE)
-#define SEGMENT_RO	__pgprot(_HPAGE_TYPE_RO)
-#define SEGMENT_RW	__pgprot(_HPAGE_TYPE_RW)
+#define SEGMENT_NONE	__pgprot(_SEGMENT_ENTRY_INVALID | \
+				 _SEGMENT_ENTRY_PROTECT)
+#define SEGMENT_READ	__pgprot(_SEGMENT_ENTRY_PROTECT)
+#define SEGMENT_WRITE	__pgprot(0)
 
 static inline int mm_exclusive(struct mm_struct *mm)
 {
@@ -467,7 +455,7 @@ static inline int pgd_none(pgd_t pgd)
 {
 	if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2)
 		return 0;
-	return (pgd_val(pgd) & _REGION_ENTRY_INV) != 0UL;
+	return (pgd_val(pgd) & _REGION_ENTRY_INVALID) != 0UL;
 }
 
 static inline int pgd_bad(pgd_t pgd)
@@ -478,7 +466,7 @@ static inline int pgd_bad(pgd_t pgd)
 	 * invalid for either table entry.
 	 */
 	unsigned long mask =
-		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV &
+		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INVALID &
 		~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;
 	return (pgd_val(pgd) & mask) != 0;
 }
@@ -494,7 +482,7 @@ static inline int pud_none(pud_t pud)
 {
 	if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3)
 		return 0;
-	return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL;
+	return (pud_val(pud) & _REGION_ENTRY_INVALID) != 0UL;
 }
 
 static inline int pud_large(pud_t pud)
@@ -512,7 +500,7 @@ static inline int pud_bad(pud_t pud)
 	 * invalid for either table entry.
 	 */
 	unsigned long mask =
-		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV &
+		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INVALID &
 		~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;
 	return (pud_val(pud) & mask) != 0;
 }
@@ -521,21 +509,18 @@ static inline int pud_bad(pud_t pud)
 
 static inline int pmd_present(pmd_t pmd)
 {
-	unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
-	return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
-	       !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
+	return pmd_val(pmd) != _SEGMENT_ENTRY_INVALID;
 }
 
 static inline int pmd_none(pmd_t pmd)
 {
-	return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
-	       !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
+	return pmd_val(pmd) == _SEGMENT_ENTRY_INVALID;
 }
 
 static inline int pmd_large(pmd_t pmd)
 {
 #ifdef CONFIG_64BIT
-	return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
+	return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
 #else
 	return 0;
 #endif
@@ -543,7 +528,7 @@ static inline int pmd_large(pmd_t pmd)
 
 static inline int pmd_bad(pmd_t pmd)
 {
-	unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV;
+	unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INVALID;
 	return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY;
 }
 
@@ -563,7 +548,7 @@ extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
 #define __HAVE_ARCH_PMD_WRITE
 static inline int pmd_write(pmd_t pmd)
 {
-	return (pmd_val(pmd) & _SEGMENT_ENTRY_RO) == 0;
+	return (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) == 0;
 }
 
 static inline int pmd_young(pmd_t pmd)
@@ -571,23 +556,23 @@ static inline int pmd_young(pmd_t pmd)
 	return 0;
 }
 
-static inline int pte_none(pte_t pte)
+static inline int pte_present(pte_t pte)
 {
-	return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
+	/* Bit pattern: (pte & 0x001) == 0x001 */
+	return (pte_val(pte) & _PAGE_PRESENT) != 0;
 }
 
-static inline int pte_present(pte_t pte)
+static inline int pte_none(pte_t pte)
 {
-	unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT | _PAGE_SWX;
-	return (pte_val(pte) & mask) == _PAGE_TYPE_NONE ||
-		(!(pte_val(pte) & _PAGE_INVALID) &&
-		 !(pte_val(pte) & _PAGE_SWT));
+	/* Bit pattern: pte == 0x400 */
+	return pte_val(pte) == _PAGE_INVALID;
 }
 
 static inline int pte_file(pte_t pte)
 {
-	unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT;
-	return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
+	/* Bit pattern: (pte & 0x601) == 0x600 */
+	return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT | _PAGE_PRESENT))
+		== (_PAGE_INVALID | _PAGE_PROTECT);
 }
 
 static inline int pte_special(pte_t pte)
@@ -634,6 +619,15 @@ static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
 #endif
 }
 
+static inline pgste_t pgste_get(pte_t *ptep)
+{
+	unsigned long pgste = 0;
+#ifdef CONFIG_PGSTE
+	pgste = *(unsigned long *)(ptep + PTRS_PER_PTE);
+#endif
+	return __pgste(pgste);
+}
+
 static inline void pgste_set(pte_t *ptep, pgste_t pgste)
 {
 #ifdef CONFIG_PGSTE
@@ -695,7 +689,7 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 	/* Transfer referenced bit to kvm user bits and pte */
 	if (young) {
 		pgste_val(pgste) |= PGSTE_UR_BIT;
-		pte_val(*ptep) |= _PAGE_SWR;
+		pte_val(*ptep) |= _PAGE_YOUNG;
 	}
 #endif
 	return pgste;
@@ -723,13 +717,13 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry)
 
 static inline void pgste_set_pte(pte_t *ptep, pte_t entry)
 {
-	if (!MACHINE_HAS_ESOP && (pte_val(entry) & _PAGE_SWW)) {
+	if (!MACHINE_HAS_ESOP && (pte_val(entry) & _PAGE_WRITE)) {
 		/*
 		 * Without enhanced suppression-on-protection force
 		 * the dirty bit on for all writable ptes.
 		 */
-		pte_val(entry) |= _PAGE_SWC;
-		pte_val(entry) &= ~_PAGE_RO;
+		pte_val(entry) |= _PAGE_DIRTY;
+		pte_val(entry) &= ~_PAGE_PROTECT;
 	}
 	*ptep = entry;
 }
@@ -841,18 +835,18 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
  */
 static inline int pte_write(pte_t pte)
 {
-	return (pte_val(pte) & _PAGE_SWW) != 0;
+	return (pte_val(pte) & _PAGE_WRITE) != 0;
 }
 
 static inline int pte_dirty(pte_t pte)
 {
-	return (pte_val(pte) & _PAGE_SWC) != 0;
+	return (pte_val(pte) & _PAGE_DIRTY) != 0;
 }
 
 static inline int pte_young(pte_t pte)
 {
 #ifdef CONFIG_PGSTE
-	if (pte_val(pte) & _PAGE_SWR)
+	if (pte_val(pte) & _PAGE_YOUNG)
 		return 1;
 #endif
 	return 0;
@@ -880,12 +874,12 @@ static inline void pud_clear(pud_t *pud)
 
 static inline void pmd_clear(pmd_t *pmdp)
 {
-	pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
+	pmd_val(*pmdp) = _SEGMENT_ENTRY_INVALID;
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	pte_val(*ptep) = _PAGE_INVALID;
 }
 
 /*
@@ -896,49 +890,49 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	pte_val(pte) &= _PAGE_CHG_MASK;
 	pte_val(pte) |= pgprot_val(newprot);
-	if ((pte_val(pte) & _PAGE_SWC) && (pte_val(pte) & _PAGE_SWW))
-		pte_val(pte) &= ~_PAGE_RO;
+	if ((pte_val(pte) & _PAGE_DIRTY) && (pte_val(pte) & _PAGE_WRITE))
+		pte_val(pte) &= ~_PAGE_PROTECT;
 	return pte;
 }
 
 static inline pte_t pte_wrprotect(pte_t pte)
 {
-	pte_val(pte) &= ~_PAGE_SWW;
-	/* Do not clobber _PAGE_TYPE_NONE pages!  */
+	pte_val(pte) &= ~_PAGE_WRITE;
+	/* Do not clobber PROT_NONE pages!  */
 	if (!(pte_val(pte) & _PAGE_INVALID))
-		pte_val(pte) |= _PAGE_RO;
+		pte_val(pte) |= _PAGE_PROTECT;
 	return pte;
 }
 
 static inline pte_t pte_mkwrite(pte_t pte)
 {
-	pte_val(pte) |= _PAGE_SWW;
-	if (pte_val(pte) & _PAGE_SWC)
-		pte_val(pte) &= ~_PAGE_RO;
+	pte_val(pte) |= _PAGE_WRITE;
+	if (pte_val(pte) & _PAGE_DIRTY)
+		pte_val(pte) &= ~_PAGE_PROTECT;
 	return pte;
 }
 
 static inline pte_t pte_mkclean(pte_t pte)
 {
-	pte_val(pte) &= ~_PAGE_SWC;
-	/* Do not clobber _PAGE_TYPE_NONE pages!  */
+	pte_val(pte) &= ~_PAGE_DIRTY;
+	/* Do not clobber PROT_NONE pages!  */
 	if (!(pte_val(pte) & _PAGE_INVALID))
-		pte_val(pte) |= _PAGE_RO;
+		pte_val(pte) |= _PAGE_PROTECT;
 	return pte;
 }
 
 static inline pte_t pte_mkdirty(pte_t pte)
 {
-	pte_val(pte) |= _PAGE_SWC;
-	if (pte_val(pte) & _PAGE_SWW)
-		pte_val(pte) &= ~_PAGE_RO;
+	pte_val(pte) |= _PAGE_DIRTY;
+	if (pte_val(pte) & _PAGE_WRITE)
+		pte_val(pte) &= ~_PAGE_PROTECT;
 	return pte;
 }
 
 static inline pte_t pte_mkold(pte_t pte)
 {
 #ifdef CONFIG_PGSTE
-	pte_val(pte) &= ~_PAGE_SWR;
+	pte_val(pte) &= ~_PAGE_YOUNG;
 #endif
 	return pte;
 }
@@ -957,7 +951,7 @@ static inline pte_t pte_mkspecial(pte_t pte)
 #ifdef CONFIG_HUGETLB_PAGE
 static inline pte_t pte_mkhuge(pte_t pte)
 {
-	pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
+	pte_val(pte) |= _PAGE_LARGE;
 	return pte;
 }
 #endif
@@ -1076,7 +1070,7 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 	pte = *ptep;
 	if (!mm_exclusive(mm))
 		__ptep_ipte(address, ptep);
-	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	pte_val(*ptep) = _PAGE_INVALID;
 
 	if (mm_has_pgste(mm)) {
 		pgste = pgste_update_all(&pte, pgste);
@@ -1117,7 +1111,7 @@ static inline void ptep_modify_prot_commit(struct mm_struct *mm,
 	pgste_t pgste;
 
 	if (mm_has_pgste(mm)) {
-		pgste = *(pgste_t *)(ptep + PTRS_PER_PTE);
+		pgste = pgste_get(ptep);
 		pgste_set_key(ptep, pgste, pte);
 		pgste_set_pte(ptep, pte);
 		pgste_set_unlock(ptep, pgste);
@@ -1139,7 +1133,7 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
 
 	pte = *ptep;
 	__ptep_ipte(address, ptep);
-	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	pte_val(*ptep) = _PAGE_INVALID;
 
 	if (mm_has_pgste(vma->vm_mm)) {
 		pgste = pgste_update_all(&pte, pgste);
@@ -1163,18 +1157,17 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
 	pgste_t pgste;
 	pte_t pte;
 
-	if (mm_has_pgste(mm)) {
+	if (!full && mm_has_pgste(mm)) {
 		pgste = pgste_get_lock(ptep);
-		if (!full)
-			pgste = pgste_ipte_notify(mm, address, ptep, pgste);
+		pgste = pgste_ipte_notify(mm, address, ptep, pgste);
 	}
 
 	pte = *ptep;
 	if (!full)
 		__ptep_ipte(address, ptep);
-	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	pte_val(*ptep) = _PAGE_INVALID;
 
-	if (mm_has_pgste(mm)) {
+	if (!full && mm_has_pgste(mm)) {
 		pgste = pgste_update_all(&pte, pgste);
 		pgste_set_unlock(ptep, pgste);
 	}
@@ -1248,10 +1241,8 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
 	unsigned long physpage = page_to_phys(page);
 	pte_t __pte = mk_pte_phys(physpage, pgprot);
 
-	if ((pte_val(__pte) & _PAGE_SWW) && PageDirty(page)) {
-		pte_val(__pte) |= _PAGE_SWC;
-		pte_val(__pte) &= ~_PAGE_RO;
-	}
+	if (pte_write(__pte) && PageDirty(page))
+		__pte = pte_mkdirty(__pte);
 	return __pte;
 }
 
@@ -1313,7 +1304,7 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
 	unsigned long sto = (unsigned long) pmdp -
 			    pmd_index(address) * sizeof(pmd_t);
 
-	if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INV)) {
+	if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID)) {
 		asm volatile(
 			"	.insn	rrf,0xb98e0000,%2,%3,0,0"
 			: "=m" (*pmdp)
@@ -1324,18 +1315,31 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
 	}
 }
 
+static inline void __pmd_csp(pmd_t *pmdp)
+{
+	register unsigned long reg2 asm("2") = pmd_val(*pmdp);
+	register unsigned long reg3 asm("3") = pmd_val(*pmdp) |
+					       _SEGMENT_ENTRY_INVALID;
+	register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5;
+
+	asm volatile(
+		"	csp %1,%3"
+		: "=m" (*pmdp)
+		: "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc");
+}
+
 #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)
 static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
 {
 	/*
-	 * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
+	 * pgprot is PAGE_NONE, PAGE_READ, or PAGE_WRITE (see __Pxxx / __Sxxx)
 	 * Convert to segment table entry format.
 	 */
 	if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
 		return pgprot_val(SEGMENT_NONE);
-	if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
-		return pgprot_val(SEGMENT_RO);
-	return pgprot_val(SEGMENT_RW);
+	if (pgprot_val(pgprot) == pgprot_val(PAGE_READ))
+		return pgprot_val(SEGMENT_READ);
+	return pgprot_val(SEGMENT_WRITE);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
@@ -1354,13 +1358,24 @@ static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
 
 static inline pmd_t pmd_mkwrite(pmd_t pmd)
 {
-	/* Do not clobber _HPAGE_TYPE_NONE pages! */
-	if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
-		pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
+	/* Do not clobber PROT_NONE pages! */
+	if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INVALID))
+		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
 	return pmd;
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */
 
+static inline void pmdp_flush_lazy(struct mm_struct *mm,
+				   unsigned long address, pmd_t *pmdp)
+{
+	int active = (mm == current->active_mm) ? 1 : 0;
+
+	if ((atomic_read(&mm->context.attach_count) & 0xffff) > active)
+		__pmd_idte(address, pmdp);
+	else
+		mm->context.flush_mm = 1;
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
@@ -1378,7 +1393,7 @@ static inline int pmd_trans_splitting(pmd_t pmd)
 static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 			      pmd_t *pmdp, pmd_t entry)
 {
-	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INV) && MACHINE_HAS_EDAT1)
+	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INVALID) && MACHINE_HAS_EDAT1)
 		pmd_val(entry) |= _SEGMENT_ENTRY_CO;
 	*pmdp = entry;
 }
@@ -1391,7 +1406,7 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 
 static inline pmd_t pmd_wrprotect(pmd_t pmd)
 {
-	pmd_val(pmd) |= _SEGMENT_ENTRY_RO;
+	pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
 	return pmd;
 }
 
@@ -1547,7 +1562,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 {
 	pte_t pte;
 	offset &= __SWP_OFFSET_MASK;
-	pte_val(pte) = _PAGE_TYPE_SWAP | ((type & 0x1f) << 2) |
+	pte_val(pte) = _PAGE_INVALID | _PAGE_TYPE | ((type & 0x1f) << 2) |
 		((offset & 1UL) << 7) | ((offset & ~1UL) << 11);
 	return pte;
 }
@@ -1570,7 +1585,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 
 #define pgoff_to_pte(__off) \
 	((pte_t) { ((((__off) & 0x7f) << 1) + (((__off) >> 7) << 12)) \
-		   | _PAGE_TYPE_FILE })
+		   | _PAGE_INVALID | _PAGE_PROTECT })
 
 #endif /* !__ASSEMBLY__ */
 
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index b0e6435..0eb3750 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -43,6 +43,7 @@ extern void execve_tail(void);
 #ifndef CONFIG_64BIT
 
 #define TASK_SIZE		(1UL << 31)
+#define TASK_MAX_SIZE		(1UL << 31)
 #define TASK_UNMAPPED_BASE	(1UL << 30)
 
 #else /* CONFIG_64BIT */
@@ -51,6 +52,7 @@ extern void execve_tail(void);
 #define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \
 					(1UL << 30) : (1UL << 41))
 #define TASK_SIZE		TASK_SIZE_OF(current)
+#define TASK_MAX_SIZE		(1UL << 53)
 
 #endif /* CONFIG_64BIT */
 
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index 06a1361..7dc7f9c 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -56,5 +56,6 @@ bool sclp_has_linemode(void);
 bool sclp_has_vt220(void);
 int sclp_pci_configure(u32 fid);
 int sclp_pci_deconfigure(u32 fid);
+int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
 
 #endif /* _ASM_S390_SCLP_H */
diff --git a/arch/s390/include/asm/serial.h b/arch/s390/include/asm/serial.h
new file mode 100644
index 0000000..5b3e48e
--- /dev/null
+++ b/arch/s390/include/asm/serial.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_S390_SERIAL_H
+#define _ASM_S390_SERIAL_H
+
+#define BASE_BAUD 0
+
+#endif /* _ASM_S390_SERIAL_H */
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index d8f3556..c84f33d 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -16,6 +16,7 @@
 #include <asm/os_info.h>
 #include <asm/elf.h>
 #include <asm/ipl.h>
+#include <asm/sclp.h>
 
 #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
@@ -64,22 +65,46 @@ static ssize_t copy_page_real(void *buf, void *src, size_t csize)
 }
 
 /*
- * Copy one page from "oldmem"
+ * Pointer to ELF header in new kernel
+ */
+static void *elfcorehdr_newmem;
+
+/*
+ * Copy one page from zfcpdump "oldmem"
+ *
+ * For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise
+ * real memory copy is used.
+ */
+static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
+					 unsigned long src, int userbuf)
+{
+	int rc;
+
+	if (src < ZFCPDUMP_HSA_SIZE) {
+		rc = memcpy_hsa(buf, src, csize, userbuf);
+	} else {
+		if (userbuf)
+			rc = copy_to_user_real((void __force __user *) buf,
+					       (void *) src, csize);
+		else
+			rc = memcpy_real(buf, (void *) src, csize);
+	}
+	return rc ? rc : csize;
+}
+
+/*
+ * Copy one page from kdump "oldmem"
  *
  * For the kdump reserved memory this functions performs a swap operation:
  *  - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
  *  - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
  */
-ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
-			 size_t csize, unsigned long offset, int userbuf)
+static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,
+				      unsigned long src, int userbuf)
+
 {
-	unsigned long src;
 	int rc;
 
-	if (!csize)
-		return 0;
-
-	src = (pfn << PAGE_SHIFT) + offset;
 	if (src < OLDMEM_SIZE)
 		src += OLDMEM_BASE;
 	else if (src > OLDMEM_BASE &&
@@ -90,7 +115,88 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
 				       (void *) src, csize);
 	else
 		rc = copy_page_real(buf, (void *) src, csize);
-	return (rc == 0) ? csize : rc;
+	return (rc == 0) ? rc : csize;
+}
+
+/*
+ * Copy one page from "oldmem"
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
+			 unsigned long offset, int userbuf)
+{
+	unsigned long src;
+
+	if (!csize)
+		return 0;
+	src = (pfn << PAGE_SHIFT) + offset;
+	if (OLDMEM_BASE)
+		return copy_oldmem_page_kdump(buf, csize, src, userbuf);
+	else
+		return copy_oldmem_page_zfcpdump(buf, csize, src, userbuf);
+}
+
+/*
+ * Remap "oldmem" for kdump
+ *
+ * For the kdump reserved memory this functions performs a swap operation:
+ * [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
+ */
+static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
+					unsigned long from, unsigned long pfn,
+					unsigned long size, pgprot_t prot)
+{
+	unsigned long size_old;
+	int rc;
+
+	if (pfn < OLDMEM_SIZE >> PAGE_SHIFT) {
+		size_old = min(size, OLDMEM_SIZE - (pfn << PAGE_SHIFT));
+		rc = remap_pfn_range(vma, from,
+				     pfn + (OLDMEM_BASE >> PAGE_SHIFT),
+				     size_old, prot);
+		if (rc || size == size_old)
+			return rc;
+		size -= size_old;
+		from += size_old;
+		pfn += size_old >> PAGE_SHIFT;
+	}
+	return remap_pfn_range(vma, from, pfn, size, prot);
+}
+
+/*
+ * Remap "oldmem" for zfcpdump
+ *
+ * We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below
+ * ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function.
+ */
+static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
+					   unsigned long from,
+					   unsigned long pfn,
+					   unsigned long size, pgprot_t prot)
+{
+	unsigned long size_hsa;
+
+	if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) {
+		size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT));
+		if (size == size_hsa)
+			return 0;
+		size -= size_hsa;
+		from += size_hsa;
+		pfn += size_hsa >> PAGE_SHIFT;
+	}
+	return remap_pfn_range(vma, from, pfn, size, prot);
+}
+
+/*
+ * Remap "oldmem" for kdump or zfcpdump
+ */
+int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
+			   unsigned long pfn, unsigned long size, pgprot_t prot)
+{
+	if (OLDMEM_BASE)
+		return remap_oldmem_pfn_range_kdump(vma, from, pfn, size, prot);
+	else
+		return remap_oldmem_pfn_range_zfcpdump(vma, from, pfn, size,
+						       prot);
 }
 
 /*
@@ -101,11 +207,21 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
 	unsigned long copied = 0;
 	int rc;
 
-	if ((unsigned long) src < OLDMEM_SIZE) {
-		copied = min(count, OLDMEM_SIZE - (unsigned long) src);
-		rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
-		if (rc)
-			return rc;
+	if (OLDMEM_BASE) {
+		if ((unsigned long) src < OLDMEM_SIZE) {
+			copied = min(count, OLDMEM_SIZE - (unsigned long) src);
+			rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
+			if (rc)
+				return rc;
+		}
+	} else {
+		if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) {
+			copied = min(count,
+				     ZFCPDUMP_HSA_SIZE - (unsigned long) src);
+			rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);
+			if (rc)
+				return rc;
+		}
 	}
 	return memcpy_real(dest + copied, src + copied, count - copied);
 }
@@ -368,14 +484,6 @@ static int get_mem_chunk_cnt(void)
 }
 
 /*
- * Relocate pointer in order to allow vmcore code access the data
- */
-static inline unsigned long relocate(unsigned long addr)
-{
-	return OLDMEM_BASE + addr;
-}
-
-/*
  * Initialize ELF loads (new kernel)
  */
 static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
@@ -426,7 +534,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
 	ptr = nt_vmcoreinfo(ptr);
 	memset(phdr, 0, sizeof(*phdr));
 	phdr->p_type = PT_NOTE;
-	phdr->p_offset = relocate(notes_offset);
+	phdr->p_offset = notes_offset;
 	phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
 	phdr->p_memsz = phdr->p_filesz;
 	return ptr;
@@ -435,7 +543,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
 /*
  * Create ELF core header (new kernel)
  */
-static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
+int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
 {
 	Elf64_Phdr *phdr_notes, *phdr_loads;
 	int mem_chunk_cnt;
@@ -443,6 +551,12 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
 	u32 alloc_size;
 	u64 hdr_off;
 
+	/* If we are not in kdump or zfcpdump mode return */
+	if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP)
+		return 0;
+	/* If elfcorehdr= has been passed via cmdline, we use that one */
+	if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
+		return 0;
 	mem_chunk_cnt = get_mem_chunk_cnt();
 
 	alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
@@ -460,27 +574,52 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
 	ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
 	/* Init loads */
 	hdr_off = PTR_DIFF(ptr, hdr);
-	loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
-	*elfcorebuf_sz = hdr_off;
-	*elfcorebuf = (void *) relocate((unsigned long) hdr);
-	BUG_ON(*elfcorebuf_sz > alloc_size);
+	loads_init(phdr_loads, hdr_off);
+	*addr = (unsigned long long) hdr;
+	elfcorehdr_newmem = hdr;
+	*size = (unsigned long long) hdr_off;
+	BUG_ON(elfcorehdr_size > alloc_size);
+	return 0;
 }
 
 /*
- * Create kdump ELF core header in new kernel, if it has not been passed via
- * the "elfcorehdr" kernel parameter
+ * Free ELF core header (new kernel)
  */
-static int setup_kdump_elfcorehdr(void)
+void elfcorehdr_free(unsigned long long addr)
 {
-	size_t elfcorebuf_sz;
-	char *elfcorebuf;
+	if (!elfcorehdr_newmem)
+		return;
+	kfree((void *)(unsigned long)addr);
+}
 
-	if (!OLDMEM_BASE || is_kdump_kernel())
-		return -EINVAL;
-	s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
-	elfcorehdr_addr = (unsigned long long) elfcorebuf;
-	elfcorehdr_size = elfcorebuf_sz;
-	return 0;
+/*
+ * Read from ELF header
+ */
+ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
+{
+	void *src = (void *)(unsigned long)*ppos;
+
+	src = elfcorehdr_newmem ? src : src - OLDMEM_BASE;
+	memcpy(buf, src, count);
+	*ppos += count;
+	return count;
 }
 
-subsys_initcall(setup_kdump_elfcorehdr);
+/*
+ * Read from ELF notes data
+ */
+ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
+{
+	void *src = (void *)(unsigned long)*ppos;
+	int rc;
+
+	if (elfcorehdr_newmem) {
+		memcpy(buf, src, count);
+	} else {
+		rc = copy_from_oldmem(buf, src, count);
+		if (rc)
+			return rc;
+	}
+	*ppos += count;
+	return count;
+}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index be7a408..5ca70b4 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -18,6 +18,7 @@
 #include <asm/unistd.h>
 #include <asm/page.h>
 #include <asm/sigp.h>
+#include <asm/irq.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 4
@@ -435,6 +436,11 @@ io_skip:
 io_loop:
 	l	%r1,BASED(.Ldo_IRQ)
 	lr	%r2,%r11		# pass pointer to pt_regs
+	lhi	%r3,IO_INTERRUPT
+	tm	__PT_INT_CODE+8(%r11),0x80	# adapter interrupt ?
+	jz	io_call
+	lhi	%r3,THIN_INTERRUPT
+io_call:
 	basr	%r14,%r1		# call do_IRQ
 	tm	__LC_MACHINE_FLAGS+2,0x10	# MACHINE_FLAG_LPAR
 	jz	io_return
@@ -584,9 +590,10 @@ ext_skip:
 	mvc	__PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR
 	mvc	__PT_INT_PARM(4,%r11),__LC_EXT_PARAMS
 	TRACE_IRQS_OFF
+	l	%r1,BASED(.Ldo_IRQ)
 	lr	%r2,%r11		# pass pointer to pt_regs
-	l	%r1,BASED(.Ldo_extint)
-	basr	%r14,%r1		# call do_extint
+	lhi	%r3,EXT_INTERRUPT
+	basr	%r14,%r1		# call do_IRQ
 	j	io_return
 
 /*
@@ -902,7 +909,6 @@ cleanup_idle_wait:
 .Ldo_machine_check:	.long	s390_do_machine_check
 .Lhandle_mcck:		.long	s390_handle_mcck
 .Ldo_IRQ:		.long	do_IRQ
-.Ldo_extint:		.long	do_extint
 .Ldo_signal:		.long	do_signal
 .Ldo_notify_resume:	.long	do_notify_resume
 .Ldo_per_trap:		.long	do_per_trap
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 1c039d0..980c7aa 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -19,6 +19,7 @@
 #include <asm/unistd.h>
 #include <asm/page.h>
 #include <asm/sigp.h>
+#include <asm/irq.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -468,6 +469,11 @@ io_skip:
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 io_loop:
 	lgr	%r2,%r11		# pass pointer to pt_regs
+	lghi	%r3,IO_INTERRUPT
+	tm	__PT_INT_CODE+8(%r11),0x80	# adapter interrupt ?
+	jz	io_call
+	lghi	%r3,THIN_INTERRUPT
+io_call:
 	brasl	%r14,do_IRQ
 	tm	__LC_MACHINE_FLAGS+6,0x10	# MACHINE_FLAG_LPAR
 	jz	io_return
@@ -623,7 +629,8 @@ ext_skip:
 	TRACE_IRQS_OFF
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 	lgr	%r2,%r11		# pass pointer to pt_regs
-	brasl	%r14,do_extint
+	lghi	%r3,EXT_INTERRUPT
+	brasl	%r14,do_IRQ
 	j	io_return
 
 /*
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 54b0995..b34ba0e 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -22,6 +22,7 @@
 #include <asm/cputime.h>
 #include <asm/lowcore.h>
 #include <asm/irq.h>
+#include <asm/hw_irq.h>
 #include "entry.h"
 
 DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
@@ -42,9 +43,10 @@ struct irq_class {
  * Since the external and I/O interrupt fields are already sums we would end
  * up with having a sum which accounts each interrupt twice.
  */
-static const struct irq_class irqclass_main_desc[NR_IRQS] = {
-	[EXTERNAL_INTERRUPT] = {.name = "EXT"},
-	[IO_INTERRUPT]	     = {.name = "I/O"}
+static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
+	[EXT_INTERRUPT]  = {.name = "EXT"},
+	[IO_INTERRUPT]	 = {.name = "I/O"},
+	[THIN_INTERRUPT] = {.name = "AIO"},
 };
 
 /*
@@ -86,6 +88,28 @@ static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
 	[CPU_RST]    = {.name = "RST", .desc = "[CPU] CPU Restart"},
 };
 
+void __init init_IRQ(void)
+{
+	irq_reserve_irqs(0, THIN_INTERRUPT);
+	init_cio_interrupts();
+	init_airq_interrupts();
+	init_ext_interrupts();
+}
+
+void do_IRQ(struct pt_regs *regs, int irq)
+{
+	struct pt_regs *old_regs;
+
+	old_regs = set_irq_regs(regs);
+	irq_enter();
+	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
+		/* Serve timer interrupts first. */
+		clock_comparator_work();
+	generic_handle_irq(irq);
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
 /*
  * show_interrupts is needed by /proc/interrupts.
  */
@@ -100,27 +124,36 @@ int show_interrupts(struct seq_file *p, void *v)
 		for_each_online_cpu(cpu)
 			seq_printf(p, "CPU%d       ", cpu);
 		seq_putc(p, '\n');
+		goto out;
 	}
 	if (irq < NR_IRQS) {
+		if (irq >= NR_IRQS_BASE)
+			goto out;
 		seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
 		for_each_online_cpu(cpu)
-			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
 		seq_putc(p, '\n');
-		goto skip_arch_irqs;
+		goto out;
 	}
 	for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
 		seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
 		for_each_online_cpu(cpu)
-			seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]);
+			seq_printf(p, "%10u ",
+				   per_cpu(irq_stat, cpu).irqs[irq]);
 		if (irqclass_sub_desc[irq].desc)
 			seq_printf(p, "  %s", irqclass_sub_desc[irq].desc);
 		seq_putc(p, '\n');
 	}
-skip_arch_irqs:
+out:
 	put_online_cpus();
 	return 0;
 }
 
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+	return 0;
+}
+
 /*
  * Switch to the asynchronous interrupt stack for softirq execution.
  */
@@ -159,14 +192,6 @@ asmlinkage void do_softirq(void)
 	local_irq_restore(flags);
 }
 
-#ifdef CONFIG_PROC_FS
-void init_irq_proc(void)
-{
-	if (proc_mkdir("irq", NULL))
-		create_prof_cpu_mask();
-}
-#endif
-
 /*
  * ext_int_hash[index] is the list head for all external interrupts that hash
  * to this index.
@@ -183,14 +208,6 @@ struct ext_int_info {
 /* ext_int_hash_lock protects the handler lists for external interrupts */
 DEFINE_SPINLOCK(ext_int_hash_lock);
 
-static void __init init_external_interrupts(void)
-{
-	int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
-		INIT_LIST_HEAD(&ext_int_hash[idx]);
-}
-
 static inline int ext_hash(u16 code)
 {
 	return (code + (code >> 9)) & 0xff;
@@ -234,20 +251,13 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
 }
 EXPORT_SYMBOL(unregister_external_interrupt);
 
-void __irq_entry do_extint(struct pt_regs *regs)
+static irqreturn_t do_ext_interrupt(int irq, void *dummy)
 {
+	struct pt_regs *regs = get_irq_regs();
 	struct ext_code ext_code;
-	struct pt_regs *old_regs;
 	struct ext_int_info *p;
 	int index;
 
-	old_regs = set_irq_regs(regs);
-	irq_enter();
-	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) {
-		/* Serve timer interrupts first. */
-		clock_comparator_work();
-	}
-	kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL);
 	ext_code = *(struct ext_code *) &regs->int_code;
 	if (ext_code.code != 0x1004)
 		__get_cpu_var(s390_idle).nohz_delay = 1;
@@ -259,13 +269,25 @@ void __irq_entry do_extint(struct pt_regs *regs)
 			p->handler(ext_code, regs->int_parm,
 				   regs->int_parm_long);
 	rcu_read_unlock();
-	irq_exit();
-	set_irq_regs(old_regs);
+
+	return IRQ_HANDLED;
 }
 
-void __init init_IRQ(void)
+static struct irqaction external_interrupt = {
+	.name	 = "EXT",
+	.handler = do_ext_interrupt,
+};
+
+void __init init_ext_interrupts(void)
 {
-	init_external_interrupts();
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
+		INIT_LIST_HEAD(&ext_int_hash[idx]);
+
+	irq_set_chip_and_handler(EXT_INTERRUPT,
+				 &dummy_irq_chip, handle_percpu_irq);
+	setup_irq(EXT_INTERRUPT, &external_interrupt);
 }
 
 static DEFINE_SPINLOCK(sc_irq_lock);
@@ -313,69 +335,3 @@ void measurement_alert_subclass_unregister(void)
 	spin_unlock(&ma_subclass_lock);
 }
 EXPORT_SYMBOL(measurement_alert_subclass_unregister);
-
-#ifdef CONFIG_SMP
-void synchronize_irq(unsigned int irq)
-{
-	/*
-	 * Not needed, the handler is protected by a lock and IRQs that occur
-	 * after the handler is deleted are just NOPs.
-	 */
-}
-EXPORT_SYMBOL_GPL(synchronize_irq);
-#endif
-
-#ifndef CONFIG_PCI
-
-/* Only PCI devices have dynamically-defined IRQ handlers */
-
-int request_irq(unsigned int irq, irq_handler_t handler,
-		unsigned long irqflags, const char *devname, void *dev_id)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	WARN_ON(1);
-}
-EXPORT_SYMBOL_GPL(free_irq);
-
-void enable_irq(unsigned int irq)
-{
-	WARN_ON(1);
-}
-EXPORT_SYMBOL_GPL(enable_irq);
-
-void disable_irq(unsigned int irq)
-{
-	WARN_ON(1);
-}
-EXPORT_SYMBOL_GPL(disable_irq);
-
-#endif /* !CONFIG_PCI */
-
-void disable_irq_nosync(unsigned int irq)
-{
-	disable_irq(irq);
-}
-EXPORT_SYMBOL_GPL(disable_irq_nosync);
-
-unsigned long probe_irq_on(void)
-{
-	return 0;
-}
-EXPORT_SYMBOL_GPL(probe_irq_on);
-
-int probe_irq_off(unsigned long val)
-{
-	return 0;
-}
-EXPORT_SYMBOL_GPL(probe_irq_off);
-
-unsigned int probe_irq_mask(unsigned long val)
-{
-	return val;
-}
-EXPORT_SYMBOL_GPL(probe_irq_mask);
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 504175e..c4c0338 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -214,10 +214,7 @@ static int notrace s390_revalidate_registers(struct mci *mci)
 			: "0", "cc");
 #endif
 	/* Revalidate clock comparator register */
-	if (S390_lowcore.clock_comparator == -1)
-		set_clock_comparator(S390_lowcore.mcck_clock);
-	else
-		set_clock_comparator(S390_lowcore.clock_comparator);
+	set_clock_comparator(S390_lowcore.clock_comparator);
 	/* Check if old PSW is valid */
 	if (!mci->wp)
 		/*
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c
index a6fc037..500aa10 100644
--- a/arch/s390/kernel/perf_event.c
+++ b/arch/s390/kernel/perf_event.c
@@ -52,12 +52,13 @@ static struct kvm_s390_sie_block *sie_block(struct pt_regs *regs)
 
 static bool is_in_guest(struct pt_regs *regs)
 {
-	unsigned long ip = instruction_pointer(regs);
-
 	if (user_mode(regs))
 		return false;
-
-	return ip == (unsigned long) &sie_exit;
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+	return instruction_pointer(regs) == (unsigned long) &sie_exit;
+#else
+	return false;
+#endif
 }
 
 static unsigned long guest_is_user_mode(struct pt_regs *regs)
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index e9fadb0..2bc0803 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -1299,7 +1299,7 @@ int regs_query_register_offset(const char *name)
 
 	if (!name || *name != 'r')
 		return -EINVAL;
-	if (strict_strtoul(name + 1, 10, &offset))
+	if (kstrtoul(name + 1, 10, &offset))
 		return -EINVAL;
 	if (offset >= NUM_GPRS)
 		return -EINVAL;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 497451e..aeed8a6 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -994,6 +994,7 @@ static void __init setup_hwcaps(void)
 		strcpy(elf_platform, "z196");
 		break;
 	case 0x2827:
+	case 0x2828:
 		strcpy(elf_platform, "zEC12");
 		break;
 	}
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index d777628..05d75c4 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -63,7 +63,7 @@ static int __init vdso_setup(char *s)
 	else if (strncmp(s, "off", 4) == 0)
 		vdso_enabled = 0;
 	else {
-		rc = strict_strtoul(s, 0, &val);
+		rc = kstrtoul(s, 0, &val);
 		vdso_enabled = rc ? 0 : !!val;
 	}
 	return !rc;
@@ -113,11 +113,11 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
 
 	clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY,
 		    PAGE_SIZE << SEGMENT_ORDER);
-	clear_table((unsigned long *) page_table, _PAGE_TYPE_EMPTY,
+	clear_table((unsigned long *) page_table, _PAGE_INVALID,
 		    256*sizeof(unsigned long));
 
 	*(unsigned long *) segment_table = _SEGMENT_ENTRY + page_table;
-	*(unsigned long *) page_table = _PAGE_RO + page_frame;
+	*(unsigned long *) page_table = _PAGE_PROTECT + page_frame;
 
 	psal = (u32 *) (page_table + 256*sizeof(unsigned long));
 	aste = psal + 32;
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 3074475..3a74d8a 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -119,12 +119,21 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
 	 * The layout is as follows:
 	 * - gpr 2 contains the subchannel id (passed as addr)
 	 * - gpr 3 contains the virtqueue index (passed as datamatch)
+	 * - gpr 4 contains the index on the bus (optionally)
 	 */
-	ret = kvm_io_bus_write(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
-				vcpu->run->s.regs.gprs[2],
-				8, &vcpu->run->s.regs.gprs[3]);
+	ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
+				      vcpu->run->s.regs.gprs[2],
+				      8, &vcpu->run->s.regs.gprs[3],
+				      vcpu->run->s.regs.gprs[4]);
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
-	/* kvm_io_bus_write returns -EOPNOTSUPP if it found no match. */
+
+	/*
+	 * Return cookie in gpr 2, but don't overwrite the register if the
+	 * diagnose will be handled by userspace.
+	 */
+	if (ret != -EOPNOTSUPP)
+		vcpu->run->s.regs.gprs[2] = ret;
+	/* kvm_io_bus_write_cookie returns -EOPNOTSUPP if it found no match. */
 	return ret < 0 ? ret : 0;
 }
 
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
index 302e0e5..99d789e 100644
--- a/arch/s390/kvm/gaccess.h
+++ b/arch/s390/kvm/gaccess.h
@@ -42,9 +42,11 @@ static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu,
 ({								\
 	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
 	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\
-	int __ret = PTR_RET((void __force *)__uptr);		\
+	int __ret;						\
 								\
-	if (!__ret) {						\
+	if (IS_ERR((void __force *)__uptr)) {			\
+		__ret = PTR_ERR((void __force *)__uptr);	\
+	} else {						\
 		BUG_ON((unsigned long)__uptr & __mask);		\
 		__ret = get_user(x, __uptr);			\
 	}							\
@@ -55,9 +57,11 @@ static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu,
 ({								\
 	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
 	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\
-	int __ret = PTR_RET((void __force *)__uptr);		\
+	int __ret;						\
 								\
-	if (!__ret) {						\
+	if (IS_ERR((void __force *)__uptr)) {			\
+		__ret = PTR_ERR((void __force *)__uptr);	\
+	} else {						\
 		BUG_ON((unsigned long)__uptr & __mask);		\
 		__ret = put_user(x, __uptr);			\
 	}							\
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ba694d2..ac8e667 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -28,6 +28,7 @@
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
 #include <asm/switch_to.h>
+#include <asm/facility.h>
 #include <asm/sclp.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
@@ -84,9 +85,15 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
-static unsigned long long *facilities;
+unsigned long *vfacilities;
 static struct gmap_notifier gmap_notifier;
 
+/* test availability of vfacility */
+static inline int test_vfacility(unsigned long nr)
+{
+	return __test_facility(nr, (void *) vfacilities);
+}
+
 /* Section: not file related */
 int kvm_arch_hardware_enable(void *garbage)
 {
@@ -387,7 +394,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	vcpu->arch.sie_block->ecb   = 6;
 	vcpu->arch.sie_block->ecb2  = 8;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
-	vcpu->arch.sie_block->fac   = (int) (long) facilities;
+	vcpu->arch.sie_block->fac   = (int) (long) vfacilities;
 	hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
 		     (unsigned long) vcpu);
@@ -1056,6 +1063,10 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 	return 0;
 }
 
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
 /* Section: memory related */
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   struct kvm_memory_slot *memslot,
@@ -1122,20 +1133,20 @@ static int __init kvm_s390_init(void)
 	 * to hold the maximum amount of facilities. On the other hand, we
 	 * only set facilities that are known to work in KVM.
 	 */
-	facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
-	if (!facilities) {
+	vfacilities = (unsigned long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
+	if (!vfacilities) {
 		kvm_exit();
 		return -ENOMEM;
 	}
-	memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
-	facilities[0] &= 0xff82fff3f47c0000ULL;
-	facilities[1] &= 0x001c000000000000ULL;
+	memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16);
+	vfacilities[0] &= 0xff82fff3f47c0000UL;
+	vfacilities[1] &= 0x001c000000000000UL;
 	return 0;
 }
 
 static void __exit kvm_s390_exit(void)
 {
-	free_page((unsigned long) facilities);
+	free_page((unsigned long) vfacilities);
 	kvm_exit();
 }
 
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 028ca9f..dc99f1c 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -24,6 +24,9 @@
 
 typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
 
+/* declare vfacilities extern */
+extern unsigned long *vfacilities;
+
 /* negativ values are error codes, positive values for internal conditions */
 #define SIE_INTERCEPT_RERUNVCPU		(1<<0)
 #define SIE_INTERCEPT_UCONTROL		(1<<1)
@@ -112,6 +115,13 @@ static inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu)
 	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
 }
 
+/* Set the condition code in the guest program status word */
+static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
+{
+	vcpu->arch.sie_block->gpsw.mask &= ~(3UL << 44);
+	vcpu->arch.sie_block->gpsw.mask |= cc << 44;
+}
+
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
 void kvm_s390_tasklet(unsigned long parm);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 0da3e6e..8f8d8ee 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -163,8 +163,7 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
 	kfree(inti);
 no_interrupt:
 	/* Set condition code and we're done. */
-	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
-	vcpu->arch.sie_block->gpsw.mask |= (cc & 3ul) << 44;
+	kvm_s390_set_psw_cc(vcpu, cc);
 	return 0;
 }
 
@@ -219,15 +218,13 @@ static int handle_io_inst(struct kvm_vcpu *vcpu)
 		 * Set condition code 3 to stop the guest from issueing channel
 		 * I/O instructions.
 		 */
-		vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
-		vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
+		kvm_s390_set_psw_cc(vcpu, 3);
 		return 0;
 	}
 }
 
 static int handle_stfl(struct kvm_vcpu *vcpu)
 {
-	unsigned int facility_list;
 	int rc;
 
 	vcpu->stat.instruction_stfl++;
@@ -235,15 +232,13 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
 	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
 		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-	/* only pass the facility bits, which we can handle */
-	facility_list = S390_lowcore.stfl_fac_list & 0xff82fff3;
-
 	rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
-			   &facility_list, sizeof(facility_list));
+			   vfacilities, 4);
 	if (rc)
 		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-	VCPU_EVENT(vcpu, 5, "store facility list value %x", facility_list);
-	trace_kvm_s390_handle_stfl(vcpu, facility_list);
+	VCPU_EVENT(vcpu, 5, "store facility list value %x",
+		   *(unsigned int *) vfacilities);
+	trace_kvm_s390_handle_stfl(vcpu, *(unsigned int *) vfacilities);
 	return 0;
 }
 
@@ -386,7 +381,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
 	if (fc > 3) {
-		vcpu->arch.sie_block->gpsw.mask |= 3ul << 44;	  /* cc 3 */
+		kvm_s390_set_psw_cc(vcpu, 3);
 		return 0;
 	}
 
@@ -396,7 +391,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 
 	if (fc == 0) {
 		vcpu->run->s.regs.gprs[0] = 3 << 28;
-		vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);  /* cc 0 */
+		kvm_s390_set_psw_cc(vcpu, 0);
 		return 0;
 	}
 
@@ -430,12 +425,11 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 	}
 	trace_kvm_s390_handle_stsi(vcpu, fc, sel1, sel2, operand2);
 	free_page(mem);
-	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+	kvm_s390_set_psw_cc(vcpu, 0);
 	vcpu->run->s.regs.gprs[0] = 0;
 	return 0;
 out_no_data:
-	/* condition code 3 */
-	vcpu->arch.sie_block->gpsw.mask |= 3ul << 44;
+	kvm_s390_set_psw_cc(vcpu, 3);
 out_exception:
 	free_page(mem);
 	return rc;
@@ -493,12 +487,12 @@ static int handle_epsw(struct kvm_vcpu *vcpu)
 	kvm_s390_get_regs_rre(vcpu, &reg1, &reg2);
 
 	/* This basically extracts the mask half of the psw. */
-	vcpu->run->s.regs.gprs[reg1] &= 0xffffffff00000000;
+	vcpu->run->s.regs.gprs[reg1] &= 0xffffffff00000000UL;
 	vcpu->run->s.regs.gprs[reg1] |= vcpu->arch.sie_block->gpsw.mask >> 32;
 	if (reg2) {
-		vcpu->run->s.regs.gprs[reg2] &= 0xffffffff00000000;
+		vcpu->run->s.regs.gprs[reg2] &= 0xffffffff00000000UL;
 		vcpu->run->s.regs.gprs[reg2] |=
-			vcpu->arch.sie_block->gpsw.mask & 0x00000000ffffffff;
+			vcpu->arch.sie_block->gpsw.mask & 0x00000000ffffffffUL;
 	}
 	return 0;
 }
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 50ea137..1694d73 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -86,28 +86,28 @@ static unsigned long follow_table(struct mm_struct *mm,
 	switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
 	case _ASCE_TYPE_REGION1:
 		table = table + ((address >> 53) & 0x7ff);
-		if (unlikely(*table & _REGION_ENTRY_INV))
+		if (unlikely(*table & _REGION_ENTRY_INVALID))
 			return -0x39UL;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		/* fallthrough */
 	case _ASCE_TYPE_REGION2:
 		table = table + ((address >> 42) & 0x7ff);
-		if (unlikely(*table & _REGION_ENTRY_INV))
+		if (unlikely(*table & _REGION_ENTRY_INVALID))
 			return -0x3aUL;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		/* fallthrough */
 	case _ASCE_TYPE_REGION3:
 		table = table + ((address >> 31) & 0x7ff);
-		if (unlikely(*table & _REGION_ENTRY_INV))
+		if (unlikely(*table & _REGION_ENTRY_INVALID))
 			return -0x3bUL;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		/* fallthrough */
 	case _ASCE_TYPE_SEGMENT:
 		table = table + ((address >> 20) & 0x7ff);
-		if (unlikely(*table & _SEGMENT_ENTRY_INV))
+		if (unlikely(*table & _SEGMENT_ENTRY_INVALID))
 			return -0x10UL;
 		if (unlikely(*table & _SEGMENT_ENTRY_LARGE)) {
-			if (write && (*table & _SEGMENT_ENTRY_RO))
+			if (write && (*table & _SEGMENT_ENTRY_PROTECT))
 				return -0x04UL;
 			return (*table & _SEGMENT_ENTRY_ORIGIN_LARGE) +
 				(address & ~_SEGMENT_ENTRY_ORIGIN_LARGE);
@@ -117,7 +117,7 @@ static unsigned long follow_table(struct mm_struct *mm,
 	table = table + ((address >> 12) & 0xff);
 	if (unlikely(*table & _PAGE_INVALID))
 		return -0x11UL;
-	if (write && (*table & _PAGE_RO))
+	if (write && (*table & _PAGE_PROTECT))
 		return -0x04UL;
 	return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
 }
@@ -130,13 +130,13 @@ static unsigned long follow_table(struct mm_struct *mm,
 	unsigned long *table = (unsigned long *)__pa(mm->pgd);
 
 	table = table + ((address >> 20) & 0x7ff);
-	if (unlikely(*table & _SEGMENT_ENTRY_INV))
+	if (unlikely(*table & _SEGMENT_ENTRY_INVALID))
 		return -0x10UL;
 	table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
 	table = table + ((address >> 12) & 0xff);
 	if (unlikely(*table & _PAGE_INVALID))
 		return -0x11UL;
-	if (write && (*table & _PAGE_RO))
+	if (write && (*table & _PAGE_PROTECT))
 		return -0x04UL;
 	return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
 }
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index 3ad65b0..46d517c 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -53,7 +53,7 @@ static void print_prot(struct seq_file *m, unsigned int pr, int level)
 		seq_printf(m, "I\n");
 		return;
 	}
-	seq_printf(m, "%s", pr & _PAGE_RO ? "RO " : "RW ");
+	seq_printf(m, "%s", pr & _PAGE_PROTECT ? "RO " : "RW ");
 	seq_printf(m, "%s", pr & _PAGE_CO ? "CO " : "   ");
 	seq_putc(m, '\n');
 }
@@ -105,12 +105,12 @@ static void note_page(struct seq_file *m, struct pg_state *st,
 }
 
 /*
- * The actual page table walker functions. In order to keep the implementation
- * of print_prot() short, we only check and pass _PAGE_INVALID and _PAGE_RO
- * flags to note_page() if a region, segment or page table entry is invalid or
- * read-only.
- * After all it's just a hint that the current level being walked contains an
- * invalid or read-only entry.
+ * The actual page table walker functions. In order to keep the
+ * implementation of print_prot() short, we only check and pass
+ * _PAGE_INVALID and _PAGE_PROTECT flags to note_page() if a region,
+ * segment or page table entry is invalid or read-only.
+ * After all it's just a hint that the current level being walked
+ * contains an invalid or read-only entry.
  */
 static void walk_pte_level(struct seq_file *m, struct pg_state *st,
 			   pmd_t *pmd, unsigned long addr)
@@ -122,14 +122,14 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st,
 	for (i = 0; i < PTRS_PER_PTE && addr < max_addr; i++) {
 		st->current_address = addr;
 		pte = pte_offset_kernel(pmd, addr);
-		prot = pte_val(*pte) & (_PAGE_RO | _PAGE_INVALID);
+		prot = pte_val(*pte) & (_PAGE_PROTECT | _PAGE_INVALID);
 		note_page(m, st, prot, 4);
 		addr += PAGE_SIZE;
 	}
 }
 
 #ifdef CONFIG_64BIT
-#define _PMD_PROT_MASK (_SEGMENT_ENTRY_RO | _SEGMENT_ENTRY_CO)
+#define _PMD_PROT_MASK (_SEGMENT_ENTRY_PROTECT | _SEGMENT_ENTRY_CO)
 #else
 #define _PMD_PROT_MASK 0
 #endif
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index f00aefb..35b81d6 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -302,6 +302,8 @@ static inline int do_exception(struct pt_regs *regs, int access)
 	address = trans_exc_code & __FAIL_ADDR_MASK;
 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 	flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 	if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
 		flags |= FAULT_FLAG_WRITE;
 	down_read(&mm->mmap_sem);
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index 1f5315d1..5d758db 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -24,7 +24,7 @@ static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
 	pte_t *ptep, pte;
 	struct page *page;
 
-	mask = (write ? _PAGE_RO : 0) | _PAGE_INVALID | _PAGE_SPECIAL;
+	mask = (write ? _PAGE_PROTECT : 0) | _PAGE_INVALID | _PAGE_SPECIAL;
 
 	ptep = ((pte_t *) pmd_deref(pmd)) + pte_index(addr);
 	do {
@@ -55,8 +55,8 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
 	struct page *head, *page, *tail;
 	int refs;
 
-	result = write ? 0 : _SEGMENT_ENTRY_RO;
-	mask = result | _SEGMENT_ENTRY_INV;
+	result = write ? 0 : _SEGMENT_ENTRY_PROTECT;
+	mask = result | _SEGMENT_ENTRY_INVALID;
 	if ((pmd_val(pmd) & mask) != result)
 		return 0;
 	VM_BUG_ON(!pfn_valid(pmd_val(pmd) >> PAGE_SHIFT));
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 121089d..bcdb99e 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -8,21 +8,107 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 
+static inline pmd_t __pte_to_pmd(pte_t pte)
+{
+	int none, prot;
+	pmd_t pmd;
+
+	/*
+	 * Convert encoding	  pte bits	  pmd bits
+	 *			.IR.....wdtp	..R...I.....
+	 * empty		.10.....0000 -> ..0...1.....
+	 * prot-none, clean	.10.....0001 -> ..1...1.....
+	 * prot-none, dirty	.10.....0101 -> ..1...1.....
+	 * read-only, clean	.01.....0001 -> ..1...0.....
+	 * read-only, dirty	.01.....0101 -> ..1...0.....
+	 * read-write, clean	.01.....1001 -> ..0...0.....
+	 * read-write, dirty	.00.....1101 -> ..0...0.....
+	 * Huge ptes are dirty by definition, a clean pte is made dirty
+	 * by the conversion.
+	 */
+	if (pte_present(pte)) {
+		pmd_val(pmd) = pte_val(pte) & PAGE_MASK;
+		if (pte_val(pte) & _PAGE_INVALID)
+			pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
+		none = (pte_val(pte) & _PAGE_PRESENT) &&
+			(pte_val(pte) & _PAGE_INVALID);
+		prot = (pte_val(pte) & _PAGE_PROTECT);
+		if (prot || none)
+			pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+	} else
+		pmd_val(pmd) = _SEGMENT_ENTRY_INVALID;
+	return pmd;
+}
+
+static inline pte_t __pmd_to_pte(pmd_t pmd)
+{
+	pte_t pte;
+
+	/*
+	 * Convert encoding	  pmd bits	  pte bits
+	 *			..R...I.....	.IR.....wdtp
+	 * empty		..0...1..... -> .10.....0000
+	 * prot-none, young	..1...1..... -> .10.....0101
+	 * read-only, young	..1...0..... -> .01.....0101
+	 * read-write, young	..0...0..... -> .00.....1101
+	 * Huge ptes are dirty by definition
+	 */
+	if (pmd_present(pmd)) {
+		pte_val(pte) = _PAGE_PRESENT | _PAGE_LARGE | _PAGE_DIRTY |
+			(pmd_val(pmd) & PAGE_MASK);
+		if (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID)
+			pte_val(pte) |= _PAGE_INVALID;
+		else {
+			if (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT)
+				pte_val(pte) |= _PAGE_PROTECT;
+			else
+				pte_val(pte) |= _PAGE_WRITE;
+		}
+	} else
+		pte_val(pte) = _PAGE_INVALID;
+	return pte;
+}
 
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-				   pte_t *pteptr, pte_t pteval)
+		     pte_t *ptep, pte_t pte)
 {
-	pmd_t *pmdp = (pmd_t *) pteptr;
-	unsigned long mask;
+	pmd_t pmd;
 
+	pmd = __pte_to_pmd(pte);
 	if (!MACHINE_HAS_HPAGE) {
-		pteptr = (pte_t *) pte_page(pteval)[1].index;
-		mask = pte_val(pteval) &
-				(_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
-		pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
+		pmd_val(pmd) &= ~_SEGMENT_ENTRY_ORIGIN;
+		pmd_val(pmd) |= pte_page(pte)[1].index;
+	} else
+		pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO;
+	*(pmd_t *) ptep = pmd;
+}
+
+pte_t huge_ptep_get(pte_t *ptep)
+{
+	unsigned long origin;
+	pmd_t pmd;
+
+	pmd = *(pmd_t *) ptep;
+	if (!MACHINE_HAS_HPAGE && pmd_present(pmd)) {
+		origin = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
+		pmd_val(pmd) &= ~_SEGMENT_ENTRY_ORIGIN;
+		pmd_val(pmd) |= *(unsigned long *) origin;
 	}
+	return __pmd_to_pte(pmd);
+}
 
-	pmd_val(*pmdp) = pte_val(pteval);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+			      unsigned long addr, pte_t *ptep)
+{
+	pmd_t *pmdp = (pmd_t *) ptep;
+	pte_t pte = huge_ptep_get(ptep);
+
+	if (MACHINE_HAS_IDTE)
+		__pmd_idte(addr, pmdp);
+	else
+		__pmd_csp(pmdp);
+	pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
+	return pte;
 }
 
 int arch_prepare_hugepage(struct page *page)
@@ -58,7 +144,7 @@ void arch_release_hugepage(struct page *page)
 	ptep = (pte_t *) page[1].index;
 	if (!ptep)
 		return;
-	clear_table((unsigned long *) ptep, _PAGE_TYPE_EMPTY,
+	clear_table((unsigned long *) ptep, _PAGE_INVALID,
 		    PTRS_PER_PTE * sizeof(pte_t));
 	page_table_free(&init_mm, (unsigned long *) ptep);
 	page[1].index = 0;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index ce36ea8..ad446b0 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -69,6 +69,7 @@ static void __init setup_zero_pages(void)
 		order = 2;
 		break;
 	case 0x2827:	/* zEC12 */
+	case 0x2828:	/* zEC12 */
 	default:
 		order = 5;
 		break;
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 80adfbf..9903974 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -118,7 +118,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
 		pte = pte_offset_kernel(pmd, address);
 		if (!enable) {
 			__ptep_ipte(address, pte);
-			pte_val(*pte) = _PAGE_TYPE_EMPTY;
+			pte_val(*pte) = _PAGE_INVALID;
 			continue;
 		}
 		pte_val(*pte) = __pa(address);
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index a8154a1..e249803 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -161,7 +161,7 @@ static int gmap_unlink_segment(struct gmap *gmap, unsigned long *table)
 	struct gmap_rmap *rmap;
 	struct page *page;
 
-	if (*table & _SEGMENT_ENTRY_INV)
+	if (*table & _SEGMENT_ENTRY_INVALID)
 		return 0;
 	page = pfn_to_page(*table >> PAGE_SHIFT);
 	mp = (struct gmap_pgtable *) page->index;
@@ -172,7 +172,7 @@ static int gmap_unlink_segment(struct gmap *gmap, unsigned long *table)
 		kfree(rmap);
 		break;
 	}
-	*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+	*table = mp->vmaddr | _SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_PROTECT;
 	return 1;
 }
 
@@ -258,7 +258,7 @@ static int gmap_alloc_table(struct gmap *gmap,
 		return -ENOMEM;
 	new = (unsigned long *) page_to_phys(page);
 	crst_table_init(new, init);
-	if (*table & _REGION_ENTRY_INV) {
+	if (*table & _REGION_ENTRY_INVALID) {
 		list_add(&page->lru, &gmap->crst_list);
 		*table = (unsigned long) new | _REGION_ENTRY_LENGTH |
 			(*table & _REGION_ENTRY_TYPE_MASK);
@@ -292,22 +292,22 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
 	for (off = 0; off < len; off += PMD_SIZE) {
 		/* Walk the guest addr space page table */
 		table = gmap->table + (((to + off) >> 53) & 0x7ff);
-		if (*table & _REGION_ENTRY_INV)
+		if (*table & _REGION_ENTRY_INVALID)
 			goto out;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + (((to + off) >> 42) & 0x7ff);
-		if (*table & _REGION_ENTRY_INV)
+		if (*table & _REGION_ENTRY_INVALID)
 			goto out;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + (((to + off) >> 31) & 0x7ff);
-		if (*table & _REGION_ENTRY_INV)
+		if (*table & _REGION_ENTRY_INVALID)
 			goto out;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + (((to + off) >> 20) & 0x7ff);
 
 		/* Clear segment table entry in guest address space. */
 		flush |= gmap_unlink_segment(gmap, table);
-		*table = _SEGMENT_ENTRY_INV;
+		*table = _SEGMENT_ENTRY_INVALID;
 	}
 out:
 	spin_unlock(&gmap->mm->page_table_lock);
@@ -335,7 +335,7 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,
 
 	if ((from | to | len) & (PMD_SIZE - 1))
 		return -EINVAL;
-	if (len == 0 || from + len > PGDIR_SIZE ||
+	if (len == 0 || from + len > TASK_MAX_SIZE ||
 	    from + len < from || to + len < to)
 		return -EINVAL;
 
@@ -345,17 +345,17 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,
 	for (off = 0; off < len; off += PMD_SIZE) {
 		/* Walk the gmap address space page table */
 		table = gmap->table + (((to + off) >> 53) & 0x7ff);
-		if ((*table & _REGION_ENTRY_INV) &&
+		if ((*table & _REGION_ENTRY_INVALID) &&
 		    gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY))
 			goto out_unmap;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + (((to + off) >> 42) & 0x7ff);
-		if ((*table & _REGION_ENTRY_INV) &&
+		if ((*table & _REGION_ENTRY_INVALID) &&
 		    gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY))
 			goto out_unmap;
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + (((to + off) >> 31) & 0x7ff);
-		if ((*table & _REGION_ENTRY_INV) &&
+		if ((*table & _REGION_ENTRY_INVALID) &&
 		    gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY))
 			goto out_unmap;
 		table = (unsigned long *) (*table & _REGION_ENTRY_ORIGIN);
@@ -363,7 +363,8 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,
 
 		/* Store 'from' address in an invalid segment table entry. */
 		flush |= gmap_unlink_segment(gmap, table);
-		*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
+		*table =  (from + off) | (_SEGMENT_ENTRY_INVALID |
+					  _SEGMENT_ENTRY_PROTECT);
 	}
 	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
@@ -384,15 +385,15 @@ static unsigned long *gmap_table_walk(unsigned long address, struct gmap *gmap)
 	unsigned long *table;
 
 	table = gmap->table + ((address >> 53) & 0x7ff);
-	if (unlikely(*table & _REGION_ENTRY_INV))
+	if (unlikely(*table & _REGION_ENTRY_INVALID))
 		return ERR_PTR(-EFAULT);
 	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 	table = table + ((address >> 42) & 0x7ff);
-	if (unlikely(*table & _REGION_ENTRY_INV))
+	if (unlikely(*table & _REGION_ENTRY_INVALID))
 		return ERR_PTR(-EFAULT);
 	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 	table = table + ((address >> 31) & 0x7ff);
-	if (unlikely(*table & _REGION_ENTRY_INV))
+	if (unlikely(*table & _REGION_ENTRY_INVALID))
 		return ERR_PTR(-EFAULT);
 	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 	table = table + ((address >> 20) & 0x7ff);
@@ -422,11 +423,11 @@ unsigned long __gmap_translate(unsigned long address, struct gmap *gmap)
 		return PTR_ERR(segment_ptr);
 	/* Convert the gmap address to an mm address. */
 	segment = *segment_ptr;
-	if (!(segment & _SEGMENT_ENTRY_INV)) {
+	if (!(segment & _SEGMENT_ENTRY_INVALID)) {
 		page = pfn_to_page(segment >> PAGE_SHIFT);
 		mp = (struct gmap_pgtable *) page->index;
 		return mp->vmaddr | (address & ~PMD_MASK);
-	} else if (segment & _SEGMENT_ENTRY_RO) {
+	} else if (segment & _SEGMENT_ENTRY_PROTECT) {
 		vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
 		return vmaddr | (address & ~PMD_MASK);
 	}
@@ -517,8 +518,8 @@ static void gmap_disconnect_pgtable(struct mm_struct *mm, unsigned long *table)
 	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
 	mp = (struct gmap_pgtable *) page->index;
 	list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
-		*rmap->entry =
-			_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+		*rmap->entry = mp->vmaddr | (_SEGMENT_ENTRY_INVALID |
+					     _SEGMENT_ENTRY_PROTECT);
 		list_del(&rmap->list);
 		kfree(rmap);
 		flush = 1;
@@ -545,13 +546,13 @@ unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
 	/* Convert the gmap address to an mm address. */
 	while (1) {
 		segment = *segment_ptr;
-		if (!(segment & _SEGMENT_ENTRY_INV)) {
+		if (!(segment & _SEGMENT_ENTRY_INVALID)) {
 			/* Page table is present */
 			page = pfn_to_page(segment >> PAGE_SHIFT);
 			mp = (struct gmap_pgtable *) page->index;
 			return mp->vmaddr | (address & ~PMD_MASK);
 		}
-		if (!(segment & _SEGMENT_ENTRY_RO))
+		if (!(segment & _SEGMENT_ENTRY_PROTECT))
 			/* Nothing mapped in the gmap address space. */
 			break;
 		rc = gmap_connect_pgtable(address, segment, segment_ptr, gmap);
@@ -586,25 +587,25 @@ void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
 	while (address < to) {
 		/* Walk the gmap address space page table */
 		table = gmap->table + ((address >> 53) & 0x7ff);
-		if (unlikely(*table & _REGION_ENTRY_INV)) {
+		if (unlikely(*table & _REGION_ENTRY_INVALID)) {
 			address = (address + PMD_SIZE) & PMD_MASK;
 			continue;
 		}
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + ((address >> 42) & 0x7ff);
-		if (unlikely(*table & _REGION_ENTRY_INV)) {
+		if (unlikely(*table & _REGION_ENTRY_INVALID)) {
 			address = (address + PMD_SIZE) & PMD_MASK;
 			continue;
 		}
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + ((address >> 31) & 0x7ff);
-		if (unlikely(*table & _REGION_ENTRY_INV)) {
+		if (unlikely(*table & _REGION_ENTRY_INVALID)) {
 			address = (address + PMD_SIZE) & PMD_MASK;
 			continue;
 		}
 		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
 		table = table + ((address >> 20) & 0x7ff);
-		if (unlikely(*table & _SEGMENT_ENTRY_INV)) {
+		if (unlikely(*table & _SEGMENT_ENTRY_INVALID)) {
 			address = (address + PMD_SIZE) & PMD_MASK;
 			continue;
 		}
@@ -687,7 +688,7 @@ int gmap_ipte_notify(struct gmap *gmap, unsigned long start, unsigned long len)
 			continue;
 		/* Set notification bit in the pgste of the pte */
 		entry = *ptep;
-		if ((pte_val(entry) & (_PAGE_INVALID | _PAGE_RO)) == 0) {
+		if ((pte_val(entry) & (_PAGE_INVALID | _PAGE_PROTECT)) == 0) {
 			pgste = pgste_get_lock(ptep);
 			pgste_val(pgste) |= PGSTE_IN_BIT;
 			pgste_set_unlock(ptep, pgste);
@@ -731,6 +732,11 @@ void gmap_do_ipte_notify(struct mm_struct *mm, unsigned long addr, pte_t *pte)
 	spin_unlock(&gmap_notifier_lock);
 }
 
+static inline int page_table_with_pgste(struct page *page)
+{
+	return atomic_read(&page->_mapcount) == 0;
+}
+
 static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
 						    unsigned long vmaddr)
 {
@@ -750,9 +756,9 @@ static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
 	mp->vmaddr = vmaddr & PMD_MASK;
 	INIT_LIST_HEAD(&mp->mapper);
 	page->index = (unsigned long) mp;
-	atomic_set(&page->_mapcount, 3);
+	atomic_set(&page->_mapcount, 0);
 	table = (unsigned long *) page_to_phys(page);
-	clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
+	clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
 	clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
 	return table;
 }
@@ -821,6 +827,11 @@ EXPORT_SYMBOL(set_guest_storage_key);
 
 #else /* CONFIG_PGSTE */
 
+static inline int page_table_with_pgste(struct page *page)
+{
+	return 0;
+}
+
 static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
 						    unsigned long vmaddr)
 {
@@ -878,7 +889,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
 		pgtable_page_ctor(page);
 		atomic_set(&page->_mapcount, 1);
 		table = (unsigned long *) page_to_phys(page);
-		clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+		clear_table(table, _PAGE_INVALID, PAGE_SIZE);
 		spin_lock_bh(&mm->context.list_lock);
 		list_add(&page->lru, &mm->context.pgtable_list);
 	} else {
@@ -897,12 +908,12 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
 	struct page *page;
 	unsigned int bit, mask;
 
-	if (mm_has_pgste(mm)) {
+	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+	if (page_table_with_pgste(page)) {
 		gmap_disconnect_pgtable(mm, table);
 		return page_table_free_pgste(table);
 	}
 	/* Free 1K/2K page table fragment of a 4K page */
-	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
 	bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
 	spin_lock_bh(&mm->context.list_lock);
 	if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
@@ -940,14 +951,14 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
 	unsigned int bit, mask;
 
 	mm = tlb->mm;
-	if (mm_has_pgste(mm)) {
+	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+	if (page_table_with_pgste(page)) {
 		gmap_disconnect_pgtable(mm, table);
 		table = (unsigned long *) (__pa(table) | FRAG_MASK);
 		tlb_remove_table(tlb, table);
 		return;
 	}
 	bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
-	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
 	spin_lock_bh(&mm->context.list_lock);
 	if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
 		list_del(&page->lru);
@@ -1033,36 +1044,120 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-void thp_split_vma(struct vm_area_struct *vma)
+static inline void thp_split_vma(struct vm_area_struct *vma)
 {
 	unsigned long addr;
-	struct page *page;
 
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) {
-		page = follow_page(vma, addr, FOLL_SPLIT);
-	}
+	for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE)
+		follow_page(vma, addr, FOLL_SPLIT);
 }
 
-void thp_split_mm(struct mm_struct *mm)
+static inline void thp_split_mm(struct mm_struct *mm)
 {
-	struct vm_area_struct *vma = mm->mmap;
+	struct vm_area_struct *vma;
 
-	while (vma != NULL) {
+	for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
 		thp_split_vma(vma);
 		vma->vm_flags &= ~VM_HUGEPAGE;
 		vma->vm_flags |= VM_NOHUGEPAGE;
-		vma = vma->vm_next;
 	}
+	mm->def_flags |= VM_NOHUGEPAGE;
+}
+#else
+static inline void thp_split_mm(struct mm_struct *mm)
+{
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+static unsigned long page_table_realloc_pmd(struct mmu_gather *tlb,
+				struct mm_struct *mm, pud_t *pud,
+				unsigned long addr, unsigned long end)
+{
+	unsigned long next, *table, *new;
+	struct page *page;
+	pmd_t *pmd;
+
+	pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+again:
+		if (pmd_none_or_clear_bad(pmd))
+			continue;
+		table = (unsigned long *) pmd_deref(*pmd);
+		page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+		if (page_table_with_pgste(page))
+			continue;
+		/* Allocate new page table with pgstes */
+		new = page_table_alloc_pgste(mm, addr);
+		if (!new) {
+			mm->context.has_pgste = 0;
+			continue;
+		}
+		spin_lock(&mm->page_table_lock);
+		if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
+			/* Nuke pmd entry pointing to the "short" page table */
+			pmdp_flush_lazy(mm, addr, pmd);
+			pmd_clear(pmd);
+			/* Copy ptes from old table to new table */
+			memcpy(new, table, PAGE_SIZE/2);
+			clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
+			/* Establish new table */
+			pmd_populate(mm, pmd, (pte_t *) new);
+			/* Free old table with rcu, there might be a walker! */
+			page_table_free_rcu(tlb, table);
+			new = NULL;
+		}
+		spin_unlock(&mm->page_table_lock);
+		if (new) {
+			page_table_free_pgste(new);
+			goto again;
+		}
+	} while (pmd++, addr = next, addr != end);
+
+	return addr;
+}
+
+static unsigned long page_table_realloc_pud(struct mmu_gather *tlb,
+				   struct mm_struct *mm, pgd_t *pgd,
+				   unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+	pud_t *pud;
+
+	pud = pud_offset(pgd, addr);
+	do {
+		next = pud_addr_end(addr, end);
+		if (pud_none_or_clear_bad(pud))
+			continue;
+		next = page_table_realloc_pmd(tlb, mm, pud, addr, next);
+	} while (pud++, addr = next, addr != end);
+
+	return addr;
+}
+
+static void page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
+			       unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+	pgd_t *pgd;
+
+	pgd = pgd_offset(mm, addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (pgd_none_or_clear_bad(pgd))
+			continue;
+		next = page_table_realloc_pud(tlb, mm, pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+}
+
 /*
  * switch on pgstes for its userspace process (for kvm)
  */
 int s390_enable_sie(void)
 {
 	struct task_struct *tsk = current;
-	struct mm_struct *mm, *old_mm;
+	struct mm_struct *mm = tsk->mm;
+	struct mmu_gather tlb;
 
 	/* Do we have switched amode? If no, we cannot do sie */
 	if (s390_user_mode == HOME_SPACE_MODE)
@@ -1072,57 +1167,16 @@ int s390_enable_sie(void)
 	if (mm_has_pgste(tsk->mm))
 		return 0;
 
-	/* lets check if we are allowed to replace the mm */
-	task_lock(tsk);
-	if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
-#ifdef CONFIG_AIO
-	    !hlist_empty(&tsk->mm->ioctx_list) ||
-#endif
-	    tsk->mm != tsk->active_mm) {
-		task_unlock(tsk);
-		return -EINVAL;
-	}
-	task_unlock(tsk);
-
-	/* we copy the mm and let dup_mm create the page tables with_pgstes */
-	tsk->mm->context.alloc_pgste = 1;
-	/* make sure that both mms have a correct rss state */
-	sync_mm_rss(tsk->mm);
-	mm = dup_mm(tsk);
-	tsk->mm->context.alloc_pgste = 0;
-	if (!mm)
-		return -ENOMEM;
-
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	down_write(&mm->mmap_sem);
 	/* split thp mappings and disable thp for future mappings */
 	thp_split_mm(mm);
-	mm->def_flags |= VM_NOHUGEPAGE;
-#endif
-
-	/* Now lets check again if something happened */
-	task_lock(tsk);
-	if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
-#ifdef CONFIG_AIO
-	    !hlist_empty(&tsk->mm->ioctx_list) ||
-#endif
-	    tsk->mm != tsk->active_mm) {
-		mmput(mm);
-		task_unlock(tsk);
-		return -EINVAL;
-	}
-
-	/* ok, we are alone. No ptrace, no threads, etc. */
-	old_mm = tsk->mm;
-	tsk->mm = tsk->active_mm = mm;
-	preempt_disable();
-	update_mm(mm, tsk);
-	atomic_inc(&mm->context.attach_count);
-	atomic_dec(&old_mm->context.attach_count);
-	cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-	preempt_enable();
-	task_unlock(tsk);
-	mmput(old_mm);
-	return 0;
+	/* Reallocate the page tables with pgstes */
+	mm->context.has_pgste = 1;
+	tlb_gather_mmu(&tlb, mm, 0);
+	page_table_realloc(&tlb, mm, 0, TASK_SIZE);
+	tlb_finish_mmu(&tlb, 0, -1);
+	up_write(&mm->mmap_sem);
+	return mm->context.has_pgste ? 0 : -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
 
@@ -1198,9 +1252,9 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 		list_del(lh);
 	}
 	ptep = (pte_t *) pgtable;
-	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	pte_val(*ptep) = _PAGE_INVALID;
 	ptep++;
-	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	pte_val(*ptep) = _PAGE_INVALID;
 	return pgtable;
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 8b268fc..e1299d4 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -69,7 +69,7 @@ static pte_t __ref *vmem_pte_alloc(unsigned long address)
 		pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
 	if (!pte)
 		return NULL;
-	clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY,
+	clear_table((unsigned long *) pte, _PAGE_INVALID,
 		    PTRS_PER_PTE * sizeof(pte_t));
 	return pte;
 }
@@ -101,7 +101,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 		    !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) {
 			pud_val(*pu_dir) = __pa(address) |
 				_REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE |
-				(ro ? _REGION_ENTRY_RO : 0);
+				(ro ? _REGION_ENTRY_PROTECT : 0);
 			address += PUD_SIZE;
 			continue;
 		}
@@ -118,7 +118,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 		    !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
 			pmd_val(*pm_dir) = __pa(address) |
 				_SEGMENT_ENTRY | _SEGMENT_ENTRY_LARGE |
-				(ro ? _SEGMENT_ENTRY_RO : 0);
+				(ro ? _SEGMENT_ENTRY_PROTECT : 0);
 			address += PMD_SIZE;
 			continue;
 		}
@@ -131,7 +131,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 		}
 
 		pt_dir = pte_offset_kernel(pm_dir, address);
-		pte_val(*pt_dir) = __pa(address) | (ro ? _PAGE_RO : 0);
+		pte_val(*pt_dir) = __pa(address) |
+			pgprot_val(ro ? PAGE_KERNEL_RO : PAGE_KERNEL);
 		address += PAGE_SIZE;
 	}
 	ret = 0;
@@ -154,7 +155,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
 	pte_t *pt_dir;
 	pte_t  pte;
 
-	pte_val(pte) = _PAGE_TYPE_EMPTY;
+	pte_val(pte) = _PAGE_INVALID;
 	while (address < end) {
 		pg_dir = pgd_offset_k(address);
 		if (pgd_none(*pg_dir)) {
@@ -255,7 +256,8 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 			new_page =__pa(vmem_alloc_pages(0));
 			if (!new_page)
 				goto out;
-			pte_val(*pt_dir) = __pa(new_page);
+			pte_val(*pt_dir) =
+				__pa(new_page) | pgprot_val(PAGE_KERNEL);
 		}
 		address += PAGE_SIZE;
 	}
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index ffeb17c..930783d 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -440,7 +440,7 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops)
 		switch (id.machine) {
 		case 0x2097: case 0x2098: ops->cpu_type = "s390/z10"; break;
 		case 0x2817: case 0x2818: ops->cpu_type = "s390/z196"; break;
-		case 0x2827:              ops->cpu_type = "s390/zEC12"; break;
+		case 0x2827: case 0x2828: ops->cpu_type = "s390/zEC12"; break;
 		default: return -ENODEV;
 		}
 	}
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
index 086a2e3..a9e1dc4 100644
--- a/arch/s390/pci/Makefile
+++ b/arch/s390/pci/Makefile
@@ -2,5 +2,5 @@
 # Makefile for the s390 PCI subsystem.
 #
 
-obj-$(CONFIG_PCI)	+= pci.o pci_dma.o pci_clp.o pci_msi.o pci_sysfs.o \
+obj-$(CONFIG_PCI)	+= pci.o pci_dma.o pci_clp.o pci_sysfs.o \
 			   pci_event.o pci_debug.o pci_insn.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index e2956ad..d65dc4f 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -42,7 +42,6 @@
 #define	SIC_IRQ_MODE_SINGLE		1
 
 #define ZPCI_NR_DMA_SPACES		1
-#define ZPCI_MSI_VEC_BITS		6
 #define ZPCI_NR_DEVICES			CONFIG_PCI_NR_FUNCTIONS
 
 /* list of all detected zpci devices */
@@ -51,36 +50,23 @@ EXPORT_SYMBOL_GPL(zpci_list);
 DEFINE_MUTEX(zpci_list_lock);
 EXPORT_SYMBOL_GPL(zpci_list_lock);
 
-static struct pci_hp_callback_ops *hotplug_ops;
 
-static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
-static DEFINE_SPINLOCK(zpci_domain_lock);
+static void zpci_enable_irq(struct irq_data *data);
+static void zpci_disable_irq(struct irq_data *data);
 
-struct callback {
-	irq_handler_t	handler;
-	void		*data;
+static struct irq_chip zpci_irq_chip = {
+	.name = "zPCI",
+	.irq_unmask = zpci_enable_irq,
+	.irq_mask = zpci_disable_irq,
 };
 
-struct zdev_irq_map {
-	unsigned long	aibv;		/* AI bit vector */
-	int		msi_vecs;	/* consecutive MSI-vectors used */
-	int		__unused;
-	struct callback	cb[ZPCI_NR_MSI_VECS]; /* callback handler array */
-	spinlock_t	lock;		/* protect callbacks against de-reg */
-};
+static struct pci_hp_callback_ops *hotplug_ops;
 
-struct intr_bucket {
-	/* amap of adapters, one bit per dev, corresponds to one irq nr */
-	unsigned long	*alloc;
-	/* AI summary bit, global page for all devices */
-	unsigned long	*aisb;
-	/* pointer to aibv and callback data in zdev */
-	struct zdev_irq_map *imap[ZPCI_NR_DEVICES];
-	/* protects the whole bucket struct */
-	spinlock_t	lock;
-};
+static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
+static DEFINE_SPINLOCK(zpci_domain_lock);
 
-static struct intr_bucket *bucket;
+static struct airq_iv *zpci_aisb_iv;
+static struct airq_iv *zpci_aibv[ZPCI_NR_DEVICES];
 
 /* Adapter interrupt definitions */
 static void zpci_irq_handler(struct airq_struct *airq);
@@ -96,27 +82,8 @@ static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES);
 struct zpci_iomap_entry *zpci_iomap_start;
 EXPORT_SYMBOL_GPL(zpci_iomap_start);
 
-/* highest irq summary bit */
-static int __read_mostly aisb_max;
-
-static struct kmem_cache *zdev_irq_cache;
 static struct kmem_cache *zdev_fmb_cache;
 
-static inline int irq_to_msi_nr(unsigned int irq)
-{
-	return irq & ZPCI_MSI_MASK;
-}
-
-static inline int irq_to_dev_nr(unsigned int irq)
-{
-	return irq >> ZPCI_MSI_VEC_BITS;
-}
-
-static inline struct zdev_irq_map *get_imap(unsigned int irq)
-{
-	return bucket->imap[irq_to_dev_nr(irq)];
-}
-
 struct zpci_dev *get_zdev(struct pci_dev *pdev)
 {
 	return (struct zpci_dev *) pdev->sysdata;
@@ -160,8 +127,7 @@ int pci_proc_domain(struct pci_bus *bus)
 EXPORT_SYMBOL_GPL(pci_proc_domain);
 
 /* Modify PCI: Register adapter interruptions */
-static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb,
-			      u64 aibv)
+static int zpci_set_airq(struct zpci_dev *zdev)
 {
 	u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT);
 	struct zpci_fib *fib;
@@ -172,14 +138,14 @@ static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb,
 		return -ENOMEM;
 
 	fib->isc = PCI_ISC;
-	fib->noi = zdev->irq_map->msi_vecs;
 	fib->sum = 1;		/* enable summary notifications */
-	fib->aibv = aibv;
-	fib->aibvo = 0;		/* every function has its own page */
-	fib->aisb = (u64) bucket->aisb + aisb / 8;
-	fib->aisbo = aisb & ZPCI_MSI_MASK;
+	fib->noi = airq_iv_end(zdev->aibv);
+	fib->aibv = (unsigned long) zdev->aibv->vector;
+	fib->aibvo = 0;		/* each zdev has its own interrupt vector */
+	fib->aisb = (unsigned long) zpci_aisb_iv->vector + (zdev->aisb/64)*8;
+	fib->aisbo = zdev->aisb & 63;
 
-	rc = s390pci_mod_fc(req, fib);
+	rc = zpci_mod_fc(req, fib);
 	pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi);
 
 	free_page((unsigned long) fib);
@@ -209,7 +175,7 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
 	fib->iota = args->iota;
 	fib->fmb_addr = args->fmb_addr;
 
-	rc = s390pci_mod_fc(req, fib);
+	rc = zpci_mod_fc(req, fib);
 	free_page((unsigned long) fib);
 	return rc;
 }
@@ -234,7 +200,7 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
 }
 
 /* Modify PCI: Unregister adapter interruptions */
-static int zpci_unregister_airq(struct zpci_dev *zdev)
+static int zpci_clear_airq(struct zpci_dev *zdev)
 {
 	struct mod_pci_args args = { 0, 0, 0, 0 };
 
@@ -283,7 +249,7 @@ static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)
 	u64 data;
 	int rc;
 
-	rc = s390pci_load(&data, req, offset);
+	rc = zpci_load(&data, req, offset);
 	if (!rc) {
 		data = data << ((8 - len) * 8);
 		data = le64_to_cpu(data);
@@ -301,25 +267,46 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
 
 	data = cpu_to_le64(data);
 	data = data >> ((8 - len) * 8);
-	rc = s390pci_store(data, req, offset);
+	rc = zpci_store(data, req, offset);
 	return rc;
 }
 
-void enable_irq(unsigned int irq)
+static int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
 {
-	struct msi_desc *msi = irq_get_msi_desc(irq);
+	int offset, pos;
+	u32 mask_bits;
+
+	if (msi->msi_attrib.is_msix) {
+		offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_VECTOR_CTRL;
+		msi->masked = readl(msi->mask_base + offset);
+		writel(flag, msi->mask_base + offset);
+	} else if (msi->msi_attrib.maskbit) {
+		pos = (long) msi->mask_base;
+		pci_read_config_dword(msi->dev, pos, &mask_bits);
+		mask_bits &= ~(mask);
+		mask_bits |= flag & mask;
+		pci_write_config_dword(msi->dev, pos, mask_bits);
+	} else
+		return 0;
+
+	msi->msi_attrib.maskbit = !!flag;
+	return 1;
+}
+
+static void zpci_enable_irq(struct irq_data *data)
+{
+	struct msi_desc *msi = irq_get_msi_desc(data->irq);
 
 	zpci_msi_set_mask_bits(msi, 1, 0);
 }
-EXPORT_SYMBOL_GPL(enable_irq);
 
-void disable_irq(unsigned int irq)
+static void zpci_disable_irq(struct irq_data *data)
 {
-	struct msi_desc *msi = irq_get_msi_desc(irq);
+	struct msi_desc *msi = irq_get_msi_desc(data->irq);
 
 	zpci_msi_set_mask_bits(msi, 1, 1);
 }
-EXPORT_SYMBOL_GPL(disable_irq);
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
@@ -404,152 +391,147 @@ static struct pci_ops pci_root_ops = {
 	.write = pci_write,
 };
 
-/* store the last handled bit to implement fair scheduling of devices */
-static DEFINE_PER_CPU(unsigned long, next_sbit);
-
 static void zpci_irq_handler(struct airq_struct *airq)
 {
-	unsigned long sbit, mbit, last = 0, start = __get_cpu_var(next_sbit);
-	int rescan = 0, max = aisb_max;
-	struct zdev_irq_map *imap;
+	unsigned long si, ai;
+	struct airq_iv *aibv;
+	int irqs_on = 0;
 
 	inc_irq_stat(IRQIO_PCI);
-	sbit = start;
-
-scan:
-	/* find summary_bit */
-	for_each_set_bit_left_cont(sbit, bucket->aisb, max) {
-		clear_bit(63 - (sbit & 63), bucket->aisb + (sbit >> 6));
-		last = sbit;
+	for (si = 0;;) {
+		/* Scan adapter summary indicator bit vector */
+		si = airq_iv_scan(zpci_aisb_iv, si, airq_iv_end(zpci_aisb_iv));
+		if (si == -1UL) {
+			if (irqs_on++)
+				/* End of second scan with interrupts on. */
+				break;
+			/* First scan complete, reenable interrupts. */
+			zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+			si = 0;
+			continue;
+		}
 
-		/* find vector bit */
-		imap = bucket->imap[sbit];
-		for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) {
+		/* Scan the adapter interrupt vector for this device. */
+		aibv = zpci_aibv[si];
+		for (ai = 0;;) {
+			ai = airq_iv_scan(aibv, ai, airq_iv_end(aibv));
+			if (ai == -1UL)
+				break;
 			inc_irq_stat(IRQIO_MSI);
-			clear_bit(63 - mbit, &imap->aibv);
-
-			spin_lock(&imap->lock);
-			if (imap->cb[mbit].handler)
-				imap->cb[mbit].handler(mbit,
-					imap->cb[mbit].data);
-			spin_unlock(&imap->lock);
+			airq_iv_lock(aibv, ai);
+			generic_handle_irq(airq_iv_get_data(aibv, ai));
+			airq_iv_unlock(aibv, ai);
 		}
 	}
-
-	if (rescan)
-		goto out;
-
-	/* scan the skipped bits */
-	if (start > 0) {
-		sbit = 0;
-		max = start;
-		start = 0;
-		goto scan;
-	}
-
-	/* enable interrupts again */
-	set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
-
-	/* check again to not lose initiative */
-	rmb();
-	max = aisb_max;
-	sbit = find_first_bit_left(bucket->aisb, max);
-	if (sbit != max) {
-		rescan++;
-		goto scan;
-	}
-out:
-	/* store next device bit to scan */
-	__get_cpu_var(next_sbit) = (++last >= aisb_max) ? 0 : last;
 }
 
-/* msi_vecs - number of requested interrupts, 0 place function to error state */
-static int zpci_setup_msi(struct pci_dev *pdev, int msi_vecs)
+int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
 	struct zpci_dev *zdev = get_zdev(pdev);
-	unsigned int aisb, msi_nr;
+	unsigned int hwirq, irq, msi_vecs;
+	unsigned long aisb;
 	struct msi_desc *msi;
+	struct msi_msg msg;
 	int rc;
 
-	/* store the number of used MSI vectors */
-	zdev->irq_map->msi_vecs = min(msi_vecs, ZPCI_NR_MSI_VECS);
-
-	spin_lock(&bucket->lock);
-	aisb = find_first_zero_bit(bucket->alloc, PAGE_SIZE);
-	/* alloc map exhausted? */
-	if (aisb == PAGE_SIZE) {
-		spin_unlock(&bucket->lock);
-		return -EIO;
-	}
-	set_bit(aisb, bucket->alloc);
-	spin_unlock(&bucket->lock);
+	pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
+	if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
+		return -EINVAL;
+	msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX);
+	msi_vecs = min_t(unsigned int, msi_vecs, CONFIG_PCI_NR_MSI);
 
+	/* Allocate adapter summary indicator bit */
+	rc = -EIO;
+	aisb = airq_iv_alloc_bit(zpci_aisb_iv);
+	if (aisb == -1UL)
+		goto out;
 	zdev->aisb = aisb;
-	if (aisb + 1 > aisb_max)
-		aisb_max = aisb + 1;
 
-	/* wire up IRQ shortcut pointer */
-	bucket->imap[zdev->aisb] = zdev->irq_map;
-	pr_debug("%s: imap[%u] linked to %p\n", __func__, zdev->aisb, zdev->irq_map);
+	/* Create adapter interrupt vector */
+	rc = -ENOMEM;
+	zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
+	if (!zdev->aibv)
+		goto out_si;
 
-	/* TODO: irq number 0 wont be found if we return less than requested MSIs.
-	 * ignore it for now and fix in common code.
-	 */
-	msi_nr = aisb << ZPCI_MSI_VEC_BITS;
+	/* Wire up shortcut pointer */
+	zpci_aibv[aisb] = zdev->aibv;
 
+	/* Request MSI interrupts */
+	hwirq = 0;
 	list_for_each_entry(msi, &pdev->msi_list, list) {
-		rc = zpci_setup_msi_irq(zdev, msi, msi_nr,
-					  aisb << ZPCI_MSI_VEC_BITS);
+		rc = -EIO;
+		irq = irq_alloc_desc(0);	/* Alloc irq on node 0 */
+		if (irq == NO_IRQ)
+			goto out_msi;
+		rc = irq_set_msi_desc(irq, msi);
 		if (rc)
-			return rc;
-		msi_nr++;
+			goto out_msi;
+		irq_set_chip_and_handler(irq, &zpci_irq_chip,
+					 handle_simple_irq);
+		msg.data = hwirq;
+		msg.address_lo = zdev->msi_addr & 0xffffffff;
+		msg.address_hi = zdev->msi_addr >> 32;
+		write_msi_msg(irq, &msg);
+		airq_iv_set_data(zdev->aibv, hwirq, irq);
+		hwirq++;
 	}
 
-	rc = zpci_register_airq(zdev, aisb, (u64) &zdev->irq_map->aibv);
-	if (rc) {
-		clear_bit(aisb, bucket->alloc);
-		dev_err(&pdev->dev, "register MSI failed with: %d\n", rc);
-		return rc;
+	/* Enable adapter interrupts */
+	rc = zpci_set_airq(zdev);
+	if (rc)
+		goto out_msi;
+
+	return (msi_vecs == nvec) ? 0 : msi_vecs;
+
+out_msi:
+	list_for_each_entry(msi, &pdev->msi_list, list) {
+		if (hwirq-- == 0)
+			break;
+		irq_set_msi_desc(msi->irq, NULL);
+		irq_free_desc(msi->irq);
+		msi->msg.address_lo = 0;
+		msi->msg.address_hi = 0;
+		msi->msg.data = 0;
+		msi->irq = 0;
 	}
-	return (zdev->irq_map->msi_vecs == msi_vecs) ?
-		0 : zdev->irq_map->msi_vecs;
+	zpci_aibv[aisb] = NULL;
+	airq_iv_release(zdev->aibv);
+out_si:
+	airq_iv_free_bit(zpci_aisb_iv, aisb);
+out:
+	dev_err(&pdev->dev, "register MSI failed with: %d\n", rc);
+	return rc;
 }
 
-static void zpci_teardown_msi(struct pci_dev *pdev)
+void arch_teardown_msi_irqs(struct pci_dev *pdev)
 {
 	struct zpci_dev *zdev = get_zdev(pdev);
 	struct msi_desc *msi;
-	int aisb, rc;
+	int rc;
 
-	rc = zpci_unregister_airq(zdev);
+	pr_info("%s: on pdev: %p\n", __func__, pdev);
+
+	/* Disable adapter interrupts */
+	rc = zpci_clear_airq(zdev);
 	if (rc) {
 		dev_err(&pdev->dev, "deregister MSI failed with: %d\n", rc);
 		return;
 	}
 
-	msi = list_first_entry(&pdev->msi_list, struct msi_desc, list);
-	aisb = irq_to_dev_nr(msi->irq);
-
-	list_for_each_entry(msi, &pdev->msi_list, list)
-		zpci_teardown_msi_irq(zdev, msi);
-
-	clear_bit(aisb, bucket->alloc);
-	if (aisb + 1 == aisb_max)
-		aisb_max--;
-}
-
-int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
-{
-	pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
-	if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
-		return -EINVAL;
-	return zpci_setup_msi(pdev, nvec);
-}
+	/* Release MSI interrupts */
+	list_for_each_entry(msi, &pdev->msi_list, list) {
+		zpci_msi_set_mask_bits(msi, 1, 1);
+		irq_set_msi_desc(msi->irq, NULL);
+		irq_free_desc(msi->irq);
+		msi->msg.address_lo = 0;
+		msi->msg.address_hi = 0;
+		msi->msg.data = 0;
+		msi->irq = 0;
+	}
 
-void arch_teardown_msi_irqs(struct pci_dev *pdev)
-{
-	pr_info("%s: on pdev: %p\n", __func__, pdev);
-	zpci_teardown_msi(pdev);
+	zpci_aibv[zdev->aisb] = NULL;
+	airq_iv_release(zdev->aibv);
+	airq_iv_free_bit(zpci_aisb_iv, zdev->aisb);
 }
 
 static void zpci_map_resources(struct zpci_dev *zdev)
@@ -589,24 +571,11 @@ struct zpci_dev *zpci_alloc_device(void)
 
 	/* Alloc memory for our private pci device data */
 	zdev = kzalloc(sizeof(*zdev), GFP_KERNEL);
-	if (!zdev)
-		return ERR_PTR(-ENOMEM);
-
-	/* Alloc aibv & callback space */
-	zdev->irq_map = kmem_cache_zalloc(zdev_irq_cache, GFP_KERNEL);
-	if (!zdev->irq_map)
-		goto error;
-	WARN_ON((u64) zdev->irq_map & 0xff);
-	return zdev;
-
-error:
-	kfree(zdev);
-	return ERR_PTR(-ENOMEM);
+	return zdev ? : ERR_PTR(-ENOMEM);
 }
 
 void zpci_free_device(struct zpci_dev *zdev)
 {
-	kmem_cache_free(zdev_irq_cache, zdev->irq_map);
 	kfree(zdev);
 }
 
@@ -641,110 +610,34 @@ int pcibios_add_platform_entries(struct pci_dev *pdev)
 	return zpci_sysfs_add_device(&pdev->dev);
 }
 
-int zpci_request_irq(unsigned int irq, irq_handler_t handler, void *data)
-{
-	int msi_nr = irq_to_msi_nr(irq);
-	struct zdev_irq_map *imap;
-	struct msi_desc *msi;
-
-	msi = irq_get_msi_desc(irq);
-	if (!msi)
-		return -EIO;
-
-	imap = get_imap(irq);
-	spin_lock_init(&imap->lock);
-
-	pr_debug("%s: register handler for IRQ:MSI %d:%d\n", __func__, irq >> 6, msi_nr);
-	imap->cb[msi_nr].handler = handler;
-	imap->cb[msi_nr].data = data;
-
-	/*
-	 * The generic MSI code returns with the interrupt disabled on the
-	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
-	 * at that level, so we do it here by hand.
-	 */
-	zpci_msi_set_mask_bits(msi, 1, 0);
-	return 0;
-}
-
-void zpci_free_irq(unsigned int irq)
-{
-	struct zdev_irq_map *imap = get_imap(irq);
-	int msi_nr = irq_to_msi_nr(irq);
-	unsigned long flags;
-
-	pr_debug("%s: for irq: %d\n", __func__, irq);
-
-	spin_lock_irqsave(&imap->lock, flags);
-	imap->cb[msi_nr].handler = NULL;
-	imap->cb[msi_nr].data = NULL;
-	spin_unlock_irqrestore(&imap->lock, flags);
-}
-
-int request_irq(unsigned int irq, irq_handler_t handler,
-		unsigned long irqflags, const char *devname, void *dev_id)
-{
-	pr_debug("%s: irq: %d  handler: %p  flags: %lx  dev: %s\n",
-		__func__, irq, handler, irqflags, devname);
-
-	return zpci_request_irq(irq, handler, dev_id);
-}
-EXPORT_SYMBOL_GPL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	zpci_free_irq(irq);
-}
-EXPORT_SYMBOL_GPL(free_irq);
-
 static int __init zpci_irq_init(void)
 {
-	int cpu, rc;
-
-	bucket = kzalloc(sizeof(*bucket), GFP_KERNEL);
-	if (!bucket)
-		return -ENOMEM;
-
-	bucket->aisb = (unsigned long *) get_zeroed_page(GFP_KERNEL);
-	if (!bucket->aisb) {
-		rc = -ENOMEM;
-		goto out_aisb;
-	}
-
-	bucket->alloc = (unsigned long *) get_zeroed_page(GFP_KERNEL);
-	if (!bucket->alloc) {
-		rc = -ENOMEM;
-		goto out_alloc;
-	}
+	int rc;
 
 	rc = register_adapter_interrupt(&zpci_airq);
 	if (rc)
-		goto out_ai;
+		goto out;
 	/* Set summary to 1 to be called every time for the ISC. */
 	*zpci_airq.lsi_ptr = 1;
 
-	for_each_online_cpu(cpu)
-		per_cpu(next_sbit, cpu) = 0;
+	rc = -ENOMEM;
+	zpci_aisb_iv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC);
+	if (!zpci_aisb_iv)
+		goto out_airq;
 
-	spin_lock_init(&bucket->lock);
-	set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+	zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
 	return 0;
 
-out_ai:
-	free_page((unsigned long) bucket->alloc);
-out_alloc:
-	free_page((unsigned long) bucket->aisb);
-out_aisb:
-	kfree(bucket);
+out_airq:
+	unregister_adapter_interrupt(&zpci_airq);
+out:
 	return rc;
 }
 
 static void zpci_irq_exit(void)
 {
-	free_page((unsigned long) bucket->alloc);
-	free_page((unsigned long) bucket->aisb);
+	airq_iv_release(zpci_aisb_iv);
 	unregister_adapter_interrupt(&zpci_airq);
-	kfree(bucket);
 }
 
 static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size,
@@ -967,15 +860,10 @@ static inline int barsize(u8 size)
 
 static int zpci_mem_init(void)
 {
-	zdev_irq_cache = kmem_cache_create("PCI_IRQ_cache", sizeof(struct zdev_irq_map),
-				L1_CACHE_BYTES, SLAB_HWCACHE_ALIGN, NULL);
-	if (!zdev_irq_cache)
-		goto error_zdev;
-
 	zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
 				16, 0, NULL);
 	if (!zdev_fmb_cache)
-		goto error_fmb;
+		goto error_zdev;
 
 	/* TODO: use realloc */
 	zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start),
@@ -986,8 +874,6 @@ static int zpci_mem_init(void)
 
 error_iomap:
 	kmem_cache_destroy(zdev_fmb_cache);
-error_fmb:
-	kmem_cache_destroy(zdev_irq_cache);
 error_zdev:
 	return -ENOMEM;
 }
@@ -995,7 +881,6 @@ error_zdev:
 static void zpci_mem_exit(void)
 {
 	kfree(zpci_iomap_start);
-	kmem_cache_destroy(zdev_irq_cache);
 	kmem_cache_destroy(zdev_fmb_cache);
 }
 
@@ -1044,16 +929,12 @@ static int __init pci_base_init(void)
 
 	rc = zpci_debug_init();
 	if (rc)
-		return rc;
+		goto out;
 
 	rc = zpci_mem_init();
 	if (rc)
 		goto out_mem;
 
-	rc = zpci_msihash_init();
-	if (rc)
-		goto out_hash;
-
 	rc = zpci_irq_init();
 	if (rc)
 		goto out_irq;
@@ -1073,11 +954,10 @@ out_find:
 out_dma:
 	zpci_irq_exit();
 out_irq:
-	zpci_msihash_exit();
-out_hash:
 	zpci_mem_exit();
 out_mem:
 	zpci_debug_exit();
+out:
 	return rc;
 }
 subsys_initcall(pci_base_init);
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index a2343c1..2125310 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -170,8 +170,8 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
 		 */
 		goto no_refresh;
 
-	rc = s390pci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
-				   nr_pages * PAGE_SIZE);
+	rc = zpci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
+				nr_pages * PAGE_SIZE);
 
 no_refresh:
 	spin_unlock_irqrestore(&zdev->dma_table_lock, irq_flags);
diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c
index 22eeb9d..85267c0 100644
--- a/arch/s390/pci/pci_insn.c
+++ b/arch/s390/pci/pci_insn.c
@@ -27,7 +27,7 @@ static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
 	return cc;
 }
 
-int s390pci_mod_fc(u64 req, struct zpci_fib *fib)
+int zpci_mod_fc(u64 req, struct zpci_fib *fib)
 {
 	u8 cc, status;
 
@@ -61,7 +61,7 @@ static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
 	return cc;
 }
 
-int s390pci_refresh_trans(u64 fn, u64 addr, u64 range)
+int zpci_refresh_trans(u64 fn, u64 addr, u64 range)
 {
 	u8 cc, status;
 
@@ -78,7 +78,7 @@ int s390pci_refresh_trans(u64 fn, u64 addr, u64 range)
 }
 
 /* Set Interruption Controls */
-void set_irq_ctrl(u16 ctl, char *unused, u8 isc)
+void zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc)
 {
 	asm volatile (
 		"	.insn	rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
@@ -109,7 +109,7 @@ static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
 	return cc;
 }
 
-int s390pci_load(u64 *data, u64 req, u64 offset)
+int zpci_load(u64 *data, u64 req, u64 offset)
 {
 	u8 status;
 	int cc;
@@ -125,7 +125,7 @@ int s390pci_load(u64 *data, u64 req, u64 offset)
 			    __func__, cc, status, req, offset);
 	return (cc > 0) ? -EIO : cc;
 }
-EXPORT_SYMBOL_GPL(s390pci_load);
+EXPORT_SYMBOL_GPL(zpci_load);
 
 /* PCI Store */
 static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status)
@@ -147,7 +147,7 @@ static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status)
 	return cc;
 }
 
-int s390pci_store(u64 data, u64 req, u64 offset)
+int zpci_store(u64 data, u64 req, u64 offset)
 {
 	u8 status;
 	int cc;
@@ -163,7 +163,7 @@ int s390pci_store(u64 data, u64 req, u64 offset)
 			__func__, cc, status, req, offset);
 	return (cc > 0) ? -EIO : cc;
 }
-EXPORT_SYMBOL_GPL(s390pci_store);
+EXPORT_SYMBOL_GPL(zpci_store);
 
 /* PCI Store Block */
 static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
@@ -183,7 +183,7 @@ static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
 	return cc;
 }
 
-int s390pci_store_block(const u64 *data, u64 req, u64 offset)
+int zpci_store_block(const u64 *data, u64 req, u64 offset)
 {
 	u8 status;
 	int cc;
@@ -199,4 +199,4 @@ int s390pci_store_block(const u64 *data, u64 req, u64 offset)
 			    __func__, cc, status, req, offset);
 	return (cc > 0) ? -EIO : cc;
 }
-EXPORT_SYMBOL_GPL(s390pci_store_block);
+EXPORT_SYMBOL_GPL(zpci_store_block);
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c
deleted file mode 100644
index b097aed..0000000
--- a/arch/s390/pci/pci_msi.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright IBM Corp. 2012
- *
- * Author(s):
- *   Jan Glauber <jang@linux.vnet.ibm.com>
- */
-
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/rculist.h>
-#include <linux/hash.h>
-#include <linux/pci.h>
-#include <linux/msi.h>
-#include <asm/hw_irq.h>
-
-/* mapping of irq numbers to msi_desc */
-static struct hlist_head *msi_hash;
-static const unsigned int msi_hash_bits = 8;
-#define MSI_HASH_BUCKETS (1U << msi_hash_bits)
-#define msi_hashfn(nr)	hash_long(nr, msi_hash_bits)
-
-static DEFINE_SPINLOCK(msi_map_lock);
-
-struct msi_desc *__irq_get_msi_desc(unsigned int irq)
-{
-	struct msi_map *map;
-
-	hlist_for_each_entry_rcu(map,
-			&msi_hash[msi_hashfn(irq)], msi_chain)
-		if (map->irq == irq)
-			return map->msi;
-	return NULL;
-}
-
-int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
-{
-	if (msi->msi_attrib.is_msix) {
-		int offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
-			PCI_MSIX_ENTRY_VECTOR_CTRL;
-		msi->masked = readl(msi->mask_base + offset);
-		writel(flag, msi->mask_base + offset);
-	} else {
-		if (msi->msi_attrib.maskbit) {
-			int pos;
-			u32 mask_bits;
-
-			pos = (long) msi->mask_base;
-			pci_read_config_dword(msi->dev, pos, &mask_bits);
-			mask_bits &= ~(mask);
-			mask_bits |= flag & mask;
-			pci_write_config_dword(msi->dev, pos, mask_bits);
-		} else {
-			return 0;
-		}
-	}
-
-	msi->msi_attrib.maskbit = !!flag;
-	return 1;
-}
-
-int zpci_setup_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi,
-			unsigned int nr, int offset)
-{
-	struct msi_map *map;
-	struct msi_msg msg;
-	int rc;
-
-	map = kmalloc(sizeof(*map), GFP_KERNEL);
-	if (map == NULL)
-		return -ENOMEM;
-
-	map->irq = nr;
-	map->msi = msi;
-	zdev->msi_map[nr & ZPCI_MSI_MASK] = map;
-	INIT_HLIST_NODE(&map->msi_chain);
-
-	pr_debug("%s hashing irq: %u  to bucket nr: %llu\n",
-		__func__, nr, msi_hashfn(nr));
-	hlist_add_head_rcu(&map->msi_chain, &msi_hash[msi_hashfn(nr)]);
-
-	spin_lock(&msi_map_lock);
-	rc = irq_set_msi_desc(nr, msi);
-	if (rc) {
-		spin_unlock(&msi_map_lock);
-		hlist_del_rcu(&map->msi_chain);
-		kfree(map);
-		zdev->msi_map[nr & ZPCI_MSI_MASK] = NULL;
-		return rc;
-	}
-	spin_unlock(&msi_map_lock);
-
-	msg.data = nr - offset;
-	msg.address_lo = zdev->msi_addr & 0xffffffff;
-	msg.address_hi = zdev->msi_addr >> 32;
-	write_msi_msg(nr, &msg);
-	return 0;
-}
-
-void zpci_teardown_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi)
-{
-	int irq = msi->irq & ZPCI_MSI_MASK;
-	struct msi_map *map;
-
-	msi->msg.address_lo = 0;
-	msi->msg.address_hi = 0;
-	msi->msg.data = 0;
-	msi->irq = 0;
-	zpci_msi_set_mask_bits(msi, 1, 1);
-
-	spin_lock(&msi_map_lock);
-	map = zdev->msi_map[irq];
-	hlist_del_rcu(&map->msi_chain);
-	kfree(map);
-	zdev->msi_map[irq] = NULL;
-	spin_unlock(&msi_map_lock);
-}
-
-/*
- * The msi hash table has 256 entries which is good for 4..20
- * devices (a typical device allocates 10 + CPUs MSI's). Maybe make
- * the hash table size adjustable later.
- */
-int __init zpci_msihash_init(void)
-{
-	unsigned int i;
-
-	msi_hash = kmalloc(MSI_HASH_BUCKETS * sizeof(*msi_hash), GFP_KERNEL);
-	if (!msi_hash)
-		return -ENOMEM;
-
-	for (i = 0; i < MSI_HASH_BUCKETS; i++)
-		INIT_HLIST_HEAD(&msi_hash[i]);
-	return 0;
-}
-
-void __init zpci_msihash_exit(void)
-{
-	kfree(msi_hash);
-}
diff --git a/arch/score/Kconfig b/arch/score/Kconfig
index c8def8b..5fc2375 100644
--- a/arch/score/Kconfig
+++ b/arch/score/Kconfig
@@ -87,6 +87,8 @@ config STACKTRACE_SUPPORT
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 config MMU
 	def_bool y
 
diff --git a/arch/score/mm/fault.c b/arch/score/mm/fault.c
index 6b18fb0..52238983 100644
--- a/arch/score/mm/fault.c
+++ b/arch/score/mm/fault.c
@@ -47,6 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
 	struct task_struct *tsk = current;
 	struct mm_struct *mm = tsk->mm;
 	const int field = sizeof(unsigned long) * 2;
+	unsigned long flags = 0;
 	siginfo_t info;
 	int fault;
 
@@ -75,6 +76,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
 	if (in_atomic() || !mm)
 		goto bad_area_nosemaphore;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -95,18 +99,18 @@ good_area:
 	if (write) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
 			goto bad_area;
 	}
 
-survive:
 	/*
 	* If for any reason at all we couldn't handle the fault,
 	* make sure we exit gracefully rather than endlessly redo
 	* the fault.
 	*/
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, flags);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -167,11 +171,6 @@ no_context:
 	*/
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (is_global_init(tsk)) {
-		yield();
-		down_read(&mm->mmap_sem);
-		goto survive;
-	}
 	if (!user_mode(regs))
 		goto no_context;
 	pagefault_out_of_memory();
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 61fade0..bcbb86b 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -30,6 +30,7 @@
 #include <linux/spi/mmc_spi.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/platform_data/gpio_backlight.h>
 #include <linux/sh_eth.h>
 #include <linux/sh_intc.h>
 #include <linux/videodev2.h>
@@ -303,7 +304,7 @@ static struct platform_device usbhs_device = {
 	.resource	= usbhs_resources,
 };
 
-/* LCDC */
+/* LCDC and backlight */
 static const struct fb_videomode ecovec_lcd_modes[] = {
 	{
 		.name		= "Panel",
@@ -334,13 +335,6 @@ static const struct fb_videomode ecovec_dvi_modes[] = {
 	},
 };
 
-static int ecovec24_set_brightness(int brightness)
-{
-	gpio_set_value(GPIO_PTR1, brightness);
-
-	return 0;
-}
-
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.ch[0] = {
 		.interface_type = RGB18,
@@ -350,11 +344,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.width = 152,
 			.height = 91,
 		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = ecovec24_set_brightness,
-		},
 	}
 };
 
@@ -380,6 +369,20 @@ static struct platform_device lcdc_device = {
 	},
 };
 
+static struct gpio_backlight_platform_data gpio_backlight_data = {
+	.fbdev = &lcdc_device.dev,
+	.gpio = GPIO_PTR1,
+	.def_value = 1,
+	.name = "backlight",
+};
+
+static struct platform_device gpio_backlight_device = {
+	.name = "gpio-backlight",
+	.dev = {
+		.platform_data = &gpio_backlight_data,
+	},
+};
+
 /* CEU0 */
 static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
 	.flags = SH_CEU_FLAG_USE_8BIT_BUS,
@@ -1049,6 +1052,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
 	&usb1_common_device,
 	&usbhs_device,
 	&lcdc_device,
+	&gpio_backlight_device,
 	&ceu0_device,
 	&ceu1_device,
 	&keysc_device,
@@ -1239,11 +1243,9 @@ static int __init arch_setup(void)
 
 	gpio_request(GPIO_PTE6, NULL);
 	gpio_request(GPIO_PTU1, NULL);
-	gpio_request(GPIO_PTR1, NULL);
 	gpio_request(GPIO_PTA2, NULL);
 	gpio_direction_input(GPIO_PTE6);
 	gpio_direction_output(GPIO_PTU1, 0);
-	gpio_direction_output(GPIO_PTR1, 0);
 	gpio_direction_output(GPIO_PTA2, 0);
 
 	/* I/O buffer drive ability is high */
@@ -1256,6 +1258,9 @@ static int __init arch_setup(void)
 		lcdc_info.ch[0].lcd_modes		= ecovec_dvi_modes;
 		lcdc_info.ch[0].num_modes		= ARRAY_SIZE(ecovec_dvi_modes);
 
+		/* No backlight */
+		gpio_backlight_data.fbdev = NULL;
+
 		gpio_set_value(GPIO_PTA2, 1);
 		gpio_set_value(GPIO_PTU1, 1);
 	} else {
@@ -1265,8 +1270,6 @@ static int __init arch_setup(void)
 		lcdc_info.ch[0].lcd_modes		= ecovec_lcd_modes;
 		lcdc_info.ch[0].num_modes		= ARRAY_SIZE(ecovec_lcd_modes);
 
-		gpio_set_value(GPIO_PTR1, 1);
-
 		/* FIXME
 		 *
 		 * LCDDON control is needed for Panel,
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
index c620503..355a78a 100644
--- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -276,51 +276,3 @@ void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
 {
 	write_memory_start(sohandle, so);
 }
-
-#define CTRL_CKSW       0x10
-#define CTRL_C10        0x20
-#define CTRL_CPSW       0x80
-#define MAIN_MLED4      0x40
-#define MAIN_MSW        0x80
-
-int kfr2r09_lcd_set_brightness(int brightness)
-{
-	struct i2c_adapter *a;
-	struct i2c_msg msg;
-	unsigned char buf[2];
-	int ret;
-
-	a = i2c_get_adapter(0);
-	if (!a)
-		return -ENODEV;
-
-	buf[0] = 0x00;
-	if (brightness)
-		buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
-	else
-		buf[1] = 0;
-
-	msg.addr = 0x75;
-	msg.buf = buf;
-	msg.len = 2;
-	msg.flags = 0;
-	ret = i2c_transfer(a, &msg, 1);
-	if (ret != 1)
-		return -ENODEV;
-
-	buf[0] = 0x01;
-	if (brightness)
-		buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
-	else
-		buf[1] = 0;
-
-	msg.addr = 0x75;
-	msg.buf = buf;
-	msg.len = 2;
-	msg.flags = 0;
-	ret = i2c_transfer(a, &msg, 1);
-	if (ret != 1)
-		return -ENODEV;
-
-	return 0;
-}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index ab502f12..1df4398 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -21,6 +21,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/i2c.h>
+#include <linux/platform_data/lv5207lp.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/usb/r8a66597.h>
@@ -159,11 +160,6 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
 			.setup_sys = kfr2r09_lcd_setup,
 			.start_transfer = kfr2r09_lcd_start,
 		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = kfr2r09_lcd_set_brightness,
-		},
 		.sys_bus_cfg = {
 			.ldmt2r = 0x07010904,
 			.ldmt3r = 0x14012914,
@@ -195,6 +191,17 @@ static struct platform_device kfr2r09_sh_lcdc_device = {
 	},
 };
 
+static struct lv5207lp_platform_data kfr2r09_backlight_data = {
+	.fbdev = &kfr2r09_sh_lcdc_device.dev,
+	.def_value = 13,
+	.max_value = 13,
+};
+
+static struct i2c_board_info kfr2r09_backlight_board_info = {
+	I2C_BOARD_INFO("lv5207lp", 0x75),
+	.platform_data = &kfr2r09_backlight_data,
+};
+
 static struct r8a66597_platdata kfr2r09_usb0_gadget_data = {
 	.on_chip = 1,
 };
@@ -627,6 +634,8 @@ static int __init kfr2r09_devices_setup(void)
 	gpio_request(GPIO_FN_SDHI0CMD, NULL);
 	gpio_request(GPIO_FN_SDHI0CLK, NULL);
 
+	i2c_register_board_info(0, &kfr2r09_backlight_board_info, 1);
+
 	return platform_add_devices(kfr2r09_devices,
 				    ARRAY_SIZE(kfr2r09_devices));
 }
diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h
index ec9ad59..01a3869 100644
--- a/arch/sh/include/asm/hw_breakpoint.h
+++ b/arch/sh/include/asm/hw_breakpoint.h
@@ -7,6 +7,7 @@
 
 #include <linux/kdebug.h>
 #include <linux/types.h>
+#include <cpu/ubc.h>
 
 struct arch_hw_breakpoint {
 	char		*name; /* Contains name of the symbol to set bkpt */
@@ -15,17 +16,6 @@ struct arch_hw_breakpoint {
 	u16		type;
 };
 
-enum {
-	SH_BREAKPOINT_READ	= (1 << 1),
-	SH_BREAKPOINT_WRITE	= (1 << 2),
-	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
-
-	SH_BREAKPOINT_LEN_1	= (1 << 12),
-	SH_BREAKPOINT_LEN_2	= (1 << 13),
-	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
-	SH_BREAKPOINT_LEN_8	= (1 << 14),
-};
-
 struct sh_ubc {
 	const char	*name;
 	unsigned int	num_events;
diff --git a/arch/sh/include/cpu-common/cpu/ubc.h b/arch/sh/include/cpu-common/cpu/ubc.h
new file mode 100644
index 0000000..b604619
--- /dev/null
+++ b/arch/sh/include/cpu-common/cpu/ubc.h
@@ -0,0 +1,17 @@
+#ifndef __ARCH_SH_CPU_UBC_H__
+#define __ARCH_SH_CPU_UBC_H__
+
+enum {
+	SH_BREAKPOINT_READ	= (1 << 1),
+	SH_BREAKPOINT_WRITE	= (1 << 2),
+	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+	SH_BREAKPOINT_LEN_1	= (1 << 12),
+	SH_BREAKPOINT_LEN_2	= (1 << 13),
+	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+	SH_BREAKPOINT_LEN_8	= (1 << 14),
+};
+
+#define UBC_64BIT	1
+
+#endif /* __ARCH_SH_CPU_UBC_H__ */
diff --git a/arch/sh/include/cpu-sh2a/cpu/ubc.h b/arch/sh/include/cpu-sh2a/cpu/ubc.h
new file mode 100644
index 0000000..3371f90
--- /dev/null
+++ b/arch/sh/include/cpu-sh2a/cpu/ubc.h
@@ -0,0 +1,14 @@
+#ifndef __ARCH_SH_CPU_UBC_H__
+#define __ARCH_SH_CPU_UBC_H__
+
+enum {
+	SH_BREAKPOINT_READ	= (1 << 2),
+	SH_BREAKPOINT_WRITE	= (1 << 3),
+	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+	SH_BREAKPOINT_LEN_1	= (1 << 0),
+	SH_BREAKPOINT_LEN_2	= (1 << 1),
+	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+};
+
+#endif /* __ARCH_SH_CPU_UBC_H__ */
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
index c20c9e5..79f154e 100644
--- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -4,13 +4,11 @@
 #include <video/sh_mobile_lcdc.h>
 
 #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
-int kfr2r09_lcd_set_brightness(int brightness);
 int kfr2r09_lcd_setup(void *sys_ops_handle,
 		      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 void kfr2r09_lcd_start(void *sys_ops_handle,
 		       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 #else
-static int kfr2r09_lcd_set_brightness(int brightness) {}
 static int kfr2r09_lcd_setup(void *sys_ops_handle,
 				struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
 {
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 990195d..92f0da4 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -22,3 +22,4 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7264)	:= pinmux-sh7264.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7269)	:= pinmux-sh7269.o
 
 obj-$(CONFIG_GPIOLIB)			+= $(pinmux-y)
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= ubc.o
diff --git a/arch/sh/kernel/cpu/sh2a/ubc.c b/arch/sh/kernel/cpu/sh2a/ubc.c
new file mode 100644
index 0000000..ef95a9b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/ubc.c
@@ -0,0 +1,154 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/ubc.c
+ *
+ * On-chip UBC support for SH-2A CPUs.
+ *
+ * Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/hw_breakpoint.h>
+
+#define UBC_BAR(idx)	(0xfffc0400 + (0x10 * idx))
+#define UBC_BAMR(idx)	(0xfffc0404 + (0x10 * idx))
+#define UBC_BBR(idx)	(0xfffc04A0 + (0x10 * idx))
+#define UBC_BDR(idx)	(0xfffc0408 + (0x10 * idx))
+#define UBC_BDMR(idx)	(0xfffc040C + (0x10 * idx))
+
+#define UBC_BRCR	0xfffc04C0
+
+/* BBR */
+#define UBC_BBR_UBID	(1 << 13)     /* User Break Interrupt Disable */
+#define UBC_BBR_DBE	(1 << 12)     /* Data Break Enable */
+#define UBC_BBR_CD_C	(1 << 6)      /* C Bus Cycle */
+#define UBC_BBR_CD_I	(2 << 6)      /* I Bus Cycle */
+#define UBC_BBR_ID_I	(1 << 4)      /* Break Condition is instruction fetch cycle */
+#define UBC_BBR_ID_D	(2 << 4)      /* Break Condition is data access cycle */
+#define UBC_BBR_ID_ID	(3 << 4)      /* Break Condition is instruction fetch or data access cycle */
+
+#define UBC_CRR_BIE	(1 << 0)
+
+/* CBR */
+#define UBC_CBR_CE	(1 << 0)
+
+static struct sh_ubc sh2a_ubc;
+
+static void sh2a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
+{
+	__raw_writel(UBC_BBR_DBE | UBC_BBR_CD_C | UBC_BBR_ID_ID |
+		     info->len | info->type, UBC_BBR(idx));
+	__raw_writel(info->address, UBC_BAR(idx));
+}
+
+static void sh2a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
+{
+	__raw_writel(UBC_BBR_UBID, UBC_BBR(idx));
+	__raw_writel(0, UBC_BAR(idx));
+}
+
+static void sh2a_ubc_enable_all(unsigned long mask)
+{
+	int i;
+
+	for (i = 0; i < sh2a_ubc.num_events; i++)
+		if (mask & (1 << i))
+			__raw_writel(__raw_readl(UBC_BBR(i)) & ~UBC_BBR_UBID,
+				     UBC_BBR(i));
+}
+
+static void sh2a_ubc_disable_all(void)
+{
+	int i;
+	
+	for (i = 0; i < sh2a_ubc.num_events; i++)
+		__raw_writel(__raw_readl(UBC_BBR(i)) | UBC_BBR_UBID,
+			     UBC_BBR(i));
+}
+
+static unsigned long sh2a_ubc_active_mask(void)
+{
+	unsigned long active = 0;
+	int i;
+
+	for (i = 0; i < sh2a_ubc.num_events; i++)
+		if (!(__raw_readl(UBC_BBR(i)) & UBC_BBR_UBID))
+			active |= (1 << i);
+
+	return active;
+}
+
+static unsigned long sh2a_ubc_triggered_mask(void)
+{
+	unsigned int ret, mask;
+	
+	mask = 0;
+	ret = __raw_readl(UBC_BRCR);
+	if ((ret & (1 << 15)) || (ret & (1 << 13))) {
+		mask |= (1 << 0); /* Match condition for channel 0 */
+	} else 
+		mask &= ~(1 << 0);
+	
+	if ((ret & (1 << 14)) || (ret & (1 << 12))) {
+		mask |= (1 << 1); /* Match condition for channel 1 */
+	} else 
+		mask &= ~(1 << 1);
+
+	return mask;
+}
+
+static void sh2a_ubc_clear_triggered_mask(unsigned long mask)
+{
+	if (mask & (1 << 0)) /* Channel 0 statisfied break condition */
+		__raw_writel(__raw_readl(UBC_BRCR) &
+			     ~((1 << 15) | (1 << 13)), UBC_BRCR);
+	
+	if (mask & (1 << 1)) /* Channel 1 statisfied break condition */
+		__raw_writel(__raw_readl(UBC_BRCR) &
+			     ~((1 << 14) | (1 << 12)), UBC_BRCR);
+}
+
+static struct sh_ubc sh2a_ubc = {
+	.name			= "SH-2A",
+	.num_events		= 2,
+	.trap_nr		= 0x1e0,
+	.enable			= sh2a_ubc_enable,
+	.disable		= sh2a_ubc_disable,
+	.enable_all		= sh2a_ubc_enable_all,
+	.disable_all		= sh2a_ubc_disable_all,
+	.active_mask		= sh2a_ubc_active_mask,
+	.triggered_mask		= sh2a_ubc_triggered_mask,
+	.clear_triggered_mask	= sh2a_ubc_clear_triggered_mask,
+};
+
+static int __init sh2a_ubc_init(void)
+{
+	struct clk *ubc_iclk = clk_get(NULL, "ubc0");
+	int i;
+
+	/*
+	 * The UBC MSTP bit is optional, as not all platforms will have
+	 * it. Just ignore it if we can't find it.
+	 */
+	if (IS_ERR(ubc_iclk))
+		ubc_iclk = NULL;
+
+	clk_enable(ubc_iclk);
+
+	for (i = 0; i < sh2a_ubc.num_events; i++) {
+		__raw_writel(0, UBC_BAMR(i));
+		__raw_writel(0, UBC_BBR(i));
+	}
+
+	clk_disable(ubc_iclk);
+
+	sh2a_ubc.clk = ubc_iclk;
+
+	return register_sh_ubc(&sh2a_ubc);
+}
+arch_initcall(sh2a_ubc_init);
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
index f917376..ac4922a 100644
--- a/arch/sh/kernel/hw_breakpoint.c
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -113,9 +113,11 @@ static int get_hbp_len(u16 hbp_len)
 	case SH_BREAKPOINT_LEN_4:
 		len_in_bytes = 4;
 		break;
+#ifdef UBC_64BIT
 	case SH_BREAKPOINT_LEN_8:
 		len_in_bytes = 8;
 		break;
+#endif
 	}
 	return len_in_bytes;
 }
@@ -149,9 +151,11 @@ int arch_bp_generic_fields(int sh_len, int sh_type,
 	case SH_BREAKPOINT_LEN_4:
 		*gen_len = HW_BREAKPOINT_LEN_4;
 		break;
+#ifdef UBC_64BIT
 	case SH_BREAKPOINT_LEN_8:
 		*gen_len = HW_BREAKPOINT_LEN_8;
 		break;
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -190,9 +194,11 @@ static int arch_build_bp_info(struct perf_event *bp)
 	case HW_BREAKPOINT_LEN_4:
 		info->len = SH_BREAKPOINT_LEN_4;
 		break;
+#ifdef UBC_64BIT
 	case HW_BREAKPOINT_LEN_8:
 		info->len = SH_BREAKPOINT_LEN_8;
 		break;
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -240,9 +246,11 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 	case SH_BREAKPOINT_LEN_4:
 		align = 3;
 		break;
+#ifdef UBC_64BIT
 	case SH_BREAKPOINT_LEN_8:
 		align = 7;
 		break;
+#endif
 	default:
 		return ret;
 	}
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 174d124..e2062e6 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -374,7 +374,7 @@ asmlinkage void ret_from_kernel_thread(void);
 int copy_thread(unsigned long clone_flags, unsigned long usp,
 		unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs *childregs, *regs = current_pt_regs();
+	struct pt_regs *childregs;
 
 #ifdef CONFIG_SH_FPU
 	/* can't happen for a kernel thread */
@@ -393,7 +393,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	if (unlikely(p->flags & PF_KTHREAD)) {
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->regs[2] = (unsigned long)arg;
-		childregs->regs[3] = (unsigned long)fn;
+		childregs->regs[3] = (unsigned long)usp;
 		childregs->sr = (1 << 30); /* not user_mode */
 		childregs->sr |= SR_FD; /* Invalidate FPU flag */
 		p->thread.pc = (unsigned long) ret_from_kernel_thread;
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 1f49c28..541dc61 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -400,9 +400,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
 	int fault;
-	int write = error_code & FAULT_CODE_WRITE;
-	unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-			      (write ? FAULT_FLAG_WRITE : 0));
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	tsk = current;
 	mm = tsk->mm;
@@ -476,6 +474,11 @@ good_area:
 
 	set_thread_fault_code(error_code);
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+	if (error_code & FAULT_CODE_WRITE)
+		flags |= FAULT_FLAG_WRITE;
+
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index a00cbd3..1570ad2 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -52,7 +52,6 @@ config SPARC32
 
 config SPARC64
 	def_bool 64BIT
-	select ARCH_SUPPORTS_MSI
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_GRAPH_FP_TEST
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
index c7de332..8d28480 100644
--- a/arch/sparc/include/asm/switch_to_64.h
+++ b/arch/sparc/include/asm/switch_to_64.h
@@ -48,8 +48,8 @@ do {	save_and_clear_fpu();						\
 	"wrpr	%%g0, 14, %%pil\n\t"					\
 	"brz,pt %%o7, switch_to_pc\n\t"					\
 	" mov	%%g7, %0\n\t"						\
-	"sethi	%%hi(ret_from_syscall), %%g1\n\t"			\
-	"jmpl	%%g1 + %%lo(ret_from_syscall), %%g0\n\t"		\
+	"sethi	%%hi(ret_from_fork), %%g1\n\t"				\
+	"jmpl	%%g1 + %%lo(ret_from_fork), %%g0\n\t"			\
 	" nop\n\t"							\
 	".globl switch_to_pc\n\t"					\
 	"switch_to_pc:\n\t"						\
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c
index e4de74c..cb5d272 100644
--- a/arch/sparc/kernel/cpumap.c
+++ b/arch/sparc/kernel/cpumap.c
@@ -327,6 +327,7 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
 	case SUN4V_CHIP_NIAGARA3:
 	case SUN4V_CHIP_NIAGARA4:
 	case SUN4V_CHIP_NIAGARA5:
+	case SUN4V_CHIP_SPARC64X:
 		rover_inc_table = niagara_iterate_method;
 		break;
 	default:
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index e2a0300..33c02b1 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -839,7 +839,7 @@ sys_sigreturn:
 	 nop
 
 	call	syscall_trace
-	 nop
+	 mov	1, %o1
 
 1:
 	/* We don't want to muck with user registers like a
diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c
index c875955..53c0a82 100644
--- a/arch/sparc/kernel/kgdb_64.c
+++ b/arch/sparc/kernel/kgdb_64.c
@@ -42,7 +42,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 {
 	struct thread_info *t = task_thread_info(p);
 	extern unsigned int switch_to_pc;
-	extern unsigned int ret_from_syscall;
+	extern unsigned int ret_from_fork;
 	struct reg_window *win;
 	unsigned long pc, cwp;
 	int i;
@@ -66,7 +66,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 		gdb_regs[i] = 0;
 
 	if (t->new_child)
-		pc = (unsigned long) &ret_from_syscall;
+		pc = (unsigned long) &ret_from_fork;
 	else
 		pc = (unsigned long) &switch_to_pc;
 
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index 0746e5e..fde5a41 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -25,11 +25,10 @@ kvmap_itlb:
 	 */
 kvmap_itlb_4v:
 
-kvmap_itlb_nonlinear:
 	/* Catch kernel NULL pointer calls.  */
 	sethi		%hi(PAGE_SIZE), %g5
 	cmp		%g4, %g5
-	bleu,pn		%xcc, kvmap_dtlb_longpath
+	blu,pn		%xcc, kvmap_itlb_longpath
 	 nop
 
 	KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_itlb_load)
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 7ff45e4..a348330 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -1087,7 +1087,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 	audit_syscall_exit(regs);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-		trace_sys_exit(regs, regs->u_regs[UREG_G1]);
+		trace_sys_exit(regs, regs->u_regs[UREG_I0]);
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, 0);
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 1378554..3fdb455 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -499,12 +499,14 @@ static void __init init_sparc64_elf_hwcap(void)
 		    sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
 		    sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
 		    sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
-		    sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
+		    sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
+		    sun4v_chip_type == SUN4V_CHIP_SPARC64X)
 			cap |= HWCAP_SPARC_BLKINIT;
 		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
 		    sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
 		    sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
-		    sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
+		    sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
+		    sun4v_chip_type == SUN4V_CHIP_SPARC64X)
 			cap |= HWCAP_SPARC_N2;
 	}
 
@@ -530,13 +532,15 @@ static void __init init_sparc64_elf_hwcap(void)
 			if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
 			    sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
 			    sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
-			    sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
+			    sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
+			    sun4v_chip_type == SUN4V_CHIP_SPARC64X)
 				cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
 					AV_SPARC_ASI_BLK_INIT |
 					AV_SPARC_POPC);
 			if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
 			    sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
-			    sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
+			    sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
+			    sun4v_chip_type == SUN4V_CHIP_SPARC64X)
 				cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
 					AV_SPARC_FMAF);
 		}
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index 3d0ddbc..7136885 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -169,10 +169,10 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig,
 		new_ka.ka_restorer = restorer;
 		ret = get_user(u_handler, &act->sa_handler);
 		new_ka.sa.sa_handler =  compat_ptr(u_handler);
-		ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
+		ret |= copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
 		sigset_from_compat(&new_ka.sa.sa_mask, &set32);
-		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		ret |= __get_user(u_restorer, &act->sa_restorer);
+		ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		ret |= get_user(u_restorer, &act->sa_restorer);
 		new_ka.sa.sa_restorer = compat_ptr(u_restorer);
                 if (ret)
                 	return -EFAULT;
@@ -183,9 +183,9 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig,
 	if (!ret && oact) {
 		sigset_to_compat(&set32, &old_ka.sa.sa_mask);
 		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
-		ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
-		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
+		ret |= copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
+		ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
 		if (ret)
 			ret = -EFAULT;
         }
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 22a1098..d950197 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -98,8 +98,8 @@ sys_clone:
 	ba,pt	%xcc, sparc_do_fork
 	 add	%sp, PTREGS_OFF, %o2
 
-	.globl	ret_from_syscall
-ret_from_syscall:
+	.globl	ret_from_fork
+ret_from_fork:
 	/* Clear current_thread_info()->new_child. */
 	stb	%g0, [%g6 + TI_NEW_CHILD]
 	call	schedule_tail
@@ -152,7 +152,7 @@ linux_syscall_trace32:
 	srl	%i4, 0, %o4
 	srl	%i1, 0, %o1
 	srl	%i2, 0, %o2
-	ba,pt	%xcc, 2f
+	ba,pt	%xcc, 5f
 	 srl	%i3, 0, %o3
 
 linux_syscall_trace:
@@ -182,13 +182,13 @@ linux_sparc_syscall32:
 	srl	%i1, 0, %o1				! IEU0	Group
 	ldx	[%g6 + TI_FLAGS], %l0		! Load
 
-	srl	%i5, 0, %o5				! IEU1
+	srl	%i3, 0, %o3				! IEU0
 	srl	%i2, 0, %o2				! IEU0	Group
 	andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
 	bne,pn	%icc, linux_syscall_trace32		! CTI
 	 mov	%i0, %l5				! IEU1
-	call	%l7					! CTI	Group brk forced
-	 srl	%i3, 0, %o3				! IEU0
+5:	call	%l7					! CTI	Group brk forced
+	 srl	%i5, 0, %o5				! IEU1
 	ba,a,pt	%xcc, 3f
 
 	/* Linux native system calls enter here... */
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index e98bfda..59dbd46 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -177,8 +177,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
 	unsigned long g2;
 	int from_user = !(regs->psr & PSR_PS);
 	int fault, code;
-	unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-			      (write ? FAULT_FLAG_WRITE : 0));
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	if (text_fault)
 		address = regs->pc;
@@ -235,6 +234,11 @@ good_area:
 			goto bad_area;
 	}
 
+	if (from_user)
+		flags |= FAULT_FLAG_USER;
+	if (write)
+		flags |= FAULT_FLAG_WRITE;
+
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
@@ -383,6 +387,7 @@ static void force_user_fault(unsigned long address, int write)
 	struct vm_area_struct *vma;
 	struct task_struct *tsk = current;
 	struct mm_struct *mm = tsk->mm;
+	unsigned int flags = FAULT_FLAG_USER;
 	int code;
 
 	code = SEGV_MAPERR;
@@ -402,11 +407,12 @@ good_area:
 	if (write) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
-	switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) {
+	switch (handle_mm_fault(mm, vma, address, flags)) {
 	case VM_FAULT_SIGBUS:
 	case VM_FAULT_OOM:
 		goto do_sigbus;
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 5062ff3..2ebec26 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -315,7 +315,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
 			bad_kernel_pc(regs, address);
 			return;
 		}
-	}
+	} else
+		flags |= FAULT_FLAG_USER;
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -418,13 +419,14 @@ good_area:
 		    vma->vm_file != NULL)
 			set_thread_fault_code(fault_code |
 					      FAULT_CODE_BLKCOMMIT);
+
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		/* Allow reads even for write-only mappings */
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
 
-	flags |= ((fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
 	fault = handle_mm_fault(mm, vma, address, flags);
 
 	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 24565a7..cea05f1 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -64,6 +64,9 @@ config HUGETLB_SUPER_PAGES
 	depends on HUGETLB_PAGE && TILEGX
 	def_bool y
 
+config GENERIC_TIME_VSYSCALL
+	def_bool y
+
 # FIXME: tilegx can implement a more efficient rwsem.
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
@@ -112,6 +115,7 @@ config SMP
 config HVC_TILE
 	depends on TTY
 	select HVC_DRIVER
+	select HVC_IRQ if TILEGX
 	def_bool y
 
 config TILEGX
@@ -300,6 +304,8 @@ config PAGE_OFFSET
 
 source "mm/Kconfig"
 
+source "kernel/Kconfig.preempt"
+
 config CMDLINE_BOOL
 	bool "Built-in kernel command line"
 	default n
@@ -380,7 +386,6 @@ config PCI
 	select PCI_DOMAINS
 	select GENERIC_PCI_IOMAP
 	select TILE_GXIO_TRIO if TILEGX
-	select ARCH_SUPPORTS_MSI if TILEGX
 	select PCI_MSI if TILEGX
 	---help---
 	  Enable PCI root complex support, so PCIe endpoint devices can
@@ -396,8 +401,20 @@ config NO_IOMEM
 config NO_IOPORT
 	def_bool !PCI
 
+config TILE_PCI_IO
+	bool "PCI I/O space support"
+	default n
+	depends on PCI
+	depends on TILEGX
+	---help---
+	  Enable PCI I/O space support on TILEGx. Since the PCI I/O space
+	  is used by few modern PCIe endpoint devices, its support is disabled
+	  by default to save the TRIO PIO Region resource for other purposes.
+
 source "drivers/pci/Kconfig"
 
+source "drivers/pci/pcie/Kconfig"
+
 config TILE_USB
 	tristate "Tilera USB host adapter support"
 	default y
diff --git a/arch/tile/Kconfig.debug b/arch/tile/Kconfig.debug
index 9165ea9..b8d69f2 100644
--- a/arch/tile/Kconfig.debug
+++ b/arch/tile/Kconfig.debug
@@ -24,4 +24,12 @@ config DEBUG_EXTRA_FLAGS
 	  size and build time noticeably.  Such flags are often
 	  helpful if the main use of debug info is line number info.
 
+config TILE_HVGLUE_TRACE
+	bool "Provide wrapper functions for hypervisor ABI calls"
+	default n
+	help
+	  Provide wrapper functions for the hypervisor ABI calls
+	  defined in arch/tile/kernel/hvglue.S.  This allows tracing
+	  mechanisms, etc., to have visibility into those calls.
+
 endmenu
diff --git a/arch/tile/gxio/iorpc_mpipe.c b/arch/tile/gxio/iorpc_mpipe.c
index 31b87bf..4f8f3d6 100644
--- a/arch/tile/gxio/iorpc_mpipe.c
+++ b/arch/tile/gxio/iorpc_mpipe.c
@@ -387,6 +387,27 @@ int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac)
 
 EXPORT_SYMBOL(gxio_mpipe_link_close_aux);
 
+struct link_set_attr_aux_param {
+	int mac;
+	uint32_t attr;
+	int64_t val;
+};
+
+int gxio_mpipe_link_set_attr_aux(gxio_mpipe_context_t * context, int mac,
+				 uint32_t attr, int64_t val)
+{
+	struct link_set_attr_aux_param temp;
+	struct link_set_attr_aux_param *params = &temp;
+
+	params->mac = mac;
+	params->attr = attr;
+	params->val = val;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_MPIPE_OP_LINK_SET_ATTR_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_link_set_attr_aux);
 
 struct get_timestamp_aux_param {
 	uint64_t sec;
@@ -454,6 +475,51 @@ int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
 
 EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux);
 
+struct adjust_timestamp_freq_param {
+	int32_t ppb;
+};
+
+int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context,
+				     int32_t ppb)
+{
+	struct adjust_timestamp_freq_param temp;
+	struct adjust_timestamp_freq_param *params = &temp;
+
+	params->ppb = ppb;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params),
+			     GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_freq);
+
+struct config_edma_ring_blks_param {
+	unsigned int ering;
+	unsigned int max_blks;
+	unsigned int min_snf_blks;
+	unsigned int db;
+};
+
+int gxio_mpipe_config_edma_ring_blks(gxio_mpipe_context_t * context,
+				     unsigned int ering, unsigned int max_blks,
+				     unsigned int min_snf_blks, unsigned int db)
+{
+	struct config_edma_ring_blks_param temp;
+	struct config_edma_ring_blks_param *params = &temp;
+
+	params->ering = ering;
+	params->max_blks = max_blks;
+	params->min_snf_blks = min_snf_blks;
+	params->db = db;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params),
+			     GXIO_MPIPE_OP_CONFIG_EDMA_RING_BLKS);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_config_edma_ring_blks);
+
 struct arm_pollfd_param {
 	union iorpc_pollfd pollfd;
 };
diff --git a/arch/tile/gxio/iorpc_mpipe_info.c b/arch/tile/gxio/iorpc_mpipe_info.c
index d0254aa..64883aa 100644
--- a/arch/tile/gxio/iorpc_mpipe_info.c
+++ b/arch/tile/gxio/iorpc_mpipe_info.c
@@ -16,6 +16,24 @@
 #include "gxio/iorpc_mpipe_info.h"
 
 
+struct instance_aux_param {
+	_gxio_mpipe_link_name_t name;
+};
+
+int gxio_mpipe_info_instance_aux(gxio_mpipe_info_context_t * context,
+				 _gxio_mpipe_link_name_t name)
+{
+	struct instance_aux_param temp;
+	struct instance_aux_param *params = &temp;
+
+	params->name = name;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_MPIPE_INFO_OP_INSTANCE_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_info_instance_aux);
+
 struct enumerate_aux_param {
 	_gxio_mpipe_link_name_t name;
 	_gxio_mpipe_link_mac_t mac;
diff --git a/arch/tile/gxio/iorpc_trio.c b/arch/tile/gxio/iorpc_trio.c
index cef4b22..da6e18e 100644
--- a/arch/tile/gxio/iorpc_trio.c
+++ b/arch/tile/gxio/iorpc_trio.c
@@ -61,6 +61,29 @@ int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
 
 EXPORT_SYMBOL(gxio_trio_alloc_memory_maps);
 
+struct alloc_scatter_queues_param {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+};
+
+int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
+				   unsigned int count, unsigned int first,
+				   unsigned int flags)
+{
+	struct alloc_scatter_queues_param temp;
+	struct alloc_scatter_queues_param *params = &temp;
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params),
+			     GXIO_TRIO_OP_ALLOC_SCATTER_QUEUES);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_scatter_queues);
 
 struct alloc_pio_regions_param {
 	unsigned int count;
diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c
index e71c633..5301a9f 100644
--- a/arch/tile/gxio/mpipe.c
+++ b/arch/tile/gxio/mpipe.c
@@ -36,8 +36,14 @@ int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index)
 	int fd;
 	int i;
 
+	if (mpipe_index >= GXIO_MPIPE_INSTANCE_MAX)
+		return -EINVAL;
+
 	snprintf(file, sizeof(file), "mpipe/%d/iorpc", mpipe_index);
 	fd = hv_dev_open((HV_VirtAddr) file, 0);
+
+	context->fd = fd;
+
 	if (fd < 0) {
 		if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
 			return fd;
@@ -45,8 +51,6 @@ int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index)
 			return -ENODEV;
 	}
 
-	context->fd = fd;
-
 	/* Map in the MMIO space. */
 	context->mmio_cfg_base = (void __force *)
 		iorpc_ioremap(fd, HV_MPIPE_CONFIG_MMIO_OFFSET,
@@ -64,12 +68,15 @@ int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index)
 	for (i = 0; i < 8; i++)
 		context->__stacks.stacks[i] = 255;
 
+	context->instance = mpipe_index;
+
 	return 0;
 
       fast_failed:
 	iounmap((void __force __iomem *)(context->mmio_cfg_base));
       cfg_failed:
 	hv_dev_close(context->fd);
+	context->fd = -1;
 	return -ENODEV;
 }
 
@@ -383,7 +390,7 @@ EXPORT_SYMBOL_GPL(gxio_mpipe_iqueue_init);
 
 int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
 			   gxio_mpipe_context_t *context,
-			   unsigned int edma_ring_id,
+			   unsigned int ering,
 			   unsigned int channel,
 			   void *mem, unsigned int mem_size,
 			   unsigned int mem_flags)
@@ -394,7 +401,7 @@ int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
 	/* Offset used to read number of completed commands. */
 	MPIPE_EDMA_POST_REGION_ADDR_t offset;
 
-	int result = gxio_mpipe_init_edma_ring(context, edma_ring_id, channel,
+	int result = gxio_mpipe_init_edma_ring(context, ering, channel,
 					       mem, mem_size, mem_flags);
 	if (result < 0)
 		return result;
@@ -405,7 +412,7 @@ int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
 	offset.region =
 		MPIPE_MMIO_ADDR__REGION_VAL_EDMA -
 		MPIPE_MMIO_ADDR__REGION_VAL_IDMA;
-	offset.ring = edma_ring_id;
+	offset.ring = ering;
 
 	__gxio_dma_queue_init(&equeue->dma_queue,
 			      context->mmio_fast_base + offset.word,
@@ -413,6 +420,9 @@ int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
 	equeue->edescs = mem;
 	equeue->mask_num_entries = num_entries - 1;
 	equeue->log2_num_entries = __builtin_ctz(num_entries);
+	equeue->context = context;
+	equeue->ering = ering;
+	equeue->channel = channel;
 
 	return 0;
 }
@@ -493,6 +503,20 @@ static gxio_mpipe_context_t *_gxio_get_link_context(void)
 	return contextp;
 }
 
+int gxio_mpipe_link_instance(const char *link_name)
+{
+	_gxio_mpipe_link_name_t name;
+	gxio_mpipe_context_t *context = _gxio_get_link_context();
+
+	if (!context)
+		return GXIO_ERR_NO_DEVICE;
+
+	strncpy(name.name, link_name, sizeof(name.name));
+	name.name[GXIO_MPIPE_LINK_NAME_LEN - 1] = '\0';
+
+	return gxio_mpipe_info_instance_aux(context, name);
+}
+
 int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac)
 {
 	int rv;
@@ -543,3 +567,12 @@ int gxio_mpipe_link_close(gxio_mpipe_link_t *link)
 }
 
 EXPORT_SYMBOL_GPL(gxio_mpipe_link_close);
+
+int gxio_mpipe_link_set_attr(gxio_mpipe_link_t *link, uint32_t attr,
+			     int64_t val)
+{
+	return gxio_mpipe_link_set_attr_aux(link->context, link->mac, attr,
+					    val);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_link_set_attr);
diff --git a/arch/tile/include/arch/trio.h b/arch/tile/include/arch/trio.h
index d3000a8..c0ddedc 100644
--- a/arch/tile/include/arch/trio.h
+++ b/arch/tile/include/arch/trio.h
@@ -23,6 +23,45 @@
 #ifndef __ASSEMBLER__
 
 /*
+ * Map SQ Doorbell Format.
+ * This describes the format of the write-only doorbell register that exists
+ * in the last 8-bytes of the MAP_SQ_BASE/LIM range.  This register is only
+ * writable from PCIe space.  Writes to this register will not be written to
+ * Tile memory space and thus no IO VA translation is required if the last
+ * page of the BASE/LIM range is not otherwise written.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * When written with a 1, the associated MAP_SQ region's doorbell
+     * interrupt will be triggered once all previous writes are visible to
+     * Tile software.
+     */
+    uint_reg_t doorbell   : 1;
+    /*
+     * When written with a 1, the descriptor at the head of the associated
+     * MAP_SQ's FIFO will be dequeued.
+     */
+    uint_reg_t pop        : 1;
+    /* Reserved. */
+    uint_reg_t __reserved : 62;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved : 62;
+    uint_reg_t pop        : 1;
+    uint_reg_t doorbell   : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_MAP_SQ_DOORBELL_FMT_t;
+
+
+/*
  * Tile PIO Region Configuration - CFG Address Format.
  * This register describes the address format for PIO accesses when the
  * associated region is setup with TYPE=CFG.
diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h
index 0fc63c4..92ee4c8 100644
--- a/arch/tile/include/asm/cacheflush.h
+++ b/arch/tile/include/asm/cacheflush.h
@@ -75,23 +75,6 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	memcpy((dst), (src), (len))
 
-/*
- * Invalidate a VA range; pads to L2 cacheline boundaries.
- *
- * Note that on TILE64, __inv_buffer() actually flushes modified
- * cache lines in addition to invalidating them, i.e., it's the
- * same as __finv_buffer().
- */
-static inline void __inv_buffer(void *buffer, size_t size)
-{
-	char *next = (char *)((long)buffer & -L2_CACHE_BYTES);
-	char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);
-	while (next < finish) {
-		__insn_inv(next);
-		next += CHIP_INV_STRIDE();
-	}
-}
-
 /* Flush a VA range; pads to L2 cacheline boundaries. */
 static inline void __flush_buffer(void *buffer, size_t size)
 {
@@ -115,13 +98,6 @@ static inline void __finv_buffer(void *buffer, size_t size)
 }
 
 
-/* Invalidate a VA range and wait for it to be complete. */
-static inline void inv_buffer(void *buffer, size_t size)
-{
-	__inv_buffer(buffer, size);
-	mb();
-}
-
 /*
  * Flush a locally-homecached VA range and wait for the evicted
  * cachelines to hit memory.
@@ -142,6 +118,26 @@ static inline void finv_buffer_local(void *buffer, size_t size)
 	mb_incoherent();
 }
 
+#ifdef __tilepro__
+/* Invalidate a VA range; pads to L2 cacheline boundaries. */
+static inline void __inv_buffer(void *buffer, size_t size)
+{
+	char *next = (char *)((long)buffer & -L2_CACHE_BYTES);
+	char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);
+	while (next < finish) {
+		__insn_inv(next);
+		next += CHIP_INV_STRIDE();
+	}
+}
+
+/* Invalidate a VA range and wait for it to be complete. */
+static inline void inv_buffer(void *buffer, size_t size)
+{
+	__inv_buffer(buffer, size);
+	mb();
+}
+#endif
+
 /*
  * Flush and invalidate a VA range that is homed remotely, waiting
  * until the memory controller holds the flushed values.  If "hfh" is
diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h
index 276f067..1da5bfb 100644
--- a/arch/tile/include/asm/cmpxchg.h
+++ b/arch/tile/include/asm/cmpxchg.h
@@ -68,6 +68,12 @@ extern unsigned long __cmpxchg_called_with_bad_pointer(void);
 
 #define tas(ptr) (xchg((ptr), 1))
 
+#define cmpxchg64(ptr, o, n)						\
+({									\
+	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+	cmpxchg((ptr), (o), (n));					\
+})
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_TILE_CMPXCHG_H */
diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h
index f2ff191..6f522d5 100644
--- a/arch/tile/include/asm/dma-mapping.h
+++ b/arch/tile/include/asm/dma-mapping.h
@@ -20,9 +20,14 @@
 #include <linux/cache.h>
 #include <linux/io.h>
 
+#ifdef __tilegx__
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+#endif
+
 extern struct dma_map_ops *tile_dma_map_ops;
 extern struct dma_map_ops *gx_pci_dma_map_ops;
 extern struct dma_map_ops *gx_legacy_pci_dma_map_ops;
+extern struct dma_map_ops *gx_hybrid_pci_dma_map_ops;
 
 static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 {
@@ -44,12 +49,12 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return paddr + get_dma_offset(dev);
+	return paddr;
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-	return daddr - get_dma_offset(dev);
+	return daddr;
 }
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
@@ -88,7 +93,10 @@ dma_set_mask(struct device *dev, u64 mask)
 	struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
 	/* Handle legacy PCI devices with limited memory addressability. */
-	if ((dma_ops == gx_pci_dma_map_ops) && (mask <= DMA_BIT_MASK(32))) {
+	if ((dma_ops == gx_pci_dma_map_ops ||
+	     dma_ops == gx_hybrid_pci_dma_map_ops ||
+	     dma_ops == gx_legacy_pci_dma_map_ops) &&
+	    (mask <= DMA_BIT_MASK(32))) {
 		set_dma_ops(dev, gx_legacy_pci_dma_map_ops);
 		set_dma_offset(dev, 0);
 		if (mask > dev->archdata.max_direct_dma_addr)
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index ff8a934..31d854f 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -132,6 +132,11 @@ extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 				       int executable_stack);
+#define ARCH_DLINFO \
+do { \
+	NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \
+} while (0)
+
 #ifdef CONFIG_COMPAT
 
 #define COMPAT_ELF_PLATFORM "tilegx-m32"
diff --git a/arch/tile/include/asm/homecache.h b/arch/tile/include/asm/homecache.h
index 7b77713..49d19df 100644
--- a/arch/tile/include/asm/homecache.h
+++ b/arch/tile/include/asm/homecache.h
@@ -44,16 +44,8 @@ struct zone;
  */
 #define PAGE_HOME_INCOHERENT -3
 
-#if CHIP_HAS_CBOX_HOME_MAP()
 /* Home for the page is distributed via hash-for-home. */
 #define PAGE_HOME_HASH -4
-#endif
-
-/* Homing is unknown or unspecified.  Not valid for page_home(). */
-#define PAGE_HOME_UNKNOWN -5
-
-/* Home on the current cpu.  Not valid for page_home(). */
-#define PAGE_HOME_HERE -6
 
 /* Support wrapper to use instead of explicit hv_flush_remote(). */
 extern void flush_remote(unsigned long cache_pfn, unsigned long cache_length,
diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h
index 3167291..73b319e 100644
--- a/arch/tile/include/asm/io.h
+++ b/arch/tile/include/asm/io.h
@@ -19,7 +19,8 @@
 #include <linux/bug.h>
 #include <asm/page.h>
 
-#define IO_SPACE_LIMIT 0xfffffffful
+/* Maximum PCI I/O space address supported. */
+#define IO_SPACE_LIMIT 0xffffffff
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
@@ -281,8 +282,108 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
 
 #endif
 
+#if CHIP_HAS_MMIO() && defined(CONFIG_TILE_PCI_IO)
+
+static inline u8 inb(unsigned long addr)
+{
+	return readb((volatile void __iomem *) addr);
+}
+
+static inline u16 inw(unsigned long addr)
+{
+	return readw((volatile void __iomem *) addr);
+}
+
+static inline u32 inl(unsigned long addr)
+{
+	return readl((volatile void __iomem *) addr);
+}
+
+static inline void outb(u8 b, unsigned long addr)
+{
+	writeb(b, (volatile void __iomem *) addr);
+}
+
+static inline void outw(u16 b, unsigned long addr)
+{
+	writew(b, (volatile void __iomem *) addr);
+}
+
+static inline void outl(u32 b, unsigned long addr)
+{
+	writel(b, (volatile void __iomem *) addr);
+}
+
+static inline void insb(unsigned long addr, void *buffer, int count)
+{
+	if (count) {
+		u8 *buf = buffer;
+		do {
+			u8 x = inb(addr);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insw(unsigned long addr, void *buffer, int count)
+{
+	if (count) {
+		u16 *buf = buffer;
+		do {
+			u16 x = inw(addr);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insl(unsigned long addr, void *buffer, int count)
+{
+	if (count) {
+		u32 *buf = buffer;
+		do {
+			u32 x = inl(addr);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void outsb(unsigned long addr, const void *buffer, int count)
+{
+	if (count) {
+		const u8 *buf = buffer;
+		do {
+			outb(*buf++, addr);
+		} while (--count);
+	}
+}
+
+static inline void outsw(unsigned long addr, const void *buffer, int count)
+{
+	if (count) {
+		const u16 *buf = buffer;
+		do {
+			outw(*buf++, addr);
+		} while (--count);
+	}
+}
+
+static inline void outsl(unsigned long addr, const void *buffer, int count)
+{
+	if (count) {
+		const u32 *buf = buffer;
+		do {
+			outl(*buf++, addr);
+		} while (--count);
+	}
+}
+
+extern void __iomem *ioport_map(unsigned long port, unsigned int len);
+extern void ioport_unmap(void __iomem *addr);
+
+#else
+
 /*
- * The Tile architecture does not support IOPORT, even with PCI.
+ * The TilePro architecture does not support IOPORT, even with PCI.
  * Unfortunately we can't yet simply not declare these methods,
  * since some generic code that compiles into the kernel, but
  * we never run, uses them unconditionally.
@@ -290,7 +391,12 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
 
 static inline long ioport_panic(void)
 {
+#ifdef __tilegx__
+	panic("PCI IO space support is disabled. Configure the kernel with"
+	      " CONFIG_TILE_PCI_IO to enable it");
+#else
 	panic("inb/outb and friends do not exist on tile");
+#endif
 	return 0;
 }
 
@@ -335,13 +441,6 @@ static inline void outl(u32 b, unsigned long addr)
 	ioport_panic();
 }
 
-#define inb_p(addr)	inb(addr)
-#define inw_p(addr)	inw(addr)
-#define inl_p(addr)	inl(addr)
-#define outb_p(x, addr)	outb((x), (addr))
-#define outw_p(x, addr)	outw((x), (addr))
-#define outl_p(x, addr)	outl((x), (addr))
-
 static inline void insb(unsigned long addr, void *buffer, int count)
 {
 	ioport_panic();
@@ -372,6 +471,15 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 	ioport_panic();
 }
 
+#endif /* CHIP_HAS_MMIO() && defined(CONFIG_TILE_PCI_IO) */
+
+#define inb_p(addr)	inb(addr)
+#define inw_p(addr)	inw(addr)
+#define inl_p(addr)	inl(addr)
+#define outb_p(x, addr)	outb((x), (addr))
+#define outw_p(x, addr)	outw((x), (addr))
+#define outl_p(x, addr)	outl((x), (addr))
+
 #define ioread16be(addr)	be16_to_cpu(ioread16(addr))
 #define ioread32be(addr)	be32_to_cpu(ioread32(addr))
 #define iowrite16be(v, addr)	iowrite16(be16_to_cpu(v), (addr))
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index c96f9bb..71af574 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -124,6 +124,12 @@
 DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 #define INITIAL_INTERRUPTS_ENABLED (1ULL << INT_MEM_ERROR)
 
+#ifdef CONFIG_DEBUG_PREEMPT
+/* Due to inclusion issues, we can't rely on <linux/smp.h> here. */
+extern unsigned int debug_smp_processor_id(void);
+# define smp_processor_id() debug_smp_processor_id()
+#endif
+
 /* Disable interrupts. */
 #define arch_local_irq_disable() \
 	interrupt_mask_set_mask(LINUX_MASKABLE_INTERRUPTS)
@@ -132,9 +138,18 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 #define arch_local_irq_disable_all() \
 	interrupt_mask_set_mask(-1ULL)
 
+/*
+ * Read the set of maskable interrupts.
+ * We avoid the preemption warning here via __this_cpu_ptr since even
+ * if irqs are already enabled, it's harmless to read the wrong cpu's
+ * enabled mask.
+ */
+#define arch_local_irqs_enabled() \
+	(*__this_cpu_ptr(&interrupts_enabled_mask))
+
 /* Re-enable all maskable interrupts. */
 #define arch_local_irq_enable() \
-	interrupt_mask_reset_mask(__get_cpu_var(interrupts_enabled_mask))
+	interrupt_mask_reset_mask(arch_local_irqs_enabled())
 
 /* Disable or enable interrupts based on flag argument. */
 #define arch_local_irq_restore(disabled) do { \
@@ -161,7 +176,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 
 /* Prevent the given interrupt from being enabled next time we enable irqs. */
 #define arch_local_irq_mask(interrupt) \
-	(__get_cpu_var(interrupts_enabled_mask) &= ~(1ULL << (interrupt)))
+	this_cpu_and(interrupts_enabled_mask, ~(1ULL << (interrupt)))
 
 /* Prevent the given interrupt from being enabled immediately. */
 #define arch_local_irq_mask_now(interrupt) do { \
@@ -171,7 +186,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 
 /* Allow the given interrupt to be enabled next time we enable irqs. */
 #define arch_local_irq_unmask(interrupt) \
-	(__get_cpu_var(interrupts_enabled_mask) |= (1ULL << (interrupt)))
+	this_cpu_or(interrupts_enabled_mask, (1ULL << (interrupt)))
 
 /* Allow the given interrupt to be enabled immediately, if !irqs_disabled. */
 #define arch_local_irq_unmask_now(interrupt) do { \
diff --git a/arch/tile/include/asm/mmu.h b/arch/tile/include/asm/mmu.h
index e2c7890..0cab118 100644
--- a/arch/tile/include/asm/mmu.h
+++ b/arch/tile/include/asm/mmu.h
@@ -22,6 +22,7 @@ struct mm_context {
 	 * semaphore but atomically, but it is conservatively set.
 	 */
 	unsigned long priority_cached;
+	unsigned long vdso_base;
 };
 
 typedef struct mm_context mm_context_t;
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index dd033a4..b4f96c0 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -39,6 +39,12 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 
 /*
+ * We do define AT_SYSINFO_EHDR to support vDSO,
+ * but don't use the gate mechanism.
+ */
+#define __HAVE_ARCH_GATE_AREA		1
+
+/*
  * If the Kconfig doesn't specify, set a maximum zone order that
  * is enough so that we can create huge pages from small pages given
  * the respective sizes of the two page types.  See <linux/mmzone.h>.
@@ -246,7 +252,7 @@ static inline __attribute_const__ int get_order(unsigned long size)
 
 #endif /* __tilegx__ */
 
-#ifndef __ASSEMBLY__
+#if !defined(__ASSEMBLY__) && !defined(VDSO_BUILD)
 
 #ifdef CONFIG_HIGHMEM
 
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h
index 54a9242..c99ad44 100644
--- a/arch/tile/include/asm/pci.h
+++ b/arch/tile/include/asm/pci.h
@@ -17,7 +17,6 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
-#include <linux/numa.h>
 #include <asm-generic/pci_iomap.h>
 
 #ifndef __tilegx__
@@ -29,7 +28,6 @@ struct pci_controller {
 	int index;		/* PCI domain number */
 	struct pci_bus *root_bus;
 
-	int first_busno;
 	int last_busno;
 
 	int hv_cfg_fd[2];	/* config{0,1} fds for this PCIe controller */
@@ -145,6 +143,10 @@ struct pci_controller {
 
 	int pio_mem_index;	/* PIO region index for memory access */
 
+#ifdef CONFIG_TILE_PCI_IO
+	int pio_io_index;	/* PIO region index for I/O space access */
+#endif
+
 	/*
 	 * Mem-Map regions for all the memory controllers so that Linux can
 	 * map all of its physical memory space to the PCI bus.
@@ -154,6 +156,10 @@ struct pci_controller {
 	int index;		/* PCI domain number */
 	struct pci_bus *root_bus;
 
+	/* PCI I/O space resource for this controller. */
+	struct resource io_space;
+	char io_space_name[32];
+
 	/* PCI memory space resource for this controller. */
 	struct resource mem_space;
 	char mem_space_name[32];
@@ -166,13 +172,11 @@ struct pci_controller {
 
 	/* Table that maps the INTx numbers to Linux irq numbers. */
 	int irq_intx_table[4];
-
-	/* Address ranges that are routed to this controller/bridge. */
-	struct resource mem_resources[3];
 };
 
 extern struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
 extern gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+extern int num_trio_shims;
 
 extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
 
@@ -211,7 +215,8 @@ static inline int pcibios_assign_all_busses(void)
 }
 
 #define PCIBIOS_MIN_MEM		0
-#define PCIBIOS_MIN_IO		0
+/* Minimum PCI I/O address, starting at the page boundary. */
+#define PCIBIOS_MIN_IO		PAGE_SIZE
 
 /* Use any cpu for PCI. */
 #define cpumask_of_pcibus(bus) cpu_online_mask
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index b3f1049..461322b 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -110,6 +110,8 @@ struct thread_struct {
 	unsigned long long interrupt_mask;
 	/* User interrupt-control 0 state */
 	unsigned long intctrl_0;
+	/* Is this task currently doing a backtrace? */
+	bool in_backtrace;
 #if CHIP_HAS_PROC_STATUS_SPR()
 	/* Any other miscellaneous processor state bits */
 	unsigned long proc_status;
@@ -178,10 +180,10 @@ struct thread_struct {
 #define TASK_SIZE		TASK_SIZE_MAX
 #endif
 
-/* We provide a minimal "vdso" a la x86; just the sigreturn code for now. */
-#define VDSO_BASE		(TASK_SIZE - PAGE_SIZE)
+#define VDSO_BASE	((unsigned long)current->active_mm->context.vdso_base)
+#define VDSO_SYM(x)	(VDSO_BASE + (unsigned long)(x))
 
-#define STACK_TOP		VDSO_BASE
+#define STACK_TOP		TASK_SIZE
 
 /* STACK_TOP_MAX is used temporarily in execve and should not check COMPAT. */
 #define STACK_TOP_MAX		TASK_SIZE_MAX
@@ -247,6 +249,13 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(task)	task_pc(task)
 #define KSTK_ESP(task)	task_sp(task)
 
+/* Fine-grained unaligned JIT support */
+#define GET_UNALIGN_CTL(tsk, adr)	get_unalign_ctl((tsk), (adr))
+#define SET_UNALIGN_CTL(tsk, val)	set_unalign_ctl((tsk), (val))
+
+extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
+extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+
 /* Standard format for printing registers and other word-size data. */
 #ifdef __tilegx__
 # define REGFMT "0x%016lx"
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index fd41226..73b681b 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -79,8 +79,7 @@ extern void single_step_execve(void);
 
 struct task_struct;
 
-extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
-			 int error_code);
+extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs);
 
 #ifdef __tilegx__
 /* We need this since sigval_t has a user pointer in it, for GETSIGINFO etc. */
diff --git a/arch/tile/include/asm/sections.h b/arch/tile/include/asm/sections.h
index 7d8a935..5d5d3b7 100644
--- a/arch/tile/include/asm/sections.h
+++ b/arch/tile/include/asm/sections.h
@@ -25,10 +25,16 @@ extern char _sinitdata[], _einitdata[];
 /* Write-once data is writable only till the end of initialization. */
 extern char __w1data_begin[], __w1data_end[];
 
+extern char vdso_start[], vdso_end[];
+#ifdef CONFIG_COMPAT
+extern char vdso32_start[], vdso32_end[];
+#endif
 
 /* Not exactly sections, but PC comparison points in the code. */
 extern char __rt_sigreturn[], __rt_sigreturn_end[];
-#ifndef __tilegx__
+#ifdef __tilegx__
+extern char __start_unalign_asm_code[], __end_unalign_asm_code[];
+#else
 extern char sys_cmpxchg[], __sys_cmpxchg_end[];
 extern char __sys_cmpxchg_grab_lock[];
 extern char __start_atomic_asm_code[], __end_atomic_asm_code[];
diff --git a/arch/tile/include/asm/setup.h b/arch/tile/include/asm/setup.h
index d048888..e989090 100644
--- a/arch/tile/include/asm/setup.h
+++ b/arch/tile/include/asm/setup.h
@@ -24,9 +24,8 @@
  */
 #define MAXMEM_PFN	PFN_DOWN(MAXMEM)
 
+int tile_console_write(const char *buf, int count);
 void early_panic(const char *fmt, ...);
-void warn_early_printk(void);
-void __init disable_early_printk(void);
 
 /* Init-time routine to do tile-specific per-cpu setup. */
 void setup_cpu(int boot);
diff --git a/arch/tile/include/asm/string.h b/arch/tile/include/asm/string.h
index 7535cf1..92b271b 100644
--- a/arch/tile/include/asm/string.h
+++ b/arch/tile/include/asm/string.h
@@ -21,8 +21,10 @@
 #define __HAVE_ARCH_MEMMOVE
 #define __HAVE_ARCH_STRCHR
 #define __HAVE_ARCH_STRLEN
+#define __HAVE_ARCH_STRNLEN
 
 extern __kernel_size_t strlen(const char *);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t);
 extern char *strchr(const char *s, int c);
 extern void *memchr(const void *s, int c, size_t n);
 extern void *memset(void *, int, __kernel_size_t);
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h
index d1733de..b8aa6df 100644
--- a/arch/tile/include/asm/thread_info.h
+++ b/arch/tile/include/asm/thread_info.h
@@ -39,6 +39,11 @@ struct thread_info {
 	struct restart_block	restart_block;
 	struct single_step_state *step_state;	/* single step state
 						   (if non-zero) */
+	int			align_ctl;	/* controls unaligned access */
+#ifdef __tilegx__
+	unsigned long		unalign_jit_tmp[4]; /* temp r0..r3 storage */
+	void __user		*unalign_jit_base; /* unalign fixup JIT base */
+#endif
 };
 
 /*
@@ -56,6 +61,7 @@ struct thread_info {
 		.fn = do_no_restart_syscall,	\
 	},					\
 	.step_state	= NULL,			\
+	.align_ctl	= 0,			\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h
index d5e86c9..d15c0d8 100644
--- a/arch/tile/include/asm/topology.h
+++ b/arch/tile/include/asm/topology.h
@@ -89,9 +89,6 @@ static inline const struct cpumask *cpumask_of_node(int node)
 #define topology_core_id(cpu)                   (cpu)
 #define topology_core_cpumask(cpu)              ((void)(cpu), cpu_online_mask)
 #define topology_thread_cpumask(cpu)            cpumask_of(cpu)
-
-/* indicates that pointers to the topology struct cpumask maps are valid */
-#define arch_provides_topology_pointers         yes
 #endif
 
 #endif /* _ASM_TILE_TOPOLOGY_H */
diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h
index e28c3df4..8cd7f2e 100644
--- a/arch/tile/include/asm/traps.h
+++ b/arch/tile/include/asm/traps.h
@@ -15,6 +15,7 @@
 #ifndef _ASM_TILE_TRAPS_H
 #define _ASM_TILE_TRAPS_H
 
+#ifndef __ASSEMBLY__
 #include <arch/chip.h>
 
 /* mm/fault.c */
@@ -71,4 +72,14 @@ void gx_singlestep_handle(struct pt_regs *, int fault_num);
 void fill_ra_stack(void);
 #endif
 
+/* Handle unalign data fixup. */
+extern void do_unaligned(struct pt_regs *regs, int vecnum);
+
+#endif /* __ASSEMBLY__ */
+
+#ifdef __tilegx__
+/* 128 byte JIT per unalign fixup. */
+#define UNALIGN_JIT_SHIFT    7
+#endif
+
 #endif /* _ASM_TILE_TRAPS_H */
diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h
index e4d44bd..f68503f 100644
--- a/arch/tile/include/asm/uaccess.h
+++ b/arch/tile/include/asm/uaccess.h
@@ -567,37 +567,6 @@ static inline unsigned long __must_check flush_user(
 }
 
 /**
- * inv_user: - Invalidate a block of memory in user space from cache.
- * @mem:   Destination address, in user space.
- * @len:   Number of bytes to invalidate.
- *
- * Returns number of bytes that could not be invalidated.
- * On success, this will be zero.
- *
- * Note that on Tile64, the "inv" operation is in fact a
- * "flush and invalidate", so cache write-backs will occur prior
- * to the cache being marked invalid.
- */
-extern unsigned long inv_user_asm(void __user *mem, unsigned long len);
-static inline unsigned long __must_check __inv_user(
-	void __user *mem, unsigned long len)
-{
-	int retval;
-
-	might_fault();
-	retval = inv_user_asm(mem, len);
-	mb_incoherent();
-	return retval;
-}
-static inline unsigned long __must_check inv_user(
-	void __user *mem, unsigned long len)
-{
-	if (access_ok(VERIFY_WRITE, mem, len))
-		return __inv_user(mem, len);
-	return len;
-}
-
-/**
  * finv_user: - Flush-inval a block of memory in user space from cache.
  * @mem:   Destination address, in user space.
  * @len:   Number of bytes to invalidate.
diff --git a/arch/tile/include/asm/unaligned.h b/arch/tile/include/asm/unaligned.h
index 37dfbe5..5a58a0d 100644
--- a/arch/tile/include/asm/unaligned.h
+++ b/arch/tile/include/asm/unaligned.h
@@ -15,11 +15,15 @@
 #ifndef _ASM_TILE_UNALIGNED_H
 #define _ASM_TILE_UNALIGNED_H
 
-#include <linux/unaligned/le_struct.h>
-#include <linux/unaligned/be_byteshift.h>
-#include <linux/unaligned/generic.h>
-#define get_unaligned	__get_unaligned_le
-#define put_unaligned	__put_unaligned_le
+/*
+ * We could implement faster get_unaligned_[be/le]64 using the ldna
+ * instruction on tilegx; however, we need to either copy all of the
+ * other generic functions to here (which is pretty ugly) or else
+ * modify both the generic code and other arch code to allow arch
+ * specific unaligned data access functions.  Given these functions
+ * are not often called, we'll stick with the generic version.
+ */
+#include <asm-generic/unaligned.h>
 
 /*
  * Is the kernel doing fixups of unaligned accesses?  If <0, no kernel
diff --git a/arch/tile/include/asm/vdso.h b/arch/tile/include/asm/vdso.h
new file mode 100644
index 0000000..9f6a78d
--- /dev/null
+++ b/arch/tile/include/asm/vdso.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef __TILE_VDSO_H__
+#define __TILE_VDSO_H__
+
+#include <linux/types.h>
+
+/*
+ * Note about the vdso_data structure:
+ *
+ * NEVER USE THEM IN USERSPACE CODE DIRECTLY. The layout of the
+ * structure is supposed to be known only to the function in the vdso
+ * itself and may change without notice.
+ */
+
+struct vdso_data {
+	__u64 tz_update_count;  /* Timezone atomicity ctr             */
+	__u64 tb_update_count;  /* Timebase atomicity ctr             */
+	__u64 xtime_tod_stamp;  /* TOD clock for xtime                */
+	__u64 xtime_clock_sec;  /* Kernel time second                 */
+	__u64 xtime_clock_nsec; /* Kernel time nanosecond             */
+	__u64 wtom_clock_sec;   /* Wall to monotonic clock second     */
+	__u64 wtom_clock_nsec;  /* Wall to monotonic clock nanosecond */
+	__u32 mult;             /* Cycle to nanosecond multiplier     */
+	__u32 shift;            /* Cycle to nanosecond divisor (power of two) */
+	__u32 tz_minuteswest;   /* Minutes west of Greenwich          */
+	__u32 tz_dsttime;       /* Type of dst correction             */
+};
+
+extern struct vdso_data *vdso_data;
+
+/* __vdso_rt_sigreturn is defined with the addresses in the vdso page. */
+extern void __vdso_rt_sigreturn(void);
+
+extern int setup_vdso_pages(void);
+
+#endif /* __TILE_VDSO_H__ */
diff --git a/arch/tile/include/gxio/iorpc_mpipe.h b/arch/tile/include/gxio/iorpc_mpipe.h
index 9d50fce..fdd07f8 100644
--- a/arch/tile/include/gxio/iorpc_mpipe.h
+++ b/arch/tile/include/gxio/iorpc_mpipe.h
@@ -44,10 +44,13 @@
 #define GXIO_MPIPE_OP_REGISTER_CLIENT_MEMORY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1210)
 #define GXIO_MPIPE_OP_LINK_OPEN_AUX    IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1211)
 #define GXIO_MPIPE_OP_LINK_CLOSE_AUX   IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1212)
+#define GXIO_MPIPE_OP_LINK_SET_ATTR_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1213)
 
-#define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121e)
-#define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121f)
-#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1220)
+#define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x121e)
+#define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x121f)
+#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1220)
+#define GXIO_MPIPE_OP_CONFIG_EDMA_RING_BLKS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1221)
+#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1222)
 #define GXIO_MPIPE_OP_ARM_POLLFD       IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000)
 #define GXIO_MPIPE_OP_CLOSE_POLLFD     IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001)
 #define GXIO_MPIPE_OP_GET_MMIO_BASE    IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
@@ -114,6 +117,8 @@ int gxio_mpipe_link_open_aux(gxio_mpipe_context_t * context,
 
 int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac);
 
+int gxio_mpipe_link_set_attr_aux(gxio_mpipe_context_t * context, int mac,
+				 uint32_t attr, int64_t val);
 
 int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t * context, uint64_t * sec,
 				 uint64_t * nsec, uint64_t * cycles);
@@ -124,6 +129,9 @@ int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec,
 int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
 				    int64_t nsec);
 
+int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context,
+				     int32_t ppb);
+
 int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
 
 int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
diff --git a/arch/tile/include/gxio/iorpc_mpipe_info.h b/arch/tile/include/gxio/iorpc_mpipe_info.h
index 0bcf3f7..476c5e5 100644
--- a/arch/tile/include/gxio/iorpc_mpipe_info.h
+++ b/arch/tile/include/gxio/iorpc_mpipe_info.h
@@ -27,11 +27,15 @@
 #include <asm/pgtable.h>
 
 
+#define GXIO_MPIPE_INFO_OP_INSTANCE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1250)
 #define GXIO_MPIPE_INFO_OP_ENUMERATE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1251)
 #define GXIO_MPIPE_INFO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
 #define GXIO_MPIPE_INFO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
 
+int gxio_mpipe_info_instance_aux(gxio_mpipe_info_context_t * context,
+				 _gxio_mpipe_link_name_t name);
+
 int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
 				  unsigned int idx,
 				  _gxio_mpipe_link_name_t * name,
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
index 58105c3..d95b96f 100644
--- a/arch/tile/include/gxio/iorpc_trio.h
+++ b/arch/tile/include/gxio/iorpc_trio.h
@@ -30,6 +30,7 @@
 
 #define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404)
 
+#define GXIO_TRIO_OP_ALLOC_SCATTER_QUEUES IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
 #define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412)
 
 #define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414)
@@ -54,6 +55,10 @@ int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
 				unsigned int flags);
 
 
+int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
+				   unsigned int count, unsigned int first,
+				   unsigned int flags);
+
 int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
 				unsigned int count, unsigned int first,
 				unsigned int flags);
diff --git a/arch/tile/include/gxio/mpipe.h b/arch/tile/include/gxio/mpipe.h
index b74f470..e37cf4f 100644
--- a/arch/tile/include/gxio/mpipe.h
+++ b/arch/tile/include/gxio/mpipe.h
@@ -220,6 +220,13 @@ typedef MPIPE_PDESC_t gxio_mpipe_idesc_t;
  */
 typedef MPIPE_EDMA_DESC_t gxio_mpipe_edesc_t;
 
+/*
+ * Max # of mpipe instances. 2 currently.
+ */
+#define GXIO_MPIPE_INSTANCE_MAX  HV_MPIPE_INSTANCE_MAX
+
+#define NR_MPIPE_MAX   GXIO_MPIPE_INSTANCE_MAX
+
 /* Get the "va" field from an "idesc".
  *
  * This is the address at which the ingress hardware copied the first
@@ -311,6 +318,9 @@ typedef struct {
 	/* File descriptor for calling up to Linux (and thus the HV). */
 	int fd;
 
+	/* Corresponding mpipe instance #. */
+	int instance;
+
 	/* The VA at which configuration registers are mapped. */
 	char *mmio_cfg_base;
 
@@ -810,7 +820,7 @@ extern int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t *context,
 /* Initialize an eDMA ring, using the given memory and size.
  *
  * @param context An initialized mPIPE context.
- * @param ring The eDMA ring index.
+ * @param ering The eDMA ring index.
  * @param channel The channel to use.  This must be one of the channels
  * associated with the context's set of open links.
  * @param mem A physically contiguous region of memory to be filled
@@ -823,10 +833,37 @@ extern int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t *context,
  * ::GXIO_ERR_INVAL_MEMORY_SIZE on failure.
  */
 extern int gxio_mpipe_init_edma_ring(gxio_mpipe_context_t *context,
-				     unsigned int ring, unsigned int channel,
+				     unsigned int ering, unsigned int channel,
 				     void *mem, size_t mem_size,
 				     unsigned int mem_flags);
 
+/* Set the "max_blks", "min_snf_blks", and "db" fields of
+ * ::MPIPE_EDMA_RG_INIT_DAT_THRESH_t for a given edma ring.
+ *
+ * The global pool of dynamic blocks will be automatically adjusted.
+ *
+ * This function should not be called after any egress has been done
+ * on the edma ring.
+ *
+ * Most applications should just use gxio_mpipe_equeue_set_snf_size().
+ *
+ * @param context An initialized mPIPE context.
+ * @param ering The eDMA ring index.
+ * @param max_blks The number of blocks to dedicate to the ring
+ * (normally min_snf_blks + 1).  Must be greater than min_snf_blocks.
+ * @param min_snf_blks The number of blocks which must be stored
+ * prior to starting to send the packet (normally 12).
+ * @param db Whether to allow use of dynamic blocks by the ring
+ * (normally 1).
+ *
+ * @return 0 on success, negative on error.
+ */
+extern int gxio_mpipe_config_edma_ring_blks(gxio_mpipe_context_t *context,
+					    unsigned int ering,
+					    unsigned int max_blks,
+					    unsigned int min_snf_blks,
+					    unsigned int db);
+
 /*****************************************************************
  *                      Classifier Program                        *
  ******************************************************************/
@@ -1288,15 +1325,39 @@ typedef struct {
 	/* The log2() of the number of entries. */
 	unsigned long log2_num_entries;
 
+	/* The context. */
+	gxio_mpipe_context_t *context;
+
+	/* The ering. */
+	unsigned int ering;
+
+	/* The channel. */
+	unsigned int channel;
+
 } gxio_mpipe_equeue_t;
 
 /* Initialize an "equeue".
  *
- * Takes the equeue plus the same args as gxio_mpipe_init_edma_ring().
+ * This function uses gxio_mpipe_init_edma_ring() to initialize the
+ * underlying edma_ring using the provided arguments.
+ *
+ * @param equeue An egress queue to be initialized.
+ * @param context An initialized mPIPE context.
+ * @param ering The eDMA ring index.
+ * @param channel The channel to use.  This must be one of the channels
+ * associated with the context's set of open links.
+ * @param mem A physically contiguous region of memory to be filled
+ * with a ring of ::gxio_mpipe_edesc_t structures.
+ * @param mem_size Number of bytes in the ring.  Must be 512, 2048,
+ * 8192 or 65536, times 16 (i.e. sizeof(gxio_mpipe_edesc_t)).
+ * @param mem_flags ::gxio_mpipe_mem_flags_e memory flags.
+ *
+ * @return 0 on success, ::GXIO_MPIPE_ERR_BAD_EDMA_RING or
+ * ::GXIO_ERR_INVAL_MEMORY_SIZE on failure.
  */
 extern int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
 				  gxio_mpipe_context_t *context,
-				  unsigned int edma_ring_id,
+				  unsigned int ering,
 				  unsigned int channel,
 				  void *mem, unsigned int mem_size,
 				  unsigned int mem_flags);
@@ -1494,6 +1555,37 @@ static inline int gxio_mpipe_equeue_is_complete(gxio_mpipe_equeue_t *equeue,
 					    completion_slot, update);
 }
 
+/* Set the snf (store and forward) size for an equeue.
+ *
+ * The snf size for an equeue defaults to 1536, and encodes the size
+ * of the largest packet for which egress is guaranteed to avoid
+ * transmission underruns and/or corrupt checksums under heavy load.
+ *
+ * The snf size affects a global resource pool which cannot support,
+ * for example, all 24 equeues each requesting an snf size of 8K.
+ *
+ * To ensure that jumbo packets can be egressed properly, the snf size
+ * should be set to the size of the largest possible packet, which
+ * will usually be limited by the size of the app's largest buffer.
+ *
+ * This is a convenience wrapper around
+ * gxio_mpipe_config_edma_ring_blks().
+ *
+ * This function should not be called after any egress has been done
+ * on the equeue.
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param size The snf size, in bytes.
+ * @return Zero on success, negative error otherwise.
+ */
+static inline int gxio_mpipe_equeue_set_snf_size(gxio_mpipe_equeue_t *equeue,
+						 size_t size)
+{
+	int blks = (size + 127) / 128;
+	return gxio_mpipe_config_edma_ring_blks(equeue->context, equeue->ering,
+						blks + 1, blks, 1);
+}
+
 /*****************************************************************
  *                        Link Management                         *
  ******************************************************************/
@@ -1634,6 +1726,24 @@ typedef struct {
 	uint8_t mac;
 } gxio_mpipe_link_t;
 
+/* Translate a link name to the instance number of the mPIPE shim which is
+ *  connected to that link.  This call does not verify whether the link is
+ *  currently available, and does not reserve any link resources;
+ *  gxio_mpipe_link_open() must be called to perform those functions.
+ *
+ *  Typically applications will call this function to translate a link name
+ *  to an mPIPE instance number; call gxio_mpipe_init(), passing it that
+ *  instance number, to initialize the mPIPE shim; and then call
+ *  gxio_mpipe_link_open(), passing it the same link name plus the mPIPE
+ *  context, to configure the link.
+ *
+ * @param link_name Name of the link; see @ref gxio_mpipe_link_names.
+ * @return The mPIPE instance number which is associated with the named
+ *  link, or a negative error code (::GXIO_ERR_NO_DEVICE) if the link does
+ *  not exist.
+ */
+extern int gxio_mpipe_link_instance(const char *link_name);
+
 /* Retrieve one of this system's legal link names, and its MAC address.
  *
  * @param index Link name index.  If a system supports N legal link names,
@@ -1697,6 +1807,17 @@ static inline int gxio_mpipe_link_channel(gxio_mpipe_link_t *link)
 	return link->channel;
 }
 
+/* Set a link attribute.
+ *
+ * @param link A properly initialized link state object.
+ * @param attr An attribute from the set of @ref gxio_mpipe_link_attrs.
+ * @param val New value of the attribute.
+ * @return 0 if the attribute was successfully set, or a negative error
+ *  code.
+ */
+extern int gxio_mpipe_link_set_attr(gxio_mpipe_link_t *link, uint32_t attr,
+				    int64_t val);
+
 ///////////////////////////////////////////////////////////////////
 //                             Timestamp                         //
 ///////////////////////////////////////////////////////////////////
@@ -1733,4 +1854,18 @@ extern int gxio_mpipe_set_timestamp(gxio_mpipe_context_t *context,
 extern int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context,
 				       int64_t delta);
 
+/** Adjust the mPIPE timestamp clock frequency.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ppb A 32-bit signed PPB (Parts Per Billion) value to adjust.
+ * The absolute value of ppb must be less than or equal to 1000000000.
+ * Values less than about 30000 will generally cause a GXIO_ERR_INVAL
+ * return due to the granularity of the hardware that converts reference
+ * clock cycles into seconds and nanoseconds.
+ * @return If the call was successful, zero; otherwise, a negative error
+ *  code.
+ */
+extern int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t* context,
+                                            int32_t ppb);
+
 #endif /* !_GXIO_MPIPE_H_ */
diff --git a/arch/tile/include/hv/drv_mpipe_intf.h b/arch/tile/include/hv/drv_mpipe_intf.h
index 6cdae3b..c97e416 100644
--- a/arch/tile/include/hv/drv_mpipe_intf.h
+++ b/arch/tile/include/hv/drv_mpipe_intf.h
@@ -23,6 +23,9 @@
 #include <arch/mpipe_constants.h>
 
 
+/** Number of mPIPE instances supported */
+#define HV_MPIPE_INSTANCE_MAX   (2)
+
 /** Number of buffer stacks (32). */
 #define HV_MPIPE_NUM_BUFFER_STACKS \
   (MPIPE_MMIO_INIT_DAT_GX36_1__BUFFER_STACK_MASK_WIDTH)
diff --git a/arch/tile/include/hv/drv_trio_intf.h b/arch/tile/include/hv/drv_trio_intf.h
index ef9f3f5..237e04d 100644
--- a/arch/tile/include/hv/drv_trio_intf.h
+++ b/arch/tile/include/hv/drv_trio_intf.h
@@ -64,8 +64,9 @@ struct pcie_port_property
    *  will not consider it an error if the link comes up as a x8 link. */
   uint8_t allow_x8: 1;
 
-  /** Reserved. */
-  uint8_t reserved: 1;
+  /** If true, this link is connected to a device which may or may not
+   *  be present. */
+  uint8_t removable: 1;
 
 };
 
@@ -167,6 +168,9 @@ pcie_stream_intr_config_sel_t;
 struct pcie_trio_ports_property
 {
   struct pcie_port_property ports[TILEGX_TRIO_PCIES];
+
+  /** Set if this TRIO belongs to a Gx72 device. */
+  uint8_t is_gx72;
 };
 
 /* Flags indicating traffic class. */
diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h
index 837dca5..0971ebb 100644
--- a/arch/tile/include/hv/hypervisor.h
+++ b/arch/tile/include/hv/hypervisor.h
@@ -318,8 +318,11 @@
 /** hv_set_pte_super_shift */
 #define HV_DISPATCH_SET_PTE_SUPER_SHIFT           57
 
+/** hv_console_set_ipi */
+#define HV_DISPATCH_CONSOLE_SET_IPI               63
+
 /** One more than the largest dispatch value */
-#define _HV_DISPATCH_END                          58
+#define _HV_DISPATCH_END                          64
 
 
 #ifndef __ASSEMBLER__
@@ -561,16 +564,11 @@ int hv_confstr(HV_ConfstrQuery query, HV_VirtAddr buf, int len);
 /** Tile coordinate */
 typedef struct
 {
-#ifndef __BIG_ENDIAN__
   /** X coordinate, relative to supervisor's top-left coordinate */
   int x;
 
   /** Y coordinate, relative to supervisor's top-left coordinate */
   int y;
-#else
-  int y;
-  int x;
-#endif
 } HV_Coord;
 
 
@@ -585,6 +583,30 @@ typedef struct
  */
 int hv_get_ipi_pte(HV_Coord tile, int pl, HV_PTE* pte);
 
+/** Configure the console interrupt.
+ *
+ * When the console client interrupt is enabled, the hypervisor will
+ * deliver the specified IPI to the client in the following situations:
+ *
+ * - The console has at least one character available for input.
+ *
+ * - The console can accept new characters for output, and the last call
+ *   to hv_console_write() did not write all of the characters requested
+ *   by the client.
+ *
+ * Note that in some system configurations, console interrupt will not
+ * be available; clients should be prepared for this routine to fail and
+ * to fall back to periodic console polling in that case.
+ *
+ * @param ipi Index of the IPI register which will receive the interrupt.
+ * @param event IPI event number for console interrupt. If less than 0,
+ *        disable the console IPI interrupt.
+ * @param coord Tile to be targeted for console interrupt.
+ * @return 0 on success, otherwise, HV_EINVAL if illegal parameter,
+ *         HV_ENOTSUP if console interrupt are not available.
+ */
+int hv_console_set_ipi(int ipi, int event, HV_Coord coord);
+
 #else /* !CHIP_HAS_IPI() */
 
 /** A set of interrupts. */
@@ -1092,13 +1114,8 @@ HV_VirtAddrRange hv_inquire_virtual(int idx);
 /** A range of ASID values. */
 typedef struct
 {
-#ifndef __BIG_ENDIAN__
   HV_ASID start;        /**< First ASID in the range. */
   unsigned int size;    /**< Number of ASIDs. Zero for an invalid range. */
-#else
-  unsigned int size;    /**< Number of ASIDs. Zero for an invalid range. */
-  HV_ASID start;        /**< First ASID in the range. */
-#endif
 } HV_ASIDRange;
 
 /** Returns information about a range of ASIDs.
@@ -1422,7 +1439,6 @@ typedef enum
 /** Message recipient. */
 typedef struct
 {
-#ifndef __BIG_ENDIAN__
   /** X coordinate, relative to supervisor's top-left coordinate */
   unsigned int x:11;
 
@@ -1431,11 +1447,6 @@ typedef struct
 
   /** Status of this recipient */
   HV_Recip_State state:10;
-#else //__BIG_ENDIAN__
-  HV_Recip_State state:10;
-  unsigned int y:11;
-  unsigned int x:11;
-#endif
 } HV_Recipient;
 
 /** Send a message to a set of recipients.
diff --git a/arch/tile/include/uapi/asm/auxvec.h b/arch/tile/include/uapi/asm/auxvec.h
index 1d393ed..c93e927 100644
--- a/arch/tile/include/uapi/asm/auxvec.h
+++ b/arch/tile/include/uapi/asm/auxvec.h
@@ -15,6 +15,7 @@
 #ifndef _ASM_TILE_AUXVEC_H
 #define _ASM_TILE_AUXVEC_H
 
-/* No extensions to auxvec */
+/* The vDSO location. */
+#define AT_SYSINFO_EHDR         33
 
 #endif /* _ASM_TILE_AUXVEC_H */
diff --git a/arch/tile/include/uapi/asm/cachectl.h b/arch/tile/include/uapi/asm/cachectl.h
index af4c9f9..572ddca 100644
--- a/arch/tile/include/uapi/asm/cachectl.h
+++ b/arch/tile/include/uapi/asm/cachectl.h
@@ -29,8 +29,8 @@
  * to honor the arguments at some point.)
  *
  * Flush and invalidation of memory can normally be performed with the
- * __insn_flush(), __insn_inv(), and __insn_finv() instructions from
- * userspace.  The DCACHE option to the system call allows userspace
+ * __insn_flush() and __insn_finv() instructions from userspace.
+ * The DCACHE option to the system call allows userspace
  * to flush the entire L1+L2 data cache from the core.  In this case,
  * the address and length arguments are not used.  The DCACHE flush is
  * restricted to the current core, not all cores in the address space.
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index 5334be8..c4a957a 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -3,9 +3,10 @@
 #
 
 extra-y := vmlinux.lds head_$(BITS).o
-obj-y := backtrace.o entry.o irq.o messaging.o \
+obj-y := backtrace.o entry.o hvglue.o irq.o messaging.o \
 	pci-dma.o proc.o process.o ptrace.o reboot.o \
-	setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \
+	setup.o signal.o single_step.o stack.o sys.o \
+	sysfs.o time.o traps.o unaligned.o vdso.o \
 	intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o
 
 obj-$(CONFIG_HARDWALL)		+= hardwall.o
@@ -20,3 +21,6 @@ else
 obj-$(CONFIG_PCI)		+= pci.o
 endif
 obj-$(CONFIG_TILE_USB)		+= usb.o
+obj-$(CONFIG_TILE_HVGLUE_TRACE)	+= hvglue_trace.o
+
+obj-y				+= vdso/
diff --git a/arch/tile/kernel/asm-offsets.c b/arch/tile/kernel/asm-offsets.c
index 01ddf19..97ea6ac 100644
--- a/arch/tile/kernel/asm-offsets.c
+++ b/arch/tile/kernel/asm-offsets.c
@@ -37,40 +37,48 @@
 
 void foo(void)
 {
-	DEFINE(SINGLESTEP_STATE_BUFFER_OFFSET, \
+	DEFINE(SINGLESTEP_STATE_BUFFER_OFFSET,
 	       offsetof(struct single_step_state, buffer));
-	DEFINE(SINGLESTEP_STATE_FLAGS_OFFSET, \
+	DEFINE(SINGLESTEP_STATE_FLAGS_OFFSET,
 	       offsetof(struct single_step_state, flags));
-	DEFINE(SINGLESTEP_STATE_ORIG_PC_OFFSET, \
+	DEFINE(SINGLESTEP_STATE_ORIG_PC_OFFSET,
 	       offsetof(struct single_step_state, orig_pc));
-	DEFINE(SINGLESTEP_STATE_NEXT_PC_OFFSET, \
+	DEFINE(SINGLESTEP_STATE_NEXT_PC_OFFSET,
 	       offsetof(struct single_step_state, next_pc));
-	DEFINE(SINGLESTEP_STATE_BRANCH_NEXT_PC_OFFSET, \
+	DEFINE(SINGLESTEP_STATE_BRANCH_NEXT_PC_OFFSET,
 	       offsetof(struct single_step_state, branch_next_pc));
-	DEFINE(SINGLESTEP_STATE_UPDATE_VALUE_OFFSET, \
+	DEFINE(SINGLESTEP_STATE_UPDATE_VALUE_OFFSET,
 	       offsetof(struct single_step_state, update_value));
 
-	DEFINE(THREAD_INFO_TASK_OFFSET, \
+	DEFINE(THREAD_INFO_TASK_OFFSET,
 	       offsetof(struct thread_info, task));
-	DEFINE(THREAD_INFO_FLAGS_OFFSET, \
+	DEFINE(THREAD_INFO_FLAGS_OFFSET,
 	       offsetof(struct thread_info, flags));
-	DEFINE(THREAD_INFO_STATUS_OFFSET, \
+	DEFINE(THREAD_INFO_STATUS_OFFSET,
 	       offsetof(struct thread_info, status));
-	DEFINE(THREAD_INFO_HOMECACHE_CPU_OFFSET, \
+	DEFINE(THREAD_INFO_HOMECACHE_CPU_OFFSET,
 	       offsetof(struct thread_info, homecache_cpu));
-	DEFINE(THREAD_INFO_STEP_STATE_OFFSET, \
+	DEFINE(THREAD_INFO_PREEMPT_COUNT_OFFSET,
+	       offsetof(struct thread_info, preempt_count));
+	DEFINE(THREAD_INFO_STEP_STATE_OFFSET,
 	       offsetof(struct thread_info, step_state));
+#ifdef __tilegx__
+	DEFINE(THREAD_INFO_UNALIGN_JIT_BASE_OFFSET,
+	       offsetof(struct thread_info, unalign_jit_base));
+	DEFINE(THREAD_INFO_UNALIGN_JIT_TMP_OFFSET,
+	       offsetof(struct thread_info, unalign_jit_tmp));
+#endif
 
 	DEFINE(TASK_STRUCT_THREAD_KSP_OFFSET,
 	       offsetof(struct task_struct, thread.ksp));
 	DEFINE(TASK_STRUCT_THREAD_PC_OFFSET,
 	       offsetof(struct task_struct, thread.pc));
 
-	DEFINE(HV_TOPOLOGY_WIDTH_OFFSET, \
+	DEFINE(HV_TOPOLOGY_WIDTH_OFFSET,
 	       offsetof(HV_Topology, width));
-	DEFINE(HV_TOPOLOGY_HEIGHT_OFFSET, \
+	DEFINE(HV_TOPOLOGY_HEIGHT_OFFSET,
 	       offsetof(HV_Topology, height));
 
-	DEFINE(IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET, \
+	DEFINE(IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET,
 	       offsetof(irq_cpustat_t, irq_syscall_count));
 }
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index d0a052e..85e00b2 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -32,6 +32,7 @@
 #include <asm/ucontext.h>
 #include <asm/sigframe.h>
 #include <asm/syscalls.h>
+#include <asm/vdso.h>
 #include <arch/interrupts.h>
 
 struct compat_ucontext {
@@ -227,7 +228,7 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (err)
 		goto give_sigsegv;
 
-	restorer = VDSO_BASE;
+	restorer = VDSO_SYM(&__vdso_rt_sigreturn);
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
 
diff --git a/arch/tile/kernel/early_printk.c b/arch/tile/kernel/early_printk.c
index 34d72a1..b608e00 100644
--- a/arch/tile/kernel/early_printk.c
+++ b/arch/tile/kernel/early_printk.c
@@ -23,19 +23,24 @@
 
 static void early_hv_write(struct console *con, const char *s, unsigned n)
 {
-	hv_console_write((HV_VirtAddr) s, n);
+	tile_console_write(s, n);
+
+	/*
+	 * Convert NL to NLCR (close enough to CRNL) during early boot.
+	 * We assume newlines are at the ends of strings, which turns out
+	 * to be good enough for early boot console output.
+	 */
+	if (n && s[n-1] == '\n')
+		tile_console_write("\r", 1);
 }
 
 static struct console early_hv_console = {
 	.name =		"earlyhv",
 	.write =	early_hv_write,
-	.flags =	CON_PRINTBUFFER,
+	.flags =	CON_PRINTBUFFER | CON_BOOT,
 	.index =	-1,
 };
 
-/* Direct interface for emergencies */
-static int early_console_complete;
-
 void early_panic(const char *fmt, ...)
 {
 	va_list ap;
@@ -43,51 +48,21 @@ void early_panic(const char *fmt, ...)
 	va_start(ap, fmt);
 	early_printk("Kernel panic - not syncing: ");
 	early_vprintk(fmt, ap);
-	early_console->write(early_console, "\n", 1);
+	early_printk("\n");
 	va_end(ap);
 	dump_stack();
 	hv_halt();
 }
 
-static int __initdata keep_early;
-
 static int __init setup_early_printk(char *str)
 {
 	if (early_console)
 		return 1;
 
-	if (str != NULL && strncmp(str, "keep", 4) == 0)
-		keep_early = 1;
-
 	early_console = &early_hv_console;
 	register_console(early_console);
 
 	return 0;
 }
 
-void __init disable_early_printk(void)
-{
-	early_console_complete = 1;
-	if (!early_console)
-		return;
-	if (!keep_early) {
-		early_printk("disabling early console\n");
-		unregister_console(early_console);
-		early_console = NULL;
-	} else {
-		early_printk("keeping early console\n");
-	}
-}
-
-void warn_early_printk(void)
-{
-	if (early_console_complete || early_console)
-		return;
-	early_printk("\
-Machine shutting down before console output is fully initialized.\n\
-You may wish to reboot and add the option 'earlyprintk' to your\n\
-boot command line to see any diagnostic early console output.\n\
-");
-}
-
 early_param("earlyprintk", setup_early_printk);
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index f116cb0..3d91759 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -27,22 +27,6 @@ STD_ENTRY(current_text_addr)
 	{ move r0, lr; jrp lr }
 	STD_ENDPROC(current_text_addr)
 
-/*
- * We don't run this function directly, but instead copy it to a page
- * we map into every user process.  See vdso_setup().
- *
- * Note that libc has a copy of this function that it uses to compare
- * against the PC when a stack backtrace ends, so if this code is
- * changed, the libc implementation(s) should also be updated.
- */
-	.pushsection .data
-ENTRY(__rt_sigreturn)
-	moveli TREG_SYSCALL_NR_NAME,__NR_rt_sigreturn
-	swint1
-	ENDPROC(__rt_sigreturn)
-	ENTRY(__rt_sigreturn_end)
-	.popsection
-
 STD_ENTRY(dump_stack)
 	{ move r2, lr; lnk r1 }
 	{ move r4, r52; addli r1, r1, dump_stack - . }
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 38ac189..df27a1f 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -272,9 +272,9 @@ static void hardwall_setup_func(void *info)
 	struct hardwall_info *r = info;
 	struct hardwall_type *hwt = r->type;
 
-	int cpu = smp_processor_id();
-	int x = cpu % smp_width;
-	int y = cpu / smp_width;
+	int cpu = smp_processor_id();  /* on_each_cpu disables preemption */
+	int x = cpu_x(cpu);
+	int y = cpu_y(cpu);
 	int bits = 0;
 	if (x == r->ulhc_x)
 		bits |= W_PROTECT;
@@ -317,6 +317,7 @@ static void hardwall_protect_rectangle(struct hardwall_info *r)
 	on_each_cpu_mask(&rect_cpus, hardwall_setup_func, r, 1);
 }
 
+/* Entered from INT_xDN_FIREWALL interrupt vector with irqs disabled. */
 void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
 {
 	struct hardwall_info *rect;
@@ -325,7 +326,6 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
 	struct siginfo info;
 	int cpu = smp_processor_id();
 	int found_processes;
-	unsigned long flags;
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
 	irq_enter();
@@ -346,7 +346,7 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
 	BUG_ON(hwt->disabled);
 
 	/* This tile trapped a network access; find the rectangle. */
-	spin_lock_irqsave(&hwt->lock, flags);
+	spin_lock(&hwt->lock);
 	list_for_each_entry(rect, &hwt->list, list) {
 		if (cpumask_test_cpu(cpu, &rect->cpumask))
 			break;
@@ -401,7 +401,7 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
 		pr_notice("hardwall: no associated processes!\n");
 
  done:
-	spin_unlock_irqrestore(&hwt->lock, flags);
+	spin_unlock(&hwt->lock);
 
 	/*
 	 * We have to disable firewall interrupts now, or else when we
@@ -540,6 +540,14 @@ static struct hardwall_info *hardwall_create(struct hardwall_type *hwt,
 		}
 	}
 
+	/*
+	 * Eliminate cpus that are not part of this Linux client.
+	 * Note that this allows for configurations that we might not want to
+	 * support, such as one client on every even cpu, another client on
+	 * every odd cpu.
+	 */
+	cpumask_and(&info->cpumask, &info->cpumask, cpu_online_mask);
+
 	/* Confirm it doesn't overlap and add it to the list. */
 	spin_lock_irqsave(&hwt->lock, flags);
 	list_for_each_entry(iter, &hwt->list, list) {
@@ -612,7 +620,7 @@ static int hardwall_activate(struct hardwall_info *info)
 
 /*
  * Deactivate a task's hardwall.  Must hold lock for hardwall_type.
- * This method may be called from free_task(), so we don't want to
+ * This method may be called from exit_thread(), so we don't want to
  * rely on too many fields of struct task_struct still being valid.
  * We assume the cpus_allowed, pid, and comm fields are still valid.
  */
@@ -653,7 +661,7 @@ static int hardwall_deactivate(struct hardwall_type *hwt,
 		return -EINVAL;
 
 	printk(KERN_DEBUG "Pid %d (%s) deactivated for %s hardwall: cpu %d\n",
-	       task->pid, task->comm, hwt->name, smp_processor_id());
+	       task->pid, task->comm, hwt->name, raw_smp_processor_id());
 	return 0;
 }
 
@@ -795,8 +803,8 @@ static void reset_xdn_network_state(struct hardwall_type *hwt)
 	/* Reset UDN coordinates to their standard value */
 	{
 		unsigned int cpu = smp_processor_id();
-		unsigned int x = cpu % smp_width;
-		unsigned int y = cpu / smp_width;
+		unsigned int x = cpu_x(cpu);
+		unsigned int y = cpu_y(cpu);
 		__insn_mtspr(SPR_UDN_TILE_COORD, (x << 18) | (y << 7));
 	}
 
diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S
index ac11530..d1527fc 100644
--- a/arch/tile/kernel/head_32.S
+++ b/arch/tile/kernel/head_32.S
@@ -39,12 +39,12 @@ ENTRY(_start)
 	}
 	{
 	  moveli r0, _HV_VERSION_OLD_HV_INIT
-	  jal hv_init
+	  jal _hv_init
 	}
 	/* Get a reasonable default ASID in r0 */
 	{
 	  move r0, zero
-	  jal hv_inquire_asid
+	  jal _hv_inquire_asid
 	}
 	/* Install the default page table */
 	{
@@ -64,7 +64,7 @@ ENTRY(_start)
 	  auli r0, r0, ha16(swapper_pg_dir - PAGE_OFFSET)
 	}
 	{
-	  inv r6
+	  finv r6
 	  move r1, zero   /* high 32 bits of CPA is zero */
 	}
 	{
@@ -73,12 +73,12 @@ ENTRY(_start)
 	}
 	{
 	  auli lr, lr, ha16(1f)
-	  j hv_install_context
+	  j _hv_install_context
 	}
 1:
 
 	/* Get our processor number and save it away in SAVE_K_0. */
-	jal hv_inquire_topology
+	jal _hv_inquire_topology
 	mulll_uu r4, r1, r2        /* r1 == y, r2 == width */
 	add r4, r4, r0             /* r0 == x, so r4 == cpu == y*width + x */
 
diff --git a/arch/tile/kernel/head_64.S b/arch/tile/kernel/head_64.S
index 6093964..969e4f8 100644
--- a/arch/tile/kernel/head_64.S
+++ b/arch/tile/kernel/head_64.S
@@ -25,6 +25,15 @@
 #include <arch/chip.h>
 #include <arch/spr_def.h>
 
+/* Extract two 32-bit bit values that were read into one register. */
+#ifdef __BIG_ENDIAN__
+#define GET_FIRST_INT(rd, rs) shrsi rd, rs, 32
+#define GET_SECOND_INT(rd, rs) addxi rd, rs, 0
+#else
+#define GET_FIRST_INT(rd, rs) addxi rd, rs, 0
+#define GET_SECOND_INT(rd, rs) shrsi rd, rs, 32
+#endif
+
 /*
  * This module contains the entry code for kernel images. It performs the
  * minimal setup needed to call the generic C routines.
@@ -46,11 +55,11 @@ ENTRY(_start)
 	  movei r2, TILE_CHIP_REV
 	  movei r3, KERNEL_PL
 	}
-	jal hv_init
+	jal _hv_init
 	/* Get a reasonable default ASID in r0 */
 	{
 	  move r0, zero
-	  jal hv_inquire_asid
+	  jal _hv_inquire_asid
 	}
 
 	/*
@@ -61,7 +70,7 @@ ENTRY(_start)
 	 * other CPUs should see a properly-constructed page table.
 	 */
 	{
-	  v4int_l r2, zero, r0    /* ASID for hv_install_context */
+	  GET_FIRST_INT(r2, r0)    /* ASID for hv_install_context */
 	  moveli r4, hw1_last(swapper_pgprot - PAGE_OFFSET)
 	}
 	{
@@ -77,7 +86,7 @@ ENTRY(_start)
 	{
 	  /* After initializing swapper_pgprot, HV_PTE_GLOBAL is set. */
 	  bfextu r7, r1, HV_PTE_INDEX_GLOBAL, HV_PTE_INDEX_GLOBAL
-	  inv r4
+	  finv r4
 	}
 	bnez r7, .Lno_write
 	{
@@ -121,7 +130,7 @@ ENTRY(_start)
 	}
 	{
 	  moveli r3, CTX_PAGE_FLAG
-	  j hv_install_context
+	  j _hv_install_context
 	}
 1:
 
@@ -131,19 +140,14 @@ ENTRY(_start)
 	shl16insli r0, r0, hw0(MEM_SV_START)
 	mtspr SPR_INTERRUPT_VECTOR_BASE_K, r0
 
-	/*
-	 * Get our processor number and save it away in SAVE_K_0.
-	 * Extract stuff from the topology structure: r4 = y, r6 = x,
-	 * r5 = width.  FIXME: consider whether we want to just make these
-	 * 64-bit values (and if so fix smp_topology write below, too).
-	 */
-	jal hv_inquire_topology
+	/* Get our processor number and save it away in SAVE_K_0. */
+	jal _hv_inquire_topology
 	{
-	  v4int_l r5, zero, r1    /* r5 = width */
-	  shrui r4, r0, 32        /* r4 = y */
+	  GET_FIRST_INT(r5, r1)   /* r5 = width */
+	  GET_SECOND_INT(r4, r0)  /* r4 = y */
 	}
 	{
-	  v4int_l r6, zero, r0    /* r6 = x */
+	  GET_FIRST_INT(r6, r0)   /* r6 = x */
 	  mul_lu_lu r4, r4, r5
 	}
 	{
diff --git a/arch/tile/kernel/hvglue.S b/arch/tile/kernel/hvglue.S
new file mode 100644
index 0000000..2ab4566
--- /dev/null
+++ b/arch/tile/kernel/hvglue.S
@@ -0,0 +1,74 @@
+/* Hypervisor call vector addresses; see <hv/hypervisor.h> */
+.macro gensym sym, val, size
+.org \val
+.global _\sym
+.type _\sym,function
+_\sym:
+.size _\sym,\size
+#ifndef CONFIG_TILE_HVGLUE_TRACE
+.globl \sym
+.set \sym,_\sym
+#endif
+.endm
+
+.section .hvglue,"x",@nobits
+.align 8
+gensym hv_init, 0x20, 32
+gensym hv_install_context, 0x40, 32
+gensym hv_sysconf, 0x60, 32
+gensym hv_get_rtc, 0x80, 32
+gensym hv_set_rtc, 0xa0, 32
+gensym hv_flush_asid, 0xc0, 32
+gensym hv_flush_page, 0xe0, 32
+gensym hv_flush_pages, 0x100, 32
+gensym hv_restart, 0x120, 32
+gensym hv_halt, 0x140, 32
+gensym hv_power_off, 0x160, 32
+gensym hv_inquire_physical, 0x180, 32
+gensym hv_inquire_memory_controller, 0x1a0, 32
+gensym hv_inquire_virtual, 0x1c0, 32
+gensym hv_inquire_asid, 0x1e0, 32
+gensym hv_nanosleep, 0x200, 32
+gensym hv_console_read_if_ready, 0x220, 32
+gensym hv_console_write, 0x240, 32
+gensym hv_downcall_dispatch, 0x260, 32
+gensym hv_inquire_topology, 0x280, 32
+gensym hv_fs_findfile, 0x2a0, 32
+gensym hv_fs_fstat, 0x2c0, 32
+gensym hv_fs_pread, 0x2e0, 32
+gensym hv_physaddr_read64, 0x300, 32
+gensym hv_physaddr_write64, 0x320, 32
+gensym hv_get_command_line, 0x340, 32
+gensym hv_set_caching, 0x360, 32
+gensym hv_bzero_page, 0x380, 32
+gensym hv_register_message_state, 0x3a0, 32
+gensym hv_send_message, 0x3c0, 32
+gensym hv_receive_message, 0x3e0, 32
+gensym hv_inquire_context, 0x400, 32
+gensym hv_start_all_tiles, 0x420, 32
+gensym hv_dev_open, 0x440, 32
+gensym hv_dev_close, 0x460, 32
+gensym hv_dev_pread, 0x480, 32
+gensym hv_dev_pwrite, 0x4a0, 32
+gensym hv_dev_poll, 0x4c0, 32
+gensym hv_dev_poll_cancel, 0x4e0, 32
+gensym hv_dev_preada, 0x500, 32
+gensym hv_dev_pwritea, 0x520, 32
+gensym hv_flush_remote, 0x540, 32
+gensym hv_console_putc, 0x560, 32
+gensym hv_inquire_tiles, 0x580, 32
+gensym hv_confstr, 0x5a0, 32
+gensym hv_reexec, 0x5c0, 32
+gensym hv_set_command_line, 0x5e0, 32
+gensym hv_clear_intr, 0x600, 32
+gensym hv_enable_intr, 0x620, 32
+gensym hv_disable_intr, 0x640, 32
+gensym hv_raise_intr, 0x660, 32
+gensym hv_trigger_ipi, 0x680, 32
+gensym hv_store_mapping, 0x6a0, 32
+gensym hv_inquire_realpa, 0x6c0, 32
+gensym hv_flush_all, 0x6e0, 32
+gensym hv_get_ipi_pte, 0x700, 32
+gensym hv_set_pte_super_shift, 0x720, 32
+gensym hv_console_set_ipi, 0x7e0, 32
+gensym hv_glue_internals, 0x800, 30720
diff --git a/arch/tile/kernel/hvglue.lds b/arch/tile/kernel/hvglue.lds
deleted file mode 100644
index d44c5a6..0000000
--- a/arch/tile/kernel/hvglue.lds
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Hypervisor call vector addresses; see <hv/hypervisor.h> */
-hv_init = TEXT_OFFSET + 0x10020;
-hv_install_context = TEXT_OFFSET + 0x10040;
-hv_sysconf = TEXT_OFFSET + 0x10060;
-hv_get_rtc = TEXT_OFFSET + 0x10080;
-hv_set_rtc = TEXT_OFFSET + 0x100a0;
-hv_flush_asid = TEXT_OFFSET + 0x100c0;
-hv_flush_page = TEXT_OFFSET + 0x100e0;
-hv_flush_pages = TEXT_OFFSET + 0x10100;
-hv_restart = TEXT_OFFSET + 0x10120;
-hv_halt = TEXT_OFFSET + 0x10140;
-hv_power_off = TEXT_OFFSET + 0x10160;
-hv_inquire_physical = TEXT_OFFSET + 0x10180;
-hv_inquire_memory_controller = TEXT_OFFSET + 0x101a0;
-hv_inquire_virtual = TEXT_OFFSET + 0x101c0;
-hv_inquire_asid = TEXT_OFFSET + 0x101e0;
-hv_nanosleep = TEXT_OFFSET + 0x10200;
-hv_console_read_if_ready = TEXT_OFFSET + 0x10220;
-hv_console_write = TEXT_OFFSET + 0x10240;
-hv_downcall_dispatch = TEXT_OFFSET + 0x10260;
-hv_inquire_topology = TEXT_OFFSET + 0x10280;
-hv_fs_findfile = TEXT_OFFSET + 0x102a0;
-hv_fs_fstat = TEXT_OFFSET + 0x102c0;
-hv_fs_pread = TEXT_OFFSET + 0x102e0;
-hv_physaddr_read64 = TEXT_OFFSET + 0x10300;
-hv_physaddr_write64 = TEXT_OFFSET + 0x10320;
-hv_get_command_line = TEXT_OFFSET + 0x10340;
-hv_set_caching = TEXT_OFFSET + 0x10360;
-hv_bzero_page = TEXT_OFFSET + 0x10380;
-hv_register_message_state = TEXT_OFFSET + 0x103a0;
-hv_send_message = TEXT_OFFSET + 0x103c0;
-hv_receive_message = TEXT_OFFSET + 0x103e0;
-hv_inquire_context = TEXT_OFFSET + 0x10400;
-hv_start_all_tiles = TEXT_OFFSET + 0x10420;
-hv_dev_open = TEXT_OFFSET + 0x10440;
-hv_dev_close = TEXT_OFFSET + 0x10460;
-hv_dev_pread = TEXT_OFFSET + 0x10480;
-hv_dev_pwrite = TEXT_OFFSET + 0x104a0;
-hv_dev_poll = TEXT_OFFSET + 0x104c0;
-hv_dev_poll_cancel = TEXT_OFFSET + 0x104e0;
-hv_dev_preada = TEXT_OFFSET + 0x10500;
-hv_dev_pwritea = TEXT_OFFSET + 0x10520;
-hv_flush_remote = TEXT_OFFSET + 0x10540;
-hv_console_putc = TEXT_OFFSET + 0x10560;
-hv_inquire_tiles = TEXT_OFFSET + 0x10580;
-hv_confstr = TEXT_OFFSET + 0x105a0;
-hv_reexec = TEXT_OFFSET + 0x105c0;
-hv_set_command_line = TEXT_OFFSET + 0x105e0;
-hv_clear_intr = TEXT_OFFSET + 0x10600;
-hv_enable_intr = TEXT_OFFSET + 0x10620;
-hv_disable_intr = TEXT_OFFSET + 0x10640;
-hv_raise_intr = TEXT_OFFSET + 0x10660;
-hv_trigger_ipi = TEXT_OFFSET + 0x10680;
-hv_store_mapping = TEXT_OFFSET + 0x106a0;
-hv_inquire_realpa = TEXT_OFFSET + 0x106c0;
-hv_flush_all = TEXT_OFFSET + 0x106e0;
-hv_get_ipi_pte = TEXT_OFFSET + 0x10700;
-hv_set_pte_super_shift = TEXT_OFFSET + 0x10720;
-hv_glue_internals = TEXT_OFFSET + 0x10740;
diff --git a/arch/tile/kernel/hvglue_trace.c b/arch/tile/kernel/hvglue_trace.c
new file mode 100644
index 0000000..85c74ad
--- /dev/null
+++ b/arch/tile/kernel/hvglue_trace.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2013 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Pull in the hypervisor header so we declare all the ABI functions
+ * with the underscore versions, then undef the names so that we can
+ * provide our own wrapper versions.
+ */
+#define hv_init _hv_init
+#define hv_install_context _hv_install_context
+#define hv_sysconf _hv_sysconf
+#define hv_get_rtc _hv_get_rtc
+#define hv_set_rtc _hv_set_rtc
+#define hv_flush_asid _hv_flush_asid
+#define hv_flush_page _hv_flush_page
+#define hv_flush_pages _hv_flush_pages
+#define hv_restart _hv_restart
+#define hv_halt _hv_halt
+#define hv_power_off _hv_power_off
+#define hv_inquire_physical _hv_inquire_physical
+#define hv_inquire_memory_controller _hv_inquire_memory_controller
+#define hv_inquire_virtual _hv_inquire_virtual
+#define hv_inquire_asid _hv_inquire_asid
+#define hv_nanosleep _hv_nanosleep
+#define hv_console_read_if_ready _hv_console_read_if_ready
+#define hv_console_write _hv_console_write
+#define hv_downcall_dispatch _hv_downcall_dispatch
+#define hv_inquire_topology _hv_inquire_topology
+#define hv_fs_findfile _hv_fs_findfile
+#define hv_fs_fstat _hv_fs_fstat
+#define hv_fs_pread _hv_fs_pread
+#define hv_physaddr_read64 _hv_physaddr_read64
+#define hv_physaddr_write64 _hv_physaddr_write64
+#define hv_get_command_line _hv_get_command_line
+#define hv_set_caching _hv_set_caching
+#define hv_bzero_page _hv_bzero_page
+#define hv_register_message_state _hv_register_message_state
+#define hv_send_message _hv_send_message
+#define hv_receive_message _hv_receive_message
+#define hv_inquire_context _hv_inquire_context
+#define hv_start_all_tiles _hv_start_all_tiles
+#define hv_dev_open _hv_dev_open
+#define hv_dev_close _hv_dev_close
+#define hv_dev_pread _hv_dev_pread
+#define hv_dev_pwrite _hv_dev_pwrite
+#define hv_dev_poll _hv_dev_poll
+#define hv_dev_poll_cancel _hv_dev_poll_cancel
+#define hv_dev_preada _hv_dev_preada
+#define hv_dev_pwritea _hv_dev_pwritea
+#define hv_flush_remote _hv_flush_remote
+#define hv_console_putc _hv_console_putc
+#define hv_inquire_tiles _hv_inquire_tiles
+#define hv_confstr _hv_confstr
+#define hv_reexec _hv_reexec
+#define hv_set_command_line _hv_set_command_line
+#define hv_clear_intr _hv_clear_intr
+#define hv_enable_intr _hv_enable_intr
+#define hv_disable_intr _hv_disable_intr
+#define hv_raise_intr _hv_raise_intr
+#define hv_trigger_ipi _hv_trigger_ipi
+#define hv_store_mapping _hv_store_mapping
+#define hv_inquire_realpa _hv_inquire_realpa
+#define hv_flush_all _hv_flush_all
+#define hv_get_ipi_pte _hv_get_ipi_pte
+#define hv_set_pte_super_shift _hv_set_pte_super_shift
+#define hv_console_set_ipi _hv_console_set_ipi
+#include <hv/hypervisor.h>
+#undef hv_init
+#undef hv_install_context
+#undef hv_sysconf
+#undef hv_get_rtc
+#undef hv_set_rtc
+#undef hv_flush_asid
+#undef hv_flush_page
+#undef hv_flush_pages
+#undef hv_restart
+#undef hv_halt
+#undef hv_power_off
+#undef hv_inquire_physical
+#undef hv_inquire_memory_controller
+#undef hv_inquire_virtual
+#undef hv_inquire_asid
+#undef hv_nanosleep
+#undef hv_console_read_if_ready
+#undef hv_console_write
+#undef hv_downcall_dispatch
+#undef hv_inquire_topology
+#undef hv_fs_findfile
+#undef hv_fs_fstat
+#undef hv_fs_pread
+#undef hv_physaddr_read64
+#undef hv_physaddr_write64
+#undef hv_get_command_line
+#undef hv_set_caching
+#undef hv_bzero_page
+#undef hv_register_message_state
+#undef hv_send_message
+#undef hv_receive_message
+#undef hv_inquire_context
+#undef hv_start_all_tiles
+#undef hv_dev_open
+#undef hv_dev_close
+#undef hv_dev_pread
+#undef hv_dev_pwrite
+#undef hv_dev_poll
+#undef hv_dev_poll_cancel
+#undef hv_dev_preada
+#undef hv_dev_pwritea
+#undef hv_flush_remote
+#undef hv_console_putc
+#undef hv_inquire_tiles
+#undef hv_confstr
+#undef hv_reexec
+#undef hv_set_command_line
+#undef hv_clear_intr
+#undef hv_enable_intr
+#undef hv_disable_intr
+#undef hv_raise_intr
+#undef hv_trigger_ipi
+#undef hv_store_mapping
+#undef hv_inquire_realpa
+#undef hv_flush_all
+#undef hv_get_ipi_pte
+#undef hv_set_pte_super_shift
+#undef hv_console_set_ipi
+
+/*
+ * Provide macros based on <linux/syscalls.h> to provide a wrapper
+ * function that invokes the same function with an underscore prefix.
+ * We can't use the existing __SC_xxx macros because we need to
+ * support up to nine arguments rather than up to six, and also this
+ * way the file stands alone from possible changes in the
+ * implementation of <linux/syscalls.h>.
+ */
+#define HV_WRAP0(type, name)					\
+	type name(void);					\
+	type name(void)						\
+	{							\
+		return _##name();				\
+	}
+#define __HV_DECL1(t1, a1)	t1 a1
+#define __HV_DECL2(t2, a2, ...) t2 a2, __HV_DECL1(__VA_ARGS__)
+#define __HV_DECL3(t3, a3, ...) t3 a3, __HV_DECL2(__VA_ARGS__)
+#define __HV_DECL4(t4, a4, ...) t4 a4, __HV_DECL3(__VA_ARGS__)
+#define __HV_DECL5(t5, a5, ...) t5 a5, __HV_DECL4(__VA_ARGS__)
+#define __HV_DECL6(t6, a6, ...) t6 a6, __HV_DECL5(__VA_ARGS__)
+#define __HV_DECL7(t7, a7, ...) t7 a7, __HV_DECL6(__VA_ARGS__)
+#define __HV_DECL8(t8, a8, ...) t8 a8, __HV_DECL7(__VA_ARGS__)
+#define __HV_DECL9(t9, a9, ...) t9 a9, __HV_DECL8(__VA_ARGS__)
+#define __HV_PASS1(t1, a1)	a1
+#define __HV_PASS2(t2, a2, ...) a2, __HV_PASS1(__VA_ARGS__)
+#define __HV_PASS3(t3, a3, ...) a3, __HV_PASS2(__VA_ARGS__)
+#define __HV_PASS4(t4, a4, ...) a4, __HV_PASS3(__VA_ARGS__)
+#define __HV_PASS5(t5, a5, ...) a5, __HV_PASS4(__VA_ARGS__)
+#define __HV_PASS6(t6, a6, ...) a6, __HV_PASS5(__VA_ARGS__)
+#define __HV_PASS7(t7, a7, ...) a7, __HV_PASS6(__VA_ARGS__)
+#define __HV_PASS8(t8, a8, ...) a8, __HV_PASS7(__VA_ARGS__)
+#define __HV_PASS9(t9, a9, ...) a9, __HV_PASS8(__VA_ARGS__)
+#define HV_WRAPx(x, type, name, ...)				\
+	type name(__HV_DECL##x(__VA_ARGS__));			\
+	type name(__HV_DECL##x(__VA_ARGS__))			\
+	{							\
+		return _##name(__HV_PASS##x(__VA_ARGS__));	\
+	}
+#define HV_WRAP1(type, name, ...) HV_WRAPx(1, type, name, __VA_ARGS__)
+#define HV_WRAP2(type, name, ...) HV_WRAPx(2, type, name, __VA_ARGS__)
+#define HV_WRAP3(type, name, ...) HV_WRAPx(3, type, name, __VA_ARGS__)
+#define HV_WRAP4(type, name, ...) HV_WRAPx(4, type, name, __VA_ARGS__)
+#define HV_WRAP5(type, name, ...) HV_WRAPx(5, type, name, __VA_ARGS__)
+#define HV_WRAP6(type, name, ...) HV_WRAPx(6, type, name, __VA_ARGS__)
+#define HV_WRAP7(type, name, ...) HV_WRAPx(7, type, name, __VA_ARGS__)
+#define HV_WRAP8(type, name, ...) HV_WRAPx(8, type, name, __VA_ARGS__)
+#define HV_WRAP9(type, name, ...) HV_WRAPx(9, type, name, __VA_ARGS__)
+
+/* List all the hypervisor API functions. */
+HV_WRAP4(void, hv_init, HV_VersionNumber, interface_version_number,
+	 int, chip_num, int, chip_rev_num, int, client_pl)
+HV_WRAP1(long, hv_sysconf, HV_SysconfQuery, query)
+HV_WRAP3(int, hv_confstr, HV_ConfstrQuery, query, HV_VirtAddr, buf, int, len)
+#if CHIP_HAS_IPI()
+HV_WRAP3(int, hv_get_ipi_pte, HV_Coord, tile, int, pl, HV_PTE*, pte)
+HV_WRAP3(int, hv_console_set_ipi, int, ipi, int, event, HV_Coord, coord);
+#else
+HV_WRAP1(void, hv_enable_intr, HV_IntrMask, enab_mask)
+HV_WRAP1(void, hv_disable_intr, HV_IntrMask, disab_mask)
+HV_WRAP1(void, hv_clear_intr, HV_IntrMask, clear_mask)
+HV_WRAP1(void, hv_raise_intr, HV_IntrMask, raise_mask)
+HV_WRAP2(HV_Errno, hv_trigger_ipi, HV_Coord, tile, int, interrupt)
+#endif /* !CHIP_HAS_IPI() */
+HV_WRAP3(int, hv_store_mapping, HV_VirtAddr, va, unsigned int, len,
+	 HV_PhysAddr, pa)
+HV_WRAP2(HV_PhysAddr, hv_inquire_realpa, HV_PhysAddr, cpa, unsigned int, len)
+HV_WRAP0(HV_RTCTime, hv_get_rtc)
+HV_WRAP1(void, hv_set_rtc, HV_RTCTime, time)
+HV_WRAP4(int, hv_install_context, HV_PhysAddr, page_table, HV_PTE, access,
+	 HV_ASID, asid, __hv32, flags)
+HV_WRAP2(int, hv_set_pte_super_shift, int, level, int, log2_count)
+HV_WRAP0(HV_Context, hv_inquire_context)
+HV_WRAP1(int, hv_flush_asid, HV_ASID, asid)
+HV_WRAP2(int, hv_flush_page, HV_VirtAddr, address, HV_PageSize, page_size)
+HV_WRAP3(int, hv_flush_pages, HV_VirtAddr, start, HV_PageSize, page_size,
+	 unsigned long, size)
+HV_WRAP1(int, hv_flush_all, int, preserve_global)
+HV_WRAP2(void, hv_restart, HV_VirtAddr, cmd, HV_VirtAddr, args)
+HV_WRAP0(void, hv_halt)
+HV_WRAP0(void, hv_power_off)
+HV_WRAP1(int, hv_reexec, HV_PhysAddr, entry)
+HV_WRAP0(HV_Topology, hv_inquire_topology)
+HV_WRAP3(HV_Errno, hv_inquire_tiles, HV_InqTileSet, set, HV_VirtAddr, cpumask,
+	 int, length)
+HV_WRAP1(HV_PhysAddrRange, hv_inquire_physical, int, idx)
+HV_WRAP2(HV_MemoryControllerInfo, hv_inquire_memory_controller, HV_Coord, coord,
+	 int, controller)
+HV_WRAP1(HV_VirtAddrRange, hv_inquire_virtual, int, idx)
+HV_WRAP1(HV_ASIDRange, hv_inquire_asid, int, idx)
+HV_WRAP1(void, hv_nanosleep, int, nanosecs)
+HV_WRAP0(int, hv_console_read_if_ready)
+HV_WRAP1(void, hv_console_putc, int, byte)
+HV_WRAP2(int, hv_console_write, HV_VirtAddr, bytes, int, len)
+HV_WRAP0(void, hv_downcall_dispatch)
+HV_WRAP1(int, hv_fs_findfile, HV_VirtAddr, filename)
+HV_WRAP1(HV_FS_StatInfo, hv_fs_fstat, int, inode)
+HV_WRAP4(int, hv_fs_pread, int, inode, HV_VirtAddr, buf,
+	 int, length, int, offset)
+HV_WRAP2(unsigned long long, hv_physaddr_read64, HV_PhysAddr, addr,
+	 HV_PTE, access)
+HV_WRAP3(void, hv_physaddr_write64, HV_PhysAddr, addr, HV_PTE, access,
+	 unsigned long long, val)
+HV_WRAP2(int, hv_get_command_line, HV_VirtAddr, buf, int, length)
+HV_WRAP2(HV_Errno, hv_set_command_line, HV_VirtAddr, buf, int, length)
+HV_WRAP1(void, hv_set_caching, unsigned long, bitmask)
+HV_WRAP2(void, hv_bzero_page, HV_VirtAddr, va, unsigned int, size)
+HV_WRAP1(HV_Errno, hv_register_message_state, HV_MsgState*, msgstate)
+HV_WRAP4(int, hv_send_message, HV_Recipient *, recips, int, nrecip,
+	 HV_VirtAddr, buf, int, buflen)
+HV_WRAP3(HV_RcvMsgInfo, hv_receive_message, HV_MsgState, msgstate,
+	 HV_VirtAddr, buf, int, buflen)
+HV_WRAP0(void, hv_start_all_tiles)
+HV_WRAP2(int, hv_dev_open, HV_VirtAddr, name, __hv32, flags)
+HV_WRAP1(int, hv_dev_close, int, devhdl)
+HV_WRAP5(int, hv_dev_pread, int, devhdl, __hv32, flags, HV_VirtAddr, va,
+	 __hv32, len, __hv64, offset)
+HV_WRAP5(int, hv_dev_pwrite, int, devhdl, __hv32, flags, HV_VirtAddr, va,
+	 __hv32, len, __hv64, offset)
+HV_WRAP3(int, hv_dev_poll, int, devhdl, __hv32, events, HV_IntArg, intarg)
+HV_WRAP1(int, hv_dev_poll_cancel, int, devhdl)
+HV_WRAP6(int, hv_dev_preada, int, devhdl, __hv32, flags, __hv32, sgl_len,
+	 HV_SGL *, sglp, __hv64, offset, HV_IntArg, intarg)
+HV_WRAP6(int, hv_dev_pwritea, int, devhdl, __hv32, flags, __hv32, sgl_len,
+	 HV_SGL *, sglp, __hv64, offset, HV_IntArg, intarg)
+HV_WRAP9(int, hv_flush_remote, HV_PhysAddr, cache_pa,
+	 unsigned long, cache_control, unsigned long*, cache_cpumask,
+	 HV_VirtAddr, tlb_va, unsigned long, tlb_length,
+	 unsigned long, tlb_pgsize, unsigned long*, tlb_cpumask,
+	 HV_Remote_ASID*, asids, int, asidcount)
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index cb52d66..9c0c3cb 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -28,10 +28,6 @@
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
 
-#ifdef CONFIG_PREEMPT
-# error "No support for kernel preemption currently"
-#endif
-
 #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
 
 #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR)
@@ -762,7 +758,7 @@ intvec_\vecname:
 	.macro  dc_dispatch vecnum, vecname
 	.org    (\vecnum << 8)
 intvec_\vecname:
-	j       hv_downcall_dispatch
+	j       _hv_downcall_dispatch
 	ENDPROC(intvec_\vecname)
 	.endm
 
@@ -812,17 +808,34 @@ STD_ENTRY(interrupt_return)
 	}
 	lw      r29, r29
 	andi    r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
+	bzt     r29, .Lresume_userspace
+
+#ifdef CONFIG_PREEMPT
+	/* Returning to kernel space. Check if we need preemption. */
+	GET_THREAD_INFO(r29)
+	addli   r28, r29, THREAD_INFO_FLAGS_OFFSET
 	{
-	 bzt    r29, .Lresume_userspace
-	 PTREGS_PTR(r29, PTREGS_OFFSET_PC)
+	 lw     r28, r28
+	 addli  r29, r29, THREAD_INFO_PREEMPT_COUNT_OFFSET
+	}
+	{
+	 andi   r28, r28, _TIF_NEED_RESCHED
+	 lw     r29, r29
 	}
+	bzt     r28, 1f
+	bnz     r29, 1f
+	jal     preempt_schedule_irq
+	FEEDBACK_REENTER(interrupt_return)
+1:
+#endif
 
 	/* If we're resuming to _cpu_idle_nap, bump PC forward by 8. */
 	{
-	 lw     r28, r29
+	 PTREGS_PTR(r29, PTREGS_OFFSET_PC)
 	 moveli r27, lo16(_cpu_idle_nap)
 	}
 	{
+	 lw     r28, r29
 	 auli   r27, r27, ha16(_cpu_idle_nap)
 	}
 	{
@@ -1420,7 +1433,6 @@ handle_ill:
 	{
 	 lw     r0, r0          /* indirect thru thread_info to get task_info*/
 	 addi   r1, sp, C_ABI_SAVE_AREA_SIZE  /* put ptregs pointer into r1 */
-	 move   r2, zero        /* load error code into r2 */
 	}
 
 	jal     send_sigtrap    /* issue a SIGTRAP */
@@ -1609,7 +1621,7 @@ ENTRY(sys_cmpxchg)
 	  * Because of C pointer arithmetic, we want to compute this:
 	  *
 	  * ((char*)atomic_locks +
-	  *  (((r0 >> 3) & (1 << (ATOMIC_HASH_SIZE - 1))) << 2))
+	  *  (((r0 >> 3) & ((1 << ATOMIC_HASH_SHIFT) - 1)) << 2))
 	  *
 	  * Instead of two shifts we just ">> 1", and use 'mm'
 	  * to ignore the low and high bits we don't want.
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index 85d4839..99f8e9a 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -17,21 +17,19 @@
 #include <linux/linkage.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
+#include <linux/init.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 #include <asm/irqflags.h>
 #include <asm/asm-offsets.h>
 #include <asm/types.h>
+#include <asm/traps.h>
 #include <asm/signal.h>
 #include <hv/hypervisor.h>
 #include <arch/abi.h>
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
 
-#ifdef CONFIG_PREEMPT
-# error "No support for kernel preemption currently"
-#endif
-
 #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
 
 #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR)
@@ -98,6 +96,189 @@
 	}
 	.endm
 
+	/*
+	 * Unalign data exception fast handling: In order to handle
+	 * unaligned data access, a fast JIT version is generated and stored
+	 * in a specific area in user space. We first need to do a quick poke
+	 * to see if the JIT is available. We use certain bits in the fault
+	 * PC (3 to 9 is used for 16KB page size) as index to address the JIT
+	 * code area. The first 64bit word is the fault PC, and the 2nd one is
+	 * the fault bundle itself. If these 2 words both match, then we
+	 * directly "iret" to JIT code. If not, a slow path is invoked to
+	 * generate new JIT code. Note: the current JIT code WILL be
+	 * overwritten if it existed. So, ideally we can handle 128 unalign
+	 * fixups via JIT. For lookup efficiency and to effectively support
+	 * tight loops with multiple unaligned reference, a simple
+	 * direct-mapped cache is used.
+	 *
+	 * SPR_EX_CONTEXT_K_0 is modified to return to JIT code.
+	 * SPR_EX_CONTEXT_K_1 has ICS set.
+	 * SPR_EX_CONTEXT_0_0 is setup to user program's next PC.
+	 * SPR_EX_CONTEXT_0_1 = 0.
+	 */
+	.macro int_hand_unalign_fast  vecnum, vecname
+	.org  (\vecnum << 8)
+intvec_\vecname:
+	/* Put r3 in SPR_SYSTEM_SAVE_K_1.  */
+	mtspr   SPR_SYSTEM_SAVE_K_1, r3
+
+	mfspr   r3, SPR_EX_CONTEXT_K_1
+	/*
+	 * Examine if exception comes from user without ICS set.
+	 * If not, just go directly to the slow path.
+	 */
+	bnez    r3, hand_unalign_slow_nonuser
+
+	mfspr   r3, SPR_SYSTEM_SAVE_K_0
+
+	/* Get &thread_info->unalign_jit_tmp[0] in r3. */
+	mm      r3, zero, LOG2_THREAD_SIZE, 63
+#if THREAD_SIZE < 65536
+	addli   r3, r3, -(PAGE_SIZE - THREAD_INFO_UNALIGN_JIT_TMP_OFFSET)
+#else
+	addli   r3, r3, -(PAGE_SIZE/2)
+	addli   r3, r3, -(PAGE_SIZE/2 - THREAD_INFO_UNALIGN_JIT_TMP_OFFSET)
+#endif
+
+	/*
+	 * Save r0, r1, r2 into thread_info array r3 points to
+	 * from low to high memory in order.
+	 */
+	st_add  r3, r0, 8
+	st_add  r3, r1, 8
+	{
+	 st_add r3, r2, 8
+	 andi   r2, sp, 7
+	}
+
+	/* Save stored r3 value so we can revert it on a page fault. */
+	mfspr   r1, SPR_SYSTEM_SAVE_K_1
+	st      r3, r1
+
+	{
+	 /* Generate a SIGBUS if sp is not 8-byte aligned. */
+	 bnez   r2, hand_unalign_slow_badsp
+	}
+
+	/*
+	 * Get the thread_info in r0; load r1 with pc. Set the low bit of sp
+	 * as an indicator to the page fault code in case we fault.
+	 */
+	{
+	 ori    sp, sp, 1
+	 mfspr  r1, SPR_EX_CONTEXT_K_0
+	}
+
+	/* Add the jit_info offset in thread_info; extract r1 [3:9] into r2. */
+	{
+	 addli  r0, r3, THREAD_INFO_UNALIGN_JIT_BASE_OFFSET - \
+	  (THREAD_INFO_UNALIGN_JIT_TMP_OFFSET + (3 * 8))
+	 bfextu r2, r1, 3, (2 + PAGE_SHIFT - UNALIGN_JIT_SHIFT)
+	}
+
+	/* Load the jit_info; multiply r2 by 128. */
+	{
+	 ld     r0, r0
+	 shli   r2, r2, UNALIGN_JIT_SHIFT
+	}
+
+	/*
+	 * If r0 is NULL, the JIT page is not mapped, so go to slow path;
+	 * add offset r2 to r0 at the same time.
+	 */
+	{
+	 beqz   r0, hand_unalign_slow
+	 add    r2, r0, r2
+	}
+
+        /*
+	 * We are loading from userspace (both the JIT info PC and
+	 * instruction word, and the instruction word we executed)
+	 * and since either could fault while holding the interrupt
+	 * critical section, we must tag this region and check it in
+	 * do_page_fault() to handle it properly.
+	 */
+ENTRY(__start_unalign_asm_code)
+
+	/* Load first word of JIT in r0 and increment r2 by 8. */
+	ld_add  r0, r2, 8
+
+	/*
+	 * Compare the PC with the 1st word in JIT; load the fault bundle
+	 * into r1.
+	 */
+	{
+	 cmpeq  r0, r0, r1
+	 ld     r1, r1
+	}
+
+	/* Go to slow path if PC doesn't match. */
+	beqz    r0, hand_unalign_slow
+
+	/*
+	 * Load the 2nd word of JIT, which is supposed to be the fault
+	 * bundle for a cache hit. Increment r2; after this bundle r2 will
+	 * point to the potential start of the JIT code we want to run.
+	 */
+	ld_add  r0, r2, 8
+
+	/* No further accesses to userspace are done after this point. */
+ENTRY(__end_unalign_asm_code)
+
+	/* Compare the real bundle with what is saved in the JIT area. */
+	{
+	 cmpeq  r0, r1, r0
+	 mtspr  SPR_EX_CONTEXT_0_1, zero
+	}
+
+	/* Go to slow path if the fault bundle does not match. */
+	beqz    r0, hand_unalign_slow
+
+	/*
+	 * A cache hit is found.
+	 * r2 points to start of JIT code (3rd word).
+	 * r0 is the fault pc.
+	 * r1 is the fault bundle.
+	 * Reset the low bit of sp.
+	 */
+	{
+	 mfspr  r0, SPR_EX_CONTEXT_K_0
+	 andi   sp, sp, ~1
+	}
+
+	/* Write r2 into EX_CONTEXT_K_0 and increment PC. */
+	{
+	 mtspr  SPR_EX_CONTEXT_K_0, r2
+	 addi   r0, r0, 8
+	}
+
+	/*
+	 * Set ICS on kernel EX_CONTEXT_K_1 in order to "iret" to
+	 * user with ICS set. This way, if the JIT fixup causes another
+	 * unalign exception (which shouldn't be possible) the user
+	 * process will be terminated with SIGBUS. Also, our fixup will
+	 * run without interleaving with external interrupts.
+	 * Each fixup is at most 14 bundles, so it won't hold ICS for long.
+	 */
+	{
+	 movei  r1, PL_ICS_EX1(USER_PL, 1)
+	 mtspr  SPR_EX_CONTEXT_0_0, r0
+	}
+
+	{
+	 mtspr  SPR_EX_CONTEXT_K_1, r1
+	 addi   r3, r3, -(3 * 8)
+	}
+
+	/* Restore r0..r3. */
+	ld_add  r0, r3, 8
+	ld_add  r1, r3, 8
+	ld_add  r2, r3, 8
+	ld      r3, r3
+
+	iret
+	ENDPROC(intvec_\vecname)
+	.endm
 
 #ifdef __COLLECT_LINKER_FEEDBACK__
 	.pushsection .text.intvec_feedback,"ax"
@@ -118,8 +299,7 @@ intvec_feedback:
 	 * The "processing" argument specifies the code for processing
 	 * the interrupt. Defaults to "handle_interrupt".
 	 */
-	.macro  int_hand vecnum, vecname, c_routine, processing=handle_interrupt
-	.org    (\vecnum << 8)
+	.macro __int_hand vecnum, vecname, c_routine,processing=handle_interrupt
 intvec_\vecname:
 	/* Temporarily save a register so we have somewhere to work. */
 
@@ -305,7 +485,7 @@ intvec_\vecname:
 	mfspr   r3, SPR_SYSTEM_SAVE_K_2   /* info about page fault */
 	.else
 	.ifc \vecnum, INT_ILL_TRANS
-	mfspr   r2, ILL_TRANS_REASON
+	mfspr   r2, ILL_VA_PC
 	.else
 	.ifc \vecnum, INT_DOUBLE_FAULT
 	mfspr   r2, SPR_SYSTEM_SAVE_K_2   /* double fault info from HV */
@@ -585,7 +765,7 @@ intvec_\vecname:
 	.macro  dc_dispatch vecnum, vecname
 	.org    (\vecnum << 8)
 intvec_\vecname:
-	j       hv_downcall_dispatch
+	j       _hv_downcall_dispatch
 	ENDPROC(intvec_\vecname)
 	.endm
 
@@ -629,11 +809,33 @@ STD_ENTRY(interrupt_return)
 	andi    r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
 	{
 	 beqzt  r29, .Lresume_userspace
-	 PTREGS_PTR(r29, PTREGS_OFFSET_PC)
+	 move   r29, sp
 	}
 
+#ifdef CONFIG_PREEMPT
+	/* Returning to kernel space. Check if we need preemption. */
+	EXTRACT_THREAD_INFO(r29)
+	addli   r28, r29, THREAD_INFO_FLAGS_OFFSET
+	{
+	 ld     r28, r28
+	 addli  r29, r29, THREAD_INFO_PREEMPT_COUNT_OFFSET
+	}
+	{
+	 andi   r28, r28, _TIF_NEED_RESCHED
+	 ld4s   r29, r29
+	}
+	beqzt   r28, 1f
+	bnez    r29, 1f
+	jal     preempt_schedule_irq
+	FEEDBACK_REENTER(interrupt_return)
+1:
+#endif
+
 	/* If we're resuming to _cpu_idle_nap, bump PC forward by 8. */
-	moveli  r27, hw2_last(_cpu_idle_nap)
+	{
+	 moveli r27, hw2_last(_cpu_idle_nap)
+	 PTREGS_PTR(r29, PTREGS_OFFSET_PC)
+	}
 	{
 	 ld     r28, r29
 	 shl16insli r27, r27, hw1(_cpu_idle_nap)
@@ -1223,10 +1425,31 @@ STD_ENTRY(_sys_clone)
 	j       sys_clone
 	STD_ENDPROC(_sys_clone)
 
-/* The single-step support may need to read all the registers. */
+	/*
+	 * Recover r3, r2, r1 and r0 here saved by unalign fast vector.
+	 * The vector area limit is 32 bundles, so we handle the reload here.
+	 * r0, r1, r2 are in thread_info from low to high memory in order.
+	 * r3 points to location the original r3 was saved.
+	 * We put this code in the __HEAD section so it can be reached
+	 * via a conditional branch from the fast path.
+	 */
+	__HEAD
+hand_unalign_slow:
+	andi    sp, sp, ~1
+hand_unalign_slow_badsp:
+	addi    r3, r3, -(3 * 8)
+	ld_add  r0, r3, 8
+	ld_add  r1, r3, 8
+	ld      r2, r3
+hand_unalign_slow_nonuser:
+	mfspr   r3, SPR_SYSTEM_SAVE_K_1
+	__int_hand     INT_UNALIGN_DATA, UNALIGN_DATA_SLOW, int_unalign
+
+/* The unaligned data support needs to read all the registers. */
 int_unalign:
 	push_extra_callee_saves r0
-	j       do_trap
+	j       do_unaligned
+ENDPROC(hand_unalign_slow)
 
 /* Fill the return address stack with nonzero entries. */
 STD_ENTRY(fill_ra_stack)
@@ -1240,6 +1463,11 @@ STD_ENTRY(fill_ra_stack)
 4:	jrp	r0
 	STD_ENDPROC(fill_ra_stack)
 
+	.macro int_hand  vecnum, vecname, c_routine, processing=handle_interrupt
+	.org   (\vecnum << 8)
+		__int_hand   \vecnum, \vecname, \c_routine, \processing
+	.endm
+
 /* Include .intrpt1 array of interrupt vectors */
 	.section ".intrpt1", "ax"
 
@@ -1272,7 +1500,7 @@ STD_ENTRY(fill_ra_stack)
 	int_hand     INT_SWINT_1, SWINT_1, SYSCALL, handle_syscall
 	int_hand     INT_SWINT_0, SWINT_0, do_trap
 	int_hand     INT_ILL_TRANS, ILL_TRANS, do_trap
-	int_hand     INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign
+	int_hand_unalign_fast INT_UNALIGN_DATA, UNALIGN_DATA
 	int_hand     INT_DTLB_MISS, DTLB_MISS, do_page_fault
 	int_hand     INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault
 	int_hand     INT_IDN_FIREWALL, IDN_FIREWALL, do_hardwall_trap
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c
index 3ccf2cd..19c0706 100644
--- a/arch/tile/kernel/irq.c
+++ b/arch/tile/kernel/irq.c
@@ -74,6 +74,7 @@ static DEFINE_SPINLOCK(available_irqs_lock);
 /*
  * The interrupt handling path, implemented in terms of HV interrupt
  * emulation on TILE64 and TILEPro, and IPI hardware on TILE-Gx.
+ * Entered with interrupts disabled.
  */
 void tile_dev_intr(struct pt_regs *regs, int intnum)
 {
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c
index b9fe80e..d94f487 100644
--- a/arch/tile/kernel/pci-dma.c
+++ b/arch/tile/kernel/pci-dma.c
@@ -36,8 +36,9 @@ static void *tile_dma_alloc_coherent(struct device *dev, size_t size,
 				     dma_addr_t *dma_handle, gfp_t gfp,
 				     struct dma_attrs *attrs)
 {
-	u64 dma_mask = dev->coherent_dma_mask ?: DMA_BIT_MASK(32);
-	int node = dev_to_node(dev);
+	u64 dma_mask = (dev && dev->coherent_dma_mask) ?
+		dev->coherent_dma_mask : DMA_BIT_MASK(32);
+	int node = dev ? dev_to_node(dev) : 0;
 	int order = get_order(size);
 	struct page *pg;
 	dma_addr_t addr;
@@ -256,7 +257,7 @@ static void tile_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
 	BUG_ON(!valid_dma_direction(direction));
 
 	__dma_complete_page(pfn_to_page(PFN_DOWN(dma_address)),
-			    dma_address & PAGE_OFFSET, size, direction);
+			    dma_address & (PAGE_SIZE - 1), size, direction);
 }
 
 static void tile_dma_sync_single_for_cpu(struct device *dev,
@@ -357,7 +358,7 @@ static void *tile_pci_dma_alloc_coherent(struct device *dev, size_t size,
 
 	addr = page_to_phys(pg);
 
-	*dma_handle = phys_to_dma(dev, addr);
+	*dma_handle = addr + get_dma_offset(dev);
 
 	return page_address(pg);
 }
@@ -387,7 +388,7 @@ static int tile_pci_dma_map_sg(struct device *dev, struct scatterlist *sglist,
 		sg->dma_address = sg_phys(sg);
 		__dma_prep_pa_range(sg->dma_address, sg->length, direction);
 
-		sg->dma_address = phys_to_dma(dev, sg->dma_address);
+		sg->dma_address = sg->dma_address + get_dma_offset(dev);
 #ifdef CONFIG_NEED_SG_DMA_LENGTH
 		sg->dma_length = sg->length;
 #endif
@@ -422,7 +423,7 @@ static dma_addr_t tile_pci_dma_map_page(struct device *dev, struct page *page,
 	BUG_ON(offset + size > PAGE_SIZE);
 	__dma_prep_page(page, offset, size, direction);
 
-	return phys_to_dma(dev, page_to_pa(page) + offset);
+	return page_to_pa(page) + offset + get_dma_offset(dev);
 }
 
 static void tile_pci_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
@@ -432,10 +433,10 @@ static void tile_pci_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
 {
 	BUG_ON(!valid_dma_direction(direction));
 
-	dma_address = dma_to_phys(dev, dma_address);
+	dma_address -= get_dma_offset(dev);
 
 	__dma_complete_page(pfn_to_page(PFN_DOWN(dma_address)),
-			    dma_address & PAGE_OFFSET, size, direction);
+			    dma_address & (PAGE_SIZE - 1), size, direction);
 }
 
 static void tile_pci_dma_sync_single_for_cpu(struct device *dev,
@@ -445,7 +446,7 @@ static void tile_pci_dma_sync_single_for_cpu(struct device *dev,
 {
 	BUG_ON(!valid_dma_direction(direction));
 
-	dma_handle = dma_to_phys(dev, dma_handle);
+	dma_handle -= get_dma_offset(dev);
 
 	__dma_complete_pa_range(dma_handle, size, direction);
 }
@@ -456,7 +457,7 @@ static void tile_pci_dma_sync_single_for_device(struct device *dev,
 						enum dma_data_direction
 						direction)
 {
-	dma_handle = dma_to_phys(dev, dma_handle);
+	dma_handle -= get_dma_offset(dev);
 
 	__dma_prep_pa_range(dma_handle, size, direction);
 }
@@ -558,21 +559,43 @@ static struct dma_map_ops pci_swiotlb_dma_ops = {
 	.mapping_error = swiotlb_dma_mapping_error,
 };
 
+static struct dma_map_ops pci_hybrid_dma_ops = {
+	.alloc = tile_swiotlb_alloc_coherent,
+	.free = tile_swiotlb_free_coherent,
+	.map_page = tile_pci_dma_map_page,
+	.unmap_page = tile_pci_dma_unmap_page,
+	.map_sg = tile_pci_dma_map_sg,
+	.unmap_sg = tile_pci_dma_unmap_sg,
+	.sync_single_for_cpu = tile_pci_dma_sync_single_for_cpu,
+	.sync_single_for_device = tile_pci_dma_sync_single_for_device,
+	.sync_sg_for_cpu = tile_pci_dma_sync_sg_for_cpu,
+	.sync_sg_for_device = tile_pci_dma_sync_sg_for_device,
+	.mapping_error = tile_pci_dma_mapping_error,
+	.dma_supported = tile_pci_dma_supported
+};
+
 struct dma_map_ops *gx_legacy_pci_dma_map_ops = &pci_swiotlb_dma_ops;
+struct dma_map_ops *gx_hybrid_pci_dma_map_ops = &pci_hybrid_dma_ops;
 #else
 struct dma_map_ops *gx_legacy_pci_dma_map_ops;
+struct dma_map_ops *gx_hybrid_pci_dma_map_ops;
 #endif
 EXPORT_SYMBOL(gx_legacy_pci_dma_map_ops);
+EXPORT_SYMBOL(gx_hybrid_pci_dma_map_ops);
 
 #ifdef CONFIG_ARCH_HAS_DMA_SET_COHERENT_MASK
 int dma_set_coherent_mask(struct device *dev, u64 mask)
 {
 	struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
-	/* Handle legacy PCI devices with limited memory addressability. */
-	if (((dma_ops == gx_pci_dma_map_ops) ||
-	    (dma_ops == gx_legacy_pci_dma_map_ops)) &&
+	/* Handle hybrid PCI devices with limited memory addressability. */
+	if ((dma_ops == gx_pci_dma_map_ops ||
+	     dma_ops == gx_hybrid_pci_dma_map_ops ||
+	     dma_ops == gx_legacy_pci_dma_map_ops) &&
 	    (mask <= DMA_BIT_MASK(32))) {
+		if (dma_ops == gx_pci_dma_map_ops)
+			set_dma_ops(dev, gx_hybrid_pci_dma_map_ops);
+
 		if (mask > dev->archdata.max_direct_dma_addr)
 			mask = dev->archdata.max_direct_dma_addr;
 	}
@@ -584,3 +607,21 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
 }
 EXPORT_SYMBOL(dma_set_coherent_mask);
 #endif
+
+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
+/*
+ * The generic dma_get_required_mask() uses the highest physical address
+ * (max_pfn) to provide the hint to the PCI drivers regarding 32-bit or
+ * 64-bit DMA configuration. Since TILEGx has I/O TLB/MMU, allowing the
+ * DMAs to use the full 64-bit PCI address space and not limited by
+ * the physical memory space, we always let the PCI devices use
+ * 64-bit DMA if they have that capability, by returning the 64-bit
+ * DMA mask here. The device driver has the option to use 32-bit DMA if
+ * the device is not capable of 64-bit DMA.
+ */
+u64 dma_get_required_mask(struct device *dev)
+{
+	return DMA_BIT_MASK(64);
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+#endif
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 67237d3..af75835 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -20,7 +20,6 @@
 #include <linux/capability.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bootmem.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
@@ -52,6 +51,8 @@
  *
  */
 
+static int pci_probe = 1;
+
 /*
  * This flag tells if the platform is TILEmpower that needs
  * special configuration for the PLX switch chip.
@@ -144,6 +145,11 @@ int __init tile_pci_init(void)
 {
 	int i;
 
+	if (!pci_probe) {
+		pr_info("PCI: disabled by boot argument\n");
+		return 0;
+	}
+
 	pr_info("PCI: Searching for controllers...\n");
 
 	/* Re-init number of PCIe controllers to support hot-plug feature. */
@@ -192,7 +198,6 @@ int __init tile_pci_init(void)
 			controller->hv_cfg_fd[0] = hv_cfg_fd0;
 			controller->hv_cfg_fd[1] = hv_cfg_fd1;
 			controller->hv_mem_fd = hv_mem_fd;
-			controller->first_busno = 0;
 			controller->last_busno = 0xff;
 			controller->ops = &tile_cfg_ops;
 
@@ -283,7 +288,7 @@ int __init pcibios_init(void)
 	 * known to require at least 20ms here, but we use a more
 	 * conservative value.
 	 */
-	mdelay(250);
+	msleep(250);
 
 	/* Scan all of the recorded PCI controllers.  */
 	for (i = 0; i < TILE_NUM_PCIE; i++) {
@@ -304,18 +309,10 @@ int __init pcibios_init(void)
 
 			pr_info("PCI: initializing controller #%d\n", i);
 
-			/*
-			 * This comes from the generic Linux PCI driver.
-			 *
-			 * It reads the PCI tree for this bus into the Linux
-			 * data structures.
-			 *
-			 * This is inlined in linux/pci.h and calls into
-			 * pci_scan_bus_parented() in probe.c.
-			 */
 			pci_add_resource(&resources, &ioport_resource);
 			pci_add_resource(&resources, &iomem_resource);
-			bus = pci_scan_root_bus(NULL, 0, controller->ops, controller, &resources);
+			bus = pci_scan_root_bus(NULL, 0, controller->ops,
+						controller, &resources);
 			controller->root_bus = bus;
 			controller->last_busno = bus->busn_res.end;
 		}
@@ -388,6 +385,16 @@ void pcibios_set_master(struct pci_dev *dev)
 	/* No special bus mastering setup handling. */
 }
 
+/* Process any "pci=" kernel boot arguments. */
+char * __init pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	}
+	return str;
+}
+
 /*
  * Enable memory and/or address decoding, as appropriate, for the
  * device described by the 'dev' struct.
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index 1142563..4843881 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -69,19 +69,32 @@ static int pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
  * a HW PCIe link-training bug. The exact delay is specified with
  * a kernel boot argument in the form of "pcie_rc_delay=T,P,S",
  * where T is the TRIO instance number, P is the port number and S is
- * the delay in seconds. If the delay is not provided, the value
- * will be DEFAULT_RC_DELAY.
+ * the delay in seconds. If the argument is specified, but the delay is
+ * not provided, the value will be DEFAULT_RC_DELAY.
  */
 static int rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
 
 /* Default number of seconds that the PCIe RC port probe can be delayed. */
 #define DEFAULT_RC_DELAY	10
 
-/* Max number of seconds that the PCIe RC port probe can be delayed. */
-#define MAX_RC_DELAY		20
+/* The PCI I/O space size in each PCI domain. */
+#define IO_SPACE_SIZE		0x10000
+
+/* Provide shorter versions of some very long constant names. */
+#define AUTO_CONFIG_RC	\
+	TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC
+#define AUTO_CONFIG_RC_G1	\
+	TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1
+#define AUTO_CONFIG_EP	\
+	TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT
+#define AUTO_CONFIG_EP_G1	\
+	TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1
 
 /* Array of the PCIe ports configuration info obtained from the BIB. */
-struct pcie_port_property pcie_ports[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+struct pcie_trio_ports_property pcie_ports[TILEGX_NUM_TRIO];
+
+/* Number of configured TRIO instances. */
+int num_trio_shims;
 
 /* All drivers share the TRIO contexts defined here. */
 gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
@@ -89,24 +102,21 @@ gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
 /* Pointer to an array of PCIe RC controllers. */
 struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
 int num_rc_controllers;
-static int num_ep_controllers;
 
 static struct pci_ops tile_cfg_ops;
 
 /* Mask of CPUs that should receive PCIe interrupts. */
 static struct cpumask intr_cpus_map;
 
-/*
- * We don't need to worry about the alignment of resources.
- */
+/* We don't need to worry about the alignment of resources. */
 resource_size_t pcibios_align_resource(void *data, const struct resource *res,
-				resource_size_t size, resource_size_t align)
+				       resource_size_t size,
+				       resource_size_t align)
 {
 	return res->start;
 }
 EXPORT_SYMBOL(pcibios_align_resource);
 
-
 /*
  * Pick a CPU to receive and handle the PCIe interrupts, based on the IRQ #.
  * For now, we simply send interrupts to non-dataplane CPUs.
@@ -134,24 +144,19 @@ static int tile_irq_cpu(int irq)
 	return cpu;
 }
 
-/*
- * Open a file descriptor to the TRIO shim.
- */
+/* Open a file descriptor to the TRIO shim. */
 static int tile_pcie_open(int trio_index)
 {
 	gxio_trio_context_t *context = &trio_contexts[trio_index];
 	int ret;
+	int mac;
 
-	/*
-	 * This opens a file descriptor to the TRIO shim.
-	 */
+	/* This opens a file descriptor to the TRIO shim. */
 	ret = gxio_trio_init(context, trio_index);
 	if (ret < 0)
-		return ret;
+		goto gxio_trio_init_failure;
 
-	/*
-	 * Allocate an ASID for the kernel.
-	 */
+	/* Allocate an ASID for the kernel. */
 	ret = gxio_trio_alloc_asids(context, 1, 0, 0);
 	if (ret < 0) {
 		pr_err("PCI: ASID alloc failure on TRIO %d, give up\n",
@@ -189,31 +194,97 @@ static int tile_pcie_open(int trio_index)
 	}
 #endif
 
+	/* Get the properties of the PCIe ports on this TRIO instance. */
+	ret = gxio_trio_get_port_property(context, &pcie_ports[trio_index]);
+	if (ret < 0) {
+		pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
+		       " on TRIO %d\n", ret, trio_index);
+		goto get_port_property_failure;
+	}
+
+	context->mmio_base_mac =
+		iorpc_ioremap(context->fd, 0, HV_TRIO_CONFIG_IOREMAP_SIZE);
+	if (context->mmio_base_mac == NULL) {
+		pr_err("PCI: TRIO config space mapping failure, error %d,"
+		       " on TRIO %d\n", ret, trio_index);
+		ret = -ENOMEM;
+
+		goto trio_mmio_mapping_failure;
+	}
+
+	/* Check the port strap state which will override the BIB setting. */
+	for (mac = 0; mac < TILEGX_TRIO_PCIES; mac++) {
+		TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
+		unsigned int reg_offset;
+
+		/* Ignore ports that are not specified in the BIB. */
+		if (!pcie_ports[trio_index].ports[mac].allow_rc &&
+		    !pcie_ports[trio_index].ports[mac].allow_ep)
+			continue;
+
+		reg_offset =
+			(TRIO_PCIE_INTFC_PORT_CONFIG <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		port_config.word =
+			__gxio_mmio_read(context->mmio_base_mac + reg_offset);
+
+		if (port_config.strap_state != AUTO_CONFIG_RC &&
+		    port_config.strap_state != AUTO_CONFIG_RC_G1) {
+			/*
+			 * If this is really intended to be an EP port, record
+			 * it so that the endpoint driver will know about it.
+			 */
+			if (port_config.strap_state == AUTO_CONFIG_EP ||
+			    port_config.strap_state == AUTO_CONFIG_EP_G1)
+				pcie_ports[trio_index].ports[mac].allow_ep = 1;
+		}
+	}
+
 	return ret;
 
+trio_mmio_mapping_failure:
+get_port_property_failure:
 asid_alloc_failure:
 #ifdef USE_SHARED_PCIE_CONFIG_REGION
 pio_alloc_failure:
 #endif
 	hv_dev_close(context->fd);
+gxio_trio_init_failure:
+	context->fd = -1;
 
 	return ret;
 }
 
-static void
-tilegx_legacy_irq_ack(struct irq_data *d)
+static int __init tile_trio_init(void)
+{
+	int i;
+
+	/* We loop over all the TRIO shims. */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		if (tile_pcie_open(i) < 0)
+			continue;
+		num_trio_shims++;
+	}
+
+	return 0;
+}
+postcore_initcall(tile_trio_init);
+
+static void tilegx_legacy_irq_ack(struct irq_data *d)
 {
 	__insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
 }
 
-static void
-tilegx_legacy_irq_mask(struct irq_data *d)
+static void tilegx_legacy_irq_mask(struct irq_data *d)
 {
 	__insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
 }
 
-static void
-tilegx_legacy_irq_unmask(struct irq_data *d)
+static void tilegx_legacy_irq_unmask(struct irq_data *d)
 {
 	__insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
 }
@@ -234,8 +305,7 @@ static struct irq_chip tilegx_legacy_irq_chip = {
  * to Linux which just calls handle_level_irq() after clearing the
  * MAC INTx Assert status bit associated with this interrupt.
  */
-static void
-trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
+static void trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
 {
 	struct pci_controller *controller = irq_desc_get_handler_data(desc);
 	gxio_trio_context_t *trio_context = controller->trio;
@@ -301,9 +371,7 @@ static int tile_init_irqs(struct pci_controller *controller)
 			goto free_irqs;
 		}
 
-		/*
-		 * Register the IRQ handler with the kernel.
-		 */
+		/* Register the IRQ handler with the kernel. */
 		irq_set_chip_and_handler(irq, &tilegx_legacy_irq_chip,
 					trio_handle_level_irq);
 		irq_set_chip_data(irq, (void *)(uint64_t)i);
@@ -320,14 +388,39 @@ free_irqs:
 }
 
 /*
+ * Return 1 if the port is strapped to operate in RC mode.
+ */
+static int
+strapped_for_rc(gxio_trio_context_t *trio_context, int mac)
+{
+	TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
+	unsigned int reg_offset;
+
+	/* Check the port configuration. */
+	reg_offset =
+		(TRIO_PCIE_INTFC_PORT_CONFIG <<
+			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+			TRIO_CFG_REGION_ADDR__INTFC_SHIFT) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+	port_config.word =
+		__gxio_mmio_read(trio_context->mmio_base_mac + reg_offset);
+
+	if (port_config.strap_state == AUTO_CONFIG_RC ||
+	    port_config.strap_state == AUTO_CONFIG_RC_G1)
+		return 1;
+	else
+		return 0;
+}
+
+/*
  * Find valid controllers and fill in pci_controller structs for each
  * of them.
  *
- * Returns the number of controllers discovered.
+ * Return the number of controllers discovered.
  */
 int __init tile_pci_init(void)
 {
-	int num_trio_shims = 0;
 	int ctl_index = 0;
 	int i, j;
 
@@ -338,64 +431,62 @@ int __init tile_pci_init(void)
 
 	pr_info("PCI: Searching for controllers...\n");
 
-	/*
-	 * We loop over all the TRIO shims.
-	 */
-	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
-		int ret;
-
-		ret = tile_pcie_open(i);
-		if (ret < 0)
-			continue;
-
-		num_trio_shims++;
-	}
-
 	if (num_trio_shims == 0 || sim_is_simulator())
 		return 0;
 
 	/*
-	 * Now determine which PCIe ports are configured to operate in RC mode.
-	 * We look at the Board Information Block first and then see if there
-	 * are any overriding configuration by the HW strapping pin.
+	 * Now determine which PCIe ports are configured to operate in RC
+	 * mode. There is a differece in the port configuration capability
+	 * between the Gx36 and Gx72 devices.
+	 *
+	 * The Gx36 has configuration capability for each of the 3 PCIe
+	 * interfaces (disable, auto endpoint, auto RC, etc.).
+	 * On the Gx72, you can only select one of the 3 PCIe interfaces per
+	 * TRIO to train automatically. Further, the allowable training modes
+	 * are reduced to four options (auto endpoint, auto RC, stream x1,
+	 * stream x4).
+	 *
+	 * For Gx36 ports, it must be allowed to be in RC mode by the
+	 * Board Information Block, and the hardware strapping pins must be
+	 * set to RC mode.
+	 *
+	 * For Gx72 ports, the port will operate in RC mode if either of the
+	 * following is true:
+	 * 1. It is allowed to be in RC mode by the Board Information Block,
+	 *    and the BIB doesn't allow the EP mode.
+	 * 2. It is allowed to be in either the RC or the EP mode by the BIB,
+	 *    and the hardware strapping pin is set to RC mode.
 	 */
 	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
 		gxio_trio_context_t *context = &trio_contexts[i];
-		int ret;
 
 		if (context->fd < 0)
 			continue;
 
-		ret = hv_dev_pread(context->fd, 0,
-			(HV_VirtAddr)&pcie_ports[i][0],
-			sizeof(struct pcie_port_property) * TILEGX_TRIO_PCIES,
-			GXIO_TRIO_OP_GET_PORT_PROPERTY);
-		if (ret < 0) {
-			pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
-				" on TRIO %d\n", ret, i);
-			continue;
-		}
-
 		for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
-			if (pcie_ports[i][j].allow_rc) {
+			int is_rc = 0;
+
+			if (pcie_ports[i].is_gx72 &&
+			    pcie_ports[i].ports[j].allow_rc) {
+				if (!pcie_ports[i].ports[j].allow_ep ||
+				    strapped_for_rc(context, j))
+					is_rc = 1;
+			} else if (pcie_ports[i].ports[j].allow_rc &&
+				   strapped_for_rc(context, j)) {
+				is_rc = 1;
+			}
+			if (is_rc) {
 				pcie_rc[i][j] = 1;
 				num_rc_controllers++;
 			}
-			else if (pcie_ports[i][j].allow_ep) {
-				num_ep_controllers++;
-			}
 		}
 	}
 
-	/*
-	 * Return if no PCIe ports are configured to operate in RC mode.
-	 */
+	/* Return if no PCIe ports are configured to operate in RC mode. */
 	if (num_rc_controllers == 0)
 		return 0;
 
-	/*
-	 * Set the TRIO pointer and MAC index for each PCIe RC port.
-	 */
+	/* Set the TRIO pointer and MAC index for each PCIe RC port. */
 	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
 		for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
 			if (pcie_rc[i][j]) {
@@ -411,26 +502,32 @@ int __init tile_pci_init(void)
 	}
 
 out:
-	/*
-	 * Configure each PCIe RC port.
-	 */
+	/* Configure each PCIe RC port. */
 	for (i = 0; i < num_rc_controllers; i++) {
-		/*
-		 * Configure the PCIe MAC to run in RC mode.
-		 */
 
+		/* Configure the PCIe MAC to run in RC mode. */
 		struct pci_controller *controller = &pci_controllers[i];
 
 		controller->index = i;
 		controller->ops = &tile_cfg_ops;
 
+		controller->io_space.start = PCIBIOS_MIN_IO +
+			(i * IO_SPACE_SIZE);
+		controller->io_space.end = controller->io_space.start +
+			IO_SPACE_SIZE - 1;
+		BUG_ON(controller->io_space.end > IO_SPACE_LIMIT);
+		controller->io_space.flags = IORESOURCE_IO;
+		snprintf(controller->io_space_name,
+			 sizeof(controller->io_space_name),
+			 "PCI I/O domain %d", i);
+		controller->io_space.name = controller->io_space_name;
+
 		/*
 		 * The PCI memory resource is located above the PA space.
 		 * For every host bridge, the BAR window or the MMIO aperture
 		 * is in range [3GB, 4GB - 1] of a 4GB space beyond the
 		 * PA space.
 		 */
-
 		controller->mem_offset = TILE_PCI_MEM_START +
 			(i * TILE_PCI_BAR_WINDOW_TOP);
 		controller->mem_space.start = controller->mem_offset +
@@ -458,7 +555,6 @@ static int tile_map_irq(const struct pci_dev *dev, u8 device, u8 pin)
 	return controller->irq_intx_table[pin - 1];
 }
 
-
 static void fixup_read_and_payload_sizes(struct pci_controller *controller)
 {
 	gxio_trio_context_t *trio_context = controller->trio;
@@ -472,9 +568,7 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller)
 
 	mac = controller->mac;
 
-	/*
-	 * Set our max read request size to be 4KB.
-	 */
+	/* Set our max read request size to be 4KB. */
 	reg_offset =
 		(TRIO_PCIE_RC_DEVICE_CONTROL <<
 			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
@@ -483,10 +577,10 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller)
 		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
 
 	dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
-						reg_offset);
+					      reg_offset);
 	dev_control.max_read_req_sz = 5;
 	__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
-						dev_control.word);
+			    dev_control.word);
 
 	/*
 	 * Set the max payload size supported by this Gx PCIe MAC.
@@ -502,10 +596,10 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller)
 		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
 
 	rc_dev_cap.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
-						reg_offset);
+					     reg_offset);
 	rc_dev_cap.mps_sup = 1;
 	__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
-						rc_dev_cap.word);
+			    rc_dev_cap.word);
 
 	/* Configure PCI Express MPS setting. */
 	list_for_each_entry(child, &root_bus->children, node) {
@@ -533,7 +627,7 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller)
 				    dev_control.max_payload_size,
 				    dev_control.max_read_req_sz,
 				    mac);
-        if (err < 0) {
+	if (err < 0) {
 		pr_err("PCI: PCIE_CONFIGURE_MAC_MPS_MRS failure, "
 			"MAC %d on TRIO %d\n",
 			mac, controller->trio_index);
@@ -570,21 +664,14 @@ static int setup_pcie_rc_delay(char *str)
 		if (!isdigit(*str))
 			return -EINVAL;
 		delay = simple_strtoul(str, (char **)&str, 10);
-		if (delay > MAX_RC_DELAY)
-			return -EINVAL;
 	}
 
 	rc_delay[trio_index][mac] = delay ? : DEFAULT_RC_DELAY;
-	pr_info("Delaying PCIe RC link training for %u sec"
-		" on MAC %lu on TRIO %lu\n", rc_delay[trio_index][mac],
-		mac, trio_index);
 	return 0;
 }
 early_param("pcie_rc_delay", setup_pcie_rc_delay);
 
-/*
- * PCI initialization entry point, called by subsys_initcall.
- */
+/* PCI initialization entry point, called by subsys_initcall. */
 int __init pcibios_init(void)
 {
 	resource_size_t offset;
@@ -594,35 +681,10 @@ int __init pcibios_init(void)
 
 	tile_pci_init();
 
-	if (num_rc_controllers == 0 && num_ep_controllers == 0)
+	if (num_rc_controllers == 0)
 		return 0;
 
 	/*
-	 * We loop over all the TRIO shims and set up the MMIO mappings.
-	 */
-	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
-		gxio_trio_context_t *context = &trio_contexts[i];
-
-		if (context->fd < 0)
-			continue;
-
-		/*
-		 * Map in the MMIO space for the MAC.
-		 */
-		offset = 0;
-		context->mmio_base_mac =
-			iorpc_ioremap(context->fd, offset,
-				      HV_TRIO_CONFIG_IOREMAP_SIZE);
-		if (context->mmio_base_mac == NULL) {
-			pr_err("PCI: MAC map failure on TRIO %d\n", i);
-
-			hv_dev_close(context->fd);
-			context->fd = -1;
-			continue;
-		}
-	}
-
-	/*
 	 * Delay a bit in case devices aren't ready.  Some devices are
 	 * known to require at least 20ms here, but we use a more
 	 * conservative value.
@@ -633,7 +695,6 @@ int __init pcibios_init(void)
 	for (next_busno = 0, i = 0; i < num_rc_controllers; i++) {
 		struct pci_controller *controller = &pci_controllers[i];
 		gxio_trio_context_t *trio_context = controller->trio;
-		TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
 		TRIO_PCIE_INTFC_PORT_STATUS_t port_status;
 		TRIO_PCIE_INTFC_TX_FIFO_CTL_t tx_fifo_ctl;
 		struct pci_bus *bus;
@@ -650,75 +711,64 @@ int __init pcibios_init(void)
 		mac = controller->mac;
 
 		/*
-		 * Check the port strap state which will override the BIB
-		 * setting.
+		 * Check for PCIe link-up status to decide if we need
+		 * to force the link to come up.
 		 */
-
 		reg_offset =
-			(TRIO_PCIE_INTFC_PORT_CONFIG <<
+			(TRIO_PCIE_INTFC_PORT_STATUS <<
 				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
 			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
-				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT) |
 			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
 
-		port_config.word =
+		port_status.word =
 			__gxio_mmio_read(trio_context->mmio_base_mac +
 					 reg_offset);
-
-		if ((port_config.strap_state !=
-			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC) &&
-			(port_config.strap_state !=
-			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1)) {
-			/*
-			 * If this is really intended to be an EP port,
-			 * record it so that the endpoint driver will know about it.
-			 */
-			if (port_config.strap_state ==
-			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT ||
-			port_config.strap_state ==
-			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1)
-				pcie_ports[trio_index][mac].allow_ep = 1;
-
-			continue;
+		if (!port_status.dl_up) {
+			if (rc_delay[trio_index][mac]) {
+				pr_info("Delaying PCIe RC TRIO init %d sec"
+					" on MAC %d on TRIO %d\n",
+					rc_delay[trio_index][mac], mac,
+					trio_index);
+				msleep(rc_delay[trio_index][mac] * 1000);
+			}
+			ret = gxio_trio_force_rc_link_up(trio_context, mac);
+			if (ret < 0)
+				pr_err("PCI: PCIE_FORCE_LINK_UP failure, "
+					"MAC %d on TRIO %d\n", mac, trio_index);
 		}
 
-		/*
-		 * Delay the RC link training if needed.
-		 */
-		if (rc_delay[trio_index][mac])
-			msleep(rc_delay[trio_index][mac] * 1000);
-
-		ret = gxio_trio_force_rc_link_up(trio_context, mac);
-		if (ret < 0)
-			pr_err("PCI: PCIE_FORCE_LINK_UP failure, "
-				"MAC %d on TRIO %d\n", mac, trio_index);
-
 		pr_info("PCI: Found PCI controller #%d on TRIO %d MAC %d\n", i,
 			trio_index, controller->mac);
 
-		/*
-		 * Wait a bit here because some EP devices take longer
-		 * to come up.
-		 */
-		msleep(1000);
-
-		/*
-		 * Check for PCIe link-up status.
-		 */
-
-		reg_offset =
-			(TRIO_PCIE_INTFC_PORT_STATUS <<
-				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
-			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
-				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
-			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+		/* Delay the bus probe if needed. */
+		if (rc_delay[trio_index][mac]) {
+			pr_info("Delaying PCIe RC bus enumerating %d sec"
+				" on MAC %d on TRIO %d\n",
+				rc_delay[trio_index][mac], mac,
+				trio_index);
+			msleep(rc_delay[trio_index][mac] * 1000);
+		} else {
+			/*
+			 * Wait a bit here because some EP devices
+			 * take longer to come up.
+			 */
+			msleep(1000);
+		}
 
+		/* Check for PCIe link-up status again. */
 		port_status.word =
 			__gxio_mmio_read(trio_context->mmio_base_mac +
 					 reg_offset);
 		if (!port_status.dl_up) {
-			pr_err("PCI: link is down, MAC %d on TRIO %d\n",
-				mac, trio_index);
+			if (pcie_ports[trio_index].ports[mac].removable) {
+				pr_info("PCI: link is down, MAC %d on TRIO %d\n",
+					mac, trio_index);
+				pr_info("This is expected if no PCIe card"
+					" is connected to this link\n");
+			} else
+				pr_err("PCI: link is down, MAC %d on TRIO %d\n",
+					mac, trio_index);
 			continue;
 		}
 
@@ -744,7 +794,6 @@ int __init pcibios_init(void)
 		 * Change the device ID so that Linux bus crawl doesn't confuse
 		 * the internal bridge with any Tilera endpoints.
 		 */
-
 		reg_offset =
 			(TRIO_PCIE_RC_DEVICE_ID_VEN_ID <<
 				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
@@ -757,10 +806,7 @@ int __init pcibios_init(void)
 				    TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT) |
 				    TILERA_VENDOR_ID);
 
-		/*
-		 * Set the internal P2P bridge class code.
-		 */
-
+		/* Set the internal P2P bridge class code. */
 		reg_offset =
 			(TRIO_PCIE_RC_REVISION_ID <<
 				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
@@ -771,26 +817,22 @@ int __init pcibios_init(void)
 		class_code_revision =
 			__gxio_mmio_read32(trio_context->mmio_base_mac +
 					   reg_offset);
-		class_code_revision = (class_code_revision & 0xff ) |
-					(PCI_CLASS_BRIDGE_PCI << 16);
+		class_code_revision = (class_code_revision & 0xff) |
+			(PCI_CLASS_BRIDGE_PCI << 16);
 
 		__gxio_mmio_write32(trio_context->mmio_base_mac +
 				    reg_offset, class_code_revision);
 
 #ifdef USE_SHARED_PCIE_CONFIG_REGION
 
-		/*
-		 * Map in the MMIO space for the PIO region.
-		 */
+		/* Map in the MMIO space for the PIO region. */
 		offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index) |
 			(((unsigned long long)mac) <<
 			TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
 
 #else
 
-		/*
-		 * Alloc a PIO region for PCI config access per MAC.
-		 */
+		/* Alloc a PIO region for PCI config access per MAC. */
 		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
 		if (ret < 0) {
 			pr_err("PCI: PCI CFG PIO alloc failure for mac %d "
@@ -801,9 +843,7 @@ int __init pcibios_init(void)
 
 		trio_context->pio_cfg_index[mac] = ret;
 
-		/*
-		 * For PIO CFG, the bus_address_hi parameter is 0.
-		 */
+		/* For PIO CFG, the bus_address_hi parameter is 0. */
 		ret = gxio_trio_init_pio_region_aux(trio_context,
 			trio_context->pio_cfg_index[mac],
 			mac, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
@@ -820,9 +860,15 @@ int __init pcibios_init(void)
 
 #endif
 
+		/*
+		 * To save VMALLOC space, we take advantage of the fact that
+		 * bit 29 in the PIO CFG address format is reserved 0. With
+		 * TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT being 30,
+		 * this cuts VMALLOC space usage from 1GB to 512MB per mac.
+		 */
 		trio_context->mmio_base_pio_cfg[mac] =
-			iorpc_ioremap(trio_context->fd, offset,
-			(1 << TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT));
+			iorpc_ioremap(trio_context->fd, offset, (1UL <<
+			(TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT - 1)));
 		if (trio_context->mmio_base_pio_cfg[mac] == NULL) {
 			pr_err("PCI: PIO map failure for mac %d on TRIO %d\n",
 				mac, trio_index);
@@ -830,9 +876,7 @@ int __init pcibios_init(void)
 			continue;
 		}
 
-		/*
-		 * Initialize the PCIe interrupts.
-		 */
+		/* Initialize the PCIe interrupts. */
 		if (tile_init_irqs(controller)) {
 			pr_err("PCI: IRQs init failure for mac %d on TRIO %d\n",
 				mac, trio_index);
@@ -843,17 +887,16 @@ int __init pcibios_init(void)
 		/*
 		 * The PCI memory resource is located above the PA space.
 		 * The memory range for the PCI root bus should not overlap
-		 * with the physical RAM
+		 * with the physical RAM.
 		 */
 		pci_add_resource_offset(&resources, &controller->mem_space,
 					controller->mem_offset);
-
+		pci_add_resource(&resources, &controller->io_space);
 		controller->first_busno = next_busno;
 		bus = pci_scan_root_bus(NULL, next_busno, controller->ops,
 					controller, &resources);
 		controller->root_bus = bus;
 		next_busno = bus->busn_res.end + 1;
-
 	}
 
 	/* Do machine dependent PCI interrupt routing */
@@ -865,7 +908,6 @@ int __init pcibios_init(void)
 	 * It allocates all of the resources (I/O memory, etc)
 	 * associated with the devices read in above.
 	 */
-
 	pci_assign_unassigned_resources();
 
 	/* Record the I/O resources in the PCI controller structure. */
@@ -873,9 +915,6 @@ int __init pcibios_init(void)
 		struct pci_controller *controller = &pci_controllers[i];
 		gxio_trio_context_t *trio_context = controller->trio;
 		struct pci_bus *root_bus = pci_controllers[i].root_bus;
-		struct pci_bus *next_bus;
-		uint32_t bus_address_hi;
-		struct pci_dev *dev;
 		int ret;
 		int j;
 
@@ -889,43 +928,12 @@ int __init pcibios_init(void)
 		/* Configure the max_payload_size values for this domain. */
 		fixup_read_and_payload_sizes(controller);
 
-		list_for_each_entry(dev, &root_bus->devices, bus_list) {
-			/* Find the PCI host controller, ie. the 1st bridge. */
-			if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
-				(PCI_SLOT(dev->devfn) == 0)) {
-				next_bus = dev->subordinate;
-				pci_controllers[i].mem_resources[0] =
-					*next_bus->resource[0];
-				pci_controllers[i].mem_resources[1] =
-					 *next_bus->resource[1];
-				pci_controllers[i].mem_resources[2] =
-					 *next_bus->resource[2];
-
-				break;
-			}
-		}
-
-		if (pci_controllers[i].mem_resources[1].flags & IORESOURCE_MEM)
-			bus_address_hi =
-				pci_controllers[i].mem_resources[1].start >> 32;
-		else if (pci_controllers[i].mem_resources[2].flags & IORESOURCE_PREFETCH)
-			bus_address_hi =
-				pci_controllers[i].mem_resources[2].start >> 32;
-		else {
-			/* This is unlikely. */
-			pr_err("PCI: no memory resources on TRIO %d mac %d\n",
-				controller->trio_index, controller->mac);
-			continue;
-		}
-
-		/*
-		 * Alloc a PIO region for PCI memory access for each RC port.
-		 */
+		/* Alloc a PIO region for PCI memory access for each RC port. */
 		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
 		if (ret < 0) {
 			pr_err("PCI: MEM PIO alloc failure on TRIO %d mac %d, "
-				"give up\n", controller->trio_index,
-				controller->mac);
+			       "give up\n", controller->trio_index,
+			       controller->mac);
 
 			continue;
 		}
@@ -943,12 +951,45 @@ int __init pcibios_init(void)
 						    0);
 		if (ret < 0) {
 			pr_err("PCI: MEM PIO init failure on TRIO %d mac %d, "
-				"give up\n", controller->trio_index,
-				controller->mac);
+			       "give up\n", controller->trio_index,
+			       controller->mac);
 
 			continue;
 		}
 
+#ifdef CONFIG_TILE_PCI_IO
+		/*
+		 * Alloc a PIO region for PCI I/O space access for each RC port.
+		 */
+		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+		if (ret < 0) {
+			pr_err("PCI: I/O PIO alloc failure on TRIO %d mac %d, "
+			       "give up\n", controller->trio_index,
+			       controller->mac);
+
+			continue;
+		}
+
+		controller->pio_io_index = ret;
+
+		/*
+		 * For PIO IO, the bus_address_hi parameter is hard-coded 0
+		 * because PCI I/O address space is 32-bit.
+		 */
+		ret = gxio_trio_init_pio_region_aux(trio_context,
+						    controller->pio_io_index,
+						    controller->mac,
+						    0,
+						    HV_TRIO_PIO_FLAG_IO_SPACE);
+		if (ret < 0) {
+			pr_err("PCI: I/O PIO init failure on TRIO %d mac %d, "
+			       "give up\n", controller->trio_index,
+			       controller->mac);
+
+			continue;
+		}
+#endif
+
 		/*
 		 * Configure a Mem-Map region for each memory controller so
 		 * that Linux can map all of its PA space to the PCI bus.
@@ -963,9 +1004,9 @@ int __init pcibios_init(void)
 							  0);
 			if (ret < 0) {
 				pr_err("PCI: Mem-Map alloc failure on TRIO %d "
-					"mac %d for MC %d, give up\n",
-					controller->trio_index,
-					controller->mac, j);
+				       "mac %d for MC %d, give up\n",
+				       controller->trio_index,
+				       controller->mac, j);
 
 				goto alloc_mem_map_failed;
 			}
@@ -996,9 +1037,9 @@ int __init pcibios_init(void)
 				GXIO_TRIO_ORDER_MODE_UNORDERED);
 			if (ret < 0) {
 				pr_err("PCI: Mem-Map init failure on TRIO %d "
-					"mac %d for MC %d, give up\n",
-					controller->trio_index,
-					controller->mac, j);
+				       "mac %d for MC %d, give up\n",
+				       controller->trio_index,
+				       controller->mac, j);
 
 				goto alloc_mem_map_failed;
 			}
@@ -1007,22 +1048,18 @@ int __init pcibios_init(void)
 alloc_mem_map_failed:
 			break;
 		}
-
 	}
 
 	return 0;
 }
 subsys_initcall(pcibios_init);
 
-/* Note: to be deleted after Linux 3.6 merge. */
+/* No bus fixups needed. */
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
-/*
- * This can be called from the generic PCI layer, but doesn't need to
- * do anything.
- */
+/* Process any "pci=" kernel boot arguments. */
 char *pcibios_setup(char *str)
 {
 	if (!strcmp(str, "off")) {
@@ -1034,8 +1071,7 @@ char *pcibios_setup(char *str)
 
 /*
  * Enable memory address decoding, as appropriate, for the
- * device described by the 'dev' struct. The I/O decoding
- * is disabled, though the TILE-Gx supports I/O addressing.
+ * device described by the 'dev' struct.
  *
  * This is called from the generic PCI layer, and can be called
  * for bridges or endpoints.
@@ -1065,19 +1101,15 @@ void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
 	resource_size_t start;
 	resource_size_t end;
 	int trio_fd;
-	int i, j;
+	int i;
 
 	start = phys_addr;
 	end = phys_addr + size - 1;
 
 	/*
-	 * In the following, each PCI controller's mem_resources[1]
-	 * represents its (non-prefetchable) PCI memory resource and
-	 * mem_resources[2] refers to its prefetchable PCI memory resource.
-	 * By searching phys_addr in each controller's mem_resources[], we can
+	 * By searching phys_addr in each controller's mem_space, we can
 	 * determine the controller that should accept the PCI memory access.
 	 */
-
 	for (i = 0; i < num_rc_controllers; i++) {
 		/*
 		 * Skip controllers that are not properly initialized or
@@ -1086,25 +1118,18 @@ void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
 		if (pci_controllers[i].root_bus == NULL)
 			continue;
 
-		for (j = 1; j < 3; j++) {
-			bar_start =
-				pci_controllers[i].mem_resources[j].start;
-			bar_end =
-				pci_controllers[i].mem_resources[j].end;
-
-			if ((start >= bar_start) && (end <= bar_end)) {
-
-				controller = &pci_controllers[i];
+		bar_start = pci_controllers[i].mem_space.start;
+		bar_end = pci_controllers[i].mem_space.end;
 
-				goto got_it;
-			}
+		if ((start >= bar_start) && (end <= bar_end)) {
+			controller = &pci_controllers[i];
+			break;
 		}
 	}
 
 	if (controller == NULL)
 		return NULL;
 
-got_it:
 	trio_fd = controller->trio->fd;
 
 	/* Convert the resource start to the bus address offset. */
@@ -1112,14 +1137,71 @@ got_it:
 
 	offset = HV_TRIO_PIO_OFFSET(controller->pio_mem_index) + start;
 
-	/*
-	 * We need to keep the PCI bus address's in-page offset in the VA.
-	 */
+	/* We need to keep the PCI bus address's in-page offset in the VA. */
 	return iorpc_ioremap(trio_fd, offset, size) +
-		(phys_addr & (PAGE_SIZE - 1));
+		(start & (PAGE_SIZE - 1));
 }
 EXPORT_SYMBOL(ioremap);
 
+#ifdef CONFIG_TILE_PCI_IO
+/* Map a PCI I/O address into VA space. */
+void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+	struct pci_controller *controller = NULL;
+	resource_size_t bar_start;
+	resource_size_t bar_end;
+	resource_size_t offset;
+	resource_size_t start;
+	resource_size_t end;
+	int trio_fd;
+	int i;
+
+	start = port;
+	end = port + size - 1;
+
+	/*
+	 * By searching the port in each controller's io_space, we can
+	 * determine the controller that should accept the PCI I/O access.
+	 */
+	for (i = 0; i < num_rc_controllers; i++) {
+		/*
+		 * Skip controllers that are not properly initialized or
+		 * have down links.
+		 */
+		if (pci_controllers[i].root_bus == NULL)
+			continue;
+
+		bar_start = pci_controllers[i].io_space.start;
+		bar_end = pci_controllers[i].io_space.end;
+
+		if ((start >= bar_start) && (end <= bar_end)) {
+			controller = &pci_controllers[i];
+			break;
+		}
+	}
+
+	if (controller == NULL)
+		return NULL;
+
+	trio_fd = controller->trio->fd;
+
+	/* Convert the resource start to the bus address offset. */
+	port -= controller->io_space.start;
+
+	offset = HV_TRIO_PIO_OFFSET(controller->pio_io_index) + port;
+
+	/* We need to keep the PCI bus address's in-page offset in the VA. */
+	return iorpc_ioremap(trio_fd, offset, size) + (port & (PAGE_SIZE - 1));
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+	iounmap(addr);
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif
+
 void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
 {
 	iounmap(addr);
@@ -1141,7 +1223,6 @@ EXPORT_SYMBOL(pci_iounmap);
  * offset is in bytes, from the start of config space for the
  * specified bus & device.
  */
-
 static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset,
 			 int size, u32 *val)
 {
@@ -1191,7 +1272,6 @@ static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset,
 	 * Accesses to the directly attached device have to be
 	 * sent as type-0 configs.
 	 */
-
 	if (busnum == (controller->first_busno + 1)) {
 		/*
 		 * There is only one device off of our built-in P2P bridge.
@@ -1213,9 +1293,8 @@ static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset,
 	 * Note that we don't set the mac field in cfg_addr because the
 	 * mapping is per port.
 	 */
-
 	mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
-			cfg_addr.word;
+		cfg_addr.word;
 
 valid_device:
 
@@ -1319,7 +1398,6 @@ static int tile_cfg_write(struct pci_bus *bus, unsigned int devfn, int offset,
 	 * Accesses to the directly attached device have to be
 	 * sent as type-0 configs.
 	 */
-
 	if (busnum == (controller->first_busno + 1)) {
 		/*
 		 * There is only one device off of our built-in P2P bridge.
@@ -1341,7 +1419,6 @@ static int tile_cfg_write(struct pci_bus *bus, unsigned int devfn, int offset,
 	 * Note that we don't set the mac field in cfg_addr because the
 	 * mapping is per port.
 	 */
-
 	mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
 			cfg_addr.word;
 
@@ -1379,11 +1456,8 @@ static struct pci_ops tile_cfg_ops = {
 };
 
 
-/*
- * MSI support starts here.
- */
-static unsigned int
-tilegx_msi_startup(struct irq_data *d)
+/* MSI support starts here. */
+static unsigned int tilegx_msi_startup(struct irq_data *d)
 {
 	if (d->msi_desc)
 		unmask_msi_irq(d);
@@ -1391,21 +1465,18 @@ tilegx_msi_startup(struct irq_data *d)
 	return 0;
 }
 
-static void
-tilegx_msi_ack(struct irq_data *d)
+static void tilegx_msi_ack(struct irq_data *d)
 {
 	__insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
 }
 
-static void
-tilegx_msi_mask(struct irq_data *d)
+static void tilegx_msi_mask(struct irq_data *d)
 {
 	mask_msi_irq(d);
 	__insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
 }
 
-static void
-tilegx_msi_unmask(struct irq_data *d)
+static void tilegx_msi_unmask(struct irq_data *d)
 {
 	__insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
 	unmask_msi_irq(d);
@@ -1462,32 +1533,55 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 	trio_context = controller->trio;
 
 	/*
-	 * Allocate the Mem-Map that will accept the MSI write and
-	 * trigger the TILE-side interrupts.
+	 * Allocate a scatter-queue that will accept the MSI write and
+	 * trigger the TILE-side interrupts. We use the scatter-queue regions
+	 * before the mem map regions, because the latter are needed by more
+	 * applications.
 	 */
-	mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0);
-	if (mem_map < 0) {
-		dev_printk(KERN_INFO, &pdev->dev,
-			"%s Mem-Map alloc failure. "
-			"Failed to initialize MSI interrupts. "
-			"Falling back to legacy interrupts.\n",
-			desc->msi_attrib.is_msix ? "MSI-X" : "MSI");
+	mem_map = gxio_trio_alloc_scatter_queues(trio_context, 1, 0, 0);
+	if (mem_map >= 0) {
+		TRIO_MAP_SQ_DOORBELL_FMT_t doorbell_template = {{
+			.pop = 0,
+			.doorbell = 1,
+		}};
+
+		mem_map += TRIO_NUM_MAP_MEM_REGIONS;
+		mem_map_base = MEM_MAP_INTR_REGIONS_BASE +
+			mem_map * MEM_MAP_INTR_REGION_SIZE;
+		mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1;
+
+		msi_addr = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 8;
+		msg.data = (unsigned int)doorbell_template.word;
+	} else {
+		/* SQ regions are out, allocate from map mem regions. */
+		mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0);
+		if (mem_map < 0) {
+			dev_printk(KERN_INFO, &pdev->dev,
+				"%s Mem-Map alloc failure. "
+				"Failed to initialize MSI interrupts. "
+				"Falling back to legacy interrupts.\n",
+				desc->msi_attrib.is_msix ? "MSI-X" : "MSI");
+			ret = -ENOMEM;
+			goto msi_mem_map_alloc_failure;
+		}
 
-		ret = -ENOMEM;
-		goto msi_mem_map_alloc_failure;
+		mem_map_base = MEM_MAP_INTR_REGIONS_BASE +
+			mem_map * MEM_MAP_INTR_REGION_SIZE;
+		mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1;
+
+		msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 -
+			TRIO_MAP_MEM_REG_INT0;
+
+		msg.data = mem_map;
 	}
 
 	/* We try to distribute different IRQs to different tiles. */
 	cpu = tile_irq_cpu(irq);
 
 	/*
-	 * Now call up to the HV to configure the Mem-Map interrupt and
+	 * Now call up to the HV to configure the MSI interrupt and
 	 * set up the IPI binding.
 	 */
-	mem_map_base = MEM_MAP_INTR_REGIONS_BASE +
-		mem_map * MEM_MAP_INTR_REGION_SIZE;
-	mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1;
-
 	ret = gxio_trio_config_msi_intr(trio_context, cpu_x(cpu), cpu_y(cpu),
 					KERNEL_PL, irq, controller->mac,
 					mem_map, mem_map_base, mem_map_limit,
@@ -1500,13 +1594,9 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 
 	irq_set_msi_desc(irq, desc);
 
-	msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 - TRIO_MAP_MEM_REG_INT0;
-
 	msg.address_hi = msi_addr >> 32;
 	msg.address_lo = msi_addr & 0xffffffff;
 
-	msg.data = mem_map;
-
 	write_msi_msg(irq, &msg);
 	irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq);
 	irq_set_handler_data(irq, controller);
diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c
index dafc447..681100c 100644
--- a/arch/tile/kernel/proc.c
+++ b/arch/tile/kernel/proc.c
@@ -113,7 +113,6 @@ arch_initcall(proc_tile_init);
  * Support /proc/sys/tile directory
  */
 
-#ifndef __tilegx__  /* FIXME: GX: no support for unaligned access yet */
 static ctl_table unaligned_subtable[] = {
 	{
 		.procname	= "enabled",
@@ -160,4 +159,3 @@ static int __init proc_sys_tile_init(void)
 }
 
 arch_initcall(proc_sys_tile_init);
-#endif
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 8ac3044..663289b 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -33,6 +33,7 @@
 #include <asm/syscalls.h>
 #include <asm/traps.h>
 #include <asm/setup.h>
+#include <asm/uaccess.h>
 #ifdef CONFIG_HARDWALL
 #include <asm/hardwall.h>
 #endif
@@ -74,19 +75,6 @@ void arch_release_thread_info(struct thread_info *info)
 {
 	struct single_step_state *step_state = info->step_state;
 
-#ifdef CONFIG_HARDWALL
-	/*
-	 * We free a thread_info from the context of the task that has
-	 * been scheduled next, so the original task is already dead.
-	 * Calling deactivate here just frees up the data structures.
-	 * If the task we're freeing held the last reference to a
-	 * hardwall fd, it would have been released prior to this point
-	 * anyway via exit_files(), and the hardwall_task.info pointers
-	 * would be NULL by now.
-	 */
-	hardwall_deactivate_all(info->task);
-#endif
-
 	if (step_state) {
 
 		/*
@@ -160,6 +148,14 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	 */
 	task_thread_info(p)->step_state = NULL;
 
+#ifdef __tilegx__
+	/*
+	 * Do not clone unalign jit fixup from the parent; each thread
+	 * must allocate its own on demand.
+	 */
+	task_thread_info(p)->unalign_jit_base = NULL;
+#endif
+
 	/*
 	 * Copy the registers onto the kernel stack so the
 	 * return-from-interrupt code will reload it into registers.
@@ -218,6 +214,18 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	return 0;
 }
 
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+	task_thread_info(tsk)->align_ctl = val;
+	return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+	return put_user(task_thread_info(tsk)->align_ctl,
+			(unsigned int __user *)adr);
+}
+
 /*
  * Return "current" if it looks plausible, or else a pointer to a dummy.
  * This can be helpful if we are just trying to emit a clean panic.
@@ -564,7 +572,15 @@ void flush_thread(void)
  */
 void exit_thread(void)
 {
-	/* Nothing */
+#ifdef CONFIG_HARDWALL
+	/*
+	 * Remove the task from the list of tasks that are associated
+	 * with any live hardwalls.  (If the task that is exiting held
+	 * the last reference to a hardwall fd, it would already have
+	 * been released and deactivated at this point.)
+	 */
+	hardwall_deactivate_all(current);
+#endif
 }
 
 void show_regs(struct pt_regs *regs)
@@ -575,21 +591,21 @@ void show_regs(struct pt_regs *regs)
 	pr_err("\n");
 	show_regs_print_info(KERN_ERR);
 #ifdef __tilegx__
-	for (i = 0; i < 51; i += 3)
+	for (i = 0; i < 17; i++)
 		pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
-		       i, regs->regs[i], i+1, regs->regs[i+1],
-		       i+2, regs->regs[i+2]);
-	pr_err(" r51: "REGFMT" r52: "REGFMT" tp : "REGFMT"\n",
-	       regs->regs[51], regs->regs[52], regs->tp);
+		       i, regs->regs[i], i+18, regs->regs[i+18],
+		       i+36, regs->regs[i+36]);
+	pr_err(" r17: "REGFMT" r35: "REGFMT" tp : "REGFMT"\n",
+	       regs->regs[17], regs->regs[35], regs->tp);
 	pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr);
 #else
-	for (i = 0; i < 52; i += 4)
+	for (i = 0; i < 13; i++)
 		pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT
 		       " r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
-		       i, regs->regs[i], i+1, regs->regs[i+1],
-		       i+2, regs->regs[i+2], i+3, regs->regs[i+3]);
-	pr_err(" r52: "REGFMT" tp : "REGFMT" sp : "REGFMT" lr : "REGFMT"\n",
-	       regs->regs[52], regs->tp, regs->sp, regs->lr);
+		       i, regs->regs[i], i+14, regs->regs[i+14],
+		       i+27, regs->regs[i+27], i+40, regs->regs[i+40]);
+	pr_err(" r13: "REGFMT" tp : "REGFMT" sp : "REGFMT" lr : "REGFMT"\n",
+	       regs->regs[13], regs->tp, regs->sp, regs->lr);
 #endif
 	pr_err(" pc : "REGFMT" ex1: %ld     faultnum: %ld\n",
 	       regs->pc, regs->ex1, regs->faultnum);
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index 0f83ed4..bac1874 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -272,7 +272,7 @@ void do_syscall_trace_exit(struct pt_regs *regs)
 		trace_sys_exit(regs, regs->regs[0]);
 }
 
-void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
+void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs)
 {
 	struct siginfo info;
 
@@ -288,5 +288,5 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
 /* Handle synthetic interrupt delivered only by the simulator. */
 void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
 {
-	send_sigtrap(current, regs, fault_num);
+	send_sigtrap(current, regs);
 }
diff --git a/arch/tile/kernel/reboot.c b/arch/tile/kernel/reboot.c
index d1b5c91..6c5d2c0 100644
--- a/arch/tile/kernel/reboot.c
+++ b/arch/tile/kernel/reboot.c
@@ -27,7 +27,6 @@
 
 void machine_halt(void)
 {
-	warn_early_printk();
 	arch_local_irq_disable_all();
 	smp_send_stop();
 	hv_halt();
@@ -35,7 +34,6 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	warn_early_printk();
 	arch_local_irq_disable_all();
 	smp_send_stop();
 	hv_power_off();
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index eceb834..ff8302c 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -154,6 +154,65 @@ static int __init setup_maxnodemem(char *str)
 }
 early_param("maxnodemem", setup_maxnodemem);
 
+struct memmap_entry {
+	u64 addr;	/* start of memory segment */
+	u64 size;	/* size of memory segment */
+};
+static struct memmap_entry memmap_map[64];
+static int memmap_nr;
+
+static void add_memmap_region(u64 addr, u64 size)
+{
+	if (memmap_nr >= ARRAY_SIZE(memmap_map)) {
+		pr_err("Ooops! Too many entries in the memory map!\n");
+		return;
+	}
+	memmap_map[memmap_nr].addr = addr;
+	memmap_map[memmap_nr].size = size;
+	memmap_nr++;
+}
+
+static int __init setup_memmap(char *p)
+{
+	char *oldp;
+	u64 start_at, mem_size;
+
+	if (!p)
+		return -EINVAL;
+
+	if (!strncmp(p, "exactmap", 8)) {
+		pr_err("\"memmap=exactmap\" not valid on tile\n");
+		return 0;
+	}
+
+	oldp = p;
+	mem_size = memparse(p, &p);
+	if (p == oldp)
+		return -EINVAL;
+
+	if (*p == '@') {
+		pr_err("\"memmap=nn@ss\" (force RAM) invalid on tile\n");
+	} else if (*p == '#') {
+		pr_err("\"memmap=nn#ss\" (force ACPI data) invalid on tile\n");
+	} else if (*p == '$') {
+		start_at = memparse(p+1, &p);
+		add_memmap_region(start_at, mem_size);
+	} else {
+		if (mem_size == 0)
+			return -EINVAL;
+		maxmem_pfn = (mem_size >> HPAGE_SHIFT) <<
+			(HPAGE_SHIFT - PAGE_SHIFT);
+	}
+	return *p == '\0' ? 0 : -EINVAL;
+}
+early_param("memmap", setup_memmap);
+
+static int __init setup_mem(char *str)
+{
+	return setup_maxmem(str);
+}
+early_param("mem", setup_mem);  /* compatibility with x86 */
+
 static int __init setup_isolnodes(char *str)
 {
 	char buf[MAX_NUMNODES * 5];
@@ -614,11 +673,12 @@ static void __init setup_bootmem_allocator_node(int i)
 	/*
 	 * Throw away any memory aliased by the PCI region.
 	 */
-	if (pci_reserve_start_pfn < end && pci_reserve_end_pfn > start)
-		reserve_bootmem(PFN_PHYS(pci_reserve_start_pfn),
-				PFN_PHYS(pci_reserve_end_pfn -
-					 pci_reserve_start_pfn),
+	if (pci_reserve_start_pfn < end && pci_reserve_end_pfn > start) {
+		start = max(pci_reserve_start_pfn, start);
+		end = min(pci_reserve_end_pfn, end);
+		reserve_bootmem(PFN_PHYS(start), PFN_PHYS(end - start),
 				BOOTMEM_EXCLUSIVE);
+	}
 #endif
 }
 
@@ -628,6 +688,12 @@ static void __init setup_bootmem_allocator(void)
 	for (i = 0; i < MAX_NUMNODES; ++i)
 		setup_bootmem_allocator_node(i);
 
+	/* Reserve any memory excluded by "memmap" arguments. */
+	for (i = 0; i < memmap_nr; ++i) {
+		struct memmap_entry *m = &memmap_map[i];
+		reserve_bootmem(m->addr, m->size, 0);
+	}
+
 #ifdef CONFIG_KEXEC
 	if (crashk_res.start != crashk_res.end)
 		reserve_bootmem(crashk_res.start, resource_size(&crashk_res), 0);
@@ -1561,11 +1627,11 @@ insert_non_bus_resource(void)
 #endif
 
 static struct resource* __init
-insert_ram_resource(u64 start_pfn, u64 end_pfn)
+insert_ram_resource(u64 start_pfn, u64 end_pfn, bool reserved)
 {
 	struct resource *res =
 		kzalloc(sizeof(struct resource), GFP_ATOMIC);
-	res->name = "System RAM";
+	res->name = reserved ? "Reserved" : "System RAM";
 	res->start = start_pfn << PAGE_SHIFT;
 	res->end = (end_pfn << PAGE_SHIFT) - 1;
 	res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
@@ -1600,11 +1666,11 @@ static int __init request_standard_resources(void)
 		    end_pfn > pci_reserve_start_pfn) {
 			if (end_pfn > pci_reserve_end_pfn)
 				insert_ram_resource(pci_reserve_end_pfn,
-						     end_pfn);
+						    end_pfn, 0);
 			end_pfn = pci_reserve_start_pfn;
 		}
 #endif
-		insert_ram_resource(start_pfn, end_pfn);
+		insert_ram_resource(start_pfn, end_pfn, 0);
 	}
 
 	code_resource.start = __pa(_text - CODE_DELTA);
@@ -1615,6 +1681,13 @@ static int __init request_standard_resources(void)
 	insert_resource(&iomem_resource, &code_resource);
 	insert_resource(&iomem_resource, &data_resource);
 
+	/* Mark any "memmap" regions busy for the resource manager. */
+	for (i = 0; i < memmap_nr; ++i) {
+		struct memmap_entry *m = &memmap_map[i];
+		insert_ram_resource(PFN_DOWN(m->addr),
+				    PFN_UP(m->addr + m->size - 1), 1);
+	}
+
 #ifdef CONFIG_KEXEC
 	insert_resource(&iomem_resource, &crashk_res);
 #endif
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index 9531845b..2d1dbf3 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -33,6 +33,7 @@
 #include <asm/ucontext.h>
 #include <asm/sigframe.h>
 #include <asm/syscalls.h>
+#include <asm/vdso.h>
 #include <arch/interrupts.h>
 
 #define DEBUG_SIG 0
@@ -190,7 +191,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (err)
 		goto give_sigsegv;
 
-	restorer = VDSO_BASE;
+	restorer = VDSO_SYM(&__vdso_rt_sigreturn);
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = (unsigned long) ka->sa.sa_restorer;
 
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 27742e8..c617327 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -12,41 +12,30 @@
  *   more details.
  *
  * A code-rewriter that enables instruction single-stepping.
- * Derived from iLib's single-stepping code.
  */
 
-#ifndef __tilegx__   /* Hardware support for single step unavailable. */
-
-/* These functions are only used on the TILE platform */
+#include <linux/smp.h>
+#include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/thread_info.h>
 #include <linux/uaccess.h>
 #include <linux/mman.h>
 #include <linux/types.h>
 #include <linux/err.h>
+#include <linux/prctl.h>
 #include <asm/cacheflush.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <arch/abi.h>
+#include <arch/spr_def.h>
 #include <arch/opcode.h>
 
-#define signExtend17(val) sign_extend((val), 17)
-#define TILE_X1_MASK (0xffffffffULL << 31)
-
-int unaligned_printk;
 
-static int __init setup_unaligned_printk(char *str)
-{
-	long val;
-	if (strict_strtol(str, 0, &val) != 0)
-		return 0;
-	unaligned_printk = val;
-	pr_info("Printk for each unaligned data accesses is %s\n",
-		unaligned_printk ? "enabled" : "disabled");
-	return 1;
-}
-__setup("unaligned_printk=", setup_unaligned_printk);
+#ifndef __tilegx__   /* Hardware support for single step unavailable. */
 
-unsigned int unaligned_fixup_count;
+#define signExtend17(val) sign_extend((val), 17)
+#define TILE_X1_MASK (0xffffffffULL << 31)
 
 enum mem_op {
 	MEMOP_NONE,
@@ -56,12 +45,13 @@ enum mem_op {
 	MEMOP_STORE_POSTINCR
 };
 
-static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset)
+static inline tilepro_bundle_bits set_BrOff_X1(tilepro_bundle_bits n,
+	s32 offset)
 {
-	tile_bundle_bits result;
+	tilepro_bundle_bits result;
 
 	/* mask out the old offset */
-	tile_bundle_bits mask = create_BrOff_X1(-1);
+	tilepro_bundle_bits mask = create_BrOff_X1(-1);
 	result = n & (~mask);
 
 	/* or in the new offset */
@@ -70,10 +60,11 @@ static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset)
 	return result;
 }
 
-static inline tile_bundle_bits move_X1(tile_bundle_bits n, int dest, int src)
+static inline tilepro_bundle_bits move_X1(tilepro_bundle_bits n, int dest,
+	int src)
 {
-	tile_bundle_bits result;
-	tile_bundle_bits op;
+	tilepro_bundle_bits result;
+	tilepro_bundle_bits op;
 
 	result = n & (~TILE_X1_MASK);
 
@@ -87,13 +78,13 @@ static inline tile_bundle_bits move_X1(tile_bundle_bits n, int dest, int src)
 	return result;
 }
 
-static inline tile_bundle_bits nop_X1(tile_bundle_bits n)
+static inline tilepro_bundle_bits nop_X1(tilepro_bundle_bits n)
 {
 	return move_X1(n, TREG_ZERO, TREG_ZERO);
 }
 
-static inline tile_bundle_bits addi_X1(
-	tile_bundle_bits n, int dest, int src, int imm)
+static inline tilepro_bundle_bits addi_X1(
+	tilepro_bundle_bits n, int dest, int src, int imm)
 {
 	n &= ~TILE_X1_MASK;
 
@@ -107,15 +98,26 @@ static inline tile_bundle_bits addi_X1(
 	return n;
 }
 
-static tile_bundle_bits rewrite_load_store_unaligned(
+static tilepro_bundle_bits rewrite_load_store_unaligned(
 	struct single_step_state *state,
-	tile_bundle_bits bundle,
+	tilepro_bundle_bits bundle,
 	struct pt_regs *regs,
 	enum mem_op mem_op,
 	int size, int sign_ext)
 {
 	unsigned char __user *addr;
 	int val_reg, addr_reg, err, val;
+	int align_ctl;
+
+	align_ctl = unaligned_fixup;
+	switch (task_thread_info(current)->align_ctl) {
+	case PR_UNALIGN_NOPRINT:
+		align_ctl = 1;
+		break;
+	case PR_UNALIGN_SIGBUS:
+		align_ctl = 0;
+		break;
+	}
 
 	/* Get address and value registers */
 	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
@@ -160,7 +162,7 @@ static tile_bundle_bits rewrite_load_store_unaligned(
 	 * tilepro hardware would be doing, if it could provide us with the
 	 * actual bad address in an SPR, which it doesn't.
 	 */
-	if (unaligned_fixup == 0) {
+	if (align_ctl == 0) {
 		siginfo_t info = {
 			.si_signo = SIGBUS,
 			.si_code = BUS_ADRALN,
@@ -209,14 +211,14 @@ static tile_bundle_bits rewrite_load_store_unaligned(
 
 	if (err) {
 		siginfo_t info = {
-			.si_signo = SIGSEGV,
-			.si_code = SEGV_MAPERR,
+			.si_signo = SIGBUS,
+			.si_code = BUS_ADRALN,
 			.si_addr = addr
 		};
-		trace_unhandled_signal("segfault", regs,
-				       (unsigned long)addr, SIGSEGV);
+		trace_unhandled_signal("bad address for unaligned fixup", regs,
+				       (unsigned long)addr, SIGBUS);
 		force_sig_info(info.si_signo, &info, current);
-		return (tile_bundle_bits) 0;
+		return (tilepro_bundle_bits) 0;
 	}
 
 	if (unaligned_printk || unaligned_fixup_count == 0) {
@@ -285,7 +287,7 @@ void single_step_execve(void)
 	ti->step_state = NULL;
 }
 
-/**
+/*
  * single_step_once() - entry point when single stepping has been triggered.
  * @regs: The machine register state
  *
@@ -304,20 +306,31 @@ void single_step_execve(void)
  */
 void single_step_once(struct pt_regs *regs)
 {
-	extern tile_bundle_bits __single_step_ill_insn;
-	extern tile_bundle_bits __single_step_j_insn;
-	extern tile_bundle_bits __single_step_addli_insn;
-	extern tile_bundle_bits __single_step_auli_insn;
+	extern tilepro_bundle_bits __single_step_ill_insn;
+	extern tilepro_bundle_bits __single_step_j_insn;
+	extern tilepro_bundle_bits __single_step_addli_insn;
+	extern tilepro_bundle_bits __single_step_auli_insn;
 	struct thread_info *info = (void *)current_thread_info();
 	struct single_step_state *state = info->step_state;
 	int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
-	tile_bundle_bits __user *buffer, *pc;
-	tile_bundle_bits bundle;
+	tilepro_bundle_bits __user *buffer, *pc;
+	tilepro_bundle_bits bundle;
 	int temp_reg;
 	int target_reg = TREG_LR;
 	int err;
 	enum mem_op mem_op = MEMOP_NONE;
 	int size = 0, sign_ext = 0;  /* happy compiler */
+	int align_ctl;
+
+	align_ctl = unaligned_fixup;
+	switch (task_thread_info(current)->align_ctl) {
+	case PR_UNALIGN_NOPRINT:
+		align_ctl = 1;
+		break;
+	case PR_UNALIGN_SIGBUS:
+		align_ctl = 0;
+		break;
+	}
 
 	asm(
 "    .pushsection .rodata.single_step\n"
@@ -356,6 +369,9 @@ void single_step_once(struct pt_regs *regs)
 		/* allocate a cache line of writable, executable memory */
 		buffer = (void __user *) vm_mmap(NULL, 0, 64,
 					  PROT_EXEC | PROT_READ | PROT_WRITE,
+#ifdef CONFIG_HOMECACHE
+					  MAP_CACHE_HOME_TASK |
+#endif
 					  MAP_PRIVATE | MAP_ANONYMOUS,
 					  0);
 
@@ -390,7 +406,7 @@ void single_step_once(struct pt_regs *regs)
 	if (regs->faultnum == INT_SWINT_1)
 		regs->pc -= 8;
 
-	pc = (tile_bundle_bits __user *)(regs->pc);
+	pc = (tilepro_bundle_bits __user *)(regs->pc);
 	if (get_user(bundle, pc) != 0) {
 		pr_err("Couldn't read instruction at %p trying to step\n", pc);
 		return;
@@ -627,9 +643,9 @@ void single_step_once(struct pt_regs *regs)
 
 	/*
 	 * Check if we need to rewrite an unaligned load/store.
-	 * Returning zero is a special value meaning we need to SIGSEGV.
+	 * Returning zero is a special value meaning we generated a signal.
 	 */
-	if (mem_op != MEMOP_NONE && unaligned_fixup >= 0) {
+	if (mem_op != MEMOP_NONE && align_ctl >= 0) {
 		bundle = rewrite_load_store_unaligned(state, bundle, regs,
 						      mem_op, size, sign_ext);
 		if (bundle == 0)
@@ -668,9 +684,9 @@ void single_step_once(struct pt_regs *regs)
 		}
 
 		/* End with a jump back to the next instruction */
-		delta = ((regs->pc + TILE_BUNDLE_SIZE_IN_BYTES) -
+		delta = ((regs->pc + TILEPRO_BUNDLE_SIZE_IN_BYTES) -
 			(unsigned long)buffer) >>
-			TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES;
+			TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES;
 		bundle = __single_step_j_insn;
 		bundle |= create_JOffLong_X1(delta);
 		err |= __put_user(bundle, buffer++);
@@ -698,9 +714,6 @@ void single_step_once(struct pt_regs *regs)
 }
 
 #else
-#include <linux/smp.h>
-#include <linux/ptrace.h>
-#include <arch/spr_def.h>
 
 static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
 
@@ -743,10 +756,10 @@ void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
 	} else if ((*ss_pc != regs->pc) ||
 		   (!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) {
 
-		ptrace_notify(SIGTRAP);
 		control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
 		control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
 		__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
+		send_sigtrap(current, regs);
 	}
 }
 
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c
index cbc73a8..6cc520d 100644
--- a/arch/tile/kernel/smp.c
+++ b/arch/tile/kernel/smp.c
@@ -100,8 +100,8 @@ static void smp_start_cpu_interrupt(void)
 /* Handler to stop the current cpu. */
 static void smp_stop_cpu_interrupt(void)
 {
-	set_cpu_online(smp_processor_id(), 0);
 	arch_local_irq_disable_all();
+	set_cpu_online(smp_processor_id(), 0);
 	for (;;)
 		asm("nap; nop");
 }
diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c
index a535655..732e9d1 100644
--- a/arch/tile/kernel/smpboot.c
+++ b/arch/tile/kernel/smpboot.c
@@ -142,13 +142,15 @@ static struct cpumask cpu_started;
  */
 static void start_secondary(void)
 {
-	int cpuid = smp_processor_id();
+	int cpuid;
+
+	preempt_disable();
+
+	cpuid = smp_processor_id();
 
 	/* Set our thread pointer appropriately. */
 	set_my_cpu_offset(__per_cpu_offset[cpuid]);
 
-	preempt_disable();
-
 	/*
 	 * In large machines even this will slow us down, since we
 	 * will be contending for for the printk spinlock.
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index af8dfc9..a9db923 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -29,6 +29,7 @@
 #include <asm/switch_to.h>
 #include <asm/sigframe.h>
 #include <asm/stack.h>
+#include <asm/vdso.h>
 #include <arch/abi.h>
 #include <arch/interrupts.h>
 
@@ -103,8 +104,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
 		if (kbt->verbose)
 			pr_err("  <%s while in kernel mode>\n", fault);
 	} else if (EX1_PL(p->ex1) == USER_PL &&
-	    p->pc < PAGE_OFFSET &&
-	    p->sp < PAGE_OFFSET) {
+		   p->sp < PAGE_OFFSET && p->sp != 0) {
 		if (kbt->verbose)
 			pr_err("  <%s while in user mode>\n", fault);
 	} else if (kbt->verbose) {
@@ -120,7 +120,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
 /* Is the pc pointing to a sigreturn trampoline? */
 static int is_sigreturn(unsigned long pc)
 {
-	return (pc == VDSO_BASE);
+	return current->mm && (pc == VDSO_SYM(&__vdso_rt_sigreturn));
 }
 
 /* Return a pt_regs pointer for a valid signal handler frame */
@@ -129,7 +129,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt,
 {
 	BacktraceIterator *b = &kbt->it;
 
-	if (b->pc == VDSO_BASE && b->sp < PAGE_OFFSET &&
+	if (is_sigreturn(b->pc) && b->sp < PAGE_OFFSET &&
 	    b->sp % sizeof(long) == 0) {
 		int retval;
 		pagefault_disable();
@@ -195,7 +195,7 @@ static int KBacktraceIterator_next_item_inclusive(
  */
 static void validate_stack(struct pt_regs *regs)
 {
-	int cpu = smp_processor_id();
+	int cpu = raw_smp_processor_id();
 	unsigned long ksp0 = get_current_ksp0();
 	unsigned long ksp0_base = ksp0 - THREAD_SIZE;
 	unsigned long sp = stack_pointer;
@@ -352,6 +352,26 @@ static void describe_addr(struct KBacktraceIterator *kbt,
 }
 
 /*
+ * Avoid possible crash recursion during backtrace.  If it happens, it
+ * makes it easy to lose the actual root cause of the failure, so we
+ * put a simple guard on all the backtrace loops.
+ */
+static bool start_backtrace(void)
+{
+	if (current->thread.in_backtrace) {
+		pr_err("Backtrace requested while in backtrace!\n");
+		return false;
+	}
+	current->thread.in_backtrace = true;
+	return true;
+}
+
+static void end_backtrace(void)
+{
+	current->thread.in_backtrace = false;
+}
+
+/*
  * This method wraps the backtracer's more generic support.
  * It is only invoked from the architecture-specific code; show_stack()
  * and dump_stack() (in entry.S) are architecture-independent entry points.
@@ -361,6 +381,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
 	int i;
 	int have_mmap_sem = 0;
 
+	if (!start_backtrace())
+		return;
 	if (headers) {
 		/*
 		 * Add a blank line since if we are called from panic(),
@@ -371,7 +393,7 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
 		pr_err("Starting stack dump of tid %d, pid %d (%s)"
 		       " on cpu %d at cycle %lld\n",
 		       kbt->task->pid, kbt->task->tgid, kbt->task->comm,
-		       smp_processor_id(), get_cycles());
+		       raw_smp_processor_id(), get_cycles());
 	}
 	kbt->verbose = 1;
 	i = 0;
@@ -402,6 +424,7 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
 		pr_err("Stack dump complete\n");
 	if (have_mmap_sem)
 		up_read(&kbt->task->mm->mmap_sem);
+	end_backtrace();
 }
 EXPORT_SYMBOL(tile_show_stack);
 
@@ -463,6 +486,8 @@ void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
 	int skip = trace->skip;
 	int i = 0;
 
+	if (!start_backtrace())
+		goto done;
 	if (task == NULL || task == current)
 		KBacktraceIterator_init_current(&kbt);
 	else
@@ -476,6 +501,8 @@ void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
 			break;
 		trace->entries[i++] = kbt.it.pc;
 	}
+	end_backtrace();
+done:
 	trace->nr_entries = i;
 }
 EXPORT_SYMBOL(save_stack_trace_tsk);
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c
index b881a7b..38debe7 100644
--- a/arch/tile/kernel/sys.c
+++ b/arch/tile/kernel/sys.c
@@ -38,8 +38,10 @@
 SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len,
 		unsigned long, flags)
 {
+	/* DCACHE is not particularly effective if not bound to one cpu. */
 	if (flags & DCACHE)
-		homecache_evict(cpumask_of(smp_processor_id()));
+		homecache_evict(cpumask_of(raw_smp_processor_id()));
+
 	if (flags & ICACHE)
 		flush_remote(0, HV_FLUSH_EVICT_L1I, mm_cpumask(current->mm),
 			     0, 0, 0, NULL, NULL, 0);
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index 7c353d8..5d10642 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -23,8 +23,10 @@
 #include <linux/smp.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/timekeeper_internal.h>
 #include <asm/irq_regs.h>
 #include <asm/traps.h>
+#include <asm/vdso.h>
 #include <hv/hypervisor.h>
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
@@ -110,7 +112,6 @@ void __init time_init(void)
 	setup_tile_timer();
 }
 
-
 /*
  * Define the tile timer clock event device.  The timer is driven by
  * the TILE_TIMER_CONTROL register, which consists of a 31-bit down
@@ -237,3 +238,37 @@ cycles_t ns2cycles(unsigned long nsecs)
 	struct clock_event_device *dev = &__raw_get_cpu_var(tile_timer);
 	return ((u64)nsecs * dev->mult) >> dev->shift;
 }
+
+void update_vsyscall_tz(void)
+{
+	/* Userspace gettimeofday will spin while this value is odd. */
+	++vdso_data->tz_update_count;
+	smp_wmb();
+	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
+	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
+	smp_wmb();
+	++vdso_data->tz_update_count;
+}
+
+void update_vsyscall(struct timekeeper *tk)
+{
+	struct timespec wall_time = tk_xtime(tk);
+	struct timespec *wtm = &tk->wall_to_monotonic;
+	struct clocksource *clock = tk->clock;
+
+	if (clock != &cycle_counter_cs)
+		return;
+
+	/* Userspace gettimeofday will spin while this value is odd. */
+	++vdso_data->tb_update_count;
+	smp_wmb();
+	vdso_data->xtime_tod_stamp = clock->cycle_last;
+	vdso_data->xtime_clock_sec = wall_time.tv_sec;
+	vdso_data->xtime_clock_nsec = wall_time.tv_nsec;
+	vdso_data->wtom_clock_sec = wtm->tv_sec;
+	vdso_data->wtom_clock_nsec = wtm->tv_nsec;
+	vdso_data->mult = clock->mult;
+	vdso_data->shift = clock->shift;
+	smp_wmb();
+	++vdso_data->tb_update_count;
+}
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 5b19a23..a1bbc5de 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -222,8 +222,9 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 	unsigned long address = 0;
 	bundle_bits instr;
 
-	/* Re-enable interrupts. */
-	local_irq_enable();
+	/* Re-enable interrupts, if they were previously enabled. */
+	if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
+		local_irq_enable();
 
 	/*
 	 * If it hits in kernel mode and we can't fix it up, just exit the
@@ -231,7 +232,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 	 */
 	if (!user_mode(regs)) {
 		const char *name;
-		if (fixup_exception(regs))  /* only UNALIGN_DATA in practice */
+		char buf[100];
+		if (fixup_exception(regs))  /* ILL_TRANS or UNALIGN_DATA */
 			return;
 		if (fault_num >= 0 &&
 		    fault_num < sizeof(int_name)/sizeof(int_name[0]) &&
@@ -239,10 +241,16 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 			name = int_name[fault_num];
 		else
 			name = "Unknown interrupt";
-		pr_alert("Kernel took bad trap %d (%s) at PC %#lx\n",
-			 fault_num, name, regs->pc);
 		if (fault_num == INT_GPV)
-			pr_alert("GPV_REASON is %#lx\n", reason);
+			snprintf(buf, sizeof(buf), "; GPV_REASON %#lx", reason);
+#ifdef __tilegx__
+		else if (fault_num == INT_ILL_TRANS)
+			snprintf(buf, sizeof(buf), "; address %#lx", reason);
+#endif
+		else
+			buf[0] = '\0';
+		pr_alert("Kernel took bad trap %d (%s) at PC %#lx%s\n",
+			 fault_num, name, regs->pc, buf);
 		show_regs(regs);
 		do_exit(SIGKILL);  /* FIXME: implement i386 die() */
 		return;
@@ -324,11 +332,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 		fill_ra_stack();
 
 		signo = SIGSEGV;
+		address = reason;
 		code = SEGV_MAPERR;
-		if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
-			address = regs->pc;
-		else
-			address = 0;  /* FIXME: GX: single-step for address */
 		break;
 	}
 #endif
diff --git a/arch/tile/kernel/unaligned.c b/arch/tile/kernel/unaligned.c
new file mode 100644
index 0000000..b425fb6
--- /dev/null
+++ b/arch/tile/kernel/unaligned.c
@@ -0,0 +1,1609 @@
+/*
+ * Copyright 2013 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ * A code-rewriter that handles unaligned exception.
+ */
+
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/thread_info.h>
+#include <linux/uaccess.h>
+#include <linux/mman.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/compat.h>
+#include <linux/prctl.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+#include <arch/abi.h>
+#include <arch/spr_def.h>
+#include <arch/opcode.h>
+
+
+/*
+ * This file handles unaligned exception for tile-Gx. The tilepro's unaligned
+ * exception is supported out of single_step.c
+ */
+
+int unaligned_printk;
+
+static int __init setup_unaligned_printk(char *str)
+{
+	long val;
+	if (kstrtol(str, 0, &val) != 0)
+		return 0;
+	unaligned_printk = val;
+	pr_info("Printk for each unaligned data accesses is %s\n",
+		unaligned_printk ? "enabled" : "disabled");
+	return 1;
+}
+__setup("unaligned_printk=", setup_unaligned_printk);
+
+unsigned int unaligned_fixup_count;
+
+#ifdef __tilegx__
+
+/*
+ * Unalign data jit fixup code fragement. Reserved space is 128 bytes.
+ * The 1st 64-bit word saves fault PC address, 2nd word is the fault
+ * instruction bundle followed by 14 JIT bundles.
+ */
+
+struct unaligned_jit_fragment {
+	unsigned long       pc;
+	tilegx_bundle_bits  bundle;
+	tilegx_bundle_bits  insn[14];
+};
+
+/*
+ * Check if a nop or fnop at bundle's pipeline X0.
+ */
+
+static bool is_bundle_x0_nop(tilegx_bundle_bits bundle)
+{
+	return (((get_UnaryOpcodeExtension_X0(bundle) ==
+		  NOP_UNARY_OPCODE_X0) &&
+		 (get_RRROpcodeExtension_X0(bundle) ==
+		  UNARY_RRR_0_OPCODE_X0) &&
+		 (get_Opcode_X0(bundle) ==
+		  RRR_0_OPCODE_X0)) ||
+		((get_UnaryOpcodeExtension_X0(bundle) ==
+		  FNOP_UNARY_OPCODE_X0) &&
+		 (get_RRROpcodeExtension_X0(bundle) ==
+		  UNARY_RRR_0_OPCODE_X0) &&
+		 (get_Opcode_X0(bundle) ==
+		  RRR_0_OPCODE_X0)));
+}
+
+/*
+ * Check if nop or fnop at bundle's pipeline X1.
+ */
+
+static bool is_bundle_x1_nop(tilegx_bundle_bits bundle)
+{
+	return (((get_UnaryOpcodeExtension_X1(bundle) ==
+		  NOP_UNARY_OPCODE_X1) &&
+		 (get_RRROpcodeExtension_X1(bundle) ==
+		  UNARY_RRR_0_OPCODE_X1) &&
+		 (get_Opcode_X1(bundle) ==
+		  RRR_0_OPCODE_X1)) ||
+		((get_UnaryOpcodeExtension_X1(bundle) ==
+		  FNOP_UNARY_OPCODE_X1) &&
+		 (get_RRROpcodeExtension_X1(bundle) ==
+		  UNARY_RRR_0_OPCODE_X1) &&
+		 (get_Opcode_X1(bundle) ==
+		  RRR_0_OPCODE_X1)));
+}
+
+/*
+ * Check if nop or fnop at bundle's Y0 pipeline.
+ */
+
+static bool is_bundle_y0_nop(tilegx_bundle_bits bundle)
+{
+	return (((get_UnaryOpcodeExtension_Y0(bundle) ==
+		  NOP_UNARY_OPCODE_Y0) &&
+		 (get_RRROpcodeExtension_Y0(bundle) ==
+		  UNARY_RRR_1_OPCODE_Y0) &&
+		 (get_Opcode_Y0(bundle) ==
+		  RRR_1_OPCODE_Y0)) ||
+		((get_UnaryOpcodeExtension_Y0(bundle) ==
+		  FNOP_UNARY_OPCODE_Y0) &&
+		 (get_RRROpcodeExtension_Y0(bundle) ==
+		  UNARY_RRR_1_OPCODE_Y0) &&
+		 (get_Opcode_Y0(bundle) ==
+		  RRR_1_OPCODE_Y0)));
+}
+
+/*
+ * Check if nop or fnop at bundle's pipeline Y1.
+ */
+
+static bool is_bundle_y1_nop(tilegx_bundle_bits bundle)
+{
+	return (((get_UnaryOpcodeExtension_Y1(bundle) ==
+		  NOP_UNARY_OPCODE_Y1) &&
+		 (get_RRROpcodeExtension_Y1(bundle) ==
+		  UNARY_RRR_1_OPCODE_Y1) &&
+		 (get_Opcode_Y1(bundle) ==
+		  RRR_1_OPCODE_Y1)) ||
+		((get_UnaryOpcodeExtension_Y1(bundle) ==
+		  FNOP_UNARY_OPCODE_Y1) &&
+		 (get_RRROpcodeExtension_Y1(bundle) ==
+		  UNARY_RRR_1_OPCODE_Y1) &&
+		 (get_Opcode_Y1(bundle) ==
+		  RRR_1_OPCODE_Y1)));
+}
+
+/*
+ * Test if a bundle's y0 and y1 pipelines are both nop or fnop.
+ */
+
+static bool is_y0_y1_nop(tilegx_bundle_bits bundle)
+{
+	return is_bundle_y0_nop(bundle) && is_bundle_y1_nop(bundle);
+}
+
+/*
+ * Test if a bundle's x0 and x1 pipelines are both nop or fnop.
+ */
+
+static bool is_x0_x1_nop(tilegx_bundle_bits bundle)
+{
+	return is_bundle_x0_nop(bundle) && is_bundle_x1_nop(bundle);
+}
+
+/*
+ * Find the destination, source registers of fault unalign access instruction
+ * at X1 or Y2. Also, allocate up to 3 scratch registers clob1, clob2 and
+ * clob3, which are guaranteed different from any register used in the fault
+ * bundle. r_alias is used to return if the other instructions other than the
+ * unalign load/store shares same register with ra, rb and rd.
+ */
+
+static void find_regs(tilegx_bundle_bits bundle, uint64_t *rd, uint64_t *ra,
+		      uint64_t *rb, uint64_t *clob1, uint64_t *clob2,
+		      uint64_t *clob3, bool *r_alias)
+{
+	int i;
+	uint64_t reg;
+	uint64_t reg_map = 0, alias_reg_map = 0, map;
+	bool alias;
+
+	*ra = -1;
+	*rb = -1;
+
+	if (rd)
+		*rd = -1;
+
+	*clob1 = -1;
+	*clob2 = -1;
+	*clob3 = -1;
+	alias = false;
+
+	/*
+	 * Parse fault bundle, find potential used registers and mark
+	 * corresponding bits in reg_map and alias_map. These 2 bit maps
+	 * are used to find the scratch registers and determine if there
+	 * is register alais.
+	 */
+	if (bundle & TILEGX_BUNDLE_MODE_MASK) {  /* Y Mode Bundle. */
+
+		reg = get_SrcA_Y2(bundle);
+		reg_map |= 1ULL << reg;
+		*ra = reg;
+		reg = get_SrcBDest_Y2(bundle);
+		reg_map |= 1ULL << reg;
+
+		if (rd) {
+			/* Load. */
+			*rd = reg;
+			alias_reg_map = (1ULL << *rd) | (1ULL << *ra);
+		} else {
+			/* Store. */
+			*rb = reg;
+			alias_reg_map = (1ULL << *ra) | (1ULL << *rb);
+		}
+
+		if (!is_bundle_y1_nop(bundle)) {
+			reg = get_SrcA_Y1(bundle);
+			reg_map |= (1ULL << reg);
+			map = (1ULL << reg);
+
+			reg = get_SrcB_Y1(bundle);
+			reg_map |= (1ULL << reg);
+			map |= (1ULL << reg);
+
+			reg = get_Dest_Y1(bundle);
+			reg_map |= (1ULL << reg);
+			map |= (1ULL << reg);
+
+			if (map & alias_reg_map)
+				alias = true;
+		}
+
+		if (!is_bundle_y0_nop(bundle)) {
+			reg = get_SrcA_Y0(bundle);
+			reg_map |= (1ULL << reg);
+			map = (1ULL << reg);
+
+			reg = get_SrcB_Y0(bundle);
+			reg_map |= (1ULL << reg);
+			map |= (1ULL << reg);
+
+			reg = get_Dest_Y0(bundle);
+			reg_map |= (1ULL << reg);
+			map |= (1ULL << reg);
+
+			if (map & alias_reg_map)
+				alias = true;
+		}
+	} else	{ /* X Mode Bundle. */
+
+		reg = get_SrcA_X1(bundle);
+		reg_map |= (1ULL << reg);
+		*ra = reg;
+		if (rd)	{
+			/* Load. */
+			reg = get_Dest_X1(bundle);
+			reg_map |= (1ULL << reg);
+			*rd = reg;
+			alias_reg_map = (1ULL << *rd) | (1ULL << *ra);
+		} else {
+			/* Store. */
+			reg = get_SrcB_X1(bundle);
+			reg_map |= (1ULL << reg);
+			*rb = reg;
+			alias_reg_map = (1ULL << *ra) | (1ULL << *rb);
+		}
+
+		if (!is_bundle_x0_nop(bundle)) {
+			reg = get_SrcA_X0(bundle);
+			reg_map |= (1ULL << reg);
+			map = (1ULL << reg);
+
+			reg = get_SrcB_X0(bundle);
+			reg_map |= (1ULL << reg);
+			map |= (1ULL << reg);
+
+			reg = get_Dest_X0(bundle);
+			reg_map |= (1ULL << reg);
+			map |= (1ULL << reg);
+
+			if (map & alias_reg_map)
+				alias = true;
+		}
+	}
+
+	/*
+	 * "alias" indicates if the unalign access registers have collision
+	 * with others in the same bundle. We jsut simply test all register
+	 * operands case (RRR), ignored the case with immidate. If a bundle
+	 * has no register alias, we may do fixup in a simple or fast manner.
+	 * So if an immidata field happens to hit with a register, we may end
+	 * up fall back to the generic handling.
+	 */
+
+	*r_alias = alias;
+
+	/* Flip bits on reg_map. */
+	reg_map ^= -1ULL;
+
+	/* Scan reg_map lower 54(TREG_SP) bits to find 3 set bits. */
+	for (i = 0; i < TREG_SP; i++) {
+		if (reg_map & (0x1ULL << i)) {
+			if (*clob1 == -1) {
+				*clob1 = i;
+			} else if (*clob2 == -1) {
+				*clob2 = i;
+			} else if (*clob3 == -1) {
+				*clob3 = i;
+				return;
+			}
+		}
+	}
+}
+
+/*
+ * Sanity check for register ra, rb, rd, clob1/2/3. Return true if any of them
+ * is unexpected.
+ */
+
+static bool check_regs(uint64_t rd, uint64_t ra, uint64_t rb,
+		       uint64_t clob1, uint64_t clob2,  uint64_t clob3)
+{
+	bool unexpected = false;
+	if ((ra >= 56) && (ra != TREG_ZERO))
+		unexpected = true;
+
+	if ((clob1 >= 56) || (clob2 >= 56) || (clob3 >= 56))
+		unexpected = true;
+
+	if (rd != -1) {
+		if ((rd >= 56) && (rd != TREG_ZERO))
+			unexpected = true;
+	} else {
+		if ((rb >= 56) && (rb != TREG_ZERO))
+			unexpected = true;
+	}
+	return unexpected;
+}
+
+
+#define  GX_INSN_X0_MASK   ((1ULL << 31) - 1)
+#define  GX_INSN_X1_MASK   (((1ULL << 31) - 1) << 31)
+#define  GX_INSN_Y0_MASK   ((0xFULL << 27) | (0xFFFFFULL))
+#define  GX_INSN_Y1_MASK   (GX_INSN_Y0_MASK << 31)
+#define  GX_INSN_Y2_MASK   ((0x7FULL << 51) | (0x7FULL << 20))
+
+#ifdef __LITTLE_ENDIAN
+#define  GX_INSN_BSWAP(_bundle_)    (_bundle_)
+#else
+#define  GX_INSN_BSWAP(_bundle_)    swab64(_bundle_)
+#endif /* __LITTLE_ENDIAN */
+
+/*
+ * __JIT_CODE(.) creates template bundles in .rodata.unalign_data section.
+ * The corresponding static function jix_x#_###(.) generates partial or
+ * whole bundle based on the template and given arguments.
+ */
+
+#define __JIT_CODE(_X_)						\
+	asm (".pushsection .rodata.unalign_data, \"a\"\n"	\
+	     _X_"\n"						\
+	     ".popsection\n")
+
+__JIT_CODE("__unalign_jit_x1_mtspr:   {mtspr 0,  r0}");
+static tilegx_bundle_bits jit_x1_mtspr(int spr, int reg)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_mtspr;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_mtspr) & GX_INSN_X1_MASK) |
+		create_MT_Imm14_X1(spr) | create_SrcA_X1(reg);
+}
+
+__JIT_CODE("__unalign_jit_x1_mfspr:   {mfspr r0, 0}");
+static tilegx_bundle_bits  jit_x1_mfspr(int reg, int spr)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_mfspr;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_mfspr) & GX_INSN_X1_MASK) |
+		create_MF_Imm14_X1(spr) | create_Dest_X1(reg);
+}
+
+__JIT_CODE("__unalign_jit_x0_addi:   {addi  r0, r0, 0; iret}");
+static tilegx_bundle_bits  jit_x0_addi(int rd, int ra, int imm8)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x0_addi;
+	return (GX_INSN_BSWAP(__unalign_jit_x0_addi) & GX_INSN_X0_MASK) |
+		create_Dest_X0(rd) | create_SrcA_X0(ra) |
+		create_Imm8_X0(imm8);
+}
+
+__JIT_CODE("__unalign_jit_x1_ldna:   {ldna  r0, r0}");
+static tilegx_bundle_bits  jit_x1_ldna(int rd, int ra)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_ldna;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_ldna) &  GX_INSN_X1_MASK) |
+		create_Dest_X1(rd) | create_SrcA_X1(ra);
+}
+
+__JIT_CODE("__unalign_jit_x0_dblalign:   {dblalign r0, r0 ,r0}");
+static tilegx_bundle_bits  jit_x0_dblalign(int rd, int ra, int rb)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x0_dblalign;
+	return (GX_INSN_BSWAP(__unalign_jit_x0_dblalign) & GX_INSN_X0_MASK) |
+		create_Dest_X0(rd) | create_SrcA_X0(ra) |
+		create_SrcB_X0(rb);
+}
+
+__JIT_CODE("__unalign_jit_x1_iret:   {iret}");
+static tilegx_bundle_bits  jit_x1_iret(void)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_iret;
+	return GX_INSN_BSWAP(__unalign_jit_x1_iret) & GX_INSN_X1_MASK;
+}
+
+__JIT_CODE("__unalign_jit_x01_fnop:   {fnop;fnop}");
+static tilegx_bundle_bits  jit_x0_fnop(void)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x01_fnop;
+	return GX_INSN_BSWAP(__unalign_jit_x01_fnop) & GX_INSN_X0_MASK;
+}
+
+static tilegx_bundle_bits  jit_x1_fnop(void)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x01_fnop;
+	return GX_INSN_BSWAP(__unalign_jit_x01_fnop) & GX_INSN_X1_MASK;
+}
+
+__JIT_CODE("__unalign_jit_y2_dummy:   {fnop; fnop; ld zero, sp}");
+static tilegx_bundle_bits  jit_y2_dummy(void)
+{
+	extern  tilegx_bundle_bits __unalign_jit_y2_dummy;
+	return GX_INSN_BSWAP(__unalign_jit_y2_dummy) & GX_INSN_Y2_MASK;
+}
+
+static tilegx_bundle_bits  jit_y1_fnop(void)
+{
+	extern  tilegx_bundle_bits __unalign_jit_y2_dummy;
+	return GX_INSN_BSWAP(__unalign_jit_y2_dummy) & GX_INSN_Y1_MASK;
+}
+
+__JIT_CODE("__unalign_jit_x1_st1_add:  {st1_add r1, r0, 0}");
+static tilegx_bundle_bits  jit_x1_st1_add(int ra, int rb, int imm8)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_st1_add;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_st1_add) &
+		(~create_SrcA_X1(-1)) &
+		GX_INSN_X1_MASK) | create_SrcA_X1(ra) |
+		create_SrcB_X1(rb) | create_Dest_Imm8_X1(imm8);
+}
+
+__JIT_CODE("__unalign_jit_x1_st:  {crc32_8 r1, r0, r0; st  r0, r0}");
+static tilegx_bundle_bits  jit_x1_st(int ra, int rb)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_st;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_st) & GX_INSN_X1_MASK) |
+		create_SrcA_X1(ra) | create_SrcB_X1(rb);
+}
+
+__JIT_CODE("__unalign_jit_x1_st_add:  {st_add  r1, r0, 0}");
+static tilegx_bundle_bits  jit_x1_st_add(int ra, int rb, int imm8)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_st_add;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_st_add) &
+		(~create_SrcA_X1(-1)) &
+		GX_INSN_X1_MASK) | create_SrcA_X1(ra) |
+		create_SrcB_X1(rb) | create_Dest_Imm8_X1(imm8);
+}
+
+__JIT_CODE("__unalign_jit_x1_ld:  {crc32_8 r1, r0, r0; ld  r0, r0}");
+static tilegx_bundle_bits  jit_x1_ld(int rd, int ra)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_ld;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_ld) & GX_INSN_X1_MASK) |
+		create_Dest_X1(rd) | create_SrcA_X1(ra);
+}
+
+__JIT_CODE("__unalign_jit_x1_ld_add:  {ld_add  r1, r0, 0}");
+static tilegx_bundle_bits  jit_x1_ld_add(int rd, int ra, int imm8)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_ld_add;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_ld_add) &
+		(~create_Dest_X1(-1)) &
+		GX_INSN_X1_MASK) | create_Dest_X1(rd) |
+		create_SrcA_X1(ra) | create_Imm8_X1(imm8);
+}
+
+__JIT_CODE("__unalign_jit_x0_bfexts:  {bfexts r0, r0, 0, 0}");
+static tilegx_bundle_bits  jit_x0_bfexts(int rd, int ra, int bfs, int bfe)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x0_bfexts;
+	return (GX_INSN_BSWAP(__unalign_jit_x0_bfexts) &
+		GX_INSN_X0_MASK) |
+		create_Dest_X0(rd) | create_SrcA_X0(ra) |
+		create_BFStart_X0(bfs) | create_BFEnd_X0(bfe);
+}
+
+__JIT_CODE("__unalign_jit_x0_bfextu:  {bfextu r0, r0, 0, 0}");
+static tilegx_bundle_bits  jit_x0_bfextu(int rd, int ra, int bfs, int bfe)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x0_bfextu;
+	return (GX_INSN_BSWAP(__unalign_jit_x0_bfextu) &
+		GX_INSN_X0_MASK) |
+		create_Dest_X0(rd) | create_SrcA_X0(ra) |
+		create_BFStart_X0(bfs) | create_BFEnd_X0(bfe);
+}
+
+__JIT_CODE("__unalign_jit_x1_addi:  {bfextu r1, r1, 0, 0; addi r0, r0, 0}");
+static tilegx_bundle_bits  jit_x1_addi(int rd, int ra, int imm8)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_addi;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_addi) & GX_INSN_X1_MASK) |
+		create_Dest_X1(rd) | create_SrcA_X1(ra) |
+		create_Imm8_X1(imm8);
+}
+
+__JIT_CODE("__unalign_jit_x0_shrui:  {shrui r0, r0, 0; iret}");
+static tilegx_bundle_bits  jit_x0_shrui(int rd, int ra, int imm6)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x0_shrui;
+	return (GX_INSN_BSWAP(__unalign_jit_x0_shrui) &
+		GX_INSN_X0_MASK) |
+		create_Dest_X0(rd) | create_SrcA_X0(ra) |
+		create_ShAmt_X0(imm6);
+}
+
+__JIT_CODE("__unalign_jit_x0_rotli:  {rotli r0, r0, 0; iret}");
+static tilegx_bundle_bits  jit_x0_rotli(int rd, int ra, int imm6)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x0_rotli;
+	return (GX_INSN_BSWAP(__unalign_jit_x0_rotli) &
+		GX_INSN_X0_MASK) |
+		create_Dest_X0(rd) | create_SrcA_X0(ra) |
+		create_ShAmt_X0(imm6);
+}
+
+__JIT_CODE("__unalign_jit_x1_bnezt:  {bnezt r0, __unalign_jit_x1_bnezt}");
+static tilegx_bundle_bits  jit_x1_bnezt(int ra, int broff)
+{
+	extern  tilegx_bundle_bits __unalign_jit_x1_bnezt;
+	return (GX_INSN_BSWAP(__unalign_jit_x1_bnezt) &
+		GX_INSN_X1_MASK) |
+		create_SrcA_X1(ra) | create_BrOff_X1(broff);
+}
+
+#undef __JIT_CODE
+
+/*
+ * This function generates unalign fixup JIT.
+ *
+ * We fist find unalign load/store instruction's destination, source
+ * reguisters: ra, rb and rd. and 3 scratch registers by calling
+ * find_regs(...). 3 scratch clobbers should not alias with any register
+ * used in the fault bundle. Then analyze the fault bundle to determine
+ * if it's a load or store, operand width, branch or address increment etc.
+ * At last generated JIT is copied into JIT code area in user space.
+ */
+
+static
+void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle,
+		    int align_ctl)
+{
+	struct thread_info *info = current_thread_info();
+	struct unaligned_jit_fragment frag;
+	struct unaligned_jit_fragment *jit_code_area;
+	tilegx_bundle_bits bundle_2 = 0;
+	/* If bundle_2_enable = false, bundle_2 is fnop/nop operation. */
+	bool     bundle_2_enable = true;
+	uint64_t ra, rb, rd = -1, clob1, clob2, clob3;
+	/*
+	 * Indicate if the unalign access
+	 * instruction's registers hit with
+	 * others in the same bundle.
+	 */
+	bool     alias = false;
+	bool     load_n_store = true;
+	bool     load_store_signed = false;
+	unsigned int  load_store_size = 8;
+	bool     y1_br = false;  /* True, for a branch in same bundle at Y1.*/
+	int      y1_br_reg = 0;
+	/* True for link operation. i.e. jalr or lnk at Y1 */
+	bool     y1_lr = false;
+	int      y1_lr_reg = 0;
+	bool     x1_add = false;/* True, for load/store ADD instruction at X1*/
+	int      x1_add_imm8 = 0;
+	bool     unexpected = false;
+	int      n = 0, k;
+
+	jit_code_area =
+		(struct unaligned_jit_fragment *)(info->unalign_jit_base);
+
+	memset((void *)&frag, 0, sizeof(frag));
+
+	/* 0: X mode, Otherwise: Y mode. */
+	if (bundle & TILEGX_BUNDLE_MODE_MASK) {
+		unsigned int mod, opcode;
+
+		if (get_Opcode_Y1(bundle) == RRR_1_OPCODE_Y1 &&
+		    get_RRROpcodeExtension_Y1(bundle) ==
+		    UNARY_RRR_1_OPCODE_Y1) {
+
+			opcode = get_UnaryOpcodeExtension_Y1(bundle);
+
+			/*
+			 * Test "jalr", "jalrp", "jr", "jrp" instruction at Y1
+			 * pipeline.
+			 */
+			switch (opcode) {
+			case JALR_UNARY_OPCODE_Y1:
+			case JALRP_UNARY_OPCODE_Y1:
+				y1_lr = true;
+				y1_lr_reg = 55; /* Link register. */
+				/* FALLTHROUGH */
+			case JR_UNARY_OPCODE_Y1:
+			case JRP_UNARY_OPCODE_Y1:
+				y1_br = true;
+				y1_br_reg = get_SrcA_Y1(bundle);
+				break;
+			case LNK_UNARY_OPCODE_Y1:
+				/* "lnk" at Y1 pipeline. */
+				y1_lr = true;
+				y1_lr_reg = get_Dest_Y1(bundle);
+				break;
+			}
+		}
+
+		opcode = get_Opcode_Y2(bundle);
+		mod = get_Mode(bundle);
+
+		/*
+		 *  bundle_2 is bundle after making Y2 as a dummy operation
+		 *  - ld zero, sp
+		 */
+		bundle_2 = (bundle & (~GX_INSN_Y2_MASK)) | jit_y2_dummy();
+
+		/* Make Y1 as fnop if Y1 is a branch or lnk operation. */
+		if (y1_br || y1_lr) {
+			bundle_2 &= ~(GX_INSN_Y1_MASK);
+			bundle_2 |= jit_y1_fnop();
+		}
+
+		if (is_y0_y1_nop(bundle_2))
+			bundle_2_enable = false;
+
+		if (mod == MODE_OPCODE_YC2) {
+			/* Store. */
+			load_n_store = false;
+			load_store_size = 1 << opcode;
+			load_store_signed = false;
+			find_regs(bundle, 0, &ra, &rb, &clob1, &clob2,
+				  &clob3, &alias);
+			if (load_store_size > 8)
+				unexpected = true;
+		} else {
+			/* Load. */
+			load_n_store = true;
+			if (mod == MODE_OPCODE_YB2) {
+				switch (opcode) {
+				case LD_OPCODE_Y2:
+					load_store_signed = false;
+					load_store_size = 8;
+					break;
+				case LD4S_OPCODE_Y2:
+					load_store_signed = true;
+					load_store_size = 4;
+					break;
+				case LD4U_OPCODE_Y2:
+					load_store_signed = false;
+					load_store_size = 4;
+					break;
+				default:
+					unexpected = true;
+				}
+			} else if (mod == MODE_OPCODE_YA2) {
+				if (opcode == LD2S_OPCODE_Y2) {
+					load_store_signed = true;
+					load_store_size = 2;
+				} else if (opcode == LD2U_OPCODE_Y2) {
+					load_store_signed = false;
+					load_store_size = 2;
+				} else
+					unexpected = true;
+			} else
+				unexpected = true;
+			find_regs(bundle, &rd, &ra, &rb, &clob1, &clob2,
+				  &clob3, &alias);
+		}
+	} else {
+		unsigned int opcode;
+
+		/* bundle_2 is bundle after making X1 as "fnop". */
+		bundle_2 = (bundle & (~GX_INSN_X1_MASK)) | jit_x1_fnop();
+
+		if (is_x0_x1_nop(bundle_2))
+			bundle_2_enable = false;
+
+		if (get_Opcode_X1(bundle) == RRR_0_OPCODE_X1) {
+			opcode = get_UnaryOpcodeExtension_X1(bundle);
+
+			if (get_RRROpcodeExtension_X1(bundle) ==
+			    UNARY_RRR_0_OPCODE_X1) {
+				load_n_store = true;
+				find_regs(bundle, &rd, &ra, &rb, &clob1,
+					  &clob2, &clob3, &alias);
+
+				switch (opcode) {
+				case LD_UNARY_OPCODE_X1:
+					load_store_signed = false;
+					load_store_size = 8;
+					break;
+				case LD4S_UNARY_OPCODE_X1:
+					load_store_signed = true;
+					/* FALLTHROUGH */
+				case LD4U_UNARY_OPCODE_X1:
+					load_store_size = 4;
+					break;
+
+				case LD2S_UNARY_OPCODE_X1:
+					load_store_signed = true;
+					/* FALLTHROUGH */
+				case LD2U_UNARY_OPCODE_X1:
+					load_store_size = 2;
+					break;
+				default:
+					unexpected = true;
+				}
+			} else {
+				load_n_store = false;
+				load_store_signed = false;
+				find_regs(bundle, 0, &ra, &rb,
+					  &clob1, &clob2, &clob3,
+					  &alias);
+
+				opcode = get_RRROpcodeExtension_X1(bundle);
+				switch (opcode)	{
+				case ST_RRR_0_OPCODE_X1:
+					load_store_size = 8;
+					break;
+				case ST4_RRR_0_OPCODE_X1:
+					load_store_size = 4;
+					break;
+				case ST2_RRR_0_OPCODE_X1:
+					load_store_size = 2;
+					break;
+				default:
+					unexpected = true;
+				}
+			}
+		} else if (get_Opcode_X1(bundle) == IMM8_OPCODE_X1) {
+			load_n_store = true;
+			opcode = get_Imm8OpcodeExtension_X1(bundle);
+			switch (opcode)	{
+			case LD_ADD_IMM8_OPCODE_X1:
+				load_store_size = 8;
+				break;
+
+			case LD4S_ADD_IMM8_OPCODE_X1:
+				load_store_signed = true;
+				/* FALLTHROUGH */
+			case LD4U_ADD_IMM8_OPCODE_X1:
+				load_store_size = 4;
+				break;
+
+			case LD2S_ADD_IMM8_OPCODE_X1:
+				load_store_signed = true;
+				/* FALLTHROUGH */
+			case LD2U_ADD_IMM8_OPCODE_X1:
+				load_store_size = 2;
+				break;
+
+			case ST_ADD_IMM8_OPCODE_X1:
+				load_n_store = false;
+				load_store_size = 8;
+				break;
+			case ST4_ADD_IMM8_OPCODE_X1:
+				load_n_store = false;
+				load_store_size = 4;
+				break;
+			case ST2_ADD_IMM8_OPCODE_X1:
+				load_n_store = false;
+				load_store_size = 2;
+				break;
+			default:
+				unexpected = true;
+			}
+
+			if (!unexpected) {
+				x1_add = true;
+				if (load_n_store)
+					x1_add_imm8 = get_Imm8_X1(bundle);
+				else
+					x1_add_imm8 = get_Dest_Imm8_X1(bundle);
+			}
+
+			find_regs(bundle, load_n_store ? (&rd) : NULL,
+				  &ra, &rb, &clob1, &clob2, &clob3, &alias);
+		} else
+			unexpected = true;
+	}
+
+	/*
+	 * Some sanity check for register numbers extracted from fault bundle.
+	 */
+	if (check_regs(rd, ra, rb, clob1, clob2, clob3) == true)
+		unexpected = true;
+
+	/* Give warning if register ra has an aligned address. */
+	if (!unexpected)
+		WARN_ON(!((load_store_size - 1) & (regs->regs[ra])));
+
+
+	/*
+	 * Fault came from kernel space, here we only need take care of
+	 * unaligned "get_user/put_user" macros defined in "uaccess.h".
+	 * Basically, we will handle bundle like this:
+	 * {ld/2u/4s rd, ra; movei rx, 0} or {st/2/4 ra, rb; movei rx, 0}
+	 * (Refer to file "arch/tile/include/asm/uaccess.h" for details).
+	 * For either load or store, byte-wise operation is performed by calling
+	 * get_user() or put_user(). If the macro returns non-zero value,
+	 * set the value to rx, otherwise set zero to rx. Finally make pc point
+	 * to next bundle and return.
+	 */
+
+	if (EX1_PL(regs->ex1) != USER_PL) {
+
+		unsigned long rx = 0;
+		unsigned long x = 0, ret = 0;
+
+		if (y1_br || y1_lr || x1_add ||
+		    (load_store_signed !=
+		     (load_n_store && load_store_size == 4))) {
+			/* No branch, link, wrong sign-ext or load/store add. */
+			unexpected = true;
+		} else if (!unexpected) {
+			if (bundle & TILEGX_BUNDLE_MODE_MASK) {
+				/*
+				 * Fault bundle is Y mode.
+				 * Check if the Y1 and Y0 is the form of
+				 * { movei rx, 0; nop/fnop }, if yes,
+				 * find the rx.
+				 */
+
+				if ((get_Opcode_Y1(bundle) == ADDI_OPCODE_Y1)
+				    && (get_SrcA_Y1(bundle) == TREG_ZERO) &&
+				    (get_Imm8_Y1(bundle) == 0) &&
+				    is_bundle_y0_nop(bundle)) {
+					rx = get_Dest_Y1(bundle);
+				} else if ((get_Opcode_Y0(bundle) ==
+					    ADDI_OPCODE_Y0) &&
+					   (get_SrcA_Y0(bundle) == TREG_ZERO) &&
+					   (get_Imm8_Y0(bundle) == 0) &&
+					   is_bundle_y1_nop(bundle)) {
+					rx = get_Dest_Y0(bundle);
+				} else {
+					unexpected = true;
+				}
+			} else {
+				/*
+				 * Fault bundle is X mode.
+				 * Check if the X0 is 'movei rx, 0',
+				 * if yes, find the rx.
+				 */
+
+				if ((get_Opcode_X0(bundle) == IMM8_OPCODE_X0)
+				    && (get_Imm8OpcodeExtension_X0(bundle) ==
+					ADDI_IMM8_OPCODE_X0) &&
+				    (get_SrcA_X0(bundle) == TREG_ZERO) &&
+				    (get_Imm8_X0(bundle) == 0)) {
+					rx = get_Dest_X0(bundle);
+				} else {
+					unexpected = true;
+				}
+			}
+
+			/* rx should be less than 56. */
+			if (!unexpected && (rx >= 56))
+				unexpected = true;
+		}
+
+		if (!search_exception_tables(regs->pc)) {
+			/* No fixup in the exception tables for the pc. */
+			unexpected = true;
+		}
+
+		if (unexpected) {
+			/* Unexpected unalign kernel fault. */
+			struct task_struct *tsk = validate_current();
+
+			bust_spinlocks(1);
+
+			show_regs(regs);
+
+			if (unlikely(tsk->pid < 2)) {
+				panic("Kernel unalign fault running %s!",
+				      tsk->pid ? "init" : "the idle task");
+			}
+#ifdef SUPPORT_DIE
+			die("Oops", regs);
+#endif
+			bust_spinlocks(1);
+
+			do_group_exit(SIGKILL);
+
+		} else {
+			unsigned long i, b = 0;
+			unsigned char *ptr =
+				(unsigned char *)regs->regs[ra];
+			if (load_n_store) {
+				/* handle get_user(x, ptr) */
+				for (i = 0; i < load_store_size; i++) {
+					ret = get_user(b, ptr++);
+					if (!ret) {
+						/* Success! update x. */
+#ifdef __LITTLE_ENDIAN
+						x |= (b << (8 * i));
+#else
+						x <<= 8;
+						x |= b;
+#endif /* __LITTLE_ENDIAN */
+					} else {
+						x = 0;
+						break;
+					}
+				}
+
+				/* Sign-extend 4-byte loads. */
+				if (load_store_size == 4)
+					x = (long)(int)x;
+
+				/* Set register rd. */
+				regs->regs[rd] = x;
+
+				/* Set register rx. */
+				regs->regs[rx] = ret;
+
+				/* Bump pc. */
+				regs->pc += 8;
+
+			} else {
+				/* Handle put_user(x, ptr) */
+				x = regs->regs[rb];
+#ifdef __LITTLE_ENDIAN
+				b = x;
+#else
+				/*
+				 * Swap x in order to store x from low
+				 * to high memory same as the
+				 * little-endian case.
+				 */
+				switch (load_store_size) {
+				case 8:
+					b = swab64(x);
+					break;
+				case 4:
+					b = swab32(x);
+					break;
+				case 2:
+					b = swab16(x);
+					break;
+				}
+#endif /* __LITTLE_ENDIAN */
+				for (i = 0; i < load_store_size; i++) {
+					ret = put_user(b, ptr++);
+					if (ret)
+						break;
+					/* Success! shift 1 byte. */
+					b >>= 8;
+				}
+				/* Set register rx. */
+				regs->regs[rx] = ret;
+
+				/* Bump pc. */
+				regs->pc += 8;
+			}
+		}
+
+		unaligned_fixup_count++;
+
+		if (unaligned_printk) {
+			pr_info("%s/%d. Unalign fixup for kernel access "
+				"to userspace %lx.",
+				current->comm, current->pid, regs->regs[ra]);
+		}
+
+		/* Done! Return to the exception handler. */
+		return;
+	}
+
+	if ((align_ctl == 0) || unexpected) {
+		siginfo_t info = {
+			.si_signo = SIGBUS,
+			.si_code = BUS_ADRALN,
+			.si_addr = (unsigned char __user *)0
+		};
+		if (unaligned_printk)
+			pr_info("Unalign bundle: unexp @%llx, %llx",
+				(unsigned long long)regs->pc,
+				(unsigned long long)bundle);
+
+		if (ra < 56) {
+			unsigned long uaa = (unsigned long)regs->regs[ra];
+			/* Set bus Address. */
+			info.si_addr = (unsigned char __user *)uaa;
+		}
+
+		unaligned_fixup_count++;
+
+		trace_unhandled_signal("unaligned fixup trap", regs,
+				       (unsigned long)info.si_addr, SIGBUS);
+		force_sig_info(info.si_signo, &info, current);
+		return;
+	}
+
+#ifdef __LITTLE_ENDIAN
+#define UA_FIXUP_ADDR_DELTA          1
+#define UA_FIXUP_BFEXT_START(_B_)    0
+#define UA_FIXUP_BFEXT_END(_B_)     (8 * (_B_) - 1)
+#else /* __BIG_ENDIAN */
+#define UA_FIXUP_ADDR_DELTA          -1
+#define UA_FIXUP_BFEXT_START(_B_)   (64 - 8 * (_B_))
+#define UA_FIXUP_BFEXT_END(_B_)      63
+#endif /* __LITTLE_ENDIAN */
+
+
+
+	if ((ra != rb) && (rd != TREG_SP) && !alias &&
+	    !y1_br && !y1_lr && !x1_add) {
+		/*
+		 * Simple case: ra != rb and no register alias found,
+		 * and no branch or link. This will be the majority.
+		 * We can do a little better for simplae case than the
+		 * generic scheme below.
+		 */
+		if (!load_n_store) {
+			/*
+			 * Simple store: ra != rb, no need for scratch register.
+			 * Just store and rotate to right bytewise.
+			 */
+#ifdef __BIG_ENDIAN
+			frag.insn[n++] =
+				jit_x0_addi(ra, ra, load_store_size - 1) |
+				jit_x1_fnop();
+#endif /* __BIG_ENDIAN */
+			for (k = 0; k < load_store_size; k++) {
+				/* Store a byte. */
+				frag.insn[n++] =
+					jit_x0_rotli(rb, rb, 56) |
+					jit_x1_st1_add(ra, rb,
+						       UA_FIXUP_ADDR_DELTA);
+			}
+#ifdef __BIG_ENDIAN
+			frag.insn[n] = jit_x1_addi(ra, ra, 1);
+#else
+			frag.insn[n] = jit_x1_addi(ra, ra,
+						   -1 * load_store_size);
+#endif /* __LITTLE_ENDIAN */
+
+			if (load_store_size == 8) {
+				frag.insn[n] |= jit_x0_fnop();
+			} else if (load_store_size == 4) {
+				frag.insn[n] |= jit_x0_rotli(rb, rb, 32);
+			} else { /* = 2 */
+				frag.insn[n] |= jit_x0_rotli(rb, rb, 16);
+			}
+			n++;
+			if (bundle_2_enable)
+				frag.insn[n++] = bundle_2;
+			frag.insn[n++] = jit_x0_fnop() | jit_x1_iret();
+		} else {
+			if (rd == ra) {
+				/* Use two clobber registers: clob1/2. */
+				frag.insn[n++] =
+					jit_x0_addi(TREG_SP, TREG_SP, -16) |
+					jit_x1_fnop();
+				frag.insn[n++] =
+					jit_x0_addi(clob1, ra, 7) |
+					jit_x1_st_add(TREG_SP, clob1, -8);
+				frag.insn[n++] =
+					jit_x0_addi(clob2, ra, 0) |
+					jit_x1_st(TREG_SP, clob2);
+				frag.insn[n++] =
+					jit_x0_fnop() |
+					jit_x1_ldna(rd, ra);
+				frag.insn[n++] =
+					jit_x0_fnop() |
+					jit_x1_ldna(clob1, clob1);
+				/*
+				 * Note: we must make sure that rd must not
+				 * be sp. Recover clob1/2 from stack.
+				 */
+				frag.insn[n++] =
+					jit_x0_dblalign(rd, clob1, clob2) |
+					jit_x1_ld_add(clob2, TREG_SP, 8);
+				frag.insn[n++] =
+					jit_x0_fnop() |
+					jit_x1_ld_add(clob1, TREG_SP, 16);
+			} else {
+				/* Use one clobber register: clob1 only. */
+				frag.insn[n++] =
+					jit_x0_addi(TREG_SP, TREG_SP, -16) |
+					jit_x1_fnop();
+				frag.insn[n++] =
+					jit_x0_addi(clob1, ra, 7) |
+					jit_x1_st(TREG_SP, clob1);
+				frag.insn[n++] =
+					jit_x0_fnop() |
+					jit_x1_ldna(rd, ra);
+				frag.insn[n++] =
+					jit_x0_fnop() |
+					jit_x1_ldna(clob1, clob1);
+				/*
+				 * Note: we must make sure that rd must not
+				 * be sp. Recover clob1 from stack.
+				 */
+				frag.insn[n++] =
+					jit_x0_dblalign(rd, clob1, ra) |
+					jit_x1_ld_add(clob1, TREG_SP, 16);
+			}
+
+			if (bundle_2_enable)
+				frag.insn[n++] = bundle_2;
+			/*
+			 * For non 8-byte load, extract corresponding bytes and
+			 * signed extension.
+			 */
+			if (load_store_size == 4) {
+				if (load_store_signed)
+					frag.insn[n++] =
+						jit_x0_bfexts(
+							rd, rd,
+							UA_FIXUP_BFEXT_START(4),
+							UA_FIXUP_BFEXT_END(4)) |
+						jit_x1_fnop();
+				else
+					frag.insn[n++] =
+						jit_x0_bfextu(
+							rd, rd,
+							UA_FIXUP_BFEXT_START(4),
+							UA_FIXUP_BFEXT_END(4)) |
+						jit_x1_fnop();
+			} else if (load_store_size == 2) {
+				if (load_store_signed)
+					frag.insn[n++] =
+						jit_x0_bfexts(
+							rd, rd,
+							UA_FIXUP_BFEXT_START(2),
+							UA_FIXUP_BFEXT_END(2)) |
+						jit_x1_fnop();
+				else
+					frag.insn[n++] =
+						jit_x0_bfextu(
+							rd, rd,
+							UA_FIXUP_BFEXT_START(2),
+							UA_FIXUP_BFEXT_END(2)) |
+						jit_x1_fnop();
+			}
+
+			frag.insn[n++] =
+				jit_x0_fnop()  |
+				jit_x1_iret();
+		}
+	} else if (!load_n_store) {
+
+		/*
+		 * Generic memory store cases: use 3 clobber registers.
+		 *
+		 * Alloc space for saveing clob2,1,3 on user's stack.
+		 * register clob3 points to where clob2 saved, followed by
+		 * clob1 and 3 from high to low memory.
+		 */
+		frag.insn[n++] =
+			jit_x0_addi(TREG_SP, TREG_SP, -32)    |
+			jit_x1_fnop();
+		frag.insn[n++] =
+			jit_x0_addi(clob3, TREG_SP, 16)  |
+			jit_x1_st_add(TREG_SP, clob3, 8);
+#ifdef __LITTLE_ENDIAN
+		frag.insn[n++] =
+			jit_x0_addi(clob1, ra, 0)   |
+			jit_x1_st_add(TREG_SP, clob1, 8);
+#else
+		frag.insn[n++] =
+			jit_x0_addi(clob1, ra, load_store_size - 1)   |
+			jit_x1_st_add(TREG_SP, clob1, 8);
+#endif
+		if (load_store_size == 8) {
+			/*
+			 * We save one byte a time, not for fast, but compact
+			 * code. After each store, data source register shift
+			 * right one byte. unchanged after 8 stores.
+			 */
+			frag.insn[n++] =
+				jit_x0_addi(clob2, TREG_ZERO, 7)     |
+				jit_x1_st_add(TREG_SP, clob2, 16);
+			frag.insn[n++] =
+				jit_x0_rotli(rb, rb, 56)      |
+				jit_x1_st1_add(clob1, rb, UA_FIXUP_ADDR_DELTA);
+			frag.insn[n++] =
+				jit_x0_addi(clob2, clob2, -1) |
+				jit_x1_bnezt(clob2, -1);
+			frag.insn[n++] =
+				jit_x0_fnop()                 |
+				jit_x1_addi(clob2, y1_br_reg, 0);
+		} else if (load_store_size == 4) {
+			frag.insn[n++] =
+				jit_x0_addi(clob2, TREG_ZERO, 3)     |
+				jit_x1_st_add(TREG_SP, clob2, 16);
+			frag.insn[n++] =
+				jit_x0_rotli(rb, rb, 56)      |
+				jit_x1_st1_add(clob1, rb, UA_FIXUP_ADDR_DELTA);
+			frag.insn[n++] =
+				jit_x0_addi(clob2, clob2, -1) |
+				jit_x1_bnezt(clob2, -1);
+			/*
+			 * same as 8-byte case, but need shift another 4
+			 * byte to recover rb for 4-byte store.
+			 */
+			frag.insn[n++] = jit_x0_rotli(rb, rb, 32)      |
+				jit_x1_addi(clob2, y1_br_reg, 0);
+		} else { /* =2 */
+			frag.insn[n++] =
+				jit_x0_addi(clob2, rb, 0)     |
+				jit_x1_st_add(TREG_SP, clob2, 16);
+			for (k = 0; k < 2; k++) {
+				frag.insn[n++] =
+					jit_x0_shrui(rb, rb, 8)  |
+					jit_x1_st1_add(clob1, rb,
+						       UA_FIXUP_ADDR_DELTA);
+			}
+			frag.insn[n++] =
+				jit_x0_addi(rb, clob2, 0)       |
+				jit_x1_addi(clob2, y1_br_reg, 0);
+		}
+
+		if (bundle_2_enable)
+			frag.insn[n++] = bundle_2;
+
+		if (y1_lr) {
+			frag.insn[n++] =
+				jit_x0_fnop()                    |
+				jit_x1_mfspr(y1_lr_reg,
+					     SPR_EX_CONTEXT_0_0);
+		}
+		if (y1_br) {
+			frag.insn[n++] =
+				jit_x0_fnop()                    |
+				jit_x1_mtspr(SPR_EX_CONTEXT_0_0,
+					     clob2);
+		}
+		if (x1_add) {
+			frag.insn[n++] =
+				jit_x0_addi(ra, ra, x1_add_imm8) |
+				jit_x1_ld_add(clob2, clob3, -8);
+		} else {
+			frag.insn[n++] =
+				jit_x0_fnop()                    |
+				jit_x1_ld_add(clob2, clob3, -8);
+		}
+		frag.insn[n++] =
+			jit_x0_fnop()   |
+			jit_x1_ld_add(clob1, clob3, -8);
+		frag.insn[n++] = jit_x0_fnop()   | jit_x1_ld(clob3, clob3);
+		frag.insn[n++] = jit_x0_fnop()   | jit_x1_iret();
+
+	} else {
+		/*
+		 * Generic memory load cases.
+		 *
+		 * Alloc space for saveing clob1,2,3 on user's stack.
+		 * register clob3 points to where clob1 saved, followed
+		 * by clob2 and 3 from high to low memory.
+		 */
+
+		frag.insn[n++] =
+			jit_x0_addi(TREG_SP, TREG_SP, -32) |
+			jit_x1_fnop();
+		frag.insn[n++] =
+			jit_x0_addi(clob3, TREG_SP, 16) |
+			jit_x1_st_add(TREG_SP, clob3, 8);
+		frag.insn[n++] =
+			jit_x0_addi(clob2, ra, 0) |
+			jit_x1_st_add(TREG_SP, clob2, 8);
+
+		if (y1_br) {
+			frag.insn[n++] =
+				jit_x0_addi(clob1, y1_br_reg, 0) |
+				jit_x1_st_add(TREG_SP, clob1, 16);
+		} else {
+			frag.insn[n++] =
+				jit_x0_fnop() |
+				jit_x1_st_add(TREG_SP, clob1, 16);
+		}
+
+		if (bundle_2_enable)
+			frag.insn[n++] = bundle_2;
+
+		if (y1_lr) {
+			frag.insn[n++] =
+				jit_x0_fnop()  |
+				jit_x1_mfspr(y1_lr_reg,
+					     SPR_EX_CONTEXT_0_0);
+		}
+
+		if (y1_br) {
+			frag.insn[n++] =
+				jit_x0_fnop() |
+				jit_x1_mtspr(SPR_EX_CONTEXT_0_0,
+					     clob1);
+		}
+
+		frag.insn[n++] =
+			jit_x0_addi(clob1, clob2, 7)      |
+			jit_x1_ldna(rd, clob2);
+		frag.insn[n++] =
+			jit_x0_fnop()                     |
+			jit_x1_ldna(clob1, clob1);
+		frag.insn[n++] =
+			jit_x0_dblalign(rd, clob1, clob2) |
+			jit_x1_ld_add(clob1, clob3, -8);
+		if (x1_add) {
+			frag.insn[n++] =
+				jit_x0_addi(ra, ra, x1_add_imm8) |
+				jit_x1_ld_add(clob2, clob3, -8);
+		} else {
+			frag.insn[n++] =
+				jit_x0_fnop()  |
+				jit_x1_ld_add(clob2, clob3, -8);
+		}
+
+		frag.insn[n++] =
+			jit_x0_fnop() |
+			jit_x1_ld(clob3, clob3);
+
+		if (load_store_size == 4) {
+			if (load_store_signed)
+				frag.insn[n++] =
+					jit_x0_bfexts(
+						rd, rd,
+						UA_FIXUP_BFEXT_START(4),
+						UA_FIXUP_BFEXT_END(4)) |
+					jit_x1_fnop();
+			else
+				frag.insn[n++] =
+					jit_x0_bfextu(
+						rd, rd,
+						UA_FIXUP_BFEXT_START(4),
+						UA_FIXUP_BFEXT_END(4)) |
+					jit_x1_fnop();
+		} else if (load_store_size == 2) {
+			if (load_store_signed)
+				frag.insn[n++] =
+					jit_x0_bfexts(
+						rd, rd,
+						UA_FIXUP_BFEXT_START(2),
+						UA_FIXUP_BFEXT_END(2)) |
+					jit_x1_fnop();
+			else
+				frag.insn[n++] =
+					jit_x0_bfextu(
+						rd, rd,
+						UA_FIXUP_BFEXT_START(2),
+						UA_FIXUP_BFEXT_END(2)) |
+					jit_x1_fnop();
+		}
+
+		frag.insn[n++] = jit_x0_fnop() | jit_x1_iret();
+	}
+
+	/* Max JIT bundle count is 14. */
+	WARN_ON(n > 14);
+
+	if (!unexpected) {
+		int status = 0;
+		int idx = (regs->pc >> 3) &
+			((1ULL << (PAGE_SHIFT - UNALIGN_JIT_SHIFT)) - 1);
+
+		frag.pc = regs->pc;
+		frag.bundle = bundle;
+
+		if (unaligned_printk) {
+			pr_info("%s/%d, Unalign fixup: pc=%lx "
+				"bundle=%lx %d %d %d %d %d %d %d %d.",
+				current->comm, current->pid,
+				(unsigned long)frag.pc,
+				(unsigned long)frag.bundle,
+				(int)alias, (int)rd, (int)ra,
+				(int)rb, (int)bundle_2_enable,
+				(int)y1_lr, (int)y1_br, (int)x1_add);
+
+			for (k = 0; k < n; k += 2)
+				pr_info("[%d] %016llx %016llx", k,
+					(unsigned long long)frag.insn[k],
+					(unsigned long long)frag.insn[k+1]);
+		}
+
+		/* Swap bundle byte order for big endian sys. */
+#ifdef __BIG_ENDIAN
+		frag.bundle = GX_INSN_BSWAP(frag.bundle);
+		for (k = 0; k < n; k++)
+			frag.insn[k] = GX_INSN_BSWAP(frag.insn[k]);
+#endif /* __BIG_ENDIAN */
+
+		status = copy_to_user((void __user *)&jit_code_area[idx],
+				      &frag, sizeof(frag));
+		if (status) {
+			/* Fail to copy JIT into user land. send SIGSEGV. */
+			siginfo_t info = {
+				.si_signo = SIGSEGV,
+				.si_code = SEGV_MAPERR,
+				.si_addr = (void __user *)&jit_code_area[idx]
+			};
+
+			pr_warn("Unalign fixup: pid=%d %s jit_code_area=%llx",
+				current->pid, current->comm,
+				(unsigned long long)&jit_code_area[idx]);
+
+			trace_unhandled_signal("segfault in unalign fixup",
+					       regs,
+					       (unsigned long)info.si_addr,
+					       SIGSEGV);
+			force_sig_info(info.si_signo, &info, current);
+			return;
+		}
+
+
+		/* Do a cheaper increment, not accurate. */
+		unaligned_fixup_count++;
+		__flush_icache_range((unsigned long)&jit_code_area[idx],
+				     (unsigned long)&jit_code_area[idx] +
+				     sizeof(frag));
+
+		/* Setup SPR_EX_CONTEXT_0_0/1 for returning to user program.*/
+		__insn_mtspr(SPR_EX_CONTEXT_0_0, regs->pc + 8);
+		__insn_mtspr(SPR_EX_CONTEXT_0_1, PL_ICS_EX1(USER_PL, 0));
+
+		/* Modify pc at the start of new JIT. */
+		regs->pc = (unsigned long)&jit_code_area[idx].insn[0];
+		/* Set ICS in SPR_EX_CONTEXT_K_1. */
+		regs->ex1 = PL_ICS_EX1(USER_PL, 1);
+	}
+}
+
+
+/*
+ * C function to generate unalign data JIT. Called from unalign data
+ * interrupt handler.
+ *
+ * First check if unalign fix is disabled or exception did not not come from
+ * user space or sp register points to unalign address, if true, generate a
+ * SIGBUS. Then map a page into user space as JIT area if it is not mapped
+ * yet. Genenerate JIT code by calling jit_bundle_gen(). After that return
+ * back to exception handler.
+ *
+ * The exception handler will "iret" to new generated JIT code after
+ * restoring caller saved registers. In theory, the JIT code will perform
+ * another "iret" to resume user's program.
+ */
+
+void do_unaligned(struct pt_regs *regs, int vecnum)
+{
+	tilegx_bundle_bits __user  *pc;
+	tilegx_bundle_bits bundle;
+	struct thread_info *info = current_thread_info();
+	int align_ctl;
+
+	/* Checks the per-process unaligned JIT flags */
+	align_ctl = unaligned_fixup;
+	switch (task_thread_info(current)->align_ctl) {
+	case PR_UNALIGN_NOPRINT:
+		align_ctl = 1;
+		break;
+	case PR_UNALIGN_SIGBUS:
+		align_ctl = 0;
+		break;
+	}
+
+	/* Enable iterrupt in order to access user land. */
+	local_irq_enable();
+
+	/*
+	 * The fault came from kernel space. Two choices:
+	 * (a) unaligned_fixup < 1, we will first call get/put_user fixup
+	 *     to return -EFAULT. If no fixup, simply panic the kernel.
+	 * (b) unaligned_fixup >=1, we will try to fix the unaligned access
+	 *     if it was triggered by get_user/put_user() macros. Panic the
+	 *     kernel if it is not fixable.
+	 */
+
+	if (EX1_PL(regs->ex1) != USER_PL) {
+
+		if (align_ctl < 1) {
+			unaligned_fixup_count++;
+			/* If exception came from kernel, try fix it up. */
+			if (fixup_exception(regs)) {
+				if (unaligned_printk)
+					pr_info("Unalign fixup: %d %llx @%llx",
+						(int)unaligned_fixup,
+						(unsigned long long)regs->ex1,
+						(unsigned long long)regs->pc);
+				return;
+			}
+			/* Not fixable. Go panic. */
+			panic("Unalign exception in Kernel. pc=%lx",
+			      regs->pc);
+			return;
+		} else {
+			/*
+			 * Try to fix the exception. If we can't, panic the
+			 * kernel.
+			 */
+			bundle = GX_INSN_BSWAP(
+				*((tilegx_bundle_bits *)(regs->pc)));
+			jit_bundle_gen(regs, bundle, align_ctl);
+			return;
+		}
+	}
+
+	/*
+	 * Fault came from user with ICS or stack is not aligned.
+	 * If so, we will trigger SIGBUS.
+	 */
+	if ((regs->sp & 0x7) || (regs->ex1) || (align_ctl < 0)) {
+		siginfo_t info = {
+			.si_signo = SIGBUS,
+			.si_code = BUS_ADRALN,
+			.si_addr = (unsigned char __user *)0
+		};
+
+		if (unaligned_printk)
+			pr_info("Unalign fixup: %d %llx @%llx",
+				(int)unaligned_fixup,
+				(unsigned long long)regs->ex1,
+				(unsigned long long)regs->pc);
+
+		unaligned_fixup_count++;
+
+		trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS);
+		force_sig_info(info.si_signo, &info, current);
+		return;
+	}
+
+
+	/* Read the bundle casued the exception! */
+	pc = (tilegx_bundle_bits __user *)(regs->pc);
+	if (get_user(bundle, pc) != 0) {
+		/* Probably never be here since pc is valid user address.*/
+		siginfo_t info = {
+			.si_signo = SIGSEGV,
+			.si_code = SEGV_MAPERR,
+			.si_addr = (void __user *)pc
+		};
+		pr_err("Couldn't read instruction at %p trying to step\n", pc);
+		trace_unhandled_signal("segfault in unalign fixup", regs,
+				       (unsigned long)info.si_addr, SIGSEGV);
+		force_sig_info(info.si_signo, &info, current);
+		return;
+	}
+
+	if (!info->unalign_jit_base) {
+		void __user *user_page;
+
+		/*
+		 * Allocate a page in userland.
+		 * For 64-bit processes we try to place the mapping far
+		 * from anything else that might be going on (specifically
+		 * 64 GB below the top of the user address space).  If it
+		 * happens not to be possible to put it there, it's OK;
+		 * the kernel will choose another location and we'll
+		 * remember it for later.
+		 */
+		if (is_compat_task())
+			user_page = NULL;
+		else
+			user_page = (void __user *)(TASK_SIZE - (1UL << 36)) +
+				(current->pid << PAGE_SHIFT);
+
+		user_page = (void __user *) vm_mmap(NULL,
+						    (unsigned long)user_page,
+						    PAGE_SIZE,
+						    PROT_EXEC | PROT_READ |
+						    PROT_WRITE,
+#ifdef CONFIG_HOMECACHE
+						    MAP_CACHE_HOME_TASK |
+#endif
+						    MAP_PRIVATE |
+						    MAP_ANONYMOUS,
+						    0);
+
+		if (IS_ERR((void __force *)user_page)) {
+			pr_err("Out of kernel pages trying do_mmap.\n");
+			return;
+		}
+
+		/* Save the address in the thread_info struct */
+		info->unalign_jit_base = user_page;
+		if (unaligned_printk)
+			pr_info("Unalign bundle: %d:%d, allocate page @%llx",
+				raw_smp_processor_id(), current->pid,
+				(unsigned long long)user_page);
+	}
+
+	/* Generate unalign JIT */
+	jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl);
+}
+
+#endif /* __tilegx__ */
diff --git a/arch/tile/kernel/vdso.c b/arch/tile/kernel/vdso.c
new file mode 100644
index 0000000..1533af2
--- /dev/null
+++ b/arch/tile/kernel/vdso.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/binfmts.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/vdso.h>
+#include <asm/mman.h>
+#include <asm/sections.h>
+
+#include <arch/sim.h>
+
+/* The alignment of the vDSO. */
+#define VDSO_ALIGNMENT  PAGE_SIZE
+
+
+static unsigned int vdso_pages;
+static struct page **vdso_pagelist;
+
+#ifdef CONFIG_COMPAT
+static unsigned int vdso32_pages;
+static struct page **vdso32_pagelist;
+#endif
+static int vdso_ready;
+
+/*
+ * The vdso data page.
+ */
+static union {
+	struct vdso_data	data;
+	u8			page[PAGE_SIZE];
+} vdso_data_store __page_aligned_data;
+
+struct vdso_data *vdso_data = &vdso_data_store.data;
+
+static unsigned int __read_mostly vdso_enabled = 1;
+
+static struct page **vdso_setup(void *vdso_kbase, unsigned int pages)
+{
+	int i;
+	struct page **pagelist;
+
+	pagelist = kzalloc(sizeof(struct page *) * (pages + 1), GFP_KERNEL);
+	BUG_ON(pagelist == NULL);
+	for (i = 0; i < pages - 1; i++) {
+		struct page *pg = virt_to_page(vdso_kbase + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		pagelist[i] = pg;
+	}
+	pagelist[pages - 1] = virt_to_page(vdso_data);
+	pagelist[pages] = NULL;
+
+	return pagelist;
+}
+
+static int __init vdso_init(void)
+{
+	int data_pages = sizeof(vdso_data_store) >> PAGE_SHIFT;
+
+	/*
+	 * We can disable vDSO support generally, but we need to retain
+	 * one page to support the two-bundle (16-byte) rt_sigreturn path.
+	 */
+	if (!vdso_enabled) {
+		size_t offset = (unsigned long)&__vdso_rt_sigreturn;
+		static struct page *sigret_page;
+		sigret_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		BUG_ON(sigret_page == NULL);
+		vdso_pagelist = &sigret_page;
+		vdso_pages = 1;
+		BUG_ON(offset >= PAGE_SIZE);
+		memcpy(page_address(sigret_page) + offset,
+		       vdso_start + offset, 16);
+#ifdef CONFIG_COMPAT
+		vdso32_pages = vdso_pages;
+		vdso32_pagelist = vdso_pagelist;
+#endif
+		vdso_ready = 1;
+		return 0;
+	}
+
+	vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
+	vdso_pages += data_pages;
+	vdso_pagelist = vdso_setup(vdso_start, vdso_pages);
+
+#ifdef CONFIG_COMPAT
+	vdso32_pages = (vdso32_end - vdso32_start) >> PAGE_SHIFT;
+	vdso32_pages += data_pages;
+	vdso32_pagelist = vdso_setup(vdso32_start, vdso32_pages);
+#endif
+
+	smp_wmb();
+	vdso_ready = 1;
+
+	return 0;
+}
+arch_initcall(vdso_init);
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == VDSO_BASE)
+		return "[vdso]";
+#ifndef __tilegx__
+	if (vma->vm_start == MEM_USER_INTRPT)
+		return "[intrpt]";
+#endif
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long address)
+{
+	return 0;
+}
+
+int in_gate_area_no_mm(unsigned long address)
+{
+	return 0;
+}
+
+int setup_vdso_pages(void)
+{
+	struct page **pagelist;
+	unsigned long pages;
+	struct mm_struct *mm = current->mm;
+	unsigned long vdso_base = 0;
+	int retval = 0;
+
+	if (!vdso_ready)
+		return 0;
+
+	mm->context.vdso_base = 0;
+
+	pagelist = vdso_pagelist;
+	pages = vdso_pages;
+#ifdef CONFIG_COMPAT
+	if (is_compat_task()) {
+		pagelist = vdso32_pagelist;
+		pages = vdso32_pages;
+	}
+#endif
+
+	/*
+	 * vDSO has a problem and was disabled, just don't "enable" it for the
+	 * process.
+	 */
+	if (pages == 0)
+		return 0;
+
+	vdso_base = get_unmapped_area(NULL, vdso_base,
+				      (pages << PAGE_SHIFT) +
+				      ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
+				      0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		retval = vdso_base;
+		return retval;
+	}
+
+	/* Add required alignment. */
+	vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT);
+
+	/*
+	 * Put vDSO base into mm struct. We need to do this before calling
+	 * install_special_mapping or the perf counter mmap tracking code
+	 * will fail to recognise it as a vDSO (since arch_vma_name fails).
+	 */
+	mm->context.vdso_base = vdso_base;
+
+	/*
+	 * our vma flags don't have VM_WRITE so by default, the process isn't
+	 * allowed to write those pages.
+	 * gdb can break that with ptrace interface, and thus trigger COW on
+	 * those pages but it's then your responsibility to never do that on
+	 * the "data" page of the vDSO or you'll stop getting kernel updates
+	 * and your nice userland gettimeofday will be totally dead.
+	 * It's fine to use that for setting breakpoints in the vDSO code
+	 * pages though
+	 */
+	retval = install_special_mapping(mm, vdso_base,
+					 pages << PAGE_SHIFT,
+					 VM_READ|VM_EXEC |
+					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+					 pagelist);
+	if (retval)
+		mm->context.vdso_base = 0;
+
+	return retval;
+}
+
+static __init int vdso_func(char *s)
+{
+	return kstrtouint(s, 0, &vdso_enabled);
+}
+__setup("vdso=", vdso_func);
diff --git a/arch/tile/kernel/vdso/Makefile b/arch/tile/kernel/vdso/Makefile
new file mode 100644
index 0000000..e2b7a2f
--- /dev/null
+++ b/arch/tile/kernel/vdso/Makefile
@@ -0,0 +1,118 @@
+# Symbols present in the vdso
+vdso-syms = rt_sigreturn gettimeofday
+
+# Files to link into the vdso
+obj-vdso = $(patsubst %, v%.o, $(vdso-syms))
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+# vdso32 is only for tilegx -m32 compat task.
+VDSO32-$(CONFIG_COMPAT) := y
+
+obj-y += vdso.o
+obj-$(VDSO32-y) += vdso32.o
+extra-y += vdso.lds
+CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
+CFLAGS_REMOVE_vdso.o = -pg
+CFLAGS_REMOVE_vdso32.o = -pg
+CFLAGS_REMOVE_vrt_sigreturn.o = -pg
+CFLAGS_REMOVE_vrt_sigreturn32.o = -pg
+CFLAGS_REMOVE_vgettimeofday.o = -pg
+CFLAGS_REMOVE_vgettimeofday32.o = -pg
+
+ifdef CONFIG_FEEDBACK_COLLECT
+# vDSO code runs in userspace, not collecting feedback data.
+CFLAGS_REMOVE_vdso.o = -ffeedback-generate
+CFLAGS_REMOVE_vdso32.o = -ffeedback-generate
+CFLAGS_REMOVE_vrt_sigreturn.o = -ffeedback-generate
+CFLAGS_REMOVE_vrt_sigreturn32.o = -ffeedback-generate
+CFLAGS_REMOVE_vgettimeofday.o = -ffeedback-generate
+CFLAGS_REMOVE_vgettimeofday32.o = -ffeedback-generate
+endif
+
+# Disable gcov profiling for VDSO code
+GCOV_PROFILE := n
+
+# Force dependency
+$(obj)/vdso.o: $(obj)/vdso.so
+
+# link rule for the .so file, .lds has to be first
+SYSCFLAGS_vdso.so.dbg = $(c_flags)
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso)
+	$(call if_changed,vdsold)
+
+
+# We also create a special relocatable object that should mirror the symbol
+# table and layout of the linked DSO.  With ld -R we can then refer to
+# these symbols in the kernel code rather than hand-coded addresses.
+extra-y += vdso-syms.o
+$(obj)/built-in.o: $(obj)/vdso-syms.o
+$(obj)/built-in.o: ld_flags += -R $(obj)/vdso-syms.o
+
+SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
+                            $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+SYSCFLAGS_vdso_syms.o = -r
+$(obj)/vdso-syms.o: $(src)/vdso.lds $(obj)/vrt_sigreturn.o FORCE
+	$(call if_changed,vdsold)
+
+
+# strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+# actual build commands
+# The DSO images are built using a special linker script
+# Add -lgcc so tilepro gets static muldi3 and lshrdi3 definitions.
+# Make sure only to export the intended __vdso_xxx symbol offsets.
+quiet_cmd_vdsold = VDSOLD  $@
+      cmd_vdsold = $(CC) $(KCFLAGS) -nostdlib $(SYSCFLAGS_$(@F)) \
+                           -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp -lgcc && \
+                   $(CROSS_COMPILE)objcopy \
+                           $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@
+
+# install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso.so: $(obj)/vdso.so.dbg
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+vdso32.so: $(obj)/vdso32.so.dbg
+	$(call cmd,vdso_install)
+
+vdso_install: vdso.so
+vdso32_install: vdso32.so
+
+
+KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS))
+KBUILD_AFLAGS_32 += -m32 -s
+KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
+KBUILD_CFLAGS_32 += -m32 -fPIC -shared
+
+obj-vdso32 = $(patsubst %, v%32.o, $(vdso-syms))
+obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
+
+targets += $(obj-vdso32) vdso32.so vdso32.so.dbg
+
+$(obj-vdso32:%=%): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
+$(obj-vdso32:%=%): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
+
+$(obj)/vgettimeofday32.o: $(obj)/vgettimeofday.c
+	$(call if_changed,cc_o_c)
+
+$(obj)/vrt_sigreturn32.o: $(obj)/vrt_sigreturn.S
+	$(call if_changed,as_o_S)
+
+# Force dependency
+$(obj)/vdso32.o: $(obj)/vdso32.so
+
+SYSCFLAGS_vdso32.so.dbg = -m32 -shared -s -Wl,-soname=linux-vdso32.so.1 \
+			    $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+$(obj)/vdso32.so.dbg: $(src)/vdso.lds $(obj-vdso32)
+	$(call if_changed,vdsold)
diff --git a/arch/tile/kernel/vdso/vdso.S b/arch/tile/kernel/vdso/vdso.S
new file mode 100644
index 0000000..3467adb
--- /dev/null
+++ b/arch/tile/kernel/vdso/vdso.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.global vdso_start, vdso_end
+	.align PAGE_SIZE
+vdso_start:
+	.incbin "arch/tile/kernel/vdso/vdso.so"
+	.align PAGE_SIZE
+vdso_end:
+
+	.previous
diff --git a/arch/tile/kernel/vdso/vdso.lds.S b/arch/tile/kernel/vdso/vdso.lds.S
new file mode 100644
index 0000000..041cd6c
--- /dev/null
+++ b/arch/tile/kernel/vdso/vdso.lds.S
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#define VDSO_VERSION_STRING	LINUX_2.6
+
+
+OUTPUT_ARCH(tile)
+
+/* The ELF entry point can be used to set the AT_SYSINFO value. */
+ENTRY(__vdso_rt_sigreturn);
+
+
+SECTIONS
+{
+	. = SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.rodata	 : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+
+	/*
+	 * This linker script is used both with -r and with -shared.
+	 * For the layouts to match, we need to skip more than enough
+	 * space for the dynamic symbol table et al. If this amount
+	 * is insufficient, ld -shared will barf. Just increase it here.
+	 */
+	. = 0x1000;
+	.text		: { *(.text .text.*) }		:text
+
+	.data		: {
+		*(.got.plt) *(.got)
+		*(.data .data.* .gnu.linkonce.d.*)
+		*(.dynbss)
+		*(.bss .bss.* .gnu.linkonce.b.*)
+	}
+}
+
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS;	/* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
+
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION
+{
+	VDSO_VERSION_STRING {
+	global:
+		__vdso_rt_sigreturn;
+		__vdso_gettimeofday;
+		gettimeofday;
+	local:*;
+	};
+}
diff --git a/arch/tile/kernel/vdso/vdso32.S b/arch/tile/kernel/vdso/vdso32.S
new file mode 100644
index 0000000..1d1ac32
--- /dev/null
+++ b/arch/tile/kernel/vdso/vdso32.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.global vdso32_start, vdso32_end
+	.align PAGE_SIZE
+vdso32_start:
+	.incbin "arch/tile/kernel/vdso/vdso32.so"
+	.align PAGE_SIZE
+vdso32_end:
+
+	.previous
diff --git a/arch/tile/kernel/vdso/vgettimeofday.c b/arch/tile/kernel/vdso/vgettimeofday.c
new file mode 100644
index 0000000..51ec8e4
--- /dev/null
+++ b/arch/tile/kernel/vdso/vgettimeofday.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#define VDSO_BUILD  /* avoid some shift warnings for -m32 in <asm/page.h> */
+#include <linux/time.h>
+#include <asm/timex.h>
+#include <asm/vdso.h>
+
+#if CHIP_HAS_SPLIT_CYCLE()
+static inline cycles_t get_cycles_inline(void)
+{
+	unsigned int high = __insn_mfspr(SPR_CYCLE_HIGH);
+	unsigned int low = __insn_mfspr(SPR_CYCLE_LOW);
+	unsigned int high2 = __insn_mfspr(SPR_CYCLE_HIGH);
+
+	while (unlikely(high != high2)) {
+		low = __insn_mfspr(SPR_CYCLE_LOW);
+		high = high2;
+		high2 = __insn_mfspr(SPR_CYCLE_HIGH);
+	}
+
+	return (((cycles_t)high) << 32) | low;
+}
+#define get_cycles get_cycles_inline
+#endif
+
+/*
+ * Find out the vDSO data page address in the process address space.
+ */
+inline unsigned long get_datapage(void)
+{
+	unsigned long ret;
+
+	/* vdso data page located in the 2nd vDSO page. */
+	asm volatile ("lnk %0" : "=r"(ret));
+	ret &= ~(PAGE_SIZE - 1);
+	ret += PAGE_SIZE;
+
+	return ret;
+}
+
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	cycles_t cycles;
+	unsigned long count, sec, ns;
+	volatile struct vdso_data *vdso_data;
+
+	vdso_data = (struct vdso_data *)get_datapage();
+	/* The use of the timezone is obsolete, normally tz is NULL. */
+	if (unlikely(tz != NULL)) {
+		while (1) {
+			/* Spin until the update finish. */
+			count = vdso_data->tz_update_count;
+			if (count & 1)
+				continue;
+
+			tz->tz_minuteswest = vdso_data->tz_minuteswest;
+			tz->tz_dsttime = vdso_data->tz_dsttime;
+
+			/* Check whether updated, read again if so. */
+			if (count == vdso_data->tz_update_count)
+				break;
+		}
+	}
+
+	if (unlikely(tv == NULL))
+		return 0;
+
+	while (1) {
+		/* Spin until the update finish. */
+		count = vdso_data->tb_update_count;
+		if (count & 1)
+			continue;
+
+		cycles = (get_cycles() - vdso_data->xtime_tod_stamp);
+		ns = (cycles * vdso_data->mult) >> vdso_data->shift;
+		sec = vdso_data->xtime_clock_sec;
+		ns += vdso_data->xtime_clock_nsec;
+		if (ns >= NSEC_PER_SEC) {
+			ns -= NSEC_PER_SEC;
+			sec += 1;
+		}
+
+		/* Check whether updated, read again if so. */
+		if (count == vdso_data->tb_update_count)
+			break;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = ns / 1000;
+
+	return 0;
+}
+
+int gettimeofday(struct timeval *tv, struct timezone *tz)
+	__attribute__((weak, alias("__vdso_gettimeofday")));
diff --git a/arch/tile/kernel/vdso/vrt_sigreturn.S b/arch/tile/kernel/vdso/vrt_sigreturn.S
new file mode 100644
index 0000000..6326caf
--- /dev/null
+++ b/arch/tile/kernel/vdso/vrt_sigreturn.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/linkage.h>
+#include <arch/abi.h>
+#include <asm/unistd.h>
+
+/*
+ * Note that libc has a copy of this function that it uses to compare
+ * against the PC when a stack backtrace ends, so if this code is
+ * changed, the libc implementation(s) should also be updated.
+ */
+ENTRY(__vdso_rt_sigreturn)
+	moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn
+	swint1
+	/* We don't use ENDPROC to avoid tagging this symbol as FUNC,
+	 * which confuses the perf tool.
+	 */
+	END(__vdso_rt_sigreturn)
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index a13ed90..0f0edaf 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -31,7 +31,10 @@ SECTIONS
   } :intrpt1 =0
 
   /* Hypervisor call vectors */
-  #include "hvglue.lds"
+  . = ALIGN(0x10000);
+  .hvglue : AT (ADDR(.hvglue) - LOAD_OFFSET) {
+    *(.hvglue)
+  } :NONE
 
   /* Now the real code */
   . = ALIGN(0x20000);
diff --git a/arch/tile/lib/Makefile b/arch/tile/lib/Makefile
index 985f598..5d84437 100644
--- a/arch/tile/lib/Makefile
+++ b/arch/tile/lib/Makefile
@@ -4,7 +4,7 @@
 
 lib-y = cacheflush.o checksum.o cpumask.o delay.o uaccess.o \
 	memmove.o memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
-	strchr_$(BITS).o strlen_$(BITS).o
+	strchr_$(BITS).o strlen_$(BITS).o strnlen_$(BITS).o
 
 ifeq ($(CONFIG_TILEGX),y)
 CFLAGS_REMOVE_memcpy_user_64.o = -fno-omit-frame-pointer
diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c
index 8f8ad81..2238b40 100644
--- a/arch/tile/lib/cacheflush.c
+++ b/arch/tile/lib/cacheflush.c
@@ -147,18 +147,21 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
 		force_load(p);
 
 	/*
-	 * Repeat, but with inv's instead of loads, to get rid of the
+	 * Repeat, but with finv's instead of loads, to get rid of the
 	 * data we just loaded into our own cache and the old home L3.
-	 * No need to unroll since inv's don't target a register.
+	 * No need to unroll since finv's don't target a register.
+	 * The finv's are guaranteed not to actually flush the data in
+	 * the buffer back to their home, since we just read it, so the
+	 * lines are clean in cache; we will only invalidate those lines.
 	 */
 	p = (char *)buffer + size - 1;
-	__insn_inv(p);
+	__insn_finv(p);
 	p -= step_size;
 	p = (char *)((unsigned long)p | (step_size - 1));
 	for (; p >= base; p -= step_size)
-		__insn_inv(p);
+		__insn_finv(p);
 
-	/* Wait for the load+inv's (and thus finvs) to have completed. */
+	/* Wait for these finv's (and thus the first finvs) to be done. */
 	__insn_mf();
 
 #ifdef __tilegx__
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c
index a93b02a..359b1bc 100644
--- a/arch/tile/lib/exports.c
+++ b/arch/tile/lib/exports.c
@@ -22,7 +22,6 @@ EXPORT_SYMBOL(strnlen_user_asm);
 EXPORT_SYMBOL(strncpy_from_user_asm);
 EXPORT_SYMBOL(clear_user_asm);
 EXPORT_SYMBOL(flush_user_asm);
-EXPORT_SYMBOL(inv_user_asm);
 EXPORT_SYMBOL(finv_user_asm);
 
 /* arch/tile/kernel/entry.S */
diff --git a/arch/tile/lib/memchr_64.c b/arch/tile/lib/memchr_64.c
index 6f867db..f8196b3 100644
--- a/arch/tile/lib/memchr_64.c
+++ b/arch/tile/lib/memchr_64.c
@@ -36,7 +36,7 @@ void *memchr(const void *s, int c, size_t n)
 	p = (const uint64_t *)(s_int & -8);
 
 	/* Create eight copies of the byte for which we are looking. */
-	goal = 0x0101010101010101ULL * (uint8_t) c;
+	goal = copy_byte(c);
 
 	/* Read the first word, but munge it so that bytes before the array
 	 * will not match goal.
diff --git a/arch/tile/lib/memcpy_64.c b/arch/tile/lib/memcpy_64.c
index c79b8e7..46fc160 100644
--- a/arch/tile/lib/memcpy_64.c
+++ b/arch/tile/lib/memcpy_64.c
@@ -18,14 +18,17 @@
 /* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */
 
 /* Must be 8 bytes in size. */
-#define word_t uint64_t
+#define op_t uint64_t
 
-#if CHIP_L2_LINE_SIZE() != 64 && CHIP_L2_LINE_SIZE() != 128
-#error "Assumes 64 or 128 byte line size"
+/* Threshold value for when to enter the unrolled loops. */
+#define	OP_T_THRES	16
+
+#if CHIP_L2_LINE_SIZE() != 64
+#error "Assumes 64 byte line size"
 #endif
 
 /* How many cache lines ahead should we prefetch? */
-#define PREFETCH_LINES_AHEAD 3
+#define PREFETCH_LINES_AHEAD 4
 
 /*
  * Provide "base versions" of load and store for the normal code path.
@@ -58,8 +61,8 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n)
 	const char *__restrict src1 = (const char *)srcv;
 	const char *__restrict src1_end;
 	const char *__restrict prefetch;
-	word_t *__restrict dst8;    /* 8-byte pointer to destination memory. */
-	word_t final; /* Final bytes to write to trailing word, if any */
+	op_t *__restrict dst8;    /* 8-byte pointer to destination memory. */
+	op_t final; /* Final bytes to write to trailing word, if any */
 	long i;
 
 	if (n < 16) {
@@ -79,104 +82,228 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n)
 	for (i = 0; i < PREFETCH_LINES_AHEAD; i++) {
 		__insn_prefetch(prefetch);
 		prefetch += CHIP_L2_LINE_SIZE();
-		prefetch = (prefetch > src1_end) ? prefetch : src1;
+		prefetch = (prefetch < src1_end) ? prefetch : src1;
 	}
 
 	/* Copy bytes until dst is word-aligned. */
-	for (; (uintptr_t)dst1 & (sizeof(word_t) - 1); n--)
+	for (; (uintptr_t)dst1 & (sizeof(op_t) - 1); n--)
 		ST1(dst1++, LD1(src1++));
 
 	/* 8-byte pointer to destination memory. */
-	dst8 = (word_t *)dst1;
-
-	if (__builtin_expect((uintptr_t)src1 & (sizeof(word_t) - 1), 0)) {
-		/*
-		 * Misaligned copy.  Copy 8 bytes at a time, but don't
-		 * bother with other fanciness.
-		 *
-		 * TODO: Consider prefetching and using wh64 as well.
-		 */
-
-		/* Create an aligned src8. */
-		const word_t *__restrict src8 =
-			(const word_t *)((uintptr_t)src1 & -sizeof(word_t));
-		word_t b;
-
-		word_t a = LD8(src8++);
-		for (; n >= sizeof(word_t); n -= sizeof(word_t)) {
-			b = LD8(src8++);
-			a = __insn_dblalign(a, b, src1);
-			ST8(dst8++, a);
-			a = b;
+	dst8 = (op_t *)dst1;
+
+	if (__builtin_expect((uintptr_t)src1 & (sizeof(op_t) - 1), 0)) {
+		/* Unaligned copy. */
+
+		op_t  tmp0 = 0, tmp1 = 0, tmp2, tmp3;
+		const op_t *src8 = (const op_t *) ((uintptr_t)src1 &
+						   -sizeof(op_t));
+		const void *srci = (void *)src1;
+		int m;
+
+		m = (CHIP_L2_LINE_SIZE() << 2) -
+			(((uintptr_t)dst8) & ((CHIP_L2_LINE_SIZE() << 2) - 1));
+		m = (n < m) ? n : m;
+		m /= sizeof(op_t);
+
+		/* Copy until 'dst' is cache-line-aligned. */
+		n -= (sizeof(op_t) * m);
+
+		switch (m % 4) {
+		case 0:
+			if (__builtin_expect(!m, 0))
+				goto _M0;
+			tmp1 = LD8(src8++);
+			tmp2 = LD8(src8++);
+			goto _8B3;
+		case 2:
+			m += 2;
+			tmp3 = LD8(src8++);
+			tmp0 = LD8(src8++);
+			goto _8B1;
+		case 3:
+			m += 1;
+			tmp2 = LD8(src8++);
+			tmp3 = LD8(src8++);
+			goto _8B2;
+		case 1:
+			m--;
+			tmp0 = LD8(src8++);
+			tmp1 = LD8(src8++);
+			if (__builtin_expect(!m, 0))
+				goto _8B0;
+		}
+
+		do {
+			tmp2 = LD8(src8++);
+			tmp0 =  __insn_dblalign(tmp0, tmp1, srci);
+			ST8(dst8++, tmp0);
+_8B3:
+			tmp3 = LD8(src8++);
+			tmp1 = __insn_dblalign(tmp1, tmp2, srci);
+			ST8(dst8++, tmp1);
+_8B2:
+			tmp0 = LD8(src8++);
+			tmp2 = __insn_dblalign(tmp2, tmp3, srci);
+			ST8(dst8++, tmp2);
+_8B1:
+			tmp1 = LD8(src8++);
+			tmp3 = __insn_dblalign(tmp3, tmp0, srci);
+			ST8(dst8++, tmp3);
+			m -= 4;
+		} while (m);
+
+_8B0:
+		tmp0 = __insn_dblalign(tmp0, tmp1, srci);
+		ST8(dst8++, tmp0);
+		src8--;
+
+_M0:
+		if (__builtin_expect(n >= CHIP_L2_LINE_SIZE(), 0)) {
+			op_t tmp4, tmp5, tmp6, tmp7, tmp8;
+
+			prefetch = ((const char *)src8) +
+				CHIP_L2_LINE_SIZE() * PREFETCH_LINES_AHEAD;
+
+			for (tmp0 = LD8(src8++); n >= CHIP_L2_LINE_SIZE();
+			     n -= CHIP_L2_LINE_SIZE()) {
+				/* Prefetch and advance to next line to
+				   prefetch, but don't go past the end.  */
+				__insn_prefetch(prefetch);
+
+				/* Make sure prefetch got scheduled
+				   earlier.  */
+				__asm__ ("" : : : "memory");
+
+				prefetch += CHIP_L2_LINE_SIZE();
+				prefetch = (prefetch < src1_end) ? prefetch :
+					(const char *) src8;
+
+				tmp1 = LD8(src8++);
+				tmp2 = LD8(src8++);
+				tmp3 = LD8(src8++);
+				tmp4 = LD8(src8++);
+				tmp5 = LD8(src8++);
+				tmp6 = LD8(src8++);
+				tmp7 = LD8(src8++);
+				tmp8 = LD8(src8++);
+
+				tmp0 = __insn_dblalign(tmp0, tmp1, srci);
+				tmp1 = __insn_dblalign(tmp1, tmp2, srci);
+				tmp2 = __insn_dblalign(tmp2, tmp3, srci);
+				tmp3 = __insn_dblalign(tmp3, tmp4, srci);
+				tmp4 = __insn_dblalign(tmp4, tmp5, srci);
+				tmp5 = __insn_dblalign(tmp5, tmp6, srci);
+				tmp6 = __insn_dblalign(tmp6, tmp7, srci);
+				tmp7 = __insn_dblalign(tmp7, tmp8, srci);
+
+				__insn_wh64(dst8);
+
+				ST8(dst8++, tmp0);
+				ST8(dst8++, tmp1);
+				ST8(dst8++, tmp2);
+				ST8(dst8++, tmp3);
+				ST8(dst8++, tmp4);
+				ST8(dst8++, tmp5);
+				ST8(dst8++, tmp6);
+				ST8(dst8++, tmp7);
+
+				tmp0 = tmp8;
+			}
+			src8--;
+		}
+
+		/* Copy the rest 8-byte chunks. */
+		if (n >= sizeof(op_t)) {
+			tmp0 = LD8(src8++);
+			for (; n >= sizeof(op_t); n -= sizeof(op_t)) {
+				tmp1 = LD8(src8++);
+				tmp0 = __insn_dblalign(tmp0, tmp1, srci);
+				ST8(dst8++, tmp0);
+				tmp0 = tmp1;
+			}
+			src8--;
 		}
 
 		if (n == 0)
 			return RETVAL;
 
-		b = ((const char *)src8 <= src1_end) ? *src8 : 0;
+		tmp0 = LD8(src8++);
+		tmp1 = ((const char *)src8 <= src1_end)
+			? LD8((op_t *)src8) : 0;
+		final = __insn_dblalign(tmp0, tmp1, srci);
 
-		/*
-		 * Final source bytes to write to trailing partial
-		 * word, if any.
-		 */
-		final = __insn_dblalign(a, b, src1);
 	} else {
 		/* Aligned copy. */
 
-		const word_t* __restrict src8 = (const word_t *)src1;
+		const op_t *__restrict src8 = (const op_t *)src1;
 
 		/* src8 and dst8 are both word-aligned. */
 		if (n >= CHIP_L2_LINE_SIZE()) {
 			/* Copy until 'dst' is cache-line-aligned. */
 			for (; (uintptr_t)dst8 & (CHIP_L2_LINE_SIZE() - 1);
-			     n -= sizeof(word_t))
+			     n -= sizeof(op_t))
 				ST8(dst8++, LD8(src8++));
 
 			for (; n >= CHIP_L2_LINE_SIZE(); ) {
-				__insn_wh64(dst8);
+				op_t tmp0, tmp1, tmp2, tmp3;
+				op_t tmp4, tmp5, tmp6, tmp7;
 
 				/*
 				 * Prefetch and advance to next line
-				 * to prefetch, but don't go past the end
+				 * to prefetch, but don't go past the
+				 * end.
 				 */
 				__insn_prefetch(prefetch);
+
+				/* Make sure prefetch got scheduled
+				   earlier.  */
+				__asm__ ("" : : : "memory");
+
 				prefetch += CHIP_L2_LINE_SIZE();
-				prefetch = (prefetch > src1_end) ? prefetch :
+				prefetch = (prefetch < src1_end) ? prefetch :
 					(const char *)src8;
 
 				/*
-				 * Copy an entire cache line.  Manually
-				 * unrolled to avoid idiosyncracies of
-				 * compiler unrolling.
+				 * Do all the loads before wh64.  This
+				 * is necessary if [src8, src8+7] and
+				 * [dst8, dst8+7] share the same cache
+				 * line and dst8 <= src8, as can be
+				 * the case when called from memmove,
+				 * or with code tested on x86 whose
+				 * memcpy always works with forward
+				 * copies.
 				 */
-#define COPY_WORD(offset) ({ ST8(dst8+offset, LD8(src8+offset)); n -= 8; })
-				COPY_WORD(0);
-				COPY_WORD(1);
-				COPY_WORD(2);
-				COPY_WORD(3);
-				COPY_WORD(4);
-				COPY_WORD(5);
-				COPY_WORD(6);
-				COPY_WORD(7);
-#if CHIP_L2_LINE_SIZE() == 128
-				COPY_WORD(8);
-				COPY_WORD(9);
-				COPY_WORD(10);
-				COPY_WORD(11);
-				COPY_WORD(12);
-				COPY_WORD(13);
-				COPY_WORD(14);
-				COPY_WORD(15);
-#elif CHIP_L2_LINE_SIZE() != 64
-# error Fix code that assumes particular L2 cache line sizes
-#endif
+				tmp0 = LD8(src8++);
+				tmp1 = LD8(src8++);
+				tmp2 = LD8(src8++);
+				tmp3 = LD8(src8++);
+				tmp4 = LD8(src8++);
+				tmp5 = LD8(src8++);
+				tmp6 = LD8(src8++);
+				tmp7 = LD8(src8++);
+
+				/* wh64 and wait for tmp7 load completion. */
+				__asm__ ("move %0, %0; wh64 %1\n"
+					 : : "r"(tmp7), "r"(dst8));
 
-				dst8 += CHIP_L2_LINE_SIZE() / sizeof(word_t);
-				src8 += CHIP_L2_LINE_SIZE() / sizeof(word_t);
+				ST8(dst8++, tmp0);
+				ST8(dst8++, tmp1);
+				ST8(dst8++, tmp2);
+				ST8(dst8++, tmp3);
+				ST8(dst8++, tmp4);
+				ST8(dst8++, tmp5);
+				ST8(dst8++, tmp6);
+				ST8(dst8++, tmp7);
+
+				n -= CHIP_L2_LINE_SIZE();
 			}
+#if CHIP_L2_LINE_SIZE() != 64
+# error "Fix code that assumes particular L2 cache line size."
+#endif
 		}
 
-		for (; n >= sizeof(word_t); n -= sizeof(word_t))
+		for (; n >= sizeof(op_t); n -= sizeof(op_t))
 			ST8(dst8++, LD8(src8++));
 
 		if (__builtin_expect(n == 0, 1))
diff --git a/arch/tile/lib/memcpy_tile64.c b/arch/tile/lib/memcpy_tile64.c
index 3bc4b4e..0290c22 100644
--- a/arch/tile/lib/memcpy_tile64.c
+++ b/arch/tile/lib/memcpy_tile64.c
@@ -65,7 +65,7 @@ static void memcpy_multicache(void *dest, const void *source,
 	pmd_t *pmdp;
 	pte_t *ptep;
 	int type0, type1;
-	int cpu = get_cpu();
+	int cpu = smp_processor_id();
 
 	/*
 	 * Disable interrupts so that we don't recurse into memcpy()
@@ -126,7 +126,6 @@ static void memcpy_multicache(void *dest, const void *source,
 	kmap_atomic_idx_pop();
 	sim_allow_multiple_caching(0);
 	local_irq_restore(flags);
-	put_cpu();
 }
 
 /*
@@ -137,6 +136,9 @@ static void memcpy_multicache(void *dest, const void *source,
 static unsigned long fast_copy(void *dest, const void *source, int len,
 			       memcpy_t func)
 {
+	int cpu = get_cpu();
+	unsigned long retval;
+
 	/*
 	 * Check if it's big enough to bother with.  We may end up doing a
 	 * small copy via TLB manipulation if we're near a page boundary,
@@ -158,7 +160,7 @@ retry_source:
 		    !hv_pte_get_readable(src_pte) ||
 		    hv_pte_get_mode(src_pte) != HV_PTE_MODE_CACHE_TILE_L3)
 			break;
-		if (get_remote_cache_cpu(src_pte) == smp_processor_id())
+		if (get_remote_cache_cpu(src_pte) == cpu)
 			break;
 		src_page = pfn_to_page(pte_pfn(src_pte));
 		get_page(src_page);
@@ -235,7 +237,9 @@ retry_dest:
 		len -= copy_size;
 	}
 
-	return func(dest, source, len);
+	retval = func(dest, source, len);
+	put_cpu();
+	return retval;
 }
 
 void *memcpy(void *to, const void *from, __kernel_size_t n)
diff --git a/arch/tile/lib/memset_32.c b/arch/tile/lib/memset_32.c
index 57dbb3a..9a7837d 100644
--- a/arch/tile/lib/memset_32.c
+++ b/arch/tile/lib/memset_32.c
@@ -12,13 +12,10 @@
  *   more details.
  */
 
-#include <arch/chip.h>
-
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/module.h>
-
-#undef memset
+#include <arch/chip.h>
 
 void *memset(void *s, int c, size_t n)
 {
diff --git a/arch/tile/lib/memset_64.c b/arch/tile/lib/memset_64.c
index 3873085..03ef69c 100644
--- a/arch/tile/lib/memset_64.c
+++ b/arch/tile/lib/memset_64.c
@@ -12,13 +12,11 @@
  *   more details.
  */
 
-#include <arch/chip.h>
-
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/module.h>
-
-#undef memset
+#include <arch/chip.h>
+#include "string-endian.h"
 
 void *memset(void *s, int c, size_t n)
 {
@@ -70,8 +68,7 @@ void *memset(void *s, int c, size_t n)
 	n64 = n >> 3;
 
 	/* Tile input byte out to 64 bits. */
-	/* KLUDGE */
-	v64 = 0x0101010101010101ULL * (uint8_t)c;
+	v64 = copy_byte(c);
 
 	/* This must be at least 8 or the following loop doesn't work. */
 #define CACHE_LINE_SIZE_IN_DOUBLEWORDS (CHIP_L2_LINE_SIZE() / 8)
diff --git a/arch/tile/lib/strchr_32.c b/arch/tile/lib/strchr_32.c
index c94e6f7..841fe69 100644
--- a/arch/tile/lib/strchr_32.c
+++ b/arch/tile/lib/strchr_32.c
@@ -16,8 +16,6 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
-#undef strchr
-
 char *strchr(const char *s, int c)
 {
 	int z, g;
diff --git a/arch/tile/lib/strchr_64.c b/arch/tile/lib/strchr_64.c
index f39f9dc..fe6e31c 100644
--- a/arch/tile/lib/strchr_64.c
+++ b/arch/tile/lib/strchr_64.c
@@ -26,7 +26,7 @@ char *strchr(const char *s, int c)
 	const uint64_t *p = (const uint64_t *)(s_int & -8);
 
 	/* Create eight copies of the byte for which we are looking. */
-	const uint64_t goal = 0x0101010101010101ULL * (uint8_t) c;
+	const uint64_t goal = copy_byte(c);
 
 	/* Read the first aligned word, but force bytes before the string to
 	 * match neither zero nor goal (we make sure the high bit of each
diff --git a/arch/tile/lib/string-endian.h b/arch/tile/lib/string-endian.h
index c0eed7c..2e49cbf 100644
--- a/arch/tile/lib/string-endian.h
+++ b/arch/tile/lib/string-endian.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ * Copyright 2013 Tilera Corporation. All Rights Reserved.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
@@ -31,3 +31,14 @@
 #define CFZ(x) __insn_clz(x)
 #define REVCZ(x) __insn_ctz(x)
 #endif
+
+/*
+ * Create eight copies of the byte in a uint64_t.  Byte Shuffle uses
+ * the bytes of srcB as the index into the dest vector to select a
+ * byte.  With all indices of zero, the first byte is copied into all
+ * the other bytes.
+ */
+static inline uint64_t copy_byte(uint8_t byte)
+{
+	return __insn_shufflebytes(byte, 0, 0);
+}
diff --git a/arch/tile/lib/strlen_32.c b/arch/tile/lib/strlen_32.c
index 4974292..f26f88e 100644
--- a/arch/tile/lib/strlen_32.c
+++ b/arch/tile/lib/strlen_32.c
@@ -16,8 +16,6 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
-#undef strlen
-
 size_t strlen(const char *s)
 {
 	/* Get an aligned pointer. */
diff --git a/arch/tile/lib/strnlen_32.c b/arch/tile/lib/strnlen_32.c
new file mode 100644
index 0000000..1434141
--- /dev/null
+++ b/arch/tile/lib/strnlen_32.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+size_t strnlen(const char *s, size_t count)
+{
+	/* Get an aligned pointer. */
+	const uintptr_t s_int = (uintptr_t) s;
+	const uint32_t *p = (const uint32_t *)(s_int & -4);
+	size_t bytes_read = sizeof(*p) - (s_int & (sizeof(*p) - 1));
+	size_t len;
+	uint32_t v, bits;
+
+	/* Avoid page fault risk by not reading any bytes when count is 0. */
+	if (count == 0)
+		return 0;
+
+	/* Read first word, but force bytes before the string to be nonzero. */
+	v = *p | ((1 << ((s_int << 3) & 31)) - 1);
+
+	while ((bits = __insn_seqb(v, 0)) == 0) {
+		if (bytes_read >= count) {
+			/* Read COUNT bytes and didn't find the terminator. */
+			return count;
+		}
+		v = *++p;
+		bytes_read += sizeof(v);
+	}
+
+	len = ((const char *) p) + (__insn_ctz(bits) >> 3) - s;
+	return (len < count ? len : count);
+}
+EXPORT_SYMBOL(strnlen);
diff --git a/arch/tile/lib/strnlen_64.c b/arch/tile/lib/strnlen_64.c
new file mode 100644
index 0000000..2e8de6a
--- /dev/null
+++ b/arch/tile/lib/strnlen_64.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include "string-endian.h"
+
+size_t strnlen(const char *s, size_t count)
+{
+	/* Get an aligned pointer. */
+	const uintptr_t s_int = (uintptr_t) s;
+	const uint64_t *p = (const uint64_t *)(s_int & -8);
+	size_t bytes_read = sizeof(*p) - (s_int & (sizeof(*p) - 1));
+	size_t len;
+	uint64_t v, bits;
+
+	/* Avoid page fault risk by not reading any bytes when count is 0. */
+	if (count == 0)
+		return 0;
+
+	/* Read and MASK the first word. */
+	v = *p | MASK(s_int);
+
+	while ((bits = __insn_v1cmpeqi(v, 0)) == 0) {
+		if (bytes_read >= count) {
+			/* Read COUNT bytes and didn't find the terminator. */
+			return count;
+		}
+		v = *++p;
+		bytes_read += sizeof(v);
+	}
+
+	len = ((const char *) p) + (CFZ(bits) >> 3) - s;
+	return (len < count ? len : count);
+}
+EXPORT_SYMBOL(strnlen);
diff --git a/arch/tile/lib/usercopy_32.S b/arch/tile/lib/usercopy_32.S
index b62d002..21ffa88 100644
--- a/arch/tile/lib/usercopy_32.S
+++ b/arch/tile/lib/usercopy_32.S
@@ -109,25 +109,6 @@ STD_ENTRY(flush_user_asm)
 	.popsection
 
 /*
- * inv_user_asm takes the user target address in r0 and the
- * number of bytes to invalidate in r1.
- * It returns the number of not inv'able bytes (hopefully zero) in r0.
- */
-STD_ENTRY(inv_user_asm)
-	bz r1, 2f
-	{ movei r2, L2_CACHE_BYTES; add r1, r0, r1 }
-	{ sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 }
-	{ and r0, r0, r2; and r1, r1, r2 }
-	{ sub r1, r1, r0 }
-1:      { inv r0; addi r1, r1, -CHIP_INV_STRIDE() }
-	{ addi r0, r0, CHIP_INV_STRIDE(); bnzt r1, 1b }
-2:      { move r0, r1; jrp lr }
-	STD_ENDPROC(inv_user_asm)
-	.pushsection __ex_table,"a"
-	.word 1b, 2b
-	.popsection
-
-/*
  * finv_user_asm takes the user target address in r0 and the
  * number of bytes to flush-invalidate in r1.
  * It returns the number of not finv'able bytes (hopefully zero) in r0.
diff --git a/arch/tile/lib/usercopy_64.S b/arch/tile/lib/usercopy_64.S
index adb2dbb..f248d31 100644
--- a/arch/tile/lib/usercopy_64.S
+++ b/arch/tile/lib/usercopy_64.S
@@ -109,25 +109,6 @@ STD_ENTRY(flush_user_asm)
 	.popsection
 
 /*
- * inv_user_asm takes the user target address in r0 and the
- * number of bytes to invalidate in r1.
- * It returns the number of not inv'able bytes (hopefully zero) in r0.
- */
-STD_ENTRY(inv_user_asm)
-	beqz r1, 2f
-	{ movei r2, L2_CACHE_BYTES; add r1, r0, r1 }
-	{ sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 }
-	{ and r0, r0, r2; and r1, r1, r2 }
-	{ sub r1, r1, r0 }
-1:      { inv r0; addi r1, r1, -CHIP_INV_STRIDE() }
-	{ addi r0, r0, CHIP_INV_STRIDE(); bnezt r1, 1b }
-2:      { move r0, r1; jrp lr }
-	STD_ENDPROC(inv_user_asm)
-	.pushsection __ex_table,"a"
-	.quad 1b, 2b
-	.popsection
-
-/*
  * finv_user_asm takes the user target address in r0 and the
  * number of bytes to flush-invalidate in r1.
  * It returns the number of not finv'able bytes (hopefully zero) in r0.
diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c
index 743c951..23f044e 100644
--- a/arch/tile/mm/elf.c
+++ b/arch/tile/mm/elf.c
@@ -21,7 +21,8 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
-#include <arch/sim_def.h>
+#include <asm/vdso.h>
+#include <arch/sim.h>
 
 /* Notify a running simulator, if any, that an exec just occurred. */
 static void sim_notify_exec(const char *binary_name)
@@ -38,21 +39,55 @@ static void sim_notify_exec(const char *binary_name)
 
 static int notify_exec(struct mm_struct *mm)
 {
-	int retval = 0;  /* failure */
-
-	if (mm->exe_file) {
-		char *buf = (char *) __get_free_page(GFP_KERNEL);
-		if (buf) {
-			char *path = d_path(&mm->exe_file->f_path,
-					    buf, PAGE_SIZE);
-			if (!IS_ERR(path)) {
-				sim_notify_exec(path);
-				retval = 1;
-			}
-			free_page((unsigned long)buf);
+	char *buf, *path;
+	struct vm_area_struct *vma;
+
+	if (!sim_is_simulator())
+		return 1;
+
+	if (mm->exe_file == NULL)
+		return 0;
+
+	for (vma = current->mm->mmap; ; vma = vma->vm_next) {
+		if (vma == NULL)
+			return 0;
+		if (vma->vm_file == mm->exe_file)
+			break;
+	}
+
+	buf = (char *) __get_free_page(GFP_KERNEL);
+	if (buf == NULL)
+		return 0;
+
+	path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE);
+	if (IS_ERR(path)) {
+		free_page((unsigned long)buf);
+		return 0;
+	}
+
+	/*
+	 * Notify simulator of an ET_DYN object so we know the load address.
+	 * The somewhat cryptic overuse of SIM_CONTROL_DLOPEN allows us
+	 * to be backward-compatible with older simulator releases.
+	 */
+	if (vma->vm_start == (ELF_ET_DYN_BASE & PAGE_MASK)) {
+		char buf[64];
+		int i;
+
+		snprintf(buf, sizeof(buf), "0x%lx:@", vma->vm_start);
+		for (i = 0; ; ++i) {
+			char c = buf[i];
+			__insn_mtspr(SPR_SIM_CONTROL,
+				     (SIM_CONTROL_DLOPEN
+				      | (c << _SIM_CONTROL_OPERATOR_BITS)));
+			if (c == '\0')
+				break;
 		}
 	}
-	return retval;
+
+	sim_notify_exec(path);
+	free_page((unsigned long)buf);
+	return 1;
 }
 
 /* Notify a running simulator, if any, that we loaded an interpreter. */
@@ -68,37 +103,10 @@ static void sim_notify_interp(unsigned long load_addr)
 }
 
 
-/* Kernel address of page used to map read-only kernel data into userspace. */
-static void *vdso_page;
-
-/* One-entry array used for install_special_mapping. */
-static struct page *vdso_pages[1];
-
-static int __init vdso_setup(void)
-{
-	vdso_page = (void *)get_zeroed_page(GFP_ATOMIC);
-	memcpy(vdso_page, __rt_sigreturn, __rt_sigreturn_end - __rt_sigreturn);
-	vdso_pages[0] = virt_to_page(vdso_page);
-	return 0;
-}
-device_initcall(vdso_setup);
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-	if (vma->vm_private_data == vdso_pages)
-		return "[vdso]";
-#ifndef __tilegx__
-	if (vma->vm_start == MEM_USER_INTRPT)
-		return "[intrpt]";
-#endif
-	return NULL;
-}
-
 int arch_setup_additional_pages(struct linux_binprm *bprm,
 				int executable_stack)
 {
 	struct mm_struct *mm = current->mm;
-	unsigned long vdso_base;
 	int retval = 0;
 
 	down_write(&mm->mmap_sem);
@@ -111,14 +119,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	if (!notify_exec(mm))
 		sim_notify_exec(bprm->filename);
 
-	/*
-	 * MAYWRITE to allow gdb to COW and set breakpoints
-	 */
-	vdso_base = VDSO_BASE;
-	retval = install_special_mapping(mm, vdso_base, PAGE_SIZE,
-					 VM_READ|VM_EXEC|
-					 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-					 vdso_pages);
+	retval = setup_vdso_pages();
 
 #ifndef __tilegx__
 	/*
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index f7f99f9..b8fae6f 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -122,10 +122,9 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
 	pmd_k = pmd_offset(pud_k, address);
 	if (!pmd_present(*pmd_k))
 		return NULL;
-	if (!pmd_present(*pmd)) {
+	if (!pmd_present(*pmd))
 		set_pmd(pmd, *pmd_k);
-		arch_flush_lazy_mmu_mode();
-	} else
+	else
 		BUG_ON(pmd_ptfn(*pmd) != pmd_ptfn(*pmd_k));
 	return pmd_k;
 }
@@ -280,8 +279,7 @@ static int handle_page_fault(struct pt_regs *regs,
 	if (!is_page_fault)
 		write = 1;
 
-	flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-		 (write ? FAULT_FLAG_WRITE : 0));
+	flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL);
 
@@ -365,6 +363,9 @@ static int handle_page_fault(struct pt_regs *regs,
 		goto bad_area_nosemaphore;
 	}
 
+	if (!is_kernel_mode)
+		flags |= FAULT_FLAG_USER;
+
 	/*
 	 * When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
@@ -425,12 +426,12 @@ good_area:
 #endif
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
 	} else {
 		if (!is_page_fault || !(vma->vm_flags & VM_READ))
 			goto bad_area;
 	}
 
- survive:
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
@@ -568,11 +569,6 @@ no_context:
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (is_global_init(tsk)) {
-		yield();
-		down_read(&mm->mmap_sem);
-		goto survive;
-	}
 	if (is_kernel_mode)
 		goto no_context;
 	pagefault_out_of_memory();
@@ -722,8 +718,49 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
 {
 	int is_page_fault;
 
+#ifdef __tilegx__
+	/*
+	 * We don't need early do_page_fault_ics() support, since unlike
+	 * Pro we don't need to worry about unlocking the atomic locks.
+	 * There is only one current case in GX where we touch any memory
+	 * under ICS other than our own kernel stack, and we handle that
+	 * here.  (If we crash due to trying to touch our own stack,
+	 * we're in too much trouble for C code to help out anyway.)
+	 */
+	if (write & ~1) {
+		unsigned long pc = write & ~1;
+		if (pc >= (unsigned long) __start_unalign_asm_code &&
+		    pc < (unsigned long) __end_unalign_asm_code) {
+			struct thread_info *ti = current_thread_info();
+			/*
+			 * Our EX_CONTEXT is still what it was from the
+			 * initial unalign exception, but now we've faulted
+			 * on the JIT page.  We would like to complete the
+			 * page fault however is appropriate, and then retry
+			 * the instruction that caused the unalign exception.
+			 * Our state has been "corrupted" by setting the low
+			 * bit in "sp", and stashing r0..r3 in the
+			 * thread_info area, so we revert all of that, then
+			 * continue as if this were a normal page fault.
+			 */
+			regs->sp &= ~1UL;
+			regs->regs[0] = ti->unalign_jit_tmp[0];
+			regs->regs[1] = ti->unalign_jit_tmp[1];
+			regs->regs[2] = ti->unalign_jit_tmp[2];
+			regs->regs[3] = ti->unalign_jit_tmp[3];
+			write &= 1;
+		} else {
+			pr_alert("%s/%d: ICS set at page fault at %#lx: %#lx\n",
+				 current->comm, current->pid, pc, address);
+			show_regs(regs);
+			do_group_exit(SIGKILL);
+			return;
+		}
+	}
+#else
 	/* This case should have been handled by do_page_fault_ics(). */
 	BUG_ON(write & ~1);
+#endif
 
 #if CHIP_HAS_TILE_DMA()
 	/*
@@ -870,7 +907,8 @@ void vmalloc_sync_all(void)
 {
 #ifdef __tilegx__
 	/* Currently all L1 kernel pmd's are static and shared. */
-	BUG_ON(pgd_index(VMALLOC_END) != pgd_index(VMALLOC_START));
+	BUILD_BUG_ON(pgd_index(VMALLOC_END - PAGE_SIZE) !=
+		     pgd_index(VMALLOC_START));
 #else
 	/*
 	 * Note that races in the updates of insync and start aren't
diff --git a/arch/tile/mm/highmem.c b/arch/tile/mm/highmem.c
index 347d123..0dc2182 100644
--- a/arch/tile/mm/highmem.c
+++ b/arch/tile/mm/highmem.c
@@ -114,7 +114,6 @@ static void kmap_atomic_register(struct page *page, int type,
 
 	list_add(&amp->list, &amp_list);
 	set_pte(ptep, pteval);
-	arch_flush_lazy_mmu_mode();
 
 	spin_unlock(&amp_lock);
 	homecache_kpte_unlock(flags);
@@ -259,7 +258,6 @@ void __kunmap_atomic(void *kvaddr)
 		BUG_ON(vaddr >= (unsigned long)high_memory);
 	}
 
-	arch_flush_lazy_mmu_mode();
 	pagefault_enable();
 }
 EXPORT_SYMBOL(__kunmap_atomic);
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index 1ae9119..df46a2d 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -172,7 +172,8 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
 
 static void homecache_finv_page_va(void* va, int home)
 {
-	if (home == smp_processor_id()) {
+	int cpu = get_cpu();
+	if (home == cpu) {
 		finv_buffer_local(va, PAGE_SIZE);
 	} else if (home == PAGE_HOME_HASH) {
 		finv_buffer_remote(va, PAGE_SIZE, 1);
@@ -180,6 +181,7 @@ static void homecache_finv_page_va(void* va, int home)
 		BUG_ON(home < 0 || home >= NR_CPUS);
 		finv_buffer_remote(va, PAGE_SIZE, 0);
 	}
+	put_cpu();
 }
 
 void homecache_finv_map_page(struct page *page, int home)
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c
index 650ccff..e514899 100644
--- a/arch/tile/mm/hugetlbpage.c
+++ b/arch/tile/mm/hugetlbpage.c
@@ -49,38 +49,6 @@ int huge_shift[HUGE_SHIFT_ENTRIES] = {
 #endif
 };
 
-/*
- * This routine is a hybrid of pte_alloc_map() and pte_alloc_kernel().
- * It assumes that L2 PTEs are never in HIGHMEM (we don't support that).
- * It locks the user pagetable, and bumps up the mm->nr_ptes field,
- * but otherwise allocate the page table using the kernel versions.
- */
-static pte_t *pte_alloc_hugetlb(struct mm_struct *mm, pmd_t *pmd,
-				unsigned long address)
-{
-	pte_t *new;
-
-	if (pmd_none(*pmd)) {
-		new = pte_alloc_one_kernel(mm, address);
-		if (!new)
-			return NULL;
-
-		smp_wmb(); /* See comment in __pte_alloc */
-
-		spin_lock(&mm->page_table_lock);
-		if (likely(pmd_none(*pmd))) {  /* Has another populated it ? */
-			mm->nr_ptes++;
-			pmd_populate_kernel(mm, pmd, new);
-			new = NULL;
-		} else
-			VM_BUG_ON(pmd_trans_splitting(*pmd));
-		spin_unlock(&mm->page_table_lock);
-		if (new)
-			pte_free_kernel(mm, new);
-	}
-
-	return pte_offset_kernel(pmd, address);
-}
 #endif
 
 pte_t *huge_pte_alloc(struct mm_struct *mm,
@@ -109,7 +77,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
 		else {
 			if (sz != PAGE_SIZE << huge_shift[HUGE_SHIFT_PAGE])
 				panic("Unexpected page size %#lx\n", sz);
-			return pte_alloc_hugetlb(mm, pmd, addr);
+			return pte_alloc_map(mm, NULL, pmd, addr);
 		}
 	}
 #else
@@ -144,14 +112,14 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 
 	/* Get the top-level page table entry. */
 	pgd = (pgd_t *)get_pte((pte_t *)mm->pgd, pgd_index(addr), 0);
-	if (!pgd_present(*pgd))
-		return NULL;
 
 	/* We don't have four levels. */
 	pud = pud_offset(pgd, addr);
 #ifndef __PAGETABLE_PUD_FOLDED
 # error support fourth page table level
 #endif
+	if (!pud_present(*pud))
+		return NULL;
 
 	/* Check for an L0 huge PTE, if we have three levels. */
 #ifndef __PAGETABLE_PMD_FOLDED
diff --git a/arch/tile/mm/migrate_32.S b/arch/tile/mm/migrate_32.S
index 5305814..7720854 100644
--- a/arch/tile/mm/migrate_32.S
+++ b/arch/tile/mm/migrate_32.S
@@ -136,7 +136,7 @@ STD_ENTRY(flush_and_install_context)
 	 move r8, zero  /* asids */
 	 move r9, zero  /* asidcount */
 	}
-	jal hv_flush_remote
+	jal _hv_flush_remote
 	bnz r0, .Ldone
 
 	/* Now install the new page table. */
@@ -152,7 +152,7 @@ STD_ENTRY(flush_and_install_context)
 	 move r4, r_asid
 	 moveli r5, HV_CTX_DIRECTIO | CTX_PAGE_FLAG
 	}
-	jal hv_install_context
+	jal _hv_install_context
 	bnz r0, .Ldone
 
 	/* Finally, flush the TLB. */
diff --git a/arch/tile/mm/migrate_64.S b/arch/tile/mm/migrate_64.S
index 1d15b108..a49eee3 100644
--- a/arch/tile/mm/migrate_64.S
+++ b/arch/tile/mm/migrate_64.S
@@ -123,7 +123,7 @@ STD_ENTRY(flush_and_install_context)
 	}
 	{
 	 move r8, zero  /* asidcount */
-	 jal hv_flush_remote
+	 jal _hv_flush_remote
 	}
 	bnez r0, 1f
 
@@ -136,7 +136,7 @@ STD_ENTRY(flush_and_install_context)
 	 move r2, r_asid
 	 moveli r3, HV_CTX_DIRECTIO | CTX_PAGE_FLAG
 	}
-	jal hv_install_context
+	jal _hv_install_context
 	bnez r0, 1f
 
 	/* Finally, flush the TLB. */
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index dfd63ce..2bd572b 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -568,7 +568,7 @@ void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
 	addr = area->addr;
 	if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
 			       phys_addr, pgprot)) {
-		remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
+		free_vm_area(area);
 		return NULL;
 	}
 	return (__force void __iomem *) (offset + (char *)addr);
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 089f398..5c3aef7 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -30,8 +30,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
 	pmd_t *pmd;
 	pte_t *pte;
 	int err = -EFAULT;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				 (is_write ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	*code_out = SEGV_MAPERR;
 
@@ -42,6 +41,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
 	if (in_atomic())
 		goto out_nosemaphore;
 
+	if (is_user)
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -58,12 +59,15 @@ retry:
 
 good_area:
 	*code_out = SEGV_ACCERR;
-	if (is_write && !(vma->vm_flags & VM_WRITE))
-		goto out;
-
-	/* Don't require VM_READ|VM_EXEC for write faults! */
-	if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
-		goto out;
+	if (is_write) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto out;
+		flags |= FAULT_FLAG_WRITE;
+	} else {
+		/* Don't require VM_READ|VM_EXEC for write faults! */
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto out;
+	}
 
 	do {
 		int fault;
@@ -124,6 +128,8 @@ out_of_memory:
 	 * (which will retry the fault, or kill us if we got oom-killed).
 	 */
 	up_read(&mm->mmap_sem);
+	if (!is_user)
+		goto out_nosemaphore;
 	pagefault_out_of_memory();
 	return 0;
 }
diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c
index f9b5c10..0dc922d 100644
--- a/arch/unicore32/mm/fault.c
+++ b/arch/unicore32/mm/fault.c
@@ -209,8 +209,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	int fault, sig, code;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-				 ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	tsk = current;
 	mm = tsk->mm;
@@ -222,6 +221,11 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	if (in_atomic() || !mm)
 		goto no_context;
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
+	if (!(fsr ^ 0x12))
+		flags |= FAULT_FLAG_WRITE;
+
 	/*
 	 * As per x86, we may deadlock here.  However, since the kernel only
 	 * validly references user space from well defined areas of the code,
@@ -278,6 +282,13 @@ retry:
 	       (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
 		return 0;
 
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (!user_mode(regs))
+		goto no_context;
+
 	if (fault & VM_FAULT_OOM) {
 		/*
 		 * We ran out of memory, call the OOM killer, and return to
@@ -288,13 +299,6 @@ retry:
 		return 0;
 	}
 
-	/*
-	 * If we are in kernel mode at this point, we
-	 * have no context to handle this fault with.
-	 */
-	if (!user_mode(regs))
-		goto no_context;
-
 	if (fault & VM_FAULT_SIGBUS) {
 		/*
 		 * We had some memory, but were unable to
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b32ebf9..047ba6a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -81,7 +81,6 @@ config X86
 	select HAVE_USER_RETURN_NOTIFIER
 	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 	select HAVE_ARCH_JUMP_LABEL
-	select HAVE_TEXT_POKE_SMP
 	select HAVE_GENERIC_HARDIRQS
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select SPARSE_IRQ
@@ -1344,8 +1343,12 @@ config ARCH_SELECT_MEMORY_MODEL
 	depends on ARCH_SPARSEMEM_ENABLE
 
 config ARCH_MEMORY_PROBE
-	def_bool y
+	bool "Enable sysfs memory/probe interface"
 	depends on X86_64 && MEMORY_HOTPLUG
+	help
+	  This option enables a sysfs memory/probe interface for testing.
+	  See Documentation/memory-hotplug.txt for more information.
+	  If you are unsure how to answer this question, answer N.
 
 config ARCH_PROC_KCORE_TEXT
 	def_bool y
@@ -2014,7 +2017,6 @@ menu "Bus options (PCI etc.)"
 config PCI
 	bool "PCI support"
 	default y
-	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
 	---help---
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -2332,10 +2334,6 @@ config HAVE_ATOMIC_IOMAP
 	def_bool y
 	depends on X86_32
 
-config HAVE_TEXT_POKE_SMP
-	bool
-	select STOP_MACHINE if SMP
-
 config X86_DEV_DMA_OPS
 	bool
 	depends on X86_64 || STA2X11
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index d606463..b7388a4 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -225,7 +225,7 @@ static void low_free(unsigned long size, unsigned long addr)
 	unsigned long nr_pages;
 
 	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-	efi_call_phys2(sys_table->boottime->free_pages, addr, size);
+	efi_call_phys2(sys_table->boottime->free_pages, addr, nr_pages);
 }
 
 static void find_bits(unsigned long mask, u8 *pos, u8 *size)
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index bae3aba..b987cd5 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -130,14 +130,6 @@ static void set_brk(unsigned long start, unsigned long end)
 
 #include <linux/coredump.h>
 
-#define DUMP_WRITE(addr, nr)			     \
-	if (!dump_write(file, (void *)(addr), (nr))) \
-		goto end_coredump;
-
-#define DUMP_SEEK(offset)		\
-	if (!dump_seek(file, offset))	\
-		goto end_coredump;
-
 #define START_DATA()	(u.u_tsize << PAGE_SHIFT)
 #define START_STACK(u)	(u.start_stack)
 
@@ -190,22 +182,26 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
 
 	set_fs(KERNEL_DS);
 	/* struct user */
-	DUMP_WRITE(&dump, sizeof(dump));
+	if (!dump_emit(cprm, &dump, sizeof(dump)))
+		goto end_coredump;
 	/* Now dump all of the user data.  Include malloced stuff as well */
-	DUMP_SEEK(PAGE_SIZE - sizeof(dump));
+	if (!dump_align(cprm, PAGE_SIZE))
+		goto end_coredump;
 	/* now we start writing out the user space info */
 	set_fs(USER_DS);
 	/* Dump the data area */
 	if (dump.u_dsize != 0) {
 		dump_start = START_DATA(dump);
 		dump_size = dump.u_dsize << PAGE_SHIFT;
-		DUMP_WRITE(dump_start, dump_size);
+		if (!dump_emit(cprm, dump_start, dump_size))
+			goto end_coredump;
 	}
 	/* Now prepare to dump the stack area */
 	if (dump.u_ssize != 0) {
 		dump_start = START_STACK(dump);
 		dump_size = dump.u_ssize << PAGE_SHIFT;
-		DUMP_WRITE(dump_start, dump_size);
+		if (!dump_emit(cprm, dump_start, dump_size))
+			goto end_coredump;
 	}
 end_coredump:
 	set_fs(fs);
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 474dc1b..4299eb0 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -452,7 +452,7 @@ ia32_badsys:
 
 	CFI_ENDPROC
 	
-	.macro PTREGSCALL label, func, arg
+	.macro PTREGSCALL label, func
 	ALIGN
 GLOBAL(\label)
 	leaq \func(%rip),%rax
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 2dfac58..b1977ba 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -86,6 +86,7 @@ extern int acpi_pci_disabled;
 extern int acpi_skip_timer_override;
 extern int acpi_use_timer_override;
 extern int acpi_fix_pin2_polarity;
+extern int acpi_disable_cmcff;
 
 extern u8 acpi_sci_flags;
 extern int acpi_sci_override_gsi;
@@ -168,6 +169,7 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)
 
 #define acpi_lapic 0
 #define acpi_ioapic 0
+#define acpi_disable_cmcff 0
 static inline void acpi_noirq_set(void) { }
 static inline void acpi_disable_pci(void) { }
 static inline void disable_acpi(void) { }
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 58ed6d9..0a3f9c9 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -5,6 +5,7 @@
 #include <linux/stddef.h>
 #include <linux/stringify.h>
 #include <asm/asm.h>
+#include <asm/ptrace.h>
 
 /*
  * Alternative inline assembly for SMP.
@@ -220,20 +221,11 @@ extern void *text_poke_early(void *addr, const void *opcode, size_t len);
  * no thread can be preempted in the instructions being modified (no iret to an
  * invalid instruction possible) or if the instructions are changed from a
  * consistent state to another consistent state atomically.
- * More care must be taken when modifying code in the SMP case because of
- * Intel's errata. text_poke_smp() takes care that errata, but still
- * doesn't support NMI/MCE handler code modifying.
  * On the local CPU you need to be protected again NMI or MCE handlers seeing an
  * inconsistent instruction while you patch.
  */
-struct text_poke_param {
-	void *addr;
-	const void *opcode;
-	size_t len;
-};
-
 extern void *text_poke(void *addr, const void *opcode, size_t len);
-extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
-extern void text_poke_smp_batch(struct text_poke_param *params, int n);
+extern int poke_int3_handler(struct pt_regs *regs);
+extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler);
 
 #endif /* _ASM_X86_ALTERNATIVE_H */
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 6dfd019..41639ce 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -15,6 +15,14 @@
 #include <linux/compiler.h>
 #include <asm/alternative.h>
 
+#if BITS_PER_LONG == 32
+# define _BITOPS_LONG_SHIFT 5
+#elif BITS_PER_LONG == 64
+# define _BITOPS_LONG_SHIFT 6
+#else
+# error "Unexpected BITS_PER_LONG"
+#endif
+
 #define BIT_64(n)			(U64_C(1) << (n))
 
 /*
@@ -59,7 +67,7 @@
  * restricted to acting on a single-word quantity.
  */
 static __always_inline void
-set_bit(unsigned int nr, volatile unsigned long *addr)
+set_bit(long nr, volatile unsigned long *addr)
 {
 	if (IS_IMMEDIATE(nr)) {
 		asm volatile(LOCK_PREFIX "orb %1,%0"
@@ -81,7 +89,7 @@ set_bit(unsigned int nr, volatile unsigned long *addr)
  * If it's called on the same region of memory simultaneously, the effect
  * may be that only one operation succeeds.
  */
-static inline void __set_bit(int nr, volatile unsigned long *addr)
+static inline void __set_bit(long nr, volatile unsigned long *addr)
 {
 	asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
 }
@@ -97,7 +105,7 @@ static inline void __set_bit(int nr, volatile unsigned long *addr)
  * in order to ensure changes are visible on other processors.
  */
 static __always_inline void
-clear_bit(int nr, volatile unsigned long *addr)
+clear_bit(long nr, volatile unsigned long *addr)
 {
 	if (IS_IMMEDIATE(nr)) {
 		asm volatile(LOCK_PREFIX "andb %1,%0"
@@ -118,13 +126,13 @@ clear_bit(int nr, volatile unsigned long *addr)
  * clear_bit() is atomic and implies release semantics before the memory
  * operation. It can be used for an unlock.
  */
-static inline void clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
+static inline void clear_bit_unlock(long nr, volatile unsigned long *addr)
 {
 	barrier();
 	clear_bit(nr, addr);
 }
 
-static inline void __clear_bit(int nr, volatile unsigned long *addr)
+static inline void __clear_bit(long nr, volatile unsigned long *addr)
 {
 	asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
 }
@@ -141,7 +149,7 @@ static inline void __clear_bit(int nr, volatile unsigned long *addr)
  * No memory barrier is required here, because x86 cannot reorder stores past
  * older loads. Same principle as spin_unlock.
  */
-static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
+static inline void __clear_bit_unlock(long nr, volatile unsigned long *addr)
 {
 	barrier();
 	__clear_bit(nr, addr);
@@ -159,7 +167,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
  * If it's called on the same region of memory simultaneously, the effect
  * may be that only one operation succeeds.
  */
-static inline void __change_bit(int nr, volatile unsigned long *addr)
+static inline void __change_bit(long nr, volatile unsigned long *addr)
 {
 	asm volatile("btc %1,%0" : ADDR : "Ir" (nr));
 }
@@ -173,7 +181,7 @@ static inline void __change_bit(int nr, volatile unsigned long *addr)
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static inline void change_bit(int nr, volatile unsigned long *addr)
+static inline void change_bit(long nr, volatile unsigned long *addr)
 {
 	if (IS_IMMEDIATE(nr)) {
 		asm volatile(LOCK_PREFIX "xorb %1,%0"
@@ -194,7 +202,7 @@ static inline void change_bit(int nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_set_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -212,7 +220,7 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
  * This is the same as test_and_set_bit on x86.
  */
 static __always_inline int
-test_and_set_bit_lock(int nr, volatile unsigned long *addr)
+test_and_set_bit_lock(long nr, volatile unsigned long *addr)
 {
 	return test_and_set_bit(nr, addr);
 }
@@ -226,7 +234,7 @@ test_and_set_bit_lock(int nr, volatile unsigned long *addr)
  * If two examples of this operation race, one can appear to succeed
  * but actually fail.  You must protect multiple accesses with a lock.
  */
-static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -245,7 +253,7 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -272,7 +280,7 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
  * accessed from a hypervisor on the same CPU if running in a VM: don't change
  * this without also updating arch/x86/kernel/kvm.c
  */
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -284,7 +292,7 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
 }
 
 /* WARNING: non atomic and it can be reordered! */
-static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -304,7 +312,7 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_change_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -315,13 +323,13 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 	return oldbit;
 }
 
-static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
+static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
 {
-	return ((1UL << (nr % BITS_PER_LONG)) &
-		(addr[nr / BITS_PER_LONG])) != 0;
+	return ((1UL << (nr & (BITS_PER_LONG-1))) &
+		(addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
 }
 
-static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
+static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
 {
 	int oldbit;
 
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 47538a6..d3f5c63 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -366,9 +366,10 @@ extern bool __static_cpu_has_safe(u16 bit);
  */
 static __always_inline __pure bool __static_cpu_has(u16 bit)
 {
-#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5
+#ifdef CC_HAVE_ASM_GOTO
 
 #ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS
+
 		/*
 		 * Catch too early usage of this before alternatives
 		 * have run.
@@ -384,6 +385,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 			 ".previous\n"
 			 /* skipping size check since replacement size = 0 */
 			 : : "i" (X86_FEATURE_ALWAYS) : : t_warn);
+
 #endif
 
 		asm goto("1: jmp %l[t_no]\n"
@@ -406,7 +408,9 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 		warn_pre_alternatives();
 		return false;
 #endif
-#else /* GCC_VERSION >= 40500 */
+
+#else /* CC_HAVE_ASM_GOTO */
+
 		u8 flag;
 		/* Open-coded due to __stringify() in ALTERNATIVE() */
 		asm volatile("1: movb $0,%0\n"
@@ -427,7 +431,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 			     ".previous\n"
 			     : "=qm" (flag) : "i" (bit));
 		return flag;
-#endif
+
+#endif /* CC_HAVE_ASM_GOTO */
 }
 
 #define static_cpu_has(bit)					\
@@ -441,7 +446,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 
 static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
 {
-#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5
+#ifdef CC_HAVE_ASM_GOTO
 /*
  * We need to spell the jumps to the compiler because, depending on the offset,
  * the replacement jump can be bigger than the original jump, and this we cannot
@@ -475,7 +480,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
 		return false;
 	t_dynamic:
 		return __static_cpu_has_safe(bit);
-#else /* GCC_VERSION >= 40500 */
+#else
 		u8 flag;
 		/* Open-coded due to __stringify() in ALTERNATIVE() */
 		asm volatile("1: movb $2,%0\n"
@@ -511,7 +516,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
 			     : "=qm" (flag)
 			     : "i" (bit), "i" (X86_FEATURE_ALWAYS));
 		return (flag == 2 ? __static_cpu_has_safe(bit) : flag);
-#endif
+#endif /* CC_HAVE_ASM_GOTO */
 }
 
 #define static_cpu_has_safe(bit)				\
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index cccd07f..b8e9224 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -17,6 +17,8 @@ extern unsigned long pci_mem_start;
 extern int e820_any_mapped(u64 start, u64 end, unsigned type);
 extern int e820_all_mapped(u64 start, u64 end, unsigned type);
 extern void e820_add_region(u64 start, u64 size, int type);
+extern void e820_add_limit_region(u64 start, u64 size, int type);
+extern void e820_adjust_region(u64 *start, u64 *size);
 extern void e820_print_map(char *who);
 extern int
 sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map);
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index f87f7fc..f5df0a8 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -323,6 +323,7 @@ struct kvm_pmu {
 	u64 global_ovf_ctrl;
 	u64 counter_bitmask[2];
 	u64 global_ctrl_mask;
+	u64 reserved_bits;
 	u8 version;
 	struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
 	struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
@@ -802,8 +803,8 @@ extern u32  kvm_min_guest_tsc_khz;
 extern u32  kvm_max_guest_tsc_khz;
 
 enum emulation_result {
-	EMULATE_DONE,       /* no further processing */
-	EMULATE_DO_MMIO,      /* kvm_run filled with mmio request */
+	EMULATE_DONE,         /* no further processing */
+	EMULATE_USER_EXIT,    /* kvm_run ready for userspace exit */
 	EMULATE_FAIL,         /* can't emulate this instruction */
 };
 
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 29e3093..163d7a4 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -188,6 +188,9 @@ extern void register_mce_write_callback(ssize_t (*)(struct file *filp,
 				    const char __user *ubuf,
 				    size_t usize, loff_t *off));
 
+/* Disable CMCI/polling for MCA bank claimed by firmware */
+extern void mce_disable_bank(int bank);
+
 /*
  * Exception handler
  */
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index cdbf367..be12c53 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -45,22 +45,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 		/* Re-load page tables */
 		load_cr3(next->pgd);
 
-		/* stop flush ipis for the previous mm */
+		/* Stop flush ipis for the previous mm */
 		cpumask_clear_cpu(cpu, mm_cpumask(prev));
 
-		/*
-		 * load the LDT, if the LDT is different:
-		 */
+		/* Load the LDT, if the LDT is different: */
 		if (unlikely(prev->context.ldt != next->context.ldt))
 			load_LDT_nolock(&next->context);
 	}
 #ifdef CONFIG_SMP
-	else {
+	  else {
 		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
 		BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next);
 
-		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) {
-			/* We were in lazy tlb mode and leave_mm disabled
+		if (!cpumask_test_cpu(cpu, mm_cpumask(next))) {
+			/*
+			 * On established mms, the mm_cpumask is only changed
+			 * from irq context, from ptep_clear_flush() while in
+			 * lazy tlb mode, and here. Irqs are blocked during
+			 * schedule, protecting us from simultaneous changes.
+			 */
+			cpumask_set_cpu(cpu, mm_cpumask(next));
+			/*
+			 * We were in lazy tlb mode and leave_mm disabled
 			 * tlb flush IPI delivery. We must reload CR3
 			 * to make sure to use no freed page tables.
 			 */
diff --git a/arch/x86/include/asm/mutex_64.h b/arch/x86/include/asm/mutex_64.h
index 2c543ff..e7e6751 100644
--- a/arch/x86/include/asm/mutex_64.h
+++ b/arch/x86/include/asm/mutex_64.h
@@ -16,6 +16,20 @@
  *
  * Atomically decrements @v and calls <fail_fn> if the result is negative.
  */
+#ifdef CC_HAVE_ASM_GOTO
+static inline void __mutex_fastpath_lock(atomic_t *v,
+					 void (*fail_fn)(atomic_t *))
+{
+	asm volatile goto(LOCK_PREFIX "   decl %0\n"
+			  "   jns %l[exit]\n"
+			  : : "m" (v->counter)
+			  : "memory", "cc"
+			  : exit);
+	fail_fn(v);
+exit:
+	return;
+}
+#else
 #define __mutex_fastpath_lock(v, fail_fn)			\
 do {								\
 	unsigned long dummy;					\
@@ -32,6 +46,7 @@ do {								\
 		     : "rax", "rsi", "rdx", "rcx",		\
 		       "r8", "r9", "r10", "r11", "memory");	\
 } while (0)
+#endif
 
 /**
  *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
@@ -56,6 +71,20 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count)
  *
  * Atomically increments @v and calls <fail_fn> if the result is nonpositive.
  */
+#ifdef CC_HAVE_ASM_GOTO
+static inline void __mutex_fastpath_unlock(atomic_t *v,
+					   void (*fail_fn)(atomic_t *))
+{
+	asm volatile goto(LOCK_PREFIX "   incl %0\n"
+			  "   jg %l[exit]\n"
+			  : : "m" (v->counter)
+			  : "memory", "cc"
+			  : exit);
+	fail_fn(v);
+exit:
+	return;
+}
+#else
 #define __mutex_fastpath_unlock(v, fail_fn)			\
 do {								\
 	unsigned long dummy;					\
@@ -72,6 +101,7 @@ do {								\
 		     : "rax", "rsi", "rdx", "rcx",		\
 		       "r8", "r9", "r10", "r11", "memory");	\
 } while (0)
+#endif
 
 #define __mutex_slowpath_needs_to_unlock()	1
 
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index d9e9e6c..8c61de0 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -100,29 +100,6 @@ static inline void early_quirks(void) { }
 extern void pci_iommu_alloc(void);
 
 #ifdef CONFIG_PCI_MSI
-/* MSI arch specific hooks */
-static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	return x86_msi.setup_msi_irqs(dev, nvec, type);
-}
-
-static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
-{
-	x86_msi.teardown_msi_irqs(dev);
-}
-
-static inline void x86_teardown_msi_irq(unsigned int irq)
-{
-	x86_msi.teardown_msi_irq(irq);
-}
-static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
-{
-	x86_msi.restore_msi_irqs(dev, irq);
-}
-#define arch_setup_msi_irqs x86_setup_msi_irqs
-#define arch_teardown_msi_irqs x86_teardown_msi_irqs
-#define arch_teardown_msi_irq x86_teardown_msi_irq
-#define arch_restore_msi_irqs x86_restore_msi_irqs
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
@@ -130,11 +107,6 @@ void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev, int irq);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 		  unsigned int irq_base, unsigned int irq_offset);
-/* default to the implementation in drivers/lib/msi.c */
-#define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#define HAVE_DEFAULT_MSI_RESTORE_IRQS
-void default_teardown_msi_irqs(struct pci_dev *dev);
-void default_restore_msi_irqs(struct pci_dev *dev, int irq);
 #else
 #define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h
index f2b489c..3bf2dd0 100644
--- a/arch/x86/include/asm/pgtable-2level.h
+++ b/arch/x86/include/asm/pgtable-2level.h
@@ -55,9 +55,53 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
 #endif
 
+#ifdef CONFIG_MEM_SOFT_DIRTY
+
+/*
+ * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE, _PAGE_BIT_SOFT_DIRTY and
+ * _PAGE_BIT_PROTNONE are taken, split up the 28 bits of offset
+ * into this range.
+ */
+#define PTE_FILE_MAX_BITS	28
+#define PTE_FILE_SHIFT1		(_PAGE_BIT_PRESENT + 1)
+#define PTE_FILE_SHIFT2		(_PAGE_BIT_FILE + 1)
+#define PTE_FILE_SHIFT3		(_PAGE_BIT_PROTNONE + 1)
+#define PTE_FILE_SHIFT4		(_PAGE_BIT_SOFT_DIRTY + 1)
+#define PTE_FILE_BITS1		(PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1)
+#define PTE_FILE_BITS2		(PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1)
+#define PTE_FILE_BITS3		(PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1)
+
+#define pte_to_pgoff(pte)						\
+	((((pte).pte_low >> (PTE_FILE_SHIFT1))				\
+	  & ((1U << PTE_FILE_BITS1) - 1)))				\
+	+ ((((pte).pte_low >> (PTE_FILE_SHIFT2))			\
+	    & ((1U << PTE_FILE_BITS2) - 1))				\
+	   << (PTE_FILE_BITS1))						\
+	+ ((((pte).pte_low >> (PTE_FILE_SHIFT3))			\
+	    & ((1U << PTE_FILE_BITS3) - 1))				\
+	   << (PTE_FILE_BITS1 + PTE_FILE_BITS2))			\
+	+ ((((pte).pte_low >> (PTE_FILE_SHIFT4)))			\
+	    << (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3))
+
+#define pgoff_to_pte(off)						\
+	((pte_t) { .pte_low =						\
+	 ((((off)) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1)	\
+	 + ((((off) >> PTE_FILE_BITS1)					\
+	     & ((1U << PTE_FILE_BITS2) - 1))				\
+	    << PTE_FILE_SHIFT2)						\
+	 + ((((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2))		\
+	     & ((1U << PTE_FILE_BITS3) - 1))				\
+	    << PTE_FILE_SHIFT3)						\
+	 + ((((off) >>							\
+	      (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)))	\
+	    << PTE_FILE_SHIFT4)						\
+	 + _PAGE_FILE })
+
+#else /* CONFIG_MEM_SOFT_DIRTY */
+
 /*
  * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE and _PAGE_BIT_PROTNONE are taken,
- * split up the 29 bits of offset into this range:
+ * split up the 29 bits of offset into this range.
  */
 #define PTE_FILE_MAX_BITS	29
 #define PTE_FILE_SHIFT1		(_PAGE_BIT_PRESENT + 1)
@@ -88,6 +132,8 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 	    << PTE_FILE_SHIFT3)						\
 	 + _PAGE_FILE })
 
+#endif /* CONFIG_MEM_SOFT_DIRTY */
+
 /* Encode and de-code a swap entry */
 #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
 #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
index 4cc9f2b..81bb91b 100644
--- a/arch/x86/include/asm/pgtable-3level.h
+++ b/arch/x86/include/asm/pgtable-3level.h
@@ -179,6 +179,9 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp)
 /*
  * Bits 0, 6 and 7 are taken in the low part of the pte,
  * put the 32 bits of offset into the high part.
+ *
+ * For soft-dirty tracking 11 bit is taken from
+ * the low part of pte as well.
  */
 #define pte_to_pgoff(pte) ((pte).pte_high)
 #define pgoff_to_pte(off)						\
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 7dc305a..1c00631 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -314,6 +314,36 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd)
 	return pmd_set_flags(pmd, _PAGE_SOFT_DIRTY);
 }
 
+static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_SWP_SOFT_DIRTY);
+}
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_SWP_SOFT_DIRTY;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY);
+}
+
+static inline pte_t pte_file_clear_soft_dirty(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_SOFT_DIRTY);
+}
+
+static inline pte_t pte_file_mksoft_dirty(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_SOFT_DIRTY);
+}
+
+static inline int pte_file_soft_dirty(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_SOFT_DIRTY;
+}
+
 /*
  * Mask out unsupported bits in a present pgprot.  Non-present pgprots
  * can use those bits for other purposes, so leave them be.
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index c98ac63..f4843e0 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -61,12 +61,27 @@
  * they do not conflict with each other.
  */
 
+#define _PAGE_BIT_SOFT_DIRTY	_PAGE_BIT_HIDDEN
+
 #ifdef CONFIG_MEM_SOFT_DIRTY
-#define _PAGE_SOFT_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
+#define _PAGE_SOFT_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_SOFT_DIRTY)
 #else
 #define _PAGE_SOFT_DIRTY	(_AT(pteval_t, 0))
 #endif
 
+/*
+ * Tracking soft dirty bit when a page goes to a swap is tricky.
+ * We need a bit which can be stored in pte _and_ not conflict
+ * with swap entry format. On x86 bits 6 and 7 are *not* involved
+ * into swap entry computation, but bit 6 is used for nonlinear
+ * file mapping, so we borrow bit 7 for soft dirty tracking.
+ */
+#ifdef CONFIG_MEM_SOFT_DIRTY
+#define _PAGE_SWP_SOFT_DIRTY	_PAGE_PSE
+#else
+#define _PAGE_SWP_SOFT_DIRTY	(_AT(pteval_t, 0))
+#endif
+
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 #define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
 #else
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 24cf5ae..4f4a3d9 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -942,35 +942,6 @@ extern int set_tsc_mode(unsigned int val);
 
 extern u16 amd_get_nb_id(int cpu);
 
-struct aperfmperf {
-	u64 aperf, mperf;
-};
-
-static inline void get_aperfmperf(struct aperfmperf *am)
-{
-	WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_APERFMPERF));
-
-	rdmsrl(MSR_IA32_APERF, am->aperf);
-	rdmsrl(MSR_IA32_MPERF, am->mperf);
-}
-
-#define APERFMPERF_SHIFT 10
-
-static inline
-unsigned long calc_aperfmperf_ratio(struct aperfmperf *old,
-				    struct aperfmperf *new)
-{
-	u64 aperf = new->aperf - old->aperf;
-	u64 mperf = new->mperf - old->mperf;
-	unsigned long ratio = aperf;
-
-	mperf >>= APERFMPERF_SHIFT;
-	if (mperf)
-		ratio = div64_u64(aperf, mperf);
-
-	return ratio;
-}
-
 extern unsigned long arch_align_stack(unsigned long sp);
 extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
 
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h
index 109a9dd..be8269b 100644
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -93,7 +93,6 @@ unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
 
 struct pvclock_vsyscall_time_info {
 	struct pvclock_vcpu_time_info pvti;
-	u32 migrate_count;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
diff --git a/arch/x86/include/asm/sync_bitops.h b/arch/x86/include/asm/sync_bitops.h
index 9d09b40..05af3b3 100644
--- a/arch/x86/include/asm/sync_bitops.h
+++ b/arch/x86/include/asm/sync_bitops.h
@@ -26,9 +26,9 @@
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static inline void sync_set_bit(int nr, volatile unsigned long *addr)
+static inline void sync_set_bit(long nr, volatile unsigned long *addr)
 {
-	asm volatile("lock; btsl %1,%0"
+	asm volatile("lock; bts %1,%0"
 		     : "+m" (ADDR)
 		     : "Ir" (nr)
 		     : "memory");
@@ -44,9 +44,9 @@ static inline void sync_set_bit(int nr, volatile unsigned long *addr)
  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  * in order to ensure changes are visible on other processors.
  */
-static inline void sync_clear_bit(int nr, volatile unsigned long *addr)
+static inline void sync_clear_bit(long nr, volatile unsigned long *addr)
 {
-	asm volatile("lock; btrl %1,%0"
+	asm volatile("lock; btr %1,%0"
 		     : "+m" (ADDR)
 		     : "Ir" (nr)
 		     : "memory");
@@ -61,9 +61,9 @@ static inline void sync_clear_bit(int nr, volatile unsigned long *addr)
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static inline void sync_change_bit(int nr, volatile unsigned long *addr)
+static inline void sync_change_bit(long nr, volatile unsigned long *addr)
 {
-	asm volatile("lock; btcl %1,%0"
+	asm volatile("lock; btc %1,%0"
 		     : "+m" (ADDR)
 		     : "Ir" (nr)
 		     : "memory");
@@ -77,11 +77,11 @@ static inline void sync_change_bit(int nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr)
+static inline int sync_test_and_set_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
-	asm volatile("lock; btsl %2,%1\n\tsbbl %0,%0"
+	asm volatile("lock; bts %2,%1\n\tsbbl %0,%0"
 		     : "=r" (oldbit), "+m" (ADDR)
 		     : "Ir" (nr) : "memory");
 	return oldbit;
@@ -95,11 +95,11 @@ static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int sync_test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
-	asm volatile("lock; btrl %2,%1\n\tsbbl %0,%0"
+	asm volatile("lock; btr %2,%1\n\tsbbl %0,%0"
 		     : "=r" (oldbit), "+m" (ADDR)
 		     : "Ir" (nr) : "memory");
 	return oldbit;
@@ -113,11 +113,11 @@ static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int sync_test_and_change_bit(long nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
-	asm volatile("lock; btcl %2,%1\n\tsbbl %0,%0"
+	asm volatile("lock; btc %2,%1\n\tsbbl %0,%0"
 		     : "=r" (oldbit), "+m" (ADDR)
 		     : "Ir" (nr) : "memory");
 	return oldbit;
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index cf51200..e6d90ba 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -62,6 +62,7 @@ static inline void __flush_tlb_all(void)
 
 static inline void __flush_tlb_one(unsigned long addr)
 {
+	count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
 	__flush_tlb_single(addr);
 }
 
@@ -84,14 +85,38 @@ static inline void __flush_tlb_one(unsigned long addr)
 
 #ifndef CONFIG_SMP
 
-#define flush_tlb() __flush_tlb()
-#define flush_tlb_all() __flush_tlb_all()
-#define local_flush_tlb() __flush_tlb()
+/* "_up" is for UniProcessor.
+ *
+ * This is a helper for other header functions.  *Not* intended to be called
+ * directly.  All global TLB flushes need to either call this, or to bump the
+ * vm statistics themselves.
+ */
+static inline void __flush_tlb_up(void)
+{
+	count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+	__flush_tlb();
+}
+
+static inline void flush_tlb_all(void)
+{
+	count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+	__flush_tlb_all();
+}
+
+static inline void flush_tlb(void)
+{
+	__flush_tlb_up();
+}
+
+static inline void local_flush_tlb(void)
+{
+	__flush_tlb_up();
+}
 
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 	if (mm == current->active_mm)
-		__flush_tlb();
+		__flush_tlb_up();
 }
 
 static inline void flush_tlb_page(struct vm_area_struct *vma,
@@ -105,14 +130,14 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
 				   unsigned long start, unsigned long end)
 {
 	if (vma->vm_mm == current->active_mm)
-		__flush_tlb();
+		__flush_tlb_up();
 }
 
 static inline void flush_tlb_mm_range(struct mm_struct *mm,
 	   unsigned long start, unsigned long end, unsigned long vmflag)
 {
 	if (mm == current->active_mm)
-		__flush_tlb();
+		__flush_tlb_up();
 }
 
 static inline void native_flush_tlb_others(const struct cpumask *cpumask,
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 095b215..d35f24e 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -124,9 +124,6 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu);
 #define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
 #define topology_core_cpumask(cpu)		(per_cpu(cpu_core_map, cpu))
 #define topology_thread_cpumask(cpu)		(per_cpu(cpu_sibling_map, cpu))
-
-/* indicates that pointers to the topology cpumask_t maps are valid */
-#define arch_provides_topology_pointers		yes
 #endif
 
 static inline void arch_fix_phys_package_id(int num, u32 slot)
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index c91e8b9..235be70 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -49,6 +49,7 @@ extern void tsc_init(void);
 extern void mark_tsc_unstable(char *reason);
 extern int unsynchronized_tsc(void);
 extern int check_tsc_unstable(void);
+extern int check_tsc_disabled(void);
 extern unsigned long native_calibrate_tsc(void);
 
 extern int tsc_clocksource_reliable;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 2627a81..e482d06 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -67,6 +67,7 @@ EXPORT_SYMBOL(acpi_pci_disabled);
 int acpi_lapic;
 int acpi_ioapic;
 int acpi_strict;
+int acpi_disable_cmcff;
 
 u8 acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
@@ -141,16 +142,8 @@ static u32 irq_to_gsi(int irq)
 }
 
 /*
- * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
- * to map the target physical address. The problem is that set_fixmap()
- * provides a single page, and it is possible that the page is not
- * sufficient.
- * By using this area, we can map up to MAX_IO_APICS pages temporarily,
- * i.e. until the next __va_range() call.
- *
- * Important Safety Note:  The fixed I/O APIC page numbers are *subtracted*
- * from the fixed base.  That's why we start at FIX_IO_APIC_BASE_END and
- * count idx down while incrementing the phys address.
+ * This is just a simple wrapper around early_ioremap(),
+ * with sanity checks for phys == 0 and size == 0.
  */
 char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 {
@@ -160,6 +153,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 
 	return early_ioremap(phys, size);
 }
+
 void __init __acpi_unmap_table(char *map, unsigned long size)
 {
 	if (!map || !size)
@@ -199,7 +193,7 @@ static void acpi_register_lapic(int id, u8 enabled)
 {
 	unsigned int ver = 0;
 
-	if (id >= (MAX_LOCAL_APIC-1)) {
+	if (id >= MAX_LOCAL_APIC) {
 		printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
 		return;
 	}
@@ -1626,6 +1620,10 @@ static int __init parse_acpi(char *arg)
 	/* "acpi=copy_dsdt" copys DSDT */
 	else if (strcmp(arg, "copy_dsdt") == 0) {
 		acpi_gbl_copy_dsdt_locally = 1;
+	}
+	/* "acpi=nocmcff" disables FF mode for corrected errors */
+	else if (strcmp(arg, "nocmcff") == 0) {
+		acpi_disable_cmcff = 1;
 	} else {
 		/* Core will printk when we return error. */
 		return -EINVAL;
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index c15cf9a..15e8563 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -11,6 +11,7 @@
 #include <linux/memory.h>
 #include <linux/stop_machine.h>
 #include <linux/slab.h>
+#include <linux/kdebug.h>
 #include <asm/alternative.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
@@ -596,97 +597,93 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
 	return addr;
 }
 
-/*
- * Cross-modifying kernel text with stop_machine().
- * This code originally comes from immediate value.
- */
-static atomic_t stop_machine_first;
-static int wrote_text;
+static void do_sync_core(void *info)
+{
+	sync_core();
+}
 
-struct text_poke_params {
-	struct text_poke_param *params;
-	int nparams;
-};
+static bool bp_patching_in_progress;
+static void *bp_int3_handler, *bp_int3_addr;
 
-static int __kprobes stop_machine_text_poke(void *data)
+int poke_int3_handler(struct pt_regs *regs)
 {
-	struct text_poke_params *tpp = data;
-	struct text_poke_param *p;
-	int i;
+	/* bp_patching_in_progress */
+	smp_rmb();
 
-	if (atomic_xchg(&stop_machine_first, 0)) {
-		for (i = 0; i < tpp->nparams; i++) {
-			p = &tpp->params[i];
-			text_poke(p->addr, p->opcode, p->len);
-		}
-		smp_wmb();	/* Make sure other cpus see that this has run */
-		wrote_text = 1;
-	} else {
-		while (!wrote_text)
-			cpu_relax();
-		smp_mb();	/* Load wrote_text before following execution */
-	}
+	if (likely(!bp_patching_in_progress))
+		return 0;
 
-	for (i = 0; i < tpp->nparams; i++) {
-		p = &tpp->params[i];
-		flush_icache_range((unsigned long)p->addr,
-				   (unsigned long)p->addr + p->len);
-	}
-	/*
-	 * Intel Archiecture Software Developer's Manual section 7.1.3 specifies
-	 * that a core serializing instruction such as "cpuid" should be
-	 * executed on _each_ core before the new instruction is made visible.
-	 */
-	sync_core();
-	return 0;
-}
+	if (user_mode_vm(regs) || regs->ip != (unsigned long)bp_int3_addr)
+		return 0;
+
+	/* set up the specified breakpoint handler */
+	regs->ip = (unsigned long) bp_int3_handler;
+
+	return 1;
 
-/**
- * text_poke_smp - Update instructions on a live kernel on SMP
- * @addr: address to modify
- * @opcode: source of the copy
- * @len: length to copy
- *
- * Modify multi-byte instruction by using stop_machine() on SMP. This allows
- * user to poke/set multi-byte text on SMP. Only non-NMI/MCE code modifying
- * should be allowed, since stop_machine() does _not_ protect code against
- * NMI and MCE.
- *
- * Note: Must be called under get_online_cpus() and text_mutex.
- */
-void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
-{
-	struct text_poke_params tpp;
-	struct text_poke_param p;
-
-	p.addr = addr;
-	p.opcode = opcode;
-	p.len = len;
-	tpp.params = &p;
-	tpp.nparams = 1;
-	atomic_set(&stop_machine_first, 1);
-	wrote_text = 0;
-	/* Use __stop_machine() because the caller already got online_cpus. */
-	__stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask);
-	return addr;
 }
 
 /**
- * text_poke_smp_batch - Update instructions on a live kernel on SMP
- * @params: an array of text_poke parameters
- * @n: the number of elements in params.
+ * text_poke_bp() -- update instructions on live kernel on SMP
+ * @addr:	address to patch
+ * @opcode:	opcode of new instruction
+ * @len:	length to copy
+ * @handler:	address to jump to when the temporary breakpoint is hit
  *
- * Modify multi-byte instruction by using stop_machine() on SMP. Since the
- * stop_machine() is heavy task, it is better to aggregate text_poke requests
- * and do it once if possible.
+ * Modify multi-byte instruction by using int3 breakpoint on SMP.
+ * We completely avoid stop_machine() here, and achieve the
+ * synchronization using int3 breakpoint.
  *
- * Note: Must be called under get_online_cpus() and text_mutex.
+ * The way it is done:
+ *	- add a int3 trap to the address that will be patched
+ *	- sync cores
+ *	- update all but the first byte of the patched range
+ *	- sync cores
+ *	- replace the first byte (int3) by the first byte of
+ *	  replacing opcode
+ *	- sync cores
+ *
+ * Note: must be called under text_mutex.
  */
-void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)
+void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler)
 {
-	struct text_poke_params tpp = {.params = params, .nparams = n};
+	unsigned char int3 = 0xcc;
+
+	bp_int3_handler = handler;
+	bp_int3_addr = (u8 *)addr + sizeof(int3);
+	bp_patching_in_progress = true;
+	/*
+	 * Corresponding read barrier in int3 notifier for
+	 * making sure the in_progress flags is correctly ordered wrt.
+	 * patching
+	 */
+	smp_wmb();
+
+	text_poke(addr, &int3, sizeof(int3));
 
-	atomic_set(&stop_machine_first, 1);
-	wrote_text = 0;
-	__stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask);
+	on_each_cpu(do_sync_core, NULL, 1);
+
+	if (len - sizeof(int3) > 0) {
+		/* patch all but the first byte */
+		text_poke((char *)addr + sizeof(int3),
+			  (const char *) opcode + sizeof(int3),
+			  len - sizeof(int3));
+		/*
+		 * According to Intel, this core syncing is very likely
+		 * not necessary and we'd be safe even without it. But
+		 * better safe than sorry (plus there's not only Intel).
+		 */
+		on_each_cpu(do_sync_core, NULL, 1);
+	}
+
+	/* patch the first byte */
+	text_poke(addr, opcode, sizeof(int3));
+
+	on_each_cpu(do_sync_core, NULL, 1);
+
+	bp_patching_in_progress = false;
+	smp_wmb();
+
+	return addr;
 }
+
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index eca89c5..d9dd5a6 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1622,11 +1622,8 @@ void __init enable_IR_x2apic(void)
 		goto skip_x2apic;
 
 	if (ret < 0) {
-		/* IR is required if there is APIC ID > 255 even when running
-		 * under KVM
-		 */
-		if (max_physical_apicid > 255 ||
-		    !hypervisor_x2apic_available()) {
+		/* IR is required if there is APIC ID > 255 */
+		if (max_physical_apicid > 255) {
 			if (x2apic_preenabled)
 				disable_x2apic();
 			goto skip_x2apic;
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index 5b7d4fa..09edd0b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -25,15 +25,18 @@ int mce_severity(struct mce *a, int tolerant, char **msg);
 struct dentry *mce_get_debugfs_dir(void);
 
 extern struct mce_bank *mce_banks;
+extern mce_banks_t mce_banks_ce_disabled;
 
 #ifdef CONFIG_X86_MCE_INTEL
 unsigned long mce_intel_adjust_timer(unsigned long interval);
 void mce_intel_cmci_poll(void);
 void mce_intel_hcpu_update(unsigned long cpu);
+void cmci_disable_bank(int bank);
 #else
 # define mce_intel_adjust_timer mce_adjust_timer_default
 static inline void mce_intel_cmci_poll(void) { }
 static inline void mce_intel_hcpu_update(unsigned long cpu) { }
+static inline void cmci_disable_bank(int bank) { }
 #endif
 
 void mce_timer_kick(unsigned long interval);
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 87a65c9..b3218cd 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -97,6 +97,15 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
 	[0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
 };
 
+/*
+ * MCA banks controlled through firmware first for corrected errors.
+ * This is a global list of banks for which we won't enable CMCI and we
+ * won't poll. Firmware controls these banks and is responsible for
+ * reporting corrected errors through GHES. Uncorrected/recoverable
+ * errors are still notified through a machine check.
+ */
+mce_banks_t mce_banks_ce_disabled;
+
 static DEFINE_PER_CPU(struct work_struct, mce_work);
 
 static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs);
@@ -1935,6 +1944,25 @@ static struct miscdevice mce_chrdev_device = {
 	&mce_chrdev_ops,
 };
 
+static void __mce_disable_bank(void *arg)
+{
+	int bank = *((int *)arg);
+	__clear_bit(bank, __get_cpu_var(mce_poll_banks));
+	cmci_disable_bank(bank);
+}
+
+void mce_disable_bank(int bank)
+{
+	if (bank >= mca_cfg.banks) {
+		pr_warn(FW_BUG
+			"Ignoring request to disable invalid MCA bank %d.\n",
+			bank);
+		return;
+	}
+	set_bit(bank, mce_banks_ce_disabled);
+	on_each_cpu(__mce_disable_bank, &bank, 1);
+}
+
 /*
  * mce=off Disables machine check
  * mce=no_cmci Disables CMCI
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index d5640530..4cfe045 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -203,6 +203,10 @@ static void cmci_discover(int banks)
 		if (test_bit(i, owned))
 			continue;
 
+		/* Skip banks in firmware first mode */
+		if (test_bit(i, mce_banks_ce_disabled))
+			continue;
+
 		rdmsrl(MSR_IA32_MCx_CTL2(i), val);
 
 		/* Already owned by someone else? */
@@ -271,6 +275,19 @@ void cmci_recheck(void)
 	local_irq_restore(flags);
 }
 
+/* Caller must hold the lock on cmci_discover_lock */
+static void __cmci_disable_bank(int bank)
+{
+	u64 val;
+
+	if (!test_bit(bank, __get_cpu_var(mce_banks_owned)))
+		return;
+	rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
+	val &= ~MCI_CTL2_CMCI_EN;
+	wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
+	__clear_bit(bank, __get_cpu_var(mce_banks_owned));
+}
+
 /*
  * Disable CMCI on this CPU for all banks it owns when it goes down.
  * This allows other CPUs to claim the banks on rediscovery.
@@ -280,20 +297,12 @@ void cmci_clear(void)
 	unsigned long flags;
 	int i;
 	int banks;
-	u64 val;
 
 	if (!cmci_supported(&banks))
 		return;
 	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
-	for (i = 0; i < banks; i++) {
-		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
-			continue;
-		/* Disable CMCI */
-		rdmsrl(MSR_IA32_MCx_CTL2(i), val);
-		val &= ~MCI_CTL2_CMCI_EN;
-		wrmsrl(MSR_IA32_MCx_CTL2(i), val);
-		__clear_bit(i, __get_cpu_var(mce_banks_owned));
-	}
+	for (i = 0; i < banks; i++)
+		__cmci_disable_bank(i);
 	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
@@ -327,6 +336,19 @@ void cmci_reenable(void)
 		cmci_discover(banks);
 }
 
+void cmci_disable_bank(int bank)
+{
+	int banks;
+	unsigned long flags;
+
+	if (!cmci_supported(&banks))
+		return;
+
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
+	__cmci_disable_bank(bank);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
+}
+
 static void intel_init_cmci(void)
 {
 	int banks;
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index d4cdfa6..ce2d0a2 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -683,6 +683,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
 	}
 
 	/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
+	count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
 	__flush_tlb();
 
 	/* Save MTRR state */
@@ -696,6 +697,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
 static void post_set(void) __releases(set_atomicity_lock)
 {
 	/* Flush TLBs (no need to flush caches - they are disabled) */
+	count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
 	__flush_tlb();
 
 	/* Intel (P6) standard MTRRs */
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index a7c7305..8355c84 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1884,6 +1884,7 @@ static struct pmu pmu = {
 void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
 {
 	userpg->cap_usr_time = 0;
+	userpg->cap_usr_time_zero = 0;
 	userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc;
 	userpg->pmc_width = x86_pmu.cntval_bits;
 
@@ -1897,6 +1898,11 @@ void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
 	userpg->time_mult = this_cpu_read(cyc2ns);
 	userpg->time_shift = CYC2NS_SCALE_FACTOR;
 	userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;
+
+	if (sched_clock_stable && !check_tsc_disabled()) {
+		userpg->cap_usr_time_zero = 1;
+		userpg->time_zero = this_cpu_read(cyc2ns_offset);
+	}
 }
 
 /*
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 69eb2fa..376dc78 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -52,8 +52,7 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (unsigned long)__va(start);
 	initrd_end = (unsigned long)__va(end);
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index d32abea..0d5bb68 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -47,6 +47,7 @@ unsigned long pci_mem_start = 0xaeedbabe;
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(pci_mem_start);
 #endif
+static u64 mem_limit = ~0ULL;
 
 /*
  * This function checks if any part of the range <start,end> is mapped
@@ -108,7 +109,7 @@ int __init e820_all_mapped(u64 start, u64 end, unsigned type)
  * Add a memory region to the kernel e820 map.
  */
 static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
-					 int type)
+					 int type, bool limited)
 {
 	int x = e820x->nr_map;
 
@@ -119,6 +120,22 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
 		return;
 	}
 
+	if (limited) {
+		if (start >= mem_limit) {
+			printk(KERN_ERR "e820: ignoring [mem %#010llx-%#010llx]\n",
+			       (unsigned long long)start,
+			       (unsigned long long)(start + size - 1));
+			return;
+		}
+
+		if (mem_limit - start < size) {
+			printk(KERN_ERR "e820: ignoring [mem %#010llx-%#010llx]\n",
+			       (unsigned long long)mem_limit,
+			       (unsigned long long)(start + size - 1));
+			size = mem_limit - start;
+		}
+	}
+
 	e820x->map[x].addr = start;
 	e820x->map[x].size = size;
 	e820x->map[x].type = type;
@@ -127,7 +144,37 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
 
 void __init e820_add_region(u64 start, u64 size, int type)
 {
-	__e820_add_region(&e820, start, size, type);
+	__e820_add_region(&e820, start, size, type, false);
+}
+
+/*
+ * do_add_efi_memmap() calls this function().
+ *
+ * Note: BOOT_SERVICES_{CODE,DATA} regions on some efi machines are marked
+ * as E820_RAM, and they are needed to be mapped. Please use e820_add_region()
+ * to add BOOT_SERVICES_{CODE,DATA} regions.
+ */
+void __init e820_add_limit_region(u64 start, u64 size, int type)
+{
+	/*
+	 * efi_init() is called after finish_e820_parsing(), so we should
+	 * check whether [start, start + size) contains address above
+	 * mem_limit if the type is E820_RAM.
+	 */
+	__e820_add_region(&e820, start, size, type, type == E820_RAM);
+}
+
+void __init e820_adjust_region(u64 *start, u64 *size)
+{
+	if (*start >= mem_limit) {
+		*size = 0;
+		return;
+	}
+
+	if (mem_limit - *start < *size)
+		*size = mem_limit - *start;
+
+	return;
 }
 
 static void __init e820_print_type(u32 type)
@@ -455,8 +502,9 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 
 		/* new range is totally covered? */
 		if (ei->addr < start && ei_end > end) {
-			__e820_add_region(e820x, start, size, new_type);
-			__e820_add_region(e820x, end, ei_end - end, ei->type);
+			__e820_add_region(e820x, start, size, new_type, false);
+			__e820_add_region(e820x, end, ei_end - end, ei->type,
+					  false);
 			ei->size = start - ei->addr;
 			real_updated_size += size;
 			continue;
@@ -469,7 +517,7 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 			continue;
 
 		__e820_add_region(e820x, final_start, final_end - final_start,
-				  new_type);
+				  new_type, false);
 
 		real_updated_size += final_end - final_start;
 
@@ -809,7 +857,7 @@ static int userdef __initdata;
 /* "mem=nopentium" disables the 4MB page tables. */
 static int __init parse_memopt(char *p)
 {
-	u64 mem_size;
+	char *oldp;
 
 	if (!p)
 		return -EINVAL;
@@ -825,11 +873,11 @@ static int __init parse_memopt(char *p)
 	}
 
 	userdef = 1;
-	mem_size = memparse(p, &p);
+	oldp = p;
+	mem_limit = memparse(p, &p);
 	/* don't remove all of memory when handling "mem={invalid}" param */
-	if (mem_size == 0)
+	if (mem_limit == 0 || p == oldp)
 		return -EINVAL;
-	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
 }
@@ -895,6 +943,12 @@ early_param("memmap", parse_memmap_opt);
 
 void __init finish_e820_parsing(void)
 {
+	if (mem_limit != ~0ULL) {
+		userdef = 1;
+		e820_remove_range(mem_limit, ULLONG_MAX - mem_limit,
+				  E820_RAM, 1);
+	}
+
 	if (userdef) {
 		u32 nr = e820.nr_map;
 
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 94ab6b9..63bdb29 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -196,15 +196,23 @@ static void __init ati_bugs_contd(int num, int slot, int func)
 static void __init intel_remapping_check(int num, int slot, int func)
 {
 	u8 revision;
+	u16 device;
 
+	device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID);
 	revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID);
 
 	/*
-	 * Revision 0x13 of this chipset supports irq remapping
-	 * but has an erratum that breaks its behavior, flag it as such
+ 	 * Revision 13 of all triggering devices id in this quirk have
+	 * a problem draining interrupts when irq remapping is enabled,
+	 * and should be flagged as broken.  Additionally revisions 0x12
+	 * and 0x22 of device id 0x3405 has this problem.
 	 */
 	if (revision == 0x13)
 		set_irq_remapping_broken();
+	else if ((device == 0x3405) &&
+	    ((revision == 0x12) ||
+	     (revision == 0x22)))
+		set_irq_remapping_broken();
 
 }
 
@@ -239,6 +247,8 @@ static struct chipset early_qrk[] __initdata = {
 	  PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd },
 	{ PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST,
 	  PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
+	{ PCI_VENDOR_ID_INTEL, 0x3405, PCI_CLASS_BRIDGE_HOST,
+	  PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
 	{ PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST,
 	  PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
 	{}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 5dd87a8..81ba276 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -409,6 +409,7 @@ enable_paging:
 /*
  * Check if it is 486
  */
+	movb $4,X86			# at least 486
 	cmpl $-1,X86_CPUID
 	je is486
 
@@ -436,7 +437,6 @@ enable_paging:
 	movl %edx,X86_CAPABILITY
 
 is486:
-	movb $4,X86
 	movl $0x50022,%ecx	# set AM, WP, NE and MP
 	movl %cr0,%eax
 	andl $0x80000011,%eax	# Save PG,PE,ET
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 202d24f..5d576ab 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -116,7 +116,7 @@ static void mxcsr_feature_mask_init(void)
 
 	if (cpu_has_fxsr) {
 		memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct));
-		asm volatile("fxsave %0" : : "m" (fx_scratch));
+		asm volatile("fxsave %0" : "+m" (fx_scratch));
 		mask = fx_scratch.mxcsr_mask;
 		if (mask == 0)
 			mask = 0x0000ffbf;
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
index 2889b3d..460f5d9 100644
--- a/arch/x86/kernel/jump_label.c
+++ b/arch/x86/kernel/jump_label.c
@@ -37,7 +37,19 @@ static void __jump_label_transform(struct jump_entry *entry,
 	} else
 		memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
 
-	(*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+	/*
+	 * Make text_poke_bp() a default fallback poker.
+	 *
+	 * At the time the change is being done, just ignore whether we
+	 * are doing nop -> jump or jump -> nop transition, and assume
+	 * always nop being the 'currently valid' instruction
+	 *
+	 */
+	if (poker)
+		(*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+	else
+		text_poke_bp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE,
+			     (void *)entry->code + JUMP_LABEL_NOP_SIZE);
 }
 
 void arch_jump_label_transform(struct jump_entry *entry,
@@ -45,7 +57,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
 {
 	get_online_cpus();
 	mutex_lock(&text_mutex);
-	__jump_label_transform(entry, type, text_poke_smp);
+	__jump_label_transform(entry, type, NULL);
 	mutex_unlock(&text_mutex);
 	put_online_cpus();
 }
diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h
index 2e9d4b5..c6ee63f 100644
--- a/arch/x86/kernel/kprobes/common.h
+++ b/arch/x86/kernel/kprobes/common.h
@@ -82,14 +82,9 @@ extern void synthesize_reljump(void *from, void *to);
 extern void synthesize_relcall(void *from, void *to);
 
 #ifdef	CONFIG_OPTPROBES
-extern int arch_init_optprobes(void);
 extern int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter);
 extern unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr);
 #else	/* !CONFIG_OPTPROBES */
-static inline int arch_init_optprobes(void)
-{
-	return 0;
-}
 static inline int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
 {
 	return 0;
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 211bce4..cd49b2c 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -1068,7 +1068,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 int __init arch_init_kprobes(void)
 {
-	return arch_init_optprobes();
+	return 0;
 }
 
 int __kprobes arch_trampoline_kprobe(struct kprobe *p)
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index 76dc6f0..d71e994 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -371,31 +371,6 @@ int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op)
 	return 0;
 }
 
-#define MAX_OPTIMIZE_PROBES 256
-static struct text_poke_param *jump_poke_params;
-static struct jump_poke_buffer {
-	u8 buf[RELATIVEJUMP_SIZE];
-} *jump_poke_bufs;
-
-static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm,
-					    u8 *insn_buf,
-					    struct optimized_kprobe *op)
-{
-	s32 rel = (s32)((long)op->optinsn.insn -
-			((long)op->kp.addr + RELATIVEJUMP_SIZE));
-
-	/* Backup instructions which will be replaced by jump address */
-	memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
-	       RELATIVE_ADDR_SIZE);
-
-	insn_buf[0] = RELATIVEJUMP_OPCODE;
-	*(s32 *)(&insn_buf[1]) = rel;
-
-	tprm->addr = op->kp.addr;
-	tprm->opcode = insn_buf;
-	tprm->len = RELATIVEJUMP_SIZE;
-}
-
 /*
  * Replace breakpoints (int3) with relative jumps.
  * Caller must call with locking kprobe_mutex and text_mutex.
@@ -403,37 +378,38 @@ static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm,
 void __kprobes arch_optimize_kprobes(struct list_head *oplist)
 {
 	struct optimized_kprobe *op, *tmp;
-	int c = 0;
+	u8 insn_buf[RELATIVEJUMP_SIZE];
 
 	list_for_each_entry_safe(op, tmp, oplist, list) {
+		s32 rel = (s32)((long)op->optinsn.insn -
+			((long)op->kp.addr + RELATIVEJUMP_SIZE));
+
 		WARN_ON(kprobe_disabled(&op->kp));
-		/* Setup param */
-		setup_optimize_kprobe(&jump_poke_params[c],
-				      jump_poke_bufs[c].buf, op);
+
+		/* Backup instructions which will be replaced by jump address */
+		memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
+		       RELATIVE_ADDR_SIZE);
+
+		insn_buf[0] = RELATIVEJUMP_OPCODE;
+		*(s32 *)(&insn_buf[1]) = rel;
+
+		text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE,
+			     op->optinsn.insn);
+
 		list_del_init(&op->list);
-		if (++c >= MAX_OPTIMIZE_PROBES)
-			break;
 	}
-
-	/*
-	 * text_poke_smp doesn't support NMI/MCE code modifying.
-	 * However, since kprobes itself also doesn't support NMI/MCE
-	 * code probing, it's not a problem.
-	 */
-	text_poke_smp_batch(jump_poke_params, c);
 }
 
-static void __kprobes setup_unoptimize_kprobe(struct text_poke_param *tprm,
-					      u8 *insn_buf,
-					      struct optimized_kprobe *op)
+/* Replace a relative jump with a breakpoint (int3).  */
+void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op)
 {
+	u8 insn_buf[RELATIVEJUMP_SIZE];
+
 	/* Set int3 to first byte for kprobes */
 	insn_buf[0] = BREAKPOINT_INSTRUCTION;
 	memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
-
-	tprm->addr = op->kp.addr;
-	tprm->opcode = insn_buf;
-	tprm->len = RELATIVEJUMP_SIZE;
+	text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE,
+		     op->optinsn.insn);
 }
 
 /*
@@ -444,34 +420,11 @@ extern void arch_unoptimize_kprobes(struct list_head *oplist,
 				    struct list_head *done_list)
 {
 	struct optimized_kprobe *op, *tmp;
-	int c = 0;
 
 	list_for_each_entry_safe(op, tmp, oplist, list) {
-		/* Setup param */
-		setup_unoptimize_kprobe(&jump_poke_params[c],
-					jump_poke_bufs[c].buf, op);
+		arch_unoptimize_kprobe(op);
 		list_move(&op->list, done_list);
-		if (++c >= MAX_OPTIMIZE_PROBES)
-			break;
 	}
-
-	/*
-	 * text_poke_smp doesn't support NMI/MCE code modifying.
-	 * However, since kprobes itself also doesn't support NMI/MCE
-	 * code probing, it's not a problem.
-	 */
-	text_poke_smp_batch(jump_poke_params, c);
-}
-
-/* Replace a relative jump with a breakpoint (int3).  */
-void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op)
-{
-	u8 buf[RELATIVEJUMP_SIZE];
-
-	/* Set int3 to first byte for kprobes */
-	buf[0] = BREAKPOINT_INSTRUCTION;
-	memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
-	text_poke_smp(op->kp.addr, buf, RELATIVEJUMP_SIZE);
 }
 
 int  __kprobes
@@ -491,22 +444,3 @@ setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
 	}
 	return 0;
 }
-
-int __kprobes arch_init_optprobes(void)
-{
-	/* Allocate code buffer and parameter array */
-	jump_poke_bufs = kmalloc(sizeof(struct jump_poke_buffer) *
-				 MAX_OPTIMIZE_PROBES, GFP_KERNEL);
-	if (!jump_poke_bufs)
-		return -ENOMEM;
-
-	jump_poke_params = kmalloc(sizeof(struct text_poke_param) *
-				   MAX_OPTIMIZE_PROBES, GFP_KERNEL);
-	if (!jump_poke_params) {
-		kfree(jump_poke_bufs);
-		jump_poke_bufs = NULL;
-		return -ENOMEM;
-	}
-
-	return 0;
-}
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 47ebb1d..7a0adb7 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -220,12 +220,13 @@ int apply_microcode_amd(int cpu)
 		return 0;
 	}
 
-	if (__apply_microcode_amd(mc_amd))
+	if (__apply_microcode_amd(mc_amd)) {
 		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 			cpu, mc_amd->hdr.patch_id);
-	else
-		pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
-			mc_amd->hdr.patch_id);
+		return -1;
+	}
+	pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
+		mc_amd->hdr.patch_id);
 
 	uci->cpu_sig.rev = mc_amd->hdr.patch_id;
 	c->microcode = mc_amd->hdr.patch_id;
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c
index 2cb9470..a16bae3 100644
--- a/arch/x86/kernel/pvclock.c
+++ b/arch/x86/kernel/pvclock.c
@@ -128,46 +128,7 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
 	set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
 }
 
-static struct pvclock_vsyscall_time_info *pvclock_vdso_info;
-
-static struct pvclock_vsyscall_time_info *
-pvclock_get_vsyscall_user_time_info(int cpu)
-{
-	if (!pvclock_vdso_info) {
-		BUG();
-		return NULL;
-	}
-
-	return &pvclock_vdso_info[cpu];
-}
-
-struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu)
-{
-	return &pvclock_get_vsyscall_user_time_info(cpu)->pvti;
-}
-
 #ifdef CONFIG_X86_64
-static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l,
-			        void *v)
-{
-	struct task_migration_notifier *mn = v;
-	struct pvclock_vsyscall_time_info *pvti;
-
-	pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu);
-
-	/* this is NULL when pvclock vsyscall is not initialized */
-	if (unlikely(pvti == NULL))
-		return NOTIFY_DONE;
-
-	pvti->migrate_count++;
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block pvclock_migrate = {
-	.notifier_call = pvclock_task_migrate,
-};
-
 /*
  * Initialize the generic pvclock vsyscall state.  This will allocate
  * a/some page(s) for the per-vcpu pvclock information, set up a
@@ -181,17 +142,12 @@ int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
 
 	WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE);
 
-	pvclock_vdso_info = i;
-
 	for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) {
 		__set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx,
 			     __pa(i) + (idx*PAGE_SIZE),
 			     PAGE_KERNEL_VVAR);
 	}
 
-
-	register_task_migration_notifier(&pvclock_migrate);
-
 	return 0;
 }
 #endif
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index dbded5a..48f8375 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
 				*begin = new_begin;
 		}
 	} else {
-		*begin = TASK_UNMAPPED_BASE;
+		*begin = mmap_legacy_base();
 		*end = TASK_SIZE;
 	}
 }
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index addf7b5..91a4496 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -301,6 +301,15 @@ static int tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
 	return 0;
 }
 
+static int tboot_extended_sleep(u8 sleep_state, u32 val_a, u32 val_b)
+{
+	if (!tboot_enabled())
+		return 0;
+
+	pr_warning("tboot is not able to suspend on platforms with reduced hardware sleep (ACPIv5)");
+	return -ENODEV;
+}
+
 static atomic_t ap_wfs_count;
 
 static int tboot_wait_for_aps(int num_aps)
@@ -422,6 +431,7 @@ static __init int tboot_late_init(void)
 #endif
 
 	acpi_os_set_prepare_sleep(&tboot_sleep);
+	acpi_os_set_prepare_extended_sleep(&tboot_extended_sleep);
 	return 0;
 }
 
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 1b23a1c..8c8093b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -58,6 +58,7 @@
 #include <asm/mce.h>
 #include <asm/fixmap.h>
 #include <asm/mach_traps.h>
+#include <asm/alternative.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/x86_init.h>
@@ -327,6 +328,9 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co
 	    ftrace_int3_handler(regs))
 		return;
 #endif
+	if (poke_int3_handler(regs))
+		return;
+
 	prev_state = exception_enter();
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
 	if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 6ff4924..930e5d4 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -89,6 +89,12 @@ int check_tsc_unstable(void)
 }
 EXPORT_SYMBOL_GPL(check_tsc_unstable);
 
+int check_tsc_disabled(void)
+{
+	return tsc_disabled;
+}
+EXPORT_SYMBOL_GPL(check_tsc_disabled);
+
 #ifdef CONFIG_X86_TSC
 int __init notsc_setup(char *str)
 {
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 5f24c71..4c374a9 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -116,6 +116,27 @@ struct x86_msi_ops x86_msi = {
 	.setup_hpet_msi		= default_setup_hpet_msi,
 };
 
+/* MSI arch specific hooks */
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	return x86_msi.setup_msi_irqs(dev, nvec, type);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	x86_msi.teardown_msi_irqs(dev);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	x86_msi.teardown_msi_irq(irq);
+}
+
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+	x86_msi.restore_msi_irqs(dev, irq);
+}
+
 struct x86_io_apic_ops x86_io_apic_ops = {
 	.init			= native_io_apic_init_mappings,
 	.read			= native_io_apic_read,
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index afc1124..c98f054 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -79,16 +79,6 @@ static inline void apic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val)
 	*((u32 *) (apic->regs + reg_off)) = val;
 }
 
-static inline int apic_test_and_set_vector(int vec, void *bitmap)
-{
-	return test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
-}
-
-static inline int apic_test_and_clear_vector(int vec, void *bitmap)
-{
-	return test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
-}
-
 static inline int apic_test_vector(int vec, void *bitmap)
 {
 	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
@@ -331,10 +321,10 @@ void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir)
 }
 EXPORT_SYMBOL_GPL(kvm_apic_update_irr);
 
-static inline int apic_test_and_set_irr(int vec, struct kvm_lapic *apic)
+static inline void apic_set_irr(int vec, struct kvm_lapic *apic)
 {
 	apic->irr_pending = true;
-	return apic_test_and_set_vector(vec, apic->regs + APIC_IRR);
+	apic_set_vector(vec, apic->regs + APIC_IRR);
 }
 
 static inline int apic_search_irr(struct kvm_lapic *apic)
@@ -681,28 +671,21 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 		if (unlikely(!apic_enabled(apic)))
 			break;
 
+		result = 1;
+
 		if (dest_map)
 			__set_bit(vcpu->vcpu_id, dest_map);
 
-		if (kvm_x86_ops->deliver_posted_interrupt) {
-			result = 1;
+		if (kvm_x86_ops->deliver_posted_interrupt)
 			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
-		} else {
-			result = !apic_test_and_set_irr(vector, apic);
-
-			if (!result) {
-				if (trig_mode)
-					apic_debug("level trig mode repeatedly "
-						"for vector %d", vector);
-				goto out;
-			}
+		else {
+			apic_set_irr(vector, apic);
 
 			kvm_make_request(KVM_REQ_EVENT, vcpu);
 			kvm_vcpu_kick(vcpu);
 		}
-out:
 		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
-				trig_mode, vector, !result);
+					  trig_mode, vector, false);
 		break;
 
 	case APIC_DM_REMRD:
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 9e9285a..196e0ea 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -4182,7 +4182,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
 	switch (er) {
 	case EMULATE_DONE:
 		return 1;
-	case EMULATE_DO_MMIO:
+	case EMULATE_USER_EXIT:
 		++vcpu->stat.mmio_exits;
 		/* fall through */
 	case EMULATE_FAIL:
@@ -4390,23 +4390,19 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm)
 	/*
 	 * The very rare case: if the generation-number is round,
 	 * zap all shadow pages.
-	 *
-	 * The max value is MMIO_MAX_GEN - 1 since it is not called
-	 * when mark memslot invalid.
 	 */
-	if (unlikely(kvm_current_mmio_generation(kvm) >= (MMIO_MAX_GEN - 1))) {
+	if (unlikely(kvm_current_mmio_generation(kvm) >= MMIO_MAX_GEN)) {
 		printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n");
 		kvm_mmu_invalidate_zap_all_pages(kvm);
 	}
 }
 
-static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long
+mmu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	struct kvm *kvm;
 	int nr_to_scan = sc->nr_to_scan;
-
-	if (nr_to_scan == 0)
-		goto out;
+	unsigned long freed = 0;
 
 	raw_spin_lock(&kvm_lock);
 
@@ -4441,25 +4437,37 @@ static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
 			goto unlock;
 		}
 
-		prepare_zap_oldest_mmu_page(kvm, &invalid_list);
+		if (prepare_zap_oldest_mmu_page(kvm, &invalid_list))
+			freed++;
 		kvm_mmu_commit_zap_page(kvm, &invalid_list);
 
 unlock:
 		spin_unlock(&kvm->mmu_lock);
 		srcu_read_unlock(&kvm->srcu, idx);
 
+		/*
+		 * unfair on small ones
+		 * per-vm shrinkers cry out
+		 * sadness comes quickly
+		 */
 		list_move_tail(&kvm->vm_list, &vm_list);
 		break;
 	}
 
 	raw_spin_unlock(&kvm_lock);
+	return freed;
 
-out:
+}
+
+static unsigned long
+mmu_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
 	return percpu_counter_read_positive(&kvm_total_used_mmu_pages);
 }
 
 static struct shrinker mmu_shrinker = {
-	.shrink = mmu_shrink,
+	.count_objects = mmu_shrink_count,
+	.scan_objects = mmu_shrink_scan,
 	.seeks = DEFAULT_SEEKS * 10,
 };
 
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index c53e797..5c4f631 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -160,7 +160,7 @@ static void stop_counter(struct kvm_pmc *pmc)
 
 static void reprogram_counter(struct kvm_pmc *pmc, u32 type,
 		unsigned config, bool exclude_user, bool exclude_kernel,
-		bool intr)
+		bool intr, bool in_tx, bool in_tx_cp)
 {
 	struct perf_event *event;
 	struct perf_event_attr attr = {
@@ -173,6 +173,10 @@ static void reprogram_counter(struct kvm_pmc *pmc, u32 type,
 		.exclude_kernel = exclude_kernel,
 		.config = config,
 	};
+	if (in_tx)
+		attr.config |= HSW_IN_TX;
+	if (in_tx_cp)
+		attr.config |= HSW_IN_TX_CHECKPOINTED;
 
 	attr.sample_period = (-pmc->counter) & pmc_bitmask(pmc);
 
@@ -226,7 +230,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
 
 	if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
 				ARCH_PERFMON_EVENTSEL_INV |
-				ARCH_PERFMON_EVENTSEL_CMASK))) {
+				ARCH_PERFMON_EVENTSEL_CMASK |
+				HSW_IN_TX |
+				HSW_IN_TX_CHECKPOINTED))) {
 		config = find_arch_event(&pmc->vcpu->arch.pmu, event_select,
 				unit_mask);
 		if (config != PERF_COUNT_HW_MAX)
@@ -239,7 +245,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
 	reprogram_counter(pmc, type, config,
 			!(eventsel & ARCH_PERFMON_EVENTSEL_USR),
 			!(eventsel & ARCH_PERFMON_EVENTSEL_OS),
-			eventsel & ARCH_PERFMON_EVENTSEL_INT);
+			eventsel & ARCH_PERFMON_EVENTSEL_INT,
+			(eventsel & HSW_IN_TX),
+			(eventsel & HSW_IN_TX_CHECKPOINTED));
 }
 
 static void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 en_pmi, int idx)
@@ -256,7 +264,7 @@ static void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 en_pmi, int idx)
 			arch_events[fixed_pmc_events[idx]].event_type,
 			!(en & 0x2), /* exclude user */
 			!(en & 0x1), /* exclude kernel */
-			pmi);
+			pmi, false, false);
 }
 
 static inline u8 fixed_en_pmi(u64 ctrl, int idx)
@@ -408,7 +416,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		} else if ((pmc = get_gp_pmc(pmu, index, MSR_P6_EVNTSEL0))) {
 			if (data == pmc->eventsel)
 				return 0;
-			if (!(data & 0xffffffff00200000ull)) {
+			if (!(data & pmu->reserved_bits)) {
 				reprogram_gp_counter(pmc, data);
 				return 0;
 			}
@@ -450,6 +458,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
 	pmu->counter_bitmask[KVM_PMC_GP] = 0;
 	pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
 	pmu->version = 0;
+	pmu->reserved_bits = 0xffffffff00200000ull;
 
 	entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
 	if (!entry)
@@ -478,6 +487,12 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
 	pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
 		(((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
 	pmu->global_ctrl_mask = ~pmu->global_ctrl;
+
+	entry = kvm_find_cpuid_entry(vcpu, 7, 0);
+	if (entry &&
+	    (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
+	    (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM)))
+		pmu->reserved_bits ^= HSW_IN_TX|HSW_IN_TX_CHECKPOINTED;
 }
 
 void kvm_pmu_init(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 064d0be..45fd70c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -373,6 +373,7 @@ struct nested_vmx {
 	 * we must keep them pinned while L2 runs.
 	 */
 	struct page *apic_access_page;
+	u64 msr_ia32_feature_control;
 };
 
 #define POSTED_INTR_ON  0
@@ -2282,8 +2283,11 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 
 	switch (msr_index) {
 	case MSR_IA32_FEATURE_CONTROL:
-		*pdata = 0;
-		break;
+		if (nested_vmx_allowed(vcpu)) {
+			*pdata = to_vmx(vcpu)->nested.msr_ia32_feature_control;
+			break;
+		}
+		return 0;
 	case MSR_IA32_VMX_BASIC:
 		/*
 		 * This MSR reports some information about VMX support. We
@@ -2356,14 +2360,24 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 	return 1;
 }
 
-static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
+	u32 msr_index = msr_info->index;
+	u64 data = msr_info->data;
+	bool host_initialized = msr_info->host_initiated;
+
 	if (!nested_vmx_allowed(vcpu))
 		return 0;
 
-	if (msr_index == MSR_IA32_FEATURE_CONTROL)
-		/* TODO: the right thing. */
+	if (msr_index == MSR_IA32_FEATURE_CONTROL) {
+		if (!host_initialized &&
+				to_vmx(vcpu)->nested.msr_ia32_feature_control
+				& FEATURE_CONTROL_LOCKED)
+			return 0;
+		to_vmx(vcpu)->nested.msr_ia32_feature_control = data;
 		return 1;
+	}
+
 	/*
 	 * No need to treat VMX capability MSRs specially: If we don't handle
 	 * them, handle_wrmsr will #GP(0), which is correct (they are readonly)
@@ -2494,7 +2508,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 			return 1;
 		/* Otherwise falls through */
 	default:
-		if (vmx_set_vmx_msr(vcpu, msr_index, data))
+		if (vmx_set_vmx_msr(vcpu, msr_info))
 			break;
 		msr = find_msr_entry(vmx, msr_index);
 		if (msr) {
@@ -5438,7 +5452,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 
 		err = emulate_instruction(vcpu, EMULTYPE_NO_REEXECUTE);
 
-		if (err == EMULATE_DO_MMIO) {
+		if (err == EMULATE_USER_EXIT) {
 			ret = 0;
 			goto out;
 		}
@@ -5567,8 +5581,47 @@ static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
 		free_loaded_vmcs(&vmx->vmcs01);
 }
 
+/*
+ * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
+ * set the success or error code of an emulated VMX instruction, as specified
+ * by Vol 2B, VMX Instruction Reference, "Conventions".
+ */
+static void nested_vmx_succeed(struct kvm_vcpu *vcpu)
+{
+	vmx_set_rflags(vcpu, vmx_get_rflags(vcpu)
+			& ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+			    X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF));
+}
+
+static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu)
+{
+	vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+			& ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
+			    X86_EFLAGS_SF | X86_EFLAGS_OF))
+			| X86_EFLAGS_CF);
+}
+
 static void nested_vmx_failValid(struct kvm_vcpu *vcpu,
-				 u32 vm_instruction_error);
+					u32 vm_instruction_error)
+{
+	if (to_vmx(vcpu)->nested.current_vmptr == -1ull) {
+		/*
+		 * failValid writes the error number to the current VMCS, which
+		 * can't be done there isn't a current VMCS.
+		 */
+		nested_vmx_failInvalid(vcpu);
+		return;
+	}
+	vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+			& ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+			    X86_EFLAGS_SF | X86_EFLAGS_OF))
+			| X86_EFLAGS_ZF);
+	get_vmcs12(vcpu)->vm_instruction_error = vm_instruction_error;
+	/*
+	 * We don't need to force a shadow sync because
+	 * VM_INSTRUCTION_ERROR is not shadowed
+	 */
+}
 
 /*
  * Emulate the VMXON instruction.
@@ -5583,6 +5636,8 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
 	struct kvm_segment cs;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	struct vmcs *shadow_vmcs;
+	const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
+		| FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
 
 	/* The Intel VMX Instruction Reference lists a bunch of bits that
 	 * are prerequisite to running VMXON, most notably cr4.VMXE must be
@@ -5611,6 +5666,13 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
 		skip_emulated_instruction(vcpu);
 		return 1;
 	}
+
+	if ((vmx->nested.msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
+			!= VMXON_NEEDED_FEATURES) {
+		kvm_inject_gp(vcpu, 0);
+		return 1;
+	}
+
 	if (enable_shadow_vmcs) {
 		shadow_vmcs = alloc_vmcs();
 		if (!shadow_vmcs)
@@ -5628,6 +5690,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
 	vmx->nested.vmxon = true;
 
 	skip_emulated_instruction(vcpu);
+	nested_vmx_succeed(vcpu);
 	return 1;
 }
 
@@ -5712,6 +5775,7 @@ static int handle_vmoff(struct kvm_vcpu *vcpu)
 		return 1;
 	free_nested(to_vmx(vcpu));
 	skip_emulated_instruction(vcpu);
+	nested_vmx_succeed(vcpu);
 	return 1;
 }
 
@@ -5768,48 +5832,6 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
-/*
- * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
- * set the success or error code of an emulated VMX instruction, as specified
- * by Vol 2B, VMX Instruction Reference, "Conventions".
- */
-static void nested_vmx_succeed(struct kvm_vcpu *vcpu)
-{
-	vmx_set_rflags(vcpu, vmx_get_rflags(vcpu)
-			& ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
-			    X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF));
-}
-
-static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu)
-{
-	vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
-			& ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
-			    X86_EFLAGS_SF | X86_EFLAGS_OF))
-			| X86_EFLAGS_CF);
-}
-
-static void nested_vmx_failValid(struct kvm_vcpu *vcpu,
-					u32 vm_instruction_error)
-{
-	if (to_vmx(vcpu)->nested.current_vmptr == -1ull) {
-		/*
-		 * failValid writes the error number to the current VMCS, which
-		 * can't be done there isn't a current VMCS.
-		 */
-		nested_vmx_failInvalid(vcpu);
-		return;
-	}
-	vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
-			& ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
-			    X86_EFLAGS_SF | X86_EFLAGS_OF))
-			| X86_EFLAGS_ZF);
-	get_vmcs12(vcpu)->vm_instruction_error = vm_instruction_error;
-	/*
-	 * We don't need to force a shadow sync because
-	 * VM_INSTRUCTION_ERROR is not shadowed
-	 */
-}
-
 /* Emulate the VMCLEAR instruction */
 static int handle_vmclear(struct kvm_vcpu *vcpu)
 {
@@ -5972,8 +5994,8 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
 	unsigned long field;
 	u64 field_value;
 	struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs;
-	unsigned long *fields = (unsigned long *)shadow_read_write_fields;
-	int num_fields = max_shadow_read_write_fields;
+	const unsigned long *fields = shadow_read_write_fields;
+	const int num_fields = max_shadow_read_write_fields;
 
 	vmcs_load(shadow_vmcs);
 
@@ -6002,12 +6024,11 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
 
 static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
 {
-	unsigned long *fields[] = {
-		(unsigned long *)shadow_read_write_fields,
-		(unsigned long *)shadow_read_only_fields
+	const unsigned long *fields[] = {
+		shadow_read_write_fields,
+		shadow_read_only_fields
 	};
-	int num_lists =  ARRAY_SIZE(fields);
-	int max_fields[] = {
+	const int max_fields[] = {
 		max_shadow_read_write_fields,
 		max_shadow_read_only_fields
 	};
@@ -6018,7 +6039,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
 
 	vmcs_load(shadow_vmcs);
 
-	for (q = 0; q < num_lists; q++) {
+	for (q = 0; q < ARRAY_SIZE(fields); q++) {
 		for (i = 0; i < max_fields[q]; i++) {
 			field = fields[q][i];
 			vmcs12_read_any(&vmx->vcpu, field, &field_value);
@@ -7948,6 +7969,8 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
 				   struct vmcs12 *vmcs12)
 {
+	struct kvm_segment seg;
+
 	if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
 		vcpu->arch.efer = vmcs12->host_ia32_efer;
 	else if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
@@ -8001,16 +8024,6 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
 	vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
 	vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
 	vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
-	vmcs_writel(GUEST_TR_BASE, vmcs12->host_tr_base);
-	vmcs_writel(GUEST_GS_BASE, vmcs12->host_gs_base);
-	vmcs_writel(GUEST_FS_BASE, vmcs12->host_fs_base);
-	vmcs_write16(GUEST_ES_SELECTOR, vmcs12->host_es_selector);
-	vmcs_write16(GUEST_CS_SELECTOR, vmcs12->host_cs_selector);
-	vmcs_write16(GUEST_SS_SELECTOR, vmcs12->host_ss_selector);
-	vmcs_write16(GUEST_DS_SELECTOR, vmcs12->host_ds_selector);
-	vmcs_write16(GUEST_FS_SELECTOR, vmcs12->host_fs_selector);
-	vmcs_write16(GUEST_GS_SELECTOR, vmcs12->host_gs_selector);
-	vmcs_write16(GUEST_TR_SELECTOR, vmcs12->host_tr_selector);
 
 	if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT)
 		vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
@@ -8018,6 +8031,52 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
 		vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL,
 			vmcs12->host_ia32_perf_global_ctrl);
 
+	/* Set L1 segment info according to Intel SDM
+	    27.5.2 Loading Host Segment and Descriptor-Table Registers */
+	seg = (struct kvm_segment) {
+		.base = 0,
+		.limit = 0xFFFFFFFF,
+		.selector = vmcs12->host_cs_selector,
+		.type = 11,
+		.present = 1,
+		.s = 1,
+		.g = 1
+	};
+	if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
+		seg.l = 1;
+	else
+		seg.db = 1;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_CS);
+	seg = (struct kvm_segment) {
+		.base = 0,
+		.limit = 0xFFFFFFFF,
+		.type = 3,
+		.present = 1,
+		.s = 1,
+		.db = 1,
+		.g = 1
+	};
+	seg.selector = vmcs12->host_ds_selector;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_DS);
+	seg.selector = vmcs12->host_es_selector;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_ES);
+	seg.selector = vmcs12->host_ss_selector;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_SS);
+	seg.selector = vmcs12->host_fs_selector;
+	seg.base = vmcs12->host_fs_base;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_FS);
+	seg.selector = vmcs12->host_gs_selector;
+	seg.base = vmcs12->host_gs_base;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_GS);
+	seg = (struct kvm_segment) {
+		.base = 0,
+		.limit = 0x67,
+		.selector = vmcs12->host_tr_selector,
+		.type = 11,
+		.present = 1
+	};
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
+
 	kvm_set_dr(vcpu, 7, 0x400);
 	vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
 }
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d21bce5..05afd1a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -850,7 +850,8 @@ static u32 msrs_to_save[] = {
 #ifdef CONFIG_X86_64
 	MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
-	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA
+	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
+	MSR_IA32_FEATURE_CONTROL
 };
 
 static unsigned num_msrs_to_save;
@@ -4955,6 +4956,97 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 static int complete_emulated_mmio(struct kvm_vcpu *vcpu);
 static int complete_emulated_pio(struct kvm_vcpu *vcpu);
 
+static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7,
+				unsigned long *db)
+{
+	u32 dr6 = 0;
+	int i;
+	u32 enable, rwlen;
+
+	enable = dr7;
+	rwlen = dr7 >> 16;
+	for (i = 0; i < 4; i++, enable >>= 2, rwlen >>= 4)
+		if ((enable & 3) && (rwlen & 15) == type && db[i] == addr)
+			dr6 |= (1 << i);
+	return dr6;
+}
+
+static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, int *r)
+{
+	struct kvm_run *kvm_run = vcpu->run;
+
+	/*
+	 * Use the "raw" value to see if TF was passed to the processor.
+	 * Note that the new value of the flags has not been saved yet.
+	 *
+	 * This is correct even for TF set by the guest, because "the
+	 * processor will not generate this exception after the instruction
+	 * that sets the TF flag".
+	 */
+	unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
+
+	if (unlikely(rflags & X86_EFLAGS_TF)) {
+		if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
+			kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1;
+			kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip;
+			kvm_run->debug.arch.exception = DB_VECTOR;
+			kvm_run->exit_reason = KVM_EXIT_DEBUG;
+			*r = EMULATE_USER_EXIT;
+		} else {
+			vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF;
+			/*
+			 * "Certain debug exceptions may clear bit 0-3.  The
+			 * remaining contents of the DR6 register are never
+			 * cleared by the processor".
+			 */
+			vcpu->arch.dr6 &= ~15;
+			vcpu->arch.dr6 |= DR6_BS;
+			kvm_queue_exception(vcpu, DB_VECTOR);
+		}
+	}
+}
+
+static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
+{
+	struct kvm_run *kvm_run = vcpu->run;
+	unsigned long eip = vcpu->arch.emulate_ctxt.eip;
+	u32 dr6 = 0;
+
+	if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) &&
+	    (vcpu->arch.guest_debug_dr7 & DR7_BP_EN_MASK)) {
+		dr6 = kvm_vcpu_check_hw_bp(eip, 0,
+					   vcpu->arch.guest_debug_dr7,
+					   vcpu->arch.eff_db);
+
+		if (dr6 != 0) {
+			kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
+			kvm_run->debug.arch.pc = kvm_rip_read(vcpu) +
+				get_segment_base(vcpu, VCPU_SREG_CS);
+
+			kvm_run->debug.arch.exception = DB_VECTOR;
+			kvm_run->exit_reason = KVM_EXIT_DEBUG;
+			*r = EMULATE_USER_EXIT;
+			return true;
+		}
+	}
+
+	if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK)) {
+		dr6 = kvm_vcpu_check_hw_bp(eip, 0,
+					   vcpu->arch.dr7,
+					   vcpu->arch.db);
+
+		if (dr6 != 0) {
+			vcpu->arch.dr6 &= ~15;
+			vcpu->arch.dr6 |= dr6;
+			kvm_queue_exception(vcpu, DB_VECTOR);
+			*r = EMULATE_DONE;
+			return true;
+		}
+	}
+
+	return false;
+}
+
 int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 			    unsigned long cr2,
 			    int emulation_type,
@@ -4975,6 +5067,16 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 
 	if (!(emulation_type & EMULTYPE_NO_DECODE)) {
 		init_emulate_ctxt(vcpu);
+
+		/*
+		 * We will reenter on the same instruction since
+		 * we do not set complete_userspace_io.  This does not
+		 * handle watchpoints yet, those would be handled in
+		 * the emulate_ops.
+		 */
+		if (kvm_vcpu_check_breakpoint(vcpu, &r))
+			return r;
+
 		ctxt->interruptibility = 0;
 		ctxt->have_exception = false;
 		ctxt->perm_ok = false;
@@ -5037,11 +5139,11 @@ restart:
 			writeback = false;
 			vcpu->arch.complete_userspace_io = complete_emulated_pio;
 		}
-		r = EMULATE_DO_MMIO;
+		r = EMULATE_USER_EXIT;
 	} else if (vcpu->mmio_needed) {
 		if (!vcpu->mmio_is_write)
 			writeback = false;
-		r = EMULATE_DO_MMIO;
+		r = EMULATE_USER_EXIT;
 		vcpu->arch.complete_userspace_io = complete_emulated_mmio;
 	} else if (r == EMULATION_RESTART)
 		goto restart;
@@ -5050,10 +5152,12 @@ restart:
 
 	if (writeback) {
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
-		kvm_set_rflags(vcpu, ctxt->eflags);
 		kvm_make_request(KVM_REQ_EVENT, vcpu);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
 		kvm_rip_write(vcpu, ctxt->eip);
+		if (r == EMULATE_DONE)
+			kvm_vcpu_check_singlestep(vcpu, &r);
+		kvm_set_rflags(vcpu, ctxt->eflags);
 	} else
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = true;
 
@@ -5347,7 +5451,7 @@ static struct notifier_block pvclock_gtod_notifier = {
 int kvm_arch_init(void *opaque)
 {
 	int r;
-	struct kvm_x86_ops *ops = (struct kvm_x86_ops *)opaque;
+	struct kvm_x86_ops *ops = opaque;
 
 	if (kvm_x86_ops) {
 		printk(KERN_ERR "kvm: already loaded the other module\n");
@@ -7019,6 +7123,15 @@ out_free:
 	return -ENOMEM;
 }
 
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+	/*
+	 * memslots->generation has been incremented.
+	 * mmio generation may have reached its maximum value.
+	 */
+	kvm_mmu_invalidate_mmio_sptes(kvm);
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				struct kvm_memory_slot *memslot,
 				struct kvm_userspace_memory_region *mem,
@@ -7079,11 +7192,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 	 */
 	if ((change != KVM_MR_DELETE) && (mem->flags & KVM_MEM_LOG_DIRTY_PAGES))
 		kvm_mmu_slot_remove_write_access(kvm, mem->slot);
-	/*
-	 * If memory slot is created, or moved, we need to clear all
-	 * mmio sptes.
-	 */
-	kvm_mmu_invalidate_mmio_sptes(kvm);
 }
 
 void kvm_arch_flush_shadow_all(struct kvm *kvm)
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 6a22c19..7c1fde5 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -7,8 +7,7 @@
  * kernel and insert a module (lg.ko) which allows us to run other Linux
  * kernels the same way we'd run processes.  We call the first kernel the Host,
  * and the others the Guests.  The program which sets up and configures Guests
- * (such as the example in Documentation/virtual/lguest/lguest.c) is called the
- * Launcher.
+ * (such as the example in tools/lguest/lguest.c) is called the Launcher.
  *
  * Secondly, we only run specially modified Guests, not normal kernels: setting
  * CONFIG_LGUEST_GUEST to "y" compiles this file into the kernel so it knows
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 654be4a..3aaeffc 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -842,23 +842,15 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
 	force_sig_info_fault(SIGBUS, code, address, tsk, fault);
 }
 
-static noinline int
+static noinline void
 mm_fault_error(struct pt_regs *regs, unsigned long error_code,
 	       unsigned long address, unsigned int fault)
 {
-	/*
-	 * Pagefault was interrupted by SIGKILL. We have no reason to
-	 * continue pagefault.
-	 */
-	if (fatal_signal_pending(current)) {
-		if (!(fault & VM_FAULT_RETRY))
-			up_read(&current->mm->mmap_sem);
-		if (!(error_code & PF_USER))
-			no_context(regs, error_code, address, 0, 0);
-		return 1;
+	if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
+		up_read(&current->mm->mmap_sem);
+		no_context(regs, error_code, address, 0, 0);
+		return;
 	}
-	if (!(fault & VM_FAULT_ERROR))
-		return 0;
 
 	if (fault & VM_FAULT_OOM) {
 		/* Kernel mode? Handle exceptions or die: */
@@ -866,7 +858,7 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
 			up_read(&current->mm->mmap_sem);
 			no_context(regs, error_code, address,
 				   SIGSEGV, SEGV_MAPERR);
-			return 1;
+			return;
 		}
 
 		up_read(&current->mm->mmap_sem);
@@ -884,7 +876,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
 		else
 			BUG();
 	}
-	return 1;
 }
 
 static int spurious_fault_check(unsigned long error_code, pte_t *pte)
@@ -1011,9 +1002,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
 	unsigned long address;
 	struct mm_struct *mm;
 	int fault;
-	int write = error_code & PF_WRITE;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
-					(write ? FAULT_FLAG_WRITE : 0);
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	tsk = current;
 	mm = tsk->mm;
@@ -1083,6 +1072,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
 	if (user_mode_vm(regs)) {
 		local_irq_enable();
 		error_code |= PF_USER;
+		flags |= FAULT_FLAG_USER;
 	} else {
 		if (regs->flags & X86_EFLAGS_IF)
 			local_irq_enable();
@@ -1109,6 +1099,9 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
 		return;
 	}
 
+	if (error_code & PF_WRITE)
+		flags |= FAULT_FLAG_WRITE;
+
 	/*
 	 * When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in
@@ -1187,9 +1180,17 @@ good_area:
 	 */
 	fault = handle_mm_fault(mm, vma, address, flags);
 
-	if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
-		if (mm_fault_error(regs, error_code, address, fault))
-			return;
+	/*
+	 * If we need to retry but a fatal signal is pending, handle the
+	 * signal first. We do not need to release the mmap_sem because it
+	 * would already be released in __lock_page_or_retry in mm/filemap.c.
+	 */
+	if (unlikely((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)))
+		return;
+
+	if (unlikely(fault & VM_FAULT_ERROR)) {
+		mm_fault_error(regs, error_code, address, fault);
+		return;
 	}
 
 	/*
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 62c29a5..f63778c 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -98,7 +98,7 @@ static unsigned long mmap_base(void)
  * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
  * does, but not when emulating X86_32
  */
-static unsigned long mmap_legacy_base(void)
+unsigned long mmap_legacy_base(void)
 {
 	if (mmap_is_ia32())
 		return TASK_UNMAPPED_BASE;
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 282375f..ae699b3 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -103,6 +103,7 @@ static void flush_tlb_func(void *info)
 	if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
 		return;
 
+	count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
 	if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
 		if (f->flush_end == TLB_FLUSH_ALL)
 			local_flush_tlb();
@@ -130,6 +131,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
 	info.flush_start = start;
 	info.flush_end = end;
 
+	count_vm_event(NR_TLB_REMOTE_FLUSH);
 	if (is_uv_system()) {
 		unsigned int cpu;
 
@@ -149,6 +151,7 @@ void flush_tlb_current_task(void)
 
 	preempt_disable();
 
+	count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
 	local_flush_tlb();
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
 		flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
@@ -211,16 +214,19 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
 	act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm;
 
 	/* tlb_flushall_shift is on balance point, details in commit log */
-	if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift)
+	if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) {
+		count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
 		local_flush_tlb();
-	else {
+	} else {
 		if (has_large_page(mm, start, end)) {
 			local_flush_tlb();
 			goto flush_all;
 		}
 		/* flush range by one by one 'invlpg' */
-		for (addr = start; addr < end;	addr += PAGE_SIZE)
+		for (addr = start; addr < end;	addr += PAGE_SIZE) {
+			count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
 			__flush_tlb_single(addr);
+		}
 
 		if (cpumask_any_but(mm_cpumask(mm),
 				smp_processor_id()) < nr_cpu_ids)
@@ -256,6 +262,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)
 
 static void do_flush_tlb_all(void *info)
 {
+	count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
 	__flush_tlb_all();
 	if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
 		leave_mm(smp_processor_id());
@@ -263,6 +270,7 @@ static void do_flush_tlb_all(void *info)
 
 void flush_tlb_all(void)
 {
+	count_vm_event(NR_TLB_REMOTE_FLUSH);
 	on_each_cpu(do_flush_tlb_all, NULL, 1);
 }
 
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 94919e3..db6b1ab 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -210,6 +210,8 @@ static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
 		r = &dev->resource[idx];
 		if (!r->flags)
 			continue;
+		if (r->parent)	/* Already allocated */
+			continue;
 		if (!r->start || pci_claim_resource(dev, idx) < 0) {
 			/*
 			 * Something is wrong with the region.
@@ -318,6 +320,8 @@ static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 	r = &dev->resource[PCI_ROM_RESOURCE];
 	if (!r->flags || !r->start)
 		return;
+	if (r->parent) /* Already allocated */
+		return;
 
 	if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
 		r->end -= r->start;
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 082e881..5596c7b 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -700,7 +700,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
 	if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
 		return -ENODEV;
 
-	if (start > end)
+	if (start > end || !addr)
 		return -EINVAL;
 
 	mutex_lock(&pci_mmcfg_lock);
@@ -716,11 +716,6 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
 		return -EEXIST;
 	}
 
-	if (!addr) {
-		mutex_unlock(&pci_mmcfg_lock);
-		return -EINVAL;
-	}
-
 	rc = -EBUSY;
 	cfg = pci_mmconfig_alloc(seg, start, end, addr);
 	if (cfg == NULL) {
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c
index 6eb18c4..903fded 100644
--- a/arch/x86/pci/mrst.c
+++ b/arch/x86/pci/mrst.c
@@ -23,11 +23,11 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/smp.h>
 
-#include <asm/acpi.h>
 #include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/smp.h>
 #include <asm/pci_x86.h>
 #include <asm/hw_irq.h>
 #include <asm/io_apic.h>
@@ -43,7 +43,7 @@
 #define PCI_FIXED_BAR_4_SIZE	0x14
 #define PCI_FIXED_BAR_5_SIZE	0x1c
 
-static int pci_soc_mode = 0;
+static int pci_soc_mode;
 
 /**
  * fixed_bar_cap - return the offset of the fixed BAR cap if found
@@ -141,7 +141,8 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
  */
 static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
 {
-	/* This is a workaround for A0 LNC bug where PCI status register does
+	/*
+	 * This is a workaround for A0 LNC bug where PCI status register does
 	 * not have new CAP bit set. can not be written by SW either.
 	 *
 	 * PCI header type in real LNC indicates a single function device, this
@@ -154,7 +155,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
 				|| devfn == PCI_DEVFN(0, 0)
 				|| devfn == PCI_DEVFN(3, 0)))
 		return 1;
-	return 0; /* langwell on others */
+	return 0; /* Langwell on others */
 }
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
@@ -172,7 +173,8 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 {
 	int offset;
 
-	/* On MRST, there is no PCI ROM BAR, this will cause a subsequent read
+	/*
+	 * On MRST, there is no PCI ROM BAR, this will cause a subsequent read
 	 * to ROM BAR return 0 then being ignored.
 	 */
 	if (where == PCI_ROM_ADDRESS)
@@ -210,7 +212,8 @@ static int mrst_pci_irq_enable(struct pci_dev *dev)
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 
-	/* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
+	/*
+	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
 	 * IOAPIC RTE entries, so we just enable RTE for the device.
 	 */
 	irq_attr.ioapic = mp_find_ioapic(dev->irq);
@@ -235,7 +238,7 @@ struct pci_ops pci_mrst_ops = {
  */
 int __init pci_mrst_init(void)
 {
-	printk(KERN_INFO "Intel MID platform detected, using MID PCI ops\n");
+	pr_info("Intel MID platform detected, using MID PCI ops\n");
 	pci_mmcfg_late_init();
 	pcibios_enable_irq = mrst_pci_irq_enable;
 	pci_root_ops = pci_mrst_ops;
@@ -244,17 +247,21 @@ int __init pci_mrst_init(void)
 	return 1;
 }
 
-/* Langwell devices are not true pci devices, they are not subject to 10 ms
- * d3 to d0 delay required by pci spec.
+/*
+ * Langwell devices are not true PCI devices; they are not subject to 10 ms
+ * d3 to d0 delay required by PCI spec.
  */
 static void pci_d3delay_fixup(struct pci_dev *dev)
 {
-	/* PCI fixups are effectively decided compile time. If we have a dual
-	   SoC/non-SoC kernel we don't want to mangle d3 on non SoC devices */
-        if (!pci_soc_mode)
-            return;
-	/* true pci devices in lincroft should allow type 1 access, the rest
-	 * are langwell fake pci devices.
+	/*
+	 * PCI fixups are effectively decided compile time. If we have a dual
+	 * SoC/non-SoC kernel we don't want to mangle d3 on non-SoC devices.
+	 */
+	if (!pci_soc_mode)
+		return;
+	/*
+	 * True PCI devices in Lincroft should allow type 1 access, the rest
+	 * are Langwell fake PCI devices.
 	 */
 	if (type1_access_ok(dev->bus->number, dev->devfn, PCI_DEVICE_ID))
 		return;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 90f6ed1..f0d732c 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -343,10 +343,17 @@ static void __init do_add_efi_memmap(void)
 		int e820_type;
 
 		switch (md->type) {
-		case EFI_LOADER_CODE:
-		case EFI_LOADER_DATA:
 		case EFI_BOOT_SERVICES_CODE:
 		case EFI_BOOT_SERVICES_DATA:
+			/* EFI_BOOT_SERVICES_{CODE,DATA} needs to be mapped */
+			if (md->attribute & EFI_MEMORY_WB)
+				e820_type = E820_RAM;
+			else
+				e820_type = E820_RESERVED;
+			e820_add_region(start, size, e820_type);
+			continue;
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
 		case EFI_CONVENTIONAL_MEMORY:
 			if (md->attribute & EFI_MEMORY_WB)
 				e820_type = E820_RAM;
@@ -371,7 +378,7 @@ static void __init do_add_efi_memmap(void)
 			e820_type = E820_RESERVED;
 			break;
 		}
-		e820_add_region(start, size, e820_type);
+		e820_add_limit_region(start, size, e820_type);
 	}
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
@@ -479,6 +486,8 @@ void __init efi_free_boot_services(void)
 		    md->type != EFI_BOOT_SERVICES_DATA)
 			continue;
 
+		e820_adjust_region(&start, &size);
+
 		/* Could not reserve boot area */
 		if (!size)
 			continue;
diff --git a/arch/x86/um/elfcore.c b/arch/x86/um/elfcore.c
index 6bb49b6..a623ee6 100644
--- a/arch/x86/um/elfcore.c
+++ b/arch/x86/um/elfcore.c
@@ -11,8 +11,7 @@ Elf32_Half elf_core_extra_phdrs(void)
 	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
 }
 
-int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-			       unsigned long limit)
+int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
 {
 	if ( vsyscall_ehdr ) {
 		const struct elfhdr *const ehdrp =
@@ -32,19 +31,16 @@ int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
 				phdr.p_offset += ofs;
 			}
 			phdr.p_paddr = 0; /* match other core phdrs */
-			*size += sizeof(phdr);
-			if (*size > limit
-			    || !dump_write(file, &phdr, sizeof(phdr)))
+			if (!dump_emit(cprm, &phdr, sizeof(phdr)))
 				return 0;
 		}
 	}
 	return 1;
 }
 
-int elf_core_write_extra_data(struct file *file, size_t *size,
-			      unsigned long limit)
+int elf_core_write_extra_data(struct coredump_params *cprm)
 {
-	if ( vsyscall_ehdr ) {
+	if (vsyscall_ehdr) {
 		const struct elfhdr *const ehdrp =
 			(struct elfhdr *) vsyscall_ehdr;
 		const struct elf_phdr *const phdrp =
@@ -56,9 +52,7 @@ int elf_core_write_extra_data(struct file *file, size_t *size,
 				void *addr = (void *) phdrp[i].p_vaddr;
 				size_t filesz = phdrp[i].p_filesz;
 
-				*size += filesz;
-				if (*size > limit
-				    || !dump_write(file, addr, filesz))
+				if (!dump_emit(cprm, addr, filesz))
 					return 0;
 			}
 		}
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index c74436e..72074d5 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -85,15 +85,18 @@ static notrace cycle_t vread_pvclock(int *mode)
 	cycle_t ret;
 	u64 last;
 	u32 version;
-	u32 migrate_count;
 	u8 flags;
 	unsigned cpu, cpu1;
 
 
 	/*
-	 * When looping to get a consistent (time-info, tsc) pair, we
-	 * also need to deal with the possibility we can switch vcpus,
-	 * so make sure we always re-fetch time-info for the current vcpu.
+	 * Note: hypervisor must guarantee that:
+	 * 1. cpu ID number maps 1:1 to per-CPU pvclock time info.
+	 * 2. that per-CPU pvclock time info is updated if the
+	 *    underlying CPU changes.
+	 * 3. that version is increased whenever underlying CPU
+	 *    changes.
+	 *
 	 */
 	do {
 		cpu = __getcpu() & VGETCPU_CPU_MASK;
@@ -104,8 +107,6 @@ static notrace cycle_t vread_pvclock(int *mode)
 
 		pvti = get_pvti(cpu);
 
-		migrate_count = pvti->migrate_count;
-
 		version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
 
 		/*
@@ -117,8 +118,7 @@ static notrace cycle_t vread_pvclock(int *mode)
 		cpu1 = __getcpu() & VGETCPU_CPU_MASK;
 	} while (unlikely(cpu != cpu1 ||
 			  (pvti->pvti.version & 1) ||
-			  pvti->pvti.version != version ||
-			  pvti->migrate_count != migrate_count));
+			  pvti->pvti.version != version));
 
 	if (unlikely(!(flags & PVCLOCK_TSC_STABLE_BIT)))
 		*mode = VCLOCK_NONE;
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 42a8bba..101012b 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -170,8 +170,7 @@ static int __init parse_tag_fdt(const bp_tag_t *tag)
 
 __tagtable(BP_TAG_FDT, parse_tag_fdt);
 
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-		unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
 	initrd_start = (void *)__va(start);
 	initrd_end = (void *)__va(end);
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 4b7bc8d..70fa7bc 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -72,6 +72,8 @@ void do_page_fault(struct pt_regs *regs)
 	       address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
 #endif
 
+	if (user_mode(regs))
+		flags |= FAULT_FLAG_USER;
 retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 4464c82..46cd7bd 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -367,7 +367,7 @@ struct io_cq *ioc_create_icq(struct io_context *ioc, struct request_queue *q,
 	if (!icq)
 		return NULL;
 
-	if (radix_tree_preload(gfp_mask) < 0) {
+	if (radix_tree_maybe_preload(gfp_mask) < 0) {
 		kmem_cache_free(et->icq_cache, icq);
 		return NULL;
 	}
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 5efc5a6..3aa5b19 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -29,7 +29,7 @@ queue_var_store(unsigned long *var, const char *page, size_t count)
 	int err;
 	unsigned long v;
 
-	err = strict_strtoul(page, 10, &v);
+	err = kstrtoul(page, 10, &v);
 	if (err || v > UINT_MAX)
 		return -EINVAL;
 
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 7e5d474..fbd5a67 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -70,7 +70,7 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
 		return ret;
 
 	ret = copy_to_user(ugeo, &geo, 4);
-	ret |= __put_user(geo.start, &ugeo->start);
+	ret |= put_user(geo.start, &ugeo->start);
 	if (ret)
 		ret = -EFAULT;
 
diff --git a/block/genhd.c b/block/genhd.c
index dadf42b..01b4813 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -849,7 +849,7 @@ static int show_partition(struct seq_file *seqf, void *v)
 	char buf[BDEVNAME_SIZE];
 
 	/* Don't show non-partitionable removeable devices or empty devices */
-	if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
+	if (!get_capacity(sgp) || (!(disk_max_parts(sgp) > 1) &&
 				   (sgp->flags & GENHD_FL_REMOVABLE)))
 		return 0;
 	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig
index 4cebb2f..2ebf251 100644
--- a/block/partitions/Kconfig
+++ b/block/partitions/Kconfig
@@ -260,3 +260,9 @@ config SYSV68_PARTITION
 	  partition table format used by Motorola Delta machines (using
 	  sysv68).
 	  Otherwise, say N.
+
+config CMDLINE_PARTITION
+	bool "Command line partition support" if PARTITION_ADVANCED
+	help
+	  Say Y here if you would read the partitions table from bootargs.
+	  The format for the command line is just like mtdparts.
diff --git a/block/partitions/Makefile b/block/partitions/Makefile
index 2be4d7b..3a48468 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o
 obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
 obj-$(CONFIG_ATARI_PARTITION) += atari.o
 obj-$(CONFIG_AIX_PARTITION) += aix.o
+obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o
 obj-$(CONFIG_MAC_PARTITION) += mac.o
 obj-$(CONFIG_LDM_PARTITION) += ldm.o
 obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
@@ -19,3 +20,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
 obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
+obj-$(CONFIG_BLOCKCONSOLE) += blockconsole.o
diff --git a/block/partitions/blockconsole.c b/block/partitions/blockconsole.c
new file mode 100644
index 0000000..79796a8
--- /dev/null
+++ b/block/partitions/blockconsole.c
@@ -0,0 +1,22 @@
+#include <linux/blockconsole.h>
+
+#include "check.h"
+
+int blockconsole_partition(struct parsed_partitions *state)
+{
+	Sector sect;
+	void *data;
+	int err = 0;
+
+	data = read_part_sector(state, 0, &sect);
+	if (!data)
+		return -EIO;
+	if (!bcon_magic_present(data))
+		goto out;
+
+	bcon_add(state->name);
+	err = 1;
+out:
+	put_dev_sector(sect);
+	return err;
+}
diff --git a/block/partitions/check.c b/block/partitions/check.c
index 19ba207..ca671199 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -34,6 +34,7 @@
 #include "efi.h"
 #include "karma.h"
 #include "sysv68.h"
+#include "cmdline.h"
 
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
 
@@ -42,6 +43,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
 	 * Probe partition formats with tables at disk address 0
 	 * that also have an ADFS boot block at 0xdc0.
 	 */
+#ifdef CONFIG_BLOCKCONSOLE
+	blockconsole_partition,
+#endif
 #ifdef CONFIG_ACORN_PARTITION_ICS
 	adfspart_check_ICS,
 #endif
@@ -65,6 +69,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
 	adfspart_check_ADFS,
 #endif
 
+#ifdef CONFIG_CMDLINE_PARTITION
+	cmdline_partition,
+#endif
 #ifdef CONFIG_EFI_PARTITION
 	efi_partition,		/* this must come before msdos */
 #endif
diff --git a/block/partitions/check.h b/block/partitions/check.h
index eade17e..bca9624 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -52,3 +52,6 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
 
 extern int warn_no_part;
 
+#ifdef CONFIG_BLOCKCONSOLE
+int blockconsole_partition(struct parsed_partitions *state);
+#endif
diff --git a/block/partitions/cmdline.c b/block/partitions/cmdline.c
new file mode 100644
index 0000000..1a1eac7
--- /dev/null
+++ b/block/partitions/cmdline.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2013 HUAWEI
+ * Author: Cai Zhiyong <caizhiyong@huawei.com>
+ *
+ * Read block device partition table from command line.
+ * The partition used for fixed block device (eMMC) embedded device.
+ * It is no MBR, save storage space. Bootloader can be easily accessed
+ * by absolute address of data on the block device.
+ * Users can easily change the partition.
+ *
+ * This code reference MTD partition, source "drivers/mtd/cmdlinepart.c"
+ * The format for the command line is just like mtdparts.
+ *
+ * Verbose config please reference "Documentation/block/cmdline-partition.txt"
+ *
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+
+#include "check.h"
+#include "cmdline.h"
+
+struct cmdline_subpart {
+	char name[BDEVNAME_SIZE]; /* partition name, such as 'rootfs' */
+	sector_t from;
+	sector_t size;
+	struct cmdline_subpart *next_subpart;
+};
+
+struct cmdline_parts {
+	char name[BDEVNAME_SIZE]; /* block device, such as 'mmcblk0' */
+	struct cmdline_subpart *subpart;
+	struct cmdline_parts *next_parts;
+};
+
+static char *cmdline_string;
+static struct cmdline_parts *cmdline_parts;
+
+static int parse_subpart(struct cmdline_subpart **subpart, char *cmdline)
+{
+	int ret = 0;
+	struct cmdline_subpart *new_subpart;
+
+	*subpart = NULL;
+
+	new_subpart = kzalloc(sizeof(struct cmdline_subpart), GFP_KERNEL);
+	if (!new_subpart)
+		return -ENOMEM;
+
+	if (*cmdline == '-') {
+		new_subpart->size = (sector_t)(~0ULL);
+		cmdline++;
+	} else {
+		new_subpart->size = (sector_t)memparse(cmdline, &cmdline);
+		if (new_subpart->size < (sector_t)PAGE_SIZE) {
+			pr_warn("cmdline partition size is invalid.");
+			ret = -EINVAL;
+			goto fail;
+		}
+	}
+
+	if (*cmdline == '@') {
+		cmdline++;
+		new_subpart->from = (sector_t)memparse(cmdline, &cmdline);
+	} else {
+		new_subpart->from = (sector_t)(~0ULL);
+	}
+
+	if (*cmdline == '(') {
+		int length;
+		char *next = strchr(++cmdline, ')');
+
+		if (!next) {
+			pr_warn("cmdline partition format is invalid.");
+			ret = -EINVAL;
+			goto fail;
+		}
+
+		length = min_t(int, next - cmdline,
+			       sizeof(new_subpart->name) - 1);
+		strncpy(new_subpart->name, cmdline, length);
+		new_subpart->name[length] = '\0';
+
+		cmdline = ++next;
+	} else
+		new_subpart->name[0] = '\0';
+
+	*subpart = new_subpart;
+	return 0;
+fail:
+	kfree(new_subpart);
+	return ret;
+}
+
+static void free_subpart(struct cmdline_parts *parts)
+{
+	struct cmdline_subpart *subpart;
+
+	while (parts->subpart) {
+		subpart = parts->subpart;
+		parts->subpart = subpart->next_subpart;
+		kfree(subpart);
+	}
+}
+
+static void free_parts(struct cmdline_parts **parts)
+{
+	struct cmdline_parts *next_parts;
+
+	while (*parts) {
+		next_parts = (*parts)->next_parts;
+		free_subpart(*parts);
+		kfree(*parts);
+		*parts = next_parts;
+	}
+}
+
+static int parse_parts(struct cmdline_parts **parts, const char *cmdline)
+{
+	int ret = -EINVAL;
+	char *next;
+	int length;
+	struct cmdline_subpart **next_subpart;
+	struct cmdline_parts *newparts;
+	char buf[BDEVNAME_SIZE + 32 + 4];
+
+	*parts = NULL;
+
+	newparts = kzalloc(sizeof(struct cmdline_parts), GFP_KERNEL);
+	if (!newparts)
+		return -ENOMEM;
+
+	next = strchr(cmdline, ':');
+	if (!next) {
+		pr_warn("cmdline partition has no block device.");
+		goto fail;
+	}
+
+	length = min_t(int, next - cmdline, sizeof(newparts->name) - 1);
+	strncpy(newparts->name, cmdline, length);
+	newparts->name[length] = '\0';
+
+	next_subpart = &newparts->subpart;
+
+	while (next && *(++next)) {
+		cmdline = next;
+		next = strchr(cmdline, ',');
+
+		length = (!next) ? (sizeof(buf) - 1) :
+			min_t(int, next - cmdline, sizeof(buf) - 1);
+
+		strncpy(buf, cmdline, length);
+		buf[length] = '\0';
+
+		ret = parse_subpart(next_subpart, buf);
+		if (ret)
+			goto fail;
+
+		next_subpart = &(*next_subpart)->next_subpart;
+	}
+
+	if (!newparts->subpart) {
+		pr_warn("cmdline partition has no valid partition.");
+		goto fail;
+	}
+
+	*parts = newparts;
+
+	return 0;
+fail:
+	free_subpart(newparts);
+	kfree(newparts);
+	return ret;
+}
+
+static int parse_cmdline(struct cmdline_parts **parts, const char *cmdline)
+{
+	int ret;
+	char *buf;
+	char *pbuf;
+	char *next;
+	struct cmdline_parts **next_parts;
+
+	*parts = NULL;
+
+	next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	next_parts = parts;
+
+	while (next && *pbuf) {
+		next = strchr(pbuf, ';');
+		if (next)
+			*next = '\0';
+
+		ret = parse_parts(next_parts, pbuf);
+		if (ret)
+			goto fail;
+
+		if (next)
+			pbuf = ++next;
+
+		next_parts = &(*next_parts)->next_parts;
+	}
+
+	if (!*parts) {
+		pr_warn("cmdline partition has no valid partition.");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	ret = 0;
+done:
+	kfree(buf);
+	return ret;
+
+fail:
+	free_parts(parts);
+	goto done;
+}
+
+/*
+ * Purpose: allocate cmdline partitions.
+ * Returns:
+ * -1 if unable to read the partition table
+ *  0 if this isn't our partition table
+ *  1 if successful
+ */
+static int parse_partitions(struct parsed_partitions *state,
+			    struct cmdline_parts *parts)
+{
+	int slot;
+	sector_t from = 0;
+	sector_t disk_size;
+	char buf[BDEVNAME_SIZE];
+	struct cmdline_subpart *subpart;
+
+	bdevname(state->bdev, buf);
+
+	while (parts && strncmp(buf, parts->name, BDEVNAME_SIZE))
+		parts = parts->next_parts;
+
+	if (!parts)
+		return 0;
+
+	disk_size = get_capacity(state->bdev->bd_disk) << 9;
+
+	for (slot = 1, subpart = parts->subpart;
+	     subpart && slot < state->limit;
+	     subpart = subpart->next_subpart, slot++) {
+		int label_min;
+		struct partition_meta_info *info;
+		char tmp[sizeof(info->volname) + 4];
+
+		if (subpart->from == (sector_t)(~0ULL))
+			subpart->from = from;
+		else
+			from = subpart->from;
+
+		if (from >= disk_size)
+			break;
+
+		if (subpart->size > (disk_size - from))
+			subpart->size = disk_size - from;
+
+		from += subpart->size;
+
+		put_partition(state, slot, subpart->from >> 9,
+			      subpart->size >> 9);
+
+		info = &state->parts[slot].info;
+
+		label_min = min_t(int, sizeof(info->volname) - 1,
+				  sizeof(subpart->name));
+		strncpy(info->volname, subpart->name, label_min);
+		info->volname[label_min] = '\0';
+
+		snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
+		strlcat(state->pp_buf, tmp, PAGE_SIZE);
+
+		state->parts[slot].has_info = true;
+	}
+
+	strlcat(state->pp_buf, "\n", PAGE_SIZE);
+
+	return 1;
+}
+
+static int __init cmdline_parts_setup(char *s)
+{
+	cmdline_string = s;
+	return 1;
+}
+__setup("blkdevparts=", cmdline_parts_setup);
+
+/*
+ * Purpose: allocate cmdline partitions.
+ * Returns:
+ * -1 if unable to read the partition table
+ *  0 if this isn't our partition table
+ *  1 if successful
+ */
+int cmdline_partition(struct parsed_partitions *state)
+{
+	if (cmdline_string) {
+		if (cmdline_parts)
+			free_parts(&cmdline_parts);
+
+		if (parse_cmdline(&cmdline_parts, cmdline_string))
+			goto fail;
+
+		cmdline_string = NULL;
+	}
+
+	if (!cmdline_parts)
+		return 0;
+
+	return parse_partitions(state, cmdline_parts);
+
+fail:
+	cmdline_string = NULL;
+	return -1;
+}
diff --git a/block/partitions/cmdline.h b/block/partitions/cmdline.h
new file mode 100644
index 0000000..26e0f8d
--- /dev/null
+++ b/block/partitions/cmdline.h
@@ -0,0 +1,2 @@
+
+int cmdline_partition(struct parsed_partitions *state);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ecddf92..b7bc2e7 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -3224,7 +3224,7 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
 	if (i >= 0)
 		rc |= alg_test_descs[i].test(alg_test_descs + i, driver,
 					     type, mask);
-	if (j >= 0)
+	if (j >= 0 && j != i)
 		rc |= alg_test_descs[j].test(alg_test_descs + j, driver,
 					     type, mask);
 
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 100bd72..3278a21 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -91,24 +91,6 @@ config ACPI_EC_DEBUGFS
 	  Thus this option is a debug option that helps to write ACPI drivers
 	  and can be used to identify ACPI code or EC firmware bugs.
 
-config ACPI_PROC_EVENT
-	bool "Deprecated /proc/acpi/event support"
-	depends on PROC_FS
-	default y
-	help
-	  A user-space daemon, acpid, typically reads /proc/acpi/event
-	  and handles all ACPI-generated events.
-
-	  These events are now delivered to user-space either
-	  via the input layer or as netlink events.
-
-	  This build option enables the old code for legacy
-	  user-space implementation.  After some time, this will
-	  be moved under CONFIG_ACPI_PROCFS, and then deleted.
-
-	  Say Y here to retain the old behaviour.  Say N if your
-	  user-space is newer than kernel 2.6.23 (September 2007).
-
 config ACPI_AC
 	tristate "AC Adapter"
 	depends on X86
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 4f4e741..f37beaa3 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -267,7 +267,6 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
 			msleep(ac_sleep_before_get_state_ms);
 
 		acpi_ac_get_state(ac);
-		acpi_bus_generate_proc_event(device, event, (u32) ac->state);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event,
 						  (u32) ac->state);
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 27bb6a9..fc6008f 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -231,16 +231,19 @@ static struct task_struct *ps_tsks[NR_CPUS];
 static unsigned int ps_tsk_num;
 static int create_power_saving_task(void)
 {
-	int rc = -ENOMEM;
+	int rc;
 
 	ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread,
 		(void *)(unsigned long)ps_tsk_num,
 		"acpi_pad/%d", ps_tsk_num);
-	rc = PTR_RET(ps_tsks[ps_tsk_num]);
-	if (!rc)
-		ps_tsk_num++;
-	else
+
+	if (IS_ERR(ps_tsks[ps_tsk_num])) {
+		rc = PTR_ERR(ps_tsks[ps_tsk_num]);
 		ps_tsks[ps_tsk_num] = NULL;
+	} else {
+		rc = 0;
+		ps_tsk_num++;
+	}
 
 	return rc;
 }
@@ -452,7 +455,6 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
 	switch (event) {
 	case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
 		acpi_pad_handle_notify(handle);
-		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 			dev_name(&device->dev), event, 0);
 		break;
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index fafec5d..1bde127 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -52,7 +52,7 @@ int acpi_create_platform_device(struct acpi_device *adev,
 	struct platform_device_info pdevinfo;
 	struct resource_list_entry *rentry;
 	struct list_head resource_list;
-	struct resource *resources;
+	struct resource *resources = NULL;
 	int count;
 
 	/* If the ACPI node already has a physical device attached, skip it. */
@@ -61,20 +61,22 @@ int acpi_create_platform_device(struct acpi_device *adev,
 
 	INIT_LIST_HEAD(&resource_list);
 	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
-	if (count <= 0)
+	if (count < 0) {
 		return 0;
+	} else if (count > 0) {
+		resources = kmalloc(count * sizeof(struct resource),
+				    GFP_KERNEL);
+		if (!resources) {
+			dev_err(&adev->dev, "No memory for resources\n");
+			acpi_dev_free_resource_list(&resource_list);
+			return -ENOMEM;
+		}
+		count = 0;
+		list_for_each_entry(rentry, &resource_list, node)
+			resources[count++] = rentry->res;
 
-	resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
-	if (!resources) {
-		dev_err(&adev->dev, "No memory for resources\n");
 		acpi_dev_free_resource_list(&resource_list);
-		return -ENOMEM;
 	}
-	count = 0;
-	list_for_each_entry(rentry, &resource_list, node)
-		resources[count++] = rentry->res;
-
-	acpi_dev_free_resource_list(&resource_list);
 
 	memset(&pdevinfo, 0, sizeof(pdevinfo));
 	/*
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index fd6c51c..5a74a9c 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -451,7 +451,6 @@ static void acpi_processor_remove(struct acpi_device *device)
 	/* Clean up. */
 	per_cpu(processor_device_array, pr->id) = NULL;
 	per_cpu(processors, pr->id) = NULL;
-	try_offline_node(cpu_to_node(pr->id));
 
 	/* Remove the CPU. */
 	get_online_cpus();
@@ -459,6 +458,8 @@ static void acpi_processor_remove(struct acpi_device *device)
 	acpi_unmap_lsapic(pr->id);
 	put_online_cpus();
 
+	try_offline_node(cpu_to_node(pr->id));
+
  out:
 	free_cpumask_var(pr->throttling.shared_cpu_map);
 	kfree(pr);
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index d4a49016..b0e3d15 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -942,6 +942,9 @@ struct acpi_interface_info {
 
 #define ACPI_OSI_INVALID                0x01
 #define ACPI_OSI_DYNAMIC                0x02
+#define ACPI_OSI_FEATURE                0x04
+#define ACPI_OSI_DEFAULT_INVALID        0x08
+#define ACPI_OSI_OPTIONAL_FEATURE       (ACPI_OSI_FEATURE | ACPI_OSI_DEFAULT_INVALID | ACPI_OSI_INVALID)
 
 struct acpi_port_info {
 	char *name;
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index 7755e91..917315e 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -47,6 +47,11 @@
 acpi_status acpi_allocate_root_table(u32 initial_table_count);
 
 /*
+ * tbxfroot - Root pointer utilities
+ */
+u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
+
+/*
  * tbfadt - FADT parse/convert/validate
  */
 void acpi_tb_parse_fadt(u32 table_index);
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 3c76ede..d5a62a6 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -470,6 +470,8 @@ acpi_status acpi_ut_install_interface(acpi_string interface_name);
 
 acpi_status acpi_ut_remove_interface(acpi_string interface_name);
 
+acpi_status acpi_ut_update_interfaces(u8 action);
+
 struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
 
 acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
@@ -616,7 +618,7 @@ int acpi_ut_stricmp(char *string1, char *string2);
 
 acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
 
-void acpi_ut_print_string(char *string, u8 max_length);
+void acpi_ut_print_string(char *string, u16 max_length);
 
 void ut_convert_backslashes(char *pathname);
 
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index 9037f17..7842700 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -125,7 +125,6 @@ acpi_status acpi_ev_gpe_initialize(void)
 		/* GPE block 0 exists (has both length and address > 0) */
 
 		register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2);
-
 		gpe_number_max =
 		    (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
 
@@ -204,16 +203,6 @@ acpi_status acpi_ev_gpe_initialize(void)
 		goto cleanup;
 	}
 
-	/* Check for Max GPE number out-of-range */
-
-	if (gpe_number_max > ACPI_GPE_MAX) {
-		ACPI_ERROR((AE_INFO,
-			    "Maximum GPE number from FADT is too large: 0x%X",
-			    gpe_number_max));
-		status = AE_BAD_VALUE;
-		goto cleanup;
-	}
-
       cleanup:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index c740f24..4d046fa 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -338,6 +338,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
 {
 	u8 *target;
 	char *name;
+	const char *reference_name;
 	u8 count;
 
 	if (!info) {
@@ -426,10 +427,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
 
 		case ACPI_EXD_REFERENCE:
 
+			reference_name = acpi_ut_get_reference_name(obj_desc);
 			acpi_ex_out_string("Class Name",
-					   ACPI_CAST_PTR(char,
-							 acpi_ut_get_reference_name
-							 (obj_desc)));
+					   ACPI_CAST_PTR(char, reference_name));
 			acpi_ex_dump_reference_obj(obj_desc);
 			break;
 
diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c
index 5e5f762..4140768 100644
--- a/drivers/acpi/acpica/hwesleep.c
+++ b/drivers/acpi/acpica/hwesleep.c
@@ -43,6 +43,7 @@
  */
 
 #include <acpi/acpi.h>
+#include <linux/acpi.h>
 #include "accommon.h"
 
 #define _COMPONENT          ACPI_HARDWARE
@@ -128,6 +129,14 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
 
 	ACPI_FLUSH_CPU_CACHE();
 
+	status = acpi_os_prepare_extended_sleep(sleep_state,
+						acpi_gbl_sleep_type_a,
+						acpi_gbl_sleep_type_b);
+	if (ACPI_SKIP(status))
+		return_ACPI_STATUS(AE_OK);
+	if (ACPI_FAILURE(status))
+		return_ACPI_STATUS(status);
+
 	/*
 	 * Set the SLP_TYP and SLP_EN bits.
 	 *
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index f3a4d95..83c1644 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -158,6 +158,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 {
 	acpi_status status;
 	struct acpi_namespace_node *node;
+	char *node_name;
 
 	/* Parameter validation */
 
@@ -202,7 +203,8 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 
 	/* Just copy the ACPI name from the Node and zero terminate it */
 
-	ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node));
+	node_name = acpi_ut_get_node_name(node);
+	ACPI_MOVE_NAME(buffer->pointer, node_name);
 	((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
 	status = AE_OK;
 
@@ -379,9 +381,14 @@ acpi_get_object_info(acpi_handle handle,
 		 * Get extra info for ACPI Device/Processor objects only:
 		 * Run the _STA, _ADR and, sx_w, and _sx_d methods.
 		 *
-		 * Note: none of these methods are required, so they may or may
+		 * Notes: none of these methods are required, so they may or may
 		 * not be present for this device. The Info->Valid bitfield is used
 		 * to indicate which methods were found and run successfully.
+		 *
+		 * For _STA, if the method does not exist, then (as per the ACPI
+		 * specification), the returned current_status flags will indicate
+		 * that the device is present/functional/enabled. Otherwise, the
+		 * current_status flags reflect the value returned from _STA.
 		 */
 
 		/* Execute the Device._STA method */
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 7c2ecfb..e76ed0f 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -49,8 +49,6 @@
 ACPI_MODULE_NAME("tbxfroot")
 
 /* Local prototypes */
-static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
-
 static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
 
 /*******************************************************************************
@@ -231,7 +229,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
  * DESCRIPTION: Search a block of memory for the RSDP signature
  *
  ******************************************************************************/
-static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
+u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
 {
 	acpi_status status;
 	u8 *mem_rover;
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c
index ee83adb..4fd6897 100644
--- a/drivers/acpi/acpica/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -239,7 +239,8 @@ acpi_ut_evaluate_numeric_object(char *object_name,
  * RETURN:      Status
  *
  * DESCRIPTION: Executes _STA for selected device and stores results in
- *              *Flags.
+ *              *Flags. If _STA does not exist, then the device is assumed
+ *              to be present/functional/enabled (as per the ACPI spec).
  *
  *              NOTE: Internal function, no parameter validation
  *
@@ -257,6 +258,11 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
 					 ACPI_BTYPE_INTEGER, &obj_desc);
 	if (ACPI_FAILURE(status)) {
 		if (AE_NOT_FOUND == status) {
+			/*
+			 * if _STA does not exist, then (as per the ACPI specification),
+			 * the returned flags will indicate that the device is present,
+			 * functional, and enabled.
+			 */
 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 					  "_STA on %4.4s was not found, assuming device is present\n",
 					  acpi_ut_get_node_name(device_node)));
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 7e80772..8856bd3 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -77,21 +77,20 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
 
 	/* Feature Group Strings */
 
-	{"Extended Address Space Descriptor", NULL, 0, 0}
+	{"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0},
 
 	/*
 	 * All "optional" feature group strings (features that are implemented
-	 * by the host) should be dynamically added by the host via
-	 * acpi_install_interface and should not be manually added here.
-	 *
-	 * Examples of optional feature group strings:
-	 *
-	 * "Module Device"
-	 * "Processor Device"
-	 * "3.0 Thermal Model"
-	 * "3.0 _SCP Extensions"
-	 * "Processor Aggregator Device"
+	 * by the host) should be dynamically modified to VALID by the host via
+	 * acpi_install_interface or acpi_update_interfaces. Such optional feature
+	 * group strings are set as INVALID by default here.
 	 */
+
+	{"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+	{"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+	{"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+	{"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+	{"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}
 };
 
 /*******************************************************************************
@@ -158,11 +157,20 @@ acpi_status acpi_ut_interface_terminate(void)
 	while (next_interface) {
 		acpi_gbl_supported_interfaces = next_interface->next;
 
-		/* Only interfaces added at runtime can be freed */
-
 		if (next_interface->flags & ACPI_OSI_DYNAMIC) {
+
+			/* Only interfaces added at runtime can be freed */
+
 			ACPI_FREE(next_interface->name);
 			ACPI_FREE(next_interface);
+		} else {
+			/* Interface is in static list. Reset it to invalid or valid. */
+
+			if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) {
+				next_interface->flags |= ACPI_OSI_INVALID;
+			} else {
+				next_interface->flags &= ~ACPI_OSI_INVALID;
+			}
 		}
 
 		next_interface = acpi_gbl_supported_interfaces;
@@ -278,6 +286,49 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name)
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_update_interfaces
+ *
+ * PARAMETERS:  action              - Actions to be performed during the
+ *                                    update
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
+ *              strings or/and feature group strings.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_update_interfaces(u8 action)
+{
+	struct acpi_interface_info *next_interface;
+
+	next_interface = acpi_gbl_supported_interfaces;
+	while (next_interface) {
+		if (((next_interface->flags & ACPI_OSI_FEATURE) &&
+		     (action & ACPI_FEATURE_STRINGS)) ||
+		    (!(next_interface->flags & ACPI_OSI_FEATURE) &&
+		     (action & ACPI_VENDOR_STRINGS))) {
+			if (action & ACPI_DISABLE_INTERFACES) {
+
+				/* Mark the interfaces as invalid */
+
+				next_interface->flags |= ACPI_OSI_INVALID;
+			} else {
+				/* Mark the interfaces as valid */
+
+				next_interface->flags &= ~ACPI_OSI_INVALID;
+			}
+		}
+
+		next_interface = next_interface->next;
+	}
+
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_get_interface
  *
  * PARAMETERS:  interface_name      - The interface to find
diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c
index c53759b..cb1e9cc 100644
--- a/drivers/acpi/acpica/utstring.c
+++ b/drivers/acpi/acpica/utstring.c
@@ -333,7 +333,8 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
  * FUNCTION:    acpi_ut_print_string
  *
  * PARAMETERS:  string          - Null terminated ASCII string
- *              max_length      - Maximum output length
+ *              max_length      - Maximum output length. Used to constrain the
+ *                                length of strings during debug output only.
  *
  * RETURN:      None
  *
@@ -342,7 +343,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
  *
  ******************************************************************************/
 
-void acpi_ut_print_string(char *string, u8 max_length)
+void acpi_ut_print_string(char *string, u16 max_length)
 {
 	u32 i;
 
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 6505774..03a211e 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -389,6 +389,34 @@ ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
 
 /*****************************************************************************
  *
+ * FUNCTION:    acpi_update_interfaces
+ *
+ * PARAMETERS:  action              - Actions to be performed during the
+ *                                    update
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
+ *              string or/and feature group strings.
+ *
+ ****************************************************************************/
+acpi_status acpi_update_interfaces(u8 action)
+{
+	acpi_status status;
+
+	status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	status = acpi_ut_update_interfaces(action);
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+	return (status);
+}
+
+/*****************************************************************************
+ *
  * FUNCTION:    acpi_check_address_range
  *
  * PARAMETERS:  space_id            - Address space ID
@@ -402,6 +430,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
  *              ASL operation region address ranges.
  *
  ****************************************************************************/
+
 u32
 acpi_check_address_range(acpi_adr_space_type space_id,
 			 acpi_physical_address address,
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 88d0b0f..40ffcda 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -39,7 +39,8 @@
 
 #include "apei-internal.h"
 
-#define ERST_PFX "ERST: "
+#undef pr_fmt
+#define pr_fmt(fmt) "ERST: " fmt
 
 /* ERST command status */
 #define ERST_STATUS_SUCCESS			0x0
@@ -109,8 +110,7 @@ static inline int erst_errno(int command_status)
 static int erst_timedout(u64 *t, u64 spin_unit)
 {
 	if ((s64)*t < spin_unit) {
-		pr_warning(FW_WARN ERST_PFX
-			   "Firmware does not respond in time\n");
+		pr_warn(FW_WARN "Firmware does not respond in time.\n");
 		return 1;
 	}
 	*t -= spin_unit;
@@ -186,8 +186,8 @@ static int erst_exec_stall(struct apei_exec_context *ctx,
 
 	if (ctx->value > FIRMWARE_MAX_STALL) {
 		if (!in_nmi())
-			pr_warning(FW_WARN ERST_PFX
-			"Too long stall time for stall instruction: %llx.\n",
+			pr_warn(FW_WARN
+			"Too long stall time for stall instruction: 0x%llx.\n",
 				   ctx->value);
 		stall_time = FIRMWARE_MAX_STALL;
 	} else
@@ -206,8 +206,8 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
 
 	if (ctx->var1 > FIRMWARE_MAX_STALL) {
 		if (!in_nmi())
-			pr_warning(FW_WARN ERST_PFX
-		"Too long stall time for stall while true instruction: %llx.\n",
+			pr_warn(FW_WARN
+		"Too long stall time for stall while true instruction: 0x%llx.\n",
 				   ctx->var1);
 		stall_time = FIRMWARE_MAX_STALL;
 	} else
@@ -271,8 +271,7 @@ static int erst_exec_move_data(struct apei_exec_context *ctx,
 
 	/* ioremap does not work in interrupt context */
 	if (in_interrupt()) {
-		pr_warning(ERST_PFX
-			   "MOVE_DATA can not be used in interrupt context");
+		pr_warn("MOVE_DATA can not be used in interrupt context.\n");
 		return -EBUSY;
 	}
 
@@ -522,8 +521,7 @@ retry:
 				     ERST_RECORD_ID_CACHE_SIZE_MAX);
 		if (new_size <= erst_record_id_cache.size) {
 			if (printk_ratelimit())
-				pr_warning(FW_WARN ERST_PFX
-					   "too many record ID!\n");
+				pr_warn(FW_WARN "too many record IDs!\n");
 			return 0;
 		}
 		alloc_size = new_size * sizeof(entries[0]);
@@ -759,8 +757,7 @@ static int __erst_clear_from_storage(u64 record_id)
 static void pr_unimpl_nvram(void)
 {
 	if (printk_ratelimit())
-		pr_warning(ERST_PFX
-		"NVRAM ERST Log Address Range is not implemented yet\n");
+		pr_warn("NVRAM ERST Log Address Range not implemented yet.\n");
 }
 
 static int __erst_write_to_nvram(const struct cper_record_header *record)
@@ -1120,7 +1117,7 @@ static int __init erst_init(void)
 		goto err;
 
 	if (erst_disable) {
-		pr_info(ERST_PFX
+		pr_info(
 	"Error Record Serialization Table (ERST) support is disabled.\n");
 		goto err;
 	}
@@ -1131,14 +1128,14 @@ static int __init erst_init(void)
 		goto err;
 	else if (ACPI_FAILURE(status)) {
 		const char *msg = acpi_format_exception(status);
-		pr_err(ERST_PFX "Failed to get table, %s\n", msg);
+		pr_err("Failed to get table, %s\n", msg);
 		rc = -EINVAL;
 		goto err;
 	}
 
 	rc = erst_check_table(erst_tab);
 	if (rc) {
-		pr_err(FW_BUG ERST_PFX "ERST table is invalid\n");
+		pr_err(FW_BUG "ERST table is invalid.\n");
 		goto err;
 	}
 
@@ -1156,21 +1153,19 @@ static int __init erst_init(void)
 	rc = erst_get_erange(&erst_erange);
 	if (rc) {
 		if (rc == -ENODEV)
-			pr_info(ERST_PFX
+			pr_info(
 	"The corresponding hardware device or firmware implementation "
 	"is not available.\n");
 		else
-			pr_err(ERST_PFX
-			       "Failed to get Error Log Address Range.\n");
+			pr_err("Failed to get Error Log Address Range.\n");
 		goto err_unmap_reg;
 	}
 
 	r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST");
 	if (!r) {
-		pr_err(ERST_PFX
-		"Can not request iomem region <0x%16llx-0x%16llx> for ERST.\n",
-		(unsigned long long)erst_erange.base,
-		(unsigned long long)erst_erange.base + erst_erange.size);
+		pr_err("Can not request [mem %#010llx-%#010llx] for ERST.\n",
+		       (unsigned long long)erst_erange.base,
+		       (unsigned long long)erst_erange.base + erst_erange.size - 1);
 		rc = -EIO;
 		goto err_unmap_reg;
 	}
@@ -1180,7 +1175,7 @@ static int __init erst_init(void)
 	if (!erst_erange.vaddr)
 		goto err_release_erange;
 
-	pr_info(ERST_PFX
+	pr_info(
 	"Error Record Serialization Table (ERST) support is initialized.\n");
 
 	buf = kmalloc(erst_erange.size, GFP_KERNEL);
@@ -1192,15 +1187,15 @@ static int __init erst_init(void)
 		rc = pstore_register(&erst_info);
 		if (rc) {
 			if (rc != -EPERM)
-				pr_info(ERST_PFX
-				"Could not register with persistent store\n");
+				pr_info(
+				"Could not register with persistent store.\n");
 			erst_info.buf = NULL;
 			erst_info.bufsize = 0;
 			kfree(buf);
 		}
 	} else
-		pr_err(ERST_PFX
-		"Failed to allocate %lld bytes for persistent store error log\n",
+		pr_err(
+		"Failed to allocate %lld bytes for persistent store error log.\n",
 		erst_erange.size);
 
 	return 0;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index ec9b57d..8ec37bb 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -409,6 +409,34 @@ static void ghes_clear_estatus(struct ghes *ghes)
 	ghes->flags &= ~GHES_TO_CLEAR;
 }
 
+static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
+{
+#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
+	unsigned long pfn;
+	int sec_sev = ghes_severity(gdata->error_severity);
+	struct cper_sec_mem_err *mem_err;
+	mem_err = (struct cper_sec_mem_err *)(gdata + 1);
+
+	if (sec_sev == GHES_SEV_CORRECTED &&
+	    (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) &&
+	    (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS)) {
+		pfn = mem_err->physical_addr >> PAGE_SHIFT;
+		if (pfn_valid(pfn))
+			memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE);
+		else if (printk_ratelimit())
+			pr_warn(FW_WARN GHES_PFX
+			"Invalid address in generic error data: %#llx\n",
+			mem_err->physical_addr);
+	}
+	if (sev == GHES_SEV_RECOVERABLE &&
+	    sec_sev == GHES_SEV_RECOVERABLE &&
+	    mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) {
+		pfn = mem_err->physical_addr >> PAGE_SHIFT;
+		memory_failure_queue(pfn, 0, 0);
+	}
+#endif
+}
+
 static void ghes_do_proc(struct ghes *ghes,
 			 const struct acpi_hest_generic_status *estatus)
 {
@@ -428,15 +456,7 @@ static void ghes_do_proc(struct ghes *ghes,
 			apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED,
 						  mem_err);
 #endif
-#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
-			if (sev == GHES_SEV_RECOVERABLE &&
-			    sec_sev == GHES_SEV_RECOVERABLE &&
-			    mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) {
-				unsigned long pfn;
-				pfn = mem_err->physical_addr >> PAGE_SHIFT;
-				memory_failure_queue(pfn, 0, 0);
-			}
-#endif
+			ghes_handle_memory_failure(gdata, sev);
 		}
 #ifdef CONFIG_ACPI_APEI_PCIEAER
 		else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index f5ef5d5..5020245 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <acpi/apei.h>
+#include <asm/mce.h>
 
 #include "apei-internal.h"
 
@@ -121,6 +122,40 @@ int apei_hest_parse(apei_hest_func_t func, void *data)
 }
 EXPORT_SYMBOL_GPL(apei_hest_parse);
 
+/*
+ * Check if firmware advertises firmware first mode. We need FF bit to be set
+ * along with a set of MC banks which work in FF mode.
+ */
+static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data)
+{
+	int i;
+	struct acpi_hest_ia_corrected *cmc;
+	struct acpi_hest_ia_error_bank *mc_bank;
+
+	if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
+		return 0;
+
+	cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
+	if (!cmc->enabled)
+		return 0;
+
+	/*
+	 * We expect HEST to provide a list of MC banks that report errors
+	 * in firmware first mode. Otherwise, return non-zero value to
+	 * indicate that we are done parsing HEST.
+	 */
+	if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) || !cmc->num_hardware_banks)
+		return 1;
+
+	pr_info(HEST_PFX "Enabling Firmware First mode for corrected errors.\n");
+
+	mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1);
+	for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++)
+		mce_disable_bank(mc_bank->bank_number);
+
+	return 1;
+}
+
 struct ghes_arr {
 	struct platform_device **ghes_devs;
 	unsigned int count;
@@ -227,6 +262,9 @@ void __init acpi_hest_init(void)
 		goto err;
 	}
 
+	if (!acpi_disable_cmcff)
+		apei_hest_parse(hest_parse_cmc, NULL);
+
 	if (!ghes_disable) {
 		rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
 		if (rc)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index d405fba..2c9958c 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -527,18 +527,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
 static int acpi_battery_set_alarm(struct acpi_battery *battery)
 {
 	acpi_status status = 0;
-	union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
-	struct acpi_object_list arg_list = { 1, &arg0 };
 
 	if (!acpi_battery_present(battery) ||
 	    !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
 		return -ENODEV;
 
-	arg0.integer.value = battery->alarm;
-
 	mutex_lock(&battery->lock);
-	status = acpi_evaluate_object(battery->device->handle, "_BTP",
-				 &arg_list, NULL);
+	status = acpi_execute_simple_method(battery->device->handle, "_BTP",
+					    battery->alarm);
 	mutex_unlock(&battery->lock);
 
 	if (ACPI_FAILURE(status))
@@ -550,12 +546,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
 
 static int acpi_battery_init_alarm(struct acpi_battery *battery)
 {
-	acpi_status status = AE_OK;
-	acpi_handle handle = NULL;
-
 	/* See if alarms are supported, and if so, set default */
-	status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
-	if (ACPI_FAILURE(status)) {
+	if (!acpi_has_method(battery->device->handle, "_BTP")) {
 		clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
 		return 0;
 	}
@@ -1036,8 +1028,6 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
 	if (event == ACPI_BATTERY_NOTIFY_INFO)
 		acpi_battery_refresh(battery);
 	acpi_battery_update(battery);
-	acpi_bus_generate_proc_event(device, event,
-				     acpi_battery_present(battery));
 	acpi_bus_generate_netlink_event(device->pnp.device_class,
 					dev_name(&device->dev), event,
 					acpi_battery_present(battery));
@@ -1068,7 +1058,7 @@ static int acpi_battery_add(struct acpi_device *device)
 {
 	int result = 0;
 	struct acpi_battery *battery = NULL;
-	acpi_handle handle;
+
 	if (!device)
 		return -EINVAL;
 	battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
@@ -1080,8 +1070,7 @@ static int acpi_battery_add(struct acpi_device *device)
 	device->driver_data = battery;
 	mutex_init(&battery->lock);
 	mutex_init(&battery->sysfs_lock);
-	if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
-			"_BIX", &handle)))
+	if (acpi_has_method(battery->device->handle, "_BIX"))
 		set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
 	result = acpi_battery_update(battery);
 	if (result)
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index cb96296..a404127 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -192,6 +192,12 @@ static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
 	acpi_osi_setup("!Windows 2009");
 	return 0;
 }
+static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
+	acpi_osi_setup("!Windows 2012");
+	return 0;
+}
 
 static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	{
@@ -267,6 +273,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 		     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
 		},
 	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "ASUS Zenbook Prime UX31A",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
+		},
+	},
 
 	/*
 	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index a5bb33b..b587ec8 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -89,27 +89,6 @@ static struct dmi_system_id dsdt_dmi_table[] __initdata = {
                                 Device Management
    -------------------------------------------------------------------------- */
 
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
-{
-	acpi_status status;
-
-	if (!device)
-		return -EINVAL;
-
-	/* TBD: Support fixed-feature devices */
-
-	status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
-	if (ACPI_FAILURE(status) || !*device) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
-				  handle));
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-EXPORT_SYMBOL(acpi_bus_get_device);
-
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
 				       unsigned long long *sta)
 {
@@ -346,104 +325,6 @@ static void acpi_bus_osc_support(void)
 }
 
 /* --------------------------------------------------------------------------
-                                Event Management
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROC_EVENT
-static DEFINE_SPINLOCK(acpi_bus_event_lock);
-
-LIST_HEAD(acpi_bus_event_list);
-DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
-
-extern int event_is_open;
-
-int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
-{
-	struct acpi_bus_event *event;
-	unsigned long flags;
-
-	/* drop event on the floor if no one's listening */
-	if (!event_is_open)
-		return 0;
-
-	event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
-	if (!event)
-		return -ENOMEM;
-
-	strcpy(event->device_class, device_class);
-	strcpy(event->bus_id, bus_id);
-	event->type = type;
-	event->data = data;
-
-	spin_lock_irqsave(&acpi_bus_event_lock, flags);
-	list_add_tail(&event->node, &acpi_bus_event_list);
-	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
-
-	wake_up_interruptible(&acpi_bus_event_queue);
-
-	return 0;
-
-}
-
-EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);
-
-int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
-{
-	if (!device)
-		return -EINVAL;
-	return acpi_bus_generate_proc_event4(device->pnp.device_class,
-					     device->pnp.bus_id, type, data);
-}
-
-EXPORT_SYMBOL(acpi_bus_generate_proc_event);
-
-int acpi_bus_receive_event(struct acpi_bus_event *event)
-{
-	unsigned long flags;
-	struct acpi_bus_event *entry = NULL;
-
-	DECLARE_WAITQUEUE(wait, current);
-
-
-	if (!event)
-		return -EINVAL;
-
-	if (list_empty(&acpi_bus_event_list)) {
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&acpi_bus_event_queue, &wait);
-
-		if (list_empty(&acpi_bus_event_list))
-			schedule();
-
-		remove_wait_queue(&acpi_bus_event_queue, &wait);
-		set_current_state(TASK_RUNNING);
-
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-	}
-
-	spin_lock_irqsave(&acpi_bus_event_lock, flags);
-	if (!list_empty(&acpi_bus_event_list)) {
-		entry = list_entry(acpi_bus_event_list.next,
-				   struct acpi_bus_event, node);
-		list_del(&entry->node);
-	}
-	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
-
-	if (!entry)
-		return -ENODEV;
-
-	memcpy(event, entry, sizeof(struct acpi_bus_event));
-
-	kfree(entry);
-
-	return 0;
-}
-
-#endif	/* CONFIG_ACPI_PROC_EVENT */
-
-/* --------------------------------------------------------------------------
                              Notification Handling
    -------------------------------------------------------------------------- */
 
@@ -499,19 +380,6 @@ static void acpi_bus_check_scope(acpi_handle handle)
 	 */
 }
 
-static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
-int register_acpi_bus_notifier(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
-}
-EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
-
-void unregister_acpi_bus_notifier(struct notifier_block *nb)
-{
-	blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
-
 /**
  * acpi_bus_notify
  * ---------------
@@ -525,9 +393,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
 			  type, handle));
 
-	blocking_notifier_call_chain(&acpi_bus_notify_list,
-		type, (void *)handle);
-
 	switch (type) {
 
 	case ACPI_NOTIFY_BUS_CHECK:
@@ -593,8 +458,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 static int __init acpi_bus_init_irq(void)
 {
 	acpi_status status;
-	union acpi_object arg = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list arg_list = { 1, &arg };
 	char *message = NULL;
 
 
@@ -623,9 +486,7 @@ static int __init acpi_bus_init_irq(void)
 
 	printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);
 
-	arg.integer.value = acpi_irq_model;
-
-	status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
+	status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model);
 	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
 		return -ENODEV;
@@ -715,7 +576,6 @@ static int __init acpi_bus_init(void)
 {
 	int result;
 	acpi_status status;
-	extern acpi_status acpi_os_initialize1(void);
 
 	acpi_os_initialize1();
 
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index d2e617b..a557738 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -303,8 +303,6 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 
 			pm_wakeup_event(&device->dev, 0);
 		}
-
-		acpi_bus_generate_proc_event(device, event, ++button->pushed);
 		break;
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 4ab807d..59d3202 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -159,26 +159,29 @@ int acpi_device_set_power(struct acpi_device *device, int state)
 	int result = 0;
 	bool cut_power = false;
 
-	if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
+	if (!device || !device->flags.power_manageable
+	    || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
 		return -EINVAL;
 
 	/* Make sure this is a valid target state */
 
 	if (state == device->power.state) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n",
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already in %s\n",
+				  device->pnp.bus_id,
 				  acpi_power_state_string(state)));
 		return 0;
 	}
 
 	if (!device->power.states[state].flags.valid) {
-		printk(KERN_WARNING PREFIX "Device does not support %s\n",
-		       acpi_power_state_string(state));
+		dev_warn(&device->dev, "Power state %s not supported\n",
+			 acpi_power_state_string(state));
 		return -ENODEV;
 	}
 	if (device->parent && (state < device->parent->power.state)) {
-		printk(KERN_WARNING PREFIX
-			      "Cannot set device to a higher-powered"
-			      " state than parent\n");
+		dev_warn(&device->dev,
+			 "Cannot transition to power state %s for parent in %s\n",
+			 acpi_power_state_string(state),
+			 acpi_power_state_string(device->parent->power.state));
 		return -ENODEV;
 	}
 
@@ -191,8 +194,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
 
 	if (state < device->power.state && state != ACPI_STATE_D0
 	    && device->power.state >= ACPI_STATE_D3_HOT) {
-		printk(KERN_WARNING PREFIX
-			"Cannot transition to non-D0 state from D3\n");
+		dev_warn(&device->dev,
+			 "Cannot transition to non-D0 state from D3\n");
 		return -ENODEV;
 	}
 
@@ -219,10 +222,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
 
  end:
 	if (result) {
-		printk(KERN_WARNING PREFIX
-			      "Device [%s] failed to transition to %s\n",
-			      device->pnp.bus_id,
-			      acpi_power_state_string(state));
+		dev_warn(&device->dev, "Failed to change power state to %s\n",
+			 acpi_power_state_string(state));
 	} else {
 		device->power.state = state;
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -244,13 +245,6 @@ int acpi_bus_set_power(acpi_handle handle, int state)
 	if (result)
 		return result;
 
-	if (!device->flags.power_manageable) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				"Device [%s] is not power manageable\n",
-				dev_name(&device->dev)));
-		return -ENODEV;
-	}
-
 	return acpi_device_set_power(device, state);
 }
 EXPORT_SYMBOL(acpi_bus_set_power);
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 8265607..b527c1b 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -51,8 +51,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
 	" the driver to wait for userspace to write the undock sysfs file "
 	" before undocking");
 
-static struct atomic_notifier_head dock_notifier_list;
-
 static const struct acpi_device_id dock_device_ids[] = {
 	{"LNXDOCK", 0},
 	{"", 0},
@@ -63,8 +61,6 @@ struct dock_station {
 	acpi_handle handle;
 	unsigned long last_dock_time;
 	u32 flags;
-	spinlock_t dd_lock;
-	struct mutex hp_lock;
 	struct list_head dependent_devices;
 
 	struct list_head sibling;
@@ -91,6 +87,12 @@ struct dock_dependent_device {
 #define DOCK_EVENT	3
 #define UNDOCK_EVENT	2
 
+enum dock_callback_type {
+	DOCK_CALL_HANDLER,
+	DOCK_CALL_FIXUP,
+	DOCK_CALL_UEVENT,
+};
+
 /*****************************************************************************
  *                         Dock Dependent device functions                   *
  *****************************************************************************/
@@ -101,7 +103,7 @@ struct dock_dependent_device {
  *
  * Add the dependent device to the dock's dependent device list.
  */
-static int
+static int __init
 add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 {
 	struct dock_dependent_device *dd;
@@ -112,14 +114,21 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 
 	dd->handle = handle;
 	INIT_LIST_HEAD(&dd->list);
-
-	spin_lock(&ds->dd_lock);
 	list_add_tail(&dd->list, &ds->dependent_devices);
-	spin_unlock(&ds->dd_lock);
 
 	return 0;
 }
 
+static void remove_dock_dependent_devices(struct dock_station *ds)
+{
+	struct dock_dependent_device *dd, *aux;
+
+	list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) {
+		list_del(&dd->list);
+		kfree(dd);
+	}
+}
+
 /**
  * dock_init_hotplug - Initialize a hotplug device on a docking station.
  * @dd: Dock-dependent device.
@@ -135,19 +144,16 @@ static int dock_init_hotplug(struct dock_dependent_device *dd,
 	int ret = 0;
 
 	mutex_lock(&hotplug_lock);
-
-	if (dd->hp_context) {
+	if (WARN_ON(dd->hp_context)) {
 		ret = -EEXIST;
 	} else {
 		dd->hp_refcount = 1;
 		dd->hp_ops = ops;
 		dd->hp_context = context;
 		dd->hp_release = release;
+		if (init)
+			init(context);
 	}
-
-	if (!WARN_ON(ret) && init)
-		init(context);
-
 	mutex_unlock(&hotplug_lock);
 	return ret;
 }
@@ -162,27 +168,22 @@ static int dock_init_hotplug(struct dock_dependent_device *dd,
  */
 static void dock_release_hotplug(struct dock_dependent_device *dd)
 {
-	void (*release)(void *) = NULL;
-	void *context = NULL;
-
 	mutex_lock(&hotplug_lock);
-
 	if (dd->hp_context && !--dd->hp_refcount) {
+		void (*release)(void *) = dd->hp_release;
+		void *context = dd->hp_context;
+
 		dd->hp_ops = NULL;
-		context = dd->hp_context;
 		dd->hp_context = NULL;
-		release = dd->hp_release;
 		dd->hp_release = NULL;
+		if (release)
+			release(context);
 	}
-
-	if (release && context)
-		release(context);
-
 	mutex_unlock(&hotplug_lock);
 }
 
 static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
-			       bool uevent)
+			       enum dock_callback_type cb_type)
 {
 	acpi_notify_handler cb = NULL;
 	bool run = false;
@@ -192,8 +193,18 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
 	if (dd->hp_context) {
 		run = true;
 		dd->hp_refcount++;
-		if (dd->hp_ops)
-			cb = uevent ? dd->hp_ops->uevent : dd->hp_ops->handler;
+		if (dd->hp_ops) {
+			switch (cb_type) {
+			case DOCK_CALL_FIXUP:
+				cb = dd->hp_ops->fixup;
+				break;
+			case DOCK_CALL_UEVENT:
+				cb = dd->hp_ops->uevent;
+				break;
+			default:
+				cb = dd->hp_ops->handler;
+			}
+		}
 	}
 
 	mutex_unlock(&hotplug_lock);
@@ -220,63 +231,17 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 {
 	struct dock_dependent_device *dd;
 
-	spin_lock(&ds->dd_lock);
-	list_for_each_entry(dd, &ds->dependent_devices, list) {
-		if (handle == dd->handle) {
-			spin_unlock(&ds->dd_lock);
+	list_for_each_entry(dd, &ds->dependent_devices, list)
+		if (handle == dd->handle)
 			return dd;
-		}
-	}
-	spin_unlock(&ds->dd_lock);
+
 	return NULL;
 }
 
 /*****************************************************************************
  *                         Dock functions                                    *
  *****************************************************************************/
-/**
- * is_dock - see if a device is a dock station
- * @handle: acpi handle of the device
- *
- * If an acpi object has a _DCK method, then it is by definition a dock
- * station, so return true.
- */
-static int is_dock(acpi_handle handle)
-{
-	acpi_status status;
-	acpi_handle tmp;
-
-	status = acpi_get_handle(handle, "_DCK", &tmp);
-	if (ACPI_FAILURE(status))
-		return 0;
-	return 1;
-}
-
-static int is_ejectable(acpi_handle handle)
-{
-	acpi_status status;
-	acpi_handle tmp;
-
-	status = acpi_get_handle(handle, "_EJ0", &tmp);
-	if (ACPI_FAILURE(status))
-		return 0;
-	return 1;
-}
-
-static int is_ata(acpi_handle handle)
-{
-	acpi_handle tmp;
-
-	if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
-	   (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
-	   (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
-	   (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
-		return 1;
-
-	return 0;
-}
-
-static int is_battery(acpi_handle handle)
+static int __init is_battery(acpi_handle handle)
 {
 	struct acpi_device_info *info;
 	int ret = 1;
@@ -292,17 +257,13 @@ static int is_battery(acpi_handle handle)
 	return ret;
 }
 
-static int is_ejectable_bay(acpi_handle handle)
+/* Check whether ACPI object is an ejectable battery or disk bay */
+static bool __init is_ejectable_bay(acpi_handle handle)
 {
-	acpi_handle phandle;
+	if (acpi_has_method(handle, "_EJ0") && is_battery(handle))
+		return true;
 
-	if (!is_ejectable(handle))
-		return 0;
-	if (is_battery(handle) || is_ata(handle))
-		return 1;
-	if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
-		return 1;
-	return 0;
+	return acpi_bay_match(handle);
 }
 
 /**
@@ -320,7 +281,7 @@ int is_dock_device(acpi_handle handle)
 	if (!dock_station_count)
 		return 0;
 
-	if (is_dock(handle))
+	if (acpi_dock_match(handle))
 		return 1;
 
 	list_for_each_entry(dock_station, &dock_stations, sibling)
@@ -359,10 +320,8 @@ static int dock_present(struct dock_station *ds)
  *  handle if one does not exist already.  This should cause
  *  acpi to scan for drivers for the given devices, and call
  *  matching driver's add routine.
- *
- *  Returns a pointer to the acpi_device corresponding to the handle.
  */
-static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
+static void dock_create_acpi_device(acpi_handle handle)
 {
 	struct acpi_device *device;
 	int ret;
@@ -375,10 +334,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
 		ret = acpi_bus_scan(handle);
 		if (ret)
 			pr_debug("error adding bus, %x\n", -ret);
-
-		acpi_bus_get_device(handle, &device);
 	}
-	return device;
 }
 
 /**
@@ -397,9 +353,29 @@ static void dock_remove_acpi_device(acpi_handle handle)
 }
 
 /**
- * hotplug_dock_devices - insert or remove devices on the dock station
+ * hot_remove_dock_devices - Remove dock station devices.
+ * @ds: Dock station.
+ */
+static void hot_remove_dock_devices(struct dock_station *ds)
+{
+	struct dock_dependent_device *dd;
+
+	/*
+	 * Walk the list in reverse order so that devices that have been added
+	 * last are removed first (in case there are some indirect dependencies
+	 * between them).
+	 */
+	list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
+		dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
+
+	list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
+		dock_remove_acpi_device(dd->handle);
+}
+
+/**
+ * hotplug_dock_devices - Insert devices on a dock station.
  * @ds: the dock station
- * @event: either bus check or eject request
+ * @event: either bus check or device check request
  *
  * Some devices on the dock station need to have drivers called
  * to perform hotplug operations after a dock event has occurred.
@@ -410,27 +386,21 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
 {
 	struct dock_dependent_device *dd;
 
-	mutex_lock(&ds->hp_lock);
+	/* Call driver specific post-dock fixups. */
+	list_for_each_entry(dd, &ds->dependent_devices, list)
+		dock_hotplug_event(dd, event, DOCK_CALL_FIXUP);
 
-	/*
-	 * First call driver specific hotplug functions
-	 */
+	/* Call driver specific hotplug functions. */
 	list_for_each_entry(dd, &ds->dependent_devices, list)
-		dock_hotplug_event(dd, event, false);
+		dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
 
 	/*
-	 * Now make sure that an acpi_device is created for each
-	 * dependent device, or removed if this is an eject request.
-	 * This will cause acpi_drivers to be stopped/started if they
-	 * exist
+	 * Now make sure that an acpi_device is created for each dependent
+	 * device.  That will cause scan handlers to be attached to device
+	 * objects or acpi_drivers to be stopped/started if they are present.
 	 */
-	list_for_each_entry(dd, &ds->dependent_devices, list) {
-		if (event == ACPI_NOTIFY_EJECT_REQUEST)
-			dock_remove_acpi_device(dd->handle);
-		else
-			dock_create_acpi_device(dd->handle);
-	}
-	mutex_unlock(&ds->hp_lock);
+	list_for_each_entry(dd, &ds->dependent_devices, list)
+		dock_create_acpi_device(dd->handle);
 }
 
 static void dock_event(struct dock_station *ds, u32 event, int num)
@@ -453,44 +423,13 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
 		kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 
 	list_for_each_entry(dd, &ds->dependent_devices, list)
-		dock_hotplug_event(dd, event, true);
+		dock_hotplug_event(dd, event, DOCK_CALL_UEVENT);
 
 	if (num != DOCK_EVENT)
 		kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
 
 /**
- * eject_dock - respond to a dock eject request
- * @ds: the dock station
- *
- * This is called after _DCK is called, to execute the dock station's
- * _EJ0 method.
- */
-static void eject_dock(struct dock_station *ds)
-{
-	struct acpi_object_list arg_list;
-	union acpi_object arg;
-	acpi_status status;
-	acpi_handle tmp;
-
-	/* all dock devices should have _EJ0, but check anyway */
-	status = acpi_get_handle(ds->handle, "_EJ0", &tmp);
-	if (ACPI_FAILURE(status)) {
-		pr_debug("No _EJ0 support for dock device\n");
-		return;
-	}
-
-	arg_list.count = 1;
-	arg_list.pointer = &arg;
-	arg.type = ACPI_TYPE_INTEGER;
-	arg.integer.value = 1;
-
-	status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL);
-	if (ACPI_FAILURE(status))
-		pr_debug("Failed to evaluate _EJ0!\n");
-}
-
-/**
  * handle_dock - handle a dock event
  * @ds: the dock station
  * @dock: to dock, or undock - that is the question
@@ -550,27 +489,6 @@ static inline void complete_undock(struct dock_station *ds)
 	ds->flags &= ~(DOCK_UNDOCKING);
 }
 
-static void dock_lock(struct dock_station *ds, int lock)
-{
-	struct acpi_object_list arg_list;
-	union acpi_object arg;
-	acpi_status status;
-
-	arg_list.count = 1;
-	arg_list.pointer = &arg;
-	arg.type = ACPI_TYPE_INTEGER;
-	arg.integer.value = !!lock;
-	status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		if (lock)
-			acpi_handle_warn(ds->handle,
-				"Locking device failed (0x%x)\n", status);
-		else
-			acpi_handle_warn(ds->handle,
-				"Unlocking device failed (0x%x)\n", status);
-	}
-}
-
 /**
  * dock_in_progress - see if we are in the middle of handling a dock event
  * @ds: the dock station
@@ -588,37 +506,6 @@ static int dock_in_progress(struct dock_station *ds)
 }
 
 /**
- * register_dock_notifier - add yourself to the dock notifier list
- * @nb: the callers notifier block
- *
- * If a driver wishes to be notified about dock events, they can
- * use this function to put a notifier block on the dock notifier list.
- * this notifier call chain will be called after a dock event, but
- * before hotplugging any new devices.
- */
-int register_dock_notifier(struct notifier_block *nb)
-{
-	if (!dock_station_count)
-		return -ENODEV;
-
-	return atomic_notifier_chain_register(&dock_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(register_dock_notifier);
-
-/**
- * unregister_dock_notifier - remove yourself from the dock notifier list
- * @nb: the callers notifier block
- */
-void unregister_dock_notifier(struct notifier_block *nb)
-{
-	if (!dock_station_count)
-		return;
-
-	atomic_notifier_chain_unregister(&dock_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_dock_notifier);
-
-/**
  * register_hotplug_dock_device - register a hotplug function
  * @handle: the handle of the device
  * @ops: handlers to call after docking
@@ -703,10 +590,10 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
 	 */
 	dock_event(ds, event, UNDOCK_EVENT);
 
-	hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
+	hot_remove_dock_devices(ds);
 	undock(ds);
-	dock_lock(ds, 0);
-	eject_dock(ds);
+	acpi_evaluate_lck(ds->handle, 0);
+	acpi_evaluate_ej0(ds->handle);
 	if (dock_present(ds)) {
 		acpi_handle_err(ds->handle, "Unable to undock!\n");
 		return -EBUSY;
@@ -717,18 +604,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
 
 /**
  * dock_notify - act upon an acpi dock notification
- * @handle: the dock station handle
+ * @ds: dock station
  * @event: the acpi event
- * @data: our driver data struct
  *
  * If we are notified to dock, then check to see if the dock is
  * present and then dock.  Notify all drivers of the dock event,
  * and then hotplug and devices that may need hotplugging.
  */
-static void dock_notify(acpi_handle handle, u32 event, void *data)
+static void dock_notify(struct dock_station *ds, u32 event)
 {
-	struct dock_station *ds = data;
-	struct acpi_device *tmp;
+	acpi_handle handle = ds->handle;
+	struct acpi_device *ad;
 	int surprise_removal = 0;
 
 	/*
@@ -751,8 +637,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
 	switch (event) {
 	case ACPI_NOTIFY_BUS_CHECK:
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
-		   &tmp)) {
+		if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) {
 			begin_dock(ds);
 			dock(ds);
 			if (!dock_present(ds)) {
@@ -760,12 +645,10 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
 				complete_dock(ds);
 				break;
 			}
-			atomic_notifier_call_chain(&dock_notifier_list,
-						   event, NULL);
 			hotplug_dock_devices(ds, event);
 			complete_dock(ds);
 			dock_event(ds, event, DOCK_EVENT);
-			dock_lock(ds, 1);
+			acpi_evaluate_lck(ds->handle, 1);
 			acpi_update_all_gpes();
 			break;
 		}
@@ -789,9 +672,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
 }
 
 struct dock_data {
-	acpi_handle handle;
-	unsigned long event;
 	struct dock_station *ds;
+	u32 event;
 };
 
 static void acpi_dock_deferred_cb(void *context)
@@ -799,52 +681,31 @@ static void acpi_dock_deferred_cb(void *context)
 	struct dock_data *data = context;
 
 	acpi_scan_lock_acquire();
-	dock_notify(data->handle, data->event, data->ds);
+	dock_notify(data->ds, data->event);
 	acpi_scan_lock_release();
 	kfree(data);
 }
 
-static int acpi_dock_notifier_call(struct notifier_block *this,
-	unsigned long event, void *data)
+static void dock_notify_handler(acpi_handle handle, u32 event, void *data)
 {
-	struct dock_station *dock_station;
-	acpi_handle handle = data;
+	struct dock_data *dd;
 
 	if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
 	   && event != ACPI_NOTIFY_EJECT_REQUEST)
-		return 0;
-
-	acpi_scan_lock_acquire();
-
-	list_for_each_entry(dock_station, &dock_stations, sibling) {
-		if (dock_station->handle == handle) {
-			struct dock_data *dd;
-			acpi_status status;
-
-			dd = kmalloc(sizeof(*dd), GFP_KERNEL);
-			if (!dd)
-				break;
+		return;
 
-			dd->handle = handle;
-			dd->event = event;
-			dd->ds = dock_station;
-			status = acpi_os_hotplug_execute(acpi_dock_deferred_cb,
-							 dd);
-			if (ACPI_FAILURE(status))
-				kfree(dd);
+	dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+	if (dd) {
+		acpi_status status;
 
-			break;
-		}
+		dd->ds = data;
+		dd->event = event;
+		status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
+		if (ACPI_FAILURE(status))
+			kfree(dd);
 	}
-
-	acpi_scan_lock_release();
-	return 0;
 }
 
-static struct notifier_block dock_acpi_notifier = {
-	.notifier_call = acpi_dock_notifier_call,
-};
-
 /**
  * find_dock_devices - find devices on the dock station
  * @handle: the handle of the device we are examining
@@ -856,29 +717,16 @@ static struct notifier_block dock_acpi_notifier = {
  * check to see if an object has an _EJD method.  If it does, then it
  * will see if it is dependent on the dock station.
  */
-static acpi_status
-find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
+static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl,
+					    void *context, void **rv)
 {
-	acpi_status status;
-	acpi_handle tmp, parent;
 	struct dock_station *ds = context;
+	acpi_handle ejd = NULL;
 
-	status = acpi_bus_get_ejd(handle, &tmp);
-	if (ACPI_FAILURE(status)) {
-		/* try the parent device as well */
-		status = acpi_get_parent(handle, &parent);
-		if (ACPI_FAILURE(status))
-			goto fdd_out;
-		/* see if parent is dependent on dock */
-		status = acpi_bus_get_ejd(parent, &tmp);
-		if (ACPI_FAILURE(status))
-			goto fdd_out;
-	}
-
-	if (tmp == ds->handle)
+	acpi_bus_get_ejd(handle, &ejd);
+	if (ejd == ds->handle)
 		add_dock_dependent_device(ds, handle);
 
-fdd_out:
 	return AE_OK;
 }
 
@@ -988,13 +836,13 @@ static struct attribute_group dock_attribute_group = {
  */
 static int __init dock_add(acpi_handle handle)
 {
-	int ret, id;
-	struct dock_station ds, *dock_station;
+	struct dock_station *dock_station, ds = { NULL, };
 	struct platform_device *dd;
+	acpi_status status;
+	int ret;
 
-	id = dock_station_count;
-	memset(&ds, 0, sizeof(ds));
-	dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds));
+	dd = platform_device_register_data(NULL, "dock", dock_station_count,
+					   &ds, sizeof(ds));
 	if (IS_ERR(dd))
 		return PTR_ERR(dd);
 
@@ -1004,18 +852,15 @@ static int __init dock_add(acpi_handle handle)
 	dock_station->dock_device = dd;
 	dock_station->last_dock_time = jiffies - HZ;
 
-	mutex_init(&dock_station->hp_lock);
-	spin_lock_init(&dock_station->dd_lock);
 	INIT_LIST_HEAD(&dock_station->sibling);
-	ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
 	INIT_LIST_HEAD(&dock_station->dependent_devices);
 
 	/* we want the dock device to send uevents */
 	dev_set_uevent_suppress(&dd->dev, 0);
 
-	if (is_dock(handle))
+	if (acpi_dock_match(handle))
 		dock_station->flags |= DOCK_IS_DOCK;
-	if (is_ata(handle))
+	if (acpi_ata_match(handle))
 		dock_station->flags |= DOCK_IS_ATA;
 	if (is_battery(handle))
 		dock_station->flags |= DOCK_IS_BAT;
@@ -1034,11 +879,19 @@ static int __init dock_add(acpi_handle handle)
 	if (ret)
 		goto err_rmgroup;
 
+	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					     dock_notify_handler, dock_station);
+	if (ACPI_FAILURE(status)) {
+		ret = -ENODEV;
+		goto err_rmgroup;
+	}
+
 	dock_station_count++;
 	list_add(&dock_station->sibling, &dock_stations);
 	return 0;
 
 err_rmgroup:
+	remove_dock_dependent_devices(dock_station);
 	sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
 err_unregister:
 	platform_device_unregister(dd);
@@ -1058,7 +911,7 @@ err_unregister:
 static __init acpi_status
 find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-	if (is_dock(handle) || is_ejectable_bay(handle))
+	if (acpi_dock_match(handle) || is_ejectable_bay(handle))
 		dock_add(handle);
 
 	return AE_OK;
@@ -1078,7 +931,6 @@ void __init acpi_dock_init(void)
 		return;
 	}
 
-	register_acpi_bus_notifier(&dock_acpi_notifier);
 	pr_info(PREFIX "%s: %d docks/bays found\n",
 		ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
 }
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 80403c1..8dd2d4d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -948,7 +948,7 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
 	return 0;
 }
 
-static struct dmi_system_id __initdata ec_dmi_table[] = {
+static struct dmi_system_id ec_dmi_table[] __initdata = {
 	{
 	ec_skip_dsdt_scan, "Compal JFL92", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
@@ -1049,10 +1049,8 @@ int __init acpi_ec_ecdt_probe(void)
 		* which needs it, has fake EC._INI method, so use it as flag.
 		* Keep boot_ec struct as it will be needed soon.
 		*/
-		acpi_handle dummy;
 		if (!dmi_name_in_vendors("ASUS") ||
-		    ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI",
-							&dummy)))
+		    !acpi_has_method(boot_ec->handle, "_INI"))
 			return -ENODEV;
 	}
 install:
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 1442737..8247fcd 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -21,100 +21,6 @@
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME("event");
 
-#ifdef CONFIG_ACPI_PROC_EVENT
-/* Global vars for handling event proc entry */
-static DEFINE_SPINLOCK(acpi_system_event_lock);
-int event_is_open = 0;
-extern struct list_head acpi_bus_event_list;
-extern wait_queue_head_t acpi_bus_event_queue;
-
-static int acpi_system_open_event(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&acpi_system_event_lock);
-
-	if (event_is_open)
-		goto out_busy;
-
-	event_is_open = 1;
-
-	spin_unlock_irq(&acpi_system_event_lock);
-	return 0;
-
-      out_busy:
-	spin_unlock_irq(&acpi_system_event_lock);
-	return -EBUSY;
-}
-
-static ssize_t
-acpi_system_read_event(struct file *file, char __user * buffer, size_t count,
-		       loff_t * ppos)
-{
-	int result = 0;
-	struct acpi_bus_event event;
-	static char str[ACPI_MAX_STRING];
-	static int chars_remaining = 0;
-	static char *ptr;
-
-	if (!chars_remaining) {
-		memset(&event, 0, sizeof(struct acpi_bus_event));
-
-		if ((file->f_flags & O_NONBLOCK)
-		    && (list_empty(&acpi_bus_event_list)))
-			return -EAGAIN;
-
-		result = acpi_bus_receive_event(&event);
-		if (result)
-			return result;
-
-		chars_remaining = sprintf(str, "%s %s %08x %08x\n",
-					  event.device_class ? event.
-					  device_class : "<unknown>",
-					  event.bus_id ? event.
-					  bus_id : "<unknown>", event.type,
-					  event.data);
-		ptr = str;
-	}
-
-	if (chars_remaining < count) {
-		count = chars_remaining;
-	}
-
-	if (copy_to_user(buffer, ptr, count))
-		return -EFAULT;
-
-	*ppos += count;
-	chars_remaining -= count;
-	ptr += count;
-
-	return count;
-}
-
-static int acpi_system_close_event(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&acpi_system_event_lock);
-	event_is_open = 0;
-	spin_unlock_irq(&acpi_system_event_lock);
-	return 0;
-}
-
-static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
-{
-	poll_wait(file, &acpi_bus_event_queue, wait);
-	if (!list_empty(&acpi_bus_event_list))
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static const struct file_operations acpi_system_event_ops = {
-	.owner = THIS_MODULE,
-	.open = acpi_system_open_event,
-	.read = acpi_system_read_event,
-	.release = acpi_system_close_event,
-	.poll = acpi_system_poll_event,
-	.llseek = default_llseek,
-};
-#endif	/* CONFIG_ACPI_PROC_EVENT */
-
 /* ACPI notifier chain */
 static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
 
@@ -280,9 +186,6 @@ static int acpi_event_genetlink_init(void)
 
 static int __init acpi_event_init(void)
 {
-#ifdef CONFIG_ACPI_PROC_EVENT
-	struct proc_dir_entry *entry;
-#endif
 	int error = 0;
 
 	if (acpi_disabled)
@@ -293,15 +196,6 @@ static int __init acpi_event_init(void)
 	if (error)
 		printk(KERN_WARNING PREFIX
 		       "Failed to create genetlink family for ACPI event\n");
-
-#ifdef CONFIG_ACPI_PROC_EVENT
-	/* 'event' [R] */
-	entry = proc_create("event", S_IRUSR, acpi_root_dir,
-			    &acpi_system_event_ops);
-	if (!entry)
-		return -ENODEV;
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 5b02a0a..41ade65 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -93,7 +93,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
 	if (result)
 		return result;
 
-	*state = (acpi_state == ACPI_STATE_D3 ? 0 :
+	*state = (acpi_state == ACPI_STATE_D3_COLD ? 0 :
 		 (acpi_state == ACPI_STATE_D0 ? 1 : -1));
 	return 0;
 }
@@ -108,7 +108,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
 		return -EINVAL;
 
 	result = acpi_bus_set_power(device->handle,
-				state ? ACPI_STATE_D0 : ACPI_STATE_D3);
+				state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
 
 	return result;
 }
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index f680957..dcba319 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -31,6 +31,7 @@ static LIST_HEAD(bus_type_list);
 static DECLARE_RWSEM(bus_type_sem);
 
 #define PHYSICAL_NODE_STRING "physical_node"
+#define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10)
 
 int register_acpi_bus_type(struct acpi_bus_type *type)
 {
@@ -78,41 +79,117 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
 	return ret;
 }
 
-static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
-				      void *addr_p, void **ret_p)
+static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used,
+				  void *not_used, void **ret_p)
 {
-	unsigned long long addr, sta;
+	struct acpi_device *adev = NULL;
+
+	acpi_bus_get_device(handle, &adev);
+	if (adev) {
+		*ret_p = handle;
+		return AE_CTRL_TERMINATE;
+	}
+	return AE_OK;
+}
+
+static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge)
+{
+	unsigned long long sta;
+	acpi_status status;
+
+	status = acpi_bus_get_status_handle(handle, &sta);
+	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
+		return false;
+
+	if (is_bridge) {
+		void *test = NULL;
+
+		/* Check if this object has at least one child device. */
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				    acpi_dev_present, NULL, NULL, &test);
+		return !!test;
+	}
+	return true;
+}
+
+struct find_child_context {
+	u64 addr;
+	bool is_bridge;
+	acpi_handle ret;
+	bool ret_checked;
+};
+
+static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used,
+				 void *data, void **not_used)
+{
+	struct find_child_context *context = data;
+	unsigned long long addr;
 	acpi_status status;
 
 	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
-	if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) {
-		*ret_p = handle;
-		status = acpi_bus_get_status_handle(handle, &sta);
-		if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_ENABLED))
+	if (ACPI_FAILURE(status) || addr != context->addr)
+		return AE_OK;
+
+	if (!context->ret) {
+		/* This is the first matching object.  Save its handle. */
+		context->ret = handle;
+		return AE_OK;
+	}
+	/*
+	 * There is more than one matching object with the same _ADR value.
+	 * That really is unexpected, so we are kind of beyond the scope of the
+	 * spec here.  We have to choose which one to return, though.
+	 *
+	 * First, check if the previously found object is good enough and return
+	 * its handle if so.  Second, check the same for the object that we've
+	 * just found.
+	 */
+	if (!context->ret_checked) {
+		if (acpi_extra_checks_passed(context->ret, context->is_bridge))
 			return AE_CTRL_TERMINATE;
+		else
+			context->ret_checked = true;
+	}
+	if (acpi_extra_checks_passed(handle, context->is_bridge)) {
+		context->ret = handle;
+		return AE_CTRL_TERMINATE;
 	}
 	return AE_OK;
 }
 
-acpi_handle acpi_get_child(acpi_handle parent, u64 address)
+acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
 {
-	void *ret = NULL;
-
-	if (!parent)
-		return NULL;
+	if (parent) {
+		struct find_child_context context = {
+			.addr = addr,
+			.is_bridge = is_bridge,
+		};
+
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child,
+				    NULL, &context, NULL);
+		return context.ret;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(acpi_find_child);
 
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL,
-			    do_acpi_find_child, &address, &ret);
-	return (acpi_handle)ret;
+static void acpi_physnode_link_name(char *buf, unsigned int node_id)
+{
+	if (node_id > 0)
+		snprintf(buf, PHYSICAL_NODE_NAME_SIZE,
+			 PHYSICAL_NODE_STRING "%u", node_id);
+	else
+		strcpy(buf, PHYSICAL_NODE_STRING);
 }
-EXPORT_SYMBOL(acpi_get_child);
 
 int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
 	struct acpi_device *acpi_dev;
 	acpi_status status;
 	struct acpi_device_physical_node *physical_node, *pn;
-	char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+	char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
+	struct list_head *physnode_list;
+	unsigned int node_id;
 	int retval = -EINVAL;
 
 	if (ACPI_HANDLE(dev)) {
@@ -139,41 +216,42 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
 
 	mutex_lock(&acpi_dev->physical_node_lock);
 
-	/* Sanity check. */
-	list_for_each_entry(pn, &acpi_dev->physical_node_list, node)
+	/*
+	 * Keep the list sorted by node_id so that the IDs of removed nodes can
+	 * be recycled easily.
+	 */
+	physnode_list = &acpi_dev->physical_node_list;
+	node_id = 0;
+	list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
+		/* Sanity check. */
 		if (pn->dev == dev) {
 			dev_warn(dev, "Already associated with ACPI node\n");
-			goto err_free;
-		}
+			if (ACPI_HANDLE(dev) == handle)
+				retval = 0;
 
-	/* allocate physical node id according to physical_node_id_bitmap */
-	physical_node->node_id =
-		find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
-		ACPI_MAX_PHYSICAL_NODE);
-	if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
-		retval = -ENOSPC;
-		goto err_free;
+			goto out_free;
+		}
+		if (pn->node_id == node_id) {
+			physnode_list = &pn->node;
+			node_id++;
+		}
 	}
 
-	set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
+	physical_node->node_id = node_id;
 	physical_node->dev = dev;
-	list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
+	list_add(&physical_node->node, physnode_list);
 	acpi_dev->physical_node_count++;
 
-	mutex_unlock(&acpi_dev->physical_node_lock);
-
 	if (!ACPI_HANDLE(dev))
 		ACPI_HANDLE_SET(dev, acpi_dev->handle);
 
-	if (!physical_node->node_id)
-		strcpy(physical_node_name, PHYSICAL_NODE_STRING);
-	else
-		sprintf(physical_node_name,
-			"physical_node%d", physical_node->node_id);
+	acpi_physnode_link_name(physical_node_name, node_id);
 	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
-			physical_node_name);
+				   physical_node_name);
 	retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
-		"firmware_node");
+				   "firmware_node");
+
+	mutex_unlock(&acpi_dev->physical_node_lock);
 
 	if (acpi_dev->wakeup.flags.valid)
 		device_set_wakeup_capable(dev, true);
@@ -185,10 +263,14 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
 	put_device(dev);
 	return retval;
 
- err_free:
+ out_free:
 	mutex_unlock(&acpi_dev->physical_node_lock);
 	kfree(physical_node);
-	goto err;
+	if (retval)
+		goto err;
+
+	put_device(dev);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_bind_one);
 
@@ -197,49 +279,37 @@ int acpi_unbind_one(struct device *dev)
 	struct acpi_device_physical_node *entry;
 	struct acpi_device *acpi_dev;
 	acpi_status status;
-	struct list_head *node, *next;
 
 	if (!ACPI_HANDLE(dev))
 		return 0;
 
 	status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
-	if (ACPI_FAILURE(status))
-		goto err;
+	if (ACPI_FAILURE(status)) {
+		dev_err(dev, "Oops, ACPI handle corrupt in %s()\n", __func__);
+		return -EINVAL;
+	}
 
 	mutex_lock(&acpi_dev->physical_node_lock);
-	list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
-		char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
 
-		entry = list_entry(node, struct acpi_device_physical_node,
-			node);
-		if (entry->dev != dev)
-			continue;
+	list_for_each_entry(entry, &acpi_dev->physical_node_list, node)
+		if (entry->dev == dev) {
+			char physnode_name[PHYSICAL_NODE_NAME_SIZE];
 
-		list_del(node);
-		clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
+			list_del(&entry->node);
+			acpi_dev->physical_node_count--;
 
-		acpi_dev->physical_node_count--;
+			acpi_physnode_link_name(physnode_name, entry->node_id);
+			sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
+			sysfs_remove_link(&dev->kobj, "firmware_node");
+			ACPI_HANDLE_SET(dev, NULL);
+			/* acpi_bind_one() increase refcnt by one. */
+			put_device(dev);
+			kfree(entry);
+			break;
+		}
 
-		if (!entry->node_id)
-			strcpy(physical_node_name, PHYSICAL_NODE_STRING);
-		else
-			sprintf(physical_node_name,
-				"physical_node%d", entry->node_id);
-
-		sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
-		sysfs_remove_link(&dev->kobj, "firmware_node");
-		ACPI_HANDLE_SET(dev, NULL);
-		/* acpi_bind_one increase refcnt by one */
-		put_device(dev);
-		kfree(entry);
-	}
 	mutex_unlock(&acpi_dev->physical_node_lock);
-
 	return 0;
-
-err:
-	dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
-	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(acpi_unbind_one);
 
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 5da44e8..20f4233 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -23,6 +23,7 @@
 
 #define PREFIX "ACPI: "
 
+acpi_status acpi_os_initialize1(void);
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
 #ifdef	CONFIG_ACPI_PCI_SLOT
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6ab2c35..d6bc619 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -52,6 +52,7 @@
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/processor.h>
+#include "internal.h"
 
 #define _COMPONENT		ACPI_OS_SERVICES
 ACPI_MODULE_NAME("osl");
@@ -79,6 +80,8 @@ extern char line_buf[80];
 
 static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl,
 				      u32 pm1b_ctrl);
+static int (*__acpi_os_prepare_extended_sleep)(u8 sleep_state, u32 val_a,
+				      u32 val_b);
 
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
@@ -140,7 +143,8 @@ static struct osi_linux {
 	unsigned int	enable:1;
 	unsigned int	dmi:1;
 	unsigned int	cmdline:1;
-} osi_linux = {0, 0, 0};
+	unsigned int	default_disabling:1;
+} osi_linux = {0, 0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
@@ -1376,6 +1380,17 @@ void __init acpi_osi_setup(char *str)
 
 	if (*str == '!') {
 		str++;
+		if (*str == '\0') {
+			osi_linux.default_disabling = 1;
+			return;
+		} else if (*str == '*') {
+			acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS);
+			for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+				osi = &osi_setup_entries[i];
+				osi->enable = false;
+			}
+			return;
+		}
 		enable = false;
 	}
 
@@ -1441,6 +1456,13 @@ static void __init acpi_osi_setup_late(void)
 	int i;
 	acpi_status status;
 
+	if (osi_linux.default_disabling) {
+		status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
+
+		if (ACPI_SUCCESS(status))
+			printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n");
+	}
+
 	for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
 		osi = &osi_setup_entries[i];
 		str = osi->string;
@@ -1779,6 +1801,28 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 	__acpi_os_prepare_sleep = func;
 }
 
+acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
+				  u32 val_b)
+{
+	int rc = 0;
+	if (__acpi_os_prepare_extended_sleep)
+		rc = __acpi_os_prepare_extended_sleep(sleep_state,
+					     val_a, val_b);
+	if (rc < 0)
+		return AE_ERROR;
+	else if (rc > 0)
+		return AE_CTRL_SKIP;
+
+	return AE_OK;
+}
+
+void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
+			       u32 val_a, u32 val_b))
+{
+	__acpi_os_prepare_extended_sleep = func;
+}
+
+
 void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
 			void (*func)(struct work_struct *work))
 {
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index 033d117..d678a18 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -159,12 +159,16 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 	return AE_OK;
 }
 
-void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle)
+void acpi_pci_slot_enumerate(struct pci_bus *bus)
 {
-	mutex_lock(&slot_list_lock);
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-			    register_slot, NULL, bus, NULL);
-	mutex_unlock(&slot_list_lock);
+	acpi_handle handle = ACPI_HANDLE(bus->bridge);
+
+	if (handle) {
+		mutex_lock(&slot_list_lock);
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				    register_slot, NULL, bus, NULL);
+		mutex_unlock(&slot_list_lock);
+	}
 }
 
 void acpi_pci_slot_remove(struct pci_bus *bus)
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 5c28c89..0dbe5cd 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -637,9 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
 	}
 
 	/* Execute _PSW */
-	arg_list.count = 1;
-	in_arg[0].integer.value = enable;
-	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+	status = acpi_execute_simple_method(dev->handle, "_PSW", enable);
 	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
 		printk(KERN_ERR PREFIX "_PSW execution failed\n");
 		dev->wakeup.flags.valid = 0;
@@ -786,7 +784,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
 		}
 	}
 
-	*state = ACPI_STATE_D3;
+	*state = ACPI_STATE_D3_COLD;
 	return 0;
 }
 
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index aa1227a..04a1378 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -311,6 +311,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 			   dev->pnp.bus_id,
 			   (u32) dev->wakeup.sleep_state);
 
+		mutex_lock(&dev->physical_node_lock);
+
 		if (!dev->physical_node_count) {
 			seq_printf(seq, "%c%-8s\n",
 				dev->wakeup.flags.run_wake ? '*' : ' ',
@@ -338,6 +340,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 				put_device(ldev);
 			}
 		}
+
+		mutex_unlock(&dev->physical_node_lock);
 	}
 	mutex_unlock(&acpi_device_lock);
 	return 0;
@@ -347,12 +351,16 @@ static void physical_device_enable_wakeup(struct acpi_device *adev)
 {
 	struct acpi_device_physical_node *entry;
 
+	mutex_lock(&adev->physical_node_lock);
+
 	list_for_each_entry(entry,
 		&adev->physical_node_list, node)
 		if (entry->dev && device_can_wakeup(entry->dev)) {
 			bool enable = !device_may_wakeup(entry->dev);
 			device_set_wakeup_enable(entry->dev, enable);
 		}
+
+	mutex_unlock(&adev->physical_node_lock);
 }
 
 static ssize_t
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index a5e9f4a..cf34d90 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -28,7 +28,7 @@ static int __init set_no_mwait(const struct dmi_system_id *id)
 	return 0;
 }
 
-static struct dmi_system_id __initdata processor_idle_dmi_table[] = {
+static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
 	{
 	set_no_mwait, "Extensa 5220", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 870eaf5..bd11ef9 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -91,21 +91,17 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
 		acpi_processor_ppc_has_changed(pr, 1);
 		if (saved == pr->performance_platform_limit)
 			break;
-		acpi_bus_generate_proc_event(device, event,
-					pr->performance_platform_limit);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event,
 						  pr->performance_platform_limit);
 		break;
 	case ACPI_PROCESSOR_NOTIFY_POWER:
 		acpi_processor_cst_has_changed(pr);
-		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event, 0);
 		break;
 	case ACPI_PROCESSOR_NOTIFY_THROTTLING:
 		acpi_processor_tstate_has_changed(pr);
-		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event, 0);
 		break;
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 1e9732d..51d7948 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -164,17 +164,12 @@ static void acpi_processor_ppc_ost(acpi_handle handle, int status)
 		{.type = ACPI_TYPE_INTEGER,},
 	};
 	struct acpi_object_list arg_list = {2, params};
-	acpi_handle temp;
 
-	params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
-	params[1].integer.value =  status;
-
-	/* when there is no _OST , skip it */
-	if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
-		return;
-
-	acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
-	return;
+	if (acpi_has_method(handle, "_OST")) {
+		params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
+		params[1].integer.value =  status;
+		acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
+	}
 }
 
 int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
@@ -468,14 +463,11 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
 int acpi_processor_get_performance_info(struct acpi_processor *pr)
 {
 	int result = 0;
-	acpi_status status = AE_OK;
-	acpi_handle handle = NULL;
 
 	if (!pr || !pr->performance || !pr->handle)
 		return -EINVAL;
 
-	status = acpi_get_handle(pr->handle, "_PCT", &handle);
-	if (ACPI_FAILURE(status)) {
+	if (!acpi_has_method(pr->handle, "_PCT")) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "ACPI-based processor performance control unavailable\n"));
 		return -ENODEV;
@@ -501,7 +493,7 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr)
 	 */
  update_bios:
 #ifdef CONFIG_X86
-	if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
+	if (acpi_has_method(pr->handle, "_PPC")) {
 		if(boot_cpu_has(X86_FEATURE_EST))
 			printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
 			       "frequency support\n");
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 3322b47..b7201fc 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -505,14 +505,12 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
 			   void *preproc_data)
 {
 	struct res_proc_context c;
-	acpi_handle not_used;
 	acpi_status status;
 
 	if (!adev || !adev->handle || !list_empty(list))
 		return -EINVAL;
 
-	status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, &not_used);
-	if (ACPI_FAILURE(status))
+	if (!acpi_has_method(adev->handle, METHOD_NAME__CRS))
 		return 0;
 
 	c.list = list;
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index b6241ee..aef7e1c 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -873,14 +873,9 @@ static void acpi_sbs_callback(void *context)
 	u8 saved_charger_state = sbs->charger_present;
 	u8 saved_battery_state;
 	acpi_ac_get_present(sbs);
-	if (sbs->charger_present != saved_charger_state) {
-#ifdef CONFIG_ACPI_PROC_EVENT
-		acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
-					      ACPI_SBS_NOTIFY_STATUS,
-					      sbs->charger_present);
-#endif
+	if (sbs->charger_present != saved_charger_state)
 		kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
-	}
+
 	if (sbs->manager_present) {
 		for (id = 0; id < MAX_SBS_BAT; ++id) {
 			if (!(sbs->batteries_supported & (1 << id)))
@@ -890,12 +885,6 @@ static void acpi_sbs_callback(void *context)
 			acpi_battery_read(bat);
 			if (saved_battery_state == bat->present)
 				continue;
-#ifdef CONFIG_ACPI_PROC_EVENT
-			acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
-						      bat->name,
-						      ACPI_SBS_NOTIFY_STATUS,
-						      bat->present);
-#endif
 			kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
 		}
 	}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 8a46c92..e763651 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -193,9 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl,
 static int acpi_scan_hot_remove(struct acpi_device *device)
 {
 	acpi_handle handle = device->handle;
-	acpi_handle not_used;
-	struct acpi_object_list arg_list;
-	union acpi_object arg;
 	struct device *errdev;
 	acpi_status status;
 	unsigned long long sta;
@@ -258,32 +255,15 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
 	put_device(&device->dev);
 	device = NULL;
 
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &not_used))) {
-		arg_list.count = 1;
-		arg_list.pointer = &arg;
-		arg.type = ACPI_TYPE_INTEGER;
-		arg.integer.value = 0;
-		acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
-	}
-
-	arg_list.count = 1;
-	arg_list.pointer = &arg;
-	arg.type = ACPI_TYPE_INTEGER;
-	arg.integer.value = 1;
-
+	acpi_evaluate_lck(handle, 0);
 	/*
 	 * TBD: _EJD support.
 	 */
-	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
-	if (ACPI_FAILURE(status)) {
-		if (status == AE_NOT_FOUND) {
-			return -ENODEV;
-		} else {
-			acpi_handle_warn(handle, "Eject failed (0x%x)\n",
-								status);
-			return -EIO;
-		}
-	}
+	status = acpi_evaluate_ej0(handle);
+	if (status == AE_NOT_FOUND)
+		return -ENODEV;
+	else if (ACPI_FAILURE(status))
+		return -EIO;
 
 	/*
 	 * Verify if eject was indeed successful.  If not, log an error
@@ -654,7 +634,6 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 {
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_status status;
-	acpi_handle temp;
 	unsigned long long sun;
 	int result = 0;
 
@@ -680,8 +659,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 	/*
 	 * If device has _STR, 'description' file is created
 	 */
-	status = acpi_get_handle(dev->handle, "_STR", &temp);
-	if (ACPI_SUCCESS(status)) {
+	if (acpi_has_method(dev->handle, "_STR")) {
 		status = acpi_evaluate_object(dev->handle, "_STR",
 					NULL, &buffer);
 		if (ACPI_FAILURE(status))
@@ -711,8 +689,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
          */
-	status = acpi_get_handle(dev->handle, "_EJ0", &temp);
-	if (ACPI_SUCCESS(status)) {
+	if (acpi_has_method(dev->handle, "_EJ0")) {
 		result = device_create_file(&dev->dev, &dev_attr_eject);
 		if (result)
 			return result;
@@ -734,9 +711,6 @@ end:
 
 static void acpi_device_remove_files(struct acpi_device *dev)
 {
-	acpi_status status;
-	acpi_handle temp;
-
 	if (dev->flags.power_manageable) {
 		device_remove_file(&dev->dev, &dev_attr_power_state);
 		if (dev->power.flags.power_resources)
@@ -747,20 +721,17 @@ static void acpi_device_remove_files(struct acpi_device *dev)
 	/*
 	 * If device has _STR, remove 'description' file
 	 */
-	status = acpi_get_handle(dev->handle, "_STR", &temp);
-	if (ACPI_SUCCESS(status)) {
+	if (acpi_has_method(dev->handle, "_STR")) {
 		kfree(dev->pnp.str_obj);
 		device_remove_file(&dev->dev, &dev_attr_description);
 	}
 	/*
 	 * If device has _EJ0, remove 'eject' file.
 	 */
-	status = acpi_get_handle(dev->handle, "_EJ0", &temp);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(dev->handle, "_EJ0"))
 		device_remove_file(&dev->dev, &dev_attr_eject);
 
-	status = acpi_get_handle(dev->handle, "_SUN", &temp);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(dev->handle, "_SUN"))
 		device_remove_file(&dev->dev, &dev_attr_sun);
 
 	if (dev->pnp.unique_id)
@@ -999,6 +970,28 @@ struct bus_type acpi_bus_type = {
 	.uevent		= acpi_device_uevent,
 };
 
+static void acpi_bus_data_handler(acpi_handle handle, void *context)
+{
+	/* Intentionally empty. */
+}
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+	acpi_status status;
+
+	if (!device)
+		return -EINVAL;
+
+	status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
+	if (ACPI_FAILURE(status) || !*device) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+				  handle));
+		return -ENODEV;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_get_device);
+
 int acpi_device_add(struct acpi_device *device,
 		    void (*release)(struct device *))
 {
@@ -1210,14 +1203,6 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
 }
 EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
 
-void acpi_bus_data_handler(acpi_handle handle, void *context)
-{
-
-	/* TBD */
-
-	return;
-}
-
 static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
 					struct acpi_device_wakeup *wakeup)
 {
@@ -1336,13 +1321,10 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 
 static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 {
-	acpi_handle temp;
-	acpi_status status = 0;
 	int err;
 
 	/* Presence of _PRW indicates wake capable */
-	status = acpi_get_handle(device->handle, "_PRW", &temp);
-	if (ACPI_FAILURE(status))
+	if (!acpi_has_method(device->handle, "_PRW"))
 		return;
 
 	err = acpi_bus_extract_wakeup_device_power_package(device->handle,
@@ -1372,7 +1354,6 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
 	struct acpi_device_power_state *ps = &device->power.states[state];
 	char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' };
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	acpi_handle handle;
 	acpi_status status;
 
 	INIT_LIST_HEAD(&ps->resources);
@@ -1395,8 +1376,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
 
 	/* Evaluate "_PSx" to see if we can do explicit sets */
 	pathname[2] = 'S';
-	status = acpi_get_handle(device->handle, pathname, &handle);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(device->handle, pathname))
 		ps->flags.explicit_set = 1;
 
 	/*
@@ -1415,28 +1395,21 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
 
 static void acpi_bus_get_power_flags(struct acpi_device *device)
 {
-	acpi_status status;
-	acpi_handle handle;
 	u32 i;
 
 	/* Presence of _PS0|_PR0 indicates 'power manageable' */
-	status = acpi_get_handle(device->handle, "_PS0", &handle);
-	if (ACPI_FAILURE(status)) {
-		status = acpi_get_handle(device->handle, "_PR0", &handle);
-		if (ACPI_FAILURE(status))
-			return;
-	}
+	if (!acpi_has_method(device->handle, "_PS0") &&
+	    !acpi_has_method(device->handle, "_PR0"))
+		return;
 
 	device->flags.power_manageable = 1;
 
 	/*
 	 * Power Management Flags
 	 */
-	status = acpi_get_handle(device->handle, "_PSC", &handle);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(device->handle, "_PSC"))
 		device->power.flags.explicit_get = 1;
-	status = acpi_get_handle(device->handle, "_IRC", &handle);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(device->handle, "_IRC"))
 		device->power.flags.inrush_current = 1;
 
 	/*
@@ -1450,8 +1423,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
 	/* Set defaults for D0 and D3 states (always valid) */
 	device->power.states[ACPI_STATE_D0].flags.valid = 1;
 	device->power.states[ACPI_STATE_D0].power = 100;
-	device->power.states[ACPI_STATE_D3].flags.valid = 1;
-	device->power.states[ACPI_STATE_D3].power = 0;
+	device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
+	device->power.states[ACPI_STATE_D3_COLD].power = 0;
 
 	/* Set D3cold's explicit_set flag if _PS3 exists. */
 	if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
@@ -1470,28 +1443,18 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
 
 static void acpi_bus_get_flags(struct acpi_device *device)
 {
-	acpi_status status = AE_OK;
-	acpi_handle temp = NULL;
-
 	/* Presence of _STA indicates 'dynamic_status' */
-	status = acpi_get_handle(device->handle, "_STA", &temp);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(device->handle, "_STA"))
 		device->flags.dynamic_status = 1;
 
 	/* Presence of _RMV indicates 'removable' */
-	status = acpi_get_handle(device->handle, "_RMV", &temp);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(device->handle, "_RMV"))
 		device->flags.removable = 1;
 
 	/* Presence of _EJD|_EJ0 indicates 'ejectable' */
-	status = acpi_get_handle(device->handle, "_EJD", &temp);
-	if (ACPI_SUCCESS(status))
+	if (acpi_has_method(device->handle, "_EJD") ||
+	    acpi_has_method(device->handle, "_EJ0"))
 		device->flags.ejectable = 1;
-	else {
-		status = acpi_get_handle(device->handle, "_EJ0", &temp);
-		if (ACPI_SUCCESS(status))
-			device->flags.ejectable = 1;
-	}
 }
 
 static void acpi_device_get_busid(struct acpi_device *device)
@@ -1533,46 +1496,45 @@ static void acpi_device_get_busid(struct acpi_device *device)
 }
 
 /*
+ * acpi_ata_match - see if an acpi object is an ATA device
+ *
+ * If an acpi object has one of the ACPI ATA methods defined,
+ * then we can safely call it an ATA device.
+ */
+bool acpi_ata_match(acpi_handle handle)
+{
+	return acpi_has_method(handle, "_GTF") ||
+	       acpi_has_method(handle, "_GTM") ||
+	       acpi_has_method(handle, "_STM") ||
+	       acpi_has_method(handle, "_SDD");
+}
+
+/*
  * acpi_bay_match - see if an acpi object is an ejectable driver bay
  *
  * If an acpi object is ejectable and has one of the ACPI ATA methods defined,
  * then we can safely call it an ejectable drive bay
  */
-static int acpi_bay_match(acpi_handle handle)
+bool acpi_bay_match(acpi_handle handle)
 {
-	acpi_status status;
-	acpi_handle tmp;
 	acpi_handle phandle;
 
-	status = acpi_get_handle(handle, "_EJ0", &tmp);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
-		(ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
-		(ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
-		(ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
-		return 0;
+	if (!acpi_has_method(handle, "_EJ0"))
+		return false;
+	if (acpi_ata_match(handle))
+		return true;
+	if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
+		return false;
 
-	if (acpi_get_parent(handle, &phandle))
-		return -ENODEV;
-
-        if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) ||
-                (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) ||
-                (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) ||
-                (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp))))
-                return 0;
-
-	return -ENODEV;
+	return acpi_ata_match(phandle);
 }
 
 /*
  * acpi_dock_match - see if an acpi object has a _DCK method
  */
-static int acpi_dock_match(acpi_handle handle)
+bool acpi_dock_match(acpi_handle handle)
 {
-	acpi_handle tmp;
-	return acpi_get_handle(handle, "_DCK", &tmp);
+	return acpi_has_method(handle, "_DCK");
 }
 
 const char *acpi_device_hid(struct acpi_device *device)
@@ -1610,34 +1572,26 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
  * lacks the SMBUS01 HID and the methods do not have the necessary "_"
  * prefix.  Work around this.
  */
-static int acpi_ibm_smbus_match(acpi_handle handle)
+static bool acpi_ibm_smbus_match(acpi_handle handle)
 {
-	acpi_handle h_dummy;
-	struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
-	int result;
+	char node_name[ACPI_PATH_SEGMENT_LENGTH];
+	struct acpi_buffer path = { sizeof(node_name), node_name };
 
 	if (!dmi_name_in_vendors("IBM"))
-		return -ENODEV;
+		return false;
 
 	/* Look for SMBS object */
-	result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path);
-	if (result)
-		return result;
-
-	if (strcmp("SMBS", path.pointer)) {
-		result = -ENODEV;
-		goto out;
-	}
+	if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &path)) ||
+	    strcmp("SMBS", path.pointer))
+		return false;
 
 	/* Does it have the necessary (but misnamed) methods? */
-	result = -ENODEV;
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy)))
-		result = 0;
-out:
-	kfree(path.pointer);
-	return result;
+	if (acpi_has_method(handle, "SBI") &&
+	    acpi_has_method(handle, "SBR") &&
+	    acpi_has_method(handle, "SBW"))
+		return true;
+
+	return false;
 }
 
 static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
@@ -1685,11 +1639,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
 		 */
 		if (acpi_is_video_device(handle))
 			acpi_add_id(pnp, ACPI_VIDEO_HID);
-		else if (ACPI_SUCCESS(acpi_bay_match(handle)))
+		else if (acpi_bay_match(handle))
 			acpi_add_id(pnp, ACPI_BAY_HID);
-		else if (ACPI_SUCCESS(acpi_dock_match(handle)))
+		else if (acpi_dock_match(handle))
 			acpi_add_id(pnp, ACPI_DOCK_HID);
-		else if (!acpi_ibm_smbus_match(handle))
+		else if (acpi_ibm_smbus_match(handle))
 			acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
 		else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
 			acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
@@ -1900,7 +1854,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
-	acpi_status status;
 	int result;
 
 	acpi_bus_get_device(handle, &device);
@@ -1921,10 +1874,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
 	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
 		struct acpi_device_wakeup wakeup;
-		acpi_handle temp;
 
-		status = acpi_get_handle(handle, "_PRW", &temp);
-		if (ACPI_SUCCESS(status)) {
+		if (acpi_has_method(handle, "_PRW")) {
 			acpi_bus_extract_wakeup_device_power_package(handle,
 								     &wakeup);
 			acpi_power_resources_list_free(&wakeup.resources);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 187ab61..0fa6427 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -31,12 +31,9 @@ static u8 sleep_states[ACPI_S_STATE_COUNT];
 
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
-	union acpi_object in_arg = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list arg_list = { 1, &in_arg };
-	acpi_status status = AE_OK;
+	acpi_status status;
 
-	in_arg.integer.value = acpi_state;
-	status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
+	status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 		/*
 		 * OS can't evaluate the _TTS object correctly. Some warning
@@ -141,7 +138,7 @@ static int __init init_nvs_nosave(const struct dmi_system_id *d)
 	return 0;
 }
 
-static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+static struct dmi_system_id acpisleep_dmi_table[] __initdata = {
 	{
 	.callback = init_old_suspend_ordering,
 	.ident = "Abit KN9 (nForce4 variant)",
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index a33821c..a3e38a0 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -239,26 +239,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
 
 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
 {
-	acpi_status status = AE_OK;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list arg_list = { 1, &arg0 };
-	acpi_handle handle = NULL;
-
-
 	if (!tz)
 		return -EINVAL;
 
-	status = acpi_get_handle(tz->device->handle, "_SCP", &handle);
-	if (ACPI_FAILURE(status)) {
+	if (!acpi_has_method(tz->device->handle, "_SCP")) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
 		return -ENODEV;
-	}
-
-	arg0.integer.value = mode;
-
-	status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
-	if (ACPI_FAILURE(status))
+	} else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
+							   "_SCP", mode))) {
 		return -ENODEV;
+	}
 
 	return 0;
 }
@@ -769,7 +759,6 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
 	else
 		return 0;
 
-	acpi_bus_generate_proc_event(tz->device, type, 1);
 	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
 					dev_name(&tz->device->dev), type, 1);
 
@@ -980,14 +969,12 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
 	case ACPI_THERMAL_NOTIFY_THRESHOLDS:
 		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
 		acpi_thermal_check(tz);
-		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event, 0);
 		break;
 	case ACPI_THERMAL_NOTIFY_DEVICES:
 		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
 		acpi_thermal_check(tz);
-		acpi_bus_generate_proc_event(device, event, 0);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event, 0);
 		break;
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 74437130..552248b 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -495,3 +495,73 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
 	kfree(buffer.pointer);
 }
 EXPORT_SYMBOL(acpi_handle_printk);
+
+/**
+ * acpi_has_method: Check whether @handle has a method named @name
+ * @handle: ACPI device handle
+ * @name: name of object or method
+ *
+ * Check whether @handle has a method named @name.
+ */
+bool acpi_has_method(acpi_handle handle, char *name)
+{
+	acpi_handle tmp;
+
+	return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp));
+}
+EXPORT_SYMBOL(acpi_has_method);
+
+acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
+				       u64 arg)
+{
+	union acpi_object obj = { .type = ACPI_TYPE_INTEGER };
+	struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, };
+
+	obj.integer.value = arg;
+
+	return acpi_evaluate_object(handle, method, &arg_list, NULL);
+}
+EXPORT_SYMBOL(acpi_execute_simple_method);
+
+/**
+ * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations
+ * @handle: ACPI device handle
+ *
+ * Evaluate device's _EJ0 method for hotplug operations.
+ */
+acpi_status acpi_evaluate_ej0(acpi_handle handle)
+{
+	acpi_status status;
+
+	status = acpi_execute_simple_method(handle, "_EJ0", 1);
+	if (status == AE_NOT_FOUND)
+		acpi_handle_warn(handle, "No _EJ0 support for device\n");
+	else if (ACPI_FAILURE(status))
+		acpi_handle_warn(handle, "Eject failed (0x%x)\n", status);
+
+	return status;
+}
+
+/**
+ * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device
+ * @handle: ACPI device handle
+ * @lock: lock device if non-zero, otherwise unlock device
+ *
+ * Evaluate device's _LCK method if present to lock/unlock device
+ */
+acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
+{
+	acpi_status status;
+
+	status = acpi_execute_simple_method(handle, "_LCK", !!lock);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+		if (lock)
+			acpi_handle_warn(handle,
+				"Locking device failed (0x%x)\n", status);
+		else
+			acpi_handle_warn(handle,
+				"Unlocking device failed (0x%x)\n", status);
+	}
+
+	return status;
+}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 0ec434d..ae0d09c 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1,5 +1,5 @@
 /*
- *  video.c - ACPI Video Driver ($Revision:$)
+ *  video.c - ACPI Video Driver
  *
  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  *  Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
@@ -88,7 +88,7 @@ module_param(allow_duplicates, bool, 0644);
 static bool use_bios_initial_backlight = 1;
 module_param(use_bios_initial_backlight, bool, 0644);
 
-static int register_count = 0;
+static int register_count;
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device);
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
@@ -118,26 +118,26 @@ struct acpi_video_bus_flags {
 };
 
 struct acpi_video_bus_cap {
-	u8 _DOS:1;		/*Enable/Disable output switching */
-	u8 _DOD:1;		/*Enumerate all devices attached to display adapter */
-	u8 _ROM:1;		/*Get ROM Data */
-	u8 _GPD:1;		/*Get POST Device */
-	u8 _SPD:1;		/*Set POST Device */
-	u8 _VPO:1;		/*Video POST Options */
+	u8 _DOS:1;		/* Enable/Disable output switching */
+	u8 _DOD:1;		/* Enumerate all devices attached to display adapter */
+	u8 _ROM:1;		/* Get ROM Data */
+	u8 _GPD:1;		/* Get POST Device */
+	u8 _SPD:1;		/* Set POST Device */
+	u8 _VPO:1;		/* Video POST Options */
 	u8 reserved:2;
 };
 
 struct acpi_video_device_attrib {
 	u32 display_index:4;	/* A zero-based instance of the Display */
-	u32 display_port_attachment:4;	/*This field differentiates the display type */
-	u32 display_type:4;	/*Describe the specific type in use */
-	u32 vendor_specific:4;	/*Chipset Vendor Specific */
-	u32 bios_can_detect:1;	/*BIOS can detect the device */
-	u32 depend_on_vga:1;	/*Non-VGA output device whose power is related to 
+	u32 display_port_attachment:4;	/* This field differentiates the display type */
+	u32 display_type:4;	/* Describe the specific type in use */
+	u32 vendor_specific:4;	/* Chipset Vendor Specific */
+	u32 bios_can_detect:1;	/* BIOS can detect the device */
+	u32 depend_on_vga:1;	/* Non-VGA output device whose power is related to
 				   the VGA device. */
-	u32 pipe_id:3;		/*For VGA multiple-head devices. */
-	u32 reserved:10;	/*Must be 0 */
-	u32 device_id_scheme:1;	/*Device ID Scheme */
+	u32 pipe_id:3;		/* For VGA multiple-head devices. */
+	u32 reserved:10;	/* Must be 0 */
+	u32 device_id_scheme:1;	/* Device ID Scheme */
 };
 
 struct acpi_video_enumerated_device {
@@ -174,19 +174,17 @@ struct acpi_video_device_flags {
 };
 
 struct acpi_video_device_cap {
-	u8 _ADR:1;		/*Return the unique ID */
-	u8 _BCL:1;		/*Query list of brightness control levels supported */
-	u8 _BCM:1;		/*Set the brightness level */
+	u8 _ADR:1;		/* Return the unique ID */
+	u8 _BCL:1;		/* Query list of brightness control levels supported */
+	u8 _BCM:1;		/* Set the brightness level */
 	u8 _BQC:1;		/* Get current brightness level */
 	u8 _BCQ:1;		/* Some buggy BIOS uses _BCQ instead of _BQC */
-	u8 _DDC:1;		/*Return the EDID for this device */
+	u8 _DDC:1;		/* Return the EDID for this device */
 };
 
 struct acpi_video_brightness_flags {
 	u8 _BCL_no_ac_battery_levels:1;	/* no AC/Battery levels in _BCL */
-	u8 _BCL_reversed:1;		/* _BCL package is in a reversed order*/
-	u8 _BCL_use_index:1;		/* levels in _BCL are index values */
-	u8 _BCM_use_index:1;		/* input of _BCM is an index value */
+	u8 _BCL_reversed:1;		/* _BCL package is in a reversed order */
 	u8 _BQC_use_index:1;		/* _BQC returns an index value */
 };
 
@@ -231,21 +229,22 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
 					 int event);
 
-/*backlight device sysfs support*/
+/* backlight device sysfs support */
 static int acpi_video_get_brightness(struct backlight_device *bd)
 {
 	unsigned long long cur_level;
 	int i;
-	struct acpi_video_device *vd =
-		(struct acpi_video_device *)bl_get_data(bd);
+	struct acpi_video_device *vd = bl_get_data(bd);
 
 	if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
 		return -EINVAL;
 	for (i = 2; i < vd->brightness->count; i++) {
 		if (vd->brightness->levels[i] == cur_level)
-			/* The first two entries are special - see page 575
-			   of the ACPI spec 3.0 */
-			return i-2;
+			/*
+			 * The first two entries are special - see page 575
+			 * of the ACPI spec 3.0
+			 */
+			return i - 2;
 	}
 	return 0;
 }
@@ -253,8 +252,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
 	int request_level = bd->props.brightness + 2;
-	struct acpi_video_device *vd =
-		(struct acpi_video_device *)bl_get_data(bd);
+	struct acpi_video_device *vd = bl_get_data(bd);
 
 	return acpi_video_device_lcd_set_level(vd,
 				vd->brightness->levels[request_level]);
@@ -302,11 +300,11 @@ video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long st
 	struct acpi_video_device *video = acpi_driver_data(device);
 	int level;
 
-	if ( state >= video->brightness->count - 2)
+	if (state >= video->brightness->count - 2)
 		return -EINVAL;
 
 	state = video->brightness->count - state;
-	level = video->brightness->levels[state -1];
+	level = video->brightness->levels[state - 1];
 	return acpi_video_device_lcd_set_level(video, level);
 }
 
@@ -316,9 +314,11 @@ static const struct thermal_cooling_device_ops video_cooling_ops = {
 	.set_cur_state = video_set_cur_state,
 };
 
-/* --------------------------------------------------------------------------
-                               Video Management
-   -------------------------------------------------------------------------- */
+/*
+ * --------------------------------------------------------------------------
+ *                             Video Management
+ * --------------------------------------------------------------------------
+ */
 
 static int
 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
@@ -345,7 +345,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
 
 	return 0;
 
-      err:
+err:
 	kfree(buffer.pointer);
 
 	return status;
@@ -355,14 +355,10 @@ static int
 acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
 {
 	int status;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list args = { 1, &arg0 };
 	int state;
 
-	arg0.integer.value = level;
-
-	status = acpi_evaluate_object(device->dev->handle, "_BCM",
-				      &args, NULL);
+	status = acpi_execute_simple_method(device->dev->handle,
+					    "_BCM", level);
 	if (ACPI_FAILURE(status)) {
 		ACPI_ERROR((AE_INFO, "Evaluating _BCM failed"));
 		return -EIO;
@@ -546,7 +542,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
 				if (device->brightness->levels[i] == *level) {
 					device->brightness->curr = *level;
 					return 0;
-			}
+				}
 			/*
 			 * BQC returned an invalid level.
 			 * Stop using it.
@@ -556,7 +552,8 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
 				      buf));
 			device->cap._BQC = device->cap._BCQ = 0;
 		} else {
-			/* Fixme:
+			/*
+			 * Fixme:
 			 * should we return an error or ignore this failure?
 			 * dev->brightness->curr is a cached value which stores
 			 * the correct current backlight level in most cases.
@@ -615,8 +612,8 @@ acpi_video_device_EDID(struct acpi_video_device *device,
 
 /*
  *  Arg:
- *  	video		: video bus device pointer
- *	bios_flag	: 
+ *	video		: video bus device pointer
+ *	bios_flag	:
  *		0.	The system BIOS should NOT automatically switch(toggle)
  *			the active display output.
  *		1.	The system BIOS should automatically switch (toggle) the
@@ -628,9 +625,9 @@ acpi_video_device_EDID(struct acpi_video_device *device,
  *	lcd_flag	:
  *		0.	The system BIOS should automatically control the brightness level
  *			of the LCD when the power changes from AC to DC
- *		1. 	The system BIOS should NOT automatically control the brightness 
+ *		1.	The system BIOS should NOT automatically control the brightness
  *			level of the LCD when the power changes from AC to DC.
- * Return Value:
+ *  Return Value:
  *		-EINVAL	wrong arg.
  */
 
@@ -638,18 +635,15 @@ static int
 acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
 {
 	acpi_status status;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list args = { 1, &arg0 };
 
 	if (!video->cap._DOS)
 		return 0;
 
 	if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1)
 		return -EINVAL;
-	arg0.integer.value = (lcd_flag << 2) | bios_flag;
-	video->dos_setting = arg0.integer.value;
-	status = acpi_evaluate_object(video->device->handle, "_DOS",
-		&args, NULL);
+	video->dos_setting = (lcd_flag << 2) | bios_flag;
+	status = acpi_execute_simple_method(video->device->handle, "_DOS",
+					    (lcd_flag << 2) | bios_flag);
 	if (ACPI_FAILURE(status))
 		return -EIO;
 
@@ -689,7 +683,7 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
 	 * Some systems always report current brightness level as maximum
 	 * through _BQC, we need to test another value for them.
 	 */
-	test_level = current_level == max_level ? br->levels[2] : max_level;
+	test_level = current_level == max_level ? br->levels[3] : max_level;
 
 	result = acpi_video_device_lcd_set_level(device, test_level);
 	if (result)
@@ -717,8 +711,8 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
 
 
 /*
- *  Arg:	
- *  	device	: video output device (LCD, CRT, ..)
+ *  Arg:
+ *	device	: video output device (LCD, CRT, ..)
  *
  *  Return Value:
  *	Maximum brightness level
@@ -806,16 +800,6 @@ acpi_video_init_brightness(struct acpi_video_device *device)
 	br->count = count;
 	device->brightness = br;
 
-	/* Check the input/output of _BQC/_BCL/_BCM */
-	if ((max_level < 100) && (max_level <= (count - 2)))
-		br->flags._BCL_use_index = 1;
-
-	/*
-	 * _BCM is always consistent with _BCL,
-	 * at least for all the laptops we have ever seen.
-	 */
-	br->flags._BCM_use_index = br->flags._BCL_use_index;
-
 	/* _BQC uses INDEX while _BCL uses VALUE in some laptops */
 	br->curr = level = max_level;
 
@@ -877,7 +861,7 @@ out:
  *	device	: video output device (LCD, CRT, ..)
  *
  *  Return Value:
- *  	None
+ *	None
  *
  *  Find out all required AML methods defined under the output
  *  device.
@@ -885,28 +869,21 @@ out:
 
 static void acpi_video_device_find_cap(struct acpi_video_device *device)
 {
-	acpi_handle h_dummy1;
-
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
+	if (acpi_has_method(device->dev->handle, "_ADR"))
 		device->cap._ADR = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) {
+	if (acpi_has_method(device->dev->handle, "_BCL"))
 		device->cap._BCL = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
+	if (acpi_has_method(device->dev->handle, "_BCM"))
 		device->cap._BCM = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
+	if (acpi_has_method(device->dev->handle, "_BQC")) {
 		device->cap._BQC = 1;
-	else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ",
-				&h_dummy1))) {
+	} else if (acpi_has_method(device->dev->handle, "_BCQ")) {
 		printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n");
 		device->cap._BCQ = 1;
 	}
 
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
+	if (acpi_has_method(device->dev->handle, "_DDC"))
 		device->cap._DDC = 1;
-	}
 
 	if (acpi_video_init_brightness(device))
 		return;
@@ -917,7 +894,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 		acpi_handle acpi_parent;
 		struct device *parent = NULL;
 		int result;
-		static int count = 0;
+		static int count;
 		char *name;
 
 		name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
@@ -988,37 +965,29 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 }
 
 /*
- *  Arg:	
- *  	device	: video output device (VGA)
+ *  Arg:
+ *	device	: video output device (VGA)
  *
  *  Return Value:
- *  	None
+ *	None
  *
  *  Find out all required AML methods defined under the video bus device.
  */
 
 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
 {
-	acpi_handle h_dummy1;
-
-	if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
+	if (acpi_has_method(video->device->handle, "_DOS"))
 		video->cap._DOS = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) {
+	if (acpi_has_method(video->device->handle, "_DOD"))
 		video->cap._DOD = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) {
+	if (acpi_has_method(video->device->handle, "_ROM"))
 		video->cap._ROM = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) {
+	if (acpi_has_method(video->device->handle, "_GPD"))
 		video->cap._GPD = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) {
+	if (acpi_has_method(video->device->handle, "_SPD"))
 		video->cap._SPD = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) {
+	if (acpi_has_method(video->device->handle, "_VPO"))
 		video->cap._VPO = 1;
-	}
 }
 
 /*
@@ -1039,7 +1008,8 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
 		return -ENODEV;
 	pci_dev_put(dev);
 
-	/* Since there is no HID, CID and so on for VGA driver, we have
+	/*
+	 * Since there is no HID, CID and so on for VGA driver, we have
 	 * to check well known required nodes.
 	 */
 
@@ -1069,12 +1039,14 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
 	return status;
 }
 
-/* --------------------------------------------------------------------------
-                                 Driver Interface
-   -------------------------------------------------------------------------- */
+/*
+ * --------------------------------------------------------------------------
+ *                               Driver Interface
+ * --------------------------------------------------------------------------
+ */
 
 /* device interface */
-static struct acpi_video_device_attrib*
+static struct acpi_video_device_attrib *
 acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
 {
 	struct acpi_video_enumerated_device *ids;
@@ -1112,7 +1084,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 	unsigned long long device_id;
 	int status, device_type;
 	struct acpi_video_device *data;
-	struct acpi_video_device_attrib* attribute;
+	struct acpi_video_device_attrib *attribute;
 
 	status =
 	    acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
@@ -1134,7 +1106,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
 	attribute = acpi_video_get_device_attr(video, device_id);
 
-	if((attribute != NULL) && attribute->device_id_scheme) {
+	if (attribute && attribute->device_id_scheme) {
 		switch (attribute->display_type) {
 		case ACPI_VIDEO_DISPLAY_CRT:
 			data->flags.crt = 1;
@@ -1152,24 +1124,24 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 			data->flags.unknown = 1;
 			break;
 		}
-		if(attribute->bios_can_detect)
+		if (attribute->bios_can_detect)
 			data->flags.bios = 1;
 	} else {
 		/* Check for legacy IDs */
 		device_type = acpi_video_get_device_type(video, device_id);
 		/* Ignore bits 16 and 18-20 */
 		switch (device_type & 0xffe2ffff) {
-			case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
-				data->flags.crt = 1;
-				break;
-			case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
-				data->flags.lcd = 1;
-				break;
-			case ACPI_VIDEO_DISPLAY_LEGACY_TV:
-				data->flags.tvout = 1;
-				break;
-			default:
-				data->flags.unknown = 1;
+		case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
+			data->flags.crt = 1;
+			break;
+		case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
+			data->flags.lcd = 1;
+			break;
+		case ACPI_VIDEO_DISPLAY_LEGACY_TV:
+			data->flags.tvout = 1;
+			break;
+		default:
+			data->flags.unknown = 1;
 		}
 	}
 
@@ -1192,12 +1164,12 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
 /*
  *  Arg:
- *  	video	: video bus device 
+ *	video	: video bus device
  *
  *  Return:
- *  	none
- *  
- *  Enumerate the video device list of the video bus, 
+ *	none
+ *
+ *  Enumerate the video device list of the video bus,
  *  bind the ids with the corresponding video devices
  *  under the video bus.
  */
@@ -1216,13 +1188,13 @@ static void acpi_video_device_rebind(struct acpi_video_bus *video)
 
 /*
  *  Arg:
- *  	video	: video bus device 
- *  	device	: video output device under the video 
- *  		bus
+ *	video	: video bus device
+ *	device	: video output device under the video
+ *		bus
  *
  *  Return:
- *  	none
- *  
+ *	none
+ *
  *  Bind the ids with the corresponding video devices
  *  under the video bus.
  */
@@ -1245,11 +1217,11 @@ acpi_video_device_bind(struct acpi_video_bus *video,
 
 /*
  *  Arg:
- *  	video	: video bus device 
+ *	video	: video bus device
  *
  *  Return:
- *  	< 0	: error
- *  
+ *	< 0	: error
+ *
  *  Call _DOD to enumerate all devices attached to display adapter
  *
  */
@@ -1310,7 +1282,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
 	video->attached_array = active_list;
 	video->attached_count = count;
 
- out:
+out:
 	kfree(buffer.pointer);
 	return status;
 }
@@ -1577,7 +1549,6 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
 	switch (event) {
 	case ACPI_VIDEO_NOTIFY_SWITCH:	/* User requested a switch,
 					 * most likely via hotkey. */
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_SWITCHVIDEOMODE;
 		break;
 
@@ -1585,20 +1556,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
 					 * connector. */
 		acpi_video_device_enumerate(video);
 		acpi_video_device_rebind(video);
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_SWITCHVIDEOMODE;
 		break;
 
 	case ACPI_VIDEO_NOTIFY_CYCLE:	/* Cycle Display output hotkey pressed. */
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_SWITCHVIDEOMODE;
 		break;
 	case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:	/* Next Display output hotkey pressed. */
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_VIDEO_NEXT;
 		break;
 	case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:	/* previous Display output hotkey pressed. */
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_VIDEO_PREV;
 		break;
 
@@ -1641,31 +1608,26 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 	case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:	/* Cycle brightness */
 		if (brightness_switch_enabled)
 			acpi_video_switch_brightness(video_device, event);
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_BRIGHTNESS_CYCLE;
 		break;
 	case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:	/* Increase brightness */
 		if (brightness_switch_enabled)
 			acpi_video_switch_brightness(video_device, event);
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_BRIGHTNESSUP;
 		break;
 	case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:	/* Decrease brightness */
 		if (brightness_switch_enabled)
 			acpi_video_switch_brightness(video_device, event);
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_BRIGHTNESSDOWN;
 		break;
 	case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:	/* zero brightness */
 		if (brightness_switch_enabled)
 			acpi_video_switch_brightness(video_device, event);
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_BRIGHTNESS_ZERO;
 		break;
 	case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:	/* display device off */
 		if (brightness_switch_enabled)
 			acpi_video_switch_brightness(video_device, event);
-		acpi_bus_generate_proc_event(device, event, 0);
 		keycode = KEY_DISPLAY_OFF;
 		break;
 	default:
@@ -1765,7 +1727,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
 	if (!strcmp(device->pnp.bus_id, "VID")) {
 		if (instance)
 			device->pnp.bus_id[3] = '0' + instance;
-		instance ++;
+		instance++;
 	}
 	/* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
 	if (!strcmp(device->pnp.bus_id, "VGA")) {
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index c339774..940edbf 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -53,14 +53,13 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
 			  void **retyurn_value)
 {
 	long *cap = context;
-	acpi_handle h_dummy;
 
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) {
+	if (acpi_has_method(handle, "_BCM") &&
+	    acpi_has_method(handle, "_BCL")) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
 				  "support\n"));
 		*cap |= ACPI_VIDEO_BACKLIGHT;
-		if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy)))
+		if (!acpi_has_method(handle, "_BQC"))
 			printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
 				"cannot determine initial brightness\n");
 		/* We have backlight support, no need to scan further */
@@ -79,22 +78,20 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
  */
 long acpi_is_video_device(acpi_handle handle)
 {
-	acpi_handle h_dummy;
 	long video_caps = 0;
 
 	/* Is this device able to support video switching ? */
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) ||
-	    ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy)))
+	if (acpi_has_method(handle, "_DOD") || acpi_has_method(handle, "_DOS"))
 		video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
 
 	/* Is this device able to retrieve a video ROM ? */
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy)))
+	if (acpi_has_method(handle, "_ROM"))
 		video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
 
 	/* Is this device able to configure which video head to be POSTed ? */
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy)))
+	if (acpi_has_method(handle, "_VPO") &&
+	    acpi_has_method(handle, "_GPD") &&
+	    acpi_has_method(handle, "_SPD"))
 		video_caps |= ACPI_VIDEO_DEVICE_POSTING;
 
 	/* Only check for backlight functionality if one of the above hit. */
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index cf4e702..da8170d 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -947,11 +947,11 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)
 			continue;
 
 		acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ?
-						ACPI_STATE_D0 : ACPI_STATE_D3);
+					ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
 	}
 
 	if (!(state.event & PM_EVENT_RESUME))
-		acpi_bus_set_power(port_handle, ACPI_STATE_D3);
+		acpi_bus_set_power(port_handle, ACPI_STATE_D3_COLD);
 }
 
 /**
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 577d902..cc8a6e8 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -120,8 +120,6 @@ extern void ata_acpi_on_disable(struct ata_device *dev);
 extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
 extern int ata_acpi_register(void);
 extern void ata_acpi_unregister(void);
-extern void ata_acpi_bind(struct ata_device *dev);
-extern void ata_acpi_unbind(struct ata_device *dev);
 extern void ata_acpi_hotplug_init(struct ata_host *host);
 #else
 static inline void ata_acpi_dissociate(struct ata_host *host) { }
@@ -133,8 +131,6 @@ static inline void ata_acpi_set_state(struct ata_port *ap,
 				      pm_message_t state) { }
 static inline int ata_acpi_register(void) { return 0; }
 static inline void ata_acpi_unregister(void) { }
-static inline void ata_acpi_bind(struct ata_device *dev) { }
-static inline void ata_acpi_unbind(struct ata_device *dev) { }
 static inline void ata_acpi_hotplug_init(struct ata_host *host) {}
 #endif
 
diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
index 8d493b4..d59d523 100644
--- a/drivers/ata/pata_at32.c
+++ b/drivers/ata/pata_at32.c
@@ -271,7 +271,7 @@ static int __init pata_at32_probe(struct platform_device *pdev)
 
 	struct device		 *dev = &pdev->dev;
 	struct at32_ide_info	 *info;
-	struct ide_platform_data *board = pdev->dev.platform_data;
+	struct ide_platform_data *board = dev_get_platdata(&pdev->dev);
 	struct resource		 *res;
 
 	int irq;
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index 5364f97..d63ee8f 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -315,7 +315,7 @@ static struct ata_port_operations pata_at91_port_ops = {
 
 static int pata_at91_probe(struct platform_device *pdev)
 {
-	struct at91_cf_data *board = pdev->dev.platform_data;
+	struct at91_cf_data *board = dev_get_platdata(&pdev->dev);
 	struct device *dev = &pdev->dev;
 	struct at91_ide_info *info;
 	struct resource *mem_res;
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c
index 4ec7c04..26386f0 100644
--- a/drivers/ata/pata_imx.c
+++ b/drivers/ata/pata_imx.c
@@ -237,6 +237,7 @@ static const struct of_device_id imx_pata_dt_ids[] = {
 		/* sentinel */
 	}
 };
+MODULE_DEVICE_TABLE(of, imx_pata_dt_ids);
 
 static struct platform_driver pata_imx_driver = {
 	.probe		= pata_imx_probe,
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index dcc6b24..1ec53f8 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -48,7 +48,7 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
 	u16 *buf16 = (u16 *) buf;
 	struct ata_port *ap = dev->link->ap;
 	void __iomem *mmio = ap->ioaddr.data_addr;
-	struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
+	struct ixp4xx_pata_data *data = dev_get_platdata(ap->host->dev);
 
 	/* set the expansion bus in 16bit mode and restore
 	 * 8 bit mode after the transaction.
@@ -143,7 +143,7 @@ static int ixp4xx_pata_probe(struct platform_device *pdev)
 	struct resource *cs0, *cs1;
 	struct ata_host *host;
 	struct ata_port *ap;
-	struct ixp4xx_pata_data *data = pdev->dev.platform_data;
+	struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev);
 
 	cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index e73bef3..c51bbb9 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -1037,7 +1037,7 @@ static void octeon_cf_shutdown(struct device *dev)
 	union cvmx_mio_boot_dma_cfgx dma_cfg;
 	union cvmx_mio_boot_dma_intx dma_int;
 
-	struct octeon_cf_port *cf_port = dev->platform_data;
+	struct octeon_cf_port *cf_port = dev_get_platdata(dev);
 
 	if (cf_port->dma_base) {
 		/* Stop and clear the dma engine.  */
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 71e0937..0279488 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -180,7 +180,7 @@ static int pata_platform_probe(struct platform_device *pdev)
 	struct resource *io_res;
 	struct resource *ctl_res;
 	struct resource *irq_res;
-	struct pata_platform_info *pp_info = pdev->dev.platform_data;
+	struct pata_platform_info *pp_info = dev_get_platdata(&pdev->dev);
 
 	/*
 	 * Simple resource validation ..
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 942ef94..a6f05ac 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -238,7 +238,7 @@ static int pxa_ata_probe(struct platform_device *pdev)
 	struct resource *ctl_res;
 	struct resource *dma_res;
 	struct resource *irq_res;
-	struct pata_pxa_pdata *pdata = pdev->dev.platform_data;
+	struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev);
 	int ret = 0;
 
 	/*
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index 6ef27e9..951aa95 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -475,7 +475,7 @@ static void pata_s3c_hwinit(struct s3c_ide_info *info,
 
 static int __init pata_s3c_probe(struct platform_device *pdev)
 {
-	struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
+	struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev);
 	struct device *dev = &pdev->dev;
 	struct s3c_ide_info *info;
 	struct resource *res;
@@ -617,7 +617,7 @@ static int pata_s3c_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct ata_host *host = platform_get_drvdata(pdev);
-	struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
+	struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev);
 	struct s3c_ide_info *info = host->private_data;
 
 	pata_s3c_hwinit(info, pdata);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 35c6b6d..56be318 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -553,10 +553,15 @@ struct mv_host_priv {
 	u32			irq_mask_offset;
 	u32			unmask_all_irqs;
 
-#if defined(CONFIG_HAVE_CLK)
+	/*
+	 * Needed on some devices that require their clocks to be enabled.
+	 * These are optional: if the platform device does not have any
+	 * clocks, they won't be used.  Also, if the underlying hardware
+	 * does not support the common clock framework (CONFIG_HAVE_CLK=n),
+	 * all the clock operations become no-ops (see clk.h).
+	 */
 	struct clk		*clk;
 	struct clk              **port_clks;
-#endif
 	/*
 	 * These consistent DMA memory pools give us guaranteed
 	 * alignment for hardware-accessed data structures,
@@ -4032,9 +4037,7 @@ static int mv_platform_probe(struct platform_device *pdev)
 	struct resource *res;
 	int n_ports = 0, irq = 0;
 	int rc;
-#if defined(CONFIG_HAVE_CLK)
 	int port;
-#endif
 
 	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
@@ -4058,7 +4061,7 @@ static int mv_platform_probe(struct platform_device *pdev)
 		of_property_read_u32(pdev->dev.of_node, "nr-ports", &n_ports);
 		irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
 	} else {
-		mv_platform_data = pdev->dev.platform_data;
+		mv_platform_data = dev_get_platdata(&pdev->dev);
 		n_ports = mv_platform_data->n_ports;
 		irq = platform_get_irq(pdev, 0);
 	}
@@ -4068,13 +4071,11 @@ static int mv_platform_probe(struct platform_device *pdev)
 
 	if (!host || !hpriv)
 		return -ENOMEM;
-#if defined(CONFIG_HAVE_CLK)
 	hpriv->port_clks = devm_kzalloc(&pdev->dev,
 					sizeof(struct clk *) * n_ports,
 					GFP_KERNEL);
 	if (!hpriv->port_clks)
 		return -ENOMEM;
-#endif
 	host->private_data = hpriv;
 	hpriv->n_ports = n_ports;
 	hpriv->board_idx = chip_soc;
@@ -4084,7 +4085,6 @@ static int mv_platform_probe(struct platform_device *pdev)
 				   resource_size(res));
 	hpriv->base -= SATAHC0_REG_BASE;
 
-#if defined(CONFIG_HAVE_CLK)
 	hpriv->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(hpriv->clk))
 		dev_notice(&pdev->dev, "cannot get optional clkdev\n");
@@ -4098,7 +4098,6 @@ static int mv_platform_probe(struct platform_device *pdev)
 		if (!IS_ERR(hpriv->port_clks[port]))
 			clk_prepare_enable(hpriv->port_clks[port]);
 	}
-#endif
 
 	/*
 	 * (Re-)program MBUS remapping windows if we are asked to.
@@ -4124,7 +4123,6 @@ static int mv_platform_probe(struct platform_device *pdev)
 		return 0;
 
 err:
-#if defined(CONFIG_HAVE_CLK)
 	if (!IS_ERR(hpriv->clk)) {
 		clk_disable_unprepare(hpriv->clk);
 		clk_put(hpriv->clk);
@@ -4135,7 +4133,6 @@ err:
 			clk_put(hpriv->port_clks[port]);
 		}
 	}
-#endif
 
 	return rc;
 }
@@ -4151,13 +4148,10 @@ err:
 static int mv_platform_remove(struct platform_device *pdev)
 {
 	struct ata_host *host = platform_get_drvdata(pdev);
-#if defined(CONFIG_HAVE_CLK)
 	struct mv_host_priv *hpriv = host->private_data;
 	int port;
-#endif
 	ata_host_detach(host);
 
-#if defined(CONFIG_HAVE_CLK)
 	if (!IS_ERR(hpriv->clk)) {
 		clk_disable_unprepare(hpriv->clk);
 		clk_put(hpriv->clk);
@@ -4168,7 +4162,6 @@ static int mv_platform_remove(struct platform_device *pdev)
 			clk_put(hpriv->port_clks[port]);
 		}
 	}
-#endif
 	return 0;
 }
 
@@ -4428,9 +4421,6 @@ static int mv_pci_device_resume(struct pci_dev *pdev)
 #endif
 #endif
 
-static int mv_platform_probe(struct platform_device *pdev);
-static int mv_platform_remove(struct platform_device *pdev);
-
 static int __init mv_init(void)
 {
 	int rc = -ENODEV;
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 507362a..80f9743 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -2872,15 +2872,4 @@ static struct pci_driver he_driver = {
 	.id_table =	he_pci_tbl,
 };
 
-static int __init he_init(void)
-{
-	return pci_register_driver(&he_driver);
-}
-
-static void __exit he_cleanup(void)
-{
-	pci_unregister_driver(&he_driver);
-}
-
-module_init(he_init);
-module_exit(he_cleanup);
+module_pci_driver(he_driver);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 5daa259..e373671 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -200,11 +200,9 @@ config DMA_SHARED_BUFFER
 	  APIs extension; the file's descriptor can then be passed on to other
 	  driver.
 
-config CMA
-	bool "Contiguous Memory Allocator"
-	depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
-	select MIGRATION
-	select MEMORY_ISOLATION
+config DMA_CMA
+	bool "DMA Contiguous Memory Allocator"
+	depends on HAVE_DMA_CONTIGUOUS && CMA
 	help
 	  This enables the Contiguous Memory Allocator which allows drivers
 	  to allocate big physically-contiguous blocks of memory for use with
@@ -213,17 +211,7 @@ config CMA
 	  For more information see <include/linux/dma-contiguous.h>.
 	  If unsure, say "n".
 
-if CMA
-
-config CMA_DEBUG
-	bool "CMA debug messages (DEVELOPMENT)"
-	depends on DEBUG_KERNEL
-	help
-	  Turns on debug messages in CMA.  This produces KERN_DEBUG
-	  messages for every CMA call as well as various messages while
-	  processing calls such as dma_alloc_from_contiguous().
-	  This option does not affect warning and error messages.
-
+if  DMA_CMA
 comment "Default contiguous memory area size:"
 
 config CMA_SIZE_MBYTES
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 48029aa..94e8a80 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -6,7 +6,7 @@ obj-y			:= core.o bus.o dd.o syscore.o \
 			   attribute_container.o transport_class.o \
 			   topology.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
-obj-$(CONFIG_CMA) += dma-contiguous.o
+obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
 obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8856d74..e51c787 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -38,7 +38,7 @@ long sysfs_deprecated = 0;
 #endif
 static __init int sysfs_deprecated_setup(char *arg)
 {
-	return strict_strtol(arg, 10, &sysfs_deprecated);
+	return kstrtol(arg, 10, &sysfs_deprecated);
 }
 early_param("sysfs.deprecated", sysfs_deprecated_setup);
 #endif
@@ -626,6 +626,7 @@ int device_create_file(struct device *dev,
 
 	return error;
 }
+EXPORT_SYMBOL_GPL(device_create_file);
 
 /**
  * device_remove_file - remove sysfs attribute file.
@@ -638,6 +639,7 @@ void device_remove_file(struct device *dev,
 	if (dev)
 		sysfs_remove_file(&dev->kobj, &attr->attr);
 }
+EXPORT_SYMBOL_GPL(device_remove_file);
 
 /**
  * device_create_bin_file - create sysfs binary attribute file for device.
@@ -748,6 +750,7 @@ void device_initialize(struct device *dev)
 	device_pm_init(dev);
 	set_dev_node(dev, -1);
 }
+EXPORT_SYMBOL_GPL(device_initialize);
 
 struct kobject *virtual_device_parent(struct device *dev)
 {
@@ -1187,6 +1190,7 @@ name_error:
 	dev->p = NULL;
 	goto done;
 }
+EXPORT_SYMBOL_GPL(device_add);
 
 /**
  * device_register - register a device with the system.
@@ -1211,6 +1215,7 @@ int device_register(struct device *dev)
 	device_initialize(dev);
 	return device_add(dev);
 }
+EXPORT_SYMBOL_GPL(device_register);
 
 /**
  * get_device - increment reference count for device.
@@ -1224,6 +1229,7 @@ struct device *get_device(struct device *dev)
 {
 	return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
 }
+EXPORT_SYMBOL_GPL(get_device);
 
 /**
  * put_device - decrement reference count.
@@ -1235,6 +1241,7 @@ void put_device(struct device *dev)
 	if (dev)
 		kobject_put(&dev->kobj);
 }
+EXPORT_SYMBOL_GPL(put_device);
 
 /**
  * device_del - delete device from system.
@@ -1297,6 +1304,7 @@ void device_del(struct device *dev)
 	kobject_del(&dev->kobj);
 	put_device(parent);
 }
+EXPORT_SYMBOL_GPL(device_del);
 
 /**
  * device_unregister - unregister device from system.
@@ -1315,6 +1323,7 @@ void device_unregister(struct device *dev)
 	device_del(dev);
 	put_device(dev);
 }
+EXPORT_SYMBOL_GPL(device_unregister);
 
 static struct device *next_device(struct klist_iter *i)
 {
@@ -1403,6 +1412,7 @@ int device_for_each_child(struct device *parent, void *data,
 	klist_iter_exit(&i);
 	return error;
 }
+EXPORT_SYMBOL_GPL(device_for_each_child);
 
 /**
  * device_find_child - device iterator for locating a particular device.
@@ -1437,6 +1447,7 @@ struct device *device_find_child(struct device *parent, void *data,
 	klist_iter_exit(&i);
 	return child;
 }
+EXPORT_SYMBOL_GPL(device_find_child);
 
 int __init devices_init(void)
 {
@@ -1464,21 +1475,6 @@ int __init devices_init(void)
 	return -ENOMEM;
 }
 
-EXPORT_SYMBOL_GPL(device_for_each_child);
-EXPORT_SYMBOL_GPL(device_find_child);
-
-EXPORT_SYMBOL_GPL(device_initialize);
-EXPORT_SYMBOL_GPL(device_add);
-EXPORT_SYMBOL_GPL(device_register);
-
-EXPORT_SYMBOL_GPL(device_del);
-EXPORT_SYMBOL_GPL(device_unregister);
-EXPORT_SYMBOL_GPL(get_device);
-EXPORT_SYMBOL_GPL(put_device);
-
-EXPORT_SYMBOL_GPL(device_create_file);
-EXPORT_SYMBOL_GPL(device_remove_file);
-
 static DEFINE_MUTEX(device_hotplug_lock);
 
 void lock_device_hotplug(void)
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 6687ba7..1219ab7 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -680,7 +680,7 @@ int dma_buf_debugfs_create_file(const char *name,
 	d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir,
 			write, &dma_buf_debug_fops);
 
-	return PTR_RET(d);
+	return PTR_ERR_OR_ZERO(d);
 }
 #else
 static inline int dma_buf_init_debugfs(void)
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 2b7813e..ddd14ce 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -469,7 +469,7 @@ store_soft_offline_page(struct device *dev,
 	u64 pfn;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (strict_strtoull(buf, 0, &pfn) < 0)
+	if (kstrtoull(buf, 0, &pfn) < 0)
 		return -EINVAL;
 	pfn >>= PAGE_SHIFT;
 	if (!pfn_valid(pfn))
@@ -488,7 +488,7 @@ store_hard_offline_page(struct device *dev,
 	u64 pfn;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (strict_strtoull(buf, 0, &pfn) < 0)
+	if (kstrtoull(buf, 0, &pfn) < 0)
 		return -EINVAL;
 	pfn >>= PAGE_SHIFT;
 	ret = memory_failure(pfn, 0, 0);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 7616a77..bc9f43b 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -125,13 +125,7 @@ static ssize_t node_read_meminfo(struct device *dev,
 		       nid, K(node_page_state(nid, NR_WRITEBACK)),
 		       nid, K(node_page_state(nid, NR_FILE_PAGES)),
 		       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-		       nid, K(node_page_state(nid, NR_ANON_PAGES)
-			+ node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-			HPAGE_PMD_NR),
-#else
 		       nid, K(node_page_state(nid, NR_ANON_PAGES)),
-#endif
 		       nid, K(node_page_state(nid, NR_SHMEM)),
 		       nid, node_page_state(nid, NR_KERNEL_STACK) *
 				THREAD_SIZE / 1024,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 5a9b656..9f098a8 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/async.h>
 #include <linux/suspend.h>
+#include <trace/events/power.h>
 #include <linux/cpuidle.h>
 #include "../base.h"
 #include "power.h"
@@ -56,6 +57,30 @@ static pm_message_t pm_transition;
 
 static int async_error;
 
+static char *pm_verb(int event)
+{
+	switch (event) {
+	case PM_EVENT_SUSPEND:
+		return "suspend";
+	case PM_EVENT_RESUME:
+		return "resume";
+	case PM_EVENT_FREEZE:
+		return "freeze";
+	case PM_EVENT_QUIESCE:
+		return "quiesce";
+	case PM_EVENT_HIBERNATE:
+		return "hibernate";
+	case PM_EVENT_THAW:
+		return "thaw";
+	case PM_EVENT_RESTORE:
+		return "restore";
+	case PM_EVENT_RECOVER:
+		return "recover";
+	default:
+		return "(unknown PM event)";
+	}
+}
+
 /**
  * device_pm_sleep_init - Initialize system suspend-related device fields.
  * @dev: Device object being initialized.
@@ -172,16 +197,21 @@ static ktime_t initcall_debug_start(struct device *dev)
 }
 
 static void initcall_debug_report(struct device *dev, ktime_t calltime,
-				  int error)
+				  int error, pm_message_t state, char *info)
 {
-	ktime_t delta, rettime;
+	ktime_t rettime;
+	s64 nsecs;
+
+	rettime = ktime_get();
+	nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
 
 	if (pm_print_times_enabled) {
-		rettime = ktime_get();
-		delta = ktime_sub(rettime, calltime);
 		pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
-			error, (unsigned long long)ktime_to_ns(delta) >> 10);
+			error, (unsigned long long)nsecs >> 10);
 	}
+
+	trace_device_pm_report_time(dev, info, nsecs, pm_verb(state.event),
+				    error);
 }
 
 /**
@@ -309,30 +339,6 @@ static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t stat
 	return NULL;
 }
 
-static char *pm_verb(int event)
-{
-	switch (event) {
-	case PM_EVENT_SUSPEND:
-		return "suspend";
-	case PM_EVENT_RESUME:
-		return "resume";
-	case PM_EVENT_FREEZE:
-		return "freeze";
-	case PM_EVENT_QUIESCE:
-		return "quiesce";
-	case PM_EVENT_HIBERNATE:
-		return "hibernate";
-	case PM_EVENT_THAW:
-		return "thaw";
-	case PM_EVENT_RESTORE:
-		return "restore";
-	case PM_EVENT_RECOVER:
-		return "recover";
-	default:
-		return "(unknown PM event)";
-	}
-}
-
 static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
 {
 	dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
@@ -379,7 +385,7 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev,
 	error = cb(dev);
 	suspend_report_result(cb, error);
 
-	initcall_debug_report(dev, calltime, error);
+	initcall_debug_report(dev, calltime, error, state, info);
 
 	return error;
 }
@@ -1027,7 +1033,8 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
  * @cb: Suspend callback to execute.
  */
 static int legacy_suspend(struct device *dev, pm_message_t state,
-			  int (*cb)(struct device *dev, pm_message_t state))
+			  int (*cb)(struct device *dev, pm_message_t state),
+			  char *info)
 {
 	int error;
 	ktime_t calltime;
@@ -1037,7 +1044,7 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
 	error = cb(dev, state);
 	suspend_report_result(cb, error);
 
-	initcall_debug_report(dev, calltime, error);
+	initcall_debug_report(dev, calltime, error, state, info);
 
 	return error;
 }
@@ -1097,7 +1104,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 			goto Run;
 		} else if (dev->class->suspend) {
 			pm_dev_dbg(dev, state, "legacy class ");
-			error = legacy_suspend(dev, state, dev->class->suspend);
+			error = legacy_suspend(dev, state, dev->class->suspend,
+						"legacy class ");
 			goto End;
 		}
 	}
@@ -1108,7 +1116,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 			callback = pm_op(dev->bus->pm, state);
 		} else if (dev->bus->suspend) {
 			pm_dev_dbg(dev, state, "legacy bus ");
-			error = legacy_suspend(dev, state, dev->bus->suspend);
+			error = legacy_suspend(dev, state, dev->bus->suspend,
+						"legacy bus ");
 			goto End;
 		}
 	}
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index c8ec186..ef89897 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -460,6 +460,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 	srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(opp_add);
 
 /**
  * opp_set_availability() - helper to set the availability of an opp
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a53ebd2..03e089a 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -206,7 +206,7 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
 	if (!dev->power.use_autosuspend)
 		return -EIO;
 
-	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
+	if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay)
 		return -EINVAL;
 
 	device_lock(dev);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index e691026..3455f83 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -719,7 +719,8 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
 		}
 	}
 
-	return regcache_sync_block_raw_flush(map, &data, base, regtmp);
+	return regcache_sync_block_raw_flush(map, &data, base, regtmp +
+			map->reg_stride);
 }
 
 int regcache_sync_block(struct regmap *map, void *block,
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 5349575..634164d 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -281,7 +281,7 @@ static ssize_t regmap_map_write_file(struct file *file,
 	reg = simple_strtoul(start, &start, 16);
 	while (*start == ' ')
 		start++;
-	if (strict_strtoul(start, 16, &value))
+	if (kstrtoul(start, 16, &value))
 		return -EINVAL;
 
 	/* Userspace has been fiddling around behind the kernel's back */
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 1643e88..d10456f 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -418,6 +418,31 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 				reg, ret);
 			goto err_alloc;
 		}
+
+		if (!chip->init_ack_masked)
+			continue;
+
+		/* Ack masked but set interrupts */
+		reg = chip->status_base +
+			(i * map->reg_stride * d->irq_reg_stride);
+		ret = regmap_read(map, reg, &d->status_buf[i]);
+		if (ret != 0) {
+			dev_err(map->dev, "Failed to read IRQ status: %d\n",
+				ret);
+			goto err_alloc;
+		}
+
+		if (d->status_buf[i] && chip->ack_base) {
+			reg = chip->ack_base +
+				(i * map->reg_stride * d->irq_reg_stride);
+			ret = regmap_write(map, reg,
+					d->status_buf[i] & d->mask_buf[i]);
+			if (ret != 0) {
+				dev_err(map->dev, "Failed to ack 0x%x: %d\n",
+					reg, ret);
+				goto err_alloc;
+			}
+		}
 	}
 
 	/* Wake is disabled by default */
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index e0d0c7d..fa76b61 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -303,6 +303,7 @@ static void regmap_unlock_mutex(void *__map)
 }
 
 static void regmap_lock_spinlock(void *__map)
+__acquires(&map->spinlock)
 {
 	struct regmap *map = __map;
 	unsigned long flags;
@@ -312,6 +313,7 @@ static void regmap_lock_spinlock(void *__map)
 }
 
 static void regmap_unlock_spinlock(void *__map)
+__releases(&map->spinlock)
 {
 	struct regmap *map = __map;
 	spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags);
@@ -687,6 +689,10 @@ skip_format_initialization:
 			unsigned win_max = win_min +
 					   config->ranges[j].window_len - 1;
 
+			/* Allow data window inside its own virtual range */
+			if (j == i)
+				continue;
+
 			if (range_cfg->range_min <= sel_reg &&
 			    sel_reg <= range_cfg->range_max) {
 				dev_err(map->dev,
@@ -1888,13 +1894,10 @@ EXPORT_SYMBOL_GPL(regmap_async_complete);
 int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 			  int num_regs)
 {
+	struct reg_default *p;
 	int i, ret;
 	bool bypass;
 
-	/* If needed the implementation can be extended to support this */
-	if (map->patch)
-		return -EBUSY;
-
 	map->lock(map->lock_arg);
 
 	bypass = map->cache_bypass;
@@ -1911,11 +1914,13 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 		}
 	}
 
-	map->patch = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL);
-	if (map->patch != NULL) {
-		memcpy(map->patch, regs,
-		       num_regs * sizeof(struct reg_default));
-		map->patch_regs = num_regs;
+	p = krealloc(map->patch,
+		     sizeof(struct reg_default) * (map->patch_regs + num_regs),
+		     GFP_KERNEL);
+	if (p) {
+		memcpy(p + map->patch_regs, regs, num_regs);
+		map->patch = p;
+		map->patch_regs += num_regs;
 	} else {
 		ret = -ENOMEM;
 	}
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 2f5919e..94ffee3 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -62,25 +62,6 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
 }
 #endif
 
-#ifdef arch_provides_topology_pointers
-#define define_siblings_show_map(name)					\
-static ssize_t show_##name(struct device *dev,				\
-			   struct device_attribute *attr, char *buf)	\
-{									\
-	unsigned int cpu = dev->id;					\
-	return show_cpumap(0, topology_##name(cpu), buf);		\
-}
-
-#define define_siblings_show_list(name)					\
-static ssize_t show_##name##_list(struct device *dev,			\
-				  struct device_attribute *attr,	\
-				  char *buf)				\
-{									\
-	unsigned int cpu = dev->id;					\
-	return show_cpumap(1, topology_##name(cpu), buf);		\
-}
-
-#else
 #define define_siblings_show_map(name)					\
 static ssize_t show_##name(struct device *dev,				\
 			   struct device_attribute *attr, char *buf)	\
@@ -95,7 +76,6 @@ static ssize_t show_##name##_list(struct device *dev,			\
 {									\
 	return show_cpumap(1, topology_##name(dev->id), buf);		\
 }
-#endif
 
 #define define_siblings_show_func(name)		\
 	define_siblings_show_map(name); define_siblings_show_list(name)
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index 380a200..7c081b3 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -35,8 +35,14 @@ config BCMA_DRIVER_PCI_HOSTMODE
 	  PCI core hostmode operation (external PCI bus).
 
 config BCMA_HOST_SOC
-	bool
-	depends on BCMA_DRIVER_MIPS
+	bool "Support for BCMA in a SoC"
+	depends on BCMA
+	help
+	  Host interface for a Broadcom AIX bus directly mapped into
+	  the memory. This only works with the Broadcom SoCs from the
+	  BCM47XX line.
+
+	  If unsure, say N
 
 config BCMA_DRIVER_MIPS
 	bool "BCMA Broadcom MIPS core driver"
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 0067422..90ee350 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -237,7 +237,7 @@ int bcma_bus_register(struct bcma_bus *bus)
 	err = bcma_bus_scan(bus);
 	if (err) {
 		bcma_err(bus, "Failed to scan: %d\n", err);
-		return -1;
+		return err;
 	}
 
 	/* Early init CC core */
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 8bffa5c..cd6b20f 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -32,6 +32,18 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
 	{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
 	{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
 	{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
+	{ BCMA_CORE_PCIEG2, "PCIe Gen 2" },
+	{ BCMA_CORE_DMA, "DMA" },
+	{ BCMA_CORE_SDIO3, "SDIO3" },
+	{ BCMA_CORE_USB20, "USB 2.0" },
+	{ BCMA_CORE_USB30, "USB 3.0" },
+	{ BCMA_CORE_A9JTAG, "ARM Cortex A9 JTAG" },
+	{ BCMA_CORE_DDR23, "Denali DDR2/DDR3 memory controller" },
+	{ BCMA_CORE_ROM, "ROM" },
+	{ BCMA_CORE_NAND, "NAND flash controller" },
+	{ BCMA_CORE_QSPI, "SPI flash controller" },
+	{ BCMA_CORE_CHIPCOMMON_B, "Chipcommon B" },
+	{ BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" },
 	{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
 	{ BCMA_CORE_ALTA, "ALTA (I2S)" },
 	{ BCMA_CORE_INVALID, "Invalid" },
@@ -201,7 +213,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
 	return ent;
 }
 
-static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
+static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
 				  u32 type, u8 port)
 {
 	u32 addrl, addrh, sizel, sizeh = 0;
@@ -213,7 +225,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
 	    ((ent & SCAN_ADDR_TYPE) != type) ||
 	    (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
 		bcma_erom_push_ent(eromptr);
-		return -EINVAL;
+		return (u32)-EINVAL;
 	}
 
 	addrl = ent & SCAN_ADDR_ADDR;
@@ -261,7 +273,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
 			      struct bcma_device_id *match, int core_num,
 			      struct bcma_device *core)
 {
-	s32 tmp;
+	u32 tmp;
 	u8 i, j;
 	s32 cia, cib;
 	u8 ports[2], wrappers[2];
@@ -339,11 +351,11 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
 	 * the main register space for the core
 	 */
 	tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
-	if (tmp <= 0) {
+	if (tmp == 0 || IS_ERR_VALUE(tmp)) {
 		/* Try again to see if it is a bridge */
 		tmp = bcma_erom_get_addr_desc(bus, eromptr,
 					      SCAN_ADDR_TYPE_BRIDGE, 0);
-		if (tmp <= 0) {
+		if (tmp == 0 || IS_ERR_VALUE(tmp)) {
 			return -EILSEQ;
 		} else {
 			bcma_info(bus, "Bridge found\n");
@@ -357,7 +369,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
 		for (j = 0; ; j++) {
 			tmp = bcma_erom_get_addr_desc(bus, eromptr,
 				SCAN_ADDR_TYPE_SLAVE, i);
-			if (tmp < 0) {
+			if (IS_ERR_VALUE(tmp)) {
 				/* no more entries for port _i_ */
 				/* pr_debug("erom: slave port %d "
 				 * "has %d descriptors\n", i, j); */
@@ -374,7 +386,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
 		for (j = 0; ; j++) {
 			tmp = bcma_erom_get_addr_desc(bus, eromptr,
 				SCAN_ADDR_TYPE_MWRAP, i);
-			if (tmp < 0) {
+			if (IS_ERR_VALUE(tmp)) {
 				/* no more entries for port _i_ */
 				/* pr_debug("erom: master wrapper %d "
 				 * "has %d descriptors\n", i, j); */
@@ -392,7 +404,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
 		for (j = 0; ; j++) {
 			tmp = bcma_erom_get_addr_desc(bus, eromptr,
 				SCAN_ADDR_TYPE_SWRAP, i + hack);
-			if (tmp < 0) {
+			if (IS_ERR_VALUE(tmp)) {
 				/* no more entries for port _i_ */
 				/* pr_debug("erom: master wrapper %d "
 				 * has %d descriptors\n", i, j); */
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index e07a5fd..bb237c4 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -541,4 +541,10 @@ config BLK_DEV_RSXX
 	  To compile this driver as a module, choose M here: the
 	  module will be called rsxx.
 
+config BLOCKCONSOLE
+	bool "Block device console logging support"
+	help
+	  This enables logging to block devices.
+	  See <file:Documentation/block/blockconsole.txt> for details.
+
 endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index ca07399..2a63ed3 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= xen-blkback/
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
 obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX)	+= mtip32xx/
+obj-$(CONFIG_BLOCKCONSOLE)	+= blockconsole.o
 
 obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/
 
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 025c41d..14a9d19 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "83"
+#define VERSION "85"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -169,6 +169,7 @@ struct aoedev {
 	ulong ref;
 	struct work_struct work;/* disk create work struct */
 	struct gendisk *gd;
+	struct dentry *debugfs;
 	struct request_queue *blkq;
 	struct hd_geometry geo;
 	sector_t ssize;
@@ -206,6 +207,7 @@ struct ktstate {
 int aoeblk_init(void);
 void aoeblk_exit(void);
 void aoeblk_gdalloc(void *);
+void aoedisk_rm_debugfs(struct aoedev *d);
 void aoedisk_rm_sysfs(struct aoedev *d);
 
 int aoechr_init(void);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 916d9ed..d63dcf0 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoeblk.c
  * block device routines
@@ -17,11 +17,13 @@
 #include <linux/mutex.h>
 #include <linux/export.h>
 #include <linux/moduleparam.h>
+#include <linux/debugfs.h>
 #include <scsi/sg.h>
 #include "aoe.h"
 
 static DEFINE_MUTEX(aoeblk_mutex);
 static struct kmem_cache *buf_pool_cache;
+static struct dentry *aoe_debugfs_dir;
 
 /* GPFS needs a larger value than the default. */
 static int aoe_maxsectors;
@@ -108,6 +110,55 @@ static ssize_t aoedisk_show_payload(struct device *dev,
 	return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt);
 }
 
+static int aoedisk_debugfs_show(struct seq_file *s, void *ignored)
+{
+	struct aoedev *d;
+	struct aoetgt **t, **te;
+	struct aoeif *ifp, *ife;
+	unsigned long flags;
+	char c;
+
+	d = s->private;
+	seq_printf(s, "rttavg: %d rttdev: %d\n",
+		d->rttavg >> RTTSCALE,
+		d->rttdev >> RTTDSCALE);
+	seq_printf(s, "nskbpool: %d\n", skb_queue_len(&d->skbpool));
+	seq_printf(s, "kicked: %ld\n", d->kicked);
+	seq_printf(s, "maxbcnt: %ld\n", d->maxbcnt);
+	seq_printf(s, "ref: %ld\n", d->ref);
+
+	spin_lock_irqsave(&d->lock, flags);
+	t = d->targets;
+	te = t + d->ntargets;
+	for (; t < te && *t; t++) {
+		c = '\t';
+		seq_printf(s, "falloc: %ld\n", (*t)->falloc);
+		seq_printf(s, "ffree: %p\n",
+			list_empty(&(*t)->ffree) ? NULL : (*t)->ffree.next);
+		seq_printf(s, "%pm:%d:%d:%d\n", (*t)->addr, (*t)->nout,
+			(*t)->maxout, (*t)->nframes);
+		seq_printf(s, "\tssthresh:%d\n", (*t)->ssthresh);
+		seq_printf(s, "\ttaint:%d\n", (*t)->taint);
+		seq_printf(s, "\tr:%d\n", (*t)->rpkts);
+		seq_printf(s, "\tw:%d\n", (*t)->wpkts);
+		ifp = (*t)->ifs;
+		ife = ifp + ARRAY_SIZE((*t)->ifs);
+		for (; ifp->nd && ifp < ife; ifp++) {
+			seq_printf(s, "%c%s", c, ifp->nd->name);
+			c = ',';
+		}
+		seq_puts(s, "\n");
+	}
+	spin_unlock_irqrestore(&d->lock, flags);
+
+	return 0;
+}
+
+static int aoe_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, aoedisk_debugfs_show, inode->i_private);
+}
+
 static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
 static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
 static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
@@ -130,6 +181,45 @@ static const struct attribute_group attr_group = {
 	.attrs = aoe_attrs,
 };
 
+static const struct file_operations aoe_debugfs_fops = {
+	.open = aoe_debugfs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void
+aoedisk_add_debugfs(struct aoedev *d)
+{
+	struct dentry *entry;
+	char *p;
+
+	if (aoe_debugfs_dir == NULL)
+		return;
+	p = strchr(d->gd->disk_name, '/');
+	if (p == NULL)
+		p = d->gd->disk_name;
+	else
+		p++;
+	BUG_ON(*p == '\0');
+	entry = debugfs_create_file(p, 0444, aoe_debugfs_dir, d,
+				    &aoe_debugfs_fops);
+	if (IS_ERR_OR_NULL(entry)) {
+		pr_info("aoe: cannot create debugfs file for %s\n",
+			d->gd->disk_name);
+		return;
+	}
+	BUG_ON(d->debugfs);
+	d->debugfs = entry;
+}
+void
+aoedisk_rm_debugfs(struct aoedev *d)
+{
+	BUG_ON(d->debugfs == NULL);
+	debugfs_remove(d->debugfs);
+	d->debugfs = NULL;
+}
+
 static int
 aoedisk_add_sysfs(struct aoedev *d)
 {
@@ -330,6 +420,7 @@ aoeblk_gdalloc(void *vp)
 
 	add_disk(gd);
 	aoedisk_add_sysfs(d);
+	aoedisk_add_debugfs(d);
 
 	spin_lock_irqsave(&d->lock, flags);
 	WARN_ON(!(d->flags & DEVFL_GD_NOW));
@@ -351,6 +442,8 @@ err:
 void
 aoeblk_exit(void)
 {
+	debugfs_remove_recursive(aoe_debugfs_dir);
+	aoe_debugfs_dir = NULL;
 	kmem_cache_destroy(buf_pool_cache);
 }
 
@@ -362,7 +455,11 @@ aoeblk_init(void)
 					   0, 0, NULL);
 	if (buf_pool_cache == NULL)
 		return -ENOMEM;
-
+	aoe_debugfs_dir = debugfs_create_dir("aoe", NULL);
+	if (IS_ERR_OR_NULL(aoe_debugfs_dir)) {
+		pr_info("aoe: cannot create debugfs directory\n");
+		aoe_debugfs_dir = NULL;
+	}
 	return 0;
 }
 
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 99cb944..4d45dba 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -906,16 +906,10 @@ bio_pageinc(struct bio *bio)
 	int i;
 
 	bio_for_each_segment(bv, bio, i) {
-		page = bv->bv_page;
 		/* Non-zero page count for non-head members of
-		 * compound pages is no longer allowed by the kernel,
-		 * but this has never been seen here.
+		 * compound pages is no longer allowed by the kernel.
 		 */
-		if (unlikely(PageCompound(page)))
-			if (compound_trans_head(page) != page) {
-				pr_crit("page tail used for block I/O\n");
-				BUG();
-			}
+		page = compound_trans_head(bv->bv_page);
 		atomic_inc(&page->_count);
 	}
 }
@@ -924,10 +918,13 @@ static void
 bio_pagedec(struct bio *bio)
 {
 	struct bio_vec *bv;
+	struct page *page;
 	int i;
 
-	bio_for_each_segment(bv, bio, i)
-		atomic_dec(&bv->bv_page->_count);
+	bio_for_each_segment(bv, bio, i) {
+		page = compound_trans_head(bv->bv_page);
+		atomic_dec(&page->_count);
+	}
 }
 
 static void
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 784c92e..6f68095 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -12,6 +12,8 @@
 #include <linux/bitmap.h>
 #include <linux/kdev_t.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
 #include "aoe.h"
 
 static void dummy_timer(ulong);
@@ -241,20 +243,13 @@ aoedev_downdev(struct aoedev *d)
 static int
 user_req(char *s, size_t slen, struct aoedev *d)
 {
-	char *p;
+	const char *p;
 	size_t lim;
 
 	if (!d->gd)
 		return 0;
-	p = strrchr(d->gd->disk_name, '/');
-	if (!p)
-		p = d->gd->disk_name;
-	else
-		p += 1;
-	lim = sizeof(d->gd->disk_name);
-	lim -= p - d->gd->disk_name;
-	if (slen < lim)
-		lim = slen;
+	p = kbasename(d->gd->disk_name);
+	lim = min(sizeof(d->gd->disk_name) - (p - d->gd->disk_name), slen);
 
 	return !strncmp(s, p, lim);
 }
@@ -278,6 +273,7 @@ freedev(struct aoedev *d)
 
 	del_timer_sync(&d->timer);
 	if (d->gd) {
+		aoedisk_rm_debugfs(d);
 		aoedisk_rm_sysfs(d);
 		del_gendisk(d->gd);
 		put_disk(d->gd);
diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
new file mode 100644
index 0000000..65f8ace
--- /dev/null
+++ b/drivers/block/blockconsole.c
@@ -0,0 +1,618 @@
+/*
+ * Blockconsole - write kernel console to a block device
+ *
+ * Copyright (C) 2012  Joern Engel <joern@logfs.org>
+ */
+#include <linux/bio.h>
+#include <linux/blockconsole.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+#include <linux/kref.h>
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/sched/rt.h>
+#include <linux/ctype.h>
+
+#define BLOCKCONSOLE_MAGIC	"\nLinux blockconsole version 1.1\n"
+#define BCON_UUID_OFS		(32)
+#define BCON_ROUND_OFS		(41)
+#define BCON_TILE_OFS		(50)
+#define BCON_HEADERSIZE		(50)
+#define BCON_LONG_HEADERSIZE	(59) /* with tile index */
+
+#define PAGE_COUNT		(256)
+#define SECTOR_COUNT		(PAGE_COUNT * (PAGE_SIZE >> 9))
+#define CACHE_PAGE_MASK		(PAGE_COUNT - 1)
+#define CACHE_SECTOR_MASK	(SECTOR_COUNT - 1)
+#define CACHE_SIZE		(PAGE_COUNT << PAGE_SHIFT)
+#define CACHE_MASK		(CACHE_SIZE - 1)
+#define SECTOR_SHIFT		(9)
+#define SECTOR_SIZE		(1 << SECTOR_SHIFT)
+#define SECTOR_MASK		(~(SECTOR_SIZE-1))
+#define PG_SECTOR_MASK		((PAGE_SIZE >> 9) - 1)
+
+#undef pr_fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+struct bcon_bio {
+	struct bio bio;
+	struct bio_vec bvec;
+	void *sector;
+	int in_flight;
+};
+
+struct blockconsole {
+	char devname[32];
+	spinlock_t end_io_lock;
+	struct timer_list pad_timer;
+	int error_count;
+	struct kref kref;
+	u64 console_bytes;
+	u64 write_bytes;
+	u64 max_bytes;
+	u32 round;
+	u32 uuid;
+	struct bcon_bio bio_array[SECTOR_COUNT];
+	struct page *pages;
+	struct bcon_bio zero_bios[PAGE_COUNT];
+	struct page *zero_page;
+	struct block_device *bdev;
+	struct console console;
+	struct work_struct unregister_work;
+	struct work_struct release_work;
+	struct task_struct *writeback_thread;
+	struct notifier_block panic_block;
+};
+
+static void bcon_get(struct blockconsole *bc)
+{
+	kref_get(&bc->kref);
+}
+
+static void __bcon_release(struct work_struct *work)
+{
+	struct blockconsole *bc = container_of(work, struct blockconsole,
+			release_work);
+
+	__free_pages(bc->zero_page, 0);
+	__free_pages(bc->pages, 8);
+	invalidate_mapping_pages(bc->bdev->bd_inode->i_mapping, 0, -1);
+	blkdev_put(bc->bdev, FMODE_READ|FMODE_WRITE);
+	kfree(bc);
+}
+
+static void bcon_release(struct kref *kref)
+{
+	struct blockconsole *bc = container_of(kref, struct blockconsole, kref);
+
+	/* bcon_release can be called from atomic context */
+	schedule_work(&bc->release_work);
+}
+
+static void bcon_put(struct blockconsole *bc)
+{
+	kref_put(&bc->kref, bcon_release);
+}
+
+static int __bcon_console_ofs(u64 console_bytes)
+{
+	return console_bytes & ~SECTOR_MASK;
+}
+
+static int bcon_console_ofs(struct blockconsole *bc)
+{
+	return __bcon_console_ofs(bc->console_bytes);
+}
+
+static int __bcon_console_sector(u64 console_bytes)
+{
+	return (console_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static int bcon_console_sector(struct blockconsole *bc)
+{
+	return __bcon_console_sector(bc->console_bytes);
+}
+
+static int bcon_write_sector(struct blockconsole *bc)
+{
+	return (bc->write_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static void clear_sector(void *sector)
+{
+	memset(sector, ' ', 511);
+	memset(sector + 511, 10, 1);
+}
+
+static void bcon_init_first_page(struct blockconsole *bc)
+{
+	char *buf = page_address(bc->pages);
+	size_t len = strlen(BLOCKCONSOLE_MAGIC);
+	u32 tile = bc->console_bytes >> 20; /* We overflow after 4TB - fine */
+
+	clear_sector(buf);
+	memcpy(buf, BLOCKCONSOLE_MAGIC, len);
+	sprintf(buf + BCON_UUID_OFS, "%08x", bc->uuid);
+	sprintf(buf + BCON_ROUND_OFS, "%08x", bc->round);
+	sprintf(buf + BCON_TILE_OFS, "%08x", tile);
+	/* replace NUL with newline */
+	buf[BCON_UUID_OFS + 8] = 10;
+	buf[BCON_ROUND_OFS + 8] = 10;
+	buf[BCON_TILE_OFS + 8] = 10;
+}
+
+static void bcon_advance_console_bytes(struct blockconsole *bc, int bytes)
+{
+	u64 old, new;
+
+	do {
+		old = bc->console_bytes;
+		new = old + bytes;
+		if (new >= bc->max_bytes)
+			new = 0;
+		if ((new & CACHE_MASK) == 0) {
+			bcon_init_first_page(bc);
+			new += BCON_LONG_HEADERSIZE;
+		}
+	} while (cmpxchg64(&bc->console_bytes, old, new) != old);
+}
+
+static void request_complete(struct bio *bio, int err)
+{
+	complete((struct completion *)bio->bi_private);
+}
+
+static int sync_read(struct blockconsole *bc, u64 ofs)
+{
+	struct bio bio;
+	struct bio_vec bio_vec;
+	struct completion complete;
+
+	bio_init(&bio);
+	bio.bi_io_vec = &bio_vec;
+	bio_vec.bv_page = bc->pages;
+	bio_vec.bv_len = SECTOR_SIZE;
+	bio_vec.bv_offset = 0;
+	bio.bi_vcnt = 1;
+	bio.bi_idx = 0;
+	bio.bi_size = SECTOR_SIZE;
+	bio.bi_bdev = bc->bdev;
+	bio.bi_sector = ofs >> SECTOR_SHIFT;
+	init_completion(&complete);
+	bio.bi_private = &complete;
+	bio.bi_end_io = request_complete;
+
+	submit_bio(READ, &bio);
+	wait_for_completion(&complete);
+	return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+}
+
+static void bcon_erase_segment(struct blockconsole *bc)
+{
+	int i;
+
+	for (i = 0; i < PAGE_COUNT; i++) {
+		struct bcon_bio *bcon_bio = bc->zero_bios + i;
+		struct bio *bio = &bcon_bio->bio;
+
+		/*
+		 * If the last erase hasn't finished yet, just skip it.  The log
+		 * will look messy, but that's all.
+		 */
+		rmb();
+		if (bcon_bio->in_flight)
+			continue;
+		bio_init(bio);
+		bio->bi_io_vec = &bcon_bio->bvec;
+		bio->bi_vcnt = 1;
+		bio->bi_size = PAGE_SIZE;
+		bio->bi_bdev = bc->bdev;
+		bio->bi_private = bc;
+		bio->bi_idx = 0;
+		bio->bi_sector = (bc->write_bytes + i * PAGE_SIZE) >> 9;
+		bcon_bio->in_flight = 1;
+		wmb();
+		/* We want the erase to go to the device first somehow */
+		submit_bio(WRITE | REQ_SOFTBARRIER, bio);
+	}
+}
+
+static void bcon_advance_write_bytes(struct blockconsole *bc, int bytes)
+{
+	bc->write_bytes += bytes;
+	if (bc->write_bytes >= bc->max_bytes) {
+		bc->write_bytes = 0;
+		bc->round++;
+		bcon_init_first_page(bc);
+	}
+}
+
+static int bcon_find_end_of_log(struct blockconsole *bc)
+{
+	u64 start = 0, end = bc->max_bytes, middle;
+	void *sec0 = bc->bio_array[0].sector;
+	void *sec1 = bc->bio_array[1].sector;
+	int err, version;
+
+	err = sync_read(bc, 0);
+	if (err)
+		return err;
+	/* Second sanity check, out of sheer paranoia */
+	version = bcon_magic_present(sec0);
+	if (!version)
+		return -EINVAL;
+
+	bc->uuid = simple_strtoull(sec0 + BCON_UUID_OFS, NULL, 16);
+	bc->round = simple_strtoull(sec0 + BCON_ROUND_OFS, NULL, 16);
+
+	memcpy(sec1, sec0, BCON_HEADERSIZE);
+	for (;;) {
+		middle = (start + end) / 2;
+		middle &= ~CACHE_MASK;
+		if (middle == start)
+			break;
+		err = sync_read(bc, middle);
+		if (err)
+			return err;
+		if (memcmp(sec1, sec0, BCON_HEADERSIZE)) {
+			/* If the two differ, we haven't written that far yet */
+			end = middle;
+		} else {
+			start = middle;
+		}
+	}
+	bc->console_bytes = bc->write_bytes = end;
+	bcon_advance_console_bytes(bc, 0); /* To skip the header */
+	bcon_advance_write_bytes(bc, 0); /* To wrap around, if necessary */
+	bcon_erase_segment(bc);
+	return 0;
+}
+
+static void bcon_unregister(struct work_struct *work)
+{
+	struct blockconsole *bc = container_of(work, struct blockconsole,
+			unregister_work);
+
+	atomic_notifier_chain_unregister(&panic_notifier_list, &bc->panic_block);
+	unregister_console(&bc->console);
+	del_timer_sync(&bc->pad_timer);
+	kthread_stop(bc->writeback_thread);
+	/* No new io will be scheduled anymore now */
+	bcon_put(bc);
+}
+
+#define BCON_MAX_ERRORS	10
+static void bcon_end_io(struct bio *bio, int err)
+{
+	struct bcon_bio *bcon_bio = container_of(bio, struct bcon_bio, bio);
+	struct blockconsole *bc = bio->bi_private;
+	unsigned long flags;
+
+	/*
+	 * We want to assume the device broken and free this console if
+	 * we accumulate too many errors.  But if errors are transient,
+	 * we also want to forget about them once writes succeed again.
+	 * Oh, and we only want to reset the counter if it hasn't reached
+	 * the limit yet, so we don't bcon_put() twice from here.
+	 */
+	spin_lock_irqsave(&bc->end_io_lock, flags);
+	if (err) {
+		if (bc->error_count++ == BCON_MAX_ERRORS) {
+			pr_info("no longer logging to %s\n", bc->devname);
+			schedule_work(&bc->unregister_work);
+		}
+	} else {
+		if (bc->error_count && bc->error_count < BCON_MAX_ERRORS)
+			bc->error_count = 0;
+	}
+	/*
+	 * Add padding (a bunch of spaces and a newline) early so bcon_pad
+	 * only has to advance a pointer.
+	 */
+	clear_sector(bcon_bio->sector);
+	bcon_bio->in_flight = 0;
+	spin_unlock_irqrestore(&bc->end_io_lock, flags);
+	bcon_put(bc);
+}
+
+static void bcon_writesector(struct blockconsole *bc, int index)
+{
+	struct bcon_bio *bcon_bio = bc->bio_array + index;
+	struct bio *bio = &bcon_bio->bio;
+
+	rmb();
+	if (bcon_bio->in_flight)
+		return;
+	bcon_get(bc);
+
+	bio_init(bio);
+	bio->bi_io_vec = &bcon_bio->bvec;
+	bio->bi_vcnt = 1;
+	bio->bi_size = SECTOR_SIZE;
+	bio->bi_bdev = bc->bdev;
+	bio->bi_private = bc;
+	bio->bi_end_io = bcon_end_io;
+
+	bio->bi_idx = 0;
+	bio->bi_sector = bc->write_bytes >> 9;
+	bcon_bio->in_flight = 1;
+	wmb();
+	submit_bio(WRITE, bio);
+}
+
+static int bcon_writeback(void *_bc)
+{
+	struct blockconsole *bc = _bc;
+	struct sched_param(sp);
+
+	sp.sched_priority = MAX_RT_PRIO - 1; /* Highest realtime prio */
+	sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (kthread_should_stop())
+			break;
+		while (bcon_write_sector(bc) != bcon_console_sector(bc)) {
+			bcon_writesector(bc, bcon_write_sector(bc));
+			bcon_advance_write_bytes(bc, SECTOR_SIZE);
+			if (bcon_write_sector(bc) == 0)
+				bcon_erase_segment(bc);
+		}
+	}
+	return 0;
+}
+
+static void bcon_pad(unsigned long data)
+{
+	struct blockconsole *bc = (void *)data;
+	unsigned int n;
+
+	/*
+	 * We deliberately race against bcon_write here.  If we lose the race,
+	 * our padding is no longer where we expected it to be, i.e. it is
+	 * no longer a bunch of spaces with a newline at the end.  There could
+	 * not be a newline at all or it could be somewhere in the middle.
+	 * Either way, the log corruption is fairly obvious to spot and ignore
+	 * for human readers.
+	 */
+	n = SECTOR_SIZE - bcon_console_ofs(bc);
+	if (n != SECTOR_SIZE) {
+		bcon_advance_console_bytes(bc, n);
+		wake_up_process(bc->writeback_thread);
+	}
+}
+
+static void bcon_write(struct console *console, const char *msg,
+		unsigned int len)
+{
+	struct blockconsole *bc = container_of(console, struct blockconsole,
+			console);
+	unsigned int n;
+	u64 console_bytes;
+	int i;
+
+	while (len) {
+		console_bytes = bc->console_bytes;
+		i = __bcon_console_sector(console_bytes);
+		rmb();
+		if (bc->bio_array[i].in_flight)
+			break;
+		n = min_t(int, len, SECTOR_SIZE -
+				__bcon_console_ofs(console_bytes));
+		memcpy(bc->bio_array[i].sector +
+				__bcon_console_ofs(console_bytes), msg, n);
+		len -= n;
+		msg += n;
+		bcon_advance_console_bytes(bc, n);
+	}
+	wake_up_process(bc->writeback_thread);
+	mod_timer(&bc->pad_timer, jiffies + HZ);
+}
+
+static void bcon_init_bios(struct blockconsole *bc)
+{
+	int i;
+
+	for (i = 0; i < SECTOR_COUNT; i++) {
+		int page_index = i >> (PAGE_SHIFT - SECTOR_SHIFT);
+		struct page *page = bc->pages + page_index;
+		struct bcon_bio *bcon_bio = bc->bio_array + i;
+		struct bio_vec *bvec = &bcon_bio->bvec;
+
+		bcon_bio->in_flight = 0;
+		bcon_bio->sector = page_address(bc->pages + page_index)
+			+ SECTOR_SIZE * (i & PG_SECTOR_MASK);
+		clear_sector(bcon_bio->sector);
+		bvec->bv_page = page;
+		bvec->bv_len = SECTOR_SIZE;
+		bvec->bv_offset = SECTOR_SIZE * (i & PG_SECTOR_MASK);
+	}
+}
+
+static void bcon_init_zero_bio(struct blockconsole *bc)
+{
+	int i;
+
+	memset(page_address(bc->zero_page), 0, PAGE_SIZE);
+	for (i = 0; i < PAGE_COUNT; i++) {
+		struct bcon_bio *bcon_bio = bc->zero_bios + i;
+		struct bio_vec *bvec = &bcon_bio->bvec;
+
+		bcon_bio->in_flight = 0;
+		bvec->bv_page = bc->zero_page;
+		bvec->bv_len = PAGE_SIZE;
+		bvec->bv_offset = 0;
+	}
+}
+
+static int blockconsole_panic(struct notifier_block *this, unsigned long event,
+		void *ptr)
+{
+	struct blockconsole *bc = container_of(this, struct blockconsole,
+			panic_block);
+	unsigned int n;
+
+	n = SECTOR_SIZE - bcon_console_ofs(bc);
+	if (n != SECTOR_SIZE)
+		bcon_advance_console_bytes(bc, n);
+	bcon_writeback(bc);
+	return NOTIFY_DONE;
+}
+
+static int bcon_create(const char *devname)
+{
+	const fmode_t mode = FMODE_READ | FMODE_WRITE;
+	struct blockconsole *bc;
+	int err;
+
+	bc = kzalloc(sizeof(*bc), GFP_KERNEL);
+	if (!bc)
+		return -ENOMEM;
+	memset(bc->devname, ' ', sizeof(bc->devname));
+	strlcpy(bc->devname, devname, sizeof(bc->devname));
+	spin_lock_init(&bc->end_io_lock);
+	strcpy(bc->console.name, "bcon");
+	bc->console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ALLDATA;
+	bc->console.write = bcon_write;
+	bc->bdev = blkdev_get_by_path(devname, mode, NULL);
+#ifndef MODULE
+	if (IS_ERR(bc->bdev)) {
+		dev_t devt = name_to_dev_t(devname);
+		if (devt)
+			bc->bdev = blkdev_get_by_dev(devt, mode, NULL);
+	}
+#endif
+	if (IS_ERR(bc->bdev))
+		goto out;
+	bc->pages = alloc_pages(GFP_KERNEL, 8);
+	if (!bc->pages)
+		goto out;
+	bc->zero_page = alloc_pages(GFP_KERNEL, 0);
+	if (!bc->zero_page)
+		goto out1;
+	bcon_init_bios(bc);
+	bcon_init_zero_bio(bc);
+	setup_timer(&bc->pad_timer, bcon_pad, (unsigned long)bc);
+	bc->max_bytes = bc->bdev->bd_inode->i_size & ~CACHE_MASK;
+	err = bcon_find_end_of_log(bc);
+	if (err)
+		goto out2;
+	kref_init(&bc->kref); /* This reference gets freed on errors */
+	bc->writeback_thread = kthread_run(bcon_writeback, bc, "bcon_%s",
+			devname);
+	if (IS_ERR(bc->writeback_thread))
+		goto out2;
+	INIT_WORK(&bc->unregister_work, bcon_unregister);
+	INIT_WORK(&bc->release_work, __bcon_release);
+	register_console(&bc->console);
+	bc->panic_block.notifier_call = blockconsole_panic;
+	bc->panic_block.priority = INT_MAX;
+	atomic_notifier_chain_register(&panic_notifier_list, &bc->panic_block);
+	pr_info("now logging to %s at %llx\n", devname, bc->console_bytes >> 20);
+
+	return 0;
+
+out2:
+	__free_pages(bc->zero_page, 0);
+out1:
+	__free_pages(bc->pages, 8);
+out:
+	kfree(bc);
+	/* Not strictly correct, be the caller doesn't care */
+	return -ENOMEM;
+}
+
+static void bcon_create_fuzzy(const char *name)
+{
+	char *longname;
+	int err;
+
+	err = bcon_create(name);
+	if (err) {
+		longname = kzalloc(strlen(name) + 6, GFP_KERNEL);
+		if (!longname)
+			return;
+		strcpy(longname, "/dev/");
+		strcat(longname, name);
+		bcon_create(longname);
+		kfree(longname);
+	}
+}
+
+static DEFINE_SPINLOCK(bcon_device_lock);
+static char scanned_devices[80];
+
+static void bcon_do_add(struct work_struct *work)
+{
+	char local_devices[80], *name, *remainder = local_devices;
+
+	spin_lock(&bcon_device_lock);
+	memcpy(local_devices, scanned_devices, sizeof(local_devices));
+	memset(scanned_devices, 0, sizeof(scanned_devices));
+	spin_unlock(&bcon_device_lock);
+
+	while (remainder && remainder[0]) {
+		name = strsep(&remainder, ",");
+		bcon_create_fuzzy(name);
+	}
+}
+
+static DECLARE_WORK(bcon_add_work, bcon_do_add);
+
+void bcon_add(const char *name)
+{
+	/*
+	 * We add each name to a small static buffer and ask for a workqueue
+	 * to go pick it up asap.  Once it is picked up, the buffer is empty
+	 * again, so hopefully it will suffice for all sane users.
+	 */
+	spin_lock(&bcon_device_lock);
+	if (scanned_devices[0])
+		strncat(scanned_devices, ",", sizeof(scanned_devices));
+	strncat(scanned_devices, name, sizeof(scanned_devices));
+	spin_unlock(&bcon_device_lock);
+	schedule_work(&bcon_add_work);
+}
+
+/*
+ * Check if we have an 8-digit hex number followed by newline
+ */
+static bool is_four_byte_hex(const void *data)
+{
+	const char *str = data;
+	int len = 0;
+
+	while (isxdigit(*str) && len++ < 9)
+		str++;
+
+	if (len != 8)
+		return false;
+
+	/* str should point to a \n now */
+	if (*str != 0xa)
+		return false;
+
+	return true;
+}
+
+int bcon_magic_present(const void *data)
+{
+	size_t len = strlen(BLOCKCONSOLE_MAGIC);
+
+	if (memcmp(data, BLOCKCONSOLE_MAGIC, len))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_UUID_OFS))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_ROUND_OFS))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_TILE_OFS))
+		return 0;
+	return 11;
+}
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index 1bbc681..79aa179 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -598,7 +598,7 @@ static ssize_t class_osdblk_remove(struct class *c,
 	unsigned long ul;
 	struct list_head *tmp;
 
-	rc = strict_strtoul(buf, 10, &ul);
+	rc = kstrtoul(buf, 10, &ul);
 	if (rc)
 		return rc;
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index f5d0ea1..5618847 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -44,6 +44,8 @@
  *
  *************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/pktcdvd.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -69,23 +71,24 @@
 
 #define DRIVER_NAME	"pktcdvd"
 
-#if PACKET_DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#if PACKET_DEBUG > 1
-#define VPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
-#else
-#define VPRINTK(fmt, args...)
-#endif
+#define pkt_err(pd, fmt, ...)						\
+	pr_err("%s: " fmt, pd->name, ##__VA_ARGS__)
+#define pkt_notice(pd, fmt, ...)					\
+	pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__)
+#define pkt_info(pd, fmt, ...)						\
+	pr_info("%s: " fmt, pd->name, ##__VA_ARGS__)
+
+#define pkt_dbg(level, pd, fmt, ...)					\
+do {									\
+	if (level == 2 && PACKET_DEBUG >= 2)				\
+		pr_notice("%s: %s():" fmt,				\
+			  pd->name, __func__, ##__VA_ARGS__);		\
+	else if (level == 1 && PACKET_DEBUG >= 1)			\
+		pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__);		\
+} while (0)
 
 #define MAX_SPEED 0xffff
 
-#define ZONE(sector, pd) (((sector) + (pd)->offset) & \
-			~(sector_t)((pd)->settings.size - 1))
-
 static DEFINE_MUTEX(pktcdvd_mutex);
 static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
 static struct proc_dir_entry *pkt_proc;
@@ -103,7 +106,10 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
 static int pkt_remove_dev(dev_t pkt_dev);
 static int pkt_seq_show(struct seq_file *m, void *p);
 
-
+static sector_t get_zone(sector_t sector, struct pktcdvd_device *pd)
+{
+	return (sector + pd->offset) & ~(sector_t)(pd->settings.size - 1);
+}
 
 /*
  * create and register a pktcdvd kernel object.
@@ -424,7 +430,7 @@ static int pkt_sysfs_init(void)
 	if (ret) {
 		kfree(class_pktcdvd);
 		class_pktcdvd = NULL;
-		printk(DRIVER_NAME": failed to create class pktcdvd\n");
+		pr_err("failed to create class pktcdvd\n");
 		return ret;
 	}
 	return 0;
@@ -517,7 +523,7 @@ static void pkt_bio_finished(struct pktcdvd_device *pd)
 {
 	BUG_ON(atomic_read(&pd->cdrw.pending_bios) <= 0);
 	if (atomic_dec_and_test(&pd->cdrw.pending_bios)) {
-		VPRINTK(DRIVER_NAME": queue empty\n");
+		pkt_dbg(2, pd, "queue empty\n");
 		atomic_set(&pd->iosched.attention, 1);
 		wake_up(&pd->wqueue);
 	}
@@ -734,36 +740,33 @@ out:
 	return ret;
 }
 
+static const char *sense_key_string(__u8 index)
+{
+	static const char * const info[] = {
+		"No sense", "Recovered error", "Not ready",
+		"Medium error", "Hardware error", "Illegal request",
+		"Unit attention", "Data protect", "Blank check",
+	};
+
+	return index < ARRAY_SIZE(info) ? info[index] : "INVALID";
+}
+
 /*
  * A generic sense dump / resolve mechanism should be implemented across
  * all ATAPI + SCSI devices.
  */
-static void pkt_dump_sense(struct packet_command *cgc)
+static void pkt_dump_sense(struct pktcdvd_device *pd,
+			   struct packet_command *cgc)
 {
-	static char *info[9] = { "No sense", "Recovered error", "Not ready",
-				 "Medium error", "Hardware error", "Illegal request",
-				 "Unit attention", "Data protect", "Blank check" };
-	int i;
 	struct request_sense *sense = cgc->sense;
 
-	printk(DRIVER_NAME":");
-	for (i = 0; i < CDROM_PACKET_SIZE; i++)
-		printk(" %02x", cgc->cmd[i]);
-	printk(" - ");
-
-	if (sense == NULL) {
-		printk("no sense\n");
-		return;
-	}
-
-	printk("sense %02x.%02x.%02x", sense->sense_key, sense->asc, sense->ascq);
-
-	if (sense->sense_key > 8) {
-		printk(" (INVALID)\n");
-		return;
-	}
-
-	printk(" (%s)\n", info[sense->sense_key]);
+	if (sense)
+		pkt_err(pd, "%*ph - sense %02x.%02x.%02x (%s)\n",
+			CDROM_PACKET_SIZE, cgc->cmd,
+			sense->sense_key, sense->asc, sense->ascq,
+			sense_key_string(sense->sense_key));
+	else
+		pkt_err(pd, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd);
 }
 
 /*
@@ -806,7 +809,7 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd,
 	cgc.cmd[5] = write_speed & 0xff;
 
 	if ((ret = pkt_generic_packet(pd, &cgc)))
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 
 	return ret;
 }
@@ -872,7 +875,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
 				need_write_seek = 0;
 			if (need_write_seek && reads_queued) {
 				if (atomic_read(&pd->cdrw.pending_bios) > 0) {
-					VPRINTK(DRIVER_NAME": write, waiting\n");
+					pkt_dbg(2, pd, "write, waiting\n");
 					break;
 				}
 				pkt_flush_cache(pd);
@@ -881,7 +884,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
 		} else {
 			if (!reads_queued && writes_queued) {
 				if (atomic_read(&pd->cdrw.pending_bios) > 0) {
-					VPRINTK(DRIVER_NAME": read, waiting\n");
+					pkt_dbg(2, pd, "read, waiting\n");
 					break;
 				}
 				pd->iosched.writing = 1;
@@ -943,7 +946,7 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_que
 		set_bit(PACKET_MERGE_SEGS, &pd->flags);
 		return 0;
 	} else {
-		printk(DRIVER_NAME": cdrom max_phys_segments too small\n");
+		pkt_err(pd, "cdrom max_phys_segments too small\n");
 		return -EIO;
 	}
 }
@@ -987,8 +990,9 @@ static void pkt_end_io_read(struct bio *bio, int err)
 	struct pktcdvd_device *pd = pkt->pd;
 	BUG_ON(!pd);
 
-	VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio,
-		(unsigned long long)pkt->sector, (unsigned long long)bio->bi_sector, err);
+	pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n",
+		bio, (unsigned long long)pkt->sector,
+		(unsigned long long)bio->bi_sector, err);
 
 	if (err)
 		atomic_inc(&pkt->io_errors);
@@ -1005,7 +1009,7 @@ static void pkt_end_io_packet_write(struct bio *bio, int err)
 	struct pktcdvd_device *pd = pkt->pd;
 	BUG_ON(!pd);
 
-	VPRINTK("pkt_end_io_packet_write: id=%d, err=%d\n", pkt->id, err);
+	pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, err);
 
 	pd->stats.pkt_ended++;
 
@@ -1047,7 +1051,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
 	spin_unlock(&pkt->lock);
 
 	if (pkt->cache_valid) {
-		VPRINTK("pkt_gather_data: zone %llx cached\n",
+		pkt_dbg(2, pd, "zone %llx cached\n",
 			(unsigned long long)pkt->sector);
 		goto out_account;
 	}
@@ -1070,7 +1074,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
 
 		p = (f * CD_FRAMESIZE) / PAGE_SIZE;
 		offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
-		VPRINTK("pkt_gather_data: Adding frame %d, page:%p offs:%d\n",
+		pkt_dbg(2, pd, "Adding frame %d, page:%p offs:%d\n",
 			f, pkt->pages[p], offset);
 		if (!bio_add_page(bio, pkt->pages[p], CD_FRAMESIZE, offset))
 			BUG();
@@ -1082,7 +1086,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
 	}
 
 out_account:
-	VPRINTK("pkt_gather_data: need %d frames for zone %llx\n",
+	pkt_dbg(2, pd, "need %d frames for zone %llx\n",
 		frames_read, (unsigned long long)pkt->sector);
 	pd->stats.pkt_started++;
 	pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
@@ -1183,7 +1187,8 @@ static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state
 		"IDLE", "WAITING", "READ_WAIT", "WRITE_WAIT", "RECOVERY", "FINISHED"
 	};
 	enum packet_data_state old_state = pkt->state;
-	VPRINTK("pkt %2d : s=%6llx %s -> %s\n", pkt->id, (unsigned long long)pkt->sector,
+	pkt_dbg(2, pd, "pkt %2d : s=%6llx %s -> %s\n",
+		pkt->id, (unsigned long long)pkt->sector,
 		state_name[old_state], state_name[state]);
 #endif
 	pkt->state = state;
@@ -1202,12 +1207,10 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
 	struct rb_node *n;
 	int wakeup;
 
-	VPRINTK("handle_queue\n");
-
 	atomic_set(&pd->scan_queue, 0);
 
 	if (list_empty(&pd->cdrw.pkt_free_list)) {
-		VPRINTK("handle_queue: no pkt\n");
+		pkt_dbg(2, pd, "no pkt\n");
 		return 0;
 	}
 
@@ -1224,7 +1227,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
 	node = first_node;
 	while (node) {
 		bio = node->bio;
-		zone = ZONE(bio->bi_sector, pd);
+		zone = get_zone(bio->bi_sector, pd);
 		list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
 			if (p->sector == zone) {
 				bio = NULL;
@@ -1244,7 +1247,7 @@ try_next_bio:
 	}
 	spin_unlock(&pd->lock);
 	if (!bio) {
-		VPRINTK("handle_queue: no bio\n");
+		pkt_dbg(2, pd, "no bio\n");
 		return 0;
 	}
 
@@ -1260,12 +1263,12 @@ try_next_bio:
 	 * to this packet.
 	 */
 	spin_lock(&pd->lock);
-	VPRINTK("pkt_handle_queue: looking for zone %llx\n", (unsigned long long)zone);
+	pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone);
 	while ((node = pkt_rbtree_find(pd, zone)) != NULL) {
 		bio = node->bio;
-		VPRINTK("pkt_handle_queue: found zone=%llx\n",
-			(unsigned long long)ZONE(bio->bi_sector, pd));
-		if (ZONE(bio->bi_sector, pd) != zone)
+		pkt_dbg(2, pd, "found zone=%llx\n",
+			(unsigned long long)get_zone(bio->bi_sector, pd));
+		if (get_zone(bio->bi_sector, pd) != zone)
 			break;
 		pkt_rbtree_erase(pd, node);
 		spin_lock(&pkt->lock);
@@ -1316,7 +1319,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 		if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
 			BUG();
 	}
-	VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);
+	pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
 
 	/*
 	 * Fill-in bvec with data from orig_bios.
@@ -1327,7 +1330,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 	pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE);
 	spin_unlock(&pkt->lock);
 
-	VPRINTK("pkt_start_write: Writing %d frames for zone %llx\n",
+	pkt_dbg(2, pd, "Writing %d frames for zone %llx\n",
 		pkt->write_size, (unsigned long long)pkt->sector);
 
 	if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
@@ -1359,7 +1362,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
 {
 	int uptodate;
 
-	VPRINTK("run_state_machine: pkt %d\n", pkt->id);
+	pkt_dbg(2, pd, "pkt %d\n", pkt->id);
 
 	for (;;) {
 		switch (pkt->state) {
@@ -1398,7 +1401,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
 			if (pkt_start_recovery(pkt)) {
 				pkt_start_write(pd, pkt);
 			} else {
-				VPRINTK("No recovery possible\n");
+				pkt_dbg(2, pd, "No recovery possible\n");
 				pkt_set_state(pkt, PACKET_FINISHED_STATE);
 			}
 			break;
@@ -1419,8 +1422,6 @@ static void pkt_handle_packets(struct pktcdvd_device *pd)
 {
 	struct packet_data *pkt, *next;
 
-	VPRINTK("pkt_handle_packets\n");
-
 	/*
 	 * Run state machine for active packets
 	 */
@@ -1502,9 +1503,9 @@ static int kcdrwd(void *foobar)
 			if (PACKET_DEBUG > 1) {
 				int states[PACKET_NUM_STATES];
 				pkt_count_states(pd, states);
-				VPRINTK("kcdrwd: i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
-					states[0], states[1], states[2], states[3],
-					states[4], states[5]);
+				pkt_dbg(2, pd, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
+					states[0], states[1], states[2],
+					states[3], states[4], states[5]);
 			}
 
 			min_sleep_time = MAX_SCHEDULE_TIMEOUT;
@@ -1513,9 +1514,9 @@ static int kcdrwd(void *foobar)
 					min_sleep_time = pkt->sleep_time;
 			}
 
-			VPRINTK("kcdrwd: sleeping\n");
+			pkt_dbg(2, pd, "sleeping\n");
 			residue = schedule_timeout(min_sleep_time);
-			VPRINTK("kcdrwd: wake up\n");
+			pkt_dbg(2, pd, "wake up\n");
 
 			/* make swsusp happy with our thread */
 			try_to_freeze();
@@ -1563,9 +1564,10 @@ work_to_do:
 
 static void pkt_print_settings(struct pktcdvd_device *pd)
 {
-	printk(DRIVER_NAME": %s packets, ", pd->settings.fp ? "Fixed" : "Variable");
-	printk("%u blocks, ", pd->settings.size >> 2);
-	printk("Mode-%c disc\n", pd->settings.block_mode == 8 ? '1' : '2');
+	pkt_info(pd, "%s packets, %u blocks, Mode-%c disc\n",
+		 pd->settings.fp ? "Fixed" : "Variable",
+		 pd->settings.size >> 2,
+		 pd->settings.block_mode == 8 ? '1' : '2');
 }
 
 static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc, int page_code, int page_control)
@@ -1699,7 +1701,7 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
 	init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ);
 	cgc.sense = &sense;
 	if ((ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) {
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 		return ret;
 	}
 
@@ -1714,7 +1716,7 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
 	init_cdrom_command(&cgc, buffer, size, CGC_DATA_READ);
 	cgc.sense = &sense;
 	if ((ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) {
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 		return ret;
 	}
 
@@ -1749,14 +1751,14 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
 		/*
 		 * paranoia
 		 */
-		printk(DRIVER_NAME": write mode wrong %d\n", wp->data_block_type);
+		pkt_err(pd, "write mode wrong %d\n", wp->data_block_type);
 		return 1;
 	}
 	wp->packet_size = cpu_to_be32(pd->settings.size >> 2);
 
 	cgc.buflen = cgc.cmd[8] = size;
 	if ((ret = pkt_mode_select(pd, &cgc))) {
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 		return ret;
 	}
 
@@ -1793,7 +1795,7 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
 	if (ti->rt == 1 && ti->blank == 0)
 		return 1;
 
-	printk(DRIVER_NAME": bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
+	pkt_err(pd, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
 	return 0;
 }
 
@@ -1811,7 +1813,8 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
 		case 0x12: /* DVD-RAM */
 			return 1;
 		default:
-			VPRINTK(DRIVER_NAME": Wrong disc profile (%x)\n", pd->mmc3_profile);
+			pkt_dbg(2, pd, "Wrong disc profile (%x)\n",
+				pd->mmc3_profile);
 			return 0;
 	}
 
@@ -1820,22 +1823,22 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
 	 * but i'm not sure, should we leave this to user apps? probably.
 	 */
 	if (di->disc_type == 0xff) {
-		printk(DRIVER_NAME": Unknown disc. No track?\n");
+		pkt_notice(pd, "unknown disc - no track?\n");
 		return 0;
 	}
 
 	if (di->disc_type != 0x20 && di->disc_type != 0) {
-		printk(DRIVER_NAME": Wrong disc type (%x)\n", di->disc_type);
+		pkt_err(pd, "wrong disc type (%x)\n", di->disc_type);
 		return 0;
 	}
 
 	if (di->erasable == 0) {
-		printk(DRIVER_NAME": Disc not erasable\n");
+		pkt_notice(pd, "disc not erasable\n");
 		return 0;
 	}
 
 	if (di->border_status == PACKET_SESSION_RESERVED) {
-		printk(DRIVER_NAME": Can't write to last track (reserved)\n");
+		pkt_err(pd, "can't write to last track (reserved)\n");
 		return 0;
 	}
 
@@ -1860,7 +1863,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
 	memset(&ti, 0, sizeof(track_information));
 
 	if ((ret = pkt_get_disc_info(pd, &di))) {
-		printk("failed get_disc\n");
+		pkt_err(pd, "failed get_disc\n");
 		return ret;
 	}
 
@@ -1871,12 +1874,12 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
 
 	track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
 	if ((ret = pkt_get_track_info(pd, track, 1, &ti))) {
-		printk(DRIVER_NAME": failed get_track\n");
+		pkt_err(pd, "failed get_track\n");
 		return ret;
 	}
 
 	if (!pkt_writable_track(pd, &ti)) {
-		printk(DRIVER_NAME": can't write to this track\n");
+		pkt_err(pd, "can't write to this track\n");
 		return -EROFS;
 	}
 
@@ -1886,11 +1889,11 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
 	 */
 	pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
 	if (pd->settings.size == 0) {
-		printk(DRIVER_NAME": detected zero packet size!\n");
+		pkt_notice(pd, "detected zero packet size!\n");
 		return -ENXIO;
 	}
 	if (pd->settings.size > PACKET_MAX_SECTORS) {
-		printk(DRIVER_NAME": packet size is too big\n");
+		pkt_err(pd, "packet size is too big\n");
 		return -EROFS;
 	}
 	pd->settings.fp = ti.fp;
@@ -1932,7 +1935,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
 			pd->settings.block_mode = PACKET_BLOCK_MODE2;
 			break;
 		default:
-			printk(DRIVER_NAME": unknown data mode\n");
+			pkt_err(pd, "unknown data mode\n");
 			return -EROFS;
 	}
 	return 0;
@@ -1966,10 +1969,10 @@ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd,
 	cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff));
 	ret = pkt_mode_select(pd, &cgc);
 	if (ret) {
-		printk(DRIVER_NAME": write caching control failed\n");
-		pkt_dump_sense(&cgc);
+		pkt_err(pd, "write caching control failed\n");
+		pkt_dump_sense(pd, &cgc);
 	} else if (!ret && set)
-		printk(DRIVER_NAME": enabled write caching on %s\n", pd->name);
+		pkt_notice(pd, "enabled write caching\n");
 	return ret;
 }
 
@@ -2005,7 +2008,7 @@ static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd,
 			     sizeof(struct mode_page_header);
 		ret = pkt_mode_sense(pd, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
 		if (ret) {
-			pkt_dump_sense(&cgc);
+			pkt_dump_sense(pd, &cgc);
 			return ret;
 		}
 	}
@@ -2064,7 +2067,7 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
 	cgc.cmd[8] = 2;
 	ret = pkt_generic_packet(pd, &cgc);
 	if (ret) {
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 		return ret;
 	}
 	size = ((unsigned int) buf[0]<<8) + buf[1] + 2;
@@ -2079,16 +2082,16 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
 	cgc.cmd[8] = size;
 	ret = pkt_generic_packet(pd, &cgc);
 	if (ret) {
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 		return ret;
 	}
 
 	if (!(buf[6] & 0x40)) {
-		printk(DRIVER_NAME": Disc type is not CD-RW\n");
+		pkt_notice(pd, "disc type is not CD-RW\n");
 		return 1;
 	}
 	if (!(buf[6] & 0x4)) {
-		printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n");
+		pkt_notice(pd, "A1 values on media are not valid, maybe not CDRW?\n");
 		return 1;
 	}
 
@@ -2108,14 +2111,14 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
 			*speed = us_clv_to_speed[sp];
 			break;
 		default:
-			printk(DRIVER_NAME": Unknown disc sub-type %d\n",st);
+			pkt_notice(pd, "unknown disc sub-type %d\n", st);
 			return 1;
 	}
 	if (*speed) {
-		printk(DRIVER_NAME": Max. media speed: %d\n",*speed);
+		pkt_info(pd, "maximum media speed: %d\n", *speed);
 		return 0;
 	} else {
-		printk(DRIVER_NAME": Unknown speed %d for sub-type %d\n",sp,st);
+		pkt_notice(pd, "unknown speed %d for sub-type %d\n", sp, st);
 		return 1;
 	}
 }
@@ -2126,7 +2129,7 @@ static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd)
 	struct request_sense sense;
 	int ret;
 
-	VPRINTK(DRIVER_NAME": Performing OPC\n");
+	pkt_dbg(2, pd, "Performing OPC\n");
 
 	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
 	cgc.sense = &sense;
@@ -2134,7 +2137,7 @@ static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd)
 	cgc.cmd[0] = GPCMD_SEND_OPC;
 	cgc.cmd[1] = 1;
 	if ((ret = pkt_generic_packet(pd, &cgc)))
-		pkt_dump_sense(&cgc);
+		pkt_dump_sense(pd, &cgc);
 	return ret;
 }
 
@@ -2144,12 +2147,12 @@ static int pkt_open_write(struct pktcdvd_device *pd)
 	unsigned int write_speed, media_write_speed, read_speed;
 
 	if ((ret = pkt_probe_settings(pd))) {
-		VPRINTK(DRIVER_NAME": %s failed probe\n", pd->name);
+		pkt_dbg(2, pd, "failed probe\n");
 		return ret;
 	}
 
 	if ((ret = pkt_set_write_settings(pd))) {
-		DPRINTK(DRIVER_NAME": %s failed saving write settings\n", pd->name);
+		pkt_dbg(1, pd, "failed saving write settings\n");
 		return -EIO;
 	}
 
@@ -2161,26 +2164,26 @@ static int pkt_open_write(struct pktcdvd_device *pd)
 		case 0x13: /* DVD-RW */
 		case 0x1a: /* DVD+RW */
 		case 0x12: /* DVD-RAM */
-			DPRINTK(DRIVER_NAME": write speed %ukB/s\n", write_speed);
+			pkt_dbg(1, pd, "write speed %ukB/s\n", write_speed);
 			break;
 		default:
 			if ((ret = pkt_media_speed(pd, &media_write_speed)))
 				media_write_speed = 16;
 			write_speed = min(write_speed, media_write_speed * 177);
-			DPRINTK(DRIVER_NAME": write speed %ux\n", write_speed / 176);
+			pkt_dbg(1, pd, "write speed %ux\n", write_speed / 176);
 			break;
 	}
 	read_speed = write_speed;
 
 	if ((ret = pkt_set_speed(pd, write_speed, read_speed))) {
-		DPRINTK(DRIVER_NAME": %s couldn't set write speed\n", pd->name);
+		pkt_dbg(1, pd, "couldn't set write speed\n");
 		return -EIO;
 	}
 	pd->write_speed = write_speed;
 	pd->read_speed = read_speed;
 
 	if ((ret = pkt_perform_opc(pd))) {
-		DPRINTK(DRIVER_NAME": %s Optimum Power Calibration failed\n", pd->name);
+		pkt_dbg(1, pd, "Optimum Power Calibration failed\n");
 	}
 
 	return 0;
@@ -2205,7 +2208,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
 		goto out;
 
 	if ((ret = pkt_get_last_written(pd, &lba))) {
-		printk(DRIVER_NAME": pkt_get_last_written failed\n");
+		pkt_err(pd, "pkt_get_last_written failed\n");
 		goto out_putdev;
 	}
 
@@ -2235,11 +2238,11 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
 
 	if (write) {
 		if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
-			printk(DRIVER_NAME": not enough memory for buffers\n");
+			pkt_err(pd, "not enough memory for buffers\n");
 			ret = -ENOMEM;
 			goto out_putdev;
 		}
-		printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
+		pkt_info(pd, "%lukB available on disc\n", lba << 1);
 	}
 
 	return 0;
@@ -2257,7 +2260,7 @@ out:
 static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
 {
 	if (flush && pkt_flush_cache(pd))
-		DPRINTK(DRIVER_NAME": %s not flushing cache\n", pd->name);
+		pkt_dbg(1, pd, "not flushing cache\n");
 
 	pkt_lock_door(pd, 0);
 
@@ -2279,8 +2282,6 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
 	struct pktcdvd_device *pd = NULL;
 	int ret;
 
-	VPRINTK(DRIVER_NAME": entering open\n");
-
 	mutex_lock(&pktcdvd_mutex);
 	mutex_lock(&ctl_mutex);
 	pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
@@ -2315,7 +2316,6 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
 out_dec:
 	pd->refcnt--;
 out:
-	VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
 	mutex_unlock(&ctl_mutex);
 	mutex_unlock(&pktcdvd_mutex);
 	return ret;
@@ -2360,7 +2360,8 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
 
 	pd = q->queuedata;
 	if (!pd) {
-		printk(DRIVER_NAME": %s incorrect request queue\n", bdevname(bio->bi_bdev, b));
+		pr_err("%s incorrect request queue\n",
+		       bdevname(bio->bi_bdev, b));
 		goto end_io;
 	}
 
@@ -2382,20 +2383,20 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
 	}
 
 	if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
-		printk(DRIVER_NAME": WRITE for ro device %s (%llu)\n",
-			pd->name, (unsigned long long)bio->bi_sector);
+		pkt_notice(pd, "WRITE for ro device (%llu)\n",
+			   (unsigned long long)bio->bi_sector);
 		goto end_io;
 	}
 
 	if (!bio->bi_size || (bio->bi_size % CD_FRAMESIZE)) {
-		printk(DRIVER_NAME": wrong bio size\n");
+		pkt_err(pd, "wrong bio size\n");
 		goto end_io;
 	}
 
 	blk_queue_bounce(q, &bio);
 
-	zone = ZONE(bio->bi_sector, pd);
-	VPRINTK("pkt_make_request: start = %6llx stop = %6llx\n",
+	zone = get_zone(bio->bi_sector, pd);
+	pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
 		(unsigned long long)bio->bi_sector,
 		(unsigned long long)bio_end_sector(bio));
 
@@ -2405,7 +2406,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
 		sector_t last_zone;
 		int first_sectors;
 
-		last_zone = ZONE(bio_end_sector(bio) - 1, pd);
+		last_zone = get_zone(bio_end_sector(bio) - 1, pd);
 		if (last_zone != zone) {
 			BUG_ON(last_zone != zone + pd->settings.size);
 			first_sectors = last_zone - bio->bi_sector;
@@ -2500,7 +2501,7 @@ static int pkt_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
 			  struct bio_vec *bvec)
 {
 	struct pktcdvd_device *pd = q->queuedata;
-	sector_t zone = ZONE(bmd->bi_sector, pd);
+	sector_t zone = get_zone(bmd->bi_sector, pd);
 	int used = ((bmd->bi_sector - zone) << 9) + bmd->bi_size;
 	int remaining = (pd->settings.size << 9) - used;
 	int remaining2;
@@ -2609,7 +2610,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
 	struct block_device *bdev;
 
 	if (pd->pkt_dev == dev) {
-		printk(DRIVER_NAME": Recursive setup not allowed\n");
+		pkt_err(pd, "recursive setup not allowed\n");
 		return -EBUSY;
 	}
 	for (i = 0; i < MAX_WRITERS; i++) {
@@ -2617,11 +2618,12 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
 		if (!pd2)
 			continue;
 		if (pd2->bdev->bd_dev == dev) {
-			printk(DRIVER_NAME": %s already setup\n", bdevname(pd2->bdev, b));
+			pkt_err(pd, "%s already setup\n",
+				bdevname(pd2->bdev, b));
 			return -EBUSY;
 		}
 		if (pd2->pkt_dev == dev) {
-			printk(DRIVER_NAME": Can't chain pktcdvd devices\n");
+			pkt_err(pd, "can't chain pktcdvd devices\n");
 			return -EBUSY;
 		}
 	}
@@ -2644,13 +2646,13 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
 	atomic_set(&pd->cdrw.pending_bios, 0);
 	pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name);
 	if (IS_ERR(pd->cdrw.thread)) {
-		printk(DRIVER_NAME": can't start kernel thread\n");
+		pkt_err(pd, "can't start kernel thread\n");
 		ret = -ENOMEM;
 		goto out_mem;
 	}
 
 	proc_create_data(pd->name, 0, pkt_proc, &pkt_proc_fops, pd);
-	DPRINTK(DRIVER_NAME": writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
+	pkt_dbg(1, pd, "writer mapped to %s\n", bdevname(bdev, b));
 	return 0;
 
 out_mem:
@@ -2665,8 +2667,8 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
 	struct pktcdvd_device *pd = bdev->bd_disk->private_data;
 	int ret;
 
-	VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
-		MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
+	pkt_dbg(2, pd, "cmd %x, dev %d:%d\n",
+		cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
 
 	mutex_lock(&pktcdvd_mutex);
 	switch (cmd) {
@@ -2690,7 +2692,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
 		break;
 
 	default:
-		VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
+		pkt_dbg(2, pd, "Unknown ioctl (%x)\n", cmd);
 		ret = -ENOTTY;
 	}
 	mutex_unlock(&pktcdvd_mutex);
@@ -2743,7 +2745,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
 		if (!pkt_devs[idx])
 			break;
 	if (idx == MAX_WRITERS) {
-		printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS);
+		pr_err("max %d writers supported\n", MAX_WRITERS);
 		ret = -EBUSY;
 		goto out_mutex;
 	}
@@ -2818,7 +2820,7 @@ out_mem:
 	kfree(pd);
 out_mutex:
 	mutex_unlock(&ctl_mutex);
-	printk(DRIVER_NAME": setup of pktcdvd device failed\n");
+	pr_err("setup of pktcdvd device failed\n");
 	return ret;
 }
 
@@ -2839,7 +2841,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
 			break;
 	}
 	if (idx == MAX_WRITERS) {
-		DPRINTK(DRIVER_NAME": dev not setup\n");
+		pr_debug("dev not setup\n");
 		ret = -ENXIO;
 		goto out;
 	}
@@ -2859,7 +2861,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
 	blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
 
 	remove_proc_entry(pd->name, pkt_proc);
-	DPRINTK(DRIVER_NAME": writer %s unmapped\n", pd->name);
+	pkt_dbg(1, pd, "writer unmapped\n");
 
 	del_gendisk(pd->disk);
 	blk_cleanup_queue(pd->disk->queue);
@@ -2969,7 +2971,7 @@ static int __init pkt_init(void)
 
 	ret = register_blkdev(pktdev_major, DRIVER_NAME);
 	if (ret < 0) {
-		printk(DRIVER_NAME": Unable to register block device\n");
+		pr_err("unable to register block device\n");
 		goto out2;
 	}
 	if (!pktdev_major)
@@ -2983,7 +2985,7 @@ static int __init pkt_init(void)
 
 	ret = misc_register(&pkt_misc);
 	if (ret) {
-		printk(DRIVER_NAME": Unable to register misc device\n");
+		pr_err("unable to register misc device\n");
 		goto out_misc;
 	}
 
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 4ad2ad9..9e00010 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -5126,7 +5126,7 @@ static ssize_t rbd_remove(struct bus_type *bus,
 	bool already = false;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &ul);
+	ret = kstrtoul(buf, 10, &ul);
 	if (ret)
 		return ret;
 
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index fe5c3cd..c2014a0 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -620,7 +620,7 @@ static void backend_changed(struct xenbus_watch *watch,
 	}
 
 	/* Front end dir is a number, which is used as the handle. */
-	err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
+	err = kstrtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
 	if (err)
 		return;
 
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index db2c3c3..023d35e 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -43,7 +43,7 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
 	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
-	ret = strict_strtol(buf, 10, &result);
+	ret = kstrtol(buf, 10, &result);
 	if (ret)
 		return ret;
 
@@ -89,7 +89,7 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
 	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
-	ret = strict_strtol(buf, 10, &result);
+	ret = kstrtol(buf, 10, &result);
 	if (ret)
 		return ret;
 
@@ -135,7 +135,7 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
 	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
-	ret = strict_strtol(buf, 10, &result);
+	ret = kstrtol(buf, 10, &result);
 	if (ret)
 		return ret;
 
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 1f70e84..552373c 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -8,10 +8,9 @@ config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
 	help
-	  Driver for i.MX6 WEIM controller.
+	  Driver for i.MX WEIM controller.
 	  The WEIM(Wireless External Interface Module) works like a bus.
 	  You can attach many different devices on it, such as NOR, onenand.
-	  But now, we only support the Parallel NOR.
 
 config MVEBU_MBUS
 	bool
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 349f14e..3ef58c8 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -12,52 +12,83 @@
 #include <linux/io.h>
 #include <linux/of_device.h>
 
-struct imx_weim {
-	void __iomem *base;
-	struct clk *clk;
+struct imx_weim_devtype {
+	unsigned int	cs_count;
+	unsigned int	cs_regs_count;
+	unsigned int	cs_stride;
+};
+
+static const struct imx_weim_devtype imx1_weim_devtype = {
+	.cs_count	= 6,
+	.cs_regs_count	= 2,
+	.cs_stride	= 0x08,
+};
+
+static const struct imx_weim_devtype imx27_weim_devtype = {
+	.cs_count	= 6,
+	.cs_regs_count	= 3,
+	.cs_stride	= 0x10,
+};
+
+static const struct imx_weim_devtype imx50_weim_devtype = {
+	.cs_count	= 4,
+	.cs_regs_count	= 6,
+	.cs_stride	= 0x18,
+};
+
+static const struct imx_weim_devtype imx51_weim_devtype = {
+	.cs_count	= 6,
+	.cs_regs_count	= 6,
+	.cs_stride	= 0x18,
 };
 
 static const struct of_device_id weim_id_table[] = {
-	{ .compatible = "fsl,imx6q-weim", },
-	{}
+	/* i.MX1/21 */
+	{ .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, },
+	/* i.MX25/27/31/35 */
+	{ .compatible = "fsl,imx27-weim", .data = &imx27_weim_devtype, },
+	/* i.MX50/53/6Q */
+	{ .compatible = "fsl,imx50-weim", .data = &imx50_weim_devtype, },
+	{ .compatible = "fsl,imx6q-weim", .data = &imx50_weim_devtype, },
+	/* i.MX51 */
+	{ .compatible = "fsl,imx51-weim", .data = &imx51_weim_devtype, },
+	{ }
 };
 MODULE_DEVICE_TABLE(of, weim_id_table);
 
-#define CS_TIMING_LEN 6
-#define CS_REG_RANGE  0x18
-
 /* Parse and set the timing for this device. */
-static int
-weim_timing_setup(struct platform_device *pdev, struct device_node *np)
+static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
+				    const struct imx_weim_devtype *devtype)
 {
-	struct imx_weim *weim = platform_get_drvdata(pdev);
-	u32 value[CS_TIMING_LEN];
-	u32 cs_idx;
-	int ret;
-	int i;
+	u32 cs_idx, value[devtype->cs_regs_count];
+	int i, ret;
 
 	/* get the CS index from this child node's "reg" property. */
 	ret = of_property_read_u32(np, "reg", &cs_idx);
 	if (ret)
 		return ret;
 
-	/* The weim has four chip selects. */
-	if (cs_idx > 3)
+	if (cs_idx >= devtype->cs_count)
 		return -EINVAL;
 
 	ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
-					value, CS_TIMING_LEN);
+					 value, devtype->cs_regs_count);
 	if (ret)
 		return ret;
 
 	/* set the timing for WEIM */
-	for (i = 0; i < CS_TIMING_LEN; i++)
-		writel(value[i], weim->base + cs_idx * CS_REG_RANGE + i * 4);
+	for (i = 0; i < devtype->cs_regs_count; i++)
+		writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
+
 	return 0;
 }
 
-static int weim_parse_dt(struct platform_device *pdev)
+static int __init weim_parse_dt(struct platform_device *pdev,
+				void __iomem *base)
 {
+	const struct of_device_id *of_id = of_match_device(weim_id_table,
+							   &pdev->dev);
+	const struct imx_weim_devtype *devtype = of_id->data;
 	struct device_node *child;
 	int ret;
 
@@ -65,7 +96,7 @@ static int weim_parse_dt(struct platform_device *pdev)
 		if (!child->name)
 			continue;
 
-		ret = weim_timing_setup(pdev, child);
+		ret = weim_timing_setup(child, base, devtype);
 		if (ret) {
 			dev_err(&pdev->dev, "%s set timing failed.\n",
 				child->full_name);
@@ -80,59 +111,47 @@ static int weim_parse_dt(struct platform_device *pdev)
 	return ret;
 }
 
-static int weim_probe(struct platform_device *pdev)
+static int __init weim_probe(struct platform_device *pdev)
 {
-	struct imx_weim *weim;
 	struct resource *res;
-	int ret = -EINVAL;
-
-	weim = devm_kzalloc(&pdev->dev, sizeof(*weim), GFP_KERNEL);
-	if (!weim) {
-		ret = -ENOMEM;
-		goto weim_err;
-	}
-	platform_set_drvdata(pdev, weim);
+	struct clk *clk;
+	void __iomem *base;
+	int ret;
 
 	/* get the resource */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	weim->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(weim->base)) {
-		ret = PTR_ERR(weim->base);
-		goto weim_err;
-	}
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	/* get the clock */
-	weim->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(weim->clk))
-		goto weim_err;
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
 
-	ret = clk_prepare_enable(weim->clk);
+	ret = clk_prepare_enable(clk);
 	if (ret)
-		goto weim_err;
+		return ret;
 
 	/* parse the device node */
-	ret = weim_parse_dt(pdev);
-	if (ret) {
-		clk_disable_unprepare(weim->clk);
-		goto weim_err;
-	}
-
-	dev_info(&pdev->dev, "WEIM driver registered.\n");
-	return 0;
+	ret = weim_parse_dt(pdev, base);
+	if (ret)
+		clk_disable_unprepare(clk);
+	else
+		dev_info(&pdev->dev, "Driver registered.\n");
 
-weim_err:
 	return ret;
 }
 
 static struct platform_driver weim_driver = {
 	.driver = {
-		.name = "imx-weim",
-		.of_match_table = weim_id_table,
+		.name		= "imx-weim",
+		.owner		= THIS_MODULE,
+		.of_match_table	= weim_id_table,
 	},
-	.probe   = weim_probe,
 };
+module_platform_driver_probe(weim_driver, weim_probe);
 
-module_platform_driver(weim_driver);
 MODULE_AUTHOR("Freescale Semiconductor Inc.");
 MODULE_DESCRIPTION("i.MX EIM Controller Driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 33c6947..19ab6ff 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -35,13 +35,9 @@
  *
  * - Provides an API for platform code or device drivers to
  *   dynamically add or remove address decoding windows for the CPU ->
- *   device accesses. This API is mvebu_mbus_add_window(),
- *   mvebu_mbus_add_window_remap_flags() and
- *   mvebu_mbus_del_window(). Since the (target, attribute) values
- *   differ from one SoC family to another, the API uses a 'const char
- *   *' string to identify devices, and this driver is responsible for
- *   knowing the mapping between the name of a device and its
- *   corresponding (target, attribute) in the current SoC family.
+ *   device accesses. This API is mvebu_mbus_add_window_by_id(),
+ *   mvebu_mbus_add_window_remap_by_id() and
+ *   mvebu_mbus_del_window().
  *
  * - Provides a debugfs interface in /sys/kernel/debug/mvebu-mbus/ to
  *   see the list of CPU -> SDRAM windows and their configuration
@@ -97,33 +93,6 @@
 
 #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
 
-struct mvebu_mbus_mapping {
-	const char *name;
-	u8 target;
-	u8 attr;
-	u8 attrmask;
-};
-
-/*
- * Masks used for the 'attrmask' field of mvebu_mbus_mapping. They
- * allow to get the real attribute value, discarding the special bits
- * used to select a PCI MEM region or a PCI WA region. This allows the
- * debugfs code to reverse-match the name of a device from its
- * target/attr values.
- *
- * For all devices except PCI, all bits of 'attr' must be
- * considered. For most SoCs, only bit 3 should be ignored (it allows
- * to select between PCI MEM and PCI I/O). On Orion5x however, there
- * is the special bit 5 to select a PCI WA region.
- */
-#define MAPDEF_NOMASK       0xff
-#define MAPDEF_PCIMASK      0xf7
-#define MAPDEF_ORIONPCIMASK 0xd7
-
-/* Macro used to define one mvebu_mbus_mapping entry */
-#define MAPDEF(__n, __t, __a, __m) \
-	{ .name = __n, .target = __t, .attr = __a, .attrmask = __m }
-
 struct mvebu_mbus_state;
 
 struct mvebu_mbus_soc_data {
@@ -133,7 +102,6 @@ struct mvebu_mbus_soc_data {
 	void (*setup_cpu_target)(struct mvebu_mbus_state *s);
 	int (*show_cpu_target)(struct mvebu_mbus_state *s,
 			       struct seq_file *seq, void *v);
-	const struct mvebu_mbus_mapping *map;
 };
 
 struct mvebu_mbus_state {
@@ -142,6 +110,8 @@ struct mvebu_mbus_state {
 	struct dentry *debugfs_root;
 	struct dentry *debugfs_sdram;
 	struct dentry *debugfs_devs;
+	struct resource pcie_mem_aperture;
+	struct resource pcie_io_aperture;
 	const struct mvebu_mbus_soc_data *soc;
 	int hw_io_coherency;
 };
@@ -428,8 +398,7 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
 		u64 wbase, wremap;
 		u32 wsize;
 		u8 wtarget, wattr;
-		int enabled, i;
-		const char *name;
+		int enabled;
 
 		mvebu_mbus_read_window(mbus, win,
 				       &enabled, &wbase, &wsize,
@@ -440,18 +409,9 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
 			continue;
 		}
 
-
-		for (i = 0; mbus->soc->map[i].name; i++)
-			if (mbus->soc->map[i].target == wtarget &&
-			    mbus->soc->map[i].attr ==
-			    (wattr & mbus->soc->map[i].attrmask))
-				break;
-
-		name = mbus->soc->map[i].name ?: "unknown";
-
-		seq_printf(seq, "[%02d] %016llx - %016llx : %s",
+		seq_printf(seq, "[%02d] %016llx - %016llx : %04x:%04x",
 			   win, (unsigned long long)wbase,
-			   (unsigned long long)(wbase + wsize), name);
+			   (unsigned long long)(wbase + wsize), wtarget, wattr);
 
 		if (win < mbus->soc->num_remappable_wins) {
 			seq_printf(seq, " (remap %016llx)\n",
@@ -576,62 +536,12 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
 	mvebu_mbus_dram_info.num_cs = cs;
 }
 
-static const struct mvebu_mbus_mapping armada_370_map[] = {
-	MAPDEF("bootrom",     1, 0xe0, MAPDEF_NOMASK),
-	MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs0",  1, 0x3e, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs1",  1, 0x3d, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs2",  1, 0x3b, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs3",  1, 0x37, MAPDEF_NOMASK),
-	MAPDEF("pcie0.0",     4, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.0",     8, 0xe0, MAPDEF_PCIMASK),
-	{},
-};
-
-static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
+static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
 	.num_wins            = 20,
 	.num_remappable_wins = 8,
 	.win_cfg_offset      = armada_370_xp_mbus_win_offset,
 	.setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
 	.show_cpu_target     = mvebu_sdram_debug_show_orion,
-	.map                 = armada_370_map,
-};
-
-static const struct mvebu_mbus_mapping armada_xp_map[] = {
-	MAPDEF("bootrom",     1, 0x1d, MAPDEF_NOMASK),
-	MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs0",  1, 0x3e, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs1",  1, 0x3d, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs2",  1, 0x3b, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs3",  1, 0x37, MAPDEF_NOMASK),
-	MAPDEF("pcie0.0",     4, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie0.1",     4, 0xd0, MAPDEF_PCIMASK),
-	MAPDEF("pcie0.2",     4, 0xb0, MAPDEF_PCIMASK),
-	MAPDEF("pcie0.3",     4, 0x70, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.0",     8, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.1",     8, 0xd0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.2",     8, 0xb0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.3",     8, 0x70, MAPDEF_PCIMASK),
-	MAPDEF("pcie2.0",     4, 0xf0, MAPDEF_PCIMASK),
-	MAPDEF("pcie3.0",     8, 0xf0, MAPDEF_PCIMASK),
-	{},
-};
-
-static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
-	.num_wins            = 20,
-	.num_remappable_wins = 8,
-	.win_cfg_offset      = armada_370_xp_mbus_win_offset,
-	.setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
-	.show_cpu_target     = mvebu_sdram_debug_show_orion,
-	.map                 = armada_xp_map,
-};
-
-static const struct mvebu_mbus_mapping kirkwood_map[] = {
-	MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.0", 4, 0xd0, MAPDEF_PCIMASK),
-	MAPDEF("sram",    3, 0x01, MAPDEF_NOMASK),
-	MAPDEF("nand",    1, 0x2f, MAPDEF_NOMASK),
-	{},
 };
 
 static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
@@ -640,16 +550,6 @@ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
 	.win_cfg_offset      = orion_mbus_win_offset,
 	.setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
 	.show_cpu_target     = mvebu_sdram_debug_show_orion,
-	.map                 = kirkwood_map,
-};
-
-static const struct mvebu_mbus_mapping dove_map[] = {
-	MAPDEF("pcie0.0",    0x4, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.0",    0x8, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("cesa",       0x3, 0x01, MAPDEF_NOMASK),
-	MAPDEF("bootrom",    0x1, 0xfd, MAPDEF_NOMASK),
-	MAPDEF("scratchpad", 0xd, 0x0, MAPDEF_NOMASK),
-	{},
 };
 
 static const struct mvebu_mbus_soc_data dove_mbus_data = {
@@ -658,18 +558,6 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = {
 	.win_cfg_offset      = orion_mbus_win_offset,
 	.setup_cpu_target    = mvebu_mbus_dove_setup_cpu_target,
 	.show_cpu_target     = mvebu_sdram_debug_show_dove,
-	.map                 = dove_map,
-};
-
-static const struct mvebu_mbus_mapping orion5x_map[] = {
-	MAPDEF("pcie0.0",     4, 0x51, MAPDEF_ORIONPCIMASK),
-	MAPDEF("pci0.0",      3, 0x51, MAPDEF_ORIONPCIMASK),
-	MAPDEF("devbus-boot", 1, 0x0f, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs0",  1, 0x1e, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs1",  1, 0x1d, MAPDEF_NOMASK),
-	MAPDEF("devbus-cs2",  1, 0x1b, MAPDEF_NOMASK),
-	MAPDEF("sram",        0, 0x00, MAPDEF_NOMASK),
-	{},
 };
 
 /*
@@ -682,7 +570,6 @@ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
 	.win_cfg_offset      = orion_mbus_win_offset,
 	.setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
 	.show_cpu_target     = mvebu_sdram_debug_show_orion,
-	.map                 = orion5x_map,
 };
 
 static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
@@ -691,21 +578,6 @@ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
 	.win_cfg_offset      = orion_mbus_win_offset,
 	.setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
 	.show_cpu_target     = mvebu_sdram_debug_show_orion,
-	.map                 = orion5x_map,
-};
-
-static const struct mvebu_mbus_mapping mv78xx0_map[] = {
-	MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK),
-	MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK),
-	MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK),
-	MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK),
-	MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK),
-	MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK),
-	{},
 };
 
 static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
@@ -714,7 +586,6 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
 	.win_cfg_offset      = mv78xx0_mbus_win_offset,
 	.setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
 	.show_cpu_target     = mvebu_sdram_debug_show_orion,
-	.map                 = mv78xx0_map,
 };
 
 /*
@@ -725,9 +596,9 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
  */
 static const struct of_device_id of_mvebu_mbus_ids[] = {
 	{ .compatible = "marvell,armada370-mbus",
-	  .data = &armada_370_mbus_data, },
+	  .data = &armada_370_xp_mbus_data, },
 	{ .compatible = "marvell,armadaxp-mbus",
-	  .data = &armada_xp_mbus_data, },
+	  .data = &armada_370_xp_mbus_data, },
 	{ .compatible = "marvell,kirkwood-mbus",
 	  .data = &kirkwood_mbus_data, },
 	{ .compatible = "marvell,dove-mbus",
@@ -748,48 +619,27 @@ static const struct of_device_id of_mvebu_mbus_ids[] = {
 /*
  * Public API of the driver
  */
-int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
-				      size_t size, phys_addr_t remap,
-				      unsigned int flags)
+int mvebu_mbus_add_window_remap_by_id(unsigned int target,
+				      unsigned int attribute,
+				      phys_addr_t base, size_t size,
+				      phys_addr_t remap)
 {
 	struct mvebu_mbus_state *s = &mbus_state;
-	u8 target, attr;
-	int i;
-
-	if (!s->soc->map)
-		return -ENODEV;
-
-	for (i = 0; s->soc->map[i].name; i++)
-		if (!strcmp(s->soc->map[i].name, devname))
-			break;
-
-	if (!s->soc->map[i].name) {
-		pr_err("unknown device '%s'\n", devname);
-		return -ENODEV;
-	}
-
-	target = s->soc->map[i].target;
-	attr   = s->soc->map[i].attr;
-
-	if (flags == MVEBU_MBUS_PCI_MEM)
-		attr |= 0x8;
-	else if (flags == MVEBU_MBUS_PCI_WA)
-		attr |= 0x28;
 
-	if (!mvebu_mbus_window_conflicts(s, base, size, target, attr)) {
-		pr_err("cannot add window '%s', conflicts with another window\n",
-		       devname);
+	if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) {
+		pr_err("cannot add window '%x:%x', conflicts with another window\n",
+		       target, attribute);
 		return -EINVAL;
 	}
 
-	return mvebu_mbus_alloc_window(s, base, size, remap, target, attr);
-
+	return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute);
 }
 
-int mvebu_mbus_add_window(const char *devname, phys_addr_t base, size_t size)
+int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
+				phys_addr_t base, size_t size)
 {
-	return mvebu_mbus_add_window_remap_flags(devname, base, size,
-						 MVEBU_MBUS_NO_REMAP, 0);
+	return mvebu_mbus_add_window_remap_by_id(target, attribute, base,
+						 size, MVEBU_MBUS_NO_REMAP);
 }
 
 int mvebu_mbus_del_window(phys_addr_t base, size_t size)
@@ -804,6 +654,20 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size)
 	return 0;
 }
 
+void mvebu_mbus_get_pcie_mem_aperture(struct resource *res)
+{
+	if (!res)
+		return;
+	*res = mbus_state.pcie_mem_aperture;
+}
+
+void mvebu_mbus_get_pcie_io_aperture(struct resource *res)
+{
+	if (!res)
+		return;
+	*res = mbus_state.pcie_io_aperture;
+}
+
 static __init int mvebu_mbus_debugfs_init(void)
 {
 	struct mvebu_mbus_state *s = &mbus_state;
@@ -830,14 +694,41 @@ static __init int mvebu_mbus_debugfs_init(void)
 }
 fs_initcall(mvebu_mbus_debugfs_init);
 
+static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
+					 phys_addr_t mbuswins_phys_base,
+					 size_t mbuswins_size,
+					 phys_addr_t sdramwins_phys_base,
+					 size_t sdramwins_size)
+{
+	int win;
+
+	mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
+	if (!mbus->mbuswins_base)
+		return -ENOMEM;
+
+	mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size);
+	if (!mbus->sdramwins_base) {
+		iounmap(mbus_state.mbuswins_base);
+		return -ENOMEM;
+	}
+
+	if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
+		mbus->hw_io_coherency = 1;
+
+	for (win = 0; win < mbus->soc->num_wins; win++)
+		mvebu_mbus_disable_window(mbus, win);
+
+	mbus->soc->setup_cpu_target(mbus);
+
+	return 0;
+}
+
 int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
 			   size_t mbuswins_size,
 			   phys_addr_t sdramwins_phys_base,
 			   size_t sdramwins_size)
 {
-	struct mvebu_mbus_state *mbus = &mbus_state;
 	const struct of_device_id *of_id;
-	int win;
 
 	for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++)
 		if (!strcmp(of_id->compatible, soc))
@@ -848,25 +739,201 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
 		return -ENODEV;
 	}
 
-	mbus->soc = of_id->data;
+	mbus_state.soc = of_id->data;
 
-	mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
-	if (!mbus->mbuswins_base)
-		return -ENOMEM;
+	return mvebu_mbus_common_init(&mbus_state,
+			mbuswins_phys_base,
+			mbuswins_size,
+			sdramwins_phys_base,
+			sdramwins_size);
+}
 
-	mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size);
-	if (!mbus->sdramwins_base) {
-		iounmap(mbus_state.mbuswins_base);
+#ifdef CONFIG_OF
+/*
+ * The window IDs in the ranges DT property have the following format:
+ *  - bits 28 to 31: MBus custom field
+ *  - bits 24 to 27: window target ID
+ *  - bits 16 to 23: window attribute ID
+ *  - bits  0 to 15: unused
+ */
+#define CUSTOM(id) (((id) & 0xF0000000) >> 24)
+#define TARGET(id) (((id) & 0x0F000000) >> 24)
+#define ATTR(id)   (((id) & 0x00FF0000) >> 16)
+
+static int __init mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
+				    u32 base, u32 size,
+				    u8 target, u8 attr)
+{
+	if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) {
+		pr_err("cannot add window '%04x:%04x', conflicts with another window\n",
+		       target, attr);
+		return -EBUSY;
+	}
+
+	if (mvebu_mbus_alloc_window(mbus, base, size, MVEBU_MBUS_NO_REMAP,
+				    target, attr)) {
+		pr_err("cannot add window '%04x:%04x', too many windows\n",
+		       target, attr);
 		return -ENOMEM;
 	}
+	return 0;
+}
 
-	if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
-		mbus->hw_io_coherency = 1;
+static int __init
+mbus_parse_ranges(struct device_node *node,
+		  int *addr_cells, int *c_addr_cells, int *c_size_cells,
+		  int *cell_count, const __be32 **ranges_start,
+		  const __be32 **ranges_end)
+{
+	const __be32 *prop;
+	int ranges_len, tuple_len;
+
+	/* Allow a node with no 'ranges' property */
+	*ranges_start = of_get_property(node, "ranges", &ranges_len);
+	if (*ranges_start == NULL) {
+		*addr_cells = *c_addr_cells = *c_size_cells = *cell_count = 0;
+		*ranges_start = *ranges_end = NULL;
+		return 0;
+	}
+	*ranges_end = *ranges_start + ranges_len / sizeof(__be32);
 
-	for (win = 0; win < mbus->soc->num_wins; win++)
-		mvebu_mbus_disable_window(mbus, win);
+	*addr_cells = of_n_addr_cells(node);
 
-	mbus->soc->setup_cpu_target(mbus);
+	prop = of_get_property(node, "#address-cells", NULL);
+	*c_addr_cells = be32_to_cpup(prop);
+
+	prop = of_get_property(node, "#size-cells", NULL);
+	*c_size_cells = be32_to_cpup(prop);
+
+	*cell_count = *addr_cells + *c_addr_cells + *c_size_cells;
+	tuple_len = (*cell_count) * sizeof(__be32);
+
+	if (ranges_len % tuple_len) {
+		pr_warn("malformed ranges entry '%s'\n", node->name);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int __init mbus_dt_setup(struct mvebu_mbus_state *mbus,
+				struct device_node *np)
+{
+	int addr_cells, c_addr_cells, c_size_cells;
+	int i, ret, cell_count;
+	const __be32 *r, *ranges_start, *ranges_end;
+
+	ret = mbus_parse_ranges(np, &addr_cells, &c_addr_cells,
+				&c_size_cells, &cell_count,
+				&ranges_start, &ranges_end);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0, r = ranges_start; r < ranges_end; r += cell_count, i++) {
+		u32 windowid, base, size;
+		u8 target, attr;
+
+		/*
+		 * An entry with a non-zero custom field do not
+		 * correspond to a static window, so skip it.
+		 */
+		windowid = of_read_number(r, 1);
+		if (CUSTOM(windowid))
+			continue;
+
+		target = TARGET(windowid);
+		attr = ATTR(windowid);
 
+		base = of_read_number(r + c_addr_cells, addr_cells);
+		size = of_read_number(r + c_addr_cells + addr_cells,
+				      c_size_cells);
+		ret = mbus_dt_setup_win(mbus, base, size, target, attr);
+		if (ret < 0)
+			return ret;
+	}
 	return 0;
 }
+
+static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
+						 struct resource *mem,
+						 struct resource *io)
+{
+	u32 reg[2];
+	int ret;
+
+	/*
+	 * These are optional, so we clear them and they'll
+	 * be zero if they are missing from the DT.
+	 */
+	memset(mem, 0, sizeof(struct resource));
+	memset(io, 0, sizeof(struct resource));
+
+	ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
+	if (!ret) {
+		mem->start = reg[0];
+		mem->end = mem->start + reg[1];
+		mem->flags = IORESOURCE_MEM;
+	}
+
+	ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
+	if (!ret) {
+		io->start = reg[0];
+		io->end = io->start + reg[1];
+		io->flags = IORESOURCE_IO;
+	}
+}
+
+int __init mvebu_mbus_dt_init(void)
+{
+	struct resource mbuswins_res, sdramwins_res;
+	struct device_node *np, *controller;
+	const struct of_device_id *of_id;
+	const __be32 *prop;
+	int ret;
+
+	np = of_find_matching_node(NULL, of_mvebu_mbus_ids);
+	if (!np) {
+		pr_err("could not find a matching SoC family\n");
+		return -ENODEV;
+	}
+
+	of_id = of_match_node(of_mvebu_mbus_ids, np);
+	mbus_state.soc = of_id->data;
+
+	prop = of_get_property(np, "controller", NULL);
+	if (!prop) {
+		pr_err("required 'controller' property missing\n");
+		return -EINVAL;
+	}
+
+	controller = of_find_node_by_phandle(be32_to_cpup(prop));
+	if (!controller) {
+		pr_err("could not find an 'mbus-controller' node\n");
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(controller, 0, &mbuswins_res)) {
+		pr_err("cannot get MBUS register address\n");
+		return -EINVAL;
+	}
+
+	if (of_address_to_resource(controller, 1, &sdramwins_res)) {
+		pr_err("cannot get SDRAM register address\n");
+		return -EINVAL;
+	}
+
+	/* Get optional pcie-{mem,io}-aperture properties */
+	mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture,
+					  &mbus_state.pcie_io_aperture);
+
+	ret = mvebu_mbus_common_init(&mbus_state,
+				     mbuswins_res.start,
+				     resource_size(&mbuswins_res),
+				     sdramwins_res.start,
+				     resource_size(&sdramwins_res));
+	if (ret)
+		return ret;
+
+	/* Setup statically declared windows in the DT */
+	return mbus_dt_setup(&mbus_state, np);
+}
+#endif
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 9746705..0671e45 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -95,6 +95,7 @@ bsr_size_show(struct device *dev, struct device_attribute *attr, char *buf)
 	struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
 }
+static DEVICE_ATTR_RO(bsr_size);
 
 static ssize_t
 bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -102,20 +103,23 @@ bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
 	struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
 }
+static DEVICE_ATTR_RO(bsr_stride);
 
 static ssize_t
-bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf)
+bsr_length_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
 	return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
 }
+static DEVICE_ATTR_RO(bsr_length);
 
-static struct device_attribute bsr_dev_attrs[] = {
-	__ATTR(bsr_size, S_IRUGO, bsr_size_show, NULL),
-	__ATTR(bsr_stride, S_IRUGO, bsr_stride_show, NULL),
-	__ATTR(bsr_length, S_IRUGO, bsr_len_show, NULL),
-	__ATTR_NULL
+static struct attribute *bsr_dev_attrs[] = {
+	&dev_attr_bsr_size.attr,
+	&dev_attr_bsr_stride.attr,
+	&dev_attr_bsr_length.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(bsr_dev);
 
 static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
 {
@@ -308,7 +312,7 @@ static int __init bsr_init(void)
 		ret = PTR_ERR(bsr_class);
 		goto out_err_1;
 	}
-	bsr_class->dev_attrs = bsr_dev_attrs;
+	bsr_class->dev_groups = bsr_dev_groups;
 
 	ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
 	bsr_major = MAJOR(bsr_dev);
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index 19a12ac..6a86b6f 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -164,7 +164,9 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	clk_prepare_enable(mxc_rng->clk);
+	err = clk_prepare_enable(mxc_rng->clk);
+	if (err)
+		goto out;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	mxc_rng->mem = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 5c5cc00..d39cca6 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1182,14 +1182,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
 		}
 		count++;
 
-		if (gis & (BIT1 + BIT0)) {
+		if (gis & (BIT1 | BIT0)) {
 			isr = read_reg16(info, CHB + ISR);
 			if (isr & IRQ_DCD)
 				dcd_change(info, tty);
 			if (isr & IRQ_CTS)
 				cts_change(info, tty);
 		}
-		if (gis & (BIT3 + BIT2))
+		if (gis & (BIT3 | BIT2))
 		{
 			isr = read_reg16(info, CHA + ISR);
 			if (isr & IRQ_TIMER) {
@@ -1210,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
 			if (isr & IRQ_RXTIME) {
 				issue_command(info, CHA, CMD_RXFIFO_READ);
 			}
-			if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) {
+			if (isr & (IRQ_RXEOM | IRQ_RXFIFO)) {
 				if (info->params.mode == MGSL_MODE_HDLC)
 					rx_ready_hdlc(info, isr & IRQ_RXEOM);
 				else
@@ -3031,11 +3031,11 @@ static void loopback_enable(MGSLPC_INFO *info)
 	unsigned char val;
 
 	/* CCR1:02..00  CM[2..0] Clock Mode = 111 (clock mode 7) */
-	val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0);
+	val = read_reg(info, CHA + CCR1) | (BIT2 | BIT1 | BIT0);
 	write_reg(info, CHA + CCR1, val);
 
 	/* CCR2:04 SSEL Clock source select, 1=submode b */
-	val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5);
+	val = read_reg(info, CHA + CCR2) | (BIT4 | BIT5);
 	write_reg(info, CHA + CCR2, val);
 
 	/* set LinkSpeed if available, otherwise default to 2Mbps */
@@ -3125,10 +3125,10 @@ static void hdlc_mode(MGSLPC_INFO *info)
 		val |= BIT4;
 		break;		// FM0
 	case HDLC_ENCODING_BIPHASE_MARK:
-		val |= BIT4 + BIT2;
+		val |= BIT4 | BIT2;
 		break;		// FM1
 	case HDLC_ENCODING_BIPHASE_LEVEL:
-		val |= BIT4 + BIT3;
+		val |= BIT4 | BIT3;
 		break;		// Manchester
 	}
 	write_reg(info, CHA + CCR0, val);
@@ -3185,7 +3185,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
 	 */
 	val = 0x00;
 	if (info->params.crc_type == HDLC_CRC_NONE)
-		val |= BIT2 + BIT1;
+		val |= BIT2 | BIT1;
 	if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
 		val |= BIT5;
 	switch (info->params.preamble_length)
@@ -3197,7 +3197,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
 		val |= BIT6;
 		break;
 	case HDLC_PREAMBLE_LENGTH_64BITS:
-		val |= BIT7 + BIT6;
+		val |= BIT7 | BIT6;
 		break;
 	}
 	write_reg(info, CHA + CCR3, val);
@@ -3264,8 +3264,8 @@ static void hdlc_mode(MGSLPC_INFO *info)
 		clear_reg_bits(info, CHA + PVR, BIT3);
 
 	irq_enable(info, CHA,
-			 IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT +
-			 IRQ_UNDERRUN + IRQ_TXFIFO);
+			 IRQ_RXEOM | IRQ_RXFIFO | IRQ_ALLSENT |
+			 IRQ_UNDERRUN | IRQ_TXFIFO);
 	issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
 	wait_command_complete(info, CHA);
 	read_reg16(info, CHA + ISR);	/* clear pending IRQs */
@@ -3582,8 +3582,8 @@ static void async_mode(MGSLPC_INFO *info)
 	} else
 		clear_reg_bits(info, CHA + PVR, BIT3);
 	irq_enable(info, CHA,
-			  IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME +
-			  IRQ_ALLSENT + IRQ_TXFIFO);
+			  IRQ_RXEOM | IRQ_RXFIFO | IRQ_BREAK_ON | IRQ_RXTIME |
+			  IRQ_ALLSENT | IRQ_TXFIFO);
 	issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
 	wait_command_complete(info, CHA);
 	read_reg16(info, CHA + ISR);	/* clear pending IRQs */
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index bf2349db..7cc1fe22 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -876,11 +876,6 @@ found:
 	if (useinput)
 		sonypi_report_input_event(event);
 
-#ifdef CONFIG_ACPI
-	if (sonypi_acpi_device)
-		acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event);
-#endif
-
 	kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event,
 			sizeof(event), &sonypi_device.fifo_lock);
 	kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index 7faeb1c..0e506ba 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -279,33 +279,37 @@ loff_t srom_llseek(struct file *file, loff_t offset, int origin)
 	return fixed_size_llseek(file, offset, origin, srom->total_size);
 }
 
-static ssize_t total_show(struct device *dev,
-			  struct device_attribute *attr, char *buf)
+static ssize_t total_size_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct srom_dev *srom = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", srom->total_size);
 }
+static DEVICE_ATTR_RO(total_size);
 
-static ssize_t sector_show(struct device *dev,
-			   struct device_attribute *attr, char *buf)
+static ssize_t sector_size_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct srom_dev *srom = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", srom->sector_size);
 }
+static DEVICE_ATTR_RO(sector_size);
 
-static ssize_t page_show(struct device *dev,
-			 struct device_attribute *attr, char *buf)
+static ssize_t page_size_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct srom_dev *srom = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", srom->page_size);
 }
+static DEVICE_ATTR_RO(page_size);
 
-static struct device_attribute srom_dev_attrs[] = {
-	__ATTR(total_size, S_IRUGO, total_show, NULL),
-	__ATTR(sector_size, S_IRUGO, sector_show, NULL),
-	__ATTR(page_size, S_IRUGO, page_show, NULL),
-	__ATTR_NULL
+static struct attribute *srom_dev_attrs[] = {
+	&dev_attr_total_size.attr,
+	&dev_attr_sector_size.attr,
+	&dev_attr_page_size.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(srom_dev);
 
 static char *srom_devnode(struct device *dev, umode_t *mode)
 {
@@ -349,7 +353,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
 
 	dev = device_create(srom_class, &platform_bus,
 			    MKDEV(srom_major, index), srom, "%d", index);
-	return PTR_RET(dev);
+	return PTR_ERR_OR_ZERO(dev);
 }
 
 /** srom_init() - Initialize the driver's module. */
@@ -418,7 +422,7 @@ static int srom_init(void)
 		result = PTR_ERR(srom_class);
 		goto fail_cdev;
 	}
-	srom_class->dev_attrs = srom_dev_attrs;
+	srom_class->dev_groups = srom_dev_groups;
 	srom_class->devnode = srom_devnode;
 
 	/* Do per-partition initialization */
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 1b456fe..d0e75aa 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -272,9 +272,12 @@ static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev,
 	unsigned long flags;
 
 	spin_lock_irqsave(&portdev->ports_lock, flags);
-	list_for_each_entry(port, &portdev->ports, list)
-		if (port->cdev->dev == dev)
+	list_for_each_entry(port, &portdev->ports, list) {
+		if (port->cdev->dev == dev) {
+			kref_get(&port->kref);
 			goto out;
+		}
+	}
 	port = NULL;
 out:
 	spin_unlock_irqrestore(&portdev->ports_lock, flags);
@@ -746,6 +749,10 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
 
 	port = filp->private_data;
 
+	/* Port is hot-unplugged. */
+	if (!port->guest_connected)
+		return -ENODEV;
+
 	if (!port_has_data(port)) {
 		/*
 		 * If nothing's connected on the host just return 0 in
@@ -762,7 +769,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
 		if (ret < 0)
 			return ret;
 	}
-	/* Port got hot-unplugged. */
+	/* Port got hot-unplugged while we were waiting above. */
 	if (!port->guest_connected)
 		return -ENODEV;
 	/*
@@ -932,13 +939,25 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
 	if (is_rproc_serial(port->out_vq->vdev))
 		return -EINVAL;
 
+	/*
+	 * pipe->nrbufs == 0 means there are no data to transfer,
+	 * so this returns just 0 for no data.
+	 */
+	pipe_lock(pipe);
+	if (!pipe->nrbufs) {
+		ret = 0;
+		goto error_out;
+	}
+
 	ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
 	if (ret < 0)
-		return ret;
+		goto error_out;
 
 	buf = alloc_buf(port->out_vq, 0, pipe->nrbufs);
-	if (!buf)
-		return -ENOMEM;
+	if (!buf) {
+		ret = -ENOMEM;
+		goto error_out;
+	}
 
 	sgl.n = 0;
 	sgl.len = 0;
@@ -946,12 +965,17 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
 	sgl.sg = buf->sg;
 	sg_init_table(sgl.sg, sgl.size);
 	ret = __splice_from_pipe(pipe, &sd, pipe_to_sg);
+	pipe_unlock(pipe);
 	if (likely(ret > 0))
 		ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true);
 
 	if (unlikely(ret <= 0))
 		free_buf(buf, true);
 	return ret;
+
+error_out:
+	pipe_unlock(pipe);
+	return ret;
 }
 
 static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
@@ -1019,14 +1043,14 @@ static int port_fops_open(struct inode *inode, struct file *filp)
 	struct port *port;
 	int ret;
 
+	/* We get the port with a kref here */
 	port = find_port_by_devt(cdev->dev);
+	if (!port) {
+		/* Port was unplugged before we could proceed */
+		return -ENXIO;
+	}
 	filp->private_data = port;
 
-	/* Prevent against a port getting hot-unplugged at the same time */
-	spin_lock_irq(&port->portdev->ports_lock);
-	kref_get(&port->kref);
-	spin_unlock_irq(&port->portdev->ports_lock);
-
 	/*
 	 * Don't allow opening of console port devices -- that's done
 	 * via /dev/hvc
@@ -1498,14 +1522,6 @@ static void remove_port(struct kref *kref)
 
 	port = container_of(kref, struct port, kref);
 
-	sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
-	device_destroy(pdrvdata.class, port->dev->devt);
-	cdev_del(port->cdev);
-
-	kfree(port->name);
-
-	debugfs_remove(port->debugfs_file);
-
 	kfree(port);
 }
 
@@ -1513,18 +1529,22 @@ static void remove_port_data(struct port *port)
 {
 	struct port_buffer *buf;
 
+	spin_lock_irq(&port->inbuf_lock);
 	/* Remove unused data this port might have received. */
 	discard_port_data(port);
 
-	reclaim_consumed_buffers(port);
-
 	/* Remove buffers we queued up for the Host to send us data in. */
 	while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
 		free_buf(buf, true);
+	spin_unlock_irq(&port->inbuf_lock);
+
+	spin_lock_irq(&port->outvq_lock);
+	reclaim_consumed_buffers(port);
 
 	/* Free pending buffers from the out-queue. */
 	while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
 		free_buf(buf, true);
+	spin_unlock_irq(&port->outvq_lock);
 }
 
 /*
@@ -1538,14 +1558,18 @@ static void unplug_port(struct port *port)
 	list_del(&port->list);
 	spin_unlock_irq(&port->portdev->ports_lock);
 
+	spin_lock_irq(&port->inbuf_lock);
 	if (port->guest_connected) {
+		/* Let the app know the port is going down. */
+		send_sigio_to_port(port);
+
+		/* Do this after sigio is actually sent */
 		port->guest_connected = false;
 		port->host_connected = false;
-		wake_up_interruptible(&port->waitqueue);
 
-		/* Let the app know the port is going down. */
-		send_sigio_to_port(port);
+		wake_up_interruptible(&port->waitqueue);
 	}
+	spin_unlock_irq(&port->inbuf_lock);
 
 	if (is_console_port(port)) {
 		spin_lock_irq(&pdrvdata_lock);
@@ -1563,6 +1587,14 @@ static void unplug_port(struct port *port)
 	 */
 	port->portdev = NULL;
 
+	sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
+	device_destroy(pdrvdata.class, port->dev->devt);
+	cdev_del(port->cdev);
+
+	kfree(port->name);
+
+	debugfs_remove(port->debugfs_file);
+
 	/*
 	 * Locks around here are not necessary - a port can't be
 	 * opened after we removed the port struct from ports_list
@@ -1655,7 +1687,9 @@ static void handle_control_message(struct ports_device *portdev,
 		 * If the guest is connected, it'll be interested in
 		 * knowing the host connection state changed.
 		 */
+		spin_lock_irq(&port->inbuf_lock);
 		send_sigio_to_port(port);
+		spin_unlock_irq(&port->inbuf_lock);
 		break;
 	case VIRTIO_CONSOLE_PORT_NAME:
 		/*
@@ -1775,13 +1809,13 @@ static void in_intr(struct virtqueue *vq)
 	if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
 		discard_port_data(port);
 
+	/* Send a SIGIO indicating new data in case the process asked for it */
+	send_sigio_to_port(port);
+
 	spin_unlock_irqrestore(&port->inbuf_lock, flags);
 
 	wake_up_interruptible(&port->waitqueue);
 
-	/* Send a SIGIO indicating new data in case the process asked for it */
-	send_sigio_to_port(port);
-
 	if (is_console_port(port) && hvc_poll(port->cons.hvc))
 		hvc_kick();
 }
@@ -2215,10 +2249,8 @@ static int __init init(void)
 	}
 
 	pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL);
-	if (!pdrvdata.debugfs_dir) {
-		pr_warning("Error %ld creating debugfs dir for virtio-ports\n",
-			   PTR_ERR(pdrvdata.debugfs_dir));
-	}
+	if (!pdrvdata.debugfs_dir)
+		pr_warning("Error creating debugfs dir for virtio-ports\n");
 	INIT_LIST_HEAD(&pdrvdata.consoles);
 	INIT_LIST_HEAD(&pdrvdata.portdevs);
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 51380d6..cd49096 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -27,7 +27,7 @@ config COMMON_CLK_DEBUG
 	bool "DebugFS representation of clock tree"
 	select DEBUG_FS
 	---help---
-	  Creates a directory hierchy in debugfs for visualizing the clk
+	  Creates a directory hierarchy in debugfs for visualizing the clk
 	  tree structure.  Each directory contains read-only members
 	  that export information specific to that clk node: clk_rate,
 	  clk_flags, clk_prepare_count, clk_enable_count &
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 54a191c..56a00db 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -702,7 +702,7 @@ void __clk_unprepare(struct clk *clk)
 
 /**
  * clk_unprepare - undo preparation of a clock source
- * @clk: the clk being unprepare
+ * @clk: the clk being unprepared
  *
  * clk_unprepare may sleep, which differentiates it from clk_disable.  In a
  * simple case, clk_unprepare can be used instead of clk_disable to gate a clk
@@ -869,6 +869,7 @@ EXPORT_SYMBOL_GPL(clk_enable);
 /**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
+ * @rate: the rate which is to be rounded
  *
  * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
  */
@@ -956,7 +957,7 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
  *
  * Walks the subtree of clks starting with clk and recalculates rates as it
  * goes.  Note that if a clk does not implement the .recalc_rate callback then
- * it is assumed that the clock will take on the rate of it's parent.
+ * it is assumed that the clock will take on the rate of its parent.
  *
  * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
  * if necessary.
@@ -1026,7 +1027,7 @@ EXPORT_SYMBOL_GPL(clk_get_rate);
  * pre-rate change notifications and returns early if no clks in the
  * subtree have subscribed to the notifications.  Note that if a clk does not
  * implement the .recalc_rate callback then it is assumed that the clock will
- * take on the rate of it's parent.
+ * take on the rate of its parent.
  *
  * Caller must hold prepare_lock.
  */
@@ -1198,7 +1199,7 @@ static void clk_change_rate(struct clk *clk)
  * outcome of clk's .round_rate implementation.  If *parent_rate is unchanged
  * after calling .round_rate then upstream parent propagation is ignored.  If
  * *parent_rate comes back with a new rate for clk's parent then we propagate
- * up to clk's parent and set it's rate.  Upward propagation will continue
+ * up to clk's parent and set its rate.  Upward propagation will continue
  * until either a clk does not support the CLK_SET_RATE_PARENT flag or
  * .round_rate stops requesting changes to clk's parent_rate.
  *
@@ -1648,7 +1649,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 	 * The .init callback is not used by any of the basic clock types, but
 	 * exists for weird hardware that must perform initialization magic.
 	 * Please consider other ways of solving initialization problems before
-	 * using this callback, as it's use is discouraged.
+	 * using this callback, as its use is discouraged.
 	 */
 	if (clk->ops->init)
 		clk->ops->init(clk->hw);
@@ -1675,7 +1676,7 @@ out:
  * very large numbers of clocks that need to be statically initialized.  It is
  * a layering violation to include clk-private.h from any code which implements
  * a clock's .ops; as such any statically initialized clock data MUST be in a
- * separate C file from the logic that implements it's operations.  Returns 0
+ * separate C file from the logic that implements its operations.  Returns 0
  * on success, otherwise an error code.
  */
 struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index 9b1bbd5..51b48da 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -62,7 +62,7 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = {
 #endif /* CONFIG_PM_SLEEP */
 
 /* register exynos_audss clocks */
-void __init exynos_audss_clk_init(struct device_node *np)
+static void __init exynos_audss_clk_init(struct device_node *np)
 {
 	reg_base = of_iomap(np, 0);
 	if (!reg_base) {
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 1bdb882..68f9a4a 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -17,7 +17,6 @@
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS		0x4200
@@ -97,12 +96,14 @@
 #define GATE_IP_PERIL		0xc950
 #define E4210_GATE_IP_PERIR	0xc960
 #define GATE_BLOCK		0xc970
+#define E4X12_MPLL_LOCK		0x10008
 #define E4X12_MPLL_CON0		0x10108
 #define SRC_DMC			0x10200
 #define SRC_MASK_DMC		0x10300
 #define DIV_DMC0		0x10500
 #define DIV_DMC1		0x10504
 #define GATE_IP_DMC		0x10900
+#define APLL_LOCK		0x14000
 #define APLL_CON0		0x14100
 #define E4210_MPLL_CON0		0x14108
 #define SRC_CPU			0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
 	EXYNOS4X12,
 };
 
+/* list of PLLs to be registered */
+enum exynos4_plls {
+	apll, mpll, epll, vpll,
+	nr_plls			/* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the clock
  * for device tree based platforms. The clocks are categorized into three
@@ -169,7 +176,7 @@ enum exynos4_clks {
 	gicisp, smmu_isp, smmu_drc, smmu_fd, smmu_lite0, smmu_lite1, mcuctl_isp,
 	mpwm_isp, i2c0_isp, i2c1_isp, mtcadc_isp, pwm_isp, wdt_isp, uart_isp,
 	asyncaxim, smmu_ispcx, spi0_isp, spi1_isp, pwm_isp_sclk, spi0_isp_sclk,
-	spi1_isp_sclk, uart_isp_sclk,
+	spi1_isp_sclk, uart_isp_sclk, tmu_apbif,
 
 	/* mux clocks */
 	mout_fimc0 = 384, mout_fimc1, mout_fimc2, mout_fimc3, mout_cam0,
@@ -338,24 +345,24 @@ PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
 PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
 	FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0),
 	FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
 	FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
 	FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
 	FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
 };
 
-struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
 	FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
 };
 
 /* list of mux clocks supported in all exynos4 soc's */
-struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 	MUX_FA(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
 			CLK_SET_RATE_PARENT, 0, "mout_apll"),
 	MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
@@ -372,7 +379,7 @@ struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4210 soc */
-struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
 	MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
 	MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
 	MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
@@ -423,7 +430,7 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4x12 soc */
-struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
 	MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
 			SRC_CPU, 24, 1, "mout_mpll"),
 	MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
@@ -491,7 +498,7 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in all exynos4 soc's */
-struct samsung_div_clock exynos4_div_clks[] __initdata = {
+static struct samsung_div_clock exynos4_div_clks[] __initdata = {
 	DIV(none, "div_core", "mout_core", DIV_CPU0, 0, 3),
 	DIV(none, "div_core2", "div_core", DIV_CPU0, 28, 3),
 	DIV(none, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
@@ -554,7 +561,7 @@ struct samsung_div_clock exynos4_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4210 soc */
-struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
 	DIV(aclk200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
 	DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4),
 	DIV(none, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
@@ -565,7 +572,7 @@ struct samsung_div_clock exynos4210_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4x12 soc */
-struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
 	DIV(none, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
 	DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
 	DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
@@ -590,7 +597,7 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in all exynos4 soc's */
-struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
 	/*
 	 * After all Exynos4 based platforms are migrated to use device tree,
 	 * the device name and clock alias names specified below for some
@@ -782,7 +789,7 @@ struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in exynos4210 soc */
-struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
 	GATE(tvenc, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
 	GATE(g2d, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
 	GATE(rotator, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
@@ -814,10 +821,11 @@ struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
 	GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"),
 	GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1",
 			E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+	GATE(tmu_apbif, "tmu_apbif", "aclk100", E4210_GATE_IP_PERIR, 17, 0, 0),
 };
 
 /* list of gate clocks supported in exynos4x12 soc */
-struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
 	GATE(audss, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
 	GATE(mdnie0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
 	GATE(rotator, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
@@ -915,6 +923,7 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
 	GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
 			CLK_IGNORE_UNUSED, 0),
 	GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
+	GATE(tmu_apbif, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 0),
 };
 
 /*
@@ -969,28 +978,27 @@ static void __init exynos4_clk_register_finpll(unsigned long xom)
 
 }
 
-/*
- * This function allows non-dt platforms to specify the clock speed of the
- * xxti and xusbxti clocks. These clocks are then registered with the specified
- * clock speed.
- */
-void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
-						unsigned long xusbxti_f)
-{
-	exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
-	exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
-	samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
-			ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
-}
-
 static __initdata struct of_device_id ext_clk_match[] = {
 	{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
 	{ .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
 	{},
 };
 
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+		APLL_CON0, "fout_apll", NULL),
+	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
+		E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL),
+	[epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+		EPLL_CON0, "fout_epll", NULL),
+	[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+		VPLL_CON0, "fout_vpll", NULL),
+};
+
 /* register exynos4 clocks */
-void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
+static void __init exynos4_clk_init(struct device_node *np,
+				    enum exynos4_soc exynos4_soc,
+				    void __iomem *reg_base, unsigned long xom)
 {
 	struct clk *apll, *mpll, *epll, *vpll;
 
@@ -1025,22 +1033,16 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
 					reg_base + EPLL_CON0, pll_4600);
 		vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
 					reg_base + VPLL_CON0, pll_4650c);
+
+		samsung_clk_add_lookup(apll, fout_apll);
+		samsung_clk_add_lookup(mpll, fout_mpll);
+		samsung_clk_add_lookup(epll, fout_epll);
+		samsung_clk_add_lookup(vpll, fout_vpll);
 	} else {
-		apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-					reg_base + APLL_CON0);
-		mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-					reg_base + E4X12_MPLL_CON0);
-		epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-					reg_base + EPLL_CON0);
-		vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
-					reg_base + VPLL_CON0);
+		samsung_clk_register_pll(exynos4_plls,
+					ARRAY_SIZE(exynos4_plls), reg_base);
 	}
 
-	samsung_clk_add_lookup(apll, fout_apll);
-	samsung_clk_add_lookup(mpll, fout_mpll);
-	samsung_clk_add_lookup(epll, fout_epll);
-	samsung_clk_add_lookup(vpll, fout_vpll);
-
 	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
 			ARRAY_SIZE(exynos4_fixed_rate_clks));
 	samsung_clk_register_mux(exynos4_mux_clks,
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 6f767c5..df3628c 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -17,11 +17,22 @@
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
+#define APLL_LOCK		0x0
+#define APLL_CON0		0x100
 #define SRC_CPU			0x200
 #define DIV_CPU0		0x500
+#define MPLL_LOCK		0x4000
+#define MPLL_CON0		0x4100
 #define SRC_CORE1		0x4204
+#define CPLL_LOCK		0x10020
+#define EPLL_LOCK		0x10030
+#define VPLL_LOCK		0x10040
+#define GPLL_LOCK		0x10050
+#define CPLL_CON0		0x10120
+#define EPLL_CON0		0x10130
+#define VPLL_CON0		0x10140
+#define GPLL_CON0		0x10150
 #define SRC_TOP0		0x10210
 #define SRC_TOP2		0x10218
 #define SRC_GSCL		0x10220
@@ -59,9 +70,18 @@
 #define GATE_IP_FSYS		0x10944
 #define GATE_IP_PERIC		0x10950
 #define GATE_IP_PERIS		0x10960
+#define BPLL_LOCK		0x20010
+#define BPLL_CON0		0x20110
 #define SRC_CDREX		0x20200
 #define PLL_DIV2_SEL		0x20a24
 #define GATE_IP_DISP1		0x10928
+#define GATE_IP_ACP		0x10000
+
+/* list of PLLs to be registered */
+enum exynos5250_plls {
+	apll, mpll, cpll, epll, vpll, gpll, bpll,
+	nr_plls			/* number of PLLs */
+};
 
 /*
  * Let each supported clock get a unique id. This id is used to lookup the clock
@@ -79,7 +99,8 @@ enum exynos5250_clks {
 	none,
 
 	/* core clocks */
-	fin_pll,
+	fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll,
+	fout_epll, fout_vpll,
 
 	/* gate for special clocks (sclk) */
 	sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
@@ -87,7 +108,7 @@ enum exynos5250_clks {
 	sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
 	sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
 	sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
-	div_i2s1, div_i2s2,
+	div_i2s1, div_i2s2, sclk_hdmiphy,
 
 	/* gate clocks */
 	gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
@@ -99,7 +120,10 @@ enum exynos5250_clks {
 	spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
 	hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
 	tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
-	wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
+	wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+
+	/* mux clocks */
+	mout_hdmi = 1024,
 
 	nr_clks,
 };
@@ -152,6 +176,7 @@ static __initdata unsigned long exynos5250_clk_regs[] = {
 	SRC_CDREX,
 	PLL_DIV2_SEL,
 	GATE_IP_DISP1,
+	GATE_IP_ACP,
 };
 
 /* list of all parent clock list */
@@ -191,31 +216,34 @@ PNAME(mout_spdif_p)	= { "sclk_audio0", "sclk_audio1", "sclk_audio2",
 				"spdif_extclk" };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
 	FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
-	FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
+static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
+	FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
 	FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
 	FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
 	FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
 };
 
-struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
 	FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
 	FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
 };
 
-struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
+static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	MUX_A(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, "mout_apll"),
 	MUX_A(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
 	MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
 	MUX_A(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"),
 	MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
 	MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
-	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
 	MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
 	MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
 	MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
@@ -232,7 +260,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
 	MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
 	MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
-	MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
+	MUX(mout_hdmi, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
 	MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
 	MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
 	MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
@@ -254,7 +282,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
 };
 
-struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
 	DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
 	DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
 	DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3),
@@ -314,7 +342,7 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = {
 			DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
 };
 
-struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
 	GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0),
 	GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0),
 	GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0),
@@ -463,6 +491,47 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
 	GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
 	GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
 	GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
+	GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+};
+
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+	/* sorted in descending order */
+	/* PLL_36XX_RATE(rate, m, p, s, k) */
+	PLL_36XX_RATE(266000000, 266, 3, 3, 0),
+	/* Not in UM, but need for eDP on snow */
+	PLL_36XX_RATE(70500000, 94, 2, 4, 0),
+	{ },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+	/* sorted in descending order */
+	/* PLL_36XX_RATE(rate, m, p, s, k) */
+	PLL_36XX_RATE(192000000, 64, 2, 2, 0),
+	PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+	PLL_36XX_RATE(180000000, 90, 3, 2, 0),
+	PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
+	PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
+	PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
+	PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
+	PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+	{ },
+};
+
+struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
+	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+		APLL_CON0, "fout_apll", NULL),
+	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+		MPLL_CON0, "fout_mpll", NULL),
+	[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
+		BPLL_CON0, NULL),
+	[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
+		GPLL_CON0, NULL),
+	[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
+		CPLL_CON0, NULL),
+	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+		EPLL_CON0, NULL),
+	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc",
+		VPLL_LOCK, VPLL_CON0, NULL),
 };
 
 static __initdata struct of_device_id ext_clk_match[] = {
@@ -471,10 +540,11 @@ static __initdata struct of_device_id ext_clk_match[] = {
 };
 
 /* register exynox5250 clocks */
-void __init exynos5250_clk_init(struct device_node *np)
+static void __init exynos5250_clk_init(struct device_node *np)
 {
 	void __iomem *reg_base;
-	struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
+	struct clk *vpllsrc;
+	unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
 	if (np) {
 		reg_base = of_iomap(np, 0);
@@ -490,22 +560,23 @@ void __init exynos5250_clk_init(struct device_node *np)
 	samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
 			ext_clk_match);
+	samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+				ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+	fin_pll_rate = _get_rate("fin_pll");
+
+	if (fin_pll_rate == 24 * MHZ)
+		exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+	vpllsrc = __clk_lookup("mout_vpllsrc");
+	if (vpllsrc)
+		mout_vpllsrc_rate = clk_get_rate(vpllsrc);
 
-	apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-			reg_base + 0x100);
-	mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-			reg_base + 0x4100);
-	bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
-			reg_base + 0x20110);
-	gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
-			reg_base + 0x10150);
-	cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
-			reg_base + 0x10120);
-	epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-			reg_base + 0x10130);
-	vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
-			reg_base + 0x10140);
+	if (mout_vpllsrc_rate == 24 * MHZ)
+		exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
 
+	samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
+					reg_base);
 	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_clks));
 	samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 68a96cb..ca352695 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -17,13 +17,30 @@
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
+#define APLL_LOCK		0x0
+#define APLL_CON0		0x100
 #define SRC_CPU			0x200
 #define DIV_CPU0		0x500
 #define DIV_CPU1		0x504
 #define GATE_BUS_CPU		0x700
 #define GATE_SCLK_CPU		0x800
+#define CPLL_LOCK		0x10020
+#define DPLL_LOCK		0x10030
+#define EPLL_LOCK		0x10040
+#define RPLL_LOCK		0x10050
+#define IPLL_LOCK		0x10060
+#define SPLL_LOCK		0x10070
+#define VPLL_LOCK		0x10070
+#define MPLL_LOCK		0x10090
+#define CPLL_CON0		0x10120
+#define DPLL_CON0		0x10128
+#define EPLL_CON0		0x10130
+#define RPLL_CON0		0x10140
+#define IPLL_CON0		0x10150
+#define SPLL_CON0		0x10160
+#define VPLL_CON0		0x10170
+#define MPLL_CON0		0x10180
 #define SRC_TOP0		0x10200
 #define SRC_TOP1		0x10204
 #define SRC_TOP2		0x10208
@@ -75,15 +92,27 @@
 #define GATE_TOP_SCLK_MAU	0x1083c
 #define GATE_TOP_SCLK_FSYS	0x10840
 #define GATE_TOP_SCLK_PERIC	0x10850
+#define BPLL_LOCK		0x20010
+#define BPLL_CON0		0x20110
 #define SRC_CDREX		0x20200
+#define KPLL_LOCK		0x28000
+#define KPLL_CON0		0x28100
 #define SRC_KFC			0x28200
 #define DIV_KFC0		0x28500
 
+/* list of PLLs */
+enum exynos5420_plls {
+	apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll,
+	bpll, kpll,
+	nr_plls			/* number of PLLs */
+};
+
 enum exynos5420_clks {
 	none,
 
 	/* core clocks */
-	fin_pll,
+	fin_pll,  fout_apll, fout_cpll, fout_dpll, fout_epll, fout_rpll,
+	fout_ipll, fout_spll, fout_vpll, fout_mpll, fout_bpll, fout_kpll,
 
 	/* gate for special clocks (sclk) */
 	sclk_uart0 = 128, sclk_uart1, sclk_uart2, sclk_uart3, sclk_mmc0,
@@ -262,12 +291,12 @@ PNAME(maudio0_p)	= { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll",
 			  "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = {
 	FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
 	FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
 	FRATE(none, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000),
 	FRATE(none, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000),
@@ -275,11 +304,11 @@ struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
 	FRATE(none, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000),
 };
 
-struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = {
+static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = {
 	FFACTOR(none, "sclk_hsic_12m", "fin_pll", 1, 2, 0),
 };
 
-struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(none, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2),
 	MUX(none, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2),
 	MUX(none, "mout_apll", apll_p, SRC_CPU, 0, 1),
@@ -399,7 +428,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(none, "mout_spi2", group2_p, SRC_PERIC1, 28, 3),
 };
 
-struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
 	DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
 	DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
 	DIV(none, "armclk2", "div_arm", DIV_CPU0, 28, 3),
@@ -479,7 +508,7 @@ struct samsung_div_clock exynos5420_div_clks[] __initdata = {
 	DIV(none, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8),
 };
 
-struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
 	/* TODO: Re-verify the CG bits for all the gate clocks */
 	GATE_A(mct, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, "mct"),
 
@@ -698,17 +727,40 @@ struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
 	GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0),
 };
 
+struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
+	[apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+		APLL_CON0, NULL),
+	[cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+		MPLL_CON0, NULL),
+	[dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK,
+		DPLL_CON0, NULL),
+	[epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+		EPLL_CON0, NULL),
+	[rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", RPLL_LOCK,
+		RPLL_CON0, NULL),
+	[ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", IPLL_LOCK,
+		IPLL_CON0, NULL),
+	[spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", SPLL_LOCK,
+		SPLL_CON0, NULL),
+	[vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+		VPLL_CON0, NULL),
+	[mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+		MPLL_CON0, NULL),
+	[bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
+		BPLL_CON0, NULL),
+	[kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", KPLL_LOCK,
+		KPLL_CON0, NULL),
+};
+
 static __initdata struct of_device_id ext_clk_match[] = {
 	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
 	{ },
 };
 
 /* register exynos5420 clocks */
-void __init exynos5420_clk_init(struct device_node *np)
+static void __init exynos5420_clk_init(struct device_node *np)
 {
 	void __iomem *reg_base;
-	struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll;
-	struct clk *rpll, *spll, *vpll;
 
 	if (np) {
 		reg_base = of_iomap(np, 0);
@@ -724,30 +776,8 @@ void __init exynos5420_clk_init(struct device_node *np)
 	samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
 			ext_clk_match);
-
-	apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-			reg_base + 0x100);
-	bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
-			reg_base + 0x20110);
-	cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
-			reg_base + 0x10120);
-	dpll = samsung_clk_register_pll35xx("fout_dpll", "fin_pll",
-			reg_base + 0x10128);
-	epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-			reg_base + 0x10130);
-	ipll = samsung_clk_register_pll35xx("fout_ipll", "fin_pll",
-			reg_base + 0x10150);
-	kpll = samsung_clk_register_pll35xx("fout_kpll", "fin_pll",
-			reg_base + 0x28100);
-	mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-			reg_base + 0x10180);
-	rpll = samsung_clk_register_pll36xx("fout_rpll", "fin_pll",
-			reg_base + 0x10140);
-	spll = samsung_clk_register_pll35xx("fout_spll", "fin_pll",
-			reg_base + 0x10160);
-	vpll = samsung_clk_register_pll35xx("fout_vpll", "fin_pll",
-			reg_base + 0x10170);
-
+	samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
+					reg_base);
 	samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
 			ARRAY_SIZE(exynos5420_fixed_rate_clks));
 	samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index 7d54341..6d043a2 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -41,12 +41,12 @@ PNAME(mout_armclk_p)	= { "cplla", "cpllb" };
 PNAME(mout_spi_p)	= { "div125", "div200" };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
 	FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks */
-struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
 	FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000),
 	FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
 	FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
@@ -55,26 +55,26 @@ struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
 };
 
 /* fixed factor clocks */
-struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
 	FFACTOR(none, "div250", "ppll", 1, 4, 0),
 	FFACTOR(none, "div200", "ppll", 1, 5, 0),
 	FFACTOR(none, "div125", "div250", 1, 2, 0),
 };
 
 /* mux clocks */
-struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
 	MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
 	MUX_A(arm_clk, "arm_clk", mout_armclk_p,
 			CPU_CLK_STATUS, 0, 1, "armclk"),
 };
 
 /* divider clocks */
-struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
 	DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
 };
 
 /* gate clocks */
-struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
 	GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
 	GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
 	GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
@@ -103,7 +103,7 @@ static __initdata struct of_device_id ext_clk_match[] = {
 };
 
 /* register exynos5440 clocks */
-void __init exynos5440_clk_init(struct device_node *np)
+static void __init exynos5440_clk_init(struct device_node *np)
 {
 	void __iomem *reg_base;
 
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 362f12d..f80efb6 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,28 +13,67 @@
 #include "clk.h"
 #include "clk-pll.h"
 
+struct samsung_clk_pll {
+	struct clk_hw		hw;
+	void __iomem		*lock_reg;
+	void __iomem		*con_reg;
+	enum samsung_pll_type	type;
+	unsigned int		rate_count;
+	const struct samsung_pll_rate_table *rate_table;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+				struct samsung_clk_pll *pll, unsigned long rate)
+{
+	const struct samsung_pll_rate_table  *rate_table = pll->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+	}
+
+	return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+			unsigned long drate, unsigned long *prate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	const struct samsung_pll_rate_table *rate_table = pll->rate_table;
+	int i;
+
+	/* Assumming rate_table is in descending order */
+	for (i = 0; i < pll->rate_count; i++) {
+		if (drate >= rate_table[i].rate)
+			return rate_table[i].rate;
+	}
+
+	/* return minimum supported value */
+	return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR	(270)
 
 #define PLL35XX_MDIV_MASK       (0x3FF)
 #define PLL35XX_PDIV_MASK       (0x3F)
 #define PLL35XX_SDIV_MASK       (0x7)
+#define PLL35XX_LOCK_STAT_MASK	(0x1)
 #define PLL35XX_MDIV_SHIFT      (16)
 #define PLL35XX_PDIV_SHIFT      (8)
 #define PLL35XX_SDIV_SHIFT      (0)
-
-struct samsung_clk_pll35xx {
-	struct clk_hw		hw;
-	const void __iomem	*con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
+#define PLL35XX_LOCK_STAT_SHIFT	(29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
 {
-	struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
 	u32 mdiv, pdiv, sdiv, pll_con;
 	u64 fvco = parent_rate;
 
@@ -49,48 +88,80 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 	return (unsigned long)fvco;
 }
 
-static const struct clk_ops samsung_pll35xx_clk_ops = {
-	.recalc_rate = samsung_pll35xx_recalc_rate,
-};
-
-struct clk * __init samsung_clk_register_pll35xx(const char *name,
-			const char *pname, const void __iomem *con_reg)
+static inline bool samsung_pll35xx_mp_change(
+		const struct samsung_pll_rate_table *rate, u32 pll_con)
 {
-	struct samsung_clk_pll35xx *pll;
-	struct clk *clk;
-	struct clk_init_data init;
+	u32 old_mdiv, old_pdiv;
 
-	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-	if (!pll) {
-		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
-		return NULL;
+	old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+	old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	const struct samsung_pll_rate_table *rate;
+	u32 tmp;
+
+	/* Get required rate settings from table */
+	rate = samsung_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
 	}
 
-	init.name = name;
-	init.ops = &samsung_pll35xx_clk_ops;
-	init.flags = CLK_GET_RATE_NOCACHE;
-	init.parent_names = &pname;
-	init.num_parents = 1;
+	tmp = __raw_readl(pll->con_reg);
 
-	pll->hw.init = &init;
-	pll->con_reg = con_reg;
+	if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+		/* If only s change, change just s value only*/
+		tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
+		tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
+		__raw_writel(tmp, pll->con_reg);
 
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk)) {
-		pr_err("%s: failed to register pll clock %s\n", __func__,
-				name);
-		kfree(pll);
+		return 0;
 	}
 
-	if (clk_register_clkdev(clk, name, NULL))
-		pr_err("%s: failed to register lookup for %s", __func__, name);
-
-	return clk;
+	/* Set PLL lock time. */
+	__raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+			pll->lock_reg);
+
+	/* Change PLL PMS values */
+	tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
+			(PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
+			(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
+	tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
+			(rate->pdiv << PLL35XX_PDIV_SHIFT) |
+			(rate->sdiv << PLL35XX_SDIV_SHIFT);
+	__raw_writel(tmp, pll->con_reg);
+
+	/* wait_lock_time */
+	do {
+		cpu_relax();
+		tmp = __raw_readl(pll->con_reg);
+	} while (!(tmp & (PLL35XX_LOCK_STAT_MASK
+				<< PLL35XX_LOCK_STAT_SHIFT)));
+	return 0;
 }
 
+static const struct clk_ops samsung_pll35xx_clk_ops = {
+	.recalc_rate = samsung_pll35xx_recalc_rate,
+	.round_rate = samsung_pll_round_rate,
+	.set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+	.recalc_rate = samsung_pll35xx_recalc_rate,
+};
+
 /*
  * PLL36xx Clock Type
  */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR    (3000)
 
 #define PLL36XX_KDIV_MASK	(0xFFFF)
 #define PLL36XX_MDIV_MASK	(0x1FF)
@@ -99,18 +170,13 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name,
 #define PLL36XX_MDIV_SHIFT	(16)
 #define PLL36XX_PDIV_SHIFT	(8)
 #define PLL36XX_SDIV_SHIFT	(0)
-
-struct samsung_clk_pll36xx {
-	struct clk_hw		hw;
-	const void __iomem	*con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
+#define PLL36XX_KDIV_SHIFT	(0)
+#define PLL36XX_LOCK_STAT_SHIFT	(29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
 {
-	struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
 	u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
 	s16 kdiv;
 	u64 fvco = parent_rate;
@@ -129,45 +195,80 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 	return (unsigned long)fvco;
 }
 
-static const struct clk_ops samsung_pll36xx_clk_ops = {
-	.recalc_rate = samsung_pll36xx_recalc_rate,
-};
-
-struct clk * __init samsung_clk_register_pll36xx(const char *name,
-			const char *pname, const void __iomem *con_reg)
+static inline bool samsung_pll36xx_mpk_change(
+	const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
 {
-	struct samsung_clk_pll36xx *pll;
-	struct clk *clk;
-	struct clk_init_data init;
+	u32 old_mdiv, old_pdiv, old_kdiv;
 
-	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-	if (!pll) {
-		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
-		return NULL;
+	old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+	old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+	old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+		rate->kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long parent_rate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 tmp, pll_con0, pll_con1;
+	const struct samsung_pll_rate_table *rate;
+
+	rate = samsung_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
 	}
 
-	init.name = name;
-	init.ops = &samsung_pll36xx_clk_ops;
-	init.flags = CLK_GET_RATE_NOCACHE;
-	init.parent_names = &pname;
-	init.num_parents = 1;
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);
 
-	pll->hw.init = &init;
-	pll->con_reg = con_reg;
+	if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+		/* If only s change, change just s value only*/
+		pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
+		pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
+		__raw_writel(pll_con0, pll->con_reg);
 
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk)) {
-		pr_err("%s: failed to register pll clock %s\n", __func__,
-				name);
-		kfree(pll);
+		return 0;
 	}
 
-	if (clk_register_clkdev(clk, name, NULL))
-		pr_err("%s: failed to register lookup for %s", __func__, name);
-
-	return clk;
+	/* Set PLL lock time. */
+	__raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+
+	 /* Change PLL PMS values */
+	pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
+			(PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
+			(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
+	pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
+			(rate->pdiv << PLL36XX_PDIV_SHIFT) |
+			(rate->sdiv << PLL36XX_SDIV_SHIFT);
+	__raw_writel(pll_con0, pll->con_reg);
+
+	pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
+	pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
+	__raw_writel(pll_con1, pll->con_reg + 4);
+
+	/* wait_lock_time */
+	do {
+		cpu_relax();
+		tmp = __raw_readl(pll->con_reg);
+	} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
+
+	return 0;
 }
 
+static const struct clk_ops samsung_pll36xx_clk_ops = {
+	.recalc_rate = samsung_pll36xx_recalc_rate,
+	.set_rate = samsung_pll36xx_set_rate,
+	.round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+	.recalc_rate = samsung_pll36xx_recalc_rate,
+};
+
 /*
  * PLL45xx Clock Type
  */
@@ -418,3 +519,93 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
 
 	return clk;
 }
+
+static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
+						void __iomem *base)
+{
+	struct samsung_clk_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+	int ret, len;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("%s: could not allocate pll clk %s\n",
+			__func__, pll_clk->name);
+		return;
+	}
+
+	init.name = pll_clk->name;
+	init.flags = pll_clk->flags;
+	init.parent_names = &pll_clk->parent_name;
+	init.num_parents = 1;
+
+	if (pll_clk->rate_table) {
+		/* find count of rates in rate_table */
+		for (len = 0; pll_clk->rate_table[len].rate != 0; )
+			len++;
+
+		pll->rate_count = len;
+		pll->rate_table = kmemdup(pll_clk->rate_table,
+					pll->rate_count *
+					sizeof(struct samsung_pll_rate_table),
+					GFP_KERNEL);
+		WARN(!pll->rate_table,
+			"%s: could not allocate rate table for %s\n",
+			__func__, pll_clk->name);
+	}
+
+	switch (pll_clk->type) {
+	/* clk_ops for 35xx and 2550 are similar */
+	case pll_35xx:
+	case pll_2550:
+		if (!pll->rate_table)
+			init.ops = &samsung_pll35xx_clk_min_ops;
+		else
+			init.ops = &samsung_pll35xx_clk_ops;
+		break;
+	/* clk_ops for 36xx and 2650 are similar */
+	case pll_36xx:
+	case pll_2650:
+		if (!pll->rate_table)
+			init.ops = &samsung_pll36xx_clk_min_ops;
+		else
+			init.ops = &samsung_pll36xx_clk_ops;
+		break;
+	default:
+		pr_warn("%s: Unknown pll type for pll clk %s\n",
+			__func__, pll_clk->name);
+	}
+
+	pll->hw.init = &init;
+	pll->type = pll_clk->type;
+	pll->lock_reg = base + pll_clk->lock_offset;
+	pll->con_reg = base + pll_clk->con_offset;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s : %ld\n",
+			__func__, pll_clk->name, PTR_ERR(clk));
+		kfree(pll);
+		return;
+	}
+
+	samsung_clk_add_lookup(clk, pll_clk->id);
+
+	if (!pll_clk->alias)
+		return;
+
+	ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
+	if (ret)
+		pr_err("%s: failed to register lookup for %s : %d",
+			__func__, pll_clk->name, ret);
+}
+
+void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
+				unsigned int nr_pll, void __iomem *base)
+{
+	int cnt;
+
+	for (cnt = 0; cnt < nr_pll; cnt++)
+		_samsung_clk_register_pll(&pll_list[cnt], base);
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index f33786e..95ae23d 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -12,6 +12,40 @@
 #ifndef __SAMSUNG_CLK_PLL_H
 #define __SAMSUNG_CLK_PLL_H
 
+enum samsung_pll_type {
+	pll_35xx,
+	pll_36xx,
+	pll_2550,
+	pll_2650,
+};
+
+#define PLL_35XX_RATE(_rate, _m, _p, _s)			\
+	{							\
+		.rate	=	(_rate),				\
+		.mdiv	=	(_m),				\
+		.pdiv	=	(_p),				\
+		.sdiv	=	(_s),				\
+	}
+
+#define PLL_36XX_RATE(_rate, _m, _p, _s, _k)			\
+	{							\
+		.rate	=	(_rate),				\
+		.mdiv	=	(_m),				\
+		.pdiv	=	(_p),				\
+		.sdiv	=	(_s),				\
+		.kdiv	=	(_k),				\
+	}
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+
+struct samsung_pll_rate_table {
+	unsigned int rate;
+	unsigned int pdiv;
+	unsigned int mdiv;
+	unsigned int sdiv;
+	unsigned int kdiv;
+};
+
 enum pll45xx_type {
 	pll_4500,
 	pll_4502,
@@ -24,10 +58,6 @@ enum pll46xx_type {
 	pll_4650c,
 };
 
-extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
-			const char *pname, const void __iomem *con_reg);
-extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
-			const char *pname, const void __iomem *con_reg);
 extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
 			const char *pname, const void __iomem *con_reg,
 			enum pll45xx_type type);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 2f7dba2..e7dfccb 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -19,6 +19,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include "clk-pll.h"
 
 /**
  * struct samsung_clock_alias: information about mux clock
@@ -39,6 +40,8 @@ struct samsung_clock_alias {
 		.alias		= a,				\
 	}
 
+#define MHZ (1000 * 1000)
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.
@@ -261,6 +264,54 @@ struct samsung_clk_reg_dump {
 	u32	value;
 };
 
+/**
+ * struct samsung_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @lock_offset: offset of the register for locking the PLL.
+ * @type: Type of PLL to be registered.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_pll_clock {
+	unsigned int		id;
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	int			con_offset;
+	int			lock_offset;
+	enum samsung_pll_type	type;
+	const struct samsung_pll_rate_table *rate_table;
+	const char              *alias;
+};
+
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con,	\
+		_rtable, _alias)					\
+	{								\
+		.id		= _id,					\
+		.type		= _typ,					\
+		.dev_name	= _dname,				\
+		.name		= _name,				\
+		.parent_name	= _pname,				\
+		.flags		= CLK_GET_RATE_NOCACHE,			\
+		.con_offset	= _con,					\
+		.lock_offset	= _lock,				\
+		.rate_table	= _rtable,				\
+		.alias		= _alias,				\
+	}
+
+#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable)	\
+	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
+		_lock, _con, _rtable, _name)
+
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
+	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
+		_lock, _con, _rtable, _alias)
+
 extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
 		unsigned long nr_clks, unsigned long *rdump,
 		unsigned long nr_rdump, unsigned long *soc_rdump,
@@ -284,6 +335,8 @@ extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
 		unsigned int nr_clk);
 extern void __init samsung_clk_register_gate(
 		struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
+		unsigned int nr_clk, void __iomem *base);
 
 extern unsigned long _get_rate(const char *clk_name);
 
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index b6015cb..f74ed19 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -290,6 +290,12 @@
 /* Tegra CPU clock and reset control regs */
 #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
 
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+	u32 clk_csite_src;
+} tegra114_cpu_clk_sctx;
+#endif
+
 static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
 
 static void __iomem *clk_base;
@@ -2142,9 +2148,29 @@ static void tegra114_disable_cpu_clock(u32 cpu)
 	/* flow controller would take care in the power sequence. */
 }
 
+#ifdef CONFIG_PM_SLEEP
+static void tegra114_cpu_clock_suspend(void)
+{
+	/* switch coresite to clk_m, save off original source */
+	tegra114_cpu_clk_sctx.clk_csite_src =
+				readl(clk_base + CLK_SOURCE_CSITE);
+	writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+}
+
+static void tegra114_cpu_clock_resume(void)
+{
+	writel(tegra114_cpu_clk_sctx.clk_csite_src,
+					clk_base + CLK_SOURCE_CSITE);
+}
+#endif
+
 static struct tegra_cpu_car_ops tegra114_cpu_car_ops = {
 	.wait_for_reset	= tegra114_wait_cpu_in_reset,
 	.disable_clock	= tegra114_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+	.suspend	= tegra114_cpu_clock_suspend,
+	.resume		= tegra114_cpu_clock_resume,
+#endif
 };
 
 static const struct of_device_id pmc_match[] __initconst = {
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8b00c5c..704d6d3 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ORION_TIMER)	+= time-orion.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
 obj-$(CONFIG_ARCH_MARCO)	+= timer-marco.o
+obj-$(CONFIG_ARCH_MOXART)	+= moxart_timer.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o
 obj-$(CONFIG_ARCH_PRIMA2)	+= timer-prima2.o
 obj-$(CONFIG_SUN4I_TIMER)	+= sun4i_timer.o
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index 4cbe28c..b2bb3a4b 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -21,7 +21,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
-#include <linux/clk-provider.h>
+#include <linux/sched_clock.h>
 
 /*
  * This driver configures the 2 16-bit count-up timers as follows:
@@ -95,6 +95,8 @@ struct ttc_timer_clockevent {
 #define to_ttc_timer_clkevent(x) \
 		container_of(x, struct ttc_timer_clockevent, ce)
 
+static void __iomem *ttc_sched_clock_val_reg;
+
 /**
  * ttc_set_interval - Set the timer interval value
  *
@@ -156,6 +158,11 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs)
 				TTC_COUNT_VAL_OFFSET);
 }
 
+static u32 notrace ttc_sched_clock_read(void)
+{
+	return __raw_readl(ttc_sched_clock_val_reg);
+}
+
 /**
  * ttc_set_next_event - Sets the time interval for next event
  *
@@ -297,6 +304,10 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
 		kfree(ttccs);
 		return;
 	}
+
+	ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
+	setup_sched_clock(ttc_sched_clock_read, 16,
+			clk_get_rate(ttccs->ttc.clk) / PRESCALE);
 }
 
 static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
index 4329a29..b9c81b7 100644
--- a/drivers/clocksource/em_sti.c
+++ b/drivers/clocksource/em_sti.c
@@ -315,68 +315,47 @@ static int em_sti_probe(struct platform_device *pdev)
 {
 	struct em_sti_priv *p;
 	struct resource *res;
-	int irq, ret;
+	int irq;
 
-	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
 	if (p == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
-		ret = -ENOMEM;
-		goto err0;
+		return -ENOMEM;
 	}
 
 	p->pdev = pdev;
 	platform_set_drvdata(pdev, p);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get I/O memory\n");
-		ret = -EINVAL;
-		goto err0;
-	}
-
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "failed to get irq\n");
-		ret = -EINVAL;
-		goto err0;
+		return -EINVAL;
 	}
 
 	/* map memory, let base point to the STI instance */
-	p->base = ioremap_nocache(res->start, resource_size(res));
-	if (p->base == NULL) {
-		dev_err(&pdev->dev, "failed to remap I/O memory\n");
-		ret = -ENXIO;
-		goto err0;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	p->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(p->base))
+		return PTR_ERR(p->base);
 
 	/* get hold of clock */
-	p->clk = clk_get(&pdev->dev, "sclk");
+	p->clk = devm_clk_get(&pdev->dev, "sclk");
 	if (IS_ERR(p->clk)) {
 		dev_err(&pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(p->clk);
-		goto err1;
+		return PTR_ERR(p->clk);
 	}
 
-	if (request_irq(irq, em_sti_interrupt,
-			IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			dev_name(&pdev->dev), p)) {
+	if (devm_request_irq(&pdev->dev, irq, em_sti_interrupt,
+			     IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			     dev_name(&pdev->dev), p)) {
 		dev_err(&pdev->dev, "failed to request low IRQ\n");
-		ret = -ENOENT;
-		goto err2;
+		return -ENOENT;
 	}
 
 	raw_spin_lock_init(&p->lock);
 	em_sti_register_clockevent(p);
 	em_sti_register_clocksource(p);
 	return 0;
-
-err2:
-	clk_put(p->clk);
-err1:
-	iounmap(p->base);
-err0:
-	kfree(p);
-	return ret;
 }
 
 static int em_sti_remove(struct platform_device *pdev)
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index b2bbc41..5b34768 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
+#include <linux/cpu.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/percpu.h>
@@ -24,7 +25,6 @@
 #include <linux/of_address.h>
 #include <linux/clocksource.h>
 
-#include <asm/localtimer.h>
 #include <asm/mach/time.h>
 
 #define EXYNOS4_MCTREG(x)		(x)
@@ -80,7 +80,7 @@ static unsigned int mct_int_type;
 static int mct_irqs[MCT_NR_IRQS];
 
 struct mct_clock_event_device {
-	struct clock_event_device *evt;
+	struct clock_event_device evt;
 	unsigned long base;
 	char name[10];
 };
@@ -295,8 +295,6 @@ static void exynos4_clockevent_init(void)
 	setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
 }
 
-#ifdef CONFIG_LOCAL_TIMERS
-
 static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
 
 /* Clock event handling */
@@ -369,7 +367,7 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
 
 static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 {
-	struct clock_event_device *evt = mevt->evt;
+	struct clock_event_device *evt = &mevt->evt;
 
 	/*
 	 * This is for supporting oneshot mode.
@@ -391,7 +389,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
 {
 	struct mct_clock_event_device *mevt = dev_id;
-	struct clock_event_device *evt = mevt->evt;
+	struct clock_event_device *evt = &mevt->evt;
 
 	exynos4_mct_tick_clear(mevt);
 
@@ -405,8 +403,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
 	struct mct_clock_event_device *mevt;
 	unsigned int cpu = smp_processor_id();
 
-	mevt = this_cpu_ptr(&percpu_mct_tick);
-	mevt->evt = evt;
+	mevt = container_of(evt, struct mct_clock_event_device, evt);
 
 	mevt->base = EXYNOS4_MCT_L_BASE(cpu);
 	sprintf(mevt->name, "mct_tick%d", cpu);
@@ -448,14 +445,37 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
 		disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 }
 
-static struct local_timer_ops exynos4_mct_tick_ops = {
-	.setup	= exynos4_local_timer_setup,
-	.stop	= exynos4_local_timer_stop,
+static int exynos4_mct_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	struct mct_clock_event_device *mevt;
+
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		mevt = this_cpu_ptr(&percpu_mct_tick);
+		exynos4_local_timer_setup(&mevt->evt);
+		break;
+	case CPU_DYING:
+		mevt = this_cpu_ptr(&percpu_mct_tick);
+		exynos4_local_timer_stop(&mevt->evt);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block exynos4_mct_cpu_nb = {
+	.notifier_call = exynos4_mct_cpu_notify,
 };
-#endif /* CONFIG_LOCAL_TIMERS */
 
 static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
 {
+	int err;
+	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
 	struct clk *mct_clk, *tick_clk;
 
 	tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
@@ -473,9 +493,7 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
 	if (!reg_base)
 		panic("%s: unable to ioremap mct address space\n", __func__);
 
-#ifdef CONFIG_LOCAL_TIMERS
 	if (mct_int_type == MCT_INT_PPI) {
-		int err;
 
 		err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
 					 exynos4_mct_tick_isr, "MCT",
@@ -484,8 +502,16 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
 		     mct_irqs[MCT_L0_IRQ], err);
 	}
 
-	local_timer_register(&exynos4_mct_tick_ops);
-#endif /* CONFIG_LOCAL_TIMERS */
+	err = register_cpu_notifier(&exynos4_mct_cpu_nb);
+	if (err)
+		goto out_irq;
+
+	/* Immediately configure the timer on the boot CPU */
+	exynos4_local_timer_setup(&mevt->evt);
+	return;
+
+out_irq:
+	free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
 }
 
 void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1)
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
new file mode 100644
index 0000000..08a5943
--- /dev/null
+++ b/drivers/clocksource/moxart_timer.c
@@ -0,0 +1,164 @@
+/*
+ * MOXA ART SoCs timer handling.
+ *
+ * Copyright (C) 2013 Jonas Jensen
+ *
+ * Jonas Jensen <jonas.jensen@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/clocksource.h>
+
+#define TIMER1_BASE		0x00
+#define TIMER2_BASE		0x10
+#define TIMER3_BASE		0x20
+
+#define REG_COUNT		0x0 /* writable */
+#define REG_LOAD		0x4
+#define REG_MATCH1		0x8
+#define REG_MATCH2		0xC
+
+#define TIMER_CR		0x30
+#define TIMER_INTR_STATE	0x34
+#define TIMER_INTR_MASK		0x38
+
+/*
+ * TIMER_CR flags:
+ *
+ * TIMEREG_CR_*_CLOCK	0: PCLK, 1: EXT1CLK
+ * TIMEREG_CR_*_INT	overflow interrupt enable bit
+ */
+#define TIMEREG_CR_1_ENABLE	BIT(0)
+#define TIMEREG_CR_1_CLOCK	BIT(1)
+#define TIMEREG_CR_1_INT	BIT(2)
+#define TIMEREG_CR_2_ENABLE	BIT(3)
+#define TIMEREG_CR_2_CLOCK	BIT(4)
+#define TIMEREG_CR_2_INT	BIT(5)
+#define TIMEREG_CR_3_ENABLE	BIT(6)
+#define TIMEREG_CR_3_CLOCK	BIT(7)
+#define TIMEREG_CR_3_INT	BIT(8)
+#define TIMEREG_CR_COUNT_UP	BIT(9)
+
+#define TIMER1_ENABLE		(TIMEREG_CR_2_ENABLE | TIMEREG_CR_1_ENABLE)
+#define TIMER1_DISABLE		(TIMEREG_CR_2_ENABLE)
+
+static void __iomem *base;
+static unsigned int clock_count_per_tick;
+
+static void moxart_clkevt_mode(enum clock_event_mode mode,
+			       struct clock_event_device *clk)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_ONESHOT:
+		writel(TIMER1_DISABLE, base + TIMER_CR);
+		writel(~0, base + TIMER1_BASE + REG_LOAD);
+		break;
+	case CLOCK_EVT_MODE_PERIODIC:
+		writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
+		writel(TIMER1_ENABLE, base + TIMER_CR);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		writel(TIMER1_DISABLE, base + TIMER_CR);
+		break;
+	}
+}
+
+static int moxart_clkevt_next_event(unsigned long cycles,
+				    struct clock_event_device *unused)
+{
+	u32 u;
+
+	writel(TIMER1_DISABLE, base + TIMER_CR);
+
+	u = readl(base + TIMER1_BASE + REG_COUNT) - cycles;
+	writel(u, base + TIMER1_BASE + REG_MATCH1);
+
+	writel(TIMER1_ENABLE, base + TIMER_CR);
+
+	return 0;
+}
+
+static struct clock_event_device moxart_clockevent = {
+	.name		= "moxart_timer",
+	.rating		= 200,
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= moxart_clkevt_mode,
+	.set_next_event	= moxart_clkevt_next_event,
+};
+
+static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction moxart_timer_irq = {
+	.name		= "moxart-timer",
+	.flags		= IRQF_TIMER,
+	.handler	= moxart_timer_interrupt,
+	.dev_id		= &moxart_clockevent,
+};
+
+static void __init moxart_timer_init(struct device_node *node)
+{
+	int ret, irq;
+	unsigned long pclk;
+	struct clk *clk;
+
+	base = of_iomap(node, 0);
+	if (!base)
+		panic("%s: of_iomap failed\n", node->full_name);
+
+	irq = irq_of_parse_and_map(node, 0);
+	if (irq <= 0)
+		panic("%s: irq_of_parse_and_map failed\n", node->full_name);
+
+	ret = setup_irq(irq, &moxart_timer_irq);
+	if (ret)
+		panic("%s: setup_irq failed\n", node->full_name);
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk))
+		panic("%s: of_clk_get failed\n", node->full_name);
+
+	pclk = clk_get_rate(clk);
+
+	if (clocksource_mmio_init(base + TIMER2_BASE + REG_COUNT,
+				  "moxart_timer", pclk, 200, 32,
+				  clocksource_mmio_readl_down))
+		panic("%s: clocksource_mmio_init failed\n", node->full_name);
+
+	clock_count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
+
+	writel(~0, base + TIMER2_BASE + REG_LOAD);
+	writel(TIMEREG_CR_2_ENABLE, base + TIMER_CR);
+
+	moxart_clockevent.cpumask = cpumask_of(0);
+	moxart_clockevent.irq = irq;
+
+	/*
+	 * documentation is not publicly available:
+	 * min_delta / max_delta obtained by trial-and-error,
+	 * max_delta 0xfffffffe should be ok because count
+	 * register size is u32
+	 */
+	clockevents_config_and_register(&moxart_clockevent, pclk,
+					0x4, 0xfffffffe);
+}
+CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 08d0c41..0965e98 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -37,6 +37,7 @@
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
+	void __iomem *mapbase_str;
 	struct clk *clk;
 	unsigned long width; /* 16 or 32 bit version of hardware block */
 	unsigned long overflow_bit;
@@ -79,6 +80,12 @@ struct sh_cmt_priv {
  * CMCSR 0xffca0060 16-bit
  * CMCNT 0xffca0064 32-bit
  * CMCOR 0xffca0068 32-bit
+ *
+ * "32-bit counter and 32-bit control" as found on r8a73a4 and r8a7790:
+ * CMSTR 0xffca0500 32-bit
+ * CMCSR 0xffca0510 32-bit
+ * CMCNT 0xffca0514 32-bit
+ * CMCOR 0xffca0518 32-bit
  */
 
 static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
@@ -109,9 +116,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-
-	return p->read_control(p->mapbase - cfg->channel_offset, 0);
+	return p->read_control(p->mapbase_str, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
@@ -127,9 +132,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
 static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-
-	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
+	p->write_control(p->mapbase_str, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
@@ -676,7 +679,7 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
 static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	struct resource *res;
+	struct resource *res, *res2;
 	int irq, ret;
 	ret = -ENXIO;
 
@@ -694,6 +697,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
+	/* optional resource for the shared timer start/stop register */
+	res2 = platform_get_resource(p->pdev, IORESOURCE_MEM, 1);
+
 	irq = platform_get_irq(p->pdev, 0);
 	if (irq < 0) {
 		dev_err(&p->pdev->dev, "failed to get irq\n");
@@ -707,6 +713,15 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
+	/* map second resource for CMSTR */
+	p->mapbase_str = ioremap_nocache(res2 ? res2->start :
+					 res->start - cfg->channel_offset,
+					 res2 ? resource_size(res2) : 2);
+	if (p->mapbase_str == NULL) {
+		dev_err(&p->pdev->dev, "failed to remap I/O second memory\n");
+		goto err1;
+	}
+
 	/* request irq using setup_irq() (too early for request_irq()) */
 	p->irqaction.name = dev_name(&p->pdev->dev);
 	p->irqaction.handler = sh_cmt_interrupt;
@@ -719,11 +734,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 	if (IS_ERR(p->clk)) {
 		dev_err(&p->pdev->dev, "cannot get clock\n");
 		ret = PTR_ERR(p->clk);
-		goto err1;
+		goto err2;
 	}
 
-	p->read_control = sh_cmt_read16;
-	p->write_control = sh_cmt_write16;
+	if (res2 && (resource_size(res2) == 4)) {
+		/* assume both CMSTR and CMCSR to be 32-bit */
+		p->read_control = sh_cmt_read32;
+		p->write_control = sh_cmt_write32;
+	} else {
+		p->read_control = sh_cmt_read16;
+		p->write_control = sh_cmt_write16;
+	}
 
 	if (resource_size(res) == 6) {
 		p->width = 16;
@@ -752,22 +773,23 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 			      cfg->clocksource_rating);
 	if (ret) {
 		dev_err(&p->pdev->dev, "registration failed\n");
-		goto err2;
+		goto err3;
 	}
 	p->cs_enabled = false;
 
 	ret = setup_irq(irq, &p->irqaction);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
-		goto err2;
+		goto err3;
 	}
 
 	platform_set_drvdata(pdev, p);
 
 	return 0;
-err2:
+err3:
 	clk_put(p->clk);
-
+err2:
+	iounmap(p->mapbase_str);
 err1:
 	iounmap(p->mapbase);
 err0:
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
index d4674e7..8ead025 100644
--- a/drivers/clocksource/sun4i_timer.c
+++ b/drivers/clocksource/sun4i_timer.c
@@ -19,42 +19,83 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqreturn.h>
+#include <linux/sched_clock.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
 #define TIMER_IRQ_EN_REG	0x00
-#define TIMER_IRQ_EN(val)		(1 << val)
+#define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
 #define TIMER_CTL_REG(val)	(0x10 * val + 0x10)
-#define TIMER_CTL_ENABLE		(1 << 0)
-#define TIMER_CTL_AUTORELOAD		(1 << 1)
-#define TIMER_CTL_ONESHOT		(1 << 7)
-#define TIMER_INTVAL_REG(val)	(0x10 * val + 0x14)
-#define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
-
-#define TIMER_SCAL		16
+#define TIMER_CTL_ENABLE		BIT(0)
+#define TIMER_CTL_RELOAD		BIT(1)
+#define TIMER_CTL_CLK_SRC(val)		(((val) & 0x3) << 2)
+#define TIMER_CTL_CLK_SRC_OSC24M		(1)
+#define TIMER_CTL_CLK_PRES(val)		(((val) & 0x7) << 4)
+#define TIMER_CTL_ONESHOT		BIT(7)
+#define TIMER_INTVAL_REG(val)	(0x10 * (val) + 0x14)
+#define TIMER_CNTVAL_REG(val)	(0x10 * (val) + 0x18)
 
 static void __iomem *timer_base;
+static u32 ticks_per_jiffy;
+
+/*
+ * When we disable a timer, we need to wait at least for 2 cycles of
+ * the timer source clock. We will use for that the clocksource timer
+ * that is already setup and runs at the same frequency than the other
+ * timers, and we never will be disabled.
+ */
+static void sun4i_clkevt_sync(void)
+{
+	u32 old = readl(timer_base + TIMER_CNTVAL_REG(1));
+
+	while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < 3)
+		cpu_relax();
+}
+
+static void sun4i_clkevt_time_stop(u8 timer)
+{
+	u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+	writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer));
+	sun4i_clkevt_sync();
+}
+
+static void sun4i_clkevt_time_setup(u8 timer, unsigned long delay)
+{
+	writel(delay, timer_base + TIMER_INTVAL_REG(timer));
+}
+
+static void sun4i_clkevt_time_start(u8 timer, bool periodic)
+{
+	u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+
+	if (periodic)
+		val &= ~TIMER_CTL_ONESHOT;
+	else
+		val |= TIMER_CTL_ONESHOT;
+
+	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
+	       timer_base + TIMER_CTL_REG(timer));
+}
 
 static void sun4i_clkevt_mode(enum clock_event_mode mode,
 			      struct clock_event_device *clk)
 {
-	u32 u = readl(timer_base + TIMER_CTL_REG(0));
-
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		u &= ~(TIMER_CTL_ONESHOT);
-		writel(u | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
+		sun4i_clkevt_time_stop(0);
+		sun4i_clkevt_time_setup(0, ticks_per_jiffy);
+		sun4i_clkevt_time_start(0, true);
 		break;
-
 	case CLOCK_EVT_MODE_ONESHOT:
-		writel(u | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(0));
+		sun4i_clkevt_time_stop(0);
+		sun4i_clkevt_time_start(0, false);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	default:
-		writel(u & ~(TIMER_CTL_ENABLE), timer_base + TIMER_CTL_REG(0));
+		sun4i_clkevt_time_stop(0);
 		break;
 	}
 }
@@ -62,10 +103,9 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode,
 static int sun4i_clkevt_next_event(unsigned long evt,
 				   struct clock_event_device *unused)
 {
-	u32 u = readl(timer_base + TIMER_CTL_REG(0));
-	writel(evt, timer_base + TIMER_CNTVAL_REG(0));
-	writel(u | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD,
-	       timer_base + TIMER_CTL_REG(0));
+	sun4i_clkevt_time_stop(0);
+	sun4i_clkevt_time_setup(0, evt);
+	sun4i_clkevt_time_start(0, false);
 
 	return 0;
 }
@@ -96,6 +136,11 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
+static u32 sun4i_timer_sched_read(void)
+{
+	return ~readl(timer_base + TIMER_CNTVAL_REG(1));
+}
+
 static void __init sun4i_timer_init(struct device_node *node)
 {
 	unsigned long rate = 0;
@@ -114,22 +159,23 @@ static void __init sun4i_timer_init(struct device_node *node)
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk))
 		panic("Can't get timer clock");
+	clk_prepare_enable(clk);
 
 	rate = clk_get_rate(clk);
 
-	writel(rate / (TIMER_SCAL * HZ),
-	       timer_base + TIMER_INTVAL_REG(0));
+	writel(~0, timer_base + TIMER_INTVAL_REG(1));
+	writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD |
+	       TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
+	       timer_base + TIMER_CTL_REG(1));
+
+	setup_sched_clock(sun4i_timer_sched_read, 32, rate);
+	clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name,
+			      rate, 300, 32, clocksource_mmio_readl_down);
 
-	/* set clock source to HOSC, 16 pre-division */
-	val = readl(timer_base + TIMER_CTL_REG(0));
-	val &= ~(0x07 << 4);
-	val &= ~(0x03 << 2);
-	val |= (4 << 4) | (1 << 2);
-	writel(val, timer_base + TIMER_CTL_REG(0));
+	ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
 
-	/* set mode to auto reload */
-	val = readl(timer_base + TIMER_CTL_REG(0));
-	writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0));
+	writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
+	       timer_base + TIMER_CTL_REG(0));
 
 	ret = setup_irq(irq, &sun4i_timer_irq);
 	if (ret)
@@ -141,8 +187,8 @@ static void __init sun4i_timer_init(struct device_node *node)
 
 	sun4i_clockevent.cpumask = cpumask_of(0);
 
-	clockevents_config_and_register(&sun4i_clockevent, rate / TIMER_SCAL,
-					0x1, 0xff);
+	clockevents_config_and_register(&sun4i_clockevent, rate, 0x1,
+					0xffffffff);
 }
 CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer",
 		       sun4i_timer_init);
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 1b04b7e..847cab6 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/timer.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
@@ -28,9 +29,9 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/sched_clock.h>
-
-#include <asm/localtimer.h>
 #include <linux/percpu.h>
+#include <linux/time-armada-370-xp.h>
+
 /*
  * Timer block registers.
  */
@@ -69,7 +70,7 @@ static bool timer25Mhz = true;
  */
 static u32 ticks_per_jiffy;
 
-static struct clock_event_device __percpu **percpu_armada_370_xp_evt;
+static struct clock_event_device __percpu *armada_370_xp_evt;
 
 static u32 notrace armada_370_xp_read_sched_clock(void)
 {
@@ -142,21 +143,14 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode,
 	}
 }
 
-static struct clock_event_device armada_370_xp_clkevt = {
-	.name		= "armada_370_xp_per_cpu_tick",
-	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
-	.shift		= 32,
-	.rating		= 300,
-	.set_next_event	= armada_370_xp_clkevt_next_event,
-	.set_mode	= armada_370_xp_clkevt_mode,
-};
+static int armada_370_xp_clkevt_irq;
 
 static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
 {
 	/*
 	 * ACK timer interrupt and call event handler.
 	 */
-	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+	struct clock_event_device *evt = dev_id;
 
 	writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
 	evt->event_handler(evt);
@@ -172,42 +166,55 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt)
 	u32 u;
 	int cpu = smp_processor_id();
 
-	/* Use existing clock_event for cpu 0 */
-	if (!smp_processor_id())
-		return 0;
-
 	u = readl(local_base + TIMER_CTRL_OFF);
 	if (timer25Mhz)
 		writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
 	else
 		writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
 
-	evt->name		= armada_370_xp_clkevt.name;
-	evt->irq		= armada_370_xp_clkevt.irq;
-	evt->features		= armada_370_xp_clkevt.features;
-	evt->shift		= armada_370_xp_clkevt.shift;
-	evt->rating		= armada_370_xp_clkevt.rating,
+	evt->name		= "armada_370_xp_per_cpu_tick",
+	evt->features		= CLOCK_EVT_FEAT_ONESHOT |
+				  CLOCK_EVT_FEAT_PERIODIC;
+	evt->shift		= 32,
+	evt->rating		= 300,
 	evt->set_next_event	= armada_370_xp_clkevt_next_event,
 	evt->set_mode		= armada_370_xp_clkevt_mode,
+	evt->irq		= armada_370_xp_clkevt_irq;
 	evt->cpumask		= cpumask_of(cpu);
 
-	*__this_cpu_ptr(percpu_armada_370_xp_evt) = evt;
-
 	clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe);
 	enable_percpu_irq(evt->irq, 0);
 
 	return 0;
 }
 
-static void  armada_370_xp_timer_stop(struct clock_event_device *evt)
+static void armada_370_xp_timer_stop(struct clock_event_device *evt)
 {
 	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
 	disable_percpu_irq(evt->irq);
 }
 
-static struct local_timer_ops armada_370_xp_local_timer_ops = {
-	.setup	= armada_370_xp_timer_setup,
-	.stop	=  armada_370_xp_timer_stop,
+static int armada_370_xp_timer_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
+		break;
+	case CPU_DYING:
+		armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt));
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block armada_370_xp_timer_cpu_nb = {
+	.notifier_call = armada_370_xp_timer_cpu_notify,
 };
 
 void __init armada_370_xp_timer_init(void)
@@ -223,9 +230,6 @@ void __init armada_370_xp_timer_init(void)
 
 	if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
 		/* The fixed 25MHz timer is available so let's use it */
-		u = readl(local_base + TIMER_CTRL_OFF);
-		writel(u | TIMER0_25MHZ,
-		       local_base + TIMER_CTRL_OFF);
 		u = readl(timer_base + TIMER_CTRL_OFF);
 		writel(u | TIMER0_25MHZ,
 		       timer_base + TIMER_CTRL_OFF);
@@ -235,9 +239,6 @@ void __init armada_370_xp_timer_init(void)
 		struct clk *clk = of_clk_get(np, 0);
 		WARN_ON(IS_ERR(clk));
 		rate =  clk_get_rate(clk);
-		u = readl(local_base + TIMER_CTRL_OFF);
-		writel(u & ~(TIMER0_25MHZ),
-		       local_base + TIMER_CTRL_OFF);
 
 		u = readl(timer_base + TIMER_CTRL_OFF);
 		writel(u & ~(TIMER0_25MHZ),
@@ -251,7 +252,7 @@ void __init armada_370_xp_timer_init(void)
 	 * We use timer 0 as clocksource, and private(local) timer 0
 	 * for clockevents
 	 */
-	armada_370_xp_clkevt.irq = irq_of_parse_and_map(np, 4);
+	armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4);
 
 	ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
 
@@ -276,26 +277,19 @@ void __init armada_370_xp_timer_init(void)
 			      "armada_370_xp_clocksource",
 			      timer_clk, 300, 32, clocksource_mmio_readl_down);
 
-	/* Register the clockevent on the private timer of CPU 0 */
-	armada_370_xp_clkevt.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&armada_370_xp_clkevt,
-					timer_clk, 1, 0xfffffffe);
+	register_cpu_notifier(&armada_370_xp_timer_cpu_nb);
 
-	percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *);
+	armada_370_xp_evt = alloc_percpu(struct clock_event_device);
 
 
 	/*
 	 * Setup clockevent timer (interrupt-driven).
 	 */
-	*__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt;
-	res = request_percpu_irq(armada_370_xp_clkevt.irq,
+	res = request_percpu_irq(armada_370_xp_clkevt_irq,
 				armada_370_xp_timer_interrupt,
-				armada_370_xp_clkevt.name,
-				percpu_armada_370_xp_evt);
-	if (!res) {
-		enable_percpu_irq(armada_370_xp_clkevt.irq, 0);
-#ifdef CONFIG_LOCAL_TIMERS
-		local_timer_register(&armada_370_xp_local_timer_ops);
-#endif
-	}
+				"armada_370_xp_per_cpu_tick",
+				armada_370_xp_evt);
+	/* Immediately configure the timer on the boot CPU */
+	if (!res)
+		armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
 }
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c
index ecbeb68..9c7f018 100644
--- a/drivers/clocksource/time-orion.c
+++ b/drivers/clocksource/time-orion.c
@@ -19,7 +19,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
-#include <asm/sched_clock.h>
+#include <linux/sched_clock.h>
 
 #define TIMER_CTRL		0x00
 #define  TIMER0_EN		BIT(0)
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index 62876ba..09a17d9 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
+#include <linux/cpu.h>
 #include <linux/bitops.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
@@ -18,7 +19,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/sched_clock.h>
-#include <asm/localtimer.h>
 #include <asm/mach/time.h>
 
 #define SIRFSOC_TIMER_32COUNTER_0_CTRL			0x0000
@@ -151,13 +151,7 @@ static void sirfsoc_clocksource_resume(struct clocksource *cs)
 		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
 }
 
-static struct clock_event_device sirfsoc_clockevent = {
-	.name = "sirfsoc_clockevent",
-	.rating = 200,
-	.features = CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode = sirfsoc_timer_set_mode,
-	.set_next_event = sirfsoc_timer_set_next_event,
-};
+static struct clock_event_device __percpu *sirfsoc_clockevent;
 
 static struct clocksource sirfsoc_clocksource = {
 	.name = "sirfsoc_clocksource",
@@ -173,11 +167,8 @@ static struct irqaction sirfsoc_timer_irq = {
 	.name = "sirfsoc_timer0",
 	.flags = IRQF_TIMER | IRQF_NOBALANCING,
 	.handler = sirfsoc_timer_interrupt,
-	.dev_id = &sirfsoc_clockevent,
 };
 
-#ifdef CONFIG_LOCAL_TIMERS
-
 static struct irqaction sirfsoc_timer1_irq = {
 	.name = "sirfsoc_timer1",
 	.flags = IRQF_TIMER | IRQF_NOBALANCING,
@@ -186,24 +177,28 @@ static struct irqaction sirfsoc_timer1_irq = {
 
 static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
 {
-	/* Use existing clock_event for cpu 0 */
-	if (!smp_processor_id())
-		return 0;
+	int cpu = smp_processor_id();
+	struct irqaction *action;
+
+	if (cpu == 0)
+		action = &sirfsoc_timer_irq;
+	else
+		action = &sirfsoc_timer1_irq;
 
-	ce->irq = sirfsoc_timer1_irq.irq;
+	ce->irq = action->irq;
 	ce->name = "local_timer";
-	ce->features = sirfsoc_clockevent.features;
-	ce->rating = sirfsoc_clockevent.rating;
+	ce->features = CLOCK_EVT_FEAT_ONESHOT;
+	ce->rating = 200;
 	ce->set_mode = sirfsoc_timer_set_mode;
 	ce->set_next_event = sirfsoc_timer_set_next_event;
-	ce->shift = sirfsoc_clockevent.shift;
-	ce->mult = sirfsoc_clockevent.mult;
-	ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
-	ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
+	clockevents_calc_mult_shift(ce, CLOCK_TICK_RATE, 60);
+	ce->max_delta_ns = clockevent_delta2ns(-2, ce);
+	ce->min_delta_ns = clockevent_delta2ns(2, ce);
+	ce->cpumask = cpumask_of(cpu);
 
-	sirfsoc_timer1_irq.dev_id = ce;
-	BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
-	irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
+	action->dev_id = ce;
+	BUG_ON(setup_irq(ce->irq, action));
+	irq_set_affinity(action->irq, cpumask_of(cpu));
 
 	clockevents_register_device(ce);
 	return 0;
@@ -211,31 +206,48 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
 
 static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
 {
+	int cpu = smp_processor_id();
+
 	sirfsoc_timer_count_disable(1);
 
-	remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
+	if (cpu == 0)
+		remove_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq);
+	else
+		remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
 }
 
-static struct local_timer_ops sirfsoc_local_timer_ops = {
-	.setup	= sirfsoc_local_timer_setup,
-	.stop	= sirfsoc_local_timer_stop,
+static int sirfsoc_cpu_notify(struct notifier_block *self,
+			      unsigned long action, void *hcpu)
+{
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent));
+		break;
+	case CPU_DYING:
+		sirfsoc_local_timer_stop(this_cpu_ptr(sirfsoc_clockevent));
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block sirfsoc_cpu_nb = {
+	.notifier_call = sirfsoc_cpu_notify,
 };
-#endif /* CONFIG_LOCAL_TIMERS */
 
 static void __init sirfsoc_clockevent_init(void)
 {
-	clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
-
-	sirfsoc_clockevent.max_delta_ns =
-		clockevent_delta2ns(-2, &sirfsoc_clockevent);
-	sirfsoc_clockevent.min_delta_ns =
-		clockevent_delta2ns(2, &sirfsoc_clockevent);
-
-	sirfsoc_clockevent.cpumask = cpumask_of(0);
-	clockevents_register_device(&sirfsoc_clockevent);
-#ifdef CONFIG_LOCAL_TIMERS
-	local_timer_register(&sirfsoc_local_timer_ops);
-#endif
+	sirfsoc_clockevent = alloc_percpu(struct clock_event_device);
+	BUG_ON(!sirfsoc_clockevent);
+
+	BUG_ON(register_cpu_notifier(&sirfsoc_cpu_nb));
+
+	/* Immediately configure the timer on the boot CPU */
+	sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent));
 }
 
 /* initialize the kernel jiffy timer source */
@@ -273,8 +285,6 @@ static void __init sirfsoc_marco_timer_init(void)
 
 	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
 
-	BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
-
 	sirfsoc_clockevent_init();
 }
 
@@ -288,11 +298,9 @@ static void __init sirfsoc_of_timer_init(struct device_node *np)
 	if (!sirfsoc_timer_irq.irq)
 		panic("No irq passed for timer0 via DT\n");
 
-#ifdef CONFIG_LOCAL_TIMERS
 	sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
 	if (!sirfsoc_timer1_irq.irq)
 		panic("No irq passed for timer1 via DT\n");
-#endif
 
 	sirfsoc_marco_timer_init();
 }
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index d345b5a..ad5866c 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_GENERIC_CPUFREQ_CPU0)	+= cpufreq-cpu0.o
 # powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers.
 # speedstep-* is preferred over p4-clockmod.
 
-obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o mperf.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o
 obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o
 obj-$(CONFIG_X86_PCC_CPUFREQ)		+= pcc-cpufreq.o
 obj-$(CONFIG_X86_POWERNOW_K6)		+= powernow-k6.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 3926402..9b5d1b1 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -45,7 +45,6 @@
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
-#include "mperf.h"
 
 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
@@ -710,7 +709,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		return blacklisted;
 #endif
 
-	data = kzalloc(sizeof(struct acpi_cpufreq_data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -800,7 +799,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_unreg;
 	}
 
-	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+	data->freq_table = kmalloc(sizeof(*data->freq_table) *
 		    (perf->state_count+1), GFP_KERNEL);
 	if (!data->freq_table) {
 		result = -ENOMEM;
@@ -861,10 +860,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	/* notify BIOS that we exist */
 	acpi_processor_notify_smm(THIS_MODULE);
 
-	/* Check for APERF/MPERF support in hardware */
-	if (boot_cpu_has(X86_FEATURE_APERFMPERF))
-		acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
-
 	pr_debug("CPU%u - ACPI performance management activated.\n", cpu);
 	for (i = 0; i < perf->state_count; i++)
 		pr_debug("     %cP%d: %d MHz, %d mW, %d uS\n",
@@ -941,7 +936,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
 	.exit		= acpi_cpufreq_cpu_exit,
 	.resume		= acpi_cpufreq_resume,
 	.name		= "acpi-cpufreq",
-	.owner		= THIS_MODULE,
 	.attr		= acpi_cpufreq_attr,
 };
 
diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c
index 6544887..e0c38d9 100644
--- a/drivers/cpufreq/at32ap-cpufreq.c
+++ b/drivers/cpufreq/at32ap-cpufreq.c
@@ -108,7 +108,6 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver at32_driver = {
 	.name		= "at32ap",
-	.owner		= THIS_MODULE,
 	.init		= at32_cpufreq_driver_init,
 	.verify		= at32_verify_speed,
 	.target		= at32_set_target,
diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c
index 9cdbbd2..ef05978 100644
--- a/drivers/cpufreq/blackfin-cpufreq.c
+++ b/drivers/cpufreq/blackfin-cpufreq.c
@@ -225,7 +225,6 @@ static struct cpufreq_driver bfin_driver = {
 	.get = bfin_getfreq_khz,
 	.init = __bfin_cpu_init,
 	.name = "bfin cpufreq",
-	.owner = THIS_MODULE,
 	.attr = bfin_freq_attr,
 };
 
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c
index af1542d..b83d45f 100644
--- a/drivers/cpufreq/cpufreq-nforce2.c
+++ b/drivers/cpufreq/cpufreq-nforce2.c
@@ -379,7 +379,6 @@ static struct cpufreq_driver nforce2_driver = {
 	.get = nforce2_get,
 	.init = nforce2_cpu_init,
 	.exit = nforce2_cpu_exit,
-	.owner = THIS_MODULE,
 };
 
 #ifdef MODULE
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f0a5e2b..06f8671 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -17,24 +17,17 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <asm/cputime.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/notifier.h>
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/tick.h>
 #include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/cpu.h>
-#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 #include <linux/syscore_ops.h>
-
+#include <linux/tick.h>
 #include <trace/events/power.h>
 
 /**
@@ -44,8 +37,10 @@
  */
 static struct cpufreq_driver *cpufreq_driver;
 static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
+static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
 static DEFINE_RWLOCK(cpufreq_driver_lock);
 static DEFINE_MUTEX(cpufreq_governor_lock);
+static LIST_HEAD(cpufreq_policy_list);
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* This one keeps track of the previously set governor of a removed CPU */
@@ -96,6 +91,12 @@ static void unlock_policy_rwsem_##mode(int cpu)				\
 unlock_policy_rwsem(read, cpu);
 unlock_policy_rwsem(write, cpu);
 
+/*
+ * rwsem to guarantee that cpufreq driver module doesn't unload during critical
+ * sections
+ */
+static DECLARE_RWSEM(cpufreq_rwsem);
+
 /* internal prototypes */
 static int __cpufreq_governor(struct cpufreq_policy *policy,
 		unsigned int event);
@@ -183,78 +184,46 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
 }
 EXPORT_SYMBOL_GPL(get_cpu_idle_time);
 
-static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 {
-	struct cpufreq_policy *data;
+	struct cpufreq_policy *policy = NULL;
 	unsigned long flags;
 
-	if (cpu >= nr_cpu_ids)
-		goto err_out;
+	if (cpufreq_disabled() || (cpu >= nr_cpu_ids))
+		return NULL;
+
+	if (!down_read_trylock(&cpufreq_rwsem))
+		return NULL;
 
 	/* get the cpufreq driver */
 	read_lock_irqsave(&cpufreq_driver_lock, flags);
 
-	if (!cpufreq_driver)
-		goto err_out_unlock;
-
-	if (!try_module_get(cpufreq_driver->owner))
-		goto err_out_unlock;
-
-	/* get the CPU */
-	data = per_cpu(cpufreq_cpu_data, cpu);
-
-	if (!data)
-		goto err_out_put_module;
-
-	if (!sysfs && !kobject_get(&data->kobj))
-		goto err_out_put_module;
+	if (cpufreq_driver) {
+		/* get the CPU */
+		policy = per_cpu(cpufreq_cpu_data, cpu);
+		if (policy)
+			kobject_get(&policy->kobj);
+	}
 
 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-	return data;
 
-err_out_put_module:
-	module_put(cpufreq_driver->owner);
-err_out_unlock:
-	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-err_out:
-	return NULL;
-}
-
-struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
-{
-	if (cpufreq_disabled())
-		return NULL;
+	if (!policy)
+		up_read(&cpufreq_rwsem);
 
-	return __cpufreq_cpu_get(cpu, false);
+	return policy;
 }
 EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
 
-static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
-{
-	return __cpufreq_cpu_get(cpu, true);
-}
-
-static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
-{
-	if (!sysfs)
-		kobject_put(&data->kobj);
-	module_put(cpufreq_driver->owner);
-}
-
-void cpufreq_cpu_put(struct cpufreq_policy *data)
+void cpufreq_cpu_put(struct cpufreq_policy *policy)
 {
 	if (cpufreq_disabled())
 		return;
 
-	__cpufreq_cpu_put(data, false);
+	kobject_put(&policy->kobj);
+	up_read(&cpufreq_rwsem);
 }
 EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
 
-static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
-{
-	__cpufreq_cpu_put(data, true);
-}
-
 /*********************************************************************
  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
  *********************************************************************/
@@ -459,8 +428,8 @@ show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
 
-static int __cpufreq_set_policy(struct cpufreq_policy *data,
-				struct cpufreq_policy *policy);
+static int __cpufreq_set_policy(struct cpufreq_policy *policy,
+				struct cpufreq_policy *new_policy);
 
 /**
  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
@@ -699,12 +668,12 @@ 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);
 	ssize_t ret = -EINVAL;
-	policy = cpufreq_cpu_get_sysfs(policy->cpu);
-	if (!policy)
-		goto no_policy;
+
+	if (!down_read_trylock(&cpufreq_rwsem))
+		goto exit;
 
 	if (lock_policy_rwsem_read(policy->cpu) < 0)
-		goto fail;
+		goto up_read;
 
 	if (fattr->show)
 		ret = fattr->show(policy, buf);
@@ -712,9 +681,10 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 		ret = -EIO;
 
 	unlock_policy_rwsem_read(policy->cpu);
-fail:
-	cpufreq_cpu_put_sysfs(policy);
-no_policy:
+
+up_read:
+	up_read(&cpufreq_rwsem);
+exit:
 	return ret;
 }
 
@@ -724,12 +694,12 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 	struct cpufreq_policy *policy = to_policy(kobj);
 	struct freq_attr *fattr = to_attr(attr);
 	ssize_t ret = -EINVAL;
-	policy = cpufreq_cpu_get_sysfs(policy->cpu);
-	if (!policy)
-		goto no_policy;
+
+	if (!down_read_trylock(&cpufreq_rwsem))
+		goto exit;
 
 	if (lock_policy_rwsem_write(policy->cpu) < 0)
-		goto fail;
+		goto up_read;
 
 	if (fattr->store)
 		ret = fattr->store(policy, buf, count);
@@ -737,9 +707,10 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 		ret = -EIO;
 
 	unlock_policy_rwsem_write(policy->cpu);
-fail:
-	cpufreq_cpu_put_sysfs(policy);
-no_policy:
+
+up_read:
+	up_read(&cpufreq_rwsem);
+exit:
 	return ret;
 }
 
@@ -805,41 +776,32 @@ void cpufreq_sysfs_remove_file(const struct attribute *attr)
 EXPORT_SYMBOL(cpufreq_sysfs_remove_file);
 
 /* symlink affected CPUs */
-static int cpufreq_add_dev_symlink(unsigned int cpu,
-				   struct cpufreq_policy *policy)
+static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy)
 {
 	unsigned int j;
 	int ret = 0;
 
 	for_each_cpu(j, policy->cpus) {
-		struct cpufreq_policy *managed_policy;
 		struct device *cpu_dev;
 
-		if (j == cpu)
+		if (j == policy->cpu)
 			continue;
 
-		pr_debug("CPU %u already managed, adding link\n", j);
-		managed_policy = cpufreq_cpu_get(cpu);
+		pr_debug("Adding link for CPU: %u\n", j);
 		cpu_dev = get_cpu_device(j);
 		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
 					"cpufreq");
-		if (ret) {
-			cpufreq_cpu_put(managed_policy);
-			return ret;
-		}
+		if (ret)
+			break;
 	}
 	return ret;
 }
 
-static int cpufreq_add_dev_interface(unsigned int cpu,
-				     struct cpufreq_policy *policy,
+static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
 				     struct device *dev)
 {
-	struct cpufreq_policy new_policy;
 	struct freq_attr **drv_attr;
-	unsigned long flags;
 	int ret = 0;
-	unsigned int j;
 
 	/* prepare interface data */
 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
@@ -871,18 +833,24 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
 			goto err_out_kobj_put;
 	}
 
-	write_lock_irqsave(&cpufreq_driver_lock, flags);
-	for_each_cpu(j, policy->cpus) {
-		per_cpu(cpufreq_cpu_data, j) = policy;
-		per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
-	}
-	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
-	ret = cpufreq_add_dev_symlink(cpu, policy);
+	ret = cpufreq_add_dev_symlink(policy);
 	if (ret)
 		goto err_out_kobj_put;
 
-	memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+	return ret;
+
+err_out_kobj_put:
+	kobject_put(&policy->kobj);
+	wait_for_completion(&policy->kobj_unregister);
+	return ret;
+}
+
+static void cpufreq_init_policy(struct cpufreq_policy *policy)
+{
+	struct cpufreq_policy new_policy;
+	int ret = 0;
+
+	memcpy(&new_policy, policy, sizeof(*policy));
 	/* assure that the starting sequence is run in __cpufreq_set_policy */
 	policy->governor = NULL;
 
@@ -896,29 +864,25 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
 		if (cpufreq_driver->exit)
 			cpufreq_driver->exit(policy);
 	}
-	return ret;
-
-err_out_kobj_put:
-	kobject_put(&policy->kobj);
-	wait_for_completion(&policy->kobj_unregister);
-	return ret;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
-				  struct device *dev)
+static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
+				  unsigned int cpu, struct device *dev,
+				  bool frozen)
 {
-	struct cpufreq_policy *policy;
 	int ret = 0, has_target = !!cpufreq_driver->target;
 	unsigned long flags;
 
-	policy = cpufreq_cpu_get(sibling);
-	WARN_ON(!policy);
-
-	if (has_target)
-		__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+	if (has_target) {
+		ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+		if (ret) {
+			pr_err("%s: Failed to stop governor\n", __func__);
+			return ret;
+		}
+	}
 
-	lock_policy_rwsem_write(sibling);
+	lock_policy_rwsem_write(policy->cpu);
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 
@@ -927,41 +891,85 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
 	per_cpu(cpufreq_cpu_data, cpu) = policy;
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-	unlock_policy_rwsem_write(sibling);
+	unlock_policy_rwsem_write(policy->cpu);
 
 	if (has_target) {
-		__cpufreq_governor(policy, CPUFREQ_GOV_START);
-		__cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+		if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
+			(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
+			pr_err("%s: Failed to start governor\n", __func__);
+			return ret;
+		}
 	}
 
-	ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
-	if (ret) {
-		cpufreq_cpu_put(policy);
-		return ret;
-	}
+	/* Don't touch sysfs links during light-weight init */
+	if (!frozen)
+		ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
 
-	return 0;
+	return ret;
 }
 #endif
 
-/**
- * cpufreq_add_dev - add a CPU device
- *
- * Adds the cpufreq interface for a CPU device.
- *
- * The Oracle says: try running cpufreq registration/unregistration concurrently
- * with with cpu hotplugging and all hell will break loose. Tried to clean this
- * mess up, but more thorough testing is needed. - Mathieu
- */
-static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
+static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
+{
+	struct cpufreq_policy *policy;
+	unsigned long flags;
+
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
+
+	policy = per_cpu(cpufreq_cpu_data_fallback, cpu);
+
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+	return policy;
+}
+
+static struct cpufreq_policy *cpufreq_policy_alloc(void)
+{
+	struct cpufreq_policy *policy;
+
+	policy = kzalloc(sizeof(*policy), GFP_KERNEL);
+	if (!policy)
+		return NULL;
+
+	if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
+		goto err_free_policy;
+
+	if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
+		goto err_free_cpumask;
+
+	return policy;
+
+err_free_cpumask:
+	free_cpumask_var(policy->cpus);
+err_free_policy:
+	kfree(policy);
+
+	return NULL;
+}
+
+static void cpufreq_policy_free(struct cpufreq_policy *policy)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
+	list_del(&policy->policy_list);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+	free_cpumask_var(policy->related_cpus);
+	free_cpumask_var(policy->cpus);
+	kfree(policy);
+}
+
+static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
+			     bool frozen)
 {
 	unsigned int j, cpu = dev->id;
 	int ret = -ENOMEM;
 	struct cpufreq_policy *policy;
 	unsigned long flags;
 #ifdef CONFIG_HOTPLUG_CPU
+	struct cpufreq_policy *tpolicy;
 	struct cpufreq_governor *gov;
-	int sibling;
 #endif
 
 	if (cpu_is_offline(cpu))
@@ -978,35 +986,33 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 		return 0;
 	}
 
+	if (!down_read_trylock(&cpufreq_rwsem))
+		return 0;
+
 #ifdef CONFIG_HOTPLUG_CPU
 	/* Check if this cpu was hot-unplugged earlier and has siblings */
 	read_lock_irqsave(&cpufreq_driver_lock, flags);
-	for_each_online_cpu(sibling) {
-		struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
-		if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) {
+	list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
+		if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
 			read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-			return cpufreq_add_policy_cpu(cpu, sibling, dev);
+			ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
+			up_read(&cpufreq_rwsem);
+			return ret;
 		}
 	}
 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 #endif
 
-	if (!try_module_get(cpufreq_driver->owner)) {
-		ret = -EINVAL;
-		goto module_out;
-	}
+	if (frozen)
+		/* Restore the saved policy when doing light-weight init */
+		policy = cpufreq_policy_restore(cpu);
+	else
+		policy = cpufreq_policy_alloc();
 
-	policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
 	if (!policy)
 		goto nomem_out;
 
-	if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
-		goto err_free_policy;
-
-	if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
-		goto err_free_cpumask;
-
 	policy->cpu = cpu;
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	cpumask_copy(policy->cpus, cpumask_of(cpu));
@@ -1050,38 +1056,64 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 	}
 #endif
 
-	ret = cpufreq_add_dev_interface(cpu, policy, dev);
-	if (ret)
-		goto err_out_unregister;
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
+	for_each_cpu(j, policy->cpus) {
+		per_cpu(cpufreq_cpu_data, j) = policy;
+		per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
+	}
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+	if (!frozen) {
+		ret = cpufreq_add_dev_interface(policy, dev);
+		if (ret)
+			goto err_out_unregister;
+
+		write_lock_irqsave(&cpufreq_driver_lock, flags);
+		list_add(&policy->policy_list, &cpufreq_policy_list);
+		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	}
+
+	cpufreq_init_policy(policy);
 
 	kobject_uevent(&policy->kobj, KOBJ_ADD);
-	module_put(cpufreq_driver->owner);
+	up_read(&cpufreq_rwsem);
+
 	pr_debug("initialization complete\n");
 
 	return 0;
 
 err_out_unregister:
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
-	for_each_cpu(j, policy->cpus)
+	for_each_cpu(j, policy->cpus) {
 		per_cpu(cpufreq_cpu_data, j) = NULL;
+		if (j != cpu)
+			per_cpu(cpufreq_policy_cpu, j) = -1;
+	}
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-	kobject_put(&policy->kobj);
-	wait_for_completion(&policy->kobj_unregister);
-
 err_set_policy_cpu:
 	per_cpu(cpufreq_policy_cpu, cpu) = -1;
-	free_cpumask_var(policy->related_cpus);
-err_free_cpumask:
-	free_cpumask_var(policy->cpus);
-err_free_policy:
-	kfree(policy);
+	cpufreq_policy_free(policy);
 nomem_out:
-	module_put(cpufreq_driver->owner);
-module_out:
+	up_read(&cpufreq_rwsem);
+
 	return ret;
 }
 
+/**
+ * cpufreq_add_dev - add a CPU device
+ *
+ * Adds the cpufreq interface for a CPU device.
+ *
+ * The Oracle says: try running cpufreq registration/unregistration concurrently
+ * with with cpu hotplugging and all hell will break loose. Tried to clean this
+ * mess up, but more thorough testing is needed. - Mathieu
+ */
+static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
+{
+	return __cpufreq_add_dev(dev, sif, false);
+}
+
 static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
 {
 	int j;
@@ -1099,6 +1131,43 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
 			CPUFREQ_UPDATE_POLICY_CPU, policy);
 }
 
+static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
+					   unsigned int old_cpu, bool frozen)
+{
+	struct device *cpu_dev;
+	unsigned long flags;
+	int ret;
+
+	/* first sibling now owns the new sysfs dir */
+	cpu_dev = get_cpu_device(cpumask_first(policy->cpus));
+
+	/* Don't touch sysfs files during light-weight tear-down */
+	if (frozen)
+		return cpu_dev->id;
+
+	sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
+	ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
+	if (ret) {
+		pr_err("%s: Failed to move kobj: %d", __func__, ret);
+
+		WARN_ON(lock_policy_rwsem_write(old_cpu));
+		cpumask_set_cpu(old_cpu, policy->cpus);
+
+		write_lock_irqsave(&cpufreq_driver_lock, flags);
+		per_cpu(cpufreq_cpu_data, old_cpu) = policy;
+		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+		unlock_policy_rwsem_write(old_cpu);
+
+		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
+					"cpufreq");
+
+		return -EINVAL;
+	}
+
+	return cpu_dev->id;
+}
+
 /**
  * __cpufreq_remove_dev - remove a CPU device
  *
@@ -1107,107 +1176,118 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
  * This routine frees the rwsem before returning.
  */
 static int __cpufreq_remove_dev(struct device *dev,
-		struct subsys_interface *sif)
+				struct subsys_interface *sif, bool frozen)
 {
-	unsigned int cpu = dev->id, ret, cpus;
+	unsigned int cpu = dev->id, cpus;
+	int new_cpu, ret;
 	unsigned long flags;
-	struct cpufreq_policy *data;
+	struct cpufreq_policy *policy;
 	struct kobject *kobj;
 	struct completion *cmp;
-	struct device *cpu_dev;
 
 	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 
-	data = per_cpu(cpufreq_cpu_data, cpu);
+	policy = per_cpu(cpufreq_cpu_data, cpu);
 	per_cpu(cpufreq_cpu_data, cpu) = NULL;
 
+	/* Save the policy somewhere when doing a light-weight tear-down */
+	if (frozen)
+		per_cpu(cpufreq_cpu_data_fallback, cpu) = policy;
+
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-	if (!data) {
+	if (!policy) {
 		pr_debug("%s: No cpu_data found\n", __func__);
 		return -EINVAL;
 	}
 
-	if (cpufreq_driver->target)
-		__cpufreq_governor(data, CPUFREQ_GOV_STOP);
+	if (cpufreq_driver->target) {
+		ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+		if (ret) {
+			pr_err("%s: Failed to stop governor\n", __func__);
+			return ret;
+		}
+	}
 
 #ifdef CONFIG_HOTPLUG_CPU
 	if (!cpufreq_driver->setpolicy)
 		strncpy(per_cpu(cpufreq_cpu_governor, cpu),
-			data->governor->name, CPUFREQ_NAME_LEN);
+			policy->governor->name, CPUFREQ_NAME_LEN);
 #endif
 
 	WARN_ON(lock_policy_rwsem_write(cpu));
-	cpus = cpumask_weight(data->cpus);
+	cpus = cpumask_weight(policy->cpus);
 
 	if (cpus > 1)
-		cpumask_clear_cpu(cpu, data->cpus);
+		cpumask_clear_cpu(cpu, policy->cpus);
 	unlock_policy_rwsem_write(cpu);
 
-	if (cpu != data->cpu) {
+	if (cpu != policy->cpu && !frozen) {
 		sysfs_remove_link(&dev->kobj, "cpufreq");
 	} else if (cpus > 1) {
-		/* first sibling now owns the new sysfs dir */
-		cpu_dev = get_cpu_device(cpumask_first(data->cpus));
-		sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
-		ret = kobject_move(&data->kobj, &cpu_dev->kobj);
-		if (ret) {
-			pr_err("%s: Failed to move kobj: %d", __func__, ret);
 
+		new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
+		if (new_cpu >= 0) {
 			WARN_ON(lock_policy_rwsem_write(cpu));
-			cpumask_set_cpu(cpu, data->cpus);
-
-			write_lock_irqsave(&cpufreq_driver_lock, flags);
-			per_cpu(cpufreq_cpu_data, cpu) = data;
-			write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
+			update_policy_cpu(policy, new_cpu);
 			unlock_policy_rwsem_write(cpu);
 
-			ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj,
-					"cpufreq");
-			return -EINVAL;
+			if (!frozen) {
+				pr_debug("%s: policy Kobject moved to cpu: %d "
+					 "from: %d\n",__func__, new_cpu, cpu);
+			}
 		}
-
-		WARN_ON(lock_policy_rwsem_write(cpu));
-		update_policy_cpu(data, cpu_dev->id);
-		unlock_policy_rwsem_write(cpu);
-		pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
-				__func__, cpu_dev->id, cpu);
 	}
 
 	/* If cpu is last user of policy, free policy */
 	if (cpus == 1) {
-		if (cpufreq_driver->target)
-			__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
-
-		lock_policy_rwsem_read(cpu);
-		kobj = &data->kobj;
-		cmp = &data->kobj_unregister;
-		unlock_policy_rwsem_read(cpu);
-		kobject_put(kobj);
-
-		/* we need to make sure that the underlying kobj is actually
-		 * not referenced anymore by anybody before we proceed with
-		 * unloading.
-		 */
-		pr_debug("waiting for dropping of refcount\n");
-		wait_for_completion(cmp);
-		pr_debug("wait complete\n");
+		if (cpufreq_driver->target) {
+			ret = __cpufreq_governor(policy,
+					CPUFREQ_GOV_POLICY_EXIT);
+			if (ret) {
+				pr_err("%s: Failed to exit governor\n",
+						__func__);
+				return ret;
+			}
+	}
 
+		if (!frozen) {
+			lock_policy_rwsem_read(cpu);
+			kobj = &policy->kobj;
+			cmp = &policy->kobj_unregister;
+			unlock_policy_rwsem_read(cpu);
+			kobject_put(kobj);
+
+			/*
+			 * We need to make sure that the underlying kobj is
+			 * actually not referenced anymore by anybody before we
+			 * proceed with unloading.
+			 */
+			pr_debug("waiting for dropping of refcount\n");
+			wait_for_completion(cmp);
+			pr_debug("wait complete\n");
+		}
+
+		/*
+		 * Perform the ->exit() even during light-weight tear-down,
+		 * since this is a core component, and is essential for the
+		 * subsequent light-weight ->init() to succeed.
+		 */
 		if (cpufreq_driver->exit)
-			cpufreq_driver->exit(data);
+			cpufreq_driver->exit(policy);
 
-		free_cpumask_var(data->related_cpus);
-		free_cpumask_var(data->cpus);
-		kfree(data);
+		if (!frozen)
+			cpufreq_policy_free(policy);
 	} else {
-		pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
-		cpufreq_cpu_put(data);
 		if (cpufreq_driver->target) {
-			__cpufreq_governor(data, CPUFREQ_GOV_START);
-			__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+			if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
+					(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
+				pr_err("%s: Failed to start governor\n",
+						__func__);
+				return ret;
+			}
 		}
 	}
 
@@ -1223,7 +1303,7 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
 	if (cpu_is_offline(cpu))
 		return 0;
 
-	retval = __cpufreq_remove_dev(dev, sif);
+	retval = __cpufreq_remove_dev(dev, sif, false);
 	return retval;
 }
 
@@ -1344,10 +1424,9 @@ static unsigned int __cpufreq_get(unsigned int cpu)
 unsigned int cpufreq_get(unsigned int cpu)
 {
 	unsigned int ret_freq = 0;
-	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
 
-	if (!policy)
-		goto out;
+	if (!down_read_trylock(&cpufreq_rwsem))
+		return 0;
 
 	if (unlikely(lock_policy_rwsem_read(cpu)))
 		goto out_policy;
@@ -1357,8 +1436,8 @@ unsigned int cpufreq_get(unsigned int cpu)
 	unlock_policy_rwsem_read(cpu);
 
 out_policy:
-	cpufreq_cpu_put(policy);
-out:
+	up_read(&cpufreq_rwsem);
+
 	return ret_freq;
 }
 EXPORT_SYMBOL(cpufreq_get);
@@ -1381,23 +1460,23 @@ static int cpufreq_bp_suspend(void)
 	int ret = 0;
 
 	int cpu = smp_processor_id();
-	struct cpufreq_policy *cpu_policy;
+	struct cpufreq_policy *policy;
 
 	pr_debug("suspending cpu %u\n", cpu);
 
 	/* If there's no policy for the boot CPU, we have nothing to do. */
-	cpu_policy = cpufreq_cpu_get(cpu);
-	if (!cpu_policy)
+	policy = cpufreq_cpu_get(cpu);
+	if (!policy)
 		return 0;
 
 	if (cpufreq_driver->suspend) {
-		ret = cpufreq_driver->suspend(cpu_policy);
+		ret = cpufreq_driver->suspend(policy);
 		if (ret)
 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
-					"step on CPU %u\n", cpu_policy->cpu);
+					"step on CPU %u\n", policy->cpu);
 	}
 
-	cpufreq_cpu_put(cpu_policy);
+	cpufreq_cpu_put(policy);
 	return ret;
 }
 
@@ -1419,28 +1498,28 @@ static void cpufreq_bp_resume(void)
 	int ret = 0;
 
 	int cpu = smp_processor_id();
-	struct cpufreq_policy *cpu_policy;
+	struct cpufreq_policy *policy;
 
 	pr_debug("resuming cpu %u\n", cpu);
 
 	/* If there's no policy for the boot CPU, we have nothing to do. */
-	cpu_policy = cpufreq_cpu_get(cpu);
-	if (!cpu_policy)
+	policy = cpufreq_cpu_get(cpu);
+	if (!policy)
 		return;
 
 	if (cpufreq_driver->resume) {
-		ret = cpufreq_driver->resume(cpu_policy);
+		ret = cpufreq_driver->resume(policy);
 		if (ret) {
 			printk(KERN_ERR "cpufreq: resume failed in ->resume "
-					"step on CPU %u\n", cpu_policy->cpu);
+					"step on CPU %u\n", policy->cpu);
 			goto fail;
 		}
 	}
 
-	schedule_work(&cpu_policy->update);
+	schedule_work(&policy->update);
 
 fail:
-	cpufreq_cpu_put(cpu_policy);
+	cpufreq_cpu_put(policy);
 }
 
 static struct syscore_ops cpufreq_syscore_ops = {
@@ -1594,18 +1673,6 @@ fail:
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
-int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
-{
-	if (cpufreq_disabled())
-		return 0;
-
-	if (!cpufreq_driver->getavg)
-		return 0;
-
-	return cpufreq_driver->getavg(policy, cpu);
-}
-EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
-
 /*
  * when "event" is CPUFREQ_GOV_LIMITS
  */
@@ -1640,8 +1707,9 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 		}
 	}
 
-	if (!try_module_get(policy->governor->owner))
-		return -EINVAL;
+	if (event == CPUFREQ_GOV_POLICY_INIT)
+		if (!try_module_get(policy->governor->owner))
+			return -EINVAL;
 
 	pr_debug("__cpufreq_governor for CPU %u, event %u\n",
 						policy->cpu, event);
@@ -1650,6 +1718,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 	if ((!policy->governor_enabled && (event == CPUFREQ_GOV_STOP)) ||
 	    (policy->governor_enabled && (event == CPUFREQ_GOV_START))) {
 		mutex_unlock(&cpufreq_governor_lock);
+		if (event == CPUFREQ_GOV_POLICY_INIT)
+			module_put(policy->governor->owner);
 		return -EBUSY;
 	}
 
@@ -1677,11 +1747,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 		mutex_unlock(&cpufreq_governor_lock);
 	}
 
-	/* we keep one module reference alive for
-			each CPU governed by this CPU */
-	if ((event != CPUFREQ_GOV_START) || ret)
-		module_put(policy->governor->owner);
-	if ((event == CPUFREQ_GOV_STOP) && !ret)
+	if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) ||
+			((event == CPUFREQ_GOV_POLICY_EXIT) && !ret))
 		module_put(policy->governor->owner);
 
 	return ret;
@@ -1761,7 +1828,7 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 	if (!cpu_policy)
 		return -EINVAL;
 
-	memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
+	memcpy(policy, cpu_policy, sizeof(*policy));
 
 	cpufreq_cpu_put(cpu_policy);
 	return 0;
@@ -1772,95 +1839,94 @@ EXPORT_SYMBOL(cpufreq_get_policy);
  * data   : current policy.
  * policy : policy to be set.
  */
-static int __cpufreq_set_policy(struct cpufreq_policy *data,
-				struct cpufreq_policy *policy)
+static int __cpufreq_set_policy(struct cpufreq_policy *policy,
+				struct cpufreq_policy *new_policy)
 {
 	int ret = 0, failed = 1;
 
-	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
-		policy->min, policy->max);
+	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu,
+		new_policy->min, new_policy->max);
 
-	memcpy(&policy->cpuinfo, &data->cpuinfo,
-				sizeof(struct cpufreq_cpuinfo));
+	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
 
-	if (policy->min > data->max || policy->max < data->min) {
+	if (new_policy->min > policy->max || new_policy->max < policy->min) {
 		ret = -EINVAL;
 		goto error_out;
 	}
 
 	/* verify the cpu speed can be set within this limit */
-	ret = cpufreq_driver->verify(policy);
+	ret = cpufreq_driver->verify(new_policy);
 	if (ret)
 		goto error_out;
 
 	/* adjust if necessary - all reasons */
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
-			CPUFREQ_ADJUST, policy);
+			CPUFREQ_ADJUST, new_policy);
 
 	/* adjust if necessary - hardware incompatibility*/
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
-			CPUFREQ_INCOMPATIBLE, policy);
+			CPUFREQ_INCOMPATIBLE, new_policy);
 
 	/*
 	 * verify the cpu speed can be set within this limit, which might be
 	 * different to the first one
 	 */
-	ret = cpufreq_driver->verify(policy);
+	ret = cpufreq_driver->verify(new_policy);
 	if (ret)
 		goto error_out;
 
 	/* notification of the new policy */
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
-			CPUFREQ_NOTIFY, policy);
+			CPUFREQ_NOTIFY, new_policy);
 
-	data->min = policy->min;
-	data->max = policy->max;
+	policy->min = new_policy->min;
+	policy->max = new_policy->max;
 
 	pr_debug("new min and max freqs are %u - %u kHz\n",
-					data->min, data->max);
+					policy->min, policy->max);
 
 	if (cpufreq_driver->setpolicy) {
-		data->policy = policy->policy;
+		policy->policy = new_policy->policy;
 		pr_debug("setting range\n");
-		ret = cpufreq_driver->setpolicy(policy);
+		ret = cpufreq_driver->setpolicy(new_policy);
 	} else {
-		if (policy->governor != data->governor) {
+		if (new_policy->governor != policy->governor) {
 			/* save old, working values */
-			struct cpufreq_governor *old_gov = data->governor;
+			struct cpufreq_governor *old_gov = policy->governor;
 
 			pr_debug("governor switch\n");
 
 			/* end old governor */
-			if (data->governor) {
-				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
-				unlock_policy_rwsem_write(policy->cpu);
-				__cpufreq_governor(data,
+			if (policy->governor) {
+				__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+				unlock_policy_rwsem_write(new_policy->cpu);
+				__cpufreq_governor(policy,
 						CPUFREQ_GOV_POLICY_EXIT);
-				lock_policy_rwsem_write(policy->cpu);
+				lock_policy_rwsem_write(new_policy->cpu);
 			}
 
 			/* start new governor */
-			data->governor = policy->governor;
-			if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
-				if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
+			policy->governor = new_policy->governor;
+			if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
+				if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) {
 					failed = 0;
 				} else {
-					unlock_policy_rwsem_write(policy->cpu);
-					__cpufreq_governor(data,
+					unlock_policy_rwsem_write(new_policy->cpu);
+					__cpufreq_governor(policy,
 							CPUFREQ_GOV_POLICY_EXIT);
-					lock_policy_rwsem_write(policy->cpu);
+					lock_policy_rwsem_write(new_policy->cpu);
 				}
 			}
 
 			if (failed) {
 				/* new governor failed, so re-start old one */
 				pr_debug("starting governor %s failed\n",
-							data->governor->name);
+							policy->governor->name);
 				if (old_gov) {
-					data->governor = old_gov;
-					__cpufreq_governor(data,
+					policy->governor = old_gov;
+					__cpufreq_governor(policy,
 							CPUFREQ_GOV_POLICY_INIT);
-					__cpufreq_governor(data,
+					__cpufreq_governor(policy,
 							   CPUFREQ_GOV_START);
 				}
 				ret = -EINVAL;
@@ -1869,7 +1935,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
 			/* might be a policy change, too, so fall through */
 		}
 		pr_debug("governor: change or update limits\n");
-		__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+		ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
 	}
 
 error_out:
@@ -1885,11 +1951,11 @@ error_out:
  */
 int cpufreq_update_policy(unsigned int cpu)
 {
-	struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
-	struct cpufreq_policy policy;
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	struct cpufreq_policy new_policy;
 	int ret;
 
-	if (!data) {
+	if (!policy) {
 		ret = -ENODEV;
 		goto no_policy;
 	}
@@ -1900,34 +1966,34 @@ int cpufreq_update_policy(unsigned int cpu)
 	}
 
 	pr_debug("updating policy for CPU %u\n", cpu);
-	memcpy(&policy, data, sizeof(struct cpufreq_policy));
-	policy.min = data->user_policy.min;
-	policy.max = data->user_policy.max;
-	policy.policy = data->user_policy.policy;
-	policy.governor = data->user_policy.governor;
+	memcpy(&new_policy, policy, sizeof(*policy));
+	new_policy.min = policy->user_policy.min;
+	new_policy.max = policy->user_policy.max;
+	new_policy.policy = policy->user_policy.policy;
+	new_policy.governor = policy->user_policy.governor;
 
 	/*
 	 * BIOS might change freq behind our back
 	 * -> ask driver for current freq and notify governors about a change
 	 */
 	if (cpufreq_driver->get) {
-		policy.cur = cpufreq_driver->get(cpu);
-		if (!data->cur) {
+		new_policy.cur = cpufreq_driver->get(cpu);
+		if (!policy->cur) {
 			pr_debug("Driver did not initialize current freq");
-			data->cur = policy.cur;
+			policy->cur = new_policy.cur;
 		} else {
-			if (data->cur != policy.cur && cpufreq_driver->target)
-				cpufreq_out_of_sync(cpu, data->cur,
-								policy.cur);
+			if (policy->cur != new_policy.cur && cpufreq_driver->target)
+				cpufreq_out_of_sync(cpu, policy->cur,
+								new_policy.cur);
 		}
 	}
 
-	ret = __cpufreq_set_policy(data, &policy);
+	ret = __cpufreq_set_policy(policy, &new_policy);
 
 	unlock_policy_rwsem_write(cpu);
 
 fail:
-	cpufreq_cpu_put(data);
+	cpufreq_cpu_put(policy);
 no_policy:
 	return ret;
 }
@@ -1938,21 +2004,26 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
 {
 	unsigned int cpu = (unsigned long)hcpu;
 	struct device *dev;
+	bool frozen = false;
 
 	dev = get_cpu_device(cpu);
 	if (dev) {
-		switch (action) {
+
+		if (action & CPU_TASKS_FROZEN)
+			frozen = true;
+
+		switch (action & ~CPU_TASKS_FROZEN) {
 		case CPU_ONLINE:
-		case CPU_ONLINE_FROZEN:
-			cpufreq_add_dev(dev, NULL);
+			__cpufreq_add_dev(dev, NULL, frozen);
+			cpufreq_update_policy(cpu);
 			break;
+
 		case CPU_DOWN_PREPARE:
-		case CPU_DOWN_PREPARE_FROZEN:
-			__cpufreq_remove_dev(dev, NULL);
+			__cpufreq_remove_dev(dev, NULL, frozen);
 			break;
+
 		case CPU_DOWN_FAILED:
-		case CPU_DOWN_FAILED_FROZEN:
-			cpufreq_add_dev(dev, NULL);
+			__cpufreq_add_dev(dev, NULL, frozen);
 			break;
 		}
 	}
@@ -2059,9 +2130,13 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 	subsys_interface_unregister(&cpufreq_interface);
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
+	down_write(&cpufreq_rwsem);
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
+
 	cpufreq_driver = NULL;
+
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	up_write(&cpufreq_rwsem);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 0ceb2ef..7f67a75 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -11,19 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/cpufreq.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/notifier.h>
-#include <linux/percpu-defs.h>
 #include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
 #include "cpufreq_governor.h"
 
 /* Conservative governor macros */
@@ -221,8 +209,8 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
 	return count;
 }
 
-static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
+		const char *buf, size_t count)
 {
 	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input, j;
@@ -235,10 +223,10 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
 	if (input > 1)
 		input = 1;
 
-	if (input == cs_tuners->ignore_nice) /* nothing to do */
+	if (input == cs_tuners->ignore_nice_load) /* nothing to do */
 		return count;
 
-	cs_tuners->ignore_nice = input;
+	cs_tuners->ignore_nice_load = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
@@ -246,7 +234,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
 		dbs_info = &per_cpu(cs_cpu_dbs_info, j);
 		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
 					&dbs_info->cdbs.prev_cpu_wall, 0);
-		if (cs_tuners->ignore_nice)
+		if (cs_tuners->ignore_nice_load)
 			dbs_info->cdbs.prev_cpu_nice =
 				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 	}
@@ -279,7 +267,7 @@ show_store_one(cs, sampling_rate);
 show_store_one(cs, sampling_down_factor);
 show_store_one(cs, up_threshold);
 show_store_one(cs, down_threshold);
-show_store_one(cs, ignore_nice);
+show_store_one(cs, ignore_nice_load);
 show_store_one(cs, freq_step);
 declare_show_sampling_rate_min(cs);
 
@@ -287,7 +275,7 @@ gov_sys_pol_attr_rw(sampling_rate);
 gov_sys_pol_attr_rw(sampling_down_factor);
 gov_sys_pol_attr_rw(up_threshold);
 gov_sys_pol_attr_rw(down_threshold);
-gov_sys_pol_attr_rw(ignore_nice);
+gov_sys_pol_attr_rw(ignore_nice_load);
 gov_sys_pol_attr_rw(freq_step);
 gov_sys_pol_attr_ro(sampling_rate_min);
 
@@ -297,7 +285,7 @@ static struct attribute *dbs_attributes_gov_sys[] = {
 	&sampling_down_factor_gov_sys.attr,
 	&up_threshold_gov_sys.attr,
 	&down_threshold_gov_sys.attr,
-	&ignore_nice_gov_sys.attr,
+	&ignore_nice_load_gov_sys.attr,
 	&freq_step_gov_sys.attr,
 	NULL
 };
@@ -313,7 +301,7 @@ static struct attribute *dbs_attributes_gov_pol[] = {
 	&sampling_down_factor_gov_pol.attr,
 	&up_threshold_gov_pol.attr,
 	&down_threshold_gov_pol.attr,
-	&ignore_nice_gov_pol.attr,
+	&ignore_nice_load_gov_pol.attr,
 	&freq_step_gov_pol.attr,
 	NULL
 };
@@ -329,7 +317,7 @@ static int cs_init(struct dbs_data *dbs_data)
 {
 	struct cs_dbs_tuners *tuners;
 
-	tuners = kzalloc(sizeof(struct cs_dbs_tuners), GFP_KERNEL);
+	tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
 	if (!tuners) {
 		pr_err("%s: kzalloc failed\n", __func__);
 		return -ENOMEM;
@@ -338,7 +326,7 @@ static int cs_init(struct dbs_data *dbs_data)
 	tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
 	tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
 	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
-	tuners->ignore_nice = 0;
+	tuners->ignore_nice_load = 0;
 	tuners->freq_step = DEF_FREQUENCY_STEP;
 
 	dbs_data->tuners = tuners;
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 7b839a8..8742736 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -16,15 +16,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <asm/cputime.h>
-#include <linux/cpufreq.h>
-#include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/kernel_stat.h>
-#include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
 
 #include "cpufreq_governor.h"
 
@@ -47,13 +41,13 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 	unsigned int j;
 
 	if (dbs_data->cdata->governor == GOV_ONDEMAND)
-		ignore_nice = od_tuners->ignore_nice;
+		ignore_nice = od_tuners->ignore_nice_load;
 	else
-		ignore_nice = cs_tuners->ignore_nice;
+		ignore_nice = cs_tuners->ignore_nice_load;
 
 	policy = cdbs->cur_policy;
 
-	/* Get Absolute Load (in terms of freq for ondemand gov) */
+	/* Get Absolute Load */
 	for_each_cpu(j, policy->cpus) {
 		struct cpu_dbs_common_info *j_cdbs;
 		u64 cur_wall_time, cur_idle_time;
@@ -104,14 +98,6 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 
 		load = 100 * (wall_time - idle_time) / wall_time;
 
-		if (dbs_data->cdata->governor == GOV_ONDEMAND) {
-			int freq_avg = __cpufreq_driver_getavg(policy, j);
-			if (freq_avg <= 0)
-				freq_avg = policy->cur;
-
-			load *= freq_avg;
-		}
-
 		if (load > max_load)
 			max_load = load;
 	}
@@ -298,12 +284,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		cs_tuners = dbs_data->tuners;
 		cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
 		sampling_rate = cs_tuners->sampling_rate;
-		ignore_nice = cs_tuners->ignore_nice;
+		ignore_nice = cs_tuners->ignore_nice_load;
 	} else {
 		od_tuners = dbs_data->tuners;
 		od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
 		sampling_rate = od_tuners->sampling_rate;
-		ignore_nice = od_tuners->ignore_nice;
+		ignore_nice = od_tuners->ignore_nice_load;
 		od_ops = dbs_data->cdata->gov_ops;
 		io_busy = od_tuners->io_is_busy;
 	}
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 6663ec3..a02d78b 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -18,10 +18,9 @@
 #define _CPUFREQ_GOVERNOR_H
 
 #include <linux/cpufreq.h>
-#include <linux/kobject.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/workqueue.h>
-#include <linux/sysfs.h>
 
 /*
  * The polling frequency depends on the capability of the processor. Default
@@ -165,17 +164,16 @@ struct cs_cpu_dbs_info_s {
 
 /* Per policy Governers sysfs tunables */
 struct od_dbs_tuners {
-	unsigned int ignore_nice;
+	unsigned int ignore_nice_load;
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
 	unsigned int up_threshold;
-	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
 };
 
 struct cs_dbs_tuners {
-	unsigned int ignore_nice;
+	unsigned int ignore_nice_load;
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
 	unsigned int up_threshold;
@@ -223,7 +221,7 @@ struct od_ops {
 	void (*powersave_bias_init_cpu)(int cpu);
 	unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
 			unsigned int freq_next, unsigned int relation);
-	void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq);
+	void (*freq_increase)(struct cpufreq_policy *policy, unsigned int freq);
 };
 
 struct cs_ops {
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 93eb5cb..87f3305 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -12,28 +12,16 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/cpufreq.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
+#include <linux/cpu.h>
 #include <linux/percpu-defs.h>
 #include <linux/slab.h>
-#include <linux/sysfs.h>
 #include <linux/tick.h>
-#include <linux/types.h>
-#include <linux/cpu.h>
-
 #include "cpufreq_governor.h"
 
 /* On-demand governor macros */
-#define DEF_FREQUENCY_DOWN_DIFFERENTIAL		(10)
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(100000)
-#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL	(3)
 #define MICRO_FREQUENCY_UP_THRESHOLD		(95)
 #define MICRO_FREQUENCY_MIN_SAMPLE_RATE		(10000)
 #define MIN_FREQUENCY_UP_THRESHOLD		(11)
@@ -144,31 +132,27 @@ static void ondemand_powersave_bias_init(void)
 	}
 }
 
-static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
+static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq)
 {
-	struct dbs_data *dbs_data = p->governor_data;
+	struct dbs_data *dbs_data = policy->governor_data;
 	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 
 	if (od_tuners->powersave_bias)
-		freq = od_ops.powersave_bias_target(p, freq,
+		freq = od_ops.powersave_bias_target(policy, freq,
 				CPUFREQ_RELATION_H);
-	else if (p->cur == p->max)
+	else if (policy->cur == policy->max)
 		return;
 
-	__cpufreq_driver_target(p, freq, od_tuners->powersave_bias ?
+	__cpufreq_driver_target(policy, freq, od_tuners->powersave_bias ?
 			CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
 }
 
 /*
  * Every sampling_rate, we check, if current idle time is less than 20%
- * (default), then we try to increase frequency. Every sampling_rate, we look
- * for the lowest frequency which can sustain the load while keeping idle time
- * over 30%. If such a frequency exist, we try to decrease to this frequency.
- *
- * Any frequency increase takes it to the maximum frequency. Frequency reduction
- * happens at minimum steps of 5% (default) of current frequency
+ * (default), then we try to increase frequency. Else, we adjust the frequency
+ * proportional to load.
  */
-static void od_check_cpu(int cpu, unsigned int load_freq)
+static void od_check_cpu(int cpu, unsigned int load)
 {
 	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
 	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
@@ -178,29 +162,17 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 	dbs_info->freq_lo = 0;
 
 	/* Check for frequency increase */
-	if (load_freq > od_tuners->up_threshold * policy->cur) {
+	if (load > od_tuners->up_threshold) {
 		/* If switching to max speed, apply sampling_down_factor */
 		if (policy->cur < policy->max)
 			dbs_info->rate_mult =
 				od_tuners->sampling_down_factor;
 		dbs_freq_increase(policy, policy->max);
 		return;
-	}
-
-	/* Check for frequency decrease */
-	/* if we cannot reduce the frequency anymore, break out early */
-	if (policy->cur == policy->min)
-		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_freq < od_tuners->adj_up_threshold
-			* policy->cur) {
+	} else {
+		/* Calculate the next frequency proportional to load */
 		unsigned int freq_next;
-		freq_next = load_freq / od_tuners->adj_up_threshold;
+		freq_next = load * policy->cpuinfo.max_freq / 100;
 
 		/* No longer fully busy, reset rate_mult */
 		dbs_info->rate_mult = 1;
@@ -374,9 +346,6 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
 			input < MIN_FREQUENCY_UP_THRESHOLD) {
 		return -EINVAL;
 	}
-	/* Calculate the new adj_up_threshold */
-	od_tuners->adj_up_threshold += input;
-	od_tuners->adj_up_threshold -= od_tuners->up_threshold;
 
 	od_tuners->up_threshold = input;
 	return count;
@@ -403,8 +372,8 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
 	return count;
 }
 
-static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
+		const char *buf, size_t count)
 {
 	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	unsigned int input;
@@ -419,10 +388,10 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
 	if (input > 1)
 		input = 1;
 
-	if (input == od_tuners->ignore_nice) { /* nothing to do */
+	if (input == od_tuners->ignore_nice_load) { /* nothing to do */
 		return count;
 	}
-	od_tuners->ignore_nice = input;
+	od_tuners->ignore_nice_load = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
@@ -430,7 +399,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
 		dbs_info = &per_cpu(od_cpu_dbs_info, j);
 		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
 			&dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
-		if (od_tuners->ignore_nice)
+		if (od_tuners->ignore_nice_load)
 			dbs_info->cdbs.prev_cpu_nice =
 				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
@@ -461,7 +430,7 @@ show_store_one(od, sampling_rate);
 show_store_one(od, io_is_busy);
 show_store_one(od, up_threshold);
 show_store_one(od, sampling_down_factor);
-show_store_one(od, ignore_nice);
+show_store_one(od, ignore_nice_load);
 show_store_one(od, powersave_bias);
 declare_show_sampling_rate_min(od);
 
@@ -469,7 +438,7 @@ gov_sys_pol_attr_rw(sampling_rate);
 gov_sys_pol_attr_rw(io_is_busy);
 gov_sys_pol_attr_rw(up_threshold);
 gov_sys_pol_attr_rw(sampling_down_factor);
-gov_sys_pol_attr_rw(ignore_nice);
+gov_sys_pol_attr_rw(ignore_nice_load);
 gov_sys_pol_attr_rw(powersave_bias);
 gov_sys_pol_attr_ro(sampling_rate_min);
 
@@ -478,7 +447,7 @@ static struct attribute *dbs_attributes_gov_sys[] = {
 	&sampling_rate_gov_sys.attr,
 	&up_threshold_gov_sys.attr,
 	&sampling_down_factor_gov_sys.attr,
-	&ignore_nice_gov_sys.attr,
+	&ignore_nice_load_gov_sys.attr,
 	&powersave_bias_gov_sys.attr,
 	&io_is_busy_gov_sys.attr,
 	NULL
@@ -494,7 +463,7 @@ static struct attribute *dbs_attributes_gov_pol[] = {
 	&sampling_rate_gov_pol.attr,
 	&up_threshold_gov_pol.attr,
 	&sampling_down_factor_gov_pol.attr,
-	&ignore_nice_gov_pol.attr,
+	&ignore_nice_load_gov_pol.attr,
 	&powersave_bias_gov_pol.attr,
 	&io_is_busy_gov_pol.attr,
 	NULL
@@ -513,7 +482,7 @@ static int od_init(struct dbs_data *dbs_data)
 	u64 idle_time;
 	int cpu;
 
-	tuners = kzalloc(sizeof(struct od_dbs_tuners), GFP_KERNEL);
+	tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
 	if (!tuners) {
 		pr_err("%s: kzalloc failed\n", __func__);
 		return -ENOMEM;
@@ -525,8 +494,6 @@ static int od_init(struct dbs_data *dbs_data)
 	if (idle_time != -1ULL) {
 		/* Idle micro accounting is supported. Use finer thresholds */
 		tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
-		tuners->adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD -
-			MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
 		/*
 		 * In nohz/micro accounting case we set the minimum frequency
 		 * not depending on HZ, but fixed (very low). The deferred
@@ -535,8 +502,6 @@ static int od_init(struct dbs_data *dbs_data)
 		dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
 	} else {
 		tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
-		tuners->adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD -
-			DEF_FREQUENCY_DOWN_DIFFERENTIAL;
 
 		/* For correct statistics, we need 10 ticks for each measure */
 		dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
@@ -544,7 +509,7 @@ static int od_init(struct dbs_data *dbs_data)
 	}
 
 	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
-	tuners->ignore_nice = 0;
+	tuners->ignore_nice_load = 0;
 	tuners->powersave_bias = default_powersave_bias;
 	tuners->io_is_busy = should_io_be_busy();
 
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index 9fef7d6..cf117de 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -12,10 +12,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 static int cpufreq_governor_performance(struct cpufreq_policy *policy,
 					unsigned int event)
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 32109a1..e3b874c 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -12,10 +12,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
 					unsigned int event)
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index d37568c..04452f0 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -9,17 +9,10 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/slab.h>
 #include <linux/cpu.h>
-#include <linux/sysfs.h>
 #include <linux/cpufreq.h>
 #include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/percpu.h>
-#include <linux/kobject.h>
-#include <linux/spinlock.h>
-#include <linux/notifier.h>
+#include <linux/slab.h>
 #include <asm/cputime.h>
 
 static spinlock_t cpufreq_stats_lock;
@@ -200,22 +193,22 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
 {
 	unsigned int i, j, count = 0, ret = 0;
 	struct cpufreq_stats *stat;
-	struct cpufreq_policy *data;
+	struct cpufreq_policy *current_policy;
 	unsigned int alloc_size;
 	unsigned int cpu = policy->cpu;
 	if (per_cpu(cpufreq_stats_table, cpu))
 		return -EBUSY;
-	stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL);
+	stat = kzalloc(sizeof(*stat), GFP_KERNEL);
 	if ((stat) == NULL)
 		return -ENOMEM;
 
-	data = cpufreq_cpu_get(cpu);
-	if (data == NULL) {
+	current_policy = cpufreq_cpu_get(cpu);
+	if (current_policy == NULL) {
 		ret = -EINVAL;
 		goto error_get_fail;
 	}
 
-	ret = sysfs_create_group(&data->kobj, &stats_attr_group);
+	ret = sysfs_create_group(&current_policy->kobj, &stats_attr_group);
 	if (ret)
 		goto error_out;
 
@@ -258,10 +251,10 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
 	stat->last_time = get_jiffies_64();
 	stat->last_index = freq_table_get_index(stat, policy->cur);
 	spin_unlock(&cpufreq_stats_lock);
-	cpufreq_cpu_put(data);
+	cpufreq_cpu_put(current_policy);
 	return 0;
 error_out:
-	cpufreq_cpu_put(data);
+	cpufreq_cpu_put(current_policy);
 error_get_fail:
 	kfree(stat);
 	per_cpu(cpufreq_stats_table, cpu) = NULL;
@@ -348,16 +341,10 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb,
 	unsigned int cpu = (unsigned long)hcpu;
 
 	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		cpufreq_update_policy(cpu);
-		break;
 	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
 		cpufreq_stats_free_sysfs(cpu);
 		break;
 	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
 		cpufreq_stats_free_table(cpu);
 		break;
 	}
@@ -390,8 +377,6 @@ static int __init cpufreq_stats_init(void)
 		return ret;
 
 	register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
-	for_each_online_cpu(cpu)
-		cpufreq_update_policy(cpu);
 
 	ret = cpufreq_register_notifier(&notifier_trans_block,
 				CPUFREQ_TRANSITION_NOTIFIER);
diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c
index ee142c4..cb8276d 100644
--- a/drivers/cpufreq/cris-artpec3-cpufreq.c
+++ b/drivers/cpufreq/cris-artpec3-cpufreq.c
@@ -111,7 +111,6 @@ static struct cpufreq_driver cris_freq_driver = {
 	.init	= cris_freq_cpu_init,
 	.exit	= cris_freq_cpu_exit,
 	.name	= "cris_freq",
-	.owner	= THIS_MODULE,
 	.attr	= cris_freq_attr,
 };
 
diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c
index 1295223..72328f7 100644
--- a/drivers/cpufreq/cris-etraxfs-cpufreq.c
+++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c
@@ -108,7 +108,6 @@ static struct cpufreq_driver cris_freq_driver = {
 	.init = cris_freq_cpu_init,
 	.exit = cris_freq_cpu_exit,
 	.name = "cris_freq",
-	.owner = THIS_MODULE,
 	.attr = cris_freq_attr,
 };
 
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index a60efae..09f64cc 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -54,7 +54,7 @@ static struct acpi_processor_performance *eps_acpi_cpu_perf;
 /* Minimum necessary to get acpi_processor_get_bios_limit() working */
 static int eps_acpi_init(void)
 {
-	eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance),
+	eps_acpi_cpu_perf = kzalloc(sizeof(*eps_acpi_cpu_perf),
 				      GFP_KERNEL);
 	if (!eps_acpi_cpu_perf)
 		return -ENOMEM;
@@ -366,7 +366,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
 		states = 2;
 
 	/* Allocate private data and frequency table for current cpu */
-	centaur = kzalloc(sizeof(struct eps_cpu_data)
+	centaur = kzalloc(sizeof(*centaur)
 		    + (states + 1) * sizeof(struct cpufreq_frequency_table),
 		    GFP_KERNEL);
 	if (!centaur)
@@ -436,7 +436,6 @@ static struct cpufreq_driver eps_driver = {
 	.exit		= eps_cpu_exit,
 	.get		= eps_get,
 	.name		= "e_powersaver",
-	.owner		= THIS_MODULE,
 	.attr		= eps_attr,
 };
 
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
index 658d860..823a400 100644
--- a/drivers/cpufreq/elanfreq.c
+++ b/drivers/cpufreq/elanfreq.c
@@ -274,7 +274,6 @@ static struct cpufreq_driver elanfreq_driver = {
 	.init		= elanfreq_cpu_init,
 	.exit		= elanfreq_cpu_exit,
 	.name		= "elanfreq",
-	.owner		= THIS_MODULE,
 	.attr		= elanfreq_attr,
 };
 
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 0d32f02..3664751 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -289,7 +289,7 @@ static int __init exynos_cpufreq_init(void)
 {
 	int ret = -EINVAL;
 
-	exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
+	exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
 	if (!exynos_info)
 		return -ENOMEM;
 
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index f0d8741..f111454a 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -11,10 +11,8 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/cpufreq.h>
+#include <linux/module.h>
 
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c
index 3dfc99b..ef5fee7 100644
--- a/drivers/cpufreq/gx-suspmod.c
+++ b/drivers/cpufreq/gx-suspmod.c
@@ -446,7 +446,6 @@ static struct cpufreq_driver gx_suspmod_driver = {
 	.target		= cpufreq_gx_target,
 	.init		= cpufreq_gx_cpu_init,
 	.name		= "gx-suspmod",
-	.owner		= THIS_MODULE,
 };
 
 static int __init cpufreq_gx_init(void)
@@ -466,7 +465,7 @@ static int __init cpufreq_gx_init(void)
 
 	pr_debug("geode suspend modulation available.\n");
 
-	params = kzalloc(sizeof(struct gxfreq_params), GFP_KERNEL);
+	params = kzalloc(sizeof(*params), GFP_KERNEL);
 	if (params == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index 573c14e..3e14f03 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -274,7 +274,7 @@ acpi_cpufreq_cpu_init (
 
 	pr_debug("acpi_cpufreq_cpu_init\n");
 
-	data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return (-ENOMEM);
 
@@ -304,7 +304,7 @@ acpi_cpufreq_cpu_init (
 	}
 
 	/* alloc freq_table */
-	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+	data->freq_table = kmalloc(sizeof(*data->freq_table) *
 	                           (data->acpi_data.state_count + 1),
 	                           GFP_KERNEL);
 	if (!data->freq_table) {
@@ -409,7 +409,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
 	.init		= acpi_cpufreq_cpu_init,
 	.exit		= acpi_cpufreq_cpu_exit,
 	.name		= "acpi-cpufreq",
-	.owner		= THIS_MODULE,
 	.attr           = acpi_cpufreq_attr,
 };
 
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 7cde885..6efd96c 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -665,7 +665,6 @@ static struct cpufreq_driver intel_pstate_driver = {
 	.init		= intel_pstate_cpu_init,
 	.exit		= intel_pstate_cpu_exit,
 	.name		= "intel_pstate",
-	.owner		= THIS_MODULE,
 };
 
 static int __initdata no_load;
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index c233ea6..45e4d7f 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -158,7 +158,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = {
 	.init	= kirkwood_cpufreq_cpu_init,
 	.exit	= kirkwood_cpufreq_cpu_exit,
 	.name	= "kirkwood-cpufreq",
-	.owner	= THIS_MODULE,
 	.attr	= kirkwood_cpufreq_attr,
 };
 
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 8c49261..4ada1cc 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -948,7 +948,6 @@ static struct cpufreq_driver longhaul_driver = {
 	.init	= longhaul_cpu_init,
 	.exit	= longhaul_cpu_exit,
 	.name	= "longhaul",
-	.owner	= THIS_MODULE,
 	.attr	= longhaul_attr,
 };
 
diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c
index 0fe041d..5aa0316 100644
--- a/drivers/cpufreq/longrun.c
+++ b/drivers/cpufreq/longrun.c
@@ -286,7 +286,6 @@ static struct cpufreq_driver longrun_driver = {
 	.get		= longrun_get,
 	.init		= longrun_cpu_init,
 	.name		= "longrun",
-	.owner		= THIS_MODULE,
 };
 
 static const struct x86_cpu_id longrun_ids[] = {
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index bb838b9..7bc3c44 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -118,11 +118,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		clk_put(cpuclk);
 		return -EINVAL;
 	}
-	ret = clk_set_rate(cpuclk, rate);
-	if (ret) {
-		clk_put(cpuclk);
-		return ret;
-	}
 
 	/* clock table init */
 	for (i = 2;
@@ -130,6 +125,12 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	     i++)
 		loongson2_clockmod_table[i].frequency = (rate * i) / 8;
 
+	ret = clk_set_rate(cpuclk, rate);
+	if (ret) {
+		clk_put(cpuclk);
+		return ret;
+	}
+
 	policy->cur = loongson2_cpufreq_get(policy->cpu);
 
 	cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
@@ -157,7 +158,6 @@ static struct freq_attr *loongson2_table_attr[] = {
 };
 
 static struct cpufreq_driver loongson2_cpufreq_driver = {
-	.owner = THIS_MODULE,
 	.name = "loongson2",
 	.init = loongson2_cpufreq_cpu_init,
 	.verify = loongson2_cpufreq_verify,
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
index cdd6291..41c601f 100644
--- a/drivers/cpufreq/maple-cpufreq.c
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -190,7 +190,6 @@ static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver maple_cpufreq_driver = {
 	.name		= "maple",
-	.owner		= THIS_MODULE,
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.init		= maple_cpufreq_cpu_init,
 	.verify		= maple_cpufreq_verify,
diff --git a/drivers/cpufreq/mperf.c b/drivers/cpufreq/mperf.c
deleted file mode 100644
index 911e193..0000000
--- a/drivers/cpufreq/mperf.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/slab.h>
-
-#include "mperf.h"
-
-static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);
-
-/* Called via smp_call_function_single(), on the target CPU */
-static void read_measured_perf_ctrs(void *_cur)
-{
-	struct aperfmperf *am = _cur;
-
-	get_aperfmperf(am);
-}
-
-/*
- * Return the measured active (C0) frequency on this CPU since last call
- * to this function.
- * Input: cpu number
- * Return: Average CPU frequency in terms of max frequency (zero on error)
- *
- * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
- * over a period of time, while CPU is in C0 state.
- * IA32_MPERF counts at the rate of max advertised frequency
- * IA32_APERF counts at the rate of actual CPU frequency
- * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
- * no meaning should be associated with absolute values of these MSRs.
- */
-unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy,
-					unsigned int cpu)
-{
-	struct aperfmperf perf;
-	unsigned long ratio;
-	unsigned int retval;
-
-	if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1))
-		return 0;
-
-	ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf);
-	per_cpu(acfreq_old_perf, cpu) = perf;
-
-	retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT;
-
-	return retval;
-}
-EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf);
-MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/mperf.h b/drivers/cpufreq/mperf.h
deleted file mode 100644
index 5dbf295..0000000
--- a/drivers/cpufreq/mperf.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- *  (c) 2010 Advanced Micro Devices, Inc.
- *  Your use of this code is subject to the terms and conditions of the
- *  GNU general public license version 2. See "COPYING" or
- *  http://www.gnu.org/licenses/gpl.html
- */
-
-unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy,
-					unsigned int cpu);
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index 9ee7817..2f0a2a6 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -279,7 +279,6 @@ static struct cpufreq_driver p4clockmod_driver = {
 	.exit		= cpufreq_p4_cpu_exit,
 	.get		= cpufreq_p4_get,
 	.name		= "p4-clockmod",
-	.owner		= THIS_MODULE,
 	.attr		= p4clockmod_attr,
 };
 
diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c
index b704da4..534e43a 100644
--- a/drivers/cpufreq/pasemi-cpufreq.c
+++ b/drivers/cpufreq/pasemi-cpufreq.c
@@ -297,7 +297,6 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
 
 static struct cpufreq_driver pas_cpufreq_driver = {
 	.name		= "pas-cpufreq",
-	.owner		= THIS_MODULE,
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.init		= pas_cpufreq_cpu_init,
 	.exit		= pas_cpufreq_cpu_exit,
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index 1581fcc..d81c4e5 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -587,7 +587,6 @@ static struct cpufreq_driver pcc_cpufreq_driver = {
 	.init = pcc_cpufreq_cpu_init,
 	.exit = pcc_cpufreq_cpu_exit,
 	.name = "pcc-cpufreq",
-	.owner = THIS_MODULE,
 };
 
 static int __init pcc_cpufreq_init(void)
diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c
index 3104fad..38cdc63 100644
--- a/drivers/cpufreq/pmac32-cpufreq.c
+++ b/drivers/cpufreq/pmac32-cpufreq.c
@@ -477,7 +477,6 @@ static struct cpufreq_driver pmac_cpufreq_driver = {
 	.flags		= CPUFREQ_PM_NO_WARN,
 	.attr		= pmac_cpu_freqs_attr,
 	.name		= "powermac",
-	.owner		= THIS_MODULE,
 };
 
 
diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c
index 7ba4234..b6850d9 100644
--- a/drivers/cpufreq/pmac64-cpufreq.c
+++ b/drivers/cpufreq/pmac64-cpufreq.c
@@ -371,7 +371,6 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver g5_cpufreq_driver = {
 	.name		= "powermac",
-	.owner		= THIS_MODULE,
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.init		= g5_cpufreq_cpu_init,
 	.verify		= g5_cpufreq_verify,
@@ -447,9 +446,8 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
 		if (!shdr)
 			goto bail_noprops;
 		g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1];
-		ssize = (shdr->len * sizeof(u32)) -
-			sizeof(struct smu_sdbp_header);
-		g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt);
+		ssize = (shdr->len * sizeof(u32)) - sizeof(*shdr);
+		g5_fvt_count = ssize / sizeof(*g5_fvt_table);
 		g5_fvt_cur = 0;
 
 		/* Sanity checking */
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index ea8e103..85f1c8c 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -207,7 +207,6 @@ static struct cpufreq_driver powernow_k6_driver = {
 	.exit		= powernow_k6_cpu_exit,
 	.get		= powernow_k6_get,
 	.name		= "powernow-k6",
-	.owner		= THIS_MODULE,
 	.attr		= powernow_k6_attr,
 };
 
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index 9558708..14ce480 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -177,7 +177,7 @@ static int get_ranges(unsigned char *pst)
 	unsigned int speed;
 	u8 fid, vid;
 
-	powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) *
+	powernow_table = kzalloc((sizeof(*powernow_table) *
 				(number_scales + 1)), GFP_KERNEL);
 	if (!powernow_table)
 		return -ENOMEM;
@@ -309,8 +309,7 @@ static int powernow_acpi_init(void)
 		goto err0;
 	}
 
-	acpi_processor_perf = kzalloc(sizeof(struct acpi_processor_performance),
-				      GFP_KERNEL);
+	acpi_processor_perf = kzalloc(sizeof(*acpi_processor_perf), GFP_KERNEL);
 	if (!acpi_processor_perf) {
 		retval = -ENOMEM;
 		goto err0;
@@ -346,7 +345,7 @@ static int powernow_acpi_init(void)
 		goto err2;
 	}
 
-	powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) *
+	powernow_table = kzalloc((sizeof(*powernow_table) *
 				(number_scales + 1)), GFP_KERNEL);
 	if (!powernow_table) {
 		retval = -ENOMEM;
@@ -497,7 +496,7 @@ static int powernow_decode_bios(int maxfid, int startvid)
 					"relevant to this CPU).\n",
 					psb->numpst);
 
-			p += sizeof(struct psb_s);
+			p += sizeof(*psb);
 
 			pst = (struct pst_s *) p;
 
@@ -510,12 +509,12 @@ static int powernow_decode_bios(int maxfid, int startvid)
 				    (maxfid == pst->maxfid) &&
 				    (startvid == pst->startvid)) {
 					print_pst_entry(pst, j);
-					p = (char *)pst + sizeof(struct pst_s);
+					p = (char *)pst + sizeof(*pst);
 					ret = get_ranges(p);
 					return ret;
 				} else {
 					unsigned int k;
-					p = (char *)pst + sizeof(struct pst_s);
+					p = (char *)pst + sizeof(*pst);
 					for (k = 0; k < number_scales; k++)
 						p += 2;
 				}
@@ -717,7 +716,6 @@ static struct cpufreq_driver powernow_driver = {
 	.init		= powernow_cpu_init,
 	.exit		= powernow_cpu_exit,
 	.name		= "powernow-k7",
-	.owner		= THIS_MODULE,
 	.attr		= powernow_table_attr,
 };
 
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index c39d189..2344a9e 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -623,7 +623,7 @@ static int fill_powernow_table(struct powernow_k8_data *data,
 	if (check_pst_table(data, pst, maxvid))
 		return -EINVAL;
 
-	powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table)
+	powernow_table = kmalloc((sizeof(*powernow_table)
 		* (data->numps + 1)), GFP_KERNEL);
 	if (!powernow_table) {
 		printk(KERN_ERR PFX "powernow_table memory alloc failure\n");
@@ -793,7 +793,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 	}
 
 	/* fill in data->powernow_table */
-	powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table)
+	powernow_table = kmalloc((sizeof(*powernow_table)
 		* (data->acpi_data.state_count + 1)), GFP_KERNEL);
 	if (!powernow_table) {
 		pr_debug("powernow_table memory alloc failure\n");
@@ -1106,7 +1106,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
 	if (rc)
 		return -ENODEV;
 
-	data = kzalloc(sizeof(struct powernow_k8_data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data) {
 		printk(KERN_ERR PFX "unable to alloc powernow_k8_data");
 		return -ENOMEM;
@@ -1240,7 +1240,6 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
 	.exit		= powernowk8_cpu_exit,
 	.get		= powernowk8_get,
 	.name		= "powernow-k8",
-	.owner		= THIS_MODULE,
 	.attr		= powernow_k8_attr,
 };
 
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c
index 3cae452..60e81d5 100644
--- a/drivers/cpufreq/ppc-corenet-cpufreq.c
+++ b/drivers/cpufreq/ppc-corenet-cpufreq.c
@@ -300,7 +300,6 @@ static struct freq_attr *corenet_cpufreq_attr[] = {
 
 static struct cpufreq_driver ppc_corenet_cpufreq_driver = {
 	.name		= "ppc_cpufreq",
-	.owner		= THIS_MODULE,
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.init		= corenet_cpufreq_cpu_init,
 	.exit		= __exit_p(corenet_cpufreq_cpu_exit),
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c
index 5936f8d..2e448f0 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq.c
@@ -181,7 +181,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = {
 	.init		= cbe_cpufreq_cpu_init,
 	.exit		= cbe_cpufreq_cpu_exit,
 	.name		= "cbe-cpufreq",
-	.owner		= THIS_MODULE,
 	.flags		= CPUFREQ_CONST_LOOPS,
 };
 
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
index ce5b9fc..22dcb81 100644
--- a/drivers/cpufreq/s3c2416-cpufreq.c
+++ b/drivers/cpufreq/s3c2416-cpufreq.c
@@ -524,7 +524,6 @@ static struct freq_attr *s3c2416_cpufreq_attr[] = {
 };
 
 static struct cpufreq_driver s3c2416_cpufreq_driver = {
-	.owner		= THIS_MODULE,
 	.flags          = 0,
 	.verify		= s3c2416_cpufreq_verify_speed,
 	.target		= s3c2416_cpufreq_set_target,
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 87781eb..f169ee5 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -522,7 +522,7 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
 	/* Copy the board information so that each board can make this
 	 * initdata. */
 
-	ours = kzalloc(sizeof(struct s3c_cpufreq_board), GFP_KERNEL);
+	ours = kzalloc(sizeof(*ours), GFP_KERNEL);
 	if (ours == NULL) {
 		printk(KERN_ERR "%s: no memory\n", __func__);
 		return -ENOMEM;
@@ -615,7 +615,7 @@ static int s3c_cpufreq_build_freq(void)
 	size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
 	size++;
 
-	ftab = kmalloc(sizeof(struct cpufreq_frequency_table) * size, GFP_KERNEL);
+	ftab = kmalloc(sizeof(*ftab) * size, GFP_KERNEL);
 	if (!ftab) {
 		printk(KERN_ERR "%s: no memory for tables\n", __func__);
 		return -ENOMEM;
@@ -691,7 +691,7 @@ int __init s3c_plltab_register(struct cpufreq_frequency_table *plls,
 	struct cpufreq_frequency_table *vals;
 	unsigned int size;
 
-	size = sizeof(struct cpufreq_frequency_table) * (plls_no + 1);
+	size = sizeof(*vals) * (plls_no + 1);
 
 	vals = kmalloc(size, GFP_KERNEL);
 	if (vals) {
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 13bb4ba..8a72b0c 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -263,7 +263,6 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver s3c64xx_cpufreq_driver = {
-	.owner		= THIS_MODULE,
 	.flags          = 0,
 	.verify		= s3c64xx_cpufreq_verify_speed,
 	.target		= s3c64xx_cpufreq_set_target,
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
index 77a2109..d6f6c6f 100644
--- a/drivers/cpufreq/sc520_freq.c
+++ b/drivers/cpufreq/sc520_freq.c
@@ -147,7 +147,6 @@ static struct cpufreq_driver sc520_freq_driver = {
 	.init	= sc520_freq_cpu_init,
 	.exit	= sc520_freq_cpu_exit,
 	.name	= "sc520_freq",
-	.owner	= THIS_MODULE,
 	.attr	= sc520_freq_attr,
 };
 
diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c
index 73adb64..ffc6d24 100644
--- a/drivers/cpufreq/sh-cpufreq.c
+++ b/drivers/cpufreq/sh-cpufreq.c
@@ -160,7 +160,6 @@ static struct freq_attr *sh_freq_attr[] = {
 };
 
 static struct cpufreq_driver sh_cpufreq_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "sh",
 	.get		= sh_cpufreq_get,
 	.target		= sh_cpufreq_target,
diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c
index 93061a4..cf5bc2c 100644
--- a/drivers/cpufreq/sparc-us2e-cpufreq.c
+++ b/drivers/cpufreq/sparc-us2e-cpufreq.c
@@ -351,12 +351,11 @@ static int __init us2e_freq_init(void)
 		struct cpufreq_driver *driver;
 
 		ret = -ENOMEM;
-		driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL);
+		driver = kzalloc(sizeof(*driver), GFP_KERNEL);
 		if (!driver)
 			goto err_out;
 
-		us2e_freq_table = kzalloc(
-			(NR_CPUS * sizeof(struct us2e_freq_percpu_info)),
+		us2e_freq_table = kzalloc((NR_CPUS * sizeof(*us2e_freq_table)),
 			GFP_KERNEL);
 		if (!us2e_freq_table)
 			goto err_out;
@@ -366,7 +365,6 @@ static int __init us2e_freq_init(void)
 		driver->target = us2e_freq_target;
 		driver->get = us2e_freq_get;
 		driver->exit = us2e_freq_cpu_exit;
-		driver->owner = THIS_MODULE,
 		strcpy(driver->name, "UltraSPARC-IIe");
 
 		cpufreq_us2e_driver = driver;
diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c
index 880ee29..ac76b48 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -212,12 +212,11 @@ static int __init us3_freq_init(void)
 		struct cpufreq_driver *driver;
 
 		ret = -ENOMEM;
-		driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL);
+		driver = kzalloc(sizeof(*driver), GFP_KERNEL);
 		if (!driver)
 			goto err_out;
 
-		us3_freq_table = kzalloc(
-			(NR_CPUS * sizeof(struct us3_freq_percpu_info)),
+		us3_freq_table = kzalloc((NR_CPUS * sizeof(*us3_freq_table)),
 			GFP_KERNEL);
 		if (!us3_freq_table)
 			goto err_out;
@@ -227,7 +226,6 @@ static int __init us3_freq_init(void)
 		driver->target = us3_freq_target;
 		driver->get = us3_freq_get;
 		driver->exit = us3_freq_cpu_exit;
-		driver->owner = THIS_MODULE,
 		strcpy(driver->name, "UltraSPARC-III");
 
 		cpufreq_us3_driver = driver;
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index 0915e71..f897d51 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -575,7 +575,6 @@ static struct cpufreq_driver centrino_driver = {
 	.target		= centrino_target,
 	.get		= get_cur_freq,
 	.attr           = centrino_attr,
-	.owner		= THIS_MODULE,
 };
 
 /*
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index e2e5aa9..5355abb 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -378,7 +378,6 @@ static struct cpufreq_driver speedstep_driver = {
 	.init	= speedstep_cpu_init,
 	.exit	= speedstep_cpu_exit,
 	.get	= speedstep_get,
-	.owner	= THIS_MODULE,
 	.attr	= speedstep_attr,
 };
 
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index f5a6b70..abfba4f 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -375,7 +375,6 @@ static struct cpufreq_driver speedstep_driver = {
 	.exit		= speedstep_cpu_exit,
 	.get		= speedstep_get,
 	.resume		= speedstep_resume,
-	.owner		= THIS_MODULE,
 	.attr		= speedstep_attr,
 };
 
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 0e2cd5c..b3fb81d 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -1,5 +1,6 @@
+menu "CPU Idle"
 
-menuconfig CPU_IDLE
+config CPU_IDLE
 	bool "CPU idle PM support"
 	default y if ACPI || PPC_PSERIES
 	select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE)
@@ -29,20 +30,13 @@ config CPU_IDLE_GOV_MENU
 	bool "Menu governor (for tickless system)"
 	default y
 
-config CPU_IDLE_CALXEDA
-	bool "CPU Idle Driver for Calxeda processors"
-	depends on ARCH_HIGHBANK
-	select ARM_CPU_SUSPEND
-	help
-	  Select this to enable cpuidle on Calxeda processors.
-
-config CPU_IDLE_ZYNQ
-	bool "CPU Idle Driver for Xilinx Zynq processors"
-	depends on ARCH_ZYNQ
-	help
-	  Select this to enable cpuidle on Xilinx Zynq processors.
+menu "ARM CPU Idle Drivers"
+depends on ARM
+source "drivers/cpuidle/Kconfig.arm"
+endmenu
 
 endif
 
 config ARCH_NEEDS_CPU_IDLE_COUPLED
 	def_bool n
+endmenu
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
new file mode 100644
index 0000000..b330219
--- /dev/null
+++ b/drivers/cpuidle/Kconfig.arm
@@ -0,0 +1,29 @@
+#
+# ARM CPU Idle drivers
+#
+
+config ARM_HIGHBANK_CPUIDLE
+	bool "CPU Idle Driver for Calxeda processors"
+	depends on ARCH_HIGHBANK
+	select ARM_CPU_SUSPEND
+	help
+	  Select this to enable cpuidle on Calxeda processors.
+
+config ARM_KIRKWOOD_CPUIDLE
+	bool "CPU Idle Driver for Marvell Kirkwood SoCs"
+	depends on ARCH_KIRKWOOD
+	help
+	  This adds the CPU Idle driver for Marvell Kirkwood SoCs.
+
+config ARM_ZYNQ_CPUIDLE
+	bool "CPU Idle Driver for Xilinx Zynq processors"
+	depends on ARCH_ZYNQ
+	help
+	  Select this to enable cpuidle on Xilinx Zynq processors.
+
+config ARM_U8500_CPUIDLE
+	bool "Cpu Idle Driver for the ST-E u8500 processors"
+	depends on ARCH_U8500
+	help
+	  Select this to enable cpuidle for ST-E u8500 processors
+
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 8767a7b..0b9d200 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -5,6 +5,9 @@
 obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
-obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
-obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o
-obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o
+##################################################################################
+# ARM SoC drivers
+obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)	+= cpuidle-calxeda.o
+obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE)	+= cpuidle-kirkwood.o
+obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)		+= cpuidle-zynq.o
+obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c
new file mode 100644
index 0000000..e056465
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-ux500.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM)
+ *
+ * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com>
+ * and Jonas Aaberg <jonas.aberg@stericsson.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+#include <linux/smp.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/arm-ux500-pm.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+
+static atomic_t master = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(master_lock);
+
+static inline int ux500_enter_idle(struct cpuidle_device *dev,
+				   struct cpuidle_driver *drv, int index)
+{
+	int this_cpu = smp_processor_id();
+	bool recouple = false;
+
+	if (atomic_inc_return(&master) == num_online_cpus()) {
+
+		/* With this lock, we prevent the other cpu to exit and enter
+		 * this function again and become the master */
+		if (!spin_trylock(&master_lock))
+			goto wfi;
+
+		/* decouple the gic from the A9 cores */
+		if (prcmu_gic_decouple()) {
+			spin_unlock(&master_lock);
+			goto out;
+		}
+
+		/* If an error occur, we will have to recouple the gic
+		 * manually */
+		recouple = true;
+
+		/* At this state, as the gic is decoupled, if the other
+		 * cpu is in WFI, we have the guarantee it won't be wake
+		 * up, so we can safely go to retention */
+		if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1))
+			goto out;
+
+		/* The prcmu will be in charge of watching the interrupts
+		 * and wake up the cpus */
+		if (prcmu_copy_gic_settings())
+			goto out;
+
+		/* Check in the meantime an interrupt did
+		 * not occur on the gic ... */
+		if (prcmu_gic_pending_irq())
+			goto out;
+
+		/* ... and the prcmu */
+		if (prcmu_pending_irq())
+			goto out;
+
+		/* Go to the retention state, the prcmu will wait for the
+		 * cpu to go WFI and this is what happens after exiting this
+		 * 'master' critical section */
+		if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
+			goto out;
+
+		/* When we switch to retention, the prcmu is in charge
+		 * of recoupling the gic automatically */
+		recouple = false;
+
+		spin_unlock(&master_lock);
+	}
+wfi:
+	cpu_do_idle();
+out:
+	atomic_dec(&master);
+
+	if (recouple) {
+		prcmu_gic_recouple();
+		spin_unlock(&master_lock);
+	}
+
+	return index;
+}
+
+static struct cpuidle_driver ux500_idle_driver = {
+	.name = "ux500_idle",
+	.owner = THIS_MODULE,
+	.states = {
+		ARM_CPUIDLE_WFI_STATE,
+		{
+			.enter		  = ux500_enter_idle,
+			.exit_latency	  = 70,
+			.target_residency = 260,
+			.flags		  = CPUIDLE_FLAG_TIME_VALID |
+			                    CPUIDLE_FLAG_TIMER_STOP,
+			.name		  = "ApIdle",
+			.desc		  = "ARM Retention",
+		},
+	},
+	.safe_state_index = 0,
+	.state_count = 2,
+};
+
+static int __init dbx500_cpuidle_probe(struct platform_device *pdev)
+{
+	/* Configure wake up reasons */
+	prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
+			     PRCMU_WAKEUP(ABB));
+
+	return cpuidle_register(&ux500_idle_driver, NULL);
+}
+
+static struct platform_driver dbx500_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-dbx500",
+		.owner = THIS_MODULE,
+	},
+	.probe = dbx500_cpuidle_probe,
+};
+
+module_platform_driver(dbx500_cpuidle_plat_driver);
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index fdc432f..d75040d 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -42,8 +42,6 @@ void disable_cpuidle(void)
 	off = 1;
 }
 
-static int __cpuidle_register_device(struct cpuidle_device *dev);
-
 /**
  * cpuidle_play_dead - cpu off-lining
  *
@@ -278,7 +276,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
  */
 int cpuidle_enable_device(struct cpuidle_device *dev)
 {
-	int ret, i;
+	int ret;
 	struct cpuidle_driver *drv;
 
 	if (!dev)
@@ -292,15 +290,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 	if (!drv || !cpuidle_curr_governor)
 		return -EIO;
 
+	if (!dev->registered)
+		return -EINVAL;
+
 	if (!dev->state_count)
 		dev->state_count = drv->state_count;
 
-	if (dev->registered == 0) {
-		ret = __cpuidle_register_device(dev);
-		if (ret)
-			return ret;
-	}
-
 	poll_idle_init(drv);
 
 	ret = cpuidle_add_device_sysfs(dev);
@@ -311,12 +306,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 	    (ret = cpuidle_curr_governor->enable(drv, dev)))
 		goto fail_sysfs;
 
-	for (i = 0; i < dev->state_count; i++) {
-		dev->states_usage[i].usage = 0;
-		dev->states_usage[i].time = 0;
-	}
-	dev->last_residency = 0;
-
 	smp_wmb();
 
 	dev->enabled = 1;
@@ -360,6 +349,23 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
 
 EXPORT_SYMBOL_GPL(cpuidle_disable_device);
 
+static void __cpuidle_unregister_device(struct cpuidle_device *dev)
+{
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+
+	list_del(&dev->device_list);
+	per_cpu(cpuidle_devices, dev->cpu) = NULL;
+	module_put(drv->owner);
+}
+
+static int __cpuidle_device_init(struct cpuidle_device *dev)
+{
+	memset(dev->states_usage, 0, sizeof(dev->states_usage));
+	dev->last_residency = 0;
+
+	return 0;
+}
+
 /**
  * __cpuidle_register_device - internal register function called before register
  * and enable routines
@@ -377,24 +383,15 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
 
 	per_cpu(cpuidle_devices, dev->cpu) = dev;
 	list_add(&dev->device_list, &cpuidle_detected_devices);
-	ret = cpuidle_add_sysfs(dev);
-	if (ret)
-		goto err_sysfs;
 
 	ret = cpuidle_coupled_register_device(dev);
-	if (ret)
-		goto err_coupled;
+	if (ret) {
+		__cpuidle_unregister_device(dev);
+		return ret;
+	}
 
 	dev->registered = 1;
 	return 0;
-
-err_coupled:
-	cpuidle_remove_sysfs(dev);
-err_sysfs:
-	list_del(&dev->device_list);
-	per_cpu(cpuidle_devices, dev->cpu) = NULL;
-	module_put(drv->owner);
-	return ret;
 }
 
 /**
@@ -403,25 +400,44 @@ err_sysfs:
  */
 int cpuidle_register_device(struct cpuidle_device *dev)
 {
-	int ret;
+	int ret = -EBUSY;
 
 	if (!dev)
 		return -EINVAL;
 
 	mutex_lock(&cpuidle_lock);
 
-	if ((ret = __cpuidle_register_device(dev))) {
-		mutex_unlock(&cpuidle_lock);
-		return ret;
-	}
+	if (dev->registered)
+		goto out_unlock;
+
+	ret = __cpuidle_device_init(dev);
+	if (ret)
+		goto out_unlock;
+
+	ret = __cpuidle_register_device(dev);
+	if (ret)
+		goto out_unlock;
+
+	ret = cpuidle_add_sysfs(dev);
+	if (ret)
+		goto out_unregister;
+
+	ret = cpuidle_enable_device(dev);
+	if (ret)
+		goto out_sysfs;
 
-	cpuidle_enable_device(dev);
 	cpuidle_install_idle_handler();
 
+out_unlock:
 	mutex_unlock(&cpuidle_lock);
 
-	return 0;
+	return ret;
 
+out_sysfs:
+	cpuidle_remove_sysfs(dev);
+out_unregister:
+	__cpuidle_unregister_device(dev);
+	goto out_unlock;
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_register_device);
@@ -432,8 +448,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
-
 	if (dev->registered == 0)
 		return;
 
@@ -442,14 +456,12 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
 	cpuidle_disable_device(dev);
 
 	cpuidle_remove_sysfs(dev);
-	list_del(&dev->device_list);
-	per_cpu(cpuidle_devices, dev->cpu) = NULL;
+
+	__cpuidle_unregister_device(dev);
 
 	cpuidle_coupled_unregister_device(dev);
 
 	cpuidle_resume_and_unlock();
-
-	module_put(drv->owner);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 9b78405..9f08e8c 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -192,14 +192,4 @@ static int __init init_ladder(void)
 	return cpuidle_register_governor(&ladder_governor);
 }
 
-/**
- * exit_ladder - exits the governor
- */
-static void __exit exit_ladder(void)
-{
-	cpuidle_unregister_governor(&ladder_governor);
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_ladder);
-module_exit(exit_ladder);
+postcore_initcall(init_ladder);
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index bc580b6..cbbb73b 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -442,14 +442,4 @@ static int __init init_menu(void)
 	return cpuidle_register_governor(&menu_governor);
 }
 
-/**
- * exit_menu - exits the governor
- */
-static void __exit exit_menu(void)
-{
-	cpuidle_unregister_governor(&menu_governor);
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_menu);
-module_exit(exit_menu);
+postcore_initcall(init_menu);
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 428754a..8739cc0 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -11,8 +11,10 @@
 #include <linux/sysfs.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <linux/completion.h>
 #include <linux/capability.h>
 #include <linux/device.h>
+#include <linux/kobject.h>
 
 #include "cpuidle.h"
 
@@ -33,7 +35,8 @@ static ssize_t show_available_governors(struct device *dev,
 
 	mutex_lock(&cpuidle_lock);
 	list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
-		if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
+		if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) -
+				    CPUIDLE_NAME_LEN - 2))
 			goto out;
 		i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
 	}
@@ -166,13 +169,28 @@ struct cpuidle_attr {
 #define define_one_rw(_name, show, store) \
 	static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
 
-#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
 #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
-static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
+
+struct cpuidle_device_kobj {
+	struct cpuidle_device *dev;
+	struct completion kobj_unregister;
+	struct kobject kobj;
+};
+
+static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj)
+{
+	struct cpuidle_device_kobj *kdev =
+		container_of(kobj, struct cpuidle_device_kobj, kobj);
+
+	return kdev->dev;
+}
+
+static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr,
+			    char *buf)
 {
 	int ret = -EIO;
-	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-	struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+	struct cpuidle_device *dev = to_cpuidle_device(kobj);
+	struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
 
 	if (cattr->show) {
 		mutex_lock(&cpuidle_lock);
@@ -182,12 +200,12 @@ static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char
 	return ret;
 }
 
-static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
-		     const char * buf, size_t count)
+static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr,
+			     const char *buf, size_t count)
 {
 	int ret = -EIO;
-	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-	struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+	struct cpuidle_device *dev = to_cpuidle_device(kobj);
+	struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
 
 	if (cattr->store) {
 		mutex_lock(&cpuidle_lock);
@@ -204,9 +222,10 @@ static const struct sysfs_ops cpuidle_sysfs_ops = {
 
 static void cpuidle_sysfs_release(struct kobject *kobj)
 {
-	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+	struct cpuidle_device_kobj *kdev =
+		container_of(kobj, struct cpuidle_device_kobj, kobj);
 
-	complete(&dev->kobj_unregister);
+	complete(&kdev->kobj_unregister);
 }
 
 static struct kobj_type ktype_cpuidle = {
@@ -237,8 +256,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \
 
 #define define_store_state_ull_function(_name) \
 static ssize_t store_state_##_name(struct cpuidle_state *state, \
-		struct cpuidle_state_usage *state_usage, \
-		const char *buf, size_t size) \
+				   struct cpuidle_state_usage *state_usage, \
+				   const char *buf, size_t size)	\
 { \
 	unsigned long long value; \
 	int err; \
@@ -256,14 +275,16 @@ static ssize_t store_state_##_name(struct cpuidle_state *state, \
 
 #define define_show_state_ull_function(_name) \
 static ssize_t show_state_##_name(struct cpuidle_state *state, \
-			struct cpuidle_state_usage *state_usage, char *buf) \
+				  struct cpuidle_state_usage *state_usage, \
+				  char *buf)				\
 { \
 	return sprintf(buf, "%llu\n", state_usage->_name);\
 }
 
 #define define_show_state_str_function(_name) \
 static ssize_t show_state_##_name(struct cpuidle_state *state, \
-			struct cpuidle_state_usage *state_usage, char *buf) \
+				  struct cpuidle_state_usage *state_usage, \
+				  char *buf)				\
 { \
 	if (state->_name[0] == '\0')\
 		return sprintf(buf, "<null>\n");\
@@ -309,8 +330,9 @@ struct cpuidle_state_kobj {
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
-static ssize_t cpuidle_state_show(struct kobject * kobj,
-	struct attribute * attr ,char * buf)
+
+static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr,
+				  char * buf)
 {
 	int ret = -EIO;
 	struct cpuidle_state *state = kobj_to_state(kobj);
@@ -323,8 +345,8 @@ static ssize_t cpuidle_state_show(struct kobject * kobj,
 	return ret;
 }
 
-static ssize_t cpuidle_state_store(struct kobject *kobj,
-	struct attribute *attr, const char *buf, size_t size)
+static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr,
+				   const char *buf, size_t size)
 {
 	int ret = -EIO;
 	struct cpuidle_state *state = kobj_to_state(kobj);
@@ -371,6 +393,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 {
 	int i, ret = -ENOMEM;
 	struct cpuidle_state_kobj *kobj;
+	struct cpuidle_device_kobj *kdev = device->kobj_dev;
 	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
 	/* state statistics */
@@ -383,7 +406,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 		init_completion(&kobj->kobj_unregister);
 
 		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
-					   &device->kobj, "state%d", i);
+					   &kdev->kobj, "state%d", i);
 		if (ret) {
 			kfree(kobj);
 			goto error_state;
@@ -449,8 +472,8 @@ static void cpuidle_driver_sysfs_release(struct kobject *kobj)
 	complete(&driver_kobj->kobj_unregister);
 }
 
-static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr,
-				   char * buf)
+static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute *attr,
+				   char *buf)
 {
 	int ret = -EIO;
 	struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
@@ -500,6 +523,7 @@ static struct kobj_type ktype_driver_cpuidle = {
 static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
 {
 	struct cpuidle_driver_kobj *kdrv;
+	struct cpuidle_device_kobj *kdev = dev->kobj_dev;
 	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
 	int ret;
 
@@ -511,7 +535,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
 	init_completion(&kdrv->kobj_unregister);
 
 	ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
-				   &dev->kobj, "driver");
+				   &kdev->kobj, "driver");
 	if (ret) {
 		kfree(kdrv);
 		return ret;
@@ -580,16 +604,28 @@ void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
  */
 int cpuidle_add_sysfs(struct cpuidle_device *dev)
 {
+	struct cpuidle_device_kobj *kdev;
 	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
 	int error;
 
-	init_completion(&dev->kobj_unregister);
+	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+	if (!kdev)
+		return -ENOMEM;
+	kdev->dev = dev;
+	dev->kobj_dev = kdev;
 
-	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
-				     "cpuidle");
-	if (!error)
-		kobject_uevent(&dev->kobj, KOBJ_ADD);
-	return error;
+	init_completion(&kdev->kobj_unregister);
+
+	error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
+				   "cpuidle");
+	if (error) {
+		kfree(kdev);
+		return error;
+	}
+
+	kobject_uevent(&kdev->kobj, KOBJ_ADD);
+
+	return 0;
 }
 
 /**
@@ -598,6 +634,9 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
  */
 void cpuidle_remove_sysfs(struct cpuidle_device *dev)
 {
-	kobject_put(&dev->kobj);
-	wait_for_completion(&dev->kobj_unregister);
+	struct cpuidle_device_kobj *kdev = dev->kobj_dev;
+
+	kobject_put(&kdev->kobj);
+	wait_for_completion(&kdev->kobj_unregister);
+	kfree(kdev);
 }
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 8ff7c23..62fb673 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -242,13 +242,16 @@ config CRYPTO_DEV_PPC4XX
 	  This option allows you to have support for AMCC crypto acceleration.
 
 config CRYPTO_DEV_OMAP_SHAM
-	tristate "Support for OMAP SHA1/MD5 hw accelerator"
-	depends on ARCH_OMAP2 || ARCH_OMAP3
+	tristate "Support for OMAP MD5/SHA1/SHA2 hw accelerator"
+	depends on ARCH_OMAP2PLUS
 	select CRYPTO_SHA1
 	select CRYPTO_MD5
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	select CRYPTO_HMAC
 	help
-	  OMAP processors have SHA1/MD5 hw accelerator. Select this if you
-	  want to use the OMAP module for SHA1/MD5 algorithms.
+	  OMAP processors have MD5/SHA1/SHA2 hw accelerator. Select this if you
+	  want to use the OMAP module for MD5/SHA1/SHA2 algorithms.
 
 config CRYPTO_DEV_OMAP_AES
 	tristate "Support for OMAP AES hw engine"
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index bf416a8..7a9052c 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -65,8 +65,6 @@
 #define CAAM_MAX_IV_LENGTH		16
 
 /* length of descriptors text */
-#define DESC_JOB_IO_LEN			(CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
-
 #define DESC_AEAD_BASE			(4 * CAAM_CMD_SZ)
 #define DESC_AEAD_ENC_LEN		(DESC_AEAD_BASE + 16 * CAAM_CMD_SZ)
 #define DESC_AEAD_DEC_LEN		(DESC_AEAD_BASE + 21 * CAAM_CMD_SZ)
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 84573b4..98429b8 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -72,8 +72,6 @@
 #define CAAM_MAX_HASH_DIGEST_SIZE	SHA512_DIGEST_SIZE
 
 /* length of descriptors text */
-#define DESC_JOB_IO_LEN			(CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
-
 #define DESC_AHASH_BASE			(4 * CAAM_CMD_SZ)
 #define DESC_AHASH_UPDATE_LEN		(6 * CAAM_CMD_SZ)
 #define DESC_AHASH_UPDATE_FIRST_LEN	(DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index f5d6dec..b010d42 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -75,55 +75,53 @@ static void build_instantiation_desc(u32 *desc)
 			 OP_ALG_RNG4_SK);
 }
 
-struct instantiate_result {
-	struct completion completion;
-	int err;
-};
-
-static void rng4_init_done(struct device *dev, u32 *desc, u32 err,
-			   void *context)
-{
-	struct instantiate_result *instantiation = context;
-
-	if (err) {
-		char tmp[CAAM_ERROR_STR_MAX];
-
-		dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
-	}
-
-	instantiation->err = err;
-	complete(&instantiation->completion);
-}
-
-static int instantiate_rng(struct device *jrdev)
+static int instantiate_rng(struct device *ctrldev)
 {
-	struct instantiate_result instantiation;
-
-	dma_addr_t desc_dma;
+	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+	struct caam_full __iomem *topregs;
+	unsigned int timeout = 100000;
 	u32 *desc;
-	int ret;
+	int i, ret = 0;
 
 	desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
 	if (!desc) {
-		dev_err(jrdev, "cannot allocate RNG init descriptor memory\n");
+		dev_err(ctrldev, "can't allocate RNG init descriptor memory\n");
 		return -ENOMEM;
 	}
-
 	build_instantiation_desc(desc);
-	desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE);
-	init_completion(&instantiation.completion);
-	ret = caam_jr_enqueue(jrdev, desc, rng4_init_done, &instantiation);
-	if (!ret) {
-		wait_for_completion_interruptible(&instantiation.completion);
-		ret = instantiation.err;
-		if (ret)
-			dev_err(jrdev, "unable to instantiate RNG\n");
+
+	/* Set the bit to request direct access to DECO0 */
+	topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+	setbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
+
+	while (!(rd_reg32(&topregs->ctrl.deco_rq) & DECORR_DEN0) &&
+								 --timeout)
+		cpu_relax();
+
+	if (!timeout) {
+		dev_err(ctrldev, "failed to acquire DECO 0\n");
+		ret = -EIO;
+		goto out;
 	}
 
-	dma_unmap_single(jrdev, desc_dma, desc_bytes(desc), DMA_TO_DEVICE);
+	for (i = 0; i < desc_len(desc); i++)
+		topregs->deco.descbuf[i] = *(desc + i);
 
-	kfree(desc);
+	wr_reg32(&topregs->deco.jr_ctl_hi, DECO_JQCR_WHL | DECO_JQCR_FOUR);
 
+	timeout = 10000000;
+	while ((rd_reg32(&topregs->deco.desc_dbg) & DECO_DBG_VALID) &&
+								 --timeout)
+		cpu_relax();
+
+	if (!timeout) {
+		dev_err(ctrldev, "failed to instantiate RNG\n");
+		ret = -EIO;
+	}
+
+	clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
+out:
+	kfree(desc);
 	return ret;
 }
 
@@ -303,7 +301,7 @@ static int caam_probe(struct platform_device *pdev)
 	if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4 &&
 	    !(rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IF0)) {
 		kick_trng(pdev);
-		ret = instantiate_rng(ctrlpriv->jrdev[0]);
+		ret = instantiate_rng(dev);
 		if (ret) {
 			caam_remove(pdev);
 			return ret;
@@ -315,9 +313,6 @@ static int caam_probe(struct platform_device *pdev)
 
 	/* NOTE: RTIC detection ought to go here, around Si time */
 
-	/* Initialize queue allocator lock */
-	spin_lock_init(&ctrlpriv->jr_alloc_lock);
-
 	caam_id = rd_reg64(&topregs->ctrl.perfmon.caam_id);
 
 	/* Report "alive" for developer to see */
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index fe3bfd1..cd5f678 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -10,6 +10,7 @@
 #define CAAM_CMD_SZ sizeof(u32)
 #define CAAM_PTR_SZ sizeof(dma_addr_t)
 #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
+#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
 
 #ifdef DEBUG
 #define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index e4a16b7..34c4b9f 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -9,9 +9,6 @@
 #ifndef INTERN_H
 #define INTERN_H
 
-#define JOBR_UNASSIGNED 0
-#define JOBR_ASSIGNED 1
-
 /* Currently comes from Kconfig param as a ^2 (driver-required) */
 #define JOBR_DEPTH (1 << CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE)
 
@@ -46,7 +43,6 @@ struct caam_drv_private_jr {
 	struct caam_job_ring __iomem *rregs;	/* JobR's register space */
 	struct tasklet_struct irqtask;
 	int irq;			/* One per queue */
-	int assign;			/* busy/free */
 
 	/* Job ring info */
 	int ringsize;	/* Size of rings (assume input = output) */
@@ -68,7 +64,6 @@ struct caam_drv_private {
 
 	struct device *dev;
 	struct device **jrdev; /* Alloc'ed array per sub-device */
-	spinlock_t jr_alloc_lock;
 	struct platform_device *pdev;
 
 	/* Physical-presence section */
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index b4aa773e..105ba4d 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -126,72 +126,6 @@ static void caam_jr_dequeue(unsigned long devarg)
 }
 
 /**
- * caam_jr_register() - Alloc a ring for someone to use as needed. Returns
- * an ordinal of the rings allocated, else returns -ENODEV if no rings
- * are available.
- * @ctrldev: points to the controller level dev (parent) that
- *           owns rings available for use.
- * @dev:     points to where a pointer to the newly allocated queue's
- *           dev can be written to if successful.
- **/
-int caam_jr_register(struct device *ctrldev, struct device **rdev)
-{
-	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
-	struct caam_drv_private_jr *jrpriv = NULL;
-	int ring;
-
-	/* Lock, if free ring - assign, unlock */
-	spin_lock(&ctrlpriv->jr_alloc_lock);
-	for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
-		jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]);
-		if (jrpriv->assign == JOBR_UNASSIGNED) {
-			jrpriv->assign = JOBR_ASSIGNED;
-			*rdev = ctrlpriv->jrdev[ring];
-			spin_unlock(&ctrlpriv->jr_alloc_lock);
-			return ring;
-		}
-	}
-
-	/* If assigned, write dev where caller needs it */
-	spin_unlock(&ctrlpriv->jr_alloc_lock);
-	*rdev = NULL;
-
-	return -ENODEV;
-}
-EXPORT_SYMBOL(caam_jr_register);
-
-/**
- * caam_jr_deregister() - Deregister an API and release the queue.
- * Returns 0 if OK, -EBUSY if queue still contains pending entries
- * or unprocessed results at the time of the call
- * @dev     - points to the dev that identifies the queue to
- *            be released.
- **/
-int caam_jr_deregister(struct device *rdev)
-{
-	struct caam_drv_private_jr *jrpriv = dev_get_drvdata(rdev);
-	struct caam_drv_private *ctrlpriv;
-
-	/* Get the owning controller's private space */
-	ctrlpriv = dev_get_drvdata(jrpriv->parentdev);
-
-	/*
-	 * Make sure ring empty before release
-	 */
-	if (rd_reg32(&jrpriv->rregs->outring_used) ||
-	    (rd_reg32(&jrpriv->rregs->inpring_avail) != JOBR_DEPTH))
-		return -EBUSY;
-
-	/* Release ring */
-	spin_lock(&ctrlpriv->jr_alloc_lock);
-	jrpriv->assign = JOBR_UNASSIGNED;
-	spin_unlock(&ctrlpriv->jr_alloc_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(caam_jr_deregister);
-
-/**
  * caam_jr_enqueue() - Enqueue a job descriptor head. Returns 0 if OK,
  * -EBUSY if the queue is full, -EIO if it cannot map the caller's
  * descriptor.
@@ -379,7 +313,6 @@ static int caam_jr_init(struct device *dev)
 		  (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
 		  (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
 
-	jrp->assign = JOBR_UNASSIGNED;
 	return 0;
 }
 
diff --git a/drivers/crypto/caam/jr.h b/drivers/crypto/caam/jr.h
index c23df39..9d8741a 100644
--- a/drivers/crypto/caam/jr.h
+++ b/drivers/crypto/caam/jr.h
@@ -8,8 +8,6 @@
 #define JR_H
 
 /* Prototypes for backend-level services exposed to APIs */
-int caam_jr_register(struct device *ctrldev, struct device **rdev);
-int caam_jr_deregister(struct device *rdev);
 int caam_jr_enqueue(struct device *dev, u32 *desc,
 		    void (*cbk)(struct device *dev, u32 *desc, u32 status,
 				void *areq),
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index c09142f..4455396 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -341,6 +341,8 @@ struct caam_ctrl {
 #define MCFGR_DMA_RESET		0x10000000
 #define MCFGR_LONG_PTR		0x00010000 /* Use >32-bit desc addressing */
 #define SCFGR_RDBENABLE		0x00000400
+#define DECORR_RQD0ENABLE	0x00000001 /* Enable DECO0 for direct access */
+#define DECORR_DEN0		0x00010000 /* DECO0 available for access*/
 
 /* AXI read cache control */
 #define MCFGR_ARCACHE_SHIFT	12
@@ -703,9 +705,16 @@ struct caam_deco {
 	struct deco_sg_table sctr_tbl[4];	/* DxSTR - Scatter Tables */
 	u32 rsvd29[48];
 	u32 descbuf[64];	/* DxDESB - Descriptor buffer */
-	u32 rsvd30[320];
+	u32 rscvd30[193];
+	u32 desc_dbg;		/* DxDDR - DECO Debug Register */
+	u32 rsvd31[126];
 };
 
+/* DECO DBG Register Valid Bit*/
+#define DECO_DBG_VALID		0x80000000
+#define DECO_JQCR_WHL		0x20000000
+#define DECO_JQCR_FOUR		0x10000000
+
 /*
  * Current top-level view of memory map is:
  *
@@ -733,6 +742,7 @@ struct caam_full {
 	u64 rsvd[512];
 	struct caam_assurance assure;
 	struct caam_queue_if qi;
+	struct caam_deco deco;
 };
 
 #endif /* REGS_H */
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 4bb6765..ae1ca8b2 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -44,7 +44,6 @@
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
 
-#define SHA1_MD5_BLOCK_SIZE		SHA1_BLOCK_SIZE
 #define MD5_DIGEST_SIZE			16
 
 #define DST_MAXBURST			16
@@ -54,7 +53,7 @@
 #define SHA_REG_DIN(dd, x)		((dd)->pdata->din_ofs + ((x) * 0x04))
 #define SHA_REG_DIGCNT(dd)		((dd)->pdata->digcnt_ofs)
 
-#define SHA_REG_ODIGEST(x)		(0x00 + ((x) * 0x04))
+#define SHA_REG_ODIGEST(dd, x)		((dd)->pdata->odigest_ofs + (x * 0x04))
 
 #define SHA_REG_CTRL			0x18
 #define SHA_REG_CTRL_LENGTH		(0xFFFFFFFF << 5)
@@ -75,18 +74,21 @@
 #define SHA_REG_SYSSTATUS(dd)		((dd)->pdata->sysstatus_ofs)
 #define SHA_REG_SYSSTATUS_RESETDONE	(1 << 0)
 
-#define SHA_REG_MODE			0x44
+#define SHA_REG_MODE(dd)		((dd)->pdata->mode_ofs)
 #define SHA_REG_MODE_HMAC_OUTER_HASH	(1 << 7)
 #define SHA_REG_MODE_HMAC_KEY_PROC	(1 << 5)
 #define SHA_REG_MODE_CLOSE_HASH		(1 << 4)
 #define SHA_REG_MODE_ALGO_CONSTANT	(1 << 3)
-#define SHA_REG_MODE_ALGO_MASK		(3 << 1)
-#define		SHA_REG_MODE_ALGO_MD5_128	(0 << 1)
-#define		SHA_REG_MODE_ALGO_SHA1_160	(1 << 1)
-#define		SHA_REG_MODE_ALGO_SHA2_224	(2 << 1)
-#define		SHA_REG_MODE_ALGO_SHA2_256	(3 << 1)
 
-#define SHA_REG_LENGTH			0x48
+#define SHA_REG_MODE_ALGO_MASK		(7 << 0)
+#define SHA_REG_MODE_ALGO_MD5_128	(0 << 1)
+#define SHA_REG_MODE_ALGO_SHA1_160	(1 << 1)
+#define SHA_REG_MODE_ALGO_SHA2_224	(2 << 1)
+#define SHA_REG_MODE_ALGO_SHA2_256	(3 << 1)
+#define SHA_REG_MODE_ALGO_SHA2_384	(1 << 0)
+#define SHA_REG_MODE_ALGO_SHA2_512	(3 << 0)
+
+#define SHA_REG_LENGTH(dd)		((dd)->pdata->length_ofs)
 
 #define SHA_REG_IRQSTATUS		0x118
 #define SHA_REG_IRQSTATUS_CTX_RDY	(1 << 3)
@@ -117,18 +119,16 @@
 #define FLAGS_SG		17
 
 #define FLAGS_MODE_SHIFT	18
-#define FLAGS_MODE_MASK		(SHA_REG_MODE_ALGO_MASK			\
-					<< (FLAGS_MODE_SHIFT - 1))
-#define		FLAGS_MODE_MD5		(SHA_REG_MODE_ALGO_MD5_128	\
-						<< (FLAGS_MODE_SHIFT - 1))
-#define		FLAGS_MODE_SHA1		(SHA_REG_MODE_ALGO_SHA1_160	\
-						<< (FLAGS_MODE_SHIFT - 1))
-#define		FLAGS_MODE_SHA224	(SHA_REG_MODE_ALGO_SHA2_224	\
-						<< (FLAGS_MODE_SHIFT - 1))
-#define		FLAGS_MODE_SHA256	(SHA_REG_MODE_ALGO_SHA2_256	\
-						<< (FLAGS_MODE_SHIFT - 1))
-#define FLAGS_HMAC		20
-#define FLAGS_ERROR		21
+#define FLAGS_MODE_MASK		(SHA_REG_MODE_ALGO_MASK	<< FLAGS_MODE_SHIFT)
+#define FLAGS_MODE_MD5		(SHA_REG_MODE_ALGO_MD5_128 << FLAGS_MODE_SHIFT)
+#define FLAGS_MODE_SHA1		(SHA_REG_MODE_ALGO_SHA1_160 << FLAGS_MODE_SHIFT)
+#define FLAGS_MODE_SHA224	(SHA_REG_MODE_ALGO_SHA2_224 << FLAGS_MODE_SHIFT)
+#define FLAGS_MODE_SHA256	(SHA_REG_MODE_ALGO_SHA2_256 << FLAGS_MODE_SHIFT)
+#define FLAGS_MODE_SHA384	(SHA_REG_MODE_ALGO_SHA2_384 << FLAGS_MODE_SHIFT)
+#define FLAGS_MODE_SHA512	(SHA_REG_MODE_ALGO_SHA2_512 << FLAGS_MODE_SHIFT)
+
+#define FLAGS_HMAC		21
+#define FLAGS_ERROR		22
 
 #define OP_UPDATE		1
 #define OP_FINAL		2
@@ -145,7 +145,7 @@ struct omap_sham_reqctx {
 	unsigned long		flags;
 	unsigned long		op;
 
-	u8			digest[SHA256_DIGEST_SIZE] OMAP_ALIGNED;
+	u8			digest[SHA512_DIGEST_SIZE] OMAP_ALIGNED;
 	size_t			digcnt;
 	size_t			bufcnt;
 	size_t			buflen;
@@ -162,8 +162,8 @@ struct omap_sham_reqctx {
 
 struct omap_sham_hmac_ctx {
 	struct crypto_shash	*shash;
-	u8			ipad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
-	u8			opad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
+	u8			ipad[SHA512_BLOCK_SIZE] OMAP_ALIGNED;
+	u8			opad[SHA512_BLOCK_SIZE] OMAP_ALIGNED;
 };
 
 struct omap_sham_ctx {
@@ -205,6 +205,8 @@ struct omap_sham_pdata {
 	u32		rev_ofs;
 	u32		mask_ofs;
 	u32		sysstatus_ofs;
+	u32		mode_ofs;
+	u32		length_ofs;
 
 	u32		major_mask;
 	u32		major_shift;
@@ -306,9 +308,9 @@ static void omap_sham_copy_hash_omap4(struct ahash_request *req, int out)
 		for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
 			if (out)
 				opad[i] = omap_sham_read(dd,
-						SHA_REG_ODIGEST(i));
+						SHA_REG_ODIGEST(dd, i));
 			else
-				omap_sham_write(dd, SHA_REG_ODIGEST(i),
+				omap_sham_write(dd, SHA_REG_ODIGEST(dd, i),
 						opad[i]);
 		}
 	}
@@ -342,6 +344,12 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
 	case FLAGS_MODE_SHA256:
 		d = SHA256_DIGEST_SIZE / sizeof(u32);
 		break;
+	case FLAGS_MODE_SHA384:
+		d = SHA384_DIGEST_SIZE / sizeof(u32);
+		break;
+	case FLAGS_MODE_SHA512:
+		d = SHA512_DIGEST_SIZE / sizeof(u32);
+		break;
 	default:
 		d = 0;
 	}
@@ -404,6 +412,30 @@ static int omap_sham_poll_irq_omap2(struct omap_sham_dev *dd)
 	return omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY);
 }
 
+static int get_block_size(struct omap_sham_reqctx *ctx)
+{
+	int d;
+
+	switch (ctx->flags & FLAGS_MODE_MASK) {
+	case FLAGS_MODE_MD5:
+	case FLAGS_MODE_SHA1:
+		d = SHA1_BLOCK_SIZE;
+		break;
+	case FLAGS_MODE_SHA224:
+	case FLAGS_MODE_SHA256:
+		d = SHA256_BLOCK_SIZE;
+		break;
+	case FLAGS_MODE_SHA384:
+	case FLAGS_MODE_SHA512:
+		d = SHA512_BLOCK_SIZE;
+		break;
+	default:
+		d = 0;
+	}
+
+	return d;
+}
+
 static void omap_sham_write_n(struct omap_sham_dev *dd, u32 offset,
 				    u32 *value, int count)
 {
@@ -422,20 +454,24 @@ static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
 	 * CLOSE_HASH only for the last one. Note that flags mode bits
 	 * correspond to algorithm encoding in mode register.
 	 */
-	val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT - 1);
+	val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT);
 	if (!ctx->digcnt) {
 		struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
 		struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
 		struct omap_sham_hmac_ctx *bctx = tctx->base;
+		int bs, nr_dr;
 
 		val |= SHA_REG_MODE_ALGO_CONSTANT;
 
 		if (ctx->flags & BIT(FLAGS_HMAC)) {
+			bs = get_block_size(ctx);
+			nr_dr = bs / (2 * sizeof(u32));
 			val |= SHA_REG_MODE_HMAC_KEY_PROC;
-			omap_sham_write_n(dd, SHA_REG_ODIGEST(0),
-					  (u32 *)bctx->ipad,
-					  SHA1_BLOCK_SIZE / sizeof(u32));
-			ctx->digcnt += SHA1_BLOCK_SIZE;
+			omap_sham_write_n(dd, SHA_REG_ODIGEST(dd, 0),
+					  (u32 *)bctx->ipad, nr_dr);
+			omap_sham_write_n(dd, SHA_REG_IDIGEST(dd, 0),
+					  (u32 *)bctx->ipad + nr_dr, nr_dr);
+			ctx->digcnt += bs;
 		}
 	}
 
@@ -451,7 +487,7 @@ static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
 	       SHA_REG_MODE_HMAC_KEY_PROC;
 
 	dev_dbg(dd->dev, "ctrl: %08x, flags: %08lx\n", val, ctx->flags);
-	omap_sham_write_mask(dd, SHA_REG_MODE, val, mask);
+	omap_sham_write_mask(dd, SHA_REG_MODE(dd), val, mask);
 	omap_sham_write(dd, SHA_REG_IRQENA, SHA_REG_IRQENA_OUTPUT_RDY);
 	omap_sham_write_mask(dd, SHA_REG_MASK(dd),
 			     SHA_REG_MASK_IT_EN |
@@ -461,7 +497,7 @@ static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
 
 static void omap_sham_trigger_omap4(struct omap_sham_dev *dd, size_t length)
 {
-	omap_sham_write(dd, SHA_REG_LENGTH, length);
+	omap_sham_write(dd, SHA_REG_LENGTH(dd), length);
 }
 
 static int omap_sham_poll_irq_omap4(struct omap_sham_dev *dd)
@@ -666,14 +702,14 @@ static int omap_sham_update_dma_slow(struct omap_sham_dev *dd)
 /* Start address alignment */
 #define SG_AA(sg)	(IS_ALIGNED(sg->offset, sizeof(u32)))
 /* SHA1 block size alignment */
-#define SG_SA(sg)	(IS_ALIGNED(sg->length, SHA1_MD5_BLOCK_SIZE))
+#define SG_SA(sg, bs)	(IS_ALIGNED(sg->length, bs))
 
 static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 	unsigned int length, final, tail;
 	struct scatterlist *sg;
-	int ret;
+	int ret, bs;
 
 	if (!ctx->total)
 		return 0;
@@ -694,23 +730,24 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 			ctx->digcnt, ctx->bufcnt, ctx->total);
 
 	sg = ctx->sg;
+	bs = get_block_size(ctx);
 
 	if (!SG_AA(sg))
 		return omap_sham_update_dma_slow(dd);
 
-	if (!sg_is_last(sg) && !SG_SA(sg))
-		/* size is not SHA1_BLOCK_SIZE aligned */
+	if (!sg_is_last(sg) && !SG_SA(sg, bs))
+		/* size is not BLOCK_SIZE aligned */
 		return omap_sham_update_dma_slow(dd);
 
 	length = min(ctx->total, sg->length);
 
 	if (sg_is_last(sg)) {
 		if (!(ctx->flags & BIT(FLAGS_FINUP))) {
-			/* not last sg must be SHA1_MD5_BLOCK_SIZE aligned */
-			tail = length & (SHA1_MD5_BLOCK_SIZE - 1);
+			/* not last sg must be BLOCK_SIZE aligned */
+			tail = length & (bs - 1);
 			/* without finup() we need one block to close hash */
 			if (!tail)
-				tail = SHA1_MD5_BLOCK_SIZE;
+				tail = bs;
 			length -= tail;
 		}
 	}
@@ -773,6 +810,7 @@ static int omap_sham_init(struct ahash_request *req)
 	struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	struct omap_sham_dev *dd = NULL, *tmp;
+	int bs = 0;
 
 	spin_lock_bh(&sham.lock);
 	if (!tctx->dd) {
@@ -796,15 +834,27 @@ static int omap_sham_init(struct ahash_request *req)
 	switch (crypto_ahash_digestsize(tfm)) {
 	case MD5_DIGEST_SIZE:
 		ctx->flags |= FLAGS_MODE_MD5;
+		bs = SHA1_BLOCK_SIZE;
 		break;
 	case SHA1_DIGEST_SIZE:
 		ctx->flags |= FLAGS_MODE_SHA1;
+		bs = SHA1_BLOCK_SIZE;
 		break;
 	case SHA224_DIGEST_SIZE:
 		ctx->flags |= FLAGS_MODE_SHA224;
+		bs = SHA224_BLOCK_SIZE;
 		break;
 	case SHA256_DIGEST_SIZE:
 		ctx->flags |= FLAGS_MODE_SHA256;
+		bs = SHA256_BLOCK_SIZE;
+		break;
+	case SHA384_DIGEST_SIZE:
+		ctx->flags |= FLAGS_MODE_SHA384;
+		bs = SHA384_BLOCK_SIZE;
+		break;
+	case SHA512_DIGEST_SIZE:
+		ctx->flags |= FLAGS_MODE_SHA512;
+		bs = SHA512_BLOCK_SIZE;
 		break;
 	}
 
@@ -816,8 +866,8 @@ static int omap_sham_init(struct ahash_request *req)
 		if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
 			struct omap_sham_hmac_ctx *bctx = tctx->base;
 
-			memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
-			ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
+			memcpy(ctx->buffer, bctx->ipad, bs);
+			ctx->bufcnt = bs;
 		}
 
 		ctx->flags |= BIT(FLAGS_HMAC);
@@ -1006,6 +1056,7 @@ static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
 static int omap_sham_update(struct ahash_request *req)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	int bs = get_block_size(ctx);
 
 	if (!req->nbytes)
 		return 0;
@@ -1023,7 +1074,7 @@ static int omap_sham_update(struct ahash_request *req)
 			*/
 			omap_sham_append_sg(ctx);
 			return 0;
-		} else if (ctx->bufcnt + ctx->total <= SHA1_MD5_BLOCK_SIZE) {
+		} else if (ctx->bufcnt + ctx->total <= bs) {
 			/*
 			* faster to use CPU for short transfers
 			*/
@@ -1214,6 +1265,16 @@ static int omap_sham_cra_md5_init(struct crypto_tfm *tfm)
 	return omap_sham_cra_init_alg(tfm, "md5");
 }
 
+static int omap_sham_cra_sha384_init(struct crypto_tfm *tfm)
+{
+	return omap_sham_cra_init_alg(tfm, "sha384");
+}
+
+static int omap_sham_cra_sha512_init(struct crypto_tfm *tfm)
+{
+	return omap_sham_cra_init_alg(tfm, "sha512");
+}
+
 static void omap_sham_cra_exit(struct crypto_tfm *tfm)
 {
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm);
@@ -1422,6 +1483,101 @@ static struct ahash_alg algs_sha224_sha256[] = {
 },
 };
 
+static struct ahash_alg algs_sha384_sha512[] = {
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.halg.digestsize	= SHA384_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "sha384",
+		.cra_driver_name	= "omap-sha384",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA384_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
+		.cra_alignmask		= 0,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.halg.digestsize	= SHA512_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "sha512",
+		.cra_driver_name	= "omap-sha512",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA512_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
+		.cra_alignmask		= 0,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.setkey		= omap_sham_setkey,
+	.halg.digestsize	= SHA384_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "hmac(sha384)",
+		.cra_driver_name	= "omap-hmac-sha384",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA384_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
+					sizeof(struct omap_sham_hmac_ctx),
+		.cra_alignmask		= OMAP_ALIGN_MASK,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_sha384_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.setkey		= omap_sham_setkey,
+	.halg.digestsize	= SHA512_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "hmac(sha512)",
+		.cra_driver_name	= "omap-hmac-sha512",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA512_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
+					sizeof(struct omap_sham_hmac_ctx),
+		.cra_alignmask		= OMAP_ALIGN_MASK,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_sha512_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+};
+
 static void omap_sham_done_task(unsigned long data)
 {
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
@@ -1548,11 +1704,54 @@ static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
 	.poll_irq	= omap_sham_poll_irq_omap4,
 	.intr_hdlr	= omap_sham_irq_omap4,
 	.idigest_ofs	= 0x020,
+	.odigest_ofs	= 0x0,
 	.din_ofs	= 0x080,
 	.digcnt_ofs	= 0x040,
 	.rev_ofs	= 0x100,
 	.mask_ofs	= 0x110,
 	.sysstatus_ofs	= 0x114,
+	.mode_ofs	= 0x44,
+	.length_ofs	= 0x48,
+	.major_mask	= 0x0700,
+	.major_shift	= 8,
+	.minor_mask	= 0x003f,
+	.minor_shift	= 0,
+};
+
+static struct omap_sham_algs_info omap_sham_algs_info_omap5[] = {
+	{
+		.algs_list	= algs_sha1_md5,
+		.size		= ARRAY_SIZE(algs_sha1_md5),
+	},
+	{
+		.algs_list	= algs_sha224_sha256,
+		.size		= ARRAY_SIZE(algs_sha224_sha256),
+	},
+	{
+		.algs_list	= algs_sha384_sha512,
+		.size		= ARRAY_SIZE(algs_sha384_sha512),
+	},
+};
+
+static const struct omap_sham_pdata omap_sham_pdata_omap5 = {
+	.algs_info	= omap_sham_algs_info_omap5,
+	.algs_info_size	= ARRAY_SIZE(omap_sham_algs_info_omap5),
+	.flags		= BIT(FLAGS_AUTO_XOR),
+	.digest_size	= SHA512_DIGEST_SIZE,
+	.copy_hash	= omap_sham_copy_hash_omap4,
+	.write_ctrl	= omap_sham_write_ctrl_omap4,
+	.trigger	= omap_sham_trigger_omap4,
+	.poll_irq	= omap_sham_poll_irq_omap4,
+	.intr_hdlr	= omap_sham_irq_omap4,
+	.idigest_ofs	= 0x240,
+	.odigest_ofs	= 0x200,
+	.din_ofs	= 0x080,
+	.digcnt_ofs	= 0x280,
+	.rev_ofs	= 0x100,
+	.mask_ofs	= 0x110,
+	.sysstatus_ofs	= 0x114,
+	.mode_ofs	= 0x284,
+	.length_ofs	= 0x288,
 	.major_mask	= 0x0700,
 	.major_shift	= 8,
 	.minor_mask	= 0x003f,
@@ -1568,6 +1767,10 @@ static const struct of_device_id omap_sham_of_match[] = {
 		.compatible	= "ti,omap4-sham",
 		.data		= &omap_sham_pdata_omap4,
 	},
+	{
+		.compatible	= "ti,omap5-sham",
+		.data		= &omap_sham_pdata_omap5,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, omap_sham_of_match);
@@ -1667,7 +1870,7 @@ static int omap_sham_probe(struct platform_device *pdev)
 	int err, i, j;
 	u32 rev;
 
-	dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
+	dd = devm_kzalloc(dev, sizeof(struct omap_sham_dev), GFP_KERNEL);
 	if (dd == NULL) {
 		dev_err(dev, "unable to alloc data struct.\n");
 		err = -ENOMEM;
@@ -1684,20 +1887,21 @@ static int omap_sham_probe(struct platform_device *pdev)
 	err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) :
 			       omap_sham_get_res_pdev(dd, pdev, &res);
 	if (err)
-		goto res_err;
+		goto data_err;
 
 	dd->io_base = devm_ioremap_resource(dev, &res);
 	if (IS_ERR(dd->io_base)) {
 		err = PTR_ERR(dd->io_base);
-		goto res_err;
+		goto data_err;
 	}
 	dd->phys_base = res.start;
 
-	err = request_irq(dd->irq, dd->pdata->intr_hdlr, IRQF_TRIGGER_LOW,
-			  dev_name(dev), dd);
+	err = devm_request_irq(dev, dd->irq, dd->pdata->intr_hdlr,
+			       IRQF_TRIGGER_NONE, dev_name(dev), dd);
 	if (err) {
-		dev_err(dev, "unable to request irq.\n");
-		goto res_err;
+		dev_err(dev, "unable to request irq %d, err = %d\n",
+			dd->irq, err);
+		goto data_err;
 	}
 
 	dma_cap_zero(mask);
@@ -1709,7 +1913,7 @@ static int omap_sham_probe(struct platform_device *pdev)
 		dev_err(dev, "unable to obtain RX DMA engine channel %u\n",
 			dd->dma);
 		err = -ENXIO;
-		goto dma_err;
+		goto data_err;
 	}
 
 	dd->flags |= dd->pdata->flags;
@@ -1747,11 +1951,6 @@ err_algs:
 					&dd->pdata->algs_info[i].algs_list[j]);
 	pm_runtime_disable(dev);
 	dma_release_channel(dd->dma_lch);
-dma_err:
-	free_irq(dd->irq, dd);
-res_err:
-	kfree(dd);
-	dd = NULL;
 data_err:
 	dev_err(dev, "initialization failed.\n");
 
@@ -1776,9 +1975,6 @@ static int omap_sham_remove(struct platform_device *pdev)
 	tasklet_kill(&dd->done_task);
 	pm_runtime_disable(&pdev->dev);
 	dma_release_channel(dd->dma_lch);
-	free_irq(dd->irq, dd);
-	kfree(dd);
-	dd = NULL;
 
 	return 0;
 }
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 496ae6a..1c73f4f 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -11,6 +11,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) "hashX hashX: " fmt
+
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -35,8 +37,6 @@
 
 #include "hash_alg.h"
 
-#define DEV_DBG_NAME "hashX hashX:"
-
 static int hash_mode;
 module_param(hash_mode, int, 0);
 MODULE_PARM_DESC(hash_mode, "CPU or DMA mode. CPU = 0 (default), DMA = 1");
@@ -44,13 +44,13 @@ MODULE_PARM_DESC(hash_mode, "CPU or DMA mode. CPU = 0 (default), DMA = 1");
 /**
  * Pre-calculated empty message digests.
  */
-static u8 zero_message_hash_sha1[SHA1_DIGEST_SIZE] = {
+static const u8 zero_message_hash_sha1[SHA1_DIGEST_SIZE] = {
 	0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
 	0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
 	0xaf, 0xd8, 0x07, 0x09
 };
 
-static u8 zero_message_hash_sha256[SHA256_DIGEST_SIZE] = {
+static const u8 zero_message_hash_sha256[SHA256_DIGEST_SIZE] = {
 	0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
 	0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
 	0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
@@ -58,14 +58,14 @@ static u8 zero_message_hash_sha256[SHA256_DIGEST_SIZE] = {
 };
 
 /* HMAC-SHA1, no key */
-static u8 zero_message_hmac_sha1[SHA1_DIGEST_SIZE] = {
+static const u8 zero_message_hmac_sha1[SHA1_DIGEST_SIZE] = {
 	0xfb, 0xdb, 0x1d, 0x1b, 0x18, 0xaa, 0x6c, 0x08,
 	0x32, 0x4b, 0x7d, 0x64, 0xb7, 0x1f, 0xb7, 0x63,
 	0x70, 0x69, 0x0e, 0x1d
 };
 
 /* HMAC-SHA256, no key */
-static u8 zero_message_hmac_sha256[SHA256_DIGEST_SIZE] = {
+static const u8 zero_message_hmac_sha256[SHA256_DIGEST_SIZE] = {
 	0xb6, 0x13, 0x67, 0x9a, 0x08, 0x14, 0xd9, 0xec,
 	0x77, 0x2f, 0x95, 0xd7, 0x78, 0xc3, 0x5f, 0xc5,
 	0xff, 0x16, 0x97, 0xc4, 0x93, 0x71, 0x56, 0x53,
@@ -97,7 +97,7 @@ static struct hash_driver_data	driver_data;
  *
  */
 static void hash_messagepad(struct hash_device_data *device_data,
-		const u32 *message, u8 index_bytes);
+			    const u32 *message, u8 index_bytes);
 
 /**
  * release_hash_device - Releases a previously allocated hash device.
@@ -119,7 +119,7 @@ static void release_hash_device(struct hash_device_data *device_data)
 }
 
 static void hash_dma_setup_channel(struct hash_device_data *device_data,
-				struct device *dev)
+				   struct device *dev)
 {
 	struct hash_platform_data *platform_data = dev->platform_data;
 	struct dma_slave_config conf = {
@@ -127,7 +127,7 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data,
 		.dst_addr = device_data->phybase + HASH_DMA_FIFO,
 		.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
 		.dst_maxburst = 16,
-        };
+	};
 
 	dma_cap_zero(device_data->dma.mask);
 	dma_cap_set(DMA_SLAVE, device_data->dma.mask);
@@ -135,8 +135,8 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data,
 	device_data->dma.cfg_mem2hash = platform_data->mem_to_engine;
 	device_data->dma.chan_mem2hash =
 		dma_request_channel(device_data->dma.mask,
-				platform_data->dma_filter,
-				device_data->dma.cfg_mem2hash);
+				    platform_data->dma_filter,
+				    device_data->dma.cfg_mem2hash);
 
 	dmaengine_slave_config(device_data->dma.chan_mem2hash, &conf);
 
@@ -145,21 +145,21 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data,
 
 static void hash_dma_callback(void *data)
 {
-	struct hash_ctx *ctx = (struct hash_ctx *) data;
+	struct hash_ctx *ctx = data;
 
 	complete(&ctx->device->dma.complete);
 }
 
 static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg,
-		int len, enum dma_data_direction direction)
+				 int len, enum dma_data_direction direction)
 {
 	struct dma_async_tx_descriptor *desc = NULL;
 	struct dma_chan *channel = NULL;
 	dma_cookie_t cookie;
 
 	if (direction != DMA_TO_DEVICE) {
-		dev_err(ctx->device->dev, "[%s] Invalid DMA direction",
-				__func__);
+		dev_err(ctx->device->dev, "%s: Invalid DMA direction\n",
+			__func__);
 		return -EFAULT;
 	}
 
@@ -172,20 +172,19 @@ static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg,
 			direction);
 
 	if (!ctx->device->dma.sg_len) {
-		dev_err(ctx->device->dev,
-				"[%s]: Could not map the sg list (TO_DEVICE)",
-				__func__);
+		dev_err(ctx->device->dev, "%s: Could not map the sg list (TO_DEVICE)\n",
+			__func__);
 		return -EFAULT;
 	}
 
-	dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer "
-			"(TO_DEVICE)", __func__);
+	dev_dbg(ctx->device->dev, "%s: Setting up DMA for buffer (TO_DEVICE)\n",
+		__func__);
 	desc = dmaengine_prep_slave_sg(channel,
 			ctx->device->dma.sg, ctx->device->dma.sg_len,
 			direction, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
 	if (!desc) {
 		dev_err(ctx->device->dev,
-			"[%s]: device_prep_slave_sg() failed!", __func__);
+			"%s: device_prep_slave_sg() failed!\n", __func__);
 		return -EFAULT;
 	}
 
@@ -205,17 +204,16 @@ static void hash_dma_done(struct hash_ctx *ctx)
 	chan = ctx->device->dma.chan_mem2hash;
 	dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
 	dma_unmap_sg(chan->device->dev, ctx->device->dma.sg,
-			ctx->device->dma.sg_len, DMA_TO_DEVICE);
-
+		     ctx->device->dma.sg_len, DMA_TO_DEVICE);
 }
 
 static int hash_dma_write(struct hash_ctx *ctx,
-		struct scatterlist *sg, int len)
+			  struct scatterlist *sg, int len)
 {
 	int error = hash_set_dma_transfer(ctx, sg, len, DMA_TO_DEVICE);
 	if (error) {
-		dev_dbg(ctx->device->dev, "[%s]: hash_set_dma_transfer() "
-			"failed", __func__);
+		dev_dbg(ctx->device->dev,
+			"%s: hash_set_dma_transfer() failed\n", __func__);
 		return error;
 	}
 
@@ -245,19 +243,18 @@ static int get_empty_message_digest(
 	if (HASH_OPER_MODE_HASH == ctx->config.oper_mode) {
 		if (HASH_ALGO_SHA1 == ctx->config.algorithm) {
 			memcpy(zero_hash, &zero_message_hash_sha1[0],
-					SHA1_DIGEST_SIZE);
+			       SHA1_DIGEST_SIZE);
 			*zero_hash_size = SHA1_DIGEST_SIZE;
 			*zero_digest = true;
 		} else if (HASH_ALGO_SHA256 ==
 				ctx->config.algorithm) {
 			memcpy(zero_hash, &zero_message_hash_sha256[0],
-					SHA256_DIGEST_SIZE);
+			       SHA256_DIGEST_SIZE);
 			*zero_hash_size = SHA256_DIGEST_SIZE;
 			*zero_digest = true;
 		} else {
-			dev_err(device_data->dev, "[%s] "
-					"Incorrect algorithm!"
-					, __func__);
+			dev_err(device_data->dev, "%s: Incorrect algorithm!\n",
+				__func__);
 			ret = -EINVAL;
 			goto out;
 		}
@@ -265,25 +262,24 @@ static int get_empty_message_digest(
 		if (!ctx->keylen) {
 			if (HASH_ALGO_SHA1 == ctx->config.algorithm) {
 				memcpy(zero_hash, &zero_message_hmac_sha1[0],
-						SHA1_DIGEST_SIZE);
+				       SHA1_DIGEST_SIZE);
 				*zero_hash_size = SHA1_DIGEST_SIZE;
 				*zero_digest = true;
 			} else if (HASH_ALGO_SHA256 == ctx->config.algorithm) {
 				memcpy(zero_hash, &zero_message_hmac_sha256[0],
-						SHA256_DIGEST_SIZE);
+				       SHA256_DIGEST_SIZE);
 				*zero_hash_size = SHA256_DIGEST_SIZE;
 				*zero_digest = true;
 			} else {
-				dev_err(device_data->dev, "[%s] "
-						"Incorrect algorithm!"
-						, __func__);
+				dev_err(device_data->dev, "%s: Incorrect algorithm!\n",
+					__func__);
 				ret = -EINVAL;
 				goto out;
 			}
 		} else {
-			dev_dbg(device_data->dev, "[%s] Continue hash "
-					"calculation, since hmac key avalable",
-					__func__);
+			dev_dbg(device_data->dev,
+				"%s: Continue hash calculation, since hmac key available\n",
+				__func__);
 		}
 	}
 out:
@@ -299,9 +295,8 @@ out:
  * This function request for disabling power (regulator) and clock,
  * and could also save current hw state.
  */
-static int hash_disable_power(
-		struct hash_device_data *device_data,
-		bool			save_device_state)
+static int hash_disable_power(struct hash_device_data *device_data,
+			      bool save_device_state)
 {
 	int ret = 0;
 	struct device *dev = device_data->dev;
@@ -319,7 +314,7 @@ static int hash_disable_power(
 	clk_disable(device_data->clk);
 	ret = regulator_disable(device_data->regulator);
 	if (ret)
-		dev_err(dev, "[%s] regulator_disable() failed!", __func__);
+		dev_err(dev, "%s: regulator_disable() failed!\n", __func__);
 
 	device_data->power_state = false;
 
@@ -337,9 +332,8 @@ out:
  * This function request for enabling power (regulator) and clock,
  * and could also restore a previously saved hw state.
  */
-static int hash_enable_power(
-		struct hash_device_data *device_data,
-		bool			restore_device_state)
+static int hash_enable_power(struct hash_device_data *device_data,
+			     bool restore_device_state)
 {
 	int ret = 0;
 	struct device *dev = device_data->dev;
@@ -348,14 +342,13 @@ static int hash_enable_power(
 	if (!device_data->power_state) {
 		ret = regulator_enable(device_data->regulator);
 		if (ret) {
-			dev_err(dev, "[%s]: regulator_enable() failed!",
-					__func__);
+			dev_err(dev, "%s: regulator_enable() failed!\n",
+				__func__);
 			goto out;
 		}
 		ret = clk_enable(device_data->clk);
 		if (ret) {
-			dev_err(dev, "[%s]: clk_enable() failed!",
-					__func__);
+			dev_err(dev, "%s: clk_enable() failed!\n", __func__);
 			ret = regulator_disable(
 					device_data->regulator);
 			goto out;
@@ -366,8 +359,7 @@ static int hash_enable_power(
 	if (device_data->restore_dev_state) {
 		if (restore_device_state) {
 			device_data->restore_dev_state = false;
-			hash_resume_state(device_data,
-				&device_data->state);
+			hash_resume_state(device_data, &device_data->state);
 		}
 	}
 out:
@@ -447,7 +439,7 @@ static int hash_get_device_data(struct hash_ctx *ctx,
  * spec or due to a bug in the hw.
  */
 static void hash_hw_write_key(struct hash_device_data *device_data,
-		const u8 *key, unsigned int keylen)
+			      const u8 *key, unsigned int keylen)
 {
 	u32 word = 0;
 	int nwords = 1;
@@ -491,14 +483,14 @@ static void hash_hw_write_key(struct hash_device_data *device_data,
  * calculation.
  */
 static int init_hash_hw(struct hash_device_data *device_data,
-		struct hash_ctx *ctx)
+			struct hash_ctx *ctx)
 {
 	int ret = 0;
 
 	ret = hash_setconfiguration(device_data, &ctx->config);
 	if (ret) {
-		dev_err(device_data->dev, "[%s] hash_setconfiguration() "
-				"failed!", __func__);
+		dev_err(device_data->dev, "%s: hash_setconfiguration() failed!\n",
+			__func__);
 		return ret;
 	}
 
@@ -528,9 +520,8 @@ static int hash_get_nents(struct scatterlist *sg, int size, bool *aligned)
 		size -= sg->length;
 
 		/* hash_set_dma_transfer will align last nent */
-		if ((aligned && !IS_ALIGNED(sg->offset, HASH_DMA_ALIGN_SIZE))
-			|| (!IS_ALIGNED(sg->length, HASH_DMA_ALIGN_SIZE) &&
-				size > 0))
+		if ((aligned && !IS_ALIGNED(sg->offset, HASH_DMA_ALIGN_SIZE)) ||
+		    (!IS_ALIGNED(sg->length, HASH_DMA_ALIGN_SIZE) && size > 0))
 			aligned_data = false;
 
 		sg = sg_next(sg);
@@ -585,21 +576,17 @@ static int hash_init(struct ahash_request *req)
 		if (req->nbytes < HASH_DMA_ALIGN_SIZE) {
 			req_ctx->dma_mode = false; /* Don't use DMA */
 
-			pr_debug(DEV_DBG_NAME " [%s] DMA mode, but direct "
-					"to CPU mode for data size < %d",
-					__func__, HASH_DMA_ALIGN_SIZE);
+			pr_debug("%s: DMA mode, but direct to CPU mode for data size < %d\n",
+				 __func__, HASH_DMA_ALIGN_SIZE);
 		} else {
 			if (req->nbytes >= HASH_DMA_PERFORMANCE_MIN_SIZE &&
-					hash_dma_valid_data(req->src,
-						req->nbytes)) {
+			    hash_dma_valid_data(req->src, req->nbytes)) {
 				req_ctx->dma_mode = true;
 			} else {
 				req_ctx->dma_mode = false;
-				pr_debug(DEV_DBG_NAME " [%s] DMA mode, but use"
-						" CPU mode for datalength < %d"
-						" or non-aligned data, except "
-						"in last nent", __func__,
-						HASH_DMA_PERFORMANCE_MIN_SIZE);
+				pr_debug("%s: DMA mode, but use CPU mode for datalength < %d or non-aligned data, except in last nent\n",
+					 __func__,
+					 HASH_DMA_PERFORMANCE_MIN_SIZE);
 			}
 		}
 	}
@@ -614,9 +601,8 @@ static int hash_init(struct ahash_request *req)
  *			the HASH hardware.
  *
  */
-static void hash_processblock(
-		struct hash_device_data *device_data,
-		const u32 *message, int length)
+static void hash_processblock(struct hash_device_data *device_data,
+			      const u32 *message, int length)
 {
 	int len = length / HASH_BYTES_PER_WORD;
 	/*
@@ -641,7 +627,7 @@ static void hash_processblock(
  *
  */
 static void hash_messagepad(struct hash_device_data *device_data,
-		const u32 *message, u8 index_bytes)
+			    const u32 *message, u8 index_bytes)
 {
 	int nwords = 1;
 
@@ -666,15 +652,13 @@ static void hash_messagepad(struct hash_device_data *device_data,
 
 	/* num_of_bytes == 0 => NBLW <- 0 (32 bits valid in DATAIN) */
 	HASH_SET_NBLW(index_bytes * 8);
-	dev_dbg(device_data->dev, "[%s] DIN=0x%08x NBLW=%d", __func__,
-			readl_relaxed(&device_data->base->din),
-			(int)(readl_relaxed(&device_data->base->str) &
-				HASH_STR_NBLW_MASK));
+	dev_dbg(device_data->dev, "%s: DIN=0x%08x NBLW=%lu\n",
+		__func__, readl_relaxed(&device_data->base->din),
+		readl_relaxed(&device_data->base->str) & HASH_STR_NBLW_MASK);
 	HASH_SET_DCAL;
-	dev_dbg(device_data->dev, "[%s] after dcal -> DIN=0x%08x NBLW=%d",
-			__func__, readl_relaxed(&device_data->base->din),
-			(int)(readl_relaxed(&device_data->base->str) &
-				HASH_STR_NBLW_MASK));
+	dev_dbg(device_data->dev, "%s: after dcal -> DIN=0x%08x NBLW=%lu\n",
+		__func__, readl_relaxed(&device_data->base->din),
+		readl_relaxed(&device_data->base->str) & HASH_STR_NBLW_MASK);
 
 	while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK)
 		cpu_relax();
@@ -704,7 +688,7 @@ static void hash_incrementlength(struct hash_req_ctx *ctx, u32 incr)
  * @config:		Pointer to a configuration structure.
  */
 int hash_setconfiguration(struct hash_device_data *device_data,
-		struct hash_config *config)
+			  struct hash_config *config)
 {
 	int ret = 0;
 
@@ -731,8 +715,8 @@ int hash_setconfiguration(struct hash_device_data *device_data,
 		break;
 
 	default:
-		dev_err(device_data->dev, "[%s] Incorrect algorithm.",
-				__func__);
+		dev_err(device_data->dev, "%s: Incorrect algorithm\n",
+			__func__);
 		return -EPERM;
 	}
 
@@ -744,23 +728,22 @@ int hash_setconfiguration(struct hash_device_data *device_data,
 		HASH_CLEAR_BITS(&device_data->base->cr,
 				HASH_CR_MODE_MASK);
 	else if (HASH_OPER_MODE_HMAC == config->oper_mode) {
-		HASH_SET_BITS(&device_data->base->cr,
-				HASH_CR_MODE_MASK);
+		HASH_SET_BITS(&device_data->base->cr, HASH_CR_MODE_MASK);
 		if (device_data->current_ctx->keylen > HASH_BLOCK_SIZE) {
 			/* Truncate key to blocksize */
-			dev_dbg(device_data->dev, "[%s] LKEY set", __func__);
+			dev_dbg(device_data->dev, "%s: LKEY set\n", __func__);
 			HASH_SET_BITS(&device_data->base->cr,
-					HASH_CR_LKEY_MASK);
+				      HASH_CR_LKEY_MASK);
 		} else {
-			dev_dbg(device_data->dev, "[%s] LKEY cleared",
-					__func__);
+			dev_dbg(device_data->dev, "%s: LKEY cleared\n",
+				__func__);
 			HASH_CLEAR_BITS(&device_data->base->cr,
 					HASH_CR_LKEY_MASK);
 		}
 	} else {	/* Wrong hash mode */
 		ret = -EPERM;
-		dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
-				__func__);
+		dev_err(device_data->dev, "%s: HASH_INVALID_PARAMETER!\n",
+			__func__);
 	}
 	return ret;
 }
@@ -793,8 +776,9 @@ void hash_begin(struct hash_device_data *device_data, struct hash_ctx *ctx)
 }
 
 static int hash_process_data(struct hash_device_data *device_data,
-		struct hash_ctx *ctx, struct hash_req_ctx *req_ctx,
-		int msg_length, u8 *data_buffer, u8 *buffer, u8 *index)
+			     struct hash_ctx *ctx, struct hash_req_ctx *req_ctx,
+			     int msg_length, u8 *data_buffer, u8 *buffer,
+			     u8 *index)
 {
 	int ret = 0;
 	u32 count;
@@ -809,24 +793,23 @@ static int hash_process_data(struct hash_device_data *device_data,
 			msg_length = 0;
 		} else {
 			if (req_ctx->updated) {
-
 				ret = hash_resume_state(device_data,
 						&device_data->state);
 				memmove(req_ctx->state.buffer,
-						device_data->state.buffer,
-						HASH_BLOCK_SIZE / sizeof(u32));
+					device_data->state.buffer,
+					HASH_BLOCK_SIZE / sizeof(u32));
 				if (ret) {
-					dev_err(device_data->dev, "[%s] "
-							"hash_resume_state()"
-							" failed!", __func__);
+					dev_err(device_data->dev,
+						"%s: hash_resume_state() failed!\n",
+						__func__);
 					goto out;
 				}
 			} else {
 				ret = init_hash_hw(device_data, ctx);
 				if (ret) {
-					dev_err(device_data->dev, "[%s] "
-							"init_hash_hw()"
-							" failed!", __func__);
+					dev_err(device_data->dev,
+						"%s: init_hash_hw() failed!\n",
+						__func__);
 					goto out;
 				}
 				req_ctx->updated = 1;
@@ -838,22 +821,21 @@ static int hash_process_data(struct hash_device_data *device_data,
 			 * HW peripheral, otherwise we first copy data
 			 * to a local buffer
 			 */
-			if ((0 == (((u32)data_buffer) % 4))
-					&& (0 == *index))
+			if ((0 == (((u32)data_buffer) % 4)) &&
+			    (0 == *index))
 				hash_processblock(device_data,
-						(const u32 *)
-						data_buffer, HASH_BLOCK_SIZE);
+						  (const u32 *)data_buffer,
+						  HASH_BLOCK_SIZE);
 			else {
-				for (count = 0; count <
-						(u32)(HASH_BLOCK_SIZE -
-							*index);
-						count++) {
+				for (count = 0;
+				     count < (u32)(HASH_BLOCK_SIZE - *index);
+				     count++) {
 					buffer[*index + count] =
 						*(data_buffer + count);
 				}
 				hash_processblock(device_data,
-						(const u32 *)buffer,
-						HASH_BLOCK_SIZE);
+						  (const u32 *)buffer,
+						  HASH_BLOCK_SIZE);
 			}
 			hash_incrementlength(req_ctx, HASH_BLOCK_SIZE);
 			data_buffer += (HASH_BLOCK_SIZE - *index);
@@ -865,12 +847,11 @@ static int hash_process_data(struct hash_device_data *device_data,
 					&device_data->state);
 
 			memmove(device_data->state.buffer,
-					req_ctx->state.buffer,
-					HASH_BLOCK_SIZE / sizeof(u32));
+				req_ctx->state.buffer,
+				HASH_BLOCK_SIZE / sizeof(u32));
 			if (ret) {
-				dev_err(device_data->dev, "[%s] "
-						"hash_save_state()"
-						" failed!", __func__);
+				dev_err(device_data->dev, "%s: hash_save_state() failed!\n",
+					__func__);
 				goto out;
 			}
 		}
@@ -898,25 +879,24 @@ static int hash_dma_final(struct ahash_request *req)
 	if (ret)
 		return ret;
 
-	dev_dbg(device_data->dev, "[%s] (ctx=0x%x)!", __func__, (u32) ctx);
+	dev_dbg(device_data->dev, "%s: (ctx=0x%x)!\n", __func__, (u32) ctx);
 
 	if (req_ctx->updated) {
 		ret = hash_resume_state(device_data, &device_data->state);
 
 		if (ret) {
-			dev_err(device_data->dev, "[%s] hash_resume_state() "
-					"failed!", __func__);
+			dev_err(device_data->dev, "%s: hash_resume_state() failed!\n",
+				__func__);
 			goto out;
 		}
-
 	}
 
 	if (!req_ctx->updated) {
 		ret = hash_setconfiguration(device_data, &ctx->config);
 		if (ret) {
-			dev_err(device_data->dev, "[%s] "
-					"hash_setconfiguration() failed!",
-					__func__);
+			dev_err(device_data->dev,
+				"%s: hash_setconfiguration() failed!\n",
+				__func__);
 			goto out;
 		}
 
@@ -926,9 +906,9 @@ static int hash_dma_final(struct ahash_request *req)
 					HASH_CR_DMAE_MASK);
 		} else {
 			HASH_SET_BITS(&device_data->base->cr,
-					HASH_CR_DMAE_MASK);
+				      HASH_CR_DMAE_MASK);
 			HASH_SET_BITS(&device_data->base->cr,
-					HASH_CR_PRIVN_MASK);
+				      HASH_CR_PRIVN_MASK);
 		}
 
 		HASH_INITIALIZE;
@@ -944,16 +924,16 @@ static int hash_dma_final(struct ahash_request *req)
 	/* Store the nents in the dma struct. */
 	ctx->device->dma.nents = hash_get_nents(req->src, req->nbytes, NULL);
 	if (!ctx->device->dma.nents) {
-		dev_err(device_data->dev, "[%s] "
-				"ctx->device->dma.nents = 0", __func__);
+		dev_err(device_data->dev, "%s: ctx->device->dma.nents = 0\n",
+			__func__);
 		ret = ctx->device->dma.nents;
 		goto out;
 	}
 
 	bytes_written = hash_dma_write(ctx, req->src, req->nbytes);
 	if (bytes_written != req->nbytes) {
-		dev_err(device_data->dev, "[%s] "
-				"hash_dma_write() failed!", __func__);
+		dev_err(device_data->dev, "%s: hash_dma_write() failed!\n",
+			__func__);
 		ret = bytes_written;
 		goto out;
 	}
@@ -968,8 +948,8 @@ static int hash_dma_final(struct ahash_request *req)
 		unsigned int keylen = ctx->keylen;
 		u8 *key = ctx->key;
 
-		dev_dbg(device_data->dev, "[%s] keylen: %d", __func__,
-				ctx->keylen);
+		dev_dbg(device_data->dev, "%s: keylen: %d\n",
+			__func__, ctx->keylen);
 		hash_hw_write_key(device_data, key, keylen);
 	}
 
@@ -1004,14 +984,14 @@ static int hash_hw_final(struct ahash_request *req)
 	if (ret)
 		return ret;
 
-	dev_dbg(device_data->dev, "[%s] (ctx=0x%x)!", __func__, (u32) ctx);
+	dev_dbg(device_data->dev, "%s: (ctx=0x%x)!\n", __func__, (u32) ctx);
 
 	if (req_ctx->updated) {
 		ret = hash_resume_state(device_data, &device_data->state);
 
 		if (ret) {
-			dev_err(device_data->dev, "[%s] hash_resume_state() "
-					"failed!", __func__);
+			dev_err(device_data->dev,
+				"%s: hash_resume_state() failed!\n", __func__);
 			goto out;
 		}
 	} else if (req->nbytes == 0 && ctx->keylen == 0) {
@@ -1025,31 +1005,33 @@ static int hash_hw_final(struct ahash_request *req)
 		ret = get_empty_message_digest(device_data, &zero_hash[0],
 				&zero_hash_size, &zero_digest);
 		if (!ret && likely(zero_hash_size == ctx->digestsize) &&
-				zero_digest) {
+		    zero_digest) {
 			memcpy(req->result, &zero_hash[0], ctx->digestsize);
 			goto out;
 		} else if (!ret && !zero_digest) {
-			dev_dbg(device_data->dev, "[%s] HMAC zero msg with "
-					"key, continue...", __func__);
+			dev_dbg(device_data->dev,
+				"%s: HMAC zero msg with key, continue...\n",
+				__func__);
 		} else {
-			dev_err(device_data->dev, "[%s] ret=%d, or wrong "
-					"digest size? %s", __func__, ret,
-					(zero_hash_size == ctx->digestsize) ?
-					"true" : "false");
+			dev_err(device_data->dev,
+				"%s: ret=%d, or wrong digest size? %s\n",
+				__func__, ret,
+				zero_hash_size == ctx->digestsize ?
+				"true" : "false");
 			/* Return error */
 			goto out;
 		}
 	} else if (req->nbytes == 0 && ctx->keylen > 0) {
-		dev_err(device_data->dev, "[%s] Empty message with "
-				"keylength > 0, NOT supported.", __func__);
+		dev_err(device_data->dev, "%s: Empty message with keylength > 0, NOT supported\n",
+			__func__);
 		goto out;
 	}
 
 	if (!req_ctx->updated) {
 		ret = init_hash_hw(device_data, ctx);
 		if (ret) {
-			dev_err(device_data->dev, "[%s] init_hash_hw() "
-					"failed!", __func__);
+			dev_err(device_data->dev,
+				"%s: init_hash_hw() failed!\n", __func__);
 			goto out;
 		}
 	}
@@ -1067,8 +1049,8 @@ static int hash_hw_final(struct ahash_request *req)
 		unsigned int keylen = ctx->keylen;
 		u8 *key = ctx->key;
 
-		dev_dbg(device_data->dev, "[%s] keylen: %d", __func__,
-				ctx->keylen);
+		dev_dbg(device_data->dev, "%s: keylen: %d\n",
+			__func__, ctx->keylen);
 		hash_hw_write_key(device_data, key, keylen);
 	}
 
@@ -1115,10 +1097,8 @@ int hash_hw_update(struct ahash_request *req)
 	/* Check if ctx->state.length + msg_length
 	   overflows */
 	if (msg_length > (req_ctx->state.length.low_word + msg_length) &&
-			HASH_HIGH_WORD_MAX_VAL ==
-			req_ctx->state.length.high_word) {
-		pr_err(DEV_DBG_NAME " [%s] HASH_MSG_LENGTH_OVERFLOW!",
-				__func__);
+	    HASH_HIGH_WORD_MAX_VAL == req_ctx->state.length.high_word) {
+		pr_err("%s: HASH_MSG_LENGTH_OVERFLOW!\n", __func__);
 		return -EPERM;
 	}
 
@@ -1133,8 +1113,8 @@ int hash_hw_update(struct ahash_request *req)
 				data_buffer, buffer, &index);
 
 		if (ret) {
-			dev_err(device_data->dev, "[%s] hash_internal_hw_"
-					"update() failed!", __func__);
+			dev_err(device_data->dev, "%s: hash_internal_hw_update() failed!\n",
+				__func__);
 			goto out;
 		}
 
@@ -1142,9 +1122,8 @@ int hash_hw_update(struct ahash_request *req)
 	}
 
 	req_ctx->state.index = index;
-	dev_dbg(device_data->dev, "[%s] indata length=%d, bin=%d))",
-			__func__, req_ctx->state.index,
-			req_ctx->state.bit_index);
+	dev_dbg(device_data->dev, "%s: indata length=%d, bin=%d\n",
+		__func__, req_ctx->state.index, req_ctx->state.bit_index);
 
 out:
 	release_hash_device(device_data);
@@ -1158,23 +1137,23 @@ out:
  * @device_state:	The state to be restored in the hash hardware
  */
 int hash_resume_state(struct hash_device_data *device_data,
-		const struct hash_state *device_state)
+		      const struct hash_state *device_state)
 {
 	u32 temp_cr;
 	s32 count;
 	int hash_mode = HASH_OPER_MODE_HASH;
 
 	if (NULL == device_state) {
-		dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
-				__func__);
+		dev_err(device_data->dev, "%s: HASH_INVALID_PARAMETER!\n",
+			__func__);
 		return -EPERM;
 	}
 
 	/* Check correctness of index and length members */
-	if (device_state->index > HASH_BLOCK_SIZE
-	    || (device_state->length.low_word % HASH_BLOCK_SIZE) != 0) {
-		dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
-				__func__);
+	if (device_state->index > HASH_BLOCK_SIZE ||
+	    (device_state->length.low_word % HASH_BLOCK_SIZE) != 0) {
+		dev_err(device_data->dev, "%s: HASH_INVALID_PARAMETER!\n",
+			__func__);
 		return -EPERM;
 	}
 
@@ -1198,7 +1177,7 @@ int hash_resume_state(struct hash_device_data *device_data,
 			break;
 
 		writel_relaxed(device_state->csr[count],
-				&device_data->base->csrx[count]);
+			       &device_data->base->csrx[count]);
 	}
 
 	writel_relaxed(device_state->csfull, &device_data->base->csfull);
@@ -1216,15 +1195,15 @@ int hash_resume_state(struct hash_device_data *device_data,
  * @device_state:	The strucure where the hardware state should be saved.
  */
 int hash_save_state(struct hash_device_data *device_data,
-		struct hash_state *device_state)
+		    struct hash_state *device_state)
 {
 	u32 temp_cr;
 	u32 count;
 	int hash_mode = HASH_OPER_MODE_HASH;
 
 	if (NULL == device_state) {
-		dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
-				__func__);
+		dev_err(device_data->dev, "%s: HASH_INVALID_PARAMETER!\n",
+			__func__);
 		return -ENOTSUPP;
 	}
 
@@ -1270,20 +1249,18 @@ int hash_save_state(struct hash_device_data *device_data,
 int hash_check_hw(struct hash_device_data *device_data)
 {
 	/* Checking Peripheral Ids  */
-	if (HASH_P_ID0 == readl_relaxed(&device_data->base->periphid0)
-		&& HASH_P_ID1 == readl_relaxed(&device_data->base->periphid1)
-		&& HASH_P_ID2 == readl_relaxed(&device_data->base->periphid2)
-		&& HASH_P_ID3 == readl_relaxed(&device_data->base->periphid3)
-		&& HASH_CELL_ID0 == readl_relaxed(&device_data->base->cellid0)
-		&& HASH_CELL_ID1 == readl_relaxed(&device_data->base->cellid1)
-		&& HASH_CELL_ID2 == readl_relaxed(&device_data->base->cellid2)
-		&& HASH_CELL_ID3 == readl_relaxed(&device_data->base->cellid3)
-	   ) {
+	if (HASH_P_ID0 == readl_relaxed(&device_data->base->periphid0) &&
+	    HASH_P_ID1 == readl_relaxed(&device_data->base->periphid1) &&
+	    HASH_P_ID2 == readl_relaxed(&device_data->base->periphid2) &&
+	    HASH_P_ID3 == readl_relaxed(&device_data->base->periphid3) &&
+	    HASH_CELL_ID0 == readl_relaxed(&device_data->base->cellid0) &&
+	    HASH_CELL_ID1 == readl_relaxed(&device_data->base->cellid1) &&
+	    HASH_CELL_ID2 == readl_relaxed(&device_data->base->cellid2) &&
+	    HASH_CELL_ID3 == readl_relaxed(&device_data->base->cellid3)) {
 		return 0;
 	}
 
-	dev_err(device_data->dev, "[%s] HASH_UNSUPPORTED_HW!",
-			__func__);
+	dev_err(device_data->dev, "%s: HASH_UNSUPPORTED_HW!\n", __func__);
 	return -ENOTSUPP;
 }
 
@@ -1294,14 +1271,14 @@ int hash_check_hw(struct hash_device_data *device_data)
  * @algorithm:		The algorithm in use.
  */
 void hash_get_digest(struct hash_device_data *device_data,
-		u8 *digest, int algorithm)
+		     u8 *digest, int algorithm)
 {
 	u32 temp_hx_val, count;
 	int loop_ctr;
 
 	if (algorithm != HASH_ALGO_SHA1 && algorithm != HASH_ALGO_SHA256) {
-		dev_err(device_data->dev, "[%s] Incorrect algorithm %d",
-				__func__, algorithm);
+		dev_err(device_data->dev, "%s: Incorrect algorithm %d\n",
+			__func__, algorithm);
 		return;
 	}
 
@@ -1310,8 +1287,8 @@ void hash_get_digest(struct hash_device_data *device_data,
 	else
 		loop_ctr = SHA256_DIGEST_SIZE / sizeof(u32);
 
-	dev_dbg(device_data->dev, "[%s] digest array:(0x%x)",
-			__func__, (u32) digest);
+	dev_dbg(device_data->dev, "%s: digest array:(0x%x)\n",
+		__func__, (u32) digest);
 
 	/* Copy result into digest array */
 	for (count = 0; count < loop_ctr; count++) {
@@ -1337,8 +1314,7 @@ static int ahash_update(struct ahash_request *req)
 	/* Skip update for DMA, all data will be passed to DMA in final */
 
 	if (ret) {
-		pr_err(DEV_DBG_NAME " [%s] hash_hw_update() failed!",
-				__func__);
+		pr_err("%s: hash_hw_update() failed!\n", __func__);
 	}
 
 	return ret;
@@ -1353,7 +1329,7 @@ static int ahash_final(struct ahash_request *req)
 	int ret = 0;
 	struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
 
-	pr_debug(DEV_DBG_NAME " [%s] data size: %d", __func__, req->nbytes);
+	pr_debug("%s: data size: %d\n", __func__, req->nbytes);
 
 	if ((hash_mode == HASH_MODE_DMA) && req_ctx->dma_mode)
 		ret = hash_dma_final(req);
@@ -1361,15 +1337,14 @@ static int ahash_final(struct ahash_request *req)
 		ret = hash_hw_final(req);
 
 	if (ret) {
-		pr_err(DEV_DBG_NAME " [%s] hash_hw/dma_final() failed",
-				__func__);
+		pr_err("%s: hash_hw/dma_final() failed\n", __func__);
 	}
 
 	return ret;
 }
 
 static int hash_setkey(struct crypto_ahash *tfm,
-		const u8 *key, unsigned int keylen, int alg)
+		       const u8 *key, unsigned int keylen, int alg)
 {
 	int ret = 0;
 	struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
@@ -1379,8 +1354,8 @@ static int hash_setkey(struct crypto_ahash *tfm,
 	 */
 	ctx->key = kmemdup(key, keylen, GFP_KERNEL);
 	if (!ctx->key) {
-		pr_err(DEV_DBG_NAME " [%s] Failed to allocate ctx->key "
-		       "for %d\n", __func__, alg);
+		pr_err("%s: Failed to allocate ctx->key for %d\n",
+		       __func__, alg);
 		return -ENOMEM;
 	}
 	ctx->keylen = keylen;
@@ -1501,13 +1476,13 @@ out:
 }
 
 static int hmac_sha1_setkey(struct crypto_ahash *tfm,
-		const u8 *key, unsigned int keylen)
+			    const u8 *key, unsigned int keylen)
 {
 	return hash_setkey(tfm, key, keylen, HASH_ALGO_SHA1);
 }
 
 static int hmac_sha256_setkey(struct crypto_ahash *tfm,
-		const u8 *key, unsigned int keylen)
+			      const u8 *key, unsigned int keylen)
 {
 	return hash_setkey(tfm, key, keylen, HASH_ALGO_SHA256);
 }
@@ -1528,7 +1503,7 @@ static int hash_cra_init(struct crypto_tfm *tfm)
 			hash);
 
 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
-			sizeof(struct hash_req_ctx));
+				 sizeof(struct hash_req_ctx));
 
 	ctx->config.data_format = HASH_DATA_8_BITS;
 	ctx->config.algorithm = hash_alg->conf.algorithm;
@@ -1541,98 +1516,97 @@ static int hash_cra_init(struct crypto_tfm *tfm)
 
 static struct hash_algo_template hash_algs[] = {
 	{
-			.conf.algorithm	= HASH_ALGO_SHA1,
-			.conf.oper_mode	= HASH_OPER_MODE_HASH,
-			.hash = {
-				.init = hash_init,
-				.update = ahash_update,
-				.final = ahash_final,
-				.digest = ahash_sha1_digest,
-				.halg.digestsize = SHA1_DIGEST_SIZE,
-				.halg.statesize = sizeof(struct hash_ctx),
-				.halg.base = {
-					.cra_name = "sha1",
-					.cra_driver_name = "sha1-ux500",
-					.cra_flags = CRYPTO_ALG_TYPE_AHASH |
-							CRYPTO_ALG_ASYNC,
-					.cra_blocksize = SHA1_BLOCK_SIZE,
-					.cra_ctxsize = sizeof(struct hash_ctx),
-					.cra_init = hash_cra_init,
-					.cra_module = THIS_MODULE,
+		.conf.algorithm = HASH_ALGO_SHA1,
+		.conf.oper_mode = HASH_OPER_MODE_HASH,
+		.hash = {
+			.init = hash_init,
+			.update = ahash_update,
+			.final = ahash_final,
+			.digest = ahash_sha1_digest,
+			.halg.digestsize = SHA1_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct hash_ctx),
+			.halg.base = {
+				.cra_name = "sha1",
+				.cra_driver_name = "sha1-ux500",
+				.cra_flags = (CRYPTO_ALG_TYPE_AHASH |
+					      CRYPTO_ALG_ASYNC),
+				.cra_blocksize = SHA1_BLOCK_SIZE,
+				.cra_ctxsize = sizeof(struct hash_ctx),
+				.cra_init = hash_cra_init,
+				.cra_module = THIS_MODULE,
 			}
 		}
 	},
 	{
-			.conf.algorithm		= HASH_ALGO_SHA256,
-			.conf.oper_mode		= HASH_OPER_MODE_HASH,
-			.hash = {
-				.init = hash_init,
-				.update	= ahash_update,
-				.final = ahash_final,
-				.digest = ahash_sha256_digest,
-				.halg.digestsize = SHA256_DIGEST_SIZE,
-				.halg.statesize = sizeof(struct hash_ctx),
-				.halg.base = {
-					.cra_name = "sha256",
-					.cra_driver_name = "sha256-ux500",
-					.cra_flags = CRYPTO_ALG_TYPE_AHASH |
-							CRYPTO_ALG_ASYNC,
-					.cra_blocksize = SHA256_BLOCK_SIZE,
-					.cra_ctxsize = sizeof(struct hash_ctx),
-					.cra_type = &crypto_ahash_type,
-					.cra_init = hash_cra_init,
-					.cra_module = THIS_MODULE,
-				}
+		.conf.algorithm	= HASH_ALGO_SHA256,
+		.conf.oper_mode	= HASH_OPER_MODE_HASH,
+		.hash = {
+			.init = hash_init,
+			.update	= ahash_update,
+			.final = ahash_final,
+			.digest = ahash_sha256_digest,
+			.halg.digestsize = SHA256_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct hash_ctx),
+			.halg.base = {
+				.cra_name = "sha256",
+				.cra_driver_name = "sha256-ux500",
+				.cra_flags = (CRYPTO_ALG_TYPE_AHASH |
+					      CRYPTO_ALG_ASYNC),
+				.cra_blocksize = SHA256_BLOCK_SIZE,
+				.cra_ctxsize = sizeof(struct hash_ctx),
+				.cra_type = &crypto_ahash_type,
+				.cra_init = hash_cra_init,
+				.cra_module = THIS_MODULE,
 			}
-
+		}
 	},
 	{
-			.conf.algorithm		= HASH_ALGO_SHA1,
-			.conf.oper_mode		= HASH_OPER_MODE_HMAC,
+		.conf.algorithm = HASH_ALGO_SHA1,
+		.conf.oper_mode = HASH_OPER_MODE_HMAC,
 			.hash = {
-				.init = hash_init,
-				.update = ahash_update,
-				.final = ahash_final,
-				.digest = hmac_sha1_digest,
-				.setkey = hmac_sha1_setkey,
-				.halg.digestsize = SHA1_DIGEST_SIZE,
-				.halg.statesize = sizeof(struct hash_ctx),
-				.halg.base = {
-					.cra_name = "hmac(sha1)",
-					.cra_driver_name = "hmac-sha1-ux500",
-					.cra_flags = CRYPTO_ALG_TYPE_AHASH |
-							CRYPTO_ALG_ASYNC,
-					.cra_blocksize = SHA1_BLOCK_SIZE,
-					.cra_ctxsize = sizeof(struct hash_ctx),
-					.cra_type = &crypto_ahash_type,
-					.cra_init = hash_cra_init,
-					.cra_module = THIS_MODULE,
-				}
+			.init = hash_init,
+			.update = ahash_update,
+			.final = ahash_final,
+			.digest = hmac_sha1_digest,
+			.setkey = hmac_sha1_setkey,
+			.halg.digestsize = SHA1_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct hash_ctx),
+			.halg.base = {
+				.cra_name = "hmac(sha1)",
+				.cra_driver_name = "hmac-sha1-ux500",
+				.cra_flags = (CRYPTO_ALG_TYPE_AHASH |
+					      CRYPTO_ALG_ASYNC),
+				.cra_blocksize = SHA1_BLOCK_SIZE,
+				.cra_ctxsize = sizeof(struct hash_ctx),
+				.cra_type = &crypto_ahash_type,
+				.cra_init = hash_cra_init,
+				.cra_module = THIS_MODULE,
 			}
+		}
 	},
 	{
-			.conf.algorithm		= HASH_ALGO_SHA256,
-			.conf.oper_mode		= HASH_OPER_MODE_HMAC,
-			.hash = {
-				.init = hash_init,
-				.update = ahash_update,
-				.final = ahash_final,
-				.digest = hmac_sha256_digest,
-				.setkey = hmac_sha256_setkey,
-				.halg.digestsize = SHA256_DIGEST_SIZE,
-				.halg.statesize = sizeof(struct hash_ctx),
-				.halg.base = {
-					.cra_name = "hmac(sha256)",
-					.cra_driver_name = "hmac-sha256-ux500",
-					.cra_flags = CRYPTO_ALG_TYPE_AHASH |
-							CRYPTO_ALG_ASYNC,
-					.cra_blocksize = SHA256_BLOCK_SIZE,
-					.cra_ctxsize = sizeof(struct hash_ctx),
-					.cra_type = &crypto_ahash_type,
-					.cra_init = hash_cra_init,
-					.cra_module = THIS_MODULE,
-				}
+		.conf.algorithm = HASH_ALGO_SHA256,
+		.conf.oper_mode = HASH_OPER_MODE_HMAC,
+		.hash = {
+			.init = hash_init,
+			.update = ahash_update,
+			.final = ahash_final,
+			.digest = hmac_sha256_digest,
+			.setkey = hmac_sha256_setkey,
+			.halg.digestsize = SHA256_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct hash_ctx),
+			.halg.base = {
+				.cra_name = "hmac(sha256)",
+				.cra_driver_name = "hmac-sha256-ux500",
+				.cra_flags = (CRYPTO_ALG_TYPE_AHASH |
+					      CRYPTO_ALG_ASYNC),
+				.cra_blocksize = SHA256_BLOCK_SIZE,
+				.cra_ctxsize = sizeof(struct hash_ctx),
+				.cra_type = &crypto_ahash_type,
+				.cra_init = hash_cra_init,
+				.cra_module = THIS_MODULE,
 			}
+		}
 	}
 };
 
@@ -1649,7 +1623,7 @@ static int ahash_algs_register_all(struct hash_device_data *device_data)
 		ret = crypto_register_ahash(&hash_algs[i].hash);
 		if (ret) {
 			count = i;
-			dev_err(device_data->dev, "[%s] alg registration failed",
+			dev_err(device_data->dev, "%s: alg registration failed\n",
 				hash_algs[i].hash.halg.base.cra_driver_name);
 			goto unreg;
 		}
@@ -1683,9 +1657,8 @@ static int ux500_hash_probe(struct platform_device *pdev)
 	struct hash_device_data *device_data;
 	struct device		*dev = &pdev->dev;
 
-	device_data = kzalloc(sizeof(struct hash_device_data), GFP_ATOMIC);
+	device_data = kzalloc(sizeof(*device_data), GFP_ATOMIC);
 	if (!device_data) {
-		dev_dbg(dev, "[%s] kzalloc() failed!", __func__);
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -1695,14 +1668,14 @@ static int ux500_hash_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_dbg(dev, "[%s] platform_get_resource() failed!", __func__);
+		dev_dbg(dev, "%s: platform_get_resource() failed!\n", __func__);
 		ret = -ENODEV;
 		goto out_kfree;
 	}
 
 	res = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (res == NULL) {
-		dev_dbg(dev, "[%s] request_mem_region() failed!", __func__);
+		dev_dbg(dev, "%s: request_mem_region() failed!\n", __func__);
 		ret = -EBUSY;
 		goto out_kfree;
 	}
@@ -1710,8 +1683,7 @@ static int ux500_hash_probe(struct platform_device *pdev)
 	device_data->phybase = res->start;
 	device_data->base = ioremap(res->start, resource_size(res));
 	if (!device_data->base) {
-		dev_err(dev, "[%s] ioremap() failed!",
-				__func__);
+		dev_err(dev, "%s: ioremap() failed!\n", __func__);
 		ret = -ENOMEM;
 		goto out_free_mem;
 	}
@@ -1721,7 +1693,7 @@ static int ux500_hash_probe(struct platform_device *pdev)
 	/* Enable power for HASH1 hardware block */
 	device_data->regulator = regulator_get(dev, "v-ape");
 	if (IS_ERR(device_data->regulator)) {
-		dev_err(dev, "[%s] regulator_get() failed!", __func__);
+		dev_err(dev, "%s: regulator_get() failed!\n", __func__);
 		ret = PTR_ERR(device_data->regulator);
 		device_data->regulator = NULL;
 		goto out_unmap;
@@ -1730,27 +1702,27 @@ static int ux500_hash_probe(struct platform_device *pdev)
 	/* Enable the clock for HASH1 hardware block */
 	device_data->clk = clk_get(dev, NULL);
 	if (IS_ERR(device_data->clk)) {
-		dev_err(dev, "[%s] clk_get() failed!", __func__);
+		dev_err(dev, "%s: clk_get() failed!\n", __func__);
 		ret = PTR_ERR(device_data->clk);
 		goto out_regulator;
 	}
 
 	ret = clk_prepare(device_data->clk);
 	if (ret) {
-		dev_err(dev, "[%s] clk_prepare() failed!", __func__);
+		dev_err(dev, "%s: clk_prepare() failed!\n", __func__);
 		goto out_clk;
 	}
 
 	/* Enable device power (and clock) */
 	ret = hash_enable_power(device_data, false);
 	if (ret) {
-		dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
+		dev_err(dev, "%s: hash_enable_power() failed!\n", __func__);
 		goto out_clk_unprepare;
 	}
 
 	ret = hash_check_hw(device_data);
 	if (ret) {
-		dev_err(dev, "[%s] hash_check_hw() failed!", __func__);
+		dev_err(dev, "%s: hash_check_hw() failed!\n", __func__);
 		goto out_power;
 	}
 
@@ -1766,8 +1738,8 @@ static int ux500_hash_probe(struct platform_device *pdev)
 
 	ret = ahash_algs_register_all(device_data);
 	if (ret) {
-		dev_err(dev, "[%s] ahash_algs_register_all() "
-				"failed!", __func__);
+		dev_err(dev, "%s: ahash_algs_register_all() failed!\n",
+			__func__);
 		goto out_power;
 	}
 
@@ -1810,8 +1782,7 @@ static int ux500_hash_remove(struct platform_device *pdev)
 
 	device_data = platform_get_drvdata(pdev);
 	if (!device_data) {
-		dev_err(dev, "[%s]: platform_get_drvdata() failed!",
-			__func__);
+		dev_err(dev, "%s: platform_get_drvdata() failed!\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -1841,7 +1812,7 @@ static int ux500_hash_remove(struct platform_device *pdev)
 		ahash_algs_unregister_all(device_data);
 
 	if (hash_disable_power(device_data, false))
-		dev_err(dev, "[%s]: hash_disable_power() failed",
+		dev_err(dev, "%s: hash_disable_power() failed\n",
 			__func__);
 
 	clk_unprepare(device_data->clk);
@@ -1870,8 +1841,8 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
 
 	device_data = platform_get_drvdata(pdev);
 	if (!device_data) {
-		dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
-				__func__);
+		dev_err(&pdev->dev, "%s: platform_get_drvdata() failed!\n",
+			__func__);
 		return;
 	}
 
@@ -1880,8 +1851,8 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
 	/* current_ctx allocates a device, NULL = unallocated */
 	if (!device_data->current_ctx) {
 		if (down_trylock(&driver_data.device_allocation))
-			dev_dbg(&pdev->dev, "[%s]: Cryp still in use!"
-				"Shutting down anyway...", __func__);
+			dev_dbg(&pdev->dev, "%s: Cryp still in use! Shutting down anyway...\n",
+				__func__);
 		/**
 		 * (Allocate the device)
 		 * Need to set this to non-null (dummy) value,
@@ -1906,8 +1877,8 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
 		release_mem_region(res->start, resource_size(res));
 
 	if (hash_disable_power(device_data, false))
-		dev_err(&pdev->dev, "[%s] hash_disable_power() failed",
-				__func__);
+		dev_err(&pdev->dev, "%s: hash_disable_power() failed\n",
+			__func__);
 }
 
 /**
@@ -1922,7 +1893,7 @@ static int ux500_hash_suspend(struct device *dev)
 
 	device_data = dev_get_drvdata(dev);
 	if (!device_data) {
-		dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
+		dev_err(dev, "%s: platform_get_drvdata() failed!\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -1933,15 +1904,16 @@ static int ux500_hash_suspend(struct device *dev)
 
 	if (device_data->current_ctx == ++temp_ctx) {
 		if (down_interruptible(&driver_data.device_allocation))
-			dev_dbg(dev, "[%s]: down_interruptible() failed",
+			dev_dbg(dev, "%s: down_interruptible() failed\n",
 				__func__);
 		ret = hash_disable_power(device_data, false);
 
-	} else
+	} else {
 		ret = hash_disable_power(device_data, true);
+	}
 
 	if (ret)
-		dev_err(dev, "[%s]: hash_disable_power()", __func__);
+		dev_err(dev, "%s: hash_disable_power()\n", __func__);
 
 	return ret;
 }
@@ -1958,7 +1930,7 @@ static int ux500_hash_resume(struct device *dev)
 
 	device_data = dev_get_drvdata(dev);
 	if (!device_data) {
-		dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
+		dev_err(dev, "%s: platform_get_drvdata() failed!\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -1973,7 +1945,7 @@ static int ux500_hash_resume(struct device *dev)
 		ret = hash_enable_power(device_data, true);
 
 	if (ret)
-		dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
+		dev_err(dev, "%s: hash_enable_power() failed!\n", __func__);
 
 	return ret;
 }
@@ -1981,8 +1953,8 @@ static int ux500_hash_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(ux500_hash_pm, ux500_hash_suspend, ux500_hash_resume);
 
 static const struct of_device_id ux500_hash_match[] = {
-        { .compatible = "stericsson,ux500-hash" },
-        { },
+	{ .compatible = "stericsson,ux500-hash" },
+	{ },
 };
 
 static struct platform_driver hash_driver = {
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index 5a18f82..ba7f932 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -73,7 +73,7 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
 	if (si->mmio_base_low != mem || si->gsi_interrupt != irq)
 		return 0;
 
-	vendor_id = le32_to_cpu(grp->vendor_id);
+	vendor_id = le32_to_cpu((__force __le32)grp->vendor_id);
 	dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
 		(char *)&vendor_id, grp->device_id, grp->revision);
 
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 9e56745..99af4db 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -87,7 +87,8 @@ static struct dma_chan *dev_to_dma_chan(struct device *dev)
 	return chan_dev->chan;
 }
 
-static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t memcpy_count_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
 {
 	struct dma_chan *chan;
 	unsigned long count = 0;
@@ -106,9 +107,10 @@ static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *at
 
 	return err;
 }
+static DEVICE_ATTR_RO(memcpy_count);
 
-static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr,
-				      char *buf)
+static ssize_t bytes_transferred_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
 {
 	struct dma_chan *chan;
 	unsigned long count = 0;
@@ -127,8 +129,10 @@ static ssize_t show_bytes_transferred(struct device *dev, struct device_attribut
 
 	return err;
 }
+static DEVICE_ATTR_RO(bytes_transferred);
 
-static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t in_use_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct dma_chan *chan;
 	int err;
@@ -143,13 +147,15 @@ static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, ch
 
 	return err;
 }
+static DEVICE_ATTR_RO(in_use);
 
-static struct device_attribute dma_attrs[] = {
-	__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
-	__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
-	__ATTR(in_use, S_IRUGO, show_in_use, NULL),
-	__ATTR_NULL
+static struct attribute *dma_dev_attrs[] = {
+	&dev_attr_memcpy_count.attr,
+	&dev_attr_bytes_transferred.attr,
+	&dev_attr_in_use.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(dma_dev);
 
 static void chan_dev_release(struct device *dev)
 {
@@ -167,7 +173,7 @@ static void chan_dev_release(struct device *dev)
 
 static struct class dma_devclass = {
 	.name		= "dma",
-	.dev_attrs	= dma_attrs,
+	.dev_groups	= dma_dev_groups,
 	.dev_release	= chan_dev_release,
 };
 
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index eea479c..89eb89f 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -37,16 +37,22 @@
  * which does not support descriptor writeback.
  */
 
+static inline bool is_request_line_unset(struct dw_dma_chan *dwc)
+{
+	return dwc->request_line == (typeof(dwc->request_line))~0;
+}
+
 static inline void dwc_set_masters(struct dw_dma_chan *dwc)
 {
 	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
 	struct dw_dma_slave *dws = dwc->chan.private;
 	unsigned char mmax = dw->nr_masters - 1;
 
-	if (dwc->request_line == ~0) {
-		dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws));
-		dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws));
-	}
+	if (!is_request_line_unset(dwc))
+		return;
+
+	dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws));
+	dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws));
 }
 
 #define DWC_DEFAULT_CTLLO(_chan) ({				\
@@ -644,10 +650,13 @@ static void dw_dma_tasklet(unsigned long data)
 static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
 {
 	struct dw_dma *dw = dev_id;
-	u32 status;
+	u32 status = dma_readl(dw, STATUS_INT);
+
+	dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__, status);
 
-	dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__,
-			dma_readl(dw, STATUS_INT));
+	/* Check if we have any interrupt from the DMAC */
+	if (!status)
+		return IRQ_NONE;
 
 	/*
 	 * Just disable the interrupts. We'll turn them back on in the
@@ -984,7 +993,7 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 	dwc->direction = sconfig->direction;
 
 	/* Take the request line from slave_id member */
-	if (dwc->request_line == ~0)
+	if (is_request_line_unset(dwc))
 		dwc->request_line = sconfig->slave_id;
 
 	convert_burst(&dwc->dma_sconfig.src_maxburst);
@@ -1089,16 +1098,16 @@ dwc_tx_status(struct dma_chan *chan,
 	enum dma_status		ret;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
-	if (ret != DMA_SUCCESS) {
-		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+	if (ret == DMA_SUCCESS)
+		return ret;
 
-		ret = dma_cookie_status(chan, cookie, txstate);
-	}
+	dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
 
+	ret = dma_cookie_status(chan, cookie, txstate);
 	if (ret != DMA_SUCCESS)
 		dma_set_residue(txstate, dwc_get_residue(dwc));
 
-	if (dwc->paused)
+	if (dwc->paused && ret == DMA_IN_PROGRESS)
 		return DMA_PAUSED;
 
 	return ret;
@@ -1560,8 +1569,8 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
 	/* Disable BLOCK interrupts as well */
 	channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
 
-	err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt, 0,
-			       "dw_dmac", dw);
+	err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt,
+			       IRQF_SHARED, "dw_dmac", dw);
 	if (err)
 		return err;
 
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index 6c9449c..e35d975 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -253,6 +253,7 @@ static const struct acpi_device_id dw_dma_acpi_id_table[] = {
 	{ "INTL9C60", 0 },
 	{ }
 };
+MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
 #endif
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 5f3e532..4f6d87b 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -502,8 +502,6 @@ static enum dma_status edma_tx_status(struct dma_chan *chan,
 	} else if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) {
 		struct edma_desc *edesc = echan->edesc;
 		txstate->residue = edma_desc_size(edesc);
-	} else {
-		txstate->residue = 0;
 	}
 	spin_unlock_irqrestore(&echan->vchan.lock, flags);
 
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index f2bf8c0..591cd8c 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -1313,15 +1313,7 @@ static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
 					    dma_cookie_t cookie,
 					    struct dma_tx_state *state)
 {
-	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
-	enum dma_status ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&edmac->lock, flags);
-	ret = dma_cookie_status(chan, cookie, state);
-	spin_unlock_irqrestore(&edmac->lock, flags);
-
-	return ret;
+	return dma_cookie_status(chan, cookie, state);
 }
 
 /**
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 49e8fbd..b3f3e90 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -979,15 +979,7 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
 					dma_cookie_t cookie,
 					struct dma_tx_state *txstate)
 {
-	struct fsldma_chan *chan = to_fsl_chan(dchan);
-	enum dma_status ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
-	ret = dma_cookie_status(dchan, cookie, txstate);
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
-
-	return ret;
+	return dma_cookie_status(dchan, cookie, txstate);
 }
 
 /*----------------------------------------------------------------------------*/
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 1e44b8c..f45e092 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1120,15 +1120,12 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 }
 
 static enum dma_status sdma_tx_status(struct dma_chan *chan,
-					    dma_cookie_t cookie,
-					    struct dma_tx_state *txstate)
+				      dma_cookie_t cookie,
+				      struct dma_tx_state *txstate)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
-	dma_cookie_t last_used;
 
-	last_used = chan->cookie;
-
-	dma_set_tx_state(txstate, chan->completed_cookie, last_used,
+	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
 			sdmac->chn_count - sdmac->chn_real_count);
 
 	return sdmac->status;
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index d39c2cd..608d4a2 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1593,10 +1593,7 @@ static void idmac_free_chan_resources(struct dma_chan *chan)
 static enum dma_status idmac_tx_status(struct dma_chan *chan,
 		       dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
-	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, 0);
-	if (cookie != chan->cookie)
-		return DMA_ERROR;
-	return DMA_SUCCESS;
+	return dma_cookie_status(chan, cookie, txstate);
 }
 
 static int __init ipu_idmac_init(struct ipu *ipu)
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index c26699f..9a32f2d 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -121,6 +121,7 @@ struct mmp_pdma_device {
 	struct device			*dev;
 	struct dma_device		device;
 	struct mmp_pdma_phy		*phy;
+	spinlock_t phy_lock; /* protect alloc/free phy channels */
 };
 
 #define tx_to_mmp_pdma_desc(tx) container_of(tx, struct mmp_pdma_desc_sw, async_tx)
@@ -219,6 +220,7 @@ static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan)
 	int prio, i;
 	struct mmp_pdma_device *pdev = to_mmp_pdma_dev(pchan->chan.device);
 	struct mmp_pdma_phy *phy;
+	unsigned long flags;
 
 	/*
 	 * dma channel priorities
@@ -227,6 +229,8 @@ static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan)
 	 * ch 8 - 11, 24 - 27  <--> (2)
 	 * ch 12 - 15, 28 - 31  <--> (3)
 	 */
+
+	spin_lock_irqsave(&pdev->phy_lock, flags);
 	for (prio = 0; prio <= (((pdev->dma_channels - 1) & 0xf) >> 2); prio++) {
 		for (i = 0; i < pdev->dma_channels; i++) {
 			if (prio != ((i & 0xf) >> 2))
@@ -234,14 +238,36 @@ static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan)
 			phy = &pdev->phy[i];
 			if (!phy->vchan) {
 				phy->vchan = pchan;
+				spin_unlock_irqrestore(&pdev->phy_lock, flags);
 				return phy;
 			}
 		}
 	}
 
+	spin_unlock_irqrestore(&pdev->phy_lock, flags);
 	return NULL;
 }
 
+static void mmp_pdma_free_phy(struct mmp_pdma_chan *pchan)
+{
+	struct mmp_pdma_device *pdev = to_mmp_pdma_dev(pchan->chan.device);
+	unsigned long flags;
+	u32 reg;
+
+	if (!pchan->phy)
+		return;
+
+	/* clear the channel mapping in DRCMR */
+	reg = pchan->phy->vchan->drcmr;
+	reg = ((reg < 64) ? 0x0100 : 0x1100) + ((reg & 0x3f) << 2);
+	writel(0, pchan->phy->base + reg);
+
+	spin_lock_irqsave(&pdev->phy_lock, flags);
+	pchan->phy->vchan = NULL;
+	pchan->phy = NULL;
+	spin_unlock_irqrestore(&pdev->phy_lock, flags);
+}
+
 /* desc->tx_list ==> pending list */
 static void append_pending_queue(struct mmp_pdma_chan *chan,
 					struct mmp_pdma_desc_sw *desc)
@@ -277,10 +303,7 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)
 
 	if (list_empty(&chan->chain_pending)) {
 		/* chance to re-fetch phy channel with higher prio */
-		if (chan->phy) {
-			chan->phy->vchan = NULL;
-			chan->phy = NULL;
-		}
+		mmp_pdma_free_phy(chan);
 		dev_dbg(chan->dev, "no pending list\n");
 		return;
 	}
@@ -377,10 +400,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan)
 		dev_err(chan->dev, "unable to allocate descriptor pool\n");
 		return -ENOMEM;
 	}
-	if (chan->phy) {
-		chan->phy->vchan = NULL;
-		chan->phy = NULL;
-	}
+	mmp_pdma_free_phy(chan);
 	chan->idle = true;
 	chan->dev_addr = 0;
 	return 1;
@@ -411,10 +431,7 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)
 	chan->desc_pool = NULL;
 	chan->idle = true;
 	chan->dev_addr = 0;
-	if (chan->phy) {
-		chan->phy->vchan = NULL;
-		chan->phy = NULL;
-	}
+	mmp_pdma_free_phy(chan);
 	return;
 }
 
@@ -581,10 +598,7 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
 	switch (cmd) {
 	case DMA_TERMINATE_ALL:
 		disable_chan(chan->phy);
-		if (chan->phy) {
-			chan->phy->vchan = NULL;
-			chan->phy = NULL;
-		}
+		mmp_pdma_free_phy(chan);
 		spin_lock_irqsave(&chan->desc_lock, flags);
 		mmp_pdma_free_desc_list(chan, &chan->chain_pending);
 		mmp_pdma_free_desc_list(chan, &chan->chain_running);
@@ -632,15 +646,7 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
 static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan,
 			dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
-	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
-	enum dma_status ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
-	ret = dma_cookie_status(dchan, cookie, txstate);
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
-
-	return ret;
+	return dma_cookie_status(dchan, cookie, txstate);
 }
 
 /**
@@ -777,6 +783,8 @@ static int mmp_pdma_probe(struct platform_device *op)
 		return -ENOMEM;
 	pdev->dev = &op->dev;
 
+	spin_lock_init(&pdev->phy_lock);
+
 	iores = platform_get_resource(op, IORESOURCE_MEM, 0);
 	if (!iores)
 		return -EINVAL;
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index 9b93665..a9345d0 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -460,7 +460,8 @@ static enum dma_status mmp_tdma_tx_status(struct dma_chan *chan,
 {
 	struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
 
-	dma_set_residue(txstate, tdmac->buf_len - tdmac->pos);
+	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
+			 tdmac->buf_len - tdmac->pos);
 
 	return tdmac->status;
 }
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2d95673..2fe4353 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -556,15 +556,7 @@ static enum dma_status
 mpc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 	       struct dma_tx_state *txstate)
 {
-	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
-	enum dma_status ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mchan->lock, flags);
-	ret = dma_cookie_status(chan, cookie, txstate);
-	spin_unlock_irqrestore(&mchan->lock, flags);
-
-	return ret;
+	return dma_cookie_status(chan, cookie, txstate);
 }
 
 /* Prepare descriptor for memory to memory copy */
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 7195930..6fb4b7b 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -622,10 +622,8 @@ static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
 			dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
 	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
-	dma_cookie_t last_used;
 
-	last_used = chan->cookie;
-	dma_set_tx_state(txstate, chan->completed_cookie, last_used, 0);
+	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, 0);
 
 	return mxs_chan->status;
 }
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 0bbdea5..956314d 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -564,14 +564,7 @@ static void pd_free_chan_resources(struct dma_chan *chan)
 static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 				    struct dma_tx_state *txstate)
 {
-	struct pch_dma_chan *pd_chan = to_pd_chan(chan);
-	enum dma_status ret;
-
-	spin_lock_irq(&pd_chan->lock);
-	ret = dma_cookie_status(chan, cookie, txstate);
-	spin_unlock_irq(&pd_chan->lock);
-
-	return ret;
+	return dma_cookie_status(chan, cookie, txstate);
 }
 
 static void pd_issue_pending(struct dma_chan *chan)
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index fa645d8..4ad13eb 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2896,6 +2896,32 @@ static irqreturn_t pl330_irq_handler(int irq, void *data)
 		return IRQ_NONE;
 }
 
+#define PL330_DMA_BUSWIDTHS \
+	BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
+	BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+	BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+	BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
+	BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)
+
+static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
+	struct dma_slave_caps *caps)
+{
+	caps->src_addr_widths = PL330_DMA_BUSWIDTHS;
+	caps->dstn_addr_widths = PL330_DMA_BUSWIDTHS;
+	caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	caps->cmd_pause = false;
+	caps->cmd_terminate = true;
+
+	/*
+	 * This is the limit for transfers with a buswidth of 1, larger
+	 * buswidths will have larger limits.
+	 */
+	caps->max_sg_len = 1900800;
+	caps->max_sg_nr = 0;
+
+	return 0;
+}
+
 static int
 pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -3000,6 +3026,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	pd->device_prep_slave_sg = pl330_prep_slave_sg;
 	pd->device_control = pl330_control;
 	pd->device_issue_pending = pl330_issue_pending;
+	pd->device_slave_caps = pl330_dma_device_slave_caps;
 
 	ret = dma_async_device_register(pd);
 	if (ret) {
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index b67f45f..5039fbc 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -400,8 +400,8 @@ static size_t sh_dmae_get_partial(struct shdma_chan *schan,
 						    shdma_chan);
 	struct sh_dmae_desc *sh_desc = container_of(sdesc,
 					struct sh_dmae_desc, shdma_desc);
-	return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
-		sh_chan->xmit_shift;
+	return sh_desc->hw.tcr -
+		(sh_dmae_readl(sh_chan, TCR) << sh_chan->xmit_shift);
 }
 
 /* Called from error IRQ or NMI */
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index f137914..5d4986e 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -767,13 +767,11 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
 	unsigned long flags;
 	unsigned int residual;
 
-	spin_lock_irqsave(&tdc->lock, flags);
-
 	ret = dma_cookie_status(dc, cookie, txstate);
-	if (ret == DMA_SUCCESS) {
-		spin_unlock_irqrestore(&tdc->lock, flags);
+	if (ret == DMA_SUCCESS)
 		return ret;
-	}
+
+	spin_lock_irqsave(&tdc->lock, flags);
 
 	/* Check on wait_ack desc status */
 	list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index a59fb48..59357db 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -962,15 +962,14 @@ txx9dmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 	enum dma_status ret;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
-	if (ret != DMA_SUCCESS) {
-		spin_lock_bh(&dc->lock);
-		txx9dmac_scan_descriptors(dc);
-		spin_unlock_bh(&dc->lock);
+	if (ret == DMA_SUCCESS)
+		return DMA_SUCCESS;
 
-		ret = dma_cookie_status(chan, cookie, txstate);
-	}
+	spin_lock_bh(&dc->lock);
+	txx9dmac_scan_descriptors(dc);
+	spin_unlock_bh(&dc->lock);
 
-	return ret;
+	return dma_cookie_status(chan, cookie, txstate);
 }
 
 static void txx9dmac_chain_dynamic(struct txx9dmac_chan *dc,
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 8b6a034..8b3d901 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2470,8 +2470,15 @@ static int amd64_init_one_instance(struct pci_dev *F2)
 	layers[0].size = pvt->csels[0].b_cnt;
 	layers[0].is_virt_csrow = true;
 	layers[1].type = EDAC_MC_LAYER_CHANNEL;
-	layers[1].size = pvt->channel_count;
+
+	/*
+	 * Always allocate two channels since we can have setups with DIMMs on
+	 * only one channel. Also, this simplifies handling later for the price
+	 * of a couple of KBs tops.
+	 */
+	layers[1].size = 2;
 	layers[1].is_virt_csrow = false;
+
 	mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0);
 	if (!mci)
 		goto err_siblings;
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index e7c32c4..9f7e0e60 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -58,8 +58,10 @@ static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
 	if (!val)
 		return -EINVAL;
 
-	ret = strict_strtol(val, 0, &l);
-	if (ret == -EINVAL || ((int)l != l))
+	ret = kstrtol(val, 0, &l);
+	if (ret)
+		return ret;
+	if ((int)l != l)
 		return -EINVAL;
 	*((int *)kp->arg) = l;
 
diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c
index a082053..578f915 100644
--- a/drivers/edac/tile_edac.c
+++ b/drivers/edac/tile_edac.c
@@ -257,7 +257,6 @@ static void __exit tile_edac_exit(void)
 		if (!pdev)
 			continue;
 
-		platform_set_drvdata(pdev, NULL);
 		platform_device_unregister(pdev);
 	}
 	platform_driver_unregister(&tile_edac_mc_driver);
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 63f454e..f1d54a3 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -14,6 +14,10 @@ if EXTCON
 
 comment "Extcon Device Drivers"
 
+config OF_EXTCON
+	def_tristate y
+	depends on OF
+
 config EXTCON_GPIO
 	tristate "GPIO extcon support"
 	depends on GPIOLIB
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 540e2c3..759fdae 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -2,6 +2,8 @@
 # Makefile for external connector class (extcon) devices
 #
 
+obj-$(CONFIG_OF_EXTCON)		+= of_extcon.o
+
 obj-$(CONFIG_EXTCON)		+= extcon-class.o
 obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
 obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index d0233cd..5985807 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -87,7 +87,8 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
 {
 	struct adc_jack_data *data = _data;
 
-	schedule_delayed_work(&data->handler, data->handling_delay);
+	queue_delayed_work(system_power_efficient_wq,
+			   &data->handler, data->handling_delay);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 7a1b4a7..e557130 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -890,8 +890,9 @@ static void arizona_micd_detect(struct work_struct *work)
 
 handled:
 	if (info->detecting)
-		schedule_delayed_work(&info->micd_timeout_work,
-				      msecs_to_jiffies(info->micd_timeout));
+		queue_delayed_work(system_power_efficient_wq,
+				   &info->micd_timeout_work,
+				   msecs_to_jiffies(info->micd_timeout));
 
 	pm_runtime_mark_last_busy(info->dev);
 	mutex_unlock(&info->lock);
@@ -912,8 +913,9 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 	mutex_unlock(&info->lock);
 
 	if (debounce)
-		schedule_delayed_work(&info->micd_detect_work,
-				      msecs_to_jiffies(debounce));
+		queue_delayed_work(system_power_efficient_wq,
+				   &info->micd_detect_work,
+				   msecs_to_jiffies(debounce));
 	else
 		arizona_micd_detect(&info->micd_detect_work.work);
 
@@ -967,12 +969,14 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 	if (val == info->last_jackdet) {
 		dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
 		if (cancelled_hp)
-			schedule_delayed_work(&info->hpdet_work,
-					      msecs_to_jiffies(HPDET_DEBOUNCE));
+			queue_delayed_work(system_power_efficient_wq,
+					   &info->hpdet_work,
+					   msecs_to_jiffies(HPDET_DEBOUNCE));
 
 		if (cancelled_mic)
-			schedule_delayed_work(&info->micd_timeout_work,
-					      msecs_to_jiffies(info->micd_timeout));
+			queue_delayed_work(system_power_efficient_wq,
+					   &info->micd_timeout_work,
+					   msecs_to_jiffies(info->micd_timeout));
 
 		goto out;
 	}
@@ -994,8 +998,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 
 			arizona_start_mic(info);
 		} else {
-			schedule_delayed_work(&info->hpdet_work,
-					      msecs_to_jiffies(HPDET_DEBOUNCE));
+			queue_delayed_work(system_power_efficient_wq,
+					   &info->hpdet_work,
+					   msecs_to_jiffies(HPDET_DEBOUNCE));
 		}
 
 		regmap_update_bits(arizona->regmap,
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 18ccade..148382f 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -148,6 +148,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
+static DEVICE_ATTR_RW(state);
 
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -163,6 +164,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 
 	return sprintf(buf, "%s\n", dev_name(edev->dev));
 }
+static DEVICE_ATTR_RO(name);
 
 static ssize_t cable_name_show(struct device *dev,
 			       struct device_attribute *attr, char *buf)
@@ -527,11 +529,12 @@ int extcon_unregister_notifier(struct extcon_dev *edev,
 }
 EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
 
-static struct device_attribute extcon_attrs[] = {
-	__ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
-	__ATTR_RO(name),
-	__ATTR_NULL,
+static struct attribute *extcon_attrs[] = {
+	&dev_attr_state.attr,
+	&dev_attr_name.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(extcon);
 
 static int create_extcon_class(void)
 {
@@ -539,7 +542,7 @@ static int create_extcon_class(void)
 		extcon_class = class_create(THIS_MODULE, "extcon");
 		if (IS_ERR(extcon_class))
 			return PTR_ERR(extcon_class);
-		extcon_class->dev_attrs = extcon_attrs;
+		extcon_class->dev_groups = extcon_groups;
 
 #if defined(CONFIG_ANDROID)
 		switch_class = class_compat_register("switch");
@@ -602,7 +605,8 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
 	edev->dev->class = extcon_class;
 	edev->dev->release = extcon_dev_release;
 
-	dev_set_name(edev->dev, "%s", edev->name ? edev->name : dev_name(dev));
+	edev->name = edev->name ? edev->name : dev_name(dev);
+	dev_set_name(edev->dev, "%s", edev->name);
 
 	if (edev->max_supported) {
 		char buf[10];
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 02bec32..f874c30 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -56,7 +56,7 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
 {
 	struct gpio_extcon_data *extcon_data = dev_id;
 
-	schedule_delayed_work(&extcon_data->work,
+	queue_delayed_work(system_power_efficient_wq, &extcon_data->work,
 			      extcon_data->debounce_jiffies);
 	return IRQ_HANDLED;
 }
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index b752a0a..89fdd05 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -57,6 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
 		if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
 			palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
 			extcon_set_cable_state(&palmas_usb->edev, "USB", true);
+			dev_info(palmas_usb->dev, "USB cable is attached\n");
 		} else {
 			dev_dbg(palmas_usb->dev,
 				"Spurious connect event detected\n");
@@ -65,6 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
 		if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
 			palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
 			extcon_set_cable_state(&palmas_usb->edev, "USB", false);
+			dev_info(palmas_usb->dev, "USB cable is detached\n");
 		} else {
 			dev_dbg(palmas_usb->dev,
 				"Spurious disconnect event detected\n");
@@ -84,28 +86,23 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
 
 	if (set & PALMAS_USB_ID_INT_SRC_ID_GND) {
 		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
-			PALMAS_USB_ID_INT_EN_HI_SET,
-			PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
-		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
-			PALMAS_USB_ID_INT_EN_HI_CLR,
-			PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
-		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
 			PALMAS_USB_ID_INT_LATCH_CLR,
 			PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
 		palmas_usb->linkstat = PALMAS_USB_STATE_ID;
 		extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
+		dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
 	} else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) {
 		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
-			PALMAS_USB_ID_INT_EN_HI_SET,
-			PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
-		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
-			PALMAS_USB_ID_INT_EN_HI_CLR,
-			PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
-		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
 			PALMAS_USB_ID_INT_LATCH_CLR,
 			PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
 		palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
 		extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+		dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
+	} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
+				(!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
+		palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
+		extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+		dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
 	}
 
 	return IRQ_HANDLED;
@@ -122,13 +119,17 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb)
 
 	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
 		PALMAS_USB_ID_INT_EN_HI_SET,
-		PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
+		PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
+		PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
 
-	palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
+	if (palmas_usb->enable_vbus_detection)
+		palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
 
 	/* cold plug for host mode needs this delay */
-	msleep(30);
-	palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
+	if (palmas_usb->enable_id_detection) {
+		msleep(30);
+		palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
+	}
 }
 
 static int palmas_usb_probe(struct platform_device *pdev)
@@ -139,21 +140,25 @@ static int palmas_usb_probe(struct platform_device *pdev)
 	struct palmas_usb *palmas_usb;
 	int status;
 
-	if (node && !pdata) {
-		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-
-		if (!pdata)
-			return -ENOMEM;
-
-		pdata->wakeup = of_property_read_bool(node, "ti,wakeup");
-	} else if (!pdata) {
-		return -EINVAL;
-	}
-
 	palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL);
 	if (!palmas_usb)
 		return -ENOMEM;
 
+	if (node && !pdata) {
+		palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup");
+		palmas_usb->enable_id_detection = of_property_read_bool(node,
+						"ti,enable-id-detection");
+		palmas_usb->enable_vbus_detection = of_property_read_bool(node,
+						"ti,enable-vbus-detection");
+	} else {
+		palmas_usb->wakeup = true;
+		palmas_usb->enable_id_detection = true;
+		palmas_usb->enable_vbus_detection = true;
+
+		if (pdata)
+			palmas_usb->wakeup = pdata->wakeup;
+	}
+
 	palmas->usb = palmas_usb;
 	palmas_usb->palmas = palmas;
 
@@ -168,11 +173,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
 	palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
 						PALMAS_VBUS_IRQ);
 
-	palmas_usb_wakeup(palmas, pdata->wakeup);
+	palmas_usb_wakeup(palmas, palmas_usb->wakeup);
 
 	platform_set_drvdata(pdev, palmas_usb);
 
-	palmas_usb->edev.name = "palmas-usb";
 	palmas_usb->edev.supported_cable = palmas_extcon_cable;
 	palmas_usb->edev.mutually_exclusive = mutually_exclusive;
 
@@ -182,28 +186,36 @@ static int palmas_usb_probe(struct platform_device *pdev)
 		return status;
 	}
 
-	status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq,
-			NULL, palmas_id_irq_handler,
-			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-			"palmas_usb_id", palmas_usb);
-	if (status < 0) {
-		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+	if (palmas_usb->enable_id_detection) {
+		status = devm_request_threaded_irq(palmas_usb->dev,
+				palmas_usb->id_irq,
+				NULL, palmas_id_irq_handler,
+				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+				IRQF_ONESHOT | IRQF_EARLY_RESUME,
+				"palmas_usb_id", palmas_usb);
+		if (status < 0) {
+			dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
 					palmas_usb->id_irq, status);
-		goto fail_extcon;
+			goto fail_extcon;
+		}
 	}
 
-	status = devm_request_threaded_irq(palmas_usb->dev,
-			palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler,
-			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-			"palmas_usb_vbus", palmas_usb);
-	if (status < 0) {
-		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+	if (palmas_usb->enable_vbus_detection) {
+		status = devm_request_threaded_irq(palmas_usb->dev,
+				palmas_usb->vbus_irq, NULL,
+				palmas_vbus_irq_handler,
+				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+				IRQF_ONESHOT | IRQF_EARLY_RESUME,
+				"palmas_usb_vbus", palmas_usb);
+		if (status < 0) {
+			dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
 					palmas_usb->vbus_irq, status);
-		goto fail_extcon;
+			goto fail_extcon;
+		}
 	}
 
 	palmas_enable_irq(palmas_usb);
-
+	device_set_wakeup_capable(&pdev->dev, true);
 	return 0;
 
 fail_extcon:
@@ -221,6 +233,39 @@ static int palmas_usb_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int palmas_usb_suspend(struct device *dev)
+{
+	struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev)) {
+		if (palmas_usb->enable_vbus_detection)
+			enable_irq_wake(palmas_usb->vbus_irq);
+		if (palmas_usb->enable_id_detection)
+			enable_irq_wake(palmas_usb->id_irq);
+	}
+	return 0;
+}
+
+static int palmas_usb_resume(struct device *dev)
+{
+	struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev)) {
+		if (palmas_usb->enable_vbus_detection)
+			disable_irq_wake(palmas_usb->vbus_irq);
+		if (palmas_usb->enable_id_detection)
+			disable_irq_wake(palmas_usb->id_irq);
+	}
+	return 0;
+};
+#endif
+
+static const struct dev_pm_ops palmas_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(palmas_usb_suspend,
+				palmas_usb_resume)
+};
+
 static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas-usb", },
 	{ .compatible = "ti,twl6035-usb", },
@@ -234,6 +279,7 @@ static struct platform_driver palmas_usb_driver = {
 		.name = "palmas-usb",
 		.of_match_table = of_palmas_match_tbl,
 		.owner = THIS_MODULE,
+		.pm = &palmas_pm_ops,
 	},
 };
 
diff --git a/drivers/extcon/of_extcon.c b/drivers/extcon/of_extcon.c
new file mode 100644
index 0000000..72173ec
--- /dev/null
+++ b/drivers/extcon/of_extcon.c
@@ -0,0 +1,64 @@
+/*
+ * OF helpers for External connector (extcon) framework
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ * Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * Copyright (C) 2013 Samsung Electronics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/extcon/of_extcon.h>
+
+/*
+ * of_extcon_get_extcon_dev - Get the name of extcon device from devicetree
+ * @dev - instance to the given device
+ * @index - index into list of extcon_dev
+ *
+ * return the instance of extcon device
+ */
+struct extcon_dev *of_extcon_get_extcon_dev(struct device *dev, int index)
+{
+	struct device_node *node;
+	struct extcon_dev *edev;
+	struct platform_device *extcon_parent_dev;
+
+	if (!dev->of_node) {
+		dev_dbg(dev, "device does not have a device node entry\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	node = of_parse_phandle(dev->of_node, "extcon", index);
+	if (!node) {
+		dev_dbg(dev, "failed to get phandle in %s node\n",
+			dev->of_node->full_name);
+		return ERR_PTR(-ENODEV);
+	}
+
+	extcon_parent_dev = of_find_device_by_node(node);
+	if (!extcon_parent_dev) {
+		dev_dbg(dev, "unable to find device by node\n");
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	edev = extcon_get_extcon_dev(dev_name(&extcon_parent_dev->dev));
+	if (!edev) {
+		dev_dbg(dev, "unable to get extcon device : %s\n",
+				dev_name(&extcon_parent_dev->dev));
+		return ERR_PTR(-ENODEV);
+	}
+
+	return edev;
+}
+EXPORT_SYMBOL_GPL(of_extcon_get_extcon_dev);
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index ac1b43a..d7d5c8a 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -486,7 +486,7 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
 static int add_client_resource(struct client *client,
 			       struct client_resource *resource, gfp_t gfp_mask)
 {
-	bool preload = gfp_mask & __GFP_WAIT;
+	bool preload = !!(gfp_mask & __GFP_WAIT);
 	unsigned long flags;
 	int ret;
 
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 28a94c7..e5af0e3 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -1262,8 +1262,7 @@ static int __init fw_core_init(void)
 {
 	int ret;
 
-	fw_workqueue = alloc_workqueue("firewire",
-				       WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
+	fw_workqueue = alloc_workqueue("firewire", WQ_MEM_RECLAIM, 0);
 	if (!fw_workqueue)
 		return -ENOMEM;
 
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 232fa8f..fa0affb 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -14,7 +14,7 @@
  * of and an antecedent to, SMBIOS, which stands for System
  * Management BIOS.  See further: http://www.dmtf.org/standards
  */
-static char dmi_empty_string[] = "        ";
+static const char dmi_empty_string[] = "        ";
 
 static u16 __initdata dmi_ver;
 /*
@@ -49,7 +49,7 @@ static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
 	return "";
 }
 
-static char * __init dmi_string(const struct dmi_header *dm, u8 s)
+static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
 {
 	const char *bp = dmi_string_nosave(dm, s);
 	char *str;
@@ -62,8 +62,6 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
 	str = dmi_alloc(len);
 	if (str != NULL)
 		strcpy(str, bp);
-	else
-		printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len);
 
 	return str;
 }
@@ -133,17 +131,18 @@ static int __init dmi_checksum(const u8 *buf, u8 len)
 	return sum == 0;
 }
 
-static char *dmi_ident[DMI_STRING_MAX];
+static const char *dmi_ident[DMI_STRING_MAX];
 static LIST_HEAD(dmi_devices);
 int dmi_available;
 
 /*
  *	Save a DMI string
  */
-static void __init dmi_save_ident(const struct dmi_header *dm, int slot, int string)
+static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
+		int string)
 {
-	const char *d = (const char*) dm;
-	char *p;
+	const char *d = (const char *) dm;
+	const char *p;
 
 	if (dmi_ident[slot])
 		return;
@@ -155,9 +154,10 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot, int str
 	dmi_ident[slot] = p;
 }
 
-static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int index)
+static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
+		int index)
 {
-	const u8 *d = (u8*) dm + index;
+	const u8 *d = (u8 *) dm + index;
 	char *s;
 	int is_ff = 1, is_00 = 1, i;
 
@@ -188,12 +188,13 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
 	else
 		sprintf(s, "%pUB", d);
 
-        dmi_ident[slot] = s;
+	dmi_ident[slot] = s;
 }
 
-static void __init dmi_save_type(const struct dmi_header *dm, int slot, int index)
+static void __init dmi_save_type(const struct dmi_header *dm, int slot,
+		int index)
 {
-	const u8 *d = (u8*) dm + index;
+	const u8 *d = (u8 *) dm + index;
 	char *s;
 
 	if (dmi_ident[slot])
@@ -216,10 +217,8 @@ static void __init dmi_save_one_device(int type, const char *name)
 		return;
 
 	dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
-	if (!dev) {
-		printk(KERN_ERR "dmi_save_one_device: out of memory.\n");
+	if (!dev)
 		return;
-	}
 
 	dev->type = type;
 	strcpy((char *)(dev + 1), name);
@@ -249,17 +248,14 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
 	struct dmi_device *dev;
 
 	for (i = 1; i <= count; i++) {
-		char *devname = dmi_string(dm, i);
+		const char *devname = dmi_string(dm, i);
 
 		if (devname == dmi_empty_string)
 			continue;
 
 		dev = dmi_alloc(sizeof(*dev));
-		if (!dev) {
-			printk(KERN_ERR
-			   "dmi_save_oem_strings_devices: out of memory.\n");
+		if (!dev)
 			break;
-		}
 
 		dev->type = DMI_DEV_TYPE_OEM_STRING;
 		dev->name = devname;
@@ -272,21 +268,17 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
 static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
 {
 	struct dmi_device *dev;
-	void * data;
+	void *data;
 
 	data = dmi_alloc(dm->length);
-	if (data == NULL) {
-		printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
+	if (data == NULL)
 		return;
-	}
 
 	memcpy(data, dm, dm->length);
 
 	dev = dmi_alloc(sizeof(*dev));
-	if (!dev) {
-		printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
+	if (!dev)
 		return;
-	}
 
 	dev->type = DMI_DEV_TYPE_IPMI;
 	dev->name = "IPMI controller";
@@ -301,10 +293,9 @@ static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
 	struct dmi_dev_onboard *onboard_dev;
 
 	onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
-	if (!onboard_dev) {
-		printk(KERN_ERR "dmi_save_dev_onboard: out of memory.\n");
+	if (!onboard_dev)
 		return;
-	}
+
 	onboard_dev->instance = instance;
 	onboard_dev->segment = segment;
 	onboard_dev->bus = bus;
@@ -320,7 +311,7 @@ static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
 
 static void __init dmi_save_extended_devices(const struct dmi_header *dm)
 {
-	const u8 *d = (u8*) dm + 5;
+	const u8 *d = (u8 *) dm + 5;
 
 	/* Skip disabled device */
 	if ((*d & 0x80) == 0)
@@ -338,7 +329,7 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
  */
 static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
 {
-	switch(dm->type) {
+	switch (dm->type) {
 	case 0:		/* BIOS Information */
 		dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
 		dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
@@ -502,13 +493,7 @@ void __init dmi_scan_machine(void)
 			dmi_available = 1;
 			goto out;
 		}
-	}
-	else {
-		/*
-		 * no iounmap() for that ioremap(); it would be a no-op, but
-		 * it's so early in setup that sucker gets confused into doing
-		 * what it shouldn't if we actually call it.
-		 */
+	} else {
 		p = dmi_ioremap(0xF0000, 0x10000);
 		if (p == NULL)
 			goto error;
@@ -533,7 +518,7 @@ void __init dmi_scan_machine(void)
 		dmi_iounmap(p, 0x10000);
 	}
  error:
-	printk(KERN_INFO "DMI not present or invalid.\n");
+	pr_info("DMI not present or invalid.\n");
  out:
 	dmi_initialized = 1;
 }
@@ -669,7 +654,7 @@ int dmi_name_in_serial(const char *str)
 
 /**
  *	dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
- *	@str: 	Case sensitive Name
+ *	@str: Case sensitive Name
  */
 int dmi_name_in_vendors(const char *str)
 {
@@ -696,13 +681,13 @@ EXPORT_SYMBOL(dmi_name_in_vendors);
  *	A new search is initiated by passing %NULL as the @from argument.
  *	If @from is not %NULL, searches continue from next device.
  */
-const struct dmi_device * dmi_find_device(int type, const char *name,
+const struct dmi_device *dmi_find_device(int type, const char *name,
 				    const struct dmi_device *from)
 {
 	const struct list_head *head = from ? &from->list : &dmi_devices;
 	struct list_head *d;
 
-	for(d = head->next; d != &dmi_devices; d = d->next) {
+	for (d = head->next; d != &dmi_devices; d = d->next) {
 		const struct dmi_device *dev =
 			list_entry(d, struct dmi_device, list);
 
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index acba0b9..6eb535f 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -525,7 +525,7 @@ static ssize_t gsmi_clear_eventlog_store(struct kobject *kobj,
 		u32 data_type;
 	} param;
 
-	rc = strict_strtoul(buf, 0, &val);
+	rc = kstrtoul(buf, 0, &val);
 	if (rc)
 		return rc;
 
diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c
index cc031db..ace6ef2 100644
--- a/drivers/fmc/fmc-chardev.c
+++ b/drivers/fmc/fmc-chardev.c
@@ -143,18 +143,17 @@ static int fc_probe(struct fmc_device *fmc)
 	fc->misc.fops = &fc_fops;
 	fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL);
 
-	spin_lock(&fc_lock);
 	ret = misc_register(&fc->misc);
 	if (ret < 0)
-		goto err_unlock;
+		goto out;
+	spin_lock(&fc_lock);
 	list_add(&fc->list, &fc_devices);
 	spin_unlock(&fc_lock);
 	dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n",
 		 fc->misc.name);
 	return 0;
 
-err_unlock:
-	spin_unlock(&fc_lock);
+out:
 	kfree(fc->misc.name);
 	kfree(fc);
 	return ret;
@@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc)
 
 	spin_lock(&fc_lock);
 	list_del(&fc->list);
+	spin_unlock(&fc_lock);
 	misc_deregister(&fc->misc);
 	kfree(fc->misc.name);
 	kfree(fc);
-	spin_unlock(&fc_lock);
 
 	return 0;
 }
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b2450ba..4b7ba53 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -242,6 +242,21 @@ config GPIO_TS5500
 	  blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
 	  LCD port.
 
+config GPIO_TZ1090
+	bool "Toumaz Xenif TZ1090 GPIO support"
+	depends on SOC_TZ1090
+	select GENERIC_IRQ_CHIP
+	default y
+	help
+	  Say yes here to support Toumaz Xenif TZ1090 GPIOs.
+
+config GPIO_TZ1090_PDC
+	bool "Toumaz Xenif TZ1090 PDC GPIO support"
+	depends on SOC_TZ1090
+	default y
+	help
+	  Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
+
 config GPIO_XILINX
 	bool "Xilinx GPIO support"
 	depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
@@ -676,6 +691,18 @@ config GPIO_UCB1400
 	  This enables support for the Philips UCB1400 GPIO pins.
 	  The UCB1400 is an AC97 audio codec.
 
+comment "LPC GPIO expanders:"
+
+config GPIO_KEMPLD
+	tristate "Kontron ETX / COMexpress GPIO"
+	depends on MFD_KEMPLD
+	help
+	  This enables support for the PLD GPIO interface on some Kontron ETX
+	  and COMexpress (ETXexpress) modules.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called gpio-kempld.
+
 comment "MODULbus GPIO expanders:"
 
 config GPIO_JANZ_TTL
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ef3e983..156fd28 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
+obj-$(CONFIG_GPIO_KEMPLD)	+= gpio-kempld.o
 obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o
 obj-$(CONFIG_GPIO_LANGWELL)	+= gpio-langwell.o
 obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o
@@ -79,6 +80,8 @@ obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
+obj-$(CONFIG_GPIO_TZ1090)	+= gpio-tz1090.o
+obj-$(CONFIG_GPIO_TZ1090_PDC)	+= gpio-tz1090-pdc.o
 obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
 obj-$(CONFIG_GPIO_VIPERBOARD)	+= gpio-viperboard.o
 obj-$(CONFIG_GPIO_VR41XX)	+= gpio-vr41xx.o
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index 5cba855..eca119b 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/gpio-em.h>
 
 struct em_gio_priv {
@@ -216,6 +217,21 @@ static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
 	return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 }
 
+static int em_gio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void em_gio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+
+	/* Set the GPIO as an input to ensure that the next GPIO request won't
+	* drive the GPIO pin as an output.
+	*/
+	em_gio_direction_input(chip, offset);
+}
+
 static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
 				 irq_hw_number_t hw)
 {
@@ -308,6 +324,8 @@ static int em_gio_probe(struct platform_device *pdev)
 	gpio_chip->direction_output = em_gio_direction_output;
 	gpio_chip->set = em_gio_set;
 	gpio_chip->to_irq = em_gio_to_irq;
+	gpio_chip->request = em_gio_request;
+	gpio_chip->free = em_gio_free;
 	gpio_chip->label = name;
 	gpio_chip->owner = THIS_MODULE;
 	gpio_chip->base = pdata->gpio_base;
@@ -351,6 +369,13 @@ static int em_gio_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failed to add GPIO controller\n");
 		goto err1;
 	}
+
+	if (pdata->pctl_name) {
+		ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0,
+					     gpio_chip->base, gpio_chip->ngpio);
+		if (ret < 0)
+			dev_warn(&pdev->dev, "failed to add pin range\n");
+	}
 	return 0;
 
 err1:
diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c
new file mode 100644
index 0000000..1bdc3a2
--- /dev/null
+++ b/drivers/gpio/gpio-kempld.c
@@ -0,0 +1,225 @@
+/*
+ * Kontron PLD GPIO driver
+ *
+ * Copyright (c) 2010-2013 Kontron Europe GmbH
+ * Author: Michael Brunner <michael.brunner@kontron.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mfd/kempld.h>
+
+#define KEMPLD_GPIO_MAX_NUM		16
+#define KEMPLD_GPIO_MASK(x)		(1 << ((x) % 8))
+#define KEMPLD_GPIO_DIR_NUM(x)		(0x40 + (x) / 8)
+#define KEMPLD_GPIO_LVL_NUM(x)		(0x42 + (x) / 8)
+#define KEMPLD_GPIO_EVT_LVL_EDGE	0x46
+#define KEMPLD_GPIO_IEN			0x4A
+
+struct kempld_gpio_data {
+	struct gpio_chip		chip;
+	struct kempld_device_data	*pld;
+};
+
+/*
+ * Set or clear GPIO bit
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+static void kempld_gpio_bitop(struct kempld_device_data *pld,
+			      u8 reg, u8 bit, u8 val)
+{
+	u8 status;
+
+	status = kempld_read8(pld, reg);
+	if (val)
+		status |= (1 << bit);
+	else
+		status &= ~(1 << bit);
+	kempld_write8(pld, reg, status);
+}
+
+static int kempld_gpio_get_bit(struct kempld_device_data *pld, u8 reg, u8 bit)
+{
+	u8 status;
+
+	kempld_get_mutex(pld);
+	status = kempld_read8(pld, reg);
+	kempld_release_mutex(pld);
+
+	return !!(status & (1 << bit));
+}
+
+static int kempld_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct kempld_gpio_data *gpio
+		= container_of(chip, struct kempld_gpio_data, chip);
+	struct kempld_device_data *pld = gpio->pld;
+
+	return kempld_gpio_get_bit(pld, KEMPLD_GPIO_LVL_NUM(offset),
+				   KEMPLD_GPIO_MASK(offset));
+}
+
+static void kempld_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct kempld_gpio_data *gpio
+		= container_of(chip, struct kempld_gpio_data, chip);
+	struct kempld_device_data *pld = gpio->pld;
+
+	kempld_get_mutex(pld);
+	kempld_gpio_bitop(pld, KEMPLD_GPIO_LVL_NUM(offset),
+			  KEMPLD_GPIO_MASK(offset), value);
+	kempld_release_mutex(pld);
+}
+
+static int kempld_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct kempld_gpio_data *gpio
+		= container_of(chip, struct kempld_gpio_data, chip);
+	struct kempld_device_data *pld = gpio->pld;
+
+	kempld_get_mutex(pld);
+	kempld_gpio_bitop(pld, KEMPLD_GPIO_DIR_NUM(offset),
+			  KEMPLD_GPIO_MASK(offset), 0);
+	kempld_release_mutex(pld);
+
+	return 0;
+}
+
+static int kempld_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int value)
+{
+	struct kempld_gpio_data *gpio
+		= container_of(chip, struct kempld_gpio_data, chip);
+	struct kempld_device_data *pld = gpio->pld;
+
+	kempld_get_mutex(pld);
+	kempld_gpio_bitop(pld, KEMPLD_GPIO_LVL_NUM(offset),
+			  KEMPLD_GPIO_MASK(offset), value);
+	kempld_gpio_bitop(pld, KEMPLD_GPIO_DIR_NUM(offset),
+			  KEMPLD_GPIO_MASK(offset), 1);
+	kempld_release_mutex(pld);
+
+	return 0;
+}
+
+static int kempld_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+	struct kempld_gpio_data *gpio
+		= container_of(chip, struct kempld_gpio_data, chip);
+	struct kempld_device_data *pld = gpio->pld;
+
+	return kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset),
+				   KEMPLD_GPIO_MASK(offset));
+}
+
+static int kempld_gpio_pincount(struct kempld_device_data *pld)
+{
+	u16 evt, evt_back;
+
+	kempld_get_mutex(pld);
+
+	/* Backup event register as it might be already initialized */
+	evt_back = kempld_read16(pld, KEMPLD_GPIO_EVT_LVL_EDGE);
+	/* Clear event register */
+	kempld_write16(pld, KEMPLD_GPIO_EVT_LVL_EDGE, 0x0000);
+	/* Read back event register */
+	evt = kempld_read16(pld, KEMPLD_GPIO_EVT_LVL_EDGE);
+	/* Restore event register */
+	kempld_write16(pld, KEMPLD_GPIO_EVT_LVL_EDGE, evt_back);
+
+	kempld_release_mutex(pld);
+
+	return evt ? __ffs(evt) : 16;
+}
+
+static int kempld_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct kempld_device_data *pld = dev_get_drvdata(dev->parent);
+	struct kempld_platform_data *pdata = pld->dev->platform_data;
+	struct kempld_gpio_data *gpio;
+	struct gpio_chip *chip;
+	int ret;
+
+	if (pld->info.spec_major < 2) {
+		dev_err(dev,
+			"Driver only supports GPIO devices compatible to PLD spec. rev. 2.0 or higher\n");
+		return -ENODEV;
+	}
+
+	gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
+	if (gpio == NULL)
+		return -ENOMEM;
+
+	gpio->pld = pld;
+
+	platform_set_drvdata(pdev, gpio);
+
+	chip = &gpio->chip;
+	chip->label = "gpio-kempld";
+	chip->owner = THIS_MODULE;
+	chip->dev = dev;
+	chip->can_sleep = 1;
+	if (pdata && pdata->gpio_base)
+		chip->base = pdata->gpio_base;
+	else
+		chip->base = -1;
+	chip->direction_input = kempld_gpio_direction_input;
+	chip->direction_output = kempld_gpio_direction_output;
+	chip->get_direction = kempld_gpio_get_direction;
+	chip->get = kempld_gpio_get;
+	chip->set = kempld_gpio_set;
+	chip->ngpio = kempld_gpio_pincount(pld);
+	if (chip->ngpio == 0) {
+		dev_err(dev, "No GPIO pins detected\n");
+		return -ENODEV;
+	}
+
+	ret = gpiochip_add(chip);
+	if (ret) {
+		dev_err(dev, "Could not register GPIO chip\n");
+		return ret;
+	}
+
+	dev_info(dev, "GPIO functionality initialized with %d pins\n",
+		 chip->ngpio);
+
+	return 0;
+}
+
+static int kempld_gpio_remove(struct platform_device *pdev)
+{
+	struct kempld_gpio_data *gpio = platform_get_drvdata(pdev);
+
+	return gpiochip_remove(&gpio->chip);
+}
+
+static struct platform_driver kempld_gpio_driver = {
+	.driver = {
+		.name = "gpio-kempld",
+		.owner = THIS_MODULE,
+	},
+	.probe		= kempld_gpio_probe,
+	.remove		= kempld_gpio_remove,
+};
+
+module_platform_driver(kempld_gpio_driver);
+
+MODULE_DESCRIPTION("KEM PLD GPIO Driver");
+MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-kempld");
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 7176743..875a7c5 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -405,34 +406,19 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 
 	mxc_gpio_get_hw(pdev);
 
-	port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
+	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
 	if (!port)
 		return -ENOMEM;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iores) {
-		err = -ENODEV;
-		goto out_kfree;
-	}
-
-	if (!request_mem_region(iores->start, resource_size(iores),
-				pdev->name)) {
-		err = -EBUSY;
-		goto out_kfree;
-	}
-
-	port->base = ioremap(iores->start, resource_size(iores));
-	if (!port->base) {
-		err = -ENOMEM;
-		goto out_release_mem;
-	}
+	port->base = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(port->base))
+		return PTR_ERR(port->base);
 
 	port->irq_high = platform_get_irq(pdev, 1);
 	port->irq = platform_get_irq(pdev, 0);
-	if (port->irq < 0) {
-		err = -EINVAL;
-		goto out_iounmap;
-	}
+	if (port->irq < 0)
+		return -EINVAL;
 
 	/* disable the interrupt and clear the status */
 	writel(0, port->base + GPIO_IMR);
@@ -462,7 +448,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 			 port->base + GPIO_DR, NULL,
 			 port->base + GPIO_GDIR, NULL, 0);
 	if (err)
-		goto out_iounmap;
+		goto out_bgio;
 
 	port->bgc.gc.to_irq = mxc_gpio_to_irq;
 	port->bgc.gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 :
@@ -498,12 +484,7 @@ out_gpiochip_remove:
 	WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
 out_bgpio_remove:
 	bgpio_remove(&port->bgc);
-out_iounmap:
-	iounmap(port->base);
-out_release_mem:
-	release_mem_region(iores->start, resource_size(iores));
-out_kfree:
-	kfree(port);
+out_bgio:
 	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
 	return err;
 }
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index e3a4e56..09360c4 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -134,7 +134,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
 	palmas_gpio->gpio_chip.get	= palmas_gpio_get;
 	palmas_gpio->gpio_chip.dev = &pdev->dev;
 #ifdef CONFIG_OF_GPIO
-	palmas_gpio->gpio_chip.of_node = palmas->dev->of_node;
+	palmas_gpio->gpio_chip.of_node = pdev->dev.of_node;
 #endif
 	palmas_pdata = dev_get_platdata(palmas->dev);
 	if (palmas_pdata && palmas_pdata->gpio_base)
@@ -159,9 +159,19 @@ static int palmas_gpio_remove(struct platform_device *pdev)
 	return gpiochip_remove(&palmas_gpio->gpio_chip);
 }
 
+static struct of_device_id of_palmas_gpio_match[] = {
+	{ .compatible = "ti,palmas-gpio"},
+	{ .compatible = "ti,tps65913-gpio"},
+	{ .compatible = "ti,tps65914-gpio"},
+	{ .compatible = "ti,tps80036-gpio"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
+
 static struct platform_driver palmas_gpio_driver = {
 	.driver.name	= "palmas-gpio",
 	.driver.owner	= THIS_MODULE,
+	.driver.of_match_table = of_palmas_gpio_match,
 	.probe		= palmas_gpio_probe,
 	.remove		= palmas_gpio_remove,
 };
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index df2199d..cc13d1b 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -524,8 +524,8 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
 
 static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
-	int ret, nr_gpios;
-	struct device_node *prev, *next, *np = pdev->dev.of_node;
+	int ret = 0, nr_gpios;
+	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
 	const struct pxa_gpio_id *gpio_id;
@@ -537,20 +537,13 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
 	gpio_id = of_id->data;
 	gpio_type = gpio_id->type;
 
-	next = of_get_next_child(np, NULL);
-	prev = next;
-	if (!next) {
-		dev_err(&pdev->dev, "Failed to find child gpio node\n");
-		ret = -EINVAL;
-		goto err;
-	}
-	of_node_put(prev);
 	nr_gpios = gpio_id->gpio_nums;
 	pxa_last_gpio = nr_gpios - 1;
 
 	irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
 	if (irq_base < 0) {
 		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+		ret = irq_base;
 		goto err;
 	}
 	domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
index 0be82c6..d420d30 100644
--- a/drivers/gpio/gpio-twl6040.c
+++ b/drivers/gpio/gpio-twl6040.c
@@ -84,15 +84,11 @@ static struct gpio_chip twl6040gpo_chip = {
 
 static int gpo_twl6040_probe(struct platform_device *pdev)
 {
-	struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
 	struct device *twl6040_core_dev = pdev->dev.parent;
 	struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
 	int ret;
 
-	if (pdata)
-		twl6040gpo_chip.base = pdata->gpio_base;
-	else
-		twl6040gpo_chip.base = -1;
+	twl6040gpo_chip.base = -1;
 
 	if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
 		twl6040gpo_chip.ngpio = 3; /* twl6040 have 3 GPO */
diff --git a/drivers/gpio/gpio-tz1090-pdc.c b/drivers/gpio/gpio-tz1090-pdc.c
new file mode 100644
index 0000000..f512da2
--- /dev/null
+++ b/drivers/gpio/gpio-tz1090-pdc.c
@@ -0,0 +1,243 @@
+/*
+ * Toumaz Xenif TZ1090 PDC GPIO handling.
+ *
+ * Copyright (C) 2012-2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <asm/global_lock.h>
+
+/* Register offsets from SOC_GPIO_CONTROL0 */
+#define REG_SOC_GPIO_CONTROL0	0x00
+#define REG_SOC_GPIO_CONTROL1	0x04
+#define REG_SOC_GPIO_CONTROL2	0x08
+#define REG_SOC_GPIO_CONTROL3	0x0c
+#define REG_SOC_GPIO_STATUS	0x80
+
+/* PDC GPIOs go after normal GPIOs */
+#define GPIO_PDC_BASE		90
+#define GPIO_PDC_NGPIO		7
+
+/* Out of PDC gpios, only syswakes have irqs */
+#define GPIO_PDC_IRQ_FIRST	2
+#define GPIO_PDC_NIRQ		3
+
+/**
+ * struct tz1090_pdc_gpio - GPIO bank private data
+ * @chip:	Generic GPIO chip for GPIO bank
+ * @reg:	Base of registers, offset for this GPIO bank
+ * @irq:	IRQ numbers for Syswake GPIOs
+ *
+ * This is the main private data for the PDC GPIO driver. It encapsulates a
+ * gpio_chip, and the callbacks for the gpio_chip can access the private data
+ * with the to_pdc() macro below.
+ */
+struct tz1090_pdc_gpio {
+	struct gpio_chip chip;
+	void __iomem *reg;
+	int irq[GPIO_PDC_NIRQ];
+};
+#define to_pdc(c)	container_of(c, struct tz1090_pdc_gpio, chip)
+
+/* Register accesses into the PDC MMIO area */
+
+static inline void pdc_write(struct tz1090_pdc_gpio *priv, unsigned int reg_offs,
+		      unsigned int data)
+{
+	writel(data, priv->reg + reg_offs);
+}
+
+static inline unsigned int pdc_read(struct tz1090_pdc_gpio *priv,
+			     unsigned int reg_offs)
+{
+	return readl(priv->reg + reg_offs);
+}
+
+/* Generic GPIO interface */
+
+static int tz1090_pdc_gpio_direction_input(struct gpio_chip *chip,
+					   unsigned int offset)
+{
+	struct tz1090_pdc_gpio *priv = to_pdc(chip);
+	u32 value;
+	int lstat;
+
+	__global_lock2(lstat);
+	value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
+	value |= BIT(offset);
+	pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
+	__global_unlock2(lstat);
+
+	return 0;
+}
+
+static int tz1090_pdc_gpio_direction_output(struct gpio_chip *chip,
+					    unsigned int offset,
+					    int output_value)
+{
+	struct tz1090_pdc_gpio *priv = to_pdc(chip);
+	u32 value;
+	int lstat;
+
+	__global_lock2(lstat);
+	/* EXT_POWER doesn't seem to have an output value bit */
+	if (offset < 6) {
+		value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
+		if (output_value)
+			value |= BIT(offset);
+		else
+			value &= ~BIT(offset);
+		pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
+	}
+
+	value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
+	value &= ~BIT(offset);
+	pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
+	__global_unlock2(lstat);
+
+	return 0;
+}
+
+static int tz1090_pdc_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tz1090_pdc_gpio *priv = to_pdc(chip);
+	return pdc_read(priv, REG_SOC_GPIO_STATUS) & BIT(offset);
+}
+
+static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset,
+				int output_value)
+{
+	struct tz1090_pdc_gpio *priv = to_pdc(chip);
+	u32 value;
+	int lstat;
+
+	/* EXT_POWER doesn't seem to have an output value bit */
+	if (offset >= 6)
+		return;
+
+	__global_lock2(lstat);
+	value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
+	if (output_value)
+		value |= BIT(offset);
+	else
+		value &= ~BIT(offset);
+	pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
+	__global_unlock2(lstat);
+}
+
+static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+}
+
+static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tz1090_pdc_gpio *priv = to_pdc(chip);
+	unsigned int syswake = offset - GPIO_PDC_IRQ_FIRST;
+	int irq;
+
+	/* only syswakes have irqs */
+	if (syswake >= GPIO_PDC_NIRQ)
+		return -EINVAL;
+
+	irq = priv->irq[syswake];
+	if (!irq)
+		return -EINVAL;
+
+	return irq;
+}
+
+static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res_regs;
+	struct tz1090_pdc_gpio *priv;
+	unsigned int i;
+
+	if (!np) {
+		dev_err(&pdev->dev, "must be instantiated via devicetree\n");
+		return -ENOENT;
+	}
+
+	res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_regs) {
+		dev_err(&pdev->dev, "cannot find registers resource\n");
+		return -ENOENT;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "unable to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	/* Ioremap the registers */
+	priv->reg = devm_ioremap(&pdev->dev, res_regs->start,
+				 res_regs->end - res_regs->start);
+	if (!priv->reg) {
+		dev_err(&pdev->dev, "unable to ioremap registers\n");
+		return -ENOMEM;
+	}
+
+	/* Set up GPIO chip */
+	priv->chip.label		= "tz1090-pdc-gpio";
+	priv->chip.dev			= &pdev->dev;
+	priv->chip.direction_input	= tz1090_pdc_gpio_direction_input;
+	priv->chip.direction_output	= tz1090_pdc_gpio_direction_output;
+	priv->chip.get			= tz1090_pdc_gpio_get;
+	priv->chip.set			= tz1090_pdc_gpio_set;
+	priv->chip.free			= tz1090_pdc_gpio_free;
+	priv->chip.request		= tz1090_pdc_gpio_request;
+	priv->chip.to_irq		= tz1090_pdc_gpio_to_irq;
+	priv->chip.of_node		= np;
+
+	/* GPIO numbering */
+	priv->chip.base			= GPIO_PDC_BASE;
+	priv->chip.ngpio		= GPIO_PDC_NGPIO;
+
+	/* Map the syswake irqs */
+	for (i = 0; i < GPIO_PDC_NIRQ; ++i)
+		priv->irq[i] = irq_of_parse_and_map(np, i);
+
+	/* Add the GPIO bank */
+	gpiochip_add(&priv->chip);
+
+	return 0;
+}
+
+static struct of_device_id tz1090_pdc_gpio_of_match[] = {
+	{ .compatible = "img,tz1090-pdc-gpio" },
+	{ },
+};
+
+static struct platform_driver tz1090_pdc_gpio_driver = {
+	.driver = {
+		.name		= "tz1090-pdc-gpio",
+		.owner		= THIS_MODULE,
+		.of_match_table	= tz1090_pdc_gpio_of_match,
+	},
+	.probe		= tz1090_pdc_gpio_probe,
+};
+
+static int __init tz1090_pdc_gpio_init(void)
+{
+	return platform_driver_register(&tz1090_pdc_gpio_driver);
+}
+subsys_initcall(tz1090_pdc_gpio_init);
diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c
new file mode 100644
index 0000000..23e0613
--- /dev/null
+++ b/drivers/gpio/gpio-tz1090.c
@@ -0,0 +1,606 @@
+/*
+ * Toumaz Xenif TZ1090 GPIO handling.
+ *
+ * Copyright (C) 2008-2013 Imagination Technologies Ltd.
+ *
+ *  Based on ARM PXA code and others.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/export.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <asm/global_lock.h>
+
+/* Register offsets from bank base address */
+#define REG_GPIO_DIR		0x00
+#define REG_GPIO_IRQ_PLRT	0x20
+#define REG_GPIO_IRQ_TYPE	0x30
+#define REG_GPIO_IRQ_EN		0x40
+#define REG_GPIO_IRQ_STS	0x50
+#define REG_GPIO_BIT_EN		0x60
+#define REG_GPIO_DIN		0x70
+#define REG_GPIO_DOUT		0x80
+
+/* REG_GPIO_IRQ_PLRT */
+#define REG_GPIO_IRQ_PLRT_LOW	0
+#define REG_GPIO_IRQ_PLRT_HIGH	1
+
+/* REG_GPIO_IRQ_TYPE */
+#define REG_GPIO_IRQ_TYPE_LEVEL	0
+#define REG_GPIO_IRQ_TYPE_EDGE	1
+
+/**
+ * struct tz1090_gpio_bank - GPIO bank private data
+ * @chip:	Generic GPIO chip for GPIO bank
+ * @domain:	IRQ domain for GPIO bank (may be NULL)
+ * @reg:	Base of registers, offset for this GPIO bank
+ * @irq:	IRQ number for GPIO bank
+ * @label:	Debug GPIO bank label, used for storage of chip->label
+ *
+ * This is the main private data for a GPIO bank. It encapsulates a gpio_chip,
+ * and the callbacks for the gpio_chip can access the private data with the
+ * to_bank() macro below.
+ */
+struct tz1090_gpio_bank {
+	struct gpio_chip chip;
+	struct irq_domain *domain;
+	void __iomem *reg;
+	int irq;
+	char label[16];
+};
+#define to_bank(c)	container_of(c, struct tz1090_gpio_bank, chip)
+
+/**
+ * struct tz1090_gpio - Overall GPIO device private data
+ * @dev:	Device (from platform device)
+ * @reg:	Base of GPIO registers
+ *
+ * Represents the overall GPIO device. This structure is actually only
+ * temporary, and used during init.
+ */
+struct tz1090_gpio {
+	struct device *dev;
+	void __iomem *reg;
+};
+
+/**
+ * struct tz1090_gpio_bank_info - Temporary registration info for GPIO bank
+ * @priv:	Overall GPIO device private data
+ * @node:	Device tree node specific to this GPIO bank
+ * @index:	Index of bank in range 0-2
+ */
+struct tz1090_gpio_bank_info {
+	struct tz1090_gpio *priv;
+	struct device_node *node;
+	unsigned int index;
+};
+
+/* Convenience register accessors */
+static inline void tz1090_gpio_write(struct tz1090_gpio_bank *bank,
+			      unsigned int reg_offs, u32 data)
+{
+	iowrite32(data, bank->reg + reg_offs);
+}
+
+static inline u32 tz1090_gpio_read(struct tz1090_gpio_bank *bank,
+			    unsigned int reg_offs)
+{
+	return ioread32(bank->reg + reg_offs);
+}
+
+/* caller must hold LOCK2 */
+static inline void _tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank,
+					  unsigned int reg_offs,
+					  unsigned int offset)
+{
+	u32 value;
+
+	value = tz1090_gpio_read(bank, reg_offs);
+	value &= ~BIT(offset);
+	tz1090_gpio_write(bank, reg_offs, value);
+}
+
+static void tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank,
+				  unsigned int reg_offs,
+				  unsigned int offset)
+{
+	int lstat;
+
+	__global_lock2(lstat);
+	_tz1090_gpio_clear_bit(bank, reg_offs, offset);
+	__global_unlock2(lstat);
+}
+
+/* caller must hold LOCK2 */
+static inline void _tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank,
+					unsigned int reg_offs,
+					unsigned int offset)
+{
+	u32 value;
+
+	value = tz1090_gpio_read(bank, reg_offs);
+	value |= BIT(offset);
+	tz1090_gpio_write(bank, reg_offs, value);
+}
+
+static void tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank,
+				unsigned int reg_offs,
+				unsigned int offset)
+{
+	int lstat;
+
+	__global_lock2(lstat);
+	_tz1090_gpio_set_bit(bank, reg_offs, offset);
+	__global_unlock2(lstat);
+}
+
+/* caller must hold LOCK2 */
+static inline void _tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank,
+					unsigned int reg_offs,
+					unsigned int offset,
+					bool val)
+{
+	u32 value;
+
+	value = tz1090_gpio_read(bank, reg_offs);
+	value &= ~BIT(offset);
+	if (val)
+		value |= BIT(offset);
+	tz1090_gpio_write(bank, reg_offs, value);
+}
+
+static void tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank,
+				unsigned int reg_offs,
+				unsigned int offset,
+				bool val)
+{
+	int lstat;
+
+	__global_lock2(lstat);
+	_tz1090_gpio_mod_bit(bank, reg_offs, offset, val);
+	__global_unlock2(lstat);
+}
+
+static inline int tz1090_gpio_read_bit(struct tz1090_gpio_bank *bank,
+				       unsigned int reg_offs,
+				       unsigned int offset)
+{
+	return tz1090_gpio_read(bank, reg_offs) & BIT(offset);
+}
+
+/* GPIO chip callbacks */
+
+static int tz1090_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+	tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset);
+
+	return 0;
+}
+
+static int tz1090_gpio_direction_output(struct gpio_chip *chip,
+					unsigned int offset, int output_value)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+	int lstat;
+
+	__global_lock2(lstat);
+	_tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value);
+	_tz1090_gpio_clear_bit(bank, REG_GPIO_DIR, offset);
+	__global_unlock2(lstat);
+
+	return 0;
+}
+
+/*
+ * Return GPIO level
+ */
+static int tz1090_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+
+	return tz1090_gpio_read_bit(bank, REG_GPIO_DIN, offset);
+}
+
+/*
+ * Set output GPIO level
+ */
+static void tz1090_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			    int output_value)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+
+	tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value);
+}
+
+static int tz1090_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+	int ret;
+
+	ret = pinctrl_request_gpio(chip->base + offset);
+	if (ret)
+		return ret;
+
+	tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset);
+	tz1090_gpio_set_bit(bank, REG_GPIO_BIT_EN, offset);
+
+	return 0;
+}
+
+static void tz1090_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+
+	pinctrl_free_gpio(chip->base + offset);
+
+	tz1090_gpio_clear_bit(bank, REG_GPIO_BIT_EN, offset);
+}
+
+static int tz1090_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct tz1090_gpio_bank *bank = to_bank(chip);
+
+	if (!bank->domain)
+		return -EINVAL;
+
+	return irq_create_mapping(bank->domain, offset);
+}
+
+/* IRQ chip handlers */
+
+/* Get TZ1090 GPIO chip from irq data provided to generic IRQ callbacks */
+static inline struct tz1090_gpio_bank *irqd_to_gpio_bank(struct irq_data *data)
+{
+	return (struct tz1090_gpio_bank *)data->domain->host_data;
+}
+
+static void tz1090_gpio_irq_polarity(struct tz1090_gpio_bank *bank,
+				     unsigned int offset, unsigned int polarity)
+{
+	tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_PLRT, offset, polarity);
+}
+
+static void tz1090_gpio_irq_type(struct tz1090_gpio_bank *bank,
+				 unsigned int offset, unsigned int type)
+{
+	tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_TYPE, offset, type);
+}
+
+/* set polarity to trigger on next edge, whether rising or falling */
+static void tz1090_gpio_irq_next_edge(struct tz1090_gpio_bank *bank,
+				      unsigned int offset)
+{
+	unsigned int value_p, value_i;
+	int lstat;
+
+	/*
+	 * Set the GPIO's interrupt polarity to the opposite of the current
+	 * input value so that the next edge triggers an interrupt.
+	 */
+	__global_lock2(lstat);
+	value_i = ~tz1090_gpio_read(bank, REG_GPIO_DIN);
+	value_p = tz1090_gpio_read(bank, REG_GPIO_IRQ_PLRT);
+	value_p &= ~BIT(offset);
+	value_p |= value_i & BIT(offset);
+	tz1090_gpio_write(bank, REG_GPIO_IRQ_PLRT, value_p);
+	__global_unlock2(lstat);
+}
+
+static unsigned int gpio_startup_irq(struct irq_data *data)
+{
+	/*
+	 * This warning indicates that the type of the irq hasn't been set
+	 * before enabling the irq. This would normally be done by passing some
+	 * trigger flags to request_irq().
+	 */
+	WARN(irqd_get_trigger_type(data) == IRQ_TYPE_NONE,
+		"irq type not set before enabling gpio irq %d", data->irq);
+
+	irq_gc_ack_clr_bit(data);
+	irq_gc_mask_set_bit(data);
+	return 0;
+}
+
+static int gpio_set_irq_type(struct irq_data *data, unsigned int flow_type)
+{
+	struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data);
+	unsigned int type;
+	unsigned int polarity;
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_BOTH:
+		type = REG_GPIO_IRQ_TYPE_EDGE;
+		polarity = REG_GPIO_IRQ_PLRT_LOW;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		type = REG_GPIO_IRQ_TYPE_EDGE;
+		polarity = REG_GPIO_IRQ_PLRT_HIGH;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		type = REG_GPIO_IRQ_TYPE_EDGE;
+		polarity = REG_GPIO_IRQ_PLRT_LOW;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		type = REG_GPIO_IRQ_TYPE_LEVEL;
+		polarity = REG_GPIO_IRQ_PLRT_HIGH;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		type = REG_GPIO_IRQ_TYPE_LEVEL;
+		polarity = REG_GPIO_IRQ_PLRT_LOW;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	tz1090_gpio_irq_type(bank, data->hwirq, type);
+	irq_setup_alt_chip(data, flow_type);
+
+	if (flow_type == IRQ_TYPE_EDGE_BOTH)
+		tz1090_gpio_irq_next_edge(bank, data->hwirq);
+	else
+		tz1090_gpio_irq_polarity(bank, data->hwirq, polarity);
+
+	return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+static int gpio_set_irq_wake(struct irq_data *data, unsigned int on)
+{
+	struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data);
+
+#ifdef CONFIG_PM_DEBUG
+	pr_info("irq_wake irq%d state:%d\n", data->irq, on);
+#endif
+
+	/* wake on gpio block interrupt */
+	return irq_set_irq_wake(bank->irq, on);
+}
+#else
+#define gpio_set_irq_wake NULL
+#endif
+
+static void tz1090_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	irq_hw_number_t hw;
+	unsigned int irq_stat, irq_no;
+	struct tz1090_gpio_bank *bank;
+	struct irq_desc *child_desc;
+
+	bank = (struct tz1090_gpio_bank *)irq_desc_get_handler_data(desc);
+	irq_stat = tz1090_gpio_read(bank, REG_GPIO_DIR) &
+		   tz1090_gpio_read(bank, REG_GPIO_IRQ_STS) &
+		   tz1090_gpio_read(bank, REG_GPIO_IRQ_EN) &
+		   0x3FFFFFFF; /* 30 bits only */
+
+	for (hw = 0; irq_stat; irq_stat >>= 1, ++hw) {
+		if (!(irq_stat & 1))
+			continue;
+
+		irq_no = irq_linear_revmap(bank->domain, hw);
+		child_desc = irq_to_desc(irq_no);
+
+		/* Toggle edge for pin with both edges triggering enabled */
+		if (irqd_get_trigger_type(&child_desc->irq_data)
+				== IRQ_TYPE_EDGE_BOTH)
+			tz1090_gpio_irq_next_edge(bank, hw);
+
+		generic_handle_irq_desc(irq_no, child_desc);
+	}
+}
+
+static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info)
+{
+	struct device_node *np = info->node;
+	struct device *dev = info->priv->dev;
+	struct tz1090_gpio_bank *bank;
+	struct irq_chip_generic *gc;
+	int err;
+
+	bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
+	if (!bank) {
+		dev_err(dev, "unable to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	/* Offset the main registers to the first register in this bank */
+	bank->reg = info->priv->reg + info->index * 4;
+
+	/* Set up GPIO chip */
+	snprintf(bank->label, sizeof(bank->label), "tz1090-gpio-%u",
+		 info->index);
+	bank->chip.label		= bank->label;
+	bank->chip.dev			= dev;
+	bank->chip.direction_input	= tz1090_gpio_direction_input;
+	bank->chip.direction_output	= tz1090_gpio_direction_output;
+	bank->chip.get			= tz1090_gpio_get;
+	bank->chip.set			= tz1090_gpio_set;
+	bank->chip.free			= tz1090_gpio_free;
+	bank->chip.request		= tz1090_gpio_request;
+	bank->chip.to_irq		= tz1090_gpio_to_irq;
+	bank->chip.of_node		= np;
+
+	/* GPIO numbering from 0 */
+	bank->chip.base			= info->index * 30;
+	bank->chip.ngpio		= 30;
+
+	/* Add the GPIO bank */
+	gpiochip_add(&bank->chip);
+
+	/* Get the GPIO bank IRQ if provided */
+	bank->irq = irq_of_parse_and_map(np, 0);
+
+	/* The interrupt is optional (it may be used by another core on chip) */
+	if (bank->irq < 0) {
+		dev_info(dev, "IRQ not provided for bank %u, IRQs disabled\n",
+			 info->index);
+		return 0;
+	}
+
+	dev_info(dev, "Setting up IRQs for GPIO bank %u\n",
+		 info->index);
+
+	/*
+	 * Initialise all interrupts to disabled so we don't get
+	 * spurious ones on a dirty boot and hit the BUG_ON in the
+	 * handler.
+	 */
+	tz1090_gpio_write(bank, REG_GPIO_IRQ_EN, 0);
+
+	/* Add a virtual IRQ for each GPIO */
+	bank->domain = irq_domain_add_linear(np,
+					     bank->chip.ngpio,
+					     &irq_generic_chip_ops,
+					     bank);
+
+	/* Set up a generic irq chip with 2 chip types (level and edge) */
+	err = irq_alloc_domain_generic_chips(bank->domain, bank->chip.ngpio, 2,
+					     bank->label, handle_bad_irq, 0, 0,
+					     IRQ_GC_INIT_NESTED_LOCK);
+	if (err) {
+		dev_info(dev,
+			 "irq_alloc_domain_generic_chips failed for bank %u, IRQs disabled\n",
+			 info->index);
+		irq_domain_remove(bank->domain);
+		return 0;
+	}
+
+	gc = irq_get_domain_generic_chip(bank->domain, 0);
+	gc->reg_base	= bank->reg;
+
+	/* level chip type */
+	gc->chip_types[0].type			= IRQ_TYPE_LEVEL_MASK;
+	gc->chip_types[0].handler		= handle_level_irq;
+	gc->chip_types[0].regs.ack		= REG_GPIO_IRQ_STS;
+	gc->chip_types[0].regs.mask		= REG_GPIO_IRQ_EN;
+	gc->chip_types[0].chip.irq_startup	= gpio_startup_irq,
+	gc->chip_types[0].chip.irq_ack		= irq_gc_ack_clr_bit,
+	gc->chip_types[0].chip.irq_mask		= irq_gc_mask_clr_bit,
+	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit,
+	gc->chip_types[0].chip.irq_set_type	= gpio_set_irq_type,
+	gc->chip_types[0].chip.irq_set_wake	= gpio_set_irq_wake,
+	gc->chip_types[0].chip.flags		= IRQCHIP_MASK_ON_SUSPEND,
+
+	/* edge chip type */
+	gc->chip_types[1].type			= IRQ_TYPE_EDGE_BOTH;
+	gc->chip_types[1].handler		= handle_edge_irq;
+	gc->chip_types[1].regs.ack		= REG_GPIO_IRQ_STS;
+	gc->chip_types[1].regs.mask		= REG_GPIO_IRQ_EN;
+	gc->chip_types[1].chip.irq_startup	= gpio_startup_irq,
+	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_clr_bit,
+	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit,
+	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit,
+	gc->chip_types[1].chip.irq_set_type	= gpio_set_irq_type,
+	gc->chip_types[1].chip.irq_set_wake	= gpio_set_irq_wake,
+	gc->chip_types[1].chip.flags		= IRQCHIP_MASK_ON_SUSPEND,
+
+	/* Setup chained handler for this GPIO bank */
+	irq_set_handler_data(bank->irq, bank);
+	irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler);
+
+	return 0;
+}
+
+static void tz1090_gpio_register_banks(struct tz1090_gpio *priv)
+{
+	struct device_node *np = priv->dev->of_node;
+	struct device_node *node;
+
+	for_each_available_child_of_node(np, node) {
+		struct tz1090_gpio_bank_info info;
+		u32 addr;
+		int ret;
+
+		ret = of_property_read_u32(node, "reg", &addr);
+		if (ret) {
+			dev_err(priv->dev, "invalid reg on %s\n",
+				node->full_name);
+			continue;
+		}
+		if (addr >= 3) {
+			dev_err(priv->dev, "index %u in %s out of range\n",
+				addr, node->full_name);
+			continue;
+		}
+
+		info.index = addr;
+		info.node = of_node_get(node);
+		info.priv = priv;
+
+		ret = tz1090_gpio_bank_probe(&info);
+		if (ret) {
+			dev_err(priv->dev, "failure registering %s\n",
+				node->full_name);
+			of_node_put(node);
+			continue;
+		}
+	}
+}
+
+static int tz1090_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res_regs;
+	struct tz1090_gpio priv;
+
+	if (!np) {
+		dev_err(&pdev->dev, "must be instantiated via devicetree\n");
+		return -ENOENT;
+	}
+
+	res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_regs) {
+		dev_err(&pdev->dev, "cannot find registers resource\n");
+		return -ENOENT;
+	}
+
+	priv.dev = &pdev->dev;
+
+	/* Ioremap the registers */
+	priv.reg = devm_ioremap(&pdev->dev, res_regs->start,
+				 res_regs->end - res_regs->start);
+	if (!priv.reg) {
+		dev_err(&pdev->dev, "unable to ioremap registers\n");
+		return -ENOMEM;
+	}
+
+	/* Look for banks */
+	tz1090_gpio_register_banks(&priv);
+
+	return 0;
+}
+
+static struct of_device_id tz1090_gpio_of_match[] = {
+	{ .compatible = "img,tz1090-gpio" },
+	{ },
+};
+
+static struct platform_driver tz1090_gpio_driver = {
+	.driver = {
+		.name		= "tz1090-gpio",
+		.owner		= THIS_MODULE,
+		.of_match_table	= tz1090_gpio_of_match,
+	},
+	.probe		= tz1090_gpio_probe,
+};
+
+static int __init tz1090_gpio_init(void)
+{
+	return platform_driver_register(&tz1090_gpio_driver);
+}
+subsys_initcall(tz1090_gpio_init);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index ff0fd65..d6413b2 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -349,7 +349,7 @@ static ssize_t gpio_value_store(struct device *dev,
 	else {
 		long		value;
 
-		status = strict_strtol(buf, 0, &value);
+		status = kstrtol(buf, 0, &value);
 		if (status == 0) {
 			if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
 				value = !value;
@@ -570,7 +570,7 @@ static ssize_t gpio_active_low_store(struct device *dev,
 	} else {
 		long		value;
 
-		status = strict_strtol(buf, 0, &value);
+		status = kstrtol(buf, 0, &value);
 		if (status == 0)
 			status = sysfs_set_active_low(desc, dev, value != 0);
 	}
@@ -652,7 +652,7 @@ static ssize_t export_store(struct class *class,
 	struct gpio_desc	*desc;
 	int			status;
 
-	status = strict_strtol(buf, 0, &gpio);
+	status = kstrtol(buf, 0, &gpio);
 	if (status < 0)
 		goto done;
 
@@ -694,7 +694,7 @@ static ssize_t unexport_store(struct class *class,
 	struct gpio_desc	*desc;
 	int			status;
 
-	status = strict_strtol(buf, 0, &gpio);
+	status = kstrtol(buf, 0, &gpio);
 	if (status < 0)
 		goto done;
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 801bcaf..d943b94 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -13,7 +13,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
 		drm_trace_points.o drm_global.o drm_prime.o \
-		drm_rect.o
+		drm_rect.o drm_vma_manager.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index df0d0a0..a144fb0 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -216,7 +216,7 @@ static struct drm_driver driver = {
 	.gem_free_object = ast_gem_free_object,
 	.dumb_create = ast_dumb_create,
 	.dumb_map_offset = ast_dumb_mmap_offset,
-	.dumb_destroy = ast_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 
 };
 
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 622d4ae..796dbb2 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -322,9 +322,6 @@ ast_bo(struct ttm_buffer_object *bo)
 extern int ast_dumb_create(struct drm_file *file,
 			   struct drm_device *dev,
 			   struct drm_mode_create_dumb *args);
-extern int ast_dumb_destroy(struct drm_file *file,
-			    struct drm_device *dev,
-			    uint32_t handle);
 
 extern int ast_gem_init_object(struct drm_gem_object *obj);
 extern void ast_gem_free_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index f60fd7b..7f6152d 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -449,13 +449,6 @@ int ast_dumb_create(struct drm_file *file,
 	return 0;
 }
 
-int ast_dumb_destroy(struct drm_file *file,
-		     struct drm_device *dev,
-		     uint32_t handle)
-{
-	return drm_gem_handle_delete(file, handle);
-}
-
 int ast_gem_init_object(struct drm_gem_object *obj)
 {
 	BUG();
@@ -487,7 +480,7 @@ void ast_gem_free_object(struct drm_gem_object *obj)
 
 static inline u64 ast_bo_mmap_offset(struct ast_bo *bo)
 {
-	return bo->bo.addr_space_offset;
+	return drm_vma_node_offset_addr(&bo->bo.vma_node);
 }
 int
 ast_dumb_mmap_offset(struct drm_file *file,
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 8ecb601..d35d99c 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -102,7 +102,7 @@ static struct drm_driver driver = {
 	.gem_free_object = cirrus_gem_free_object,
 	.dumb_create = cirrus_dumb_create,
 	.dumb_map_offset = cirrus_dumb_mmap_offset,
-	.dumb_destroy = cirrus_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 };
 
 static struct pci_driver cirrus_pci_driver = {
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index bae5560..9b0bb91 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -203,9 +203,6 @@ int cirrus_gem_create(struct drm_device *dev,
 int cirrus_dumb_create(struct drm_file *file,
 		    struct drm_device *dev,
 		       struct drm_mode_create_dumb *args);
-int cirrus_dumb_destroy(struct drm_file *file,
-		     struct drm_device *dev,
-			uint32_t handle);
 
 int cirrus_framebuffer_init(struct drm_device *dev,
 			   struct cirrus_framebuffer *gfb,
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index 35cbae8..f130a53 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -255,13 +255,6 @@ int cirrus_dumb_create(struct drm_file *file,
 	return 0;
 }
 
-int cirrus_dumb_destroy(struct drm_file *file,
-		     struct drm_device *dev,
-		     uint32_t handle)
-{
-	return drm_gem_handle_delete(file, handle);
-}
-
 int cirrus_gem_init_object(struct drm_gem_object *obj)
 {
 	BUG();
@@ -294,7 +287,7 @@ void cirrus_gem_free_object(struct drm_gem_object *obj)
 
 static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
 {
-	return bo->bo.addr_space_offset;
+	return drm_vma_node_offset_addr(&bo->bo.vma_node);
 }
 
 int
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 60685b2..379a47e 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -273,8 +273,8 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
 		sr07 |= 0x11;
 		break;
 	case 16:
-		sr07 |= 0xc1;
-		hdr = 0xc0;
+		sr07 |= 0x17;
+		hdr = 0xc1;
 		break;
 	case 24:
 		sr07 |= 0x15;
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index 3d8fed1..e301d65 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -424,6 +424,57 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 }
 
 /**
+ * drm_agp_clear - Clear AGP resource list
+ * @dev: DRM device
+ *
+ * Iterate over all AGP resources and remove them. But keep the AGP head
+ * intact so it can still be used. It is safe to call this if AGP is disabled or
+ * was already removed.
+ *
+ * If DRIVER_MODESET is active, nothing is done to protect the modesetting
+ * resources from getting destroyed. Drivers are responsible of cleaning them up
+ * during device shutdown.
+ */
+void drm_agp_clear(struct drm_device *dev)
+{
+	struct drm_agp_mem *entry, *tempe;
+
+	if (!drm_core_has_AGP(dev) || !dev->agp)
+		return;
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
+
+	list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
+		if (entry->bound)
+			drm_unbind_agp(entry->memory);
+		drm_free_agp(entry->memory, entry->pages);
+		kfree(entry);
+	}
+	INIT_LIST_HEAD(&dev->agp->memory);
+
+	if (dev->agp->acquired)
+		drm_agp_release(dev);
+
+	dev->agp->acquired = 0;
+	dev->agp->enabled = 0;
+}
+
+/**
+ * drm_agp_destroy - Destroy AGP head
+ * @dev: DRM device
+ *
+ * Destroy resources that were previously allocated via drm_agp_initp. Caller
+ * must ensure to clean up all AGP resources before calling this. See
+ * drm_agp_clear().
+ *
+ * Call this to destroy AGP heads allocated via drm_agp_init().
+ */
+void drm_agp_destroy(struct drm_agp_head *agp)
+{
+	kfree(agp);
+}
+
+/**
  * Binds a collection of pages into AGP memory at the given offset, returning
  * the AGP memory structure containing them.
  *
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 5a4dbb4..bef4abf 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -243,7 +243,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
 		}
 		map->handle = vmalloc_user(map->size);
 		DRM_DEBUG("%lu %d %p\n",
-			  map->size, drm_order(map->size), map->handle);
+			  map->size, order_base_2(map->size), map->handle);
 		if (!map->handle) {
 			kfree(map);
 			return -ENOMEM;
@@ -630,7 +630,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
 		return -EINVAL;
 
 	count = request->count;
-	order = drm_order(request->size);
+	order = order_base_2(request->size);
 	size = 1 << order;
 
 	alignment = (request->flags & _DRM_PAGE_ALIGN)
@@ -800,7 +800,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
 		return -EPERM;
 
 	count = request->count;
-	order = drm_order(request->size);
+	order = order_base_2(request->size);
 	size = 1 << order;
 
 	DRM_DEBUG("count=%d, size=%d (%d), order=%d\n",
@@ -1002,7 +1002,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request
 		return -EPERM;
 
 	count = request->count;
-	order = drm_order(request->size);
+	order = order_base_2(request->size);
 	size = 1 << order;
 
 	alignment = (request->flags & _DRM_PAGE_ALIGN)
@@ -1157,7 +1157,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request
 		return -EPERM;
 
 	count = request->count;
-	order = drm_order(request->size);
+	order = order_base_2(request->size);
 	size = 1 << order;
 
 	alignment = (request->flags & _DRM_PAGE_ALIGN)
@@ -1435,7 +1435,7 @@ int drm_markbufs(struct drm_device *dev, void *data,
 
 	DRM_DEBUG("%d, %d, %d\n",
 		  request->size, request->low_mark, request->high_mark);
-	order = drm_order(request->size);
+	order = order_base_2(request->size);
 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
 		return -EINVAL;
 	entry = &dma->bufs[order];
@@ -1600,25 +1600,16 @@ int drm_mapbufs(struct drm_device *dev, void *data,
 	return retcode;
 }
 
-/**
- * Compute size order.  Returns the exponent of the smaller power of two which
- * is greater or equal to given number.
- *
- * \param size size.
- * \return order.
- *
- * \todo Can be made faster.
- */
-int drm_order(unsigned long size)
+struct drm_local_map *drm_getsarea(struct drm_device *dev)
 {
-	int order;
-	unsigned long tmp;
-
-	for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
-
-	if (size & (size - 1))
-		++order;
+	struct drm_map_list *entry;
 
-	return order;
+	list_for_each_entry(entry, &dev->maplist, head) {
+		if (entry->map && entry->map->type == _DRM_SHM &&
+		    (entry->map->flags & _DRM_CONTAINS_LOCK)) {
+			return entry->map;
+		}
+	}
+	return NULL;
 }
-EXPORT_SYMBOL(drm_order);
+EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index 725968d..224ff96 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -251,7 +251,6 @@ static int drm_context_switch_complete(struct drm_device *dev,
 				       struct drm_file *file_priv, int new)
 {
 	dev->last_context = new;	/* PRE/POST: This is the _only_ writer. */
-	dev->last_switch = jiffies;
 
 	if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
 		DRM_ERROR("Lock isn't held after context switch\n");
@@ -261,7 +260,6 @@ static int drm_context_switch_complete(struct drm_device *dev,
 	   when the kernel holds the lock, release
 	   that lock here. */
 	clear_bit(0, &dev->context_flag);
-	wake_up(&dev->context_wait);
 
 	return 0;
 }
@@ -342,12 +340,6 @@ int drm_addctx(struct drm_device *dev, void *data,
 	return 0;
 }
 
-int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	/* This does nothing */
-	return 0;
-}
-
 /**
  * Get context.
  *
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 99fcd7c..dddd799 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -87,7 +87,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 
 	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -122,7 +122,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 #endif
 
-	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
@@ -195,27 +195,8 @@ int drm_lastclose(struct drm_device * dev)
 
 	mutex_lock(&dev->struct_mutex);
 
-	/* Clear AGP information */
-	if (drm_core_has_AGP(dev) && dev->agp &&
-			!drm_core_check_feature(dev, DRIVER_MODESET)) {
-		struct drm_agp_mem *entry, *tempe;
-
-		/* Remove AGP resources, but leave dev->agp
-		   intact until drv_cleanup is called. */
-		list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
-			if (entry->bound)
-				drm_unbind_agp(entry->memory);
-			drm_free_agp(entry->memory, entry->pages);
-			kfree(entry);
-		}
-		INIT_LIST_HEAD(&dev->agp->memory);
-
-		if (dev->agp->acquired)
-			drm_agp_release(dev);
+	drm_agp_clear(dev);
 
-		dev->agp->acquired = 0;
-		dev->agp->enabled = 0;
-	}
 	if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg &&
 	    !drm_core_check_feature(dev, DRIVER_MODESET)) {
 		drm_sg_cleanup(dev->sg);
@@ -485,19 +466,4 @@ long drm_ioctl(struct file *filp,
 		DRM_DEBUG("ret = %d\n", retcode);
 	return retcode;
 }
-
 EXPORT_SYMBOL(drm_ioctl);
-
-struct drm_local_map *drm_getsarea(struct drm_device *dev)
-{
-	struct drm_map_list *entry;
-
-	list_for_each_entry(entry, &dev->maplist, head) {
-		if (entry->map && entry->map->type == _DRM_SHM &&
-		    (entry->map->flags & _DRM_CONTAINS_LOCK)) {
-			return entry->map;
-		}
-	}
-	return NULL;
-}
-EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 95d6f4b..dfc7a1b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3102,11 +3102,13 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 	if (err < 0)
 		return err;
 
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		frame->pixel_repeat = 1;
+
 	frame->video_code = drm_match_cea_mode(mode);
-	if (!frame->video_code)
-		return 0;
 
 	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
+	frame->active_info_valid = 1;
 	frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
 
 	return 0;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3d13ca6e2..f6f6cc7 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -416,6 +416,14 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 		return;
 
 	/*
+	 * fbdev->blank can be called from irq context in case of a panic.
+	 * Since we already have our own special panic handler which will
+	 * restore the fbdev console mode completely, just bail out early.
+	 */
+	if (oops_in_progress)
+		return;
+
+	/*
 	 * For each CRTC in this fb, turn the connectors on/off.
 	 */
 	drm_modeset_lock_all(dev);
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 3a24385..72acae9 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -76,20 +76,10 @@ static int drm_setup(struct drm_device * dev)
 	dev->sigdata.lock = NULL;
 
 	dev->context_flag = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag = 0;
 	dev->last_context = 0;
-	dev->last_switch = 0;
-	dev->last_checked = 0;
-	init_waitqueue_head(&dev->context_wait);
 	dev->if_version = 0;
 
-	dev->ctx_start = 0;
-	dev->lck_start = 0;
-
 	dev->buf_async = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
 
 	DRM_DEBUG("\n");
 
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 603f256..9ab038c 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -37,6 +37,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 #include <drm/drmP.h>
+#include <drm/drm_vma_manager.h>
 
 /** @file drm_gem.c
  *
@@ -102,14 +103,9 @@ drm_gem_init(struct drm_device *dev)
 	}
 
 	dev->mm_private = mm;
-
-	if (drm_ht_create(&mm->offset_hash, 12)) {
-		kfree(mm);
-		return -ENOMEM;
-	}
-
-	drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
-		    DRM_FILE_PAGE_OFFSET_SIZE);
+	drm_vma_offset_manager_init(&mm->vma_manager,
+				    DRM_FILE_PAGE_OFFSET_START,
+				    DRM_FILE_PAGE_OFFSET_SIZE);
 
 	return 0;
 }
@@ -119,8 +115,7 @@ drm_gem_destroy(struct drm_device *dev)
 {
 	struct drm_gem_mm *mm = dev->mm_private;
 
-	drm_mm_takedown(&mm->offset_manager);
-	drm_ht_remove(&mm->offset_hash);
+	drm_vma_offset_manager_destroy(&mm->vma_manager);
 	kfree(mm);
 	dev->mm_private = NULL;
 }
@@ -132,16 +127,14 @@ drm_gem_destroy(struct drm_device *dev)
 int drm_gem_object_init(struct drm_device *dev,
 			struct drm_gem_object *obj, size_t size)
 {
-	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+	struct file *filp;
 
-	obj->dev = dev;
-	obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
-	if (IS_ERR(obj->filp))
-		return PTR_ERR(obj->filp);
+	filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
+	if (IS_ERR(filp))
+		return PTR_ERR(filp);
 
-	kref_init(&obj->refcount);
-	atomic_set(&obj->handle_count, 0);
-	obj->size = size;
+	drm_gem_private_object_init(dev, obj, size);
+	obj->filp = filp;
 
 	return 0;
 }
@@ -152,8 +145,8 @@ EXPORT_SYMBOL(drm_gem_object_init);
  * no GEM provided backing store. Instead the caller is responsible for
  * backing the object and handling it.
  */
-int drm_gem_private_object_init(struct drm_device *dev,
-			struct drm_gem_object *obj, size_t size)
+void drm_gem_private_object_init(struct drm_device *dev,
+				 struct drm_gem_object *obj, size_t size)
 {
 	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
 
@@ -163,8 +156,6 @@ int drm_gem_private_object_init(struct drm_device *dev,
 	kref_init(&obj->refcount);
 	atomic_set(&obj->handle_count, 0);
 	obj->size = size;
-
-	return 0;
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
@@ -253,6 +244,20 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 EXPORT_SYMBOL(drm_gem_handle_delete);
 
 /**
+ * drm_gem_dumb_destroy - dumb fb callback helper for gem based drivers
+ * 
+ * This implements the ->dumb_destroy kms driver callback for drivers which use
+ * gem to manage their backing storage.
+ */
+int drm_gem_dumb_destroy(struct drm_file *file,
+			 struct drm_device *dev,
+			 uint32_t handle)
+{
+	return drm_gem_handle_delete(file, handle);
+}
+EXPORT_SYMBOL(drm_gem_dumb_destroy);
+
+/**
  * Create a handle for this object. This adds a handle reference
  * to the object, which includes a regular reference count. Callers
  * will likely want to dereference the object afterwards.
@@ -306,12 +311,8 @@ drm_gem_free_mmap_offset(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list = &obj->map_list;
 
-	drm_ht_remove_item(&mm->offset_hash, &list->hash);
-	drm_mm_put_block(list->file_offset_node);
-	kfree(list->map);
-	list->map = NULL;
+	drm_vma_offset_remove(&mm->vma_manager, &obj->vma_node);
 }
 EXPORT_SYMBOL(drm_gem_free_mmap_offset);
 
@@ -331,54 +332,9 @@ drm_gem_create_mmap_offset(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret;
 
-	/* Set the object up for mmap'ing */
-	list = &obj->map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (!list->map)
-		return -ENOMEM;
-
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = obj->size;
-	map->handle = obj;
-
-	/* Get a DRM GEM mmap offset allocated... */
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-			obj->size / PAGE_SIZE, 0, false);
-
-	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
-		ret = -ENOSPC;
-		goto out_free_list;
-	}
-
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-			obj->size / PAGE_SIZE, 0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto out_free_list;
-	}
-
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		DRM_ERROR("failed to add to map hash\n");
-		goto out_free_mm;
-	}
-
-	return 0;
-
-out_free_mm:
-	drm_mm_put_block(list->file_offset_node);
-out_free_list:
-	kfree(list->map);
-	list->map = NULL;
-
-	return ret;
+	return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
+				  obj->size / PAGE_SIZE);
 }
 EXPORT_SYMBOL(drm_gem_create_mmap_offset);
 
@@ -707,8 +663,8 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 	struct drm_file *priv = filp->private_data;
 	struct drm_device *dev = priv->minor->dev;
 	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_local_map *map = NULL;
-	struct drm_hash_item *hash;
+	struct drm_gem_object *obj;
+	struct drm_vma_offset_node *node;
 	int ret = 0;
 
 	if (drm_device_is_unplugged(dev))
@@ -716,21 +672,16 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 
 	mutex_lock(&dev->struct_mutex);
 
-	if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
+	node = drm_vma_offset_exact_lookup(&mm->vma_manager, vma->vm_pgoff,
+					   vma_pages(vma));
+	if (!node) {
 		mutex_unlock(&dev->struct_mutex);
 		return drm_mmap(filp, vma);
 	}
 
-	map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
-	if (!map ||
-	    ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
-		ret =  -EPERM;
-		goto out_unlock;
-	}
-
-	ret = drm_gem_mmap_obj(map->handle, map->size, vma);
+	obj = container_of(node, struct drm_gem_object, vma_node);
+	ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, vma);
 
-out_unlock:
 	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index ece72a8..6b51bf9 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -27,11 +27,7 @@
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include <drm/drm_gem_cma_helper.h>
-
-static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
-{
-	return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
-}
+#include <drm/drm_vma_manager.h>
 
 /*
  * __drm_gem_cma_create - Create a GEM CMA object without allocating memory
@@ -172,8 +168,7 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
 {
 	struct drm_gem_cma_object *cma_obj;
 
-	if (gem_obj->map_list.map)
-		drm_gem_free_mmap_offset(gem_obj);
+	drm_gem_free_mmap_offset(gem_obj);
 
 	cma_obj = to_drm_gem_cma_obj(gem_obj);
 
@@ -215,7 +210,7 @@ int drm_gem_cma_dumb_create(struct drm_file *file_priv,
 
 	cma_obj = drm_gem_cma_create_with_handle(file_priv, dev,
 			args->size, &args->handle);
-	return PTR_RET(cma_obj);
+	return PTR_ERR_OR_ZERO(cma_obj);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
 
@@ -237,7 +232,7 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
 		return -EINVAL;
 	}
 
-	*offset = get_gem_mmap_offset(gem_obj);
+	*offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
 
 	drm_gem_object_unreference(gem_obj);
 
@@ -286,27 +281,16 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
 
-/*
- * drm_gem_cma_dumb_destroy - (struct drm_driver)->dumb_destroy callback function
- */
-int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
-		struct drm_device *drm, unsigned int handle)
-{
-	return drm_gem_handle_delete(file_priv, handle);
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy);
-
 #ifdef CONFIG_DEBUG_FS
 void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m)
 {
 	struct drm_gem_object *obj = &cma_obj->base;
 	struct drm_device *dev = obj->dev;
-	uint64_t off = 0;
+	uint64_t off;
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	if (obj->map_list.map)
-		off = (uint64_t)obj->map_list.hash.key;
+	off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d",
 			obj->name, obj->refcount.refcount.counter,
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 543b9b3..aded1e1 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -49,58 +49,18 @@
 
 #define MM_UNUSED_TARGET 4
 
-static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
-{
-	struct drm_mm_node *child;
-
-	if (atomic)
-		child = kzalloc(sizeof(*child), GFP_ATOMIC);
-	else
-		child = kzalloc(sizeof(*child), GFP_KERNEL);
-
-	if (unlikely(child == NULL)) {
-		spin_lock(&mm->unused_lock);
-		if (list_empty(&mm->unused_nodes))
-			child = NULL;
-		else {
-			child =
-			    list_entry(mm->unused_nodes.next,
-				       struct drm_mm_node, node_list);
-			list_del(&child->node_list);
-			--mm->num_unused;
-		}
-		spin_unlock(&mm->unused_lock);
-	}
-	return child;
-}
-
-/* drm_mm_pre_get() - pre allocate drm_mm_node structure
- * drm_mm:	memory manager struct we are pre-allocating for
- *
- * Returns 0 on success or -ENOMEM if allocation fails.
- */
-int drm_mm_pre_get(struct drm_mm *mm)
-{
-	struct drm_mm_node *node;
-
-	spin_lock(&mm->unused_lock);
-	while (mm->num_unused < MM_UNUSED_TARGET) {
-		spin_unlock(&mm->unused_lock);
-		node = kzalloc(sizeof(*node), GFP_KERNEL);
-		spin_lock(&mm->unused_lock);
-
-		if (unlikely(node == NULL)) {
-			int ret = (mm->num_unused < 2) ? -ENOMEM : 0;
-			spin_unlock(&mm->unused_lock);
-			return ret;
-		}
-		++mm->num_unused;
-		list_add_tail(&node->node_list, &mm->unused_nodes);
-	}
-	spin_unlock(&mm->unused_lock);
-	return 0;
-}
-EXPORT_SYMBOL(drm_mm_pre_get);
+static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long color,
+						enum drm_mm_search_flags flags);
+static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long color,
+						unsigned long start,
+						unsigned long end,
+						enum drm_mm_search_flags flags);
 
 static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 				 struct drm_mm_node *node,
@@ -147,33 +107,27 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 	}
 }
 
-struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
-					unsigned long start,
-					unsigned long size,
-					bool atomic)
+int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
 {
-	struct drm_mm_node *hole, *node;
-	unsigned long end = start + size;
+	struct drm_mm_node *hole;
+	unsigned long end = node->start + node->size;
 	unsigned long hole_start;
 	unsigned long hole_end;
 
+	BUG_ON(node == NULL);
+
+	/* Find the relevant hole to add our node to */
 	drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
-		if (hole_start > start || hole_end < end)
+		if (hole_start > node->start || hole_end < end)
 			continue;
 
-		node = drm_mm_kmalloc(mm, atomic);
-		if (unlikely(node == NULL))
-			return NULL;
-
-		node->start = start;
-		node->size = size;
 		node->mm = mm;
 		node->allocated = 1;
 
 		INIT_LIST_HEAD(&node->hole_stack);
 		list_add(&node->node_list, &hole->node_list);
 
-		if (start == hole_start) {
+		if (node->start == hole_start) {
 			hole->hole_follows = 0;
 			list_del_init(&hole->hole_stack);
 		}
@@ -184,31 +138,14 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
 			node->hole_follows = 1;
 		}
 
-		return node;
+		return 0;
 	}
 
-	WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size);
-	return NULL;
-}
-EXPORT_SYMBOL(drm_mm_create_block);
-
-struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
-					     unsigned long size,
-					     unsigned alignment,
-					     unsigned long color,
-					     int atomic)
-{
-	struct drm_mm_node *node;
-
-	node = drm_mm_kmalloc(hole_node->mm, atomic);
-	if (unlikely(node == NULL))
-		return NULL;
-
-	drm_mm_insert_helper(hole_node, node, size, alignment, color);
-
-	return node;
+	WARN(1, "no hole found for node 0x%lx + 0x%lx\n",
+	     node->start, node->size);
+	return -ENOSPC;
 }
-EXPORT_SYMBOL(drm_mm_get_block_generic);
+EXPORT_SYMBOL(drm_mm_reserve_node);
 
 /**
  * Search for free space and insert a preallocated memory node. Returns
@@ -217,12 +154,13 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
  */
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
 			       unsigned long size, unsigned alignment,
-			       unsigned long color)
+			       unsigned long color,
+			       enum drm_mm_search_flags flags)
 {
 	struct drm_mm_node *hole_node;
 
 	hole_node = drm_mm_search_free_generic(mm, size, alignment,
-					       color, 0);
+					       color, flags);
 	if (!hole_node)
 		return -ENOSPC;
 
@@ -231,13 +169,6 @@ int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
 }
 EXPORT_SYMBOL(drm_mm_insert_node_generic);
 
-int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
-		       unsigned long size, unsigned alignment)
-{
-	return drm_mm_insert_node_generic(mm, node, size, alignment, 0);
-}
-EXPORT_SYMBOL(drm_mm_insert_node);
-
 static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
 				       struct drm_mm_node *node,
 				       unsigned long size, unsigned alignment,
@@ -290,27 +221,6 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
 	}
 }
 
-struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long color,
-						unsigned long start,
-						unsigned long end,
-						int atomic)
-{
-	struct drm_mm_node *node;
-
-	node = drm_mm_kmalloc(hole_node->mm, atomic);
-	if (unlikely(node == NULL))
-		return NULL;
-
-	drm_mm_insert_helper_range(hole_node, node, size, alignment, color,
-				   start, end);
-
-	return node;
-}
-EXPORT_SYMBOL(drm_mm_get_block_range_generic);
-
 /**
  * Search for free space and insert a preallocated memory node. Returns
  * -ENOSPC if no suitable free area is available. This is for range
@@ -318,13 +228,14 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic);
  */
 int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
 					unsigned long size, unsigned alignment, unsigned long color,
-					unsigned long start, unsigned long end)
+					unsigned long start, unsigned long end,
+					enum drm_mm_search_flags flags)
 {
 	struct drm_mm_node *hole_node;
 
 	hole_node = drm_mm_search_free_in_range_generic(mm,
 							size, alignment, color,
-							start, end, 0);
+							start, end, flags);
 	if (!hole_node)
 		return -ENOSPC;
 
@@ -335,14 +246,6 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *n
 }
 EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
 
-int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
-				unsigned long size, unsigned alignment,
-				unsigned long start, unsigned long end)
-{
-	return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end);
-}
-EXPORT_SYMBOL(drm_mm_insert_node_in_range);
-
 /**
  * Remove a memory node from the allocator.
  */
@@ -377,28 +280,6 @@ void drm_mm_remove_node(struct drm_mm_node *node)
 }
 EXPORT_SYMBOL(drm_mm_remove_node);
 
-/*
- * Remove a memory node from the allocator and free the allocated struct
- * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
- * drm_mm_get_block functions.
- */
-void drm_mm_put_block(struct drm_mm_node *node)
-{
-
-	struct drm_mm *mm = node->mm;
-
-	drm_mm_remove_node(node);
-
-	spin_lock(&mm->unused_lock);
-	if (mm->num_unused < MM_UNUSED_TARGET) {
-		list_add(&node->node_list, &mm->unused_nodes);
-		++mm->num_unused;
-	} else
-		kfree(node);
-	spin_unlock(&mm->unused_lock);
-}
-EXPORT_SYMBOL(drm_mm_put_block);
-
 static int check_free_hole(unsigned long start, unsigned long end,
 			   unsigned long size, unsigned alignment)
 {
@@ -414,11 +295,11 @@ static int check_free_hole(unsigned long start, unsigned long end,
 	return end >= start + size;
 }
 
-struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
-					       unsigned long size,
-					       unsigned alignment,
-					       unsigned long color,
-					       bool best_match)
+static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
+						      unsigned long size,
+						      unsigned alignment,
+						      unsigned long color,
+						      enum drm_mm_search_flags flags)
 {
 	struct drm_mm_node *entry;
 	struct drm_mm_node *best;
@@ -441,7 +322,7 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
 		if (!check_free_hole(adj_start, adj_end, size, alignment))
 			continue;
 
-		if (!best_match)
+		if (!(flags & DRM_MM_SEARCH_BEST))
 			return entry;
 
 		if (entry->size < best_size) {
@@ -452,15 +333,14 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
 
 	return best;
 }
-EXPORT_SYMBOL(drm_mm_search_free_generic);
 
-struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
+static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
 							unsigned long size,
 							unsigned alignment,
 							unsigned long color,
 							unsigned long start,
 							unsigned long end,
-							bool best_match)
+							enum drm_mm_search_flags flags)
 {
 	struct drm_mm_node *entry;
 	struct drm_mm_node *best;
@@ -488,7 +368,7 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
 		if (!check_free_hole(adj_start, adj_end, size, alignment))
 			continue;
 
-		if (!best_match)
+		if (!(flags & DRM_MM_SEARCH_BEST))
 			return entry;
 
 		if (entry->size < best_size) {
@@ -499,7 +379,6 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
 
 	return best;
 }
-EXPORT_SYMBOL(drm_mm_search_free_in_range_generic);
 
 /**
  * Moves an allocation. To be used with embedded struct drm_mm_node.
@@ -634,8 +513,8 @@ EXPORT_SYMBOL(drm_mm_scan_add_block);
  * corrupted.
  *
  * When the scan list is empty, the selected memory nodes can be freed. An
- * immediately following drm_mm_search_free with best_match = 0 will then return
- * the just freed block (because its at the top of the free_stack list).
+ * immediately following drm_mm_search_free with !DRM_MM_SEARCH_BEST will then
+ * return the just freed block (because its at the top of the free_stack list).
  *
  * Returns one if this block should be evicted, zero otherwise. Will always
  * return zero when no hole has been found.
@@ -672,10 +551,7 @@ EXPORT_SYMBOL(drm_mm_clean);
 void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
 	INIT_LIST_HEAD(&mm->hole_stack);
-	INIT_LIST_HEAD(&mm->unused_nodes);
-	mm->num_unused = 0;
 	mm->scanned_blocks = 0;
-	spin_lock_init(&mm->unused_lock);
 
 	/* Clever trick to avoid a special case in the free hole tracking. */
 	INIT_LIST_HEAD(&mm->head_node.node_list);
@@ -695,22 +571,8 @@ EXPORT_SYMBOL(drm_mm_init);
 
 void drm_mm_takedown(struct drm_mm * mm)
 {
-	struct drm_mm_node *entry, *next;
-
-	if (WARN(!list_empty(&mm->head_node.node_list),
-		 "Memory manager not clean. Delaying takedown\n")) {
-		return;
-	}
-
-	spin_lock(&mm->unused_lock);
-	list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) {
-		list_del(&entry->node_list);
-		kfree(entry);
-		--mm->num_unused;
-	}
-	spin_unlock(&mm->unused_lock);
-
-	BUG_ON(mm->num_unused != 0);
+	WARN(!list_empty(&mm->head_node.node_list),
+	     "Memory manager not clean during takedown.\n");
 }
 EXPORT_SYMBOL(drm_mm_takedown);
 
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index 80c0b2b..0f54ad8 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -52,10 +52,8 @@
 drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
 {
 	drm_dma_handle_t *dmah;
-#if 1
 	unsigned long addr;
 	size_t sz;
-#endif
 
 	/* pci_alloc_consistent only guarantees alignment to the smallest
 	 * PAGE_SIZE order which is greater than or equal to the requested size.
@@ -97,10 +95,8 @@ EXPORT_SYMBOL(drm_pci_alloc);
  */
 void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
-#if 1
 	unsigned long addr;
 	size_t sz;
-#endif
 
 	if (dmah->vaddr) {
 		/* XXX - Is virt_to_page() legal for consistent mem? */
@@ -287,6 +283,17 @@ static int drm_pci_agp_init(struct drm_device *dev)
 	return 0;
 }
 
+static void drm_pci_agp_destroy(struct drm_device *dev)
+{
+	if (drm_core_has_AGP(dev) && dev->agp) {
+		if (drm_core_has_MTRR(dev))
+			arch_phys_wc_del(dev->agp->agp_mtrr);
+		drm_agp_clear(dev);
+		drm_agp_destroy(dev->agp);
+		dev->agp = NULL;
+	}
+}
+
 static struct drm_bus drm_pci_bus = {
 	.bus_type = DRIVER_BUS_PCI,
 	.get_irq = drm_pci_get_irq,
@@ -295,6 +302,7 @@ static struct drm_bus drm_pci_bus = {
 	.set_unique = drm_pci_set_unique,
 	.irq_by_busid = drm_pci_irq_by_busid,
 	.agp_init = drm_pci_agp_init,
+	.agp_destroy = drm_pci_agp_destroy,
 };
 
 /**
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c
index d87f60b..a4a076f 100644
--- a/drivers/gpu/drm/drm_scatter.c
+++ b/drivers/gpu/drm/drm_scatter.c
@@ -70,8 +70,10 @@ void drm_sg_cleanup(struct drm_sg_mem * entry)
 # define ScatterHandle(x) (unsigned int)(x)
 #endif
 
-int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
+int drm_sg_alloc(struct drm_device *dev, void *data,
+		 struct drm_file *file_priv)
 {
+	struct drm_scatter_gather *request = data;
 	struct drm_sg_mem *entry;
 	unsigned long pages, i, j;
 
@@ -181,15 +183,6 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
 	return -ENOMEM;
 }
 
-int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	struct drm_scatter_gather *request = data;
-
-	return drm_sg_alloc(dev, request);
-
-}
-
 int drm_sg_free(struct drm_device *dev, void *data,
 		struct drm_file *file_priv)
 {
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 327ca19..d663f7d 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -451,16 +451,11 @@ void drm_put_dev(struct drm_device *dev)
 
 	drm_lastclose(dev);
 
-	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp)
-		arch_phys_wc_del(dev->agp->agp_mtrr);
-
 	if (dev->driver->unload)
 		dev->driver->unload(dev);
 
-	if (drm_core_has_AGP(dev) && dev->agp) {
-		kfree(dev->agp);
-		dev->agp = NULL;
-	}
+	if (dev->driver->bus->agp_destroy)
+		dev->driver->bus->agp_destroy(dev);
 
 	drm_vblank_cleanup(dev);
 
diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c
new file mode 100644
index 0000000..3837481
--- /dev/null
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * Copyright (c) 2012 David Airlie <airlied@linux.ie>
+ * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_mm.h>
+#include <drm/drm_vma_manager.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+/**
+ * DOC: vma offset manager
+ *
+ * The vma-manager is responsible to map arbitrary driver-dependent memory
+ * regions into the linear user address-space. It provides offsets to the
+ * caller which can then be used on the address_space of the drm-device. It
+ * takes care to not overlap regions, size them appropriately and to not
+ * confuse mm-core by inconsistent fake vm_pgoff fields.
+ * Drivers shouldn't use this for object placement in VMEM. This manager should
+ * only be used to manage mappings into linear user-space VMs.
+ *
+ * We use drm_mm as backend to manage object allocations. But it is highly
+ * optimized for alloc/free calls, not lookups. Hence, we use an rb-tree to
+ * speed up offset lookups.
+ *
+ * You must not use multiple offset managers on a single address_space.
+ * Otherwise, mm-core will be unable to tear down memory mappings as the VM will
+ * no longer be linear. Please use VM_NONLINEAR in that case and implement your
+ * own offset managers.
+ *
+ * This offset manager works on page-based addresses. That is, every argument
+ * and return code (with the exception of drm_vma_node_offset_addr()) is given
+ * in number of pages, not number of bytes. That means, object sizes and offsets
+ * must always be page-aligned (as usual).
+ * If you want to get a valid byte-based user-space address for a given offset,
+ * please see drm_vma_node_offset_addr().
+ */
+
+/**
+ * drm_vma_offset_manager_init - Initialize new offset-manager
+ * @mgr: Manager object
+ * @page_offset: Offset of available memory area (page-based)
+ * @size: Size of available address space range (page-based)
+ *
+ * Initialize a new offset-manager. The offset and area size available for the
+ * manager are given as @page_offset and @size. Both are interpreted as
+ * page-numbers, not bytes.
+ *
+ * Adding/removing nodes from the manager is locked internally and protected
+ * against concurrent access. However, node allocation and destruction is left
+ * for the caller. While calling into the vma-manager, a given node must
+ * always be guaranteed to be referenced.
+ */
+void drm_vma_offset_manager_init(struct drm_vma_offset_manager *mgr,
+				 unsigned long page_offset, unsigned long size)
+{
+	rwlock_init(&mgr->vm_lock);
+	mgr->vm_addr_space_rb = RB_ROOT;
+	drm_mm_init(&mgr->vm_addr_space_mm, page_offset, size);
+}
+EXPORT_SYMBOL(drm_vma_offset_manager_init);
+
+/**
+ * drm_vma_offset_manager_destroy() - Destroy offset manager
+ * @mgr: Manager object
+ *
+ * Destroy an object manager which was previously created via
+ * drm_vma_offset_manager_init(). The caller must remove all allocated nodes
+ * before destroying the manager. Otherwise, drm_mm will refuse to free the
+ * requested resources.
+ *
+ * The manager must not be accessed after this function is called.
+ */
+void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager *mgr)
+{
+	/* take the lock to protect against buggy drivers */
+	write_lock(&mgr->vm_lock);
+	drm_mm_takedown(&mgr->vm_addr_space_mm);
+	write_unlock(&mgr->vm_lock);
+}
+EXPORT_SYMBOL(drm_vma_offset_manager_destroy);
+
+/**
+ * drm_vma_offset_lookup() - Find node in offset space
+ * @mgr: Manager object
+ * @start: Start address for object (page-based)
+ * @pages: Size of object (page-based)
+ *
+ * Find a node given a start address and object size. This returns the _best_
+ * match for the given node. That is, @start may point somewhere into a valid
+ * region and the given node will be returned, as long as the node spans the
+ * whole requested area (given the size in number of pages as @pages).
+ *
+ * RETURNS:
+ * Returns NULL if no suitable node can be found. Otherwise, the best match
+ * is returned. It's the caller's responsibility to make sure the node doesn't
+ * get destroyed before the caller can access it.
+ */
+struct drm_vma_offset_node *drm_vma_offset_lookup(struct drm_vma_offset_manager *mgr,
+						  unsigned long start,
+						  unsigned long pages)
+{
+	struct drm_vma_offset_node *node;
+
+	read_lock(&mgr->vm_lock);
+	node = drm_vma_offset_lookup_locked(mgr, start, pages);
+	read_unlock(&mgr->vm_lock);
+
+	return node;
+}
+EXPORT_SYMBOL(drm_vma_offset_lookup);
+
+/**
+ * drm_vma_offset_lookup_locked() - Find node in offset space
+ * @mgr: Manager object
+ * @start: Start address for object (page-based)
+ * @pages: Size of object (page-based)
+ *
+ * Same as drm_vma_offset_lookup() but requires the caller to lock offset lookup
+ * manually. See drm_vma_offset_lock_lookup() for an example.
+ *
+ * RETURNS:
+ * Returns NULL if no suitable node can be found. Otherwise, the best match
+ * is returned.
+ */
+struct drm_vma_offset_node *drm_vma_offset_lookup_locked(struct drm_vma_offset_manager *mgr,
+							 unsigned long start,
+							 unsigned long pages)
+{
+	struct drm_vma_offset_node *node, *best;
+	struct rb_node *iter;
+	unsigned long offset;
+
+	iter = mgr->vm_addr_space_rb.rb_node;
+	best = NULL;
+
+	while (likely(iter)) {
+		node = rb_entry(iter, struct drm_vma_offset_node, vm_rb);
+		offset = node->vm_node.start;
+		if (start >= offset) {
+			iter = iter->rb_right;
+			best = node;
+			if (start == offset)
+				break;
+		} else {
+			iter = iter->rb_left;
+		}
+	}
+
+	/* verify that the node spans the requested area */
+	if (best) {
+		offset = best->vm_node.start + best->vm_node.size;
+		if (offset < start + pages)
+			best = NULL;
+	}
+
+	return best;
+}
+EXPORT_SYMBOL(drm_vma_offset_lookup_locked);
+
+/* internal helper to link @node into the rb-tree */
+static void _drm_vma_offset_add_rb(struct drm_vma_offset_manager *mgr,
+				   struct drm_vma_offset_node *node)
+{
+	struct rb_node **iter = &mgr->vm_addr_space_rb.rb_node;
+	struct rb_node *parent = NULL;
+	struct drm_vma_offset_node *iter_node;
+
+	while (likely(*iter)) {
+		parent = *iter;
+		iter_node = rb_entry(*iter, struct drm_vma_offset_node, vm_rb);
+
+		if (node->vm_node.start < iter_node->vm_node.start)
+			iter = &(*iter)->rb_left;
+		else if (node->vm_node.start > iter_node->vm_node.start)
+			iter = &(*iter)->rb_right;
+		else
+			BUG();
+	}
+
+	rb_link_node(&node->vm_rb, parent, iter);
+	rb_insert_color(&node->vm_rb, &mgr->vm_addr_space_rb);
+}
+
+/**
+ * drm_vma_offset_add() - Add offset node to manager
+ * @mgr: Manager object
+ * @node: Node to be added
+ * @pages: Allocation size visible to user-space (in number of pages)
+ *
+ * Add a node to the offset-manager. If the node was already added, this does
+ * nothing and return 0. @pages is the size of the object given in number of
+ * pages.
+ * After this call succeeds, you can access the offset of the node until it
+ * is removed again.
+ *
+ * If this call fails, it is safe to retry the operation or call
+ * drm_vma_offset_remove(), anyway. However, no cleanup is required in that
+ * case.
+ *
+ * @pages is not required to be the same size as the underlying memory object
+ * that you want to map. It only limits the size that user-space can map into
+ * their address space.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
+		       struct drm_vma_offset_node *node, unsigned long pages)
+{
+	int ret;
+
+	write_lock(&mgr->vm_lock);
+
+	if (drm_mm_node_allocated(&node->vm_node)) {
+		ret = 0;
+		goto out_unlock;
+	}
+
+	ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node,
+				 pages, 0, DRM_MM_SEARCH_DEFAULT);
+	if (ret)
+		goto out_unlock;
+
+	_drm_vma_offset_add_rb(mgr, node);
+
+out_unlock:
+	write_unlock(&mgr->vm_lock);
+	return ret;
+}
+EXPORT_SYMBOL(drm_vma_offset_add);
+
+/**
+ * drm_vma_offset_remove() - Remove offset node from manager
+ * @mgr: Manager object
+ * @node: Node to be removed
+ *
+ * Remove a node from the offset manager. If the node wasn't added before, this
+ * does nothing. After this call returns, the offset and size will be 0 until a
+ * new offset is allocated via drm_vma_offset_add() again. Helper functions like
+ * drm_vma_node_start() and drm_vma_node_offset_addr() will return 0 if no
+ * offset is allocated.
+ */
+void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
+			   struct drm_vma_offset_node *node)
+{
+	write_lock(&mgr->vm_lock);
+
+	if (drm_mm_node_allocated(&node->vm_node)) {
+		rb_erase(&node->vm_rb, &mgr->vm_addr_space_rb);
+		drm_mm_remove_node(&node->vm_node);
+		memset(&node->vm_node, 0, sizeof(node->vm_node));
+	}
+
+	write_unlock(&mgr->vm_lock);
+}
+EXPORT_SYMBOL(drm_vma_offset_remove);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index ca2729a..df81d3c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -213,7 +213,7 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
 	.close = drm_gem_vm_close,
 };
 
-static struct drm_ioctl_desc exynos_ioctls[] = {
+static const struct drm_ioctl_desc exynos_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
 			DRM_UNLOCKED | DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
@@ -271,12 +271,13 @@ static struct drm_driver exynos_drm_driver = {
 	.gem_vm_ops		= &exynos_drm_gem_vm_ops,
 	.dumb_create		= exynos_drm_gem_dumb_create,
 	.dumb_map_offset	= exynos_drm_gem_dumb_map_offset,
-	.dumb_destroy		= exynos_drm_gem_dumb_destroy,
+	.dumb_destroy		= drm_gem_dumb_destroy,
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
 	.gem_prime_export	= exynos_dmabuf_prime_export,
 	.gem_prime_import	= exynos_dmabuf_prime_import,
 	.ioctls			= exynos_ioctls,
+	.num_ioctls		= ARRAY_SIZE(exynos_ioctls),
 	.fops			= &exynos_drm_driver_fops,
 	.name	= DRIVER_NAME,
 	.desc	= DRIVER_DESC,
@@ -288,7 +289,6 @@ static struct drm_driver exynos_drm_driver = {
 static int exynos_drm_platform_probe(struct platform_device *pdev)
 {
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-	exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
 
 	return drm_platform_init(&exynos_drm_driver, pdev);
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 24c22a8..b904633 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -10,6 +10,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_vma_manager.h>
 
 #include <linux/shmem_fs.h>
 #include <drm/exynos_drm.h>
@@ -152,8 +153,7 @@ out:
 	exynos_drm_fini_buf(obj->dev, buf);
 	exynos_gem_obj->buffer = NULL;
 
-	if (obj->map_list.map)
-		drm_gem_free_mmap_offset(obj);
+	drm_gem_free_mmap_offset(obj);
 
 	/* release file pointer to gem object. */
 	drm_gem_object_release(obj);
@@ -703,13 +703,11 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
 		goto unlock;
 	}
 
-	if (!obj->map_list.map) {
-		ret = drm_gem_create_mmap_offset(obj);
-		if (ret)
-			goto out;
-	}
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		goto out;
 
-	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+	*offset = drm_vma_node_offset_addr(&obj->vma_node);
 	DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
 
 out:
@@ -719,26 +717,6 @@ unlock:
 	return ret;
 }
 
-int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
-				struct drm_device *dev,
-				unsigned int handle)
-{
-	int ret;
-
-	/*
-	 * obj->refcount and obj->handle_count are decreased and
-	 * if both them are 0 then exynos_drm_gem_free_object()
-	 * would be called by callback to release resources.
-	 */
-	ret = drm_gem_handle_delete(file_priv, handle);
-	if (ret < 0) {
-		DRM_ERROR("failed to delete drm_gem_handle.\n");
-		return ret;
-	}
-
-	return 0;
-}
-
 int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct drm_gem_object *obj = vma->vm_private_data;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 468766b..09555af 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -151,15 +151,6 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
 				   struct drm_device *dev, uint32_t handle,
 				   uint64_t *offset);
 
-/*
- * destroy memory region allocated.
- *	- a gem handle and physical memory region pointed by a gem object
- *	would be released by drm_gem_handle_delete().
- */
-int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
-				struct drm_device *dev,
-				unsigned int handle);
-
 /* page fault handler and mmap fault address(virtual) to physical memory. */
 int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 8b1b6d9..362dd2a 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -321,10 +321,8 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 	/* Begin by trying to use stolen memory backing */
 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
 	if (backing) {
-		if (drm_gem_private_object_init(dev,
-					&backing->gem, aligned_size) == 0)
-			return backing;
-		psb_gtt_free_range(dev, backing);
+		drm_gem_private_object_init(dev, &backing->gem, aligned_size);
+		return backing;
 	}
 	return NULL;
 }
diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index eefd6cc..10ae8c5 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -26,6 +26,7 @@
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include <drm/gma_drm.h>
+#include <drm/drm_vma_manager.h>
 #include "psb_drv.h"
 
 int psb_gem_init_object(struct drm_gem_object *obj)
@@ -38,8 +39,7 @@ void psb_gem_free_object(struct drm_gem_object *obj)
 	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
 
 	/* Remove the list map if one is present */
-	if (obj->map_list.map)
-		drm_gem_free_mmap_offset(obj);
+	drm_gem_free_mmap_offset(obj);
 	drm_gem_object_release(obj);
 
 	/* This must occur last as it frees up the memory of the GEM object */
@@ -81,13 +81,10 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 	/* What validation is needed here ? */
 
 	/* Make it mmapable */
-	if (!obj->map_list.map) {
-		ret = drm_gem_create_mmap_offset(obj);
-		if (ret)
-			goto out;
-	}
-	/* GEM should really work out the hash offsets for us */
-	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		goto out;
+	*offset = drm_vma_node_offset_addr(&obj->vma_node);
 out:
 	drm_gem_object_unreference(obj);
 unlock:
@@ -165,23 +162,6 @@ int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 }
 
 /**
- *	psb_gem_dumb_destroy	-	destroy a dumb buffer
- *	@file: client file
- *	@dev: our DRM device
- *	@handle: the object handle
- *
- *	Destroy a handle that was created via psb_gem_dumb_create, at least
- *	we hope it was created that way. i915 seems to assume the caller
- *	does the checking but that might be worth review ! FIXME
- */
-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-			uint32_t handle)
-{
-	/* No special work needed, drop the reference and see what falls out */
-	return drm_gem_handle_delete(file, handle);
-}
-
-/**
  *	psb_gem_fault		-	pagefault handler for GEM objects
  *	@vma: the VMA of the GEM object
  *	@vmf: fault detail
@@ -261,11 +241,12 @@ static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
 	struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
 	if (gtt == NULL)
 		return -ENOMEM;
-	if (drm_gem_private_object_init(dev, &gtt->gem, size) != 0)
-		goto free_gtt;
+
+	drm_gem_private_object_init(dev, &gtt->gem, size);
 	if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
 		return 0;
-free_gtt:
+
+	drm_gem_object_release(&gtt->gem);
 	psb_gtt_free_range(dev, gtt);
 	return -ENOMEM;
 }
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index bddea58..d13c2fc 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -131,7 +131,7 @@ static int psb_gamma_ioctl(struct drm_device *dev, void *data,
 static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv);
 
-static struct drm_ioctl_desc psb_ioctls[] = {
+static const struct drm_ioctl_desc psb_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl,
 		      DRM_AUTH),
@@ -652,7 +652,7 @@ static struct drm_driver driver = {
 	.gem_vm_ops = &psb_gem_vm_ops,
 	.dumb_create = psb_gem_dumb_create,
 	.dumb_map_offset = psb_gem_dumb_map_gtt,
-	.dumb_destroy = psb_gem_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 	.fops = &psb_gem_fops,
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 6053b8a..984cacf 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -838,8 +838,6 @@ extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
 			struct drm_file *file);
 extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 			struct drm_mode_create_dumb *args);
-extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-			uint32_t handle);
 extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 			uint32_t handle, uint64_t *offset);
 extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index ada49ed..eac755b 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -1241,7 +1241,7 @@ int i810_driver_dma_quiescent(struct drm_device *dev)
 	return 0;
 }
 
-struct drm_ioctl_desc i810_ioctls[] = {
+const struct drm_ioctl_desc i810_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h
index 6e0acad..d4d16ed 100644
--- a/drivers/gpu/drm/i810/i810_drv.h
+++ b/drivers/gpu/drm/i810/i810_drv.h
@@ -125,7 +125,7 @@ extern void i810_driver_preclose(struct drm_device *dev,
 extern int i810_driver_device_is_agp(struct drm_device *dev);
 
 extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-extern struct drm_ioctl_desc i810_ioctls[];
+extern const struct drm_ioctl_desc i810_ioctls[];
 extern int i810_max_ioctl;
 
 #define I810_BASE(reg)		((unsigned long) \
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 40034ec..b8449a8 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -5,6 +5,7 @@
 ccflags-y := -Iinclude/drm
 i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  i915_debugfs.o \
+	  i915_gpu_error.o \
           i915_suspend.o \
 	  i915_gem.o \
 	  i915_gem_context.o \
@@ -37,6 +38,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  intel_sprite.o \
 	  intel_opregion.o \
 	  intel_sideband.o \
+	  intel_uncore.o \
 	  dvo_ch7xxx.o \
 	  dvo_ch7017.o \
 	  dvo_ivch.o \
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index 757e0fa..af42e94 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -307,7 +307,7 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
 		idf |= CH7xxx_IDF_HSP;
 
 	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
-		idf |= CH7xxx_IDF_HSP;
+		idf |= CH7xxx_IDF_VSP;
 
 	ch7xxx_writeb(dvo, CH7xxx_IDF, idf);
 }
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 47d6c74..1a87cc9 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -30,7 +30,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/export.h>
-#include <generated/utsrelease.h>
+#include <linux/list_sort.h>
 #include <drm/drmP.h>
 #include "intel_drv.h"
 #include "intel_ringbuffer.h"
@@ -90,30 +90,27 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
 	}
 }
 
-static const char *cache_level_str(int type)
+static inline const char *get_global_flag(struct drm_i915_gem_object *obj)
 {
-	switch (type) {
-	case I915_CACHE_NONE: return " uncached";
-	case I915_CACHE_LLC: return " snooped (LLC)";
-	case I915_CACHE_LLC_MLC: return " snooped (LLC+MLC)";
-	default: return "";
-	}
+	return obj->has_global_gtt_mapping ? "g" : " ";
 }
 
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
-	seq_printf(m, "%pK: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
+	struct i915_vma *vma;
+	seq_printf(m, "%pK: %s%s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
 		   &obj->base,
 		   get_pin_flag(obj),
 		   get_tiling_flag(obj),
+		   get_global_flag(obj),
 		   obj->base.size / 1024,
 		   obj->base.read_domains,
 		   obj->base.write_domain,
 		   obj->last_read_seqno,
 		   obj->last_write_seqno,
 		   obj->last_fenced_seqno,
-		   cache_level_str(obj->cache_level),
+		   i915_cache_level_str(obj->cache_level),
 		   obj->dirty ? " dirty" : "",
 		   obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
 	if (obj->base.name)
@@ -122,9 +119,14 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 		seq_printf(m, " (pinned x %d)", obj->pin_count);
 	if (obj->fence_reg != I915_FENCE_REG_NONE)
 		seq_printf(m, " (fence: %d)", obj->fence_reg);
-	if (obj->gtt_space != NULL)
-		seq_printf(m, " (gtt offset: %08x, size: %08x)",
-			   obj->gtt_offset, (unsigned int)obj->gtt_space->size);
+	list_for_each_entry(vma, &obj->vma_list, vma_link) {
+		if (!i915_is_ggtt(vma->vm))
+			seq_puts(m, " (pp");
+		else
+			seq_puts(m, " (g");
+		seq_printf(m, "gtt offset: %08lx, size: %08lx)",
+			   vma->node.start, vma->node.size);
+	}
 	if (obj->stolen)
 		seq_printf(m, " (stolen: %08lx)", obj->stolen->start);
 	if (obj->pin_mappable || obj->fault_mappable) {
@@ -146,8 +148,9 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 	uintptr_t list = (uintptr_t) node->info_ent->data;
 	struct list_head *head;
 	struct drm_device *dev = node->minor->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_address_space *vm = &dev_priv->gtt.base;
+	struct i915_vma *vma;
 	size_t total_obj_size, total_gtt_size;
 	int count, ret;
 
@@ -155,14 +158,15 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 	if (ret)
 		return ret;
 
+	/* FIXME: the user of this interface might want more than just GGTT */
 	switch (list) {
 	case ACTIVE_LIST:
-		seq_printf(m, "Active:\n");
-		head = &dev_priv->mm.active_list;
+		seq_puts(m, "Active:\n");
+		head = &vm->active_list;
 		break;
 	case INACTIVE_LIST:
-		seq_printf(m, "Inactive:\n");
-		head = &dev_priv->mm.inactive_list;
+		seq_puts(m, "Inactive:\n");
+		head = &vm->inactive_list;
 		break;
 	default:
 		mutex_unlock(&dev->struct_mutex);
@@ -170,14 +174,75 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 	}
 
 	total_obj_size = total_gtt_size = count = 0;
-	list_for_each_entry(obj, head, mm_list) {
+	list_for_each_entry(vma, head, mm_list) {
 		seq_printf(m, "   ");
-		describe_obj(m, obj);
+		describe_obj(m, vma->obj);
 		seq_printf(m, "\n");
+		total_obj_size += vma->obj->base.size;
+		total_gtt_size += vma->node.size;
+		count++;
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
+		   count, total_obj_size, total_gtt_size);
+	return 0;
+}
+
+static int obj_rank_by_stolen(void *priv,
+			      struct list_head *A, struct list_head *B)
+{
+	struct drm_i915_gem_object *a =
+		container_of(A, struct drm_i915_gem_object, exec_list);
+	struct drm_i915_gem_object *b =
+		container_of(B, struct drm_i915_gem_object, exec_list);
+
+	return a->stolen->start - b->stolen->start;
+}
+
+static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj;
+	size_t total_obj_size, total_gtt_size;
+	LIST_HEAD(stolen);
+	int count, ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	total_obj_size = total_gtt_size = count = 0;
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+		if (obj->stolen == NULL)
+			continue;
+
+		list_add(&obj->exec_list, &stolen);
+
 		total_obj_size += obj->base.size;
-		total_gtt_size += obj->gtt_space->size;
+		total_gtt_size += i915_gem_obj_ggtt_size(obj);
 		count++;
 	}
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+		if (obj->stolen == NULL)
+			continue;
+
+		list_add(&obj->exec_list, &stolen);
+
+		total_obj_size += obj->base.size;
+		count++;
+	}
+	list_sort(NULL, &stolen, obj_rank_by_stolen);
+	seq_puts(m, "Stolen:\n");
+	while (!list_empty(&stolen)) {
+		obj = list_first_entry(&stolen, typeof(*obj), exec_list);
+		seq_puts(m, "   ");
+		describe_obj(m, obj);
+		seq_putc(m, '\n');
+		list_del_init(&obj->exec_list);
+	}
 	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
@@ -187,10 +252,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 
 #define count_objects(list, member) do { \
 	list_for_each_entry(obj, list, member) { \
-		size += obj->gtt_space->size; \
+		size += i915_gem_obj_ggtt_size(obj); \
 		++count; \
 		if (obj->map_and_fenceable) { \
-			mappable_size += obj->gtt_space->size; \
+			mappable_size += i915_gem_obj_ggtt_size(obj); \
 			++mappable_count; \
 		} \
 	} \
@@ -209,7 +274,7 @@ static int per_file_stats(int id, void *ptr, void *data)
 	stats->count++;
 	stats->total += obj->base.size;
 
-	if (obj->gtt_space) {
+	if (i915_gem_obj_ggtt_bound(obj)) {
 		if (!list_empty(&obj->ring_list))
 			stats->active += obj->base.size;
 		else
@@ -222,6 +287,17 @@ static int per_file_stats(int id, void *ptr, void *data)
 	return 0;
 }
 
+#define count_vmas(list, member) do { \
+	list_for_each_entry(vma, list, member) { \
+		size += i915_gem_obj_ggtt_size(vma->obj); \
+		++count; \
+		if (vma->obj->map_and_fenceable) { \
+			mappable_size += i915_gem_obj_ggtt_size(vma->obj); \
+			++mappable_count; \
+		} \
+	} \
+} while (0)
+
 static int i915_gem_object_info(struct seq_file *m, void* data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -230,7 +306,9 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	u32 count, mappable_count, purgeable_count;
 	size_t size, mappable_size, purgeable_size;
 	struct drm_i915_gem_object *obj;
+	struct i915_address_space *vm = &dev_priv->gtt.base;
 	struct drm_file *file;
+	struct i915_vma *vma;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -247,12 +325,12 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 		   count, mappable_count, size, mappable_size);
 
 	size = count = mappable_size = mappable_count = 0;
-	count_objects(&dev_priv->mm.active_list, mm_list);
+	count_vmas(&vm->active_list, mm_list);
 	seq_printf(m, "  %u [%u] active objects, %zu [%zu] bytes\n",
 		   count, mappable_count, size, mappable_size);
 
 	size = count = mappable_size = mappable_count = 0;
-	count_objects(&dev_priv->mm.inactive_list, mm_list);
+	count_vmas(&vm->inactive_list, mm_list);
 	seq_printf(m, "  %u [%u] inactive objects, %zu [%zu] bytes\n",
 		   count, mappable_count, size, mappable_size);
 
@@ -267,11 +345,11 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	size = count = mappable_size = mappable_count = 0;
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		if (obj->fault_mappable) {
-			size += obj->gtt_space->size;
+			size += i915_gem_obj_ggtt_size(obj);
 			++count;
 		}
 		if (obj->pin_mappable) {
-			mappable_size += obj->gtt_space->size;
+			mappable_size += i915_gem_obj_ggtt_size(obj);
 			++mappable_count;
 		}
 		if (obj->madv == I915_MADV_DONTNEED) {
@@ -287,10 +365,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 		   count, size);
 
 	seq_printf(m, "%zu [%lu] gtt total\n",
-		   dev_priv->gtt.total,
-		   dev_priv->gtt.mappable_end - dev_priv->gtt.start);
+		   dev_priv->gtt.base.total,
+		   dev_priv->gtt.mappable_end - dev_priv->gtt.base.start);
 
-	seq_printf(m, "\n");
+	seq_putc(m, '\n');
 	list_for_each_entry_reverse(file, &dev->filelist, lhead) {
 		struct file_stats stats;
 
@@ -310,7 +388,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	return 0;
 }
 
-static int i915_gem_gtt_info(struct seq_file *m, void* data)
+static int i915_gem_gtt_info(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
@@ -329,11 +407,11 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
 		if (list == PINNED_LIST && obj->pin_count == 0)
 			continue;
 
-		seq_printf(m, "   ");
+		seq_puts(m, "   ");
 		describe_obj(m, obj);
-		seq_printf(m, "\n");
+		seq_putc(m, '\n');
 		total_obj_size += obj->base.size;
-		total_gtt_size += obj->gtt_space->size;
+		total_gtt_size += i915_gem_obj_ggtt_size(obj);
 		count++;
 	}
 
@@ -371,20 +449,22 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
 					   pipe, plane);
 			}
 			if (work->enable_stall_check)
-				seq_printf(m, "Stall check enabled, ");
+				seq_puts(m, "Stall check enabled, ");
 			else
-				seq_printf(m, "Stall check waiting for page flip ioctl, ");
+				seq_puts(m, "Stall check waiting for page flip ioctl, ");
 			seq_printf(m, "%d prepares\n", atomic_read(&work->pending));
 
 			if (work->old_fb_obj) {
 				struct drm_i915_gem_object *obj = work->old_fb_obj;
 				if (obj)
-					seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj->gtt_offset);
+					seq_printf(m, "Old framebuffer gtt_offset 0x%08lx\n",
+						   i915_gem_obj_ggtt_offset(obj));
 			}
 			if (work->pending_flip_obj) {
 				struct drm_i915_gem_object *obj = work->pending_flip_obj;
 				if (obj)
-					seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj->gtt_offset);
+					seq_printf(m, "New framebuffer gtt_offset 0x%08lx\n",
+						   i915_gem_obj_ggtt_offset(obj));
 			}
 		}
 		spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -424,7 +504,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
 	mutex_unlock(&dev->struct_mutex);
 
 	if (count == 0)
-		seq_printf(m, "No requests\n");
+		seq_puts(m, "No requests\n");
 
 	return 0;
 }
@@ -574,10 +654,10 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
 		seq_printf(m, "Fence %d, pin count = %d, object = ",
 			   i, dev_priv->fence_regs[i].pin_count);
 		if (obj == NULL)
-			seq_printf(m, "unused");
+			seq_puts(m, "unused");
 		else
 			describe_obj(m, obj);
-		seq_printf(m, "\n");
+		seq_putc(m, '\n');
 	}
 
 	mutex_unlock(&dev->struct_mutex);
@@ -606,361 +686,6 @@ static int i915_hws_info(struct seq_file *m, void *data)
 	return 0;
 }
 
-static const char *ring_str(int ring)
-{
-	switch (ring) {
-	case RCS: return "render";
-	case VCS: return "bsd";
-	case BCS: return "blt";
-	case VECS: return "vebox";
-	default: return "";
-	}
-}
-
-static const char *pin_flag(int pinned)
-{
-	if (pinned > 0)
-		return " P";
-	else if (pinned < 0)
-		return " p";
-	else
-		return "";
-}
-
-static const char *tiling_flag(int tiling)
-{
-	switch (tiling) {
-	default:
-	case I915_TILING_NONE: return "";
-	case I915_TILING_X: return " X";
-	case I915_TILING_Y: return " Y";
-	}
-}
-
-static const char *dirty_flag(int dirty)
-{
-	return dirty ? " dirty" : "";
-}
-
-static const char *purgeable_flag(int purgeable)
-{
-	return purgeable ? " purgeable" : "";
-}
-
-static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
-{
-
-	if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
-		e->err = -ENOSPC;
-		return false;
-	}
-
-	if (e->bytes == e->size - 1 || e->err)
-		return false;
-
-	return true;
-}
-
-static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
-			      unsigned len)
-{
-	if (e->pos + len <= e->start) {
-		e->pos += len;
-		return false;
-	}
-
-	/* First vsnprintf needs to fit in its entirety for memmove */
-	if (len >= e->size) {
-		e->err = -EIO;
-		return false;
-	}
-
-	return true;
-}
-
-static void __i915_error_advance(struct drm_i915_error_state_buf *e,
-				 unsigned len)
-{
-	/* If this is first printf in this window, adjust it so that
-	 * start position matches start of the buffer
-	 */
-
-	if (e->pos < e->start) {
-		const size_t off = e->start - e->pos;
-
-		/* Should not happen but be paranoid */
-		if (off > len || e->bytes) {
-			e->err = -EIO;
-			return;
-		}
-
-		memmove(e->buf, e->buf + off, len - off);
-		e->bytes = len - off;
-		e->pos = e->start;
-		return;
-	}
-
-	e->bytes += len;
-	e->pos += len;
-}
-
-static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
-			       const char *f, va_list args)
-{
-	unsigned len;
-
-	if (!__i915_error_ok(e))
-		return;
-
-	/* Seek the first printf which is hits start position */
-	if (e->pos < e->start) {
-		len = vsnprintf(NULL, 0, f, args);
-		if (!__i915_error_seek(e, len))
-			return;
-	}
-
-	len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
-	if (len >= e->size - e->bytes)
-		len = e->size - e->bytes - 1;
-
-	__i915_error_advance(e, len);
-}
-
-static void i915_error_puts(struct drm_i915_error_state_buf *e,
-			    const char *str)
-{
-	unsigned len;
-
-	if (!__i915_error_ok(e))
-		return;
-
-	len = strlen(str);
-
-	/* Seek the first printf which is hits start position */
-	if (e->pos < e->start) {
-		if (!__i915_error_seek(e, len))
-			return;
-	}
-
-	if (len >= e->size - e->bytes)
-		len = e->size - e->bytes - 1;
-	memcpy(e->buf + e->bytes, str, len);
-
-	__i915_error_advance(e, len);
-}
-
-void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
-{
-	va_list args;
-
-	va_start(args, f);
-	i915_error_vprintf(e, f, args);
-	va_end(args);
-}
-
-#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
-#define err_puts(e, s) i915_error_puts(e, s)
-
-static void print_error_buffers(struct drm_i915_error_state_buf *m,
-				const char *name,
-				struct drm_i915_error_buffer *err,
-				int count)
-{
-	err_printf(m, "%s [%d]:\n", name, count);
-
-	while (count--) {
-		err_printf(m, "  %08x %8u %02x %02x %x %x",
-			   err->gtt_offset,
-			   err->size,
-			   err->read_domains,
-			   err->write_domain,
-			   err->rseqno, err->wseqno);
-		err_puts(m, pin_flag(err->pinned));
-		err_puts(m, tiling_flag(err->tiling));
-		err_puts(m, dirty_flag(err->dirty));
-		err_puts(m, purgeable_flag(err->purgeable));
-		err_puts(m, err->ring != -1 ? " " : "");
-		err_puts(m, ring_str(err->ring));
-		err_puts(m, cache_level_str(err->cache_level));
-
-		if (err->name)
-			err_printf(m, " (name: %d)", err->name);
-		if (err->fence_reg != I915_FENCE_REG_NONE)
-			err_printf(m, " (fence: %d)", err->fence_reg);
-
-		err_puts(m, "\n");
-		err++;
-	}
-}
-
-static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
-				  struct drm_device *dev,
-				  struct drm_i915_error_state *error,
-				  unsigned ring)
-{
-	BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
-	err_printf(m, "%s command stream:\n", ring_str(ring));
-	err_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
-	err_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
-	err_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
-	err_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
-	err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
-	err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
-	err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
-	if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
-		err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
-
-	if (INTEL_INFO(dev)->gen >= 4)
-		err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
-	err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
-	err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
-	if (INTEL_INFO(dev)->gen >= 6) {
-		err_printf(m, "  RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
-		err_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
-		err_printf(m, "  SYNC_0: 0x%08x [last synced 0x%08x]\n",
-			   error->semaphore_mboxes[ring][0],
-			   error->semaphore_seqno[ring][0]);
-		err_printf(m, "  SYNC_1: 0x%08x [last synced 0x%08x]\n",
-			   error->semaphore_mboxes[ring][1],
-			   error->semaphore_seqno[ring][1]);
-	}
-	err_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
-	err_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
-	err_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
-	err_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
-}
-
-struct i915_error_state_file_priv {
-	struct drm_device *dev;
-	struct drm_i915_error_state *error;
-};
-
-
-static int i915_error_state(struct i915_error_state_file_priv *error_priv,
-			    struct drm_i915_error_state_buf *m)
-
-{
-	struct drm_device *dev = error_priv->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_error_state *error = error_priv->error;
-	struct intel_ring_buffer *ring;
-	int i, j, page, offset, elt;
-
-	if (!error) {
-		err_printf(m, "no error state collected\n");
-		return 0;
-	}
-
-	err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
-		   error->time.tv_usec);
-	err_printf(m, "Kernel: " UTS_RELEASE "\n");
-	err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
-	err_printf(m, "EIR: 0x%08x\n", error->eir);
-	err_printf(m, "IER: 0x%08x\n", error->ier);
-	err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
-	err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
-	err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
-	err_printf(m, "CCID: 0x%08x\n", error->ccid);
-
-	for (i = 0; i < dev_priv->num_fence_regs; i++)
-		err_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
-
-	for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
-		err_printf(m, "  INSTDONE_%d: 0x%08x\n", i,
-			   error->extra_instdone[i]);
-
-	if (INTEL_INFO(dev)->gen >= 6) {
-		err_printf(m, "ERROR: 0x%08x\n", error->error);
-		err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
-	}
-
-	if (INTEL_INFO(dev)->gen == 7)
-		err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
-
-	for_each_ring(ring, dev_priv, i)
-		i915_ring_error_state(m, dev, error, i);
-
-	if (error->active_bo)
-		print_error_buffers(m, "Active",
-				    error->active_bo,
-				    error->active_bo_count);
-
-	if (error->pinned_bo)
-		print_error_buffers(m, "Pinned",
-				    error->pinned_bo,
-				    error->pinned_bo_count);
-
-	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
-		struct drm_i915_error_object *obj;
-
-		if ((obj = error->ring[i].batchbuffer)) {
-			err_printf(m, "%s --- gtt_offset = 0x%08x\n",
-				   dev_priv->ring[i].name,
-				   obj->gtt_offset);
-			offset = 0;
-			for (page = 0; page < obj->page_count; page++) {
-				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-					err_printf(m, "%08x :  %08x\n", offset,
-						   obj->pages[page][elt]);
-					offset += 4;
-				}
-			}
-		}
-
-		if (error->ring[i].num_requests) {
-			err_printf(m, "%s --- %d requests\n",
-				   dev_priv->ring[i].name,
-				   error->ring[i].num_requests);
-			for (j = 0; j < error->ring[i].num_requests; j++) {
-				err_printf(m, "  seqno 0x%08x, emitted %ld, tail 0x%08x\n",
-					   error->ring[i].requests[j].seqno,
-					   error->ring[i].requests[j].jiffies,
-					   error->ring[i].requests[j].tail);
-			}
-		}
-
-		if ((obj = error->ring[i].ringbuffer)) {
-			err_printf(m, "%s --- ringbuffer = 0x%08x\n",
-				   dev_priv->ring[i].name,
-				   obj->gtt_offset);
-			offset = 0;
-			for (page = 0; page < obj->page_count; page++) {
-				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-					err_printf(m, "%08x :  %08x\n",
-						   offset,
-						   obj->pages[page][elt]);
-					offset += 4;
-				}
-			}
-		}
-
-		obj = error->ring[i].ctx;
-		if (obj) {
-			err_printf(m, "%s --- HW Context = 0x%08x\n",
-				   dev_priv->ring[i].name,
-				   obj->gtt_offset);
-			offset = 0;
-			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
-				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
-					   offset,
-					   obj->pages[0][elt],
-					   obj->pages[0][elt+1],
-					   obj->pages[0][elt+2],
-					   obj->pages[0][elt+3]);
-					offset += 16;
-			}
-		}
-	}
-
-	if (error->overlay)
-		intel_overlay_print_error_state(m, error->overlay);
-
-	if (error->display)
-		intel_display_print_error_state(m, dev, error->display);
-
-	return 0;
-}
-
 static ssize_t
 i915_error_state_write(struct file *filp,
 		       const char __user *ubuf,
@@ -986,9 +711,7 @@ i915_error_state_write(struct file *filp,
 static int i915_error_state_open(struct inode *inode, struct file *file)
 {
 	struct drm_device *dev = inode->i_private;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct i915_error_state_file_priv *error_priv;
-	unsigned long flags;
 
 	error_priv = kzalloc(sizeof(*error_priv), GFP_KERNEL);
 	if (!error_priv)
@@ -996,11 +719,7 @@ static int i915_error_state_open(struct inode *inode, struct file *file)
 
 	error_priv->dev = dev;
 
-	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
-	error_priv->error = dev_priv->gpu_error.first_error;
-	if (error_priv->error)
-		kref_get(&error_priv->error->ref);
-	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
+	i915_error_state_get(dev, error_priv);
 
 	file->private_data = error_priv;
 
@@ -1011,8 +730,7 @@ static int i915_error_state_release(struct inode *inode, struct file *file)
 {
 	struct i915_error_state_file_priv *error_priv = file->private_data;
 
-	if (error_priv->error)
-		kref_put(&error_priv->error->ref, i915_error_state_free);
+	i915_error_state_put(error_priv);
 	kfree(error_priv);
 
 	return 0;
@@ -1025,41 +743,16 @@ static ssize_t i915_error_state_read(struct file *file, char __user *userbuf,
 	struct drm_i915_error_state_buf error_str;
 	loff_t tmp_pos = 0;
 	ssize_t ret_count = 0;
-	int ret = 0;
-
-	memset(&error_str, 0, sizeof(error_str));
-
-	/* We need to have enough room to store any i915_error_state printf
-	 * so that we can move it to start position.
-	 */
-	error_str.size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
-	error_str.buf = kmalloc(error_str.size,
-				GFP_TEMPORARY | __GFP_NORETRY | __GFP_NOWARN);
-
-	if (error_str.buf == NULL) {
-		error_str.size = PAGE_SIZE;
-		error_str.buf = kmalloc(error_str.size, GFP_TEMPORARY);
-	}
-
-	if (error_str.buf == NULL) {
-		error_str.size = 128;
-		error_str.buf = kmalloc(error_str.size, GFP_TEMPORARY);
-	}
-
-	if (error_str.buf == NULL)
-		return -ENOMEM;
+	int ret;
 
-	error_str.start = *pos;
+	ret = i915_error_state_buf_init(&error_str, count, *pos);
+	if (ret)
+		return ret;
 
-	ret = i915_error_state(error_priv, &error_str);
+	ret = i915_error_state_to_str(&error_str, error_priv);
 	if (ret)
 		goto out;
 
-	if (error_str.bytes == 0 && error_str.err) {
-		ret = error_str.err;
-		goto out;
-	}
-
 	ret_count = simple_read_from_buffer(userbuf, count, &tmp_pos,
 					    error_str.buf,
 					    error_str.bytes);
@@ -1069,7 +762,7 @@ static ssize_t i915_error_state_read(struct file *file, char __user *userbuf,
 	else
 		*pos = error_str.start + ret_count;
 out:
-	kfree(error_str.buf);
+	i915_error_state_buf_release(&error_str);
 	return ret ?: ret_count;
 }
 
@@ -1246,7 +939,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 					(freq_sts >> 8) & 0xff));
 		mutex_unlock(&dev_priv->rps.hw_lock);
 	} else {
-		seq_printf(m, "no P-state info available\n");
+		seq_puts(m, "no P-state info available\n");
 	}
 
 	return 0;
@@ -1341,28 +1034,28 @@ static int ironlake_drpc_info(struct seq_file *m)
 	seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
 	seq_printf(m, "Render standby enabled: %s\n",
 		   (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
-	seq_printf(m, "Current RS state: ");
+	seq_puts(m, "Current RS state: ");
 	switch (rstdbyctl & RSX_STATUS_MASK) {
 	case RSX_STATUS_ON:
-		seq_printf(m, "on\n");
+		seq_puts(m, "on\n");
 		break;
 	case RSX_STATUS_RC1:
-		seq_printf(m, "RC1\n");
+		seq_puts(m, "RC1\n");
 		break;
 	case RSX_STATUS_RC1E:
-		seq_printf(m, "RC1E\n");
+		seq_puts(m, "RC1E\n");
 		break;
 	case RSX_STATUS_RS1:
-		seq_printf(m, "RS1\n");
+		seq_puts(m, "RS1\n");
 		break;
 	case RSX_STATUS_RS2:
-		seq_printf(m, "RS2 (RC6)\n");
+		seq_puts(m, "RS2 (RC6)\n");
 		break;
 	case RSX_STATUS_RS3:
-		seq_printf(m, "RC3 (RC6+)\n");
+		seq_puts(m, "RC3 (RC6+)\n");
 		break;
 	default:
-		seq_printf(m, "unknown\n");
+		seq_puts(m, "unknown\n");
 		break;
 	}
 
@@ -1377,20 +1070,19 @@ static int gen6_drpc_info(struct seq_file *m)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 rpmodectl1, gt_core_status, rcctl1, rc6vids = 0;
 	unsigned forcewake_count;
-	int count=0, ret;
-
+	int count = 0, ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	spin_lock_irq(&dev_priv->gt_lock);
-	forcewake_count = dev_priv->forcewake_count;
-	spin_unlock_irq(&dev_priv->gt_lock);
+	spin_lock_irq(&dev_priv->uncore.lock);
+	forcewake_count = dev_priv->uncore.forcewake_count;
+	spin_unlock_irq(&dev_priv->uncore.lock);
 
 	if (forcewake_count) {
-		seq_printf(m, "RC information inaccurate because somebody "
-			      "holds a forcewake reference \n");
+		seq_puts(m, "RC information inaccurate because somebody "
+			    "holds a forcewake reference \n");
 	} else {
 		/* NB: we cannot use forcewake, else we read the wrong values */
 		while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
@@ -1399,7 +1091,7 @@ static int gen6_drpc_info(struct seq_file *m)
 	}
 
 	gt_core_status = readl(dev_priv->regs + GEN6_GT_CORE_STATUS);
-	trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4);
+	trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true);
 
 	rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
 	rcctl1 = I915_READ(GEN6_RC_CONTROL);
@@ -1423,25 +1115,25 @@ static int gen6_drpc_info(struct seq_file *m)
 		   yesno(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE));
 	seq_printf(m, "Deepest RC6 Enabled: %s\n",
 		   yesno(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE));
-	seq_printf(m, "Current RC state: ");
+	seq_puts(m, "Current RC state: ");
 	switch (gt_core_status & GEN6_RCn_MASK) {
 	case GEN6_RC0:
 		if (gt_core_status & GEN6_CORE_CPD_STATE_MASK)
-			seq_printf(m, "Core Power Down\n");
+			seq_puts(m, "Core Power Down\n");
 		else
-			seq_printf(m, "on\n");
+			seq_puts(m, "on\n");
 		break;
 	case GEN6_RC3:
-		seq_printf(m, "RC3\n");
+		seq_puts(m, "RC3\n");
 		break;
 	case GEN6_RC6:
-		seq_printf(m, "RC6\n");
+		seq_puts(m, "RC6\n");
 		break;
 	case GEN6_RC7:
-		seq_printf(m, "RC7\n");
+		seq_puts(m, "RC7\n");
 		break;
 	default:
-		seq_printf(m, "Unknown\n");
+		seq_puts(m, "Unknown\n");
 		break;
 	}
 
@@ -1485,43 +1177,52 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
 	if (!I915_HAS_FBC(dev)) {
-		seq_printf(m, "FBC unsupported on this chipset\n");
+		seq_puts(m, "FBC unsupported on this chipset\n");
 		return 0;
 	}
 
 	if (intel_fbc_enabled(dev)) {
-		seq_printf(m, "FBC enabled\n");
+		seq_puts(m, "FBC enabled\n");
 	} else {
-		seq_printf(m, "FBC disabled: ");
-		switch (dev_priv->no_fbc_reason) {
+		seq_puts(m, "FBC disabled: ");
+		switch (dev_priv->fbc.no_fbc_reason) {
+		case FBC_OK:
+			seq_puts(m, "FBC actived, but currently disabled in hardware");
+			break;
+		case FBC_UNSUPPORTED:
+			seq_puts(m, "unsupported by this chipset");
+			break;
 		case FBC_NO_OUTPUT:
-			seq_printf(m, "no outputs");
+			seq_puts(m, "no outputs");
 			break;
 		case FBC_STOLEN_TOO_SMALL:
-			seq_printf(m, "not enough stolen memory");
+			seq_puts(m, "not enough stolen memory");
 			break;
 		case FBC_UNSUPPORTED_MODE:
-			seq_printf(m, "mode not supported");
+			seq_puts(m, "mode not supported");
 			break;
 		case FBC_MODE_TOO_LARGE:
-			seq_printf(m, "mode too large");
+			seq_puts(m, "mode too large");
 			break;
 		case FBC_BAD_PLANE:
-			seq_printf(m, "FBC unsupported on plane");
+			seq_puts(m, "FBC unsupported on plane");
 			break;
 		case FBC_NOT_TILED:
-			seq_printf(m, "scanout buffer not tiled");
+			seq_puts(m, "scanout buffer not tiled");
 			break;
 		case FBC_MULTIPLE_PIPES:
-			seq_printf(m, "multiple pipes are enabled");
+			seq_puts(m, "multiple pipes are enabled");
 			break;
 		case FBC_MODULE_PARAM:
-			seq_printf(m, "disabled per module param (default off)");
+			seq_puts(m, "disabled per module param (default off)");
+			break;
+		case FBC_CHIP_DEFAULT:
+			seq_puts(m, "disabled per chip default");
 			break;
 		default:
-			seq_printf(m, "unknown reason");
+			seq_puts(m, "unknown reason");
 		}
-		seq_printf(m, "\n");
+		seq_putc(m, '\n');
 	}
 	return 0;
 }
@@ -1604,7 +1305,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	int gpu_freq, ia_freq;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
-		seq_printf(m, "unsupported on this chipset\n");
+		seq_puts(m, "unsupported on this chipset\n");
 		return 0;
 	}
 
@@ -1612,7 +1313,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	if (ret)
 		return ret;
 
-	seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
+	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
 	for (gpu_freq = dev_priv->rps.min_delay;
 	     gpu_freq <= dev_priv->rps.max_delay;
@@ -1701,7 +1402,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
 		   fb->base.bits_per_pixel,
 		   atomic_read(&fb->base.refcount.refcount));
 	describe_obj(m, fb->obj);
-	seq_printf(m, "\n");
+	seq_putc(m, '\n');
 	mutex_unlock(&dev->mode_config.mutex);
 
 	mutex_lock(&dev->mode_config.fb_lock);
@@ -1716,7 +1417,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
 			   fb->base.bits_per_pixel,
 			   atomic_read(&fb->base.refcount.refcount));
 		describe_obj(m, fb->obj);
-		seq_printf(m, "\n");
+		seq_putc(m, '\n');
 	}
 	mutex_unlock(&dev->mode_config.fb_lock);
 
@@ -1736,22 +1437,22 @@ static int i915_context_status(struct seq_file *m, void *unused)
 		return ret;
 
 	if (dev_priv->ips.pwrctx) {
-		seq_printf(m, "power context ");
+		seq_puts(m, "power context ");
 		describe_obj(m, dev_priv->ips.pwrctx);
-		seq_printf(m, "\n");
+		seq_putc(m, '\n');
 	}
 
 	if (dev_priv->ips.renderctx) {
-		seq_printf(m, "render context ");
+		seq_puts(m, "render context ");
 		describe_obj(m, dev_priv->ips.renderctx);
-		seq_printf(m, "\n");
+		seq_putc(m, '\n');
 	}
 
 	for_each_ring(ring, dev_priv, i) {
 		if (ring->default_context) {
 			seq_printf(m, "HW default context %s ring ", ring->name);
 			describe_obj(m, ring->default_context->obj);
-			seq_printf(m, "\n");
+			seq_putc(m, '\n');
 		}
 	}
 
@@ -1767,9 +1468,9 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned forcewake_count;
 
-	spin_lock_irq(&dev_priv->gt_lock);
-	forcewake_count = dev_priv->forcewake_count;
-	spin_unlock_irq(&dev_priv->gt_lock);
+	spin_lock_irq(&dev_priv->uncore.lock);
+	forcewake_count = dev_priv->uncore.forcewake_count;
+	spin_unlock_irq(&dev_priv->uncore.lock);
 
 	seq_printf(m, "forcewake count = %u\n", forcewake_count);
 
@@ -1778,7 +1479,7 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
 
 static const char *swizzle_string(unsigned swizzle)
 {
-	switch(swizzle) {
+	switch (swizzle) {
 	case I915_BIT_6_SWIZZLE_NONE:
 		return "none";
 	case I915_BIT_6_SWIZZLE_9:
@@ -1868,7 +1569,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 	if (dev_priv->mm.aliasing_ppgtt) {
 		struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 
-		seq_printf(m, "aliasing PPGTT:\n");
+		seq_puts(m, "aliasing PPGTT:\n");
 		seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd_offset);
 	}
 	seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
@@ -1886,7 +1587,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 
 
 	if (!IS_VALLEYVIEW(dev)) {
-		seq_printf(m, "unsupported\n");
+		seq_puts(m, "unsupported\n");
 		return 0;
 	}
 
@@ -1924,6 +1625,148 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_llc(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* Size calculation for LLC is a bit of a pain. Ignore for now. */
+	seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(dev)));
+	seq_printf(m, "eLLC: %zuMB\n", dev_priv->ellc_size);
+
+	return 0;
+}
+
+static int i915_edp_psr_status(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 psrstat, psrperf;
+
+	if (!IS_HASWELL(dev)) {
+		seq_puts(m, "PSR not supported on this platform\n");
+	} else if (IS_HASWELL(dev) && I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
+		seq_puts(m, "PSR enabled\n");
+	} else {
+		seq_puts(m, "PSR disabled: ");
+		switch (dev_priv->no_psr_reason) {
+		case PSR_NO_SOURCE:
+			seq_puts(m, "not supported on this platform");
+			break;
+		case PSR_NO_SINK:
+			seq_puts(m, "not supported by panel");
+			break;
+		case PSR_MODULE_PARAM:
+			seq_puts(m, "disabled by flag");
+			break;
+		case PSR_CRTC_NOT_ACTIVE:
+			seq_puts(m, "crtc not active");
+			break;
+		case PSR_PWR_WELL_ENABLED:
+			seq_puts(m, "power well enabled");
+			break;
+		case PSR_NOT_TILED:
+			seq_puts(m, "not tiled");
+			break;
+		case PSR_SPRITE_ENABLED:
+			seq_puts(m, "sprite enabled");
+			break;
+		case PSR_S3D_ENABLED:
+			seq_puts(m, "stereo 3d enabled");
+			break;
+		case PSR_INTERLACED_ENABLED:
+			seq_puts(m, "interlaced enabled");
+			break;
+		case PSR_HSW_NOT_DDIA:
+			seq_puts(m, "HSW ties PSR to DDI A (eDP)");
+			break;
+		default:
+			seq_puts(m, "unknown reason");
+		}
+		seq_puts(m, "\n");
+		return 0;
+	}
+
+	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
+
+	seq_puts(m, "PSR Current State: ");
+	switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
+	case EDP_PSR_STATUS_STATE_IDLE:
+		seq_puts(m, "Reset state\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDONACK:
+		seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDENT:
+		seq_puts(m, "SRD entry\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFOFF:
+		seq_puts(m, "Wait for buffer turn off\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFON:
+		seq_puts(m, "Wait for buffer turn on\n");
+		break;
+	case EDP_PSR_STATUS_STATE_AUXACK:
+		seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDOFFACK:
+		seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");
+		break;
+	default:
+		seq_puts(m, "Unknown\n");
+		break;
+	}
+
+	seq_puts(m, "Link Status: ");
+	switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
+	case EDP_PSR_STATUS_LINK_FULL_OFF:
+		seq_puts(m, "Link is fully off\n");
+		break;
+	case EDP_PSR_STATUS_LINK_FULL_ON:
+		seq_puts(m, "Link is fully on\n");
+		break;
+	case EDP_PSR_STATUS_LINK_STANDBY:
+		seq_puts(m, "Link is in standby\n");
+		break;
+	default:
+		seq_puts(m, "Unknown\n");
+		break;
+	}
+
+	seq_printf(m, "PSR Entry Count: %u\n",
+		   psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
+		   EDP_PSR_STATUS_COUNT_MASK);
+
+	seq_printf(m, "Max Sleep Timer Counter: %u\n",
+		   psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
+		   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
+
+	seq_printf(m, "Had AUX error: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
+
+	seq_printf(m, "Sending AUX: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
+
+	seq_printf(m, "Sending Idle: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE));
+
+	seq_printf(m, "Sending TP2 TP3: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3));
+
+	seq_printf(m, "Sending TP1: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
+
+	seq_printf(m, "Idle Count: %u\n",
+		   psrstat & EDP_PSR_STATUS_IDLE_MASK);
+
+	psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
+	seq_printf(m, "Performance Counter: %u\n", psrperf);
+
+	return 0;
+}
+
 static int
 i915_wedged_get(void *data, u64 *val)
 {
@@ -2006,6 +1849,8 @@ i915_drop_caches_set(void *data, u64 val)
 	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj, *next;
+	struct i915_address_space *vm;
+	struct i915_vma *vma, *x;
 	int ret;
 
 	DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val);
@@ -2026,12 +1871,17 @@ i915_drop_caches_set(void *data, u64 val)
 		i915_gem_retire_requests(dev);
 
 	if (val & DROP_BOUND) {
-		list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list, mm_list)
-			if (obj->pin_count == 0) {
-				ret = i915_gem_object_unbind(obj);
+		list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+			list_for_each_entry_safe(vma, x, &vm->inactive_list,
+						 mm_list) {
+				if (vma->obj->pin_count)
+					continue;
+
+				ret = i915_vma_unbind(vma);
 				if (ret)
 					goto unlock;
 			}
+		}
 	}
 
 	if (val & DROP_UNBOUND) {
@@ -2326,6 +2176,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_gem_pinned", i915_gem_gtt_info, 0, (void *) PINNED_LIST},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
 	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
+	{"i915_gem_stolen", i915_gem_stolen_list_info },
 	{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
 	{"i915_gem_request", i915_gem_request_info, 0},
 	{"i915_gem_seqno", i915_gem_seqno_info, 0},
@@ -2353,64 +2204,40 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_dpio", i915_dpio_info, 0},
+	{"i915_llc", i915_llc, 0},
+	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
+static struct i915_debugfs_files {
+	const char *name;
+	const struct file_operations *fops;
+} i915_debugfs_files[] = {
+	{"i915_wedged", &i915_wedged_fops},
+	{"i915_max_freq", &i915_max_freq_fops},
+	{"i915_min_freq", &i915_min_freq_fops},
+	{"i915_cache_sharing", &i915_cache_sharing_fops},
+	{"i915_ring_stop", &i915_ring_stop_fops},
+	{"i915_gem_drop_caches", &i915_drop_caches_fops},
+	{"i915_error_state", &i915_error_state_fops},
+	{"i915_next_seqno", &i915_next_seqno_fops},
+};
+
 int i915_debugfs_init(struct drm_minor *minor)
 {
-	int ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_wedged",
-				  &i915_wedged_fops);
-	if (ret)
-		return ret;
+	int ret, i;
 
 	ret = i915_forcewake_create(minor->debugfs_root, minor);
 	if (ret)
 		return ret;
 
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_max_freq",
-				  &i915_max_freq_fops);
-	if (ret)
-		return ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_min_freq",
-				  &i915_min_freq_fops);
-	if (ret)
-		return ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_cache_sharing",
-				  &i915_cache_sharing_fops);
-	if (ret)
-		return ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_ring_stop",
-				  &i915_ring_stop_fops);
-	if (ret)
-		return ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_gem_drop_caches",
-				  &i915_drop_caches_fops);
-	if (ret)
-		return ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				  "i915_error_state",
-				  &i915_error_state_fops);
-	if (ret)
-		return ret;
-
-	ret = i915_debugfs_create(minor->debugfs_root, minor,
-				 "i915_next_seqno",
-				 &i915_next_seqno_fops);
-	if (ret)
-		return ret;
+	for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
+		ret = i915_debugfs_create(minor->debugfs_root, minor,
+					  i915_debugfs_files[i].name,
+					  i915_debugfs_files[i].fops);
+		if (ret)
+			return ret;
+	}
 
 	return drm_debugfs_create_files(i915_debugfs_list,
 					I915_DEBUGFS_ENTRIES,
@@ -2419,26 +2246,18 @@ int i915_debugfs_init(struct drm_minor *minor)
 
 void i915_debugfs_cleanup(struct drm_minor *minor)
 {
+	int i;
+
 	drm_debugfs_remove_files(i915_debugfs_list,
 				 I915_DEBUGFS_ENTRIES, minor);
 	drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops,
 				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_min_freq_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_drop_caches_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops,
-				 1, minor);
-	drm_debugfs_remove_files((struct drm_info_list *) &i915_next_seqno_fops,
-				 1, minor);
+	for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
+		struct drm_info_list *info_list =
+			(struct drm_info_list *) i915_debugfs_files[i].fops;
+
+		drm_debugfs_remove_files(info_list, 1, minor);
+	}
 }
 
 #endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f466980..0af35cd 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1323,10 +1323,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	/* Always safe in the mode setting case. */
 	/* FIXME: do pre/post-mode set stuff in core KMS code */
 	dev->vblank_disable_allowed = 1;
-	if (INTEL_INFO(dev)->num_pipes == 0) {
-		dev_priv->mm.suspended = 0;
+	if (INTEL_INFO(dev)->num_pipes == 0)
 		return 0;
-	}
 
 	ret = intel_fbdev_init(dev);
 	if (ret)
@@ -1352,9 +1350,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
 	drm_kms_helper_poll_init(dev);
 
-	/* We're off and running w/KMS */
-	dev_priv->mm.suspended = 0;
-
 	return 0;
 
 cleanup_gem:
@@ -1363,7 +1358,7 @@ cleanup_gem:
 	i915_gem_context_fini(dev);
 	mutex_unlock(&dev->struct_mutex);
 	i915_gem_cleanup_aliasing_ppgtt(dev);
-	drm_mm_takedown(&dev_priv->mm.gtt_space);
+	drm_mm_takedown(&dev_priv->gtt.base.mm);
 cleanup_irq:
 	drm_irq_uninstall(dev);
 cleanup_gem_stolen:
@@ -1441,22 +1436,6 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 }
 
 /**
- * intel_early_sanitize_regs - clean up BIOS state
- * @dev: DRM device
- *
- * This function must be called before we do any I915_READ or I915_WRITE. Its
- * purpose is to clean up any state left by the BIOS that may affect us when
- * reading and/or writing registers.
- */
-static void intel_early_sanitize_regs(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (HAS_FPGA_DBG_UNCLAIMED(dev))
-		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-}
-
-/**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
  * @flags: startup flags
@@ -1497,9 +1476,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->gpu_error.lock);
-	spin_lock_init(&dev_priv->rps.lock);
-	spin_lock_init(&dev_priv->gt_lock);
 	spin_lock_init(&dev_priv->backlight.lock);
+	spin_lock_init(&dev_priv->uncore.lock);
+	spin_lock_init(&dev_priv->mm.object_stat_lock);
 	mutex_init(&dev_priv->dpio_lock);
 	mutex_init(&dev_priv->rps.hw_lock);
 	mutex_init(&dev_priv->modeset_restore_lock);
@@ -1531,7 +1510,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto put_bridge;
 	}
 
-	intel_early_sanitize_regs(dev);
+	intel_uncore_early_sanitize(dev);
+
+	if (IS_HASWELL(dev) && (I915_READ(HSW_EDRAM_PRESENT) == 1)) {
+		/* The docs do not explain exactly how the calculation can be
+		 * made. It is somewhat guessable, but for now, it's always
+		 * 128MB.
+		 * NB: We can't write IDICR yet because we do not have gt funcs
+		 * set up */
+		dev_priv->ellc_size = 128;
+		DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size);
+	}
 
 	ret = i915_gem_gtt_init(dev);
 	if (ret)
@@ -1567,8 +1556,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto out_rmmap;
 	}
 
-	dev_priv->mm.gtt_mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
-						 aperture_size);
+	dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
+					      aperture_size);
 
 	/* The i915 workqueue is primarily used for batched retirement of
 	 * requests (and thus managing bo) once the task has been completed
@@ -1595,8 +1584,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_irq_init(dev);
 	intel_pm_init(dev);
-	intel_gt_sanitize(dev);
-	intel_gt_init(dev);
+	intel_uncore_sanitize(dev);
+	intel_uncore_init(dev);
 
 	/* Try to make sure MCHBAR is enabled before poking at it */
 	intel_setup_mchbar(dev);
@@ -1631,9 +1620,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 			goto out_gem_unload;
 	}
 
-	/* Start out suspended */
-	dev_priv->mm.suspended = 1;
-
 	if (HAS_POWER_WELL(dev))
 		i915_init_power_well(dev);
 
@@ -1643,6 +1629,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 			DRM_ERROR("failed to init modeset\n");
 			goto out_gem_unload;
 		}
+	} else {
+		/* Start out suspended in ums mode. */
+		dev_priv->ums.mm_suspended = 1;
 	}
 
 	i915_setup_sysfs(dev);
@@ -1659,7 +1648,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	return 0;
 
 out_gem_unload:
-	if (dev_priv->mm.inactive_shrinker.shrink)
+	if (dev_priv->mm.inactive_shrinker.scan_objects)
 		unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
 	if (dev->pdev->msi_enabled)
@@ -1669,9 +1658,9 @@ out_gem_unload:
 	intel_teardown_mchbar(dev);
 	destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
-	arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
+	arch_phys_wc_del(dev_priv->gtt.mtrr);
 	io_mapping_free(dev_priv->gtt.mappable);
-	dev_priv->gtt.gtt_remove(dev);
+	dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
 out_rmmap:
 	pci_iounmap(dev->pdev, dev_priv->regs);
 put_bridge:
@@ -1693,7 +1682,7 @@ int i915_driver_unload(struct drm_device *dev)
 
 	i915_teardown_sysfs(dev);
 
-	if (dev_priv->mm.inactive_shrinker.shrink)
+	if (dev_priv->mm.inactive_shrinker.scan_objects)
 		unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
 	mutex_lock(&dev->struct_mutex);
@@ -1707,7 +1696,7 @@ int i915_driver_unload(struct drm_device *dev)
 	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
 
 	io_mapping_free(dev_priv->gtt.mappable);
-	arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
+	arch_phys_wc_del(dev_priv->gtt.mtrr);
 
 	acpi_video_unregister();
 
@@ -1756,7 +1745,9 @@ int i915_driver_unload(struct drm_device *dev)
 			i915_free_hws(dev);
 	}
 
-	drm_mm_takedown(&dev_priv->mm.gtt_space);
+	list_del(&dev_priv->gtt.base.global_link);
+	WARN_ON(!list_empty(&dev_priv->vm_list));
+	drm_mm_takedown(&dev_priv->gtt.base.mm);
 	if (dev_priv->regs != NULL)
 		pci_iounmap(dev->pdev, dev_priv->regs);
 
@@ -1766,7 +1757,7 @@ int i915_driver_unload(struct drm_device *dev)
 	destroy_workqueue(dev_priv->wq);
 	pm_qos_remove_request(&dev_priv->pm_qos);
 
-	dev_priv->gtt.gtt_remove(dev);
+	dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
 
 	if (dev_priv->slab)
 		kmem_cache_destroy(dev_priv->slab);
@@ -1842,7 +1833,7 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
 	kfree(file_priv);
 }
 
-struct drm_ioctl_desc i915_ioctls[] = {
+const struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(I915_FLIP, i915_flip_bufs, DRM_AUTH),
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 45b3c03..13457e3e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -118,6 +118,10 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
 		"Enable PPGTT (default: true)");
 
+int i915_enable_psr __read_mostly = 0;
+module_param_named(enable_psr, i915_enable_psr, int, 0600);
+MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)");
+
 unsigned int i915_preliminary_hw_support __read_mostly = 0;
 module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
 MODULE_PARM_DESC(preliminary_hw_support,
@@ -132,6 +136,16 @@ int i915_enable_ips __read_mostly = 1;
 module_param_named(enable_ips, i915_enable_ips, int, 0600);
 MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
 
+bool i915_fastboot __read_mostly = 0;
+module_param_named(fastboot, i915_fastboot, bool, 0600);
+MODULE_PARM_DESC(fastboot, "Try to skip unnecessary mode sets at boot time "
+		 "(default: false)");
+
+bool i915_prefault_disable __read_mostly;
+module_param_named(prefault_disable, i915_prefault_disable, bool, 0600);
+MODULE_PARM_DESC(prefault_disable,
+		"Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only.");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -551,7 +565,11 @@ static int i915_drm_freeze(struct drm_device *dev)
 
 	/* If KMS is active, we do the leavevt stuff here */
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		int error = i915_gem_idle(dev);
+		int error;
+
+		mutex_lock(&dev->struct_mutex);
+		error = i915_gem_idle(dev);
+		mutex_unlock(&dev->struct_mutex);
 		if (error) {
 			dev_err(&dev->pdev->dev,
 				"GEM idle failed, resume might fail\n");
@@ -656,7 +674,6 @@ static int __i915_drm_thaw(struct drm_device *dev)
 		intel_init_pch_refclk(dev);
 
 		mutex_lock(&dev->struct_mutex);
-		dev_priv->mm.suspended = 0;
 
 		error = i915_gem_init_hw(dev);
 		mutex_unlock(&dev->struct_mutex);
@@ -706,7 +723,7 @@ static int i915_drm_thaw(struct drm_device *dev)
 {
 	int error = 0;
 
-	intel_gt_sanitize(dev);
+	intel_uncore_sanitize(dev);
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		mutex_lock(&dev->struct_mutex);
@@ -732,7 +749,7 @@ int i915_resume(struct drm_device *dev)
 
 	pci_set_master(dev->pdev);
 
-	intel_gt_sanitize(dev);
+	intel_uncore_sanitize(dev);
 
 	/*
 	 * Platforms with opregion should have sane BIOS, older ones (gen3 and
@@ -753,139 +770,6 @@ int i915_resume(struct drm_device *dev)
 	return 0;
 }
 
-static int i8xx_do_reset(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (IS_I85X(dev))
-		return -ENODEV;
-
-	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
-	POSTING_READ(D_STATE);
-
-	if (IS_I830(dev) || IS_845G(dev)) {
-		I915_WRITE(DEBUG_RESET_I830,
-			   DEBUG_RESET_DISPLAY |
-			   DEBUG_RESET_RENDER |
-			   DEBUG_RESET_FULL);
-		POSTING_READ(DEBUG_RESET_I830);
-		msleep(1);
-
-		I915_WRITE(DEBUG_RESET_I830, 0);
-		POSTING_READ(DEBUG_RESET_I830);
-	}
-
-	msleep(1);
-
-	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
-	POSTING_READ(D_STATE);
-
-	return 0;
-}
-
-static int i965_reset_complete(struct drm_device *dev)
-{
-	u8 gdrst;
-	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
-	return (gdrst & GRDOM_RESET_ENABLE) == 0;
-}
-
-static int i965_do_reset(struct drm_device *dev)
-{
-	int ret;
-	u8 gdrst;
-
-	/*
-	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
-	 * well as the reset bit (GR/bit 0).  Setting the GR bit
-	 * triggers the reset; when done, the hardware will clear it.
-	 */
-	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
-	pci_write_config_byte(dev->pdev, I965_GDRST,
-			      gdrst | GRDOM_RENDER |
-			      GRDOM_RESET_ENABLE);
-	ret =  wait_for(i965_reset_complete(dev), 500);
-	if (ret)
-		return ret;
-
-	/* We can't reset render&media without also resetting display ... */
-	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
-	pci_write_config_byte(dev->pdev, I965_GDRST,
-			      gdrst | GRDOM_MEDIA |
-			      GRDOM_RESET_ENABLE);
-
-	return wait_for(i965_reset_complete(dev), 500);
-}
-
-static int ironlake_do_reset(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 gdrst;
-	int ret;
-
-	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
-	gdrst &= ~GRDOM_MASK;
-	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
-		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
-	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
-	if (ret)
-		return ret;
-
-	/* We can't reset render&media without also resetting display ... */
-	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
-	gdrst &= ~GRDOM_MASK;
-	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
-		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
-	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
-}
-
-static int gen6_do_reset(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int	ret;
-	unsigned long irqflags;
-
-	/* Hold gt_lock across reset to prevent any register access
-	 * with forcewake not set correctly
-	 */
-	spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
-
-	/* Reset the chip */
-
-	/* GEN6_GDRST is not in the gt power well, no need to check
-	 * for fifo space for the write or forcewake the chip for
-	 * the read
-	 */
-	I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
-
-	/* Spin waiting for the device to ack the reset request */
-	ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
-
-	/* If reset with a user forcewake, try to restore, otherwise turn it off */
-	if (dev_priv->forcewake_count)
-		dev_priv->gt.force_wake_get(dev_priv);
-	else
-		dev_priv->gt.force_wake_put(dev_priv);
-
-	/* Restore fifo count */
-	dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-
-	spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
-	return ret;
-}
-
-int intel_gpu_reset(struct drm_device *dev)
-{
-	switch (INTEL_INFO(dev)->gen) {
-	case 7:
-	case 6: return gen6_do_reset(dev);
-	case 5: return ironlake_do_reset(dev);
-	case 4: return i965_do_reset(dev);
-	case 2: return i8xx_do_reset(dev);
-	default: return -ENODEV;
-	}
-}
-
 /**
  * i915_reset - reset chip after a hang
  * @dev: drm device to reset
@@ -955,11 +839,11 @@ int i915_reset(struct drm_device *dev)
 	 * switched away).
 	 */
 	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
-			!dev_priv->mm.suspended) {
+			!dev_priv->ums.mm_suspended) {
 		struct intel_ring_buffer *ring;
 		int i;
 
-		dev_priv->mm.suspended = 0;
+		dev_priv->ums.mm_suspended = 0;
 
 		i915_gem_init_swizzling(dev);
 
@@ -1154,7 +1038,7 @@ static struct drm_driver driver = {
 
 	.dumb_create = i915_gem_dumb_create,
 	.dumb_map_offset = i915_gem_mmap_gtt,
-	.dumb_destroy = i915_gem_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 	.ioctls = i915_ioctls,
 	.fops = &i915_driver_fops,
 	.name = DRIVER_NAME,
@@ -1215,136 +1099,3 @@ module_exit(i915_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL and additional rights");
-
-/* We give fast paths for the really cool registers */
-#define NEEDS_FORCE_WAKE(dev_priv, reg) \
-	((HAS_FORCE_WAKE((dev_priv)->dev)) && \
-	 ((reg) < 0x40000) &&            \
-	 ((reg) != FORCEWAKE))
-static void
-ilk_dummy_write(struct drm_i915_private *dev_priv)
-{
-	/* WaIssueDummyWriteToWakeupFromRC6:ilk Issue a dummy write to wake up
-	 * the chip from rc6 before touching it for real. MI_MODE is masked,
-	 * hence harmless to write 0 into. */
-	I915_WRITE_NOTRACE(MI_MODE, 0);
-}
-
-static void
-hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
-{
-	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
-	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
-		DRM_ERROR("Unknown unclaimed register before writing to %x\n",
-			  reg);
-		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-	}
-}
-
-static void
-hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
-{
-	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
-	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
-		DRM_ERROR("Unclaimed write to %x\n", reg);
-		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-	}
-}
-
-#define __i915_read(x, y) \
-u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
-	unsigned long irqflags; \
-	u##x val = 0; \
-	spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
-	if (IS_GEN5(dev_priv->dev)) \
-		ilk_dummy_write(dev_priv); \
-	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-		if (dev_priv->forcewake_count == 0) \
-			dev_priv->gt.force_wake_get(dev_priv); \
-		val = read##y(dev_priv->regs + reg); \
-		if (dev_priv->forcewake_count == 0) \
-			dev_priv->gt.force_wake_put(dev_priv); \
-	} else { \
-		val = read##y(dev_priv->regs + reg); \
-	} \
-	spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
-	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
-	return val; \
-}
-
-__i915_read(8, b)
-__i915_read(16, w)
-__i915_read(32, l)
-__i915_read(64, q)
-#undef __i915_read
-
-#define __i915_write(x, y) \
-void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
-	unsigned long irqflags; \
-	u32 __fifo_ret = 0; \
-	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
-	spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
-	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
-	} \
-	if (IS_GEN5(dev_priv->dev)) \
-		ilk_dummy_write(dev_priv); \
-	hsw_unclaimed_reg_clear(dev_priv, reg); \
-	write##y(val, dev_priv->regs + reg); \
-	if (unlikely(__fifo_ret)) { \
-		gen6_gt_check_fifodbg(dev_priv); \
-	} \
-	hsw_unclaimed_reg_check(dev_priv, reg); \
-	spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
-}
-__i915_write(8, b)
-__i915_write(16, w)
-__i915_write(32, l)
-__i915_write(64, q)
-#undef __i915_write
-
-static const struct register_whitelist {
-	uint64_t offset;
-	uint32_t size;
-	uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
-} whitelist[] = {
-	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
-};
-
-int i915_reg_read_ioctl(struct drm_device *dev,
-			void *data, struct drm_file *file)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_reg_read *reg = data;
-	struct register_whitelist const *entry = whitelist;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
-		if (entry->offset == reg->offset &&
-		    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
-			break;
-	}
-
-	if (i == ARRAY_SIZE(whitelist))
-		return -EINVAL;
-
-	switch (entry->size) {
-	case 8:
-		reg->val = I915_READ64(reg->offset);
-		break;
-	case 4:
-		reg->val = I915_READ(reg->offset);
-		break;
-	case 2:
-		reg->val = I915_READ16(reg->offset);
-		break;
-	case 1:
-		reg->val = I915_READ8(reg->offset);
-		break;
-	default:
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1929bff..7863c8a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -144,6 +144,7 @@ enum intel_dpll_id {
 
 struct intel_dpll_hw_state {
 	uint32_t dpll;
+	uint32_t dpll_md;
 	uint32_t fp0;
 	uint32_t fp1;
 };
@@ -156,6 +157,8 @@ struct intel_shared_dpll {
 	/* should match the index in the dev_priv->shared_dplls array */
 	enum intel_dpll_id id;
 	struct intel_dpll_hw_state hw_state;
+	void (*mode_set)(struct drm_i915_private *dev_priv,
+			 struct intel_shared_dpll *pll);
 	void (*enable)(struct drm_i915_private *dev_priv,
 		       struct intel_shared_dpll *pll);
 	void (*disable)(struct drm_i915_private *dev_priv,
@@ -320,8 +323,8 @@ struct drm_i915_error_state {
 		u32 purgeable:1;
 		s32 ring:4;
 		u32 cache_level:2;
-	} *active_bo, *pinned_bo;
-	u32 active_bo_count, pinned_bo_count;
+	} **active_bo, **pinned_bo;
+	u32 *active_bo_count, *pinned_bo_count;
 	struct intel_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
 };
@@ -356,14 +359,16 @@ struct drm_i915_display_funcs {
 			  struct dpll *match_clock,
 			  struct dpll *best_clock);
 	void (*update_wm)(struct drm_device *dev);
-	void (*update_sprite_wm)(struct drm_device *dev, int pipe,
+	void (*update_sprite_wm)(struct drm_plane *plane,
+				 struct drm_crtc *crtc,
 				 uint32_t sprite_width, int pixel_size,
-				 bool enable);
+				 bool enable, bool scaled);
 	void (*modeset_global_resources)(struct drm_device *dev);
 	/* Returns the active state of the crtc, and if the crtc is active,
 	 * fills out the pipe-config with the hw state. */
 	bool (*get_pipe_config)(struct intel_crtc *,
 				struct intel_crtc_config *);
+	void (*get_clock)(struct intel_crtc *, struct intel_crtc_config *);
 	int (*crtc_mode_set)(struct drm_crtc *crtc,
 			     int x, int y,
 			     struct drm_framebuffer *old_fb);
@@ -387,11 +392,20 @@ struct drm_i915_display_funcs {
 	/* pll clock increase/decrease */
 };
 
-struct drm_i915_gt_funcs {
+struct intel_uncore_funcs {
 	void (*force_wake_get)(struct drm_i915_private *dev_priv);
 	void (*force_wake_put)(struct drm_i915_private *dev_priv);
 };
 
+struct intel_uncore {
+	spinlock_t lock; /** lock is also taken in irq contexts. */
+
+	struct intel_uncore_funcs funcs;
+
+	unsigned fifo_count;
+	unsigned forcewake_count;
+};
+
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
 	func(is_mobile) sep \
 	func(is_i85x) sep \
@@ -436,12 +450,63 @@ struct intel_device_info {
 
 enum i915_cache_level {
 	I915_CACHE_NONE = 0,
-	I915_CACHE_LLC,
-	I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */
+	I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */
+	I915_CACHE_L3_LLC, /* gen7+, L3 sits between the domain specifc
+			      caches, eg sampler/render caches, and the
+			      large Last-Level-Cache. LLC is coherent with
+			      the CPU, but L3 is only visible to the GPU. */
 };
 
 typedef uint32_t gen6_gtt_pte_t;
 
+struct i915_address_space {
+	struct drm_mm mm;
+	struct drm_device *dev;
+	struct list_head global_link;
+	unsigned long start;		/* Start offset always 0 for dri2 */
+	size_t total;		/* size addr space maps (ex. 2GB for ggtt) */
+
+	struct {
+		dma_addr_t addr;
+		struct page *page;
+	} scratch;
+
+	/**
+	 * List of objects currently involved in rendering.
+	 *
+	 * Includes buffers having the contents of their GPU caches
+	 * flushed, not necessarily primitives.  last_rendering_seqno
+	 * represents when the rendering involved will be completed.
+	 *
+	 * A reference is held on the buffer while on this list.
+	 */
+	struct list_head active_list;
+
+	/**
+	 * LRU list of objects which are not in the ringbuffer and
+	 * are ready to unbind, but are still in the GTT.
+	 *
+	 * last_rendering_seqno is 0 while an object is in this list.
+	 *
+	 * A reference is not held on the buffer while on this list,
+	 * as merely being GTT-bound shouldn't prevent its being
+	 * freed, and we'll pull it off the list in the free path.
+	 */
+	struct list_head inactive_list;
+
+	/* FIXME: Need a more generic return type */
+	gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
+				     enum i915_cache_level level);
+	void (*clear_range)(struct i915_address_space *vm,
+			    unsigned int first_entry,
+			    unsigned int num_entries);
+	void (*insert_entries)(struct i915_address_space *vm,
+			       struct sg_table *st,
+			       unsigned int first_entry,
+			       enum i915_cache_level cache_level);
+	void (*cleanup)(struct i915_address_space *vm);
+};
+
 /* The Graphics Translation Table is the way in which GEN hardware translates a
  * Graphics Virtual Address into a Physical Address. In addition to the normal
  * collateral associated with any va->pa translations GEN hardware also has a
@@ -450,8 +515,7 @@ typedef uint32_t gen6_gtt_pte_t;
  * the spec.
  */
 struct i915_gtt {
-	unsigned long start;		/* Start offset of used GTT */
-	size_t total;			/* Total size GTT can map */
+	struct i915_address_space base;
 	size_t stolen_size;		/* Total size of stolen memory */
 
 	unsigned long mappable_end;	/* End offset that we can CPU map */
@@ -462,50 +526,43 @@ struct i915_gtt {
 	void __iomem *gsm;
 
 	bool do_idle_maps;
-	dma_addr_t scratch_page_dma;
-	struct page *scratch_page;
+
+	int mtrr;
 
 	/* global gtt ops */
 	int (*gtt_probe)(struct drm_device *dev, size_t *gtt_total,
 			  size_t *stolen, phys_addr_t *mappable_base,
 			  unsigned long *mappable_end);
-	void (*gtt_remove)(struct drm_device *dev);
-	void (*gtt_clear_range)(struct drm_device *dev,
-				unsigned int first_entry,
-				unsigned int num_entries);
-	void (*gtt_insert_entries)(struct drm_device *dev,
-				   struct sg_table *st,
-				   unsigned int pg_start,
-				   enum i915_cache_level cache_level);
-	gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev,
-				     dma_addr_t addr,
-				     enum i915_cache_level level);
 };
-#define gtt_total_entries(gtt) ((gtt).total >> PAGE_SHIFT)
+#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
 
-#define I915_PPGTT_PD_ENTRIES 512
-#define I915_PPGTT_PT_ENTRIES 1024
 struct i915_hw_ppgtt {
-	struct drm_device *dev;
+	struct i915_address_space base;
 	unsigned num_pd_entries;
 	struct page **pt_pages;
 	uint32_t pd_offset;
 	dma_addr_t *pt_dma_addr;
-	dma_addr_t scratch_page_dma_addr;
 
-	/* pte functions, mirroring the interface of the global gtt. */
-	void (*clear_range)(struct i915_hw_ppgtt *ppgtt,
-			    unsigned int first_entry,
-			    unsigned int num_entries);
-	void (*insert_entries)(struct i915_hw_ppgtt *ppgtt,
-			       struct sg_table *st,
-			       unsigned int pg_start,
-			       enum i915_cache_level cache_level);
-	gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev,
-				     dma_addr_t addr,
-				     enum i915_cache_level level);
 	int (*enable)(struct drm_device *dev);
-	void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
+};
+
+/**
+ * A VMA represents a GEM BO that is bound into an address space. Therefore, a
+ * VMA's presence cannot be guaranteed before binding, or after unbinding the
+ * object into/from the address space.
+ *
+ * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
+ * will always be <= an objects lifetime. So object refcounting should cover us.
+ */
+struct i915_vma {
+	struct drm_mm_node node;
+	struct drm_i915_gem_object *obj;
+	struct i915_address_space *vm;
+
+	/** This object's place on the active/inactive lists */
+	struct list_head mm_list;
+
+	struct list_head vma_link; /* Link in the object's VMA list */
 };
 
 struct i915_ctx_hang_stats {
@@ -528,15 +585,48 @@ struct i915_hw_context {
 	struct i915_ctx_hang_stats hang_stats;
 };
 
-enum no_fbc_reason {
-	FBC_NO_OUTPUT, /* no outputs enabled to compress */
-	FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
-	FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
-	FBC_MODE_TOO_LARGE, /* mode too large for compression */
-	FBC_BAD_PLANE, /* fbc not supported on plane */
-	FBC_NOT_TILED, /* buffer not tiled */
-	FBC_MULTIPLE_PIPES, /* more than one pipe active */
-	FBC_MODULE_PARAM,
+struct i915_fbc {
+	unsigned long size;
+	unsigned int fb_id;
+	enum plane plane;
+	int y;
+
+	struct drm_mm_node *compressed_fb;
+	struct drm_mm_node *compressed_llb;
+
+	struct intel_fbc_work {
+		struct delayed_work work;
+		struct drm_crtc *crtc;
+		struct drm_framebuffer *fb;
+		int interval;
+	} *fbc_work;
+
+	enum no_fbc_reason {
+		FBC_OK, /* FBC is enabled */
+		FBC_UNSUPPORTED, /* FBC is not supported by this chipset */
+		FBC_NO_OUTPUT, /* no outputs enabled to compress */
+		FBC_STOLEN_TOO_SMALL, /* not enough space for buffers */
+		FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
+		FBC_MODE_TOO_LARGE, /* mode too large for compression */
+		FBC_BAD_PLANE, /* fbc not supported on plane */
+		FBC_NOT_TILED, /* buffer not tiled */
+		FBC_MULTIPLE_PIPES, /* more than one pipe active */
+		FBC_MODULE_PARAM,
+		FBC_CHIP_DEFAULT, /* disabled by default on this chip */
+	} no_fbc_reason;
+};
+
+enum no_psr_reason {
+	PSR_NO_SOURCE, /* Not supported on platform */
+	PSR_NO_SINK, /* Not supported by panel */
+	PSR_MODULE_PARAM,
+	PSR_CRTC_NOT_ACTIVE,
+	PSR_PWR_WELL_ENABLED,
+	PSR_NOT_TILED,
+	PSR_SPRITE_ENABLED,
+	PSR_S3D_ENABLED,
+	PSR_INTERLACED_ENABLED,
+	PSR_HSW_NOT_DDIA,
 };
 
 enum intel_pch {
@@ -722,12 +812,12 @@ struct i915_suspend_saved_registers {
 };
 
 struct intel_gen6_power_mgmt {
+	/* work and pm_iir are protected by dev_priv->irq_lock */
 	struct work_struct work;
-	struct delayed_work vlv_work;
 	u32 pm_iir;
-	/* lock - irqsave spinlock that protectects the work_struct and
-	 * pm_iir. */
-	spinlock_t lock;
+
+	/* On vlv we need to manually drop to Vmin with a delayed work. */
+	struct delayed_work vlv_work;
 
 	/* The below variables an all the rps hw state are protected by
 	 * dev->struct mutext. */
@@ -793,6 +883,18 @@ struct i915_dri1_state {
 	uint32_t counter;
 };
 
+struct i915_ums_state {
+	/**
+	 * Flag if the X Server, and thus DRM, is not currently in
+	 * control of the device.
+	 *
+	 * This is set between LeaveVT and EnterVT.  It needs to be
+	 * replaced with a semaphore.  It also needs to be
+	 * transitioned away from for kernel modesetting.
+	 */
+	int mm_suspended;
+};
+
 struct intel_l3_parity {
 	u32 *remap_info;
 	struct work_struct error_work;
@@ -801,8 +903,6 @@ struct intel_l3_parity {
 struct i915_gem_mm {
 	/** Memory allocator for GTT stolen memory */
 	struct drm_mm stolen;
-	/** Memory allocator for GTT */
-	struct drm_mm gtt_space;
 	/** List of all objects in gtt_space. Used to restore gtt
 	 * mappings on resume */
 	struct list_head bound_list;
@@ -816,37 +916,12 @@ struct i915_gem_mm {
 	/** Usable portion of the GTT for GEM */
 	unsigned long stolen_base; /* limited to low memory (32-bit) */
 
-	int gtt_mtrr;
-
 	/** PPGTT used for aliasing the PPGTT with the GTT */
 	struct i915_hw_ppgtt *aliasing_ppgtt;
 
 	struct shrinker inactive_shrinker;
 	bool shrinker_no_lock_stealing;
 
-	/**
-	 * List of objects currently involved in rendering.
-	 *
-	 * Includes buffers having the contents of their GPU caches
-	 * flushed, not necessarily primitives.  last_rendering_seqno
-	 * represents when the rendering involved will be completed.
-	 *
-	 * A reference is held on the buffer while on this list.
-	 */
-	struct list_head active_list;
-
-	/**
-	 * LRU list of objects which are not in the ringbuffer and
-	 * are ready to unbind, but are still in the GTT.
-	 *
-	 * last_rendering_seqno is 0 while an object is in this list.
-	 *
-	 * A reference is not held on the buffer while on this list,
-	 * as merely being GTT-bound shouldn't prevent its being
-	 * freed, and we'll pull it off the list in the free path.
-	 */
-	struct list_head inactive_list;
-
 	/** LRU list of objects with fence regs on them. */
 	struct list_head fence_list;
 
@@ -865,16 +940,6 @@ struct i915_gem_mm {
 	 */
 	bool interruptible;
 
-	/**
-	 * Flag if the X Server, and thus DRM, is not currently in
-	 * control of the device.
-	 *
-	 * This is set between LeaveVT and EnterVT.  It needs to be
-	 * replaced with a semaphore.  It also needs to be
-	 * transitioned away from for kernel modesetting.
-	 */
-	int suspended;
-
 	/** Bit 6 swizzling required for X tiling */
 	uint32_t bit_6_swizzle_x;
 	/** Bit 6 swizzling required for Y tiling */
@@ -884,6 +949,7 @@ struct i915_gem_mm {
 	struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
 
 	/* accounting, useful for userland debugging */
+	spinlock_t object_stat_lock;
 	size_t object_memory;
 	u32 object_count;
 };
@@ -897,6 +963,11 @@ struct drm_i915_error_state_buf {
 	loff_t pos;
 };
 
+struct i915_error_state_file_priv {
+	struct drm_device *dev;
+	struct drm_i915_error_state *error;
+};
+
 struct i915_gpu_error {
 	/* For hangcheck timer */
 #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
@@ -988,6 +1059,19 @@ struct intel_vbt_data {
 	struct child_device_config *child_dev;
 };
 
+enum intel_ddb_partitioning {
+	INTEL_DDB_PART_1_2,
+	INTEL_DDB_PART_5_6, /* IVB+ */
+};
+
+struct intel_wm_level {
+	bool enable;
+	uint32_t pri_val;
+	uint32_t spr_val;
+	uint32_t cur_val;
+	uint32_t fbc_val;
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
@@ -998,14 +1082,7 @@ typedef struct drm_i915_private {
 
 	void __iomem *regs;
 
-	struct drm_i915_gt_funcs gt;
-	/** gt_fifo_count and the subsequent register write are synchronized
-	 * with dev->struct_mutex. */
-	unsigned gt_fifo_count;
-	/** forcewake_count is protected by gt_lock */
-	unsigned forcewake_count;
-	/** gt_lock is also taken in irq contexts. */
-	spinlock_t gt_lock;
+	struct intel_uncore uncore;
 
 	struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
 
@@ -1059,12 +1136,7 @@ typedef struct drm_i915_private {
 
 	int num_plane;
 
-	unsigned long cfb_size;
-	unsigned int cfb_fb;
-	enum plane cfb_plane;
-	int cfb_y;
-	struct intel_fbc_work *fbc_work;
-
+	struct i915_fbc fbc;
 	struct intel_opregion opregion;
 	struct intel_vbt_data vbt;
 
@@ -1081,8 +1153,6 @@ typedef struct drm_i915_private {
 	} backlight;
 
 	/* LVDS info */
-	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
-	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
 	bool no_aux_handshake;
 
 	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
@@ -1105,7 +1175,8 @@ typedef struct drm_i915_private {
 	enum modeset_restore modeset_restore;
 	struct mutex modeset_restore_lock;
 
-	struct i915_gtt gtt;
+	struct list_head vm_list; /* Global list of all address spaces */
+	struct i915_gtt gtt; /* VMA representing the global address space */
 
 	struct i915_gem_mm mm;
 
@@ -1132,6 +1203,9 @@ typedef struct drm_i915_private {
 
 	struct intel_l3_parity l3_parity;
 
+	/* Cannot be determined by PCIID. You must always read a register. */
+	size_t ellc_size;
+
 	/* gen6+ rps state */
 	struct intel_gen6_power_mgmt rps;
 
@@ -1142,10 +1216,7 @@ typedef struct drm_i915_private {
 	/* Haswell power well */
 	struct i915_power_well power_well;
 
-	enum no_fbc_reason no_fbc_reason;
-
-	struct drm_mm_node *compressed_fb;
-	struct drm_mm_node *compressed_llb;
+	enum no_psr_reason no_psr_reason;
 
 	struct i915_gpu_error gpu_error;
 
@@ -1170,11 +1241,32 @@ typedef struct drm_i915_private {
 
 	struct i915_suspend_saved_registers regfile;
 
+	struct {
+		/*
+		 * Raw watermark latency values:
+		 * in 0.1us units for WM0,
+		 * in 0.5us units for WM1+.
+		 */
+		/* primary */
+		uint16_t pri_latency[5];
+		/* sprite */
+		uint16_t spr_latency[5];
+		/* cursor */
+		uint16_t cur_latency[5];
+	} wm;
+
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
+	/* Old ums support infrastructure, same warning applies. */
+	struct i915_ums_state ums;
 } drm_i915_private_t;
 
+static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
+{
+	return dev->dev_private;
+}
+
 /* Iterate over initialised rings */
 #define for_each_ring(ring__, dev_priv__, i__) \
 	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
@@ -1187,7 +1279,7 @@ enum hdmi_force_audio {
 	HDMI_AUDIO_ON,			/* force turn on HDMI audio */
 };
 
-#define I915_GTT_RESERVED ((struct drm_mm_node *)0x1)
+#define I915_GTT_OFFSET_NONE ((u32)-1)
 
 struct drm_i915_gem_object_ops {
 	/* Interface between the GEM object and its backing storage.
@@ -1212,15 +1304,14 @@ struct drm_i915_gem_object {
 
 	const struct drm_i915_gem_object_ops *ops;
 
-	/** Current space allocated to this object in the GTT, if any. */
-	struct drm_mm_node *gtt_space;
+	/** List of VMAs backed by this object */
+	struct list_head vma_list;
+
 	/** Stolen memory for this object, instead of being backed by shmem. */
 	struct drm_mm_node *stolen;
 	struct list_head global_list;
 
-	/** This object's place on the active/inactive lists */
 	struct list_head ring_list;
-	struct list_head mm_list;
 	/** This object's place in the batchbuffer or on the eviction list */
 	struct list_head exec_list;
 
@@ -1314,13 +1405,6 @@ struct drm_i915_gem_object {
 	unsigned long exec_handle;
 	struct drm_i915_gem_exec_object2 *exec_entry;
 
-	/**
-	 * Current offset of the object in GTT space.
-	 *
-	 * This is the same as gtt_space->start
-	 */
-	uint32_t gtt_offset;
-
 	struct intel_ring_buffer *ring;
 
 	/** Breadcrumb of last rendering to the buffer. */
@@ -1396,7 +1480,7 @@ struct drm_i915_file_private {
 	struct i915_ctx_hang_stats hang_stats;
 };
 
-#define INTEL_INFO(dev)	(((struct drm_i915_private *) (dev)->dev_private)->info)
+#define INTEL_INFO(dev)	(to_i915(dev)->info)
 
 #define IS_I830(dev)		((dev)->pci_device == 0x3577)
 #define IS_845G(dev)		((dev)->pci_device == 0x2562)
@@ -1490,7 +1574,7 @@ struct drm_i915_file_private {
 #define INTEL_PCH_LPT_DEVICE_ID_TYPE		0x8c00
 #define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE		0x9c00
 
-#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
+#define INTEL_PCH_TYPE(dev) (to_i915(dev)->pch_type)
 #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
 #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
 #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
@@ -1526,7 +1610,7 @@ struct drm_i915_file_private {
 #define INTEL_RC6p_ENABLE			(1<<1)
 #define INTEL_RC6pp_ENABLE			(1<<2)
 
-extern struct drm_ioctl_desc i915_ioctls[];
+extern const struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc __always_unused;
 extern int i915_panel_ignore_lid __read_mostly;
@@ -1540,9 +1624,12 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern int i915_enable_psr __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
 extern int i915_enable_ips __read_mostly;
+extern bool i915_fastboot __read_mostly;
+extern bool i915_prefault_disable __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -1578,16 +1665,21 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
 extern void intel_console_resume(struct work_struct *work);
 
 /* i915_irq.c */
+void i915_queue_hangcheck(struct drm_device *dev);
 void i915_hangcheck_elapsed(unsigned long data);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
 extern void intel_pm_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
-extern void intel_gt_init(struct drm_device *dev);
-extern void intel_gt_sanitize(struct drm_device *dev);
+extern void intel_pm_init(struct drm_device *dev);
 
-void i915_error_state_free(struct kref *error_ref);
+extern void intel_uncore_sanitize(struct drm_device *dev);
+extern void intel_uncore_early_sanitize(struct drm_device *dev);
+extern void intel_uncore_init(struct drm_device *dev);
+extern void intel_uncore_reset(struct drm_device *dev);
+extern void intel_uncore_clear_errors(struct drm_device *dev);
+extern void intel_uncore_check_errors(struct drm_device *dev);
 
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -1595,13 +1687,6 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
-#ifdef CONFIG_DEBUG_FS
-extern void i915_destroy_error_state(struct drm_device *dev);
-#else
-#define i915_destroy_error_state(x)
-#endif
-
-
 /* i915_gem.c */
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
@@ -1658,13 +1743,18 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 						  size_t size);
 void i915_gem_free_object(struct drm_gem_object *obj);
+struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj,
+				     struct i915_address_space *vm);
+void i915_gem_vma_destroy(struct i915_vma *vma);
 
 int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
+				     struct i915_address_space *vm,
 				     uint32_t alignment,
 				     bool map_and_fenceable,
 				     bool nonblocking);
 void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
-int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj);
+int __must_check i915_vma_unbind(struct i915_vma *vma);
+int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
@@ -1701,8 +1791,6 @@ int i915_gem_dumb_create(struct drm_file *file_priv,
 			 struct drm_mode_create_dumb *args);
 int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
 		      uint32_t handle, uint64_t *offset);
-int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
-			  uint32_t handle);
 /**
  * Returns true if seq1 is later than seq2.
  */
@@ -1810,6 +1898,53 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
 
 void i915_gem_restore_fences(struct drm_device *dev);
 
+unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
+				  struct i915_address_space *vm);
+bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o);
+bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
+			struct i915_address_space *vm);
+unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o,
+				struct i915_address_space *vm);
+struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
+				     struct i915_address_space *vm);
+/* Some GGTT VM helpers */
+#define obj_to_ggtt(obj) \
+	(&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base)
+static inline bool i915_is_ggtt(struct i915_address_space *vm)
+{
+	struct i915_address_space *ggtt =
+		&((struct drm_i915_private *)(vm)->dev->dev_private)->gtt.base;
+	return vm == ggtt;
+}
+
+static inline bool i915_gem_obj_ggtt_bound(struct drm_i915_gem_object *obj)
+{
+	return i915_gem_obj_bound(obj, obj_to_ggtt(obj));
+}
+
+static inline unsigned long
+i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *obj)
+{
+	return i915_gem_obj_offset(obj, obj_to_ggtt(obj));
+}
+
+static inline unsigned long
+i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj)
+{
+	return i915_gem_obj_size(obj, obj_to_ggtt(obj));
+}
+
+static inline int __must_check
+i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
+		      uint32_t alignment,
+		      bool map_and_fenceable,
+		      bool nonblocking)
+{
+	return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment,
+				   map_and_fenceable, nonblocking);
+}
+#undef obj_to_ggtt
+
 /* i915_gem_context.c */
 void i915_gem_context_init(struct drm_device *dev);
 void i915_gem_context_fini(struct drm_device *dev);
@@ -1828,7 +1963,7 @@ static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
 }
 
 struct i915_ctx_hang_stats * __must_check
-i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+i915_gem_context_get_hang_stats(struct drm_device *dev,
 				struct drm_file *file,
 				u32 id);
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
@@ -1862,7 +1997,9 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev)
 
 
 /* i915_gem_evict.c */
-int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
+int __must_check i915_gem_evict_something(struct drm_device *dev,
+					  struct i915_address_space *vm,
+					  int min_size,
 					  unsigned alignment,
 					  unsigned cache_level,
 					  bool mappable,
@@ -1884,7 +2021,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);
 
 /* i915_gem_tiling.c */
-inline static bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
+static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
 	drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
 
@@ -1912,8 +2049,27 @@ void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
 /* i915_debugfs.c */
 int i915_debugfs_init(struct drm_minor *minor);
 void i915_debugfs_cleanup(struct drm_minor *minor);
+
+/* i915_gpu_error.c */
 __printf(2, 3)
 void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
+int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
+			    const struct i915_error_state_file_priv *error);
+int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
+			      size_t count, loff_t pos);
+static inline void i915_error_state_buf_release(
+	struct drm_i915_error_state_buf *eb)
+{
+	kfree(eb->buf);
+}
+void i915_capture_error_state(struct drm_device *dev);
+void i915_error_state_get(struct drm_device *dev,
+			  struct i915_error_state_file_priv *error_priv);
+void i915_error_state_put(struct i915_error_state_file_priv *error_priv);
+void i915_destroy_error_state(struct drm_device *dev);
+
+void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
+const char *i915_cache_level_str(int type);
 
 /* i915_suspend.c */
 extern int i915_save_state(struct drm_device *dev);
@@ -1993,7 +2149,6 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file);
 
 /* overlay */
-#ifdef CONFIG_DEBUG_FS
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
 extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
 					    struct intel_overlay_error_state *error);
@@ -2002,7 +2157,6 @@ extern struct intel_display_error_state *intel_display_capture_error_state(struc
 extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
 					    struct drm_device *dev,
 					    struct intel_display_error_state *error);
-#endif
 
 /* On SNB platform, before reading ring registers forcewake bit
  * must be set to prevent GT core from power down and stale values being
@@ -2010,7 +2164,6 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
  */
 void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
 void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
-int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
@@ -2029,39 +2182,37 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
 int vlv_gpu_freq(int ddr_freq, int val);
 int vlv_freq_opcode(int ddr_freq, int val);
 
-#define __i915_read(x, y) \
-	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
-
-__i915_read(8, b)
-__i915_read(16, w)
-__i915_read(32, l)
-__i915_read(64, q)
+#define __i915_read(x) \
+	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg, bool trace);
+__i915_read(8)
+__i915_read(16)
+__i915_read(32)
+__i915_read(64)
 #undef __i915_read
 
-#define __i915_write(x, y) \
-	void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
-
-__i915_write(8, b)
-__i915_write(16, w)
-__i915_write(32, l)
-__i915_write(64, q)
+#define __i915_write(x) \
+	void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val, bool trace);
+__i915_write(8)
+__i915_write(16)
+__i915_write(32)
+__i915_write(64)
 #undef __i915_write
 
-#define I915_READ8(reg)		i915_read8(dev_priv, (reg))
-#define I915_WRITE8(reg, val)	i915_write8(dev_priv, (reg), (val))
+#define I915_READ8(reg)		i915_read8(dev_priv, (reg), true)
+#define I915_WRITE8(reg, val)	i915_write8(dev_priv, (reg), (val), true)
 
-#define I915_READ16(reg)	i915_read16(dev_priv, (reg))
-#define I915_WRITE16(reg, val)	i915_write16(dev_priv, (reg), (val))
-#define I915_READ16_NOTRACE(reg)	readw(dev_priv->regs + (reg))
-#define I915_WRITE16_NOTRACE(reg, val)	writew(val, dev_priv->regs + (reg))
+#define I915_READ16(reg)	i915_read16(dev_priv, (reg), true)
+#define I915_WRITE16(reg, val)	i915_write16(dev_priv, (reg), (val), true)
+#define I915_READ16_NOTRACE(reg)	i915_read16(dev_priv, (reg), false)
+#define I915_WRITE16_NOTRACE(reg, val)	i915_write16(dev_priv, (reg), (val), false)
 
-#define I915_READ(reg)		i915_read32(dev_priv, (reg))
-#define I915_WRITE(reg, val)	i915_write32(dev_priv, (reg), (val))
-#define I915_READ_NOTRACE(reg)		readl(dev_priv->regs + (reg))
-#define I915_WRITE_NOTRACE(reg, val)	writel(val, dev_priv->regs + (reg))
+#define I915_READ(reg)		i915_read32(dev_priv, (reg), true)
+#define I915_WRITE(reg, val)	i915_write32(dev_priv, (reg), (val), true)
+#define I915_READ_NOTRACE(reg)		i915_read32(dev_priv, (reg), false)
+#define I915_WRITE_NOTRACE(reg, val)	i915_write32(dev_priv, (reg), (val), false)
 
-#define I915_WRITE64(reg, val)	i915_write64(dev_priv, (reg), (val))
-#define I915_READ64(reg)	i915_read64(dev_priv, (reg))
+#define I915_WRITE64(reg, val)	i915_write64(dev_priv, (reg), (val), true)
+#define I915_READ64(reg)	i915_read64(dev_priv, (reg), true)
 
 #define POSTING_READ(reg)	(void)I915_READ_NOTRACE(reg)
 #define POSTING_READ16(reg)	(void)I915_READ16_NOTRACE(reg)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d9e2208..e6ed227 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -26,6 +26,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_vma_manager.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -38,10 +39,12 @@
 
 static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
-static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
-						    unsigned alignment,
-						    bool map_and_fenceable,
-						    bool nonblocking);
+static __must_check int
+i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
+			   struct i915_address_space *vm,
+			   unsigned alignment,
+			   bool map_and_fenceable,
+			   bool nonblocking);
 static int i915_gem_phys_pwrite(struct drm_device *dev,
 				struct drm_i915_gem_object *obj,
 				struct drm_i915_gem_pwrite *args,
@@ -53,10 +56,12 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
 					 struct drm_i915_fence_reg *fence,
 					 bool enable);
 
-static int i915_gem_inactive_shrink(struct shrinker *shrinker,
-				    struct shrink_control *sc);
+static unsigned long i915_gem_inactive_count(struct shrinker *shrinker,
+					     struct shrink_control *sc);
+static unsigned long i915_gem_inactive_scan(struct shrinker *shrinker,
+					    struct shrink_control *sc);
 static long i915_gem_purge(struct drm_i915_private *dev_priv, long target);
-static void i915_gem_shrink_all(struct drm_i915_private *dev_priv);
+static long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
 static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
 
 static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj)
@@ -75,15 +80,19 @@ static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj)
 static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
 				  size_t size)
 {
+	spin_lock(&dev_priv->mm.object_stat_lock);
 	dev_priv->mm.object_count++;
 	dev_priv->mm.object_memory += size;
+	spin_unlock(&dev_priv->mm.object_stat_lock);
 }
 
 static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
 				     size_t size)
 {
+	spin_lock(&dev_priv->mm.object_stat_lock);
 	dev_priv->mm.object_count--;
 	dev_priv->mm.object_memory -= size;
+	spin_unlock(&dev_priv->mm.object_stat_lock);
 }
 
 static int
@@ -135,7 +144,7 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
 static inline bool
 i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
 {
-	return obj->gtt_space && !obj->active;
+	return i915_gem_obj_bound_any(obj) && !obj->active;
 }
 
 int
@@ -178,10 +187,10 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 	mutex_lock(&dev->struct_mutex);
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
 		if (obj->pin_count)
-			pinned += obj->gtt_space->size;
+			pinned += i915_gem_obj_ggtt_size(obj);
 	mutex_unlock(&dev->struct_mutex);
 
-	args->aper_size = dev_priv->gtt.total;
+	args->aper_size = dev_priv->gtt.base.total;
 	args->aper_available_size = args->aper_size - pinned;
 
 	return 0;
@@ -219,16 +228,10 @@ i915_gem_create(struct drm_file *file,
 		return -ENOMEM;
 
 	ret = drm_gem_handle_create(file, &obj->base, &handle);
-	if (ret) {
-		drm_gem_object_release(&obj->base);
-		i915_gem_info_remove_obj(dev->dev_private, obj->base.size);
-		i915_gem_object_free(obj);
-		return ret;
-	}
-
 	/* drop reference from allocate - handle holds it now */
-	drm_gem_object_unreference(&obj->base);
-	trace_i915_gem_object_create(obj);
+	drm_gem_object_unreference_unlocked(&obj->base);
+	if (ret)
+		return ret;
 
 	*handle_p = handle;
 	return 0;
@@ -246,13 +249,6 @@ i915_gem_dumb_create(struct drm_file *file,
 			       args->size, &args->handle);
 }
 
-int i915_gem_dumb_destroy(struct drm_file *file,
-			  struct drm_device *dev,
-			  uint32_t handle)
-{
-	return drm_gem_handle_delete(file, handle);
-}
-
 /**
  * Creates a new mm object and returns a handle to it.
  */
@@ -422,7 +418,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
 		 * anyway again before the next pread happens. */
 		if (obj->cache_level == I915_CACHE_NONE)
 			needs_clflush = 1;
-		if (obj->gtt_space) {
+		if (i915_gem_obj_bound_any(obj)) {
 			ret = i915_gem_object_set_to_gtt_domain(obj, false);
 			if (ret)
 				return ret;
@@ -465,7 +461,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
 
 		mutex_unlock(&dev->struct_mutex);
 
-		if (!prefaulted) {
+		if (likely(!i915_prefault_disable) && !prefaulted) {
 			ret = fault_in_multipages_writeable(user_data, remain);
 			/* Userspace is tricking us, but we've already clobbered
 			 * its pages with the prefault and promised to write the
@@ -594,7 +590,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
 	char __user *user_data;
 	int page_offset, page_length, ret;
 
-	ret = i915_gem_object_pin(obj, 0, true, true);
+	ret = i915_gem_obj_ggtt_pin(obj, 0, true, true);
 	if (ret)
 		goto out;
 
@@ -609,7 +605,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
 	user_data = to_user_ptr(args->data_ptr);
 	remain = args->size;
 
-	offset = obj->gtt_offset + args->offset;
+	offset = i915_gem_obj_ggtt_offset(obj) + args->offset;
 
 	while (remain > 0) {
 		/* Operation in this page
@@ -739,7 +735,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev,
 		 * right away and we therefore have to clflush anyway. */
 		if (obj->cache_level == I915_CACHE_NONE)
 			needs_clflush_after = 1;
-		if (obj->gtt_space) {
+		if (i915_gem_obj_bound_any(obj)) {
 			ret = i915_gem_object_set_to_gtt_domain(obj, true);
 			if (ret)
 				return ret;
@@ -860,10 +856,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		       args->size))
 		return -EFAULT;
 
-	ret = fault_in_multipages_readable(to_user_ptr(args->data_ptr),
-					   args->size);
-	if (ret)
-		return -EFAULT;
+	if (likely(!i915_prefault_disable)) {
+		ret = fault_in_multipages_readable(to_user_ptr(args->data_ptr),
+						   args->size);
+		if (ret)
+			return -EFAULT;
+	}
 
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
@@ -1346,7 +1344,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	}
 
 	/* Now bind it into the GTT if needed */
-	ret = i915_gem_object_pin(obj, 0, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj,  0, true, false);
 	if (ret)
 		goto unlock;
 
@@ -1360,8 +1358,9 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 	obj->fault_mappable = true;
 
-	pfn = ((dev_priv->gtt.mappable_base + obj->gtt_offset) >> PAGE_SHIFT) +
-		page_offset;
+	pfn = dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj);
+	pfn >>= PAGE_SHIFT;
+	pfn += page_offset;
 
 	/* Finally, remap it using the new GTT offset */
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
@@ -1425,11 +1424,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 	if (!obj->fault_mappable)
 		return;
 
-	if (obj->base.dev->dev_mapping)
-		unmap_mapping_range(obj->base.dev->dev_mapping,
-				    (loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT,
-				    obj->base.size, 1);
-
+	drm_vma_node_unmap(&obj->base.vma_node, obj->base.dev->dev_mapping);
 	obj->fault_mappable = false;
 }
 
@@ -1485,7 +1480,7 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
 	int ret;
 
-	if (obj->base.map_list.map)
+	if (drm_vma_node_has_offset(&obj->base.vma_node))
 		return 0;
 
 	dev_priv->mm.shrinker_no_lock_stealing = true;
@@ -1516,9 +1511,6 @@ out:
 
 static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
 {
-	if (!obj->base.map_list.map)
-		return;
-
 	drm_gem_free_mmap_offset(&obj->base);
 }
 
@@ -1557,7 +1549,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 	if (ret)
 		goto out;
 
-	*offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
+	*offset = drm_vma_node_offset_addr(&obj->base.vma_node);
 
 out:
 	drm_gem_object_unreference(&obj->base);
@@ -1667,11 +1659,11 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
 	if (obj->pages == NULL)
 		return 0;
 
-	BUG_ON(obj->gtt_space);
-
 	if (obj->pages_pin_count)
 		return -EBUSY;
 
+	BUG_ON(i915_gem_obj_bound_any(obj));
+
 	/* ->put_pages might need to allocate memory for the bit17 swizzle
 	 * array, hence protect them from being reaped by removing them from gtt
 	 * lists early. */
@@ -1704,12 +1696,18 @@ __i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
 		}
 	}
 
-	list_for_each_entry_safe(obj, next,
-				 &dev_priv->mm.inactive_list,
-				 mm_list) {
-		if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
-		    i915_gem_object_unbind(obj) == 0 &&
-		    i915_gem_object_put_pages(obj) == 0) {
+	list_for_each_entry_safe(obj, next, &dev_priv->mm.bound_list,
+				 global_list) {
+		struct i915_vma *vma, *v;
+
+		if (!i915_gem_object_is_purgeable(obj) && purgeable_only)
+			continue;
+
+		list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link)
+			if (i915_vma_unbind(vma))
+				break;
+
+		if (!i915_gem_object_put_pages(obj)) {
 			count += obj->base.size >> PAGE_SHIFT;
 			if (count >= target)
 				return count;
@@ -1725,16 +1723,21 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target)
 	return __i915_gem_shrink(dev_priv, target, true);
 }
 
-static void
+static long
 i915_gem_shrink_all(struct drm_i915_private *dev_priv)
 {
 	struct drm_i915_gem_object *obj, *next;
+	long freed = 0;
 
 	i915_gem_evict_everything(dev_priv->dev);
 
 	list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
-				 global_list)
+				 global_list) {
+		if (obj->pages_pin_count == 0)
+			freed += obj->base.size >> PAGE_SHIFT;
 		i915_gem_object_put_pages(obj);
+	}
+	return freed;
 }
 
 static int
@@ -1892,8 +1895,6 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
 		obj->active = 1;
 	}
 
-	/* Move from whatever list we were on to the tail of execution. */
-	list_move_tail(&obj->mm_list, &dev_priv->mm.active_list);
 	list_move_tail(&obj->ring_list, &ring->active_list);
 
 	obj->last_read_seqno = seqno;
@@ -1915,13 +1916,14 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
 static void
 i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
+	struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm);
 
 	BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
 	BUG_ON(!obj->active);
 
-	list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+	list_move_tail(&vma->mm_list, &ggtt_vm->inactive_list);
 
 	list_del_init(&obj->ring_list);
 	obj->ring = NULL;
@@ -2085,11 +2087,9 @@ int __i915_add_request(struct intel_ring_buffer *ring,
 	trace_i915_gem_request_add(ring, request->seqno);
 	ring->outstanding_lazy_request = 0;
 
-	if (!dev_priv->mm.suspended) {
-		if (i915_enable_hangcheck) {
-			mod_timer(&dev_priv->gpu_error.hangcheck_timer,
-				  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
-		}
+	if (!dev_priv->ums.mm_suspended) {
+		i915_queue_hangcheck(ring->dev);
+
 		if (was_empty) {
 			queue_delayed_work(dev_priv->wq,
 					   &dev_priv->mm.retire_work,
@@ -2119,10 +2119,11 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
 	spin_unlock(&file_priv->mm.lock);
 }
 
-static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
+static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj,
+				    struct i915_address_space *vm)
 {
-	if (acthd >= obj->gtt_offset &&
-	    acthd < obj->gtt_offset + obj->base.size)
+	if (acthd >= i915_gem_obj_offset(obj, vm) &&
+	    acthd < i915_gem_obj_offset(obj, vm) + obj->base.size)
 		return true;
 
 	return false;
@@ -2145,6 +2146,17 @@ static bool i915_head_inside_request(const u32 acthd_unmasked,
 	return false;
 }
 
+static struct i915_address_space *
+request_to_vm(struct drm_i915_gem_request *request)
+{
+	struct drm_i915_private *dev_priv = request->ring->dev->dev_private;
+	struct i915_address_space *vm;
+
+	vm = &dev_priv->gtt.base;
+
+	return vm;
+}
+
 static bool i915_request_guilty(struct drm_i915_gem_request *request,
 				const u32 acthd, bool *inside)
 {
@@ -2152,9 +2164,9 @@ static bool i915_request_guilty(struct drm_i915_gem_request *request,
 	 * pointing inside the ring, matches the batch_obj address range.
 	 * However this is extremely unlikely.
 	 */
-
 	if (request->batch_obj) {
-		if (i915_head_inside_object(acthd, request->batch_obj)) {
+		if (i915_head_inside_object(acthd, request->batch_obj,
+					    request_to_vm(request))) {
 			*inside = true;
 			return true;
 		}
@@ -2174,17 +2186,21 @@ static void i915_set_reset_status(struct intel_ring_buffer *ring,
 {
 	struct i915_ctx_hang_stats *hs = NULL;
 	bool inside, guilty;
+	unsigned long offset = 0;
 
 	/* Innocent until proven guilty */
 	guilty = false;
 
+	if (request->batch_obj)
+		offset = i915_gem_obj_offset(request->batch_obj,
+					     request_to_vm(request));
+
 	if (ring->hangcheck.action != wait &&
 	    i915_request_guilty(request, acthd, &inside)) {
-		DRM_ERROR("%s hung %s bo (0x%x ctx %d) at 0x%x\n",
+		DRM_ERROR("%s hung %s bo (0x%lx ctx %d) at 0x%x\n",
 			  ring->name,
 			  inside ? "inside" : "flushing",
-			  request->batch_obj ?
-			  request->batch_obj->gtt_offset : 0,
+			  offset,
 			  request->ctx ? request->ctx->id : 0,
 			  acthd);
 
@@ -2275,23 +2291,12 @@ void i915_gem_restore_fences(struct drm_device *dev)
 void i915_gem_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj;
 	struct intel_ring_buffer *ring;
 	int i;
 
 	for_each_ring(ring, dev_priv, i)
 		i915_gem_reset_ring_lists(dev_priv, ring);
 
-	/* Move everything out of the GPU domains to ensure we do any
-	 * necessary invalidation upon reuse.
-	 */
-	list_for_each_entry(obj,
-			    &dev_priv->mm.inactive_list,
-			    mm_list)
-	{
-		obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
-	}
-
 	i915_gem_restore_fences(dev);
 }
 
@@ -2400,7 +2405,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
 		idle &= list_empty(&ring->request_list);
 	}
 
-	if (!dev_priv->mm.suspended && !idle)
+	if (!dev_priv->ums.mm_suspended && !idle)
 		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work,
 				   round_jiffies_up_relative(HZ));
 	if (idle)
@@ -2586,16 +2591,13 @@ static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
 					    old_write_domain);
 }
 
-/**
- * Unbinds an object from the GTT aperture.
- */
-int
-i915_gem_object_unbind(struct drm_i915_gem_object *obj)
+int i915_vma_unbind(struct i915_vma *vma)
 {
+	struct drm_i915_gem_object *obj = vma->obj;
 	drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
 	int ret;
 
-	if (obj->gtt_space == NULL)
+	if (list_empty(&vma->vma_link))
 		return 0;
 
 	if (obj->pin_count)
@@ -2618,7 +2620,7 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	if (ret)
 		return ret;
 
-	trace_i915_gem_object_unbind(obj);
+	trace_i915_vma_unbind(vma);
 
 	if (obj->has_global_gtt_mapping)
 		i915_gem_gtt_unbind_object(obj);
@@ -2629,18 +2631,44 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	i915_gem_gtt_finish_object(obj);
 	i915_gem_object_unpin_pages(obj);
 
-	list_del(&obj->mm_list);
-	list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
+	list_del(&vma->mm_list);
 	/* Avoid an unnecessary call to unbind on rebind. */
-	obj->map_and_fenceable = true;
+	if (i915_is_ggtt(vma->vm))
+		obj->map_and_fenceable = true;
 
-	drm_mm_put_block(obj->gtt_space);
-	obj->gtt_space = NULL;
-	obj->gtt_offset = 0;
+	drm_mm_remove_node(&vma->node);
+	i915_gem_vma_destroy(vma);
+
+	/* Since the unbound list is global, only move to that list if
+	 * no more VMAs exist.
+	 * NB: Until we have real VMAs there will only ever be one */
+	WARN_ON(!list_empty(&obj->vma_list));
+	if (list_empty(&obj->vma_list))
+		list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
 
 	return 0;
 }
 
+/**
+ * Unbinds an object from the global GTT aperture.
+ */
+int
+i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	struct i915_address_space *ggtt = &dev_priv->gtt.base;
+
+	if (!i915_gem_obj_ggtt_bound(obj));
+		return 0;
+
+	if (obj->pin_count)
+		return -EBUSY;
+
+	BUG_ON(obj->pages == NULL);
+
+	return i915_vma_unbind(i915_gem_obj_to_vma(obj, ggtt));
+}
+
 int i915_gpu_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -2691,12 +2719,12 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
 	POSTING_READ(fence_reg);
 
 	if (obj) {
-		u32 size = obj->gtt_space->size;
+		u32 size = i915_gem_obj_ggtt_size(obj);
 		uint64_t val;
 
-		val = (uint64_t)((obj->gtt_offset + size - 4096) &
+		val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) &
 				 0xfffff000) << 32;
-		val |= obj->gtt_offset & 0xfffff000;
+		val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000;
 		val |= (uint64_t)((obj->stride / 128) - 1) << fence_pitch_shift;
 		if (obj->tiling_mode == I915_TILING_Y)
 			val |= 1 << I965_FENCE_TILING_Y_SHIFT;
@@ -2720,15 +2748,15 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
 	u32 val;
 
 	if (obj) {
-		u32 size = obj->gtt_space->size;
+		u32 size = i915_gem_obj_ggtt_size(obj);
 		int pitch_val;
 		int tile_width;
 
-		WARN((obj->gtt_offset & ~I915_FENCE_START_MASK) ||
+		WARN((i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK) ||
 		     (size & -size) != size ||
-		     (obj->gtt_offset & (size - 1)),
-		     "object 0x%08x [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
-		     obj->gtt_offset, obj->map_and_fenceable, size);
+		     (i915_gem_obj_ggtt_offset(obj) & (size - 1)),
+		     "object 0x%08lx [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
+		     i915_gem_obj_ggtt_offset(obj), obj->map_and_fenceable, size);
 
 		if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
 			tile_width = 128;
@@ -2739,7 +2767,7 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
 		pitch_val = obj->stride / tile_width;
 		pitch_val = ffs(pitch_val) - 1;
 
-		val = obj->gtt_offset;
+		val = i915_gem_obj_ggtt_offset(obj);
 		if (obj->tiling_mode == I915_TILING_Y)
 			val |= 1 << I830_FENCE_TILING_Y_SHIFT;
 		val |= I915_FENCE_SIZE_BITS(size);
@@ -2764,19 +2792,19 @@ static void i830_write_fence_reg(struct drm_device *dev, int reg,
 	uint32_t val;
 
 	if (obj) {
-		u32 size = obj->gtt_space->size;
+		u32 size = i915_gem_obj_ggtt_size(obj);
 		uint32_t pitch_val;
 
-		WARN((obj->gtt_offset & ~I830_FENCE_START_MASK) ||
+		WARN((i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK) ||
 		     (size & -size) != size ||
-		     (obj->gtt_offset & (size - 1)),
-		     "object 0x%08x not 512K or pot-size 0x%08x aligned\n",
-		     obj->gtt_offset, size);
+		     (i915_gem_obj_ggtt_offset(obj) & (size - 1)),
+		     "object 0x%08lx not 512K or pot-size 0x%08x aligned\n",
+		     i915_gem_obj_ggtt_offset(obj), size);
 
 		pitch_val = obj->stride / 128;
 		pitch_val = ffs(pitch_val) - 1;
 
-		val = obj->gtt_offset;
+		val = i915_gem_obj_ggtt_offset(obj);
 		if (obj->tiling_mode == I915_TILING_Y)
 			val |= 1 << I830_FENCE_TILING_Y_SHIFT;
 		val |= I830_FENCE_SIZE_BITS(size);
@@ -2997,7 +3025,7 @@ static bool i915_gem_valid_gtt_space(struct drm_device *dev,
 	if (HAS_LLC(dev))
 		return true;
 
-	if (gtt_space == NULL)
+	if (!drm_mm_node_allocated(gtt_space))
 		return true;
 
 	if (list_empty(&gtt_space->node_list))
@@ -3030,8 +3058,8 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
 
 		if (obj->cache_level != obj->gtt_space->color) {
 			printk(KERN_ERR "object reserved space [%08lx, %08lx] with wrong color, cache_level=%x, color=%lx\n",
-			       obj->gtt_space->start,
-			       obj->gtt_space->start + obj->gtt_space->size,
+			       i915_gem_obj_ggtt_offset(obj),
+			       i915_gem_obj_ggtt_offset(obj) + i915_gem_obj_ggtt_size(obj),
 			       obj->cache_level,
 			       obj->gtt_space->color);
 			err++;
@@ -3042,8 +3070,8 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
 					      obj->gtt_space,
 					      obj->cache_level)) {
 			printk(KERN_ERR "invalid GTT space found at [%08lx, %08lx] - color=%x\n",
-			       obj->gtt_space->start,
-			       obj->gtt_space->start + obj->gtt_space->size,
+			       i915_gem_obj_ggtt_offset(obj),
+			       i915_gem_obj_ggtt_offset(obj) + i915_gem_obj_ggtt_size(obj),
 			       obj->cache_level);
 			err++;
 			continue;
@@ -3058,20 +3086,24 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
  * Finds free space in the GTT aperture and binds the object there.
  */
 static int
-i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
-			    unsigned alignment,
-			    bool map_and_fenceable,
-			    bool nonblocking)
+i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
+			   struct i915_address_space *vm,
+			   unsigned alignment,
+			   bool map_and_fenceable,
+			   bool nonblocking)
 {
 	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_mm_node *node;
 	u32 size, fence_size, fence_alignment, unfenced_alignment;
 	bool mappable, fenceable;
-	size_t gtt_max = map_and_fenceable ?
-		dev_priv->gtt.mappable_end : dev_priv->gtt.total;
+	size_t gtt_max =
+		map_and_fenceable ? dev_priv->gtt.mappable_end : vm->total;
+	struct i915_vma *vma;
 	int ret;
 
+	if (WARN_ON(!list_empty(&obj->vma_list)))
+		return -EBUSY;
+
 	fence_size = i915_gem_get_gtt_size(dev,
 					   obj->base.size,
 					   obj->tiling_mode);
@@ -3110,59 +3142,68 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 
 	i915_gem_object_pin_pages(obj);
 
-	node = kzalloc(sizeof(*node), GFP_KERNEL);
-	if (node == NULL) {
-		i915_gem_object_unpin_pages(obj);
-		return -ENOMEM;
+	/* FIXME: For now we only ever use 1 VMA per object */
+	BUG_ON(!i915_is_ggtt(vm));
+	WARN_ON(!list_empty(&obj->vma_list));
+
+	vma = i915_gem_vma_create(obj, vm);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
+		goto err_unpin;
 	}
 
 search_free:
-	ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
+	ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
 						  size, alignment,
-						  obj->cache_level, 0, gtt_max);
+						  obj->cache_level, 0, gtt_max,
+						  DRM_MM_SEARCH_DEFAULT);
 	if (ret) {
-		ret = i915_gem_evict_something(dev, size, alignment,
+		ret = i915_gem_evict_something(dev, vm, size, alignment,
 					       obj->cache_level,
 					       map_and_fenceable,
 					       nonblocking);
 		if (ret == 0)
 			goto search_free;
 
-		i915_gem_object_unpin_pages(obj);
-		kfree(node);
-		return ret;
+		goto err_free_vma;
 	}
-	if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) {
-		i915_gem_object_unpin_pages(obj);
-		drm_mm_put_block(node);
-		return -EINVAL;
+	if (WARN_ON(!i915_gem_valid_gtt_space(dev, &vma->node,
+					      obj->cache_level))) {
+		ret = -EINVAL;
+		goto err_remove_node;
 	}
 
 	ret = i915_gem_gtt_prepare_object(obj);
-	if (ret) {
-		i915_gem_object_unpin_pages(obj);
-		drm_mm_put_block(node);
-		return ret;
-	}
+	if (ret)
+		goto err_remove_node;
 
 	list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
-	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
-
-	obj->gtt_space = node;
-	obj->gtt_offset = node->start;
+	list_add_tail(&vma->mm_list, &vm->inactive_list);
 
 	fenceable =
-		node->size == fence_size &&
-		(node->start & (fence_alignment - 1)) == 0;
+		i915_is_ggtt(vm) &&
+		i915_gem_obj_ggtt_size(obj) == fence_size &&
+		(i915_gem_obj_ggtt_offset(obj) & (fence_alignment - 1)) == 0;
 
 	mappable =
-		obj->gtt_offset + obj->base.size <= dev_priv->gtt.mappable_end;
+		i915_is_ggtt(vm) &&
+		vma->node.start + obj->base.size <= dev_priv->gtt.mappable_end;
 
-	obj->map_and_fenceable = mappable && fenceable;
+	/* Map and fenceable only changes if the VM is the global GGTT */
+	if (i915_is_ggtt(vm))
+		obj->map_and_fenceable = mappable && fenceable;
 
-	trace_i915_gem_object_bind(obj, map_and_fenceable);
+	trace_i915_vma_bind(vma, map_and_fenceable);
 	i915_gem_verify_gtt(dev);
 	return 0;
+
+err_remove_node:
+	drm_mm_remove_node(&vma->node);
+err_free_vma:
+	i915_gem_vma_destroy(vma);
+err_unpin:
+	i915_gem_object_unpin_pages(obj);
+	return ret;
 }
 
 void
@@ -3258,7 +3299,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 	int ret;
 
 	/* Not valid to be called on unbound objects. */
-	if (obj->gtt_space == NULL)
+	if (!i915_gem_obj_bound_any(obj))
 		return -EINVAL;
 
 	if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
@@ -3296,8 +3337,14 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 					    old_write_domain);
 
 	/* And bump the LRU for this access */
-	if (i915_gem_object_is_inactive(obj))
-		list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+	if (i915_gem_object_is_inactive(obj)) {
+		struct i915_vma *vma = i915_gem_obj_to_vma(obj,
+							   &dev_priv->gtt.base);
+		if (vma)
+			list_move_tail(&vma->mm_list,
+				       &dev_priv->gtt.base.inactive_list);
+
+	}
 
 	return 0;
 }
@@ -3307,6 +3354,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 {
 	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct i915_vma *vma;
 	int ret;
 
 	if (obj->cache_level == cache_level)
@@ -3317,13 +3365,17 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 		return -EBUSY;
 	}
 
-	if (!i915_gem_valid_gtt_space(dev, obj->gtt_space, cache_level)) {
-		ret = i915_gem_object_unbind(obj);
-		if (ret)
-			return ret;
+	list_for_each_entry(vma, &obj->vma_list, vma_link) {
+		if (!i915_gem_valid_gtt_space(dev, &vma->node, cache_level)) {
+			ret = i915_vma_unbind(vma);
+			if (ret)
+				return ret;
+
+			break;
+		}
 	}
 
-	if (obj->gtt_space) {
+	if (i915_gem_obj_bound_any(obj)) {
 		ret = i915_gem_object_finish_gpu(obj);
 		if (ret)
 			return ret;
@@ -3345,8 +3397,6 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 		if (obj->has_aliasing_ppgtt_mapping)
 			i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
 					       obj, cache_level);
-
-		obj->gtt_space->color = cache_level;
 	}
 
 	if (cache_level == I915_CACHE_NONE) {
@@ -3372,6 +3422,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 						    old_write_domain);
 	}
 
+	list_for_each_entry(vma, &obj->vma_list, vma_link)
+		vma->node.color = cache_level;
 	obj->cache_level = cache_level;
 	i915_gem_verify_gtt(dev);
 	return 0;
@@ -3475,7 +3527,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	 * (e.g. libkms for the bootup splash), we have to ensure that we
 	 * always use map_and_fenceable for all scanout buffers.
 	 */
-	ret = i915_gem_object_pin(obj, alignment, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, alignment, true, false);
 	if (ret)
 		return ret;
 
@@ -3618,37 +3670,44 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
 
 int
 i915_gem_object_pin(struct drm_i915_gem_object *obj,
+		    struct i915_address_space *vm,
 		    uint32_t alignment,
 		    bool map_and_fenceable,
 		    bool nonblocking)
 {
+	struct i915_vma *vma;
 	int ret;
 
 	if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
 		return -EBUSY;
 
-	if (obj->gtt_space != NULL) {
-		if ((alignment && obj->gtt_offset & (alignment - 1)) ||
+	WARN_ON(map_and_fenceable && !i915_is_ggtt(vm));
+
+	vma = i915_gem_obj_to_vma(obj, vm);
+
+	if (vma) {
+		if ((alignment &&
+		     vma->node.start & (alignment - 1)) ||
 		    (map_and_fenceable && !obj->map_and_fenceable)) {
 			WARN(obj->pin_count,
 			     "bo is already pinned with incorrect alignment:"
-			     " offset=%x, req.alignment=%x, req.map_and_fenceable=%d,"
+			     " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
 			     " obj->map_and_fenceable=%d\n",
-			     obj->gtt_offset, alignment,
+			     i915_gem_obj_offset(obj, vm), alignment,
 			     map_and_fenceable,
 			     obj->map_and_fenceable);
-			ret = i915_gem_object_unbind(obj);
+			ret = i915_vma_unbind(vma);
 			if (ret)
 				return ret;
 		}
 	}
 
-	if (obj->gtt_space == NULL) {
+	if (!i915_gem_obj_bound(obj, vm)) {
 		struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
 
-		ret = i915_gem_object_bind_to_gtt(obj, alignment,
-						  map_and_fenceable,
-						  nonblocking);
+		ret = i915_gem_object_bind_to_vm(obj, vm, alignment,
+						 map_and_fenceable,
+						 nonblocking);
 		if (ret)
 			return ret;
 
@@ -3669,7 +3728,7 @@ void
 i915_gem_object_unpin(struct drm_i915_gem_object *obj)
 {
 	BUG_ON(obj->pin_count == 0);
-	BUG_ON(obj->gtt_space == NULL);
+	BUG_ON(!i915_gem_obj_bound_any(obj));
 
 	if (--obj->pin_count == 0)
 		obj->pin_mappable = false;
@@ -3707,7 +3766,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 	}
 
 	if (obj->user_pin_count == 0) {
-		ret = i915_gem_object_pin(obj, args->alignment, true, false);
+		ret = i915_gem_obj_ggtt_pin(obj, args->alignment, true, false);
 		if (ret)
 			goto out;
 	}
@@ -3719,7 +3778,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 	 * as the X server doesn't manage domains yet
 	 */
 	i915_gem_object_flush_cpu_write_domain(obj);
-	args->offset = obj->gtt_offset;
+	args->offset = i915_gem_obj_ggtt_offset(obj);
 out:
 	drm_gem_object_unreference(&obj->base);
 unlock:
@@ -3858,10 +3917,10 @@ unlock:
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			  const struct drm_i915_gem_object_ops *ops)
 {
-	INIT_LIST_HEAD(&obj->mm_list);
 	INIT_LIST_HEAD(&obj->global_list);
 	INIT_LIST_HEAD(&obj->ring_list);
 	INIT_LIST_HEAD(&obj->exec_list);
+	INIT_LIST_HEAD(&obj->vma_list);
 
 	obj->ops = ops;
 
@@ -3926,6 +3985,8 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 	} else
 		obj->cache_level = I915_CACHE_NONE;
 
+	trace_i915_gem_object_create(obj);
+
 	return obj;
 }
 
@@ -3941,6 +4002,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
 	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct i915_vma *vma, *next;
 
 	trace_i915_gem_object_destroy(obj);
 
@@ -3948,15 +4010,21 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 		i915_gem_detach_phys_object(dev, obj);
 
 	obj->pin_count = 0;
-	if (WARN_ON(i915_gem_object_unbind(obj) == -ERESTARTSYS)) {
-		bool was_interruptible;
+	/* NB: 0 or 1 elements */
+	WARN_ON(!list_empty(&obj->vma_list) &&
+		!list_is_singular(&obj->vma_list));
+	list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) {
+		int ret = i915_vma_unbind(vma);
+		if (WARN_ON(ret == -ERESTARTSYS)) {
+			bool was_interruptible;
 
-		was_interruptible = dev_priv->mm.interruptible;
-		dev_priv->mm.interruptible = false;
+			was_interruptible = dev_priv->mm.interruptible;
+			dev_priv->mm.interruptible = false;
 
-		WARN_ON(i915_gem_object_unbind(obj));
+			WARN_ON(i915_vma_unbind(vma));
 
-		dev_priv->mm.interruptible = was_interruptible;
+			dev_priv->mm.interruptible = was_interruptible;
+		}
 	}
 
 	/* Stolen objects don't hold a ref, but do hold pin count. Fix that up
@@ -3982,15 +4050,41 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	i915_gem_object_free(obj);
 }
 
+struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj,
+				     struct i915_address_space *vm)
+{
+	struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
+	if (vma == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&vma->vma_link);
+	INIT_LIST_HEAD(&vma->mm_list);
+	vma->vm = vm;
+	vma->obj = obj;
+
+	/* Keep GGTT vmas first to make debug easier */
+	if (i915_is_ggtt(vm))
+		list_add(&vma->vma_link, &obj->vma_list);
+	else
+		list_add_tail(&vma->vma_link, &obj->vma_list);
+
+	return vma;
+}
+
+void i915_gem_vma_destroy(struct i915_vma *vma)
+{
+	WARN_ON(vma->node.allocated);
+	list_del(&vma->vma_link);
+	kfree(vma);
+}
+
 int
 i915_gem_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
 
-	mutex_lock(&dev->struct_mutex);
-
-	if (dev_priv->mm.suspended) {
+	if (dev_priv->ums.mm_suspended) {
 		mutex_unlock(&dev->struct_mutex);
 		return 0;
 	}
@@ -4006,18 +4100,11 @@ i915_gem_idle(struct drm_device *dev)
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_gem_evict_everything(dev);
 
-	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
-	 * We need to replace this with a semaphore, or something.
-	 * And not confound mm.suspended!
-	 */
-	dev_priv->mm.suspended = 1;
 	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
 
 	i915_kernel_lost_context(dev);
 	i915_gem_cleanup_ringbuffer(dev);
 
-	mutex_unlock(&dev->struct_mutex);
-
 	/* Cancel the retire work handler, which should be idle now. */
 	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
 
@@ -4150,8 +4237,8 @@ i915_gem_init_hw(struct drm_device *dev)
 	if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
 		return -EIO;
 
-	if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
-		I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
+	if (dev_priv->ellc_size)
+		I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
 
 	if (HAS_PCH_NOP(dev)) {
 		u32 temp = I915_READ(GEN7_MSG_CTL);
@@ -4227,7 +4314,7 @@ int
 i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
@@ -4239,7 +4326,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	dev_priv->mm.suspended = 0;
+	dev_priv->ums.mm_suspended = 0;
 
 	ret = i915_gem_init_hw(dev);
 	if (ret != 0) {
@@ -4247,7 +4334,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 		return ret;
 	}
 
-	BUG_ON(!list_empty(&dev_priv->mm.active_list));
+	BUG_ON(!list_empty(&dev_priv->gtt.base.active_list));
 	mutex_unlock(&dev->struct_mutex);
 
 	ret = drm_irq_install(dev);
@@ -4259,7 +4346,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 cleanup_ringbuffer:
 	mutex_lock(&dev->struct_mutex);
 	i915_gem_cleanup_ringbuffer(dev);
-	dev_priv->mm.suspended = 1;
+	dev_priv->ums.mm_suspended = 1;
 	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
@@ -4269,11 +4356,26 @@ int
 i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return 0;
 
 	drm_irq_uninstall(dev);
-	return i915_gem_idle(dev);
+
+	mutex_lock(&dev->struct_mutex);
+	ret =  i915_gem_idle(dev);
+
+	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
+	 * We need to replace this with a semaphore, or something.
+	 * And not confound ums.mm_suspended!
+	 */
+	if (ret != 0)
+		dev_priv->ums.mm_suspended = 1;
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
 }
 
 void
@@ -4284,9 +4386,11 @@ i915_gem_lastclose(struct drm_device *dev)
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
+	mutex_lock(&dev->struct_mutex);
 	ret = i915_gem_idle(dev);
 	if (ret)
 		DRM_ERROR("failed to idle hardware: %d\n", ret);
+	mutex_unlock(&dev->struct_mutex);
 }
 
 static void
@@ -4296,6 +4400,16 @@ init_ring_lists(struct intel_ring_buffer *ring)
 	INIT_LIST_HEAD(&ring->request_list);
 }
 
+static void i915_init_vm(struct drm_i915_private *dev_priv,
+			 struct i915_address_space *vm)
+{
+	vm->dev = dev_priv->dev;
+	INIT_LIST_HEAD(&vm->active_list);
+	INIT_LIST_HEAD(&vm->inactive_list);
+	INIT_LIST_HEAD(&vm->global_link);
+	list_add(&vm->global_link, &dev_priv->vm_list);
+}
+
 void
 i915_gem_load(struct drm_device *dev)
 {
@@ -4308,8 +4422,9 @@ i915_gem_load(struct drm_device *dev)
 				  SLAB_HWCACHE_ALIGN,
 				  NULL);
 
-	INIT_LIST_HEAD(&dev_priv->mm.active_list);
-	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
+	INIT_LIST_HEAD(&dev_priv->vm_list);
+	i915_init_vm(dev_priv, &dev_priv->gtt.base);
+
 	INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.bound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
@@ -4349,7 +4464,8 @@ i915_gem_load(struct drm_device *dev)
 
 	dev_priv->mm.interruptible = true;
 
-	dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink;
+	dev_priv->mm.inactive_shrinker.scan_objects = i915_gem_inactive_scan;
+	dev_priv->mm.inactive_shrinker.count_objects = i915_gem_inactive_count;
 	dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS;
 	register_shrinker(&dev_priv->mm.inactive_shrinker);
 }
@@ -4572,8 +4688,8 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
 #endif
 }
 
-static int
-i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
+static unsigned long
+i915_gem_inactive_count(struct shrinker *shrinker, struct shrink_control *sc)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(shrinker,
@@ -4581,9 +4697,120 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
 			     mm.inactive_shrinker);
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_i915_gem_object *obj;
+	bool unlock = true;
+	unsigned long count;
+
+	if (!mutex_trylock(&dev->struct_mutex)) {
+		if (!mutex_is_locked_by(&dev->struct_mutex, current))
+			return SHRINK_STOP;
+
+		if (dev_priv->mm.shrinker_no_lock_stealing)
+			return SHRINK_STOP;
+
+		unlock = false;
+	}
+
+	count = 0;
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
+		if (obj->pages_pin_count == 0)
+			count += obj->base.size >> PAGE_SHIFT;
+
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+		if (obj->active)
+			continue;
+
+		if (obj->pin_count == 0 && obj->pages_pin_count == 0)
+			count += obj->base.size >> PAGE_SHIFT;
+	}
+
+	if (unlock)
+		mutex_unlock(&dev->struct_mutex);
+	return count;
+}
+
+/* All the new VM stuff */
+unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
+				  struct i915_address_space *vm)
+{
+	struct drm_i915_private *dev_priv = o->base.dev->dev_private;
+	struct i915_vma *vma;
+
+	if (vm == &dev_priv->mm.aliasing_ppgtt->base)
+		vm = &dev_priv->gtt.base;
+
+	BUG_ON(list_empty(&o->vma_list));
+	list_for_each_entry(vma, &o->vma_list, vma_link) {
+		if (vma->vm == vm)
+			return vma->node.start;
+
+	}
+	return -1;
+}
+
+bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
+			struct i915_address_space *vm)
+{
+	struct i915_vma *vma;
+
+	list_for_each_entry(vma, &o->vma_list, vma_link)
+		if (vma->vm == vm && drm_mm_node_allocated(&vma->node))
+			return true;
+
+	return false;
+}
+
+bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o)
+{
+	struct drm_i915_private *dev_priv = o->base.dev->dev_private;
+	struct i915_address_space *vm;
+
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+		if (i915_gem_obj_bound(o, vm))
+			return true;
+
+	return false;
+}
+
+unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o,
+				struct i915_address_space *vm)
+{
+	struct drm_i915_private *dev_priv = o->base.dev->dev_private;
+	struct i915_vma *vma;
+
+	if (vm == &dev_priv->mm.aliasing_ppgtt->base)
+		vm = &dev_priv->gtt.base;
+
+	BUG_ON(list_empty(&o->vma_list));
+
+	list_for_each_entry(vma, &o->vma_list, vma_link)
+		if (vma->vm == vm)
+			return vma->node.size;
+
+	return 0;
+}
+
+struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
+				     struct i915_address_space *vm)
+{
+	struct i915_vma *vma;
+	list_for_each_entry(vma, &obj->vma_list, vma_link)
+		if (vma->vm == vm)
+			return vma;
+
+	return NULL;
+}
+
+static unsigned long
+i915_gem_inactive_scan(struct shrinker *shrinker, struct shrink_control *sc)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(shrinker,
+			     struct drm_i915_private,
+			     mm.inactive_shrinker);
+	struct drm_device *dev = dev_priv->dev;
 	int nr_to_scan = sc->nr_to_scan;
+	unsigned long freed;
 	bool unlock = true;
-	int cnt;
 
 	if (!mutex_trylock(&dev->struct_mutex)) {
 		if (!mutex_is_locked_by(&dev->struct_mutex, current))
@@ -4595,24 +4822,14 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
 		unlock = false;
 	}
 
-	if (nr_to_scan) {
-		nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);
-		if (nr_to_scan > 0)
-			nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan,
+	freed = i915_gem_purge(dev_priv, nr_to_scan);
+	if (freed < nr_to_scan)
+		freed += __i915_gem_shrink(dev_priv, nr_to_scan,
 							false);
-		if (nr_to_scan > 0)
-			i915_gem_shrink_all(dev_priv);
-	}
-
-	cnt = 0;
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
-		if (obj->pages_pin_count == 0)
-			cnt += obj->base.size >> PAGE_SHIFT;
-	list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list)
-		if (obj->pin_count == 0 && obj->pages_pin_count == 0)
-			cnt += obj->base.size >> PAGE_SHIFT;
+	if (freed < nr_to_scan)
+		freed += i915_gem_shrink_all(dev_priv);
 
 	if (unlock)
 		mutex_unlock(&dev->struct_mutex);
-	return cnt;
+	return freed;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 51b7a21..403309c 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -155,7 +155,7 @@ create_hw_context(struct drm_device *dev,
 
 	if (INTEL_INFO(dev)->gen >= 7) {
 		ret = i915_gem_object_set_cache_level(ctx->obj,
-						      I915_CACHE_LLC_MLC);
+						      I915_CACHE_L3_LLC);
 		/* Failure shouldn't ever happen this early */
 		if (WARN_ON(ret))
 			goto err_out;
@@ -214,7 +214,7 @@ static int create_default_context(struct drm_i915_private *dev_priv)
 	 * default context.
 	 */
 	dev_priv->ring[RCS].default_context = ctx;
-	ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false, false);
+	ret = i915_gem_obj_ggtt_pin(ctx->obj, CONTEXT_ALIGN, false, false);
 	if (ret) {
 		DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
 		goto err_destroy;
@@ -304,31 +304,24 @@ static int context_idr_cleanup(int id, void *p, void *data)
 }
 
 struct i915_ctx_hang_stats *
-i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+i915_gem_context_get_hang_stats(struct drm_device *dev,
 				struct drm_file *file,
 				u32 id)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_file_private *file_priv = file->driver_priv;
-	struct i915_hw_context *to;
-
-	if (dev_priv->hw_contexts_disabled)
-		return ERR_PTR(-ENOENT);
-
-	if (ring->id != RCS)
-		return ERR_PTR(-EINVAL);
-
-	if (file == NULL)
-		return ERR_PTR(-EINVAL);
+	struct i915_hw_context *ctx;
 
 	if (id == DEFAULT_CONTEXT_ID)
 		return &file_priv->hang_stats;
 
-	to = i915_gem_context_get(file->driver_priv, id);
-	if (to == NULL)
+	ctx = NULL;
+	if (!dev_priv->hw_contexts_disabled)
+		ctx = i915_gem_context_get(file->driver_priv, id);
+	if (ctx == NULL)
 		return ERR_PTR(-ENOENT);
 
-	return &to->hang_stats;
+	return &ctx->hang_stats;
 }
 
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
@@ -377,7 +370,7 @@ mi_set_context(struct intel_ring_buffer *ring,
 
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_emit(ring, MI_SET_CONTEXT);
-	intel_ring_emit(ring, new_context->obj->gtt_offset |
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->obj) |
 			MI_MM_SPACE_GTT |
 			MI_SAVE_EXT_STATE_EN |
 			MI_RESTORE_EXT_STATE_EN |
@@ -407,7 +400,7 @@ static int do_switch(struct i915_hw_context *to)
 	if (from == to)
 		return 0;
 
-	ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false);
+	ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false);
 	if (ret)
 		return ret;
 
@@ -443,7 +436,10 @@ static int do_switch(struct i915_hw_context *to)
 	 * MI_SET_CONTEXT instead of when the next seqno has completed.
 	 */
 	if (from != NULL) {
+		struct drm_i915_private *dev_priv = from->obj->base.dev->dev_private;
+		struct i915_address_space *ggtt = &dev_priv->gtt.base;
 		from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+		list_move_tail(&i915_gem_obj_to_vma(from->obj, ggtt)->mm_list, &ggtt->active_list);
 		i915_gem_object_move_to_active(from->obj, ring);
 		/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
 		 * whole damn pipeline, we don't need to explicitly mark the
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
index 582e6a5..bf945a3 100644
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -97,7 +97,7 @@ i915_verify_lists(struct drm_device *dev)
 		}
 	}
 
-	list_for_each_entry(obj, &dev_priv->mm.inactive_list, list) {
+	list_for_each_entry(obj, &i915_gtt_vm->inactive_list, list) {
 		if (obj->base.dev != dev ||
 		    !atomic_read(&obj->base.refcount.refcount)) {
 			DRM_ERROR("freed inactive %p\n", obj);
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index dc53a52..f2e185c 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -289,12 +289,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 		goto fail_detach;
 	}
 
-	ret = drm_gem_private_object_init(dev, &obj->base, dma_buf->size);
-	if (ret) {
-		i915_gem_object_free(obj);
-		goto fail_detach;
-	}
-
+	drm_gem_private_object_init(dev, &obj->base, dma_buf->size);
 	i915_gem_object_init(obj, &i915_gem_object_dmabuf_ops);
 	obj->base.import_attach = attach;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index c86d5d9..425939b 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -32,22 +32,23 @@
 #include "i915_trace.h"
 
 static bool
-mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
+mark_free(struct i915_vma *vma, struct list_head *unwind)
 {
-	if (obj->pin_count)
+	if (vma->obj->pin_count)
 		return false;
 
-	list_add(&obj->exec_list, unwind);
-	return drm_mm_scan_add_block(obj->gtt_space);
+	list_add(&vma->obj->exec_list, unwind);
+	return drm_mm_scan_add_block(&vma->node);
 }
 
 int
-i915_gem_evict_something(struct drm_device *dev, int min_size,
-			 unsigned alignment, unsigned cache_level,
+i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
+			 int min_size, unsigned alignment, unsigned cache_level,
 			 bool mappable, bool nonblocking)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head eviction_list, unwind_list;
+	struct i915_vma *vma;
 	struct drm_i915_gem_object *obj;
 	int ret = 0;
 
@@ -77,17 +78,17 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
 	 */
 
 	INIT_LIST_HEAD(&unwind_list);
-	if (mappable)
-		drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space,
-					    min_size, alignment, cache_level,
-					    0, dev_priv->gtt.mappable_end);
-	else
-		drm_mm_init_scan(&dev_priv->mm.gtt_space,
-				 min_size, alignment, cache_level);
+	if (mappable) {
+		BUG_ON(!i915_is_ggtt(vm));
+		drm_mm_init_scan_with_range(&vm->mm, min_size,
+					    alignment, cache_level, 0,
+					    dev_priv->gtt.mappable_end);
+	} else
+		drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level);
 
 	/* First see if there is a large enough contiguous idle region... */
-	list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) {
-		if (mark_free(obj, &unwind_list))
+	list_for_each_entry(vma, &vm->inactive_list, mm_list) {
+		if (mark_free(vma, &unwind_list))
 			goto found;
 	}
 
@@ -95,8 +96,8 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
 		goto none;
 
 	/* Now merge in the soon-to-be-expired objects... */
-	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-		if (mark_free(obj, &unwind_list))
+	list_for_each_entry(vma, &vm->active_list, mm_list) {
+		if (mark_free(vma, &unwind_list))
 			goto found;
 	}
 
@@ -106,8 +107,8 @@ none:
 		obj = list_first_entry(&unwind_list,
 				       struct drm_i915_gem_object,
 				       exec_list);
-
-		ret = drm_mm_scan_remove_block(obj->gtt_space);
+		vma = i915_gem_obj_to_vma(obj, vm);
+		ret = drm_mm_scan_remove_block(&vma->node);
 		BUG_ON(ret);
 
 		list_del_init(&obj->exec_list);
@@ -127,7 +128,8 @@ found:
 		obj = list_first_entry(&unwind_list,
 				       struct drm_i915_gem_object,
 				       exec_list);
-		if (drm_mm_scan_remove_block(obj->gtt_space)) {
+		vma = i915_gem_obj_to_vma(obj, vm);
+		if (drm_mm_scan_remove_block(&vma->node)) {
 			list_move(&obj->exec_list, &eviction_list);
 			drm_gem_object_reference(&obj->base);
 			continue;
@@ -141,7 +143,7 @@ found:
 				       struct drm_i915_gem_object,
 				       exec_list);
 		if (ret == 0)
-			ret = i915_gem_object_unbind(obj);
+			ret = i915_vma_unbind(i915_gem_obj_to_vma(obj, vm));
 
 		list_del_init(&obj->exec_list);
 		drm_gem_object_unreference(&obj->base);
@@ -154,12 +156,18 @@ int
 i915_gem_evict_everything(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj, *next;
-	bool lists_empty;
+	struct i915_address_space *vm;
+	struct i915_vma *vma, *next;
+	bool lists_empty = true;
 	int ret;
 
-	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
-		       list_empty(&dev_priv->mm.active_list));
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		lists_empty = (list_empty(&vm->inactive_list) &&
+			       list_empty(&vm->active_list));
+		if (!lists_empty)
+			lists_empty = false;
+	}
+
 	if (lists_empty)
 		return -ENOSPC;
 
@@ -176,10 +184,11 @@ i915_gem_evict_everything(struct drm_device *dev)
 	i915_gem_retire_requests(dev);
 
 	/* Having flushed everything, unbind() should never raise an error */
-	list_for_each_entry_safe(obj, next,
-				 &dev_priv->mm.inactive_list, mm_list)
-		if (obj->pin_count == 0)
-			WARN_ON(i915_gem_object_unbind(obj));
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list)
+			if (vma->obj->pin_count == 0)
+				WARN_ON(i915_vma_unbind(vma));
+	}
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 87a3227..8ccc29a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -174,7 +174,8 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
 static int
 i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 				   struct eb_objects *eb,
-				   struct drm_i915_gem_relocation_entry *reloc)
+				   struct drm_i915_gem_relocation_entry *reloc,
+				   struct i915_address_space *vm)
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_gem_object *target_obj;
@@ -188,7 +189,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 		return -ENOENT;
 
 	target_i915_obj = to_intel_bo(target_obj);
-	target_offset = target_i915_obj->gtt_offset;
+	target_offset = i915_gem_obj_ggtt_offset(target_i915_obj);
 
 	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
 	 * pipe_control writes because the gpu doesn't properly redirect them
@@ -255,7 +256,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 
 	reloc->delta += target_offset;
 	if (use_cpu_reloc(obj)) {
-		uint32_t page_offset = reloc->offset & ~PAGE_MASK;
+		uint32_t page_offset = offset_in_page(reloc->offset);
 		char *vaddr;
 
 		ret = i915_gem_object_set_to_cpu_domain(obj, 1);
@@ -280,11 +281,11 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 			return ret;
 
 		/* Map the page containing the relocation we're going to perform.  */
-		reloc->offset += obj->gtt_offset;
+		reloc->offset += i915_gem_obj_ggtt_offset(obj);
 		reloc_page = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
 						      reloc->offset & PAGE_MASK);
 		reloc_entry = (uint32_t __iomem *)
-			(reloc_page + (reloc->offset & ~PAGE_MASK));
+			(reloc_page + offset_in_page(reloc->offset));
 		iowrite32(reloc->delta, reloc_entry);
 		io_mapping_unmap_atomic(reloc_page);
 	}
@@ -297,7 +298,8 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 
 static int
 i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
-				    struct eb_objects *eb)
+				    struct eb_objects *eb,
+				    struct i915_address_space *vm)
 {
 #define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry))
 	struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)];
@@ -321,7 +323,8 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
 		do {
 			u64 offset = r->presumed_offset;
 
-			ret = i915_gem_execbuffer_relocate_entry(obj, eb, r);
+			ret = i915_gem_execbuffer_relocate_entry(obj, eb, r,
+								 vm);
 			if (ret)
 				return ret;
 
@@ -344,13 +347,15 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
 static int
 i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
 					 struct eb_objects *eb,
-					 struct drm_i915_gem_relocation_entry *relocs)
+					 struct drm_i915_gem_relocation_entry *relocs,
+					 struct i915_address_space *vm)
 {
 	const struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
 	int i, ret;
 
 	for (i = 0; i < entry->relocation_count; i++) {
-		ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i]);
+		ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i],
+							 vm);
 		if (ret)
 			return ret;
 	}
@@ -359,7 +364,8 @@ i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
 }
 
 static int
-i915_gem_execbuffer_relocate(struct eb_objects *eb)
+i915_gem_execbuffer_relocate(struct eb_objects *eb,
+			     struct i915_address_space *vm)
 {
 	struct drm_i915_gem_object *obj;
 	int ret = 0;
@@ -373,7 +379,7 @@ i915_gem_execbuffer_relocate(struct eb_objects *eb)
 	 */
 	pagefault_disable();
 	list_for_each_entry(obj, &eb->objects, exec_list) {
-		ret = i915_gem_execbuffer_relocate_object(obj, eb);
+		ret = i915_gem_execbuffer_relocate_object(obj, eb, vm);
 		if (ret)
 			break;
 	}
@@ -395,6 +401,7 @@ need_reloc_mappable(struct drm_i915_gem_object *obj)
 static int
 i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
 				   struct intel_ring_buffer *ring,
+				   struct i915_address_space *vm,
 				   bool *need_reloc)
 {
 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
@@ -409,7 +416,8 @@ i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
 		obj->tiling_mode != I915_TILING_NONE;
 	need_mappable = need_fence || need_reloc_mappable(obj);
 
-	ret = i915_gem_object_pin(obj, entry->alignment, need_mappable, false);
+	ret = i915_gem_object_pin(obj, vm, entry->alignment, need_mappable,
+				  false);
 	if (ret)
 		return ret;
 
@@ -436,8 +444,8 @@ i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
 		obj->has_aliasing_ppgtt_mapping = 1;
 	}
 
-	if (entry->offset != obj->gtt_offset) {
-		entry->offset = obj->gtt_offset;
+	if (entry->offset != i915_gem_obj_offset(obj, vm)) {
+		entry->offset = i915_gem_obj_offset(obj, vm);
 		*need_reloc = true;
 	}
 
@@ -458,7 +466,7 @@ i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_gem_exec_object2 *entry;
 
-	if (!obj->gtt_space)
+	if (!i915_gem_obj_bound_any(obj))
 		return;
 
 	entry = obj->exec_entry;
@@ -475,6 +483,7 @@ i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 			    struct list_head *objects,
+			    struct i915_address_space *vm,
 			    bool *need_relocs)
 {
 	struct drm_i915_gem_object *obj;
@@ -529,31 +538,37 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 		list_for_each_entry(obj, objects, exec_list) {
 			struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
 			bool need_fence, need_mappable;
+			u32 obj_offset;
 
-			if (!obj->gtt_space)
+			if (!i915_gem_obj_bound(obj, vm))
 				continue;
 
+			obj_offset = i915_gem_obj_offset(obj, vm);
 			need_fence =
 				has_fenced_gpu_access &&
 				entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
 				obj->tiling_mode != I915_TILING_NONE;
 			need_mappable = need_fence || need_reloc_mappable(obj);
 
-			if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||
+			WARN_ON((need_mappable || need_fence) &&
+				!i915_is_ggtt(vm));
+
+			if ((entry->alignment &&
+			     obj_offset & (entry->alignment - 1)) ||
 			    (need_mappable && !obj->map_and_fenceable))
-				ret = i915_gem_object_unbind(obj);
+				ret = i915_vma_unbind(i915_gem_obj_to_vma(obj, vm));
 			else
-				ret = i915_gem_execbuffer_reserve_object(obj, ring, need_relocs);
+				ret = i915_gem_execbuffer_reserve_object(obj, ring, vm, need_relocs);
 			if (ret)
 				goto err;
 		}
 
 		/* Bind fresh objects */
 		list_for_each_entry(obj, objects, exec_list) {
-			if (obj->gtt_space)
+			if (i915_gem_obj_bound(obj, vm))
 				continue;
 
-			ret = i915_gem_execbuffer_reserve_object(obj, ring, need_relocs);
+			ret = i915_gem_execbuffer_reserve_object(obj, ring, vm, need_relocs);
 			if (ret)
 				goto err;
 		}
@@ -577,7 +592,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 				  struct drm_file *file,
 				  struct intel_ring_buffer *ring,
 				  struct eb_objects *eb,
-				  struct drm_i915_gem_exec_object2 *exec)
+				  struct drm_i915_gem_exec_object2 *exec,
+				  struct i915_address_space *vm)
 {
 	struct drm_i915_gem_relocation_entry *reloc;
 	struct drm_i915_gem_object *obj;
@@ -661,14 +677,15 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 		goto err;
 
 	need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-	ret = i915_gem_execbuffer_reserve(ring, &eb->objects, &need_relocs);
+	ret = i915_gem_execbuffer_reserve(ring, &eb->objects, vm, &need_relocs);
 	if (ret)
 		goto err;
 
 	list_for_each_entry(obj, &eb->objects, exec_list) {
 		int offset = obj->exec_entry - exec;
 		ret = i915_gem_execbuffer_relocate_object_slow(obj, eb,
-							       reloc + reloc_offset[offset]);
+							       reloc + reloc_offset[offset],
+							       vm);
 		if (ret)
 			goto err;
 	}
@@ -758,8 +775,10 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 		if (!access_ok(VERIFY_WRITE, ptr, length))
 			return -EFAULT;
 
-		if (fault_in_multipages_readable(ptr, length))
-			return -EFAULT;
+		if (likely(!i915_prefault_disable)) {
+			if (fault_in_multipages_readable(ptr, length))
+				return -EFAULT;
+		}
 	}
 
 	return 0;
@@ -767,6 +786,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 
 static void
 i915_gem_execbuffer_move_to_active(struct list_head *objects,
+				   struct i915_address_space *vm,
 				   struct intel_ring_buffer *ring)
 {
 	struct drm_i915_gem_object *obj;
@@ -781,6 +801,8 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 		obj->base.read_domains = obj->base.pending_read_domains;
 		obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
 
+		/* FIXME: This lookup gets fixed later <-- danvet */
+		list_move_tail(&i915_gem_obj_to_vma(obj, vm)->mm_list, &vm->active_list);
 		i915_gem_object_move_to_active(obj, ring);
 		if (obj->base.write_domain) {
 			obj->dirty = 1;
@@ -835,7 +857,8 @@ static int
 i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		       struct drm_file *file,
 		       struct drm_i915_gem_execbuffer2 *args,
-		       struct drm_i915_gem_exec_object2 *exec)
+		       struct drm_i915_gem_exec_object2 *exec,
+		       struct i915_address_space *vm)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct eb_objects *eb;
@@ -872,7 +895,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		break;
 	case I915_EXEC_BSD:
 		ring = &dev_priv->ring[VCS];
-		if (ctx_id != 0) {
+		if (ctx_id != DEFAULT_CONTEXT_ID) {
 			DRM_DEBUG("Ring %s doesn't support contexts\n",
 				  ring->name);
 			return -EPERM;
@@ -880,7 +903,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		break;
 	case I915_EXEC_BLT:
 		ring = &dev_priv->ring[BCS];
-		if (ctx_id != 0) {
+		if (ctx_id != DEFAULT_CONTEXT_ID) {
 			DRM_DEBUG("Ring %s doesn't support contexts\n",
 				  ring->name);
 			return -EPERM;
@@ -888,7 +911,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		break;
 	case I915_EXEC_VEBOX:
 		ring = &dev_priv->ring[VECS];
-		if (ctx_id != 0) {
+		if (ctx_id != DEFAULT_CONTEXT_ID) {
 			DRM_DEBUG("Ring %s doesn't support contexts\n",
 				  ring->name);
 			return -EPERM;
@@ -972,7 +995,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		goto pre_mutex_err;
 
-	if (dev_priv->mm.suspended) {
+	if (dev_priv->ums.mm_suspended) {
 		mutex_unlock(&dev->struct_mutex);
 		ret = -EBUSY;
 		goto pre_mutex_err;
@@ -997,17 +1020,17 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	/* Move the objects en-masse into the GTT, evicting if necessary. */
 	need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-	ret = i915_gem_execbuffer_reserve(ring, &eb->objects, &need_relocs);
+	ret = i915_gem_execbuffer_reserve(ring, &eb->objects, vm, &need_relocs);
 	if (ret)
 		goto err;
 
 	/* The objects are in their final locations, apply the relocations. */
 	if (need_relocs)
-		ret = i915_gem_execbuffer_relocate(eb);
+		ret = i915_gem_execbuffer_relocate(eb, vm);
 	if (ret) {
 		if (ret == -EFAULT) {
 			ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
-								eb, exec);
+								eb, exec, vm);
 			BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 		}
 		if (ret)
@@ -1058,7 +1081,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			goto err;
 	}
 
-	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
+	exec_start = i915_gem_obj_offset(batch_obj, vm) +
+		args->batch_start_offset;
 	exec_len = args->batch_len;
 	if (cliprects) {
 		for (i = 0; i < args->num_cliprects; i++) {
@@ -1083,7 +1107,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
 
-	i915_gem_execbuffer_move_to_active(&eb->objects, ring);
+	i915_gem_execbuffer_move_to_active(&eb->objects, vm, ring);
 	i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
 
 err:
@@ -1104,6 +1128,7 @@ int
 i915_gem_execbuffer(struct drm_device *dev, void *data,
 		    struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_execbuffer *args = data;
 	struct drm_i915_gem_execbuffer2 exec2;
 	struct drm_i915_gem_exec_object *exec_list = NULL;
@@ -1159,7 +1184,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 	exec2.flags = I915_EXEC_RENDER;
 	i915_execbuffer2_set_context_id(exec2, 0);
 
-	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
+	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list,
+				     &dev_priv->gtt.base);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		for (i = 0; i < args->buffer_count; i++)
@@ -1185,6 +1211,7 @@ int
 i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		     struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_execbuffer2 *args = data;
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 	int ret;
@@ -1215,7 +1242,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		return -EFAULT;
 	}
 
-	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
+	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list,
+				     &dev_priv->gtt.base);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		ret = copy_to_user(to_user_ptr(args->buffers_ptr),
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 5101ab6..24fb989 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -28,8 +28,12 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
+#define GEN6_PPGTT_PD_ENTRIES 512
+#define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t))
+
 /* PPGTT stuff */
 #define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
+#define HSW_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0x7f0))
 
 #define GEN6_PDE_VALID			(1 << 0)
 /* gen6+ has bit 11-4 for physical addr bit 39-32 */
@@ -39,19 +43,49 @@
 #define GEN6_PTE_UNCACHED		(1 << 1)
 #define HSW_PTE_UNCACHED		(0)
 #define GEN6_PTE_CACHE_LLC		(2 << 1)
-#define GEN6_PTE_CACHE_LLC_MLC		(3 << 1)
+#define GEN7_PTE_CACHE_L3_LLC		(3 << 1)
 #define GEN6_PTE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
+#define HSW_PTE_ADDR_ENCODE(addr)	HSW_GTT_ADDR_ENCODE(addr)
 
-static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
-				      dma_addr_t addr,
-				      enum i915_cache_level level)
+/* Cacheability Control is a 4-bit value. The low three bits are stored in *
+ * bits 3:1 of the PTE, while the fourth bit is stored in bit 11 of the PTE.
+ */
+#define HSW_CACHEABILITY_CONTROL(bits)	((((bits) & 0x7) << 1) | \
+					 (((bits) & 0x8) << (11 - 3)))
+#define HSW_WB_LLC_AGE3			HSW_CACHEABILITY_CONTROL(0x2)
+#define HSW_WB_LLC_AGE0			HSW_CACHEABILITY_CONTROL(0x3)
+#define HSW_WB_ELLC_LLC_AGE0		HSW_CACHEABILITY_CONTROL(0xb)
+
+static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
+				     enum i915_cache_level level)
 {
 	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
-	case I915_CACHE_LLC_MLC:
-		pte |= GEN6_PTE_CACHE_LLC_MLC;
+	case I915_CACHE_L3_LLC:
+	case I915_CACHE_LLC:
+		pte |= GEN6_PTE_CACHE_LLC;
+		break;
+	case I915_CACHE_NONE:
+		pte |= GEN6_PTE_UNCACHED;
+		break;
+	default:
+		WARN_ON(1);
+	}
+
+	return pte;
+}
+
+static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
+				     enum i915_cache_level level)
+{
+	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	pte |= GEN6_PTE_ADDR_ENCODE(addr);
+
+	switch (level) {
+	case I915_CACHE_L3_LLC:
+		pte |= GEN7_PTE_CACHE_L3_LLC;
 		break;
 	case I915_CACHE_LLC:
 		pte |= GEN6_PTE_CACHE_LLC;
@@ -60,7 +94,7 @@ static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
 		pte |= GEN6_PTE_UNCACHED;
 		break;
 	default:
-		BUG();
+		WARN_ON(1);
 	}
 
 	return pte;
@@ -69,8 +103,7 @@ static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
 #define BYT_PTE_WRITEABLE		(1 << 1)
 #define BYT_PTE_SNOOPED_BY_CPU_CACHES	(1 << 2)
 
-static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
-				     dma_addr_t addr,
+static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level)
 {
 	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
@@ -87,22 +120,33 @@ static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
 	return pte;
 }
 
-static gen6_gtt_pte_t hsw_pte_encode(struct drm_device *dev,
-				     dma_addr_t addr,
+static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level)
 {
 	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
-	pte |= GEN6_PTE_ADDR_ENCODE(addr);
+	pte |= HSW_PTE_ADDR_ENCODE(addr);
 
 	if (level != I915_CACHE_NONE)
-		pte |= GEN6_PTE_CACHE_LLC;
+		pte |= HSW_WB_LLC_AGE3;
+
+	return pte;
+}
+
+static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
+				      enum i915_cache_level level)
+{
+	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	pte |= HSW_PTE_ADDR_ENCODE(addr);
+
+	if (level != I915_CACHE_NONE)
+		pte |= HSW_WB_ELLC_LLC_AGE0;
 
 	return pte;
 }
 
 static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
 {
-	struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
+	struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private;
 	gen6_gtt_pte_t __iomem *pd_addr;
 	uint32_t pd_entry;
 	int i;
@@ -181,18 +225,18 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
 }
 
 /* PPGTT support for Sandybdrige/Gen6 and later */
-static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
+static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
 				   unsigned first_entry,
 				   unsigned num_entries)
 {
+	struct i915_hw_ppgtt *ppgtt =
+		container_of(vm, struct i915_hw_ppgtt, base);
 	gen6_gtt_pte_t *pt_vaddr, scratch_pte;
 	unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned last_pte, i;
 
-	scratch_pte = ppgtt->pte_encode(ppgtt->dev,
-					ppgtt->scratch_page_dma_addr,
-					I915_CACHE_LLC);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
 
 	while (num_entries) {
 		last_pte = first_pte + num_entries;
@@ -212,11 +256,13 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
 	}
 }
 
-static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
+static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
 				      struct sg_table *pages,
 				      unsigned first_entry,
 				      enum i915_cache_level cache_level)
 {
+	struct i915_hw_ppgtt *ppgtt =
+		container_of(vm, struct i915_hw_ppgtt, base);
 	gen6_gtt_pte_t *pt_vaddr;
 	unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
 	unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES;
@@ -227,8 +273,7 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
 		dma_addr_t page_addr;
 
 		page_addr = sg_page_iter_dma_address(&sg_iter);
-		pt_vaddr[act_pte] = ppgtt->pte_encode(ppgtt->dev, page_addr,
-						      cache_level);
+		pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level);
 		if (++act_pte == I915_PPGTT_PT_ENTRIES) {
 			kunmap_atomic(pt_vaddr);
 			act_pt++;
@@ -240,13 +285,17 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
 	kunmap_atomic(pt_vaddr);
 }
 
-static void gen6_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
+static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 {
+	struct i915_hw_ppgtt *ppgtt =
+		container_of(vm, struct i915_hw_ppgtt, base);
 	int i;
 
+	drm_mm_takedown(&ppgtt->base.mm);
+
 	if (ppgtt->pt_dma_addr) {
 		for (i = 0; i < ppgtt->num_pd_entries; i++)
-			pci_unmap_page(ppgtt->dev->pdev,
+			pci_unmap_page(ppgtt->base.dev->pdev,
 				       ppgtt->pt_dma_addr[i],
 				       4096, PCI_DMA_BIDIRECTIONAL);
 	}
@@ -260,7 +309,7 @@ static void gen6_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
 
 static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 {
-	struct drm_device *dev = ppgtt->dev;
+	struct drm_device *dev = ppgtt->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned first_pd_entry_in_global_pt;
 	int i;
@@ -271,18 +320,13 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 	 * now. */
 	first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
 
-	if (IS_HASWELL(dev)) {
-		ppgtt->pte_encode = hsw_pte_encode;
-	} else if (IS_VALLEYVIEW(dev)) {
-		ppgtt->pte_encode = byt_pte_encode;
-	} else {
-		ppgtt->pte_encode = gen6_pte_encode;
-	}
-	ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
+	ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
+	ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
 	ppgtt->enable = gen6_ppgtt_enable;
-	ppgtt->clear_range = gen6_ppgtt_clear_range;
-	ppgtt->insert_entries = gen6_ppgtt_insert_entries;
-	ppgtt->cleanup = gen6_ppgtt_cleanup;
+	ppgtt->base.clear_range = gen6_ppgtt_clear_range;
+	ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
+	ppgtt->base.cleanup = gen6_ppgtt_cleanup;
+	ppgtt->base.scratch = dev_priv->gtt.base.scratch;
 	ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries,
 				  GFP_KERNEL);
 	if (!ppgtt->pt_pages)
@@ -313,8 +357,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 		ppgtt->pt_dma_addr[i] = pt_addr;
 	}
 
-	ppgtt->clear_range(ppgtt, 0,
-			   ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES);
+	ppgtt->base.clear_range(&ppgtt->base, 0,
+				ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES);
 
 	ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
 
@@ -347,8 +391,7 @@ static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 	if (!ppgtt)
 		return -ENOMEM;
 
-	ppgtt->dev = dev;
-	ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma;
+	ppgtt->base.dev = dev;
 
 	if (INTEL_INFO(dev)->gen < 8)
 		ret = gen6_ppgtt_init(ppgtt);
@@ -357,8 +400,11 @@ static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 
 	if (ret)
 		kfree(ppgtt);
-	else
+	else {
 		dev_priv->mm.aliasing_ppgtt = ppgtt;
+		drm_mm_init(&ppgtt->base.mm, ppgtt->base.start,
+			    ppgtt->base.total);
+	}
 
 	return ret;
 }
@@ -371,7 +417,7 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
 	if (!ppgtt)
 		return;
 
-	ppgtt->cleanup(ppgtt);
+	ppgtt->base.cleanup(&ppgtt->base);
 	dev_priv->mm.aliasing_ppgtt = NULL;
 }
 
@@ -379,17 +425,17 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
 			    struct drm_i915_gem_object *obj,
 			    enum i915_cache_level cache_level)
 {
-	ppgtt->insert_entries(ppgtt, obj->pages,
-			      obj->gtt_space->start >> PAGE_SHIFT,
-			      cache_level);
+	ppgtt->base.insert_entries(&ppgtt->base, obj->pages,
+				   i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
+				   cache_level);
 }
 
 void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
 			      struct drm_i915_gem_object *obj)
 {
-	ppgtt->clear_range(ppgtt,
-			   obj->gtt_space->start >> PAGE_SHIFT,
-			   obj->base.size >> PAGE_SHIFT);
+	ppgtt->base.clear_range(&ppgtt->base,
+				i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
+				obj->base.size >> PAGE_SHIFT);
 }
 
 extern int intel_iommu_gfx_mapped;
@@ -436,8 +482,9 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 	struct drm_i915_gem_object *obj;
 
 	/* First fill our portion of the GTT with scratch pages */
-	dev_priv->gtt.gtt_clear_range(dev, dev_priv->gtt.start / PAGE_SIZE,
-				      dev_priv->gtt.total / PAGE_SIZE);
+	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
+				       dev_priv->gtt.base.start / PAGE_SIZE,
+				       dev_priv->gtt.base.total / PAGE_SIZE);
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		i915_gem_clflush_object(obj);
@@ -466,12 +513,12 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
  * within the global GTT as well as accessible by the GPU through the GMADR
  * mapped BAR (dev_priv->mm.gtt->gtt).
  */
-static void gen6_ggtt_insert_entries(struct drm_device *dev,
+static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *st,
 				     unsigned int first_entry,
 				     enum i915_cache_level level)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	gen6_gtt_pte_t __iomem *gtt_entries =
 		(gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
 	int i = 0;
@@ -480,8 +527,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_page_iter_dma_address(&sg_iter);
-		iowrite32(dev_priv->gtt.pte_encode(dev, addr, level),
-			  &gtt_entries[i]);
+		iowrite32(vm->pte_encode(addr, level), &gtt_entries[i]);
 		i++;
 	}
 
@@ -492,8 +538,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 	 * hardware should work, we must keep this posting read for paranoia.
 	 */
 	if (i != 0)
-		WARN_ON(readl(&gtt_entries[i-1])
-			!= dev_priv->gtt.pte_encode(dev, addr, level));
+		WARN_ON(readl(&gtt_entries[i-1]) !=
+			vm->pte_encode(addr, level));
 
 	/* This next bit makes the above posting read even more important. We
 	 * want to flush the TLBs only after we're certain all the PTE updates
@@ -503,11 +549,11 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
 }
 
-static void gen6_ggtt_clear_range(struct drm_device *dev,
+static void gen6_ggtt_clear_range(struct i915_address_space *vm,
 				  unsigned int first_entry,
 				  unsigned int num_entries)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
 		(gen6_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
 	const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
@@ -518,16 +564,14 @@ static void gen6_ggtt_clear_range(struct drm_device *dev,
 		 first_entry, num_entries, max_entries))
 		num_entries = max_entries;
 
-	scratch_pte = dev_priv->gtt.pte_encode(dev,
-					       dev_priv->gtt.scratch_page_dma,
-					       I915_CACHE_LLC);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
 	for (i = 0; i < num_entries; i++)
 		iowrite32(scratch_pte, &gtt_base[i]);
 	readl(gtt_base);
 }
 
 
-static void i915_ggtt_insert_entries(struct drm_device *dev,
+static void i915_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *st,
 				     unsigned int pg_start,
 				     enum i915_cache_level cache_level)
@@ -539,7 +583,7 @@ static void i915_ggtt_insert_entries(struct drm_device *dev,
 
 }
 
-static void i915_ggtt_clear_range(struct drm_device *dev,
+static void i915_ggtt_clear_range(struct i915_address_space *vm,
 				  unsigned int first_entry,
 				  unsigned int num_entries)
 {
@@ -552,10 +596,11 @@ void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT;
 
-	dev_priv->gtt.gtt_insert_entries(dev, obj->pages,
-					 obj->gtt_space->start >> PAGE_SHIFT,
-					 cache_level);
+	dev_priv->gtt.base.insert_entries(&dev_priv->gtt.base, obj->pages,
+					  entry,
+					  cache_level);
 
 	obj->has_global_gtt_mapping = 1;
 }
@@ -564,10 +609,11 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT;
 
-	dev_priv->gtt.gtt_clear_range(obj->base.dev,
-				      obj->gtt_space->start >> PAGE_SHIFT,
-				      obj->base.size >> PAGE_SHIFT);
+	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
+				       entry,
+				       obj->base.size >> PAGE_SHIFT);
 
 	obj->has_global_gtt_mapping = 0;
 }
@@ -618,7 +664,8 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
 	 * aperture.  One page should be enough to keep any prefetching inside
 	 * of the aperture.
 	 */
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
 	struct drm_mm_node *entry;
 	struct drm_i915_gem_object *obj;
 	unsigned long hole_start, hole_end;
@@ -626,37 +673,38 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
 	BUG_ON(mappable_end > end);
 
 	/* Subtract the guard page ... */
-	drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);
+	drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE);
 	if (!HAS_LLC(dev))
-		dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
+		dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust;
 
 	/* Mark any preallocated objects as occupied */
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
-		DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
-			      obj->gtt_offset, obj->base.size);
-
-		BUG_ON(obj->gtt_space != I915_GTT_RESERVED);
-		obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space,
-						     obj->gtt_offset,
-						     obj->base.size,
-						     false);
+		struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm);
+		int ret;
+		DRM_DEBUG_KMS("reserving preallocated space: %lx + %zx\n",
+			      i915_gem_obj_ggtt_offset(obj), obj->base.size);
+
+		WARN_ON(i915_gem_obj_ggtt_bound(obj));
+		ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node);
+		if (ret)
+			DRM_DEBUG_KMS("Reservation failed\n");
 		obj->has_global_gtt_mapping = 1;
+		list_add(&vma->vma_link, &obj->vma_list);
 	}
 
-	dev_priv->gtt.start = start;
-	dev_priv->gtt.total = end - start;
+	dev_priv->gtt.base.start = start;
+	dev_priv->gtt.base.total = end - start;
 
 	/* Clear any non-preallocated blocks */
-	drm_mm_for_each_hole(entry, &dev_priv->mm.gtt_space,
-			     hole_start, hole_end) {
+	drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) {
+		const unsigned long count = (hole_end - hole_start) / PAGE_SIZE;
 		DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
 			      hole_start, hole_end);
-		dev_priv->gtt.gtt_clear_range(dev, hole_start / PAGE_SIZE,
-					      (hole_end-hole_start) / PAGE_SIZE);
+		ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count);
 	}
 
 	/* And finally clear the reserved guard page */
-	dev_priv->gtt.gtt_clear_range(dev, end / PAGE_SIZE - 1, 1);
+	ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1);
 }
 
 static bool
@@ -679,7 +727,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long gtt_size, mappable_size;
 
-	gtt_size = dev_priv->gtt.total;
+	gtt_size = dev_priv->gtt.base.total;
 	mappable_size = dev_priv->gtt.mappable_end;
 
 	if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
@@ -688,7 +736,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
 		if (INTEL_INFO(dev)->gen <= 7) {
 			/* PPGTT pdes are stolen from global gtt ptes, so shrink the
 			 * aperture accordingly when using aliasing ppgtt. */
-			gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
+			gtt_size -= GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
 		}
 
 		i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
@@ -698,8 +746,8 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
 			return;
 
 		DRM_ERROR("Aliased PPGTT setup failed %d\n", ret);
-		drm_mm_takedown(&dev_priv->mm.gtt_space);
-		gtt_size += I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
+		drm_mm_takedown(&dev_priv->gtt.base.mm);
+		gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
 	}
 	i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
 }
@@ -724,8 +772,8 @@ static int setup_scratch_page(struct drm_device *dev)
 #else
 	dma_addr = page_to_phys(page);
 #endif
-	dev_priv->gtt.scratch_page = page;
-	dev_priv->gtt.scratch_page_dma = dma_addr;
+	dev_priv->gtt.base.scratch.page = page;
+	dev_priv->gtt.base.scratch.addr = dma_addr;
 
 	return 0;
 }
@@ -733,11 +781,13 @@ static int setup_scratch_page(struct drm_device *dev)
 static void teardown_scratch_page(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	set_pages_wb(dev_priv->gtt.scratch_page, 1);
-	pci_unmap_page(dev->pdev, dev_priv->gtt.scratch_page_dma,
+	struct page *page = dev_priv->gtt.base.scratch.page;
+
+	set_pages_wb(page, 1);
+	pci_unmap_page(dev->pdev, dev_priv->gtt.base.scratch.addr,
 		       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-	put_page(dev_priv->gtt.scratch_page);
-	__free_page(dev_priv->gtt.scratch_page);
+	put_page(page);
+	__free_page(page);
 }
 
 static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
@@ -800,17 +850,18 @@ static int gen6_gmch_probe(struct drm_device *dev,
 	if (ret)
 		DRM_ERROR("Scratch setup failed\n");
 
-	dev_priv->gtt.gtt_clear_range = gen6_ggtt_clear_range;
-	dev_priv->gtt.gtt_insert_entries = gen6_ggtt_insert_entries;
+	dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range;
+	dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries;
 
 	return ret;
 }
 
-static void gen6_gmch_remove(struct drm_device *dev)
+static void gen6_gmch_remove(struct i915_address_space *vm)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	iounmap(dev_priv->gtt.gsm);
-	teardown_scratch_page(dev_priv->dev);
+
+	struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
+	iounmap(gtt->gsm);
+	teardown_scratch_page(vm->dev);
 }
 
 static int i915_gmch_probe(struct drm_device *dev,
@@ -831,13 +882,13 @@ static int i915_gmch_probe(struct drm_device *dev,
 	intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end);
 
 	dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
-	dev_priv->gtt.gtt_clear_range = i915_ggtt_clear_range;
-	dev_priv->gtt.gtt_insert_entries = i915_ggtt_insert_entries;
+	dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
+	dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
 
 	return 0;
 }
 
-static void i915_gmch_remove(struct drm_device *dev)
+static void i915_gmch_remove(struct i915_address_space *vm)
 {
 	intel_gmch_remove();
 }
@@ -849,34 +900,35 @@ int i915_gem_gtt_init(struct drm_device *dev)
 	int ret;
 
 	if (INTEL_INFO(dev)->gen <= 5) {
-		dev_priv->gtt.gtt_probe = i915_gmch_probe;
-		dev_priv->gtt.gtt_remove = i915_gmch_remove;
+		gtt->gtt_probe = i915_gmch_probe;
+		gtt->base.cleanup = i915_gmch_remove;
 	} else {
-		dev_priv->gtt.gtt_probe = gen6_gmch_probe;
-		dev_priv->gtt.gtt_remove = gen6_gmch_remove;
-		if (IS_HASWELL(dev)) {
-			dev_priv->gtt.pte_encode = hsw_pte_encode;
-		} else if (IS_VALLEYVIEW(dev)) {
-			dev_priv->gtt.pte_encode = byt_pte_encode;
-		} else {
-			dev_priv->gtt.pte_encode = gen6_pte_encode;
-		}
+		gtt->gtt_probe = gen6_gmch_probe;
+		gtt->base.cleanup = gen6_gmch_remove;
+		if (IS_HASWELL(dev) && dev_priv->ellc_size)
+			gtt->base.pte_encode = iris_pte_encode;
+		else if (IS_HASWELL(dev))
+			gtt->base.pte_encode = hsw_pte_encode;
+		else if (IS_VALLEYVIEW(dev))
+			gtt->base.pte_encode = byt_pte_encode;
+		else if (INTEL_INFO(dev)->gen >= 7)
+			gtt->base.pte_encode = ivb_pte_encode;
+		else
+			gtt->base.pte_encode = snb_pte_encode;
 	}
 
-	ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,
-				     &dev_priv->gtt.stolen_size,
-				     &gtt->mappable_base,
-				     &gtt->mappable_end);
+	ret = gtt->gtt_probe(dev, &gtt->base.total, &gtt->stolen_size,
+			     &gtt->mappable_base, &gtt->mappable_end);
 	if (ret)
 		return ret;
 
+	gtt->base.dev = dev;
+
 	/* GMADR is the PCI mmio aperture into the global GTT. */
 	DRM_INFO("Memory usable by graphics device = %zdM\n",
-		 dev_priv->gtt.total >> 20);
-	DRM_DEBUG_DRIVER("GMADR size = %ldM\n",
-			 dev_priv->gtt.mappable_end >> 20);
-	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n",
-			 dev_priv->gtt.stolen_size >> 20);
+		 gtt->base.total >> 20);
+	DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20);
+	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 982d473..8912f48 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -45,49 +45,48 @@
 static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct pci_dev *pdev = dev_priv->bridge_dev;
+	struct resource *r;
 	u32 base;
 
-	/* On the machines I have tested the Graphics Base of Stolen Memory
-	 * is unreliable, so on those compute the base by subtracting the
-	 * stolen memory from the Top of Low Usable DRAM which is where the
-	 * BIOS places the graphics stolen memory.
+	/* Almost universally we can find the Graphics Base of Stolen Memory
+	 * at offset 0x5c in the igfx configuration space. On a few (desktop)
+	 * machines this is also mirrored in the bridge device at different
+	 * locations, or in the MCHBAR. On gen2, the layout is again slightly
+	 * different with the Graphics Segment immediately following Top of
+	 * Memory (or Top of Usable DRAM). Note it appears that TOUD is only
+	 * reported by 865g, so we just use the top of memory as determined
+	 * by the e820 probe.
 	 *
-	 * On gen2, the layout is slightly different with the Graphics Segment
-	 * immediately following Top of Memory (or Top of Usable DRAM). Note
-	 * it appears that TOUD is only reported by 865g, so we just use the
-	 * top of memory as determined by the e820 probe.
-	 *
-	 * XXX gen2 requires an unavailable symbol and 945gm fails with
-	 * its value of TOLUD.
+	 * XXX However gen2 requires an unavailable symbol.
 	 */
 	base = 0;
-	if (IS_VALLEYVIEW(dev)) {
+	if (INTEL_INFO(dev)->gen >= 3) {
+		/* Read Graphics Base of Stolen Memory directly */
 		pci_read_config_dword(dev->pdev, 0x5c, &base);
 		base &= ~((1<<20) - 1);
-	} else if (INTEL_INFO(dev)->gen >= 6) {
-		/* Read Base Data of Stolen Memory Register (BDSM) directly.
-		 * Note that there is also a MCHBAR miror at 0x1080c0 or
-		 * we could use device 2:0x5c instead.
-		*/
-		pci_read_config_dword(pdev, 0xB0, &base);
-		base &= ~4095; /* lower bits used for locking register */
-	} else if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-		/* Read Graphics Base of Stolen Memory directly */
-		pci_read_config_dword(pdev, 0xA4, &base);
+	} else { /* GEN2 */
 #if 0
-	} else if (IS_GEN3(dev)) {
-		u8 val;
-		/* Stolen is immediately below Top of Low Usable DRAM */
-		pci_read_config_byte(pdev, 0x9c, &val);
-		base = val >> 3 << 27;
-		base -= dev_priv->mm.gtt->stolen_size;
-	} else {
 		/* Stolen is immediately above Top of Memory */
 		base = max_low_pfn_mapped << PAGE_SHIFT;
 #endif
 	}
 
+	if (base == 0)
+		return 0;
+
+	/* Verify that nothing else uses this physical address. Stolen
+	 * memory should be reserved by the BIOS and hidden from the
+	 * kernel. So if the region is already marked as busy, something
+	 * is seriously wrong.
+	 */
+	r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size,
+				    "Graphics Stolen Memory");
+	if (r == NULL) {
+		DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
+			  base, base + (uint32_t)dev_priv->gtt.stolen_size);
+		base = 0;
+	}
+
 	return base;
 }
 
@@ -95,32 +94,37 @@ static int i915_setup_compression(struct drm_device *dev, int size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
+	int ret;
 
-	/* Try to over-allocate to reduce reallocations and fragmentation */
-	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen,
-					   size <<= 1, 4096, 0);
+	compressed_fb = kzalloc(sizeof(*compressed_fb), GFP_KERNEL);
 	if (!compressed_fb)
-		compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen,
-						   size >>= 1, 4096, 0);
-	if (compressed_fb)
-		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
-	if (!compressed_fb)
-		goto err;
+		goto err_llb;
+
+	/* Try to over-allocate to reduce reallocations and fragmentation */
+	ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_fb,
+				 size <<= 1, 4096, DRM_MM_SEARCH_DEFAULT);
+	if (ret)
+		ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_fb,
+					 size >>= 1, 4096,
+					 DRM_MM_SEARCH_DEFAULT);
+	if (ret)
+		goto err_llb;
 
 	if (HAS_PCH_SPLIT(dev))
 		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
 	else if (IS_GM45(dev)) {
 		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
 	} else {
-		compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
-						    4096, 4096, 0);
-		if (compressed_llb)
-			compressed_llb = drm_mm_get_block(compressed_llb,
-							  4096, 4096);
+		compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
 		if (!compressed_llb)
 			goto err_fb;
 
-		dev_priv->compressed_llb = compressed_llb;
+		ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_llb,
+					 4096, 4096, DRM_MM_SEARCH_DEFAULT);
+		if (ret)
+			goto err_fb;
+
+		dev_priv->fbc.compressed_llb = compressed_llb;
 
 		I915_WRITE(FBC_CFB_BASE,
 			   dev_priv->mm.stolen_base + compressed_fb->start);
@@ -128,8 +132,8 @@ static int i915_setup_compression(struct drm_device *dev, int size)
 			   dev_priv->mm.stolen_base + compressed_llb->start);
 	}
 
-	dev_priv->compressed_fb = compressed_fb;
-	dev_priv->cfb_size = size;
+	dev_priv->fbc.compressed_fb = compressed_fb;
+	dev_priv->fbc.size = size;
 
 	DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
 		      size);
@@ -137,8 +141,10 @@ static int i915_setup_compression(struct drm_device *dev, int size)
 	return 0;
 
 err_fb:
-	drm_mm_put_block(compressed_fb);
-err:
+	kfree(compressed_llb);
+	drm_mm_remove_node(compressed_fb);
+err_llb:
+	kfree(compressed_fb);
 	pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
 	return -ENOSPC;
 }
@@ -150,7 +156,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
 	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return -ENODEV;
 
-	if (size < dev_priv->cfb_size)
+	if (size < dev_priv->fbc.size)
 		return 0;
 
 	/* Release any current block */
@@ -163,16 +169,20 @@ void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->cfb_size == 0)
+	if (dev_priv->fbc.size == 0)
 		return;
 
-	if (dev_priv->compressed_fb)
-		drm_mm_put_block(dev_priv->compressed_fb);
+	if (dev_priv->fbc.compressed_fb) {
+		drm_mm_remove_node(dev_priv->fbc.compressed_fb);
+		kfree(dev_priv->fbc.compressed_fb);
+	}
 
-	if (dev_priv->compressed_llb)
-		drm_mm_put_block(dev_priv->compressed_llb);
+	if (dev_priv->fbc.compressed_llb) {
+		drm_mm_remove_node(dev_priv->fbc.compressed_llb);
+		kfree(dev_priv->fbc.compressed_llb);
+	}
 
-	dev_priv->cfb_size = 0;
+	dev_priv->fbc.size = 0;
 }
 
 void i915_gem_cleanup_stolen(struct drm_device *dev)
@@ -201,6 +211,9 @@ int i915_gem_init_stolen(struct drm_device *dev)
 	if (IS_VALLEYVIEW(dev))
 		bios_reserved = 1024*1024; /* top 1M on VLV/BYT */
 
+	if (WARN_ON(bios_reserved > dev_priv->gtt.stolen_size))
+		return 0;
+
 	/* Basic memrange allocator for stolen space */
 	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
 		    bios_reserved);
@@ -271,9 +284,7 @@ _i915_gem_object_create_stolen(struct drm_device *dev,
 	if (obj == NULL)
 		return NULL;
 
-	if (drm_gem_private_object_init(dev, &obj->base, stolen->size))
-		goto cleanup;
-
+	drm_gem_private_object_init(dev, &obj->base, stolen->size);
 	i915_gem_object_init(obj, &i915_gem_object_stolen_ops);
 
 	obj->pages = i915_pages_create_for_stolen(dev,
@@ -302,6 +313,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
 	struct drm_mm_node *stolen;
+	int ret;
 
 	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return NULL;
@@ -310,17 +322,23 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
 	if (size == 0)
 		return NULL;
 
-	stolen = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
-	if (stolen)
-		stolen = drm_mm_get_block(stolen, size, 4096);
-	if (stolen == NULL)
+	stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
+	if (!stolen)
+		return NULL;
+
+	ret = drm_mm_insert_node(&dev_priv->mm.stolen, stolen, size,
+				 4096, DRM_MM_SEARCH_DEFAULT);
+	if (ret) {
+		kfree(stolen);
 		return NULL;
+	}
 
 	obj = _i915_gem_object_create_stolen(dev, stolen);
 	if (obj)
 		return obj;
 
-	drm_mm_put_block(stolen);
+	drm_mm_remove_node(stolen);
+	kfree(stolen);
 	return NULL;
 }
 
@@ -331,8 +349,11 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 					       u32 size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_address_space *ggtt = &dev_priv->gtt.base;
 	struct drm_i915_gem_object *obj;
 	struct drm_mm_node *stolen;
+	struct i915_vma *vma;
+	int ret;
 
 	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return NULL;
@@ -347,56 +368,73 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 	if (WARN_ON(size == 0))
 		return NULL;
 
-	stolen = drm_mm_create_block(&dev_priv->mm.stolen,
-				     stolen_offset, size,
-				     false);
-	if (stolen == NULL) {
+	stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
+	if (!stolen)
+		return NULL;
+
+	stolen->start = stolen_offset;
+	stolen->size = size;
+	ret = drm_mm_reserve_node(&dev_priv->mm.stolen, stolen);
+	if (ret) {
 		DRM_DEBUG_KMS("failed to allocate stolen space\n");
+		kfree(stolen);
 		return NULL;
 	}
 
 	obj = _i915_gem_object_create_stolen(dev, stolen);
 	if (obj == NULL) {
 		DRM_DEBUG_KMS("failed to allocate stolen object\n");
-		drm_mm_put_block(stolen);
+		drm_mm_remove_node(stolen);
+		kfree(stolen);
 		return NULL;
 	}
 
 	/* Some objects just need physical mem from stolen space */
-	if (gtt_offset == -1)
+	if (gtt_offset == I915_GTT_OFFSET_NONE)
 		return obj;
 
+	vma = i915_gem_vma_create(obj, ggtt);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
+		goto err_out;
+	}
+
 	/* To simplify the initialisation sequence between KMS and GTT,
 	 * we allow construction of the stolen object prior to
 	 * setting up the GTT space. The actual reservation will occur
 	 * later.
 	 */
-	if (drm_mm_initialized(&dev_priv->mm.gtt_space)) {
-		obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space,
-						     gtt_offset, size,
-						     false);
-		if (obj->gtt_space == NULL) {
+	vma->node.start = gtt_offset;
+	vma->node.size = size;
+	if (drm_mm_initialized(&ggtt->mm)) {
+		ret = drm_mm_reserve_node(&ggtt->mm, &vma->node);
+		if (ret) {
 			DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
-			drm_gem_object_unreference(&obj->base);
-			return NULL;
+			i915_gem_vma_destroy(vma);
+			goto err_out;
 		}
-	} else
-		obj->gtt_space = I915_GTT_RESERVED;
+	}
 
-	obj->gtt_offset = gtt_offset;
 	obj->has_global_gtt_mapping = 1;
 
 	list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
-	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+	list_add_tail(&vma->mm_list, &ggtt->inactive_list);
 
 	return obj;
+
+err_out:
+	drm_mm_remove_node(stolen);
+	kfree(stolen);
+	drm_gem_object_unreference(&obj->base);
+	return NULL;
 }
 
 void
 i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
 {
 	if (obj->stolen) {
-		drm_mm_put_block(obj->stolen);
+		drm_mm_remove_node(obj->stolen);
+		kfree(obj->stolen);
 		obj->stolen = NULL;
 	}
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 537545b..032e9ef 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -268,18 +268,18 @@ i915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode)
 		return true;
 
 	if (INTEL_INFO(obj->base.dev)->gen == 3) {
-		if (obj->gtt_offset & ~I915_FENCE_START_MASK)
+		if (i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK)
 			return false;
 	} else {
-		if (obj->gtt_offset & ~I830_FENCE_START_MASK)
+		if (i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK)
 			return false;
 	}
 
 	size = i915_gem_get_gtt_size(obj->base.dev, obj->base.size, tiling_mode);
-	if (obj->gtt_space->size != size)
+	if (i915_gem_obj_ggtt_size(obj) != size)
 		return false;
 
-	if (obj->gtt_offset & (size - 1))
+	if (i915_gem_obj_ggtt_offset(obj) & (size - 1))
 		return false;
 
 	return true;
@@ -359,18 +359,19 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
 		 */
 
 		obj->map_and_fenceable =
-			obj->gtt_space == NULL ||
-			(obj->gtt_offset + obj->base.size <= dev_priv->gtt.mappable_end &&
+			!i915_gem_obj_ggtt_bound(obj) ||
+			(i915_gem_obj_ggtt_offset(obj) +
+			 obj->base.size <= dev_priv->gtt.mappable_end &&
 			 i915_gem_object_fence_ok(obj, args->tiling_mode));
 
 		/* Rebind if we need a change of alignment */
 		if (!obj->map_and_fenceable) {
-			u32 unfenced_alignment =
+			u32 unfenced_align =
 				i915_gem_get_gtt_alignment(dev, obj->base.size,
 							    args->tiling_mode,
 							    false);
-			if (obj->gtt_offset & (unfenced_alignment - 1))
-				ret = i915_gem_object_unbind(obj);
+			if (i915_gem_obj_ggtt_offset(obj) & (unfenced_align - 1))
+				ret = i915_gem_object_ggtt_unbind(obj);
 		}
 
 		if (ret == 0) {
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
new file mode 100644
index 0000000..60393cb
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (c) 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *    Keith Packard <keithp@keithp.com>
+ *    Mika Kuoppala <mika.kuoppala@intel.com>
+ *
+ */
+
+#include <generated/utsrelease.h>
+#include "i915_drv.h"
+
+static const char *yesno(int v)
+{
+	return v ? "yes" : "no";
+}
+
+static const char *ring_str(int ring)
+{
+	switch (ring) {
+	case RCS: return "render";
+	case VCS: return "bsd";
+	case BCS: return "blt";
+	case VECS: return "vebox";
+	default: return "";
+	}
+}
+
+static const char *pin_flag(int pinned)
+{
+	if (pinned > 0)
+		return " P";
+	else if (pinned < 0)
+		return " p";
+	else
+		return "";
+}
+
+static const char *tiling_flag(int tiling)
+{
+	switch (tiling) {
+	default:
+	case I915_TILING_NONE: return "";
+	case I915_TILING_X: return " X";
+	case I915_TILING_Y: return " Y";
+	}
+}
+
+static const char *dirty_flag(int dirty)
+{
+	return dirty ? " dirty" : "";
+}
+
+static const char *purgeable_flag(int purgeable)
+{
+	return purgeable ? " purgeable" : "";
+}
+
+static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
+{
+
+	if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
+		e->err = -ENOSPC;
+		return false;
+	}
+
+	if (e->bytes == e->size - 1 || e->err)
+		return false;
+
+	return true;
+}
+
+static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
+			      unsigned len)
+{
+	if (e->pos + len <= e->start) {
+		e->pos += len;
+		return false;
+	}
+
+	/* First vsnprintf needs to fit in its entirety for memmove */
+	if (len >= e->size) {
+		e->err = -EIO;
+		return false;
+	}
+
+	return true;
+}
+
+static void __i915_error_advance(struct drm_i915_error_state_buf *e,
+				 unsigned len)
+{
+	/* If this is first printf in this window, adjust it so that
+	 * start position matches start of the buffer
+	 */
+
+	if (e->pos < e->start) {
+		const size_t off = e->start - e->pos;
+
+		/* Should not happen but be paranoid */
+		if (off > len || e->bytes) {
+			e->err = -EIO;
+			return;
+		}
+
+		memmove(e->buf, e->buf + off, len - off);
+		e->bytes = len - off;
+		e->pos = e->start;
+		return;
+	}
+
+	e->bytes += len;
+	e->pos += len;
+}
+
+static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
+			       const char *f, va_list args)
+{
+	unsigned len;
+
+	if (!__i915_error_ok(e))
+		return;
+
+	/* Seek the first printf which is hits start position */
+	if (e->pos < e->start) {
+		len = vsnprintf(NULL, 0, f, args);
+		if (!__i915_error_seek(e, len))
+			return;
+	}
+
+	len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
+	if (len >= e->size - e->bytes)
+		len = e->size - e->bytes - 1;
+
+	__i915_error_advance(e, len);
+}
+
+static void i915_error_puts(struct drm_i915_error_state_buf *e,
+			    const char *str)
+{
+	unsigned len;
+
+	if (!__i915_error_ok(e))
+		return;
+
+	len = strlen(str);
+
+	/* Seek the first printf which is hits start position */
+	if (e->pos < e->start) {
+		if (!__i915_error_seek(e, len))
+			return;
+	}
+
+	if (len >= e->size - e->bytes)
+		len = e->size - e->bytes - 1;
+	memcpy(e->buf + e->bytes, str, len);
+
+	__i915_error_advance(e, len);
+}
+
+#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
+#define err_puts(e, s) i915_error_puts(e, s)
+
+static void print_error_buffers(struct drm_i915_error_state_buf *m,
+				const char *name,
+				struct drm_i915_error_buffer *err,
+				int count)
+{
+	err_printf(m, "%s [%d]:\n", name, count);
+
+	while (count--) {
+		err_printf(m, "  %08x %8u %02x %02x %x %x",
+			   err->gtt_offset,
+			   err->size,
+			   err->read_domains,
+			   err->write_domain,
+			   err->rseqno, err->wseqno);
+		err_puts(m, pin_flag(err->pinned));
+		err_puts(m, tiling_flag(err->tiling));
+		err_puts(m, dirty_flag(err->dirty));
+		err_puts(m, purgeable_flag(err->purgeable));
+		err_puts(m, err->ring != -1 ? " " : "");
+		err_puts(m, ring_str(err->ring));
+		err_puts(m, i915_cache_level_str(err->cache_level));
+
+		if (err->name)
+			err_printf(m, " (name: %d)", err->name);
+		if (err->fence_reg != I915_FENCE_REG_NONE)
+			err_printf(m, " (fence: %d)", err->fence_reg);
+
+		err_puts(m, "\n");
+		err++;
+	}
+}
+
+static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
+				  struct drm_device *dev,
+				  struct drm_i915_error_state *error,
+				  unsigned ring)
+{
+	BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
+	err_printf(m, "%s command stream:\n", ring_str(ring));
+	err_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
+	err_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
+	err_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
+	err_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
+	err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
+	err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
+	err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
+	if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
+		err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
+
+	if (INTEL_INFO(dev)->gen >= 4)
+		err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
+	err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
+	err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
+	if (INTEL_INFO(dev)->gen >= 6) {
+		err_printf(m, "  RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
+		err_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
+		err_printf(m, "  SYNC_0: 0x%08x [last synced 0x%08x]\n",
+			   error->semaphore_mboxes[ring][0],
+			   error->semaphore_seqno[ring][0]);
+		err_printf(m, "  SYNC_1: 0x%08x [last synced 0x%08x]\n",
+			   error->semaphore_mboxes[ring][1],
+			   error->semaphore_seqno[ring][1]);
+	}
+	err_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
+	err_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
+	err_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
+	err_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
+}
+
+void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
+{
+	va_list args;
+
+	va_start(args, f);
+	i915_error_vprintf(e, f, args);
+	va_end(args);
+}
+
+int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
+			    const struct i915_error_state_file_priv *error_priv)
+{
+	struct drm_device *dev = error_priv->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error = error_priv->error;
+	struct intel_ring_buffer *ring;
+	int i, j, page, offset, elt;
+
+	if (!error) {
+		err_printf(m, "no error state collected\n");
+		goto out;
+	}
+
+	err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
+		   error->time.tv_usec);
+	err_printf(m, "Kernel: " UTS_RELEASE "\n");
+	err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
+	err_printf(m, "EIR: 0x%08x\n", error->eir);
+	err_printf(m, "IER: 0x%08x\n", error->ier);
+	err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+	err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+	err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
+	err_printf(m, "CCID: 0x%08x\n", error->ccid);
+
+	for (i = 0; i < dev_priv->num_fence_regs; i++)
+		err_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
+
+	for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
+		err_printf(m, "  INSTDONE_%d: 0x%08x\n", i,
+			   error->extra_instdone[i]);
+
+	if (INTEL_INFO(dev)->gen >= 6) {
+		err_printf(m, "ERROR: 0x%08x\n", error->error);
+		err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
+	}
+
+	if (INTEL_INFO(dev)->gen == 7)
+		err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+
+	for_each_ring(ring, dev_priv, i)
+		i915_ring_error_state(m, dev, error, i);
+
+	if (error->active_bo)
+		print_error_buffers(m, "Active",
+				    error->active_bo[0],
+				    error->active_bo_count[0]);
+
+	if (error->pinned_bo)
+		print_error_buffers(m, "Pinned",
+				    error->pinned_bo[0],
+				    error->pinned_bo_count[0]);
+
+	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
+		struct drm_i915_error_object *obj;
+
+		if ((obj = error->ring[i].batchbuffer)) {
+			err_printf(m, "%s --- gtt_offset = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
+			offset = 0;
+			for (page = 0; page < obj->page_count; page++) {
+				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
+					err_printf(m, "%08x :  %08x\n", offset,
+						   obj->pages[page][elt]);
+					offset += 4;
+				}
+			}
+		}
+
+		if (error->ring[i].num_requests) {
+			err_printf(m, "%s --- %d requests\n",
+				   dev_priv->ring[i].name,
+				   error->ring[i].num_requests);
+			for (j = 0; j < error->ring[i].num_requests; j++) {
+				err_printf(m, "  seqno 0x%08x, emitted %ld, tail 0x%08x\n",
+					   error->ring[i].requests[j].seqno,
+					   error->ring[i].requests[j].jiffies,
+					   error->ring[i].requests[j].tail);
+			}
+		}
+
+		if ((obj = error->ring[i].ringbuffer)) {
+			err_printf(m, "%s --- ringbuffer = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
+			offset = 0;
+			for (page = 0; page < obj->page_count; page++) {
+				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
+					err_printf(m, "%08x :  %08x\n",
+						   offset,
+						   obj->pages[page][elt]);
+					offset += 4;
+				}
+			}
+		}
+
+		obj = error->ring[i].ctx;
+		if (obj) {
+			err_printf(m, "%s --- HW Context = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
+			offset = 0;
+			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
+				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
+					   offset,
+					   obj->pages[0][elt],
+					   obj->pages[0][elt+1],
+					   obj->pages[0][elt+2],
+					   obj->pages[0][elt+3]);
+					offset += 16;
+			}
+		}
+	}
+
+	if (error->overlay)
+		intel_overlay_print_error_state(m, error->overlay);
+
+	if (error->display)
+		intel_display_print_error_state(m, dev, error->display);
+
+out:
+	if (m->bytes == 0 && m->err)
+		return m->err;
+
+	return 0;
+}
+
+int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
+			      size_t count, loff_t pos)
+{
+	memset(ebuf, 0, sizeof(*ebuf));
+
+	/* We need to have enough room to store any i915_error_state printf
+	 * so that we can move it to start position.
+	 */
+	ebuf->size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
+	ebuf->buf = kmalloc(ebuf->size,
+				GFP_TEMPORARY | __GFP_NORETRY | __GFP_NOWARN);
+
+	if (ebuf->buf == NULL) {
+		ebuf->size = PAGE_SIZE;
+		ebuf->buf = kmalloc(ebuf->size, GFP_TEMPORARY);
+	}
+
+	if (ebuf->buf == NULL) {
+		ebuf->size = 128;
+		ebuf->buf = kmalloc(ebuf->size, GFP_TEMPORARY);
+	}
+
+	if (ebuf->buf == NULL)
+		return -ENOMEM;
+
+	ebuf->start = pos;
+
+	return 0;
+}
+
+static void i915_error_object_free(struct drm_i915_error_object *obj)
+{
+	int page;
+
+	if (obj == NULL)
+		return;
+
+	for (page = 0; page < obj->page_count; page++)
+		kfree(obj->pages[page]);
+
+	kfree(obj);
+}
+
+static void i915_error_state_free(struct kref *error_ref)
+{
+	struct drm_i915_error_state *error = container_of(error_ref,
+							  typeof(*error), ref);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
+		i915_error_object_free(error->ring[i].batchbuffer);
+		i915_error_object_free(error->ring[i].ringbuffer);
+		i915_error_object_free(error->ring[i].ctx);
+		kfree(error->ring[i].requests);
+	}
+
+	kfree(error->active_bo);
+	kfree(error->overlay);
+	kfree(error->display);
+	kfree(error);
+}
+
+static struct drm_i915_error_object *
+i915_error_object_create_sized(struct drm_i915_private *dev_priv,
+			       struct drm_i915_gem_object *src,
+			       const int num_pages)
+{
+	struct drm_i915_error_object *dst;
+	int i;
+	u32 reloc_offset;
+
+	if (src == NULL || src->pages == NULL)
+		return NULL;
+
+	dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
+	if (dst == NULL)
+		return NULL;
+
+	reloc_offset = dst->gtt_offset = i915_gem_obj_ggtt_offset(src);
+	for (i = 0; i < num_pages; i++) {
+		unsigned long flags;
+		void *d;
+
+		d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+		if (d == NULL)
+			goto unwind;
+
+		local_irq_save(flags);
+		if (reloc_offset < dev_priv->gtt.mappable_end &&
+		    src->has_global_gtt_mapping) {
+			void __iomem *s;
+
+			/* Simply ignore tiling or any overlapping fence.
+			 * It's part of the error state, and this hopefully
+			 * captures what the GPU read.
+			 */
+
+			s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+						     reloc_offset);
+			memcpy_fromio(d, s, PAGE_SIZE);
+			io_mapping_unmap_atomic(s);
+		} else if (src->stolen) {
+			unsigned long offset;
+
+			offset = dev_priv->mm.stolen_base;
+			offset += src->stolen->start;
+			offset += i << PAGE_SHIFT;
+
+			memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE);
+		} else {
+			struct page *page;
+			void *s;
+
+			page = i915_gem_object_get_page(src, i);
+
+			drm_clflush_pages(&page, 1);
+
+			s = kmap_atomic(page);
+			memcpy(d, s, PAGE_SIZE);
+			kunmap_atomic(s);
+
+			drm_clflush_pages(&page, 1);
+		}
+		local_irq_restore(flags);
+
+		dst->pages[i] = d;
+
+		reloc_offset += PAGE_SIZE;
+	}
+	dst->page_count = num_pages;
+
+	return dst;
+
+unwind:
+	while (i--)
+		kfree(dst->pages[i]);
+	kfree(dst);
+	return NULL;
+}
+#define i915_error_object_create(dev_priv, src) \
+	i915_error_object_create_sized((dev_priv), (src), \
+				       (src)->base.size>>PAGE_SHIFT)
+
+static void capture_bo(struct drm_i915_error_buffer *err,
+		       struct drm_i915_gem_object *obj)
+{
+	err->size = obj->base.size;
+	err->name = obj->base.name;
+	err->rseqno = obj->last_read_seqno;
+	err->wseqno = obj->last_write_seqno;
+	err->gtt_offset = i915_gem_obj_ggtt_offset(obj);
+	err->read_domains = obj->base.read_domains;
+	err->write_domain = obj->base.write_domain;
+	err->fence_reg = obj->fence_reg;
+	err->pinned = 0;
+	if (obj->pin_count > 0)
+		err->pinned = 1;
+	if (obj->user_pin_count > 0)
+		err->pinned = -1;
+	err->tiling = obj->tiling_mode;
+	err->dirty = obj->dirty;
+	err->purgeable = obj->madv != I915_MADV_WILLNEED;
+	err->ring = obj->ring ? obj->ring->id : -1;
+	err->cache_level = obj->cache_level;
+}
+
+static u32 capture_active_bo(struct drm_i915_error_buffer *err,
+			     int count, struct list_head *head)
+{
+	struct i915_vma *vma;
+	int i = 0;
+
+	list_for_each_entry(vma, head, mm_list) {
+		capture_bo(err++, vma->obj);
+		if (++i == count)
+			break;
+	}
+
+	return i;
+}
+
+static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
+			     int count, struct list_head *head)
+{
+	struct drm_i915_gem_object *obj;
+	int i = 0;
+
+	list_for_each_entry(obj, head, global_list) {
+		if (obj->pin_count == 0)
+			continue;
+
+		capture_bo(err++, obj);
+		if (++i == count)
+			break;
+	}
+
+	return i;
+}
+
+static void i915_gem_record_fences(struct drm_device *dev,
+				   struct drm_i915_error_state *error)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	/* Fences */
+	switch (INTEL_INFO(dev)->gen) {
+	case 7:
+	case 6:
+		for (i = 0; i < dev_priv->num_fence_regs; i++)
+			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
+		break;
+	case 5:
+	case 4:
+		for (i = 0; i < 16; i++)
+			error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
+		break;
+	case 3:
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+	case 2:
+		for (i = 0; i < 8; i++)
+			error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+		break;
+
+	default:
+		BUG();
+	}
+}
+
+static struct drm_i915_error_object *
+i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
+			     struct intel_ring_buffer *ring)
+{
+	struct i915_address_space *vm;
+	struct i915_vma *vma;
+	struct drm_i915_gem_object *obj;
+	u32 seqno;
+
+	if (!ring->get_seqno)
+		return NULL;
+
+	if (HAS_BROKEN_CS_TLB(dev_priv->dev)) {
+		u32 acthd = I915_READ(ACTHD);
+
+		if (WARN_ON(ring->id != RCS))
+			return NULL;
+
+		obj = ring->private;
+		if (acthd >= i915_gem_obj_ggtt_offset(obj) &&
+		    acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size)
+			return i915_error_object_create(dev_priv, obj);
+	}
+
+	seqno = ring->get_seqno(ring, false);
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		list_for_each_entry(vma, &vm->active_list, mm_list) {
+			obj = vma->obj;
+			if (obj->ring != ring)
+				continue;
+
+			if (i915_seqno_passed(seqno, obj->last_read_seqno))
+				continue;
+
+			if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
+				continue;
+
+			/* We need to copy these to an anonymous buffer as the simplest
+			 * method to avoid being overwritten by userspace.
+			 */
+			return i915_error_object_create(dev_priv, obj);
+		}
+	}
+
+	return NULL;
+}
+
+static void i915_record_ring_state(struct drm_device *dev,
+				   struct drm_i915_error_state *error,
+				   struct intel_ring_buffer *ring)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (INTEL_INFO(dev)->gen >= 6) {
+		error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50);
+		error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
+		error->semaphore_mboxes[ring->id][0]
+			= I915_READ(RING_SYNC_0(ring->mmio_base));
+		error->semaphore_mboxes[ring->id][1]
+			= I915_READ(RING_SYNC_1(ring->mmio_base));
+		error->semaphore_seqno[ring->id][0] = ring->sync_seqno[0];
+		error->semaphore_seqno[ring->id][1] = ring->sync_seqno[1];
+	}
+
+	if (INTEL_INFO(dev)->gen >= 4) {
+		error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
+		error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
+		error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
+		error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
+		error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
+		if (ring->id == RCS)
+			error->bbaddr = I915_READ64(BB_ADDR);
+	} else {
+		error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
+		error->ipeir[ring->id] = I915_READ(IPEIR);
+		error->ipehr[ring->id] = I915_READ(IPEHR);
+		error->instdone[ring->id] = I915_READ(INSTDONE);
+	}
+
+	error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
+	error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
+	error->seqno[ring->id] = ring->get_seqno(ring, false);
+	error->acthd[ring->id] = intel_ring_get_active_head(ring);
+	error->head[ring->id] = I915_READ_HEAD(ring);
+	error->tail[ring->id] = I915_READ_TAIL(ring);
+	error->ctl[ring->id] = I915_READ_CTL(ring);
+
+	error->cpu_ring_head[ring->id] = ring->head;
+	error->cpu_ring_tail[ring->id] = ring->tail;
+}
+
+
+static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
+					   struct drm_i915_error_state *error,
+					   struct drm_i915_error_ring *ering)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_gem_object *obj;
+
+	/* Currently render ring is the only HW context user */
+	if (ring->id != RCS || !error->ccid)
+		return;
+
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+		if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) {
+			ering->ctx = i915_error_object_create_sized(dev_priv,
+								    obj, 1);
+			break;
+		}
+	}
+}
+
+static void i915_gem_record_rings(struct drm_device *dev,
+				  struct drm_i915_error_state *error)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	struct drm_i915_gem_request *request;
+	int i, count;
+
+	for_each_ring(ring, dev_priv, i) {
+		i915_record_ring_state(dev, error, ring);
+
+		error->ring[i].batchbuffer =
+			i915_error_first_batchbuffer(dev_priv, ring);
+
+		error->ring[i].ringbuffer =
+			i915_error_object_create(dev_priv, ring->obj);
+
+
+		i915_gem_record_active_context(ring, error, &error->ring[i]);
+
+		count = 0;
+		list_for_each_entry(request, &ring->request_list, list)
+			count++;
+
+		error->ring[i].num_requests = count;
+		error->ring[i].requests =
+			kmalloc(count*sizeof(struct drm_i915_error_request),
+				GFP_ATOMIC);
+		if (error->ring[i].requests == NULL) {
+			error->ring[i].num_requests = 0;
+			continue;
+		}
+
+		count = 0;
+		list_for_each_entry(request, &ring->request_list, list) {
+			struct drm_i915_error_request *erq;
+
+			erq = &error->ring[i].requests[count++];
+			erq->seqno = request->seqno;
+			erq->jiffies = request->emitted_jiffies;
+			erq->tail = request->tail;
+		}
+	}
+}
+
+/* FIXME: Since pin count/bound list is global, we duplicate what we capture per
+ * VM.
+ */
+static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
+				struct drm_i915_error_state *error,
+				struct i915_address_space *vm,
+				const int ndx)
+{
+	struct drm_i915_error_buffer *active_bo = NULL, *pinned_bo = NULL;
+	struct drm_i915_gem_object *obj;
+	struct i915_vma *vma;
+	int i;
+
+	i = 0;
+	list_for_each_entry(vma, &vm->active_list, mm_list)
+		i++;
+	error->active_bo_count[ndx] = i;
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
+		if (obj->pin_count)
+			i++;
+	error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
+
+	if (i) {
+		active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC);
+		if (active_bo)
+			pinned_bo = active_bo + error->active_bo_count[ndx];
+	}
+
+	if (active_bo)
+		error->active_bo_count[ndx] =
+			capture_active_bo(active_bo,
+					  error->active_bo_count[ndx],
+					  &vm->active_list);
+
+	if (pinned_bo)
+		error->pinned_bo_count[ndx] =
+			capture_pinned_bo(pinned_bo,
+					  error->pinned_bo_count[ndx],
+					  &dev_priv->mm.bound_list);
+	error->active_bo[ndx] = active_bo;
+	error->pinned_bo[ndx] = pinned_bo;
+}
+
+static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
+				     struct drm_i915_error_state *error)
+{
+	struct i915_address_space *vm;
+	int cnt = 0, i = 0;
+
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+		cnt++;
+
+	if (WARN(cnt > 1, "Multiple VMs not yet supported\n"))
+		cnt = 1;
+
+	vm = &dev_priv->gtt.base;
+
+	error->active_bo = kcalloc(cnt, sizeof(*error->active_bo), GFP_ATOMIC);
+	error->pinned_bo = kcalloc(cnt, sizeof(*error->pinned_bo), GFP_ATOMIC);
+	error->active_bo_count = kcalloc(cnt, sizeof(*error->active_bo_count),
+					 GFP_ATOMIC);
+	error->pinned_bo_count = kcalloc(cnt, sizeof(*error->pinned_bo_count),
+					 GFP_ATOMIC);
+
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+		i915_gem_capture_vm(dev_priv, error, vm, i++);
+}
+
+/**
+ * i915_capture_error_state - capture an error record for later analysis
+ * @dev: drm device
+ *
+ * Should be called when an error is detected (either a hang or an error
+ * interrupt) to capture error state from the time of the error.  Fills
+ * out a structure which becomes available in debugfs for user level tools
+ * to pick up.
+ */
+void i915_capture_error_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error;
+	unsigned long flags;
+	int pipe;
+
+	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
+	error = dev_priv->gpu_error.first_error;
+	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
+	if (error)
+		return;
+
+	/* Account for pipe specific data like PIPE*STAT */
+	error = kzalloc(sizeof(*error), GFP_ATOMIC);
+	if (!error) {
+		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
+		return;
+	}
+
+	DRM_INFO("capturing error event; look for more information in "
+		 "/sys/class/drm/card%d/error\n", dev->primary->index);
+
+	kref_init(&error->ref);
+	error->eir = I915_READ(EIR);
+	error->pgtbl_er = I915_READ(PGTBL_ER);
+	if (HAS_HW_CONTEXTS(dev))
+		error->ccid = I915_READ(CCID);
+
+	if (HAS_PCH_SPLIT(dev))
+		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
+	else if (IS_VALLEYVIEW(dev))
+		error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
+	else if (IS_GEN2(dev))
+		error->ier = I915_READ16(IER);
+	else
+		error->ier = I915_READ(IER);
+
+	if (INTEL_INFO(dev)->gen >= 6)
+		error->derrmr = I915_READ(DERRMR);
+
+	if (IS_VALLEYVIEW(dev))
+		error->forcewake = I915_READ(FORCEWAKE_VLV);
+	else if (INTEL_INFO(dev)->gen >= 7)
+		error->forcewake = I915_READ(FORCEWAKE_MT);
+	else if (INTEL_INFO(dev)->gen == 6)
+		error->forcewake = I915_READ(FORCEWAKE);
+
+	if (!HAS_PCH_SPLIT(dev))
+		for_each_pipe(pipe)
+			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
+
+	if (INTEL_INFO(dev)->gen >= 6) {
+		error->error = I915_READ(ERROR_GEN6);
+		error->done_reg = I915_READ(DONE_REG);
+	}
+
+	if (INTEL_INFO(dev)->gen == 7)
+		error->err_int = I915_READ(GEN7_ERR_INT);
+
+	i915_get_extra_instdone(dev, error->extra_instdone);
+
+	i915_gem_capture_buffers(dev_priv, error);
+	i915_gem_record_fences(dev, error);
+	i915_gem_record_rings(dev, error);
+
+	do_gettimeofday(&error->time);
+
+	error->overlay = intel_overlay_capture_error_state(dev);
+	error->display = intel_display_capture_error_state(dev);
+
+	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
+	if (dev_priv->gpu_error.first_error == NULL) {
+		dev_priv->gpu_error.first_error = error;
+		error = NULL;
+	}
+	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
+
+	if (error)
+		i915_error_state_free(&error->ref);
+}
+
+void i915_error_state_get(struct drm_device *dev,
+			  struct i915_error_state_file_priv *error_priv)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
+	error_priv->error = dev_priv->gpu_error.first_error;
+	if (error_priv->error)
+		kref_get(&error_priv->error->ref);
+	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
+
+}
+
+void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
+{
+	if (error_priv->error)
+		kref_put(&error_priv->error->ref, i915_error_state_free);
+}
+
+void i915_destroy_error_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
+	error = dev_priv->gpu_error.first_error;
+	dev_priv->gpu_error.first_error = NULL;
+	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
+
+	if (error)
+		kref_put(&error->ref, i915_error_state_free);
+}
+
+const char *i915_cache_level_str(int type)
+{
+	switch (type) {
+	case I915_CACHE_NONE: return " uncached";
+	case I915_CACHE_LLC: return " snooped or LLC";
+	case I915_CACHE_L3_LLC: return " L3+LLC";
+	default: return "";
+	}
+}
+
+/* NB: please notice the memset */
+void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
+
+	switch (INTEL_INFO(dev)->gen) {
+	case 2:
+	case 3:
+		instdone[0] = I915_READ(INSTDONE);
+		break;
+	case 4:
+	case 5:
+	case 6:
+		instdone[0] = I915_READ(INSTDONE_I965);
+		instdone[1] = I915_READ(INSTDONE1);
+		break;
+	default:
+		WARN_ONCE(1, "Unsupported platform\n");
+	case 7:
+		instdone[0] = I915_READ(GEN7_INSTDONE_1);
+		instdone[1] = I915_READ(GEN7_SC_INSTDONE);
+		instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
+		instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
+		break;
+	}
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3d92a7c..6a1c207 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -128,6 +128,8 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
 	enum pipe pipe;
 	struct intel_crtc *crtc;
 
+	assert_spin_locked(&dev_priv->irq_lock);
+
 	for_each_pipe(pipe) {
 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
@@ -152,38 +154,66 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
 }
 
 static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
-						  bool enable)
+						  enum pipe pipe, bool enable)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	if (enable) {
+		I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
+
 		if (!ivb_can_enable_err_int(dev))
 			return;
 
-		I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN_A |
-					 ERR_INT_FIFO_UNDERRUN_B |
-					 ERR_INT_FIFO_UNDERRUN_C);
-
 		ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
 	} else {
+		bool was_enabled = !(I915_READ(DEIMR) & DE_ERR_INT_IVB);
+
+		/* Change the state _after_ we've read out the current one. */
 		ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
+
+		if (!was_enabled &&
+		    (I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe))) {
+			DRM_DEBUG_KMS("uncleared fifo underrun on pipe %c\n",
+				      pipe_name(pipe));
+		}
 	}
 }
 
-static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
+/**
+ * ibx_display_interrupt_update - update SDEIMR
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
+					 uint32_t interrupt_mask,
+					 uint32_t enabled_irq_mask)
+{
+	uint32_t sdeimr = I915_READ(SDEIMR);
+	sdeimr &= ~interrupt_mask;
+	sdeimr |= (~enabled_irq_mask & interrupt_mask);
+
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	I915_WRITE(SDEIMR, sdeimr);
+	POSTING_READ(SDEIMR);
+}
+#define ibx_enable_display_interrupt(dev_priv, bits) \
+	ibx_display_interrupt_update((dev_priv), (bits), (bits))
+#define ibx_disable_display_interrupt(dev_priv, bits) \
+	ibx_display_interrupt_update((dev_priv), (bits), 0)
+
+static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
+					    enum transcoder pch_transcoder,
 					    bool enable)
 {
-	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t bit = (crtc->pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
-						SDE_TRANSB_FIFO_UNDER;
+	uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
+		       SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
 
 	if (enable)
-		I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~bit);
+		ibx_enable_display_interrupt(dev_priv, bit);
 	else
-		I915_WRITE(SDEIMR, I915_READ(SDEIMR) | bit);
-
-	POSTING_READ(SDEIMR);
+		ibx_disable_display_interrupt(dev_priv, bit);
 }
 
 static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
@@ -193,19 +223,26 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (enable) {
+		I915_WRITE(SERR_INT,
+			   SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
+
 		if (!cpt_can_enable_serr_int(dev))
 			return;
 
-		I915_WRITE(SERR_INT, SERR_INT_TRANS_A_FIFO_UNDERRUN |
-				     SERR_INT_TRANS_B_FIFO_UNDERRUN |
-				     SERR_INT_TRANS_C_FIFO_UNDERRUN);
-
-		I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~SDE_ERROR_CPT);
+		ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
 	} else {
-		I915_WRITE(SDEIMR, I915_READ(SDEIMR) | SDE_ERROR_CPT);
-	}
+		uint32_t tmp = I915_READ(SERR_INT);
+		bool was_enabled = !(I915_READ(SDEIMR) & SDE_ERROR_CPT);
 
-	POSTING_READ(SDEIMR);
+		/* Change the state _after_ we've read out the current one. */
+		ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
+
+		if (!was_enabled &&
+		    (tmp & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder))) {
+			DRM_DEBUG_KMS("uncleared pch fifo underrun on pch transcoder %c\n",
+				      transcoder_name(pch_transcoder));
+		}
+	}
 }
 
 /**
@@ -243,7 +280,7 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 	if (IS_GEN5(dev) || IS_GEN6(dev))
 		ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
 	else if (IS_GEN7(dev))
-		ivybridge_set_fifo_underrun_reporting(dev, enable);
+		ivybridge_set_fifo_underrun_reporting(dev, pipe, enable);
 
 done:
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
@@ -269,29 +306,19 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 					   bool enable)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	enum pipe p;
-	struct drm_crtc *crtc;
-	struct intel_crtc *intel_crtc;
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	unsigned long flags;
 	bool ret;
 
-	if (HAS_PCH_LPT(dev)) {
-		crtc = NULL;
-		for_each_pipe(p) {
-			struct drm_crtc *c = dev_priv->pipe_to_crtc_mapping[p];
-			if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) {
-				crtc = c;
-				break;
-			}
-		}
-		if (!crtc) {
-			DRM_ERROR("PCH FIFO underrun, but no CRTC using the PCH found\n");
-			return false;
-		}
-	} else {
-		crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
-	}
-	intel_crtc = to_intel_crtc(crtc);
+	/*
+	 * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
+	 * has only one pch transcoder A that all pipes can use. To avoid racy
+	 * pch transcoder -> pipe lookups from interrupt code simply store the
+	 * underrun statistics in crtc A. Since we never expose this anywhere
+	 * nor use it outside of the fifo underrun code here using the "wrong"
+	 * crtc on LPT won't cause issues.
+	 */
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 
@@ -303,7 +330,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 	intel_crtc->pch_fifo_underrun_disabled = !enable;
 
 	if (HAS_PCH_IBX(dev))
-		ibx_set_fifo_underrun_reporting(intel_crtc, enable);
+		ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
 	else
 		cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
 
@@ -319,6 +346,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 	u32 reg = PIPESTAT(pipe);
 	u32 pipestat = I915_READ(reg) & 0x7fff0000;
 
+	assert_spin_locked(&dev_priv->irq_lock);
+
 	if ((pipestat & mask) == mask)
 		return;
 
@@ -334,6 +363,8 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 	u32 reg = PIPESTAT(pipe);
 	u32 pipestat = I915_READ(reg) & 0x7fff0000;
 
+	assert_spin_locked(&dev_priv->irq_lock);
+
 	if ((pipestat & mask) == 0)
 		return;
 
@@ -625,14 +656,13 @@ static void i915_hotplug_work_func(struct work_struct *work)
 		drm_kms_helper_hotplug_event(dev);
 }
 
-static void ironlake_handle_rps_change(struct drm_device *dev)
+static void ironlake_rps_change_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 busy_up, busy_down, max_avg, min_avg;
 	u8 new_delay;
-	unsigned long flags;
 
-	spin_lock_irqsave(&mchdev_lock, flags);
+	spin_lock(&mchdev_lock);
 
 	I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
 
@@ -660,7 +690,7 @@ static void ironlake_handle_rps_change(struct drm_device *dev)
 	if (ironlake_set_drps(dev, new_delay))
 		dev_priv->ips.cur_delay = new_delay;
 
-	spin_unlock_irqrestore(&mchdev_lock, flags);
+	spin_unlock(&mchdev_lock);
 
 	return;
 }
@@ -668,18 +698,13 @@ static void ironlake_handle_rps_change(struct drm_device *dev)
 static void notify_ring(struct drm_device *dev,
 			struct intel_ring_buffer *ring)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	if (ring->obj == NULL)
 		return;
 
 	trace_i915_gem_request_complete(ring, ring->get_seqno(ring, false));
 
 	wake_up_all(&ring->irq_queue);
-	if (i915_enable_hangcheck) {
-		mod_timer(&dev_priv->gpu_error.hangcheck_timer,
-			  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
-	}
+	i915_queue_hangcheck(dev);
 }
 
 static void gen6_pm_rps_work(struct work_struct *work)
@@ -689,13 +714,13 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	u32 pm_iir, pm_imr;
 	u8 new_delay;
 
-	spin_lock_irq(&dev_priv->rps.lock);
+	spin_lock_irq(&dev_priv->irq_lock);
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
 	pm_imr = I915_READ(GEN6_PMIMR);
 	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
 	I915_WRITE(GEN6_PMIMR, pm_imr & ~GEN6_PM_RPS_EVENTS);
-	spin_unlock_irq(&dev_priv->rps.lock);
+	spin_unlock_irq(&dev_priv->irq_lock);
 
 	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
 		return;
@@ -787,7 +812,7 @@ static void ivybridge_parity_work(struct work_struct *work)
 
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
-	parity_event[0] = "L3_PARITY_ERROR=1";
+	parity_event[0] = I915_L3_PARITY_UEVENT "=1";
 	parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
 	parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
 	parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
@@ -804,22 +829,32 @@ static void ivybridge_parity_work(struct work_struct *work)
 	kfree(parity_event[1]);
 }
 
-static void ivybridge_handle_parity_error(struct drm_device *dev)
+static void ivybridge_parity_error_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	unsigned long flags;
 
 	if (!HAS_L3_GPU_CACHE(dev))
 		return;
 
-	spin_lock_irqsave(&dev_priv->irq_lock, flags);
+	spin_lock(&dev_priv->irq_lock);
 	dev_priv->gt_irq_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+	spin_unlock(&dev_priv->irq_lock);
 
 	queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
 }
 
+static void ilk_gt_irq_handler(struct drm_device *dev,
+			       struct drm_i915_private *dev_priv,
+			       u32 gt_iir)
+{
+	if (gt_iir &
+	    (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
+		notify_ring(dev, &dev_priv->ring[RCS]);
+	if (gt_iir & ILK_BSD_USER_INTERRUPT)
+		notify_ring(dev, &dev_priv->ring[VCS]);
+}
+
 static void snb_gt_irq_handler(struct drm_device *dev,
 			       struct drm_i915_private *dev_priv,
 			       u32 gt_iir)
@@ -841,15 +876,13 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 	}
 
 	if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT)
-		ivybridge_handle_parity_error(dev);
+		ivybridge_parity_error_irq_handler(dev);
 }
 
 /* Legacy way of handling PM interrupts */
-static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
-				u32 pm_iir)
+static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv,
+				 u32 pm_iir)
 {
-	unsigned long flags;
-
 	/*
 	 * IIR bits should never already be set because IMR should
 	 * prevent an interrupt from being shown in IIR. The warning
@@ -860,11 +893,11 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
 	 * The mask bit in IMR is cleared by dev_priv->rps.work.
 	 */
 
-	spin_lock_irqsave(&dev_priv->rps.lock, flags);
+	spin_lock(&dev_priv->irq_lock);
 	dev_priv->rps.pm_iir |= pm_iir;
 	I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir);
 	POSTING_READ(GEN6_PMIMR);
-	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
+	spin_unlock(&dev_priv->irq_lock);
 
 	queue_work(dev_priv->wq, &dev_priv->rps.work);
 }
@@ -886,6 +919,10 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
 	spin_lock(&dev_priv->irq_lock);
 	for (i = 1; i < HPD_NUM_PINS; i++) {
 
+		WARN(((hpd[i] & hotplug_trigger) &&
+		      dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED),
+		     "Received HPD interrupt although disabled\n");
+
 		if (!(hpd[i] & hotplug_trigger) ||
 		    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
 			continue;
@@ -896,6 +933,7 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
 				   + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
 			dev_priv->hpd_stats[i].hpd_last_jiffies = jiffies;
 			dev_priv->hpd_stats[i].hpd_cnt = 0;
+			DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: 0\n", i);
 		} else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) {
 			dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
 			dev_priv->hpd_event_bits &= ~(1 << i);
@@ -903,6 +941,8 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
 			storm_detected = true;
 		} else {
 			dev_priv->hpd_stats[i].hpd_cnt++;
+			DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", i,
+				      dev_priv->hpd_stats[i].hpd_cnt);
 		}
 	}
 
@@ -928,7 +968,7 @@ static void dp_aux_irq_handler(struct drm_device *dev)
 	wake_up_all(&dev_priv->gmbus_wait_queue);
 }
 
-/* Unlike gen6_queue_rps_work() from which this function is originally derived,
+/* Unlike gen6_rps_irq_handler() from which this function is originally derived,
  * we must be able to deal with other PM interrupts. This is complicated because
  * of the way in which we use the masks to defer the RPS work (which for
  * posterity is necessary because of forcewake).
@@ -936,27 +976,23 @@ static void dp_aux_irq_handler(struct drm_device *dev)
 static void hsw_pm_irq_handler(struct drm_i915_private *dev_priv,
 			       u32 pm_iir)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev_priv->rps.lock, flags);
-	dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
-	if (dev_priv->rps.pm_iir) {
+	if (pm_iir & GEN6_PM_RPS_EVENTS) {
+		spin_lock(&dev_priv->irq_lock);
+		dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
 		I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir);
 		/* never want to mask useful interrupts. (also posting read) */
 		WARN_ON(I915_READ_NOTRACE(GEN6_PMIMR) & ~GEN6_PM_RPS_EVENTS);
-		/* TODO: if queue_work is slow, move it out of the spinlock */
+		spin_unlock(&dev_priv->irq_lock);
+
 		queue_work(dev_priv->wq, &dev_priv->rps.work);
 	}
-	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
 
-	if (pm_iir & ~GEN6_PM_RPS_EVENTS) {
-		if (pm_iir & PM_VEBOX_USER_INTERRUPT)
-			notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
+	if (pm_iir & PM_VEBOX_USER_INTERRUPT)
+		notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
 
-		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
-			DRM_ERROR("VEBOX CS error interrupt 0x%08x\n", pm_iir);
-			i915_handle_error(dev_priv->dev, false);
-		}
+	if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
+		DRM_ERROR("VEBOX CS error interrupt 0x%08x\n", pm_iir);
+		i915_handle_error(dev_priv->dev, false);
 	}
 }
 
@@ -1029,7 +1065,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 			gmbus_irq_handler(dev);
 
 		if (pm_iir & GEN6_PM_RPS_EVENTS)
-			gen6_queue_rps_work(dev_priv, pm_iir);
+			gen6_rps_irq_handler(dev_priv, pm_iir);
 
 		I915_WRITE(GTIIR, gt_iir);
 		I915_WRITE(GEN6_PMIIR, pm_iir);
@@ -1179,163 +1215,9 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
 		cpt_serr_int_handler(dev);
 }
 
-static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
-{
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier = 0;
-	irqreturn_t ret = IRQ_NONE;
-	int i;
-
-	atomic_inc(&dev_priv->irq_received);
-
-	/* We get interrupts on unclaimed registers, so check for this before we
-	 * do any I915_{READ,WRITE}. */
-	if (IS_HASWELL(dev) &&
-	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
-		DRM_ERROR("Unclaimed register before interrupt\n");
-		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-	}
-
-	/* disable master interrupt before clearing iir  */
-	de_ier = I915_READ(DEIER);
-	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
-
-	/* Disable south interrupts. We'll only write to SDEIIR once, so further
-	 * interrupts will will be stored on its back queue, and then we'll be
-	 * able to process them after we restore SDEIER (as soon as we restore
-	 * it, we'll get an interrupt if SDEIIR still has something to process
-	 * due to its back queue). */
-	if (!HAS_PCH_NOP(dev)) {
-		sde_ier = I915_READ(SDEIER);
-		I915_WRITE(SDEIER, 0);
-		POSTING_READ(SDEIER);
-	}
-
-	/* On Haswell, also mask ERR_INT because we don't want to risk
-	 * generating "unclaimed register" interrupts from inside the interrupt
-	 * handler. */
-	if (IS_HASWELL(dev)) {
-		spin_lock(&dev_priv->irq_lock);
-		ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
-		spin_unlock(&dev_priv->irq_lock);
-	}
-
-	gt_iir = I915_READ(GTIIR);
-	if (gt_iir) {
-		snb_gt_irq_handler(dev, dev_priv, gt_iir);
-		I915_WRITE(GTIIR, gt_iir);
-		ret = IRQ_HANDLED;
-	}
-
-	de_iir = I915_READ(DEIIR);
-	if (de_iir) {
-		if (de_iir & DE_ERR_INT_IVB)
-			ivb_err_int_handler(dev);
-
-		if (de_iir & DE_AUX_CHANNEL_A_IVB)
-			dp_aux_irq_handler(dev);
-
-		if (de_iir & DE_GSE_IVB)
-			intel_opregion_asle_intr(dev);
-
-		for (i = 0; i < 3; i++) {
-			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
-				drm_handle_vblank(dev, i);
-			if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
-				intel_prepare_page_flip(dev, i);
-				intel_finish_page_flip_plane(dev, i);
-			}
-		}
-
-		/* check event from PCH */
-		if (!HAS_PCH_NOP(dev) && (de_iir & DE_PCH_EVENT_IVB)) {
-			u32 pch_iir = I915_READ(SDEIIR);
-
-			cpt_irq_handler(dev, pch_iir);
-
-			/* clear PCH hotplug event before clear CPU irq */
-			I915_WRITE(SDEIIR, pch_iir);
-		}
-
-		I915_WRITE(DEIIR, de_iir);
-		ret = IRQ_HANDLED;
-	}
-
-	pm_iir = I915_READ(GEN6_PMIIR);
-	if (pm_iir) {
-		if (IS_HASWELL(dev))
-			hsw_pm_irq_handler(dev_priv, pm_iir);
-		else if (pm_iir & GEN6_PM_RPS_EVENTS)
-			gen6_queue_rps_work(dev_priv, pm_iir);
-		I915_WRITE(GEN6_PMIIR, pm_iir);
-		ret = IRQ_HANDLED;
-	}
-
-	if (IS_HASWELL(dev)) {
-		spin_lock(&dev_priv->irq_lock);
-		if (ivb_can_enable_err_int(dev))
-			ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
-		spin_unlock(&dev_priv->irq_lock);
-	}
-
-	I915_WRITE(DEIER, de_ier);
-	POSTING_READ(DEIER);
-	if (!HAS_PCH_NOP(dev)) {
-		I915_WRITE(SDEIER, sde_ier);
-		POSTING_READ(SDEIER);
-	}
-
-	return ret;
-}
-
-static void ilk_gt_irq_handler(struct drm_device *dev,
-			       struct drm_i915_private *dev_priv,
-			       u32 gt_iir)
-{
-	if (gt_iir &
-	    (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-		notify_ring(dev, &dev_priv->ring[RCS]);
-	if (gt_iir & ILK_BSD_USER_INTERRUPT)
-		notify_ring(dev, &dev_priv->ring[VCS]);
-}
-
-static irqreturn_t ironlake_irq_handler(int irq, void *arg)
+static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
 {
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	int ret = IRQ_NONE;
-	u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
-
-	atomic_inc(&dev_priv->irq_received);
-
-	/* disable master interrupt before clearing iir  */
-	de_ier = I915_READ(DEIER);
-	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
-	POSTING_READ(DEIER);
-
-	/* Disable south interrupts. We'll only write to SDEIIR once, so further
-	 * interrupts will will be stored on its back queue, and then we'll be
-	 * able to process them after we restore SDEIER (as soon as we restore
-	 * it, we'll get an interrupt if SDEIIR still has something to process
-	 * due to its back queue). */
-	sde_ier = I915_READ(SDEIER);
-	I915_WRITE(SDEIER, 0);
-	POSTING_READ(SDEIER);
-
-	de_iir = I915_READ(DEIIR);
-	gt_iir = I915_READ(GTIIR);
-	pm_iir = I915_READ(GEN6_PMIIR);
-
-	if (de_iir == 0 && gt_iir == 0 && (!IS_GEN6(dev) || pm_iir == 0))
-		goto done;
-
-	ret = IRQ_HANDLED;
-
-	if (IS_GEN5(dev))
-		ilk_gt_irq_handler(dev, dev_priv, gt_iir);
-	else
-		snb_gt_irq_handler(dev, dev_priv, gt_iir);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (de_iir & DE_AUX_CHANNEL_A)
 		dp_aux_irq_handler(dev);
@@ -1383,622 +1265,199 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 		I915_WRITE(SDEIIR, pch_iir);
 	}
 
-	if (IS_GEN5(dev) &&  de_iir & DE_PCU_EVENT)
-		ironlake_handle_rps_change(dev);
-
-	if (IS_GEN6(dev) && pm_iir & GEN6_PM_RPS_EVENTS)
-		gen6_queue_rps_work(dev_priv, pm_iir);
-
-	I915_WRITE(GTIIR, gt_iir);
-	I915_WRITE(DEIIR, de_iir);
-	I915_WRITE(GEN6_PMIIR, pm_iir);
-
-done:
-	I915_WRITE(DEIER, de_ier);
-	POSTING_READ(DEIER);
-	I915_WRITE(SDEIER, sde_ier);
-	POSTING_READ(SDEIER);
-
-	return ret;
-}
-
-/**
- * i915_error_work_func - do process context error handling work
- * @work: work struct
- *
- * Fire an error uevent so userspace can see that a hang or error
- * was detected.
- */
-static void i915_error_work_func(struct work_struct *work)
-{
-	struct i915_gpu_error *error = container_of(work, struct i915_gpu_error,
-						    work);
-	drm_i915_private_t *dev_priv = container_of(error, drm_i915_private_t,
-						    gpu_error);
-	struct drm_device *dev = dev_priv->dev;
-	struct intel_ring_buffer *ring;
-	char *error_event[] = { "ERROR=1", NULL };
-	char *reset_event[] = { "RESET=1", NULL };
-	char *reset_done_event[] = { "ERROR=0", NULL };
-	int i, ret;
-
-	kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
-
-	/*
-	 * Note that there's only one work item which does gpu resets, so we
-	 * need not worry about concurrent gpu resets potentially incrementing
-	 * error->reset_counter twice. We only need to take care of another
-	 * racing irq/hangcheck declaring the gpu dead for a second time. A
-	 * quick check for that is good enough: schedule_work ensures the
-	 * correct ordering between hang detection and this work item, and since
-	 * the reset in-progress bit is only ever set by code outside of this
-	 * work we don't need to worry about any other races.
-	 */
-	if (i915_reset_in_progress(error) && !i915_terminally_wedged(error)) {
-		DRM_DEBUG_DRIVER("resetting chip\n");
-		kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE,
-				   reset_event);
-
-		ret = i915_reset(dev);
-
-		if (ret == 0) {
-			/*
-			 * After all the gem state is reset, increment the reset
-			 * counter and wake up everyone waiting for the reset to
-			 * complete.
-			 *
-			 * Since unlock operations are a one-sided barrier only,
-			 * we need to insert a barrier here to order any seqno
-			 * updates before
-			 * the counter increment.
-			 */
-			smp_mb__before_atomic_inc();
-			atomic_inc(&dev_priv->gpu_error.reset_counter);
-
-			kobject_uevent_env(&dev->primary->kdev.kobj,
-					   KOBJ_CHANGE, reset_done_event);
-		} else {
-			atomic_set(&error->reset_counter, I915_WEDGED);
-		}
-
-		for_each_ring(ring, dev_priv, i)
-			wake_up_all(&ring->irq_queue);
-
-		intel_display_handle_reset(dev);
-
-		wake_up_all(&dev_priv->gpu_error.reset_queue);
-	}
+	if (IS_GEN5(dev) && de_iir & DE_PCU_EVENT)
+		ironlake_rps_change_irq_handler(dev);
 }
 
-/* NB: please notice the memset */
-static void i915_get_extra_instdone(struct drm_device *dev,
-				    uint32_t *instdone)
+static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
-
-	switch(INTEL_INFO(dev)->gen) {
-	case 2:
-	case 3:
-		instdone[0] = I915_READ(INSTDONE);
-		break;
-	case 4:
-	case 5:
-	case 6:
-		instdone[0] = I915_READ(INSTDONE_I965);
-		instdone[1] = I915_READ(INSTDONE1);
-		break;
-	default:
-		WARN_ONCE(1, "Unsupported platform\n");
-	case 7:
-		instdone[0] = I915_READ(GEN7_INSTDONE_1);
-		instdone[1] = I915_READ(GEN7_SC_INSTDONE);
-		instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
-		instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
-		break;
-	}
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct drm_i915_error_object *
-i915_error_object_create_sized(struct drm_i915_private *dev_priv,
-			       struct drm_i915_gem_object *src,
-			       const int num_pages)
-{
-	struct drm_i915_error_object *dst;
 	int i;
-	u32 reloc_offset;
-
-	if (src == NULL || src->pages == NULL)
-		return NULL;
-
-	dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
-	if (dst == NULL)
-		return NULL;
-
-	reloc_offset = src->gtt_offset;
-	for (i = 0; i < num_pages; i++) {
-		unsigned long flags;
-		void *d;
-
-		d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
-		if (d == NULL)
-			goto unwind;
-
-		local_irq_save(flags);
-		if (reloc_offset < dev_priv->gtt.mappable_end &&
-		    src->has_global_gtt_mapping) {
-			void __iomem *s;
-
-			/* Simply ignore tiling or any overlapping fence.
-			 * It's part of the error state, and this hopefully
-			 * captures what the GPU read.
-			 */
-
-			s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
-						     reloc_offset);
-			memcpy_fromio(d, s, PAGE_SIZE);
-			io_mapping_unmap_atomic(s);
-		} else if (src->stolen) {
-			unsigned long offset;
 
-			offset = dev_priv->mm.stolen_base;
-			offset += src->stolen->start;
-			offset += i << PAGE_SHIFT;
+	if (de_iir & DE_ERR_INT_IVB)
+		ivb_err_int_handler(dev);
 
-			memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE);
-		} else {
-			struct page *page;
-			void *s;
-
-			page = i915_gem_object_get_page(src, i);
-
-			drm_clflush_pages(&page, 1);
+	if (de_iir & DE_AUX_CHANNEL_A_IVB)
+		dp_aux_irq_handler(dev);
 
-			s = kmap_atomic(page);
-			memcpy(d, s, PAGE_SIZE);
-			kunmap_atomic(s);
+	if (de_iir & DE_GSE_IVB)
+		intel_opregion_asle_intr(dev);
 
-			drm_clflush_pages(&page, 1);
+	for (i = 0; i < 3; i++) {
+		if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
+			drm_handle_vblank(dev, i);
+		if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
+			intel_prepare_page_flip(dev, i);
+			intel_finish_page_flip_plane(dev, i);
 		}
-		local_irq_restore(flags);
-
-		dst->pages[i] = d;
-
-		reloc_offset += PAGE_SIZE;
-	}
-	dst->page_count = num_pages;
-	dst->gtt_offset = src->gtt_offset;
-
-	return dst;
-
-unwind:
-	while (i--)
-		kfree(dst->pages[i]);
-	kfree(dst);
-	return NULL;
-}
-#define i915_error_object_create(dev_priv, src) \
-	i915_error_object_create_sized((dev_priv), (src), \
-				       (src)->base.size>>PAGE_SHIFT)
-
-static void
-i915_error_object_free(struct drm_i915_error_object *obj)
-{
-	int page;
-
-	if (obj == NULL)
-		return;
-
-	for (page = 0; page < obj->page_count; page++)
-		kfree(obj->pages[page]);
-
-	kfree(obj);
-}
-
-void
-i915_error_state_free(struct kref *error_ref)
-{
-	struct drm_i915_error_state *error = container_of(error_ref,
-							  typeof(*error), ref);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
-		i915_error_object_free(error->ring[i].batchbuffer);
-		i915_error_object_free(error->ring[i].ringbuffer);
-		i915_error_object_free(error->ring[i].ctx);
-		kfree(error->ring[i].requests);
-	}
-
-	kfree(error->active_bo);
-	kfree(error->overlay);
-	kfree(error->display);
-	kfree(error);
-}
-static void capture_bo(struct drm_i915_error_buffer *err,
-		       struct drm_i915_gem_object *obj)
-{
-	err->size = obj->base.size;
-	err->name = obj->base.name;
-	err->rseqno = obj->last_read_seqno;
-	err->wseqno = obj->last_write_seqno;
-	err->gtt_offset = obj->gtt_offset;
-	err->read_domains = obj->base.read_domains;
-	err->write_domain = obj->base.write_domain;
-	err->fence_reg = obj->fence_reg;
-	err->pinned = 0;
-	if (obj->pin_count > 0)
-		err->pinned = 1;
-	if (obj->user_pin_count > 0)
-		err->pinned = -1;
-	err->tiling = obj->tiling_mode;
-	err->dirty = obj->dirty;
-	err->purgeable = obj->madv != I915_MADV_WILLNEED;
-	err->ring = obj->ring ? obj->ring->id : -1;
-	err->cache_level = obj->cache_level;
-}
-
-static u32 capture_active_bo(struct drm_i915_error_buffer *err,
-			     int count, struct list_head *head)
-{
-	struct drm_i915_gem_object *obj;
-	int i = 0;
-
-	list_for_each_entry(obj, head, mm_list) {
-		capture_bo(err++, obj);
-		if (++i == count)
-			break;
-	}
-
-	return i;
-}
-
-static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
-			     int count, struct list_head *head)
-{
-	struct drm_i915_gem_object *obj;
-	int i = 0;
-
-	list_for_each_entry(obj, head, global_list) {
-		if (obj->pin_count == 0)
-			continue;
-
-		capture_bo(err++, obj);
-		if (++i == count)
-			break;
-	}
-
-	return i;
-}
-
-static void i915_gem_record_fences(struct drm_device *dev,
-				   struct drm_i915_error_state *error)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-
-	/* Fences */
-	switch (INTEL_INFO(dev)->gen) {
-	case 7:
-	case 6:
-		for (i = 0; i < dev_priv->num_fence_regs; i++)
-			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
-		break;
-	case 5:
-	case 4:
-		for (i = 0; i < 16; i++)
-			error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
-		break;
-	case 3:
-		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-			for (i = 0; i < 8; i++)
-				error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
-	case 2:
-		for (i = 0; i < 8; i++)
-			error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
-		break;
-
-	default:
-		BUG();
-	}
-}
-
-static struct drm_i915_error_object *
-i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
-			     struct intel_ring_buffer *ring)
-{
-	struct drm_i915_gem_object *obj;
-	u32 seqno;
-
-	if (!ring->get_seqno)
-		return NULL;
-
-	if (HAS_BROKEN_CS_TLB(dev_priv->dev)) {
-		u32 acthd = I915_READ(ACTHD);
-
-		if (WARN_ON(ring->id != RCS))
-			return NULL;
-
-		obj = ring->private;
-		if (acthd >= obj->gtt_offset &&
-		    acthd < obj->gtt_offset + obj->base.size)
-			return i915_error_object_create(dev_priv, obj);
 	}
 
-	seqno = ring->get_seqno(ring, false);
-	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-		if (obj->ring != ring)
-			continue;
-
-		if (i915_seqno_passed(seqno, obj->last_read_seqno))
-			continue;
+	/* check event from PCH */
+	if (!HAS_PCH_NOP(dev) && (de_iir & DE_PCH_EVENT_IVB)) {
+		u32 pch_iir = I915_READ(SDEIIR);
 
-		if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
-			continue;
+		cpt_irq_handler(dev, pch_iir);
 
-		/* We need to copy these to an anonymous buffer as the simplest
-		 * method to avoid being overwritten by userspace.
-		 */
-		return i915_error_object_create(dev_priv, obj);
+		/* clear PCH hotplug event before clear CPU irq */
+		I915_WRITE(SDEIIR, pch_iir);
 	}
-
-	return NULL;
 }
 
-static void i915_record_ring_state(struct drm_device *dev,
-				   struct drm_i915_error_state *error,
-				   struct intel_ring_buffer *ring)
+static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (INTEL_INFO(dev)->gen >= 6) {
-		error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50);
-		error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
-		error->semaphore_mboxes[ring->id][0]
-			= I915_READ(RING_SYNC_0(ring->mmio_base));
-		error->semaphore_mboxes[ring->id][1]
-			= I915_READ(RING_SYNC_1(ring->mmio_base));
-		error->semaphore_seqno[ring->id][0] = ring->sync_seqno[0];
-		error->semaphore_seqno[ring->id][1] = ring->sync_seqno[1];
-	}
-
-	if (INTEL_INFO(dev)->gen >= 4) {
-		error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
-		error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
-		error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
-		error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
-		error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
-		if (ring->id == RCS)
-			error->bbaddr = I915_READ64(BB_ADDR);
-	} else {
-		error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
-		error->ipeir[ring->id] = I915_READ(IPEIR);
-		error->ipehr[ring->id] = I915_READ(IPEHR);
-		error->instdone[ring->id] = I915_READ(INSTDONE);
-	}
-
-	error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
-	error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
-	error->seqno[ring->id] = ring->get_seqno(ring, false);
-	error->acthd[ring->id] = intel_ring_get_active_head(ring);
-	error->head[ring->id] = I915_READ_HEAD(ring);
-	error->tail[ring->id] = I915_READ_TAIL(ring);
-	error->ctl[ring->id] = I915_READ_CTL(ring);
-
-	error->cpu_ring_head[ring->id] = ring->head;
-	error->cpu_ring_tail[ring->id] = ring->tail;
-}
+	struct drm_device *dev = (struct drm_device *) arg;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 de_iir, gt_iir, de_ier, sde_ier = 0;
+	irqreturn_t ret = IRQ_NONE;
 
+	atomic_inc(&dev_priv->irq_received);
 
-static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
-					   struct drm_i915_error_state *error,
-					   struct drm_i915_error_ring *ering)
-{
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	struct drm_i915_gem_object *obj;
+	/* We get interrupts on unclaimed registers, so check for this before we
+	 * do any I915_{READ,WRITE}. */
+	intel_uncore_check_errors(dev);
 
-	/* Currently render ring is the only HW context user */
-	if (ring->id != RCS || !error->ccid)
-		return;
+	/* disable master interrupt before clearing iir  */
+	de_ier = I915_READ(DEIER);
+	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
+	POSTING_READ(DEIER);
 
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
-		if ((error->ccid & PAGE_MASK) == obj->gtt_offset) {
-			ering->ctx = i915_error_object_create_sized(dev_priv,
-								    obj, 1);
-		}
+	/* Disable south interrupts. We'll only write to SDEIIR once, so further
+	 * interrupts will will be stored on its back queue, and then we'll be
+	 * able to process them after we restore SDEIER (as soon as we restore
+	 * it, we'll get an interrupt if SDEIIR still has something to process
+	 * due to its back queue). */
+	if (!HAS_PCH_NOP(dev)) {
+		sde_ier = I915_READ(SDEIER);
+		I915_WRITE(SDEIER, 0);
+		POSTING_READ(SDEIER);
 	}
-}
-
-static void i915_gem_record_rings(struct drm_device *dev,
-				  struct drm_i915_error_state *error)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ring_buffer *ring;
-	struct drm_i915_gem_request *request;
-	int i, count;
-
-	for_each_ring(ring, dev_priv, i) {
-		i915_record_ring_state(dev, error, ring);
-
-		error->ring[i].batchbuffer =
-			i915_error_first_batchbuffer(dev_priv, ring);
-
-		error->ring[i].ringbuffer =
-			i915_error_object_create(dev_priv, ring->obj);
 
+	/* On Haswell, also mask ERR_INT because we don't want to risk
+	 * generating "unclaimed register" interrupts from inside the interrupt
+	 * handler. */
+	if (IS_HASWELL(dev)) {
+		spin_lock(&dev_priv->irq_lock);
+		ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
+		spin_unlock(&dev_priv->irq_lock);
+	}
 
-		i915_gem_record_active_context(ring, error, &error->ring[i]);
+	gt_iir = I915_READ(GTIIR);
+	if (gt_iir) {
+		if (INTEL_INFO(dev)->gen >= 6)
+			snb_gt_irq_handler(dev, dev_priv, gt_iir);
+		else
+			ilk_gt_irq_handler(dev, dev_priv, gt_iir);
+		I915_WRITE(GTIIR, gt_iir);
+		ret = IRQ_HANDLED;
+	}
 
-		count = 0;
-		list_for_each_entry(request, &ring->request_list, list)
-			count++;
+	de_iir = I915_READ(DEIIR);
+	if (de_iir) {
+		if (INTEL_INFO(dev)->gen >= 7)
+			ivb_display_irq_handler(dev, de_iir);
+		else
+			ilk_display_irq_handler(dev, de_iir);
+		I915_WRITE(DEIIR, de_iir);
+		ret = IRQ_HANDLED;
+	}
 
-		error->ring[i].num_requests = count;
-		error->ring[i].requests =
-			kmalloc(count*sizeof(struct drm_i915_error_request),
-				GFP_ATOMIC);
-		if (error->ring[i].requests == NULL) {
-			error->ring[i].num_requests = 0;
-			continue;
+	if (INTEL_INFO(dev)->gen >= 6) {
+		u32 pm_iir = I915_READ(GEN6_PMIIR);
+		if (pm_iir) {
+			if (IS_HASWELL(dev))
+				hsw_pm_irq_handler(dev_priv, pm_iir);
+			else if (pm_iir & GEN6_PM_RPS_EVENTS)
+				gen6_rps_irq_handler(dev_priv, pm_iir);
+			I915_WRITE(GEN6_PMIIR, pm_iir);
+			ret = IRQ_HANDLED;
 		}
+	}
 
-		count = 0;
-		list_for_each_entry(request, &ring->request_list, list) {
-			struct drm_i915_error_request *erq;
+	if (IS_HASWELL(dev)) {
+		spin_lock(&dev_priv->irq_lock);
+		if (ivb_can_enable_err_int(dev))
+			ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
+		spin_unlock(&dev_priv->irq_lock);
+	}
 
-			erq = &error->ring[i].requests[count++];
-			erq->seqno = request->seqno;
-			erq->jiffies = request->emitted_jiffies;
-			erq->tail = request->tail;
-		}
+	I915_WRITE(DEIER, de_ier);
+	POSTING_READ(DEIER);
+	if (!HAS_PCH_NOP(dev)) {
+		I915_WRITE(SDEIER, sde_ier);
+		POSTING_READ(SDEIER);
 	}
+
+	return ret;
 }
 
 /**
- * i915_capture_error_state - capture an error record for later analysis
- * @dev: drm device
+ * i915_error_work_func - do process context error handling work
+ * @work: work struct
  *
- * Should be called when an error is detected (either a hang or an error
- * interrupt) to capture error state from the time of the error.  Fills
- * out a structure which becomes available in debugfs for user level tools
- * to pick up.
+ * Fire an error uevent so userspace can see that a hang or error
+ * was detected.
  */
-static void i915_capture_error_state(struct drm_device *dev)
+static void i915_error_work_func(struct work_struct *work)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj;
-	struct drm_i915_error_state *error;
-	unsigned long flags;
-	int i, pipe;
-
-	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
-	error = dev_priv->gpu_error.first_error;
-	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
-	if (error)
-		return;
-
-	/* Account for pipe specific data like PIPE*STAT */
-	error = kzalloc(sizeof(*error), GFP_ATOMIC);
-	if (!error) {
-		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
-		return;
-	}
-
-	DRM_INFO("capturing error event; look for more information in "
-		 "/sys/kernel/debug/dri/%d/i915_error_state\n",
-		 dev->primary->index);
-
-	kref_init(&error->ref);
-	error->eir = I915_READ(EIR);
-	error->pgtbl_er = I915_READ(PGTBL_ER);
-	if (HAS_HW_CONTEXTS(dev))
-		error->ccid = I915_READ(CCID);
-
-	if (HAS_PCH_SPLIT(dev))
-		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
-	else if (IS_VALLEYVIEW(dev))
-		error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
-	else if (IS_GEN2(dev))
-		error->ier = I915_READ16(IER);
-	else
-		error->ier = I915_READ(IER);
-
-	if (INTEL_INFO(dev)->gen >= 6)
-		error->derrmr = I915_READ(DERRMR);
-
-	if (IS_VALLEYVIEW(dev))
-		error->forcewake = I915_READ(FORCEWAKE_VLV);
-	else if (INTEL_INFO(dev)->gen >= 7)
-		error->forcewake = I915_READ(FORCEWAKE_MT);
-	else if (INTEL_INFO(dev)->gen == 6)
-		error->forcewake = I915_READ(FORCEWAKE);
-
-	if (!HAS_PCH_SPLIT(dev))
-		for_each_pipe(pipe)
-			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
-
-	if (INTEL_INFO(dev)->gen >= 6) {
-		error->error = I915_READ(ERROR_GEN6);
-		error->done_reg = I915_READ(DONE_REG);
-	}
-
-	if (INTEL_INFO(dev)->gen == 7)
-		error->err_int = I915_READ(GEN7_ERR_INT);
-
-	i915_get_extra_instdone(dev, error->extra_instdone);
-
-	i915_gem_record_fences(dev, error);
-	i915_gem_record_rings(dev, error);
+	struct i915_gpu_error *error = container_of(work, struct i915_gpu_error,
+						    work);
+	drm_i915_private_t *dev_priv = container_of(error, drm_i915_private_t,
+						    gpu_error);
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_ring_buffer *ring;
+	char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
+	char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
+	char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
+	int i, ret;
 
-	/* Record buffers on the active and pinned lists. */
-	error->active_bo = NULL;
-	error->pinned_bo = NULL;
+	kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
 
-	i = 0;
-	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
-		i++;
-	error->active_bo_count = i;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
-		if (obj->pin_count)
-			i++;
-	error->pinned_bo_count = i - error->active_bo_count;
+	/*
+	 * Note that there's only one work item which does gpu resets, so we
+	 * need not worry about concurrent gpu resets potentially incrementing
+	 * error->reset_counter twice. We only need to take care of another
+	 * racing irq/hangcheck declaring the gpu dead for a second time. A
+	 * quick check for that is good enough: schedule_work ensures the
+	 * correct ordering between hang detection and this work item, and since
+	 * the reset in-progress bit is only ever set by code outside of this
+	 * work we don't need to worry about any other races.
+	 */
+	if (i915_reset_in_progress(error) && !i915_terminally_wedged(error)) {
+		DRM_DEBUG_DRIVER("resetting chip\n");
+		kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE,
+				   reset_event);
 
-	error->active_bo = NULL;
-	error->pinned_bo = NULL;
-	if (i) {
-		error->active_bo = kmalloc(sizeof(*error->active_bo)*i,
-					   GFP_ATOMIC);
-		if (error->active_bo)
-			error->pinned_bo =
-				error->active_bo + error->active_bo_count;
-	}
+		ret = i915_reset(dev);
 
-	if (error->active_bo)
-		error->active_bo_count =
-			capture_active_bo(error->active_bo,
-					  error->active_bo_count,
-					  &dev_priv->mm.active_list);
+		if (ret == 0) {
+			/*
+			 * After all the gem state is reset, increment the reset
+			 * counter and wake up everyone waiting for the reset to
+			 * complete.
+			 *
+			 * Since unlock operations are a one-sided barrier only,
+			 * we need to insert a barrier here to order any seqno
+			 * updates before
+			 * the counter increment.
+			 */
+			smp_mb__before_atomic_inc();
+			atomic_inc(&dev_priv->gpu_error.reset_counter);
 
-	if (error->pinned_bo)
-		error->pinned_bo_count =
-			capture_pinned_bo(error->pinned_bo,
-					  error->pinned_bo_count,
-					  &dev_priv->mm.bound_list);
+			kobject_uevent_env(&dev->primary->kdev.kobj,
+					   KOBJ_CHANGE, reset_done_event);
+		} else {
+			atomic_set(&error->reset_counter, I915_WEDGED);
+		}
 
-	do_gettimeofday(&error->time);
+		for_each_ring(ring, dev_priv, i)
+			wake_up_all(&ring->irq_queue);
 
-	error->overlay = intel_overlay_capture_error_state(dev);
-	error->display = intel_display_capture_error_state(dev);
+		intel_display_handle_reset(dev);
 
-	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
-	if (dev_priv->gpu_error.first_error == NULL) {
-		dev_priv->gpu_error.first_error = error;
-		error = NULL;
+		wake_up_all(&dev_priv->gpu_error.reset_queue);
 	}
-	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
-
-	if (error)
-		i915_error_state_free(&error->ref);
 }
 
-void i915_destroy_error_state(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_error_state *error;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
-	error = dev_priv->gpu_error.first_error;
-	dev_priv->gpu_error.first_error = NULL;
-	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
-
-	if (error)
-		kref_put(&error->ref, i915_error_state_free);
-}
-#else
-#define i915_capture_error_state(x)
-#endif
-
 static void i915_report_and_clear_eir(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2155,10 +1614,10 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in
 	if (INTEL_INFO(dev)->gen >= 4) {
 		int dspsurf = DSPSURF(intel_crtc->plane);
 		stall_detected = I915_HI_DISPBASE(I915_READ(dspsurf)) ==
-					obj->gtt_offset;
+					i915_gem_obj_ggtt_offset(obj);
 	} else {
 		int dspaddr = DSPADDR(intel_crtc->plane);
-		stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
+		stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) +
 							crtc->y * crtc->fb->pitches[0] +
 							crtc->x * crtc->fb->bits_per_pixel/8);
 	}
@@ -2202,29 +1661,14 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
+	uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) :
+						     DE_PIPE_VBLANK_ILK(pipe);
 
 	if (!i915_pipe_enabled(dev, pipe))
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
-				    DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
-	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
-	return 0;
-}
-
-static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	unsigned long irqflags;
-
-	if (!i915_pipe_enabled(dev, pipe))
-		return -EINVAL;
-
-	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	ironlake_enable_display_irq(dev_priv,
-				    DE_PIPEA_VBLANK_IVB << (5 * pipe));
+	ironlake_enable_display_irq(dev_priv, bit);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -2275,21 +1719,11 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
+	uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) :
+						     DE_PIPE_VBLANK_ILK(pipe);
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
-				     DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
-	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-}
-
-static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	unsigned long irqflags;
-
-	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	ironlake_disable_display_irq(dev_priv,
-				     DE_PIPEA_VBLANK_IVB << (pipe * 5));
+	ironlake_disable_display_irq(dev_priv, bit);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -2536,9 +1970,17 @@ void i915_hangcheck_elapsed(unsigned long data)
 	if (busy_count)
 		/* Reset timer case chip hangs without another request
 		 * being added */
-		mod_timer(&dev_priv->gpu_error.hangcheck_timer,
-			  round_jiffies_up(jiffies +
-					   DRM_I915_HANGCHECK_JIFFIES));
+		i915_queue_hangcheck(dev);
+}
+
+void i915_queue_hangcheck(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (!i915_enable_hangcheck)
+		return;
+
+	mod_timer(&dev_priv->gpu_error.hangcheck_timer,
+		  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
 }
 
 static void ibx_irq_preinstall(struct drm_device *dev)
@@ -2560,31 +2002,26 @@ static void ibx_irq_preinstall(struct drm_device *dev)
 	POSTING_READ(SDEIER);
 }
 
-/* drm_dma.h hooks
-*/
-static void ironlake_irq_preinstall(struct drm_device *dev)
+static void gen5_gt_irq_preinstall(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
-	atomic_set(&dev_priv->irq_received, 0);
-
-	I915_WRITE(HWSTAM, 0xeffe);
-
-	/* XXX hotplug from PCH */
-
-	I915_WRITE(DEIMR, 0xffffffff);
-	I915_WRITE(DEIER, 0x0);
-	POSTING_READ(DEIER);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* and GT */
 	I915_WRITE(GTIMR, 0xffffffff);
 	I915_WRITE(GTIER, 0x0);
 	POSTING_READ(GTIER);
 
-	ibx_irq_preinstall(dev);
+	if (INTEL_INFO(dev)->gen >= 6) {
+		/* and PM */
+		I915_WRITE(GEN6_PMIMR, 0xffffffff);
+		I915_WRITE(GEN6_PMIER, 0x0);
+		POSTING_READ(GEN6_PMIER);
+	}
 }
 
-static void ivybridge_irq_preinstall(struct drm_device *dev)
+/* drm_dma.h hooks
+*/
+static void ironlake_irq_preinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -2592,21 +2029,11 @@ static void ivybridge_irq_preinstall(struct drm_device *dev)
 
 	I915_WRITE(HWSTAM, 0xeffe);
 
-	/* XXX hotplug from PCH */
-
 	I915_WRITE(DEIMR, 0xffffffff);
 	I915_WRITE(DEIER, 0x0);
 	POSTING_READ(DEIER);
 
-	/* and GT */
-	I915_WRITE(GTIMR, 0xffffffff);
-	I915_WRITE(GTIER, 0x0);
-	POSTING_READ(GTIER);
-
-	/* Power management */
-	I915_WRITE(GEN6_PMIMR, 0xffffffff);
-	I915_WRITE(GEN6_PMIER, 0x0);
-	POSTING_READ(GEN6_PMIER);
+	gen5_gt_irq_preinstall(dev);
 
 	ibx_irq_preinstall(dev);
 }
@@ -2627,9 +2054,8 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 	/* and GT */
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, 0xffffffff);
-	I915_WRITE(GTIER, 0x0);
-	POSTING_READ(GTIER);
+
+	gen5_gt_irq_preinstall(dev);
 
 	I915_WRITE(DPINVGTT, 0xff);
 
@@ -2648,22 +2074,21 @@ static void ibx_hpd_irq_setup(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct intel_encoder *intel_encoder;
-	u32 mask = ~I915_READ(SDEIMR);
-	u32 hotplug;
+	u32 hotplug_irqs, hotplug, enabled_irqs = 0;
 
 	if (HAS_PCH_IBX(dev)) {
-		mask &= ~SDE_HOTPLUG_MASK;
+		hotplug_irqs = SDE_HOTPLUG_MASK;
 		list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
 			if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-				mask |= hpd_ibx[intel_encoder->hpd_pin];
+				enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
 	} else {
-		mask &= ~SDE_HOTPLUG_MASK_CPT;
+		hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
 		list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
 			if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-				mask |= hpd_cpt[intel_encoder->hpd_pin];
+				enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin];
 	}
 
-	I915_WRITE(SDEIMR, ~mask);
+	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
 
 	/*
 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
@@ -2700,123 +2125,102 @@ static void ibx_irq_postinstall(struct drm_device *dev)
 	I915_WRITE(SDEIMR, ~mask);
 }
 
-static int ironlake_irq_postinstall(struct drm_device *dev)
+static void gen5_gt_irq_postinstall(struct drm_device *dev)
 {
-	unsigned long irqflags;
-
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	/* enable kind of interrupts always enabled */
-	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
-			   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
-			   DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN |
-			   DE_PIPEA_FIFO_UNDERRUN | DE_POISON;
-	u32 gt_irqs;
-
-	dev_priv->irq_mask = ~display_mask;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pm_irqs, gt_irqs;
 
-	/* should always can generate irq */
-	I915_WRITE(DEIIR, I915_READ(DEIIR));
-	I915_WRITE(DEIMR, dev_priv->irq_mask);
-	I915_WRITE(DEIER, display_mask |
-			  DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT);
-	POSTING_READ(DEIER);
+	pm_irqs = gt_irqs = 0;
 
 	dev_priv->gt_irq_mask = ~0;
+	if (HAS_L3_GPU_CACHE(dev)) {
+		/* L3 parity interrupt is always unmasked. */
+		dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+		gt_irqs |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+	}
 
-	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-
-	gt_irqs = GT_RENDER_USER_INTERRUPT;
-
-	if (IS_GEN6(dev))
-		gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
-	else
+	gt_irqs |= GT_RENDER_USER_INTERRUPT;
+	if (IS_GEN5(dev)) {
 		gt_irqs |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT |
 			   ILK_BSD_USER_INTERRUPT;
+	} else {
+		gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
+	}
 
+	I915_WRITE(GTIIR, I915_READ(GTIIR));
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 	I915_WRITE(GTIER, gt_irqs);
 	POSTING_READ(GTIER);
 
-	ibx_irq_postinstall(dev);
+	if (INTEL_INFO(dev)->gen >= 6) {
+		pm_irqs |= GEN6_PM_RPS_EVENTS;
 
-	if (IS_IRONLAKE_M(dev)) {
-		/* Enable PCU event interrupts
-		 *
-		 * spinlocking not required here for correctness since interrupt
-		 * setup is guaranteed to run in single-threaded context. But we
-		 * need it to make the assert_spin_locked happy. */
-		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-		ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-	}
+		if (HAS_VEBOX(dev))
+			pm_irqs |= PM_VEBOX_USER_INTERRUPT;
 
-	return 0;
+		I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+		I915_WRITE(GEN6_PMIMR, 0xffffffff);
+		I915_WRITE(GEN6_PMIER, pm_irqs);
+		POSTING_READ(GEN6_PMIER);
+	}
 }
 
-static int ivybridge_irq_postinstall(struct drm_device *dev)
+static int ironlake_irq_postinstall(struct drm_device *dev)
 {
+	unsigned long irqflags;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	/* enable kind of interrupts always enabled */
-	u32 display_mask =
-		DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | DE_PCH_EVENT_IVB |
-		DE_PLANEC_FLIP_DONE_IVB |
-		DE_PLANEB_FLIP_DONE_IVB |
-		DE_PLANEA_FLIP_DONE_IVB |
-		DE_AUX_CHANNEL_A_IVB |
-		DE_ERR_INT_IVB;
-	u32 pm_irqs = GEN6_PM_RPS_EVENTS;
-	u32 gt_irqs;
+	u32 display_mask, extra_mask;
+
+	if (INTEL_INFO(dev)->gen >= 7) {
+		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
+				DE_PCH_EVENT_IVB | DE_PLANEC_FLIP_DONE_IVB |
+				DE_PLANEB_FLIP_DONE_IVB |
+				DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB |
+				DE_ERR_INT_IVB);
+		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
+			      DE_PIPEA_VBLANK_IVB);
+
+		I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
+	} else {
+		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
+				DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
+				DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN |
+				DE_PIPEA_FIFO_UNDERRUN | DE_POISON);
+		extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT;
+	}
 
 	dev_priv->irq_mask = ~display_mask;
 
 	/* should always can generate irq */
-	I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
 	I915_WRITE(DEIIR, I915_READ(DEIIR));
 	I915_WRITE(DEIMR, dev_priv->irq_mask);
-	I915_WRITE(DEIER,
-		   display_mask |
-		   DE_PIPEC_VBLANK_IVB |
-		   DE_PIPEB_VBLANK_IVB |
-		   DE_PIPEA_VBLANK_IVB);
+	I915_WRITE(DEIER, display_mask | extra_mask);
 	POSTING_READ(DEIER);
 
-	dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
-
-	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-
-	gt_irqs = GT_RENDER_USER_INTERRUPT | GT_BSD_USER_INTERRUPT |
-		  GT_BLT_USER_INTERRUPT | GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
-	I915_WRITE(GTIER, gt_irqs);
-	POSTING_READ(GTIER);
-
-	I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
-	if (HAS_VEBOX(dev))
-		pm_irqs |= PM_VEBOX_USER_INTERRUPT |
-			PM_VEBOX_CS_ERROR_INTERRUPT;
-
-	/* Our enable/disable rps functions may touch these registers so
-	 * make sure to set a known state for only the non-RPS bits.
-	 * The RMW is extra paranoia since this should be called after being set
-	 * to a known state in preinstall.
-	 * */
-	I915_WRITE(GEN6_PMIMR,
-		   (I915_READ(GEN6_PMIMR) | ~GEN6_PM_RPS_EVENTS) & ~pm_irqs);
-	I915_WRITE(GEN6_PMIER,
-		   (I915_READ(GEN6_PMIER) & GEN6_PM_RPS_EVENTS) | pm_irqs);
-	POSTING_READ(GEN6_PMIER);
+	gen5_gt_irq_postinstall(dev);
 
 	ibx_irq_postinstall(dev);
 
+	if (IS_IRONLAKE_M(dev)) {
+		/* Enable PCU event interrupts
+		 *
+		 * spinlocking not required here for correctness since interrupt
+		 * setup is guaranteed to run in single-threaded context. But we
+		 * need it to make the assert_spin_locked happy. */
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+		ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	}
+
 	return 0;
 }
 
 static int valleyview_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 gt_irqs;
 	u32 enable_mask;
 	u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;
+	unsigned long irqflags;
 
 	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
 	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
@@ -2842,20 +2246,18 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	I915_WRITE(PIPESTAT(1), 0xffff);
 	POSTING_READ(VLV_IER);
 
+	/* Interrupt setup is already guaranteed to be single-threaded, this is
+	 * just to make the assert_spin_locked check happy. */
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	i915_enable_pipestat(dev_priv, 0, pipestat_enable);
 	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
 	i915_enable_pipestat(dev_priv, 1, pipestat_enable);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	I915_WRITE(VLV_IIR, 0xffffffff);
 	I915_WRITE(VLV_IIR, 0xffffffff);
 
-	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-
-	gt_irqs = GT_RENDER_USER_INTERRUPT | GT_BSD_USER_INTERRUPT |
-		GT_BLT_USER_INTERRUPT;
-	I915_WRITE(GTIER, gt_irqs);
-	POSTING_READ(GTIER);
+	gen5_gt_irq_postinstall(dev);
 
 	/* ack & enable invalid PTE error interrupts */
 #if 0 /* FIXME: add support to irq handler for checking these bits */
@@ -3323,6 +2725,7 @@ static int i965_irq_postinstall(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 enable_mask;
 	u32 error_mask;
+	unsigned long irqflags;
 
 	/* Unmask the interrupts that we always want on. */
 	dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
@@ -3341,7 +2744,11 @@ static int i965_irq_postinstall(struct drm_device *dev)
 	if (IS_G4X(dev))
 		enable_mask |= I915_BSD_USER_INTERRUPT;
 
+	/* Interrupt setup is already guaranteed to be single-threaded, this is
+	 * just to make the assert_spin_locked check happy. */
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	/*
 	 * Enable some error detection, note the instruction error mask
@@ -3616,15 +3023,6 @@ void intel_irq_init(struct drm_device *dev)
 		dev->driver->enable_vblank = valleyview_enable_vblank;
 		dev->driver->disable_vblank = valleyview_disable_vblank;
 		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
-	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
-		/* Share uninstall handlers with ILK/SNB */
-		dev->driver->irq_handler = ivybridge_irq_handler;
-		dev->driver->irq_preinstall = ivybridge_irq_preinstall;
-		dev->driver->irq_postinstall = ivybridge_irq_postinstall;
-		dev->driver->irq_uninstall = ironlake_irq_uninstall;
-		dev->driver->enable_vblank = ivybridge_enable_vblank;
-		dev->driver->disable_vblank = ivybridge_disable_vblank;
-		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev->driver->irq_handler = ironlake_irq_handler;
 		dev->driver->irq_preinstall = ironlake_irq_preinstall;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f2326fc..17f6252 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -61,6 +61,12 @@
 #define   GC_LOW_FREQUENCY_ENABLE	(1 << 7)
 #define   GC_DISPLAY_CLOCK_190_200_MHZ	(0 << 4)
 #define   GC_DISPLAY_CLOCK_333_MHZ	(4 << 4)
+#define   GC_DISPLAY_CLOCK_267_MHZ_PNV	(0 << 4)
+#define   GC_DISPLAY_CLOCK_333_MHZ_PNV	(1 << 4)
+#define   GC_DISPLAY_CLOCK_444_MHZ_PNV	(2 << 4)
+#define   GC_DISPLAY_CLOCK_200_MHZ_PNV	(5 << 4)
+#define   GC_DISPLAY_CLOCK_133_MHZ_PNV	(6 << 4)
+#define   GC_DISPLAY_CLOCK_167_MHZ_PNV	(7 << 4)
 #define   GC_DISPLAY_CLOCK_MASK		(7 << 4)
 #define   GM45_GC_RENDER_CLOCK_MASK	(0xf << 0)
 #define   GM45_GC_RENDER_CLOCK_266_MHZ	(8 << 0)
@@ -363,6 +369,7 @@
 #define PUNIT_REG_GPU_LFM			0xd3
 #define PUNIT_REG_GPU_FREQ_REQ			0xd4
 #define PUNIT_REG_GPU_FREQ_STS			0xd8
+#define   GENFREQSTATUS				(1<<0)
 #define PUNIT_REG_MEDIA_TURBO_FREQ_REQ		0xdc
 
 #define PUNIT_FUSE_BUS2				0xf6 /* bits 47:40 */
@@ -680,6 +687,7 @@
 #define   ERR_INT_FIFO_UNDERRUN_C	(1<<6)
 #define   ERR_INT_FIFO_UNDERRUN_B	(1<<3)
 #define   ERR_INT_FIFO_UNDERRUN_A	(1<<0)
+#define   ERR_INT_FIFO_UNDERRUN(pipe)	(1<<(pipe*3))
 
 #define FPGA_DBG		0x42300
 #define   FPGA_DBG_RM_NOCLAIM	(1<<31)
@@ -1125,7 +1133,8 @@
 #define _DPLL_B	(dev_priv->info->display_mmio_offset + 0x6018)
 #define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B)
 #define   DPLL_VCO_ENABLE		(1 << 31)
-#define   DPLL_DVO_HIGH_SPEED		(1 << 30)
+#define   DPLL_SDVO_HIGH_SPEED		(1 << 30)
+#define   DPLL_DVO_2X_MODE		(1 << 30)
 #define   DPLL_EXT_BUFFER_ENABLE_VLV	(1 << 30)
 #define   DPLL_SYNCLOCK_ENABLE		(1 << 29)
 #define   DPLL_REFA_CLK_ENABLE_VLV	(1 << 29)
@@ -1776,6 +1785,71 @@
 #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
 #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
+/* HSW eDP PSR registers */
+#define EDP_PSR_CTL				0x64800
+#define   EDP_PSR_ENABLE			(1<<31)
+#define   EDP_PSR_LINK_DISABLE			(0<<27)
+#define   EDP_PSR_LINK_STANDBY			(1<<27)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_MASK	(3<<25)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES	(0<<25)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES	(1<<25)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES	(2<<25)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES	(3<<25)
+#define   EDP_PSR_MAX_SLEEP_TIME_SHIFT		20
+#define   EDP_PSR_SKIP_AUX_EXIT			(1<<12)
+#define   EDP_PSR_TP1_TP2_SEL			(0<<11)
+#define   EDP_PSR_TP1_TP3_SEL			(1<<11)
+#define   EDP_PSR_TP2_TP3_TIME_500us		(0<<8)
+#define   EDP_PSR_TP2_TP3_TIME_100us		(1<<8)
+#define   EDP_PSR_TP2_TP3_TIME_2500us		(2<<8)
+#define   EDP_PSR_TP2_TP3_TIME_0us		(3<<8)
+#define   EDP_PSR_TP1_TIME_500us		(0<<4)
+#define   EDP_PSR_TP1_TIME_100us		(1<<4)
+#define   EDP_PSR_TP1_TIME_2500us		(2<<4)
+#define   EDP_PSR_TP1_TIME_0us			(3<<4)
+#define   EDP_PSR_IDLE_FRAME_SHIFT		0
+
+#define EDP_PSR_AUX_CTL			0x64810
+#define EDP_PSR_AUX_DATA1		0x64814
+#define   EDP_PSR_DPCD_COMMAND		0x80060000
+#define EDP_PSR_AUX_DATA2		0x64818
+#define   EDP_PSR_DPCD_NORMAL_OPERATION	(1<<24)
+#define EDP_PSR_AUX_DATA3		0x6481c
+#define EDP_PSR_AUX_DATA4		0x64820
+#define EDP_PSR_AUX_DATA5		0x64824
+
+#define EDP_PSR_STATUS_CTL			0x64840
+#define   EDP_PSR_STATUS_STATE_MASK		(7<<29)
+#define   EDP_PSR_STATUS_STATE_IDLE		(0<<29)
+#define   EDP_PSR_STATUS_STATE_SRDONACK		(1<<29)
+#define   EDP_PSR_STATUS_STATE_SRDENT		(2<<29)
+#define   EDP_PSR_STATUS_STATE_BUFOFF		(3<<29)
+#define   EDP_PSR_STATUS_STATE_BUFON		(4<<29)
+#define   EDP_PSR_STATUS_STATE_AUXACK		(5<<29)
+#define   EDP_PSR_STATUS_STATE_SRDOFFACK	(6<<29)
+#define   EDP_PSR_STATUS_LINK_MASK		(3<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_OFF		(0<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_ON		(1<<26)
+#define   EDP_PSR_STATUS_LINK_STANDBY		(2<<26)
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT	20
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK	0x1f
+#define   EDP_PSR_STATUS_COUNT_SHIFT		16
+#define   EDP_PSR_STATUS_COUNT_MASK		0xf
+#define   EDP_PSR_STATUS_AUX_ERROR		(1<<15)
+#define   EDP_PSR_STATUS_AUX_SENDING		(1<<12)
+#define   EDP_PSR_STATUS_SENDING_IDLE		(1<<9)
+#define   EDP_PSR_STATUS_SENDING_TP2_TP3	(1<<8)
+#define   EDP_PSR_STATUS_SENDING_TP1		(1<<4)
+#define   EDP_PSR_STATUS_IDLE_MASK		0xf
+
+#define EDP_PSR_PERF_CNT		0x64844
+#define   EDP_PSR_PERF_CNT_MASK		0xffffff
+
+#define EDP_PSR_DEBUG_CTL		0x64860
+#define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
+#define   EDP_PSR_DEBUG_MASK_MEMUP	(1<<26)
+#define   EDP_PSR_DEBUG_MASK_HPD	(1<<25)
+
 /* VGA port control */
 #define ADPA			0x61100
 #define PCH_ADPA                0xe1100
@@ -1856,10 +1930,16 @@
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2)
 
 #define PORT_HOTPLUG_STAT	(dev_priv->info->display_mmio_offset + 0x61114)
-/* HDMI/DP bits are gen4+ */
-#define   PORTB_HOTPLUG_LIVE_STATUS               (1 << 29)
+/*
+ * HDMI/DP bits are gen4+
+ *
+ * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused.
+ * Please check the detailed lore in the commit message for for experimental
+ * evidence.
+ */
+#define   PORTD_HOTPLUG_LIVE_STATUS               (1 << 29)
 #define   PORTC_HOTPLUG_LIVE_STATUS               (1 << 28)
-#define   PORTD_HOTPLUG_LIVE_STATUS               (1 << 27)
+#define   PORTB_HOTPLUG_LIVE_STATUS               (1 << 27)
 #define   PORTD_HOTPLUG_INT_STATUS		(3 << 21)
 #define   PORTC_HOTPLUG_INT_STATUS		(3 << 19)
 #define   PORTB_HOTPLUG_INT_STATUS		(3 << 17)
@@ -2045,6 +2125,7 @@
  * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte
  * of the infoframe structure specified by CEA-861. */
 #define   VIDEO_DIP_DATA_SIZE	32
+#define   VIDEO_DIP_VSC_DATA_SIZE	36
 #define VIDEO_DIP_CTL		0x61170
 /* Pre HSW: */
 #define   VIDEO_DIP_ENABLE		(1 << 31)
@@ -2192,6 +2273,8 @@
 #define BLC_PWM_CPU_CTL2	0x48250
 #define BLC_PWM_CPU_CTL		0x48254
 
+#define HSW_BLC_PWM2_CTL	0x48350
+
 /* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is
  * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */
 #define BLC_PWM_PCH_CTL1	0xc8250
@@ -2200,6 +2283,12 @@
 #define   BLM_PCH_POLARITY			(1 << 29)
 #define BLC_PWM_PCH_CTL2	0xc8254
 
+#define UTIL_PIN_CTL		0x48400
+#define   UTIL_PIN_ENABLE	(1 << 31)
+
+#define PCH_GTC_CTL		0xe7000
+#define   PCH_GTC_ENABLE	(1 << 31)
+
 /* TV port control */
 #define TV_CTL			0x68000
 /** Enables the TV encoder */
@@ -3113,9 +3202,6 @@
 #define  MLTR_WM2_SHIFT		8
 /* the unit of memory self-refresh latency time is 0.5us */
 #define  ILK_SRLT_MASK		0x3f
-#define ILK_LATENCY(shift)	(I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK)
-#define ILK_READ_WM1_LATENCY()	ILK_LATENCY(MLTR_WM1_SHIFT)
-#define ILK_READ_WM2_LATENCY()	ILK_LATENCY(MLTR_WM2_SHIFT)
 
 /* define the fifo size on Ironlake */
 #define ILK_DISPLAY_FIFO	128
@@ -3162,12 +3248,6 @@
 #define SSKPD_WM2_SHIFT		16
 #define SSKPD_WM3_SHIFT		24
 
-#define SNB_LATENCY(shift)	(I915_READ(MCHBAR_MIRROR_BASE_SNB + SSKPD) >> (shift) & SSKPD_WM_MASK)
-#define SNB_READ_WM0_LATENCY()		SNB_LATENCY(SSKPD_WM0_SHIFT)
-#define SNB_READ_WM1_LATENCY()		SNB_LATENCY(SSKPD_WM1_SHIFT)
-#define SNB_READ_WM2_LATENCY()		SNB_LATENCY(SSKPD_WM2_SHIFT)
-#define SNB_READ_WM3_LATENCY()		SNB_LATENCY(SSKPD_WM3_SHIFT)
-
 /*
  * The two pipe frame counter registers are not synchronized, so
  * reading a stable value is somewhat tricky. The following code
@@ -3718,6 +3798,9 @@
 #define DE_PLANEA_FLIP_DONE_IVB		(1<<3)
 #define DE_PIPEA_VBLANK_IVB		(1<<0)
 
+#define DE_PIPE_VBLANK_ILK(pipe)	(1 << ((pipe * 8) + 7))
+#define DE_PIPE_VBLANK_IVB(pipe)	(1 << (pipe * 5))
+
 #define VLV_MASTER_IER			0x4400c /* Gunit master IER */
 #define   MASTER_INTERRUPT_ENABLE	(1<<31)
 
@@ -3880,6 +3963,7 @@
 #define  SERR_INT_TRANS_C_FIFO_UNDERRUN	(1<<6)
 #define  SERR_INT_TRANS_B_FIFO_UNDERRUN	(1<<3)
 #define  SERR_INT_TRANS_A_FIFO_UNDERRUN	(1<<0)
+#define  SERR_INT_TRANS_FIFO_UNDERRUN(pipe)	(1<<(pipe*3))
 
 /* digital port hotplug */
 #define PCH_PORT_HOTPLUG        0xc4030		/* SHOTPLUG_CTL */
@@ -4080,6 +4164,13 @@
 #define HSW_TVIDEO_DIP_VSC_DATA(trans) \
 	 _TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B)
 
+#define HSW_STEREO_3D_CTL_A	0x70020
+#define   S3D_ENABLE		(1<<31)
+#define HSW_STEREO_3D_CTL_B	0x71020
+
+#define HSW_STEREO_3D_CTL(trans) \
+	_TRANSCODER(trans, HSW_STEREO_3D_CTL_A, HSW_STEREO_3D_CTL_A)
+
 #define _PCH_TRANS_HTOTAL_B          0xe1000
 #define _PCH_TRANS_HBLANK_B          0xe1004
 #define _PCH_TRANS_HSYNC_B           0xe1008
@@ -4468,6 +4559,10 @@
 #define  GT_FIFO_FREE_ENTRIES			0x120008
 #define    GT_FIFO_NUM_RESERVED_ENTRIES		20
 
+#define  HSW_IDICR				0x9008
+#define    IDIHASHMSK(x)			(((x) & 0x3f) << 16)
+#define  HSW_EDRAM_PRESENT			0x120010
+
 #define GEN6_UCGCTL1				0x9400
 # define GEN6_BLBUNIT_CLOCK_GATE_DISABLE		(1 << 5)
 # define GEN6_CSUNIT_CLOCK_GATE_DISABLE			(1 << 7)
@@ -4858,7 +4953,8 @@
 #define  SBI_SSCAUXDIV6				0x0610
 #define   SBI_SSCAUXDIV_FINALDIV2SEL(x)		((x)<<4)
 #define  SBI_DBUFF0				0x2a00
-#define   SBI_DBUFF0_ENABLE			(1<<0)
+#define  SBI_GEN0				0x1f00
+#define   SBI_GEN0_CFG_BUFFENABLE_DISABLE	(1<<0)
 
 /* LPT PIXCLK_GATE */
 #define PIXCLK_GATE			0xC6020
@@ -4924,7 +5020,14 @@
 #define  LCPLL_CLK_FREQ_450		(0<<26)
 #define  LCPLL_CD_CLOCK_DISABLE		(1<<25)
 #define  LCPLL_CD2X_CLOCK_DISABLE	(1<<23)
+#define  LCPLL_POWER_DOWN_ALLOW		(1<<22)
 #define  LCPLL_CD_SOURCE_FCLK		(1<<21)
+#define  LCPLL_CD_SOURCE_FCLK_DONE	(1<<19)
+
+#define D_COMP				(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
+#define  D_COMP_RCOMP_IN_PROGRESS	(1<<9)
+#define  D_COMP_COMP_FORCE		(1<<8)
+#define  D_COMP_COMP_DISABLE		(1<<0)
 
 /* Pipe WM_LINETIME - watermark line time */
 #define PIPE_WM_LINETIME_A		0x45270
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 6875b56..a777e7f 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -409,6 +409,71 @@ static const struct attribute *gen6_attrs[] = {
 	NULL,
 };
 
+static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
+				struct bin_attribute *attr, char *buf,
+				loff_t off, size_t count)
+{
+
+	struct device *kdev = container_of(kobj, struct device, kobj);
+	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
+	struct drm_device *dev = minor->dev;
+	struct i915_error_state_file_priv error_priv;
+	struct drm_i915_error_state_buf error_str;
+	ssize_t ret_count = 0;
+	int ret;
+
+	memset(&error_priv, 0, sizeof(error_priv));
+
+	ret = i915_error_state_buf_init(&error_str, count, off);
+	if (ret)
+		return ret;
+
+	error_priv.dev = dev;
+	i915_error_state_get(dev, &error_priv);
+
+	ret = i915_error_state_to_str(&error_str, &error_priv);
+	if (ret)
+		goto out;
+
+	ret_count = count < error_str.bytes ? count : error_str.bytes;
+
+	memcpy(buf, error_str.buf, ret_count);
+out:
+	i915_error_state_put(&error_priv);
+	i915_error_state_buf_release(&error_str);
+
+	return ret ?: ret_count;
+}
+
+static ssize_t error_state_write(struct file *file, struct kobject *kobj,
+				 struct bin_attribute *attr, char *buf,
+				 loff_t off, size_t count)
+{
+	struct device *kdev = container_of(kobj, struct device, kobj);
+	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
+	struct drm_device *dev = minor->dev;
+	int ret;
+
+	DRM_DEBUG_DRIVER("Resetting error state\n");
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	i915_destroy_error_state(dev);
+	mutex_unlock(&dev->struct_mutex);
+
+	return count;
+}
+
+static struct bin_attribute error_state_attr = {
+	.attr.name = "error",
+	.attr.mode = S_IRUSR | S_IWUSR,
+	.size = 0,
+	.read = error_state_read,
+	.write = error_state_write,
+};
+
 void i915_setup_sysfs(struct drm_device *dev)
 {
 	int ret;
@@ -432,10 +497,16 @@ void i915_setup_sysfs(struct drm_device *dev)
 		if (ret)
 			DRM_ERROR("gen6 sysfs setup failed\n");
 	}
+
+	ret = sysfs_create_bin_file(&dev->primary->kdev.kobj,
+				    &error_state_attr);
+	if (ret)
+		DRM_ERROR("error_state sysfs setup failed\n");
 }
 
 void i915_teardown_sysfs(struct drm_device *dev)
 {
+	sysfs_remove_bin_file(&dev->primary->kdev.kobj, &error_state_attr);
 	sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs);
 	device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);
 #ifdef CONFIG_PM
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 3db4a68..e2c5ee6 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -33,47 +33,52 @@ TRACE_EVENT(i915_gem_object_create,
 	    TP_printk("obj=%p, size=%u", __entry->obj, __entry->size)
 );
 
-TRACE_EVENT(i915_gem_object_bind,
-	    TP_PROTO(struct drm_i915_gem_object *obj, bool mappable),
-	    TP_ARGS(obj, mappable),
+TRACE_EVENT(i915_vma_bind,
+	    TP_PROTO(struct i915_vma *vma, bool mappable),
+	    TP_ARGS(vma, mappable),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
+			     __field(struct i915_address_space *, vm)
 			     __field(u32, offset)
 			     __field(u32, size)
 			     __field(bool, mappable)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->obj = obj;
-			   __entry->offset = obj->gtt_space->start;
-			   __entry->size = obj->gtt_space->size;
+			   __entry->obj = vma->obj;
+			   __entry->vm = vma->vm;
+			   __entry->offset = vma->node.start;
+			   __entry->size = vma->node.size;
 			   __entry->mappable = mappable;
 			   ),
 
-	    TP_printk("obj=%p, offset=%08x size=%x%s",
+	    TP_printk("obj=%p, offset=%08x size=%x%s vm=%p",
 		      __entry->obj, __entry->offset, __entry->size,
-		      __entry->mappable ? ", mappable" : "")
+		      __entry->mappable ? ", mappable" : "",
+		      __entry->vm)
 );
 
-TRACE_EVENT(i915_gem_object_unbind,
-	    TP_PROTO(struct drm_i915_gem_object *obj),
-	    TP_ARGS(obj),
+TRACE_EVENT(i915_vma_unbind,
+	    TP_PROTO(struct i915_vma *vma),
+	    TP_ARGS(vma),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
+			     __field(struct i915_address_space *, vm)
 			     __field(u32, offset)
 			     __field(u32, size)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->obj = obj;
-			   __entry->offset = obj->gtt_space->start;
-			   __entry->size = obj->gtt_space->size;
+			   __entry->obj = vma->obj;
+			   __entry->vm = vma->vm;
+			   __entry->offset = vma->node.start;
+			   __entry->size = vma->node.size;
 			   ),
 
-	    TP_printk("obj=%p, offset=%08x size=%x",
-		      __entry->obj, __entry->offset, __entry->size)
+	    TP_printk("obj=%p, offset=%08x size=%x vm=%p",
+		      __entry->obj, __entry->offset, __entry->size, __entry->vm)
 );
 
 TRACE_EVENT(i915_gem_object_change_domain,
@@ -406,10 +411,12 @@ TRACE_EVENT(i915_flip_complete,
 	    TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
 );
 
-TRACE_EVENT(i915_reg_rw,
-	TP_PROTO(bool write, u32 reg, u64 val, int len),
+TRACE_EVENT_CONDITION(i915_reg_rw,
+	TP_PROTO(bool write, u32 reg, u64 val, int len, bool trace),
+
+	TP_ARGS(write, reg, val, len, trace),
 
-	TP_ARGS(write, reg, val, len),
+	TP_CONDITION(trace),
 
 	TP_STRUCT__entry(
 		__field(u64, val)
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index bcbbaea..57fe1ae 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -28,7 +28,7 @@ static const u8 intel_dsm_guid[] = {
 	0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c
 };
 
-static int intel_dsm(acpi_handle handle, int func, int arg)
+static int intel_dsm(acpi_handle handle, int func)
 {
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_object_list input;
@@ -46,8 +46,9 @@ static int intel_dsm(acpi_handle handle, int func, int arg)
 	params[1].integer.value = INTEL_DSM_REVISION_ID;
 	params[2].type = ACPI_TYPE_INTEGER;
 	params[2].integer.value = func;
-	params[3].type = ACPI_TYPE_INTEGER;
-	params[3].integer.value = arg;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
 
 	ret = acpi_evaluate_object(handle, "_DSM", &input, &output);
 	if (ret) {
@@ -151,8 +152,9 @@ static void intel_dsm_platform_mux_info(void)
 	params[1].integer.value = INTEL_DSM_REVISION_ID;
 	params[2].type = ACPI_TYPE_INTEGER;
 	params[2].integer.value = INTEL_DSM_FN_PLATFORM_MUX_INFO;
-	params[3].type = ACPI_TYPE_INTEGER;
-	params[3].integer.value = 0;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
 
 	ret = acpi_evaluate_object(intel_dsm_priv.dhandle, "_DSM", &input,
 				   &output);
@@ -205,7 +207,7 @@ static bool intel_dsm_pci_probe(struct pci_dev *pdev)
 		return false;
 	}
 
-	ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0);
+	ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS);
 	if (ret < 0) {
 		DRM_DEBUG_KMS("failed to get supported _DSM functions\n");
 		return false;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 3acec8c..b5a3875 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -52,15 +52,14 @@ struct intel_crt {
 	u32 adpa_reg;
 };
 
-static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
+static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_crt, base);
+	return container_of(encoder, struct intel_crt, base);
 }
 
-static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
+static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
 {
-	return container_of(encoder, struct intel_crt, base);
+	return intel_encoder_to_crt(intel_attached_encoder(connector));
 }
 
 static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
@@ -238,17 +237,14 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
 	return true;
 }
 
-static void intel_crt_mode_set(struct drm_encoder *encoder,
-			       struct drm_display_mode *mode,
-			       struct drm_display_mode *adjusted_mode)
+static void intel_crt_mode_set(struct intel_encoder *encoder)
 {
 
-	struct drm_device *dev = encoder->dev;
-	struct drm_crtc *crtc = encoder->crtc;
-	struct intel_crt *crt =
-		intel_encoder_to_crt(to_intel_encoder(encoder));
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;
 	u32 adpa;
 
 	if (HAS_PCH_SPLIT(dev))
@@ -265,14 +261,14 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 	if (HAS_PCH_LPT(dev))
 		; /* Those bits don't exist here */
 	else if (HAS_PCH_CPT(dev))
-		adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
-	else if (intel_crtc->pipe == 0)
+		adpa |= PORT_TRANS_SEL_CPT(crtc->pipe);
+	else if (crtc->pipe == 0)
 		adpa |= ADPA_PIPE_A_SELECT;
 	else
 		adpa |= ADPA_PIPE_B_SELECT;
 
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
+		I915_WRITE(BCLRPAT(crtc->pipe), 0);
 
 	I915_WRITE(crt->adpa_reg, adpa);
 }
@@ -613,6 +609,10 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 	enum drm_connector_status status;
 	struct intel_load_detect_pipe tmp;
 
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
+		      connector->base.id, drm_get_connector_name(connector),
+		      force);
+
 	if (I915_HAS_HOTPLUG(dev)) {
 		/* We can not rely on the HPD pin always being correctly wired
 		 * up, for example many KVM do not pass it through, and so
@@ -707,10 +707,6 @@ static void intel_crt_reset(struct drm_connector *connector)
  * Routines for controlling stuff on the analog port
  */
 
-static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
-	.mode_set = intel_crt_mode_set,
-};
-
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
 	.reset = intel_crt_reset,
 	.dpms = intel_crt_dpms,
@@ -800,6 +796,7 @@ void intel_crt_init(struct drm_device *dev)
 		crt->adpa_reg = ADPA;
 
 	crt->base.compute_config = intel_crt_compute_config;
+	crt->base.mode_set = intel_crt_mode_set;
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
 	crt->base.get_config = intel_crt_get_config;
@@ -811,7 +808,6 @@ void intel_crt_init(struct drm_device *dev)
 		crt->base.get_hw_state = intel_crt_get_hw_state;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
-	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
 	drm_sysfs_connector_add(connector);
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index b042ee5..b8c096b 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -84,25 +84,17 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
  * in either FDI or DP modes only, as HDMI connections will work with both
  * of those
  */
-static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
-				      bool use_fdi_mode)
+static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 	int i;
-	const u32 *ddi_translations = ((use_fdi_mode) ?
+	const u32 *ddi_translations = (port == PORT_E) ?
 		hsw_ddi_translations_fdi :
-		hsw_ddi_translations_dp);
+		hsw_ddi_translations_dp;
 
-	DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n",
-			port_name(port),
-			use_fdi_mode ? "FDI" : "DP");
-
-	WARN((use_fdi_mode && (port != PORT_E)),
-		"Programming port %c in FDI mode, this probably will not work.\n",
-		port_name(port));
-
-	for (i=0, reg=DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
+	for (i = 0, reg = DDI_BUF_TRANS(port);
+	     i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
 		I915_WRITE(reg, ddi_translations[i]);
 		reg += 4;
 	}
@@ -118,14 +110,8 @@ void intel_prepare_ddi(struct drm_device *dev)
 	if (!HAS_DDI(dev))
 		return;
 
-	for (port = PORT_A; port < PORT_E; port++)
-		intel_prepare_ddi_buffers(dev, port, false);
-
-	/* DDI E is the suggested one to work in FDI mode, so program is as such
-	 * by default. It will have to be re-programmed in case a digital DP
-	 * output will be detected on it
-	 */
-	intel_prepare_ddi_buffers(dev, PORT_E, true);
+	for (port = PORT_A; port <= PORT_E; port++)
+		intel_prepare_ddi_buffers(dev, port);
 }
 
 static const long hsw_ddi_buf_ctl_values[] = {
@@ -281,25 +267,22 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	DRM_ERROR("FDI link training failed!\n");
 }
 
-static void intel_ddi_mode_set(struct drm_encoder *encoder,
-			       struct drm_display_mode *mode,
-			       struct drm_display_mode *adjusted_mode)
+static void intel_ddi_mode_set(struct intel_encoder *encoder)
 {
-	struct drm_crtc *crtc = encoder->crtc;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-	int port = intel_ddi_get_encoder_port(intel_encoder);
-	int pipe = intel_crtc->pipe;
-	int type = intel_encoder->type;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	int port = intel_ddi_get_encoder_port(encoder);
+	int pipe = crtc->pipe;
+	int type = encoder->type;
+	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;
 
 	DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
 		      port_name(port), pipe_name(pipe));
 
-	intel_crtc->eld_vld = false;
+	crtc->eld_vld = false;
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 		struct intel_digital_port *intel_dig_port =
-			enc_to_dig_port(encoder);
+			enc_to_dig_port(&encoder->base);
 
 		intel_dp->DP = intel_dig_port->saved_port_bits |
 			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
@@ -307,17 +290,17 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
 
 		if (intel_dp->has_audio) {
 			DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
-					 pipe_name(intel_crtc->pipe));
+					 pipe_name(crtc->pipe));
 
 			/* write eld */
 			DRM_DEBUG_DRIVER("DP audio: write eld information\n");
-			intel_write_eld(encoder, adjusted_mode);
+			intel_write_eld(&encoder->base, adjusted_mode);
 		}
 
 		intel_dp_init_link_config(intel_dp);
 
 	} else if (type == INTEL_OUTPUT_HDMI) {
-		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 
 		if (intel_hdmi->has_audio) {
 			/* Proper support for digital audio needs a new logic
@@ -325,14 +308,14 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
 			 * patch bombing.
 			 */
 			DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
-					 pipe_name(intel_crtc->pipe));
+					 pipe_name(crtc->pipe));
 
 			/* write eld */
 			DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
-			intel_write_eld(encoder, adjusted_mode);
+			intel_write_eld(&encoder->base, adjusted_mode);
 		}
 
-		intel_hdmi->set_infoframes(encoder, adjusted_mode);
+		intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
 	}
 }
 
@@ -1118,6 +1101,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 			intel_dp_stop_link_train(intel_dp);
 
 		ironlake_edp_backlight_on(intel_dp);
+		intel_edp_psr_enable(intel_dp);
 	}
 
 	if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
@@ -1148,6 +1132,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+		intel_edp_psr_disable(intel_dp);
 		ironlake_edp_backlight_off(intel_dp);
 	}
 }
@@ -1309,10 +1294,6 @@ static const struct drm_encoder_funcs intel_ddi_funcs = {
 	.destroy = intel_ddi_destroy,
 };
 
-static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
-	.mode_set = intel_ddi_mode_set,
-};
-
 void intel_ddi_init(struct drm_device *dev, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1337,9 +1318,9 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 
 	drm_encoder_init(dev, encoder, &intel_ddi_funcs,
 			 DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
 
 	intel_encoder->compute_config = intel_ddi_compute_config;
+	intel_encoder->mode_set = intel_ddi_mode_set;
 	intel_encoder->enable = intel_enable_ddi;
 	intel_encoder->pre_enable = intel_ddi_pre_enable;
 	intel_encoder->disable = intel_disable_ddi;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5fb3058..a0914db 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -45,6 +45,11 @@ bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
 static void intel_increase_pllclock(struct drm_crtc *crtc);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 
+static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
+				struct intel_crtc_config *pipe_config);
+static void ironlake_crtc_clock_get(struct intel_crtc *crtc,
+				    struct intel_crtc_config *pipe_config);
+
 typedef struct {
 	int	min, max;
 } intel_range_t;
@@ -54,7 +59,6 @@ typedef struct {
 	int	p2_slow, p2_fast;
 } intel_p2_t;
 
-#define INTEL_P2_NUM		      2
 typedef struct intel_limit intel_limit_t;
 struct intel_limit {
 	intel_range_t   dot, vco, n, m, m1, m2, p, p1;
@@ -84,7 +88,7 @@ intel_fdi_link_freq(struct drm_device *dev)
 		return 27;
 }
 
-static const intel_limit_t intel_limits_i8xx_dvo = {
+static const intel_limit_t intel_limits_i8xx_dac = {
 	.dot = { .min = 25000, .max = 350000 },
 	.vco = { .min = 930000, .max = 1400000 },
 	.n = { .min = 3, .max = 16 },
@@ -97,6 +101,19 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
 		.p2_slow = 4, .p2_fast = 2 },
 };
 
+static const intel_limit_t intel_limits_i8xx_dvo = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 930000, .max = 1400000 },
+	.n = { .min = 3, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 2, .max = 33 },
+	.p2 = { .dot_limit = 165000,
+		.p2_slow = 4, .p2_fast = 4 },
+};
+
 static const intel_limit_t intel_limits_i8xx_lvds = {
 	.dot = { .min = 25000, .max = 350000 },
 	.vco = { .min = 930000, .max = 1400000 },
@@ -405,8 +422,10 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk)
 	} else {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
 			limit = &intel_limits_i8xx_lvds;
-		else
+		else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO))
 			limit = &intel_limits_i8xx_dvo;
+		else
+			limit = &intel_limits_i8xx_dac;
 	}
 	return limit;
 }
@@ -892,8 +911,8 @@ static const char *state_string(bool enabled)
 }
 
 /* Only for pre-ILK configs */
-static void assert_pll(struct drm_i915_private *dev_priv,
-		       enum pipe pipe, bool state)
+void assert_pll(struct drm_i915_private *dev_priv,
+		enum pipe pipe, bool state)
 {
 	int reg;
 	u32 val;
@@ -906,10 +925,8 @@ static void assert_pll(struct drm_i915_private *dev_priv,
 	     "PLL state assertion failure (expected %s, current %s)\n",
 	     state_string(state), state_string(cur_state));
 }
-#define assert_pll_enabled(d, p) assert_pll(d, p, true)
-#define assert_pll_disabled(d, p) assert_pll(d, p, false)
 
-static struct intel_shared_dpll *
+struct intel_shared_dpll *
 intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -921,9 +938,9 @@ intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
 }
 
 /* For ILK+ */
-static void assert_shared_dpll(struct drm_i915_private *dev_priv,
-			       struct intel_shared_dpll *pll,
-			       bool state)
+void assert_shared_dpll(struct drm_i915_private *dev_priv,
+			struct intel_shared_dpll *pll,
+			bool state)
 {
 	bool cur_state;
 	struct intel_dpll_hw_state hw_state;
@@ -942,8 +959,6 @@ static void assert_shared_dpll(struct drm_i915_private *dev_priv,
 	     "%s assertion failure (expected %s, current %s)\n",
 	     pll->name, state_string(state), state_string(cur_state));
 }
-#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
-#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
 
 static void assert_fdi_tx(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, bool state)
@@ -1007,15 +1022,19 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
 	WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
 }
 
-static void assert_fdi_rx_pll_enabled(struct drm_i915_private *dev_priv,
-				      enum pipe pipe)
+void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
+		       enum pipe pipe, bool state)
 {
 	int reg;
 	u32 val;
+	bool cur_state;
 
 	reg = FDI_RX_CTL(pipe);
 	val = I915_READ(reg);
-	WARN(!(val & FDI_RX_PLL_ENABLE), "FDI RX PLL assertion failure, should be active but is disabled\n");
+	cur_state = !!(val & FDI_RX_PLL_ENABLE);
+	WARN(cur_state != state,
+	     "FDI RX PLL assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
 }
 
 static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
@@ -1111,7 +1130,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
 	}
 
 	/* Need to check both planes against the pipe */
-	for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
+	for_each_pipe(i) {
 		reg = DSPCNTR(i);
 		val = I915_READ(reg);
 		cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
@@ -1301,51 +1320,92 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
 	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
 }
 
-/**
- * intel_enable_pll - enable a PLL
- * @dev_priv: i915 private structure
- * @pipe: pipe PLL to enable
- *
- * Enable @pipe's PLL so we can start pumping pixels from a plane.  Check to
- * make sure the PLL reg is writable first though, since the panel write
- * protect mechanism may be enabled.
- *
- * Note!  This is for pre-ILK only.
- *
- * Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
- */
-static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+static void vlv_enable_pll(struct intel_crtc *crtc)
 {
-	int reg;
-	u32 val;
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int reg = DPLL(crtc->pipe);
+	u32 dpll = crtc->config.dpll_hw_state.dpll;
 
-	assert_pipe_disabled(dev_priv, pipe);
+	assert_pipe_disabled(dev_priv, crtc->pipe);
 
 	/* No really, not for ILK+ */
-	BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5);
+	BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
 
 	/* PLL is protected by panel, make sure we can write it */
 	if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
-		assert_panel_unlocked(dev_priv, pipe);
+		assert_panel_unlocked(dev_priv, crtc->pipe);
 
-	reg = DPLL(pipe);
-	val = I915_READ(reg);
-	val |= DPLL_VCO_ENABLE;
+	I915_WRITE(reg, dpll);
+	POSTING_READ(reg);
+	udelay(150);
+
+	if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
+		DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe);
+
+	I915_WRITE(DPLL_MD(crtc->pipe), crtc->config.dpll_hw_state.dpll_md);
+	POSTING_READ(DPLL_MD(crtc->pipe));
 
 	/* We do this three times for luck */
-	I915_WRITE(reg, val);
+	I915_WRITE(reg, dpll);
 	POSTING_READ(reg);
 	udelay(150); /* wait for warmup */
-	I915_WRITE(reg, val);
+	I915_WRITE(reg, dpll);
 	POSTING_READ(reg);
 	udelay(150); /* wait for warmup */
-	I915_WRITE(reg, val);
+	I915_WRITE(reg, dpll);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+}
+
+static void i9xx_enable_pll(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int reg = DPLL(crtc->pipe);
+	u32 dpll = crtc->config.dpll_hw_state.dpll;
+
+	assert_pipe_disabled(dev_priv, crtc->pipe);
+
+	/* No really, not for ILK+ */
+	BUG_ON(dev_priv->info->gen >= 5);
+
+	/* PLL is protected by panel, make sure we can write it */
+	if (IS_MOBILE(dev) && !IS_I830(dev))
+		assert_panel_unlocked(dev_priv, crtc->pipe);
+
+	I915_WRITE(reg, dpll);
+
+	/* Wait for the clocks to stabilize. */
+	POSTING_READ(reg);
+	udelay(150);
+
+	if (INTEL_INFO(dev)->gen >= 4) {
+		I915_WRITE(DPLL_MD(crtc->pipe),
+			   crtc->config.dpll_hw_state.dpll_md);
+	} else {
+		/* The pixel multiplier can only be updated once the
+		 * DPLL is enabled and the clocks are stable.
+		 *
+		 * So write it again.
+		 */
+		I915_WRITE(reg, dpll);
+	}
+
+	/* We do this three times for luck */
+	I915_WRITE(reg, dpll);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+	I915_WRITE(reg, dpll);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+	I915_WRITE(reg, dpll);
 	POSTING_READ(reg);
 	udelay(150); /* wait for warmup */
 }
 
 /**
- * intel_disable_pll - disable a PLL
+ * i9xx_disable_pll - disable a PLL
  * @dev_priv: i915 private structure
  * @pipe: pipe PLL to disable
  *
@@ -1353,11 +1413,8 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
  *
  * Note!  This is for pre-ILK only.
  */
-static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	int reg;
-	u32 val;
-
 	/* Don't disable pipe A or pipe A PLLs if needed */
 	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
 		return;
@@ -1365,11 +1422,8 @@ static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 	/* Make sure the pipe isn't still relying on us */
 	assert_pipe_disabled(dev_priv, pipe);
 
-	reg = DPLL(pipe);
-	val = I915_READ(reg);
-	val &= ~DPLL_VCO_ENABLE;
-	I915_WRITE(reg, val);
-	POSTING_READ(reg);
+	I915_WRITE(DPLL(pipe), 0);
+	POSTING_READ(DPLL(pipe));
 }
 
 void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
@@ -1942,16 +1996,17 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		intel_crtc->dspaddr_offset = linear_offset;
 	}
 
-	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
-		      obj->gtt_offset, linear_offset, x, y, fb->pitches[0]);
+	DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+		      i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
+		      fb->pitches[0]);
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	if (INTEL_INFO(dev)->gen >= 4) {
 		I915_MODIFY_DISPBASE(DSPSURF(plane),
-				     obj->gtt_offset + intel_crtc->dspaddr_offset);
+				     i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
 		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
 		I915_WRITE(DSPLINOFF(plane), linear_offset);
 	} else
-		I915_WRITE(DSPADDR(plane), obj->gtt_offset + linear_offset);
+		I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset);
 	POSTING_READ(reg);
 
 	return 0;
@@ -2031,11 +2086,12 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 					       fb->pitches[0]);
 	linear_offset -= intel_crtc->dspaddr_offset;
 
-	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
-		      obj->gtt_offset, linear_offset, x, y, fb->pitches[0]);
+	DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+		      i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
+		      fb->pitches[0]);
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	I915_MODIFY_DISPBASE(DSPSURF(plane),
-			     obj->gtt_offset + intel_crtc->dspaddr_offset);
+			     i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
 	if (IS_HASWELL(dev)) {
 		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
 	} else {
@@ -2183,6 +2239,20 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
+	/* Update pipe size and adjust fitter if needed */
+	if (i915_fastboot) {
+		I915_WRITE(PIPESRC(intel_crtc->pipe),
+			   ((crtc->mode.hdisplay - 1) << 16) |
+			   (crtc->mode.vdisplay - 1));
+		if (!intel_crtc->config.pch_pfit.size &&
+		    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
+		     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
+			I915_WRITE(PF_CTL(intel_crtc->pipe), 0);
+			I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0);
+			I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0);
+		}
+	}
+
 	ret = dev_priv->display.update_plane(crtc, fb, x, y);
 	if (ret) {
 		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
@@ -2203,6 +2273,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	}
 
 	intel_update_fbc(dev);
+	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc_update_sarea_pos(crtc, x, y);
@@ -2927,15 +2998,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 	/* For PCH output, training FDI link */
 	dev_priv->display.fdi_link_train(crtc);
 
-	/* XXX: pch pll's can be enabled any time before we enable the PCH
-	 * transcoder, and we actually should do this to not upset any PCH
-	 * transcoder that already use the clock when we share it.
-	 *
-	 * Note that enable_shared_dpll tries to do the right thing, but
-	 * get_shared_dpll unconditionally resets the pll - we need that to have
-	 * the right LVDS enable sequence. */
-	ironlake_enable_shared_dpll(intel_crtc);
-
+	/* We need to program the right clock selection before writing the pixel
+	 * mutliplier into the DPLL. */
 	if (HAS_PCH_CPT(dev)) {
 		u32 sel;
 
@@ -2949,6 +3013,15 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
+	/* XXX: pch pll's can be enabled any time before we enable the PCH
+	 * transcoder, and we actually should do this to not upset any PCH
+	 * transcoder that already use the clock when we share it.
+	 *
+	 * Note that enable_shared_dpll tries to do the right thing, but
+	 * get_shared_dpll unconditionally resets the pll - we need that to have
+	 * the right LVDS enable sequence. */
+	ironlake_enable_shared_dpll(intel_crtc);
+
 	/* set transcoder timing, panel must allow it */
 	assert_panel_unlocked(dev_priv, pipe);
 	ironlake_pch_transcoder_set_timings(intel_crtc, pipe);
@@ -3031,7 +3104,7 @@ static void intel_put_shared_dpll(struct intel_crtc *crtc)
 	crtc->config.shared_dpll = DPLL_ID_PRIVATE;
 }
 
-static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, u32 dpll, u32 fp)
+static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
@@ -3045,7 +3118,7 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
 
 	if (HAS_PCH_IBX(dev_priv->dev)) {
 		/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
-		i = crtc->pipe;
+		i = (enum intel_dpll_id) crtc->pipe;
 		pll = &dev_priv->shared_dplls[i];
 
 		DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
@@ -3061,8 +3134,8 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
 		if (pll->refcount == 0)
 			continue;
 
-		if (dpll == (I915_READ(PCH_DPLL(pll->id)) & 0x7fffffff) &&
-		    fp == I915_READ(PCH_FP0(pll->id))) {
+		if (memcmp(&crtc->config.dpll_hw_state, &pll->hw_state,
+			   sizeof(pll->hw_state)) == 0) {
 			DRM_DEBUG_KMS("CRTC:%d sharing existing %s (refcount %d, ative %d)\n",
 				      crtc->base.base.id,
 				      pll->name, pll->refcount, pll->active);
@@ -3096,13 +3169,7 @@ found:
 		WARN_ON(pll->on);
 		assert_shared_dpll_disabled(dev_priv, pll);
 
-		/* Wait for the clocks to stabilize before rewriting the regs */
-		I915_WRITE(PCH_DPLL(pll->id), dpll & ~DPLL_VCO_ENABLE);
-		POSTING_READ(PCH_DPLL(pll->id));
-		udelay(150);
-
-		I915_WRITE(PCH_FP0(pll->id), fp);
-		I915_WRITE(PCH_DPLL(pll->id), dpll & ~DPLL_VCO_ENABLE);
+		pll->mode_set(dev_priv, pll);
 	}
 	pll->refcount++;
 
@@ -3174,7 +3241,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
-	u32 temp;
 
 	WARN_ON(!crtc->enabled);
 
@@ -3188,12 +3254,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_update_watermarks(dev);
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		temp = I915_READ(PCH_LVDS);
-		if ((temp & LVDS_PORT_EN) == 0)
-			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
-	}
-
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->pre_enable)
+			encoder->pre_enable(encoder);
 
 	if (intel_crtc->config.has_pch_encoder) {
 		/* Note: FDI PLL enabling _must_ be done before we enable the
@@ -3205,10 +3268,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		assert_fdi_rx_disabled(dev_priv, pipe);
 	}
 
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		if (encoder->pre_enable)
-			encoder->pre_enable(encoder);
-
 	ironlake_pfit_enable(intel_crtc);
 
 	/*
@@ -3389,7 +3448,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 
-	if (dev_priv->cfb_plane == plane)
+	if (dev_priv->fbc.plane == plane)
 		intel_disable_fbc(dev);
 
 	intel_crtc_update_cursor(crtc, false);
@@ -3462,7 +3521,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	drm_vblank_off(dev, pipe);
 
 	/* FBC must be disabled before disabling the plane on HSW. */
-	if (dev_priv->cfb_plane == plane)
+	if (dev_priv->fbc.plane == plane)
 		intel_disable_fbc(dev);
 
 	hsw_disable_ips(intel_crtc);
@@ -3593,22 +3652,16 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
 
-	mutex_lock(&dev_priv->dpio_lock);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_pll_enable)
 			encoder->pre_pll_enable(encoder);
 
-	intel_enable_pll(dev_priv, pipe);
+	vlv_enable_pll(intel_crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
-	/* VLV wants encoder enabling _before_ the pipe is up. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->enable(encoder);
-
 	i9xx_pfit_enable(intel_crtc);
 
 	intel_crtc_load_lut(crtc);
@@ -3620,7 +3673,8 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 
 	intel_update_fbc(dev);
 
-	mutex_unlock(&dev_priv->dpio_lock);
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->enable(encoder);
 }
 
 static void i9xx_crtc_enable(struct drm_crtc *crtc)
@@ -3640,12 +3694,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
 
-	intel_enable_pll(dev_priv, pipe);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
+	i9xx_enable_pll(intel_crtc);
+
 	i9xx_pfit_enable(intel_crtc);
 
 	intel_crtc_load_lut(crtc);
@@ -3701,7 +3755,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 
-	if (dev_priv->cfb_plane == plane)
+	if (dev_priv->fbc.plane == plane)
 		intel_disable_fbc(dev);
 
 	intel_crtc_dpms_overlay(intel_crtc, false);
@@ -3717,7 +3771,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 		if (encoder->post_disable)
 			encoder->post_disable(encoder);
 
-	intel_disable_pll(dev_priv, pipe);
+	i9xx_disable_pll(dev_priv, pipe);
 
 	intel_crtc->active = false;
 	intel_update_fbc(dev);
@@ -4032,7 +4086,7 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc,
 {
 	pipe_config->ips_enabled = i915_enable_ips &&
 				   hsw_crtc_supports_ips(crtc) &&
-				   pipe_config->pipe_bpp == 24;
+				   pipe_config->pipe_bpp <= 24;
 }
 
 static int intel_crtc_compute_config(struct intel_crtc *crtc,
@@ -4048,12 +4102,6 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 			return -EINVAL;
 	}
 
-	/* All interlaced capable intel hw wants timings in frames. Note though
-	 * that intel_lvds_mode_fixup does some funny tricks with the crtc
-	 * timings, so we need to be careful not to clobber these.*/
-	if (!pipe_config->timings_set)
-		drm_mode_set_crtcinfo(adjusted_mode, 0);
-
 	/* Cantiga+ cannot handle modes with a hsync front porch of 0.
 	 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
 	 */
@@ -4103,6 +4151,30 @@ static int i9xx_misc_get_display_clock_speed(struct drm_device *dev)
 	return 200000;
 }
 
+static int pnv_get_display_clock_speed(struct drm_device *dev)
+{
+	u16 gcfgc = 0;
+
+	pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
+
+	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
+	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
+		return 267000;
+	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
+		return 333000;
+	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
+		return 444000;
+	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
+		return 200000;
+	default:
+		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
+	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
+		return 133000;
+	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
+		return 167000;
+	}
+}
+
 static int i915gm_get_display_clock_speed(struct drm_device *dev)
 {
 	u16 gcfgc = 0;
@@ -4266,14 +4338,17 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
 	}
 
 	I915_WRITE(FP0(pipe), fp);
+	crtc->config.dpll_hw_state.fp0 = fp;
 
 	crtc->lowfreq_avail = false;
 	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
 	    reduced_clock && i915_powersave) {
 		I915_WRITE(FP1(pipe), fp2);
+		crtc->config.dpll_hw_state.fp1 = fp2;
 		crtc->lowfreq_avail = true;
 	} else {
 		I915_WRITE(FP1(pipe), fp);
+		crtc->config.dpll_hw_state.fp1 = fp;
 	}
 }
 
@@ -4351,7 +4426,6 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_encoder *encoder;
 	int pipe = crtc->pipe;
 	u32 dpll, mdiv;
 	u32 bestn, bestm1, bestm2, bestp1, bestp2;
@@ -4407,7 +4481,7 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 	    intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) ||
 	    intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
 		vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe),
-				 0x005f0021);
+				 0x009f0003);
 	else
 		vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe),
 				 0x00d0000f);
@@ -4440,10 +4514,6 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 
 	vlv_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000);
 
-	for_each_encoder_on_crtc(dev, &crtc->base, encoder)
-		if (encoder->pre_pll_enable)
-			encoder->pre_pll_enable(encoder);
-
 	/* Enable DPIO clock input */
 	dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
 		DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
@@ -4451,17 +4521,11 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 		dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
 
 	dpll |= DPLL_VCO_ENABLE;
-	I915_WRITE(DPLL(pipe), dpll);
-	POSTING_READ(DPLL(pipe));
-	udelay(150);
-
-	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
-		DRM_ERROR("DPLL %d failed to lock\n", pipe);
+	crtc->config.dpll_hw_state.dpll = dpll;
 
 	dpll_md = (crtc->config.pixel_multiplier - 1)
 		<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
-	I915_WRITE(DPLL_MD(pipe), dpll_md);
-	POSTING_READ(DPLL_MD(pipe));
+	crtc->config.dpll_hw_state.dpll_md = dpll_md;
 
 	if (crtc->config.has_dp_encoder)
 		intel_dp_set_m_n(crtc);
@@ -4475,8 +4539,6 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_encoder *encoder;
-	int pipe = crtc->pipe;
 	u32 dpll;
 	bool is_sdvo;
 	struct dpll *clock = &crtc->config.dpll;
@@ -4499,10 +4561,10 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
 	}
 
 	if (is_sdvo)
-		dpll |= DPLL_DVO_HIGH_SPEED;
+		dpll |= DPLL_SDVO_HIGH_SPEED;
 
 	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT))
-		dpll |= DPLL_DVO_HIGH_SPEED;
+		dpll |= DPLL_SDVO_HIGH_SPEED;
 
 	/* compute bitmask from p1 value */
 	if (IS_PINEVIEW(dev))
@@ -4538,35 +4600,16 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
 		dpll |= PLL_REF_INPUT_DREFCLK;
 
 	dpll |= DPLL_VCO_ENABLE;
-	I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
-	POSTING_READ(DPLL(pipe));
-	udelay(150);
-
-	for_each_encoder_on_crtc(dev, &crtc->base, encoder)
-		if (encoder->pre_pll_enable)
-			encoder->pre_pll_enable(encoder);
-
-	if (crtc->config.has_dp_encoder)
-		intel_dp_set_m_n(crtc);
-
-	I915_WRITE(DPLL(pipe), dpll);
-
-	/* Wait for the clocks to stabilize. */
-	POSTING_READ(DPLL(pipe));
-	udelay(150);
+	crtc->config.dpll_hw_state.dpll = dpll;
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		u32 dpll_md = (crtc->config.pixel_multiplier - 1)
 			<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
-		I915_WRITE(DPLL_MD(pipe), dpll_md);
-	} else {
-		/* The pixel multiplier can only be updated once the
-		 * DPLL is enabled and the clocks are stable.
-		 *
-		 * So write it again.
-		 */
-		I915_WRITE(DPLL(pipe), dpll);
+		crtc->config.dpll_hw_state.dpll_md = dpll_md;
 	}
+
+	if (crtc->config.has_dp_encoder)
+		intel_dp_set_m_n(crtc);
 }
 
 static void i8xx_update_pll(struct intel_crtc *crtc,
@@ -4575,8 +4618,6 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_encoder *encoder;
-	int pipe = crtc->pipe;
 	u32 dpll;
 	struct dpll *clock = &crtc->config.dpll;
 
@@ -4595,6 +4636,9 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
 			dpll |= PLL_P2_DIVIDE_BY_4;
 	}
 
+	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO))
+		dpll |= DPLL_DVO_2X_MODE;
+
 	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
 		 intel_panel_use_ssc(dev_priv) && num_connectors < 2)
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
@@ -4602,26 +4646,7 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
 		dpll |= PLL_REF_INPUT_DREFCLK;
 
 	dpll |= DPLL_VCO_ENABLE;
-	I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
-	POSTING_READ(DPLL(pipe));
-	udelay(150);
-
-	for_each_encoder_on_crtc(dev, &crtc->base, encoder)
-		if (encoder->pre_pll_enable)
-			encoder->pre_pll_enable(encoder);
-
-	I915_WRITE(DPLL(pipe), dpll);
-
-	/* Wait for the clocks to stabilize. */
-	POSTING_READ(DPLL(pipe));
-	udelay(150);
-
-	/* The pixel multiplier can only be updated once the
-	 * DPLL is enabled and the clocks are stable.
-	 *
-	 * So write it again.
-	 */
-	I915_WRITE(DPLL(pipe), dpll);
+	crtc->config.dpll_hw_state.dpll = dpll;
 }
 
 static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
@@ -4727,6 +4752,27 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
 	pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1;
 }
 
+static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
+					     struct intel_crtc_config *pipe_config)
+{
+	struct drm_crtc *crtc = &intel_crtc->base;
+
+	crtc->mode.hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
+	crtc->mode.htotal = pipe_config->adjusted_mode.crtc_htotal;
+	crtc->mode.hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
+	crtc->mode.hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
+
+	crtc->mode.vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
+	crtc->mode.vtotal = pipe_config->adjusted_mode.crtc_vtotal;
+	crtc->mode.vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
+	crtc->mode.vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
+
+	crtc->mode.flags = pipe_config->adjusted_mode.flags;
+
+	crtc->mode.clock = pipe_config->adjusted_mode.clock;
+	crtc->mode.flags |= pipe_config->adjusted_mode.flags;
+}
+
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
@@ -4939,7 +4985,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
-	pipe_config->cpu_transcoder = crtc->pipe;
+	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
 	tmp = I915_READ(PIPECONF(crtc->pipe));
@@ -4955,6 +5001,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 		pipe_config->pixel_multiplier =
 			((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
 			 >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
+		pipe_config->dpll_hw_state.dpll_md = tmp;
 	} else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
 		tmp = I915_READ(DPLL(crtc->pipe));
 		pipe_config->pixel_multiplier =
@@ -4966,6 +5013,16 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 		 * function. */
 		pipe_config->pixel_multiplier = 1;
 	}
+	pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
+	if (!IS_VALLEYVIEW(dev)) {
+		pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
+		pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe));
+	} else {
+		/* Mask out read-only status bits. */
+		pipe_config->dpll_hw_state.dpll &= ~(DPLL_LOCK_VLV |
+						     DPLL_PORTC_READY_MASK |
+						     DPLL_PORTB_READY_MASK);
+	}
 
 	return true;
 }
@@ -5119,74 +5176,37 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
 	BUG_ON(val != final);
 }
 
-/* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */
-static void lpt_init_pch_refclk(struct drm_device *dev)
+static void lpt_reset_fdi_mphy(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_mode_config *mode_config = &dev->mode_config;
-	struct intel_encoder *encoder;
-	bool has_vga = false;
-	bool is_sdv = false;
-	u32 tmp;
-
-	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
-		switch (encoder->type) {
-		case INTEL_OUTPUT_ANALOG:
-			has_vga = true;
-			break;
-		}
-	}
-
-	if (!has_vga)
-		return;
-
-	mutex_lock(&dev_priv->dpio_lock);
-
-	/* XXX: Rip out SDV support once Haswell ships for real. */
-	if (IS_HASWELL(dev) && (dev->pci_device & 0xFF00) == 0x0C00)
-		is_sdv = true;
-
-	tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
-	tmp &= ~SBI_SSCCTL_DISABLE;
-	tmp |= SBI_SSCCTL_PATHALT;
-	intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
-
-	udelay(24);
+	uint32_t tmp;
 
-	tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
-	tmp &= ~SBI_SSCCTL_PATHALT;
-	intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
+	tmp = I915_READ(SOUTH_CHICKEN2);
+	tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
+	I915_WRITE(SOUTH_CHICKEN2, tmp);
 
-	if (!is_sdv) {
-		tmp = I915_READ(SOUTH_CHICKEN2);
-		tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
-		I915_WRITE(SOUTH_CHICKEN2, tmp);
+	if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) &
+			       FDI_MPHY_IOSFSB_RESET_STATUS, 100))
+		DRM_ERROR("FDI mPHY reset assert timeout\n");
 
-		if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) &
-				       FDI_MPHY_IOSFSB_RESET_STATUS, 100))
-			DRM_ERROR("FDI mPHY reset assert timeout\n");
+	tmp = I915_READ(SOUTH_CHICKEN2);
+	tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
+	I915_WRITE(SOUTH_CHICKEN2, tmp);
 
-		tmp = I915_READ(SOUTH_CHICKEN2);
-		tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
-		I915_WRITE(SOUTH_CHICKEN2, tmp);
+	if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) &
+				FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100))
+		DRM_ERROR("FDI mPHY reset de-assert timeout\n");
+}
 
-		if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) &
-				        FDI_MPHY_IOSFSB_RESET_STATUS) == 0,
-				       100))
-			DRM_ERROR("FDI mPHY reset de-assert timeout\n");
-	}
+/* WaMPhyProgramming:hsw */
+static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv)
+{
+	uint32_t tmp;
 
 	tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY);
 	tmp &= ~(0xFF << 24);
 	tmp |= (0x12 << 24);
 	intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY);
 
-	if (is_sdv) {
-		tmp = intel_sbi_read(dev_priv, 0x800C, SBI_MPHY);
-		tmp |= 0x7FFF;
-		intel_sbi_write(dev_priv, 0x800C, tmp, SBI_MPHY);
-	}
-
 	tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY);
 	tmp |= (1 << 11);
 	intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY);
@@ -5195,24 +5215,6 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
 	tmp |= (1 << 11);
 	intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY);
 
-	if (is_sdv) {
-		tmp = intel_sbi_read(dev_priv, 0x2038, SBI_MPHY);
-		tmp |= (0x3F << 24) | (0xF << 20) | (0xF << 16);
-		intel_sbi_write(dev_priv, 0x2038, tmp, SBI_MPHY);
-
-		tmp = intel_sbi_read(dev_priv, 0x2138, SBI_MPHY);
-		tmp |= (0x3F << 24) | (0xF << 20) | (0xF << 16);
-		intel_sbi_write(dev_priv, 0x2138, tmp, SBI_MPHY);
-
-		tmp = intel_sbi_read(dev_priv, 0x203C, SBI_MPHY);
-		tmp |= (0x3F << 8);
-		intel_sbi_write(dev_priv, 0x203C, tmp, SBI_MPHY);
-
-		tmp = intel_sbi_read(dev_priv, 0x213C, SBI_MPHY);
-		tmp |= (0x3F << 8);
-		intel_sbi_write(dev_priv, 0x213C, tmp, SBI_MPHY);
-	}
-
 	tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY);
 	tmp |= (1 << 24) | (1 << 21) | (1 << 18);
 	intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY);
@@ -5221,17 +5223,15 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
 	tmp |= (1 << 24) | (1 << 21) | (1 << 18);
 	intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY);
 
-	if (!is_sdv) {
-		tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY);
-		tmp &= ~(7 << 13);
-		tmp |= (5 << 13);
-		intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY);
+	tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY);
+	tmp &= ~(7 << 13);
+	tmp |= (5 << 13);
+	intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY);
 
-		tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY);
-		tmp &= ~(7 << 13);
-		tmp |= (5 << 13);
-		intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY);
-	}
+	tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY);
+	tmp &= ~(7 << 13);
+	tmp |= (5 << 13);
+	intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY);
 
 	tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY);
 	tmp &= ~0xFF;
@@ -5253,34 +5253,120 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
 	tmp |= (0x1C << 16);
 	intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY);
 
-	if (!is_sdv) {
-		tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY);
-		tmp |= (1 << 27);
-		intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY);
+	tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY);
+	tmp |= (1 << 27);
+	intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY);
+
+	tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY);
+	tmp |= (1 << 27);
+	intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY);
+
+	tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY);
+	tmp &= ~(0xF << 28);
+	tmp |= (4 << 28);
+	intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY);
+
+	tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY);
+	tmp &= ~(0xF << 28);
+	tmp |= (4 << 28);
+	intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY);
+}
+
+/* Implements 3 different sequences from BSpec chapter "Display iCLK
+ * Programming" based on the parameters passed:
+ * - Sequence to enable CLKOUT_DP
+ * - Sequence to enable CLKOUT_DP without spread
+ * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O
+ */
+static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread,
+				 bool with_fdi)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t reg, tmp;
+
+	if (WARN(with_fdi && !with_spread, "FDI requires downspread\n"))
+		with_spread = true;
+	if (WARN(dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE &&
+		 with_fdi, "LP PCH doesn't have FDI\n"))
+		with_fdi = false;
+
+	mutex_lock(&dev_priv->dpio_lock);
+
+	tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
+	tmp &= ~SBI_SSCCTL_DISABLE;
+	tmp |= SBI_SSCCTL_PATHALT;
+	intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
 
-		tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY);
-		tmp |= (1 << 27);
-		intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY);
+	udelay(24);
 
-		tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY);
-		tmp &= ~(0xF << 28);
-		tmp |= (4 << 28);
-		intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY);
+	if (with_spread) {
+		tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
+		tmp &= ~SBI_SSCCTL_PATHALT;
+		intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
 
-		tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY);
-		tmp &= ~(0xF << 28);
-		tmp |= (4 << 28);
-		intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY);
+		if (with_fdi) {
+			lpt_reset_fdi_mphy(dev_priv);
+			lpt_program_fdi_mphy(dev_priv);
+		}
 	}
 
-	/* ULT uses SBI_GEN0, but ULT doesn't have VGA, so we don't care. */
-	tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK);
-	tmp |= SBI_DBUFF0_ENABLE;
-	intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK);
+	reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ?
+	       SBI_GEN0 : SBI_DBUFF0;
+	tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
+	tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
+	intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
 
 	mutex_unlock(&dev_priv->dpio_lock);
 }
 
+/* Sequence to disable CLKOUT_DP */
+static void lpt_disable_clkout_dp(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t reg, tmp;
+
+	mutex_lock(&dev_priv->dpio_lock);
+
+	reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ?
+	       SBI_GEN0 : SBI_DBUFF0;
+	tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
+	tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
+	intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
+
+	tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
+	if (!(tmp & SBI_SSCCTL_DISABLE)) {
+		if (!(tmp & SBI_SSCCTL_PATHALT)) {
+			tmp |= SBI_SSCCTL_PATHALT;
+			intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
+			udelay(32);
+		}
+		tmp |= SBI_SSCCTL_DISABLE;
+		intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
+	}
+
+	mutex_unlock(&dev_priv->dpio_lock);
+}
+
+static void lpt_init_pch_refclk(struct drm_device *dev)
+{
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *encoder;
+	bool has_vga = false;
+
+	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_ANALOG:
+			has_vga = true;
+			break;
+		}
+	}
+
+	if (has_vga)
+		lpt_enable_clkout_dp(dev, true, true);
+	else
+		lpt_disable_clkout_dp(dev);
+}
+
 /*
  * Initialize reference clocks when the driver loads
  */
@@ -5610,9 +5696,9 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 		<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 
 	if (is_sdvo)
-		dpll |= DPLL_DVO_HIGH_SPEED;
+		dpll |= DPLL_SDVO_HIGH_SPEED;
 	if (intel_crtc->config.has_dp_encoder)
-		dpll |= DPLL_DVO_HIGH_SPEED;
+		dpll |= DPLL_SDVO_HIGH_SPEED;
 
 	/* compute bitmask from p1 value */
 	dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
@@ -5708,7 +5794,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		else
 			intel_crtc->config.dpll_hw_state.fp1 = fp;
 
-		pll = intel_get_shared_dpll(intel_crtc, dpll, fp);
+		pll = intel_get_shared_dpll(intel_crtc);
 		if (pll == NULL) {
 			DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
 					 pipe_name(pipe));
@@ -5720,10 +5806,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	if (intel_crtc->config.has_dp_encoder)
 		intel_dp_set_m_n(intel_crtc);
 
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		if (encoder->pre_pll_enable)
-			encoder->pre_pll_enable(encoder);
-
 	if (is_lvds && has_reduced_clock && i915_powersave)
 		intel_crtc->lowfreq_avail = true;
 	else
@@ -5732,23 +5814,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	if (intel_crtc->config.has_pch_encoder) {
 		pll = intel_crtc_to_shared_dpll(intel_crtc);
 
-		I915_WRITE(PCH_DPLL(pll->id), dpll);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(PCH_DPLL(pll->id));
-		udelay(150);
-
-		/* The pixel multiplier can only be updated once the
-		 * DPLL is enabled and the clocks are stable.
-		 *
-		 * So write it again.
-		 */
-		I915_WRITE(PCH_DPLL(pll->id), dpll);
-
-		if (has_reduced_clock)
-			I915_WRITE(PCH_FP1(pll->id), fp2);
-		else
-			I915_WRITE(PCH_FP1(pll->id), fp);
 	}
 
 	intel_set_pipe_timings(intel_crtc);
@@ -5820,7 +5885,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
-	pipe_config->cpu_transcoder = crtc->pipe;
+	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
 	tmp = I915_READ(PIPECONF(crtc->pipe));
@@ -5838,12 +5903,9 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 
 		ironlake_get_fdi_m_n_config(crtc, pipe_config);
 
-		/* XXX: Can't properly read out the pch dpll pixel multiplier
-		 * since we don't have state tracking for pch clocks yet. */
-		pipe_config->pixel_multiplier = 1;
-
 		if (HAS_PCH_IBX(dev_priv->dev)) {
-			pipe_config->shared_dpll = crtc->pipe;
+			pipe_config->shared_dpll =
+				(enum intel_dpll_id) crtc->pipe;
 		} else {
 			tmp = I915_READ(PCH_DPLL_SEL);
 			if (tmp & TRANS_DPLLB_SEL(crtc->pipe))
@@ -5856,6 +5918,11 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 
 		WARN_ON(!pll->get_hw_state(dev_priv, pll,
 					   &pipe_config->dpll_hw_state));
+
+		tmp = pipe_config->dpll_hw_state.dpll;
+		pipe_config->pixel_multiplier =
+			((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK)
+			 >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1;
 	} else {
 		pipe_config->pixel_multiplier = 1;
 	}
@@ -5867,6 +5934,142 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 	return true;
 }
 
+static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	struct intel_crtc *crtc;
+	unsigned long irqflags;
+	uint32_t val, pch_hpd_mask;
+
+	pch_hpd_mask = SDE_PORTB_HOTPLUG_CPT | SDE_PORTC_HOTPLUG_CPT;
+	if (!(dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE))
+		pch_hpd_mask |= SDE_PORTD_HOTPLUG_CPT | SDE_CRT_HOTPLUG_CPT;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
+		WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+		     pipe_name(crtc->pipe));
+
+	WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
+	WARN(plls->spll_refcount, "SPLL enabled\n");
+	WARN(plls->wrpll1_refcount, "WRPLL1 enabled\n");
+	WARN(plls->wrpll2_refcount, "WRPLL2 enabled\n");
+	WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
+	WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
+	     "CPU PWM1 enabled\n");
+	WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
+	     "CPU PWM2 enabled\n");
+	WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
+	     "PCH PWM1 enabled\n");
+	WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
+	     "Utility pin enabled\n");
+	WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n");
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	val = I915_READ(DEIMR);
+	WARN((val & ~DE_PCH_EVENT_IVB) != val,
+	     "Unexpected DEIMR bits enabled: 0x%x\n", val);
+	val = I915_READ(SDEIMR);
+	WARN((val & ~pch_hpd_mask) != val,
+	     "Unexpected SDEIMR bits enabled: 0x%x\n", val);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+/*
+ * This function implements pieces of two sequences from BSpec:
+ * - Sequence for display software to disable LCPLL
+ * - Sequence for display software to allow package C8+
+ * The steps implemented here are just the steps that actually touch the LCPLL
+ * register. Callers should take care of disabling all the display engine
+ * functions, doing the mode unset, fixing interrupts, etc.
+ */
+void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
+		       bool switch_to_fclk, bool allow_power_down)
+{
+	uint32_t val;
+
+	assert_can_disable_lcpll(dev_priv);
+
+	val = I915_READ(LCPLL_CTL);
+
+	if (switch_to_fclk) {
+		val |= LCPLL_CD_SOURCE_FCLK;
+		I915_WRITE(LCPLL_CTL, val);
+
+		if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
+				       LCPLL_CD_SOURCE_FCLK_DONE, 1))
+			DRM_ERROR("Switching to FCLK failed\n");
+
+		val = I915_READ(LCPLL_CTL);
+	}
+
+	val |= LCPLL_PLL_DISABLE;
+	I915_WRITE(LCPLL_CTL, val);
+	POSTING_READ(LCPLL_CTL);
+
+	if (wait_for((I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK) == 0, 1))
+		DRM_ERROR("LCPLL still locked\n");
+
+	val = I915_READ(D_COMP);
+	val |= D_COMP_COMP_DISABLE;
+	I915_WRITE(D_COMP, val);
+	POSTING_READ(D_COMP);
+	ndelay(100);
+
+	if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1))
+		DRM_ERROR("D_COMP RCOMP still in progress\n");
+
+	if (allow_power_down) {
+		val = I915_READ(LCPLL_CTL);
+		val |= LCPLL_POWER_DOWN_ALLOW;
+		I915_WRITE(LCPLL_CTL, val);
+		POSTING_READ(LCPLL_CTL);
+	}
+}
+
+/*
+ * Fully restores LCPLL, disallowing power down and switching back to LCPLL
+ * source.
+ */
+void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
+{
+	uint32_t val;
+
+	val = I915_READ(LCPLL_CTL);
+
+	if ((val & (LCPLL_PLL_LOCK | LCPLL_PLL_DISABLE | LCPLL_CD_SOURCE_FCLK |
+		    LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK)
+		return;
+
+	if (val & LCPLL_POWER_DOWN_ALLOW) {
+		val &= ~LCPLL_POWER_DOWN_ALLOW;
+		I915_WRITE(LCPLL_CTL, val);
+	}
+
+	val = I915_READ(D_COMP);
+	val |= D_COMP_COMP_FORCE;
+	val &= ~D_COMP_COMP_DISABLE;
+	I915_WRITE(D_COMP, val);
+	I915_READ(D_COMP);
+
+	val = I915_READ(LCPLL_CTL);
+	val &= ~LCPLL_PLL_DISABLE;
+	I915_WRITE(LCPLL_CTL, val);
+
+	if (wait_for(I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK, 5))
+		DRM_ERROR("LCPLL not locked yet\n");
+
+	if (val & LCPLL_CD_SOURCE_FCLK) {
+		val = I915_READ(LCPLL_CTL);
+		val &= ~LCPLL_CD_SOURCE_FCLK;
+		I915_WRITE(LCPLL_CTL, val);
+
+		if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
+					LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
+			DRM_ERROR("Switching back to LCPLL failed\n");
+	}
+}
+
 static void haswell_modeset_global_resources(struct drm_device *dev)
 {
 	bool enable = false;
@@ -5935,7 +6138,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 	enum intel_display_power_domain pfit_domain;
 	uint32_t tmp;
 
-	pipe_config->cpu_transcoder = crtc->pipe;
+	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
 	tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
@@ -6005,11 +6208,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct intel_encoder *encoder;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_display_mode *adjusted_mode =
-		&intel_crtc->config.adjusted_mode;
 	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
 	int pipe = intel_crtc->pipe;
 	int ret;
@@ -6028,12 +6228,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			encoder->base.base.id,
 			drm_get_encoder_name(&encoder->base),
 			mode->base.id, mode->name);
-		if (encoder->mode_set) {
-			encoder->mode_set(encoder);
-		} else {
-			encoder_funcs = encoder->base.helper_private;
-			encoder_funcs->mode_set(&encoder->base, mode, adjusted_mode);
-		}
+		encoder->mode_set(encoder);
 	}
 
 	return 0;
@@ -6548,7 +6743,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 			goto fail_unpin;
 		}
 
-		addr = obj->gtt_offset;
+		addr = i915_gem_obj_ggtt_offset(obj);
 	} else {
 		int align = IS_I830(dev) ? 16 * 1024 : 256;
 		ret = i915_gem_attach_phys_object(dev, obj,
@@ -6875,11 +7070,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
 }
 
 /* Returns the clock of the currently programmed mode of the given pipe. */
-static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
+static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
+				struct intel_crtc_config *pipe_config)
 {
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	int pipe = pipe_config->cpu_transcoder;
 	u32 dpll = I915_READ(DPLL(pipe));
 	u32 fp;
 	intel_clock_t clock;
@@ -6918,7 +7114,8 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 		default:
 			DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
 				  "mode\n", (int)(dpll & DPLL_MODE_MASK));
-			return 0;
+			pipe_config->adjusted_mode.clock = 0;
+			return;
 		}
 
 		if (IS_PINEVIEW(dev))
@@ -6955,12 +7152,55 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 		}
 	}
 
-	/* XXX: It would be nice to validate the clocks, but we can't reuse
-	 * i830PllIsValid() because it relies on the xf86_config connector
-	 * configuration being accurate, which it isn't necessarily.
+	pipe_config->adjusted_mode.clock = clock.dot *
+		pipe_config->pixel_multiplier;
+}
+
+static void ironlake_crtc_clock_get(struct intel_crtc *crtc,
+				    struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
+	int link_freq, repeat;
+	u64 clock;
+	u32 link_m, link_n;
+
+	repeat = pipe_config->pixel_multiplier;
+
+	/*
+	 * The calculation for the data clock is:
+	 * pixel_clock = ((m/n)*(link_clock * nr_lanes * repeat))/bpp
+	 * But we want to avoid losing precison if possible, so:
+	 * pixel_clock = ((m * link_clock * nr_lanes * repeat)/(n*bpp))
+	 *
+	 * and the link clock is simpler:
+	 * link_clock = (m * link_clock * repeat) / n
 	 */
 
-	return clock.dot;
+	/*
+	 * We need to get the FDI or DP link clock here to derive
+	 * the M/N dividers.
+	 *
+	 * For FDI, we read it from the BIOS or use a fixed 2.7GHz.
+	 * For DP, it's either 1.62GHz or 2.7GHz.
+	 * We do our calculations in 10*MHz since we don't need much precison.
+	 */
+	if (pipe_config->has_pch_encoder)
+		link_freq = intel_fdi_link_freq(dev) * 10000;
+	else
+		link_freq = pipe_config->port_clock;
+
+	link_m = I915_READ(PIPE_LINK_M1(cpu_transcoder));
+	link_n = I915_READ(PIPE_LINK_N1(cpu_transcoder));
+
+	if (!link_m || !link_n)
+		return;
+
+	clock = ((u64)link_m * (u64)link_freq * (u64)repeat);
+	do_div(clock, link_n);
+
+	pipe_config->adjusted_mode.clock = clock;
 }
 
 /** Returns the currently programmed mode of the given pipe. */
@@ -6971,6 +7211,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
 	struct drm_display_mode *mode;
+	struct intel_crtc_config pipe_config;
 	int htot = I915_READ(HTOTAL(cpu_transcoder));
 	int hsync = I915_READ(HSYNC(cpu_transcoder));
 	int vtot = I915_READ(VTOTAL(cpu_transcoder));
@@ -6980,7 +7221,18 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 	if (!mode)
 		return NULL;
 
-	mode->clock = intel_crtc_clock_get(dev, crtc);
+	/*
+	 * Construct a pipe_config sufficient for getting the clock info
+	 * back out of crtc_clock_get.
+	 *
+	 * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
+	 * to use a real value here instead.
+	 */
+	pipe_config.cpu_transcoder = (enum transcoder) intel_crtc->pipe;
+	pipe_config.pixel_multiplier = 1;
+	i9xx_crtc_clock_get(intel_crtc, &pipe_config);
+
+	mode->clock = pipe_config.adjusted_mode.clock;
 	mode->hdisplay = (htot & 0xffff) + 1;
 	mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
 	mode->hsync_start = (hsync & 0xffff) + 1;
@@ -7263,7 +7515,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
 	intel_ring_emit(ring, MI_DISPLAY_FLIP |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 	intel_ring_emit(ring, fb->pitches[0]);
-	intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
 	intel_ring_emit(ring, 0); /* aux display base address, unused */
 
 	intel_mark_page_flip_active(intel_crtc);
@@ -7304,7 +7556,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
 	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 	intel_ring_emit(ring, fb->pitches[0]);
-	intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
 	intel_ring_emit(ring, MI_NOOP);
 
 	intel_mark_page_flip_active(intel_crtc);
@@ -7344,7 +7596,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 	intel_ring_emit(ring, fb->pitches[0]);
 	intel_ring_emit(ring,
-			(obj->gtt_offset + intel_crtc->dspaddr_offset) |
+			(i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset) |
 			obj->tiling_mode);
 
 	/* XXX Enabling the panel-fitter across page-flip is so far
@@ -7387,7 +7639,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
 	intel_ring_emit(ring, MI_DISPLAY_FLIP |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 	intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
-	intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
 
 	/* Contrary to the suggestions in the documentation,
 	 * "Enable Panel Fitter" does not seem to be required when page
@@ -7452,7 +7704,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
 
 	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
 	intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
-	intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
 	intel_ring_emit(ring, (MI_NOOP));
 
 	intel_mark_page_flip_active(intel_crtc);
@@ -7789,7 +8041,6 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 			  struct drm_display_mode *mode)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct intel_encoder *encoder;
 	struct intel_crtc_config *pipe_config;
 	int plane_bpp, ret = -EINVAL;
@@ -7806,9 +8057,23 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 
 	drm_mode_copy(&pipe_config->adjusted_mode, mode);
 	drm_mode_copy(&pipe_config->requested_mode, mode);
-	pipe_config->cpu_transcoder = to_intel_crtc(crtc)->pipe;
+	pipe_config->cpu_transcoder =
+		(enum transcoder) to_intel_crtc(crtc)->pipe;
 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
+	/*
+	 * Sanitize sync polarity flags based on requested ones. If neither
+	 * positive or negative polarity is requested, treat this as meaning
+	 * negative polarity.
+	 */
+	if (!(pipe_config->adjusted_mode.flags &
+	      (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC)))
+		pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (!(pipe_config->adjusted_mode.flags &
+	      (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)))
+		pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+
 	/* Compute a starting value for pipe_config->pipe_bpp taking the source
 	 * plane pixel format and any sink constraints into account. Returns the
 	 * source plane bpp so that dithering can be selected on mismatches
@@ -7823,6 +8088,9 @@ encoder_retry:
 	pipe_config->port_clock = 0;
 	pipe_config->pixel_multiplier = 1;
 
+	/* Fill in default crtc timings, allow encoders to overwrite them. */
+	drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, 0);
+
 	/* Pass our mode to the connectors and the CRTC to give them a chance to
 	 * adjust it according to limitations or connector properties, and also
 	 * a chance to reject the mode entirely.
@@ -7833,20 +8101,8 @@ encoder_retry:
 		if (&encoder->new_crtc->base != crtc)
 			continue;
 
-		if (encoder->compute_config) {
-			if (!(encoder->compute_config(encoder, pipe_config))) {
-				DRM_DEBUG_KMS("Encoder config failure\n");
-				goto fail;
-			}
-
-			continue;
-		}
-
-		encoder_funcs = encoder->base.helper_private;
-		if (!(encoder_funcs->mode_fixup(&encoder->base,
-						&pipe_config->requested_mode,
-						&pipe_config->adjusted_mode))) {
-			DRM_DEBUG_KMS("Encoder fixup failed\n");
+		if (!(encoder->compute_config(encoder, pipe_config))) {
+			DRM_DEBUG_KMS("Encoder config failure\n");
 			goto fail;
 		}
 	}
@@ -8041,6 +8297,28 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 
 }
 
+static bool intel_fuzzy_clock_check(struct intel_crtc_config *cur,
+				    struct intel_crtc_config *new)
+{
+	int clock1, clock2, diff;
+
+	clock1 = cur->adjusted_mode.clock;
+	clock2 = new->adjusted_mode.clock;
+
+	if (clock1 == clock2)
+		return true;
+
+	if (!clock1 || !clock2)
+		return false;
+
+	diff = abs(clock1 - clock2);
+
+	if (((((diff + clock1 + clock2) * 100)) / (clock1 + clock2)) < 105)
+		return true;
+
+	return false;
+}
+
 #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
 	list_for_each_entry((intel_crtc), \
 			    &(dev)->mode_config.crtc_list, \
@@ -8072,7 +8350,7 @@ intel_pipe_config_compare(struct drm_device *dev,
 
 #define PIPE_CONF_CHECK_FLAGS(name, mask)	\
 	if ((current_config->name ^ pipe_config->name) & (mask)) { \
-		DRM_ERROR("mismatch in " #name " " \
+		DRM_ERROR("mismatch in " #name "(" #mask ") "	   \
 			  "(expected %i, found %i)\n", \
 			  current_config->name & (mask), \
 			  pipe_config->name & (mask)); \
@@ -8106,8 +8384,7 @@ intel_pipe_config_compare(struct drm_device *dev,
 	PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start);
 	PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end);
 
-	if (!HAS_PCH_SPLIT(dev))
-		PIPE_CONF_CHECK_I(pixel_multiplier);
+	PIPE_CONF_CHECK_I(pixel_multiplier);
 
 	PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
 			      DRM_MODE_FLAG_INTERLACE);
@@ -8138,6 +8415,7 @@ intel_pipe_config_compare(struct drm_device *dev,
 
 	PIPE_CONF_CHECK_I(shared_dpll);
 	PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
+	PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
 
@@ -8146,6 +8424,15 @@ intel_pipe_config_compare(struct drm_device *dev,
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_QUIRK
 
+	if (!IS_HASWELL(dev)) {
+		if (!intel_fuzzy_clock_check(current_config, pipe_config)) {
+			DRM_ERROR("mismatch in clock (expected %d, found %d)\n",
+				  current_config->adjusted_mode.clock,
+				  pipe_config->adjusted_mode.clock);
+			return false;
+		}
+	}
+
 	return true;
 }
 
@@ -8269,12 +8556,17 @@ check_crtc_state(struct drm_device *dev)
 
 		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 				    base.head) {
+			enum pipe pipe;
 			if (encoder->base.crtc != &crtc->base)
 				continue;
-			if (encoder->get_config)
+			if (encoder->get_config &&
+			    encoder->get_hw_state(encoder, &pipe))
 				encoder->get_config(encoder, &pipe_config);
 		}
 
+		if (dev_priv->display.get_clock)
+			dev_priv->display.get_clock(crtc, &pipe_config);
+
 		WARN(crtc->active != active,
 		     "crtc active state doesn't match with hw state "
 		     "(expected %i, found %i)\n", crtc->active, active);
@@ -8571,8 +8863,16 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 	} else if (set->crtc->fb != set->fb) {
 		/* If we have no fb then treat it as a full mode set */
 		if (set->crtc->fb == NULL) {
-			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
-			config->mode_changed = true;
+			struct intel_crtc *intel_crtc =
+				to_intel_crtc(set->crtc);
+
+			if (intel_crtc->active && i915_fastboot) {
+				DRM_DEBUG_KMS("crtc has no fb, will flip\n");
+				config->fb_changed = true;
+			} else {
+				DRM_DEBUG_KMS("inactive crtc, full mode set\n");
+				config->mode_changed = true;
+			}
 		} else if (set->fb == NULL) {
 			config->mode_changed = true;
 		} else if (set->fb->pixel_format !=
@@ -8802,19 +9102,32 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 	return val & DPLL_VCO_ENABLE;
 }
 
+static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
+				  struct intel_shared_dpll *pll)
+{
+	I915_WRITE(PCH_FP0(pll->id), pll->hw_state.fp0);
+	I915_WRITE(PCH_FP1(pll->id), pll->hw_state.fp1);
+}
+
 static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
 				struct intel_shared_dpll *pll)
 {
-	uint32_t reg, val;
-
 	/* PCH refclock must be enabled first */
 	assert_pch_refclk_enabled(dev_priv);
 
-	reg = PCH_DPLL(pll->id);
-	val = I915_READ(reg);
-	val |= DPLL_VCO_ENABLE;
-	I915_WRITE(reg, val);
-	POSTING_READ(reg);
+	I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll);
+
+	/* Wait for the clocks to stabilize. */
+	POSTING_READ(PCH_DPLL(pll->id));
+	udelay(150);
+
+	/* The pixel multiplier can only be updated once the
+	 * DPLL is enabled and the clocks are stable.
+	 *
+	 * So write it again.
+	 */
+	I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll);
+	POSTING_READ(PCH_DPLL(pll->id));
 	udelay(200);
 }
 
@@ -8823,7 +9136,6 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct intel_crtc *crtc;
-	uint32_t reg, val;
 
 	/* Make sure no transcoder isn't still depending on us. */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
@@ -8831,11 +9143,8 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
 			assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
 	}
 
-	reg = PCH_DPLL(pll->id);
-	val = I915_READ(reg);
-	val &= ~DPLL_VCO_ENABLE;
-	I915_WRITE(reg, val);
-	POSTING_READ(reg);
+	I915_WRITE(PCH_DPLL(pll->id), 0);
+	POSTING_READ(PCH_DPLL(pll->id));
 	udelay(200);
 }
 
@@ -8854,6 +9163,7 @@ static void ibx_pch_dpll_init(struct drm_device *dev)
 	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
 		dev_priv->shared_dplls[i].id = i;
 		dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
+		dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set;
 		dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
 		dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
 		dev_priv->shared_dplls[i].get_hw_state =
@@ -9094,13 +9404,17 @@ static void intel_setup_outputs(struct drm_device *dev)
 	drm_helper_move_panel_connectors_to_head(dev);
 }
 
+void intel_framebuffer_fini(struct intel_framebuffer *fb)
+{
+	drm_framebuffer_cleanup(&fb->base);
+	drm_gem_object_unreference_unlocked(&fb->obj->base);
+}
+
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
-	drm_framebuffer_cleanup(fb);
-	drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
-
+	intel_framebuffer_fini(intel_fb);
 	kfree(intel_fb);
 }
 
@@ -9270,6 +9584,7 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
+		dev_priv->display.get_clock = ironlake_crtc_clock_get;
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
@@ -9277,6 +9592,7 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else if (IS_VALLEYVIEW(dev)) {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_clock = i9xx_crtc_clock_get;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 		dev_priv->display.crtc_enable = valleyview_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -9284,6 +9600,7 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.update_plane = i9xx_update_plane;
 	} else {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_clock = i9xx_crtc_clock_get;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 		dev_priv->display.crtc_enable = i9xx_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -9301,9 +9618,12 @@ static void intel_init_display(struct drm_device *dev)
 	else if (IS_I915G(dev))
 		dev_priv->display.get_display_clock_speed =
 			i915_get_display_clock_speed;
-	else if (IS_I945GM(dev) || IS_845G(dev) || IS_PINEVIEW_M(dev))
+	else if (IS_I945GM(dev) || IS_845G(dev))
 		dev_priv->display.get_display_clock_speed =
 			i9xx_misc_get_display_clock_speed;
+	else if (IS_PINEVIEW(dev))
+		dev_priv->display.get_display_clock_speed =
+			pnv_get_display_clock_speed;
 	else if (IS_I915GM(dev))
 		dev_priv->display.get_display_clock_speed =
 			i915gm_get_display_clock_speed;
@@ -9584,7 +9904,7 @@ void intel_modeset_init(struct drm_device *dev)
 		      INTEL_INFO(dev)->num_pipes,
 		      INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
 
-	for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
+	for_each_pipe(i) {
 		intel_crtc_init(dev, i);
 		for (j = 0; j < dev_priv->num_plane; j++) {
 			ret = intel_plane_init(dev, i, j);
@@ -9860,6 +10180,15 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			      pipe);
 	}
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		if (!crtc->active)
+			continue;
+		if (dev_priv->display.get_clock)
+			dev_priv->display.get_clock(crtc,
+						    &crtc->config);
+	}
+
 	list_for_each_entry(connector, &dev->mode_config.connector_list,
 			    base.head) {
 		if (connector->get_hw_state(connector)) {
@@ -9891,6 +10220,22 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 
 	intel_modeset_readout_hw_state(dev);
 
+	/*
+	 * Now that we have the config, copy it to each CRTC struct
+	 * Note that this could go away if we move to using crtc_config
+	 * checking everywhere.
+	 */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		if (crtc->active && i915_fastboot) {
+			intel_crtc_mode_from_pipe_config(crtc, &crtc->config);
+
+			DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
+				      crtc->base.base.id);
+			drm_mode_debug_printmodeline(&crtc->base.mode);
+		}
+	}
+
 	/* HW state is read out, now we need to sanitize this mess. */
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 			    base.head) {
@@ -10033,9 +10378,6 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 	return 0;
 }
 
-#ifdef CONFIG_DEBUG_FS
-#include <linux/seq_file.h>
-
 struct intel_display_error_state {
 
 	u32 power_well_driver;
@@ -10127,8 +10469,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 	 * well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to
 	 * prevent the next I915_WRITE from detecting it and printing an error
 	 * message. */
-	if (HAS_POWER_WELL(dev))
-		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+	intel_uncore_clear_errors(dev);
 
 	return error;
 }
@@ -10179,4 +10520,3 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
 		err_printf(m, "  BASE: %08x\n", error->cursor[i].base);
 	}
 }
-#endif
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 26e162b..63b6722d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -276,29 +276,13 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 	return status;
 }
 
-static int
-intel_dp_aux_ch(struct intel_dp *intel_dp,
-		uint8_t *send, int send_bytes,
-		uint8_t *recv, int recv_size)
+static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp,
+				      int index)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
-	uint32_t ch_data = ch_ctl + 4;
-	int i, ret, recv_bytes;
-	uint32_t status;
-	uint32_t aux_clock_divider;
-	int try, precharge;
-	bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
 
-	/* dp aux is extremely sensitive to irq latency, hence request the
-	 * lowest possible wakeup latency and so prevent the cpu from going into
-	 * deep sleep states.
-	 */
-	pm_qos_update_request(&dev_priv->pm_qos, 0);
-
-	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
 	 * hrawclk value and divide by 2 and use that
@@ -307,23 +291,53 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 * clock divider.
 	 */
 	if (IS_VALLEYVIEW(dev)) {
-		aux_clock_divider = 100;
+		return index ? 0 : 100;
 	} else if (intel_dig_port->port == PORT_A) {
+		if (index)
+			return 0;
 		if (HAS_DDI(dev))
-			aux_clock_divider = DIV_ROUND_CLOSEST(
-				intel_ddi_get_cdclk_freq(dev_priv), 2000);
+			return DIV_ROUND_CLOSEST(intel_ddi_get_cdclk_freq(dev_priv), 2000);
 		else if (IS_GEN6(dev) || IS_GEN7(dev))
-			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
+			return 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
-			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
+			return 225; /* eDP input clock at 450Mhz */
 	} else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
 		/* Workaround for non-ULT HSW */
-		aux_clock_divider = 74;
+		switch (index) {
+		case 0: return 63;
+		case 1: return 72;
+		default: return 0;
+		}
 	} else if (HAS_PCH_SPLIT(dev)) {
-		aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
+		return index ? 0 : DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
 	} else {
-		aux_clock_divider = intel_hrawclk(dev) / 2;
+		return index ? 0 :intel_hrawclk(dev) / 2;
 	}
+}
+
+static int
+intel_dp_aux_ch(struct intel_dp *intel_dp,
+		uint8_t *send, int send_bytes,
+		uint8_t *recv, int recv_size)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
+	uint32_t ch_data = ch_ctl + 4;
+	uint32_t aux_clock_divider;
+	int i, ret, recv_bytes;
+	uint32_t status;
+	int try, precharge, clock = 0;
+	bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
+
+	/* dp aux is extremely sensitive to irq latency, hence request the
+	 * lowest possible wakeup latency and so prevent the cpu from going into
+	 * deep sleep states.
+	 */
+	pm_qos_update_request(&dev_priv->pm_qos, 0);
+
+	intel_dp_check_edp(intel_dp);
 
 	if (IS_GEN6(dev))
 		precharge = 3;
@@ -345,37 +359,41 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 		goto out;
 	}
 
-	/* Must try at least 3 times according to DP spec */
-	for (try = 0; try < 5; try++) {
-		/* Load the send data into the aux channel data registers */
-		for (i = 0; i < send_bytes; i += 4)
-			I915_WRITE(ch_data + i,
-				   pack_aux(send + i, send_bytes - i));
-
-		/* Send the command and wait for it to complete */
-		I915_WRITE(ch_ctl,
-			   DP_AUX_CH_CTL_SEND_BUSY |
-			   (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |
-			   DP_AUX_CH_CTL_TIME_OUT_400us |
-			   (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-			   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
-			   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
-			   DP_AUX_CH_CTL_DONE |
-			   DP_AUX_CH_CTL_TIME_OUT_ERROR |
-			   DP_AUX_CH_CTL_RECEIVE_ERROR);
-
-		status = intel_dp_aux_wait_done(intel_dp, has_aux_irq);
-
-		/* Clear done status and any errors */
-		I915_WRITE(ch_ctl,
-			   status |
-			   DP_AUX_CH_CTL_DONE |
-			   DP_AUX_CH_CTL_TIME_OUT_ERROR |
-			   DP_AUX_CH_CTL_RECEIVE_ERROR);
-
-		if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
-			      DP_AUX_CH_CTL_RECEIVE_ERROR))
-			continue;
+	while ((aux_clock_divider = get_aux_clock_divider(intel_dp, clock++))) {
+		/* Must try at least 3 times according to DP spec */
+		for (try = 0; try < 5; try++) {
+			/* Load the send data into the aux channel data registers */
+			for (i = 0; i < send_bytes; i += 4)
+				I915_WRITE(ch_data + i,
+					   pack_aux(send + i, send_bytes - i));
+
+			/* Send the command and wait for it to complete */
+			I915_WRITE(ch_ctl,
+				   DP_AUX_CH_CTL_SEND_BUSY |
+				   (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |
+				   DP_AUX_CH_CTL_TIME_OUT_400us |
+				   (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+				   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+				   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
+				   DP_AUX_CH_CTL_DONE |
+				   DP_AUX_CH_CTL_TIME_OUT_ERROR |
+				   DP_AUX_CH_CTL_RECEIVE_ERROR);
+
+			status = intel_dp_aux_wait_done(intel_dp, has_aux_irq);
+
+			/* Clear done status and any errors */
+			I915_WRITE(ch_ctl,
+				   status |
+				   DP_AUX_CH_CTL_DONE |
+				   DP_AUX_CH_CTL_TIME_OUT_ERROR |
+				   DP_AUX_CH_CTL_RECEIVE_ERROR);
+
+			if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
+				      DP_AUX_CH_CTL_RECEIVE_ERROR))
+				continue;
+			if (status & DP_AUX_CH_CTL_DONE)
+				break;
+		}
 		if (status & DP_AUX_CH_CTL_DONE)
 			break;
 	}
@@ -710,8 +728,11 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Walk through all bpp values. Luckily they're all nicely spaced with 2
 	 * bpc in between. */
 	bpp = pipe_config->pipe_bpp;
-	if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp)
+	if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp) {
+		DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n",
+			      dev_priv->vbt.edp_bpp);
 		bpp = min_t(int, bpp, dev_priv->vbt.edp_bpp);
+	}
 
 	for (; bpp >= 6*3; bpp -= 2*3) {
 		mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
@@ -812,15 +833,14 @@ static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp)
 	udelay(500);
 }
 
-static void
-intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
-		  struct drm_display_mode *adjusted_mode)
+static void intel_dp_mode_set(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	enum port port = dp_to_dig_port(intel_dp)->port;
-	struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;
 
 	/*
 	 * There are four kinds of DP registers:
@@ -852,7 +872,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
 				 pipe_name(crtc->pipe));
 		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
-		intel_write_eld(encoder, adjusted_mode);
+		intel_write_eld(&encoder->base, adjusted_mode);
 	}
 
 	intel_dp_init_link_config(intel_dp);
@@ -1360,6 +1380,275 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
 	}
 
 	pipe_config->adjusted_mode.flags |= flags;
+
+	if (dp_to_dig_port(intel_dp)->port == PORT_A) {
+		if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ)
+			pipe_config->port_clock = 162000;
+		else
+			pipe_config->port_clock = 270000;
+	}
+}
+
+static bool is_edp_psr(struct intel_dp *intel_dp)
+{
+	return is_edp(intel_dp) &&
+		intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED;
+}
+
+static bool intel_edp_is_psr_enabled(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!IS_HASWELL(dev))
+		return false;
+
+	return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
+}
+
+static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
+				    struct edp_vsc_psr *vsc_psr)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
+	u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc->config.cpu_transcoder);
+	u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc->config.cpu_transcoder);
+	uint32_t *data = (uint32_t *) vsc_psr;
+	unsigned int i;
+
+	/* As per BSPec (Pipe Video Data Island Packet), we need to disable
+	   the video DIP being updated before program video DIP data buffer
+	   registers for DIP being updated. */
+	I915_WRITE(ctl_reg, 0);
+	POSTING_READ(ctl_reg);
+
+	for (i = 0; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) {
+		if (i < sizeof(struct edp_vsc_psr))
+			I915_WRITE(data_reg + i, *data++);
+		else
+			I915_WRITE(data_reg + i, 0);
+	}
+
+	I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW);
+	POSTING_READ(ctl_reg);
+}
+
+static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct edp_vsc_psr psr_vsc;
+
+	if (intel_dp->psr_setup_done)
+		return;
+
+	/* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
+	memset(&psr_vsc, 0, sizeof(psr_vsc));
+	psr_vsc.sdp_header.HB0 = 0;
+	psr_vsc.sdp_header.HB1 = 0x7;
+	psr_vsc.sdp_header.HB2 = 0x2;
+	psr_vsc.sdp_header.HB3 = 0x8;
+	intel_edp_psr_write_vsc(intel_dp, &psr_vsc);
+
+	/* Avoid continuous PSR exit by masking memup and hpd */
+	I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
+		   EDP_PSR_DEBUG_MASK_HPD);
+
+	intel_dp->psr_setup_done = true;
+}
+
+static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp, 0);
+	int precharge = 0x3;
+	int msg_size = 5;       /* Header(4) + Message(1) */
+
+	/* Enable PSR in sink */
+	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT)
+		intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
+					    DP_PSR_ENABLE &
+					    ~DP_PSR_MAIN_LINK_ACTIVE);
+	else
+		intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
+					    DP_PSR_ENABLE |
+					    DP_PSR_MAIN_LINK_ACTIVE);
+
+	/* Setup AUX registers */
+	I915_WRITE(EDP_PSR_AUX_DATA1, EDP_PSR_DPCD_COMMAND);
+	I915_WRITE(EDP_PSR_AUX_DATA2, EDP_PSR_DPCD_NORMAL_OPERATION);
+	I915_WRITE(EDP_PSR_AUX_CTL,
+		   DP_AUX_CH_CTL_TIME_OUT_400us |
+		   (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+		   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+		   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
+}
+
+static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t max_sleep_time = 0x1f;
+	uint32_t idle_frames = 1;
+	uint32_t val = 0x0;
+
+	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
+		val |= EDP_PSR_LINK_STANDBY;
+		val |= EDP_PSR_TP2_TP3_TIME_0us;
+		val |= EDP_PSR_TP1_TIME_0us;
+		val |= EDP_PSR_SKIP_AUX_EXIT;
+	} else
+		val |= EDP_PSR_LINK_DISABLE;
+
+	I915_WRITE(EDP_PSR_CTL, val |
+		   EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES |
+		   max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
+		   idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
+		   EDP_PSR_ENABLE);
+}
+
+static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dig_port->base.base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+
+	if (!IS_HASWELL(dev)) {
+		DRM_DEBUG_KMS("PSR not supported on this platform\n");
+		dev_priv->no_psr_reason = PSR_NO_SOURCE;
+		return false;
+	}
+
+	if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
+	    (dig_port->port != PORT_A)) {
+		DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
+		dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
+		return false;
+	}
+
+	if (!is_edp_psr(intel_dp)) {
+		DRM_DEBUG_KMS("PSR not supported by this panel\n");
+		dev_priv->no_psr_reason = PSR_NO_SINK;
+		return false;
+	}
+
+	if (!i915_enable_psr) {
+		DRM_DEBUG_KMS("PSR disable by flag\n");
+		dev_priv->no_psr_reason = PSR_MODULE_PARAM;
+		return false;
+	}
+
+	crtc = dig_port->base.base.crtc;
+	if (crtc == NULL) {
+		DRM_DEBUG_KMS("crtc not active for PSR\n");
+		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
+		return false;
+	}
+
+	intel_crtc = to_intel_crtc(crtc);
+	if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
+		DRM_DEBUG_KMS("crtc not active for PSR\n");
+		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
+		return false;
+	}
+
+	obj = to_intel_framebuffer(crtc->fb)->obj;
+	if (obj->tiling_mode != I915_TILING_X ||
+	    obj->fence_reg == I915_FENCE_REG_NONE) {
+		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
+		dev_priv->no_psr_reason = PSR_NOT_TILED;
+		return false;
+	}
+
+	if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
+		DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
+		dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
+		return false;
+	}
+
+	if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
+	    S3D_ENABLE) {
+		DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
+		dev_priv->no_psr_reason = PSR_S3D_ENABLED;
+		return false;
+	}
+
+	if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
+		DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
+		dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
+		return false;
+	}
+
+	return true;
+}
+
+static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+	if (!intel_edp_psr_match_conditions(intel_dp) ||
+	    intel_edp_is_psr_enabled(dev))
+		return;
+
+	/* Setup PSR once */
+	intel_edp_psr_setup(intel_dp);
+
+	/* Enable PSR on the panel */
+	intel_edp_psr_enable_sink(intel_dp);
+
+	/* Enable PSR on the host */
+	intel_edp_psr_enable_source(intel_dp);
+}
+
+void intel_edp_psr_enable(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+	if (intel_edp_psr_match_conditions(intel_dp) &&
+	    !intel_edp_is_psr_enabled(dev))
+		intel_edp_psr_do_enable(intel_dp);
+}
+
+void intel_edp_psr_disable(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!intel_edp_is_psr_enabled(dev))
+		return;
+
+	I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE);
+
+	/* Wait till PSR is idle */
+	if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
+		       EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
+		DRM_ERROR("Timed out waiting for PSR Idle State\n");
+}
+
+void intel_edp_psr_update(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP) {
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+			if (!is_edp_psr(intel_dp))
+				return;
+
+			if (!intel_edp_psr_match_conditions(intel_dp))
+				intel_edp_psr_disable(intel_dp);
+			else
+				if (!intel_edp_is_psr_enabled(dev))
+					intel_edp_psr_do_enable(intel_dp);
+		}
 }
 
 static void intel_disable_dp(struct intel_encoder *encoder)
@@ -1411,47 +1700,50 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	intel_dp_complete_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 	ironlake_edp_backlight_on(intel_dp);
+}
 
-	if (IS_VALLEYVIEW(dev)) {
-		struct intel_digital_port *dport =
-			enc_to_dig_port(&encoder->base);
-		int channel = vlv_dport_to_channel(dport);
-
-		vlv_wait_port_ready(dev_priv, channel);
-	}
+static void vlv_enable_dp(struct intel_encoder *encoder)
+{
 }
 
 static void intel_pre_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
+
+	if (dport->port == PORT_A)
+		ironlake_edp_pll_on(intel_dp);
+}
+
+static void vlv_pre_enable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	int port = vlv_dport_to_channel(dport);
+	int pipe = intel_crtc->pipe;
+	u32 val;
 
-	if (dport->port == PORT_A && !IS_VALLEYVIEW(dev))
-		ironlake_edp_pll_on(intel_dp);
+	mutex_lock(&dev_priv->dpio_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
-		struct intel_crtc *intel_crtc =
-			to_intel_crtc(encoder->base.crtc);
-		int port = vlv_dport_to_channel(dport);
-		int pipe = intel_crtc->pipe;
-		u32 val;
-
-		val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
-		val = 0;
-		if (pipe)
-			val |= (1<<21);
-		else
-			val &= ~(1<<21);
-		val |= 0x001000c4;
-		vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
+	val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
+	val = 0;
+	if (pipe)
+		val |= (1<<21);
+	else
+		val &= ~(1<<21);
+	val |= 0x001000c4;
+	vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
+	vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), 0x00760018);
+	vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), 0x00400888);
 
-		vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port),
-				 0x00760018);
-		vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
-				 0x00400888);
-	}
+	mutex_unlock(&dev_priv->dpio_lock);
+
+	intel_enable_dp(encoder);
+
+	vlv_wait_port_ready(dev_priv, port);
 }
 
 static void intel_dp_pre_pll_enable(struct intel_encoder *encoder)
@@ -1465,6 +1757,7 @@ static void intel_dp_pre_pll_enable(struct intel_encoder *encoder)
 		return;
 
 	/* Program Tx lane resets to default */
+	mutex_lock(&dev_priv->dpio_lock);
 	vlv_dpio_write(dev_priv, DPIO_PCS_TX(port),
 			 DPIO_PCS_TX_LANE2_RESET |
 			 DPIO_PCS_TX_LANE1_RESET);
@@ -1478,6 +1771,7 @@ static void intel_dp_pre_pll_enable(struct intel_encoder *encoder)
 	vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
 	vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
 	vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
+	mutex_unlock(&dev_priv->dpio_lock);
 }
 
 /*
@@ -1689,6 +1983,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
 		return 0;
 	}
 
+	mutex_lock(&dev_priv->dpio_lock);
 	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000);
 	vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value);
 	vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
@@ -1697,6 +1992,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
 	vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
 	vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value);
 	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000);
+	mutex_unlock(&dev_priv->dpio_lock);
 
 	return 0;
 }
@@ -2275,6 +2571,13 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0)
 		return false; /* DPCD not present */
 
+	/* Check if the panel supports PSR */
+	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
+	intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
+				       intel_dp->psr_dpcd,
+				       sizeof(intel_dp->psr_dpcd));
+	if (is_edp_psr(intel_dp))
+		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 	      DP_DWN_STRM_PORT_PRESENT))
 		return true; /* native DP sink */
@@ -2542,6 +2845,9 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
 
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+		      connector->base.id, drm_get_connector_name(connector));
+
 	intel_dp->has_audio = false;
 
 	if (HAS_PCH_SPLIT(dev))
@@ -2735,10 +3041,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	kfree(intel_dig_port);
 }
 
-static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
-	.mode_set = intel_dp_mode_set,
-};
-
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.dpms = intel_connector_dpms,
 	.detect = intel_dp_detect,
@@ -3166,6 +3468,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
+	intel_dp->psr_setup_done = false;
+
 	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
@@ -3216,17 +3520,21 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
 
 	intel_encoder->compute_config = intel_dp_compute_config;
-	intel_encoder->enable = intel_enable_dp;
-	intel_encoder->pre_enable = intel_pre_enable_dp;
+	intel_encoder->mode_set = intel_dp_mode_set;
 	intel_encoder->disable = intel_disable_dp;
 	intel_encoder->post_disable = intel_post_disable_dp;
 	intel_encoder->get_hw_state = intel_dp_get_hw_state;
 	intel_encoder->get_config = intel_dp_get_config;
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev)) {
 		intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
+		intel_encoder->pre_enable = vlv_pre_enable_dp;
+		intel_encoder->enable = vlv_enable_dp;
+	} else {
+		intel_encoder->pre_enable = intel_pre_enable_dp;
+		intel_encoder->enable = intel_enable_dp;
+	}
 
 	intel_dig_port->port = port;
 	intel_dig_port->dp.output_reg = output_reg;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b7d6e09..caf8b8d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -26,6 +26,7 @@
 #define __INTEL_DRV_H__
 
 #include <linux/i2c.h>
+#include <linux/hdmi.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include <drm/drm_crtc.h>
@@ -208,10 +209,6 @@ struct intel_crtc_config {
 
 	struct drm_display_mode requested_mode;
 	struct drm_display_mode adjusted_mode;
-	/* This flag must be set by the encoder's compute_config callback if it
-	 * changes the crtc timings in the mode to prevent the crtc fixup from
-	 * overwriting them.  Currently only lvds needs that. */
-	bool timings_set;
 	/* Whether to set up the PCH/FDI. Note that we never allow sharing
 	 * between pch encoders and cpu encoders. */
 	bool has_pch_encoder;
@@ -334,6 +331,13 @@ struct intel_crtc {
 	bool pch_fifo_underrun_disabled;
 };
 
+struct intel_plane_wm_parameters {
+	uint32_t horiz_pixels;
+	uint8_t bytes_per_pixel;
+	bool enabled;
+	bool scaled;
+};
+
 struct intel_plane {
 	struct drm_plane base;
 	int plane;
@@ -352,20 +356,18 @@ struct intel_plane {
 	 * as the other pieces of the struct may not reflect the values we want
 	 * for the watermark calculations. Currently only Haswell uses this.
 	 */
-	struct {
-		bool enable;
-		uint8_t bytes_per_pixel;
-		uint32_t horiz_pixels;
-	} wm;
+	struct intel_plane_wm_parameters wm;
 
 	void (*update_plane)(struct drm_plane *plane,
+			     struct drm_crtc *crtc,
 			     struct drm_framebuffer *fb,
 			     struct drm_i915_gem_object *obj,
 			     int crtc_x, int crtc_y,
 			     unsigned int crtc_w, unsigned int crtc_h,
 			     uint32_t x, uint32_t y,
 			     uint32_t src_w, uint32_t src_h);
-	void (*disable_plane)(struct drm_plane *plane);
+	void (*disable_plane)(struct drm_plane *plane,
+			      struct drm_crtc *crtc);
 	int (*update_colorkey)(struct drm_plane *plane,
 			       struct drm_intel_sprite_colorkey *key);
 	void (*get_colorkey)(struct drm_plane *plane,
@@ -397,66 +399,6 @@ struct cxsr_latency {
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)
 
-#define DIP_HEADER_SIZE	5
-
-#define DIP_TYPE_AVI    0x82
-#define DIP_VERSION_AVI 0x2
-#define DIP_LEN_AVI     13
-#define DIP_AVI_PR_1    0
-#define DIP_AVI_PR_2    1
-#define DIP_AVI_RGB_QUANT_RANGE_DEFAULT	(0 << 2)
-#define DIP_AVI_RGB_QUANT_RANGE_LIMITED	(1 << 2)
-#define DIP_AVI_RGB_QUANT_RANGE_FULL	(2 << 2)
-
-#define DIP_TYPE_SPD	0x83
-#define DIP_VERSION_SPD	0x1
-#define DIP_LEN_SPD	25
-#define DIP_SPD_UNKNOWN	0
-#define DIP_SPD_DSTB	0x1
-#define DIP_SPD_DVDP	0x2
-#define DIP_SPD_DVHS	0x3
-#define DIP_SPD_HDDVR	0x4
-#define DIP_SPD_DVC	0x5
-#define DIP_SPD_DSC	0x6
-#define DIP_SPD_VCD	0x7
-#define DIP_SPD_GAME	0x8
-#define DIP_SPD_PC	0x9
-#define DIP_SPD_BD	0xa
-#define DIP_SPD_SCD	0xb
-
-struct dip_infoframe {
-	uint8_t type;		/* HB0 */
-	uint8_t ver;		/* HB1 */
-	uint8_t len;		/* HB2 - body len, not including checksum */
-	uint8_t ecc;		/* Header ECC */
-	uint8_t checksum;	/* PB0 */
-	union {
-		struct {
-			/* PB1 - Y 6:5, A 4:4, B 3:2, S 1:0 */
-			uint8_t Y_A_B_S;
-			/* PB2 - C 7:6, M 5:4, R 3:0 */
-			uint8_t C_M_R;
-			/* PB3 - ITC 7:7, EC 6:4, Q 3:2, SC 1:0 */
-			uint8_t ITC_EC_Q_SC;
-			/* PB4 - VIC 6:0 */
-			uint8_t VIC;
-			/* PB5 - YQ 7:6, CN 5:4, PR 3:0 */
-			uint8_t YQ_CN_PR;
-			/* PB6 to PB13 */
-			uint16_t top_bar_end;
-			uint16_t bottom_bar_start;
-			uint16_t left_bar_end;
-			uint16_t right_bar_start;
-		} __attribute__ ((packed)) avi;
-		struct {
-			uint8_t vn[8];
-			uint8_t pd[16];
-			uint8_t sdi;
-		} __attribute__ ((packed)) spd;
-		uint8_t payload[27];
-	} __attribute__ ((packed)) body;
-} __attribute__((packed));
-
 struct intel_hdmi {
 	u32 hdmi_reg;
 	int ddc_bus;
@@ -467,7 +409,8 @@ struct intel_hdmi {
 	enum hdmi_force_audio force_audio;
 	bool rgb_quant_range_selectable;
 	void (*write_infoframe)(struct drm_encoder *encoder,
-				struct dip_infoframe *frame);
+				enum hdmi_infoframe_type type,
+				const uint8_t *frame, ssize_t len);
 	void (*set_infoframes)(struct drm_encoder *encoder,
 			       struct drm_display_mode *adjusted_mode);
 };
@@ -487,6 +430,7 @@ struct intel_dp {
 	uint8_t link_bw;
 	uint8_t lane_count;
 	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
+	uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
@@ -498,6 +442,7 @@ struct intel_dp {
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
 	bool want_panel_vdd;
+	bool psr_setup_done;
 	struct intel_connector *attached_connector;
 };
 
@@ -549,13 +494,6 @@ struct intel_unpin_work {
 	bool enable_stall_check;
 };
 
-struct intel_fbc_work {
-	struct delayed_work work;
-	struct drm_crtc *crtc;
-	struct drm_framebuffer *fb;
-	int interval;
-};
-
 int intel_pch_rawclk(struct drm_device *dev);
 
 int intel_connector_update_modes(struct drm_connector *connector,
@@ -574,7 +512,6 @@ extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
 extern bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 				      struct intel_crtc_config *pipe_config);
-extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 			    bool is_sdvob);
 extern void intel_dvo_init(struct drm_device *dev);
@@ -728,6 +665,7 @@ extern int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *ifb,
 				  struct drm_mode_fb_cmd2 *mode_cmd,
 				  struct drm_i915_gem_object *obj);
+extern void intel_framebuffer_fini(struct intel_framebuffer *fb);
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_initial_config(struct drm_device *dev);
 extern void intel_fbdev_fini(struct drm_device *dev);
@@ -747,6 +685,22 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
 extern void intel_fb_restore_mode(struct drm_device *dev);
 
+struct intel_shared_dpll *
+intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
+
+void assert_shared_dpll(struct drm_i915_private *dev_priv,
+			struct intel_shared_dpll *pll,
+			bool state);
+#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
+#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
+void assert_pll(struct drm_i915_private *dev_priv,
+		enum pipe pipe, bool state);
+#define assert_pll_enabled(d, p) assert_pll(d, p, true)
+#define assert_pll_disabled(d, p) assert_pll(d, p, false)
+void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
+		       enum pipe pipe, bool state);
+#define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true)
+#define assert_fdi_rx_pll_disabled(d, p) assert_fdi_rx_pll(d, p, false)
 extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 			bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
@@ -762,9 +716,10 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
 
 /* For use by IVB LP watermark workaround in intel_sprite.c */
 extern void intel_update_watermarks(struct drm_device *dev);
-extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
-					   uint32_t sprite_width,
-					   int pixel_size, bool enable);
+extern void intel_update_sprite_watermarks(struct drm_plane *plane,
+					   struct drm_crtc *crtc,
+					   uint32_t sprite_width, int pixel_size,
+					   bool enabled, bool scaled);
 
 extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
 						    unsigned int tiling_mode,
@@ -780,7 +735,6 @@ extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 extern void intel_init_pm(struct drm_device *dev);
 /* FBC */
 extern bool intel_fbc_enabled(struct drm_device *dev);
-extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern void intel_update_fbc(struct drm_device *dev);
 /* IPS */
 extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
@@ -796,7 +750,6 @@ extern void intel_init_power_well(struct drm_device *dev);
 extern void intel_set_power_well(struct drm_device *dev, bool enable);
 extern void intel_enable_gt_powersave(struct drm_device *dev);
 extern void intel_disable_gt_powersave(struct drm_device *dev);
-extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
 extern void ironlake_teardown_rc6(struct drm_device *dev);
 
 extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
@@ -825,4 +778,11 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 						 enum transcoder pch_transcoder,
 						 bool enable);
 
+extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
+extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
+extern void intel_edp_psr_update(struct drm_device *dev);
+extern void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
+			      bool switch_to_fclk, bool allow_power_down);
+extern void hsw_restore_lcpll(struct drm_i915_private *dev_priv);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index eb2020e..406303b 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -100,15 +100,14 @@ struct intel_dvo {
 	bool panel_wants_dither;
 };
 
-static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder)
+static struct intel_dvo *enc_to_dvo(struct intel_encoder *encoder)
 {
-	return container_of(encoder, struct intel_dvo, base.base);
+	return container_of(encoder, struct intel_dvo, base);
 }
 
 static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_dvo, base);
+	return enc_to_dvo(intel_attached_encoder(connector));
 }
 
 static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
@@ -123,7 +122,7 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
 	u32 tmp;
 
 	tmp = I915_READ(intel_dvo->dev.dvo_reg);
@@ -140,7 +139,7 @@ static void intel_dvo_get_config(struct intel_encoder *encoder,
 				 struct intel_crtc_config *pipe_config)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
 	u32 tmp, flags = 0;
 
 	tmp = I915_READ(intel_dvo->dev.dvo_reg);
@@ -159,7 +158,7 @@ static void intel_dvo_get_config(struct intel_encoder *encoder,
 static void intel_disable_dvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
 	u32 dvo_reg = intel_dvo->dev.dvo_reg;
 	u32 temp = I915_READ(dvo_reg);
 
@@ -171,7 +170,7 @@ static void intel_disable_dvo(struct intel_encoder *encoder)
 static void intel_enable_dvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
 	u32 dvo_reg = intel_dvo->dev.dvo_reg;
 	u32 temp = I915_READ(dvo_reg);
 
@@ -241,11 +240,11 @@ static int intel_dvo_mode_valid(struct drm_connector *connector,
 	return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
 }
 
-static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
-				 const struct drm_display_mode *mode,
-				 struct drm_display_mode *adjusted_mode)
+static bool intel_dvo_compute_config(struct intel_encoder *encoder,
+				     struct intel_crtc_config *pipe_config)
 {
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
+	struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 
 	/* If we have timings from the BIOS for the panel, put them in
 	 * to the adjusted mode.  The CRTC will be set up for this mode,
@@ -267,23 +266,23 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
 	}
 
 	if (intel_dvo->dev.dev_ops->mode_fixup)
-		return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev, mode, adjusted_mode);
+		return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev,
+							  &pipe_config->requested_mode,
+							  adjusted_mode);
 
 	return true;
 }
 
-static void intel_dvo_mode_set(struct drm_encoder *encoder,
-			       struct drm_display_mode *mode,
-			       struct drm_display_mode *adjusted_mode)
+static void intel_dvo_mode_set(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
-	int pipe = intel_crtc->pipe;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;
+	struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
+	int pipe = crtc->pipe;
 	u32 dvo_val;
 	u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
-	int dpll_reg = DPLL(pipe);
 
 	switch (dvo_reg) {
 	case DVOA:
@@ -298,7 +297,9 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
 		break;
 	}
 
-	intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, mode, adjusted_mode);
+	intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
+					 &crtc->config.requested_mode,
+					 adjusted_mode);
 
 	/* Save the data order, since I don't know what it should be set to. */
 	dvo_val = I915_READ(dvo_reg) &
@@ -314,8 +315,6 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		dvo_val |= DVO_VSYNC_ACTIVE_HIGH;
 
-	I915_WRITE(dpll_reg, I915_READ(dpll_reg) | DPLL_DVO_HIGH_SPEED);
-
 	/*I915_WRITE(DVOB_SRCDIM,
 	  (adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
 	  (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
@@ -335,6 +334,8 @@ static enum drm_connector_status
 intel_dvo_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+		      connector->base.id, drm_get_connector_name(connector));
 	return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
 }
 
@@ -372,11 +373,6 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
-	.mode_fixup = intel_dvo_mode_fixup,
-	.mode_set = intel_dvo_mode_set,
-};
-
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
 	.dpms = intel_dvo_dpms,
 	.detect = intel_dvo_detect,
@@ -392,7 +388,7 @@ static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs
 
 static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
 {
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
+	struct intel_dvo *intel_dvo = enc_to_dvo(to_intel_encoder(encoder));
 
 	if (intel_dvo->dev.dev_ops->destroy)
 		intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev);
@@ -471,6 +467,8 @@ void intel_dvo_init(struct drm_device *dev)
 	intel_encoder->enable = intel_enable_dvo;
 	intel_encoder->get_hw_state = intel_dvo_get_hw_state;
 	intel_encoder->get_config = intel_dvo_get_config;
+	intel_encoder->compute_config = intel_dvo_compute_config;
+	intel_encoder->mode_set = intel_dvo_mode_set;
 	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
 
 	/* Now, try to find a controller */
@@ -537,9 +535,6 @@ void intel_dvo_init(struct drm_device *dev)
 		connector->interlace_allowed = false;
 		connector->doublescan_allowed = false;
 
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_dvo_helper_funcs);
-
 		intel_connector_attach_encoder(intel_connector, intel_encoder);
 		if (dvo->type == INTEL_DVO_CHIP_LVDS) {
 			/* For our LVDS chipsets, we should hopefully be able
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index dff669e..bc21000 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -139,11 +139,11 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	info->apertures->ranges[0].base = dev->mode_config.fb_base;
 	info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
 
-	info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset;
+	info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
 	info->fix.smem_len = size;
 
 	info->screen_base =
-		ioremap_wc(dev_priv->gtt.mappable_base + obj->gtt_offset,
+		ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
 			   size);
 	if (!info->screen_base) {
 		ret = -ENOSPC;
@@ -166,9 +166,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
 
-	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
+	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n",
 		      fb->width, fb->height,
-		      obj->gtt_offset, obj);
+		      i915_gem_obj_ggtt_offset(obj), obj);
 
 
 	mutex_unlock(&dev->struct_mutex);
@@ -193,26 +193,21 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
 static void intel_fbdev_destroy(struct drm_device *dev,
 				struct intel_fbdev *ifbdev)
 {
-	struct fb_info *info;
-	struct intel_framebuffer *ifb = &ifbdev->ifb;
-
 	if (ifbdev->helper.fbdev) {
-		info = ifbdev->helper.fbdev;
+		struct fb_info *info = ifbdev->helper.fbdev;
+
 		unregister_framebuffer(info);
 		iounmap(info->screen_base);
 		if (info->cmap.len)
 			fb_dealloc_cmap(&info->cmap);
+
 		framebuffer_release(info);
 	}
 
 	drm_fb_helper_fini(&ifbdev->helper);
 
-	drm_framebuffer_unregister_private(&ifb->base);
-	drm_framebuffer_cleanup(&ifb->base);
-	if (ifb->obj) {
-		drm_gem_object_unreference_unlocked(&ifb->obj->base);
-		ifb->obj = NULL;
-	}
+	drm_framebuffer_unregister_private(&ifbdev->ifb.base);
+	intel_framebuffer_fini(&ifbdev->ifb);
 }
 
 int intel_fbdev_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 2fd3fd5..dd4fa35 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/hdmi.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -66,89 +67,75 @@ static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
 	return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
 }
 
-void intel_dip_infoframe_csum(struct dip_infoframe *frame)
+static u32 g4x_infoframe_index(enum hdmi_infoframe_type type)
 {
-	uint8_t *data = (uint8_t *)frame;
-	uint8_t sum = 0;
-	unsigned i;
-
-	frame->checksum = 0;
-	frame->ecc = 0;
-
-	for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
-		sum += data[i];
-
-	frame->checksum = 0x100 - sum;
-}
-
-static u32 g4x_infoframe_index(struct dip_infoframe *frame)
-{
-	switch (frame->type) {
-	case DIP_TYPE_AVI:
+	switch (type) {
+	case HDMI_INFOFRAME_TYPE_AVI:
 		return VIDEO_DIP_SELECT_AVI;
-	case DIP_TYPE_SPD:
+	case HDMI_INFOFRAME_TYPE_SPD:
 		return VIDEO_DIP_SELECT_SPD;
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
 		return 0;
 	}
 }
 
-static u32 g4x_infoframe_enable(struct dip_infoframe *frame)
+static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type)
 {
-	switch (frame->type) {
-	case DIP_TYPE_AVI:
+	switch (type) {
+	case HDMI_INFOFRAME_TYPE_AVI:
 		return VIDEO_DIP_ENABLE_AVI;
-	case DIP_TYPE_SPD:
+	case HDMI_INFOFRAME_TYPE_SPD:
 		return VIDEO_DIP_ENABLE_SPD;
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
 		return 0;
 	}
 }
 
-static u32 hsw_infoframe_enable(struct dip_infoframe *frame)
+static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
 {
-	switch (frame->type) {
-	case DIP_TYPE_AVI:
+	switch (type) {
+	case HDMI_INFOFRAME_TYPE_AVI:
 		return VIDEO_DIP_ENABLE_AVI_HSW;
-	case DIP_TYPE_SPD:
+	case HDMI_INFOFRAME_TYPE_SPD:
 		return VIDEO_DIP_ENABLE_SPD_HSW;
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
 		return 0;
 	}
 }
 
-static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame,
+static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
 				  enum transcoder cpu_transcoder)
 {
-	switch (frame->type) {
-	case DIP_TYPE_AVI:
+	switch (type) {
+	case HDMI_INFOFRAME_TYPE_AVI:
 		return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder);
-	case DIP_TYPE_SPD:
+	case HDMI_INFOFRAME_TYPE_SPD:
 		return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder);
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
 		return 0;
 	}
 }
 
 static void g4x_write_infoframe(struct drm_encoder *encoder,
-				struct dip_infoframe *frame)
+				enum hdmi_infoframe_type type,
+				const uint8_t *frame, ssize_t len)
 {
 	uint32_t *data = (uint32_t *)frame;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 val = I915_READ(VIDEO_DIP_CTL);
-	unsigned i, len = DIP_HEADER_SIZE + frame->len;
+	int i;
 
 	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
 	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-	val |= g4x_infoframe_index(frame);
+	val |= g4x_infoframe_index(type);
 
-	val &= ~g4x_infoframe_enable(frame);
+	val &= ~g4x_infoframe_enable(type);
 
 	I915_WRITE(VIDEO_DIP_CTL, val);
 
@@ -162,7 +149,7 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
 		I915_WRITE(VIDEO_DIP_DATA, 0);
 	mmiowb();
 
-	val |= g4x_infoframe_enable(frame);
+	val |= g4x_infoframe_enable(type);
 	val &= ~VIDEO_DIP_FREQ_MASK;
 	val |= VIDEO_DIP_FREQ_VSYNC;
 
@@ -171,22 +158,22 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
 }
 
 static void ibx_write_infoframe(struct drm_encoder *encoder,
-				struct dip_infoframe *frame)
+				enum hdmi_infoframe_type type,
+				const uint8_t *frame, ssize_t len)
 {
 	uint32_t *data = (uint32_t *)frame;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
-	unsigned i, len = DIP_HEADER_SIZE + frame->len;
+	int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
 	u32 val = I915_READ(reg);
 
 	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
 	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-	val |= g4x_infoframe_index(frame);
+	val |= g4x_infoframe_index(type);
 
-	val &= ~g4x_infoframe_enable(frame);
+	val &= ~g4x_infoframe_enable(type);
 
 	I915_WRITE(reg, val);
 
@@ -200,7 +187,7 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
 		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
 	mmiowb();
 
-	val |= g4x_infoframe_enable(frame);
+	val |= g4x_infoframe_enable(type);
 	val &= ~VIDEO_DIP_FREQ_MASK;
 	val |= VIDEO_DIP_FREQ_VSYNC;
 
@@ -209,25 +196,25 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
 }
 
 static void cpt_write_infoframe(struct drm_encoder *encoder,
-				struct dip_infoframe *frame)
+				enum hdmi_infoframe_type type,
+				const uint8_t *frame, ssize_t len)
 {
 	uint32_t *data = (uint32_t *)frame;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
-	unsigned i, len = DIP_HEADER_SIZE + frame->len;
+	int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
 	u32 val = I915_READ(reg);
 
 	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
 	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-	val |= g4x_infoframe_index(frame);
+	val |= g4x_infoframe_index(type);
 
 	/* The DIP control register spec says that we need to update the AVI
 	 * infoframe without clearing its enable bit */
-	if (frame->type != DIP_TYPE_AVI)
-		val &= ~g4x_infoframe_enable(frame);
+	if (type != HDMI_INFOFRAME_TYPE_AVI)
+		val &= ~g4x_infoframe_enable(type);
 
 	I915_WRITE(reg, val);
 
@@ -241,7 +228,7 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
 		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
 	mmiowb();
 
-	val |= g4x_infoframe_enable(frame);
+	val |= g4x_infoframe_enable(type);
 	val &= ~VIDEO_DIP_FREQ_MASK;
 	val |= VIDEO_DIP_FREQ_VSYNC;
 
@@ -250,22 +237,22 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
 }
 
 static void vlv_write_infoframe(struct drm_encoder *encoder,
-				     struct dip_infoframe *frame)
+				enum hdmi_infoframe_type type,
+				const uint8_t *frame, ssize_t len)
 {
 	uint32_t *data = (uint32_t *)frame;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
-	unsigned i, len = DIP_HEADER_SIZE + frame->len;
+	int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
 	u32 val = I915_READ(reg);
 
 	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
 
 	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-	val |= g4x_infoframe_index(frame);
+	val |= g4x_infoframe_index(type);
 
-	val &= ~g4x_infoframe_enable(frame);
+	val &= ~g4x_infoframe_enable(type);
 
 	I915_WRITE(reg, val);
 
@@ -279,7 +266,7 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
 		I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
 	mmiowb();
 
-	val |= g4x_infoframe_enable(frame);
+	val |= g4x_infoframe_enable(type);
 	val &= ~VIDEO_DIP_FREQ_MASK;
 	val |= VIDEO_DIP_FREQ_VSYNC;
 
@@ -288,21 +275,24 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
 }
 
 static void hsw_write_infoframe(struct drm_encoder *encoder,
-				struct dip_infoframe *frame)
+				enum hdmi_infoframe_type type,
+				const uint8_t *frame, ssize_t len)
 {
 	uint32_t *data = (uint32_t *)frame;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder);
-	u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->config.cpu_transcoder);
-	unsigned int i, len = DIP_HEADER_SIZE + frame->len;
+	u32 data_reg;
+	int i;
 	u32 val = I915_READ(ctl_reg);
 
+	data_reg = hsw_infoframe_data_reg(type,
+					  intel_crtc->config.cpu_transcoder);
 	if (data_reg == 0)
 		return;
 
-	val &= ~hsw_infoframe_enable(frame);
+	val &= ~hsw_infoframe_enable(type);
 	I915_WRITE(ctl_reg, val);
 
 	mmiowb();
@@ -315,18 +305,48 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
 		I915_WRITE(data_reg + i, 0);
 	mmiowb();
 
-	val |= hsw_infoframe_enable(frame);
+	val |= hsw_infoframe_enable(type);
 	I915_WRITE(ctl_reg, val);
 	POSTING_READ(ctl_reg);
 }
 
-static void intel_set_infoframe(struct drm_encoder *encoder,
-				struct dip_infoframe *frame)
+/*
+ * The data we write to the DIP data buffer registers is 1 byte bigger than the
+ * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting
+ * at 0). It's also a byte used by DisplayPort so the same DIP registers can be
+ * used for both technologies.
+ *
+ * DW0: Reserved/ECC/DP | HB2 | HB1 | HB0
+ * DW1:       DB3       | DB2 | DB1 | DB0
+ * DW2:       DB7       | DB6 | DB5 | DB4
+ * DW3: ...
+ *
+ * (HB is Header Byte, DB is Data Byte)
+ *
+ * The hdmi pack() functions don't know about that hardware specific hole so we
+ * trick them by giving an offset into the buffer and moving back the header
+ * bytes by one.
+ */
+static void intel_write_infoframe(struct drm_encoder *encoder,
+				  union hdmi_infoframe *frame)
 {
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	uint8_t buffer[VIDEO_DIP_DATA_SIZE];
+	ssize_t len;
 
-	intel_dip_infoframe_csum(frame);
-	intel_hdmi->write_infoframe(encoder, frame);
+	/* see comment above for the reason for this offset */
+	len = hdmi_infoframe_pack(frame, buffer + 1, sizeof(buffer) - 1);
+	if (len < 0)
+		return;
+
+	/* Insert the 'hole' (see big comment above) at position 3 */
+	buffer[0] = buffer[1];
+	buffer[1] = buffer[2];
+	buffer[2] = buffer[3];
+	buffer[3] = 0;
+	len++;
+
+	intel_hdmi->write_infoframe(encoder, frame->any.type, buffer, len);
 }
 
 static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
@@ -334,40 +354,42 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 {
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	struct dip_infoframe avi_if = {
-		.type = DIP_TYPE_AVI,
-		.ver = DIP_VERSION_AVI,
-		.len = DIP_LEN_AVI,
-	};
+	union hdmi_infoframe frame;
+	int ret;
 
-	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
-		avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2;
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+						       adjusted_mode);
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill AVI infoframe\n");
+		return;
+	}
 
 	if (intel_hdmi->rgb_quant_range_selectable) {
 		if (intel_crtc->config.limited_color_range)
-			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED;
+			frame.avi.quantization_range =
+				HDMI_QUANTIZATION_RANGE_LIMITED;
 		else
-			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL;
+			frame.avi.quantization_range =
+				HDMI_QUANTIZATION_RANGE_FULL;
 	}
 
-	avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode);
-
-	intel_set_infoframe(encoder, &avi_if);
+	intel_write_infoframe(encoder, &frame);
 }
 
 static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
 {
-	struct dip_infoframe spd_if;
+	union hdmi_infoframe frame;
+	int ret;
+
+	ret = hdmi_spd_infoframe_init(&frame.spd, "Intel", "Integrated gfx");
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill SPD infoframe\n");
+		return;
+	}
 
-	memset(&spd_if, 0, sizeof(spd_if));
-	spd_if.type = DIP_TYPE_SPD;
-	spd_if.ver = DIP_VERSION_SPD;
-	spd_if.len = DIP_LEN_SPD;
-	strcpy(spd_if.body.spd.vn, "Intel");
-	strcpy(spd_if.body.spd.pd, "Integrated gfx");
-	spd_if.body.spd.sdi = DIP_SPD_PC;
+	frame.spd.sdi = HDMI_SPD_SDI_PC;
 
-	intel_set_infoframe(encoder, &spd_if);
+	intel_write_infoframe(encoder, &frame);
 }
 
 static void g4x_set_infoframes(struct drm_encoder *encoder,
@@ -591,14 +613,13 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
 	intel_hdmi_set_spd_infoframe(encoder);
 }
 
-static void intel_hdmi_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
+static void intel_hdmi_mode_set(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;
 	u32 hdmi_val;
 
 	hdmi_val = SDVO_ENCODING_HDMI;
@@ -609,7 +630,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 		hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH;
 
-	if (intel_crtc->config.pipe_bpp > 24)
+	if (crtc->config.pipe_bpp > 24)
 		hdmi_val |= HDMI_COLOR_FORMAT_12bpc;
 	else
 		hdmi_val |= SDVO_COLOR_FORMAT_8bpc;
@@ -620,21 +641,21 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 
 	if (intel_hdmi->has_audio) {
 		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
-				 pipe_name(intel_crtc->pipe));
+				 pipe_name(crtc->pipe));
 		hdmi_val |= SDVO_AUDIO_ENABLE;
 		hdmi_val |= HDMI_MODE_SELECT_HDMI;
-		intel_write_eld(encoder, adjusted_mode);
+		intel_write_eld(&encoder->base, adjusted_mode);
 	}
 
 	if (HAS_PCH_CPT(dev))
-		hdmi_val |= SDVO_PIPE_SEL_CPT(intel_crtc->pipe);
+		hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
 	else
-		hdmi_val |= SDVO_PIPE_SEL(intel_crtc->pipe);
+		hdmi_val |= SDVO_PIPE_SEL(crtc->pipe);
 
 	I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val);
 	POSTING_READ(intel_hdmi->hdmi_reg);
 
-	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+	intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
 }
 
 static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
@@ -719,14 +740,10 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
 		I915_WRITE(intel_hdmi->hdmi_reg, temp);
 		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
+}
 
-	if (IS_VALLEYVIEW(dev)) {
-		struct intel_digital_port *dport =
-			enc_to_dig_port(&encoder->base);
-		int channel = vlv_dport_to_channel(dport);
-
-		vlv_wait_port_ready(dev_priv, channel);
-	}
+static void vlv_enable_hdmi(struct intel_encoder *encoder)
+{
 }
 
 static void intel_disable_hdmi(struct intel_encoder *encoder)
@@ -879,6 +896,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 	struct edid *edid;
 	enum drm_connector_status status = connector_status_disconnected;
 
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+		      connector->base.id, drm_get_connector_name(connector));
+
 	intel_hdmi->has_hdmi_sink = false;
 	intel_hdmi->has_audio = false;
 	intel_hdmi->rgb_quant_range_selectable = false;
@@ -1030,6 +1050,7 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
 		return;
 
 	/* Enable clock channels for this port */
+	mutex_lock(&dev_priv->dpio_lock);
 	val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
 	val = 0;
 	if (pipe)
@@ -1060,6 +1081,11 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
 			 0x00760018);
 	vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
 			 0x00400888);
+	mutex_unlock(&dev_priv->dpio_lock);
+
+	intel_enable_hdmi(encoder);
+
+	vlv_wait_port_ready(dev_priv, port);
 }
 
 static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
@@ -1073,6 +1099,7 @@ static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 		return;
 
 	/* Program Tx lane resets to default */
+	mutex_lock(&dev_priv->dpio_lock);
 	vlv_dpio_write(dev_priv, DPIO_PCS_TX(port),
 			 DPIO_PCS_TX_LANE2_RESET |
 			 DPIO_PCS_TX_LANE1_RESET);
@@ -1091,6 +1118,7 @@ static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 			 0x00002000);
 	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
 			 DPIO_TX_OCALINIT_EN);
+	mutex_unlock(&dev_priv->dpio_lock);
 }
 
 static void intel_hdmi_post_disable(struct intel_encoder *encoder)
@@ -1113,10 +1141,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
-	.mode_set = intel_hdmi_mode_set,
-};
-
 static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
 	.dpms = intel_connector_dpms,
 	.detect = intel_hdmi_detect,
@@ -1239,17 +1263,19 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
 	intel_encoder->compute_config = intel_hdmi_compute_config;
-	intel_encoder->enable = intel_enable_hdmi;
+	intel_encoder->mode_set = intel_hdmi_mode_set;
 	intel_encoder->disable = intel_disable_hdmi;
 	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
 	intel_encoder->get_config = intel_hdmi_get_config;
 	if (IS_VALLEYVIEW(dev)) {
-		intel_encoder->pre_enable = intel_hdmi_pre_enable;
 		intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
+		intel_encoder->pre_enable = intel_hdmi_pre_enable;
+		intel_encoder->enable = vlv_enable_hdmi;
 		intel_encoder->post_disable = intel_hdmi_post_disable;
+	} else {
+		intel_encoder->enable = intel_enable_hdmi;
 	}
 
 	intel_encoder->type = INTEL_OUTPUT_HDMI;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 61348ea..4d33278 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -122,17 +122,25 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
  * This is an exception to the general rule that mode_set doesn't turn
  * things on.
  */
-static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
+static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 {
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	struct drm_display_mode *fixed_mode =
 		lvds_encoder->attached_connector->base.panel.fixed_mode;
-	int pipe = intel_crtc->pipe;
+	int pipe = crtc->pipe;
 	u32 temp;
 
+	if (HAS_PCH_SPLIT(dev)) {
+		assert_fdi_rx_pll_disabled(dev_priv, pipe);
+		assert_shared_dpll_disabled(dev_priv,
+					    intel_crtc_to_shared_dpll(crtc));
+	} else {
+		assert_pll_disabled(dev_priv, pipe);
+	}
+
 	temp = I915_READ(lvds_encoder->reg);
 	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
 
@@ -149,7 +157,7 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
 
 	/* set the corresponsding LVDS_BORDER bit */
 	temp &= ~LVDS_BORDER_ENABLE;
-	temp |= intel_crtc->config.gmch_pfit.lvds_border_bits;
+	temp |= crtc->config.gmch_pfit.lvds_border_bits;
 	/* Set the B0-B3 data pairs corresponding to whether we're going to
 	 * set the DPLLs for dual-channel mode or not.
 	 */
@@ -169,8 +177,7 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
 	if (INTEL_INFO(dev)->gen == 4) {
 		/* Bspec wording suggests that LVDS port dithering only exists
 		 * for 18bpp panels. */
-		if (intel_crtc->config.dither &&
-		    intel_crtc->config.pipe_bpp == 18)
+		if (crtc->config.dither && crtc->config.pipe_bpp == 18)
 			temp |= LVDS_ENABLE_DITHER;
 		else
 			temp &= ~LVDS_ENABLE_DITHER;
@@ -312,14 +319,12 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 	return true;
 }
 
-static void intel_lvds_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
+static void intel_lvds_mode_set(struct intel_encoder *encoder)
 {
 	/*
-	 * The LVDS pin pair will already have been turned on in the
-	 * intel_crtc_mode_set since it has a large impact on the DPLL
-	 * settings.
+	 * We don't do anything here, the LVDS port is fully set up in the pre
+	 * enable hook - the ordering constraints for enabling the lvds port vs.
+	 * enabling the display pll are too strict.
 	 */
 }
 
@@ -336,6 +341,9 @@ intel_lvds_detect(struct drm_connector *connector, bool force)
 	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+		      connector->base.id, drm_get_connector_name(connector));
+
 	status = intel_panel_detect(dev);
 	if (status != connector_status_unknown)
 		return status;
@@ -497,10 +505,6 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 	return 0;
 }
 
-static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
-	.mode_set = intel_lvds_mode_set,
-};
-
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
 	.get_modes = intel_lvds_get_modes,
 	.mode_valid = intel_lvds_mode_valid,
@@ -959,8 +963,9 @@ void intel_lvds_init(struct drm_device *dev)
 			 DRM_MODE_ENCODER_LVDS);
 
 	intel_encoder->enable = intel_enable_lvds;
-	intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
+	intel_encoder->pre_enable = intel_pre_enable_lvds;
 	intel_encoder->compute_config = intel_lvds_compute_config;
+	intel_encoder->mode_set = intel_lvds_mode_set;
 	intel_encoder->disable = intel_disable_lvds;
 	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
 	intel_encoder->get_config = intel_lvds_get_config;
@@ -977,7 +982,6 @@ void intel_lvds_init(struct drm_device *dev)
 	else
 		intel_encoder->crtc_mask = (1 << 1);
 
-	drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
 	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 	connector->interlace_allowed = false;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index a369881..ddfd0ae 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -196,7 +196,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay)
 		regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_obj->handle->vaddr;
 	else
 		regs = io_mapping_map_wc(dev_priv->gtt.mappable,
-					 overlay->reg_bo->gtt_offset);
+					 i915_gem_obj_ggtt_offset(overlay->reg_bo));
 
 	return regs;
 }
@@ -740,7 +740,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 	swidth = params->src_w;
 	swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
 	sheight = params->src_h;
-	iowrite32(new_bo->gtt_offset + params->offset_Y, &regs->OBUF_0Y);
+	iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_Y, &regs->OBUF_0Y);
 	ostride = params->stride_Y;
 
 	if (params->format & I915_OVERLAY_YUV_PLANAR) {
@@ -754,8 +754,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 				      params->src_w/uv_hscale);
 		swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
 		sheight |= (params->src_h/uv_vscale) << 16;
-		iowrite32(new_bo->gtt_offset + params->offset_U, &regs->OBUF_0U);
-		iowrite32(new_bo->gtt_offset + params->offset_V, &regs->OBUF_0V);
+		iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_U, &regs->OBUF_0U);
+		iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_V, &regs->OBUF_0V);
 		ostride |= params->stride_UV << 16;
 	}
 
@@ -1333,7 +1333,9 @@ void intel_setup_overlay(struct drm_device *dev)
 
 	overlay->dev = dev;
 
-	reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE);
+	reg_bo = NULL;
+	if (!OVERLAY_NEEDS_PHYSICAL(dev))
+		reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE);
 	if (reg_bo == NULL)
 		reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
 	if (reg_bo == NULL)
@@ -1350,12 +1352,12 @@ void intel_setup_overlay(struct drm_device *dev)
 		}
 		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
 	} else {
-		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true, false);
+		ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, true, false);
 		if (ret) {
 			DRM_ERROR("failed to pin overlay register bo\n");
 			goto out_free_bo;
 		}
-		overlay->flip_addr = reg_bo->gtt_offset;
+		overlay->flip_addr = i915_gem_obj_ggtt_offset(reg_bo);
 
 		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
 		if (ret) {
@@ -1412,9 +1414,6 @@ void intel_cleanup_overlay(struct drm_device *dev)
 	kfree(dev_priv->overlay);
 }
 
-#ifdef CONFIG_DEBUG_FS
-#include <linux/seq_file.h>
-
 struct intel_overlay_error_state {
 	struct overlay_registers regs;
 	unsigned long base;
@@ -1435,7 +1434,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
 			overlay->reg_bo->phys_obj->handle->vaddr;
 	else
 		regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
-						overlay->reg_bo->gtt_offset);
+						i915_gem_obj_ggtt_offset(overlay->reg_bo));
 
 	return regs;
 }
@@ -1468,7 +1467,7 @@ intel_overlay_capture_error_state(struct drm_device *dev)
 	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
 		error->base = (__force long)overlay->reg_bo->phys_obj->handle->vaddr;
 	else
-		error->base = overlay->reg_bo->gtt_offset;
+		error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo);
 
 	regs = intel_overlay_map_regs_atomic(overlay);
 	if (!regs)
@@ -1537,4 +1536,3 @@ intel_overlay_print_error_state(struct drm_i915_error_state_buf *m,
 	P(UVSCALEV);
 #undef P
 }
-#endif
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 67e2c1f..a43c33b 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -194,9 +194,6 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
 	    adjusted_mode->vdisplay == mode->vdisplay)
 		goto out;
 
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-	pipe_config->timings_set = true;
-
 	switch (fitting_mode) {
 	case DRM_MODE_SCALE_CENTER:
 		/*
@@ -497,8 +494,11 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
 		goto out;
 	}
 
-	/* scale to hardware */
-	level = level * freq / max;
+	/* scale to hardware, but be careful to not overflow */
+	if (freq < max)
+		level = level * freq / max;
+	else
+		level = freq / max * level;
 
 	dev_priv->backlight.level = level;
 	if (dev_priv->backlight.device)
@@ -515,6 +515,17 @@ void intel_panel_disable_backlight(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
+	/*
+	 * Do not disable backlight on the vgaswitcheroo path. When switching
+	 * away from i915, the other client may depend on i915 to handle the
+	 * backlight. This will leave the backlight on unnecessarily when
+	 * another client is not activated.
+	 */
+	if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
+		DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
+		return;
+	}
+
 	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
 
 	dev_priv->backlight.enabled = false;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f895d15..96234c6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -30,8 +30,7 @@
 #include "intel_drv.h"
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
-
-#define FORCEWAKE_ACK_TIMEOUT_MS 2
+#include <drm/i915_powerwell.h>
 
 /* FBC, or Frame Buffer Compression, is a technique employed to compress the
  * framebuffer contents in-memory, aiming at reducing the required bandwidth
@@ -86,7 +85,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	int plane, i;
 	u32 fbc_ctl, fbc_ctl2;
 
-	cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
+	cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
 	if (fb->pitches[0] < cfb_pitch)
 		cfb_pitch = fb->pitches[0];
 
@@ -217,7 +216,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 		   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
 		   (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
 	I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
-	I915_WRITE(ILK_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID);
+	I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
 	/* enable it... */
 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
@@ -274,7 +273,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset);
+	I915_WRITE(IVB_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj));
 
 	I915_WRITE(ILK_DPFC_CONTROL, DPFC_CTL_EN | DPFC_CTL_LIMIT_1X |
 		   IVB_DPFC_CTL_FENCE_EN |
@@ -325,7 +324,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	mutex_lock(&dev->struct_mutex);
-	if (work == dev_priv->fbc_work) {
+	if (work == dev_priv->fbc.fbc_work) {
 		/* Double check that we haven't switched fb without cancelling
 		 * the prior work.
 		 */
@@ -333,12 +332,12 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 			dev_priv->display.enable_fbc(work->crtc,
 						     work->interval);
 
-			dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
-			dev_priv->cfb_fb = work->crtc->fb->base.id;
-			dev_priv->cfb_y = work->crtc->y;
+			dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
+			dev_priv->fbc.fb_id = work->crtc->fb->base.id;
+			dev_priv->fbc.y = work->crtc->y;
 		}
 
-		dev_priv->fbc_work = NULL;
+		dev_priv->fbc.fbc_work = NULL;
 	}
 	mutex_unlock(&dev->struct_mutex);
 
@@ -347,28 +346,28 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 
 static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
 {
-	if (dev_priv->fbc_work == NULL)
+	if (dev_priv->fbc.fbc_work == NULL)
 		return;
 
 	DRM_DEBUG_KMS("cancelling pending FBC enable\n");
 
 	/* Synchronisation is provided by struct_mutex and checking of
-	 * dev_priv->fbc_work, so we can perform the cancellation
+	 * dev_priv->fbc.fbc_work, so we can perform the cancellation
 	 * entirely asynchronously.
 	 */
-	if (cancel_delayed_work(&dev_priv->fbc_work->work))
+	if (cancel_delayed_work(&dev_priv->fbc.fbc_work->work))
 		/* tasklet was killed before being run, clean up */
-		kfree(dev_priv->fbc_work);
+		kfree(dev_priv->fbc.fbc_work);
 
 	/* Mark the work as no longer wanted so that if it does
 	 * wake-up (because the work was already running and waiting
 	 * for our mutex), it will discover that is no longer
 	 * necessary to run.
 	 */
-	dev_priv->fbc_work = NULL;
+	dev_priv->fbc.fbc_work = NULL;
 }
 
-void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 {
 	struct intel_fbc_work *work;
 	struct drm_device *dev = crtc->dev;
@@ -381,6 +380,7 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
 	work = kzalloc(sizeof *work, GFP_KERNEL);
 	if (work == NULL) {
+		DRM_ERROR("Failed to allocate FBC work structure\n");
 		dev_priv->display.enable_fbc(crtc, interval);
 		return;
 	}
@@ -390,9 +390,7 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	work->interval = interval;
 	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
 
-	dev_priv->fbc_work = work;
-
-	DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
+	dev_priv->fbc.fbc_work = work;
 
 	/* Delay the actual enabling to let pageflipping cease and the
 	 * display to settle before starting the compression. Note that
@@ -404,6 +402,8 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	 * following the termination of the page-flipping sequence
 	 * and indeed performing the enable as a co-routine and not
 	 * waiting synchronously upon the vblank.
+	 *
+	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
 	 */
 	schedule_delayed_work(&work->work, msecs_to_jiffies(50));
 }
@@ -418,7 +418,17 @@ void intel_disable_fbc(struct drm_device *dev)
 		return;
 
 	dev_priv->display.disable_fbc(dev);
-	dev_priv->cfb_plane = -1;
+	dev_priv->fbc.plane = -1;
+}
+
+static bool set_no_fbc_reason(struct drm_i915_private *dev_priv,
+			      enum no_fbc_reason reason)
+{
+	if (dev_priv->fbc.no_fbc_reason == reason)
+		return false;
+
+	dev_priv->fbc.no_fbc_reason = reason;
+	return true;
 }
 
 /**
@@ -448,14 +458,18 @@ void intel_update_fbc(struct drm_device *dev)
 	struct drm_framebuffer *fb;
 	struct intel_framebuffer *intel_fb;
 	struct drm_i915_gem_object *obj;
-	int enable_fbc;
 	unsigned int max_hdisplay, max_vdisplay;
 
-	if (!i915_powersave)
+	if (!I915_HAS_FBC(dev)) {
+		set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED);
 		return;
+	}
 
-	if (!I915_HAS_FBC(dev))
+	if (!i915_powersave) {
+		if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM))
+			DRM_DEBUG_KMS("fbc disabled per module param\n");
 		return;
+	}
 
 	/*
 	 * If FBC is already on, we just have to verify that we can
@@ -470,8 +484,8 @@ void intel_update_fbc(struct drm_device *dev)
 		if (intel_crtc_active(tmp_crtc) &&
 		    !to_intel_crtc(tmp_crtc)->primary_disabled) {
 			if (crtc) {
-				DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
-				dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
+				if (set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES))
+					DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
 				goto out_disable;
 			}
 			crtc = tmp_crtc;
@@ -479,8 +493,8 @@ void intel_update_fbc(struct drm_device *dev)
 	}
 
 	if (!crtc || crtc->fb == NULL) {
-		DRM_DEBUG_KMS("no output, disabling\n");
-		dev_priv->no_fbc_reason = FBC_NO_OUTPUT;
+		if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT))
+			DRM_DEBUG_KMS("no output, disabling\n");
 		goto out_disable;
 	}
 
@@ -489,23 +503,22 @@ void intel_update_fbc(struct drm_device *dev)
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
 
-	enable_fbc = i915_enable_fbc;
-	if (enable_fbc < 0) {
-		DRM_DEBUG_KMS("fbc set to per-chip default\n");
-		enable_fbc = 1;
-		if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
-			enable_fbc = 0;
+	if (i915_enable_fbc < 0 &&
+	    INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) {
+		if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT))
+			DRM_DEBUG_KMS("disabled per chip default\n");
+		goto out_disable;
 	}
-	if (!enable_fbc) {
-		DRM_DEBUG_KMS("fbc disabled per module param\n");
-		dev_priv->no_fbc_reason = FBC_MODULE_PARAM;
+	if (!i915_enable_fbc) {
+		if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM))
+			DRM_DEBUG_KMS("fbc disabled per module param\n");
 		goto out_disable;
 	}
 	if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
 	    (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
-		DRM_DEBUG_KMS("mode incompatible with compression, "
-			      "disabling\n");
-		dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
+		if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE))
+			DRM_DEBUG_KMS("mode incompatible with compression, "
+				      "disabling\n");
 		goto out_disable;
 	}
 
@@ -518,14 +531,14 @@ void intel_update_fbc(struct drm_device *dev)
 	}
 	if ((crtc->mode.hdisplay > max_hdisplay) ||
 	    (crtc->mode.vdisplay > max_vdisplay)) {
-		DRM_DEBUG_KMS("mode too large for compression, disabling\n");
-		dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
+		if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE))
+			DRM_DEBUG_KMS("mode too large for compression, disabling\n");
 		goto out_disable;
 	}
 	if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
 	    intel_crtc->plane != 0) {
-		DRM_DEBUG_KMS("plane not 0, disabling compression\n");
-		dev_priv->no_fbc_reason = FBC_BAD_PLANE;
+		if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE))
+			DRM_DEBUG_KMS("plane not 0, disabling compression\n");
 		goto out_disable;
 	}
 
@@ -534,8 +547,8 @@ void intel_update_fbc(struct drm_device *dev)
 	 */
 	if (obj->tiling_mode != I915_TILING_X ||
 	    obj->fence_reg == I915_FENCE_REG_NONE) {
-		DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
-		dev_priv->no_fbc_reason = FBC_NOT_TILED;
+		if (set_no_fbc_reason(dev_priv, FBC_NOT_TILED))
+			DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
 		goto out_disable;
 	}
 
@@ -544,8 +557,8 @@ void intel_update_fbc(struct drm_device *dev)
 		goto out_disable;
 
 	if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) {
-		DRM_DEBUG_KMS("framebuffer too large, disabling compression\n");
-		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
+		if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL))
+			DRM_DEBUG_KMS("framebuffer too large, disabling compression\n");
 		goto out_disable;
 	}
 
@@ -554,9 +567,9 @@ void intel_update_fbc(struct drm_device *dev)
 	 * cannot be unpinned (and have its GTT offset and fence revoked)
 	 * without first being decoupled from the scanout and FBC disabled.
 	 */
-	if (dev_priv->cfb_plane == intel_crtc->plane &&
-	    dev_priv->cfb_fb == fb->base.id &&
-	    dev_priv->cfb_y == crtc->y)
+	if (dev_priv->fbc.plane == intel_crtc->plane &&
+	    dev_priv->fbc.fb_id == fb->base.id &&
+	    dev_priv->fbc.y == crtc->y)
 		return;
 
 	if (intel_fbc_enabled(dev)) {
@@ -588,6 +601,7 @@ void intel_update_fbc(struct drm_device *dev)
 	}
 
 	intel_enable_fbc(crtc, 500);
+	dev_priv->fbc.no_fbc_reason = FBC_OK;
 	return;
 
 out_disable:
@@ -1666,9 +1680,6 @@ static void i830_update_wm(struct drm_device *dev)
 	I915_WRITE(FW_BLC, fwater_lo);
 }
 
-#define ILK_LP0_PLANE_LATENCY		700
-#define ILK_LP0_CURSOR_LATENCY		1300
-
 /*
  * Check the wm result.
  *
@@ -1783,9 +1794,9 @@ static void ironlake_update_wm(struct drm_device *dev)
 	enabled = 0;
 	if (g4x_compute_wm0(dev, PIPE_A,
 			    &ironlake_display_wm_info,
-			    ILK_LP0_PLANE_LATENCY,
+			    dev_priv->wm.pri_latency[0] * 100,
 			    &ironlake_cursor_wm_info,
-			    ILK_LP0_CURSOR_LATENCY,
+			    dev_priv->wm.cur_latency[0] * 100,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEA_ILK,
 			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
@@ -1797,9 +1808,9 @@ static void ironlake_update_wm(struct drm_device *dev)
 
 	if (g4x_compute_wm0(dev, PIPE_B,
 			    &ironlake_display_wm_info,
-			    ILK_LP0_PLANE_LATENCY,
+			    dev_priv->wm.pri_latency[0] * 100,
 			    &ironlake_cursor_wm_info,
-			    ILK_LP0_CURSOR_LATENCY,
+			    dev_priv->wm.cur_latency[0] * 100,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEB_ILK,
 			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
@@ -1823,7 +1834,7 @@ static void ironlake_update_wm(struct drm_device *dev)
 
 	/* WM1 */
 	if (!ironlake_compute_srwm(dev, 1, enabled,
-				   ILK_READ_WM1_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[1] * 500,
 				   &ironlake_display_srwm_info,
 				   &ironlake_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -1831,14 +1842,14 @@ static void ironlake_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM1_LP_ILK,
 		   WM1_LP_SR_EN |
-		   (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 
 	/* WM2 */
 	if (!ironlake_compute_srwm(dev, 2, enabled,
-				   ILK_READ_WM2_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[2] * 500,
 				   &ironlake_display_srwm_info,
 				   &ironlake_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -1846,7 +1857,7 @@ static void ironlake_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM2_LP_ILK,
 		   WM2_LP_EN |
-		   (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
@@ -1860,7 +1871,7 @@ static void ironlake_update_wm(struct drm_device *dev)
 static void sandybridge_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
+	int latency = dev_priv->wm.pri_latency[0] * 100;	/* In unit 0.1us */
 	u32 val;
 	int fbc_wm, plane_wm, cursor_wm;
 	unsigned int enabled;
@@ -1915,7 +1926,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
 
 	/* WM1 */
 	if (!ironlake_compute_srwm(dev, 1, enabled,
-				   SNB_READ_WM1_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[1] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -1923,14 +1934,14 @@ static void sandybridge_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM1_LP_ILK,
 		   WM1_LP_SR_EN |
-		   (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 
 	/* WM2 */
 	if (!ironlake_compute_srwm(dev, 2, enabled,
-				   SNB_READ_WM2_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[2] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -1938,14 +1949,14 @@ static void sandybridge_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM2_LP_ILK,
 		   WM2_LP_EN |
-		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 
 	/* WM3 */
 	if (!ironlake_compute_srwm(dev, 3, enabled,
-				   SNB_READ_WM3_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[3] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -1953,7 +1964,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM3_LP_ILK,
 		   WM3_LP_EN |
-		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
@@ -1962,7 +1973,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
 static void ivybridge_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
+	int latency = dev_priv->wm.pri_latency[0] * 100;	/* In unit 0.1us */
 	u32 val;
 	int fbc_wm, plane_wm, cursor_wm;
 	int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
@@ -2032,7 +2043,7 @@ static void ivybridge_update_wm(struct drm_device *dev)
 
 	/* WM1 */
 	if (!ironlake_compute_srwm(dev, 1, enabled,
-				   SNB_READ_WM1_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[1] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -2040,14 +2051,14 @@ static void ivybridge_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM1_LP_ILK,
 		   WM1_LP_SR_EN |
-		   (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 
 	/* WM2 */
 	if (!ironlake_compute_srwm(dev, 2, enabled,
-				   SNB_READ_WM2_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[2] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -2055,19 +2066,19 @@ static void ivybridge_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM2_LP_ILK,
 		   WM2_LP_EN |
-		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 
 	/* WM3, note we have to correct the cursor latency */
 	if (!ironlake_compute_srwm(dev, 3, enabled,
-				   SNB_READ_WM3_LATENCY() * 500,
+				   dev_priv->wm.pri_latency[3] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
 	    !ironlake_compute_srwm(dev, 3, enabled,
-				   2 * SNB_READ_WM3_LATENCY() * 500,
+				   dev_priv->wm.cur_latency[3] * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
@@ -2075,14 +2086,14 @@ static void ivybridge_update_wm(struct drm_device *dev)
 
 	I915_WRITE(WM3_LP_ILK,
 		   WM3_LP_EN |
-		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) |
 		   (fbc_wm << WM1_LP_FBC_SHIFT) |
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 }
 
-static uint32_t hsw_wm_get_pixel_rate(struct drm_device *dev,
-				      struct drm_crtc *crtc)
+static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
+				    struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t pixel_rate, pfit_size;
@@ -2112,30 +2123,38 @@ static uint32_t hsw_wm_get_pixel_rate(struct drm_device *dev,
 	return pixel_rate;
 }
 
-static uint32_t hsw_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
+/* latency must be in 0.1us units. */
+static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
 			       uint32_t latency)
 {
 	uint64_t ret;
 
+	if (WARN(latency == 0, "Latency value missing\n"))
+		return UINT_MAX;
+
 	ret = (uint64_t) pixel_rate * bytes_per_pixel * latency;
 	ret = DIV_ROUND_UP_ULL(ret, 64 * 10000) + 2;
 
 	return ret;
 }
 
-static uint32_t hsw_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
+/* latency must be in 0.1us units. */
+static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
 			       uint32_t horiz_pixels, uint8_t bytes_per_pixel,
 			       uint32_t latency)
 {
 	uint32_t ret;
 
+	if (WARN(latency == 0, "Latency value missing\n"))
+		return UINT_MAX;
+
 	ret = (latency * pixel_rate) / (pipe_htotal * 10000);
 	ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
 	ret = DIV_ROUND_UP(ret, 64) + 2;
 	return ret;
 }
 
-static uint32_t hsw_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
+static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
 			   uint8_t bytes_per_pixel)
 {
 	return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
@@ -2143,15 +2162,11 @@ static uint32_t hsw_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
 
 struct hsw_pipe_wm_parameters {
 	bool active;
-	bool sprite_enabled;
-	uint8_t pri_bytes_per_pixel;
-	uint8_t spr_bytes_per_pixel;
-	uint8_t cur_bytes_per_pixel;
-	uint32_t pri_horiz_pixels;
-	uint32_t spr_horiz_pixels;
-	uint32_t cur_horiz_pixels;
 	uint32_t pipe_htotal;
 	uint32_t pixel_rate;
+	struct intel_plane_wm_parameters pri;
+	struct intel_plane_wm_parameters spr;
+	struct intel_plane_wm_parameters cur;
 };
 
 struct hsw_wm_maximums {
@@ -2161,15 +2176,6 @@ struct hsw_wm_maximums {
 	uint16_t fbc;
 };
 
-struct hsw_lp_wm_result {
-	bool enable;
-	bool fbc_enable;
-	uint32_t pri_val;
-	uint32_t spr_val;
-	uint32_t cur_val;
-	uint32_t fbc_val;
-};
-
 struct hsw_wm_values {
 	uint32_t wm_pipe[3];
 	uint32_t wm_lp[3];
@@ -2178,128 +2184,289 @@ struct hsw_wm_values {
 	bool enable_fbc_wm;
 };
 
-enum hsw_data_buf_partitioning {
-	HSW_DATA_BUF_PART_1_2,
-	HSW_DATA_BUF_PART_5_6,
+/* used in computing the new watermarks state */
+struct intel_wm_config {
+	unsigned int num_pipes_active;
+	bool sprites_enabled;
+	bool sprites_scaled;
+	bool fbc_wm_enabled;
 };
 
-/* For both WM_PIPE and WM_LP. */
-static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
+/*
+ * For both WM_PIPE and WM_LP.
+ * mem_value must be in 0.1us units.
+ */
+static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value,
 				   bool is_lp)
 {
 	uint32_t method1, method2;
 
-	/* TODO: for now, assume the primary plane is always enabled. */
-	if (!params->active)
+	if (!params->active || !params->pri.enabled)
 		return 0;
 
-	method1 = hsw_wm_method1(params->pixel_rate,
-				 params->pri_bytes_per_pixel,
+	method1 = ilk_wm_method1(params->pixel_rate,
+				 params->pri.bytes_per_pixel,
 				 mem_value);
 
 	if (!is_lp)
 		return method1;
 
-	method2 = hsw_wm_method2(params->pixel_rate,
+	method2 = ilk_wm_method2(params->pixel_rate,
 				 params->pipe_htotal,
-				 params->pri_horiz_pixels,
-				 params->pri_bytes_per_pixel,
+				 params->pri.horiz_pixels,
+				 params->pri.bytes_per_pixel,
 				 mem_value);
 
 	return min(method1, method2);
 }
 
-/* For both WM_PIPE and WM_LP. */
-static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
+/*
+ * For both WM_PIPE and WM_LP.
+ * mem_value must be in 0.1us units.
+ */
+static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value)
 {
 	uint32_t method1, method2;
 
-	if (!params->active || !params->sprite_enabled)
+	if (!params->active || !params->spr.enabled)
 		return 0;
 
-	method1 = hsw_wm_method1(params->pixel_rate,
-				 params->spr_bytes_per_pixel,
+	method1 = ilk_wm_method1(params->pixel_rate,
+				 params->spr.bytes_per_pixel,
 				 mem_value);
-	method2 = hsw_wm_method2(params->pixel_rate,
+	method2 = ilk_wm_method2(params->pixel_rate,
 				 params->pipe_htotal,
-				 params->spr_horiz_pixels,
-				 params->spr_bytes_per_pixel,
+				 params->spr.horiz_pixels,
+				 params->spr.bytes_per_pixel,
 				 mem_value);
 	return min(method1, method2);
 }
 
-/* For both WM_PIPE and WM_LP. */
-static uint32_t hsw_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
+/*
+ * For both WM_PIPE and WM_LP.
+ * mem_value must be in 0.1us units.
+ */
+static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value)
 {
-	if (!params->active)
+	if (!params->active || !params->cur.enabled)
 		return 0;
 
-	return hsw_wm_method2(params->pixel_rate,
+	return ilk_wm_method2(params->pixel_rate,
 			      params->pipe_htotal,
-			      params->cur_horiz_pixels,
-			      params->cur_bytes_per_pixel,
+			      params->cur.horiz_pixels,
+			      params->cur.bytes_per_pixel,
 			      mem_value);
 }
 
 /* Only for WM_LP. */
-static uint32_t hsw_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
-				   uint32_t pri_val,
-				   uint32_t mem_value)
+static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
+				   uint32_t pri_val)
 {
-	if (!params->active)
+	if (!params->active || !params->pri.enabled)
 		return 0;
 
-	return hsw_wm_fbc(pri_val,
-			  params->pri_horiz_pixels,
-			  params->pri_bytes_per_pixel);
+	return ilk_wm_fbc(pri_val,
+			  params->pri.horiz_pixels,
+			  params->pri.bytes_per_pixel);
 }
 
-static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
-			      struct hsw_pipe_wm_parameters *params,
-			      struct hsw_lp_wm_result *result)
+static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
 {
-	enum pipe pipe;
-	uint32_t pri_val[3], spr_val[3], cur_val[3], fbc_val[3];
+	if (INTEL_INFO(dev)->gen >= 7)
+		return 768;
+	else
+		return 512;
+}
 
-	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
-		struct hsw_pipe_wm_parameters *p = &params[pipe];
+/* Calculate the maximum primary/sprite plane watermark */
+static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
+				     int level,
+				     const struct intel_wm_config *config,
+				     enum intel_ddb_partitioning ddb_partitioning,
+				     bool is_sprite)
+{
+	unsigned int fifo_size = ilk_display_fifo_size(dev);
+	unsigned int max;
 
-		pri_val[pipe] = hsw_compute_pri_wm(p, mem_value, true);
-		spr_val[pipe] = hsw_compute_spr_wm(p, mem_value);
-		cur_val[pipe] = hsw_compute_cur_wm(p, mem_value);
-		fbc_val[pipe] = hsw_compute_fbc_wm(p, pri_val[pipe], mem_value);
-	}
+	/* if sprites aren't enabled, sprites get nothing */
+	if (is_sprite && !config->sprites_enabled)
+		return 0;
 
-	result->pri_val = max3(pri_val[0], pri_val[1], pri_val[2]);
-	result->spr_val = max3(spr_val[0], spr_val[1], spr_val[2]);
-	result->cur_val = max3(cur_val[0], cur_val[1], cur_val[2]);
-	result->fbc_val = max3(fbc_val[0], fbc_val[1], fbc_val[2]);
+	/* HSW allows LP1+ watermarks even with multiple pipes */
+	if (level == 0 || config->num_pipes_active > 1) {
+		fifo_size /= INTEL_INFO(dev)->num_pipes;
 
-	if (result->fbc_val > max->fbc) {
-		result->fbc_enable = false;
-		result->fbc_val = 0;
-	} else {
-		result->fbc_enable = true;
+		/*
+		 * For some reason the non self refresh
+		 * FIFO size is only half of the self
+		 * refresh FIFO size on ILK/SNB.
+		 */
+		if (INTEL_INFO(dev)->gen <= 6)
+			fifo_size /= 2;
+	}
+
+	if (config->sprites_enabled) {
+		/* level 0 is always calculated with 1:1 split */
+		if (level > 0 && ddb_partitioning == INTEL_DDB_PART_5_6) {
+			if (is_sprite)
+				fifo_size *= 5;
+			fifo_size /= 6;
+		} else {
+			fifo_size /= 2;
+		}
 	}
 
+	/* clamp to max that the registers can hold */
+	if (INTEL_INFO(dev)->gen >= 7)
+		/* IVB/HSW primary/sprite plane watermarks */
+		max = level == 0 ? 127 : 1023;
+	else if (!is_sprite)
+		/* ILK/SNB primary plane watermarks */
+		max = level == 0 ? 127 : 511;
+	else
+		/* ILK/SNB sprite plane watermarks */
+		max = level == 0 ? 63 : 255;
+
+	return min(fifo_size, max);
+}
+
+/* Calculate the maximum cursor plane watermark */
+static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
+				      int level,
+				      const struct intel_wm_config *config)
+{
+	/* HSW LP1+ watermarks w/ multiple pipes */
+	if (level > 0 && config->num_pipes_active > 1)
+		return 64;
+
+	/* otherwise just report max that registers can hold */
+	if (INTEL_INFO(dev)->gen >= 7)
+		return level == 0 ? 63 : 255;
+	else
+		return level == 0 ? 31 : 63;
+}
+
+/* Calculate the maximum FBC watermark */
+static unsigned int ilk_fbc_wm_max(void)
+{
+	/* max that registers can hold */
+	return 15;
+}
+
+static void ilk_wm_max(struct drm_device *dev,
+		       int level,
+		       const struct intel_wm_config *config,
+		       enum intel_ddb_partitioning ddb_partitioning,
+		       struct hsw_wm_maximums *max)
+{
+	max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
+	max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
+	max->cur = ilk_cursor_wm_max(dev, level, config);
+	max->fbc = ilk_fbc_wm_max();
+}
+
+static bool ilk_check_wm(int level,
+			 const struct hsw_wm_maximums *max,
+			 struct intel_wm_level *result)
+{
+	bool ret;
+
+	/* already determined to be invalid? */
+	if (!result->enable)
+		return false;
+
 	result->enable = result->pri_val <= max->pri &&
 			 result->spr_val <= max->spr &&
 			 result->cur_val <= max->cur;
-	return result->enable;
+
+	ret = result->enable;
+
+	/*
+	 * HACK until we can pre-compute everything,
+	 * and thus fail gracefully if LP0 watermarks
+	 * are exceeded...
+	 */
+	if (level == 0 && !result->enable) {
+		if (result->pri_val > max->pri)
+			DRM_DEBUG_KMS("Primary WM%d too large %u (max %u)\n",
+				      level, result->pri_val, max->pri);
+		if (result->spr_val > max->spr)
+			DRM_DEBUG_KMS("Sprite WM%d too large %u (max %u)\n",
+				      level, result->spr_val, max->spr);
+		if (result->cur_val > max->cur)
+			DRM_DEBUG_KMS("Cursor WM%d too large %u (max %u)\n",
+				      level, result->cur_val, max->cur);
+
+		result->pri_val = min_t(uint32_t, result->pri_val, max->pri);
+		result->spr_val = min_t(uint32_t, result->spr_val, max->spr);
+		result->cur_val = min_t(uint32_t, result->cur_val, max->cur);
+		result->enable = true;
+	}
+
+	DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis");
+
+	return ret;
+}
+
+static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
+				 int level,
+				 struct hsw_pipe_wm_parameters *p,
+				 struct intel_wm_level *result)
+{
+	uint16_t pri_latency = dev_priv->wm.pri_latency[level];
+	uint16_t spr_latency = dev_priv->wm.spr_latency[level];
+	uint16_t cur_latency = dev_priv->wm.cur_latency[level];
+
+	/* WM1+ latency values stored in 0.5us units */
+	if (level > 0) {
+		pri_latency *= 5;
+		spr_latency *= 5;
+		cur_latency *= 5;
+	}
+
+	result->pri_val = ilk_compute_pri_wm(p, pri_latency, level);
+	result->spr_val = ilk_compute_spr_wm(p, spr_latency);
+	result->cur_val = ilk_compute_cur_wm(p, cur_latency);
+	result->fbc_val = ilk_compute_fbc_wm(p, result->pri_val);
+	result->enable = true;
+}
+
+static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
+			      int level, struct hsw_wm_maximums *max,
+			      struct hsw_pipe_wm_parameters *params,
+			      struct intel_wm_level *result)
+{
+	enum pipe pipe;
+	struct intel_wm_level res[3];
+
+	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
+		ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
+
+	result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
+	result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
+	result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
+	result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
+	result->enable = true;
+
+	return ilk_check_wm(level, max, result);
 }
 
 static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
-				    uint32_t mem_value, enum pipe pipe,
+				    enum pipe pipe,
 				    struct hsw_pipe_wm_parameters *params)
 {
 	uint32_t pri_val, cur_val, spr_val;
+	/* WM0 latency values stored in 0.1us units */
+	uint16_t pri_latency = dev_priv->wm.pri_latency[0];
+	uint16_t spr_latency = dev_priv->wm.spr_latency[0];
+	uint16_t cur_latency = dev_priv->wm.cur_latency[0];
 
-	pri_val = hsw_compute_pri_wm(params, mem_value, false);
-	spr_val = hsw_compute_spr_wm(params, mem_value);
-	cur_val = hsw_compute_cur_wm(params, mem_value);
+	pri_val = ilk_compute_pri_wm(params, pri_latency, false);
+	spr_val = ilk_compute_spr_wm(params, spr_latency);
+	cur_val = ilk_compute_cur_wm(params, cur_latency);
 
 	WARN(pri_val > 127,
 	     "Primary WM error, mode not supported for pipe %c\n",
@@ -2338,27 +2505,116 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
 	       PIPE_WM_LINETIME_TIME(linetime);
 }
 
+static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_HASWELL(dev)) {
+		uint64_t sskpd = I915_READ64(MCH_SSKPD);
+
+		wm[0] = (sskpd >> 56) & 0xFF;
+		if (wm[0] == 0)
+			wm[0] = sskpd & 0xF;
+		wm[1] = (sskpd >> 4) & 0xFF;
+		wm[2] = (sskpd >> 12) & 0xFF;
+		wm[3] = (sskpd >> 20) & 0x1FF;
+		wm[4] = (sskpd >> 32) & 0x1FF;
+	} else if (INTEL_INFO(dev)->gen >= 6) {
+		uint32_t sskpd = I915_READ(MCH_SSKPD);
+
+		wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
+		wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
+		wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
+		wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
+	} else if (INTEL_INFO(dev)->gen >= 5) {
+		uint32_t mltr = I915_READ(MLTR_ILK);
+
+		/* ILK primary LP0 latency is 700 ns */
+		wm[0] = 7;
+		wm[1] = (mltr >> MLTR_WM1_SHIFT) & ILK_SRLT_MASK;
+		wm[2] = (mltr >> MLTR_WM2_SHIFT) & ILK_SRLT_MASK;
+	}
+}
+
+static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5])
+{
+	/* ILK sprite LP0 latency is 1300 ns */
+	if (INTEL_INFO(dev)->gen == 5)
+		wm[0] = 13;
+}
+
+static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
+{
+	/* ILK cursor LP0 latency is 1300 ns */
+	if (INTEL_INFO(dev)->gen == 5)
+		wm[0] = 13;
+
+	/* WaDoubleCursorLP3Latency:ivb */
+	if (IS_IVYBRIDGE(dev))
+		wm[3] *= 2;
+}
+
+static void intel_print_wm_latency(struct drm_device *dev,
+				   const char *name,
+				   const uint16_t wm[5])
+{
+	int level, max_level;
+
+	/* how many WM levels are we expecting */
+	if (IS_HASWELL(dev))
+		max_level = 4;
+	else if (INTEL_INFO(dev)->gen >= 6)
+		max_level = 3;
+	else
+		max_level = 2;
+
+	for (level = 0; level <= max_level; level++) {
+		unsigned int latency = wm[level];
+
+		if (latency == 0) {
+			DRM_ERROR("%s WM%d latency not provided\n",
+				  name, level);
+			continue;
+		}
+
+		/* WM1+ latency values in 0.5us units */
+		if (level > 0)
+			latency *= 5;
+
+		DRM_DEBUG_KMS("%s WM%d latency %u (%u.%u usec)\n",
+			      name, level, wm[level],
+			      latency / 10, latency % 10);
+	}
+}
+
+static void intel_setup_wm_latency(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	intel_read_wm_latency(dev, dev_priv->wm.pri_latency);
+
+	memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency,
+	       sizeof(dev_priv->wm.pri_latency));
+	memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency,
+	       sizeof(dev_priv->wm.pri_latency));
+
+	intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
+	intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
+
+	intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
+	intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
+	intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+}
+
 static void hsw_compute_wm_parameters(struct drm_device *dev,
 				      struct hsw_pipe_wm_parameters *params,
-				      uint32_t *wm,
 				      struct hsw_wm_maximums *lp_max_1_2,
 				      struct hsw_wm_maximums *lp_max_5_6)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 	struct drm_plane *plane;
-	uint64_t sskpd = I915_READ64(MCH_SSKPD);
 	enum pipe pipe;
-	int pipes_active = 0, sprites_enabled = 0;
-
-	if ((sskpd >> 56) & 0xFF)
-		wm[0] = (sskpd >> 56) & 0xFF;
-	else
-		wm[0] = sskpd & 0xF;
-	wm[1] = ((sskpd >> 4) & 0xFF) * 5;
-	wm[2] = ((sskpd >> 12) & 0xFF) * 5;
-	wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
-	wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
+	struct intel_wm_config config = {};
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -2371,15 +2627,18 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		if (!p->active)
 			continue;
 
-		pipes_active++;
+		config.num_pipes_active++;
 
 		p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
-		p->pixel_rate = hsw_wm_get_pixel_rate(dev, crtc);
-		p->pri_bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
-		p->cur_bytes_per_pixel = 4;
-		p->pri_horiz_pixels =
+		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
+		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
+		p->cur.bytes_per_pixel = 4;
+		p->pri.horiz_pixels =
 			intel_crtc->config.requested_mode.hdisplay;
-		p->cur_horiz_pixels = 64;
+		p->cur.horiz_pixels = 64;
+		/* TODO: for now, assume primary and cursor planes are always enabled. */
+		p->pri.enabled = true;
+		p->cur.enabled = true;
 	}
 
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
@@ -2389,42 +2648,35 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		pipe = intel_plane->pipe;
 		p = &params[pipe];
 
-		p->sprite_enabled = intel_plane->wm.enable;
-		p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
-		p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
+		p->spr = intel_plane->wm;
 
-		if (p->sprite_enabled)
-			sprites_enabled++;
+		config.sprites_enabled |= p->spr.enabled;
+		config.sprites_scaled |= p->spr.scaled;
 	}
 
-	if (pipes_active > 1) {
-		lp_max_1_2->pri = lp_max_5_6->pri = sprites_enabled ? 128 : 256;
-		lp_max_1_2->spr = lp_max_5_6->spr = 128;
-		lp_max_1_2->cur = lp_max_5_6->cur = 64;
-	} else {
-		lp_max_1_2->pri = sprites_enabled ? 384 : 768;
-		lp_max_5_6->pri = sprites_enabled ? 128 : 768;
-		lp_max_1_2->spr = 384;
-		lp_max_5_6->spr = 640;
-		lp_max_1_2->cur = lp_max_5_6->cur = 255;
-	}
-	lp_max_1_2->fbc = lp_max_5_6->fbc = 15;
+	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
+
+	/* 5/6 split only in single pipe config on IVB+ */
+	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1)
+		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
+	else
+		*lp_max_5_6 = *lp_max_1_2;
 }
 
 static void hsw_compute_wm_results(struct drm_device *dev,
 				   struct hsw_pipe_wm_parameters *params,
-				   uint32_t *wm,
 				   struct hsw_wm_maximums *lp_maximums,
 				   struct hsw_wm_values *results)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
-	struct hsw_lp_wm_result lp_results[4] = {};
+	struct intel_wm_level lp_results[4] = {};
 	enum pipe pipe;
 	int level, max_level, wm_lp;
 
 	for (level = 1; level <= 4; level++)
-		if (!hsw_compute_lp_wm(wm[level], lp_maximums, params,
+		if (!hsw_compute_lp_wm(dev_priv, level,
+				       lp_maximums, params,
 				       &lp_results[level - 1]))
 			break;
 	max_level = level - 1;
@@ -2433,15 +2685,15 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	 * a WM level. */
 	results->enable_fbc_wm = true;
 	for (level = 1; level <= max_level; level++) {
-		if (!lp_results[level - 1].fbc_enable) {
+		if (!lp_results[level - 1].fbc_val > lp_maximums->fbc) {
 			results->enable_fbc_wm = false;
-			break;
+			lp_results[level - 1].fbc_val = 0;
 		}
 	}
 
 	memset(results, 0, sizeof(*results));
 	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
-		const struct hsw_lp_wm_result *r;
+		const struct intel_wm_level *r;
 
 		level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
 		if (level > max_level)
@@ -2456,8 +2708,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	}
 
 	for_each_pipe(pipe)
-		results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, wm[0],
-							     pipe,
+		results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe,
 							     &params[pipe]);
 
 	for_each_pipe(pipe) {
@@ -2468,8 +2719,8 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 
 /* Find the result with the highest level enabled. Check for enable_fbc_wm in
  * case both are at the same level. Prefer r1 in case they're the same. */
-struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
-					   struct hsw_wm_values *r2)
+static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
+						  struct hsw_wm_values *r2)
 {
 	int i, val_r1 = 0, val_r2 = 0;
 
@@ -2498,11 +2749,11 @@ struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
  */
 static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 				struct hsw_wm_values *results,
-				enum hsw_data_buf_partitioning partitioning)
+				enum intel_ddb_partitioning partitioning)
 {
 	struct hsw_wm_values previous;
 	uint32_t val;
-	enum hsw_data_buf_partitioning prev_partitioning;
+	enum intel_ddb_partitioning prev_partitioning;
 	bool prev_enable_fbc_wm;
 
 	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
@@ -2519,7 +2770,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 	previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
 
 	prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-			    HSW_DATA_BUF_PART_5_6 : HSW_DATA_BUF_PART_1_2;
+				INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
 
 	prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
 
@@ -2558,7 +2809,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 
 	if (prev_partitioning != partitioning) {
 		val = I915_READ(WM_MISC);
-		if (partitioning == HSW_DATA_BUF_PART_1_2)
+		if (partitioning == INTEL_DDB_PART_1_2)
 			val &= ~WM_MISC_DATA_PARTITION_5_6;
 		else
 			val |= WM_MISC_DATA_PARTITION_5_6;
@@ -2595,44 +2846,39 @@ static void haswell_update_wm(struct drm_device *dev)
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params[3];
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
-	uint32_t wm[5];
-	enum hsw_data_buf_partitioning partitioning;
+	enum intel_ddb_partitioning partitioning;
 
-	hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2, &lp_max_5_6);
+	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
 
-	hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
+	hsw_compute_wm_results(dev, params,
+			       &lp_max_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-		hsw_compute_wm_results(dev, params, wm, &lp_max_5_6,
-				       &results_5_6);
+		hsw_compute_wm_results(dev, params,
+				       &lp_max_5_6, &results_5_6);
 		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
 	} else {
 		best_results = &results_1_2;
 	}
 
 	partitioning = (best_results == &results_1_2) ?
-		       HSW_DATA_BUF_PART_1_2 : HSW_DATA_BUF_PART_5_6;
+		       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
 	hsw_write_wm_values(dev_priv, best_results, partitioning);
 }
 
-static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
+static void haswell_update_sprite_wm(struct drm_plane *plane,
+				     struct drm_crtc *crtc,
 				     uint32_t sprite_width, int pixel_size,
-				     bool enable)
+				     bool enabled, bool scaled)
 {
-	struct drm_plane *plane;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
 
-	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		struct intel_plane *intel_plane = to_intel_plane(plane);
-
-		if (intel_plane->pipe == pipe) {
-			intel_plane->wm.enable = enable;
-			intel_plane->wm.horiz_pixels = sprite_width + 1;
-			intel_plane->wm.bytes_per_pixel = pixel_size;
-			break;
-		}
-	}
+	intel_plane->wm.enabled = enabled;
+	intel_plane->wm.scaled = scaled;
+	intel_plane->wm.horiz_pixels = sprite_width;
+	intel_plane->wm.bytes_per_pixel = pixel_size;
 
-	haswell_update_wm(dev);
+	haswell_update_wm(plane->dev);
 }
 
 static bool
@@ -2711,17 +2957,20 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
 	return *sprite_wm > 0x3ff ? false : true;
 }
 
-static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
+static void sandybridge_update_sprite_wm(struct drm_plane *plane,
+					 struct drm_crtc *crtc,
 					 uint32_t sprite_width, int pixel_size,
-					 bool enable)
+					 bool enabled, bool scaled)
 {
+	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
+	int pipe = to_intel_plane(plane)->pipe;
+	int latency = dev_priv->wm.spr_latency[0] * 100;	/* In unit 0.1us */
 	u32 val;
 	int sprite_wm, reg;
 	int ret;
 
-	if (!enable)
+	if (!enabled)
 		return;
 
 	switch (pipe) {
@@ -2756,7 +3005,7 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
 	ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
 					      pixel_size,
 					      &sandybridge_display_srwm_info,
-					      SNB_READ_WM1_LATENCY() * 500,
+					      dev_priv->wm.spr_latency[1] * 500,
 					      &sprite_wm);
 	if (!ret) {
 		DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n",
@@ -2772,7 +3021,7 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
 	ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
 					      pixel_size,
 					      &sandybridge_display_srwm_info,
-					      SNB_READ_WM2_LATENCY() * 500,
+					      dev_priv->wm.spr_latency[2] * 500,
 					      &sprite_wm);
 	if (!ret) {
 		DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n",
@@ -2784,7 +3033,7 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
 	ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
 					      pixel_size,
 					      &sandybridge_display_srwm_info,
-					      SNB_READ_WM3_LATENCY() * 500,
+					      dev_priv->wm.spr_latency[3] * 500,
 					      &sprite_wm);
 	if (!ret) {
 		DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n",
@@ -2834,15 +3083,16 @@ void intel_update_watermarks(struct drm_device *dev)
 		dev_priv->display.update_wm(dev);
 }
 
-void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
+void intel_update_sprite_watermarks(struct drm_plane *plane,
+				    struct drm_crtc *crtc,
 				    uint32_t sprite_width, int pixel_size,
-				    bool enable)
+				    bool enabled, bool scaled)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = plane->dev->dev_private;
 
 	if (dev_priv->display.update_sprite_wm)
-		dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
-						   pixel_size, enable);
+		dev_priv->display.update_sprite_wm(plane, crtc, sprite_width,
+						   pixel_size, enabled, scaled);
 }
 
 static struct drm_i915_gem_object *
@@ -2859,7 +3109,7 @@ intel_alloc_context_page(struct drm_device *dev)
 		return NULL;
 	}
 
-	ret = i915_gem_object_pin(ctx, 4096, true, false);
+	ret = i915_gem_obj_ggtt_pin(ctx, 4096, true, false);
 	if (ret) {
 		DRM_ERROR("failed to pin power context: %d\n", ret);
 		goto err_unref;
@@ -3076,19 +3326,12 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
  */
 static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv)
 {
-	unsigned long timeout = jiffies + msecs_to_jiffies(10);
 	u32 pval;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
-	do {
-		pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-		if (time_after(jiffies, timeout)) {
-			DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
-			break;
-		}
-		udelay(10);
-	} while (pval & 1);
+	if (wait_for(((pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) & GENFREQSTATUS) == 0, 10))
+		DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
 
 	pval >>= 8;
 
@@ -3129,13 +3372,10 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val));
 }
 
-
-static void gen6_disable_rps(struct drm_device *dev)
+static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	I915_WRITE(GEN6_RC_CONTROL, 0);
-	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
 	I915_WRITE(GEN6_PMIER, I915_READ(GEN6_PMIER) & ~GEN6_PM_RPS_EVENTS);
 	/* Complete PM interrupt masking here doesn't race with the rps work
@@ -3143,30 +3383,30 @@ static void gen6_disable_rps(struct drm_device *dev)
 	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
 	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
-	spin_lock_irq(&dev_priv->rps.lock);
+	spin_lock_irq(&dev_priv->irq_lock);
 	dev_priv->rps.pm_iir = 0;
-	spin_unlock_irq(&dev_priv->rps.lock);
+	spin_unlock_irq(&dev_priv->irq_lock);
 
 	I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
 }
 
-static void valleyview_disable_rps(struct drm_device *dev)
+static void gen6_disable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	I915_WRITE(GEN6_RC_CONTROL, 0);
-	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
-	I915_WRITE(GEN6_PMIER, 0);
-	/* Complete PM interrupt masking here doesn't race with the rps work
-	 * item again unmasking PM interrupts because that is using a different
-	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
-	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 
-	spin_lock_irq(&dev_priv->rps.lock);
-	dev_priv->rps.pm_iir = 0;
-	spin_unlock_irq(&dev_priv->rps.lock);
+	gen6_disable_rps_interrupts(dev);
+}
 
-	I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+static void valleyview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+
+	gen6_disable_rps_interrupts(dev);
 
 	if (dev_priv->vlv_pctx) {
 		drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
@@ -3176,6 +3416,10 @@ static void valleyview_disable_rps(struct drm_device *dev)
 
 int intel_enable_rc6(const struct drm_device *dev)
 {
+	/* No RC6 before Ironlake */
+	if (INTEL_INFO(dev)->gen < 5)
+		return 0;
+
 	/* Respect the kernel parameter if it is set */
 	if (i915_enable_rc6 >= 0)
 		return i915_enable_rc6;
@@ -3199,6 +3443,19 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 }
 
+static void gen6_enable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	WARN_ON(dev_priv->rps.pm_iir);
+	I915_WRITE(GEN6_PMIMR, I915_READ(GEN6_PMIMR) & ~GEN6_PM_RPS_EVENTS);
+	I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
+	spin_unlock_irq(&dev_priv->irq_lock);
+	/* unmask all PM interrupts */
+	I915_WRITE(GEN6_PMINTRMSK, 0);
+}
+
 static void gen6_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3327,17 +3584,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 
 	gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8);
 
-	/* requires MSI enabled */
-	I915_WRITE(GEN6_PMIER, I915_READ(GEN6_PMIER) | GEN6_PM_RPS_EVENTS);
-	spin_lock_irq(&dev_priv->rps.lock);
-	/* FIXME: Our interrupt enabling sequence is bonghits.
-	 * dev_priv->rps.pm_iir really should be 0 here. */
-	dev_priv->rps.pm_iir = 0;
-	I915_WRITE(GEN6_PMIMR, I915_READ(GEN6_PMIMR) & ~GEN6_PM_RPS_EVENTS);
-	I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
-	spin_unlock_irq(&dev_priv->rps.lock);
-	/* unmask all PM interrupts */
-	I915_WRITE(GEN6_PMINTRMSK, 0);
+	gen6_enable_rps_interrupts(dev);
 
 	rc6vids = 0;
 	ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
@@ -3482,7 +3729,7 @@ static void valleyview_setup_pctx(struct drm_device *dev)
 		pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base;
 		pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv->dev,
 								      pcbr_offset,
-								      -1,
+								      I915_GTT_OFFSET_NONE,
 								      pctx_size);
 		goto out;
 	}
@@ -3607,14 +3854,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
 
 	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 
-	/* requires MSI enabled */
-	I915_WRITE(GEN6_PMIER, GEN6_PM_RPS_EVENTS);
-	spin_lock_irq(&dev_priv->rps.lock);
-	WARN_ON(dev_priv->rps.pm_iir != 0);
-	I915_WRITE(GEN6_PMIMR, 0);
-	spin_unlock_irq(&dev_priv->rps.lock);
-	/* enable all PM interrupts */
-	I915_WRITE(GEN6_PMINTRMSK, 0);
+	gen6_enable_rps_interrupts(dev);
 
 	gen6_gt_force_wake_put(dev_priv);
 }
@@ -3708,7 +3948,7 @@ static void ironlake_enable_rc6(struct drm_device *dev)
 
 	intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
 	intel_ring_emit(ring, MI_SET_CONTEXT);
-	intel_ring_emit(ring, dev_priv->ips.renderctx->gtt_offset |
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(dev_priv->ips.renderctx) |
 			MI_MM_SPACE_GTT |
 			MI_SAVE_EXT_STATE_EN |
 			MI_RESTORE_EXT_STATE_EN |
@@ -3731,7 +3971,7 @@ static void ironlake_enable_rc6(struct drm_device *dev)
 		return;
 	}
 
-	I915_WRITE(PWRCTXA, dev_priv->ips.pwrctx->gtt_offset | PWRCTX_EN);
+	I915_WRITE(PWRCTXA, i915_gem_obj_ggtt_offset(dev_priv->ips.pwrctx) | PWRCTX_EN);
 	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
 }
 
@@ -4429,7 +4669,10 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
-	/* Required for FBC */
+	/*
+	 * Required for FBC
+	 * WaFbcDisableDpfcClockGating:ilk
+	 */
 	dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE |
 		   ILK_DPFCUNIT_CLOCK_GATE_DISABLE |
 		   ILK_DPFDUNIT_CLOCK_GATE_ENABLE;
@@ -4466,6 +4709,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
 	 * The bit 7,8,9 of 0x42020.
 	 */
 	if (IS_IRONLAKE_M(dev)) {
+		/* WaFbcAsynchFlipDisableFbcQueue:ilk */
 		I915_WRITE(ILK_DISPLAY_CHICKEN1,
 			   I915_READ(ILK_DISPLAY_CHICKEN1) |
 			   ILK_FBCQ_DIS);
@@ -4602,6 +4846,8 @@ static void gen6_init_clock_gating(struct drm_device *dev)
 	 * The bit5 and bit7 of 0x42020
 	 * The bit14 of 0x70180
 	 * The bit14 of 0x71180
+	 *
+	 * WaFbcAsynchFlipDisableFbcQueue:snb
 	 */
 	I915_WRITE(ILK_DISPLAY_CHICKEN1,
 		   I915_READ(ILK_DISPLAY_CHICKEN1) |
@@ -5063,8 +5309,26 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 		}
 	} else {
 		if (enable_requested) {
+			unsigned long irqflags;
+			enum pipe p;
+
 			I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
+			POSTING_READ(HSW_PWR_WELL_DRIVER);
 			DRM_DEBUG_KMS("Requesting to disable the power well\n");
+
+			/*
+			 * After this, the registers on the pipes that are part
+			 * of the power well will become zero, so we have to
+			 * adjust our counters according to that.
+			 *
+			 * FIXME: Should we do this in general in
+			 * drm_vblank_post_modeset?
+			 */
+			spin_lock_irqsave(&dev->vbl_lock, irqflags);
+			for_each_pipe(p)
+				if (p != PIPE_A)
+					dev->last_vblank[p] = 0;
+			spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 		}
 	}
 }
@@ -5199,8 +5463,12 @@ void intel_init_pm(struct drm_device *dev)
 
 	/* For FIFO watermark updates */
 	if (HAS_PCH_SPLIT(dev)) {
+		intel_setup_wm_latency(dev);
+
 		if (IS_GEN5(dev)) {
-			if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
+			if (dev_priv->wm.pri_latency[1] &&
+			    dev_priv->wm.spr_latency[1] &&
+			    dev_priv->wm.cur_latency[1])
 				dev_priv->display.update_wm = ironlake_update_wm;
 			else {
 				DRM_DEBUG_KMS("Failed to get proper latency. "
@@ -5209,7 +5477,9 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
 		} else if (IS_GEN6(dev)) {
-			if (SNB_READ_WM0_LATENCY()) {
+			if (dev_priv->wm.pri_latency[0] &&
+			    dev_priv->wm.spr_latency[0] &&
+			    dev_priv->wm.cur_latency[0]) {
 				dev_priv->display.update_wm = sandybridge_update_wm;
 				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
 			} else {
@@ -5219,7 +5489,9 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = gen6_init_clock_gating;
 		} else if (IS_IVYBRIDGE(dev)) {
-			if (SNB_READ_WM0_LATENCY()) {
+			if (dev_priv->wm.pri_latency[0] &&
+			    dev_priv->wm.spr_latency[0] &&
+			    dev_priv->wm.cur_latency[0]) {
 				dev_priv->display.update_wm = ivybridge_update_wm;
 				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
 			} else {
@@ -5229,7 +5501,9 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
 		} else if (IS_HASWELL(dev)) {
-			if (I915_READ64(MCH_SSKPD)) {
+			if (dev_priv->wm.pri_latency[0] &&
+			    dev_priv->wm.spr_latency[0] &&
+			    dev_priv->wm.cur_latency[0]) {
 				dev_priv->display.update_wm = haswell_update_wm;
 				dev_priv->display.update_sprite_wm =
 					haswell_update_sprite_wm;
@@ -5292,260 +5566,6 @@ void intel_init_pm(struct drm_device *dev)
 	}
 }
 
-static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
-{
-	u32 gt_thread_status_mask;
-
-	if (IS_HASWELL(dev_priv->dev))
-		gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW;
-	else
-		gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK;
-
-	/* w/a for a sporadic read returning 0 by waiting for the GT
-	 * thread to wake up.
-	 */
-	if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500))
-		DRM_ERROR("GT thread status wait timed out\n");
-}
-
-static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE_NOTRACE(FORCEWAKE, 0);
-	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
-}
-
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
-{
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0,
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
-
-	I915_WRITE_NOTRACE(FORCEWAKE, 1);
-	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
-
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK) & 1),
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
-
-	/* WaRsForcewakeWaitTC0:snb */
-	__gen6_gt_wait_for_thread_c0(dev_priv);
-}
-
-static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
-	/* something from same cacheline, but !FORCEWAKE_MT */
-	POSTING_READ(ECOBUS);
-}
-
-static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
-{
-	u32 forcewake_ack;
-
-	if (IS_HASWELL(dev_priv->dev))
-		forcewake_ack = FORCEWAKE_ACK_HSW;
-	else
-		forcewake_ack = FORCEWAKE_MT_ACK;
-
-	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & FORCEWAKE_KERNEL) == 0,
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
-
-	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-	/* something from same cacheline, but !FORCEWAKE_MT */
-	POSTING_READ(ECOBUS);
-
-	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & FORCEWAKE_KERNEL),
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
-
-	/* WaRsForcewakeWaitTC0:ivb,hsw */
-	__gen6_gt_wait_for_thread_c0(dev_priv);
-}
-
-/*
- * Generally this is called implicitly by the register read function. However,
- * if some sequence requires the GT to not power down then this function should
- * be called at the beginning of the sequence followed by a call to
- * gen6_gt_force_wake_put() at the end of the sequence.
- */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
-{
-	unsigned long irqflags;
-
-	spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
-	if (dev_priv->forcewake_count++ == 0)
-		dev_priv->gt.force_wake_get(dev_priv);
-	spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
-}
-
-void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
-{
-	u32 gtfifodbg;
-	gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
-	if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
-	     "MMIO read or write has been dropped %x\n", gtfifodbg))
-		I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
-}
-
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE_NOTRACE(FORCEWAKE, 0);
-	/* something from same cacheline, but !FORCEWAKE */
-	POSTING_READ(ECOBUS);
-	gen6_gt_check_fifodbg(dev_priv);
-}
-
-static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-	/* something from same cacheline, but !FORCEWAKE_MT */
-	POSTING_READ(ECOBUS);
-	gen6_gt_check_fifodbg(dev_priv);
-}
-
-/*
- * see gen6_gt_force_wake_get()
- */
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
-{
-	unsigned long irqflags;
-
-	spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
-	if (--dev_priv->forcewake_count == 0)
-		dev_priv->gt.force_wake_put(dev_priv);
-	spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
-}
-
-int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
-{
-	int ret = 0;
-
-	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
-		int loop = 500;
-		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
-			udelay(10);
-			fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-		}
-		if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
-			++ret;
-		dev_priv->gt_fifo_count = fifo;
-	}
-	dev_priv->gt_fifo_count--;
-
-	return ret;
-}
-
-static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
-	/* something from same cacheline, but !FORCEWAKE_VLV */
-	POSTING_READ(FORCEWAKE_ACK_VLV);
-}
-
-static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
-{
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0,
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
-
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-	I915_WRITE_NOTRACE(FORCEWAKE_MEDIA_VLV,
-			   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL),
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n");
-
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_MEDIA_VLV) &
-			     FORCEWAKE_KERNEL),
-			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
-
-	/* WaRsForcewakeWaitTC0:vlv */
-	__gen6_gt_wait_for_thread_c0(dev_priv);
-}
-
-static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-	I915_WRITE_NOTRACE(FORCEWAKE_MEDIA_VLV,
-			   _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-	/* The below doubles as a POSTING_READ */
-	gen6_gt_check_fifodbg(dev_priv);
-}
-
-void intel_gt_sanitize(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (IS_VALLEYVIEW(dev)) {
-		vlv_force_wake_reset(dev_priv);
-	} else if (INTEL_INFO(dev)->gen >= 6) {
-		__gen6_gt_force_wake_reset(dev_priv);
-		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-			__gen6_gt_force_wake_mt_reset(dev_priv);
-	}
-
-	/* BIOS often leaves RC6 enabled, but disable it for hw init */
-	if (INTEL_INFO(dev)->gen >= 6)
-		intel_disable_gt_powersave(dev);
-}
-
-void intel_gt_init(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (IS_VALLEYVIEW(dev)) {
-		dev_priv->gt.force_wake_get = vlv_force_wake_get;
-		dev_priv->gt.force_wake_put = vlv_force_wake_put;
-	} else if (IS_HASWELL(dev)) {
-		dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get;
-		dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put;
-	} else if (IS_IVYBRIDGE(dev)) {
-		u32 ecobus;
-
-		/* IVB configs may use multi-threaded forcewake */
-
-		/* A small trick here - if the bios hasn't configured
-		 * MT forcewake, and if the device is in RC6, then
-		 * force_wake_mt_get will not wake the device and the
-		 * ECOBUS read will return zero. Which will be
-		 * (correctly) interpreted by the test below as MT
-		 * forcewake being disabled.
-		 */
-		mutex_lock(&dev->struct_mutex);
-		__gen6_gt_force_wake_mt_get(dev_priv);
-		ecobus = I915_READ_NOTRACE(ECOBUS);
-		__gen6_gt_force_wake_mt_put(dev_priv);
-		mutex_unlock(&dev->struct_mutex);
-
-		if (ecobus & FORCEWAKE_MT_ENABLE) {
-			dev_priv->gt.force_wake_get =
-						__gen6_gt_force_wake_mt_get;
-			dev_priv->gt.force_wake_put =
-						__gen6_gt_force_wake_mt_put;
-		} else {
-			DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n");
-			DRM_INFO("when using vblank-synced partial screen updates.\n");
-			dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
-			dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
-		}
-	} else if (IS_GEN6(dev)) {
-		dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
-		dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
-	}
-}
-
-void intel_pm_init(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
-			  intel_gen6_powersave_work);
-}
-
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)
 {
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -5648,3 +5668,11 @@ int vlv_freq_opcode(int ddr_freq, int val)
 	return val;
 }
 
+void intel_pm_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
+			  intel_gen6_powersave_work);
+}
+
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 664118d..74d02a7 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -440,14 +440,14 @@ static int init_ring_common(struct intel_ring_buffer *ring)
 	 * registers with the above sequence (the readback of the HEAD registers
 	 * also enforces ordering), otherwise the hw might lose the new ring
 	 * register values. */
-	I915_WRITE_START(ring, obj->gtt_offset);
+	I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj));
 	I915_WRITE_CTL(ring,
 			((ring->size - PAGE_SIZE) & RING_NR_PAGES)
 			| RING_VALID);
 
 	/* If the head is still not zero, the ring is dead */
 	if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
-		     I915_READ_START(ring) == obj->gtt_offset &&
+		     I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) &&
 		     (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
 		DRM_ERROR("%s initialization failed "
 				"ctl %08x head %08x tail %08x start %08x\n",
@@ -501,11 +501,11 @@ init_pipe_control(struct intel_ring_buffer *ring)
 
 	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
-	ret = i915_gem_object_pin(obj, 4096, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, 4096, true, false);
 	if (ret)
 		goto err_unref;
 
-	pc->gtt_offset = obj->gtt_offset;
+	pc->gtt_offset = i915_gem_obj_ggtt_offset(obj);
 	pc->cpu_page = kmap(sg_page(obj->pages->sgl));
 	if (pc->cpu_page == NULL) {
 		ret = -ENOMEM;
@@ -836,7 +836,7 @@ gen5_ring_get_irq(struct intel_ring_buffer *ring)
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount.gt++ == 0) {
+	if (ring->irq_refcount++ == 0) {
 		dev_priv->gt_irq_mask &= ~ring->irq_enable_mask;
 		I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 		POSTING_READ(GTIMR);
@@ -854,7 +854,7 @@ gen5_ring_put_irq(struct intel_ring_buffer *ring)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount.gt == 0) {
+	if (--ring->irq_refcount == 0) {
 		dev_priv->gt_irq_mask |= ring->irq_enable_mask;
 		I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 		POSTING_READ(GTIMR);
@@ -873,7 +873,7 @@ i9xx_ring_get_irq(struct intel_ring_buffer *ring)
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount.gt++ == 0) {
+	if (ring->irq_refcount++ == 0) {
 		dev_priv->irq_mask &= ~ring->irq_enable_mask;
 		I915_WRITE(IMR, dev_priv->irq_mask);
 		POSTING_READ(IMR);
@@ -891,7 +891,7 @@ i9xx_ring_put_irq(struct intel_ring_buffer *ring)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount.gt == 0) {
+	if (--ring->irq_refcount == 0) {
 		dev_priv->irq_mask |= ring->irq_enable_mask;
 		I915_WRITE(IMR, dev_priv->irq_mask);
 		POSTING_READ(IMR);
@@ -910,7 +910,7 @@ i8xx_ring_get_irq(struct intel_ring_buffer *ring)
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount.gt++ == 0) {
+	if (ring->irq_refcount++ == 0) {
 		dev_priv->irq_mask &= ~ring->irq_enable_mask;
 		I915_WRITE16(IMR, dev_priv->irq_mask);
 		POSTING_READ16(IMR);
@@ -928,7 +928,7 @@ i8xx_ring_put_irq(struct intel_ring_buffer *ring)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount.gt == 0) {
+	if (--ring->irq_refcount == 0) {
 		dev_priv->irq_mask |= ring->irq_enable_mask;
 		I915_WRITE16(IMR, dev_priv->irq_mask);
 		POSTING_READ16(IMR);
@@ -1021,7 +1021,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
 	gen6_gt_force_wake_get(dev_priv);
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount.gt++ == 0) {
+	if (ring->irq_refcount++ == 0) {
 		if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
 			I915_WRITE_IMR(ring,
 				       ~(ring->irq_enable_mask |
@@ -1045,7 +1045,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount.gt == 0) {
+	if (--ring->irq_refcount == 0) {
 		if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
 			I915_WRITE_IMR(ring,
 				       ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
@@ -1070,14 +1070,14 @@ hsw_vebox_get_irq(struct intel_ring_buffer *ring)
 	if (!dev->irq_enabled)
 		return false;
 
-	spin_lock_irqsave(&dev_priv->rps.lock, flags);
-	if (ring->irq_refcount.pm++ == 0) {
+	spin_lock_irqsave(&dev_priv->irq_lock, flags);
+	if (ring->irq_refcount++ == 0) {
 		u32 pm_imr = I915_READ(GEN6_PMIMR);
 		I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
 		I915_WRITE(GEN6_PMIMR, pm_imr & ~ring->irq_enable_mask);
 		POSTING_READ(GEN6_PMIMR);
 	}
-	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
 	return true;
 }
@@ -1092,14 +1092,14 @@ hsw_vebox_put_irq(struct intel_ring_buffer *ring)
 	if (!dev->irq_enabled)
 		return;
 
-	spin_lock_irqsave(&dev_priv->rps.lock, flags);
-	if (--ring->irq_refcount.pm == 0) {
+	spin_lock_irqsave(&dev_priv->irq_lock, flags);
+	if (--ring->irq_refcount == 0) {
 		u32 pm_imr = I915_READ(GEN6_PMIMR);
 		I915_WRITE_IMR(ring, ~0);
 		I915_WRITE(GEN6_PMIMR, pm_imr | ring->irq_enable_mask);
 		POSTING_READ(GEN6_PMIMR);
 	}
-	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static int
@@ -1144,7 +1144,7 @@ i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
 		intel_ring_advance(ring);
 	} else {
 		struct drm_i915_gem_object *obj = ring->private;
-		u32 cs_offset = obj->gtt_offset;
+		u32 cs_offset = i915_gem_obj_ggtt_offset(obj);
 
 		if (len > I830_BATCH_LIMIT)
 			return -ENOSPC;
@@ -1224,12 +1224,12 @@ static int init_status_page(struct intel_ring_buffer *ring)
 
 	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
-	ret = i915_gem_object_pin(obj, 4096, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, 4096, true, false);
 	if (ret != 0) {
 		goto err_unref;
 	}
 
-	ring->status_page.gfx_addr = obj->gtt_offset;
+	ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
 	ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
 	if (ring->status_page.page_addr == NULL) {
 		ret = -ENOMEM;
@@ -1307,7 +1307,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 
 	ring->obj = obj;
 
-	ret = i915_gem_object_pin(obj, PAGE_SIZE, true, false);
+	ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, true, false);
 	if (ret)
 		goto err_unref;
 
@@ -1316,7 +1316,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 		goto err_unpin;
 
 	ring->virtual_start =
-		ioremap_wc(dev_priv->gtt.mappable_base + obj->gtt_offset,
+		ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
 			   ring->size);
 	if (ring->virtual_start == NULL) {
 		DRM_ERROR("Failed to map ringbuffer.\n");
@@ -1828,7 +1828,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 			return -ENOMEM;
 		}
 
-		ret = i915_gem_object_pin(obj, 0, true, false);
+		ret = i915_gem_obj_ggtt_pin(obj, 0, true, false);
 		if (ret != 0) {
 			drm_gem_object_unreference(&obj->base);
 			DRM_ERROR("Failed to ping batch bo\n");
@@ -2008,8 +2008,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 	ring->add_request = gen6_add_request;
 	ring->get_seqno = gen6_ring_get_seqno;
 	ring->set_seqno = ring_set_seqno;
-	ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT |
-		PM_VEBOX_CS_ERROR_INTERRUPT;
+	ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
 	ring->irq_get = hsw_vebox_get_irq;
 	ring->irq_put = hsw_vebox_put_irq;
 	ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 799f04c..6e38256 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -78,10 +78,7 @@ struct  intel_ring_buffer {
 	 */
 	u32		last_retired_head;
 
-	struct {
-		u32	gt; /*  protected by dev_priv->irq_lock */
-		u32	pm; /*  protected by dev_priv->rps.lock (sucks) */
-	} irq_refcount;
+	unsigned irq_refcount; /* protected by dev_priv->irq_lock */
 	u32		irq_enable_mask;	/* bitmask to enable ring interrupt */
 	u32		trace_irq_seqno;
 	u32		sync_seqno[I915_NUM_RINGS-1];
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2628d56..02f220b 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -202,15 +202,14 @@ struct intel_sdvo_connector {
 	u32	cur_dot_crawl,	max_dot_crawl;
 };
 
-static struct intel_sdvo *to_intel_sdvo(struct drm_encoder *encoder)
+static struct intel_sdvo *to_sdvo(struct intel_encoder *encoder)
 {
-	return container_of(encoder, struct intel_sdvo, base.base);
+	return container_of(encoder, struct intel_sdvo, base);
 }
 
 static struct intel_sdvo *intel_attached_sdvo(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_sdvo, base);
+	return to_sdvo(intel_attached_encoder(connector));
 }
 
 static struct intel_sdvo_connector *to_intel_sdvo_connector(struct drm_connector *connector)
@@ -964,30 +963,32 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
 					 const struct drm_display_mode *adjusted_mode)
 {
-	struct dip_infoframe avi_if = {
-		.type = DIP_TYPE_AVI,
-		.ver = DIP_VERSION_AVI,
-		.len = DIP_LEN_AVI,
-	};
-	uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_sdvo->base.base.crtc);
+	uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)];
+	struct drm_crtc *crtc = intel_sdvo->base.base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	union hdmi_infoframe frame;
+	int ret;
+	ssize_t len;
+
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+						       adjusted_mode);
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill AVI infoframe\n");
+		return false;
+	}
 
 	if (intel_sdvo->rgb_quant_range_selectable) {
 		if (intel_crtc->config.limited_color_range)
-			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED;
+			frame.avi.quantization_range =
+				HDMI_QUANTIZATION_RANGE_LIMITED;
 		else
-			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL;
+			frame.avi.quantization_range =
+				HDMI_QUANTIZATION_RANGE_FULL;
 	}
 
-	avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode);
-
-	intel_dip_infoframe_csum(&avi_if);
-
-	/* sdvo spec says that the ecc is handled by the hw, and it looks like
-	 * we must not send the ecc field, either. */
-	memcpy(sdvo_data, &avi_if, 3);
-	sdvo_data[3] = avi_if.checksum;
-	memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
+	len = hdmi_infoframe_pack(&frame, sdvo_data, sizeof(sdvo_data));
+	if (len < 0)
+		return false;
 
 	return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
 					  SDVO_HBUF_TX_VSYNC,
@@ -1084,7 +1085,7 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_config *pipe_config)
 static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
 				      struct intel_crtc_config *pipe_config)
 {
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 	struct drm_display_mode *mode = &pipe_config->requested_mode;
 
@@ -1154,7 +1155,7 @@ static void intel_sdvo_mode_set(struct intel_encoder *intel_encoder)
 	struct drm_display_mode *adjusted_mode =
 		&intel_crtc->config.adjusted_mode;
 	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&intel_encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder);
 	u32 sdvox;
 	struct intel_sdvo_in_out_map in_out;
 	struct intel_sdvo_dtd input_dtd, output_dtd;
@@ -1292,7 +1293,7 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
 	u16 active_outputs = 0;
 	u32 tmp;
 
@@ -1315,7 +1316,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
 	struct intel_sdvo_dtd dtd;
 	int encoder_pixel_multiplier = 0;
 	u32 flags = 0, sdvox;
@@ -1357,22 +1358,21 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
 	}
 
 	/* Cross check the port pixel multiplier with the sdvo encoder state. */
-	intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, &val, 1);
-	switch (val) {
-	case SDVO_CLOCK_RATE_MULT_1X:
-		encoder_pixel_multiplier = 1;
-		break;
-	case SDVO_CLOCK_RATE_MULT_2X:
-		encoder_pixel_multiplier = 2;
-		break;
-	case SDVO_CLOCK_RATE_MULT_4X:
-		encoder_pixel_multiplier = 4;
-		break;
+	if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT,
+				 &val, 1)) {
+		switch (val) {
+		case SDVO_CLOCK_RATE_MULT_1X:
+			encoder_pixel_multiplier = 1;
+			break;
+		case SDVO_CLOCK_RATE_MULT_2X:
+			encoder_pixel_multiplier = 2;
+			break;
+		case SDVO_CLOCK_RATE_MULT_4X:
+			encoder_pixel_multiplier = 4;
+			break;
+		}
 	}
 
-	if(HAS_PCH_SPLIT(dev))
-		return; /* no pixel multiplier readout support yet */
-
 	WARN(encoder_pixel_multiplier != pipe_config->pixel_multiplier,
 	     "SDVO pixel multiplier mismatch, port: %i, encoder: %i\n",
 	     pipe_config->pixel_multiplier, encoder_pixel_multiplier);
@@ -1381,7 +1381,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
 static void intel_disable_sdvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
 	u32 temp;
 
 	intel_sdvo_set_active_outputs(intel_sdvo, 0);
@@ -1423,7 +1423,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	u32 temp;
 	bool input1, input2;
@@ -1584,7 +1584,7 @@ static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
 
 static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder)
 {
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
 
 	intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG,
 			&intel_sdvo->hotplug_active, 2);
@@ -1697,6 +1697,9 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
 	struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
 	enum drm_connector_status ret;
 
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+		      connector->base.id, drm_get_connector_name(connector));
+
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_ATTACHED_DISPLAYS,
 				  &response, 2))
@@ -2188,7 +2191,7 @@ static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs
 
 static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
 {
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
+	struct intel_sdvo *intel_sdvo = to_sdvo(to_intel_encoder(encoder));
 
 	if (intel_sdvo->sdvo_lvds_fixed_mode != NULL)
 		drm_mode_destroy(encoder->dev,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 1fa5612..78b621c 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -38,7 +38,8 @@
 #include "i915_drv.h"
 
 static void
-vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
+vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
+		 struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
 		 uint32_t x, uint32_t y,
@@ -108,14 +109,15 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 
 	sprctl |= SP_ENABLE;
 
+	intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
-
 	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
 	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
 
@@ -133,13 +135,13 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 
 	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 	I915_WRITE(SPCNTR(pipe, plane), sprctl);
-	I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset +
+	I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
 			     sprsurf_offset);
 	POSTING_READ(SPSURF(pipe, plane));
 }
 
 static void
-vlv_disable_plane(struct drm_plane *dplane)
+vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 {
 	struct drm_device *dev = dplane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -152,6 +154,8 @@ vlv_disable_plane(struct drm_plane *dplane)
 	/* Activate double buffered register update */
 	I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
 	POSTING_READ(SPSURF(pipe, plane));
+
+	intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
 }
 
 static int
@@ -206,7 +210,8 @@ vlv_get_colorkey(struct drm_plane *dplane,
 }
 
 static void
-ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		 struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
 		 uint32_t x, uint32_t y,
@@ -262,14 +267,15 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	if (IS_HASWELL(dev))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
+	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
-
 	/*
 	 * IVB workaround: must disable low power watermarks for at least
 	 * one frame before enabling scaling.  LP watermarks can be re-enabled
@@ -308,7 +314,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	if (intel_plane->can_scale)
 		I915_WRITE(SPRSCALE(pipe), sprscale);
 	I915_WRITE(SPRCTL(pipe), sprctl);
-	I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
+	I915_MODIFY_DISPBASE(SPRSURF(pipe),
+			     i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
 	POSTING_READ(SPRSURF(pipe));
 
 	/* potentially re-enable LP watermarks */
@@ -317,7 +324,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 }
 
 static void
-ivb_disable_plane(struct drm_plane *plane)
+ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -335,7 +342,7 @@ ivb_disable_plane(struct drm_plane *plane)
 
 	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 
-	intel_update_sprite_watermarks(dev, pipe, 0, 0, false);
+	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 
 	/* potentially re-enable LP watermarks */
 	if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
@@ -397,7 +404,8 @@ ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 }
 
 static void
-ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		 struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
 		 uint32_t x, uint32_t y,
@@ -449,14 +457,15 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 	dvscntr |= DVS_ENABLE;
 
+	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
-
 	dvsscale = 0;
 	if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
@@ -478,12 +487,13 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
 	I915_WRITE(DVSSCALE(pipe), dvsscale);
 	I915_WRITE(DVSCNTR(pipe), dvscntr);
-	I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
+	I915_MODIFY_DISPBASE(DVSSURF(pipe),
+			     i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
 	POSTING_READ(DVSSURF(pipe));
 }
 
 static void
-ilk_disable_plane(struct drm_plane *plane)
+ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -496,6 +506,8 @@ ilk_disable_plane(struct drm_plane *plane)
 	/* Flush double buffered register updates */
 	I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
 	POSTING_READ(DVSSURF(pipe));
+
+	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 }
 
 static void
@@ -818,11 +830,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		intel_enable_primary(crtc);
 
 	if (visible)
-		intel_plane->update_plane(plane, fb, obj,
+		intel_plane->update_plane(plane, crtc, fb, obj,
 					  crtc_x, crtc_y, crtc_w, crtc_h,
 					  src_x, src_y, src_w, src_h);
 	else
-		intel_plane->disable_plane(plane);
+		intel_plane->disable_plane(plane, crtc);
 
 	if (disable_primary)
 		intel_disable_primary(crtc);
@@ -855,9 +867,14 @@ intel_disable_plane(struct drm_plane *plane)
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int ret = 0;
 
-	if (plane->crtc)
-		intel_enable_primary(plane->crtc);
-	intel_plane->disable_plane(plane);
+	if (!plane->fb)
+		return 0;
+
+	if (WARN_ON(!plane->crtc))
+		return -EINVAL;
+
+	intel_enable_primary(plane->crtc);
+	intel_plane->disable_plane(plane, plane->crtc);
 
 	if (!intel_plane->obj)
 		goto out;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 39debd8..f2c6d79 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -823,16 +823,14 @@ static const struct tv_mode tv_modes[] = {
 	},
 };
 
-static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
+static struct intel_tv *enc_to_tv(struct intel_encoder *encoder)
 {
-	return container_of(encoder, struct intel_tv, base.base);
+	return container_of(encoder, struct intel_tv, base);
 }
 
 static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_tv,
-			    base);
+	return enc_to_tv(intel_attached_encoder(connector));
 }
 
 static bool
@@ -908,7 +906,7 @@ static bool
 intel_tv_compute_config(struct intel_encoder *encoder,
 			struct intel_crtc_config *pipe_config)
 {
-	struct intel_tv *intel_tv = enc_to_intel_tv(&encoder->base);
+	struct intel_tv *intel_tv = enc_to_tv(encoder);
 	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 
 	if (!tv_mode)
@@ -921,15 +919,12 @@ intel_tv_compute_config(struct intel_encoder *encoder,
 	return true;
 }
 
-static void
-intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
-		  struct drm_display_mode *adjusted_mode)
+static void intel_tv_mode_set(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc = encoder->crtc;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	struct intel_tv *intel_tv = enc_to_tv(encoder);
 	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 	u32 tv_ctl;
 	u32 hctl1, hctl2, hctl3;
@@ -1305,6 +1300,10 @@ intel_tv_detect(struct drm_connector *connector, bool force)
 	struct intel_tv *intel_tv = intel_attached_tv(connector);
 	int type;
 
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
+		      connector->base.id, drm_get_connector_name(connector),
+		      force);
+
 	mode = reported_modes[0];
 
 	if (force) {
@@ -1483,10 +1482,6 @@ out:
 	return ret;
 }
 
-static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
-	.mode_set = intel_tv_mode_set,
-};
-
 static const struct drm_connector_funcs intel_tv_connector_funcs = {
 	.dpms = intel_connector_dpms,
 	.detect = intel_tv_detect,
@@ -1619,6 +1614,7 @@ intel_tv_init(struct drm_device *dev)
 			 DRM_MODE_ENCODER_TVDAC);
 
 	intel_encoder->compute_config = intel_tv_compute_config;
+	intel_encoder->mode_set = intel_tv_mode_set;
 	intel_encoder->enable = intel_enable_tv;
 	intel_encoder->disable = intel_disable_tv;
 	intel_encoder->get_hw_state = intel_tv_get_hw_state;
@@ -1640,7 +1636,6 @@ intel_tv_init(struct drm_device *dev)
 
 	intel_tv->tv_format = tv_modes[initial_mode].name;
 
-	drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs);
 	drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
new file mode 100644
index 0000000..8f5bc86
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "i915_drv.h"
+#include "intel_drv.h"
+
+#define FORCEWAKE_ACK_TIMEOUT_MS 2
+
+#define __raw_i915_read8(dev_priv__, reg__) readb((dev_priv__)->regs + (reg__))
+#define __raw_i915_write8(dev_priv__, reg__, val__) writeb(val__, (dev_priv__)->regs + (reg__))
+
+#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__))
+#define __raw_i915_write16(dev_priv__, reg__, val__) writew(val__, (dev_priv__)->regs + (reg__))
+
+#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
+#define __raw_i915_write32(dev_priv__, reg__, val__) writel(val__, (dev_priv__)->regs + (reg__))
+
+#define __raw_i915_read64(dev_priv__, reg__) readq((dev_priv__)->regs + (reg__))
+#define __raw_i915_write64(dev_priv__, reg__, val__) writeq(val__, (dev_priv__)->regs + (reg__))
+
+#define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32(dev_priv__, reg__)
+
+
+static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
+{
+	u32 gt_thread_status_mask;
+
+	if (IS_HASWELL(dev_priv->dev))
+		gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW;
+	else
+		gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK;
+
+	/* w/a for a sporadic read returning 0 by waiting for the GT
+	 * thread to wake up.
+	 */
+	if (wait_for_atomic_us((__raw_i915_read32(dev_priv, GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500))
+		DRM_ERROR("GT thread status wait timed out\n");
+}
+
+static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
+{
+	__raw_i915_write32(dev_priv, FORCEWAKE, 0);
+	/* something from same cacheline, but !FORCEWAKE */
+	__raw_posting_read(dev_priv, ECOBUS);
+}
+
+static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+{
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
+
+	__raw_i915_write32(dev_priv, FORCEWAKE, 1);
+	/* something from same cacheline, but !FORCEWAKE */
+	__raw_posting_read(dev_priv, ECOBUS);
+
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
+
+	/* WaRsForcewakeWaitTC0:snb */
+	__gen6_gt_wait_for_thread_c0(dev_priv);
+}
+
+static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
+{
+	__raw_i915_write32(dev_priv, FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
+	/* something from same cacheline, but !FORCEWAKE_MT */
+	__raw_posting_read(dev_priv, ECOBUS);
+}
+
+static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+{
+	u32 forcewake_ack;
+
+	if (IS_HASWELL(dev_priv->dev))
+		forcewake_ack = FORCEWAKE_ACK_HSW;
+	else
+		forcewake_ack = FORCEWAKE_MT_ACK;
+
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, forcewake_ack) & FORCEWAKE_KERNEL) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
+
+	__raw_i915_write32(dev_priv, FORCEWAKE_MT,
+			   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+	/* something from same cacheline, but !FORCEWAKE_MT */
+	__raw_posting_read(dev_priv, ECOBUS);
+
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, forcewake_ack) & FORCEWAKE_KERNEL),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
+
+	/* WaRsForcewakeWaitTC0:ivb,hsw */
+	__gen6_gt_wait_for_thread_c0(dev_priv);
+}
+
+static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
+{
+	u32 gtfifodbg;
+
+	gtfifodbg = __raw_i915_read32(dev_priv, GTFIFODBG);
+	if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
+	     "MMIO read or write has been dropped %x\n", gtfifodbg))
+		__raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
+}
+
+static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+{
+	__raw_i915_write32(dev_priv, FORCEWAKE, 0);
+	/* something from same cacheline, but !FORCEWAKE */
+	__raw_posting_read(dev_priv, ECOBUS);
+	gen6_gt_check_fifodbg(dev_priv);
+}
+
+static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+{
+	__raw_i915_write32(dev_priv, FORCEWAKE_MT,
+			   _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+	/* something from same cacheline, but !FORCEWAKE_MT */
+	__raw_posting_read(dev_priv, ECOBUS);
+	gen6_gt_check_fifodbg(dev_priv);
+}
+
+static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
+{
+	int ret = 0;
+
+	if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
+		int loop = 500;
+		u32 fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
+			udelay(10);
+			fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+		}
+		if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
+			++ret;
+		dev_priv->uncore.fifo_count = fifo;
+	}
+	dev_priv->uncore.fifo_count--;
+
+	return ret;
+}
+
+static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
+{
+	__raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+			   _MASKED_BIT_DISABLE(0xffff));
+	/* something from same cacheline, but !FORCEWAKE_VLV */
+	__raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
+}
+
+static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+{
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
+
+	__raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+			   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+	__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+			   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n");
+
+	if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_MEDIA_VLV) &
+			     FORCEWAKE_KERNEL),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
+
+	/* WaRsForcewakeWaitTC0:vlv */
+	__gen6_gt_wait_for_thread_c0(dev_priv);
+}
+
+static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+{
+	__raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+			   _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+	__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+			   _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+	/* The below doubles as a POSTING_READ */
+	gen6_gt_check_fifodbg(dev_priv);
+}
+
+void intel_uncore_early_sanitize(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (HAS_FPGA_DBG_UNCLAIMED(dev))
+		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+}
+
+void intel_uncore_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_VALLEYVIEW(dev)) {
+		dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
+		dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
+	} else if (IS_HASWELL(dev)) {
+		dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get;
+		dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put;
+	} else if (IS_IVYBRIDGE(dev)) {
+		u32 ecobus;
+
+		/* IVB configs may use multi-threaded forcewake */
+
+		/* A small trick here - if the bios hasn't configured
+		 * MT forcewake, and if the device is in RC6, then
+		 * force_wake_mt_get will not wake the device and the
+		 * ECOBUS read will return zero. Which will be
+		 * (correctly) interpreted by the test below as MT
+		 * forcewake being disabled.
+		 */
+		mutex_lock(&dev->struct_mutex);
+		__gen6_gt_force_wake_mt_get(dev_priv);
+		ecobus = __raw_i915_read32(dev_priv, ECOBUS);
+		__gen6_gt_force_wake_mt_put(dev_priv);
+		mutex_unlock(&dev->struct_mutex);
+
+		if (ecobus & FORCEWAKE_MT_ENABLE) {
+			dev_priv->uncore.funcs.force_wake_get =
+				__gen6_gt_force_wake_mt_get;
+			dev_priv->uncore.funcs.force_wake_put =
+				__gen6_gt_force_wake_mt_put;
+		} else {
+			DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n");
+			DRM_INFO("when using vblank-synced partial screen updates.\n");
+			dev_priv->uncore.funcs.force_wake_get =
+				__gen6_gt_force_wake_get;
+			dev_priv->uncore.funcs.force_wake_put =
+				__gen6_gt_force_wake_put;
+		}
+	} else if (IS_GEN6(dev)) {
+		dev_priv->uncore.funcs.force_wake_get =
+			__gen6_gt_force_wake_get;
+		dev_priv->uncore.funcs.force_wake_put =
+			__gen6_gt_force_wake_put;
+	}
+}
+
+void intel_uncore_sanitize(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_VALLEYVIEW(dev)) {
+		vlv_force_wake_reset(dev_priv);
+	} else if (INTEL_INFO(dev)->gen >= 6) {
+		__gen6_gt_force_wake_reset(dev_priv);
+		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+			__gen6_gt_force_wake_mt_reset(dev_priv);
+	}
+
+	/* BIOS often leaves RC6 enabled, but disable it for hw init */
+	intel_disable_gt_powersave(dev);
+}
+
+/*
+ * Generally this is called implicitly by the register read function. However,
+ * if some sequence requires the GT to not power down then this function should
+ * be called at the beginning of the sequence followed by a call to
+ * gen6_gt_force_wake_put() at the end of the sequence.
+ */
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+	if (dev_priv->uncore.forcewake_count++ == 0)
+		dev_priv->uncore.funcs.force_wake_get(dev_priv);
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+/*
+ * see gen6_gt_force_wake_get()
+ */
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+	if (--dev_priv->uncore.forcewake_count == 0)
+		dev_priv->uncore.funcs.force_wake_put(dev_priv);
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+	((HAS_FORCE_WAKE((dev_priv)->dev)) && \
+	 ((reg) < 0x40000) &&            \
+	 ((reg) != FORCEWAKE))
+
+static void
+ilk_dummy_write(struct drm_i915_private *dev_priv)
+{
+	/* WaIssueDummyWriteToWakeupFromRC6:ilk Issue a dummy write to wake up
+	 * the chip from rc6 before touching it for real. MI_MODE is masked,
+	 * hence harmless to write 0 into. */
+	__raw_i915_write32(dev_priv, MI_MODE, 0);
+}
+
+static void
+hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
+{
+	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
+	    (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+		DRM_ERROR("Unknown unclaimed register before writing to %x\n",
+			  reg);
+		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+	}
+}
+
+static void
+hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
+{
+	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
+	    (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+		DRM_ERROR("Unclaimed write to %x\n", reg);
+		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+	}
+}
+
+#define __i915_read(x) \
+u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg, bool trace) { \
+	unsigned long irqflags; \
+	u##x val = 0; \
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); \
+	if (dev_priv->info->gen == 5) \
+		ilk_dummy_write(dev_priv); \
+	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+		if (dev_priv->uncore.forcewake_count == 0) \
+			dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+		val = __raw_i915_read##x(dev_priv, reg); \
+		if (dev_priv->uncore.forcewake_count == 0) \
+			dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+	} else { \
+		val = __raw_i915_read##x(dev_priv, reg); \
+	} \
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+	trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
+	return val; \
+}
+
+__i915_read(8)
+__i915_read(16)
+__i915_read(32)
+__i915_read(64)
+#undef __i915_read
+
+#define __i915_write(x) \
+void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val, bool trace) { \
+	unsigned long irqflags; \
+	u32 __fifo_ret = 0; \
+	trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); \
+	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
+	} \
+	if (dev_priv->info->gen == 5) \
+		ilk_dummy_write(dev_priv); \
+	hsw_unclaimed_reg_clear(dev_priv, reg); \
+	__raw_i915_write##x(dev_priv, reg, val); \
+	if (unlikely(__fifo_ret)) { \
+		gen6_gt_check_fifodbg(dev_priv); \
+	} \
+	hsw_unclaimed_reg_check(dev_priv, reg); \
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+}
+__i915_write(8)
+__i915_write(16)
+__i915_write(32)
+__i915_write(64)
+#undef __i915_write
+
+static const struct register_whitelist {
+	uint64_t offset;
+	uint32_t size;
+	uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
+} whitelist[] = {
+	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
+};
+
+int i915_reg_read_ioctl(struct drm_device *dev,
+			void *data, struct drm_file *file)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_reg_read *reg = data;
+	struct register_whitelist const *entry = whitelist;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
+		if (entry->offset == reg->offset &&
+		    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
+			break;
+	}
+
+	if (i == ARRAY_SIZE(whitelist))
+		return -EINVAL;
+
+	switch (entry->size) {
+	case 8:
+		reg->val = I915_READ64(reg->offset);
+		break;
+	case 4:
+		reg->val = I915_READ(reg->offset);
+		break;
+	case 2:
+		reg->val = I915_READ16(reg->offset);
+		break;
+	case 1:
+		reg->val = I915_READ8(reg->offset);
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int i8xx_do_reset(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_I85X(dev))
+		return -ENODEV;
+
+	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
+	POSTING_READ(D_STATE);
+
+	if (IS_I830(dev) || IS_845G(dev)) {
+		I915_WRITE(DEBUG_RESET_I830,
+			   DEBUG_RESET_DISPLAY |
+			   DEBUG_RESET_RENDER |
+			   DEBUG_RESET_FULL);
+		POSTING_READ(DEBUG_RESET_I830);
+		msleep(1);
+
+		I915_WRITE(DEBUG_RESET_I830, 0);
+		POSTING_READ(DEBUG_RESET_I830);
+	}
+
+	msleep(1);
+
+	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
+	POSTING_READ(D_STATE);
+
+	return 0;
+}
+
+static int i965_reset_complete(struct drm_device *dev)
+{
+	u8 gdrst;
+	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
+	return (gdrst & GRDOM_RESET_ENABLE) == 0;
+}
+
+static int i965_do_reset(struct drm_device *dev)
+{
+	int ret;
+
+	/*
+	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
+	 * well as the reset bit (GR/bit 0).  Setting the GR bit
+	 * triggers the reset; when done, the hardware will clear it.
+	 */
+	pci_write_config_byte(dev->pdev, I965_GDRST,
+			      GRDOM_RENDER | GRDOM_RESET_ENABLE);
+	ret =  wait_for(i965_reset_complete(dev), 500);
+	if (ret)
+		return ret;
+
+	/* We can't reset render&media without also resetting display ... */
+	pci_write_config_byte(dev->pdev, I965_GDRST,
+			      GRDOM_MEDIA | GRDOM_RESET_ENABLE);
+
+	ret =  wait_for(i965_reset_complete(dev), 500);
+	if (ret)
+		return ret;
+
+	pci_write_config_byte(dev->pdev, I965_GDRST, 0);
+
+	return 0;
+}
+
+static int ironlake_do_reset(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 gdrst;
+	int ret;
+
+	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+	gdrst &= ~GRDOM_MASK;
+	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
+		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
+	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
+	if (ret)
+		return ret;
+
+	/* We can't reset render&media without also resetting display ... */
+	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+	gdrst &= ~GRDOM_MASK;
+	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
+		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
+	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
+}
+
+static int gen6_do_reset(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int	ret;
+	unsigned long irqflags;
+
+	/* Hold uncore.lock across reset to prevent any register access
+	 * with forcewake not set correctly
+	 */
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	/* Reset the chip */
+
+	/* GEN6_GDRST is not in the gt power well, no need to check
+	 * for fifo space for the write or forcewake the chip for
+	 * the read
+	 */
+	__raw_i915_write32(dev_priv, GEN6_GDRST, GEN6_GRDOM_FULL);
+
+	/* Spin waiting for the device to ack the reset request */
+	ret = wait_for((__raw_i915_read32(dev_priv, GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+
+	/* If reset with a user forcewake, try to restore, otherwise turn it off */
+	if (dev_priv->uncore.forcewake_count)
+		dev_priv->uncore.funcs.force_wake_get(dev_priv);
+	else
+		dev_priv->uncore.funcs.force_wake_put(dev_priv);
+
+	/* Restore fifo count */
+	dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+	return ret;
+}
+
+int intel_gpu_reset(struct drm_device *dev)
+{
+	switch (INTEL_INFO(dev)->gen) {
+	case 7:
+	case 6: return gen6_do_reset(dev);
+	case 5: return ironlake_do_reset(dev);
+	case 4: return i965_do_reset(dev);
+	case 2: return i8xx_do_reset(dev);
+	default: return -ENODEV;
+	}
+}
+
+void intel_uncore_clear_errors(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* XXX needs spinlock around caller's grouping */
+	if (HAS_FPGA_DBG_UNCLAIMED(dev))
+		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+}
+
+void intel_uncore_check_errors(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (HAS_FPGA_DBG_UNCLAIMED(dev) &&
+	    (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+		DRM_ERROR("Unclaimed register before interrupt\n");
+		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+	}
+}
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
index 54558a0..ca4bc54 100644
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -149,7 +149,7 @@ typedef struct drm_mga_private {
 	unsigned int agp_size;
 } drm_mga_private_t;
 
-extern struct drm_ioctl_desc mga_ioctls[];
+extern const struct drm_ioctl_desc mga_ioctls[];
 extern int mga_max_ioctl;
 
 				/* mga_dma.c */
diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c
index 9c14514..37cc2fb 100644
--- a/drivers/gpu/drm/mga/mga_state.c
+++ b/drivers/gpu/drm/mga/mga_state.c
@@ -1083,7 +1083,7 @@ file_priv)
 	return 0;
 }
 
-struct drm_ioctl_desc mga_ioctls[] = {
+const struct drm_ioctl_desc mga_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH),
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 122b571..bd91964 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -104,7 +104,7 @@ static struct drm_driver driver = {
 	.gem_free_object = mgag200_gem_free_object,
 	.dumb_create = mgag200_dumb_create,
 	.dumb_map_offset = mgag200_dumb_mmap_offset,
-	.dumb_destroy = mgag200_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 };
 
 static struct pci_driver mgag200_pci_driver = {
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 12e2499..baaae19 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -264,9 +264,6 @@ int mgag200_gem_init_object(struct drm_gem_object *obj);
 int mgag200_dumb_create(struct drm_file *file,
 			struct drm_device *dev,
 			struct drm_mode_create_dumb *args);
-int mgag200_dumb_destroy(struct drm_file *file,
-			 struct drm_device *dev,
-			 uint32_t handle);
 void mgag200_gem_free_object(struct drm_gem_object *obj);
 int
 mgag200_dumb_mmap_offset(struct drm_file *file,
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index 9fa5685..0f8b861 100644
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -310,13 +310,6 @@ int mgag200_dumb_create(struct drm_file *file,
 	return 0;
 }
 
-int mgag200_dumb_destroy(struct drm_file *file,
-		     struct drm_device *dev,
-		     uint32_t handle)
-{
-	return drm_gem_handle_delete(file, handle);
-}
-
 int mgag200_gem_init_object(struct drm_gem_object *obj)
 {
 	BUG();
@@ -349,7 +342,7 @@ void mgag200_gem_free_object(struct drm_gem_object *obj)
 
 static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo)
 {
-	return bo->bo.addr_space_offset;
+	return drm_vma_node_offset_addr(&bo->bo.vma_node);
 }
 
 int
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
index 31cc8fe..054d9cf 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -150,7 +150,7 @@ dp_link_train_update(struct dp_state *dp, u32 delay)
 	if (ret)
 		return ret;
 
-	DBG("status %*ph\n", 6, dp->stat);
+	DBG("status %6ph\n", dp->stat);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index d97f200..4d70fb7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -46,6 +46,7 @@ bool nouveau_is_v1_dsm(void) {
 #define NOUVEAU_DSM_HAS_MUX 0x1
 #define NOUVEAU_DSM_HAS_OPT 0x2
 
+#ifdef CONFIG_VGA_SWITCHEROO
 static const char nouveau_dsm_muid[] = {
 	0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
 	0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
@@ -337,6 +338,10 @@ void nouveau_unregister_dsm_handler(void)
 	if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
 		vga_switcheroo_unregister_handler();
 }
+#else
+void nouveau_register_dsm_handler(void) {}
+void nouveau_unregister_dsm_handler(void) {}
+#endif
 
 /* retrieve the ROM in 4k blocks */
 static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 907d20e..78637af 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -674,13 +674,6 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
 }
 
 int
-nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
-			     uint32_t handle)
-{
-	return drm_gem_handle_delete(file_priv, handle);
-}
-
-int
 nouveau_display_dumb_map_offset(struct drm_file *file_priv,
 				struct drm_device *dev,
 				uint32_t handle, uint64_t *poffset)
@@ -690,7 +683,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv,
 	gem = drm_gem_object_lookup(dev, file_priv, handle);
 	if (gem) {
 		struct nouveau_bo *bo = gem->driver_private;
-		*poffset = bo->bo.addr_space_offset;
+		*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
 		drm_gem_object_unreference_unlocked(gem);
 		return 0;
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 1ea3e47..185e741 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -68,8 +68,6 @@ int  nouveau_display_dumb_create(struct drm_file *, struct drm_device *,
 				 struct drm_mode_create_dumb *args);
 int  nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
 				     u32 handle, u64 *offset);
-int  nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *,
-				  u32 handle);
 
 void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 6197266..1faa75f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -649,7 +649,7 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
 	nouveau_cli_destroy(cli);
 }
 
-static struct drm_ioctl_desc
+static const struct drm_ioctl_desc
 nouveau_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -684,7 +684,7 @@ nouveau_driver_fops = {
 static struct drm_driver
 driver = {
 	.driver_features =
-		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
+		DRIVER_USE_AGP |
 		DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME,
 
 	.load = nouveau_drm_load,
@@ -704,6 +704,7 @@ driver = {
 	.disable_vblank = nouveau_drm_vblank_disable,
 
 	.ioctls = nouveau_ioctls,
+	.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
 	.fops = &nouveau_driver_fops,
 
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
@@ -724,7 +725,7 @@ driver = {
 
 	.dumb_create = nouveau_display_dumb_create,
 	.dumb_map_offset = nouveau_display_dumb_map_offset,
-	.dumb_destroy = nouveau_display_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -774,8 +775,6 @@ nouveau_drm_pci_driver = {
 static int __init
 nouveau_drm_init(void)
 {
-	driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls);
-
 	if (nouveau_modeset == -1) {
 #ifdef CONFIG_VGA_CONSOLE
 		if (vgacon_text_force())
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 830cb7b..487242f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -220,7 +220,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
 	}
 
 	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
-	rep->map_handle = nvbo->bo.addr_space_offset;
+	rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node);
 	rep->tile_mode = nvbo->tile_mode;
 	rep->tile_flags = nvbo->tile_flags;
 	return 0;
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index a3004f1..2f9e22e 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -419,7 +419,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
 	return ret;
 }
 
-static struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
+static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
 	DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
@@ -633,7 +633,7 @@ static struct drm_driver omap_drm_driver = {
 		.gem_vm_ops = &omap_gem_vm_ops,
 		.dumb_create = omap_gem_dumb_create,
 		.dumb_map_offset = omap_gem_dumb_map_offset,
-		.dumb_destroy = omap_gem_dumb_destroy,
+		.dumb_destroy = drm_gem_dumb_destroy,
 		.ioctls = ioctls,
 		.num_ioctls = DRM_OMAP_NUM_IOCTLS,
 		.fops = &omapdriver_fops,
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 14f17da..f2ba425 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -225,8 +225,6 @@ int omap_gem_init_object(struct drm_gem_object *obj);
 void *omap_gem_vaddr(struct drm_gem_object *obj);
 int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
 		uint32_t handle, uint64_t *offset);
-int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-		uint32_t handle);
 int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 		struct drm_mode_create_dumb *args);
 int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma);
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index ebbdf41..b1f1970 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -20,6 +20,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/shmem_fs.h>
+#include <drm/drm_vma_manager.h>
 
 #include "omap_drv.h"
 #include "omap_dmm_tiler.h"
@@ -308,21 +309,20 @@ uint32_t omap_gem_flags(struct drm_gem_object *obj)
 static uint64_t mmap_offset(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
+	int ret;
+	size_t size;
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	if (!obj->map_list.map) {
-		/* Make it mmapable */
-		size_t size = omap_gem_mmap_size(obj);
-		int ret = _drm_gem_create_mmap_offset_size(obj, size);
-
-		if (ret) {
-			dev_err(dev->dev, "could not allocate mmap offset\n");
-			return 0;
-		}
+	/* Make it mmapable */
+	size = omap_gem_mmap_size(obj);
+	ret = _drm_gem_create_mmap_offset_size(obj, size);
+	if (ret) {
+		dev_err(dev->dev, "could not allocate mmap offset\n");
+		return 0;
 	}
 
-	return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
+	return drm_vma_node_offset_addr(&obj->vma_node);
 }
 
 uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
@@ -629,21 +629,6 @@ int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 }
 
 /**
- * omap_gem_dumb_destroy	-	destroy a dumb buffer
- * @file: client file
- * @dev: our DRM device
- * @handle: the object handle
- *
- * Destroy a handle that was created via omap_gem_dumb_create.
- */
-int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-		uint32_t handle)
-{
-	/* No special work needed, drop the reference and see what falls out */
-	return drm_gem_handle_delete(file, handle);
-}
-
-/**
  * omap_gem_dumb_map	-	buffer mapping for dumb interface
  * @file: our drm client file
  * @dev: drm device
@@ -997,12 +982,11 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 {
 	struct drm_device *dev = obj->dev;
 	struct omap_gem_object *omap_obj = to_omap_bo(obj);
-	uint64_t off = 0;
+	uint64_t off;
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	if (obj->map_list.map)
-		off = (uint64_t)obj->map_list.hash.key;
+	off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
 			omap_obj->flags, obj->name, obj->refcount.refcount.counter,
@@ -1309,8 +1293,7 @@ void omap_gem_free_object(struct drm_gem_object *obj)
 
 	list_del(&omap_obj->mm_list);
 
-	if (obj->map_list.map)
-		drm_gem_free_mmap_offset(obj);
+	drm_gem_free_mmap_offset(obj);
 
 	/* this means the object is still pinned.. which really should
 	 * not happen.  I think..
@@ -1427,8 +1410,9 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
 		omap_obj->height = gsize.tiled.height;
 	}
 
+	ret = 0;
 	if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM))
-		ret = drm_gem_private_object_init(dev, obj, size);
+		drm_gem_private_object_init(dev, obj, size);
 	else
 		ret = drm_gem_object_init(dev, obj, size);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c b/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
index f9eb679..dbb1575 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
@@ -118,52 +118,7 @@ _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret = 0;
-
-	/* Set the object up for mmap'ing */
-	list = &obj->map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (!list->map)
-		return -ENOMEM;
-
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = size;
-	map->handle = obj;
-
-	/* Get a DRM GEM mmap offset allocated... */
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-			size / PAGE_SIZE, 0, 0);
-
-	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
-		ret = -ENOSPC;
-		goto out_free_list;
-	}
-
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-			size / PAGE_SIZE, 0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto out_free_list;
-	}
-
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		DRM_ERROR("failed to add to map hash\n");
-		goto out_free_mm;
-	}
-
-	return 0;
-
-out_free_mm:
-	drm_mm_put_block(list->file_offset_node);
-out_free_list:
-	kfree(list->map);
-	list->map = NULL;
 
-	return ret;
+	return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
+				  size / PAGE_SIZE);
 }
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index df0b577..48f2dfd 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -221,7 +221,7 @@ static struct drm_driver qxl_driver = {
 
 	.dumb_create = qxl_mode_dumb_create,
 	.dumb_map_offset = qxl_mode_dumb_mmap,
-	.dumb_destroy = qxl_mode_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 #if defined(CONFIG_DEBUG_FS)
 	.debugfs_init = qxl_debugfs_init,
 	.debugfs_cleanup = qxl_debugfs_takedown,
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 7e96f4f..4708621 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -328,7 +328,7 @@ struct qxl_device {
 /* forward declaration for QXL_INFO_IO */
 void qxl_io_log(struct qxl_device *qdev, const char *fmt, ...);
 
-extern struct drm_ioctl_desc qxl_ioctls[];
+extern const struct drm_ioctl_desc qxl_ioctls[];
 extern int qxl_max_ioctl;
 
 int qxl_driver_load(struct drm_device *dev, unsigned long flags);
@@ -427,9 +427,6 @@ int qxl_bo_kmap(struct qxl_bo *bo, void **ptr);
 int qxl_mode_dumb_create(struct drm_file *file_priv,
 			 struct drm_device *dev,
 			 struct drm_mode_create_dumb *args);
-int qxl_mode_dumb_destroy(struct drm_file *file_priv,
-			  struct drm_device *dev,
-			  uint32_t handle);
 int qxl_mode_dumb_mmap(struct drm_file *filp,
 		       struct drm_device *dev,
 		       uint32_t handle, uint64_t *offset_p);
diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
index 847c4ee..d34bb41 100644
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -68,13 +68,6 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
 	return 0;
 }
 
-int qxl_mode_dumb_destroy(struct drm_file *file_priv,
-			     struct drm_device *dev,
-			     uint32_t handle)
-{
-	return drm_gem_handle_delete(file_priv, handle);
-}
-
 int qxl_mode_dumb_mmap(struct drm_file *file_priv,
 		       struct drm_device *dev,
 		       uint32_t handle, uint64_t *offset_p)
diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
index 6de3356..7b95c75 100644
--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
+++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
@@ -433,7 +433,7 @@ static int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data,
 	return ret;
 }
 
-struct drm_ioctl_desc qxl_ioctls[] = {
+const struct drm_ioctl_desc qxl_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(QXL_ALLOC, qxl_alloc_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF_DRV(QXL_MAP, qxl_map_ioctl, DRM_AUTH|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/qxl/qxl_object.h b/drivers/gpu/drm/qxl/qxl_object.h
index 8cb6167..d458a14 100644
--- a/drivers/gpu/drm/qxl/qxl_object.h
+++ b/drivers/gpu/drm/qxl/qxl_object.h
@@ -59,7 +59,7 @@ static inline unsigned long qxl_bo_size(struct qxl_bo *bo)
 
 static inline u64 qxl_bo_mmap_offset(struct qxl_bo *bo)
 {
-	return bo->tbo.addr_space_offset;
+	return drm_vma_node_offset_addr(&bo->tbo.vma_node);
 }
 
 static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type,
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index b61449e..0109a96 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -88,7 +88,7 @@ qxl_release_free(struct qxl_device *qdev,
 	list_for_each_entry_safe(entry, tmp, &release->bos, tv.head) {
 		struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
 		QXL_INFO(qdev, "release %llx\n",
-			entry->tv.bo->addr_space_offset
+			drm_vma_node_offset_addr(&entry->tv.bo->vma_node)
 						- DRM_FILE_OFFSET);
 		qxl_fence_remove_release(&bo->fence, release->id);
 		qxl_bo_unref(&bo);
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index d4660cf..c451257 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -540,7 +540,7 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
 	dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+	dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8);
 
 	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
 
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 930c71b..56eb5e3 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -131,7 +131,7 @@ typedef struct drm_r128_buf_priv {
 	drm_r128_freelist_t *list_entry;
 } drm_r128_buf_priv_t;
 
-extern struct drm_ioctl_desc r128_ioctls[];
+extern const struct drm_ioctl_desc r128_ioctls[];
 extern int r128_max_ioctl;
 
 				/* r128_cce.c */
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 19bb7e6..01dd9ae 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1643,7 +1643,7 @@ void r128_driver_lastclose(struct drm_device *dev)
 	r128_do_cleanup_cce(dev);
 }
 
-struct drm_ioctl_desc r128_ioctls[] = {
+const struct drm_ioctl_desc r128_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 32501f6..3569d89 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -585,7 +585,7 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
 		return false;
 	}
 
-	DRM_DEBUG_KMS("link status %*ph\n", 6, link_status);
+	DRM_DEBUG_KMS("link status %6ph\n", link_status);
 	return true;
 }
 
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 6dacec4..6adbc99 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -2535,8 +2535,8 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
 	/* ring 0 - compute and gfx */
 	/* Set ring buffer size */
 	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
-	rb_bufsz = drm_order(ring->ring_size / 8);
-	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+	rb_bufsz = order_base_2(ring->ring_size / 8);
+	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
@@ -2915,7 +2915,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
 		/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
 		tmp = RREG32(CP_HPD_EOP_CONTROL);
 		tmp &= ~EOP_SIZE_MASK;
-		tmp |= drm_order(MEC_HPD_SIZE / 8);
+		tmp |= order_base_2(MEC_HPD_SIZE / 8);
 		WREG32(CP_HPD_EOP_CONTROL, tmp);
 	}
 	cik_srbm_select(rdev, 0, 0, 0, 0);
@@ -3030,9 +3030,9 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
 			~(QUEUE_SIZE_MASK | RPTR_BLOCK_SIZE_MASK);
 
 		mqd->queue_state.cp_hqd_pq_control |=
-			drm_order(rdev->ring[idx].ring_size / 8);
+			order_base_2(rdev->ring[idx].ring_size / 8);
 		mqd->queue_state.cp_hqd_pq_control |=
-			(drm_order(RADEON_GPU_PAGE_SIZE/8) << 8);
+			(order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8);
 #ifdef __BIG_ENDIAN
 		mqd->queue_state.cp_hqd_pq_control |= BUF_SWAP_32BIT;
 #endif
@@ -3375,7 +3375,7 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev)
 		WREG32(SDMA0_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
 
 		/* Set ring buffer size in dwords */
-		rb_bufsz = drm_order(ring->ring_size / 4);
+		rb_bufsz = order_base_2(ring->ring_size / 4);
 		rb_cntl = rb_bufsz << 1;
 #ifdef __BIG_ENDIAN
 		rb_cntl |= SDMA_RB_SWAP_ENABLE | SDMA_RPTR_WRITEBACK_SWAP_ENABLE;
@@ -5030,7 +5030,7 @@ static int cik_irq_init(struct radeon_device *rdev)
 	WREG32(INTERRUPT_CNTL, interrupt_cntl);
 
 	WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
-	rb_bufsz = drm_order(rdev->ih.ring_size / 4);
+	rb_bufsz = order_base_2(rdev->ih.ring_size / 4);
 
 	ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
 		      IH_WPTR_OVERFLOW_CLEAR |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 038dcac..b67c9ec 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2881,8 +2881,8 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
 	RREG32(GRBM_SOFT_RESET);
 
 	/* Set ring buffer size */
-	rb_bufsz = drm_order(ring->ring_size / 8);
-	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+	rb_bufsz = order_base_2(ring->ring_size / 8);
+	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 56bd4f3..5b6e477 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1560,8 +1560,8 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 
 		/* Set ring buffer size */
 		ring = &rdev->ring[ridx[i]];
-		rb_cntl = drm_order(ring->ring_size / 8);
-		rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8;
+		rb_cntl = order_base_2(ring->ring_size / 8);
+		rb_cntl |= order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8;
 #ifdef __BIG_ENDIAN
 		rb_cntl |= BUF_SWAP_32BIT;
 #endif
@@ -1720,7 +1720,7 @@ int cayman_dma_resume(struct radeon_device *rdev)
 		WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
 
 		/* Set ring buffer size in dwords */
-		rb_bufsz = drm_order(ring->ring_size / 4);
+		rb_bufsz = order_base_2(ring->ring_size / 4);
 		rb_cntl = rb_bufsz << 1;
 #ifdef __BIG_ENDIAN
 		rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE;
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 75349cd..5625cf7 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1097,7 +1097,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
 	}
 
 	/* Align ring size */
-	rb_bufsz = drm_order(ring_size / 8);
+	rb_bufsz = order_base_2(ring_size / 8);
 	ring_size = (1 << (rb_bufsz + 1)) * 4;
 	r100_cp_load_microcode(rdev);
 	r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET,
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 10f712e..cfc1d28 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2413,8 +2413,8 @@ int r600_cp_resume(struct radeon_device *rdev)
 	WREG32(GRBM_SOFT_RESET, 0);
 
 	/* Set ring buffer size */
-	rb_bufsz = drm_order(ring->ring_size / 8);
-	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+	rb_bufsz = order_base_2(ring->ring_size / 8);
+	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
@@ -2467,7 +2467,7 @@ void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsign
 	int r;
 
 	/* Align ring size */
-	rb_bufsz = drm_order(ring_size / 8);
+	rb_bufsz = order_base_2(ring_size / 8);
 	ring_size = (1 << (rb_bufsz + 1)) * 4;
 	ring->ring_size = ring_size;
 	ring->align_mask = 16 - 1;
@@ -2547,7 +2547,7 @@ int r600_dma_resume(struct radeon_device *rdev)
 	WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL, 0);
 
 	/* Set ring buffer size in dwords */
-	rb_bufsz = drm_order(ring->ring_size / 4);
+	rb_bufsz = order_base_2(ring->ring_size / 4);
 	rb_cntl = rb_bufsz << 1;
 #ifdef __BIG_ENDIAN
 	rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE;
@@ -2656,7 +2656,7 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
 	WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
 
 	/* Set ring buffer size */
-	rb_bufsz = drm_order(ring->ring_size);
+	rb_bufsz = order_base_2(ring->ring_size);
 	rb_bufsz = (0x1 << 8) | rb_bufsz;
 	WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
 
@@ -3815,7 +3815,7 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
 	u32 rb_bufsz;
 
 	/* Align ring size */
-	rb_bufsz = drm_order(ring_size / 4);
+	rb_bufsz = order_base_2(ring_size / 4);
 	ring_size = (1 << rb_bufsz) * 4;
 	rdev->ih.ring_size = ring_size;
 	rdev->ih.ptr_mask = rdev->ih.ring_size - 1;
@@ -4052,7 +4052,7 @@ int r600_irq_init(struct radeon_device *rdev)
 	WREG32(INTERRUPT_CNTL, interrupt_cntl);
 
 	WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
-	rb_bufsz = drm_order(rdev->ih.ring_size / 4);
+	rb_bufsz = order_base_2(rdev->ih.ring_size / 4);
 
 	ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
 		      IH_WPTR_OVERFLOW_CLEAR |
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 1c51c08..d8eb48b 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -2200,13 +2200,13 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
 	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+	dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8);
 
 	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
-	dev_priv->ring.rptr_update_l2qw = drm_order(/* init->rptr_update */ 4096 / 8);
+	dev_priv->ring.rptr_update_l2qw = order_base_2(/* init->rptr_update */ 4096 / 8);
 
 	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
-	dev_priv->ring.fetch_size_l2ow = drm_order(/* init->fetch_size */ 32 / 16);
+	dev_priv->ring.fetch_size_l2ow = order_base_2(/* init->fetch_size */ 32 / 16);
 
 	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
 
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 2f08219..19066d1 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -492,9 +492,6 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
 int radeon_mode_dumb_mmap(struct drm_file *filp,
 			  struct drm_device *dev,
 			  uint32_t handle, uint64_t *offset_p);
-int radeon_mode_dumb_destroy(struct drm_file *file_priv,
-			     struct drm_device *dev,
-			     uint32_t handle);
 
 /*
  * Semaphores.
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index efc4f64..3cae2bb 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -1444,13 +1444,13 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
 	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+	dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8);
 
 	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
-	dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
+	dev_priv->ring.rptr_update_l2qw = order_base_2( /* init->rptr_update */ 4096 / 8);
 
 	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
-	dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
+	dev_priv->ring.fetch_size_l2ow = order_base_2( /* init->fetch_size */ 32 / 16);
 	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
 
 	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 29876b1..fa7a7e1 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -101,8 +101,6 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
 int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
 void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
 irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS);
-int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv);
 int radeon_gem_object_init(struct drm_gem_object *obj);
 void radeon_gem_object_free(struct drm_gem_object *obj);
 int radeon_gem_object_open(struct drm_gem_object *obj,
@@ -111,7 +109,7 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
 				struct drm_file *file_priv);
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
 				      int *vpos, int *hpos);
-extern struct drm_ioctl_desc radeon_ioctls_kms[];
+extern const struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
 int radeon_mode_dumb_mmap(struct drm_file *filp,
@@ -120,9 +118,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
 int radeon_mode_dumb_create(struct drm_file *file_priv,
 			    struct drm_device *dev,
 			    struct drm_mode_create_dumb *args);
-int radeon_mode_dumb_destroy(struct drm_file *file_priv,
-			     struct drm_device *dev,
-			     uint32_t handle);
 struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
 							size_t size,
@@ -390,8 +385,8 @@ static const struct file_operations radeon_driver_kms_fops = {
 
 static struct drm_driver kms_driver = {
 	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_GEM |
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | 
+	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
 	    DRIVER_PRIME,
 	.dev_priv_size = 0,
 	.load = radeon_driver_load_kms,
@@ -421,10 +416,9 @@ static struct drm_driver kms_driver = {
 	.gem_free_object = radeon_gem_object_free,
 	.gem_open_object = radeon_gem_object_open,
 	.gem_close_object = radeon_gem_object_close,
-	.dma_ioctl = radeon_dma_ioctl_kms,
 	.dumb_create = radeon_mode_dumb_create,
 	.dumb_map_offset = radeon_mode_dumb_mmap,
-	.dumb_destroy = radeon_mode_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 	.fops = &radeon_driver_kms_fops,
 
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index aa79603..dce99c8 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -570,13 +570,6 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
 	return 0;
 }
 
-int radeon_mode_dumb_destroy(struct drm_file *file_priv,
-			     struct drm_device *dev,
-			     uint32_t handle)
-{
-	return drm_gem_handle_delete(file_priv, handle);
-}
-
 #if defined(CONFIG_DEBUG_FS)
 static int radeon_debugfs_gem_info(struct seq_file *m, void *data)
 {
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 49ff3d1..866c2b7 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -683,16 +683,6 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
 						     drmcrtc);
 }
 
-/*
- * IOCTL.
- */
-int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	/* Not valid in KMS. */
-	return -EINVAL;
-}
-
 #define KMS_INVALID_IOCTL(name)						\
 int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\
 {									\
@@ -732,7 +722,7 @@ KMS_INVALID_IOCTL(radeon_surface_alloc_kms)
 KMS_INVALID_IOCTL(radeon_surface_free_kms)
 
 
-struct drm_ioctl_desc radeon_ioctls_kms[] = {
+const struct drm_ioctl_desc radeon_ioctls_kms[] = {
 	DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 49c82c4..209b111 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -113,13 +113,10 @@ static inline unsigned radeon_bo_gpu_page_alignment(struct radeon_bo *bo)
  * @bo:	radeon object for which we query the offset
  *
  * Returns mmap offset of the object.
- *
- * Note: addr_space_offset is constant after ttm bo init thus isn't protected
- * by any lock.
  */
 static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo)
 {
-	return bo->tbo.addr_space_offset;
+	return drm_vma_node_offset_addr(&bo->tbo.vma_node);
 }
 
 extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 6ca9046..8e23b6d 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -3383,8 +3383,8 @@ static int si_cp_resume(struct radeon_device *rdev)
 	/* ring 0 - compute and gfx */
 	/* Set ring buffer size */
 	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
-	rb_bufsz = drm_order(ring->ring_size / 8);
-	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+	rb_bufsz = order_base_2(ring->ring_size / 8);
+	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
@@ -3416,8 +3416,8 @@ static int si_cp_resume(struct radeon_device *rdev)
 	/* ring1  - compute only */
 	/* Set ring buffer size */
 	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
-	rb_bufsz = drm_order(ring->ring_size / 8);
-	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+	rb_bufsz = order_base_2(ring->ring_size / 8);
+	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
@@ -3442,8 +3442,8 @@ static int si_cp_resume(struct radeon_device *rdev)
 	/* ring2 - compute only */
 	/* Set ring buffer size */
 	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
-	rb_bufsz = drm_order(ring->ring_size / 8);
-	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+	rb_bufsz = order_base_2(ring->ring_size / 8);
+	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
@@ -5647,7 +5647,7 @@ static int si_irq_init(struct radeon_device *rdev)
 	WREG32(INTERRUPT_CNTL, interrupt_cntl);
 
 	WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
-	rb_bufsz = drm_order(rdev->ih.ring_size / 4);
+	rb_bufsz = order_base_2(rdev->ih.ring_size / 4);
 
 	ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
 		      IH_WPTR_OVERFLOW_CLEAR |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index dc0fe09..5069d9c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -258,7 +258,7 @@ static struct drm_driver rcar_du_driver = {
 	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
 	.dumb_create		= rcar_du_dumb_create,
 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
-	.dumb_destroy		= drm_gem_cma_dumb_destroy,
+	.dumb_destroy		= drm_gem_dumb_destroy,
 	.fops			= &rcar_du_fops,
 	.name			= "rcar-du",
 	.desc			= "Renesas R-Car Display Unit",
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
index bd6b2cf..b17d071 100644
--- a/drivers/gpu/drm/savage/savage_bci.c
+++ b/drivers/gpu/drm/savage/savage_bci.c
@@ -1072,7 +1072,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
 		drm_idlelock_release(&file_priv->master->lock);
 }
 
-struct drm_ioctl_desc savage_ioctls[] = {
+const struct drm_ioctl_desc savage_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
diff --git a/drivers/gpu/drm/savage/savage_drv.h b/drivers/gpu/drm/savage/savage_drv.h
index c05082a..335f8fc 100644
--- a/drivers/gpu/drm/savage/savage_drv.h
+++ b/drivers/gpu/drm/savage/savage_drv.h
@@ -104,7 +104,7 @@ enum savage_family {
 	S3_LAST
 };
 
-extern struct drm_ioctl_desc savage_ioctls[];
+extern const struct drm_ioctl_desc savage_ioctls[];
 extern int savage_max_ioctl;
 
 #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index 5f83f9a..7f2ea1a 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -285,7 +285,7 @@ static struct drm_driver shmob_drm_driver = {
 	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
 	.dumb_create		= drm_gem_cma_dumb_create,
 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
-	.dumb_destroy		= drm_gem_cma_dumb_destroy,
+	.dumb_destroy		= drm_gem_dumb_destroy,
 	.fops			= &shmob_drm_fops,
 	.name			= "shmob-drm",
 	.desc			= "Renesas SH Mobile DRM",
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
index 13b527b..c31c025 100644
--- a/drivers/gpu/drm/sis/sis_drv.h
+++ b/drivers/gpu/drm/sis/sis_drv.h
@@ -70,7 +70,7 @@ extern void sis_reclaim_buffers_locked(struct drm_device *dev,
 				       struct drm_file *file_priv);
 extern void sis_lastclose(struct drm_device *dev);
 
-extern struct drm_ioctl_desc sis_ioctls[];
+extern const struct drm_ioctl_desc sis_ioctls[];
 extern int sis_max_ioctl;
 
 #endif
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index 9a43d98..01857d8 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -109,7 +109,8 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
 	if (pool == AGP_TYPE) {
 		retval = drm_mm_insert_node(&dev_priv->agp_mm,
 					    &item->mm_node,
-					    mem->size, 0);
+					    mem->size, 0,
+					    DRM_MM_SEARCH_DEFAULT);
 		offset = item->mm_node.start;
 	} else {
 #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
@@ -121,7 +122,8 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
 #else
 		retval = drm_mm_insert_node(&dev_priv->vram_mm,
 					    &item->mm_node,
-					    mem->size, 0);
+					    mem->size, 0,
+					    DRM_MM_SEARCH_DEFAULT);
 		offset = item->mm_node.start;
 #endif
 	}
@@ -348,7 +350,7 @@ void sis_reclaim_buffers_locked(struct drm_device *dev,
 	return;
 }
 
-struct drm_ioctl_desc sis_ioctls[] = {
+const struct drm_ioctl_desc sis_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 40b71da..14801c2 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -519,7 +519,7 @@ static struct drm_driver tilcdc_driver = {
 	.gem_vm_ops         = &drm_gem_cma_vm_ops,
 	.dumb_create        = drm_gem_cma_dumb_create,
 	.dumb_map_offset    = drm_gem_cma_dumb_map_offset,
-	.dumb_destroy       = drm_gem_cma_dumb_destroy,
+	.dumb_destroy       = drm_gem_dumb_destroy,
 #ifdef CONFIG_DEBUG_FS
 	.debugfs_init       = tilcdc_debugfs_init,
 	.debugfs_cleanup    = tilcdc_debugfs_cleanup,
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index cb9dd67..f1a857e 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -45,7 +45,6 @@
 #define TTM_DEBUG(fmt, arg...)
 #define TTM_BO_HASH_ORDER 13
 
-static int ttm_bo_setup_vm(struct ttm_buffer_object *bo);
 static int ttm_bo_swapout(struct ttm_mem_shrink *shrink);
 static void ttm_bo_global_kobj_release(struct kobject *kobj);
 
@@ -615,13 +614,7 @@ static void ttm_bo_release(struct kref *kref)
 	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];
 
-	write_lock(&bdev->vm_lock);
-	if (likely(bo->vm_node != NULL)) {
-		rb_erase(&bo->vm_rb, &bdev->addr_space_rb);
-		drm_mm_put_block(bo->vm_node);
-		bo->vm_node = NULL;
-	}
-	write_unlock(&bdev->vm_lock);
+	drm_vma_offset_remove(&bdev->vma_manager, &bo->vma_node);
 	ttm_mem_io_lock(man, false);
 	ttm_mem_io_free_vm(bo);
 	ttm_mem_io_unlock(man);
@@ -1129,6 +1122,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
 	bo->resv = &bo->ttm_resv;
 	reservation_object_init(bo->resv);
 	atomic_inc(&bo->glob->bo_count);
+	drm_vma_node_reset(&bo->vma_node);
 
 	ret = ttm_bo_check_placement(bo, placement);
 
@@ -1139,7 +1133,8 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
 	if (likely(!ret) &&
 	    (bo->type == ttm_bo_type_device ||
 	     bo->type == ttm_bo_type_sg))
-		ret = ttm_bo_setup_vm(bo);
+		ret = drm_vma_offset_add(&bdev->vma_manager, &bo->vma_node,
+					 bo->mem.num_pages);
 
 	locked = ww_mutex_trylock(&bo->resv->lock);
 	WARN_ON(!locked);
@@ -1424,10 +1419,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev)
 		TTM_DEBUG("Swap list was clean\n");
 	spin_unlock(&glob->lru_lock);
 
-	BUG_ON(!drm_mm_clean(&bdev->addr_space_mm));
-	write_lock(&bdev->vm_lock);
-	drm_mm_takedown(&bdev->addr_space_mm);
-	write_unlock(&bdev->vm_lock);
+	drm_vma_offset_manager_destroy(&bdev->vma_manager);
 
 	return ret;
 }
@@ -1441,7 +1433,6 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
 {
 	int ret = -EINVAL;
 
-	rwlock_init(&bdev->vm_lock);
 	bdev->driver = driver;
 
 	memset(bdev->man, 0, sizeof(bdev->man));
@@ -1454,9 +1445,8 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
 	if (unlikely(ret != 0))
 		goto out_no_sys;
 
-	bdev->addr_space_rb = RB_ROOT;
-	drm_mm_init(&bdev->addr_space_mm, file_page_offset, 0x10000000);
-
+	drm_vma_offset_manager_init(&bdev->vma_manager, file_page_offset,
+				    0x10000000);
 	INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue);
 	INIT_LIST_HEAD(&bdev->ddestroy);
 	bdev->dev_mapping = NULL;
@@ -1498,12 +1488,8 @@ bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
-	loff_t offset = (loff_t) bo->addr_space_offset;
-	loff_t holelen = ((loff_t) bo->mem.num_pages) << PAGE_SHIFT;
 
-	if (!bdev->dev_mapping)
-		return;
-	unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1);
+	drm_vma_node_unmap(&bo->vma_node, bdev->dev_mapping);
 	ttm_mem_io_free_vm(bo);
 }
 
@@ -1520,78 +1506,6 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
 
 EXPORT_SYMBOL(ttm_bo_unmap_virtual);
 
-static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo)
-{
-	struct ttm_bo_device *bdev = bo->bdev;
-	struct rb_node **cur = &bdev->addr_space_rb.rb_node;
-	struct rb_node *parent = NULL;
-	struct ttm_buffer_object *cur_bo;
-	unsigned long offset = bo->vm_node->start;
-	unsigned long cur_offset;
-
-	while (*cur) {
-		parent = *cur;
-		cur_bo = rb_entry(parent, struct ttm_buffer_object, vm_rb);
-		cur_offset = cur_bo->vm_node->start;
-		if (offset < cur_offset)
-			cur = &parent->rb_left;
-		else if (offset > cur_offset)
-			cur = &parent->rb_right;
-		else
-			BUG();
-	}
-
-	rb_link_node(&bo->vm_rb, parent, cur);
-	rb_insert_color(&bo->vm_rb, &bdev->addr_space_rb);
-}
-
-/**
- * ttm_bo_setup_vm:
- *
- * @bo: the buffer to allocate address space for
- *
- * Allocate address space in the drm device so that applications
- * can mmap the buffer and access the contents. This only
- * applies to ttm_bo_type_device objects as others are not
- * placed in the drm device address space.
- */
-
-static int ttm_bo_setup_vm(struct ttm_buffer_object *bo)
-{
-	struct ttm_bo_device *bdev = bo->bdev;
-	int ret;
-
-retry_pre_get:
-	ret = drm_mm_pre_get(&bdev->addr_space_mm);
-	if (unlikely(ret != 0))
-		return ret;
-
-	write_lock(&bdev->vm_lock);
-	bo->vm_node = drm_mm_search_free(&bdev->addr_space_mm,
-					 bo->mem.num_pages, 0, 0);
-
-	if (unlikely(bo->vm_node == NULL)) {
-		ret = -ENOMEM;
-		goto out_unlock;
-	}
-
-	bo->vm_node = drm_mm_get_block_atomic(bo->vm_node,
-					      bo->mem.num_pages, 0);
-
-	if (unlikely(bo->vm_node == NULL)) {
-		write_unlock(&bdev->vm_lock);
-		goto retry_pre_get;
-	}
-
-	ttm_bo_vm_insert_rb(bo);
-	write_unlock(&bdev->vm_lock);
-	bo->addr_space_offset = ((uint64_t) bo->vm_node->start) << PAGE_SHIFT;
-
-	return 0;
-out_unlock:
-	write_unlock(&bdev->vm_lock);
-	return ret;
-}
 
 int ttm_bo_wait(struct ttm_buffer_object *bo,
 		bool lazy, bool interruptible, bool no_wait)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c
index e4367f9..c58eba33 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c
@@ -61,28 +61,25 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
 	lpfn = placement->lpfn;
 	if (!lpfn)
 		lpfn = man->size;
-	do {
-		ret = drm_mm_pre_get(mm);
-		if (unlikely(ret))
-			return ret;
 
-		spin_lock(&rman->lock);
-		node = drm_mm_search_free_in_range(mm,
-					mem->num_pages, mem->page_alignment,
-					placement->fpfn, lpfn, 1);
-		if (unlikely(node == NULL)) {
-			spin_unlock(&rman->lock);
-			return 0;
-		}
-		node = drm_mm_get_block_atomic_range(node, mem->num_pages,
-						     mem->page_alignment,
-						     placement->fpfn,
-						     lpfn);
-		spin_unlock(&rman->lock);
-	} while (node == NULL);
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+
+	spin_lock(&rman->lock);
+	ret = drm_mm_insert_node_in_range(mm, node, mem->num_pages,
+					  mem->page_alignment,
+					  placement->fpfn, lpfn,
+					  DRM_MM_SEARCH_BEST);
+	spin_unlock(&rman->lock);
+
+	if (unlikely(ret)) {
+		kfree(node);
+	} else {
+		mem->mm_node = node;
+		mem->start = node->start;
+	}
 
-	mem->mm_node = node;
-	mem->start = node->start;
 	return 0;
 }
 
@@ -93,8 +90,10 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man,
 
 	if (mem->mm_node) {
 		spin_lock(&rman->lock);
-		drm_mm_put_block(mem->mm_node);
+		drm_mm_remove_node(mem->mm_node);
 		spin_unlock(&rman->lock);
+
+		kfree(mem->mm_node);
 		mem->mm_node = NULL;
 	}
 }
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 319cf41..7cc904d 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -30,6 +30,7 @@
 
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_placement.h>
+#include <drm/drm_vma_manager.h>
 #include <linux/io.h>
 #include <linux/highmem.h>
 #include <linux/wait.h>
@@ -450,7 +451,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
 	INIT_LIST_HEAD(&fbo->lru);
 	INIT_LIST_HEAD(&fbo->swap);
 	INIT_LIST_HEAD(&fbo->io_reserve_lru);
-	fbo->vm_node = NULL;
+	drm_vma_node_reset(&fbo->vma_node);
 	atomic_set(&fbo->cpu_writers, 0);
 
 	spin_lock(&bdev->fence_lock);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 3df9f16..8c0e2c0 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -33,6 +33,7 @@
 #include <ttm/ttm_module.h>
 #include <ttm/ttm_bo_driver.h>
 #include <ttm/ttm_placement.h>
+#include <drm/drm_vma_manager.h>
 #include <linux/mm.h>
 #include <linux/rbtree.h>
 #include <linux/module.h>
@@ -40,37 +41,6 @@
 
 #define TTM_BO_VM_NUM_PREFAULT 16
 
-static struct ttm_buffer_object *ttm_bo_vm_lookup_rb(struct ttm_bo_device *bdev,
-						     unsigned long page_start,
-						     unsigned long num_pages)
-{
-	struct rb_node *cur = bdev->addr_space_rb.rb_node;
-	unsigned long cur_offset;
-	struct ttm_buffer_object *bo;
-	struct ttm_buffer_object *best_bo = NULL;
-
-	while (likely(cur != NULL)) {
-		bo = rb_entry(cur, struct ttm_buffer_object, vm_rb);
-		cur_offset = bo->vm_node->start;
-		if (page_start >= cur_offset) {
-			cur = cur->rb_right;
-			best_bo = bo;
-			if (page_start == cur_offset)
-				break;
-		} else
-			cur = cur->rb_left;
-	}
-
-	if (unlikely(best_bo == NULL))
-		return NULL;
-
-	if (unlikely((best_bo->vm_node->start + best_bo->num_pages) <
-		     (page_start + num_pages)))
-		return NULL;
-
-	return best_bo;
-}
-
 static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
@@ -146,9 +116,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	}
 
 	page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
-	    bo->vm_node->start - vma->vm_pgoff;
+	    drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
 	page_last = vma_pages(vma) +
-	    bo->vm_node->start - vma->vm_pgoff;
+	    drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
 
 	if (unlikely(page_offset >= bo->num_pages)) {
 		retval = VM_FAULT_SIGBUS;
@@ -249,6 +219,30 @@ static const struct vm_operations_struct ttm_bo_vm_ops = {
 	.close = ttm_bo_vm_close
 };
 
+static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_bo_device *bdev,
+						  unsigned long offset,
+						  unsigned long pages)
+{
+	struct drm_vma_offset_node *node;
+	struct ttm_buffer_object *bo = NULL;
+
+	drm_vma_offset_lock_lookup(&bdev->vma_manager);
+
+	node = drm_vma_offset_lookup_locked(&bdev->vma_manager, offset, pages);
+	if (likely(node)) {
+		bo = container_of(node, struct ttm_buffer_object, vma_node);
+		if (!kref_get_unless_zero(&bo->kref))
+			bo = NULL;
+	}
+
+	drm_vma_offset_unlock_lookup(&bdev->vma_manager);
+
+	if (!bo)
+		pr_err("Could not find buffer object to map\n");
+
+	return bo;
+}
+
 int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
 		struct ttm_bo_device *bdev)
 {
@@ -256,17 +250,9 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
 	struct ttm_buffer_object *bo;
 	int ret;
 
-	read_lock(&bdev->vm_lock);
-	bo = ttm_bo_vm_lookup_rb(bdev, vma->vm_pgoff,
-				 vma_pages(vma));
-	if (likely(bo != NULL) && !kref_get_unless_zero(&bo->kref))
-		bo = NULL;
-	read_unlock(&bdev->vm_lock);
-
-	if (unlikely(bo == NULL)) {
-		pr_err("Could not find buffer object to map\n");
+	bo = ttm_bo_vm_lookup(bdev, vma->vm_pgoff, vma_pages(vma));
+	if (unlikely(!bo))
 		return -EINVAL;
-	}
 
 	driver = bo->bdev->driver;
 	if (unlikely(!driver->verify_access)) {
@@ -324,12 +310,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
 	bool no_wait = false;
 	bool dummy;
 
-	read_lock(&bdev->vm_lock);
-	bo = ttm_bo_vm_lookup_rb(bdev, dev_offset, 1);
-	if (likely(bo != NULL))
-		ttm_bo_reference(bo);
-	read_unlock(&bdev->vm_lock);
-
+	bo = ttm_bo_vm_lookup(bdev, dev_offset, 1);
 	if (unlikely(bo == NULL))
 		return -EFAULT;
 
@@ -343,7 +324,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
 	if (unlikely(ret != 0))
 		goto out_unref;
 
-	kmap_offset = dev_offset - bo->vm_node->start;
+	kmap_offset = dev_offset - drm_vma_node_start(&bo->vma_node);
 	if (unlikely(kmap_offset >= bo->num_pages)) {
 		ret = -EFBIG;
 		goto out_unref;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index bd2a3b4..863bef9 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -377,28 +377,26 @@ out:
 	return nr_free;
 }
 
-/* Get good estimation how many pages are free in pools */
-static int ttm_pool_get_num_unused_pages(void)
-{
-	unsigned i;
-	int total = 0;
-	for (i = 0; i < NUM_POOLS; ++i)
-		total += _manager->pools[i].npages;
-
-	return total;
-}
-
 /**
  * Callback for mm to request pool to reduce number of page held.
+ *
+ * XXX: (dchinner) Deadlock warning!
+ *
+ * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that means
+ * this can deadlock when called a sc->gfp_mask that is not equal to
+ * GFP_KERNEL.
+ *
+ * This code is crying out for a shrinker per pool....
  */
-static int ttm_pool_mm_shrink(struct shrinker *shrink,
-			      struct shrink_control *sc)
+static unsigned long
+ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	static atomic_t start_pool = ATOMIC_INIT(0);
 	unsigned i;
 	unsigned pool_offset = atomic_add_return(1, &start_pool);
 	struct ttm_page_pool *pool;
 	int shrink_pages = sc->nr_to_scan;
+	unsigned long freed = 0;
 
 	pool_offset = pool_offset % NUM_POOLS;
 	/* select start pool in round robin fashion */
@@ -408,14 +406,28 @@ static int ttm_pool_mm_shrink(struct shrinker *shrink,
 			break;
 		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
 		shrink_pages = ttm_page_pool_free(pool, nr_free);
+		freed += nr_free - shrink_pages;
 	}
-	/* return estimated number of unused pages in pool */
-	return ttm_pool_get_num_unused_pages();
+	return freed;
+}
+
+
+static unsigned long
+ttm_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+	unsigned i;
+	unsigned long count = 0;
+
+	for (i = 0; i < NUM_POOLS; ++i)
+		count += _manager->pools[i].npages;
+
+	return count;
 }
 
 static void ttm_pool_mm_shrink_init(struct ttm_pool_manager *manager)
 {
-	manager->mm_shrink.shrink = &ttm_pool_mm_shrink;
+	manager->mm_shrink.count_objects = ttm_pool_shrink_count;
+	manager->mm_shrink.scan_objects = ttm_pool_shrink_scan;
 	manager->mm_shrink.seeks = 1;
 	register_shrinker(&manager->mm_shrink);
 }
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index b8b3943..7957bee 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -918,19 +918,6 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev)
 }
 EXPORT_SYMBOL_GPL(ttm_dma_populate);
 
-/* Get good estimation how many pages are free in pools */
-static int ttm_dma_pool_get_num_unused_pages(void)
-{
-	struct device_pools *p;
-	unsigned total = 0;
-
-	mutex_lock(&_manager->lock);
-	list_for_each_entry(p, &_manager->pools, pools)
-		total += p->pool->npages_free;
-	mutex_unlock(&_manager->lock);
-	return total;
-}
-
 /* Put all pages in pages list to correct pool to wait for reuse */
 void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
 {
@@ -1002,18 +989,29 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
 
 /**
  * Callback for mm to request pool to reduce number of page held.
+ *
+ * XXX: (dchinner) Deadlock warning!
+ *
+ * ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention
+ * needs to be paid to sc->gfp_mask to determine if this can be done or not.
+ * GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really
+ * bad.
+ *
+ * I'm getting sadder as I hear more pathetical whimpers about needing per-pool
+ * shrinkers
  */
-static int ttm_dma_pool_mm_shrink(struct shrinker *shrink,
-				  struct shrink_control *sc)
+static unsigned long
+ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	static atomic_t start_pool = ATOMIC_INIT(0);
 	unsigned idx = 0;
 	unsigned pool_offset = atomic_add_return(1, &start_pool);
 	unsigned shrink_pages = sc->nr_to_scan;
 	struct device_pools *p;
+	unsigned long freed = 0;
 
 	if (list_empty(&_manager->pools))
-		return 0;
+		return SHRINK_STOP;
 
 	mutex_lock(&_manager->lock);
 	pool_offset = pool_offset % _manager->npools;
@@ -1029,18 +1027,33 @@ static int ttm_dma_pool_mm_shrink(struct shrinker *shrink,
 			continue;
 		nr_free = shrink_pages;
 		shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free);
+		freed += nr_free - shrink_pages;
+
 		pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n",
 			 p->pool->dev_name, p->pool->name, current->pid,
 			 nr_free, shrink_pages);
 	}
 	mutex_unlock(&_manager->lock);
-	/* return estimated number of unused pages in pool */
-	return ttm_dma_pool_get_num_unused_pages();
+	return freed;
+}
+
+static unsigned long
+ttm_dma_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+	struct device_pools *p;
+	unsigned long count = 0;
+
+	mutex_lock(&_manager->lock);
+	list_for_each_entry(p, &_manager->pools, pools)
+		count += p->pool->npages_free;
+	mutex_unlock(&_manager->lock);
+	return count;
 }
 
 static void ttm_dma_pool_mm_shrink_init(struct ttm_pool_manager *manager)
 {
-	manager->mm_shrink.shrink = &ttm_dma_pool_mm_shrink;
+	manager->mm_shrink.count_objects = ttm_dma_pool_shrink_count;
+	manager->mm_shrink.scan_objects = &ttm_dma_pool_shrink_scan;
 	manager->mm_shrink.seeks = 1;
 	register_shrinker(&manager->mm_shrink);
 }
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index c0770db..bb0af58 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -84,7 +84,7 @@ static struct drm_driver driver = {
 
 	.dumb_create = udl_dumb_create,
 	.dumb_map_offset = udl_gem_mmap,
-	.dumb_destroy = udl_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 	.fops = &udl_driver_fops,
 
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index cc6d90f..56aec94 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -114,8 +114,6 @@ int udl_dumb_create(struct drm_file *file_priv,
 		    struct drm_mode_create_dumb *args);
 int udl_gem_mmap(struct drm_file *file_priv, struct drm_device *dev,
 		 uint32_t handle, uint64_t *offset);
-int udl_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
-		     uint32_t handle);
 
 int udl_gem_init_object(struct drm_gem_object *obj);
 void udl_gem_free_object(struct drm_gem_object *gem_obj);
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index ef034fa..b5e3b80 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -66,12 +66,6 @@ int udl_dumb_create(struct drm_file *file,
 			      args->size, &args->handle);
 }
 
-int udl_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-		     uint32_t handle)
-{
-	return drm_gem_handle_delete(file, handle);
-}
-
 int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	int ret;
@@ -223,8 +217,7 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj)
 	if (obj->pages)
 		udl_gem_put_pages(obj);
 
-	if (gem_obj->map_list.map)
-		drm_gem_free_mmap_offset(gem_obj);
+	drm_gem_free_mmap_offset(gem_obj);
 }
 
 /* the dumb interface doesn't work with the GEM straight MMAP
@@ -247,13 +240,11 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev,
 	ret = udl_gem_get_pages(gobj, GFP_KERNEL);
 	if (ret)
 		goto out;
-	if (!gobj->base.map_list.map) {
-		ret = drm_gem_create_mmap_offset(obj);
-		if (ret)
-			goto out;
-	}
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		goto out;
 
-	*offset = (u64)gobj->base.map_list.hash.key << PAGE_SHIFT;
+	*offset = drm_vma_node_offset_addr(&gobj->base.vma_node);
 
 out:
 	drm_gem_object_unreference(&gobj->base);
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 0ce2d71..f5ae574 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -41,8 +41,8 @@ static int udl_parse_vendor_descriptor(struct drm_device *dev,
 	total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
 				    0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
 	if (total_len > 5) {
-		DRM_INFO("vendor descriptor length:%x data:%*ph\n",
-			total_len, 11, desc);
+		DRM_INFO("vendor descriptor length:%x data:%11ph\n",
+			total_len, desc);
 
 		if ((desc[0] != total_len) || /* descriptor length */
 		    (desc[1] != 0x5f) ||   /* vendor descriptor type */
diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c
index 13558f5..652f9b4 100644
--- a/drivers/gpu/drm/via/via_dma.c
+++ b/drivers/gpu/drm/via/via_dma.c
@@ -720,7 +720,7 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *
 	return ret;
 }
 
-struct drm_ioctl_desc via_ioctls[] = {
+const struct drm_ioctl_desc via_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 893a650..a811ef2 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -114,7 +114,7 @@ enum via_family {
 #define VIA_READ8(reg)		DRM_READ8(VIA_BASE, reg)
 #define VIA_WRITE8(reg, val)	DRM_WRITE8(VIA_BASE, reg, val)
 
-extern struct drm_ioctl_desc via_ioctls[];
+extern const struct drm_ioctl_desc via_ioctls[];
 extern int via_max_ioctl;
 
 extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
index 0ab93ff..7e3ad87 100644
--- a/drivers/gpu/drm/via/via_mm.c
+++ b/drivers/gpu/drm/via/via_mm.c
@@ -140,11 +140,11 @@ int via_mem_alloc(struct drm_device *dev, void *data,
 	if (mem->type == VIA_MEM_AGP)
 		retval = drm_mm_insert_node(&dev_priv->agp_mm,
 					    &item->mm_node,
-					    tmpSize, 0);
+					    tmpSize, 0, DRM_MM_SEARCH_DEFAULT);
 	else
 		retval = drm_mm_insert_node(&dev_priv->vram_mm,
 					    &item->mm_node,
-					    tmpSize, 0);
+					    tmpSize, 0, DRM_MM_SEARCH_DEFAULT);
 	if (retval)
 		goto fail_alloc;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 78e2164..5086150 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -124,7 +124,7 @@
  * Ioctl definitions.
  */
 
-static struct drm_ioctl_desc vmw_ioctls[] = {
+static const struct drm_ioctl_desc vmw_ioctls[] = {
 	VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
 		      DRM_AUTH | DRM_UNLOCKED),
 	VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
@@ -782,7 +782,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
 
 	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
 	    && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
-		struct drm_ioctl_desc *ioctl =
+		const struct drm_ioctl_desc *ioctl =
 		    &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
 		if (unlikely(ioctl->cmd_drv != cmd)) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 7953d1f..0e67cf4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -500,7 +500,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
 		goto out_no_dmabuf;
 
 	rep->handle = handle;
-	rep->map_handle = dma_buf->base.addr_space_offset;
+	rep->map_handle = drm_vma_node_offset_addr(&dma_buf->base.vma_node);
 	rep->cur_gmr_id = handle;
 	rep->cur_gmr_offset = 0;
 
@@ -834,7 +834,7 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
 	if (ret != 0)
 		return -EINVAL;
 
-	*offset = out_buf->base.addr_space_offset;
+	*offset = drm_vma_node_offset_addr(&out_buf->base.vma_node);
 	vmw_dmabuf_unreference(&out_buf);
 	return 0;
 }
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index e184b00..b128b90 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -487,7 +487,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
 }
 #endif
 
-static struct drm_ioctl_desc tegra_drm_ioctls[] = {
+static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
 #ifdef CONFIG_DRM_TEGRA_STAGING
 	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
@@ -633,7 +633,7 @@ struct drm_driver tegra_drm_driver = {
 	.gem_vm_ops = &tegra_bo_vm_ops,
 	.dumb_create = tegra_bo_dumb_create,
 	.dumb_map_offset = tegra_bo_dumb_map_offset,
-	.dumb_destroy = tegra_bo_dumb_destroy,
+	.dumb_destroy = drm_gem_dumb_destroy,
 
 	.ioctls = tegra_drm_ioctls,
 	.num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c
index c5e9a9b..3c35622 100644
--- a/drivers/gpu/host1x/drm/gem.c
+++ b/drivers/gpu/host1x/drm/gem.c
@@ -108,7 +108,7 @@ static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo)
 
 unsigned int tegra_bo_get_mmap_offset(struct tegra_bo *bo)
 {
-	return (unsigned int)bo->gem.map_list.hash.key << PAGE_SHIFT;
+	return (unsigned int)drm_vma_node_offset_addr(&bo->gem.vma_node);
 }
 
 struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
@@ -182,8 +182,7 @@ void tegra_bo_free_object(struct drm_gem_object *gem)
 {
 	struct tegra_bo *bo = to_tegra_bo(gem);
 
-	if (gem->map_list.map)
-		drm_gem_free_mmap_offset(gem);
+	drm_gem_free_mmap_offset(gem);
 
 	drm_gem_object_release(gem);
 	tegra_bo_destroy(gem->dev, bo);
@@ -262,9 +261,3 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
 
 	return ret;
 }
-
-int tegra_bo_dumb_destroy(struct drm_file *file, struct drm_device *drm,
-			  unsigned int handle)
-{
-	return drm_gem_handle_delete(file, handle);
-}
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h
index 34de2b4..2e93b03 100644
--- a/drivers/gpu/host1x/drm/gem.h
+++ b/drivers/gpu/host1x/drm/gem.h
@@ -49,8 +49,6 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
 			 struct drm_mode_create_dumb *args);
 int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
 			     uint32_t handle, uint64_t *offset);
-int tegra_bo_dumb_destroy(struct drm_file *file, struct drm_device *drm,
-			  unsigned int handle);
 
 int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
 
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 14ef6ab..3d7c9f6 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -743,6 +743,14 @@ config HID_WIIMOTE
 	To compile this driver as a module, choose M here: the
 	module will be called hid-wiimote.
 
+config HID_XINMO
+	tristate "Xin-Mo non-fully compliant devices"
+	depends on HID
+	---help---
+	Support for Xin-Mo devices that are not fully compliant with the HID
+	standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
+	if you have a Xin-Mo Dual Arcade controller.
+
 config HID_ZEROPLUS
 	tristate "Zeroplus based game controller support"
 	depends on HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 6f68728..a959f4a 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_HID_TIVO)		+= hid-tivo.o
 obj-$(CONFIG_HID_TOPSEED)	+= hid-topseed.o
 obj-$(CONFIG_HID_TWINHAN)	+= hid-twinhan.o
 obj-$(CONFIG_HID_UCLOGIC)	+= hid-uclogic.o
+obj-$(CONFIG_HID_XINMO)		+= hid-xinmo.o
 obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
 obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
 obj-$(CONFIG_HID_WACOM)		+= hid-wacom.o
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
index 7c5507e..9428ea7 100644
--- a/drivers/hid/hid-a4tech.c
+++ b/drivers/hid/hid-a4tech.c
@@ -90,11 +90,10 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	struct a4tech_sc *a4;
 	int ret;
 
-	a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
+	a4 = devm_kzalloc(&hdev->dev, sizeof(*a4), GFP_KERNEL);
 	if (a4 == NULL) {
 		hid_err(hdev, "can't alloc device descriptor\n");
-		ret = -ENOMEM;
-		goto err_free;
+		return -ENOMEM;
 	}
 
 	a4->quirks = id->driver_data;
@@ -104,27 +103,16 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
 		hid_err(hdev, "hw start failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	return 0;
-err_free:
-	kfree(a4);
-	return ret;
-}
-
-static void a4_remove(struct hid_device *hdev)
-{
-	struct a4tech_sc *a4 = hid_get_drvdata(hdev);
-
-	hid_hw_stop(hdev);
-	kfree(a4);
 }
 
 static const struct hid_device_id a4_devices[] = {
@@ -144,7 +132,6 @@ static struct hid_driver a4_driver = {
 	.input_mapped = a4_input_mapped,
 	.event = a4_event,
 	.probe = a4_probe,
-	.remove = a4_remove,
 };
 module_hid_driver(a4_driver);
 
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index c7710b5..881cf7b 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -349,7 +349,7 @@ static int apple_probe(struct hid_device *hdev,
 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
 	int ret;
 
-	asc = kzalloc(sizeof(*asc), GFP_KERNEL);
+	asc = devm_kzalloc(&hdev->dev, sizeof(*asc), GFP_KERNEL);
 	if (asc == NULL) {
 		hid_err(hdev, "can't alloc apple descriptor\n");
 		return -ENOMEM;
@@ -362,7 +362,7 @@ static int apple_probe(struct hid_device *hdev,
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	if (quirks & APPLE_HIDDEV)
@@ -373,19 +373,10 @@ static int apple_probe(struct hid_device *hdev,
 	ret = hid_hw_start(hdev, connect_mask);
 	if (ret) {
 		hid_err(hdev, "hw start failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	return 0;
-err_free:
-	kfree(asc);
-	return ret;
-}
-
-static void apple_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
 }
 
 static const struct hid_device_id apple_devices[] = {
@@ -551,7 +542,6 @@ static struct hid_driver apple_driver = {
 	.id_table = apple_devices,
 	.report_fixup = apple_report_fixup,
 	.probe = apple_probe,
-	.remove = apple_remove,
 	.event = apple_event,
 	.input_mapping = apple_input_mapping,
 	.input_mapped = apple_input_mapped,
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 36668d1..3efe19f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -450,7 +450,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
 			}
 			parser->local.delimiter_depth--;
 		}
-		return 1;
+		return 0;
 
 	case HID_LOCAL_ITEM_TAG_USAGE:
 
@@ -1128,7 +1128,8 @@ static void hid_output_field(const struct hid_device *hid,
 }
 
 /*
- * Create a report.
+ * Create a report. 'data' has to be allocated using
+ * hid_alloc_report_buf() so that it has proper size.
  */
 
 void hid_output_report(struct hid_report *report, __u8 *data)
@@ -1145,6 +1146,22 @@ void hid_output_report(struct hid_report *report, __u8 *data)
 EXPORT_SYMBOL_GPL(hid_output_report);
 
 /*
+ * Allocator for buffer that is going to be passed to hid_output_report()
+ */
+u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
+{
+	/*
+	 * 7 extra bytes are necessary to achieve proper functionality
+	 * of implement() working on 8 byte chunks
+	 */
+
+	int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
+
+	return kmalloc(len, flags);
+}
+EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
+
+/*
  * Set a field value. The report this field belongs to has to be
  * created and transferred to the device, to set this value in the
  * device.
@@ -1597,6 +1614,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
@@ -1736,6 +1754,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
index 9a8f051..9325545 100644
--- a/drivers/hid/hid-holtekff.c
+++ b/drivers/hid/hid-holtekff.c
@@ -98,7 +98,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
 		holtekff->field->value[i] = data[i];
 	}
 
-	dbg_hid("sending %*ph\n", 7, data);
+	dbg_hid("sending %7ph\n", data);
 
 	hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
 }
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 7132173..8fae6d1 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -590,6 +590,5 @@ static void __exit mousevsc_exit(void)
 }
 
 MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
 module_init(mousevsc_init);
 module_exit(mousevsc_exit);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ffe4c7a..4f01a52 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -482,6 +482,7 @@
 #define USB_VENDOR_ID_KYE		0x0458
 #define USB_DEVICE_ID_KYE_ERGO_525V	0x0087
 #define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE	0x0138
+#define USB_DEVICE_ID_GENIUS_GX_IMPERATOR	0x4018
 #define USB_DEVICE_ID_KYE_GPEN_560	0x5003
 #define USB_DEVICE_ID_KYE_EASYPEN_I405X	0x5010
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X	0x5011
@@ -887,6 +888,9 @@
 #define USB_VENDOR_ID_XAT	0x2505
 #define USB_DEVICE_ID_XAT_CSR	0x0220
 
+#define USB_VENDOR_ID_XIN_MO			0x16c0
+#define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE	0x05e1
+
 #define USB_VENDOR_ID_XIROKU		0x1477
 #define USB_DEVICE_ID_XIROKU_SPX	0x1006
 #define USB_DEVICE_ID_XIROKU_MPX	0x1007
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7480799..308eee8 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1137,6 +1137,74 @@ unsigned int hidinput_count_leds(struct hid_device *hid)
 }
 EXPORT_SYMBOL_GPL(hidinput_count_leds);
 
+static void hidinput_led_worker(struct work_struct *work)
+{
+	struct hid_device *hid = container_of(work, struct hid_device,
+					      led_work);
+	struct hid_field *field;
+	struct hid_report *report;
+	int len;
+	__u8 *buf;
+
+	field = hidinput_get_led_field(hid);
+	if (!field)
+		return;
+
+	/*
+	 * field->report is accessed unlocked regarding HID core. So there might
+	 * be another incoming SET-LED request from user-space, which changes
+	 * the LED state while we assemble our outgoing buffer. However, this
+	 * doesn't matter as hid_output_report() correctly converts it into a
+	 * boolean value no matter what information is currently set on the LED
+	 * field (even garbage). So the remote device will always get a valid
+	 * request.
+	 * And in case we send a wrong value, a next led worker is spawned
+	 * for every SET-LED request so the following worker will send the
+	 * correct value, guaranteed!
+	 */
+
+	report = field->report;
+
+	/* use custom SET_REPORT request if possible (asynchronous) */
+	if (hid->ll_driver->request)
+		return hid->ll_driver->request(hid, report, HID_REQ_SET_REPORT);
+
+	/* fall back to generic raw-output-report */
+	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+	buf = kmalloc(len, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	hid_output_report(report, buf);
+	/* synchronous output report */
+	hid->hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT);
+	kfree(buf);
+}
+
+static int hidinput_input_event(struct input_dev *dev, unsigned int type,
+				unsigned int code, int value)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct hid_field *field;
+	int offset;
+
+	if (type == EV_FF)
+		return input_ff_event(dev, type, code, value);
+
+	if (type != EV_LED)
+		return -1;
+
+	if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
+		hid_warn(dev, "event field not found\n");
+		return -1;
+	}
+
+	hid_set_field(field, offset, value);
+
+	schedule_work(&hid->led_work);
+	return 0;
+}
+
 static int hidinput_open(struct input_dev *dev)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
@@ -1183,7 +1251,10 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
 	}
 
 	input_set_drvdata(input_dev, hid);
-	input_dev->event = hid->ll_driver->hidinput_input_event;
+	if (hid->ll_driver->hidinput_input_event)
+		input_dev->event = hid->ll_driver->hidinput_input_event;
+	else if (hid->ll_driver->request || hid->hid_output_raw_report)
+		input_dev->event = hidinput_input_event;
 	input_dev->open = hidinput_open;
 	input_dev->close = hidinput_close;
 	input_dev->setkeycode = hidinput_setkeycode;
@@ -1278,6 +1349,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 	int i, j, k;
 
 	INIT_LIST_HEAD(&hid->inputs);
+	INIT_WORK(&hid->led_work, hidinput_led_worker);
 
 	if (!force) {
 		for (i = 0; i < hid->maxcollection; i++) {
@@ -1379,6 +1451,12 @@ void hidinput_disconnect(struct hid_device *hid)
 		input_unregister_device(hidinput->input);
 		kfree(hidinput);
 	}
+
+	/* led_work is spawned by input_dev callbacks, but doesn't access the
+	 * parent input_dev at all. Once all input devices are removed, we
+	 * know that led_work will never get restarted, so we can cancel it
+	 * synchronously and are safe. */
+	cancel_work_sync(&hid->led_work);
 }
 EXPORT_SYMBOL_GPL(hidinput_disconnect);
 
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c
index 1e2ee2aa..7384512 100644
--- a/drivers/hid/hid-kye.c
+++ b/drivers/hid/hid-kye.c
@@ -268,6 +268,26 @@ static __u8 easypen_m610x_rdesc_fixed[] = {
 	0xC0                          /*  End Collection                  */
 };
 
+static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int *rsize, int offset, const char *device_name) {
+	/*
+	 * the fixup that need to be done:
+	 *   - change Usage Maximum in the Comsumer Control
+	 *     (report ID 3) to a reasonable value
+	 */
+	if (*rsize >= offset + 31 &&
+	    /* Usage Page (Consumer Devices) */
+	    rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
+	    /* Usage (Consumer Control) */
+	    rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
+	    /*   Usage Maximum > 12287 */
+	    rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
+		hid_info(hdev, "fixing up %s report descriptor\n", device_name);
+		rdesc[offset + 12] = 0x2f;
+	}
+	return rdesc;
+}
+
 static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
@@ -315,23 +335,12 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		}
 		break;
 	case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
-		/*
-		 * the fixup that need to be done:
-		 *   - change Usage Maximum in the Comsumer Control
-		 *     (report ID 3) to a reasonable value
-		 */
-		if (*rsize >= 135 &&
-			/* Usage Page (Consumer Devices) */
-			rdesc[104] == 0x05 && rdesc[105] == 0x0c &&
-			/* Usage (Consumer Control) */
-			rdesc[106] == 0x09 && rdesc[107] == 0x01 &&
-			/*   Usage Maximum > 12287 */
-			rdesc[114] == 0x2a && rdesc[116] > 0x2f) {
-			hid_info(hdev,
-				 "fixing up Genius Gila Gaming Mouse "
-				 "report descriptor\n");
-			rdesc[116] = 0x2f;
-		}
+		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
+					"Genius Gila Gaming Mouse");
+		break;
+	case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
+		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
+					"Genius Gx Imperator Keyboard");
 		break;
 	}
 	return rdesc;
@@ -428,6 +437,8 @@ static const struct hid_device_id kye_devices[] = {
 				USB_DEVICE_ID_KYE_EASYPEN_M610X) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
 				USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+				USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, kye_devices);
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 7a57648..2f5b3bb 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -621,7 +621,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
 
 	struct hid_field *field;
 	struct hid_report *report;
-	unsigned char data[8];
+	unsigned char *data;
 	int offset;
 
 	dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
@@ -637,6 +637,13 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
 		return -1;
 	}
 	hid_set_field(field, offset, value);
+
+	data = hid_alloc_report_buf(field->report, GFP_ATOMIC);
+	if (!data) {
+		dev_warn(&dev->dev, "failed to allocate report buf memory\n");
+		return -1;
+	}
+
 	hid_output_report(field->report, &data[0]);
 
 	output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
@@ -647,8 +654,9 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
 
 	hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
 
-	return 0;
+	kfree(data);
 
+	return 0;
 }
 
 static int logi_dj_ll_start(struct hid_device *hid)
@@ -803,10 +811,10 @@ static int logi_dj_probe(struct hid_device *hdev,
 	}
 
 	/* This is enabling the polling urb on the IN endpoint */
-	retval = hdev->ll_driver->open(hdev);
+	retval = hid_hw_open(hdev);
 	if (retval < 0) {
-		dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
-			"error:%d\n", __func__, retval);
+		dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
+			__func__, retval);
 		goto llopen_failed;
 	}
 
@@ -823,7 +831,7 @@ static int logi_dj_probe(struct hid_device *hdev,
 	return retval;
 
 logi_dj_recv_query_paired_devices_failed:
-	hdev->ll_driver->close(hdev);
+	hid_hw_close(hdev);
 
 llopen_failed:
 switch_to_dj_mode_fail:
@@ -865,7 +873,7 @@ static void logi_dj_remove(struct hid_device *hdev)
 
 	cancel_work_sync(&djrcv_dev->work);
 
-	hdev->ll_driver->close(hdev);
+	hid_hw_close(hdev);
 	hid_hw_stop(hdev);
 
 	/* I suppose that at this point the only context that can access
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 5bc3734..3b43d1c 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
 static unsigned int scroll_speed = 32;
 static int param_set_scroll_speed(const char *val, struct kernel_param *kp) {
 	unsigned long speed;
-	if (!val || strict_strtoul(val, 0, &speed) || speed > 63)
+	if (!val || kstrtoul(val, 0, &speed) || speed > 63)
 		return -EINVAL;
 	scroll_speed = speed;
 	return 0;
@@ -484,7 +484,7 @@ static int magicmouse_probe(struct hid_device *hdev,
 	struct hid_report *report;
 	int ret;
 
-	msc = kzalloc(sizeof(*msc), GFP_KERNEL);
+	msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
 	if (msc == NULL) {
 		hid_err(hdev, "can't alloc magicmouse descriptor\n");
 		return -ENOMEM;
@@ -498,13 +498,13 @@ static int magicmouse_probe(struct hid_device *hdev,
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "magicmouse hid parse failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
 		hid_err(hdev, "magicmouse hw start failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	if (!msc->input) {
@@ -548,19 +548,9 @@ static int magicmouse_probe(struct hid_device *hdev,
 	return 0;
 err_stop_hw:
 	hid_hw_stop(hdev);
-err_free:
-	kfree(msc);
 	return ret;
 }
 
-static void magicmouse_remove(struct hid_device *hdev)
-{
-	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
-
-	hid_hw_stop(hdev);
-	kfree(msc);
-}
-
 static const struct hid_device_id magic_mice[] = {
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 		USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
@@ -574,7 +564,6 @@ static struct hid_driver magicmouse_driver = {
 	.name = "magicmouse",
 	.id_table = magic_mice,
 	.probe = magicmouse_probe,
-	.remove = magicmouse_remove,
 	.raw_event = magicmouse_raw_event,
 	.input_mapping = magicmouse_input_mapping,
 	.input_configured = magicmouse_input_configured,
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index cb0e361..0fe00e2 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -261,17 +261,6 @@ static struct mt_class mt_classes[] = {
 	{ }
 };
 
-static void mt_free_input_name(struct hid_input *hi)
-{
-	struct hid_device *hdev = hi->report->device;
-	const char *name = hi->input->name;
-
-	if (name != hdev->name) {
-		hi->input->name = hdev->name;
-		kfree(name);
-	}
-}
-
 static ssize_t mt_show_quirks(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
@@ -415,13 +404,6 @@ static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
 static void mt_pen_input_configured(struct hid_device *hdev,
 					struct hid_input *hi)
 {
-	char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL);
-	if (name) {
-		sprintf(name, "%s Pen", hi->input->name);
-		mt_free_input_name(hi);
-		hi->input->name = name;
-	}
-
 	/* force BTN_STYLUS to allow tablet matching in udev */
 	__set_bit(BTN_STYLUS, hi->input->keybit);
 }
@@ -928,16 +910,26 @@ static void mt_post_parse(struct mt_device *td)
 static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
 {
 	struct mt_device *td = hid_get_drvdata(hdev);
-	char *name = kstrdup(hdev->name, GFP_KERNEL);
-
-	if (name)
-		hi->input->name = name;
+	char *name;
+	const char *suffix = NULL;
 
 	if (hi->report->id == td->mt_report_id)
 		mt_touch_input_configured(hdev, hi);
 
-	if (hi->report->id == td->pen_report_id)
+	if (hi->report->field[0]->physical == HID_DG_STYLUS) {
+		suffix = "Pen";
 		mt_pen_input_configured(hdev, hi);
+	}
+
+	if (suffix) {
+		name = devm_kzalloc(&hi->input->dev,
+				    strlen(hdev->name) + strlen(suffix) + 2,
+				    GFP_KERNEL);
+		if (name) {
+			sprintf(name, "%s %s", hdev->name, suffix);
+			hi->input->name = name;
+		}
+	}
 }
 
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -945,7 +937,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	int ret, i;
 	struct mt_device *td;
 	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
-	struct hid_input *hi;
 
 	for (i = 0; mt_classes[i].name ; i++) {
 		if (id->driver_data == mt_classes[i].name) {
@@ -967,7 +958,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
 	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
 
-	td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
+	td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
 	if (!td) {
 		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
 		return -ENOMEM;
@@ -980,11 +971,11 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	td->pen_report_id = -1;
 	hid_set_drvdata(hdev, td);
 
-	td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL);
+	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
+				  GFP_KERNEL);
 	if (!td->fields) {
 		dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
-		ret = -ENOMEM;
-		goto fail;
+		return -ENOMEM;
 	}
 
 	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
@@ -992,29 +983,22 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	ret = hid_parse(hdev);
 	if (ret != 0)
-		goto fail;
+		return ret;
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret)
-		goto hid_fail;
+		return ret;
 
 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
 
 	mt_set_maxcontacts(hdev);
 	mt_set_input_mode(hdev);
 
-	kfree(td->fields);
+	/* release .fields memory as it is not used anymore */
+	devm_kfree(&hdev->dev, td->fields);
 	td->fields = NULL;
 
 	return 0;
-
-hid_fail:
-	list_for_each_entry(hi, &hdev->inputs, list)
-		mt_free_input_name(hi);
-fail:
-	kfree(td->fields);
-	kfree(td);
-	return ret;
 }
 
 #ifdef CONFIG_PM
@@ -1039,17 +1023,8 @@ static int mt_resume(struct hid_device *hdev)
 
 static void mt_remove(struct hid_device *hdev)
 {
-	struct mt_device *td = hid_get_drvdata(hdev);
-	struct hid_input *hi;
-
 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
-	list_for_each_entry(hi, &hdev->inputs, list)
-		mt_free_input_name(hi);
-
 	hid_hw_stop(hdev);
-
-	kfree(td);
-	hid_set_drvdata(hdev, NULL);
 }
 
 static const struct hid_device_id mt_devices[] = {
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index ef95102..98d1fdf 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -237,7 +237,7 @@ static ssize_t set_min_width(struct device *dev,
 
 	unsigned long val;
 
-	if (strict_strtoul(buf, 0, &val))
+	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
 	if (val > nd->sensor_physical_width)
@@ -272,7 +272,7 @@ static ssize_t set_min_height(struct device *dev,
 
 	unsigned long val;
 
-	if (strict_strtoul(buf, 0, &val))
+	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
 	if (val > nd->sensor_physical_height)
@@ -306,7 +306,7 @@ static ssize_t set_activate_slack(struct device *dev,
 
 	unsigned long val;
 
-	if (strict_strtoul(buf, 0, &val))
+	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
 	if (val > 0x7f)
@@ -341,7 +341,7 @@ static ssize_t set_activation_width(struct device *dev,
 
 	unsigned long val;
 
-	if (strict_strtoul(buf, 0, &val))
+	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
 	if (val > nd->sensor_physical_width)
@@ -377,7 +377,7 @@ static ssize_t set_activation_height(struct device *dev,
 
 	unsigned long val;
 
-	if (strict_strtoul(buf, 0, &val))
+	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
 	if (val > nd->sensor_physical_height)
@@ -411,7 +411,7 @@ static ssize_t set_deactivate_slack(struct device *dev,
 
 	unsigned long val;
 
-	if (strict_strtoul(buf, 0, &val))
+	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
 	/*
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
index 59ab8e1..024cdf3 100644
--- a/drivers/hid/hid-picolcd_debugfs.c
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -394,7 +394,7 @@ static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
 void picolcd_debug_out_report(struct picolcd_data *data,
 		struct hid_device *hdev, struct hid_report *report)
 {
-	u8 raw_data[70];
+	u8 *raw_data;
 	int raw_size = (report->size >> 3) + 1;
 	char *buff;
 #define BUFF_SZ 256
@@ -407,20 +407,20 @@ void picolcd_debug_out_report(struct picolcd_data *data,
 	if (!buff)
 		return;
 
-	snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
-			report->id, raw_size);
-	hid_debug_event(hdev, buff);
-	if (raw_size + 5 > sizeof(raw_data)) {
+	raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
+	if (!raw_data) {
 		kfree(buff);
-		hid_debug_event(hdev, " TOO BIG\n");
 		return;
-	} else {
-		raw_data[0] = report->id;
-		hid_output_report(report, raw_data);
-		dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
-		hid_debug_event(hdev, buff);
 	}
 
+	snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
+			report->id, raw_size);
+	hid_debug_event(hdev, buff);
+	raw_data[0] = report->id;
+	hid_output_report(report, raw_data);
+	dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
+	hid_debug_event(hdev, buff);
+
 	switch (report->id) {
 	case REPORT_LED_STATE:
 		/* 1 data byte with GPO state */
@@ -644,6 +644,7 @@ void picolcd_debug_out_report(struct picolcd_data *data,
 		break;
 	}
 	wake_up_interruptible(&hdev->debug_wait);
+	kfree(raw_data);
 	kfree(buff);
 }
 
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 327f9b8..071ee9e 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -59,7 +59,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
 	unsigned long state;
 	int retval;
 
-	retval = strict_strtoul(buf, 10, &state);
+	retval = kstrtoul(buf, 10, &state);
 	if (retval)
 		return retval;
 
@@ -107,7 +107,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
 	unsigned long key_mask;
 	int retval;
 
-	retval = strict_strtoul(buf, 10, &key_mask);
+	retval = kstrtoul(buf, 10, &key_mask);
 	if (retval)
 		return retval;
 
@@ -159,7 +159,7 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
 	unsigned long profile;
 	int retval;
 
-	retval = strict_strtoul(buf, 10, &profile);
+	retval = kstrtoul(buf, 10, &profile);
 	if (retval)
 		return retval;
 
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 8023751..5dd0ea4 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -82,7 +82,7 @@ static ssize_t isku_sysfs_set_actual_profile(struct device *dev,
 	isku = hid_get_drvdata(dev_get_drvdata(dev));
 	usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-	retval = strict_strtoul(buf, 10, &profile);
+	retval = kstrtoul(buf, 10, &profile);
 	if (retval)
 		return retval;
 
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 7fae070..00ab287 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -456,7 +456,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
 	kone = hid_get_drvdata(dev_get_drvdata(dev));
 	usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-	retval = strict_strtoul(buf, 10, &state);
+	retval = kstrtoul(buf, 10, &state);
 	if (retval)
 		return retval;
 
@@ -545,7 +545,7 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
 	kone = hid_get_drvdata(dev_get_drvdata(dev));
 	usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-	retval = strict_strtoul(buf, 10, &new_startup_profile);
+	retval = kstrtoul(buf, 10, &new_startup_profile);
 	if (retval)
 		return retval;
 
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 6a48fa3..26b9663 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -246,7 +246,7 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
 	koneplus = hid_get_drvdata(dev_get_drvdata(dev));
 	usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-	retval = strict_strtoul(buf, 10, &profile);
+	retval = kstrtoul(buf, 10, &profile);
 	if (retval)
 		return retval;
 
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index b8b3778..c2a17e4 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -282,7 +282,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
 	kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
 	usb_dev = interface_to_usbdev(to_usb_interface(dev));
 
-	retval = strict_strtoul(buf, 10, &profile);
+	retval = kstrtoul(buf, 10, &profile);
 	if (retval)
 		return retval;
 
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 87fbe29..30dbb6b 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -624,7 +624,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	struct sony_sc *sc;
 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
 
-	sc = kzalloc(sizeof(*sc), GFP_KERNEL);
+	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
 	if (sc == NULL) {
 		hid_err(hdev, "can't alloc sony descriptor\n");
 		return -ENOMEM;
@@ -636,7 +636,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	if (sc->quirks & VAIO_RDESC_CONSTANT)
@@ -649,7 +649,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	ret = hid_hw_start(hdev, connect_mask);
 	if (ret) {
 		hid_err(hdev, "hw start failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
@@ -669,8 +669,6 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	return 0;
 err_stop:
 	hid_hw_stop(hdev);
-err_free:
-	kfree(sc);
 	return ret;
 }
 
@@ -682,7 +680,6 @@ static void sony_remove(struct hid_device *hdev)
 		buzz_remove(hdev);
 
 	hid_hw_stop(hdev);
-	kfree(sc);
 }
 
 static const struct hid_device_id sony_devices[] = {
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 0c06054..6602098 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -212,10 +212,12 @@ static __u8 select_drm(struct wiimote_data *wdata)
 
 	if (ir == WIIPROTO_FLAG_IR_BASIC) {
 		if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) {
-			if (ext)
-				return WIIPROTO_REQ_DRM_KAIE;
-			else
-				return WIIPROTO_REQ_DRM_KAI;
+			/* GEN10 and ealier devices bind IR formats to DRMs.
+			 * Hence, we cannot use DRM_KAI here as it might be
+			 * bound to IR_EXT. Use DRM_KAIE unconditionally so we
+			 * work with all devices and our parsers can use the
+			 * fixed formats, too. */
+			return WIIPROTO_REQ_DRM_KAIE;
 		} else {
 			return WIIPROTO_REQ_DRM_KIE;
 		}
diff --git a/drivers/hid/hid-xinmo.c b/drivers/hid/hid-xinmo.c
new file mode 100644
index 0000000..6153e50
--- /dev/null
+++ b/drivers/hid/hid-xinmo.c
@@ -0,0 +1,72 @@
+/*
+ *  HID driver for Xin-Mo devices, currently only the Dual Arcade controller.
+ *  Fixes the negative axis event values (the devices sends -2) to match the
+ *  logical axis minimum of the HID report descriptor (the report announces
+ *  -1). It is needed because hid-input discards out of bounds values.
+ *  (This module is based on "hid-saitek" and "hid-lg".)
+ *
+ *  Copyright (c) 2013 Olivier Scherler
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include "hid-ids.h"
+
+/*
+ * Fix negative events that are out of bounds.
+ */
+static int xinmo_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	switch (usage->code) {
+	case ABS_X:
+	case ABS_Y:
+	case ABS_Z:
+	case ABS_RX:
+		if (value < -1) {
+			input_event(field->hidinput->input, usage->type,
+				usage->code, -1);
+			return 1;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static const struct hid_device_id xinmo_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, xinmo_devices);
+
+static struct hid_driver xinmo_driver = {
+	.name = "xinmo",
+	.id_table = xinmo_devices,
+	.event = xinmo_event
+};
+
+static int __init xinmo_init(void)
+{
+	return hid_register_driver(&xinmo_driver);
+}
+
+static void __exit xinmo_exit(void)
+{
+	hid_unregister_driver(&xinmo_driver);
+}
+
+module_init(xinmo_init);
+module_exit(xinmo_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c
index e4cddec..1a660bd 100644
--- a/drivers/hid/hid-zydacron.c
+++ b/drivers/hid/hid-zydacron.c
@@ -169,7 +169,7 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	int ret;
 	struct zc_device *zc;
 
-	zc = kzalloc(sizeof(*zc), GFP_KERNEL);
+	zc = devm_kzalloc(&hdev->dev, sizeof(*zc), GFP_KERNEL);
 	if (zc == NULL) {
 		hid_err(hdev, "can't alloc descriptor\n");
 		return -ENOMEM;
@@ -180,28 +180,16 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
 		hid_err(hdev, "hw start failed\n");
-		goto err_free;
+		return ret;
 	}
 
 	return 0;
-err_free:
-	kfree(zc);
-
-	return ret;
-}
-
-static void zc_remove(struct hid_device *hdev)
-{
-	struct zc_device *zc = hid_get_drvdata(hdev);
-
-	hid_hw_stop(hdev);
-	kfree(zc);
 }
 
 static const struct hid_device_id zc_devices[] = {
@@ -217,7 +205,6 @@ static struct hid_driver zc_driver = {
 	.input_mapping = zc_input_mapping,
 	.raw_event = zc_raw_event,
 	.probe = zc_probe,
-	.remove = zc_remove,
 };
 module_hid_driver(zc_driver);
 
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 879b0ed..05d4f96 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -35,6 +35,7 @@
 #include <linux/hid.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
+#include <linux/of.h>
 
 #include <linux/i2c/i2c-hid.h>
 
@@ -756,29 +757,6 @@ static int i2c_hid_power(struct hid_device *hid, int lvl)
 	return ret;
 }
 
-static int i2c_hid_hidinput_input_event(struct input_dev *dev,
-		unsigned int type, unsigned int code, int value)
-{
-	struct hid_device *hid = input_get_drvdata(dev);
-	struct hid_field *field;
-	int offset;
-
-	if (type == EV_FF)
-		return input_ff_event(dev, type, code, value);
-
-	if (type != EV_LED)
-		return -1;
-
-	offset = hidinput_find_field(hid, type, code, &field);
-
-	if (offset == -1) {
-		hid_warn(dev, "event field not found\n");
-		return -1;
-	}
-
-	return hid_set_field(field, offset, value);
-}
-
 static struct hid_ll_driver i2c_hid_ll_driver = {
 	.parse = i2c_hid_parse,
 	.start = i2c_hid_start,
@@ -787,7 +765,6 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
 	.close = i2c_hid_close,
 	.power = i2c_hid_power,
 	.request = i2c_hid_request,
-	.hidinput_input_event = i2c_hid_hidinput_input_event,
 };
 
 static int i2c_hid_init_irq(struct i2c_client *client)
@@ -824,8 +801,8 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
 	 * bytes 2-3 -> bcdVersion (has to be 1.00) */
 	ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
 
-	i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n",
-			__func__, 4, ihid->hdesc_buffer);
+	i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %4ph\n", __func__,
+			ihid->hdesc_buffer);
 
 	if (ret) {
 		dev_err(&client->dev,
@@ -933,6 +910,42 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
 }
 #endif
 
+#ifdef CONFIG_OF
+static int i2c_hid_of_probe(struct i2c_client *client,
+		struct i2c_hid_platform_data *pdata)
+{
+	struct device *dev = &client->dev;
+	u32 val;
+	int ret;
+
+	ret = of_property_read_u32(dev->of_node, "hid-descr-addr", &val);
+	if (ret) {
+		dev_err(&client->dev, "HID register address not provided\n");
+		return -ENODEV;
+	}
+	if (val >> 16) {
+		dev_err(&client->dev, "Bad HID register address: 0x%08x\n",
+			val);
+		return -EINVAL;
+	}
+	pdata->hid_descriptor_address = val;
+
+	return 0;
+}
+
+static const struct of_device_id i2c_hid_of_match[] = {
+	{ .compatible = "hid-over-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, i2c_hid_of_match);
+#else
+static inline int i2c_hid_of_probe(struct i2c_client *client,
+		struct i2c_hid_platform_data *pdata)
+{
+	return -ENODEV;
+}
+#endif
+
 static int i2c_hid_probe(struct i2c_client *client,
 			 const struct i2c_device_id *dev_id)
 {
@@ -954,7 +967,11 @@ static int i2c_hid_probe(struct i2c_client *client,
 	if (!ihid)
 		return -ENOMEM;
 
-	if (!platform_data) {
+	if (client->dev.of_node) {
+		ret = i2c_hid_of_probe(client, &ihid->pdata);
+		if (ret)
+			goto err;
+	} else if (!platform_data) {
 		ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
 		if (ret) {
 			dev_err(&client->dev,
@@ -1095,6 +1112,7 @@ static struct i2c_driver i2c_hid_driver = {
 		.owner	= THIS_MODULE,
 		.pm	= &i2c_hid_pm,
 		.acpi_match_table = ACPI_PTR(i2c_hid_acpi_match),
+		.of_match_table = of_match_ptr(i2c_hid_of_match),
 	},
 
 	.probe		= i2c_hid_probe,
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index fc307e0..f53f2d5 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -116,30 +116,6 @@ static void uhid_hid_close(struct hid_device *hid)
 	uhid_queue_event(uhid, UHID_CLOSE);
 }
 
-static int uhid_hid_input(struct input_dev *input, unsigned int type,
-			  unsigned int code, int value)
-{
-	struct hid_device *hid = input_get_drvdata(input);
-	struct uhid_device *uhid = hid->driver_data;
-	unsigned long flags;
-	struct uhid_event *ev;
-
-	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-	if (!ev)
-		return -ENOMEM;
-
-	ev->type = UHID_OUTPUT_EV;
-	ev->u.output_ev.type = type;
-	ev->u.output_ev.code = code;
-	ev->u.output_ev.value = value;
-
-	spin_lock_irqsave(&uhid->qlock, flags);
-	uhid_queue(uhid, ev);
-	spin_unlock_irqrestore(&uhid->qlock, flags);
-
-	return 0;
-}
-
 static int uhid_hid_parse(struct hid_device *hid)
 {
 	struct uhid_device *uhid = hid->driver_data;
@@ -273,7 +249,6 @@ static struct hid_ll_driver uhid_hid_driver = {
 	.stop = uhid_hid_stop,
 	.open = uhid_hid_open,
 	.close = uhid_hid_close,
-	.hidinput_input_event = uhid_hid_input,
 	.parse = uhid_hid_parse,
 };
 
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 9941828..bd38cdf 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -535,7 +535,6 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
 {
 	int head;
 	struct usbhid_device *usbhid = hid->driver_data;
-	int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 
 	if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
 		return;
@@ -546,7 +545,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
 			return;
 		}
 
-		usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
+		usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
 		if (!usbhid->out[usbhid->outhead].raw_report) {
 			hid_warn(hid, "output queueing failed\n");
 			return;
@@ -595,7 +594,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
 	}
 
 	if (dir == USB_DIR_OUT) {
-		usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
+		usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
 		if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
 			hid_warn(hid, "control queueing failed\n");
 			return;
@@ -649,62 +648,6 @@ static void usbhid_submit_report(struct hid_device *hid, struct hid_report *repo
 	spin_unlock_irqrestore(&usbhid->lock, flags);
 }
 
-/* Workqueue routine to send requests to change LEDs */
-static void hid_led(struct work_struct *work)
-{
-	struct usbhid_device *usbhid =
-		container_of(work, struct usbhid_device, led_work);
-	struct hid_device *hid = usbhid->hid;
-	struct hid_field *field;
-	unsigned long flags;
-
-	field = hidinput_get_led_field(hid);
-	if (!field) {
-		hid_warn(hid, "LED event field not found\n");
-		return;
-	}
-
-	spin_lock_irqsave(&usbhid->lock, flags);
-	if (!test_bit(HID_DISCONNECTED, &usbhid->iofl)) {
-		usbhid->ledcount = hidinput_count_leds(hid);
-		hid_dbg(usbhid->hid, "New ledcount = %u\n", usbhid->ledcount);
-		__usbhid_submit_report(hid, field->report, USB_DIR_OUT);
-	}
-	spin_unlock_irqrestore(&usbhid->lock, flags);
-}
-
-static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	struct hid_device *hid = input_get_drvdata(dev);
-	struct usbhid_device *usbhid = hid->driver_data;
-	struct hid_field *field;
-	unsigned long flags;
-	int offset;
-
-	if (type == EV_FF)
-		return input_ff_event(dev, type, code, value);
-
-	if (type != EV_LED)
-		return -1;
-
-	if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
-		hid_warn(dev, "event field not found\n");
-		return -1;
-	}
-
-	spin_lock_irqsave(&usbhid->lock, flags);
-	hid_set_field(field, offset, value);
-	spin_unlock_irqrestore(&usbhid->lock, flags);
-
-	/*
-	 * Defer performing requested LED action.
-	 * This is more likely gather all LED changes into a single URB.
-	 */
-	schedule_work(&usbhid->led_work);
-
-	return 0;
-}
-
 static int usbhid_wait_io(struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
@@ -857,7 +800,7 @@ static int hid_find_field_early(struct hid_device *hid, unsigned int page,
 	return -1;
 }
 
-void usbhid_set_leds(struct hid_device *hid)
+static void usbhid_set_leds(struct hid_device *hid)
 {
 	struct hid_field *field;
 	int offset;
@@ -867,7 +810,6 @@ void usbhid_set_leds(struct hid_device *hid)
 		usbhid_submit_report(hid, field->report, USB_DIR_OUT);
 	}
 }
-EXPORT_SYMBOL_GPL(usbhid_set_leds);
 
 /*
  * Traverse the supplied list of reports and find the longest
@@ -1274,7 +1216,6 @@ static struct hid_ll_driver usb_hid_driver = {
 	.open = usbhid_open,
 	.close = usbhid_close,
 	.power = usbhid_power,
-	.hidinput_input_event = usb_hidinput_input_event,
 	.request = usbhid_request,
 	.wait = usbhid_wait_io,
 	.idle = usbhid_idle,
@@ -1368,8 +1309,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
 	spin_lock_init(&usbhid->lock);
 
-	INIT_WORK(&usbhid->led_work, hid_led);
-
 	ret = hid_add_device(hid);
 	if (ret) {
 		if (ret != -ENODEV)
@@ -1402,7 +1341,6 @@ static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid)
 {
 	del_timer_sync(&usbhid->io_retry);
 	cancel_work_sync(&usbhid->reset_work);
-	cancel_work_sync(&usbhid->led_work);
 }
 
 static void hid_cease_io(struct usbhid_device *usbhid)
@@ -1522,15 +1460,17 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 	struct usbhid_device *usbhid = hid->driver_data;
 	int status = 0;
 	bool driver_suspended = false;
+	unsigned int ledcount;
 
 	if (PMSG_IS_AUTO(message)) {
+		ledcount = hidinput_count_leds(hid);
 		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
 		if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
 		    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
 		    && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)
 		    && !test_bit(HID_CTRL_RUNNING, &usbhid->iofl)
 		    && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl)
-		    && (!usbhid->ledcount || ignoreled))
+		    && (!ledcount || ignoreled))
 		{
 			set_bit(HID_SUSPENDED, &usbhid->iofl);
 			spin_unlock_irq(&usbhid->lock);
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index dbb6af6..f633c24 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -92,9 +92,6 @@ struct usbhid_device {
 	unsigned int retry_delay;                                       /* Delay length in ms */
 	struct work_struct reset_work;                                  /* Task context for resets */
 	wait_queue_head_t wait;						/* For sleeping */
-	int ledcount;							/* counting the number of active leds */
-
-	struct work_struct led_work;					/* Task context for setting LEDs */
 };
 
 #define	hid_to_usb_dev(hid_dev) \
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 0df7590..12ec8c8 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry {
  * @negop is of type &struct icmsg_negotiate.
  * Set up and fill in default negotiate response message.
  *
- * The max_fw_version specifies the maximum framework version that
- * we can support and max _srv_version specifies the maximum service
- * version we can support. A special value MAX_SRV_VER can be
- * specified to indicate that we can handle the maximum version
- * exposed by the host.
+ * The fw_version specifies the  framework version that
+ * we can support and srv_version specifies the service
+ * version we can support.
  *
  * Mainly used by Hyper-V drivers.
  */
-void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
 				struct icmsg_negotiate *negop, u8 *buf,
-				int max_fw_version, int max_srv_version)
+				int fw_version, int srv_version)
 {
-	int icframe_vercnt;
-	int icmsg_vercnt;
+	int icframe_major, icframe_minor;
+	int icmsg_major, icmsg_minor;
+	int fw_major, fw_minor;
+	int srv_major, srv_minor;
 	int i;
+	bool found_match = false;
 
 	icmsghdrp->icmsgsize = 0x10;
+	fw_major = (fw_version >> 16);
+	fw_minor = (fw_version & 0xFFFF);
+
+	srv_major = (srv_version >> 16);
+	srv_minor = (srv_version & 0xFFFF);
 
 	negop = (struct icmsg_negotiate *)&buf[
 		sizeof(struct vmbuspipe_hdr) +
 		sizeof(struct icmsg_hdr)];
 
-	icframe_vercnt = negop->icframe_vercnt;
-	icmsg_vercnt = negop->icmsg_vercnt;
+	icframe_major = negop->icframe_vercnt;
+	icframe_minor = 0;
+
+	icmsg_major = negop->icmsg_vercnt;
+	icmsg_minor = 0;
 
 	/*
 	 * Select the framework version number we will
@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
 	 */
 
 	for (i = 0; i < negop->icframe_vercnt; i++) {
-		if (negop->icversion_data[i].major <= max_fw_version)
-			icframe_vercnt = negop->icversion_data[i].major;
+		if ((negop->icversion_data[i].major == fw_major) &&
+		   (negop->icversion_data[i].minor == fw_minor)) {
+			icframe_major = negop->icversion_data[i].major;
+			icframe_minor = negop->icversion_data[i].minor;
+			found_match = true;
+		}
 	}
 
+	if (!found_match)
+		goto fw_error;
+
+	found_match = false;
+
 	for (i = negop->icframe_vercnt;
 		 (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
-		if (negop->icversion_data[i].major <= max_srv_version)
-			icmsg_vercnt = negop->icversion_data[i].major;
+		if ((negop->icversion_data[i].major == srv_major) &&
+		   (negop->icversion_data[i].minor == srv_minor)) {
+			icmsg_major = negop->icversion_data[i].major;
+			icmsg_minor = negop->icversion_data[i].minor;
+			found_match = true;
+		}
 	}
 
 	/*
-	 * Respond with the maximum framework and service
+	 * Respond with the framework and service
 	 * version numbers we can support.
 	 */
-	negop->icframe_vercnt = 1;
-	negop->icmsg_vercnt = 1;
-	negop->icversion_data[0].major = icframe_vercnt;
-	negop->icversion_data[0].minor = 0;
-	negop->icversion_data[1].major = icmsg_vercnt;
-	negop->icversion_data[1].minor = 0;
+
+fw_error:
+	if (!found_match) {
+		negop->icframe_vercnt = 0;
+		negop->icmsg_vercnt = 0;
+	} else {
+		negop->icframe_vercnt = 1;
+		negop->icmsg_vercnt = 1;
+	}
+
+	negop->icversion_data[0].major = icframe_major;
+	negop->icversion_data[0].minor = icframe_minor;
+	negop->icversion_data[1].major = icmsg_major;
+	negop->icversion_data[1].minor = icmsg_minor;
+	return found_match;
 }
 
 EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index deb5c25..7e17a54 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -825,7 +825,6 @@ static void hot_add_req(struct work_struct *dummy)
 	memset(&resp, 0, sizeof(struct dm_hot_add_response));
 	resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE;
 	resp.hdr.size = sizeof(struct dm_hot_add_response);
-	resp.hdr.trans_id = atomic_inc_return(&trans_id);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 	pg_start = dm->ha_wrk.ha_page_range.finfo.start_page;
@@ -887,6 +886,7 @@ static void hot_add_req(struct work_struct *dummy)
 		pr_info("Memory hot add failed\n");
 
 	dm->state = DM_INITIALIZED;
+	resp.hdr.trans_id = atomic_inc_return(&trans_id);
 	vmbus_sendpacket(dm->dev->channel, &resp,
 			sizeof(struct dm_hot_add_response),
 			(unsigned long)NULL,
@@ -1081,7 +1081,6 @@ static void balloon_up(struct work_struct *dummy)
 		bl_resp = (struct dm_balloon_response *)send_buffer;
 		memset(send_buffer, 0, PAGE_SIZE);
 		bl_resp->hdr.type = DM_BALLOON_RESPONSE;
-		bl_resp->hdr.trans_id = atomic_inc_return(&trans_id);
 		bl_resp->hdr.size = sizeof(struct dm_balloon_response);
 		bl_resp->more_pages = 1;
 
@@ -1109,6 +1108,7 @@ static void balloon_up(struct work_struct *dummy)
 		 */
 
 		do {
+			bl_resp->hdr.trans_id = atomic_inc_return(&trans_id);
 			ret = vmbus_sendpacket(dm_device.dev->channel,
 						bl_resp,
 						bl_resp->hdr.size,
@@ -1526,5 +1526,4 @@ static int __init init_balloon_drv(void)
 module_init(init_balloon_drv);
 
 MODULE_DESCRIPTION("Hyper-V Balloon");
-MODULE_VERSION(HV_DRV_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index ed50e9e..28b0332 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -29,6 +29,16 @@
 #include <linux/hyperv.h>
 
 
+/*
+ * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7)
+ */
+#define WIN7_SRV_MAJOR   3
+#define WIN7_SRV_MINOR   0
+#define WIN7_SRV_MAJOR_MINOR     (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
+
+#define WIN8_SRV_MAJOR   4
+#define WIN8_SRV_MINOR   0
+#define WIN8_SRV_MAJOR_MINOR     (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
 
 /*
  * Global state maintained for transaction that is being processed.
@@ -76,7 +86,9 @@ static u8 *recv_buffer;
 /*
  * Register the kernel component with the user-level daemon.
  * As part of this registration, pass the LIC version number.
+ * This number has no meaning, it satisfies the registration protocol.
  */
+#define HV_DRV_VERSION           "3.1"
 
 static void
 kvp_register(int reg_value)
@@ -593,8 +605,19 @@ void hv_kvp_onchannelcallback(void *context)
 			sizeof(struct vmbuspipe_hdr)];
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			/*
+			 * We start with win8 version and if the host cannot
+			 * support that we use the previous version.
+			 */
+			if (vmbus_prep_negotiate_resp(icmsghdrp, negop,
+				 recv_buffer, UTIL_FW_MAJOR_MINOR,
+				 WIN8_SRV_MAJOR_MINOR))
+				goto done;
+
 			vmbus_prep_negotiate_resp(icmsghdrp, negop,
-				 recv_buffer, MAX_SRV_VER, MAX_SRV_VER);
+				 recv_buffer, UTIL_FW_MAJOR_MINOR,
+				 WIN7_SRV_MAJOR_MINOR);
+
 		} else {
 			kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
 				sizeof(struct vmbuspipe_hdr) +
@@ -626,6 +649,7 @@ void hv_kvp_onchannelcallback(void *context)
 			return;
 
 		}
+done:
 
 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
 			| ICMSGHDRFLAG_RESPONSE;
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 8ad5653..e4572f3 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -24,6 +24,10 @@
 #include <linux/workqueue.h>
 #include <linux/hyperv.h>
 
+#define VSS_MAJOR  5
+#define VSS_MINOR  0
+#define VSS_MAJOR_MINOR    (VSS_MAJOR << 16 | VSS_MINOR)
+
 
 
 /*
@@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context)
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
 			vmbus_prep_negotiate_resp(icmsghdrp, negop,
-				 recv_buffer, MAX_SRV_VER, MAX_SRV_VER);
-			/*
-			 * We currently negotiate the highest number the
-			 * host has presented. If this version is not
-			 * atleast 5.0, reject.
-			 */
-			negop = (struct icmsg_negotiate *)&recv_buffer[
-				sizeof(struct vmbuspipe_hdr) +
-				sizeof(struct icmsg_hdr)];
-
-			if (negop->icversion_data[1].major < 5)
-				negop->icframe_vercnt = 0;
+				 recv_buffer, UTIL_FW_MAJOR_MINOR,
+				 VSS_MAJOR_MINOR);
 		} else {
 			vss_msg = (struct hv_vss_msg *)&recv_buffer[
 				sizeof(struct vmbuspipe_hdr) +
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 2f561c5..cb82233 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -28,6 +28,18 @@
 #include <linux/reboot.h>
 #include <linux/hyperv.h>
 
+#define SHUTDOWN_MAJOR	3
+#define SHUTDOWN_MINOR  0
+#define SHUTDOWN_MAJOR_MINOR	(SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR)
+
+#define TIMESYNCH_MAJOR	3
+#define TIMESYNCH_MINOR 0
+#define TIMESYNCH_MAJOR_MINOR	(TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR)
+
+#define HEARTBEAT_MAJOR	3
+#define HEARTBEAT_MINOR 0
+#define HEARTBEAT_MAJOR_MINOR	(HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR)
+
 static void shutdown_onchannelcallback(void *context);
 static struct hv_util_service util_shutdown = {
 	.util_cb = shutdown_onchannelcallback,
@@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context)
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
 			vmbus_prep_negotiate_resp(icmsghdrp, negop,
-					shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER);
+					shut_txf_buf, UTIL_FW_MAJOR_MINOR,
+					SHUTDOWN_MAJOR_MINOR);
 		} else {
 			shutdown_msg =
 				(struct shutdown_msg_data *)&shut_txf_buf[
@@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context)
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
 			vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
-						MAX_SRV_VER, MAX_SRV_VER);
+						UTIL_FW_MAJOR_MINOR,
+						TIMESYNCH_MAJOR_MINOR);
 		} else {
 			timedatap = (struct ictimesync_data *)&time_txf_buf[
 				sizeof(struct vmbuspipe_hdr) +
@@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context)
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
 			vmbus_prep_negotiate_resp(icmsghdrp, NULL,
-				hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER);
+				hbeat_txf_buf, UTIL_FW_MAJOR_MINOR,
+				HEARTBEAT_MAJOR_MINOR);
 		} else {
 			heartbeat_msg =
 				(struct heartbeat_msg_data *)&hbeat_txf_buf[
@@ -380,5 +395,4 @@ module_init(init_hyperv_utils);
 module_exit(exit_hyperv_utils);
 
 MODULE_DESCRIPTION("Hyper-V Utilities");
-MODULE_VERSION(HV_DRV_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index e8e071f..f9fe46f 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -816,7 +816,6 @@ static void __exit vmbus_exit(void)
 
 
 MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
 
 subsys_initcall(hv_acpi_init);
 module_exit(vmbus_exit);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e989f7f..47b3e58 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1202,8 +1202,8 @@ config SENSORS_ADS1015
 	tristate "Texas Instruments ADS1015"
 	depends on I2C
 	help
-	  If you say yes here you get support for Texas Instruments ADS1015
-	  12-bit 4-input ADC device.
+	  If you say yes here you get support for Texas Instruments
+	  ADS1015/ADS1115 12/16-bit 4-input ADC device.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called ads1015.
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 6351aba..d7d9b2f 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -970,7 +970,7 @@ static int __init enable_cap_knobs(const struct dmi_system_id *d)
 	return 0;
 }
 
-static struct dmi_system_id __initdata pm_dmi_table[] = {
+static struct dmi_system_id pm_dmi_table[] __initdata = {
 	{
 		enable_cap_knobs, "IBM Active Energy Manager",
 		{
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
index 2798246..7f9dc2f 100644
--- a/drivers/hwmon/ads1015.c
+++ b/drivers/hwmon/ads1015.c
@@ -46,17 +46,28 @@ static const unsigned int fullscale_table[8] = {
 	6144, 4096, 2048, 1024, 512, 256, 256, 256 };
 
 /* Data rates in samples per second */
-static const unsigned int data_rate_table[8] = {
-	128, 250, 490, 920, 1600, 2400, 3300, 3300 };
+static const unsigned int data_rate_table_1015[8] = {
+	128, 250, 490, 920, 1600, 2400, 3300, 3300
+};
+
+static const unsigned int data_rate_table_1115[8] = {
+	8, 16, 32, 64, 128, 250, 475, 860
+};
 
 #define ADS1015_DEFAULT_CHANNELS 0xff
 #define ADS1015_DEFAULT_PGA 2
 #define ADS1015_DEFAULT_DATA_RATE 4
 
+enum ads1015_chips {
+	ads1015,
+	ads1115,
+};
+
 struct ads1015_data {
 	struct device *hwmon_dev;
 	struct mutex update_lock; /* mutex protect updates */
 	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+	enum ads1015_chips id;
 };
 
 static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
@@ -66,6 +77,8 @@ static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
 	unsigned int pga = data->channel_data[channel].pga;
 	unsigned int data_rate = data->channel_data[channel].data_rate;
 	unsigned int conversion_time_ms;
+	const unsigned int * const rate_table = data->id == ads1115 ?
+		data_rate_table_1115 : data_rate_table_1015;
 	int res;
 
 	mutex_lock(&data->update_lock);
@@ -75,7 +88,7 @@ static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
 	if (res < 0)
 		goto err_unlock;
 	config = res;
-	conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
+	conversion_time_ms = DIV_ROUND_UP(1000, rate_table[data_rate]);
 
 	/* setup and start single conversion */
 	config &= 0x001f;
@@ -113,8 +126,9 @@ static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel,
 	struct ads1015_data *data = i2c_get_clientdata(client);
 	unsigned int pga = data->channel_data[channel].pga;
 	int fullscale = fullscale_table[pga];
+	const unsigned mask = data->id == ads1115 ? 0x7fff : 0x7ff0;
 
-	return DIV_ROUND_CLOSEST(reg * fullscale, 0x7ff0);
+	return DIV_ROUND_CLOSEST(reg * fullscale, mask);
 }
 
 /* sysfs callback function */
@@ -257,7 +271,7 @@ static int ads1015_probe(struct i2c_client *client,
 			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
-
+	data->id = id->driver_data;
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
@@ -286,7 +300,8 @@ exit_remove:
 }
 
 static const struct i2c_device_id ads1015_id[] = {
-	{ "ads1015", 0 },
+	{ "ads1015",  ads1015},
+	{ "ads1115",  ads1115},
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ads1015_id);
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index ba962ac..7092c78 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -145,7 +145,7 @@ static int ads7828_remove(struct i2c_client *client)
 static int ads7828_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	struct ads7828_platform_data *pdata = client->dev.platform_data;
+	struct ads7828_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct ads7828_data *data;
 	int err;
 
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 0f34bca..6099f50 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -215,7 +215,7 @@ static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg,
 					  u16 value)
 {
 	return i2c_smbus_write_byte_data(client, reg, value & 0xFF)
-	       && i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
+	       || i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
 }
 
 static void adt7470_init_client(struct i2c_client *client)
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 2e5e2dc..78be661 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -316,6 +316,18 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
 	return tjmax;
 }
 
+static bool cpu_has_tjmax(struct cpuinfo_x86 *c)
+{
+	u8 model = c->x86_model;
+
+	return model > 0xe &&
+	       model != 0x1c &&
+	       model != 0x26 &&
+	       model != 0x27 &&
+	       model != 0x35 &&
+	       model != 0x36;
+}
+
 static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
 {
 	int err;
@@ -328,7 +340,7 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
 	 */
 	err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
 	if (err) {
-		if (c->x86_model > 0xe && c->x86_model != 0x1c)
+		if (cpu_has_tjmax(c))
 			dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
 	} else {
 		val = (eax >> 16) & 0xff;
diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c
index f1d6b42..0918b91 100644
--- a/drivers/hwmon/ds620.c
+++ b/drivers/hwmon/ds620.c
@@ -77,7 +77,7 @@ struct ds620_data {
 
 static void ds620_init_client(struct i2c_client *client)
 {
-	struct ds620_platform_data *ds620_info = client->dev.platform_data;
+	struct ds620_platform_data *ds620_info = dev_get_platdata(&client->dev);
 	u16 conf, new_conf;
 
 	new_conf = conf =
diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c
index 936898f..82e661e 100644
--- a/drivers/hwmon/emc6w201.c
+++ b/drivers/hwmon/emc6w201.c
@@ -49,7 +49,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
 #define EMC6W201_REG_TEMP_HIGH(nr)	(0x57 + (nr) * 2)
 #define EMC6W201_REG_FAN_MIN(nr)	(0x62 + (nr) * 2)
 
-enum { input, min, max } subfeature;
+enum subfeature { input, min, max };
 
 /*
  * Per-device data
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 0c9f3da..15b7f52 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1375,7 +1375,7 @@ static void f71805f_init_device(struct f71805f_data *data)
 
 static int f71805f_probe(struct platform_device *pdev)
 {
-	struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
+	struct f71805f_sio_data *sio_data = dev_get_platdata(&pdev->dev);
 	struct f71805f_data *data;
 	struct resource *res;
 	int i, err;
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index cfb02dd..31b221e 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -2267,7 +2267,7 @@ static int f71882fg_create_fan_sysfs_files(
 static int f71882fg_probe(struct platform_device *pdev)
 {
 	struct f71882fg_data *data;
-	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
+	struct f71882fg_sio_data *sio_data = dev_get_platdata(&pdev->dev);
 	int nr_fans = f71882fg_nr_fans[sio_data->type];
 	int nr_temps = f71882fg_nr_temps[sio_data->type];
 	int err, i;
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 9e300e5..a837b94 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -832,7 +832,8 @@ static int f75375_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct f75375_data *data;
-	struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
+	struct f75375s_platform_data *f75375s_pdata =
+			dev_get_platdata(&client->dev);
 	int err;
 
 	if (!i2c_check_functionality(client->adapter,
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 73adf01..b4b8b5b 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -717,7 +717,7 @@ static void g762_of_clock_disable(struct i2c_client *client) { }
 
 static int g762_pdata_prop_import(struct i2c_client *client)
 {
-	struct g762_platform_data *pdata = client->dev.platform_data;
+	struct g762_platform_data *pdata = dev_get_platdata(&client->dev);
 	int ret;
 
 	if (!pdata)
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 3104149..b7d6a57 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -495,7 +495,7 @@ static int gpio_fan_probe(struct platform_device *pdev)
 {
 	int err;
 	struct gpio_fan_data *fan_data;
-	struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_fan_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 #ifdef CONFIG_OF_GPIO
 	if (!pdata) {
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index d917a2d..18c0623 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -232,9 +232,9 @@ static int ina2xx_probe(struct i2c_client *client,
 	if (!data)
 		return -ENOMEM;
 
-	if (client->dev.platform_data) {
+	if (dev_get_platdata(&client->dev)) {
 		pdata =
-		  (struct ina2xx_platform_data *)client->dev.platform_data;
+		  (struct ina2xx_platform_data *)dev_get_platdata(&client->dev);
 		shunt = pdata->shunt_uohms;
 	} else if (!of_property_read_u32(client->dev.of_node,
 				"shunt-resistor", &val)) {
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 72b21d5..29ffa27 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1962,7 +1962,7 @@ exit:
 static void it87_remove_files(struct device *dev)
 {
 	struct it87_data *data = platform_get_drvdata(pdev);
-	struct it87_sio_data *sio_data = dev->platform_data;
+	struct it87_sio_data *sio_data = dev_get_platdata(dev);
 	int i;
 
 	sysfs_remove_group(&dev->kobj, &it87_group);
@@ -2014,7 +2014,7 @@ static int it87_probe(struct platform_device *pdev)
 	struct it87_data *data;
 	struct resource *res;
 	struct device *dev = &pdev->dev;
-	struct it87_sio_data *sio_data = dev->platform_data;
+	struct it87_sio_data *sio_data = dev_get_platdata(dev);
 	int err = 0, i;
 	int enable_pwm_interface;
 	int fan_beep_need_rw;
@@ -2316,7 +2316,7 @@ static int it87_check_pwm(struct device *dev)
 /* Called when we have found a new IT87. */
 static void it87_init_device(struct platform_device *pdev)
 {
-	struct it87_sio_data *sio_data = pdev->dev.platform_data;
+	struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev);
 	struct it87_data *data = platform_get_drvdata(pdev);
 	int tmp, i;
 	u8 mask;
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 16e45d7..333092c 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -855,8 +855,8 @@ static void lm87_init_client(struct i2c_client *client)
 {
 	struct lm87_data *data = i2c_get_clientdata(client);
 
-	if (client->dev.platform_data) {
-		data->channel = *(u8 *)client->dev.platform_data;
+	if (dev_get_platdata(&client->dev)) {
+		data->channel = *(u8 *)dev_get_platdata(&client->dev);
 		lm87_write_value(client,
 				 LM87_REG_CHANNEL_MODE, data->channel);
 	} else {
diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
index b5ebb91..96dccaf 100644
--- a/drivers/hwmon/max197.c
+++ b/drivers/hwmon/max197.c
@@ -261,7 +261,7 @@ static int max197_probe(struct platform_device *pdev)
 {
 	int ch, ret;
 	struct max197_data *data;
-	struct max197_platform_data *pdata = pdev->dev.platform_data;
+	struct max197_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	enum max197_chips chip = platform_get_device_id(pdev)->driver_data;
 
 	if (pdata == NULL) {
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index 3e7b426..066e587 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -428,7 +428,7 @@ static int max6639_init_client(struct i2c_client *client)
 {
 	struct max6639_data *data = i2c_get_clientdata(client);
 	struct max6639_platform_data *max6639_info =
-		client->dev.platform_data;
+		dev_get_platdata(&client->dev);
 	int i;
 	int rpm_range = 1; /* default: 4000 RPM */
 	int err;
diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
index eedb322..d219c06 100644
--- a/drivers/hwmon/mcp3021.c
+++ b/drivers/hwmon/mcp3021.c
@@ -143,12 +143,13 @@ static int mcp3021_probe(struct i2c_client *client,
 		break;
 	}
 
-	if (client->dev.platform_data) {
-		data->vdd = *(u32 *)client->dev.platform_data;
+	if (dev_get_platdata(&client->dev)) {
+		data->vdd = *(u32 *)dev_get_platdata(&client->dev);
 		if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
 			return -EINVAL;
-	} else
+	} else {
 		data->vdd = MCP3021_VDD_REF;
+	}
 
 	err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr);
 	if (err)
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 99cec18..6eb03ce 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -33,9 +33,11 @@
  * Supports the following chips:
  *
  * Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
+ * nct6106d     9      3       3       6+3    0xc450 0xc1    0x5ca3
  * nct6775f     9      4       3       6+3    0xb470 0xc1    0x5ca3
  * nct6776f     9      5       3       6+3    0xc330 0xc1    0x5ca3
  * nct6779d    15      5       5       2+6    0xc560 0xc1    0x5ca3
+ * nct6791d    15      6       6       2+6    0xc800 0xc1    0x5ca3
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -59,13 +61,15 @@
 
 #define USE_ALTERNATE
 
-enum kinds { nct6775, nct6776, nct6779 };
+enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791 };
 
 /* used to set data->name = nct6775_device_names[data->sio_kind] */
 static const char * const nct6775_device_names[] = {
+	"nct6106",
 	"nct6775",
 	"nct6776",
 	"nct6779",
+	"nct6791",
 };
 
 static unsigned short force_id;
@@ -91,9 +95,11 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_REG_ENABLE		0x30	/* Logical device enable */
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 
+#define SIO_NCT6106_ID		0xc450
 #define SIO_NCT6775_ID		0xb470
 #define SIO_NCT6776_ID		0xc330
 #define SIO_NCT6779_ID		0xc560
+#define SIO_NCT6791_ID		0xc800
 #define SIO_ID_MASK		0xFFF0
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -167,7 +173,10 @@ superio_exit(int ioreg)
 #define NUM_TEMP	10	/* Max number of temp attribute sets w/ limits*/
 #define NUM_TEMP_FIXED	6	/* Max number of fixed temp attribute sets */
 
-#define NUM_REG_ALARM	4	/* Max number of alarm registers */
+#define NUM_REG_ALARM	7	/* Max number of alarm registers */
+#define NUM_REG_BEEP	5	/* Max number of beep registers */
+
+#define NUM_FAN		6
 
 /* Common and NCT6775 specific data */
 
@@ -185,6 +194,7 @@ static const u16 NCT6775_REG_IN[] = {
 
 #define NCT6775_REG_VBAT		0x5D
 #define NCT6775_REG_DIODE		0x5E
+#define NCT6775_DIODE_MASK		0x02
 
 #define NCT6775_REG_FANDIV1		0x506
 #define NCT6775_REG_FANDIV2		0x507
@@ -193,7 +203,7 @@ static const u16 NCT6775_REG_IN[] = {
 
 static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
 
-/* 0..15 voltages, 16..23 fans, 24..31 temperatures */
+/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
 
 static const s8 NCT6775_ALARM_BITS[] = {
 	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
@@ -208,6 +218,23 @@ static const s8 NCT6775_ALARM_BITS[] = {
 #define TEMP_ALARM_BASE		24
 #define INTRUSION_ALARM_BASE	30
 
+static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
+
+/*
+ * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
+ * 30..31 intrusion
+ */
+static const s8 NCT6775_BEEP_BITS[] = {
+	0, 1, 2, 3, 8, 9, 10, 16,	/* in0.. in7 */
+	17, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
+	21,				/* global beep enable */
+	6, 7, 11, 28, -1,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	12, -1 };			/* intrusion0, intrusion1 */
+
+#define BEEP_ENABLE_BASE		15
+
 static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
 static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
 
@@ -217,27 +244,32 @@ static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
 
 /* Advanced Fan control, some values are common for all fans */
 
-static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
-static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
+static const u16 NCT6775_REG_TARGET[] = {
+	0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
+static const u16 NCT6775_REG_FAN_MODE[] = {
+	0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
 static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
-	0x103, 0x203, 0x303, 0x803, 0x903 };
+	0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
 static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
-	0x104, 0x204, 0x304, 0x804, 0x904 };
+	0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
 static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
-	0x105, 0x205, 0x305, 0x805, 0x905 };
-static const u16 NCT6775_REG_FAN_START_OUTPUT[]
-	= { 0x106, 0x206, 0x306, 0x806, 0x906 };
+	0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
+static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
+	0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
 static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
 static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
 
 static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
-	0x107, 0x207, 0x307, 0x807, 0x907 };
-static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
-static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
+	0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
+static const u16 NCT6775_REG_PWM[] = {
+	0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
+static const u16 NCT6775_REG_PWM_READ[] = {
+	0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
 
 static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
 static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
 static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
+static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
 
 static const u16 NCT6775_REG_TEMP[] = {
 	0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
@@ -253,25 +285,25 @@ static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
 	0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
 
 static const u16 NCT6775_REG_TEMP_SEL[] = {
-	0x100, 0x200, 0x300, 0x800, 0x900 };
+	0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
 
 static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
-	0x139, 0x239, 0x339, 0x839, 0x939 };
+	0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
 static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
-	0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
+	0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
 static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
-	0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
+	0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
 static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
-	0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
+	0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
 static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
-	0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
+	0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
 
 static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
 
 static const u16 NCT6775_REG_AUTO_TEMP[] = {
-	0x121, 0x221, 0x321, 0x821, 0x921 };
+	0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
 static const u16 NCT6775_REG_AUTO_PWM[] = {
-	0x127, 0x227, 0x327, 0x827, 0x927 };
+	0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
 
 #define NCT6775_AUTO_TEMP(data, nr, p)	((data)->REG_AUTO_TEMP[nr] + (p))
 #define NCT6775_AUTO_PWM(data, nr, p)	((data)->REG_AUTO_PWM[nr] + (p))
@@ -279,9 +311,9 @@ static const u16 NCT6775_REG_AUTO_PWM[] = {
 static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
 
 static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
-	0x135, 0x235, 0x335, 0x835, 0x935 };
+	0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
 static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
-	0x138, 0x238, 0x338, 0x838, 0x938 };
+	0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
 
 static const char *const nct6775_temp_label[] = {
 	"",
@@ -325,17 +357,28 @@ static const s8 NCT6776_ALARM_BITS[] = {
 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
 	12, 9 };			/* intrusion0, intrusion1 */
 
+static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
+
+static const s8 NCT6776_BEEP_BITS[] = {
+	0, 1, 2, 3, 4, 5, 6, 7,		/* in0.. in7 */
+	8, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
+	24,				/* global beep enable */
+	25, 26, 27, 28, 29,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	16, 17, 18, 19, 20, 21,		/* temp1..temp6 */
+	30, 31 };			/* intrusion0, intrusion1 */
+
 static const u16 NCT6776_REG_TOLERANCE_H[] = {
-	0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
+	0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
 
-static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
-static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
+static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
+static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
 
 static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
 static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
 
 static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
-	0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
+	0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
 
 static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
 	0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
@@ -390,14 +433,25 @@ static const s8 NCT6779_ALARM_BITS[] = {
 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
 	12, 9 };			/* intrusion0, intrusion1 */
 
-static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
+static const s8 NCT6779_BEEP_BITS[] = {
+	0, 1, 2, 3, 4, 5, 6, 7,		/* in0.. in7 */
+	8, 9, 10, 11, 12, 13, 14,	/* in8..in14 */
+	24,				/* global beep enable */
+	25, 26, 27, 28, 29,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	16, 17, -1, -1, -1, -1,		/* temp1..temp6 */
+	30, 31 };			/* intrusion0, intrusion1 */
+
+static const u16 NCT6779_REG_FAN[] = {
+	0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
 static const u16 NCT6779_REG_FAN_PULSES[] = {
-	0x644, 0x645, 0x646, 0x647, 0x648 };
+	0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
 
 static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
-	0x136, 0x236, 0x336, 0x836, 0x936 };
+	0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
+#define NCT6779_CRITICAL_PWM_ENABLE_MASK	0x01
 static const u16 NCT6779_REG_CRITICAL_PWM[] = {
-	0x137, 0x237, 0x337, 0x837, 0x937 };
+	0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
 
 static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
 static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
@@ -449,6 +503,122 @@ static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
 static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
 	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
 
+/* NCT6791 specific data */
+
+#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE	0x28
+
+static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
+	0x459, 0x45A, 0x45B, 0x568, 0x45D };
+
+static const s8 NCT6791_ALARM_BITS[] = {
+	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
+	17, 24, 25, 26, 27, 28, 29,	/* in8..in14 */
+	-1,				/* unused */
+	6, 7, 11, 10, 23, 33,		/* fan1..fan6 */
+	-1, -1,				/* unused */
+	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	12, 9 };			/* intrusion0, intrusion1 */
+
+
+/* NCT6102D/NCT6106D specific data */
+
+#define NCT6106_REG_VBAT	0x318
+#define NCT6106_REG_DIODE	0x319
+#define NCT6106_DIODE_MASK	0x01
+
+static const u16 NCT6106_REG_IN_MAX[] = {
+	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
+static const u16 NCT6106_REG_IN_MIN[] = {
+	0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
+static const u16 NCT6106_REG_IN[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
+
+static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
+static const u16 NCT6106_REG_TEMP_HYST[] = {
+	0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
+static const u16 NCT6106_REG_TEMP_OVER[] = {
+	0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
+static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
+	0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
+static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
+	0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
+static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
+static const u16 NCT6106_REG_TEMP_CONFIG[] = {
+	0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
+
+static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
+static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
+static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
+static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
+
+static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
+static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
+static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
+static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
+static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
+static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
+static const u16 NCT6106_REG_TEMP_SOURCE[] = {
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
+
+static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
+static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
+	0x11b, 0x12b, 0x13b };
+
+static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
+#define NCT6106_CRITICAL_PWM_ENABLE_MASK	0x10
+static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
+
+static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
+static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
+static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
+static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
+static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
+static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
+
+static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
+
+static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
+static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
+static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
+static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
+static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
+static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
+
+static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
+static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
+
+static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
+	0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
+
+static const s8 NCT6106_ALARM_BITS[] = {
+	0, 1, 2, 3, 4, 5, 7, 8,		/* in0.. in7 */
+	9, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
+	-1,				/* unused */
+	32, 33, 34, -1, -1,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	16, 17, 18, 19, 20, 21,		/* temp1..temp6 */
+	48, -1				/* intrusion0, intrusion1 */
+};
+
+static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
+	0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
+
+static const s8 NCT6106_BEEP_BITS[] = {
+	0, 1, 2, 3, 4, 5, 7, 8,		/* in0.. in7 */
+	9, 10, 11, 12, -1, -1, -1,	/* in8..in14 */
+	32,				/* global beep enable */
+	24, 25, 26, 27, 28,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	16, 17, 18, 19, 20, 21,		/* temp1..temp6 */
+	34, -1				/* intrusion0, intrusion1 */
+};
+
+static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
+
+static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
+
 static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
 {
 	if (mode == 0 && pwm == 255)
@@ -550,13 +720,18 @@ static inline u8 in_to_reg(u32 val, u8 nr)
 
 struct nct6775_data {
 	int addr;	/* IO base of hw monitor block */
+	int sioreg;	/* SIO register address */
 	enum kinds kind;
 	const char *name;
 
 	struct device *hwmon_dev;
+	struct attribute_group *group_in;
+	struct attribute_group *group_fan;
+	struct attribute_group *group_temp;
+	struct attribute_group *group_pwm;
 
-	u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
-				    * 3=temp_crit
+	u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
+				    * 3=temp_crit, 4=temp_lcrit
 				    */
 	u8 temp_src[NUM_TEMP];
 	u16 reg_temp_config[NUM_TEMP];
@@ -566,8 +741,10 @@ struct nct6775_data {
 	u16 REG_CONFIG;
 	u16 REG_VBAT;
 	u16 REG_DIODE;
+	u8 DIODE_MASK;
 
 	const s8 *ALARM_BITS;
+	const s8 *BEEP_BITS;
 
 	const u16 *REG_VIN;
 	const u16 *REG_IN_MINMAX[2];
@@ -577,6 +754,7 @@ struct nct6775_data {
 	const u16 *REG_FAN_MODE;
 	const u16 *REG_FAN_MIN;
 	const u16 *REG_FAN_PULSES;
+	const u16 *FAN_PULSE_SHIFT;
 	const u16 *REG_FAN_TIME[3];
 
 	const u16 *REG_TOLERANCE_H;
@@ -590,6 +768,10 @@ struct nct6775_data {
 				 */
 	const u16 *REG_PWM_READ;
 
+	const u16 *REG_CRITICAL_PWM_ENABLE;
+	u8 CRITICAL_PWM_ENABLE_MASK;
+	const u16 *REG_CRITICAL_PWM;
+
 	const u16 *REG_AUTO_TEMP;
 	const u16 *REG_AUTO_PWM;
 
@@ -604,6 +786,7 @@ struct nct6775_data {
 	const u16 *REG_TEMP_OFFSET;
 
 	const u16 *REG_ALARM;
+	const u16 *REG_BEEP;
 
 	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
 	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
@@ -616,26 +799,30 @@ struct nct6775_data {
 	u8 bank;		/* current register bank */
 	u8 in_num;		/* number of in inputs we have */
 	u8 in[15][3];		/* [0]=in, [1]=in_max, [2]=in_min */
-	unsigned int rpm[5];
-	u16 fan_min[5];
-	u8 fan_pulses[5];
-	u8 fan_div[5];
+	unsigned int rpm[NUM_FAN];
+	u16 fan_min[NUM_FAN];
+	u8 fan_pulses[NUM_FAN];
+	u8 fan_div[NUM_FAN];
 	u8 has_pwm;
 	u8 has_fan;		/* some fan inputs can be disabled */
 	u8 has_fan_min;		/* some fans don't have min register */
 	bool has_fan_div;
 
-	u8 num_temp_alarms;	/* 2 or 3 */
+	u8 num_temp_alarms;	/* 2, 3, or 6 */
+	u8 num_temp_beeps;	/* 2, 3, or 6 */
 	u8 temp_fixed_num;	/* 3 or 6 */
 	u8 temp_type[NUM_TEMP_FIXED];
 	s8 temp_offset[NUM_TEMP_FIXED];
-	s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
-				* 3=temp_crit */
+	s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
+				* 3=temp_crit, 4=temp_lcrit */
 	u64 alarms;
+	u64 beeps;
 
 	u8 pwm_num;	/* number of pwm */
-	u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
-	enum pwm_enable pwm_enable[5];
+	u8 pwm_mode[NUM_FAN];	/* 1->DC variable voltage,
+				 * 0->PWM variable duty cycle
+				 */
+	enum pwm_enable pwm_enable[NUM_FAN];
 			/* 0->off
 			 * 1->manual
 			 * 2->thermal cruise mode (also called SmartFan I)
@@ -643,35 +830,37 @@ struct nct6775_data {
 			 * 4->SmartFan III
 			 * 5->enhanced variable thermal cruise (SmartFan IV)
 			 */
-	u8 pwm[7][5];	/* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
-			 * [3]=pwm_max, [4]=pwm_step,
-			 * [5]=weight_duty_step, [6]=weight_duty_base
-			 */
+	u8 pwm[7][NUM_FAN];	/* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
+				 * [3]=pwm_max, [4]=pwm_step,
+				 * [5]=weight_duty_step, [6]=weight_duty_base
+				 */
 
-	u8 target_temp[5];
+	u8 target_temp[NUM_FAN];
 	u8 target_temp_mask;
-	u32 target_speed[5];
-	u32 target_speed_tolerance[5];
+	u32 target_speed[NUM_FAN];
+	u32 target_speed_tolerance[NUM_FAN];
 	u8 speed_tolerance_limit;
 
-	u8 temp_tolerance[2][5];
+	u8 temp_tolerance[2][NUM_FAN];
 	u8 tolerance_mask;
 
-	u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
+	u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
 
 	/* Automatic fan speed control registers */
 	int auto_pwm_num;
-	u8 auto_pwm[5][7];
-	u8 auto_temp[5][7];
-	u8 pwm_temp_sel[5];
-	u8 pwm_weight_temp_sel[5];
-	u8 weight_temp[3][5];	/* 0->temp_step, 1->temp_step_tol,
-				 * 2->temp_base
-				 */
+	u8 auto_pwm[NUM_FAN][7];
+	u8 auto_temp[NUM_FAN][7];
+	u8 pwm_temp_sel[NUM_FAN];
+	u8 pwm_weight_temp_sel[NUM_FAN];
+	u8 weight_temp[3][NUM_FAN];	/* 0->temp_step, 1->temp_step_tol,
+					 * 2->temp_base
+					 */
 
 	u8 vid;
 	u8 vrm;
 
+	bool have_vid;
+
 	u16 have_temp;
 	u16 have_temp_fixed;
 	u16 have_in;
@@ -688,9 +877,145 @@ struct nct6775_sio_data {
 	enum kinds kind;
 };
 
+struct sensor_device_template {
+	struct device_attribute dev_attr;
+	union {
+		struct {
+			u8 nr;
+			u8 index;
+		} s;
+		int index;
+	} u;
+	bool s2;	/* true if both index and nr are used */
+};
+
+struct sensor_device_attr_u {
+	union {
+		struct sensor_device_attribute a1;
+		struct sensor_device_attribute_2 a2;
+	} u;
+	char name[32];
+};
+
+#define __TEMPLATE_ATTR(_template, _mode, _show, _store) {	\
+	.attr = {.name = _template, .mode = _mode },		\
+	.show	= _show,					\
+	.store	= _store,					\
+}
+
+#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index)	\
+	{ .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store),	\
+	  .u.index = _index,						\
+	  .s2 = false }
+
+#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store,	\
+				 _nr, _index)				\
+	{ .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store),	\
+	  .u.s.index = _index,						\
+	  .u.s.nr = _nr,						\
+	  .s2 = true }
+
+#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index)	\
+static struct sensor_device_template sensor_dev_template_##_name	\
+	= SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store,	\
+				 _index)
+
+#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store,	\
+			  _nr, _index)					\
+static struct sensor_device_template sensor_dev_template_##_name	\
+	= SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store,	\
+				 _nr, _index)
+
+struct sensor_template_group {
+	struct sensor_device_template **templates;
+	umode_t (*is_visible)(struct kobject *, struct attribute *, int);
+	int base;
+};
+
+static struct attribute_group *
+nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
+			  int repeat)
+{
+	struct attribute_group *group;
+	struct sensor_device_attr_u *su;
+	struct sensor_device_attribute *a;
+	struct sensor_device_attribute_2 *a2;
+	struct attribute **attrs;
+	struct sensor_device_template **t;
+	int err, i, j, count;
+
+	if (repeat <= 0)
+		return ERR_PTR(-EINVAL);
+
+	t = tg->templates;
+	for (count = 0; *t; t++, count++)
+		;
+
+	if (count == 0)
+		return ERR_PTR(-EINVAL);
+
+	group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
+	if (group == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
+			     GFP_KERNEL);
+	if (attrs == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
+			       GFP_KERNEL);
+	if (su == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	group->attrs = attrs;
+	group->is_visible = tg->is_visible;
+
+	for (i = 0; i < repeat; i++) {
+		t = tg->templates;
+		for (j = 0; *t != NULL; j++) {
+			snprintf(su->name, sizeof(su->name),
+				 (*t)->dev_attr.attr.name, tg->base + i);
+			if ((*t)->s2) {
+				a2 = &su->u.a2;
+				a2->dev_attr.attr.name = su->name;
+				a2->nr = (*t)->u.s.nr + i;
+				a2->index = (*t)->u.s.index;
+				a2->dev_attr.attr.mode =
+				  (*t)->dev_attr.attr.mode;
+				a2->dev_attr.show = (*t)->dev_attr.show;
+				a2->dev_attr.store = (*t)->dev_attr.store;
+				*attrs = &a2->dev_attr.attr;
+			} else {
+				a = &su->u.a1;
+				a->dev_attr.attr.name = su->name;
+				a->index = (*t)->u.index + i;
+				a->dev_attr.attr.mode =
+				  (*t)->dev_attr.attr.mode;
+				a->dev_attr.show = (*t)->dev_attr.show;
+				a->dev_attr.store = (*t)->dev_attr.store;
+				*attrs = &a->dev_attr.attr;
+			}
+			attrs++;
+			su++;
+			t++;
+		}
+	}
+
+	err = sysfs_create_group(&dev->kobj, group);
+	if (err)
+		return ERR_PTR(-ENOMEM);
+
+	return group;
+}
+
 static bool is_word_sized(struct nct6775_data *data, u16 reg)
 {
 	switch (data->kind) {
+	case nct6106:
+		return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
+		  reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
+		  reg == 0x111 || reg == 0x121 || reg == 0x131;
 	case nct6775:
 		return (((reg & 0xff00) == 0x100 ||
 		    (reg & 0xff00) == 0x200) &&
@@ -714,8 +1039,9 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
 		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
 		  reg == 0x73 || reg == 0x75 || reg == 0x77;
 	case nct6779:
+	case nct6791:
 		return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
-		  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
+		  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
 		  reg == 0x402 ||
 		  reg == 0x63a || reg == 0x63c || reg == 0x63e ||
 		  reg == 0x640 || reg == 0x642 ||
@@ -1056,15 +1382,17 @@ static void nct6775_update_pwm_limits(struct device *dev)
 		case nct6776:
 			data->auto_pwm[i][data->auto_pwm_num] = 0xff;
 			break;
+		case nct6106:
 		case nct6779:
+		case nct6791:
 			reg = nct6775_read_value(data,
-					NCT6779_REG_CRITICAL_PWM_ENABLE[i]);
-			if (reg & 1)
-				data->auto_pwm[i][data->auto_pwm_num] =
-				  nct6775_read_value(data,
-					NCT6779_REG_CRITICAL_PWM[i]);
+					data->REG_CRITICAL_PWM_ENABLE[i]);
+			if (reg & data->CRITICAL_PWM_ENABLE_MASK)
+				reg = nct6775_read_value(data,
+					data->REG_CRITICAL_PWM[i]);
 			else
-				data->auto_pwm[i][data->auto_pwm_num] = 0xff;
+				reg = 0xff;
+			data->auto_pwm[i][data->auto_pwm_num] = reg;
 			break;
 		}
 	}
@@ -1110,7 +1438,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
 				data->fan_min[i] = nct6775_read_value(data,
 					   data->REG_FAN_MIN[i]);
 			data->fan_pulses[i] =
-			  nct6775_read_value(data, data->REG_FAN_PULSES[i]);
+			  (nct6775_read_value(data, data->REG_FAN_PULSES[i])
+				>> data->FAN_PULSE_SHIFT[i]) & 0x03;
 
 			nct6775_select_fan_div(dev, data, i, reg);
 		}
@@ -1143,6 +1472,15 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
 			data->alarms |= ((u64)alarm) << (i << 3);
 		}
 
+		data->beeps = 0;
+		for (i = 0; i < NUM_REG_BEEP; i++) {
+			u8 beep;
+			if (!data->REG_BEEP[i])
+				continue;
+			beep = nct6775_read_value(data, data->REG_BEEP[i]);
+			data->beeps |= ((u64)beep) << (i << 3);
+		}
+
 		data->last_updated = jiffies;
 		data->valid = true;
 	}
@@ -1230,224 +1568,138 @@ show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
 	return sprintf(buf, "%u\n", alarm);
 }
 
-static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
-static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
-static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
-static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0);
-static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0);
-static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0);
-static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0);
-static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0);
-static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0);
-static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0);
-static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0);
-static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0);
-static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0);
-static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0);
-static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0);
-
-static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
-static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
-static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
-static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
-static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11);
-static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12);
-static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13);
-static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14);
-
-static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 0, 1);
-static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 1, 1);
-static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 2, 1);
-static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 3, 1);
-static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 4, 1);
-static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 5, 1);
-static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 6, 1);
-static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 7, 1);
-static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 8, 1);
-static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 9, 1);
-static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 10, 1);
-static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 11, 1);
-static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 12, 1);
-static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 13, 1);
-static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 14, 1);
-
-static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 0, 2);
-static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 1, 2);
-static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 2, 2);
-static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 3, 2);
-static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 4, 2);
-static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 5, 2);
-static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 6, 2);
-static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 7, 2);
-static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 8, 2);
-static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 9, 2);
-static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 10, 2);
-static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 11, 2);
-static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 12, 2);
-static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 13, 2);
-static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg,
-			    store_in_reg, 14, 2);
-
-static struct attribute *nct6775_attributes_in[15][5] = {
-	{
-		&sensor_dev_attr_in0_input.dev_attr.attr,
-		&sensor_dev_attr_in0_min.dev_attr.attr,
-		&sensor_dev_attr_in0_max.dev_attr.attr,
-		&sensor_dev_attr_in0_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in1_input.dev_attr.attr,
-		&sensor_dev_attr_in1_min.dev_attr.attr,
-		&sensor_dev_attr_in1_max.dev_attr.attr,
-		&sensor_dev_attr_in1_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in2_input.dev_attr.attr,
-		&sensor_dev_attr_in2_min.dev_attr.attr,
-		&sensor_dev_attr_in2_max.dev_attr.attr,
-		&sensor_dev_attr_in2_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in3_input.dev_attr.attr,
-		&sensor_dev_attr_in3_min.dev_attr.attr,
-		&sensor_dev_attr_in3_max.dev_attr.attr,
-		&sensor_dev_attr_in3_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in4_input.dev_attr.attr,
-		&sensor_dev_attr_in4_min.dev_attr.attr,
-		&sensor_dev_attr_in4_max.dev_attr.attr,
-		&sensor_dev_attr_in4_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in5_input.dev_attr.attr,
-		&sensor_dev_attr_in5_min.dev_attr.attr,
-		&sensor_dev_attr_in5_max.dev_attr.attr,
-		&sensor_dev_attr_in5_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in6_input.dev_attr.attr,
-		&sensor_dev_attr_in6_min.dev_attr.attr,
-		&sensor_dev_attr_in6_max.dev_attr.attr,
-		&sensor_dev_attr_in6_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in7_input.dev_attr.attr,
-		&sensor_dev_attr_in7_min.dev_attr.attr,
-		&sensor_dev_attr_in7_max.dev_attr.attr,
-		&sensor_dev_attr_in7_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in8_input.dev_attr.attr,
-		&sensor_dev_attr_in8_min.dev_attr.attr,
-		&sensor_dev_attr_in8_max.dev_attr.attr,
-		&sensor_dev_attr_in8_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in9_input.dev_attr.attr,
-		&sensor_dev_attr_in9_min.dev_attr.attr,
-		&sensor_dev_attr_in9_max.dev_attr.attr,
-		&sensor_dev_attr_in9_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in10_input.dev_attr.attr,
-		&sensor_dev_attr_in10_min.dev_attr.attr,
-		&sensor_dev_attr_in10_max.dev_attr.attr,
-		&sensor_dev_attr_in10_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in11_input.dev_attr.attr,
-		&sensor_dev_attr_in11_min.dev_attr.attr,
-		&sensor_dev_attr_in11_max.dev_attr.attr,
-		&sensor_dev_attr_in11_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in12_input.dev_attr.attr,
-		&sensor_dev_attr_in12_min.dev_attr.attr,
-		&sensor_dev_attr_in12_max.dev_attr.attr,
-		&sensor_dev_attr_in12_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in13_input.dev_attr.attr,
-		&sensor_dev_attr_in13_min.dev_attr.attr,
-		&sensor_dev_attr_in13_max.dev_attr.attr,
-		&sensor_dev_attr_in13_alarm.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_in14_input.dev_attr.attr,
-		&sensor_dev_attr_in14_min.dev_attr.attr,
-		&sensor_dev_attr_in14_max.dev_attr.attr,
-		&sensor_dev_attr_in14_alarm.dev_attr.attr,
-		NULL
-	},
+static ssize_t
+show_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct nct6775_data *data = nct6775_update_device(dev);
+	int nr = data->BEEP_BITS[sattr->index];
+
+	return sprintf(buf, "%u\n",
+		       (unsigned int)((data->beeps >> nr) & 0x01));
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
+	   size_t count)
+{
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int nr = data->BEEP_BITS[sattr->index];
+	int regindex = nr >> 3;
+	unsigned long val;
+
+	int err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val > 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	if (val)
+		data->beeps |= (1ULL << nr);
+	else
+		data->beeps &= ~(1ULL << nr);
+	nct6775_write_value(data, data->REG_BEEP[regindex],
+			    (data->beeps >> (regindex << 3)) & 0xff);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct nct6775_data *data = nct6775_update_device(dev);
+	unsigned int beep = 0;
+	int nr;
+
+	/*
+	 * For temperatures, there is no fixed mapping from registers to beep
+	 * enable bits. Beep enable bits are determined by the temperature
+	 * source mapping.
+	 */
+	nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
+	if (nr >= 0) {
+		int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
+		beep = (data->beeps >> bit) & 0x01;
+	}
+	return sprintf(buf, "%u\n", beep);
+}
+
+static ssize_t
+store_temp_beep(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int nr, bit, regindex;
+	unsigned long val;
+
+	int err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val > 1)
+		return -EINVAL;
+
+	nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
+	if (nr < 0)
+		return -ENODEV;
+
+	bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
+	regindex = bit >> 3;
+
+	mutex_lock(&data->update_lock);
+	if (val)
+		data->beeps |= (1ULL << bit);
+	else
+		data->beeps &= ~(1ULL << bit);
+	nct6775_write_value(data, data->REG_BEEP[regindex],
+			    (data->beeps >> (regindex << 3)) & 0xff);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static umode_t nct6775_in_is_visible(struct kobject *kobj,
+				     struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int in = index / 5;	/* voltage index */
+
+	if (!(data->have_in & (1 << in)))
+		return 0;
+
+	return attr->mode;
+}
+
+SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
+SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
+SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
+		0);
+SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
+		  store_in_reg, 0, 1);
+SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
+		  store_in_reg, 0, 2);
+
+/*
+ * nct6775_in_is_visible uses the index into the following array
+ * to determine if attributes should be created or not.
+ * Any change in order or content must be matched.
+ */
+static struct sensor_device_template *nct6775_attributes_in_template[] = {
+	&sensor_dev_template_in_input,
+	&sensor_dev_template_in_alarm,
+	&sensor_dev_template_in_beep,
+	&sensor_dev_template_in_min,
+	&sensor_dev_template_in_max,
+	NULL
 };
 
-static const struct attribute_group nct6775_group_in[15] = {
-	{ .attrs = nct6775_attributes_in[0] },
-	{ .attrs = nct6775_attributes_in[1] },
-	{ .attrs = nct6775_attributes_in[2] },
-	{ .attrs = nct6775_attributes_in[3] },
-	{ .attrs = nct6775_attributes_in[4] },
-	{ .attrs = nct6775_attributes_in[5] },
-	{ .attrs = nct6775_attributes_in[6] },
-	{ .attrs = nct6775_attributes_in[7] },
-	{ .attrs = nct6775_attributes_in[8] },
-	{ .attrs = nct6775_attributes_in[9] },
-	{ .attrs = nct6775_attributes_in[10] },
-	{ .attrs = nct6775_attributes_in[11] },
-	{ .attrs = nct6775_attributes_in[12] },
-	{ .attrs = nct6775_attributes_in[13] },
-	{ .attrs = nct6775_attributes_in[14] },
+static struct sensor_template_group nct6775_in_template_group = {
+	.templates = nct6775_attributes_in_template,
+	.is_visible = nct6775_in_is_visible,
 };
 
 static ssize_t
@@ -1592,6 +1844,7 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr,
 	int nr = sattr->index;
 	unsigned long val;
 	int err;
+	u8 reg;
 
 	err = kstrtoul(buf, 10, &val);
 	if (err < 0)
@@ -1602,60 +1855,68 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr,
 
 	mutex_lock(&data->update_lock);
 	data->fan_pulses[nr] = val & 3;
-	nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3);
+	reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
+	reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
+	reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
+	nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
 	mutex_unlock(&data->update_lock);
 
 	return count;
 }
 
-static struct sensor_device_attribute sda_fan_input[] = {
-	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
-	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
-	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
-	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
-	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
-};
+static umode_t nct6775_fan_is_visible(struct kobject *kobj,
+				      struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int fan = index / 6;	/* fan index */
+	int nr = index % 6;	/* attribute index */
 
-static struct sensor_device_attribute sda_fan_alarm[] = {
-	SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE),
-	SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1),
-	SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2),
-	SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3),
-	SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4),
-};
+	if (!(data->has_fan & (1 << fan)))
+		return 0;
 
-static struct sensor_device_attribute sda_fan_min[] = {
-	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
-		    store_fan_min, 0),
-	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
-		    store_fan_min, 1),
-	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
-		    store_fan_min, 2),
-	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
-		    store_fan_min, 3),
-	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
-		    store_fan_min, 4),
-};
+	if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
+		return 0;
+	if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
+		return 0;
+	if (nr == 4 && !(data->has_fan_min & (1 << fan)))
+		return 0;
+	if (nr == 5 && data->kind != nct6775)
+		return 0;
+
+	return attr->mode;
+}
 
-static struct sensor_device_attribute sda_fan_pulses[] = {
-	SENSOR_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
-		    store_fan_pulses, 0),
-	SENSOR_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
-		    store_fan_pulses, 1),
-	SENSOR_ATTR(fan3_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
-		    store_fan_pulses, 2),
-	SENSOR_ATTR(fan4_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
-		    store_fan_pulses, 3),
-	SENSOR_ATTR(fan5_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
-		    store_fan_pulses, 4),
+SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
+SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
+		FAN_ALARM_BASE);
+SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
+		store_beep, FAN_ALARM_BASE);
+SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
+		store_fan_pulses, 0);
+SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
+		store_fan_min, 0);
+SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
+
+/*
+ * nct6775_fan_is_visible uses the index into the following array
+ * to determine if attributes should be created or not.
+ * Any change in order or content must be matched.
+ */
+static struct sensor_device_template *nct6775_attributes_fan_template[] = {
+	&sensor_dev_template_fan_input,
+	&sensor_dev_template_fan_alarm,	/* 1 */
+	&sensor_dev_template_fan_beep,	/* 2 */
+	&sensor_dev_template_fan_pulses,
+	&sensor_dev_template_fan_min,	/* 4 */
+	&sensor_dev_template_fan_div,	/* 5 */
+	NULL
 };
 
-static struct sensor_device_attribute sda_fan_div[] = {
-	SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
-	SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
-	SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
-	SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
-	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
+static struct sensor_template_group nct6775_fan_template_group = {
+	.templates = nct6775_attributes_fan_template,
+	.is_visible = nct6775_fan_is_visible,
+	.base = 1,
 };
 
 static ssize_t
@@ -1752,7 +2013,7 @@ store_temp_type(struct device *dev, struct device_attribute *attr,
 	int nr = sattr->index;
 	unsigned long val;
 	int err;
-	u8 vbat, diode, bit;
+	u8 vbat, diode, vbit, dbit;
 
 	err = kstrtoul(buf, 10, &val);
 	if (err < 0)
@@ -1764,16 +2025,17 @@ store_temp_type(struct device *dev, struct device_attribute *attr,
 	mutex_lock(&data->update_lock);
 
 	data->temp_type[nr] = val;
-	vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr);
-	diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr);
-	bit = 0x02 << nr;
+	vbit = 0x02 << nr;
+	dbit = data->DIODE_MASK << nr;
+	vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
+	diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
 	switch (val) {
 	case 1:	/* CPU diode (diode, current mode) */
-		vbat |= bit;
-		diode |= bit;
+		vbat |= vbit;
+		diode |= dbit;
 		break;
 	case 3: /* diode, voltage mode */
-		vbat |= bit;
+		vbat |= dbit;
 		break;
 	case 4:	/* thermistor */
 		break;
@@ -1785,142 +2047,83 @@ store_temp_type(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-static struct sensor_device_attribute_2 sda_temp_input[] = {
-	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
-	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0),
-	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0),
-	SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0),
-	SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0),
-	SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0),
-	SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0),
-	SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0),
-	SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0),
-	SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0),
-};
+static umode_t nct6775_temp_is_visible(struct kobject *kobj,
+				       struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int temp = index / 10;	/* temp index */
+	int nr = index % 10;	/* attribute index */
 
-static struct sensor_device_attribute sda_temp_label[] = {
-	SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
-	SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
-	SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
-	SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
-	SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
-	SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
-	SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
-	SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
-	SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
-	SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9),
-};
+	if (!(data->have_temp & (1 << temp)))
+		return 0;
 
-static struct sensor_device_attribute_2 sda_temp_max[] = {
-	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      0, 1),
-	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      1, 1),
-	SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      2, 1),
-	SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      3, 1),
-	SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      4, 1),
-	SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      5, 1),
-	SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      6, 1),
-	SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      7, 1),
-	SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      8, 1),
-	SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      9, 1),
-};
+	if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
+		return 0;				/* alarm */
 
-static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
-	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      0, 2),
-	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      1, 2),
-	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      2, 2),
-	SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      3, 2),
-	SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      4, 2),
-	SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      5, 2),
-	SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      6, 2),
-	SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      7, 2),
-	SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      8, 2),
-	SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      9, 2),
-};
+	if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
+		return 0;				/* beep */
 
-static struct sensor_device_attribute_2 sda_temp_crit[] = {
-	SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      0, 3),
-	SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      1, 3),
-	SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      2, 3),
-	SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      3, 3),
-	SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      4, 3),
-	SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      5, 3),
-	SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      6, 3),
-	SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      7, 3),
-	SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      8, 3),
-	SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
-		      9, 3),
-};
+	if (nr == 4 && !data->reg_temp[1][temp])	/* max */
+		return 0;
 
-static struct sensor_device_attribute sda_temp_offset[] = {
-	SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
-		    store_temp_offset, 0),
-	SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
-		    store_temp_offset, 1),
-	SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
-		    store_temp_offset, 2),
-	SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset,
-		    store_temp_offset, 3),
-	SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset,
-		    store_temp_offset, 4),
-	SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset,
-		    store_temp_offset, 5),
-};
+	if (nr == 5 && !data->reg_temp[2][temp])	/* max_hyst */
+		return 0;
+
+	if (nr == 6 && !data->reg_temp[3][temp])	/* crit */
+		return 0;
+
+	if (nr == 7 && !data->reg_temp[4][temp])	/* lcrit */
+		return 0;
+
+	/* offset and type only apply to fixed sensors */
+	if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
+		return 0;
 
-static struct sensor_device_attribute sda_temp_type[] = {
-	SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
-		    store_temp_type, 0),
-	SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
-		    store_temp_type, 1),
-	SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
-		    store_temp_type, 2),
-	SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type,
-		    store_temp_type, 3),
-	SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type,
-		    store_temp_type, 4),
-	SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type,
-		    store_temp_type, 5),
+	return attr->mode;
+}
+
+SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
+SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
+SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
+		  store_temp, 0, 1);
+SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
+		  show_temp, store_temp, 0, 2);
+SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
+		  store_temp, 0, 3);
+SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
+		  store_temp, 0, 4);
+SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
+		show_temp_offset, store_temp_offset, 0);
+SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
+		store_temp_type, 0);
+SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
+SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
+		store_temp_beep, 0);
+
+/*
+ * nct6775_temp_is_visible uses the index into the following array
+ * to determine if attributes should be created or not.
+ * Any change in order or content must be matched.
+ */
+static struct sensor_device_template *nct6775_attributes_temp_template[] = {
+	&sensor_dev_template_temp_input,
+	&sensor_dev_template_temp_label,
+	&sensor_dev_template_temp_alarm,	/* 2 */
+	&sensor_dev_template_temp_beep,		/* 3 */
+	&sensor_dev_template_temp_max,		/* 4 */
+	&sensor_dev_template_temp_max_hyst,	/* 5 */
+	&sensor_dev_template_temp_crit,		/* 6 */
+	&sensor_dev_template_temp_lcrit,	/* 7 */
+	&sensor_dev_template_temp_offset,	/* 8 */
+	&sensor_dev_template_temp_type,		/* 9 */
+	NULL
 };
 
-static struct sensor_device_attribute sda_temp_alarm[] = {
-	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0),
-	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1),
-	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2),
-	SENSOR_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3),
-	SENSOR_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4),
-	SENSOR_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 5),
-	SENSOR_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 6),
-	SENSOR_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 7),
-	SENSOR_ATTR(temp9_alarm, S_IRUGO, show_temp_alarm, NULL, 8),
-	SENSOR_ATTR(temp10_alarm, S_IRUGO, show_temp_alarm, NULL, 9),
+static struct sensor_template_group nct6775_temp_template_group = {
+	.templates = nct6775_attributes_temp_template,
+	.is_visible = nct6775_temp_is_visible,
+	.base = 1,
 };
 
 static ssize_t
@@ -2422,77 +2625,19 @@ store_speed_tolerance(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
-static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0);
-static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0);
-static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0);
-static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0);
-
-static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
-			  store_pwm_mode, 0);
-static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
-			  store_pwm_mode, 1);
-static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
-			  store_pwm_mode, 2);
-static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
-			  store_pwm_mode, 3);
-static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
-			  store_pwm_mode, 4);
-
-static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  store_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  store_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  store_pwm_enable, 2);
-static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  store_pwm_enable, 3);
-static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  store_pwm_enable, 4);
-
-static SENSOR_DEVICE_ATTR(pwm1_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_temp_sel, store_pwm_temp_sel, 0);
-static SENSOR_DEVICE_ATTR(pwm2_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_temp_sel, store_pwm_temp_sel, 1);
-static SENSOR_DEVICE_ATTR(pwm3_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_temp_sel, store_pwm_temp_sel, 2);
-static SENSOR_DEVICE_ATTR(pwm4_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_temp_sel, store_pwm_temp_sel, 3);
-static SENSOR_DEVICE_ATTR(pwm5_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_temp_sel, store_pwm_temp_sel, 4);
-
-static SENSOR_DEVICE_ATTR(pwm1_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
-			  store_target_temp, 0);
-static SENSOR_DEVICE_ATTR(pwm2_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
-			  store_target_temp, 1);
-static SENSOR_DEVICE_ATTR(pwm3_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
-			  store_target_temp, 2);
-static SENSOR_DEVICE_ATTR(pwm4_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
-			  store_target_temp, 3);
-static SENSOR_DEVICE_ATTR(pwm5_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
-			  store_target_temp, 4);
-
-static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_target_speed,
-			  store_target_speed, 0);
-static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_target_speed,
-			  store_target_speed, 1);
-static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_target_speed,
-			  store_target_speed, 2);
-static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_target_speed,
-			  store_target_speed, 3);
-static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_target_speed,
-			  store_target_speed, 4);
-
-static SENSOR_DEVICE_ATTR(fan1_tolerance, S_IWUSR | S_IRUGO,
-			    show_speed_tolerance, store_speed_tolerance, 0);
-static SENSOR_DEVICE_ATTR(fan2_tolerance, S_IWUSR | S_IRUGO,
-			    show_speed_tolerance, store_speed_tolerance, 1);
-static SENSOR_DEVICE_ATTR(fan3_tolerance, S_IWUSR | S_IRUGO,
-			    show_speed_tolerance, store_speed_tolerance, 2);
-static SENSOR_DEVICE_ATTR(fan4_tolerance, S_IWUSR | S_IRUGO,
-			    show_speed_tolerance, store_speed_tolerance, 3);
-static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO,
-			    show_speed_tolerance, store_speed_tolerance, 4);
+SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
+SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
+		store_pwm_mode, 0);
+SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
+		store_pwm_enable, 0);
+SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
+		show_pwm_temp_sel, store_pwm_temp_sel, 0);
+SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
+		show_target_temp, store_target_temp, 0);
+SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
+		show_target_speed, store_target_speed, 0);
+SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
+		show_speed_tolerance, store_speed_tolerance, 0);
 
 /* Smart Fan registers */
 
@@ -2531,79 +2676,18 @@ store_weight_temp(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
-			    0);
-static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
-			    1);
-static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
-			    2);
-static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
-			    3);
-static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO,
-			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
-			    4);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 0, 0);
-static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 1, 0);
-static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 2, 0);
-static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 3, 0);
-static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 4, 0);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 0, 1);
-static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 1, 1);
-static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 2, 1);
-static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 3, 1);
-static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 4, 1);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 0, 2);
-static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 1, 2);
-static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 2, 2);
-static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 3, 2);
-static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO,
-			    show_weight_temp, store_weight_temp, 4, 2);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO,
-			    show_pwm, store_pwm, 0, 5);
-static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO,
-			    show_pwm, store_pwm, 1, 5);
-static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO,
-			    show_pwm, store_pwm, 2, 5);
-static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO,
-			    show_pwm, store_pwm, 3, 5);
-static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO,
-			    show_pwm, store_pwm, 4, 5);
-
-/* duty_base is not supported on all chips */
-static struct sensor_device_attribute_2 sda_weight_duty_base[] = {
-	SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO,
-		      show_pwm, store_pwm, 0, 6),
-	SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO,
-		      show_pwm, store_pwm, 1, 6),
-	SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO,
-		      show_pwm, store_pwm, 2, 6),
-	SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO,
-		      show_pwm, store_pwm, 3, 6),
-	SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO,
-		      show_pwm, store_pwm, 4, 6),
-};
+SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
+		  show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
+SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
+		  S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
+SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
+		  S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
+SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
+		  S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
+SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
+		  S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
+SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
+		  S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
 
 static ssize_t
 show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
@@ -2651,227 +2735,6 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf)
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 0, 0);
-static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 1, 0);
-static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 2, 0);
-static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 3, 0);
-static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 4, 0);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 0, 1);
-static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 1, 1);
-static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 2, 1);
-static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 3, 1);
-static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
-			    store_fan_time, 4, 1);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO,
-			    show_fan_time, store_fan_time, 0, 2);
-static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO,
-			    show_fan_time, store_fan_time, 1, 2);
-static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO,
-			    show_fan_time, store_fan_time, 2, 2);
-static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO,
-			    show_fan_time, store_fan_time, 3, 2);
-static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO,
-			    show_fan_time, store_fan_time, 4, 2);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_start, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 0, 1);
-static SENSOR_DEVICE_ATTR_2(pwm2_start, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 1, 1);
-static SENSOR_DEVICE_ATTR_2(pwm3_start, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 2, 1);
-static SENSOR_DEVICE_ATTR_2(pwm4_start, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 3, 1);
-static SENSOR_DEVICE_ATTR_2(pwm5_start, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 4, 1);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_floor, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 0, 2);
-static SENSOR_DEVICE_ATTR_2(pwm2_floor, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 1, 2);
-static SENSOR_DEVICE_ATTR_2(pwm3_floor, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 2, 2);
-static SENSOR_DEVICE_ATTR_2(pwm4_floor, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 3, 2);
-static SENSOR_DEVICE_ATTR_2(pwm5_floor, S_IWUSR | S_IRUGO, show_pwm,
-			    store_pwm, 4, 2);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 0, 0);
-static SENSOR_DEVICE_ATTR_2(pwm2_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 1, 0);
-static SENSOR_DEVICE_ATTR_2(pwm3_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 2, 0);
-static SENSOR_DEVICE_ATTR_2(pwm4_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 3, 0);
-static SENSOR_DEVICE_ATTR_2(pwm5_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 4, 0);
-
-static SENSOR_DEVICE_ATTR_2(pwm1_crit_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 0, 1);
-static SENSOR_DEVICE_ATTR_2(pwm2_crit_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 1, 1);
-static SENSOR_DEVICE_ATTR_2(pwm3_crit_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 2, 1);
-static SENSOR_DEVICE_ATTR_2(pwm4_crit_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 3, 1);
-static SENSOR_DEVICE_ATTR_2(pwm5_crit_temp_tolerance, S_IWUSR | S_IRUGO,
-			    show_temp_tolerance, store_temp_tolerance, 4, 1);
-
-/* pwm_max is not supported on all chips */
-static struct sensor_device_attribute_2 sda_pwm_max[] = {
-	SENSOR_ATTR_2(pwm1_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
-		      0, 3),
-	SENSOR_ATTR_2(pwm2_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
-		      1, 3),
-	SENSOR_ATTR_2(pwm3_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
-		      2, 3),
-	SENSOR_ATTR_2(pwm4_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
-		      3, 3),
-	SENSOR_ATTR_2(pwm5_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
-		      4, 3),
-};
-
-/* pwm_step is not supported on all chips */
-static struct sensor_device_attribute_2 sda_pwm_step[] = {
-	SENSOR_ATTR_2(pwm1_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 4),
-	SENSOR_ATTR_2(pwm2_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 4),
-	SENSOR_ATTR_2(pwm3_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 4),
-	SENSOR_ATTR_2(pwm4_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 4),
-	SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4),
-};
-
-static struct attribute *nct6775_attributes_pwm[5][20] = {
-	{
-		&sensor_dev_attr_pwm1.dev_attr.attr,
-		&sensor_dev_attr_pwm1_mode.dev_attr.attr,
-		&sensor_dev_attr_pwm1_enable.dev_attr.attr,
-		&sensor_dev_attr_pwm1_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm1_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm1_crit_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm1_target_temp.dev_attr.attr,
-		&sensor_dev_attr_fan1_target.dev_attr.attr,
-		&sensor_dev_attr_fan1_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm1_stop_time.dev_attr.attr,
-		&sensor_dev_attr_pwm1_step_up_time.dev_attr.attr,
-		&sensor_dev_attr_pwm1_step_down_time.dev_attr.attr,
-		&sensor_dev_attr_pwm1_start.dev_attr.attr,
-		&sensor_dev_attr_pwm1_floor.dev_attr.attr,
-		&sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr,
-		&sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr,
-		&sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr,
-		&sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_pwm2.dev_attr.attr,
-		&sensor_dev_attr_pwm2_mode.dev_attr.attr,
-		&sensor_dev_attr_pwm2_enable.dev_attr.attr,
-		&sensor_dev_attr_pwm2_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm2_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm2_crit_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm2_target_temp.dev_attr.attr,
-		&sensor_dev_attr_fan2_target.dev_attr.attr,
-		&sensor_dev_attr_fan2_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm2_stop_time.dev_attr.attr,
-		&sensor_dev_attr_pwm2_step_up_time.dev_attr.attr,
-		&sensor_dev_attr_pwm2_step_down_time.dev_attr.attr,
-		&sensor_dev_attr_pwm2_start.dev_attr.attr,
-		&sensor_dev_attr_pwm2_floor.dev_attr.attr,
-		&sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr,
-		&sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr,
-		&sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr,
-		&sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_pwm3.dev_attr.attr,
-		&sensor_dev_attr_pwm3_mode.dev_attr.attr,
-		&sensor_dev_attr_pwm3_enable.dev_attr.attr,
-		&sensor_dev_attr_pwm3_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm3_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm3_crit_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm3_target_temp.dev_attr.attr,
-		&sensor_dev_attr_fan3_target.dev_attr.attr,
-		&sensor_dev_attr_fan3_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm3_stop_time.dev_attr.attr,
-		&sensor_dev_attr_pwm3_step_up_time.dev_attr.attr,
-		&sensor_dev_attr_pwm3_step_down_time.dev_attr.attr,
-		&sensor_dev_attr_pwm3_start.dev_attr.attr,
-		&sensor_dev_attr_pwm3_floor.dev_attr.attr,
-		&sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr,
-		&sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr,
-		&sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr,
-		&sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_pwm4.dev_attr.attr,
-		&sensor_dev_attr_pwm4_mode.dev_attr.attr,
-		&sensor_dev_attr_pwm4_enable.dev_attr.attr,
-		&sensor_dev_attr_pwm4_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm4_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm4_crit_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm4_target_temp.dev_attr.attr,
-		&sensor_dev_attr_fan4_target.dev_attr.attr,
-		&sensor_dev_attr_fan4_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm4_stop_time.dev_attr.attr,
-		&sensor_dev_attr_pwm4_step_up_time.dev_attr.attr,
-		&sensor_dev_attr_pwm4_step_down_time.dev_attr.attr,
-		&sensor_dev_attr_pwm4_start.dev_attr.attr,
-		&sensor_dev_attr_pwm4_floor.dev_attr.attr,
-		&sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr,
-		&sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr,
-		&sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr,
-		&sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr,
-		NULL
-	},
-	{
-		&sensor_dev_attr_pwm5.dev_attr.attr,
-		&sensor_dev_attr_pwm5_mode.dev_attr.attr,
-		&sensor_dev_attr_pwm5_enable.dev_attr.attr,
-		&sensor_dev_attr_pwm5_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm5_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm5_crit_temp_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm5_target_temp.dev_attr.attr,
-		&sensor_dev_attr_fan5_target.dev_attr.attr,
-		&sensor_dev_attr_fan5_tolerance.dev_attr.attr,
-		&sensor_dev_attr_pwm5_stop_time.dev_attr.attr,
-		&sensor_dev_attr_pwm5_step_up_time.dev_attr.attr,
-		&sensor_dev_attr_pwm5_step_down_time.dev_attr.attr,
-		&sensor_dev_attr_pwm5_start.dev_attr.attr,
-		&sensor_dev_attr_pwm5_floor.dev_attr.attr,
-		&sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr,
-		&sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr,
-		&sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr,
-		&sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr,
-		&sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr,
-		NULL
-	},
-};
-
-static const struct attribute_group nct6775_group_pwm[5] = {
-	{ .attrs = nct6775_attributes_pwm[0] },
-	{ .attrs = nct6775_attributes_pwm[1] },
-	{ .attrs = nct6775_attributes_pwm[2] },
-	{ .attrs = nct6775_attributes_pwm[3] },
-	{ .attrs = nct6775_attributes_pwm[4] },
-};
-
 static ssize_t
 show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -2927,17 +2790,19 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
 			break;
 		case nct6776:
 			break; /* always enabled, nothing to do */
+		case nct6106:
 		case nct6779:
-			nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr],
+		case nct6791:
+			nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
 					    val);
 			reg = nct6775_read_value(data,
-					NCT6779_REG_CRITICAL_PWM_ENABLE[nr]);
+					data->REG_CRITICAL_PWM_ENABLE[nr]);
 			if (val == 255)
-				reg &= ~0x01;
+				reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
 			else
-				reg |= 0x01;
+				reg |= data->CRITICAL_PWM_ENABLE_MASK;
 			nct6775_write_value(data,
-					    NCT6779_REG_CRITICAL_PWM_ENABLE[nr],
+					    data->REG_CRITICAL_PWM_ENABLE[nr],
 					    reg);
 			break;
 		}
@@ -2992,155 +2857,140 @@ store_auto_temp(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
+static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
+				      struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int pwm = index / 36;	/* pwm index */
+	int nr = index % 36;	/* attribute index */
+
+	if (!(data->has_pwm & (1 << pwm)))
+		return 0;
+
+	if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
+		return 0;
+	if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
+		return 0;
+	if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
+		return 0;
+
+	if (nr >= 22 && nr <= 35) {		/* auto point */
+		int api = (nr - 22) / 2;	/* auto point index */
+
+		if (api > data->auto_pwm_num)
+			return 0;
+	}
+	return attr->mode;
+}
+
+SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
+		  show_fan_time, store_fan_time, 0, 0);
+SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
+		  show_fan_time, store_fan_time, 0, 1);
+SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
+		  show_fan_time, store_fan_time, 0, 2);
+SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
+		  store_pwm, 0, 1);
+SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
+		  store_pwm, 0, 2);
+SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
+		  show_temp_tolerance, store_temp_tolerance, 0, 0);
+SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
+		  S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
+		  0, 1);
+
+SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		  0, 3);
+
+SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
+		  store_pwm, 0, 4);
+
+SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
+SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
+
+SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
+SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
+
+SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
+SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
+
+SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
+SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
+
+SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
+SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
+
+SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
+SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
+
+SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
+		  S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
+SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
+		  S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
+
 /*
- * The number of auto-point trip points is chip dependent.
- * Need to check support while generating/removing attribute files.
+ * nct6775_pwm_is_visible uses the index into the following array
+ * to determine if attributes should be created or not.
+ * Any change in order or content must be matched.
  */
-static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = {
-	SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 0),
-	SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 0),
-	SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 1),
-	SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 1),
-	SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 2),
-	SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 2),
-	SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 3),
-	SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 3),
-	SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 4),
-	SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 4),
-	SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 5),
-	SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 5),
-	SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 0, 6),
-	SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 0, 6),
-
-	SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 0),
-	SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 0),
-	SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 1),
-	SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 1),
-	SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 2),
-	SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 2),
-	SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 3),
-	SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 3),
-	SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 4),
-	SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 4),
-	SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 5),
-	SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 5),
-	SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 1, 6),
-	SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 1, 6),
-
-	SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 0),
-	SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 0),
-	SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 1),
-	SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 1),
-	SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 2),
-	SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 2),
-	SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 3),
-	SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 3),
-	SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 4),
-	SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 4),
-	SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 5),
-	SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 5),
-	SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 2, 6),
-	SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 2, 6),
-
-	SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 0),
-	SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 0),
-	SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 1),
-	SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 1),
-	SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 2),
-	SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 2),
-	SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 3),
-	SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 3),
-	SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 4),
-	SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 4),
-	SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 5),
-	SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 5),
-	SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 3, 6),
-	SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 3, 6),
-
-	SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 0),
-	SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 0),
-	SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 1),
-	SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 1),
-	SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 2),
-	SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 2),
-	SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 3),
-	SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 3),
-	SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 4),
-	SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 4),
-	SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 5),
-	SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 5),
-	SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO,
-		      show_auto_pwm, store_auto_pwm, 4, 6),
-	SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO,
-		      show_auto_temp, store_auto_temp, 4, 6),
+static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
+	&sensor_dev_template_pwm,
+	&sensor_dev_template_pwm_mode,
+	&sensor_dev_template_pwm_enable,
+	&sensor_dev_template_pwm_temp_sel,
+	&sensor_dev_template_pwm_temp_tolerance,
+	&sensor_dev_template_pwm_crit_temp_tolerance,
+	&sensor_dev_template_pwm_target_temp,
+	&sensor_dev_template_fan_target,
+	&sensor_dev_template_fan_tolerance,
+	&sensor_dev_template_pwm_stop_time,
+	&sensor_dev_template_pwm_step_up_time,
+	&sensor_dev_template_pwm_step_down_time,
+	&sensor_dev_template_pwm_start,
+	&sensor_dev_template_pwm_floor,
+	&sensor_dev_template_pwm_weight_temp_sel,
+	&sensor_dev_template_pwm_weight_temp_step,
+	&sensor_dev_template_pwm_weight_temp_step_tol,
+	&sensor_dev_template_pwm_weight_temp_step_base,
+	&sensor_dev_template_pwm_weight_duty_step,
+	&sensor_dev_template_pwm_max,			/* 19 */
+	&sensor_dev_template_pwm_step,			/* 20 */
+	&sensor_dev_template_pwm_weight_duty_base,	/* 21 */
+	&sensor_dev_template_pwm_auto_point1_pwm,	/* 22 */
+	&sensor_dev_template_pwm_auto_point1_temp,
+	&sensor_dev_template_pwm_auto_point2_pwm,
+	&sensor_dev_template_pwm_auto_point2_temp,
+	&sensor_dev_template_pwm_auto_point3_pwm,
+	&sensor_dev_template_pwm_auto_point3_temp,
+	&sensor_dev_template_pwm_auto_point4_pwm,
+	&sensor_dev_template_pwm_auto_point4_temp,
+	&sensor_dev_template_pwm_auto_point5_pwm,
+	&sensor_dev_template_pwm_auto_point5_temp,
+	&sensor_dev_template_pwm_auto_point6_pwm,
+	&sensor_dev_template_pwm_auto_point6_temp,
+	&sensor_dev_template_pwm_auto_point7_pwm,
+	&sensor_dev_template_pwm_auto_point7_temp,	/* 35 */
+
+	NULL
+};
+
+static struct sensor_template_group nct6775_pwm_template_group = {
+	.templates = nct6775_attributes_pwm_template,
+	.is_visible = nct6775_pwm_is_visible,
+	.base = 1,
 };
 
 static ssize_t
@@ -3159,7 +3009,6 @@ clear_caseopen(struct device *dev, struct device_attribute *attr,
 	       const char *buf, size_t count)
 {
 	struct nct6775_data *data = dev_get_drvdata(dev);
-	struct nct6775_sio_data *sio_data = dev->platform_data;
 	int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
 	unsigned long val;
 	u8 reg;
@@ -3175,19 +3024,19 @@ clear_caseopen(struct device *dev, struct device_attribute *attr,
 	 * The CR registers are the same for all chips, and not all chips
 	 * support clearing the caseopen status through "regular" registers.
 	 */
-	ret = superio_enter(sio_data->sioreg);
+	ret = superio_enter(data->sioreg);
 	if (ret) {
 		count = ret;
 		goto error;
 	}
 
-	superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
-	reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
+	superio_select(data->sioreg, NCT6775_LD_ACPI);
+	reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
 	reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
-	superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
+	superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
 	reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
-	superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
-	superio_exit(sio_data->sioreg);
+	superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
+	superio_exit(data->sioreg);
 
 	data->valid = false;	/* Force cache refresh */
 error:
@@ -3195,71 +3044,79 @@ error:
 	return count;
 }
 
-static struct sensor_device_attribute sda_caseopen[] = {
-	SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
-		    clear_caseopen, INTRUSION_ALARM_BASE),
-	SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
-		    clear_caseopen, INTRUSION_ALARM_BASE + 1),
-};
-
-/*
- * Driver and device management
- */
-
-static void nct6775_device_remove_files(struct device *dev)
+static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
+			  clear_caseopen, INTRUSION_ALARM_BASE);
+static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
+			  clear_caseopen, INTRUSION_ALARM_BASE + 1);
+static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
+			  store_beep, INTRUSION_ALARM_BASE);
+static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
+			  store_beep, INTRUSION_ALARM_BASE + 1);
+static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
+			  store_beep, BEEP_ENABLE_BASE);
+
+static umode_t nct6775_other_is_visible(struct kobject *kobj,
+					struct attribute *attr, int index)
 {
-	/*
-	 * some entries in the following arrays may not have been used in
-	 * device_create_file(), but device_remove_file() will ignore them
-	 */
-	int i;
+	struct device *dev = container_of(kobj, struct device, kobj);
 	struct nct6775_data *data = dev_get_drvdata(dev);
 
-	for (i = 0; i < data->pwm_num; i++)
-		sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]);
+	if (index == 1 && !data->have_vid)
+		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(sda_pwm_max); i++)
-		device_remove_file(dev, &sda_pwm_max[i].dev_attr);
+	if (index == 2 || index == 3) {
+		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
+			return 0;
+	}
+
+	if (index == 4 || index == 5) {
+		if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
+			return 0;
+	}
 
-	for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++)
-		device_remove_file(dev, &sda_pwm_step[i].dev_attr);
+	return attr->mode;
+}
 
-	for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++)
-		device_remove_file(dev, &sda_weight_duty_base[i].dev_attr);
+/*
+ * nct6775_other_is_visible uses the index into the following array
+ * to determine if attributes should be created or not.
+ * Any change in order or content must be matched.
+ */
+static struct attribute *nct6775_attributes_other[] = {
+	&dev_attr_name.attr,
+	&dev_attr_cpu0_vid.attr,				/* 1 */
+	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,	/* 2 */
+	&sensor_dev_attr_intrusion1_alarm.dev_attr.attr,	/* 3 */
+	&sensor_dev_attr_intrusion0_beep.dev_attr.attr,		/* 4 */
+	&sensor_dev_attr_intrusion1_beep.dev_attr.attr,		/* 5 */
+	&sensor_dev_attr_beep_enable.dev_attr.attr,		/* 6 */
+
+	NULL
+};
 
-	for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++)
-		device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr);
+static const struct attribute_group nct6775_group_other = {
+	.attrs = nct6775_attributes_other,
+	.is_visible = nct6775_other_is_visible,
+};
 
-	for (i = 0; i < data->in_num; i++)
-		sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]);
+/*
+ * Driver and device management
+ */
 
-	for (i = 0; i < 5; i++) {
-		device_remove_file(dev, &sda_fan_input[i].dev_attr);
-		device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
-		device_remove_file(dev, &sda_fan_div[i].dev_attr);
-		device_remove_file(dev, &sda_fan_min[i].dev_attr);
-		device_remove_file(dev, &sda_fan_pulses[i].dev_attr);
-	}
-	for (i = 0; i < NUM_TEMP; i++) {
-		if (!(data->have_temp & (1 << i)))
-			continue;
-		device_remove_file(dev, &sda_temp_input[i].dev_attr);
-		device_remove_file(dev, &sda_temp_label[i].dev_attr);
-		device_remove_file(dev, &sda_temp_max[i].dev_attr);
-		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
-		device_remove_file(dev, &sda_temp_crit[i].dev_attr);
-		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
-		if (!(data->have_temp_fixed & (1 << i)))
-			continue;
-		device_remove_file(dev, &sda_temp_type[i].dev_attr);
-		device_remove_file(dev, &sda_temp_offset[i].dev_attr);
-	}
+static void nct6775_device_remove_files(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
 
-	device_remove_file(dev, &sda_caseopen[0].dev_attr);
-	device_remove_file(dev, &sda_caseopen[1].dev_attr);
+	if (data->group_pwm)
+		sysfs_remove_group(&dev->kobj, data->group_pwm);
+	if (data->group_in)
+		sysfs_remove_group(&dev->kobj, data->group_in);
+	if (data->group_fan)
+		sysfs_remove_group(&dev->kobj, data->group_fan);
+	if (data->group_temp)
+		sysfs_remove_group(&dev->kobj, data->group_temp);
 
-	device_remove_file(dev, &dev_attr_name);
-	device_remove_file(dev, &dev_attr_cpu0_vid);
+	sysfs_remove_group(&dev->kobj, &nct6775_group_other);
 }
 
 /* Get the monitoring functions started */
@@ -3297,68 +3154,78 @@ static inline void nct6775_init_device(struct nct6775_data *data)
 	for (i = 0; i < data->temp_fixed_num; i++) {
 		if (!(data->have_temp_fixed & (1 << i)))
 			continue;
-		if ((tmp & (0x02 << i)))	/* diode */
-			data->temp_type[i] = 3 - ((diode >> i) & 0x02);
+		if ((tmp & (data->DIODE_MASK << i)))	/* diode */
+			data->temp_type[i]
+			  = 3 - ((diode >> i) & data->DIODE_MASK);
 		else				/* thermistor */
 			data->temp_type[i] = 4;
 	}
 }
 
-static int
-nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
-			 struct nct6775_data *data)
+static void
+nct6775_check_fan_inputs(struct nct6775_data *data)
 {
+	bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
+	bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
+	int sioreg = data->sioreg;
 	int regval;
-	bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
-	bool pwm3pin, pwm4pin, pwm5pin;
-	int ret;
-
-	ret = superio_enter(sio_data->sioreg);
-	if (ret)
-		return ret;
 
 	/* fan4 and fan5 share some pins with the GPIO and serial flash */
 	if (data->kind == nct6775) {
-		regval = superio_inb(sio_data->sioreg, 0x2c);
+		regval = superio_inb(sioreg, 0x2c);
 
 		fan3pin = regval & (1 << 6);
-		fan3min = fan3pin;
 		pwm3pin = regval & (1 << 7);
 
 		/* On NCT6775, fan4 shares pins with the fdc interface */
-		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
-		fan4min = 0;
-		fan5pin = 0;
-		pwm4pin = 0;
-		pwm5pin = 0;
+		fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
+		fan4min = false;
+		fan5pin = false;
+		fan6pin = false;
+		pwm4pin = false;
+		pwm5pin = false;
+		pwm6pin = false;
 	} else if (data->kind == nct6776) {
-		bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+		bool gpok = superio_inb(sioreg, 0x27) & 0x80;
 
-		superio_select(sio_data->sioreg, NCT6775_LD_HWM);
-		regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+		superio_select(sioreg, NCT6775_LD_HWM);
+		regval = superio_inb(sioreg, SIO_REG_ENABLE);
 
 		if (regval & 0x80)
 			fan3pin = gpok;
 		else
-			fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+			fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
 
 		if (regval & 0x40)
 			fan4pin = gpok;
 		else
-			fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
+			fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
 
 		if (regval & 0x20)
 			fan5pin = gpok;
 		else
-			fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
+			fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
 
 		fan4min = fan4pin;
-		fan3min = fan3pin;
+		fan6pin = false;
 		pwm3pin = fan3pin;
-		pwm4pin = 0;
-		pwm5pin = 0;
-	} else {	/* NCT6779D */
-		regval = superio_inb(sio_data->sioreg, 0x1c);
+		pwm4pin = false;
+		pwm5pin = false;
+		pwm6pin = false;
+	} else if (data->kind == nct6106) {
+		regval = superio_inb(sioreg, 0x24);
+		fan3pin = !(regval & 0x80);
+		pwm3pin = regval & 0x08;
+
+		fan4pin = false;
+		fan4min = false;
+		fan5pin = false;
+		fan6pin = false;
+		pwm4pin = false;
+		pwm5pin = false;
+		pwm6pin = false;
+	} else {	/* NCT6779D or NCT6791D */
+		regval = superio_inb(sioreg, 0x1c);
 
 		fan3pin = !(regval & (1 << 5));
 		fan4pin = !(regval & (1 << 6));
@@ -3368,22 +3235,25 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
 		pwm4pin = !(regval & (1 << 1));
 		pwm5pin = !(regval & (1 << 2));
 
-		fan3min = fan3pin;
 		fan4min = fan4pin;
-	}
-
-	superio_exit(sio_data->sioreg);
 
-	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
-	data->has_fan |= fan3pin << 2;
-	data->has_fan_min |= fan3min << 2;
-
-	data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
-	data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
-
-	data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
+		if (data->kind == nct6791) {
+			regval = superio_inb(sioreg, 0x2d);
+			fan6pin = (regval & (1 << 1));
+			pwm6pin = (regval & (1 << 0));
+		} else {	/* NCT6779D */
+			fan6pin = false;
+			pwm6pin = false;
+		}
+	}
 
-	return 0;
+	/* fan 1 and 2 (0x03) are always present */
+	data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
+		(fan5pin << 4) | (fan6pin << 5);
+	data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
+		(fan5pin << 4);
+	data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
+		(pwm5pin << 4) | (pwm6pin << 5);
 }
 
 static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
@@ -3415,16 +3285,17 @@ static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
 static int nct6775_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct nct6775_sio_data *sio_data = dev->platform_data;
+	struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
 	struct nct6775_data *data;
 	struct resource *res;
 	int i, s, err = 0;
 	int src, mask, available;
 	const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
 	const u16 *reg_temp_alternate, *reg_temp_crit;
+	const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
 	int num_reg_temp;
-	bool have_vid = false;
 	u8 cr2a;
+	struct attribute_group *group;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
@@ -3437,6 +3308,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	data->kind = sio_data->kind;
+	data->sioreg = sio_data->sioreg;
 	data->addr = res->start;
 	mutex_init(&data->update_lock);
 	data->name = nct6775_device_names[data->kind];
@@ -3444,6 +3316,75 @@ static int nct6775_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, data);
 
 	switch (data->kind) {
+	case nct6106:
+		data->in_num = 9;
+		data->pwm_num = 3;
+		data->auto_pwm_num = 4;
+		data->temp_fixed_num = 3;
+		data->num_temp_alarms = 6;
+		data->num_temp_beeps = 6;
+
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+
+		data->temp_label = nct6776_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
+
+		data->REG_VBAT = NCT6106_REG_VBAT;
+		data->REG_DIODE = NCT6106_REG_DIODE;
+		data->DIODE_MASK = NCT6106_DIODE_MASK;
+		data->REG_VIN = NCT6106_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
+		data->REG_TARGET = NCT6106_REG_TARGET;
+		data->REG_FAN = NCT6106_REG_FAN;
+		data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
+		data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
+		data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
+		data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
+		data->REG_PWM[0] = NCT6106_REG_PWM;
+		data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
+		data->REG_PWM_READ = NCT6106_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
+		data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
+		data->CRITICAL_PWM_ENABLE_MASK
+		  = NCT6106_CRITICAL_PWM_ENABLE_MASK;
+		data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
+		data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
+		data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6106_REG_ALARM;
+		data->ALARM_BITS = NCT6106_ALARM_BITS;
+		data->REG_BEEP = NCT6106_REG_BEEP;
+		data->BEEP_BITS = NCT6106_BEEP_BITS;
+
+		reg_temp = NCT6106_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
+		reg_temp_over = NCT6106_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6106_REG_TEMP_HYST;
+		reg_temp_config = NCT6106_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6106_REG_TEMP_CRIT;
+		reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
+		reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
+
+		break;
 	case nct6775:
 		data->in_num = 9;
 		data->pwm_num = 3;
@@ -3451,8 +3392,10 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->has_fan_div = true;
 		data->temp_fixed_num = 3;
 		data->num_temp_alarms = 3;
+		data->num_temp_beeps = 3;
 
 		data->ALARM_BITS = NCT6775_ALARM_BITS;
+		data->BEEP_BITS = NCT6775_BEEP_BITS;
 
 		data->fan_from_reg = fan_from_reg16;
 		data->fan_from_reg_min = fan_from_reg8;
@@ -3466,6 +3409,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_CONFIG = NCT6775_REG_CONFIG;
 		data->REG_VBAT = NCT6775_REG_VBAT;
 		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->DIODE_MASK = NCT6775_DIODE_MASK;
 		data->REG_VIN = NCT6775_REG_IN;
 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
@@ -3474,6 +3418,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
 		data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
 		data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
+		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
 		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
 		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
@@ -3499,6 +3444,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
 		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
 		data->REG_ALARM = NCT6775_REG_ALARM;
+		data->REG_BEEP = NCT6775_REG_BEEP;
 
 		reg_temp = NCT6775_REG_TEMP;
 		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
@@ -3516,8 +3462,10 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->has_fan_div = false;
 		data->temp_fixed_num = 3;
 		data->num_temp_alarms = 3;
+		data->num_temp_beeps = 6;
 
 		data->ALARM_BITS = NCT6776_ALARM_BITS;
+		data->BEEP_BITS = NCT6776_BEEP_BITS;
 
 		data->fan_from_reg = fan_from_reg13;
 		data->fan_from_reg_min = fan_from_reg13;
@@ -3531,6 +3479,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_CONFIG = NCT6775_REG_CONFIG;
 		data->REG_VBAT = NCT6775_REG_VBAT;
 		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->DIODE_MASK = NCT6775_DIODE_MASK;
 		data->REG_VIN = NCT6775_REG_IN;
 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
@@ -3539,6 +3488,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
 		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
 		data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
+		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
 		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
 		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
@@ -3564,6 +3514,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
 		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
 		data->REG_ALARM = NCT6775_REG_ALARM;
+		data->REG_BEEP = NCT6776_REG_BEEP;
 
 		reg_temp = NCT6775_REG_TEMP;
 		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
@@ -3581,8 +3532,10 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->has_fan_div = false;
 		data->temp_fixed_num = 6;
 		data->num_temp_alarms = 2;
+		data->num_temp_beeps = 2;
 
 		data->ALARM_BITS = NCT6779_ALARM_BITS;
+		data->BEEP_BITS = NCT6779_BEEP_BITS;
 
 		data->fan_from_reg = fan_from_reg13;
 		data->fan_from_reg_min = fan_from_reg13;
@@ -3596,6 +3549,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_CONFIG = NCT6775_REG_CONFIG;
 		data->REG_VBAT = NCT6775_REG_VBAT;
 		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->DIODE_MASK = NCT6775_DIODE_MASK;
 		data->REG_VIN = NCT6779_REG_IN;
 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
@@ -3604,6 +3558,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
 		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
 		data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
+		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
 		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
 		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
@@ -3621,6 +3576,10 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
 		data->REG_CRITICAL_TEMP_TOLERANCE
 		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
+		data->CRITICAL_PWM_ENABLE_MASK
+		  = NCT6779_CRITICAL_PWM_ENABLE_MASK;
+		data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
 		data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
 		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
 		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
@@ -3629,6 +3588,81 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
 		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
 		data->REG_ALARM = NCT6779_REG_ALARM;
+		data->REG_BEEP = NCT6776_REG_BEEP;
+
+		reg_temp = NCT6779_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
+		reg_temp_over = NCT6779_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6779_REG_TEMP_HYST;
+		reg_temp_config = NCT6779_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6779_REG_TEMP_CRIT;
+
+		break;
+	case nct6791:
+		data->in_num = 15;
+		data->pwm_num = 6;
+		data->auto_pwm_num = 4;
+		data->has_fan_div = false;
+		data->temp_fixed_num = 6;
+		data->num_temp_alarms = 2;
+		data->num_temp_beeps = 2;
+
+		data->ALARM_BITS = NCT6791_ALARM_BITS;
+		data->BEEP_BITS = NCT6779_BEEP_BITS;
+
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+		data->target_temp_mask = 0xff;
+		data->tolerance_mask = 0x07;
+		data->speed_tolerance_limit = 63;
+
+		data->temp_label = nct6779_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->DIODE_MASK = NCT6775_DIODE_MASK;
+		data->REG_VIN = NCT6779_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6779_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
+		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
+		data->CRITICAL_PWM_ENABLE_MASK
+		  = NCT6779_CRITICAL_PWM_ENABLE_MASK;
+		data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
+		data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
+		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6791_REG_ALARM;
+		data->REG_BEEP = NCT6776_REG_BEEP;
 
 		reg_temp = NCT6779_REG_TEMP;
 		num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
@@ -3700,6 +3734,13 @@ static int nct6775_probe(struct platform_device *pdev)
 			data->reg_temp[0][src - 1] = reg_temp[i];
 			data->reg_temp[1][src - 1] = reg_temp_over[i];
 			data->reg_temp[2][src - 1] = reg_temp_hyst[i];
+			if (reg_temp_crit_h && reg_temp_crit_h[i])
+				data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
+			else if (reg_temp_crit[src - 1])
+				data->reg_temp[3][src - 1]
+				  = reg_temp_crit[src - 1];
+			if (reg_temp_crit_l && reg_temp_crit_l[i])
+				data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
 			data->reg_temp_config[src - 1] = reg_temp_config[i];
 			data->temp_src[src - 1] = src;
 			continue;
@@ -3714,8 +3755,12 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->reg_temp[1][s] = reg_temp_over[i];
 		data->reg_temp[2][s] = reg_temp_hyst[i];
 		data->reg_temp_config[s] = reg_temp_config[i];
-		if (reg_temp_crit[src - 1])
+		if (reg_temp_crit_h && reg_temp_crit_h[i])
+			data->reg_temp[3][s] = reg_temp_crit_h[i];
+		else if (reg_temp_crit[src - 1])
 			data->reg_temp[3][s] = reg_temp_crit[src - 1];
+		if (reg_temp_crit_l && reg_temp_crit_l[i])
+			data->reg_temp[4][s] = reg_temp_crit_l[i];
 
 		data->temp_src[s] = src;
 		s++;
@@ -3767,12 +3812,14 @@ static int nct6775_probe(struct platform_device *pdev)
 	cr2a = superio_inb(sio_data->sioreg, 0x2a);
 	switch (data->kind) {
 	case nct6775:
-		have_vid = (cr2a & 0x40);
+		data->have_vid = (cr2a & 0x40);
 		break;
 	case nct6776:
-		have_vid = (cr2a & 0x60) == 0x40;
+		data->have_vid = (cr2a & 0x60) == 0x40;
 		break;
+	case nct6106:
 	case nct6779:
+	case nct6791:
 		break;
 	}
 
@@ -3780,7 +3827,7 @@ static int nct6775_probe(struct platform_device *pdev)
 	 * Read VID value
 	 * We can get the VID input values directly at logical device D 0xe3.
 	 */
-	if (have_vid) {
+	if (data->have_vid) {
 		superio_select(sio_data->sioreg, NCT6775_LD_VID);
 		data->vid = superio_inb(sio_data->sioreg, 0xe3);
 		data->vrm = vid_which_vrm();
@@ -3793,6 +3840,9 @@ static int nct6775_probe(struct platform_device *pdev)
 		tmp = superio_inb(sio_data->sioreg,
 				  NCT6775_REG_CR_FAN_DEBOUNCE);
 		switch (data->kind) {
+		case nct6106:
+			tmp |= 0xe0;
+			break;
 		case nct6775:
 			tmp |= 0x1e;
 			break;
@@ -3800,6 +3850,9 @@ static int nct6775_probe(struct platform_device *pdev)
 		case nct6779:
 			tmp |= 0x3e;
 			break;
+		case nct6791:
+			tmp |= 0x7e;
+			break;
 		}
 		superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
 			     tmp);
@@ -3807,157 +3860,47 @@ static int nct6775_probe(struct platform_device *pdev)
 			 data->name);
 	}
 
-	superio_exit(sio_data->sioreg);
-
-	if (have_vid) {
-		err = device_create_file(dev, &dev_attr_cpu0_vid);
-		if (err)
-			return err;
-	}
+	nct6775_check_fan_inputs(data);
 
-	err = nct6775_check_fan_inputs(sio_data, data);
-	if (err)
-		goto exit_remove;
+	superio_exit(sio_data->sioreg);
 
 	/* Read fan clock dividers immediately */
 	nct6775_init_fan_common(dev, data);
 
 	/* Register sysfs hooks */
-	for (i = 0; i < data->pwm_num; i++) {
-		if (!(data->has_pwm & (1 << i)))
-			continue;
-
-		err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]);
-		if (err)
-			goto exit_remove;
-
-		if (data->REG_PWM[3]) {
-			err = device_create_file(dev,
-					&sda_pwm_max[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (data->REG_PWM[4]) {
-			err = device_create_file(dev,
-					&sda_pwm_step[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (data->REG_PWM[6]) {
-			err = device_create_file(dev,
-					&sda_weight_duty_base[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-	}
-	for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) {
-		struct sensor_device_attribute_2 *attr =
-			&sda_auto_pwm_arrays[i];
-
-		if (!(data->has_pwm & (1 << attr->nr)))
-			continue;
-		if (attr->index > data->auto_pwm_num)
-			continue;
-		err = device_create_file(dev, &attr->dev_attr);
-		if (err)
-			goto exit_remove;
-	}
-
-	for (i = 0; i < data->in_num; i++) {
-		if (!(data->have_in & (1 << i)))
-			continue;
-		err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]);
-		if (err)
-			goto exit_remove;
+	group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
+					  data->pwm_num);
+	if (IS_ERR(group)) {
+		err = PTR_ERR(group);
+		goto exit_remove;
 	}
+	data->group_pwm = group;
 
-	for (i = 0; i < 5; i++) {
-		if (data->has_fan & (1 << i)) {
-			err = device_create_file(dev,
-						 &sda_fan_input[i].dev_attr);
-			if (err)
-				goto exit_remove;
-			if (data->ALARM_BITS[FAN_ALARM_BASE + i] >= 0) {
-				err = device_create_file(dev,
-						&sda_fan_alarm[i].dev_attr);
-				if (err)
-					goto exit_remove;
-			}
-			if (data->kind != nct6776 &&
-			    data->kind != nct6779) {
-				err = device_create_file(dev,
-						&sda_fan_div[i].dev_attr);
-				if (err)
-					goto exit_remove;
-			}
-			if (data->has_fan_min & (1 << i)) {
-				err = device_create_file(dev,
-						&sda_fan_min[i].dev_attr);
-				if (err)
-					goto exit_remove;
-			}
-			err = device_create_file(dev,
-						&sda_fan_pulses[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
+	group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
+					  fls(data->have_in));
+	if (IS_ERR(group)) {
+		err = PTR_ERR(group);
+		goto exit_remove;
 	}
+	data->group_in = group;
 
-	for (i = 0; i < NUM_TEMP; i++) {
-		if (!(data->have_temp & (1 << i)))
-			continue;
-		err = device_create_file(dev, &sda_temp_input[i].dev_attr);
-		if (err)
-			goto exit_remove;
-		if (data->temp_label) {
-			err = device_create_file(dev,
-						 &sda_temp_label[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (data->reg_temp[1][i]) {
-			err = device_create_file(dev,
-						 &sda_temp_max[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (data->reg_temp[2][i]) {
-			err = device_create_file(dev,
-					&sda_temp_max_hyst[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (data->reg_temp[3][i]) {
-			err = device_create_file(dev,
-						 &sda_temp_crit[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (find_temp_source(data, i, data->num_temp_alarms) >= 0) {
-			err = device_create_file(dev,
-						 &sda_temp_alarm[i].dev_attr);
-			if (err)
-				goto exit_remove;
-		}
-		if (!(data->have_temp_fixed & (1 << i)))
-			continue;
-		err = device_create_file(dev, &sda_temp_type[i].dev_attr);
-		if (err)
-			goto exit_remove;
-		err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
-		if (err)
-			goto exit_remove;
+	group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
+					  fls(data->has_fan));
+	if (IS_ERR(group)) {
+		err = PTR_ERR(group);
+		goto exit_remove;
 	}
+	data->group_fan = group;
 
-	for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
-		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0)
-			continue;
-		err = device_create_file(dev, &sda_caseopen[i].dev_attr);
-		if (err)
-			goto exit_remove;
+	group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
+					  fls(data->have_temp));
+	if (IS_ERR(group)) {
+		err = PTR_ERR(group);
+		goto exit_remove;
 	}
+	data->group_temp = group;
 
-	err = device_create_file(dev, &dev_attr_name);
+	err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
 	if (err)
 		goto exit_remove;
 
@@ -3988,11 +3931,10 @@ static int nct6775_remove(struct platform_device *pdev)
 static int nct6775_suspend(struct device *dev)
 {
 	struct nct6775_data *data = nct6775_update_device(dev);
-	struct nct6775_sio_data *sio_data = dev->platform_data;
 
 	mutex_lock(&data->update_lock);
 	data->vbat = nct6775_read_value(data, data->REG_VBAT);
-	if (sio_data->kind == nct6775) {
+	if (data->kind == nct6775) {
 		data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
 		data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
 	}
@@ -4004,7 +3946,6 @@ static int nct6775_suspend(struct device *dev)
 static int nct6775_resume(struct device *dev)
 {
 	struct nct6775_data *data = dev_get_drvdata(dev);
-	struct nct6775_sio_data *sio_data = dev->platform_data;
 	int i, j;
 
 	mutex_lock(&data->update_lock);
@@ -4041,7 +3982,7 @@ static int nct6775_resume(struct device *dev)
 
 	/* Restore other settings */
 	nct6775_write_value(data, data->REG_VBAT, data->vbat);
-	if (sio_data->kind == nct6775) {
+	if (data->kind == nct6775) {
 		nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
 		nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
 	}
@@ -4056,6 +3997,8 @@ static int nct6775_resume(struct device *dev)
 static const struct dev_pm_ops nct6775_dev_pm_ops = {
 	.suspend = nct6775_suspend,
 	.resume = nct6775_resume,
+	.freeze = nct6775_suspend,
+	.restore = nct6775_resume,
 };
 
 #define NCT6775_DEV_PM_OPS	(&nct6775_dev_pm_ops)
@@ -4074,17 +4017,19 @@ static struct platform_driver nct6775_driver = {
 };
 
 static const char * const nct6775_sio_names[] __initconst = {
+	"NCT6106D",
 	"NCT6775F",
 	"NCT6776D/F",
 	"NCT6779D",
+	"NCT6791D",
 };
 
 /* nct6775_find() looks for a '627 in the Super-I/O config space */
-static int __init nct6775_find(int sioaddr, unsigned short *addr,
-			       struct nct6775_sio_data *sio_data)
+static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
 {
 	u16 val;
 	int err;
+	int addr;
 
 	err = superio_enter(sioaddr);
 	if (err)
@@ -4096,6 +4041,9 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
 		val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
 		    | superio_inb(sioaddr, SIO_REG_DEVID + 1);
 	switch (val & SIO_ID_MASK) {
+	case SIO_NCT6106_ID:
+		sio_data->kind = nct6106;
+		break;
 	case SIO_NCT6775_ID:
 		sio_data->kind = nct6775;
 		break;
@@ -4105,6 +4053,9 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
 	case SIO_NCT6779_ID:
 		sio_data->kind = nct6779;
 		break;
+	case SIO_NCT6791_ID:
+		sio_data->kind = nct6791;
+		break;
 	default:
 		if (val != 0xffff)
 			pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -4116,8 +4067,8 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
 	superio_select(sioaddr, NCT6775_LD_HWM);
 	val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
 	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);
-	*addr = val & IOREGION_ALIGNMENT;
-	if (*addr == 0) {
+	addr = val & IOREGION_ALIGNMENT;
+	if (addr == 0) {
 		pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
 		superio_exit(sioaddr);
 		return -ENODEV;
@@ -4129,13 +4080,22 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
 		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
 		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
 	}
+	if (sio_data->kind == nct6791) {
+		val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
+		if (val & 0x10) {
+			pr_info("Enabling hardware monitor logical device mappings.\n");
+			superio_outb(sioaddr,
+				     NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
+				     val & ~0x10);
+		}
+	}
 
 	superio_exit(sioaddr);
-	pr_info("Found %s or compatible chip at %#x\n",
-		nct6775_sio_names[sio_data->kind], *addr);
+	pr_info("Found %s or compatible chip at %#x:%#x\n",
+		nct6775_sio_names[sio_data->kind], sioaddr, addr);
 	sio_data->sioreg = sioaddr;
 
-	return 0;
+	return addr;
 }
 
 /*
@@ -4144,14 +4104,20 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
  * track of the nct6775 driver. But since we platform_device_alloc(), we
  * must keep track of the device
  */
-static struct platform_device *pdev;
+static struct platform_device *pdev[2];
 
 static int __init sensors_nct6775_init(void)
 {
-	int err;
-	unsigned short address;
+	int i, err;
+	bool found = false;
+	int address;
 	struct resource res;
 	struct nct6775_sio_data sio_data;
+	int sioaddr[2] = { 0x2e, 0x4e };
+
+	err = platform_driver_register(&nct6775_driver);
+	if (err)
+		return err;
 
 	/*
 	 * initialize sio_data->kind and sio_data->sioreg.
@@ -4160,64 +4126,71 @@ static int __init sensors_nct6775_init(void)
 	 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
 	 * nct6775 hardware monitor, and call probe()
 	 */
-	if (nct6775_find(0x2e, &address, &sio_data) &&
-	    nct6775_find(0x4e, &address, &sio_data))
-		return -ENODEV;
-
-	err = platform_driver_register(&nct6775_driver);
-	if (err)
-		goto exit;
+	for (i = 0; i < ARRAY_SIZE(pdev); i++) {
+		address = nct6775_find(sioaddr[i], &sio_data);
+		if (address <= 0)
+			continue;
 
-	pdev = platform_device_alloc(DRVNAME, address);
-	if (!pdev) {
-		err = -ENOMEM;
-		pr_err("Device allocation failed\n");
-		goto exit_unregister;
-	}
+		found = true;
 
-	err = platform_device_add_data(pdev, &sio_data,
-				       sizeof(struct nct6775_sio_data));
-	if (err) {
-		pr_err("Platform data allocation failed\n");
-		goto exit_device_put;
-	}
+		pdev[i] = platform_device_alloc(DRVNAME, address);
+		if (!pdev[i]) {
+			err = -ENOMEM;
+			goto exit_device_put;
+		}
 
-	memset(&res, 0, sizeof(res));
-	res.name = DRVNAME;
-	res.start = address + IOREGION_OFFSET;
-	res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
-	res.flags = IORESOURCE_IO;
+		err = platform_device_add_data(pdev[i], &sio_data,
+					       sizeof(struct nct6775_sio_data));
+		if (err)
+			goto exit_device_put;
+
+		memset(&res, 0, sizeof(res));
+		res.name = DRVNAME;
+		res.start = address + IOREGION_OFFSET;
+		res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
+		res.flags = IORESOURCE_IO;
+
+		err = acpi_check_resource_conflict(&res);
+		if (err) {
+			platform_device_put(pdev[i]);
+			pdev[i] = NULL;
+			continue;
+		}
 
-	err = acpi_check_resource_conflict(&res);
-	if (err)
-		goto exit_device_put;
+		err = platform_device_add_resources(pdev[i], &res, 1);
+		if (err)
+			goto exit_device_put;
 
-	err = platform_device_add_resources(pdev, &res, 1);
-	if (err) {
-		pr_err("Device resource addition failed (%d)\n", err);
-		goto exit_device_put;
+		/* platform_device_add calls probe() */
+		err = platform_device_add(pdev[i]);
+		if (err)
+			goto exit_device_put;
 	}
-
-	/* platform_device_add calls probe() */
-	err = platform_device_add(pdev);
-	if (err) {
-		pr_err("Device addition failed (%d)\n", err);
-		goto exit_device_put;
+	if (!found) {
+		err = -ENODEV;
+		goto exit_unregister;
 	}
 
 	return 0;
 
 exit_device_put:
-	platform_device_put(pdev);
+	for (i = 0; i < ARRAY_SIZE(pdev); i++) {
+		if (pdev[i])
+			platform_device_put(pdev[i]);
+	}
 exit_unregister:
 	platform_driver_unregister(&nct6775_driver);
-exit:
 	return err;
 }
 
 static void __exit sensors_nct6775_exit(void)
 {
-	platform_device_unregister(pdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pdev); i++) {
+		if (pdev[i])
+			platform_device_unregister(pdev[i]);
+	}
 	platform_driver_unregister(&nct6775_driver);
 }
 
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 830a842..8c23203 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -424,7 +424,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
 	if (IS_ERR(pdata))
 		return PTR_ERR(pdata);
 	else if (pdata == NULL)
-		pdata = pdev->dev.platform_data;
+		pdata = dev_get_platdata(&pdev->dev);
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "No platform init data supplied.\n");
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index ea60686..6e6ea44 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -983,7 +983,7 @@ static int pc87427_request_regions(struct platform_device *pdev,
 
 static void pc87427_init_device(struct device *dev)
 {
-	struct pc87427_sio_data *sio_data = dev->platform_data;
+	struct pc87427_sio_data *sio_data = dev_get_platdata(dev);
 	struct pc87427_data *data = dev_get_drvdata(dev);
 	int i;
 	u8 reg;
@@ -1075,7 +1075,7 @@ static void pc87427_remove_files(struct device *dev)
 
 static int pc87427_probe(struct platform_device *pdev)
 {
-	struct pc87427_sio_data *sio_data = pdev->dev.platform_data;
+	struct pc87427_sio_data *sio_data = dev_get_platdata(&pdev->dev);
 	struct pc87427_data *data;
 	int i, err, res_count;
 
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 9add6092..9319fcf 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -1726,7 +1726,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
 		   struct pmbus_driver_info *info)
 {
 	struct device *dev = &client->dev;
-	const struct pmbus_platform_data *pdata = dev->platform_data;
+	const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
 	struct pmbus_data *data;
 	int ret;
 
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index a9f7e80..73bd64e 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -165,7 +165,7 @@ static ssize_t s3c_hwmon_ch_show(struct device *dev,
 {
 	struct sensor_device_attribute *sen_attr = to_sensor_dev_attr(attr);
 	struct s3c_hwmon *hwmon = platform_get_drvdata(to_platform_device(dev));
-	struct s3c_hwmon_pdata *pdata = dev->platform_data;
+	struct s3c_hwmon_pdata *pdata = dev_get_platdata(dev);
 	struct s3c_hwmon_chcfg *cfg;
 	int ret;
 
@@ -194,7 +194,7 @@ static ssize_t s3c_hwmon_label_show(struct device *dev,
 				    char *buf)
 {
 	struct sensor_device_attribute *sen_attr = to_sensor_dev_attr(attr);
-	struct s3c_hwmon_pdata *pdata = dev->platform_data;
+	struct s3c_hwmon_pdata *pdata = dev_get_platdata(dev);
 	struct s3c_hwmon_chcfg *cfg;
 
 	cfg = pdata->in[sen_attr->index];
@@ -274,7 +274,7 @@ static void s3c_hwmon_remove_attr(struct device *dev,
 */
 static int s3c_hwmon_probe(struct platform_device *dev)
 {
-	struct s3c_hwmon_pdata *pdata = dev->dev.platform_data;
+	struct s3c_hwmon_pdata *pdata = dev_get_platdata(&dev->dev);
 	struct s3c_hwmon *hwmon;
 	int ret = 0;
 	int i;
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 2507f90..883d291 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -940,11 +940,11 @@ static int sht15_probe(struct platform_device *pdev)
 	data->dev = &pdev->dev;
 	init_waitqueue_head(&data->wait_queue);
 
-	if (pdev->dev.platform_data == NULL) {
+	if (dev_get_platdata(&pdev->dev) == NULL) {
 		dev_err(&pdev->dev, "no platform data supplied\n");
 		return -EINVAL;
 	}
-	data->pdata = pdev->dev.platform_data;
+	data->pdata = dev_get_platdata(&pdev->dev);
 	data->supply_uv = data->pdata->supply_mv * 1000;
 	if (data->pdata->checksum)
 		data->checksumming = true;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 6d8255c..05cb814 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -668,7 +668,7 @@ static void smsc47m1_remove_files(struct device *dev)
 static int __init smsc47m1_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct smsc47m1_sio_data *sio_data = dev->platform_data;
+	struct smsc47m1_sio_data *sio_data = dev_get_platdata(dev);
 	struct smsc47m1_data *data;
 	struct resource *res;
 	int err;
@@ -940,7 +940,7 @@ exit_device:
 static void __exit sm_smsc47m1_exit(void)
 {
 	platform_driver_unregister(&smsc47m1_driver);
-	smsc47m1_restore(pdev->dev.platform_data);
+	smsc47m1_restore(dev_get_platdata(&pdev->dev));
 	platform_device_unregister(pdev);
 }
 
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 004801e..23ff210 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -673,7 +673,7 @@ static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr)
 static void w83627ehf_write_fan_div_common(struct device *dev,
 					   struct w83627ehf_data *data, int nr)
 {
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 
 	if (sio_data->kind == nct6776)
 		; /* no dividers, do nothing */
@@ -724,7 +724,7 @@ static void w83627ehf_update_fan_div(struct w83627ehf_data *data)
 static void w83627ehf_update_fan_div_common(struct device *dev,
 					    struct w83627ehf_data *data)
 {
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 
 	if (sio_data->kind == nct6776)
 		; /* no dividers, do nothing */
@@ -781,7 +781,7 @@ static void w83627ehf_update_pwm(struct w83627ehf_data *data)
 static void w83627ehf_update_pwm_common(struct device *dev,
 					struct w83627ehf_data *data)
 {
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 
 	if (sio_data->kind == nct6775 || sio_data->kind == nct6776)
 		nct6775_update_pwm(data);
@@ -792,7 +792,7 @@ static void w83627ehf_update_pwm_common(struct device *dev,
 static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 
 	int i;
 
@@ -1392,7 +1392,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 	int nr = sensor_attr->index;
 	unsigned long val;
 	int err;
@@ -1448,7 +1448,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	unsigned long val;
@@ -1527,7 +1527,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u16 reg;
@@ -2065,7 +2065,7 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
 static int w83627ehf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 	struct w83627ehf_data *data;
 	struct resource *res;
 	u8 en_vrm10;
@@ -2618,7 +2618,7 @@ static int w83627ehf_remove(struct platform_device *pdev)
 static int w83627ehf_suspend(struct device *dev)
 {
 	struct w83627ehf_data *data = w83627ehf_update_device(dev);
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 
 	mutex_lock(&data->update_lock);
 	data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
@@ -2634,7 +2634,7 @@ static int w83627ehf_suspend(struct device *dev)
 static int w83627ehf_resume(struct device *dev)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
-	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -2694,6 +2694,8 @@ static int w83627ehf_resume(struct device *dev)
 static const struct dev_pm_ops w83627ehf_dev_pm_ops = {
 	.suspend = w83627ehf_suspend,
 	.resume = w83627ehf_resume,
+	.freeze = w83627ehf_suspend,
+	.restore = w83627ehf_resume,
 };
 
 #define W83627EHF_DEV_PM_OPS	(&w83627ehf_dev_pm_ops)
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 3b9ef2d..cb9cd32 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -1415,7 +1415,7 @@ static const struct attribute_group w83627hf_group_opt = {
 static int w83627hf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct w83627hf_sio_data *sio_data = dev->platform_data;
+	struct w83627hf_sio_data *sio_data = dev_get_platdata(dev);
 	struct w83627hf_data *data;
 	struct resource *res;
 	int err, i;
@@ -1636,7 +1636,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
 
 static int w83627thf_read_gpio5(struct platform_device *pdev)
 {
-	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
+	struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev);
 	int res = 0xff, sel;
 
 	superio_enter(sio_data);
@@ -1669,7 +1669,7 @@ exit:
 
 static int w83687thf_read_vid(struct platform_device *pdev)
 {
-	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
+	struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev);
 	int res = 0xff;
 
 	superio_enter(sio_data);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 0b80489..5febb43 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -2,7 +2,7 @@
  * w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
  *	       monitoring
  * Copyright (C) 2004, 2005 Winbond Electronics Corp.
- *			    Chunhao Huang <DZShen@Winbond.com.tw>,
+ *			    Shane Huang,
  *			    Rudolf Marek <r.marek@assembler.cz>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -1665,6 +1665,6 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
 
 module_i2c_driver(w83792d_driver);
 
-MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>");
+MODULE_AUTHOR("Shane Huang (Winbond)");
 MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6");
 MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index ad46616..f325ec7 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -416,6 +416,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 	u32 addr = msgs[dev->msg_write_idx].addr;
 	u32 buf_len = dev->tx_buf_len;
 	u8 *buf = dev->tx_buf;
+	bool need_restart = false;
 
 	intr_mask = DW_IC_INTR_DEFAULT_MASK;
 
@@ -443,6 +444,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 			/* new i2c_msg */
 			buf = msgs[dev->msg_write_idx].buf;
 			buf_len = msgs[dev->msg_write_idx].len;
+
+			/* If both IC_EMPTYFIFO_HOLD_MASTER_EN and
+			 * IC_RESTART_EN are set, we must manually
+			 * set restart bit between messages.
+			 */
+			if ((dev->master_cfg & DW_IC_CON_RESTART_EN) &&
+					(dev->msg_write_idx > 0))
+				need_restart = true;
 		}
 
 		tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
@@ -461,6 +470,11 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 			    buf_len == 1)
 				cmd |= BIT(9);
 
+			if (need_restart) {
+				cmd |= BIT(10);
+				need_restart = false;
+			}
+
 			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
 
 				/* avoid rx buffer overrun */
diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c
index ccec916..af8f65f 100644
--- a/drivers/i2c/busses/i2c-kempld.c
+++ b/drivers/i2c/busses/i2c-kempld.c
@@ -246,9 +246,9 @@ static void kempld_i2c_device_init(struct kempld_i2c_data *i2c)
 		bus_frequency = KEMPLD_I2C_FREQ_MAX;
 
 	if (pld->info.spec_major == 1)
-		prescale = pld->pld_clock / bus_frequency * 5 - 1000;
+		prescale = pld->pld_clock / (bus_frequency * 5) - 1000;
 	else
-		prescale = pld->pld_clock / bus_frequency * 4 - 3000;
+		prescale = pld->pld_clock / (bus_frequency * 4) - 3000;
 
 	if (prescale < 0)
 		prescale = 0;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..99acf63 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -609,7 +609,6 @@ static const struct i2c_algorithm mpc_algo = {
 
 static struct i2c_adapter mpc_ops = {
 	.owner = THIS_MODULE,
-	.name = "MPC adapter",
 	.algo = &mpc_algo,
 	.timeout = HZ,
 };
@@ -623,6 +622,7 @@ static int fsl_i2c_probe(struct platform_device *op)
 	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
+	struct resource res;
 
 	match = of_match_device(mpc_i2c_of_match, &op->dev);
 	if (!match)
@@ -682,6 +682,9 @@ static int fsl_i2c_probe(struct platform_device *op)
 	platform_set_drvdata(op, i2c);
 
 	i2c->adap = mpc_ops;
+	of_address_to_resource(op->dev.of_node, 0, &res);
+	scnprintf(i2c->adap.name, sizeof(i2c->adap.name),
+		  "MPC adapter at 0x%llx", (unsigned long long)res.start);
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &op->dev;
 	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index df8ff5a..e2e9a0d 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -493,7 +493,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 	 * based on this empirical measurement and a lot of previous frobbing.
 	 */
 	i2c->cmd_err = 0;
-	if (msg->len < 8) {
+	if (0) {	/* disable PIO mode until a proper fix is made */
 		ret = mxs_i2c_pio_setup_xfer(adap, msg, flags);
 		if (ret)
 			mxs_i2c_reset(i2c);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 142b694d..d09512e 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
-#include <linux/pinctrl/consumer.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2		0x20
@@ -216,8 +215,6 @@ struct omap_i2c_dev {
 	u16			syscstate;
 	u16			westate;
 	u16			errata;
-
-	struct pinctrl		*pins;
 };
 
 static const u8 reg_map_ip_v1[] = {
@@ -1120,16 +1117,6 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
 	}
 
-	dev->pins = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(dev->pins)) {
-		if (PTR_ERR(dev->pins) == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-
-		dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n",
-			 PTR_ERR(dev->pins));
-		dev->pins = NULL;
-	}
-
 	dev->dev = &pdev->dev;
 	dev->irq = irq;
 
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index fbafed2..a61d906 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -110,6 +110,8 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
 #define ICR_SADIE	(1 << 13)	   /* slave address detected int enable */
 #define ICR_UR		(1 << 14)	   /* unit reset */
 #define ICR_FM		(1 << 15)	   /* fast mode */
+#define ICR_HS		(1 << 16)	   /* High Speed mode */
+#define ICR_GPIOEN	(1 << 19)	   /* enable GPIO mode for SCL in HS */
 
 #define ISR_RWM		(1 << 0)	   /* read/write mode */
 #define ISR_ACKNAK	(1 << 1)	   /* ack/nak status */
@@ -155,6 +157,10 @@ struct pxa_i2c {
 	int			irq;
 	unsigned int		use_pio :1;
 	unsigned int		fast_mode :1;
+	unsigned int		high_mode:1;
+	unsigned char		master_code;
+	unsigned long		rate;
+	bool			highmode_enter;
 };
 
 #define _IBMR(i2c)	((i2c)->reg_ibmr)
@@ -459,6 +465,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 
 	/* set control register values */
 	writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
+	writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
 
 #ifdef CONFIG_I2C_PXA_SLAVE
 	dev_info(&i2c->adap.dev, "Enabling slave mode\n");
@@ -680,6 +687,34 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
 	return 0;
 }
 
+/*
+ * PXA I2C send master code
+ * 1. Load master code to IDBR and send it.
+ *    Note for HS mode, set ICR [GPIOEN].
+ * 2. Wait until win arbitration.
+ */
+static int i2c_pxa_send_mastercode(struct pxa_i2c *i2c)
+{
+	u32 icr;
+	long timeout;
+
+	spin_lock_irq(&i2c->lock);
+	i2c->highmode_enter = true;
+	writel(i2c->master_code, _IDBR(i2c));
+
+	icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
+	icr |= ICR_GPIOEN | ICR_START | ICR_TB | ICR_ITEIE;
+	writel(icr, _ICR(i2c));
+
+	spin_unlock_irq(&i2c->lock);
+	timeout = wait_event_timeout(i2c->wait,
+			i2c->highmode_enter == false, HZ * 1);
+
+	i2c->highmode_enter = false;
+
+	return (timeout == 0) ? I2C_RETRY : 0;
+}
+
 static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
 			       struct i2c_msg *msg, int num)
 {
@@ -743,6 +778,14 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
 		goto out;
 	}
 
+	if (i2c->high_mode) {
+		ret = i2c_pxa_send_mastercode(i2c);
+		if (ret) {
+			dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n");
+			goto out;
+			}
+	}
+
 	spin_lock_irq(&i2c->lock);
 
 	i2c->msg = msg;
@@ -990,11 +1033,14 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 			i2c_pxa_slave_txempty(i2c, isr);
 		if (isr & ISR_IRF)
 			i2c_pxa_slave_rxfull(i2c, isr);
-	} else if (i2c->msg) {
+	} else if (i2c->msg && (!i2c->highmode_enter)) {
 		if (isr & ISR_ITE)
 			i2c_pxa_irq_txempty(i2c, isr);
 		if (isr & ISR_IRF)
 			i2c_pxa_irq_rxfull(i2c, isr);
+	} else if ((isr & ISR_ITE) && i2c->highmode_enter) {
+		i2c->highmode_enter = false;
+		wake_up(&i2c->wait);
 	} else {
 		i2c_pxa_scream_blue_murder(i2c, "spurious irq");
 	}
@@ -1079,6 +1125,11 @@ static int i2c_pxa_probe_pdata(struct platform_device *pdev,
 	if (plat) {
 		i2c->use_pio = plat->use_pio;
 		i2c->fast_mode = plat->fast_mode;
+		i2c->high_mode = plat->high_mode;
+		i2c->master_code = plat->master_code;
+		if (!i2c->master_code)
+			i2c->master_code = 0xe;
+		i2c->rate = plat->rate;
 	}
 	return 0;
 }
@@ -1151,6 +1202,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	i2c->irq = irq;
 
 	i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
+	i2c->highmode_enter = false;
 
 	if (plat) {
 #ifdef CONFIG_I2C_PXA_SLAVE
@@ -1160,6 +1212,16 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		i2c->adap.class = plat->class;
 	}
 
+	if (i2c->high_mode) {
+		if (i2c->rate) {
+			clk_set_rate(i2c->clk, i2c->rate);
+			pr_info("i2c: <%s> set rate to %ld\n",
+				i2c->adap.name, clk_get_rate(i2c->clk));
+		} else
+			pr_warn("i2c: <%s> clock rate not set\n",
+				i2c->adap.name);
+	}
+
 	clk_prepare_enable(i2c->clk);
 
 	if (i2c->use_pio) {
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index d1a6b20..ded21cf 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -884,9 +884,6 @@ stu300_probe(struct platform_device *pdev)
 
 	dev->pdev = pdev;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOENT;
-
 	dev->virtbase = devm_ioremap_resource(&pdev->dev, res);
 	dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual "
 		"base %p\n", bus_nr, dev->virtbase);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index f32ca29..d075df6 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1825,7 +1825,8 @@ EXPORT_SYMBOL(i2c_get_adapter);
 
 void i2c_put_adapter(struct i2c_adapter *adap)
 {
-	module_put(adap->owner);
+	if (adap)
+		module_put(adap->owner);
 }
 EXPORT_SYMBOL(i2c_put_adapter);
 
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index f1a6796b..140c8ef 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -520,11 +520,12 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
 	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_COLD);
 	}
 
 	if (!on)
-		acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
+		acpi_bus_set_power(hwif->acpidata->obj_handle,
+				   ACPI_STATE_D3_COLD);
 }
 
 /**
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 9af763a..524380c 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -23,15 +23,14 @@ if IIO_BUFFER
 config IIO_BUFFER_CB
 boolean "IIO callback buffer used for push in-kernel interfaces"
 	help
-	  Should be selected by any drivers that do-inkernel push
+	  Should be selected by any drivers that do in-kernel push
 	  usage.  That is, those where the data is pushed to the consumer.
 
 config IIO_KFIFO_BUF
 	select IIO_TRIGGER
 	tristate "Industrial I/O buffering based on kfifo"
 	help
-	  A simple fifo based on kfifo.  Use this if you want a fifo
-	  rather than a ring buffer. Note that this currently provides
+	  A simple fifo based on kfifo.  Note that this currently provides
 	  no buffer events so it is up to userspace to work out how
 	  often to read from the buffer.
 
@@ -49,7 +48,7 @@ config IIO_TRIGGER
 	help
 	  Provides IIO core support for triggers.  Currently these
 	  are used to initialize capture of samples to push into
-	  ring buffers.  The triggers are effectively a 'capture
+	  buffers.  The triggers are effectively a 'capture
 	  data now' interrupt.
 
 config IIO_CONSUMERS_PER_TRIGGER
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 719d83f..61ca7ec 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -1,6 +1,8 @@
 #
 # Accelerometer drivers
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Accelerometers"
 
 config HID_SENSOR_ACCEL_3D
@@ -14,13 +16,6 @@ config HID_SENSOR_ACCEL_3D
 	  Say yes here to build support for the HID SENSOR
 	  accelerometers 3D.
 
-config KXSD9
-	tristate "Kionix KXSD9 Accelerometer Driver"
-	depends on SPI
-	help
-	  Say yes here to build support for the Kionix KXSD9 accelerometer.
-	  Currently this only supports the device via an SPI interface.
-
 config IIO_ST_ACCEL_3AXIS
 	tristate "STMicroelectronics accelerometers 3-Axis Driver"
 	depends on (I2C || SPI_MASTER) && SYSFS
@@ -33,8 +28,8 @@ config IIO_ST_ACCEL_3AXIS
 	  LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
 	  LIS331DLH, LSM303DL, LSM303DLM, LSM330.
 
-	  This driver can also be built as a module. If so, will be created
-	  these modules:
+	  This driver can also be built as a module. If so, these modules
+	  will be created:
 	  - st_accel (core functions for the driver [it is mandatory]);
 	  - st_accel_i2c (necessary for the I2C devices [optional*]);
 	  - st_accel_spi (necessary for the SPI devices [optional*]);
@@ -51,4 +46,11 @@ config IIO_ST_ACCEL_SPI_3AXIS
 	depends on IIO_ST_ACCEL_3AXIS
 	depends on IIO_ST_SENSORS_SPI
 
+config KXSD9
+	tristate "Kionix KXSD9 Accelerometer Driver"
+	depends on SPI
+	help
+	  Say yes here to build support for the Kionix KXSD9 accelerometer.
+	  Currently this only supports the device via an SPI interface.
+
 endmenu
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 87d8fa2..2f95a3d 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -2,7 +2,9 @@
 # Makefile for industrial I/O accelerometer drivers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
+obj-$(CONFIG_KXSD9)	+= kxsd9.o
 
 obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
 st_accel-y := st_accel_core.o
@@ -10,5 +12,3 @@ st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o
 
 obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o
 obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o
-
-obj-$(CONFIG_KXSD9)	+= kxsd9.o
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index bbcbd71..68df341 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -30,10 +30,6 @@
 #include <linux/iio/triggered_buffer.h>
 #include "../common/hid-sensors/hid-sensor-trigger.h"
 
-/*Format: HID-SENSOR-usage_id_in_hex*/
-/*Usage ID from spec for Accelerometer-3D: 0x200073*/
-#define DRIVER_NAME "HID-SENSOR-200073"
-
 enum accel_3d_channel {
 	CHANNEL_SCAN_INDEX_X,
 	CHANNEL_SCAN_INDEX_Y,
@@ -286,11 +282,11 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
 	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 	struct iio_chan_spec *channels;
 
-	indio_dev = iio_device_alloc(sizeof(struct accel_3d_state));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+					  sizeof(struct accel_3d_state));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	accel_state = iio_priv(indio_dev);
@@ -302,15 +298,14 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
 					&accel_state->common_attributes);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to setup common attributes\n");
-		goto error_free_dev;
+		return ret;
 	}
 
 	channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels),
 			   GFP_KERNEL);
 	if (!channels) {
-		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
-		goto error_free_dev;
+		return -ENOMEM;
 	}
 
 	ret = accel_3d_parse_report(pdev, hsdev, channels,
@@ -367,9 +362,6 @@ error_unreg_buffer_funcs:
 	iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
 	kfree(indio_dev->channels);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
 	return ret;
 }
 
@@ -384,14 +376,23 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
 	hid_sensor_remove_trigger(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	kfree(indio_dev->channels);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
 
+static struct platform_device_id hid_accel_3d_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-200073",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids);
+
 static struct platform_driver hid_accel_3d_platform_driver = {
+	.id_table = hid_accel_3d_ids,
 	.driver = {
-		.name	= DRIVER_NAME,
+		.name	= KBUILD_MODNAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= hid_accel_3d_probe,
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 7229645..709c132 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -224,11 +224,10 @@ static int kxsd9_probe(struct spi_device *spi)
 	struct kxsd9_state *st;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
 	st = iio_priv(indio_dev);
 	spi_set_drvdata(spi, indio_dev);
 
@@ -247,20 +246,14 @@ static int kxsd9_probe(struct spi_device *spi)
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
 }
 
 static int kxsd9_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
index 37949b9..c387763 100644
--- a/drivers/iio/accel/st_accel.h
+++ b/drivers/iio/accel/st_accel.h
@@ -25,7 +25,16 @@
 #define LSM303DLM_ACCEL_DEV_NAME	"lsm303dlm_accel"
 #define LSM330_ACCEL_DEV_NAME		"lsm330_accel"
 
-int st_accel_common_probe(struct iio_dev *indio_dev);
+/**
+* struct st_sensors_platform_data - default accel platform data
+* @drdy_int_pin: default accel DRDY is available on INT1 pin.
+*/
+static const struct st_sensors_platform_data default_accel_pdata = {
+	.drdy_int_pin = 1,
+};
+
+int st_accel_common_probe(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata);
 void st_accel_common_remove(struct iio_dev *indio_dev);
 
 #ifdef CONFIG_IIO_BUFFER
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 4aec121..1458343 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -65,7 +65,8 @@
 #define ST_ACCEL_1_BDU_ADDR			0x23
 #define ST_ACCEL_1_BDU_MASK			0x80
 #define ST_ACCEL_1_DRDY_IRQ_ADDR		0x22
-#define ST_ACCEL_1_DRDY_IRQ_MASK		0x10
+#define ST_ACCEL_1_DRDY_IRQ_INT1_MASK		0x10
+#define ST_ACCEL_1_DRDY_IRQ_INT2_MASK		0x08
 #define ST_ACCEL_1_MULTIREAD_BIT		true
 
 /* CUSTOM VALUES FOR SENSOR 2 */
@@ -89,7 +90,8 @@
 #define ST_ACCEL_2_BDU_ADDR			0x23
 #define ST_ACCEL_2_BDU_MASK			0x80
 #define ST_ACCEL_2_DRDY_IRQ_ADDR		0x22
-#define ST_ACCEL_2_DRDY_IRQ_MASK		0x02
+#define ST_ACCEL_2_DRDY_IRQ_INT1_MASK		0x02
+#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK		0x10
 #define ST_ACCEL_2_MULTIREAD_BIT		true
 
 /* CUSTOM VALUES FOR SENSOR 3 */
@@ -121,7 +123,8 @@
 #define ST_ACCEL_3_BDU_ADDR			0x20
 #define ST_ACCEL_3_BDU_MASK			0x08
 #define ST_ACCEL_3_DRDY_IRQ_ADDR		0x23
-#define ST_ACCEL_3_DRDY_IRQ_MASK		0x80
+#define ST_ACCEL_3_DRDY_IRQ_INT1_MASK		0x80
+#define ST_ACCEL_3_DRDY_IRQ_INT2_MASK		0x00
 #define ST_ACCEL_3_IG1_EN_ADDR			0x23
 #define ST_ACCEL_3_IG1_EN_MASK			0x08
 #define ST_ACCEL_3_MULTIREAD_BIT		false
@@ -224,7 +227,8 @@ static const struct st_sensors st_accel_sensors[] = {
 		},
 		.drdy_irq = {
 			.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
-			.mask = ST_ACCEL_1_DRDY_IRQ_MASK,
+			.mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
 		},
 		.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
 		.bootime = 2,
@@ -285,7 +289,8 @@ static const struct st_sensors st_accel_sensors[] = {
 		},
 		.drdy_irq = {
 			.addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
-			.mask = ST_ACCEL_2_DRDY_IRQ_MASK,
+			.mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
 		},
 		.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
 		.bootime = 2,
@@ -358,7 +363,8 @@ static const struct st_sensors st_accel_sensors[] = {
 		},
 		.drdy_irq = {
 			.addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
-			.mask = ST_ACCEL_3_DRDY_IRQ_MASK,
+			.mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
 			.ig1 = {
 				.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
 				.en_mask = ST_ACCEL_3_IG1_EN_MASK,
@@ -443,7 +449,8 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
 #define ST_ACCEL_TRIGGER_OPS NULL
 #endif
 
-int st_accel_common_probe(struct iio_dev *indio_dev)
+int st_accel_common_probe(struct iio_dev *indio_dev,
+				struct st_sensors_platform_data *plat_data)
 {
 	int err;
 	struct st_sensor_data *adata = iio_priv(indio_dev);
@@ -465,7 +472,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
 						&adata->sensor->fs.fs_avl[0];
 	adata->odr = adata->sensor->odr.odr_avl[0].hz;
 
-	err = st_sensors_init_sensor(indio_dev);
+	if (!plat_data)
+		plat_data =
+			(struct st_sensors_platform_data *)&default_accel_pdata;
+
+	err = st_sensors_init_sensor(indio_dev, plat_data);
 	if (err < 0)
 		goto st_accel_common_probe_error;
 
@@ -506,7 +517,6 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
 		st_sensors_deallocate_trigger(indio_dev);
 		st_accel_deallocate_ring(indio_dev);
 	}
-	iio_device_free(indio_dev);
 }
 EXPORT_SYMBOL(st_accel_common_remove);
 
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index ffc9d09..d7bedbd 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -25,27 +25,20 @@ static int st_accel_i2c_probe(struct i2c_client *client,
 	struct st_sensor_data *adata;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*adata));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto iio_device_alloc_error;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	adata = iio_priv(indio_dev);
 	adata->dev = &client->dev;
 
 	st_sensors_i2c_configure(indio_dev, client, adata);
 
-	err = st_accel_common_probe(indio_dev);
+	err = st_accel_common_probe(indio_dev, client->dev.platform_data);
 	if (err < 0)
-		goto st_accel_common_probe_error;
+		return err;
 
 	return 0;
-
-st_accel_common_probe_error:
-	iio_device_free(indio_dev);
-iio_device_alloc_error:
-	return err;
 }
 
 static int st_accel_i2c_remove(struct i2c_client *client)
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index 22b35bf..1956396 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -24,27 +24,20 @@ static int st_accel_spi_probe(struct spi_device *spi)
 	struct st_sensor_data *adata;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*adata));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto iio_device_alloc_error;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	adata = iio_priv(indio_dev);
 	adata->dev = &spi->dev;
 
 	st_sensors_spi_configure(indio_dev, spi, adata);
 
-	err = st_accel_common_probe(indio_dev);
+	err = st_accel_common_probe(indio_dev, spi->dev.platform_data);
 	if (err < 0)
-		goto st_accel_common_probe_error;
+		return err;
 
 	return 0;
-
-st_accel_common_probe_error:
-	iio_device_free(indio_dev);
-iio_device_alloc_error:
-	return err;
 }
 
 static int st_accel_spi_remove(struct spi_device *spi)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 93129ec..f725b45 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1,6 +1,8 @@
 #
 # ADC drivers
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Analog to digital converters"
 
 config AD_SIGMA_DELTA
@@ -30,17 +32,20 @@ config AD7298
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7298.
 
-config AD7923
-	tristate "Analog Devices AD7923 and similar ADCs driver"
+config AD7476
+	tristate "Analog Devices AD7476 and similar 1-channel ADCs driver"
 	depends on SPI
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
-	  Say yes here to build support for Analog Devices
-	  AD7904, AD7914, AD7923, AD7924 4 Channel ADCs.
+	  Say yes here to build support for Analog Devices AD7273, AD7274, AD7276,
+	  AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
+	  AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
+
+	  If unsure, say N (but it's safe to say "Y").
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ad7923.
+	  module will be called ad7476.
 
 config AD7791
 	tristate "Analog Devices AD7791 ADC driver"
@@ -66,33 +71,30 @@ config AD7793
 	  To compile this driver as a module, choose M here: the
 	  module will be called AD7793.
 
-config AD7476
-	tristate "Analog Devices AD7476 and similar 1-channel ADCs driver"
+config AD7887
+	tristate "Analog Devices AD7887 ADC driver"
 	depends on SPI
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
-	  Say yes here to build support for Analog Devices AD7273, AD7274, AD7276,
-	  AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
-	  AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
-
+	  Say yes here to build support for Analog Devices
+	  AD7887 SPI analog to digital converter (ADC).
 	  If unsure, say N (but it's safe to say "Y").
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ad7476.
+	  module will be called ad7887.
 
-config AD7887
-	tristate "Analog Devices AD7887 ADC driver"
+config AD7923
+	tristate "Analog Devices AD7923 and similar ADCs driver"
 	depends on SPI
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Analog Devices
-	  AD7887 SPI analog to digital converter (ADC).
-	  If unsure, say N (but it's safe to say "Y").
+	  AD7904, AD7914, AD7923, AD7924 4 Channel ADCs.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ad7887.
+	  module will be called ad7923.
 
 config AT91_ADC
 	tristate "Atmel AT91 ADC"
@@ -143,6 +145,15 @@ config MCP320X
 	  This driver can also be built as a module. If so, the module will be
 	  called mcp320x.
 
+config NAU7802
+	tristate "Nuvoton NAU7802 ADC driver"
+	depends on I2C
+	help
+	  Say yes here to build support for Nuvoton NAU7802 ADC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called nau7802.
+
 config TI_ADC081C
 	tristate "Texas Instruments ADC081C021/027"
 	depends on I2C
@@ -154,7 +165,7 @@ config TI_ADC081C
 	  called ti-adc081c.
 
 config TI_AM335X_ADC
-	tristate "TI's ADC driver"
+	tristate "TI's AM335X ADC driver"
 	depends on MFD_TI_AM335X_TSCADC
 	help
 	  Say yes here to build support for Texas Instruments ADC
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 8f475d3..2a4324e 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -2,6 +2,7 @@
 # Makefile for IIO ADC drivers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
 obj-$(CONFIG_AD7298) += ad7298.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
+obj-$(CONFIG_NAU7802) += nau7802.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index c2744a7..371731d 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -399,17 +399,17 @@ static int ad7266_probe(struct spi_device *spi)
 	unsigned int i;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "vref");
+	st->reg = devm_regulator_get(&spi->dev, "vref");
 	if (!IS_ERR_OR_NULL(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 
 		ret = regulator_get_voltage(st->reg);
 		if (ret < 0)
@@ -489,11 +489,6 @@ error_free_gpios:
 error_disable_reg:
 	if (!IS_ERR_OR_NULL(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR_OR_NULL(st->reg))
-		regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -507,11 +502,8 @@ static int ad7266_remove(struct spi_device *spi)
 	iio_triggered_buffer_cleanup(indio_dev);
 	if (!st->fixed_addr)
 		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
-	if (!IS_ERR_OR_NULL(st->reg)) {
+	if (!IS_ERR_OR_NULL(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index 03b7718..85d1481 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -296,9 +296,10 @@ static int ad7298_probe(struct spi_device *spi)
 {
 	struct ad7298_platform_data *pdata = spi->dev.platform_data;
 	struct ad7298_state *st;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 	int ret;
 
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -308,14 +309,13 @@ static int ad7298_probe(struct spi_device *spi)
 		st->ext_ref = AD7298_EXTREF;
 
 	if (st->ext_ref) {
-		st->reg = regulator_get(&spi->dev, "vref");
-		if (IS_ERR(st->reg)) {
-			ret = PTR_ERR(st->reg);
-			goto error_free;
-		}
+		st->reg = devm_regulator_get(&spi->dev, "vref");
+		if (IS_ERR(st->reg))
+			return PTR_ERR(st->reg);
+
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
 	spi_set_drvdata(spi, indio_dev);
@@ -361,11 +361,6 @@ error_cleanup_ring:
 error_disable_reg:
 	if (st->ext_ref)
 		regulator_disable(st->reg);
-error_put_reg:
-	if (st->ext_ref)
-		regulator_put(st->reg);
-error_free:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -377,11 +372,8 @@ static int ad7298_remove(struct spi_device *spi)
 
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
-	if (st->ext_ref) {
+	if (st->ext_ref)
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 2e98bef4..6d2b1d8 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -213,24 +213,21 @@ static int ad7476_probe(struct spi_device *spi)
 	struct iio_dev *indio_dev;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
 	st = iio_priv(indio_dev);
 	st->chip_info =
 		&ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (IS_ERR(st->reg)) {
-		ret = PTR_ERR(st->reg);
-		goto error_free_dev;
-	}
+	st->reg = devm_regulator_get(&spi->dev, "vcc");
+	if (IS_ERR(st->reg))
+		return PTR_ERR(st->reg);
 
 	ret = regulator_enable(st->reg);
 	if (ret)
-		goto error_put_reg;
+		return ret;
 
 	spi_set_drvdata(spi, indio_dev);
 
@@ -268,12 +265,7 @@ error_ring_unregister:
 	iio_triggered_buffer_cleanup(indio_dev);
 error_disable_reg:
 	regulator_disable(st->reg);
-error_put_reg:
-	regulator_put(st->reg);
-error_free_dev:
-	iio_device_free(indio_dev);
 
-error_ret:
 	return ret;
 }
 
@@ -285,8 +277,6 @@ static int ad7476_remove(struct spi_device *spi)
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	regulator_disable(st->reg);
-	regulator_put(st->reg);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index 5e8d1da..c202035 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -361,21 +361,19 @@ static int ad7791_probe(struct spi_device *spi)
 		return -ENXIO;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (!indio_dev)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "refin");
-	if (IS_ERR(st->reg)) {
-		ret = PTR_ERR(st->reg);
-		goto err_iio_free;
-	}
+	st->reg = devm_regulator_get(&spi->dev, "refin");
+	if (IS_ERR(st->reg))
+		return PTR_ERR(st->reg);
 
 	ret = regulator_enable(st->reg);
 	if (ret)
-		goto error_put_reg;
+		return ret;
 
 	st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data];
 	ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info);
@@ -410,10 +408,6 @@ error_remove_trigger:
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 error_disable_reg:
 	regulator_disable(st->reg);
-error_put_reg:
-	regulator_put(st->reg);
-err_iio_free:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -427,9 +421,6 @@ static int ad7791_remove(struct spi_device *spi)
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 
 	regulator_disable(st->reg);
-	regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index 334e31f..4dddeab 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -757,7 +757,7 @@ static int ad7793_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -766,15 +766,13 @@ static int ad7793_probe(struct spi_device *spi)
 	ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info);
 
 	if (pdata->refsel != AD7793_REFSEL_INTERNAL) {
-		st->reg = regulator_get(&spi->dev, "refin");
-		if (IS_ERR(st->reg)) {
-			ret = PTR_ERR(st->reg);
-			goto error_device_free;
-		}
+		st->reg = devm_regulator_get(&spi->dev, "refin");
+		if (IS_ERR(st->reg))
+			return PTR_ERR(st->reg);
 
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 
 		vref_mv = regulator_get_voltage(st->reg);
 		if (vref_mv < 0) {
@@ -818,11 +816,6 @@ error_remove_trigger:
 error_disable_reg:
 	if (pdata->refsel != AD7793_REFSEL_INTERNAL)
 		regulator_disable(st->reg);
-error_put_reg:
-	if (pdata->refsel != AD7793_REFSEL_INTERNAL)
-		regulator_put(st->reg);
-error_device_free:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -836,12 +829,8 @@ static int ad7793_remove(struct spi_device *spi)
 	iio_device_unregister(indio_dev);
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 
-	if (pdata->refsel != AD7793_REFSEL_INTERNAL) {
+	if (pdata->refsel != AD7793_REFSEL_INTERNAL)
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index dd15a5b..9dd077b 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -237,25 +237,24 @@ static int ad7887_probe(struct spi_device *spi)
 {
 	struct ad7887_platform_data *pdata = spi->dev.platform_data;
 	struct ad7887_state *st;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 	uint8_t mode;
 	int ret;
 
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
 	if (!pdata || !pdata->use_onchip_ref) {
-		st->reg = regulator_get(&spi->dev, "vref");
-		if (IS_ERR(st->reg)) {
-			ret = PTR_ERR(st->reg);
-			goto error_free;
-		}
+		st->reg = devm_regulator_get(&spi->dev, "vref");
+		if (IS_ERR(st->reg))
+			return PTR_ERR(st->reg);
 
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
 	st->chip_info =
@@ -331,11 +330,6 @@ error_unregister_ring:
 error_disable_reg:
 	if (st->reg)
 		regulator_disable(st->reg);
-error_put_reg:
-	if (st->reg)
-		regulator_put(st->reg);
-error_free:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -347,11 +341,8 @@ static int ad7887_remove(struct spi_device *spi)
 
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
-	if (st->reg) {
+	if (st->reg)
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 97fa0d3..4108dbb 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -275,10 +275,11 @@ static const struct iio_info ad7923_info = {
 static int ad7923_probe(struct spi_device *spi)
 {
 	struct ad7923_state *st;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 	const struct ad7923_chip_info *info;
 	int ret;
 
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -311,14 +312,13 @@ static int ad7923_probe(struct spi_device *spi)
 	spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
 	spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
 
-	st->reg = regulator_get(&spi->dev, "refin");
-	if (IS_ERR(st->reg)) {
-		ret = PTR_ERR(st->reg);
-		goto error_free;
-	}
+	st->reg = devm_regulator_get(&spi->dev, "refin");
+	if (IS_ERR(st->reg))
+		return PTR_ERR(st->reg);
+
 	ret = regulator_enable(st->reg);
 	if (ret)
-		goto error_put_reg;
+		return ret;
 
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
 			&ad7923_trigger_handler, NULL);
@@ -335,10 +335,6 @@ error_cleanup_ring:
 	iio_triggered_buffer_cleanup(indio_dev);
 error_disable_reg:
 	regulator_disable(st->reg);
-error_put_reg:
-	regulator_put(st->reg);
-error_free:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -351,8 +347,6 @@ static int ad7923_remove(struct spi_device *spi)
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	regulator_disable(st->reg);
-	regulator_put(st->reg);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index b6db6a0..423e079 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -589,11 +589,9 @@ static int at91_adc_probe(struct platform_device *pdev)
 	struct resource *res;
 	u32 reg;
 
-	idev = iio_device_alloc(sizeof(struct at91_adc_state));
-	if (idev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	idev = devm_iio_device_alloc(&pdev->dev, sizeof(struct at91_adc_state));
+	if (!idev)
+		return -ENOMEM;
 
 	st = iio_priv(idev);
 
@@ -604,8 +602,7 @@ static int at91_adc_probe(struct platform_device *pdev)
 
 	if (ret) {
 		dev_err(&pdev->dev, "No platform data available.\n");
-		ret = -EINVAL;
-		goto error_free_device;
+		return -EINVAL;
 	}
 
 	platform_set_drvdata(pdev, idev);
@@ -618,16 +615,14 @@ static int at91_adc_probe(struct platform_device *pdev)
 	st->irq = platform_get_irq(pdev, 0);
 	if (st->irq < 0) {
 		dev_err(&pdev->dev, "No IRQ ID is designated\n");
-		ret = -ENODEV;
-		goto error_free_device;
+		return -ENODEV;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	st->reg_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(st->reg_base)) {
-		ret = PTR_ERR(st->reg_base);
-		goto error_free_device;
+		return PTR_ERR(st->reg_base);
 	}
 
 	/*
@@ -642,7 +637,7 @@ static int at91_adc_probe(struct platform_device *pdev)
 			  idev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
-		goto error_free_device;
+		return ret;
 	}
 
 	st->clk = devm_clk_get(&pdev->dev, "adc_clk");
@@ -752,9 +747,6 @@ error_disable_clk:
 	clk_disable_unprepare(st->clk);
 error_free_irq:
 	free_irq(st->irq, idev);
-error_free_device:
-	iio_device_free(idev);
-error_ret:
 	return ret;
 }
 
@@ -769,7 +761,6 @@ static int at91_adc_remove(struct platform_device *pdev)
 	clk_disable_unprepare(st->adc_clk);
 	clk_disable_unprepare(st->clk);
 	free_irq(st->irq, idev);
-	iio_device_free(idev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 9809fc9..d25b262 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -33,6 +33,7 @@
 #include <linux/of_irq.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_platform.h>
+#include <linux/err.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/machine.h>
@@ -261,7 +262,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
 	if (!np)
 		return ret;
 
-	indio_dev = iio_device_alloc(sizeof(struct exynos_adc));
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc));
 	if (!indio_dev) {
 		dev_err(&pdev->dev, "failed allocating iio device\n");
 		return -ENOMEM;
@@ -271,23 +272,18 @@ static int exynos_adc_probe(struct platform_device *pdev)
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	info->regs = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(info->regs)) {
-		ret = PTR_ERR(info->regs);
-		goto err_iio;
-	}
+	if (IS_ERR(info->regs))
+		return PTR_ERR(info->regs);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(info->enable_reg)) {
-		ret = PTR_ERR(info->enable_reg);
-		goto err_iio;
-	}
+	if (IS_ERR(info->enable_reg))
+		return PTR_ERR(info->enable_reg);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no irq resource?\n");
-		ret = irq;
-		goto err_iio;
+		return irq;
 	}
 
 	info->irq = irq;
@@ -299,7 +295,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
 							info->irq);
-		goto err_iio;
+		return ret;
 	}
 
 	writel(1, info->enable_reg);
@@ -365,8 +361,6 @@ err_iio_dev:
 	iio_device_unregister(indio_dev);
 err_irq:
 	free_irq(info->irq, info);
-err_iio:
-	iio_device_free(indio_dev);
 	return ret;
 }
 
@@ -382,7 +376,6 @@ static int exynos_adc_remove(struct platform_device *pdev)
 	writel(0, info->enable_reg);
 	iio_device_unregister(indio_dev);
 	free_irq(info->irq, info);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index 62bc39e..5c8c915 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -194,7 +194,7 @@ static int lp8788_adc_probe(struct platform_device *pdev)
 	struct lp8788_adc *adc;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*adc));
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -205,7 +205,7 @@ static int lp8788_adc_probe(struct platform_device *pdev)
 	indio_dev->dev.of_node = pdev->dev.of_node;
 	ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc);
 	if (ret)
-		goto err_iio_map;
+		return ret;
 
 	mutex_init(&adc->lock);
 
@@ -226,8 +226,6 @@ static int lp8788_adc_probe(struct platform_device *pdev)
 
 err_iio_device:
 	iio_map_array_unregister(indio_dev);
-err_iio_map:
-	iio_device_free(indio_dev);
 	return ret;
 }
 
@@ -237,7 +235,6 @@ static int lp8788_adc_remove(struct platform_device *pdev)
 
 	iio_device_unregister(indio_dev);
 	iio_map_array_unregister(indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index f148d00..4fb35d1 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -1498,16 +1498,15 @@ static int max1363_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	struct regulator *vref;
 
-	indio_dev = iio_device_alloc(sizeof(struct max1363_state));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_out;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev,
+					  sizeof(struct max1363_state));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	indio_dev->dev.of_node = client->dev.of_node;
 	ret = iio_map_array_register(indio_dev, client->dev.platform_data);
 	if (ret < 0)
-		goto error_free_device;
+		return ret;
 
 	st = iio_priv(indio_dev);
 
@@ -1590,9 +1589,6 @@ error_disable_reg:
 	regulator_disable(st->reg);
 error_unregister_map:
 	iio_map_array_unregister(indio_dev);
-error_free_device:
-	iio_device_free(indio_dev);
-error_out:
 	return ret;
 }
 
@@ -1607,7 +1603,6 @@ static int max1363_remove(struct i2c_client *client)
 		regulator_disable(st->vref);
 	regulator_disable(st->reg);
 	iio_map_array_unregister(indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index ebc0159..28a086e 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -169,7 +169,7 @@ static int mcp320x_probe(struct spi_device *spi)
 	const struct mcp3208_chip_info *chip_info;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*adc));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -193,15 +193,13 @@ static int mcp320x_probe(struct spi_device *spi)
 	spi_message_init_with_transfers(&adc->msg, adc->transfer,
 					ARRAY_SIZE(adc->transfer));
 
-	adc->reg = regulator_get(&spi->dev, "vref");
-	if (IS_ERR(adc->reg)) {
-		ret = PTR_ERR(adc->reg);
-		goto iio_free;
-	}
+	adc->reg = devm_regulator_get(&spi->dev, "vref");
+	if (IS_ERR(adc->reg))
+		return PTR_ERR(adc->reg);
 
 	ret = regulator_enable(adc->reg);
 	if (ret < 0)
-		goto reg_free;
+		return ret;
 
 	mutex_init(&adc->lock);
 
@@ -213,10 +211,6 @@ static int mcp320x_probe(struct spi_device *spi)
 
 reg_disable:
 	regulator_disable(adc->reg);
-reg_free:
-	regulator_put(adc->reg);
-iio_free:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -228,8 +222,6 @@ static int mcp320x_remove(struct spi_device *spi)
 
 	iio_device_unregister(indio_dev);
 	regulator_disable(adc->reg);
-	regulator_put(adc->reg);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c
new file mode 100644
index 0000000..bdf0346
--- /dev/null
+++ b/drivers/iio/adc/nau7802.c
@@ -0,0 +1,581 @@
+/*
+ * Driver for the Nuvoton NAU7802 ADC
+ *
+ * Copyright 2013 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/log2.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define NAU7802_REG_PUCTRL	0x00
+#define NAU7802_PUCTRL_RR(x)		(x << 0)
+#define NAU7802_PUCTRL_RR_BIT		NAU7802_PUCTRL_RR(1)
+#define NAU7802_PUCTRL_PUD(x)		(x << 1)
+#define NAU7802_PUCTRL_PUD_BIT		NAU7802_PUCTRL_PUD(1)
+#define NAU7802_PUCTRL_PUA(x)		(x << 2)
+#define NAU7802_PUCTRL_PUA_BIT		NAU7802_PUCTRL_PUA(1)
+#define NAU7802_PUCTRL_PUR(x)		(x << 3)
+#define NAU7802_PUCTRL_PUR_BIT		NAU7802_PUCTRL_PUR(1)
+#define NAU7802_PUCTRL_CS(x)		(x << 4)
+#define NAU7802_PUCTRL_CS_BIT		NAU7802_PUCTRL_CS(1)
+#define NAU7802_PUCTRL_CR(x)		(x << 5)
+#define NAU7802_PUCTRL_CR_BIT		NAU7802_PUCTRL_CR(1)
+#define NAU7802_PUCTRL_AVDDS(x)		(x << 7)
+#define NAU7802_PUCTRL_AVDDS_BIT	NAU7802_PUCTRL_AVDDS(1)
+#define NAU7802_REG_CTRL1	0x01
+#define NAU7802_CTRL1_VLDO(x)		(x << 3)
+#define NAU7802_CTRL1_GAINS(x)		(x)
+#define NAU7802_CTRL1_GAINS_BITS	0x07
+#define NAU7802_REG_CTRL2	0x02
+#define NAU7802_CTRL2_CHS(x)		(x << 7)
+#define NAU7802_CTRL2_CRS(x)		(x << 4)
+#define NAU7802_SAMP_FREQ_320	0x07
+#define NAU7802_CTRL2_CHS_BIT		NAU7802_CTRL2_CHS(1)
+#define NAU7802_REG_ADC_B2	0x12
+#define NAU7802_REG_ADC_B1	0x13
+#define NAU7802_REG_ADC_B0	0x14
+#define NAU7802_REG_ADC_CTRL	0x15
+
+#define NAU7802_MIN_CONVERSIONS 6
+
+struct nau7802_state {
+	struct i2c_client	*client;
+	s32			last_value;
+	struct mutex		lock;
+	struct mutex		data_lock;
+	u32			vref_mv;
+	u32			conversion_count;
+	u32			min_conversions;
+	u8			sample_rate;
+	u32			scale_avail[8];
+	struct completion	value_ok;
+};
+
+#define NAU7802_CHANNEL(chan) {					\
+	.type = IIO_VOLTAGE,					\
+	.indexed = 1,						\
+	.channel = (chan),					\
+	.scan_index = (chan),					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
+				BIT(IIO_CHAN_INFO_SAMP_FREQ)	\
+}
+
+static const struct iio_chan_spec nau7802_chan_array[] = {
+	NAU7802_CHANNEL(0),
+	NAU7802_CHANNEL(1),
+};
+
+static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80,
+						10, 10, 10, 320};
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320");
+
+static struct attribute *nau7802_attributes[] = {
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group nau7802_attribute_group = {
+	.attrs = nau7802_attributes,
+};
+
+static int nau7802_set_gain(struct nau7802_state *st, int gain)
+{
+	int ret;
+
+	mutex_lock(&st->lock);
+	st->conversion_count = 0;
+
+	ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_CTRL1);
+	if (ret < 0)
+		goto nau7802_sysfs_set_gain_out;
+	ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_CTRL1,
+					(ret & (~NAU7802_CTRL1_GAINS_BITS)) |
+					gain);
+
+nau7802_sysfs_set_gain_out:
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static int nau7802_read_conversion(struct nau7802_state *st)
+{
+	int data;
+
+	mutex_lock(&st->data_lock);
+	data = i2c_smbus_read_byte_data(st->client, NAU7802_REG_ADC_B2);
+	if (data < 0)
+		goto nau7802_read_conversion_out;
+	st->last_value = data << 16;
+
+	data = i2c_smbus_read_byte_data(st->client, NAU7802_REG_ADC_B1);
+	if (data < 0)
+		goto nau7802_read_conversion_out;
+	st->last_value |= data << 8;
+
+	data = i2c_smbus_read_byte_data(st->client, NAU7802_REG_ADC_B0);
+	if (data < 0)
+		goto nau7802_read_conversion_out;
+	st->last_value |= data;
+
+	st->last_value = sign_extend32(st->last_value, 23);
+
+nau7802_read_conversion_out:
+	mutex_unlock(&st->data_lock);
+
+	return data;
+}
+
+/*
+ * Conversions are synchronised on the rising edge of NAU7802_PUCTRL_CS_BIT
+ */
+static int nau7802_sync(struct nau7802_state *st)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
+	if (ret < 0)
+		return ret;
+	ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL,
+				ret | NAU7802_PUCTRL_CS_BIT);
+
+	return ret;
+}
+
+static irqreturn_t nau7802_eoc_trigger(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct nau7802_state *st = iio_priv(indio_dev);
+	int status;
+
+	status = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
+	if (status < 0)
+		return IRQ_HANDLED;
+
+	if (!(status & NAU7802_PUCTRL_CR_BIT))
+		return IRQ_NONE;
+
+	if (nau7802_read_conversion(st) < 0)
+		return IRQ_HANDLED;
+
+	/*
+	 * Because there is actually only one ADC for both channels, we have to
+	 * wait for enough conversions to happen before getting a significant
+	 * value when changing channels and the values are far apart.
+	 */
+	if (st->conversion_count < NAU7802_MIN_CONVERSIONS)
+		st->conversion_count++;
+	if (st->conversion_count >= NAU7802_MIN_CONVERSIONS)
+		complete_all(&st->value_ok);
+
+	return IRQ_HANDLED;
+}
+
+static int nau7802_read_irq(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int *val)
+{
+	struct nau7802_state *st = iio_priv(indio_dev);
+	int ret;
+
+	INIT_COMPLETION(st->value_ok);
+	enable_irq(st->client->irq);
+
+	nau7802_sync(st);
+
+	/* read registers to ensure we flush everything */
+	ret = nau7802_read_conversion(st);
+	if (ret < 0)
+		goto read_chan_info_failure;
+
+	/* Wait for a conversion to finish */
+	ret = wait_for_completion_interruptible_timeout(&st->value_ok,
+			msecs_to_jiffies(1000));
+	if (ret == 0)
+		ret = -ETIMEDOUT;
+
+	if (ret < 0)
+		goto read_chan_info_failure;
+
+	disable_irq(st->client->irq);
+
+	*val = st->last_value;
+
+	return IIO_VAL_INT;
+
+read_chan_info_failure:
+	disable_irq(st->client->irq);
+
+	return ret;
+}
+
+static int nau7802_read_poll(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int *val)
+{
+	struct nau7802_state *st = iio_priv(indio_dev);
+	int ret;
+
+	nau7802_sync(st);
+
+	/* read registers to ensure we flush everything */
+	ret = nau7802_read_conversion(st);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Because there is actually only one ADC for both channels, we have to
+	 * wait for enough conversions to happen before getting a significant
+	 * value when changing channels and the values are far appart.
+	 */
+	do {
+		ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
+		if (ret < 0)
+			return ret;
+
+		while (!(ret & NAU7802_PUCTRL_CR_BIT)) {
+			if (st->sample_rate != NAU7802_SAMP_FREQ_320)
+				msleep(20);
+			else
+				mdelay(4);
+			ret = i2c_smbus_read_byte_data(st->client,
+							NAU7802_REG_PUCTRL);
+			if (ret < 0)
+				return ret;
+		}
+
+		ret = nau7802_read_conversion(st);
+		if (ret < 0)
+			return ret;
+		if (st->conversion_count < NAU7802_MIN_CONVERSIONS)
+			st->conversion_count++;
+	} while (st->conversion_count < NAU7802_MIN_CONVERSIONS);
+
+	*val = st->last_value;
+
+	return IIO_VAL_INT;
+}
+
+static int nau7802_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct nau7802_state *st = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&st->lock);
+		/*
+		 * Select the channel to use
+		 *   - Channel 1 is value 0 in the CHS register
+		 *   - Channel 2 is value 1 in the CHS register
+		 */
+		ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_CTRL2);
+		if (ret < 0) {
+			mutex_unlock(&st->lock);
+			return ret;
+		}
+
+		if (((ret & NAU7802_CTRL2_CHS_BIT) && !chan->channel) ||
+				(!(ret & NAU7802_CTRL2_CHS_BIT) &&
+				 chan->channel)) {
+			st->conversion_count = 0;
+			ret = i2c_smbus_write_byte_data(st->client,
+					NAU7802_REG_CTRL2,
+					NAU7802_CTRL2_CHS(chan->channel) |
+					NAU7802_CTRL2_CRS(st->sample_rate));
+
+			if (ret < 0) {
+				mutex_unlock(&st->lock);
+				return ret;
+			}
+		}
+
+		if (st->client->irq)
+			ret = nau7802_read_irq(indio_dev, chan, val);
+		else
+			ret = nau7802_read_poll(indio_dev, chan, val);
+
+		mutex_unlock(&st->lock);
+		return ret;
+
+	case IIO_CHAN_INFO_SCALE:
+		ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_CTRL1);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * We have 24 bits of signed data, that means 23 bits of data
+		 * plus the sign bit
+		 */
+		*val = st->vref_mv;
+		*val2 = 23 + (ret & NAU7802_CTRL1_GAINS_BITS);
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val =  nau7802_sample_freq_avail[st->sample_rate];
+		*val2 = 0;
+		return IIO_VAL_INT;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int nau7802_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct nau7802_state *st = iio_priv(indio_dev);
+	int i, ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
+			if (val2 == st->scale_avail[i])
+				return nau7802_set_gain(st, i);
+
+		break;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		for (i = 0; i < ARRAY_SIZE(nau7802_sample_freq_avail); i++)
+			if (val == nau7802_sample_freq_avail[i]) {
+				mutex_lock(&st->lock);
+				st->sample_rate = i;
+				st->conversion_count = 0;
+				ret = i2c_smbus_write_byte_data(st->client,
+					NAU7802_REG_CTRL2,
+					NAU7802_CTRL2_CRS(st->sample_rate));
+				mutex_unlock(&st->lock);
+				return ret;
+			}
+
+		break;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int nau7802_write_raw_get_fmt(struct iio_dev *indio_dev,
+				     struct iio_chan_spec const *chan,
+				     long mask)
+{
+	return IIO_VAL_INT_PLUS_NANO;
+}
+
+static const struct iio_info nau7802_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &nau7802_read_raw,
+	.write_raw = &nau7802_write_raw,
+	.write_raw_get_fmt = nau7802_write_raw_get_fmt,
+	.attrs = &nau7802_attribute_group,
+};
+
+static int nau7802_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct nau7802_state *st;
+	struct device_node *np = client->dev.of_node;
+	int i, ret;
+	u8 data;
+	u32 tmp = 0;
+
+	if (!client->dev.of_node) {
+		dev_err(&client->dev, "No device tree node available.\n");
+		return -EINVAL;
+	}
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = dev_name(&client->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &nau7802_info;
+
+	st->client = client;
+
+	/* Reset the device */
+	ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL,
+				  NAU7802_PUCTRL_RR_BIT);
+	if (ret < 0)
+		return ret;
+
+	/* Enter normal operation mode */
+	ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL,
+				  NAU7802_PUCTRL_PUD_BIT);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * After about 200 usecs, the device should be ready and then
+	 * the Power Up bit will be set to 1. If not, wait for it.
+	 */
+	udelay(210);
+	ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
+	if (ret < 0)
+		return ret;
+	if (!(ret & NAU7802_PUCTRL_PUR_BIT))
+		return ret;
+
+	of_property_read_u32(np, "nuvoton,vldo", &tmp);
+	st->vref_mv = tmp;
+
+	data = NAU7802_PUCTRL_PUD_BIT | NAU7802_PUCTRL_PUA_BIT |
+		NAU7802_PUCTRL_CS_BIT;
+	if (tmp >= 2400)
+		data |= NAU7802_PUCTRL_AVDDS_BIT;
+
+	ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_PUCTRL, data);
+	if (ret < 0)
+		return ret;
+	ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_ADC_CTRL, 0x30);
+	if (ret < 0)
+		return ret;
+
+	if (tmp >= 2400) {
+		data = NAU7802_CTRL1_VLDO((4500 - tmp) / 300);
+		ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_CTRL1,
+						data);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Populate available ADC input ranges */
+	for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
+		st->scale_avail[i] = (((u64)st->vref_mv) * 1000000000ULL)
+					   >> (23 + i);
+
+	init_completion(&st->value_ok);
+
+	/*
+	 * The ADC fires continuously and we can't do anything about
+	 * it. So we need to have the IRQ disabled by default, and we
+	 * will enable them back when we will need them..
+	 */
+	if (client->irq) {
+		ret = request_threaded_irq(client->irq,
+				NULL,
+				nau7802_eoc_trigger,
+				IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				client->dev.driver->name,
+				indio_dev);
+		if (ret) {
+			/*
+			 * What may happen here is that our IRQ controller is
+			 * not able to get level interrupt but this is required
+			 * by this ADC as when going over 40 sample per second,
+			 * the interrupt line may stay high between conversions.
+			 * So, we continue no matter what but we switch to
+			 * polling mode.
+			 */
+			dev_info(&client->dev,
+				"Failed to allocate IRQ, using polling mode\n");
+			client->irq = 0;
+		} else
+			disable_irq(client->irq);
+	}
+
+	if (!client->irq) {
+		/*
+		 * We are polling, use the fastest sample rate by
+		 * default
+		 */
+		st->sample_rate = NAU7802_SAMP_FREQ_320;
+		ret = i2c_smbus_write_byte_data(st->client, NAU7802_REG_CTRL2,
+					  NAU7802_CTRL2_CRS(st->sample_rate));
+		if (ret)
+			goto error_free_irq;
+	}
+
+	/* Setup the ADC channels available on the board */
+	indio_dev->num_channels = ARRAY_SIZE(nau7802_chan_array);
+	indio_dev->channels = nau7802_chan_array;
+
+	mutex_init(&st->lock);
+	mutex_init(&st->data_lock);
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "Couldn't register the device.\n");
+		goto error_device_register;
+	}
+
+	return 0;
+
+error_device_register:
+	mutex_destroy(&st->lock);
+	mutex_destroy(&st->data_lock);
+error_free_irq:
+	if (client->irq)
+		free_irq(client->irq, indio_dev);
+
+	return ret;
+}
+
+static int nau7802_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct nau7802_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	mutex_destroy(&st->lock);
+	mutex_destroy(&st->data_lock);
+	if (client->irq)
+		free_irq(client->irq, indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id nau7802_i2c_id[] = {
+	{ "nau7802", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, nau7802_i2c_id);
+
+static const struct of_device_id nau7802_dt_ids[] = {
+	{ .compatible = "nuvoton,nau7802" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, nau7802_dt_ids);
+
+static struct i2c_driver nau7802_driver = {
+	.probe = nau7802_probe,
+	.remove = nau7802_remove,
+	.id_table = nau7802_i2c_id,
+	.driver = {
+		   .name = "nau7802",
+		   .of_match_table = of_match_ptr(nau7802_dt_ids),
+	},
+};
+
+module_i2c_driver(nau7802_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Nuvoton NAU7802 ADC Driver");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index 2826faa..ee5f72b 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -74,22 +74,20 @@ static int adc081c_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	iio = iio_device_alloc(sizeof(*adc));
+	iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
 	if (!iio)
 		return -ENOMEM;
 
 	adc = iio_priv(iio);
 	adc->i2c = client;
 
-	adc->ref = regulator_get(&client->dev, "vref");
-	if (IS_ERR(adc->ref)) {
-		err = PTR_ERR(adc->ref);
-		goto iio_free;
-	}
+	adc->ref = devm_regulator_get(&client->dev, "vref");
+	if (IS_ERR(adc->ref))
+		return PTR_ERR(adc->ref);
 
 	err = regulator_enable(adc->ref);
 	if (err < 0)
-		goto regulator_put;
+		return err;
 
 	iio->dev.parent = &client->dev;
 	iio->name = dev_name(&client->dev);
@@ -109,10 +107,6 @@ static int adc081c_probe(struct i2c_client *client,
 
 regulator_disable:
 	regulator_disable(adc->ref);
-regulator_put:
-	regulator_put(adc->ref);
-iio_free:
-	iio_device_free(iio);
 
 	return err;
 }
@@ -124,8 +118,6 @@ static int adc081c_remove(struct i2c_client *client)
 
 	iio_device_unregister(iio);
 	regulator_disable(adc->ref);
-	regulator_put(adc->ref);
-	iio_device_free(iio);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 0ad208a..a952538 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -60,7 +60,6 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 {
 	unsigned int stepconfig;
 	int i, steps;
-	u32 step_en;
 
 	/*
 	 * There are 16 configurable steps and 8 analog input
@@ -86,8 +85,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
-	step_en = get_adc_step_mask(adc_dev);
-	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+
 }
 
 static const char * const chan_name_ain[] = {
@@ -142,10 +140,22 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 		int *val, int *val2, long mask)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
-	int i;
-	unsigned int fifo1count, read;
+	int i, map_val;
+	unsigned int fifo1count, read, stepid;
 	u32 step = UINT_MAX;
 	bool found = false;
+	u32 step_en;
+	unsigned long timeout = jiffies + usecs_to_jiffies
+				(IDLE_TIMEOUT * adc_dev->channels);
+	step_en = get_adc_step_mask(adc_dev);
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+
+	/* Wait for ADC sequencer to complete sampling */
+	while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
+		if (time_after(jiffies, timeout))
+			return -EAGAIN;
+		}
+	map_val = chan->channel + TOTAL_CHANNELS;
 
 	/*
 	 * When the sub-system is first enabled,
@@ -170,12 +180,16 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
 		read = tiadc_readl(adc_dev, REG_FIFO1);
-		if (read >> 16 == step) {
-			*val = read & 0xfff;
+		stepid = read & FIFOREAD_CHNLID_MASK;
+		stepid = stepid >> 0x10;
+
+		if (stepid == map_val) {
+			read = read & FIFOREAD_DATA_MASK;
 			found = true;
+			*val = read;
 		}
 	}
-	am335x_tsc_se_update(adc_dev->mfd_tscadc);
+
 	if (found == false)
 		return -EBUSY;
 	return IIO_VAL_INT;
@@ -202,11 +216,11 @@ static int tiadc_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(struct tiadc_device));
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+					  sizeof(struct tiadc_device));
 	if (indio_dev == NULL) {
 		dev_err(&pdev->dev, "failed to allocate iio device\n");
-		err = -ENOMEM;
-		goto err_ret;
+		return -ENOMEM;
 	}
 	adc_dev = iio_priv(indio_dev);
 
@@ -227,7 +241,7 @@ static int tiadc_probe(struct platform_device *pdev)
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
-		goto err_free_device;
+		return err;
 
 	err = iio_device_register(indio_dev);
 	if (err)
@@ -239,9 +253,6 @@ static int tiadc_probe(struct platform_device *pdev)
 
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
-err_free_device:
-	iio_device_free(indio_dev);
-err_ret:
 	return err;
 }
 
@@ -257,8 +268,6 @@ static int tiadc_remove(struct platform_device *pdev)
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
 
-	iio_device_free(indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
index 56ac481..09727a7 100644
--- a/drivers/iio/adc/viperboard_adc.c
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -124,7 +124,7 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
 	int ret;
 
 	/* registering iio */
-	indio_dev = iio_device_alloc(sizeof(*adc));
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
 	if (!indio_dev) {
 		dev_err(&pdev->dev, "failed allocating iio device\n");
 		return -ENOMEM;
@@ -142,16 +142,12 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
 	ret = iio_device_register(indio_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "could not register iio (adc)");
-		goto error;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
-
-error:
-	iio_device_free(indio_dev);
-	return ret;
 }
 
 static int vprbrd_adc_remove(struct platform_device *pdev)
@@ -159,7 +155,6 @@ static int vprbrd_adc_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 
 	iio_device_unregister(indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/amplifiers/Kconfig b/drivers/iio/amplifiers/Kconfig
index 05d707e..e9c5f2c 100644
--- a/drivers/iio/amplifiers/Kconfig
+++ b/drivers/iio/amplifiers/Kconfig
@@ -1,6 +1,8 @@
 #
 # Gain Amplifiers, etc.
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Amplifiers"
 
 config AD8366
diff --git a/drivers/iio/amplifiers/Makefile b/drivers/iio/amplifiers/Makefile
index a6ca366..8da4b78 100644
--- a/drivers/iio/amplifiers/Makefile
+++ b/drivers/iio/amplifiers/Makefile
@@ -2,4 +2,5 @@
 # Makefile iio/amplifiers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD8366) += ad8366.o
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index d354554..d0a79a4 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -139,17 +139,17 @@ static int ad8366_probe(struct spi_device *spi)
 	struct ad8366_state *st;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "vcc");
+	st->reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
 	spi_set_drvdata(spi, indio_dev);
@@ -173,11 +173,6 @@ static int ad8366_probe(struct spi_device *spi)
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -195,8 +190,6 @@ static int ad8366_remove(struct spi_device *spi)
 		regulator_put(reg);
 	}
 
-	iio_device_free(indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
index c2352be..3112df0 100644
--- a/drivers/iio/common/Makefile
+++ b/drivers/iio/common/Makefile
@@ -6,5 +6,6 @@
 # instead of duplicating in each module.
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-y += hid-sensors/
 obj-y += st_sensors/
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 865b178..965ee22 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -22,7 +22,7 @@
 
 static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
 {
-	return ((s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8);
+	return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8;
 }
 
 static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
@@ -118,7 +118,7 @@ st_sensors_match_odr_error:
 }
 
 static int st_sensors_set_fullscale(struct iio_dev *indio_dev,
-							unsigned int fs)
+								unsigned int fs)
 {
 	int err, i = 0;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
@@ -198,13 +198,39 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
 }
 EXPORT_SYMBOL(st_sensors_set_axis_enable);
 
-int st_sensors_init_sensor(struct iio_dev *indio_dev)
+int st_sensors_init_sensor(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata)
 {
 	int err;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
 	mutex_init(&sdata->tb.buf_lock);
 
+	switch (pdata->drdy_int_pin) {
+	case 1:
+		if (sdata->sensor->drdy_irq.mask_int1 == 0) {
+			dev_err(&indio_dev->dev,
+					"DRDY on INT1 not available.\n");
+			err = -EINVAL;
+			goto init_error;
+		}
+		sdata->drdy_int_pin = 1;
+		break;
+	case 2:
+		if (sdata->sensor->drdy_irq.mask_int2 == 0) {
+			dev_err(&indio_dev->dev,
+					"DRDY on INT2 not available.\n");
+			err = -EINVAL;
+			goto init_error;
+		}
+		sdata->drdy_int_pin = 2;
+		break;
+	default:
+		dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n");
+		err = -EINVAL;
+		goto init_error;
+	}
+
 	err = st_sensors_set_enable(indio_dev, false);
 	if (err < 0)
 		goto init_error;
@@ -234,6 +260,7 @@ EXPORT_SYMBOL(st_sensors_init_sensor);
 int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
 {
 	int err;
+	u8 drdy_mask;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
 	/* Enable/Disable the interrupt generator 1. */
@@ -245,10 +272,14 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
 			goto st_accel_set_dataready_irq_error;
 	}
 
+	if (sdata->drdy_int_pin == 1)
+		drdy_mask = sdata->sensor->drdy_irq.mask_int1;
+	else
+		drdy_mask = sdata->sensor->drdy_irq.mask_int2;
+
 	/* Enable/Disable the interrupt generator for data ready. */
 	err = st_sensors_write_data_with_mask(indio_dev,
-			sdata->sensor->drdy_irq.addr,
-			sdata->sensor->drdy_irq.mask, (int)enable);
+			sdata->sensor->drdy_irq.addr, drdy_mask, (int)enable);
 
 st_accel_set_dataready_irq_error:
 	return err;
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index c9c33ce..3c6a78a 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -1,6 +1,8 @@
 #
 # DAC drivers
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Digital to analog converters"
 
 config AD5064
@@ -15,7 +17,7 @@ config AD5064
 	  module will be called ad5064.
 
 config AD5360
-	tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
+	tristate "Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
 	depends on SPI
 	help
 	  Say yes here to build support for Analog Devices AD5360, AD5361,
@@ -48,13 +50,6 @@ config AD5421
 	  To compile this driver as module choose M here: the module will be called
 	  ad5421.
 
-config AD5624R_SPI
-	tristate "Analog Devices AD5624/44/64R DAC spi driver"
-	depends on SPI
-	help
-	  Say yes here to build support for Analog Devices AD5624R, AD5644R and
-	  AD5664R converters (DAC). This driver uses the common SPI interface.
-
 config AD5446
 	tristate "Analog Devices AD5446 and similar single channel DACs driver"
 	depends on (SPI_MASTER && I2C!=m) || I2C
@@ -68,7 +63,7 @@ config AD5446
 	  module will be called ad5446.
 
 config AD5449
-	tristate "Analog Device AD5449 and similar DACs driver"
+	tristate "Analog Devices AD5449 and similar DACs driver"
 	depends on SPI_MASTER
 	help
 	  Say yes here to build support for Analog Devices AD5415, AD5426, AD5429,
@@ -87,6 +82,24 @@ config AD5504
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5504.
 
+config AD5624R_SPI
+	tristate "Analog Devices AD5624/44/64R DAC spi driver"
+	depends on SPI
+	help
+	  Say yes here to build support for Analog Devices AD5624R, AD5644R and
+	  AD5664R converters (DAC). This driver uses the common SPI interface.
+
+config AD5686
+	tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+	depends on SPI
+	help
+	  Say yes here to build support for Analog Devices AD5686R, AD5685R,
+	  AD5684R, AD5791 Voltage Output Digital to
+	  Analog Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad5686.
+
 config AD5755
 	tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC driver"
 	depends on SPI_MASTER
@@ -119,19 +132,8 @@ config AD5791
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5791.
 
-config AD5686
-	tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
-	depends on SPI
-	help
-	  Say yes here to build support for Analog Devices AD5686R, AD5685R,
-	  AD5684R, AD5791 Voltage Output Digital to
-	  Analog Converter.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ad5686.
-
 config AD7303
-	tristate "Analog Devices Analog Devices AD7303 DAC driver"
+	tristate "Analog Devices AD7303 DAC driver"
 	depends on SPI
 	help
 	  Say yes here to build support for Analog Devices AD7303 Digital to Analog
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index c8d7ab6..bb84ad6 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -2,6 +2,7 @@
 # Makefile for industrial I/O DAC drivers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD5360) += ad5360.o
 obj-$(CONFIG_AD5380) += ad5380.o
 obj-$(CONFIG_AD5421) += ad5421.o
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index a612ec7..1f4a48e 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -12,14 +12,13 @@
  * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC)
  * (7-bit I2C slave address 0x60, the three LSBs can be configured in
  * hardware)
- *
- * writing the DAC value to EEPROM is not supported
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -32,15 +31,19 @@ struct mcp4725_data {
 	struct i2c_client *client;
 	u16 vref_mv;
 	u16 dac_value;
+	bool powerdown;
+	unsigned powerdown_mode;
 };
 
-#ifdef CONFIG_PM_SLEEP
 static int mcp4725_suspend(struct device *dev)
 {
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct mcp4725_data *data = iio_priv(indio_dev);
 	u8 outbuf[2];
 
-	outbuf[0] = 0x3 << 4; /* power-down bits, 500 kOhm resistor */
+	outbuf[0] = (data->powerdown_mode + 1) << 4;
 	outbuf[1] = 0;
+	data->powerdown = true;
 
 	return i2c_master_send(to_i2c_client(dev), outbuf, 2);
 }
@@ -54,16 +57,150 @@ static int mcp4725_resume(struct device *dev)
 	/* restore previous DAC value */
 	outbuf[0] = (data->dac_value >> 8) & 0xf;
 	outbuf[1] = data->dac_value & 0xff;
+	data->powerdown = false;
 
 	return i2c_master_send(to_i2c_client(dev), outbuf, 2);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume);
 #define MCP4725_PM_OPS (&mcp4725_pm_ops)
 #else
 #define MCP4725_PM_OPS NULL
 #endif
 
+static ssize_t mcp4725_store_eeprom(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct mcp4725_data *data = iio_priv(indio_dev);
+	int tries = 20;
+	u8 inoutbuf[3];
+	bool state;
+	int ret;
+
+	ret = strtobool(buf, &state);
+	if (ret < 0)
+		return ret;
+
+	if (!state)
+		return 0;
+
+	inoutbuf[0] = 0x60; /* write EEPROM */
+	inoutbuf[1] = data->dac_value >> 4;
+	inoutbuf[2] = (data->dac_value & 0xf) << 4;
+
+	ret = i2c_master_send(data->client, inoutbuf, 3);
+	if (ret < 0)
+		return ret;
+	else if (ret != 3)
+		return -EIO;
+
+	/* wait for write complete, takes up to 50ms */
+	while (tries--) {
+		msleep(20);
+		ret = i2c_master_recv(data->client, inoutbuf, 3);
+		if (ret < 0)
+			return ret;
+		else if (ret != 3)
+			return -EIO;
+
+		if (inoutbuf[0] & 0x80)
+			break;
+	}
+
+	if (tries < 0) {
+		dev_err(&data->client->dev,
+			"mcp4725_store_eeprom() failed, incomplete\n");
+		return -EIO;
+	}
+
+	return len;
+}
+
+static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, NULL, mcp4725_store_eeprom, 0);
+
+static struct attribute *mcp4725_attributes[] = {
+	&iio_dev_attr_store_eeprom.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group mcp4725_attribute_group = {
+	.attrs = mcp4725_attributes,
+};
+
+static const char * const mcp4725_powerdown_modes[] = {
+	"1kohm_to_gnd",
+	"100kohm_to_gnd",
+	"500kohm_to_gnd"
+};
+
+static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	struct mcp4725_data *data = iio_priv(indio_dev);
+
+	return data->powerdown_mode;
+}
+
+static int mcp4725_set_powerdown_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned mode)
+{
+	struct mcp4725_data *data = iio_priv(indio_dev);
+
+	data->powerdown_mode = mode;
+
+	return 0;
+}
+
+static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev,
+	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
+{
+	struct mcp4725_data *data = iio_priv(indio_dev);
+
+	return sprintf(buf, "%d\n", data->powerdown);
+}
+
+static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev,
+	 uintptr_t private, const struct iio_chan_spec *chan,
+	 const char *buf, size_t len)
+{
+	struct mcp4725_data *data = iio_priv(indio_dev);
+	bool state;
+	int ret;
+
+	ret = strtobool(buf, &state);
+	if (ret)
+		return ret;
+
+	if (state)
+		ret = mcp4725_suspend(&data->client->dev);
+	else
+		ret = mcp4725_resume(&data->client->dev);
+	if (ret < 0)
+		return ret;
+
+	return len;
+}
+
+static const struct iio_enum mcp4725_powerdown_mode_enum = {
+	.items = mcp4725_powerdown_modes,
+	.num_items = ARRAY_SIZE(mcp4725_powerdown_modes),
+	.get = mcp4725_get_powerdown_mode,
+	.set = mcp4725_set_powerdown_mode,
+};
+
+static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
+	{
+		.name = "powerdown",
+		.read = mcp4725_read_powerdown,
+		.write = mcp4725_write_powerdown,
+	},
+	IIO_ENUM("powerdown_mode", false, &mcp4725_powerdown_mode_enum),
+	IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum),
+	{ },
+};
+
 static const struct iio_chan_spec mcp4725_channel = {
 	.type		= IIO_VOLTAGE,
 	.indexed	= 1,
@@ -72,6 +209,7 @@ static const struct iio_chan_spec mcp4725_channel = {
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 	.scan_type	= IIO_ST('u', 12, 16, 0),
+	.ext_info	= mcp4725_ext_info,
 };
 
 static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
@@ -138,6 +276,7 @@ static int mcp4725_write_raw(struct iio_dev *indio_dev,
 static const struct iio_info mcp4725_info = {
 	.read_raw = mcp4725_read_raw,
 	.write_raw = mcp4725_write_raw,
+	.attrs = &mcp4725_attribute_group,
 	.driver_module = THIS_MODULE,
 };
 
@@ -148,19 +287,17 @@ static int mcp4725_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	struct mcp4725_platform_data *platform_data = client->dev.platform_data;
 	u8 inbuf[3];
+	u8 pd;
 	int err;
 
 	if (!platform_data || !platform_data->vref_mv) {
 		dev_err(&client->dev, "invalid platform data");
-		err = -EINVAL;
-		goto exit;
+		return -EINVAL;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*data));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
 	data = iio_priv(indio_dev);
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
@@ -177,31 +314,25 @@ static int mcp4725_probe(struct i2c_client *client,
 	err = i2c_master_recv(client, inbuf, 3);
 	if (err < 0) {
 		dev_err(&client->dev, "failed to read DAC value");
-		goto exit_free_device;
+		return err;
 	}
+	pd = (inbuf[0] >> 1) & 0x3;
+	data->powerdown = pd > 0 ? true : false;
+	data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */
 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
 
 	err = iio_device_register(indio_dev);
 	if (err)
-		goto exit_free_device;
+		return err;
 
 	dev_info(&client->dev, "MCP4725 DAC registered\n");
 
 	return 0;
-
-exit_free_device:
-	iio_device_free(indio_dev);
-exit:
-	return err;
 }
 
 static int mcp4725_remove(struct i2c_client *client)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
-	iio_device_unregister(indio_dev);
-	iio_device_free(indio_dev);
-
+	iio_device_unregister(i2c_get_clientdata(client));
 	return 0;
 }
 
diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig
index 6aaa33e..dc5e0b7 100644
--- a/drivers/iio/frequency/Kconfig
+++ b/drivers/iio/frequency/Kconfig
@@ -4,6 +4,7 @@
 #	Clock Distribution device drivers
 #	Phase-Locked Loop (PLL) frequency synthesizers
 #
+# When adding new entries keep the list in alphabetical order
 
 menu "Frequency Synthesizers DDS/PLL"
 
diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile
index 00d26e5..2bca03f 100644
--- a/drivers/iio/frequency/Makefile
+++ b/drivers/iio/frequency/Makefile
@@ -2,5 +2,6 @@
 # Makefile iio/frequency
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD9523) += ad9523.o
 obj-$(CONFIG_ADF4350) += adf4350.o
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index 92276de..7c5245d 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -961,17 +961,17 @@ static int ad9523_probe(struct spi_device *spi)
 		return -EINVAL;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "vcc");
+	st->reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
 	spi_set_drvdata(spi, indio_dev);
@@ -1001,11 +1001,6 @@ static int ad9523_probe(struct spi_device *spi)
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -1017,12 +1012,8 @@ static int ad9523_remove(struct spi_device *spi)
 
 	iio_device_unregister(indio_dev);
 
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index a4157cd..a7b30be 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -515,7 +515,7 @@ static int adf4350_probe(struct spi_device *spi)
 	}
 
 	if (!pdata->clkin) {
-		clk = clk_get(&spi->dev, "clkin");
+		clk = devm_clk_get(&spi->dev, "clkin");
 		if (IS_ERR(clk))
 			return -EPROBE_DEFER;
 
@@ -524,17 +524,17 @@ static int adf4350_probe(struct spi_device *spi)
 			return ret;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "vcc");
+	st->reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			goto error_disable_clk;
 	}
 
 	spi_set_drvdata(spi, indio_dev);
@@ -564,7 +564,8 @@ static int adf4350_probe(struct spi_device *spi)
 	memset(st->regs_hw, 0xFF, sizeof(st->regs_hw));
 
 	if (gpio_is_valid(pdata->gpio_lock_detect)) {
-		ret = gpio_request(pdata->gpio_lock_detect, indio_dev->name);
+		ret = devm_gpio_request(&spi->dev, pdata->gpio_lock_detect,
+					indio_dev->name);
 		if (ret) {
 			dev_err(&spi->dev, "fail to request lock detect GPIO-%d",
 				pdata->gpio_lock_detect);
@@ -576,29 +577,21 @@ static int adf4350_probe(struct spi_device *spi)
 	if (pdata->power_up_frequency) {
 		ret = adf4350_set_freq(st, pdata->power_up_frequency);
 		if (ret)
-			goto error_free_gpio;
+			goto error_disable_reg;
 	}
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_gpio;
+		goto error_disable_reg;
 
 	return 0;
 
-error_free_gpio:
-	if (gpio_is_valid(pdata->gpio_lock_detect))
-		gpio_free(pdata->gpio_lock_detect);
-
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
+error_disable_clk:
 	if (clk)
 		clk_disable_unprepare(clk);
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -619,14 +612,8 @@ static int adf4350_remove(struct spi_device *spi)
 
 	if (!IS_ERR(reg)) {
 		regulator_disable(reg);
-		regulator_put(reg);
 	}
 
-	if (gpio_is_valid(st->pdata->gpio_lock_detect))
-		gpio_free(st->pdata->gpio_lock_detect);
-
-	iio_device_free(indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 8498e9d..41c64a4 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -1,6 +1,8 @@
 #
 # IIO Digital Gyroscope Sensor drivers configuration
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Digital gyroscope sensors"
 
 config ADIS16080
@@ -26,6 +28,18 @@ config ADIS16136
 	  Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
 	  ADIS16136 gyroscope devices.
 
+config ADIS16260
+	tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
+	depends on SPI
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+	help
+	  Say yes here to build support for Analog Devices ADIS16260 ADIS16265
+	  ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called adis16260.
+
 config ADXRS450
 	tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver"
 	depends on SPI
@@ -58,8 +72,8 @@ config IIO_ST_GYRO_3AXIS
 	  Say yes here to build support for STMicroelectronics gyroscopes:
 	  L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
 
-	  This driver can also be built as a module. If so, will be created
-	  these modules:
+	  This driver can also be built as a module. If so, these modules
+	  will be created:
 	  - st_gyro (core functions for the driver [it is mandatory]);
 	  - st_gyro_i2c (necessary for the I2C devices [optional*]);
 	  - st_gyro_spi (necessary for the SPI devices [optional*]);
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index e9dc034..2f2752a 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -2,9 +2,11 @@
 # Makefile for industrial I/O gyroscope sensor drivers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_ADIS16080) += adis16080.o
 obj-$(CONFIG_ADIS16130) += adis16130.o
 obj-$(CONFIG_ADIS16136) += adis16136.o
+obj-$(CONFIG_ADIS16260) += adis16260.o
 obj-$(CONFIG_ADXRS450) += adxrs450.o
 
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
new file mode 100644
index 0000000..b4cf800
--- /dev/null
+++ b/drivers/iio/gyro/adis16260.c
@@ -0,0 +1,428 @@
+/*
+ * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#define ADIS16260_STARTUP_DELAY	220 /* ms */
+
+#define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
+#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
+#define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
+#define ADIS16260_AUX_ADC    0x0A /* analog input channel measurement */
+#define ADIS16260_TEMP_OUT   0x0C /* internal temperature measurement */
+#define ADIS16260_ANGL_OUT   0x0E /* angle displacement */
+#define ADIS16260_GYRO_OFF   0x14 /* Calibration, offset/bias adjustment */
+#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
+#define ADIS16260_ALM_MAG1   0x20 /* Alarm 1 magnitude/polarity setting */
+#define ADIS16260_ALM_MAG2   0x22 /* Alarm 2 magnitude/polarity setting */
+#define ADIS16260_ALM_SMPL1  0x24 /* Alarm 1 dynamic rate of change setting */
+#define ADIS16260_ALM_SMPL2  0x26 /* Alarm 2 dynamic rate of change setting */
+#define ADIS16260_ALM_CTRL   0x28 /* Alarm control */
+#define ADIS16260_AUX_DAC    0x30 /* Auxiliary DAC data */
+#define ADIS16260_GPIO_CTRL  0x32 /* Control, digital I/O line */
+#define ADIS16260_MSC_CTRL   0x34 /* Control, data ready, self-test settings */
+#define ADIS16260_SMPL_PRD   0x36 /* Control, internal sample rate */
+#define ADIS16260_SENS_AVG   0x38 /* Control, dynamic range, filtering */
+#define ADIS16260_SLP_CNT    0x3A /* Control, sleep mode initiation */
+#define ADIS16260_DIAG_STAT  0x3C /* Diagnostic, error flags */
+#define ADIS16260_GLOB_CMD   0x3E /* Control, global commands */
+#define ADIS16260_LOT_ID1    0x52 /* Lot Identification Code 1 */
+#define ADIS16260_LOT_ID2    0x54 /* Lot Identification Code 2 */
+#define ADIS16260_PROD_ID    0x56 /* Product identifier;
+				   * convert to decimal = 16,265/16,260 */
+#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
+
+#define ADIS16260_ERROR_ACTIVE			(1<<14)
+#define ADIS16260_NEW_DATA			(1<<15)
+
+/* MSC_CTRL */
+#define ADIS16260_MSC_CTRL_MEM_TEST		(1<<11)
+/* Internal self-test enable */
+#define ADIS16260_MSC_CTRL_INT_SELF_TEST	(1<<10)
+#define ADIS16260_MSC_CTRL_NEG_SELF_TEST	(1<<9)
+#define ADIS16260_MSC_CTRL_POS_SELF_TEST	(1<<8)
+#define ADIS16260_MSC_CTRL_DATA_RDY_EN		(1<<2)
+#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
+#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
+
+/* SMPL_PRD */
+/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
+#define ADIS16260_SMPL_PRD_TIME_BASE	(1<<7)
+#define ADIS16260_SMPL_PRD_DIV_MASK	0x7F
+
+/* SLP_CNT */
+#define ADIS16260_SLP_CNT_POWER_OFF     0x80
+
+/* DIAG_STAT */
+#define ADIS16260_DIAG_STAT_ALARM2	(1<<9)
+#define ADIS16260_DIAG_STAT_ALARM1	(1<<8)
+#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT	6
+#define ADIS16260_DIAG_STAT_SELF_TEST_BIT	5
+#define ADIS16260_DIAG_STAT_OVERFLOW_BIT	4
+#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT	3
+#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT	2
+#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT	1
+#define ADIS16260_DIAG_STAT_POWER_LOW_BIT	0
+
+/* GLOB_CMD */
+#define ADIS16260_GLOB_CMD_SW_RESET	(1<<7)
+#define ADIS16260_GLOB_CMD_FLASH_UPD	(1<<3)
+#define ADIS16260_GLOB_CMD_DAC_LATCH	(1<<2)
+#define ADIS16260_GLOB_CMD_FAC_CALIB	(1<<1)
+#define ADIS16260_GLOB_CMD_AUTO_NULL	(1<<0)
+
+#define ADIS16260_SPI_SLOW	(u32)(300 * 1000)
+#define ADIS16260_SPI_BURST	(u32)(1000 * 1000)
+#define ADIS16260_SPI_FAST	(u32)(2000 * 1000)
+
+/* At the moment triggers are only used for ring buffer
+ * filling. This may change!
+ */
+
+#define ADIS16260_SCAN_GYRO	0
+#define ADIS16260_SCAN_SUPPLY	1
+#define ADIS16260_SCAN_AUX_ADC	2
+#define ADIS16260_SCAN_TEMP	3
+#define ADIS16260_SCAN_ANGL	4
+
+static ssize_t adis16260_read_frequency(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis *adis = iio_priv(indio_dev);
+	int ret, len = 0;
+	u16 t;
+	int sps;
+	ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &t);
+	if (ret)
+		return ret;
+
+	if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */
+		sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
+	else
+		sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
+	sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
+	len = sprintf(buf, "%d\n", sps);
+	return len;
+}
+
+static ssize_t adis16260_write_frequency(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis *adis = iio_priv(indio_dev);
+	unsigned int val;
+	int ret;
+	u8 t;
+
+	ret = kstrtouint(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	mutex_lock(&indio_dev->mlock);
+	if (spi_get_device_id(adis->spi)->driver_data)
+		t = 256 / val;
+	else
+		t = 2048 / val;
+
+	if (t > ADIS16260_SMPL_PRD_DIV_MASK)
+		t = ADIS16260_SMPL_PRD_DIV_MASK;
+	else if (t > 0)
+		t--;
+
+	if (t >= 0x0A)
+		adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
+	else
+		adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
+	ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
+
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret ? ret : len;
+}
+
+/* Power down the device */
+static int adis16260_stop_device(struct iio_dev *indio_dev)
+{
+	struct adis *adis = iio_priv(indio_dev);
+	int ret;
+	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+
+	ret = adis_write_reg_16(adis, ADIS16260_SLP_CNT, val);
+	if (ret)
+		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+
+	return ret;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+		adis16260_read_frequency,
+		adis16260_write_frequency);
+
+static const struct iio_chan_spec adis16260_channels[] = {
+	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
+		BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE), 14),
+	ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14),
+	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12),
+	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12),
+	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12),
+	IIO_CHAN_SOFT_TIMESTAMP(5),
+};
+
+static const u8 adis16260_addresses[][2] = {
+	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
+};
+
+static int adis16260_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct adis *adis = iio_priv(indio_dev);
+	int ret;
+	u8 addr;
+	s16 val16;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return adis_single_conversion(indio_dev, chan,
+				ADIS16260_ERROR_ACTIVE, val);
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			*val = 0;
+			if (spi_get_device_id(adis->spi)->driver_data) {
+				/* 0.01832 degree / sec */
+				*val2 = IIO_DEGREE_TO_RAD(18320);
+			} else {
+				/* 0.07326 degree / sec */
+				*val2 = IIO_DEGREE_TO_RAD(73260);
+			}
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_INCLI:
+			*val = 0;
+			*val2 = IIO_DEGREE_TO_RAD(36630);
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_VOLTAGE:
+			if (chan->channel == 0) {
+				*val = 1;
+				*val2 = 831500; /* 1.8315 mV */
+			} else {
+				*val = 0;
+				*val2 = 610500; /* 610.5 uV */
+			}
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_TEMP:
+			*val = 145;
+			*val2 = 300000; /* 0.1453 C */
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = 250000 / 1453; /* 25 C = 0x00 */
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_CALIBBIAS:
+		addr = adis16260_addresses[chan->scan_index][0];
+		ret = adis_read_reg_16(adis, addr, &val16);
+		if (ret)
+			return ret;
+
+		*val = sign_extend32(val16, 11);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_CALIBSCALE:
+		addr = adis16260_addresses[chan->scan_index][1];
+		ret = adis_read_reg_16(adis, addr, &val16);
+		if (ret)
+			return ret;
+
+		*val = val16;
+		return IIO_VAL_INT;
+	}
+	return -EINVAL;
+}
+
+static int adis16260_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct adis *adis = iio_priv(indio_dev);
+	u8 addr;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		if (val < -2048 || val >= 2048)
+			return -EINVAL;
+
+		addr = adis16260_addresses[chan->scan_index][0];
+		return adis_write_reg_16(adis, addr, val);
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (val < 0 || val >= 4096)
+			return -EINVAL;
+
+		addr = adis16260_addresses[chan->scan_index][1];
+		return adis_write_reg_16(adis, addr, val);
+	}
+	return -EINVAL;
+}
+
+static struct attribute *adis16260_attributes[] = {
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adis16260_attribute_group = {
+	.attrs = adis16260_attributes,
+};
+
+static const struct iio_info adis16260_info = {
+	.attrs = &adis16260_attribute_group,
+	.read_raw = &adis16260_read_raw,
+	.write_raw = &adis16260_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
+	.driver_module = THIS_MODULE,
+};
+
+static const char * const adis1620_status_error_msgs[] = {
+	[ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
+	[ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
+	[ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
+	[ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
+	[ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
+};
+
+static const struct adis_data adis16260_data = {
+	.write_delay = 30,
+	.read_delay = 30,
+	.msc_ctrl_reg = ADIS16260_MSC_CTRL,
+	.glob_cmd_reg = ADIS16260_GLOB_CMD,
+	.diag_stat_reg = ADIS16260_DIAG_STAT,
+
+	.self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
+	.startup_delay = ADIS16260_STARTUP_DELAY,
+
+	.status_error_msgs = adis1620_status_error_msgs,
+	.status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
+		BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
+		BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
+		BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16260_probe(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev;
+	struct adis *adis;
+	int ret;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_device_alloc(sizeof(*adis));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	adis = iio_priv(indio_dev);
+	/* this is only used for removal purposes */
+	spi_set_drvdata(spi, indio_dev);
+
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16260_info;
+	indio_dev->channels = adis16260_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16260_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = adis_init(adis, indio_dev, spi, &adis16260_data);
+	if (ret)
+		goto error_free_dev;
+
+	ret = adis_setup_buffer_and_trigger(adis, indio_dev, NULL);
+	if (ret)
+		goto error_free_dev;
+
+	/* Get the device into a sane initial state */
+	ret = adis_initial_startup(adis);
+	if (ret)
+		goto error_cleanup_buffer_trigger;
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_cleanup_buffer_trigger;
+
+	return 0;
+
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(adis, indio_dev);
+error_free_dev:
+	iio_device_free(indio_dev);
+error_ret:
+	return ret;
+}
+
+static int adis16260_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *adis = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	adis16260_stop_device(indio_dev);
+	adis_cleanup_buffer_and_trigger(adis, indio_dev);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+/*
+ * These parts do not need to be differentiated until someone adds
+ * support for the on chip filtering.
+ */
+static const struct spi_device_id adis16260_id[] = {
+	{"adis16260", 0},
+	{"adis16265", 0},
+	{"adis16250", 0},
+	{"adis16255", 0},
+	{"adis16251", 1},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, adis16260_id);
+
+static struct spi_driver adis16260_driver = {
+	.driver = {
+		.name = "adis16260",
+		.owner = THIS_MODULE,
+	},
+	.probe = adis16260_probe,
+	.remove = adis16260_remove,
+	.id_table = adis16260_id,
+};
+module_spi_driver(adis16260_driver);
+
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index bc943dd..9cc8aa1 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -30,10 +30,6 @@
 #include <linux/iio/triggered_buffer.h>
 #include "../common/hid-sensors/hid-sensor-trigger.h"
 
-/*Format: HID-SENSOR-usage_id_in_hex*/
-/*Usage ID from spec for Gyro-3D: 0x200076*/
-#define DRIVER_NAME "HID-SENSOR-200076"
-
 enum gyro_3d_channel {
 	CHANNEL_SCAN_INDEX_X,
 	CHANNEL_SCAN_INDEX_Y,
@@ -389,9 +385,19 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static struct platform_device_id hid_gyro_3d_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-200076",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_gyro_3d_ids);
+
 static struct platform_driver hid_gyro_3d_platform_driver = {
+	.id_table = hid_gyro_3d_ids,
 	.driver = {
-		.name	= DRIVER_NAME,
+		.name	= KBUILD_MODNAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= hid_gyro_3d_probe,
diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
index 3ad9907..f8f2bf8 100644
--- a/drivers/iio/gyro/st_gyro.h
+++ b/drivers/iio/gyro/st_gyro.h
@@ -23,7 +23,16 @@
 #define L3G4IS_GYRO_DEV_NAME		"l3g4is_ui"
 #define LSM330_GYRO_DEV_NAME		"lsm330_gyro"
 
-int st_gyro_common_probe(struct iio_dev *indio_dev);
+/**
+ * struct st_sensors_platform_data - gyro platform data
+ * @drdy_int_pin: DRDY on gyros is available only on INT2 pin.
+ */
+static const struct st_sensors_platform_data gyro_pdata = {
+	.drdy_int_pin = 2,
+};
+
+int st_gyro_common_probe(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata);
 void st_gyro_common_remove(struct iio_dev *indio_dev);
 
 #ifdef CONFIG_IIO_BUFFER
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index f9ed348..85fa8d3 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -60,7 +60,7 @@
 #define ST_GYRO_1_BDU_ADDR			0x23
 #define ST_GYRO_1_BDU_MASK			0x80
 #define ST_GYRO_1_DRDY_IRQ_ADDR			0x22
-#define ST_GYRO_1_DRDY_IRQ_MASK			0x08
+#define ST_GYRO_1_DRDY_IRQ_INT2_MASK		0x08
 #define ST_GYRO_1_MULTIREAD_BIT			true
 
 /* CUSTOM VALUES FOR SENSOR 2 */
@@ -84,7 +84,7 @@
 #define ST_GYRO_2_BDU_ADDR			0x23
 #define ST_GYRO_2_BDU_MASK			0x80
 #define ST_GYRO_2_DRDY_IRQ_ADDR			0x22
-#define ST_GYRO_2_DRDY_IRQ_MASK			0x08
+#define ST_GYRO_2_DRDY_IRQ_INT2_MASK		0x08
 #define ST_GYRO_2_MULTIREAD_BIT			true
 
 static const struct iio_chan_spec st_gyro_16bit_channels[] = {
@@ -158,7 +158,7 @@ static const struct st_sensors st_gyro_sensors[] = {
 		},
 		.drdy_irq = {
 			.addr = ST_GYRO_1_DRDY_IRQ_ADDR,
-			.mask = ST_GYRO_1_DRDY_IRQ_MASK,
+			.mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK,
 		},
 		.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
 		.bootime = 2,
@@ -221,7 +221,7 @@ static const struct st_sensors st_gyro_sensors[] = {
 		},
 		.drdy_irq = {
 			.addr = ST_GYRO_2_DRDY_IRQ_ADDR,
-			.mask = ST_GYRO_2_DRDY_IRQ_MASK,
+			.mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK,
 		},
 		.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
 		.bootime = 2,
@@ -302,7 +302,8 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = {
 #define ST_GYRO_TRIGGER_OPS NULL
 #endif
 
-int st_gyro_common_probe(struct iio_dev *indio_dev)
+int st_gyro_common_probe(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata)
 {
 	int err;
 	struct st_sensor_data *gdata = iio_priv(indio_dev);
@@ -324,7 +325,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
 						&gdata->sensor->fs.fs_avl[0];
 	gdata->odr = gdata->sensor->odr.odr_avl[0].hz;
 
-	err = st_sensors_init_sensor(indio_dev);
+	err = st_sensors_init_sensor(indio_dev, pdata);
 	if (err < 0)
 		goto st_gyro_common_probe_error;
 
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 8a31050..c7a29a4 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -36,7 +36,8 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
 
 	st_sensors_i2c_configure(indio_dev, client, gdata);
 
-	err = st_gyro_common_probe(indio_dev);
+	err = st_gyro_common_probe(indio_dev,
+				(struct st_sensors_platform_data *)&gyro_pdata);
 	if (err < 0)
 		goto st_gyro_common_probe_error;
 
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
index f354039..14b0762 100644
--- a/drivers/iio/gyro/st_gyro_spi.c
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -35,7 +35,8 @@ static int st_gyro_spi_probe(struct spi_device *spi)
 
 	st_sensors_spi_configure(indio_dev, spi, gdata);
 
-	err = st_gyro_common_probe(indio_dev);
+	err = st_gyro_common_probe(indio_dev,
+				(struct st_sensors_platform_data *)&gyro_pdata);
 	if (err < 0)
 		goto st_gyro_common_probe_error;
 
diff --git a/drivers/iio/iio_core_trigger.h b/drivers/iio/iio_core_trigger.h
index 6f7c56f..1fdb1e4 100644
--- a/drivers/iio/iio_core_trigger.h
+++ b/drivers/iio/iio_core_trigger.h
@@ -30,7 +30,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev);
 static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
 {
 	return 0;
-};
+}
 
 /**
  * iio_device_unregister_trigger_consumer() - reverse the registration process
@@ -38,9 +38,6 @@ static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
  **/
 static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
 {
-};
+}
 
 #endif /* CONFIG_TRIGGER_CONSUMER */
-
-
-
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 4f40a10..663e88a 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -1,6 +1,8 @@
 #
 # IIO imu drivers configuration
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Inertial measurement units"
 
 config ADIS16400
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index f2f56ce..114d2c1 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -2,6 +2,7 @@
 # Makefile for Inertial Measurement Units
 #
 
+# When adding new entries keep the list in alphabetical order
 adis16400-y             := adis16400_core.o
 adis16400-$(CONFIG_IIO_BUFFER) += adis16400_buffer.o
 obj-$(CONFIG_ADIS16400) += adis16400.o
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index f60591f..3fb7757 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -871,7 +871,7 @@ static int adis16400_probe(struct spi_device *spi)
 	struct iio_dev *indio_dev;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -893,12 +893,12 @@ static int adis16400_probe(struct spi_device *spi)
 
 	ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev,
 			adis16400_trigger_handler);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	/* Get the device into a sane initial state */
 	ret = adis16400_initial_setup(indio_dev);
@@ -913,8 +913,6 @@ static int adis16400_probe(struct spi_device *spi)
 
 error_cleanup_buffer:
 	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
 	return ret;
 }
 
@@ -928,8 +926,6 @@ static int adis16400_remove(struct spi_device *spi)
 
 	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
 
-	iio_device_free(indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index b7db383..dd4206c 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -839,7 +839,7 @@ static int adis16480_probe(struct spi_device *spi)
 	struct adis16480 *st;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -857,11 +857,11 @@ static int adis16480_probe(struct spi_device *spi)
 
 	ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	ret = adis16480_initial_setup(indio_dev);
 	if (ret)
@@ -879,8 +879,6 @@ error_stop_device:
 	adis16480_stop_device(indio_dev);
 error_cleanup_buffer:
 	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
 	return ret;
 }
 
@@ -894,8 +892,6 @@ static int adis16480_remove(struct spi_device *spi)
 
 	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
 
-	iio_device_free(indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index fe4c61e..df7f1e1 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/kfifo.h>
 #include <linux/spinlock.h>
+#include <linux/iio/iio.h>
 #include "inv_mpu_iio.h"
 
 /*
@@ -663,16 +664,13 @@ static int inv_mpu_probe(struct i2c_client *client,
 	int result;
 
 	if (!i2c_check_functionality(client->adapter,
-					I2C_FUNC_SMBUS_READ_I2C_BLOCK |
-					I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
-		result = -ENOSYS;
-		goto out_no_free;
-	}
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		result =  -ENOMEM;
-		goto out_no_free;
-	}
+		I2C_FUNC_SMBUS_I2C_BLOCK))
+		return -ENOSYS;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
 	st = iio_priv(indio_dev);
 	st->client = client;
 	st->plat_data = *(struct inv_mpu6050_platform_data
@@ -680,13 +678,13 @@ static int inv_mpu_probe(struct i2c_client *client,
 	/* power is turned on inside check chip type*/
 	result = inv_check_and_setup_chip(st, id);
 	if (result)
-		goto out_free;
+		return result;
 
 	result = inv_mpu6050_init_config(indio_dev);
 	if (result) {
 		dev_err(&client->dev,
 			"Could not initialize device.\n");
-		goto out_free;
+		return result;
 	}
 
 	i2c_set_clientdata(client, indio_dev);
@@ -705,7 +703,7 @@ static int inv_mpu_probe(struct i2c_client *client,
 	if (result) {
 		dev_err(&st->client->dev, "configure buffer fail %d\n",
 				result);
-		goto out_free;
+		return result;
 	}
 	result = inv_mpu6050_probe_trigger(indio_dev);
 	if (result) {
@@ -727,10 +725,6 @@ out_remove_trigger:
 	inv_mpu6050_remove_trigger(st);
 out_unreg_ring:
 	iio_triggered_buffer_cleanup(indio_dev);
-out_free:
-	iio_device_free(indio_dev);
-out_no_free:
-
 	return result;
 }
 
@@ -742,7 +736,6 @@ static int inv_mpu_remove(struct i2c_client *client)
 	iio_device_unregister(indio_dev);
 	inv_mpu6050_remove_trigger(st);
 	iio_triggered_buffer_cleanup(indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index e145931..97f0297 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -383,14 +383,14 @@ static ssize_t iio_read_channel_info(struct device *dev,
 		scale_db = true;
 	case IIO_VAL_INT_PLUS_MICRO:
 		if (val2 < 0)
-			return sprintf(buf, "-%d.%06u%s\n", val, -val2,
+			return sprintf(buf, "-%ld.%06u%s\n", abs(val), -val2,
 				scale_db ? " dB" : "");
 		else
 			return sprintf(buf, "%d.%06u%s\n", val, val2,
 				scale_db ? " dB" : "");
 	case IIO_VAL_INT_PLUS_NANO:
 		if (val2 < 0)
-			return sprintf(buf, "-%d.%09u\n", val, -val2);
+			return sprintf(buf, "-%ld.%09u\n", abs(val), -val2);
 		else
 			return sprintf(buf, "%d.%09u\n", val, val2);
 	case IIO_VAL_FRACTIONAL:
@@ -912,6 +912,53 @@ void iio_device_free(struct iio_dev *dev)
 }
 EXPORT_SYMBOL(iio_device_free);
 
+static void devm_iio_device_release(struct device *dev, void *res)
+{
+	iio_device_free(*(struct iio_dev **)res);
+}
+
+static int devm_iio_device_match(struct device *dev, void *res, void *data)
+{
+	struct iio_dev **r = res;
+	if (!r || !*r) {
+		WARN_ON(!r || !*r);
+		return 0;
+	}
+	return *r == data;
+}
+
+struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
+{
+	struct iio_dev **ptr, *iio_dev;
+
+	ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr),
+			   GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	/* use raw alloc_dr for kmalloc caller tracing */
+	iio_dev = iio_device_alloc(sizeof_priv);
+	if (iio_dev) {
+		*ptr = iio_dev;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return iio_dev;
+}
+EXPORT_SYMBOL_GPL(devm_iio_device_alloc);
+
+void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev)
+{
+	int rc;
+
+	rc = devres_release(dev, devm_iio_device_release,
+			    devm_iio_device_match, iio_dev);
+	WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_iio_device_free);
+
 /**
  * iio_chrdev_open() - chrdev file open for buffer access and ioctls
  **/
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index ea8a414..0dd9bb8 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -127,12 +127,17 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name,
 void iio_trigger_poll(struct iio_trigger *trig, s64 time)
 {
 	int i;
-	if (!trig->use_count)
-		for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
-			if (trig->subirqs[i].enabled) {
-				trig->use_count++;
+
+	if (!atomic_read(&trig->use_count)) {
+		atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
+
+		for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
+			if (trig->subirqs[i].enabled)
 				generic_handle_irq(trig->subirq_base + i);
-			}
+			else
+				iio_trigger_notify_done(trig);
+		}
+	}
 }
 EXPORT_SYMBOL(iio_trigger_poll);
 
@@ -146,19 +151,24 @@ EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
 void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
 {
 	int i;
-	if (!trig->use_count)
-		for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
-			if (trig->subirqs[i].enabled) {
-				trig->use_count++;
+
+	if (!atomic_read(&trig->use_count)) {
+		atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
+
+		for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
+			if (trig->subirqs[i].enabled)
 				handle_nested_irq(trig->subirq_base + i);
-			}
+			else
+				iio_trigger_notify_done(trig);
+		}
+	}
 }
 EXPORT_SYMBOL(iio_trigger_poll_chained);
 
 void iio_trigger_notify_done(struct iio_trigger *trig)
 {
-	trig->use_count--;
-	if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable)
+	if (atomic_dec_and_test(&trig->use_count) && trig->ops &&
+		trig->ops->try_reenable)
 		if (trig->ops->try_reenable(trig))
 			/* Missed an interrupt so launch new poll now */
 			iio_trigger_poll(trig, 0);
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 5ef1a39..bf9fa0d 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -1,6 +1,8 @@
 #
 # Light sensors
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Light sensors"
 
 config ADJD_S311
@@ -15,6 +17,27 @@ config ADJD_S311
 	 This driver can also be built as a module.  If so, the module
 	 will be called adjd_s311.
 
+config APDS9300
+	tristate "APDS9300 ambient light sensor"
+	depends on I2C
+	help
+	 Say Y here if you want to build a driver for the Avago APDS9300
+	 ambient light sensor.
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called apds9300.
+
+config HID_SENSOR_ALS
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
+	tristate "HID ALS"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  Ambient light sensor.
+
 config SENSORS_LM3533
 	tristate "LM3533 ambient light sensor"
 	depends on MFD_LM3533
@@ -52,15 +75,4 @@ config VCNL4000
 	 To compile this driver as a module, choose M here: the
 	 module will be called vcnl4000.
 
-config HID_SENSOR_ALS
-	depends on HID_SENSOR_HUB
-	select IIO_BUFFER
-	select IIO_TRIGGERED_BUFFER
-	select HID_SENSOR_IIO_COMMON
-	select HID_SENSOR_IIO_TRIGGER
-	tristate "HID ALS"
-	help
-	  Say yes here to build support for the HID SENSOR
-	  Ambient light sensor.
-
 endmenu
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 040d9c7..354ee9a 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -2,8 +2,10 @@
 # Makefile for IIO Light sensors
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_ADJD_S311)		+= adjd_s311.o
+obj-$(CONFIG_APDS9300)		+= apds9300.o
+obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_SENSORS_TSL2563)	+= tsl2563.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
-obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 5f4749e..55b9e18 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -293,11 +293,10 @@ static int adjd_s311_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*data));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
 	data = iio_priv(indio_dev);
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
@@ -312,7 +311,7 @@ static int adjd_s311_probe(struct i2c_client *client,
 	err = iio_triggered_buffer_setup(indio_dev, NULL,
 		adjd_s311_trigger_handler, NULL);
 	if (err < 0)
-		goto exit_free_device;
+		return err;
 
 	err = iio_device_register(indio_dev);
 	if (err)
@@ -324,9 +323,6 @@ static int adjd_s311_probe(struct i2c_client *client,
 
 exit_unreg_buffer:
 	iio_triggered_buffer_cleanup(indio_dev);
-exit_free_device:
-	iio_device_free(indio_dev);
-exit:
 	return err;
 }
 
@@ -338,7 +334,6 @@ static int adjd_s311_remove(struct i2c_client *client)
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	kfree(data->buffer);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
new file mode 100644
index 0000000..66a58bd
--- /dev/null
+++ b/drivers/iio/light/apds9300.c
@@ -0,0 +1,512 @@
+/*
+ * apds9300.c - IIO driver for Avago APDS9300 ambient light sensor
+ *
+ * Copyright 2013 Oleksandr Kravchenko <o.v.kravchenko@globallogic.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+
+#define APDS9300_DRV_NAME "apds9300"
+#define APDS9300_IRQ_NAME "apds9300_event"
+
+/* Command register bits */
+#define APDS9300_CMD	BIT(7) /* Select command register. Must write as 1 */
+#define APDS9300_WORD	BIT(5) /* I2C write/read: if 1 word, if 0 byte */
+#define APDS9300_CLEAR	BIT(6) /* Interrupt clear. Clears pending interrupt */
+
+/* Register set */
+#define APDS9300_CONTROL	0x00 /* Control of basic functions */
+#define APDS9300_THRESHLOWLOW	0x02 /* Low byte of low interrupt threshold */
+#define APDS9300_THRESHHIGHLOW	0x04 /* Low byte of high interrupt threshold */
+#define APDS9300_INTERRUPT	0x06 /* Interrupt control */
+#define APDS9300_DATA0LOW	0x0c /* Low byte of ADC channel 0 */
+#define APDS9300_DATA1LOW	0x0e /* Low byte of ADC channel 1 */
+
+/* Power on/off value for APDS9300_CONTROL register */
+#define APDS9300_POWER_ON	0x03
+#define APDS9300_POWER_OFF	0x00
+
+/* Interrupts */
+#define APDS9300_INTR_ENABLE	0x10
+/* Interrupt Persist Function: Any value outside of threshold range */
+#define APDS9300_THRESH_INTR	0x01
+
+#define APDS9300_THRESH_MAX	0xffff /* Max threshold value */
+
+struct apds9300_data {
+	struct i2c_client *client;
+	struct mutex mutex;
+	int power_state;
+	int thresh_low;
+	int thresh_hi;
+	int intr_en;
+};
+
+/* Lux calculation */
+
+/* Calculated values 1000 * (CH1/CH0)^1.4 for CH1/CH0 from 0 to 0.52 */
+static const u16 apds9300_lux_ratio[] = {
+	0, 2, 4, 7, 11, 15, 19, 24, 29, 34, 40, 45, 51, 57, 64, 70, 77, 84, 91,
+	98, 105, 112, 120, 128, 136, 144, 152, 160, 168, 177, 185, 194, 203,
+	212, 221, 230, 239, 249, 258, 268, 277, 287, 297, 307, 317, 327, 337,
+	347, 358, 368, 379, 390, 400,
+};
+
+static unsigned long apds9300_calculate_lux(u16 ch0, u16 ch1)
+{
+	unsigned long lux, tmp;
+
+	/* avoid division by zero */
+	if (ch0 == 0)
+		return 0;
+
+	tmp = DIV_ROUND_UP(ch1 * 100, ch0);
+	if (tmp <= 52) {
+		lux = 3150 * ch0 - (unsigned long)DIV_ROUND_UP_ULL(ch0
+				* apds9300_lux_ratio[tmp] * 5930ull, 1000);
+	} else if (tmp <= 65) {
+		lux = 2290 * ch0 - 2910 * ch1;
+	} else if (tmp <= 80) {
+		lux = 1570 * ch0 - 1800 * ch1;
+	} else if (tmp <= 130) {
+		lux = 338 * ch0 - 260 * ch1;
+	} else {
+		lux = 0;
+	}
+
+	return lux / 100000;
+}
+
+static int apds9300_get_adc_val(struct apds9300_data *data, int adc_number)
+{
+	int ret;
+	u8 flags = APDS9300_CMD | APDS9300_WORD;
+
+	if (!data->power_state)
+		return -EBUSY;
+
+	/* Select ADC0 or ADC1 data register */
+	flags |= adc_number ? APDS9300_DATA1LOW : APDS9300_DATA0LOW;
+
+	ret = i2c_smbus_read_word_data(data->client, flags);
+	if (ret < 0)
+		dev_err(&data->client->dev,
+			"failed to read ADC%d value\n", adc_number);
+
+	return ret;
+}
+
+static int apds9300_set_thresh_low(struct apds9300_data *data, int value)
+{
+	int ret;
+
+	if (!data->power_state)
+		return -EBUSY;
+
+	if (value > APDS9300_THRESH_MAX)
+		return -EINVAL;
+
+	ret = i2c_smbus_write_word_data(data->client, APDS9300_THRESHLOWLOW
+			| APDS9300_CMD | APDS9300_WORD, value);
+	if (ret) {
+		dev_err(&data->client->dev, "failed to set thresh_low\n");
+		return ret;
+	}
+	data->thresh_low = value;
+
+	return 0;
+}
+
+static int apds9300_set_thresh_hi(struct apds9300_data *data, int value)
+{
+	int ret;
+
+	if (!data->power_state)
+		return -EBUSY;
+
+	if (value > APDS9300_THRESH_MAX)
+		return -EINVAL;
+
+	ret = i2c_smbus_write_word_data(data->client, APDS9300_THRESHHIGHLOW
+			| APDS9300_CMD | APDS9300_WORD, value);
+	if (ret) {
+		dev_err(&data->client->dev, "failed to set thresh_hi\n");
+		return ret;
+	}
+	data->thresh_hi = value;
+
+	return 0;
+}
+
+static int apds9300_set_intr_state(struct apds9300_data *data, int state)
+{
+	int ret;
+	u8 cmd;
+
+	if (!data->power_state)
+		return -EBUSY;
+
+	cmd = state ? APDS9300_INTR_ENABLE | APDS9300_THRESH_INTR : 0x00;
+	ret = i2c_smbus_write_byte_data(data->client,
+			APDS9300_INTERRUPT | APDS9300_CMD, cmd);
+	if (ret) {
+		dev_err(&data->client->dev,
+			"failed to set interrupt state %d\n", state);
+		return ret;
+	}
+	data->intr_en = state;
+
+	return 0;
+}
+
+static int apds9300_set_power_state(struct apds9300_data *data, int state)
+{
+	int ret;
+	u8 cmd;
+
+	cmd = state ? APDS9300_POWER_ON : APDS9300_POWER_OFF;
+	ret = i2c_smbus_write_byte_data(data->client,
+			APDS9300_CONTROL | APDS9300_CMD, cmd);
+	if (ret) {
+		dev_err(&data->client->dev,
+			"failed to set power state %d\n", state);
+		return ret;
+	}
+	data->power_state = state;
+
+	return 0;
+}
+
+static void apds9300_clear_intr(struct apds9300_data *data)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte(data->client, APDS9300_CLEAR | APDS9300_CMD);
+	if (ret < 0)
+		dev_err(&data->client->dev, "failed to clear interrupt\n");
+}
+
+static int apds9300_chip_init(struct apds9300_data *data)
+{
+	int ret;
+
+	/* Need to set power off to ensure that the chip is off */
+	ret = apds9300_set_power_state(data, 0);
+	if (ret < 0)
+		goto err;
+	/*
+	 * Probe the chip. To do so we try to power up the device and then to
+	 * read back the 0x03 code
+	 */
+	ret = apds9300_set_power_state(data, 1);
+	if (ret < 0)
+		goto err;
+	ret = i2c_smbus_read_byte_data(data->client,
+			APDS9300_CONTROL | APDS9300_CMD);
+	if (ret != APDS9300_POWER_ON) {
+		ret = -ENODEV;
+		goto err;
+	}
+	/*
+	 * Disable interrupt to ensure thai it is doesn't enable
+	 * i.e. after device soft reset
+	 */
+	ret = apds9300_set_intr_state(data, 0);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(&data->client->dev, "failed to init the chip\n");
+	return ret;
+}
+
+static int apds9300_read_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan, int *val, int *val2,
+		long mask)
+{
+	int ch0, ch1, ret = -EINVAL;
+	struct apds9300_data *data = iio_priv(indio_dev);
+
+	mutex_lock(&data->mutex);
+	switch (chan->type) {
+	case IIO_LIGHT:
+		ch0 = apds9300_get_adc_val(data, 0);
+		if (ch0 < 0) {
+			ret = ch0;
+			break;
+		}
+		ch1 = apds9300_get_adc_val(data, 1);
+		if (ch1 < 0) {
+			ret = ch1;
+			break;
+		}
+		*val = apds9300_calculate_lux(ch0, ch1);
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_INTENSITY:
+		ret = apds9300_get_adc_val(data, chan->channel);
+		if (ret < 0)
+			break;
+		*val = ret;
+		ret = IIO_VAL_INT;
+		break;
+	default:
+		break;
+	}
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static int apds9300_read_thresh(struct iio_dev *indio_dev, u64 event_code,
+		int *val)
+{
+	struct apds9300_data *data = iio_priv(indio_dev);
+
+	switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	case IIO_EV_DIR_RISING:
+		*val = data->thresh_hi;
+		break;
+	case IIO_EV_DIR_FALLING:
+		*val = data->thresh_low;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int apds9300_write_thresh(struct iio_dev *indio_dev, u64 event_code,
+		int val)
+{
+	struct apds9300_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
+		ret = apds9300_set_thresh_hi(data, val);
+	else
+		ret = apds9300_set_thresh_low(data, val);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
+		u64 event_code)
+{
+	struct apds9300_data *data = iio_priv(indio_dev);
+
+	return data->intr_en;
+}
+
+static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
+		u64 event_code, int state)
+{
+	struct apds9300_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	ret = apds9300_set_intr_state(data, state);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static const struct iio_info apds9300_info_no_irq = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= apds9300_read_raw,
+};
+
+static const struct iio_info apds9300_info = {
+	.driver_module		= THIS_MODULE,
+	.read_raw		= apds9300_read_raw,
+	.read_event_value	= apds9300_read_thresh,
+	.write_event_value	= apds9300_write_thresh,
+	.read_event_config	= apds9300_read_interrupt_config,
+	.write_event_config	= apds9300_write_interrupt_config,
+};
+
+static const struct iio_chan_spec apds9300_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.channel = 0,
+		.indexed = true,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+	}, {
+		.type = IIO_INTENSITY,
+		.channel = 0,
+		.channel2 = IIO_MOD_LIGHT_BOTH,
+		.indexed = true,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
+					  IIO_EV_DIR_RISING) |
+			       IIO_EV_BIT(IIO_EV_TYPE_THRESH,
+					  IIO_EV_DIR_FALLING)),
+	}, {
+		.type = IIO_INTENSITY,
+		.channel = 1,
+		.channel2 = IIO_MOD_LIGHT_IR,
+		.indexed = true,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	},
+};
+
+static irqreturn_t apds9300_interrupt_handler(int irq, void *private)
+{
+	struct iio_dev *dev_info = private;
+	struct apds9300_data *data = iio_priv(dev_info);
+
+	iio_push_event(dev_info,
+		       IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0,
+					    IIO_EV_TYPE_THRESH,
+					    IIO_EV_DIR_EITHER),
+		       iio_get_time_ns());
+
+	apds9300_clear_intr(data);
+
+	return IRQ_HANDLED;
+}
+
+static int apds9300_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct apds9300_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+
+	ret = apds9300_chip_init(data);
+	if (ret < 0)
+		goto err;
+
+	mutex_init(&data->mutex);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = apds9300_channels;
+	indio_dev->num_channels = ARRAY_SIZE(apds9300_channels);
+	indio_dev->name = APDS9300_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	if (client->irq)
+		indio_dev->info = &apds9300_info;
+	else
+		indio_dev->info = &apds9300_info_no_irq;
+
+	if (client->irq) {
+		ret = devm_request_threaded_irq(&client->dev, client->irq,
+				NULL, apds9300_interrupt_handler,
+				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				APDS9300_IRQ_NAME, indio_dev);
+		if (ret) {
+			dev_err(&client->dev, "irq request error %d\n", -ret);
+			goto err;
+		}
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	/* Ensure that power off in case of error */
+	apds9300_set_power_state(data, 0);
+	return ret;
+}
+
+static int apds9300_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct apds9300_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	/* Ensure that power off and interrupts are disabled */
+	apds9300_set_intr_state(data, 0);
+	apds9300_set_power_state(data, 0);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int apds9300_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct apds9300_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	ret = apds9300_set_power_state(data, 0);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static int apds9300_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct apds9300_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	ret = apds9300_set_power_state(data, 1);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume);
+#define APDS9300_PM_OPS (&apds9300_pm_ops)
+#else
+#define APDS9300_PM_OPS NULL
+#endif
+
+static struct i2c_device_id apds9300_id[] = {
+	{ APDS9300_DRV_NAME, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, apds9300_id);
+
+static struct i2c_driver apds9300_driver = {
+	.driver = {
+		.name	= APDS9300_DRV_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= APDS9300_PM_OPS,
+	},
+	.probe		= apds9300_probe,
+	.remove		= apds9300_remove,
+	.id_table	= apds9300_id,
+};
+
+module_i2c_driver(apds9300_driver);
+
+MODULE_AUTHOR("Kravchenko Oleksandr <o.v.kravchenko@globallogic.com>");
+MODULE_AUTHOR("GlobalLogic inc.");
+MODULE_DESCRIPTION("APDS9300 ambient light photo sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index cdc2cad..84cf004 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -30,10 +30,6 @@
 #include <linux/iio/triggered_buffer.h>
 #include "../common/hid-sensors/hid-sensor-trigger.h"
 
-/*Format: HID-SENSOR-usage_id_in_hex*/
-/*Usage ID from spec for Ambiant-Light: 0x200041*/
-#define DRIVER_NAME "HID-SENSOR-200041"
-
 #define CHANNEL_SCAN_INDEX_ILLUM 0
 
 struct als_state {
@@ -253,11 +249,9 @@ static int hid_als_probe(struct platform_device *pdev)
 	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 	struct iio_chan_spec *channels;
 
-	indio_dev = iio_device_alloc(sizeof(struct als_state));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
+	if (!indio_dev)
+		return -ENOMEM;
 	platform_set_drvdata(pdev, indio_dev);
 
 	als_state = iio_priv(indio_dev);
@@ -268,14 +262,13 @@ static int hid_als_probe(struct platform_device *pdev)
 					&als_state->common_attributes);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to setup common attributes\n");
-		goto error_free_dev;
+		return ret;
 	}
 
 	channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL);
 	if (!channels) {
-		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
-		goto error_free_dev;
+		return -ENOMEM;
 	}
 
 	ret = als_parse_report(pdev, hsdev, channels,
@@ -333,9 +326,6 @@ error_unreg_buffer_funcs:
 	iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
 	kfree(indio_dev->channels);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
 	return ret;
 }
 
@@ -350,14 +340,23 @@ static int hid_als_remove(struct platform_device *pdev)
 	hid_sensor_remove_trigger(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	kfree(indio_dev->channels);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
 
+static struct platform_device_id hid_als_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-200041",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_als_ids);
+
 static struct platform_driver hid_als_platform_driver = {
+	.id_table = hid_als_ids,
 	.driver = {
-		.name	= DRIVER_NAME,
+		.name	= KBUILD_MODNAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= hid_als_probe,
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 5fa31a4..c1aadc6 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -847,7 +847,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*als));
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*als));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -870,7 +870,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
 	if (als->irq) {
 		ret = lm3533_als_setup_irq(als, indio_dev);
 		if (ret)
-			goto err_free_dev;
+			return ret;
 	}
 
 	ret = lm3533_als_setup(als, pdata);
@@ -894,8 +894,6 @@ err_disable:
 err_free_irq:
 	if (als->irq)
 		free_irq(als->irq, indio_dev);
-err_free_dev:
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -910,7 +908,6 @@ static int lm3533_als_remove(struct platform_device *pdev)
 	lm3533_als_disable(als);
 	if (als->irq)
 		free_irq(als->irq, indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index 1f529f3..ebb962c 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -702,7 +702,7 @@ static int tsl2563_probe(struct i2c_client *client,
 	int err = 0;
 	u8 id = 0;
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -714,13 +714,13 @@ static int tsl2563_probe(struct i2c_client *client,
 	err = tsl2563_detect(chip);
 	if (err) {
 		dev_err(&client->dev, "detect error %d\n", -err);
-		goto fail1;
+		return err;
 	}
 
 	err = tsl2563_read_id(chip, &id);
 	if (err) {
 		dev_err(&client->dev, "read id error %d\n", -err);
-		goto fail1;
+		return err;
 	}
 
 	mutex_init(&chip->lock);
@@ -751,7 +751,7 @@ static int tsl2563_probe(struct i2c_client *client,
 		indio_dev->info = &tsl2563_info_no_irq;
 
 	if (client->irq) {
-		err = request_threaded_irq(client->irq,
+		err = devm_request_threaded_irq(&client->dev, client->irq,
 					   NULL,
 					   &tsl2563_event_handler,
 					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -759,14 +759,14 @@ static int tsl2563_probe(struct i2c_client *client,
 					   indio_dev);
 		if (err) {
 			dev_err(&client->dev, "irq request error %d\n", -err);
-			goto fail1;
+			return err;
 		}
 	}
 
 	err = tsl2563_configure(chip);
 	if (err) {
 		dev_err(&client->dev, "configure error %d\n", -err);
-		goto fail2;
+		return err;
 	}
 
 	INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work);
@@ -777,19 +777,14 @@ static int tsl2563_probe(struct i2c_client *client,
 	err = iio_device_register(indio_dev);
 	if (err) {
 		dev_err(&client->dev, "iio registration error %d\n", -err);
-		goto fail3;
+		goto fail;
 	}
 
 	return 0;
 
-fail3:
+fail:
 	cancel_delayed_work(&chip->poweroff_work);
 	flush_scheduled_work();
-fail2:
-	if (client->irq)
-		free_irq(client->irq, indio_dev);
-fail1:
-	iio_device_free(indio_dev);
 	return err;
 }
 
@@ -807,10 +802,6 @@ static int tsl2563_remove(struct i2c_client *client)
 				  chip->intr);
 	flush_scheduled_work();
 	tsl2563_set_power(chip, 0);
-	if (client->irq)
-		free_irq(client->irq, indio_dev);
-
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 1014943..2bb3042 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -157,7 +157,7 @@ static int vcnl4000_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*data));
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -167,7 +167,7 @@ static int vcnl4000_probe(struct i2c_client *client,
 
 	ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
 	if (ret < 0)
-		goto error_free_dev;
+		return ret;
 
 	dev_info(&client->dev, "VCNL4000 Ambient light/proximity sensor, Prod %02x, Rev: %02x\n",
 		ret >> 4, ret & 0xf);
@@ -181,22 +181,14 @@ static int vcnl4000_probe(struct i2c_client *client,
 
 	ret = iio_device_register(indio_dev);
 	if (ret < 0)
-		goto error_free_dev;
+		return ret;
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-	return ret;
 }
 
 static int vcnl4000_remove(struct i2c_client *client)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
-	iio_device_unregister(indio_dev);
-	iio_device_free(indio_dev);
-
+	iio_device_unregister(i2c_get_clientdata(client));
 	return 0;
 }
 
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index c332b0a..4fa923f 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -1,6 +1,8 @@
 #
 # Magnetometer sensors
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Magnetometer sensors"
 
 config AK8975
@@ -36,8 +38,8 @@ config IIO_ST_MAGN_3AXIS
 	  Say yes here to build support for STMicroelectronics magnetometers:
 	  LSM303DLHC, LSM303DLM, LIS3MDL.
 
-	  This driver can also be built as a module. If so, will be created
-	  these modules:
+	  This driver can also be built as a module. If so, these modules
+	  will be created:
 	  - st_magn (core functions for the driver [it is mandatory]);
 	  - st_magn_i2c (necessary for the I2C devices [optional*]);
 	  - st_magn_spi (necessary for the SPI devices [optional*]);
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index 7f328e3..f91b1b6 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -2,6 +2,7 @@
 # Makefile for industrial I/O Magnetometer sensor drivers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AK8975)	+= ak8975.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
 
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 99f4e49..5a6162d 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -30,10 +30,6 @@
 #include <linux/iio/triggered_buffer.h>
 #include "../common/hid-sensors/hid-sensor-trigger.h"
 
-/*Format: HID-SENSOR-usage_id_in_hex*/
-/*Usage ID from spec for Magnetometer-3D: 0x200083*/
-#define DRIVER_NAME "HID-SENSOR-200083"
-
 enum magn_3d_channel {
 	CHANNEL_SCAN_INDEX_X,
 	CHANNEL_SCAN_INDEX_Y,
@@ -287,11 +283,11 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
 	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 	struct iio_chan_spec *channels;
 
-	indio_dev = iio_device_alloc(sizeof(struct magn_3d_state));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+					  sizeof(struct magn_3d_state));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	magn_state = iio_priv(indio_dev);
@@ -303,15 +299,14 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
 				&magn_state->common_attributes);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to setup common attributes\n");
-		goto error_free_dev;
+		return ret;
 	}
 
 	channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
 			   GFP_KERNEL);
 	if (!channels) {
-		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
-		goto error_free_dev;
+		return -ENOMEM;
 	}
 
 	ret = magn_3d_parse_report(pdev, hsdev, channels,
@@ -368,9 +363,6 @@ error_unreg_buffer_funcs:
 	iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
 	kfree(indio_dev->channels);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
 	return ret;
 }
 
@@ -385,14 +377,23 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
 	hid_sensor_remove_trigger(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	kfree(indio_dev->channels);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
 
+static struct platform_device_id hid_magn_3d_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-200083",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_magn_3d_ids);
+
 static struct platform_driver hid_magn_3d_platform_driver = {
+	.id_table = hid_magn_3d_ids,
 	.driver = {
-		.name	= DRIVER_NAME,
+		.name	= KBUILD_MODNAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= hid_magn_3d_probe,
diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
index 7e81d00..694e33e 100644
--- a/drivers/iio/magnetometer/st_magn.h
+++ b/drivers/iio/magnetometer/st_magn.h
@@ -18,7 +18,8 @@
 #define LSM303DLM_MAGN_DEV_NAME		"lsm303dlm_magn"
 #define LIS3MDL_MAGN_DEV_NAME		"lis3mdl"
 
-int st_magn_common_probe(struct iio_dev *indio_dev);
+int st_magn_common_probe(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata);
 void st_magn_common_remove(struct iio_dev *indio_dev);
 
 #ifdef CONFIG_IIO_BUFFER
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index ebfe8f1..e8d2849 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -345,7 +345,8 @@ static const struct iio_info magn_info = {
 	.write_raw = &st_magn_write_raw,
 };
 
-int st_magn_common_probe(struct iio_dev *indio_dev)
+int st_magn_common_probe(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata)
 {
 	int err;
 	struct st_sensor_data *mdata = iio_priv(indio_dev);
@@ -367,7 +368,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
 						&mdata->sensor->fs.fs_avl[0];
 	mdata->odr = mdata->sensor->odr.odr_avl[0].hz;
 
-	err = st_sensors_init_sensor(indio_dev);
+	err = st_sensors_init_sensor(indio_dev, pdata);
 	if (err < 0)
 		goto st_magn_common_probe_error;
 
@@ -406,7 +407,6 @@ void st_magn_common_remove(struct iio_dev *indio_dev)
 		st_sensors_deallocate_trigger(indio_dev);
 		st_magn_deallocate_ring(indio_dev);
 	}
-	iio_device_free(indio_dev);
 }
 EXPORT_SYMBOL(st_magn_common_remove);
 
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index e6adc4a..892e0fe 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -25,27 +25,20 @@ static int st_magn_i2c_probe(struct i2c_client *client,
 	struct st_sensor_data *mdata;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*mdata));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto iio_device_alloc_error;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	mdata = iio_priv(indio_dev);
 	mdata->dev = &client->dev;
 
 	st_sensors_i2c_configure(indio_dev, client, mdata);
 
-	err = st_magn_common_probe(indio_dev);
+	err = st_magn_common_probe(indio_dev, NULL);
 	if (err < 0)
-		goto st_magn_common_probe_error;
+		return err;
 
 	return 0;
-
-st_magn_common_probe_error:
-	iio_device_free(indio_dev);
-iio_device_alloc_error:
-	return err;
 }
 
 static int st_magn_i2c_remove(struct i2c_client *client)
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index 51adb79..a6143ea 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -24,27 +24,20 @@ static int st_magn_spi_probe(struct spi_device *spi)
 	struct st_sensor_data *mdata;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*mdata));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto iio_device_alloc_error;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*mdata));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	mdata = iio_priv(indio_dev);
 	mdata->dev = &spi->dev;
 
 	st_sensors_spi_configure(indio_dev, spi, mdata);
 
-	err = st_magn_common_probe(indio_dev);
+	err = st_magn_common_probe(indio_dev, NULL);
 	if (err < 0)
-		goto st_magn_common_probe_error;
+		return err;
 
 	return 0;
-
-st_magn_common_probe_error:
-	iio_device_free(indio_dev);
-iio_device_alloc_error:
-	return err;
 }
 
 static int st_magn_spi_remove(struct spi_device *spi)
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 9427f01..26fdc0b 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -1,21 +1,23 @@
 #
 # Pressure drivers
 #
-menu "Pressure Sensors"
+# When adding new entries keep the list in alphabetical order
+
+menu "Pressure sensors"
 
 config IIO_ST_PRESS
-	tristate "STMicroelectronics pressures Driver"
+	tristate "STMicroelectronics pressure sensor Driver"
 	depends on (I2C || SPI_MASTER) && SYSFS
 	select IIO_ST_SENSORS_CORE
 	select IIO_ST_PRESS_I2C if (I2C)
 	select IIO_ST_PRESS_SPI if (SPI_MASTER)
 	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
 	help
-	  Say yes here to build support for STMicroelectronics pressures:
-	  LPS331AP.
+	  Say yes here to build support for STMicroelectronics pressure
+	  sensors: LPS331AP.
 
-	  This driver can also be built as a module. If so, will be created
-	  these modules:
+	  This driver can also be built as a module. If so, these modules
+	  will be created:
 	  - st_pressure (core functions for the driver [it is mandatory]);
 	  - st_pressure_i2c (necessary for the I2C devices [optional*]);
 	  - st_pressure_spi (necessary for the SPI devices [optional*]);
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index d4bb33e..be71464 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -2,6 +2,7 @@
 # Makefile for industrial I/O pressure drivers
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
 st_pressure-y := st_pressure_core.o
 st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h
index 414e45a..b0b6306 100644
--- a/drivers/iio/pressure/st_pressure.h
+++ b/drivers/iio/pressure/st_pressure.h
@@ -16,7 +16,16 @@
 
 #define LPS331AP_PRESS_DEV_NAME		"lps331ap"
 
-int st_press_common_probe(struct iio_dev *indio_dev);
+/**
+ * struct st_sensors_platform_data - default press platform data
+ * @drdy_int_pin: default press DRDY is available on INT1 pin.
+ */
+static const struct st_sensors_platform_data default_press_pdata = {
+	.drdy_int_pin = 1,
+};
+
+int st_press_common_probe(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata);
 void st_press_common_remove(struct iio_dev *indio_dev);
 
 #ifdef CONFIG_IIO_BUFFER
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index 3ffbc56..ceebd3c 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -31,6 +31,9 @@
 #define ST_PRESS_LSB_PER_MBAR			4096UL
 #define ST_PRESS_KPASCAL_NANO_SCALE		(100000000UL / \
 						 ST_PRESS_LSB_PER_MBAR)
+#define ST_PRESS_LSB_PER_CELSIUS		480UL
+#define ST_PRESS_CELSIUS_NANO_SCALE		(1000000000UL / \
+						 ST_PRESS_LSB_PER_CELSIUS)
 #define ST_PRESS_NUMBER_DATA_CHANNELS		1
 
 /* DEFAULT VALUE FOR SENSORS */
@@ -53,12 +56,13 @@
 #define ST_PRESS_1_FS_ADDR			0x23
 #define ST_PRESS_1_FS_MASK			0x30
 #define ST_PRESS_1_FS_AVL_1260_VAL		0x00
-#define ST_PRESS_1_FS_AVL_TEMP_GAIN		2083000
 #define ST_PRESS_1_FS_AVL_1260_GAIN		ST_PRESS_KPASCAL_NANO_SCALE
+#define ST_PRESS_1_FS_AVL_TEMP_GAIN		ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_1_BDU_ADDR			0x20
 #define ST_PRESS_1_BDU_MASK			0x04
 #define ST_PRESS_1_DRDY_IRQ_ADDR		0x22
-#define ST_PRESS_1_DRDY_IRQ_MASK		0x04
+#define ST_PRESS_1_DRDY_IRQ_INT1_MASK		0x04
+#define ST_PRESS_1_DRDY_IRQ_INT2_MASK		0x20
 #define ST_PRESS_1_MULTIREAD_BIT		true
 #define ST_PRESS_1_TEMP_OFFSET			42500
 
@@ -116,7 +120,8 @@ static const struct st_sensors st_press_sensors[] = {
 		},
 		.drdy_irq = {
 			.addr = ST_PRESS_1_DRDY_IRQ_ADDR,
-			.mask = ST_PRESS_1_DRDY_IRQ_MASK,
+			.mask_int1 = ST_PRESS_1_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_PRESS_1_DRDY_IRQ_INT2_MASK,
 		},
 		.multi_read_bit = ST_PRESS_1_MULTIREAD_BIT,
 		.bootime = 2,
@@ -202,7 +207,8 @@ static const struct iio_trigger_ops st_press_trigger_ops = {
 #define ST_PRESS_TRIGGER_OPS NULL
 #endif
 
-int st_press_common_probe(struct iio_dev *indio_dev)
+int st_press_common_probe(struct iio_dev *indio_dev,
+				struct st_sensors_platform_data *plat_data)
 {
 	int err;
 	struct st_sensor_data *pdata = iio_priv(indio_dev);
@@ -224,7 +230,11 @@ int st_press_common_probe(struct iio_dev *indio_dev)
 						&pdata->sensor->fs.fs_avl[0];
 	pdata->odr = pdata->sensor->odr.odr_avl[0].hz;
 
-	err = st_sensors_init_sensor(indio_dev);
+	if (!plat_data)
+		plat_data =
+			(struct st_sensors_platform_data *)&default_press_pdata;
+
+	err = st_sensors_init_sensor(indio_dev, plat_data);
 	if (err < 0)
 		goto st_press_common_probe_error;
 
@@ -265,7 +275,6 @@ void st_press_common_remove(struct iio_dev *indio_dev)
 		st_sensors_deallocate_trigger(indio_dev);
 		st_press_deallocate_ring(indio_dev);
 	}
-	iio_device_free(indio_dev);
 }
 EXPORT_SYMBOL(st_press_common_remove);
 
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 7cebcc7..08aac5e 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -25,27 +25,20 @@ static int st_press_i2c_probe(struct i2c_client *client,
 	struct st_sensor_data *pdata;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*pdata));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto iio_device_alloc_error;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*pdata));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	pdata = iio_priv(indio_dev);
 	pdata->dev = &client->dev;
 
 	st_sensors_i2c_configure(indio_dev, client, pdata);
 
-	err = st_press_common_probe(indio_dev);
+	err = st_press_common_probe(indio_dev, client->dev.platform_data);
 	if (err < 0)
-		goto st_press_common_probe_error;
+		return err;
 
 	return 0;
-
-st_press_common_probe_error:
-	iio_device_free(indio_dev);
-iio_device_alloc_error:
-	return err;
 }
 
 static int st_press_i2c_remove(struct i2c_client *client)
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index 17a1490..399a29b 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -24,27 +24,20 @@ static int st_press_spi_probe(struct spi_device *spi)
 	struct st_sensor_data *pdata;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*pdata));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto iio_device_alloc_error;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*pdata));
+	if (indio_dev == NULL)
+		return -ENOMEM;
 
 	pdata = iio_priv(indio_dev);
 	pdata->dev = &spi->dev;
 
 	st_sensors_spi_configure(indio_dev, spi, pdata);
 
-	err = st_press_common_probe(indio_dev);
+	err = st_press_common_probe(indio_dev, spi->dev.platform_data);
 	if (err < 0)
-		goto st_press_common_probe_error;
+		return err;
 
 	return 0;
-
-st_press_common_probe_error:
-	iio_device_free(indio_dev);
-iio_device_alloc_error:
-	return err;
 }
 
 static int st_press_spi_remove(struct spi_device *spi)
diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig
index 360fd50..7999612 100644
--- a/drivers/iio/trigger/Kconfig
+++ b/drivers/iio/trigger/Kconfig
@@ -1,6 +1,8 @@
 #
 # Industrial I/O standalone triggers
 #
+# When adding new entries keep the list in alphabetical order
+
 menu "Triggers - standalone"
 
 config IIO_INTERRUPT_TRIGGER
@@ -17,7 +19,7 @@ config IIO_SYSFS_TRIGGER
 	depends on SYSFS
 	select IRQ_WORK
 	help
-	  Provides support for using SYSFS entry as IIO triggers.
+	  Provides support for using SYSFS entries as IIO triggers.
 	  If unsure, say N (but it's safe to say "Y").
 
 	  To compile this driver as a module, choose M here: the
diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile
index ce319a5..0694dae 100644
--- a/drivers/iio/trigger/Makefile
+++ b/drivers/iio/trigger/Makefile
@@ -2,5 +2,6 @@
 # Makefile for triggers not associated with iio-devices
 #
 
+# When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o
 obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 784b97c..f2ef7ef 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -383,14 +383,11 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
 {
 	unsigned long flags;
 	int id;
-	static int next_id;
 
 	idr_preload(GFP_KERNEL);
 	spin_lock_irqsave(&cm.lock, flags);
 
-	id = idr_alloc(&cm.local_id_table, cm_id_priv, next_id, 0, GFP_NOWAIT);
-	if (id >= 0)
-		next_id = max(id + 1, 0);
+	id = idr_alloc_cyclic(&cm.local_id_table, cm_id_priv, 0, 0, GFP_NOWAIT);
 
 	spin_unlock_irqrestore(&cm.lock, flags);
 	idr_preload_end();
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 7c0f953..6bd197f 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -3208,7 +3208,7 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
 						id_priv->id.port_num, &rec,
 						comp_mask, GFP_KERNEL,
 						cma_ib_mc_handler, mc);
-	return PTR_RET(mc->multicast.ib);
+	return PTR_ERR_OR_ZERO(mc->multicast.ib);
 }
 
 static void iboe_mcast_work_handler(struct work_struct *work)
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 8ab4f41..f5ff657 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -31,8 +31,8 @@
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
 
-#include <mach/iommu_hw-8xxx.h>
-#include <mach/iommu.h>
+#include "msm_iommu_hw-8xxx.h"
+#include "msm_iommu.h"
 
 #define MRC(reg, processor, op1, crn, crm, op2)				\
 __asm__ __volatile__ (							\
diff --git a/drivers/iommu/msm_iommu.h b/drivers/iommu/msm_iommu.h
new file mode 100644
index 0000000..5c7c955
--- /dev/null
+++ b/drivers/iommu/msm_iommu.h
@@ -0,0 +1,120 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef MSM_IOMMU_H
+#define MSM_IOMMU_H
+
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+
+/* Sharability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NON_SH		0x0
+#define MSM_IOMMU_ATTR_SH		0x4
+
+/* Cacheability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NONCACHED	0x0
+#define MSM_IOMMU_ATTR_CACHED_WB_WA	0x1
+#define MSM_IOMMU_ATTR_CACHED_WB_NWA	0x2
+#define MSM_IOMMU_ATTR_CACHED_WT	0x3
+
+/* Mask for the cache policy attribute */
+#define MSM_IOMMU_CP_MASK		0x03
+
+/* Maximum number of Machine IDs that we are allowing to be mapped to the same
+ * context bank. The number of MIDs mapped to the same CB does not affect
+ * performance, but there is a practical limit on how many distinct MIDs may
+ * be present. These mappings are typically determined at design time and are
+ * not expected to change at run time.
+ */
+#define MAX_NUM_MIDS	32
+
+/**
+ * struct msm_iommu_dev - a single IOMMU hardware instance
+ * name		Human-readable name given to this IOMMU HW instance
+ * ncb		Number of context banks present on this IOMMU HW instance
+ */
+struct msm_iommu_dev {
+	const char *name;
+	int ncb;
+};
+
+/**
+ * struct msm_iommu_ctx_dev - an IOMMU context bank instance
+ * name		Human-readable name given to this context bank
+ * num		Index of this context bank within the hardware
+ * mids		List of Machine IDs that are to be mapped into this context
+ *		bank, terminated by -1. The MID is a set of signals on the
+ *		AXI bus that identifies the function associated with a specific
+ *		memory request. (See ARM spec).
+ */
+struct msm_iommu_ctx_dev {
+	const char *name;
+	int num;
+	int mids[MAX_NUM_MIDS];
+};
+
+
+/**
+ * struct msm_iommu_drvdata - A single IOMMU hardware instance
+ * @base:	IOMMU config port base address (VA)
+ * @ncb		The number of contexts on this IOMMU
+ * @irq:	Interrupt number
+ * @clk:	The bus clock for this IOMMU hardware instance
+ * @pclk:	The clock for the IOMMU bus interconnect
+ *
+ * A msm_iommu_drvdata holds the global driver data about a single piece
+ * of an IOMMU hardware instance.
+ */
+struct msm_iommu_drvdata {
+	void __iomem *base;
+	int irq;
+	int ncb;
+	struct clk *clk;
+	struct clk *pclk;
+};
+
+/**
+ * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
+ * @num:		Hardware context number of this context
+ * @pdev:		Platform device associated wit this HW instance
+ * @attached_elm:	List element for domains to track which devices are
+ *			attached to them
+ *
+ * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
+ * within each IOMMU hardware instance
+ */
+struct msm_iommu_ctx_drvdata {
+	int num;
+	struct platform_device *pdev;
+	struct list_head attached_elm;
+};
+
+/*
+ * Look up an IOMMU context device by its context name. NULL if none found.
+ * Useful for testing and drivers that do not yet fully have IOMMU stuff in
+ * their platform devices.
+ */
+struct device *msm_iommu_get_ctx(const char *ctx_name);
+
+/*
+ * Interrupt handler for the IOMMU context fault interrupt. Hooking the
+ * interrupt is not supported in the API yet, but this will print an error
+ * message and dump useful IOMMU registers.
+ */
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
+
+#endif
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 6ba3514..0a1c962 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -27,8 +27,8 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 
-#include <mach/iommu_hw-8xxx.h>
-#include <mach/iommu.h>
+#include "msm_iommu_hw-8xxx.h"
+#include "msm_iommu.h"
 
 struct iommu_ctx_iter_data {
 	/* input */
diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
new file mode 100644
index 0000000..fc16010
--- /dev/null
+++ b/drivers/iommu/msm_iommu_hw-8xxx.h
@@ -0,0 +1,1865 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+
+#define CTX_SHIFT 12
+
+#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg)))
+#define GET_CTX_REG(reg, base, ctx) \
+				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
+
+#define SET_CTX_REG(reg, base, ctx, val) \
+			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+/* Wrappers for numbered registers */
+#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
+#define GET_GLOBAL_REG_N(b, n, r)    GET_GLOBAL_REG(b, ((r) + (n << 2)))
+
+/* Field wrappers */
+#define GET_GLOBAL_FIELD(b, r, F)    GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT)
+#define GET_CONTEXT_FIELD(b, c, r, F)	\
+	GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT)
+
+#define SET_GLOBAL_FIELD(b, r, F, v) \
+	SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v))
+#define SET_CONTEXT_FIELD(b, c, r, F, v)	\
+	SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
+
+#define GET_FIELD(addr, mask, shift)  ((readl(addr) >> (shift)) & (mask))
+
+#define SET_FIELD(addr, mask, shift, v) \
+do { \
+	int t = readl(addr); \
+	writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+} while (0)
+
+
+#define NUM_FL_PTE	4096
+#define NUM_SL_PTE	256
+#define NUM_TEX_CLASS	8
+
+/* First-level page table bits */
+#define FL_BASE_MASK		0xFFFFFC00
+#define FL_TYPE_TABLE		(1 << 0)
+#define FL_TYPE_SECT		(2 << 0)
+#define FL_SUPERSECTION		(1 << 18)
+#define FL_AP_WRITE		(1 << 10)
+#define FL_AP_READ		(1 << 11)
+#define FL_SHARED		(1 << 16)
+#define FL_BUFFERABLE		(1 << 2)
+#define FL_CACHEABLE		(1 << 3)
+#define FL_TEX0			(1 << 12)
+#define FL_OFFSET(va)		(((va) & 0xFFF00000) >> 20)
+#define FL_NG			(1 << 17)
+
+/* Second-level page table bits */
+#define SL_BASE_MASK_LARGE	0xFFFF0000
+#define SL_BASE_MASK_SMALL	0xFFFFF000
+#define SL_TYPE_LARGE		(1 << 0)
+#define SL_TYPE_SMALL		(2 << 0)
+#define SL_AP0			(1 << 4)
+#define SL_AP1			(2 << 4)
+#define SL_SHARED		(1 << 10)
+#define SL_BUFFERABLE		(1 << 2)
+#define SL_CACHEABLE		(1 << 3)
+#define SL_TEX0			(1 << 6)
+#define SL_OFFSET(va)		(((va) & 0xFF000) >> 12)
+#define SL_NG			(1 << 11)
+
+/* Memory type and cache policy attributes */
+#define MT_SO			0
+#define MT_DEV			1
+#define MT_NORMAL		2
+#define CP_NONCACHED		0
+#define CP_WB_WA		1
+#define CP_WT			2
+#define CP_WB_NWA		3
+
+/* Global register setters / getters */
+#define SET_M2VCBR_N(b, N, v)	 SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
+#define SET_CBACR_N(b, N, v)	 SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
+#define SET_TLBRSW(b, v)	 SET_GLOBAL_REG(TLBRSW, (b), (v))
+#define SET_TLBTR0(b, v)	 SET_GLOBAL_REG(TLBTR0, (b), (v))
+#define SET_TLBTR1(b, v)	 SET_GLOBAL_REG(TLBTR1, (b), (v))
+#define SET_TLBTR2(b, v)	 SET_GLOBAL_REG(TLBTR2, (b), (v))
+#define SET_TESTBUSCR(b, v)	 SET_GLOBAL_REG(TESTBUSCR, (b), (v))
+#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v))
+#define SET_TLBIVMID(b, v)	 SET_GLOBAL_REG(TLBIVMID, (b), (v))
+#define SET_CR(b, v)		 SET_GLOBAL_REG(CR, (b), (v))
+#define SET_EAR(b, v)		 SET_GLOBAL_REG(EAR, (b), (v))
+#define SET_ESR(b, v)		 SET_GLOBAL_REG(ESR, (b), (v))
+#define SET_ESRRESTORE(b, v)	 SET_GLOBAL_REG(ESRRESTORE, (b), (v))
+#define SET_ESYNR0(b, v)	 SET_GLOBAL_REG(ESYNR0, (b), (v))
+#define SET_ESYNR1(b, v)	 SET_GLOBAL_REG(ESYNR1, (b), (v))
+#define SET_RPU_ACR(b, v)	 SET_GLOBAL_REG(RPU_ACR, (b), (v))
+
+#define GET_M2VCBR_N(b, N)	 GET_GLOBAL_REG_N(M2VCBR_N, N, (b))
+#define GET_CBACR_N(b, N)	 GET_GLOBAL_REG_N(CBACR_N, N, (b))
+#define GET_TLBTR0(b)		 GET_GLOBAL_REG(TLBTR0, (b))
+#define GET_TLBTR1(b)		 GET_GLOBAL_REG(TLBTR1, (b))
+#define GET_TLBTR2(b)		 GET_GLOBAL_REG(TLBTR2, (b))
+#define GET_TESTBUSCR(b)	 GET_GLOBAL_REG(TESTBUSCR, (b))
+#define GET_GLOBAL_TLBIALL(b)	 GET_GLOBAL_REG(GLOBAL_TLBIALL, (b))
+#define GET_TLBIVMID(b)		 GET_GLOBAL_REG(TLBIVMID, (b))
+#define GET_CR(b)		 GET_GLOBAL_REG(CR, (b))
+#define GET_EAR(b)		 GET_GLOBAL_REG(EAR, (b))
+#define GET_ESR(b)		 GET_GLOBAL_REG(ESR, (b))
+#define GET_ESRRESTORE(b)	 GET_GLOBAL_REG(ESRRESTORE, (b))
+#define GET_ESYNR0(b)		 GET_GLOBAL_REG(ESYNR0, (b))
+#define GET_ESYNR1(b)		 GET_GLOBAL_REG(ESYNR1, (b))
+#define GET_REV(b)		 GET_GLOBAL_REG(REV, (b))
+#define GET_IDR(b)		 GET_GLOBAL_REG(IDR, (b))
+#define GET_RPU_ACR(b)		 GET_GLOBAL_REG(RPU_ACR, (b))
+
+
+/* Context register setters/getters */
+#define SET_SCTLR(b, c, v)	 SET_CTX_REG(SCTLR, (b), (c), (v))
+#define SET_ACTLR(b, c, v)	 SET_CTX_REG(ACTLR, (b), (c), (v))
+#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
+#define SET_TTBR0(b, c, v)	 SET_CTX_REG(TTBR0, (b), (c), (v))
+#define SET_TTBR1(b, c, v)	 SET_CTX_REG(TTBR1, (b), (c), (v))
+#define SET_TTBCR(b, c, v)	 SET_CTX_REG(TTBCR, (b), (c), (v))
+#define SET_PAR(b, c, v)	 SET_CTX_REG(PAR, (b), (c), (v))
+#define SET_FSR(b, c, v)	 SET_CTX_REG(FSR, (b), (c), (v))
+#define SET_FSRRESTORE(b, c, v)	 SET_CTX_REG(FSRRESTORE, (b), (c), (v))
+#define SET_FAR(b, c, v)	 SET_CTX_REG(FAR, (b), (c), (v))
+#define SET_FSYNR0(b, c, v)	 SET_CTX_REG(FSYNR0, (b), (c), (v))
+#define SET_FSYNR1(b, c, v)	 SET_CTX_REG(FSYNR1, (b), (c), (v))
+#define SET_PRRR(b, c, v)	 SET_CTX_REG(PRRR, (b), (c), (v))
+#define SET_NMRR(b, c, v)	 SET_CTX_REG(NMRR, (b), (c), (v))
+#define SET_TLBLKCR(b, c, v)	 SET_CTX_REG(TLBLCKR, (b), (c), (v))
+#define SET_V2PSR(b, c, v)	 SET_CTX_REG(V2PSR, (b), (c), (v))
+#define SET_TLBFLPTER(b, c, v)	 SET_CTX_REG(TLBFLPTER, (b), (c), (v))
+#define SET_TLBSLPTER(b, c, v)	 SET_CTX_REG(TLBSLPTER, (b), (c), (v))
+#define SET_BFBCR(b, c, v)	 SET_CTX_REG(BFBCR, (b), (c), (v))
+#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v))
+#define SET_TLBIASID(b, c, v)	 SET_CTX_REG(TLBIASID, (b), (c), (v))
+#define SET_TLBIVA(b, c, v)	 SET_CTX_REG(TLBIVA, (b), (c), (v))
+#define SET_TLBIVAA(b, c, v)	 SET_CTX_REG(TLBIVAA, (b), (c), (v))
+#define SET_V2PPR(b, c, v)	 SET_CTX_REG(V2PPR, (b), (c), (v))
+#define SET_V2PPW(b, c, v)	 SET_CTX_REG(V2PPW, (b), (c), (v))
+#define SET_V2PUR(b, c, v)	 SET_CTX_REG(V2PUR, (b), (c), (v))
+#define SET_V2PUW(b, c, v)	 SET_CTX_REG(V2PUW, (b), (c), (v))
+#define SET_RESUME(b, c, v)	 SET_CTX_REG(RESUME, (b), (c), (v))
+
+#define GET_SCTLR(b, c)		 GET_CTX_REG(SCTLR, (b), (c))
+#define GET_ACTLR(b, c)		 GET_CTX_REG(ACTLR, (b), (c))
+#define GET_CONTEXTIDR(b, c)	 GET_CTX_REG(CONTEXTIDR, (b), (c))
+#define GET_TTBR0(b, c)		 GET_CTX_REG(TTBR0, (b), (c))
+#define GET_TTBR1(b, c)		 GET_CTX_REG(TTBR1, (b), (c))
+#define GET_TTBCR(b, c)		 GET_CTX_REG(TTBCR, (b), (c))
+#define GET_PAR(b, c)		 GET_CTX_REG(PAR, (b), (c))
+#define GET_FSR(b, c)		 GET_CTX_REG(FSR, (b), (c))
+#define GET_FSRRESTORE(b, c)	 GET_CTX_REG(FSRRESTORE, (b), (c))
+#define GET_FAR(b, c)		 GET_CTX_REG(FAR, (b), (c))
+#define GET_FSYNR0(b, c)	 GET_CTX_REG(FSYNR0, (b), (c))
+#define GET_FSYNR1(b, c)	 GET_CTX_REG(FSYNR1, (b), (c))
+#define GET_PRRR(b, c)		 GET_CTX_REG(PRRR, (b), (c))
+#define GET_NMRR(b, c)		 GET_CTX_REG(NMRR, (b), (c))
+#define GET_TLBLCKR(b, c)	 GET_CTX_REG(TLBLCKR, (b), (c))
+#define GET_V2PSR(b, c)		 GET_CTX_REG(V2PSR, (b), (c))
+#define GET_TLBFLPTER(b, c)	 GET_CTX_REG(TLBFLPTER, (b), (c))
+#define GET_TLBSLPTER(b, c)	 GET_CTX_REG(TLBSLPTER, (b), (c))
+#define GET_BFBCR(b, c)		 GET_CTX_REG(BFBCR, (b), (c))
+#define GET_CTX_TLBIALL(b, c)	 GET_CTX_REG(CTX_TLBIALL, (b), (c))
+#define GET_TLBIASID(b, c)	 GET_CTX_REG(TLBIASID, (b), (c))
+#define GET_TLBIVA(b, c)	 GET_CTX_REG(TLBIVA, (b), (c))
+#define GET_TLBIVAA(b, c)	 GET_CTX_REG(TLBIVAA, (b), (c))
+#define GET_V2PPR(b, c)		 GET_CTX_REG(V2PPR, (b), (c))
+#define GET_V2PPW(b, c)		 GET_CTX_REG(V2PPW, (b), (c))
+#define GET_V2PUR(b, c)		 GET_CTX_REG(V2PUR, (b), (c))
+#define GET_V2PUW(b, c)		 GET_CTX_REG(V2PUW, (b), (c))
+#define GET_RESUME(b, c)	 GET_CTX_REG(RESUME, (b), (c))
+
+
+/* Global field setters / getters */
+/* Global Field Setters: */
+/* CBACR_N */
+#define SET_RWVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v)
+#define SET_RWE(b, n, v)      SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v)
+#define SET_RWGE(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v)
+#define SET_CBVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v)
+#define SET_IRPTNDX(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v)
+
+
+/* M2VCBR_N */
+#define SET_VMID(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v)
+#define SET_CBNDX(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v)
+#define SET_BYPASSD(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v)
+#define SET_BPRCOSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v)
+#define SET_BPRCISH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v)
+#define SET_BPRCNSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v)
+#define SET_BPSHCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v)
+#define SET_NSCFG(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v)
+#define SET_BPMTCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v)
+#define SET_BPMEMTYPE(b, n, v) \
+	SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v)
+
+
+/* CR */
+#define SET_RPUE(b, v)		 SET_GLOBAL_FIELD(b, CR, RPUE, v)
+#define SET_RPUERE(b, v)	 SET_GLOBAL_FIELD(b, CR, RPUERE, v)
+#define SET_RPUEIE(b, v)	 SET_GLOBAL_FIELD(b, CR, RPUEIE, v)
+#define SET_DCDEE(b, v)		 SET_GLOBAL_FIELD(b, CR, DCDEE, v)
+#define SET_CLIENTPD(b, v)       SET_GLOBAL_FIELD(b, CR, CLIENTPD, v)
+#define SET_STALLD(b, v)	 SET_GLOBAL_FIELD(b, CR, STALLD, v)
+#define SET_TLBLKCRWE(b, v)      SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v)
+#define SET_CR_TLBIALLCFG(b, v)  SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v)
+#define SET_TLBIVMIDCFG(b, v)    SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v)
+#define SET_CR_HUME(b, v)        SET_GLOBAL_FIELD(b, CR, CR_HUME, v)
+
+
+/* ESR */
+#define SET_CFG(b, v)		 SET_GLOBAL_FIELD(b, ESR, CFG, v)
+#define SET_BYPASS(b, v)	 SET_GLOBAL_FIELD(b, ESR, BYPASS, v)
+#define SET_ESR_MULTI(b, v)      SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v)
+
+
+/* ESYNR0 */
+#define SET_ESYNR0_AMID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v)
+#define SET_ESYNR0_APID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v)
+#define SET_ESYNR0_ABID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v)
+#define SET_ESYNR0_AVMID(b, v)   SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v)
+#define SET_ESYNR0_ATID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v)
+
+
+/* ESYNR1 */
+#define SET_ESYNR1_AMEMTYPE(b, v) \
+			SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v)
+#define SET_ESYNR1_ASHARED(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v)
+#define SET_ESYNR1_AINNERSHARED(b, v) \
+			SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v)
+#define SET_ESYNR1_APRIV(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v)
+#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v)
+#define SET_ESYNR1_AINST(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v)
+#define SET_ESYNR1_AWRITE(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v)
+#define SET_ESYNR1_ABURST(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v)
+#define SET_ESYNR1_ALEN(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v)
+#define SET_ESYNR1_ASIZE(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v)
+#define SET_ESYNR1_ALOCK(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v)
+#define SET_ESYNR1_AOOO(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v)
+#define SET_ESYNR1_AFULL(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v)
+#define SET_ESYNR1_AC(b, v)      SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v)
+#define SET_ESYNR1_DCD(b, v)     SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v)
+
+
+/* TESTBUSCR */
+#define SET_TBE(b, v)		 SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v)
+#define SET_SPDMBE(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v)
+#define SET_WGSEL(b, v)		 SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v)
+#define SET_TBLSEL(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v)
+#define SET_TBHSEL(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v)
+#define SET_SPDM0SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v)
+#define SET_SPDM1SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v)
+#define SET_SPDM2SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v)
+#define SET_SPDM3SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v)
+
+
+/* TLBIVMID */
+#define SET_TLBIVMID_VMID(b, v)  SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v)
+
+
+/* TLBRSW */
+#define SET_TLBRSW_INDEX(b, v)   SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v)
+#define SET_TLBBFBS(b, v)	 SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v)
+
+
+/* TLBTR0 */
+#define SET_PR(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, PR, v)
+#define SET_PW(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, PW, v)
+#define SET_UR(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, UR, v)
+#define SET_UW(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, UW, v)
+#define SET_XN(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, XN, v)
+#define SET_NSDESC(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v)
+#define SET_ISH(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, ISH, v)
+#define SET_SH(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, SH, v)
+#define SET_MT(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, MT, v)
+#define SET_DPSIZR(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v)
+#define SET_DPSIZC(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v)
+
+
+/* TLBTR1 */
+#define SET_TLBTR1_VMID(b, v)    SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v)
+#define SET_TLBTR1_PA(b, v)      SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v)
+
+
+/* TLBTR2 */
+#define SET_TLBTR2_ASID(b, v)    SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v)
+#define SET_TLBTR2_V(b, v)       SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v)
+#define SET_TLBTR2_NSTID(b, v)   SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v)
+#define SET_TLBTR2_NV(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v)
+#define SET_TLBTR2_VA(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v)
+
+
+/* Global Field Getters */
+/* CBACR_N */
+#define GET_RWVMID(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID)
+#define GET_RWE(b, n)		 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE)
+#define GET_RWGE(b, n)		 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE)
+#define GET_CBVMID(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID)
+#define GET_IRPTNDX(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX)
+
+
+/* M2VCBR_N */
+#define GET_VMID(b, n)       GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID)
+#define GET_CBNDX(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX)
+#define GET_BYPASSD(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD)
+#define GET_BPRCOSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH)
+#define GET_BPRCISH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH)
+#define GET_BPRCNSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH)
+#define GET_BPSHCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG)
+#define GET_NSCFG(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG)
+#define GET_BPMTCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG)
+#define GET_BPMEMTYPE(b, n)  GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE)
+
+
+/* CR */
+#define GET_RPUE(b)		 GET_GLOBAL_FIELD(b, CR, RPUE)
+#define GET_RPUERE(b)		 GET_GLOBAL_FIELD(b, CR, RPUERE)
+#define GET_RPUEIE(b)		 GET_GLOBAL_FIELD(b, CR, RPUEIE)
+#define GET_DCDEE(b)		 GET_GLOBAL_FIELD(b, CR, DCDEE)
+#define GET_CLIENTPD(b)		 GET_GLOBAL_FIELD(b, CR, CLIENTPD)
+#define GET_STALLD(b)		 GET_GLOBAL_FIELD(b, CR, STALLD)
+#define GET_TLBLKCRWE(b)	 GET_GLOBAL_FIELD(b, CR, TLBLKCRWE)
+#define GET_CR_TLBIALLCFG(b)	 GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG)
+#define GET_TLBIVMIDCFG(b)	 GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG)
+#define GET_CR_HUME(b)		 GET_GLOBAL_FIELD(b, CR, CR_HUME)
+
+
+/* ESR */
+#define GET_CFG(b)		 GET_GLOBAL_FIELD(b, ESR, CFG)
+#define GET_BYPASS(b)		 GET_GLOBAL_FIELD(b, ESR, BYPASS)
+#define GET_ESR_MULTI(b)	 GET_GLOBAL_FIELD(b, ESR, ESR_MULTI)
+
+
+/* ESYNR0 */
+#define GET_ESYNR0_AMID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID)
+#define GET_ESYNR0_APID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID)
+#define GET_ESYNR0_ABID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID)
+#define GET_ESYNR0_AVMID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID)
+#define GET_ESYNR0_ATID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID)
+
+
+/* ESYNR1 */
+#define GET_ESYNR1_AMEMTYPE(b)   GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE)
+#define GET_ESYNR1_ASHARED(b)    GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED)
+#define GET_ESYNR1_AINNERSHARED(b) \
+			GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED)
+#define GET_ESYNR1_APRIV(b)      GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV)
+#define GET_ESYNR1_APROTNS(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS)
+#define GET_ESYNR1_AINST(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST)
+#define GET_ESYNR1_AWRITE(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE)
+#define GET_ESYNR1_ABURST(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST)
+#define GET_ESYNR1_ALEN(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN)
+#define GET_ESYNR1_ASIZE(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE)
+#define GET_ESYNR1_ALOCK(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK)
+#define GET_ESYNR1_AOOO(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO)
+#define GET_ESYNR1_AFULL(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL)
+#define GET_ESYNR1_AC(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC)
+#define GET_ESYNR1_DCD(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD)
+
+
+/* IDR */
+#define GET_NM2VCBMT(b)		 GET_GLOBAL_FIELD(b, IDR, NM2VCBMT)
+#define GET_HTW(b)		 GET_GLOBAL_FIELD(b, IDR, HTW)
+#define GET_HUM(b)		 GET_GLOBAL_FIELD(b, IDR, HUM)
+#define GET_TLBSIZE(b)		 GET_GLOBAL_FIELD(b, IDR, TLBSIZE)
+#define GET_NCB(b)		 GET_GLOBAL_FIELD(b, IDR, NCB)
+#define GET_NIRPT(b)		 GET_GLOBAL_FIELD(b, IDR, NIRPT)
+
+
+/* REV */
+#define GET_MAJOR(b)		 GET_GLOBAL_FIELD(b, REV, MAJOR)
+#define GET_MINOR(b)		 GET_GLOBAL_FIELD(b, REV, MINOR)
+
+
+/* TESTBUSCR */
+#define GET_TBE(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBE)
+#define GET_SPDMBE(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE)
+#define GET_WGSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL)
+#define GET_TBLSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL)
+#define GET_TBHSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL)
+#define GET_SPDM0SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL)
+#define GET_SPDM1SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL)
+#define GET_SPDM2SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL)
+#define GET_SPDM3SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL)
+
+
+/* TLBIVMID */
+#define GET_TLBIVMID_VMID(b)	 GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID)
+
+
+/* TLBTR0 */
+#define GET_PR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, PR)
+#define GET_PW(b)		 GET_GLOBAL_FIELD(b, TLBTR0, PW)
+#define GET_UR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, UR)
+#define GET_UW(b)		 GET_GLOBAL_FIELD(b, TLBTR0, UW)
+#define GET_XN(b)		 GET_GLOBAL_FIELD(b, TLBTR0, XN)
+#define GET_NSDESC(b)		 GET_GLOBAL_FIELD(b, TLBTR0, NSDESC)
+#define GET_ISH(b)		 GET_GLOBAL_FIELD(b, TLBTR0, ISH)
+#define GET_SH(b)		 GET_GLOBAL_FIELD(b, TLBTR0, SH)
+#define GET_MT(b)		 GET_GLOBAL_FIELD(b, TLBTR0, MT)
+#define GET_DPSIZR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR)
+#define GET_DPSIZC(b)		 GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC)
+
+
+/* TLBTR1 */
+#define GET_TLBTR1_VMID(b)	 GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID)
+#define GET_TLBTR1_PA(b)	 GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA)
+
+
+/* TLBTR2 */
+#define GET_TLBTR2_ASID(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID)
+#define GET_TLBTR2_V(b)		 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V)
+#define GET_TLBTR2_NSTID(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID)
+#define GET_TLBTR2_NV(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV)
+#define GET_TLBTR2_VA(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA)
+
+
+/* Context Register setters / getters */
+/* Context Register setters */
+/* ACTLR */
+#define SET_CFERE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v)
+#define SET_CFEIE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v)
+#define SET_PTSHCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v)
+#define SET_RCOSH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v)
+#define SET_RCISH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v)
+#define SET_RCNSH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v)
+#define SET_PRIVCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v)
+#define SET_DNA(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v)
+#define SET_DNLV2PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v)
+#define SET_TLBMCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v)
+#define SET_CFCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v)
+#define SET_TIPCF(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v)
+#define SET_V2PCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v)
+#define SET_HUME(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v)
+#define SET_PTMTCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v)
+#define SET_PTMEMTYPE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v)
+
+
+/* BFBCR */
+#define SET_BFBDFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v)
+#define SET_BFBSFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v)
+#define SET_SFVS(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v)
+#define SET_FLVIC(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v)
+#define SET_SLVIC(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v)
+
+
+/* CONTEXTIDR */
+#define SET_CONTEXTIDR_ASID(b, c, v)   \
+		SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v)
+#define SET_CONTEXTIDR_PROCID(b, c, v) \
+		SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v)
+
+
+/* FSR */
+#define SET_TF(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, TF, v)
+#define SET_AFF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, AFF, v)
+#define SET_APF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, APF, v)
+#define SET_TLBMF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v)
+#define SET_HTWDEEF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v)
+#define SET_HTWSEEF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v)
+#define SET_MHF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, MHF, v)
+#define SET_SL(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, SL, v)
+#define SET_SS(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, SS, v)
+#define SET_MULTI(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, MULTI, v)
+
+
+/* FSYNR0 */
+#define SET_AMID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v)
+#define SET_APID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v)
+#define SET_ABID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v)
+#define SET_ATID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v)
+
+
+/* FSYNR1 */
+#define SET_AMEMTYPE(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v)
+#define SET_ASHARED(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v)
+#define SET_AINNERSHARED(b, c, v)  \
+				SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v)
+#define SET_APRIV(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v)
+#define SET_APROTNS(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v)
+#define SET_AINST(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v)
+#define SET_AWRITE(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v)
+#define SET_ABURST(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v)
+#define SET_ALEN(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v)
+#define SET_FSYNR1_ASIZE(b, c, v) \
+				SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v)
+#define SET_ALOCK(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v)
+#define SET_AFULL(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v)
+
+
+/* NMRR */
+#define SET_ICPC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v)
+#define SET_ICPC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v)
+#define SET_ICPC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v)
+#define SET_ICPC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v)
+#define SET_ICPC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v)
+#define SET_ICPC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v)
+#define SET_ICPC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v)
+#define SET_ICPC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v)
+#define SET_OCPC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v)
+#define SET_OCPC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v)
+#define SET_OCPC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v)
+#define SET_OCPC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v)
+#define SET_OCPC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v)
+#define SET_OCPC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v)
+#define SET_OCPC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v)
+#define SET_OCPC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v)
+
+
+/* PAR */
+#define SET_FAULT(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT, v)
+
+#define SET_FAULT_TF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v)
+#define SET_FAULT_AFF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v)
+#define SET_FAULT_APF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v)
+#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v)
+#define SET_FAULT_HTWDEEF(b, c, v) \
+				SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v)
+#define SET_FAULT_HTWSEEF(b, c, v) \
+				SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v)
+#define SET_FAULT_MHF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v)
+#define SET_FAULT_SL(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v)
+#define SET_FAULT_SS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v)
+
+#define SET_NOFAULT_SS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v)
+#define SET_NOFAULT_MT(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v)
+#define SET_NOFAULT_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v)
+#define SET_NOFAULT_NS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v)
+#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v)
+#define SET_NPFAULT_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v)
+
+
+/* PRRR */
+#define SET_MTC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v)
+#define SET_MTC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v)
+#define SET_MTC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v)
+#define SET_MTC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v)
+#define SET_MTC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v)
+#define SET_MTC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v)
+#define SET_MTC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v)
+#define SET_MTC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v)
+#define SET_SHDSH0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v)
+#define SET_SHDSH1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v)
+#define SET_SHNMSH0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v)
+#define SET_SHNMSH1(b, c, v)     SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v)
+#define SET_NOS0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v)
+#define SET_NOS1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v)
+#define SET_NOS2(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v)
+#define SET_NOS3(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v)
+#define SET_NOS4(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v)
+#define SET_NOS5(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v)
+#define SET_NOS6(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v)
+#define SET_NOS7(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v)
+
+
+/* RESUME */
+#define SET_TNR(b, c, v)	 SET_CONTEXT_FIELD(b, c, RESUME, TNR, v)
+
+
+/* SCTLR */
+#define SET_M(b, c, v)		 SET_CONTEXT_FIELD(b, c, SCTLR, M, v)
+#define SET_TRE(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v)
+#define SET_AFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v)
+#define SET_HAF(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v)
+#define SET_BE(b, c, v)		 SET_CONTEXT_FIELD(b, c, SCTLR, BE, v)
+#define SET_AFFD(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v)
+
+
+/* TLBLKCR */
+#define SET_LKE(b, c, v)	   SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v)
+#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \
+			SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v)
+#define SET_TLBIASIDCFG(b, c, v) \
+			SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v)
+#define SET_TLBIVAACFG(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v)
+#define SET_FLOOR(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v)
+#define SET_VICTIM(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v)
+
+
+/* TTBCR */
+#define SET_N(b, c, v)	         SET_CONTEXT_FIELD(b, c, TTBCR, N, v)
+#define SET_PD0(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v)
+#define SET_PD1(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v)
+
+
+/* TTBR0 */
+#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v)
+#define SET_TTBR0_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v)
+#define SET_TTBR0_ORGN(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v)
+#define SET_TTBR0_NOS(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v)
+#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v)
+#define SET_TTBR0_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v)
+
+
+/* TTBR1 */
+#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v)
+#define SET_TTBR1_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v)
+#define SET_TTBR1_ORGN(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v)
+#define SET_TTBR1_NOS(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v)
+#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v)
+#define SET_TTBR1_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v)
+
+
+/* V2PSR */
+#define SET_HIT(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v)
+#define SET_INDEX(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v)
+
+
+/* Context Register getters */
+/* ACTLR */
+#define GET_CFERE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFERE)
+#define GET_CFEIE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE)
+#define GET_PTSHCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG)
+#define GET_RCOSH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH)
+#define GET_RCISH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCISH)
+#define GET_RCNSH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH)
+#define GET_PRIVCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG)
+#define GET_DNA(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, DNA)
+#define GET_DNLV2PA(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA)
+#define GET_TLBMCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG)
+#define GET_CFCFG(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG)
+#define GET_TIPCF(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF)
+#define GET_V2PCFG(b, c)        GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG)
+#define GET_HUME(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, HUME)
+#define GET_PTMTCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG)
+#define GET_PTMEMTYPE(b, c)     GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE)
+
+/* BFBCR */
+#define GET_BFBDFE(b, c)	GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE)
+#define GET_BFBSFE(b, c)	GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE)
+#define GET_SFVS(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, SFVS)
+#define GET_FLVIC(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC)
+#define GET_SLVIC(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC)
+
+
+/* CONTEXTIDR */
+#define GET_CONTEXTIDR_ASID(b, c) \
+			GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID)
+#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID)
+
+
+/* FSR */
+#define GET_TF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, TF)
+#define GET_AFF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, AFF)
+#define GET_APF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, APF)
+#define GET_TLBMF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, TLBMF)
+#define GET_HTWDEEF(b, c)	GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF)
+#define GET_HTWSEEF(b, c)	GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF)
+#define GET_MHF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, MHF)
+#define GET_SL(b, c)		GET_CONTEXT_FIELD(b, c, FSR, SL)
+#define GET_SS(b, c)		GET_CONTEXT_FIELD(b, c, FSR, SS)
+#define GET_MULTI(b, c)		GET_CONTEXT_FIELD(b, c, FSR, MULTI)
+
+
+/* FSYNR0 */
+#define GET_AMID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, AMID)
+#define GET_APID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, APID)
+#define GET_ABID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, ABID)
+#define GET_ATID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, ATID)
+
+
+/* FSYNR1 */
+#define GET_AMEMTYPE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE)
+#define GET_ASHARED(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED)
+#define GET_AINNERSHARED(b, c)  GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED)
+#define GET_APRIV(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV)
+#define GET_APROTNS(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS)
+#define GET_AINST(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, AINST)
+#define GET_AWRITE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE)
+#define GET_ABURST(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST)
+#define GET_ALEN(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN)
+#define GET_FSYNR1_ASIZE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE)
+#define GET_ALOCK(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK)
+#define GET_AFULL(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL)
+
+
+/* NMRR */
+#define GET_ICPC0(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC0)
+#define GET_ICPC1(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC1)
+#define GET_ICPC2(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC2)
+#define GET_ICPC3(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC3)
+#define GET_ICPC4(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC4)
+#define GET_ICPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC5)
+#define GET_ICPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC6)
+#define GET_ICPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC7)
+#define GET_OCPC0(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC0)
+#define GET_OCPC1(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC1)
+#define GET_OCPC2(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC2)
+#define GET_OCPC3(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC3)
+#define GET_OCPC4(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC4)
+#define GET_OCPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC5)
+#define GET_OCPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC6)
+#define GET_OCPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC7)
+#define NMRR_ICP(nmrr, n)	(((nmrr) & (3 << ((n) * 2))) >> ((n) * 2))
+#define NMRR_OCP(nmrr, n)	(((nmrr) & (3 << ((n) * 2 + 16))) >> \
+								((n) * 2 + 16))
+
+/* PAR */
+#define GET_FAULT(b, c)		GET_CONTEXT_FIELD(b, c, PAR, FAULT)
+
+#define GET_FAULT_TF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF)
+#define GET_FAULT_AFF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF)
+#define GET_FAULT_APF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF)
+#define GET_FAULT_TLBMF(b, c)   GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF)
+#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF)
+#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF)
+#define GET_FAULT_MHF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF)
+#define GET_FAULT_SL(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL)
+#define GET_FAULT_SS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS)
+
+#define GET_NOFAULT_SS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS)
+#define GET_NOFAULT_MT(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT)
+#define GET_NOFAULT_SH(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH)
+#define GET_NOFAULT_NS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS)
+#define GET_NOFAULT_NOS(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS)
+#define GET_NPFAULT_PA(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA)
+
+
+/* PRRR */
+#define GET_MTC0(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC0)
+#define GET_MTC1(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC1)
+#define GET_MTC2(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC2)
+#define GET_MTC3(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC3)
+#define GET_MTC4(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC4)
+#define GET_MTC5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC5)
+#define GET_MTC6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC6)
+#define GET_MTC7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC7)
+#define GET_SHDSH0(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0)
+#define GET_SHDSH1(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1)
+#define GET_SHNMSH0(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0)
+#define GET_SHNMSH1(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1)
+#define GET_NOS0(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS0)
+#define GET_NOS1(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS1)
+#define GET_NOS2(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS2)
+#define GET_NOS3(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS3)
+#define GET_NOS4(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS4)
+#define GET_NOS5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS5)
+#define GET_NOS6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS6)
+#define GET_NOS7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS7)
+#define PRRR_NOS(prrr, n)	 ((prrr) & (1 << ((n) + 24)) ? 1 : 0)
+#define PRRR_MT(prrr, n)	 ((((prrr) & (3 << ((n) * 2))) >> ((n) * 2)))
+
+
+/* RESUME */
+#define GET_TNR(b, c)		GET_CONTEXT_FIELD(b, c, RESUME, TNR)
+
+
+/* SCTLR */
+#define GET_M(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, M)
+#define GET_TRE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, TRE)
+#define GET_AFE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, AFE)
+#define GET_HAF(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, HAF)
+#define GET_BE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, BE)
+#define GET_AFFD(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, AFFD)
+
+
+/* TLBLKCR */
+#define GET_LKE(b, c)		GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE)
+#define GET_TLBLCKR_TLBIALLCFG(b, c) \
+			GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG)
+#define GET_TLBIASIDCFG(b, c)   GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG)
+#define GET_TLBIVAACFG(b, c)	GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG)
+#define GET_FLOOR(b, c)		GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR)
+#define GET_VICTIM(b, c)	GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM)
+
+
+/* TTBCR */
+#define GET_N(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, N)
+#define GET_PD0(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, PD0)
+#define GET_PD1(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, PD1)
+
+
+/* TTBR0 */
+#define GET_TTBR0_IRGNH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH)
+#define GET_TTBR0_SH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH)
+#define GET_TTBR0_ORGN(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN)
+#define GET_TTBR0_NOS(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS)
+#define GET_TTBR0_IRGNL(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL)
+#define GET_TTBR0_PA(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA)
+
+
+/* TTBR1 */
+#define GET_TTBR1_IRGNH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH)
+#define GET_TTBR1_SH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH)
+#define GET_TTBR1_ORGN(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN)
+#define GET_TTBR1_NOS(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS)
+#define GET_TTBR1_IRGNL(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL)
+#define GET_TTBR1_PA(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA)
+
+
+/* V2PSR */
+#define GET_HIT(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, HIT)
+#define GET_INDEX(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, INDEX)
+
+
+/* Global Registers */
+#define M2VCBR_N	(0xFF000)
+#define CBACR_N		(0xFF800)
+#define TLBRSW		(0xFFE00)
+#define TLBTR0		(0xFFE80)
+#define TLBTR1		(0xFFE84)
+#define TLBTR2		(0xFFE88)
+#define TESTBUSCR	(0xFFE8C)
+#define GLOBAL_TLBIALL	(0xFFF00)
+#define TLBIVMID	(0xFFF04)
+#define CR		(0xFFF80)
+#define EAR		(0xFFF84)
+#define ESR		(0xFFF88)
+#define ESRRESTORE	(0xFFF8C)
+#define ESYNR0		(0xFFF90)
+#define ESYNR1		(0xFFF94)
+#define REV		(0xFFFF4)
+#define IDR		(0xFFFF8)
+#define RPU_ACR		(0xFFFFC)
+
+
+/* Context Bank Registers */
+#define SCTLR		(0x000)
+#define ACTLR		(0x004)
+#define CONTEXTIDR	(0x008)
+#define TTBR0		(0x010)
+#define TTBR1		(0x014)
+#define TTBCR		(0x018)
+#define PAR		(0x01C)
+#define FSR		(0x020)
+#define FSRRESTORE	(0x024)
+#define FAR		(0x028)
+#define FSYNR0		(0x02C)
+#define FSYNR1		(0x030)
+#define PRRR		(0x034)
+#define NMRR		(0x038)
+#define TLBLCKR		(0x03C)
+#define V2PSR		(0x040)
+#define TLBFLPTER	(0x044)
+#define TLBSLPTER	(0x048)
+#define BFBCR		(0x04C)
+#define CTX_TLBIALL	(0x800)
+#define TLBIASID	(0x804)
+#define TLBIVA		(0x808)
+#define TLBIVAA		(0x80C)
+#define V2PPR		(0x810)
+#define V2PPW		(0x814)
+#define V2PUR		(0x818)
+#define V2PUW		(0x81C)
+#define RESUME		(0x820)
+
+
+/* Global Register Fields */
+/* CBACRn */
+#define RWVMID        (RWVMID_MASK       << RWVMID_SHIFT)
+#define RWE           (RWE_MASK          << RWE_SHIFT)
+#define RWGE          (RWGE_MASK         << RWGE_SHIFT)
+#define CBVMID        (CBVMID_MASK       << CBVMID_SHIFT)
+#define IRPTNDX       (IRPTNDX_MASK      << IRPTNDX_SHIFT)
+
+
+/* CR */
+#define RPUE          (RPUE_MASK          << RPUE_SHIFT)
+#define RPUERE        (RPUERE_MASK        << RPUERE_SHIFT)
+#define RPUEIE        (RPUEIE_MASK        << RPUEIE_SHIFT)
+#define DCDEE         (DCDEE_MASK         << DCDEE_SHIFT)
+#define CLIENTPD      (CLIENTPD_MASK      << CLIENTPD_SHIFT)
+#define STALLD        (STALLD_MASK        << STALLD_SHIFT)
+#define TLBLKCRWE     (TLBLKCRWE_MASK     << TLBLKCRWE_SHIFT)
+#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT)
+#define TLBIVMIDCFG   (TLBIVMIDCFG_MASK   << TLBIVMIDCFG_SHIFT)
+#define CR_HUME       (CR_HUME_MASK       << CR_HUME_SHIFT)
+
+
+/* ESR */
+#define CFG           (CFG_MASK          << CFG_SHIFT)
+#define BYPASS        (BYPASS_MASK       << BYPASS_SHIFT)
+#define ESR_MULTI     (ESR_MULTI_MASK    << ESR_MULTI_SHIFT)
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID   (ESYNR0_AMID_MASK  << ESYNR0_AMID_SHIFT)
+#define ESYNR0_APID   (ESYNR0_APID_MASK  << ESYNR0_APID_SHIFT)
+#define ESYNR0_ABID   (ESYNR0_ABID_MASK  << ESYNR0_ABID_SHIFT)
+#define ESYNR0_AVMID  (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT)
+#define ESYNR0_ATID   (ESYNR0_ATID_MASK  << ESYNR0_ATID_SHIFT)
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE      (ESYNR1_AMEMTYPE_MASK    << ESYNR1_AMEMTYPE_SHIFT)
+#define ESYNR1_ASHARED       (ESYNR1_ASHARED_MASK     << ESYNR1_ASHARED_SHIFT)
+#define ESYNR1_AINNERSHARED  (ESYNR1_AINNERSHARED_MASK<< \
+						ESYNR1_AINNERSHARED_SHIFT)
+#define ESYNR1_APRIV         (ESYNR1_APRIV_MASK       << ESYNR1_APRIV_SHIFT)
+#define ESYNR1_APROTNS       (ESYNR1_APROTNS_MASK     << ESYNR1_APROTNS_SHIFT)
+#define ESYNR1_AINST         (ESYNR1_AINST_MASK       << ESYNR1_AINST_SHIFT)
+#define ESYNR1_AWRITE        (ESYNR1_AWRITE_MASK      << ESYNR1_AWRITE_SHIFT)
+#define ESYNR1_ABURST        (ESYNR1_ABURST_MASK      << ESYNR1_ABURST_SHIFT)
+#define ESYNR1_ALEN          (ESYNR1_ALEN_MASK        << ESYNR1_ALEN_SHIFT)
+#define ESYNR1_ASIZE         (ESYNR1_ASIZE_MASK       << ESYNR1_ASIZE_SHIFT)
+#define ESYNR1_ALOCK         (ESYNR1_ALOCK_MASK       << ESYNR1_ALOCK_SHIFT)
+#define ESYNR1_AOOO          (ESYNR1_AOOO_MASK        << ESYNR1_AOOO_SHIFT)
+#define ESYNR1_AFULL         (ESYNR1_AFULL_MASK       << ESYNR1_AFULL_SHIFT)
+#define ESYNR1_AC            (ESYNR1_AC_MASK          << ESYNR1_AC_SHIFT)
+#define ESYNR1_DCD           (ESYNR1_DCD_MASK         << ESYNR1_DCD_SHIFT)
+
+
+/* IDR */
+#define NM2VCBMT      (NM2VCBMT_MASK     << NM2VCBMT_SHIFT)
+#define HTW           (HTW_MASK          << HTW_SHIFT)
+#define HUM           (HUM_MASK          << HUM_SHIFT)
+#define TLBSIZE       (TLBSIZE_MASK      << TLBSIZE_SHIFT)
+#define NCB           (NCB_MASK          << NCB_SHIFT)
+#define NIRPT         (NIRPT_MASK        << NIRPT_SHIFT)
+
+
+/* M2VCBRn */
+#define VMID          (VMID_MASK         << VMID_SHIFT)
+#define CBNDX         (CBNDX_MASK        << CBNDX_SHIFT)
+#define BYPASSD       (BYPASSD_MASK      << BYPASSD_SHIFT)
+#define BPRCOSH       (BPRCOSH_MASK      << BPRCOSH_SHIFT)
+#define BPRCISH       (BPRCISH_MASK      << BPRCISH_SHIFT)
+#define BPRCNSH       (BPRCNSH_MASK      << BPRCNSH_SHIFT)
+#define BPSHCFG       (BPSHCFG_MASK      << BPSHCFG_SHIFT)
+#define NSCFG         (NSCFG_MASK        << NSCFG_SHIFT)
+#define BPMTCFG       (BPMTCFG_MASK      << BPMTCFG_SHIFT)
+#define BPMEMTYPE     (BPMEMTYPE_MASK    << BPMEMTYPE_SHIFT)
+
+
+/* REV */
+#define IDR_MINOR     (MINOR_MASK        << MINOR_SHIFT)
+#define IDR_MAJOR     (MAJOR_MASK        << MAJOR_SHIFT)
+
+
+/* TESTBUSCR */
+#define TBE           (TBE_MASK          << TBE_SHIFT)
+#define SPDMBE        (SPDMBE_MASK       << SPDMBE_SHIFT)
+#define WGSEL         (WGSEL_MASK        << WGSEL_SHIFT)
+#define TBLSEL        (TBLSEL_MASK       << TBLSEL_SHIFT)
+#define TBHSEL        (TBHSEL_MASK       << TBHSEL_SHIFT)
+#define SPDM0SEL      (SPDM0SEL_MASK     << SPDM0SEL_SHIFT)
+#define SPDM1SEL      (SPDM1SEL_MASK     << SPDM1SEL_SHIFT)
+#define SPDM2SEL      (SPDM2SEL_MASK     << SPDM2SEL_SHIFT)
+#define SPDM3SEL      (SPDM3SEL_MASK     << SPDM3SEL_SHIFT)
+
+
+/* TLBIVMID */
+#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT)
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX  (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT)
+#define TLBBFBS       (TLBBFBS_MASK      << TLBBFBS_SHIFT)
+
+
+/* TLBTR0 */
+#define PR            (PR_MASK           << PR_SHIFT)
+#define PW            (PW_MASK           << PW_SHIFT)
+#define UR            (UR_MASK           << UR_SHIFT)
+#define UW            (UW_MASK           << UW_SHIFT)
+#define XN            (XN_MASK           << XN_SHIFT)
+#define NSDESC        (NSDESC_MASK       << NSDESC_SHIFT)
+#define ISH           (ISH_MASK          << ISH_SHIFT)
+#define SH            (SH_MASK           << SH_SHIFT)
+#define MT            (MT_MASK           << MT_SHIFT)
+#define DPSIZR        (DPSIZR_MASK       << DPSIZR_SHIFT)
+#define DPSIZC        (DPSIZC_MASK       << DPSIZC_SHIFT)
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID   (TLBTR1_VMID_MASK  << TLBTR1_VMID_SHIFT)
+#define TLBTR1_PA     (TLBTR1_PA_MASK    << TLBTR1_PA_SHIFT)
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID   (TLBTR2_ASID_MASK  << TLBTR2_ASID_SHIFT)
+#define TLBTR2_V      (TLBTR2_V_MASK     << TLBTR2_V_SHIFT)
+#define TLBTR2_NSTID  (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT)
+#define TLBTR2_NV     (TLBTR2_NV_MASK    << TLBTR2_NV_SHIFT)
+#define TLBTR2_VA     (TLBTR2_VA_MASK    << TLBTR2_VA_SHIFT)
+
+
+/* Context Register Fields */
+/* ACTLR */
+#define CFERE              (CFERE_MASK              << CFERE_SHIFT)
+#define CFEIE              (CFEIE_MASK              << CFEIE_SHIFT)
+#define PTSHCFG            (PTSHCFG_MASK            << PTSHCFG_SHIFT)
+#define RCOSH              (RCOSH_MASK              << RCOSH_SHIFT)
+#define RCISH              (RCISH_MASK              << RCISH_SHIFT)
+#define RCNSH              (RCNSH_MASK              << RCNSH_SHIFT)
+#define PRIVCFG            (PRIVCFG_MASK            << PRIVCFG_SHIFT)
+#define DNA                (DNA_MASK                << DNA_SHIFT)
+#define DNLV2PA            (DNLV2PA_MASK            << DNLV2PA_SHIFT)
+#define TLBMCFG            (TLBMCFG_MASK            << TLBMCFG_SHIFT)
+#define CFCFG              (CFCFG_MASK              << CFCFG_SHIFT)
+#define TIPCF              (TIPCF_MASK              << TIPCF_SHIFT)
+#define V2PCFG             (V2PCFG_MASK             << V2PCFG_SHIFT)
+#define HUME               (HUME_MASK               << HUME_SHIFT)
+#define PTMTCFG            (PTMTCFG_MASK            << PTMTCFG_SHIFT)
+#define PTMEMTYPE          (PTMEMTYPE_MASK          << PTMEMTYPE_SHIFT)
+
+
+/* BFBCR */
+#define BFBDFE             (BFBDFE_MASK             << BFBDFE_SHIFT)
+#define BFBSFE             (BFBSFE_MASK             << BFBSFE_SHIFT)
+#define SFVS               (SFVS_MASK               << SFVS_SHIFT)
+#define FLVIC              (FLVIC_MASK              << FLVIC_SHIFT)
+#define SLVIC              (SLVIC_MASK              << SLVIC_SHIFT)
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID    (CONTEXTIDR_ASID_MASK    << CONTEXTIDR_ASID_SHIFT)
+#define PROCID             (PROCID_MASK             << PROCID_SHIFT)
+
+
+/* FSR */
+#define TF                 (TF_MASK                 << TF_SHIFT)
+#define AFF                (AFF_MASK                << AFF_SHIFT)
+#define APF                (APF_MASK                << APF_SHIFT)
+#define TLBMF              (TLBMF_MASK              << TLBMF_SHIFT)
+#define HTWDEEF            (HTWDEEF_MASK            << HTWDEEF_SHIFT)
+#define HTWSEEF            (HTWSEEF_MASK            << HTWSEEF_SHIFT)
+#define MHF                (MHF_MASK                << MHF_SHIFT)
+#define SL                 (SL_MASK                 << SL_SHIFT)
+#define SS                 (SS_MASK                 << SS_SHIFT)
+#define MULTI              (MULTI_MASK              << MULTI_SHIFT)
+
+
+/* FSYNR0 */
+#define AMID               (AMID_MASK               << AMID_SHIFT)
+#define APID               (APID_MASK               << APID_SHIFT)
+#define ABID               (ABID_MASK               << ABID_SHIFT)
+#define ATID               (ATID_MASK               << ATID_SHIFT)
+
+
+/* FSYNR1 */
+#define AMEMTYPE           (AMEMTYPE_MASK           << AMEMTYPE_SHIFT)
+#define ASHARED            (ASHARED_MASK            << ASHARED_SHIFT)
+#define AINNERSHARED       (AINNERSHARED_MASK       << AINNERSHARED_SHIFT)
+#define APRIV              (APRIV_MASK              << APRIV_SHIFT)
+#define APROTNS            (APROTNS_MASK            << APROTNS_SHIFT)
+#define AINST              (AINST_MASK              << AINST_SHIFT)
+#define AWRITE             (AWRITE_MASK             << AWRITE_SHIFT)
+#define ABURST             (ABURST_MASK             << ABURST_SHIFT)
+#define ALEN               (ALEN_MASK               << ALEN_SHIFT)
+#define FSYNR1_ASIZE       (FSYNR1_ASIZE_MASK       << FSYNR1_ASIZE_SHIFT)
+#define ALOCK              (ALOCK_MASK              << ALOCK_SHIFT)
+#define AFULL              (AFULL_MASK              << AFULL_SHIFT)
+
+
+/* NMRR */
+#define ICPC0              (ICPC0_MASK              << ICPC0_SHIFT)
+#define ICPC1              (ICPC1_MASK              << ICPC1_SHIFT)
+#define ICPC2              (ICPC2_MASK              << ICPC2_SHIFT)
+#define ICPC3              (ICPC3_MASK              << ICPC3_SHIFT)
+#define ICPC4              (ICPC4_MASK              << ICPC4_SHIFT)
+#define ICPC5              (ICPC5_MASK              << ICPC5_SHIFT)
+#define ICPC6              (ICPC6_MASK              << ICPC6_SHIFT)
+#define ICPC7              (ICPC7_MASK              << ICPC7_SHIFT)
+#define OCPC0              (OCPC0_MASK              << OCPC0_SHIFT)
+#define OCPC1              (OCPC1_MASK              << OCPC1_SHIFT)
+#define OCPC2              (OCPC2_MASK              << OCPC2_SHIFT)
+#define OCPC3              (OCPC3_MASK              << OCPC3_SHIFT)
+#define OCPC4              (OCPC4_MASK              << OCPC4_SHIFT)
+#define OCPC5              (OCPC5_MASK              << OCPC5_SHIFT)
+#define OCPC6              (OCPC6_MASK              << OCPC6_SHIFT)
+#define OCPC7              (OCPC7_MASK              << OCPC7_SHIFT)
+
+
+/* PAR */
+#define FAULT              (FAULT_MASK              << FAULT_SHIFT)
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF           (FAULT_TF_MASK           << FAULT_TF_SHIFT)
+#define FAULT_AFF          (FAULT_AFF_MASK          << FAULT_AFF_SHIFT)
+#define FAULT_APF          (FAULT_APF_MASK          << FAULT_APF_SHIFT)
+#define FAULT_TLBMF        (FAULT_TLBMF_MASK        << FAULT_TLBMF_SHIFT)
+#define FAULT_HTWDEEF      (FAULT_HTWDEEF_MASK      << FAULT_HTWDEEF_SHIFT)
+#define FAULT_HTWSEEF      (FAULT_HTWSEEF_MASK      << FAULT_HTWSEEF_SHIFT)
+#define FAULT_MHF          (FAULT_MHF_MASK          << FAULT_MHF_SHIFT)
+#define FAULT_SL           (FAULT_SL_MASK           << FAULT_SL_SHIFT)
+#define FAULT_SS           (FAULT_SS_MASK           << FAULT_SS_SHIFT)
+
+/* If NO fault is present, the following fields are in effect */
+/* (FAULT remains as before) */
+#define PAR_NOFAULT_SS     (PAR_NOFAULT_SS_MASK     << PAR_NOFAULT_SS_SHIFT)
+#define PAR_NOFAULT_MT     (PAR_NOFAULT_MT_MASK     << PAR_NOFAULT_MT_SHIFT)
+#define PAR_NOFAULT_SH     (PAR_NOFAULT_SH_MASK     << PAR_NOFAULT_SH_SHIFT)
+#define PAR_NOFAULT_NS     (PAR_NOFAULT_NS_MASK     << PAR_NOFAULT_NS_SHIFT)
+#define PAR_NOFAULT_NOS    (PAR_NOFAULT_NOS_MASK    << PAR_NOFAULT_NOS_SHIFT)
+#define PAR_NPFAULT_PA     (PAR_NPFAULT_PA_MASK     << PAR_NPFAULT_PA_SHIFT)
+
+
+/* PRRR */
+#define MTC0               (MTC0_MASK               << MTC0_SHIFT)
+#define MTC1               (MTC1_MASK               << MTC1_SHIFT)
+#define MTC2               (MTC2_MASK               << MTC2_SHIFT)
+#define MTC3               (MTC3_MASK               << MTC3_SHIFT)
+#define MTC4               (MTC4_MASK               << MTC4_SHIFT)
+#define MTC5               (MTC5_MASK               << MTC5_SHIFT)
+#define MTC6               (MTC6_MASK               << MTC6_SHIFT)
+#define MTC7               (MTC7_MASK               << MTC7_SHIFT)
+#define SHDSH0             (SHDSH0_MASK             << SHDSH0_SHIFT)
+#define SHDSH1             (SHDSH1_MASK             << SHDSH1_SHIFT)
+#define SHNMSH0            (SHNMSH0_MASK            << SHNMSH0_SHIFT)
+#define SHNMSH1            (SHNMSH1_MASK            << SHNMSH1_SHIFT)
+#define NOS0               (NOS0_MASK               << NOS0_SHIFT)
+#define NOS1               (NOS1_MASK               << NOS1_SHIFT)
+#define NOS2               (NOS2_MASK               << NOS2_SHIFT)
+#define NOS3               (NOS3_MASK               << NOS3_SHIFT)
+#define NOS4               (NOS4_MASK               << NOS4_SHIFT)
+#define NOS5               (NOS5_MASK               << NOS5_SHIFT)
+#define NOS6               (NOS6_MASK               << NOS6_SHIFT)
+#define NOS7               (NOS7_MASK               << NOS7_SHIFT)
+
+
+/* RESUME */
+#define TNR                (TNR_MASK                << TNR_SHIFT)
+
+
+/* SCTLR */
+#define M                  (M_MASK                  << M_SHIFT)
+#define TRE                (TRE_MASK                << TRE_SHIFT)
+#define AFE                (AFE_MASK                << AFE_SHIFT)
+#define HAF                (HAF_MASK                << HAF_SHIFT)
+#define BE                 (BE_MASK                 << BE_SHIFT)
+#define AFFD               (AFFD_MASK               << AFFD_SHIFT)
+
+
+/* TLBIASID */
+#define TLBIASID_ASID      (TLBIASID_ASID_MASK      << TLBIASID_ASID_SHIFT)
+
+
+/* TLBIVA */
+#define TLBIVA_ASID        (TLBIVA_ASID_MASK        << TLBIVA_ASID_SHIFT)
+#define TLBIVA_VA          (TLBIVA_VA_MASK          << TLBIVA_VA_SHIFT)
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA         (TLBIVAA_VA_MASK         << TLBIVAA_VA_SHIFT)
+
+
+/* TLBLCKR */
+#define LKE                (LKE_MASK                << LKE_SHIFT)
+#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT)
+#define TLBIASIDCFG        (TLBIASIDCFG_MASK        << TLBIASIDCFG_SHIFT)
+#define TLBIVAACFG         (TLBIVAACFG_MASK         << TLBIVAACFG_SHIFT)
+#define FLOOR              (FLOOR_MASK              << FLOOR_SHIFT)
+#define VICTIM             (VICTIM_MASK             << VICTIM_SHIFT)
+
+
+/* TTBCR */
+#define N                  (N_MASK                  << N_SHIFT)
+#define PD0                (PD0_MASK                << PD0_SHIFT)
+#define PD1                (PD1_MASK                << PD1_SHIFT)
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH        (TTBR0_IRGNH_MASK        << TTBR0_IRGNH_SHIFT)
+#define TTBR0_SH           (TTBR0_SH_MASK           << TTBR0_SH_SHIFT)
+#define TTBR0_ORGN         (TTBR0_ORGN_MASK         << TTBR0_ORGN_SHIFT)
+#define TTBR0_NOS          (TTBR0_NOS_MASK          << TTBR0_NOS_SHIFT)
+#define TTBR0_IRGNL        (TTBR0_IRGNL_MASK        << TTBR0_IRGNL_SHIFT)
+#define TTBR0_PA           (TTBR0_PA_MASK           << TTBR0_PA_SHIFT)
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH        (TTBR1_IRGNH_MASK        << TTBR1_IRGNH_SHIFT)
+#define TTBR1_SH           (TTBR1_SH_MASK           << TTBR1_SH_SHIFT)
+#define TTBR1_ORGN         (TTBR1_ORGN_MASK         << TTBR1_ORGN_SHIFT)
+#define TTBR1_NOS          (TTBR1_NOS_MASK          << TTBR1_NOS_SHIFT)
+#define TTBR1_IRGNL        (TTBR1_IRGNL_MASK        << TTBR1_IRGNL_SHIFT)
+#define TTBR1_PA           (TTBR1_PA_MASK           << TTBR1_PA_SHIFT)
+
+
+/* V2PSR */
+#define HIT                (HIT_MASK                << HIT_SHIFT)
+#define INDEX              (INDEX_MASK              << INDEX_SHIFT)
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX        (V2Pxx_INDEX_MASK        << V2Pxx_INDEX_SHIFT)
+#define V2Pxx_VA           (V2Pxx_VA_MASK           << V2Pxx_VA_SHIFT)
+
+
+/* Global Register Masks */
+/* CBACRn */
+#define RWVMID_MASK               0x1F
+#define RWE_MASK                  0x01
+#define RWGE_MASK                 0x01
+#define CBVMID_MASK               0x1F
+#define IRPTNDX_MASK              0xFF
+
+
+/* CR */
+#define RPUE_MASK                 0x01
+#define RPUERE_MASK               0x01
+#define RPUEIE_MASK               0x01
+#define DCDEE_MASK                0x01
+#define CLIENTPD_MASK             0x01
+#define STALLD_MASK               0x01
+#define TLBLKCRWE_MASK            0x01
+#define CR_TLBIALLCFG_MASK        0x01
+#define TLBIVMIDCFG_MASK          0x01
+#define CR_HUME_MASK              0x01
+
+
+/* ESR */
+#define CFG_MASK                  0x01
+#define BYPASS_MASK               0x01
+#define ESR_MULTI_MASK            0x01
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_MASK          0xFF
+#define ESYNR0_APID_MASK          0x1F
+#define ESYNR0_ABID_MASK          0x07
+#define ESYNR0_AVMID_MASK         0x1F
+#define ESYNR0_ATID_MASK          0xFF
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_MASK             0x07
+#define ESYNR1_ASHARED_MASK              0x01
+#define ESYNR1_AINNERSHARED_MASK         0x01
+#define ESYNR1_APRIV_MASK                0x01
+#define ESYNR1_APROTNS_MASK              0x01
+#define ESYNR1_AINST_MASK                0x01
+#define ESYNR1_AWRITE_MASK               0x01
+#define ESYNR1_ABURST_MASK               0x01
+#define ESYNR1_ALEN_MASK                 0x0F
+#define ESYNR1_ASIZE_MASK                0x01
+#define ESYNR1_ALOCK_MASK                0x03
+#define ESYNR1_AOOO_MASK                 0x01
+#define ESYNR1_AFULL_MASK                0x01
+#define ESYNR1_AC_MASK                   0x01
+#define ESYNR1_DCD_MASK                  0x01
+
+
+/* IDR */
+#define NM2VCBMT_MASK             0x1FF
+#define HTW_MASK                  0x01
+#define HUM_MASK                  0x01
+#define TLBSIZE_MASK              0x0F
+#define NCB_MASK                  0xFF
+#define NIRPT_MASK                0xFF
+
+
+/* M2VCBRn */
+#define VMID_MASK                 0x1F
+#define CBNDX_MASK                0xFF
+#define BYPASSD_MASK              0x01
+#define BPRCOSH_MASK              0x01
+#define BPRCISH_MASK              0x01
+#define BPRCNSH_MASK              0x01
+#define BPSHCFG_MASK              0x03
+#define NSCFG_MASK                0x03
+#define BPMTCFG_MASK              0x01
+#define BPMEMTYPE_MASK            0x07
+
+
+/* REV */
+#define MINOR_MASK                0x0F
+#define MAJOR_MASK                0x0F
+
+
+/* TESTBUSCR */
+#define TBE_MASK                  0x01
+#define SPDMBE_MASK               0x01
+#define WGSEL_MASK                0x03
+#define TBLSEL_MASK               0x03
+#define TBHSEL_MASK               0x03
+#define SPDM0SEL_MASK             0x0F
+#define SPDM1SEL_MASK             0x0F
+#define SPDM2SEL_MASK             0x0F
+#define SPDM3SEL_MASK             0x0F
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_MASK        0x1F
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_MASK         0xFF
+#define TLBBFBS_MASK              0x03
+
+
+/* TLBTR0 */
+#define PR_MASK                   0x01
+#define PW_MASK                   0x01
+#define UR_MASK                   0x01
+#define UW_MASK                   0x01
+#define XN_MASK                   0x01
+#define NSDESC_MASK               0x01
+#define ISH_MASK                  0x01
+#define SH_MASK                   0x01
+#define MT_MASK                   0x07
+#define DPSIZR_MASK               0x07
+#define DPSIZC_MASK               0x07
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_MASK          0x1F
+#define TLBTR1_PA_MASK            0x000FFFFF
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_MASK          0xFF
+#define TLBTR2_V_MASK             0x01
+#define TLBTR2_NSTID_MASK         0x01
+#define TLBTR2_NV_MASK            0x01
+#define TLBTR2_VA_MASK            0x000FFFFF
+
+
+/* Global Register Shifts */
+/* CBACRn */
+#define RWVMID_SHIFT             0
+#define RWE_SHIFT                8
+#define RWGE_SHIFT               9
+#define CBVMID_SHIFT             16
+#define IRPTNDX_SHIFT            24
+
+
+/* CR */
+#define RPUE_SHIFT               0
+#define RPUERE_SHIFT             1
+#define RPUEIE_SHIFT             2
+#define DCDEE_SHIFT              3
+#define CLIENTPD_SHIFT           4
+#define STALLD_SHIFT             5
+#define TLBLKCRWE_SHIFT          6
+#define CR_TLBIALLCFG_SHIFT      7
+#define TLBIVMIDCFG_SHIFT        8
+#define CR_HUME_SHIFT            9
+
+
+/* ESR */
+#define CFG_SHIFT                0
+#define BYPASS_SHIFT             1
+#define ESR_MULTI_SHIFT          31
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_SHIFT        0
+#define ESYNR0_APID_SHIFT        8
+#define ESYNR0_ABID_SHIFT        13
+#define ESYNR0_AVMID_SHIFT       16
+#define ESYNR0_ATID_SHIFT        24
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_SHIFT           0
+#define ESYNR1_ASHARED_SHIFT            3
+#define ESYNR1_AINNERSHARED_SHIFT       4
+#define ESYNR1_APRIV_SHIFT              5
+#define ESYNR1_APROTNS_SHIFT            6
+#define ESYNR1_AINST_SHIFT              7
+#define ESYNR1_AWRITE_SHIFT             8
+#define ESYNR1_ABURST_SHIFT             10
+#define ESYNR1_ALEN_SHIFT               12
+#define ESYNR1_ASIZE_SHIFT              16
+#define ESYNR1_ALOCK_SHIFT              20
+#define ESYNR1_AOOO_SHIFT               22
+#define ESYNR1_AFULL_SHIFT              24
+#define ESYNR1_AC_SHIFT                 30
+#define ESYNR1_DCD_SHIFT                31
+
+
+/* IDR */
+#define NM2VCBMT_SHIFT           0
+#define HTW_SHIFT                9
+#define HUM_SHIFT                10
+#define TLBSIZE_SHIFT            12
+#define NCB_SHIFT                16
+#define NIRPT_SHIFT              24
+
+
+/* M2VCBRn */
+#define VMID_SHIFT               0
+#define CBNDX_SHIFT              8
+#define BYPASSD_SHIFT            16
+#define BPRCOSH_SHIFT            17
+#define BPRCISH_SHIFT            18
+#define BPRCNSH_SHIFT            19
+#define BPSHCFG_SHIFT            20
+#define NSCFG_SHIFT              22
+#define BPMTCFG_SHIFT            24
+#define BPMEMTYPE_SHIFT          25
+
+
+/* REV */
+#define MINOR_SHIFT              0
+#define MAJOR_SHIFT              4
+
+
+/* TESTBUSCR */
+#define TBE_SHIFT                0
+#define SPDMBE_SHIFT             1
+#define WGSEL_SHIFT              8
+#define TBLSEL_SHIFT             12
+#define TBHSEL_SHIFT             14
+#define SPDM0SEL_SHIFT           16
+#define SPDM1SEL_SHIFT           20
+#define SPDM2SEL_SHIFT           24
+#define SPDM3SEL_SHIFT           28
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_SHIFT      0
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_SHIFT       0
+#define TLBBFBS_SHIFT            8
+
+
+/* TLBTR0 */
+#define PR_SHIFT                 0
+#define PW_SHIFT                 1
+#define UR_SHIFT                 2
+#define UW_SHIFT                 3
+#define XN_SHIFT                 4
+#define NSDESC_SHIFT             6
+#define ISH_SHIFT                7
+#define SH_SHIFT                 8
+#define MT_SHIFT                 9
+#define DPSIZR_SHIFT             16
+#define DPSIZC_SHIFT             20
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_SHIFT        0
+#define TLBTR1_PA_SHIFT          12
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_SHIFT        0
+#define TLBTR2_V_SHIFT           8
+#define TLBTR2_NSTID_SHIFT       9
+#define TLBTR2_NV_SHIFT          10
+#define TLBTR2_VA_SHIFT          12
+
+
+/* Context Register Masks */
+/* ACTLR */
+#define CFERE_MASK                       0x01
+#define CFEIE_MASK                       0x01
+#define PTSHCFG_MASK                     0x03
+#define RCOSH_MASK                       0x01
+#define RCISH_MASK                       0x01
+#define RCNSH_MASK                       0x01
+#define PRIVCFG_MASK                     0x03
+#define DNA_MASK                         0x01
+#define DNLV2PA_MASK                     0x01
+#define TLBMCFG_MASK                     0x03
+#define CFCFG_MASK                       0x01
+#define TIPCF_MASK                       0x01
+#define V2PCFG_MASK                      0x03
+#define HUME_MASK                        0x01
+#define PTMTCFG_MASK                     0x01
+#define PTMEMTYPE_MASK                   0x07
+
+
+/* BFBCR */
+#define BFBDFE_MASK                      0x01
+#define BFBSFE_MASK                      0x01
+#define SFVS_MASK                        0x01
+#define FLVIC_MASK                       0x0F
+#define SLVIC_MASK                       0x0F
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_MASK             0xFF
+#define PROCID_MASK                      0x00FFFFFF
+
+
+/* FSR */
+#define TF_MASK                          0x01
+#define AFF_MASK                         0x01
+#define APF_MASK                         0x01
+#define TLBMF_MASK                       0x01
+#define HTWDEEF_MASK                     0x01
+#define HTWSEEF_MASK                     0x01
+#define MHF_MASK                         0x01
+#define SL_MASK                          0x01
+#define SS_MASK                          0x01
+#define MULTI_MASK                       0x01
+
+
+/* FSYNR0 */
+#define AMID_MASK                        0xFF
+#define APID_MASK                        0x1F
+#define ABID_MASK                        0x07
+#define ATID_MASK                        0xFF
+
+
+/* FSYNR1 */
+#define AMEMTYPE_MASK                    0x07
+#define ASHARED_MASK                     0x01
+#define AINNERSHARED_MASK                0x01
+#define APRIV_MASK                       0x01
+#define APROTNS_MASK                     0x01
+#define AINST_MASK                       0x01
+#define AWRITE_MASK                      0x01
+#define ABURST_MASK                      0x01
+#define ALEN_MASK                        0x0F
+#define FSYNR1_ASIZE_MASK                0x07
+#define ALOCK_MASK                       0x03
+#define AFULL_MASK                       0x01
+
+
+/* NMRR */
+#define ICPC0_MASK                       0x03
+#define ICPC1_MASK                       0x03
+#define ICPC2_MASK                       0x03
+#define ICPC3_MASK                       0x03
+#define ICPC4_MASK                       0x03
+#define ICPC5_MASK                       0x03
+#define ICPC6_MASK                       0x03
+#define ICPC7_MASK                       0x03
+#define OCPC0_MASK                       0x03
+#define OCPC1_MASK                       0x03
+#define OCPC2_MASK                       0x03
+#define OCPC3_MASK                       0x03
+#define OCPC4_MASK                       0x03
+#define OCPC5_MASK                       0x03
+#define OCPC6_MASK                       0x03
+#define OCPC7_MASK                       0x03
+
+
+/* PAR */
+#define FAULT_MASK                       0x01
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_MASK                    0x01
+#define FAULT_AFF_MASK                   0x01
+#define FAULT_APF_MASK                   0x01
+#define FAULT_TLBMF_MASK                 0x01
+#define FAULT_HTWDEEF_MASK               0x01
+#define FAULT_HTWSEEF_MASK               0x01
+#define FAULT_MHF_MASK                   0x01
+#define FAULT_SL_MASK                    0x01
+#define FAULT_SS_MASK                    0x01
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_MASK              0x01
+#define PAR_NOFAULT_MT_MASK              0x07
+#define PAR_NOFAULT_SH_MASK              0x01
+#define PAR_NOFAULT_NS_MASK              0x01
+#define PAR_NOFAULT_NOS_MASK             0x01
+#define PAR_NPFAULT_PA_MASK              0x000FFFFF
+
+
+/* PRRR */
+#define MTC0_MASK                        0x03
+#define MTC1_MASK                        0x03
+#define MTC2_MASK                        0x03
+#define MTC3_MASK                        0x03
+#define MTC4_MASK                        0x03
+#define MTC5_MASK                        0x03
+#define MTC6_MASK                        0x03
+#define MTC7_MASK                        0x03
+#define SHDSH0_MASK                      0x01
+#define SHDSH1_MASK                      0x01
+#define SHNMSH0_MASK                     0x01
+#define SHNMSH1_MASK                     0x01
+#define NOS0_MASK                        0x01
+#define NOS1_MASK                        0x01
+#define NOS2_MASK                        0x01
+#define NOS3_MASK                        0x01
+#define NOS4_MASK                        0x01
+#define NOS5_MASK                        0x01
+#define NOS6_MASK                        0x01
+#define NOS7_MASK                        0x01
+
+
+/* RESUME */
+#define TNR_MASK                         0x01
+
+
+/* SCTLR */
+#define M_MASK                           0x01
+#define TRE_MASK                         0x01
+#define AFE_MASK                         0x01
+#define HAF_MASK                         0x01
+#define BE_MASK                          0x01
+#define AFFD_MASK                        0x01
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_MASK               0xFF
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_MASK                 0xFF
+#define TLBIVA_VA_MASK                   0x000FFFFF
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_MASK                  0x000FFFFF
+
+
+/* TLBLCKR */
+#define LKE_MASK                         0x01
+#define TLBLCKR_TLBIALLCFG_MASK          0x01
+#define TLBIASIDCFG_MASK                 0x01
+#define TLBIVAACFG_MASK                  0x01
+#define FLOOR_MASK                       0xFF
+#define VICTIM_MASK                      0xFF
+
+
+/* TTBCR */
+#define N_MASK                           0x07
+#define PD0_MASK                         0x01
+#define PD1_MASK                         0x01
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_MASK                 0x01
+#define TTBR0_SH_MASK                    0x01
+#define TTBR0_ORGN_MASK                  0x03
+#define TTBR0_NOS_MASK                   0x01
+#define TTBR0_IRGNL_MASK                 0x01
+#define TTBR0_PA_MASK                    0x0003FFFF
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_MASK                 0x01
+#define TTBR1_SH_MASK                    0x01
+#define TTBR1_ORGN_MASK                  0x03
+#define TTBR1_NOS_MASK                   0x01
+#define TTBR1_IRGNL_MASK                 0x01
+#define TTBR1_PA_MASK                    0x0003FFFF
+
+
+/* V2PSR */
+#define HIT_MASK                         0x01
+#define INDEX_MASK                       0xFF
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_MASK                 0xFF
+#define V2Pxx_VA_MASK                    0x000FFFFF
+
+
+/* Context Register Shifts */
+/* ACTLR */
+#define CFERE_SHIFT                    0
+#define CFEIE_SHIFT                    1
+#define PTSHCFG_SHIFT                  2
+#define RCOSH_SHIFT                    4
+#define RCISH_SHIFT                    5
+#define RCNSH_SHIFT                    6
+#define PRIVCFG_SHIFT                  8
+#define DNA_SHIFT                      10
+#define DNLV2PA_SHIFT                  11
+#define TLBMCFG_SHIFT                  12
+#define CFCFG_SHIFT                    14
+#define TIPCF_SHIFT                    15
+#define V2PCFG_SHIFT                   16
+#define HUME_SHIFT                     18
+#define PTMTCFG_SHIFT                  20
+#define PTMEMTYPE_SHIFT                21
+
+
+/* BFBCR */
+#define BFBDFE_SHIFT                   0
+#define BFBSFE_SHIFT                   1
+#define SFVS_SHIFT                     2
+#define FLVIC_SHIFT                    4
+#define SLVIC_SHIFT                    8
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_SHIFT          0
+#define PROCID_SHIFT                   8
+
+
+/* FSR */
+#define TF_SHIFT                       1
+#define AFF_SHIFT                      2
+#define APF_SHIFT                      3
+#define TLBMF_SHIFT                    4
+#define HTWDEEF_SHIFT                  5
+#define HTWSEEF_SHIFT                  6
+#define MHF_SHIFT                      7
+#define SL_SHIFT                       16
+#define SS_SHIFT                       30
+#define MULTI_SHIFT                    31
+
+
+/* FSYNR0 */
+#define AMID_SHIFT                     0
+#define APID_SHIFT                     8
+#define ABID_SHIFT                     13
+#define ATID_SHIFT                     24
+
+
+/* FSYNR1 */
+#define AMEMTYPE_SHIFT                 0
+#define ASHARED_SHIFT                  3
+#define AINNERSHARED_SHIFT             4
+#define APRIV_SHIFT                    5
+#define APROTNS_SHIFT                  6
+#define AINST_SHIFT                    7
+#define AWRITE_SHIFT                   8
+#define ABURST_SHIFT                   10
+#define ALEN_SHIFT                     12
+#define FSYNR1_ASIZE_SHIFT             16
+#define ALOCK_SHIFT                    20
+#define AFULL_SHIFT                    24
+
+
+/* NMRR */
+#define ICPC0_SHIFT                    0
+#define ICPC1_SHIFT                    2
+#define ICPC2_SHIFT                    4
+#define ICPC3_SHIFT                    6
+#define ICPC4_SHIFT                    8
+#define ICPC5_SHIFT                    10
+#define ICPC6_SHIFT                    12
+#define ICPC7_SHIFT                    14
+#define OCPC0_SHIFT                    16
+#define OCPC1_SHIFT                    18
+#define OCPC2_SHIFT                    20
+#define OCPC3_SHIFT                    22
+#define OCPC4_SHIFT                    24
+#define OCPC5_SHIFT                    26
+#define OCPC6_SHIFT                    28
+#define OCPC7_SHIFT                    30
+
+
+/* PAR */
+#define FAULT_SHIFT                    0
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_SHIFT                 1
+#define FAULT_AFF_SHIFT                2
+#define FAULT_APF_SHIFT                3
+#define FAULT_TLBMF_SHIFT              4
+#define FAULT_HTWDEEF_SHIFT            5
+#define FAULT_HTWSEEF_SHIFT            6
+#define FAULT_MHF_SHIFT                7
+#define FAULT_SL_SHIFT                 16
+#define FAULT_SS_SHIFT                 30
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_SHIFT           1
+#define PAR_NOFAULT_MT_SHIFT           4
+#define PAR_NOFAULT_SH_SHIFT           7
+#define PAR_NOFAULT_NS_SHIFT           9
+#define PAR_NOFAULT_NOS_SHIFT          10
+#define PAR_NPFAULT_PA_SHIFT           12
+
+
+/* PRRR */
+#define MTC0_SHIFT                     0
+#define MTC1_SHIFT                     2
+#define MTC2_SHIFT                     4
+#define MTC3_SHIFT                     6
+#define MTC4_SHIFT                     8
+#define MTC5_SHIFT                     10
+#define MTC6_SHIFT                     12
+#define MTC7_SHIFT                     14
+#define SHDSH0_SHIFT                   16
+#define SHDSH1_SHIFT                   17
+#define SHNMSH0_SHIFT                  18
+#define SHNMSH1_SHIFT                  19
+#define NOS0_SHIFT                     24
+#define NOS1_SHIFT                     25
+#define NOS2_SHIFT                     26
+#define NOS3_SHIFT                     27
+#define NOS4_SHIFT                     28
+#define NOS5_SHIFT                     29
+#define NOS6_SHIFT                     30
+#define NOS7_SHIFT                     31
+
+
+/* RESUME */
+#define TNR_SHIFT                      0
+
+
+/* SCTLR */
+#define M_SHIFT                        0
+#define TRE_SHIFT                      1
+#define AFE_SHIFT                      2
+#define HAF_SHIFT                      3
+#define BE_SHIFT                       4
+#define AFFD_SHIFT                     5
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_SHIFT            0
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_SHIFT              0
+#define TLBIVA_VA_SHIFT                12
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_SHIFT               12
+
+
+/* TLBLCKR */
+#define LKE_SHIFT                      0
+#define TLBLCKR_TLBIALLCFG_SHIFT       1
+#define TLBIASIDCFG_SHIFT              2
+#define TLBIVAACFG_SHIFT               3
+#define FLOOR_SHIFT                    8
+#define VICTIM_SHIFT                   8
+
+
+/* TTBCR */
+#define N_SHIFT                        3
+#define PD0_SHIFT                      4
+#define PD1_SHIFT                      5
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_SHIFT              0
+#define TTBR0_SH_SHIFT                 1
+#define TTBR0_ORGN_SHIFT               3
+#define TTBR0_NOS_SHIFT                5
+#define TTBR0_IRGNL_SHIFT              6
+#define TTBR0_PA_SHIFT                 14
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_SHIFT              0
+#define TTBR1_SH_SHIFT                 1
+#define TTBR1_ORGN_SHIFT               3
+#define TTBR1_NOS_SHIFT                5
+#define TTBR1_IRGNL_SHIFT              6
+#define TTBR1_PA_SHIFT                 14
+
+
+/* V2PSR */
+#define HIT_SHIFT                      0
+#define INDEX_SHIFT                    8
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_SHIFT              0
+#define V2Pxx_VA_SHIFT                 12
+
+#endif
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index 4c68265..868ed40 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -19,10 +19,6 @@
 #include <linux/of_irq.h>
 #include <asm/mach/irq.h>
 
-#ifdef CONFIG_EXYNOS_ATAGS
-#include <plat/cpu.h>
-#endif
-
 #include "irqchip.h"
 
 #define COMBINER_ENABLE_SET	0x0
@@ -138,7 +134,6 @@ static void __init combiner_init_one(struct combiner_chip_data *combiner_data,
 	__raw_writel(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
 }
 
-#ifdef CONFIG_OF
 static int combiner_irq_domain_xlate(struct irq_domain *d,
 				     struct device_node *controller,
 				     const u32 *intspec, unsigned int intsize,
@@ -156,16 +151,6 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
 
 	return 0;
 }
-#else
-static int combiner_irq_domain_xlate(struct irq_domain *d,
-				     struct device_node *controller,
-				     const u32 *intspec, unsigned int intsize,
-				     unsigned long *out_hwirq,
-				     unsigned int *out_type)
-{
-	return -EINVAL;
-}
-#endif
 
 static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
 				   irq_hw_number_t hw)
@@ -184,26 +169,6 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
 	.map	= combiner_irq_domain_map,
 };
 
-static unsigned int combiner_lookup_irq(int group)
-{
-#ifdef CONFIG_EXYNOS_ATAGS
-	if (group < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250())
-		return IRQ_SPI(group);
-
-	switch (group) {
-	case 16:
-		return IRQ_SPI(107);
-	case 17:
-		return IRQ_SPI(108);
-	case 18:
-		return IRQ_SPI(48);
-	case 19:
-		return IRQ_SPI(42);
-	}
-#endif
-	return 0;
-}
-
 static void __init combiner_init(void __iomem *combiner_base,
 				 struct device_node *np,
 				 unsigned int max_nr,
@@ -229,12 +194,7 @@ static void __init combiner_init(void __iomem *combiner_base,
 	}
 
 	for (i = 0; i < max_nr; i++) {
-#ifdef CONFIG_OF
-		if (np)
-			irq = irq_of_parse_and_map(np, i);
-		else
-#endif
-			irq = combiner_lookup_irq(i);
+		irq = irq_of_parse_and_map(np, i);
 
 		combiner_init_one(&combiner_data[i], i,
 				  combiner_base + (i >> 2) * 0x10, irq);
@@ -242,7 +202,6 @@ static void __init combiner_init(void __iomem *combiner_base,
 	}
 }
 
-#ifdef CONFIG_OF
 static int __init combiner_of_init(struct device_node *np,
 				   struct device_node *parent)
 {
@@ -275,4 +234,3 @@ static int __init combiner_of_init(struct device_node *np,
 }
 IRQCHIP_DECLARE(exynos4210_combiner, "samsung,exynos4210-combiner",
 		combiner_of_init);
-#endif
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index bb328a3..f2bb224 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -21,7 +21,10 @@
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/of_pci.h>
 #include <linux/irqdomain.h>
+#include <linux/slab.h>
+#include <linux/msi.h>
 #include <asm/mach/arch.h>
 #include <asm/exception.h>
 #include <asm/smp_plat.h>
@@ -51,12 +54,20 @@
 #define IPI_DOORBELL_START                      (0)
 #define IPI_DOORBELL_END                        (8)
 #define IPI_DOORBELL_MASK                       0xFF
+#define PCI_MSI_DOORBELL_START                  (16)
+#define PCI_MSI_DOORBELL_NR                     (16)
+#define PCI_MSI_DOORBELL_END                    (32)
+#define PCI_MSI_DOORBELL_MASK                   0xFFFF0000
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 static void __iomem *per_cpu_int_base;
 static void __iomem *main_int_base;
 static struct irq_domain *armada_370_xp_mpic_domain;
+#ifdef CONFIG_PCI_MSI
+static struct irq_domain *armada_370_xp_msi_domain;
+static phys_addr_t msi_doorbell_addr;
+#endif
 
 /*
  * In SMP mode:
@@ -87,6 +98,102 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
 				ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
 }
 
+#ifdef CONFIG_PCI_MSI
+
+static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
+				       struct pci_dev *pdev,
+				       struct msi_desc *desc)
+{
+	struct msi_msg msg;
+	irq_hw_number_t hwirq;
+	int virq;
+
+	virq = irq_alloc_mapping(armada_370_xp_msi_domain, &hwirq);
+	if (!virq)
+		return -EINVAL;
+
+	irq_set_msi_desc(virq, desc);
+
+	msg.address_lo = msi_doorbell_addr;
+	msg.address_hi = 0;
+	msg.data = 0xf00 | (hwirq + 16);
+
+	write_msi_msg(virq, &msg);
+	return 0;
+}
+
+static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
+					   unsigned int irq)
+{
+	irq_dispose_mapping(irq);
+}
+
+static struct irq_chip armada_370_xp_msi_irq_chip = {
+	.name = "armada_370_xp_msi_irq",
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
+};
+
+static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
+				 handle_simple_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
+	.map = armada_370_xp_msi_map,
+};
+
+static int armada_370_xp_msi_init(struct device_node *node,
+				  phys_addr_t main_int_phys_base)
+{
+	struct msi_chip *msi_chip;
+	u32 reg;
+
+	msi_doorbell_addr = main_int_phys_base +
+		ARMADA_370_XP_SW_TRIG_INT_OFFS;
+
+	msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
+	if (!msi_chip)
+		return -ENOMEM;
+
+	msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
+	msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
+
+	armada_370_xp_msi_domain =
+		irq_domain_add_msi(node, PCI_MSI_DOORBELL_NR,
+				   &armada_370_xp_msi_irq_ops,
+				   msi_chip, NULL);
+	if (!armada_370_xp_msi_domain) {
+		kfree(msi_chip);
+		return -ENOMEM;
+	}
+
+	reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
+		| PCI_MSI_DOORBELL_MASK;
+
+	writel(reg, per_cpu_int_base +
+	       ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+
+	/* Unmask IPI interrupt */
+	writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+
+	return 0;
+}
+#else
+static inline int armada_370_xp_msi_init(struct device_node *node,
+					 phys_addr_t main_int_phys_base)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SMP
 static int armada_xp_set_affinity(struct irq_data *d,
 				  const struct cpumask *mask_val, bool force)
@@ -214,12 +321,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
 		if (irqnr > 1022)
 			break;
 
-		if (irqnr > 0) {
+		if (irqnr > 1) {
 			irqnr =	irq_find_mapping(armada_370_xp_mpic_domain,
 					irqnr);
 			handle_IRQ(irqnr, regs);
 			continue;
 		}
+
+#ifdef CONFIG_PCI_MSI
+		/* MSI handling */
+		if (irqnr == 1) {
+			u32 msimask, msinr;
+
+			msimask = readl_relaxed(per_cpu_int_base +
+						ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
+				& PCI_MSI_DOORBELL_MASK;
+
+			writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
+			       ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+			for (msinr = PCI_MSI_DOORBELL_START;
+			     msinr < PCI_MSI_DOORBELL_END; msinr++) {
+				int irq;
+
+				if (!(msimask & BIT(msinr)))
+					continue;
+
+				irq = irq_find_mapping(armada_370_xp_msi_domain,
+						       msinr - 16);
+				handle_IRQ(irq, regs);
+			}
+		}
+#endif
+
 #ifdef CONFIG_SMP
 		/* IPI Handling */
 		if (irqnr == 0) {
@@ -248,12 +382,25 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
 static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 					     struct device_node *parent)
 {
+	struct resource main_int_res, per_cpu_int_res;
 	u32 control;
 
-	main_int_base = of_iomap(node, 0);
-	per_cpu_int_base = of_iomap(node, 1);
+	BUG_ON(of_address_to_resource(node, 0, &main_int_res));
+	BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res));
 
+	BUG_ON(!request_mem_region(main_int_res.start,
+				   resource_size(&main_int_res),
+				   node->full_name));
+	BUG_ON(!request_mem_region(per_cpu_int_res.start,
+				   resource_size(&per_cpu_int_res),
+				   node->full_name));
+
+	main_int_base = ioremap(main_int_res.start,
+				resource_size(&main_int_res));
 	BUG_ON(!main_int_base);
+
+	per_cpu_int_base = ioremap(per_cpu_int_res.start,
+				   resource_size(&per_cpu_int_res));
 	BUG_ON(!per_cpu_int_base);
 
 	control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
@@ -262,8 +409,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 		irq_domain_add_linear(node, (control >> 2) & 0x3ff,
 				&armada_370_xp_mpic_irq_ops, NULL);
 
-	if (!armada_370_xp_mpic_domain)
-		panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
+	BUG_ON(!armada_370_xp_mpic_domain);
 
 	irq_set_default_host(armada_370_xp_mpic_domain);
 
@@ -280,6 +426,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 
 #endif
 
+	armada_370_xp_msi_init(node, main_int_res.start);
+
 	set_handle_irq(armada_370_xp_handle_irq);
 
 	return 0;
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index a7e4939..7f910c7 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -1307,11 +1307,11 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
 		}
 		if (fifo2 & 2) {
 			hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2;
-			hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS +
+			hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS |
 					   HFCPCI_INTS_B2REC);
 		} else {
 			hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B1;
-			hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS +
+			hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS |
 					   HFCPCI_INTS_B1REC);
 		}
 #ifdef REVERSE_BITORDER
@@ -1346,14 +1346,14 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
 		if (fifo2 & 2) {
 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
 			if (!tics)
-				hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
+				hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS |
 						  HFCPCI_INTS_B2REC);
 			hc->hw.ctmt |= 2;
 			hc->hw.conn &= ~0x18;
 		} else {
 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
 			if (!tics)
-				hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
+				hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS |
 						  HFCPCI_INTS_B1REC);
 			hc->hw.ctmt |= 1;
 			hc->hw.conn &= ~0x03;
@@ -1375,14 +1375,14 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
 		if (fifo2 & 2) {
 			hc->hw.last_bfifo_cnt[1] = 0;
 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
-			hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
+			hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS |
 					  HFCPCI_INTS_B2REC);
 			hc->hw.ctmt &= ~2;
 			hc->hw.conn &= ~0x18;
 		} else {
 			hc->hw.last_bfifo_cnt[0] = 0;
 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
-			hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
+			hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS |
 					  HFCPCI_INTS_B1REC);
 			hc->hw.ctmt &= ~1;
 			hc->hw.conn &= ~0x03;
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index 1063bab..36817e0 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -314,7 +314,7 @@ Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
 
 							t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx);
 							QuickHex(t, cs->rcvbuf, cs->rcvidx);
-							debugl1(cs, cs->dlog);
+							debugl1(cs, "%s", cs->dlog);
 						}
 						/* moves received data in sk-buffer */
 						memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx);
@@ -406,7 +406,7 @@ Amd7930_fill_Dfifo(struct IsdnCardState *cs)
 
 		t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);
 		QuickHex(t, deb_ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 	/* AMD interrupts on */
 	AmdIrqOn(cs);
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index ee9b9a0..d1427bd 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -285,7 +285,7 @@ hdlc_empty_fifo(struct BCState *bcs, int count)
 		t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
 			     bcs->channel ? 'B' : 'A', count);
 		QuickHex(t, p, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
@@ -345,7 +345,7 @@ hdlc_fill_fifo(struct BCState *bcs)
 		t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
 			     bcs->channel ? 'B' : 'A', count);
 		QuickHex(t, p, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..b33f53b 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1896,7 +1896,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if)
 				ptr--;
 				*ptr++ = '\n';
 				*ptr = 0;
-				HiSax_putstatus(cs, NULL, cs->dlog);
+				HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 			} else
 				HiSax_putstatus(cs, "LogEcho: ",
 						"warning Frame too big (%d)",
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 8d0cf6e..4fc90de 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -427,7 +427,7 @@ Memhscx_empty_fifo(struct BCState *bcs, int count)
 		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
 			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
@@ -469,7 +469,7 @@ Memhscx_fill_fifo(struct BCState *bcs)
 		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
 			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 1df6f9a..2be1c8a 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -535,7 +535,7 @@ check_arcofi(struct IsdnCardState *cs)
 		t = tmp;
 		t += sprintf(tmp, "Arcofi data");
 		QuickHex(t, p, cs->dc.isac.mon_rxp);
-		debugl1(cs, tmp);
+		debugl1(cs, "%s", tmp);
 		if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) {
 			switch (cs->dc.isac.mon_rx[1]) {
 			case 0x80:
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index d4c98d3..3f84dd8 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -344,7 +344,7 @@ static inline void receive_chars(struct IsdnCardState *cs,
 
 		t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
 		QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
-		debugl1(cs, tmp);
+		debugl1(cs, "%s", tmp);
 	}
 	cs->hw.elsa.rcvcnt = 0;
 }
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 3ccd724..497bd02 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -901,7 +901,7 @@ Begin:
 					ptr--;
 					*ptr++ = '\n';
 					*ptr = 0;
-					HiSax_putstatus(cs, NULL, cs->dlog);
+					HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 				} else
 					HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
 			}
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index dc4574f..fa1fefd 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -674,7 +674,7 @@ receive_emsg(struct IsdnCardState *cs)
 					ptr--;
 					*ptr++ = '\n';
 					*ptr = 0;
-					HiSax_putstatus(cs, NULL, cs->dlog);
+					HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 				} else
 					HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len);
 			}
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index f398d48..a8d6188 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -75,7 +75,7 @@ hscx_empty_fifo(struct BCState *bcs, int count)
 		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
 			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
@@ -115,7 +115,7 @@ hscx_fill_fifo(struct BCState *bcs)
 		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
 			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index db5321f..51dae91 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -134,7 +134,7 @@ icc_empty_fifo(struct IsdnCardState *cs, int count)
 
 		t += sprintf(t, "icc_empty_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
@@ -176,7 +176,7 @@ icc_fill_fifo(struct IsdnCardState *cs)
 
 		t += sprintf(t, "icc_fill_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
index 74feb5c..5faa5de 100644
--- a/drivers/isdn/hisax/ipacx.c
+++ b/drivers/isdn/hisax/ipacx.c
@@ -260,7 +260,7 @@ dch_empty_fifo(struct IsdnCardState *cs, int count)
 
 		t += sprintf(t, "dch_empty_fifo() cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
@@ -307,7 +307,7 @@ dch_fill_fifo(struct IsdnCardState *cs)
 
 		t += sprintf(t, "dch_fill_fifo() cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
@@ -539,7 +539,7 @@ bch_empty_fifo(struct BCState *bcs, int count)
 
 		t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
@@ -582,7 +582,7 @@ bch_fill_fifo(struct BCState *bcs)
 
 		t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index a365ccc..7fdf78f 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -137,7 +137,7 @@ isac_empty_fifo(struct IsdnCardState *cs, int count)
 
 		t += sprintf(t, "isac_empty_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
@@ -179,7 +179,7 @@ isac_fill_fifo(struct IsdnCardState *cs)
 
 		t += sprintf(t, "isac_fill_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 7fdf347..f4956c7 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -74,7 +74,7 @@ sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
 				t = tmp;
 				t += sprintf(t, "sendmbox cnt %d", len);
 				QuickHex(t, &msg[len-i], (i > 64) ? 64 : i);
-				debugl1(cs, tmp);
+				debugl1(cs, "%s", tmp);
 				i -= 64;
 			}
 		}
@@ -105,7 +105,7 @@ rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
 				t = tmp;
 				t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
 				QuickHex(t, &msg[ireg->clsb - i], (i > 64) ? 64 : i);
-				debugl1(cs, tmp);
+				debugl1(cs, "%s", tmp);
 				i -= 64;
 			}
 		}
@@ -1248,7 +1248,7 @@ isar_int_main(struct IsdnCardState *cs)
 			tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
 				      ireg->iis, ireg->cmsb);
 			QuickHex(tp, (u_char *)ireg->par, ireg->clsb);
-			debugl1(cs, debbuf);
+			debugl1(cs, "%s", debbuf);
 		}
 		break;
 	case ISAR_IIS_INVMSG:
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index f946c58..e2ae787 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -81,10 +81,7 @@ modejade(struct BCState *bcs, int mode, int bc)
 	int jade = bcs->hw.hscx.hscx;
 
 	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "jade %c mode %d ichan %d",
-			'A' + jade, mode, bc);
-		debugl1(cs, tmp);
+		debugl1(cs, "jade %c mode %d ichan %d", 'A' + jade, mode, bc);
 	}
 	bcs->mode = mode;
 	bcs->channel = bc;
@@ -257,23 +254,18 @@ void
 clear_pending_jade_ints(struct IsdnCardState *cs)
 {
 	int val;
-	char tmp[64];
 
 	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
 	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
 
 	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
-	sprintf(tmp, "jade B ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade B ISTA %x", val);
 	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
-	sprintf(tmp, "jade A ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade A ISTA %x", val);
 	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
-	sprintf(tmp, "jade B STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade B STAR %x", val);
 	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
-	sprintf(tmp, "jade A STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade A STAR %x", val);
 	/* Unmask ints */
 	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
 	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
index f521fc8..b930da9 100644
--- a/drivers/isdn/hisax/jade_irq.c
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -65,7 +65,7 @@ jade_empty_fifo(struct BCState *bcs, int count)
 		t += sprintf(t, "jade_empty_fifo %c cnt %d",
 			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
@@ -105,7 +105,7 @@ jade_fill_fifo(struct BCState *bcs)
 		t += sprintf(t, "jade_fill_fifo %c cnt %d",
 			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index 4c1bca5..875402e 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -63,7 +63,7 @@ l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
 {
 	dev_kfree_skb(skb);
 	if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, msg);
+		l3_debug(pc->st, "%s", msg);
 	l3_1tr6_release_req(pc, 0, NULL);
 }
 
@@ -161,7 +161,6 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
 {
 	u_char *p;
 	int bcfound = 0;
-	char tmp[80];
 	struct sk_buff *skb = arg;
 
 	/* Channel Identification */
@@ -214,10 +213,9 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
 	/* Signal all services, linklevel takes care of Service-Indicator */
 	if (bcfound) {
 		if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) {
-			sprintf(tmp, "non-digital call: %s -> %s",
+			l3_debug(pc->st, "non-digital call: %s -> %s",
 				pc->para.setup.phone,
 				pc->para.setup.eazmsn);
-			l3_debug(pc->st, tmp);
 		}
 		newl3state(pc, 6);
 		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
@@ -301,7 +299,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
 {
 	u_char *p;
 	int i, tmpcharge = 0;
-	char a_charge[8], tmp[32];
+	char a_charge[8];
 	struct sk_buff *skb = arg;
 
 	p = skb->data;
@@ -316,8 +314,8 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
 			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
-			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
-			l3_debug(pc->st, tmp);
+			l3_debug(pc->st, "charging info %d",
+				 pc->para.chargeinfo);
 		}
 	} else if (pc->st->l3.debug & L3_DEB_CHARGE)
 		l3_debug(pc->st, "charging info not found");
@@ -399,7 +397,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
 	struct sk_buff *skb = arg;
 	u_char *p;
 	int i, tmpcharge = 0;
-	char a_charge[8], tmp[32];
+	char a_charge[8];
 
 	StopAllL3Timer(pc);
 	p = skb->data;
@@ -414,8 +412,8 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
 			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
-			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
-			l3_debug(pc->st, tmp);
+			l3_debug(pc->st, "charging info %d",
+				 pc->para.chargeinfo);
 		}
 	} else if (pc->st->l3.debug & L3_DEB_CHARGE)
 		l3_debug(pc->st, "charging info not found");
@@ -746,7 +744,6 @@ up1tr6(struct PStack *st, int pr, void *arg)
 	int i, mt, cr;
 	struct l3_process *proc;
 	struct sk_buff *skb = arg;
-	char tmp[80];
 
 	switch (pr) {
 	case (DL_DATA | INDICATION):
@@ -762,26 +759,23 @@ up1tr6(struct PStack *st, int pr, void *arg)
 	}
 	if (skb->len < 4) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6 len only %d", skb->len);
-			l3_debug(st, tmp);
+			l3_debug(st, "up1tr6 len only %d", skb->len);
 		}
 		dev_kfree_skb(skb);
 		return;
 	}
 	if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
+			l3_debug(st, "up1tr6%sunexpected discriminator %x message len %d",
 				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				skb->data[0], skb->len);
-			l3_debug(st, tmp);
 		}
 		dev_kfree_skb(skb);
 		return;
 	}
 	if (skb->data[1] != 1) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "up1tr6 CR len not 1");
-			l3_debug(st, tmp);
+			l3_debug(st, "up1tr6 CR len not 1");
 		}
 		dev_kfree_skb(skb);
 		return;
@@ -791,9 +785,8 @@ up1tr6(struct PStack *st, int pr, void *arg)
 	if (skb->data[0] == PROTO_DIS_N0) {
 		dev_kfree_skb(skb);
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
+			l3_debug(st, "up1tr6%s N0 mt %x unhandled",
 				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
-			l3_debug(st, tmp);
 		}
 	} else if (skb->data[0] == PROTO_DIS_N1) {
 		if (!(proc = getl3proc(st, cr))) {
@@ -801,8 +794,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 				if (cr < 128) {
 					if (!(proc = new_l3_process(st, cr))) {
 						if (st->l3.debug & L3_DEB_PROTERR) {
-							sprintf(tmp, "up1tr6 no roc mem");
-							l3_debug(st, tmp);
+							l3_debug(st, "up1tr6 no roc mem");
 						}
 						dev_kfree_skb(skb);
 						return;
@@ -821,8 +813,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 			} else {
 				if (!(proc = new_l3_process(st, cr))) {
 					if (st->l3.debug & L3_DEB_PROTERR) {
-						sprintf(tmp, "up1tr6 no roc mem");
-						l3_debug(st, tmp);
+						l3_debug(st, "up1tr6 no roc mem");
 					}
 					dev_kfree_skb(skb);
 					return;
@@ -837,18 +828,16 @@ up1tr6(struct PStack *st, int pr, void *arg)
 		if (i == ARRAY_SIZE(datastln1)) {
 			dev_kfree_skb(skb);
 			if (st->l3.debug & L3_DEB_STATE) {
-				sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
+				l3_debug(st, "up1tr6%sstate %d mt %x unhandled",
 					(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 					proc->state, mt);
-				l3_debug(st, tmp);
 			}
 			return;
 		} else {
 			if (st->l3.debug & L3_DEB_STATE) {
-				sprintf(tmp, "up1tr6%sstate %d mt %x",
+				l3_debug(st, "up1tr6%sstate %d mt %x",
 					(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 					proc->state, mt);
-				l3_debug(st, tmp);
 			}
 			datastln1[i].rout(proc, pr, skb);
 		}
@@ -861,7 +850,6 @@ down1tr6(struct PStack *st, int pr, void *arg)
 	int i, cr;
 	struct l3_process *proc;
 	struct Channel *chan;
-	char tmp[80];
 
 	if ((DL_ESTABLISH | REQUEST) == pr) {
 		l3_msg(st, pr, NULL);
@@ -888,15 +876,13 @@ down1tr6(struct PStack *st, int pr, void *arg)
 			break;
 	if (i == ARRAY_SIZE(downstl)) {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "down1tr6 state %d prim %d unhandled",
+			l3_debug(st, "down1tr6 state %d prim %d unhandled",
 				proc->state, pr);
-			l3_debug(st, tmp);
 		}
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "down1tr6 state %d prim %d",
+			l3_debug(st, "down1tr6 state %d prim %d",
 				proc->state, pr);
-			l3_debug(st, tmp);
 		}
 		downstl[i].rout(proc, pr, arg);
 	}
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index b646eed..233e432 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -176,7 +176,7 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s
 		else
 			j = i;
 		QuickHex(t, p, j);
-		debugl1(cs, tmp);
+		debugl1(cs, "%s", tmp);
 		p += j;
 		i -= j;
 		t = tmp;
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index 041bf52..af1b020 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -1179,7 +1179,7 @@ LogFrame(struct IsdnCardState *cs, u_char *buf, int size)
 		dp--;
 		*dp++ = '\n';
 		*dp = 0;
-		HiSax_putstatus(cs, NULL, cs->dlog);
+		HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 	} else
 		HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
 }
@@ -1246,7 +1246,7 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
 	}
 	if (finish) {
 		*dp = 0;
-		HiSax_putstatus(cs, NULL, cs->dlog);
+		HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 		return;
 	}
 	if ((0xfe & buf[0]) == PROTO_DIS_N0) {	/* 1TR6 */
@@ -1509,5 +1509,5 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
 		dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
 	}
 	*dp = 0;
-	HiSax_putstatus(cs, NULL, cs->dlog);
+	HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 }
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index d8cac69..a858955 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -154,7 +154,7 @@ W6692_empty_fifo(struct IsdnCardState *cs, int count)
 
 		t += sprintf(t, "W6692_empty_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
@@ -196,7 +196,7 @@ W6692_fill_fifo(struct IsdnCardState *cs)
 
 		t += sprintf(t, "W6692_fill_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
+		debugl1(cs, "%s", cs->dlog);
 	}
 }
 
@@ -226,7 +226,7 @@ W6692B_empty_fifo(struct BCState *bcs, int count)
 		t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
 			     bcs->channel + '1', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
@@ -264,7 +264,7 @@ W6692B_fill_fifo(struct BCState *bcs)
 		t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
 			     bcs->channel + '1', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
+		debugl1(cs, "%s", bcs->blog);
 	}
 }
 
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index da30c5c..6b3c8b7 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -21,10 +21,14 @@
 #include "core.h"
 
 static u_int debug;
+static u_int gid;
+kgid_t misdn_permitted_gid;
 
 MODULE_AUTHOR("Karsten Keil");
 MODULE_LICENSE("GPL");
 module_param(debug, uint, S_IRUGO | S_IWUSR);
+module_param(gid, uint, 0);
+MODULE_PARM_DESC(gid, "Unix group for accessing misdn socket (default 0)");
 
 static u64		device_ids;
 #define MAX_DEVICE_ID	63
@@ -37,8 +41,8 @@ static void mISDN_dev_release(struct device *dev)
 	/* nothing to do: the device is part of its parent's data structure */
 }
 
-static ssize_t _show_id(struct device *dev,
-			struct device_attribute *attr, char *buf)
+static ssize_t id_show(struct device *dev,
+		       struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -46,9 +50,10 @@ static ssize_t _show_id(struct device *dev,
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->id);
 }
+static DEVICE_ATTR_RO(id);
 
-static ssize_t _show_nrbchan(struct device *dev,
-			     struct device_attribute *attr, char *buf)
+static ssize_t nrbchan_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -56,9 +61,10 @@ static ssize_t _show_nrbchan(struct device *dev,
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->nrbchan);
 }
+static DEVICE_ATTR_RO(nrbchan);
 
-static ssize_t _show_d_protocols(struct device *dev,
-				 struct device_attribute *attr, char *buf)
+static ssize_t d_protocols_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -66,9 +72,10 @@ static ssize_t _show_d_protocols(struct device *dev,
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->Dprotocols);
 }
+static DEVICE_ATTR_RO(d_protocols);
 
-static ssize_t _show_b_protocols(struct device *dev,
-				 struct device_attribute *attr, char *buf)
+static ssize_t b_protocols_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -76,9 +83,10 @@ static ssize_t _show_b_protocols(struct device *dev,
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
 }
+static DEVICE_ATTR_RO(b_protocols);
 
-static ssize_t _show_protocol(struct device *dev,
-			      struct device_attribute *attr, char *buf)
+static ssize_t protocol_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -86,17 +94,19 @@ static ssize_t _show_protocol(struct device *dev,
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->D.protocol);
 }
+static DEVICE_ATTR_RO(protocol);
 
-static ssize_t _show_name(struct device *dev,
-			  struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
 {
 	strcpy(buf, dev_name(dev));
 	return strlen(buf);
 }
+static DEVICE_ATTR_RO(name);
 
 #if 0 /* hangs */
-static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count)
+static ssize_t name_set(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
 	int err = 0;
 	char *out = kmalloc(count + 1, GFP_KERNEL);
@@ -113,10 +123,11 @@ static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
 
 	return (err < 0) ? err : count;
 }
+static DEVICE_ATTR_RW(name);
 #endif
 
-static ssize_t _show_channelmap(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t channelmap_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 	char *bp = buf;
@@ -127,18 +138,19 @@ static ssize_t _show_channelmap(struct device *dev,
 
 	return bp - buf;
 }
-
-static struct device_attribute mISDN_dev_attrs[] = {
-	__ATTR(id,          S_IRUGO,         _show_id,          NULL),
-	__ATTR(d_protocols, S_IRUGO,         _show_d_protocols, NULL),
-	__ATTR(b_protocols, S_IRUGO,         _show_b_protocols, NULL),
-	__ATTR(protocol,    S_IRUGO,         _show_protocol,    NULL),
-	__ATTR(channelmap,  S_IRUGO,         _show_channelmap,  NULL),
-	__ATTR(nrbchan,     S_IRUGO,         _show_nrbchan,     NULL),
-	__ATTR(name,        S_IRUGO,         _show_name,        NULL),
-/*	__ATTR(name,        S_IRUGO | S_IWUSR, _show_name,      _set_name), */
-	{}
+static DEVICE_ATTR_RO(channelmap);
+
+static struct attribute *mISDN_attrs[] = {
+	&dev_attr_id.attr,
+	&dev_attr_d_protocols.attr,
+	&dev_attr_b_protocols.attr,
+	&dev_attr_protocol.attr,
+	&dev_attr_channelmap.attr,
+	&dev_attr_nrbchan.attr,
+	&dev_attr_name.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(mISDN);
 
 static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -162,7 +174,7 @@ static struct class mISDN_class = {
 	.name = "mISDN",
 	.owner = THIS_MODULE,
 	.dev_uevent = mISDN_uevent,
-	.dev_attrs = mISDN_dev_attrs,
+	.dev_groups = mISDN_groups,
 	.dev_release = mISDN_dev_release,
 	.class_release = mISDN_class_release,
 };
@@ -372,6 +384,8 @@ mISDNInit(void)
 {
 	int	err;
 
+	misdn_permitted_gid = make_kgid(current_user_ns(), gid);
+
 	printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
 	       MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
 	mISDN_init_clock(&debug);
diff --git a/drivers/isdn/mISDN/core.h b/drivers/isdn/mISDN/core.h
index 52695bb..5f509bf 100644
--- a/drivers/isdn/mISDN/core.h
+++ b/drivers/isdn/mISDN/core.h
@@ -17,6 +17,7 @@
 
 extern struct mISDNdevice	*get_mdevice(u_int);
 extern int			get_mdevice_count(void);
+extern kgid_t misdn_permitted_gid;
 
 /* stack status flag */
 #define mISDN_STACK_ACTION_MASK		0x0000ffff
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index e47dcb9..8dcef36 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -612,6 +612,11 @@ data_sock_create(struct net *net, struct socket *sock, int protocol)
 {
 	struct sock *sk;
 
+	if (!capable(CAP_SYS_ADMIN) &&
+			!gid_eq(misdn_permitted_gid, current_gid()) &&
+			!in_group_p(misdn_permitted_gid))
+		return -EPERM;
+
 	if (sock->type != SOCK_DGRAM)
 		return -ESOCKTNOSUPPORT;
 
@@ -694,6 +699,10 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 	case IMSETDEVNAME:
 	{
 		struct mISDN_devrename dn;
+		if (!capable(CAP_SYS_ADMIN) &&
+				!gid_eq(misdn_permitted_gid, current_gid()) &&
+				!in_group_p(misdn_permitted_gid))
+			return -EPERM;
 		if (copy_from_user(&dn, (void __user *)arg,
 				   sizeof(dn))) {
 			err = -EFAULT;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e43402d..24e055d 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -194,11 +194,11 @@ config LEDS_LP3944
 	  module will be called leds-lp3944.
 
 config LEDS_LP55XX_COMMON
-	tristate "Common Driver for TI/National LP5521, LP5523/55231 and LP5562"
-	depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562
+	tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
+	depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
 	select FW_LOADER
 	help
-	  This option supports common operations for LP5521 and LP5523/55231
+	  This option supports common operations for LP5521/5523/55231/5562/8501
 	  devices.
 
 config LEDS_LP5521
@@ -232,6 +232,18 @@ config LEDS_LP5562
 	  Driver provides direct control via LED class and interface for
 	  programming the engines.
 
+config LEDS_LP8501
+	tristate "LED Support for TI LP8501 LED driver chip"
+	depends on LEDS_CLASS && I2C
+	select LEDS_LP55XX_COMMON
+	help
+	  If you say yes here you get support for TI LP8501 LED driver.
+	  It is 9 channel chip with programmable engines.
+	  Driver provides direct control via LED class and interface for
+	  programming the engines.
+	  It is similar as LP5523, but output power selection is available.
+	  And register layout and engine program schemes are different.
+
 config LEDS_LP8788
 	tristate "LED support for the TI LP8788 PMIC"
 	depends on LEDS_CLASS
@@ -398,10 +410,7 @@ config LEDS_MC13783
 config LEDS_NS2
 	tristate "LED support for Network Space v2 GPIO LEDs"
 	depends on LEDS_CLASS
-	depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || \
-		   MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2 || \
-		   MACH_NETSPACE_V2_DT || MACH_INETSPACE_V2_DT || \
-		   MACH_NETSPACE_MAX_V2_DT || MACH_NETSPACE_MINI_V2_DT
+	depends on ARCH_KIRKWOOD
 	default y
 	help
 	  This option enable support for the dual-GPIO LED found on the
@@ -410,8 +419,8 @@ config LEDS_NS2
 
 config LEDS_NETXBIG
 	tristate "LED support for Big Network series LEDs"
-	depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
 	depends on LEDS_CLASS
+	depends on ARCH_KIRKWOOD
 	default y
 	help
 	  This option enable support for LEDs found on the LaCie 2Big
@@ -429,18 +438,6 @@ config LEDS_ASIC3
 	  cannot be used. This driver supports hardware blinking with an on+off
 	  period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
 
-config LEDS_RENESAS_TPU
-	bool "LED support for Renesas TPU"
-	depends on LEDS_CLASS=y && HAVE_CLK && GPIOLIB
-	help
-	  This option enables build of the LED TPU platform driver,
-	  suitable to drive any TPU channel on newer Renesas SoCs.
-	  The driver controls the GPIO pin connected to the LED via
-	  the GPIO framework and expects the LED to be connected to
-	  a pin that can be driven in both GPIO mode and using TPU
-	  pin function. The latter to support brightness control.
-	  Brightness control is supported but hardware blinking is not.
-
 config LEDS_TCA6507
 	tristate "LED Support for TCA6507 I2C chip"
 	depends on LEDS_CLASS && I2C
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index ac28977..a46b165 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_LEDS_LP55XX_COMMON)	+= leds-lp55xx-common.o
 obj-$(CONFIG_LEDS_LP5521)		+= leds-lp5521.o
 obj-$(CONFIG_LEDS_LP5523)		+= leds-lp5523.o
 obj-$(CONFIG_LEDS_LP5562)		+= leds-lp5562.o
+obj-$(CONFIG_LEDS_LP8501)		+= leds-lp8501.o
 obj-$(CONFIG_LEDS_LP8788)		+= leds-lp8788.o
 obj-$(CONFIG_LEDS_TCA6507)		+= leds-tca6507.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
@@ -49,7 +50,6 @@ obj-$(CONFIG_LEDS_MC13783)		+= leds-mc13783.o
 obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
-obj-$(CONFIG_LEDS_RENESAS_TPU)		+= leds-renesas-tpu.o
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 4336e37..f37d63c 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev)
 		led_cdev->brightness = led_cdev->brightness_get(led_cdev);
 }
 
-static ssize_t led_brightness_show(struct device *dev,
+static ssize_t brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -40,7 +40,7 @@ static ssize_t led_brightness_show(struct device *dev,
 	return sprintf(buf, "%u\n", led_cdev->brightness);
 }
 
-static ssize_t led_brightness_store(struct device *dev,
+static ssize_t brightness_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t size)
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -57,6 +57,7 @@ static ssize_t led_brightness_store(struct device *dev,
 
 	return size;
 }
+static DEVICE_ATTR_RW(brightness);
 
 static ssize_t led_max_brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -65,14 +66,35 @@ static ssize_t led_max_brightness_show(struct device *dev,
 
 	return sprintf(buf, "%u\n", led_cdev->max_brightness);
 }
+static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL);
 
-static struct device_attribute led_class_attrs[] = {
-	__ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
-	__ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
 #ifdef CONFIG_LEDS_TRIGGERS
-	__ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
+static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
+static struct attribute *led_trigger_attrs[] = {
+	&dev_attr_trigger.attr,
+	NULL,
+};
+static const struct attribute_group led_trigger_group = {
+	.attrs = led_trigger_attrs,
+};
+#endif
+
+static struct attribute *led_class_attrs[] = {
+	&dev_attr_brightness.attr,
+	&dev_attr_max_brightness.attr,
+	NULL,
+};
+
+static const struct attribute_group led_group = {
+	.attrs = led_class_attrs,
+};
+
+static const struct attribute_group *led_groups[] = {
+	&led_group,
+#ifdef CONFIG_LEDS_TRIGGERS
+	&led_trigger_group,
 #endif
-	__ATTR_NULL,
+	NULL,
 };
 
 static void led_timer_function(unsigned long data)
@@ -258,7 +280,7 @@ static int __init leds_init(void)
 	if (IS_ERR(leds_class))
 		return PTR_ERR(leds_class);
 	leds_class->pm = &leds_class_dev_pm_ops;
-	leds_class->dev_attrs = led_class_attrs;
+	leds_class->dev_groups = led_groups;
 	return 0;
 }
 
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 232b3ce..5f588c0 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -157,7 +157,7 @@ static int pm860x_led_dt_init(struct platform_device *pdev,
 static int pm860x_led_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_led_pdata *pdata = pdev->dev.platform_data;
+	struct pm860x_led_pdata *pdata = dev_get_platdata(&pdev->dev);
 	struct pm860x_led *data;
 	struct resource *res;
 	int ret = 0;
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index e8072ab..7e311a1 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -87,7 +87,7 @@ static int adp5520_led_setup(struct adp5520_led *led)
 
 static int adp5520_led_prepare(struct platform_device *pdev)
 {
-	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device *dev = pdev->dev.parent;
 	int ret = 0;
 
@@ -103,7 +103,7 @@ static int adp5520_led_prepare(struct platform_device *pdev)
 
 static int adp5520_led_probe(struct platform_device *pdev)
 {
-	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct adp5520_led *led, *led_dat;
 	struct led_info *cur_led;
 	int ret, i;
@@ -185,7 +185,7 @@ err:
 
 static int adp5520_led_remove(struct platform_device *pdev)
 {
-	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct adp5520_led *led;
 	int i;
 
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index cf9efe4..6de216a 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -94,7 +94,7 @@ static int blink_set(struct led_classdev *cdev,
 
 static int asic3_led_probe(struct platform_device *pdev)
 {
-	struct asic3_led *led = pdev->dev.platform_data;
+	struct asic3_led *led = dev_get_platdata(&pdev->dev);
 	int ret;
 
 	ret = mfd_cell_enable(pdev);
@@ -127,7 +127,7 @@ out:
 
 static int asic3_led_remove(struct platform_device *pdev)
 {
-	struct asic3_led *led = pdev->dev.platform_data;
+	struct asic3_led *led = dev_get_platdata(&pdev->dev);
 
 	led_classdev_unregister(led->cdev);
 
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 90518f8..56cec8d 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -42,7 +42,7 @@ static int pwmled_probe(struct platform_device *pdev)
 	int					i;
 	int					status;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata || pdata->num_leds < 1)
 		return -ENODEV;
 
@@ -119,7 +119,7 @@ static int pwmled_remove(struct platform_device *pdev)
 	struct pwmled				*leds;
 	unsigned				i;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	leds = platform_get_drvdata(pdev);
 
 	for (i = 0; i < pdata->num_leds; i++) {
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 2db0423..fb5a347 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -684,7 +684,7 @@ static int bd2802_probe(struct i2c_client *client,
 	}
 
 	led->client = client;
-	pdata = led->pdata = client->dev.platform_data;
+	pdata = led->pdata = dev_get_platdata(&client->dev);
 	i2c_set_clientdata(client, led);
 
 	/* Configure RESET GPIO (L: RESET, H: RESET cancel) */
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index 6a8405d..d93e245 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -40,7 +40,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
  * detected as working, but in reality it is not) as low as
  * possible.
  */
-static struct dmi_system_id __initdata clevo_mail_led_dmi_table[] = {
+static struct dmi_system_id clevo_mail_led_dmi_table[] __initdata = {
 	{
 		.callback = clevo_mail_led_dmi_callback,
 		.ident = "Clevo D410J",
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index c263a21..2a4b87f 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -93,7 +93,7 @@ static void da903x_led_set(struct led_classdev *led_cdev,
 
 static int da903x_led_probe(struct platform_device *pdev)
 {
-	struct led_info *pdata = pdev->dev.platform_data;
+	struct led_info *pdata = dev_get_platdata(&pdev->dev);
 	struct da903x_led *led;
 	int id, ret;
 
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index efec433..865d4fa 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -112,7 +112,7 @@ static int da9052_led_probe(struct platform_device *pdev)
 	int i;
 
 	da9052 = dev_get_drvdata(pdev->dev.parent);
-	pdata = da9052->dev->platform_data;
+	pdata = dev_get_platdata(da9052->dev);
 	if (pdata == NULL) {
 		dev_err(&pdev->dev, "No platform data\n");
 		goto err;
@@ -185,7 +185,7 @@ static int da9052_led_remove(struct platform_device *pdev)
 	int i;
 
 	da9052 = dev_get_drvdata(pdev->dev.parent);
-	pdata = da9052->dev->platform_data;
+	pdata = dev_get_platdata(da9052->dev);
 	pled = pdata->pled;
 
 	for (i = 0; i < pled->num_leds; i++) {
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 84d74c37..e8b01e5 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -233,7 +233,7 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 
 static int gpio_led_probe(struct platform_device *pdev)
 {
-	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct gpio_leds_priv *priv;
 	int i, ret = 0;
 
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index a036a19..652368c 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -403,7 +403,7 @@ static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
 static int lm3530_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
-	struct lm3530_platform_data *pdata = client->dev.platform_data;
+	struct lm3530_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct lm3530_data *drvdata;
 	int err = 0;
 
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index bbf24d0..027ede7 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -671,7 +671,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
 	if (!lm3533)
 		return -EINVAL;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data\n");
 		return -EINVAL;
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index d81a8e7..591eb5e 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -423,7 +423,7 @@ static const struct regmap_config lm355x_regmap = {
 static int lm355x_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
-	struct lm355x_platform_data *pdata = client->dev.platform_data;
+	struct lm355x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct lm355x_chip_data *chip;
 
 	int err;
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index f361bbe..ceb6b3c 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -316,7 +316,7 @@ static const struct regmap_config lm3642_regmap = {
 static int lm3642_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
-	struct lm3642_platform_data *pdata = client->dev.platform_data;
+	struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct lm3642_chip_data *chip;
 
 	int err;
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 0c4386e..8e1abdc 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -289,7 +289,7 @@ static void lp3944_led_set_brightness(struct led_classdev *led_cdev,
 	dev_dbg(&led->client->dev, "%s: %s, %d\n",
 		__func__, led_cdev->name, brightness);
 
-	led->status = brightness;
+	led->status = !!brightness;
 	schedule_work(&led->work);
 }
 
@@ -377,7 +377,8 @@ exit:
 static int lp3944_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
-	struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
+	struct lp3944_platform_data *lp3944_pdata =
+			dev_get_platdata(&client->dev);
 	struct lp3944_data *data;
 	int err;
 
@@ -413,7 +414,7 @@ static int lp3944_probe(struct i2c_client *client,
 
 static int lp3944_remove(struct i2c_client *client)
 {
-	struct lp3944_platform_data *pdata = client->dev.platform_data;
+	struct lp3944_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct lp3944_data *data = i2c_get_clientdata(client);
 	int i;
 
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 1392feb..9e28dd0 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -420,7 +420,7 @@ static int lp5521_probe(struct i2c_client *client,
 	struct lp55xx_platform_data *pdata;
 	struct device_node *np = client->dev.of_node;
 
-	if (!client->dev.platform_data) {
+	if (!dev_get_platdata(&client->dev)) {
 		if (np) {
 			ret = lp55xx_of_populate_pdata(&client->dev, np);
 			if (ret < 0)
@@ -430,7 +430,7 @@ static int lp5521_probe(struct i2c_client *client,
 			return -EINVAL;
 		}
 	}
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 3979428..72c10e2 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -432,7 +432,7 @@ static int lp5523_probe(struct i2c_client *client,
 	struct lp55xx_platform_data *pdata;
 	struct device_node *np = client->dev.of_node;
 
-	if (!client->dev.platform_data) {
+	if (!dev_get_platdata(&client->dev)) {
 		if (np) {
 			ret = lp55xx_of_populate_pdata(&client->dev, np);
 			if (ret < 0)
@@ -442,7 +442,7 @@ static int lp5523_probe(struct i2c_client *client,
 			return -EINVAL;
 		}
 	}
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index cbd856d..a2c7398 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -518,7 +518,7 @@ static int lp5562_probe(struct i2c_client *client,
 	struct lp55xx_platform_data *pdata;
 	struct device_node *np = client->dev.of_node;
 
-	if (!client->dev.platform_data) {
+	if (!dev_get_platdata(&client->dev)) {
 		if (np) {
 			ret = lp55xx_of_populate_pdata(&client->dev, np);
 			if (ret < 0)
@@ -528,7 +528,7 @@ static int lp5562_probe(struct i2c_client *client,
 			return -EINVAL;
 		}
 	}
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index c2fecd4..351825b 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -593,6 +593,9 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
 	of_property_read_string(np, "label", &pdata->label);
 	of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
 
+	/* LP8501 specific */
+	of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
+
 	dev->platform_data = pdata;
 
 	return 0;
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
new file mode 100644
index 0000000..8d55a780
--- /dev/null
+++ b/drivers/leds/leds-lp8501.c
@@ -0,0 +1,410 @@
+/*
+ * TI LP8501 9 channel LED Driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_data/leds-lp55xx.h>
+#include <linux/slab.h>
+
+#include "leds-lp55xx-common.h"
+
+#define LP8501_PROGRAM_LENGTH		32
+#define LP8501_MAX_LEDS			9
+
+/* Registers */
+#define LP8501_REG_ENABLE		0x00
+#define LP8501_ENABLE			BIT(6)
+#define LP8501_EXEC_M			0x3F
+#define LP8501_EXEC_ENG1_M		0x30
+#define LP8501_EXEC_ENG2_M		0x0C
+#define LP8501_EXEC_ENG3_M		0x03
+#define LP8501_RUN_ENG1			0x20
+#define LP8501_RUN_ENG2			0x08
+#define LP8501_RUN_ENG3			0x02
+
+#define LP8501_REG_OP_MODE		0x01
+#define LP8501_MODE_ENG1_M		0x30
+#define LP8501_MODE_ENG2_M		0x0C
+#define LP8501_MODE_ENG3_M		0x03
+#define LP8501_LOAD_ENG1		0x10
+#define LP8501_LOAD_ENG2		0x04
+#define LP8501_LOAD_ENG3		0x01
+
+#define LP8501_REG_PWR_CONFIG		0x05
+#define LP8501_PWR_CONFIG_M		0x03
+
+#define LP8501_REG_LED_PWM_BASE		0x16
+
+#define LP8501_REG_LED_CURRENT_BASE	0x26
+
+#define LP8501_REG_CONFIG		0x36
+#define LP8501_PWM_PSAVE		BIT(7)
+#define LP8501_AUTO_INC			BIT(6)
+#define LP8501_PWR_SAVE			BIT(5)
+#define LP8501_CP_AUTO			0x18
+#define LP8501_INT_CLK			BIT(0)
+#define LP8501_DEFAULT_CFG	\
+	(LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO)
+
+#define LP8501_REG_RESET		0x3D
+#define LP8501_RESET			0xFF
+
+#define LP8501_REG_PROG_PAGE_SEL	0x4F
+#define LP8501_PAGE_ENG1		0
+#define LP8501_PAGE_ENG2		1
+#define LP8501_PAGE_ENG3		2
+
+#define LP8501_REG_PROG_MEM		0x50
+
+#define LP8501_ENG1_IS_LOADING(mode)	\
+	((mode & LP8501_MODE_ENG1_M) == LP8501_LOAD_ENG1)
+#define LP8501_ENG2_IS_LOADING(mode)	\
+	((mode & LP8501_MODE_ENG2_M) == LP8501_LOAD_ENG2)
+#define LP8501_ENG3_IS_LOADING(mode)	\
+	((mode & LP8501_MODE_ENG3_M) == LP8501_LOAD_ENG3)
+
+static inline void lp8501_wait_opmode_done(void)
+{
+	usleep_range(1000, 2000);
+}
+
+static void lp8501_set_led_current(struct lp55xx_led *led, u8 led_current)
+{
+	led->led_current = led_current;
+	lp55xx_write(led->chip, LP8501_REG_LED_CURRENT_BASE + led->chan_nr,
+		led_current);
+}
+
+static int lp8501_post_init_device(struct lp55xx_chip *chip)
+{
+	int ret;
+	u8 val = LP8501_DEFAULT_CFG;
+
+	ret = lp55xx_write(chip, LP8501_REG_ENABLE, LP8501_ENABLE);
+	if (ret)
+		return ret;
+
+	/* Chip startup time is 500 us, 1 - 2 ms gives some margin */
+	usleep_range(1000, 2000);
+
+	if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT)
+		val |= LP8501_INT_CLK;
+
+	ret = lp55xx_write(chip, LP8501_REG_CONFIG, val);
+	if (ret)
+		return ret;
+
+	/* Power selection for each output */
+	return lp55xx_update_bits(chip, LP8501_REG_PWR_CONFIG,
+				LP8501_PWR_CONFIG_M, chip->pdata->pwr_sel);
+}
+
+static void lp8501_load_engine(struct lp55xx_chip *chip)
+{
+	enum lp55xx_engine_index idx = chip->engine_idx;
+	u8 mask[] = {
+		[LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M,
+		[LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M,
+		[LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M,
+	};
+
+	u8 val[] = {
+		[LP55XX_ENGINE_1] = LP8501_LOAD_ENG1,
+		[LP55XX_ENGINE_2] = LP8501_LOAD_ENG2,
+		[LP55XX_ENGINE_3] = LP8501_LOAD_ENG3,
+	};
+
+	u8 page_sel[] = {
+		[LP55XX_ENGINE_1] = LP8501_PAGE_ENG1,
+		[LP55XX_ENGINE_2] = LP8501_PAGE_ENG2,
+		[LP55XX_ENGINE_3] = LP8501_PAGE_ENG3,
+	};
+
+	lp55xx_update_bits(chip, LP8501_REG_OP_MODE, mask[idx], val[idx]);
+
+	lp8501_wait_opmode_done();
+
+	lp55xx_write(chip, LP8501_REG_PROG_PAGE_SEL, page_sel[idx]);
+}
+
+static void lp8501_stop_engine(struct lp55xx_chip *chip)
+{
+	lp55xx_write(chip, LP8501_REG_OP_MODE, 0);
+	lp8501_wait_opmode_done();
+}
+
+static void lp8501_turn_off_channels(struct lp55xx_chip *chip)
+{
+	int i;
+
+	for (i = 0; i < LP8501_MAX_LEDS; i++)
+		lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + i, 0);
+}
+
+static void lp8501_run_engine(struct lp55xx_chip *chip, bool start)
+{
+	int ret;
+	u8 mode;
+	u8 exec;
+
+	/* stop engine */
+	if (!start) {
+		lp8501_stop_engine(chip);
+		lp8501_turn_off_channels(chip);
+		return;
+	}
+
+	/*
+	 * To run the engine,
+	 * operation mode and enable register should updated at the same time
+	 */
+
+	ret = lp55xx_read(chip, LP8501_REG_OP_MODE, &mode);
+	if (ret)
+		return;
+
+	ret = lp55xx_read(chip, LP8501_REG_ENABLE, &exec);
+	if (ret)
+		return;
+
+	/* change operation mode to RUN only when each engine is loading */
+	if (LP8501_ENG1_IS_LOADING(mode)) {
+		mode = (mode & ~LP8501_MODE_ENG1_M) | LP8501_RUN_ENG1;
+		exec = (exec & ~LP8501_EXEC_ENG1_M) | LP8501_RUN_ENG1;
+	}
+
+	if (LP8501_ENG2_IS_LOADING(mode)) {
+		mode = (mode & ~LP8501_MODE_ENG2_M) | LP8501_RUN_ENG2;
+		exec = (exec & ~LP8501_EXEC_ENG2_M) | LP8501_RUN_ENG2;
+	}
+
+	if (LP8501_ENG3_IS_LOADING(mode)) {
+		mode = (mode & ~LP8501_MODE_ENG3_M) | LP8501_RUN_ENG3;
+		exec = (exec & ~LP8501_EXEC_ENG3_M) | LP8501_RUN_ENG3;
+	}
+
+	lp55xx_write(chip, LP8501_REG_OP_MODE, mode);
+	lp8501_wait_opmode_done();
+
+	lp55xx_update_bits(chip, LP8501_REG_ENABLE, LP8501_EXEC_M, exec);
+}
+
+static int lp8501_update_program_memory(struct lp55xx_chip *chip,
+					const u8 *data, size_t size)
+{
+	u8 pattern[LP8501_PROGRAM_LENGTH] = {0};
+	unsigned cmd;
+	char c[3];
+	int update_size;
+	int nrchars;
+	int offset = 0;
+	int ret;
+	int i;
+
+	/* clear program memory before updating */
+	for (i = 0; i < LP8501_PROGRAM_LENGTH; i++)
+		lp55xx_write(chip, LP8501_REG_PROG_MEM + i, 0);
+
+	i = 0;
+	while ((offset < size - 1) && (i < LP8501_PROGRAM_LENGTH)) {
+		/* separate sscanfs because length is working only for %s */
+		ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
+		if (ret != 1)
+			goto err;
+
+		ret = sscanf(c, "%2x", &cmd);
+		if (ret != 1)
+			goto err;
+
+		pattern[i] = (u8)cmd;
+		offset += nrchars;
+		i++;
+	}
+
+	/* Each instruction is 16bit long. Check that length is even */
+	if (i % 2)
+		goto err;
+
+	update_size = i;
+	for (i = 0; i < update_size; i++)
+		lp55xx_write(chip, LP8501_REG_PROG_MEM + i, pattern[i]);
+
+	return 0;
+
+err:
+	dev_err(&chip->cl->dev, "wrong pattern format\n");
+	return -EINVAL;
+}
+
+static void lp8501_firmware_loaded(struct lp55xx_chip *chip)
+{
+	const struct firmware *fw = chip->fw;
+
+	if (fw->size > LP8501_PROGRAM_LENGTH) {
+		dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n",
+			fw->size);
+		return;
+	}
+
+	/*
+	 * Program momery sequence
+	 *  1) set engine mode to "LOAD"
+	 *  2) write firmware data into program memory
+	 */
+
+	lp8501_load_engine(chip);
+	lp8501_update_program_memory(chip, fw->data, fw->size);
+}
+
+static void lp8501_led_brightness_work(struct work_struct *work)
+{
+	struct lp55xx_led *led = container_of(work, struct lp55xx_led,
+					      brightness_work);
+	struct lp55xx_chip *chip = led->chip;
+
+	mutex_lock(&chip->lock);
+	lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr,
+		     led->brightness);
+	mutex_unlock(&chip->lock);
+}
+
+/* Chip specific configurations */
+static struct lp55xx_device_config lp8501_cfg = {
+	.reset = {
+		.addr = LP8501_REG_RESET,
+		.val  = LP8501_RESET,
+	},
+	.enable = {
+		.addr = LP8501_REG_ENABLE,
+		.val  = LP8501_ENABLE,
+	},
+	.max_channel  = LP8501_MAX_LEDS,
+	.post_init_device   = lp8501_post_init_device,
+	.brightness_work_fn = lp8501_led_brightness_work,
+	.set_led_current    = lp8501_set_led_current,
+	.firmware_cb        = lp8501_firmware_loaded,
+	.run_engine         = lp8501_run_engine,
+};
+
+static int lp8501_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct lp55xx_chip *chip;
+	struct lp55xx_led *led;
+	struct lp55xx_platform_data *pdata;
+	struct device_node *np = client->dev.of_node;
+
+	if (!dev_get_platdata(&client->dev)) {
+		if (np) {
+			ret = lp55xx_of_populate_pdata(&client->dev, np);
+			if (ret < 0)
+				return ret;
+		} else {
+			dev_err(&client->dev, "no platform data\n");
+			return -EINVAL;
+		}
+	}
+	pdata = dev_get_platdata(&client->dev);
+
+	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	led = devm_kzalloc(&client->dev,
+			sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	chip->cl = client;
+	chip->pdata = pdata;
+	chip->cfg = &lp8501_cfg;
+
+	mutex_init(&chip->lock);
+
+	i2c_set_clientdata(client, led);
+
+	ret = lp55xx_init_device(chip);
+	if (ret)
+		goto err_init;
+
+	dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
+
+	ret = lp55xx_register_leds(led, chip);
+	if (ret)
+		goto err_register_leds;
+
+	ret = lp55xx_register_sysfs(chip);
+	if (ret) {
+		dev_err(&client->dev, "registering sysfs failed\n");
+		goto err_register_sysfs;
+	}
+
+	return 0;
+
+err_register_sysfs:
+	lp55xx_unregister_leds(led, chip);
+err_register_leds:
+	lp55xx_deinit_device(chip);
+err_init:
+	return ret;
+}
+
+static int lp8501_remove(struct i2c_client *client)
+{
+	struct lp55xx_led *led = i2c_get_clientdata(client);
+	struct lp55xx_chip *chip = led->chip;
+
+	lp8501_stop_engine(chip);
+	lp55xx_unregister_sysfs(chip);
+	lp55xx_unregister_leds(led, chip);
+	lp55xx_deinit_device(chip);
+
+	return 0;
+}
+
+static const struct i2c_device_id lp8501_id[] = {
+	{ "lp8501",  0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lp8501_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_lp8501_leds_match[] = {
+	{ .compatible = "ti,lp8501", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, of_lp8501_leds_match);
+#endif
+
+static struct i2c_driver lp8501_driver = {
+	.driver = {
+		.name	= "lp8501",
+		.of_match_table = of_match_ptr(of_lp8501_leds_match),
+	},
+	.probe		= lp8501_probe,
+	.remove		= lp8501_remove,
+	.id_table	= lp8501_id,
+};
+
+module_i2c_driver(lp8501_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LP8501 LED drvier");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index ca48a7d5..3417e5b 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -135,7 +135,7 @@ static void delete_lt3593_led(struct lt3593_led_data *led)
 
 static int lt3593_led_probe(struct platform_device *pdev)
 {
-	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct lt3593_led_data *leds_data;
 	int i, ret = 0;
 
@@ -169,7 +169,7 @@ err:
 static int lt3593_led_remove(struct platform_device *pdev)
 {
 	int i;
-	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct lt3593_led_data *leds_data;
 
 	leds_data = platform_get_drvdata(pdev);
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index c61c5eb..2f9f141 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -306,7 +306,7 @@ create_netxbig_led(struct platform_device *pdev,
 		   struct netxbig_led_data *led_dat,
 		   const struct netxbig_led *template)
 {
-	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+	struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int ret;
 
 	spin_lock_init(&led_dat->lock);
@@ -354,7 +354,7 @@ create_netxbig_led(struct platform_device *pdev,
 
 static int netxbig_led_probe(struct platform_device *pdev)
 {
-	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+	struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct netxbig_led_data *leds_data;
 	int i;
 	int ret;
@@ -391,7 +391,7 @@ err_free_leds:
 
 static int netxbig_led_remove(struct platform_device *pdev)
 {
-	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+	struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct netxbig_led_data *leds_data;
 	int i;
 
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index e7df987..141f134 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -321,7 +321,7 @@ static inline int sizeof_ns2_led_priv(int num_leds)
 
 static int ns2_led_probe(struct platform_device *pdev)
 {
-	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
+	struct ns2_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct ns2_led_priv *priv;
 	int i;
 	int ret;
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 0c597bd..4a0e786 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -446,7 +446,8 @@ static int pca9532_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
 	struct pca9532_data *data = i2c_get_clientdata(client);
-	struct pca9532_platform_data *pca9532_pdata = client->dev.platform_data;
+	struct pca9532_platform_data *pca9532_pdata =
+			dev_get_platdata(&client->dev);
 
 	if (!pca9532_pdata)
 		return -EIO;
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index edf485b..c3a08b6 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -267,7 +267,7 @@ static int pca955x_probe(struct i2c_client *client,
 
 	chip = &pca955x_chipdefs[id->driver_data];
 	adapter = to_i2c_adapter(client->dev.parent);
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	/* Make sure the slave address / chip type combo given is possible */
 	if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) !=
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
index 9aae567..ecd1449 100644
--- a/drivers/leds/leds-pca9633.c
+++ b/drivers/leds/leds-pca9633.c
@@ -11,6 +11,15 @@
  *
  * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
  *
+ * Note that hardware blinking violates the leds infrastructure driver
+ * interface since the hardware only supports blinking all LEDs with the
+ * same delay_on/delay_off rates.  That is, only the LEDs that are set to
+ * blink will actually blink but all LEDs that are set to blink will blink
+ * in identical fashion.  The delay_on/delay_off values of the last LED
+ * that is set to blink will be used for all of the blinking LEDs.
+ * Hardware blinking is disabled by default but can be enabled by setting
+ * the 'blink_type' member in the platform_data struct to 'PCA9633_HW_BLINK'
+ * or by adding the 'nxp,hw-blink' property to the DTS.
  */
 
 #include <linux/module.h>
@@ -22,6 +31,7 @@
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/platform_data/leds-pca9633.h>
 
 /* LED select registers determine the source that drives LED outputs */
@@ -30,30 +40,44 @@
 #define PCA9633_LED_PWM		0x2	/* Controlled through PWM */
 #define PCA9633_LED_GRP_PWM	0x3	/* Controlled through PWM/GRPPWM */
 
+#define PCA9633_MODE2_DMBLNK	0x20	/* Enable blinking */
+
 #define PCA9633_MODE1		0x00
 #define PCA9633_MODE2		0x01
 #define PCA9633_PWM_BASE	0x02
+#define PCA9633_GRPPWM		0x06
+#define PCA9633_GRPFREQ		0x07
 #define PCA9633_LEDOUT		0x08
 
+/* Total blink period in milliseconds */
+#define PCA9632_BLINK_PERIOD_MIN	42
+#define PCA9632_BLINK_PERIOD_MAX	10667
+
 static const struct i2c_device_id pca9633_id[] = {
 	{ "pca9633", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pca9633_id);
 
+enum pca9633_cmd {
+	BRIGHTNESS_SET,
+	BLINK_SET,
+};
+
 struct pca9633_led {
 	struct i2c_client *client;
 	struct work_struct work;
 	enum led_brightness brightness;
 	struct led_classdev led_cdev;
 	int led_num; /* 0 .. 3 potentially */
+	enum pca9633_cmd cmd;
 	char name[32];
+	u8 gdc;
+	u8 gfrq;
 };
 
-static void pca9633_led_work(struct work_struct *work)
+static void pca9633_brightness_work(struct pca9633_led *pca9633)
 {
-	struct pca9633_led *pca9633 = container_of(work,
-		struct pca9633_led, work);
 	u8 ledout = i2c_smbus_read_byte_data(pca9633->client, PCA9633_LEDOUT);
 	int shift = 2 * pca9633->led_num;
 	u8 mask = 0x3 << shift;
@@ -77,6 +101,43 @@ static void pca9633_led_work(struct work_struct *work)
 	}
 }
 
+static void pca9633_blink_work(struct pca9633_led *pca9633)
+{
+	u8 ledout = i2c_smbus_read_byte_data(pca9633->client, PCA9633_LEDOUT);
+	u8 mode2 = i2c_smbus_read_byte_data(pca9633->client, PCA9633_MODE2);
+	int shift = 2 * pca9633->led_num;
+	u8 mask = 0x3 << shift;
+
+	i2c_smbus_write_byte_data(pca9633->client, PCA9633_GRPPWM,
+		pca9633->gdc);
+
+	i2c_smbus_write_byte_data(pca9633->client, PCA9633_GRPFREQ,
+		pca9633->gfrq);
+
+	if (!(mode2 & PCA9633_MODE2_DMBLNK))
+		i2c_smbus_write_byte_data(pca9633->client, PCA9633_MODE2,
+			mode2 | PCA9633_MODE2_DMBLNK);
+
+	if ((ledout & mask) != (PCA9633_LED_GRP_PWM << shift))
+		i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT,
+			(ledout & ~mask) | (PCA9633_LED_GRP_PWM << shift));
+}
+
+static void pca9633_work(struct work_struct *work)
+{
+	struct pca9633_led *pca9633 = container_of(work,
+		struct pca9633_led, work);
+
+	switch (pca9633->cmd) {
+	case BRIGHTNESS_SET:
+		pca9633_brightness_work(pca9633);
+		break;
+	case BLINK_SET:
+		pca9633_blink_work(pca9633);
+		break;
+	}
+}
+
 static void pca9633_led_set(struct led_classdev *led_cdev,
 	enum led_brightness value)
 {
@@ -84,6 +145,7 @@ static void pca9633_led_set(struct led_classdev *led_cdev,
 
 	pca9633 = container_of(led_cdev, struct pca9633_led, led_cdev);
 
+	pca9633->cmd = BRIGHTNESS_SET;
 	pca9633->brightness = value;
 
 	/*
@@ -93,6 +155,131 @@ static void pca9633_led_set(struct led_classdev *led_cdev,
 	schedule_work(&pca9633->work);
 }
 
+static int pca9633_blink_set(struct led_classdev *led_cdev,
+		unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct pca9633_led *pca9633;
+	unsigned long time_on, time_off, period;
+	u8 gdc, gfrq;
+
+	pca9633 = container_of(led_cdev, struct pca9633_led, led_cdev);
+
+	time_on = *delay_on;
+	time_off = *delay_off;
+
+	/* If both zero, pick reasonable defaults of 500ms each */
+	if (!time_on && !time_off) {
+		time_on = 500;
+		time_off = 500;
+	}
+
+	period = time_on + time_off;
+
+	/* If period not supported by hardware, default to someting sane. */
+	if ((period < PCA9632_BLINK_PERIOD_MIN) ||
+	    (period > PCA9632_BLINK_PERIOD_MAX)) {
+		time_on = 500;
+		time_off = 500;
+		period = time_on + time_off;
+	}
+
+	/*
+	 * From manual: duty cycle = (GDC / 256) ->
+	 *	(time_on / period) = (GDC / 256) ->
+	 *		GDC = ((time_on * 256) / period)
+	 */
+	gdc = (time_on * 256) / period;
+
+	/*
+	 * From manual: period = ((GFRQ + 1) / 24) in seconds.
+	 * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) ->
+	 *		GFRQ = ((period * 24 / 1000) - 1)
+	 */
+	gfrq = (period * 24 / 1000) - 1;
+
+	pca9633->cmd = BLINK_SET;
+	pca9633->gdc = gdc;
+	pca9633->gfrq = gfrq;
+
+	/*
+	 * Must use workqueue for the actual I/O since I2C operations
+	 * can sleep.
+	 */
+	schedule_work(&pca9633->work);
+
+	*delay_on = time_on;
+	*delay_off = time_off;
+
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_OF)
+static struct pca9633_platform_data *
+pca9633_dt_init(struct i2c_client *client)
+{
+	struct device_node *np = client->dev.of_node, *child;
+	struct pca9633_platform_data *pdata;
+	struct led_info *pca9633_leds;
+	int count;
+
+	count = of_get_child_count(np);
+	if (!count || count > 4)
+		return ERR_PTR(-ENODEV);
+
+	pca9633_leds = devm_kzalloc(&client->dev,
+				sizeof(struct led_info) * count, GFP_KERNEL);
+	if (!pca9633_leds)
+		return ERR_PTR(-ENOMEM);
+
+	for_each_child_of_node(np, child) {
+		struct led_info led;
+		u32 reg;
+		int res;
+
+		led.name =
+			of_get_property(child, "label", NULL) ? : child->name;
+		led.default_trigger =
+			of_get_property(child, "linux,default-trigger", NULL);
+		res = of_property_read_u32(child, "reg", &reg);
+		if (res != 0)
+			continue;
+		pca9633_leds[reg] = led;
+	}
+	pdata = devm_kzalloc(&client->dev,
+			     sizeof(struct pca9633_platform_data), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->leds.leds = pca9633_leds;
+	pdata->leds.num_leds = count;
+
+	/* default to open-drain unless totem pole (push-pull) is specified */
+	if (of_property_read_bool(np, "nxp,totem-pole"))
+		pdata->outdrv = PCA9633_TOTEM_POLE;
+	else
+		pdata->outdrv = PCA9633_OPEN_DRAIN;
+
+	/* default to software blinking unless hardware blinking is specified */
+	if (of_property_read_bool(np, "nxp,hw-blink"))
+		pdata->blink_type = PCA9633_HW_BLINK;
+	else
+		pdata->blink_type = PCA9633_SW_BLINK;
+
+	return pdata;
+}
+
+static const struct of_device_id of_pca9633_match[] = {
+	{ .compatible = "nxp,pca963x", },
+	{},
+};
+#else
+static struct pca9633_platform_data *
+pca9633_dt_init(struct i2c_client *client)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
+
 static int pca9633_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
@@ -100,7 +287,15 @@ static int pca9633_probe(struct i2c_client *client,
 	struct pca9633_platform_data *pdata;
 	int i, err;
 
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
+
+	if (!pdata) {
+		pdata = pca9633_dt_init(client);
+		if (IS_ERR(pdata)) {
+			dev_warn(&client->dev, "could not parse configuration\n");
+			pdata = NULL;
+		}
+	}
 
 	if (pdata) {
 		if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) {
@@ -136,7 +331,10 @@ static int pca9633_probe(struct i2c_client *client,
 		pca9633[i].led_cdev.name = pca9633[i].name;
 		pca9633[i].led_cdev.brightness_set = pca9633_led_set;
 
-		INIT_WORK(&pca9633[i].work, pca9633_led_work);
+		if (pdata && pdata->blink_type == PCA9633_HW_BLINK)
+			pca9633[i].led_cdev.blink_set = pca9633_blink_set;
+
+		INIT_WORK(&pca9633[i].work, pca9633_work);
 
 		err = led_classdev_register(&client->dev, &pca9633[i].led_cdev);
 		if (err < 0)
@@ -181,6 +379,7 @@ static struct i2c_driver pca9633_driver = {
 	.driver = {
 		.name	= "leds-pca9633",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(of_pca9633_match),
 	},
 	.probe	= pca9633_probe,
 	.remove	= pca9633_remove,
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index faf52c0..bb6f948 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -147,7 +147,7 @@ err:
 
 static int led_pwm_probe(struct platform_device *pdev)
 {
-	struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
+	struct led_pwm_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct led_pwm_priv *priv;
 	int i, ret = 0;
 
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index 4253a9b..358430d 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -142,7 +142,8 @@ static void regulator_led_brightness_set(struct led_classdev *led_cdev,
 
 static int regulator_led_probe(struct platform_device *pdev)
 {
-	struct led_regulator_platform_data *pdata = pdev->dev.platform_data;
+	struct led_regulator_platform_data *pdata =
+			dev_get_platdata(&pdev->dev);
 	struct regulator_led *led;
 	struct regulator *vcc;
 	int ret = 0;
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
deleted file mode 100644
index adebf49..0000000
--- a/drivers/leds/leds-renesas-tpu.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * LED control using Renesas TPU
- *
- *  Copyright (C) 2011 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/printk.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/leds.h>
-#include <linux/platform_data/leds-renesas-tpu.h>
-#include <linux/gpio.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/workqueue.h>
-
-enum r_tpu_pin { R_TPU_PIN_UNUSED, R_TPU_PIN_GPIO, R_TPU_PIN_GPIO_FN };
-enum r_tpu_timer { R_TPU_TIMER_UNUSED, R_TPU_TIMER_ON };
-
-struct r_tpu_priv {
-	struct led_classdev ldev;
-	void __iomem *mapbase;
-	struct clk *clk;
-	struct platform_device *pdev;
-	enum r_tpu_pin pin_state;
-	enum r_tpu_timer timer_state;
-	unsigned long min_rate;
-	unsigned int refresh_rate;
-	struct work_struct work;
-	enum led_brightness new_brightness;
-};
-
-static DEFINE_SPINLOCK(r_tpu_lock);
-
-#define TSTR -1 /* Timer start register (shared register) */
-#define TCR  0 /* Timer control register (+0x00) */
-#define TMDR 1 /* Timer mode register (+0x04) */
-#define TIOR 2 /* Timer I/O control register (+0x08) */
-#define TIER 3 /* Timer interrupt enable register (+0x0c) */
-#define TSR  4 /* Timer status register (+0x10) */
-#define TCNT 5 /* Timer counter (+0x14) */
-#define TGRA 6 /* Timer general register A (+0x18) */
-#define TGRB 7 /* Timer general register B (+0x1c) */
-#define TGRC 8 /* Timer general register C (+0x20) */
-#define TGRD 9 /* Timer general register D (+0x24) */
-
-static inline u16 r_tpu_read(struct r_tpu_priv *p, int reg_nr)
-{
-	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
-	unsigned long offs = reg_nr << 2;
-
-	if (reg_nr == TSTR)
-		return ioread16(base - cfg->channel_offset);
-
-	return ioread16(base + offs);
-}
-
-static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr, u16 value)
-{
-	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
-	unsigned long offs = reg_nr << 2;
-
-	if (reg_nr == TSTR) {
-		iowrite16(value, base - cfg->channel_offset);
-		return;
-	}
-
-	iowrite16(value, base + offs);
-}
-
-static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
-{
-	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
-	unsigned long flags;
-	u16 value;
-
-	/* start stop register shared by multiple timer channels */
-	spin_lock_irqsave(&r_tpu_lock, flags);
-	value = r_tpu_read(p, TSTR);
-
-	if (start)
-		value |= 1 << cfg->timer_bit;
-	else
-		value &= ~(1 << cfg->timer_bit);
-
-	r_tpu_write(p, TSTR, value);
-	spin_unlock_irqrestore(&r_tpu_lock, flags);
-}
-
-static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
-{
-	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
-	int prescaler[] = { 1, 4, 16, 64 };
-	int k, ret;
-	unsigned long rate, tmp;
-
-	if (p->timer_state == R_TPU_TIMER_ON)
-		return 0;
-
-	/* wake up device and enable clock */
-	pm_runtime_get_sync(&p->pdev->dev);
-	ret = clk_enable(p->clk);
-	if (ret) {
-		dev_err(&p->pdev->dev, "cannot enable clock\n");
-		return ret;
-	}
-
-	/* make sure channel is disabled */
-	r_tpu_start_stop_ch(p, 0);
-
-	/* get clock rate after enabling it */
-	rate = clk_get_rate(p->clk);
-
-	/* pick the lowest acceptable rate */
-	for (k = ARRAY_SIZE(prescaler) - 1; k >= 0; k--)
-		if ((rate / prescaler[k]) >= p->min_rate)
-			break;
-
-	if (k < 0) {
-		dev_err(&p->pdev->dev, "clock rate mismatch\n");
-		goto err0;
-	}
-	dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
-		rate, prescaler[k]);
-
-	/* clear TCNT on TGRB match, count on rising edge, set prescaler */
-	r_tpu_write(p, TCR, 0x0040 | k);
-
-	/* output 0 until TGRA, output 1 until TGRB */
-	r_tpu_write(p, TIOR, 0x0002);
-
-	rate /= prescaler[k] * p->refresh_rate;
-	r_tpu_write(p, TGRB, rate);
-	dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);
-
-	tmp = (cfg->max_brightness - brightness) * rate;
-	r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
-	dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);
-
-	/* PWM mode */
-	r_tpu_write(p, TMDR, 0x0002);
-
-	/* enable channel */
-	r_tpu_start_stop_ch(p, 1);
-
-	p->timer_state = R_TPU_TIMER_ON;
-	return 0;
- err0:
-	clk_disable(p->clk);
-	pm_runtime_put_sync(&p->pdev->dev);
-	return -ENOTSUPP;
-}
-
-static void r_tpu_disable(struct r_tpu_priv *p)
-{
-	if (p->timer_state == R_TPU_TIMER_UNUSED)
-		return;
-
-	/* disable channel */
-	r_tpu_start_stop_ch(p, 0);
-
-	/* stop clock and mark device as idle */
-	clk_disable(p->clk);
-	pm_runtime_put_sync(&p->pdev->dev);
-
-	p->timer_state = R_TPU_TIMER_UNUSED;
-}
-
-static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
-			  enum led_brightness brightness)
-{
-	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
-
-	if (p->pin_state == new_state) {
-		if (p->pin_state == R_TPU_PIN_GPIO)
-			gpio_set_value(cfg->pin_gpio, brightness);
-		return;
-	}
-
-	if (p->pin_state == R_TPU_PIN_GPIO)
-		gpio_free(cfg->pin_gpio);
-
-	if (p->pin_state == R_TPU_PIN_GPIO_FN)
-		gpio_free(cfg->pin_gpio_fn);
-
-	if (new_state == R_TPU_PIN_GPIO)
-		gpio_request_one(cfg->pin_gpio, !!brightness ?
-				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
-				cfg->name);
-
-	if (new_state == R_TPU_PIN_GPIO_FN)
-		gpio_request(cfg->pin_gpio_fn, cfg->name);
-
-	p->pin_state = new_state;
-}
-
-static void r_tpu_work(struct work_struct *work)
-{
-	struct r_tpu_priv *p = container_of(work, struct r_tpu_priv, work);
-	enum led_brightness brightness = p->new_brightness;
-
-	r_tpu_disable(p);
-
-	/* off and maximum are handled as GPIO pins, in between PWM */
-	if ((brightness == 0) || (brightness == p->ldev.max_brightness))
-		r_tpu_set_pin(p, R_TPU_PIN_GPIO, brightness);
-	else {
-		r_tpu_set_pin(p, R_TPU_PIN_GPIO_FN, 0);
-		r_tpu_enable(p, brightness);
-	}
-}
-
-static void r_tpu_set_brightness(struct led_classdev *ldev,
-				 enum led_brightness brightness)
-{
-	struct r_tpu_priv *p = container_of(ldev, struct r_tpu_priv, ldev);
-	p->new_brightness = brightness;
-	schedule_work(&p->work);
-}
-
-static int r_tpu_probe(struct platform_device *pdev)
-{
-	struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
-	struct r_tpu_priv *p;
-	struct resource *res;
-	int ret;
-
-	if (!cfg) {
-		dev_err(&pdev->dev, "missing platform data\n");
-		return -ENODEV;
-	}
-
-	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
-	if (p == NULL) {
-		dev_err(&pdev->dev, "failed to allocate driver data\n");
-		return -ENOMEM;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get I/O memory\n");
-		return -ENXIO;
-	}
-
-	/* map memory, let mapbase point to our channel */
-	p->mapbase = devm_ioremap_nocache(&pdev->dev, res->start,
-					resource_size(res));
-	if (p->mapbase == NULL) {
-		dev_err(&pdev->dev, "failed to remap I/O memory\n");
-		return -ENXIO;
-	}
-
-	/* get hold of clock */
-	p->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(p->clk)) {
-		dev_err(&pdev->dev, "cannot get clock\n");
-		return PTR_ERR(p->clk);
-	}
-
-	p->pdev = pdev;
-	p->pin_state = R_TPU_PIN_UNUSED;
-	p->timer_state = R_TPU_TIMER_UNUSED;
-	p->refresh_rate = cfg->refresh_rate ? cfg->refresh_rate : 100;
-	r_tpu_set_pin(p, R_TPU_PIN_GPIO, LED_OFF);
-	platform_set_drvdata(pdev, p);
-
-	INIT_WORK(&p->work, r_tpu_work);
-
-	p->ldev.name = cfg->name;
-	p->ldev.brightness = LED_OFF;
-	p->ldev.max_brightness = cfg->max_brightness;
-	p->ldev.brightness_set = r_tpu_set_brightness;
-	p->ldev.flags |= LED_CORE_SUSPENDRESUME;
-	ret = led_classdev_register(&pdev->dev, &p->ldev);
-	if (ret < 0)
-		goto err0;
-
-	/* max_brightness may be updated by the LED core code */
-	p->min_rate = p->ldev.max_brightness * p->refresh_rate;
-
-	pm_runtime_enable(&pdev->dev);
-	return 0;
-
- err0:
-	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
-	return ret;
-}
-
-static int r_tpu_remove(struct platform_device *pdev)
-{
-	struct r_tpu_priv *p = platform_get_drvdata(pdev);
-
-	r_tpu_set_brightness(&p->ldev, LED_OFF);
-	led_classdev_unregister(&p->ldev);
-	cancel_work_sync(&p->work);
-	r_tpu_disable(p);
-	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
-
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
-static struct platform_driver r_tpu_device_driver = {
-	.probe		= r_tpu_probe,
-	.remove		= r_tpu_remove,
-	.driver		= {
-		.name	= "leds-renesas-tpu",
-	}
-};
-
-module_platform_driver(r_tpu_device_driver);
-
-MODULE_AUTHOR("Magnus Damm");
-MODULE_DESCRIPTION("Renesas TPU LED Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index e1a0df6..76483fb 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -71,7 +71,7 @@ static int s3c24xx_led_remove(struct platform_device *dev)
 
 static int s3c24xx_led_probe(struct platform_device *dev)
 {
-	struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
+	struct s3c24xx_led_platdata *pdata = dev_get_platdata(&dev->dev);
 	struct s3c24xx_gpio_led *led;
 	int ret;
 
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 64e204e..5b8f938 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -91,7 +91,7 @@ MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection");
  * detected as working, but in reality it is not) as low as
  * possible.
  */
-static struct dmi_system_id __initdata nas_led_whitelist[] = {
+static struct dmi_system_id nas_led_whitelist[] __initdata = {
 	{
 		.callback = ss4200_led_dmi_callback,
 		.ident = "Intel SS4200-E",
@@ -197,7 +197,7 @@ static void nasgpio_led_set_attr(struct led_classdev *led_cdev,
 	spin_unlock(&nasgpio_gpio_lock);
 }
 
-u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port)
+static u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port)
 {
 	struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
 	u32 gpio_in;
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index 98fe021..8cc304f 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -737,7 +737,7 @@ static int tca6507_probe(struct i2c_client *client,
 	int i = 0;
 
 	adapter = to_i2c_adapter(client->dev.parent);
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
 		return -EIO;
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index 120815a..c32dad4 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -246,8 +246,8 @@ static int wm831x_status_probe(struct platform_device *pdev)
 	drvdata->wm831x = wm831x;
 	drvdata->reg = res->start;
 
-	if (wm831x->dev->platform_data)
-		chip_pdata = wm831x->dev->platform_data;
+	if (dev_get_platdata(wm831x->dev))
+		chip_pdata = dev_get_platdata(wm831x->dev);
 	else
 		chip_pdata = NULL;
 
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 8a181d5..3f75fd2 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -203,7 +203,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
 {
 	struct regulator *isink, *dcdc;
 	struct wm8350_led *led;
-	struct wm8350_led_platform_data *pdata = pdev->dev.platform_data;
+	struct wm8350_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int i;
 
 	if (pdata == NULL) {
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index ee37288..f9764e6 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -597,24 +597,19 @@ static int mca_reap(struct btree *b, struct closure *cl, unsigned min_order)
 	return 0;
 }
 
-static int bch_mca_shrink(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long bch_mca_scan(struct shrinker *shrink,
+				  struct shrink_control *sc)
 {
 	struct cache_set *c = container_of(shrink, struct cache_set, shrink);
 	struct btree *b, *t;
 	unsigned long i, nr = sc->nr_to_scan;
+	unsigned long freed = 0;
 
 	if (c->shrinker_disabled)
-		return 0;
+		return SHRINK_STOP;
 
 	if (c->try_harder)
-		return 0;
-
-	/*
-	 * If nr == 0, we're supposed to return the number of items we have
-	 * cached. Not allowed to return -1.
-	 */
-	if (!nr)
-		return mca_can_free(c) * c->btree_pages;
+		return SHRINK_STOP;
 
 	/* Return -1 if we can't do anything right now */
 	if (sc->gfp_mask & __GFP_WAIT)
@@ -634,14 +629,14 @@ static int bch_mca_shrink(struct shrinker *shrink, struct shrink_control *sc)
 
 	i = 0;
 	list_for_each_entry_safe(b, t, &c->btree_cache_freeable, list) {
-		if (!nr)
+		if (freed >= nr)
 			break;
 
 		if (++i > 3 &&
 		    !mca_reap(b, NULL, 0)) {
 			mca_data_free(b);
 			rw_unlock(true, b);
-			--nr;
+			freed++;
 		}
 	}
 
@@ -652,7 +647,7 @@ static int bch_mca_shrink(struct shrinker *shrink, struct shrink_control *sc)
 	if (list_empty(&c->btree_cache))
 		goto out;
 
-	for (i = 0; nr && i < c->bucket_cache_used; i++) {
+	for (i = 0; (nr--) && i < c->bucket_cache_used; i++) {
 		b = list_first_entry(&c->btree_cache, struct btree, list);
 		list_rotate_left(&c->btree_cache);
 
@@ -661,14 +656,27 @@ static int bch_mca_shrink(struct shrinker *shrink, struct shrink_control *sc)
 			mca_bucket_free(b);
 			mca_data_free(b);
 			rw_unlock(true, b);
-			--nr;
+			freed++;
 		} else
 			b->accessed = 0;
 	}
 out:
-	nr = mca_can_free(c) * c->btree_pages;
 	mutex_unlock(&c->bucket_lock);
-	return nr;
+	return freed;
+}
+
+static unsigned long bch_mca_count(struct shrinker *shrink,
+				   struct shrink_control *sc)
+{
+	struct cache_set *c = container_of(shrink, struct cache_set, shrink);
+
+	if (c->shrinker_disabled)
+		return 0;
+
+	if (c->try_harder)
+		return 0;
+
+	return mca_can_free(c) * c->btree_pages;
 }
 
 void bch_btree_cache_free(struct cache_set *c)
@@ -737,7 +745,8 @@ int bch_btree_cache_alloc(struct cache_set *c)
 		c->verify_data = NULL;
 #endif
 
-	c->shrink.shrink = bch_mca_shrink;
+	c->shrink.count_objects = bch_mca_count;
+	c->shrink.scan_objects = bch_mca_scan;
 	c->shrink.seeks = 4;
 	c->shrink.batch = c->btree_pages * 2;
 	register_shrinker(&c->shrink);
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 12a2c28..4fe6ab2 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -556,7 +556,7 @@ STORE(__bch_cache_set)
 		struct shrink_control sc;
 		sc.gfp_mask = GFP_KERNEL;
 		sc.nr_to_scan = strtoul_or_return(buf);
-		c->shrink.shrink(&c->shrink, &sc);
+		c->shrink.scan_objects(&c->shrink, &sc);
 	}
 
 	sysfs_strtoul(congested_read_threshold_us,
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 5227e07..173cbb2 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1425,62 +1425,75 @@ static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp,
 				unsigned long max_jiffies)
 {
 	if (jiffies - b->last_accessed < max_jiffies)
-		return 1;
+		return 0;
 
 	if (!(gfp & __GFP_IO)) {
 		if (test_bit(B_READING, &b->state) ||
 		    test_bit(B_WRITING, &b->state) ||
 		    test_bit(B_DIRTY, &b->state))
-			return 1;
+			return 0;
 	}
 
 	if (b->hold_count)
-		return 1;
+		return 0;
 
 	__make_buffer_clean(b);
 	__unlink_buffer(b);
 	__free_buffer_wake(b);
 
-	return 0;
+	return 1;
 }
 
-static void __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
-		   struct shrink_control *sc)
+static long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
+		   gfp_t gfp_mask)
 {
 	int l;
 	struct dm_buffer *b, *tmp;
+	long freed = 0;
 
 	for (l = 0; l < LIST_SIZE; l++) {
-		list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list)
-			if (!__cleanup_old_buffer(b, sc->gfp_mask, 0) &&
-			    !--nr_to_scan)
-				return;
+		list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) {
+			freed += __cleanup_old_buffer(b, gfp_mask, 0);
+			if (!--nr_to_scan)
+				break;
+		}
 		dm_bufio_cond_resched();
 	}
+	return freed;
 }
 
-static int shrink(struct shrinker *shrinker, struct shrink_control *sc)
+static unsigned long
+dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
-	struct dm_bufio_client *c =
-	    container_of(shrinker, struct dm_bufio_client, shrinker);
-	unsigned long r;
-	unsigned long nr_to_scan = sc->nr_to_scan;
+	struct dm_bufio_client *c;
+	unsigned long freed;
 
+	c = container_of(shrink, struct dm_bufio_client, shrinker);
 	if (sc->gfp_mask & __GFP_IO)
 		dm_bufio_lock(c);
 	else if (!dm_bufio_trylock(c))
-		return !nr_to_scan ? 0 : -1;
+		return SHRINK_STOP;
 
-	if (nr_to_scan)
-		__scan(c, nr_to_scan, sc);
+	freed  = __scan(c, sc->nr_to_scan, sc->gfp_mask);
+	dm_bufio_unlock(c);
+	return freed;
+}
 
-	r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
-	if (r > INT_MAX)
-		r = INT_MAX;
+static unsigned long
+dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+	struct dm_bufio_client *c;
+	unsigned long count;
 
-	dm_bufio_unlock(c);
+	c = container_of(shrink, struct dm_bufio_client, shrinker);
+	if (sc->gfp_mask & __GFP_IO)
+		dm_bufio_lock(c);
+	else if (!dm_bufio_trylock(c))
+		return 0;
 
-	return r;
+	count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+	dm_bufio_unlock(c);
+	return count;
 }
 
 /*
@@ -1582,7 +1595,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
 	__cache_size_refresh();
 	mutex_unlock(&dm_bufio_clients_lock);
 
-	c->shrinker.shrink = shrink;
+	c->shrinker.count_objects = dm_bufio_shrink_count;
+	c->shrinker.scan_objects = dm_bufio_shrink_scan;
 	c->shrinker.seeks = 1;
 	c->shrinker.batch = 0;
 	register_shrinker(&c->shrinker);
@@ -1669,7 +1683,7 @@ static void cleanup_old_buffers(void)
 			struct dm_buffer *b;
 			b = list_entry(c->lru[LIST_CLEAN].prev,
 				       struct dm_buffer, lru_list);
-			if (__cleanup_old_buffer(b, 0, max_age * HZ))
+			if (!__cleanup_old_buffer(b, 0, max_age * HZ))
 				break;
 			dm_bufio_cond_resched();
 		}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9f13e13..b71d75e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -602,9 +602,9 @@ static struct mddev * mddev_find(dev_t unit)
 	goto retry;
 }
 
-static inline int mddev_lock(struct mddev * mddev)
+int md_queue_misc_work(struct work_struct *work)
 {
-	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+	return queue_work(md_misc_wq, work);
 }
 
 static inline int mddev_is_locked(struct mddev *mddev)
@@ -619,7 +619,7 @@ static inline int mddev_trylock(struct mddev * mddev)
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(struct mddev * mddev)
+void mddev_unlock(struct mddev * mddev)
 {
 	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
@@ -5628,10 +5628,7 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg)
 	char *ptr, *buf = NULL;
 	int err = -ENOMEM;
 
-	if (md_allow_write(mddev))
-		file = kmalloc(sizeof(*file), GFP_NOIO);
-	else
-		file = kmalloc(sizeof(*file), GFP_KERNEL);
+	file = kmalloc(sizeof(*file), GFP_NOIO);
 
 	if (!file)
 		goto out;
@@ -8681,6 +8678,8 @@ EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_check_recovery);
 EXPORT_SYMBOL(md_reap_sync_thread);
+EXPORT_SYMBOL(mddev_unlock);
+EXPORT_SYMBOL(md_queue_misc_work);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD RAID framework");
 MODULE_ALIAS("md");
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 20f02c0..77924d3 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -621,4 +621,12 @@ static inline int mddev_check_plugged(struct mddev *mddev)
 	return !!blk_check_plugged(md_unplug, mddev,
 				   sizeof(struct blk_plug_cb));
 }
+
+static inline int mddev_lock(struct mddev * mddev)
+{
+	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+}
+extern void mddev_unlock(struct mddev *mddev);
+extern int md_queue_misc_work(struct work_struct *work);
+
 #endif /* _MD_MD_H */
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 78ea443..840d0dd 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -200,6 +200,21 @@ static int stripe_operations_active(struct stripe_head *sh)
 	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
+static void raid5_wakeup_stripe_thread(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	struct raid5_percpu *percpu;
+	int i, orphaned = 1;
+
+	percpu = per_cpu_ptr(conf->percpu, sh->cpu);
+	for_each_cpu(i, &percpu->handle_threads) {
+		md_wakeup_thread(conf->aux_threads[i]->thread);
+		orphaned = 0;
+	}
+	if (orphaned)
+		md_wakeup_thread(conf->mddev->thread);
+}
+
 static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
 	BUG_ON(!list_empty(&sh->lru));
@@ -212,9 +227,19 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 			   sh->bm_seq - conf->seq_write > 0)
 			list_add_tail(&sh->lru, &conf->bitmap_list);
 		else {
+			int cpu = sh->cpu;
+			struct raid5_percpu *percpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			clear_bit(STRIPE_BIT_DELAY, &sh->state);
-			list_add_tail(&sh->lru, &conf->handle_list);
+			list_add_tail(&sh->lru, &percpu->handle_list);
+			raid5_wakeup_stripe_thread(sh);
+			return;
 		}
 		md_wakeup_thread(conf->mddev->thread);
 	} else {
@@ -239,12 +264,47 @@ static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
 		do_release_stripe(conf, sh);
 }
 
+/* should hold conf->device_lock already */
+static int release_stripe_list(struct r5conf *conf)
+{
+	struct stripe_head *sh;
+	int count = 0;
+	struct llist_node *head;
+
+	head = llist_del_all(&conf->released_stripes);
+	while (head) {
+		sh = llist_entry(head, struct stripe_head, release_list);
+		head = llist_next(head);
+		/* sh could be readded after STRIPE_ON_RELEASE_LIST is cleard */
+		smp_mb();
+		clear_bit(STRIPE_ON_RELEASE_LIST, &sh->state);
+		/*
+		 * Don't worry the bit is set here, because if the bit is set
+		 * again, the count is always > 1. This is true for
+		 * STRIPE_ON_UNPLUG_LIST bit too.
+		 */
+		__release_stripe(conf, sh);
+		count++;
+	}
+
+	return count;
+}
+
 static void release_stripe(struct stripe_head *sh)
 {
 	struct r5conf *conf = sh->raid_conf;
 	unsigned long flags;
+	bool wakeup;
 
+	if (test_and_set_bit(STRIPE_ON_RELEASE_LIST, &sh->state))
+		goto slow_path;
+	wakeup = llist_add(&sh->release_list, &conf->released_stripes);
+	if (wakeup)
+		md_wakeup_thread(conf->mddev->thread);
+	return;
+slow_path:
 	local_irq_save(flags);
+	/* we are ok here if STRIPE_ON_RELEASE_LIST is set or not */
 	if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) {
 		do_release_stripe(conf, sh);
 		spin_unlock(&conf->device_lock);
@@ -359,6 +419,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 		raid5_build_block(sh, i, previous);
 	}
 	insert_hash(conf, sh);
+	sh->cpu = smp_processor_id();
 }
 
 static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
@@ -491,7 +552,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
 			if (atomic_read(&sh->count)) {
 				BUG_ON(!list_empty(&sh->lru)
 				    && !test_bit(STRIPE_EXPANDING, &sh->state)
-				    && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state));
+				    && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state)
+				    && !test_bit(STRIPE_ON_RELEASE_LIST, &sh->state));
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
@@ -3773,12 +3835,19 @@ static void raid5_activate_delayed(struct r5conf *conf)
 		while (!list_empty(&conf->delayed_list)) {
 			struct list_head *l = conf->delayed_list.next;
 			struct stripe_head *sh;
+			int cpu;
 			sh = list_entry(l, struct stripe_head, lru);
 			list_del_init(l);
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
 				atomic_inc(&conf->preread_active_stripes);
 			list_add_tail(&sh->lru, &conf->hold_list);
+			cpu = sh->cpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			raid5_wakeup_stripe_thread(sh);
 		}
 	}
 }
@@ -4058,18 +4127,29 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
-{
-	struct stripe_head *sh;
-
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf,
+	cpumask_t *mask)
+{
+	struct stripe_head *sh = NULL, *tmp;
+	struct list_head *handle_list = NULL;
+	int cpu;
+
+	/* Should we take action to avoid starvation of latter CPUs ? */
+	for_each_cpu(cpu, mask) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+		if (!list_empty(&percpu->handle_list)) {
+			handle_list = &percpu->handle_list;
+			break;
+		}
+	}
 	pr_debug("%s: handle: %s hold: %s full_writes: %d bypass_count: %d\n",
 		  __func__,
-		  list_empty(&conf->handle_list) ? "empty" : "busy",
+		  !handle_list ? "empty" : "busy",
 		  list_empty(&conf->hold_list) ? "empty" : "busy",
 		  atomic_read(&conf->pending_full_writes), conf->bypass_count);
 
-	if (!list_empty(&conf->handle_list)) {
-		sh = list_entry(conf->handle_list.next, typeof(*sh), lru);
+	if (handle_list) {
+		sh = list_entry(handle_list->next, typeof(*sh), lru);
 
 		if (list_empty(&conf->hold_list))
 			conf->bypass_count = 0;
@@ -4087,12 +4167,23 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
 		   ((conf->bypass_threshold &&
 		     conf->bypass_count > conf->bypass_threshold) ||
 		    atomic_read(&conf->pending_full_writes) == 0)) {
-		sh = list_entry(conf->hold_list.next,
-				typeof(*sh), lru);
-		conf->bypass_count -= conf->bypass_threshold;
-		if (conf->bypass_count < 0)
-			conf->bypass_count = 0;
-	} else
+
+		list_for_each_entry(tmp, &conf->hold_list,  lru) {
+			if (cpumask_test_cpu(tmp->cpu, mask) ||
+			    !cpu_online(tmp->cpu)) {
+				sh = tmp;
+				break;
+			}
+		}
+
+		if (sh) {
+			conf->bypass_count -= conf->bypass_threshold;
+			if (conf->bypass_count < 0)
+				conf->bypass_count = 0;
+		}
+	}
+
+	if (!sh)
 		return NULL;
 
 	list_del_init(&sh->lru);
@@ -4127,6 +4218,10 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
 			 */
 			smp_mb__before_clear_bit();
 			clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state);
+			/*
+			 * STRIPE_ON_RELEASE_LIST could be set here. In that
+			 * case, the count is always > 1 here
+			 */
 			__release_stripe(conf, sh);
 			cnt++;
 		}
@@ -4789,13 +4884,13 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 }
 
 #define MAX_STRIPE_BATCH 8
-static int handle_active_stripes(struct r5conf *conf)
+static int handle_active_stripes(struct r5conf *conf, cpumask_t *mask)
 {
 	struct stripe_head *batch[MAX_STRIPE_BATCH], *sh;
 	int i, batch_size = 0;
 
 	while (batch_size < MAX_STRIPE_BATCH &&
-			(sh = __get_priority_stripe(conf)) != NULL)
+			(sh = __get_priority_stripe(conf, mask)) != NULL)
 		batch[batch_size++] = sh;
 
 	if (batch_size == 0)
@@ -4813,6 +4908,37 @@ static int handle_active_stripes(struct r5conf *conf)
 	return batch_size;
 }
 
+static void raid5auxd(struct md_thread *thread)
+{
+	struct mddev *mddev = thread->mddev;
+	struct r5conf *conf = mddev->private;
+	struct blk_plug plug;
+	int handled;
+	struct raid5_auxth *auxth = thread->private;
+
+	pr_debug("+++ raid5auxd active\n");
+
+	blk_start_plug(&plug);
+	handled = 0;
+	spin_lock_irq(&conf->device_lock);
+	while (1) {
+		int batch_size, released;
+
+		released = release_stripe_list(conf);
+
+		batch_size = handle_active_stripes(conf, &auxth->work_mask);
+		if (!batch_size && !released)
+			break;
+		handled += batch_size;
+	}
+	pr_debug("%d stripes handled\n", handled);
+
+	spin_unlock_irq(&conf->device_lock);
+	blk_finish_plug(&plug);
+
+	pr_debug("--- raid5auxd inactive\n");
+}
+
 /*
  * This is our raid5 kernel thread.
  *
@@ -4836,7 +4962,9 @@ static void raid5d(struct md_thread *thread)
 	spin_lock_irq(&conf->device_lock);
 	while (1) {
 		struct bio *bio;
-		int batch_size;
+		int batch_size, released;
+
+		released = release_stripe_list(conf);
 
 		if (
 		    !list_empty(&conf->bitmap_list)) {
@@ -4860,8 +4988,8 @@ static void raid5d(struct md_thread *thread)
 			handled++;
 		}
 
-		batch_size = handle_active_stripes(conf);
-		if (!batch_size)
+		batch_size = handle_active_stripes(conf, &conf->work_mask);
+		if (!batch_size && !released)
 			break;
 		handled += batch_size;
 
@@ -4989,10 +5117,270 @@ stripe_cache_active_show(struct mddev *mddev, char *page)
 static struct md_sysfs_entry
 raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
 
+static void raid5_update_threads_handle_mask(struct mddev *mddev)
+{
+	int cpu, i;
+	struct raid5_percpu *percpu;
+	struct r5conf *conf = mddev->private;
+
+	for_each_online_cpu(cpu) {
+		percpu = per_cpu_ptr(conf->percpu, cpu);
+		cpumask_clear(&percpu->handle_threads);
+	}
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
+	for (i = 0; i < conf->aux_thread_num; i++) {
+		cpumask_t *work_mask = &conf->aux_threads[i]->work_mask;
+		for_each_cpu(cpu, work_mask) {
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+			cpumask_set_cpu(i, &percpu->handle_threads);
+		}
+		cpumask_andnot(&conf->work_mask, &conf->work_mask,
+				work_mask);
+	}
+}
+
+struct raid5_auxth_sysfs {
+	struct attribute attr;
+	ssize_t (*show)(struct mddev *, struct raid5_auxth *, char *);
+	ssize_t (*store)(struct mddev *, struct raid5_auxth *,
+		const char *, size_t);
+};
+
+static ssize_t raid5_show_thread_cpulist(struct mddev *mddev,
+	struct raid5_auxth *thread, char *page)
+{
+	if (!mddev->private)
+		return 0;
+	return cpulist_scnprintf(page, PAGE_SIZE, &thread->work_mask);
+}
+
+static ssize_t
+raid5_store_thread_cpulist(struct mddev *mddev, struct raid5_auxth *thread,
+	const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	cpumask_var_t mask;
+
+	if (!conf)
+		return -ENODEV;
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	if (cpulist_parse(page, mask)) {
+		free_cpumask_var(mask);
+		return -EINVAL;
+	}
+
+	get_online_cpus();
+	spin_lock_irq(&conf->device_lock);
+	cpumask_copy(&thread->work_mask, mask);
+	raid5_update_threads_handle_mask(mddev);
+	spin_unlock_irq(&conf->device_lock);
+	put_online_cpus();
+	set_cpus_allowed_ptr(thread->thread->tsk, mask);
+
+	free_cpumask_var(mask);
+	return len;
+}
+
+static struct raid5_auxth_sysfs thread_cpulist =
+__ATTR(cpulist, S_IRUGO|S_IWUSR, raid5_show_thread_cpulist,
+	raid5_store_thread_cpulist);
+
+static struct attribute *auxth_attrs[] = {
+	&thread_cpulist.attr,
+	NULL,
+};
+
+static ssize_t
+raid5_auxth_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->show)
+		return -EIO;
+	mddev_lock(mddev);
+	ret = entry->show(mddev, thread, page);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static ssize_t
+raid5_auxth_attr_store(struct kobject *kobj, struct attribute *attr,
+	      const char *page, size_t length)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->store)
+		return -EIO;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	mddev_lock(mddev);
+	ret = entry->store(mddev, thread, page, length);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static void raid5_auxth_release(struct kobject *kobj)
+{
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	kfree(thread);
+}
+
+static const struct sysfs_ops raid5_auxth_sysfsops = {
+	.show = raid5_auxth_attr_show,
+	.store = raid5_auxth_attr_store,
+};
+static struct kobj_type raid5_auxth_ktype = {
+	.release = raid5_auxth_release,
+	.sysfs_ops = &raid5_auxth_sysfsops,
+	.default_attrs = auxth_attrs,
+};
+
+static ssize_t
+raid5_show_auxthread_number(struct mddev *mddev, char *page)
+{
+	struct r5conf *conf = mddev->private;
+	if (conf)
+		return sprintf(page, "%d\n", conf->aux_thread_num);
+	else
+		return 0;
+}
+
+static void raid5_auxth_delete(struct work_struct *ws)
+{
+	struct raid5_auxth *thread = container_of(ws, struct raid5_auxth,
+		del_work);
+
+	kobject_del(&thread->kobj);
+	kobject_put(&thread->kobj);
+}
+
+static void __free_aux_thread(struct mddev *mddev, struct raid5_auxth *thread)
+{
+	md_unregister_thread(&thread->thread);
+	INIT_WORK(&thread->del_work, raid5_auxth_delete);
+	kobject_get(&thread->kobj);
+	md_queue_misc_work(&thread->del_work);
+}
+
+static struct raid5_auxth *__create_aux_thread(struct mddev *mddev, int i)
+{
+	struct raid5_auxth *thread;
+	char name[10];
+
+	thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+	if (!thread)
+		return NULL;
+	snprintf(name, 10, "aux%d", i);
+	thread->thread = md_register_thread(raid5auxd, mddev, name);
+	if (!thread->thread) {
+		kfree(thread);
+		return NULL;
+	}
+	thread->thread->private = thread;
+
+	cpumask_copy(&thread->work_mask, cpu_online_mask);
+
+	if (kobject_init_and_add(&thread->kobj, &raid5_auxth_ktype,
+	    &mddev->kobj, "auxth%d", i)) {
+		md_unregister_thread(&thread->thread);
+		kfree(thread);
+		return NULL;
+	}
+	return thread;
+}
+
+static ssize_t
+raid5_store_auxthread_number(struct mddev *mddev, const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	unsigned long new;
+	int i;
+	struct raid5_auxth **threads;
+
+	if (len >= PAGE_SIZE)
+		return -EINVAL;
+	if (!conf)
+		return -ENODEV;
+
+	if (kstrtoul(page, 10, &new))
+		return -EINVAL;
+
+	if (new == conf->aux_thread_num)
+		return len;
+
+	/* There is no point creating more threads than cpu number */
+	if (new > num_online_cpus())
+		return -EINVAL;
+
+	if (new > conf->aux_thread_num) {
+		threads = kzalloc(sizeof(struct raid5_auxth *) * new,
+				GFP_KERNEL);
+		if (!threads)
+			return -ENOMEM;
+
+		i = conf->aux_thread_num;
+		while (i < new) {
+			threads[i] = __create_aux_thread(mddev, i);
+			if (!threads[i])
+				goto error;
+
+			i++;
+		}
+		memcpy(threads, conf->aux_threads,
+			sizeof(struct raid5_auxth *) * conf->aux_thread_num);
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		kfree(conf->aux_threads);
+		conf->aux_threads = threads;
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+	} else {
+		int old = conf->aux_thread_num;
+
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+		for (i = new; i < old; i++)
+			__free_aux_thread(mddev, conf->aux_threads[i]);
+	}
+
+	return len;
+error:
+	while (--i >= conf->aux_thread_num)
+		__free_aux_thread(mddev, threads[i]);
+	kfree(threads);
+	return -ENOMEM;
+}
+
+static struct md_sysfs_entry
+raid5_auxthread_number = __ATTR(auxthread_number, S_IRUGO|S_IWUSR,
+				raid5_show_auxthread_number,
+				raid5_store_auxthread_number);
+
 static struct attribute *raid5_attrs[] =  {
 	&raid5_stripecache_size.attr,
 	&raid5_stripecache_active.attr,
 	&raid5_preread_bypass_threshold.attr,
+	&raid5_auxthread_number.attr,
 	NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -5040,6 +5428,7 @@ static void raid5_free_percpu(struct r5conf *conf)
 
 static void free_conf(struct r5conf *conf)
 {
+	kfree(conf->aux_threads);
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
 	kfree(conf->disks);
@@ -5052,7 +5441,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
 {
 	struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
-	long cpu = (long)hcpu;
+	long cpu = (long)hcpu, anycpu;
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
 	switch (action) {
@@ -5071,9 +5460,17 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			       __func__, cpu);
 			return notifier_from_errno(-ENOMEM);
 		}
+		INIT_LIST_HEAD(&(percpu->handle_list));
+		cpumask_clear(&percpu->handle_threads);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
+		spin_lock_irq(&conf->device_lock);
+		anycpu = cpumask_any(cpu_online_mask);
+		list_splice_tail_init(&percpu->handle_list,
+			&per_cpu_ptr(conf->percpu, anycpu)->handle_list);
+		spin_unlock_irq(&conf->device_lock);
+
 		safe_put_page(percpu->spare_page);
 		kfree(percpu->scribble);
 		percpu->spare_page = NULL;
@@ -5082,6 +5479,10 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 	default:
 		break;
 	}
+
+	spin_lock_irq(&conf->device_lock);
+	raid5_update_threads_handle_mask(conf->mddev);
+	spin_unlock_irq(&conf->device_lock);
 	return NOTIFY_OK;
 }
 #endif
@@ -5102,20 +5503,24 @@ static int raid5_alloc_percpu(struct r5conf *conf)
 	get_online_cpus();
 	err = 0;
 	for_each_present_cpu(cpu) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+
 		if (conf->level == 6) {
 			spare_page = alloc_page(GFP_KERNEL);
 			if (!spare_page) {
 				err = -ENOMEM;
 				break;
 			}
-			per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
+			percpu->spare_page = spare_page;
 		}
 		scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
 		if (!scribble) {
 			err = -ENOMEM;
 			break;
 		}
-		per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
+		percpu->scribble = scribble;
+		INIT_LIST_HEAD(&percpu->handle_list);
+		cpumask_clear(&percpu->handle_threads);
 	}
 #ifdef CONFIG_HOTPLUG_CPU
 	conf->cpu_notify.notifier_call = raid456_cpu_notify;
@@ -5171,17 +5576,19 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
 	init_waitqueue_head(&conf->wait_for_overlap);
-	INIT_LIST_HEAD(&conf->handle_list);
 	INIT_LIST_HEAD(&conf->hold_list);
 	INIT_LIST_HEAD(&conf->delayed_list);
 	INIT_LIST_HEAD(&conf->bitmap_list);
 	INIT_LIST_HEAD(&conf->inactive_list);
+	init_llist_head(&conf->released_stripes);
 	atomic_set(&conf->active_stripes, 0);
 	atomic_set(&conf->preread_active_stripes, 0);
 	atomic_set(&conf->active_aligned_reads, 0);
 	conf->bypass_threshold = BYPASS_THRESHOLD;
 	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
 	conf->raid_disks = mddev->raid_disks;
 	if (mddev->reshape_position == MaxSector)
 		conf->previous_raid_disks = mddev->raid_disks;
@@ -5640,6 +6047,10 @@ abort:
 static int stop(struct mddev *mddev)
 {
 	struct r5conf *conf = mddev->private;
+	int i;
+
+	for (i = 0; i < conf->aux_thread_num; i++)
+		__free_aux_thread(mddev, conf->aux_threads[i]);
 
 	md_unregister_thread(&mddev->thread);
 	if (mddev->queue)
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 70c4932..04540f3 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -197,6 +197,7 @@ enum reconstruct_states {
 struct stripe_head {
 	struct hlist_node	hash;
 	struct list_head	lru;	      /* inactive_list or handle_list */
+	struct llist_node	release_list;
 	struct r5conf		*raid_conf;
 	short			generation;	/* increments with every
 						 * reshape */
@@ -211,6 +212,7 @@ struct stripe_head {
 	enum check_states	check_state;
 	enum reconstruct_states reconstruct_state;
 	spinlock_t		stripe_lock;
+	int			cpu;
 	/**
 	 * struct stripe_operations
 	 * @target - STRIPE_OP_COMPUTE_BLK target
@@ -321,6 +323,7 @@ enum {
 	STRIPE_OPS_REQ_PENDING,
 	STRIPE_ON_UNPLUG_LIST,
 	STRIPE_DISCARD,
+	STRIPE_ON_RELEASE_LIST,
 };
 
 /*
@@ -363,6 +366,14 @@ struct disk_info {
 	struct md_rdev	*rdev, *replacement;
 };
 
+struct raid5_auxth {
+	struct md_thread	*thread;
+	/* which CPUs should the auxiliary thread handle stripes from */
+	cpumask_t		work_mask;
+	struct kobject		kobj;
+	struct work_struct	del_work;
+};
+
 struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
 	struct mddev		*mddev;
@@ -431,6 +442,12 @@ struct r5conf {
 					      * lists and performing address
 					      * conversions
 					      */
+		struct list_head handle_list;
+		cpumask_t	handle_threads; /* Which threads can the CPU's
+						 * stripes be handled. It really
+						 * is a bitmap to aux_threads[],
+						 * but has max bits NR_CPUS
+						 */
 	} __percpu *percpu;
 	size_t			scribble_len; /* size of scribble region must be
 					       * associated with conf to handle
@@ -445,6 +462,7 @@ struct r5conf {
 	 */
 	atomic_t		active_stripes;
 	struct list_head	inactive_list;
+	struct llist_head	released_stripes;
 	wait_queue_head_t	wait_for_stripe;
 	wait_queue_head_t	wait_for_overlap;
 	int			inactive_blocked;	/* release of inactive stripes blocked,
@@ -458,6 +476,10 @@ struct r5conf {
 	 * the new thread here until we fully activate the array.
 	 */
 	struct md_thread	*thread;
+	int			aux_thread_num;
+	struct raid5_auxth	**aux_threads;
+	/* which CPUs should raid5d thread handle stripes from */
+	cpumask_t		work_mask;
 };
 
 /*
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index 886da16..419a2d6 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -369,4 +369,6 @@
 #define USB_PID_TECHNISAT_USB2_DVB_S2			0x0500
 #define USB_PID_CPYTO_REDI_PC50A			0xa803
 #define USB_PID_CTVDIGDUAL_V2				0xe410
+#define USB_PID_PCTV_2002E                              0x025c
+#define USB_PID_PCTV_2002E_SE                           0x025d
 #endif
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c
index 7606218..aeb56c5 100644
--- a/drivers/media/i2c/adv7343.c
+++ b/drivers/media/i2c/adv7343.c
@@ -27,8 +27,10 @@
 #include <linux/uaccess.h>
 
 #include <media/adv7343.h>
+#include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-of.h>
 
 #include "adv7343_regs.h"
 
@@ -226,12 +228,12 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
 	else
 		val = state->pdata->mode_config.sleep_mode << 0 |
 		      state->pdata->mode_config.pll_control << 1 |
-		      state->pdata->mode_config.dac_3 << 2 |
-		      state->pdata->mode_config.dac_2 << 3 |
-		      state->pdata->mode_config.dac_1 << 4 |
-		      state->pdata->mode_config.dac_6 << 5 |
-		      state->pdata->mode_config.dac_5 << 6 |
-		      state->pdata->mode_config.dac_4 << 7;
+		      state->pdata->mode_config.dac[2] << 2 |
+		      state->pdata->mode_config.dac[1] << 3 |
+		      state->pdata->mode_config.dac[0] << 4 |
+		      state->pdata->mode_config.dac[5] << 5 |
+		      state->pdata->mode_config.dac[4] << 6 |
+		      state->pdata->mode_config.dac[3] << 7;
 
 	err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
 	if (err < 0)
@@ -250,15 +252,15 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
 	/* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
 	val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
 
-	if (state->pdata && state->pdata->sd_config.sd_dac_out1)
-		val = val | (state->pdata->sd_config.sd_dac_out1 << 1);
-	else if (state->pdata && !state->pdata->sd_config.sd_dac_out1)
-		val = val & ~(state->pdata->sd_config.sd_dac_out1 << 1);
+	if (state->pdata && state->pdata->sd_config.sd_dac_out[0])
+		val = val | (state->pdata->sd_config.sd_dac_out[0] << 1);
+	else if (state->pdata && !state->pdata->sd_config.sd_dac_out[0])
+		val = val & ~(state->pdata->sd_config.sd_dac_out[0] << 1);
 
-	if (state->pdata && state->pdata->sd_config.sd_dac_out2)
-		val = val | (state->pdata->sd_config.sd_dac_out2 << 2);
-	else if (state->pdata && !state->pdata->sd_config.sd_dac_out2)
-		val = val & ~(state->pdata->sd_config.sd_dac_out2 << 2);
+	if (state->pdata && state->pdata->sd_config.sd_dac_out[1])
+		val = val | (state->pdata->sd_config.sd_dac_out[1] << 2);
+	else if (state->pdata && !state->pdata->sd_config.sd_dac_out[1])
+		val = val & ~(state->pdata->sd_config.sd_dac_out[1] << 2);
 
 	err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
 	if (err < 0)
@@ -398,6 +400,40 @@ static int adv7343_initialize(struct v4l2_subdev *sd)
 	return err;
 }
 
+static struct adv7343_platform_data *
+adv7343_get_pdata(struct i2c_client *client)
+{
+	struct adv7343_platform_data *pdata;
+	struct device_node *np;
+
+	if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
+		return client->dev.platform_data;
+
+	np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL);
+	if (!np)
+		return NULL;
+
+	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		goto done;
+
+	pdata->mode_config.sleep_mode =
+			of_property_read_bool(np, "adi,power-mode-sleep-mode");
+
+	pdata->mode_config.pll_control =
+			of_property_read_bool(np, "adi,power-mode-pll-ctrl");
+
+	of_property_read_u32_array(np, "adi,dac-enable",
+				   pdata->mode_config.dac, 6);
+
+	of_property_read_u32_array(np, "adi,sd-dac-enable",
+				   pdata->sd_config.sd_dac_out, 2);
+
+done:
+	of_node_put(np);
+	return pdata;
+}
+
 static int adv7343_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
@@ -416,7 +452,7 @@ static int adv7343_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	/* Copy board specific information here */
-	state->pdata = client->dev.platform_data;
+	state->pdata = adv7343_get_pdata(client);
 
 	state->reg00	= 0x80;
 	state->reg01	= 0x00;
@@ -445,16 +481,21 @@ static int adv7343_probe(struct i2c_client *client,
 				       ADV7343_GAIN_DEF);
 	state->sd.ctrl_handler = &state->hdl;
 	if (state->hdl.error) {
-		int err = state->hdl.error;
-
-		v4l2_ctrl_handler_free(&state->hdl);
-		return err;
+		err = state->hdl.error;
+		goto done;
 	}
 	v4l2_ctrl_handler_setup(&state->hdl);
 
 	err = adv7343_initialize(&state->sd);
 	if (err)
+		goto done;
+
+	err = v4l2_async_register_subdev(&state->sd);
+
+done:
+	if (err < 0)
 		v4l2_ctrl_handler_free(&state->hdl);
+
 	return err;
 }
 
@@ -463,6 +504,7 @@ static int adv7343_remove(struct i2c_client *client)
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct adv7343_state *state = to_state(sd);
 
+	v4l2_async_unregister_subdev(&state->sd);
 	v4l2_device_unregister_subdev(sd);
 	v4l2_ctrl_handler_free(&state->hdl);
 
@@ -476,8 +518,17 @@ static const struct i2c_device_id adv7343_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, adv7343_id);
 
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id adv7343_of_match[] = {
+	{.compatible = "adi,adv7343", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, adv7343_of_match);
+#endif
+
 static struct i2c_driver adv7343_driver = {
 	.driver = {
+		.of_match_table = of_match_ptr(adv7343_of_match),
 		.owner	= THIS_MODULE,
 		.name	= "adv7343",
 	},
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
index efdc873..a9110d8 100644
--- a/drivers/media/i2c/ml86v7667.c
+++ b/drivers/media/i2c/ml86v7667.c
@@ -117,7 +117,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = to_sd(ctrl);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	int ret;
+	int ret = -EINVAL;
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
@@ -157,7 +157,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
@@ -209,7 +209,8 @@ static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd,
 
 	fmt->code = V4L2_MBUS_FMT_YUYV8_2X8;
 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	fmt->field = V4L2_FIELD_INTERLACED;
+	/* The top field is always transferred first by the chip */
+	fmt->field = V4L2_FIELD_INTERLACED_TB;
 	fmt->width = 720;
 	fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576;
 
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index a24f90c..8a29810 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/v4l2-dv-timings.h>
 
+#include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
 
 #include "ths8200_regs.h"
@@ -500,6 +501,7 @@ static int ths8200_probe(struct i2c_client *client,
 {
 	struct ths8200_state *state;
 	struct v4l2_subdev *sd;
+	int error;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -517,6 +519,10 @@ static int ths8200_probe(struct i2c_client *client,
 
 	ths8200_core_init(sd);
 
+	error = v4l2_async_register_subdev(&state->sd);
+	if (error)
+		return error;
+
 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
 		  client->addr << 1, client->adapter->name);
 
@@ -526,12 +532,13 @@ static int ths8200_probe(struct i2c_client *client,
 static int ths8200_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ths8200_state *decoder = to_state(sd);
 
 	v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
 		 client->addr << 1, client->adapter->name);
 
 	ths8200_s_power(sd, false);
-
+	v4l2_async_unregister_subdev(&decoder->sd);
 	v4l2_device_unregister_subdev(sd);
 
 	return 0;
@@ -543,10 +550,19 @@ static struct i2c_device_id ths8200_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ths8200_id);
 
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id ths8200_of_match[] = {
+	{ .compatible = "ti,ths8200", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ths8200_of_match);
+#endif
+
 static struct i2c_driver ths8200_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "ths8200",
+		.of_match_table = of_match_ptr(ths8200_of_match),
 	},
 	.probe = ths8200_probe,
 	.remove = ths8200_remove,
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index 9c6d66a..91f3dd4 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/v4l2-mediabus.h>
 
+#include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-mediabus.h>
@@ -1175,16 +1176,22 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	sd->ctrl_handler = &decoder->hdl;
 	if (decoder->hdl.error) {
 		ret = decoder->hdl.error;
-
-		v4l2_ctrl_handler_free(&decoder->hdl);
-		return ret;
+		goto done;
 	}
 	v4l2_ctrl_handler_setup(&decoder->hdl);
 
-	v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
-
-	return 0;
+	ret = v4l2_async_register_subdev(&decoder->sd);
+	if (!ret)
+		v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
 
+done:
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&decoder->hdl);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+		media_entity_cleanup(&decoder->sd.entity);
+#endif
+	}
+	return ret;
 }
 
 /**
@@ -1199,6 +1206,7 @@ static int tvp514x_remove(struct i2c_client *client)
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct tvp514x_decoder *decoder = to_decoder(sd);
 
+	v4l2_async_unregister_subdev(&decoder->sd);
 	v4l2_device_unregister_subdev(sd);
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	media_entity_cleanup(&decoder->sd.entity);
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index a4e4948..f6b1f3f 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/v4l2-dv-timings.h>
 #include <media/tvp7002.h>
+#include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
@@ -1039,6 +1040,10 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
 	}
 	v4l2_ctrl_handler_setup(&device->hdl);
 
+	error = v4l2_async_register_subdev(&device->sd);
+	if (error)
+		goto error;
+
 	return 0;
 
 error:
@@ -1063,6 +1068,7 @@ static int tvp7002_remove(struct i2c_client *c)
 
 	v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter"
 				"on address 0x%x\n", c->addr);
+	v4l2_async_unregister_subdev(&device->sd);
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	media_entity_cleanup(&device->sd.entity);
 #endif
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index e564aac..d85cb0ac 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -4441,9 +4441,7 @@ static void tibetCS16_init(struct bttv *btv)
  * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
  * unit 3, the second (which is the master) is logical unit 0, etc.
  * We need to maintain the status of the analog switch (which of the 16
- * cameras is connected to which of the 4 controllers).  Rather than
- * add to the bttv structure for this, we use the data reserved for
- * the mbox (unused for this card type).
+ * cameras is connected to which of the 4 controllers) in sw_status array.
  */
 
 /*
@@ -4478,7 +4476,6 @@ static void kodicom4400r_write(struct bttv *btv,
  */
 static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
 {
-	char *sw_status;
 	int xaddr, yaddr;
 	struct bttv *mctlr;
 	static unsigned char map[4] = {3, 0, 2, 1};
@@ -4489,14 +4486,13 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
 	}
 	yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
 	yaddr = map[yaddr];
-	sw_status = (char *)(&mctlr->mbox_we);
 	xaddr = input & 0xf;
 	/* Check if the controller/camera pair has changed, else ignore */
-	if (sw_status[yaddr] != xaddr)
+	if (mctlr->sw_status[yaddr] != xaddr)
 	{
 		/* "open" the old switch, "close" the new one, save the new */
-		kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
-		sw_status[yaddr] = xaddr;
+		kodicom4400r_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0);
+		mctlr->sw_status[yaddr] = xaddr;
 		kodicom4400r_write(mctlr, xaddr, yaddr, 1);
 	}
 }
@@ -4509,7 +4505,6 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
  */
 static void kodicom4400r_init(struct bttv *btv)
 {
-	char *sw_status = (char *)(&btv->mbox_we);
 	int ix;
 
 	gpio_inout(0x0003ff, 0x0003ff);
@@ -4517,7 +4512,7 @@ static void kodicom4400r_init(struct bttv *btv)
 	gpio_write(0);
 	/* Preset camera 0 to the 4 controllers */
 	for (ix = 0; ix < 4; ix++) {
-		sw_status[ix] = ix;
+		btv->sw_status[ix] = ix;
 		kodicom4400r_write(btv, ix, ix, 1);
 	}
 	/*
@@ -4794,7 +4789,6 @@ static void gv800s_write(struct bttv *btv,
 static void gv800s_muxsel(struct bttv *btv, unsigned int input)
 {
 	struct bttv *mctlr;
-	char *sw_status;
 	int xaddr, yaddr;
 	static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 },
 					  { 0x1, 0x5, 0xb, 0x7 },
@@ -4807,14 +4801,13 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input)
 		return;
 	}
 	yaddr = (btv->c.nr - mctlr->c.nr) & 3;
-	sw_status = (char *)(&mctlr->mbox_we);
 	xaddr = map[yaddr][input] & 0xf;
 
 	/* Check if the controller/camera pair has changed, ignore otherwise */
-	if (sw_status[yaddr] != xaddr) {
+	if (mctlr->sw_status[yaddr] != xaddr) {
 		/* disable the old switch, enable the new one and save status */
-		gv800s_write(mctlr, sw_status[yaddr], yaddr, 0);
-		sw_status[yaddr] = xaddr;
+		gv800s_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0);
+		mctlr->sw_status[yaddr] = xaddr;
 		gv800s_write(mctlr, xaddr, yaddr, 1);
 	}
 }
@@ -4822,7 +4815,6 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input)
 /* GeoVision GV-800(S) "master" chip init */
 static void gv800s_init(struct bttv *btv)
 {
-	char *sw_status = (char *)(&btv->mbox_we);
 	int ix;
 
 	gpio_inout(0xf107f, 0xf107f);
@@ -4831,7 +4823,7 @@ static void gv800s_init(struct bttv *btv)
 
 	/* Preset camera 0 to the 4 controllers */
 	for (ix = 0; ix < 4; ix++) {
-		sw_status[ix] = ix;
+		btv->sw_status[ix] = ix;
 		gv800s_write(btv, ix, ix, 1);
 	}
 
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 9c1cc2c..6eefb59 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -459,6 +459,9 @@ struct bttv {
 	int mbox_iow;
 	int mbox_csel;
 
+	/* switch status for multi-controller cards */
+	char sw_status[4];
+
 	/* risc memory management data
 	   - must acquire s_lock before changing these
 	   - only the irq handler is supported to touch top + bottom + vcurr */
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c
index e958a01..c443b7a 100644
--- a/drivers/media/pci/cx23885/cx23885-av.c
+++ b/drivers/media/pci/cx23885/cx23885-av.c
@@ -23,6 +23,7 @@
 
 #include "cx23885.h"
 #include "cx23885-av.h"
+#include "cx23885-video.h"
 
 void cx23885_av_work_handler(struct work_struct *work)
 {
@@ -32,5 +33,17 @@ void cx23885_av_work_handler(struct work_struct *work)
 
 	v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
 			 PCI_MSK_AV_CORE, &handled);
+
+	/* Getting here with the interrupt not handled
+	   then probbaly flatiron does have pending interrupts.
+	*/
+	if (!handled) {
+		/* clear left and right adc channel interrupt request flag */
+		cx23885_flatiron_write(dev, 0x1f,
+			cx23885_flatiron_read(dev, 0x1f) | 0x80);
+		cx23885_flatiron_write(dev, 0x23,
+			cx23885_flatiron_read(dev, 0x23) | 0x80);
+	}
+
 	cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
 }
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 9c5ed10..bb291c6 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -1249,6 +1249,10 @@ static int dvb_register(struct cx23885_tsport *port)
 		fe0->dvb.frontend = dvb_attach(ds3000_attach,
 					&tevii_ds3000_config,
 					&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(ts2020_attach, fe0->dvb.frontend,
+				&tevii_ts2020_config, &i2c_bus->i2c_adap);
+		}
 		break;
 	case CX23885_BOARD_PROF_8000:
 		i2c_bus = &dev->i2c_bus[0];
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index e33d1a7..1616868 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -32,6 +32,7 @@
 #include <asm/div64.h>
 
 #include "cx23885.h"
+#include "cx23885-video.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include "cx23885-ioctl.h"
@@ -417,7 +418,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
 	mutex_unlock(&dev->lock);
 }
 
-static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
 {
 	/* 8 bit registers, 8 bit values */
 	u8 buf[] = { reg, data };
@@ -428,7 +429,7 @@ static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
 	return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
 }
 
-static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
 {
 	/* 8 bit registers, 8 bit values */
 	int ret;
diff --git a/drivers/media/pci/cx23885/cx23885-video.h b/drivers/media/pci/cx23885/cx23885-video.h
new file mode 100644
index 0000000..c961a2b
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-video.h
@@ -0,0 +1,26 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX23885_VIDEO_H_
+#define _CX23885_VIDEO_H_
+int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data);
+u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg);
+#endif
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c
index df4ada88..66db0df 100644
--- a/drivers/media/platform/coda.c
+++ b/drivers/media/platform/coda.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/kfifo.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -28,6 +29,7 @@
 
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-core.h>
@@ -41,13 +43,16 @@
 
 #define CODA_FMO_BUF_SIZE	32
 #define CODADX6_WORK_BUF_SIZE	(288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
-#define CODA7_WORK_BUF_SIZE	(512 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
+#define CODA7_WORK_BUF_SIZE	(128 * 1024)
+#define CODA7_TEMP_BUF_SIZE	(304 * 1024)
 #define CODA_PARA_BUF_SIZE	(10 * 1024)
 #define CODA_ISRAM_SIZE	(2048 * 2)
 #define CODADX6_IRAM_SIZE	0xb000
-#define CODA7_IRAM_SIZE		0x14000 /* 81920 bytes */
+#define CODA7_IRAM_SIZE		0x14000
 
-#define CODA_MAX_FRAMEBUFFERS	2
+#define CODA7_PS_BUF_SIZE	0x28000
+
+#define CODA_MAX_FRAMEBUFFERS	8
 
 #define MAX_W		8192
 #define MAX_H		8192
@@ -129,6 +134,7 @@ struct coda_dev {
 	struct clk		*clk_ahb;
 
 	struct coda_aux_buf	codebuf;
+	struct coda_aux_buf	tempbuf;
 	struct coda_aux_buf	workbuf;
 	struct gen_pool		*iram_pool;
 	long unsigned int	iram_vaddr;
@@ -153,6 +159,7 @@ struct coda_params {
 	u8			mpeg4_inter_qp;
 	u8			gop_size;
 	int			codec_mode;
+	int			codec_mode_aux;
 	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
 	u32			framerate;
 	u16			bitrate;
@@ -160,13 +167,30 @@ struct coda_params {
 	u32			slice_max_mb;
 };
 
+struct coda_iram_info {
+	u32		axi_sram_use;
+	phys_addr_t	buf_bit_use;
+	phys_addr_t	buf_ip_ac_dc_use;
+	phys_addr_t	buf_dbk_y_use;
+	phys_addr_t	buf_dbk_c_use;
+	phys_addr_t	buf_ovl_use;
+	phys_addr_t	buf_btp_use;
+	phys_addr_t	search_ram_paddr;
+	int		search_ram_size;
+};
+
 struct coda_ctx {
 	struct coda_dev			*dev;
+	struct mutex			buffer_mutex;
 	struct list_head		list;
+	struct work_struct		skip_run;
 	int				aborting;
+	int				initialized;
 	int				streamon_out;
 	int				streamon_cap;
 	u32				isequence;
+	u32				qsequence;
+	u32				osequence;
 	struct coda_q_data		q_data[2];
 	enum coda_inst_type		inst_type;
 	struct coda_codec		*codec;
@@ -176,12 +200,25 @@ struct coda_ctx {
 	struct v4l2_ctrl_handler	ctrls;
 	struct v4l2_fh			fh;
 	int				gopcounter;
+	int				runcounter;
 	char				vpu_header[3][64];
 	int				vpu_header_size[3];
+	struct kfifo			bitstream_fifo;
+	struct mutex			bitstream_mutex;
+	struct coda_aux_buf		bitstream;
+	bool				prescan_failed;
 	struct coda_aux_buf		parabuf;
+	struct coda_aux_buf		psbuf;
+	struct coda_aux_buf		slicebuf;
 	struct coda_aux_buf		internal_frames[CODA_MAX_FRAMEBUFFERS];
+	struct coda_aux_buf		workbuf;
 	int				num_internal_frames;
 	int				idx;
+	int				reg_idx;
+	struct coda_iram_info		iram_info;
+	u32				bit_stream_param;
+	u32				frm_dis_flg;
+	int				display_idx;
 };
 
 static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
@@ -228,10 +265,22 @@ static int coda_wait_timeout(struct coda_dev *dev)
 static void coda_command_async(struct coda_ctx *ctx, int cmd)
 {
 	struct coda_dev *dev = ctx->dev;
+
+	if (dev->devtype->product == CODA_7541) {
+		/* Restore context related registers to CODA */
+		coda_write(dev, ctx->bit_stream_param,
+				CODA_REG_BIT_BIT_STREAM_PARAM);
+		coda_write(dev, ctx->frm_dis_flg,
+				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+		coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR);
+	}
+
 	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
 
 	coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
 	coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD);
+	coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD);
+
 	coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
 }
 
@@ -297,6 +346,8 @@ static struct coda_codec codadx6_codecs[] = {
 static struct coda_codec coda7_codecs[] = {
 	CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1280, 720),
 	CODA_CODEC(CODA7_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1280, 720),
+	CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1080),
+	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1080),
 };
 
 static bool coda_format_is_yuv(u32 fourcc)
@@ -365,7 +416,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 }
 
 static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
-			enum v4l2_buf_type type)
+			enum v4l2_buf_type type, int src_fourcc)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
 	struct coda_codec *codecs = ctx->dev->devtype->codecs;
@@ -377,7 +428,8 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
 
 	for (i = 0; i < num_formats; i++) {
 		/* Both uncompressed formats are always supported */
-		if (coda_format_is_yuv(formats[i].fourcc)) {
+		if (coda_format_is_yuv(formats[i].fourcc) &&
+		    !coda_format_is_yuv(src_fourcc)) {
 			if (num == f->index)
 				break;
 			++num;
@@ -385,8 +437,10 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
 		}
 		/* Compressed formats may be supported, check the codec list */
 		for (k = 0; k < num_codecs; k++) {
+			/* if src_fourcc is set, only consider matching codecs */
 			if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-			    formats[i].fourcc == codecs[k].dst_fourcc)
+			    formats[i].fourcc == codecs[k].dst_fourcc &&
+			    (!src_fourcc || src_fourcc == codecs[k].src_fourcc))
 				break;
 			if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
 			    formats[i].fourcc == codecs[k].src_fourcc)
@@ -413,13 +467,26 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 				   struct v4l2_fmtdesc *f)
 {
-	return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *src_vq;
+	struct coda_q_data *q_data_src;
+
+	/* If the source format is already fixed, only list matching formats */
+	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	if (vb2_is_streaming(src_vq)) {
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+		return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				q_data_src->fourcc);
+	}
+
+	return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0);
 }
 
 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
 				   struct v4l2_fmtdesc *f)
 {
-	return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0);
 }
 
 static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
@@ -492,15 +559,45 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
-	struct coda_codec *codec = NULL;
+	struct coda_codec *codec;
+	struct vb2_queue *src_vq;
+	int ret;
 
-	/* Determine codec by the encoded format */
-	codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
-				f->fmt.pix.pixelformat);
+	/*
+	 * If the source format is already fixed, try to find a codec that
+	 * converts to the given destination format
+	 */
+	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	if (vb2_is_streaming(src_vq)) {
+		struct coda_q_data *q_data_src;
+
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
+					f->fmt.pix.pixelformat);
+		if (!codec)
+			return -EINVAL;
+	} else {
+		/* Otherwise determine codec by encoded format, if possible */
+		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
+					f->fmt.pix.pixelformat);
+	}
 
 	f->fmt.pix.colorspace = ctx->colorspace;
 
-	return vidioc_try_fmt(codec, f);
+	ret = vidioc_try_fmt(codec, f);
+	if (ret < 0)
+		return ret;
+
+	/* The h.264 decoder only returns complete 16x16 macroblocks */
+	if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) {
+		f->fmt.pix.width = round_up(f->fmt.pix.width, 16);
+		f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
+		f->fmt.pix.bytesperline = f->fmt.pix.width;
+		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+				       f->fmt.pix.height * 3 / 2;
+	}
+
+	return 0;
 }
 
 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
@@ -610,11 +707,35 @@ static int vidioc_expbuf(struct file *file, void *priv,
 	return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
 }
 
+static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx,
+				      struct v4l2_buffer *buf)
+{
+	struct vb2_queue *src_vq;
+
+	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+	return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) &&
+		(buf->sequence == (ctx->qsequence - 1)));
+}
+
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+
+	/* If this is the last capture buffer, emit an end-of-stream event */
+	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    coda_buf_is_end_of_stream(ctx, buf)) {
+		const struct v4l2_event eos_event = {
+			.type = V4L2_EVENT_EOS
+		};
+
+		v4l2_event_queue_fh(&ctx->fh, &eos_event);
+	}
 
-	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+	return ret;
 }
 
 static int vidioc_create_bufs(struct file *file, void *priv,
@@ -637,8 +758,53 @@ static int vidioc_streamoff(struct file *file, void *priv,
 			    enum v4l2_buf_type type)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	/*
+	 * This indirectly calls __vb2_queue_cancel, which dequeues all buffers.
+	 * We therefore have to lock it against running hardware in this context,
+	 * which still needs the buffers.
+	 */
+	mutex_lock(&ctx->buffer_mutex);
+	ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+	mutex_unlock(&ctx->buffer_mutex);
+
+	return ret;
+}
+
+static int vidioc_decoder_cmd(struct file *file, void *fh,
+			      struct v4l2_decoder_cmd *dc)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+
+	if (dc->cmd != V4L2_DEC_CMD_STOP)
+		return -EINVAL;
+
+	if ((dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK) ||
+	    (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY))
+		return -EINVAL;
+
+	if (dc->stop.pts != 0)
+		return -EINVAL;
+
+	if (ctx->inst_type != CODA_INST_DECODER)
+		return -EINVAL;
+
+	/* Set the strem-end flag on this context */
+	ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+
+	return 0;
+}
 
-	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+				  const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	default:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	}
 }
 
 static const struct v4l2_ioctl_ops coda_ioctl_ops = {
@@ -664,14 +830,206 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
 
 	.vidioc_streamon	= vidioc_streamon,
 	.vidioc_streamoff	= vidioc_streamoff,
+
+	.vidioc_decoder_cmd	= vidioc_decoder_cmd,
+
+	.vidioc_subscribe_event = vidioc_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
+static int coda_start_decoding(struct coda_ctx *ctx);
+
+static void coda_skip_run(struct work_struct *work)
+{
+	struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run);
+
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
+}
+
+static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
+{
+	return kfifo_len(&ctx->bitstream_fifo);
+}
+
+static void coda_kfifo_sync_from_device(struct coda_ctx *ctx)
+{
+	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
+	struct coda_dev *dev = ctx->dev;
+	u32 rd_ptr;
+
+	rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
+	kfifo->out = (kfifo->in & ~kfifo->mask) |
+		      (rd_ptr - ctx->bitstream.paddr);
+	if (kfifo->out > kfifo->in)
+		kfifo->out -= kfifo->mask + 1;
+}
+
+static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx)
+{
+	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
+	struct coda_dev *dev = ctx->dev;
+	u32 rd_ptr, wr_ptr;
+
+	rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask);
+	coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
+	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
+	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+}
+
+static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
+{
+	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
+	struct coda_dev *dev = ctx->dev;
+	u32 wr_ptr;
+
+	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
+	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+}
+
+static int coda_bitstream_queue(struct coda_ctx *ctx, struct vb2_buffer *src_buf)
+{
+	u32 src_size = vb2_get_plane_payload(src_buf, 0);
+	u32 n;
+
+	n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0), src_size);
+	if (n < src_size)
+		return -ENOSPC;
+
+	dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr,
+				   ctx->bitstream.size, DMA_TO_DEVICE);
+
+	ctx->qsequence++;
+
+	return 0;
+}
+
+static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
+				     struct vb2_buffer *src_buf)
+{
+	int ret;
+
+	if (coda_get_bitstream_payload(ctx) +
+	    vb2_get_plane_payload(src_buf, 0) + 512 >= ctx->bitstream.size)
+		return false;
+
+	if (vb2_plane_vaddr(src_buf, 0) == NULL) {
+		v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n");
+		return true;
+	}
+
+	ret = coda_bitstream_queue(ctx, src_buf);
+	if (ret < 0) {
+		v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n");
+		return false;
+	}
+	/* Sync read pointer to device */
+	if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
+		coda_kfifo_sync_to_device_write(ctx);
+
+	ctx->prescan_failed = false;
+
+	return true;
+}
+
+static void coda_fill_bitstream(struct coda_ctx *ctx)
+{
+	struct vb2_buffer *src_buf;
+
+	while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) {
+		src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+
+		if (coda_bitstream_try_queue(ctx, src_buf)) {
+			src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+		} else {
+			break;
+		}
+	}
+}
+
 /*
  * Mem-to-mem operations.
  */
-static void coda_device_run(void *m2m_priv)
+static int coda_prepare_decode(struct coda_ctx *ctx)
+{
+	struct vb2_buffer *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	struct coda_q_data *q_data_dst;
+	u32 stridey, height;
+	u32 picture_y, picture_cb, picture_cr;
+
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+	if (ctx->params.rot_mode & CODA_ROT_90) {
+		stridey = q_data_dst->height;
+		height = q_data_dst->width;
+	} else {
+		stridey = q_data_dst->width;
+		height = q_data_dst->height;
+	}
+
+	/* Try to copy source buffer contents into the bitstream ringbuffer */
+	mutex_lock(&ctx->bitstream_mutex);
+	coda_fill_bitstream(ctx);
+	mutex_unlock(&ctx->bitstream_mutex);
+
+	if (coda_get_bitstream_payload(ctx) < 512 &&
+	    (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+			 "bitstream payload: %d, skipping\n",
+			 coda_get_bitstream_payload(ctx));
+		schedule_work(&ctx->skip_run);
+		return -EAGAIN;
+	}
+
+	/* Run coda_start_decoding (again) if not yet initialized */
+	if (!ctx->initialized) {
+		int ret = coda_start_decoding(ctx);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
+			schedule_work(&ctx->skip_run);
+			return -EAGAIN;
+		} else {
+			ctx->initialized = 1;
+		}
+	}
+
+	/* Set rotator output */
+	picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
+		/* Switch Cr and Cb for YVU420 format */
+		picture_cr = picture_y + stridey * height;
+		picture_cb = picture_cr + stridey / 2 * height / 2;
+	} else {
+		picture_cb = picture_y + stridey * height;
+		picture_cr = picture_cb + stridey / 2 * height / 2;
+	}
+	coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
+	coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
+	coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
+	coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
+	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
+			CODA_CMD_DEC_PIC_ROT_MODE);
+
+	switch (dev->devtype->product) {
+	case CODA_DX6:
+		/* TBD */
+	case CODA_7541:
+		coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
+		break;
+	}
+
+	coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
+
+	coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START);
+	coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE);
+
+	return 0;
+}
+
+static void coda_prepare_encode(struct coda_ctx *ctx)
 {
-	struct coda_ctx *ctx = m2m_priv;
 	struct coda_q_data *q_data_src, *q_data_dst;
 	struct vb2_buffer *src_buf, *dst_buf;
 	struct coda_dev *dev = ctx->dev;
@@ -681,17 +1039,15 @@ static void coda_device_run(void *m2m_priv)
 	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
 	u32 dst_fourcc;
 
-	mutex_lock(&dev->coda_mutex);
-
 	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 	dst_fourcc = q_data_dst->fourcc;
 
-	src_buf->v4l2_buf.sequence = ctx->isequence;
-	dst_buf->v4l2_buf.sequence = ctx->isequence;
-	ctx->isequence++;
+	src_buf->v4l2_buf.sequence = ctx->osequence;
+	dst_buf->v4l2_buf.sequence = ctx->osequence;
+	ctx->osequence++;
 
 	/*
 	 * Workaround coda firmware BUG that only marks the first
@@ -793,16 +1149,53 @@ static void coda_device_run(void *m2m_priv)
 	coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START);
 	coda_write(dev, pic_stream_buffer_size / 1024,
 		   CODA_CMD_ENC_PIC_BB_SIZE);
+}
 
-	if (dev->devtype->product == CODA_7541) {
-		coda_write(dev, CODA7_USE_BIT_ENABLE | CODA7_USE_HOST_BIT_ENABLE |
-				CODA7_USE_ME_ENABLE | CODA7_USE_HOST_ME_ENABLE,
-				CODA7_REG_BIT_AXI_SRAM_USE);
+static void coda_device_run(void *m2m_priv)
+{
+	struct coda_ctx *ctx = m2m_priv;
+	struct coda_dev *dev = ctx->dev;
+	int ret;
+
+	mutex_lock(&ctx->buffer_mutex);
+
+	/*
+	 * If streamoff dequeued all buffers before we could get the lock,
+	 * just bail out immediately.
+	 */
+	if ((!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) &&
+	    ctx->inst_type != CODA_INST_DECODER) ||
+		!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+			"%d: device_run without buffers\n", ctx->idx);
+		mutex_unlock(&ctx->buffer_mutex);
+		schedule_work(&ctx->skip_run);
+		return;
+	}
+
+	mutex_lock(&dev->coda_mutex);
+
+	if (ctx->inst_type == CODA_INST_DECODER) {
+		ret = coda_prepare_decode(ctx);
+		if (ret < 0) {
+			mutex_unlock(&dev->coda_mutex);
+			mutex_unlock(&ctx->buffer_mutex);
+			/* job_finish scheduled by prepare_decode */
+			return;
+		}
+	} else {
+		coda_prepare_encode(ctx);
 	}
 
+	if (dev->devtype->product != CODA_DX6)
+		coda_write(dev, ctx->iram_info.axi_sram_use,
+				CODA7_REG_BIT_AXI_SRAM_USE);
+
 	/* 1 second timeout in case CODA locks up */
 	schedule_delayed_work(&dev->timeout, HZ);
 
+	if (ctx->inst_type == CODA_INST_DECODER)
+		coda_kfifo_sync_to_device_full(ctx);
 	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
 }
 
@@ -812,15 +1205,32 @@ static int coda_job_ready(void *m2m_priv)
 
 	/*
 	 * For both 'P' and 'key' frame cases 1 picture
-	 * and 1 frame are needed.
+	 * and 1 frame are needed. In the decoder case,
+	 * the compressed frame can be in the bitstream.
 	 */
-	if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) ||
-		!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
+	if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) &&
+	    ctx->inst_type != CODA_INST_DECODER) {
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			 "not ready: not enough video buffers.\n");
 		return 0;
 	}
 
+	if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
+		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+			 "not ready: not enough video capture buffers.\n");
+		return 0;
+	}
+
+	if (ctx->prescan_failed ||
+	    ((ctx->inst_type == CODA_INST_DECODER) &&
+	     (coda_get_bitstream_payload(ctx) < 512) &&
+	     !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
+		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+			 "%d: not ready: not enough bitstream data.\n",
+			 ctx->idx);
+		return 0;
+	}
+
 	if (ctx->aborting) {
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			 "not ready: aborting\n");
@@ -936,7 +1346,29 @@ static int coda_buf_prepare(struct vb2_buffer *vb)
 static void coda_buf_queue(struct vb2_buffer *vb)
 {
 	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+	struct coda_q_data *q_data;
+
+	q_data = get_q_data(ctx, vb->vb2_queue->type);
+
+	/*
+	 * In the decoder case, immediately try to copy the buffer into the
+	 * bitstream ringbuffer and mark it as ready to be dequeued.
+	 */
+	if (q_data->fourcc == V4L2_PIX_FMT_H264 &&
+	    vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		/*
+		 * For backwards compatiblity, queuing an empty buffer marks
+		 * the stream end
+		 */
+		if (vb2_get_plane_payload(vb, 0) == 0)
+			ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+		mutex_lock(&ctx->bitstream_mutex);
+		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+		coda_fill_bitstream(ctx);
+		mutex_unlock(&ctx->bitstream_mutex);
+	} else {
+		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+	}
 }
 
 static void coda_wait_prepare(struct vb2_queue *q)
@@ -951,88 +1383,488 @@ static void coda_wait_finish(struct vb2_queue *q)
 	coda_lock(ctx);
 }
 
+static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
+{
+	struct coda_dev *dev = ctx->dev;
+	u32 *p = ctx->parabuf.vaddr;
+
+	if (dev->devtype->product == CODA_DX6)
+		p[index] = value;
+	else
+		p[index ^ 1] = value;
+}
+
+static int coda_alloc_aux_buf(struct coda_dev *dev,
+			      struct coda_aux_buf *buf, size_t size)
+{
+	buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr,
+					GFP_KERNEL);
+	if (!buf->vaddr)
+		return -ENOMEM;
+
+	buf->size = size;
+
+	return 0;
+}
+
+static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
+					 struct coda_aux_buf *buf, size_t size)
+{
+	return coda_alloc_aux_buf(ctx->dev, buf, size);
+}
+
+static void coda_free_aux_buf(struct coda_dev *dev,
+			      struct coda_aux_buf *buf)
+{
+	if (buf->vaddr) {
+		dma_free_coherent(&dev->plat_dev->dev, buf->size,
+				  buf->vaddr, buf->paddr);
+		buf->vaddr = NULL;
+		buf->size = 0;
+	}
+}
+
 static void coda_free_framebuffers(struct coda_ctx *ctx)
 {
 	int i;
 
-	for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) {
-		if (ctx->internal_frames[i].vaddr) {
-			dma_free_coherent(&ctx->dev->plat_dev->dev,
-				ctx->internal_frames[i].size,
-				ctx->internal_frames[i].vaddr,
-				ctx->internal_frames[i].paddr);
-			ctx->internal_frames[i].vaddr = NULL;
+	for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++)
+		coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]);
+}
+
+static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc)
+{
+	struct coda_dev *dev = ctx->dev;
+	int height = q_data->height;
+	dma_addr_t paddr;
+	int ysize;
+	int ret;
+	int i;
+
+	if (ctx->codec && ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
+		height = round_up(height, 16);
+	ysize = round_up(q_data->width, 8) * height;
+
+	/* Allocate frame buffers */
+	for (i = 0; i < ctx->num_internal_frames; i++) {
+		size_t size;
+
+		size = q_data->sizeimage;
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
+		    dev->devtype->product != CODA_DX6)
+			ctx->internal_frames[i].size += ysize/4;
+		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size);
+		if (ret < 0) {
+			coda_free_framebuffers(ctx);
+			return ret;
 		}
 	}
+
+	/* Register frame buffers in the parameter buffer */
+	for (i = 0; i < ctx->num_internal_frames; i++) {
+		paddr = ctx->internal_frames[i].paddr;
+		coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */
+		coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */
+		coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */
+
+		/* mvcol buffer for h.264 */
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
+		    dev->devtype->product != CODA_DX6)
+			coda_parabuf_write(ctx, 96 + i,
+					   ctx->internal_frames[i].paddr +
+					   ysize + ysize/4 + ysize/4);
+	}
+
+	/* mvcol buffer for mpeg4 */
+	if ((dev->devtype->product != CODA_DX6) &&
+	    (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4))
+		coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr +
+					    ysize + ysize/4 + ysize/4);
+
+	return 0;
 }
 
-static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
+static int coda_h264_padding(int size, char *p)
+{
+	int nal_size;
+	int diff;
+
+	diff = size - (size & ~0x7);
+	if (diff == 0)
+		return 0;
+
+	nal_size = coda_filler_size[diff];
+	memcpy(p, coda_filler_nal, nal_size);
+
+	/* Add rbsp stop bit and trailing at the end */
+	*(p + nal_size - 1) = 0x80;
+
+	return nal_size;
+}
+
+static void coda_setup_iram(struct coda_ctx *ctx)
 {
+	struct coda_iram_info *iram_info = &ctx->iram_info;
 	struct coda_dev *dev = ctx->dev;
-	u32 *p = ctx->parabuf.vaddr;
+	int ipacdc_size;
+	int bitram_size;
+	int dbk_size;
+	int ovl_size;
+	int mb_width;
+	int me_size;
+	int size;
+
+	memset(iram_info, 0, sizeof(*iram_info));
+	size = dev->iram_size;
 
 	if (dev->devtype->product == CODA_DX6)
-		p[index] = value;
-	else
-		p[index ^ 1] = value;
+		return;
+
+	if (ctx->inst_type == CODA_INST_ENCODER) {
+		struct coda_q_data *q_data_src;
+
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		mb_width = DIV_ROUND_UP(q_data_src->width, 16);
+
+		/* Prioritize in case IRAM is too small for everything */
+		me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048,
+				   1024);
+		iram_info->search_ram_size = me_size;
+		if (size >= iram_info->search_ram_size) {
+			if (dev->devtype->product == CODA_7541)
+				iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE;
+			iram_info->search_ram_paddr = dev->iram_paddr;
+			size -= iram_info->search_ram_size;
+		} else {
+			pr_err("IRAM is smaller than the search ram size\n");
+			goto out;
+		}
+
+		/* Only H.264BP and H.263P3 are considered */
+		dbk_size = round_up(128 * mb_width, 1024);
+		if (size >= dbk_size) {
+			iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
+			iram_info->buf_dbk_y_use = dev->iram_paddr +
+						   iram_info->search_ram_size;
+			iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use +
+						   dbk_size / 2;
+			size -= dbk_size;
+		} else {
+			goto out;
+		}
+
+		bitram_size = round_up(128 * mb_width, 1024);
+		if (size >= bitram_size) {
+			iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
+			iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
+						 dbk_size / 2;
+			size -= bitram_size;
+		} else {
+			goto out;
+		}
+
+		ipacdc_size = round_up(128 * mb_width, 1024);
+		if (size >= ipacdc_size) {
+			iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
+			iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
+						      bitram_size;
+			size -= ipacdc_size;
+		}
+
+		/* OVL and BTP disabled for encoder */
+	} else if (ctx->inst_type == CODA_INST_DECODER) {
+		struct coda_q_data *q_data_dst;
+		int mb_height;
+
+		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
+		mb_height = DIV_ROUND_UP(q_data_dst->height, 16);
+
+		dbk_size = round_up(256 * mb_width, 1024);
+		if (size >= dbk_size) {
+			iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
+			iram_info->buf_dbk_y_use = dev->iram_paddr;
+			iram_info->buf_dbk_c_use = dev->iram_paddr +
+						   dbk_size / 2;
+			size -= dbk_size;
+		} else {
+			goto out;
+		}
+
+		bitram_size = round_up(128 * mb_width, 1024);
+		if (size >= bitram_size) {
+			iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
+			iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
+						 dbk_size / 2;
+			size -= bitram_size;
+		} else {
+			goto out;
+		}
+
+		ipacdc_size = round_up(128 * mb_width, 1024);
+		if (size >= ipacdc_size) {
+			iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
+			iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
+						      bitram_size;
+			size -= ipacdc_size;
+		} else {
+			goto out;
+		}
+
+		ovl_size = round_up(80 * mb_width, 1024);
+	}
+
+out:
+	switch (dev->devtype->product) {
+	case CODA_DX6:
+		break;
+	case CODA_7541:
+		/* i.MX53 uses secondary AXI for IRAM access */
+		if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE)
+			iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE;
+		if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)
+			iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE;
+		if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE)
+			iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE;
+		if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE)
+			iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE;
+		if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE)
+			iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE;
+	}
+
+	if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
+		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+			 "IRAM smaller than needed\n");
+
+	if (dev->devtype->product == CODA_7541) {
+		/* TODO - Enabling these causes picture errors on CODA7541 */
+		if (ctx->inst_type == CODA_INST_DECODER) {
+			/* fw 1.4.50 */
+			iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE |
+						     CODA7_USE_IP_ENABLE);
+		} else {
+			/* fw 13.4.29 */
+			iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE |
+						     CODA7_USE_HOST_DBK_ENABLE |
+						     CODA7_USE_IP_ENABLE |
+						     CODA7_USE_DBK_ENABLE);
+		}
+	}
 }
 
-static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc)
+static void coda_free_context_buffers(struct coda_ctx *ctx)
 {
 	struct coda_dev *dev = ctx->dev;
 
-	int height = q_data->height;
-	dma_addr_t paddr;
-	int ysize;
-	int i;
+	coda_free_aux_buf(dev, &ctx->slicebuf);
+	coda_free_aux_buf(dev, &ctx->psbuf);
+	if (dev->devtype->product != CODA_DX6)
+		coda_free_aux_buf(dev, &ctx->workbuf);
+}
+
+static int coda_alloc_context_buffers(struct coda_ctx *ctx,
+				      struct coda_q_data *q_data)
+{
+	struct coda_dev *dev = ctx->dev;
+	size_t size;
+	int ret;
+
+	switch (dev->devtype->product) {
+	case CODA_7541:
+		size = CODA7_WORK_BUF_SIZE;
+		break;
+	default:
+		return 0;
+	}
+
+	if (ctx->psbuf.vaddr) {
+		v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n");
+		return -EBUSY;
+	}
+	if (ctx->slicebuf.vaddr) {
+		v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n");
+		return -EBUSY;
+	}
+	if (ctx->workbuf.vaddr) {
+		v4l2_err(&dev->v4l2_dev, "context buffer still allocated\n");
+		ret = -EBUSY;
+		return -ENOMEM;
+	}
+
+	if (q_data->fourcc == V4L2_PIX_FMT_H264) {
+		/* worst case slice size */
+		size = (DIV_ROUND_UP(q_data->width, 16) *
+			DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
+		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer",
+				 ctx->slicebuf.size);
+			return ret;
+		}
+	}
+
+	if (dev->devtype->product == CODA_7541) {
+		ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer");
+			goto err;
+		}
+	}
+
+	ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer",
+			 ctx->workbuf.size);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	coda_free_context_buffers(ctx);
+	return ret;
+}
+
+static int coda_start_decoding(struct coda_ctx *ctx)
+{
+	struct coda_q_data *q_data_src, *q_data_dst;
+	u32 bitstream_buf, bitstream_size;
+	struct coda_dev *dev = ctx->dev;
+	int width, height;
+	u32 src_fourcc;
+	u32 val;
+	int ret;
+
+	/* Start decoding */
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	bitstream_buf = ctx->bitstream.paddr;
+	bitstream_size = ctx->bitstream.size;
+	src_fourcc = q_data_src->fourcc;
+
+	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
+
+	/* Update coda bitstream read and write pointers from kfifo */
+	coda_kfifo_sync_to_device_full(ctx);
+
+	ctx->display_idx = -1;
+	ctx->frm_dis_flg = 0;
+	coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+
+	coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE,
+			CODA_REG_BIT_BIT_STREAM_PARAM);
+
+	coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
+	coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
+	val = 0;
+	if (dev->devtype->product == CODA_7541)
+		val |= CODA_REORDER_ENABLE;
+	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
+
+	ctx->params.codec_mode = ctx->codec->mode;
+	ctx->params.codec_mode_aux = 0;
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		if (dev->devtype->product == CODA_7541) {
+			coda_write(dev, ctx->psbuf.paddr,
+					CODA_CMD_DEC_SEQ_PS_BB_START);
+			coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
+					CODA_CMD_DEC_SEQ_PS_BB_SIZE);
+		}
+	}
+
+	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
+		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
+		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
+		return -ETIMEDOUT;
+	}
+
+	/* Update kfifo out pointer from coda bitstream read pointer */
+	coda_kfifo_sync_from_device(ctx);
 
-	ysize = round_up(q_data->width, 8) * height;
+	coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
 
-	/* Allocate frame buffers */
-	ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS;
-	for (i = 0; i < ctx->num_internal_frames; i++) {
-		ctx->internal_frames[i].size = q_data->sizeimage;
-		if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6)
-			ctx->internal_frames[i].size += ysize/4;
-		ctx->internal_frames[i].vaddr = dma_alloc_coherent(
-				&dev->plat_dev->dev, ctx->internal_frames[i].size,
-				&ctx->internal_frames[i].paddr, GFP_KERNEL);
-		if (!ctx->internal_frames[i].vaddr) {
-			coda_free_framebuffers(ctx);
-			return -ENOMEM;
-		}
+	if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) {
+		v4l2_err(&dev->v4l2_dev,
+			"CODA_COMMAND_SEQ_INIT failed, error code = %d\n",
+			coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON));
+		return -EAGAIN;
 	}
 
-	/* Register frame buffers in the parameter buffer */
-	for (i = 0; i < ctx->num_internal_frames; i++) {
-		paddr = ctx->internal_frames[i].paddr;
-		coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */
-		coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */
-		coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */
+	val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE);
+	if (dev->devtype->product == CODA_DX6) {
+		width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK;
+		height = val & CODADX6_PICHEIGHT_MASK;
+	} else {
+		width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK;
+		height = val & CODA7_PICHEIGHT_MASK;
+	}
 
-		if (dev->devtype->product != CODA_DX6 && fourcc == V4L2_PIX_FMT_H264)
-			coda_parabuf_write(ctx, 96 + i, ctx->internal_frames[i].paddr + ysize + ysize/4 + ysize/4);
+	if (width > q_data_dst->width || height > q_data_dst->height) {
+		v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n",
+			 width, height, q_data_dst->width, q_data_dst->height);
+		return -EINVAL;
 	}
 
-	return 0;
-}
+	width = round_up(width, 16);
+	height = round_up(height, 16);
 
-static int coda_h264_padding(int size, char *p)
-{
-	int nal_size;
-	int diff;
+	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n",
+		 __func__, ctx->idx, width, height);
 
-	diff = size - (size & ~0x7);
-	if (diff == 0)
-		return 0;
+	ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1;
+	if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
+		v4l2_err(&dev->v4l2_dev,
+			 "not enough framebuffers to decode (%d < %d)\n",
+			 CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames);
+		return -EINVAL;
+	}
 
-	nal_size = coda_filler_size[diff];
-	memcpy(p, coda_filler_nal, nal_size);
+	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
+	if (ret < 0)
+		return ret;
 
-	/* Add rbsp stop bit and trailing at the end */
-	*(p + nal_size - 1) = 0x80;
+	/* Tell the decoder how many frame buffers we allocated. */
+	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
+	coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE);
 
-	return nal_size;
+	if (dev->devtype->product != CODA_DX6) {
+		/* Set secondary AXI IRAM */
+		coda_setup_iram(ctx);
+
+		coda_write(dev, ctx->iram_info.buf_bit_use,
+				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
+				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ovl_use,
+				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+	}
+
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		coda_write(dev, ctx->slicebuf.paddr,
+				CODA_CMD_SET_FRAME_SLICE_BB_START);
+		coda_write(dev, ctx->slicebuf.size / 1024,
+				CODA_CMD_SET_FRAME_SLICE_BB_SIZE);
+	}
+
+	if (dev->devtype->product == CODA_7541) {
+		int max_mb_x = 1920 / 16;
+		int max_mb_y = 1088 / 16;
+		int max_mb_num = max_mb_x * max_mb_y;
+		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
+				CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
+	}
+
+	if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "CODA_COMMAND_SET_FRAME_BUF timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
 }
 
 static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
@@ -1050,7 +1882,7 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
 		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
 		return ret;
 	}
-	*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) -
+	*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
 		coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
 	memcpy(header, vb2_plane_vaddr(buf, 0), *size);
 
@@ -1069,26 +1901,36 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 	u32 value;
 	int ret = 0;
 
-	if (count < 1)
-		return -EINVAL;
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		if (q_data_src->fourcc == V4L2_PIX_FMT_H264) {
+			if (coda_get_bitstream_payload(ctx) < 512)
+				return -EINVAL;
+		} else {
+			if (count < 1)
+				return -EINVAL;
+		}
 
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
 		ctx->streamon_out = 1;
-	else
-		ctx->streamon_cap = 1;
 
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	if (ctx->streamon_out) {
 		if (coda_format_is_yuv(q_data_src->fourcc))
 			ctx->inst_type = CODA_INST_ENCODER;
 		else
 			ctx->inst_type = CODA_INST_DECODER;
+	} else {
+		if (count < 1)
+			return -EINVAL;
+
+		ctx->streamon_cap = 1;
 	}
 
 	/* Don't start the coda unless both queues are on */
 	if (!(ctx->streamon_out & ctx->streamon_cap))
 		return 0;
 
+	/* Allow device_run with no buffers queued and after streamoff */
+	v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true);
+
 	ctx->gopcounter = ctx->params.gop_size - 1;
 	buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 	bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
@@ -1103,6 +1945,25 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 		return -EINVAL;
 	}
 
+	/* Allocate per-instance buffers */
+	ret = coda_alloc_context_buffers(ctx, q_data_src);
+	if (ret < 0)
+		return ret;
+
+	if (ctx->inst_type == CODA_INST_DECODER) {
+		mutex_lock(&dev->coda_mutex);
+		ret = coda_start_decoding(ctx);
+		mutex_unlock(&dev->coda_mutex);
+		if (ret == -EAGAIN) {
+			return 0;
+		} else if (ret < 0) {
+			return ret;
+		} else {
+			ctx->initialized = 1;
+			return 0;
+		}
+	}
+
 	if (!coda_is_initialized(dev)) {
 		v4l2_err(v4l2_dev, "coda is not initialized.\n");
 		return -EFAULT;
@@ -1111,8 +1972,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 	mutex_lock(&dev->coda_mutex);
 
 	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
-	coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx));
-	coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx));
+	coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
+	coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
 	switch (dev->devtype->product) {
 	case CODA_DX6:
 		coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
@@ -1207,6 +2068,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 	}
 	coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
 
+	coda_setup_iram(ctx);
+
 	if (dst_fourcc == V4L2_PIX_FMT_H264) {
 		value  = (FMO_SLICE_SAVE_BUF_SIZE << 7);
 		value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET;
@@ -1214,8 +2077,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 		if (dev->devtype->product == CODA_DX6) {
 			coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
 		} else {
-			coda_write(dev, dev->iram_paddr, CODA7_CMD_ENC_SEQ_SEARCH_BASE);
-			coda_write(dev, 48 * 1024, CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
+			coda_write(dev, ctx->iram_info.search_ram_paddr,
+					CODA7_CMD_ENC_SEQ_SEARCH_BASE);
+			coda_write(dev, ctx->iram_info.search_ram_size,
+					CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
 		}
 	}
 
@@ -1231,6 +2096,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 		goto out;
 	}
 
+	ctx->num_internal_frames = 2;
 	ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
 	if (ret < 0) {
 		v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
@@ -1239,13 +2105,20 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 
 	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
 	coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE);
+	if (dev->devtype->product == CODA_7541)
+		coda_write(dev, round_up(q_data_src->width, 8),
+				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
 	if (dev->devtype->product != CODA_DX6) {
-		coda_write(dev, round_up(q_data_src->width, 8), CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
-		coda_write(dev, dev->iram_paddr + 48 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
-		coda_write(dev, dev->iram_paddr + 53 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
-		coda_write(dev, dev->iram_paddr + 58 * 1024, CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
-		coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
-		coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+		coda_write(dev, ctx->iram_info.buf_bit_use,
+				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
+				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ovl_use,
+				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
 	}
 	ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
 	if (ret < 0) {
@@ -1326,32 +2199,26 @@ static int coda_stop_streaming(struct vb2_queue *q)
 	struct coda_dev *dev = ctx->dev;
 
 	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 			 "%s: output\n", __func__);
 		ctx->streamon_out = 0;
+
+		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+
+		ctx->isequence = 0;
 	} else {
-		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 			 "%s: capture\n", __func__);
 		ctx->streamon_cap = 0;
-	}
-
-	/* Don't stop the coda unless both queues are off */
-	if (ctx->streamon_out || ctx->streamon_cap)
-		return 0;
 
-	cancel_delayed_work(&dev->timeout);
-
-	mutex_lock(&dev->coda_mutex);
-	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
-		 "%s: sent command 'SEQ_END' to coda\n", __func__);
-	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
-		v4l2_err(&dev->v4l2_dev,
-			 "CODA_COMMAND_SEQ_END failed\n");
-		return -ETIMEDOUT;
+		ctx->osequence = 0;
 	}
-	mutex_unlock(&dev->coda_mutex);
 
-	coda_free_framebuffers(ctx);
+	if (!ctx->streamon_out && !ctx->streamon_cap) {
+		kfifo_init(&ctx->bitstream_fifo,
+			ctx->bitstream.vaddr, ctx->bitstream.size);
+		ctx->runcounter = 0;
+	}
 
 	return 0;
 }
@@ -1511,7 +2378,7 @@ static int coda_open(struct file *file)
 {
 	struct coda_dev *dev = video_drvdata(file);
 	struct coda_ctx *ctx = NULL;
-	int ret = 0;
+	int ret;
 	int idx;
 
 	idx = coda_next_free_instance(dev);
@@ -1523,12 +2390,19 @@ static int coda_open(struct file *file)
 	if (!ctx)
 		return -ENOMEM;
 
+	INIT_WORK(&ctx->skip_run, coda_skip_run);
 	v4l2_fh_init(&ctx->fh, video_devdata(file));
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
 	ctx->dev = dev;
 	ctx->idx = idx;
-
+	switch (dev->devtype->product) {
+	case CODA_7541:
+		ctx->reg_idx = 0;
+		break;
+	default:
+		ctx->reg_idx = idx;
+	}
 	set_default_params(ctx);
 	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
 					 &coda_queue_init);
@@ -1547,13 +2421,24 @@ static int coda_open(struct file *file)
 
 	ctx->fh.ctrl_handler = &ctx->ctrls;
 
-	ctx->parabuf.vaddr = dma_alloc_coherent(&dev->plat_dev->dev,
-			CODA_PARA_BUF_SIZE, &ctx->parabuf.paddr, GFP_KERNEL);
-	if (!ctx->parabuf.vaddr) {
+	ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE);
+	if (ret < 0) {
 		v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
+		goto err;
+	}
+
+	ctx->bitstream.size = CODA_MAX_FRAME_SIZE;
+	ctx->bitstream.vaddr = dma_alloc_writecombine(&dev->plat_dev->dev,
+			ctx->bitstream.size, &ctx->bitstream.paddr, GFP_KERNEL);
+	if (!ctx->bitstream.vaddr) {
+		v4l2_err(&dev->v4l2_dev, "failed to allocate bitstream ringbuffer");
 		ret = -ENOMEM;
 		goto err;
 	}
+	kfifo_init(&ctx->bitstream_fifo,
+		ctx->bitstream.vaddr, ctx->bitstream.size);
+	mutex_init(&ctx->bitstream_mutex);
+	mutex_init(&ctx->buffer_mutex);
 
 	coda_lock(ctx);
 	list_add(&ctx->list, &dev->instances);
@@ -1582,13 +2467,34 @@ static int coda_release(struct file *file)
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
 		 ctx);
 
+	/* If this instance is running, call .job_abort and wait for it to end */
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+
+	/* In case the instance was not running, we still need to call SEQ_END */
+	mutex_lock(&dev->coda_mutex);
+	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+		 "%s: sent command 'SEQ_END' to coda\n", __func__);
+	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
+		v4l2_err(&dev->v4l2_dev,
+			 "CODA_COMMAND_SEQ_END failed\n");
+		mutex_unlock(&dev->coda_mutex);
+		return -ETIMEDOUT;
+	}
+	mutex_unlock(&dev->coda_mutex);
+
+	coda_free_framebuffers(ctx);
+
 	coda_lock(ctx);
 	list_del(&ctx->list);
 	coda_unlock(ctx);
 
-	dma_free_coherent(&dev->plat_dev->dev, CODA_PARA_BUF_SIZE,
-		ctx->parabuf.vaddr, ctx->parabuf.paddr);
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
+		ctx->bitstream.vaddr, ctx->bitstream.paddr);
+	coda_free_context_buffers(ctx);
+	if (ctx->dev->devtype->product == CODA_DX6)
+		coda_free_aux_buf(dev, &ctx->workbuf);
+
+	coda_free_aux_buf(dev, &ctx->parabuf);
 	v4l2_ctrl_handler_free(&ctx->ctrls);
 	clk_disable_unprepare(dev->clk_per);
 	clk_disable_unprepare(dev->clk_ahb);
@@ -1628,55 +2534,180 @@ static const struct v4l2_file_operations coda_fops = {
 	.mmap		= coda_mmap,
 };
 
-static irqreturn_t coda_irq_handler(int irq, void *data)
+static void coda_finish_decode(struct coda_ctx *ctx)
 {
-	struct vb2_buffer *src_buf, *dst_buf;
-	struct coda_dev *dev = data;
-	u32 wr_ptr, start_ptr;
-	struct coda_ctx *ctx;
+	struct coda_dev *dev = ctx->dev;
+	struct coda_q_data *q_data_src;
+	struct coda_q_data *q_data_dst;
+	struct vb2_buffer *dst_buf;
+	int width, height;
+	int decoded_idx;
+	int display_idx;
+	u32 src_fourcc;
+	int success;
+	u32 val;
 
-	cancel_delayed_work(&dev->timeout);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 
-	/* read status register to attend the IRQ */
-	coda_read(dev, CODA_REG_BIT_INT_STATUS);
-	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
-		      CODA_REG_BIT_INT_CLEAR);
+	/* Update kfifo out pointer from coda bitstream read pointer */
+	coda_kfifo_sync_from_device(ctx);
 
-	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
-	if (ctx == NULL) {
-		v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n");
-		mutex_unlock(&dev->coda_mutex);
-		return IRQ_HANDLED;
+	/*
+	 * in stream-end mode, the read pointer can overshoot the write pointer
+	 * by up to 512 bytes
+	 */
+	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) {
+		if (coda_get_bitstream_payload(ctx) >= 0x100000 - 512)
+			kfifo_init(&ctx->bitstream_fifo,
+				ctx->bitstream.vaddr, ctx->bitstream.size);
 	}
 
-	if (ctx->aborting) {
-		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
-			 "task has been aborted\n");
-		mutex_unlock(&dev->coda_mutex);
-		return IRQ_HANDLED;
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	src_fourcc = q_data_src->fourcc;
+
+	val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS);
+	if (val != 1)
+		pr_err("DEC_PIC_SUCCESS = %d\n", val);
+
+	success = val & 0x1;
+	if (!success)
+		v4l2_err(&dev->v4l2_dev, "decode failed\n");
+
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		if (val & (1 << 3))
+			v4l2_err(&dev->v4l2_dev,
+				 "insufficient PS buffer space (%d bytes)\n",
+				 ctx->psbuf.size);
+		if (val & (1 << 2))
+			v4l2_err(&dev->v4l2_dev,
+				 "insufficient slice buffer space (%d bytes)\n",
+				 ctx->slicebuf.size);
 	}
 
-	if (coda_isbusy(ctx->dev)) {
-		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
-			 "coda is still busy!!!!\n");
-		return IRQ_NONE;
+	val = coda_read(dev, CODA_RET_DEC_PIC_SIZE);
+	width = (val >> 16) & 0xffff;
+	height = val & 0xffff;
+
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+	val = coda_read(dev, CODA_RET_DEC_PIC_TYPE);
+	if ((val & 0x7) == 0) {
+		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
+	} else {
+		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+	}
+
+	val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
+	if (val > 0)
+		v4l2_err(&dev->v4l2_dev,
+			 "errors in %d macroblocks\n", val);
+
+	if (dev->devtype->product == CODA_7541) {
+		val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
+		if (val == 0) {
+			/* not enough bitstream data */
+			v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+				 "prescan failed: %d\n", val);
+			ctx->prescan_failed = true;
+			return;
+		}
+	}
+
+	ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+
+	/*
+	 * The previous display frame was copied out by the rotator,
+	 * now it can be overwritten again
+	 */
+	if (ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
+		coda_write(dev, ctx->frm_dis_flg,
+				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+	}
+
+	/*
+	 * The index of the last decoded frame, not necessarily in
+	 * display order, and the index of the next display frame.
+	 * The latter could have been decoded in a previous run.
+	 */
+	decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX);
+	display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX);
+
+	if (decoded_idx == -1) {
+		/* no frame was decoded, but we might have a display frame */
+		if (display_idx < 0 && ctx->display_idx < 0)
+			ctx->prescan_failed = true;
+	} else if (decoded_idx == -2) {
+		/* no frame was decoded, we still return the remaining buffers */
+	} else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
+		v4l2_err(&dev->v4l2_dev,
+			 "decoded frame index out of range: %d\n", decoded_idx);
+	}
+
+	if (display_idx == -1) {
+		/*
+		 * no more frames to be decoded, but there could still
+		 * be rotator output to dequeue
+		 */
+		ctx->prescan_failed = true;
+	} else if (display_idx == -3) {
+		/* possibly prescan failure */
+	} else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) {
+		v4l2_err(&dev->v4l2_dev,
+			 "presentation frame index out of range: %d\n",
+			 display_idx);
+	}
+
+	/* If a frame was copied out, return it */
+	if (ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		dst_buf->v4l2_buf.sequence = ctx->osequence++;
+
+		vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
+
+		v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE :
+						     VB2_BUF_STATE_ERROR);
+
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+			"job finished: decoding frame (%d) (%s)\n",
+			dst_buf->v4l2_buf.sequence,
+			(dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
+			"KEYFRAME" : "PFRAME");
+	} else {
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+			"job finished: no frame decoded\n");
 	}
 
+	/* The rotator will copy the current display frame next time */
+	ctx->display_idx = display_idx;
+}
+
+static void coda_finish_encode(struct coda_ctx *ctx)
+{
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	u32 wr_ptr, start_ptr;
+
 	src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
 	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
 
 	/* Get results from the coda */
 	coda_read(dev, CODA_RET_ENC_PIC_TYPE);
 	start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
-	wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx));
+	wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+
 	/* Calculate bytesused field */
 	if (dst_buf->v4l2_buf.sequence == 0) {
-		dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr) +
-						ctx->vpu_header_size[0] +
-						ctx->vpu_header_size[1] +
-						ctx->vpu_header_size[2];
+		vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr +
+					ctx->vpu_header_size[0] +
+					ctx->vpu_header_size[1] +
+					ctx->vpu_header_size[2]);
 	} else {
-		dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr);
+		vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr);
 	}
 
 	v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n",
@@ -1708,8 +2739,62 @@ static irqreturn_t coda_irq_handler(int irq, void *data)
 		dst_buf->v4l2_buf.sequence,
 		(dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
 		"KEYFRAME" : "PFRAME");
+}
+
+static irqreturn_t coda_irq_handler(int irq, void *data)
+{
+	struct coda_dev *dev = data;
+	struct coda_ctx *ctx;
+
+	cancel_delayed_work(&dev->timeout);
+
+	/* read status register to attend the IRQ */
+	coda_read(dev, CODA_REG_BIT_INT_STATUS);
+	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
+		      CODA_REG_BIT_INT_CLEAR);
+
+	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+	if (ctx == NULL) {
+		v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n");
+		mutex_unlock(&dev->coda_mutex);
+		return IRQ_HANDLED;
+	}
+
+	if (ctx->aborting) {
+		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+			 "task has been aborted\n");
+		goto out;
+	}
+
+	if (coda_isbusy(ctx->dev)) {
+		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+			 "coda is still busy!!!!\n");
+		return IRQ_NONE;
+	}
+
+	if (ctx->inst_type == CODA_INST_DECODER)
+		coda_finish_decode(ctx);
+	else
+		coda_finish_encode(ctx);
+
+out:
+	if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) {
+		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+			 "%s: sent command 'SEQ_END' to coda\n", __func__);
+		if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
+			v4l2_err(&dev->v4l2_dev,
+				 "CODA_COMMAND_SEQ_END failed\n");
+		}
+
+		kfifo_init(&ctx->bitstream_fifo,
+			ctx->bitstream.vaddr, ctx->bitstream.size);
+
+		coda_free_framebuffers(ctx);
+		coda_free_context_buffers(ctx);
+	}
 
 	mutex_unlock(&dev->coda_mutex);
+	mutex_unlock(&ctx->buffer_mutex);
 
 	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
 
@@ -1726,6 +2811,8 @@ static void coda_timeout(struct work_struct *work)
 
 	mutex_lock(&dev->dev_mutex);
 	list_for_each_entry(ctx, &dev->instances, list) {
+		if (mutex_is_locked(&ctx->buffer_mutex))
+			mutex_unlock(&ctx->buffer_mutex);
 		v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 		v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 	}
@@ -1738,7 +2825,7 @@ static void coda_timeout(struct work_struct *work)
 
 static u32 coda_supported_firmwares[] = {
 	CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
-	CODA_FIRMWARE_VERNUM(CODA_7541, 13, 4, 29),
+	CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
 };
 
 static bool coda_firmware_supported(u32 vernum)
@@ -1803,8 +2890,14 @@ static int coda_hw_init(struct coda_dev *dev)
 		coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4);
 
 	/* Tell the BIT where to find everything it needs */
-	coda_write(dev, dev->workbuf.paddr,
-		      CODA_REG_BIT_WORK_BUF_ADDR);
+	if (dev->devtype->product == CODA_7541) {
+		coda_write(dev, dev->tempbuf.paddr,
+				CODA_REG_BIT_TEMP_BUF_ADDR);
+		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
+	} else {
+		coda_write(dev, dev->workbuf.paddr,
+			      CODA_REG_BIT_WORK_BUF_ADDR);
+	}
 	coda_write(dev, dev->codebuf.paddr,
 		      CODA_REG_BIT_CODE_BUF_ADDR);
 	coda_write(dev, 0, CODA_REG_BIT_CODE_RUN);
@@ -1891,11 +2984,8 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
 	}
 
 	/* allocate auxiliary per-device code buffer for the BIT processor */
-	dev->codebuf.size = fw->size;
-	dev->codebuf.vaddr = dma_alloc_coherent(&pdev->dev, fw->size,
-						    &dev->codebuf.paddr,
-						    GFP_KERNEL);
-	if (!dev->codebuf.vaddr) {
+	ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size);
+	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to allocate code buffer\n");
 		return;
 	}
@@ -1987,7 +3077,7 @@ MODULE_DEVICE_TABLE(platform, coda_platform_ids);
 
 #ifdef CONFIG_OF
 static const struct of_device_id coda_dt_ids[] = {
-	{ .compatible = "fsl,imx27-vpu", .data = &coda_platform_ids[CODA_IMX27] },
+	{ .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] },
 	{ .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
 	{ /* sentinel */ }
 };
@@ -2048,8 +3138,8 @@ static int coda_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	if (devm_request_irq(&pdev->dev, irq, coda_irq_handler,
-		0, CODA_NAME, dev) < 0) {
+	if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler,
+		IRQF_ONESHOT, CODA_NAME, dev) < 0) {
 		dev_err(&pdev->dev, "failed to request irq\n");
 		return -ENOENT;
 	}
@@ -2085,24 +3175,36 @@ static int coda_probe(struct platform_device *pdev)
 	/* allocate auxiliary per-device buffers for the BIT processor */
 	switch (dev->devtype->product) {
 	case CODA_DX6:
-		dev->workbuf.size = CODADX6_WORK_BUF_SIZE;
+		ret = coda_alloc_aux_buf(dev, &dev->workbuf,
+					 CODADX6_WORK_BUF_SIZE);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to allocate work buffer\n");
+			v4l2_device_unregister(&dev->v4l2_dev);
+			return ret;
+		}
+		break;
+	case CODA_7541:
+		dev->tempbuf.size = CODA7_TEMP_BUF_SIZE;
 		break;
-	default:
-		dev->workbuf.size = CODA7_WORK_BUF_SIZE;
 	}
-	dev->workbuf.vaddr = dma_alloc_coherent(&pdev->dev, dev->workbuf.size,
-						    &dev->workbuf.paddr,
-						    GFP_KERNEL);
-	if (!dev->workbuf.vaddr) {
-		dev_err(&pdev->dev, "failed to allocate work buffer\n");
-		v4l2_device_unregister(&dev->v4l2_dev);
-		return -ENOMEM;
+	if (dev->tempbuf.size) {
+		ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
+					 dev->tempbuf.size);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to allocate temp buffer\n");
+			v4l2_device_unregister(&dev->v4l2_dev);
+			return ret;
+		}
 	}
 
-	if (dev->devtype->product == CODA_DX6)
+	switch (dev->devtype->product) {
+	case CODA_DX6:
 		dev->iram_size = CODADX6_IRAM_SIZE;
-	else
+		break;
+	case CODA_7541:
 		dev->iram_size = CODA7_IRAM_SIZE;
+		break;
+	}
 	dev->iram_vaddr = gen_pool_alloc(dev->iram_pool, dev->iram_size);
 	if (!dev->iram_vaddr) {
 		dev_err(&pdev->dev, "unable to alloc iram\n");
@@ -2128,12 +3230,9 @@ static int coda_remove(struct platform_device *pdev)
 	v4l2_device_unregister(&dev->v4l2_dev);
 	if (dev->iram_vaddr)
 		gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size);
-	if (dev->codebuf.vaddr)
-		dma_free_coherent(&pdev->dev, dev->codebuf.size,
-				  &dev->codebuf.vaddr, dev->codebuf.paddr);
-	if (dev->workbuf.vaddr)
-		dma_free_coherent(&pdev->dev, dev->workbuf.size, &dev->workbuf.vaddr,
-			  dev->workbuf.paddr);
+	coda_free_aux_buf(dev, &dev->codebuf);
+	coda_free_aux_buf(dev, &dev->tempbuf);
+	coda_free_aux_buf(dev, &dev->workbuf);
 	return 0;
 }
 
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h
index ace0bf0..4e32e2e 100644
--- a/drivers/media/platform/coda.h
+++ b/drivers/media/platform/coda.h
@@ -43,14 +43,26 @@
 #define		CODA_STREAM_ENDIAN_SELECT	(1 << 0)
 #define CODA_REG_BIT_FRAME_MEM_CTRL		0x110
 #define		CODA_IMAGE_ENDIAN_SELECT	(1 << 0)
+#define CODA_REG_BIT_BIT_STREAM_PARAM		0x114
+#define		CODA_BIT_STREAM_END_FLAG	(1 << 2)
+#define		CODA_BIT_DEC_SEQ_INIT_ESCAPE	(1 << 0)
+#define CODA_REG_BIT_TEMP_BUF_ADDR		0x118
 #define CODA_REG_BIT_RD_PTR(x)			(0x120 + 8 * (x))
 #define CODA_REG_BIT_WR_PTR(x)			(0x124 + 8 * (x))
+#define CODA_REG_BIT_FRM_DIS_FLG(x)		(0x150 + 4 * (x))
 #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR	0x140
 #define CODA7_REG_BIT_AXI_SRAM_USE		0x140
-#define		CODA7_USE_BIT_ENABLE		(1 << 0)
+#define		CODA7_USE_HOST_ME_ENABLE	(1 << 11)
+#define		CODA7_USE_HOST_OVL_ENABLE	(1 << 10)
+#define		CODA7_USE_HOST_DBK_ENABLE	(1 << 9)
+#define		CODA7_USE_HOST_IP_ENABLE	(1 << 8)
 #define		CODA7_USE_HOST_BIT_ENABLE	(1 << 7)
 #define		CODA7_USE_ME_ENABLE		(1 << 4)
-#define		CODA7_USE_HOST_ME_ENABLE	(1 << 11)
+#define		CODA7_USE_OVL_ENABLE		(1 << 3)
+#define		CODA7_USE_DBK_ENABLE		(1 << 2)
+#define		CODA7_USE_IP_ENABLE		(1 << 1)
+#define		CODA7_USE_BIT_ENABLE		(1 << 0)
+
 #define CODA_REG_BIT_BUSY			0x160
 #define		CODA_REG_BIT_BUSY_FLAG		1
 #define CODA_REG_BIT_RUN_COMMAND		0x164
@@ -84,6 +96,15 @@
 #define 	CODA_MODE_INVALID		0xffff
 #define CODA_REG_BIT_INT_ENABLE		0x170
 #define		CODA_INT_INTERRUPT_ENABLE	(1 << 3)
+#define CODA_REG_BIT_INT_REASON			0x174
+#define CODA7_REG_BIT_RUN_AUX_STD		0x178
+#define		CODA_MP4_AUX_MPEG4		0
+#define		CODA_MP4_AUX_DIVX3		1
+#define		CODA_VPX_AUX_THO		0
+#define		CODA_VPX_AUX_VP6		1
+#define		CODA_VPX_AUX_VP8		2
+#define		CODA_H264_AUX_AVC		0
+#define		CODA_H264_AUX_MVC		1
 
 /*
  * Commands' mailbox:
@@ -92,15 +113,89 @@
  * issued.
  */
 
+/* Decoder Sequence Initialization */
+#define CODA_CMD_DEC_SEQ_BB_START		0x180
+#define CODA_CMD_DEC_SEQ_BB_SIZE		0x184
+#define CODA_CMD_DEC_SEQ_OPTION			0x188
+#define		CODA_REORDER_ENABLE			(1 << 1)
+#define		CODADX6_QP_REPORT			(1 << 0)
+#define		CODA7_MP4_DEBLK_ENABLE			(1 << 0)
+#define CODA_CMD_DEC_SEQ_SRC_SIZE		0x18c
+#define CODA_CMD_DEC_SEQ_START_BYTE		0x190
+#define CODA_CMD_DEC_SEQ_PS_BB_START		0x194
+#define CODA_CMD_DEC_SEQ_PS_BB_SIZE		0x198
+#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS		0x19c
+#define CODA_CMD_DEC_SEQ_X264_MV_EN		0x19c
+#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE		0x1a0
+
+#define CODA7_RET_DEC_SEQ_ASPECT		0x1b0
+#define CODA_RET_DEC_SEQ_SUCCESS		0x1c0
+#define CODA_RET_DEC_SEQ_SRC_FMT		0x1c4 /* SRC_SIZE on CODA7 */
+#define CODA_RET_DEC_SEQ_SRC_SIZE		0x1c4
+#define CODA_RET_DEC_SEQ_SRC_F_RATE		0x1c8
+#define CODA9_RET_DEC_SEQ_ASPECT		0x1c8
+#define CODA_RET_DEC_SEQ_FRAME_NEED		0x1cc
+#define CODA_RET_DEC_SEQ_FRAME_DELAY		0x1d0
+#define CODA_RET_DEC_SEQ_INFO			0x1d4
+#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT	0x1d8
+#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM	0x1dc
+#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM		0x1e0
+#define CODA_RET_DEC_SEQ_ERR_REASON		0x1e0
+#define CODA_RET_DEC_SEQ_FRATE_NR		0x1e4
+#define CODA_RET_DEC_SEQ_FRATE_DR		0x1e8
+#define CODA_RET_DEC_SEQ_JPG_PARA		0x1e4
+#define CODA_RET_DEC_SEQ_JPG_THUMB_IND		0x1e8
+
+/* Decoder Picture Run */
+#define CODA_CMD_DEC_PIC_ROT_MODE		0x180
+#define CODA_CMD_DEC_PIC_ROT_ADDR_Y		0x184
+#define CODA_CMD_DEC_PIC_ROT_ADDR_CB		0x188
+#define CODA_CMD_DEC_PIC_ROT_ADDR_CR		0x18c
+#define CODA_CMD_DEC_PIC_ROT_STRIDE		0x190
+
+#define CODA_CMD_DEC_PIC_OPTION			0x194
+#define		CODA_PRE_SCAN_EN			(1 << 0)
+#define		CODA_PRE_SCAN_MODE_DECODE		(0 << 1)
+#define		CODA_PRE_SCAN_MODE_RETURN		(1 << 1)
+#define		CODA_IFRAME_SEARCH_EN			(1 << 2)
+#define		CODA_SKIP_FRAME_MODE			(0x3 << 3)
+#define CODA_CMD_DEC_PIC_SKIP_NUM		0x198
+#define CODA_CMD_DEC_PIC_CHUNK_SIZE		0x19c
+#define CODA_CMD_DEC_PIC_BB_START		0x1a0
+#define CODA_CMD_DEC_PIC_START_BYTE		0x1a4
+#define CODA_RET_DEC_PIC_SIZE			0x1bc
+#define CODA_RET_DEC_PIC_FRAME_NUM		0x1c0
+#define CODA_RET_DEC_PIC_FRAME_IDX		0x1c4
+#define CODA_RET_DEC_PIC_ERR_MB			0x1c8
+#define CODA_RET_DEC_PIC_TYPE			0x1cc
+#define		CODA_PIC_TYPE_MASK			0x7
+#define		CODA_PIC_TYPE_MASK_VC1			0x3f
+#define		CODA9_PIC_TYPE_FIRST_MASK		(0x7 << 3)
+#define		CODA9_PIC_TYPE_IDR_MASK			(0x3 << 6)
+#define		CODA7_PIC_TYPE_H264_NPF_MASK		(0x3 << 16)
+#define		CODA7_PIC_TYPE_INTERLACED		(1 << 18)
+#define CODA_RET_DEC_PIC_POST			0x1d0
+#define CODA_RET_DEC_PIC_MVC_REPORT		0x1d0
+#define CODA_RET_DEC_PIC_OPTION			0x1d4
+#define CODA_RET_DEC_PIC_SUCCESS		0x1d8
+#define CODA_RET_DEC_PIC_CUR_IDX		0x1dc
+#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT	0x1e0
+#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM	0x1e4
+#define CODA_RET_DEC_PIC_FRAME_NEED		0x1ec
+
 /* Encoder Sequence Initialization */
 #define CODA_CMD_ENC_SEQ_BB_START				0x180
 #define CODA_CMD_ENC_SEQ_BB_SIZE				0x184
 #define CODA_CMD_ENC_SEQ_OPTION				0x188
+#define		CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET		9
 #define		CODA7_OPTION_GAMMA_OFFSET			8
+#define		CODA7_OPTION_RCQPMAX_OFFSET			7
 #define		CODADX6_OPTION_GAMMA_OFFSET			7
+#define		CODA7_OPTION_RCQPMIN_OFFSET			6
 #define		CODA_OPTION_LIMITQP_OFFSET			6
 #define		CODA_OPTION_RCINTRAQP_OFFSET			5
 #define		CODA_OPTION_FMO_OFFSET				4
+#define		CODA_OPTION_AVC_AUD_OFFSET			2
 #define		CODA_OPTION_SLICEREPORT_OFFSET			1
 #define CODA_CMD_ENC_SEQ_COD_STD				0x18c
 #define		CODA_STD_MPEG4					0
@@ -169,8 +264,10 @@
 #define		CODA_FMOPARAM_TYPE_MASK				1
 #define		CODA_FMOPARAM_SLICENUM_OFFSET			0
 #define		CODA_FMOPARAM_SLICENUM_MASK			0x0f
+#define CODADX6_CMD_ENC_SEQ_INTRA_QP				0x1bc
 #define CODA7_CMD_ENC_SEQ_SEARCH_BASE				0x1b8
 #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE				0x1bc
+#define CODA7_CMD_ENC_SEQ_INTRA_QP				0x1c4
 #define CODA_CMD_ENC_SEQ_RC_QP_MAX				0x1c8
 #define		CODA_QPMAX_OFFSET				0
 #define		CODA_QPMAX_MASK					0x3f
@@ -197,18 +294,24 @@
 #define CODA_CMD_ENC_PIC_OPTION	0x194
 #define CODA_CMD_ENC_PIC_BB_START	0x198
 #define CODA_CMD_ENC_PIC_BB_SIZE	0x19c
+#define CODA_RET_ENC_FRAME_NUM		0x1c0
 #define CODA_RET_ENC_PIC_TYPE		0x1c4
+#define CODA_RET_ENC_PIC_FRAME_IDX	0x1c8
 #define CODA_RET_ENC_PIC_SLICE_NUM	0x1cc
 #define CODA_RET_ENC_PIC_FLAG		0x1d0
+#define CODA_RET_ENC_PIC_SUCCESS	0x1d8
 
 /* Set Frame Buffer */
 #define CODA_CMD_SET_FRAME_BUF_NUM		0x180
 #define CODA_CMD_SET_FRAME_BUF_STRIDE		0x184
+#define CODA_CMD_SET_FRAME_SLICE_BB_START	0x188
+#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE	0x18c
 #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR	0x190
 #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR	0x194
 #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR	0x198
 #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR	0x19c
 #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR	0x1a0
+#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE	0x1a4
 #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE	0x1a8
 
 /* Encoder Header */
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index e180ff7..04609cc6 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -1743,11 +1743,10 @@ static int vpbe_display_probe(struct platform_device *pdev)
 
 	printk(KERN_DEBUG "vpbe_display_probe\n");
 	/* Allocate memory for vpbe_display */
-	disp_dev = kzalloc(sizeof(struct vpbe_display), GFP_KERNEL);
-	if (!disp_dev) {
-		printk(KERN_ERR "ran out of memory\n");
+	disp_dev = devm_kzalloc(&pdev->dev, sizeof(struct vpbe_display),
+				GFP_KERNEL);
+	if (!disp_dev)
 		return -ENOMEM;
-	}
 
 	spin_lock_init(&disp_dev->dma_queue_lock);
 	/*
@@ -1786,26 +1785,24 @@ static int vpbe_display_probe(struct platform_device *pdev)
 	}
 
 	irq = res->start;
-	if (request_irq(irq, venc_isr,  IRQF_DISABLED, VPBE_DISPLAY_DRIVER,
-		disp_dev)) {
+	err = devm_request_irq(&pdev->dev, irq, venc_isr, IRQF_DISABLED,
+			       VPBE_DISPLAY_DRIVER, disp_dev);
+	if (err) {
 		v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
 				"Unable to request interrupt\n");
-		err = -ENODEV;
 		goto probe_out;
 	}
 
 	for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
 		if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
 			err = -ENODEV;
-			goto probe_out_irq;
+			goto probe_out;
 		}
 	}
 
 	printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
 	return 0;
 
-probe_out_irq:
-	free_irq(res->start, disp_dev);
 probe_out:
 	for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
 		/* Get the pointer to the layer object */
@@ -1817,7 +1814,6 @@ probe_out:
 				kfree(disp_dev->dev[k]);
 		}
 	}
-	kfree(disp_dev);
 	return err;
 }
 
@@ -1830,15 +1826,10 @@ static int vpbe_display_remove(struct platform_device *pdev)
 	struct vpbe_layer *vpbe_display_layer;
 	struct vpbe_display *disp_dev = platform_get_drvdata(pdev);
 	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
-	struct resource *res;
 	int i;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n");
 
-	/* unregister irq */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	free_irq(res->start, disp_dev);
-
 	/* deinitialize the vpbe display controller */
 	if (NULL != vpbe_dev->ops.deinitialize)
 		vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev);
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c
index 6ed82e8..d053c26 100644
--- a/drivers/media/platform/davinci/vpbe_osd.c
+++ b/drivers/media/platform/davinci/vpbe_osd.c
@@ -1547,61 +1547,36 @@ static int osd_probe(struct platform_device *pdev)
 	const struct platform_device_id *pdev_id;
 	struct osd_state *osd;
 	struct resource *res;
-	int ret = 0;
 
-	osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL);
+	pdev_id = platform_get_device_id(pdev);
+	if (!pdev_id)
+		return -EINVAL;
+
+	osd = devm_kzalloc(&pdev->dev, sizeof(struct osd_state), GFP_KERNEL);
 	if (osd == NULL)
 		return -ENOMEM;
 
-	pdev_id = platform_get_device_id(pdev);
-	if (!pdev_id) {
-		ret = -EINVAL;
-		goto free_mem;
-	}
 
 	osd->dev = &pdev->dev;
 	osd->vpbe_type = pdev_id->driver_data;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(osd->dev, "Unable to get OSD register address map\n");
-		ret = -ENODEV;
-		goto free_mem;
-	}
+	osd->osd_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(osd->osd_base))
+		return PTR_ERR(osd->osd_base);
+
 	osd->osd_base_phys = res->start;
 	osd->osd_size = resource_size(res);
-	if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
-				MODULE_NAME)) {
-		dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
-		ret = -ENODEV;
-		goto free_mem;
-	}
-	osd->osd_base = ioremap_nocache(res->start, osd->osd_size);
-	if (!osd->osd_base) {
-		dev_err(osd->dev, "Unable to map the OSD region\n");
-		ret = -ENODEV;
-		goto release_mem_region;
-	}
 	spin_lock_init(&osd->lock);
 	osd->ops = osd_ops;
 	platform_set_drvdata(pdev, osd);
 	dev_notice(osd->dev, "OSD sub device probe success\n");
-	return ret;
 
-release_mem_region:
-	release_mem_region(osd->osd_base_phys, osd->osd_size);
-free_mem:
-	kfree(osd);
-	return ret;
+	return 0;
 }
 
 static int osd_remove(struct platform_device *pdev)
 {
-	struct osd_state *osd = platform_get_drvdata(pdev);
-
-	iounmap((void *)osd->osd_base);
-	release_mem_region(osd->osd_base_phys, osd->osd_size);
-	kfree(osd);
 	return 0;
 }
 
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c
index 87eef9b..14a023a 100644
--- a/drivers/media/platform/davinci/vpbe_venc.c
+++ b/drivers/media/platform/davinci/vpbe_venc.c
@@ -639,105 +639,46 @@ static int venc_probe(struct platform_device *pdev)
 	const struct platform_device_id *pdev_id;
 	struct venc_state *venc;
 	struct resource *res;
-	int ret;
 
-	venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL);
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "No platform data for VENC sub device");
+		return -EINVAL;
+	}
+
+	pdev_id = platform_get_device_id(pdev);
+	if (!pdev_id)
+		return -EINVAL;
+
+	venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL);
 	if (venc == NULL)
 		return -ENOMEM;
 
-	pdev_id = platform_get_device_id(pdev);
-	if (!pdev_id) {
-		ret = -EINVAL;
-		goto free_mem;
-	}
 	venc->venc_type = pdev_id->driver_data;
 	venc->pdev = &pdev->dev;
 	venc->pdata = pdev->dev.platform_data;
-	if (NULL == venc->pdata) {
-		dev_err(venc->pdev, "Unable to get platform data for"
-			" VENC sub device");
-		ret = -ENOENT;
-		goto free_mem;
-	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(venc->pdev,
-			"Unable to get VENC register address map\n");
-		ret = -ENODEV;
-		goto free_mem;
-	}
 
-	if (!request_mem_region(res->start, resource_size(res), "venc")) {
-		dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n");
-		ret = -ENODEV;
-		goto free_mem;
-	}
-
-	venc->venc_base = ioremap_nocache(res->start, resource_size(res));
-	if (!venc->venc_base) {
-		dev_err(venc->pdev, "Unable to map VENC IO space\n");
-		ret = -ENODEV;
-		goto release_venc_mem_region;
-	}
+	venc->venc_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(venc->venc_base))
+		return PTR_ERR(venc->venc_base);
 
 	if (venc->venc_type != VPBE_VERSION_1) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (!res) {
-			dev_err(venc->pdev,
-				"Unable to get VDAC_CONFIG address map\n");
-			ret = -ENODEV;
-			goto unmap_venc_io;
-		}
-
-		if (!request_mem_region(res->start,
-					resource_size(res), "venc")) {
-			dev_err(venc->pdev,
-				"Unable to reserve VDAC_CONFIG  MMIO region\n");
-			ret = -ENODEV;
-			goto unmap_venc_io;
-		}
-
-		venc->vdaccfg_reg = ioremap_nocache(res->start,
-						    resource_size(res));
-		if (!venc->vdaccfg_reg) {
-			dev_err(venc->pdev,
-				"Unable to map VDAC_CONFIG IO space\n");
-			ret = -ENODEV;
-			goto release_vdaccfg_mem_region;
-		}
+
+		venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(venc->vdaccfg_reg))
+			return PTR_ERR(venc->vdaccfg_reg);
 	}
 	spin_lock_init(&venc->lock);
 	platform_set_drvdata(pdev, venc);
 	dev_notice(venc->pdev, "VENC sub device probe success\n");
-	return 0;
 
-release_vdaccfg_mem_region:
-	release_mem_region(res->start, resource_size(res));
-unmap_venc_io:
-	iounmap(venc->venc_base);
-release_venc_mem_region:
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-free_mem:
-	kfree(venc);
-	return ret;
+	return 0;
 }
 
 static int venc_remove(struct platform_device *pdev)
 {
-	struct venc_state *venc = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iounmap((void *)venc->venc_base);
-	release_mem_region(res->start, resource_size(res));
-	if (venc->venc_type != VPBE_VERSION_1) {
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		iounmap((void *)venc->vdaccfg_reg);
-		release_mem_region(res->start, resource_size(res));
-	}
-	kfree(venc);
-
 	return 0;
 }
 
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 5514175..7fbde6d 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -1979,6 +1979,76 @@ vpif_init_free_channel_objects:
 	return err;
 }
 
+static int vpif_async_bound(struct v4l2_async_notifier *notifier,
+			    struct v4l2_subdev *subdev,
+			    struct v4l2_async_subdev *asd)
+{
+	int i;
+
+	for (i = 0; i < vpif_obj.config->subdev_count; i++)
+		if (!strcmp(vpif_obj.config->subdev_info[i].name,
+			    subdev->name)) {
+			vpif_obj.sd[i] = subdev;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static int vpif_probe_complete(void)
+{
+	struct common_obj *common;
+	struct channel_obj *ch;
+	int i, j, err, k;
+
+	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
+		ch = vpif_obj.dev[j];
+		ch->channel_id = j;
+		common = &(ch->common[VPIF_VIDEO_INDEX]);
+		spin_lock_init(&common->irqlock);
+		mutex_init(&common->lock);
+		ch->video_dev->lock = &common->lock;
+		/* Initialize prio member of channel object */
+		v4l2_prio_init(&ch->prio);
+		video_set_drvdata(ch->video_dev, ch);
+
+		/* select input 0 */
+		err = vpif_set_input(vpif_obj.config, ch, 0);
+		if (err)
+			goto probe_out;
+
+		err = video_register_device(ch->video_dev,
+					    VFL_TYPE_GRABBER, (j ? 1 : 0));
+		if (err)
+			goto probe_out;
+	}
+
+	v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
+	return 0;
+
+probe_out:
+	for (k = 0; k < j; k++) {
+		/* Get the pointer to the channel object */
+		ch = vpif_obj.dev[k];
+		/* Unregister video device */
+		video_unregister_device(ch->video_dev);
+	}
+	kfree(vpif_obj.sd);
+	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
+		ch = vpif_obj.dev[i];
+		/* Note: does nothing if ch->video_dev == NULL */
+		video_device_release(ch->video_dev);
+	}
+	v4l2_device_unregister(&vpif_obj.v4l2_dev);
+
+	return err;
+}
+
+static int vpif_async_complete(struct v4l2_async_notifier *notifier)
+{
+	return vpif_probe_complete();
+}
+
 /**
  * vpif_probe : This function probes the vpif capture driver
  * @pdev: platform device pointer
@@ -1989,12 +2059,10 @@ vpif_init_free_channel_objects:
 static __init int vpif_probe(struct platform_device *pdev)
 {
 	struct vpif_subdev_info *subdevdata;
-	struct vpif_capture_config *config;
-	int i, j, k, err;
+	int i, j, err;
 	int res_idx = 0;
 	struct i2c_adapter *i2c_adap;
 	struct channel_obj *ch;
-	struct common_obj *common;
 	struct video_device *vfd;
 	struct resource *res;
 	int subdev_count;
@@ -2068,10 +2136,9 @@ static __init int vpif_probe(struct platform_device *pdev)
 		}
 	}
 
-	i2c_adap = i2c_get_adapter(1);
-	config = pdev->dev.platform_data;
+	vpif_obj.config = pdev->dev.platform_data;
 
-	subdev_count = config->subdev_count;
+	subdev_count = vpif_obj.config->subdev_count;
 	vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
 				GFP_KERNEL);
 	if (vpif_obj.sd == NULL) {
@@ -2080,54 +2147,42 @@ static __init int vpif_probe(struct platform_device *pdev)
 		goto vpif_sd_error;
 	}
 
-	for (i = 0; i < subdev_count; i++) {
-		subdevdata = &config->subdev_info[i];
-		vpif_obj.sd[i] =
-			v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-						  i2c_adap,
-						  &subdevdata->board_info,
-						  NULL);
-
-		if (!vpif_obj.sd[i]) {
-			vpif_err("Error registering v4l2 subdevice\n");
-			err = -ENODEV;
+	if (!vpif_obj.config->asd_sizes) {
+		i2c_adap = i2c_get_adapter(1);
+		for (i = 0; i < subdev_count; i++) {
+			subdevdata = &vpif_obj.config->subdev_info[i];
+			vpif_obj.sd[i] =
+				v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+							  i2c_adap,
+							  &subdevdata->
+							  board_info,
+							  NULL);
+
+			if (!vpif_obj.sd[i]) {
+				vpif_err("Error registering v4l2 subdevice\n");
+				goto probe_subdev_out;
+			}
+			v4l2_info(&vpif_obj.v4l2_dev,
+				  "registered sub device %s\n",
+				   subdevdata->name);
+		}
+		vpif_probe_complete();
+	} else {
+		vpif_obj.notifier.subdevs = vpif_obj.config->asd;
+		vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
+		vpif_obj.notifier.bound = vpif_async_bound;
+		vpif_obj.notifier.complete = vpif_async_complete;
+		err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
+						   &vpif_obj.notifier);
+		if (err) {
+			vpif_err("Error registering async notifier\n");
+			err = -EINVAL;
 			goto probe_subdev_out;
 		}
-		v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
-			  subdevdata->name);
 	}
 
-	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
-		ch = vpif_obj.dev[j];
-		ch->channel_id = j;
-		common = &(ch->common[VPIF_VIDEO_INDEX]);
-		spin_lock_init(&common->irqlock);
-		mutex_init(&common->lock);
-		ch->video_dev->lock = &common->lock;
-		/* Initialize prio member of channel object */
-		v4l2_prio_init(&ch->prio);
-		video_set_drvdata(ch->video_dev, ch);
-
-		/* select input 0 */
-		err = vpif_set_input(config, ch, 0);
-		if (err)
-			goto probe_out;
-
-		err = video_register_device(ch->video_dev,
-					    VFL_TYPE_GRABBER, (j ? 1 : 0));
-		if (err)
-			goto probe_out;
-	}
-	v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
 	return 0;
 
-probe_out:
-	for (k = 0; k < j; k++) {
-		/* Get the pointer to the channel object */
-		ch = vpif_obj.dev[k];
-		/* Unregister video device */
-		video_unregister_device(ch->video_dev);
-	}
 probe_subdev_out:
 	/* free sub devices memory */
 	kfree(vpif_obj.sd);
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h
index 0ebb312..5a29d9a 100644
--- a/drivers/media/platform/davinci/vpif_capture.h
+++ b/drivers/media/platform/davinci/vpif_capture.h
@@ -142,6 +142,8 @@ struct vpif_device {
 	struct v4l2_device v4l2_dev;
 	struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS];
 	struct v4l2_subdev **sd;
+	struct v4l2_async_notifier notifier;
+	struct vpif_capture_config *config;
 };
 
 struct vpif_config_params {
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index e6e5736..6336dfc 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1618,6 +1618,102 @@ vpif_init_free_channel_objects:
 	return err;
 }
 
+static int vpif_async_bound(struct v4l2_async_notifier *notifier,
+			    struct v4l2_subdev *subdev,
+			    struct v4l2_async_subdev *asd)
+{
+	int i;
+
+	for (i = 0; i < vpif_obj.config->subdev_count; i++)
+		if (!strcmp(vpif_obj.config->subdevinfo[i].name,
+			    subdev->name)) {
+			vpif_obj.sd[i] = subdev;
+			vpif_obj.sd[i]->grp_id = 1 << i;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static int vpif_probe_complete(void)
+{
+	struct common_obj *common;
+	struct channel_obj *ch;
+	int j, err, k;
+
+	for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
+		ch = vpif_obj.dev[j];
+		/* Initialize field of the channel objects */
+		atomic_set(&ch->usrs, 0);
+		for (k = 0; k < VPIF_NUMOBJECTS; k++) {
+			ch->common[k].numbuffers = 0;
+			common = &ch->common[k];
+			common->io_usrs = 0;
+			common->started = 0;
+			spin_lock_init(&common->irqlock);
+			mutex_init(&common->lock);
+			common->numbuffers = 0;
+			common->set_addr = NULL;
+			common->ytop_off = 0;
+			common->ybtm_off = 0;
+			common->ctop_off = 0;
+			common->cbtm_off = 0;
+			common->cur_frm = NULL;
+			common->next_frm = NULL;
+			memset(&common->fmt, 0, sizeof(common->fmt));
+			common->numbuffers = config_params.numbuffers[k];
+		}
+		ch->initialized = 0;
+		if (vpif_obj.config->subdev_count)
+			ch->sd = vpif_obj.sd[0];
+		ch->channel_id = j;
+		if (j < 2)
+			ch->common[VPIF_VIDEO_INDEX].numbuffers =
+			    config_params.numbuffers[ch->channel_id];
+		else
+			ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
+
+		memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
+
+		/* Initialize prio member of channel object */
+		v4l2_prio_init(&ch->prio);
+		ch->common[VPIF_VIDEO_INDEX].fmt.type =
+						V4L2_BUF_TYPE_VIDEO_OUTPUT;
+		ch->video_dev->lock = &common->lock;
+		video_set_drvdata(ch->video_dev, ch);
+
+		/* select output 0 */
+		err = vpif_set_output(vpif_obj.config, ch, 0);
+		if (err)
+			goto probe_out;
+
+		/* register video device */
+		vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
+			 (int)ch, (int)&ch->video_dev);
+
+		err = video_register_device(ch->video_dev,
+					  VFL_TYPE_GRABBER, (j ? 3 : 2));
+		if (err < 0)
+			goto probe_out;
+	}
+
+	return 0;
+
+probe_out:
+	for (k = 0; k < j; k++) {
+		ch = vpif_obj.dev[k];
+		video_unregister_device(ch->video_dev);
+		video_device_release(ch->video_dev);
+		ch->video_dev = NULL;
+	}
+	return err;
+}
+
+static int vpif_async_complete(struct v4l2_async_notifier *notifier)
+{
+	return vpif_probe_complete();
+}
+
 /*
  * vpif_probe: This function creates device entries by register itself to the
  * V4L2 driver and initializes fields of each channel objects
@@ -1625,11 +1721,9 @@ vpif_init_free_channel_objects:
 static __init int vpif_probe(struct platform_device *pdev)
 {
 	struct vpif_subdev_info *subdevdata;
-	struct vpif_display_config *config;
-	int i, j = 0, k, err = 0;
+	int i, j = 0, err = 0;
 	int res_idx = 0;
 	struct i2c_adapter *i2c_adap;
-	struct common_obj *common;
 	struct channel_obj *ch;
 	struct video_device *vfd;
 	struct resource *res;
@@ -1708,11 +1802,9 @@ static __init int vpif_probe(struct platform_device *pdev)
 									size/2;
 		}
 	}
-
-	i2c_adap = i2c_get_adapter(1);
-	config = pdev->dev.platform_data;
-	subdev_count = config->subdev_count;
-	subdevdata = config->subdevinfo;
+	vpif_obj.config = pdev->dev.platform_data;
+	subdev_count = vpif_obj.config->subdev_count;
+	subdevdata = vpif_obj.config->subdevinfo;
 	vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
 								GFP_KERNEL);
 	if (vpif_obj.sd == NULL) {
@@ -1721,86 +1813,40 @@ static __init int vpif_probe(struct platform_device *pdev)
 		goto vpif_sd_error;
 	}
 
-	for (i = 0; i < subdev_count; i++) {
-		vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-						i2c_adap,
-						&subdevdata[i].board_info,
-						NULL);
-		if (!vpif_obj.sd[i]) {
-			vpif_err("Error registering v4l2 subdevice\n");
-			err = -ENODEV;
-			goto probe_subdev_out;
-		}
-
-		if (vpif_obj.sd[i])
-			vpif_obj.sd[i]->grp_id = 1 << i;
-	}
-
-	for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
-		ch = vpif_obj.dev[j];
-		/* Initialize field of the channel objects */
-		atomic_set(&ch->usrs, 0);
-		for (k = 0; k < VPIF_NUMOBJECTS; k++) {
-			ch->common[k].numbuffers = 0;
-			common = &ch->common[k];
-			common->io_usrs = 0;
-			common->started = 0;
-			spin_lock_init(&common->irqlock);
-			mutex_init(&common->lock);
-			common->numbuffers = 0;
-			common->set_addr = NULL;
-			common->ytop_off = common->ybtm_off = 0;
-			common->ctop_off = common->cbtm_off = 0;
-			common->cur_frm = common->next_frm = NULL;
-			memset(&common->fmt, 0, sizeof(common->fmt));
-			common->numbuffers = config_params.numbuffers[k];
+	if (!vpif_obj.config->asd_sizes) {
+		i2c_adap = i2c_get_adapter(1);
+		for (i = 0; i < subdev_count; i++) {
+			vpif_obj.sd[i] =
+				v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+							  i2c_adap,
+							  &subdevdata[i].
+							  board_info,
+							  NULL);
+			if (!vpif_obj.sd[i]) {
+				vpif_err("Error registering v4l2 subdevice\n");
+				goto probe_subdev_out;
+			}
 
+			if (vpif_obj.sd[i])
+				vpif_obj.sd[i]->grp_id = 1 << i;
+		}
+		vpif_probe_complete();
+	} else {
+		vpif_obj.notifier.subdevs = vpif_obj.config->asd;
+		vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
+		vpif_obj.notifier.bound = vpif_async_bound;
+		vpif_obj.notifier.complete = vpif_async_complete;
+		err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
+						   &vpif_obj.notifier);
+		if (err) {
+			vpif_err("Error registering async notifier\n");
+			err = -EINVAL;
+			goto probe_subdev_out;
 		}
-		ch->initialized = 0;
-		if (subdev_count)
-			ch->sd = vpif_obj.sd[0];
-		ch->channel_id = j;
-		if (j < 2)
-			ch->common[VPIF_VIDEO_INDEX].numbuffers =
-			    config_params.numbuffers[ch->channel_id];
-		else
-			ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
-
-		memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
-
-		/* Initialize prio member of channel object */
-		v4l2_prio_init(&ch->prio);
-		ch->common[VPIF_VIDEO_INDEX].fmt.type =
-						V4L2_BUF_TYPE_VIDEO_OUTPUT;
-		ch->video_dev->lock = &common->lock;
-		video_set_drvdata(ch->video_dev, ch);
-
-		/* select output 0 */
-		err = vpif_set_output(config, ch, 0);
-		if (err)
-			goto probe_out;
-
-		/* register video device */
-		vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
-				(int)ch, (int)&ch->video_dev);
-
-		err = video_register_device(ch->video_dev,
-					  VFL_TYPE_GRABBER, (j ? 3 : 2));
-		if (err < 0)
-			goto probe_out;
 	}
 
-	v4l2_info(&vpif_obj.v4l2_dev,
-			" VPIF display driver initialized\n");
 	return 0;
 
-probe_out:
-	for (k = 0; k < j; k++) {
-		ch = vpif_obj.dev[k];
-		video_unregister_device(ch->video_dev);
-		video_device_release(ch->video_dev);
-		ch->video_dev = NULL;
-	}
 probe_subdev_out:
 	kfree(vpif_obj.sd);
 vpif_sd_error:
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h
index 5d87fc8..4d0485b 100644
--- a/drivers/media/platform/davinci/vpif_display.h
+++ b/drivers/media/platform/davinci/vpif_display.h
@@ -148,7 +148,8 @@ struct vpif_device {
 	struct v4l2_device v4l2_dev;
 	struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
 	struct v4l2_subdev **sd;
-
+	struct v4l2_async_notifier notifier;
+	struct vpif_display_config *config;
 };
 
 struct vpif_config_params {
diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c
index 8a2f01e..31120b4 100644
--- a/drivers/media/platform/davinci/vpss.c
+++ b/drivers/media/platform/davinci/vpss.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+#include <linux/err.h>
 
 #include <media/davinci/vpss.h>
 
@@ -404,9 +405,8 @@ EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size);
 
 static int vpss_probe(struct platform_device *pdev)
 {
-	struct resource		*r1, *r2;
+	struct resource *res;
 	char *platform_name;
-	int status;
 
 	if (!pdev->dev.platform_data) {
 		dev_err(&pdev->dev, "no platform data\n");
@@ -427,38 +427,19 @@ static int vpss_probe(struct platform_device *pdev)
 	}
 
 	dev_info(&pdev->dev, "%s vpss probed\n", platform_name);
-	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r1)
-		return -ENOENT;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	r1 = request_mem_region(r1->start, resource_size(r1), r1->name);
-	if (!r1)
-		return -EBUSY;
-
-	oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1));
-	if (!oper_cfg.vpss_regs_base0) {
-		status = -EBUSY;
-		goto fail1;
-	}
+	oper_cfg.vpss_regs_base0 = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oper_cfg.vpss_regs_base0))
+		return PTR_ERR(oper_cfg.vpss_regs_base0);
 
 	if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
-		r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (!r2) {
-			status = -ENOENT;
-			goto fail2;
-		}
-		r2 = request_mem_region(r2->start, resource_size(r2), r2->name);
-		if (!r2) {
-			status = -EBUSY;
-			goto fail2;
-		}
-
-		oper_cfg.vpss_regs_base1 = ioremap(r2->start,
-						   resource_size(r2));
-		if (!oper_cfg.vpss_regs_base1) {
-			status = -EBUSY;
-			goto fail3;
-		}
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+		oper_cfg.vpss_regs_base1 = devm_ioremap_resource(&pdev->dev,
+								 res);
+		if (IS_ERR(oper_cfg.vpss_regs_base1))
+			return PTR_ERR(oper_cfg.vpss_regs_base1);
 	}
 
 	if (oper_cfg.platform == DM355) {
@@ -493,30 +474,13 @@ static int vpss_probe(struct platform_device *pdev)
 
 	spin_lock_init(&oper_cfg.vpss_lock);
 	dev_info(&pdev->dev, "%s vpss probe success\n", platform_name);
-	return 0;
 
-fail3:
-	release_mem_region(r2->start, resource_size(r2));
-fail2:
-	iounmap(oper_cfg.vpss_regs_base0);
-fail1:
-	release_mem_region(r1->start, resource_size(r1));
-	return status;
+	return 0;
 }
 
 static int vpss_remove(struct platform_device *pdev)
 {
-	struct resource		*res;
-
 	pm_runtime_disable(&pdev->dev);
-	iounmap(oper_cfg.vpss_regs_base0);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
-		iounmap(oper_cfg.vpss_regs_base1);
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		release_mem_region(res->start, resource_size(res));
-	}
 	return 0;
 }
 
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
index 1f079ff..5628453 100644
--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
+++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
@@ -399,7 +399,7 @@ static void cafe_ctlr_init(struct mcam_camera *mcam)
 }
 
 
-static void cafe_ctlr_power_up(struct mcam_camera *mcam)
+static int cafe_ctlr_power_up(struct mcam_camera *mcam)
 {
 	/*
 	 * Part one of the sensor dance: turn the global
@@ -414,6 +414,8 @@ static void cafe_ctlr_power_up(struct mcam_camera *mcam)
 	 */
 	mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
 	mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
+
+	return 0;
 }
 
 static void cafe_ctlr_power_down(struct mcam_camera *mcam)
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 0821ed0..5184887 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -93,6 +94,9 @@ MODULE_PARM_DESC(buffer_mode,
 #define CF_CONFIG_NEEDED 4	/* Must configure hardware */
 #define CF_SINGLE_BUFFER 5	/* Running with a single buffer */
 #define CF_SG_RESTART	 6	/* SG restart needed */
+#define CF_FRAME_SOF0	 7	/* Frame 0 started */
+#define CF_FRAME_SOF1	 8
+#define CF_FRAME_SOF2	 9
 
 #define sensor_call(cam, o, f, args...) \
 	v4l2_subdev_call(cam->sensor, o, f, ##args)
@@ -101,6 +105,7 @@ static struct mcam_format_struct {
 	__u8 *desc;
 	__u32 pixelformat;
 	int bpp;   /* Bytes per pixel */
+	bool planar;
 	enum v4l2_mbus_pixelcode mbus_code;
 } mcam_formats[] = {
 	{
@@ -108,24 +113,56 @@ static struct mcam_format_struct {
 		.pixelformat	= V4L2_PIX_FMT_YUYV,
 		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
+		.planar		= false,
+	},
+	{
+		.desc		= "UYVY 4:2:2",
+		.pixelformat	= V4L2_PIX_FMT_UYVY,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.bpp		= 2,
+		.planar		= false,
+	},
+	{
+		.desc		= "YUV 4:2:2 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YUV422P,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.bpp		= 2,
+		.planar		= true,
+	},
+	{
+		.desc		= "YUV 4:2:0 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YUV420,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.bpp		= 2,
+		.planar		= true,
+	},
+	{
+		.desc		= "YVU 4:2:0 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YVU420,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.bpp		= 2,
+		.planar		= true,
 	},
 	{
 		.desc		= "RGB 444",
 		.pixelformat	= V4L2_PIX_FMT_RGB444,
 		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
 		.bpp		= 2,
+		.planar		= false,
 	},
 	{
 		.desc		= "RGB 565",
 		.pixelformat	= V4L2_PIX_FMT_RGB565,
 		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.bpp		= 2,
+		.planar		= false,
 	},
 	{
 		.desc		= "Raw RGB Bayer",
 		.pixelformat	= V4L2_PIX_FMT_SBGGR8,
 		.mbus_code	= V4L2_MBUS_FMT_SBGGR8_1X8,
-		.bpp		= 1
+		.bpp		= 1,
+		.planar		= false,
 	},
 };
 #define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
@@ -168,6 +205,12 @@ struct mcam_dma_desc {
 	u32 segment_len;
 };
 
+struct yuv_pointer_t {
+	dma_addr_t y;
+	dma_addr_t u;
+	dma_addr_t v;
+};
+
 /*
  * Our buffer type for working with videobuf2.  Note that the vb2
  * developers have decreed that struct vb2_buffer must be at the
@@ -179,6 +222,7 @@ struct mcam_vb_buffer {
 	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
 	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
 	int dma_desc_nent;		/* Number of mapped descriptors */
+	struct yuv_pointer_t yuv_p;
 };
 
 static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
@@ -219,8 +263,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam)
 	int i;
 
 	cam->next_buf = -1;
-	for (i = 0; i < cam->nbufs; i++)
+	for (i = 0; i < cam->nbufs; i++) {
 		clear_bit(i, &cam->flags);
+		clear_bit(CF_FRAME_SOF0 + i, &cam->flags);
+	}
 }
 
 static inline int mcam_needs_config(struct mcam_camera *cam)
@@ -253,6 +299,45 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
 	mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
 }
 
+static void mcam_enable_mipi(struct mcam_camera *mcam)
+{
+	/* Using MIPI mode and enable MIPI */
+	cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n",
+			mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]);
+	mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]);
+	mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]);
+	mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]);
+
+	if (!mcam->mipi_enabled) {
+		if (mcam->lane > 4 || mcam->lane <= 0) {
+			cam_warn(mcam, "lane number error\n");
+			mcam->lane = 1;	/* set the default value */
+		}
+		/*
+		 * 0x41 actives 1 lane
+		 * 0x43 actives 2 lanes
+		 * 0x45 actives 3 lanes (never happen)
+		 * 0x47 actives 4 lanes
+		 */
+		mcam_reg_write(mcam, REG_CSI2_CTRL0,
+			CSI2_C0_MIPI_EN | CSI2_C0_ACT_LANE(mcam->lane));
+		mcam_reg_write(mcam, REG_CLKCTRL,
+			(mcam->mclk_src << 29) | mcam->mclk_div);
+
+		mcam->mipi_enabled = true;
+	}
+}
+
+static void mcam_disable_mipi(struct mcam_camera *mcam)
+{
+	/* Using Parallel mode or disable MIPI */
+	mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0);
+	mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0);
+	mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0);
+	mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0);
+	mcam->mipi_enabled = false;
+}
+
 /* ------------------------------------------------------------------- */
 
 #ifdef MCAM_MODE_VMALLOC
@@ -425,6 +510,15 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
 /*
  * DMA-contiguous code.
  */
+
+static bool mcam_fmt_is_planar(__u32 pfmt)
+{
+	struct mcam_format_struct *f;
+
+	f = mcam_find_format(pfmt);
+	return f->planar;
+}
+
 /*
  * Set up a contiguous buffer for the given frame.  Here also is where
  * the underrun strategy is set: if there is no buffer available, reuse
@@ -436,27 +530,58 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
 static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf;
+	struct v4l2_pix_format *fmt = &cam->pix_format;
+	dma_addr_t dma_handle;
+	u32 pixel_count = fmt->width * fmt->height;
+	struct vb2_buffer *vb;
+
 	/*
 	 * If there are no available buffers, go into single mode
 	 */
 	if (list_empty(&cam->buffers)) {
 		buf = cam->vb_bufs[frame ^ 0x1];
-		cam->vb_bufs[frame] = buf;
-		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 		set_bit(CF_SINGLE_BUFFER, &cam->flags);
 		cam->frame_state.singles++;
-		return;
+	} else {
+		/*
+		 * OK, we have a buffer we can use.
+		 */
+		buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
+					queue);
+		list_del_init(&buf->queue);
+		clear_bit(CF_SINGLE_BUFFER, &cam->flags);
 	}
-	/*
-	 * OK, we have a buffer we can use.
-	 */
-	buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
-	list_del_init(&buf->queue);
-	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-			vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
+
 	cam->vb_bufs[frame] = buf;
-	clear_bit(CF_SINGLE_BUFFER, &cam->flags);
+	vb = &buf->vb_buf;
+
+	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
+	buf->yuv_p.y = dma_handle;
+
+	switch (cam->pix_format.pixelformat) {
+	case V4L2_PIX_FMT_YUV422P:
+		buf->yuv_p.u = buf->yuv_p.y + pixel_count;
+		buf->yuv_p.v = buf->yuv_p.u + pixel_count / 2;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+		buf->yuv_p.u = buf->yuv_p.y + pixel_count;
+		buf->yuv_p.v = buf->yuv_p.u + pixel_count / 4;
+		break;
+	case V4L2_PIX_FMT_YVU420:
+		buf->yuv_p.v = buf->yuv_p.y + pixel_count;
+		buf->yuv_p.u = buf->yuv_p.v + pixel_count / 4;
+		break;
+	default:
+		break;
+	}
+
+	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
+	if (mcam_fmt_is_planar(fmt->pixelformat)) {
+		mcam_reg_write(cam, frame == 0 ?
+					REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
+		mcam_reg_write(cam, frame == 0 ?
+					REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
+	}
 }
 
 /*
@@ -614,48 +739,90 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
  */
 static void mcam_ctlr_image(struct mcam_camera *cam)
 {
-	int imgsz;
 	struct v4l2_pix_format *fmt = &cam->pix_format;
+	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
+
+	cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
+		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
+	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
+	imgsz_w = (fmt->width * 2) & IMGSZ_H_MASK;
+
+	switch (fmt->pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+		widthy = fmt->width * 2;
+		widthuv = 0;
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
+		widthy = fmt->bytesperline;
+		widthuv = 0;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		widthy = fmt->width;
+		widthuv = fmt->width / 2;
+		break;
+	default:
+		widthy = fmt->bytesperline;
+		widthuv = 0;
+	}
+
+	mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
+			IMGP_YP_MASK | IMGP_UVP_MASK);
+	mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
+	mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
 
-	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
-		(fmt->bytesperline & IMGSZ_H_MASK);
-	mcam_reg_write(cam, REG_IMGSIZE, imgsz);
-	mcam_reg_write(cam, REG_IMGOFFSET, 0);
-	/* YPITCH just drops the last two bits */
-	mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
-			IMGP_YP_MASK);
 	/*
 	 * Tell the controller about the image format we are using.
 	 */
-	switch (cam->pix_format.pixelformat) {
+	switch (fmt->pixelformat) {
+	case V4L2_PIX_FMT_YUV422P:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_YUYV:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
-			    C0_DF_MASK);
-	    break;
-
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_RGB444:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
-			    C0_DF_MASK);
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
 		/* Alpha value? */
-	    break;
-
+		break;
 	case V4L2_PIX_FMT_RGB565:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
-			    C0_DF_MASK);
-	    break;
-
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
+		break;
 	default:
-	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
-	    break;
+		cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
+		break;
 	}
+
 	/*
 	 * Make sure it knows we want to use hsync/vsync.
 	 */
-	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
-			C0_SIFM_MASK);
+	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
+	/*
+	 * This field controls the generation of EOF(DVP only)
+	 */
+	if (cam->bus_type != V4L2_MBUS_CSI2)
+		mcam_reg_set_bit(cam, REG_CTRL0,
+				C0_EOF_VSYNC | C0_VEDGE_CTRL);
 }
 
 
@@ -753,15 +920,21 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam)
 /*
  * Power up and down.
  */
-static void mcam_ctlr_power_up(struct mcam_camera *cam)
+static int mcam_ctlr_power_up(struct mcam_camera *cam)
 {
 	unsigned long flags;
+	int ret;
 
 	spin_lock_irqsave(&cam->dev_lock, flags);
-	cam->plat_power_up(cam);
+	ret = cam->plat_power_up(cam);
+	if (ret) {
+		spin_unlock_irqrestore(&cam->dev_lock, flags);
+		return ret;
+	}
 	mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
 	spin_unlock_irqrestore(&cam->dev_lock, flags);
 	msleep(5); /* Just to be sure */
+	return 0;
 }
 
 static void mcam_ctlr_power_down(struct mcam_camera *cam)
@@ -869,6 +1042,17 @@ static int mcam_read_setup(struct mcam_camera *cam)
 	spin_lock_irqsave(&cam->dev_lock, flags);
 	clear_bit(CF_DMA_ACTIVE, &cam->flags);
 	mcam_reset_buffers(cam);
+	/*
+	 * Update CSI2_DPHY value
+	 */
+	if (cam->calc_dphy)
+		cam->calc_dphy(cam);
+	cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
+			cam->dphy[0], cam->dphy[1], cam->dphy[2]);
+	if (cam->bus_type == V4L2_MBUS_CSI2)
+		mcam_enable_mipi(cam);
+	else
+		mcam_disable_mipi(cam);
 	mcam_ctlr_irq_enable(cam);
 	cam->state = S_STREAMING;
 	if (!test_bit(CF_SG_RESTART, &cam->flags))
@@ -943,6 +1127,7 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
 static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	unsigned int frame;
 
 	if (cam->state != S_IDLE) {
 		INIT_LIST_HEAD(&cam->buffers);
@@ -960,6 +1145,14 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 		cam->state = S_BUFWAIT;
 		return 0;
 	}
+
+	/*
+	 * Ensure clear the left over frame flags
+	 * before every really start streaming
+	 */
+	for (frame = 0; frame < cam->nbufs; frame++)
+		clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
+
 	return mcam_read_setup(cam);
 }
 
@@ -977,6 +1170,12 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
 		return -EINVAL;
 	mcam_ctlr_stop_dma(cam);
 	/*
+	 * Reset the CCIC PHY after stopping streaming,
+	 * otherwise, the CCIC may be unstable.
+	 */
+	if (cam->ctlr_reset)
+		cam->ctlr_reset(cam);
+	/*
 	 * VB2 reclaims the buffers, so we need to forget
 	 * about them.
 	 */
@@ -1087,6 +1286,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 #ifdef MCAM_MODE_DMA_CONTIG
 		vq->ops = &mcam_vb2_ops;
 		vq->mem_ops = &vb2_dma_contig_memops;
+		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
 		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_contig;
@@ -1097,6 +1297,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 #ifdef MCAM_MODE_DMA_SG
 		vq->ops = &mcam_vb2_sg_ops;
 		vq->mem_ops = &vb2_dma_sg_memops;
+		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_sg;
 		cam->frame_complete = mcam_dma_sg_done;
@@ -1247,7 +1448,15 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
 	ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
 	mutex_unlock(&cam->s_mutex);
 	v4l2_fill_pix_format(pix, &mbus_fmt);
-	pix->bytesperline = pix->width * f->bpp;
+	switch (f->pixelformat) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		pix->bytesperline = pix->width * 3 / 2;
+		break;
+	default:
+		pix->bytesperline = pix->width * f->bpp;
+		break;
+	}
 	pix->sizeimage = pix->height * pix->bytesperline;
 	return ret;
 }
@@ -1475,7 +1684,9 @@ static int mcam_v4l_open(struct file *filp)
 		ret = mcam_setup_vb2(cam);
 		if (ret)
 			goto out;
-		mcam_ctlr_power_up(cam);
+		ret = mcam_ctlr_power_up(cam);
+		if (ret)
+			goto out;
 		__mcam_cam_reset(cam);
 		mcam_set_config_needed(cam, 1);
 	}
@@ -1498,10 +1709,12 @@ static int mcam_v4l_release(struct file *filp)
 	if (cam->users == 0) {
 		mcam_ctlr_stop_dma(cam);
 		mcam_cleanup_vb2(cam);
+		mcam_disable_mipi(cam);
 		mcam_ctlr_power_down(cam);
 		if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
 			mcam_free_dma_bufs(cam);
 	}
+
 	mutex_unlock(&cam->s_mutex);
 	return 0;
 }
@@ -1617,9 +1830,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	 * each time.
 	 */
 	for (frame = 0; frame < cam->nbufs; frame++)
-		if (irqs & (IRQ_EOF0 << frame)) {
+		if (irqs & (IRQ_EOF0 << frame) &&
+			test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) {
 			mcam_frame_complete(cam, frame);
 			handled = 1;
+			clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
 			if (cam->buffer_mode == B_DMA_sg)
 				break;
 		}
@@ -1628,9 +1843,15 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	 * code assumes that we won't get multiple frame interrupts
 	 * at once; may want to rethink that.
 	 */
-	if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) {
+	for (frame = 0; frame < cam->nbufs; frame++) {
+		if (irqs & (IRQ_SOF0 << frame)) {
+			set_bit(CF_FRAME_SOF0 + frame, &cam->flags);
+			handled = IRQ_HANDLED;
+		}
+	}
+
+	if (handled == IRQ_HANDLED) {
 		set_bit(CF_DMA_ACTIVE, &cam->flags);
-		handled = 1;
 		if (cam->buffer_mode == B_DMA_sg)
 			mcam_ctlr_stop(cam);
 	}
@@ -1787,7 +2008,11 @@ int mccic_resume(struct mcam_camera *cam)
 
 	mutex_lock(&cam->s_mutex);
 	if (cam->users > 0) {
-		mcam_ctlr_power_up(cam);
+		ret = mcam_ctlr_power_up(cam);
+		if (ret) {
+			mutex_unlock(&cam->s_mutex);
+			return ret;
+		}
 		__mcam_cam_reset(cam);
 	} else {
 		mcam_ctlr_power_down(cam);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 520c8de..e0e628c 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -88,6 +88,8 @@ struct mcam_frame_state {
 	unsigned int delivered;
 };
 
+#define NR_MCAM_CLK 3
+
 /*
  * A description of one of our devices.
  * Locking: controlled by s_mutex.  Certain fields, however, require
@@ -108,11 +110,33 @@ struct mcam_camera {
 	short int clock_speed;	/* Sensor clock speed, default 30 */
 	short int use_smbus;	/* SMBUS or straight I2c? */
 	enum mcam_buffer_mode buffer_mode;
+
+	int mclk_min;	/* The minimal value of mclk */
+	int mclk_src;	/* which clock source the mclk derives from */
+	int mclk_div;	/* Clock Divider Value for MCLK */
+
+	int ccic_id;
+	enum v4l2_mbus_type bus_type;
+	/* MIPI support */
+	/* The dphy config value, allocated in board file
+	 * dphy[0]: DPHY3
+	 * dphy[1]: DPHY5
+	 * dphy[2]: DPHY6
+	 */
+	int *dphy;
+	bool mipi_enabled;	/* flag whether mipi is enabled already */
+	int lane;			/* lane number */
+
+	/* clock tree support */
+	struct clk *clk[NR_MCAM_CLK];
+
 	/*
 	 * Callbacks from the core to the platform code.
 	 */
-	void (*plat_power_up) (struct mcam_camera *cam);
+	int (*plat_power_up) (struct mcam_camera *cam);
 	void (*plat_power_down) (struct mcam_camera *cam);
+	void (*calc_dphy) (struct mcam_camera *cam);
+	void (*ctlr_reset) (struct mcam_camera *cam);
 
 	/*
 	 * Everything below here is private to the mcam core and
@@ -225,6 +249,23 @@ int mccic_resume(struct mcam_camera *cam);
 #define REG_Y0BAR	0x00
 #define REG_Y1BAR	0x04
 #define REG_Y2BAR	0x08
+#define REG_U0BAR	0x0c
+#define REG_U1BAR	0x10
+#define REG_U2BAR	0x14
+#define REG_V0BAR	0x18
+#define REG_V1BAR	0x1C
+#define REG_V2BAR	0x20
+
+/*
+ * register definitions for MIPI support
+ */
+#define REG_CSI2_CTRL0	0x100
+#define   CSI2_C0_MIPI_EN (0x1 << 0)
+#define   CSI2_C0_ACT_LANE(n) ((n-1) << 1)
+#define REG_CSI2_DPHY3	0x12c
+#define REG_CSI2_DPHY5	0x134
+#define REG_CSI2_DPHY6	0x138
+
 /* ... */
 
 #define REG_IMGPITCH	0x24	/* Image pitch register */
@@ -293,13 +334,16 @@ int mccic_resume(struct mcam_camera *cam);
 #define	  C0_YUVE_XUVY	  0x00020000	/* 420: .UVY		*/
 #define	  C0_YUVE_XVUY	  0x00030000	/* 420: .VUY		*/
 /* Bayer bits 18,19 if needed */
+#define	  C0_EOF_VSYNC	  0x00400000	/* Generate EOF by VSYNC */
+#define	  C0_VEDGE_CTRL   0x00800000	/* Detect falling edge of VSYNC */
 #define	  C0_HPOL_LOW	  0x01000000	/* HSYNC polarity active low */
 #define	  C0_VPOL_LOW	  0x02000000	/* VSYNC polarity active low */
 #define	  C0_VCLK_LOW	  0x04000000	/* VCLK on falling edge */
 #define	  C0_DOWNSCALE	  0x08000000	/* Enable downscaler */
-#define	  C0_SIFM_MASK	  0xc0000000	/* SIF mode bits */
+/* SIFMODE */
 #define	  C0_SIF_HVSYNC	  0x00000000	/* Use H/VSYNC */
-#define	  CO_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
+#define	  C0_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
+#define	  C0_SIFM_MASK	  0xc0000000	/* SIF mode bits */
 
 /* Bits below C1_444ALPHA are not present in Cafe */
 #define REG_CTRL1	0x40	/* Control 1 */
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index a634888..f06daa4 100644
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/pm.h>
+#include <linux/clk.h>
 
 #include "mcam-core.h"
 
@@ -33,11 +34,14 @@ MODULE_ALIAS("platform:mmp-camera");
 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
 MODULE_LICENSE("GPL");
 
+static char *mcam_clks[] = {"CCICAXICLK", "CCICFUNCLK", "CCICPHYCLK"};
+
 struct mmp_camera {
 	void *power_regs;
 	struct platform_device *pdev;
 	struct mcam_camera mcam;
 	struct list_head devlist;
+	struct clk *mipi_clk;
 	int irq;
 };
 
@@ -101,6 +105,27 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
 #define CPU_SUBSYS_PMU_BASE	0xd4282800
 #define REG_CCIC_DCGCR		0x28	/* CCIC dyn clock gate ctrl reg */
 #define REG_CCIC_CRCR		0x50	/* CCIC clk reset ctrl reg	*/
+#define REG_CCIC2_CRCR		0xf4	/* CCIC2 clk reset ctrl reg	*/
+
+static void mcam_clk_enable(struct mcam_camera *mcam)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_MCAM_CLK; i++) {
+		if (!IS_ERR(mcam->clk[i]))
+			clk_prepare_enable(mcam->clk[i]);
+	}
+}
+
+static void mcam_clk_disable(struct mcam_camera *mcam)
+{
+	int i;
+
+	for (i = NR_MCAM_CLK - 1; i >= 0; i--) {
+		if (!IS_ERR(mcam->clk[i]))
+			clk_disable_unprepare(mcam->clk[i]);
+	}
+}
 
 /*
  * Power control.
@@ -112,10 +137,17 @@ static void mmpcam_power_up_ctlr(struct mmp_camera *cam)
 	mdelay(1);
 }
 
-static void mmpcam_power_up(struct mcam_camera *mcam)
+static int mmpcam_power_up(struct mcam_camera *mcam)
 {
 	struct mmp_camera *cam = mcam_to_cam(mcam);
 	struct mmp_camera_platform_data *pdata;
+
+	if (mcam->bus_type == V4L2_MBUS_CSI2) {
+		cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
+		if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
+			return PTR_ERR(cam->mipi_clk);
+	}
+
 /*
  * Turn on power and clocks to the controller.
  */
@@ -132,6 +164,10 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
 	mdelay(5);
 	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
 	mdelay(5);
+
+	mcam_clk_enable(mcam);
+
+	return 0;
 }
 
 static void mmpcam_power_down(struct mcam_camera *mcam)
@@ -149,8 +185,133 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
 	pdata = cam->pdev->dev.platform_data;
 	gpio_set_value(pdata->sensor_power_gpio, 0);
 	gpio_set_value(pdata->sensor_reset_gpio, 0);
+
+	if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) {
+		if (cam->mipi_clk)
+			devm_clk_put(mcam->dev, cam->mipi_clk);
+		cam->mipi_clk = NULL;
+	}
+
+	mcam_clk_disable(mcam);
 }
 
+void mcam_ctlr_reset(struct mcam_camera *mcam)
+{
+	unsigned long val;
+	struct mmp_camera *cam = mcam_to_cam(mcam);
+
+	if (mcam->ccic_id) {
+		/*
+		 * Using CCIC2
+		 */
+		val = ioread32(cam->power_regs + REG_CCIC2_CRCR);
+		iowrite32(val & ~0x2, cam->power_regs + REG_CCIC2_CRCR);
+		iowrite32(val | 0x2, cam->power_regs + REG_CCIC2_CRCR);
+	} else {
+		/*
+		 * Using CCIC1
+		 */
+		val = ioread32(cam->power_regs + REG_CCIC_CRCR);
+		iowrite32(val & ~0x2, cam->power_regs + REG_CCIC_CRCR);
+		iowrite32(val | 0x2, cam->power_regs + REG_CCIC_CRCR);
+	}
+}
+
+/*
+ * calc the dphy register values
+ * There are three dphy registers being used.
+ * dphy[0] - CSI2_DPHY3
+ * dphy[1] - CSI2_DPHY5
+ * dphy[2] - CSI2_DPHY6
+ * CSI2_DPHY3 and CSI2_DPHY6 can be set with a default value
+ * or be calculated dynamically
+ */
+void mmpcam_calc_dphy(struct mcam_camera *mcam)
+{
+	struct mmp_camera *cam = mcam_to_cam(mcam);
+	struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data;
+	struct device *dev = &cam->pdev->dev;
+	unsigned long tx_clk_esc;
+
+	/*
+	 * If CSI2_DPHY3 is calculated dynamically,
+	 * pdata->lane_clk should be already set
+	 * either in the board driver statically
+	 * or in the sensor driver dynamically.
+	 */
+	/*
+	 * dphy[0] - CSI2_DPHY3:
+	 *  bit 0 ~ bit 7: HS Term Enable.
+	 *   defines the time that the DPHY
+	 *   wait before enabling the data
+	 *   lane termination after detecting
+	 *   that the sensor has driven the data
+	 *   lanes to the LP00 bridge state.
+	 *   The value is calculated by:
+	 *   (Max T(D_TERM_EN)/Period(DDR)) - 1
+	 *  bit 8 ~ bit 15: HS_SETTLE
+	 *   Time interval during which the HS
+	 *   receiver shall ignore any Data Lane
+	 *   HS transistions.
+	 *   The vaule has been calibrated on
+	 *   different boards. It seems to work well.
+	 *
+	 *  More detail please refer
+	 *  MIPI Alliance Spectification for D-PHY
+	 *  document for explanation of HS-SETTLE
+	 *  and D-TERM-EN.
+	 */
+	switch (pdata->dphy3_algo) {
+	case DPHY3_ALGO_PXA910:
+		/*
+		 * Calculate CSI2_DPHY3 algo for PXA910
+		 */
+		pdata->dphy[0] =
+			(((1 + (pdata->lane_clk * 80) / 1000) & 0xff) << 8)
+			| (1 + pdata->lane_clk * 35 / 1000);
+		break;
+	case DPHY3_ALGO_PXA2128:
+		/*
+		 * Calculate CSI2_DPHY3 algo for PXA2128
+		 */
+		pdata->dphy[0] =
+			(((2 + (pdata->lane_clk * 110) / 1000) & 0xff) << 8)
+			| (1 + pdata->lane_clk * 35 / 1000);
+		break;
+	default:
+		/*
+		 * Use default CSI2_DPHY3 value for PXA688/PXA988
+		 */
+		dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n");
+	}
+
+	/*
+	 * mipi_clk will never be changed, it is a fixed value on MMP
+	 */
+	if (IS_ERR(cam->mipi_clk))
+		return;
+
+	/* get the escape clk, this is hard coded */
+	tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12;
+
+	/*
+	 * dphy[2] - CSI2_DPHY6:
+	 * bit 0 ~ bit 7: CK Term Enable
+	 *  Time for the Clock Lane receiver to enable the HS line
+	 *  termination. The value is calculated similarly with
+	 *  HS Term Enable
+	 * bit 8 ~ bit 15: CK Settle
+	 *  Time interval during which the HS receiver shall ignore
+	 *  any Clock Lane HS transitions.
+	 *  The value is calibrated on the boards.
+	 */
+	pdata->dphy[2] =
+		((((534 * tx_clk_esc) / 2000 - 1) & 0xff) << 8)
+		| (((38 * tx_clk_esc) / 1000 - 1) & 0xff);
+
+	dev_dbg(dev, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
+		pdata->dphy[0], pdata->dphy[1], pdata->dphy[2]);
+}
 
 static irqreturn_t mmpcam_irq(int irq, void *data)
 {
@@ -164,6 +325,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
 	return IRQ_RETVAL(handled);
 }
 
+static void mcam_deinit_clk(struct mcam_camera *mcam)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_MCAM_CLK; i++) {
+		if (!IS_ERR(mcam->clk[i])) {
+			if (mcam->clk[i])
+				devm_clk_put(mcam->dev, mcam->clk[i]);
+		}
+		mcam->clk[i] = NULL;
+	}
+}
+
+static void mcam_init_clk(struct mcam_camera *mcam)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_MCAM_CLK; i++) {
+		if (mcam_clks[i] != NULL) {
+			/* Some clks are not necessary on some boards
+			 * We still try to run even it fails getting clk
+			 */
+			mcam->clk[i] = devm_clk_get(mcam->dev, mcam_clks[i]);
+			if (IS_ERR(mcam->clk[i]))
+				dev_warn(mcam->dev, "Could not get clk: %s\n",
+						mcam_clks[i]);
+		}
+	}
+}
 
 static int mmpcam_probe(struct platform_device *pdev)
 {
@@ -173,17 +363,32 @@ static int mmpcam_probe(struct platform_device *pdev)
 	struct mmp_camera_platform_data *pdata;
 	int ret;
 
-	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENODEV;
+
+	cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
 	if (cam == NULL)
 		return -ENOMEM;
 	cam->pdev = pdev;
+	cam->mipi_clk = NULL;
 	INIT_LIST_HEAD(&cam->devlist);
 
 	mcam = &cam->mcam;
 	mcam->plat_power_up = mmpcam_power_up;
 	mcam->plat_power_down = mmpcam_power_down;
+	mcam->ctlr_reset = mcam_ctlr_reset;
+	mcam->calc_dphy = mmpcam_calc_dphy;
 	mcam->dev = &pdev->dev;
 	mcam->use_smbus = 0;
+	mcam->ccic_id = pdev->id;
+	mcam->mclk_min = pdata->mclk_min;
+	mcam->mclk_src = pdata->mclk_src;
+	mcam->mclk_div = pdata->mclk_div;
+	mcam->bus_type = pdata->bus_type;
+	mcam->dphy = pdata->dphy;
+	mcam->mipi_enabled = false;
+	mcam->lane = pdata->lane;
 	mcam->chip_id = MCAM_ARMADA610;
 	mcam->buffer_mode = B_DMA_sg;
 	spin_lock_init(&mcam->dev_lock);
@@ -193,15 +398,11 @@ static int mmpcam_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "no iomem resource!\n");
-		ret = -ENODEV;
-		goto out_free;
-	}
-	mcam->regs = ioremap(res->start, resource_size(res));
-	if (mcam->regs == NULL) {
-		dev_err(&pdev->dev, "MMIO ioremap fail\n");
-		ret = -ENODEV;
-		goto out_free;
+		return -ENODEV;
 	}
+	mcam->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mcam->regs))
+		return PTR_ERR(mcam->regs);
 	mcam->regs_size = resource_size(res);
 	/*
 	 * Power/clock memory is elsewhere; get it too.  Perhaps this
@@ -210,50 +411,51 @@ static int mmpcam_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "no power resource!\n");
-		ret = -ENODEV;
-		goto out_unmap1;
-	}
-	cam->power_regs = ioremap(res->start, resource_size(res));
-	if (cam->power_regs == NULL) {
-		dev_err(&pdev->dev, "power MMIO ioremap fail\n");
-		ret = -ENODEV;
-		goto out_unmap1;
+		return -ENODEV;
 	}
+	cam->power_regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(cam->power_regs))
+		return PTR_ERR(cam->power_regs);
 	/*
 	 * Find the i2c adapter.  This assumes, of course, that the
 	 * i2c bus is already up and functioning.
 	 */
-	pdata = pdev->dev.platform_data;
 	mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
 	if (mcam->i2c_adapter == NULL) {
-		ret = -ENODEV;
 		dev_err(&pdev->dev, "No i2c adapter\n");
-		goto out_unmap2;
+		return -ENODEV;
 	}
 	/*
 	 * Sensor GPIO pins.
 	 */
-	ret = gpio_request(pdata->sensor_power_gpio, "cam-power");
+	ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio,
+							"cam-power");
 	if (ret) {
 		dev_err(&pdev->dev, "Can't get sensor power gpio %d",
 				pdata->sensor_power_gpio);
-		goto out_unmap2;
+		return ret;
 	}
 	gpio_direction_output(pdata->sensor_power_gpio, 0);
-	ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset");
+	ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio,
+							"cam-reset");
 	if (ret) {
 		dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
 				pdata->sensor_reset_gpio);
-		goto out_gpio;
+		return ret;
 	}
 	gpio_direction_output(pdata->sensor_reset_gpio, 0);
+
+	mcam_init_clk(mcam);
+
 	/*
 	 * Power the device up and hand it off to the core.
 	 */
-	mmpcam_power_up(mcam);
+	ret = mmpcam_power_up(mcam);
+	if (ret)
+		goto out_deinit_clk;
 	ret = mccic_register(mcam);
 	if (ret)
-		goto out_gpio2;
+		goto out_power_down;
 	/*
 	 * Finally, set up our IRQ now that the core is ready to
 	 * deal with it.
@@ -264,8 +466,8 @@ static int mmpcam_probe(struct platform_device *pdev)
 		goto out_unregister;
 	}
 	cam->irq = res->start;
-	ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED,
-			"mmp-camera", mcam);
+	ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED,
+					"mmp-camera", mcam);
 	if (ret == 0) {
 		mmpcam_add_device(cam);
 		return 0;
@@ -273,17 +475,10 @@ static int mmpcam_probe(struct platform_device *pdev)
 
 out_unregister:
 	mccic_shutdown(mcam);
-out_gpio2:
+out_power_down:
 	mmpcam_power_down(mcam);
-	gpio_free(pdata->sensor_reset_gpio);
-out_gpio:
-	gpio_free(pdata->sensor_power_gpio);
-out_unmap2:
-	iounmap(cam->power_regs);
-out_unmap1:
-	iounmap(mcam->regs);
-out_free:
-	kfree(cam);
+out_deinit_clk:
+	mcam_deinit_clk(mcam);
 	return ret;
 }
 
@@ -300,6 +495,7 @@ static int mmpcam_remove(struct mmp_camera *cam)
 	pdata = cam->pdev->dev.platform_data;
 	gpio_free(pdata->sensor_reset_gpio);
 	gpio_free(pdata->sensor_power_gpio);
+	mcam_deinit_clk(mcam);
 	iounmap(cam->power_regs);
 	iounmap(mcam->regs);
 	kfree(cam);
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 553d87e..fd6289d 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -784,6 +784,7 @@ static int g2d_probe(struct platform_device *pdev)
 	}
 	*vfd = g2d_videodev;
 	vfd->lock = &dev->mutex;
+	vfd->v4l2_dev = &dev->v4l2_dev;
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
 	if (ret) {
 		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 5296385..4f6dd42 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -344,7 +344,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		pix_mp->num_planes = 2;
 		/* Set pixelformat to the format in which MFC
 		   outputs the decoded frame */
-		pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT;
+		pix_mp->pixelformat = ctx->dst_fmt->fourcc;
 		pix_mp->plane_fmt[0].bytesperline = ctx->buf_width;
 		pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;
 		pix_mp->plane_fmt[1].bytesperline = ctx->buf_width;
@@ -382,10 +382,16 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 			mfc_err("Unsupported format for source.\n");
 			return -EINVAL;
 		}
-		if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
-			mfc_err("Not supported format.\n");
+		if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
+			mfc_err("Unknown codec\n");
 			return -EINVAL;
 		}
+		if (!IS_MFCV6(dev)) {
+			if (fmt->fourcc == V4L2_PIX_FMT_VP8) {
+				mfc_err("Not supported format.\n");
+				return -EINVAL;
+			}
+		}
 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		fmt = find_format(f, MFC_FMT_RAW);
 		if (!fmt) {
@@ -411,7 +417,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 	struct s5p_mfc_dev *dev = video_drvdata(file);
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
 	int ret = 0;
-	struct s5p_mfc_fmt *fmt;
 	struct v4l2_pix_format_mplane *pix_mp;
 
 	mfc_debug_enter();
@@ -425,54 +430,32 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		goto out;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		fmt = find_format(f, MFC_FMT_RAW);
-		if (!fmt) {
-			mfc_err("Unsupported format for source.\n");
-			return -EINVAL;
-		}
-		if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
-			mfc_err("Not supported format.\n");
-			return -EINVAL;
-		} else if (IS_MFCV6(dev) &&
-				(fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
-			mfc_err("Not supported format.\n");
-			return -EINVAL;
-		}
-		ctx->dst_fmt = fmt;
-		mfc_debug_leave();
-		return ret;
-	} else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		mfc_err("Wrong type error for S_FMT : %d", f->type);
-		return -EINVAL;
-	}
-	fmt = find_format(f, MFC_FMT_DEC);
-	if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
-		mfc_err("Unknown codec\n");
-		ret = -EINVAL;
+		/* dst_fmt is validated by call to vidioc_try_fmt */
+		ctx->dst_fmt = find_format(f, MFC_FMT_RAW);
+		ret = 0;
 		goto out;
-	}
-	if (fmt->type != MFC_FMT_DEC) {
-		mfc_err("Wrong format selected, you should choose "
-					"format for decoding\n");
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		/* src_fmt is validated by call to vidioc_try_fmt */
+		ctx->src_fmt = find_format(f, MFC_FMT_DEC);
+		ctx->codec_mode = ctx->src_fmt->codec_mode;
+		mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
+		pix_mp->height = 0;
+		pix_mp->width = 0;
+		if (pix_mp->plane_fmt[0].sizeimage)
+			ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
+		else
+			pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
+								DEF_CPB_SIZE;
+		pix_mp->plane_fmt[0].bytesperline = 0;
+		ctx->state = MFCINST_INIT;
+		ret = 0;
+		goto out;
+	} else {
+		mfc_err("Wrong type error for S_FMT : %d", f->type);
 		ret = -EINVAL;
 		goto out;
 	}
-	if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
-		mfc_err("Not supported format.\n");
-		return -EINVAL;
-	}
-	ctx->src_fmt = fmt;
-	ctx->codec_mode = fmt->codec_mode;
-	mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
-	pix_mp->height = 0;
-	pix_mp->width = 0;
-	if (pix_mp->plane_fmt[0].sizeimage)
-		ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
-	else
-		pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
-								DEF_CPB_SIZE;
-	pix_mp->plane_fmt[0].bytesperline = 0;
-	ctx->state = MFCINST_INIT;
+
 out:
 	mfc_debug_leave();
 	return ret;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 2549967..59e56f4 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -906,6 +906,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 
 static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
+	struct s5p_mfc_dev *dev = video_drvdata(file);
 	struct s5p_mfc_fmt *fmt;
 	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
 
@@ -930,6 +931,18 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 			return -EINVAL;
 		}
 
+		if (!IS_MFCV6(dev)) {
+			if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
+				mfc_err("Not supported format.\n");
+				return -EINVAL;
+			}
+		} else if (IS_MFCV6(dev)) {
+			if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+				mfc_err("Not supported format.\n");
+				return -EINVAL;
+			}
+		}
+
 		if (fmt->num_planes != pix_fmt_mp->num_planes) {
 			mfc_err("failed to try output format\n");
 			return -EINVAL;
@@ -947,7 +960,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
 	struct s5p_mfc_dev *dev = video_drvdata(file);
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-	struct s5p_mfc_fmt *fmt;
 	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
 	int ret = 0;
 
@@ -960,13 +972,9 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		goto out;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		fmt = find_format(f, MFC_FMT_ENC);
-		if (!fmt) {
-			mfc_err("failed to set capture format\n");
-			return -EINVAL;
-		}
+		/* dst_fmt is validated by call to vidioc_try_fmt */
+		ctx->dst_fmt = find_format(f, MFC_FMT_ENC);
 		ctx->state = MFCINST_INIT;
-		ctx->dst_fmt = fmt;
 		ctx->codec_mode = ctx->dst_fmt->codec_mode;
 		ctx->enc_dst_buf_size =	pix_fmt_mp->plane_fmt[0].sizeimage;
 		pix_fmt_mp->plane_fmt[0].bytesperline = 0;
@@ -987,28 +995,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		}
 		mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		fmt = find_format(f, MFC_FMT_RAW);
-		if (!fmt) {
-			mfc_err("failed to set output format\n");
-			return -EINVAL;
-		}
-
-		if (!IS_MFCV6(dev) &&
-				(fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
-			mfc_err("Not supported format.\n");
-			return -EINVAL;
-		} else if (IS_MFCV6(dev) &&
-				(fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
-			mfc_err("Not supported format.\n");
-			return -EINVAL;
-		}
-
-		if (fmt->num_planes != pix_fmt_mp->num_planes) {
-			mfc_err("failed to set output format\n");
-			ret = -EINVAL;
-			goto out;
-		}
-		ctx->src_fmt = fmt;
+		/* src_fmt is validated by call to vidioc_try_fmt */
+		ctx->src_fmt = find_format(f, MFC_FMT_RAW);
 		ctx->img_width = pix_fmt_mp->width;
 		ctx->img_height = pix_fmt_mp->height;
 		mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode);
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index aa4cca3..744e43b 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -359,7 +359,7 @@ static int sh_veu_context_init(struct sh_veu_dev *veu)
 	veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu,
 					 sh_veu_queue_init);
 
-	return PTR_RET(veu->m2m_ctx);
+	return PTR_ERR_OR_ZERO(veu->m2m_ctx);
 }
 
 static int sh_veu_querycap(struct file *file, void *priv,
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index f2de006..dae9716 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -1837,9 +1837,9 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
 		for (j = 0; pcdev->pdata->asd_sizes[j]; j++) {
 			for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) {
 				dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n",
-					__func__, i, (*asd)->bus_type);
-				if ((*asd)->bus_type == V4L2_ASYNC_BUS_PLATFORM &&
-				    !strncmp(name, (*asd)->match.platform.name,
+					__func__, i, (*asd)->match_type);
+				if ((*asd)->match_type == V4L2_ASYNC_MATCH_DEVNAME &&
+				    !strncmp(name, (*asd)->match.device_name.name,
 					     sizeof(name) - 1)) {
 					pcdev->csi2_asd = *asd;
 					break;
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 2dd0e52..4b42572 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -1475,7 +1475,7 @@ static int scan_async_group(struct soc_camera_host *ici,
 			break;
 	}
 
-	if (i == size || asd[i]->bus_type != V4L2_ASYNC_BUS_I2C) {
+	if (i == size || asd[i]->match_type != V4L2_ASYNC_MATCH_I2C) {
 		/* All useless */
 		dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n");
 		return -ENODEV;
@@ -1501,7 +1501,7 @@ static int scan_async_group(struct soc_camera_host *ici,
 		return -ENOMEM;
 	}
 
-	sasc->notifier.subdev = asd;
+	sasc->notifier.subdevs = asd;
 	sasc->notifier.num_subdevs = size;
 	sasc->notifier.bound = soc_camera_async_bound;
 	sasc->notifier.unbind = soc_camera_async_unbind;
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 177bcbd..705dd6f 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -26,6 +26,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
 #include "radio-isa.h"
+#include "lm7000.h"
 
 MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the Aztech radio card.");
@@ -54,18 +55,29 @@ struct aztech {
 	int curvol;
 };
 
-static void send_0_byte(struct aztech *az)
-{
-	udelay(radio_wait_time);
-	outb_p(2 + az->curvol, az->isa.io);
-	outb_p(64 + 2 + az->curvol, az->isa.io);
-}
+/* bit definitions for register read */
+#define AZTECH_BIT_NOT_TUNED	(1 << 0)
+#define AZTECH_BIT_MONO		(1 << 1)
+/* bit definitions for register write */
+#define AZTECH_BIT_TUN_CE	(1 << 1)
+#define AZTECH_BIT_TUN_CLK	(1 << 6)
+#define AZTECH_BIT_TUN_DATA	(1 << 7)
+/* bits 0 and 2 are volume control, bits 3..5 are not connected */
 
-static void send_1_byte(struct aztech *az)
+static void aztech_set_pins(void *handle, u8 pins)
 {
-	udelay(radio_wait_time);
-	outb_p(128 + 2 + az->curvol, az->isa.io);
-	outb_p(128 + 64 + 2 + az->curvol, az->isa.io);
+	struct radio_isa_card *isa = handle;
+	struct aztech *az = container_of(isa, struct aztech, isa);
+	u8 bits = az->curvol;
+
+	if (pins & LM7000_DATA)
+		bits |= AZTECH_BIT_TUN_DATA;
+	if (pins & LM7000_CLK)
+		bits |= AZTECH_BIT_TUN_CLK;
+	if (pins & LM7000_CE)
+		bits |= AZTECH_BIT_TUN_CE;
+
+	outb_p(bits, az->isa.io);
 }
 
 static struct radio_isa_card *aztech_alloc(void)
@@ -77,58 +89,21 @@ static struct radio_isa_card *aztech_alloc(void)
 
 static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq)
 {
-	struct aztech *az = container_of(isa, struct aztech, isa);
-	int  i;
-
-	freq += 171200;			/* Add 10.7 MHz IF		*/
-	freq /= 800;			/* Convert to 50 kHz units	*/
-
-	send_0_byte(az);		/*  0: LSB of frequency       */
-
-	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)  */
-		if (freq & (1 << i))
-			send_1_byte(az);
-		else
-			send_0_byte(az);
-
-	send_0_byte(az);		/* 14: test bit - always 0    */
-	send_0_byte(az);		/* 15: test bit - always 0    */
-	send_0_byte(az);		/* 16: band data 0 - always 0 */
-	if (isa->stereo)		/* 17: stereo (1 to enable)   */
-		send_1_byte(az);
-	else
-		send_0_byte(az);
-
-	send_1_byte(az);		/* 18: band data 1 - unknown  */
-	send_0_byte(az);		/* 19: time base - always 0   */
-	send_0_byte(az);		/* 20: spacing (0 = 25 kHz)   */
-	send_1_byte(az);		/* 21: spacing (1 = 25 kHz)   */
-	send_0_byte(az);		/* 22: spacing (0 = 25 kHz)   */
-	send_1_byte(az);		/* 23: AM/FM (FM = 1, always) */
-
-	/* latch frequency */
-
-	udelay(radio_wait_time);
-	outb_p(128 + 64 + az->curvol, az->isa.io);
+	lm7000_set_freq(freq, isa, aztech_set_pins);
 
 	return 0;
 }
 
-/* thanks to Michael Dwyer for giving me a dose of clues in
- * the signal strength department..
- *
- * This card has a stereo bit - bit 0 set = mono, not set = stereo
- */
 static u32 aztech_g_rxsubchans(struct radio_isa_card *isa)
 {
-	if (inb(isa->io) & 1)
+	if (inb(isa->io) & AZTECH_BIT_MONO)
 		return V4L2_TUNER_SUB_MONO;
 	return V4L2_TUNER_SUB_STEREO;
 }
 
-static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo)
+static u32 aztech_g_signal(struct radio_isa_card *isa)
 {
-	return aztech_s_frequency(isa, isa->freq);
+	return (inb(isa->io) & AZTECH_BIT_NOT_TUNED) ? 0 : 0xffff;
 }
 
 static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
@@ -146,8 +121,8 @@ static const struct radio_isa_ops aztech_ops = {
 	.alloc = aztech_alloc,
 	.s_mute_volume = aztech_s_mute_volume,
 	.s_frequency = aztech_s_frequency,
-	.s_stereo = aztech_s_stereo,
 	.g_rxsubchans = aztech_g_rxsubchans,
+	.g_signal = aztech_g_signal,
 };
 
 static const int aztech_ioports[] = { 0x350, 0x358 };
@@ -165,7 +140,7 @@ static struct radio_isa_driver aztech_driver = {
 	.radio_nr_params = radio_nr,
 	.io_ports = aztech_ioports,
 	.num_of_io_ports = ARRAY_SIZE(aztech_ioports),
-	.region_size = 2,
+	.region_size = 8,
 	.card = "Aztech Radio",
 	.ops = &aztech_ops,
 	.has_stereo = true,
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index bd4d3a7..1d1c9e1 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -200,15 +200,4 @@ static struct pci_driver maxiradio_driver = {
 	.remove		= maxiradio_remove,
 };
 
-static int __init maxiradio_init(void)
-{
-	return pci_register_driver(&maxiradio_driver);
-}
-
-static void __exit maxiradio_exit(void)
-{
-	pci_unregister_driver(&maxiradio_driver);
-}
-
-module_init(maxiradio_init);
-module_exit(maxiradio_exit);
+module_pci_driver(maxiradio_driver);
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index ed184f6..c1444f8 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -476,7 +476,7 @@ select_timeout:
 }
 
 /* Enable the device for receive */
-static void ene_rx_enable(struct ene_device *dev)
+static void ene_rx_enable_hw(struct ene_device *dev)
 {
 	u8 reg_value;
 
@@ -504,11 +504,17 @@ static void ene_rx_enable(struct ene_device *dev)
 
 	/* enter idle mode */
 	ir_raw_event_set_idle(dev->rdev, true);
+}
+
+/* Enable the device for receive - wrapper to track the state*/
+static void ene_rx_enable(struct ene_device *dev)
+{
+	ene_rx_enable_hw(dev);
 	dev->rx_enabled = true;
 }
 
 /* Disable the device receiver */
-static void ene_rx_disable(struct ene_device *dev)
+static void ene_rx_disable_hw(struct ene_device *dev)
 {
 	/* disable inputs */
 	ene_rx_enable_cir_engine(dev, false);
@@ -516,8 +522,13 @@ static void ene_rx_disable(struct ene_device *dev)
 
 	/* disable hardware IRQ and firmware flag */
 	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
-
 	ir_raw_event_set_idle(dev->rdev, true);
+}
+
+/* Disable the device receiver - wrapper to track the state */
+static void ene_rx_disable(struct ene_device *dev)
+{
+	ene_rx_disable_hw(dev);
 	dev->rx_enabled = false;
 }
 
@@ -1022,6 +1033,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 	spin_lock_init(&dev->hw_lock);
 
 	dev->hw_io = pnp_port_start(pnp_dev, 0);
+	dev->irq = pnp_irq(pnp_dev, 0);
+
 
 	pnp_set_drvdata(pnp_dev, dev);
 	dev->pnp_dev = pnp_dev;
@@ -1085,7 +1098,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 		goto exit_unregister_device;
 	}
 
-	dev->irq = pnp_irq(pnp_dev, 0);
 	if (request_irq(dev->irq, ene_isr,
 			IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
 		goto exit_release_hw_io;
@@ -1123,9 +1135,8 @@ static void ene_remove(struct pnp_dev *pnp_dev)
 }
 
 /* enable wake on IR (wakes on specific button on original remote) */
-static void ene_enable_wake(struct ene_device *dev, int enable)
+static void ene_enable_wake(struct ene_device *dev, bool enable)
 {
-	enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
 	dbg("wake on IR %s", enable ? "enabled" : "disabled");
 	ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
 }
@@ -1134,9 +1145,12 @@ static void ene_enable_wake(struct ene_device *dev, int enable)
 static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
 {
 	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
-	ene_enable_wake(dev, true);
+	bool wake = device_may_wakeup(&dev->pnp_dev->dev);
+
+	if (!wake && dev->rx_enabled)
+		ene_rx_disable_hw(dev);
 
-	/* TODO: add support for wake pattern */
+	ene_enable_wake(dev, wake);
 	return 0;
 }
 
diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h
index 6f978e8..a7911e3 100644
--- a/drivers/media/rc/ene_ir.h
+++ b/drivers/media/rc/ene_ir.h
@@ -185,7 +185,7 @@
 #define __dbg(level, format, ...)				\
 do {								\
 	if (debug >= level)					\
-		pr_debug(format "\n", ## __VA_ARGS__);		\
+		pr_info(format "\n", ## __VA_ARGS__);		\
 } while (0)
 
 #define dbg(format, ...)		__dbg(1, format, ## __VA_ARGS__)
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index a4ab2e6..19632b1 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -364,8 +364,8 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 		periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
 		bytes = DIV_ROUND_UP(periods, 127);
 		if (size + bytes > ir->bufsize) {
-			count = i;
-			break;
+			rc = -EINVAL;
+			goto out;
 		}
 		while (periods > 127) {
 			ir->packet->payload[size++] = 127 | space;
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index e456126..ed2c8a1 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -140,11 +140,20 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 		goto out;
 	}
 
+	for (i = 0; i < count; i++) {
+		if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		duration += txbuf[i];
+	}
+
 	ret = dev->tx_ir(dev, txbuf, count);
 	if (ret < 0)
 		goto out;
 
-	for (i = 0; i < ret; i++)
+	for (duration = i = 0; i < ret; i++)
 		duration += txbuf[i];
 
 	ret *= sizeof(unsigned int);
@@ -375,6 +384,7 @@ static int ir_lirc_register(struct rc_dev *dev)
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
 	drv->fops = &lirc_fops;
 	drv->dev = &dev->dev;
+	drv->rdev = dev;
 	drv->owner = THIS_MODULE;
 
 	drv->minor = lirc_register_driver(drv);
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 8dc057b..dc5cbff 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -35,6 +35,7 @@
 #include <linux/device.h>
 #include <linux/cdev.h>
 
+#include <media/rc-core.h>
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
@@ -467,6 +468,12 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 		goto error;
 	}
 
+	if (ir->d.rdev) {
+		retval = rc_open(ir->d.rdev);
+		if (retval)
+			goto error;
+	}
+
 	cdev = ir->cdev;
 	if (try_module_get(cdev->owner)) {
 		ir->open++;
@@ -511,6 +518,9 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
 
 	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
 
+	if (ir->d.rdev)
+		rc_close(ir->d.rdev);
+
 	ir->open--;
 	if (ir->attached) {
 		ir->d.set_use_dec(ir->d.data);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 1cf382a..1dedebd 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -699,19 +699,50 @@ void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle)
 }
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
 
+int rc_open(struct rc_dev *rdev)
+{
+	int rval = 0;
+
+	if (!rdev)
+		return -EINVAL;
+
+	mutex_lock(&rdev->lock);
+	if (!rdev->users++)
+		rval = rdev->open(rdev);
+
+	if (rval)
+		rdev->users--;
+
+	mutex_unlock(&rdev->lock);
+
+	return rval;
+}
+EXPORT_SYMBOL_GPL(rc_open);
+
 static int ir_open(struct input_dev *idev)
 {
 	struct rc_dev *rdev = input_get_drvdata(idev);
 
-	return rdev->open(rdev);
+	return rc_open(rdev);
+}
+
+void rc_close(struct rc_dev *rdev)
+{
+	if (rdev) {
+		mutex_lock(&rdev->lock);
+
+		 if (!--rdev->users)
+			rdev->close(rdev);
+
+		mutex_unlock(&rdev->lock);
+	}
 }
+EXPORT_SYMBOL_GPL(rc_close);
 
 static void ir_close(struct input_dev *idev)
 {
 	struct rc_dev *rdev = input_get_drvdata(idev);
-
-	 if (rdev)
-		rdev->close(rdev);
+	rc_close(rdev);
 }
 
 /* class for /sys/class/rc */
@@ -1076,7 +1107,14 @@ int rc_register_device(struct rc_dev *dev)
 	memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id));
 	dev->input_dev->phys = dev->input_phys;
 	dev->input_dev->name = dev->input_name;
+
+	/* input_register_device can call ir_open, so unlock mutex here */
+	mutex_unlock(&dev->lock);
+
 	rc = input_register_device(dev->input_dev);
+
+	mutex_lock(&dev->lock);
+
 	if (rc)
 		goto out_table;
 
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 12167a6..0042367 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -206,8 +206,6 @@ struct redrat3_dev {
 	struct timer_list rx_timeout;
 	u32 hw_timeout;
 
-	/* is the detector enabled*/
-	bool det_enabled;
 	/* Is the device currently transmitting?*/
 	bool transmitting;
 
@@ -472,32 +470,11 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3)
 		return -EIO;
 	}
 
-	rr3->det_enabled = true;
 	redrat3_issue_async(rr3);
 
 	return 0;
 }
 
-/* Disables the rr3 long range detector */
-static void redrat3_disable_detector(struct redrat3_dev *rr3)
-{
-	struct device *dev = rr3->dev;
-	u8 ret;
-
-	rr3_ftr(dev, "Entering %s\n", __func__);
-
-	ret = redrat3_send_cmd(RR3_RC_DET_DISABLE, rr3);
-	if (ret != 0)
-		dev_err(dev, "%s: failure!\n", __func__);
-
-	ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3);
-	if (ret != 0)
-		dev_warn(dev, "%s: detector status: %d, should be 0\n",
-			 __func__, ret);
-
-	rr3->det_enabled = false;
-}
-
 static inline void redrat3_delete(struct redrat3_dev *rr3,
 				  struct usb_device *udev)
 {
@@ -785,10 +762,10 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
 		return -EAGAIN;
 	}
 
-	count = min_t(unsigned, count, RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN);
+	if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN)
+		return -EINVAL;
 
 	/* rr3 will disable rc detector on transmit */
-	rr3->det_enabled = false;
 	rr3->transmitting = true;
 
 	sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
@@ -825,8 +802,8 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
 						&irdata->lens[curlencheck]);
 				curlencheck++;
 			} else {
-				count = i - 1;
-				break;
+				ret = -EINVAL;
+				goto out;
 			}
 		}
 		irdata->sigdata[i] = lencheck;
@@ -868,7 +845,6 @@ out:
 
 	rr3->transmitting = false;
 	/* rr3 re-enables rc detector because it was enabled before */
-	rr3->det_enabled = true;
 
 	return ret;
 }
@@ -1048,8 +1024,6 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
 	if (!rr3)
 		return;
 
-	redrat3_disable_detector(rr3);
-
 	usb_set_intfdata(intf, NULL);
 	rc_unregister_device(rr3->rc);
 	del_timer_sync(&rr3->rx_timeout);
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index a3c8ecf..2059d0c 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -1,6 +1,6 @@
 config DVB_USB_V2
 	tristate "Support for various USB DVB devices v2"
-	depends on DVB_CORE && USB && I2C
+	depends on DVB_CORE && USB && I2C && (RC_CORE || RC_CORE=n)
 	help
 	  By enabling this you will be able to choose the various supported
 	  USB1.1 and USB2.0 DVB devices.
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index f081360..829323e 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -3589,6 +3589,8 @@ struct usb_device_id dib0700_usb_id_table[] = {
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7790P) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE8096P) },
 /* 80 */{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT_2) },
+	{ USB_DEVICE(USB_VID_PCTV,      USB_PID_PCTV_2002E) },
+	{ USB_DEVICE(USB_VID_PCTV,      USB_PID_PCTV_2002E_SE) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -3993,12 +3995,20 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			}
 		},
 
-		.num_device_descs = 1,
+		.num_device_descs = 3,
 		.devices = {
 			{   "Hauppauge Nova-TD Stick (52009)",
 				{ &dib0700_usb_id_table[35], NULL },
 				{ NULL },
 			},
+			{   "PCTV 2002e",
+				{ &dib0700_usb_id_table[81], NULL },
+				{ NULL },
+			},
+			{   "PCTV 2002e SE",
+				{ &dib0700_usb_id_table[82], NULL },
+				{ NULL },
+			},
 		},
 
 		.rc.core = {
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c
index c2b635d..0306cb7 100644
--- a/drivers/media/usb/dvb-usb/m920x.c
+++ b/drivers/media/usb/dvb-usb/m920x.c
@@ -1212,7 +1212,7 @@ static struct dvb_usb_device_properties vp7049_properties = {
 		.rc_interval    = 150,
 		.rc_codes       = RC_MAP_TWINHAN_VP1027_DVBS,
 		.rc_query       = m920x_rc_core_query,
-		.allowed_protos = RC_TYPE_UNKNOWN,
+		.allowed_protos = RC_BIT_UNKNOWN,
 	},
 
 	.size_of_priv     = sizeof(struct m920x_state),
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 4851cc2..c4ff973 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -726,7 +726,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
 
 	*eedata = data;
 	*eedata_len = len;
-	dev_config = (void *)eedata;
+	dev_config = (void *)*eedata;
 
 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
 	case 0:
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 1a577ed..9d10334 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1008,6 +1008,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 	else
 		f->fmt.pix.field = dev->interlaced ?
 			   V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c
index d6890bc..a2275cf 100644
--- a/drivers/media/usb/gspca/vicam.c
+++ b/drivers/media/usb/gspca/vicam.c
@@ -6,7 +6,7 @@
  * Based on the usbvideo vicam driver, which is:
  *
  * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
- *                    Christopher L Cheney (ccheney@cheney.cx),
+ *                    Chris Cheney (chris.cheney@gmail.com),
  *                    Pavel Machek (pavel@ucw.cz),
  *                    John Tyner (jtyner@cs.ucr.edu),
  *                    Monroe Williams (monroe@pobox.com)
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
index cb69405..6e50707 100644
--- a/drivers/media/usb/hdpvr/hdpvr-core.c
+++ b/drivers/media/usb/hdpvr/hdpvr-core.c
@@ -303,6 +303,11 @@ static int hdpvr_probe(struct usb_interface *interface,
 
 	dev->workqueue = 0;
 
+	/* init video transfer queues first of all */
+	/* to prevent oops in hdpvr_delete() on error paths */
+	INIT_LIST_HEAD(&dev->free_buff_list);
+	INIT_LIST_HEAD(&dev->rec_buff_list);
+
 	/* register v4l2_device early so it can be used for printks */
 	if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
 		dev_err(&interface->dev, "v4l2_device_register failed\n");
@@ -325,10 +330,6 @@ static int hdpvr_probe(struct usb_interface *interface,
 	if (!dev->workqueue)
 		goto error;
 
-	/* init video transfer queues */
-	INIT_LIST_HEAD(&dev->free_buff_list);
-	INIT_LIST_HEAD(&dev->rec_buff_list);
-
 	dev->options = hdpvr_default_options;
 
 	if (default_video_input < HDPVR_VIDEO_INPUTS)
@@ -405,7 +406,7 @@ static int hdpvr_probe(struct usb_interface *interface,
 				    video_nr[atomic_inc_return(&dev_nr)]);
 	if (retval < 0) {
 		v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
-		goto error;
+		goto reg_fail;
 	}
 
 	/* let the user know what node this device is now attached to */
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index ab97e7d..6bc9b8e 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -1,7 +1,7 @@
 /*
  *  s2255drv.c - a driver for the Sensoray 2255 USB video capture device
  *
- *   Copyright (C) 2007-2010 by Sensoray Company Inc.
+ *   Copyright (C) 2007-2013 by Sensoray Company Inc.
  *                              Dean Anderson
  *
  * Some video buffer code based on vivi driver:
@@ -52,7 +52,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
 
-#define S2255_VERSION		"1.22.1"
+#define S2255_VERSION		"1.23.1"
 #define FIRMWARE_FILE_NAME "f2255usb.bin"
 
 /* default JPEG quality */
@@ -1303,11 +1303,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i)
 	int ret = 0;
 
 	mutex_lock(&q->vb_lock);
-	if (videobuf_queue_is_busy(q)) {
-		dprintk(1, "queue busy\n");
-		ret = -EBUSY;
-		goto out_s_std;
-	}
 	if (res_locked(fh)) {
 		dprintk(1, "can't change standard after started\n");
 		ret = -EBUSY;
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig
index 1c3a1ec..95584c1 100644
--- a/drivers/media/usb/stk1160/Kconfig
+++ b/drivers/media/usb/stk1160/Kconfig
@@ -1,8 +1,6 @@
-config VIDEO_STK1160
+config VIDEO_STK1160_COMMON
 	tristate "STK1160 USB video capture support"
 	depends on VIDEO_DEV && I2C
-	select VIDEOBUF2_VMALLOC
-	select VIDEO_SAA711X
 
 	---help---
 	  This is a video4linux driver for STK1160 based video capture devices.
@@ -12,9 +10,15 @@ config VIDEO_STK1160
 
 config VIDEO_STK1160_AC97
 	bool "STK1160 AC97 codec support"
-	depends on VIDEO_STK1160 && SND
-	select SND_AC97_CODEC
+	depends on VIDEO_STK1160_COMMON && SND
 
 	---help---
 	  Enables AC97 codec support for stk1160 driver.
-.
+
+config VIDEO_STK1160
+	tristate
+	depends on (!VIDEO_STK1160_AC97 || (SND='n') || SND) && VIDEO_STK1160_COMMON
+	default y
+	select VIDEOBUF2_VMALLOC
+	select VIDEO_SAA711X
+	select SND_AC97_CODEC if SND
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 876fc26..c45c988 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -379,6 +379,9 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
 	struct stk1160 *dev = video_drvdata(file);
 	struct vb2_queue *q = &dev->vb_vidq;
 
+	if (dev->norm == norm)
+		return 0;
+
 	if (vb2_is_busy(q))
 		return -EBUSY;
 
@@ -440,9 +443,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct stk1160 *dev = video_drvdata(file);
 
-	if (vb2_is_busy(&dev->vb_vidq))
-		return -EBUSY;
-
 	if (i > STK1160_MAX_INPUT)
 		return -EINVAL;
 
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
index e07e4c6..95f94e5 100644
--- a/drivers/media/usb/tlg2300/pd-main.c
+++ b/drivers/media/usb/tlg2300/pd-main.c
@@ -375,7 +375,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
 }
 #endif
 
-static int check_firmware(struct usb_device *udev, int *down_firmware)
+static int check_firmware(struct usb_device *udev)
 {
 	void *buf;
 	int ret;
@@ -395,10 +395,8 @@ static int check_firmware(struct usb_device *udev, int *down_firmware)
 			 USB_CTRL_GET_TIMEOUT);
 	kfree(buf);
 
-	if (ret < 0) {
-		*down_firmware = 1;
+	if (ret < 0)
 		return firmware_download(udev);
-	}
 	return 0;
 }
 
@@ -411,9 +409,9 @@ static int poseidon_probe(struct usb_interface *interface,
 	int new_one = 0;
 
 	/* download firmware */
-	check_firmware(udev, &ret);
+	ret = check_firmware(udev);
 	if (ret)
-		return 0;
+		return ret;
 
 	/* Do I recovery from the hibernate ? */
 	pd = find_old_poseidon(udev);
@@ -436,12 +434,22 @@ static int poseidon_probe(struct usb_interface *interface,
 
 		/* register v4l2 device */
 		ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev);
+		if (ret)
+			goto err_v4l2;
 
 		/* register devices in directory /dev */
 		ret = pd_video_init(pd);
-		poseidon_audio_init(pd);
-		poseidon_fm_init(pd);
-		pd_dvb_usb_device_init(pd);
+		if (ret)
+			goto err_video;
+		ret = poseidon_audio_init(pd);
+		if (ret)
+			goto err_audio;
+		ret = poseidon_fm_init(pd);
+		if (ret)
+			goto err_fm;
+		ret = pd_dvb_usb_device_init(pd);
+		if (ret)
+			goto err_dvb;
 
 		INIT_LIST_HEAD(&pd->device_list);
 		list_add_tail(&pd->device_list, &pd_device_list);
@@ -459,6 +467,17 @@ static int poseidon_probe(struct usb_interface *interface,
 	}
 #endif
 	return 0;
+err_dvb:
+	poseidon_fm_exit(pd);
+err_fm:
+	poseidon_audio_free(pd);
+err_audio:
+	pd_video_exit(pd);
+err_video:
+	v4l2_device_unregister(&pd->v4l2_dev);
+err_v4l2:
+	kfree(pd);
+	return ret;
 }
 
 static void poseidon_disconnect(struct usb_interface *interface)
diff --git a/drivers/media/usb/usbtv/Kconfig b/drivers/media/usb/usbtv/Kconfig
index 8864436..7c5b860 100644
--- a/drivers/media/usb/usbtv/Kconfig
+++ b/drivers/media/usb/usbtv/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_USBTV
         tristate "USBTV007 video capture support"
-        depends on VIDEO_DEV
+        depends on VIDEO_V4L2
         select VIDEOBUF2_VMALLOC
 
         ---help---
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c
index bf43f87..8a505a9 100644
--- a/drivers/media/usb/usbtv/usbtv.c
+++ b/drivers/media/usb/usbtv/usbtv.c
@@ -33,7 +33,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 
 #include <media/v4l2-device.h>
@@ -57,7 +56,7 @@
 #define USBTV_CHUNK_SIZE	256
 #define USBTV_CHUNK		240
 #define USBTV_CHUNKS		(USBTV_WIDTH * USBTV_HEIGHT \
-					/ 2 / USBTV_CHUNK)
+					/ 4 / USBTV_CHUNK)
 
 /* Chunk header. */
 #define USBTV_MAGIC_OK(chunk)	((be32_to_cpu(chunk[0]) & 0xff000000) \
@@ -89,18 +88,80 @@ struct usbtv {
 	/* Number of currently processed frame, useful find
 	 * out when a new one begins. */
 	u32 frame_id;
+	int chunks_done;
 
+	enum {
+		USBTV_COMPOSITE_INPUT,
+		USBTV_SVIDEO_INPUT,
+	} input;
 	int iso_size;
 	unsigned int sequence;
 	struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS];
 };
 
-static int usbtv_setup_capture(struct usbtv *usbtv)
+static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
 {
 	int ret;
 	int pipe = usb_rcvctrlpipe(usbtv->udev, 0);
 	int i;
-	static const u16 protoregs[][2] = {
+
+	for (i = 0; i < size; i++) {
+		u16 index = regs[i][0];
+		u16 value = regs[i][1];
+
+		ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value, index, NULL, 0, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int usbtv_select_input(struct usbtv *usbtv, int input)
+{
+	int ret;
+
+	static const u16 composite[][2] = {
+		{ USBTV_BASE + 0x0105, 0x0060 },
+		{ USBTV_BASE + 0x011f, 0x00f2 },
+		{ USBTV_BASE + 0x0127, 0x0060 },
+		{ USBTV_BASE + 0x00ae, 0x0010 },
+		{ USBTV_BASE + 0x0284, 0x00aa },
+		{ USBTV_BASE + 0x0239, 0x0060 },
+	};
+
+	static const u16 svideo[][2] = {
+		{ USBTV_BASE + 0x0105, 0x0010 },
+		{ USBTV_BASE + 0x011f, 0x00ff },
+		{ USBTV_BASE + 0x0127, 0x0060 },
+		{ USBTV_BASE + 0x00ae, 0x0030 },
+		{ USBTV_BASE + 0x0284, 0x0088 },
+		{ USBTV_BASE + 0x0239, 0x0060 },
+	};
+
+	switch (input) {
+	case USBTV_COMPOSITE_INPUT:
+		ret = usbtv_set_regs(usbtv, composite, ARRAY_SIZE(composite));
+		break;
+	case USBTV_SVIDEO_INPUT:
+		ret = usbtv_set_regs(usbtv, svideo, ARRAY_SIZE(svideo));
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	if (!ret)
+		usbtv->input = input;
+
+	return ret;
+}
+
+static int usbtv_setup_capture(struct usbtv *usbtv)
+{
+	int ret;
+	static const u16 setup[][2] = {
 		/* These seem to enable the device. */
 		{ USBTV_BASE + 0x0008, 0x0001 },
 		{ USBTV_BASE + 0x01d0, 0x00ff },
@@ -188,20 +249,37 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
 		{ USBTV_BASE + 0x024f, 0x0002 },
 	};
 
-	for (i = 0; i < ARRAY_SIZE(protoregs); i++) {
-		u16 index = protoregs[i][0];
-		u16 value = protoregs[i][1];
+	ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup));
+	if (ret)
+		return ret;
 
-		ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value, index, NULL, 0, 0);
-		if (ret < 0)
-			return ret;
-	}
+	ret = usbtv_select_input(usbtv, usbtv->input);
+	if (ret)
+		return ret;
 
 	return 0;
 }
 
+/* Copy data from chunk into a frame buffer, deinterlacing the data
+ * into every second line. Unfortunately, they don't align nicely into
+ * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels.
+ * Therefore, we break down the chunk into two halves before copyting,
+ * so that we can interleave a line if needed. */
+static void usbtv_chunk_to_vbuf(u32 *frame, u32 *src, int chunk_no, int odd)
+{
+	int half;
+
+	for (half = 0; half < 2; half++) {
+		int part_no = chunk_no * 2 + half;
+		int line = part_no / 3;
+		int part_index = (line * 2 + !odd) * 3 + (part_no % 3);
+
+		u32 *dst = &frame[part_index * USBTV_CHUNK/2];
+		memcpy(dst, src, USBTV_CHUNK/2 * sizeof(*src));
+		src += USBTV_CHUNK/2;
+	}
+}
+
 /* Called for each 256-byte image chunk.
  * First word identifies the chunk, followed by 240 words of image
  * data and padding. */
@@ -218,17 +296,17 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
 	frame_id = USBTV_FRAME_ID(chunk);
 	odd = USBTV_ODD(chunk);
 	chunk_no = USBTV_CHUNK_NO(chunk);
-
-	/* Deinterlace. TODO: Use interlaced frame format. */
-	chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3;
-	chunk_no += !odd * 3;
-
 	if (chunk_no >= USBTV_CHUNKS)
 		return;
 
 	/* Beginning of a frame. */
-	if (chunk_no == 0)
+	if (chunk_no == 0) {
 		usbtv->frame_id = frame_id;
+		usbtv->chunks_done = 0;
+	}
+
+	if (usbtv->frame_id != frame_id)
+		return;
 
 	spin_lock_irqsave(&usbtv->buflock, flags);
 	if (list_empty(&usbtv->bufs)) {
@@ -241,19 +319,23 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
 	buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
 	frame = vb2_plane_vaddr(&buf->vb, 0);
 
-	/* Copy the chunk. */
-	memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1],
-			USBTV_CHUNK * sizeof(chunk[1]));
+	/* Copy the chunk data. */
+	usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
+	usbtv->chunks_done++;
 
 	/* Last chunk in a frame, signalling an end */
-	if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) {
+	if (odd && chunk_no == USBTV_CHUNKS-1) {
 		int size = vb2_plane_size(&buf->vb, 0);
+		enum vb2_buffer_state state = usbtv->chunks_done ==
+						USBTV_CHUNKS ?
+						VB2_BUF_STATE_DONE :
+						VB2_BUF_STATE_ERROR;
 
 		buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
 		buf->vb.v4l2_buf.sequence = usbtv->sequence++;
 		v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 		vb2_set_plane_payload(&buf->vb, 0, size);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&buf->vb, state);
 		list_del(&buf->list);
 	}
 
@@ -418,10 +500,17 @@ static int usbtv_querycap(struct file *file, void *priv,
 static int usbtv_enum_input(struct file *file, void *priv,
 					struct v4l2_input *i)
 {
-	if (i->index > 0)
+	switch (i->index) {
+	case USBTV_COMPOSITE_INPUT:
+		strlcpy(i->name, "Composite", sizeof(i->name));
+		break;
+	case USBTV_SVIDEO_INPUT:
+		strlcpy(i->name, "S-Video", sizeof(i->name));
+		break;
+	default:
 		return -EINVAL;
+	}
 
-	strlcpy(i->name, "Composite", sizeof(i->name));
 	i->type = V4L2_INPUT_TYPE_CAMERA;
 	i->std = V4L2_STD_525_60;
 	return 0;
@@ -461,15 +550,15 @@ static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 
 static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	*i = 0;
+	struct usbtv *usbtv = video_drvdata(file);
+	*i = usbtv->input;
 	return 0;
 }
 
 static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
 {
-	if (i > 0)
-		return -EINVAL;
-	return 0;
+	struct usbtv *usbtv = video_drvdata(file);
+	return usbtv_select_input(usbtv, i);
 }
 
 static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
@@ -518,7 +607,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
 	if (*nbuffers < 2)
 		*nbuffers = 2;
 	*nplanes = 1;
-	sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32);
+	sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
 
 	return 0;
 }
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index aae2417..b350ab9 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -27,7 +27,6 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd)
 #if IS_ENABLED(CONFIG_I2C)
 	struct i2c_client *client = i2c_verify_client(dev);
 	return client &&
-		asd->bus_type == V4L2_ASYNC_BUS_I2C &&
 		asd->match.i2c.adapter_id == client->adapter->nr &&
 		asd->match.i2c.address == client->addr;
 #else
@@ -35,10 +34,14 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd)
 #endif
 }
 
-static bool match_platform(struct device *dev, struct v4l2_async_subdev *asd)
+static bool match_devname(struct device *dev, struct v4l2_async_subdev *asd)
 {
-	return asd->bus_type == V4L2_ASYNC_BUS_PLATFORM &&
-		!strcmp(asd->match.platform.name, dev_name(dev));
+	return !strcmp(asd->match.device_name.name, dev_name(dev));
+}
+
+static bool match_of(struct device *dev, struct v4l2_async_subdev *asd)
+{
+	return dev->of_node == asd->match.of.node;
 }
 
 static LIST_HEAD(subdev_list);
@@ -46,28 +49,29 @@ static LIST_HEAD(notifier_list);
 static DEFINE_MUTEX(list_lock);
 
 static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier,
-						    struct v4l2_async_subdev_list *asdl)
+						    struct v4l2_subdev *sd)
 {
-	struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl);
 	struct v4l2_async_subdev *asd;
-	bool (*match)(struct device *,
-		      struct v4l2_async_subdev *);
+	bool (*match)(struct device *, struct v4l2_async_subdev *);
 
 	list_for_each_entry(asd, &notifier->waiting, list) {
 		/* bus_type has been verified valid before */
-		switch (asd->bus_type) {
-		case V4L2_ASYNC_BUS_CUSTOM:
+		switch (asd->match_type) {
+		case V4L2_ASYNC_MATCH_CUSTOM:
 			match = asd->match.custom.match;
 			if (!match)
 				/* Match always */
 				return asd;
 			break;
-		case V4L2_ASYNC_BUS_PLATFORM:
-			match = match_platform;
+		case V4L2_ASYNC_MATCH_DEVNAME:
+			match = match_devname;
 			break;
-		case V4L2_ASYNC_BUS_I2C:
+		case V4L2_ASYNC_MATCH_I2C:
 			match = match_i2c;
 			break;
+		case V4L2_ASYNC_MATCH_OF:
+			match = match_of;
+			break;
 		default:
 			/* Cannot happen, unless someone breaks us */
 			WARN_ON(true);
@@ -83,16 +87,15 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *
 }
 
 static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier,
-				  struct v4l2_async_subdev_list *asdl,
+				  struct v4l2_subdev *sd,
 				  struct v4l2_async_subdev *asd)
 {
-	struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl);
 	int ret;
 
 	/* Remove from the waiting list */
 	list_del(&asd->list);
-	asdl->asd = asd;
-	asdl->notifier = notifier;
+	sd->asd = asd;
+	sd->notifier = notifier;
 
 	if (notifier->bound) {
 		ret = notifier->bound(notifier, sd, asd);
@@ -100,7 +103,7 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier,
 			return ret;
 	}
 	/* Move from the global subdevice list to notifier's done */
-	list_move(&asdl->list, &notifier->done);
+	list_move(&sd->async_list, &notifier->done);
 
 	ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd);
 	if (ret < 0) {
@@ -115,21 +118,19 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier,
 	return 0;
 }
 
-static void v4l2_async_cleanup(struct v4l2_async_subdev_list *asdl)
+static void v4l2_async_cleanup(struct v4l2_subdev *sd)
 {
-	struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl);
-
 	v4l2_device_unregister_subdev(sd);
-	/* Subdevice driver will reprobe and put asdl back onto the list */
-	list_del_init(&asdl->list);
-	asdl->asd = NULL;
+	/* Subdevice driver will reprobe and put the subdev back onto the list */
+	list_del_init(&sd->async_list);
+	sd->asd = NULL;
 	sd->dev = NULL;
 }
 
 int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
 				 struct v4l2_async_notifier *notifier)
 {
-	struct v4l2_async_subdev_list *asdl, *tmp;
+	struct v4l2_subdev *sd, *tmp;
 	struct v4l2_async_subdev *asd;
 	int i;
 
@@ -141,17 +142,18 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
 	INIT_LIST_HEAD(&notifier->done);
 
 	for (i = 0; i < notifier->num_subdevs; i++) {
-		asd = notifier->subdev[i];
+		asd = notifier->subdevs[i];
 
-		switch (asd->bus_type) {
-		case V4L2_ASYNC_BUS_CUSTOM:
-		case V4L2_ASYNC_BUS_PLATFORM:
-		case V4L2_ASYNC_BUS_I2C:
+		switch (asd->match_type) {
+		case V4L2_ASYNC_MATCH_CUSTOM:
+		case V4L2_ASYNC_MATCH_DEVNAME:
+		case V4L2_ASYNC_MATCH_I2C:
+		case V4L2_ASYNC_MATCH_OF:
 			break;
 		default:
 			dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL,
-				"Invalid bus-type %u on %p\n",
-				asd->bus_type, asd);
+				"Invalid match type %u on %p\n",
+				asd->match_type, asd);
 			return -EINVAL;
 		}
 		list_add_tail(&asd->list, &notifier->waiting);
@@ -162,14 +164,14 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
 	/* Keep also completed notifiers on the list */
 	list_add(&notifier->list, &notifier_list);
 
-	list_for_each_entry_safe(asdl, tmp, &subdev_list, list) {
+	list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) {
 		int ret;
 
-		asd = v4l2_async_belongs(notifier, asdl);
+		asd = v4l2_async_belongs(notifier, sd);
 		if (!asd)
 			continue;
 
-		ret = v4l2_async_test_notify(notifier, asdl, asd);
+		ret = v4l2_async_test_notify(notifier, sd, asd);
 		if (ret < 0) {
 			mutex_unlock(&list_lock);
 			return ret;
@@ -184,7 +186,7 @@ EXPORT_SYMBOL(v4l2_async_notifier_register);
 
 void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
 {
-	struct v4l2_async_subdev_list *asdl, *tmp;
+	struct v4l2_subdev *sd, *tmp;
 	unsigned int notif_n_subdev = notifier->num_subdevs;
 	unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS);
 	struct device *dev[n_subdev];
@@ -194,18 +196,16 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
 
 	list_del(&notifier->list);
 
-	list_for_each_entry_safe(asdl, tmp, &notifier->done, list) {
-		struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl);
-
+	list_for_each_entry_safe(sd, tmp, &notifier->done, list) {
 		dev[i] = get_device(sd->dev);
 
-		v4l2_async_cleanup(asdl);
+		v4l2_async_cleanup(sd);
 
 		/* If we handled USB devices, we'd have to lock the parent too */
 		device_release_driver(dev[i++]);
 
 		if (notifier->unbind)
-			notifier->unbind(notifier, sd, sd->asdl.asd);
+			notifier->unbind(notifier, sd, sd->asd);
 	}
 
 	mutex_unlock(&list_lock);
@@ -234,24 +234,23 @@ EXPORT_SYMBOL(v4l2_async_notifier_unregister);
 
 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
-	struct v4l2_async_subdev_list *asdl = &sd->asdl;
 	struct v4l2_async_notifier *notifier;
 
 	mutex_lock(&list_lock);
 
-	INIT_LIST_HEAD(&asdl->list);
+	INIT_LIST_HEAD(&sd->async_list);
 
 	list_for_each_entry(notifier, &notifier_list, list) {
-		struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, asdl);
+		struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd);
 		if (asd) {
-			int ret = v4l2_async_test_notify(notifier, asdl, asd);
+			int ret = v4l2_async_test_notify(notifier, sd, asd);
 			mutex_unlock(&list_lock);
 			return ret;
 		}
 	}
 
 	/* None matched, wait for hot-plugging */
-	list_add(&asdl->list, &subdev_list);
+	list_add(&sd->async_list, &subdev_list);
 
 	mutex_unlock(&list_lock);
 
@@ -261,23 +260,22 @@ EXPORT_SYMBOL(v4l2_async_register_subdev);
 
 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 {
-	struct v4l2_async_subdev_list *asdl = &sd->asdl;
-	struct v4l2_async_notifier *notifier = asdl->notifier;
+	struct v4l2_async_notifier *notifier = sd->notifier;
 
-	if (!asdl->asd) {
-		if (!list_empty(&asdl->list))
-			v4l2_async_cleanup(asdl);
+	if (!sd->asd) {
+		if (!list_empty(&sd->async_list))
+			v4l2_async_cleanup(sd);
 		return;
 	}
 
 	mutex_lock(&list_lock);
 
-	list_add(&asdl->asd->list, &notifier->waiting);
+	list_add(&sd->asd->list, &notifier->waiting);
 
-	v4l2_async_cleanup(asdl);
+	v4l2_async_cleanup(sd);
 
 	if (notifier->unbind)
-		notifier->unbind(notifier, sd, sd->asdl.asd);
+		notifier->unbind(notifier, sd, sd->asd);
 
 	mutex_unlock(&list_lock);
 }
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index e96497f..89b9067 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -196,6 +196,10 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
  * 2) at least one destination buffer has to be queued,
  * 3) streaming has to be on.
  *
+ * If a queue is buffered (for example a decoder hardware ringbuffer that has
+ * to be drained before doing streamoff), allow scheduling without v4l2 buffers
+ * on that queue.
+ *
  * There may also be additional, custom requirements. In such case the driver
  * should supply a custom callback (job_ready in v4l2_m2m_ops) that should
  * return 1 if the instance is ready.
@@ -224,7 +228,8 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
 	}
 
 	spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out);
-	if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) {
+	if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)
+	    && !m2m_ctx->out_q_ctx.buffered) {
 		spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock,
 					flags_out);
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
@@ -232,7 +237,8 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
 		return;
 	}
 	spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap);
-	if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) {
+	if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)
+	    && !m2m_ctx->cap_q_ctx.buffered) {
 		spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock,
 					flags_cap);
 		spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock,
diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c
index 978e8e3..94c9248 100644
--- a/drivers/memory/mvebu-devbus.c
+++ b/drivers/memory/mvebu-devbus.c
@@ -208,16 +208,11 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *node = pdev->dev.of_node;
-	struct device_node *parent;
 	struct devbus *devbus;
 	struct resource *res;
 	struct clk *clk;
 	unsigned long rate;
-	const __be32 *ranges;
-	int err, cs;
-	int addr_cells, p_addr_cells, size_cells;
-	int ranges_len, tuple_len;
-	u32 base, size;
+	int err;
 
 	devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
 	if (!devbus)
@@ -248,68 +243,13 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
 		return err;
 
 	/*
-	 * Allocate an address window for this device.
-	 * If the device probing fails, then we won't be able to
-	 * remove the allocated address decoding window.
-	 *
-	 * FIXME: This is only a temporary hack! We need to do this here
-	 * because we still don't have device tree bindings for mbus.
-	 * Once that support is added, we will declare these address windows
-	 * statically in the device tree, and remove the window configuration
-	 * from here.
-	 */
-
-	/*
-	 * Get the CS to choose the window string.
-	 * This is a bit hacky, but it will be removed once the
-	 * address windows are declared in the device tree.
-	 */
-	cs = (((unsigned long)devbus->base) % 0x400) / 8;
-
-	/*
-	 * Parse 'ranges' property to obtain a (base,size) window tuple.
-	 * This will be removed once the address windows
-	 * are declared in the device tree.
-	 */
-	parent = of_get_parent(node);
-	if (!parent)
-		return -EINVAL;
-
-	p_addr_cells = of_n_addr_cells(parent);
-	of_node_put(parent);
-
-	addr_cells = of_n_addr_cells(node);
-	size_cells = of_n_size_cells(node);
-	tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32);
-
-	ranges = of_get_property(node, "ranges", &ranges_len);
-	if (ranges == NULL || ranges_len != tuple_len)
-		return -EINVAL;
-
-	base = of_translate_address(node, ranges + addr_cells);
-	if (base == OF_BAD_ADDR)
-		return -EINVAL;
-	size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells);
-
-	/*
-	 * Create an mbus address windows.
-	 * FIXME: Remove this, together with the above code, once the
-	 * address windows are declared in the device tree.
-	 */
-	err = mvebu_mbus_add_window(devbus_wins[cs], base, size);
-	if (err < 0)
-		return err;
-
-	/*
 	 * We need to create a child device explicitly from here to
 	 * guarantee that the child will be probed after the timing
 	 * parameters for the bus are written.
 	 */
 	err = of_platform_populate(node, NULL, NULL, dev);
-	if (err < 0) {
-		mvebu_mbus_del_window(base, size);
+	if (err < 0)
 		return err;
-	}
 
 	return 0;
 }
diff --git a/drivers/memstick/core/Kconfig b/drivers/memstick/core/Kconfig
index 95f1814..1d38949 100644
--- a/drivers/memstick/core/Kconfig
+++ b/drivers/memstick/core/Kconfig
@@ -24,3 +24,15 @@ config MSPRO_BLOCK
 	  support. This provides a block device driver, which you can use
 	  to mount the filesystem. Almost everyone wishing MemoryStick
 	  support should say Y or M here.
+
+config MS_BLOCK
+	tristate "MemoryStick Standard device driver"
+	depends on BLOCK
+	help
+	  Say Y here to enable the MemoryStick Standard device driver
+	  support. This provides a block device driver, which you can use
+	  to mount the filesystem.
+	  This driver works with old (bulky) MemoryStick and MemoryStick Duo
+	  but not PRO. Say Y if you have such card.
+	  Driver is new and not yet well tested, thus it can damage your card
+	  (even permanently)
diff --git a/drivers/memstick/core/Makefile b/drivers/memstick/core/Makefile
index ecd0299..0d7f90c 100644
--- a/drivers/memstick/core/Makefile
+++ b/drivers/memstick/core/Makefile
@@ -3,5 +3,5 @@
 #
 
 obj-$(CONFIG_MEMSTICK)		+= memstick.o
-
+obj-$(CONFIG_MS_BLOCK)		+= ms_block.o
 obj-$(CONFIG_MSPRO_BLOCK)	+= mspro_block.o
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
new file mode 100644
index 0000000..08e7023
--- /dev/null
+++ b/drivers/memstick/core/ms_block.c
@@ -0,0 +1,2385 @@
+/*
+ *  ms_block.c - Sony MemoryStick (legacy) storage support
+
+ *  Copyright (C) 2013 Maxim Levitsky <maximlevitsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Minor portions of the driver were copied from mspro_block.c which is
+ * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ */
+#define DRIVER_NAME "ms_block"
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/memstick.h>
+#include <linux/idr.h>
+#include <linux/hdreg.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitmap.h>
+#include <linux/scatterlist.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include "ms_block.h"
+
+static int debug;
+static int cache_flush_timeout = 1000;
+static bool verify_writes;
+
+/*
+ * Copies section of 'sg_from' starting from offset 'offset' and with length
+ * 'len' To another scatterlist of to_nents enties
+ */
+static size_t msb_sg_copy(struct scatterlist *sg_from,
+	struct scatterlist *sg_to, int to_nents, size_t offset, size_t len)
+{
+	size_t copied = 0;
+
+	while (offset > 0) {
+		if (offset >= sg_from->length) {
+			if (sg_is_last(sg_from))
+				return 0;
+
+			offset -= sg_from->length;
+			sg_from = sg_next(sg_from);
+			continue;
+		}
+
+		copied = min(len, sg_from->length - offset);
+		sg_set_page(sg_to, sg_page(sg_from),
+			copied, sg_from->offset + offset);
+
+		len -= copied;
+		offset = 0;
+
+		if (sg_is_last(sg_from) || !len)
+			goto out;
+
+		sg_to = sg_next(sg_to);
+		to_nents--;
+		sg_from = sg_next(sg_from);
+	}
+
+	while (len > sg_from->length && to_nents--) {
+		len -= sg_from->length;
+		copied += sg_from->length;
+
+		sg_set_page(sg_to, sg_page(sg_from),
+				sg_from->length, sg_from->offset);
+
+		if (sg_is_last(sg_from) || !len)
+			goto out;
+
+		sg_from = sg_next(sg_from);
+		sg_to = sg_next(sg_to);
+	}
+
+	if (len && to_nents) {
+		sg_set_page(sg_to, sg_page(sg_from), len, sg_from->offset);
+		copied += len;
+	}
+out:
+	sg_mark_end(sg_to);
+	return copied;
+}
+
+/*
+ * Compares section of 'sg' starting from offset 'offset' and with length 'len'
+ * to linear buffer of length 'len' at address 'buffer'
+ * Returns 0 if equal and  -1 otherwice
+ */
+static int msb_sg_compare_to_buffer(struct scatterlist *sg,
+					size_t offset, u8 *buffer, size_t len)
+{
+	int retval = 0, cmplen;
+	struct sg_mapping_iter miter;
+
+	sg_miter_start(&miter, sg, sg_nents(sg),
+					SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+
+	while (sg_miter_next(&miter) && len > 0) {
+		if (offset >= miter.length) {
+			offset -= miter.length;
+			continue;
+		}
+
+		cmplen = min(miter.length - offset, len);
+		retval = memcmp(miter.addr + offset, buffer, cmplen) ? -1 : 0;
+		if (retval)
+			break;
+
+		buffer += cmplen;
+		len -= cmplen;
+		offset = 0;
+	}
+
+	if (!retval && len)
+		retval = -1;
+
+	sg_miter_stop(&miter);
+	return retval;
+}
+
+
+/* Get zone at which block with logical address 'lba' lives
+ * Flash is broken into zones.
+ * Each zone consists of 512 eraseblocks, out of which in first
+ * zone 494 are used and 496 are for all following zones.
+ * Therefore zone #0 hosts blocks 0-493, zone #1 blocks 494-988, etc...
+*/
+static int msb_get_zone_from_lba(int lba)
+{
+	if (lba < 494)
+		return 0;
+	return ((lba - 494) / 496) + 1;
+}
+
+/* Get zone of physical block. Trivial */
+static int msb_get_zone_from_pba(int pba)
+{
+	return pba / MS_BLOCKS_IN_ZONE;
+}
+
+/* Debug test to validate free block counts */
+static int msb_validate_used_block_bitmap(struct msb_data *msb)
+{
+	int total_free_blocks = 0;
+	int i;
+
+	if (!debug)
+		return 0;
+
+	for (i = 0; i < msb->zone_count; i++)
+		total_free_blocks += msb->free_block_count[i];
+
+	if (msb->block_count - bitmap_weight(msb->used_blocks_bitmap,
+					msb->block_count) == total_free_blocks)
+		return 0;
+
+	pr_err("BUG: free block counts don't match the bitmap");
+	msb->read_only = true;
+	return -EINVAL;
+}
+
+/* Mark physical block as used */
+static void msb_mark_block_used(struct msb_data *msb, int pba)
+{
+	int zone = msb_get_zone_from_pba(pba);
+
+	if (test_bit(pba, msb->used_blocks_bitmap)) {
+		pr_err(
+		"BUG: attempt to mark already used pba %d as used", pba);
+		msb->read_only = true;
+		return;
+	}
+
+	if (msb_validate_used_block_bitmap(msb))
+		return;
+
+	/* No races because all IO is single threaded */
+	__set_bit(pba, msb->used_blocks_bitmap);
+	msb->free_block_count[zone]--;
+}
+
+/* Mark physical block as free */
+static void msb_mark_block_unused(struct msb_data *msb, int pba)
+{
+	int zone = msb_get_zone_from_pba(pba);
+
+	if (!test_bit(pba, msb->used_blocks_bitmap)) {
+		pr_err("BUG: attempt to mark already unused pba %d as unused" , pba);
+		msb->read_only = true;
+		return;
+	}
+
+	if (msb_validate_used_block_bitmap(msb))
+		return;
+
+	/* No races because all IO is single threaded */
+	__clear_bit(pba, msb->used_blocks_bitmap);
+	msb->free_block_count[zone]++;
+}
+
+/* Invalidate current register window */
+static void msb_invalidate_reg_window(struct msb_data *msb)
+{
+	msb->reg_addr.w_offset = offsetof(struct ms_register, id);
+	msb->reg_addr.w_length = sizeof(struct ms_id_register);
+	msb->reg_addr.r_offset = offsetof(struct ms_register, id);
+	msb->reg_addr.r_length = sizeof(struct ms_id_register);
+	msb->addr_valid = false;
+}
+
+/* Start a state machine */
+static int msb_run_state_machine(struct msb_data *msb, int   (*state_func)
+		(struct memstick_dev *card, struct memstick_request **req))
+{
+	struct memstick_dev *card = msb->card;
+
+	WARN_ON(msb->state != -1);
+	msb->int_polling = false;
+	msb->state = 0;
+	msb->exit_error = 0;
+
+	memset(&card->current_mrq, 0, sizeof(card->current_mrq));
+
+	card->next_request = state_func;
+	memstick_new_req(card->host);
+	wait_for_completion(&card->mrq_complete);
+
+	WARN_ON(msb->state != -1);
+	return msb->exit_error;
+}
+
+/* State machines call that to exit */
+static int msb_exit_state_machine(struct msb_data *msb, int error)
+{
+	WARN_ON(msb->state == -1);
+
+	msb->state = -1;
+	msb->exit_error = error;
+	msb->card->next_request = h_msb_default_bad;
+
+	/* Invalidate reg window on errors */
+	if (error)
+		msb_invalidate_reg_window(msb);
+
+	complete(&msb->card->mrq_complete);
+	return -ENXIO;
+}
+
+/* read INT register */
+static int msb_read_int_reg(struct msb_data *msb, long timeout)
+{
+	struct memstick_request *mrq = &msb->card->current_mrq;
+
+	WARN_ON(msb->state == -1);
+
+	if (!msb->int_polling) {
+		msb->int_timeout = jiffies +
+			msecs_to_jiffies(timeout == -1 ? 500 : timeout);
+		msb->int_polling = true;
+	} else if (time_after(jiffies, msb->int_timeout)) {
+		mrq->data[0] = MEMSTICK_INT_CMDNAK;
+		return 0;
+	}
+
+	if ((msb->caps & MEMSTICK_CAP_AUTO_GET_INT) &&
+				mrq->need_card_int && !mrq->error) {
+		mrq->data[0] = mrq->int_reg;
+		mrq->need_card_int = false;
+		return 0;
+	} else {
+		memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1);
+		return 1;
+	}
+}
+
+/* Read a register */
+static int msb_read_regs(struct msb_data *msb, int offset, int len)
+{
+	struct memstick_request *req = &msb->card->current_mrq;
+
+	if (msb->reg_addr.r_offset != offset ||
+	    msb->reg_addr.r_length != len || !msb->addr_valid) {
+
+		msb->reg_addr.r_offset = offset;
+		msb->reg_addr.r_length = len;
+		msb->addr_valid = true;
+
+		memstick_init_req(req, MS_TPC_SET_RW_REG_ADRS,
+			&msb->reg_addr, sizeof(msb->reg_addr));
+		return 0;
+	}
+
+	memstick_init_req(req, MS_TPC_READ_REG, NULL, len);
+	return 1;
+}
+
+/* Write a card register */
+static int msb_write_regs(struct msb_data *msb, int offset, int len, void *buf)
+{
+	struct memstick_request *req = &msb->card->current_mrq;
+
+	if (msb->reg_addr.w_offset != offset ||
+		msb->reg_addr.w_length != len  || !msb->addr_valid) {
+
+		msb->reg_addr.w_offset = offset;
+		msb->reg_addr.w_length = len;
+		msb->addr_valid = true;
+
+		memstick_init_req(req, MS_TPC_SET_RW_REG_ADRS,
+			&msb->reg_addr, sizeof(msb->reg_addr));
+		return 0;
+	}
+
+	memstick_init_req(req, MS_TPC_WRITE_REG, buf, len);
+	return 1;
+}
+
+/* Handler for absence of IO */
+static int h_msb_default_bad(struct memstick_dev *card,
+						struct memstick_request **mrq)
+{
+	return -ENXIO;
+}
+
+/*
+ * This function is a handler for reads of one page from device.
+ * Writes output to msb->current_sg, takes sector address from msb->reg.param
+ * Can also be used to read extra data only. Set params accordintly.
+ */
+static int h_msb_read_page(struct memstick_dev *card,
+					struct memstick_request **out_mrq)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+	struct scatterlist sg[2];
+	u8 command, intreg;
+
+	if (mrq->error) {
+		dbg("read_page, unknown error");
+		return msb_exit_state_machine(msb, mrq->error);
+	}
+again:
+	switch (msb->state) {
+	case MSB_RP_SEND_BLOCK_ADDRESS:
+		/* msb_write_regs sometimes "fails" because it needs to update
+			the reg window, and thus it returns request for that.
+			Then we stay in this state and retry */
+		if (!msb_write_regs(msb,
+			offsetof(struct ms_register, param),
+			sizeof(struct ms_param_register),
+			(unsigned char *)&msb->regs.param))
+			return 0;
+
+		msb->state = MSB_RP_SEND_READ_COMMAND;
+		return 0;
+
+	case MSB_RP_SEND_READ_COMMAND:
+		command = MS_CMD_BLOCK_READ;
+		memstick_init_req(mrq, MS_TPC_SET_CMD, &command, 1);
+		msb->state = MSB_RP_SEND_INT_REQ;
+		return 0;
+
+	case MSB_RP_SEND_INT_REQ:
+		msb->state = MSB_RP_RECEIVE_INT_REQ_RESULT;
+		/* If dont actually need to send the int read request (only in
+			serial mode), then just fall through */
+		if (msb_read_int_reg(msb, -1))
+			return 0;
+		/* fallthrough */
+
+	case MSB_RP_RECEIVE_INT_REQ_RESULT:
+		intreg = mrq->data[0];
+		msb->regs.status.interrupt = intreg;
+
+		if (intreg & MEMSTICK_INT_CMDNAK)
+			return msb_exit_state_machine(msb, -EIO);
+
+		if (!(intreg & MEMSTICK_INT_CED)) {
+			msb->state = MSB_RP_SEND_INT_REQ;
+			goto again;
+		}
+
+		msb->int_polling = false;
+		msb->state = (intreg & MEMSTICK_INT_ERR) ?
+			MSB_RP_SEND_READ_STATUS_REG : MSB_RP_SEND_OOB_READ;
+		goto again;
+
+	case MSB_RP_SEND_READ_STATUS_REG:
+		 /* read the status register to understand source of the INT_ERR */
+		if (!msb_read_regs(msb,
+			offsetof(struct ms_register, status),
+			sizeof(struct ms_status_register)))
+			return 0;
+
+		msb->state = MSB_RP_RECEIVE_OOB_READ;
+		return 0;
+
+	case MSB_RP_RECIVE_STATUS_REG:
+		msb->regs.status = *(struct ms_status_register *)mrq->data;
+		msb->state = MSB_RP_SEND_OOB_READ;
+		/* fallthrough */
+
+	case MSB_RP_SEND_OOB_READ:
+		if (!msb_read_regs(msb,
+			offsetof(struct ms_register, extra_data),
+			sizeof(struct ms_extra_data_register)))
+			return 0;
+
+		msb->state = MSB_RP_RECEIVE_OOB_READ;
+		return 0;
+
+	case MSB_RP_RECEIVE_OOB_READ:
+		msb->regs.extra_data =
+			*(struct ms_extra_data_register *) mrq->data;
+		msb->state = MSB_RP_SEND_READ_DATA;
+		/* fallthrough */
+
+	case MSB_RP_SEND_READ_DATA:
+		/* Skip that state if we only read the oob */
+		if (msb->regs.param.cp == MEMSTICK_CP_EXTRA) {
+			msb->state = MSB_RP_RECEIVE_READ_DATA;
+			goto again;
+		}
+
+		sg_init_table(sg, ARRAY_SIZE(sg));
+		msb_sg_copy(msb->current_sg, sg, ARRAY_SIZE(sg),
+			msb->current_sg_offset,
+			msb->page_size);
+
+		memstick_init_req_sg(mrq, MS_TPC_READ_LONG_DATA, sg);
+		msb->state = MSB_RP_RECEIVE_READ_DATA;
+		return 0;
+
+	case MSB_RP_RECEIVE_READ_DATA:
+		if (!(msb->regs.status.interrupt & MEMSTICK_INT_ERR)) {
+			msb->current_sg_offset += msb->page_size;
+			return msb_exit_state_machine(msb, 0);
+		}
+
+		if (msb->regs.status.status1 & MEMSTICK_UNCORR_ERROR) {
+			dbg("read_page: uncorrectable error");
+			return msb_exit_state_machine(msb, -EBADMSG);
+		}
+
+		if (msb->regs.status.status1 & MEMSTICK_CORR_ERROR) {
+			dbg("read_page: correctable error");
+			msb->current_sg_offset += msb->page_size;
+			return msb_exit_state_machine(msb, -EUCLEAN);
+		} else {
+			dbg("read_page: INT error, but no status error bits");
+			return msb_exit_state_machine(msb, -EIO);
+		}
+	}
+
+	BUG();
+}
+
+/*
+ * Handler of writes of exactly one block.
+ * Takes address from msb->regs.param.
+ * Writes same extra data to blocks, also taken
+ * from msb->regs.extra
+ * Returns -EBADMSG if write fails due to uncorrectable error, or -EIO if
+ * device refuses to take the command or something else
+ */
+static int h_msb_write_block(struct memstick_dev *card,
+					struct memstick_request **out_mrq)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+	struct scatterlist sg[2];
+	u8 intreg, command;
+
+	if (mrq->error)
+		return msb_exit_state_machine(msb, mrq->error);
+
+again:
+	switch (msb->state) {
+
+	/* HACK: Jmicon handling of TPCs between 8 and
+	 *	sizeof(memstick_request.data) is broken due to hardware
+	 *	bug in PIO mode that is used for these TPCs
+	 *	Therefore split the write
+	 */
+
+	case MSB_WB_SEND_WRITE_PARAMS:
+		if (!msb_write_regs(msb,
+			offsetof(struct ms_register, param),
+			sizeof(struct ms_param_register),
+			&msb->regs.param))
+			return 0;
+
+		msb->state = MSB_WB_SEND_WRITE_OOB;
+		return 0;
+
+	case MSB_WB_SEND_WRITE_OOB:
+		if (!msb_write_regs(msb,
+			offsetof(struct ms_register, extra_data),
+			sizeof(struct ms_extra_data_register),
+			&msb->regs.extra_data))
+			return 0;
+		msb->state = MSB_WB_SEND_WRITE_COMMAND;
+		return 0;
+
+
+	case MSB_WB_SEND_WRITE_COMMAND:
+		command = MS_CMD_BLOCK_WRITE;
+		memstick_init_req(mrq, MS_TPC_SET_CMD, &command, 1);
+		msb->state = MSB_WB_SEND_INT_REQ;
+		return 0;
+
+	case MSB_WB_SEND_INT_REQ:
+		msb->state = MSB_WB_RECEIVE_INT_REQ;
+		if (msb_read_int_reg(msb, -1))
+			return 0;
+		/* fallthrough */
+
+	case MSB_WB_RECEIVE_INT_REQ:
+		intreg = mrq->data[0];
+		msb->regs.status.interrupt = intreg;
+
+		/* errors mean out of here, and fast... */
+		if (intreg & (MEMSTICK_INT_CMDNAK))
+			return msb_exit_state_machine(msb, -EIO);
+
+		if (intreg & MEMSTICK_INT_ERR)
+			return msb_exit_state_machine(msb, -EBADMSG);
+
+
+		/* for last page we need to poll CED */
+		if (msb->current_page == msb->pages_in_block) {
+			if (intreg & MEMSTICK_INT_CED)
+				return msb_exit_state_machine(msb, 0);
+			msb->state = MSB_WB_SEND_INT_REQ;
+			goto again;
+
+		}
+
+		/* for non-last page we need BREQ before writing next chunk */
+		if (!(intreg & MEMSTICK_INT_BREQ)) {
+			msb->state = MSB_WB_SEND_INT_REQ;
+			goto again;
+		}
+
+		msb->int_polling = false;
+		msb->state = MSB_WB_SEND_WRITE_DATA;
+		/* fallthrough */
+
+	case MSB_WB_SEND_WRITE_DATA:
+		sg_init_table(sg, ARRAY_SIZE(sg));
+
+		if (msb_sg_copy(msb->current_sg, sg, ARRAY_SIZE(sg),
+			msb->current_sg_offset,
+			msb->page_size) < msb->page_size)
+			return msb_exit_state_machine(msb, -EIO);
+
+		memstick_init_req_sg(mrq, MS_TPC_WRITE_LONG_DATA, sg);
+		mrq->need_card_int = 1;
+		msb->state = MSB_WB_RECEIVE_WRITE_CONFIRMATION;
+		return 0;
+
+	case MSB_WB_RECEIVE_WRITE_CONFIRMATION:
+		msb->current_page++;
+		msb->current_sg_offset += msb->page_size;
+		msb->state = MSB_WB_SEND_INT_REQ;
+		goto again;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+/*
+ * This function is used to send simple IO requests to device that consist
+ * of register write + command
+ */
+static int h_msb_send_command(struct memstick_dev *card,
+					struct memstick_request **out_mrq)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+	u8 intreg;
+
+	if (mrq->error) {
+		dbg("send_command: unknown error");
+		return msb_exit_state_machine(msb, mrq->error);
+	}
+again:
+	switch (msb->state) {
+
+	/* HACK: see h_msb_write_block */
+	case MSB_SC_SEND_WRITE_PARAMS: /* write param register*/
+		if (!msb_write_regs(msb,
+			offsetof(struct ms_register, param),
+			sizeof(struct ms_param_register),
+			&msb->regs.param))
+			return 0;
+		msb->state = MSB_SC_SEND_WRITE_OOB;
+		return 0;
+
+	case MSB_SC_SEND_WRITE_OOB:
+		if (!msb->command_need_oob) {
+			msb->state = MSB_SC_SEND_COMMAND;
+			goto again;
+		}
+
+		if (!msb_write_regs(msb,
+			offsetof(struct ms_register, extra_data),
+			sizeof(struct ms_extra_data_register),
+			&msb->regs.extra_data))
+			return 0;
+
+		msb->state = MSB_SC_SEND_COMMAND;
+		return 0;
+
+	case MSB_SC_SEND_COMMAND:
+		memstick_init_req(mrq, MS_TPC_SET_CMD, &msb->command_value, 1);
+		msb->state = MSB_SC_SEND_INT_REQ;
+		return 0;
+
+	case MSB_SC_SEND_INT_REQ:
+		msb->state = MSB_SC_RECEIVE_INT_REQ;
+		if (msb_read_int_reg(msb, -1))
+			return 0;
+		/* fallthrough */
+
+	case MSB_SC_RECEIVE_INT_REQ:
+		intreg = mrq->data[0];
+
+		if (intreg & MEMSTICK_INT_CMDNAK)
+			return msb_exit_state_machine(msb, -EIO);
+		if (intreg & MEMSTICK_INT_ERR)
+			return msb_exit_state_machine(msb, -EBADMSG);
+
+		if (!(intreg & MEMSTICK_INT_CED)) {
+			msb->state = MSB_SC_SEND_INT_REQ;
+			goto again;
+		}
+
+		return msb_exit_state_machine(msb, 0);
+	}
+
+	BUG();
+}
+
+/* Small handler for card reset */
+static int h_msb_reset(struct memstick_dev *card,
+					struct memstick_request **out_mrq)
+{
+	u8 command = MS_CMD_RESET;
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+
+	if (mrq->error)
+		return msb_exit_state_machine(msb, mrq->error);
+
+	switch (msb->state) {
+	case MSB_RS_SEND:
+		memstick_init_req(mrq, MS_TPC_SET_CMD, &command, 1);
+		mrq->need_card_int = 0;
+		msb->state = MSB_RS_CONFIRM;
+		return 0;
+	case MSB_RS_CONFIRM:
+		return msb_exit_state_machine(msb, 0);
+	}
+	BUG();
+}
+
+/* This handler is used to do serial->parallel switch */
+static int h_msb_parallel_switch(struct memstick_dev *card,
+					struct memstick_request **out_mrq)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+	struct memstick_host *host = card->host;
+
+	if (mrq->error) {
+		dbg("parallel_switch: error");
+		msb->regs.param.system &= ~MEMSTICK_SYS_PAM;
+		return msb_exit_state_machine(msb, mrq->error);
+	}
+
+	switch (msb->state) {
+	case MSB_PS_SEND_SWITCH_COMMAND:
+		/* Set the parallel interface on memstick side */
+		msb->regs.param.system |= MEMSTICK_SYS_PAM;
+
+		if (!msb_write_regs(msb,
+			offsetof(struct ms_register, param),
+			1,
+			(unsigned char *)&msb->regs.param))
+			return 0;
+
+		msb->state = MSB_PS_SWICH_HOST;
+		return 0;
+
+	case MSB_PS_SWICH_HOST:
+		 /* Set parallel interface on our side + send a dummy request
+			to see if card responds */
+		host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
+		memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1);
+		msb->state = MSB_PS_CONFIRM;
+		return 0;
+
+	case MSB_PS_CONFIRM:
+		return msb_exit_state_machine(msb, 0);
+	}
+
+	BUG();
+}
+
+static int msb_switch_to_parallel(struct msb_data *msb);
+
+/* Reset the card, to guard against hw errors beeing treated as bad blocks */
+static int msb_reset(struct msb_data *msb, bool full)
+{
+
+	bool was_parallel = msb->regs.param.system & MEMSTICK_SYS_PAM;
+	struct memstick_dev *card = msb->card;
+	struct memstick_host *host = card->host;
+	int error;
+
+	/* Reset the card */
+	msb->regs.param.system = MEMSTICK_SYS_BAMD;
+
+	if (full) {
+		error =  host->set_param(host,
+					MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+		if (error)
+			goto out_error;
+
+		msb_invalidate_reg_window(msb);
+
+		error = host->set_param(host,
+					MEMSTICK_POWER, MEMSTICK_POWER_ON);
+		if (error)
+			goto out_error;
+
+		error = host->set_param(host,
+					MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+		if (error) {
+out_error:
+			dbg("Failed to reset the host controller");
+			msb->read_only = true;
+			return -EFAULT;
+		}
+	}
+
+	error = msb_run_state_machine(msb, h_msb_reset);
+	if (error) {
+		dbg("Failed to reset the card");
+		msb->read_only = true;
+		return -ENODEV;
+	}
+
+	/* Set parallel mode */
+	if (was_parallel)
+		msb_switch_to_parallel(msb);
+	return 0;
+}
+
+/* Attempts to switch interface to parallel mode */
+static int msb_switch_to_parallel(struct msb_data *msb)
+{
+	int error;
+
+	error = msb_run_state_machine(msb, h_msb_parallel_switch);
+	if (error) {
+		pr_err("Switch to parallel failed");
+		msb->regs.param.system &= ~MEMSTICK_SYS_PAM;
+		msb_reset(msb, true);
+		return -EFAULT;
+	}
+
+	msb->caps |= MEMSTICK_CAP_AUTO_GET_INT;
+	return 0;
+}
+
+/* Changes overwrite flag on a page */
+static int msb_set_overwrite_flag(struct msb_data *msb,
+						u16 pba, u8 page, u8 flag)
+{
+	if (msb->read_only)
+		return -EROFS;
+
+	msb->regs.param.block_address = cpu_to_be16(pba);
+	msb->regs.param.page_address = page;
+	msb->regs.param.cp = MEMSTICK_CP_OVERWRITE;
+	msb->regs.extra_data.overwrite_flag = flag;
+	msb->command_value = MS_CMD_BLOCK_WRITE;
+	msb->command_need_oob = true;
+
+	dbg_verbose("changing overwrite flag to %02x for sector %d, page %d",
+							flag, pba, page);
+	return msb_run_state_machine(msb, h_msb_send_command);
+}
+
+static int msb_mark_bad(struct msb_data *msb, int pba)
+{
+	pr_notice("marking pba %d as bad", pba);
+	msb_reset(msb, true);
+	return msb_set_overwrite_flag(
+			msb, pba, 0, 0xFF & ~MEMSTICK_OVERWRITE_BKST);
+}
+
+static int msb_mark_page_bad(struct msb_data *msb, int pba, int page)
+{
+	dbg("marking page %d of pba %d as bad", page, pba);
+	msb_reset(msb, true);
+	return msb_set_overwrite_flag(msb,
+		pba, page, ~MEMSTICK_OVERWRITE_PGST0);
+}
+
+/* Erases one physical block */
+static int msb_erase_block(struct msb_data *msb, u16 pba)
+{
+	int error, try;
+	if (msb->read_only)
+		return -EROFS;
+
+	dbg_verbose("erasing pba %d", pba);
+
+	for (try = 1; try < 3; try++) {
+		msb->regs.param.block_address = cpu_to_be16(pba);
+		msb->regs.param.page_address = 0;
+		msb->regs.param.cp = MEMSTICK_CP_BLOCK;
+		msb->command_value = MS_CMD_BLOCK_ERASE;
+		msb->command_need_oob = false;
+
+
+		error = msb_run_state_machine(msb, h_msb_send_command);
+		if (!error || msb_reset(msb, true))
+			break;
+	}
+
+	if (error) {
+		pr_err("erase failed, marking pba %d as bad", pba);
+		msb_mark_bad(msb, pba);
+	}
+
+	dbg_verbose("erase success, marking pba %d as unused", pba);
+	msb_mark_block_unused(msb, pba);
+	__set_bit(pba, msb->erased_blocks_bitmap);
+	return error;
+}
+
+/* Reads one page from device */
+static int msb_read_page(struct msb_data *msb,
+	u16 pba, u8 page, struct ms_extra_data_register *extra,
+					struct scatterlist *sg,  int offset)
+{
+	int try, error;
+
+	if (pba == MS_BLOCK_INVALID) {
+		unsigned long flags;
+		struct sg_mapping_iter miter;
+		size_t len = msb->page_size;
+
+		dbg_verbose("read unmapped sector. returning 0xFF");
+
+		local_irq_save(flags);
+		sg_miter_start(&miter, sg, sg_nents(sg),
+				SG_MITER_ATOMIC | SG_MITER_TO_SG);
+
+		while (sg_miter_next(&miter) && len > 0) {
+
+			int chunklen;
+
+			if (offset && offset >= miter.length) {
+				offset -= miter.length;
+				continue;
+			}
+
+			chunklen = min(miter.length - offset, len);
+			memset(miter.addr + offset, 0xFF, chunklen);
+			len -= chunklen;
+			offset = 0;
+		}
+
+		sg_miter_stop(&miter);
+		local_irq_restore(flags);
+
+		if (offset)
+			return -EFAULT;
+
+		if (extra)
+			memset(extra, 0xFF, sizeof(*extra));
+		return 0;
+	}
+
+	if (pba >= msb->block_count) {
+		pr_err("BUG: attempt to read beyond the end of the card at pba %d", pba);
+		return -EINVAL;
+	}
+
+	for (try = 1; try < 3; try++) {
+		msb->regs.param.block_address = cpu_to_be16(pba);
+		msb->regs.param.page_address = page;
+		msb->regs.param.cp = MEMSTICK_CP_PAGE;
+
+		msb->current_sg = sg;
+		msb->current_sg_offset = offset;
+		error = msb_run_state_machine(msb, h_msb_read_page);
+
+
+		if (error == -EUCLEAN) {
+			pr_notice("correctable error on pba %d, page %d",
+				pba, page);
+			error = 0;
+		}
+
+		if (!error && extra)
+			*extra = msb->regs.extra_data;
+
+		if (!error || msb_reset(msb, true))
+			break;
+
+	}
+
+	/* Mark bad pages */
+	if (error == -EBADMSG) {
+		pr_err("uncorrectable error on read of pba %d, page %d",
+			pba, page);
+
+		if (msb->regs.extra_data.overwrite_flag &
+					MEMSTICK_OVERWRITE_PGST0)
+			msb_mark_page_bad(msb, pba, page);
+		return -EBADMSG;
+	}
+
+	if (error)
+		pr_err("read of pba %d, page %d failed with error %d",
+			pba, page, error);
+	return error;
+}
+
+/* Reads oob of page only */
+static int msb_read_oob(struct msb_data *msb, u16 pba, u16 page,
+	struct ms_extra_data_register *extra)
+{
+	int error;
+
+	BUG_ON(!extra);
+	msb->regs.param.block_address = cpu_to_be16(pba);
+	msb->regs.param.page_address = page;
+	msb->regs.param.cp = MEMSTICK_CP_EXTRA;
+
+	if (pba > msb->block_count) {
+		pr_err("BUG: attempt to read beyond the end of card at pba %d", pba);
+		return -EINVAL;
+	}
+
+	error = msb_run_state_machine(msb, h_msb_read_page);
+	*extra = msb->regs.extra_data;
+
+	if (error == -EUCLEAN) {
+		pr_notice("correctable error on pba %d, page %d",
+			pba, page);
+		return 0;
+	}
+
+	return error;
+}
+
+/* Reads a block and compares it with data contained in scatterlist orig_sg */
+static int msb_verify_block(struct msb_data *msb, u16 pba,
+				struct scatterlist *orig_sg,  int offset)
+{
+	struct scatterlist sg;
+	int page = 0, error;
+
+	sg_init_one(&sg, msb->block_buffer, msb->block_size);
+
+	while (page < msb->pages_in_block) {
+
+		error = msb_read_page(msb, pba, page,
+				NULL, &sg, page * msb->page_size);
+		if (error)
+			return error;
+		page++;
+	}
+
+	if (msb_sg_compare_to_buffer(orig_sg, offset,
+				msb->block_buffer, msb->block_size))
+		return -EIO;
+	return 0;
+}
+
+/* Writes exectly one block + oob */
+static int msb_write_block(struct msb_data *msb,
+			u16 pba, u32 lba, struct scatterlist *sg, int offset)
+{
+	int error, current_try = 1;
+	BUG_ON(sg->length < msb->page_size);
+
+	if (msb->read_only)
+		return -EROFS;
+
+	if (pba == MS_BLOCK_INVALID) {
+		pr_err(
+			"BUG: write: attempt to write MS_BLOCK_INVALID block");
+		return -EINVAL;
+	}
+
+	if (pba >= msb->block_count || lba >= msb->logical_block_count) {
+		pr_err(
+		"BUG: write: attempt to write beyond the end of device");
+		return -EINVAL;
+	}
+
+	if (msb_get_zone_from_lba(lba) != msb_get_zone_from_pba(pba)) {
+		pr_err("BUG: write: lba zone mismatch");
+		return -EINVAL;
+	}
+
+	if (pba == msb->boot_block_locations[0] ||
+		pba == msb->boot_block_locations[1]) {
+		pr_err("BUG: write: attempt to write to boot blocks!");
+		return -EINVAL;
+	}
+
+	while (1) {
+
+		if (msb->read_only)
+			return -EROFS;
+
+		msb->regs.param.cp = MEMSTICK_CP_BLOCK;
+		msb->regs.param.page_address = 0;
+		msb->regs.param.block_address = cpu_to_be16(pba);
+
+		msb->regs.extra_data.management_flag = 0xFF;
+		msb->regs.extra_data.overwrite_flag = 0xF8;
+		msb->regs.extra_data.logical_address = cpu_to_be16(lba);
+
+		msb->current_sg = sg;
+		msb->current_sg_offset = offset;
+		msb->current_page = 0;
+
+		error = msb_run_state_machine(msb, h_msb_write_block);
+
+		/* Sector we just wrote to is assumed erased since its pba
+			was erased. If it wasn't erased, write will succeed
+			and will just clear the bits that were set in the block
+			thus test that what we have written,
+			matches what we expect.
+			We do trust the blocks that we erased */
+		if (!error && (verify_writes ||
+				!test_bit(pba, msb->erased_blocks_bitmap)))
+			error = msb_verify_block(msb, pba, sg, offset);
+
+		if (!error)
+			break;
+
+		if (current_try > 1 || msb_reset(msb, true))
+			break;
+
+		pr_err("write failed, trying to erase the pba %d", pba);
+		error = msb_erase_block(msb, pba);
+		if (error)
+			break;
+
+		current_try++;
+	}
+	return error;
+}
+
+/* Finds a free block for write replacement */
+static u16 msb_get_free_block(struct msb_data *msb, int zone)
+{
+	u16 pos;
+	int pba = zone * MS_BLOCKS_IN_ZONE;
+	int i;
+
+	get_random_bytes(&pos, sizeof(pos));
+
+	if (!msb->free_block_count[zone]) {
+		pr_err("NO free blocks in the zone %d, to use for a write, (media is WORN out) switching to RO mode", zone);
+		msb->read_only = true;
+		return MS_BLOCK_INVALID;
+	}
+
+	pos %= msb->free_block_count[zone];
+
+	dbg_verbose("have %d choices for a free block, selected randomally: %d",
+		msb->free_block_count[zone], pos);
+
+	pba = find_next_zero_bit(msb->used_blocks_bitmap,
+							msb->block_count, pba);
+	for (i = 0; i < pos; ++i)
+		pba = find_next_zero_bit(msb->used_blocks_bitmap,
+						msb->block_count, pba + 1);
+
+	dbg_verbose("result of the free blocks scan: pba %d", pba);
+
+	if (pba == msb->block_count || (msb_get_zone_from_pba(pba)) != zone) {
+		pr_err("BUG: cant get a free block");
+		msb->read_only = true;
+		return MS_BLOCK_INVALID;
+	}
+
+	msb_mark_block_used(msb, pba);
+	return pba;
+}
+
+static int msb_update_block(struct msb_data *msb, u16 lba,
+	struct scatterlist *sg, int offset)
+{
+	u16 pba, new_pba;
+	int error, try;
+
+	pba = msb->lba_to_pba_table[lba];
+	dbg_verbose("start of a block update at lba  %d, pba %d", lba, pba);
+
+	if (pba != MS_BLOCK_INVALID) {
+		dbg_verbose("setting the update flag on the block");
+		msb_set_overwrite_flag(msb, pba, 0,
+				0xFF & ~MEMSTICK_OVERWRITE_UDST);
+	}
+
+	for (try = 0; try < 3; try++) {
+		new_pba = msb_get_free_block(msb,
+			msb_get_zone_from_lba(lba));
+
+		if (new_pba == MS_BLOCK_INVALID) {
+			error = -EIO;
+			goto out;
+		}
+
+		dbg_verbose("block update: writing updated block to the pba %d",
+								new_pba);
+		error = msb_write_block(msb, new_pba, lba, sg, offset);
+		if (error == -EBADMSG) {
+			msb_mark_bad(msb, new_pba);
+			continue;
+		}
+
+		if (error)
+			goto out;
+
+		dbg_verbose("block update: erasing the old block");
+		msb_erase_block(msb, pba);
+		msb->lba_to_pba_table[lba] = new_pba;
+		return 0;
+	}
+out:
+	if (error) {
+		pr_err("block update error after %d tries,  switching to r/o mode", try);
+		msb->read_only = true;
+	}
+	return error;
+}
+
+/* Converts endiannes in the boot block for easy use */
+static void msb_fix_boot_page_endianness(struct ms_boot_page *p)
+{
+	p->header.block_id = be16_to_cpu(p->header.block_id);
+	p->header.format_reserved = be16_to_cpu(p->header.format_reserved);
+	p->entry.disabled_block.start_addr
+		= be32_to_cpu(p->entry.disabled_block.start_addr);
+	p->entry.disabled_block.data_size
+		= be32_to_cpu(p->entry.disabled_block.data_size);
+	p->entry.cis_idi.start_addr
+		= be32_to_cpu(p->entry.cis_idi.start_addr);
+	p->entry.cis_idi.data_size
+		= be32_to_cpu(p->entry.cis_idi.data_size);
+	p->attr.block_size = be16_to_cpu(p->attr.block_size);
+	p->attr.number_of_blocks = be16_to_cpu(p->attr.number_of_blocks);
+	p->attr.number_of_effective_blocks
+		= be16_to_cpu(p->attr.number_of_effective_blocks);
+	p->attr.page_size = be16_to_cpu(p->attr.page_size);
+	p->attr.memory_manufacturer_code
+		= be16_to_cpu(p->attr.memory_manufacturer_code);
+	p->attr.memory_device_code = be16_to_cpu(p->attr.memory_device_code);
+	p->attr.implemented_capacity
+		= be16_to_cpu(p->attr.implemented_capacity);
+	p->attr.controller_number = be16_to_cpu(p->attr.controller_number);
+	p->attr.controller_function = be16_to_cpu(p->attr.controller_function);
+}
+
+static int msb_read_boot_blocks(struct msb_data *msb)
+{
+	int pba = 0;
+	struct scatterlist sg;
+	struct ms_extra_data_register extra;
+	struct ms_boot_page *page;
+
+	msb->boot_block_locations[0] = MS_BLOCK_INVALID;
+	msb->boot_block_locations[1] = MS_BLOCK_INVALID;
+	msb->boot_block_count = 0;
+
+	dbg_verbose("Start of a scan for the boot blocks");
+
+	if (!msb->boot_page) {
+		page = kmalloc(sizeof(struct ms_boot_page)*2, GFP_KERNEL);
+		if (!page)
+			return -ENOMEM;
+
+		msb->boot_page = page;
+	} else
+		page = msb->boot_page;
+
+	msb->block_count = MS_BLOCK_MAX_BOOT_ADDR;
+
+	for (pba = 0; pba < MS_BLOCK_MAX_BOOT_ADDR; pba++) {
+
+		sg_init_one(&sg, page, sizeof(*page));
+		if (msb_read_page(msb, pba, 0, &extra, &sg, 0)) {
+			dbg("boot scan: can't read pba %d", pba);
+			continue;
+		}
+
+		if (extra.management_flag & MEMSTICK_MANAGEMENT_SYSFLG) {
+			dbg("managment flag doesn't indicate boot block %d",
+									pba);
+			continue;
+		}
+
+		if (be16_to_cpu(page->header.block_id) != MS_BLOCK_BOOT_ID) {
+			dbg("the pba at %d doesn' contain boot block ID", pba);
+			continue;
+		}
+
+		msb_fix_boot_page_endianness(page);
+		msb->boot_block_locations[msb->boot_block_count] = pba;
+
+		page++;
+		msb->boot_block_count++;
+
+		if (msb->boot_block_count == 2)
+			break;
+	}
+
+	if (!msb->boot_block_count) {
+		pr_err("media doesn't contain master page, aborting");
+		return -EIO;
+	}
+
+	dbg_verbose("End of scan for boot blocks");
+	return 0;
+}
+
+static int msb_read_bad_block_table(struct msb_data *msb, int block_nr)
+{
+	struct ms_boot_page *boot_block;
+	struct scatterlist sg;
+	u16 *buffer = NULL;
+	int offset = 0;
+	int i, error = 0;
+	int data_size, data_offset, page, page_offset, size_to_read;
+	u16 pba;
+
+	BUG_ON(block_nr > 1);
+	boot_block = &msb->boot_page[block_nr];
+	pba = msb->boot_block_locations[block_nr];
+
+	if (msb->boot_block_locations[block_nr] == MS_BLOCK_INVALID)
+		return -EINVAL;
+
+	data_size = boot_block->entry.disabled_block.data_size;
+	data_offset = sizeof(struct ms_boot_page) +
+			boot_block->entry.disabled_block.start_addr;
+	if (!data_size)
+		return 0;
+
+	page = data_offset / msb->page_size;
+	page_offset = data_offset % msb->page_size;
+	size_to_read =
+		DIV_ROUND_UP(data_size + page_offset, msb->page_size) *
+			msb->page_size;
+
+	dbg("reading bad block of boot block at pba %d, offset %d len %d",
+		pba, data_offset, data_size);
+
+	buffer = kzalloc(size_to_read, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	/* Read the buffer */
+	sg_init_one(&sg, buffer, size_to_read);
+
+	while (offset < size_to_read) {
+		error = msb_read_page(msb, pba, page, NULL, &sg, offset);
+		if (error)
+			goto out;
+
+		page++;
+		offset += msb->page_size;
+
+		if (page == msb->pages_in_block) {
+			pr_err(
+			"bad block table extends beyond the boot block");
+			break;
+		}
+	}
+
+	/* Process the bad block table */
+	for (i = page_offset; i < data_size / sizeof(u16); i++) {
+
+		u16 bad_block = be16_to_cpu(buffer[i]);
+
+		if (bad_block >= msb->block_count) {
+			dbg("bad block table contains invalid block %d",
+								bad_block);
+			continue;
+		}
+
+		if (test_bit(bad_block, msb->used_blocks_bitmap))  {
+			dbg("duplicate bad block %d in the table",
+				bad_block);
+			continue;
+		}
+
+		dbg("block %d is marked as factory bad", bad_block);
+		msb_mark_block_used(msb, bad_block);
+	}
+out:
+	kfree(buffer);
+	return error;
+}
+
+static int msb_ftl_initialize(struct msb_data *msb)
+{
+	int i;
+
+	if (msb->ftl_initialized)
+		return 0;
+
+	msb->zone_count = msb->block_count / MS_BLOCKS_IN_ZONE;
+	msb->logical_block_count = msb->zone_count * 496 - 2;
+
+	msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
+	msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
+	msb->lba_to_pba_table =
+		kmalloc(msb->logical_block_count * sizeof(u16), GFP_KERNEL);
+
+	if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table ||
+						!msb->erased_blocks_bitmap) {
+		kfree(msb->used_blocks_bitmap);
+		kfree(msb->lba_to_pba_table);
+		kfree(msb->erased_blocks_bitmap);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < msb->zone_count; i++)
+		msb->free_block_count[i] = MS_BLOCKS_IN_ZONE;
+
+	memset(msb->lba_to_pba_table, MS_BLOCK_INVALID,
+			msb->logical_block_count * sizeof(u16));
+
+	dbg("initial FTL tables created. Zone count = %d, Logical block count = %d",
+		msb->zone_count, msb->logical_block_count);
+
+	msb->ftl_initialized = true;
+	return 0;
+}
+
+static int msb_ftl_scan(struct msb_data *msb)
+{
+	u16 pba, lba, other_block;
+	u8 overwrite_flag, managment_flag, other_overwrite_flag;
+	int error;
+	struct ms_extra_data_register extra;
+	u8 *overwrite_flags = kzalloc(msb->block_count, GFP_KERNEL);
+
+	if (!overwrite_flags)
+		return -ENOMEM;
+
+	dbg("Start of media scanning");
+	for (pba = 0; pba < msb->block_count; pba++) {
+
+		if (pba == msb->boot_block_locations[0] ||
+			pba == msb->boot_block_locations[1]) {
+			dbg_verbose("pba %05d -> [boot block]", pba);
+			msb_mark_block_used(msb, pba);
+			continue;
+		}
+
+		if (test_bit(pba, msb->used_blocks_bitmap)) {
+			dbg_verbose("pba %05d -> [factory bad]", pba);
+			continue;
+		}
+
+		memset(&extra, 0, sizeof(extra));
+		error = msb_read_oob(msb, pba, 0, &extra);
+
+		/* can't trust the page if we can't read the oob */
+		if (error == -EBADMSG) {
+			pr_notice(
+			"oob of pba %d damaged, will try to erase it", pba);
+			msb_mark_block_used(msb, pba);
+			msb_erase_block(msb, pba);
+			continue;
+		} else if (error) {
+			pr_err("unknown error %d on read of oob of pba %d - aborting",
+				error, pba);
+
+			kfree(overwrite_flags);
+			return error;
+		}
+
+		lba = be16_to_cpu(extra.logical_address);
+		managment_flag = extra.management_flag;
+		overwrite_flag = extra.overwrite_flag;
+		overwrite_flags[pba] = overwrite_flag;
+
+		/* Skip bad blocks */
+		if (!(overwrite_flag & MEMSTICK_OVERWRITE_BKST)) {
+			dbg("pba %05d -> [BAD]", pba);
+			msb_mark_block_used(msb, pba);
+			continue;
+		}
+
+		/* Skip system/drm blocks */
+		if ((managment_flag & MEMSTICK_MANAGMENT_FLAG_NORMAL) !=
+			MEMSTICK_MANAGMENT_FLAG_NORMAL) {
+			dbg("pba %05d -> [reserved managment flag %02x]",
+							pba, managment_flag);
+			msb_mark_block_used(msb, pba);
+			continue;
+		}
+
+		/* Erase temporary tables */
+		if (!(managment_flag & MEMSTICK_MANAGEMENT_ATFLG)) {
+			dbg("pba %05d -> [temp table] - will erase", pba);
+
+			msb_mark_block_used(msb, pba);
+			msb_erase_block(msb, pba);
+			continue;
+		}
+
+		if (lba == MS_BLOCK_INVALID) {
+			dbg_verbose("pba %05d -> [free]", pba);
+			continue;
+		}
+
+		msb_mark_block_used(msb, pba);
+
+		/* Block has LBA not according to zoning*/
+		if (msb_get_zone_from_lba(lba) != msb_get_zone_from_pba(pba)) {
+			pr_notice("pba %05d -> [bad lba %05d] - will erase",
+								pba, lba);
+			msb_erase_block(msb, pba);
+			continue;
+		}
+
+		/* No collisions - great */
+		if (msb->lba_to_pba_table[lba] == MS_BLOCK_INVALID) {
+			dbg_verbose("pba %05d -> [lba %05d]", pba, lba);
+			msb->lba_to_pba_table[lba] = pba;
+			continue;
+		}
+
+		other_block = msb->lba_to_pba_table[lba];
+		other_overwrite_flag = overwrite_flags[other_block];
+
+		pr_notice("Collision between pba %d and pba %d",
+			pba, other_block);
+
+		if (!(overwrite_flag & MEMSTICK_OVERWRITE_UDST)) {
+			pr_notice("pba %d is marked as stable, use it", pba);
+			msb_erase_block(msb, other_block);
+			msb->lba_to_pba_table[lba] = pba;
+			continue;
+		}
+
+		if (!(other_overwrite_flag & MEMSTICK_OVERWRITE_UDST)) {
+			pr_notice("pba %d is marked as stable, use it",
+								other_block);
+			msb_erase_block(msb, pba);
+			continue;
+		}
+
+		pr_notice("collision between blocks %d and %d, without stable flag set on both, erasing pba %d",
+				pba, other_block, other_block);
+
+		msb_erase_block(msb, other_block);
+		msb->lba_to_pba_table[lba] = pba;
+	}
+
+	dbg("End of media scanning");
+	kfree(overwrite_flags);
+	return 0;
+}
+
+static void msb_cache_flush_timer(unsigned long data)
+{
+	struct msb_data *msb = (struct msb_data *)data;
+	msb->need_flush_cache = true;
+	queue_work(msb->io_queue, &msb->io_work);
+}
+
+
+static void msb_cache_discard(struct msb_data *msb)
+{
+	if (msb->cache_block_lba == MS_BLOCK_INVALID)
+		return;
+
+	del_timer_sync(&msb->cache_flush_timer);
+
+	dbg_verbose("Discarding the write cache");
+	msb->cache_block_lba = MS_BLOCK_INVALID;
+	bitmap_zero(&msb->valid_cache_bitmap, msb->pages_in_block);
+}
+
+static int msb_cache_init(struct msb_data *msb)
+{
+	setup_timer(&msb->cache_flush_timer, msb_cache_flush_timer,
+		(unsigned long)msb);
+
+	if (!msb->cache)
+		msb->cache = kzalloc(msb->block_size, GFP_KERNEL);
+	if (!msb->cache)
+		return -ENOMEM;
+
+	msb_cache_discard(msb);
+	return 0;
+}
+
+static int msb_cache_flush(struct msb_data *msb)
+{
+	struct scatterlist sg;
+	struct ms_extra_data_register extra;
+	int page, offset, error;
+	u16 pba, lba;
+
+	if (msb->read_only)
+		return -EROFS;
+
+	if (msb->cache_block_lba == MS_BLOCK_INVALID)
+		return 0;
+
+	lba = msb->cache_block_lba;
+	pba = msb->lba_to_pba_table[lba];
+
+	dbg_verbose("Flushing the write cache of pba %d (LBA %d)",
+						pba, msb->cache_block_lba);
+
+	sg_init_one(&sg, msb->cache , msb->block_size);
+
+	/* Read all missing pages in cache */
+	for (page = 0; page < msb->pages_in_block; page++) {
+
+		if (test_bit(page, &msb->valid_cache_bitmap))
+			continue;
+
+		offset = page * msb->page_size;
+
+		dbg_verbose("reading non-present sector %d of cache block %d",
+			page, lba);
+		error = msb_read_page(msb, pba, page, &extra, &sg, offset);
+
+		/* Bad pages are copied with 00 page status */
+		if (error == -EBADMSG) {
+			pr_err("read error on sector %d, contents probably damaged", page);
+			continue;
+		}
+
+		if (error)
+			return error;
+
+		if ((extra.overwrite_flag & MEMSTICK_OV_PG_NORMAL) !=
+							MEMSTICK_OV_PG_NORMAL) {
+			dbg("page %d is marked as bad", page);
+			continue;
+		}
+
+		set_bit(page, &msb->valid_cache_bitmap);
+	}
+
+	/* Write the cache now */
+	error = msb_update_block(msb, msb->cache_block_lba, &sg, 0);
+	pba = msb->lba_to_pba_table[msb->cache_block_lba];
+
+	/* Mark invalid pages */
+	if (!error) {
+		for (page = 0; page < msb->pages_in_block; page++) {
+
+			if (test_bit(page, &msb->valid_cache_bitmap))
+				continue;
+
+			dbg("marking page %d as containing damaged data",
+				page);
+			msb_set_overwrite_flag(msb,
+				pba , page, 0xFF & ~MEMSTICK_OV_PG_NORMAL);
+		}
+	}
+
+	msb_cache_discard(msb);
+	return error;
+}
+
+static int msb_cache_write(struct msb_data *msb, int lba,
+	int page, bool add_to_cache_only, struct scatterlist *sg, int offset)
+{
+	int error;
+	struct scatterlist sg_tmp[10];
+
+	if (msb->read_only)
+		return -EROFS;
+
+	if (msb->cache_block_lba == MS_BLOCK_INVALID ||
+						lba != msb->cache_block_lba)
+		if (add_to_cache_only)
+			return 0;
+
+	/* If we need to write different block */
+	if (msb->cache_block_lba != MS_BLOCK_INVALID &&
+						lba != msb->cache_block_lba) {
+		dbg_verbose("first flush the cache");
+		error = msb_cache_flush(msb);
+		if (error)
+			return error;
+	}
+
+	if (msb->cache_block_lba  == MS_BLOCK_INVALID) {
+		msb->cache_block_lba  = lba;
+		mod_timer(&msb->cache_flush_timer,
+			jiffies + msecs_to_jiffies(cache_flush_timeout));
+	}
+
+	dbg_verbose("Write of LBA %d page %d to cache ", lba, page);
+
+	sg_init_table(sg_tmp, ARRAY_SIZE(sg_tmp));
+	msb_sg_copy(sg, sg_tmp, ARRAY_SIZE(sg_tmp), offset, msb->page_size);
+
+	sg_copy_to_buffer(sg_tmp, sg_nents(sg_tmp),
+		msb->cache + page * msb->page_size, msb->page_size);
+
+	set_bit(page, &msb->valid_cache_bitmap);
+	return 0;
+}
+
+static int msb_cache_read(struct msb_data *msb, int lba,
+				int page, struct scatterlist *sg, int offset)
+{
+	int pba = msb->lba_to_pba_table[lba];
+	struct scatterlist sg_tmp[10];
+	int error = 0;
+
+	if (lba == msb->cache_block_lba &&
+			test_bit(page, &msb->valid_cache_bitmap)) {
+
+		dbg_verbose("Read of LBA %d (pba %d) sector %d from cache",
+							lba, pba, page);
+
+		sg_init_table(sg_tmp, ARRAY_SIZE(sg_tmp));
+		msb_sg_copy(sg, sg_tmp, ARRAY_SIZE(sg_tmp),
+			offset, msb->page_size);
+		sg_copy_from_buffer(sg_tmp, sg_nents(sg_tmp),
+			msb->cache + msb->page_size * page,
+							msb->page_size);
+	} else {
+		dbg_verbose("Read of LBA %d (pba %d) sector %d from device",
+							lba, pba, page);
+
+		error = msb_read_page(msb, pba, page, NULL, sg, offset);
+		if (error)
+			return error;
+
+		msb_cache_write(msb, lba, page, true, sg, offset);
+	}
+	return error;
+}
+
+/* Emulated geometry table
+ * This table content isn't that importaint,
+ * One could put here different values, providing that they still
+ * cover whole disk.
+ * 64 MB entry is what windows reports for my 64M memstick */
+
+static const struct chs_entry chs_table[] = {
+/*        size sectors cylynders  heads */
+	{ 4,    16,    247,       2  },
+	{ 8,    16,    495,       2  },
+	{ 16,   16,    495,       4  },
+	{ 32,   16,    991,       4  },
+	{ 64,   16,    991,       8  },
+	{128,   16,    991,       16 },
+	{ 0 }
+};
+
+/* Load information about the card */
+static int msb_init_card(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_host *host = card->host;
+	struct ms_boot_page *boot_block;
+	int error = 0, i, raw_size_in_megs;
+
+	msb->caps = 0;
+
+	if (card->id.class >= MEMSTICK_CLASS_ROM &&
+				card->id.class <= MEMSTICK_CLASS_ROM)
+		msb->read_only = true;
+
+	msb->state = -1;
+	error = msb_reset(msb, false);
+	if (error)
+		return error;
+
+	/* Due to a bug in Jmicron driver written by Alex Dubov,
+	 its serial mode barely works,
+	 so we switch to parallel mode right away */
+	if (host->caps & MEMSTICK_CAP_PAR4)
+		msb_switch_to_parallel(msb);
+
+	msb->page_size = sizeof(struct ms_boot_page);
+
+	/* Read the boot page */
+	error = msb_read_boot_blocks(msb);
+	if (error)
+		return -EIO;
+
+	boot_block = &msb->boot_page[0];
+
+	/* Save intersting attributes from boot page */
+	msb->block_count = boot_block->attr.number_of_blocks;
+	msb->page_size = boot_block->attr.page_size;
+
+	msb->pages_in_block = boot_block->attr.block_size * 2;
+	msb->block_size = msb->page_size * msb->pages_in_block;
+
+	if (msb->page_size > PAGE_SIZE) {
+		/* this isn't supported by linux at all, anyway*/
+		dbg("device page %d size isn't supported", msb->page_size);
+		return -EINVAL;
+	}
+
+	msb->block_buffer = kzalloc(msb->block_size, GFP_KERNEL);
+	if (!msb->block_buffer)
+		return -ENOMEM;
+
+	raw_size_in_megs = (msb->block_size * msb->block_count) >> 20;
+
+	for (i = 0; chs_table[i].size; i++) {
+
+		if (chs_table[i].size != raw_size_in_megs)
+			continue;
+
+		msb->geometry.cylinders = chs_table[i].cyl;
+		msb->geometry.heads = chs_table[i].head;
+		msb->geometry.sectors = chs_table[i].sec;
+		break;
+	}
+
+	if (boot_block->attr.transfer_supporting == 1)
+		msb->caps |= MEMSTICK_CAP_PAR4;
+
+	if (boot_block->attr.device_type & 0x03)
+		msb->read_only = true;
+
+	dbg("Total block count = %d", msb->block_count);
+	dbg("Each block consists of %d pages", msb->pages_in_block);
+	dbg("Page size = %d bytes", msb->page_size);
+	dbg("Parallel mode supported: %d", !!(msb->caps & MEMSTICK_CAP_PAR4));
+	dbg("Read only: %d", msb->read_only);
+
+#if 0
+	/* Now we can switch the interface */
+	if (host->caps & msb->caps & MEMSTICK_CAP_PAR4)
+		msb_switch_to_parallel(msb);
+#endif
+
+	error = msb_cache_init(msb);
+	if (error)
+		return error;
+
+	error = msb_ftl_initialize(msb);
+	if (error)
+		return error;
+
+
+	/* Read the bad block table */
+	error = msb_read_bad_block_table(msb, 0);
+
+	if (error && error != -ENOMEM) {
+		dbg("failed to read bad block table from primary boot block, trying from backup");
+		error = msb_read_bad_block_table(msb, 1);
+	}
+
+	if (error)
+		return error;
+
+	/* *drum roll* Scan the media */
+	error = msb_ftl_scan(msb);
+	if (error) {
+		pr_err("Scan of media failed");
+		return error;
+	}
+
+	return 0;
+
+}
+
+static int msb_do_write_request(struct msb_data *msb, int lba,
+	int page, struct scatterlist *sg, size_t len, int *sucessfuly_written)
+{
+	int error = 0;
+	off_t offset = 0;
+	*sucessfuly_written = 0;
+
+	while (offset < len) {
+		if (page == 0 && len - offset >= msb->block_size) {
+
+			if (msb->cache_block_lba == lba)
+				msb_cache_discard(msb);
+
+			dbg_verbose("Writing whole lba %d", lba);
+			error = msb_update_block(msb, lba, sg, offset);
+			if (error)
+				return error;
+
+			offset += msb->block_size;
+			*sucessfuly_written += msb->block_size;
+			lba++;
+			continue;
+		}
+
+		error = msb_cache_write(msb, lba, page, false, sg, offset);
+		if (error)
+			return error;
+
+		offset += msb->page_size;
+		*sucessfuly_written += msb->page_size;
+
+		page++;
+		if (page == msb->pages_in_block) {
+			page = 0;
+			lba++;
+		}
+	}
+	return 0;
+}
+
+static int msb_do_read_request(struct msb_data *msb, int lba,
+		int page, struct scatterlist *sg, int len, int *sucessfuly_read)
+{
+	int error = 0;
+	int offset = 0;
+	*sucessfuly_read = 0;
+
+	while (offset < len) {
+
+		error = msb_cache_read(msb, lba, page, sg, offset);
+		if (error)
+			return error;
+
+		offset += msb->page_size;
+		*sucessfuly_read += msb->page_size;
+
+		page++;
+		if (page == msb->pages_in_block) {
+			page = 0;
+			lba++;
+		}
+	}
+	return 0;
+}
+
+static void msb_io_work(struct work_struct *work)
+{
+	struct msb_data *msb = container_of(work, struct msb_data, io_work);
+	int page, error, len;
+	sector_t lba;
+	unsigned long flags;
+	struct scatterlist *sg = msb->prealloc_sg;
+
+	dbg_verbose("IO: work started");
+
+	while (1) {
+		spin_lock_irqsave(&msb->q_lock, flags);
+
+		if (msb->need_flush_cache) {
+			msb->need_flush_cache = false;
+			spin_unlock_irqrestore(&msb->q_lock, flags);
+			msb_cache_flush(msb);
+			continue;
+		}
+
+		if (!msb->req) {
+			msb->req = blk_fetch_request(msb->queue);
+			if (!msb->req) {
+				dbg_verbose("IO: no more requests exiting");
+				spin_unlock_irqrestore(&msb->q_lock, flags);
+				return;
+			}
+		}
+
+		spin_unlock_irqrestore(&msb->q_lock, flags);
+
+		/* If card was removed meanwhile */
+		if (!msb->req)
+			return;
+
+		/* process the request */
+		dbg_verbose("IO: processing new request");
+		blk_rq_map_sg(msb->queue, msb->req, sg);
+
+		lba = blk_rq_pos(msb->req);
+
+		sector_div(lba, msb->page_size / 512);
+		page = do_div(lba, msb->pages_in_block);
+
+		if (rq_data_dir(msb->req) == READ)
+			error = msb_do_read_request(msb, lba, page, sg,
+				blk_rq_bytes(msb->req), &len);
+		else
+			error = msb_do_write_request(msb, lba, page, sg,
+				blk_rq_bytes(msb->req), &len);
+
+		spin_lock_irqsave(&msb->q_lock, flags);
+
+		if (len)
+			if (!__blk_end_request(msb->req, 0, len))
+				msb->req = NULL;
+
+		if (error && msb->req) {
+			dbg_verbose("IO: ending one sector of the request with error");
+			if (!__blk_end_request(msb->req, error, msb->page_size))
+				msb->req = NULL;
+		}
+
+		if (msb->req)
+			dbg_verbose("IO: request still pending");
+
+		spin_unlock_irqrestore(&msb->q_lock, flags);
+	}
+}
+
+static DEFINE_IDR(msb_disk_idr); /*set of used disk numbers */
+static DEFINE_MUTEX(msb_disk_lock); /* protects against races in open/release */
+
+static int msb_bd_open(struct block_device *bdev, fmode_t mode)
+{
+	struct gendisk *disk = bdev->bd_disk;
+	struct msb_data *msb = disk->private_data;
+
+	dbg_verbose("block device open");
+
+	mutex_lock(&msb_disk_lock);
+
+	if (msb && msb->card)
+		msb->usage_count++;
+
+	mutex_unlock(&msb_disk_lock);
+	return 0;
+}
+
+static void msb_data_clear(struct msb_data *msb)
+{
+	kfree(msb->boot_page);
+	kfree(msb->used_blocks_bitmap);
+	kfree(msb->lba_to_pba_table);
+	kfree(msb->cache);
+	msb->card = NULL;
+}
+
+static int msb_disk_release(struct gendisk *disk)
+{
+	struct msb_data *msb = disk->private_data;
+
+	dbg_verbose("block device release");
+	mutex_lock(&msb_disk_lock);
+
+	if (msb) {
+		if (msb->usage_count)
+			msb->usage_count--;
+
+		if (!msb->usage_count) {
+			disk->private_data = NULL;
+			idr_remove(&msb_disk_idr, msb->disk_id);
+			put_disk(disk);
+			kfree(msb);
+		}
+	}
+	mutex_unlock(&msb_disk_lock);
+	return 0;
+}
+
+static void msb_bd_release(struct gendisk *disk, fmode_t mode)
+{
+	msb_disk_release(disk);
+}
+
+static int msb_bd_getgeo(struct block_device *bdev,
+				 struct hd_geometry *geo)
+{
+	struct msb_data *msb = bdev->bd_disk->private_data;
+	*geo = msb->geometry;
+	return 0;
+}
+
+static int msb_prepare_req(struct request_queue *q, struct request *req)
+{
+	if (req->cmd_type != REQ_TYPE_FS &&
+				req->cmd_type != REQ_TYPE_BLOCK_PC) {
+		blk_dump_rq_flags(req, "MS unsupported request");
+		return BLKPREP_KILL;
+	}
+	req->cmd_flags |= REQ_DONTPREP;
+	return BLKPREP_OK;
+}
+
+static void msb_submit_req(struct request_queue *q)
+{
+	struct memstick_dev *card = q->queuedata;
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct request *req = NULL;
+
+	dbg_verbose("Submit request");
+
+	if (msb->card_dead) {
+		dbg("Refusing requests on removed card");
+
+		WARN_ON(!msb->io_queue_stopped);
+
+		while ((req = blk_fetch_request(q)) != NULL)
+			__blk_end_request_all(req, -ENODEV);
+		return;
+	}
+
+	if (msb->req)
+		return;
+
+	if (!msb->io_queue_stopped)
+		queue_work(msb->io_queue, &msb->io_work);
+}
+
+static int msb_check_card(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	return (msb->card_dead == 0);
+}
+
+static void msb_stop(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	unsigned long flags;
+
+	dbg("Stopping all msblock IO");
+
+	spin_lock_irqsave(&msb->q_lock, flags);
+	blk_stop_queue(msb->queue);
+	msb->io_queue_stopped = true;
+	spin_unlock_irqrestore(&msb->q_lock, flags);
+
+	del_timer_sync(&msb->cache_flush_timer);
+	flush_workqueue(msb->io_queue);
+
+	if (msb->req) {
+		spin_lock_irqsave(&msb->q_lock, flags);
+		blk_requeue_request(msb->queue, msb->req);
+		msb->req = NULL;
+		spin_unlock_irqrestore(&msb->q_lock, flags);
+	}
+
+}
+
+static void msb_start(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	unsigned long flags;
+
+	dbg("Resuming IO from msblock");
+
+	msb_invalidate_reg_window(msb);
+
+	spin_lock_irqsave(&msb->q_lock, flags);
+	if (!msb->io_queue_stopped || msb->card_dead) {
+		spin_unlock_irqrestore(&msb->q_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&msb->q_lock, flags);
+
+	/* Kick cache flush anyway, its harmless */
+	msb->need_flush_cache = true;
+	msb->io_queue_stopped = false;
+
+	spin_lock_irqsave(&msb->q_lock, flags);
+	blk_start_queue(msb->queue);
+	spin_unlock_irqrestore(&msb->q_lock, flags);
+
+	queue_work(msb->io_queue, &msb->io_work);
+
+}
+
+static const struct block_device_operations msb_bdops = {
+	.open    = msb_bd_open,
+	.release = msb_bd_release,
+	.getgeo  = msb_bd_getgeo,
+	.owner   = THIS_MODULE
+};
+
+/* Registers the block device */
+static int msb_init_disk(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct memstick_host *host = card->host;
+	int rc;
+	u64 limit = BLK_BOUNCE_HIGH;
+	unsigned long capacity;
+
+	if (host->dev.dma_mask && *(host->dev.dma_mask))
+		limit = *(host->dev.dma_mask);
+
+	mutex_lock(&msb_disk_lock);
+	msb->disk_id = idr_alloc(&msb_disk_idr, card, 0, 256, GFP_KERNEL);
+	mutex_unlock(&msb_disk_lock);
+
+	if (msb->disk_id  < 0)
+		return msb->disk_id;
+
+	msb->disk = alloc_disk(0);
+	if (!msb->disk) {
+		rc = -ENOMEM;
+		goto out_release_id;
+	}
+
+	msb->queue = blk_init_queue(msb_submit_req, &msb->q_lock);
+	if (!msb->queue) {
+		rc = -ENOMEM;
+		goto out_put_disk;
+	}
+
+	msb->queue->queuedata = card;
+	blk_queue_prep_rq(msb->queue, msb_prepare_req);
+
+	blk_queue_bounce_limit(msb->queue, limit);
+	blk_queue_max_hw_sectors(msb->queue, MS_BLOCK_MAX_PAGES);
+	blk_queue_max_segments(msb->queue, MS_BLOCK_MAX_SEGS);
+	blk_queue_max_segment_size(msb->queue,
+				   MS_BLOCK_MAX_PAGES * msb->page_size);
+	blk_queue_logical_block_size(msb->queue, msb->page_size);
+
+	sprintf(msb->disk->disk_name, "msblk%d", msb->disk_id);
+	msb->disk->fops = &msb_bdops;
+	msb->disk->private_data = msb;
+	msb->disk->queue = msb->queue;
+	msb->disk->driverfs_dev = &card->dev;
+	msb->disk->flags |= GENHD_FL_EXT_DEVT;
+
+	capacity = msb->pages_in_block * msb->logical_block_count;
+	capacity *= (msb->page_size / 512);
+	set_capacity(msb->disk, capacity);
+	dbg("Set total disk size to %lu sectors", capacity);
+
+	msb->usage_count = 1;
+	msb->io_queue = alloc_ordered_workqueue("ms_block", WQ_MEM_RECLAIM);
+	INIT_WORK(&msb->io_work, msb_io_work);
+	sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1);
+
+	if (msb->read_only)
+		set_disk_ro(msb->disk, 1);
+
+	msb_start(card);
+	add_disk(msb->disk);
+	dbg("Disk added");
+	return 0;
+
+out_put_disk:
+	put_disk(msb->disk);
+out_release_id:
+	mutex_lock(&msb_disk_lock);
+	idr_remove(&msb_disk_idr, msb->disk_id);
+	mutex_unlock(&msb_disk_lock);
+	return rc;
+}
+
+static int msb_probe(struct memstick_dev *card)
+{
+	struct msb_data *msb;
+	int rc = 0;
+
+	msb = kzalloc(sizeof(struct msb_data), GFP_KERNEL);
+	if (!msb)
+		return -ENOMEM;
+	memstick_set_drvdata(card, msb);
+	msb->card = card;
+	spin_lock_init(&msb->q_lock);
+
+	rc = msb_init_card(card);
+	if (rc)
+		goto out_free;
+
+	rc = msb_init_disk(card);
+	if (!rc) {
+		card->check = msb_check_card;
+		card->stop = msb_stop;
+		card->start = msb_start;
+		return 0;
+	}
+out_free:
+	memstick_set_drvdata(card, NULL);
+	msb_data_clear(msb);
+	kfree(msb);
+	return rc;
+}
+
+static void msb_remove(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	unsigned long flags;
+
+	if (!msb->io_queue_stopped)
+		msb_stop(card);
+
+	dbg("Removing the disk device");
+
+	/* Take care of unhandled + new requests from now on */
+	spin_lock_irqsave(&msb->q_lock, flags);
+	msb->card_dead = true;
+	blk_start_queue(msb->queue);
+	spin_unlock_irqrestore(&msb->q_lock, flags);
+
+	/* Remove the disk */
+	del_gendisk(msb->disk);
+	blk_cleanup_queue(msb->queue);
+	msb->queue = NULL;
+
+	mutex_lock(&msb_disk_lock);
+	msb_data_clear(msb);
+	mutex_unlock(&msb_disk_lock);
+
+	msb_disk_release(msb->disk);
+	memstick_set_drvdata(card, NULL);
+}
+
+#ifdef CONFIG_PM
+
+static int msb_suspend(struct memstick_dev *card, pm_message_t state)
+{
+	msb_stop(card);
+	return 0;
+}
+
+static int msb_resume(struct memstick_dev *card)
+{
+	struct msb_data *msb = memstick_get_drvdata(card);
+	struct msb_data *new_msb = NULL;
+	bool card_dead = true;
+
+#ifndef CONFIG_MEMSTICK_UNSAFE_RESUME
+	msb->card_dead = true;
+	return 0;
+#endif
+	mutex_lock(&card->host->lock);
+
+	new_msb = kzalloc(sizeof(struct msb_data), GFP_KERNEL);
+	if (!new_msb)
+		goto out;
+
+	new_msb->card = card;
+	memstick_set_drvdata(card, new_msb);
+	spin_lock_init(&new_msb->q_lock);
+	sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1);
+
+	if (msb_init_card(card))
+		goto out;
+
+	if (msb->block_size != new_msb->block_size)
+		goto out;
+
+	if (memcmp(msb->boot_page, new_msb->boot_page,
+					sizeof(struct ms_boot_page)))
+		goto out;
+
+	if (msb->logical_block_count != new_msb->logical_block_count ||
+		memcmp(msb->lba_to_pba_table, new_msb->lba_to_pba_table,
+						msb->logical_block_count))
+		goto out;
+
+	if (msb->block_count != new_msb->block_count ||
+		memcmp(msb->used_blocks_bitmap, new_msb->used_blocks_bitmap,
+							msb->block_count / 8))
+		goto out;
+
+	card_dead = false;
+out:
+	if (card_dead)
+		dbg("Card was removed/replaced during suspend");
+
+	msb->card_dead = card_dead;
+	memstick_set_drvdata(card, msb);
+
+	if (new_msb) {
+		msb_data_clear(new_msb);
+		kfree(new_msb);
+	}
+
+	msb_start(card);
+	mutex_unlock(&card->host->lock);
+	return 0;
+}
+#else
+
+#define msb_suspend NULL
+#define msb_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct memstick_device_id msb_id_tbl[] = {
+	{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+	 MEMSTICK_CLASS_FLASH},
+
+	{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+	 MEMSTICK_CLASS_ROM},
+
+	{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+	 MEMSTICK_CLASS_RO},
+
+	{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+	 MEMSTICK_CLASS_WP},
+
+	{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_DUO, MEMSTICK_CATEGORY_STORAGE_DUO,
+	 MEMSTICK_CLASS_DUO},
+	{}
+};
+MODULE_DEVICE_TABLE(memstick, msb_id_tbl);
+
+
+static struct memstick_driver msb_driver = {
+	.driver = {
+		.name  = DRIVER_NAME,
+		.owner = THIS_MODULE
+	},
+	.id_table = msb_id_tbl,
+	.probe    = msb_probe,
+	.remove   = msb_remove,
+	.suspend  = msb_suspend,
+	.resume   = msb_resume
+};
+
+static int major;
+
+static int __init msb_init(void)
+{
+	int rc = register_blkdev(0, DRIVER_NAME);
+
+	if (rc < 0) {
+		pr_err("failed to register major (error %d)\n", rc);
+		return rc;
+	}
+
+	major = rc;
+	rc = memstick_register_driver(&msb_driver);
+	if (rc) {
+		unregister_blkdev(major, DRIVER_NAME);
+		pr_err("failed to register memstick driver (error %d)\n", rc);
+	}
+
+	return rc;
+}
+
+static void __exit msb_exit(void)
+{
+	memstick_unregister_driver(&msb_driver);
+	unregister_blkdev(major, DRIVER_NAME);
+	idr_destroy(&msb_disk_idr);
+}
+
+module_init(msb_init);
+module_exit(msb_exit);
+
+module_param(cache_flush_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(cache_flush_timeout,
+				"Cache flush timeout in msec (1000 default)");
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+module_param(verify_writes, bool, S_IRUGO);
+MODULE_PARM_DESC(verify_writes, "Read back and check all data that is written");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxim Levitsky");
+MODULE_DESCRIPTION("Sony MemoryStick block device driver");
diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h
new file mode 100644
index 0000000..96e6375
--- /dev/null
+++ b/drivers/memstick/core/ms_block.h
@@ -0,0 +1,290 @@
+/*
+ *  ms_block.h - Sony MemoryStick (legacy) storage support
+
+ *  Copyright (C) 2013 Maxim Levitsky <maximlevitsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Minor portions of the driver are copied from mspro_block.c which is
+ * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ * Also ms structures were copied from old broken driver by same author
+ * These probably come from MS spec
+ *
+ */
+
+#ifndef MS_BLOCK_NEW_H
+#define MS_BLOCK_NEW_H
+
+#define MS_BLOCK_MAX_SEGS      32
+#define MS_BLOCK_MAX_PAGES     ((2 << 16) - 1)
+
+#define MS_BLOCK_MAX_BOOT_ADDR 0x000c
+#define MS_BLOCK_BOOT_ID       0x0001
+#define MS_BLOCK_INVALID       0xffff
+#define MS_MAX_ZONES           16
+#define MS_BLOCKS_IN_ZONE      512
+
+#define MS_BLOCK_MAP_LINE_SZ   16
+#define MS_BLOCK_PART_SHIFT    3
+
+
+#define MEMSTICK_UNCORR_ERROR (MEMSTICK_STATUS1_UCFG | \
+		MEMSTICK_STATUS1_UCEX | MEMSTICK_STATUS1_UCDT)
+
+#define MEMSTICK_CORR_ERROR (MEMSTICK_STATUS1_FGER | MEMSTICK_STATUS1_EXER | \
+	MEMSTICK_STATUS1_DTER)
+
+#define MEMSTICK_INT_ERROR (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)
+
+#define MEMSTICK_OVERWRITE_FLAG_NORMAL \
+	(MEMSTICK_OVERWRITE_PGST1 | \
+	MEMSTICK_OVERWRITE_PGST0  | \
+	MEMSTICK_OVERWRITE_BKST)
+
+#define MEMSTICK_OV_PG_NORMAL \
+	(MEMSTICK_OVERWRITE_PGST1 | MEMSTICK_OVERWRITE_PGST0)
+
+#define MEMSTICK_MANAGMENT_FLAG_NORMAL \
+	(MEMSTICK_MANAGEMENT_SYSFLG |  \
+	MEMSTICK_MANAGEMENT_SCMS1   |  \
+	MEMSTICK_MANAGEMENT_SCMS0)     \
+
+struct ms_boot_header {
+	unsigned short block_id;
+	unsigned short format_reserved;
+	unsigned char  reserved0[184];
+	unsigned char  data_entry;
+	unsigned char  reserved1[179];
+} __packed;
+
+
+struct ms_system_item {
+	unsigned int  start_addr;
+	unsigned int  data_size;
+	unsigned char data_type_id;
+	unsigned char reserved[3];
+} __packed;
+
+struct ms_system_entry {
+	struct ms_system_item disabled_block;
+	struct ms_system_item cis_idi;
+	unsigned char         reserved[24];
+} __packed;
+
+struct ms_boot_attr_info {
+	unsigned char      memorystick_class;
+	unsigned char      format_unique_value1;
+	unsigned short     block_size;
+	unsigned short     number_of_blocks;
+	unsigned short     number_of_effective_blocks;
+	unsigned short     page_size;
+	unsigned char      extra_data_size;
+	unsigned char      format_unique_value2;
+	unsigned char      assembly_time[8];
+	unsigned char      format_unique_value3;
+	unsigned char      serial_number[3];
+	unsigned char      assembly_manufacturer_code;
+	unsigned char      assembly_model_code[3];
+	unsigned short     memory_manufacturer_code;
+	unsigned short     memory_device_code;
+	unsigned short     implemented_capacity;
+	unsigned char      format_unique_value4[2];
+	unsigned char      vcc;
+	unsigned char      vpp;
+	unsigned short     controller_number;
+	unsigned short     controller_function;
+	unsigned char      reserved0[9];
+	unsigned char      transfer_supporting;
+	unsigned short     format_unique_value5;
+	unsigned char      format_type;
+	unsigned char      memorystick_application;
+	unsigned char      device_type;
+	unsigned char      reserved1[22];
+	unsigned char      format_uniqure_value6[2];
+	unsigned char      reserved2[15];
+} __packed;
+
+struct ms_cis_idi {
+	unsigned short general_config;
+	unsigned short logical_cylinders;
+	unsigned short reserved0;
+	unsigned short logical_heads;
+	unsigned short track_size;
+	unsigned short page_size;
+	unsigned short pages_per_track;
+	unsigned short msw;
+	unsigned short lsw;
+	unsigned short reserved1;
+	unsigned char  serial_number[20];
+	unsigned short buffer_type;
+	unsigned short buffer_size_increments;
+	unsigned short long_command_ecc;
+	unsigned char  firmware_version[28];
+	unsigned char  model_name[18];
+	unsigned short reserved2[5];
+	unsigned short pio_mode_number;
+	unsigned short dma_mode_number;
+	unsigned short field_validity;
+	unsigned short current_logical_cylinders;
+	unsigned short current_logical_heads;
+	unsigned short current_pages_per_track;
+	unsigned int   current_page_capacity;
+	unsigned short mutiple_page_setting;
+	unsigned int   addressable_pages;
+	unsigned short single_word_dma;
+	unsigned short multi_word_dma;
+	unsigned char  reserved3[128];
+} __packed;
+
+
+struct ms_boot_page {
+	struct ms_boot_header    header;
+	struct ms_system_entry   entry;
+	struct ms_boot_attr_info attr;
+} __packed;
+
+struct msb_data {
+	unsigned int			usage_count;
+	struct memstick_dev		*card;
+	struct gendisk			*disk;
+	struct request_queue		*queue;
+	spinlock_t			q_lock;
+	struct hd_geometry		geometry;
+	struct attribute_group		attr_group;
+	struct request			*req;
+	int				caps;
+	int				disk_id;
+
+	/* IO */
+	struct workqueue_struct		*io_queue;
+	bool				io_queue_stopped;
+	struct work_struct		io_work;
+	bool				card_dead;
+
+	/* Media properties */
+	struct ms_boot_page		*boot_page;
+	u16				boot_block_locations[2];
+	int				boot_block_count;
+
+	bool				read_only;
+	unsigned short			page_size;
+	int				block_size;
+	int				pages_in_block;
+	int				zone_count;
+	int				block_count;
+	int				logical_block_count;
+
+	/* FTL tables */
+	unsigned long			*used_blocks_bitmap;
+	unsigned long			*erased_blocks_bitmap;
+	u16				*lba_to_pba_table;
+	int				free_block_count[MS_MAX_ZONES];
+	bool				ftl_initialized;
+
+	/* Cache */
+	unsigned char			*cache;
+	unsigned long			valid_cache_bitmap;
+	int				cache_block_lba;
+	bool				need_flush_cache;
+	struct timer_list		cache_flush_timer;
+
+	/* Preallocated buffers */
+	unsigned char			*block_buffer;
+	struct scatterlist		prealloc_sg[MS_BLOCK_MAX_SEGS+1];
+
+
+	/* handler's local data */
+	struct ms_register_addr		reg_addr;
+	bool				addr_valid;
+
+	u8				command_value;
+	bool				command_need_oob;
+	struct scatterlist		*current_sg;
+	int				current_sg_offset;
+
+	struct ms_register		regs;
+	int				current_page;
+
+	int				state;
+	int				exit_error;
+	bool				int_polling;
+	unsigned long			int_timeout;
+
+};
+
+enum msb_readpage_states {
+	MSB_RP_SEND_BLOCK_ADDRESS = 0,
+	MSB_RP_SEND_READ_COMMAND,
+
+	MSB_RP_SEND_INT_REQ,
+	MSB_RP_RECEIVE_INT_REQ_RESULT,
+
+	MSB_RP_SEND_READ_STATUS_REG,
+	MSB_RP_RECIVE_STATUS_REG,
+
+	MSB_RP_SEND_OOB_READ,
+	MSB_RP_RECEIVE_OOB_READ,
+
+	MSB_RP_SEND_READ_DATA,
+	MSB_RP_RECEIVE_READ_DATA,
+};
+
+enum msb_write_block_states {
+	MSB_WB_SEND_WRITE_PARAMS = 0,
+	MSB_WB_SEND_WRITE_OOB,
+	MSB_WB_SEND_WRITE_COMMAND,
+
+	MSB_WB_SEND_INT_REQ,
+	MSB_WB_RECEIVE_INT_REQ,
+
+	MSB_WB_SEND_WRITE_DATA,
+	MSB_WB_RECEIVE_WRITE_CONFIRMATION,
+};
+
+enum msb_send_command_states {
+	MSB_SC_SEND_WRITE_PARAMS,
+	MSB_SC_SEND_WRITE_OOB,
+	MSB_SC_SEND_COMMAND,
+
+	MSB_SC_SEND_INT_REQ,
+	MSB_SC_RECEIVE_INT_REQ,
+
+};
+
+enum msb_reset_states {
+	MSB_RS_SEND,
+	MSB_RS_CONFIRM,
+};
+
+enum msb_par_switch_states {
+	MSB_PS_SEND_SWITCH_COMMAND,
+	MSB_PS_SWICH_HOST,
+	MSB_PS_CONFIRM,
+};
+
+struct chs_entry {
+	unsigned long size;
+	unsigned char sec;
+	unsigned short cyl;
+	unsigned char head;
+};
+
+static int msb_reset(struct msb_data *msb, bool full);
+
+static int h_msb_default_bad(struct memstick_dev *card,
+						struct memstick_request **mrq);
+
+#define __dbg(level, format, ...) \
+	do { \
+		if (debug >= level) \
+			pr_err(format "\n", ## __VA_ARGS__); \
+	} while (0)
+
+
+#define dbg(format, ...)		__dbg(1, format, ## __VA_ARGS__)
+#define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
+
+#endif
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 6c95483..cd9e174 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -541,7 +541,7 @@ static int pm800_probe(struct i2c_client *client,
 {
 	int ret = 0;
 	struct pm80x_chip *chip;
-	struct pm80x_platform_data *pdata = client->dev.platform_data;
+	struct pm80x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct pm80x_subchip *subchip;
 
 	ret = pm80x_init(client);
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 5216022..0686cdb 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -227,7 +227,7 @@ static int pm805_probe(struct i2c_client *client,
 {
 	int ret = 0;
 	struct pm80x_chip *chip;
-	struct pm80x_platform_data *pdata = client->dev.platform_data;
+	struct pm80x_platform_data *pdata = dev_get_platdata(&client->dev);
 
 	ret = pm80x_init(client);
 	if (ret) {
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index eeb481d..7ebe9ef 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -1130,7 +1130,7 @@ static int pm860x_dt_init(struct device_node *np,
 static int pm860x_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
-	struct pm860x_platform_data *pdata = client->dev.platform_data;
+	struct pm860x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct device_node *node = client->dev.of_node;
 	struct pm860x_chip *chip;
 	int ret;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index aecd6dd..633ee43 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1070,7 +1070,7 @@ config MFD_WM5110
 	  Support for Wolfson Microelectronics WM5110 low power audio SoC
 
 config MFD_WM8997
-	bool "Support Wolfson Microelectronics WM8997"
+	bool "Wolfson Microelectronics WM8997"
 	depends on MFD_ARIZONA
 	help
 	  Support for Wolfson Microelectronics WM8997 low power audio SoC
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index d4f5945..6f68472 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -363,7 +363,7 @@ static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
 static int aat2870_i2c_probe(struct i2c_client *client,
 			     const struct i2c_device_id *id)
 {
-	struct aat2870_platform_data *pdata = client->dev.platform_data;
+	struct aat2870_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct aat2870_data *aat2870;
 	int i, j;
 	int ret = 0;
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index ddc669d..b348ae5 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -854,7 +854,7 @@ static int ab3100_probe(struct i2c_client *client,
 {
 	struct ab3100 *ab3100;
 	struct ab3100_platform_data *ab3100_plf_data =
-		client->dev.platform_data;
+		dev_get_platdata(&client->dev);
 	int err;
 	int i;
 
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index 7623e91..36000f9 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -867,6 +867,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 		gpadc->cal_data[ADC_INPUT_VBAT].offset);
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static int ab8500_gpadc_runtime_suspend(struct device *dev)
 {
 	struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
@@ -885,7 +886,9 @@ static int ab8500_gpadc_runtime_resume(struct device *dev)
 		dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
 	return ret;
 }
+#endif
 
+#ifdef CONFIG_PM_SLEEP
 static int ab8500_gpadc_suspend(struct device *dev)
 {
 	struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
@@ -913,6 +916,7 @@ static int ab8500_gpadc_resume(struct device *dev)
 	mutex_unlock(&gpadc->ab8500_gpadc_lock);
 	return ret;
 }
+#endif
 
 static int ab8500_gpadc_probe(struct platform_device *pdev)
 {
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index 28346ad..6250155 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -207,7 +207,7 @@ static int adp5520_remove_subdevs(struct adp5520_chip *chip)
 static int adp5520_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
-	struct adp5520_platform_data *pdata = client->dev.platform_data;
+	struct adp5520_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct platform_device *pdev;
 	struct adp5520_chip *chip;
 	int ret;
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 89a1153..5ac3aa4 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -438,9 +438,9 @@ static int arizona_runtime_suspend(struct device *dev)
 		}
 	}
 
-	regulator_disable(arizona->dcvdd);
 	regcache_cache_only(arizona->regmap, true);
 	regcache_mark_dirty(arizona->regmap);
+	regulator_disable(arizona->dcvdd);
 
 	return 0;
 }
diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c
index 01e4141..abd3ab7 100644
--- a/drivers/mfd/as3711.c
+++ b/drivers/mfd/as3711.c
@@ -129,7 +129,7 @@ static int as3711_i2c_probe(struct i2c_client *client,
 	int ret;
 
 	if (!client->dev.of_node) {
-		pdata = client->dev.platform_data;
+		pdata = dev_get_platdata(&client->dev);
 		if (!pdata)
 			dev_dbg(&client->dev, "Platform data not found\n");
 	} else {
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 9532f74..fa22154 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -952,7 +952,7 @@ static void asic3_mfd_remove(struct platform_device *pdev)
 /* Core */
 static int __init asic3_probe(struct platform_device *pdev)
 {
-	struct asic3_platform_data *pdata = pdev->dev.platform_data;
+	struct asic3_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct asic3 *asic;
 	struct resource *mem;
 	unsigned long clksel;
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index f1a316e..e0a2e0e 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -494,7 +494,7 @@ failed:
 static int da903x_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
-	struct da903x_platform_data *pdata = client->dev.platform_data;
+	struct da903x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct da903x_chip *chip;
 	unsigned int tmp;
 	int ret;
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index a3c9613..ea28a33 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(da9052_regmap_config);
 
 int da9052_device_init(struct da9052 *da9052, u8 chip_id)
 {
-	struct da9052_pdata *pdata = da9052->dev->platform_data;
+	struct da9052_pdata *pdata = dev_get_platdata(da9052->dev);
 	int ret;
 
 	mutex_init(&da9052->auxadc_lock);
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
index 49cb23d..d3670cd 100644
--- a/drivers/mfd/da9055-core.c
+++ b/drivers/mfd/da9055-core.c
@@ -379,8 +379,9 @@ static struct regmap_irq_chip da9055_regmap_irq_chip = {
 
 int da9055_device_init(struct da9055 *da9055)
 {
-	struct da9055_pdata *pdata = da9055->dev->platform_data;
+	struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
 	int ret;
+	uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF};
 
 	if (pdata && pdata->init != NULL)
 		pdata->init(da9055);
@@ -390,6 +391,10 @@ int da9055_device_init(struct da9055 *da9055)
 	else
 		da9055->irq_base = pdata->irq_base;
 
+	ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events);
+	if (ret < 0)
+		return ret;
+
 	ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
 				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 				  da9055->irq_base, &da9055_regmap_irq_chip,
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 607387f..13af7e5 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -54,7 +54,7 @@ static int da9055_i2c_remove(struct i2c_client *i2c)
 }
 
 static struct i2c_device_id da9055_i2c_id[] = {
-	{"da9055-pmic", 0},
+	{"da9055", 0},
 	{ }
 };
 
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 3c157fa..0d68eb1 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -3094,6 +3094,10 @@ static struct mfd_cell db8500_prcmu_devs[] = {
 		.pdata_size = sizeof(db8500_cpufreq_table),
 	},
 	{
+		.name = "cpuidle-dbx500",
+		.of_compatible = "stericsson,cpuidle-dbx500",
+	},
+	{
 		.name = "db8500-thermal",
 		.num_resources = ARRAY_SIZE(db8500_thsens_resources),
 		.resources = db8500_thsens_resources,
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 7710227..7a55c00 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -315,8 +315,8 @@ static int add_children(struct i2c_client *client)
 	}
 
 	/* MMC/SD inputs -- right after the last config input */
-	if (client->dev.platform_data) {
-		void (*mmcsd_setup)(unsigned) = client->dev.platform_data;
+	if (dev_get_platdata(&client->dev)) {
+		void (*mmcsd_setup)(unsigned) = dev_get_platdata(&client->dev);
 
 		mmcsd_setup(dm355evm_msp_gpio.base + 8 + 5);
 	}
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index 5502106..7245b0c 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -177,7 +177,7 @@ static void pcap_msr_work(struct work_struct *work)
 static void pcap_isr_work(struct work_struct *work)
 {
 	struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work);
-	struct pcap_platform_data *pdata = pcap->spi->dev.platform_data;
+	struct pcap_platform_data *pdata = dev_get_platdata(&pcap->spi->dev);
 	u32 msr, isr, int_sel, service;
 	int irq;
 
@@ -394,7 +394,7 @@ static int pcap_add_subdev(struct pcap_chip *pcap,
 static int ezx_pcap_remove(struct spi_device *spi)
 {
 	struct pcap_chip *pcap = spi_get_drvdata(spi);
-	struct pcap_platform_data *pdata = spi->dev.platform_data;
+	struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev);
 	int i, adc_irq;
 
 	/* remove all registered subdevs */
@@ -420,7 +420,7 @@ static int ezx_pcap_remove(struct spi_device *spi)
 
 static int ezx_pcap_probe(struct spi_device *spi)
 {
-	struct pcap_platform_data *pdata = spi->dev.platform_data;
+	struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev);
 	struct pcap_chip *pcap;
 	int i, adc_irq;
 	int ret = -ENODEV;
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index 26aca54..49f39fe 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -261,7 +261,7 @@ static void egpio_write_cache(struct egpio_info *ei)
 
 static int __init egpio_probe(struct platform_device *pdev)
 {
-	struct htc_egpio_platform_data *pdata = pdev->dev.platform_data;
+	struct htc_egpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct resource   *res;
 	struct egpio_info *ei;
 	struct gpio_chip  *chip;
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index c9dfce6..d7b2a75 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -340,7 +340,7 @@ static int htcpld_setup_chip_irq(
 	int ret = 0;
 
 	/* Get the platform and driver data */
-	pdata = dev->platform_data;
+	pdata = dev_get_platdata(dev);
 	htcpld = platform_get_drvdata(pdev);
 	chip = &htcpld->chip[chip_index];
 	plat_chip_data = &pdata->chip[chip_index];
@@ -375,7 +375,7 @@ static int htcpld_register_chip_i2c(
 	struct i2c_board_info info;
 
 	/* Get the platform and driver data */
-	pdata = dev->platform_data;
+	pdata = dev_get_platdata(dev);
 	htcpld = platform_get_drvdata(pdev);
 	chip = &htcpld->chip[chip_index];
 	plat_chip_data = &pdata->chip[chip_index];
@@ -447,7 +447,7 @@ static int htcpld_register_chip_gpio(
 	int ret = 0;
 
 	/* Get the platform and driver data */
-	pdata = dev->platform_data;
+	pdata = dev_get_platdata(dev);
 	htcpld = platform_get_drvdata(pdev);
 	chip = &htcpld->chip[chip_index];
 	plat_chip_data = &pdata->chip[chip_index];
@@ -509,7 +509,7 @@ static int htcpld_setup_chips(struct platform_device *pdev)
 	int i;
 
 	/* Get the platform and driver data */
-	pdata = dev->platform_data;
+	pdata = dev_get_platdata(dev);
 	htcpld = platform_get_drvdata(pdev);
 
 	/* Setup each chip's output GPIOs */
@@ -574,7 +574,7 @@ static int htcpld_core_probe(struct platform_device *pdev)
 	if (!dev)
 		return -ENODEV;
 
-	pdata = dev->platform_data;
+	pdata = dev_get_platdata(dev);
 	if (!pdata) {
 		dev_warn(dev, "Platform data not found for htcpld core!\n");
 		return -ENXIO;
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 0a5e85f..6bf92a5 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -126,7 +126,7 @@ static struct mfd_cell ds1wm_cell __initdata = {
 
 static int __init pasic3_probe(struct platform_device *pdev)
 {
-	struct pasic3_platform_data *pdata = pdev->dev.platform_data;
+	struct pasic3_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device *dev = &pdev->dev;
 	struct pasic3_data *asic;
 	struct resource *r;
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 4f2462f..9203d47 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -310,7 +310,7 @@ EXPORT_SYMBOL_GPL(intel_msic_irq_read);
 static int intel_msic_init_devices(struct intel_msic *msic)
 {
 	struct platform_device *pdev = msic->pdev;
-	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+	struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int ret, i;
 
 	if (pdata->gpio) {
@@ -372,7 +372,7 @@ static void intel_msic_remove_devices(struct intel_msic *msic)
 
 static int intel_msic_probe(struct platform_device *pdev)
 {
-	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+	struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct intel_msic *msic;
 	struct resource *res;
 	u8 id0, id1;
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 686a456..ab36e6e 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -258,7 +258,7 @@ EXPORT_SYMBOL_GPL(kempld_write32);
  */
 void kempld_get_mutex(struct kempld_device_data *pld)
 {
-	struct kempld_platform_data *pdata = pld->dev->platform_data;
+	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
 	mutex_lock(&pld->lock);
 	pdata->get_hardware_mutex(pld);
@@ -271,7 +271,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex);
  */
 void kempld_release_mutex(struct kempld_device_data *pld)
 {
-	struct kempld_platform_data *pdata = pld->dev->platform_data;
+	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
 	pdata->release_hardware_mutex(pld);
 	mutex_unlock(&pld->lock);
@@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
  */
 static int kempld_get_info(struct kempld_device_data *pld)
 {
-	struct kempld_platform_data *pdata = pld->dev->platform_data;
+	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
 	return pdata->get_info(pld);
 }
@@ -302,7 +302,7 @@ static int kempld_get_info(struct kempld_device_data *pld)
  */
 static int kempld_register_cells(struct kempld_device_data *pld)
 {
-	struct kempld_platform_data *pdata = pld->dev->platform_data;
+	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
 	return pdata->register_cells(pld);
 }
@@ -357,7 +357,7 @@ static int kempld_detect_device(struct kempld_device_data *pld)
 
 static int kempld_probe(struct platform_device *pdev)
 {
-	struct kempld_platform_data *pdata = pdev->dev.platform_data;
+	struct kempld_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device *dev = &pdev->dev;
 	struct kempld_device_data *pld;
 	struct resource *ioport;
@@ -394,7 +394,7 @@ static int kempld_probe(struct platform_device *pdev)
 static int kempld_remove(struct platform_device *pdev)
 {
 	struct kempld_device_data *pld = platform_get_drvdata(pdev);
-	struct kempld_platform_data *pdata = pld->dev->platform_data;
+	struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
 	mfd_remove_devices(&pdev->dev);
 	pdata->release_hardware_mutex(pld);
diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 4b7e6da..8c29f7b 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -384,7 +384,7 @@ static struct attribute_group lm3533_attribute_group = {
 
 static int lm3533_device_als_init(struct lm3533 *lm3533)
 {
-	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
 	int ret;
 
 	if (!pdata->als)
@@ -407,7 +407,7 @@ static int lm3533_device_als_init(struct lm3533 *lm3533)
 
 static int lm3533_device_bl_init(struct lm3533 *lm3533)
 {
-	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
 	int i;
 	int ret;
 
@@ -436,7 +436,7 @@ static int lm3533_device_bl_init(struct lm3533 *lm3533)
 
 static int lm3533_device_led_init(struct lm3533 *lm3533)
 {
-	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
 	int i;
 	int ret;
 
@@ -481,7 +481,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533,
 
 static int lm3533_device_init(struct lm3533 *lm3533)
 {
-	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
 	int ret;
 
 	dev_dbg(lm3533->dev, "%s\n", __func__);
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index c3d3c9b..0f12219 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -173,7 +173,7 @@ static const struct regmap_config lp8788_regmap_config = {
 static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
 	struct lp8788 *lp;
-	struct lp8788_platform_data *pdata = cl->dev.platform_data;
+	struct lp8788_platform_data *pdata = dev_get_platdata(&cl->dev);
 	int ret;
 
 	lp = devm_kzalloc(&cl->dev, sizeof(struct lp8788), GFP_KERNEL);
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 2403332..9483bc8 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -213,7 +213,7 @@ enum lpc_chipsets {
 	LPC_COLETO,	/* Coleto Creek */
 };
 
-struct lpc_ich_info lpc_chipset_info[] = {
+static struct lpc_ich_info lpc_chipset_info[] = {
 	[LPC_ICH] = {
 		.name = "ICH",
 		.iTCO_version = 1,
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index f27a218..522be67 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -77,7 +77,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
 	struct max77686_dev *max77686 = NULL;
-	struct max77686_platform_data *pdata = i2c->dev.platform_data;
+	struct max77686_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	unsigned int data;
 	int ret = 0;
 
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 9e60fed..c04723e 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -110,7 +110,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
 	struct max77693_dev *max77693;
-	struct max77693_platform_data *pdata = i2c->dev.platform_data;
+	struct max77693_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	u8 reg_data;
 	int ret = 0;
 
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index 8042b32..de7fb80 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -151,7 +151,7 @@ static int max8925_dt_init(struct device_node *np, struct device *dev,
 static int max8925_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
-	struct max8925_platform_data *pdata = client->dev.platform_data;
+	struct max8925_platform_data *pdata = dev_get_platdata(&client->dev);
 	static struct max8925_chip *chip;
 	struct device_node *node = client->dev.of_node;
 
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 1471405..1523047 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -51,7 +51,7 @@ static struct mfd_cell max8997_devs[] = {
 
 #ifdef CONFIG_OF
 static struct of_device_id max8997_pmic_dt_match[] = {
-	{ .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
+	{ .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 },
 	{},
 };
 #endif
@@ -188,7 +188,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct max8997_dev *max8997;
-	struct max8997_platform_data *pdata = i2c->dev.platform_data;
+	struct max8997_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	int ret = 0;
 
 	max8997 = kzalloc(sizeof(struct max8997_dev), GFP_KERNEL);
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 21af51a..45bffb8 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -184,7 +184,7 @@ static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
 static int max8998_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
-	struct max8998_platform_data *pdata = i2c->dev.platform_data;
+	struct max8998_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	struct max8998_dev *max8998;
 	int ret = 0;
 
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 13198d9..41c31b3 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -156,7 +156,7 @@ static struct mcp_ops mcp_sa11x0 = {
 
 static int mcp_sa11x0_probe(struct platform_device *dev)
 {
-	struct mcp_plat_data *data = dev->dev.platform_data;
+	struct mcp_plat_data *data = dev_get_platdata(&dev->dev);
 	struct resource *mem0, *mem1;
 	struct mcp_sa11x0 *m;
 	struct mcp *mcp;
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index 998ce8c..f24df8c 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -442,7 +442,7 @@ void menelaus_unregister_mmc_callback(void)
 	menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
 
 	the_menelaus->mmc_callback = NULL;
-	the_menelaus->mmc_callback_data = 0;
+	the_menelaus->mmc_callback_data = NULL;
 }
 EXPORT_SYMBOL(menelaus_unregister_mmc_callback);
 
@@ -466,7 +466,7 @@ static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV,
 	struct i2c_client *c = the_menelaus->client;
 
 	mutex_lock(&the_menelaus->lock);
-	if (vtg == 0)
+	if (!vtg)
 		goto set_voltage;
 
 	ret = menelaus_read_reg(vtg->vtg_reg);
@@ -1189,7 +1189,7 @@ static int menelaus_probe(struct i2c_client *client,
 	int			rev = 0, val;
 	int			err = 0;
 	struct menelaus_platform_data *menelaus_pdata =
-					client->dev.platform_data;
+					dev_get_platdata(&client->dev);
 
 	if (the_menelaus) {
 		dev_dbg(&client->dev, "only one %s for now\n",
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 759fae3..d2b8e71 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -232,7 +232,7 @@ err_end:
 static int omap_usbhs_alloc_children(struct platform_device *pdev)
 {
 	struct device				*dev = &pdev->dev;
-	struct usbhs_omap_platform_data		*pdata = dev->platform_data;
+	struct usbhs_omap_platform_data		*pdata = dev_get_platdata(dev);
 	struct platform_device			*ehci;
 	struct platform_device			*ohci;
 	struct resource				*res;
@@ -571,7 +571,7 @@ static struct of_device_id usbhs_child_match_table[] = {
 static int usbhs_omap_probe(struct platform_device *pdev)
 {
 	struct device			*dev =  &pdev->dev;
-	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_omap_platform_data	*pdata = dev_get_platdata(dev);
 	struct usbhs_hcd_omap		*omap;
 	struct resource			*res;
 	int				ret = 0;
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index d115673..6841d68 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -195,7 +195,7 @@ static int pcf50633_probe(struct i2c_client *client,
 				const struct i2c_device_id *ids)
 {
 	struct pcf50633 *pcf;
-	struct pcf50633_platform_data *pdata = client->dev.platform_data;
+	struct pcf50633_platform_data *pdata = dev_get_platdata(&client->dev);
 	int i, ret;
 	int version, variant;
 
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index ecc137f..9be6840 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -106,7 +106,7 @@ static int pm8921_add_subdevices(const struct pm8921_platform_data
 
 static int pm8921_probe(struct platform_device *pdev)
 {
-	const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
+	const struct pm8921_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct pm8921 *pmic;
 	int rc;
 	u8 val;
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index 14bdacc..3463301 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -250,7 +250,7 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
 	struct rc5t583 *rc5t583;
-	struct rc5t583_platform_data *pdata = i2c->dev.platform_data;
+	struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	int ret;
 	bool irq_init_success = false;
 
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 7976768..86a7d61 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -69,6 +69,9 @@ static struct of_device_id sec_dt_match[] = {
 	{	.compatible = "samsung,s5m8767-pmic",
 		.data = (void *)S5M8767X,
 	},
+	{	.compatible = "samsung,s2mps11-pmic",
+		.data = (void *)S2MPS11X,
+	},
 	{},
 };
 #endif
@@ -103,6 +106,31 @@ int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask)
 }
 EXPORT_SYMBOL_GPL(sec_reg_update);
 
+static bool s2mps11_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MPS11_REG_INT1M:
+	case S2MPS11_REG_INT2M:
+	case S2MPS11_REG_INT3M:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static bool s5m8763_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S5M8763_REG_IRQM1:
+	case S5M8763_REG_IRQM2:
+	case S5M8763_REG_IRQM3:
+	case S5M8763_REG_IRQM4:
+		return false;
+	default:
+		return true;
+	}
+}
+
 static struct regmap_config sec_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -113,6 +141,8 @@ static struct regmap_config s2mps11_regmap_config = {
 	.val_bits = 8,
 
 	.max_register = S2MPS11_REG_L38CTRL,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
 };
 
 static struct regmap_config s5m8763_regmap_config = {
@@ -120,6 +150,8 @@ static struct regmap_config s5m8763_regmap_config = {
 	.val_bits = 8,
 
 	.max_register = S5M8763_REG_LBCNFG2,
+	.volatile_reg = s5m8763_volatile,
+	.cache_type = REGCACHE_FLAT,
 };
 
 static struct regmap_config s5m8767_regmap_config = {
@@ -127,6 +159,8 @@ static struct regmap_config s5m8767_regmap_config = {
 	.val_bits = 8,
 
 	.max_register = S5M8767_REG_LDO28CTRL,
+	.volatile_reg = s2mps11_volatile,
+	.cache_type = REGCACHE_FLAT,
 };
 
 #ifdef CONFIG_OF
@@ -182,7 +216,7 @@ static inline int sec_i2c_get_driver_data(struct i2c_client *i2c,
 static int sec_pmic_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
-	struct sec_platform_data *pdata = i2c->dev.platform_data;
+	struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	const struct regmap_config *regmap;
 	struct sec_pmic_dev *sec_pmic;
 	int ret;
diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c
index f5bc8e4..0e4a76d 100644
--- a/drivers/mfd/si476x-i2c.c
+++ b/drivers/mfd/si476x-i2c.c
@@ -718,7 +718,7 @@ static int si476x_core_probe(struct i2c_client *client,
 	atomic_set(&core->is_alive, 0);
 	core->power_state = SI476X_POWER_DOWN;
 
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 	if (pdata) {
 		memcpy(&core->power_up_parameters,
 		       &pdata->power_up_parameters,
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 9816c23..33f040c 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -840,7 +840,7 @@ static int sm501_register_uart(struct sm501_devdata *sm, int devices)
 	if (!pdev)
 		return -ENOMEM;
 
-	uart_data = pdev->dev.platform_data;
+	uart_data = dev_get_platdata(&pdev->dev);
 
 	if (devices & SM501_USE_UART0) {
 		sm501_setup_uart_data(sm, uart_data++, 0x30000);
@@ -1167,7 +1167,7 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
 	if (!pdev)
 		return -ENOMEM;
 
-	icd = pdev->dev.platform_data;
+	icd = dev_get_platdata(&pdev->dev);
 
 	/* We keep the pin_sda and pin_scl fields relative in case the
 	 * same platform data is passed to >1 SM501.
@@ -1403,7 +1403,7 @@ static int sm501_plat_probe(struct platform_device *dev)
 
 	sm->dev = &dev->dev;
 	sm->pdev_id = dev->id;
-	sm->platdata = dev->dev.platform_data;
+	sm->platdata = dev_get_platdata(&dev->dev);
 
 	ret = platform_get_irq(dev, 0);
 	if (ret < 0) {
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index d70a3430..65c6fa6 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -133,7 +133,7 @@ int sta2x11_mfd_get_regs_data(struct platform_device *dev,
 			      void __iomem **regs,
 			      spinlock_t **lock)
 {
-	struct pci_dev *pdev = *(struct pci_dev **)(dev->dev.platform_data);
+	struct pci_dev *pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
 	struct sta2x11_mfd *mfd;
 
 	if (!pdev)
@@ -312,7 +312,7 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
 	const char *name = sta2x11_mfd_names[index];
 	struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
 
-	pdev = dev->dev.platform_data;
+	pdev = dev_get_platdata(&dev->dev);
 	mfd = sta2x11_mfd_find(*pdev);
 	if (!mfd)
 		return -ENODEV;
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 5d5e6f9..fff63a4 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1106,7 +1106,8 @@ static int stmpe_devices_init(struct stmpe *stmpe)
 	return ret;
 }
 
-void stmpe_of_probe(struct stmpe_platform_data *pdata, struct device_node *np)
+static void stmpe_of_probe(struct stmpe_platform_data *pdata,
+			   struct device_node *np)
 {
 	struct device_node *child;
 
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 1a31512..27db1f9 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -25,7 +25,6 @@
 static struct platform_driver syscon_driver;
 
 struct syscon {
-	void __iomem *base;
 	struct regmap *regmap;
 };
 
@@ -129,6 +128,7 @@ static int syscon_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct syscon *syscon;
 	struct resource *res;
+	void __iomem *base;
 
 	syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
 	if (!syscon)
@@ -138,12 +138,12 @@ static int syscon_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENOENT;
 
-	syscon->base = devm_ioremap(dev, res->start, resource_size(res));
-	if (!syscon->base)
+	base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!base)
 		return -ENOMEM;
 
 	syscon_regmap_config.max_register = res->end - res->start - 3;
-	syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
+	syscon->regmap = devm_regmap_init_mmio(dev, base,
 					&syscon_regmap_config);
 	if (IS_ERR(syscon->regmap)) {
 		dev_err(dev, "regmap init failed\n");
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index a21bff2..9e04a74 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -281,7 +281,7 @@ static void t7l66xb_detach_irq(struct platform_device *dev)
 static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
-	struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
+	struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 
 	if (pdata && pdata->suspend)
 		pdata->suspend(dev);
@@ -293,7 +293,7 @@ static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
 static int t7l66xb_resume(struct platform_device *dev)
 {
 	struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
-	struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
+	struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 
 	clk_enable(t7l66xb->clk48m);
 	if (pdata && pdata->resume)
@@ -313,7 +313,7 @@ static int t7l66xb_resume(struct platform_device *dev)
 
 static int t7l66xb_probe(struct platform_device *dev)
 {
-	struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
+	struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 	struct t7l66xb *t7l66xb;
 	struct resource *iomem, *rscr;
 	int ret;
@@ -409,7 +409,7 @@ err_noirq:
 
 static int t7l66xb_remove(struct platform_device *dev)
 {
-	struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
+	struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 	struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
 	int ret;
 
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 4cb92bb..70f4909f 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -325,7 +325,7 @@ static int tc3589x_of_probe(struct device_node *np,
 static int tc3589x_probe(struct i2c_client *i2c,
 				   const struct i2c_device_id *id)
 {
-	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
+	struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	struct device_node *np = i2c->dev.of_node;
 	struct tc3589x *tc3589x;
 	int ret;
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 65c425a..acd0f3a 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -48,7 +48,7 @@ static struct resource tc6387xb_mmc_resources[] = {
 static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
-	struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
+	struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 
 	if (pdata && pdata->suspend)
 		pdata->suspend(dev);
@@ -60,7 +60,7 @@ static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
 static int tc6387xb_resume(struct platform_device *dev)
 {
 	struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
-	struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
+	struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 
 	clk_enable(tc6387xb->clk32k);
 	if (pdata && pdata->resume)
@@ -140,7 +140,7 @@ static struct mfd_cell tc6387xb_cells[] = {
 
 static int tc6387xb_probe(struct platform_device *dev)
 {
-	struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
+	struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 	struct resource *iomem, *rscr;
 	struct clk *clk32k;
 	struct tc6387xb *tc6387xb;
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index a563dfa..11c19e5 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -604,7 +604,7 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
 
 static int tc6393xb_probe(struct platform_device *dev)
 {
-	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
 	struct tc6393xb *tc6393xb;
 	struct resource *iomem, *rscr;
 	int ret, temp;
@@ -733,7 +733,7 @@ err_kzalloc:
 
 static int tc6393xb_remove(struct platform_device *dev)
 {
-	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
 	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
 	int ret;
 
@@ -765,7 +765,7 @@ static int tc6393xb_remove(struct platform_device *dev)
 #ifdef CONFIG_PM
 static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
 {
-	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
 	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
 	int i, ret;
 
@@ -788,7 +788,7 @@ static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
 
 static int tc6393xb_resume(struct platform_device *dev)
 {
-	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
 	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
 	int ret;
 	int i;
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
index 09a14ce..1c2b994 100644
--- a/drivers/mfd/ti-ssp.c
+++ b/drivers/mfd/ti-ssp.c
@@ -318,7 +318,7 @@ static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
 static int ti_ssp_probe(struct platform_device *pdev)
 {
 	static struct ti_ssp *ssp;
-	const struct ti_ssp_data *pdata = pdev->dev.platform_data;
+	const struct ti_ssp_data *pdata = dev_get_platdata(&pdev->dev);
 	int error = 0, prediv = 0xff, id;
 	unsigned long sysclk;
 	struct device *dev = &pdev->dev;
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index b003a16..9f3f07a 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -57,10 +57,10 @@ EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
 void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
 {
 	spin_lock(&tsadc->reg_lock);
+	tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
 	tsadc->reg_se_cache |= val;
-	spin_unlock(&tsadc->reg_lock);
-
 	am335x_tsc_se_update(tsadc);
+	spin_unlock(&tsadc->reg_lock);
 }
 EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
 
@@ -197,24 +197,21 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 	clock_rate = clk_get_rate(clk);
 	clk_put(clk);
 	clk_value = clock_rate / ADC_CLK;
-	if (clk_value < MAX_CLK_DIV) {
-		dev_err(&pdev->dev, "clock input less than min clock requirement\n");
-		err = -EINVAL;
-		goto err_disable_clk;
-	}
+
 	/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
 	clk_value = clk_value - 1;
 	tscadc_writel(tscadc, REG_CLKDIV, clk_value);
 
 	/* Set the control register bits */
 	ctrl = CNTRLREG_STEPCONFIGWRT |
-			CNTRLREG_TSCENB |
-			CNTRLREG_STEPID |
-			CNTRLREG_4WIRE;
+			CNTRLREG_STEPID;
+	if (tsc_wires > 0)
+		ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
 	tscadc_writel(tscadc, REG_CTRL, ctrl);
 
 	/* Set register bits for Idle Config Mode */
-	tscadc_idle_config(tscadc);
+	if (tsc_wires > 0)
+		tscadc_idle_config(tscadc);
 
 	/* Enable the TSC module enable bit */
 	ctrl = tscadc_readl(tscadc, REG_CTRL);
@@ -294,10 +291,13 @@ static int tscadc_resume(struct device *dev)
 	pm_runtime_get_sync(dev);
 
 	/* context restore */
-	ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
-			CNTRLREG_STEPID | CNTRLREG_4WIRE;
+	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
+	if (tscadc_dev->tsc_cell != -1)
+		ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE;
 	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
-	tscadc_idle_config(tscadc_dev);
+
+	if (tscadc_dev->tsc_cell != -1)
+		tscadc_idle_config(tscadc_dev);
 	am335x_tsc_se_update(tscadc_dev);
 	restore = tscadc_readl(tscadc_dev, REG_CTRL);
 	tscadc_writel(tscadc_dev, REG_CTRL,
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index 1d302f5..b5dfa6e 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -147,7 +147,7 @@ static int tps6105x_probe(struct i2c_client *client,
 
 	i2c_set_clientdata(client, tps6105x);
 	tps6105x->client = client;
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 	tps6105x->pdata = pdata;
 	mutex_init(&tps6105x->lock);
 
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index da2691f..4d67692 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -517,7 +517,7 @@ static struct tps65010 *the_tps;
 static int __exit tps65010_remove(struct i2c_client *client)
 {
 	struct tps65010		*tps = i2c_get_clientdata(client);
-	struct tps65010_board	*board = client->dev.platform_data;
+	struct tps65010_board	*board = dev_get_platdata(&client->dev);
 
 	if (board && board->teardown) {
 		int status = board->teardown(client, board->context);
@@ -539,7 +539,7 @@ static int tps65010_probe(struct i2c_client *client,
 {
 	struct tps65010		*tps;
 	int			status;
-	struct tps65010_board	*board = client->dev.platform_data;
+	struct tps65010_board	*board = dev_get_platdata(&client->dev);
 
 	if (the_tps) {
 		dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index fbd6ee6..e6f03a7 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -172,7 +172,7 @@ MODULE_DEVICE_TABLE(of, tps65090_of_match);
 static int tps65090_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
-	struct tps65090_platform_data *pdata = client->dev.platform_data;
+	struct tps65090_platform_data *pdata = dev_get_platdata(&client->dev);
 	int irq_base = 0;
 	struct tps65090 *tps65090;
 	int ret;
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 4b93ed4..f54fe4d 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -462,7 +462,7 @@ static void tps6586x_power_off(void)
 static int tps6586x_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
-	struct tps6586x_platform_data *pdata = client->dev.platform_data;
+	struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct tps6586x *tps6586x;
 	int ret;
 
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
index 479886a..925a044 100644
--- a/drivers/mfd/tps65912-core.c
+++ b/drivers/mfd/tps65912-core.c
@@ -123,7 +123,7 @@ EXPORT_SYMBOL_GPL(tps65912_reg_write);
 
 int tps65912_device_init(struct tps65912 *tps65912)
 {
-	struct tps65912_board *pmic_plat_data = tps65912->dev->platform_data;
+	struct tps65912_board *pmic_plat_data = dev_get_platdata(tps65912->dev);
 	struct tps65912_platform_data *init_data;
 	int ret, dcdc_avs, value;
 
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index c90a2c4..f15ee6d 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -418,7 +418,7 @@ static const struct regmap_config tps80031_regmap_configs[] = {
 static int tps80031_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
-	struct tps80031_platform_data *pdata = client->dev.platform_data;
+	struct tps80031_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct tps80031 *tps80031;
 	int ret;
 	uint8_t es_version;
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 7f150d9..29473c2 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1137,7 +1137,7 @@ static int twl_remove(struct i2c_client *client)
 static int
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct twl4030_platform_data	*pdata = client->dev.platform_data;
+	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
 	struct device_node		*node = client->dev.of_node;
 	struct platform_device		*pdev;
 	struct regmap_config		*twl_regmap_config;
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index a31fba9..07fe542 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -187,7 +187,7 @@ static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
 static int twl4030_audio_probe(struct platform_device *pdev)
 {
 	struct twl4030_audio *audio;
-	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+	struct twl4030_audio_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device_node *node = pdev->dev.of_node;
 	struct mfd_cell *cell = NULL;
 	int ret, childs = 0;
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 1ea54d4..4c583e4 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -701,7 +701,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
 static int twl4030_madc_probe(struct platform_device *pdev)
 {
 	struct twl4030_madc_data *madc;
-	struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
+	struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int ret;
 	u8 regval;
 
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index a5fd3c7..96162b6 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -493,7 +493,7 @@ int twl4030_remove_script(u8 flags)
 	return err;
 }
 
-int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
+static int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
 {
 	int err;
 	int i;
@@ -509,7 +509,7 @@ int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
 	return 0;
 }
 
-int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
+static int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
 {
 	struct twl4030_resconfig *resconfig = pdata->resource_config;
 	int err;
@@ -553,9 +553,9 @@ static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata,
 	return false;
 }
 
-int twl4030_power_probe(struct platform_device *pdev)
+static int twl4030_power_probe(struct platform_device *pdev)
 {
-	struct twl4030_power_data *pdata = pdev->dev.platform_data;
+	struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device_node *node = pdev->dev.of_node;
 	int err = 0;
 	int err2 = 0;
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index 492ee2c..4d8d3b7 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -44,17 +44,12 @@
 #define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
 #define TWL6040_NUM_SUPPLIES	(2)
 
-static bool twl6040_has_vibra(struct twl6040_platform_data *pdata,
-			      struct device_node *node)
+static bool twl6040_has_vibra(struct device_node *node)
 {
-	if (pdata && pdata->vibra)
-		return true;
-
 #ifdef CONFIG_OF
 	if (of_find_node_by_name(node, "vibra"))
 		return true;
 #endif
-
 	return false;
 }
 
@@ -520,14 +515,13 @@ static struct regmap_irq_chip twl6040_irq_chip = {
 static int twl6040_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	struct twl6040_platform_data *pdata = client->dev.platform_data;
 	struct device_node *node = client->dev.of_node;
 	struct twl6040 *twl6040;
 	struct mfd_cell *cell = NULL;
 	int irq, ret, children = 0;
 
-	if (!pdata && !node) {
-		dev_err(&client->dev, "Platform data is missing\n");
+	if (!node) {
+		dev_err(&client->dev, "of node is missing\n");
 		return -EINVAL;
 	}
 
@@ -539,23 +533,19 @@ static int twl6040_probe(struct i2c_client *client,
 
 	twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
 			       GFP_KERNEL);
-	if (!twl6040) {
-		ret = -ENOMEM;
-		goto err;
-	}
+	if (!twl6040)
+		return -ENOMEM;
 
 	twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config);
-	if (IS_ERR(twl6040->regmap)) {
-		ret = PTR_ERR(twl6040->regmap);
-		goto err;
-	}
+	if (IS_ERR(twl6040->regmap))
+		return PTR_ERR(twl6040->regmap);
 
 	i2c_set_clientdata(client, twl6040);
 
 	twl6040->supplies[0].supply = "vio";
 	twl6040->supplies[1].supply = "v2v1";
 	ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
-				 twl6040->supplies);
+				      twl6040->supplies);
 	if (ret != 0) {
 		dev_err(&client->dev, "Failed to get supplies: %d\n", ret);
 		goto regulator_get_err;
@@ -576,44 +566,40 @@ static int twl6040_probe(struct i2c_client *client,
 	twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
 
 	/* ERRATA: Automatic power-up is not possible in ES1.0 */
-	if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
-		if (pdata)
-			twl6040->audpwron = pdata->audpwron_gpio;
-		else
-			twl6040->audpwron = of_get_named_gpio(node,
-						"ti,audpwron-gpio", 0);
-	} else
+	if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
+		twl6040->audpwron = of_get_named_gpio(node,
+						      "ti,audpwron-gpio", 0);
+	else
 		twl6040->audpwron = -EINVAL;
 
 	if (gpio_is_valid(twl6040->audpwron)) {
 		ret = devm_gpio_request_one(&client->dev, twl6040->audpwron,
-					GPIOF_OUT_INIT_LOW, "audpwron");
+					    GPIOF_OUT_INIT_LOW, "audpwron");
 		if (ret)
 			goto gpio_err;
 	}
 
-	ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq,
-			IRQF_ONESHOT, 0, &twl6040_irq_chip,
-			&twl6040->irq_data);
+	ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
+				  0, &twl6040_irq_chip,&twl6040->irq_data);
 	if (ret < 0)
 		goto gpio_err;
 
 	twl6040->irq_ready = regmap_irq_get_virq(twl6040->irq_data,
-					       TWL6040_IRQ_READY);
+						 TWL6040_IRQ_READY);
 	twl6040->irq_th = regmap_irq_get_virq(twl6040->irq_data,
-					       TWL6040_IRQ_TH);
+					      TWL6040_IRQ_TH);
 
 	ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_ready, NULL,
-				   twl6040_readyint_handler, IRQF_ONESHOT,
-				   "twl6040_irq_ready", twl6040);
+					twl6040_readyint_handler, IRQF_ONESHOT,
+					"twl6040_irq_ready", twl6040);
 	if (ret) {
 		dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret);
 		goto readyirq_err;
 	}
 
 	ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_th, NULL,
-				   twl6040_thint_handler, IRQF_ONESHOT,
-				   "twl6040_irq_th", twl6040);
+					twl6040_thint_handler, IRQF_ONESHOT,
+					"twl6040_irq_th", twl6040);
 	if (ret) {
 		dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret);
 		goto thirq_err;
@@ -625,8 +611,6 @@ static int twl6040_probe(struct i2c_client *client,
 	/*
 	 * The main functionality of twl6040 to provide audio on OMAP4+ systems.
 	 * We can add the ASoC codec child whenever this driver has been loaded.
-	 * The ASoC codec can work without pdata, pass the platform_data only if
-	 * it has been provided.
 	 */
 	irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_PLUG);
 	cell = &twl6040->cells[children];
@@ -635,13 +619,10 @@ static int twl6040_probe(struct i2c_client *client,
 	twl6040_codec_rsrc[0].end = irq;
 	cell->resources = twl6040_codec_rsrc;
 	cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
-	if (pdata && pdata->codec) {
-		cell->platform_data = pdata->codec;
-		cell->pdata_size = sizeof(*pdata->codec);
-	}
 	children++;
 
-	if (twl6040_has_vibra(pdata, node)) {
+	/* Vibra input driver support */
+	if (twl6040_has_vibra(node)) {
 		irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_VIB);
 
 		cell = &twl6040->cells[children];
@@ -650,28 +631,13 @@ static int twl6040_probe(struct i2c_client *client,
 		twl6040_vibra_rsrc[0].end = irq;
 		cell->resources = twl6040_vibra_rsrc;
 		cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
-
-		if (pdata && pdata->vibra) {
-			cell->platform_data = pdata->vibra;
-			cell->pdata_size = sizeof(*pdata->vibra);
-		}
 		children++;
 	}
 
-	/*
-	 * Enable the GPO driver in the following cases:
-	 * DT booted kernel or legacy boot with valid gpo platform_data
-	 */
-	if (!pdata || (pdata && pdata->gpo)) {
-		cell = &twl6040->cells[children];
-		cell->name = "twl6040-gpo";
-
-		if (pdata) {
-			cell->platform_data = pdata->gpo;
-			cell->pdata_size = sizeof(*pdata->gpo);
-		}
-		children++;
-	}
+	/* GPO support */
+	cell = &twl6040->cells[children];
+	cell->name = "twl6040-gpo";
+	children++;
 
 	ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
 			      NULL, 0, NULL);
@@ -690,7 +656,7 @@ gpio_err:
 	regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
 regulator_get_err:
 	i2c_set_clientdata(client, NULL);
-err:
+
 	return ret;
 }
 
diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c
index e9031fa..ebb20ed 100644
--- a/drivers/mfd/ucb1400_core.c
+++ b/drivers/mfd/ucb1400_core.c
@@ -52,7 +52,7 @@ static int ucb1400_core_probe(struct device *dev)
 	struct ucb1400_ts ucb_ts;
 	struct ucb1400_gpio ucb_gpio;
 	struct snd_ac97 *ac97;
-	struct ucb1400_pdata *pdata = dev->platform_data;
+	struct ucb1400_pdata *pdata = dev_get_platdata(dev);
 
 	memset(&ucb_ts, 0, sizeof(ucb_ts));
 	memset(&ucb_gpio, 0, sizeof(ucb_gpio));
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 70f02da..b7cf98f 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -669,9 +669,10 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
 	mutex_unlock(&ucb1x00_mutex);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ucb1x00_suspend(struct device *dev)
 {
-	struct ucb1x00_plat_data *pdata = dev->platform_data;
+	struct ucb1x00_plat_data *pdata = dev_get_platdata(dev);
 	struct ucb1x00 *ucb = dev_get_drvdata(dev);
 	struct ucb1x00_dev *udev;
 
@@ -703,7 +704,7 @@ static int ucb1x00_suspend(struct device *dev)
 
 static int ucb1x00_resume(struct device *dev)
 {
-	struct ucb1x00_plat_data *pdata = dev->platform_data;
+	struct ucb1x00_plat_data *pdata = dev_get_platdata(dev);
 	struct ucb1x00 *ucb = dev_get_drvdata(dev);
 	struct ucb1x00_dev *udev;
 
@@ -736,6 +737,7 @@ static int ucb1x00_resume(struct device *dev)
 	mutex_unlock(&ucb1x00_mutex);
 	return 0;
 }
+#endif
 
 static const struct dev_pm_ops ucb1x00_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index edbe6c1..1288e99 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -185,7 +185,7 @@ static int wl1273_core_remove(struct i2c_client *client)
 static int wl1273_core_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
-	struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
+	struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct wl1273_core *core;
 	struct mfd_cell *cell;
 	int children = 0;
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 2a79723..3113e39 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -468,12 +468,14 @@ static const struct reg_default wm5110_reg_default[] = {
 	{ 0x00000176, 0x0000 },    /* R374   - FLL1 Control 6 */
 	{ 0x00000177, 0x0281 },    /* R375   - FLL1 Loop Filter Test 1 */
 	{ 0x00000178, 0x0000 },    /* R376   - FLL1 NCO Test 0 */
+	{ 0x00000179, 0x0000 },    /* R376   - FLL1 Control 7 */
 	{ 0x00000181, 0x0000 },    /* R385   - FLL1 Synchroniser 1 */
 	{ 0x00000182, 0x0000 },    /* R386   - FLL1 Synchroniser 2 */
 	{ 0x00000183, 0x0000 },    /* R387   - FLL1 Synchroniser 3 */
 	{ 0x00000184, 0x0000 },    /* R388   - FLL1 Synchroniser 4 */
 	{ 0x00000185, 0x0000 },    /* R389   - FLL1 Synchroniser 5 */
 	{ 0x00000186, 0x0000 },    /* R390   - FLL1 Synchroniser 6 */
+	{ 0x00000187, 0x0001 },    /* R390   - FLL1 Synchroniser 7 */
 	{ 0x00000189, 0x0000 },    /* R393   - FLL1 Spread Spectrum */
 	{ 0x0000018A, 0x0004 },    /* R394   - FLL1 GPIO Clock */
 	{ 0x00000191, 0x0000 },    /* R401   - FLL2 Control 1 */
@@ -484,12 +486,14 @@ static const struct reg_default wm5110_reg_default[] = {
 	{ 0x00000196, 0x0000 },    /* R406   - FLL2 Control 6 */
 	{ 0x00000197, 0x0000 },    /* R407   - FLL2 Loop Filter Test 1 */
 	{ 0x00000198, 0x0000 },    /* R408   - FLL2 NCO Test 0 */
+	{ 0x00000199, 0x0000 },    /* R408   - FLL2 Control 7 */
 	{ 0x000001A1, 0x0000 },    /* R417   - FLL2 Synchroniser 1 */
 	{ 0x000001A2, 0x0000 },    /* R418   - FLL2 Synchroniser 2 */
 	{ 0x000001A3, 0x0000 },    /* R419   - FLL2 Synchroniser 3 */
 	{ 0x000001A4, 0x0000 },    /* R420   - FLL2 Synchroniser 4 */
 	{ 0x000001A5, 0x0000 },    /* R421   - FLL2 Synchroniser 5 */
 	{ 0x000001A6, 0x0000 },    /* R422   - FLL2 Synchroniser 6 */
+	{ 0x000001A7, 0x0001 },    /* R422   - FLL2 Synchroniser 7 */
 	{ 0x000001A9, 0x0000 },    /* R425   - FLL2 Spread Spectrum */
 	{ 0x000001AA, 0x0004 },    /* R426   - FLL2 GPIO Clock */
 	{ 0x00000200, 0x0006 },    /* R512   - Mic Charge Pump 1 */
@@ -503,6 +507,11 @@ static const struct reg_default wm5110_reg_default[] = {
 	{ 0x0000029C, 0x0000 },    /* R668   - Headphone Detect 2 */
 	{ 0x000002A3, 0x1102 },    /* R675   - Mic Detect 1 */
 	{ 0x000002A4, 0x009F },    /* R676   - Mic Detect 2 */
+	{ 0x000002A5, 0x0000 },    /* R677   - Mic Detect 3 */
+	{ 0x000002A6, 0x3737 },    /* R678   - Mic Detect Level 1 */
+	{ 0x000002A7, 0x372C },    /* R679   - Mic Detect Level 2 */
+	{ 0x000002A8, 0x1422 },    /* R680   - Mic Detect Level 3 */
+	{ 0x000002A9, 0x300A },    /* R681   - Mic Detect Level 4 */
 	{ 0x000002C3, 0x0000 },    /* R707   - Mic noise mix control 1 */
 	{ 0x000002D3, 0x0000 },    /* R723   - Jack detect analogue */
 	{ 0x00000300, 0x0000 },    /* R768   - Input Enables */
@@ -1392,6 +1401,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL1_CONTROL_4:
 	case ARIZONA_FLL1_CONTROL_5:
 	case ARIZONA_FLL1_CONTROL_6:
+	case ARIZONA_FLL1_CONTROL_7:
 	case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
 	case ARIZONA_FLL1_NCO_TEST_0:
 	case ARIZONA_FLL1_SYNCHRONISER_1:
@@ -1400,6 +1410,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL1_SYNCHRONISER_4:
 	case ARIZONA_FLL1_SYNCHRONISER_5:
 	case ARIZONA_FLL1_SYNCHRONISER_6:
+	case ARIZONA_FLL1_SYNCHRONISER_7:
 	case ARIZONA_FLL1_SPREAD_SPECTRUM:
 	case ARIZONA_FLL1_GPIO_CLOCK:
 	case ARIZONA_FLL2_CONTROL_1:
@@ -1408,6 +1419,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL2_CONTROL_4:
 	case ARIZONA_FLL2_CONTROL_5:
 	case ARIZONA_FLL2_CONTROL_6:
+	case ARIZONA_FLL2_CONTROL_7:
 	case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
 	case ARIZONA_FLL2_NCO_TEST_0:
 	case ARIZONA_FLL2_SYNCHRONISER_1:
@@ -1416,6 +1428,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL2_SYNCHRONISER_4:
 	case ARIZONA_FLL2_SYNCHRONISER_5:
 	case ARIZONA_FLL2_SYNCHRONISER_6:
+	case ARIZONA_FLL2_SYNCHRONISER_7:
 	case ARIZONA_FLL2_SPREAD_SPECTRUM:
 	case ARIZONA_FLL2_GPIO_CLOCK:
 	case ARIZONA_MIC_CHARGE_PUMP_1:
@@ -1430,6 +1443,10 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_MIC_DETECT_1:
 	case ARIZONA_MIC_DETECT_2:
 	case ARIZONA_MIC_DETECT_3:
+	case ARIZONA_MIC_DETECT_LEVEL_1:
+	case ARIZONA_MIC_DETECT_LEVEL_2:
+	case ARIZONA_MIC_DETECT_LEVEL_3:
+	case ARIZONA_MIC_DETECT_LEVEL_4:
 	case ARIZONA_MIC_NOISE_MIX_CONTROL_1:
 	case ARIZONA_JACK_DETECT_ANALOGUE:
 	case ARIZONA_INPUT_ENABLES:
@@ -2332,6 +2349,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_IRQ_PIN_STATUS:
 	case ARIZONA_AOD_IRQ1:
 	case ARIZONA_AOD_IRQ2:
+	case ARIZONA_FX_CTRL2:
 	case ARIZONA_ASRC_STATUS:
 	case ARIZONA_DSP_STATUS:
 	case ARIZONA_DSP1_CONTROL_1:
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 521340a..5c459f4 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1618,7 +1618,7 @@ EXPORT_SYMBOL_GPL(wm831x_regmap_config);
  */
 int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
 {
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	int rev, wm831x_num;
 	enum wm831x_parent parent;
 	int ret, i;
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index 804e56e..64e512e 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -571,7 +571,7 @@ static struct irq_domain_ops wm831x_irq_domain_ops = {
 
 int wm831x_irq_init(struct wm831x *wm831x, int irq)
 {
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct irq_domain *domain;
 	int i, ret, irq_base;
 
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index e7ed14f66..07de3cc 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -34,7 +34,6 @@ static int wm831x_spi_probe(struct spi_device *spi)
 	if (wm831x == NULL)
 		return -ENOMEM;
 
-	spi->bits_per_word = 16;
 	spi->mode = SPI_MODE_0;
 
 	spi_set_drvdata(spi, wm831x);
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 2e57101..f919def 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -27,6 +27,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct wm8350 *wm8350;
+	struct wm8350_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	int ret = 0;
 
 	wm8350 = devm_kzalloc(&i2c->dev, sizeof(struct wm8350), GFP_KERNEL);
@@ -44,7 +45,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
 	i2c_set_clientdata(i2c, wm8350);
 	wm8350->dev = &i2c->dev;
 
-	return wm8350_device_init(wm8350, i2c->irq, i2c->dev.platform_data);
+	return wm8350_device_init(wm8350, i2c->irq, pdata);
 }
 
 static int wm8350_i2c_remove(struct i2c_client *i2c)
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 639ca35..d66d256 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -178,7 +178,7 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
 	wm8400->dev = &i2c->dev;
 	i2c_set_clientdata(i2c, wm8400);
 
-	ret = wm8400_init(wm8400, i2c->dev.platform_data);
+	ret = wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
 	if (ret != 0)
 		goto err;
 
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 781115e..e1c283e 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -201,35 +201,7 @@ static int wm8994_suspend(struct device *dev)
 	int ret;
 
 	/* Don't actually go through with the suspend if the CODEC is
-	 * still active (eg, for audio passthrough from CP. */
-	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
-	if (ret < 0) {
-		dev_err(dev, "Failed to read power status: %d\n", ret);
-	} else if (ret & WM8994_VMID_SEL_MASK) {
-		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
-		return 0;
-	}
-
-	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
-	if (ret < 0) {
-		dev_err(dev, "Failed to read power status: %d\n", ret);
-	} else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
-			  WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
-			  WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
-		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
-		return 0;
-	}
-
-	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
-	if (ret < 0) {
-		dev_err(dev, "Failed to read power status: %d\n", ret);
-	} else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
-			  WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
-			  WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
-		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
-		return 0;
-	}
-
+	 * still active for accessory detect. */
 	switch (wm8994->type) {
 	case WM8958:
 	case WM1811:
@@ -245,20 +217,6 @@ static int wm8994_suspend(struct device *dev)
 		break;
 	}
 
-	switch (wm8994->type) {
-	case WM1811:
-		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
-		if (ret < 0) {
-			dev_err(dev, "Failed to read jackdet: %d\n", ret);
-		} else if (ret & WM1811_JACKDET_MODE_MASK) {
-			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
-			return 0;
-		}
-		break;
-	default:
-		break;
-	}
-
 	/* Disable LDO pulldowns while the device is suspended if we
 	 * don't know that something will be driving them. */
 	if (!wm8994->ldo_ena_always_driven)
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
index d3a184a..e74dedd 100644
--- a/drivers/mfd/wm8994-irq.c
+++ b/drivers/mfd/wm8994-irq.c
@@ -193,7 +193,7 @@ int wm8994_irq_init(struct wm8994 *wm8994)
 {
 	int ret;
 	unsigned long irqflags;
-	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev);
 
 	if (!wm8994->irq) {
 		dev_warn(wm8994->dev,
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index e068a76..5be80840 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 
 #include <linux/of.h>
-#include <linux/pinctrl/consumer.h>
 
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
@@ -137,13 +136,6 @@ static int ssc_probe(struct platform_device *pdev)
 	struct resource *regs;
 	struct ssc_device *ssc;
 	const struct atmel_ssc_platform_data *plat_dat;
-	struct pinctrl *pinctrl;
-
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		dev_err(&pdev->dev, "Failed to request pinctrl\n");
-		return PTR_ERR(pinctrl);
-	}
 
 	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
 	if (!ssc) {
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index f32550a..464419b 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -311,6 +311,7 @@ static ssize_t c2port_show_name(struct device *dev,
 
 	return sprintf(buf, "%s\n", c2dev->name);
 }
+static DEVICE_ATTR(name, 0444, c2port_show_name, NULL);
 
 static ssize_t c2port_show_flash_blocks_num(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -320,6 +321,7 @@ static ssize_t c2port_show_flash_blocks_num(struct device *dev,
 
 	return sprintf(buf, "%d\n", ops->blocks_num);
 }
+static DEVICE_ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL);
 
 static ssize_t c2port_show_flash_block_size(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -329,6 +331,7 @@ static ssize_t c2port_show_flash_block_size(struct device *dev,
 
 	return sprintf(buf, "%d\n", ops->block_size);
 }
+static DEVICE_ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL);
 
 static ssize_t c2port_show_flash_size(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -338,18 +341,18 @@ static ssize_t c2port_show_flash_size(struct device *dev,
 
 	return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size);
 }
+static DEVICE_ATTR(flash_size, 0444, c2port_show_flash_size, NULL);
 
-static ssize_t c2port_show_access(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t access_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct c2port_device *c2dev = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", c2dev->access);
 }
 
-static ssize_t c2port_store_access(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
+static ssize_t access_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct c2port_device *c2dev = dev_get_drvdata(dev);
 	struct c2port_ops *ops = c2dev->ops;
@@ -375,6 +378,7 @@ static ssize_t c2port_store_access(struct device *dev,
 
 	return count;
 }
+static DEVICE_ATTR_RW(access);
 
 static ssize_t c2port_store_reset(struct device *dev,
 				struct device_attribute *attr,
@@ -395,6 +399,7 @@ static ssize_t c2port_store_reset(struct device *dev,
 
 	return count;
 }
+static DEVICE_ATTR(reset, 0200, NULL, c2port_store_reset);
 
 static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf)
 {
@@ -431,6 +436,7 @@ static ssize_t c2port_show_dev_id(struct device *dev,
 
 	return ret;
 }
+static DEVICE_ATTR(dev_id, 0444, c2port_show_dev_id, NULL);
 
 static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf)
 {
@@ -467,6 +473,7 @@ static ssize_t c2port_show_rev_id(struct device *dev,
 
 	return ret;
 }
+static DEVICE_ATTR(rev_id, 0444, c2port_show_rev_id, NULL);
 
 static ssize_t c2port_show_flash_access(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -536,6 +543,8 @@ static ssize_t c2port_store_flash_access(struct device *dev,
 
 	return count;
 }
+static DEVICE_ATTR(flash_access, 0644, c2port_show_flash_access,
+		   c2port_store_flash_access);
 
 static ssize_t __c2port_write_flash_erase(struct c2port_device *dev)
 {
@@ -616,6 +625,7 @@ static ssize_t c2port_store_flash_erase(struct device *dev,
 
 	return count;
 }
+static DEVICE_ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase);
 
 static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
 				char *buffer, loff_t offset, size_t count)
@@ -846,35 +856,40 @@ static ssize_t c2port_write_flash_data(struct file *filp, struct kobject *kobj,
 
 	return ret;
 }
+/* size is computed at run-time */
+static BIN_ATTR(flash_data, 0644, c2port_read_flash_data,
+		c2port_write_flash_data, 0);
 
 /*
  * Class attributes
  */
+static struct attribute *c2port_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_flash_blocks_num.attr,
+	&dev_attr_flash_block_size.attr,
+	&dev_attr_flash_size.attr,
+	&dev_attr_access.attr,
+	&dev_attr_reset.attr,
+	&dev_attr_dev_id.attr,
+	&dev_attr_rev_id.attr,
+	&dev_attr_flash_access.attr,
+	&dev_attr_flash_erase.attr,
+	NULL,
+};
 
-static struct device_attribute c2port_attrs[] = {
-	__ATTR(name, 0444, c2port_show_name, NULL),
-	__ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL),
-	__ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL),
-	__ATTR(flash_size, 0444, c2port_show_flash_size, NULL),
-	__ATTR(access, 0644, c2port_show_access, c2port_store_access),
-	__ATTR(reset, 0200, NULL, c2port_store_reset),
-	__ATTR(dev_id, 0444, c2port_show_dev_id, NULL),
-	__ATTR(rev_id, 0444, c2port_show_rev_id, NULL),
-
-	__ATTR(flash_access, 0644, c2port_show_flash_access,
-					c2port_store_flash_access),
-	__ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase),
-	__ATTR_NULL,
+static struct bin_attribute *c2port_bin_attrs[] = {
+	&bin_attr_flash_data,
+	NULL,
 };
 
-static struct bin_attribute c2port_bin_attrs = {
-	.attr	= {
-		.name	= "flash_data",
-		.mode	= 0644
-	},
-	.read	= c2port_read_flash_data,
-	.write	= c2port_write_flash_data,
-	/* .size is computed at run-time */
+static const struct attribute_group c2port_group = {
+	.attrs = c2port_attrs,
+	.bin_attrs = c2port_bin_attrs,
+};
+
+static const struct attribute_group *c2port_groups[] = {
+	&c2port_group,
+	NULL,
 };
 
 /*
@@ -907,6 +922,8 @@ struct c2port_device *c2port_device_register(char *name,
 		goto error_idr_alloc;
 	c2dev->id = ret;
 
+	bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
+
 	c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
 				   "c2port%d", c2dev->id);
 	if (unlikely(IS_ERR(c2dev->dev))) {
@@ -919,12 +936,6 @@ struct c2port_device *c2port_device_register(char *name,
 	c2dev->ops = ops;
 	mutex_init(&c2dev->mutex);
 
-	/* Create binary file */
-	c2port_bin_attrs.size = ops->blocks_num * ops->block_size;
-	ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs);
-	if (unlikely(ret))
-		goto error_device_create_bin_file;
-
 	/* By default C2 port access is off */
 	c2dev->access = c2dev->flash_access = 0;
 	ops->access(c2dev, 0);
@@ -937,9 +948,6 @@ struct c2port_device *c2port_device_register(char *name,
 
 	return c2dev;
 
-error_device_create_bin_file:
-	device_destroy(c2port_class, 0);
-
 error_device_create:
 	spin_lock_irq(&c2port_idr_lock);
 	idr_remove(&c2port_idr, c2dev->id);
@@ -959,7 +967,6 @@ void c2port_device_unregister(struct c2port_device *c2dev)
 
 	dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name);
 
-	device_remove_bin_file(c2dev->dev, &c2port_bin_attrs);
 	spin_lock_irq(&c2port_idr_lock);
 	idr_remove(&c2port_idr, c2dev->id);
 	spin_unlock_irq(&c2port_idr_lock);
@@ -984,7 +991,7 @@ static int __init c2port_init(void)
 		printk(KERN_ERR "c2port: failed to allocate class\n");
 		return PTR_ERR(c2port_class);
 	}
-	c2port_class->dev_attrs = c2port_attrs;
+	c2port_class->dev_groups = c2port_groups;
 
 	return 0;
 }
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 00e5fcac8..0e8df41 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -239,7 +239,7 @@ static void enclosure_component_release(struct device *dev)
 	put_device(dev->parent);
 }
 
-static const struct attribute_group *enclosure_groups[];
+static const struct attribute_group *enclosure_component_groups[];
 
 /**
  * enclosure_component_register - add a particular component to an enclosure
@@ -282,7 +282,7 @@ enclosure_component_register(struct enclosure_device *edev,
 		dev_set_name(cdev, "%u", number);
 
 	cdev->release = enclosure_component_release;
-	cdev->groups = enclosure_groups;
+	cdev->groups = enclosure_component_groups;
 
 	err = device_register(cdev);
 	if (err) {
@@ -365,25 +365,26 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
  * sysfs pieces below
  */
 
-static ssize_t enclosure_show_components(struct device *cdev,
-					 struct device_attribute *attr,
-					 char *buf)
+static ssize_t components_show(struct device *cdev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct enclosure_device *edev = to_enclosure_device(cdev);
 
 	return snprintf(buf, 40, "%d\n", edev->components);
 }
+static DEVICE_ATTR_RO(components);
 
-static struct device_attribute enclosure_attrs[] = {
-	__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
-	__ATTR_NULL
+static struct attribute *enclosure_class_attrs[] = {
+	&dev_attr_components.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(enclosure_class);
 
 static struct class enclosure_class = {
 	.name			= "enclosure",
 	.owner			= THIS_MODULE,
 	.dev_release		= enclosure_release,
-	.dev_attrs		= enclosure_attrs,
+	.dev_groups		= enclosure_class_groups,
 };
 
 static const char *const enclosure_status [] = {
@@ -536,15 +537,7 @@ static struct attribute *enclosure_component_attrs[] = {
 	&dev_attr_type.attr,
 	NULL
 };
-
-static struct attribute_group enclosure_group = {
-	.attrs = enclosure_component_attrs,
-};
-
-static const struct attribute_group *enclosure_groups[] = {
-	&enclosure_group,
-	NULL
-};
+ATTRIBUTE_GROUPS(enclosure_component);
 
 static int __init enclosure_init(void)
 {
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 08aad69..2fc0586 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/debugfs.h>
+#include <linux/vmalloc.h>
 
 #ifdef CONFIG_IDE
 #include <linux/ide.h>
@@ -50,6 +51,7 @@
 
 #define DEFAULT_COUNT 10
 #define REC_NUM_DEFAULT 10
+#define EXEC_SIZE 64
 
 enum cname {
 	CN_INVALID,
@@ -68,6 +70,7 @@ enum ctype {
 	CT_NONE,
 	CT_PANIC,
 	CT_BUG,
+	CT_WARNING,
 	CT_EXCEPTION,
 	CT_LOOP,
 	CT_OVERFLOW,
@@ -77,7 +80,12 @@ enum ctype {
 	CT_WRITE_AFTER_FREE,
 	CT_SOFTLOCKUP,
 	CT_HARDLOCKUP,
+	CT_SPINLOCKUP,
 	CT_HUNG_TASK,
+	CT_EXEC_DATA,
+	CT_EXEC_STACK,
+	CT_EXEC_KMALLOC,
+	CT_EXEC_VMALLOC,
 };
 
 static char* cp_name[] = {
@@ -95,6 +103,7 @@ static char* cp_name[] = {
 static char* cp_type[] = {
 	"PANIC",
 	"BUG",
+	"WARNING",
 	"EXCEPTION",
 	"LOOP",
 	"OVERFLOW",
@@ -104,7 +113,12 @@ static char* cp_type[] = {
 	"WRITE_AFTER_FREE",
 	"SOFTLOCKUP",
 	"HARDLOCKUP",
+	"SPINLOCKUP",
 	"HUNG_TASK",
+	"EXEC_DATA",
+	"EXEC_STACK",
+	"EXEC_KMALLOC",
+	"EXEC_VMALLOC",
 };
 
 static struct jprobe lkdtm;
@@ -121,6 +135,9 @@ static enum cname cpoint = CN_INVALID;
 static enum ctype cptype = CT_NONE;
 static int count = DEFAULT_COUNT;
 static DEFINE_SPINLOCK(count_lock);
+static DEFINE_SPINLOCK(lock_me_up);
+
+static u8 data_area[EXEC_SIZE];
 
 module_param(recur_count, int, 0644);
 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
@@ -275,6 +292,19 @@ static int recursive_loop(int a)
         	return recursive_loop(a);
 }
 
+static void do_nothing(void)
+{
+	return;
+}
+
+static void execute_location(void *dst)
+{
+	void (*func)(void) = dst;
+
+	memcpy(dst, do_nothing, EXEC_SIZE);
+	func();
+}
+
 static void lkdtm_do_action(enum ctype which)
 {
 	switch (which) {
@@ -284,6 +314,9 @@ static void lkdtm_do_action(enum ctype which)
 	case CT_BUG:
 		BUG();
 		break;
+	case CT_WARNING:
+		WARN_ON(1);
+		break;
 	case CT_EXCEPTION:
 		*((int *) 0) = 0;
 		break;
@@ -295,10 +328,10 @@ static void lkdtm_do_action(enum ctype which)
 		(void) recursive_loop(0);
 		break;
 	case CT_CORRUPT_STACK: {
-		volatile u32 data[8];
-		volatile u32 *p = data;
+		/* Make sure the compiler creates and uses an 8 char array. */
+		volatile char data[8];
 
-		p[12] = 0x12345678;
+		memset((void *)data, 0, 64);
 		break;
 	}
 	case CT_UNALIGNED_LOAD_STORE_WRITE: {
@@ -340,10 +373,34 @@ static void lkdtm_do_action(enum ctype which)
 		for (;;)
 			cpu_relax();
 		break;
+	case CT_SPINLOCKUP:
+		/* Must be called twice to trigger. */
+		spin_lock(&lock_me_up);
+		break;
 	case CT_HUNG_TASK:
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule();
 		break;
+	case CT_EXEC_DATA:
+		execute_location(data_area);
+		break;
+	case CT_EXEC_STACK: {
+		u8 stack_area[EXEC_SIZE];
+		execute_location(stack_area);
+		break;
+	}
+	case CT_EXEC_KMALLOC: {
+		u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL);
+		execute_location(kmalloc_area);
+		kfree(kmalloc_area);
+		break;
+	}
+	case CT_EXEC_VMALLOC: {
+		u32 *vmalloc_area = vmalloc(EXEC_SIZE);
+		execute_location(vmalloc_area);
+		vfree(vmalloc_area);
+		break;
+	}
 	case CT_NONE:
 	default:
 		break;
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 749452f..d0fdc13 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -418,15 +418,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 		struct file *file, poll_table *wait)
 {
 	unsigned int mask = 0;
-	mutex_unlock(&dev->device_lock);
+
 	poll_wait(file, &dev->iamthif_cl.wait, wait);
+
 	mutex_lock(&dev->device_lock);
-	if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
-		dev->iamthif_file_object == file) {
+	if (!mei_cl_is_connected(&dev->iamthif_cl)) {
+
+		mask = POLLERR;
+
+	} else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
+		   dev->iamthif_file_object == file) {
+
 		mask |= (POLLIN | POLLRDNORM);
 		dev_dbg(&dev->pdev->dev, "run next amthif cb\n");
 		mei_amthif_run_next_cmd(dev);
 	}
+	mutex_unlock(&dev->device_lock);
+
 	return mask;
 }
 
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 9ecd49a..a150a42 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -47,7 +47,7 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
 	id = driver->id_table;
 
 	while (id->name[0]) {
-		if (!strcmp(dev_name(dev), id->name))
+		if (!strncmp(dev_name(dev), id->name, sizeof(id->name)))
 			return 1;
 
 		id++;
@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev)
 
 	dev_dbg(dev, "Device probe\n");
 
-	strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE);
+	strncpy(id.name, dev_name(dev), sizeof(id.name));
 
 	return driver->probe(device, &id);
 }
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 21d3f5a..e0684b4 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -635,10 +635,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 
 	dev = cl->dev;
 
-	if (cl->state != MEI_FILE_CONNECTED)
-		return -ENODEV;
-
-	if (dev->dev_state != MEI_DEV_ENABLED)
+	if (!mei_cl_is_connected(cl))
 		return -ENODEV;
 
 	if (cl->read_cb) {
@@ -892,18 +889,22 @@ void mei_cl_all_disconnect(struct mei_device *dev)
 
 
 /**
- * mei_cl_all_read_wakeup  - wake up all readings so they can be interrupted
+ * mei_cl_all_wakeup  - wake up all readers and writers they can be interrupted
  *
  * @dev  - mei device
  */
-void mei_cl_all_read_wakeup(struct mei_device *dev)
+void mei_cl_all_wakeup(struct mei_device *dev)
 {
 	struct mei_cl *cl, *next;
 	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
 		if (waitqueue_active(&cl->rx_wait)) {
-			dev_dbg(&dev->pdev->dev, "Waking up client!\n");
+			dev_dbg(&dev->pdev->dev, "Waking up reading client!\n");
 			wake_up_interruptible(&cl->rx_wait);
 		}
+		if (waitqueue_active(&cl->tx_wait)) {
+			dev_dbg(&dev->pdev->dev, "Waking up writing client!\n");
+			wake_up_interruptible(&cl->tx_wait);
+		}
 	}
 }
 
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 26b157d..9eb031e 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -84,6 +84,13 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
 /*
  *  MEI input output function prototype
  */
+static inline bool mei_cl_is_connected(struct mei_cl *cl)
+{
+	return (cl->dev &&
+		cl->dev->dev_state == MEI_DEV_ENABLED &&
+		cl->state == MEI_FILE_CONNECTED);
+}
+
 bool mei_cl_is_other_connecting(struct mei_cl *cl);
 int mei_cl_disconnect(struct mei_cl *cl);
 int mei_cl_connect(struct mei_cl *cl, struct file *file);
@@ -99,7 +106,7 @@ void mei_host_client_init(struct work_struct *work);
 
 
 void mei_cl_all_disconnect(struct mei_device *dev);
-void mei_cl_all_read_wakeup(struct mei_device *dev);
+void mei_cl_all_wakeup(struct mei_device *dev);
 void mei_cl_all_write_clear(struct mei_device *dev);
 
 #endif /* _MEI_CLIENT_H_ */
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index e6f16f8..92c7311 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -154,8 +154,14 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		    dev->dev_state != MEI_DEV_POWER_DOWN)
 			dev->dev_state = MEI_DEV_RESETTING;
 
+		/* remove all waiting requests */
+		mei_cl_all_write_clear(dev);
+
 		mei_cl_all_disconnect(dev);
 
+		/* wake up all readings so they can be interrupted */
+		mei_cl_all_wakeup(dev);
+
 		/* remove entry if already in list */
 		dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
 		mei_cl_unlink(&dev->wd_cl);
@@ -196,11 +202,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 
 	mei_hbm_start_req(dev);
 
-	/* wake up all readings so they can be interrupted */
-	mei_cl_all_read_wakeup(dev);
-
-	/* remove all waiting requests */
-	mei_cl_all_write_clear(dev);
 }
 EXPORT_SYMBOL_GPL(mei_reset);
 
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 5e11b5b..173ff09 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -625,24 +625,32 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 	unsigned int mask = 0;
 
 	if (WARN_ON(!cl || !cl->dev))
-		return mask;
+		return POLLERR;
 
 	dev = cl->dev;
 
 	mutex_lock(&dev->device_lock);
 
-	if (dev->dev_state != MEI_DEV_ENABLED)
-		goto out;
-
-
-	if (cl == &dev->iamthif_cl) {
-		mask = mei_amthif_poll(dev, file, wait);
+	if (!mei_cl_is_connected(cl)) {
+		mask = POLLERR;
 		goto out;
 	}
 
 	mutex_unlock(&dev->device_lock);
+
+
+	if (cl == &dev->iamthif_cl)
+		return mei_amthif_poll(dev, file, wait);
+
 	poll_wait(file, &cl->tx_wait, wait);
+
 	mutex_lock(&dev->device_lock);
+
+	if (!mei_cl_is_connected(cl)) {
+		mask = POLLERR;
+		goto out;
+	}
+
 	if (MEI_WRITE_COMPLETE == cl->writing_state)
 		mask |= (POLLIN | POLLRDNORM);
 
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index d87cc91..afe66571 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -68,7 +68,8 @@ static int sram_probe(struct platform_device *pdev)
 	ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base,
 				res->start, size, -1);
 	if (ret < 0) {
-		gen_pool_destroy(sram->pool);
+		if (sram->clk)
+			clk_disable_unprepare(sram->clk);
 		return ret;
 	}
 
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 0a14280..8e64eb1 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -343,7 +343,7 @@ void st_int_recv(void *disc_data,
 			/* Unknow packet? */
 		default:
 			type = *ptr;
-			if (st_gdata->list[type] == NULL) {
+			if (type >= ST_MAX_CHANNELS || st_gdata->list[type] == NULL) {
 				pr_err("chip/interface misbehavior dropping"
 					" frame starting with 0x%02x", type);
 				goto done;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 49a5bca..5d08855 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1313,7 +1313,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
 
 	supply = devm_regulator_get(dev, "vmmc");
 	mmc->supply.vmmc = supply;
-	mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc");
+	mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
 
 	if (IS_ERR(supply))
 		return PTR_ERR(supply);
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index ee5f167..5424073 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2231,7 +2231,7 @@ int dw_mci_probe(struct dw_mci *host)
 		}
 	}
 
-	host->vmmc = devm_regulator_get(host->dev, "vmmc");
+	host->vmmc = devm_regulator_get_optional(host->dev, "vmmc");
 	if (IS_ERR(host->vmmc)) {
 		ret = PTR_ERR(host->vmmc);
 		if (ret == -EPROBE_DEFER)
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 2c5a91b..1956a3d 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -83,7 +83,7 @@ struct pxamci_host {
 static inline void pxamci_init_ocr(struct pxamci_host *host)
 {
 #ifdef CONFIG_REGULATOR
-	host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
+	host->vcc = regulator_get_optional(mmc_dev(host->mmc), "vmmc");
 
 	if (IS_ERR(host->vcc))
 		host->vcc = NULL;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a78bd4f..dd2c083 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2966,7 +2966,7 @@ int sdhci_add_host(struct sdhci_host *host)
 		mmc->caps |= MMC_CAP_NEEDS_POLL;
 
 	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
-	host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
+	host->vqmmc = regulator_get_optional(mmc_dev(mmc), "vqmmc");
 	if (IS_ERR_OR_NULL(host->vqmmc)) {
 		if (PTR_ERR(host->vqmmc) < 0) {
 			pr_info("%s: no vqmmc regulator found\n",
@@ -3042,7 +3042,7 @@ int sdhci_add_host(struct sdhci_host *host)
 
 	ocr_avail = 0;
 
-	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+	host->vmmc = regulator_get_optional(mmc_dev(mmc), "vmmc");
 	if (IS_ERR_OR_NULL(host->vmmc)) {
 		if (PTR_ERR(host->vmmc) < 0) {
 			pr_info("%s: no vmmc regulator found\n",
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index b72edb7..718843c 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -795,9 +795,13 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd)
 	 * omap_hsmmc.c driver does.
 	 */
 	if (!IS_ERR(mmc->supply.vqmmc) && !ret) {
-		regulator_enable(mmc->supply.vqmmc);
+		ret = regulator_enable(mmc->supply.vqmmc);
 		udelay(200);
 	}
+
+	if (ret < 0)
+		dev_dbg(&host->pdev->dev, "Regulators failed to power up: %d\n",
+			ret);
 }
 
 static void tmio_mmc_power_off(struct tmio_mmc_host *host)
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index 6eeb84c..5c81390 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -4,7 +4,7 @@
  * Copyright © 2006-2008  Florian Fainelli <florian@openwrt.org>
  *			  Mike Albon <malbon@openwrt.org>
  * Copyright © 2009-2010  Daniel Dickinson <openwrt@cshore.neomailbox.net>
- * Copyright © 2011-2012  Jonas Gorski <jonas.gorski@gmail.com>
+ * Copyright © 2011-2013  Jonas Gorski <jonas.gorski@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,17 +27,19 @@
 #include <linux/crc32.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
 #include <asm/mach-bcm63xx/bcm963xx_tag.h>
 #include <asm/mach-bcm63xx/board_bcm963xx.h>
 
 #define BCM63XX_EXTENDED_SIZE	0xBFC00000	/* Extended flash address */
 
-#define BCM63XX_CFE_BLOCK_SIZE	0x10000		/* always at least 64KiB */
+#define BCM63XX_CFE_BLOCK_SIZE	SZ_64K		/* always at least 64KiB */
 
 #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
 
@@ -90,7 +92,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
 			      BCM63XX_CFE_BLOCK_SIZE);
 
 	cfelen = cfe_erasesize;
-	nvramlen = cfe_erasesize;
+	nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
+	nvramlen = roundup(nvramlen, cfe_erasesize);
 
 	/* Allocate memory for buffer */
 	buf = vmalloc(sizeof(struct bcm_tag));
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index fff665d..89b9d68 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -1571,8 +1571,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 	xip_enable(map, chip, adr);
 	/* FIXME - should have reset delay before continuing */
 
-	printk(KERN_WARNING "MTD %s(): software timeout\n",
-	       __func__ );
+	printk(KERN_WARNING "MTD %s(): software timeout, address:0x%.8lx.\n",
+	       __func__, adr);
 
 	ret = -EIO;
  op_done:
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index 74dbb6b..ffb36ba 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -211,9 +211,7 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
 
 	probe_function = __symbol_get(probename);
 	if (!probe_function) {
-		char modname[sizeof("cfi_cmdset_%4.4X")];
-		sprintf(modname, "cfi_cmdset_%4.4X", type);
-		request_module(modname);
+		request_module("cfi_cmdset_%4.4X", type);
 		probe_function = __symbol_get(probename);
 	}
 
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index c443f52..7c0b27d 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -120,7 +120,7 @@
 #define PM49FL008	0x006A
 
 /* Sharp */
-#define LH28F640BF	0x00b0
+#define LH28F640BF	0x00B0
 
 /* ST - www.st.com */
 #define M29F800AB	0x0058
@@ -1299,13 +1299,14 @@ static const struct amd_flash_info jedec_table[] = {
 		.mfr_id		= CFI_MFR_SHARP,
 		.dev_id		= LH28F640BF,
 		.name		= "LH28F640BF",
-		.devtypes	= CFI_DEVICETYPE_X8,
+		.devtypes	= CFI_DEVICETYPE_X16,
 		.uaddr		= MTD_UADDR_UNNECESSARY,
-		.dev_size	= SIZE_4MiB,
-		.cmd_set	= P_ID_INTEL_STD,
-		.nr_regions	= 1,
+		.dev_size	= SIZE_8MiB,
+		.cmd_set	= P_ID_INTEL_EXT,
+		.nr_regions	= 2,
 		.regions	= {
-			ERASEINFO(0x40000,16),
+			ERASEINFO(0x10000, 127),
+			ERASEINFO(0x02000, 8),
 		}
 	}, {
 		.mfr_id		= CFI_MFR_SST,
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 2a4d55e..74ab4b7 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -224,59 +224,4 @@ config BCH_CONST_T
 	default 4
 endif
 
-config MTD_DOCPROBE
-	tristate
-	select MTD_DOCECC
-
-config MTD_DOCECC
-	tristate
-
-config MTD_DOCPROBE_ADVANCED
-	bool "Advanced detection options for DiskOnChip"
-	depends on MTD_DOCPROBE
-	help
-	  This option allows you to specify nonstandard address at which to
-	  probe for a DiskOnChip, or to change the detection options.  You
-	  are unlikely to need any of this unless you are using LinuxBIOS.
-	  Say 'N'.
-
-config MTD_DOCPROBE_ADDRESS
-	hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
-	depends on MTD_DOCPROBE
-	default "0x0"
-	---help---
-	  By default, the probe for DiskOnChip devices will look for a
-	  DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
-	  This option allows you to specify a single address at which to probe
-	  for the device, which is useful if you have other devices in that
-	  range which get upset when they are probed.
-
-	  (Note that on PowerPC, the normal probe will only check at
-	  0xE4000000.)
-
-	  Normally, you should leave this set to zero, to allow the probe at
-	  the normal addresses.
-
-config MTD_DOCPROBE_HIGH
-	bool "Probe high addresses"
-	depends on MTD_DOCPROBE_ADVANCED
-	help
-	  By default, the probe for DiskOnChip devices will look for a
-	  DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
-	  This option changes to make it probe between 0xFFFC8000 and
-	  0xFFFEE000.  Unless you are using LinuxBIOS, this is unlikely to be
-	  useful to you.  Say 'N'.
-
-config MTD_DOCPROBE_55AA
-	bool "Probe for 0x55 0xAA BIOS Extension Signature"
-	depends on MTD_DOCPROBE_ADVANCED
-	help
-	  Check for the 0x55 0xAA signature of a DiskOnChip, and do not
-	  continue with probing if it is absent.  The signature will always be
-	  present for a DiskOnChip 2000 or a normal DiskOnChip Millennium.
-	  Only if you have overwritten the first block of a DiskOnChip
-	  Millennium will it be absent.  Enable this option if you are using
-	  LinuxBIOS or if you need to recover a DiskOnChip Millennium on which
-	  you have managed to wipe the first block.
-
 endmenu
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
index 18e7761..2060856 100644
--- a/drivers/mtd/devices/bcm47xxsflash.c
+++ b/drivers/mtd/devices/bcm47xxsflash.c
@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
@@ -12,6 +13,57 @@ MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
 
 static const char * const probes[] = { "bcm47xxpart", NULL };
 
+/**************************************************
+ * Various helpers
+ **************************************************/
+
+static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
+{
+	int i;
+
+	b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
+	for (i = 0; i < 1000; i++) {
+		if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
+		      BCMA_CC_FLASHCTL_BUSY))
+			return;
+		cpu_relax();
+	}
+	pr_err("Control command failed (timeout)!\n");
+}
+
+static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
+{
+	unsigned long deadline = jiffies + timeout;
+
+	do {
+		switch (b47s->type) {
+		case BCM47XXSFLASH_TYPE_ST:
+			bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
+			if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
+			      SR_ST_WIP))
+				return 0;
+			break;
+		case BCM47XXSFLASH_TYPE_ATMEL:
+			bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
+			if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
+			    SR_AT_READY)
+				return 0;
+			break;
+		}
+
+		cpu_relax();
+		udelay(1);
+	} while (!time_after_eq(jiffies, deadline));
+
+	pr_err("Timeout waiting for flash to be ready!\n");
+
+	return -EBUSY;
+}
+
+/**************************************************
+ * MTD ops
+ **************************************************/
+
 static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 			      size_t *retlen, u_char *buf)
 {
@@ -48,6 +100,17 @@ static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s)
  * BCMA
  **************************************************/
 
+static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset)
+{
+	return bcma_cc_read32(b47s->bcma_cc, offset);
+}
+
+static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
+					u32 value)
+{
+	bcma_cc_write32(b47s->bcma_cc, offset, value);
+}
+
 static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
 {
 	struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
@@ -62,6 +125,8 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
 	sflash->priv = b47s;
 
 	b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
+	b47s->cc_read = bcm47xxsflash_bcma_cc_read;
+	b47s->cc_write = bcm47xxsflash_bcma_cc_write;
 
 	switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
 	case BCMA_CC_FLASHT_STSER:
@@ -84,6 +149,9 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
 		goto err_dev_reg;
 	}
 
+	if (bcm47xxsflash_poll(b47s, HZ / 10))
+		pr_warn("Serial flash busy\n");
+
 	return 0;
 
 err_dev_reg:
diff --git a/drivers/mtd/devices/bcm47xxsflash.h b/drivers/mtd/devices/bcm47xxsflash.h
index f22f8c4..fe93daf 100644
--- a/drivers/mtd/devices/bcm47xxsflash.h
+++ b/drivers/mtd/devices/bcm47xxsflash.h
@@ -60,6 +60,8 @@ enum bcm47xxsflash_type {
 
 struct bcm47xxsflash {
 	struct bcma_drv_cc *bcma_cc;
+	int (*cc_read)(struct bcm47xxsflash *b47s, u16 offset);
+	void (*cc_write)(struct bcm47xxsflash *b47s, u16 offset, u32 value);
 
 	enum bcm47xxsflash_type type;
 
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index e081bfe..5cb4c04 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -6,6 +6,9 @@
  *
  * Licence: GPL
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
@@ -18,10 +21,6 @@
 #include <linux/mount.h>
 #include <linux/slab.h>
 
-#define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args)
-#define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args)
-
-
 /* Info for the block device */
 struct block2mtd_dev {
 	struct list_head list;
@@ -84,7 +83,7 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 	err = _block2mtd_erase(dev, from, len);
 	mutex_unlock(&dev->write_mutex);
 	if (err) {
-		ERROR("erase failed err = %d", err);
+		pr_err("erase failed err = %d\n", err);
 		instr->state = MTD_ERASE_FAILED;
 	} else
 		instr->state = MTD_ERASE_DONE;
@@ -239,13 +238,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 #endif
 
 	if (IS_ERR(bdev)) {
-		ERROR("error: cannot open device %s", devname);
+		pr_err("error: cannot open device %s\n", devname);
 		goto devinit_err;
 	}
 	dev->blkdev = bdev;
 
 	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
-		ERROR("attempting to use an MTD device as a block device");
+		pr_err("attempting to use an MTD device as a block device\n");
 		goto devinit_err;
 	}
 
@@ -277,9 +276,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 		goto devinit_err;
 	}
 	list_add(&dev->list, &blkmtd_device_list);
-	INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
-			dev->mtd.name + strlen("block2mtd: "),
-			dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
+		dev->mtd.index,
+		dev->mtd.name + strlen("block2mtd: "),
+		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 	return dev;
 
 devinit_err:
@@ -339,17 +339,11 @@ static inline void kill_final_newline(char *str)
 }
 
 
-#define parse_err(fmt, args...) do {	\
-	ERROR(fmt, ## args);		\
-	return 0;			\
-} while (0)
-
 #ifndef MODULE
 static int block2mtd_init_called = 0;
 static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
 #endif
 
-
 static int block2mtd_setup2(const char *val)
 {
 	char buf[80 + 12]; /* 80 for device, 12 for erase size */
@@ -359,8 +353,10 @@ static int block2mtd_setup2(const char *val)
 	size_t erase_size = PAGE_SIZE;
 	int i, ret;
 
-	if (strnlen(val, sizeof(buf)) >= sizeof(buf))
-		parse_err("parameter too long");
+	if (strnlen(val, sizeof(buf)) >= sizeof(buf)) {
+		pr_err("parameter too long\n");
+		return 0;
+	}
 
 	strcpy(str, val);
 	kill_final_newline(str);
@@ -368,20 +364,27 @@ static int block2mtd_setup2(const char *val)
 	for (i = 0; i < 2; i++)
 		token[i] = strsep(&str, ",");
 
-	if (str)
-		parse_err("too many arguments");
+	if (str) {
+		pr_err("too many arguments\n");
+		return 0;
+	}
 
-	if (!token[0])
-		parse_err("no argument");
+	if (!token[0]) {
+		pr_err("no argument\n");
+		return 0;
+	}
 
 	name = token[0];
-	if (strlen(name) + 1 > 80)
-		parse_err("device name too long");
+	if (strlen(name) + 1 > 80) {
+		pr_err("device name too long\n");
+		return 0;
+	}
 
 	if (token[1]) {
 		ret = parse_num(&erase_size, token[1]);
 		if (ret) {
-			parse_err("illegal erase size");
+			pr_err("illegal erase size\n");
+			return 0;
 		}
 	}
 
@@ -444,8 +447,9 @@ static void block2mtd_exit(void)
 		struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
 		block2mtd_sync(&dev->mtd);
 		mtd_device_unregister(&dev->mtd);
-		INFO("mtd%d: [%s] removed", dev->mtd.index,
-				dev->mtd.name + strlen("block2mtd: "));
+		pr_info("mtd%d: [%s] removed\n",
+			dev->mtd.index,
+			dev->mtd.name + strlen("block2mtd: "));
 		list_del(&dev->list);
 		block2mtd_free_device(dev);
 	}
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
index dccef9f..4f683d2 100644
--- a/drivers/mtd/devices/elm.c
+++ b/drivers/mtd/devices/elm.c
@@ -20,14 +20,21 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/sched.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_data/elm.h>
 
+#define ELM_SYSCONFIG			0x010
 #define ELM_IRQSTATUS			0x018
 #define ELM_IRQENABLE			0x01c
 #define ELM_LOCATION_CONFIG		0x020
 #define ELM_PAGE_CTRL			0x080
 #define ELM_SYNDROME_FRAGMENT_0		0x400
+#define ELM_SYNDROME_FRAGMENT_1		0x404
+#define ELM_SYNDROME_FRAGMENT_2		0x408
+#define ELM_SYNDROME_FRAGMENT_3		0x40c
+#define ELM_SYNDROME_FRAGMENT_4		0x410
+#define ELM_SYNDROME_FRAGMENT_5		0x414
 #define ELM_SYNDROME_FRAGMENT_6		0x418
 #define ELM_LOCATION_STATUS		0x800
 #define ELM_ERROR_LOCATION_0		0x880
@@ -56,12 +63,27 @@
 #define SYNDROME_FRAGMENT_REG_SIZE	0x40
 #define ERROR_LOCATION_SIZE		0x100
 
+struct elm_registers {
+	u32 elm_irqenable;
+	u32 elm_sysconfig;
+	u32 elm_location_config;
+	u32 elm_page_ctrl;
+	u32 elm_syndrome_fragment_6[ERROR_VECTOR_MAX];
+	u32 elm_syndrome_fragment_5[ERROR_VECTOR_MAX];
+	u32 elm_syndrome_fragment_4[ERROR_VECTOR_MAX];
+	u32 elm_syndrome_fragment_3[ERROR_VECTOR_MAX];
+	u32 elm_syndrome_fragment_2[ERROR_VECTOR_MAX];
+	u32 elm_syndrome_fragment_1[ERROR_VECTOR_MAX];
+	u32 elm_syndrome_fragment_0[ERROR_VECTOR_MAX];
+};
+
 struct elm_info {
 	struct device *dev;
 	void __iomem *elm_base;
 	struct completion elm_completion;
 	struct list_head list;
 	enum bch_ecc bch_type;
+	struct elm_registers elm_regs;
 };
 
 static LIST_HEAD(elm_devices);
@@ -351,9 +373,9 @@ static int elm_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	info->elm_base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!info->elm_base)
-		return -EADDRNOTAVAIL;
+	info->elm_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(info->elm_base))
+		return PTR_ERR(info->elm_base);
 
 	ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0,
 			pdev->name, info);
@@ -381,10 +403,103 @@ static int elm_remove(struct platform_device *pdev)
 {
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
+/**
+ * elm_context_save
+ * saves ELM configurations to preserve them across Hardware powered-down
+ */
+static int elm_context_save(struct elm_info *info)
+{
+	struct elm_registers *regs = &info->elm_regs;
+	enum bch_ecc bch_type = info->bch_type;
+	u32 offset = 0, i;
+
+	regs->elm_irqenable       = elm_read_reg(info, ELM_IRQENABLE);
+	regs->elm_sysconfig       = elm_read_reg(info, ELM_SYSCONFIG);
+	regs->elm_location_config = elm_read_reg(info, ELM_LOCATION_CONFIG);
+	regs->elm_page_ctrl       = elm_read_reg(info, ELM_PAGE_CTRL);
+	for (i = 0; i < ERROR_VECTOR_MAX; i++) {
+		offset = i * SYNDROME_FRAGMENT_REG_SIZE;
+		switch (bch_type) {
+		case BCH8_ECC:
+			regs->elm_syndrome_fragment_3[i] = elm_read_reg(info,
+					ELM_SYNDROME_FRAGMENT_3 + offset);
+			regs->elm_syndrome_fragment_2[i] = elm_read_reg(info,
+					ELM_SYNDROME_FRAGMENT_2 + offset);
+		case BCH4_ECC:
+			regs->elm_syndrome_fragment_1[i] = elm_read_reg(info,
+					ELM_SYNDROME_FRAGMENT_1 + offset);
+			regs->elm_syndrome_fragment_0[i] = elm_read_reg(info,
+					ELM_SYNDROME_FRAGMENT_0 + offset);
+		default:
+			return -EINVAL;
+		}
+		/* ELM SYNDROME_VALID bit in SYNDROME_FRAGMENT_6[] needs
+		 * to be saved for all BCH schemes*/
+		regs->elm_syndrome_fragment_6[i] = elm_read_reg(info,
+					ELM_SYNDROME_FRAGMENT_6 + offset);
+	}
+	return 0;
+}
+
+/**
+ * elm_context_restore
+ * writes configurations saved duing power-down back into ELM registers
+ */
+static int elm_context_restore(struct elm_info *info)
+{
+	struct elm_registers *regs = &info->elm_regs;
+	enum bch_ecc bch_type = info->bch_type;
+	u32 offset = 0, i;
+
+	elm_write_reg(info, ELM_IRQENABLE,	 regs->elm_irqenable);
+	elm_write_reg(info, ELM_SYSCONFIG,	 regs->elm_sysconfig);
+	elm_write_reg(info, ELM_LOCATION_CONFIG, regs->elm_location_config);
+	elm_write_reg(info, ELM_PAGE_CTRL,	 regs->elm_page_ctrl);
+	for (i = 0; i < ERROR_VECTOR_MAX; i++) {
+		offset = i * SYNDROME_FRAGMENT_REG_SIZE;
+		switch (bch_type) {
+		case BCH8_ECC:
+			elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset,
+					regs->elm_syndrome_fragment_3[i]);
+			elm_write_reg(info, ELM_SYNDROME_FRAGMENT_2 + offset,
+					regs->elm_syndrome_fragment_2[i]);
+		case BCH4_ECC:
+			elm_write_reg(info, ELM_SYNDROME_FRAGMENT_1 + offset,
+					regs->elm_syndrome_fragment_1[i]);
+			elm_write_reg(info, ELM_SYNDROME_FRAGMENT_0 + offset,
+					regs->elm_syndrome_fragment_0[i]);
+		default:
+			return -EINVAL;
+		}
+		/* ELM_SYNDROME_VALID bit to be set in last to trigger FSM */
+		elm_write_reg(info, ELM_SYNDROME_FRAGMENT_6 + offset,
+					regs->elm_syndrome_fragment_6[i] &
+							 ELM_SYNDROME_VALID);
+	}
+	return 0;
+}
+
+static int elm_suspend(struct device *dev)
+{
+	struct elm_info *info = dev_get_drvdata(dev);
+	elm_context_save(info);
+	pm_runtime_put_sync(dev);
+	return 0;
+}
+
+static int elm_resume(struct device *dev)
+{
+	struct elm_info *info = dev_get_drvdata(dev);
+	pm_runtime_get_sync(dev);
+	elm_context_restore(info);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(elm_pm_ops, elm_suspend, elm_resume);
+
 #ifdef CONFIG_OF
 static const struct of_device_id elm_of_match[] = {
 	{ .compatible = "ti,am3352-elm" },
@@ -398,6 +513,7 @@ static struct platform_driver elm_driver = {
 		.name	= "elm",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(elm_of_match),
+		.pm	= &elm_pm_ops,
 	},
 	.probe	= elm_probe,
 	.remove	= elm_remove,
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 2f3d2a5..b5190c4 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -48,12 +48,18 @@
 #define	OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
 #define	OPCODE_RDID		0x9f	/* Read JEDEC ID */
 
+/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
+#define	OPCODE_NORM_READ_4B	0x13	/* Read data bytes (low frequency) */
+#define	OPCODE_FAST_READ_4B	0x0c	/* Read data bytes (high frequency) */
+#define	OPCODE_PP_4B		0x12	/* Page program (up to 256 bytes) */
+#define	OPCODE_SE_4B		0xdc	/* Sector erase (usually 64KiB) */
+
 /* Used for SST flashes only. */
 #define	OPCODE_BP		0x02	/* Byte program */
 #define	OPCODE_WRDI		0x04	/* Write disable */
 #define	OPCODE_AAI_WP		0xad	/* Auto address increment word program */
 
-/* Used for Macronix flashes only. */
+/* Used for Macronix and Winbond flashes. */
 #define	OPCODE_EN4B		0xb7	/* Enter 4-byte mode */
 #define	OPCODE_EX4B		0xe9	/* Exit 4-byte mode */
 
@@ -84,6 +90,8 @@ struct m25p {
 	u16			page_size;
 	u16			addr_width;
 	u8			erase_opcode;
+	u8			read_opcode;
+	u8			program_opcode;
 	u8			*command;
 	bool			fast_read;
 };
@@ -371,7 +379,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 	 */
 
 	/* Set up the write data buffer. */
-	opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ;
+	opcode = flash->read_opcode;
 	flash->command[0] = opcode;
 	m25p_addr2cmd(flash, from, flash->command);
 
@@ -422,7 +430,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
 	write_enable(flash);
 
 	/* Set up the opcode in the write buffer. */
-	flash->command[0] = OPCODE_PP;
+	flash->command[0] = flash->program_opcode;
 	m25p_addr2cmd(flash, to, flash->command);
 
 	page_offset = to & (flash->page_size - 1);
@@ -840,6 +848,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64, SECT_4K) },
 	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
 	{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
 	{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
 	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
@@ -920,7 +929,7 @@ static int m25p_probe(struct spi_device *spi)
 	 * a chip ID, try the JEDEC id commands; they'll work for most
 	 * newer chips, even if we don't recognize the particular chip.
 	 */
-	data = spi->dev.platform_data;
+	data = dev_get_platdata(&spi->dev);
 	if (data && data->type) {
 		const struct spi_device_id *plat_id;
 
@@ -972,7 +981,7 @@ static int m25p_probe(struct spi_device *spi)
 
 	flash->spi = spi;
 	mutex_init(&flash->lock);
-	dev_set_drvdata(&spi->dev, flash);
+	spi_set_drvdata(spi, flash);
 
 	/*
 	 * Atmel, SST and Intel/Numonyx serial flash tend to power
@@ -1037,15 +1046,32 @@ static int m25p_probe(struct spi_device *spi)
 	flash->fast_read = true;
 #endif
 
+	/* Default commands */
+	if (flash->fast_read)
+		flash->read_opcode = OPCODE_FAST_READ;
+	else
+		flash->read_opcode = OPCODE_NORM_READ;
+
+	flash->program_opcode = OPCODE_PP;
+
 	if (info->addr_width)
 		flash->addr_width = info->addr_width;
-	else {
+	else if (flash->mtd.size > 0x1000000) {
 		/* enable 4-byte addressing if the device exceeds 16MiB */
-		if (flash->mtd.size > 0x1000000) {
-			flash->addr_width = 4;
-			set_4byte(flash, info->jedec_id, 1);
+		flash->addr_width = 4;
+		if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) {
+			/* Dedicated 4-byte command set */
+			flash->read_opcode = flash->fast_read ?
+				OPCODE_FAST_READ_4B :
+				OPCODE_NORM_READ_4B;
+			flash->program_opcode = OPCODE_PP_4B;
+			/* No small sector erase for 4-byte command set */
+			flash->erase_opcode = OPCODE_SE_4B;
+			flash->mtd.erasesize = info->sector_size;
 		} else
-			flash->addr_width = 3;
+			set_4byte(flash, info->jedec_id, 1);
+	} else {
+		flash->addr_width = 3;
 	}
 
 	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
@@ -1080,7 +1106,7 @@ static int m25p_probe(struct spi_device *spi)
 
 static int m25p_remove(struct spi_device *spi)
 {
-	struct m25p	*flash = dev_get_drvdata(&spi->dev);
+	struct m25p	*flash = spi_get_drvdata(spi);
 	int		status;
 
 	/* Clean up MTD stuff. */
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 28779b6..0e8cbfe 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -622,7 +622,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
 	struct dataflash		*priv;
 	struct mtd_info			*device;
 	struct mtd_part_parser_data	ppdata;
-	struct flash_platform_data	*pdata = spi->dev.platform_data;
+	struct flash_platform_data	*pdata = dev_get_platdata(&spi->dev);
 	char				*otp_tag = "";
 	int				err = 0;
 
@@ -661,7 +661,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
 	dev_info(&spi->dev, "%s (%lld KBytes) pagesize %d bytes%s\n",
 			name, (long long)((device->size + 1023) >> 10),
 			pagesize, otp_tag);
-	dev_set_drvdata(&spi->dev, priv);
+	spi_set_drvdata(spi, priv);
 
 	ppdata.of_node = spi->dev.of_node;
 	err = mtd_device_parse_register(device, NULL, &ppdata,
@@ -671,7 +671,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
 	if (!err)
 		return 0;
 
-	dev_set_drvdata(&spi->dev, NULL);
+	spi_set_drvdata(spi, NULL);
 	kfree(priv);
 	return err;
 }
@@ -895,14 +895,14 @@ static int dataflash_probe(struct spi_device *spi)
 
 static int dataflash_remove(struct spi_device *spi)
 {
-	struct dataflash	*flash = dev_get_drvdata(&spi->dev);
+	struct dataflash	*flash = spi_get_drvdata(spi);
 	int			status;
 
 	pr_debug("%s: remove\n", dev_name(&spi->dev));
 
 	status = mtd_device_unregister(&flash->mtd);
 	if (status == 0) {
-		dev_set_drvdata(&spi->dev, NULL);
+		spi_set_drvdata(spi, NULL);
 		kfree(flash);
 	}
 	return status;
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
index 8a82b8b..092bb68 100644
--- a/drivers/mtd/devices/spear_smi.c
+++ b/drivers/mtd/devices/spear_smi.c
@@ -995,14 +995,12 @@ static int spear_smi_probe(struct platform_device *pdev)
 		ret = spear_smi_setup_banks(pdev, i, pdata->np[i]);
 		if (ret) {
 			dev_err(&dev->pdev->dev, "bank setup failed\n");
-			goto err_bank_setup;
+			goto err_irq;
 		}
 	}
 
 	return 0;
 
-err_bank_setup:
-	platform_set_drvdata(pdev, NULL);
 err_irq:
 	clk_disable_unprepare(dev->clk);
 err:
@@ -1040,12 +1038,11 @@ static int spear_smi_remove(struct platform_device *pdev)
 	}
 
 	clk_disable_unprepare(dev->clk);
-	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int spear_smi_suspend(struct device *dev)
 {
 	struct spear_smi *sdev = dev_get_drvdata(dev);
@@ -1068,9 +1065,9 @@ static int spear_smi_resume(struct device *dev)
 		spear_smi_hw_init(sdev);
 	return ret;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(spear_smi_pm_ops, spear_smi_suspend, spear_smi_resume);
-#endif
 
 #ifdef CONFIG_OF
 static const struct of_device_id spear_smi_id_table[] = {
@@ -1086,9 +1083,7 @@ static struct platform_driver spear_smi_driver = {
 		.bus = &platform_bus_type,
 		.owner = THIS_MODULE,
 		.of_match_table = of_match_ptr(spear_smi_id_table),
-#ifdef CONFIG_PM
 		.pm = &spear_smi_pm_ops,
-#endif
 	},
 	.probe = spear_smi_probe,
 	.remove = spear_smi_remove,
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 8091b01..a42f1f0 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -370,9 +370,9 @@ static int sst25l_probe(struct spi_device *spi)
 
 	flash->spi = spi;
 	mutex_init(&flash->lock);
-	dev_set_drvdata(&spi->dev, flash);
+	spi_set_drvdata(spi, flash);
 
-	data = spi->dev.platform_data;
+	data = dev_get_platdata(&spi->dev);
 	if (data && data->name)
 		flash->mtd.name = data->name;
 	else
@@ -404,7 +404,7 @@ static int sst25l_probe(struct spi_device *spi)
 					data ? data->nr_parts : 0);
 	if (ret) {
 		kfree(flash);
-		dev_set_drvdata(&spi->dev, NULL);
+		spi_set_drvdata(spi, NULL);
 		return -ENODEV;
 	}
 
@@ -413,7 +413,7 @@ static int sst25l_probe(struct spi_device *spi)
 
 static int sst25l_remove(struct spi_device *spi)
 {
-	struct sst25l_flash *flash = dev_get_drvdata(&spi->dev);
+	struct sst25l_flash *flash = spi_get_drvdata(spi);
 	int ret;
 
 	ret = mtd_device_unregister(&flash->mtd);
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 8b27ca0..310dc7c 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -157,24 +157,6 @@ config MTD_PXA2XX
 	help
 	  This provides a driver for the NOR flash attached to a PXA2xx chip.
 
-config MTD_OCTAGON
-	tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
-	depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
-	help
-	  This provides a 'mapping' driver which supports the way in which
-	  the flash chips are connected in the Octagon-5066 Single Board
-	  Computer. More information on the board is available at
-	  <http://www.octagonsystems.com/products/5066.aspx>.
-
-config MTD_VMAX
-	tristate "JEDEC Flash device mapped on Tempustech VMAX SBC301"
-	depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
-	help
-	  This provides a 'mapping' driver which supports the way in which
-	  the flash chips are connected in the Tempustech VMAX SBC301 Single
-	  Board Computer. More information on the board is available at
-	  <http://www.tempustech.com/>.
-
 config MTD_SCx200_DOCFLASH
 	tristate "Flash device mapped with DOCCS on NatSemi SCx200"
 	depends on SCx200 && MTD_CFI
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 9fdbd4b..141c91a 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_MTD_ICHXROM)	+= ichxrom.o
 obj-$(CONFIG_MTD_CK804XROM)	+= ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
-obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
 obj-$(CONFIG_MTD_PISMO)		+= pismo.o
@@ -28,7 +27,6 @@ obj-$(CONFIG_MTD_SC520CDP)	+= sc520cdp.o
 obj-$(CONFIG_MTD_NETSC520)	+= netsc520.o
 obj-$(CONFIG_MTD_TS5500)	+= ts5500_flash.o
 obj-$(CONFIG_MTD_SUN_UFLASH)	+= sun_uflash.o
-obj-$(CONFIG_MTD_VMAX)		+= vmax301.o
 obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 319b04a..5434d8d 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -128,7 +128,7 @@ static const char * const part_probe_types[] = {
 static int bfin_flash_probe(struct platform_device *pdev)
 {
 	int ret;
-	struct physmap_flash_data *pdata = pdev->dev.platform_data;
+	struct physmap_flash_data *pdata = dev_get_platdata(&pdev->dev);
 	struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	struct async_state *state;
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 5ede282..1adba86 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -196,7 +196,7 @@ static int gpio_flash_probe(struct platform_device *pdev)
 	struct resource *gpios;
 	struct async_state *state;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 52b3410..10debfe 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -152,11 +152,9 @@ static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int ixp4xx_flash_remove(struct platform_device *dev)
 {
-	struct flash_platform_data *plat = dev->dev.platform_data;
+	struct flash_platform_data *plat = dev_get_platdata(&dev->dev);
 	struct ixp4xx_flash_info *info = platform_get_drvdata(dev);
 
-	platform_set_drvdata(dev, NULL);
-
 	if(!info)
 		return 0;
 
@@ -180,7 +178,7 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
 
 static int ixp4xx_flash_probe(struct platform_device *dev)
 {
-	struct flash_platform_data *plat = dev->dev.platform_data;
+	struct flash_platform_data *plat = dev_get_platdata(&dev->dev);
 	struct ixp4xx_flash_info *info;
 	struct mtd_part_parser_data ppdata = {
 		.origin = dev->resource->start,
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index ab0fead..98bb5d5 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -102,9 +102,8 @@ static int latch_addr_flash_remove(struct platform_device *dev)
 	info = platform_get_drvdata(dev);
 	if (info == NULL)
 		return 0;
-	platform_set_drvdata(dev, NULL);
 
-	latch_addr_data = dev->dev.platform_data;
+	latch_addr_data = dev_get_platdata(&dev->dev);
 
 	if (info->mtd != NULL) {
 		mtd_device_unregister(info->mtd);
@@ -135,7 +134,7 @@ static int latch_addr_flash_probe(struct platform_device *dev)
 	int chipsel;
 	int err;
 
-	latch_addr_data = dev->dev.platform_data;
+	latch_addr_data = dev_get_platdata(&dev->dev);
 	if (latch_addr_data == NULL)
 		return -ENODEV;
 
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c
deleted file mode 100644
index 807ac2a..0000000
--- a/drivers/mtd/maps/octagon-5066.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* ######################################################################
-
-   Octagon 5066 MTD Driver.
-
-   The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It
-   comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that
-   is replacable by flash. Both units are mapped through a multiplexer
-   into a 32k memory window at 0xe8000. The control register for the
-   multiplexing unit is located at IO 0x208 with a bit map of
-     0-5 Page Selection in 32k increments
-     6-7 Device selection:
-        00 SSD off
-        01 SSD 0 (Socket)
-        10 SSD 1 (Flash chip)
-        11 undefined
-
-   On each SSD, the first 128k is reserved for use by the bios
-   (actually it IS the bios..) This only matters if you are booting off the
-   flash, you must not put a file system starting there.
-
-   The driver tries to do a detection algorithm to guess what sort of devices
-   are plugged into the sockets.
-
-   ##################################################################### */
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-
-#define WINDOW_START 0xe8000
-#define WINDOW_LENGTH 0x8000
-#define WINDOW_SHIFT 27
-#define WINDOW_MASK 0x7FFF
-#define PAGE_IO 0x208
-
-static volatile char page_n_dev = 0;
-static unsigned long iomapadr;
-static DEFINE_SPINLOCK(oct5066_spin);
-
-/*
- * We use map_priv_1 to identify which device we are.
- */
-
-static void __oct5066_page(struct map_info *map, __u8 byte)
-{
-	outb(byte,PAGE_IO);
-	page_n_dev = byte;
-}
-
-static inline void oct5066_page(struct map_info *map, unsigned long ofs)
-{
-	__u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
-
-	if (page_n_dev != byte)
-		__oct5066_page(map, byte);
-}
-
-
-static map_word oct5066_read8(struct map_info *map, unsigned long ofs)
-{
-	map_word ret;
-	spin_lock(&oct5066_spin);
-	oct5066_page(map, ofs);
-	ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
-	spin_unlock(&oct5066_spin);
-	return ret;
-}
-
-static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-{
-	while(len) {
-		unsigned long thislen = len;
-		if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
-			thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
-
-		spin_lock(&oct5066_spin);
-		oct5066_page(map, from);
-		memcpy_fromio(to, iomapadr + from, thislen);
-		spin_unlock(&oct5066_spin);
-		to += thislen;
-		from += thislen;
-		len -= thislen;
-	}
-}
-
-static void oct5066_write8(struct map_info *map, map_word d, unsigned long adr)
-{
-	spin_lock(&oct5066_spin);
-	oct5066_page(map, adr);
-	writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
-	spin_unlock(&oct5066_spin);
-}
-
-static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-{
-	while(len) {
-		unsigned long thislen = len;
-		if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
-			thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
-
-		spin_lock(&oct5066_spin);
-		oct5066_page(map, to);
-		memcpy_toio(iomapadr + to, from, thislen);
-		spin_unlock(&oct5066_spin);
-		to += thislen;
-		from += thislen;
-		len -= thislen;
-	}
-}
-
-static struct map_info oct5066_map[2] = {
-	{
-		.name = "Octagon 5066 Socket",
-		.phys = NO_XIP,
-		.size = 512 * 1024,
-		.bankwidth = 1,
-		.read = oct5066_read8,
-		.copy_from = oct5066_copy_from,
-		.write = oct5066_write8,
-		.copy_to = oct5066_copy_to,
-		.map_priv_1 = 1<<6
-	},
-	{
-		.name = "Octagon 5066 Internal Flash",
-		.phys = NO_XIP,
-		.size = 2 * 1024 * 1024,
-		.bankwidth = 1,
-		.read = oct5066_read8,
-		.copy_from = oct5066_copy_from,
-		.write = oct5066_write8,
-		.copy_to = oct5066_copy_to,
-		.map_priv_1 = 2<<6
-	}
-};
-
-static struct mtd_info *oct5066_mtd[2] = {NULL, NULL};
-
-// OctProbe - Sense if this is an octagon card
-// ---------------------------------------------------------------------
-/* Perform a simple validity test, we map the window select SSD0 and
-   change pages while monitoring the window. A change in the window,
-   controlled by the PAGE_IO port is a functioning 5066 board. This will
-   fail if the thing in the socket is set to a uniform value. */
-static int __init OctProbe(void)
-{
-   unsigned int Base = (1 << 6);
-   unsigned long I;
-   unsigned long Values[10];
-   for (I = 0; I != 20; I++)
-   {
-      outb(Base + (I%10),PAGE_IO);
-      if (I < 10)
-      {
-	 // Record the value and check for uniqueness
-	 Values[I%10] = readl(iomapadr);
-	 if (I > 0 && Values[I%10] == Values[0])
-	    return -EAGAIN;
-      }
-      else
-      {
-	 // Make sure we get the same values on the second pass
-	 if (Values[I%10] != readl(iomapadr))
-	    return -EAGAIN;
-      }
-   }
-   return 0;
-}
-
-void cleanup_oct5066(void)
-{
-	int i;
-	for (i=0; i<2; i++) {
-		if (oct5066_mtd[i]) {
-			mtd_device_unregister(oct5066_mtd[i]);
-			map_destroy(oct5066_mtd[i]);
-		}
-	}
-	iounmap((void *)iomapadr);
-	release_region(PAGE_IO, 1);
-}
-
-static int __init init_oct5066(void)
-{
-	int i;
-	int ret = 0;
-
-	// Do an autoprobe sequence
-	if (!request_region(PAGE_IO,1,"Octagon SSD")) {
-		printk(KERN_NOTICE "5066: Page Register in Use\n");
-		return -EAGAIN;
-	}
-	iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
-	if (!iomapadr) {
-		printk(KERN_NOTICE "Failed to ioremap memory region\n");
-		ret = -EIO;
-		goto out_rel;
-	}
-	if (OctProbe() != 0) {
-		printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n");
-		iounmap((void *)iomapadr);
-		ret = -EAGAIN;
-		goto out_unmap;
-	}
-
-	// Print out our little header..
-	printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START,
-	       WINDOW_START+WINDOW_LENGTH);
-
-	for (i=0; i<2; i++) {
-		oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]);
-		if (!oct5066_mtd[i])
-			oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]);
-		if (!oct5066_mtd[i])
-			oct5066_mtd[i] = do_map_probe("map_ram", &oct5066_map[i]);
-		if (!oct5066_mtd[i])
-			oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]);
-		if (oct5066_mtd[i]) {
-			oct5066_mtd[i]->owner = THIS_MODULE;
-			mtd_device_register(oct5066_mtd[i], NULL, 0);
-		}
-	}
-
-	if (!oct5066_mtd[0] && !oct5066_mtd[1]) {
-		cleanup_oct5066();
-		return -ENXIO;
-	}
-
-	return 0;
-
- out_unmap:
-	iounmap((void *)iomapadr);
- out_rel:
-	release_region(PAGE_IO, 1);
-	return ret;
-}
-
-module_init(init_oct5066);
-module_exit(cleanup_oct5066);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com>, David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("MTD map driver for Octagon 5066 Single Board Computer");
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index e7a592c..f73cd46 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -40,9 +40,8 @@ static int physmap_flash_remove(struct platform_device *dev)
 	info = platform_get_drvdata(dev);
 	if (info == NULL)
 		return 0;
-	platform_set_drvdata(dev, NULL);
 
-	physmap_data = dev->dev.platform_data;
+	physmap_data = dev_get_platdata(&dev->dev);
 
 	if (info->cmtd) {
 		mtd_device_unregister(info->cmtd);
@@ -69,7 +68,7 @@ static void physmap_set_vpp(struct map_info *map, int state)
 	unsigned long flags;
 
 	pdev = (struct platform_device *)map->map_priv_1;
-	physmap_data = pdev->dev.platform_data;
+	physmap_data = dev_get_platdata(&pdev->dev);
 
 	if (!physmap_data->set_vpp)
 		return;
@@ -103,7 +102,7 @@ static int physmap_flash_probe(struct platform_device *dev)
 	int i;
 	int devices_found = 0;
 
-	physmap_data = dev->dev.platform_data;
+	physmap_data = dev_get_platdata(&dev->dev);
 	if (physmap_data == NULL)
 		return -ENODEV;
 
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 71fdda2..6762716 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -84,8 +84,6 @@ static int platram_remove(struct platform_device *pdev)
 {
 	struct platram_info *info = to_platram_info(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	dev_dbg(&pdev->dev, "removing device\n");
 
 	if (info == NULL)
@@ -130,13 +128,13 @@ static int platram_probe(struct platform_device *pdev)
 
 	dev_dbg(&pdev->dev, "probe entered\n");
 
-	if (pdev->dev.platform_data == NULL) {
+	if (dev_get_platdata(&pdev->dev) == NULL) {
 		dev_err(&pdev->dev, "no platform data supplied\n");
 		err = -ENOENT;
 		goto exit_error;
 	}
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (info == NULL) {
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index acb1dbc..d210d13 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -49,7 +49,7 @@ static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int pxa2xx_flash_probe(struct platform_device *pdev)
 {
-	struct flash_platform_data *flash = pdev->dev.platform_data;
+	struct flash_platform_data *flash = dev_get_platdata(&pdev->dev);
 	struct pxa2xx_flash_info *info;
 	struct resource *res;
 
@@ -107,8 +107,6 @@ static int pxa2xx_flash_remove(struct platform_device *dev)
 {
 	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
 
-	platform_set_drvdata(dev, NULL);
-
 	mtd_device_unregister(info->mtd);
 
 	map_destroy(info->mtd);
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index ac02fbf..9352512 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -34,10 +34,9 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
 	info = platform_get_drvdata(dev);
 	if (!info)
 		return 0;
-	platform_set_drvdata(dev, NULL);
 
 	if (info->mtd) {
-		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
+		struct rbtx4939_flash_data *pdata = dev_get_platdata(&dev->dev);
 
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
@@ -57,7 +56,7 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
 	int err = 0;
 	unsigned long size;
 
-	pdata = dev->dev.platform_data;
+	pdata = dev_get_platdata(&dev->dev);
 	if (!pdata)
 		return -ENODEV;
 
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 29e3dca..8fc06bf 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -248,7 +248,7 @@ static const char * const part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
 static int sa1100_mtd_probe(struct platform_device *pdev)
 {
-	struct flash_platform_data *plat = pdev->dev.platform_data;
+	struct flash_platform_data *plat = dev_get_platdata(&pdev->dev);
 	struct sa_info *info;
 	int err;
 
@@ -277,9 +277,8 @@ static int sa1100_mtd_probe(struct platform_device *pdev)
 static int __exit sa1100_mtd_remove(struct platform_device *pdev)
 {
 	struct sa_info *info = platform_get_drvdata(pdev);
-	struct flash_platform_data *plat = pdev->dev.platform_data;
+	struct flash_platform_data *plat = dev_get_platdata(&pdev->dev);
 
-	platform_set_drvdata(pdev, NULL);
 	sa1100_destroy(info, plat);
 
 	return 0;
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c
deleted file mode 100644
index 5e68de7..0000000
--- a/drivers/mtd/maps/vmax301.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* ######################################################################
-
-   Tempustech VMAX SBC301 MTD Driver.
-
-   The VMAx 301 is a SBC based on . It
-   comes with three builtin AMD 29F016B flash chips and a socket for SRAM or
-   more flash. Each unit has it's own 8k mapping into a settable region
-   (0xD8000). There are two 8k mappings for each MTD, the first is always set
-   to the lower 8k of the device the second is paged. Writing a 16 bit page
-   value to anywhere in the first 8k will cause the second 8k to page around.
-
-   To boot the device a bios extension must be installed into the first 8k
-   of flash that is smart enough to copy itself down, page in the rest of
-   itself and begin executing.
-
-   ##################################################################### */
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-
-
-#define WINDOW_START 0xd8000
-#define WINDOW_LENGTH 0x2000
-#define WINDOW_SHIFT 25
-#define WINDOW_MASK 0x1FFF
-
-/* Actually we could use two spinlocks, but we'd have to have
-   more private space in the struct map_info. We lose a little
-   performance like this, but we'd probably lose more by having
-   the extra indirection from having one of the map->map_priv
-   fields pointing to yet another private struct.
-*/
-static DEFINE_SPINLOCK(vmax301_spin);
-
-static void __vmax301_page(struct map_info *map, unsigned long page)
-{
-	writew(page, map->map_priv_2 - WINDOW_LENGTH);
-	map->map_priv_1 = page;
-}
-
-static inline void vmax301_page(struct map_info *map,
-				  unsigned long ofs)
-{
-	unsigned long page = (ofs >> WINDOW_SHIFT);
-	if (map->map_priv_1 != page)
-		__vmax301_page(map, page);
-}
-
-static map_word vmax301_read8(struct map_info *map, unsigned long ofs)
-{
-	map_word ret;
-	spin_lock(&vmax301_spin);
-	vmax301_page(map, ofs);
-	ret.x[0] = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
-	spin_unlock(&vmax301_spin);
-	return ret;
-}
-
-static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-{
-	while(len) {
-		unsigned long thislen = len;
-		if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
-			thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
-		spin_lock(&vmax301_spin);
-		vmax301_page(map, from);
-		memcpy_fromio(to, map->map_priv_2 + from, thislen);
-		spin_unlock(&vmax301_spin);
-		to += thislen;
-		from += thislen;
-		len -= thislen;
-	}
-}
-
-static void vmax301_write8(struct map_info *map, map_word d, unsigned long adr)
-{
-	spin_lock(&vmax301_spin);
-	vmax301_page(map, adr);
-	writeb(d.x[0], map->map_priv_2 + (adr & WINDOW_MASK));
-	spin_unlock(&vmax301_spin);
-}
-
-static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-{
-	while(len) {
-		unsigned long thislen = len;
-		if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
-			thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
-
-		spin_lock(&vmax301_spin);
-		vmax301_page(map, to);
-		memcpy_toio(map->map_priv_2 + to, from, thislen);
-		spin_unlock(&vmax301_spin);
-		to += thislen;
-		from += thislen;
-		len -= thislen;
-	}
-}
-
-static struct map_info vmax_map[2] = {
-	{
-		.name = "VMAX301 Internal Flash",
-		.phys = NO_XIP,
-		.size = 3*2*1024*1024,
-		.bankwidth = 1,
-		.read = vmax301_read8,
-		.copy_from = vmax301_copy_from,
-		.write = vmax301_write8,
-		.copy_to = vmax301_copy_to,
-		.map_priv_1 = WINDOW_START + WINDOW_LENGTH,
-		.map_priv_2 = 0xFFFFFFFF
-	},
-	{
-		.name = "VMAX301 Socket",
-		.phys = NO_XIP,
-		.size = 0,
-		.bankwidth = 1,
-		.read = vmax301_read8,
-		.copy_from = vmax301_copy_from,
-		.write = vmax301_write8,
-		.copy_to = vmax301_copy_to,
-		.map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH),
-		.map_priv_2 = 0xFFFFFFFF
-	}
-};
-
-static struct mtd_info *vmax_mtd[2] = {NULL, NULL};
-
-static void __exit cleanup_vmax301(void)
-{
-	int i;
-
-	for (i=0; i<2; i++) {
-		if (vmax_mtd[i]) {
-			mtd_device_unregister(vmax_mtd[i]);
-			map_destroy(vmax_mtd[i]);
-		}
-	}
-	iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START);
-}
-
-static int __init init_vmax301(void)
-{
-	int i;
-	unsigned long iomapadr;
-	// Print out our little header..
-	printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START,
-	       WINDOW_START+4*WINDOW_LENGTH);
-
-	iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4);
-	if (!iomapadr) {
-		printk("Failed to ioremap memory region\n");
-		return -EIO;
-	}
-	/* Put the address in the map's private data area.
-	   We store the actual MTD IO address rather than the
-	   address of the first half, because it's used more
-	   often.
-	*/
-	vmax_map[0].map_priv_2 = iomapadr + WINDOW_START;
-	vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START);
-
-	for (i=0; i<2; i++) {
-		vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]);
-		if (!vmax_mtd[i])
-			vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]);
-		if (!vmax_mtd[i])
-			vmax_mtd[i] = do_map_probe("map_ram", &vmax_map[i]);
-		if (!vmax_mtd[i])
-			vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]);
-		if (vmax_mtd[i]) {
-			vmax_mtd[i]->owner = THIS_MODULE;
-			mtd_device_register(vmax_mtd[i], NULL, 0);
-		}
-	}
-
-	if (!vmax_mtd[0] && !vmax_mtd[1]) {
-		iounmap((void *)iomapadr);
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-module_init(init_vmax301);
-module_exit(cleanup_vmax301);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("MTD map driver for Tempustech VMAX SBC301 board");
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 50543f1..5ef8f5e 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -75,7 +75,7 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR
 
 config MTD_NAND_GPIO
 	tristate "GPIO NAND Flash driver"
-	depends on GPIOLIB && ARM
+	depends on GPIOLIB
 	help
 	  This enables a GPIO based NAND flash driver.
 
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index f1d71cd..8611eb4 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -258,7 +258,6 @@ static int ams_delta_init(struct platform_device *pdev)
  out_mtd:
 	gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
 out_gpio:
-	platform_set_drvdata(pdev, NULL);
 	gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
 	iounmap(io_base);
 out_free:
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 2d23d29..0e365da 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -18,6 +18,9 @@
  *  Add Programmable Multibit ECC support for various AT91 SoC
  *     © Copyright 2012 ATMEL, Hong Xu
  *
+ *  Add Nand Flash Controller support for SAMA5 SoC
+ *     © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -37,13 +40,12 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/platform_data/atmel.h>
-#include <linux/pinctrl/consumer.h>
-
-#include <mach/cpu.h>
 
 static int use_dma = 1;
 module_param(use_dma, int, 0);
@@ -58,6 +60,7 @@ module_param(on_flash_bbt, int, 0);
 	__raw_writel((value), add + ATMEL_ECC_##reg)
 
 #include "atmel_nand_ecc.h"	/* Hardware ECC registers */
+#include "atmel_nand_nfc.h"	/* Nand Flash Controller definition */
 
 /* oob layout for large page size
  * bad block info is on bytes 0 and 1
@@ -85,6 +88,23 @@ static struct nand_ecclayout atmel_oobinfo_small = {
 	},
 };
 
+struct atmel_nfc {
+	void __iomem		*base_cmd_regs;
+	void __iomem		*hsmc_regs;
+	void __iomem		*sram_bank0;
+	dma_addr_t		sram_bank0_phys;
+	bool			use_nfc_sram;
+	bool			write_by_sram;
+
+	bool			is_initialized;
+	struct completion	comp_nfc;
+
+	/* Point to the sram bank which include readed data via NFC */
+	void __iomem		*data_in_sram;
+	bool			will_write_sram;
+};
+static struct atmel_nfc	nand_nfc;
+
 struct atmel_nand_host {
 	struct nand_chip	nand_chip;
 	struct mtd_info		mtd;
@@ -97,6 +117,8 @@ struct atmel_nand_host {
 	struct completion	comp;
 	struct dma_chan		*dma_chan;
 
+	struct atmel_nfc	*nfc;
+
 	bool			has_pmecc;
 	u8			pmecc_corr_cap;
 	u16			pmecc_sector_size;
@@ -128,11 +150,6 @@ struct atmel_nand_host {
 
 static struct nand_ecclayout atmel_pmecc_oobinfo;
 
-static int cpu_has_dma(void)
-{
-	return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
-}
-
 /*
  * Enable NAND.
  */
@@ -186,21 +203,103 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
                 !!host->board.rdy_pin_active_low;
 }
 
+/* Set up for hardware ready pin and enable pin. */
+static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct atmel_nand_host *host = chip->priv;
+	int res = 0;
+
+	if (gpio_is_valid(host->board.rdy_pin)) {
+		res = devm_gpio_request(host->dev,
+				host->board.rdy_pin, "nand_rdy");
+		if (res < 0) {
+			dev_err(host->dev,
+				"can't request rdy gpio %d\n",
+				host->board.rdy_pin);
+			return res;
+		}
+
+		res = gpio_direction_input(host->board.rdy_pin);
+		if (res < 0) {
+			dev_err(host->dev,
+				"can't request input direction rdy gpio %d\n",
+				host->board.rdy_pin);
+			return res;
+		}
+
+		chip->dev_ready = atmel_nand_device_ready;
+	}
+
+	if (gpio_is_valid(host->board.enable_pin)) {
+		res = devm_gpio_request(host->dev,
+				host->board.enable_pin, "nand_enable");
+		if (res < 0) {
+			dev_err(host->dev,
+				"can't request enable gpio %d\n",
+				host->board.enable_pin);
+			return res;
+		}
+
+		res = gpio_direction_output(host->board.enable_pin, 1);
+		if (res < 0) {
+			dev_err(host->dev,
+				"can't request output direction enable gpio %d\n",
+				host->board.enable_pin);
+			return res;
+		}
+	}
+
+	return res;
+}
+
+static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
+{
+	int i;
+	u32 *t = trg;
+	const __iomem u32 *s = src;
+
+	for (i = 0; i < (size >> 2); i++)
+		*t++ = readl_relaxed(s++);
+}
+
+static void memcpy32_toio(void __iomem *trg, const void *src, int size)
+{
+	int i;
+	u32 __iomem *t = trg;
+	const u32 *s = src;
+
+	for (i = 0; i < (size >> 2); i++)
+		writel_relaxed(*s++, t++);
+}
+
 /*
  * Minimal-overhead PIO for data access.
  */
 static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip	*nand_chip = mtd->priv;
+	struct atmel_nand_host *host = nand_chip->priv;
 
-	__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+	if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
+		memcpy32_fromio(buf, host->nfc->data_in_sram, len);
+		host->nfc->data_in_sram += len;
+	} else {
+		__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+	}
 }
 
 static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip	*nand_chip = mtd->priv;
+	struct atmel_nand_host *host = nand_chip->priv;
 
-	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+	if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
+		memcpy32_fromio(buf, host->nfc->data_in_sram, len);
+		host->nfc->data_in_sram += len;
+	} else {
+		__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+	}
 }
 
 static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
@@ -222,6 +321,40 @@ static void dma_complete_func(void *completion)
 	complete(completion);
 }
 
+static int nfc_set_sram_bank(struct atmel_nand_host *host, unsigned int bank)
+{
+	/* NFC only has two banks. Must be 0 or 1 */
+	if (bank > 1)
+		return -EINVAL;
+
+	if (bank) {
+		/* Only for a 2k-page or lower flash, NFC can handle 2 banks */
+		if (host->mtd.writesize > 2048)
+			return -EINVAL;
+		nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK1);
+	} else {
+		nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK0);
+	}
+
+	return 0;
+}
+
+static uint nfc_get_sram_off(struct atmel_nand_host *host)
+{
+	if (nfc_readl(host->nfc->hsmc_regs, BANK) & ATMEL_HSMC_NFC_BANK1)
+		return NFC_SRAM_BANK1_OFFSET;
+	else
+		return 0;
+}
+
+static dma_addr_t nfc_sram_phys(struct atmel_nand_host *host)
+{
+	if (nfc_readl(host->nfc->hsmc_regs, BANK) & ATMEL_HSMC_NFC_BANK1)
+		return host->nfc->sram_bank0_phys + NFC_SRAM_BANK1_OFFSET;
+	else
+		return host->nfc->sram_bank0_phys;
+}
+
 static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
 			       int is_read)
 {
@@ -235,6 +368,7 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
 	void *p = buf;
 	int err = -EIO;
 	enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	struct atmel_nfc *nfc = host->nfc;
 
 	if (buf >= high_memory)
 		goto err_buf;
@@ -251,11 +385,20 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
 	}
 
 	if (is_read) {
-		dma_src_addr = host->io_phys;
+		if (nfc && nfc->data_in_sram)
+			dma_src_addr = nfc_sram_phys(host) + (nfc->data_in_sram
+				- (nfc->sram_bank0 + nfc_get_sram_off(host)));
+		else
+			dma_src_addr = host->io_phys;
+
 		dma_dst_addr = phys_addr;
 	} else {
 		dma_src_addr = phys_addr;
-		dma_dst_addr = host->io_phys;
+
+		if (nfc && nfc->write_by_sram)
+			dma_dst_addr = nfc_sram_phys(host);
+		else
+			dma_dst_addr = host->io_phys;
 	}
 
 	tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
@@ -278,6 +421,10 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
 	dma_async_issue_pending(host->dma_chan);
 	wait_for_completion(&host->comp);
 
+	if (is_read && nfc && nfc->data_in_sram)
+		/* After read data from SRAM, need to increase the position */
+		nfc->data_in_sram += len;
+
 	err = 0;
 
 err_dma:
@@ -366,43 +513,34 @@ static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
 			table_size * sizeof(int16_t);
 }
 
-static void pmecc_data_free(struct atmel_nand_host *host)
-{
-	kfree(host->pmecc_partial_syn);
-	kfree(host->pmecc_si);
-	kfree(host->pmecc_lmu);
-	kfree(host->pmecc_smu);
-	kfree(host->pmecc_mu);
-	kfree(host->pmecc_dmu);
-	kfree(host->pmecc_delta);
-}
-
 static int pmecc_data_alloc(struct atmel_nand_host *host)
 {
 	const int cap = host->pmecc_corr_cap;
+	int size;
+
+	size = (2 * cap + 1) * sizeof(int16_t);
+	host->pmecc_partial_syn = devm_kzalloc(host->dev, size, GFP_KERNEL);
+	host->pmecc_si = devm_kzalloc(host->dev, size, GFP_KERNEL);
+	host->pmecc_lmu = devm_kzalloc(host->dev,
+			(cap + 1) * sizeof(int16_t), GFP_KERNEL);
+	host->pmecc_smu = devm_kzalloc(host->dev,
+			(cap + 2) * size, GFP_KERNEL);
+
+	size = (cap + 1) * sizeof(int);
+	host->pmecc_mu = devm_kzalloc(host->dev, size, GFP_KERNEL);
+	host->pmecc_dmu = devm_kzalloc(host->dev, size, GFP_KERNEL);
+	host->pmecc_delta = devm_kzalloc(host->dev, size, GFP_KERNEL);
+
+	if (!host->pmecc_partial_syn ||
+		!host->pmecc_si ||
+		!host->pmecc_lmu ||
+		!host->pmecc_smu ||
+		!host->pmecc_mu ||
+		!host->pmecc_dmu ||
+		!host->pmecc_delta)
+		return -ENOMEM;
 
-	host->pmecc_partial_syn = kzalloc((2 * cap + 1) * sizeof(int16_t),
-					GFP_KERNEL);
-	host->pmecc_si = kzalloc((2 * cap + 1) * sizeof(int16_t), GFP_KERNEL);
-	host->pmecc_lmu = kzalloc((cap + 1) * sizeof(int16_t), GFP_KERNEL);
-	host->pmecc_smu = kzalloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t),
-					GFP_KERNEL);
-	host->pmecc_mu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
-	host->pmecc_dmu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
-	host->pmecc_delta = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
-
-	if (host->pmecc_partial_syn &&
-			host->pmecc_si &&
-			host->pmecc_lmu &&
-			host->pmecc_smu &&
-			host->pmecc_mu &&
-			host->pmecc_dmu &&
-			host->pmecc_delta)
-		return 0;
-
-	/* error happened */
-	pmecc_data_free(host);
-	return -ENOMEM;
+	return 0;
 }
 
 static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
@@ -763,6 +901,30 @@ normal_check:
 	return total_err;
 }
 
+static void pmecc_enable(struct atmel_nand_host *host, int ecc_op)
+{
+	u32 val;
+
+	if (ecc_op != NAND_ECC_READ && ecc_op != NAND_ECC_WRITE) {
+		dev_err(host->dev, "atmel_nand: wrong pmecc operation type!");
+		return;
+	}
+
+	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
+	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
+	val = pmecc_readl_relaxed(host->ecc, CFG);
+
+	if (ecc_op == NAND_ECC_READ)
+		pmecc_writel(host->ecc, CFG, (val & ~PMECC_CFG_WRITE_OP)
+			| PMECC_CFG_AUTO_ENABLE);
+	else
+		pmecc_writel(host->ecc, CFG, (val | PMECC_CFG_WRITE_OP)
+			& ~PMECC_CFG_AUTO_ENABLE);
+
+	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
+	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
+}
+
 static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
 	struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
 {
@@ -774,13 +936,8 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
 	unsigned long end_time;
 	int bitflips = 0;
 
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-	pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG)
-		& ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE);
-
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
+	if (!host->nfc || !host->nfc->use_nfc_sram)
+		pmecc_enable(host, NAND_ECC_READ);
 
 	chip->read_buf(mtd, buf, eccsize);
 	chip->read_buf(mtd, oob, mtd->oobsize);
@@ -813,16 +970,10 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
 	int i, j;
 	unsigned long end_time;
 
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-
-	pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) |
-		PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE);
-
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-	pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
-
-	chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
+	if (!host->nfc || !host->nfc->write_by_sram) {
+		pmecc_enable(host, NAND_ECC_WRITE);
+		chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
+	}
 
 	end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
 	while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
@@ -967,11 +1118,11 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
 			host->pmecc_corr_cap = 2;
 		else if (*cap <= 4)
 			host->pmecc_corr_cap = 4;
-		else if (*cap < 8)
+		else if (*cap <= 8)
 			host->pmecc_corr_cap = 8;
-		else if (*cap < 12)
+		else if (*cap <= 12)
 			host->pmecc_corr_cap = 12;
-		else if (*cap < 24)
+		else if (*cap <= 24)
 			host->pmecc_corr_cap = 24;
 		else
 			return -EINVAL;
@@ -1002,7 +1153,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
 		return err_no;
 	}
 
-	if (cap != host->pmecc_corr_cap ||
+	if (cap > host->pmecc_corr_cap ||
 			sector_size != host->pmecc_sector_size)
 		dev_info(host->dev, "WARNING: Be Caution! Using different PMECC parameters from Nand ONFI ECC reqirement.\n");
 
@@ -1023,27 +1174,28 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
 		return 0;
 	}
 
-	host->ecc = ioremap(regs->start, resource_size(regs));
-	if (host->ecc == NULL) {
+	host->ecc = devm_ioremap_resource(&pdev->dev, regs);
+	if (IS_ERR(host->ecc)) {
 		dev_err(host->dev, "ioremap failed\n");
-		err_no = -EIO;
-		goto err_pmecc_ioremap;
+		err_no = PTR_ERR(host->ecc);
+		goto err;
 	}
 
 	regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
-	if (regs_pmerr && regs_rom) {
-		host->pmerrloc_base = ioremap(regs_pmerr->start,
-			resource_size(regs_pmerr));
-		host->pmecc_rom_base = ioremap(regs_rom->start,
-			resource_size(regs_rom));
+	host->pmerrloc_base = devm_ioremap_resource(&pdev->dev, regs_pmerr);
+	if (IS_ERR(host->pmerrloc_base)) {
+		dev_err(host->dev,
+			"Can not get I/O resource for PMECC ERRLOC controller!\n");
+		err_no = PTR_ERR(host->pmerrloc_base);
+		goto err;
 	}
 
-	if (!host->pmerrloc_base || !host->pmecc_rom_base) {
-		dev_err(host->dev,
-			"Can not get I/O resource for PMECC ERRLOC controller or ROM!\n");
-		err_no = -EIO;
-		goto err_pmloc_ioremap;
+	regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+	host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom);
+	if (IS_ERR(host->pmecc_rom_base)) {
+		dev_err(host->dev, "Can not get I/O resource for ROM!\n");
+		err_no = PTR_ERR(host->pmecc_rom_base);
+		goto err;
 	}
 
 	/* ECC is calculated for the whole page (1 step) */
@@ -1068,7 +1220,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
 		if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
 			dev_err(host->dev, "No room for ECC bytes\n");
 			err_no = -EINVAL;
-			goto err_no_ecc_room;
+			goto err;
 		}
 		pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
 					mtd->oobsize,
@@ -1093,7 +1245,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
 	if (err_no) {
 		dev_err(host->dev,
 				"Cannot allocate memory for PMECC computation!\n");
-		goto err_pmecc_data_alloc;
+		goto err;
 	}
 
 	nand_chip->ecc.read_page = atmel_nand_pmecc_read_page;
@@ -1103,15 +1255,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
 
 	return 0;
 
-err_pmecc_data_alloc:
-err_no_ecc_room:
-err_pmloc_ioremap:
-	iounmap(host->ecc);
-	if (host->pmerrloc_base)
-		iounmap(host->pmerrloc_base);
-	if (host->pmecc_rom_base)
-		iounmap(host->pmecc_rom_base);
-err_pmecc_ioremap:
+err:
 	return err_no;
 }
 
@@ -1174,10 +1318,9 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	 * Workaround: Reset the parity registers before reading the
 	 * actual data.
 	 */
-	if (cpu_is_at32ap7000()) {
-		struct atmel_nand_host *host = chip->priv;
+	struct atmel_nand_host *host = chip->priv;
+	if (host->board.need_reset_workaround)
 		ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
-	}
 
 	/* read the page */
 	chip->read_buf(mtd, p, eccsize);
@@ -1298,11 +1441,11 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
  */
 static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
 {
-	if (cpu_is_at32ap7000()) {
-		struct nand_chip *nand_chip = mtd->priv;
-		struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd->priv;
+	struct atmel_nand_host *host = nand_chip->priv;
+
+	if (host->board.need_reset_workaround)
 		ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
-	}
 }
 
 #if defined(CONFIG_OF)
@@ -1337,6 +1480,8 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
 
 	board->on_flash_bbt = of_get_nand_on_flash_bbt(np);
 
+	board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma");
+
 	if (of_get_nand_bus_width(np) == 16)
 		board->bus_width_16 = 1;
 
@@ -1348,6 +1493,9 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
 
 	host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc");
 
+	/* load the nfc driver if there is */
+	of_platform_populate(np, NULL, NULL, host->dev);
+
 	if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc)
 		return 0;	/* Not using PMECC */
 
@@ -1414,10 +1562,10 @@ static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
 		return 0;
 	}
 
-	host->ecc = ioremap(regs->start, resource_size(regs));
-	if (host->ecc == NULL) {
+	host->ecc = devm_ioremap_resource(&pdev->dev, regs);
+	if (IS_ERR(host->ecc)) {
 		dev_err(host->dev, "ioremap failed\n");
-		return -EIO;
+		return PTR_ERR(host->ecc);
 	}
 
 	/* ECC is calculated for the whole page (1 step) */
@@ -1459,6 +1607,382 @@ static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
 	return 0;
 }
 
+/* SMC interrupt service routine */
+static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
+{
+	struct atmel_nand_host *host = dev_id;
+	u32 status, mask, pending;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	status = nfc_readl(host->nfc->hsmc_regs, SR);
+	mask = nfc_readl(host->nfc->hsmc_regs, IMR);
+	pending = status & mask;
+
+	if (pending & NFC_SR_XFR_DONE) {
+		complete(&host->nfc->comp_nfc);
+		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
+	} else if (pending & NFC_SR_RB_EDGE) {
+		complete(&host->nfc->comp_nfc);
+		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
+	} else if (pending & NFC_SR_CMD_DONE) {
+		complete(&host->nfc->comp_nfc);
+		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE);
+	} else {
+		ret = IRQ_NONE;
+	}
+
+	return ret;
+}
+
+/* NFC(Nand Flash Controller) related functions */
+static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
+{
+	unsigned long timeout;
+	init_completion(&host->nfc->comp_nfc);
+
+	/* Enable interrupt that need to wait for */
+	nfc_writel(host->nfc->hsmc_regs, IER, flag);
+
+	timeout = wait_for_completion_timeout(&host->nfc->comp_nfc,
+			msecs_to_jiffies(NFC_TIME_OUT_MS));
+	if (timeout)
+		return 0;
+
+	/* Time out to wait for the interrupt */
+	dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag);
+	return -ETIMEDOUT;
+}
+
+static int nfc_send_command(struct atmel_nand_host *host,
+	unsigned int cmd, unsigned int addr, unsigned char cycle0)
+{
+	unsigned long timeout;
+	dev_dbg(host->dev,
+		"nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n",
+		cmd, addr, cycle0);
+
+	timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS);
+	while (nfc_cmd_readl(NFCADDR_CMD_NFCBUSY, host->nfc->base_cmd_regs)
+			& NFCADDR_CMD_NFCBUSY) {
+		if (time_after(jiffies, timeout)) {
+			dev_err(host->dev,
+				"Time out to wait CMD_NFCBUSY ready!\n");
+			return -ETIMEDOUT;
+		}
+	}
+	nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0);
+	nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs);
+	return nfc_wait_interrupt(host, NFC_SR_CMD_DONE);
+}
+
+static int nfc_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct atmel_nand_host *host = nand_chip->priv;
+	if (!nfc_wait_interrupt(host, NFC_SR_RB_EDGE))
+		return 1;
+	return 0;
+}
+
+static void nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct atmel_nand_host *host = nand_chip->priv;
+
+	if (chip == -1)
+		nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_DISABLE);
+	else
+		nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE);
+}
+
+static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr,
+		unsigned int *addr1234, unsigned int *cycle0)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	int acycle = 0;
+	unsigned char addr_bytes[8];
+	int index = 0, bit_shift;
+
+	BUG_ON(addr1234 == NULL || cycle0 == NULL);
+
+	*cycle0 = 0;
+	*addr1234 = 0;
+
+	if (column != -1) {
+		if (chip->options & NAND_BUSWIDTH_16)
+			column >>= 1;
+		addr_bytes[acycle++] = column & 0xff;
+		if (mtd->writesize > 512)
+			addr_bytes[acycle++] = (column >> 8) & 0xff;
+	}
+
+	if (page_addr != -1) {
+		addr_bytes[acycle++] = page_addr & 0xff;
+		addr_bytes[acycle++] = (page_addr >> 8) & 0xff;
+		if (chip->chipsize > (128 << 20))
+			addr_bytes[acycle++] = (page_addr >> 16) & 0xff;
+	}
+
+	if (acycle > 4)
+		*cycle0 = addr_bytes[index++];
+
+	for (bit_shift = 0; index < acycle; bit_shift += 8)
+		*addr1234 += addr_bytes[index++] << bit_shift;
+
+	/* return acycle in cmd register */
+	return acycle << NFCADDR_CMD_ACYCLE_BIT_POS;
+}
+
+static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
+				int column, int page_addr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct atmel_nand_host *host = chip->priv;
+	unsigned long timeout;
+	unsigned int nfc_addr_cmd = 0;
+
+	unsigned int cmd1 = command << NFCADDR_CMD_CMD1_BIT_POS;
+
+	/* Set default settings: no cmd2, no addr cycle. read from nand */
+	unsigned int cmd2 = 0;
+	unsigned int vcmd2 = 0;
+	int acycle = NFCADDR_CMD_ACYCLE_NONE;
+	int csid = NFCADDR_CMD_CSID_3;
+	int dataen = NFCADDR_CMD_DATADIS;
+	int nfcwr = NFCADDR_CMD_NFCRD;
+	unsigned int addr1234 = 0;
+	unsigned int cycle0 = 0;
+	bool do_addr = true;
+	host->nfc->data_in_sram = NULL;
+
+	dev_dbg(host->dev, "%s: cmd = 0x%02x, col = 0x%08x, page = 0x%08x\n",
+	     __func__, command, column, page_addr);
+
+	switch (command) {
+	case NAND_CMD_RESET:
+		nfc_addr_cmd = cmd1 | acycle | csid | dataen | nfcwr;
+		nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
+		udelay(chip->chip_delay);
+
+		nfc_nand_command(mtd, NAND_CMD_STATUS, -1, -1);
+		timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS);
+		while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) {
+			if (time_after(jiffies, timeout)) {
+				dev_err(host->dev,
+					"Time out to wait status ready!\n");
+				break;
+			}
+		}
+		return;
+	case NAND_CMD_STATUS:
+		do_addr = false;
+		break;
+	case NAND_CMD_PARAM:
+	case NAND_CMD_READID:
+		do_addr = false;
+		acycle = NFCADDR_CMD_ACYCLE_1;
+		if (column != -1)
+			addr1234 = column;
+		break;
+	case NAND_CMD_RNDOUT:
+		cmd2 = NAND_CMD_RNDOUTSTART << NFCADDR_CMD_CMD2_BIT_POS;
+		vcmd2 = NFCADDR_CMD_VCMD2;
+		break;
+	case NAND_CMD_READ0:
+	case NAND_CMD_READOOB:
+		if (command == NAND_CMD_READOOB) {
+			column += mtd->writesize;
+			command = NAND_CMD_READ0; /* only READ0 is valid */
+			cmd1 = command << NFCADDR_CMD_CMD1_BIT_POS;
+		}
+		if (host->nfc->use_nfc_sram) {
+			/* Enable Data transfer to sram */
+			dataen = NFCADDR_CMD_DATAEN;
+
+			/* Need enable PMECC now, since NFC will transfer
+			 * data in bus after sending nfc read command.
+			 */
+			if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
+				pmecc_enable(host, NAND_ECC_READ);
+		}
+
+		cmd2 = NAND_CMD_READSTART << NFCADDR_CMD_CMD2_BIT_POS;
+		vcmd2 = NFCADDR_CMD_VCMD2;
+		break;
+	/* For prgramming command, the cmd need set to write enable */
+	case NAND_CMD_PAGEPROG:
+	case NAND_CMD_SEQIN:
+	case NAND_CMD_RNDIN:
+		nfcwr = NFCADDR_CMD_NFCWR;
+		if (host->nfc->will_write_sram && command == NAND_CMD_SEQIN)
+			dataen = NFCADDR_CMD_DATAEN;
+		break;
+	default:
+		break;
+	}
+
+	if (do_addr)
+		acycle = nfc_make_addr(mtd, column, page_addr, &addr1234,
+				&cycle0);
+
+	nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr;
+	nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
+
+	if (dataen == NFCADDR_CMD_DATAEN)
+		if (nfc_wait_interrupt(host, NFC_SR_XFR_DONE))
+			dev_err(host->dev, "something wrong, No XFR_DONE interrupt comes.\n");
+
+	/*
+	 * Program and erase have their own busy handlers status, sequential
+	 * in, and deplete1 need no delay.
+	 */
+	switch (command) {
+	case NAND_CMD_CACHEDPROG:
+	case NAND_CMD_PAGEPROG:
+	case NAND_CMD_ERASE1:
+	case NAND_CMD_ERASE2:
+	case NAND_CMD_RNDIN:
+	case NAND_CMD_STATUS:
+	case NAND_CMD_RNDOUT:
+	case NAND_CMD_SEQIN:
+	case NAND_CMD_READID:
+		return;
+
+	case NAND_CMD_READ0:
+		if (dataen == NFCADDR_CMD_DATAEN) {
+			host->nfc->data_in_sram = host->nfc->sram_bank0 +
+				nfc_get_sram_off(host);
+			return;
+		}
+		/* fall through */
+	default:
+		nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
+	}
+}
+
+static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+			uint32_t offset, int data_len, const uint8_t *buf,
+			int oob_required, int page, int cached, int raw)
+{
+	int cfg, len;
+	int status = 0;
+	struct atmel_nand_host *host = chip->priv;
+	void __iomem *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host);
+
+	/* Subpage write is not supported */
+	if (offset || (data_len < mtd->writesize))
+		return -EINVAL;
+
+	cfg = nfc_readl(host->nfc->hsmc_regs, CFG);
+	len = mtd->writesize;
+
+	if (unlikely(raw)) {
+		len += mtd->oobsize;
+		nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE);
+	} else
+		nfc_writel(host->nfc->hsmc_regs, CFG, cfg & ~NFC_CFG_WSPARE);
+
+	/* Copy page data to sram that will write to nand via NFC */
+	if (use_dma) {
+		if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0)
+			/* Fall back to use cpu copy */
+			memcpy32_toio(sram, buf, len);
+	} else {
+		memcpy32_toio(sram, buf, len);
+	}
+
+	if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
+		/*
+		 * When use NFC sram, need set up PMECC before send
+		 * NAND_CMD_SEQIN command. Since when the nand command
+		 * is sent, nfc will do transfer from sram and nand.
+		 */
+		pmecc_enable(host, NAND_ECC_WRITE);
+
+	host->nfc->will_write_sram = true;
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+	host->nfc->will_write_sram = false;
+
+	if (likely(!raw))
+		/* Need to write ecc into oob */
+		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+
+	if (status < 0)
+		return status;
+
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	status = chip->waitfunc(mtd, chip);
+
+	if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
+
+	if (status & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+static int nfc_sram_init(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct atmel_nand_host *host = chip->priv;
+	int res = 0;
+
+	/* Initialize the NFC CFG register */
+	unsigned int cfg_nfc = 0;
+
+	/* set page size and oob layout */
+	switch (mtd->writesize) {
+	case 512:
+		cfg_nfc = NFC_CFG_PAGESIZE_512;
+		break;
+	case 1024:
+		cfg_nfc = NFC_CFG_PAGESIZE_1024;
+		break;
+	case 2048:
+		cfg_nfc = NFC_CFG_PAGESIZE_2048;
+		break;
+	case 4096:
+		cfg_nfc = NFC_CFG_PAGESIZE_4096;
+		break;
+	case 8192:
+		cfg_nfc = NFC_CFG_PAGESIZE_8192;
+		break;
+	default:
+		dev_err(host->dev, "Unsupported page size for NFC.\n");
+		res = -ENXIO;
+		return res;
+	}
+
+	/* oob bytes size = (NFCSPARESIZE + 1) * 4
+	 * Max support spare size is 512 bytes. */
+	cfg_nfc |= (((mtd->oobsize / 4) - 1) << NFC_CFG_NFC_SPARESIZE_BIT_POS
+		& NFC_CFG_NFC_SPARESIZE);
+	/* default set a max timeout */
+	cfg_nfc |= NFC_CFG_RSPARE |
+			NFC_CFG_NFC_DTOCYC | NFC_CFG_NFC_DTOMUL;
+
+	nfc_writel(host->nfc->hsmc_regs, CFG, cfg_nfc);
+
+	host->nfc->will_write_sram = false;
+	nfc_set_sram_bank(host, 0);
+
+	/* Use Write page with NFC SRAM only for PMECC or ECC NONE. */
+	if (host->nfc->write_by_sram) {
+		if ((chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) ||
+				chip->ecc.mode == NAND_ECC_NONE)
+			chip->write_page = nfc_sram_write_page;
+		else
+			host->nfc->write_by_sram = false;
+	}
+
+	dev_info(host->dev, "Using NFC Sram read %s\n",
+			host->nfc->write_by_sram ? "and write" : "");
+	return 0;
+}
+
+static struct platform_driver atmel_nand_nfc_driver;
 /*
  * Probe for the NAND device.
  */
@@ -1469,30 +1993,27 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	struct nand_chip *nand_chip;
 	struct resource *mem;
 	struct mtd_part_parser_data ppdata = {};
-	int res;
-	struct pinctrl *pinctrl;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
-		return -ENXIO;
-	}
+	int res, irq;
 
 	/* Allocate memory for the device structure (and zero it) */
-	host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
 	if (!host) {
 		printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
 		return -ENOMEM;
 	}
 
-	host->io_phys = (dma_addr_t)mem->start;
+	res = platform_driver_register(&atmel_nand_nfc_driver);
+	if (res)
+		dev_err(&pdev->dev, "atmel_nand: can't register NFC driver\n");
 
-	host->io_base = ioremap(mem->start, resource_size(mem));
-	if (host->io_base == NULL) {
-		printk(KERN_ERR "atmel_nand: ioremap failed\n");
-		res = -EIO;
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->io_base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(host->io_base)) {
+		dev_err(&pdev->dev, "atmel_nand: ioremap resource failed\n");
+		res = PTR_ERR(host->io_base);
 		goto err_nand_ioremap;
 	}
+	host->io_phys = (dma_addr_t)mem->start;
 
 	mtd = &host->mtd;
 	nand_chip = &host->nand_chip;
@@ -1500,9 +2021,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	if (pdev->dev.of_node) {
 		res = atmel_of_init_port(host, pdev->dev.of_node);
 		if (res)
-			goto err_ecc_ioremap;
+			goto err_nand_ioremap;
 	} else {
-		memcpy(&host->board, pdev->dev.platform_data,
+		memcpy(&host->board, dev_get_platdata(&pdev->dev),
 		       sizeof(struct atmel_nand_data));
 	}
 
@@ -1513,51 +2034,35 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	/* Set address of NAND IO lines */
 	nand_chip->IO_ADDR_R = host->io_base;
 	nand_chip->IO_ADDR_W = host->io_base;
-	nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		dev_err(host->dev, "Failed to request pinctrl\n");
-		res = PTR_ERR(pinctrl);
-		goto err_ecc_ioremap;
-	}
+	if (nand_nfc.is_initialized) {
+		/* NFC driver is probed and initialized */
+		host->nfc = &nand_nfc;
 
-	if (gpio_is_valid(host->board.rdy_pin)) {
-		res = gpio_request(host->board.rdy_pin, "nand_rdy");
-		if (res < 0) {
-			dev_err(&pdev->dev,
-				"can't request rdy gpio %d\n",
-				host->board.rdy_pin);
-			goto err_ecc_ioremap;
-		}
+		nand_chip->select_chip = nfc_select_chip;
+		nand_chip->dev_ready = nfc_device_ready;
+		nand_chip->cmdfunc = nfc_nand_command;
 
-		res = gpio_direction_input(host->board.rdy_pin);
-		if (res < 0) {
-			dev_err(&pdev->dev,
-				"can't request input direction rdy gpio %d\n",
-				host->board.rdy_pin);
-			goto err_ecc_ioremap;
+		/* Initialize the interrupt for NFC */
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0) {
+			dev_err(host->dev, "Cannot get HSMC irq!\n");
+			goto err_nand_ioremap;
 		}
 
-		nand_chip->dev_ready = atmel_nand_device_ready;
-	}
-
-	if (gpio_is_valid(host->board.enable_pin)) {
-		res = gpio_request(host->board.enable_pin, "nand_enable");
-		if (res < 0) {
-			dev_err(&pdev->dev,
-				"can't request enable gpio %d\n",
-				host->board.enable_pin);
-			goto err_ecc_ioremap;
+		res = devm_request_irq(&pdev->dev, irq, hsmc_interrupt,
+				0, "hsmc", host);
+		if (res) {
+			dev_err(&pdev->dev, "Unable to request HSMC irq %d\n",
+				irq);
+			goto err_nand_ioremap;
 		}
+	} else {
+		res = atmel_nand_set_enable_ready_pins(mtd);
+		if (res)
+			goto err_nand_ioremap;
 
-		res = gpio_direction_output(host->board.enable_pin, 1);
-		if (res < 0) {
-			dev_err(&pdev->dev,
-				"can't request output direction enable gpio %d\n",
-				host->board.enable_pin);
-			goto err_ecc_ioremap;
-		}
+		nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 	}
 
 	nand_chip->ecc.mode = host->board.ecc_mode;
@@ -1573,7 +2078,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	atmel_nand_enable(host);
 
 	if (gpio_is_valid(host->board.det_pin)) {
-		res = gpio_request(host->board.det_pin, "nand_det");
+		res = devm_gpio_request(&pdev->dev,
+				host->board.det_pin, "nand_det");
 		if (res < 0) {
 			dev_err(&pdev->dev,
 				"can't request det gpio %d\n",
@@ -1601,7 +2107,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 		nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
 	}
 
-	if (!cpu_has_dma())
+	if (!host->board.has_dma)
 		use_dma = 0;
 
 	if (use_dma) {
@@ -1637,6 +2143,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 			goto err_hw_ecc;
 	}
 
+	/* initialize the nfc configuration register */
+	if (host->nfc && host->nfc->use_nfc_sram) {
+		res = nfc_sram_init(mtd);
+		if (res) {
+			host->nfc->use_nfc_sram = false;
+			dev_err(host->dev, "Disable use nfc sram for data transfer.\n");
+		}
+	}
+
 	/* second phase scan */
 	if (nand_scan_tail(mtd)) {
 		res = -ENXIO;
@@ -1651,27 +2166,16 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 		return res;
 
 err_scan_tail:
-	if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) {
+	if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW)
 		pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-		pmecc_data_free(host);
-	}
-	if (host->ecc)
-		iounmap(host->ecc);
-	if (host->pmerrloc_base)
-		iounmap(host->pmerrloc_base);
-	if (host->pmecc_rom_base)
-		iounmap(host->pmecc_rom_base);
 err_hw_ecc:
 err_scan_ident:
 err_no_card:
 	atmel_nand_disable(host);
-	platform_set_drvdata(pdev, NULL);
 	if (host->dma_chan)
 		dma_release_channel(host->dma_chan);
-err_ecc_ioremap:
-	iounmap(host->io_base);
 err_nand_ioremap:
-	kfree(host);
+	platform_driver_unregister(&atmel_nand_nfc_driver);
 	return res;
 }
 
@@ -1691,30 +2195,12 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
 		pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
 		pmerrloc_writel(host->pmerrloc_base, ELDIS,
 				PMERRLOC_DISABLE);
-		pmecc_data_free(host);
 	}
 
-	if (gpio_is_valid(host->board.det_pin))
-		gpio_free(host->board.det_pin);
-
-	if (gpio_is_valid(host->board.enable_pin))
-		gpio_free(host->board.enable_pin);
-
-	if (gpio_is_valid(host->board.rdy_pin))
-		gpio_free(host->board.rdy_pin);
-
-	if (host->ecc)
-		iounmap(host->ecc);
-	if (host->pmecc_rom_base)
-		iounmap(host->pmecc_rom_base);
-	if (host->pmerrloc_base)
-		iounmap(host->pmerrloc_base);
-
 	if (host->dma_chan)
 		dma_release_channel(host->dma_chan);
 
-	iounmap(host->io_base);
-	kfree(host);
+	platform_driver_unregister(&atmel_nand_nfc_driver);
 
 	return 0;
 }
@@ -1728,6 +2214,59 @@ static const struct of_device_id atmel_nand_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
 #endif
 
+static int atmel_nand_nfc_probe(struct platform_device *pdev)
+{
+	struct atmel_nfc *nfc = &nand_nfc;
+	struct resource *nfc_cmd_regs, *nfc_hsmc_regs, *nfc_sram;
+
+	nfc_cmd_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	nfc->base_cmd_regs = devm_ioremap_resource(&pdev->dev, nfc_cmd_regs);
+	if (IS_ERR(nfc->base_cmd_regs))
+		return PTR_ERR(nfc->base_cmd_regs);
+
+	nfc_hsmc_regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	nfc->hsmc_regs = devm_ioremap_resource(&pdev->dev, nfc_hsmc_regs);
+	if (IS_ERR(nfc->hsmc_regs))
+		return PTR_ERR(nfc->hsmc_regs);
+
+	nfc_sram = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (nfc_sram) {
+		nfc->sram_bank0 = devm_ioremap_resource(&pdev->dev, nfc_sram);
+		if (IS_ERR(nfc->sram_bank0)) {
+			dev_warn(&pdev->dev, "Fail to ioremap the NFC sram with error: %ld. So disable NFC sram.\n",
+					PTR_ERR(nfc->sram_bank0));
+		} else {
+			nfc->use_nfc_sram = true;
+			nfc->sram_bank0_phys = (dma_addr_t)nfc_sram->start;
+
+			if (pdev->dev.of_node)
+				nfc->write_by_sram = of_property_read_bool(
+						pdev->dev.of_node,
+						"atmel,write-by-sram");
+		}
+	}
+
+	nfc->is_initialized = true;
+	dev_info(&pdev->dev, "NFC is probed.\n");
+	return 0;
+}
+
+#if defined(CONFIG_OF)
+static struct of_device_id atmel_nand_nfc_match[] = {
+	{ .compatible = "atmel,sama5d3-nfc" },
+	{ /* sentinel */ }
+};
+#endif
+
+static struct platform_driver atmel_nand_nfc_driver = {
+	.driver = {
+		.name = "atmel_nand_nfc",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(atmel_nand_nfc_match),
+	},
+	.probe = atmel_nand_nfc_probe,
+};
+
 static struct platform_driver atmel_nand_driver = {
 	.remove		= __exit_p(atmel_nand_remove),
 	.driver		= {
diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h
new file mode 100644
index 0000000..4efd117
--- /dev/null
+++ b/drivers/mtd/nand/atmel_nand_nfc.h
@@ -0,0 +1,98 @@
+/*
+ * Atmel Nand Flash Controller (NFC) - System peripherals regsters.
+ * Based on SAMA5D3 datasheet.
+ *
+ * © Copyright 2013 Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef ATMEL_NAND_NFC_H
+#define ATMEL_NAND_NFC_H
+
+/*
+ * HSMC NFC registers
+ */
+#define ATMEL_HSMC_NFC_CFG	0x00		/* NFC Configuration Register */
+#define		NFC_CFG_PAGESIZE	(7 << 0)
+#define			NFC_CFG_PAGESIZE_512	(0 << 0)
+#define			NFC_CFG_PAGESIZE_1024	(1 << 0)
+#define			NFC_CFG_PAGESIZE_2048	(2 << 0)
+#define			NFC_CFG_PAGESIZE_4096	(3 << 0)
+#define			NFC_CFG_PAGESIZE_8192	(4 << 0)
+#define		NFC_CFG_WSPARE		(1 << 8)
+#define		NFC_CFG_RSPARE		(1 << 9)
+#define		NFC_CFG_NFC_DTOCYC	(0xf << 16)
+#define		NFC_CFG_NFC_DTOMUL	(0x7 << 20)
+#define		NFC_CFG_NFC_SPARESIZE	(0x7f << 24)
+#define		NFC_CFG_NFC_SPARESIZE_BIT_POS	24
+
+#define ATMEL_HSMC_NFC_CTRL	0x04		/* NFC Control Register */
+#define		NFC_CTRL_ENABLE		(1 << 0)
+#define		NFC_CTRL_DISABLE	(1 << 1)
+
+#define ATMEL_HSMC_NFC_SR	0x08		/* NFC Status Register */
+#define		NFC_SR_XFR_DONE		(1 << 16)
+#define		NFC_SR_CMD_DONE		(1 << 17)
+#define		NFC_SR_RB_EDGE		(1 << 24)
+
+#define ATMEL_HSMC_NFC_IER	0x0c
+#define ATMEL_HSMC_NFC_IDR	0x10
+#define ATMEL_HSMC_NFC_IMR	0x14
+#define ATMEL_HSMC_NFC_CYCLE0	0x18		/* NFC Address Cycle Zero */
+#define		ATMEL_HSMC_NFC_ADDR_CYCLE0	(0xff)
+
+#define ATMEL_HSMC_NFC_BANK	0x1c		/* NFC Bank Register */
+#define		ATMEL_HSMC_NFC_BANK0		(0 << 0)
+#define		ATMEL_HSMC_NFC_BANK1		(1 << 0)
+
+#define nfc_writel(addr, reg, value) \
+	writel((value), (addr) + ATMEL_HSMC_NFC_##reg)
+
+#define nfc_readl(addr, reg) \
+	readl_relaxed((addr) + ATMEL_HSMC_NFC_##reg)
+
+/*
+ * NFC Address Command definitions
+ */
+#define NFCADDR_CMD_CMD1	(0xff << 2)	/* Command for Cycle 1 */
+#define NFCADDR_CMD_CMD1_BIT_POS	2
+#define NFCADDR_CMD_CMD2	(0xff << 10)	/* Command for Cycle 2 */
+#define NFCADDR_CMD_CMD2_BIT_POS	10
+#define NFCADDR_CMD_VCMD2	(0x1 << 18)	/* Valid Cycle 2 Command */
+#define NFCADDR_CMD_ACYCLE	(0x7 << 19)	/* Number of Address required */
+#define		NFCADDR_CMD_ACYCLE_NONE		(0x0 << 19)
+#define		NFCADDR_CMD_ACYCLE_1		(0x1 << 19)
+#define		NFCADDR_CMD_ACYCLE_2		(0x2 << 19)
+#define		NFCADDR_CMD_ACYCLE_3		(0x3 << 19)
+#define		NFCADDR_CMD_ACYCLE_4		(0x4 << 19)
+#define		NFCADDR_CMD_ACYCLE_5		(0x5 << 19)
+#define NFCADDR_CMD_ACYCLE_BIT_POS	19
+#define NFCADDR_CMD_CSID	(0x7 << 22)	/* Chip Select Identifier */
+#define		NFCADDR_CMD_CSID_0		(0x0 << 22)
+#define		NFCADDR_CMD_CSID_1		(0x1 << 22)
+#define		NFCADDR_CMD_CSID_2		(0x2 << 22)
+#define		NFCADDR_CMD_CSID_3		(0x3 << 22)
+#define		NFCADDR_CMD_CSID_4		(0x4 << 22)
+#define		NFCADDR_CMD_CSID_5		(0x5 << 22)
+#define		NFCADDR_CMD_CSID_6		(0x6 << 22)
+#define		NFCADDR_CMD_CSID_7		(0x7 << 22)
+#define NFCADDR_CMD_DATAEN	(0x1 << 25)	/* Data Transfer Enable */
+#define NFCADDR_CMD_DATADIS	(0x0 << 25)	/* Data Transfer Disable */
+#define NFCADDR_CMD_NFCRD	(0x0 << 26)	/* NFC Read Enable */
+#define NFCADDR_CMD_NFCWR	(0x1 << 26)	/* NFC Write Enable */
+#define NFCADDR_CMD_NFCBUSY	(0x1 << 27)	/* NFC Busy */
+
+#define nfc_cmd_addr1234_writel(cmd, addr1234, nfc_base) \
+	writel((addr1234), (cmd) + nfc_base)
+
+#define nfc_cmd_readl(bitstatus, nfc_base) \
+	readl_relaxed((bitstatus) + nfc_base)
+
+#define NFC_TIME_OUT_MS		100
+#define	NFC_SRAM_BANK1_OFFSET	0x1200
+
+#endif
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 217459d..ae8dd7c 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -411,7 +411,7 @@ static int au1550nd_probe(struct platform_device *pdev)
 	struct resource *r;
 	int ret, cs;
 
-	pd = pdev->dev.platform_data;
+	pd = dev_get_platdata(&pdev->dev);
 	if (!pd) {
 		dev_err(&pdev->dev, "missing platform data\n");
 		return -ENODEV;
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 776df36..2c42e12 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -171,7 +171,7 @@ static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev)
 
 static struct bf5xx_nand_platform *to_nand_plat(struct platform_device *pdev)
 {
-	return pdev->dev.platform_data;
+	return dev_get_platdata(&pdev->dev);
 }
 
 /*
@@ -671,8 +671,6 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
 {
 	struct bf5xx_nand_info *info = to_nand_info(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	/* first thing we need to do is release all our mtds
 	 * and their partitions, then go through freeing the
 	 * resources used
@@ -832,7 +830,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
 out_err_nand_scan:
 	bf5xx_nand_dma_remove(info);
 out_err_hw_init:
-	platform_set_drvdata(pdev, NULL);
 	kfree(info);
 out_err_kzalloc:
 	peripheral_free_list(bfin_nfc_pin_req);
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index c3e15a5..b77a01e 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -530,7 +530,7 @@ MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
 static struct davinci_nand_pdata
 	*nand_davinci_get_pdata(struct platform_device *pdev)
 {
-	if (!pdev->dev.platform_data && pdev->dev.of_node) {
+	if (!dev_get_platdata(&pdev->dev) && pdev->dev.of_node) {
 		struct davinci_nand_pdata *pdata;
 		const char *mode;
 		u32 prop;
@@ -575,13 +575,13 @@ static struct davinci_nand_pdata
 			pdata->bbt_options = NAND_BBT_USE_FLASH;
 	}
 
-	return pdev->dev.platform_data;
+	return dev_get_platdata(&pdev->dev);
 }
 #else
 static struct davinci_nand_pdata
 	*nand_davinci_get_pdata(struct platform_device *pdev)
 {
-	return pdev->dev.platform_data;
+	return dev_get_platdata(&pdev->dev);
 }
 #endif
 
@@ -623,11 +623,14 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
 		goto err_nomem;
 	}
 
-	vaddr = devm_request_and_ioremap(&pdev->dev, res1);
-	base = devm_request_and_ioremap(&pdev->dev, res2);
-	if (!vaddr || !base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -EADDRNOTAVAIL;
+	vaddr = devm_ioremap_resource(&pdev->dev, res1);
+	if (IS_ERR(vaddr)) {
+		ret = PTR_ERR(vaddr);
+		goto err_ioremap;
+	}
+	base = devm_ioremap_resource(&pdev->dev, res2);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
 		goto err_ioremap;
 	}
 
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 0c8bb6b..2ed2bb3 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1520,7 +1520,7 @@ int denali_init(struct denali_nand_info *denali)
 	 * so just let controller do 15bit ECC for MLC and 8bit ECC for
 	 * SLC if possible.
 	 * */
-	if (denali->nand.cellinfo & 0xc &&
+	if (denali->nand.cellinfo & NAND_CI_CELLTYPE_MSK &&
 			(denali->mtd.oobsize > (denali->bbtskipbytes +
 			ECC_15BITS * (denali->mtd.writesize /
 			ECC_SECTOR_SIZE)))) {
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 81fa578..eaa3c29 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -46,13 +46,13 @@ static unsigned long __initdata doc_locations[] = {
 	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
 	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
 	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
-#else /*  CONFIG_MTD_DOCPROBE_HIGH */
+#else
 	0xc8000, 0xca000, 0xcc000, 0xce000,
 	0xd0000, 0xd2000, 0xd4000, 0xd6000,
 	0xd8000, 0xda000, 0xdc000, 0xde000,
 	0xe0000, 0xe2000, 0xe4000, 0xe6000,
 	0xe8000, 0xea000, 0xec000, 0xee000,
-#endif /*  CONFIG_MTD_DOCPROBE_HIGH */
+#endif
 #endif
 	0xffffffff };
 
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index fa25e7a..548db23 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -1093,7 +1093,6 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	struct nand_chip *nand = mtd->priv;
 	struct docg4_priv *doc = nand->priv;
 	struct nand_bbt_descr *bbtd = nand->badblock_pattern;
-	int block = (int)(ofs >> nand->bbt_erase_shift);
 	int page = (int)(ofs >> nand->page_shift);
 	uint32_t g4_addr = mtd_to_docg4_address(page, 0);
 
@@ -1108,9 +1107,6 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (buf == NULL)
 		return -ENOMEM;
 
-	/* update bbt in memory */
-	nand->bbt[block / 4] |= 0x01 << ((block & 0x03) * 2);
-
 	/* write bit-wise negation of pattern to oob buffer */
 	memset(nand->oob_poi, 0xff, mtd->oobsize);
 	for (i = 0; i < bbtd->len; i++)
@@ -1120,8 +1116,6 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	write_page_prologue(mtd, g4_addr);
 	docg4_write_page(mtd, nand, buf, 1);
 	ret = pageprog(mtd);
-	if (!ret)
-		mtd->ecc_stats.badblocks++;
 
 	kfree(buf);
 
@@ -1368,7 +1362,6 @@ static int __init probe_docg4(struct platform_device *pdev)
 		struct nand_chip *nand = mtd->priv;
 		struct docg4_priv *doc = nand->priv;
 		nand_release(mtd); /* deletes partitions and mtd devices */
-		platform_set_drvdata(pdev, NULL);
 		free_bch(doc->bch);
 		kfree(mtd);
 	}
@@ -1380,7 +1373,6 @@ static int __exit cleanup_docg4(struct platform_device *pdev)
 {
 	struct docg4_priv *doc = platform_get_drvdata(pdev);
 	nand_release(doc->mtd);
-	platform_set_drvdata(pdev, NULL);
 	free_bch(doc->bch);
 	kfree(doc->mtd);
 	iounmap(doc->virtadr);
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index f1f7f12..317a771 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -823,7 +823,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
 
 	/* set up nand options */
 	chip->bbt_options = NAND_BBT_USE_FLASH;
-
+	chip->options = NAND_NO_SUBPAGE_WRITE;
 
 	if (ioread32be(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) {
 		chip->read_byte = fsl_ifc_read_byte16;
@@ -908,7 +908,6 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
 
 	ifc_nand_ctrl->chips[priv->bank] = NULL;
 	dev_set_drvdata(priv->dev, NULL);
-	kfree(priv);
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 911e243..2a3b1b9 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -889,6 +889,24 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 	if (of_get_property(np, "nand-skip-bbtscan", NULL))
 		pdata->options = NAND_SKIP_BBTSCAN;
 
+	pdata->nand_timings = devm_kzalloc(&pdev->dev,
+				sizeof(*pdata->nand_timings), GFP_KERNEL);
+	if (!pdata->nand_timings) {
+		dev_err(&pdev->dev, "no memory for nand_timing\n");
+		return -ENOMEM;
+	}
+	of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
+						sizeof(*pdata->nand_timings));
+
+	/* Set default NAND bank to 0 */
+	pdata->bank = 0;
+	if (!of_property_read_u32(np, "bank", &val)) {
+		if (val > 3) {
+			dev_err(&pdev->dev, "invalid bank %u\n", val);
+			return -EINVAL;
+		}
+		pdata->bank = val;
+	}
 	return 0;
 }
 #else
@@ -1174,8 +1192,6 @@ static int fsmc_nand_remove(struct platform_device *pdev)
 {
 	struct fsmc_nand_data *host = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	if (host) {
 		nand_release(&host->mtd);
 
@@ -1190,7 +1206,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int fsmc_nand_suspend(struct device *dev)
 {
 	struct fsmc_nand_data *host = dev_get_drvdata(dev);
@@ -1210,9 +1226,9 @@ static int fsmc_nand_resume(struct device *dev)
 	}
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume);
-#endif
 
 #ifdef CONFIG_OF
 static const struct of_device_id fsmc_nand_id_table[] = {
@@ -1229,9 +1245,7 @@ static struct platform_driver fsmc_nand_driver = {
 		.owner = THIS_MODULE,
 		.name = "fsmc-nand",
 		.of_match_table = of_match_ptr(fsmc_nand_id_table),
-#ifdef CONFIG_PM
 		.pm = &fsmc_nand_pm_ops,
-#endif
 	},
 };
 
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 89065dd..e826f89 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -17,6 +17,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -86,59 +87,11 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 	gpio_nand_dosync(gpiomtd);
 }
 
-static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-	struct nand_chip *this = mtd->priv;
-
-	iowrite8_rep(this->IO_ADDR_W, buf, len);
-}
-
-static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len)
-{
-	struct nand_chip *this = mtd->priv;
-
-	ioread8_rep(this->IO_ADDR_R, buf, len);
-}
-
-static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf,
-				 int len)
-{
-	struct nand_chip *this = mtd->priv;
-
-	if (IS_ALIGNED((unsigned long)buf, 2)) {
-		iowrite16_rep(this->IO_ADDR_W, buf, len>>1);
-	} else {
-		int i;
-		unsigned short *ptr = (unsigned short *)buf;
-
-		for (i = 0; i < len; i += 2, ptr++)
-			writew(*ptr, this->IO_ADDR_W);
-	}
-}
-
-static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len)
-{
-	struct nand_chip *this = mtd->priv;
-
-	if (IS_ALIGNED((unsigned long)buf, 2)) {
-		ioread16_rep(this->IO_ADDR_R, buf, len>>1);
-	} else {
-		int i;
-		unsigned short *ptr = (unsigned short *)buf;
-
-		for (i = 0; i < len; i += 2, ptr++)
-			*ptr = readw(this->IO_ADDR_R);
-	}
-}
-
 static int gpio_nand_devready(struct mtd_info *mtd)
 {
 	struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
 
-	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
-		return gpio_get_value(gpiomtd->plat.gpio_rdy);
-
-	return 1;
+	return gpio_get_value(gpiomtd->plat.gpio_rdy);
 }
 
 #ifdef CONFIG_OF
@@ -153,6 +106,9 @@ static int gpio_nand_get_config_of(const struct device *dev,
 {
 	u32 val;
 
+	if (!dev->of_node)
+		return -ENODEV;
+
 	if (!of_property_read_u32(dev->of_node, "bank-width", &val)) {
 		if (val == 2) {
 			plat->options |= NAND_BUSWIDTH_16;
@@ -211,8 +167,8 @@ static inline int gpio_nand_get_config(const struct device *dev,
 	if (!ret)
 		return ret;
 
-	if (dev->platform_data) {
-		memcpy(plat, dev->platform_data, sizeof(*plat));
+	if (dev_get_platdata(dev)) {
+		memcpy(plat, dev_get_platdata(dev), sizeof(*plat));
 		return 0;
 	}
 
@@ -230,145 +186,100 @@ gpio_nand_get_io_sync(struct platform_device *pdev)
 	return platform_get_resource(pdev, IORESOURCE_MEM, 1);
 }
 
-static int gpio_nand_remove(struct platform_device *dev)
+static int gpio_nand_remove(struct platform_device *pdev)
 {
-	struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
-	struct resource *res;
+	struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
 
 	nand_release(&gpiomtd->mtd_info);
 
-	res = gpio_nand_get_io_sync(dev);
-	iounmap(gpiomtd->io_sync);
-	if (res)
-		release_mem_region(res->start, resource_size(res));
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	iounmap(gpiomtd->nand_chip.IO_ADDR_R);
-	release_mem_region(res->start, resource_size(res));
-
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
 		gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
 	gpio_set_value(gpiomtd->plat.gpio_nce, 1);
 
-	gpio_free(gpiomtd->plat.gpio_cle);
-	gpio_free(gpiomtd->plat.gpio_ale);
-	gpio_free(gpiomtd->plat.gpio_nce);
-	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
-		gpio_free(gpiomtd->plat.gpio_nwp);
-	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
-		gpio_free(gpiomtd->plat.gpio_rdy);
-
 	return 0;
 }
 
-static void __iomem *request_and_remap(struct resource *res, size_t size,
-					const char *name, int *err)
-{
-	void __iomem *ptr;
-
-	if (!request_mem_region(res->start, resource_size(res), name)) {
-		*err = -EBUSY;
-		return NULL;
-	}
-
-	ptr = ioremap(res->start, size);
-	if (!ptr) {
-		release_mem_region(res->start, resource_size(res));
-		*err = -ENOMEM;
-	}
-	return ptr;
-}
-
-static int gpio_nand_probe(struct platform_device *dev)
+static int gpio_nand_probe(struct platform_device *pdev)
 {
 	struct gpiomtd *gpiomtd;
-	struct nand_chip *this;
-	struct resource *res0, *res1;
+	struct nand_chip *chip;
+	struct resource *res;
 	struct mtd_part_parser_data ppdata = {};
 	int ret = 0;
 
-	if (!dev->dev.of_node && !dev->dev.platform_data)
-		return -EINVAL;
-
-	res0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res0)
+	if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev))
 		return -EINVAL;
 
-	gpiomtd = devm_kzalloc(&dev->dev, sizeof(*gpiomtd), GFP_KERNEL);
-	if (gpiomtd == NULL) {
-		dev_err(&dev->dev, "failed to create NAND MTD\n");
+	gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL);
+	if (!gpiomtd) {
+		dev_err(&pdev->dev, "failed to create NAND MTD\n");
 		return -ENOMEM;
 	}
 
-	this = &gpiomtd->nand_chip;
-	this->IO_ADDR_R = request_and_remap(res0, 2, "NAND", &ret);
-	if (!this->IO_ADDR_R) {
-		dev_err(&dev->dev, "unable to map NAND\n");
-		goto err_map;
-	}
+	chip = &gpiomtd->nand_chip;
 
-	res1 = gpio_nand_get_io_sync(dev);
-	if (res1) {
-		gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret);
-		if (!gpiomtd->io_sync) {
-			dev_err(&dev->dev, "unable to map sync NAND\n");
-			goto err_sync;
-		}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(chip->IO_ADDR_R))
+		return PTR_ERR(chip->IO_ADDR_R);
+
+	res = gpio_nand_get_io_sync(pdev);
+	if (res) {
+		gpiomtd->io_sync = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(gpiomtd->io_sync))
+			return PTR_ERR(gpiomtd->io_sync);
 	}
 
-	ret = gpio_nand_get_config(&dev->dev, &gpiomtd->plat);
+	ret = gpio_nand_get_config(&pdev->dev, &gpiomtd->plat);
 	if (ret)
-		goto err_nce;
+		return ret;
 
-	ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE");
+	ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce, "NAND NCE");
 	if (ret)
-		goto err_nce;
+		return ret;
 	gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) {
-		ret = gpio_request(gpiomtd->plat.gpio_nwp, "NAND NWP");
+		ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nwp,
+					"NAND NWP");
 		if (ret)
-			goto err_nwp;
-		gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
+			return ret;
 	}
-	ret = gpio_request(gpiomtd->plat.gpio_ale, "NAND ALE");
+
+	ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_ale, "NAND ALE");
 	if (ret)
-		goto err_ale;
+		return ret;
 	gpio_direction_output(gpiomtd->plat.gpio_ale, 0);
-	ret = gpio_request(gpiomtd->plat.gpio_cle, "NAND CLE");
+
+	ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_cle, "NAND CLE");
 	if (ret)
-		goto err_cle;
+		return ret;
 	gpio_direction_output(gpiomtd->plat.gpio_cle, 0);
+
 	if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) {
-		ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY");
+		ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_rdy,
+					"NAND RDY");
 		if (ret)
-			goto err_rdy;
+			return ret;
 		gpio_direction_input(gpiomtd->plat.gpio_rdy);
+		chip->dev_ready = gpio_nand_devready;
 	}
 
+	chip->IO_ADDR_W		= chip->IO_ADDR_R;
+	chip->ecc.mode		= NAND_ECC_SOFT;
+	chip->options		= gpiomtd->plat.options;
+	chip->chip_delay	= gpiomtd->plat.chip_delay;
+	chip->cmd_ctrl		= gpio_nand_cmd_ctrl;
 
-	this->IO_ADDR_W  = this->IO_ADDR_R;
-	this->ecc.mode   = NAND_ECC_SOFT;
-	this->options    = gpiomtd->plat.options;
-	this->chip_delay = gpiomtd->plat.chip_delay;
-
-	/* install our routines */
-	this->cmd_ctrl   = gpio_nand_cmd_ctrl;
-	this->dev_ready  = gpio_nand_devready;
+	gpiomtd->mtd_info.priv	= chip;
+	gpiomtd->mtd_info.owner	= THIS_MODULE;
 
-	if (this->options & NAND_BUSWIDTH_16) {
-		this->read_buf   = gpio_nand_readbuf16;
-		this->write_buf  = gpio_nand_writebuf16;
-	} else {
-		this->read_buf   = gpio_nand_readbuf;
-		this->write_buf  = gpio_nand_writebuf;
-	}
+	platform_set_drvdata(pdev, gpiomtd);
 
-	/* set the mtd private data for the nand driver */
-	gpiomtd->mtd_info.priv = this;
-	gpiomtd->mtd_info.owner = THIS_MODULE;
+	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+		gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
 
 	if (nand_scan(&gpiomtd->mtd_info, 1)) {
-		dev_err(&dev->dev, "no nand chips found?\n");
 		ret = -ENXIO;
 		goto err_wp;
 	}
@@ -377,38 +288,17 @@ static int gpio_nand_probe(struct platform_device *dev)
 		gpiomtd->plat.adjust_parts(&gpiomtd->plat,
 					   gpiomtd->mtd_info.size);
 
-	ppdata.of_node = dev->dev.of_node;
+	ppdata.of_node = pdev->dev.of_node;
 	ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata,
 					gpiomtd->plat.parts,
 					gpiomtd->plat.num_parts);
-	if (ret)
-		goto err_wp;
-	platform_set_drvdata(dev, gpiomtd);
-
-	return 0;
+	if (!ret)
+		return 0;
 
 err_wp:
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
 		gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
-	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
-		gpio_free(gpiomtd->plat.gpio_rdy);
-err_rdy:
-	gpio_free(gpiomtd->plat.gpio_cle);
-err_cle:
-	gpio_free(gpiomtd->plat.gpio_ale);
-err_ale:
-	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
-		gpio_free(gpiomtd->plat.gpio_nwp);
-err_nwp:
-	gpio_free(gpiomtd->plat.gpio_nce);
-err_nce:
-	iounmap(gpiomtd->io_sync);
-	if (res1)
-		release_mem_region(res1->start, resource_size(res1));
-err_sync:
-	iounmap(gpiomtd->nand_chip.IO_ADDR_R);
-	release_mem_region(res0->start, resource_size(res0));
-err_map:
+
 	return ret;
 }
 
@@ -417,6 +307,7 @@ static struct platform_driver gpio_nand_driver = {
 	.remove		= gpio_nand_remove,
 	.driver		= {
 		.name	= "gpio-nand",
+		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(gpio_nand_id_table),
 	},
 };
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 25ecfa1..c6b356c 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/mtd/partitions.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_mtd.h>
@@ -112,7 +111,132 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
 	return true;
 }
 
-int common_nfc_set_geometry(struct gpmi_nand_data *this)
+/*
+ * If we can get the ECC information from the nand chip, we do not
+ * need to calculate them ourselves.
+ *
+ * We may have available oob space in this case.
+ */
+static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+	struct mtd_info *mtd = &this->mtd;
+	struct nand_chip *chip = mtd->priv;
+	struct nand_oobfree *of = gpmi_hw_ecclayout.oobfree;
+	unsigned int block_mark_bit_offset;
+
+	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+		return false;
+
+	switch (chip->ecc_step_ds) {
+	case SZ_512:
+		geo->gf_len = 13;
+		break;
+	case SZ_1K:
+		geo->gf_len = 14;
+		break;
+	default:
+		dev_err(this->dev,
+			"unsupported nand chip. ecc bits : %d, ecc size : %d\n",
+			chip->ecc_strength_ds, chip->ecc_step_ds);
+		return false;
+	}
+	geo->ecc_chunk_size = chip->ecc_step_ds;
+	geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
+	if (!gpmi_check_ecc(this))
+		return false;
+
+	/* Keep the C >= O */
+	if (geo->ecc_chunk_size < mtd->oobsize) {
+		dev_err(this->dev,
+			"unsupported nand chip. ecc size: %d, oob size : %d\n",
+			chip->ecc_step_ds, mtd->oobsize);
+		return false;
+	}
+
+	/* The default value, see comment in the legacy_set_geometry(). */
+	geo->metadata_size = 10;
+
+	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+
+	/*
+	 * Now, the NAND chip with 2K page(data chunk is 512byte) shows below:
+	 *
+	 *    |                          P                            |
+	 *    |<----------------------------------------------------->|
+	 *    |                                                       |
+	 *    |                                        (Block Mark)   |
+	 *    |                      P'                      |      | |     |
+	 *    |<-------------------------------------------->|  D   | |  O' |
+	 *    |                                              |<---->| |<--->|
+	 *    V                                              V      V V     V
+	 *    +---+----------+-+----------+-+----------+-+----------+-+-----+
+	 *    | M |   data   |E|   data   |E|   data   |E|   data   |E|     |
+	 *    +---+----------+-+----------+-+----------+-+----------+-+-----+
+	 *                                                   ^              ^
+	 *                                                   |      O       |
+	 *                                                   |<------------>|
+	 *                                                   |              |
+	 *
+	 *	P : the page size for BCH module.
+	 *	E : The ECC strength.
+	 *	G : the length of Galois Field.
+	 *	N : The chunk count of per page.
+	 *	M : the metasize of per page.
+	 *	C : the ecc chunk size, aka the "data" above.
+	 *	P': the nand chip's page size.
+	 *	O : the nand chip's oob size.
+	 *	O': the free oob.
+	 *
+	 *	The formula for P is :
+	 *
+	 *	            E * G * N
+	 *	       P = ------------ + P' + M
+	 *                      8
+	 *
+	 * The position of block mark moves forward in the ECC-based view
+	 * of page, and the delta is:
+	 *
+	 *                   E * G * (N - 1)
+	 *             D = (---------------- + M)
+	 *                          8
+	 *
+	 * Please see the comment in legacy_set_geometry().
+	 * With the condition C >= O , we still can get same result.
+	 * So the bit position of the physical block mark within the ECC-based
+	 * view of the page is :
+	 *             (P' - D) * 8
+	 */
+	geo->page_size = mtd->writesize + geo->metadata_size +
+		(geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8;
+
+	/* The available oob size we have. */
+	if (geo->page_size < mtd->writesize + mtd->oobsize) {
+		of->offset = geo->page_size - mtd->writesize;
+		of->length = mtd->oobsize - of->offset;
+		mtd->oobavail = gpmi_hw_ecclayout.oobavail = of->length;
+	}
+
+	geo->payload_size = mtd->writesize;
+
+	geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
+	geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
+				+ ALIGN(geo->ecc_chunk_count, 4);
+
+	if (!this->swap_block_mark)
+		return true;
+
+	/* For bit swap. */
+	block_mark_bit_offset = mtd->writesize * 8 -
+		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+				+ geo->metadata_size * 8);
+
+	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
+	return true;
+}
+
+static int legacy_set_geometry(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
 	struct mtd_info *mtd = &this->mtd;
@@ -224,6 +348,11 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
 	return 0;
 }
 
+int common_nfc_set_geometry(struct gpmi_nand_data *this)
+{
+	return set_geometry_by_ecc_info(this) ? 0 : legacy_set_geometry(this);
+}
+
 struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
 {
 	int chipnr = this->current_chip;
@@ -355,7 +484,7 @@ static int acquire_register_block(struct gpmi_nand_data *this,
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
 	if (!r) {
 		pr_err("Can't get resource for %s\n", res_name);
-		return -ENXIO;
+		return -ENODEV;
 	}
 
 	p = ioremap(r->start, resource_size(r));
@@ -396,7 +525,7 @@ static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
 	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
 	if (!r) {
 		pr_err("Can't get resource for %s\n", res_name);
-		return -ENXIO;
+		return -ENODEV;
 	}
 
 	err = request_irq(r->start, irq_h, 0, res_name, this);
@@ -473,12 +602,14 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 	struct resources *r = &this->resources;
 	char **extra_clks = NULL;
 	struct clk *clk;
-	int i;
+	int err, i;
 
 	/* The main clock is stored in the first. */
 	r->clock[0] = clk_get(this->dev, "gpmi_io");
-	if (IS_ERR(r->clock[0]))
+	if (IS_ERR(r->clock[0])) {
+		err = PTR_ERR(r->clock[0]);
 		goto err_clock;
+	}
 
 	/* Get extra clocks */
 	if (GPMI_IS_MX6Q(this))
@@ -491,8 +622,10 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 			break;
 
 		clk = clk_get(this->dev, extra_clks[i - 1]);
-		if (IS_ERR(clk))
+		if (IS_ERR(clk)) {
+			err = PTR_ERR(clk);
 			goto err_clock;
+		}
 
 		r->clock[i] = clk;
 	}
@@ -511,12 +644,11 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 err_clock:
 	dev_dbg(this->dev, "failed in finding the clocks.\n");
 	gpmi_put_clks(this);
-	return -ENOMEM;
+	return err;
 }
 
 static int acquire_resources(struct gpmi_nand_data *this)
 {
-	struct pinctrl *pinctrl;
 	int ret;
 
 	ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME);
@@ -535,19 +667,12 @@ static int acquire_resources(struct gpmi_nand_data *this)
 	if (ret)
 		goto exit_dma_channels;
 
-	pinctrl = devm_pinctrl_get_select_default(&this->pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto exit_pin;
-	}
-
 	ret = gpmi_get_clks(this);
 	if (ret)
 		goto exit_clock;
 	return 0;
 
 exit_clock:
-exit_pin:
 	release_dma_channels(this);
 exit_dma_channels:
 	release_bch_irq(this);
@@ -1153,43 +1278,31 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct gpmi_nand_data *this = chip->priv;
-	int block, ret = 0;
+	int ret = 0;
 	uint8_t *block_mark;
 	int column, page, status, chipnr;
 
-	/* Get block number */
-	block = (int)(ofs >> chip->bbt_erase_shift);
-	if (chip->bbt)
-		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+	chipnr = (int)(ofs >> chip->chip_shift);
+	chip->select_chip(mtd, chipnr);
 
-	/* Do we have a flash based bad block table ? */
-	if (chip->bbt_options & NAND_BBT_USE_FLASH)
-		ret = nand_update_bbt(mtd, ofs);
-	else {
-		chipnr = (int)(ofs >> chip->chip_shift);
-		chip->select_chip(mtd, chipnr);
+	column = this->swap_block_mark ? mtd->writesize : 0;
 
-		column = this->swap_block_mark ? mtd->writesize : 0;
+	/* Write the block mark. */
+	block_mark = this->data_buffer_dma;
+	block_mark[0] = 0; /* bad block marker */
 
-		/* Write the block mark. */
-		block_mark = this->data_buffer_dma;
-		block_mark[0] = 0; /* bad block marker */
+	/* Shift to get page */
+	page = (int)(ofs >> chip->page_shift);
 
-		/* Shift to get page */
-		page = (int)(ofs >> chip->page_shift);
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page);
+	chip->write_buf(mtd, block_mark, 1);
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 
-		chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page);
-		chip->write_buf(mtd, block_mark, 1);
-		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	status = chip->waitfunc(mtd, chip);
+	if (status & NAND_STATUS_FAIL)
+		ret = -EIO;
 
-		status = chip->waitfunc(mtd, chip);
-		if (status & NAND_STATUS_FAIL)
-			ret = -EIO;
-
-		chip->select_chip(mtd, -1);
-	}
-	if (!ret)
-		mtd->ecc_stats.badblocks++;
+	chip->select_chip(mtd, -1);
 
 	return ret;
 }
@@ -1573,19 +1686,19 @@ static const struct platform_device_id gpmi_ids[] = {
 	{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
 	{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
 	{ .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, },
-	{},
+	{}
 };
 
 static const struct of_device_id gpmi_nand_id_table[] = {
 	{
 		.compatible = "fsl,imx23-gpmi-nand",
-		.data = (void *)&gpmi_ids[IS_MX23]
+		.data = (void *)&gpmi_ids[IS_MX23],
 	}, {
 		.compatible = "fsl,imx28-gpmi-nand",
-		.data = (void *)&gpmi_ids[IS_MX28]
+		.data = (void *)&gpmi_ids[IS_MX28],
 	}, {
 		.compatible = "fsl,imx6q-gpmi-nand",
-		.data = (void *)&gpmi_ids[IS_MX6Q]
+		.data = (void *)&gpmi_ids[IS_MX6Q],
 	}, {}
 };
 MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
@@ -1601,7 +1714,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
 		pdev->id_entry = of_id->data;
 	} else {
 		pr_err("Failed to find the right device id.\n");
-		return -ENOMEM;
+		return -ENODEV;
 	}
 
 	this = kzalloc(sizeof(*this), GFP_KERNEL);
@@ -1633,7 +1746,6 @@ static int gpmi_nand_probe(struct platform_device *pdev)
 exit_nfc_init:
 	release_resources(this);
 exit_acquire_resources:
-	platform_set_drvdata(pdev, NULL);
 	dev_err(this->dev, "driver registration failed: %d\n", ret);
 	kfree(this);
 
@@ -1646,7 +1758,6 @@ static int gpmi_nand_remove(struct platform_device *pdev)
 
 	gpmi_nfc_exit(this);
 	release_resources(this);
-	platform_set_drvdata(pdev, NULL);
 	kfree(this);
 	return 0;
 }
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index b76460e..a264b88 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -411,7 +411,7 @@ static int jz_nand_probe(struct platform_device *pdev)
 	struct jz_nand *nand;
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
-	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	size_t chipnr, bank_idx;
 	uint8_t nand_maf_id = 0, nand_dev_id = 0;
 
@@ -538,7 +538,6 @@ err_unclaim_banks:
 err_gpio_busy:
 	if (pdata && gpio_is_valid(pdata->busy_gpio))
 		gpio_free(pdata->busy_gpio);
-	platform_set_drvdata(pdev, NULL);
 err_iounmap_mmio:
 	jz_nand_iounmap_resource(nand->mem, nand->base);
 err_free:
@@ -549,7 +548,7 @@ err_free:
 static int jz_nand_remove(struct platform_device *pdev)
 {
 	struct jz_nand *nand = platform_get_drvdata(pdev);
-	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	size_t i;
 
 	nand_release(&nand->mtd);
@@ -570,7 +569,6 @@ static int jz_nand_remove(struct platform_device *pdev)
 
 	jz_nand_iounmap_resource(nand->mem, nand->base);
 
-	platform_set_drvdata(pdev, NULL);
 	kfree(nand);
 
 	return 0;
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index fd1df5e..f4dd2a8 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -696,7 +696,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	}
 	lpc32xx_wp_disable(host);
 
-	host->pdata = pdev->dev.platform_data;
+	host->pdata = dev_get_platdata(&pdev->dev);
 
 	nand_chip->priv = host;		/* link the private data structures */
 	mtd->priv = nand_chip;
@@ -828,7 +828,6 @@ err_exit3:
 err_exit2:
 	clk_disable(host->clk);
 	clk_put(host->clk);
-	platform_set_drvdata(pdev, NULL);
 err_exit1:
 	lpc32xx_wp_enable(host);
 	gpio_free(host->ncfg->wp_gpio);
@@ -851,7 +850,6 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
 
 	clk_disable(host->clk);
 	clk_put(host->clk);
-	platform_set_drvdata(pdev, NULL);
 
 	lpc32xx_wp_enable(host);
 	gpio_free(host->ncfg->wp_gpio);
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index be94ed5..add7570 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -798,7 +798,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	}
 	lpc32xx_wp_disable(host);
 
-	host->pdata = pdev->dev.platform_data;
+	host->pdata = dev_get_platdata(&pdev->dev);
 
 	mtd = &host->mtd;
 	chip = &host->nand_chip;
@@ -936,7 +936,6 @@ err_exit3:
 err_exit2:
 	clk_disable(host->clk);
 	clk_put(host->clk);
-	platform_set_drvdata(pdev, NULL);
 err_exit1:
 	lpc32xx_wp_enable(host);
 	gpio_free(host->ncfg->wp_gpio);
@@ -963,7 +962,6 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
 
 	clk_disable(host->clk);
 	clk_put(host->clk);
-	platform_set_drvdata(pdev, NULL);
 	lpc32xx_wp_enable(host);
 	gpio_free(host->ncfg->wp_gpio);
 
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 07e5784..a99ff1d 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -1432,7 +1432,8 @@ static int mxcnd_probe(struct platform_device *pdev)
 
 	err = mxcnd_probe_dt(host);
 	if (err > 0) {
-		struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+		struct mxc_nand_platform_data *pdata =
+					dev_get_platdata(&pdev->dev);
 		if (pdata) {
 			host->pdata = *pdata;
 			host->devtype_data = (struct mxc_nand_devtype_data *)
@@ -1446,8 +1447,6 @@ static int mxcnd_probe(struct platform_device *pdev)
 
 	if (host->devtype_data->needs_ip) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!res)
-			return -ENODEV;
 		host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR(host->regs_ip))
 			return PTR_ERR(host->regs_ip);
@@ -1457,9 +1456,6 @@ static int mxcnd_probe(struct platform_device *pdev)
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	}
 
-	if (!res)
-		return -ENODEV;
-
 	host->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(host->base))
 		return PTR_ERR(host->base);
@@ -1578,8 +1574,6 @@ static int mxcnd_remove(struct platform_device *pdev)
 {
 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	nand_release(&host->mtd);
 
 	return 0;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index dfcd0a5..8f04fb0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -211,11 +211,9 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
  */
 static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	int i;
 	struct nand_chip *chip = mtd->priv;
 
-	for (i = 0; i < len; i++)
-		writeb(buf[i], chip->IO_ADDR_W);
+	iowrite8_rep(chip->IO_ADDR_W, buf, len);
 }
 
 /**
@@ -228,11 +226,9 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  */
 static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	int i;
 	struct nand_chip *chip = mtd->priv;
 
-	for (i = 0; i < len; i++)
-		buf[i] = readb(chip->IO_ADDR_R);
+	ioread8_rep(chip->IO_ADDR_R, buf, len);
 }
 
 /**
@@ -245,14 +241,10 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
  */
 static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	int i;
 	struct nand_chip *chip = mtd->priv;
 	u16 *p = (u16 *) buf;
-	len >>= 1;
-
-	for (i = 0; i < len; i++)
-		writew(p[i], chip->IO_ADDR_W);
 
+	iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
 }
 
 /**
@@ -265,13 +257,10 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
  */
 static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	int i;
 	struct nand_chip *chip = mtd->priv;
 	u16 *p = (u16 *) buf;
-	len >>= 1;
 
-	for (i = 0; i < len; i++)
-		p[i] = readw(chip->IO_ADDR_R);
+	ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
 }
 
 /**
@@ -335,28 +324,70 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 }
 
 /**
- * nand_default_block_markbad - [DEFAULT] mark a block bad
+ * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
  * @mtd: MTD device structure
  * @ofs: offset from device start
  *
  * This is the default implementation, which can be overridden by a hardware
- * specific driver. We try operations in the following order, according to our
- * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
+ * specific driver. It provides the details for writing a bad block marker to a
+ * block.
+ */
+static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops ops;
+	uint8_t buf[2] = { 0, 0 };
+	int ret = 0, res, i = 0;
+
+	ops.datbuf = NULL;
+	ops.oobbuf = buf;
+	ops.ooboffs = chip->badblockpos;
+	if (chip->options & NAND_BUSWIDTH_16) {
+		ops.ooboffs &= ~0x01;
+		ops.len = ops.ooblen = 2;
+	} else {
+		ops.len = ops.ooblen = 1;
+	}
+	ops.mode = MTD_OPS_PLACE_OOB;
+
+	/* Write to first/last page(s) if necessary */
+	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+		ofs += mtd->erasesize - mtd->writesize;
+	do {
+		res = nand_do_write_oob(mtd, ofs, &ops);
+		if (!ret)
+			ret = res;
+
+		i++;
+		ofs += mtd->writesize;
+	} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+
+	return ret;
+}
+
+/**
+ * nand_block_markbad_lowlevel - mark a block bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ *
+ * This function performs the generic NAND bad block marking steps (i.e., bad
+ * block table(s) and/or marker(s)). We only allow the hardware driver to
+ * specify how to write bad block markers to OOB (chip->block_markbad).
+ *
+ * We try operations in the following order:
  *  (1) erase the affected block, to allow OOB marker to be written cleanly
- *  (2) update in-memory BBT
- *  (3) write bad block marker to OOB area of affected block
- *  (4) update flash-based BBT
- * Note that we retain the first error encountered in (3) or (4), finish the
+ *  (2) write bad block marker to OOB area of affected block (unless flag
+ *      NAND_BBT_NO_OOB_BBM is present)
+ *  (3) update the BBT
+ * Note that we retain the first error encountered in (2) or (3), finish the
  * procedures, and dump the error in the end.
 */
-static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 {
 	struct nand_chip *chip = mtd->priv;
-	uint8_t buf[2] = { 0, 0 };
-	int block, res, ret = 0, i = 0;
-	int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
+	int res, ret = 0;
 
-	if (write_oob) {
+	if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
 		struct erase_info einfo;
 
 		/* Attempt erase before marking OOB */
@@ -365,50 +396,16 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 		einfo.addr = ofs;
 		einfo.len = 1 << chip->phys_erase_shift;
 		nand_erase_nand(mtd, &einfo, 0);
-	}
-
-	/* Get block number */
-	block = (int)(ofs >> chip->bbt_erase_shift);
-	/* Mark block bad in memory-based BBT */
-	if (chip->bbt)
-		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
-
-	/* Write bad block marker to OOB */
-	if (write_oob) {
-		struct mtd_oob_ops ops;
-		loff_t wr_ofs = ofs;
 
+		/* Write bad block marker to OOB */
 		nand_get_device(mtd, FL_WRITING);
-
-		ops.datbuf = NULL;
-		ops.oobbuf = buf;
-		ops.ooboffs = chip->badblockpos;
-		if (chip->options & NAND_BUSWIDTH_16) {
-			ops.ooboffs &= ~0x01;
-			ops.len = ops.ooblen = 2;
-		} else {
-			ops.len = ops.ooblen = 1;
-		}
-		ops.mode = MTD_OPS_PLACE_OOB;
-
-		/* Write to first/last page(s) if necessary */
-		if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
-			wr_ofs += mtd->erasesize - mtd->writesize;
-		do {
-			res = nand_do_write_oob(mtd, wr_ofs, &ops);
-			if (!ret)
-				ret = res;
-
-			i++;
-			wr_ofs += mtd->writesize;
-		} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
-
+		ret = chip->block_markbad(mtd, ofs);
 		nand_release_device(mtd);
 	}
 
-	/* Update flash-based bad block table */
-	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
-		res = nand_update_bbt(mtd, ofs);
+	/* Mark block bad in BBT */
+	if (chip->bbt) {
+		res = nand_markbad_bbt(mtd, ofs);
 		if (!ret)
 			ret = res;
 	}
@@ -2694,7 +2691,6 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
  */
 static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
 	int ret;
 
 	ret = nand_block_isbad(mtd, ofs);
@@ -2705,7 +2701,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 		return ret;
 	}
 
-	return chip->block_markbad(mtd, ofs);
+	return nand_block_markbad_lowlevel(mtd, ofs);
 }
 
 /**
@@ -2720,7 +2716,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 {
 	int status;
 
-	if (!chip->onfi_version)
+	if (!chip->onfi_version ||
+	    !(le16_to_cpu(chip->onfi_params.opt_cmd)
+	      & ONFI_OPT_CMD_SET_GET_FEATURES))
 		return -EINVAL;
 
 	chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
@@ -2741,7 +2739,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
 			int addr, uint8_t *subfeature_param)
 {
-	if (!chip->onfi_version)
+	if (!chip->onfi_version ||
+	    !(le16_to_cpu(chip->onfi_params.opt_cmd)
+	      & ONFI_OPT_CMD_SET_GET_FEATURES))
 		return -EINVAL;
 
 	/* clear the sub feature parameters */
@@ -2793,7 +2793,9 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 
 	if (!chip->select_chip)
 		chip->select_chip = nand_select_chip;
-	if (!chip->read_byte)
+
+	/* If called twice, pointers that depend on busw may need to be reset */
+	if (!chip->read_byte || chip->read_byte == nand_read_byte)
 		chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
 	if (!chip->read_word)
 		chip->read_word = nand_read_word;
@@ -2801,9 +2803,9 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 		chip->block_bad = nand_block_bad;
 	if (!chip->block_markbad)
 		chip->block_markbad = nand_default_block_markbad;
-	if (!chip->write_buf)
+	if (!chip->write_buf || chip->write_buf == nand_write_buf)
 		chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
-	if (!chip->read_buf)
+	if (!chip->read_buf || chip->read_buf == nand_read_buf)
 		chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
 	if (!chip->scan_bbt)
 		chip->scan_bbt = nand_default_bbt;
@@ -2846,6 +2848,78 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
 	return crc;
 }
 
+/* Parse the Extended Parameter Page. */
+static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
+		struct nand_chip *chip, struct nand_onfi_params *p)
+{
+	struct onfi_ext_param_page *ep;
+	struct onfi_ext_section *s;
+	struct onfi_ext_ecc_info *ecc;
+	uint8_t *cursor;
+	int ret = -EINVAL;
+	int len;
+	int i;
+
+	len = le16_to_cpu(p->ext_param_page_length) * 16;
+	ep = kmalloc(len, GFP_KERNEL);
+	if (!ep) {
+		ret = -ENOMEM;
+		goto ext_out;
+	}
+
+	/* Send our own NAND_CMD_PARAM. */
+	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
+
+	/* Use the Change Read Column command to skip the ONFI param pages. */
+	chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
+			sizeof(*p) * p->num_of_param_pages , -1);
+
+	/* Read out the Extended Parameter Page. */
+	chip->read_buf(mtd, (uint8_t *)ep, len);
+	if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2)
+		!= le16_to_cpu(ep->crc))) {
+		pr_debug("fail in the CRC.\n");
+		goto ext_out;
+	}
+
+	/*
+	 * Check the signature.
+	 * Do not strictly follow the ONFI spec, maybe changed in future.
+	 */
+	if (strncmp(ep->sig, "EPPS", 4)) {
+		pr_debug("The signature is invalid.\n");
+		goto ext_out;
+	}
+
+	/* find the ECC section. */
+	cursor = (uint8_t *)(ep + 1);
+	for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) {
+		s = ep->sections + i;
+		if (s->type == ONFI_SECTION_TYPE_2)
+			break;
+		cursor += s->length * 16;
+	}
+	if (i == ONFI_EXT_SECTION_MAX) {
+		pr_debug("We can not find the ECC section.\n");
+		goto ext_out;
+	}
+
+	/* get the info we want. */
+	ecc = (struct onfi_ext_ecc_info *)cursor;
+
+	if (ecc->codeword_size) {
+		chip->ecc_strength_ds = ecc->ecc_bits;
+		chip->ecc_step_ds = 1 << ecc->codeword_size;
+	}
+
+	pr_info("ONFI extended param page detected.\n");
+	return 0;
+
+ext_out:
+	kfree(ep);
+	return ret;
+}
+
 /*
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
@@ -2907,9 +2981,31 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
 	chip->chipsize = le32_to_cpu(p->blocks_per_lun);
 	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
-	*busw = 0;
-	if (le16_to_cpu(p->features) & 1)
+
+	if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
 		*busw = NAND_BUSWIDTH_16;
+	else
+		*busw = 0;
+
+	if (p->ecc_bits != 0xff) {
+		chip->ecc_strength_ds = p->ecc_bits;
+		chip->ecc_step_ds = 512;
+	} else if (chip->onfi_version >= 21 &&
+		(onfi_feature(chip) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
+
+		/*
+		 * The nand_flash_detect_ext_param_page() uses the
+		 * Change Read Column command which maybe not supported
+		 * by the chip->cmdfunc. So try to update the chip->cmdfunc
+		 * now. We do not replace user supplied command function.
+		 */
+		if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
+			chip->cmdfunc = nand_command_lp;
+
+		/* The Extended Parameter Page is supported since ONFI 2.1. */
+		if (nand_flash_detect_ext_param_page(mtd, chip, p))
+			pr_info("Failed to detect the extended param page.\n");
+	}
 
 	pr_info("ONFI flash detected\n");
 	return 1;
@@ -3086,6 +3182,22 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		extid >>= 2;
 		/* Get buswidth information */
 		*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+
+		/*
+		 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+		 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+		 * follows:
+		 * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
+		 *                         110b -> 24nm
+		 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
+		 */
+		if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
+				!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+				(id_data[5] & 0x7) == 0x6 /* 24nm */ &&
+				!(id_data[4] & 0x80) /* !BENAND */) {
+			mtd->oobsize = 32 * mtd->writesize >> 9;
+		}
+
 	}
 }
 
@@ -3172,6 +3284,8 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->cellinfo = id_data[2];
 		chip->chipsize = (uint64_t)type->chipsize << 20;
 		chip->options |= type->options;
+		chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
+		chip->ecc_step_ds = NAND_ECC_STEP(type);
 
 		*busw = type->options & NAND_BUSWIDTH_16;
 
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 2672643..bc06196 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -71,6 +71,30 @@
 #include <linux/export.h>
 #include <linux/string.h>
 
+#define BBT_BLOCK_GOOD		0x00
+#define BBT_BLOCK_WORN		0x01
+#define BBT_BLOCK_RESERVED	0x02
+#define BBT_BLOCK_FACTORY_BAD	0x03
+
+#define BBT_ENTRY_MASK		0x03
+#define BBT_ENTRY_SHIFT		2
+
+static int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
+
+static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
+{
+	uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
+	entry >>= (block & BBT_ENTRY_MASK) * 2;
+	return entry & BBT_ENTRY_MASK;
+}
+
+static inline void bbt_mark_entry(struct nand_chip *chip, int block,
+		uint8_t mark)
+{
+	uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2);
+	chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk;
+}
+
 static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
 {
 	if (memcmp(buf, td->pattern, td->len))
@@ -86,33 +110,17 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
  * @td: search pattern descriptor
  *
  * Check for a pattern at the given place. Used to search bad block tables and
- * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
- * all bytes except the pattern area contain 0xff.
+ * good / bad block identifiers.
  */
 static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
-	int end = 0;
-	uint8_t *p = buf;
-
 	if (td->options & NAND_BBT_NO_OOB)
 		return check_pattern_no_oob(buf, td);
 
-	end = paglen + td->offs;
-	if (td->options & NAND_BBT_SCANEMPTY)
-		if (memchr_inv(p, 0xff, end))
-			return -1;
-	p += end;
-
 	/* Compare the pattern */
-	if (memcmp(p, td->pattern, td->len))
+	if (memcmp(buf + paglen + td->offs, td->pattern, td->len))
 		return -1;
 
-	if (td->options & NAND_BBT_SCANEMPTY) {
-		p += td->len;
-		end += td->len;
-		if (memchr_inv(p, 0xff, len - end))
-			return -1;
-	}
 	return 0;
 }
 
@@ -159,7 +167,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
  * @page: the starting page
  * @num: the number of bbt descriptors to read
  * @td: the bbt describtion table
- * @offs: offset in the memory table
+ * @offs: block number offset in the table
  *
  * Read the bad block table starting from page.
  */
@@ -209,14 +217,16 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		/* Analyse data */
 		for (i = 0; i < len; i++) {
 			uint8_t dat = buf[i];
-			for (j = 0; j < 8; j += bits, act += 2) {
+			for (j = 0; j < 8; j += bits, act++) {
 				uint8_t tmp = (dat >> j) & msk;
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
 					pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
-						 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
-					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
+						 (loff_t)(offs + act) <<
+						 this->bbt_erase_shift);
+					bbt_mark_entry(this, offs + act,
+							BBT_BLOCK_RESERVED);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
@@ -225,12 +235,15 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				 * move this message to pr_debug.
 				 */
 				pr_info("nand_read_bbt: bad block at 0x%012llx\n",
-					 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+					 (loff_t)(offs + act) <<
+					 this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
-					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
+					bbt_mark_entry(this, offs + act,
+							BBT_BLOCK_FACTORY_BAD);
 				else
-					this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
+					bbt_mark_entry(this, offs + act,
+							BBT_BLOCK_WORN);
 				mtd->ecc_stats.badblocks++;
 			}
 		}
@@ -265,7 +278,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 					td, offs);
 			if (res)
 				return res;
-			offs += this->chipsize >> (this->bbt_erase_shift + 2);
+			offs += this->chipsize >> this->bbt_erase_shift;
 		}
 	} else {
 		res = read_bbt(mtd, buf, td->pages[0],
@@ -478,22 +491,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	else
 		numpages = 1;
 
-	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
-		/* We need only read few bytes from the OOB area */
-		scanlen = 0;
-		readlen = bd->len;
-	} else {
-		/* Full page content should be read */
-		scanlen = mtd->writesize + mtd->oobsize;
-		readlen = numpages * mtd->writesize;
-	}
+	/* We need only read few bytes from the OOB area */
+	scanlen = 0;
+	readlen = bd->len;
 
 	if (chip == -1) {
-		/*
-		 * Note that numblocks is 2 * (real numblocks) here, see i+=2
-		 * below as it makes shifting and masking less painful
-		 */
-		numblocks = mtd->size >> (this->bbt_erase_shift - 1);
+		numblocks = mtd->size >> this->bbt_erase_shift;
 		startblock = 0;
 		from = 0;
 	} else {
@@ -502,16 +505,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
-		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
+		numblocks = this->chipsize >> this->bbt_erase_shift;
 		startblock = chip * numblocks;
 		numblocks += startblock;
-		from = (loff_t)startblock << (this->bbt_erase_shift - 1);
+		from = (loff_t)startblock << this->bbt_erase_shift;
 	}
 
 	if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * numpages);
 
-	for (i = startblock; i < numblocks;) {
+	for (i = startblock; i < numblocks; i++) {
 		int ret;
 
 		BUG_ON(bd->options & NAND_BBT_NO_OOB);
@@ -526,13 +529,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 			return ret;
 
 		if (ret) {
-			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
+			bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD);
 			pr_warn("Bad eraseblock %d at 0x%012llx\n",
-				i >> 1, (unsigned long long)from);
+				i, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
 
-		i += 2;
 		from += (1 << this->bbt_erase_shift);
 	}
 	return 0;
@@ -655,9 +657,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 {
 	struct nand_chip *this = mtd->priv;
 	struct erase_info einfo;
-	int i, j, res, chip = 0;
+	int i, res, chip = 0;
 	int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
-	int nrchips, bbtoffs, pageoffs, ooboffs;
+	int nrchips, pageoffs, ooboffs;
 	uint8_t msk[4];
 	uint8_t rcode = td->reserved_block_code;
 	size_t retlen, len = 0;
@@ -713,10 +715,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		for (i = 0; i < td->maxblocks; i++) {
 			int block = startblock + dir * i;
 			/* Check, if the block is bad */
-			switch ((this->bbt[block >> 2] >>
-				 (2 * (block & 0x03))) & 0x03) {
-			case 0x01:
-			case 0x03:
+			switch (bbt_get_entry(this, block)) {
+			case BBT_BLOCK_WORN:
+			case BBT_BLOCK_FACTORY_BAD:
 				continue;
 			}
 			page = block <<
@@ -748,8 +749,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		default: return -EINVAL;
 		}
 
-		bbtoffs = chip * (numblocks >> 2);
-
 		to = ((loff_t)page) << this->page_shift;
 
 		/* Must we save the block contents? */
@@ -814,16 +813,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			buf[ooboffs + td->veroffs] = td->version[chip];
 
 		/* Walk through the memory table */
-		for (i = 0; i < numblocks;) {
+		for (i = 0; i < numblocks; i++) {
 			uint8_t dat;
-			dat = this->bbt[bbtoffs + (i >> 2)];
-			for (j = 0; j < 4; j++, i++) {
-				int sftcnt = (i << (3 - sft)) & sftmsk;
-				/* Do not store the reserved bbt blocks! */
-				buf[offs + (i >> sft)] &=
-					~(msk[dat & 0x03] << sftcnt);
-				dat >>= 2;
-			}
+			int sftcnt = (i << (3 - sft)) & sftmsk;
+			dat = bbt_get_entry(this, chip * numblocks + i);
+			/* Do not store the reserved bbt blocks! */
+			buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt);
 		}
 
 		memset(&einfo, 0, sizeof(einfo));
@@ -865,7 +860,6 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
 {
 	struct nand_chip *this = mtd->priv;
 
-	bd->options &= ~NAND_BBT_SCANEMPTY;
 	return create_bbt(mtd, this->buffers->databuf, bd, -1);
 }
 
@@ -1009,7 +1003,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
 	struct nand_chip *this = mtd->priv;
 	int i, j, chips, block, nrblocks, update;
-	uint8_t oldval, newval;
+	uint8_t oldval;
 
 	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
@@ -1026,12 +1020,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 			if (td->pages[i] == -1)
 				continue;
 			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
-			block <<= 1;
-			oldval = this->bbt[(block >> 3)];
-			newval = oldval | (0x2 << (block & 0x06));
-			this->bbt[(block >> 3)] = newval;
-			if ((oldval != newval) && td->reserved_block_code)
-				nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1));
+			oldval = bbt_get_entry(this, block);
+			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
+			if ((oldval != BBT_BLOCK_RESERVED) &&
+					td->reserved_block_code)
+				nand_update_bbt(mtd, (loff_t)block <<
+						this->bbt_erase_shift);
 			continue;
 		}
 		update = 0;
@@ -1039,14 +1033,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 			block = ((i + 1) * nrblocks) - td->maxblocks;
 		else
 			block = i * nrblocks;
-		block <<= 1;
 		for (j = 0; j < td->maxblocks; j++) {
-			oldval = this->bbt[(block >> 3)];
-			newval = oldval | (0x2 << (block & 0x06));
-			this->bbt[(block >> 3)] = newval;
-			if (oldval != newval)
+			oldval = bbt_get_entry(this, block);
+			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
+			if (oldval != BBT_BLOCK_RESERVED)
 				update = 1;
-			block += 2;
+			block++;
 		}
 		/*
 		 * If we want reserved blocks to be recorded to flash, and some
@@ -1054,7 +1046,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 		 * bbts.  This should only happen once.
 		 */
 		if (update && td->reserved_block_code)
-			nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
+			nand_update_bbt(mtd, (loff_t)(block - 1) <<
+					this->bbt_erase_shift);
 	}
 }
 
@@ -1180,13 +1173,13 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 }
 
 /**
- * nand_update_bbt - [NAND Interface] update bad block table(s)
+ * nand_update_bbt - update bad block table(s)
  * @mtd: MTD device structure
  * @offs: the offset of the newly marked block
  *
  * The function updates the bad block table(s).
  */
-int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
+static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
 	struct nand_chip *this = mtd->priv;
 	int len, res = 0;
@@ -1356,28 +1349,47 @@ int nand_default_bbt(struct mtd_info *mtd)
 int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
 	struct nand_chip *this = mtd->priv;
-	int block;
-	uint8_t res;
+	int block, res;
 
-	/* Get block number * 2 */
-	block = (int)(offs >> (this->bbt_erase_shift - 1));
-	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+	block = (int)(offs >> this->bbt_erase_shift);
+	res = bbt_get_entry(this, block);
 
 	pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: "
 			"(block %d) 0x%02x\n",
-			(unsigned int)offs, block >> 1, res);
+			(unsigned int)offs, block, res);
 
-	switch ((int)res) {
-	case 0x00:
+	switch (res) {
+	case BBT_BLOCK_GOOD:
 		return 0;
-	case 0x01:
+	case BBT_BLOCK_WORN:
 		return 1;
-	case 0x02:
+	case BBT_BLOCK_RESERVED:
 		return allowbbt ? 0 : 1;
 	}
 	return 1;
 }
 
+/**
+ * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
+ * @mtd: MTD device structure
+ * @offs: offset of the bad block
+ */
+int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
+{
+	struct nand_chip *this = mtd->priv;
+	int block, ret = 0;
+
+	block = (int)(offs >> this->bbt_erase_shift);
+
+	/* Mark bad block in memory */
+	bbt_mark_entry(this, block, BBT_BLOCK_WORN);
+
+	/* Update flash-based bad block table */
+	if (this->bbt_options & NAND_BBT_USE_FLASH)
+		ret = nand_update_bbt(mtd, offs);
+
+	return ret;
+}
+
 EXPORT_SYMBOL(nand_scan_bbt);
 EXPORT_SYMBOL(nand_default_bbt);
-EXPORT_SYMBOL_GPL(nand_update_bbt);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 683813a..a87b0a3 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -33,16 +33,16 @@ struct nand_flash_dev nand_flash_ids[] = {
 	 */
 	{"TC58NVG2S0F 4G 3.3V 8-bit",
 		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
-		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224},
+		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
 	{"TC58NVG3S0F 8G 3.3V 8-bit",
 		{ .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} },
-		  SZ_4K, SZ_1K, SZ_256K, 0, 8, 232},
+		  SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) },
 	{"TC58NVG5D2 32G 3.3V 8-bit",
 		{ .id = {0x98, 0xd7, 0x94, 0x32, 0x76, 0x56, 0x09, 0x00} },
-		  SZ_8K, SZ_4K, SZ_1M, 0, 8, 640},
+		  SZ_8K, SZ_4K, SZ_1M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },
 	{"TC58NVG6D2 64G 3.3V 8-bit",
 		{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} },
-		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640},
+		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index cb38f3d..9e04de0 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -205,7 +205,7 @@ MODULE_PARM_DESC(bch,		 "Enable BCH ecc and set how many bits should "
 
 /* Calculate the page offset in flash RAM image by (row, column) address */
 #define NS_RAW_OFFSET(ns) \
-	(((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column)
+	(((ns)->regs.row * (ns)->geom.pgszoob) + (ns)->regs.column)
 
 /* Calculate the OOB offset in flash RAM image by (row, column) address */
 #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz)
@@ -336,7 +336,6 @@ struct nandsim {
 		uint pgsec;         /* number of pages per sector */
 		uint secshift;      /* bits number in sector size */
 		uint pgshift;       /* bits number in page size */
-		uint oobshift;      /* bits number in OOB size */
 		uint pgaddrbytes;   /* bytes per page address */
 		uint secaddrbytes;  /* bytes per sector address */
 		uint idbytes;       /* the number ID bytes that this chip outputs */
@@ -363,7 +362,7 @@ struct nandsim {
 
 	/* Fields needed when using a cache file */
 	struct file *cfile; /* Open file */
-	unsigned char *pages_written; /* Which pages have been written */
+	unsigned long *pages_written; /* Which pages have been written */
 	void *file_buf;
 	struct page *held_pages[NS_MAX_HELD_PAGES];
 	int held_cnt;
@@ -586,7 +585,8 @@ static int alloc_device(struct nandsim *ns)
 			err = -EINVAL;
 			goto err_close;
 		}
-		ns->pages_written = vzalloc(ns->geom.pgnum);
+		ns->pages_written = vzalloc(BITS_TO_LONGS(ns->geom.pgnum) *
+					    sizeof(unsigned long));
 		if (!ns->pages_written) {
 			NS_ERR("alloc_device: unable to allocate pages written array\n");
 			err = -ENOMEM;
@@ -653,9 +653,7 @@ static void free_device(struct nandsim *ns)
 
 static char *get_partition_name(int i)
 {
-	char buf[64];
-	sprintf(buf, "NAND simulator partition %d", i);
-	return kstrdup(buf, GFP_KERNEL);
+	return kasprintf(GFP_KERNEL, "NAND simulator partition %d", i);
 }
 
 /*
@@ -690,7 +688,6 @@ static int init_nandsim(struct mtd_info *mtd)
 	ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
 	ns->geom.secshift = ffs(ns->geom.secsz) - 1;
 	ns->geom.pgshift  = chip->page_shift;
-	ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
 	ns->geom.pgsec    = ns->geom.secsz / ns->geom.pgsz;
 	ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec;
 	ns->options = 0;
@@ -761,12 +758,6 @@ static int init_nandsim(struct mtd_info *mtd)
 		ns->nbparts += 1;
 	}
 
-	/* Detect how many ID bytes the NAND chip outputs */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (second_id_byte != nand_flash_ids[i].dev_id)
-			continue;
-	}
-
 	if (ns->busw == 16)
 		NS_WARN("16-bit flashes support wasn't tested\n");
 
@@ -780,7 +771,7 @@ static int init_nandsim(struct mtd_info *mtd)
 	printk("bus width: %u\n",               ns->busw);
 	printk("bits in sector size: %u\n",     ns->geom.secshift);
 	printk("bits in page size: %u\n",       ns->geom.pgshift);
-	printk("bits in OOB size: %u\n",	ns->geom.oobshift);
+	printk("bits in OOB size: %u\n",	ffs(ns->geom.oobsz) - 1);
 	printk("flash size with OOB: %llu KiB\n",
 			(unsigned long long)ns->geom.totszoob >> 10);
 	printk("page address bytes: %u\n",      ns->geom.pgaddrbytes);
@@ -1479,7 +1470,7 @@ static void read_page(struct nandsim *ns, int num)
 	union ns_mem *mypage;
 
 	if (ns->cfile) {
-		if (!ns->pages_written[ns->regs.row]) {
+		if (!test_bit(ns->regs.row, ns->pages_written)) {
 			NS_DBG("read_page: page %d not written\n", ns->regs.row);
 			memset(ns->buf.byte, 0xFF, num);
 		} else {
@@ -1490,7 +1481,7 @@ static void read_page(struct nandsim *ns, int num)
 				ns->regs.row, ns->regs.column + ns->regs.off);
 			if (do_read_error(ns, num))
 				return;
-			pos = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off;
+			pos = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off;
 			tx = read_file(ns, ns->cfile, ns->buf.byte, num, pos);
 			if (tx != num) {
 				NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx);
@@ -1525,9 +1516,9 @@ static void erase_sector(struct nandsim *ns)
 
 	if (ns->cfile) {
 		for (i = 0; i < ns->geom.pgsec; i++)
-			if (ns->pages_written[ns->regs.row + i]) {
+			if (__test_and_clear_bit(ns->regs.row + i,
+						 ns->pages_written)) {
 				NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i);
-				ns->pages_written[ns->regs.row + i] = 0;
 			}
 		return;
 	}
@@ -1559,8 +1550,8 @@ static int prog_page(struct nandsim *ns, int num)
 
 		NS_DBG("prog_page: writing page %d\n", ns->regs.row);
 		pg_off = ns->file_buf + ns->regs.column + ns->regs.off;
-		off = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off;
-		if (!ns->pages_written[ns->regs.row]) {
+		off = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off;
+		if (!test_bit(ns->regs.row, ns->pages_written)) {
 			all = 1;
 			memset(ns->file_buf, 0xff, ns->geom.pgszoob);
 		} else {
@@ -1580,7 +1571,7 @@ static int prog_page(struct nandsim *ns, int num)
 				NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
 				return -1;
 			}
-			ns->pages_written[ns->regs.row] = 1;
+			__set_bit(ns->regs.row, ns->pages_written);
 		} else {
 			tx = write_file(ns, ns->cfile, pg_off, num, off);
 			if (tx != num) {
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index cd6be2e..5211515 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -324,8 +324,6 @@ static int nuc900_nand_remove(struct platform_device *pdev)
 
 	kfree(nuc900_nand);
 
-	platform_set_drvdata(pdev, NULL);
-
 	return 0;
 }
 
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 81b80af..4ecf0e5 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -154,7 +154,7 @@ static struct nand_ecclayout omap_oobinfo;
  */
 static uint8_t scan_ff_pattern[] = { 0xff };
 static struct nand_bbt_descr bb_descrip_flashbased = {
-	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+	.options = NAND_BBT_SCANALLPAGES,
 	.offs = 0,
 	.len = 1,
 	.pattern = scan_ff_pattern,
@@ -1831,7 +1831,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	struct resource			*res;
 	struct mtd_part_parser_data	ppdata = {};
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (pdata == NULL) {
 		dev_err(&pdev->dev, "platform data missing\n");
 		return -ENODEV;
@@ -2087,7 +2087,6 @@ static int omap_nand_remove(struct platform_device *pdev)
 							mtd);
 	omap3_free_bch(&info->mtd);
 
-	platform_set_drvdata(pdev, NULL);
 	if (info->dma)
 		dma_release_channel(info->dma);
 
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 8fbd002..a393a5b 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -130,8 +130,9 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 		if (!of_property_read_u32(pdev->dev.of_node,
 						"chip-delay", &val))
 			board->chip_delay = (u8)val;
-	} else
-		board = pdev->dev.platform_data;
+	} else {
+		board = dev_get_platdata(&pdev->dev);
+	}
 
 	mtd->priv = nc;
 	mtd->owner = THIS_MODULE;
@@ -186,7 +187,6 @@ no_dev:
 		clk_disable_unprepare(clk);
 		clk_put(clk);
 	}
-	platform_set_drvdata(pdev, NULL);
 	iounmap(io_base);
 no_res:
 	kfree(nc);
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index c004566..cad4cdc 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -30,7 +30,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL };
  */
 static int plat_nand_probe(struct platform_device *pdev)
 {
-	struct platform_nand_data *pdata = pdev->dev.platform_data;
+	struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mtd_part_parser_data ppdata;
 	struct plat_nand_data *data;
 	struct resource *res;
@@ -122,7 +122,6 @@ static int plat_nand_probe(struct platform_device *pdev)
 out:
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
-	platform_set_drvdata(pdev, NULL);
 	iounmap(data->io_base);
 out_release_io:
 	release_mem_region(res->start, resource_size(res));
@@ -137,7 +136,7 @@ out_free:
 static int plat_nand_remove(struct platform_device *pdev)
 {
 	struct plat_nand_data *data = platform_get_drvdata(pdev);
-	struct platform_nand_data *pdata = pdev->dev.platform_data;
+	struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
 	struct resource *res;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dec80ca..501e380 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -506,6 +506,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	info->buf_count		= 0;
 	info->oob_size		= 0;
 	info->use_ecc		= 0;
+	info->use_dma		= (use_dma) ? 1 : 0;
 	info->is_ready		= 0;
 	info->retcode		= ERR_NONE;
 	if (info->cs != 0)
@@ -589,12 +590,23 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 				| addr_cycle;
 		break;
 
+	case NAND_CMD_PARAM:
+		cmd = NAND_CMD_PARAM;
+		info->buf_count = 256;
+		info->ndcb0 |= NDCB0_CMD_TYPE(0)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
+		info->ndcb1 = (column & 0xFF);
+		info->data_size = 256;
+		break;
+
 	case NAND_CMD_READID:
 		cmd = host->cmdset->read_id;
 		info->buf_count = host->read_id_bytes;
 		info->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
+		info->ndcb1 = (column & 0xFF);
 
 		info->data_size = 8;
 		break;
@@ -803,7 +815,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
 	struct platform_device *pdev = info->pdev;
-	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
@@ -912,6 +924,18 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 	return 0;
 }
 
+static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
+{
+	struct platform_device *pdev = info->pdev;
+	if (use_dma) {
+		pxa_free_dma(info->data_dma_ch);
+		dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
+				  info->data_buff, info->data_buff_phys);
+	} else {
+		kfree(info->data_buff);
+	}
+}
+
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
 	struct mtd_info *mtd;
@@ -934,7 +958,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	struct pxa3xx_nand_host *host = mtd->priv;
 	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
-	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
@@ -1034,13 +1058,11 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	struct resource *r;
 	int ret, irq, cs;
 
-	pdata = pdev->dev.platform_data;
-	info = kzalloc(sizeof(*info) + (sizeof(*mtd) +
-		       sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	pdata = dev_get_platdata(&pdev->dev);
+	info = devm_kzalloc(&pdev->dev, sizeof(*info) + (sizeof(*mtd) +
+			    sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
+	if (!info)
 		return -ENOMEM;
-	}
 
 	info->pdev = pdev;
 	for (cs = 0; cs < pdata->num_cs; cs++) {
@@ -1069,20 +1091,21 @@ static int alloc_nand_resource(struct platform_device *pdev)
 
 	spin_lock_init(&chip->controller->lock);
 	init_waitqueue_head(&chip->controller->wq);
-	info->clk = clk_get(&pdev->dev, NULL);
+	info->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
-		ret = PTR_ERR(info->clk);
-		goto fail_free_mtd;
+		return PTR_ERR(info->clk);
 	}
-	clk_enable(info->clk);
+	ret = clk_prepare_enable(info->clk);
+	if (ret < 0)
+		return ret;
 
 	/*
 	 * This is a dirty hack to make this driver work from devicetree
 	 * bindings. It can be removed once we have a prober DMA controller
 	 * framework for DT.
 	 */
-	if (pdev->dev.of_node && cpu_is_pxa3xx()) {
+	if (pdev->dev.of_node && of_machine_is_compatible("marvell,pxa3xx")) {
 		info->drcmr_dat = 97;
 		info->drcmr_cmd = 99;
 	} else {
@@ -1090,7 +1113,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 		if (r == NULL) {
 			dev_err(&pdev->dev, "no resource defined for data DMA\n");
 			ret = -ENXIO;
-			goto fail_put_clk;
+			goto fail_disable_clk;
 		}
 		info->drcmr_dat = r->start;
 
@@ -1098,7 +1121,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 		if (r == NULL) {
 			dev_err(&pdev->dev, "no resource defined for command DMA\n");
 			ret = -ENXIO;
-			goto fail_put_clk;
+			goto fail_disable_clk;
 		}
 		info->drcmr_cmd = r->start;
 	}
@@ -1107,34 +1130,20 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		ret = -ENXIO;
-		goto fail_put_clk;
+		goto fail_disable_clk;
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no IO memory resource defined\n");
-		ret = -ENODEV;
-		goto fail_put_clk;
-	}
-
-	r = request_mem_region(r->start, resource_size(r), pdev->name);
-	if (r == NULL) {
-		dev_err(&pdev->dev, "failed to request memory resource\n");
-		ret = -EBUSY;
-		goto fail_put_clk;
-	}
-
-	info->mmio_base = ioremap(r->start, resource_size(r));
-	if (info->mmio_base == NULL) {
-		dev_err(&pdev->dev, "ioremap() failed\n");
-		ret = -ENODEV;
-		goto fail_free_res;
+	info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(info->mmio_base)) {
+		ret = PTR_ERR(info->mmio_base);
+		goto fail_disable_clk;
 	}
 	info->mmio_phys = r->start;
 
 	ret = pxa3xx_nand_init_buff(info);
 	if (ret)
-		goto fail_free_io;
+		goto fail_disable_clk;
 
 	/* initialize all interrupts to be disabled */
 	disable_int(info, NDSR_MASK);
@@ -1152,21 +1161,9 @@ static int alloc_nand_resource(struct platform_device *pdev)
 
 fail_free_buf:
 	free_irq(irq, info);
-	if (use_dma) {
-		pxa_free_dma(info->data_dma_ch);
-		dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
-			info->data_buff, info->data_buff_phys);
-	} else
-		kfree(info->data_buff);
-fail_free_io:
-	iounmap(info->mmio_base);
-fail_free_res:
-	release_mem_region(r->start, resource_size(r));
-fail_put_clk:
-	clk_disable(info->clk);
-	clk_put(info->clk);
-fail_free_mtd:
-	kfree(info);
+	pxa3xx_nand_free_buff(info);
+fail_disable_clk:
+	clk_disable_unprepare(info->clk);
 	return ret;
 }
 
@@ -1174,35 +1171,22 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
 	struct pxa3xx_nand_platform_data *pdata;
-	struct resource *r;
 	int irq, cs;
 
 	if (!info)
 		return 0;
 
-	pdata = pdev->dev.platform_data;
-	platform_set_drvdata(pdev, NULL);
+	pdata = dev_get_platdata(&pdev->dev);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0)
 		free_irq(irq, info);
-	if (use_dma) {
-		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
-				info->data_buff, info->data_buff_phys);
-	} else
-		kfree(info->data_buff);
-
-	iounmap(info->mmio_base);
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, resource_size(r));
+	pxa3xx_nand_free_buff(info);
 
-	clk_disable(info->clk);
-	clk_put(info->clk);
+	clk_disable_unprepare(info->clk);
 
 	for (cs = 0; cs < pdata->num_cs; cs++)
 		nand_release(info->host[cs]->mtd);
-	kfree(info);
 	return 0;
 }
 
@@ -1211,7 +1195,7 @@ static struct of_device_id pxa3xx_nand_dt_ids[] = {
 	{ .compatible = "marvell,pxa3xx-nand" },
 	{}
 };
-MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
+MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
 
 static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
 {
@@ -1255,7 +1239,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data defined\n");
 		return -ENODEV;
@@ -1302,7 +1286,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 	struct mtd_info *mtd;
 	int cs;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (info->state) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
 		return -EAGAIN;
@@ -1323,7 +1307,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
 	struct mtd_info *mtd;
 	int cs;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	/* We don't want to handle interrupt without calling mtd routine */
 	disable_int(info, NDCR_INT_MASK);
 
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 4495f85..ef72884 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -1002,7 +1002,7 @@ void r852_shutdown(struct pci_dev *pci_dev)
 	pci_disable_device(pci_dev);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int r852_suspend(struct device *device)
 {
 	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
@@ -1055,9 +1055,6 @@ static int r852_resume(struct device *device)
 	r852_update_card_detect(dev);
 	return 0;
 }
-#else
-#define r852_suspend	NULL
-#define r852_resume	NULL
 #endif
 
 static const struct pci_device_id r852_pci_id_tbl[] = {
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d65afd2..d65cbe9 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -150,7 +150,7 @@ static struct s3c2410_nand_info *to_nand_info(struct platform_device *dev)
 
 static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
 {
-	return dev->dev.platform_data;
+	return dev_get_platdata(&dev->dev);
 }
 
 static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
@@ -697,8 +697,6 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
 {
 	struct s3c2410_nand_info *info = to_nand_info(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	if (info == NULL)
 		return 0;
 
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index e57e18e..a3c84eb 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -137,7 +137,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
 	dma_cap_mask_t mask;
 	struct dma_slave_config cfg;
 	struct platform_device *pdev = flctl->pdev;
-	struct sh_flctl_platform_data *pdata = pdev->dev.platform_data;
+	struct sh_flctl_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int ret;
 
 	if (!pdata)
@@ -1131,7 +1131,7 @@ static int flctl_probe(struct platform_device *pdev)
 	if (pdev->dev.of_node)
 		pdata = flctl_parse_dt(&pdev->dev);
 	else
-		pdata = pdev->dev.platform_data;
+		pdata = dev_get_platdata(&pdev->dev);
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "no setup data defined\n");
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 127bc42..87908d7 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -112,7 +112,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
 	struct resource *r;
 	int err = 0;
 	struct sharpsl_nand *sharpsl;
-	struct sharpsl_nand_platform_data *data = pdev->dev.platform_data;
+	struct sharpsl_nand_platform_data *data = dev_get_platdata(&pdev->dev);
 
 	if (!data) {
 		dev_err(&pdev->dev, "no platform data!\n");
@@ -194,7 +194,6 @@ err_add:
 	nand_release(&sharpsl->mtd);
 
 err_scan:
-	platform_set_drvdata(pdev, NULL);
 	iounmap(sharpsl->io);
 err_ioremap:
 err_get_res:
@@ -212,8 +211,6 @@ static int sharpsl_nand_remove(struct platform_device *pdev)
 	/* Release resources, unregister device */
 	nand_release(&sharpsl->mtd);
 
-	platform_set_drvdata(pdev, NULL);
-
 	iounmap(sharpsl->io);
 
 	/* Free the MTD device structure */
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c
index e8181ed..e06b5e5 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/sm_common.c
@@ -42,7 +42,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_oob_ops ops;
 	struct sm_oob oob;
-	int ret, error = 0;
+	int ret;
 
 	memset(&oob, -1, SM_OOB_SIZE);
 	oob.block_status = 0x0F;
@@ -61,11 +61,10 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
 		printk(KERN_NOTICE
 			"sm_common: can't mark sector at %i as bad\n",
 								(int)ofs);
-		error = -EIO;
-	} else
-		mtd->ecc_stats.badblocks++;
+		return -EIO;
+	}
 
-	return error;
+	return 0;
 }
 
 static struct nand_flash_dev nand_smartmedia_flash_ids[] = {
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 508e9e0..396530d 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -357,7 +357,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
 
 static int tmio_probe(struct platform_device *dev)
 {
-	struct tmio_nand_data *data = dev->dev.platform_data;
+	struct tmio_nand_data *data = dev_get_platdata(&dev->dev);
 	struct resource *fcr = platform_get_resource(dev,
 			IORESOURCE_MEM, 0);
 	struct resource *ccr = platform_get_resource(dev,
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 7ed654c..440b570 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -87,7 +87,7 @@ static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
 static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg)
 {
 	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
-	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
 
 	return drvdata->base + (reg << plat->shift);
 }
@@ -138,7 +138,7 @@ static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd,
 	struct nand_chip *chip = mtd->priv;
 	struct txx9ndfmc_priv *txx9_priv = chip->priv;
 	struct platform_device *dev = txx9_priv->dev;
-	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
@@ -225,7 +225,7 @@ static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
 
 static void txx9ndfmc_initialize(struct platform_device *dev)
 {
-	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
 	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
 	int tmout = 100;
 
@@ -274,7 +274,7 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
 
 static int __init txx9ndfmc_probe(struct platform_device *dev)
 {
-	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
 	int hold, spw;
 	int i;
 	struct txx9ndfmc_drvdata *drvdata;
@@ -387,7 +387,6 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
 	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
 	int i;
 
-	platform_set_drvdata(dev, NULL);
 	if (!drvdata)
 		return 0;
 	for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) {
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 553d6d6..7843a44 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -20,6 +20,11 @@
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
+static bool node_has_compatible(struct device_node *pp)
+{
+	return of_get_property(pp, "compatible", NULL);
+}
+
 static int parse_ofpart_partitions(struct mtd_info *master,
 				   struct mtd_partition **pparts,
 				   struct mtd_part_parser_data *data)
@@ -40,8 +45,12 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 	/* First count the subnodes */
 	pp = NULL;
 	nr_parts = 0;
-	while ((pp = of_get_next_child(node, pp)))
+	while ((pp = of_get_next_child(node, pp))) {
+		if (node_has_compatible(pp))
+			continue;
+
 		nr_parts++;
+	}
 
 	if (nr_parts == 0)
 		return 0;
@@ -57,6 +66,9 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 		int len;
 		int a_cells, s_cells;
 
+		if (node_has_compatible(pp))
+			continue;
+
 		reg = of_get_property(pp, "reg", &len);
 		if (!reg) {
 			nr_parts--;
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 9f11562..63699ff 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -38,7 +38,7 @@ struct onenand_info {
 static int generic_onenand_probe(struct platform_device *pdev)
 {
 	struct onenand_info *info;
-	struct onenand_platform_data *pdata = pdev->dev.platform_data;
+	struct onenand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct resource *res = pdev->resource;
 	unsigned long size = resource_size(res);
 	int err;
@@ -94,8 +94,6 @@ static int generic_onenand_remove(struct platform_device *pdev)
 	struct resource *res = pdev->resource;
 	unsigned long size = resource_size(res);
 
-	platform_set_drvdata(pdev, NULL);
-
 	if (info) {
 		onenand_release(&info->mtd);
 		release_mem_region(res->start, size);
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index d98b198..558071b 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -639,7 +639,7 @@ static int omap2_onenand_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct mtd_part_parser_data ppdata = {};
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (pdata == NULL) {
 		dev_err(&pdev->dev, "platform data missing\n");
 		return -ENODEV;
@@ -810,7 +810,6 @@ static int omap2_onenand_remove(struct platform_device *pdev)
 	if (c->dma_channel != -1)
 		omap_free_dma(c->dma_channel);
 	omap2_onenand_shutdown(pdev);
-	platform_set_drvdata(pdev, NULL);
 	if (c->gpio_irq) {
 		free_irq(gpio_to_irq(c->gpio_irq), c);
 		gpio_free(c->gpio_irq);
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 66fe3b7..08d0085 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -133,7 +133,6 @@ static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_desc
 {
 	struct onenand_chip *this = mtd->priv;
 
-        bd->options &= ~NAND_BBT_SCANEMPTY;
 	return create_bbt(mtd, this->page_buf, bd, -1);
 }
 
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 2cf7408..df7400d 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -867,7 +867,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	struct resource *r;
 	int size, err;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	/* No need to check pdata. the platform data is optional */
 
 	size = sizeof(struct mtd_info) + sizeof(struct onenand_chip);
@@ -1073,7 +1073,6 @@ static int s3c_onenand_remove(struct platform_device *pdev)
 	release_mem_region(onenand->base_res->start,
 			   resource_size(onenand->base_res));
 
-	platform_set_drvdata(pdev, NULL);
 	kfree(onenand->oob_buf);
 	kfree(onenand->page_buf);
 	kfree(onenand);
diff --git a/drivers/mtd/tests/Makefile b/drivers/mtd/tests/Makefile
index bd0065c..937a829 100644
--- a/drivers/mtd/tests/Makefile
+++ b/drivers/mtd/tests/Makefile
@@ -7,3 +7,12 @@ obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_nandbiterrs.o
+
+mtd_oobtest-objs := oobtest.o mtd_test.o
+mtd_pagetest-objs := pagetest.o mtd_test.o
+mtd_readtest-objs := readtest.o mtd_test.o
+mtd_speedtest-objs := speedtest.o mtd_test.o
+mtd_stresstest-objs := stresstest.o mtd_test.o
+mtd_subpagetest-objs := subpagetest.o mtd_test.o
+mtd_torturetest-objs := torturetest.o mtd_test.o
+mtd_nandbiterrs-objs := nandbiterrs.o mtd_test.o
diff --git a/drivers/mtd/tests/mtd_nandbiterrs.c b/drivers/mtd/tests/mtd_nandbiterrs.c
deleted file mode 100644
index 207bf9a..0000000
--- a/drivers/mtd/tests/mtd_nandbiterrs.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright © 2012 NetCommWireless
- * Iwo Mergler <Iwo.Mergler@netcommwireless.com.au>
- *
- * Test for multi-bit error recovery on a NAND page This mostly tests the
- * ECC controller / driver.
- *
- * There are two test modes:
- *
- *	0 - artificially inserting bit errors until the ECC fails
- *	    This is the default method and fairly quick. It should
- *	    be independent of the quality of the FLASH.
- *
- *	1 - re-writing the same pattern repeatedly until the ECC fails.
- *	    This method relies on the physics of NAND FLASH to eventually
- *	    generate '0' bits if '1' has been written sufficient times.
- *	    Depending on the NAND, the first bit errors will appear after
- *	    1000 or more writes and then will usually snowball, reaching the
- *	    limits of the ECC quickly.
- *
- *	    The test stops after 10000 cycles, should your FLASH be
- *	    exceptionally good and not generate bit errors before that. Try
- *	    a different page in that case.
- *
- * Please note that neither of these tests will significantly 'use up' any
- * FLASH endurance. Only a maximum of two erase operations will be performed.
- *
- *
- * This program is free software; you can 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; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mtd/mtd.h>
-#include <linux/err.h>
-#include <linux/mtd/nand.h>
-#include <linux/slab.h>
-
-static int dev;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static unsigned page_offset;
-module_param(page_offset, uint, S_IRUGO);
-MODULE_PARM_DESC(page_offset, "Page number relative to dev start");
-
-static unsigned seed;
-module_param(seed, uint, S_IRUGO);
-MODULE_PARM_DESC(seed, "Random seed");
-
-static int mode;
-module_param(mode, int, S_IRUGO);
-MODULE_PARM_DESC(mode, "0=incremental errors, 1=overwrite test");
-
-static unsigned max_overwrite = 10000;
-
-static loff_t   offset;     /* Offset of the page we're using. */
-static unsigned eraseblock; /* Eraseblock number for our page. */
-
-/* We assume that the ECC can correct up to a certain number
- * of biterrors per subpage. */
-static unsigned subsize;  /* Size of subpages */
-static unsigned subcount; /* Number of subpages per page */
-
-static struct mtd_info *mtd;   /* MTD device */
-
-static uint8_t *wbuffer; /* One page write / compare buffer */
-static uint8_t *rbuffer; /* One page read buffer */
-
-/* 'random' bytes from known offsets */
-static uint8_t hash(unsigned offset)
-{
-	unsigned v = offset;
-	unsigned char c;
-	v ^= 0x7f7edfd3;
-	v = v ^ (v >> 3);
-	v = v ^ (v >> 5);
-	v = v ^ (v >> 13);
-	c = v & 0xFF;
-	/* Reverse bits of result. */
-	c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
-	c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
-	c = (c & 0x55) << 1 | (c & 0xAA) >> 1;
-	return c;
-}
-
-static int erase_block(void)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = eraseblock * mtd->erasesize;
-
-	pr_info("erase_block\n");
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (err || ei.state == MTD_ERASE_FAILED) {
-		pr_err("error %d while erasing\n", err);
-		if (!err)
-			err = -EIO;
-		return err;
-	}
-
-	return 0;
-}
-
-/* Writes wbuffer to page */
-static int write_page(int log)
-{
-	int err = 0;
-	size_t written;
-
-	if (log)
-		pr_info("write_page\n");
-
-	err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer);
-	if (err || written != mtd->writesize) {
-		pr_err("error: write failed at %#llx\n", (long long)offset);
-		if (!err)
-			err = -EIO;
-	}
-
-	return err;
-}
-
-/* Re-writes the data area while leaving the OOB alone. */
-static int rewrite_page(int log)
-{
-	int err = 0;
-	struct mtd_oob_ops ops;
-
-	if (log)
-		pr_info("rewrite page\n");
-
-	ops.mode      = MTD_OPS_RAW; /* No ECC */
-	ops.len       = mtd->writesize;
-	ops.retlen    = 0;
-	ops.ooblen    = 0;
-	ops.oobretlen = 0;
-	ops.ooboffs   = 0;
-	ops.datbuf    = wbuffer;
-	ops.oobbuf    = NULL;
-
-	err = mtd_write_oob(mtd, offset, &ops);
-	if (err || ops.retlen != mtd->writesize) {
-		pr_err("error: write_oob failed (%d)\n", err);
-		if (!err)
-			err = -EIO;
-	}
-
-	return err;
-}
-
-/* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
- * or error (<0) */
-static int read_page(int log)
-{
-	int err = 0;
-	size_t read;
-	struct mtd_ecc_stats oldstats;
-
-	if (log)
-		pr_info("read_page\n");
-
-	/* Saving last mtd stats */
-	memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
-
-	err = mtd_read(mtd, offset, mtd->writesize, &read, rbuffer);
-	if (err == -EUCLEAN)
-		err = mtd->ecc_stats.corrected - oldstats.corrected;
-
-	if (err < 0 || read != mtd->writesize) {
-		pr_err("error: read failed at %#llx\n", (long long)offset);
-		if (err >= 0)
-			err = -EIO;
-	}
-
-	return err;
-}
-
-/* Verifies rbuffer against random sequence */
-static int verify_page(int log)
-{
-	unsigned i, errs = 0;
-
-	if (log)
-		pr_info("verify_page\n");
-
-	for (i = 0; i < mtd->writesize; i++) {
-		if (rbuffer[i] != hash(i+seed)) {
-			pr_err("Error: page offset %u, expected %02x, got %02x\n",
-				i, hash(i+seed), rbuffer[i]);
-			errs++;
-		}
-	}
-
-	if (errs)
-		return -EIO;
-	else
-		return 0;
-}
-
-#define CBIT(v, n) ((v) & (1 << (n)))
-#define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
-
-/* Finds the first '1' bit in wbuffer starting at offset 'byte'
- * and sets it to '0'. */
-static int insert_biterror(unsigned byte)
-{
-	int bit;
-
-	while (byte < mtd->writesize) {
-		for (bit = 7; bit >= 0; bit--) {
-			if (CBIT(wbuffer[byte], bit)) {
-				BCLR(wbuffer[byte], bit);
-				pr_info("Inserted biterror @ %u/%u\n", byte, bit);
-				return 0;
-			}
-		}
-		byte++;
-	}
-	pr_err("biterror: Failed to find a '1' bit\n");
-	return -EIO;
-}
-
-/* Writes 'random' data to page and then introduces deliberate bit
- * errors into the page, while verifying each step. */
-static int incremental_errors_test(void)
-{
-	int err = 0;
-	unsigned i;
-	unsigned errs_per_subpage = 0;
-
-	pr_info("incremental biterrors test\n");
-
-	for (i = 0; i < mtd->writesize; i++)
-		wbuffer[i] = hash(i+seed);
-
-	err = write_page(1);
-	if (err)
-		goto exit;
-
-	while (1) {
-
-		err = rewrite_page(1);
-		if (err)
-			goto exit;
-
-		err = read_page(1);
-		if (err > 0)
-			pr_info("Read reported %d corrected bit errors\n", err);
-		if (err < 0) {
-			pr_err("After %d biterrors per subpage, read reported error %d\n",
-				errs_per_subpage, err);
-			err = 0;
-			goto exit;
-		}
-
-		err = verify_page(1);
-		if (err) {
-			pr_err("ECC failure, read data is incorrect despite read success\n");
-			goto exit;
-		}
-
-		pr_info("Successfully corrected %d bit errors per subpage\n",
-			errs_per_subpage);
-
-		for (i = 0; i < subcount; i++) {
-			err = insert_biterror(i * subsize);
-			if (err < 0)
-				goto exit;
-		}
-		errs_per_subpage++;
-	}
-
-exit:
-	return err;
-}
-
-
-/* Writes 'random' data to page and then re-writes that same data repeatedly.
-   This eventually develops bit errors (bits written as '1' will slowly become
-   '0'), which are corrected as far as the ECC is capable of. */
-static int overwrite_test(void)
-{
-	int err = 0;
-	unsigned i;
-	unsigned max_corrected = 0;
-	unsigned opno = 0;
-	/* We don't expect more than this many correctable bit errors per
-	 * page. */
-	#define MAXBITS 512
-	static unsigned bitstats[MAXBITS]; /* bit error histogram. */
-
-	memset(bitstats, 0, sizeof(bitstats));
-
-	pr_info("overwrite biterrors test\n");
-
-	for (i = 0; i < mtd->writesize; i++)
-		wbuffer[i] = hash(i+seed);
-
-	err = write_page(1);
-	if (err)
-		goto exit;
-
-	while (opno < max_overwrite) {
-
-		err = rewrite_page(0);
-		if (err)
-			break;
-
-		err = read_page(0);
-		if (err >= 0) {
-			if (err >= MAXBITS) {
-				pr_info("Implausible number of bit errors corrected\n");
-				err = -EIO;
-				break;
-			}
-			bitstats[err]++;
-			if (err > max_corrected) {
-				max_corrected = err;
-				pr_info("Read reported %d corrected bit errors\n",
-					err);
-			}
-		} else { /* err < 0 */
-			pr_info("Read reported error %d\n", err);
-			err = 0;
-			break;
-		}
-
-		err = verify_page(0);
-		if (err) {
-			bitstats[max_corrected] = opno;
-			pr_info("ECC failure, read data is incorrect despite read success\n");
-			break;
-		}
-
-		opno++;
-	}
-
-	/* At this point bitstats[0] contains the number of ops with no bit
-	 * errors, bitstats[1] the number of ops with 1 bit error, etc. */
-	pr_info("Bit error histogram (%d operations total):\n", opno);
-	for (i = 0; i < max_corrected; i++)
-		pr_info("Page reads with %3d corrected bit errors: %d\n",
-			i, bitstats[i]);
-
-exit:
-	return err;
-}
-
-static int __init mtd_nandbiterrs_init(void)
-{
-	int err = 0;
-
-	printk("\n");
-	printk(KERN_INFO "==================================================\n");
-	pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		goto exit_mtddev;
-	}
-
-	if (mtd->type != MTD_NANDFLASH) {
-		pr_info("this test requires NAND flash\n");
-		err = -ENODEV;
-		goto exit_nand;
-	}
-
-	pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
-		(unsigned long long)mtd->size, mtd->erasesize,
-		mtd->writesize, mtd->oobsize);
-
-	subsize  = mtd->writesize >> mtd->subpage_sft;
-	subcount = mtd->writesize / subsize;
-
-	pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize);
-
-	offset     = page_offset * mtd->writesize;
-	eraseblock = mtd_div_by_eb(offset, mtd);
-
-	pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
-		page_offset, offset, eraseblock);
-
-	wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
-	if (!wbuffer) {
-		err = -ENOMEM;
-		goto exit_wbuffer;
-	}
-
-	rbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
-	if (!rbuffer) {
-		err = -ENOMEM;
-		goto exit_rbuffer;
-	}
-
-	err = erase_block();
-	if (err)
-		goto exit_error;
-
-	if (mode == 0)
-		err = incremental_errors_test();
-	else
-		err = overwrite_test();
-
-	if (err)
-		goto exit_error;
-
-	/* We leave the block un-erased in case of test failure. */
-	err = erase_block();
-	if (err)
-		goto exit_error;
-
-	err = -EIO;
-	pr_info("finished successfully.\n");
-	printk(KERN_INFO "==================================================\n");
-
-exit_error:
-	kfree(rbuffer);
-exit_rbuffer:
-	kfree(wbuffer);
-exit_wbuffer:
-	/* Nothing */
-exit_nand:
-	put_mtd_device(mtd);
-exit_mtddev:
-	return err;
-}
-
-static void __exit mtd_nandbiterrs_exit(void)
-{
-	return;
-}
-
-module_init(mtd_nandbiterrs_init);
-module_exit(mtd_nandbiterrs_exit);
-
-MODULE_DESCRIPTION("NAND bit error recovery test");
-MODULE_AUTHOR("Iwo Mergler");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
deleted file mode 100644
index 3e24b37..0000000
--- a/drivers/mtd/tests/mtd_oobtest.c
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Test OOB read and write on MTD device.
- *
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <asm/div64.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static struct mtd_info *mtd;
-static unsigned char *readbuf;
-static unsigned char *writebuf;
-static unsigned char *bbt;
-
-static int ebcnt;
-static int pgcnt;
-static int errcnt;
-static int use_offset;
-static int use_len;
-static int use_len_max;
-static int vary_offset;
-static struct rnd_state rnd_state;
-
-static int erase_eraseblock(int ebnum)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (err) {
-		pr_err("error %d while erasing EB %d\n", err, ebnum);
-		return err;
-	}
-
-	if (ei.state == MTD_ERASE_FAILED) {
-		pr_err("some erase error occurred at EB %d\n", ebnum);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int erase_whole_device(void)
-{
-	int err;
-	unsigned int i;
-
-	pr_info("erasing whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = erase_eraseblock(i);
-		if (err)
-			return err;
-		cond_resched();
-	}
-	pr_info("erased %u eraseblocks\n", i);
-	return 0;
-}
-
-static void do_vary_offset(void)
-{
-	use_len -= 1;
-	if (use_len < 1) {
-		use_offset += 1;
-		if (use_offset >= use_len_max)
-			use_offset = 0;
-		use_len = use_len_max - use_offset;
-	}
-}
-
-static int write_eraseblock(int ebnum)
-{
-	int i;
-	struct mtd_oob_ops ops;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
-		prandom_bytes_state(&rnd_state, writebuf, use_len);
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = use_len;
-		ops.oobretlen = 0;
-		ops.ooboffs   = use_offset;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = writebuf;
-		err = mtd_write_oob(mtd, addr, &ops);
-		if (err || ops.oobretlen != use_len) {
-			pr_err("error: writeoob failed at %#llx\n",
-			       (long long)addr);
-			pr_err("error: use_len %d, use_offset %d\n",
-			       use_len, use_offset);
-			errcnt += 1;
-			return err ? err : -1;
-		}
-		if (vary_offset)
-			do_vary_offset();
-	}
-
-	return err;
-}
-
-static int write_whole_device(void)
-{
-	int err;
-	unsigned int i;
-
-	pr_info("writing OOBs of whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock(i);
-		if (err)
-			return err;
-		if (i % 256 == 0)
-			pr_info("written up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("written %u eraseblocks\n", i);
-	return 0;
-}
-
-static int verify_eraseblock(int ebnum)
-{
-	int i;
-	struct mtd_oob_ops ops;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
-		prandom_bytes_state(&rnd_state, writebuf, use_len);
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = use_len;
-		ops.oobretlen = 0;
-		ops.ooboffs   = use_offset;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = readbuf;
-		err = mtd_read_oob(mtd, addr, &ops);
-		if (err || ops.oobretlen != use_len) {
-			pr_err("error: readoob failed at %#llx\n",
-			       (long long)addr);
-			errcnt += 1;
-			return err ? err : -1;
-		}
-		if (memcmp(readbuf, writebuf, use_len)) {
-			pr_err("error: verify failed at %#llx\n",
-			       (long long)addr);
-			errcnt += 1;
-			if (errcnt > 1000) {
-				pr_err("error: too many errors\n");
-				return -1;
-			}
-		}
-		if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
-			int k;
-
-			ops.mode      = MTD_OPS_AUTO_OOB;
-			ops.len       = 0;
-			ops.retlen    = 0;
-			ops.ooblen    = mtd->ecclayout->oobavail;
-			ops.oobretlen = 0;
-			ops.ooboffs   = 0;
-			ops.datbuf    = NULL;
-			ops.oobbuf    = readbuf;
-			err = mtd_read_oob(mtd, addr, &ops);
-			if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
-				pr_err("error: readoob failed at %#llx\n",
-						(long long)addr);
-				errcnt += 1;
-				return err ? err : -1;
-			}
-			if (memcmp(readbuf + use_offset, writebuf, use_len)) {
-				pr_err("error: verify failed at %#llx\n",
-						(long long)addr);
-				errcnt += 1;
-				if (errcnt > 1000) {
-					pr_err("error: too many errors\n");
-					return -1;
-				}
-			}
-			for (k = 0; k < use_offset; ++k)
-				if (readbuf[k] != 0xff) {
-					pr_err("error: verify 0xff "
-					       "failed at %#llx\n",
-					       (long long)addr);
-					errcnt += 1;
-					if (errcnt > 1000) {
-						pr_err("error: too "
-						       "many errors\n");
-						return -1;
-					}
-				}
-			for (k = use_offset + use_len;
-			     k < mtd->ecclayout->oobavail; ++k)
-				if (readbuf[k] != 0xff) {
-					pr_err("error: verify 0xff "
-					       "failed at %#llx\n",
-					       (long long)addr);
-					errcnt += 1;
-					if (errcnt > 1000) {
-						pr_err("error: too "
-						       "many errors\n");
-						return -1;
-					}
-				}
-		}
-		if (vary_offset)
-			do_vary_offset();
-	}
-	return err;
-}
-
-static int verify_eraseblock_in_one_go(int ebnum)
-{
-	struct mtd_oob_ops ops;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-	size_t len = mtd->ecclayout->oobavail * pgcnt;
-
-	prandom_bytes_state(&rnd_state, writebuf, len);
-	ops.mode      = MTD_OPS_AUTO_OOB;
-	ops.len       = 0;
-	ops.retlen    = 0;
-	ops.ooblen    = len;
-	ops.oobretlen = 0;
-	ops.ooboffs   = 0;
-	ops.datbuf    = NULL;
-	ops.oobbuf    = readbuf;
-	err = mtd_read_oob(mtd, addr, &ops);
-	if (err || ops.oobretlen != len) {
-		pr_err("error: readoob failed at %#llx\n",
-		       (long long)addr);
-		errcnt += 1;
-		return err ? err : -1;
-	}
-	if (memcmp(readbuf, writebuf, len)) {
-		pr_err("error: verify failed at %#llx\n",
-		       (long long)addr);
-		errcnt += 1;
-		if (errcnt > 1000) {
-			pr_err("error: too many errors\n");
-			return -1;
-		}
-	}
-
-	return err;
-}
-
-static int verify_all_eraseblocks(void)
-{
-	int err;
-	unsigned int i;
-
-	pr_info("verifying all eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = verify_eraseblock(i);
-		if (err)
-			return err;
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-	return 0;
-}
-
-static int is_block_bad(int ebnum)
-{
-	int ret;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	ret = mtd_block_isbad(mtd, addr);
-	if (ret)
-		pr_info("block %d is bad\n", ebnum);
-	return ret;
-}
-
-static int scan_for_bad_eraseblocks(void)
-{
-	int i, bad = 0;
-
-	bbt = kmalloc(ebcnt, GFP_KERNEL);
-	if (!bbt) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	pr_info("scanning for bad eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		bbt[i] = is_block_bad(i) ? 1 : 0;
-		if (bbt[i])
-			bad += 1;
-		cond_resched();
-	}
-	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
-	return 0;
-}
-
-static int __init mtd_oobtest_init(void)
-{
-	int err = 0;
-	unsigned int i;
-	uint64_t tmp;
-	struct mtd_oob_ops ops;
-	loff_t addr = 0, addr0;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
-		return -EINVAL;
-	}
-
-	pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->type != MTD_NANDFLASH) {
-		pr_info("this test requires NAND flash\n");
-		goto out;
-	}
-
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / mtd->writesize;
-
-	pr_info("MTD device size %llu, eraseblock size %u, "
-	       "page size %u, count of eraseblocks %u, pages per "
-	       "eraseblock %u, OOB size %u\n",
-	       (unsigned long long)mtd->size, mtd->erasesize,
-	       mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
-
-	err = -ENOMEM;
-	readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!readbuf) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!writebuf) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-
-	err = scan_for_bad_eraseblocks();
-	if (err)
-		goto out;
-
-	use_offset = 0;
-	use_len = mtd->ecclayout->oobavail;
-	use_len_max = mtd->ecclayout->oobavail;
-	vary_offset = 0;
-
-	/* First test: write all OOB, read it back and verify */
-	pr_info("test 1 of 5\n");
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	prandom_seed_state(&rnd_state, 1);
-	err = write_whole_device();
-	if (err)
-		goto out;
-
-	prandom_seed_state(&rnd_state, 1);
-	err = verify_all_eraseblocks();
-	if (err)
-		goto out;
-
-	/*
-	 * Second test: write all OOB, a block at a time, read it back and
-	 * verify.
-	 */
-	pr_info("test 2 of 5\n");
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	prandom_seed_state(&rnd_state, 3);
-	err = write_whole_device();
-	if (err)
-		goto out;
-
-	/* Check all eraseblocks */
-	prandom_seed_state(&rnd_state, 3);
-	pr_info("verifying all eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = verify_eraseblock_in_one_go(i);
-		if (err)
-			goto out;
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-
-	/*
-	 * Third test: write OOB at varying offsets and lengths, read it back
-	 * and verify.
-	 */
-	pr_info("test 3 of 5\n");
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	/* Write all eraseblocks */
-	use_offset = 0;
-	use_len = mtd->ecclayout->oobavail;
-	use_len_max = mtd->ecclayout->oobavail;
-	vary_offset = 1;
-	prandom_seed_state(&rnd_state, 5);
-
-	err = write_whole_device();
-	if (err)
-		goto out;
-
-	/* Check all eraseblocks */
-	use_offset = 0;
-	use_len = mtd->ecclayout->oobavail;
-	use_len_max = mtd->ecclayout->oobavail;
-	vary_offset = 1;
-	prandom_seed_state(&rnd_state, 5);
-	err = verify_all_eraseblocks();
-	if (err)
-		goto out;
-
-	use_offset = 0;
-	use_len = mtd->ecclayout->oobavail;
-	use_len_max = mtd->ecclayout->oobavail;
-	vary_offset = 0;
-
-	/* Fourth test: try to write off end of device */
-	pr_info("test 4 of 5\n");
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	addr0 = 0;
-	for (i = 0; i < ebcnt && bbt[i]; ++i)
-		addr0 += mtd->erasesize;
-
-	/* Attempt to write off end of OOB */
-	ops.mode      = MTD_OPS_AUTO_OOB;
-	ops.len       = 0;
-	ops.retlen    = 0;
-	ops.ooblen    = 1;
-	ops.oobretlen = 0;
-	ops.ooboffs   = mtd->ecclayout->oobavail;
-	ops.datbuf    = NULL;
-	ops.oobbuf    = writebuf;
-	pr_info("attempting to start write past end of OOB\n");
-	pr_info("an error is expected...\n");
-	err = mtd_write_oob(mtd, addr0, &ops);
-	if (err) {
-		pr_info("error occurred as expected\n");
-		err = 0;
-	} else {
-		pr_err("error: can write past end of OOB\n");
-		errcnt += 1;
-	}
-
-	/* Attempt to read off end of OOB */
-	ops.mode      = MTD_OPS_AUTO_OOB;
-	ops.len       = 0;
-	ops.retlen    = 0;
-	ops.ooblen    = 1;
-	ops.oobretlen = 0;
-	ops.ooboffs   = mtd->ecclayout->oobavail;
-	ops.datbuf    = NULL;
-	ops.oobbuf    = readbuf;
-	pr_info("attempting to start read past end of OOB\n");
-	pr_info("an error is expected...\n");
-	err = mtd_read_oob(mtd, addr0, &ops);
-	if (err) {
-		pr_info("error occurred as expected\n");
-		err = 0;
-	} else {
-		pr_err("error: can read past end of OOB\n");
-		errcnt += 1;
-	}
-
-	if (bbt[ebcnt - 1])
-		pr_info("skipping end of device tests because last "
-		       "block is bad\n");
-	else {
-		/* Attempt to write off end of device */
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = mtd->ecclayout->oobavail + 1;
-		ops.oobretlen = 0;
-		ops.ooboffs   = 0;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = writebuf;
-		pr_info("attempting to write past end of device\n");
-		pr_info("an error is expected...\n");
-		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
-		if (err) {
-			pr_info("error occurred as expected\n");
-			err = 0;
-		} else {
-			pr_err("error: wrote past end of device\n");
-			errcnt += 1;
-		}
-
-		/* Attempt to read off end of device */
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = mtd->ecclayout->oobavail + 1;
-		ops.oobretlen = 0;
-		ops.ooboffs   = 0;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = readbuf;
-		pr_info("attempting to read past end of device\n");
-		pr_info("an error is expected...\n");
-		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
-		if (err) {
-			pr_info("error occurred as expected\n");
-			err = 0;
-		} else {
-			pr_err("error: read past end of device\n");
-			errcnt += 1;
-		}
-
-		err = erase_eraseblock(ebcnt - 1);
-		if (err)
-			goto out;
-
-		/* Attempt to write off end of device */
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = mtd->ecclayout->oobavail;
-		ops.oobretlen = 0;
-		ops.ooboffs   = 1;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = writebuf;
-		pr_info("attempting to write past end of device\n");
-		pr_info("an error is expected...\n");
-		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
-		if (err) {
-			pr_info("error occurred as expected\n");
-			err = 0;
-		} else {
-			pr_err("error: wrote past end of device\n");
-			errcnt += 1;
-		}
-
-		/* Attempt to read off end of device */
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = mtd->ecclayout->oobavail;
-		ops.oobretlen = 0;
-		ops.ooboffs   = 1;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = readbuf;
-		pr_info("attempting to read past end of device\n");
-		pr_info("an error is expected...\n");
-		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
-		if (err) {
-			pr_info("error occurred as expected\n");
-			err = 0;
-		} else {
-			pr_err("error: read past end of device\n");
-			errcnt += 1;
-		}
-	}
-
-	/* Fifth test: write / read across block boundaries */
-	pr_info("test 5 of 5\n");
-
-	/* Erase all eraseblocks */
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	/* Write all eraseblocks */
-	prandom_seed_state(&rnd_state, 11);
-	pr_info("writing OOBs of whole device\n");
-	for (i = 0; i < ebcnt - 1; ++i) {
-		int cnt = 2;
-		int pg;
-		size_t sz = mtd->ecclayout->oobavail;
-		if (bbt[i] || bbt[i + 1])
-			continue;
-		addr = (i + 1) * mtd->erasesize - mtd->writesize;
-		for (pg = 0; pg < cnt; ++pg) {
-			prandom_bytes_state(&rnd_state, writebuf, sz);
-			ops.mode      = MTD_OPS_AUTO_OOB;
-			ops.len       = 0;
-			ops.retlen    = 0;
-			ops.ooblen    = sz;
-			ops.oobretlen = 0;
-			ops.ooboffs   = 0;
-			ops.datbuf    = NULL;
-			ops.oobbuf    = writebuf;
-			err = mtd_write_oob(mtd, addr, &ops);
-			if (err)
-				goto out;
-			if (i % 256 == 0)
-				pr_info("written up to eraseblock %u\n", i);
-			cond_resched();
-			addr += mtd->writesize;
-		}
-	}
-	pr_info("written %u eraseblocks\n", i);
-
-	/* Check all eraseblocks */
-	prandom_seed_state(&rnd_state, 11);
-	pr_info("verifying all eraseblocks\n");
-	for (i = 0; i < ebcnt - 1; ++i) {
-		if (bbt[i] || bbt[i + 1])
-			continue;
-		prandom_bytes_state(&rnd_state, writebuf,
-					mtd->ecclayout->oobavail * 2);
-		addr = (i + 1) * mtd->erasesize - mtd->writesize;
-		ops.mode      = MTD_OPS_AUTO_OOB;
-		ops.len       = 0;
-		ops.retlen    = 0;
-		ops.ooblen    = mtd->ecclayout->oobavail * 2;
-		ops.oobretlen = 0;
-		ops.ooboffs   = 0;
-		ops.datbuf    = NULL;
-		ops.oobbuf    = readbuf;
-		err = mtd_read_oob(mtd, addr, &ops);
-		if (err)
-			goto out;
-		if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
-			pr_err("error: verify failed at %#llx\n",
-			       (long long)addr);
-			errcnt += 1;
-			if (errcnt > 1000) {
-				pr_err("error: too many errors\n");
-				goto out;
-			}
-		}
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-
-	pr_info("finished with %d errors\n", errcnt);
-out:
-	kfree(bbt);
-	kfree(writebuf);
-	kfree(readbuf);
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(mtd_oobtest_init);
-
-static void __exit mtd_oobtest_exit(void)
-{
-	return;
-}
-module_exit(mtd_oobtest_exit);
-
-MODULE_DESCRIPTION("Out-of-band test module");
-MODULE_AUTHOR("Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
deleted file mode 100644
index 0c1140b..0000000
--- a/drivers/mtd/tests/mtd_pagetest.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Test page read and write on MTD device.
- *
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <asm/div64.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static struct mtd_info *mtd;
-static unsigned char *twopages;
-static unsigned char *writebuf;
-static unsigned char *boundary;
-static unsigned char *bbt;
-
-static int pgsize;
-static int bufsize;
-static int ebcnt;
-static int pgcnt;
-static int errcnt;
-static struct rnd_state rnd_state;
-
-static int erase_eraseblock(int ebnum)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (err) {
-		pr_err("error %d while erasing EB %d\n", err, ebnum);
-		return err;
-	}
-
-	if (ei.state == MTD_ERASE_FAILED) {
-		pr_err("some erase error occurred at EB %d\n",
-		       ebnum);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int write_eraseblock(int ebnum)
-{
-	int err = 0;
-	size_t written;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
-	cond_resched();
-	err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
-	if (err || written != mtd->erasesize)
-		pr_err("error: write failed at %#llx\n",
-		       (long long)addr);
-
-	return err;
-}
-
-static int verify_eraseblock(int ebnum)
-{
-	uint32_t j;
-	size_t read;
-	int err = 0, i;
-	loff_t addr0, addrn;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	addr0 = 0;
-	for (i = 0; i < ebcnt && bbt[i]; ++i)
-		addr0 += mtd->erasesize;
-
-	addrn = mtd->size;
-	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
-		addrn -= mtd->erasesize;
-
-	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
-	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
-		/* Do a read to set the internal dataRAMs to different data */
-		err = mtd_read(mtd, addr0, bufsize, &read, twopages);
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != bufsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr0);
-			return err;
-		}
-		err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != bufsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)(addrn - bufsize));
-			return err;
-		}
-		memset(twopages, 0, bufsize);
-		err = mtd_read(mtd, addr, bufsize, &read, twopages);
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != bufsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr);
-			break;
-		}
-		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
-			pr_err("error: verify failed at %#llx\n",
-			       (long long)addr);
-			errcnt += 1;
-		}
-	}
-	/* Check boundary between eraseblocks */
-	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
-		struct rnd_state old_state = rnd_state;
-
-		/* Do a read to set the internal dataRAMs to different data */
-		err = mtd_read(mtd, addr0, bufsize, &read, twopages);
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != bufsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr0);
-			return err;
-		}
-		err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != bufsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)(addrn - bufsize));
-			return err;
-		}
-		memset(twopages, 0, bufsize);
-		err = mtd_read(mtd, addr, bufsize, &read, twopages);
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != bufsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr);
-			return err;
-		}
-		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
-		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
-		if (memcmp(twopages, boundary, bufsize)) {
-			pr_err("error: verify failed at %#llx\n",
-			       (long long)addr);
-			errcnt += 1;
-		}
-		rnd_state = old_state;
-	}
-	return err;
-}
-
-static int crosstest(void)
-{
-	size_t read;
-	int err = 0, i;
-	loff_t addr, addr0, addrn;
-	unsigned char *pp1, *pp2, *pp3, *pp4;
-
-	pr_info("crosstest\n");
-	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
-	if (!pp1) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-	pp2 = pp1 + pgsize;
-	pp3 = pp2 + pgsize;
-	pp4 = pp3 + pgsize;
-	memset(pp1, 0, pgsize * 4);
-
-	addr0 = 0;
-	for (i = 0; i < ebcnt && bbt[i]; ++i)
-		addr0 += mtd->erasesize;
-
-	addrn = mtd->size;
-	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
-		addrn -= mtd->erasesize;
-
-	/* Read 2nd-to-last page to pp1 */
-	addr = addrn - pgsize - pgsize;
-	err = mtd_read(mtd, addr, pgsize, &read, pp1);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr);
-		kfree(pp1);
-		return err;
-	}
-
-	/* Read 3rd-to-last page to pp1 */
-	addr = addrn - pgsize - pgsize - pgsize;
-	err = mtd_read(mtd, addr, pgsize, &read, pp1);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr);
-		kfree(pp1);
-		return err;
-	}
-
-	/* Read first page to pp2 */
-	addr = addr0;
-	pr_info("reading page at %#llx\n", (long long)addr);
-	err = mtd_read(mtd, addr, pgsize, &read, pp2);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr);
-		kfree(pp1);
-		return err;
-	}
-
-	/* Read last page to pp3 */
-	addr = addrn - pgsize;
-	pr_info("reading page at %#llx\n", (long long)addr);
-	err = mtd_read(mtd, addr, pgsize, &read, pp3);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr);
-		kfree(pp1);
-		return err;
-	}
-
-	/* Read first page again to pp4 */
-	addr = addr0;
-	pr_info("reading page at %#llx\n", (long long)addr);
-	err = mtd_read(mtd, addr, pgsize, &read, pp4);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr);
-		kfree(pp1);
-		return err;
-	}
-
-	/* pp2 and pp4 should be the same */
-	pr_info("verifying pages read at %#llx match\n",
-	       (long long)addr0);
-	if (memcmp(pp2, pp4, pgsize)) {
-		pr_err("verify failed!\n");
-		errcnt += 1;
-	} else if (!err)
-		pr_info("crosstest ok\n");
-	kfree(pp1);
-	return err;
-}
-
-static int erasecrosstest(void)
-{
-	size_t read, written;
-	int err = 0, i, ebnum, ebnum2;
-	loff_t addr0;
-	char *readbuf = twopages;
-
-	pr_info("erasecrosstest\n");
-
-	ebnum = 0;
-	addr0 = 0;
-	for (i = 0; i < ebcnt && bbt[i]; ++i) {
-		addr0 += mtd->erasesize;
-		ebnum += 1;
-	}
-
-	ebnum2 = ebcnt - 1;
-	while (ebnum2 && bbt[ebnum2])
-		ebnum2 -= 1;
-
-	pr_info("erasing block %d\n", ebnum);
-	err = erase_eraseblock(ebnum);
-	if (err)
-		return err;
-
-	pr_info("writing 1st page of block %d\n", ebnum);
-	prandom_bytes_state(&rnd_state, writebuf, pgsize);
-	strcpy(writebuf, "There is no data like this!");
-	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
-	if (err || written != pgsize) {
-		pr_info("error: write failed at %#llx\n",
-		       (long long)addr0);
-		return err ? err : -1;
-	}
-
-	pr_info("reading 1st page of block %d\n", ebnum);
-	memset(readbuf, 0, pgsize);
-	err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr0);
-		return err ? err : -1;
-	}
-
-	pr_info("verifying 1st page of block %d\n", ebnum);
-	if (memcmp(writebuf, readbuf, pgsize)) {
-		pr_err("verify failed!\n");
-		errcnt += 1;
-		return -1;
-	}
-
-	pr_info("erasing block %d\n", ebnum);
-	err = erase_eraseblock(ebnum);
-	if (err)
-		return err;
-
-	pr_info("writing 1st page of block %d\n", ebnum);
-	prandom_bytes_state(&rnd_state, writebuf, pgsize);
-	strcpy(writebuf, "There is no data like this!");
-	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
-	if (err || written != pgsize) {
-		pr_err("error: write failed at %#llx\n",
-		       (long long)addr0);
-		return err ? err : -1;
-	}
-
-	pr_info("erasing block %d\n", ebnum2);
-	err = erase_eraseblock(ebnum2);
-	if (err)
-		return err;
-
-	pr_info("reading 1st page of block %d\n", ebnum);
-	memset(readbuf, 0, pgsize);
-	err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr0);
-		return err ? err : -1;
-	}
-
-	pr_info("verifying 1st page of block %d\n", ebnum);
-	if (memcmp(writebuf, readbuf, pgsize)) {
-		pr_err("verify failed!\n");
-		errcnt += 1;
-		return -1;
-	}
-
-	if (!err)
-		pr_info("erasecrosstest ok\n");
-	return err;
-}
-
-static int erasetest(void)
-{
-	size_t read, written;
-	int err = 0, i, ebnum, ok = 1;
-	loff_t addr0;
-
-	pr_info("erasetest\n");
-
-	ebnum = 0;
-	addr0 = 0;
-	for (i = 0; i < ebcnt && bbt[i]; ++i) {
-		addr0 += mtd->erasesize;
-		ebnum += 1;
-	}
-
-	pr_info("erasing block %d\n", ebnum);
-	err = erase_eraseblock(ebnum);
-	if (err)
-		return err;
-
-	pr_info("writing 1st page of block %d\n", ebnum);
-	prandom_bytes_state(&rnd_state, writebuf, pgsize);
-	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
-	if (err || written != pgsize) {
-		pr_err("error: write failed at %#llx\n",
-		       (long long)addr0);
-		return err ? err : -1;
-	}
-
-	pr_info("erasing block %d\n", ebnum);
-	err = erase_eraseblock(ebnum);
-	if (err)
-		return err;
-
-	pr_info("reading 1st page of block %d\n", ebnum);
-	err = mtd_read(mtd, addr0, pgsize, &read, twopages);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != pgsize) {
-		pr_err("error: read failed at %#llx\n",
-		       (long long)addr0);
-		return err ? err : -1;
-	}
-
-	pr_info("verifying 1st page of block %d is all 0xff\n",
-	       ebnum);
-	for (i = 0; i < pgsize; ++i)
-		if (twopages[i] != 0xff) {
-			pr_err("verifying all 0xff failed at %d\n",
-			       i);
-			errcnt += 1;
-			ok = 0;
-			break;
-		}
-
-	if (ok && !err)
-		pr_info("erasetest ok\n");
-
-	return err;
-}
-
-static int is_block_bad(int ebnum)
-{
-	loff_t addr = ebnum * mtd->erasesize;
-	int ret;
-
-	ret = mtd_block_isbad(mtd, addr);
-	if (ret)
-		pr_info("block %d is bad\n", ebnum);
-	return ret;
-}
-
-static int scan_for_bad_eraseblocks(void)
-{
-	int i, bad = 0;
-
-	bbt = kzalloc(ebcnt, GFP_KERNEL);
-	if (!bbt) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	pr_info("scanning for bad eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		bbt[i] = is_block_bad(i) ? 1 : 0;
-		if (bbt[i])
-			bad += 1;
-		cond_resched();
-	}
-	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
-	return 0;
-}
-
-static int __init mtd_pagetest_init(void)
-{
-	int err = 0;
-	uint64_t tmp;
-	uint32_t i;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
-		return -EINVAL;
-	}
-
-	pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->type != MTD_NANDFLASH) {
-		pr_info("this test requires NAND flash\n");
-		goto out;
-	}
-
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / mtd->writesize;
-	pgsize = mtd->writesize;
-
-	pr_info("MTD device size %llu, eraseblock size %u, "
-	       "page size %u, count of eraseblocks %u, pages per "
-	       "eraseblock %u, OOB size %u\n",
-	       (unsigned long long)mtd->size, mtd->erasesize,
-	       pgsize, ebcnt, pgcnt, mtd->oobsize);
-
-	err = -ENOMEM;
-	bufsize = pgsize * 2;
-	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!writebuf) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-	twopages = kmalloc(bufsize, GFP_KERNEL);
-	if (!twopages) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-	boundary = kmalloc(bufsize, GFP_KERNEL);
-	if (!boundary) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-
-	err = scan_for_bad_eraseblocks();
-	if (err)
-		goto out;
-
-	/* Erase all eraseblocks */
-	pr_info("erasing whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = erase_eraseblock(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	pr_info("erased %u eraseblocks\n", i);
-
-	/* Write all eraseblocks */
-	prandom_seed_state(&rnd_state, 1);
-	pr_info("writing whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock(i);
-		if (err)
-			goto out;
-		if (i % 256 == 0)
-			pr_info("written up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("written %u eraseblocks\n", i);
-
-	/* Check all eraseblocks */
-	prandom_seed_state(&rnd_state, 1);
-	pr_info("verifying all eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = verify_eraseblock(i);
-		if (err)
-			goto out;
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-
-	err = crosstest();
-	if (err)
-		goto out;
-
-	err = erasecrosstest();
-	if (err)
-		goto out;
-
-	err = erasetest();
-	if (err)
-		goto out;
-
-	pr_info("finished with %d errors\n", errcnt);
-out:
-
-	kfree(bbt);
-	kfree(boundary);
-	kfree(twopages);
-	kfree(writebuf);
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(mtd_pagetest_init);
-
-static void __exit mtd_pagetest_exit(void)
-{
-	return;
-}
-module_exit(mtd_pagetest_exit);
-
-MODULE_DESCRIPTION("NAND page test");
-MODULE_AUTHOR("Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
deleted file mode 100644
index 266de04..0000000
--- a/drivers/mtd/tests/mtd_readtest.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Check MTD device read.
- *
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static struct mtd_info *mtd;
-static unsigned char *iobuf;
-static unsigned char *iobuf1;
-static unsigned char *bbt;
-
-static int pgsize;
-static int ebcnt;
-static int pgcnt;
-
-static int read_eraseblock_by_page(int ebnum)
-{
-	size_t read;
-	int i, ret, err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-	void *buf = iobuf;
-	void *oobbuf = iobuf1;
-
-	for (i = 0; i < pgcnt; i++) {
-		memset(buf, 0 , pgsize);
-		ret = mtd_read(mtd, addr, pgsize, &read, buf);
-		if (ret == -EUCLEAN)
-			ret = 0;
-		if (ret || read != pgsize) {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr);
-			if (!err)
-				err = ret;
-			if (!err)
-				err = -EINVAL;
-		}
-		if (mtd->oobsize) {
-			struct mtd_oob_ops ops;
-
-			ops.mode      = MTD_OPS_PLACE_OOB;
-			ops.len       = 0;
-			ops.retlen    = 0;
-			ops.ooblen    = mtd->oobsize;
-			ops.oobretlen = 0;
-			ops.ooboffs   = 0;
-			ops.datbuf    = NULL;
-			ops.oobbuf    = oobbuf;
-			ret = mtd_read_oob(mtd, addr, &ops);
-			if ((ret && !mtd_is_bitflip(ret)) ||
-					ops.oobretlen != mtd->oobsize) {
-				pr_err("error: read oob failed at "
-						  "%#llx\n", (long long)addr);
-				if (!err)
-					err = ret;
-				if (!err)
-					err = -EINVAL;
-			}
-			oobbuf += mtd->oobsize;
-		}
-		addr += pgsize;
-		buf += pgsize;
-	}
-
-	return err;
-}
-
-static void dump_eraseblock(int ebnum)
-{
-	int i, j, n;
-	char line[128];
-	int pg, oob;
-
-	pr_info("dumping eraseblock %d\n", ebnum);
-	n = mtd->erasesize;
-	for (i = 0; i < n;) {
-		char *p = line;
-
-		p += sprintf(p, "%05x: ", i);
-		for (j = 0; j < 32 && i < n; j++, i++)
-			p += sprintf(p, "%02x", (unsigned int)iobuf[i]);
-		printk(KERN_CRIT "%s\n", line);
-		cond_resched();
-	}
-	if (!mtd->oobsize)
-		return;
-	pr_info("dumping oob from eraseblock %d\n", ebnum);
-	n = mtd->oobsize;
-	for (pg = 0, i = 0; pg < pgcnt; pg++)
-		for (oob = 0; oob < n;) {
-			char *p = line;
-
-			p += sprintf(p, "%05x: ", i);
-			for (j = 0; j < 32 && oob < n; j++, oob++, i++)
-				p += sprintf(p, "%02x",
-					     (unsigned int)iobuf1[i]);
-			printk(KERN_CRIT "%s\n", line);
-			cond_resched();
-		}
-}
-
-static int is_block_bad(int ebnum)
-{
-	loff_t addr = ebnum * mtd->erasesize;
-	int ret;
-
-	ret = mtd_block_isbad(mtd, addr);
-	if (ret)
-		pr_info("block %d is bad\n", ebnum);
-	return ret;
-}
-
-static int scan_for_bad_eraseblocks(void)
-{
-	int i, bad = 0;
-
-	bbt = kzalloc(ebcnt, GFP_KERNEL);
-	if (!bbt) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	if (!mtd_can_have_bb(mtd))
-		return 0;
-
-	pr_info("scanning for bad eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		bbt[i] = is_block_bad(i) ? 1 : 0;
-		if (bbt[i])
-			bad += 1;
-		cond_resched();
-	}
-	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
-	return 0;
-}
-
-static int __init mtd_readtest_init(void)
-{
-	uint64_t tmp;
-	int err, i;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		return -EINVAL;
-	}
-
-	pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: Cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->writesize == 1) {
-		pr_info("not NAND flash, assume page size is 512 "
-		       "bytes.\n");
-		pgsize = 512;
-	} else
-		pgsize = mtd->writesize;
-
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / pgsize;
-
-	pr_info("MTD device size %llu, eraseblock size %u, "
-	       "page size %u, count of eraseblocks %u, pages per "
-	       "eraseblock %u, OOB size %u\n",
-	       (unsigned long long)mtd->size, mtd->erasesize,
-	       pgsize, ebcnt, pgcnt, mtd->oobsize);
-
-	err = -ENOMEM;
-	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!iobuf) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-	iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!iobuf1) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-
-	err = scan_for_bad_eraseblocks();
-	if (err)
-		goto out;
-
-	/* Read all eraseblocks 1 page at a time */
-	pr_info("testing page read\n");
-	for (i = 0; i < ebcnt; ++i) {
-		int ret;
-
-		if (bbt[i])
-			continue;
-		ret = read_eraseblock_by_page(i);
-		if (ret) {
-			dump_eraseblock(i);
-			if (!err)
-				err = ret;
-		}
-		cond_resched();
-	}
-
-	if (err)
-		pr_info("finished with errors\n");
-	else
-		pr_info("finished\n");
-
-out:
-
-	kfree(iobuf);
-	kfree(iobuf1);
-	kfree(bbt);
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(mtd_readtest_init);
-
-static void __exit mtd_readtest_exit(void)
-{
-	return;
-}
-module_exit(mtd_readtest_exit);
-
-MODULE_DESCRIPTION("Read test module");
-MODULE_AUTHOR("Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c
deleted file mode 100644
index a6ce9c1..0000000
--- a/drivers/mtd/tests/mtd_speedtest.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright (C) 2007 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Test read and write speed of a MTD device.
- *
- * Author: Adrian Hunter <adrian.hunter@nokia.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static int count;
-module_param(count, int, S_IRUGO);
-MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use "
-			"(0 means use all)");
-
-static struct mtd_info *mtd;
-static unsigned char *iobuf;
-static unsigned char *bbt;
-
-static int pgsize;
-static int ebcnt;
-static int pgcnt;
-static int goodebcnt;
-static struct timeval start, finish;
-
-
-static int erase_eraseblock(int ebnum)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (err) {
-		pr_err("error %d while erasing EB %d\n", err, ebnum);
-		return err;
-	}
-
-	if (ei.state == MTD_ERASE_FAILED) {
-		pr_err("some erase error occurred at EB %d\n",
-		       ebnum);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int multiblock_erase(int ebnum, int blocks)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize * blocks;
-
-	err = mtd_erase(mtd, &ei);
-	if (err) {
-		pr_err("error %d while erasing EB %d, blocks %d\n",
-		       err, ebnum, blocks);
-		return err;
-	}
-
-	if (ei.state == MTD_ERASE_FAILED) {
-		pr_err("some erase error occurred at EB %d,"
-		       "blocks %d\n", ebnum, blocks);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int erase_whole_device(void)
-{
-	int err;
-	unsigned int i;
-
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = erase_eraseblock(i);
-		if (err)
-			return err;
-		cond_resched();
-	}
-	return 0;
-}
-
-static int write_eraseblock(int ebnum)
-{
-	size_t written;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf);
-	if (err || written != mtd->erasesize) {
-		pr_err("error: write failed at %#llx\n", addr);
-		if (!err)
-			err = -EINVAL;
-	}
-
-	return err;
-}
-
-static int write_eraseblock_by_page(int ebnum)
-{
-	size_t written;
-	int i, err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-	void *buf = iobuf;
-
-	for (i = 0; i < pgcnt; i++) {
-		err = mtd_write(mtd, addr, pgsize, &written, buf);
-		if (err || written != pgsize) {
-			pr_err("error: write failed at %#llx\n",
-			       addr);
-			if (!err)
-				err = -EINVAL;
-			break;
-		}
-		addr += pgsize;
-		buf += pgsize;
-	}
-
-	return err;
-}
-
-static int write_eraseblock_by_2pages(int ebnum)
-{
-	size_t written, sz = pgsize * 2;
-	int i, n = pgcnt / 2, err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-	void *buf = iobuf;
-
-	for (i = 0; i < n; i++) {
-		err = mtd_write(mtd, addr, sz, &written, buf);
-		if (err || written != sz) {
-			pr_err("error: write failed at %#llx\n",
-			       addr);
-			if (!err)
-				err = -EINVAL;
-			return err;
-		}
-		addr += sz;
-		buf += sz;
-	}
-	if (pgcnt % 2) {
-		err = mtd_write(mtd, addr, pgsize, &written, buf);
-		if (err || written != pgsize) {
-			pr_err("error: write failed at %#llx\n",
-			       addr);
-			if (!err)
-				err = -EINVAL;
-		}
-	}
-
-	return err;
-}
-
-static int read_eraseblock(int ebnum)
-{
-	size_t read;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	err = mtd_read(mtd, addr, mtd->erasesize, &read, iobuf);
-	/* Ignore corrected ECC errors */
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (err || read != mtd->erasesize) {
-		pr_err("error: read failed at %#llx\n", addr);
-		if (!err)
-			err = -EINVAL;
-	}
-
-	return err;
-}
-
-static int read_eraseblock_by_page(int ebnum)
-{
-	size_t read;
-	int i, err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-	void *buf = iobuf;
-
-	for (i = 0; i < pgcnt; i++) {
-		err = mtd_read(mtd, addr, pgsize, &read, buf);
-		/* Ignore corrected ECC errors */
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != pgsize) {
-			pr_err("error: read failed at %#llx\n",
-			       addr);
-			if (!err)
-				err = -EINVAL;
-			break;
-		}
-		addr += pgsize;
-		buf += pgsize;
-	}
-
-	return err;
-}
-
-static int read_eraseblock_by_2pages(int ebnum)
-{
-	size_t read, sz = pgsize * 2;
-	int i, n = pgcnt / 2, err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-	void *buf = iobuf;
-
-	for (i = 0; i < n; i++) {
-		err = mtd_read(mtd, addr, sz, &read, buf);
-		/* Ignore corrected ECC errors */
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != sz) {
-			pr_err("error: read failed at %#llx\n",
-			       addr);
-			if (!err)
-				err = -EINVAL;
-			return err;
-		}
-		addr += sz;
-		buf += sz;
-	}
-	if (pgcnt % 2) {
-		err = mtd_read(mtd, addr, pgsize, &read, buf);
-		/* Ignore corrected ECC errors */
-		if (mtd_is_bitflip(err))
-			err = 0;
-		if (err || read != pgsize) {
-			pr_err("error: read failed at %#llx\n",
-			       addr);
-			if (!err)
-				err = -EINVAL;
-		}
-	}
-
-	return err;
-}
-
-static int is_block_bad(int ebnum)
-{
-	loff_t addr = ebnum * mtd->erasesize;
-	int ret;
-
-	ret = mtd_block_isbad(mtd, addr);
-	if (ret)
-		pr_info("block %d is bad\n", ebnum);
-	return ret;
-}
-
-static inline void start_timing(void)
-{
-	do_gettimeofday(&start);
-}
-
-static inline void stop_timing(void)
-{
-	do_gettimeofday(&finish);
-}
-
-static long calc_speed(void)
-{
-	uint64_t k;
-	long ms;
-
-	ms = (finish.tv_sec - start.tv_sec) * 1000 +
-	     (finish.tv_usec - start.tv_usec) / 1000;
-	if (ms == 0)
-		return 0;
-	k = goodebcnt * (mtd->erasesize / 1024) * 1000;
-	do_div(k, ms);
-	return k;
-}
-
-static int scan_for_bad_eraseblocks(void)
-{
-	int i, bad = 0;
-
-	bbt = kzalloc(ebcnt, GFP_KERNEL);
-	if (!bbt) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	if (!mtd_can_have_bb(mtd))
-		goto out;
-
-	pr_info("scanning for bad eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		bbt[i] = is_block_bad(i) ? 1 : 0;
-		if (bbt[i])
-			bad += 1;
-		cond_resched();
-	}
-	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
-out:
-	goodebcnt = ebcnt - bad;
-	return 0;
-}
-
-static int __init mtd_speedtest_init(void)
-{
-	int err, i, blocks, j, k;
-	long speed;
-	uint64_t tmp;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
-		return -EINVAL;
-	}
-
-	if (count)
-		pr_info("MTD device: %d    count: %d\n", dev, count);
-	else
-		pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->writesize == 1) {
-		pr_info("not NAND flash, assume page size is 512 "
-		       "bytes.\n");
-		pgsize = 512;
-	} else
-		pgsize = mtd->writesize;
-
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / pgsize;
-
-	pr_info("MTD device size %llu, eraseblock size %u, "
-	       "page size %u, count of eraseblocks %u, pages per "
-	       "eraseblock %u, OOB size %u\n",
-	       (unsigned long long)mtd->size, mtd->erasesize,
-	       pgsize, ebcnt, pgcnt, mtd->oobsize);
-
-	if (count > 0 && count < ebcnt)
-		ebcnt = count;
-
-	err = -ENOMEM;
-	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!iobuf) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-
-	prandom_bytes(iobuf, mtd->erasesize);
-
-	err = scan_for_bad_eraseblocks();
-	if (err)
-		goto out;
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	/* Write all eraseblocks, 1 eraseblock at a time */
-	pr_info("testing eraseblock write speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("eraseblock write speed is %ld KiB/s\n", speed);
-
-	/* Read all eraseblocks, 1 eraseblock at a time */
-	pr_info("testing eraseblock read speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = read_eraseblock(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("eraseblock read speed is %ld KiB/s\n", speed);
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	/* Write all eraseblocks, 1 page at a time */
-	pr_info("testing page write speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock_by_page(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("page write speed is %ld KiB/s\n", speed);
-
-	/* Read all eraseblocks, 1 page at a time */
-	pr_info("testing page read speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = read_eraseblock_by_page(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("page read speed is %ld KiB/s\n", speed);
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	/* Write all eraseblocks, 2 pages at a time */
-	pr_info("testing 2 page write speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock_by_2pages(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("2 page write speed is %ld KiB/s\n", speed);
-
-	/* Read all eraseblocks, 2 pages at a time */
-	pr_info("testing 2 page read speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = read_eraseblock_by_2pages(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("2 page read speed is %ld KiB/s\n", speed);
-
-	/* Erase all eraseblocks */
-	pr_info("Testing erase speed\n");
-	start_timing();
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = erase_eraseblock(i);
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	stop_timing();
-	speed = calc_speed();
-	pr_info("erase speed is %ld KiB/s\n", speed);
-
-	/* Multi-block erase all eraseblocks */
-	for (k = 1; k < 7; k++) {
-		blocks = 1 << k;
-		pr_info("Testing %dx multi-block erase speed\n",
-		       blocks);
-		start_timing();
-		for (i = 0; i < ebcnt; ) {
-			for (j = 0; j < blocks && (i + j) < ebcnt; j++)
-				if (bbt[i + j])
-					break;
-			if (j < 1) {
-				i++;
-				continue;
-			}
-			err = multiblock_erase(i, j);
-			if (err)
-				goto out;
-			cond_resched();
-			i += j;
-		}
-		stop_timing();
-		speed = calc_speed();
-		pr_info("%dx multi-block erase speed is %ld KiB/s\n",
-		       blocks, speed);
-	}
-	pr_info("finished\n");
-out:
-	kfree(iobuf);
-	kfree(bbt);
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(mtd_speedtest_init);
-
-static void __exit mtd_speedtest_exit(void)
-{
-	return;
-}
-module_exit(mtd_speedtest_exit);
-
-MODULE_DESCRIPTION("Speed test module");
-MODULE_AUTHOR("Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
deleted file mode 100644
index 787f539..0000000
--- a/drivers/mtd/tests/mtd_stresstest.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Test random reads, writes and erases on MTD device.
- *
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-#include <linux/random.h>
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static int count = 10000;
-module_param(count, int, S_IRUGO);
-MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)");
-
-static struct mtd_info *mtd;
-static unsigned char *writebuf;
-static unsigned char *readbuf;
-static unsigned char *bbt;
-static int *offsets;
-
-static int pgsize;
-static int bufsize;
-static int ebcnt;
-static int pgcnt;
-
-static int rand_eb(void)
-{
-	unsigned int eb;
-
-again:
-	eb = prandom_u32();
-	/* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */
-	eb %= (ebcnt - 1);
-	if (bbt[eb])
-		goto again;
-	return eb;
-}
-
-static int rand_offs(void)
-{
-	unsigned int offs;
-
-	offs = prandom_u32();
-	offs %= bufsize;
-	return offs;
-}
-
-static int rand_len(int offs)
-{
-	unsigned int len;
-
-	len = prandom_u32();
-	len %= (bufsize - offs);
-	return len;
-}
-
-static int erase_eraseblock(int ebnum)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (unlikely(err)) {
-		pr_err("error %d while erasing EB %d\n", err, ebnum);
-		return err;
-	}
-
-	if (unlikely(ei.state == MTD_ERASE_FAILED)) {
-		pr_err("some erase error occurred at EB %d\n",
-		       ebnum);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int is_block_bad(int ebnum)
-{
-	loff_t addr = ebnum * mtd->erasesize;
-	int ret;
-
-	ret = mtd_block_isbad(mtd, addr);
-	if (ret)
-		pr_info("block %d is bad\n", ebnum);
-	return ret;
-}
-
-static int do_read(void)
-{
-	size_t read;
-	int eb = rand_eb();
-	int offs = rand_offs();
-	int len = rand_len(offs), err;
-	loff_t addr;
-
-	if (bbt[eb + 1]) {
-		if (offs >= mtd->erasesize)
-			offs -= mtd->erasesize;
-		if (offs + len > mtd->erasesize)
-			len = mtd->erasesize - offs;
-	}
-	addr = eb * mtd->erasesize + offs;
-	err = mtd_read(mtd, addr, len, &read, readbuf);
-	if (mtd_is_bitflip(err))
-		err = 0;
-	if (unlikely(err || read != len)) {
-		pr_err("error: read failed at 0x%llx\n",
-		       (long long)addr);
-		if (!err)
-			err = -EINVAL;
-		return err;
-	}
-	return 0;
-}
-
-static int do_write(void)
-{
-	int eb = rand_eb(), offs, err, len;
-	size_t written;
-	loff_t addr;
-
-	offs = offsets[eb];
-	if (offs >= mtd->erasesize) {
-		err = erase_eraseblock(eb);
-		if (err)
-			return err;
-		offs = offsets[eb] = 0;
-	}
-	len = rand_len(offs);
-	len = ((len + pgsize - 1) / pgsize) * pgsize;
-	if (offs + len > mtd->erasesize) {
-		if (bbt[eb + 1])
-			len = mtd->erasesize - offs;
-		else {
-			err = erase_eraseblock(eb + 1);
-			if (err)
-				return err;
-			offsets[eb + 1] = 0;
-		}
-	}
-	addr = eb * mtd->erasesize + offs;
-	err = mtd_write(mtd, addr, len, &written, writebuf);
-	if (unlikely(err || written != len)) {
-		pr_err("error: write failed at 0x%llx\n",
-		       (long long)addr);
-		if (!err)
-			err = -EINVAL;
-		return err;
-	}
-	offs += len;
-	while (offs > mtd->erasesize) {
-		offsets[eb++] = mtd->erasesize;
-		offs -= mtd->erasesize;
-	}
-	offsets[eb] = offs;
-	return 0;
-}
-
-static int do_operation(void)
-{
-	if (prandom_u32() & 1)
-		return do_read();
-	else
-		return do_write();
-}
-
-static int scan_for_bad_eraseblocks(void)
-{
-	int i, bad = 0;
-
-	bbt = kzalloc(ebcnt, GFP_KERNEL);
-	if (!bbt) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	if (!mtd_can_have_bb(mtd))
-		return 0;
-
-	pr_info("scanning for bad eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		bbt[i] = is_block_bad(i) ? 1 : 0;
-		if (bbt[i])
-			bad += 1;
-		cond_resched();
-	}
-	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
-	return 0;
-}
-
-static int __init mtd_stresstest_init(void)
-{
-	int err;
-	int i, op;
-	uint64_t tmp;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
-		return -EINVAL;
-	}
-
-	pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->writesize == 1) {
-		pr_info("not NAND flash, assume page size is 512 "
-		       "bytes.\n");
-		pgsize = 512;
-	} else
-		pgsize = mtd->writesize;
-
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / pgsize;
-
-	pr_info("MTD device size %llu, eraseblock size %u, "
-	       "page size %u, count of eraseblocks %u, pages per "
-	       "eraseblock %u, OOB size %u\n",
-	       (unsigned long long)mtd->size, mtd->erasesize,
-	       pgsize, ebcnt, pgcnt, mtd->oobsize);
-
-	if (ebcnt < 2) {
-		pr_err("error: need at least 2 eraseblocks\n");
-		err = -ENOSPC;
-		goto out_put_mtd;
-	}
-
-	/* Read or write up 2 eraseblocks at a time */
-	bufsize = mtd->erasesize * 2;
-
-	err = -ENOMEM;
-	readbuf = vmalloc(bufsize);
-	writebuf = vmalloc(bufsize);
-	offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL);
-	if (!readbuf || !writebuf || !offsets) {
-		pr_err("error: cannot allocate memory\n");
-		goto out;
-	}
-	for (i = 0; i < ebcnt; i++)
-		offsets[i] = mtd->erasesize;
-	prandom_bytes(writebuf, bufsize);
-
-	err = scan_for_bad_eraseblocks();
-	if (err)
-		goto out;
-
-	/* Do operations */
-	pr_info("doing operations\n");
-	for (op = 0; op < count; op++) {
-		if ((op & 1023) == 0)
-			pr_info("%d operations done\n", op);
-		err = do_operation();
-		if (err)
-			goto out;
-		cond_resched();
-	}
-	pr_info("finished, %d operations done\n", op);
-
-out:
-	kfree(offsets);
-	kfree(bbt);
-	vfree(writebuf);
-	vfree(readbuf);
-out_put_mtd:
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(mtd_stresstest_init);
-
-static void __exit mtd_stresstest_exit(void)
-{
-	return;
-}
-module_exit(mtd_stresstest_exit);
-
-MODULE_DESCRIPTION("Stress test module");
-MODULE_AUTHOR("Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c
deleted file mode 100644
index aade56f..0000000
--- a/drivers/mtd/tests/mtd_subpagetest.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (C) 2006-2007 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Test sub-page read and write on MTD device.
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static struct mtd_info *mtd;
-static unsigned char *writebuf;
-static unsigned char *readbuf;
-static unsigned char *bbt;
-
-static int subpgsize;
-static int bufsize;
-static int ebcnt;
-static int pgcnt;
-static int errcnt;
-static struct rnd_state rnd_state;
-
-static inline void clear_data(unsigned char *buf, size_t len)
-{
-	memset(buf, 0, len);
-}
-
-static int erase_eraseblock(int ebnum)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (err) {
-		pr_err("error %d while erasing EB %d\n", err, ebnum);
-		return err;
-	}
-
-	if (ei.state == MTD_ERASE_FAILED) {
-		pr_err("some erase error occurred at EB %d\n",
-		       ebnum);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int erase_whole_device(void)
-{
-	int err;
-	unsigned int i;
-
-	pr_info("erasing whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = erase_eraseblock(i);
-		if (err)
-			return err;
-		cond_resched();
-	}
-	pr_info("erased %u eraseblocks\n", i);
-	return 0;
-}
-
-static int write_eraseblock(int ebnum)
-{
-	size_t written;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
-	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
-	if (unlikely(err || written != subpgsize)) {
-		pr_err("error: write failed at %#llx\n",
-		       (long long)addr);
-		if (written != subpgsize) {
-			pr_err("  write size: %#x\n", subpgsize);
-			pr_err("  written: %#zx\n", written);
-		}
-		return err ? err : -1;
-	}
-
-	addr += subpgsize;
-
-	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
-	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
-	if (unlikely(err || written != subpgsize)) {
-		pr_err("error: write failed at %#llx\n",
-		       (long long)addr);
-		if (written != subpgsize) {
-			pr_err("  write size: %#x\n", subpgsize);
-			pr_err("  written: %#zx\n", written);
-		}
-		return err ? err : -1;
-	}
-
-	return err;
-}
-
-static int write_eraseblock2(int ebnum)
-{
-	size_t written;
-	int err = 0, k;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	for (k = 1; k < 33; ++k) {
-		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
-			break;
-		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
-		err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
-		if (unlikely(err || written != subpgsize * k)) {
-			pr_err("error: write failed at %#llx\n",
-			       (long long)addr);
-			if (written != subpgsize) {
-				pr_err("  write size: %#x\n",
-				       subpgsize * k);
-				pr_err("  written: %#08zx\n",
-				       written);
-			}
-			return err ? err : -1;
-		}
-		addr += subpgsize * k;
-	}
-
-	return err;
-}
-
-static void print_subpage(unsigned char *p)
-{
-	int i, j;
-
-	for (i = 0; i < subpgsize; ) {
-		for (j = 0; i < subpgsize && j < 32; ++i, ++j)
-			printk("%02x", *p++);
-		printk("\n");
-	}
-}
-
-static int verify_eraseblock(int ebnum)
-{
-	size_t read;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
-	clear_data(readbuf, subpgsize);
-	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
-	if (unlikely(err || read != subpgsize)) {
-		if (mtd_is_bitflip(err) && read == subpgsize) {
-			pr_info("ECC correction at %#llx\n",
-			       (long long)addr);
-			err = 0;
-		} else {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr);
-			return err ? err : -1;
-		}
-	}
-	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-		pr_err("error: verify failed at %#llx\n",
-		       (long long)addr);
-		pr_info("------------- written----------------\n");
-		print_subpage(writebuf);
-		pr_info("------------- read ------------------\n");
-		print_subpage(readbuf);
-		pr_info("-------------------------------------\n");
-		errcnt += 1;
-	}
-
-	addr += subpgsize;
-
-	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
-	clear_data(readbuf, subpgsize);
-	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
-	if (unlikely(err || read != subpgsize)) {
-		if (mtd_is_bitflip(err) && read == subpgsize) {
-			pr_info("ECC correction at %#llx\n",
-			       (long long)addr);
-			err = 0;
-		} else {
-			pr_err("error: read failed at %#llx\n",
-			       (long long)addr);
-			return err ? err : -1;
-		}
-	}
-	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-		pr_info("error: verify failed at %#llx\n",
-		       (long long)addr);
-		pr_info("------------- written----------------\n");
-		print_subpage(writebuf);
-		pr_info("------------- read ------------------\n");
-		print_subpage(readbuf);
-		pr_info("-------------------------------------\n");
-		errcnt += 1;
-	}
-
-	return err;
-}
-
-static int verify_eraseblock2(int ebnum)
-{
-	size_t read;
-	int err = 0, k;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	for (k = 1; k < 33; ++k) {
-		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
-			break;
-		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
-		clear_data(readbuf, subpgsize * k);
-		err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
-		if (unlikely(err || read != subpgsize * k)) {
-			if (mtd_is_bitflip(err) && read == subpgsize * k) {
-				pr_info("ECC correction at %#llx\n",
-				       (long long)addr);
-				err = 0;
-			} else {
-				pr_err("error: read failed at "
-				       "%#llx\n", (long long)addr);
-				return err ? err : -1;
-			}
-		}
-		if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
-			pr_err("error: verify failed at %#llx\n",
-			       (long long)addr);
-			errcnt += 1;
-		}
-		addr += subpgsize * k;
-	}
-
-	return err;
-}
-
-static int verify_eraseblock_ff(int ebnum)
-{
-	uint32_t j;
-	size_t read;
-	int err = 0;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(writebuf, 0xff, subpgsize);
-	for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
-		clear_data(readbuf, subpgsize);
-		err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
-		if (unlikely(err || read != subpgsize)) {
-			if (mtd_is_bitflip(err) && read == subpgsize) {
-				pr_info("ECC correction at %#llx\n",
-				       (long long)addr);
-				err = 0;
-			} else {
-				pr_err("error: read failed at "
-				       "%#llx\n", (long long)addr);
-				return err ? err : -1;
-			}
-		}
-		if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-			pr_err("error: verify 0xff failed at "
-			       "%#llx\n", (long long)addr);
-			errcnt += 1;
-		}
-		addr += subpgsize;
-	}
-
-	return err;
-}
-
-static int verify_all_eraseblocks_ff(void)
-{
-	int err;
-	unsigned int i;
-
-	pr_info("verifying all eraseblocks for 0xff\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = verify_eraseblock_ff(i);
-		if (err)
-			return err;
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-	return 0;
-}
-
-static int is_block_bad(int ebnum)
-{
-	loff_t addr = ebnum * mtd->erasesize;
-	int ret;
-
-	ret = mtd_block_isbad(mtd, addr);
-	if (ret)
-		pr_info("block %d is bad\n", ebnum);
-	return ret;
-}
-
-static int scan_for_bad_eraseblocks(void)
-{
-	int i, bad = 0;
-
-	bbt = kzalloc(ebcnt, GFP_KERNEL);
-	if (!bbt) {
-		pr_err("error: cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	pr_info("scanning for bad eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		bbt[i] = is_block_bad(i) ? 1 : 0;
-		if (bbt[i])
-			bad += 1;
-		cond_resched();
-	}
-	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
-	return 0;
-}
-
-static int __init mtd_subpagetest_init(void)
-{
-	int err = 0;
-	uint32_t i;
-	uint64_t tmp;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
-		return -EINVAL;
-	}
-
-	pr_info("MTD device: %d\n", dev);
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->type != MTD_NANDFLASH) {
-		pr_info("this test requires NAND flash\n");
-		goto out;
-	}
-
-	subpgsize = mtd->writesize >> mtd->subpage_sft;
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / mtd->writesize;
-
-	pr_info("MTD device size %llu, eraseblock size %u, "
-	       "page size %u, subpage size %u, count of eraseblocks %u, "
-	       "pages per eraseblock %u, OOB size %u\n",
-	       (unsigned long long)mtd->size, mtd->erasesize,
-	       mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
-
-	err = -ENOMEM;
-	bufsize = subpgsize * 32;
-	writebuf = kmalloc(bufsize, GFP_KERNEL);
-	if (!writebuf) {
-		pr_info("error: cannot allocate memory\n");
-		goto out;
-	}
-	readbuf = kmalloc(bufsize, GFP_KERNEL);
-	if (!readbuf) {
-		pr_info("error: cannot allocate memory\n");
-		goto out;
-	}
-
-	err = scan_for_bad_eraseblocks();
-	if (err)
-		goto out;
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	pr_info("writing whole device\n");
-	prandom_seed_state(&rnd_state, 1);
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock(i);
-		if (unlikely(err))
-			goto out;
-		if (i % 256 == 0)
-			pr_info("written up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("written %u eraseblocks\n", i);
-
-	prandom_seed_state(&rnd_state, 1);
-	pr_info("verifying all eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = verify_eraseblock(i);
-		if (unlikely(err))
-			goto out;
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	err = verify_all_eraseblocks_ff();
-	if (err)
-		goto out;
-
-	/* Write all eraseblocks */
-	prandom_seed_state(&rnd_state, 3);
-	pr_info("writing whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock2(i);
-		if (unlikely(err))
-			goto out;
-		if (i % 256 == 0)
-			pr_info("written up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("written %u eraseblocks\n", i);
-
-	/* Check all eraseblocks */
-	prandom_seed_state(&rnd_state, 3);
-	pr_info("verifying all eraseblocks\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = verify_eraseblock2(i);
-		if (unlikely(err))
-			goto out;
-		if (i % 256 == 0)
-			pr_info("verified up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	pr_info("verified %u eraseblocks\n", i);
-
-	err = erase_whole_device();
-	if (err)
-		goto out;
-
-	err = verify_all_eraseblocks_ff();
-	if (err)
-		goto out;
-
-	pr_info("finished with %d errors\n", errcnt);
-
-out:
-	kfree(bbt);
-	kfree(readbuf);
-	kfree(writebuf);
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(mtd_subpagetest_init);
-
-static void __exit mtd_subpagetest_exit(void)
-{
-	return;
-}
-module_exit(mtd_subpagetest_exit);
-
-MODULE_DESCRIPTION("Subpage test module");
-MODULE_AUTHOR("Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_test.c b/drivers/mtd/tests/mtd_test.c
new file mode 100644
index 0000000..9e63896
--- /dev/null
+++ b/drivers/mtd/tests/mtd_test.c
@@ -0,0 +1,110 @@
+#define pr_fmt(fmt) "mtd_test: " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/printk.h>
+
+#include "mtd_test.h"
+
+int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum)
+{
+	int err;
+	struct erase_info ei;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	memset(&ei, 0, sizeof(struct erase_info));
+	ei.mtd  = mtd;
+	ei.addr = addr;
+	ei.len  = mtd->erasesize;
+
+	err = mtd_erase(mtd, &ei);
+	if (err) {
+		pr_info("error %d while erasing EB %d\n", err, ebnum);
+		return err;
+	}
+
+	if (ei.state == MTD_ERASE_FAILED) {
+		pr_info("some erase error occurred at EB %d\n", ebnum);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum)
+{
+	int ret;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	ret = mtd_block_isbad(mtd, addr);
+	if (ret)
+		pr_info("block %d is bad\n", ebnum);
+
+	return ret;
+}
+
+int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
+					unsigned int eb, int ebcnt)
+{
+	int i, bad = 0;
+
+	if (!mtd_can_have_bb(mtd))
+		return 0;
+
+	pr_info("scanning for bad eraseblocks\n");
+	for (i = 0; i < ebcnt; ++i) {
+		bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0;
+		if (bbt[i])
+			bad += 1;
+		cond_resched();
+	}
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
+
+	return 0;
+}
+
+int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
+				unsigned int eb, int ebcnt)
+{
+	int err;
+	unsigned int i;
+
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = mtdtest_erase_eraseblock(mtd, eb + i);
+		if (err)
+			return err;
+		cond_resched();
+	}
+
+	return 0;
+}
+
+int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf)
+{
+	size_t read;
+	int err;
+
+	err = mtd_read(mtd, addr, size, &read, buf);
+	/* Ignore corrected ECC errors */
+	if (mtd_is_bitflip(err))
+		err = 0;
+	if (!err && read != size)
+		err = -EINVAL;
+
+	return err;
+}
+
+int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
+		const void *buf)
+{
+	size_t written;
+	int err;
+
+	err = mtd_write(mtd, addr, size, &written, buf);
+	if (!err && written != size)
+		err = -EIO;
+
+	return err;
+}
diff --git a/drivers/mtd/tests/mtd_test.h b/drivers/mtd/tests/mtd_test.h
new file mode 100644
index 0000000..f437c77
--- /dev/null
+++ b/drivers/mtd/tests/mtd_test.h
@@ -0,0 +1,11 @@
+#include <linux/mtd/mtd.h>
+
+int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum);
+int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
+					unsigned int eb, int ebcnt);
+int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
+				unsigned int eb, int ebcnt);
+
+int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf);
+int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
+		const void *buf);
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c
deleted file mode 100644
index 3a9f6a6..0000000
--- a/drivers/mtd/tests/mtd_torturetest.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Artem Bityutskiy
- * Copyright (C) 2006-2008 Jarkko Lavinen
- * Copyright (C) 2006-2008 Adrian Hunter
- *
- * This program is free software; you can 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; see the file COPYING. If not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Authors: Artem Bityutskiy, Jarkko Lavinen, Adria Hunter
- *
- * WARNING: this test program may kill your flash and your device. Do not
- * use it unless you know what you do. Authors are not responsible for any
- * damage caused by this program.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/err.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-
-#define RETRIES 3
-
-static int eb = 8;
-module_param(eb, int, S_IRUGO);
-MODULE_PARM_DESC(eb, "eraseblock number within the selected MTD device");
-
-static int ebcnt = 32;
-module_param(ebcnt, int, S_IRUGO);
-MODULE_PARM_DESC(ebcnt, "number of consecutive eraseblocks to torture");
-
-static int pgcnt;
-module_param(pgcnt, int, S_IRUGO);
-MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)");
-
-static int dev = -EINVAL;
-module_param(dev, int, S_IRUGO);
-MODULE_PARM_DESC(dev, "MTD device number to use");
-
-static int gran = 512;
-module_param(gran, int, S_IRUGO);
-MODULE_PARM_DESC(gran, "how often the status information should be printed");
-
-static int check = 1;
-module_param(check, int, S_IRUGO);
-MODULE_PARM_DESC(check, "if the written data should be checked");
-
-static unsigned int cycles_count;
-module_param(cycles_count, uint, S_IRUGO);
-MODULE_PARM_DESC(cycles_count, "how many erase cycles to do "
-			       "(infinite by default)");
-
-static struct mtd_info *mtd;
-
-/* This buffer contains 0x555555...0xAAAAAA... pattern */
-static unsigned char *patt_5A5;
-/* This buffer contains 0xAAAAAA...0x555555... pattern */
-static unsigned char *patt_A5A;
-/* This buffer contains all 0xFF bytes */
-static unsigned char *patt_FF;
-/* This a temporary buffer is use when checking data */
-static unsigned char *check_buf;
-/* How many erase cycles were done */
-static unsigned int erase_cycles;
-
-static int pgsize;
-static struct timeval start, finish;
-
-static void report_corrupt(unsigned char *read, unsigned char *written);
-
-static inline void start_timing(void)
-{
-	do_gettimeofday(&start);
-}
-
-static inline void stop_timing(void)
-{
-	do_gettimeofday(&finish);
-}
-
-/*
- * Erase eraseblock number @ebnum.
- */
-static inline int erase_eraseblock(int ebnum)
-{
-	int err;
-	struct erase_info ei;
-	loff_t addr = ebnum * mtd->erasesize;
-
-	memset(&ei, 0, sizeof(struct erase_info));
-	ei.mtd  = mtd;
-	ei.addr = addr;
-	ei.len  = mtd->erasesize;
-
-	err = mtd_erase(mtd, &ei);
-	if (err) {
-		pr_err("error %d while erasing EB %d\n", err, ebnum);
-		return err;
-	}
-
-	if (ei.state == MTD_ERASE_FAILED) {
-		pr_err("some erase error occurred at EB %d\n",
-		       ebnum);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/*
- * Check that the contents of eraseblock number @enbum is equivalent to the
- * @buf buffer.
- */
-static inline int check_eraseblock(int ebnum, unsigned char *buf)
-{
-	int err, retries = 0;
-	size_t read;
-	loff_t addr = ebnum * mtd->erasesize;
-	size_t len = mtd->erasesize;
-
-	if (pgcnt) {
-		addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
-		len = pgcnt * pgsize;
-	}
-
-retry:
-	err = mtd_read(mtd, addr, len, &read, check_buf);
-	if (mtd_is_bitflip(err))
-		pr_err("single bit flip occurred at EB %d "
-		       "MTD reported that it was fixed.\n", ebnum);
-	else if (err) {
-		pr_err("error %d while reading EB %d, "
-		       "read %zd\n", err, ebnum, read);
-		return err;
-	}
-
-	if (read != len) {
-		pr_err("failed to read %zd bytes from EB %d, "
-		       "read only %zd, but no error reported\n",
-		       len, ebnum, read);
-		return -EIO;
-	}
-
-	if (memcmp(buf, check_buf, len)) {
-		pr_err("read wrong data from EB %d\n", ebnum);
-		report_corrupt(check_buf, buf);
-
-		if (retries++ < RETRIES) {
-			/* Try read again */
-			yield();
-			pr_info("re-try reading data from EB %d\n",
-			       ebnum);
-			goto retry;
-		} else {
-			pr_info("retried %d times, still errors, "
-			       "give-up\n", RETRIES);
-			return -EINVAL;
-		}
-	}
-
-	if (retries != 0)
-		pr_info("only attempt number %d was OK (!!!)\n",
-		       retries);
-
-	return 0;
-}
-
-static inline int write_pattern(int ebnum, void *buf)
-{
-	int err;
-	size_t written;
-	loff_t addr = ebnum * mtd->erasesize;
-	size_t len = mtd->erasesize;
-
-	if (pgcnt) {
-		addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
-		len = pgcnt * pgsize;
-	}
-	err = mtd_write(mtd, addr, len, &written, buf);
-	if (err) {
-		pr_err("error %d while writing EB %d, written %zd"
-		      " bytes\n", err, ebnum, written);
-		return err;
-	}
-	if (written != len) {
-		pr_info("written only %zd bytes of %zd, but no error"
-		       " reported\n", written, len);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int __init tort_init(void)
-{
-	int err = 0, i, infinite = !cycles_count;
-	int *bad_ebs;
-
-	printk(KERN_INFO "\n");
-	printk(KERN_INFO "=================================================\n");
-	pr_info("Warning: this program is trying to wear out your "
-	       "flash, stop it if this is not wanted.\n");
-
-	if (dev < 0) {
-		pr_info("Please specify a valid mtd-device via module parameter\n");
-		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
-		return -EINVAL;
-	}
-
-	pr_info("MTD device: %d\n", dev);
-	pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n",
-	       ebcnt, eb, eb + ebcnt - 1, dev);
-	if (pgcnt)
-		pr_info("torturing just %d pages per eraseblock\n",
-			pgcnt);
-	pr_info("write verify %s\n", check ? "enabled" : "disabled");
-
-	mtd = get_mtd_device(NULL, dev);
-	if (IS_ERR(mtd)) {
-		err = PTR_ERR(mtd);
-		pr_err("error: cannot get MTD device\n");
-		return err;
-	}
-
-	if (mtd->writesize == 1) {
-		pr_info("not NAND flash, assume page size is 512 "
-		       "bytes.\n");
-		pgsize = 512;
-	} else
-		pgsize = mtd->writesize;
-
-	if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) {
-		pr_err("error: invalid pgcnt value %d\n", pgcnt);
-		goto out_mtd;
-	}
-
-	err = -ENOMEM;
-	patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!patt_5A5)
-		goto out_mtd;
-
-	patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!patt_A5A)
-		goto out_patt_5A5;
-
-	patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!patt_FF)
-		goto out_patt_A5A;
-
-	check_buf = kmalloc(mtd->erasesize, GFP_KERNEL);
-	if (!check_buf)
-		goto out_patt_FF;
-
-	bad_ebs = kcalloc(ebcnt, sizeof(*bad_ebs), GFP_KERNEL);
-	if (!bad_ebs)
-		goto out_check_buf;
-
-	err = 0;
-
-	/* Initialize patterns */
-	memset(patt_FF, 0xFF, mtd->erasesize);
-	for (i = 0; i < mtd->erasesize / pgsize; i++) {
-		if (!(i & 1)) {
-			memset(patt_5A5 + i * pgsize, 0x55, pgsize);
-			memset(patt_A5A + i * pgsize, 0xAA, pgsize);
-		} else {
-			memset(patt_5A5 + i * pgsize, 0xAA, pgsize);
-			memset(patt_A5A + i * pgsize, 0x55, pgsize);
-		}
-	}
-
-	/*
-	 * Check if there is a bad eraseblock among those we are going to test.
-	 */
-	if (mtd_can_have_bb(mtd)) {
-		for (i = eb; i < eb + ebcnt; i++) {
-			err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize);
-
-			if (err < 0) {
-				pr_info("block_isbad() returned %d "
-				       "for EB %d\n", err, i);
-				goto out;
-			}
-
-			if (err) {
-				pr_err("EB %d is bad. Skip it.\n", i);
-				bad_ebs[i - eb] = 1;
-			}
-		}
-	}
-
-	start_timing();
-	while (1) {
-		int i;
-		void *patt;
-
-		/* Erase all eraseblocks */
-		for (i = eb; i < eb + ebcnt; i++) {
-			if (bad_ebs[i - eb])
-				continue;
-			err = erase_eraseblock(i);
-			if (err)
-				goto out;
-			cond_resched();
-		}
-
-		/* Check if the eraseblocks contain only 0xFF bytes */
-		if (check) {
-			for (i = eb; i < eb + ebcnt; i++) {
-				if (bad_ebs[i - eb])
-					continue;
-				err = check_eraseblock(i, patt_FF);
-				if (err) {
-					pr_info("verify failed"
-					       " for 0xFF... pattern\n");
-					goto out;
-				}
-				cond_resched();
-			}
-		}
-
-		/* Write the pattern */
-		for (i = eb; i < eb + ebcnt; i++) {
-			if (bad_ebs[i - eb])
-				continue;
-			if ((eb + erase_cycles) & 1)
-				patt = patt_5A5;
-			else
-				patt = patt_A5A;
-			err = write_pattern(i, patt);
-			if (err)
-				goto out;
-			cond_resched();
-		}
-
-		/* Verify what we wrote */
-		if (check) {
-			for (i = eb; i < eb + ebcnt; i++) {
-				if (bad_ebs[i - eb])
-					continue;
-				if ((eb + erase_cycles) & 1)
-					patt = patt_5A5;
-				else
-					patt = patt_A5A;
-				err = check_eraseblock(i, patt);
-				if (err) {
-					pr_info("verify failed for %s"
-					       " pattern\n",
-					       ((eb + erase_cycles) & 1) ?
-					       "0x55AA55..." : "0xAA55AA...");
-					goto out;
-				}
-				cond_resched();
-			}
-		}
-
-		erase_cycles += 1;
-
-		if (erase_cycles % gran == 0) {
-			long ms;
-
-			stop_timing();
-			ms = (finish.tv_sec - start.tv_sec) * 1000 +
-			     (finish.tv_usec - start.tv_usec) / 1000;
-			pr_info("%08u erase cycles done, took %lu "
-			       "milliseconds (%lu seconds)\n",
-			       erase_cycles, ms, ms / 1000);
-			start_timing();
-		}
-
-		if (!infinite && --cycles_count == 0)
-			break;
-	}
-out:
-
-	pr_info("finished after %u erase cycles\n",
-	       erase_cycles);
-	kfree(bad_ebs);
-out_check_buf:
-	kfree(check_buf);
-out_patt_FF:
-	kfree(patt_FF);
-out_patt_A5A:
-	kfree(patt_A5A);
-out_patt_5A5:
-	kfree(patt_5A5);
-out_mtd:
-	put_mtd_device(mtd);
-	if (err)
-		pr_info("error %d occurred during torturing\n", err);
-	printk(KERN_INFO "=================================================\n");
-	return err;
-}
-module_init(tort_init);
-
-static void __exit tort_exit(void)
-{
-	return;
-}
-module_exit(tort_exit);
-
-static int countdiffs(unsigned char *buf, unsigned char *check_buf,
-		      unsigned offset, unsigned len, unsigned *bytesp,
-		      unsigned *bitsp);
-static void print_bufs(unsigned char *read, unsigned char *written, int start,
-		       int len);
-
-/*
- * Report the detailed information about how the read EB differs from what was
- * written.
- */
-static void report_corrupt(unsigned char *read, unsigned char *written)
-{
-	int i;
-	int bytes, bits, pages, first;
-	int offset, len;
-	size_t check_len = mtd->erasesize;
-
-	if (pgcnt)
-		check_len = pgcnt * pgsize;
-
-	bytes = bits = pages = 0;
-	for (i = 0; i < check_len; i += pgsize)
-		if (countdiffs(written, read, i, pgsize, &bytes,
-			       &bits) >= 0)
-			pages++;
-
-	pr_info("verify fails on %d pages, %d bytes/%d bits\n",
-	       pages, bytes, bits);
-	pr_info("The following is a list of all differences between"
-	       " what was read from flash and what was expected\n");
-
-	for (i = 0; i < check_len; i += pgsize) {
-		cond_resched();
-		bytes = bits = 0;
-		first = countdiffs(written, read, i, pgsize, &bytes,
-				   &bits);
-		if (first < 0)
-			continue;
-
-		printk("-------------------------------------------------------"
-		       "----------------------------------\n");
-
-		pr_info("Page %zd has %d bytes/%d bits failing verify,"
-		       " starting at offset 0x%x\n",
-		       (mtd->erasesize - check_len + i) / pgsize,
-		       bytes, bits, first);
-
-		offset = first & ~0x7;
-		len = ((first + bytes) | 0x7) + 1 - offset;
-
-		print_bufs(read, written, offset, len);
-	}
-}
-
-static void print_bufs(unsigned char *read, unsigned char *written, int start,
-		       int len)
-{
-	int i = 0, j1, j2;
-	char *diff;
-
-	printk("Offset       Read                          Written\n");
-	while (i < len) {
-		printk("0x%08x: ", start + i);
-		diff = "   ";
-		for (j1 = 0; j1 < 8 && i + j1 < len; j1++) {
-			printk(" %02x", read[start + i + j1]);
-			if (read[start + i + j1] != written[start + i + j1])
-				diff = "***";
-		}
-
-		while (j1 < 8) {
-			printk(" ");
-			j1 += 1;
-		}
-
-		printk("  %s ", diff);
-
-		for (j2 = 0; j2 < 8 && i + j2 < len; j2++)
-			printk(" %02x", written[start + i + j2]);
-		printk("\n");
-		i += 8;
-	}
-}
-
-/*
- * Count the number of differing bytes and bits and return the first differing
- * offset.
- */
-static int countdiffs(unsigned char *buf, unsigned char *check_buf,
-		      unsigned offset, unsigned len, unsigned *bytesp,
-		      unsigned *bitsp)
-{
-	unsigned i, bit;
-	int first = -1;
-
-	for (i = offset; i < offset + len; i++)
-		if (buf[i] != check_buf[i]) {
-			first = i;
-			break;
-		}
-
-	while (i < offset + len) {
-		if (buf[i] != check_buf[i]) {
-			(*bytesp)++;
-			bit = 1;
-			while (bit < 256) {
-				if ((buf[i] & bit) != (check_buf[i] & bit))
-					(*bitsp)++;
-				bit <<= 1;
-			}
-		}
-		i++;
-	}
-
-	return first;
-}
-
-MODULE_DESCRIPTION("Eraseblock torturing module");
-MODULE_AUTHOR("Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/nandbiterrs.c b/drivers/mtd/tests/nandbiterrs.c
new file mode 100644
index 0000000..5a8c858
--- /dev/null
+++ b/drivers/mtd/tests/nandbiterrs.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright © 2012 NetCommWireless
+ * Iwo Mergler <Iwo.Mergler@netcommwireless.com.au>
+ *
+ * Test for multi-bit error recovery on a NAND page This mostly tests the
+ * ECC controller / driver.
+ *
+ * There are two test modes:
+ *
+ *	0 - artificially inserting bit errors until the ECC fails
+ *	    This is the default method and fairly quick. It should
+ *	    be independent of the quality of the FLASH.
+ *
+ *	1 - re-writing the same pattern repeatedly until the ECC fails.
+ *	    This method relies on the physics of NAND FLASH to eventually
+ *	    generate '0' bits if '1' has been written sufficient times.
+ *	    Depending on the NAND, the first bit errors will appear after
+ *	    1000 or more writes and then will usually snowball, reaching the
+ *	    limits of the ECC quickly.
+ *
+ *	    The test stops after 10000 cycles, should your FLASH be
+ *	    exceptionally good and not generate bit errors before that. Try
+ *	    a different page in that case.
+ *
+ * Please note that neither of these tests will significantly 'use up' any
+ * FLASH endurance. Only a maximum of two erase operations will be performed.
+ *
+ *
+ * This program is free software; you can 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mtd/mtd.h>
+#include <linux/err.h>
+#include <linux/mtd/nand.h>
+#include <linux/slab.h>
+#include "mtd_test.h"
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static unsigned page_offset;
+module_param(page_offset, uint, S_IRUGO);
+MODULE_PARM_DESC(page_offset, "Page number relative to dev start");
+
+static unsigned seed;
+module_param(seed, uint, S_IRUGO);
+MODULE_PARM_DESC(seed, "Random seed");
+
+static int mode;
+module_param(mode, int, S_IRUGO);
+MODULE_PARM_DESC(mode, "0=incremental errors, 1=overwrite test");
+
+static unsigned max_overwrite = 10000;
+
+static loff_t   offset;     /* Offset of the page we're using. */
+static unsigned eraseblock; /* Eraseblock number for our page. */
+
+/* We assume that the ECC can correct up to a certain number
+ * of biterrors per subpage. */
+static unsigned subsize;  /* Size of subpages */
+static unsigned subcount; /* Number of subpages per page */
+
+static struct mtd_info *mtd;   /* MTD device */
+
+static uint8_t *wbuffer; /* One page write / compare buffer */
+static uint8_t *rbuffer; /* One page read buffer */
+
+/* 'random' bytes from known offsets */
+static uint8_t hash(unsigned offset)
+{
+	unsigned v = offset;
+	unsigned char c;
+	v ^= 0x7f7edfd3;
+	v = v ^ (v >> 3);
+	v = v ^ (v >> 5);
+	v = v ^ (v >> 13);
+	c = v & 0xFF;
+	/* Reverse bits of result. */
+	c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
+	c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
+	c = (c & 0x55) << 1 | (c & 0xAA) >> 1;
+	return c;
+}
+
+/* Writes wbuffer to page */
+static int write_page(int log)
+{
+	int err;
+
+	if (log)
+		pr_info("write_page\n");
+
+	err = mtdtest_write(mtd, offset, mtd->writesize, wbuffer);
+	if (err)
+		pr_err("error: write failed at %#llx\n", (long long)offset);
+
+	return err;
+}
+
+/* Re-writes the data area while leaving the OOB alone. */
+static int rewrite_page(int log)
+{
+	int err = 0;
+	struct mtd_oob_ops ops;
+
+	if (log)
+		pr_info("rewrite page\n");
+
+	ops.mode      = MTD_OPS_RAW; /* No ECC */
+	ops.len       = mtd->writesize;
+	ops.retlen    = 0;
+	ops.ooblen    = 0;
+	ops.oobretlen = 0;
+	ops.ooboffs   = 0;
+	ops.datbuf    = wbuffer;
+	ops.oobbuf    = NULL;
+
+	err = mtd_write_oob(mtd, offset, &ops);
+	if (err || ops.retlen != mtd->writesize) {
+		pr_err("error: write_oob failed (%d)\n", err);
+		if (!err)
+			err = -EIO;
+	}
+
+	return err;
+}
+
+/* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
+ * or error (<0) */
+static int read_page(int log)
+{
+	int err = 0;
+	size_t read;
+	struct mtd_ecc_stats oldstats;
+
+	if (log)
+		pr_info("read_page\n");
+
+	/* Saving last mtd stats */
+	memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
+
+	err = mtd_read(mtd, offset, mtd->writesize, &read, rbuffer);
+	if (err == -EUCLEAN)
+		err = mtd->ecc_stats.corrected - oldstats.corrected;
+
+	if (err < 0 || read != mtd->writesize) {
+		pr_err("error: read failed at %#llx\n", (long long)offset);
+		if (err >= 0)
+			err = -EIO;
+	}
+
+	return err;
+}
+
+/* Verifies rbuffer against random sequence */
+static int verify_page(int log)
+{
+	unsigned i, errs = 0;
+
+	if (log)
+		pr_info("verify_page\n");
+
+	for (i = 0; i < mtd->writesize; i++) {
+		if (rbuffer[i] != hash(i+seed)) {
+			pr_err("Error: page offset %u, expected %02x, got %02x\n",
+				i, hash(i+seed), rbuffer[i]);
+			errs++;
+		}
+	}
+
+	if (errs)
+		return -EIO;
+	else
+		return 0;
+}
+
+#define CBIT(v, n) ((v) & (1 << (n)))
+#define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
+
+/* Finds the first '1' bit in wbuffer starting at offset 'byte'
+ * and sets it to '0'. */
+static int insert_biterror(unsigned byte)
+{
+	int bit;
+
+	while (byte < mtd->writesize) {
+		for (bit = 7; bit >= 0; bit--) {
+			if (CBIT(wbuffer[byte], bit)) {
+				BCLR(wbuffer[byte], bit);
+				pr_info("Inserted biterror @ %u/%u\n", byte, bit);
+				return 0;
+			}
+		}
+		byte++;
+	}
+	pr_err("biterror: Failed to find a '1' bit\n");
+	return -EIO;
+}
+
+/* Writes 'random' data to page and then introduces deliberate bit
+ * errors into the page, while verifying each step. */
+static int incremental_errors_test(void)
+{
+	int err = 0;
+	unsigned i;
+	unsigned errs_per_subpage = 0;
+
+	pr_info("incremental biterrors test\n");
+
+	for (i = 0; i < mtd->writesize; i++)
+		wbuffer[i] = hash(i+seed);
+
+	err = write_page(1);
+	if (err)
+		goto exit;
+
+	while (1) {
+
+		err = rewrite_page(1);
+		if (err)
+			goto exit;
+
+		err = read_page(1);
+		if (err > 0)
+			pr_info("Read reported %d corrected bit errors\n", err);
+		if (err < 0) {
+			pr_err("After %d biterrors per subpage, read reported error %d\n",
+				errs_per_subpage, err);
+			err = 0;
+			goto exit;
+		}
+
+		err = verify_page(1);
+		if (err) {
+			pr_err("ECC failure, read data is incorrect despite read success\n");
+			goto exit;
+		}
+
+		pr_info("Successfully corrected %d bit errors per subpage\n",
+			errs_per_subpage);
+
+		for (i = 0; i < subcount; i++) {
+			err = insert_biterror(i * subsize);
+			if (err < 0)
+				goto exit;
+		}
+		errs_per_subpage++;
+	}
+
+exit:
+	return err;
+}
+
+
+/* Writes 'random' data to page and then re-writes that same data repeatedly.
+   This eventually develops bit errors (bits written as '1' will slowly become
+   '0'), which are corrected as far as the ECC is capable of. */
+static int overwrite_test(void)
+{
+	int err = 0;
+	unsigned i;
+	unsigned max_corrected = 0;
+	unsigned opno = 0;
+	/* We don't expect more than this many correctable bit errors per
+	 * page. */
+	#define MAXBITS 512
+	static unsigned bitstats[MAXBITS]; /* bit error histogram. */
+
+	memset(bitstats, 0, sizeof(bitstats));
+
+	pr_info("overwrite biterrors test\n");
+
+	for (i = 0; i < mtd->writesize; i++)
+		wbuffer[i] = hash(i+seed);
+
+	err = write_page(1);
+	if (err)
+		goto exit;
+
+	while (opno < max_overwrite) {
+
+		err = rewrite_page(0);
+		if (err)
+			break;
+
+		err = read_page(0);
+		if (err >= 0) {
+			if (err >= MAXBITS) {
+				pr_info("Implausible number of bit errors corrected\n");
+				err = -EIO;
+				break;
+			}
+			bitstats[err]++;
+			if (err > max_corrected) {
+				max_corrected = err;
+				pr_info("Read reported %d corrected bit errors\n",
+					err);
+			}
+		} else { /* err < 0 */
+			pr_info("Read reported error %d\n", err);
+			err = 0;
+			break;
+		}
+
+		err = verify_page(0);
+		if (err) {
+			bitstats[max_corrected] = opno;
+			pr_info("ECC failure, read data is incorrect despite read success\n");
+			break;
+		}
+
+		opno++;
+	}
+
+	/* At this point bitstats[0] contains the number of ops with no bit
+	 * errors, bitstats[1] the number of ops with 1 bit error, etc. */
+	pr_info("Bit error histogram (%d operations total):\n", opno);
+	for (i = 0; i < max_corrected; i++)
+		pr_info("Page reads with %3d corrected bit errors: %d\n",
+			i, bitstats[i]);
+
+exit:
+	return err;
+}
+
+static int __init mtd_nandbiterrs_init(void)
+{
+	int err = 0;
+
+	printk("\n");
+	printk(KERN_INFO "==================================================\n");
+	pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		goto exit_mtddev;
+	}
+
+	if (mtd->type != MTD_NANDFLASH) {
+		pr_info("this test requires NAND flash\n");
+		err = -ENODEV;
+		goto exit_nand;
+	}
+
+	pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
+		(unsigned long long)mtd->size, mtd->erasesize,
+		mtd->writesize, mtd->oobsize);
+
+	subsize  = mtd->writesize >> mtd->subpage_sft;
+	subcount = mtd->writesize / subsize;
+
+	pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize);
+
+	offset     = page_offset * mtd->writesize;
+	eraseblock = mtd_div_by_eb(offset, mtd);
+
+	pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
+		page_offset, offset, eraseblock);
+
+	wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
+	if (!wbuffer) {
+		err = -ENOMEM;
+		goto exit_wbuffer;
+	}
+
+	rbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
+	if (!rbuffer) {
+		err = -ENOMEM;
+		goto exit_rbuffer;
+	}
+
+	err = mtdtest_erase_eraseblock(mtd, eraseblock);
+	if (err)
+		goto exit_error;
+
+	if (mode == 0)
+		err = incremental_errors_test();
+	else
+		err = overwrite_test();
+
+	if (err)
+		goto exit_error;
+
+	/* We leave the block un-erased in case of test failure. */
+	err = mtdtest_erase_eraseblock(mtd, eraseblock);
+	if (err)
+		goto exit_error;
+
+	err = -EIO;
+	pr_info("finished successfully.\n");
+	printk(KERN_INFO "==================================================\n");
+
+exit_error:
+	kfree(rbuffer);
+exit_rbuffer:
+	kfree(wbuffer);
+exit_wbuffer:
+	/* Nothing */
+exit_nand:
+	put_mtd_device(mtd);
+exit_mtddev:
+	return err;
+}
+
+static void __exit mtd_nandbiterrs_exit(void)
+{
+	return;
+}
+
+module_init(mtd_nandbiterrs_init);
+module_exit(mtd_nandbiterrs_exit);
+
+MODULE_DESCRIPTION("NAND bit error recovery test");
+MODULE_AUTHOR("Iwo Mergler");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c
new file mode 100644
index 0000000..ff35c46
--- /dev/null
+++ b/drivers/mtd/tests/oobtest.c
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test OOB read and write on MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/div64.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+
+#include "mtd_test.h"
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *readbuf;
+static unsigned char *writebuf;
+static unsigned char *bbt;
+
+static int ebcnt;
+static int pgcnt;
+static int errcnt;
+static int use_offset;
+static int use_len;
+static int use_len_max;
+static int vary_offset;
+static struct rnd_state rnd_state;
+
+static void do_vary_offset(void)
+{
+	use_len -= 1;
+	if (use_len < 1) {
+		use_offset += 1;
+		if (use_offset >= use_len_max)
+			use_offset = 0;
+		use_len = use_len_max - use_offset;
+	}
+}
+
+static int write_eraseblock(int ebnum)
+{
+	int i;
+	struct mtd_oob_ops ops;
+	int err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
+		prandom_bytes_state(&rnd_state, writebuf, use_len);
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = use_len;
+		ops.oobretlen = 0;
+		ops.ooboffs   = use_offset;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = writebuf;
+		err = mtd_write_oob(mtd, addr, &ops);
+		if (err || ops.oobretlen != use_len) {
+			pr_err("error: writeoob failed at %#llx\n",
+			       (long long)addr);
+			pr_err("error: use_len %d, use_offset %d\n",
+			       use_len, use_offset);
+			errcnt += 1;
+			return err ? err : -1;
+		}
+		if (vary_offset)
+			do_vary_offset();
+	}
+
+	return err;
+}
+
+static int write_whole_device(void)
+{
+	int err;
+	unsigned int i;
+
+	pr_info("writing OOBs of whole device\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock(i);
+		if (err)
+			return err;
+		if (i % 256 == 0)
+			pr_info("written up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("written %u eraseblocks\n", i);
+	return 0;
+}
+
+static int verify_eraseblock(int ebnum)
+{
+	int i;
+	struct mtd_oob_ops ops;
+	int err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
+		prandom_bytes_state(&rnd_state, writebuf, use_len);
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = use_len;
+		ops.oobretlen = 0;
+		ops.ooboffs   = use_offset;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = readbuf;
+		err = mtd_read_oob(mtd, addr, &ops);
+		if (err || ops.oobretlen != use_len) {
+			pr_err("error: readoob failed at %#llx\n",
+			       (long long)addr);
+			errcnt += 1;
+			return err ? err : -1;
+		}
+		if (memcmp(readbuf, writebuf, use_len)) {
+			pr_err("error: verify failed at %#llx\n",
+			       (long long)addr);
+			errcnt += 1;
+			if (errcnt > 1000) {
+				pr_err("error: too many errors\n");
+				return -1;
+			}
+		}
+		if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
+			int k;
+
+			ops.mode      = MTD_OPS_AUTO_OOB;
+			ops.len       = 0;
+			ops.retlen    = 0;
+			ops.ooblen    = mtd->ecclayout->oobavail;
+			ops.oobretlen = 0;
+			ops.ooboffs   = 0;
+			ops.datbuf    = NULL;
+			ops.oobbuf    = readbuf;
+			err = mtd_read_oob(mtd, addr, &ops);
+			if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
+				pr_err("error: readoob failed at %#llx\n",
+						(long long)addr);
+				errcnt += 1;
+				return err ? err : -1;
+			}
+			if (memcmp(readbuf + use_offset, writebuf, use_len)) {
+				pr_err("error: verify failed at %#llx\n",
+						(long long)addr);
+				errcnt += 1;
+				if (errcnt > 1000) {
+					pr_err("error: too many errors\n");
+					return -1;
+				}
+			}
+			for (k = 0; k < use_offset; ++k)
+				if (readbuf[k] != 0xff) {
+					pr_err("error: verify 0xff "
+					       "failed at %#llx\n",
+					       (long long)addr);
+					errcnt += 1;
+					if (errcnt > 1000) {
+						pr_err("error: too "
+						       "many errors\n");
+						return -1;
+					}
+				}
+			for (k = use_offset + use_len;
+			     k < mtd->ecclayout->oobavail; ++k)
+				if (readbuf[k] != 0xff) {
+					pr_err("error: verify 0xff "
+					       "failed at %#llx\n",
+					       (long long)addr);
+					errcnt += 1;
+					if (errcnt > 1000) {
+						pr_err("error: too "
+						       "many errors\n");
+						return -1;
+					}
+				}
+		}
+		if (vary_offset)
+			do_vary_offset();
+	}
+	return err;
+}
+
+static int verify_eraseblock_in_one_go(int ebnum)
+{
+	struct mtd_oob_ops ops;
+	int err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+	size_t len = mtd->ecclayout->oobavail * pgcnt;
+
+	prandom_bytes_state(&rnd_state, writebuf, len);
+	ops.mode      = MTD_OPS_AUTO_OOB;
+	ops.len       = 0;
+	ops.retlen    = 0;
+	ops.ooblen    = len;
+	ops.oobretlen = 0;
+	ops.ooboffs   = 0;
+	ops.datbuf    = NULL;
+	ops.oobbuf    = readbuf;
+	err = mtd_read_oob(mtd, addr, &ops);
+	if (err || ops.oobretlen != len) {
+		pr_err("error: readoob failed at %#llx\n",
+		       (long long)addr);
+		errcnt += 1;
+		return err ? err : -1;
+	}
+	if (memcmp(readbuf, writebuf, len)) {
+		pr_err("error: verify failed at %#llx\n",
+		       (long long)addr);
+		errcnt += 1;
+		if (errcnt > 1000) {
+			pr_err("error: too many errors\n");
+			return -1;
+		}
+	}
+
+	return err;
+}
+
+static int verify_all_eraseblocks(void)
+{
+	int err;
+	unsigned int i;
+
+	pr_info("verifying all eraseblocks\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = verify_eraseblock(i);
+		if (err)
+			return err;
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+	return 0;
+}
+
+static int __init mtd_oobtest_init(void)
+{
+	int err = 0;
+	unsigned int i;
+	uint64_t tmp;
+	struct mtd_oob_ops ops;
+	loff_t addr = 0, addr0;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
+	pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->type != MTD_NANDFLASH) {
+		pr_info("this test requires NAND flash\n");
+		goto out;
+	}
+
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / mtd->writesize;
+
+	pr_info("MTD device size %llu, eraseblock size %u, "
+	       "page size %u, count of eraseblocks %u, pages per "
+	       "eraseblock %u, OOB size %u\n",
+	       (unsigned long long)mtd->size, mtd->erasesize,
+	       mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
+
+	err = -ENOMEM;
+	readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!readbuf)
+		goto out;
+	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!writebuf)
+		goto out;
+	bbt = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bbt)
+		goto out;
+
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	use_offset = 0;
+	use_len = mtd->ecclayout->oobavail;
+	use_len_max = mtd->ecclayout->oobavail;
+	vary_offset = 0;
+
+	/* First test: write all OOB, read it back and verify */
+	pr_info("test 1 of 5\n");
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	prandom_seed_state(&rnd_state, 1);
+	err = write_whole_device();
+	if (err)
+		goto out;
+
+	prandom_seed_state(&rnd_state, 1);
+	err = verify_all_eraseblocks();
+	if (err)
+		goto out;
+
+	/*
+	 * Second test: write all OOB, a block at a time, read it back and
+	 * verify.
+	 */
+	pr_info("test 2 of 5\n");
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	prandom_seed_state(&rnd_state, 3);
+	err = write_whole_device();
+	if (err)
+		goto out;
+
+	/* Check all eraseblocks */
+	prandom_seed_state(&rnd_state, 3);
+	pr_info("verifying all eraseblocks\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = verify_eraseblock_in_one_go(i);
+		if (err)
+			goto out;
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+
+	/*
+	 * Third test: write OOB at varying offsets and lengths, read it back
+	 * and verify.
+	 */
+	pr_info("test 3 of 5\n");
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Write all eraseblocks */
+	use_offset = 0;
+	use_len = mtd->ecclayout->oobavail;
+	use_len_max = mtd->ecclayout->oobavail;
+	vary_offset = 1;
+	prandom_seed_state(&rnd_state, 5);
+
+	err = write_whole_device();
+	if (err)
+		goto out;
+
+	/* Check all eraseblocks */
+	use_offset = 0;
+	use_len = mtd->ecclayout->oobavail;
+	use_len_max = mtd->ecclayout->oobavail;
+	vary_offset = 1;
+	prandom_seed_state(&rnd_state, 5);
+	err = verify_all_eraseblocks();
+	if (err)
+		goto out;
+
+	use_offset = 0;
+	use_len = mtd->ecclayout->oobavail;
+	use_len_max = mtd->ecclayout->oobavail;
+	vary_offset = 0;
+
+	/* Fourth test: try to write off end of device */
+	pr_info("test 4 of 5\n");
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	addr0 = 0;
+	for (i = 0; i < ebcnt && bbt[i]; ++i)
+		addr0 += mtd->erasesize;
+
+	/* Attempt to write off end of OOB */
+	ops.mode      = MTD_OPS_AUTO_OOB;
+	ops.len       = 0;
+	ops.retlen    = 0;
+	ops.ooblen    = 1;
+	ops.oobretlen = 0;
+	ops.ooboffs   = mtd->ecclayout->oobavail;
+	ops.datbuf    = NULL;
+	ops.oobbuf    = writebuf;
+	pr_info("attempting to start write past end of OOB\n");
+	pr_info("an error is expected...\n");
+	err = mtd_write_oob(mtd, addr0, &ops);
+	if (err) {
+		pr_info("error occurred as expected\n");
+		err = 0;
+	} else {
+		pr_err("error: can write past end of OOB\n");
+		errcnt += 1;
+	}
+
+	/* Attempt to read off end of OOB */
+	ops.mode      = MTD_OPS_AUTO_OOB;
+	ops.len       = 0;
+	ops.retlen    = 0;
+	ops.ooblen    = 1;
+	ops.oobretlen = 0;
+	ops.ooboffs   = mtd->ecclayout->oobavail;
+	ops.datbuf    = NULL;
+	ops.oobbuf    = readbuf;
+	pr_info("attempting to start read past end of OOB\n");
+	pr_info("an error is expected...\n");
+	err = mtd_read_oob(mtd, addr0, &ops);
+	if (err) {
+		pr_info("error occurred as expected\n");
+		err = 0;
+	} else {
+		pr_err("error: can read past end of OOB\n");
+		errcnt += 1;
+	}
+
+	if (bbt[ebcnt - 1])
+		pr_info("skipping end of device tests because last "
+		       "block is bad\n");
+	else {
+		/* Attempt to write off end of device */
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = mtd->ecclayout->oobavail + 1;
+		ops.oobretlen = 0;
+		ops.ooboffs   = 0;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = writebuf;
+		pr_info("attempting to write past end of device\n");
+		pr_info("an error is expected...\n");
+		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
+		if (err) {
+			pr_info("error occurred as expected\n");
+			err = 0;
+		} else {
+			pr_err("error: wrote past end of device\n");
+			errcnt += 1;
+		}
+
+		/* Attempt to read off end of device */
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = mtd->ecclayout->oobavail + 1;
+		ops.oobretlen = 0;
+		ops.ooboffs   = 0;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = readbuf;
+		pr_info("attempting to read past end of device\n");
+		pr_info("an error is expected...\n");
+		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
+		if (err) {
+			pr_info("error occurred as expected\n");
+			err = 0;
+		} else {
+			pr_err("error: read past end of device\n");
+			errcnt += 1;
+		}
+
+		err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
+		if (err)
+			goto out;
+
+		/* Attempt to write off end of device */
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = mtd->ecclayout->oobavail;
+		ops.oobretlen = 0;
+		ops.ooboffs   = 1;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = writebuf;
+		pr_info("attempting to write past end of device\n");
+		pr_info("an error is expected...\n");
+		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
+		if (err) {
+			pr_info("error occurred as expected\n");
+			err = 0;
+		} else {
+			pr_err("error: wrote past end of device\n");
+			errcnt += 1;
+		}
+
+		/* Attempt to read off end of device */
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = mtd->ecclayout->oobavail;
+		ops.oobretlen = 0;
+		ops.ooboffs   = 1;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = readbuf;
+		pr_info("attempting to read past end of device\n");
+		pr_info("an error is expected...\n");
+		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
+		if (err) {
+			pr_info("error occurred as expected\n");
+			err = 0;
+		} else {
+			pr_err("error: read past end of device\n");
+			errcnt += 1;
+		}
+	}
+
+	/* Fifth test: write / read across block boundaries */
+	pr_info("test 5 of 5\n");
+
+	/* Erase all eraseblocks */
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Write all eraseblocks */
+	prandom_seed_state(&rnd_state, 11);
+	pr_info("writing OOBs of whole device\n");
+	for (i = 0; i < ebcnt - 1; ++i) {
+		int cnt = 2;
+		int pg;
+		size_t sz = mtd->ecclayout->oobavail;
+		if (bbt[i] || bbt[i + 1])
+			continue;
+		addr = (i + 1) * mtd->erasesize - mtd->writesize;
+		for (pg = 0; pg < cnt; ++pg) {
+			prandom_bytes_state(&rnd_state, writebuf, sz);
+			ops.mode      = MTD_OPS_AUTO_OOB;
+			ops.len       = 0;
+			ops.retlen    = 0;
+			ops.ooblen    = sz;
+			ops.oobretlen = 0;
+			ops.ooboffs   = 0;
+			ops.datbuf    = NULL;
+			ops.oobbuf    = writebuf;
+			err = mtd_write_oob(mtd, addr, &ops);
+			if (err)
+				goto out;
+			if (i % 256 == 0)
+				pr_info("written up to eraseblock %u\n", i);
+			cond_resched();
+			addr += mtd->writesize;
+		}
+	}
+	pr_info("written %u eraseblocks\n", i);
+
+	/* Check all eraseblocks */
+	prandom_seed_state(&rnd_state, 11);
+	pr_info("verifying all eraseblocks\n");
+	for (i = 0; i < ebcnt - 1; ++i) {
+		if (bbt[i] || bbt[i + 1])
+			continue;
+		prandom_bytes_state(&rnd_state, writebuf,
+					mtd->ecclayout->oobavail * 2);
+		addr = (i + 1) * mtd->erasesize - mtd->writesize;
+		ops.mode      = MTD_OPS_AUTO_OOB;
+		ops.len       = 0;
+		ops.retlen    = 0;
+		ops.ooblen    = mtd->ecclayout->oobavail * 2;
+		ops.oobretlen = 0;
+		ops.ooboffs   = 0;
+		ops.datbuf    = NULL;
+		ops.oobbuf    = readbuf;
+		err = mtd_read_oob(mtd, addr, &ops);
+		if (err)
+			goto out;
+		if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
+			pr_err("error: verify failed at %#llx\n",
+			       (long long)addr);
+			errcnt += 1;
+			if (errcnt > 1000) {
+				pr_err("error: too many errors\n");
+				goto out;
+			}
+		}
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+
+	pr_info("finished with %d errors\n", errcnt);
+out:
+	kfree(bbt);
+	kfree(writebuf);
+	kfree(readbuf);
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(mtd_oobtest_init);
+
+static void __exit mtd_oobtest_exit(void)
+{
+	return;
+}
+module_exit(mtd_oobtest_exit);
+
+MODULE_DESCRIPTION("Out-of-band test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c
new file mode 100644
index 0000000..22cc38c
--- /dev/null
+++ b/drivers/mtd/tests/pagetest.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test page read and write on MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/div64.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+
+#include "mtd_test.h"
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *twopages;
+static unsigned char *writebuf;
+static unsigned char *boundary;
+static unsigned char *bbt;
+
+static int pgsize;
+static int bufsize;
+static int ebcnt;
+static int pgcnt;
+static int errcnt;
+static struct rnd_state rnd_state;
+
+static int write_eraseblock(int ebnum)
+{
+	int err;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
+	cond_resched();
+	err = mtdtest_write(mtd, addr, mtd->erasesize, writebuf);
+	if (err)
+		pr_err("error: write failed at %#llx\n",
+		       (long long)addr);
+
+	return err;
+}
+
+static int verify_eraseblock(int ebnum)
+{
+	uint32_t j;
+	int err = 0, i;
+	loff_t addr0, addrn;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	addr0 = 0;
+	for (i = 0; i < ebcnt && bbt[i]; ++i)
+		addr0 += mtd->erasesize;
+
+	addrn = mtd->size;
+	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
+		addrn -= mtd->erasesize;
+
+	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
+	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
+		/* Do a read to set the internal dataRAMs to different data */
+		err = mtdtest_read(mtd, addr0, bufsize, twopages);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr0);
+			return err;
+		}
+		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)(addrn - bufsize));
+			return err;
+		}
+		memset(twopages, 0, bufsize);
+		err = mtdtest_read(mtd, addr, bufsize, twopages);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr);
+			break;
+		}
+		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
+			pr_err("error: verify failed at %#llx\n",
+			       (long long)addr);
+			errcnt += 1;
+		}
+	}
+	/* Check boundary between eraseblocks */
+	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
+		struct rnd_state old_state = rnd_state;
+
+		/* Do a read to set the internal dataRAMs to different data */
+		err = mtdtest_read(mtd, addr0, bufsize, twopages);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr0);
+			return err;
+		}
+		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)(addrn - bufsize));
+			return err;
+		}
+		memset(twopages, 0, bufsize);
+		err = mtdtest_read(mtd, addr, bufsize, twopages);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr);
+			return err;
+		}
+		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
+		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
+		if (memcmp(twopages, boundary, bufsize)) {
+			pr_err("error: verify failed at %#llx\n",
+			       (long long)addr);
+			errcnt += 1;
+		}
+		rnd_state = old_state;
+	}
+	return err;
+}
+
+static int crosstest(void)
+{
+	int err = 0, i;
+	loff_t addr, addr0, addrn;
+	unsigned char *pp1, *pp2, *pp3, *pp4;
+
+	pr_info("crosstest\n");
+	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
+	if (!pp1)
+		return -ENOMEM;
+	pp2 = pp1 + pgsize;
+	pp3 = pp2 + pgsize;
+	pp4 = pp3 + pgsize;
+	memset(pp1, 0, pgsize * 4);
+
+	addr0 = 0;
+	for (i = 0; i < ebcnt && bbt[i]; ++i)
+		addr0 += mtd->erasesize;
+
+	addrn = mtd->size;
+	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
+		addrn -= mtd->erasesize;
+
+	/* Read 2nd-to-last page to pp1 */
+	addr = addrn - pgsize - pgsize;
+	err = mtdtest_read(mtd, addr, pgsize, pp1);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr);
+		kfree(pp1);
+		return err;
+	}
+
+	/* Read 3rd-to-last page to pp1 */
+	addr = addrn - pgsize - pgsize - pgsize;
+	err = mtdtest_read(mtd, addr, pgsize, pp1);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr);
+		kfree(pp1);
+		return err;
+	}
+
+	/* Read first page to pp2 */
+	addr = addr0;
+	pr_info("reading page at %#llx\n", (long long)addr);
+	err = mtdtest_read(mtd, addr, pgsize, pp2);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr);
+		kfree(pp1);
+		return err;
+	}
+
+	/* Read last page to pp3 */
+	addr = addrn - pgsize;
+	pr_info("reading page at %#llx\n", (long long)addr);
+	err = mtdtest_read(mtd, addr, pgsize, pp3);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr);
+		kfree(pp1);
+		return err;
+	}
+
+	/* Read first page again to pp4 */
+	addr = addr0;
+	pr_info("reading page at %#llx\n", (long long)addr);
+	err = mtdtest_read(mtd, addr, pgsize, pp4);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr);
+		kfree(pp1);
+		return err;
+	}
+
+	/* pp2 and pp4 should be the same */
+	pr_info("verifying pages read at %#llx match\n",
+	       (long long)addr0);
+	if (memcmp(pp2, pp4, pgsize)) {
+		pr_err("verify failed!\n");
+		errcnt += 1;
+	} else if (!err)
+		pr_info("crosstest ok\n");
+	kfree(pp1);
+	return err;
+}
+
+static int erasecrosstest(void)
+{
+	int err = 0, i, ebnum, ebnum2;
+	loff_t addr0;
+	char *readbuf = twopages;
+
+	pr_info("erasecrosstest\n");
+
+	ebnum = 0;
+	addr0 = 0;
+	for (i = 0; i < ebcnt && bbt[i]; ++i) {
+		addr0 += mtd->erasesize;
+		ebnum += 1;
+	}
+
+	ebnum2 = ebcnt - 1;
+	while (ebnum2 && bbt[ebnum2])
+		ebnum2 -= 1;
+
+	pr_info("erasing block %d\n", ebnum);
+	err = mtdtest_erase_eraseblock(mtd, ebnum);
+	if (err)
+		return err;
+
+	pr_info("writing 1st page of block %d\n", ebnum);
+	prandom_bytes_state(&rnd_state, writebuf, pgsize);
+	strcpy(writebuf, "There is no data like this!");
+	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
+	if (err) {
+		pr_info("error: write failed at %#llx\n",
+		       (long long)addr0);
+		return err;
+	}
+
+	pr_info("reading 1st page of block %d\n", ebnum);
+	memset(readbuf, 0, pgsize);
+	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr0);
+		return err ? err : -1;
+	}
+
+	pr_info("verifying 1st page of block %d\n", ebnum);
+	if (memcmp(writebuf, readbuf, pgsize)) {
+		pr_err("verify failed!\n");
+		errcnt += 1;
+		return -1;
+	}
+
+	pr_info("erasing block %d\n", ebnum);
+	err = mtdtest_erase_eraseblock(mtd, ebnum);
+	if (err)
+		return err;
+
+	pr_info("writing 1st page of block %d\n", ebnum);
+	prandom_bytes_state(&rnd_state, writebuf, pgsize);
+	strcpy(writebuf, "There is no data like this!");
+	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
+	if (err) {
+		pr_err("error: write failed at %#llx\n",
+		       (long long)addr0);
+		return err;
+	}
+
+	pr_info("erasing block %d\n", ebnum2);
+	err = mtdtest_erase_eraseblock(mtd, ebnum2);
+	if (err)
+		return err;
+
+	pr_info("reading 1st page of block %d\n", ebnum);
+	memset(readbuf, 0, pgsize);
+	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr0);
+		return err ? err : -1;
+	}
+
+	pr_info("verifying 1st page of block %d\n", ebnum);
+	if (memcmp(writebuf, readbuf, pgsize)) {
+		pr_err("verify failed!\n");
+		errcnt += 1;
+		return -1;
+	}
+
+	if (!err)
+		pr_info("erasecrosstest ok\n");
+	return err;
+}
+
+static int erasetest(void)
+{
+	int err = 0, i, ebnum, ok = 1;
+	loff_t addr0;
+
+	pr_info("erasetest\n");
+
+	ebnum = 0;
+	addr0 = 0;
+	for (i = 0; i < ebcnt && bbt[i]; ++i) {
+		addr0 += mtd->erasesize;
+		ebnum += 1;
+	}
+
+	pr_info("erasing block %d\n", ebnum);
+	err = mtdtest_erase_eraseblock(mtd, ebnum);
+	if (err)
+		return err;
+
+	pr_info("writing 1st page of block %d\n", ebnum);
+	prandom_bytes_state(&rnd_state, writebuf, pgsize);
+	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
+	if (err) {
+		pr_err("error: write failed at %#llx\n",
+		       (long long)addr0);
+		return err;
+	}
+
+	pr_info("erasing block %d\n", ebnum);
+	err = mtdtest_erase_eraseblock(mtd, ebnum);
+	if (err)
+		return err;
+
+	pr_info("reading 1st page of block %d\n", ebnum);
+	err = mtdtest_read(mtd, addr0, pgsize, twopages);
+	if (err) {
+		pr_err("error: read failed at %#llx\n",
+		       (long long)addr0);
+		return err ? err : -1;
+	}
+
+	pr_info("verifying 1st page of block %d is all 0xff\n",
+	       ebnum);
+	for (i = 0; i < pgsize; ++i)
+		if (twopages[i] != 0xff) {
+			pr_err("verifying all 0xff failed at %d\n",
+			       i);
+			errcnt += 1;
+			ok = 0;
+			break;
+		}
+
+	if (ok && !err)
+		pr_info("erasetest ok\n");
+
+	return err;
+}
+
+static int __init mtd_pagetest_init(void)
+{
+	int err = 0;
+	uint64_t tmp;
+	uint32_t i;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
+	pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->type != MTD_NANDFLASH) {
+		pr_info("this test requires NAND flash\n");
+		goto out;
+	}
+
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / mtd->writesize;
+	pgsize = mtd->writesize;
+
+	pr_info("MTD device size %llu, eraseblock size %u, "
+	       "page size %u, count of eraseblocks %u, pages per "
+	       "eraseblock %u, OOB size %u\n",
+	       (unsigned long long)mtd->size, mtd->erasesize,
+	       pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+	err = -ENOMEM;
+	bufsize = pgsize * 2;
+	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!writebuf)
+		goto out;
+	twopages = kmalloc(bufsize, GFP_KERNEL);
+	if (!twopages)
+		goto out;
+	boundary = kmalloc(bufsize, GFP_KERNEL);
+	if (!boundary)
+		goto out;
+
+	bbt = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bbt)
+		goto out;
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Erase all eraseblocks */
+	pr_info("erasing whole device\n");
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+	pr_info("erased %u eraseblocks\n", ebcnt);
+
+	/* Write all eraseblocks */
+	prandom_seed_state(&rnd_state, 1);
+	pr_info("writing whole device\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock(i);
+		if (err)
+			goto out;
+		if (i % 256 == 0)
+			pr_info("written up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("written %u eraseblocks\n", i);
+
+	/* Check all eraseblocks */
+	prandom_seed_state(&rnd_state, 1);
+	pr_info("verifying all eraseblocks\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = verify_eraseblock(i);
+		if (err)
+			goto out;
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+
+	err = crosstest();
+	if (err)
+		goto out;
+
+	err = erasecrosstest();
+	if (err)
+		goto out;
+
+	err = erasetest();
+	if (err)
+		goto out;
+
+	pr_info("finished with %d errors\n", errcnt);
+out:
+
+	kfree(bbt);
+	kfree(boundary);
+	kfree(twopages);
+	kfree(writebuf);
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(mtd_pagetest_init);
+
+static void __exit mtd_pagetest_exit(void)
+{
+	return;
+}
+module_exit(mtd_pagetest_exit);
+
+MODULE_DESCRIPTION("NAND page test");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/readtest.c b/drivers/mtd/tests/readtest.c
new file mode 100644
index 0000000..ffd50d6
--- /dev/null
+++ b/drivers/mtd/tests/readtest.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Check MTD device read.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "mtd_test.h"
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *iobuf;
+static unsigned char *iobuf1;
+static unsigned char *bbt;
+
+static int pgsize;
+static int ebcnt;
+static int pgcnt;
+
+static int read_eraseblock_by_page(int ebnum)
+{
+	int i, ret, err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+	void *buf = iobuf;
+	void *oobbuf = iobuf1;
+
+	for (i = 0; i < pgcnt; i++) {
+		memset(buf, 0 , pgsize);
+		ret = mtdtest_read(mtd, addr, pgsize, buf);
+		if (ret) {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr);
+			if (!err)
+				err = ret;
+		}
+		if (mtd->oobsize) {
+			struct mtd_oob_ops ops;
+
+			ops.mode      = MTD_OPS_PLACE_OOB;
+			ops.len       = 0;
+			ops.retlen    = 0;
+			ops.ooblen    = mtd->oobsize;
+			ops.oobretlen = 0;
+			ops.ooboffs   = 0;
+			ops.datbuf    = NULL;
+			ops.oobbuf    = oobbuf;
+			ret = mtd_read_oob(mtd, addr, &ops);
+			if ((ret && !mtd_is_bitflip(ret)) ||
+					ops.oobretlen != mtd->oobsize) {
+				pr_err("error: read oob failed at "
+						  "%#llx\n", (long long)addr);
+				if (!err)
+					err = ret;
+				if (!err)
+					err = -EINVAL;
+			}
+			oobbuf += mtd->oobsize;
+		}
+		addr += pgsize;
+		buf += pgsize;
+	}
+
+	return err;
+}
+
+static void dump_eraseblock(int ebnum)
+{
+	int i, j, n;
+	char line[128];
+	int pg, oob;
+
+	pr_info("dumping eraseblock %d\n", ebnum);
+	n = mtd->erasesize;
+	for (i = 0; i < n;) {
+		char *p = line;
+
+		p += sprintf(p, "%05x: ", i);
+		for (j = 0; j < 32 && i < n; j++, i++)
+			p += sprintf(p, "%02x", (unsigned int)iobuf[i]);
+		printk(KERN_CRIT "%s\n", line);
+		cond_resched();
+	}
+	if (!mtd->oobsize)
+		return;
+	pr_info("dumping oob from eraseblock %d\n", ebnum);
+	n = mtd->oobsize;
+	for (pg = 0, i = 0; pg < pgcnt; pg++)
+		for (oob = 0; oob < n;) {
+			char *p = line;
+
+			p += sprintf(p, "%05x: ", i);
+			for (j = 0; j < 32 && oob < n; j++, oob++, i++)
+				p += sprintf(p, "%02x",
+					     (unsigned int)iobuf1[i]);
+			printk(KERN_CRIT "%s\n", line);
+			cond_resched();
+		}
+}
+
+static int __init mtd_readtest_init(void)
+{
+	uint64_t tmp;
+	int err, i;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		return -EINVAL;
+	}
+
+	pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: Cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->writesize == 1) {
+		pr_info("not NAND flash, assume page size is 512 "
+		       "bytes.\n");
+		pgsize = 512;
+	} else
+		pgsize = mtd->writesize;
+
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / pgsize;
+
+	pr_info("MTD device size %llu, eraseblock size %u, "
+	       "page size %u, count of eraseblocks %u, pages per "
+	       "eraseblock %u, OOB size %u\n",
+	       (unsigned long long)mtd->size, mtd->erasesize,
+	       pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+	err = -ENOMEM;
+	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!iobuf)
+		goto out;
+	iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!iobuf1)
+		goto out;
+
+	bbt = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bbt)
+		goto out;
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Read all eraseblocks 1 page at a time */
+	pr_info("testing page read\n");
+	for (i = 0; i < ebcnt; ++i) {
+		int ret;
+
+		if (bbt[i])
+			continue;
+		ret = read_eraseblock_by_page(i);
+		if (ret) {
+			dump_eraseblock(i);
+			if (!err)
+				err = ret;
+		}
+		cond_resched();
+	}
+
+	if (err)
+		pr_info("finished with errors\n");
+	else
+		pr_info("finished\n");
+
+out:
+
+	kfree(iobuf);
+	kfree(iobuf1);
+	kfree(bbt);
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(mtd_readtest_init);
+
+static void __exit mtd_readtest_exit(void)
+{
+	return;
+}
+module_exit(mtd_readtest_exit);
+
+MODULE_DESCRIPTION("Read test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/speedtest.c b/drivers/mtd/tests/speedtest.c
new file mode 100644
index 0000000..457c45c
--- /dev/null
+++ b/drivers/mtd/tests/speedtest.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test read and write speed of a MTD device.
+ *
+ * Author: Adrian Hunter <adrian.hunter@nokia.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+
+#include "mtd_test.h"
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static int count;
+module_param(count, int, S_IRUGO);
+MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use "
+			"(0 means use all)");
+
+static struct mtd_info *mtd;
+static unsigned char *iobuf;
+static unsigned char *bbt;
+
+static int pgsize;
+static int ebcnt;
+static int pgcnt;
+static int goodebcnt;
+static struct timeval start, finish;
+
+static int multiblock_erase(int ebnum, int blocks)
+{
+	int err;
+	struct erase_info ei;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	memset(&ei, 0, sizeof(struct erase_info));
+	ei.mtd  = mtd;
+	ei.addr = addr;
+	ei.len  = mtd->erasesize * blocks;
+
+	err = mtd_erase(mtd, &ei);
+	if (err) {
+		pr_err("error %d while erasing EB %d, blocks %d\n",
+		       err, ebnum, blocks);
+		return err;
+	}
+
+	if (ei.state == MTD_ERASE_FAILED) {
+		pr_err("some erase error occurred at EB %d,"
+		       "blocks %d\n", ebnum, blocks);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int write_eraseblock(int ebnum)
+{
+	int err;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	err = mtdtest_write(mtd, addr, mtd->erasesize, iobuf);
+	if (err)
+		pr_err("error: write failed at %#llx\n", addr);
+
+	return err;
+}
+
+static int write_eraseblock_by_page(int ebnum)
+{
+	int i, err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+	void *buf = iobuf;
+
+	for (i = 0; i < pgcnt; i++) {
+		err = mtdtest_write(mtd, addr, pgsize, buf);
+		if (err) {
+			pr_err("error: write failed at %#llx\n",
+			       addr);
+			break;
+		}
+		addr += pgsize;
+		buf += pgsize;
+	}
+
+	return err;
+}
+
+static int write_eraseblock_by_2pages(int ebnum)
+{
+	size_t sz = pgsize * 2;
+	int i, n = pgcnt / 2, err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+	void *buf = iobuf;
+
+	for (i = 0; i < n; i++) {
+		err = mtdtest_write(mtd, addr, sz, buf);
+		if (err) {
+			pr_err("error: write failed at %#llx\n",
+			       addr);
+			return err;
+		}
+		addr += sz;
+		buf += sz;
+	}
+	if (pgcnt % 2) {
+		err = mtdtest_write(mtd, addr, pgsize, buf);
+		if (err) {
+			pr_err("error: write failed at %#llx\n",
+			       addr);
+		}
+	}
+
+	return err;
+}
+
+static int read_eraseblock(int ebnum)
+{
+	int err;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	err = mtdtest_read(mtd, addr, mtd->erasesize, iobuf);
+	if (err)
+		pr_err("error: read failed at %#llx\n", addr);
+
+	return err;
+}
+
+static int read_eraseblock_by_page(int ebnum)
+{
+	int i, err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+	void *buf = iobuf;
+
+	for (i = 0; i < pgcnt; i++) {
+		err = mtdtest_read(mtd, addr, pgsize, buf);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       addr);
+			break;
+		}
+		addr += pgsize;
+		buf += pgsize;
+	}
+
+	return err;
+}
+
+static int read_eraseblock_by_2pages(int ebnum)
+{
+	size_t sz = pgsize * 2;
+	int i, n = pgcnt / 2, err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+	void *buf = iobuf;
+
+	for (i = 0; i < n; i++) {
+		err = mtdtest_read(mtd, addr, sz, buf);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       addr);
+			return err;
+		}
+		addr += sz;
+		buf += sz;
+	}
+	if (pgcnt % 2) {
+		err = mtdtest_read(mtd, addr, pgsize, buf);
+		if (err) {
+			pr_err("error: read failed at %#llx\n",
+			       addr);
+		}
+	}
+
+	return err;
+}
+
+static inline void start_timing(void)
+{
+	do_gettimeofday(&start);
+}
+
+static inline void stop_timing(void)
+{
+	do_gettimeofday(&finish);
+}
+
+static long calc_speed(void)
+{
+	uint64_t k;
+	long ms;
+
+	ms = (finish.tv_sec - start.tv_sec) * 1000 +
+	     (finish.tv_usec - start.tv_usec) / 1000;
+	if (ms == 0)
+		return 0;
+	k = goodebcnt * (mtd->erasesize / 1024) * 1000;
+	do_div(k, ms);
+	return k;
+}
+
+static int __init mtd_speedtest_init(void)
+{
+	int err, i, blocks, j, k;
+	long speed;
+	uint64_t tmp;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
+	if (count)
+		pr_info("MTD device: %d    count: %d\n", dev, count);
+	else
+		pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->writesize == 1) {
+		pr_info("not NAND flash, assume page size is 512 "
+		       "bytes.\n");
+		pgsize = 512;
+	} else
+		pgsize = mtd->writesize;
+
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / pgsize;
+
+	pr_info("MTD device size %llu, eraseblock size %u, "
+	       "page size %u, count of eraseblocks %u, pages per "
+	       "eraseblock %u, OOB size %u\n",
+	       (unsigned long long)mtd->size, mtd->erasesize,
+	       pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+	if (count > 0 && count < ebcnt)
+		ebcnt = count;
+
+	err = -ENOMEM;
+	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!iobuf)
+		goto out;
+
+	prandom_bytes(iobuf, mtd->erasesize);
+
+	bbt = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bbt)
+		goto out;
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+	for (i = 0; i < ebcnt; i++) {
+		if (!bbt[i])
+			goodebcnt++;
+	}
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Write all eraseblocks, 1 eraseblock at a time */
+	pr_info("testing eraseblock write speed\n");
+	start_timing();
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock(i);
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	stop_timing();
+	speed = calc_speed();
+	pr_info("eraseblock write speed is %ld KiB/s\n", speed);
+
+	/* Read all eraseblocks, 1 eraseblock at a time */
+	pr_info("testing eraseblock read speed\n");
+	start_timing();
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = read_eraseblock(i);
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	stop_timing();
+	speed = calc_speed();
+	pr_info("eraseblock read speed is %ld KiB/s\n", speed);
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Write all eraseblocks, 1 page at a time */
+	pr_info("testing page write speed\n");
+	start_timing();
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock_by_page(i);
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	stop_timing();
+	speed = calc_speed();
+	pr_info("page write speed is %ld KiB/s\n", speed);
+
+	/* Read all eraseblocks, 1 page at a time */
+	pr_info("testing page read speed\n");
+	start_timing();
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = read_eraseblock_by_page(i);
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	stop_timing();
+	speed = calc_speed();
+	pr_info("page read speed is %ld KiB/s\n", speed);
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Write all eraseblocks, 2 pages at a time */
+	pr_info("testing 2 page write speed\n");
+	start_timing();
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock_by_2pages(i);
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	stop_timing();
+	speed = calc_speed();
+	pr_info("2 page write speed is %ld KiB/s\n", speed);
+
+	/* Read all eraseblocks, 2 pages at a time */
+	pr_info("testing 2 page read speed\n");
+	start_timing();
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = read_eraseblock_by_2pages(i);
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	stop_timing();
+	speed = calc_speed();
+	pr_info("2 page read speed is %ld KiB/s\n", speed);
+
+	/* Erase all eraseblocks */
+	pr_info("Testing erase speed\n");
+	start_timing();
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+	stop_timing();
+	speed = calc_speed();
+	pr_info("erase speed is %ld KiB/s\n", speed);
+
+	/* Multi-block erase all eraseblocks */
+	for (k = 1; k < 7; k++) {
+		blocks = 1 << k;
+		pr_info("Testing %dx multi-block erase speed\n",
+		       blocks);
+		start_timing();
+		for (i = 0; i < ebcnt; ) {
+			for (j = 0; j < blocks && (i + j) < ebcnt; j++)
+				if (bbt[i + j])
+					break;
+			if (j < 1) {
+				i++;
+				continue;
+			}
+			err = multiblock_erase(i, j);
+			if (err)
+				goto out;
+			cond_resched();
+			i += j;
+		}
+		stop_timing();
+		speed = calc_speed();
+		pr_info("%dx multi-block erase speed is %ld KiB/s\n",
+		       blocks, speed);
+	}
+	pr_info("finished\n");
+out:
+	kfree(iobuf);
+	kfree(bbt);
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(mtd_speedtest_init);
+
+static void __exit mtd_speedtest_exit(void)
+{
+	return;
+}
+module_exit(mtd_speedtest_exit);
+
+MODULE_DESCRIPTION("Speed test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/stresstest.c b/drivers/mtd/tests/stresstest.c
new file mode 100644
index 0000000..1695248
--- /dev/null
+++ b/drivers/mtd/tests/stresstest.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test random reads, writes and erases on MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+
+#include "mtd_test.h"
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static int count = 10000;
+module_param(count, int, S_IRUGO);
+MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)");
+
+static struct mtd_info *mtd;
+static unsigned char *writebuf;
+static unsigned char *readbuf;
+static unsigned char *bbt;
+static int *offsets;
+
+static int pgsize;
+static int bufsize;
+static int ebcnt;
+static int pgcnt;
+
+static int rand_eb(void)
+{
+	unsigned int eb;
+
+again:
+	eb = prandom_u32();
+	/* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */
+	eb %= (ebcnt - 1);
+	if (bbt[eb])
+		goto again;
+	return eb;
+}
+
+static int rand_offs(void)
+{
+	unsigned int offs;
+
+	offs = prandom_u32();
+	offs %= bufsize;
+	return offs;
+}
+
+static int rand_len(int offs)
+{
+	unsigned int len;
+
+	len = prandom_u32();
+	len %= (bufsize - offs);
+	return len;
+}
+
+static int do_read(void)
+{
+	int eb = rand_eb();
+	int offs = rand_offs();
+	int len = rand_len(offs), err;
+	loff_t addr;
+
+	if (bbt[eb + 1]) {
+		if (offs >= mtd->erasesize)
+			offs -= mtd->erasesize;
+		if (offs + len > mtd->erasesize)
+			len = mtd->erasesize - offs;
+	}
+	addr = eb * mtd->erasesize + offs;
+	err = mtdtest_read(mtd, addr, len, readbuf);
+	if (unlikely(err)) {
+		pr_err("error: read failed at 0x%llx\n",
+		       (long long)addr);
+		return err;
+	}
+	return 0;
+}
+
+static int do_write(void)
+{
+	int eb = rand_eb(), offs, err, len;
+	loff_t addr;
+
+	offs = offsets[eb];
+	if (offs >= mtd->erasesize) {
+		err = mtdtest_erase_eraseblock(mtd, eb);
+		if (err)
+			return err;
+		offs = offsets[eb] = 0;
+	}
+	len = rand_len(offs);
+	len = ((len + pgsize - 1) / pgsize) * pgsize;
+	if (offs + len > mtd->erasesize) {
+		if (bbt[eb + 1])
+			len = mtd->erasesize - offs;
+		else {
+			err = mtdtest_erase_eraseblock(mtd, eb + 1);
+			if (err)
+				return err;
+			offsets[eb + 1] = 0;
+		}
+	}
+	addr = eb * mtd->erasesize + offs;
+	err = mtdtest_write(mtd, addr, len, writebuf);
+	if (unlikely(err)) {
+		pr_err("error: write failed at 0x%llx\n",
+		       (long long)addr);
+		return err;
+	}
+	offs += len;
+	while (offs > mtd->erasesize) {
+		offsets[eb++] = mtd->erasesize;
+		offs -= mtd->erasesize;
+	}
+	offsets[eb] = offs;
+	return 0;
+}
+
+static int do_operation(void)
+{
+	if (prandom_u32() & 1)
+		return do_read();
+	else
+		return do_write();
+}
+
+static int __init mtd_stresstest_init(void)
+{
+	int err;
+	int i, op;
+	uint64_t tmp;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
+	pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->writesize == 1) {
+		pr_info("not NAND flash, assume page size is 512 "
+		       "bytes.\n");
+		pgsize = 512;
+	} else
+		pgsize = mtd->writesize;
+
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / pgsize;
+
+	pr_info("MTD device size %llu, eraseblock size %u, "
+	       "page size %u, count of eraseblocks %u, pages per "
+	       "eraseblock %u, OOB size %u\n",
+	       (unsigned long long)mtd->size, mtd->erasesize,
+	       pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+	if (ebcnt < 2) {
+		pr_err("error: need at least 2 eraseblocks\n");
+		err = -ENOSPC;
+		goto out_put_mtd;
+	}
+
+	/* Read or write up 2 eraseblocks at a time */
+	bufsize = mtd->erasesize * 2;
+
+	err = -ENOMEM;
+	readbuf = vmalloc(bufsize);
+	writebuf = vmalloc(bufsize);
+	offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL);
+	if (!readbuf || !writebuf || !offsets)
+		goto out;
+	for (i = 0; i < ebcnt; i++)
+		offsets[i] = mtd->erasesize;
+	prandom_bytes(writebuf, bufsize);
+
+	bbt = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bbt)
+		goto out;
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	/* Do operations */
+	pr_info("doing operations\n");
+	for (op = 0; op < count; op++) {
+		if ((op & 1023) == 0)
+			pr_info("%d operations done\n", op);
+		err = do_operation();
+		if (err)
+			goto out;
+		cond_resched();
+	}
+	pr_info("finished, %d operations done\n", op);
+
+out:
+	kfree(offsets);
+	kfree(bbt);
+	vfree(writebuf);
+	vfree(readbuf);
+out_put_mtd:
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(mtd_stresstest_init);
+
+static void __exit mtd_stresstest_exit(void)
+{
+	return;
+}
+module_exit(mtd_stresstest_exit);
+
+MODULE_DESCRIPTION("Stress test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/subpagetest.c b/drivers/mtd/tests/subpagetest.c
new file mode 100644
index 0000000..e2c0adf
--- /dev/null
+++ b/drivers/mtd/tests/subpagetest.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test sub-page read and write on MTD device.
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+
+#include "mtd_test.h"
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *writebuf;
+static unsigned char *readbuf;
+static unsigned char *bbt;
+
+static int subpgsize;
+static int bufsize;
+static int ebcnt;
+static int pgcnt;
+static int errcnt;
+static struct rnd_state rnd_state;
+
+static inline void clear_data(unsigned char *buf, size_t len)
+{
+	memset(buf, 0, len);
+}
+
+static int write_eraseblock(int ebnum)
+{
+	size_t written;
+	int err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
+	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
+	if (unlikely(err || written != subpgsize)) {
+		pr_err("error: write failed at %#llx\n",
+		       (long long)addr);
+		if (written != subpgsize) {
+			pr_err("  write size: %#x\n", subpgsize);
+			pr_err("  written: %#zx\n", written);
+		}
+		return err ? err : -1;
+	}
+
+	addr += subpgsize;
+
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
+	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
+	if (unlikely(err || written != subpgsize)) {
+		pr_err("error: write failed at %#llx\n",
+		       (long long)addr);
+		if (written != subpgsize) {
+			pr_err("  write size: %#x\n", subpgsize);
+			pr_err("  written: %#zx\n", written);
+		}
+		return err ? err : -1;
+	}
+
+	return err;
+}
+
+static int write_eraseblock2(int ebnum)
+{
+	size_t written;
+	int err = 0, k;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	for (k = 1; k < 33; ++k) {
+		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
+			break;
+		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
+		err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
+		if (unlikely(err || written != subpgsize * k)) {
+			pr_err("error: write failed at %#llx\n",
+			       (long long)addr);
+			if (written != subpgsize) {
+				pr_err("  write size: %#x\n",
+				       subpgsize * k);
+				pr_err("  written: %#08zx\n",
+				       written);
+			}
+			return err ? err : -1;
+		}
+		addr += subpgsize * k;
+	}
+
+	return err;
+}
+
+static void print_subpage(unsigned char *p)
+{
+	int i, j;
+
+	for (i = 0; i < subpgsize; ) {
+		for (j = 0; i < subpgsize && j < 32; ++i, ++j)
+			printk("%02x", *p++);
+		printk("\n");
+	}
+}
+
+static int verify_eraseblock(int ebnum)
+{
+	size_t read;
+	int err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
+	clear_data(readbuf, subpgsize);
+	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
+	if (unlikely(err || read != subpgsize)) {
+		if (mtd_is_bitflip(err) && read == subpgsize) {
+			pr_info("ECC correction at %#llx\n",
+			       (long long)addr);
+			err = 0;
+		} else {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr);
+			return err ? err : -1;
+		}
+	}
+	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
+		pr_err("error: verify failed at %#llx\n",
+		       (long long)addr);
+		pr_info("------------- written----------------\n");
+		print_subpage(writebuf);
+		pr_info("------------- read ------------------\n");
+		print_subpage(readbuf);
+		pr_info("-------------------------------------\n");
+		errcnt += 1;
+	}
+
+	addr += subpgsize;
+
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
+	clear_data(readbuf, subpgsize);
+	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
+	if (unlikely(err || read != subpgsize)) {
+		if (mtd_is_bitflip(err) && read == subpgsize) {
+			pr_info("ECC correction at %#llx\n",
+			       (long long)addr);
+			err = 0;
+		} else {
+			pr_err("error: read failed at %#llx\n",
+			       (long long)addr);
+			return err ? err : -1;
+		}
+	}
+	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
+		pr_info("error: verify failed at %#llx\n",
+		       (long long)addr);
+		pr_info("------------- written----------------\n");
+		print_subpage(writebuf);
+		pr_info("------------- read ------------------\n");
+		print_subpage(readbuf);
+		pr_info("-------------------------------------\n");
+		errcnt += 1;
+	}
+
+	return err;
+}
+
+static int verify_eraseblock2(int ebnum)
+{
+	size_t read;
+	int err = 0, k;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	for (k = 1; k < 33; ++k) {
+		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
+			break;
+		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
+		clear_data(readbuf, subpgsize * k);
+		err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
+		if (unlikely(err || read != subpgsize * k)) {
+			if (mtd_is_bitflip(err) && read == subpgsize * k) {
+				pr_info("ECC correction at %#llx\n",
+				       (long long)addr);
+				err = 0;
+			} else {
+				pr_err("error: read failed at "
+				       "%#llx\n", (long long)addr);
+				return err ? err : -1;
+			}
+		}
+		if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
+			pr_err("error: verify failed at %#llx\n",
+			       (long long)addr);
+			errcnt += 1;
+		}
+		addr += subpgsize * k;
+	}
+
+	return err;
+}
+
+static int verify_eraseblock_ff(int ebnum)
+{
+	uint32_t j;
+	size_t read;
+	int err = 0;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	memset(writebuf, 0xff, subpgsize);
+	for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
+		clear_data(readbuf, subpgsize);
+		err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
+		if (unlikely(err || read != subpgsize)) {
+			if (mtd_is_bitflip(err) && read == subpgsize) {
+				pr_info("ECC correction at %#llx\n",
+				       (long long)addr);
+				err = 0;
+			} else {
+				pr_err("error: read failed at "
+				       "%#llx\n", (long long)addr);
+				return err ? err : -1;
+			}
+		}
+		if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
+			pr_err("error: verify 0xff failed at "
+			       "%#llx\n", (long long)addr);
+			errcnt += 1;
+		}
+		addr += subpgsize;
+	}
+
+	return err;
+}
+
+static int verify_all_eraseblocks_ff(void)
+{
+	int err;
+	unsigned int i;
+
+	pr_info("verifying all eraseblocks for 0xff\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = verify_eraseblock_ff(i);
+		if (err)
+			return err;
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+	return 0;
+}
+
+static int __init mtd_subpagetest_init(void)
+{
+	int err = 0;
+	uint32_t i;
+	uint64_t tmp;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
+	pr_info("MTD device: %d\n", dev);
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->type != MTD_NANDFLASH) {
+		pr_info("this test requires NAND flash\n");
+		goto out;
+	}
+
+	subpgsize = mtd->writesize >> mtd->subpage_sft;
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / mtd->writesize;
+
+	pr_info("MTD device size %llu, eraseblock size %u, "
+	       "page size %u, subpage size %u, count of eraseblocks %u, "
+	       "pages per eraseblock %u, OOB size %u\n",
+	       (unsigned long long)mtd->size, mtd->erasesize,
+	       mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
+
+	err = -ENOMEM;
+	bufsize = subpgsize * 32;
+	writebuf = kmalloc(bufsize, GFP_KERNEL);
+	if (!writebuf)
+		goto out;
+	readbuf = kmalloc(bufsize, GFP_KERNEL);
+	if (!readbuf)
+		goto out;
+	bbt = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bbt)
+		goto out;
+
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	pr_info("writing whole device\n");
+	prandom_seed_state(&rnd_state, 1);
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock(i);
+		if (unlikely(err))
+			goto out;
+		if (i % 256 == 0)
+			pr_info("written up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("written %u eraseblocks\n", i);
+
+	prandom_seed_state(&rnd_state, 1);
+	pr_info("verifying all eraseblocks\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = verify_eraseblock(i);
+		if (unlikely(err))
+			goto out;
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	err = verify_all_eraseblocks_ff();
+	if (err)
+		goto out;
+
+	/* Write all eraseblocks */
+	prandom_seed_state(&rnd_state, 3);
+	pr_info("writing whole device\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = write_eraseblock2(i);
+		if (unlikely(err))
+			goto out;
+		if (i % 256 == 0)
+			pr_info("written up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("written %u eraseblocks\n", i);
+
+	/* Check all eraseblocks */
+	prandom_seed_state(&rnd_state, 3);
+	pr_info("verifying all eraseblocks\n");
+	for (i = 0; i < ebcnt; ++i) {
+		if (bbt[i])
+			continue;
+		err = verify_eraseblock2(i);
+		if (unlikely(err))
+			goto out;
+		if (i % 256 == 0)
+			pr_info("verified up to eraseblock %u\n", i);
+		cond_resched();
+	}
+	pr_info("verified %u eraseblocks\n", i);
+
+	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+	if (err)
+		goto out;
+
+	err = verify_all_eraseblocks_ff();
+	if (err)
+		goto out;
+
+	pr_info("finished with %d errors\n", errcnt);
+
+out:
+	kfree(bbt);
+	kfree(readbuf);
+	kfree(writebuf);
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(mtd_subpagetest_init);
+
+static void __exit mtd_subpagetest_exit(void)
+{
+	return;
+}
+module_exit(mtd_subpagetest_exit);
+
+MODULE_DESCRIPTION("Subpage test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/torturetest.c b/drivers/mtd/tests/torturetest.c
new file mode 100644
index 0000000..eeab969
--- /dev/null
+++ b/drivers/mtd/tests/torturetest.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2006-2008 Artem Bityutskiy
+ * Copyright (C) 2006-2008 Jarkko Lavinen
+ * Copyright (C) 2006-2008 Adrian Hunter
+ *
+ * This program is free software; you can 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Artem Bityutskiy, Jarkko Lavinen, Adria Hunter
+ *
+ * WARNING: this test program may kill your flash and your device. Do not
+ * use it unless you know what you do. Authors are not responsible for any
+ * damage caused by this program.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include "mtd_test.h"
+
+#define RETRIES 3
+
+static int eb = 8;
+module_param(eb, int, S_IRUGO);
+MODULE_PARM_DESC(eb, "eraseblock number within the selected MTD device");
+
+static int ebcnt = 32;
+module_param(ebcnt, int, S_IRUGO);
+MODULE_PARM_DESC(ebcnt, "number of consecutive eraseblocks to torture");
+
+static int pgcnt;
+module_param(pgcnt, int, S_IRUGO);
+MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)");
+
+static int dev = -EINVAL;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static int gran = 512;
+module_param(gran, int, S_IRUGO);
+MODULE_PARM_DESC(gran, "how often the status information should be printed");
+
+static int check = 1;
+module_param(check, int, S_IRUGO);
+MODULE_PARM_DESC(check, "if the written data should be checked");
+
+static unsigned int cycles_count;
+module_param(cycles_count, uint, S_IRUGO);
+MODULE_PARM_DESC(cycles_count, "how many erase cycles to do "
+			       "(infinite by default)");
+
+static struct mtd_info *mtd;
+
+/* This buffer contains 0x555555...0xAAAAAA... pattern */
+static unsigned char *patt_5A5;
+/* This buffer contains 0xAAAAAA...0x555555... pattern */
+static unsigned char *patt_A5A;
+/* This buffer contains all 0xFF bytes */
+static unsigned char *patt_FF;
+/* This a temporary buffer is use when checking data */
+static unsigned char *check_buf;
+/* How many erase cycles were done */
+static unsigned int erase_cycles;
+
+static int pgsize;
+static struct timeval start, finish;
+
+static void report_corrupt(unsigned char *read, unsigned char *written);
+
+static inline void start_timing(void)
+{
+	do_gettimeofday(&start);
+}
+
+static inline void stop_timing(void)
+{
+	do_gettimeofday(&finish);
+}
+
+/*
+ * Check that the contents of eraseblock number @enbum is equivalent to the
+ * @buf buffer.
+ */
+static inline int check_eraseblock(int ebnum, unsigned char *buf)
+{
+	int err, retries = 0;
+	size_t read;
+	loff_t addr = ebnum * mtd->erasesize;
+	size_t len = mtd->erasesize;
+
+	if (pgcnt) {
+		addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
+		len = pgcnt * pgsize;
+	}
+
+retry:
+	err = mtd_read(mtd, addr, len, &read, check_buf);
+	if (mtd_is_bitflip(err))
+		pr_err("single bit flip occurred at EB %d "
+		       "MTD reported that it was fixed.\n", ebnum);
+	else if (err) {
+		pr_err("error %d while reading EB %d, "
+		       "read %zd\n", err, ebnum, read);
+		return err;
+	}
+
+	if (read != len) {
+		pr_err("failed to read %zd bytes from EB %d, "
+		       "read only %zd, but no error reported\n",
+		       len, ebnum, read);
+		return -EIO;
+	}
+
+	if (memcmp(buf, check_buf, len)) {
+		pr_err("read wrong data from EB %d\n", ebnum);
+		report_corrupt(check_buf, buf);
+
+		if (retries++ < RETRIES) {
+			/* Try read again */
+			yield();
+			pr_info("re-try reading data from EB %d\n",
+			       ebnum);
+			goto retry;
+		} else {
+			pr_info("retried %d times, still errors, "
+			       "give-up\n", RETRIES);
+			return -EINVAL;
+		}
+	}
+
+	if (retries != 0)
+		pr_info("only attempt number %d was OK (!!!)\n",
+		       retries);
+
+	return 0;
+}
+
+static inline int write_pattern(int ebnum, void *buf)
+{
+	int err;
+	size_t written;
+	loff_t addr = ebnum * mtd->erasesize;
+	size_t len = mtd->erasesize;
+
+	if (pgcnt) {
+		addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
+		len = pgcnt * pgsize;
+	}
+	err = mtd_write(mtd, addr, len, &written, buf);
+	if (err) {
+		pr_err("error %d while writing EB %d, written %zd"
+		      " bytes\n", err, ebnum, written);
+		return err;
+	}
+	if (written != len) {
+		pr_info("written only %zd bytes of %zd, but no error"
+		       " reported\n", written, len);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int __init tort_init(void)
+{
+	int err = 0, i, infinite = !cycles_count;
+	unsigned char *bad_ebs;
+
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "=================================================\n");
+	pr_info("Warning: this program is trying to wear out your "
+	       "flash, stop it if this is not wanted.\n");
+
+	if (dev < 0) {
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
+	pr_info("MTD device: %d\n", dev);
+	pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n",
+	       ebcnt, eb, eb + ebcnt - 1, dev);
+	if (pgcnt)
+		pr_info("torturing just %d pages per eraseblock\n",
+			pgcnt);
+	pr_info("write verify %s\n", check ? "enabled" : "disabled");
+
+	mtd = get_mtd_device(NULL, dev);
+	if (IS_ERR(mtd)) {
+		err = PTR_ERR(mtd);
+		pr_err("error: cannot get MTD device\n");
+		return err;
+	}
+
+	if (mtd->writesize == 1) {
+		pr_info("not NAND flash, assume page size is 512 "
+		       "bytes.\n");
+		pgsize = 512;
+	} else
+		pgsize = mtd->writesize;
+
+	if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) {
+		pr_err("error: invalid pgcnt value %d\n", pgcnt);
+		goto out_mtd;
+	}
+
+	err = -ENOMEM;
+	patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!patt_5A5)
+		goto out_mtd;
+
+	patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!patt_A5A)
+		goto out_patt_5A5;
+
+	patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!patt_FF)
+		goto out_patt_A5A;
+
+	check_buf = kmalloc(mtd->erasesize, GFP_KERNEL);
+	if (!check_buf)
+		goto out_patt_FF;
+
+	bad_ebs = kzalloc(ebcnt, GFP_KERNEL);
+	if (!bad_ebs)
+		goto out_check_buf;
+
+	err = 0;
+
+	/* Initialize patterns */
+	memset(patt_FF, 0xFF, mtd->erasesize);
+	for (i = 0; i < mtd->erasesize / pgsize; i++) {
+		if (!(i & 1)) {
+			memset(patt_5A5 + i * pgsize, 0x55, pgsize);
+			memset(patt_A5A + i * pgsize, 0xAA, pgsize);
+		} else {
+			memset(patt_5A5 + i * pgsize, 0xAA, pgsize);
+			memset(patt_A5A + i * pgsize, 0x55, pgsize);
+		}
+	}
+
+	err = mtdtest_scan_for_bad_eraseblocks(mtd, bad_ebs, eb, ebcnt);
+	if (err)
+		goto out;
+
+	start_timing();
+	while (1) {
+		int i;
+		void *patt;
+
+		mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt);
+
+		/* Check if the eraseblocks contain only 0xFF bytes */
+		if (check) {
+			for (i = eb; i < eb + ebcnt; i++) {
+				if (bad_ebs[i - eb])
+					continue;
+				err = check_eraseblock(i, patt_FF);
+				if (err) {
+					pr_info("verify failed"
+					       " for 0xFF... pattern\n");
+					goto out;
+				}
+				cond_resched();
+			}
+		}
+
+		/* Write the pattern */
+		for (i = eb; i < eb + ebcnt; i++) {
+			if (bad_ebs[i - eb])
+				continue;
+			if ((eb + erase_cycles) & 1)
+				patt = patt_5A5;
+			else
+				patt = patt_A5A;
+			err = write_pattern(i, patt);
+			if (err)
+				goto out;
+			cond_resched();
+		}
+
+		/* Verify what we wrote */
+		if (check) {
+			for (i = eb; i < eb + ebcnt; i++) {
+				if (bad_ebs[i - eb])
+					continue;
+				if ((eb + erase_cycles) & 1)
+					patt = patt_5A5;
+				else
+					patt = patt_A5A;
+				err = check_eraseblock(i, patt);
+				if (err) {
+					pr_info("verify failed for %s"
+					       " pattern\n",
+					       ((eb + erase_cycles) & 1) ?
+					       "0x55AA55..." : "0xAA55AA...");
+					goto out;
+				}
+				cond_resched();
+			}
+		}
+
+		erase_cycles += 1;
+
+		if (erase_cycles % gran == 0) {
+			long ms;
+
+			stop_timing();
+			ms = (finish.tv_sec - start.tv_sec) * 1000 +
+			     (finish.tv_usec - start.tv_usec) / 1000;
+			pr_info("%08u erase cycles done, took %lu "
+			       "milliseconds (%lu seconds)\n",
+			       erase_cycles, ms, ms / 1000);
+			start_timing();
+		}
+
+		if (!infinite && --cycles_count == 0)
+			break;
+	}
+out:
+
+	pr_info("finished after %u erase cycles\n",
+	       erase_cycles);
+	kfree(bad_ebs);
+out_check_buf:
+	kfree(check_buf);
+out_patt_FF:
+	kfree(patt_FF);
+out_patt_A5A:
+	kfree(patt_A5A);
+out_patt_5A5:
+	kfree(patt_5A5);
+out_mtd:
+	put_mtd_device(mtd);
+	if (err)
+		pr_info("error %d occurred during torturing\n", err);
+	printk(KERN_INFO "=================================================\n");
+	return err;
+}
+module_init(tort_init);
+
+static void __exit tort_exit(void)
+{
+	return;
+}
+module_exit(tort_exit);
+
+static int countdiffs(unsigned char *buf, unsigned char *check_buf,
+		      unsigned offset, unsigned len, unsigned *bytesp,
+		      unsigned *bitsp);
+static void print_bufs(unsigned char *read, unsigned char *written, int start,
+		       int len);
+
+/*
+ * Report the detailed information about how the read EB differs from what was
+ * written.
+ */
+static void report_corrupt(unsigned char *read, unsigned char *written)
+{
+	int i;
+	int bytes, bits, pages, first;
+	int offset, len;
+	size_t check_len = mtd->erasesize;
+
+	if (pgcnt)
+		check_len = pgcnt * pgsize;
+
+	bytes = bits = pages = 0;
+	for (i = 0; i < check_len; i += pgsize)
+		if (countdiffs(written, read, i, pgsize, &bytes,
+			       &bits) >= 0)
+			pages++;
+
+	pr_info("verify fails on %d pages, %d bytes/%d bits\n",
+	       pages, bytes, bits);
+	pr_info("The following is a list of all differences between"
+	       " what was read from flash and what was expected\n");
+
+	for (i = 0; i < check_len; i += pgsize) {
+		cond_resched();
+		bytes = bits = 0;
+		first = countdiffs(written, read, i, pgsize, &bytes,
+				   &bits);
+		if (first < 0)
+			continue;
+
+		printk("-------------------------------------------------------"
+		       "----------------------------------\n");
+
+		pr_info("Page %zd has %d bytes/%d bits failing verify,"
+		       " starting at offset 0x%x\n",
+		       (mtd->erasesize - check_len + i) / pgsize,
+		       bytes, bits, first);
+
+		offset = first & ~0x7;
+		len = ((first + bytes) | 0x7) + 1 - offset;
+
+		print_bufs(read, written, offset, len);
+	}
+}
+
+static void print_bufs(unsigned char *read, unsigned char *written, int start,
+		       int len)
+{
+	int i = 0, j1, j2;
+	char *diff;
+
+	printk("Offset       Read                          Written\n");
+	while (i < len) {
+		printk("0x%08x: ", start + i);
+		diff = "   ";
+		for (j1 = 0; j1 < 8 && i + j1 < len; j1++) {
+			printk(" %02x", read[start + i + j1]);
+			if (read[start + i + j1] != written[start + i + j1])
+				diff = "***";
+		}
+
+		while (j1 < 8) {
+			printk(" ");
+			j1 += 1;
+		}
+
+		printk("  %s ", diff);
+
+		for (j2 = 0; j2 < 8 && i + j2 < len; j2++)
+			printk(" %02x", written[start + i + j2]);
+		printk("\n");
+		i += 8;
+	}
+}
+
+/*
+ * Count the number of differing bytes and bits and return the first differing
+ * offset.
+ */
+static int countdiffs(unsigned char *buf, unsigned char *check_buf,
+		      unsigned offset, unsigned len, unsigned *bytesp,
+		      unsigned *bitsp)
+{
+	unsigned i, bit;
+	int first = -1;
+
+	for (i = offset; i < offset + len; i++)
+		if (buf[i] != check_buf[i]) {
+			first = i;
+			break;
+		}
+
+	while (i < offset + len) {
+		if (buf[i] != check_buf[i]) {
+			(*bytesp)++;
+			bit = 1;
+			while (bit < 256) {
+				if ((buf[i] & bit) != (check_buf[i] & bit))
+					(*bitsp)++;
+				bit <<= 1;
+			}
+		}
+		i++;
+	}
+
+	return first;
+}
+
+MODULE_DESCRIPTION("Eraseblock torturing module");
+MODULE_AUTHOR("Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index cff6f02..7f2a032 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -996,7 +996,7 @@ static int __init cops_module_init(void)
 		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
 			cardname);
 	cops_dev = cops_probe(-1);
-	return PTR_RET(cops_dev);
+	return PTR_ERR_OR_ZERO(cops_dev);
 }
 
 static void __exit cops_module_exit(void)
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index b5782cd..01e2ac5 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1243,7 +1243,7 @@ static int __init ltpc_module_init(void)
 		       "ltpc: Autoprobing is not recommended for modules\n");
 
 	dev_ltpc = ltpc_probe();
-	return PTR_RET(dev_ltpc);
+	return PTR_ERR_OR_ZERO(dev_ltpc);
 }
 module_init(ltpc_module_init);
 #endif
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 390061d..9010265 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -143,10 +143,9 @@ static inline struct bonding *__get_bond_by_port(struct port *port)
  */
 static inline struct port *__get_first_port(struct bonding *bond)
 {
-	if (bond->slave_cnt == 0)
-		return NULL;
+	struct slave *first_slave = bond_first_slave(bond);
 
-	return &(SLAVE_AD_INFO(bond->first_slave).port);
+	return first_slave ? &(SLAVE_AD_INFO(first_slave).port) : NULL;
 }
 
 /**
@@ -159,13 +158,16 @@ static inline struct port *__get_first_port(struct bonding *bond)
 static inline struct port *__get_next_port(struct port *port)
 {
 	struct bonding *bond = __get_bond_by_port(port);
-	struct slave *slave = port->slave;
+	struct slave *slave = port->slave, *slave_next;
 
 	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->first_slave))
+	if (bond == NULL)
+		return NULL;
+	slave_next = bond_next_slave(bond, slave);
+	if (!slave_next || bond_is_first_slave(bond, slave_next))
 		return NULL;
 
-	return &(SLAVE_AD_INFO(slave->next).port);
+	return &(SLAVE_AD_INFO(slave_next).port);
 }
 
 /**
@@ -178,12 +180,14 @@ static inline struct port *__get_next_port(struct port *port)
 static inline struct aggregator *__get_first_agg(struct port *port)
 {
 	struct bonding *bond = __get_bond_by_port(port);
+	struct slave *first_slave;
 
 	// If there's no bond for this port, or bond has no slaves
-	if ((bond == NULL) || (bond->slave_cnt == 0))
+	if (bond == NULL)
 		return NULL;
+	first_slave = bond_first_slave(bond);
 
-	return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
+	return first_slave ? &(SLAVE_AD_INFO(first_slave).aggregator) : NULL;
 }
 
 /**
@@ -195,14 +199,17 @@ static inline struct aggregator *__get_first_agg(struct port *port)
  */
 static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
 {
-	struct slave *slave = aggregator->slave;
+	struct slave *slave = aggregator->slave, *slave_next;
 	struct bonding *bond = bond_get_bond_by_slave(slave);
 
 	// If there's no bond for this aggregator, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->first_slave))
+	if (bond == NULL)
+		return NULL;
+	slave_next = bond_next_slave(bond, slave);
+	if (!slave_next || bond_is_first_slave(bond, slave_next))
 		return NULL;
 
-	return &(SLAVE_AD_INFO(slave->next).aggregator);
+	return &(SLAVE_AD_INFO(slave_next).aggregator);
 }
 
 /*
@@ -2110,7 +2117,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
 	read_lock(&bond->lock);
 
 	//check if there are any slaves
-	if (bond->slave_cnt == 0)
+	if (list_empty(&bond->slave_list))
 		goto re_arm;
 
 	// check if agg_select_timer timer after initialize is timed out
@@ -2336,8 +2343,12 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 int bond_3ad_set_carrier(struct bonding *bond)
 {
 	struct aggregator *active;
+	struct slave *first_slave;
 
-	active = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+	first_slave = bond_first_slave(bond);
+	if (!first_slave)
+		return 0;
+	active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator));
 	if (active) {
 		/* are enough slaves available to consider link up? */
 		if (active->num_of_ports < bond->params.min_links) {
@@ -2415,6 +2426,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 	struct ad_info ad_info;
 	int res = 1;
 
+	read_lock(&bond->lock);
 	if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
 			 dev->name);
@@ -2432,7 +2444,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 
 	slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg && (agg->aggregator_identifier == agg_id)) {
@@ -2464,6 +2476,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 	}
 
 out:
+	read_unlock(&bond->lock);
 	if (res) {
 		/* no suitable interface, frame not sent */
 		kfree_skb(skb);
@@ -2501,7 +2514,6 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
  */
 void bond_3ad_update_lacp_rate(struct bonding *bond)
 {
-	int i;
 	struct slave *slave;
 	struct port *port = NULL;
 	int lacp_fast;
@@ -2509,7 +2521,7 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
 	write_lock_bh(&bond->lock);
 	lacp_fast = bond->params.lacp_fast;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		port = &(SLAVE_AD_INFO(slave).port);
 		if (port->slave == NULL)
 			continue;
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 4ea8ed1..3a5db7b 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -224,13 +224,12 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
 {
 	struct slave *slave, *least_loaded;
 	long long max_gap;
-	int i;
 
 	least_loaded = NULL;
 	max_gap = LLONG_MIN;
 
 	/* Find the slave with the largest gap */
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (SLAVE_IS_OK(slave)) {
 			long long gap = compute_gap(slave);
 
@@ -386,11 +385,10 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
 	struct slave *rx_slave, *slave, *start_at;
 	int i = 0;
 
-	if (bond_info->next_rx_slave) {
+	if (bond_info->next_rx_slave)
 		start_at = bond_info->next_rx_slave;
-	} else {
-		start_at = bond->first_slave;
-	}
+	else
+		start_at = bond_first_slave(bond);
 
 	rx_slave = NULL;
 
@@ -405,7 +403,8 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
 	}
 
 	if (rx_slave) {
-		bond_info->next_rx_slave = rx_slave->next;
+		slave = bond_next_slave(bond, rx_slave);
+		bond_info->next_rx_slave = slave;
 	}
 
 	return rx_slave;
@@ -1173,9 +1172,8 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 {
 	struct slave *tmp_slave1, *free_mac_slave = NULL;
 	struct slave *has_bond_addr = bond->curr_active_slave;
-	int i;
 
-	if (bond->slave_cnt == 0) {
+	if (list_empty(&bond->slave_list)) {
 		/* this is the first slave */
 		return 0;
 	}
@@ -1196,7 +1194,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 	/* The slave's address is equal to the address of the bond.
 	 * Search for a spare address in the bond for this slave.
 	 */
-	bond_for_each_slave(bond, tmp_slave1, i) {
+	bond_for_each_slave(bond, tmp_slave1) {
 		if (!bond_slave_has_mac(bond, tmp_slave1->perm_hwaddr)) {
 			/* no slave has tmp_slave1's perm addr
 			 * as its curr addr
@@ -1246,17 +1244,15 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
  */
 static int alb_set_mac_address(struct bonding *bond, void *addr)
 {
-	struct sockaddr sa;
-	struct slave *slave, *stop_at;
 	char tmp_addr[ETH_ALEN];
+	struct slave *slave;
+	struct sockaddr sa;
 	int res;
-	int i;
 
-	if (bond->alb_info.rlb_enabled) {
+	if (bond->alb_info.rlb_enabled)
 		return 0;
-	}
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		/* save net_device's current hw address */
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 
@@ -1276,8 +1272,7 @@ unwind:
 	sa.sa_family = bond->dev->type;
 
 	/* unwind from head to the slave that failed */
-	stop_at = slave;
-	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
+	bond_for_each_slave_continue_reverse(bond, slave) {
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 		dev_set_mac_address(slave->dev, &sa);
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
@@ -1342,6 +1337,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 
 	/* make sure that the curr_active_slave do not change during tx
 	 */
+	read_lock(&bond->lock);
 	read_lock(&bond->curr_slave_lock);
 
 	switch (ntohs(skb->protocol)) {
@@ -1446,11 +1442,12 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 	}
 
 	read_unlock(&bond->curr_slave_lock);
-
+	read_unlock(&bond->lock);
 	if (res) {
 		/* no suitable interface, frame not sent */
 		kfree_skb(skb);
 	}
+
 	return NETDEV_TX_OK;
 }
 
@@ -1460,11 +1457,10 @@ void bond_alb_monitor(struct work_struct *work)
 					    alb_work.work);
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct slave *slave;
-	int i;
 
 	read_lock(&bond->lock);
 
-	if (bond->slave_cnt == 0) {
+	if (list_empty(&bond->slave_list)) {
 		bond_info->tx_rebalance_counter = 0;
 		bond_info->lp_counter = 0;
 		goto re_arm;
@@ -1482,9 +1478,8 @@ void bond_alb_monitor(struct work_struct *work)
 		 */
 		read_lock(&bond->curr_slave_lock);
 
-		bond_for_each_slave(bond, slave, i) {
+		bond_for_each_slave(bond, slave)
 			alb_send_learning_packets(slave, slave->dev->dev_addr);
-		}
 
 		read_unlock(&bond->curr_slave_lock);
 
@@ -1496,7 +1491,7 @@ void bond_alb_monitor(struct work_struct *work)
 
 		read_lock(&bond->curr_slave_lock);
 
-		bond_for_each_slave(bond, slave, i) {
+		bond_for_each_slave(bond, slave) {
 			tlb_clear_slave(bond, slave, 1);
 			if (slave == bond->curr_active_slave) {
 				SLAVE_TLB_INFO(slave).load =
@@ -1602,9 +1597,8 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
  */
 void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
 {
-	if (bond->slave_cnt > 1) {
+	if (!list_empty(&bond->slave_list))
 		alb_change_hw_addr_on_detach(bond, slave);
-	}
 
 	tlb_clear_slave(bond, slave, 0);
 
@@ -1661,9 +1655,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
 {
 	struct slave *swap_slave;
 
-	if (bond->curr_active_slave == new_slave) {
+	if (bond->curr_active_slave == new_slave)
 		return;
-	}
 
 	if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) {
 		dev_set_promiscuity(bond->curr_active_slave->dev, -1);
@@ -1672,11 +1665,10 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
 	}
 
 	swap_slave = bond->curr_active_slave;
-	bond->curr_active_slave = new_slave;
+	rcu_assign_pointer(bond->curr_active_slave, new_slave);
 
-	if (!new_slave || (bond->slave_cnt == 0)) {
+	if (!new_slave || list_empty(&bond->slave_list))
 		return;
-	}
 
 	/* set the new curr_active_slave to the bonds mac address
 	 * i.e. swap mac addresses of old curr_active_slave and new curr_active_slave
@@ -1689,9 +1681,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
 	 * ignored so we can mess with their MAC addresses without
 	 * fear of interference from transmit activity.
 	 */
-	if (swap_slave) {
+	if (swap_slave)
 		tlb_clear_slave(bond, swap_slave, 1);
-	}
 	tlb_clear_slave(bond, new_slave, 1);
 
 	write_unlock_bh(&bond->curr_slave_lock);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 07f257d4..5697043 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -77,6 +77,7 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include <net/pkt_sched.h>
+#include <linux/rculist.h>
 #include "bonding.h"
 #include "bond_3ad.h"
 #include "bond_alb.h"
@@ -106,7 +107,7 @@ static char *arp_ip_target[BOND_MAX_ARP_TARGETS];
 static char *arp_validate;
 static char *arp_all_targets;
 static char *fail_over_mac;
-static int all_slaves_active = 0;
+static int all_slaves_active;
 static struct bond_params bonding_defaults;
 static int resend_igmp = BOND_DEFAULT_RESEND_IGMP;
 
@@ -273,7 +274,7 @@ const char *bond_mode_name(int mode)
 		[BOND_MODE_ALB] = "adaptive load balancing",
 	};
 
-	if (mode < 0 || mode > BOND_MODE_ALB)
+	if (mode < BOND_MODE_ROUNDROBIN || mode > BOND_MODE_ALB)
 		return "unknown";
 
 	return names[mode];
@@ -441,10 +442,10 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
 				__be16 proto, u16 vid)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave, *stop_at;
-	int i, res;
+	struct slave *slave;
+	int res;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		res = vlan_vid_add(slave->dev, proto, vid);
 		if (res)
 			goto unwind;
@@ -461,8 +462,7 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
 
 unwind:
 	/* unwind from head to the slave that failed */
-	stop_at = slave;
-	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at)
+	bond_for_each_slave_continue_reverse(bond, slave)
 		vlan_vid_del(slave->dev, proto, vid);
 
 	return res;
@@ -478,9 +478,9 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave;
-	int i, res;
+	int res;
 
-	bond_for_each_slave(bond, slave, i)
+	bond_for_each_slave(bond, slave)
 		vlan_vid_del(slave->dev, proto, vid);
 
 	res = bond_del_vlan(bond, vid);
@@ -532,15 +532,14 @@ static void bond_del_vlans_from_slave(struct bonding *bond,
 static int bond_set_carrier(struct bonding *bond)
 {
 	struct slave *slave;
-	int i;
 
-	if (bond->slave_cnt == 0)
+	if (list_empty(&bond->slave_list))
 		goto down;
 
 	if (bond->params.mode == BOND_MODE_8023AD)
 		return bond_3ad_set_carrier(bond);
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (slave->link == BOND_LINK_UP) {
 			if (!netif_carrier_ok(bond->dev)) {
 				netif_carrier_on(bond->dev);
@@ -681,8 +680,8 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
 		}
 	} else {
 		struct slave *slave;
-		int i;
-		bond_for_each_slave(bond, slave, i) {
+
+		bond_for_each_slave(bond, slave) {
 			err = dev_set_promiscuity(slave->dev, inc);
 			if (err)
 				return err;
@@ -705,8 +704,8 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
 		}
 	} else {
 		struct slave *slave;
-		int i;
-		bond_for_each_slave(bond, slave, i) {
+
+		bond_for_each_slave(bond, slave) {
 			err = dev_set_allmulti(slave->dev, inc);
 			if (err)
 				return err;
@@ -715,15 +714,6 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
 	return err;
 }
 
-static void __bond_resend_igmp_join_requests(struct net_device *dev)
-{
-	struct in_device *in_dev;
-
-	in_dev = __in_dev_get_rcu(dev);
-	if (in_dev)
-		ip_mc_rejoin_groups(in_dev);
-}
-
 /*
  * Retrieve the list of registered multicast addresses for the bonding
  * device and retransmit an IGMP JOIN request to the current active
@@ -731,33 +721,12 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev)
  */
 static void bond_resend_igmp_join_requests(struct bonding *bond)
 {
-	struct net_device *bond_dev, *vlan_dev, *upper_dev;
-	struct vlan_entry *vlan;
-
-	read_lock(&bond->lock);
-	rcu_read_lock();
-
-	bond_dev = bond->dev;
-
-	/* rejoin all groups on bond device */
-	__bond_resend_igmp_join_requests(bond_dev);
-
-	/*
-	 * if bond is enslaved to a bridge,
-	 * then rejoin all groups on its master
-	 */
-	upper_dev = netdev_master_upper_dev_get_rcu(bond_dev);
-	if (upper_dev && upper_dev->priv_flags & IFF_EBRIDGE)
-		__bond_resend_igmp_join_requests(upper_dev);
-
-	/* rejoin all groups on vlan devices */
-	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-		vlan_dev = __vlan_find_dev_deep(bond_dev, htons(ETH_P_8021Q),
-						vlan->vlan_id);
-		if (vlan_dev)
-			__bond_resend_igmp_join_requests(vlan_dev);
+	if (!rtnl_trylock()) {
+		queue_delayed_work(bond->wq, &bond->mcast_work, 1);
+		return;
 	}
-	rcu_read_unlock();
+	call_netdevice_notifiers(NETDEV_RESEND_IGMP, bond->dev);
+	rtnl_unlock();
 
 	/* We use curr_slave_lock to protect against concurrent access to
 	 * igmp_retrans from multiple running instances of this function and
@@ -769,7 +738,6 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
 		queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
 	}
 	write_unlock_bh(&bond->curr_slave_lock);
-	read_unlock(&bond->lock);
 }
 
 static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
@@ -808,6 +776,8 @@ static void bond_hw_addr_flush(struct net_device *bond_dev,
 static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
 			      struct slave *old_active)
 {
+	ASSERT_RTNL();
+
 	if (old_active) {
 		if (bond->dev->flags & IFF_PROMISC)
 			dev_set_promiscuity(old_active->dev, -1);
@@ -966,9 +936,8 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
 	new_active = bond->curr_active_slave;
 
 	if (!new_active) { /* there were no active slaves left */
-		if (bond->slave_cnt > 0)   /* found one slave */
-			new_active = bond->first_slave;
-		else
+		new_active = bond_first_slave(bond);
+		if (!new_active)
 			return NULL; /* still no slave, return NULL */
 	}
 
@@ -1071,7 +1040,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 		if (new_active)
 			bond_set_slave_active_flags(new_active);
 	} else {
-		bond->curr_active_slave = new_active;
+		rcu_assign_pointer(bond->curr_active_slave, new_active);
 	}
 
 	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
@@ -1115,7 +1084,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 	    ((USES_PRIMARY(bond->params.mode) && new_active) ||
 	     bond->params.mode == BOND_MODE_ROUNDROBIN)) {
 		bond->igmp_retrans = bond->params.resend_igmp;
-		queue_delayed_work(bond->wq, &bond->mcast_work, 0);
+		queue_delayed_work(bond->wq, &bond->mcast_work, 1);
 	}
 }
 
@@ -1161,17 +1130,7 @@ void bond_select_active_slave(struct bonding *bond)
  */
 static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
 {
-	if (bond->first_slave == NULL) { /* attaching the first slave */
-		new_slave->next = new_slave;
-		new_slave->prev = new_slave;
-		bond->first_slave = new_slave;
-	} else {
-		new_slave->next = bond->first_slave;
-		new_slave->prev = bond->first_slave->prev;
-		new_slave->next->prev = new_slave;
-		new_slave->prev->next = new_slave;
-	}
-
+	list_add_tail_rcu(&new_slave->list, &bond->slave_list);
 	bond->slave_cnt++;
 }
 
@@ -1187,22 +1146,7 @@ static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
  */
 static void bond_detach_slave(struct bonding *bond, struct slave *slave)
 {
-	if (slave->next)
-		slave->next->prev = slave->prev;
-
-	if (slave->prev)
-		slave->prev->next = slave->next;
-
-	if (bond->first_slave == slave) { /* slave is the first slave */
-		if (bond->slave_cnt > 1) { /* there are more slave */
-			bond->first_slave = slave->next;
-		} else {
-			bond->first_slave = NULL; /* slave was the last one */
-		}
-	}
-
-	slave->next = NULL;
-	slave->prev = NULL;
+	list_del_rcu(&slave->list);
 	bond->slave_cnt--;
 }
 
@@ -1249,47 +1193,31 @@ static void bond_poll_controller(struct net_device *bond_dev)
 {
 }
 
-static void __bond_netpoll_cleanup(struct bonding *bond)
+static void bond_netpoll_cleanup(struct net_device *bond_dev)
 {
+	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave;
-	int i;
 
-	bond_for_each_slave(bond, slave, i)
+	bond_for_each_slave(bond, slave)
 		if (IS_UP(slave->dev))
 			slave_disable_netpoll(slave);
 }
-static void bond_netpoll_cleanup(struct net_device *bond_dev)
-{
-	struct bonding *bond = netdev_priv(bond_dev);
-
-	read_lock(&bond->lock);
-	__bond_netpoll_cleanup(bond);
-	read_unlock(&bond->lock);
-}
 
 static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp)
 {
 	struct bonding *bond = netdev_priv(dev);
 	struct slave *slave;
-	int i, err = 0;
+	int err = 0;
 
-	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		err = slave_enable_netpoll(slave);
 		if (err) {
-			__bond_netpoll_cleanup(bond);
+			bond_netpoll_cleanup(dev);
 			break;
 		}
 	}
-	read_unlock(&bond->lock);
 	return err;
 }
-
-static struct netpoll_info *bond_netpoll_info(struct bonding *bond)
-{
-	return bond->dev->npinfo;
-}
-
 #else
 static inline int slave_enable_netpoll(struct slave *slave)
 {
@@ -1311,11 +1239,10 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	struct slave *slave;
 	struct bonding *bond = netdev_priv(dev);
 	netdev_features_t mask;
-	int i;
 
 	read_lock(&bond->lock);
 
-	if (!bond->first_slave) {
+	if (list_empty(&bond->slave_list)) {
 		/* Disable adding VLANs to empty bond. But why? --mq */
 		features |= NETIF_F_VLAN_CHALLENGED;
 		goto out;
@@ -1325,7 +1252,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	features &= ~NETIF_F_ONE_FOR_ALL;
 	features |= NETIF_F_ALL_FOR_ALL;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		features = netdev_increment_features(features,
 						     slave->dev->features,
 						     mask);
@@ -1349,15 +1276,14 @@ static void bond_compute_features(struct bonding *bond)
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int gso_max_size = GSO_MAX_SIZE;
 	u16 gso_max_segs = GSO_MAX_SEGS;
-	int i;
 	unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
 
 	read_lock(&bond->lock);
 
-	if (!bond->first_slave)
+	if (list_empty(&bond->slave_list))
 		goto done;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		vlan_features = netdev_increment_features(vlan_features,
 			slave->dev->vlan_features, BOND_VLAN_FEATURES);
 
@@ -1545,7 +1471,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	 * bond ether type mutual exclusion - don't allow slaves of dissimilar
 	 * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
 	 */
-	if (bond->slave_cnt == 0) {
+	if (list_empty(&bond->slave_list)) {
 		if (bond_dev->type != slave_dev->type) {
 			pr_debug("%s: change device type from %d to %d\n",
 				 bond_dev->name,
@@ -1584,7 +1510,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	}
 
 	if (slave_ops->ndo_set_mac_address == NULL) {
-		if (bond->slave_cnt == 0) {
+		if (list_empty(&bond->slave_list)) {
 			pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.",
 				   bond_dev->name);
 			bond->params.fail_over_mac = BOND_FOM_ACTIVE;
@@ -1600,7 +1526,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	/* If this is the first slave, then we need to set the master's hardware
 	 * address to be the same as the slave's. */
-	if (!bond->slave_cnt && bond->dev->addr_assign_type == NET_ADDR_RANDOM)
+	if (list_empty(&bond->slave_list) &&
+	    bond->dev->addr_assign_type == NET_ADDR_RANDOM)
 		bond_set_dev_addr(bond->dev, slave_dev);
 
 	new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
@@ -1608,7 +1535,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		res = -ENOMEM;
 		goto err_undo_flags;
 	}
-
+	INIT_LIST_HEAD(&new_slave->list);
 	/*
 	 * Set the new_slave's queue_id to be zero.  Queue ID mapping
 	 * is set via sysfs or module option if desired.
@@ -1794,15 +1721,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		 */
 		bond_set_slave_inactive_flags(new_slave);
 		/* if this is the first slave */
-		if (bond->slave_cnt == 1) {
+		if (bond_first_slave(bond) == new_slave) {
 			SLAVE_AD_INFO(new_slave).id = 1;
 			/* Initialize AD with the number of times that the AD timer is called in 1 second
 			 * can be called only after the mac address of the bond is set
 			 */
 			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
 		} else {
+			struct slave *prev_slave;
+
+			prev_slave = bond_prev_slave(bond, new_slave);
 			SLAVE_AD_INFO(new_slave).id =
-				SLAVE_AD_INFO(new_slave->prev).id + 1;
+				SLAVE_AD_INFO(prev_slave).id + 1;
 		}
 
 		bond_3ad_bind_slave(new_slave);
@@ -1824,7 +1754,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		 * so we can change it without calling change_active_interface()
 		 */
 		if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
-			bond->curr_active_slave = new_slave;
+			rcu_assign_pointer(bond->curr_active_slave, new_slave);
 
 		break;
 	} /* switch(bond_mode) */
@@ -1834,7 +1764,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	bond_set_carrier(bond);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	slave_dev->npinfo = bond_netpoll_info(bond);
+	slave_dev->npinfo = bond->dev->npinfo;
 	if (slave_dev->npinfo) {
 		if (slave_enable_netpoll(new_slave)) {
 			read_unlock(&bond->lock);
@@ -1921,7 +1851,7 @@ err_free:
 err_undo_flags:
 	bond_compute_features(bond);
 	/* Enslave of first slave has failed and we need to fix master's mac */
-	if (bond->slave_cnt == 0 &&
+	if (list_empty(&bond->slave_list) &&
 	    ether_addr_equal(bond_dev->dev_addr, slave_dev->dev_addr))
 		eth_hw_addr_random(bond_dev);
 
@@ -1977,15 +1907,6 @@ static int __bond_release_one(struct net_device *bond_dev,
 	netdev_rx_handler_unregister(slave_dev);
 	write_lock_bh(&bond->lock);
 
-	if (!all && !bond->params.fail_over_mac) {
-		if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
-		    bond->slave_cnt > 1)
-			pr_warning("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
-				   bond_dev->name, slave_dev->name,
-				   slave->perm_hwaddr,
-				   bond_dev->name, slave_dev->name);
-	}
-
 	/* Inform AD package of unbinding of slave. */
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* must be called before the slave is
@@ -2006,6 +1927,15 @@ static int __bond_release_one(struct net_device *bond_dev,
 	/* release the slave from its bond */
 	bond_detach_slave(bond, slave);
 
+	if (!all && !bond->params.fail_over_mac) {
+		if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
+		    !list_empty(&bond->slave_list))
+			pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
+				   bond_dev->name, slave_dev->name,
+				   slave->perm_hwaddr,
+				   bond_dev->name, slave_dev->name);
+	}
+
 	if (bond->primary_slave == slave)
 		bond->primary_slave = NULL;
 
@@ -2024,7 +1954,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	}
 
 	if (all) {
-		bond->curr_active_slave = NULL;
+		rcu_assign_pointer(bond->curr_active_slave, NULL);
 	} else if (oldcurrent == slave) {
 		/*
 		 * Note that we hold RTNL over this sequence, so there
@@ -2042,7 +1972,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 		write_lock_bh(&bond->lock);
 	}
 
-	if (bond->slave_cnt == 0) {
+	if (list_empty(&bond->slave_list)) {
 		bond_set_carrier(bond);
 		eth_hw_addr_random(bond_dev);
 
@@ -2056,8 +1986,9 @@ static int __bond_release_one(struct net_device *bond_dev,
 
 	write_unlock_bh(&bond->lock);
 	unblock_netpoll_tx();
+	synchronize_rcu();
 
-	if (bond->slave_cnt == 0) {
+	if (list_empty(&bond->slave_list)) {
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
 		call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
 	}
@@ -2128,7 +2059,7 @@ static int  bond_release_and_destroy(struct net_device *bond_dev,
 	int ret;
 
 	ret = bond_release(bond_dev, slave_dev);
-	if ((ret == 0) && (bond->slave_cnt == 0)) {
+	if (ret == 0 && list_empty(&bond->slave_list)) {
 		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
 		pr_info("%s: destroying bond %s.\n",
 			bond_dev->name, bond_dev->name);
@@ -2165,23 +2096,19 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
 
 	read_lock(&bond->lock);
 
-	read_lock(&bond->curr_slave_lock);
 	old_active = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
 	new_active = bond_get_slave_by_dev(bond, slave_dev);
-
 	/*
 	 * Changing to the current active: do nothing; return success.
 	 */
-	if (new_active && (new_active == old_active)) {
+	if (new_active && new_active == old_active) {
 		read_unlock(&bond->lock);
 		return 0;
 	}
 
-	if ((new_active) &&
-	    (old_active) &&
-	    (new_active->link == BOND_LINK_UP) &&
+	if (new_active &&
+	    old_active &&
+	    new_active->link == BOND_LINK_UP &&
 	    IS_UP(new_active->dev)) {
 		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
@@ -2213,13 +2140,12 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
 static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *info)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	int i = 0, res = -ENODEV;
 	struct slave *slave;
-	int i, res = -ENODEV;
 
 	read_lock(&bond->lock);
-
-	bond_for_each_slave(bond, slave, i) {
-		if (i == (int)info->slave_id) {
+	bond_for_each_slave(bond, slave) {
+		if (i++ == (int)info->slave_id) {
 			res = 0;
 			strcpy(info->slave_name, slave->dev->name);
 			info->link = slave->link;
@@ -2228,7 +2154,6 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 			break;
 		}
 	}
-
 	read_unlock(&bond->lock);
 
 	return res;
@@ -2239,13 +2164,13 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 
 static int bond_miimon_inspect(struct bonding *bond)
 {
+	int link_state, commit = 0;
 	struct slave *slave;
-	int i, link_state, commit = 0;
 	bool ignore_updelay;
 
 	ignore_updelay = !bond->curr_active_slave ? true : false;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		slave->new_link = BOND_LINK_NOCHANGE;
 
 		link_state = bond_check_dev_link(bond, slave->dev, 0);
@@ -2340,9 +2265,8 @@ static int bond_miimon_inspect(struct bonding *bond)
 static void bond_miimon_commit(struct bonding *bond)
 {
 	struct slave *slave;
-	int i;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		switch (slave->new_link) {
 		case BOND_LINK_NOCHANGE:
 			continue;
@@ -2447,7 +2371,7 @@ void bond_mii_monitor(struct work_struct *work)
 
 	delay = msecs_to_jiffies(bond->params.miimon);
 
-	if (bond->slave_cnt == 0)
+	if (list_empty(&bond->slave_list))
 		goto re_arm;
 
 	should_notify_peers = bond_should_notify_peers(bond);
@@ -2713,6 +2637,20 @@ out_unlock:
 	return RX_HANDLER_ANOTHER;
 }
 
+/* function to verify if we're in the arp_interval timeslice, returns true if
+ * (last_act - arp_interval) <= jiffies <= (last_act + mod * arp_interval +
+ * arp_interval/2) . the arp_interval/2 is needed for really fast networks.
+ */
+static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act,
+				  int mod)
+{
+	int delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
+
+	return time_in_range(jiffies,
+			     last_act - delta_in_ticks,
+			     last_act + mod * delta_in_ticks + delta_in_ticks/2);
+}
+
 /*
  * this function is called regularly to monitor each slave's link
  * ensuring that traffic is being sent and received when arp monitoring
@@ -2726,21 +2664,13 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 					    arp_work.work);
 	struct slave *slave, *oldcurrent;
 	int do_failover = 0;
-	int delta_in_ticks, extra_ticks;
-	int i;
 
 	read_lock(&bond->lock);
 
-	delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
-	extra_ticks = delta_in_ticks / 2;
-
-	if (bond->slave_cnt == 0)
+	if (list_empty(&bond->slave_list))
 		goto re_arm;
 
-	read_lock(&bond->curr_slave_lock);
 	oldcurrent = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
 	/* see if any of the previous devices are up now (i.e. they have
 	 * xmt and rcv traffic). the curr_active_slave does not come into
 	 * the picture unless it is null. also, slave->jiffies is not needed
@@ -2749,16 +2679,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 	 * TODO: what about up/down delay in arp mode? it wasn't here before
 	 *       so it can wait
 	 */
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		unsigned long trans_start = dev_trans_start(slave->dev);
 
 		if (slave->link != BOND_LINK_UP) {
-			if (time_in_range(jiffies,
-				trans_start - delta_in_ticks,
-				trans_start + delta_in_ticks + extra_ticks) &&
-			    time_in_range(jiffies,
-				slave->dev->last_rx - delta_in_ticks,
-				slave->dev->last_rx + delta_in_ticks + extra_ticks)) {
+			if (bond_time_in_interval(bond, trans_start, 1) &&
+			    bond_time_in_interval(bond, slave->dev->last_rx, 1)) {
 
 				slave->link  = BOND_LINK_UP;
 				bond_set_active_slave(slave);
@@ -2786,12 +2712,8 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 			 * when the source ip is 0, so don't take the link down
 			 * if we don't know our ip yet
 			 */
-			if (!time_in_range(jiffies,
-				trans_start - delta_in_ticks,
-				trans_start + 2 * delta_in_ticks + extra_ticks) ||
-			    !time_in_range(jiffies,
-				slave->dev->last_rx - delta_in_ticks,
-				slave->dev->last_rx + 2 * delta_in_ticks + extra_ticks)) {
+			if (!bond_time_in_interval(bond, trans_start, 2) ||
+			    !bond_time_in_interval(bond, slave->dev->last_rx, 2)) {
 
 				slave->link  = BOND_LINK_DOWN;
 				bond_set_backup_slave(slave);
@@ -2831,7 +2753,8 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 
 re_arm:
 	if (bond->params.arp_interval)
-		queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
+		queue_delayed_work(bond->wq, &bond->arp_work,
+				   msecs_to_jiffies(bond->params.arp_interval));
 
 	read_unlock(&bond->lock);
 }
@@ -2844,32 +2767,21 @@ re_arm:
  *
  * Called with bond->lock held for read.
  */
-static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
+static int bond_ab_arp_inspect(struct bonding *bond)
 {
+	unsigned long trans_start, last_rx;
 	struct slave *slave;
-	int i, commit = 0;
-	unsigned long trans_start;
-	int extra_ticks;
-
-	/* All the time comparisons below need some extra time. Otherwise, on
-	 * fast networks the ARP probe/reply may arrive within the same jiffy
-	 * as it was sent.  Then, the next time the ARP monitor is run, one
-	 * arp_interval will already have passed in the comparisons.
-	 */
-	extra_ticks = delta_in_ticks / 2;
+	int commit = 0;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		slave->new_link = BOND_LINK_NOCHANGE;
+		last_rx = slave_last_rx(bond, slave);
 
 		if (slave->link != BOND_LINK_UP) {
-			if (time_in_range(jiffies,
-				slave_last_rx(bond, slave) - delta_in_ticks,
-				slave_last_rx(bond, slave) + delta_in_ticks + extra_ticks)) {
-
+			if (bond_time_in_interval(bond, last_rx, 1)) {
 				slave->new_link = BOND_LINK_UP;
 				commit++;
 			}
-
 			continue;
 		}
 
@@ -2878,9 +2790,7 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
 		 * active.  This avoids bouncing, as the last receive
 		 * times need a full ARP monitor cycle to be updated.
 		 */
-		if (time_in_range(jiffies,
-				  slave->jiffies - delta_in_ticks,
-				  slave->jiffies + 2 * delta_in_ticks + extra_ticks))
+		if (bond_time_in_interval(bond, slave->jiffies, 2))
 			continue;
 
 		/*
@@ -2898,10 +2808,7 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
 		 */
 		if (!bond_is_active_slave(slave) &&
 		    !bond->current_arp_slave &&
-		    !time_in_range(jiffies,
-			slave_last_rx(bond, slave) - delta_in_ticks,
-			slave_last_rx(bond, slave) + 3 * delta_in_ticks + extra_ticks)) {
-
+		    !bond_time_in_interval(bond, last_rx, 3)) {
 			slave->new_link = BOND_LINK_DOWN;
 			commit++;
 		}
@@ -2914,13 +2821,8 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
 		 */
 		trans_start = dev_trans_start(slave->dev);
 		if (bond_is_active_slave(slave) &&
-		    (!time_in_range(jiffies,
-			trans_start - delta_in_ticks,
-			trans_start + 2 * delta_in_ticks + extra_ticks) ||
-		     !time_in_range(jiffies,
-			slave_last_rx(bond, slave) - delta_in_ticks,
-			slave_last_rx(bond, slave) + 2 * delta_in_ticks + extra_ticks))) {
-
+		    (!bond_time_in_interval(bond, trans_start, 2) ||
+		     !bond_time_in_interval(bond, last_rx, 2))) {
 			slave->new_link = BOND_LINK_DOWN;
 			commit++;
 		}
@@ -2935,24 +2837,21 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
  *
  * Called with RTNL and bond->lock for read.
  */
-static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
+static void bond_ab_arp_commit(struct bonding *bond)
 {
-	struct slave *slave;
-	int i;
 	unsigned long trans_start;
+	struct slave *slave;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		switch (slave->new_link) {
 		case BOND_LINK_NOCHANGE:
 			continue;
 
 		case BOND_LINK_UP:
 			trans_start = dev_trans_start(slave->dev);
-			if ((!bond->curr_active_slave &&
-			     time_in_range(jiffies,
-					   trans_start - delta_in_ticks,
-					   trans_start + delta_in_ticks + delta_in_ticks / 2)) ||
-			    bond->curr_active_slave != slave) {
+			if (bond->curr_active_slave != slave ||
+			    (!bond->curr_active_slave &&
+			     bond_time_in_interval(bond, trans_start, 1))) {
 				slave->link = BOND_LINK_UP;
 				if (bond->current_arp_slave) {
 					bond_set_slave_inactive_flags(
@@ -3014,7 +2913,7 @@ do_failover:
  */
 static void bond_ab_arp_probe(struct bonding *bond)
 {
-	struct slave *slave;
+	struct slave *slave, *next_slave;
 	int i;
 
 	read_lock(&bond->curr_slave_lock);
@@ -3038,7 +2937,7 @@ static void bond_ab_arp_probe(struct bonding *bond)
 	 */
 
 	if (!bond->current_arp_slave) {
-		bond->current_arp_slave = bond->first_slave;
+		bond->current_arp_slave = bond_first_slave(bond);
 		if (!bond->current_arp_slave)
 			return;
 	}
@@ -3046,7 +2945,8 @@ static void bond_ab_arp_probe(struct bonding *bond)
 	bond_set_slave_inactive_flags(bond->current_arp_slave);
 
 	/* search for next candidate */
-	bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave->next) {
+	next_slave = bond_next_slave(bond, bond->current_arp_slave);
+	bond_for_each_slave_from(bond, slave, i, next_slave) {
 		if (IS_UP(slave->dev)) {
 			slave->link = BOND_LINK_BACK;
 			bond_set_slave_active_flags(slave);
@@ -3087,12 +2987,12 @@ void bond_activebackup_arp_mon(struct work_struct *work)
 
 	delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
 
-	if (bond->slave_cnt == 0)
+	if (list_empty(&bond->slave_list))
 		goto re_arm;
 
 	should_notify_peers = bond_should_notify_peers(bond);
 
-	if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
+	if (bond_ab_arp_inspect(bond)) {
 		read_unlock(&bond->lock);
 
 		/* Race avoidance with bond_close flush of workqueue */
@@ -3105,7 +3005,7 @@ void bond_activebackup_arp_mon(struct work_struct *work)
 
 		read_lock(&bond->lock);
 
-		bond_ab_arp_commit(bond, delta_in_ticks);
+		bond_ab_arp_commit(bond);
 
 		read_unlock(&bond->lock);
 		rtnl_unlock();
@@ -3234,6 +3134,10 @@ static int bond_slave_netdev_event(unsigned long event,
 	case NETDEV_FEAT_CHANGE:
 		bond_compute_features(bond);
 		break;
+	case NETDEV_RESEND_IGMP:
+		/* Propagate to master device */
+		call_netdevice_notifiers(event, slave->bond->dev);
+		break;
 	default:
 		break;
 	}
@@ -3403,13 +3307,12 @@ static int bond_open(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave;
-	int i;
 
 	/* reset slave->backup and slave->inactive */
 	read_lock(&bond->lock);
-	if (bond->slave_cnt > 0) {
+	if (!list_empty(&bond->slave_list)) {
 		read_lock(&bond->curr_slave_lock);
-		bond_for_each_slave(bond, slave, i) {
+		bond_for_each_slave(bond, slave) {
 			if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
 				&& (slave != bond->curr_active_slave)) {
 				bond_set_slave_inactive_flags(slave);
@@ -3477,13 +3380,11 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct rtnl_link_stats64 temp;
 	struct slave *slave;
-	int i;
 
 	memset(stats, 0, sizeof(*stats));
 
 	read_lock_bh(&bond->lock);
-
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		const struct rtnl_link_stats64 *sstats =
 			dev_get_stats(slave->dev, &temp);
 
@@ -3513,7 +3414,6 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
 		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
 		stats->tx_window_errors += sstats->tx_window_errors;
 	}
-
 	read_unlock_bh(&bond->lock);
 
 	return stats;
@@ -3652,41 +3552,35 @@ static void bond_set_rx_mode(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave;
-	int i;
 
-	read_lock(&bond->lock);
+	ASSERT_RTNL();
 
 	if (USES_PRIMARY(bond->params.mode)) {
-		read_lock(&bond->curr_slave_lock);
-		slave = bond->curr_active_slave;
+		slave = rtnl_dereference(bond->curr_active_slave);
 		if (slave) {
 			dev_uc_sync(slave->dev, bond_dev);
 			dev_mc_sync(slave->dev, bond_dev);
 		}
-		read_unlock(&bond->curr_slave_lock);
 	} else {
-		bond_for_each_slave(bond, slave, i) {
+		bond_for_each_slave(bond, slave) {
 			dev_uc_sync_multiple(slave->dev, bond_dev);
 			dev_mc_sync_multiple(slave->dev, bond_dev);
 		}
 	}
-
-	read_unlock(&bond->lock);
 }
 
 static int bond_neigh_init(struct neighbour *n)
 {
 	struct bonding *bond = netdev_priv(n->dev);
-	struct slave *slave = bond->first_slave;
 	const struct net_device_ops *slave_ops;
 	struct neigh_parms parms;
+	struct slave *slave;
 	int ret;
 
+	slave = bond_first_slave(bond);
 	if (!slave)
 		return 0;
-
 	slave_ops = slave->dev->netdev_ops;
-
 	if (!slave_ops->ndo_neigh_setup)
 		return 0;
 
@@ -3714,11 +3608,17 @@ static int bond_neigh_init(struct neighbour *n)
  * The bonding ndo_neigh_setup is called at init time beofre any
  * slave exists. So we must declare proxy setup function which will
  * be used at run time to resolve the actual slave neigh param setup.
+ *
+ * It's also called by master devices (such as vlans) to setup their
+ * underlying devices. In that case - do nothing, we're already set up from
+ * our init.
  */
 static int bond_neigh_setup(struct net_device *dev,
 			    struct neigh_parms *parms)
 {
-	parms->neigh_setup   = bond_neigh_init;
+	/* modify only our neigh_parms */
+	if (parms->dev == dev)
+		parms->neigh_setup = bond_neigh_init;
 
 	return 0;
 }
@@ -3729,9 +3629,8 @@ static int bond_neigh_setup(struct net_device *dev,
 static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave, *stop_at;
+	struct slave *slave;
 	int res = 0;
-	int i;
 
 	pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
 		 (bond_dev ? bond_dev->name : "None"), new_mtu);
@@ -3751,10 +3650,10 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 	 * call to the base driver.
 	 */
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		pr_debug("s %p s->p %p c_m %p\n",
 			 slave,
-			 slave->prev,
+			 bond_prev_slave(bond, slave),
 			 slave->dev->netdev_ops->ndo_change_mtu);
 
 		res = dev_set_mtu(slave->dev, new_mtu);
@@ -3779,8 +3678,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 
 unwind:
 	/* unwind from head to the slave that failed */
-	stop_at = slave;
-	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
+	bond_for_each_slave_continue_reverse(bond, slave) {
 		int tmp_res;
 
 		tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
@@ -3804,9 +3702,8 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct sockaddr *sa = addr, tmp_sa;
-	struct slave *slave, *stop_at;
+	struct slave *slave;
 	int res = 0;
-	int i;
 
 	if (bond->params.mode == BOND_MODE_ALB)
 		return bond_alb_set_mac_address(bond_dev, addr);
@@ -3839,7 +3736,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
 	 * call to the base driver.
 	 */
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		const struct net_device_ops *slave_ops = slave->dev->netdev_ops;
 		pr_debug("slave %p %s\n", slave, slave->dev->name);
 
@@ -3871,8 +3768,7 @@ unwind:
 	tmp_sa.sa_family = bond_dev->type;
 
 	/* unwind from head to the slave that failed */
-	stop_at = slave;
-	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
+	bond_for_each_slave_continue_reverse(bond, slave) {
 		int tmp_res;
 
 		tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
@@ -3885,12 +3781,50 @@ unwind:
 	return res;
 }
 
+/**
+ * bond_xmit_slave_id - transmit skb through slave with slave_id
+ * @bond: bonding device that is transmitting
+ * @skb: buffer to transmit
+ * @slave_id: slave id up to slave_cnt-1 through which to transmit
+ *
+ * This function tries to transmit through slave with slave_id but in case
+ * it fails, it tries to find the first available slave for transmission.
+ * The skb is consumed in all cases, thus the function is void.
+ */
+void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
+{
+	struct slave *slave;
+	int i = slave_id;
+
+	/* Here we start from the slave with slave_id */
+	bond_for_each_slave_rcu(bond, slave) {
+		if (--i < 0) {
+			if (slave_can_tx(slave)) {
+				bond_dev_queue_xmit(bond, skb, slave->dev);
+				return;
+			}
+		}
+	}
+
+	/* Here we start from the first slave up to slave_id */
+	i = slave_id;
+	bond_for_each_slave_rcu(bond, slave) {
+		if (--i < 0)
+			break;
+		if (slave_can_tx(slave)) {
+			bond_dev_queue_xmit(bond, skb, slave->dev);
+			return;
+		}
+	}
+	/* no slave that can tx has been found */
+	kfree_skb(skb);
+}
+
 static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave, *start_at;
-	int i, slave_no, res = 1;
 	struct iphdr *iph = ip_hdr(skb);
+	struct slave *slave;
 
 	/*
 	 * Start with the curr_active_slave that joined the bond as the
@@ -3899,50 +3833,20 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
 	 * send the join/membership reports.  The curr_active_slave found
 	 * will send all of this type of traffic.
 	 */
-	if ((iph->protocol == IPPROTO_IGMP) &&
-	    (skb->protocol == htons(ETH_P_IP))) {
-
-		read_lock(&bond->curr_slave_lock);
-		slave = bond->curr_active_slave;
-		read_unlock(&bond->curr_slave_lock);
-
-		if (!slave)
-			goto out;
+	if (iph->protocol == IPPROTO_IGMP && skb->protocol == htons(ETH_P_IP)) {
+		slave = rcu_dereference(bond->curr_active_slave);
+		if (slave && slave_can_tx(slave))
+			bond_dev_queue_xmit(bond, skb, slave->dev);
+		else
+			bond_xmit_slave_id(bond, skb, 0);
 	} else {
-		/*
-		 * Concurrent TX may collide on rr_tx_counter; we accept
-		 * that as being rare enough not to justify using an
-		 * atomic op here.
-		 */
-		slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
-
-		bond_for_each_slave(bond, slave, i) {
-			slave_no--;
-			if (slave_no < 0)
-				break;
-		}
-	}
-
-	start_at = slave;
-	bond_for_each_slave_from(bond, slave, i, start_at) {
-		if (IS_UP(slave->dev) &&
-		    (slave->link == BOND_LINK_UP) &&
-		    bond_is_active_slave(slave)) {
-			res = bond_dev_queue_xmit(bond, skb, slave->dev);
-			break;
-		}
-	}
-
-out:
-	if (res) {
-		/* no suitable interface, frame not sent */
-		kfree_skb(skb);
+		bond_xmit_slave_id(bond, skb,
+				   bond->rr_tx_counter++ % bond->slave_cnt);
 	}
 
 	return NETDEV_TX_OK;
 }
 
-
 /*
  * in active-backup mode, we know that bond->curr_active_slave is always valid if
  * the bond has a usable interface.
@@ -3950,18 +3854,12 @@ out:
 static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	int res = 1;
-
-	read_lock(&bond->curr_slave_lock);
-
-	if (bond->curr_active_slave)
-		res = bond_dev_queue_xmit(bond, skb,
-			bond->curr_active_slave->dev);
-
-	read_unlock(&bond->curr_slave_lock);
+	struct slave *slave;
 
-	if (res)
-		/* no suitable interface, frame not sent */
+	slave = rcu_dereference(bond->curr_active_slave);
+	if (slave)
+		bond_dev_queue_xmit(bond, skb, slave->dev);
+	else
 		kfree_skb(skb);
 
 	return NETDEV_TX_OK;
@@ -3975,87 +3873,39 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
 static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave, *start_at;
-	int slave_no;
-	int i;
-	int res = 1;
 
-	slave_no = bond->xmit_hash_policy(skb, bond->slave_cnt);
-
-	bond_for_each_slave(bond, slave, i) {
-		slave_no--;
-		if (slave_no < 0)
-			break;
-	}
-
-	start_at = slave;
-
-	bond_for_each_slave_from(bond, slave, i, start_at) {
-		if (IS_UP(slave->dev) &&
-		    (slave->link == BOND_LINK_UP) &&
-		    bond_is_active_slave(slave)) {
-			res = bond_dev_queue_xmit(bond, skb, slave->dev);
-			break;
-		}
-	}
-
-	if (res) {
-		/* no suitable interface, frame not sent */
-		kfree_skb(skb);
-	}
+	bond_xmit_slave_id(bond, skb,
+			   bond->xmit_hash_policy(skb, bond->slave_cnt));
 
 	return NETDEV_TX_OK;
 }
 
-/*
- * in broadcast mode, we send everything to all usable interfaces.
- */
+/* in broadcast mode, we send everything to all usable interfaces. */
 static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave, *start_at;
-	struct net_device *tx_dev = NULL;
-	int i;
-	int res = 1;
-
-	read_lock(&bond->curr_slave_lock);
-	start_at = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
-	if (!start_at)
-		goto out;
+	struct slave *slave = NULL;
 
-	bond_for_each_slave_from(bond, slave, i, start_at) {
-		if (IS_UP(slave->dev) &&
-		    (slave->link == BOND_LINK_UP) &&
-		    bond_is_active_slave(slave)) {
-			if (tx_dev) {
-				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-				if (!skb2) {
-					pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
-					       bond_dev->name);
-					continue;
-				}
+	bond_for_each_slave_rcu(bond, slave) {
+		if (bond_is_last_slave(bond, slave))
+			break;
+		if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP) {
+			struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 
-				res = bond_dev_queue_xmit(bond, skb2, tx_dev);
-				if (res) {
-					kfree_skb(skb2);
-					continue;
-				}
+			if (!skb2) {
+				pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
+				       bond_dev->name);
+				continue;
 			}
-			tx_dev = slave->dev;
+			/* bond_dev_queue_xmit always returns 0 */
+			bond_dev_queue_xmit(bond, skb2, slave->dev);
 		}
 	}
-
-	if (tx_dev)
-		res = bond_dev_queue_xmit(bond, skb, tx_dev);
-
-out:
-	if (res)
-		/* no suitable interface, frame not sent */
+	if (slave && IS_UP(slave->dev) && slave->link == BOND_LINK_UP)
+		bond_dev_queue_xmit(bond, skb, slave->dev);
+	else
 		kfree_skb(skb);
 
-	/* frame sent to all suitable interfaces */
 	return NETDEV_TX_OK;
 }
 
@@ -4083,15 +3933,15 @@ static void bond_set_xmit_hash_policy(struct bonding *bond)
 static inline int bond_slave_override(struct bonding *bond,
 				      struct sk_buff *skb)
 {
-	int i, res = 1;
 	struct slave *slave = NULL;
 	struct slave *check_slave;
+	int res = 1;
 
 	if (!skb->queue_mapping)
 		return 1;
 
 	/* Find out if any slaves have the same mapping as this skb. */
-	bond_for_each_slave(bond, check_slave, i) {
+	bond_for_each_slave_rcu(bond, check_slave) {
 		if (check_slave->queue_id == skb->queue_mapping) {
 			slave = check_slave;
 			break;
@@ -4176,14 +4026,12 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (is_netpoll_tx_blocked(dev))
 		return NETDEV_TX_BUSY;
 
-	read_lock(&bond->lock);
-
-	if (bond->slave_cnt)
+	rcu_read_lock();
+	if (!list_empty(&bond->slave_list))
 		ret = __bond_start_xmit(skb, dev);
 	else
 		kfree_skb(skb);
-
-	read_unlock(&bond->lock);
+	rcu_read_unlock();
 
 	return ret;
 }
@@ -4224,9 +4072,8 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
 				     struct ethtool_cmd *ecmd)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave;
-	int i;
 	unsigned long speed = 0;
+	struct slave *slave;
 
 	ecmd->duplex = DUPLEX_UNKNOWN;
 	ecmd->port = PORT_OTHER;
@@ -4237,7 +4084,7 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
 	 * this is an accurate maximum.
 	 */
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (SLAVE_IS_OK(slave)) {
 			if (slave->speed != SPEED_UNKNOWN)
 				speed += slave->speed;
@@ -4248,6 +4095,7 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
 	}
 	ethtool_cmd_speed_set(ecmd, speed ? : SPEED_UNKNOWN);
 	read_unlock(&bond->lock);
+
 	return 0;
 }
 
@@ -4311,7 +4159,7 @@ static void bond_setup(struct net_device *bond_dev)
 	/* initialize rwlocks */
 	rwlock_init(&bond->lock);
 	rwlock_init(&bond->curr_slave_lock);
-
+	INIT_LIST_HEAD(&bond->slave_list);
 	bond->params = bonding_defaults;
 
 	/* Initialize pointers */
@@ -4368,13 +4216,14 @@ static void bond_setup(struct net_device *bond_dev)
 static void bond_uninit(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct slave *slave, *tmp_slave;
 	struct vlan_entry *vlan, *tmp;
 
 	bond_netpoll_cleanup(bond_dev);
 
 	/* Release the bonded slaves */
-	while (bond->first_slave != NULL)
-		__bond_release_one(bond_dev, bond->first_slave->dev, true);
+	list_for_each_entry_safe(slave, tmp_slave, &bond->slave_list, list)
+		__bond_release_one(bond_dev, slave->dev, true);
 	pr_info("%s: released all slaves\n", bond_dev->name);
 
 	list_del(&bond->bond_list);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 4060d41..20a6ee2 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -12,7 +12,6 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 	struct bonding *bond = seq->private;
 	loff_t off = 0;
 	struct slave *slave;
-	int i;
 
 	/* make sure the bond won't be taken away */
 	rcu_read_lock();
@@ -21,10 +20,9 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave)
 		if (++off == *pos)
 			return slave;
-	}
 
 	return NULL;
 }
@@ -36,11 +34,13 @@ static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 	++*pos;
 	if (v == SEQ_START_TOKEN)
-		return bond->first_slave;
+		return bond_first_slave(bond);
 
-	slave = slave->next;
+	if (bond_is_last_slave(bond, slave))
+		return NULL;
+	slave = bond_next_slave(bond, slave);
 
-	return (slave == bond->first_slave) ? NULL : slave;
+	return slave;
 }
 
 static void bond_info_seq_stop(struct seq_file *seq, void *v)
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index dc36a3d..0f539de 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -209,12 +209,12 @@ void bond_destroy_slave_symlinks(struct net_device *master,
 static ssize_t bonding_show_slaves(struct device *d,
 				   struct device_attribute *attr, char *buf)
 {
-	struct slave *slave;
-	int i, res = 0;
 	struct bonding *bond = to_bond(d);
+	struct slave *slave;
+	int res = 0;
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (res > (PAGE_SIZE - IFNAMSIZ)) {
 			/* not enough space for another interface name */
 			if ((PAGE_SIZE - res) > 10)
@@ -227,6 +227,7 @@ static ssize_t bonding_show_slaves(struct device *d,
 	read_unlock(&bond->lock);
 	if (res)
 		buf[res-1] = '\n'; /* eat the leftover space */
+
 	return res;
 }
 
@@ -325,7 +326,7 @@ static ssize_t bonding_store_mode(struct device *d,
 		goto out;
 	}
 
-	if (bond->slave_cnt > 0) {
+	if (!list_empty(&bond->slave_list)) {
 		pr_err("unable to update mode of %s because it has slaves.\n",
 			bond->dev->name);
 		ret = -EPERM;
@@ -501,20 +502,25 @@ static ssize_t bonding_store_fail_over_mac(struct device *d,
 					   struct device_attribute *attr,
 					   const char *buf, size_t count)
 {
-	int new_value;
+	int new_value, ret = count;
 	struct bonding *bond = to_bond(d);
 
-	if (bond->slave_cnt != 0) {
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	if (!list_empty(&bond->slave_list)) {
 		pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
 		       bond->dev->name);
-		return -EPERM;
+		ret = -EPERM;
+		goto out;
 	}
 
 	new_value = bond_parse_parm(buf, fail_over_mac_tbl);
 	if (new_value < 0) {
 		pr_err("%s: Ignoring invalid fail_over_mac value %s.\n",
 		       bond->dev->name, buf);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	bond->params.fail_over_mac = new_value;
@@ -522,7 +528,9 @@ static ssize_t bonding_store_fail_over_mac(struct device *d,
 		bond->dev->name, fail_over_mac_tbl[new_value].modename,
 		new_value);
 
-	return count;
+out:
+	rtnl_unlock();
+	return ret;
 }
 
 static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR,
@@ -661,7 +669,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
 			 &newtarget);
 		/* not to race with bond_arp_rcv */
 		write_lock_bh(&bond->lock);
-		bond_for_each_slave(bond, slave, i)
+		bond_for_each_slave(bond, slave)
 			slave->target_last_arp_rx[ind] = jiffies;
 		targets[ind] = newtarget;
 		write_unlock_bh(&bond->lock);
@@ -687,7 +695,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
 			&newtarget);
 
 		write_lock_bh(&bond->lock);
-		bond_for_each_slave(bond, slave, i) {
+		bond_for_each_slave(bond, slave) {
 			targets_rx = slave->target_last_arp_rx;
 			j = ind;
 			for (; (j < BOND_MAX_ARP_TARGETS-1) && targets[j+1]; j++)
@@ -1078,10 +1086,9 @@ static ssize_t bonding_store_primary(struct device *d,
 				     struct device_attribute *attr,
 				     const char *buf, size_t count)
 {
-	int i;
-	struct slave *slave;
 	struct bonding *bond = to_bond(d);
 	char ifname[IFNAMSIZ];
+	struct slave *slave;
 
 	if (!rtnl_trylock())
 		return restart_syscall();
@@ -1107,7 +1114,7 @@ static ssize_t bonding_store_primary(struct device *d,
 		goto out;
 	}
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
 			pr_info("%s: Setting %s as primary slave.\n",
 				bond->dev->name, slave->dev->name);
@@ -1236,16 +1243,16 @@ static ssize_t bonding_show_active_slave(struct device *d,
 					 struct device_attribute *attr,
 					 char *buf)
 {
-	struct slave *curr;
 	struct bonding *bond = to_bond(d);
+	struct slave *curr;
 	int count = 0;
 
-	read_lock(&bond->curr_slave_lock);
-	curr = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
+	rcu_read_lock();
+	curr = rcu_dereference(bond->curr_active_slave);
 	if (USES_PRIMARY(bond->params.mode) && curr)
 		count = sprintf(buf, "%s\n", curr->dev->name);
+	rcu_read_unlock();
+
 	return count;
 }
 
@@ -1253,16 +1260,14 @@ static ssize_t bonding_store_active_slave(struct device *d,
 					  struct device_attribute *attr,
 					  const char *buf, size_t count)
 {
-	int i;
-	struct slave *slave;
-	struct slave *old_active = NULL;
-	struct slave *new_active = NULL;
+	struct slave *slave, *old_active, *new_active;
 	struct bonding *bond = to_bond(d);
 	char ifname[IFNAMSIZ];
 
 	if (!rtnl_trylock())
 		return restart_syscall();
 
+	old_active = new_active = NULL;
 	block_netpoll_tx();
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
@@ -1279,12 +1284,12 @@ static ssize_t bonding_store_active_slave(struct device *d,
 	if (!strlen(ifname) || buf[0] == '\n') {
 		pr_info("%s: Clearing current active slave.\n",
 			bond->dev->name);
-		bond->curr_active_slave = NULL;
+		rcu_assign_pointer(bond->curr_active_slave, NULL);
 		bond_select_active_slave(bond);
 		goto out;
 	}
 
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
 			old_active = bond->curr_active_slave;
 			new_active = slave;
@@ -1295,8 +1300,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
 					bond->dev->name,
 					slave->dev->name);
 				goto out;
-			}
-			else {
+			} else {
 				if ((new_active) &&
 				    (old_active) &&
 				    (new_active->link == BOND_LINK_UP) &&
@@ -1307,8 +1311,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
 						slave->dev->name);
 					bond_change_active_slave(bond,
 								 new_active);
-				}
-				else {
+				} else {
 					pr_info("%s: Could not set %s as"
 						" active slave; either %s is"
 						" down or the link is down.\n",
@@ -1344,14 +1347,9 @@ static ssize_t bonding_show_mii_status(struct device *d,
 				       struct device_attribute *attr,
 				       char *buf)
 {
-	struct slave *curr;
 	struct bonding *bond = to_bond(d);
 
-	read_lock(&bond->curr_slave_lock);
-	curr = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
-	return sprintf(buf, "%s\n", curr ? "up" : "down");
+	return sprintf(buf, "%s\n", bond->curr_active_slave ? "up" : "down");
 }
 static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
 
@@ -1470,15 +1468,15 @@ static ssize_t bonding_show_queue_id(struct device *d,
 				     struct device_attribute *attr,
 				     char *buf)
 {
-	struct slave *slave;
-	int i, res = 0;
 	struct bonding *bond = to_bond(d);
+	struct slave *slave;
+	int res = 0;
 
 	if (!rtnl_trylock())
 		return restart_syscall();
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
 			/* not enough space for another interface_name:queue_id pair */
 			if ((PAGE_SIZE - res) > 10)
@@ -1493,6 +1491,7 @@ static ssize_t bonding_show_queue_id(struct device *d,
 	if (res)
 		buf[res-1] = '\n'; /* eat the leftover space */
 	rtnl_unlock();
+
 	return res;
 }
 
@@ -1507,7 +1506,7 @@ static ssize_t bonding_store_queue_id(struct device *d,
 	struct slave *slave, *update_slave;
 	struct bonding *bond = to_bond(d);
 	u16 qid;
-	int i, ret = count;
+	int ret = count;
 	char *delim;
 	struct net_device *sdev = NULL;
 
@@ -1542,7 +1541,7 @@ static ssize_t bonding_store_queue_id(struct device *d,
 
 	/* Search for thes slave and check for duplicate qids */
 	update_slave = NULL;
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (sdev == slave->dev)
 			/*
 			 * We don't need to check the matching
@@ -1594,8 +1593,8 @@ static ssize_t bonding_store_slaves_active(struct device *d,
 					   struct device_attribute *attr,
 					   const char *buf, size_t count)
 {
-	int i, new_value, ret = count;
 	struct bonding *bond = to_bond(d);
+	int new_value, ret = count;
 	struct slave *slave;
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
@@ -1618,7 +1617,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
 	}
 
 	read_lock(&bond->lock);
-	bond_for_each_slave(bond, slave, i) {
+	bond_for_each_slave(bond, slave) {
 		if (!bond_is_active_slave(slave)) {
 			if (new_value)
 				slave->inactive = 0;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 42d1c65..4bf52d5 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -71,6 +71,28 @@
 	set_fs(fs);			\
 	res; })
 
+/* slave list primitives */
+#define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
+
+/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
+#define bond_first_slave(bond) \
+	list_first_entry_or_null(&(bond)->slave_list, struct slave, list)
+#define bond_last_slave(bond) \
+	(list_empty(&(bond)->slave_list) ? NULL : \
+					   bond_to_slave((bond)->slave_list.prev))
+
+#define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list)
+#define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list)
+
+/* Since bond_first/last_slave can return NULL, these can return NULL too */
+#define bond_next_slave(bond, pos) \
+	(bond_is_last_slave(bond, pos) ? bond_first_slave(bond) : \
+					 bond_to_slave((pos)->list.next))
+
+#define bond_prev_slave(bond, pos) \
+	(bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \
+					  bond_to_slave((pos)->list.prev))
+
 /**
  * bond_for_each_slave_from - iterate the slaves list from a starting point
  * @bond:	the bond holding this list.
@@ -80,37 +102,33 @@
  *
  * Caller must hold bond->lock
  */
-#define bond_for_each_slave_from(bond, pos, cnt, start)	\
-	for (cnt = 0, pos = start;				\
-	     cnt < (bond)->slave_cnt;				\
-             cnt++, pos = (pos)->next)
+#define bond_for_each_slave_from(bond, pos, cnt, start) \
+	for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \
+	     cnt++, pos = bond_next_slave(bond, pos))
 
 /**
- * bond_for_each_slave_from_to - iterate the slaves list from start point to stop point
- * @bond:	the bond holding this list.
- * @pos:	current slave.
- * @cnt:	counter for number max of moves
- * @start:	start point.
- * @stop:	stop point.
+ * bond_for_each_slave - iterate over all slaves
+ * @bond:	the bond holding this list
+ * @pos:	current slave
  *
  * Caller must hold bond->lock
  */
-#define bond_for_each_slave_from_to(bond, pos, cnt, start, stop)	\
-	for (cnt = 0, pos = start;					\
-	     ((cnt < (bond)->slave_cnt) && (pos != (stop)->next));	\
-             cnt++, pos = (pos)->next)
+#define bond_for_each_slave(bond, pos) \
+	list_for_each_entry(pos, &(bond)->slave_list, list)
+
+/* Caller must have rcu_read_lock */
+#define bond_for_each_slave_rcu(bond, pos) \
+	list_for_each_entry_rcu(pos, &(bond)->slave_list, list)
 
 /**
- * bond_for_each_slave - iterate the slaves list from head
- * @bond:	the bond holding this list.
- * @pos:	current slave.
- * @cnt:	counter for max number of moves
+ * bond_for_each_slave_reverse - iterate in reverse from a given position
+ * @bond:	the bond holding this list
+ * @pos:	slave to continue from
  *
  * Caller must hold bond->lock
  */
-#define bond_for_each_slave(bond, pos, cnt)	\
-		bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
-
+#define bond_for_each_slave_continue_reverse(bond, pos) \
+	list_for_each_entry_continue_reverse(pos, &(bond)->slave_list, list)
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 extern atomic_t netpoll_block_tx;
@@ -174,8 +192,7 @@ struct vlan_entry {
 
 struct slave {
 	struct net_device *dev; /* first - useful for panic debug */
-	struct slave *next;
-	struct slave *prev;
+	struct list_head list;
 	struct bonding *bond; /* our master */
 	int    delay;
 	unsigned long jiffies;
@@ -215,7 +232,7 @@ struct slave {
  */
 struct bonding {
 	struct   net_device *dev; /* first - useful for panic debug */
-	struct   slave *first_slave;
+	struct   list_head slave_list;
 	struct   slave *curr_active_slave;
 	struct   slave *current_arp_slave;
 	struct   slave *primary_slave;
@@ -270,13 +287,10 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
 						  struct net_device *slave_dev)
 {
 	struct slave *slave = NULL;
-	int i;
 
-	bond_for_each_slave(bond, slave, i) {
-		if (slave->dev == slave_dev) {
+	bond_for_each_slave(bond, slave)
+		if (slave->dev == slave_dev)
 			return slave;
-		}
-	}
 
 	return NULL;
 }
@@ -416,10 +430,20 @@ static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be3
 	return addr;
 }
 
+static inline bool slave_can_tx(struct slave *slave)
+{
+	if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP &&
+	    bond_is_active_slave(slave))
+		return true;
+	else
+		return false;
+}
+
 struct bond_net;
 
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id);
 int bond_create(struct net *net, const char *name);
 int bond_create_sysfs(struct bond_net *net);
 void bond_destroy_sysfs(struct bond_net *net);
@@ -477,10 +501,9 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)
 static inline struct slave *bond_slave_has_mac(struct bonding *bond,
 					       const u8 *mac)
 {
-	int i = 0;
 	struct slave *tmp;
 
-	bond_for_each_slave(bond, tmp, i)
+	bond_for_each_slave(bond, tmp)
 		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
 			return tmp;
 
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 7b0be09..c48174e 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -850,12 +850,17 @@ static int flexcan_open(struct net_device *dev)
 	struct flexcan_priv *priv = netdev_priv(dev);
 	int err;
 
-	clk_prepare_enable(priv->clk_ipg);
-	clk_prepare_enable(priv->clk_per);
+	err = clk_prepare_enable(priv->clk_ipg);
+	if (err)
+		return err;
+
+	err = clk_prepare_enable(priv->clk_per);
+	if (err)
+		goto out_disable_ipg;
 
 	err = open_candev(dev);
 	if (err)
-		goto out;
+		goto out_disable_per;
 
 	err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
 	if (err)
@@ -875,8 +880,9 @@ static int flexcan_open(struct net_device *dev)
 
  out_close:
 	close_candev(dev);
- out:
+ out_disable_per:
 	clk_disable_unprepare(priv->clk_per);
+ out_disable_ipg:
 	clk_disable_unprepare(priv->clk_ipg);
 
 	return err;
@@ -933,8 +939,13 @@ static int register_flexcandev(struct net_device *dev)
 	struct flexcan_regs __iomem *regs = priv->base;
 	u32 reg, err;
 
-	clk_prepare_enable(priv->clk_ipg);
-	clk_prepare_enable(priv->clk_per);
+	err = clk_prepare_enable(priv->clk_ipg);
+	if (err)
+		return err;
+
+	err = clk_prepare_enable(priv->clk_per);
+	if (err)
+		goto out_disable_ipg;
 
 	/* select "bus clock", chip must be disabled */
 	flexcan_chip_disable(priv);
@@ -959,15 +970,16 @@ static int register_flexcandev(struct net_device *dev)
 	if (!(reg & FLEXCAN_MCR_FEN)) {
 		netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");
 		err = -ENODEV;
-		goto out;
+		goto out_disable_per;
 	}
 
 	err = register_candev(dev);
 
- out:
+ out_disable_per:
 	/* disable core and turn off clocks */
 	flexcan_chip_disable(priv);
 	clk_disable_unprepare(priv->clk_per);
+ out_disable_ipg:
 	clk_disable_unprepare(priv->clk_ipg);
 
 	return err;
@@ -1001,7 +1013,6 @@ static int flexcan_probe(struct platform_device *pdev)
 	struct resource *mem;
 	struct clk *clk_ipg = NULL, *clk_per = NULL;
 	void __iomem *base;
-	resource_size_t mem_size;
 	int err, irq;
 	u32 clock_freq = 0;
 
@@ -1013,43 +1024,25 @@ static int flexcan_probe(struct platform_device *pdev)
 		clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 		if (IS_ERR(clk_ipg)) {
 			dev_err(&pdev->dev, "no ipg clock defined\n");
-			err = PTR_ERR(clk_ipg);
-			goto failed_clock;
+			return PTR_ERR(clk_ipg);
 		}
 		clock_freq = clk_get_rate(clk_ipg);
 
 		clk_per = devm_clk_get(&pdev->dev, "per");
 		if (IS_ERR(clk_per)) {
 			dev_err(&pdev->dev, "no per clock defined\n");
-			err = PTR_ERR(clk_per);
-			goto failed_clock;
+			return PTR_ERR(clk_per);
 		}
 	}
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (!mem || irq <= 0) {
-		err = -ENODEV;
-		goto failed_get;
-	}
+	if (irq <= 0)
+		return -ENODEV;
 
-	mem_size = resource_size(mem);
-	if (!request_mem_region(mem->start, mem_size, pdev->name)) {
-		err = -EBUSY;
-		goto failed_get;
-	}
-
-	base = ioremap(mem->start, mem_size);
-	if (!base) {
-		err = -ENOMEM;
-		goto failed_map;
-	}
-
-	dev = alloc_candev(sizeof(struct flexcan_priv), 1);
-	if (!dev) {
-		err = -ENOMEM;
-		goto failed_alloc;
-	}
+	base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	of_id = of_match_device(flexcan_of_match, &pdev->dev);
 	if (of_id) {
@@ -1058,10 +1051,13 @@ static int flexcan_probe(struct platform_device *pdev)
 		devtype_data = (struct flexcan_devtype_data *)
 			pdev->id_entry->driver_data;
 	} else {
-		err = -ENODEV;
-		goto failed_devtype;
+		return -ENODEV;
 	}
 
+	dev = alloc_candev(sizeof(struct flexcan_priv), 1);
+	if (!dev)
+		return -ENOMEM;
+
 	dev->netdev_ops = &flexcan_netdev_ops;
 	dev->irq = irq;
 	dev->flags |= IFF_ECHO;
@@ -1104,28 +1100,15 @@ static int flexcan_probe(struct platform_device *pdev)
 	return 0;
 
  failed_register:
- failed_devtype:
 	free_candev(dev);
- failed_alloc:
-	iounmap(base);
- failed_map:
-	release_mem_region(mem->start, mem_size);
- failed_get:
- failed_clock:
 	return err;
 }
 
 static int flexcan_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
-	struct flexcan_priv *priv = netdev_priv(dev);
-	struct resource *mem;
 
 	unregister_flexcandev(dev);
-	iounmap(priv->base);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
 
 	free_candev(dev);
 
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index e1d2643..b7232a9 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -707,7 +707,7 @@ static int ax_init_dev(struct net_device *dev)
 
 #ifdef CONFIG_AX88796_93CX6
 	if (ax->plat->flags & AXFLG_HAS_93CX6) {
-		unsigned char mac_addr[6];
+		unsigned char mac_addr[ETH_ALEN];
 		struct eeprom_93cx6 eeprom;
 
 		eeprom.data = ei_local;
@@ -719,7 +719,7 @@ static int ax_init_dev(struct net_device *dev)
 				       (__le16 __force *)mac_addr,
 				       sizeof(mac_addr) >> 1);
 
-		memcpy(dev->dev_addr, mac_addr, 6);
+		memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
 	}
 #endif
 	if (ax->plat->wordlength == 2) {
diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index e8d0ef5..10ceca5 100644
--- a/drivers/net/ethernet/amd/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -1147,7 +1147,7 @@ static struct net_device *atarilance_dev;
 static int __init atarilance_module_init(void)
 {
 	atarilance_dev = atarilance_probe(-1);
-	return PTR_RET(atarilance_dev);
+	return PTR_ERR_OR_ZERO(atarilance_dev);
 }
 
 static void __exit atarilance_module_exit(void)
diff --git a/drivers/net/ethernet/amd/mvme147.c b/drivers/net/ethernet/amd/mvme147.c
index a51497c..e108e91 100644
--- a/drivers/net/ethernet/amd/mvme147.c
+++ b/drivers/net/ethernet/amd/mvme147.c
@@ -188,7 +188,7 @@ static struct net_device *dev_mvme147_lance;
 int __init init_module(void)
 {
 	dev_mvme147_lance = mvme147lance_probe(-1);
-	return PTR_RET(dev_mvme147_lance);
+	return PTR_ERR_OR_ZERO(dev_mvme147_lance);
 }
 
 void __exit cleanup_module(void)
diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
index 26fc0ce..1cf33ad 100644
--- a/drivers/net/ethernet/amd/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -1238,7 +1238,7 @@ MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
 int __init init_module(void)
 {
  	dev_ni65 = ni65_probe(-1);
-	return PTR_RET(dev_ni65);
+	return PTR_ERR_OR_ZERO(dev_ni65);
 }
 
 void __exit cleanup_module(void)
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index ed21307..2d8e288 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -1521,7 +1521,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 	char *chipname;
 	struct net_device *dev;
 	const struct pcnet32_access *a = NULL;
-	u8 promaddr[6];
+	u8 promaddr[ETH_ALEN];
 	int ret = -ENODEV;
 
 	/* reset the chip */
@@ -1665,10 +1665,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 	}
 
 	/* read PROM address and compare with CSR address */
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < ETH_ALEN; i++)
 		promaddr[i] = inb(ioaddr + i);
 
-	if (memcmp(promaddr, dev->dev_addr, 6) ||
+	if (memcmp(promaddr, dev->dev_addr, ETH_ALEN) ||
 	    !is_valid_ether_addr(dev->dev_addr)) {
 		if (is_valid_ether_addr(promaddr)) {
 			if (pcnet32_debug & NETIF_MSG_PROBE) {
diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c
index 4375abe..d6b2029 100644
--- a/drivers/net/ethernet/amd/sun3lance.c
+++ b/drivers/net/ethernet/amd/sun3lance.c
@@ -940,7 +940,7 @@ static struct net_device *sun3lance_dev;
 int __init init_module(void)
 {
 	sun3lance_dev = sun3lance_probe(-1);
-	return PTR_RET(sun3lance_dev);
+	return PTR_ERR_OR_ZERO(sun3lance_dev);
 }
 
 void __exit cleanup_module(void)
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 52c9603..2fa5b86 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -130,7 +130,7 @@ config BNX2X_SRIOV
 
 config BGMAC
 	tristate "BCMA bus GBit core support"
-	depends on BCMA_HOST_SOC && HAS_DMA
+	depends on BCMA_HOST_SOC && HAS_DMA && BCM47XX
 	select PHYLIB
 	---help---
 	  This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 6a2de1d..6fdfc18 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -1,6 +1,6 @@
 /* bnx2.c: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004-2011 Broadcom Corporation
+ * Copyright (c) 2004-2013 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -58,8 +58,8 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.2.3"
-#define DRV_MODULE_RELDATE	"June 27, 2012"
+#define DRV_MODULE_VERSION	"2.2.4"
+#define DRV_MODULE_RELDATE	"Aug 05, 2013"
 #define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-6.2.3.fw"
 #define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-6.0.15.fw"
 #define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-6.2.1b.fw"
@@ -3908,136 +3908,121 @@ init_cpu_err:
 	return rc;
 }
 
-static int
-bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
+static void
+bnx2_setup_wol(struct bnx2 *bp)
 {
-	u16 pmcsr;
+	int i;
+	u32 val, wol_msg;
 
-	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
+	if (bp->wol) {
+		u32 advertising;
+		u8 autoneg;
 
-	switch (state) {
-	case PCI_D0: {
-		u32 val;
+		autoneg = bp->autoneg;
+		advertising = bp->advertising;
 
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-			(pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
-			PCI_PM_CTRL_PME_STATUS);
+		if (bp->phy_port == PORT_TP) {
+			bp->autoneg = AUTONEG_SPEED;
+			bp->advertising = ADVERTISED_10baseT_Half |
+				ADVERTISED_10baseT_Full |
+				ADVERTISED_100baseT_Half |
+				ADVERTISED_100baseT_Full |
+				ADVERTISED_Autoneg;
+		}
 
-		if (pmcsr & PCI_PM_CTRL_STATE_MASK)
-			/* delay required during transition out of D3hot */
-			msleep(20);
+		spin_lock_bh(&bp->phy_lock);
+		bnx2_setup_phy(bp, bp->phy_port);
+		spin_unlock_bh(&bp->phy_lock);
 
-		val = BNX2_RD(bp, BNX2_EMAC_MODE);
-		val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
-		val &= ~BNX2_EMAC_MODE_MPKT;
-		BNX2_WR(bp, BNX2_EMAC_MODE, val);
+		bp->autoneg = autoneg;
+		bp->advertising = advertising;
 
-		val = BNX2_RD(bp, BNX2_RPM_CONFIG);
-		val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
-		BNX2_WR(bp, BNX2_RPM_CONFIG, val);
-		break;
-	}
-	case PCI_D3hot: {
-		int i;
-		u32 val, wol_msg;
-
-		if (bp->wol) {
-			u32 advertising;
-			u8 autoneg;
-
-			autoneg = bp->autoneg;
-			advertising = bp->advertising;
-
-			if (bp->phy_port == PORT_TP) {
-				bp->autoneg = AUTONEG_SPEED;
-				bp->advertising = ADVERTISED_10baseT_Half |
-					ADVERTISED_10baseT_Full |
-					ADVERTISED_100baseT_Half |
-					ADVERTISED_100baseT_Full |
-					ADVERTISED_Autoneg;
-			}
+		bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
 
-			spin_lock_bh(&bp->phy_lock);
-			bnx2_setup_phy(bp, bp->phy_port);
-			spin_unlock_bh(&bp->phy_lock);
+		val = BNX2_RD(bp, BNX2_EMAC_MODE);
 
-			bp->autoneg = autoneg;
-			bp->advertising = advertising;
+		/* Enable port mode. */
+		val &= ~BNX2_EMAC_MODE_PORT;
+		val |= BNX2_EMAC_MODE_MPKT_RCVD |
+		       BNX2_EMAC_MODE_ACPI_RCVD |
+		       BNX2_EMAC_MODE_MPKT;
+		if (bp->phy_port == PORT_TP) {
+			val |= BNX2_EMAC_MODE_PORT_MII;
+		} else {
+			val |= BNX2_EMAC_MODE_PORT_GMII;
+			if (bp->line_speed == SPEED_2500)
+				val |= BNX2_EMAC_MODE_25G_MODE;
+		}
 
-			bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
+		BNX2_WR(bp, BNX2_EMAC_MODE, val);
 
-			val = BNX2_RD(bp, BNX2_EMAC_MODE);
+		/* receive all multicast */
+		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
+			BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+				0xffffffff);
+		}
+		BNX2_WR(bp, BNX2_EMAC_RX_MODE, BNX2_EMAC_RX_MODE_SORT_MODE);
 
-			/* Enable port mode. */
-			val &= ~BNX2_EMAC_MODE_PORT;
-			val |= BNX2_EMAC_MODE_MPKT_RCVD |
-			       BNX2_EMAC_MODE_ACPI_RCVD |
-			       BNX2_EMAC_MODE_MPKT;
-			if (bp->phy_port == PORT_TP)
-				val |= BNX2_EMAC_MODE_PORT_MII;
-			else {
-				val |= BNX2_EMAC_MODE_PORT_GMII;
-				if (bp->line_speed == SPEED_2500)
-					val |= BNX2_EMAC_MODE_25G_MODE;
-			}
+		val = 1 | BNX2_RPM_SORT_USER0_BC_EN | BNX2_RPM_SORT_USER0_MC_EN;
+		BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+		BNX2_WR(bp, BNX2_RPM_SORT_USER0, val);
+		BNX2_WR(bp, BNX2_RPM_SORT_USER0, val | BNX2_RPM_SORT_USER0_ENA);
 
-			BNX2_WR(bp, BNX2_EMAC_MODE, val);
+		/* Need to enable EMAC and RPM for WOL. */
+		BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+			BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
+			BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
+			BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
 
-			/* receive all multicast */
-			for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-				BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-					0xffffffff);
-			}
-			BNX2_WR(bp, BNX2_EMAC_RX_MODE,
-				BNX2_EMAC_RX_MODE_SORT_MODE);
+		val = BNX2_RD(bp, BNX2_RPM_CONFIG);
+		val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
+		BNX2_WR(bp, BNX2_RPM_CONFIG, val);
 
-			val = 1 | BNX2_RPM_SORT_USER0_BC_EN |
-			      BNX2_RPM_SORT_USER0_MC_EN;
-			BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
-			BNX2_WR(bp, BNX2_RPM_SORT_USER0, val);
-			BNX2_WR(bp, BNX2_RPM_SORT_USER0, val |
-				BNX2_RPM_SORT_USER0_ENA);
+		wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
+	} else {
+			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
+	}
 
-			/* Need to enable EMAC and RPM for WOL. */
-			BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
-				BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
-				BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
-				BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
+	if (!(bp->flags & BNX2_FLAG_NO_WOL))
+		bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 1, 0);
 
-			val = BNX2_RD(bp, BNX2_RPM_CONFIG);
-			val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
-			BNX2_WR(bp, BNX2_RPM_CONFIG, val);
+}
 
-			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
-		}
-		else {
-			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
-		}
+static int
+bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
+{
+	switch (state) {
+	case PCI_D0: {
+		u32 val;
+
+		pci_enable_wake(bp->pdev, PCI_D0, false);
+		pci_set_power_state(bp->pdev, PCI_D0);
 
-		if (!(bp->flags & BNX2_FLAG_NO_WOL))
-			bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg,
-				     1, 0);
+		val = BNX2_RD(bp, BNX2_EMAC_MODE);
+		val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
+		val &= ~BNX2_EMAC_MODE_MPKT;
+		BNX2_WR(bp, BNX2_EMAC_MODE, val);
 
-		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+		val = BNX2_RD(bp, BNX2_RPM_CONFIG);
+		val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
+		BNX2_WR(bp, BNX2_RPM_CONFIG, val);
+		break;
+	}
+	case PCI_D3hot: {
+		bnx2_setup_wol(bp);
+		pci_wake_from_d3(bp->pdev, bp->wol);
 		if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
 		    (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)) {
 
 			if (bp->wol)
-				pmcsr |= 3;
-		}
-		else {
-			pmcsr |= 3;
-		}
-		if (bp->wol) {
-			pmcsr |= PCI_PM_CTRL_PME_ENABLE;
+				pci_set_power_state(bp->pdev, PCI_D3hot);
+		} else {
+			pci_set_power_state(bp->pdev, PCI_D3hot);
 		}
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-				      pmcsr);
 
 		/* No more memory access after this point until
 		 * device is brought back to D0.
 		 */
-		udelay(50);
 		break;
 	}
 	default:
@@ -6317,7 +6302,6 @@ bnx2_open(struct net_device *dev)
 
 	netif_carrier_off(dev);
 
-	bnx2_set_power_state(bp, PCI_D0);
 	bnx2_disable_int(bp);
 
 	rc = bnx2_setup_int_mode(bp, disable_msi);
@@ -6724,7 +6708,6 @@ bnx2_close(struct net_device *dev)
 	bnx2_del_napi(bp);
 	bp->link_up = 0;
 	netif_carrier_off(bp->dev);
-	bnx2_set_power_state(bp, PCI_D3hot);
 	return 0;
 }
 
@@ -7081,6 +7064,9 @@ bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	else {
 		bp->wol = 0;
 	}
+
+	device_set_wakeup_enable(&bp->pdev->dev, bp->wol);
+
 	return 0;
 }
 
@@ -7156,9 +7142,6 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 	struct bnx2 *bp = netdev_priv(dev);
 	int rc;
 
-	if (!netif_running(dev))
-		return -EAGAIN;
-
 	/* parameters already validated in ethtool_get_eeprom */
 
 	rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
@@ -7173,9 +7156,6 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 	struct bnx2 *bp = netdev_priv(dev);
 	int rc;
 
-	if (!netif_running(dev))
-		return -EAGAIN;
-
 	/* parameters already validated in ethtool_set_eeprom */
 
 	rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
@@ -7535,8 +7515,6 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 
-	bnx2_set_power_state(bp, PCI_D0);
-
 	memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
 		int i;
@@ -7585,8 +7563,6 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
 		etest->flags |= ETH_TEST_FL_FAILED;
 
 	}
-	if (!netif_running(bp->dev))
-		bnx2_set_power_state(bp, PCI_D3hot);
 }
 
 static void
@@ -7658,8 +7634,6 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
 
 	switch (state) {
 	case ETHTOOL_ID_ACTIVE:
-		bnx2_set_power_state(bp, PCI_D0);
-
 		bp->leds_save = BNX2_RD(bp, BNX2_MISC_CFG);
 		BNX2_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
 		return 1;	/* cycle on/off once per second */
@@ -7680,9 +7654,6 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
 	case ETHTOOL_ID_INACTIVE:
 		BNX2_WR(bp, BNX2_EMAC_LED, 0);
 		BNX2_WR(bp, BNX2_MISC_CFG, bp->leds_save);
-
-		if (!netif_running(dev))
-			bnx2_set_power_state(bp, PCI_D3hot);
 		break;
 	}
 
@@ -8130,8 +8101,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 		goto err_out_release;
 	}
 
-	bnx2_set_power_state(bp, PCI_D0);
-
 	/* Configure byte swap and enable write to the reg_window registers.
 	 * Rely on CPU to do target byte swapping on big endian systems
 	 * The chip's target access swapping will not swap all accesses
@@ -8369,6 +8338,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 		bp->wol = 0;
 	}
 
+	if (bp->flags & BNX2_FLAG_NO_WOL)
+		device_set_wakeup_capable(&bp->pdev->dev, false);
+	else
+		device_set_wakeup_enable(&bp->pdev->dev, bp->wol);
+
 	if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
 		bp->tx_quick_cons_trip_int =
 			bp->tx_quick_cons_trip;
@@ -8609,46 +8583,52 @@ bnx2_remove_one(struct pci_dev *pdev)
 }
 
 static int
-bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
+bnx2_suspend(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2 *bp = netdev_priv(dev);
 
-	/* PCI register 4 needs to be saved whether netif_running() or not.
-	 * MSI address and data need to be saved if using MSI and
-	 * netif_running().
-	 */
-	pci_save_state(pdev);
-	if (!netif_running(dev))
-		return 0;
-
-	cancel_work_sync(&bp->reset_task);
-	bnx2_netif_stop(bp, true);
-	netif_device_detach(dev);
-	del_timer_sync(&bp->timer);
-	bnx2_shutdown_chip(bp);
-	bnx2_free_skbs(bp);
-	bnx2_set_power_state(bp, pci_choose_state(pdev, state));
+	if (netif_running(dev)) {
+		cancel_work_sync(&bp->reset_task);
+		bnx2_netif_stop(bp, true);
+		netif_device_detach(dev);
+		del_timer_sync(&bp->timer);
+		bnx2_shutdown_chip(bp);
+		__bnx2_free_irq(bp);
+		bnx2_free_skbs(bp);
+	}
+	bnx2_setup_wol(bp);
 	return 0;
 }
 
 static int
-bnx2_resume(struct pci_dev *pdev)
+bnx2_resume(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2 *bp = netdev_priv(dev);
 
-	pci_restore_state(pdev);
 	if (!netif_running(dev))
 		return 0;
 
 	bnx2_set_power_state(bp, PCI_D0);
 	netif_device_attach(dev);
+	bnx2_request_irq(bp);
 	bnx2_init_nic(bp, 1);
 	bnx2_netif_start(bp, true);
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static SIMPLE_DEV_PM_OPS(bnx2_pm_ops, bnx2_suspend, bnx2_resume);
+#define BNX2_PM_OPS (&bnx2_pm_ops)
+
+#else
+
+#define BNX2_PM_OPS NULL
+
+#endif /* CONFIG_PM_SLEEP */
 /**
  * bnx2_io_error_detected - called when PCI error is detected
  * @pdev: Pointer to PCI device
@@ -8694,24 +8674,28 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2 *bp = netdev_priv(dev);
-	pci_ers_result_t result;
-	int err;
+	pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
+	int err = 0;
 
 	rtnl_lock();
 	if (pci_enable_device(pdev)) {
 		dev_err(&pdev->dev,
 			"Cannot re-enable PCI device after reset\n");
-		result = PCI_ERS_RESULT_DISCONNECT;
 	} else {
 		pci_set_master(pdev);
 		pci_restore_state(pdev);
 		pci_save_state(pdev);
 
-		if (netif_running(dev)) {
-			bnx2_set_power_state(bp, PCI_D0);
-			bnx2_init_nic(bp, 1);
-		}
-		result = PCI_ERS_RESULT_RECOVERED;
+		if (netif_running(dev))
+			err = bnx2_init_nic(bp, 1);
+
+		if (!err)
+			result = PCI_ERS_RESULT_RECOVERED;
+	}
+
+	if (result != PCI_ERS_RESULT_RECOVERED && netif_running(dev)) {
+		bnx2_napi_enable(bp);
+		dev_close(dev);
 	}
 	rtnl_unlock();
 
@@ -8748,6 +8732,28 @@ static void bnx2_io_resume(struct pci_dev *pdev)
 	rtnl_unlock();
 }
 
+static void bnx2_shutdown(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct bnx2 *bp;
+
+	if (!dev)
+		return;
+
+	bp = netdev_priv(dev);
+	if (!bp)
+		return;
+
+	rtnl_lock();
+	if (netif_running(dev))
+		dev_close(bp->dev);
+
+	if (system_state == SYSTEM_POWER_OFF)
+		bnx2_set_power_state(bp, PCI_D3hot);
+
+	rtnl_unlock();
+}
+
 static const struct pci_error_handlers bnx2_err_handler = {
 	.error_detected	= bnx2_io_error_detected,
 	.slot_reset	= bnx2_io_slot_reset,
@@ -8759,9 +8765,9 @@ static struct pci_driver bnx2_pci_driver = {
 	.id_table	= bnx2_pci_tbl,
 	.probe		= bnx2_init_one,
 	.remove		= bnx2_remove_one,
-	.suspend	= bnx2_suspend,
-	.resume		= bnx2_resume,
+	.driver.pm	= BNX2_PM_OPS,
 	.err_handler	= &bnx2_err_handler,
+	.shutdown	= bnx2_shutdown,
 };
 
 module_pci_driver(bnx2_pci_driver);
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index 172efbe..18cb2d2 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -1,6 +1,6 @@
 /* bnx2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004-2011 Broadcom Corporation
+ * Copyright (c) 2004-2013 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index d80e34b..7ecb44a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1331,7 +1331,7 @@ enum {
 	BNX2X_SP_RTNL_ENABLE_SRIOV,
 	BNX2X_SP_RTNL_VFPF_MCAST,
 	BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
-	BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
+	BNX2X_SP_RTNL_RX_MODE,
 	BNX2X_SP_RTNL_HYPERVISOR_VLAN,
 };
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index f2d1ff1..2e90868 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2060,7 +2060,11 @@ void bnx2x_squeeze_objects(struct bnx2x *bp)
 	rparam.mcast_obj = &bp->mcast_obj;
 	__set_bit(RAMROD_DRV_CLR_ONLY, &rparam.ramrod_flags);
 
-	/* Add a DEL command... */
+	/* Add a DEL command... - Since we're doing a driver cleanup only,
+	 * we take a lock surrounding both the initial send and the CONTs,
+	 * as we don't want a true completion to disrupt us in the middle.
+	 */
+	netif_addr_lock_bh(bp->dev);
 	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
 	if (rc < 0)
 		BNX2X_ERR("Failed to add a new DEL command to a multi-cast object: %d\n",
@@ -2072,11 +2076,13 @@ void bnx2x_squeeze_objects(struct bnx2x *bp)
 		if (rc < 0) {
 			BNX2X_ERR("Failed to clean multi-cast object: %d\n",
 				  rc);
+			netif_addr_unlock_bh(bp->dev);
 			return;
 		}
 
 		rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
 	}
+	netif_addr_unlock_bh(bp->dev);
 }
 
 #ifndef BNX2X_STOP_ON_ERROR
@@ -2432,9 +2438,7 @@ int bnx2x_load_cnic(struct bnx2x *bp)
 	}
 
 	/* Initialize Rx filter. */
-	netif_addr_lock_bh(bp->dev);
-	bnx2x_set_rx_mode(bp->dev);
-	netif_addr_unlock_bh(bp->dev);
+	bnx2x_set_rx_mode_inner(bp);
 
 	/* re-read iscsi info */
 	bnx2x_get_iscsi_info(bp);
@@ -2704,9 +2708,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	/* Start fast path */
 
 	/* Initialize Rx filter. */
-	netif_addr_lock_bh(bp->dev);
-	bnx2x_set_rx_mode(bp->dev);
-	netif_addr_unlock_bh(bp->dev);
+	bnx2x_set_rx_mode_inner(bp);
 
 	/* Start the Tx */
 	switch (load_mode) {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index c07a6d0..38be494 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -418,6 +418,7 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
  * netif_addr_lock_bh()
  */
 void bnx2x_set_rx_mode(struct net_device *dev);
+void bnx2x_set_rx_mode_inner(struct bnx2x *bp);
 
 /**
  * bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e06186c..ab5bd6c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9628,11 +9628,9 @@ sp_rtnl_not_reset:
 		}
 	}
 
-	if (test_and_clear_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
-			       &bp->sp_rtnl_state)) {
-		DP(BNX2X_MSG_SP,
-		   "sending set storm rx mode vf pf channel message from rtnl sp-task\n");
-		bnx2x_vfpf_storm_rx_mode(bp);
+	if (test_and_clear_bit(BNX2X_SP_RTNL_RX_MODE, &bp->sp_rtnl_state)) {
+		DP(BNX2X_MSG_SP, "Handling Rx Mode setting\n");
+		bnx2x_set_rx_mode_inner(bp);
 	}
 
 	if (test_and_clear_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
@@ -11849,34 +11847,48 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
 void bnx2x_set_rx_mode(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	u32 rx_mode = BNX2X_RX_MODE_NORMAL;
 
 	if (bp->state != BNX2X_STATE_OPEN) {
 		DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
 		return;
+	} else {
+		/* Schedule an SP task to handle rest of change */
+		DP(NETIF_MSG_IFUP, "Scheduling an Rx mode change\n");
+		smp_mb__before_clear_bit();
+		set_bit(BNX2X_SP_RTNL_RX_MODE, &bp->sp_rtnl_state);
+		smp_mb__after_clear_bit();
+		schedule_delayed_work(&bp->sp_rtnl_task, 0);
 	}
+}
+
+void bnx2x_set_rx_mode_inner(struct bnx2x *bp)
+{
+	u32 rx_mode = BNX2X_RX_MODE_NORMAL;
 
 	DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags);
 
-	if (dev->flags & IFF_PROMISC)
+	netif_addr_lock_bh(bp->dev);
+
+	if (bp->dev->flags & IFF_PROMISC) {
 		rx_mode = BNX2X_RX_MODE_PROMISC;
-	else if ((dev->flags & IFF_ALLMULTI) ||
-		 ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
-		  CHIP_IS_E1(bp)))
+	} else if ((bp->dev->flags & IFF_ALLMULTI) ||
+		   ((netdev_mc_count(bp->dev) > BNX2X_MAX_MULTICAST) &&
+		    CHIP_IS_E1(bp))) {
 		rx_mode = BNX2X_RX_MODE_ALLMULTI;
-	else {
+	} else {
 		if (IS_PF(bp)) {
 			/* some multicasts */
 			if (bnx2x_set_mc_list(bp) < 0)
 				rx_mode = BNX2X_RX_MODE_ALLMULTI;
 
+			/* release bh lock, as bnx2x_set_uc_list might sleep */
+			netif_addr_unlock_bh(bp->dev);
 			if (bnx2x_set_uc_list(bp) < 0)
 				rx_mode = BNX2X_RX_MODE_PROMISC;
+			netif_addr_lock_bh(bp->dev);
 		} else {
 			/* configuring mcast to a vf involves sleeping (when we
-			 * wait for the pf's response). Since this function is
-			 * called from non sleepable context we must schedule
-			 * a work item for this purpose
+			 * wait for the pf's response).
 			 */
 			smp_mb__before_clear_bit();
 			set_bit(BNX2X_SP_RTNL_VFPF_MCAST,
@@ -11894,22 +11906,20 @@ void bnx2x_set_rx_mode(struct net_device *dev)
 	/* Schedule the rx_mode command */
 	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
 		set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+		netif_addr_unlock_bh(bp->dev);
 		return;
 	}
 
 	if (IS_PF(bp)) {
 		bnx2x_set_storm_rx_mode(bp);
+		netif_addr_unlock_bh(bp->dev);
 	} else {
-		/* configuring rx mode to storms in a vf involves sleeping (when
-		 * we wait for the pf's response). Since this function is
-		 * called from non sleepable context we must schedule
-		 * a work item for this purpose
+		/* VF will need to request the PF to make this change, and so
+		 * the VF needs to release the bottom-half lock prior to the
+		 * request (as it will likely require sleep on the VF side)
 		 */
-		smp_mb__before_clear_bit();
-		set_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
-			&bp->sp_rtnl_state);
-		smp_mb__after_clear_bit();
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
+		netif_addr_unlock_bh(bp->dev);
+		bnx2x_vfpf_storm_rx_mode(bp);
 	}
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 8f03c98..1d46b68 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -159,16 +159,6 @@ static inline void __bnx2x_exe_queue_reset_pending(
 	}
 }
 
-static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
-						 struct bnx2x_exe_queue_obj *o)
-{
-	spin_lock_bh(&o->lock);
-
-	__bnx2x_exe_queue_reset_pending(bp, o);
-
-	spin_unlock_bh(&o->lock);
-}
-
 /**
  * bnx2x_exe_queue_step - execute one execution chunk atomically
  *
@@ -176,7 +166,7 @@ static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
  * @o:			queue
  * @ramrod_flags:	flags
  *
- * (Atomicity is ensured using the exe_queue->lock).
+ * (Should be called while holding the exe_queue->lock).
  */
 static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 				       struct bnx2x_exe_queue_obj *o,
@@ -187,8 +177,6 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 
 	memset(&spacer, 0, sizeof(spacer));
 
-	spin_lock_bh(&o->lock);
-
 	/* Next step should not be performed until the current is finished,
 	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
 	 * properly clear object internals without sending any command to the FW
@@ -200,7 +188,6 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 			DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list\n");
 			__bnx2x_exe_queue_reset_pending(bp, o);
 		} else {
-			spin_unlock_bh(&o->lock);
 			return 1;
 		}
 	}
@@ -228,10 +215,8 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 	}
 
 	/* Sanity check */
-	if (!cur_len) {
-		spin_unlock_bh(&o->lock);
+	if (!cur_len)
 		return 0;
-	}
 
 	rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
 	if (rc < 0)
@@ -245,7 +230,6 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
 		 */
 		__bnx2x_exe_queue_reset_pending(bp, o);
 
-	spin_unlock_bh(&o->lock);
 	return rc;
 }
 
@@ -432,12 +416,219 @@ static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
 	return true;
 }
 
+/**
+ * __bnx2x_vlan_mac_h_write_trylock - try getting the vlan mac writer lock
+ *
+ * @bp:		device handle
+ * @o:		vlan_mac object
+ *
+ * @details: Non-blocking implementation; should be called under execution
+ *           queue lock.
+ */
+static int __bnx2x_vlan_mac_h_write_trylock(struct bnx2x *bp,
+					    struct bnx2x_vlan_mac_obj *o)
+{
+	if (o->head_reader) {
+		DP(BNX2X_MSG_SP, "vlan_mac_lock writer - There are readers; Busy\n");
+		return -EBUSY;
+	}
+
+	DP(BNX2X_MSG_SP, "vlan_mac_lock writer - Taken\n");
+	return 0;
+}
+
+/**
+ * __bnx2x_vlan_mac_h_exec_pending - execute step instead of a previous step
+ *
+ * @bp:		device handle
+ * @o:		vlan_mac object
+ *
+ * @details Should be called under execution queue lock; notice it might release
+ *          and reclaim it during its run.
+ */
+static void __bnx2x_vlan_mac_h_exec_pending(struct bnx2x *bp,
+					    struct bnx2x_vlan_mac_obj *o)
+{
+	int rc;
+	unsigned long ramrod_flags = o->saved_ramrod_flags;
+
+	DP(BNX2X_MSG_SP, "vlan_mac_lock execute pending command with ramrod flags %lu\n",
+	   ramrod_flags);
+	o->head_exe_request = false;
+	o->saved_ramrod_flags = 0;
+	rc = bnx2x_exe_queue_step(bp, &o->exe_queue, &ramrod_flags);
+	if (rc != 0) {
+		BNX2X_ERR("execution of pending commands failed with rc %d\n",
+			  rc);
+#ifdef BNX2X_STOP_ON_ERROR
+		bnx2x_panic();
+#endif
+	}
+}
+
+/**
+ * __bnx2x_vlan_mac_h_pend - Pend an execution step which couldn't run
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ * @ramrod_flags:	ramrod flags of missed execution
+ *
+ * @details Should be called under execution queue lock.
+ */
+static void __bnx2x_vlan_mac_h_pend(struct bnx2x *bp,
+				    struct bnx2x_vlan_mac_obj *o,
+				    unsigned long ramrod_flags)
+{
+	o->head_exe_request = true;
+	o->saved_ramrod_flags = ramrod_flags;
+	DP(BNX2X_MSG_SP, "Placing pending execution with ramrod flags %lu\n",
+	   ramrod_flags);
+}
+
+/**
+ * __bnx2x_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ *
+ * @details Should be called under execution queue lock. Notice if a pending
+ *          execution exists, it would perform it - possibly releasing and
+ *          reclaiming the execution queue lock.
+ */
+static void __bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
+					    struct bnx2x_vlan_mac_obj *o)
+{
+	/* It's possible a new pending execution was added since this writer
+	 * executed. If so, execute again. [Ad infinitum]
+	 */
+	while (o->head_exe_request) {
+		DP(BNX2X_MSG_SP, "vlan_mac_lock - writer release encountered a pending request\n");
+		__bnx2x_vlan_mac_h_exec_pending(bp, o);
+	}
+}
+
+/**
+ * bnx2x_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ *
+ * @details Notice if a pending execution exists, it would perform it -
+ *          possibly releasing and reclaiming the execution queue lock.
+ */
+void bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
+				   struct bnx2x_vlan_mac_obj *o)
+{
+	spin_lock_bh(&o->exe_queue.lock);
+	__bnx2x_vlan_mac_h_write_unlock(bp, o);
+	spin_unlock_bh(&o->exe_queue.lock);
+}
+
+/**
+ * __bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ *
+ * @details Should be called under the execution queue lock. May sleep. May
+ *          release and reclaim execution queue lock during its run.
+ */
+static int __bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
+					struct bnx2x_vlan_mac_obj *o)
+{
+	/* If we got here, we're holding lock --> no WRITER exists */
+	o->head_reader++;
+	DP(BNX2X_MSG_SP, "vlan_mac_lock - locked reader - number %d\n",
+	   o->head_reader);
+
+	return 0;
+}
+
+/**
+ * bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ *
+ * @details May sleep. Claims and releases execution queue lock during its run.
+ */
+int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
+			       struct bnx2x_vlan_mac_obj *o)
+{
+	int rc;
+
+	spin_lock_bh(&o->exe_queue.lock);
+	rc = __bnx2x_vlan_mac_h_read_lock(bp, o);
+	spin_unlock_bh(&o->exe_queue.lock);
+
+	return rc;
+}
+
+/**
+ * __bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ *
+ * @details Should be called under execution queue lock. Notice if a pending
+ *          execution exists, it would be performed if this was the last
+ *          reader. possibly releasing and reclaiming the execution queue lock.
+ */
+static void __bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
+					  struct bnx2x_vlan_mac_obj *o)
+{
+	if (!o->head_reader) {
+		BNX2X_ERR("Need to release vlan mac reader lock, but lock isn't taken\n");
+#ifdef BNX2X_STOP_ON_ERROR
+		bnx2x_panic();
+#endif
+	} else {
+		o->head_reader--;
+		DP(BNX2X_MSG_SP, "vlan_mac_lock - decreased readers to %d\n",
+		   o->head_reader);
+	}
+
+	/* It's possible a new pending execution was added, and that this reader
+	 * was last - if so we need to execute the command.
+	 */
+	if (!o->head_reader && o->head_exe_request) {
+		DP(BNX2X_MSG_SP, "vlan_mac_lock - reader release encountered a pending request\n");
+
+		/* Writer release will do the trick */
+		__bnx2x_vlan_mac_h_write_unlock(bp, o);
+	}
+}
+
+/**
+ * bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
+ *
+ * @bp:			device handle
+ * @o:			vlan_mac object
+ *
+ * @details Notice if a pending execution exists, it would be performed if this
+ *          was the last reader. Claims and releases the execution queue lock
+ *          during its run.
+ */
+void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
+				  struct bnx2x_vlan_mac_obj *o)
+{
+	spin_lock_bh(&o->exe_queue.lock);
+	__bnx2x_vlan_mac_h_read_unlock(bp, o);
+	spin_unlock_bh(&o->exe_queue.lock);
+}
+
 static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
 				int n, u8 *base, u8 stride, u8 size)
 {
 	struct bnx2x_vlan_mac_registry_elem *pos;
 	u8 *next = base;
 	int counter = 0;
+	int read_lock;
+
+	DP(BNX2X_MSG_SP, "get_n_elements - taking vlan_mac_lock (reader)\n");
+	read_lock = bnx2x_vlan_mac_h_read_lock(bp, o);
+	if (read_lock != 0)
+		BNX2X_ERR("get_n_elements failed to get vlan mac reader lock; Access without lock\n");
 
 	/* traverse list */
 	list_for_each_entry(pos, &o->head, link) {
@@ -449,6 +640,12 @@ static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
 			next += stride + size;
 		}
 	}
+
+	if (read_lock == 0) {
+		DP(BNX2X_MSG_SP, "get_n_elements - releasing vlan_mac_lock (reader)\n");
+		bnx2x_vlan_mac_h_read_unlock(bp, o);
+	}
+
 	return counter * ETH_ALEN;
 }
 
@@ -1397,6 +1594,32 @@ static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
 	return -EBUSY;
 }
 
+static int __bnx2x_vlan_mac_execute_step(struct bnx2x *bp,
+					 struct bnx2x_vlan_mac_obj *o,
+					 unsigned long *ramrod_flags)
+{
+	int rc = 0;
+
+	spin_lock_bh(&o->exe_queue.lock);
+
+	DP(BNX2X_MSG_SP, "vlan_mac_execute_step - trying to take writer lock\n");
+	rc = __bnx2x_vlan_mac_h_write_trylock(bp, o);
+
+	if (rc != 0) {
+		__bnx2x_vlan_mac_h_pend(bp, o, *ramrod_flags);
+
+		/* Calling function should not diffrentiate between this case
+		 * and the case in which there is already a pending ramrod
+		 */
+		rc = 1;
+	} else {
+		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+	}
+	spin_unlock_bh(&o->exe_queue.lock);
+
+	return rc;
+}
+
 /**
  * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
  *
@@ -1414,19 +1637,27 @@ static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
 	struct bnx2x_raw_obj *r = &o->raw;
 	int rc;
 
+	/* Clearing the pending list & raw state should be made
+	 * atomically (as execution flow assumes they represent the same).
+	 */
+	spin_lock_bh(&o->exe_queue.lock);
+
 	/* Reset pending list */
-	bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
+	__bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
 
 	/* Clear pending */
 	r->clear_pending(r);
 
+	spin_unlock_bh(&o->exe_queue.lock);
+
 	/* If ramrod failed this is most likely a SW bug */
 	if (cqe->message.error)
 		return -EINVAL;
 
 	/* Run the next bulk of pending commands if requested */
 	if (test_bit(RAMROD_CONT, ramrod_flags)) {
-		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+		rc = __bnx2x_vlan_mac_execute_step(bp, o, ramrod_flags);
+
 		if (rc < 0)
 			return rc;
 	}
@@ -1719,9 +1950,8 @@ static inline int bnx2x_vlan_mac_push_new_cmd(
  * @p:
  *
  */
-int bnx2x_config_vlan_mac(
-	struct bnx2x *bp,
-	struct bnx2x_vlan_mac_ramrod_params *p)
+int bnx2x_config_vlan_mac(struct bnx2x *bp,
+			   struct bnx2x_vlan_mac_ramrod_params *p)
 {
 	int rc = 0;
 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
@@ -1752,7 +1982,8 @@ int bnx2x_config_vlan_mac(
 	/* Execute commands if required */
 	if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
 	    test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
-		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+		rc = __bnx2x_vlan_mac_execute_step(bp, p->vlan_mac_obj,
+						   &p->ramrod_flags);
 		if (rc < 0)
 			return rc;
 	}
@@ -1775,8 +2006,9 @@ int bnx2x_config_vlan_mac(
 				return rc;
 
 			/* Make a next step */
-			rc = bnx2x_exe_queue_step(bp, &o->exe_queue,
-						  ramrod_flags);
+			rc = __bnx2x_vlan_mac_execute_step(bp,
+							   p->vlan_mac_obj,
+							   &p->ramrod_flags);
 			if (rc < 0)
 				return rc;
 		}
@@ -1806,10 +2038,11 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
 				  unsigned long *ramrod_flags)
 {
 	struct bnx2x_vlan_mac_registry_elem *pos = NULL;
-	int rc = 0;
 	struct bnx2x_vlan_mac_ramrod_params p;
 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
 	struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+	int read_lock;
+	int rc = 0;
 
 	/* Clear pending commands first */
 
@@ -1844,6 +2077,11 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
 	__clear_bit(RAMROD_EXEC, &p.ramrod_flags);
 	__clear_bit(RAMROD_CONT, &p.ramrod_flags);
 
+	DP(BNX2X_MSG_SP, "vlan_mac_del_all -- taking vlan_mac_lock (reader)\n");
+	read_lock = bnx2x_vlan_mac_h_read_lock(bp, o);
+	if (read_lock != 0)
+		return read_lock;
+
 	list_for_each_entry(pos, &o->head, link) {
 		if (pos->vlan_mac_flags == *vlan_mac_flags) {
 			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
@@ -1851,11 +2089,15 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
 			rc = bnx2x_config_vlan_mac(bp, &p);
 			if (rc < 0) {
 				BNX2X_ERR("Failed to add a new DEL command\n");
+				bnx2x_vlan_mac_h_read_unlock(bp, o);
 				return rc;
 			}
 		}
 	}
 
+	DP(BNX2X_MSG_SP, "vlan_mac_del_all -- releasing vlan_mac_lock (reader)\n");
+	bnx2x_vlan_mac_h_read_unlock(bp, o);
+
 	p.ramrod_flags = *ramrod_flags;
 	__set_bit(RAMROD_CONT, &p.ramrod_flags);
 
@@ -1887,6 +2129,9 @@ static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
 	struct bnx2x_credit_pool_obj *vlans_pool)
 {
 	INIT_LIST_HEAD(&o->head);
+	o->head_reader = 0;
+	o->head_exe_request = false;
+	o->saved_ramrod_flags = 0;
 
 	o->macs_pool = macs_pool;
 	o->vlans_pool = vlans_pool;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 798dfe9..533a3ab 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -285,6 +285,12 @@ struct bnx2x_vlan_mac_obj {
 	 * entries.
 	 */
 	struct list_head		head;
+	/* Implement a simple reader/writer lock on the head list.
+	 * all these fields should only be accessed under the exe_queue lock
+	 */
+	u8		head_reader; /* Num. of readers accessing head list */
+	bool		head_exe_request; /* Pending execution request. */
+	unsigned long	saved_ramrod_flags; /* Ramrods of pending execution */
 
 	/* TODO: Add it's initialization in the init functions */
 	struct bnx2x_exe_queue_obj	exe_queue;
@@ -1302,8 +1308,16 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
 			     struct bnx2x_credit_pool_obj *macs_pool,
 			     struct bnx2x_credit_pool_obj *vlans_pool);
 
+int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
+					struct bnx2x_vlan_mac_obj *o);
+void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
+				  struct bnx2x_vlan_mac_obj *o);
+int bnx2x_vlan_mac_h_write_lock(struct bnx2x *bp,
+				struct bnx2x_vlan_mac_obj *o);
+void bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
+					  struct bnx2x_vlan_mac_obj *o);
 int bnx2x_config_vlan_mac(struct bnx2x *bp,
-			  struct bnx2x_vlan_mac_ramrod_params *p);
+			   struct bnx2x_vlan_mac_ramrod_params *p);
 
 int bnx2x_vlan_mac_move(struct bnx2x *bp,
 			struct bnx2x_vlan_mac_ramrod_params *p,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 95861ef..6291324 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -491,12 +491,20 @@ static inline void bnx2x_vfop_credit(struct bnx2x *bp,
 	 * and a valid credit counter
 	 */
 	if (!vfop->rc && args->credit) {
-		int cnt = 0;
 		struct list_head *pos;
+		int read_lock;
+		int cnt = 0;
+
+		read_lock = bnx2x_vlan_mac_h_read_lock(bp, obj);
+		if (read_lock)
+			DP(BNX2X_MSG_SP, "Failed to take vlan mac read head; continuing anyway\n");
 
 		list_for_each(pos, &obj->head)
 			cnt++;
 
+		if (!read_lock)
+			bnx2x_vlan_mac_h_read_unlock(bp, obj);
+
 		atomic_set(args->credit, cnt);
 	}
 }
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index d78d4cf..4f8a535 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1,6 +1,6 @@
 /* cnic.c: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2012 Broadcom Corporation
+ * Copyright (c) 2006-2013 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -1427,6 +1427,28 @@ static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type,
 	rcu_read_unlock();
 }
 
+static void cnic_bnx2x_set_tcp_options(struct cnic_dev *dev, int time_stamps,
+				       int en_tcp_dack)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct bnx2x *bp = netdev_priv(dev->netdev);
+	u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN;
+	u16 tstorm_flags = 0;
+
+	if (time_stamps) {
+		xstorm_flags |= XSTORM_L5CM_TCP_FLAGS_TS_ENABLED;
+		tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_TS_ENABLED;
+	}
+	if (en_tcp_dack)
+		tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_DELAYED_ACK_EN;
+
+	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
+		 XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags);
+
+	CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
+		  TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags);
+}
+
 static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -1506,6 +1528,10 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
 	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
 		  hq_bds);
 
+	cnic_bnx2x_set_tcp_options(dev,
+			req1->flags & ISCSI_KWQE_INIT1_TIME_STAMPS_ENABLE,
+			req1->flags & ISCSI_KWQE_INIT1_DELAYED_ACK_ENABLE);
+
 	return 0;
 }
 
@@ -2035,9 +2061,6 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
 	xstorm_buf->pseudo_header_checksum =
 		swab16(~csum_ipv6_magic(&src_ip, &dst_ip, 0, IPPROTO_TCP, 0));
 
-	if (!(kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK))
-		tstorm_buf->params |=
-			L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE;
 	if (kwqe3->ka_timeout) {
 		tstorm_buf->ka_enable = 1;
 		tstorm_buf->ka_timeout = kwqe3->ka_timeout;
@@ -2084,25 +2107,6 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
 		 mac[0]);
 }
 
-static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct bnx2x *bp = netdev_priv(dev->netdev);
-	u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN;
-	u16 tstorm_flags = 0;
-
-	if (tcp_ts) {
-		xstorm_flags |= XSTORM_L5CM_TCP_FLAGS_TS_ENABLED;
-		tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_TS_ENABLED;
-	}
-
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags);
-
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
-		  TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags);
-}
-
 static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
 			      u32 num, int *work)
 {
@@ -2178,9 +2182,6 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
 	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
 		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->pfid), csk->vlan_id);
 
-	cnic_bnx2x_set_tcp_timestamp(dev,
-		kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_TIME_STAMP);
-
 	ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT,
 			kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data);
 	if (!ret)
@@ -3603,6 +3604,7 @@ static int cnic_cm_create(struct cnic_dev *dev, int ulp_type, u32 cid,
 	csk1->rcv_buf = DEF_RCV_BUF;
 	csk1->snd_buf = DEF_SND_BUF;
 	csk1->seed = DEF_SEED;
+	csk1->tcp_flags = 0;
 
 	*csk = csk1;
 	return 0;
@@ -4020,15 +4022,18 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
 		cnic_cm_upcall(cp, csk, opcode);
 		break;
 
-	case L5CM_RAMROD_CMD_ID_CLOSE:
-		if (l4kcqe->status != 0) {
-			netdev_warn(dev->netdev, "RAMROD CLOSE compl with "
-				    "status 0x%x\n", l4kcqe->status);
+	case L5CM_RAMROD_CMD_ID_CLOSE: {
+		struct iscsi_kcqe *l5kcqe = (struct iscsi_kcqe *) kcqe;
+
+		if (l4kcqe->status != 0 || l5kcqe->completion_status != 0) {
+			netdev_warn(dev->netdev, "RAMROD CLOSE compl with status 0x%x completion status 0x%x\n",
+				    l4kcqe->status, l5kcqe->completion_status);
 			opcode = L4_KCQE_OPCODE_VALUE_CLOSE_COMP;
 			/* Fall through */
 		} else {
 			break;
 		}
+	}
 	case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED:
 	case L4_KCQE_OPCODE_VALUE_CLOSE_COMP:
 	case L4_KCQE_OPCODE_VALUE_RESET_COMP:
@@ -4219,7 +4224,7 @@ static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
 	u32 port = CNIC_PORT(cp);
 
 	cnic_init_bnx2x_mac(dev);
-	cnic_bnx2x_set_tcp_timestamp(dev, 1);
+	cnic_bnx2x_set_tcp_options(dev, 0, 1);
 
 	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
 		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfid), 0);
@@ -5271,6 +5276,13 @@ static int cnic_register_netdev(struct cnic_dev *dev)
 	if (err)
 		netdev_err(dev->netdev, "register_cnic failed\n");
 
+	/* Read iSCSI config again.  On some bnx2x device, iSCSI config
+	 * can change after firmware is downloaded.
+	 */
+	dev->max_iscsi_conn = ethdev->max_iscsi_conn;
+	if (ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)
+		dev->max_iscsi_conn = 0;
+
 	return err;
 }
 
@@ -5628,7 +5640,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 
 	dev = cnic_from_netdev(netdev);
 
-	if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) {
+	if (!dev && event == NETDEV_REGISTER) {
 		/* Check for the hot-plug device */
 		dev = is_cnic_dev(netdev);
 		if (dev) {
@@ -5644,7 +5656,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 		else if (event == NETDEV_UNREGISTER)
 			cnic_ulp_exit(dev);
 
-		if (event == NETDEV_UP || (new_dev && netif_running(netdev))) {
+		if (event == NETDEV_UP) {
 			if (cnic_register_netdev(dev) != 0) {
 				cnic_put(dev);
 				goto done;
@@ -5693,21 +5705,8 @@ static struct notifier_block cnic_netdev_notifier = {
 
 static void cnic_release(void)
 {
-	struct cnic_dev *dev;
 	struct cnic_uio_dev *udev;
 
-	while (!list_empty(&cnic_dev_list)) {
-		dev = list_entry(cnic_dev_list.next, struct cnic_dev, list);
-		if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
-			cnic_ulp_stop(dev);
-			cnic_stop_hw(dev);
-		}
-
-		cnic_ulp_exit(dev);
-		cnic_unregister_netdev(dev);
-		list_del_init(&dev->list);
-		cnic_free_dev(dev);
-	}
 	while (!list_empty(&cnic_udev_list)) {
 		udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev,
 				  list);
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index 62c6706..e7a2474 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -1,6 +1,6 @@
 /* cnic.h: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2011 Broadcom Corporation
+ * Copyright (c) 2006-2013 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/cnic_defs.h b/drivers/net/ethernet/broadcom/cnic_defs.h
index ede3db3..95a8e4b 100644
--- a/drivers/net/ethernet/broadcom/cnic_defs.h
+++ b/drivers/net/ethernet/broadcom/cnic_defs.h
@@ -1,7 +1,7 @@
 
 /* cnic.c: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2012 Broadcom Corporation
+ * Copyright (c) 2006-2013 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -5400,8 +5400,8 @@ struct tstorm_l5cm_tcp_flags {
 	u16 flags;
 #define TSTORM_L5CM_TCP_FLAGS_VLAN_ID (0xFFF<<0)
 #define TSTORM_L5CM_TCP_FLAGS_VLAN_ID_SHIFT 0
-#define TSTORM_L5CM_TCP_FLAGS_RSRV0 (0x1<<12)
-#define TSTORM_L5CM_TCP_FLAGS_RSRV0_SHIFT 12
+#define TSTORM_L5CM_TCP_FLAGS_DELAYED_ACK_EN (0x1<<12)
+#define TSTORM_L5CM_TCP_FLAGS_DELAYED_ACK_SHIFT 12
 #define TSTORM_L5CM_TCP_FLAGS_TS_ENABLED (0x1<<13)
 #define TSTORM_L5CM_TCP_FLAGS_TS_ENABLED_SHIFT 13
 #define TSTORM_L5CM_TCP_FLAGS_RSRV1 (0x3<<14)
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index ec9bb9a..95aff76 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -1,6 +1,6 @@
 /* cnic_if.h: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2012 Broadcom Corporation
+ * Copyright (c) 2006-2013 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
 
 #include "bnx2x/bnx2x_mfw_req.h"
 
-#define CNIC_MODULE_VERSION	"2.5.16"
-#define CNIC_MODULE_RELDATE	"Dec 05, 2012"
+#define CNIC_MODULE_VERSION	"2.5.17"
+#define CNIC_MODULE_RELDATE	"July 28, 2013"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
@@ -238,8 +238,8 @@ struct cnic_sock {
 	u16	src_port;
 	u16	dst_port;
 	u16	vlan_id;
-	unsigned char old_ha[6];
-	unsigned char ha[6];
+	unsigned char old_ha[ETH_ALEN];
+	unsigned char ha[ETH_ALEN];
 	u32	mtu;
 	u32	cid;
 	u32	l5_cid;
@@ -308,7 +308,7 @@ struct cnic_dev {
 #define CNIC_F_BNX2_CLASS	3
 #define CNIC_F_BNX2X_CLASS	4
 	atomic_t	ref_count;
-	u8		mac_addr[6];
+	u8		mac_addr[ETH_ALEN];
 
 	int		max_iscsi_conn;
 	int		max_fcoe_conn;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ddebc7a..51bf9ca 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -94,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME		"tg3"
 #define TG3_MAJ_NUM			3
-#define TG3_MIN_NUM			132
+#define TG3_MIN_NUM			133
 #define DRV_MODULE_VERSION	\
 	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE	"May 21, 2013"
+#define DRV_MODULE_RELDATE	"Jul 29, 2013"
 
 #define RESET_KIND_SHUTDOWN	0
 #define RESET_KIND_INIT		1
@@ -4226,8 +4226,6 @@ static int tg3_power_down_prepare(struct tg3 *tp)
 
 static void tg3_power_down(struct tg3 *tp)
 {
-	tg3_power_down_prepare(tp);
-
 	pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE));
 	pci_set_power_state(tp->pdev, PCI_D3hot);
 }
@@ -6095,10 +6093,12 @@ static u64 tg3_refclk_read(struct tg3 *tp)
 /* tp->lock must be held */
 static void tg3_refclk_write(struct tg3 *tp, u64 newval)
 {
-	tw32(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_STOP);
+	u32 clock_ctl = tr32(TG3_EAV_REF_CLCK_CTL);
+
+	tw32(TG3_EAV_REF_CLCK_CTL, clock_ctl | TG3_EAV_REF_CLCK_CTL_STOP);
 	tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff);
 	tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32);
-	tw32_f(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_RESUME);
+	tw32_f(TG3_EAV_REF_CLCK_CTL, clock_ctl | TG3_EAV_REF_CLCK_CTL_RESUME);
 }
 
 static inline void tg3_full_lock(struct tg3 *tp, int irq_sync);
@@ -6214,6 +6214,59 @@ static int tg3_ptp_settime(struct ptp_clock_info *ptp,
 static int tg3_ptp_enable(struct ptp_clock_info *ptp,
 			  struct ptp_clock_request *rq, int on)
 {
+	struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+	u32 clock_ctl;
+	int rval = 0;
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_PEROUT:
+		if (rq->perout.index != 0)
+			return -EINVAL;
+
+		tg3_full_lock(tp, 0);
+		clock_ctl = tr32(TG3_EAV_REF_CLCK_CTL);
+		clock_ctl &= ~TG3_EAV_CTL_TSYNC_GPIO_MASK;
+
+		if (on) {
+			u64 nsec;
+
+			nsec = rq->perout.start.sec * 1000000000ULL +
+			       rq->perout.start.nsec;
+
+			if (rq->perout.period.sec || rq->perout.period.nsec) {
+				netdev_warn(tp->dev,
+					    "Device supports only a one-shot timesync output, period must be 0\n");
+				rval = -EINVAL;
+				goto err_out;
+			}
+
+			if (nsec & (1ULL << 63)) {
+				netdev_warn(tp->dev,
+					    "Start value (nsec) is over limit. Maximum size of start is only 63 bits\n");
+				rval = -EINVAL;
+				goto err_out;
+			}
+
+			tw32(TG3_EAV_WATCHDOG0_LSB, (nsec & 0xffffffff));
+			tw32(TG3_EAV_WATCHDOG0_MSB,
+			     TG3_EAV_WATCHDOG0_EN |
+			     ((nsec >> 32) & TG3_EAV_WATCHDOG_MSB_MASK));
+
+			tw32(TG3_EAV_REF_CLCK_CTL,
+			     clock_ctl | TG3_EAV_CTL_TSYNC_WDOG0);
+		} else {
+			tw32(TG3_EAV_WATCHDOG0_MSB, 0);
+			tw32(TG3_EAV_REF_CLCK_CTL, clock_ctl);
+		}
+
+err_out:
+		tg3_full_unlock(tp);
+		return rval;
+
+	default:
+		break;
+	}
+
 	return -EOPNOTSUPP;
 }
 
@@ -6223,7 +6276,7 @@ static const struct ptp_clock_info tg3_ptp_caps = {
 	.max_adj	= 250000000,
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
-	.n_per_out	= 0,
+	.n_per_out	= 1,
 	.pps		= 0,
 	.adjfreq	= tg3_ptp_adjfreq,
 	.adjtime	= tg3_ptp_adjtime,
@@ -10367,6 +10420,9 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
 	if (tg3_flag(tp, 5755_PLUS))
 		tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
 
+	if (tg3_asic_rev(tp) == ASIC_REV_5762)
+		tp->rx_mode |= RX_MODE_IPV4_FRAG_FIX;
+
 	if (tg3_flag(tp, ENABLE_RSS))
 		tp->rx_mode |= RX_MODE_RSS_ENABLE |
 			       RX_MODE_RSS_ITBL_HASH_BITS_7 |
@@ -11502,7 +11558,7 @@ static int tg3_close(struct net_device *dev)
 	memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev));
 	memset(&tp->estats_prev, 0, sizeof(tp->estats_prev));
 
-	tg3_power_down(tp);
+	tg3_power_down_prepare(tp);
 
 	tg3_carrier_off(tp);
 
@@ -11724,9 +11780,6 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 	if (tg3_flag(tp, NO_NVRAM))
 		return -EINVAL;
 
-	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
-		return -EAGAIN;
-
 	offset = eeprom->offset;
 	len = eeprom->len;
 	eeprom->len = 0;
@@ -11784,9 +11837,6 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 	u8 *buf;
 	__be32 start, end;
 
-	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
-		return -EAGAIN;
-
 	if (tg3_flag(tp, NO_NVRAM) ||
 	    eeprom->magic != TG3_EEPROM_MAGIC)
 		return -EINVAL;
@@ -13515,7 +13565,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 			tg3_phy_start(tp);
 	}
 	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
-		tg3_power_down(tp);
+		tg3_power_down_prepare(tp);
 
 }
 
@@ -17547,11 +17597,6 @@ static int tg3_init_one(struct pci_dev *pdev,
 	    tg3_asic_rev(tp) == ASIC_REV_5762)
 		tg3_flag_set(tp, PTP_CAPABLE);
 
-	if (tg3_flag(tp, 5717_PLUS)) {
-		/* Resume a low-power mode */
-		tg3_frob_aux_power(tp, false);
-	}
-
 	tg3_timer_init(tp);
 
 	tg3_carrier_off(tp);
@@ -17755,6 +17800,23 @@ out:
 
 static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume);
 
+static void tg3_shutdown(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct tg3 *tp = netdev_priv(dev);
+
+	rtnl_lock();
+	netif_device_detach(dev);
+
+	if (netif_running(dev))
+		dev_close(dev);
+
+	if (system_state == SYSTEM_POWER_OFF)
+		tg3_power_down(tp);
+
+	rtnl_unlock();
+}
+
 /**
  * tg3_io_error_detected - called when PCI error is detected
  * @pdev: Pointer to PCI device
@@ -17911,6 +17973,7 @@ static struct pci_driver tg3_driver = {
 	.remove		= tg3_remove_one,
 	.err_handler	= &tg3_err_handler,
 	.driver.pm	= &tg3_pm_ops,
+	.shutdown	= tg3_shutdown,
 };
 
 module_pci_driver(tg3_driver);
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index cd63d11..ddb8be1 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -532,6 +532,7 @@
 #define  RX_MODE_RSS_ITBL_HASH_BITS_7	 0x00700000
 #define  RX_MODE_RSS_ENABLE		 0x00800000
 #define  RX_MODE_IPV6_CSUM_ENABLE	 0x01000000
+#define  RX_MODE_IPV4_FRAG_FIX		 0x02000000
 #define MAC_RX_STATUS			0x0000046c
 #define  RX_STATUS_REMOTE_TX_XOFFED	 0x00000001
 #define  RX_STATUS_XOFF_RCVD		 0x00000002
@@ -1818,12 +1819,21 @@
 #define TG3_EAV_REF_CLCK_CTL		0x00006908
 #define  TG3_EAV_REF_CLCK_CTL_STOP	 0x00000002
 #define  TG3_EAV_REF_CLCK_CTL_RESUME	 0x00000004
+#define  TG3_EAV_CTL_TSYNC_GPIO_MASK	 (0x3 << 16)
+#define  TG3_EAV_CTL_TSYNC_WDOG0	 (1 << 17)
+
+#define TG3_EAV_WATCHDOG0_LSB		0x00006918
+#define TG3_EAV_WATCHDOG0_MSB		0x0000691c
+#define  TG3_EAV_WATCHDOG0_EN		 (1 << 31)
+#define  TG3_EAV_WATCHDOG_MSB_MASK	0x7fffffff
+
 #define TG3_EAV_REF_CLK_CORRECT_CTL	0x00006928
 #define  TG3_EAV_REF_CLK_CORRECT_EN	 (1 << 31)
 #define  TG3_EAV_REF_CLK_CORRECT_NEG	 (1 << 30)
 
 #define TG3_EAV_REF_CLK_CORRECT_MASK	0xffffff
-/* 0x690c --> 0x7000 unused */
+
+/* 0x692c --> 0x7000 unused */
 
 /* NVRAM Control registers */
 #define NVRAM_CMD			0x00007000
diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
index 57cd1bf..3c07064 100644
--- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
+++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
@@ -1419,7 +1419,7 @@ static void bna_rx_sm_start_wait_entry(struct bna_rx *rx)
 	bna_bfi_rx_enet_start(rx);
 }
 
-void
+static void
 bna_rx_sm_stop_wait_entry(struct bna_rx *rx)
 {
 }
@@ -1472,7 +1472,7 @@ static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
 	bna_rxf_start(&rx->rxf);
 }
 
-void
+static void
 bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
 {
 }
@@ -1528,7 +1528,7 @@ bna_rx_sm_start_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
 	}
 }
 
-void
+static void
 bna_rx_sm_started_entry(struct bna_rx *rx)
 {
 	struct bna_rxp *rxp;
@@ -1593,12 +1593,12 @@ static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
 	}
 }
 
-void
+static void
 bna_rx_sm_cleanup_wait_entry(struct bna_rx *rx)
 {
 }
 
-void
+static void
 bna_rx_sm_cleanup_wait(struct bna_rx *rx, enum bna_rx_event event)
 {
 	switch (event) {
diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/ethernet/cisco/enic/Makefile
index 9d4974b..e52296d 100644
--- a/drivers/net/ethernet/cisco/enic/Makefile
+++ b/drivers/net/ethernet/cisco/enic/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_ENIC) := enic.o
 
 enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
-	enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o
+	enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \
+	enic_ethtool.o
 
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index afe9b16..2e37c63 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -127,9 +127,57 @@ static inline struct device *enic_get_dev(struct enic *enic)
 	return &(enic->pdev->dev);
 }
 
+static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
+{
+	return rq;
+}
+
+static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
+{
+	return enic->rq_count + wq;
+}
+
+static inline unsigned int enic_legacy_io_intr(void)
+{
+	return 0;
+}
+
+static inline unsigned int enic_legacy_err_intr(void)
+{
+	return 1;
+}
+
+static inline unsigned int enic_legacy_notify_intr(void)
+{
+	return 2;
+}
+
+static inline unsigned int enic_msix_rq_intr(struct enic *enic,
+	unsigned int rq)
+{
+	return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset;
+}
+
+static inline unsigned int enic_msix_wq_intr(struct enic *enic,
+	unsigned int wq)
+{
+	return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
+}
+
+static inline unsigned int enic_msix_err_intr(struct enic *enic)
+{
+	return enic->rq_count + enic->wq_count;
+}
+
+static inline unsigned int enic_msix_notify_intr(struct enic *enic)
+{
+	return enic->rq_count + enic->wq_count + 1;
+}
+
 void enic_reset_addr_lists(struct enic *enic);
 int enic_sriov_enabled(struct enic *enic);
 int enic_is_valid_vf(struct enic *enic, int vf);
 int enic_is_dynamic(struct enic *enic);
+void enic_set_ethtool_ops(struct net_device *netdev);
 
 #endif /* _ENIC_H_ */
diff --git a/drivers/net/ethernet/cisco/enic/enic_dev.h b/drivers/net/ethernet/cisco/enic/enic_dev.h
index 08bded0..129b14a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/enic_dev.h
@@ -20,6 +20,7 @@
 #define _ENIC_DEV_H_
 
 #include "vnic_dev.h"
+#include "vnic_vic.h"
 
 /*
  * Calls the devcmd function given by argument vnicdevcmdfn.
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
new file mode 100644
index 0000000..47e3562
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -0,0 +1,257 @@
+/**
+ * Copyright 2013 Cisco Systems, Inc.  All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+
+#include "enic_res.h"
+#include "enic.h"
+#include "enic_dev.h"
+
+struct enic_stat {
+	char name[ETH_GSTRING_LEN];
+	unsigned int index;
+};
+
+#define ENIC_TX_STAT(stat) { \
+	.name = #stat, \
+	.index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \
+}
+
+#define ENIC_RX_STAT(stat) { \
+	.name = #stat, \
+	.index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \
+}
+
+static const struct enic_stat enic_tx_stats[] = {
+	ENIC_TX_STAT(tx_frames_ok),
+	ENIC_TX_STAT(tx_unicast_frames_ok),
+	ENIC_TX_STAT(tx_multicast_frames_ok),
+	ENIC_TX_STAT(tx_broadcast_frames_ok),
+	ENIC_TX_STAT(tx_bytes_ok),
+	ENIC_TX_STAT(tx_unicast_bytes_ok),
+	ENIC_TX_STAT(tx_multicast_bytes_ok),
+	ENIC_TX_STAT(tx_broadcast_bytes_ok),
+	ENIC_TX_STAT(tx_drops),
+	ENIC_TX_STAT(tx_errors),
+	ENIC_TX_STAT(tx_tso),
+};
+
+static const struct enic_stat enic_rx_stats[] = {
+	ENIC_RX_STAT(rx_frames_ok),
+	ENIC_RX_STAT(rx_frames_total),
+	ENIC_RX_STAT(rx_unicast_frames_ok),
+	ENIC_RX_STAT(rx_multicast_frames_ok),
+	ENIC_RX_STAT(rx_broadcast_frames_ok),
+	ENIC_RX_STAT(rx_bytes_ok),
+	ENIC_RX_STAT(rx_unicast_bytes_ok),
+	ENIC_RX_STAT(rx_multicast_bytes_ok),
+	ENIC_RX_STAT(rx_broadcast_bytes_ok),
+	ENIC_RX_STAT(rx_drop),
+	ENIC_RX_STAT(rx_no_bufs),
+	ENIC_RX_STAT(rx_errors),
+	ENIC_RX_STAT(rx_rss),
+	ENIC_RX_STAT(rx_crc_errors),
+	ENIC_RX_STAT(rx_frames_64),
+	ENIC_RX_STAT(rx_frames_127),
+	ENIC_RX_STAT(rx_frames_255),
+	ENIC_RX_STAT(rx_frames_511),
+	ENIC_RX_STAT(rx_frames_1023),
+	ENIC_RX_STAT(rx_frames_1518),
+	ENIC_RX_STAT(rx_frames_to_max),
+};
+
+static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
+static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
+
+static int enic_get_settings(struct net_device *netdev,
+	struct ethtool_cmd *ecmd)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+	ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
+	ecmd->port = PORT_FIBRE;
+	ecmd->transceiver = XCVR_EXTERNAL;
+
+	if (netif_carrier_ok(netdev)) {
+		ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev));
+		ecmd->duplex = DUPLEX_FULL;
+	} else {
+		ethtool_cmd_speed_set(ecmd, -1);
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_DISABLE;
+
+	return 0;
+}
+
+static void enic_get_drvinfo(struct net_device *netdev,
+	struct ethtool_drvinfo *drvinfo)
+{
+	struct enic *enic = netdev_priv(netdev);
+	struct vnic_devcmd_fw_info *fw_info;
+
+	enic_dev_fw_info(enic, &fw_info);
+
+	strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+	strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
+	strlcpy(drvinfo->fw_version, fw_info->fw_version,
+		sizeof(drvinfo->fw_version));
+	strlcpy(drvinfo->bus_info, pci_name(enic->pdev),
+		sizeof(drvinfo->bus_info));
+}
+
+static void enic_get_strings(struct net_device *netdev, u32 stringset,
+	u8 *data)
+{
+	unsigned int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < enic_n_tx_stats; i++) {
+			memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN);
+			data += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < enic_n_rx_stats; i++) {
+			memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN);
+			data += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+static int enic_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return enic_n_tx_stats + enic_n_rx_stats;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void enic_get_ethtool_stats(struct net_device *netdev,
+	struct ethtool_stats *stats, u64 *data)
+{
+	struct enic *enic = netdev_priv(netdev);
+	struct vnic_stats *vstats;
+	unsigned int i;
+
+	enic_dev_stats_dump(enic, &vstats);
+
+	for (i = 0; i < enic_n_tx_stats; i++)
+		*(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].index];
+	for (i = 0; i < enic_n_rx_stats; i++)
+		*(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].index];
+}
+
+static u32 enic_get_msglevel(struct net_device *netdev)
+{
+	struct enic *enic = netdev_priv(netdev);
+	return enic->msg_enable;
+}
+
+static void enic_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct enic *enic = netdev_priv(netdev);
+	enic->msg_enable = value;
+}
+
+static int enic_get_coalesce(struct net_device *netdev,
+	struct ethtool_coalesce *ecmd)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
+	ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
+
+	return 0;
+}
+
+static int enic_set_coalesce(struct net_device *netdev,
+	struct ethtool_coalesce *ecmd)
+{
+	struct enic *enic = netdev_priv(netdev);
+	u32 tx_coalesce_usecs;
+	u32 rx_coalesce_usecs;
+	unsigned int i, intr;
+
+	tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
+		vnic_dev_get_intr_coal_timer_max(enic->vdev));
+	rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
+		vnic_dev_get_intr_coal_timer_max(enic->vdev));
+
+	switch (vnic_dev_get_intr_mode(enic->vdev)) {
+	case VNIC_DEV_INTR_MODE_INTX:
+		if (tx_coalesce_usecs != rx_coalesce_usecs)
+			return -EINVAL;
+
+		intr = enic_legacy_io_intr();
+		vnic_intr_coalescing_timer_set(&enic->intr[intr],
+			tx_coalesce_usecs);
+		break;
+	case VNIC_DEV_INTR_MODE_MSI:
+		if (tx_coalesce_usecs != rx_coalesce_usecs)
+			return -EINVAL;
+
+		vnic_intr_coalescing_timer_set(&enic->intr[0],
+			tx_coalesce_usecs);
+		break;
+	case VNIC_DEV_INTR_MODE_MSIX:
+		for (i = 0; i < enic->wq_count; i++) {
+			intr = enic_msix_wq_intr(enic, i);
+			vnic_intr_coalescing_timer_set(&enic->intr[intr],
+				tx_coalesce_usecs);
+		}
+
+		for (i = 0; i < enic->rq_count; i++) {
+			intr = enic_msix_rq_intr(enic, i);
+			vnic_intr_coalescing_timer_set(&enic->intr[intr],
+				rx_coalesce_usecs);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	enic->tx_coalesce_usecs = tx_coalesce_usecs;
+	enic->rx_coalesce_usecs = rx_coalesce_usecs;
+
+	return 0;
+}
+
+static const struct ethtool_ops enic_ethtool_ops = {
+	.get_settings = enic_get_settings,
+	.get_drvinfo = enic_get_drvinfo,
+	.get_msglevel = enic_get_msglevel,
+	.set_msglevel = enic_set_msglevel,
+	.get_link = ethtool_op_get_link,
+	.get_strings = enic_get_strings,
+	.get_sset_count = enic_get_sset_count,
+	.get_ethtool_stats = enic_get_ethtool_stats,
+	.get_coalesce = enic_get_coalesce,
+	.set_coalesce = enic_set_coalesce,
+};
+
+void enic_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &enic_ethtool_ops);
+}
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 992ec2e..b12b32b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -31,7 +31,6 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
-#include <linux/ethtool.h>
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
@@ -73,57 +72,6 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, enic_id_table);
 
-struct enic_stat {
-	char name[ETH_GSTRING_LEN];
-	unsigned int offset;
-};
-
-#define ENIC_TX_STAT(stat)	\
-	{ .name = #stat, .offset = offsetof(struct vnic_tx_stats, stat) / 8 }
-#define ENIC_RX_STAT(stat)	\
-	{ .name = #stat, .offset = offsetof(struct vnic_rx_stats, stat) / 8 }
-
-static const struct enic_stat enic_tx_stats[] = {
-	ENIC_TX_STAT(tx_frames_ok),
-	ENIC_TX_STAT(tx_unicast_frames_ok),
-	ENIC_TX_STAT(tx_multicast_frames_ok),
-	ENIC_TX_STAT(tx_broadcast_frames_ok),
-	ENIC_TX_STAT(tx_bytes_ok),
-	ENIC_TX_STAT(tx_unicast_bytes_ok),
-	ENIC_TX_STAT(tx_multicast_bytes_ok),
-	ENIC_TX_STAT(tx_broadcast_bytes_ok),
-	ENIC_TX_STAT(tx_drops),
-	ENIC_TX_STAT(tx_errors),
-	ENIC_TX_STAT(tx_tso),
-};
-
-static const struct enic_stat enic_rx_stats[] = {
-	ENIC_RX_STAT(rx_frames_ok),
-	ENIC_RX_STAT(rx_frames_total),
-	ENIC_RX_STAT(rx_unicast_frames_ok),
-	ENIC_RX_STAT(rx_multicast_frames_ok),
-	ENIC_RX_STAT(rx_broadcast_frames_ok),
-	ENIC_RX_STAT(rx_bytes_ok),
-	ENIC_RX_STAT(rx_unicast_bytes_ok),
-	ENIC_RX_STAT(rx_multicast_bytes_ok),
-	ENIC_RX_STAT(rx_broadcast_bytes_ok),
-	ENIC_RX_STAT(rx_drop),
-	ENIC_RX_STAT(rx_no_bufs),
-	ENIC_RX_STAT(rx_errors),
-	ENIC_RX_STAT(rx_rss),
-	ENIC_RX_STAT(rx_crc_errors),
-	ENIC_RX_STAT(rx_frames_64),
-	ENIC_RX_STAT(rx_frames_127),
-	ENIC_RX_STAT(rx_frames_255),
-	ENIC_RX_STAT(rx_frames_511),
-	ENIC_RX_STAT(rx_frames_1023),
-	ENIC_RX_STAT(rx_frames_1518),
-	ENIC_RX_STAT(rx_frames_to_max),
-};
-
-static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
-static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
-
 int enic_is_dynamic(struct enic *enic)
 {
 	return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
@@ -148,222 +96,6 @@ int enic_is_valid_vf(struct enic *enic, int vf)
 #endif
 }
 
-static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
-{
-	return rq;
-}
-
-static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
-{
-	return enic->rq_count + wq;
-}
-
-static inline unsigned int enic_legacy_io_intr(void)
-{
-	return 0;
-}
-
-static inline unsigned int enic_legacy_err_intr(void)
-{
-	return 1;
-}
-
-static inline unsigned int enic_legacy_notify_intr(void)
-{
-	return 2;
-}
-
-static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
-{
-	return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset;
-}
-
-static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
-{
-	return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
-}
-
-static inline unsigned int enic_msix_err_intr(struct enic *enic)
-{
-	return enic->rq_count + enic->wq_count;
-}
-
-static inline unsigned int enic_msix_notify_intr(struct enic *enic)
-{
-	return enic->rq_count + enic->wq_count + 1;
-}
-
-static int enic_get_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
-	ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
-	ecmd->port = PORT_FIBRE;
-	ecmd->transceiver = XCVR_EXTERNAL;
-
-	if (netif_carrier_ok(netdev)) {
-		ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev));
-		ecmd->duplex = DUPLEX_FULL;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-
-	ecmd->autoneg = AUTONEG_DISABLE;
-
-	return 0;
-}
-
-static void enic_get_drvinfo(struct net_device *netdev,
-	struct ethtool_drvinfo *drvinfo)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_devcmd_fw_info *fw_info;
-
-	enic_dev_fw_info(enic, &fw_info);
-
-	strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-	strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
-	strlcpy(drvinfo->fw_version, fw_info->fw_version,
-		sizeof(drvinfo->fw_version));
-	strlcpy(drvinfo->bus_info, pci_name(enic->pdev),
-		sizeof(drvinfo->bus_info));
-}
-
-static void enic_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
-{
-	unsigned int i;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < enic_n_tx_stats; i++) {
-			memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
-		for (i = 0; i < enic_n_rx_stats; i++) {
-			memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
-		break;
-	}
-}
-
-static int enic_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return enic_n_tx_stats + enic_n_rx_stats;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void enic_get_ethtool_stats(struct net_device *netdev,
-	struct ethtool_stats *stats, u64 *data)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_stats *vstats;
-	unsigned int i;
-
-	enic_dev_stats_dump(enic, &vstats);
-
-	for (i = 0; i < enic_n_tx_stats; i++)
-		*(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].offset];
-	for (i = 0; i < enic_n_rx_stats; i++)
-		*(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].offset];
-}
-
-static u32 enic_get_msglevel(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	return enic->msg_enable;
-}
-
-static void enic_set_msglevel(struct net_device *netdev, u32 value)
-{
-	struct enic *enic = netdev_priv(netdev);
-	enic->msg_enable = value;
-}
-
-static int enic_get_coalesce(struct net_device *netdev,
-	struct ethtool_coalesce *ecmd)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
-	ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
-
-	return 0;
-}
-
-static int enic_set_coalesce(struct net_device *netdev,
-	struct ethtool_coalesce *ecmd)
-{
-	struct enic *enic = netdev_priv(netdev);
-	u32 tx_coalesce_usecs;
-	u32 rx_coalesce_usecs;
-	unsigned int i, intr;
-
-	tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
-		vnic_dev_get_intr_coal_timer_max(enic->vdev));
-	rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
-		vnic_dev_get_intr_coal_timer_max(enic->vdev));
-
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_INTX:
-		if (tx_coalesce_usecs != rx_coalesce_usecs)
-			return -EINVAL;
-
-		intr = enic_legacy_io_intr();
-		vnic_intr_coalescing_timer_set(&enic->intr[intr],
-			tx_coalesce_usecs);
-		break;
-	case VNIC_DEV_INTR_MODE_MSI:
-		if (tx_coalesce_usecs != rx_coalesce_usecs)
-			return -EINVAL;
-
-		vnic_intr_coalescing_timer_set(&enic->intr[0],
-			tx_coalesce_usecs);
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < enic->wq_count; i++) {
-			intr = enic_msix_wq_intr(enic, i);
-			vnic_intr_coalescing_timer_set(&enic->intr[intr],
-				tx_coalesce_usecs);
-		}
-
-		for (i = 0; i < enic->rq_count; i++) {
-			intr = enic_msix_rq_intr(enic, i);
-			vnic_intr_coalescing_timer_set(&enic->intr[intr],
-				rx_coalesce_usecs);
-		}
-
-		break;
-	default:
-		break;
-	}
-
-	enic->tx_coalesce_usecs = tx_coalesce_usecs;
-	enic->rx_coalesce_usecs = rx_coalesce_usecs;
-
-	return 0;
-}
-
-static const struct ethtool_ops enic_ethtool_ops = {
-	.get_settings = enic_get_settings,
-	.get_drvinfo = enic_get_drvinfo,
-	.get_msglevel = enic_get_msglevel,
-	.set_msglevel = enic_set_msglevel,
-	.get_link = ethtool_op_get_link,
-	.get_strings = enic_get_strings,
-	.get_sset_count = enic_get_sset_count,
-	.get_ethtool_stats = enic_get_ethtool_stats,
-	.get_coalesce = enic_get_coalesce,
-	.set_coalesce = enic_set_coalesce,
-};
-
 static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
 {
 	struct enic *enic = vnic_dev_priv(wq->vdev);
@@ -2496,7 +2228,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->netdev_ops = &enic_netdev_ops;
 
 	netdev->watchdog_timeo = 2 * HZ;
-	netdev->ethtool_ops = &enic_ethtool_ops;
+	enic_set_ethtool_ops(netdev);
 
 	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
 	if (ENIC_SETTING(enic, LOOP)) {
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index c94152f..4e8cfa2 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1304,7 +1304,9 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct tulip_private *tp;
 	/* See note below on the multiport cards. */
-	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+	static unsigned char last_phys_addr[ETH_ALEN] = {
+		0x00, 'L', 'i', 'n', 'u', 'x'
+	};
 	static int last_irq;
 	static int multiport_cnt;	/* For four-port boards w/one EEPROM */
 	int i, irq;
@@ -1627,8 +1629,8 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev->dev_addr[i] = last_phys_addr[i] + 1;
 #if defined(CONFIG_SPARC)
 		addr = of_get_property(dp, "local-mac-address", &len);
-		if (addr && len == 6)
-			memcpy(dev->dev_addr, addr, 6);
+		if (addr && len == ETH_ALEN)
+			memcpy(dev->dev_addr, addr, ETH_ALEN);
 #endif
 #if defined(__i386__) || defined(__x86_64__)	/* Patch up x86 BIOS bug. */
 		if (last_irq)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index c827b1b..11c815d 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -34,7 +34,7 @@
 #include "be_hw.h"
 #include "be_roce.h"
 
-#define DRV_VER			"4.6.62.0u"
+#define DRV_VER			"4.9.134.0u"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"Emulex BladeEngine2"
 #define BE3_NAME		"Emulex BladeEngine3"
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 6e6e0a1..5175f97 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -258,7 +258,8 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter,
 		(struct be_async_event_grp5_pvid_state *)evt);
 	break;
 	default:
-		dev_warn(&adapter->pdev->dev, "Unknown grp5 event!\n");
+		dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n",
+			 event_type);
 		break;
 	}
 }
@@ -279,7 +280,8 @@ static void be_async_dbg_evt_process(struct be_adapter *adapter,
 		adapter->flags |= BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
 	break;
 	default:
-		dev_warn(&adapter->pdev->dev, "Unknown debug event\n");
+		dev_warn(&adapter->pdev->dev, "Unknown debug event 0x%x!\n",
+			 event_type);
 	break;
 	}
 }
@@ -1010,9 +1012,9 @@ static u32 be_encoded_q_len(int q_len)
 	return len_encoded;
 }
 
-int be_cmd_mccq_ext_create(struct be_adapter *adapter,
-			struct be_queue_info *mccq,
-			struct be_queue_info *cq)
+static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
+				struct be_queue_info *mccq,
+				struct be_queue_info *cq)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_mcc_ext_create *req;
@@ -1068,9 +1070,9 @@ int be_cmd_mccq_ext_create(struct be_adapter *adapter,
 	return status;
 }
 
-int be_cmd_mccq_org_create(struct be_adapter *adapter,
-			struct be_queue_info *mccq,
-			struct be_queue_info *cq)
+static int be_cmd_mccq_org_create(struct be_adapter *adapter,
+				struct be_queue_info *mccq,
+				struct be_queue_info *cq)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_mcc_create *req;
@@ -1339,6 +1341,10 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
 	if (!status) {
 		struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
 		*if_handle = le32_to_cpu(resp->interface_id);
+
+		/* Hack to retrieve VF's pmac-id on BE3 */
+		if (BE3_chip(adapter) && !be_physfn(adapter))
+			adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
 	}
 
 err:
@@ -1460,6 +1466,12 @@ static int be_mac_to_link_speed(int mac_speed)
 		return 1000;
 	case PHY_LINK_SPEED_10GBPS:
 		return 10000;
+	case PHY_LINK_SPEED_20GBPS:
+		return 20000;
+	case PHY_LINK_SPEED_25GBPS:
+		return 25000;
+	case PHY_LINK_SPEED_40GBPS:
+		return 40000;
 	}
 	return 0;
 }
@@ -1520,7 +1532,7 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_get_cntl_addnl_attribs *req;
-	int status;
+	int status = 0;
 
 	spin_lock_bh(&adapter->mcc_lock);
 
@@ -2444,6 +2456,12 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
 			le16_to_cpu(resp_phy_info->fixed_speeds_supported);
 		adapter->phy.misc_params =
 			le32_to_cpu(resp_phy_info->misc_params);
+
+		if (BE2_chip(adapter)) {
+			adapter->phy.fixed_speeds_supported =
+				BE_SUPPORTED_SPEED_10GBPS |
+				BE_SUPPORTED_SPEED_1GBPS;
+		}
 	}
 	pci_free_consistent(adapter->pdev, cmd.size,
 				cmd.va, cmd.dma);
@@ -2606,9 +2624,44 @@ err:
 	return status;
 }
 
-/* Uses synchronous MCCQ */
+/* Set privilege(s) for a function */
+int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
+			     u32 domain)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_set_fn_privileges *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_SET_FN_PRIVILEGES, sizeof(*req),
+			       wrb, NULL);
+	req->hdr.domain = domain;
+	if (lancer_chip(adapter))
+		req->privileges_lancer = cpu_to_le32(privileges);
+	else
+		req->privileges = cpu_to_le32(privileges);
+
+	status = be_mcc_notify_wait(adapter);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+/* pmac_id_valid: true => pmac_id is supplied and MAC address is requested.
+ * pmac_id_valid: false => pmac_id or MAC address is requested.
+ *		  If pmac_id is returned, pmac_id_valid is returned as true
+ */
 int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
-			     bool *pmac_id_active, u32 *pmac_id, u8 domain)
+			     bool *pmac_id_valid, u32 *pmac_id, u8 domain)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_get_mac_list *req;
@@ -2644,12 +2697,25 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 			       get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
 	req->hdr.domain = domain;
 	req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
-	req->perm_override = 1;
+	if (*pmac_id_valid) {
+		req->mac_id = cpu_to_le32(*pmac_id);
+		req->iface_id = cpu_to_le16(adapter->if_handle);
+		req->perm_override = 0;
+	} else {
+		req->perm_override = 1;
+	}
 
 	status = be_mcc_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_get_mac_list *resp =
 						get_mac_list_cmd.va;
+
+		if (*pmac_id_valid) {
+			memcpy(mac, resp->macid_macaddr.mac_addr_id.macaddr,
+			       ETH_ALEN);
+			goto out;
+		}
+
 		mac_count = resp->true_mac_count + resp->pseudo_mac_count;
 		/* Mac list returned could contain one or more active mac_ids
 		 * or one or more true or pseudo permanant mac addresses.
@@ -2667,14 +2733,14 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 			 * is 6 bytes
 			 */
 			if (mac_addr_size == sizeof(u32)) {
-				*pmac_id_active = true;
+				*pmac_id_valid = true;
 				mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
 				*pmac_id = le32_to_cpu(mac_id);
 				goto out;
 			}
 		}
 		/* If no active mac_id found, return first mac addr */
-		*pmac_id_active = false;
+		*pmac_id_valid = false;
 		memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
 								ETH_ALEN);
 	}
@@ -2686,6 +2752,41 @@ out:
 	return status;
 }
 
+int be_cmd_get_active_mac(struct be_adapter *adapter, u32 curr_pmac_id, u8 *mac)
+{
+	bool active = true;
+
+	if (BEx_chip(adapter))
+		return be_cmd_mac_addr_query(adapter, mac, false,
+					     adapter->if_handle, curr_pmac_id);
+	else
+		/* Fetch the MAC address using pmac_id */
+		return be_cmd_get_mac_from_list(adapter, mac, &active,
+						&curr_pmac_id, 0);
+}
+
+int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac)
+{
+	int status;
+	bool pmac_valid = false;
+
+	memset(mac, 0, ETH_ALEN);
+
+	if (BEx_chip(adapter)) {
+		if (be_physfn(adapter))
+			status = be_cmd_mac_addr_query(adapter, mac, true, 0,
+						       0);
+		else
+			status = be_cmd_mac_addr_query(adapter, mac, false,
+						       adapter->if_handle, 0);
+	} else {
+		status = be_cmd_get_mac_from_list(adapter, mac, &pmac_valid,
+						  NULL, 0);
+	}
+
+	return status;
+}
+
 /* Uses synchronous MCCQ */
 int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
 			u8 mac_count, u32 domain)
@@ -2729,6 +2830,25 @@ err:
 	return status;
 }
 
+/* Wrapper to delete any active MACs and provision the new mac.
+ * Changes to MAC_LIST are allowed iff none of the MAC addresses in the
+ * current list are active.
+ */
+int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
+{
+	bool active_mac = false;
+	u8 old_mac[ETH_ALEN];
+	u32 pmac_id;
+	int status;
+
+	status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
+					  &pmac_id, dom);
+	if (!status && active_mac)
+		be_cmd_pmac_del(adapter, if_id, pmac_id, dom);
+
+	return be_cmd_set_mac_list(adapter, mac, mac ? 1 : 0, dom);
+}
+
 int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
 			u32 domain, u16 intf_id)
 {
@@ -3057,8 +3177,8 @@ err:
 }
 
 /* Uses mbox */
-int be_cmd_get_profile_config_mbox(struct be_adapter *adapter,
-				   u8 domain, struct be_dma_mem *cmd)
+static int be_cmd_get_profile_config_mbox(struct be_adapter *adapter,
+					u8 domain, struct be_dma_mem *cmd)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_get_profile_config *req;
@@ -3085,8 +3205,8 @@ int be_cmd_get_profile_config_mbox(struct be_adapter *adapter,
 }
 
 /* Uses sync mcc */
-int be_cmd_get_profile_config_mccq(struct be_adapter *adapter,
-				   u8 domain, struct be_dma_mem *cmd)
+static int be_cmd_get_profile_config_mccq(struct be_adapter *adapter,
+					u8 domain, struct be_dma_mem *cmd)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_get_profile_config *req;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 5228d88..9b91608 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -202,6 +202,7 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_READ_TRANSRECV_DATA		73
 #define OPCODE_COMMON_GET_PORT_NAME			77
 #define OPCODE_COMMON_SET_INTERRUPT_ENABLE		89
+#define OPCODE_COMMON_SET_FN_PRIVILEGES			100
 #define OPCODE_COMMON_GET_PHY_DETAILS			102
 #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP		103
 #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES	121
@@ -959,7 +960,10 @@ enum {
 	PHY_LINK_SPEED_10MBPS = 0x1,
 	PHY_LINK_SPEED_100MBPS = 0x2,
 	PHY_LINK_SPEED_1GBPS = 0x3,
-	PHY_LINK_SPEED_10GBPS = 0x4
+	PHY_LINK_SPEED_10GBPS = 0x4,
+	PHY_LINK_SPEED_20GBPS = 0x5,
+	PHY_LINK_SPEED_25GBPS = 0x6,
+	PHY_LINK_SPEED_40GBPS = 0x7
 };
 
 struct be_cmd_resp_link_status {
@@ -1474,6 +1478,11 @@ struct be_cmd_resp_get_fn_privileges {
 	u32 privilege_mask;
 };
 
+struct be_cmd_req_set_fn_privileges {
+	struct be_cmd_req_hdr hdr;
+	u32 privileges;		/* Used by BE3, SH-R */
+	u32 privileges_lancer;	/* Used by Lancer */
+};
 
 /******************** GET/SET_MACLIST  **************************/
 #define BE_MAX_MAC			64
@@ -1921,11 +1930,18 @@ extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
 extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
 extern int be_cmd_get_fn_privileges(struct be_adapter *adapter,
 				    u32 *privilege, u32 domain);
+extern int be_cmd_set_fn_privileges(struct be_adapter *adapter,
+				    u32 privileges, u32 vf_num);
 extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 				    bool *pmac_id_active, u32 *pmac_id,
 				    u8 domain);
+extern int be_cmd_get_active_mac(struct be_adapter *adapter, u32 pmac_id,
+				 u8 *mac);
+extern int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac);
 extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
 						u8 mac_count, u32 domain);
+extern int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id,
+			  u32 dom);
 extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
 			u32 domain, u16 intf_id);
 extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 181edb5..ff2b40d 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -247,54 +247,54 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
 static int be_mac_addr_set(struct net_device *netdev, void *p)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
+	struct device *dev = &adapter->pdev->dev;
 	struct sockaddr *addr = p;
-	int status = 0;
-	u8 current_mac[ETH_ALEN];
-	u32 pmac_id = adapter->pmac_id[0];
-	bool active_mac = true;
+	int status;
+	u8 mac[ETH_ALEN];
+	u32 old_pmac_id = adapter->pmac_id[0], curr_pmac_id = 0;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	/* For BE VF, MAC address is already activated by PF.
-	 * Hence only operation left is updating netdev->devaddr.
-	 * Update it if user is passing the same MAC which was used
-	 * during configuring VF MAC from PF(Hypervisor).
+	/* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
+	 * privilege or if PF did not provision the new MAC address.
+	 * On BE3, this cmd will always fail if the VF doesn't have the
+	 * FILTMGMT privilege. This failure is OK, only if the PF programmed
+	 * the MAC for the VF.
 	 */
-	if (!lancer_chip(adapter) && !be_physfn(adapter)) {
-		status = be_cmd_mac_addr_query(adapter, current_mac,
-					       false, adapter->if_handle, 0);
-		if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN))
-			goto done;
-		else
-			goto err;
-	}
+	status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+				 adapter->if_handle, &adapter->pmac_id[0], 0);
+	if (!status) {
+		curr_pmac_id = adapter->pmac_id[0];
 
-	if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN))
-		goto done;
+		/* Delete the old programmed MAC. This call may fail if the
+		 * old MAC was already deleted by the PF driver.
+		 */
+		if (adapter->pmac_id[0] != old_pmac_id)
+			be_cmd_pmac_del(adapter, adapter->if_handle,
+					old_pmac_id, 0);
+	}
 
-	/* For Lancer check if any MAC is active.
-	 * If active, get its mac id.
+	/* Decide if the new MAC is successfully activated only after
+	 * querying the FW
 	 */
-	if (lancer_chip(adapter) && !be_physfn(adapter))
-		be_cmd_get_mac_from_list(adapter, current_mac, &active_mac,
-					 &pmac_id, 0);
-
-	status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-				 adapter->if_handle,
-				 &adapter->pmac_id[0], 0);
-
+	status = be_cmd_get_active_mac(adapter, curr_pmac_id, mac);
 	if (status)
 		goto err;
 
-	if (active_mac)
-		be_cmd_pmac_del(adapter, adapter->if_handle,
-				pmac_id, 0);
-done:
+	/* The MAC change did not happen, either due to lack of privilege
+	 * or PF didn't pre-provision.
+	 */
+	if (memcmp(addr->sa_data, mac, ETH_ALEN)) {
+		status = -EPERM;
+		goto err;
+	}
+
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	dev_info(dev, "MAC address changed to %pM\n", mac);
 	return 0;
 err:
-	dev_err(&adapter->pdev->dev, "MAC %pM set Failed\n", addr->sa_data);
+	dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data);
 	return status;
 }
 
@@ -472,7 +472,7 @@ static void accumulate_16bit_val(u32 *acc, u16 val)
 	ACCESS_ONCE(*acc) = newacc;
 }
 
-void populate_erx_stats(struct be_adapter *adapter,
+static void populate_erx_stats(struct be_adapter *adapter,
 			struct be_rx_obj *rxo,
 			u32 erx_stat)
 {
@@ -1146,9 +1146,6 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
 	int status;
-	bool active_mac = false;
-	u32 pmac_id;
-	u8 old_mac[ETH_ALEN];
 
 	if (!sriov_enabled(adapter))
 		return -EPERM;
@@ -1156,20 +1153,15 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 	if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs)
 		return -EINVAL;
 
-	if (lancer_chip(adapter)) {
-		status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
-						  &pmac_id, vf + 1);
-		if (!status && active_mac)
-			be_cmd_pmac_del(adapter, vf_cfg->if_handle,
-					pmac_id, vf + 1);
-
-		status = be_cmd_set_mac_list(adapter,  mac, 1, vf + 1);
-	} else {
-		status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
-					 vf_cfg->pmac_id, vf + 1);
+	if (BEx_chip(adapter)) {
+		be_cmd_pmac_del(adapter, vf_cfg->if_handle, vf_cfg->pmac_id,
+				vf + 1);
 
 		status = be_cmd_pmac_add(adapter, mac, vf_cfg->if_handle,
 					 &vf_cfg->pmac_id, vf + 1);
+	} else {
+		status = be_cmd_set_mac(adapter, mac, vf_cfg->if_handle,
+					vf + 1);
 	}
 
 	if (status)
@@ -1490,8 +1482,9 @@ static void be_rx_compl_process(struct be_rx_obj *rxo,
 }
 
 /* Process the RX completion indicated by rxcp when GRO is enabled */
-void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi,
-			     struct be_rx_compl_info *rxcp)
+static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
+				    struct napi_struct *napi,
+				    struct be_rx_compl_info *rxcp)
 {
 	struct be_adapter *adapter = rxo->adapter;
 	struct be_rx_page_info *page_info;
@@ -2267,7 +2260,7 @@ static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo,
 	return (work_done < budget); /* Done */
 }
 
-int be_poll(struct napi_struct *napi, int budget)
+static int be_poll(struct napi_struct *napi, int budget)
 {
 	struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi);
 	struct be_adapter *adapter = eqo->adapter;
@@ -2735,13 +2728,13 @@ static int be_vf_eth_addr_config(struct be_adapter *adapter)
 	be_vf_eth_addr_generate(adapter, mac);
 
 	for_all_vfs(adapter, vf_cfg, vf) {
-		if (lancer_chip(adapter)) {
-			status = be_cmd_set_mac_list(adapter,  mac, 1, vf + 1);
-		} else {
+		if (BEx_chip(adapter))
 			status = be_cmd_pmac_add(adapter, mac,
 						 vf_cfg->if_handle,
 						 &vf_cfg->pmac_id, vf + 1);
-		}
+		else
+			status = be_cmd_set_mac(adapter, mac, vf_cfg->if_handle,
+						vf + 1);
 
 		if (status)
 			dev_err(&adapter->pdev->dev,
@@ -2759,7 +2752,7 @@ static int be_vfs_mac_query(struct be_adapter *adapter)
 	int status, vf;
 	u8 mac[ETH_ALEN];
 	struct be_vf_cfg *vf_cfg;
-	bool active;
+	bool active = false;
 
 	for_all_vfs(adapter, vf_cfg, vf) {
 		be_cmd_get_mac_from_list(adapter, mac, &active,
@@ -2788,11 +2781,12 @@ static void be_vf_clear(struct be_adapter *adapter)
 	pci_disable_sriov(adapter->pdev);
 
 	for_all_vfs(adapter, vf_cfg, vf) {
-		if (lancer_chip(adapter))
-			be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
-		else
+		if (BEx_chip(adapter))
 			be_cmd_pmac_del(adapter, vf_cfg->if_handle,
 					vf_cfg->pmac_id, vf + 1);
+		else
+			be_cmd_set_mac(adapter, NULL, vf_cfg->if_handle,
+				       vf + 1);
 
 		be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
 	}
@@ -2803,7 +2797,7 @@ done:
 
 static int be_clear(struct be_adapter *adapter)
 {
-	int i = 1;
+	int i;
 
 	if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) {
 		cancel_delayed_work_sync(&adapter->work);
@@ -2813,9 +2807,11 @@ static int be_clear(struct be_adapter *adapter)
 	if (sriov_enabled(adapter))
 		be_vf_clear(adapter);
 
-	for (; adapter->uc_macs > 0; adapter->uc_macs--, i++)
+	/* delete the primary mac along with the uc-mac list */
+	for (i = 0; i < (adapter->uc_macs + 1); i++)
 		be_cmd_pmac_del(adapter, adapter->if_handle,
-			adapter->pmac_id[i], 0);
+				adapter->pmac_id[i], 0);
+	adapter->uc_macs = 0;
 
 	be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
@@ -2880,6 +2876,7 @@ static int be_vf_setup(struct be_adapter *adapter)
 	u16 def_vlan, lnk_speed;
 	int status, old_vfs, vf;
 	struct device *dev = &adapter->pdev->dev;
+	u32 privileges;
 
 	old_vfs = pci_num_vf(adapter->pdev);
 	if (old_vfs) {
@@ -2923,6 +2920,18 @@ static int be_vf_setup(struct be_adapter *adapter)
 	}
 
 	for_all_vfs(adapter, vf_cfg, vf) {
+		/* Allow VFs to programs MAC/VLAN filters */
+		status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1);
+		if (!status && !(privileges & BE_PRIV_FILTMGMT)) {
+			status = be_cmd_set_fn_privileges(adapter,
+							  privileges |
+							  BE_PRIV_FILTMGMT,
+							  vf + 1);
+			if (!status)
+				dev_info(dev, "VF%d has FILTMGMT privilege\n",
+					 vf);
+		}
+
 		/* BE3 FW, by default, caps VF TX-rate to 100mbps.
 		 * Allow full available bandwidth
 		 */
@@ -2971,41 +2980,6 @@ static void be_setup_init(struct be_adapter *adapter)
 		adapter->cmd_privileges = MIN_PRIVILEGES;
 }
 
-static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
-			   bool *active_mac, u32 *pmac_id)
-{
-	int status = 0;
-
-	if (!is_zero_ether_addr(adapter->netdev->perm_addr)) {
-		memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
-		if (!lancer_chip(adapter) && !be_physfn(adapter))
-			*active_mac = true;
-		else
-			*active_mac = false;
-
-		return status;
-	}
-
-	if (lancer_chip(adapter)) {
-		status = be_cmd_get_mac_from_list(adapter, mac,
-						  active_mac, pmac_id, 0);
-		if (*active_mac) {
-			status = be_cmd_mac_addr_query(adapter, mac, false,
-						       if_handle, *pmac_id);
-		}
-	} else if (be_physfn(adapter)) {
-		/* For BE3, for PF get permanent MAC */
-		status = be_cmd_mac_addr_query(adapter, mac, true, 0, 0);
-		*active_mac = false;
-	} else {
-		/* For BE3, for VF get soft MAC assigned by PF*/
-		status = be_cmd_mac_addr_query(adapter, mac, false,
-					       if_handle, 0);
-		*active_mac = true;
-	}
-	return status;
-}
-
 static void be_get_resources(struct be_adapter *adapter)
 {
 	u16 dev_num_vfs;
@@ -3022,13 +2996,6 @@ static void be_get_resources(struct be_adapter *adapter)
 	}
 
 	if (profile_present) {
-		/* Sanity fixes for Lancer */
-		adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt,
-					      BE_UC_PMAC_COUNT);
-		adapter->max_vlans = min_t(u16, adapter->max_vlans,
-					   BE_NUM_VLANS_SUPPORTED);
-		adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac,
-					       BE_MAX_MC);
 		adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues,
 					       MAX_TX_QS);
 		adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues,
@@ -3111,14 +3078,38 @@ err:
 	return status;
 }
 
+static int be_mac_setup(struct be_adapter *adapter)
+{
+	u8 mac[ETH_ALEN];
+	int status;
+
+	if (is_zero_ether_addr(adapter->netdev->dev_addr)) {
+		status = be_cmd_get_perm_mac(adapter, mac);
+		if (status)
+			return status;
+
+		memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
+		memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
+	} else {
+		/* Maybe the HW was reset; dev_addr must be re-programmed */
+		memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
+	}
+
+	/* On BE3 VFs this cmd may fail due to lack of privilege.
+	 * Ignore the failure as in this case pmac_id is fetched
+	 * in the IFACE_CREATE cmd.
+	 */
+	be_cmd_pmac_add(adapter, mac, adapter->if_handle,
+			&adapter->pmac_id[0], 0);
+	return 0;
+}
+
 static int be_setup(struct be_adapter *adapter)
 {
 	struct device *dev = &adapter->pdev->dev;
 	u32 en_flags;
 	u32 tx_fc, rx_fc;
 	int status;
-	u8 mac[ETH_ALEN];
-	bool active_mac;
 
 	be_setup_init(adapter);
 
@@ -3158,36 +3149,18 @@ static int be_setup(struct be_adapter *adapter)
 
 	en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
 			BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
-
 	if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
 		en_flags |= BE_IF_FLAGS_RSS;
-
 	en_flags = en_flags & adapter->if_cap_flags;
-
 	status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags,
 				  &adapter->if_handle, 0);
 	if (status != 0)
 		goto err;
 
-	memset(mac, 0, ETH_ALEN);
-	active_mac = false;
-	status = be_get_mac_addr(adapter, mac, adapter->if_handle,
-				 &active_mac, &adapter->pmac_id[0]);
-	if (status != 0)
+	status = be_mac_setup(adapter);
+	if (status)
 		goto err;
 
-	if (!active_mac) {
-		status = be_cmd_pmac_add(adapter, mac, adapter->if_handle,
-					 &adapter->pmac_id[0], 0);
-		if (status != 0)
-			goto err;
-	}
-
-	if (is_zero_ether_addr(adapter->netdev->dev_addr)) {
-		memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
-		memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
-	}
-
 	status = be_tx_qs_create(adapter);
 	if (status)
 		goto err;
@@ -3241,7 +3214,7 @@ static void be_netpoll(struct net_device *netdev)
 #endif
 
 #define FW_FILE_HDR_SIGN 	"ServerEngines Corp. "
-char flash_cookie[2][16] =      {"*** SE FLAS", "H DIRECTORY *** "};
+static char flash_cookie[2][16] =      {"*** SE FLAS", "H DIRECTORY *** "};
 
 static bool be_flash_redboot(struct be_adapter *adapter,
 			const u8 *p, u32 img_start, int image_size,
@@ -3298,7 +3271,7 @@ static bool is_comp_in_ufi(struct be_adapter *adapter,
 
 }
 
-struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
+static struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
 					 int header_size,
 					 const struct firmware *fw)
 {
@@ -4164,7 +4137,8 @@ static void be_worker(struct work_struct *work)
 			be_cmd_get_stats(adapter, &adapter->stats_cmd);
 	}
 
-	if (MODULO(adapter->work_counter, adapter->be_get_temp_freq) == 0)
+	if (be_physfn(adapter) &&
+	    MODULO(adapter->work_counter, adapter->be_get_temp_freq) == 0)
 		be_cmd_get_die_temperature(adapter);
 
 	for_all_rx_queues(adapter, rxo, i) {
@@ -4253,7 +4227,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
 
 	status = pci_enable_pcie_error_reporting(pdev);
 	if (status)
-		dev_err(&pdev->dev, "Could not use PCIe error reporting\n");
+		dev_info(&pdev->dev, "Could not use PCIe error reporting\n");
 
 	status = be_ctrl_init(adapter);
 	if (status)
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index f3d126d..645e846 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -93,7 +93,7 @@ void be_roce_dev_add(struct be_adapter *adapter)
 	}
 }
 
-void _be_roce_dev_remove(struct be_adapter *adapter)
+static void _be_roce_dev_remove(struct be_adapter *adapter)
 {
 	if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
 		ocrdma_drv->remove(adapter->ocrdma_dev);
@@ -110,7 +110,7 @@ void be_roce_dev_remove(struct be_adapter *adapter)
 	}
 }
 
-void _be_roce_dev_open(struct be_adapter *adapter)
+static void _be_roce_dev_open(struct be_adapter *adapter)
 {
 	if (ocrdma_drv && adapter->ocrdma_dev &&
 	    ocrdma_drv->state_change_handler)
@@ -126,7 +126,7 @@ void be_roce_dev_open(struct be_adapter *adapter)
 	}
 }
 
-void _be_roce_dev_close(struct be_adapter *adapter)
+static void _be_roce_dev_close(struct be_adapter *adapter)
 {
 	if (ocrdma_drv && adapter->ocrdma_dev &&
 	    ocrdma_drv->state_change_handler)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 77ea0db..fdf9307 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2056,10 +2056,6 @@ fec_probe(struct platform_device *pdev)
 	if (of_id)
 		pdev->id_entry = of_id->data;
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -ENXIO;
-
 	/* Init network device */
 	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
 	if (!ndev)
@@ -2077,6 +2073,7 @@ fec_probe(struct platform_device *pdev)
 		fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
 #endif
 
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	fep->hwp = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(fep->hwp)) {
 		ret = PTR_ERR(fep->hwp);
@@ -2126,10 +2123,25 @@ fec_probe(struct platform_device *pdev)
 		fep->bufdesc_ex = 0;
 	}
 
-	clk_prepare_enable(fep->clk_ahb);
-	clk_prepare_enable(fep->clk_ipg);
-	clk_prepare_enable(fep->clk_enet_out);
-	clk_prepare_enable(fep->clk_ptp);
+	ret = clk_prepare_enable(fep->clk_ahb);
+	if (ret)
+		goto failed_clk;
+
+	ret = clk_prepare_enable(fep->clk_ipg);
+	if (ret)
+		goto failed_clk_ipg;
+
+	if (fep->clk_enet_out) {
+		ret = clk_prepare_enable(fep->clk_enet_out);
+		if (ret)
+			goto failed_clk_enet_out;
+	}
+
+	if (fep->clk_ptp) {
+		ret = clk_prepare_enable(fep->clk_ptp);
+		if (ret)
+			goto failed_clk_ptp;
+	}
 
 	fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
 	if (!IS_ERR(fep->reg_phy)) {
@@ -2160,14 +2172,10 @@ fec_probe(struct platform_device *pdev)
 			ret = irq;
 			goto failed_irq;
 		}
-		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
-		if (ret) {
-			while (--i >= 0) {
-				irq = platform_get_irq(pdev, i);
-				free_irq(irq, ndev);
-			}
+		ret = devm_request_irq(&pdev->dev, irq, fec_enet_interrupt,
+				       IRQF_DISABLED, pdev->name, ndev);
+		if (ret)
 			goto failed_irq;
-		}
 	}
 
 	ret = fec_enet_mii_init(pdev);
@@ -2191,19 +2199,19 @@ failed_register:
 	fec_enet_mii_remove(fep);
 failed_mii_init:
 failed_irq:
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq > 0)
-			free_irq(irq, ndev);
-	}
 failed_init:
 	if (fep->reg_phy)
 		regulator_disable(fep->reg_phy);
 failed_regulator:
-	clk_disable_unprepare(fep->clk_ahb);
+	if (fep->clk_ptp)
+		clk_disable_unprepare(fep->clk_ptp);
+failed_clk_ptp:
+	if (fep->clk_enet_out)
+		clk_disable_unprepare(fep->clk_enet_out);
+failed_clk_enet_out:
 	clk_disable_unprepare(fep->clk_ipg);
-	clk_disable_unprepare(fep->clk_enet_out);
-	clk_disable_unprepare(fep->clk_ptp);
+failed_clk_ipg:
+	clk_disable_unprepare(fep->clk_ahb);
 failed_clk:
 failed_ioremap:
 	free_netdev(ndev);
@@ -2216,25 +2224,21 @@ fec_drv_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	int i;
 
 	cancel_delayed_work_sync(&(fep->delay_work.delay_work));
 	unregister_netdev(ndev);
 	fec_enet_mii_remove(fep);
 	del_timer_sync(&fep->time_keep);
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		int irq = platform_get_irq(pdev, i);
-		if (irq > 0)
-			free_irq(irq, ndev);
-	}
 	if (fep->reg_phy)
 		regulator_disable(fep->reg_phy);
-	clk_disable_unprepare(fep->clk_ptp);
+	if (fep->clk_ptp)
+		clk_disable_unprepare(fep->clk_ptp);
 	if (fep->ptp_clock)
 		ptp_clock_unregister(fep->ptp_clock);
-	clk_disable_unprepare(fep->clk_enet_out);
-	clk_disable_unprepare(fep->clk_ahb);
+	if (fep->clk_enet_out)
+		clk_disable_unprepare(fep->clk_enet_out);
 	clk_disable_unprepare(fep->clk_ipg);
+	clk_disable_unprepare(fep->clk_ahb);
 	free_netdev(ndev);
 
 	return 0;
@@ -2251,9 +2255,12 @@ fec_suspend(struct device *dev)
 		fec_stop(ndev);
 		netif_device_detach(ndev);
 	}
-	clk_disable_unprepare(fep->clk_enet_out);
-	clk_disable_unprepare(fep->clk_ahb);
+	if (fep->clk_ptp)
+		clk_disable_unprepare(fep->clk_ptp);
+	if (fep->clk_enet_out)
+		clk_disable_unprepare(fep->clk_enet_out);
 	clk_disable_unprepare(fep->clk_ipg);
+	clk_disable_unprepare(fep->clk_ahb);
 
 	if (fep->reg_phy)
 		regulator_disable(fep->reg_phy);
@@ -2274,15 +2281,44 @@ fec_resume(struct device *dev)
 			return ret;
 	}
 
-	clk_prepare_enable(fep->clk_enet_out);
-	clk_prepare_enable(fep->clk_ahb);
-	clk_prepare_enable(fep->clk_ipg);
+	ret = clk_prepare_enable(fep->clk_ahb);
+	if (ret)
+		goto failed_clk_ahb;
+
+	ret = clk_prepare_enable(fep->clk_ipg);
+	if (ret)
+		goto failed_clk_ipg;
+
+	if (fep->clk_enet_out) {
+		ret = clk_prepare_enable(fep->clk_enet_out);
+		if (ret)
+			goto failed_clk_enet_out;
+	}
+
+	if (fep->clk_ptp) {
+		ret = clk_prepare_enable(fep->clk_ptp);
+		if (ret)
+			goto failed_clk_ptp;
+	}
+
 	if (netif_running(ndev)) {
 		fec_restart(ndev, fep->full_duplex);
 		netif_device_attach(ndev);
 	}
 
 	return 0;
+
+failed_clk_ptp:
+	if (fep->clk_enet_out)
+		clk_disable_unprepare(fep->clk_enet_out);
+failed_clk_enet_out:
+	clk_disable_unprepare(fep->clk_ipg);
+failed_clk_ipg:
+	clk_disable_unprepare(fep->clk_ahb);
+failed_clk_ahb:
+	if (fep->reg_phy)
+		regulator_disable(fep->reg_phy);
+	return ret;
 }
 #endif /* CONFIG_PM_SLEEP */
 
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 8d2db7b..3cb4647 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -593,7 +593,6 @@ static int gfar_parse_group(struct device_node *np,
 			return -EINVAL;
 	}
 
-	grp->grp_id = priv->num_grps;
 	grp->priv = priv;
 	spin_lock_init(&grp->grplock);
 	if (priv->mode == MQ_MG_MODE) {
@@ -2052,6 +2051,24 @@ static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
 	return skip_txbd(bdp, 1, base, ring_size);
 }
 
+/* eTSEC12: csum generation not supported for some fcb offsets */
+static inline bool gfar_csum_errata_12(struct gfar_private *priv,
+				       unsigned long fcb_addr)
+{
+	return (gfar_has_errata(priv, GFAR_ERRATA_12) &&
+	       (fcb_addr % 0x20) > 0x18);
+}
+
+/* eTSEC76: csum generation for frames larger than 2500 may
+ * cause excess delays before start of transmission
+ */
+static inline bool gfar_csum_errata_76(struct gfar_private *priv,
+				       unsigned int len)
+{
+	return (gfar_has_errata(priv, GFAR_ERRATA_76) &&
+	       (len > 2500));
+}
+
 /* This is called by the kernel when a frame is ready for transmission.
  * It is pointed to by the dev->hard_start_xmit function pointer
  */
@@ -2064,23 +2081,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct txfcb *fcb = NULL;
 	struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL;
 	u32 lstatus;
-	int i, rq = 0, do_tstamp = 0;
+	int i, rq = 0;
+	int do_tstamp, do_csum, do_vlan;
 	u32 bufaddr;
 	unsigned long flags;
-	unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN;
-
-	/* TOE=1 frames larger than 2500 bytes may see excess delays
-	 * before start of transmission.
-	 */
-	if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_76) &&
-		     skb->ip_summed == CHECKSUM_PARTIAL &&
-		     skb->len > 2500)) {
-		int ret;
-
-		ret = skb_checksum_help(skb);
-		if (ret)
-			return ret;
-	}
+	unsigned int nr_frags, nr_txbds, length, fcb_len = 0;
 
 	rq = skb->queue_mapping;
 	tx_queue = priv->tx_queue[rq];
@@ -2088,21 +2093,23 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	base = tx_queue->tx_bd_base;
 	regs = tx_queue->grp->regs;
 
+	do_csum = (CHECKSUM_PARTIAL == skb->ip_summed);
+	do_vlan = vlan_tx_tag_present(skb);
+	do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+		    priv->hwts_tx_en;
+
+	if (do_csum || do_vlan)
+		fcb_len = GMAC_FCB_LEN;
+
 	/* check if time stamp should be generated */
-	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
-		     priv->hwts_tx_en)) {
-		do_tstamp = 1;
-		fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
-	}
+	if (unlikely(do_tstamp))
+		fcb_len = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 
 	/* make space for additional header when fcb is needed */
-	if (((skb->ip_summed == CHECKSUM_PARTIAL) ||
-	     vlan_tx_tag_present(skb) ||
-	     unlikely(do_tstamp)) &&
-	    (skb_headroom(skb) < fcb_length)) {
+	if (fcb_len && unlikely(skb_headroom(skb) < fcb_len)) {
 		struct sk_buff *skb_new;
 
-		skb_new = skb_realloc_headroom(skb, fcb_length);
+		skb_new = skb_realloc_headroom(skb, fcb_len);
 		if (!skb_new) {
 			dev->stats.tx_errors++;
 			kfree_skb(skb);
@@ -2185,36 +2192,38 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		memset(skb->data, 0, GMAC_TXPAL_LEN);
 	}
 
-	/* Set up checksumming */
-	if (CHECKSUM_PARTIAL == skb->ip_summed) {
+	/* Add TxFCB if required */
+	if (fcb_len) {
 		fcb = gfar_add_fcb(skb);
-		/* as specified by errata */
-		if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12) &&
-			     ((unsigned long)fcb % 0x20) > 0x18)) {
+		lstatus |= BD_LFLAG(TXBD_TOE);
+	}
+
+	/* Set up checksumming */
+	if (do_csum) {
+		gfar_tx_checksum(skb, fcb, fcb_len);
+
+		if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
+		    unlikely(gfar_csum_errata_76(priv, skb->len))) {
 			__skb_pull(skb, GMAC_FCB_LEN);
 			skb_checksum_help(skb);
-		} else {
-			lstatus |= BD_LFLAG(TXBD_TOE);
-			gfar_tx_checksum(skb, fcb, fcb_length);
+			if (do_vlan || do_tstamp) {
+				/* put back a new fcb for vlan/tstamp TOE */
+				fcb = gfar_add_fcb(skb);
+			} else {
+				/* Tx TOE not used */
+				lstatus &= ~(BD_LFLAG(TXBD_TOE));
+				fcb = NULL;
+			}
 		}
 	}
 
-	if (vlan_tx_tag_present(skb)) {
-		if (unlikely(NULL == fcb)) {
-			fcb = gfar_add_fcb(skb);
-			lstatus |= BD_LFLAG(TXBD_TOE);
-		}
-
+	if (do_vlan)
 		gfar_tx_vlan(skb, fcb);
-	}
 
 	/* Setup tx hardware time stamping if requested */
 	if (unlikely(do_tstamp)) {
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
-		if (fcb == NULL)
-			fcb = gfar_add_fcb(skb);
 		fcb->ptp = 1;
-		lstatus |= BD_LFLAG(TXBD_TOE);
 	}
 
 	txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
@@ -2226,9 +2235,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	 * the full frame length.
 	 */
 	if (unlikely(do_tstamp)) {
-		txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length;
+		txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_len;
 		txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) |
-					 (skb_headlen(skb) - fcb_length);
+					 (skb_headlen(skb) - fcb_len);
 		lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN;
 	} else {
 		lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 04b552c..ee19f2c 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1009,7 +1009,6 @@ struct gfar_irqinfo {
  *	@napi: the napi poll function
  *	@priv: back pointer to the priv structure
  *	@regs: the ioremapped register space for this group
- *	@grp_id: group id for this group
  *	@irqinfo: TX/RX/ER irq data for this group
  */
 
@@ -1018,11 +1017,10 @@ struct gfar_priv_grp {
 	struct	napi_struct napi;
 	struct gfar_private *priv;
 	struct gfar __iomem *regs;
-	unsigned int grp_id;
+	unsigned int rstat;
 	unsigned long num_rx_queues;
 	unsigned long rx_bit_map;
 	/* cacheline 3 */
-	unsigned int rstat;
 	unsigned int tstat;
 	unsigned long num_tx_queues;
 	unsigned long tx_bit_map;
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.h b/drivers/net/ethernet/i825xx/sun3_82586.h
index 93346f0..79aef68 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.h
+++ b/drivers/net/ethernet/i825xx/sun3_82586.h
@@ -133,8 +133,8 @@ struct rfd_struct
   unsigned char  last;		/* Bit15,Last Frame on List / Bit14,suspend */
   unsigned short next;		/* linkoffset to next RFD */
   unsigned short rbd_offset;	/* pointeroffset to RBD-buffer */
-  unsigned char  dest[6];	/* ethernet-address, destination */
-  unsigned char  source[6];	/* ethernet-address, source */
+  unsigned char  dest[ETH_ALEN];	/* ethernet-address, destination */
+  unsigned char  source[ETH_ALEN];	/* ethernet-address, source */
   unsigned short length;	/* 802.3 frame-length */
   unsigned short zero_dummy;	/* dummy */
 };
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 35853b4..741f11e 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -102,6 +102,19 @@ static int ehea_probe_adapter(struct platform_device *dev);
 
 static int ehea_remove(struct platform_device *dev);
 
+static struct of_device_id ehea_module_device_table[] = {
+	{
+		.name = "lhea",
+		.compatible = "IBM,lhea",
+	},
+	{
+		.type = "network",
+		.compatible = "IBM,lhea-ethernet",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehea_module_device_table);
+
 static struct of_device_id ehea_device_table[] = {
 	{
 		.name = "lhea",
@@ -109,7 +122,6 @@ static struct of_device_id ehea_device_table[] = {
 	},
 	{},
 };
-MODULE_DEVICE_TABLE(of, ehea_device_table);
 
 static struct platform_driver ehea_driver = {
 	.driver = {
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 5115ae7..ada6e21 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -1175,15 +1175,12 @@ static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 		config->rx_discard_short_frames = 0x0;  /* 1=discard, 0=save */
 	}
 
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		     c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		     c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		     c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
+	netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "[00-07]=%8ph\n",
+		     c + 0);
+	netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "[08-15]=%8ph\n",
+		     c + 8);
+	netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "[16-23]=%8ph\n",
+		     c + 16);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index 4c303e2..104fcec 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -2057,6 +2057,7 @@ const struct e1000_info e1000_82583_info = {
 				  | FLAG_HAS_JUMBO_FRAMES
 				  | FLAG_HAS_CTRLEXT_ON_LOAD,
 	.flags2			= FLAG2_DISABLE_ASPM_L0S
+				  | FLAG2_DISABLE_ASPM_L1
 				  | FLAG2_NO_DISABLE_RX,
 	.pba			= 32,
 	.max_hw_frame_size	= DEFAULT_JUMBO,
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index ffbc08f..ad0edd1 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -90,9 +90,6 @@ struct e1000_info;
 
 #define E1000_MNG_VLAN_NONE		(-1)
 
-/* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS			(MAX_PS_BUFFERS - 1)
-
 #define DEFAULT_JUMBO			9234
 
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 59c22bf..e4ebd7d 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -173,7 +173,7 @@ static int e1000_get_settings(struct net_device *netdev,
 			speed = adapter->link_speed;
 			ecmd->duplex = adapter->link_duplex - 1;
 		}
-	} else {
+	} else if (!pm_runtime_suspended(netdev->dev.parent)) {
 		u32 status = er32(STATUS);
 		if (status & E1000_STATUS_LU) {
 			if (status & E1000_STATUS_SPEED_1000)
@@ -264,6 +264,9 @@ static int e1000_set_settings(struct net_device *netdev,
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	int ret_val = 0;
+
+	pm_runtime_get_sync(netdev->dev.parent);
 
 	/* When SoL/IDER sessions are active, autoneg/speed/duplex
 	 * cannot be changed
@@ -271,7 +274,8 @@ static int e1000_set_settings(struct net_device *netdev,
 	if (hw->phy.ops.check_reset_block &&
 	    hw->phy.ops.check_reset_block(hw)) {
 		e_err("Cannot change link characteristics when SoL/IDER is active.\n");
-		return -EINVAL;
+		ret_val = -EINVAL;
+		goto out;
 	}
 
 	/* MDI setting is only allowed when autoneg enabled because
@@ -279,13 +283,16 @@ static int e1000_set_settings(struct net_device *netdev,
 	 * duplex is forced.
 	 */
 	if (ecmd->eth_tp_mdix_ctrl) {
-		if (hw->phy.media_type != e1000_media_type_copper)
-			return -EOPNOTSUPP;
+		if (hw->phy.media_type != e1000_media_type_copper) {
+			ret_val = -EOPNOTSUPP;
+			goto out;
+		}
 
 		if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
 		    (ecmd->autoneg != AUTONEG_ENABLE)) {
 			e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
-			return -EINVAL;
+			ret_val = -EINVAL;
+			goto out;
 		}
 	}
 
@@ -307,8 +314,8 @@ static int e1000_set_settings(struct net_device *netdev,
 		u32 speed = ethtool_cmd_speed(ecmd);
 		/* calling this overrides forced MDI setting */
 		if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
-			clear_bit(__E1000_RESETTING, &adapter->state);
-			return -EINVAL;
+			ret_val = -EINVAL;
+			goto out;
 		}
 	}
 
@@ -331,8 +338,10 @@ static int e1000_set_settings(struct net_device *netdev,
 		e1000e_reset(adapter);
 	}
 
+out:
+	pm_runtime_put_sync(netdev->dev.parent);
 	clear_bit(__E1000_RESETTING, &adapter->state);
-	return 0;
+	return ret_val;
 }
 
 static void e1000_get_pauseparam(struct net_device *netdev,
@@ -366,6 +375,8 @@ static int e1000_set_pauseparam(struct net_device *netdev,
 	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
 		usleep_range(1000, 2000);
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
 		hw->fc.requested_mode = e1000_fc_default;
 		if (netif_running(adapter->netdev)) {
@@ -398,6 +409,7 @@ static int e1000_set_pauseparam(struct net_device *netdev,
 	}
 
 out:
+	pm_runtime_put_sync(netdev->dev.parent);
 	clear_bit(__E1000_RESETTING, &adapter->state);
 	return retval;
 }
@@ -428,6 +440,8 @@ static void e1000_get_regs(struct net_device *netdev,
 	u32 *regs_buff = p;
 	u16 phy_data;
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
 
 	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
@@ -472,6 +486,8 @@ static void e1000_get_regs(struct net_device *netdev,
 	e1e_rphy(hw, MII_STAT1000, &phy_data);
 	regs_buff[24] = (u32)phy_data;	/* phy local receiver status */
 	regs_buff[25] = regs_buff[24];	/* phy remote receiver status */
+
+	pm_runtime_put_sync(netdev->dev.parent);
 }
 
 static int e1000_get_eeprom_len(struct net_device *netdev)
@@ -504,6 +520,8 @@ static int e1000_get_eeprom(struct net_device *netdev,
 	if (!eeprom_buff)
 		return -ENOMEM;
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
 		ret_val = e1000_read_nvm(hw, first_word,
 					 last_word - first_word + 1,
@@ -517,6 +535,8 @@ static int e1000_get_eeprom(struct net_device *netdev,
 		}
 	}
 
+	pm_runtime_put_sync(netdev->dev.parent);
+
 	if (ret_val) {
 		/* a read error occurred, throw away the result */
 		memset(eeprom_buff, 0xff, sizeof(u16) *
@@ -566,6 +586,8 @@ static int e1000_set_eeprom(struct net_device *netdev,
 
 	ptr = (void *)eeprom_buff;
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	if (eeprom->offset & 1) {
 		/* need read/modify/write of first changed EEPROM word */
 		/* only the second byte of the word is being modified */
@@ -606,6 +628,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
 		ret_val = e1000e_update_nvm_checksum(hw);
 
 out:
+	pm_runtime_put_sync(netdev->dev.parent);
 	kfree(eeprom_buff);
 	return ret_val;
 }
@@ -701,6 +724,8 @@ static int e1000_set_ringparam(struct net_device *netdev,
 		}
 	}
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	e1000e_down(adapter);
 
 	/* We can't just free everything and then setup again, because the
@@ -739,6 +764,7 @@ err_setup_rx:
 		e1000e_free_tx_resources(temp_tx);
 err_setup:
 	e1000e_up(adapter);
+	pm_runtime_put_sync(netdev->dev.parent);
 free_temp:
 	vfree(temp_tx);
 	vfree(temp_rx);
@@ -1732,6 +1758,8 @@ static void e1000_diag_test(struct net_device *netdev,
 	u8 autoneg;
 	bool if_running = netif_running(netdev);
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	set_bit(__E1000_TESTING, &adapter->state);
 
 	if (!if_running) {
@@ -1817,6 +1845,8 @@ static void e1000_diag_test(struct net_device *netdev,
 	}
 
 	msleep_interruptible(4 * 1000);
+
+	pm_runtime_put_sync(netdev->dev.parent);
 }
 
 static void e1000_get_wol(struct net_device *netdev,
@@ -1891,6 +1921,8 @@ static int e1000_set_phys_id(struct net_device *netdev,
 
 	switch (state) {
 	case ETHTOOL_ID_ACTIVE:
+		pm_runtime_get_sync(netdev->dev.parent);
+
 		if (!hw->mac.ops.blink_led)
 			return 2;	/* cycle on/off twice per second */
 
@@ -1902,6 +1934,7 @@ static int e1000_set_phys_id(struct net_device *netdev,
 			e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
 		hw->mac.ops.led_off(hw);
 		hw->mac.ops.cleanup_led(hw);
+		pm_runtime_put_sync(netdev->dev.parent);
 		break;
 
 	case ETHTOOL_ID_ON:
@@ -1912,6 +1945,7 @@ static int e1000_set_phys_id(struct net_device *netdev,
 		hw->mac.ops.led_off(hw);
 		break;
 	}
+
 	return 0;
 }
 
@@ -1950,11 +1984,15 @@ static int e1000_set_coalesce(struct net_device *netdev,
 		adapter->itr_setting = adapter->itr & ~3;
 	}
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	if (adapter->itr_setting != 0)
 		e1000e_write_itr(adapter, adapter->itr);
 	else
 		e1000e_write_itr(adapter, 0);
 
+	pm_runtime_put_sync(netdev->dev.parent);
+
 	return 0;
 }
 
@@ -1968,7 +2006,9 @@ static int e1000_nway_reset(struct net_device *netdev)
 	if (!adapter->hw.mac.autoneg)
 		return -EINVAL;
 
+	pm_runtime_get_sync(netdev->dev.parent);
 	e1000e_reinit_locked(adapter);
+	pm_runtime_put_sync(netdev->dev.parent);
 
 	return 0;
 }
@@ -1982,7 +2022,12 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
 	int i;
 	char *p = NULL;
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	e1000e_get_stats64(netdev, &net_stats);
+
+	pm_runtime_put_sync(netdev->dev.parent);
+
 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
 		switch (e1000_gstrings_stats[i].type) {
 		case NETDEV_STATS:
@@ -2033,7 +2078,11 @@ static int e1000_get_rxnfc(struct net_device *netdev,
 	case ETHTOOL_GRXFH: {
 		struct e1000_adapter *adapter = netdev_priv(netdev);
 		struct e1000_hw *hw = &adapter->hw;
-		u32 mrqc = er32(MRQC);
+		u32 mrqc;
+
+		pm_runtime_get_sync(netdev->dev.parent);
+		mrqc = er32(MRQC);
+		pm_runtime_put_sync(netdev->dev.parent);
 
 		if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK))
 			return 0;
@@ -2096,9 +2145,13 @@ static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
 		return -EOPNOTSUPP;
 	}
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
+	if (ret_val) {
+		pm_runtime_put_sync(netdev->dev.parent);
 		return -EBUSY;
+	}
 
 	/* EEE Capability */
 	ret_val = e1000_read_emi_reg_locked(hw, cap_addr, &phy_data);
@@ -2117,14 +2170,11 @@ static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
 
 	/* EEE PCS Status */
 	ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data);
+	if (ret_val)
+		goto release;
 	if (hw->phy.type == e1000_phy_82579)
 		phy_data <<= 8;
 
-release:
-	hw->phy.ops.release(hw);
-	if (ret_val)
-		return -ENODATA;
-
 	/* Result of the EEE auto negotiation - there is no register that
 	 * has the status of the EEE negotiation so do a best-guess based
 	 * on whether Tx or Rx LPI indications have been received.
@@ -2136,7 +2186,14 @@ release:
 	edata->tx_lpi_enabled = true;
 	edata->tx_lpi_timer = er32(LPIC) >> E1000_LPIC_LPIET_SHIFT;
 
-	return 0;
+release:
+	hw->phy.ops.release(hw);
+	if (ret_val)
+		ret_val = -ENODATA;
+
+	pm_runtime_put_sync(netdev->dev.parent);
+
+	return ret_val;
 }
 
 static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
@@ -2169,12 +2226,16 @@ static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
 
 	hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled;
 
+	pm_runtime_get_sync(netdev->dev.parent);
+
 	/* reset the link */
 	if (netif_running(netdev))
 		e1000e_reinit_locked(adapter);
 	else
 		e1000e_reset(adapter);
 
+	pm_runtime_put_sync(netdev->dev.parent);
+
 	return 0;
 }
 
@@ -2212,19 +2273,7 @@ static int e1000e_get_ts_info(struct net_device *netdev,
 	return 0;
 }
 
-static int e1000e_ethtool_begin(struct net_device *netdev)
-{
-	return pm_runtime_get_sync(netdev->dev.parent);
-}
-
-static void e1000e_ethtool_complete(struct net_device *netdev)
-{
-	pm_runtime_put_sync(netdev->dev.parent);
-}
-
 static const struct ethtool_ops e1000_ethtool_ops = {
-	.begin			= e1000e_ethtool_begin,
-	.complete		= e1000e_ethtool_complete,
 	.get_settings		= e1000_get_settings,
 	.set_settings		= e1000_set_settings,
 	.get_drvinfo		= e1000_get_drvinfo,
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index a6f903a..b799fd9 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -90,6 +90,10 @@ struct e1000_hw;
 #define E1000_DEV_ID_PCH_LPT_I217_V		0x153B
 #define E1000_DEV_ID_PCH_LPTLP_I218_LM		0x155A
 #define E1000_DEV_ID_PCH_LPTLP_I218_V		0x1559
+#define E1000_DEV_ID_PCH_I218_LM2		0x15A0
+#define E1000_DEV_ID_PCH_I218_V2		0x15A1
+#define E1000_DEV_ID_PCH_I218_LM3		0x15A2	/* Wildcat Point PCH */
+#define E1000_DEV_ID_PCH_I218_V3		0x15A3	/* Wildcat Point PCH */
 
 #define E1000_REVISION_4	4
 
@@ -227,6 +231,9 @@ union e1000_rx_desc_extended {
 };
 
 #define MAX_PS_BUFFERS 4
+
+/* Number of packet split data buffers (not including the header buffer) */
+#define PS_PAGE_BUFFERS			(MAX_PS_BUFFERS - 1)
 /* Receive Descriptor - Packet Split */
 union e1000_rx_desc_packet_split {
 	struct {
@@ -251,7 +258,8 @@ union e1000_rx_desc_packet_split {
 		} middle;
 		struct {
 			__le16 header_status;
-			__le16 length[3];	/* length of buffers 1-3 */
+			/* length of buffers 1-3 */
+			__le16 length[PS_PAGE_BUFFERS];
 		} upper;
 		__le64 reserved;
 	} wb; /* writeback */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 9dde390..af08188 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -185,6 +185,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
 	u32 phy_id = 0;
 	s32 ret_val;
 	u16 retry_count;
+	u32 mac_reg = 0;
 
 	for (retry_count = 0; retry_count < 2; retry_count++) {
 		ret_val = e1e_rphy_locked(hw, MII_PHYSID1, &phy_reg);
@@ -203,11 +204,11 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
 
 	if (hw->phy.id) {
 		if (hw->phy.id == phy_id)
-			return true;
+			goto out;
 	} else if (phy_id) {
 		hw->phy.id = phy_id;
 		hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK);
-		return true;
+		goto out;
 	}
 
 	/* In case the PHY needs to be in mdio slow mode,
@@ -219,7 +220,22 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
 		ret_val = e1000e_get_phy_id(hw);
 	hw->phy.ops.acquire(hw);
 
-	return !ret_val;
+	if (ret_val)
+		return false;
+out:
+	if (hw->mac.type == e1000_pch_lpt) {
+		/* Unforce SMBus mode in PHY */
+		e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
+		phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+		e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
+
+		/* Unforce SMBus mode in MAC */
+		mac_reg = er32(CTRL_EXT);
+		mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+		ew32(CTRL_EXT, mac_reg);
+	}
+
+	return true;
 }
 
 /**
@@ -233,7 +249,6 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 {
 	u32 mac_reg, fwsm = er32(FWSM);
 	s32 ret_val;
-	u16 phy_reg;
 
 	/* Gate automatic PHY configuration by hardware on managed and
 	 * non-managed 82579 and newer adapters.
@@ -262,22 +277,16 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 		mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
 		ew32(CTRL_EXT, mac_reg);
 
+		/* Wait 50 milliseconds for MAC to finish any retries
+		 * that it might be trying to perform from previous
+		 * attempts to acknowledge any phy read requests.
+		 */
+		msleep(50);
+
 		/* fall-through */
 	case e1000_pch2lan:
-		if (e1000_phy_is_accessible_pchlan(hw)) {
-			if (hw->mac.type == e1000_pch_lpt) {
-				/* Unforce SMBus mode in PHY */
-				e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
-				phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
-				e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
-
-				/* Unforce SMBus mode in MAC */
-				mac_reg = er32(CTRL_EXT);
-				mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
-				ew32(CTRL_EXT, mac_reg);
-			}
+		if (e1000_phy_is_accessible_pchlan(hw))
 			break;
-		}
 
 		/* fall-through */
 	case e1000_pchlan:
@@ -287,6 +296,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 
 		if (hw->phy.ops.check_reset_block(hw)) {
 			e_dbg("Required LANPHYPC toggle blocked by ME\n");
+			ret_val = -E1000_ERR_PHY;
 			break;
 		}
 
@@ -298,15 +308,6 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 		mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
 		ew32(FEXTNVM3, mac_reg);
 
-		if (hw->mac.type == e1000_pch_lpt) {
-			/* Toggling LANPHYPC brings the PHY out of SMBus mode
-			 * So ensure that the MAC is also out of SMBus mode
-			 */
-			mac_reg = er32(CTRL_EXT);
-			mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
-			ew32(CTRL_EXT, mac_reg);
-		}
-
 		/* Toggle LANPHYPC Value bit */
 		mac_reg = er32(CTRL);
 		mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
@@ -325,6 +326,21 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 				usleep_range(5000, 10000);
 			} while (!(er32(CTRL_EXT) &
 				   E1000_CTRL_EXT_LPCD) && count--);
+			usleep_range(30000, 60000);
+			if (e1000_phy_is_accessible_pchlan(hw))
+				break;
+
+			/* Toggling LANPHYPC brings the PHY out of SMBus mode
+			 * so ensure that the MAC is also out of SMBus mode
+			 */
+			mac_reg = er32(CTRL_EXT);
+			mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+			ew32(CTRL_EXT, mac_reg);
+
+			if (e1000_phy_is_accessible_pchlan(hw))
+				break;
+
+			ret_val = -E1000_ERR_PHY;
 		}
 		break;
 	default:
@@ -332,13 +348,14 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 	}
 
 	hw->phy.ops.release(hw);
-
-	/* Reset the PHY before any access to it.  Doing so, ensures
-	 * that the PHY is in a known good state before we read/write
-	 * PHY registers.  The generic reset is sufficient here,
-	 * because we haven't determined the PHY type yet.
-	 */
-	ret_val = e1000e_phy_hw_reset_generic(hw);
+	if (!ret_val) {
+		/* Reset the PHY before any access to it.  Doing so, ensures
+		 * that the PHY is in a known good state before we read/write
+		 * PHY registers.  The generic reset is sufficient here,
+		 * because we haven't determined the PHY type yet.
+		 */
+		ret_val = e1000e_phy_hw_reset_generic(hw);
+	}
 
 out:
 	/* Ungate automatic PHY configuration on non-managed 82579 */
@@ -793,29 +810,31 @@ release:
  *  When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
  *  preventing further DMA write requests.  Workaround the issue by disabling
  *  the de-assertion of the clock request when in 1Gpbs mode.
+ *  Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link
+ *  speeds in order to avoid Tx hangs.
  **/
 static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
 {
 	u32 fextnvm6 = er32(FEXTNVM6);
+	u32 status = er32(STATUS);
 	s32 ret_val = 0;
+	u16 reg;
 
-	if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) {
-		u16 kmrn_reg;
-
+	if (link && (status & E1000_STATUS_SPEED_1000)) {
 		ret_val = hw->phy.ops.acquire(hw);
 		if (ret_val)
 			return ret_val;
 
 		ret_val =
 		    e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
-						&kmrn_reg);
+						&reg);
 		if (ret_val)
 			goto release;
 
 		ret_val =
 		    e1000e_write_kmrn_reg_locked(hw,
 						 E1000_KMRNCTRLSTA_K1_CONFIG,
-						 kmrn_reg &
+						 reg &
 						 ~E1000_KMRNCTRLSTA_K1_ENABLE);
 		if (ret_val)
 			goto release;
@@ -827,12 +846,45 @@ static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
 		ret_val =
 		    e1000e_write_kmrn_reg_locked(hw,
 						 E1000_KMRNCTRLSTA_K1_CONFIG,
-						 kmrn_reg);
+						 reg);
 release:
 		hw->phy.ops.release(hw);
 	} else {
 		/* clear FEXTNVM6 bit 8 on link down or 10/100 */
-		ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+		fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
+
+		if (!link || ((status & E1000_STATUS_SPEED_100) &&
+			      (status & E1000_STATUS_FD)))
+			goto update_fextnvm6;
+
+		ret_val = e1e_rphy(hw, I217_INBAND_CTRL, &reg);
+		if (ret_val)
+			return ret_val;
+
+		/* Clear link status transmit timeout */
+		reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK;
+
+		if (status & E1000_STATUS_SPEED_100) {
+			/* Set inband Tx timeout to 5x10us for 100Half */
+			reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
+
+			/* Do not extend the K1 entry latency for 100Half */
+			fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
+		} else {
+			/* Set inband Tx timeout to 50x10us for 10Full/Half */
+			reg |= 50 <<
+			    I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
+
+			/* Extend the K1 entry latency for 10 Mbps */
+			fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
+		}
+
+		ret_val = e1e_wphy(hw, I217_INBAND_CTRL, reg);
+		if (ret_val)
+			return ret_val;
+
+update_fextnvm6:
+		ew32(FEXTNVM6, fextnvm6);
 	}
 
 	return ret_val;
@@ -993,7 +1045,9 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 
 	/* Work-around I218 hang issue */
 	if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
-	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
+	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM3) ||
+	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) {
 		ret_val = e1000_k1_workaround_lpt_lp(hw, link);
 		if (ret_val)
 			return ret_val;
@@ -4168,7 +4222,9 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
 		u16 phy_reg, device_id = hw->adapter->pdev->device;
 
 		if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
-		    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+		    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
+		    (device_id == E1000_DEV_ID_PCH_I218_LM3) ||
+		    (device_id == E1000_DEV_ID_PCH_I218_V3)) {
 			u32 fextnvm6 = er32(FEXTNVM6);
 
 			ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h
index 80034a2..5986569 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
@@ -93,6 +93,7 @@
 #define E1000_FEXTNVM4_BEACON_DURATION_16USEC	0x3
 
 #define E1000_FEXTNVM6_REQ_PLL_CLK	0x00000100
+#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION	0x00000200
 
 #define PCIE_ICH8_SNOOP_ALL	PCIE_NO_SNOOP_ALL
 
@@ -197,6 +198,11 @@
 
 #define SW_FLAG_TIMEOUT		1000	/* SW Semaphore flag timeout in ms */
 
+/* Inband Control */
+#define I217_INBAND_CTRL				PHY_REG(770, 18)
+#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK	0x3F00
+#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT	8
+
 /* PHY Low Power Idle Control */
 #define I82579_LPI_CTRL				PHY_REG(772, 20)
 #define I82579_LPI_CTRL_100_ENABLE		0x2000
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 77f81cb..e6d2c0f 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2979,17 +2979,10 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 	u32 pages = 0;
 
 	/* Workaround Si errata on PCHx - configure jumbo frame flow */
-	if (hw->mac.type >= e1000_pch2lan) {
-		s32 ret_val;
-
-		if (adapter->netdev->mtu > ETH_DATA_LEN)
-			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
-		else
-			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
-
-		if (ret_val)
-			e_dbg("failed to enable jumbo frame workaround mode\n");
-	}
+	if ((hw->mac.type >= e1000_pch2lan) &&
+	    (adapter->netdev->mtu > ETH_DATA_LEN) &&
+	    e1000_lv_jumbo_workaround_ich8lan(hw, true))
+		e_dbg("failed to enable jumbo frame workaround mode\n");
 
 	/* Program MC offset vector base */
 	rctl = er32(RCTL);
@@ -3826,6 +3819,8 @@ void e1000e_reset(struct e1000_adapter *adapter)
 			break;
 		}
 
+		pba = 14;
+		ew32(PBA, pba);
 		fc->high_water = ((pba << 10) * 9 / 10) & E1000_FCRTH_RTH;
 		fc->low_water = ((pba << 10) * 8 / 10) & E1000_FCRTL_RTL;
 		break;
@@ -4034,6 +4029,12 @@ void e1000e_down(struct e1000_adapter *adapter)
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 
+	/* Disable Si errata workaround on PCHx for jumbo frame flow */
+	if ((hw->mac.type >= e1000_pch2lan) &&
+	    (adapter->netdev->mtu > ETH_DATA_LEN) &&
+	    e1000_lv_jumbo_workaround_ich8lan(hw, false))
+		e_dbg("failed to disable jumbo frame workaround mode\n");
+
 	if (!pci_channel_offline(adapter->pdev))
 		e1000e_reset(adapter);
 
@@ -4683,11 +4684,11 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_phy_regs *phy = &adapter->phy_regs;
 
-	if ((er32(STATUS) & E1000_STATUS_LU) &&
+	if (!pm_runtime_suspended((&adapter->pdev->dev)->parent) &&
+	    (er32(STATUS) & E1000_STATUS_LU) &&
 	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
 		int ret_val;
 
-		pm_runtime_get_sync(&adapter->pdev->dev);
 		ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr);
 		ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr);
 		ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise);
@@ -4698,7 +4699,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
 		ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus);
 		if (ret_val)
 			e_warn("Error reading PHY register\n");
-		pm_runtime_put_sync(&adapter->pdev->dev);
 	} else {
 		/* Do not read PHY registers if link is not up
 		 * Set values to typical power-on defaults
@@ -5995,6 +5995,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 	 */
 	e1000e_release_hw_control(adapter);
 
+	pci_clear_master(pdev);
+
 	/* The pci-e switch on some quad port adapters will report a
 	 * correctable error when the MAC transitions from D0 to D3.  To
 	 * prevent this we need to mask off the correctable errors on the
@@ -6723,10 +6725,6 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	adapter->hw.fc.current_mode = e1000_fc_default;
 	adapter->hw.phy.autoneg_advertised = 0x2f;
 
-	/* ring size defaults */
-	adapter->rx_ring->count = E1000_DEFAULT_RXD;
-	adapter->tx_ring->count = E1000_DEFAULT_TXD;
-
 	/* Initial Wake on LAN setting - If APM wake is enabled in
 	 * the EEPROM, enable the ACPI Magic Packet filter
 	 */
@@ -6976,6 +6974,10 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_LM), board_pch_lpt },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_V), board_pch_lpt },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM2), board_pch_lpt },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V2), board_pch_lpt },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM3), board_pch_lpt },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V3), board_pch_lpt },
 
 	{ 0, 0, 0, 0, 0, 0, 0 }	/* terminate list */
 };
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index a6494e5..0ac6b11 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -618,9 +618,8 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG2_FDIR_REQUIRES_REINIT        (u32)(1 << 7)
 #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP		(u32)(1 << 8)
 #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP		(u32)(1 << 9)
-#define IXGBE_FLAG2_PTP_ENABLED			(u32)(1 << 10)
-#define IXGBE_FLAG2_PTP_PPS_ENABLED		(u32)(1 << 11)
-#define IXGBE_FLAG2_BRIDGE_MODE_VEB		(u32)(1 << 12)
+#define IXGBE_FLAG2_PTP_PPS_ENABLED		(u32)(1 << 10)
+#define IXGBE_FLAG2_BRIDGE_MODE_VEB		(u32)(1 << 11)
 
 	/* Tx fast path data */
 	int num_tx_queues;
@@ -754,7 +753,7 @@ enum ixgbe_state_t {
 	__IXGBE_DOWN,
 	__IXGBE_SERVICE_SCHED,
 	__IXGBE_IN_SFP_INIT,
-	__IXGBE_READ_I2C,
+	__IXGBE_PTP_RUNNING,
 };
 
 struct ixgbe_cb {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 4a5bfb6..a26f3fe 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -1018,8 +1018,17 @@ static s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr,
 	u16 sfp_addr = 0;
 	u16 sfp_data = 0;
 	u16 sfp_stat = 0;
+	u16 gssr;
 	u32 i;
 
+	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+		gssr = IXGBE_GSSR_PHY1_SM;
+	else
+		gssr = IXGBE_GSSR_PHY0_SM;
+
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
+		return IXGBE_ERR_SWFW_SYNC;
+
 	if (hw->phy.type == ixgbe_phy_nl) {
 		/*
 		 * phy SDA/SCL registers are at addresses 0xC30A to
@@ -1028,17 +1037,17 @@ static s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr,
 		 */
 		sfp_addr = (dev_addr << 8) + byte_offset;
 		sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
-		hw->phy.ops.write_reg(hw,
-		                      IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
-		                      MDIO_MMD_PMAPMD,
-		                      sfp_addr);
+		hw->phy.ops.write_reg_mdi(hw,
+					  IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
+					  MDIO_MMD_PMAPMD,
+					  sfp_addr);
 
 		/* Poll status */
 		for (i = 0; i < 100; i++) {
-			hw->phy.ops.read_reg(hw,
-			                     IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
-			                     MDIO_MMD_PMAPMD,
-			                     &sfp_stat);
+			hw->phy.ops.read_reg_mdi(hw,
+						IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
+						MDIO_MMD_PMAPMD,
+						&sfp_stat);
 			sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
 			if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
 				break;
@@ -1052,8 +1061,8 @@ static s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr,
 		}
 
 		/* Read data */
-		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
-		                     MDIO_MMD_PMAPMD, &sfp_data);
+		hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
+					MDIO_MMD_PMAPMD, &sfp_data);
 
 		*eeprom_data = (u8)(sfp_data >> 8);
 	} else {
@@ -1061,6 +1070,7 @@ static s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr,
 	}
 
 out:
+	hw->mac.ops.release_swfw_sync(hw, gssr);
 	return status;
 }
 
@@ -1321,11 +1331,13 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
 
 static struct ixgbe_phy_operations phy_ops_82598 = {
 	.identify		= &ixgbe_identify_phy_generic,
-	.identify_sfp		= &ixgbe_identify_sfp_module_generic,
+	.identify_sfp		= &ixgbe_identify_module_generic,
 	.init			= &ixgbe_init_phy_ops_82598,
 	.reset			= &ixgbe_reset_phy_generic,
 	.read_reg		= &ixgbe_read_phy_reg_generic,
 	.write_reg		= &ixgbe_write_phy_reg_generic,
+	.read_reg_mdi		= &ixgbe_read_phy_reg_mdi,
+	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
 	.setup_link		= &ixgbe_setup_phy_link_generic,
 	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic,
 	.read_i2c_sff8472	= &ixgbe_read_i2c_sff8472_82598,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 0b82d38..207f68f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -58,6 +58,10 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                          ixgbe_link_speed speed,
                                          bool autoneg_wait_to_complete);
 static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
+static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+				     u8 dev_addr, u8 *data);
+static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+				      u8 dev_addr, u8 data);
 
 static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
 {
@@ -219,6 +223,25 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
 	struct ixgbe_mac_info *mac = &hw->mac;
 	struct ixgbe_phy_info *phy = &hw->phy;
 	s32 ret_val = 0;
+	u32 esdp;
+
+	if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
+		/* Store flag indicating I2C bus access control unit. */
+		hw->phy.qsfp_shared_i2c_bus = true;
+
+		/* Initialize access to QSFP+ I2C bus */
+		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		esdp |= IXGBE_ESDP_SDP0_DIR;
+		esdp &= ~IXGBE_ESDP_SDP1_DIR;
+		esdp &= ~IXGBE_ESDP_SDP0;
+		esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
+		esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
+		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+		IXGBE_WRITE_FLUSH(hw);
+
+		phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_82599;
+		phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_82599;
+	}
 
 	/* Identify the PHY or SFP module */
 	ret_val = phy->ops.identify(hw);
@@ -397,6 +420,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
 	case IXGBE_DEV_ID_82599_LS:
 		media_type = ixgbe_media_type_fiber_lco;
 		break;
+	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
+		media_type = ixgbe_media_type_fiber_qsfp;
+		break;
 	default:
 		media_type = ixgbe_media_type_unknown;
 		break;
@@ -527,6 +553,75 @@ static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 }
 
 /**
+ *  ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber
+ *  @hw: pointer to hardware structure
+ *  @speed: link speed to set
+ *
+ *  We set the module speed differently for fixed fiber.  For other
+ *  multi-speed devices we don't have an error value so here if we
+ *  detect an error we just log it and exit.
+ */
+static void ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw,
+					ixgbe_link_speed speed)
+{
+	s32 status;
+	u8 rs, eeprom_data;
+
+	switch (speed) {
+	case IXGBE_LINK_SPEED_10GB_FULL:
+		/* one bit mask same as setting on */
+		rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
+		break;
+	case IXGBE_LINK_SPEED_1GB_FULL:
+		rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
+		break;
+	default:
+		hw_dbg(hw, "Invalid fixed module speed\n");
+		return;
+	}
+
+	/* Set RS0 */
+	status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+					   IXGBE_I2C_EEPROM_DEV_ADDR2,
+					   &eeprom_data);
+	if (status) {
+		hw_dbg(hw, "Failed to read Rx Rate Select RS0\n");
+		goto out;
+	}
+
+	eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
+
+	status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+					    IXGBE_I2C_EEPROM_DEV_ADDR2,
+					    eeprom_data);
+	if (status) {
+		hw_dbg(hw, "Failed to write Rx Rate Select RS0\n");
+		goto out;
+	}
+
+	/* Set RS1 */
+	status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
+					   IXGBE_I2C_EEPROM_DEV_ADDR2,
+					   &eeprom_data);
+	if (status) {
+		hw_dbg(hw, "Failed to read Rx Rate Select RS1\n");
+		goto out;
+	}
+
+	eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
+
+	status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
+					    IXGBE_I2C_EEPROM_DEV_ADDR2,
+					    eeprom_data);
+	if (status) {
+		hw_dbg(hw, "Failed to write Rx Rate Select RS1\n");
+		goto out;
+	}
+out:
+	return;
+}
+
+/**
  *  ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
  *  @hw: pointer to hardware structure
  *  @speed: new link speed
@@ -573,9 +668,14 @@ static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 			goto out;
 
 		/* Set the module link speed */
-		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
-		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-		IXGBE_WRITE_FLUSH(hw);
+		if (hw->phy.media_type == ixgbe_media_type_fiber_fixed) {
+			ixgbe_set_fiber_fixed_speed(hw,
+					IXGBE_LINK_SPEED_10GB_FULL);
+		} else {
+			esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
+			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+			IXGBE_WRITE_FLUSH(hw);
+		}
 
 		/* Allow module to change analog characteristics (1G->10G) */
 		msleep(40);
@@ -625,10 +725,15 @@ static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 			goto out;
 
 		/* Set the module link speed */
-		esdp_reg &= ~IXGBE_ESDP_SDP5;
-		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
-		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-		IXGBE_WRITE_FLUSH(hw);
+		if (hw->phy.media_type == ixgbe_media_type_fiber_fixed) {
+			ixgbe_set_fiber_fixed_speed(hw,
+						IXGBE_LINK_SPEED_1GB_FULL);
+		} else {
+			esdp_reg &= ~IXGBE_ESDP_SDP5;
+			esdp_reg |= IXGBE_ESDP_SDP5_DIR;
+			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+			IXGBE_WRITE_FLUSH(hw);
+		}
 
 		/* Allow module to change analog characteristics (10G->1G) */
 		msleep(40);
@@ -1872,7 +1977,7 @@ static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
 			goto out;
 		else
-			status = ixgbe_identify_sfp_module_generic(hw);
+			status = ixgbe_identify_module_generic(hw);
 	}
 
 	/* Set PHY type none if no PHY detected */
@@ -1978,10 +2083,12 @@ sfp_check:
 	switch (hw->phy.type) {
 	case ixgbe_phy_sfp_passive_tyco:
 	case ixgbe_phy_sfp_passive_unknown:
+	case ixgbe_phy_qsfp_passive_unknown:
 		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
 		break;
 	case ixgbe_phy_sfp_ftl_active:
 	case ixgbe_phy_sfp_active_unknown:
+	case ixgbe_phy_qsfp_active_unknown:
 		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
 		break;
 	case ixgbe_phy_sfp_avago:
@@ -1999,6 +2106,15 @@ sfp_check:
 		else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
 			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
 		break;
+	case ixgbe_phy_qsfp_intel:
+	case ixgbe_phy_qsfp_unknown:
+		hw->phy.ops.read_i2c_eeprom(hw,
+			IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g);
+		if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+		else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+		break;
 	default:
 		break;
 	}
@@ -2236,6 +2352,112 @@ reset_pipeline_out:
 	return ret_val;
 }
 
+/**
+ *  ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+				     u8 dev_addr, u8 *data)
+{
+	u32 esdp;
+	s32 status;
+	s32 timeout = 200;
+
+	if (hw->phy.qsfp_shared_i2c_bus == true) {
+		/* Acquire I2C bus ownership. */
+		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		esdp |= IXGBE_ESDP_SDP0;
+		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+		IXGBE_WRITE_FLUSH(hw);
+
+		while (timeout) {
+			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+			if (esdp & IXGBE_ESDP_SDP1)
+				break;
+
+			usleep_range(5000, 10000);
+			timeout--;
+		}
+
+		if (!timeout) {
+			hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
+			status = IXGBE_ERR_I2C;
+			goto release_i2c_access;
+		}
+	}
+
+	status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
+
+release_i2c_access:
+	if (hw->phy.qsfp_shared_i2c_bus == true) {
+		/* Release I2C bus ownership. */
+		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		esdp &= ~IXGBE_ESDP_SDP0;
+		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+		IXGBE_WRITE_FLUSH(hw);
+	}
+
+	return status;
+}
+
+/**
+ *  ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+				      u8 dev_addr, u8 data)
+{
+	u32 esdp;
+	s32 status;
+	s32 timeout = 200;
+
+	if (hw->phy.qsfp_shared_i2c_bus == true) {
+		/* Acquire I2C bus ownership. */
+		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		esdp |= IXGBE_ESDP_SDP0;
+		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+		IXGBE_WRITE_FLUSH(hw);
+
+		while (timeout) {
+			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+			if (esdp & IXGBE_ESDP_SDP1)
+				break;
+
+			usleep_range(5000, 10000);
+			timeout--;
+		}
+
+		if (!timeout) {
+			hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
+			status = IXGBE_ERR_I2C;
+			goto release_i2c_access;
+		}
+	}
+
+	status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
+
+release_i2c_access:
+	if (hw->phy.qsfp_shared_i2c_bus == true) {
+		/* Release I2C bus ownership. */
+		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		esdp &= ~IXGBE_ESDP_SDP0;
+		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+		IXGBE_WRITE_FLUSH(hw);
+	}
+
+	return status;
+}
+
 static struct ixgbe_mac_operations mac_ops_82599 = {
 	.init_hw                = &ixgbe_init_hw_generic,
 	.reset_hw               = &ixgbe_reset_hw_82599,
@@ -2300,7 +2522,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
 
 static struct ixgbe_phy_operations phy_ops_82599 = {
 	.identify		= &ixgbe_identify_phy_82599,
-	.identify_sfp		= &ixgbe_identify_sfp_module_generic,
+	.identify_sfp		= &ixgbe_identify_module_generic,
 	.init			= &ixgbe_init_phy_ops_82599,
 	.reset			= &ixgbe_reset_phy_generic,
 	.read_reg		= &ixgbe_read_phy_reg_generic,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 9bcdeb8..50e62a2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -65,17 +65,42 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
  *  function check the device id to see if the associated phy supports
  *  autoneg flow control.
  **/
-s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 {
+	bool supported = false;
+	ixgbe_link_speed speed;
+	bool link_up;
 
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_X540T:
-	case IXGBE_DEV_ID_X540T1:
-	case IXGBE_DEV_ID_82599_T3_LOM:
-		return 0;
+	switch (hw->phy.media_type) {
+	case ixgbe_media_type_fiber_fixed:
+	case ixgbe_media_type_fiber:
+		hw->mac.ops.check_link(hw, &speed, &link_up, false);
+		/* if link is down, assume supported */
+		if (link_up)
+			supported = speed == IXGBE_LINK_SPEED_1GB_FULL ?
+				true : false;
+		else
+			supported = true;
+		break;
+	case ixgbe_media_type_backplane:
+		supported = true;
+		break;
+	case ixgbe_media_type_copper:
+		/* only some copper devices support flow control autoneg */
+		switch (hw->device_id) {
+		case IXGBE_DEV_ID_82599_T3_LOM:
+		case IXGBE_DEV_ID_X540T:
+		case IXGBE_DEV_ID_X540T1:
+			supported = true;
+			break;
+		default:
+			break;
+		}
 	default:
-		return IXGBE_ERR_FC_NOT_SUPPORTED;
+		break;
 	}
+
+	return supported;
 }
 
 /**
@@ -114,6 +139,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
 	 */
 	switch (hw->phy.media_type) {
+	case ixgbe_media_type_fiber_fixed:
 	case ixgbe_media_type_fiber:
 	case ixgbe_media_type_backplane:
 		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
@@ -234,7 +260,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 						      IXGBE_GSSR_MAC_CSR_SM);
 
 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
-		    (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
+		    ixgbe_device_supports_autoneg_fc(hw)) {
 		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
 				      MDIO_MMD_AN, reg_cu);
 	}
@@ -2380,6 +2406,7 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 
 	switch (hw->phy.media_type) {
 	/* Autoneg flow control on fiber adapters */
+	case ixgbe_media_type_fiber_fixed:
 	case ixgbe_media_type_fiber:
 		if (speed == IXGBE_LINK_SPEED_1GB_FULL)
 			ret_val = ixgbe_fc_autoneg_fiber(hw);
@@ -2392,7 +2419,7 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 
 	/* Autoneg flow control on copper adapters */
 	case ixgbe_media_type_copper:
-		if (ixgbe_device_supports_autoneg_fc(hw) == 0)
+		if (ixgbe_device_supports_autoneg_fc(hw))
 			ret_val = ixgbe_fc_autoneg_copper(hw);
 		break;
 
@@ -2479,42 +2506,39 @@ out:
  **/
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 {
-	u32 gssr;
+	u32 gssr = 0;
 	u32 swmask = mask;
 	u32 fwmask = mask << 5;
-	s32 timeout = 200;
+	u32 timeout = 200;
+	u32 i;
 
-	while (timeout) {
+	for (i = 0; i < timeout; i++) {
 		/*
-		 * SW EEPROM semaphore bit is used for access to all
-		 * SW_FW_SYNC/GSSR bits (not just EEPROM)
+		 * SW NVM semaphore bit is used for access to all
+		 * SW_FW_SYNC bits (not just NVM)
 		 */
 		if (ixgbe_get_eeprom_semaphore(hw))
 			return IXGBE_ERR_SWFW_SYNC;
 
 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
-		if (!(gssr & (fwmask | swmask)))
-			break;
-
-		/*
-		 * Firmware currently using resource (fwmask) or other software
-		 * thread currently using resource (swmask)
-		 */
-		ixgbe_release_eeprom_semaphore(hw);
-		usleep_range(5000, 10000);
-		timeout--;
-	}
-
-	if (!timeout) {
-		hw_dbg(hw, "Driver can't access resource, SW_FW_SYNC timeout.\n");
-		return IXGBE_ERR_SWFW_SYNC;
+		if (!(gssr & (fwmask | swmask))) {
+			gssr |= swmask;
+			IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
+			ixgbe_release_eeprom_semaphore(hw);
+			return 0;
+		} else {
+			/* Resource is currently in use by FW or SW */
+			ixgbe_release_eeprom_semaphore(hw);
+			usleep_range(5000, 10000);
+		}
 	}
 
-	gssr |= swmask;
-	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
+	/* If time expired clear the bits holding the lock and retry */
+	if (gssr & (fwmask | swmask))
+		ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
 
-	ixgbe_release_eeprom_semaphore(hw);
-	return 0;
+	usleep_range(5000, 10000);
+	return IXGBE_ERR_SWFW_SYNC;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 22eee38..1315b8a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -80,7 +80,7 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
 s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
-s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
+bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
 void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
 
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 24e2e7a..50c1e9b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -355,10 +355,11 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (hw->fc.disable_fc_autoneg)
-		pause->autoneg = 0;
-	else
+	if (ixgbe_device_supports_autoneg_fc(hw) &&
+	    !hw->fc.disable_fc_autoneg)
 		pause->autoneg = 1;
+	else
+		pause->autoneg = 0;
 
 	if (hw->fc.current_mode == ixgbe_fc_rx_pause) {
 		pause->rx_pause = 1;
@@ -384,7 +385,7 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
 
 	/* some devices do not support autoneg of link flow control */
 	if ((pause->autoneg == AUTONEG_ENABLE) &&
-	    (ixgbe_device_supports_autoneg_fc(hw) != 0))
+	    !ixgbe_device_supports_autoneg_fc(hw))
 		return -EINVAL;
 
 	fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE);
@@ -1140,11 +1141,11 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
 			sprintf(p, "tx_queue_%u_bytes", i);
 			p += ETH_GSTRING_LEN;
 #ifdef LL_EXTENDED_STATS
-			sprintf(p, "tx_q_%u_napi_yield", i);
+			sprintf(p, "tx_queue_%u_ll_napi_yield", i);
 			p += ETH_GSTRING_LEN;
-			sprintf(p, "tx_q_%u_misses", i);
+			sprintf(p, "tx_queue_%u_ll_misses", i);
 			p += ETH_GSTRING_LEN;
-			sprintf(p, "tx_q_%u_cleaned", i);
+			sprintf(p, "tx_queue_%u_ll_cleaned", i);
 			p += ETH_GSTRING_LEN;
 #endif /* LL_EXTENDED_STATS */
 		}
@@ -1154,11 +1155,11 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
 			sprintf(p, "rx_queue_%u_bytes", i);
 			p += ETH_GSTRING_LEN;
 #ifdef LL_EXTENDED_STATS
-			sprintf(p, "rx_q_%u_ll_poll_yield", i);
+			sprintf(p, "rx_queue_%u_ll_poll_yield", i);
 			p += ETH_GSTRING_LEN;
-			sprintf(p, "rx_q_%u_misses", i);
+			sprintf(p, "rx_queue_%u_ll_misses", i);
 			p += ETH_GSTRING_LEN;
-			sprintf(p, "rx_q_%u_cleaned", i);
+			sprintf(p, "rx_queue_%u_ll_cleaned", i);
 			p += ETH_GSTRING_LEN;
 #endif /* LL_EXTENDED_STATS */
 		}
@@ -2909,33 +2910,21 @@ static int ixgbe_get_module_info(struct net_device *dev,
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 status;
 	u8 sff8472_rev, addr_mode;
-	int ret_val = 0;
 	bool page_swap = false;
 
-	/* avoid concurent i2c reads */
-	while (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
-		msleep(100);
-
-	/* used by the service task */
-	set_bit(__IXGBE_READ_I2C, &adapter->state);
-
 	/* Check whether we support SFF-8472 or not */
 	status = hw->phy.ops.read_i2c_eeprom(hw,
 					     IXGBE_SFF_SFF_8472_COMP,
 					     &sff8472_rev);
-	if (status != 0) {
-		ret_val = -EIO;
-		goto err_out;
-	}
+	if (status != 0)
+		return -EIO;
 
 	/* addressing mode is not supported */
 	status = hw->phy.ops.read_i2c_eeprom(hw,
 					     IXGBE_SFF_SFF_8472_SWAP,
 					     &addr_mode);
-	if (status != 0) {
-		ret_val = -EIO;
-		goto err_out;
-	}
+	if (status != 0)
+		return -EIO;
 
 	if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
 		e_err(drv, "Address change required to access page 0xA2, but not supported. Please report the module type to the driver maintainers.\n");
@@ -2952,9 +2941,7 @@ static int ixgbe_get_module_info(struct net_device *dev,
 		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
 	}
 
-err_out:
-	clear_bit(__IXGBE_READ_I2C, &adapter->state);
-	return ret_val;
+	return 0;
 }
 
 static int ixgbe_get_module_eeprom(struct net_device *dev,
@@ -2968,48 +2955,25 @@ static int ixgbe_get_module_eeprom(struct net_device *dev,
 	int i = 0;
 	int ret_val = 0;
 
-	/* ixgbe_get_module_info is called before this function in all
-	 * cases, so we do not need any checks we already do above,
-	 * and can trust ee->len to be a known value.
-	 */
+	if (ee->len == 0)
+		return -EINVAL;
+
+	for (i = ee->offset; i < ee->len; i++) {
+		/* I2C reads can take long time */
+		if (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
+			return -EBUSY;
 
-	while (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
-		msleep(100);
-	set_bit(__IXGBE_READ_I2C, &adapter->state);
+		if (i < ETH_MODULE_SFF_8079_LEN)
+			status  = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+		else
+			status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
 
-	/* Read the first block, SFF-8079 */
-	for (i = 0; i < ETH_MODULE_SFF_8079_LEN; i++) {
-		status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
-		if (status != 0) {
-			/* Error occured while reading module */
+		if (status != 0)
 			ret_val = -EIO;
-			goto err_out;
-		}
-		data[i] = databyte;
-	}
 
-	/* If the second block is requested, check if SFF-8472 is supported. */
-	if (ee->len == ETH_MODULE_SFF_8472_LEN) {
-		if (data[IXGBE_SFF_SFF_8472_COMP] == IXGBE_SFF_SFF_8472_UNSUP)
-			return -EOPNOTSUPP;
-
-		/* Read the second block, SFF-8472 */
-		for (i = ETH_MODULE_SFF_8079_LEN;
-		     i < ETH_MODULE_SFF_8472_LEN; i++) {
-			status = hw->phy.ops.read_i2c_sff8472(hw,
-				i - ETH_MODULE_SFF_8079_LEN, &databyte);
-			if (status != 0) {
-				/* Error occured while reading module */
-				ret_val = -EIO;
-				goto err_out;
-			}
-			data[i] = databyte;
-		}
+		data[i - ee->offset] = databyte;
 	}
 
-err_out:
-	clear_bit(__IXGBE_READ_I2C, &adapter->state);
-
 	return ret_val;
 }
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index be4b1fb..128d6b8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -63,7 +63,7 @@ char ixgbe_default_device_descr[] =
 static char ixgbe_default_device_descr[] =
 			      "Intel(R) 10 Gigabit Network Connection";
 #endif
-#define DRV_VERSION "3.13.10-k"
+#define DRV_VERSION "3.15.1-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
 				"Copyright (c) 1999-2013 Intel Corporation.";
@@ -109,6 +109,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T), board_X540 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2), board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_QSFP_SF_QP), board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 },
@@ -195,6 +196,86 @@ static s32 ixgbe_get_parent_bus_info(struct ixgbe_adapter *adapter)
 	return 0;
 }
 
+/**
+ * ixgbe_check_from_parent - Determine whether PCIe info should come from parent
+ * @hw: hw specific details
+ *
+ * This function is used by probe to determine whether a device's PCI-Express
+ * bandwidth details should be gathered from the parent bus instead of from the
+ * device. Used to ensure that various locations all have the correct device ID
+ * checks.
+ */
+static inline bool ixgbe_pcie_from_parent(struct ixgbe_hw *hw)
+{
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_82599_SFP_SF_QP:
+	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter,
+				     int expected_gts)
+{
+	int max_gts = 0;
+	enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
+	enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
+	struct pci_dev *pdev;
+
+	/* determine whether to use the the parent device
+	 */
+	if (ixgbe_pcie_from_parent(&adapter->hw))
+		pdev = adapter->pdev->bus->parent->self;
+	else
+		pdev = adapter->pdev;
+
+	if (pcie_get_minimum_link(pdev, &speed, &width) ||
+	    speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) {
+		e_dev_warn("Unable to determine PCI Express bandwidth.\n");
+		return;
+	}
+
+	switch (speed) {
+	case PCIE_SPEED_2_5GT:
+		/* 8b/10b encoding reduces max throughput by 20% */
+		max_gts = 2 * width;
+		break;
+	case PCIE_SPEED_5_0GT:
+		/* 8b/10b encoding reduces max throughput by 20% */
+		max_gts = 4 * width;
+		break;
+	case PCIE_SPEED_8_0GT:
+		/* 128b/130b encoding only reduces throughput by 1% */
+		max_gts = 8 * width;
+		break;
+	default:
+		e_dev_warn("Unable to determine PCI Express bandwidth.\n");
+		return;
+	}
+
+	e_dev_info("PCI Express bandwidth of %dGT/s available\n",
+		   max_gts);
+	e_dev_info("(Speed:%s, Width: x%d, Encoding Loss:%s)\n",
+		   (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" :
+		    speed == PCIE_SPEED_5_0GT ? "5.0GT/s" :
+		    speed == PCIE_SPEED_2_5GT ? "2.5GT/s" :
+		    "Unknown"),
+		   width,
+		   (speed == PCIE_SPEED_2_5GT ? "20%" :
+		    speed == PCIE_SPEED_5_0GT ? "20%" :
+		    speed == PCIE_SPEED_8_0GT ? "N/a" :
+		    "Unknown"));
+
+	if (max_gts < expected_gts) {
+		e_dev_warn("This is not sufficient for optimal performance of this card.\n");
+		e_dev_warn("For optimal performance, at least %dGT/s of bandwidth is required.\n",
+			expected_gts);
+		e_dev_warn("A slot with more lanes and/or higher speed is suggested.\n");
+	}
+}
+
 static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
 {
 	if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
@@ -3724,8 +3805,15 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 		hw->addr_ctrl.user_set_promisc = true;
 		fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
 		vmolr |= (IXGBE_VMOLR_ROPE | IXGBE_VMOLR_MPE);
-		/* don't hardware filter vlans in promisc mode */
-		ixgbe_vlan_filter_disable(adapter);
+		/* Only disable hardware filter vlans in promiscuous mode
+		 * if SR-IOV and VMDQ are disabled - otherwise ensure
+		 * that hardware VLAN filters remain enabled.
+		 */
+		if (!(adapter->flags & (IXGBE_FLAG_VMDQ_ENABLED |
+					IXGBE_FLAG_SRIOV_ENABLED)))
+			ixgbe_vlan_filter_disable(adapter);
+		else
+			ixgbe_vlan_filter_enable(adapter);
 	} else {
 		if (netdev->flags & IFF_ALLMULTI) {
 			fctrl |= IXGBE_FCTRL_MPE;
@@ -4352,7 +4440,7 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
 	if (hw->mac.san_mac_rar_index)
 		hw->mac.ops.set_vmdq_san_mac(hw, VMDQ_P(0));
 
-	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+	if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state))
 		ixgbe_ptp_reset(adapter);
 }
 
@@ -4714,8 +4802,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	ixgbe_pbthresh_setup(adapter);
 	hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
 	hw->fc.send_xon = true;
-	hw->fc.disable_fc_autoneg =
-		(ixgbe_device_supports_autoneg_fc(hw) == 0) ? false : true;
+	hw->fc.disable_fc_autoneg = ixgbe_device_supports_autoneg_fc(hw);
 
 #ifdef CONFIG_PCI_IOV
 	/* assign number of SR-IOV VFs */
@@ -5681,7 +5768,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 
 	adapter->last_rx_ptp_check = jiffies;
 
-	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+	if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state))
 		ixgbe_ptp_start_cyclecounter(adapter);
 
 	e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
@@ -5727,7 +5814,7 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter)
 	if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB)
 		adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
 
-	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+	if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state))
 		ixgbe_ptp_start_cyclecounter(adapter);
 
 	e_info(drv, "NIC Link is Down\n");
@@ -5826,10 +5913,6 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter)
 	    !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
 		return;
 
-	/* concurent i2c reads are not supported */
-	if (test_bit(__IXGBE_READ_I2C, &adapter->state))
-		return;
-
 	/* someone else is in init, wait until next service event */
 	if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
 		return;
@@ -6038,7 +6121,7 @@ static void ixgbe_service_task(struct work_struct *work)
 	ixgbe_fdir_reinit_subtask(adapter);
 	ixgbe_check_hang_subtask(adapter);
 
-	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) {
+	if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state)) {
 		ixgbe_ptp_overflow_check(adapter);
 		ixgbe_ptp_rx_hang(adapter);
 	}
@@ -7247,6 +7330,42 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 };
 
 /**
+ * ixgbe_enumerate_functions - Get the number of ports this device has
+ * @adapter: adapter structure
+ *
+ * This function enumerates the phsyical functions co-located on a single slot,
+ * in order to determine how many ports a device has. This is most useful in
+ * determining the required GT/s of PCIe bandwidth necessary for optimal
+ * performance.
+ **/
+static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct list_head *entry;
+	int physfns = 0;
+
+	/* Some cards can not use the generic count PCIe functions method, and
+	 * so must be hardcoded to the correct value.
+	 */
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_82599_SFP_SF_QP:
+	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
+		physfns = 4;
+		break;
+	default:
+		list_for_each(entry, &adapter->pdev->bus_list) {
+			struct pci_dev *pdev =
+				list_entry(entry, struct pci_dev, bus_list);
+			/* don't count virtual functions */
+			if (!pdev->is_virtfn)
+				physfns++;
+		}
+	}
+
+	return physfns;
+}
+
+/**
  * ixgbe_wol_supported - Check whether device supports WoL
  * @hw: hw specific details
  * @device_id: the device ID
@@ -7328,7 +7447,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct ixgbe_hw *hw;
 	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
 	static int cards_found;
-	int i, err, pci_using_dac;
+	int i, err, pci_using_dac, expected_gts;
 	unsigned int indices = MAX_TX_QUEUES;
 	u8 part_str[IXGBE_PBANUM_LENGTH];
 #ifdef IXGBE_FCOE
@@ -7617,7 +7736,7 @@ skip_sriov:
 
 	/* pick up the PCI bus settings for reporting later */
 	hw->mac.ops.get_bus_info(hw);
-	if (hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP)
+	if (ixgbe_pcie_from_parent(hw))
 		ixgbe_get_parent_bus_info(adapter);
 
 	/* print bus type/speed/width info */
@@ -7643,12 +7762,20 @@ skip_sriov:
 		e_dev_info("MAC: %d, PHY: %d, PBA No: %s\n",
 			   hw->mac.type, hw->phy.type, part_str);
 
-	if (hw->bus.width <= ixgbe_bus_width_pcie_x4) {
-		e_dev_warn("PCI-Express bandwidth available for this card is "
-			   "not sufficient for optimal performance.\n");
-		e_dev_warn("For optimal performance a x8 PCI-Express slot "
-			   "is required.\n");
+	/* calculate the expected PCIe bandwidth required for optimal
+	 * performance. Note that some older parts will never have enough
+	 * bandwidth due to being older generation PCIe parts. We clamp these
+	 * parts to ensure no warning is displayed if it can't be fixed.
+	 */
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		expected_gts = min(ixgbe_enumerate_functions(adapter) * 10, 16);
+		break;
+	default:
+		expected_gts = ixgbe_enumerate_functions(adapter) * 10;
+		break;
 	}
+	ixgbe_check_minimum_link(adapter, expected_gts);
 
 	/* reset the hardware with the new settings */
 	err = hw->mac.ops.start_hw(hw);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index e5691cc..369eef5 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -204,7 +204,83 @@ out:
 }
 
 /**
+ *  ixgbe_read_phy_mdi - Reads a value from a specified PHY register without
+ *  the SWFW lock
+ *  @hw: pointer to hardware structure
+ *  @reg_addr: 32 bit address of PHY register to read
+ *  @phy_data: Pointer to read data from PHY register
+ **/
+s32 ixgbe_read_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
+		       u16 *phy_data)
+{
+	u32 i, data, command;
+
+	/* Setup and write the address cycle command */
+	command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
+		   (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+		   (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
+
+	IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
+
+	/* Check every 10 usec to see if the address cycle completed.
+	 * The MDI Command bit will clear when the operation is
+	 * complete
+	 */
+	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+		udelay(10);
+
+		command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+		if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
+				break;
+	}
+
+
+	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
+		hw_dbg(hw, "PHY address command did not complete.\n");
+		return IXGBE_ERR_PHY;
+	}
+
+	/* Address cycle complete, setup and write the read
+	 * command
+	 */
+	command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
+		   (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+		   (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
+
+	IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
+
+	/* Check every 10 usec to see if the address cycle
+	 * completed. The MDI Command bit will clear when the
+	 * operation is complete
+	 */
+	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+		udelay(10);
+
+		command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+		if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
+		hw_dbg(hw, "PHY read command didn't complete\n");
+		return IXGBE_ERR_PHY;
+	}
+
+	/* Read operation is complete.  Get the data
+	 * from MSRWD
+	 */
+	data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
+	data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
+	*phy_data = (u16)(data);
+
+	return 0;
+}
+
+/**
  *  ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register
+ *  using the SWFW lock - this function is needed in most cases
  *  @hw: pointer to hardware structure
  *  @reg_addr: 32 bit address of PHY register to read
  *  @phy_data: Pointer to read data from PHY register
@@ -212,10 +288,7 @@ out:
 s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                                u32 device_type, u16 *phy_data)
 {
-	u32 command;
-	u32 i;
-	u32 data;
-	s32 status = 0;
+	s32 status;
 	u16 gssr;
 
 	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
@@ -223,86 +296,93 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 	else
 		gssr = IXGBE_GSSR_PHY0_SM;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == 0) {
+		status = ixgbe_read_phy_reg_mdi(hw, reg_addr, device_type,
+						phy_data);
+		hw->mac.ops.release_swfw_sync(hw, gssr);
+	} else {
 		status = IXGBE_ERR_SWFW_SYNC;
+	}
 
-	if (status == 0) {
-		/* Setup and write the address cycle command */
-		command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
-		           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-		           (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
-		           (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
+	return status;
+}
 
-		IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
+/**
+ *  ixgbe_write_phy_reg_mdi - Writes a value to specified PHY register
+ *  without SWFW lock
+ *  @hw: pointer to hardware structure
+ *  @reg_addr: 32 bit PHY register to write
+ *  @device_type: 5 bit device type
+ *  @phy_data: Data to write to the PHY register
+ **/
+s32 ixgbe_write_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr,
+				u32 device_type, u16 phy_data)
+{
+	u32 i, command;
 
-		/*
-		 * Check every 10 usec to see if the address cycle completed.
-		 * The MDI Command bit will clear when the operation is
-		 * complete
-		 */
-		for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
-			udelay(10);
+	/* Put the data in the MDI single read and write data register*/
+	IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
 
-			command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+	/* Setup and write the address cycle command */
+	command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
+		   (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+		   (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
 
-			if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
-				break;
-		}
+	IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
 
-		if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
-			hw_dbg(hw, "PHY address command did not complete.\n");
-			status = IXGBE_ERR_PHY;
-		}
+	/*
+	 * Check every 10 usec to see if the address cycle completed.
+	 * The MDI Command bit will clear when the operation is
+	 * complete
+	 */
+	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+		udelay(10);
 
-		if (status == 0) {
-			/*
-			 * Address cycle complete, setup and write the read
-			 * command
-			 */
-			command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
-			           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-			           (hw->phy.mdio.prtad <<
-				    IXGBE_MSCA_PHY_ADDR_SHIFT) |
-			           (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
-
-			IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
-
-			/*
-			 * Check every 10 usec to see if the address cycle
-			 * completed. The MDI Command bit will clear when the
-			 * operation is complete
-			 */
-			for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
-				udelay(10);
-
-				command = IXGBE_READ_REG(hw, IXGBE_MSCA);
-
-				if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
-					break;
-			}
+		command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+		if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
 
-			if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
-				hw_dbg(hw, "PHY read command didn't complete\n");
-				status = IXGBE_ERR_PHY;
-			} else {
-				/*
-				 * Read operation is complete.  Get the data
-				 * from MSRWD
-				 */
-				data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
-				data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
-				*phy_data = (u16)(data);
-			}
-		}
+	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
+		hw_dbg(hw, "PHY address cmd didn't complete\n");
+		return IXGBE_ERR_PHY;
+	}
 
-		hw->mac.ops.release_swfw_sync(hw, gssr);
+	/*
+	 * Address cycle complete, setup and write the write
+	 * command
+	 */
+	command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
+		   (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+		   (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
+
+	IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
+
+	/* Check every 10 usec to see if the address cycle
+	 * completed. The MDI Command bit will clear when the
+	 * operation is complete
+	 */
+	for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+		udelay(10);
+
+		command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+		if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
+			break;
 	}
 
-	return status;
+	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
+		hw_dbg(hw, "PHY write cmd didn't complete\n");
+		return IXGBE_ERR_PHY;
+	}
+
+	return 0;
 }
 
 /**
  *  ixgbe_write_phy_reg_generic - Writes a value to specified PHY register
+ *  using SWFW lock- this function is needed in most cases
  *  @hw: pointer to hardware structure
  *  @reg_addr: 32 bit PHY register to write
  *  @device_type: 5 bit device type
@@ -311,9 +391,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                                 u32 device_type, u16 phy_data)
 {
-	u32 command;
-	u32 i;
-	s32 status = 0;
+	s32 status;
 	u16 gssr;
 
 	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
@@ -321,74 +399,12 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 	else
 		gssr = IXGBE_GSSR_PHY0_SM;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
-		status = IXGBE_ERR_SWFW_SYNC;
-
-	if (status == 0) {
-		/* Put the data in the MDI single read and write data register*/
-		IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
-
-		/* Setup and write the address cycle command */
-		command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
-		           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-		           (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
-		           (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
-
-		IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
-
-		/*
-		 * Check every 10 usec to see if the address cycle completed.
-		 * The MDI Command bit will clear when the operation is
-		 * complete
-		 */
-		for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
-			udelay(10);
-
-			command = IXGBE_READ_REG(hw, IXGBE_MSCA);
-
-			if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
-				break;
-		}
-
-		if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
-			hw_dbg(hw, "PHY address cmd didn't complete\n");
-			status = IXGBE_ERR_PHY;
-		}
-
-		if (status == 0) {
-			/*
-			 * Address cycle complete, setup and write the write
-			 * command
-			 */
-			command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
-			           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-			           (hw->phy.mdio.prtad <<
-				    IXGBE_MSCA_PHY_ADDR_SHIFT) |
-			           (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
-
-			IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
-
-			/*
-			 * Check every 10 usec to see if the address cycle
-			 * completed. The MDI Command bit will clear when the
-			 * operation is complete
-			 */
-			for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
-				udelay(10);
-
-				command = IXGBE_READ_REG(hw, IXGBE_MSCA);
-
-				if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
-					break;
-			}
-
-			if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
-				hw_dbg(hw, "PHY address cmd didn't complete\n");
-				status = IXGBE_ERR_PHY;
-			}
-		}
-
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == 0) {
+		status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type,
+						 phy_data);
 		hw->mac.ops.release_swfw_sync(hw, gssr);
+	} else {
+		status = IXGBE_ERR_SWFW_SYNC;
 	}
 
 	return status;
@@ -825,9 +841,35 @@ out:
 }
 
 /**
- *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
+ *  ixgbe_identify_module_generic - Identifies module type
  *  @hw: pointer to hardware structure
  *
+ *  Determines HW type and calls appropriate function.
+ **/
+s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw)
+{
+	s32 status = IXGBE_ERR_SFP_NOT_PRESENT;
+
+	switch (hw->mac.ops.get_media_type(hw)) {
+	case ixgbe_media_type_fiber:
+		status = ixgbe_identify_sfp_module_generic(hw);
+		break;
+	case ixgbe_media_type_fiber_qsfp:
+		status = ixgbe_identify_qsfp_module_generic(hw);
+		break;
+	default:
+		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+		status = IXGBE_ERR_SFP_NOT_PRESENT;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
+ *  @hw: pointer to hardware structure
+*
  *  Searches for and identifies the SFP module and assigns appropriate PHY type.
  **/
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
@@ -1106,6 +1148,156 @@ err_read_i2c_eeprom:
 }
 
 /**
+ * ixgbe_identify_qsfp_module_generic - Identifies QSFP modules
+ * @hw: pointer to hardware structure
+ *
+ * Searches for and identifies the QSFP module and assigns appropriate PHY type
+ **/
+s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
+{
+	struct ixgbe_adapter *adapter = hw->back;
+	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+	u32 vendor_oui = 0;
+	enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
+	u8 identifier = 0;
+	u8 comp_codes_1g = 0;
+	u8 comp_codes_10g = 0;
+	u8 oui_bytes[3] = {0, 0, 0};
+	u16 enforce_sfp = 0;
+
+	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) {
+		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+		status = IXGBE_ERR_SFP_NOT_PRESENT;
+		goto out;
+	}
+
+	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
+					     &identifier);
+
+	if (status != 0)
+		goto err_read_i2c_eeprom;
+
+	if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
+		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+		goto out;
+	}
+
+	hw->phy.id = identifier;
+
+	/* LAN ID is needed for sfp_type determination */
+	hw->mac.ops.set_lan_id(hw);
+
+	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP,
+					     &comp_codes_10g);
+
+	if (status != 0)
+		goto err_read_i2c_eeprom;
+
+	if (comp_codes_10g & IXGBE_SFF_QSFP_DA_PASSIVE_CABLE) {
+		hw->phy.type = ixgbe_phy_qsfp_passive_unknown;
+		if (hw->bus.lan_id == 0)
+			hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0;
+		else
+			hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1;
+	} else if (comp_codes_10g & IXGBE_SFF_QSFP_DA_ACTIVE_CABLE) {
+		hw->phy.type = ixgbe_phy_qsfp_active_unknown;
+		if (hw->bus.lan_id == 0)
+			hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core0;
+		else
+			hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core1;
+	} else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE |
+				     IXGBE_SFF_10GBASELR_CAPABLE)) {
+		if (hw->bus.lan_id == 0)
+			hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0;
+		else
+			hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1;
+	} else {
+		/* unsupported module type */
+		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+		goto out;
+	}
+
+	if (hw->phy.sfp_type != stored_sfp_type)
+		hw->phy.sfp_setup_needed = true;
+
+	/* Determine if the QSFP+ PHY is dual speed or not. */
+	hw->phy.multispeed_fiber = false;
+	if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+	     (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+	    ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+	     (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
+		hw->phy.multispeed_fiber = true;
+
+	/* Determine PHY vendor for optical modules */
+	if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE |
+			      IXGBE_SFF_10GBASELR_CAPABLE)) {
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+					IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0,
+					&oui_bytes[0]);
+
+		if (status != 0)
+			goto err_read_i2c_eeprom;
+
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+					IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1,
+					&oui_bytes[1]);
+
+		if (status != 0)
+			goto err_read_i2c_eeprom;
+
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+					IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2,
+					&oui_bytes[2]);
+
+		if (status != 0)
+			goto err_read_i2c_eeprom;
+
+		vendor_oui =
+			((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
+			 (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
+			 (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
+
+		if (vendor_oui == IXGBE_SFF_VENDOR_OUI_INTEL)
+			hw->phy.type = ixgbe_phy_qsfp_intel;
+		else
+			hw->phy.type = ixgbe_phy_qsfp_unknown;
+
+		hw->mac.ops.get_device_caps(hw, &enforce_sfp);
+		if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
+			/* Make sure we're a supported PHY type */
+			if (hw->phy.type == ixgbe_phy_qsfp_intel) {
+				status = 0;
+			} else {
+				if (hw->allow_unsupported_sfp == true) {
+					e_warn(hw, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
+					status = 0;
+				} else {
+					hw_dbg(hw,
+					       "QSFP module not supported\n");
+					hw->phy.type =
+						ixgbe_phy_sfp_unsupported;
+					status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+				}
+			}
+		} else {
+			status = 0;
+		}
+	}
+
+out:
+	return status;
+
+err_read_i2c_eeprom:
+	hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+	hw->phy.id = 0;
+	hw->phy.type = ixgbe_phy_unknown;
+
+	return IXGBE_ERR_SFP_NOT_PRESENT;
+}
+
+/**
  *  ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence
  *  @hw: pointer to hardware structure
  *  @list_offset: offset to the SFP ID list
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index 886a343..138dadd 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -33,17 +33,25 @@
 #define IXGBE_I2C_EEPROM_DEV_ADDR2   0xA2
 
 /* EEPROM byte offsets */
-#define IXGBE_SFF_IDENTIFIER         0x0
-#define IXGBE_SFF_IDENTIFIER_SFP     0x3
-#define IXGBE_SFF_VENDOR_OUI_BYTE0   0x25
-#define IXGBE_SFF_VENDOR_OUI_BYTE1   0x26
-#define IXGBE_SFF_VENDOR_OUI_BYTE2   0x27
-#define IXGBE_SFF_1GBE_COMP_CODES    0x6
-#define IXGBE_SFF_10GBE_COMP_CODES   0x3
-#define IXGBE_SFF_CABLE_TECHNOLOGY   0x8
-#define IXGBE_SFF_CABLE_SPEC_COMP    0x3C
-#define IXGBE_SFF_SFF_8472_SWAP      0x5C
-#define IXGBE_SFF_SFF_8472_COMP      0x5E
+#define IXGBE_SFF_IDENTIFIER		0x0
+#define IXGBE_SFF_IDENTIFIER_SFP	0x3
+#define IXGBE_SFF_VENDOR_OUI_BYTE0	0x25
+#define IXGBE_SFF_VENDOR_OUI_BYTE1	0x26
+#define IXGBE_SFF_VENDOR_OUI_BYTE2	0x27
+#define IXGBE_SFF_1GBE_COMP_CODES	0x6
+#define IXGBE_SFF_10GBE_COMP_CODES	0x3
+#define IXGBE_SFF_CABLE_TECHNOLOGY	0x8
+#define IXGBE_SFF_CABLE_SPEC_COMP	0x3C
+#define IXGBE_SFF_SFF_8472_SWAP		0x5C
+#define IXGBE_SFF_SFF_8472_COMP		0x5E
+#define IXGBE_SFF_SFF_8472_OSCB		0x6E
+#define IXGBE_SFF_SFF_8472_ESCB		0x76
+#define IXGBE_SFF_IDENTIFIER_QSFP_PLUS	0xD
+#define IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0	0xA5
+#define IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1	0xA6
+#define IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2	0xA7
+#define IXGBE_SFF_QSFP_10GBE_COMP	0x83
+#define IXGBE_SFF_QSFP_1GBE_COMP	0x86
 
 /* Bitmasks */
 #define IXGBE_SFF_DA_PASSIVE_CABLE           0x4
@@ -54,7 +62,12 @@
 #define IXGBE_SFF_1GBASET_CAPABLE            0x8
 #define IXGBE_SFF_10GBASESR_CAPABLE          0x10
 #define IXGBE_SFF_10GBASELR_CAPABLE          0x20
+#define IXGBE_SFF_SOFT_RS_SELECT_MASK	0x8
+#define IXGBE_SFF_SOFT_RS_SELECT_10G	0x8
+#define IXGBE_SFF_SOFT_RS_SELECT_1G	0x0
 #define IXGBE_SFF_ADDRESSING_MODE	     0x4
+#define IXGBE_SFF_QSFP_DA_ACTIVE_CABLE       0x1
+#define IXGBE_SFF_QSFP_DA_PASSIVE_CABLE      0x8
 #define IXGBE_I2C_EEPROM_READ_MASK           0x100
 #define IXGBE_I2C_EEPROM_STATUS_MASK         0x3
 #define IXGBE_I2C_EEPROM_STATUS_NO_OPERATION 0x0
@@ -102,6 +115,10 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                                u32 device_type, u16 *phy_data);
 s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                                 u32 device_type, u16 phy_data);
+s32 ixgbe_read_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr,
+			   u32 device_type, u16 *phy_data);
+s32 ixgbe_write_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr,
+			    u32 device_type, u16 phy_data);
 s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw);
 s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
                                        ixgbe_link_speed speed,
@@ -121,7 +138,9 @@ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
                                            u16 *firmware_version);
 
 s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
+s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
+s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                                         u16 *list_offset,
                                         u16 *data_offset);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index 331987d..5184e2a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -885,8 +885,8 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
 	ixgbe_ptp_reset(adapter);
 
-	/* set the flag that PTP has been enabled */
-	adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED;
+	/* enter the IXGBE_PTP_RUNNING state */
+	set_bit(__IXGBE_PTP_RUNNING, &adapter->state);
 
 	return;
 }
@@ -899,10 +899,12 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
  */
 void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
 {
-	/* stop the overflow check task */
-	adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED |
-			     IXGBE_FLAG2_PTP_PPS_ENABLED);
+	/* Leave the IXGBE_PTP_RUNNING state. */
+	if (!test_and_clear_bit(__IXGBE_PTP_RUNNING, &adapter->state))
+		return;
 
+	/* stop the PPS signal */
+	adapter->flags2 &= ~IXGBE_FLAG2_PTP_PPS_ENABLED;
 	ixgbe_ptp_setup_sdp(adapter);
 
 	cancel_work_sync(&adapter->ptp_tx_work);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 1e7d587..73c8e73 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -173,39 +173,6 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
 	ixgbe_disable_sriov(adapter);
 }
 
-static bool ixgbe_vfs_are_assigned(struct ixgbe_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct pci_dev *vfdev;
-	int dev_id;
-
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82599EB:
-		dev_id = IXGBE_DEV_ID_82599_VF;
-		break;
-	case ixgbe_mac_X540:
-		dev_id = IXGBE_DEV_ID_X540_VF;
-		break;
-	default:
-		return false;
-	}
-
-	/* loop through all the VFs to see if we own any that are assigned */
-	vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL);
-	while (vfdev) {
-		/* if we don't own it we don't care */
-		if (vfdev->is_virtfn && vfdev->physfn == pdev) {
-			/* if it is assigned we cannot release it */
-			if (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
-				return true;
-		}
-
-		vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, vfdev);
-	}
-
-	return false;
-}
-
 #endif /* #ifdef CONFIG_PCI_IOV */
 int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 {
@@ -235,7 +202,7 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 	 * without causing issues, so just leave the hardware
 	 * available but disabled
 	 */
-	if (ixgbe_vfs_are_assigned(adapter)) {
+	if (pci_vfs_assigned(adapter->pdev)) {
 		e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n");
 		return -EPERM;
 	}
@@ -768,6 +735,29 @@ static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter,
 	return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0;
 }
 
+static int ixgbe_find_vlvf_entry(struct ixgbe_hw *hw, u32 vlan)
+{
+	u32 vlvf;
+	s32 regindex;
+
+	/* short cut the special case */
+	if (vlan == 0)
+		return 0;
+
+	/* Search for the vlan id in the VLVF entries */
+	for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
+		vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
+		if ((vlvf & VLAN_VID_MASK) == vlan)
+			break;
+	}
+
+	/* Return a negative value if not found */
+	if (regindex >= IXGBE_VLVF_ENTRIES)
+		regindex = -1;
+
+	return regindex;
+}
+
 static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
 				 u32 *msgbuf, u32 vf)
 {
@@ -775,6 +765,9 @@ static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
 	int add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
 	int vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
 	int err;
+	s32 reg_ndx;
+	u32 vlvf;
+	u32 bits;
 	u8 tcs = netdev_get_num_tc(adapter->netdev);
 
 	if (adapter->vfinfo[vf].pf_vlan || tcs) {
@@ -790,10 +783,50 @@ static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
 	else if (adapter->vfinfo[vf].vlan_count)
 		adapter->vfinfo[vf].vlan_count--;
 
+	/* in case of promiscuous mode any VLAN filter set for a VF must
+	 * also have the PF pool added to it.
+	 */
+	if (add && adapter->netdev->flags & IFF_PROMISC)
+		err = ixgbe_set_vf_vlan(adapter, add, vid, VMDQ_P(0));
+
 	err = ixgbe_set_vf_vlan(adapter, add, vid, vf);
 	if (!err && adapter->vfinfo[vf].spoofchk_enabled)
 		hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
 
+	/* Go through all the checks to see if the VLAN filter should
+	 * be wiped completely.
+	 */
+	if (!add && adapter->netdev->flags & IFF_PROMISC) {
+		reg_ndx = ixgbe_find_vlvf_entry(hw, vid);
+		if (reg_ndx < 0)
+			goto out;
+		vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(reg_ndx));
+		/* See if any other pools are set for this VLAN filter
+		 * entry other than the PF.
+		 */
+		if (VMDQ_P(0) < 32) {
+			bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(reg_ndx * 2));
+			bits &= ~(1 << VMDQ_P(0));
+			bits |= IXGBE_READ_REG(hw,
+					       IXGBE_VLVFB(reg_ndx * 2) + 1);
+		} else {
+			bits = IXGBE_READ_REG(hw,
+					      IXGBE_VLVFB(reg_ndx * 2) + 1);
+			bits &= ~(1 << (VMDQ_P(0) - 32));
+			bits |= IXGBE_READ_REG(hw, IXGBE_VLVFB(reg_ndx * 2));
+		}
+
+		/* If the filter was removed then ensure PF pool bit
+		 * is cleared if the PF only added itself to the pool
+		 * because the PF is in promiscuous mode.
+		 */
+		if ((vlvf & VLAN_VID_MASK) == vid &&
+		    !test_bit(vid, adapter->active_vlans) && !bits)
+			ixgbe_set_vf_vlan(adapter, add, vid, VMDQ_P(0));
+	}
+
+out:
+
 	return err;
 }
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 70c6aa3..161ff18 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -69,6 +69,7 @@
 #define IXGBE_DEV_ID_82599_LS            0x154F
 #define IXGBE_DEV_ID_X540T               0x1528
 #define IXGBE_DEV_ID_82599_SFP_SF_QP     0x154A
+#define IXGBE_DEV_ID_82599_QSFP_SF_QP    0x1558
 #define IXGBE_DEV_ID_X540T1              0x1560
 
 /* VF Device IDs */
@@ -1520,9 +1521,11 @@ enum {
 #define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */
 #define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */
 #define IXGBE_ESDP_SDP0_DIR     0x00000100 /* SDP0 IO direction */
+#define IXGBE_ESDP_SDP1_DIR     0x00000200 /* SDP1 IO direction */
 #define IXGBE_ESDP_SDP4_DIR     0x00000004 /* SDP4 IO direction */
 #define IXGBE_ESDP_SDP5_DIR     0x00002000 /* SDP5 IO direction */
 #define IXGBE_ESDP_SDP0_NATIVE  0x00010000 /* SDP0 Native Function */
+#define IXGBE_ESDP_SDP1_NATIVE  0x00020000 /* SDP1 IO mode */
 
 /* LEDCTL Bit Masks */
 #define IXGBE_LED_IVRT_BASE      0x00000040
@@ -2582,6 +2585,10 @@ enum ixgbe_phy_type {
 	ixgbe_phy_sfp_ftl_active,
 	ixgbe_phy_sfp_unknown,
 	ixgbe_phy_sfp_intel,
+	ixgbe_phy_qsfp_passive_unknown,
+	ixgbe_phy_qsfp_active_unknown,
+	ixgbe_phy_qsfp_intel,
+	ixgbe_phy_qsfp_unknown,
 	ixgbe_phy_sfp_unsupported,
 	ixgbe_phy_generic
 };
@@ -2622,6 +2629,8 @@ enum ixgbe_sfp_type {
 enum ixgbe_media_type {
 	ixgbe_media_type_unknown = 0,
 	ixgbe_media_type_fiber,
+	ixgbe_media_type_fiber_fixed,
+	ixgbe_media_type_fiber_qsfp,
 	ixgbe_media_type_fiber_lco,
 	ixgbe_media_type_copper,
 	ixgbe_media_type_backplane,
@@ -2885,6 +2894,8 @@ struct ixgbe_phy_operations {
 	s32 (*reset)(struct ixgbe_hw *);
 	s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *);
 	s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16);
+	s32 (*read_reg_mdi)(struct ixgbe_hw *, u32, u32, u16 *);
+	s32 (*write_reg_mdi)(struct ixgbe_hw *, u32, u32, u16);
 	s32 (*setup_link)(struct ixgbe_hw *);
 	s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool);
 	s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *);
@@ -2953,6 +2964,7 @@ struct ixgbe_phy_info {
 	bool                            smart_speed_active;
 	bool                            multispeed_fiber;
 	bool                            reset_if_overtemp;
+	bool                            qsfp_shared_i2c_bus;
 };
 
 #include "ixgbe_mbx.h"
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index b017818..2777c70 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -79,10 +79,10 @@
 #define MVNETA_MAC_ADDR_HIGH                     0x2418
 #define MVNETA_SDMA_CONFIG                       0x241c
 #define      MVNETA_SDMA_BRST_SIZE_16            4
-#define      MVNETA_NO_DESC_SWAP                 0x0
 #define      MVNETA_RX_BRST_SZ_MASK(burst)       ((burst) << 1)
 #define      MVNETA_RX_NO_DATA_SWAP              BIT(4)
 #define      MVNETA_TX_NO_DATA_SWAP              BIT(5)
+#define      MVNETA_DESC_SWAP                    BIT(6)
 #define      MVNETA_TX_BRST_SZ_MASK(burst)       ((burst) << 22)
 #define MVNETA_PORT_STATUS                       0x2444
 #define      MVNETA_TX_IN_PRGRS                  BIT(1)
@@ -264,8 +264,7 @@ struct mvneta_port {
  * layout of the transmit and reception DMA descriptors, and their
  * layout is therefore defined by the hardware design
  */
-struct mvneta_tx_desc {
-	u32  command;		/* Options used by HW for packet transmitting.*/
+
 #define MVNETA_TX_L3_OFF_SHIFT	0
 #define MVNETA_TX_IP_HLEN_SHIFT	8
 #define MVNETA_TX_L4_UDP	BIT(16)
@@ -280,15 +279,6 @@ struct mvneta_tx_desc {
 #define MVNETA_TX_L4_CSUM_FULL	BIT(30)
 #define MVNETA_TX_L4_CSUM_NOT	BIT(31)
 
-	u16  reserverd1;	/* csum_l4 (for future use)		*/
-	u16  data_size;		/* Data size of transmitted packet in bytes */
-	u32  buf_phys_addr;	/* Physical addr of transmitted buffer	*/
-	u32  reserved2;		/* hw_cmd - (for future use, PMT)	*/
-	u32  reserved3[4];	/* Reserved - (for future use)		*/
-};
-
-struct mvneta_rx_desc {
-	u32  status;		/* Info about received packet		*/
 #define MVNETA_RXD_ERR_CRC		0x0
 #define MVNETA_RXD_ERR_SUMMARY		BIT(16)
 #define MVNETA_RXD_ERR_OVERRUN		BIT(17)
@@ -299,16 +289,57 @@ struct mvneta_rx_desc {
 #define MVNETA_RXD_FIRST_LAST_DESC	(BIT(26) | BIT(27))
 #define MVNETA_RXD_L4_CSUM_OK		BIT(30)
 
+#if defined(__LITTLE_ENDIAN)
+struct mvneta_tx_desc {
+	u32  command;		/* Options used by HW for packet transmitting.*/
+	u16  reserverd1;	/* csum_l4 (for future use)		*/
+	u16  data_size;		/* Data size of transmitted packet in bytes */
+	u32  buf_phys_addr;	/* Physical addr of transmitted buffer	*/
+	u32  reserved2;		/* hw_cmd - (for future use, PMT)	*/
+	u32  reserved3[4];	/* Reserved - (for future use)		*/
+};
+
+struct mvneta_rx_desc {
+	u32  status;		/* Info about received packet		*/
 	u16  reserved1;		/* pnc_info - (for future use, PnC)	*/
 	u16  data_size;		/* Size of received packet in bytes	*/
+
 	u32  buf_phys_addr;	/* Physical address of the buffer	*/
 	u32  reserved2;		/* pnc_flow_id  (for future use, PnC)	*/
+
 	u32  buf_cookie;	/* cookie for access to RX buffer in rx path */
 	u16  reserved3;		/* prefetch_cmd, for future use		*/
 	u16  reserved4;		/* csum_l4 - (for future use, PnC)	*/
+
+	u32  reserved5;		/* pnc_extra PnC (for future use, PnC)	*/
+	u32  reserved6;		/* hw_cmd (for future use, PnC and HWF)	*/
+};
+#else
+struct mvneta_tx_desc {
+	u16  data_size;		/* Data size of transmitted packet in bytes */
+	u16  reserverd1;	/* csum_l4 (for future use)		*/
+	u32  command;		/* Options used by HW for packet transmitting.*/
+	u32  reserved2;		/* hw_cmd - (for future use, PMT)	*/
+	u32  buf_phys_addr;	/* Physical addr of transmitted buffer	*/
+	u32  reserved3[4];	/* Reserved - (for future use)		*/
+};
+
+struct mvneta_rx_desc {
+	u16  data_size;		/* Size of received packet in bytes	*/
+	u16  reserved1;		/* pnc_info - (for future use, PnC)	*/
+	u32  status;		/* Info about received packet		*/
+
+	u32  reserved2;		/* pnc_flow_id  (for future use, PnC)	*/
+	u32  buf_phys_addr;	/* Physical address of the buffer	*/
+
+	u16  reserved4;		/* csum_l4 - (for future use, PnC)	*/
+	u16  reserved3;		/* prefetch_cmd, for future use		*/
+	u32  buf_cookie;	/* cookie for access to RX buffer in rx path */
+
 	u32  reserved5;		/* pnc_extra PnC (for future use, PnC)	*/
 	u32  reserved6;		/* hw_cmd (for future use, PnC and HWF)	*/
 };
+#endif
 
 struct mvneta_tx_queue {
 	/* Number of this TX queue, in the range 0-7 */
@@ -908,9 +939,11 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
 	/* Default burst size */
 	val |= MVNETA_TX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16);
 	val |= MVNETA_RX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16);
+	val |= MVNETA_RX_NO_DATA_SWAP | MVNETA_TX_NO_DATA_SWAP;
 
-	val |= (MVNETA_RX_NO_DATA_SWAP | MVNETA_TX_NO_DATA_SWAP |
-		MVNETA_NO_DESC_SWAP);
+#if defined(__BIG_ENDIAN)
+	val |= MVNETA_DESC_SWAP;
+#endif
 
 	/* Assign port SDMA configuration */
 	mvreg_write(pp, MVNETA_SDMA_CONFIG, val);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index c896079..3f78336 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -931,17 +931,20 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)
 }
 
 /* Allocate and setup a new buffer for receiving */
-static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
-			  struct sk_buff *skb, unsigned int bufsize)
+static int skge_rx_setup(struct skge_port *skge, struct skge_element *e,
+			 struct sk_buff *skb, unsigned int bufsize)
 {
 	struct skge_rx_desc *rd = e->desc;
-	u64 map;
+	dma_addr_t map;
 
 	map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
 			     PCI_DMA_FROMDEVICE);
 
-	rd->dma_lo = map;
-	rd->dma_hi = map >> 32;
+	if (pci_dma_mapping_error(skge->hw->pdev, map))
+		return -1;
+
+	rd->dma_lo = lower_32_bits(map);
+	rd->dma_hi = upper_32_bits(map);
 	e->skb = skb;
 	rd->csum1_start = ETH_HLEN;
 	rd->csum2_start = ETH_HLEN;
@@ -953,6 +956,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
 	rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
 	dma_unmap_addr_set(e, mapaddr, map);
 	dma_unmap_len_set(e, maplen, bufsize);
+	return 0;
 }
 
 /* Resume receiving using existing skb,
@@ -1014,7 +1018,10 @@ static int skge_rx_fill(struct net_device *dev)
 			return -ENOMEM;
 
 		skb_reserve(skb, NET_IP_ALIGN);
-		skge_rx_setup(skge, e, skb, skge->rx_buf_size);
+		if (skge_rx_setup(skge, e, skb, skge->rx_buf_size) < 0) {
+			dev_kfree_skb(skb);
+			return -EIO;
+		}
 	} while ((e = e->next) != ring->start);
 
 	ring->to_clean = ring->start;
@@ -2544,7 +2551,7 @@ static int skge_up(struct net_device *dev)
 
 	BUG_ON(skge->dma & 7);
 
-	if ((u64)skge->dma >> 32 != ((u64) skge->dma + skge->mem_size) >> 32) {
+	if (upper_32_bits(skge->dma) != upper_32_bits(skge->dma + skge->mem_size)) {
 		dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n");
 		err = -EINVAL;
 		goto free_pci_mem;
@@ -2729,7 +2736,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
 	struct skge_tx_desc *td;
 	int i;
 	u32 control, len;
-	u64 map;
+	dma_addr_t map;
 
 	if (skb_padto(skb, ETH_ZLEN))
 		return NETDEV_TX_OK;
@@ -2743,11 +2750,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
 	e->skb = skb;
 	len = skb_headlen(skb);
 	map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(hw->pdev, map))
+		goto mapping_error;
+
 	dma_unmap_addr_set(e, mapaddr, map);
 	dma_unmap_len_set(e, maplen, len);
 
-	td->dma_lo = map;
-	td->dma_hi = map >> 32;
+	td->dma_lo = lower_32_bits(map);
+	td->dma_hi = upper_32_bits(map);
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		const int offset = skb_checksum_start_offset(skb);
@@ -2778,14 +2788,16 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
 
 			map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
 					       skb_frag_size(frag), DMA_TO_DEVICE);
+			if (dma_mapping_error(&hw->pdev->dev, map))
+				goto mapping_unwind;
 
 			e = e->next;
 			e->skb = skb;
 			tf = e->desc;
 			BUG_ON(tf->control & BMU_OWN);
 
-			tf->dma_lo = map;
-			tf->dma_hi = (u64) map >> 32;
+			tf->dma_lo = lower_32_bits(map);
+			tf->dma_hi = upper_32_bits(map);
 			dma_unmap_addr_set(e, mapaddr, map);
 			dma_unmap_len_set(e, maplen, skb_frag_size(frag));
 
@@ -2815,6 +2827,26 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
 	}
 
 	return NETDEV_TX_OK;
+
+mapping_unwind:
+	e = skge->tx_ring.to_use;
+	pci_unmap_single(hw->pdev,
+			 dma_unmap_addr(e, mapaddr),
+			 dma_unmap_len(e, maplen),
+			 PCI_DMA_TODEVICE);
+	while (i-- > 0) {
+		e = e->next;
+		pci_unmap_page(hw->pdev,
+			       dma_unmap_addr(e, mapaddr),
+			       dma_unmap_len(e, maplen),
+			       PCI_DMA_TODEVICE);
+	}
+
+mapping_error:
+	if (net_ratelimit())
+		dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
 }
 
 
@@ -3058,13 +3090,17 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
 		if (!nskb)
 			goto resubmit;
 
+		if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) {
+			dev_kfree_skb(nskb);
+			goto resubmit;
+		}
+
 		pci_unmap_single(skge->hw->pdev,
 				 dma_unmap_addr(e, mapaddr),
 				 dma_unmap_len(e, maplen),
 				 PCI_DMA_FROMDEVICE);
 		skb = e->skb;
 		prefetch(skb->data);
-		skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
 	}
 
 	skb_put(skb, len);
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 299d018..ea20182 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -800,7 +800,16 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
 				    vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
 }
 
-int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+static int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+		     struct mlx4_vhcr *vhcr,
+		     struct mlx4_cmd_mailbox *inbox,
+		     struct mlx4_cmd_mailbox *outbox,
+		     struct mlx4_cmd_info *cmd)
+{
+	return -EPERM;
+}
+
+static int MLX4_CMD_GET_OP_REQ_wrapper(struct mlx4_dev *dev, int slave,
 		     struct mlx4_vhcr *vhcr,
 		     struct mlx4_cmd_mailbox *inbox,
 		     struct mlx4_cmd_mailbox *outbox,
@@ -1252,6 +1261,15 @@ static struct mlx4_cmd_info cmd_info[] = {
 		.wrapper = MLX4_CMD_UPDATE_QP_wrapper
 	},
 	{
+		.opcode = MLX4_CMD_GET_OP_REQ,
+		.has_inbox = false,
+		.has_outbox = false,
+		.out_is_imm = false,
+		.encode_slave_id = false,
+		.verify = NULL,
+		.wrapper = MLX4_CMD_GET_OP_REQ_wrapper,
+	},
+	{
 		.opcode = MLX4_CMD_CONF_SPECIAL_QP,
 		.has_inbox = false,
 		.has_outbox = false,
@@ -1526,7 +1544,7 @@ static int calculate_transition(u16 oper_vlan, u16 admin_vlan)
 	return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT));
 }
 
-int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
+static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
 					    int slave, int port)
 {
 	struct mlx4_vport_oper_state *vp_oper;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 7c49238..6dcca98 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -191,6 +191,39 @@ void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
 		       MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
 }
 
+static void mlx4_en_stamp_wqe(struct mlx4_en_priv *priv,
+			      struct mlx4_en_tx_ring *ring, int index,
+			      u8 owner)
+{
+	__be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
+	struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
+	struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
+	void *end = ring->buf + ring->buf_size;
+	__be32 *ptr = (__be32 *)tx_desc;
+	int i;
+
+	/* Optimize the common case when there are no wraparounds */
+	if (likely((void *)tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
+		/* Stamp the freed descriptor */
+		for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE;
+		     i += STAMP_STRIDE) {
+			*ptr = stamp;
+			ptr += STAMP_DWORDS;
+		}
+	} else {
+		/* Stamp the freed descriptor */
+		for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE;
+		     i += STAMP_STRIDE) {
+			*ptr = stamp;
+			ptr += STAMP_DWORDS;
+			if ((void *)ptr >= end) {
+				ptr = ring->buf;
+				stamp ^= cpu_to_be32(0x80000000);
+			}
+		}
+	}
+}
+
 
 static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 				struct mlx4_en_tx_ring *ring,
@@ -205,8 +238,6 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 	void *end = ring->buf + ring->buf_size;
 	int frags = skb_shinfo(skb)->nr_frags;
 	int i;
-	__be32 *ptr = (__be32 *)tx_desc;
-	__be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
 	struct skb_shared_hwtstamps hwts;
 
 	if (timestamp) {
@@ -232,12 +263,6 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 					skb_frag_size(frag), PCI_DMA_TODEVICE);
 			}
 		}
-		/* Stamp the freed descriptor */
-		for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
-			*ptr = stamp;
-			ptr += STAMP_DWORDS;
-		}
-
 	} else {
 		if (!tx_info->inl) {
 			if ((void *) data >= end) {
@@ -263,16 +288,6 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 				++data;
 			}
 		}
-		/* Stamp the freed descriptor */
-		for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
-			*ptr = stamp;
-			ptr += STAMP_DWORDS;
-			if ((void *) ptr >= end) {
-				ptr = ring->buf;
-				stamp ^= cpu_to_be32(0x80000000);
-			}
-		}
-
 	}
 	dev_kfree_skb_any(skb);
 	return tx_info->nr_txbb;
@@ -318,8 +333,9 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 	struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
 	struct mlx4_cqe *cqe;
 	u16 index;
-	u16 new_index, ring_index;
+	u16 new_index, ring_index, stamp_index;
 	u32 txbbs_skipped = 0;
+	u32 txbbs_stamp = 0;
 	u32 cons_index = mcq->cons_index;
 	int size = cq->size;
 	u32 size_mask = ring->size_mask;
@@ -335,6 +351,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 	index = cons_index & size_mask;
 	cqe = &buf[(index << factor) + factor];
 	ring_index = ring->cons & size_mask;
+	stamp_index = ring_index;
 
 	/* Process all completed CQEs */
 	while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
@@ -359,6 +376,12 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 					priv, ring, ring_index,
 					!!((ring->cons + txbbs_skipped) &
 					ring->size), timestamp);
+
+			mlx4_en_stamp_wqe(priv, ring, stamp_index,
+					  !!((ring->cons + txbbs_stamp) &
+						ring->size));
+			stamp_index = ring_index;
+			txbbs_stamp = txbbs_skipped;
 			packets++;
 			bytes += ring->tx_info[ring_index].nr_bytes;
 		} while (ring_index != new_index);
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 7e04286..0416c5b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -79,6 +79,7 @@ enum {
 			       (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE)    | \
 			       (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT)	    | \
 			       (1ull << MLX4_EVENT_TYPE_CMD)		    | \
+			       (1ull << MLX4_EVENT_TYPE_OP_REQUIRED)	    | \
 			       (1ull << MLX4_EVENT_TYPE_COMM_CHANNEL)       | \
 			       (1ull << MLX4_EVENT_TYPE_FLR_EVENT)	    | \
 			       (1ull << MLX4_EVENT_TYPE_FATAL_WARNING))
@@ -629,6 +630,14 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
 			mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn);
 			break;
 
+		case MLX4_EVENT_TYPE_OP_REQUIRED:
+			atomic_inc(&priv->opreq_count);
+			/* FW commands can't be executed from interrupt context
+			 * working in deferred task
+			 */
+			queue_work(mlx4_wq, &priv->opreq_task);
+			break;
+
 		case MLX4_EVENT_TYPE_COMM_CHANNEL:
 			if (!mlx4_is_master(dev)) {
 				mlx4_warn(dev, "Received comm channel event "
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 6fc6dab..0d63daa 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -1696,3 +1696,107 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
 }
 EXPORT_SYMBOL_GPL(mlx4_wol_write);
+
+enum {
+	ADD_TO_MCG = 0x26,
+};
+
+
+void mlx4_opreq_action(struct work_struct *work)
+{
+	struct mlx4_priv *priv = container_of(work, struct mlx4_priv,
+					      opreq_task);
+	struct mlx4_dev *dev = &priv->dev;
+	int num_tasks = atomic_read(&priv->opreq_count);
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_mgm *mgm;
+	u32 *outbox;
+	u32 modifier;
+	u16 token;
+	u16 type_m;
+	u16 type;
+	int err;
+	u32 num_qps;
+	struct mlx4_qp qp;
+	int i;
+	u8 rem_mcg;
+	u8 prot;
+
+#define GET_OP_REQ_MODIFIER_OFFSET	0x08
+#define GET_OP_REQ_TOKEN_OFFSET		0x14
+#define GET_OP_REQ_TYPE_OFFSET		0x1a
+#define GET_OP_REQ_DATA_OFFSET		0x20
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox)) {
+		mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n");
+		return;
+	}
+	outbox = mailbox->buf;
+
+	while (num_tasks) {
+		err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
+				   MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
+				   MLX4_CMD_NATIVE);
+		if (err) {
+			mlx4_err(dev, "Failed to retreive required operation: %d\n",
+				 err);
+			return;
+		}
+		MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
+		MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);
+		MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET);
+		type_m = type >> 12;
+		type &= 0xfff;
+
+		switch (type) {
+		case ADD_TO_MCG:
+			if (dev->caps.steering_mode ==
+			    MLX4_STEERING_MODE_DEVICE_MANAGED) {
+				mlx4_warn(dev, "ADD MCG operation is not supported in DEVICE_MANAGED steering mode\n");
+				err = EPERM;
+				break;
+			}
+			mgm = (struct mlx4_mgm *)((u8 *)(outbox) +
+						  GET_OP_REQ_DATA_OFFSET);
+			num_qps = be32_to_cpu(mgm->members_count) &
+				  MGM_QPN_MASK;
+			rem_mcg = ((u8 *)(&mgm->members_count))[0] & 1;
+			prot = ((u8 *)(&mgm->members_count))[0] >> 6;
+
+			for (i = 0; i < num_qps; i++) {
+				qp.qpn = be32_to_cpu(mgm->qp[i]);
+				if (rem_mcg)
+					err = mlx4_multicast_detach(dev, &qp,
+								    mgm->gid,
+								    prot, 0);
+				else
+					err = mlx4_multicast_attach(dev, &qp,
+								    mgm->gid,
+								    mgm->gid[5]
+								    , 0, prot,
+								    NULL);
+				if (err)
+					break;
+			}
+			break;
+		default:
+			mlx4_warn(dev, "Bad type for required operation\n");
+			err = EINVAL;
+			break;
+		}
+		err = mlx4_cmd(dev, 0, ((u32) err | cpu_to_be32(token) << 16),
+			       1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
+			       MLX4_CMD_NATIVE);
+		if (err) {
+			mlx4_err(dev, "Failed to acknowledge required request: %d\n",
+				 err);
+			goto out;
+		}
+		memset(outbox, 0, 0xffc);
+		num_tasks = atomic_dec_return(&priv->opreq_count);
+	}
+
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index fdf4166..a0a368b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -220,5 +220,6 @@ int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
 int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
 int mlx4_NOP(struct mlx4_dev *dev);
 int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg);
+void mlx4_opreq_action(struct work_struct *work);
 
 #endif /* MLX4_FW_H */
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 36be320..60c9f4f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1692,11 +1692,19 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 		goto err_xrcd_table_free;
 	}
 
+	if (!mlx4_is_slave(dev)) {
+		err = mlx4_init_mcg_table(dev);
+		if (err) {
+			mlx4_err(dev, "Failed to initialize multicast group table, aborting.\n");
+			goto err_mr_table_free;
+		}
+	}
+
 	err = mlx4_init_eq_table(dev);
 	if (err) {
 		mlx4_err(dev, "Failed to initialize "
 			 "event queue table, aborting.\n");
-		goto err_mr_table_free;
+		goto err_mcg_table_free;
 	}
 
 	err = mlx4_cmd_use_events(dev);
@@ -1746,19 +1754,10 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 		goto err_srq_table_free;
 	}
 
-	if (!mlx4_is_slave(dev)) {
-		err = mlx4_init_mcg_table(dev);
-		if (err) {
-			mlx4_err(dev, "Failed to initialize "
-				 "multicast group table, aborting.\n");
-			goto err_qp_table_free;
-		}
-	}
-
 	err = mlx4_init_counters_table(dev);
 	if (err && err != -ENOENT) {
 		mlx4_err(dev, "Failed to initialize counters table, aborting.\n");
-		goto err_mcg_table_free;
+		goto err_qp_table_free;
 	}
 
 	if (!mlx4_is_slave(dev)) {
@@ -1803,9 +1802,6 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 err_counters_table_free:
 	mlx4_cleanup_counters_table(dev);
 
-err_mcg_table_free:
-	mlx4_cleanup_mcg_table(dev);
-
 err_qp_table_free:
 	mlx4_cleanup_qp_table(dev);
 
@@ -1821,6 +1817,10 @@ err_cmd_poll:
 err_eq_table_free:
 	mlx4_cleanup_eq_table(dev);
 
+err_mcg_table_free:
+	if (!mlx4_is_slave(dev))
+		mlx4_cleanup_mcg_table(dev);
+
 err_mr_table_free:
 	mlx4_cleanup_mr_table(dev);
 
@@ -2197,6 +2197,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
 			}
 		}
 
+		atomic_set(&priv->opreq_count, 0);
+		INIT_WORK(&priv->opreq_task, mlx4_opreq_action);
+
 		/*
 		 * Now reset the HCA before we touch the PCI capabilities or
 		 * attempt a firmware command, since a boot ROM may have left
@@ -2315,12 +2318,12 @@ err_port:
 		mlx4_cleanup_port_info(&priv->port[port]);
 
 	mlx4_cleanup_counters_table(dev);
-	mlx4_cleanup_mcg_table(dev);
 	mlx4_cleanup_qp_table(dev);
 	mlx4_cleanup_srq_table(dev);
 	mlx4_cleanup_cq_table(dev);
 	mlx4_cmd_use_polling(dev);
 	mlx4_cleanup_eq_table(dev);
+	mlx4_cleanup_mcg_table(dev);
 	mlx4_cleanup_mr_table(dev);
 	mlx4_cleanup_xrcd_table(dev);
 	mlx4_cleanup_pd_table(dev);
@@ -2403,12 +2406,12 @@ static void mlx4_remove_one(struct pci_dev *pdev)
 						   RES_TR_FREE_SLAVES_ONLY);
 
 		mlx4_cleanup_counters_table(dev);
-		mlx4_cleanup_mcg_table(dev);
 		mlx4_cleanup_qp_table(dev);
 		mlx4_cleanup_srq_table(dev);
 		mlx4_cleanup_cq_table(dev);
 		mlx4_cmd_use_polling(dev);
 		mlx4_cleanup_eq_table(dev);
+		mlx4_cleanup_mcg_table(dev);
 		mlx4_cleanup_mr_table(dev);
 		mlx4_cleanup_xrcd_table(dev);
 		mlx4_cleanup_pd_table(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index f3e804f..55f6245 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -39,19 +39,8 @@
 
 #include "mlx4.h"
 
-#define MGM_QPN_MASK       0x00FFFFFF
-#define MGM_BLCK_LB_BIT    30
-
 static const u8 zero_gid[16];	/* automatically initialized to 0 */
 
-struct mlx4_mgm {
-	__be32			next_gid_index;
-	__be32			members_count;
-	u32			reserved[2];
-	u8			gid[16];
-	__be32			qp[MLX4_MAX_QP_PER_MGM];
-};
-
 int mlx4_get_mgm_entry_size(struct mlx4_dev *dev)
 {
 	return 1 << dev->oper_log_mgm_entry_size;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 17d9277..348bb8c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -554,6 +554,17 @@ struct mlx4_mfunc {
 	struct mlx4_mfunc_master_ctx	master;
 };
 
+#define MGM_QPN_MASK       0x00FFFFFF
+#define MGM_BLCK_LB_BIT    30
+
+struct mlx4_mgm {
+	__be32			next_gid_index;
+	__be32			members_count;
+	u32			reserved[2];
+	u8			gid[16];
+	__be32			qp[MLX4_MAX_QP_PER_MGM];
+};
+
 struct mlx4_cmd {
 	struct pci_pool	       *pool;
 	void __iomem	       *hcr;
@@ -802,6 +813,8 @@ struct mlx4_priv {
 	u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
 	__be64			slave_node_guids[MLX4_MFUNC_MAX];
 
+	atomic_t		opreq_count;
+	struct work_struct	opreq_task;
 };
 
 static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 748f10a..3e6670c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -55,33 +55,9 @@ enum {
 };
 
 static DEFINE_SPINLOCK(health_lock);
-
 static LIST_HEAD(health_list);
 static struct work_struct health_work;
 
-static health_handler_t reg_handler;
-int mlx5_register_health_report_handler(health_handler_t handler)
-{
-	spin_lock_irq(&health_lock);
-	if (reg_handler) {
-		spin_unlock_irq(&health_lock);
-		return -EEXIST;
-	}
-	reg_handler = handler;
-	spin_unlock_irq(&health_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(mlx5_register_health_report_handler);
-
-void mlx5_unregister_health_report_handler(void)
-{
-	spin_lock_irq(&health_lock);
-	reg_handler = NULL;
-	spin_unlock_irq(&health_lock);
-}
-EXPORT_SYMBOL(mlx5_unregister_health_report_handler);
-
 static void health_care(struct work_struct *work)
 {
 	struct mlx5_core_health *health, *n;
@@ -98,11 +74,8 @@ static void health_care(struct work_struct *work)
 		priv = container_of(health, struct mlx5_priv, health);
 		dev = container_of(priv, struct mlx5_core_dev, priv);
 		mlx5_core_warn(dev, "handling bad device here\n");
+		/* nothing yet */
 		spin_lock_irq(&health_lock);
-		if (reg_handler)
-			reg_handler(dev->pdev, health->health,
-				    sizeof(health->health));
-
 		list_del_init(&health->list);
 		spin_unlock_irq(&health_lock);
 	}
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index e393d99..94b3bd6 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -705,7 +705,8 @@ static void ks8842_rx_frame(struct net_device *netdev,
 	ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR);
 }
 
-void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter)
+static void ks8842_handle_rx(struct net_device *netdev,
+	struct ks8842_adapter *adapter)
 {
 	u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
 	netdev_dbg(netdev, "%s Entry - rx_data: %d\n", __func__, rx_data);
@@ -715,7 +716,8 @@ void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter)
 	}
 }
 
-void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter)
+static void ks8842_handle_tx(struct net_device *netdev,
+	struct ks8842_adapter *adapter)
 {
 	u16 sr = ks8842_read16(adapter, 16, REG_TXSR);
 	netdev_dbg(netdev, "%s - entry, sr: %x\n", __func__, sr);
@@ -724,7 +726,7 @@ void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter)
 		netif_wake_queue(netdev);
 }
 
-void ks8842_handle_rx_overrun(struct net_device *netdev,
+static void ks8842_handle_rx_overrun(struct net_device *netdev,
 	struct ks8842_adapter *adapter)
 {
 	netdev_dbg(netdev, "%s: entry\n", __func__);
@@ -732,7 +734,7 @@ void ks8842_handle_rx_overrun(struct net_device *netdev,
 	netdev->stats.rx_fifo_errors++;
 }
 
-void ks8842_tasklet(unsigned long arg)
+static void ks8842_tasklet(unsigned long arg)
 {
 	struct net_device *netdev = (struct net_device *)arg;
 	struct ks8842_adapter *adapter = netdev_priv(netdev);
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index ac20098..9f3f5db 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -688,7 +688,7 @@ static void ks_soft_reset(struct ks_net *ks, unsigned op)
 }
 
 
-void ks_enable_qmu(struct ks_net *ks)
+static void ks_enable_qmu(struct ks_net *ks)
 {
 	u16 w;
 
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 967bae8..d4cdf4d 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -244,7 +244,7 @@ struct myri10ge_priv {
 	int fw_ver_minor;
 	int fw_ver_tiny;
 	int adopted_rx_filter_bug;
-	u8 mac_addr[6];		/* eeprom mac address */
+	u8 mac_addr[ETH_ALEN];		/* eeprom mac address */
 	unsigned long serial_number;
 	int vendor_specific_offset;
 	int fw_multicast_support;
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index e88bdb1..dcfe58f 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -922,7 +922,7 @@ static void __init get_mac_address(struct net_device *dev)
 {
 	struct w90p910_ether *ether = netdev_priv(dev);
 	struct platform_device *pdev;
-	char addr[6];
+	char addr[ETH_ALEN];
 
 	pdev = ether->pdev;
 
@@ -934,7 +934,7 @@ static void __init get_mac_address(struct net_device *dev)
 	addr[5] = 0xa8;
 
 	if (is_valid_ether_addr(addr))
-		memcpy(dev->dev_addr, &addr, 0x06);
+		memcpy(dev->dev_addr, &addr, ETH_ALEN);
 	else
 		dev_err(&pdev->dev, "invalid mac address\n");
 }
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index 7779036..6797b10 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -582,6 +582,19 @@ struct pch_gbe_hw_stats {
 };
 
 /**
+ * struct pch_gbe_privdata - PCI Device ID driver data
+ * @phy_tx_clk_delay:		Bool, configure the PHY TX delay in software
+ * @phy_disable_hibernate:	Bool, disable PHY hibernation
+ * @platform_init:		Platform initialization callback, called from
+ *				probe, prior to PHY initialization.
+ */
+struct pch_gbe_privdata {
+	bool phy_tx_clk_delay;
+	bool phy_disable_hibernate;
+	int (*platform_init)(struct pci_dev *pdev);
+};
+
+/**
  * struct pch_gbe_adapter - board specific private data structure
  * @stats_lock:	Spinlock structure for status
  * @ethtool_lock:	Spinlock structure for ethtool
@@ -604,6 +617,7 @@ struct pch_gbe_hw_stats {
  * @rx_buffer_len:	Receive buffer length
  * @tx_queue_len:	Transmit queue length
  * @have_msi:		PCI MSI mode flag
+ * @pch_gbe_privdata:	PCI Device ID driver_data
  */
 
 struct pch_gbe_adapter {
@@ -631,6 +645,7 @@ struct pch_gbe_adapter {
 	int hwts_tx_en;
 	int hwts_rx_en;
 	struct pci_dev *ptp_pdev;
+	struct pch_gbe_privdata *pdata;
 };
 
 #define pch_gbe_hw_to_adapter(hw)	container_of(hw, struct pch_gbe_adapter, hw)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index ab1039a..e19f1be 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_classify.h>
+#include <linux/gpio.h>
 
 #define DRV_VERSION     "1.01"
 const char pch_driver_version[] = DRV_VERSION;
@@ -111,6 +112,8 @@ const char pch_driver_version[] = DRV_VERSION;
 #define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81"
 #define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00"
 
+#define MINNOW_PHY_RESET_GPIO		13
+
 static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
 
 static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg);
@@ -682,7 +685,7 @@ static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter)
 	}
 	adapter->hw.phy.addr = adapter->mii.phy_id;
 	netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id);
-	if (addr == 32)
+	if (addr == PCH_GBE_PHY_REGS_LEN)
 		return -EAGAIN;
 	/* Selected the phy and isolate the rest */
 	for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
@@ -2635,6 +2638,9 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 	adapter->pdev = pdev;
 	adapter->hw.back = adapter;
 	adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR];
+	adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data;
+	if (adapter->pdata && adapter->pdata->platform_init)
+		adapter->pdata->platform_init(pdev);
 
 	adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number,
 					       PCI_DEVFN(12, 4));
@@ -2710,6 +2716,10 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 
 	dev_dbg(&pdev->dev, "PCH Network Connection\n");
 
+	/* Disable hibernation on certain platforms */
+	if (adapter->pdata && adapter->pdata->phy_disable_hibernate)
+		pch_gbe_phy_disable_hibernate(&adapter->hw);
+
 	device_set_wakeup_enable(&pdev->dev, 1);
 	return 0;
 
@@ -2720,9 +2730,48 @@ err_free_netdev:
 	return ret;
 }
 
+/* The AR803X PHY on the MinnowBoard requires a physical pin to be toggled to
+ * ensure it is awake for probe and init. Request the line and reset the PHY.
+ */
+static int pch_gbe_minnow_platform_init(struct pci_dev *pdev)
+{
+	unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT;
+	unsigned gpio = MINNOW_PHY_RESET_GPIO;
+	int ret;
+
+	ret = devm_gpio_request_one(&pdev->dev, gpio, flags,
+				    "minnow_phy_reset");
+	if (ret) {
+		dev_err(&pdev->dev,
+			"ERR: Can't request PHY reset GPIO line '%d'\n", gpio);
+		return ret;
+	}
+
+	gpio_set_value(gpio, 0);
+	usleep_range(1250, 1500);
+	gpio_set_value(gpio, 1);
+	usleep_range(1250, 1500);
+
+	return ret;
+}
+
+static struct pch_gbe_privdata pch_gbe_minnow_privdata = {
+	.phy_tx_clk_delay = true,
+	.phy_disable_hibernate = true,
+	.platform_init = pch_gbe_minnow_platform_init,
+};
+
 static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
 	{.vendor = PCI_VENDOR_ID_INTEL,
 	 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
+	 .subvendor = PCI_VENDOR_ID_CIRCUITCO,
+	 .subdevice = PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD,
+	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+	 .class_mask = (0xFFFF00),
+	 .driver_data = (kernel_ulong_t)&pch_gbe_minnow_privdata
+	 },
+	{.vendor = PCI_VENDOR_ID_INTEL,
+	 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
 	 .subvendor = PCI_ANY_ID,
 	 .subdevice = PCI_ANY_ID,
 	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
index da07907..8b7ff75 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
@@ -74,6 +74,15 @@
 #define MII_SR_100X_FD_CAPS      0x4000	/* 100X  Full Duplex Capable */
 #define MII_SR_100T4_CAPS        0x8000	/* 100T4 Capable */
 
+/* AR8031 PHY Debug Registers */
+#define PHY_AR803X_ID           0x00001374
+#define PHY_AR8031_DBG_OFF      0x1D
+#define PHY_AR8031_DBG_DAT      0x1E
+#define PHY_AR8031_SERDES       0x05
+#define PHY_AR8031_HIBERNATE    0x0B
+#define PHY_AR8031_SERDES_TX_CLK_DLY   0x0100 /* TX clock delay of 2.0ns */
+#define PHY_AR8031_PS_HIB_EN           0x8000 /* Hibernate enable */
+
 /* Phy Id Register (word 2) */
 #define PHY_REVISION_MASK        0x000F
 
@@ -249,6 +258,51 @@ void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
 }
 
 /**
+ * pch_gbe_phy_tx_clk_delay - Setup TX clock delay via the PHY
+ * @hw:	            Pointer to the HW structure
+ * Returns
+ *	0:		Successful.
+ *	-EINVAL:	Invalid argument.
+ */
+static int pch_gbe_phy_tx_clk_delay(struct pch_gbe_hw *hw)
+{
+	/* The RGMII interface requires a ~2ns TX clock delay. This is typically
+	 * done in layout with a longer trace or via PHY strapping, but can also
+	 * be done via PHY configuration registers.
+	 */
+	struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
+	u16 mii_reg;
+	int ret = 0;
+
+	switch (hw->phy.id) {
+	case PHY_AR803X_ID:
+		netdev_dbg(adapter->netdev,
+			   "Configuring AR803X PHY for 2ns TX clock delay\n");
+		pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_OFF, &mii_reg);
+		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
+						 PHY_AR8031_SERDES);
+		if (ret)
+			break;
+
+		pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
+		mii_reg |= PHY_AR8031_SERDES_TX_CLK_DLY;
+		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
+						 mii_reg);
+		break;
+	default:
+		netdev_err(adapter->netdev,
+			   "Unknown PHY (%x), could not set TX clock delay\n",
+			   hw->phy.id);
+		return -EINVAL;
+	}
+
+	if (ret)
+		netdev_err(adapter->netdev,
+			   "Could not configure tx clock delay for PHY\n");
+	return ret;
+}
+
+/**
  * pch_gbe_phy_init_setting - PHY initial setting
  * @hw:	            Pointer to the HW structure
  */
@@ -277,4 +331,48 @@ void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
 	pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
 	mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
 	pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
+
+	/* Setup a TX clock delay on certain platforms */
+	if (adapter->pdata && adapter->pdata->phy_tx_clk_delay)
+		pch_gbe_phy_tx_clk_delay(hw);
+}
+
+/**
+ * pch_gbe_phy_disable_hibernate - Disable the PHY low power state
+ * @hw:	            Pointer to the HW structure
+ * Returns
+ *	0:		Successful.
+ *	-EINVAL:	Invalid argument.
+ */
+int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw)
+{
+	struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
+	u16 mii_reg;
+	int ret = 0;
+
+	switch (hw->phy.id) {
+	case PHY_AR803X_ID:
+		netdev_dbg(adapter->netdev,
+			   "Disabling hibernation for AR803X PHY\n");
+		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
+						 PHY_AR8031_HIBERNATE);
+		if (ret)
+			break;
+
+		pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
+		mii_reg &= ~PHY_AR8031_PS_HIB_EN;
+		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
+						 mii_reg);
+		break;
+	default:
+		netdev_err(adapter->netdev,
+			   "Unknown PHY (%x), could not disable hibernation\n",
+			   hw->phy.id);
+		return -EINVAL;
+	}
+
+	if (ret)
+		netdev_err(adapter->netdev,
+			   "Could not disable PHY hibernation\n");
+	return ret;
 }
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
index 03264dc..0cbe692 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
@@ -33,5 +33,6 @@ void pch_gbe_phy_power_up(struct pch_gbe_hw *hw);
 void pch_gbe_phy_power_down(struct pch_gbe_hw *hw);
 void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw);
 void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw);
+int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw);
 
 #endif /* _PCH_GBE_PHY_H_ */
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index a5f0b5d..f21ae7b 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -191,7 +191,7 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
 	struct device_node *dn = pci_device_to_OF_node(pdev);
 	int len;
 	const u8 *maddr;
-	u8 addr[6];
+	u8 addr[ETH_ALEN];
 
 	if (!dn) {
 		dev_dbg(&pdev->dev,
@@ -201,8 +201,8 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
 
 	maddr = of_get_property(dn, "local-mac-address", &len);
 
-	if (maddr && len == 6) {
-		memcpy(mac->mac_addr, maddr, 6);
+	if (maddr && len == ETH_ALEN) {
+		memcpy(mac->mac_addr, maddr, ETH_ALEN);
 		return 0;
 	}
 
@@ -219,14 +219,15 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
 		return -ENOENT;
 	}
 
-	if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
-		   &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
+	if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+		   &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
+	    != ETH_ALEN) {
 		dev_warn(&pdev->dev,
 			 "can't parse mac address, not configuring\n");
 		return -EINVAL;
 	}
 
-	memcpy(mac->mac_addr, addr, 6);
+	memcpy(mac->mac_addr, addr, ETH_ALEN);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.h b/drivers/net/ethernet/pasemi/pasemi_mac.h
index e2f4efa..f2749d4 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.h
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.h
@@ -83,7 +83,7 @@ struct pasemi_mac {
 #define MAC_TYPE_GMAC	1
 #define MAC_TYPE_XAUI	2
 
-	u8		mac_addr[6];
+	u8		mac_addr[ETH_ALEN];
 
 	struct net_lro_mgr	lro_mgr;
 	struct net_lro_desc	lro_desc[MAX_LRO_DESCRIPTORS];
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
index 9fbb1cd..8375cbd 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
@@ -536,10 +536,10 @@ static void netxen_p2_nic_set_multi(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct netdev_hw_addr *ha;
-	u8 null_addr[6];
+	u8 null_addr[ETH_ALEN];
 	int i;
 
-	memset(null_addr, 0, 6);
+	memset(null_addr, 0, ETH_ALEN);
 
 	if (netdev->flags & IFF_PROMISC) {
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 221645e..3935155 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -20,7 +20,6 @@
 #include <linux/tcp.h>
 #include <linux/skbuff.h>
 #include <linux/firmware.h>
-
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/timer.h>
@@ -38,8 +37,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 2
-#define _QLCNIC_LINUX_SUBVERSION 44
-#define QLCNIC_LINUX_VERSIONID  "5.2.44"
+#define _QLCNIC_LINUX_SUBVERSION 45
+#define QLCNIC_LINUX_VERSIONID  "5.2.45"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -467,7 +466,7 @@ struct qlcnic_hardware_context {
 	u32 *ext_reg_tbl;
 	u32 mbox_aen[QLC_83XX_MBX_AEN_CNT];
 	u32 mbox_reg[4];
-	spinlock_t mbx_lock;
+	struct qlcnic_mailbox *mailbox;
 };
 
 struct qlcnic_adapter_stats {
@@ -950,12 +949,6 @@ struct qlcnic_ipaddr {
 #define QLCNIC_READD_AGE	20
 #define QLCNIC_LB_MAX_FILTERS	64
 #define QLCNIC_LB_BUCKET_SIZE	32
-
-/* QLCNIC Driver Error Code */
-#define QLCNIC_FW_NOT_RESPOND		51
-#define QLCNIC_TEST_IN_PROGRESS		52
-#define QLCNIC_UNDEFINED_ERROR		53
-#define QLCNIC_LB_CABLE_NOT_CONN	54
 #define QLCNIC_ILB_MAX_RCV_LOOP	10
 
 struct qlcnic_filter {
@@ -972,6 +965,21 @@ struct qlcnic_filter_hash {
 	u16 fbucket_size;
 };
 
+/* Mailbox specific data structures */
+struct qlcnic_mailbox {
+	struct workqueue_struct	*work_q;
+	struct qlcnic_adapter	*adapter;
+	struct qlcnic_mbx_ops	*ops;
+	struct work_struct	work;
+	struct completion	completion;
+	struct list_head	cmd_q;
+	unsigned long		status;
+	spinlock_t		queue_lock;	/* Mailbox queue lock */
+	spinlock_t		aen_lock;	/* Mailbox response/AEN lock */
+	atomic_t		rsp_status;
+	u32			num_cmds;
+};
+
 struct qlcnic_adapter {
 	struct qlcnic_hardware_context *ahw;
 	struct qlcnic_recv_context *recv_ctx;
@@ -1385,9 +1393,20 @@ struct _cdrp_cmd {
 };
 
 struct qlcnic_cmd_args {
-	struct _cdrp_cmd req;
-	struct _cdrp_cmd rsp;
-	int op_type;
+	struct completion	completion;
+	struct list_head	list;
+	struct _cdrp_cmd	req;
+	struct _cdrp_cmd	rsp;
+	atomic_t		rsp_status;
+	int			pay_size;
+	u32			rsp_opcode;
+	u32			total_cmds;
+	u32			op_type;
+	u32			type;
+	u32			cmd_op;
+	u32			*hdr;	/* Back channel message header */
+	u32			*pay;	/* Back channel message payload */
+	u8			func_num;
 };
 
 int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
@@ -1600,6 +1619,20 @@ struct qlcnic_nic_template {
 	int (*resume)(struct qlcnic_adapter *);
 };
 
+struct qlcnic_mbx_ops {
+	int (*enqueue_cmd) (struct qlcnic_adapter *,
+			    struct qlcnic_cmd_args *, unsigned long *);
+	void (*dequeue_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+	void (*decode_resp) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+	void (*encode_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+	void (*nofity_fw) (struct qlcnic_adapter *, u8);
+};
+
+int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
+void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
+void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
+void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);
+
 /* Adapter hardware abstraction */
 struct qlcnic_hardware_ops {
 	void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 92da998..55a5977 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -149,7 +149,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
 	.get_mac_address		= qlcnic_83xx_get_mac_address,
 	.setup_intr			= qlcnic_83xx_setup_intr,
 	.alloc_mbx_args			= qlcnic_83xx_alloc_mbx_args,
-	.mbx_cmd			= qlcnic_83xx_mbx_op,
+	.mbx_cmd			= qlcnic_83xx_issue_cmd,
 	.get_func_no			= qlcnic_83xx_get_func_no,
 	.api_lock			= qlcnic_83xx_cam_lock,
 	.api_unlock			= qlcnic_83xx_cam_unlock,
@@ -362,6 +362,10 @@ static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
 				     struct qlcnic_cmd_args *cmd)
 {
 	int i;
+
+	if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP)
+		return;
+
 	for (i = 0; i < cmd->rsp.num; i++)
 		cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
 }
@@ -398,24 +402,33 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
 	return IRQ_HANDLED;
 }
 
+static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx)
+{
+	atomic_set(&mbx->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED);
+	complete(&mbx->completion);
+}
+
 static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
 {
-	u32 resp, event;
+	u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
 	unsigned long flags;
 
-	spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
-
+	spin_lock_irqsave(&mbx->aen_lock, flags);
 	resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
 	if (!(resp & QLCNIC_SET_OWNER))
 		goto out;
 
 	event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
-	if (event &  QLCNIC_MBX_ASYNC_EVENT)
+	if (event &  QLCNIC_MBX_ASYNC_EVENT) {
 		__qlcnic_83xx_process_aen(adapter);
-
+	} else {
+		if (atomic_read(&mbx->rsp_status) != rsp_status)
+			qlcnic_83xx_notify_mbx_response(mbx);
+	}
 out:
 	qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
-	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
+	spin_unlock_irqrestore(&mbx->aen_lock, flags);
 }
 
 irqreturn_t qlcnic_83xx_intr(int irq, void *data)
@@ -515,7 +528,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
 	}
 
 	/* Enable mailbox interrupt */
-	qlcnic_83xx_enable_mbx_intrpt(adapter);
+	qlcnic_83xx_enable_mbx_interrupt(adapter);
 
 	return err;
 }
@@ -628,7 +641,7 @@ void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
 	ahw->max_uc_count = count;
 }
 
-void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
+void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *adapter)
 {
 	u32 val;
 
@@ -687,6 +700,9 @@ static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
 {
 	int i;
 
+	if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP)
+		return;
+
 	dev_info(&adapter->pdev->dev,
 		 "Host MBX regs(%d)\n", cmd->req.num);
 	for (i = 0; i < cmd->req.num; i++) {
@@ -705,120 +721,74 @@ static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
 	pr_info("\n");
 }
 
-/* Mailbox response for mac rcode */
-u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
+static inline void
+qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
+				    struct qlcnic_cmd_args *cmd)
 {
-	u32 fw_data;
-	u8 mac_cmd_rcode;
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	int opcode = LSW(cmd->req.arg[0]);
+	unsigned long max_loops;
 
-	fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2));
-	mac_cmd_rcode = (u8)fw_data;
-	if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
-	    mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
-	    mac_cmd_rcode == QLC_83XX_MAC_ABSENT)
-		return QLCNIC_RCODE_SUCCESS;
-	return 1;
-}
+	max_loops = cmd->total_cmds * QLC_83XX_MBX_CMD_LOOP;
 
-u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time)
-{
-	u32 data;
-	struct qlcnic_hardware_context *ahw = adapter->ahw;
-	/* wait for mailbox completion */
-	do {
-		data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
-		if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) {
-			data = QLCNIC_RCODE_TIMEOUT;
-			break;
-		}
-		mdelay(1);
-	} while (!data);
-	return data;
+	for (; max_loops; max_loops--) {
+		if (atomic_read(&cmd->rsp_status) ==
+		    QLC_83XX_MBX_RESPONSE_ARRIVED)
+			return;
+
+		udelay(1);
+	}
+
+	dev_err(&adapter->pdev->dev,
+		"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
+		__func__, opcode, cmd->type, ahw->pci_func, ahw->op_mode);
+	flush_workqueue(ahw->mailbox->work_q);
+	return;
 }
 
-int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
-		       struct qlcnic_cmd_args *cmd)
+int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter,
+			  struct qlcnic_cmd_args *cmd)
 {
-	int i;
-	u16 opcode;
-	u8 mbx_err_code;
-	unsigned long flags;
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
-	u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0;
+	int cmd_type, err, opcode;
+	unsigned long timeout;
 
 	opcode = LSW(cmd->req.arg[0]);
-	if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
-		dev_info(&adapter->pdev->dev,
-			 "Mailbox cmd attempted, 0x%x\n", opcode);
-		dev_info(&adapter->pdev->dev, "Mailbox detached\n");
-		return 0;
+	cmd_type = cmd->type;
+	err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"%s: Mailbox not available, cmd_op=0x%x, cmd_context=0x%x, pci_func=0x%x, op_mode=0x%x\n",
+			__func__, opcode, cmd->type, ahw->pci_func,
+			ahw->op_mode);
+		return err;
 	}
 
-	spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
-	mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
-
-	if (mbx_val) {
-		QLCDB(adapter, DRV,
-		      "Mailbox cmd attempted, 0x%x\n", opcode);
-		QLCDB(adapter, DRV,
-		      "Mailbox not available, 0x%x, collect FW dump\n",
-		      mbx_val);
-		cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
-		spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
-		return cmd->rsp.arg[0];
-	}
-
-	/* Fill in mailbox registers */
-	mbx_cmd = cmd->req.arg[0];
-	writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
-	for (i = 1; i < cmd->req.num; i++)
-		writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
-
-	/* Signal FW about the impending command */
-	QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
-poll:
-	rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
-	if (rsp != QLCNIC_RCODE_TIMEOUT) {
-		/* Get the FW response data */
-		fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
-		if (fw_data &  QLCNIC_MBX_ASYNC_EVENT) {
-			__qlcnic_83xx_process_aen(adapter);
-			goto poll;
-		}
-		mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
-		rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
-		opcode = QLCNIC_MBX_RSP(fw_data);
-		qlcnic_83xx_get_mbx_data(adapter, cmd);
-
-		switch (mbx_err_code) {
-		case QLCNIC_MBX_RSP_OK:
-		case QLCNIC_MBX_PORT_RSP_OK:
-			rsp = QLCNIC_RCODE_SUCCESS;
-			break;
-		default:
-			if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
-				rsp = qlcnic_83xx_mac_rcode(adapter);
-				if (!rsp)
-					goto out;
-			}
+	switch (cmd_type) {
+	case QLC_83XX_MBX_CMD_WAIT:
+		if (!wait_for_completion_timeout(&cmd->completion, timeout)) {
 			dev_err(&adapter->pdev->dev,
-				"MBX command 0x%x failed with err:0x%x\n",
-				opcode, mbx_err_code);
-			rsp = mbx_err_code;
-			qlcnic_dump_mbx(adapter, cmd);
-			break;
+				"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
+				__func__, opcode, cmd_type, ahw->pci_func,
+				ahw->op_mode);
+			flush_workqueue(mbx->work_q);
 		}
-		goto out;
+		break;
+	case QLC_83XX_MBX_CMD_NO_WAIT:
+		return 0;
+	case QLC_83XX_MBX_CMD_BUSY_WAIT:
+		qlcnic_83xx_poll_for_mbx_completion(adapter, cmd);
+		break;
+	default:
+		dev_err(&adapter->pdev->dev,
+			"%s: Invalid mailbox command, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
+			__func__, opcode, cmd_type, ahw->pci_func,
+			ahw->op_mode);
+		qlcnic_83xx_detach_mailbox_work(adapter);
 	}
 
-	dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n",
-		QLCNIC_MBX_RSP(mbx_cmd));
-	rsp = QLCNIC_RCODE_TIMEOUT;
-out:
-	/* clear fw mbx control register */
-	QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
-	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
-	return rsp;
+	return cmd->rsp_opcode;
 }
 
 int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
@@ -828,6 +798,7 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
 	u32 temp;
 	const struct qlcnic_mailbox_metadata *mbx_tbl;
 
+	memset(mbx, 0, sizeof(struct qlcnic_cmd_args));
 	mbx_tbl = qlcnic_83xx_mbx_tbl;
 	size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
 	for (i = 0; i < size; i++) {
@@ -850,6 +821,7 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
 			memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
 			temp = adapter->ahw->fw_hal_version << 29;
 			mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
+			mbx->cmd_op = type;
 			return 0;
 		}
 	}
@@ -933,20 +905,23 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
 
 static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
 {
+	u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
-	u32 resp, event;
+	struct qlcnic_mailbox *mbx = ahw->mailbox;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ahw->mbx_lock, flags);
-
+	spin_lock_irqsave(&mbx->aen_lock, flags);
 	resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
 	if (resp & QLCNIC_SET_OWNER) {
 		event = readl(QLCNIC_MBX_FW(ahw, 0));
-		if (event &  QLCNIC_MBX_ASYNC_EVENT)
+		if (event &  QLCNIC_MBX_ASYNC_EVENT) {
 			__qlcnic_83xx_process_aen(adapter);
+		} else {
+			if (atomic_read(&mbx->rsp_status) != rsp_status)
+				qlcnic_83xx_notify_mbx_response(mbx);
+		}
 	}
-
-	spin_unlock_irqrestore(&ahw->mbx_lock, flags);
+	spin_unlock_irqrestore(&mbx->aen_lock, flags);
 }
 
 static void qlcnic_83xx_mbx_poll_work(struct work_struct *work)
@@ -969,6 +944,7 @@ void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *adapter)
 		return;
 
 	INIT_DELAYED_WORK(&adapter->mbx_poll_work, qlcnic_83xx_mbx_poll_work);
+	queue_delayed_work(adapter->qlcnic_wq, &adapter->mbx_poll_work, 0);
 }
 
 void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *adapter)
@@ -1355,8 +1331,10 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
 
 	if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
 		/* disable and free mailbox interrupt */
-		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
+		if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
+			qlcnic_83xx_enable_mbx_poll(adapter);
 			qlcnic_83xx_free_mbx_intr(adapter);
+		}
 		adapter->ahw->loopback_state = 0;
 		adapter->ahw->hw_ops->setup_link_event(adapter, 1);
 	}
@@ -1377,6 +1355,8 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 		for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 			sds_ring = &adapter->recv_ctx->sds_rings[ring];
 			qlcnic_83xx_disable_intr(adapter, sds_ring);
+			if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
+				qlcnic_83xx_enable_mbx_poll(adapter);
 		}
 	}
 
@@ -1386,6 +1366,7 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 	if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
 		if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
 			err = qlcnic_83xx_setup_mbx_intr(adapter);
+			qlcnic_83xx_disable_mbx_poll(adapter);
 			if (err) {
 				dev_err(&adapter->pdev->dev,
 					"%s: failed to setup mbx interrupt\n",
@@ -1402,6 +1383,10 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 
 	if (netif_running(netdev))
 		__qlcnic_up(adapter, netdev);
+
+	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
+	    !(adapter->flags & QLCNIC_MSIX_ENABLED))
+		qlcnic_83xx_disable_mbx_poll(adapter);
 out:
 	netif_device_attach(netdev);
 }
@@ -1619,26 +1604,33 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
 
 int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
 {
-	int err;
+	struct qlcnic_cmd_args *cmd = NULL;
 	u32 temp = 0;
-	struct qlcnic_cmd_args cmd;
+	int err;
 
 	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
 		return -EIO;
 
-	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+	if (!cmd)
+		return -ENOMEM;
+
+	err = qlcnic_alloc_mbx_args(cmd, adapter,
 				    QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
 	if (err)
-		return err;
+		goto out;
 
+	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
 	qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
-	cmd.req.arg[1] = (mode ? 1 : 0) | temp;
-	err = qlcnic_issue_cmd(adapter, &cmd);
-	if (err)
-		dev_info(&adapter->pdev->dev,
-			 "Promiscous mode config failed\n");
+	cmd->req.arg[1] = (mode ? 1 : 0) | temp;
+	err = qlcnic_issue_cmd(adapter, cmd);
+	if (!err)
+		return err;
 
-	qlcnic_free_mbx_args(&cmd);
+	qlcnic_free_mbx_args(cmd);
+
+out:
+	kfree(cmd);
 	return err;
 }
 
@@ -1651,7 +1643,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
 	if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
 		netdev_warn(netdev,
 			    "Loopback test not supported in non privileged mode\n");
-		return ret;
+		return -ENOTSUPP;
 	}
 
 	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
@@ -1679,19 +1671,17 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
 	/* Poll for link up event before running traffic */
 	do {
 		msleep(QLC_83XX_LB_MSLEEP_COUNT);
-		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-			qlcnic_83xx_process_aen(adapter);
 
 		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
 			netdev_info(netdev,
 				    "Device is resetting, free LB test resources\n");
-			ret = -EIO;
+			ret = -EBUSY;
 			goto free_diag_res;
 		}
 		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
 			netdev_info(netdev,
 				    "Firmware didn't sent link up event to loopback request\n");
-			ret = -QLCNIC_FW_NOT_RESPOND;
+			ret = -ETIMEDOUT;
 			qlcnic_83xx_clear_lb_mode(adapter, mode);
 			goto free_diag_res;
 		}
@@ -1728,6 +1718,15 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 		return status;
 
 	config = ahw->port_config;
+
+	/* Check if port is already in loopback mode */
+	if ((config & QLC_83XX_CFG_LOOPBACK_HSS) ||
+	    (config & QLC_83XX_CFG_LOOPBACK_EXT)) {
+		netdev_err(netdev,
+			   "Port already in Loopback mode.\n");
+		return -EINPROGRESS;
+	}
+
 	set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
 
 	if (mode == QLCNIC_ILB_MODE)
@@ -1748,21 +1747,19 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 	/* Wait for Link and IDC Completion AEN */
 	do {
 		msleep(QLC_83XX_LB_MSLEEP_COUNT);
-		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-			qlcnic_83xx_process_aen(adapter);
 
 		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
 			netdev_info(netdev,
 				    "Device is resetting, free LB test resources\n");
 			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
-			return -EIO;
+			return -EBUSY;
 		}
 		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
 			netdev_err(netdev,
 				   "Did not receive IDC completion AEN\n");
 			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
 			qlcnic_83xx_clear_lb_mode(adapter, mode);
-			return -EIO;
+			return -ETIMEDOUT;
 		}
 	} while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
 
@@ -1797,21 +1794,19 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 	/* Wait for Link and IDC Completion AEN */
 	do {
 		msleep(QLC_83XX_LB_MSLEEP_COUNT);
-		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-			qlcnic_83xx_process_aen(adapter);
 
 		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
 			netdev_info(netdev,
 				    "Device is resetting, free LB test resources\n");
 			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
-			return -EIO;
+			return -EBUSY;
 		}
 
 		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
 			netdev_err(netdev,
 				   "Did not receive IDC completion AEN\n");
 			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
-			return -EIO;
+			return -ETIMEDOUT;
 		}
 	} while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
 
@@ -1950,25 +1945,31 @@ static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
 int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
 				   u16 vlan_id, u8 op)
 {
-	int err;
-	u32 *buf, temp = 0;
-	struct qlcnic_cmd_args cmd;
+	struct qlcnic_cmd_args *cmd = NULL;
 	struct qlcnic_macvlan_mbx mv;
+	u32 *buf, temp = 0;
+	int err;
 
 	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
 		return -EIO;
 
-	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
+	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+	if (!cmd)
+		return -ENOMEM;
+
+	err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
 	if (err)
-		return err;
+		goto out;
+
+	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
 
 	if (vlan_id)
 		op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
 		     QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;
 
-	cmd.req.arg[1] = op | (1 << 8);
+	cmd->req.arg[1] = op | (1 << 8);
 	qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
-	cmd.req.arg[1] |= temp;
+	cmd->req.arg[1] |= temp;
 	mv.vlan = vlan_id;
 	mv.mac_addr0 = addr[0];
 	mv.mac_addr1 = addr[1];
@@ -1976,14 +1977,15 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
 	mv.mac_addr3 = addr[3];
 	mv.mac_addr4 = addr[4];
 	mv.mac_addr5 = addr[5];
-	buf = &cmd.req.arg[2];
+	buf = &cmd->req.arg[2];
 	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
-	err = qlcnic_issue_cmd(adapter, &cmd);
-	if (err)
-		dev_err(&adapter->pdev->dev,
-			"MAC-VLAN %s to CAM failed, err=%d.\n",
-			((op == 1) ? "add " : "delete "), err);
-	qlcnic_free_mbx_args(&cmd);
+	err = qlcnic_issue_cmd(adapter, cmd);
+	if (!err)
+		return err;
+
+	qlcnic_free_mbx_args(cmd);
+out:
+	kfree(cmd);
 	return err;
 }
 
@@ -2099,10 +2101,12 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
 irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
 {
 	struct qlcnic_adapter *adapter = data;
-	unsigned long flags;
+	struct qlcnic_mailbox *mbx;
 	u32 mask, resp, event;
+	unsigned long flags;
 
-	spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
+	mbx = adapter->ahw->mailbox;
+	spin_lock_irqsave(&mbx->aen_lock, flags);
 	resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
 	if (!(resp & QLCNIC_SET_OWNER))
 		goto out;
@@ -2110,11 +2114,13 @@ irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
 	event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
 	if (event &  QLCNIC_MBX_ASYNC_EVENT)
 		__qlcnic_83xx_process_aen(adapter);
+	else
+		qlcnic_83xx_notify_mbx_response(mbx);
+
 out:
 	mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
 	writel(0, adapter->ahw->pci_base0 + mask);
-	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
-
+	spin_unlock_irqrestore(&mbx->aen_lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -3472,3 +3478,300 @@ int qlcnic_83xx_resume(struct qlcnic_adapter *adapter)
 			     idc->delay);
 	return err;
 }
+
+void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx)
+{
+	INIT_COMPLETION(mbx->completion);
+	set_bit(QLC_83XX_MBX_READY, &mbx->status);
+}
+
+void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx)
+{
+	destroy_workqueue(mbx->work_q);
+	kfree(mbx);
+}
+
+static inline void
+qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter,
+				  struct qlcnic_cmd_args *cmd)
+{
+	atomic_set(&cmd->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED);
+
+	if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) {
+		qlcnic_free_mbx_args(cmd);
+		kfree(cmd);
+		return;
+	}
+	complete(&cmd->completion);
+}
+
+static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
+	struct list_head *head = &mbx->cmd_q;
+	struct qlcnic_cmd_args *cmd = NULL;
+
+	spin_lock(&mbx->queue_lock);
+
+	while (!list_empty(head)) {
+		cmd = list_entry(head->next, struct qlcnic_cmd_args, list);
+		list_del(&cmd->list);
+		mbx->num_cmds--;
+		qlcnic_83xx_notify_cmd_completion(adapter, cmd);
+	}
+
+	spin_unlock(&mbx->queue_lock);
+}
+
+static inline int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_mailbox *mbx = ahw->mailbox;
+	u32 host_mbx_ctrl;
+
+	if (!test_bit(QLC_83XX_MBX_READY, &mbx->status))
+		return -EBUSY;
+
+	host_mbx_ctrl = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+	if (host_mbx_ctrl) {
+		ahw->idc.collect_dump = 1;
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter,
+					      u8 issue_cmd)
+{
+	if (issue_cmd)
+		QLCWRX(adapter->ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
+	else
+		QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+}
+
+static inline void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter,
+					       struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
+
+	spin_lock(&mbx->queue_lock);
+
+	list_del(&cmd->list);
+	mbx->num_cmds--;
+
+	spin_unlock(&mbx->queue_lock);
+
+	qlcnic_83xx_notify_cmd_completion(adapter, cmd);
+}
+
+static void qlcnic_83xx_encode_mbx_cmd(struct qlcnic_adapter *adapter,
+				       struct qlcnic_cmd_args *cmd)
+{
+	u32 mbx_cmd, fw_hal_version, hdr_size, total_size, tmp;
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	int i, j;
+
+	if (cmd->op_type != QLC_83XX_MBX_POST_BC_OP) {
+		mbx_cmd = cmd->req.arg[0];
+		writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
+		for (i = 1; i < cmd->req.num; i++)
+			writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
+	} else {
+		fw_hal_version = ahw->fw_hal_version;
+		hdr_size = sizeof(struct qlcnic_bc_hdr) / sizeof(u32);
+		total_size = cmd->pay_size + hdr_size;
+		tmp = QLCNIC_CMD_BC_EVENT_SETUP | total_size << 16;
+		mbx_cmd = tmp | fw_hal_version << 29;
+		writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
+
+		/* Back channel specific operations bits */
+		mbx_cmd = 0x1 | 1 << 4;
+
+		if (qlcnic_sriov_pf_check(adapter))
+			mbx_cmd |= cmd->func_num << 5;
+
+		writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1));
+
+		for (i = 2, j = 0; j < hdr_size; i++, j++)
+			writel(*(cmd->hdr++), QLCNIC_MBX_HOST(ahw, i));
+		for (j = 0; j < cmd->pay_size; j++, i++)
+			writel(*(cmd->pay++), QLCNIC_MBX_HOST(ahw, i));
+	}
+}
+
+void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
+
+	clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+	complete(&mbx->completion);
+	cancel_work_sync(&mbx->work);
+	flush_workqueue(mbx->work_q);
+	qlcnic_83xx_flush_mbx_queue(adapter);
+}
+
+static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
+					      struct qlcnic_cmd_args *cmd,
+					      unsigned long *timeout)
+{
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
+
+	if (test_bit(QLC_83XX_MBX_READY, &mbx->status)) {
+		atomic_set(&cmd->rsp_status, QLC_83XX_MBX_RESPONSE_WAIT);
+		init_completion(&cmd->completion);
+		cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_UNKNOWN;
+
+		spin_lock(&mbx->queue_lock);
+
+		list_add_tail(&cmd->list, &mbx->cmd_q);
+		mbx->num_cmds++;
+		cmd->total_cmds = mbx->num_cmds;
+		*timeout = cmd->total_cmds * QLC_83XX_MBX_TIMEOUT;
+		queue_work(mbx->work_q, &mbx->work);
+
+		spin_unlock(&mbx->queue_lock);
+
+		return 0;
+	}
+
+	return -EBUSY;
+}
+
+static inline int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter,
+					      struct qlcnic_cmd_args *cmd)
+{
+	u8 mac_cmd_rcode;
+	u32 fw_data;
+
+	if (cmd->cmd_op == QLCNIC_CMD_CONFIG_MAC_VLAN) {
+		fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2));
+		mac_cmd_rcode = (u8)fw_data;
+		if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
+		    mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
+		    mac_cmd_rcode == QLC_83XX_MAC_ABSENT) {
+			cmd->rsp_opcode = QLCNIC_RCODE_SUCCESS;
+			return QLCNIC_RCODE_SUCCESS;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
+				       struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct device *dev = &adapter->pdev->dev;
+	u8 mbx_err_code;
+	u32 fw_data;
+
+	fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
+	mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
+	qlcnic_83xx_get_mbx_data(adapter, cmd);
+
+	switch (mbx_err_code) {
+	case QLCNIC_MBX_RSP_OK:
+	case QLCNIC_MBX_PORT_RSP_OK:
+		cmd->rsp_opcode = QLCNIC_RCODE_SUCCESS;
+		break;
+	default:
+		if (!qlcnic_83xx_check_mac_rcode(adapter, cmd))
+			break;
+
+		dev_err(dev, "%s: Mailbox command failed, opcode=0x%x, cmd_type=0x%x, func=0x%x, op_mode=0x%x, error=0x%x\n",
+			__func__, cmd->cmd_op, cmd->type, ahw->pci_func,
+			ahw->op_mode, mbx_err_code);
+		cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_FAILED;
+		qlcnic_dump_mbx(adapter, cmd);
+	}
+
+	return;
+}
+
+static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
+{
+	struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
+						  work);
+	struct qlcnic_adapter *adapter = mbx->adapter;
+	struct qlcnic_mbx_ops *mbx_ops = mbx->ops;
+	struct device *dev = &adapter->pdev->dev;
+	atomic_t *rsp_status = &mbx->rsp_status;
+	struct list_head *head = &mbx->cmd_q;
+	struct qlcnic_hardware_context *ahw;
+	struct qlcnic_cmd_args *cmd = NULL;
+
+	ahw = adapter->ahw;
+
+	while (true) {
+		if (qlcnic_83xx_check_mbx_status(adapter))
+			return;
+
+		atomic_set(rsp_status, QLC_83XX_MBX_RESPONSE_WAIT);
+
+		spin_lock(&mbx->queue_lock);
+
+		if (list_empty(head)) {
+			spin_unlock(&mbx->queue_lock);
+			return;
+		}
+		cmd = list_entry(head->next, struct qlcnic_cmd_args, list);
+
+		spin_unlock(&mbx->queue_lock);
+
+		mbx_ops->encode_cmd(adapter, cmd);
+		mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_REQUEST);
+
+		if (wait_for_completion_timeout(&mbx->completion,
+						QLC_83XX_MBX_TIMEOUT)) {
+			mbx_ops->decode_resp(adapter, cmd);
+			mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_COMPLETION);
+		} else {
+			dev_err(dev, "%s: Mailbox command timeout, opcode=0x%x, cmd_type=0x%x, func=0x%x, op_mode=0x%x\n",
+				__func__, cmd->cmd_op, cmd->type, ahw->pci_func,
+				ahw->op_mode);
+			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+			qlcnic_83xx_idc_request_reset(adapter,
+						      QLCNIC_FORCE_FW_DUMP_KEY);
+			cmd->rsp_opcode = QLCNIC_RCODE_TIMEOUT;
+		}
+		mbx_ops->dequeue_cmd(adapter, cmd);
+	}
+}
+
+static struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = {
+	.enqueue_cmd    = qlcnic_83xx_enqueue_mbx_cmd,
+	.dequeue_cmd    = qlcnic_83xx_dequeue_mbx_cmd,
+	.decode_resp    = qlcnic_83xx_decode_mbx_rsp,
+	.encode_cmd     = qlcnic_83xx_encode_mbx_cmd,
+	.nofity_fw      = qlcnic_83xx_signal_mbx_cmd,
+};
+
+int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_mailbox *mbx;
+
+	ahw->mailbox = kzalloc(sizeof(*mbx), GFP_KERNEL);
+	if (!ahw->mailbox)
+		return -ENOMEM;
+
+	mbx = ahw->mailbox;
+	mbx->ops = &qlcnic_83xx_mbx_ops;
+	mbx->adapter = adapter;
+
+	spin_lock_init(&mbx->queue_lock);
+	spin_lock_init(&mbx->aen_lock);
+	INIT_LIST_HEAD(&mbx->cmd_q);
+	init_completion(&mbx->completion);
+
+	mbx->work_q = create_singlethread_workqueue("qlcnic_mailbox");
+	if (mbx->work_q == NULL) {
+		kfree(mbx);
+		return -ENOMEM;
+	}
+
+	INIT_WORK(&mbx->work, qlcnic_83xx_mailbox_worker);
+	set_bit(QLC_83XX_MBX_READY, &mbx->status);
+	return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 272f56a..dd22ef3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -89,6 +89,13 @@
 
 #define QLC_83XX_MAX_RESET_SEQ_ENTRIES	16
 
+#define QLC_83XX_MBX_POST_BC_OP		0x1
+#define QLC_83XX_MBX_COMPLETION		0x0
+#define QLC_83XX_MBX_REQUEST		0x1
+
+#define QLC_83XX_MBX_TIMEOUT		(5 * HZ)
+#define QLC_83XX_MBX_CMD_LOOP		5000000
+
 /* status descriptor mailbox data
  * @phy_addr_{low|high}: physical address of buffer
  * @sds_ring_size: buffer size
@@ -449,6 +456,20 @@ enum qlcnic_83xx_states {
 #define QLC_83xx_FLASH_MAX_WAIT_USEC		100
 #define QLC_83XX_FLASH_LOCK_TIMEOUT		10000
 
+enum qlc_83xx_mbx_cmd_type {
+	QLC_83XX_MBX_CMD_WAIT = 0,
+	QLC_83XX_MBX_CMD_NO_WAIT,
+	QLC_83XX_MBX_CMD_BUSY_WAIT,
+};
+
+enum qlc_83xx_mbx_response_states {
+	QLC_83XX_MBX_RESPONSE_WAIT = 0,
+	QLC_83XX_MBX_RESPONSE_ARRIVED,
+};
+
+#define QLC_83XX_MBX_RESPONSE_FAILED	0x2
+#define QLC_83XX_MBX_RESPONSE_UNKNOWN	0x3
+
 /* Additional registers in 83xx */
 enum qlc_83xx_ext_regs {
 	QLCNIC_GLOBAL_RESET = 0,
@@ -498,7 +519,7 @@ enum qlc_83xx_ext_regs {
 
 /* 83xx funcitons */
 int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
-int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
 int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8);
 void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
 int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
@@ -551,7 +572,7 @@ void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
 void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
 irqreturn_t qlcnic_83xx_handle_aen(int, void *);
 int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
-void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *);
+void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *);
 void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *);
 irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *);
 irqreturn_t qlcnic_83xx_intr(int, void *);
@@ -623,8 +644,6 @@ int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state);
 int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
 int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
 int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
-u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
-u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
 void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
 void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
 void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 9f4b8d5..cc1e32a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -399,6 +399,7 @@ static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 
 	netif_device_detach(netdev);
+	qlcnic_83xx_detach_mailbox_work(adapter);
 
 	/* Disable mailbox interrupt */
 	qlcnic_83xx_disable_mbx_intr(adapter);
@@ -610,6 +611,9 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
 {
 	int err;
 
+	qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
+	qlcnic_83xx_enable_mbx_interrupt(adapter);
+
 	/* register for NIC IDC AEN Events */
 	qlcnic_83xx_register_nic_idc_func(adapter, 1);
 
@@ -617,7 +621,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
 	if (err)
 		return err;
 
-	qlcnic_83xx_enable_mbx_intrpt(adapter);
+	qlcnic_83xx_enable_mbx_interrupt(adapter);
 
 	if (qlcnic_83xx_configure_opmode(adapter)) {
 		qlcnic_83xx_idc_enter_failed_state(adapter, 1);
@@ -640,7 +644,6 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
 
 	qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
-	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
 	qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
 	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
 
@@ -810,9 +813,10 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)
  **/
 static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
 {
-	u32 val;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_mailbox *mbx = ahw->mailbox;
 	int ret = 0;
+	u32 val;
 
 	/* Perform NIC configuration based ready state entry actions */
 	if (ahw->idc.state_entry(adapter))
@@ -824,7 +828,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
 			dev_err(&adapter->pdev->dev,
 				"Error: device temperature %d above limits\n",
 				adapter->ahw->temp);
-			clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
+			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 			set_bit(__QLCNIC_RESETTING, &adapter->state);
 			qlcnic_83xx_idc_detach_driver(adapter);
 			qlcnic_83xx_idc_enter_failed_state(adapter, 1);
@@ -837,7 +841,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
 	if (ret) {
 		adapter->flags |= QLCNIC_FW_HANG;
 		if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
-			clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
+			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 			set_bit(__QLCNIC_RESETTING, &adapter->state);
 			qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
 		}
@@ -845,6 +849,8 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
 	}
 
 	if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) {
+		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+
 		/* Move to need reset state and prepare for reset */
 		qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
 		return ret;
@@ -882,12 +888,13 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
  **/
 static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
 {
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
 	int ret = 0;
 
 	if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
 		qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
 		set_bit(__QLCNIC_RESETTING, &adapter->state);
-		clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 		if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
 			qlcnic_83xx_disable_vnic_mode(adapter, 1);
 
@@ -1079,7 +1086,6 @@ static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
 	adapter->ahw->idc.name = (char **)qlc_83xx_idc_states;
 
 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
-	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
 	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
 
 	/* Check if reset recovery is disabled */
@@ -1190,6 +1196,9 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
 {
 	u32 val;
 
+	if (qlcnic_sriov_vf_check(adapter))
+		return;
+
 	if (qlcnic_83xx_lock_driver(adapter)) {
 		dev_err(&adapter->pdev->dev,
 			"%s:failed, please retry\n", __func__);
@@ -2141,17 +2150,35 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
 int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	int err = 0;
 
-	if (qlcnic_sriov_vf_check(adapter))
-		return qlcnic_sriov_vf_init(adapter, pci_using_dac);
+	ahw->msix_supported = !!qlcnic_use_msi_x;
+	err = qlcnic_83xx_init_mailbox_work(adapter);
+	if (err)
+		goto exit;
 
-	if (qlcnic_83xx_check_hw_status(adapter))
-		return -EIO;
+	if (qlcnic_sriov_vf_check(adapter)) {
+		err = qlcnic_sriov_vf_init(adapter, pci_using_dac);
+		if (err)
+			goto detach_mbx;
+		else
+			return err;
+	}
 
-	/* Initilaize 83xx mailbox spinlock */
-	spin_lock_init(&ahw->mbx_lock);
+	err = qlcnic_83xx_check_hw_status(adapter);
+	if (err)
+		goto detach_mbx;
+
+	err = qlcnic_setup_intr(adapter, 0);
+	if (err) {
+		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
+		goto disable_intr;
+	}
+
+	err = qlcnic_83xx_setup_mbx_intr(adapter);
+	if (err)
+		goto disable_mbx_intr;
 
-	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
 	qlcnic_83xx_clear_function_resources(adapter);
 
 	INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
@@ -2162,19 +2189,33 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
 	if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
 		qlcnic_83xx_read_flash_mfg_id(adapter);
 
-	if (qlcnic_83xx_idc_init(adapter))
-		return -EIO;
+	err = qlcnic_83xx_idc_init(adapter);
+	if (err)
+		goto disable_mbx_intr;
 
 	/* Configure default, SR-IOV or Virtual NIC mode of operation */
-	if (qlcnic_83xx_configure_opmode(adapter))
-		return -EIO;
+	err = qlcnic_83xx_configure_opmode(adapter);
+	if (err)
+		goto disable_mbx_intr;
 
 	/* Perform operating mode specific initialization */
-	if (adapter->nic_ops->init_driver(adapter))
-		return -EIO;
+	err = adapter->nic_ops->init_driver(adapter);
+	if (err)
+		goto disable_mbx_intr;
 
 	/* Periodically monitor device status */
 	qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
+	return 0;
 
-	return adapter->ahw->idc.err_code;
+disable_mbx_intr:
+	qlcnic_83xx_free_mbx_intr(adapter);
+
+disable_intr:
+	qlcnic_teardown_intr(adapter);
+
+detach_mbx:
+	qlcnic_83xx_detach_mailbox_work(adapter);
+	qlcnic_83xx_free_mailbox(ahw->mailbox);
+exit:
+	return err;
 }
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 7aac23a..79a5855 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1006,9 +1006,9 @@ int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
 		msleep(500);
 		qlcnic_process_rcv_ring_diag(sds_ring);
 		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
-			netdev_info(netdev, "firmware didnt respond to loopback"
-				" configure request\n");
-			ret = -QLCNIC_FW_NOT_RESPOND;
+			netdev_info(netdev,
+				    "Firmware didn't sent link up event to loopback request\n");
+			ret = -ETIMEDOUT;
 			goto free_res;
 		} else if (adapter->ahw->diag_cnt) {
 			ret = adapter->ahw->diag_cnt;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 6946d35..f807f3b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -952,17 +952,17 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index,
 			break;
 		case 1:
 			dev_info(dev, "loopback already in progress\n");
-			adapter->ahw->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+			adapter->ahw->diag_cnt = -EINPROGRESS;
 			break;
 		case 2:
 			dev_info(dev, "loopback cable is not connected\n");
-			adapter->ahw->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+			adapter->ahw->diag_cnt = -ENODEV;
 			break;
 		default:
 			dev_info(dev,
 				 "loopback configure request failed, err %x\n",
 				 ret);
-			adapter->ahw->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+			adapter->ahw->diag_cnt = -EIO;
 			break;
 		}
 		break;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index ee013fc..b8242bc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2145,16 +2145,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev_warn(&pdev->dev,
 			 "Device does not support MSI interrupts\n");
 
-	err = qlcnic_setup_intr(adapter, 0);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to setup interrupt\n");
-		goto err_out_disable_msi;
-	}
-
-	if (qlcnic_83xx_check(adapter)) {
-		err = qlcnic_83xx_setup_mbx_intr(adapter);
-		if (err)
+	if (qlcnic_82xx_check(adapter)) {
+		err = qlcnic_setup_intr(adapter, 0);
+		if (err) {
+			dev_err(&pdev->dev, "Failed to setup interrupt\n");
 			goto err_out_disable_msi;
+		}
 	}
 
 	err = qlcnic_get_act_pci_func(adapter);
@@ -2241,9 +2237,11 @@ static void qlcnic_remove(struct pci_dev *pdev)
 	qlcnic_sriov_cleanup(adapter);
 
 	if (qlcnic_83xx_check(adapter)) {
-		qlcnic_83xx_free_mbx_intr(adapter);
 		qlcnic_83xx_register_nic_idc_func(adapter, 0);
 		cancel_delayed_work_sync(&adapter->idc_aen_work);
+		qlcnic_83xx_free_mbx_intr(adapter);
+		qlcnic_83xx_detach_mailbox_work(adapter);
+		qlcnic_83xx_free_mailbox(ahw->mailbox);
 	}
 
 	qlcnic_detach(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index 5d40045..046286a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -33,7 +33,7 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32);
 static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *);
 static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *);
 static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *);
-static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *,
+static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *,
 				  struct qlcnic_cmd_args *);
 static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
 
@@ -45,7 +45,7 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
 	.get_mac_address		= qlcnic_83xx_get_mac_address,
 	.setup_intr			= qlcnic_83xx_setup_intr,
 	.alloc_mbx_args			= qlcnic_83xx_alloc_mbx_args,
-	.mbx_cmd			= qlcnic_sriov_vf_mbx_op,
+	.mbx_cmd			= qlcnic_sriov_issue_cmd,
 	.get_func_no			= qlcnic_83xx_get_func_no,
 	.api_lock			= qlcnic_83xx_cam_lock,
 	.api_unlock			= qlcnic_83xx_cam_unlock,
@@ -286,96 +286,38 @@ void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
 static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
 				    u32 *pay, u8 pci_func, u8 size)
 {
-	u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val, wait_time = 0;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
-	unsigned long flags;
-	u16 opcode;
-	u8 mbx_err_code;
-	int i, j;
-
-	opcode = ((struct qlcnic_bc_hdr *)hdr)->cmd_op;
-
-	if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
-		dev_info(&adapter->pdev->dev,
-			 "Mailbox cmd attempted, 0x%x\n", opcode);
-		dev_info(&adapter->pdev->dev, "Mailbox detached\n");
-		return 0;
-	}
-
-	spin_lock_irqsave(&ahw->mbx_lock, flags);
-
-	mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
-	if (mbx_val) {
-		QLCDB(adapter, DRV, "Mailbox cmd attempted, 0x%x\n", opcode);
-		spin_unlock_irqrestore(&ahw->mbx_lock, flags);
-		return QLCNIC_RCODE_TIMEOUT;
-	}
-	/* Fill in mailbox registers */
-	val = size + (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
-	mbx_cmd = 0x31 | (val << 16) | (adapter->ahw->fw_hal_version << 29);
-
-	writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
-	mbx_cmd = 0x1 | (1 << 4);
+	struct qlcnic_mailbox *mbx = ahw->mailbox;
+	struct qlcnic_cmd_args cmd;
+	unsigned long timeout;
+	int err;
 
-	if (qlcnic_sriov_pf_check(adapter))
-		mbx_cmd |= (pci_func << 5);
+	memset(&cmd, 0, sizeof(struct qlcnic_cmd_args));
+	cmd.hdr = hdr;
+	cmd.pay = pay;
+	cmd.pay_size = size;
+	cmd.func_num = pci_func;
+	cmd.op_type = QLC_83XX_MBX_POST_BC_OP;
+	cmd.cmd_op = ((struct qlcnic_bc_hdr *)hdr)->cmd_op;
 
-	writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1));
-	for (i = 2, j = 0; j < (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
-			i++, j++) {
-		writel(*(hdr++), QLCNIC_MBX_HOST(ahw, i));
+	err = mbx->ops->enqueue_cmd(adapter, &cmd, &timeout);
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"%s: Mailbox not available, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
+			__func__, cmd.cmd_op, cmd.type, ahw->pci_func,
+			ahw->op_mode);
+		return err;
 	}
-	for (j = 0; j < size; j++, i++)
-		writel(*(pay++), QLCNIC_MBX_HOST(ahw, i));
-
-	/* Signal FW about the impending command */
-	QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
 
-	/* Waiting for the mailbox cmd to complete and while waiting here
-	 * some AEN might arrive. If more than 5 seconds expire we can
-	 * assume something is wrong.
-	 */
-poll:
-	rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
-	if (rsp != QLCNIC_RCODE_TIMEOUT) {
-		/* Get the FW response data */
-		fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
-		if (fw_data &  QLCNIC_MBX_ASYNC_EVENT) {
-			__qlcnic_83xx_process_aen(adapter);
-			goto poll;
-		}
-		mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
-		rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
-		opcode = QLCNIC_MBX_RSP(fw_data);
-
-		switch (mbx_err_code) {
-		case QLCNIC_MBX_RSP_OK:
-		case QLCNIC_MBX_PORT_RSP_OK:
-			rsp = QLCNIC_RCODE_SUCCESS;
-			break;
-		default:
-			if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
-				rsp = qlcnic_83xx_mac_rcode(adapter);
-				if (!rsp)
-					goto out;
-			}
-			dev_err(&adapter->pdev->dev,
-				"MBX command 0x%x failed with err:0x%x\n",
-				opcode, mbx_err_code);
-			rsp = mbx_err_code;
-			break;
-		}
-		goto out;
+	if (!wait_for_completion_timeout(&cmd.completion, timeout)) {
+		dev_err(&adapter->pdev->dev,
+			"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
+			__func__, cmd.cmd_op, cmd.type, ahw->pci_func,
+			ahw->op_mode);
+		flush_workqueue(mbx->work_q);
 	}
 
-	dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n",
-		QLCNIC_MBX_RSP(mbx_cmd));
-	rsp = QLCNIC_RCODE_TIMEOUT;
-out:
-	/* clear fw mbx control register */
-	QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
-	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
-	return rsp;
+	return cmd.rsp_opcode;
 }
 
 static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter)
@@ -522,8 +464,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter)
 
 static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter)
 {
-	struct qlcnic_info nic_info;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_info nic_info;
 	int err;
 
 	err = qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, 0);
@@ -637,8 +579,6 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac)
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
 	int err;
 
-	spin_lock_init(&ahw->mbx_lock);
-	set_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
 	set_bit(QLC_83XX_MODULE_LOADED, &ahw->idc.status);
 	ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
 	ahw->reset_context = 0;
@@ -1085,6 +1025,7 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work)
 	if (test_bit(QLC_BC_VF_FLR, &vf->state))
 		return;
 
+	memset(&cmd, 0, sizeof(struct qlcnic_cmd_args));
 	trans = list_first_entry(&vf->rcv_act.wait_list,
 				 struct qlcnic_bc_trans, list);
 	adapter = vf->adapter;
@@ -1234,6 +1175,7 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov,
 		return;
 	}
 
+	memset(&cmd, 0, sizeof(struct qlcnic_cmd_args));
 	cmd_op = hdr->cmd_op;
 	if (qlcnic_sriov_alloc_bc_trans(&trans))
 		return;
@@ -1359,7 +1301,7 @@ int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable)
 	if (enable)
 		cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
 
-	err = qlcnic_83xx_mbx_op(adapter, &cmd);
+	err = qlcnic_83xx_issue_cmd(adapter, &cmd);
 
 	if (err != QLCNIC_RCODE_SUCCESS) {
 		dev_err(&adapter->pdev->dev,
@@ -1391,10 +1333,11 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter,
 	return -EIO;
 }
 
-static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter,
+static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
 				  struct qlcnic_cmd_args *cmd)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_mailbox *mbx = ahw->mailbox;
 	struct device *dev = &adapter->pdev->dev;
 	struct qlcnic_bc_trans *trans;
 	int err;
@@ -1411,7 +1354,7 @@ static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter,
 		goto cleanup_transaction;
 
 retry:
-	if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
+	if (!test_bit(QLC_83XX_MBX_READY, &mbx->status)) {
 		rsp = -EIO;
 		QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n",
 		      QLCNIC_MBX_RSP(cmd->req.arg[0]), func);
@@ -1454,7 +1397,7 @@ err_out:
 	if (rsp == QLCNIC_RCODE_TIMEOUT) {
 		ahw->reset_context = 1;
 		adapter->need_fw_reset = 1;
-		clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
+		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 	}
 
 cleanup_transaction:
@@ -1614,7 +1557,7 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
 	int err;
 
 	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
-	qlcnic_83xx_enable_mbx_intrpt(adapter);
+	qlcnic_83xx_enable_mbx_interrupt(adapter);
 
 	err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
 	if (err)
@@ -1657,8 +1600,10 @@ static void qlcnic_sriov_vf_detach(struct qlcnic_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	u8 i, max_ints = ahw->num_msix - 1;
 
-	qlcnic_83xx_disable_mbx_intr(adapter);
 	netif_device_detach(netdev);
+	qlcnic_83xx_detach_mailbox_work(adapter);
+	qlcnic_83xx_disable_mbx_intr(adapter);
+
 	if (netif_running(netdev))
 		qlcnic_down(adapter, netdev);
 
@@ -1702,6 +1647,7 @@ static int qlcnic_sriov_vf_handle_dev_ready(struct qlcnic_adapter *adapter)
 static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_mailbox *mbx = ahw->mailbox;
 	struct device *dev = &adapter->pdev->dev;
 	struct qlc_83xx_idc *idc = &ahw->idc;
 	u8 func = ahw->pci_func;
@@ -1712,7 +1658,7 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter)
 	/* Skip the context reset and check if FW is hung */
 	if (adapter->reset_ctx_cnt < 3) {
 		adapter->need_fw_reset = 1;
-		clear_bit(QLC_83XX_MBX_READY, &idc->status);
+		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 		dev_info(dev,
 			 "Resetting context, wait here to check if FW is in failed state\n");
 		return 0;
@@ -1737,7 +1683,7 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter)
 		 __func__, adapter->reset_ctx_cnt, func);
 	set_bit(__QLCNIC_RESETTING, &adapter->state);
 	adapter->need_fw_reset = 1;
-	clear_bit(QLC_83XX_MBX_READY, &idc->status);
+	clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 	qlcnic_sriov_vf_detach(adapter);
 	adapter->need_fw_reset = 0;
 
@@ -1787,6 +1733,7 @@ static int qlcnic_sriov_vf_idc_failed_state(struct qlcnic_adapter *adapter)
 static int
 qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter)
 {
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
 	struct qlc_83xx_idc *idc = &adapter->ahw->idc;
 
 	dev_info(&adapter->pdev->dev, "Device is in quiescent state\n");
@@ -1794,7 +1741,7 @@ qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter)
 		set_bit(__QLCNIC_RESETTING, &adapter->state);
 		adapter->tx_timeo_cnt = 0;
 		adapter->reset_ctx_cnt = 0;
-		clear_bit(QLC_83XX_MBX_READY, &idc->status);
+		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 		qlcnic_sriov_vf_detach(adapter);
 	}
 
@@ -1803,6 +1750,7 @@ qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter)
 
 static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter)
 {
+	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
 	struct qlc_83xx_idc *idc = &adapter->ahw->idc;
 	u8 func = adapter->ahw->pci_func;
 
@@ -1812,7 +1760,7 @@ static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter)
 		set_bit(__QLCNIC_RESETTING, &adapter->state);
 		adapter->tx_timeo_cnt = 0;
 		adapter->reset_ctx_cnt = 0;
-		clear_bit(QLC_83XX_MBX_READY, &idc->status);
+		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
 		qlcnic_sriov_vf_detach(adapter);
 	}
 	return 0;
@@ -1990,7 +1938,7 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter)
 	int err;
 
 	set_bit(QLC_83XX_MODULE_LOADED, &idc->status);
-	qlcnic_83xx_enable_mbx_intrpt(adapter);
+	qlcnic_83xx_enable_mbx_interrupt(adapter);
 	err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
 	if (err)
 		return err;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h
index 7e8d682..8994337 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge.h
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
@@ -2149,7 +2149,7 @@ struct ql_adapter {
 	struct timer_list timer;
 	atomic_t lb_count;
 	/* Keep local copy of current mac address. */
-	char current_mac_addr[6];
+	char current_mac_addr[ETH_ALEN];
 };
 
 /*
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
index 19a8a04..a30c439 100644
--- a/drivers/net/ethernet/renesas/Kconfig
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -13,4 +13,4 @@ config SH_ETH
 	  Renesas SuperH Ethernet device driver.
 	  This driver supporting CPUs are:
 		- SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
-		  R8A7740 and R8A7779.
+		  R8A7740, R8A777x and R8A7790.
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index a753928..9e2afe8 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -189,6 +189,7 @@ static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
 	[RMCR]		= 0x0258,
 	[TFUCR]		= 0x0264,
 	[RFOCR]		= 0x0268,
+	[RMIIMODE]      = 0x026c,
 	[FCFTR]		= 0x0270,
 	[TRIMD]		= 0x027c,
 };
@@ -392,6 +393,27 @@ static struct sh_eth_cpu_data r8a777x_data = {
 	.hw_swap	= 1,
 };
 
+/* R8A7790 */
+static struct sh_eth_cpu_data r8a7790_data = {
+	.set_duplex	= sh_eth_set_duplex,
+	.set_rate	= sh_eth_set_rate_r8a777x,
+
+	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
+	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
+	.eesipr_value	= 0x01ff009f,
+
+	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
+	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |
+			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |
+			  EESR_ECI,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.hw_swap	= 1,
+	.rmiimode	= 1,
+};
+
 static void sh_eth_set_rate_sh7724(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -1124,6 +1146,9 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
 	if (ret)
 		goto out;
 
+	if (mdp->cd->rmiimode)
+		sh_eth_write(ndev, 0x1, RMIIMODE);
+
 	/* Descriptor format */
 	sh_eth_ring_format(ndev);
 	if (mdp->cd->rpadir)
@@ -2749,6 +2774,7 @@ static struct platform_device_id sh_eth_id_table[] = {
 	{ "sh7763-gether", (kernel_ulong_t)&sh7763_data },
 	{ "r8a7740-gether", (kernel_ulong_t)&r8a7740_data },
 	{ "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
+	{ "r8a7790-ether", (kernel_ulong_t)&r8a7790_data },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 99995bf..da93f5c 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -60,6 +60,7 @@ enum {
 	EDOCR,
 	TFUCR,
 	RFOCR,
+	RMIIMODE,
 	FCFTR,
 	RPADIR,
 	TRIMD,
@@ -482,6 +483,7 @@ struct sh_eth_cpu_data {
 	unsigned hw_crc:1;	/* E-DMAC have CSMR */
 	unsigned select_mii:1;	/* EtherC have RMII_MII (MII select register) */
 	unsigned shift_rd0:1;	/* shift Rx descriptor word 0 right by 16 */
+	unsigned rmiimode:1;	/* EtherC has RMIIMODE register */
 };
 
 struct sh_eth_private {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 03de76c..da8be6e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -109,9 +109,6 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
 	const char *mac = NULL;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
 	addr = devm_ioremap_resource(dev, res);
 	if (IS_ERR(addr))
 		return PTR_ERR(addr);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 22a7a43..cd95671 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -82,6 +82,7 @@ do {								\
 
 #define CPSW_VERSION_1		0x19010a
 #define CPSW_VERSION_2		0x19010c
+#define CPSW_VERSION_3		0x19010f
 
 #define HOST_PORT_NUM		0
 #define SLIVER_SIZE		0x40
@@ -91,6 +92,7 @@ do {								\
 #define CPSW1_SLAVE_SIZE	0x040
 #define CPSW1_CPDMA_OFFSET	0x100
 #define CPSW1_STATERAM_OFFSET	0x200
+#define CPSW1_HW_STATS		0x400
 #define CPSW1_CPTS_OFFSET	0x500
 #define CPSW1_ALE_OFFSET	0x600
 #define CPSW1_SLIVER_OFFSET	0x700
@@ -99,6 +101,7 @@ do {								\
 #define CPSW2_SLAVE_OFFSET	0x200
 #define CPSW2_SLAVE_SIZE	0x100
 #define CPSW2_CPDMA_OFFSET	0x800
+#define CPSW2_HW_STATS		0x900
 #define CPSW2_STATERAM_OFFSET	0xa00
 #define CPSW2_CPTS_OFFSET	0xc00
 #define CPSW2_ALE_OFFSET	0xd00
@@ -299,6 +302,44 @@ struct cpsw_sliver_regs {
 	u32	rx_pri_map;
 };
 
+struct cpsw_hw_stats {
+	u32	rxgoodframes;
+	u32	rxbroadcastframes;
+	u32	rxmulticastframes;
+	u32	rxpauseframes;
+	u32	rxcrcerrors;
+	u32	rxaligncodeerrors;
+	u32	rxoversizedframes;
+	u32	rxjabberframes;
+	u32	rxundersizedframes;
+	u32	rxfragments;
+	u32	__pad_0[2];
+	u32	rxoctets;
+	u32	txgoodframes;
+	u32	txbroadcastframes;
+	u32	txmulticastframes;
+	u32	txpauseframes;
+	u32	txdeferredframes;
+	u32	txcollisionframes;
+	u32	txsinglecollframes;
+	u32	txmultcollframes;
+	u32	txexcessivecollisions;
+	u32	txlatecollisions;
+	u32	txunderrun;
+	u32	txcarriersenseerrors;
+	u32	txoctets;
+	u32	octetframes64;
+	u32	octetframes65t127;
+	u32	octetframes128t255;
+	u32	octetframes256t511;
+	u32	octetframes512t1023;
+	u32	octetframes1024tup;
+	u32	netoctets;
+	u32	rxsofoverruns;
+	u32	rxmofoverruns;
+	u32	rxdmaoverruns;
+};
+
 struct cpsw_slave {
 	void __iomem			*regs;
 	struct cpsw_sliver_regs __iomem	*sliver;
@@ -332,6 +373,7 @@ struct cpsw_priv {
 	struct cpsw_platform_data	data;
 	struct cpsw_ss_regs __iomem	*regs;
 	struct cpsw_wr_regs __iomem	*wr_regs;
+	u8 __iomem			*hw_stats;
 	struct cpsw_host_regs __iomem	*host_port_regs;
 	u32				msg_enable;
 	u32				version;
@@ -354,6 +396,94 @@ struct cpsw_priv {
 	u32 emac_port;
 };
 
+struct cpsw_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int type;
+	int sizeof_stat;
+	int stat_offset;
+};
+
+enum {
+	CPSW_STATS,
+	CPDMA_RX_STATS,
+	CPDMA_TX_STATS,
+};
+
+#define CPSW_STAT(m)		CPSW_STATS,				\
+				sizeof(((struct cpsw_hw_stats *)0)->m), \
+				offsetof(struct cpsw_hw_stats, m)
+#define CPDMA_RX_STAT(m)	CPDMA_RX_STATS,				   \
+				sizeof(((struct cpdma_chan_stats *)0)->m), \
+				offsetof(struct cpdma_chan_stats, m)
+#define CPDMA_TX_STAT(m)	CPDMA_TX_STATS,				   \
+				sizeof(((struct cpdma_chan_stats *)0)->m), \
+				offsetof(struct cpdma_chan_stats, m)
+
+static const struct cpsw_stats cpsw_gstrings_stats[] = {
+	{ "Good Rx Frames", CPSW_STAT(rxgoodframes) },
+	{ "Broadcast Rx Frames", CPSW_STAT(rxbroadcastframes) },
+	{ "Multicast Rx Frames", CPSW_STAT(rxmulticastframes) },
+	{ "Pause Rx Frames", CPSW_STAT(rxpauseframes) },
+	{ "Rx CRC Errors", CPSW_STAT(rxcrcerrors) },
+	{ "Rx Align/Code Errors", CPSW_STAT(rxaligncodeerrors) },
+	{ "Oversize Rx Frames", CPSW_STAT(rxoversizedframes) },
+	{ "Rx Jabbers", CPSW_STAT(rxjabberframes) },
+	{ "Undersize (Short) Rx Frames", CPSW_STAT(rxundersizedframes) },
+	{ "Rx Fragments", CPSW_STAT(rxfragments) },
+	{ "Rx Octets", CPSW_STAT(rxoctets) },
+	{ "Good Tx Frames", CPSW_STAT(txgoodframes) },
+	{ "Broadcast Tx Frames", CPSW_STAT(txbroadcastframes) },
+	{ "Multicast Tx Frames", CPSW_STAT(txmulticastframes) },
+	{ "Pause Tx Frames", CPSW_STAT(txpauseframes) },
+	{ "Deferred Tx Frames", CPSW_STAT(txdeferredframes) },
+	{ "Collisions", CPSW_STAT(txcollisionframes) },
+	{ "Single Collision Tx Frames", CPSW_STAT(txsinglecollframes) },
+	{ "Multiple Collision Tx Frames", CPSW_STAT(txmultcollframes) },
+	{ "Excessive Collisions", CPSW_STAT(txexcessivecollisions) },
+	{ "Late Collisions", CPSW_STAT(txlatecollisions) },
+	{ "Tx Underrun", CPSW_STAT(txunderrun) },
+	{ "Carrier Sense Errors", CPSW_STAT(txcarriersenseerrors) },
+	{ "Tx Octets", CPSW_STAT(txoctets) },
+	{ "Rx + Tx 64 Octet Frames", CPSW_STAT(octetframes64) },
+	{ "Rx + Tx 65-127 Octet Frames", CPSW_STAT(octetframes65t127) },
+	{ "Rx + Tx 128-255 Octet Frames", CPSW_STAT(octetframes128t255) },
+	{ "Rx + Tx 256-511 Octet Frames", CPSW_STAT(octetframes256t511) },
+	{ "Rx + Tx 512-1023 Octet Frames", CPSW_STAT(octetframes512t1023) },
+	{ "Rx + Tx 1024-Up Octet Frames", CPSW_STAT(octetframes1024tup) },
+	{ "Net Octets", CPSW_STAT(netoctets) },
+	{ "Rx Start of Frame Overruns", CPSW_STAT(rxsofoverruns) },
+	{ "Rx Middle of Frame Overruns", CPSW_STAT(rxmofoverruns) },
+	{ "Rx DMA Overruns", CPSW_STAT(rxdmaoverruns) },
+	{ "Rx DMA chan: head_enqueue", CPDMA_RX_STAT(head_enqueue) },
+	{ "Rx DMA chan: tail_enqueue", CPDMA_RX_STAT(tail_enqueue) },
+	{ "Rx DMA chan: pad_enqueue", CPDMA_RX_STAT(pad_enqueue) },
+	{ "Rx DMA chan: misqueued", CPDMA_RX_STAT(misqueued) },
+	{ "Rx DMA chan: desc_alloc_fail", CPDMA_RX_STAT(desc_alloc_fail) },
+	{ "Rx DMA chan: pad_alloc_fail", CPDMA_RX_STAT(pad_alloc_fail) },
+	{ "Rx DMA chan: runt_receive_buf", CPDMA_RX_STAT(runt_receive_buff) },
+	{ "Rx DMA chan: runt_transmit_buf", CPDMA_RX_STAT(runt_transmit_buff) },
+	{ "Rx DMA chan: empty_dequeue", CPDMA_RX_STAT(empty_dequeue) },
+	{ "Rx DMA chan: busy_dequeue", CPDMA_RX_STAT(busy_dequeue) },
+	{ "Rx DMA chan: good_dequeue", CPDMA_RX_STAT(good_dequeue) },
+	{ "Rx DMA chan: requeue", CPDMA_RX_STAT(requeue) },
+	{ "Rx DMA chan: teardown_dequeue", CPDMA_RX_STAT(teardown_dequeue) },
+	{ "Tx DMA chan: head_enqueue", CPDMA_TX_STAT(head_enqueue) },
+	{ "Tx DMA chan: tail_enqueue", CPDMA_TX_STAT(tail_enqueue) },
+	{ "Tx DMA chan: pad_enqueue", CPDMA_TX_STAT(pad_enqueue) },
+	{ "Tx DMA chan: misqueued", CPDMA_TX_STAT(misqueued) },
+	{ "Tx DMA chan: desc_alloc_fail", CPDMA_TX_STAT(desc_alloc_fail) },
+	{ "Tx DMA chan: pad_alloc_fail", CPDMA_TX_STAT(pad_alloc_fail) },
+	{ "Tx DMA chan: runt_receive_buf", CPDMA_TX_STAT(runt_receive_buff) },
+	{ "Tx DMA chan: runt_transmit_buf", CPDMA_TX_STAT(runt_transmit_buff) },
+	{ "Tx DMA chan: empty_dequeue", CPDMA_TX_STAT(empty_dequeue) },
+	{ "Tx DMA chan: busy_dequeue", CPDMA_TX_STAT(busy_dequeue) },
+	{ "Tx DMA chan: good_dequeue", CPDMA_TX_STAT(good_dequeue) },
+	{ "Tx DMA chan: requeue", CPDMA_TX_STAT(requeue) },
+	{ "Tx DMA chan: teardown_dequeue", CPDMA_TX_STAT(teardown_dequeue) },
+};
+
+#define CPSW_STATS_LEN	ARRAY_SIZE(cpsw_gstrings_stats)
+
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
 #define for_each_slave(priv, func, arg...)				\
 	do {								\
@@ -723,6 +853,69 @@ static int cpsw_set_coalesce(struct net_device *ndev,
 	return 0;
 }
 
+static int cpsw_get_sset_count(struct net_device *ndev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return CPSW_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void cpsw_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	u8 *p = data;
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < CPSW_STATS_LEN; i++) {
+			memcpy(p, cpsw_gstrings_stats[i].stat_string,
+			       ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+static void cpsw_get_ethtool_stats(struct net_device *ndev,
+				    struct ethtool_stats *stats, u64 *data)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	struct cpdma_chan_stats rx_stats;
+	struct cpdma_chan_stats tx_stats;
+	u32 val;
+	u8 *p;
+	int i;
+
+	/* Collect Davinci CPDMA stats for Rx and Tx Channel */
+	cpdma_chan_get_stats(priv->rxch, &rx_stats);
+	cpdma_chan_get_stats(priv->txch, &tx_stats);
+
+	for (i = 0; i < CPSW_STATS_LEN; i++) {
+		switch (cpsw_gstrings_stats[i].type) {
+		case CPSW_STATS:
+			val = readl(priv->hw_stats +
+				    cpsw_gstrings_stats[i].stat_offset);
+			data[i] = val;
+			break;
+
+		case CPDMA_RX_STATS:
+			p = (u8 *)&rx_stats +
+				cpsw_gstrings_stats[i].stat_offset;
+			data[i] = *(u32 *)p;
+			break;
+
+		case CPDMA_TX_STATS:
+			p = (u8 *)&tx_stats +
+				cpsw_gstrings_stats[i].stat_offset;
+			data[i] = *(u32 *)p;
+			break;
+		}
+	}
+}
+
 static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 {
 	static char *leader = "........................................";
@@ -799,6 +992,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 		slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP);
 		break;
 	case CPSW_VERSION_2:
+	case CPSW_VERSION_3:
 		slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP);
 		break;
 	}
@@ -1232,6 +1426,33 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
 
 }
 
+static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	struct sockaddr *addr = (struct sockaddr *)p;
+	int flags = 0;
+	u16 vid = 0;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (priv->data.dual_emac) {
+		vid = priv->slaves[priv->emac_port].port_vlan;
+		flags = ALE_VLAN;
+	}
+
+	cpsw_ale_del_ucast(priv->ale, priv->mac_addr, priv->host_port,
+			   flags, vid);
+	cpsw_ale_add_ucast(priv->ale, addr->sa_data, priv->host_port,
+			   flags, vid);
+
+	memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
+	memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
+	for_each_slave(priv, cpsw_set_slave_mac, priv);
+
+	return 0;
+}
+
 static struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev)
 {
 	struct cpsw_priv *priv = netdev_priv(ndev);
@@ -1326,6 +1547,7 @@ static const struct net_device_ops cpsw_netdev_ops = {
 	.ndo_stop		= cpsw_ndo_stop,
 	.ndo_start_xmit		= cpsw_ndo_start_xmit,
 	.ndo_change_rx_flags	= cpsw_ndo_change_rx_flags,
+	.ndo_set_mac_address	= cpsw_ndo_set_mac_address,
 	.ndo_do_ioctl		= cpsw_ndo_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
@@ -1426,6 +1648,9 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
 	.set_settings	= cpsw_set_settings,
 	.get_coalesce	= cpsw_get_coalesce,
 	.set_coalesce	= cpsw_set_coalesce,
+	.get_sset_count		= cpsw_get_sset_count,
+	.get_strings		= cpsw_get_strings,
+	.get_ethtool_stats	= cpsw_get_ethtool_stats,
 };
 
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
@@ -1623,6 +1848,7 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
 	priv_sl2->host_port = priv->host_port;
 	priv_sl2->host_port_regs = priv->host_port_regs;
 	priv_sl2->wr_regs = priv->wr_regs;
+	priv_sl2->hw_stats = priv->hw_stats;
 	priv_sl2->dma = priv->dma;
 	priv_sl2->txch = priv->txch;
 	priv_sl2->rxch = priv->rxch;
@@ -1780,7 +2006,8 @@ static int cpsw_probe(struct platform_device *pdev)
 	switch (priv->version) {
 	case CPSW_VERSION_1:
 		priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
-		priv->cpts->reg       = ss_regs + CPSW1_CPTS_OFFSET;
+		priv->cpts->reg      = ss_regs + CPSW1_CPTS_OFFSET;
+		priv->hw_stats	     = ss_regs + CPSW1_HW_STATS;
 		dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
@@ -1790,8 +2017,10 @@ static int cpsw_probe(struct platform_device *pdev)
 		dma_params.desc_mem_phys = 0;
 		break;
 	case CPSW_VERSION_2:
+	case CPSW_VERSION_3:
 		priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
-		priv->cpts->reg       = ss_regs + CPSW2_CPTS_OFFSET;
+		priv->cpts->reg      = ss_regs + CPSW2_CPTS_OFFSET;
+		priv->hw_stats	     = ss_regs + CPSW2_HW_STATS;
 		dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig
index 098b1c4..4083ba8 100644
--- a/drivers/net/ethernet/tile/Kconfig
+++ b/drivers/net/ethernet/tile/Kconfig
@@ -15,3 +15,14 @@ config TILE_NET
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called tile_net.
+
+config PTP_1588_CLOCK_TILEGX
+        tristate "Tilera TILE-Gx mPIPE as PTP clock"
+        select PTP_1588_CLOCK
+        depends on TILE_NET
+        depends on TILEGX
+        ---help---
+          This driver adds support for using the mPIPE as a PTP
+          clock. This clock is only useful if your PTP programs are
+          getting hardware time stamps on the PTP Ethernet packets
+          using the SO_TIMESTAMPING API.
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index f3c2d03..5d2a719 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -36,7 +36,10 @@
 #include <linux/io.h>
 #include <linux/ctype.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 #include <linux/tcp.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
 
 #include <asm/checksum.h>
 #include <asm/homecache.h>
@@ -76,6 +79,9 @@
 
 #define MAX_FRAGS (MAX_SKB_FRAGS + 1)
 
+/* The "kinds" of buffer stacks (small/large/jumbo). */
+#define MAX_KINDS 3
+
 /* Size of completions data to allocate.
  * ISSUE: Probably more than needed since we don't use all the channels.
  */
@@ -130,29 +136,31 @@ struct tile_net_tx_wake {
 
 /* Info for a specific cpu. */
 struct tile_net_info {
-	/* The NAPI struct. */
-	struct napi_struct napi;
-	/* Packet queue. */
-	gxio_mpipe_iqueue_t iqueue;
 	/* Our cpu. */
 	int my_cpu;
-	/* True if iqueue is valid. */
-	bool has_iqueue;
-	/* NAPI flags. */
-	bool napi_added;
-	bool napi_enabled;
-	/* Number of small sk_buffs which must still be provided. */
-	unsigned int num_needed_small_buffers;
-	/* Number of large sk_buffs which must still be provided. */
-	unsigned int num_needed_large_buffers;
 	/* A timer for handling egress completions. */
 	struct hrtimer egress_timer;
 	/* True if "egress_timer" is scheduled. */
 	bool egress_timer_scheduled;
-	/* Comps for each egress channel. */
-	struct tile_net_comps *comps_for_echannel[TILE_NET_CHANNELS];
-	/* Transmit wake timer for each egress channel. */
-	struct tile_net_tx_wake tx_wake[TILE_NET_CHANNELS];
+	struct info_mpipe {
+		/* Packet queue. */
+		gxio_mpipe_iqueue_t iqueue;
+		/* The NAPI struct. */
+		struct napi_struct napi;
+		/* Number of buffers (by kind) which must still be provided. */
+		unsigned int num_needed_buffers[MAX_KINDS];
+		/* instance id. */
+		int instance;
+		/* True if iqueue is valid. */
+		bool has_iqueue;
+		/* NAPI flags. */
+		bool napi_added;
+		bool napi_enabled;
+		/* Comps for each egress channel. */
+		struct tile_net_comps *comps_for_echannel[TILE_NET_CHANNELS];
+		/* Transmit wake timer for each egress channel. */
+		struct tile_net_tx_wake tx_wake[TILE_NET_CHANNELS];
+	} mpipe[NR_MPIPE_MAX];
 };
 
 /* Info for egress on a particular egress channel. */
@@ -177,19 +185,67 @@ struct tile_net_priv {
 	int loopify_channel;
 	/* The egress channel (channel or loopify_channel). */
 	int echannel;
-	/* Total stats. */
-	struct net_device_stats stats;
+	/* mPIPE instance, 0 or 1. */
+	int instance;
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	/* The timestamp config. */
+	struct hwtstamp_config stamp_cfg;
+#endif
 };
 
-/* Egress info, indexed by "priv->echannel" (lazily created as needed). */
-static struct tile_net_egress egress_for_echannel[TILE_NET_CHANNELS];
+static struct mpipe_data {
+	/* The ingress irq. */
+	int ingress_irq;
 
-/* Devices currently associated with each channel.
- * NOTE: The array entry can become NULL after ifconfig down, but
- * we do not free the underlying net_device structures, so it is
- * safe to use a pointer after reading it from this array.
- */
-static struct net_device *tile_net_devs_for_channel[TILE_NET_CHANNELS];
+	/* The "context" for all devices. */
+	gxio_mpipe_context_t context;
+
+	/* Egress info, indexed by "priv->echannel"
+	 * (lazily created as needed).
+	 */
+	struct tile_net_egress
+	egress_for_echannel[TILE_NET_CHANNELS];
+
+	/* Devices currently associated with each channel.
+	 * NOTE: The array entry can become NULL after ifconfig down, but
+	 * we do not free the underlying net_device structures, so it is
+	 * safe to use a pointer after reading it from this array.
+	 */
+	struct net_device
+	*tile_net_devs_for_channel[TILE_NET_CHANNELS];
+
+	/* The actual memory allocated for the buffer stacks. */
+	void *buffer_stack_vas[MAX_KINDS];
+
+	/* The amount of memory allocated for each buffer stack. */
+	size_t buffer_stack_bytes[MAX_KINDS];
+
+	/* The first buffer stack index
+	 * (small = +0, large = +1, jumbo = +2).
+	 */
+	int first_buffer_stack;
+
+	/* The buckets. */
+	int first_bucket;
+	int num_buckets;
+
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	/* PTP-specific data. */
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info caps;
+
+	/* Lock for ptp accessors. */
+	struct mutex ptp_lock;
+#endif
+
+} mpipe_data[NR_MPIPE_MAX] = {
+	[0 ... (NR_MPIPE_MAX - 1)] {
+		.ingress_irq = -1,
+		.first_buffer_stack = -1,
+		.first_bucket = -1,
+		.num_buckets = 1
+	}
+};
 
 /* A mutex for "tile_net_devs_for_channel". */
 static DEFINE_MUTEX(tile_net_devs_for_channel_mutex);
@@ -197,34 +253,17 @@ static DEFINE_MUTEX(tile_net_devs_for_channel_mutex);
 /* The per-cpu info. */
 static DEFINE_PER_CPU(struct tile_net_info, per_cpu_info);
 
-/* The "context" for all devices. */
-static gxio_mpipe_context_t context;
 
-/* Buffer sizes and mpipe enum codes for buffer stacks.
+/* The buffer size enums for each buffer stack.
  * See arch/tile/include/gxio/mpipe.h for the set of possible values.
+ * We avoid the "10384" size because it can induce "false chaining"
+ * on "cut-through" jumbo packets.
  */
-#define BUFFER_SIZE_SMALL_ENUM GXIO_MPIPE_BUFFER_SIZE_128
-#define BUFFER_SIZE_SMALL 128
-#define BUFFER_SIZE_LARGE_ENUM GXIO_MPIPE_BUFFER_SIZE_1664
-#define BUFFER_SIZE_LARGE 1664
-
-/* The small/large "buffer stacks". */
-static int small_buffer_stack = -1;
-static int large_buffer_stack = -1;
-
-/* Amount of memory allocated for each buffer stack. */
-static size_t buffer_stack_size;
-
-/* The actual memory allocated for the buffer stacks. */
-static void *small_buffer_stack_va;
-static void *large_buffer_stack_va;
-
-/* The buckets. */
-static int first_bucket = -1;
-static int num_buckets = 1;
-
-/* The ingress irq. */
-static int ingress_irq = -1;
+static gxio_mpipe_buffer_size_enum_t buffer_size_enums[MAX_KINDS] = {
+	GXIO_MPIPE_BUFFER_SIZE_128,
+	GXIO_MPIPE_BUFFER_SIZE_1664,
+	GXIO_MPIPE_BUFFER_SIZE_16384
+};
 
 /* Text value of tile_net.cpus if passed as a module parameter. */
 static char *network_cpus_string;
@@ -232,11 +271,21 @@ static char *network_cpus_string;
 /* The actual cpus in "network_cpus". */
 static struct cpumask network_cpus_map;
 
-/* If "loopify=LINK" was specified, this is "LINK". */
+/* If "tile_net.loopify=LINK" was specified, this is "LINK". */
 static char *loopify_link_name;
 
-/* If "tile_net.custom" was specified, this is non-NULL. */
-static char *custom_str;
+/* If "tile_net.custom" was specified, this is true. */
+static bool custom_flag;
+
+/* If "tile_net.jumbo=NUM" was specified, this is "NUM". */
+static uint jumbo_num;
+
+/* Obtain mpipe instance from struct tile_net_priv given struct net_device. */
+static inline int mpipe_instance(struct net_device *dev)
+{
+	struct tile_net_priv *priv = netdev_priv(dev);
+	return priv->instance;
+}
 
 /* The "tile_net.cpus" argument specifies the cpus that are dedicated
  * to handle ingress packets.
@@ -289,9 +338,15 @@ MODULE_PARM_DESC(loopify, "name the device to use loop0/1 for ingress/egress");
 /* The "tile_net.custom" argument causes us to ignore the "conventional"
  * classifier metadata, in particular, the "l2_offset".
  */
-module_param_named(custom, custom_str, charp, 0444);
+module_param_named(custom, custom_flag, bool, 0444);
 MODULE_PARM_DESC(custom, "indicates a (heavily) customized classifier");
 
+/* The "tile_net.jumbo" argument causes us to support "jumbo" packets,
+ * and to allocate the given number of "jumbo" buffers.
+ */
+module_param_named(jumbo, jumbo_num, uint, 0444);
+MODULE_PARM_DESC(jumbo, "the number of buffers to support jumbo packets");
+
 /* Atomically update a statistics field.
  * Note that on TILE-Gx, this operation is fire-and-forget on the
  * issuing core (single-cycle dispatch) and takes only a few cycles
@@ -305,15 +360,16 @@ static void tile_net_stats_add(unsigned long value, unsigned long *field)
 }
 
 /* Allocate and push a buffer. */
-static bool tile_net_provide_buffer(bool small)
+static bool tile_net_provide_buffer(int instance, int kind)
 {
-	int stack = small ? small_buffer_stack : large_buffer_stack;
+	struct mpipe_data *md = &mpipe_data[instance];
+	gxio_mpipe_buffer_size_enum_t bse = buffer_size_enums[kind];
+	size_t bs = gxio_mpipe_buffer_size_enum_to_buffer_size(bse);
 	const unsigned long buffer_alignment = 128;
 	struct sk_buff *skb;
 	int len;
 
-	len = sizeof(struct sk_buff **) + buffer_alignment;
-	len += (small ? BUFFER_SIZE_SMALL : BUFFER_SIZE_LARGE);
+	len = sizeof(struct sk_buff **) + buffer_alignment + bs;
 	skb = dev_alloc_skb(len);
 	if (skb == NULL)
 		return false;
@@ -328,7 +384,7 @@ static bool tile_net_provide_buffer(bool small)
 	/* Make sure "skb" and the back-pointer have been flushed. */
 	wmb();
 
-	gxio_mpipe_push_buffer(&context, stack,
+	gxio_mpipe_push_buffer(&md->context, md->first_buffer_stack + kind,
 			       (void *)va_to_tile_io_addr(skb->data));
 
 	return true;
@@ -354,11 +410,14 @@ static struct sk_buff *mpipe_buf_to_skb(void *va)
 	return skb;
 }
 
-static void tile_net_pop_all_buffers(int stack)
+static void tile_net_pop_all_buffers(int instance, int stack)
 {
+	struct mpipe_data *md = &mpipe_data[instance];
+
 	for (;;) {
 		tile_io_addr_t addr =
-			(tile_io_addr_t)gxio_mpipe_pop_buffer(&context, stack);
+			(tile_io_addr_t)gxio_mpipe_pop_buffer(&md->context,
+							      stack);
 		if (addr == 0)
 			break;
 		dev_kfree_skb_irq(mpipe_buf_to_skb(tile_io_addr_to_va(addr)));
@@ -369,24 +428,111 @@ static void tile_net_pop_all_buffers(int stack)
 static void tile_net_provide_needed_buffers(void)
 {
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+	int instance, kind;
+	for (instance = 0; instance < NR_MPIPE_MAX &&
+		     info->mpipe[instance].has_iqueue; instance++)	{
+		for (kind = 0; kind < MAX_KINDS; kind++) {
+			while (info->mpipe[instance].num_needed_buffers[kind]
+			       != 0) {
+				if (!tile_net_provide_buffer(instance, kind)) {
+					pr_notice("Tile %d still needs"
+						  " some buffers\n",
+						  info->my_cpu);
+					return;
+				}
+				info->mpipe[instance].
+					num_needed_buffers[kind]--;
+			}
+		}
+	}
+}
 
-	while (info->num_needed_small_buffers != 0) {
-		if (!tile_net_provide_buffer(true))
-			goto oops;
-		info->num_needed_small_buffers--;
+/* Get RX timestamp, and store it in the skb. */
+static void tile_rx_timestamp(struct tile_net_priv *priv, struct sk_buff *skb,
+			      gxio_mpipe_idesc_t *idesc)
+{
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	if (unlikely(priv->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE)) {
+		struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+		memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+		shhwtstamps->hwtstamp = ktime_set(idesc->time_stamp_sec,
+						  idesc->time_stamp_ns);
 	}
+#endif
+}
 
-	while (info->num_needed_large_buffers != 0) {
-		if (!tile_net_provide_buffer(false))
-			goto oops;
-		info->num_needed_large_buffers--;
+/* Get TX timestamp, and store it in the skb. */
+static void tile_tx_timestamp(struct sk_buff *skb, int instance)
+{
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	struct skb_shared_info *shtx = skb_shinfo(skb);
+	if (unlikely((shtx->tx_flags & SKBTX_HW_TSTAMP) != 0)) {
+		struct mpipe_data *md = &mpipe_data[instance];
+		struct skb_shared_hwtstamps shhwtstamps;
+		struct timespec ts;
+
+		shtx->tx_flags |= SKBTX_IN_PROGRESS;
+		gxio_mpipe_get_timestamp(&md->context, &ts);
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+		shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+		skb_tstamp_tx(skb, &shhwtstamps);
 	}
+#endif
+}
 
-	return;
+/* Use ioctl() to enable or disable TX or RX timestamping. */
+static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq,
+			       int cmd)
+{
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	struct hwtstamp_config config;
+	struct tile_net_priv *priv = netdev_priv(dev);
 
-oops:
-	/* Add a description to the page allocation failure dump. */
-	pr_notice("Tile %d still needs some buffers\n", info->my_cpu);
+	if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	if (config.flags)  /* reserved for future extensions */
+		return -EINVAL;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+	case HWTSTAMP_TX_ON:
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (copy_to_user(rq->ifr_data, &config, sizeof(config)))
+		return -EFAULT;
+
+	priv->stamp_cfg = config;
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
 }
 
 static inline bool filter_packet(struct net_device *dev, void *buf)
@@ -409,6 +555,7 @@ static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb,
 {
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
 	struct tile_net_priv *priv = netdev_priv(dev);
+	int instance = priv->instance;
 
 	/* Encode the actual packet length. */
 	skb_put(skb, len);
@@ -419,47 +566,52 @@ static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb,
 	if (idesc->cs && idesc->csum_seed_val == 0xFFFF)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	netif_receive_skb(skb);
+	/* Get RX timestamp from idesc. */
+	tile_rx_timestamp(priv, skb, idesc);
+
+	napi_gro_receive(&info->mpipe[instance].napi, skb);
 
 	/* Update stats. */
-	tile_net_stats_add(1, &priv->stats.rx_packets);
-	tile_net_stats_add(len, &priv->stats.rx_bytes);
+	tile_net_stats_add(1, &dev->stats.rx_packets);
+	tile_net_stats_add(len, &dev->stats.rx_bytes);
 
 	/* Need a new buffer. */
-	if (idesc->size == BUFFER_SIZE_SMALL_ENUM)
-		info->num_needed_small_buffers++;
+	if (idesc->size == buffer_size_enums[0])
+		info->mpipe[instance].num_needed_buffers[0]++;
+	else if (idesc->size == buffer_size_enums[1])
+		info->mpipe[instance].num_needed_buffers[1]++;
 	else
-		info->num_needed_large_buffers++;
+		info->mpipe[instance].num_needed_buffers[2]++;
 }
 
 /* Handle a packet.  Return true if "processed", false if "filtered". */
-static bool tile_net_handle_packet(gxio_mpipe_idesc_t *idesc)
+static bool tile_net_handle_packet(int instance, gxio_mpipe_idesc_t *idesc)
 {
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
-	struct net_device *dev = tile_net_devs_for_channel[idesc->channel];
+	struct mpipe_data *md = &mpipe_data[instance];
+	struct net_device *dev = md->tile_net_devs_for_channel[idesc->channel];
 	uint8_t l2_offset;
 	void *va;
 	void *buf;
 	unsigned long len;
 	bool filter;
 
-	/* Drop packets for which no buffer was available.
-	 * NOTE: This happens under heavy load.
+	/* Drop packets for which no buffer was available (which can
+	 * happen under heavy load), or for which the me/tr/ce flags
+	 * are set (which can happen for jumbo cut-through packets,
+	 * or with a customized classifier).
 	 */
-	if (idesc->be) {
-		struct tile_net_priv *priv = netdev_priv(dev);
-		tile_net_stats_add(1, &priv->stats.rx_dropped);
-		gxio_mpipe_iqueue_consume(&info->iqueue, idesc);
-		if (net_ratelimit())
-			pr_info("Dropping packet (insufficient buffers).\n");
-		return false;
+	if (idesc->be || idesc->me || idesc->tr || idesc->ce) {
+		if (dev)
+			tile_net_stats_add(1, &dev->stats.rx_errors);
+		goto drop;
 	}
 
 	/* Get the "l2_offset", if allowed. */
-	l2_offset = custom_str ? 0 : gxio_mpipe_idesc_get_l2_offset(idesc);
+	l2_offset = custom_flag ? 0 : gxio_mpipe_idesc_get_l2_offset(idesc);
 
-	/* Get the raw buffer VA (includes "headroom"). */
-	va = tile_io_addr_to_va((unsigned long)(long)idesc->va);
+	/* Get the VA (including NET_IP_ALIGN bytes of "headroom"). */
+	va = tile_io_addr_to_va((unsigned long)idesc->va);
 
 	/* Get the actual packet start/length. */
 	buf = va + l2_offset;
@@ -470,7 +622,10 @@ static bool tile_net_handle_packet(gxio_mpipe_idesc_t *idesc)
 
 	filter = filter_packet(dev, buf);
 	if (filter) {
-		gxio_mpipe_iqueue_drop(&info->iqueue, idesc);
+		if (dev)
+			tile_net_stats_add(1, &dev->stats.rx_dropped);
+drop:
+		gxio_mpipe_iqueue_drop(&info->mpipe[instance].iqueue, idesc);
 	} else {
 		struct sk_buff *skb = mpipe_buf_to_skb(va);
 
@@ -480,7 +635,7 @@ static bool tile_net_handle_packet(gxio_mpipe_idesc_t *idesc)
 		tile_net_receive_skb(dev, skb, idesc, len);
 	}
 
-	gxio_mpipe_iqueue_consume(&info->iqueue, idesc);
+	gxio_mpipe_iqueue_consume(&info->mpipe[instance].iqueue, idesc);
 	return !filter;
 }
 
@@ -501,14 +656,20 @@ static int tile_net_poll(struct napi_struct *napi, int budget)
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
 	unsigned int work = 0;
 	gxio_mpipe_idesc_t *idesc;
-	int i, n;
-
-	/* Process packets. */
-	while ((n = gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc)) > 0) {
+	int instance, i, n;
+	struct mpipe_data *md;
+	struct info_mpipe *info_mpipe =
+		container_of(napi, struct info_mpipe, napi);
+
+	instance = info_mpipe->instance;
+	while ((n = gxio_mpipe_iqueue_try_peek(
+			&info_mpipe->iqueue,
+			&idesc)) > 0) {
 		for (i = 0; i < n; i++) {
 			if (i == TILE_NET_BATCH)
 				goto done;
-			if (tile_net_handle_packet(idesc + i)) {
+			if (tile_net_handle_packet(instance,
+						   idesc + i)) {
 				if (++work >= budget)
 					goto done;
 			}
@@ -516,14 +677,16 @@ static int tile_net_poll(struct napi_struct *napi, int budget)
 	}
 
 	/* There are no packets left. */
-	napi_complete(&info->napi);
+	napi_complete(&info_mpipe->napi);
 
+	md = &mpipe_data[instance];
 	/* Re-enable hypervisor interrupts. */
-	gxio_mpipe_enable_notif_ring_interrupt(&context, info->iqueue.ring);
+	gxio_mpipe_enable_notif_ring_interrupt(
+		&md->context, info->mpipe[instance].iqueue.ring);
 
 	/* HACK: Avoid the "rotting packet" problem. */
-	if (gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc) > 0)
-		napi_schedule(&info->napi);
+	if (gxio_mpipe_iqueue_try_peek(&info_mpipe->iqueue, &idesc) > 0)
+		napi_schedule(&info_mpipe->napi);
 
 	/* ISSUE: Handle completions? */
 
@@ -533,11 +696,11 @@ done:
 	return work;
 }
 
-/* Handle an ingress interrupt on the current cpu. */
-static irqreturn_t tile_net_handle_ingress_irq(int irq, void *unused)
+/* Handle an ingress interrupt from an instance on the current cpu. */
+static irqreturn_t tile_net_handle_ingress_irq(int irq, void *id)
 {
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
-	napi_schedule(&info->napi);
+	napi_schedule(&info->mpipe[(uint64_t)id].napi);
 	return IRQ_HANDLED;
 }
 
@@ -579,7 +742,9 @@ static void tile_net_schedule_tx_wake_timer(struct net_device *dev,
 {
 	struct tile_net_info *info = &per_cpu(per_cpu_info, tx_queue_idx);
 	struct tile_net_priv *priv = netdev_priv(dev);
-	struct tile_net_tx_wake *tx_wake = &info->tx_wake[priv->echannel];
+	int instance = priv->instance;
+	struct tile_net_tx_wake *tx_wake =
+		&info->mpipe[instance].tx_wake[priv->echannel];
 
 	hrtimer_start(&tx_wake->timer,
 		      ktime_set(0, TX_TIMER_DELAY_USEC * 1000UL),
@@ -617,7 +782,7 @@ static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t)
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
 	unsigned long irqflags;
 	bool pending = false;
-	int i;
+	int i, instance;
 
 	local_irq_save(irqflags);
 
@@ -625,13 +790,19 @@ static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t)
 	info->egress_timer_scheduled = false;
 
 	/* Free all possible comps for this tile. */
-	for (i = 0; i < TILE_NET_CHANNELS; i++) {
-		struct tile_net_egress *egress = &egress_for_echannel[i];
-		struct tile_net_comps *comps = info->comps_for_echannel[i];
-		if (comps->comp_last >= comps->comp_next)
-			continue;
-		tile_net_free_comps(egress->equeue, comps, -1, true);
-		pending = pending || (comps->comp_last < comps->comp_next);
+	for (instance = 0; instance < NR_MPIPE_MAX &&
+		     info->mpipe[instance].has_iqueue; instance++) {
+		for (i = 0; i < TILE_NET_CHANNELS; i++) {
+			struct tile_net_egress *egress =
+				&mpipe_data[instance].egress_for_echannel[i];
+			struct tile_net_comps *comps =
+				info->mpipe[instance].comps_for_echannel[i];
+			if (!egress || comps->comp_last >= comps->comp_next)
+				continue;
+			tile_net_free_comps(egress->equeue, comps, -1, true);
+			pending = pending ||
+				(comps->comp_last < comps->comp_next);
+		}
 	}
 
 	/* Reschedule timer if needed. */
@@ -643,37 +814,112 @@ static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t)
 	return HRTIMER_NORESTART;
 }
 
-/* Helper function for "tile_net_update()".
- * "dev" (i.e. arg) is the device being brought up or down,
- * or NULL if all devices are now down.
- */
-static void tile_net_update_cpu(void *arg)
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+
+/* PTP clock operations. */
+
+static int ptp_mpipe_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
 {
-	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
-	struct net_device *dev = arg;
+	int ret = 0;
+	struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
+	mutex_lock(&md->ptp_lock);
+	if (gxio_mpipe_adjust_timestamp_freq(&md->context, ppb))
+		ret = -EINVAL;
+	mutex_unlock(&md->ptp_lock);
+	return ret;
+}
 
-	if (!info->has_iqueue)
-		return;
+static int ptp_mpipe_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	int ret = 0;
+	struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
+	mutex_lock(&md->ptp_lock);
+	if (gxio_mpipe_adjust_timestamp(&md->context, delta))
+		ret = -EBUSY;
+	mutex_unlock(&md->ptp_lock);
+	return ret;
+}
 
-	if (dev != NULL) {
-		if (!info->napi_added) {
-			netif_napi_add(dev, &info->napi,
-				       tile_net_poll, TILE_NET_WEIGHT);
-			info->napi_added = true;
-		}
-		if (!info->napi_enabled) {
-			napi_enable(&info->napi);
-			info->napi_enabled = true;
-		}
-		enable_percpu_irq(ingress_irq, 0);
-	} else {
-		disable_percpu_irq(ingress_irq);
-		if (info->napi_enabled) {
-			napi_disable(&info->napi);
-			info->napi_enabled = false;
-		}
-		/* FIXME: Drain the iqueue. */
-	}
+static int ptp_mpipe_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	int ret = 0;
+	struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
+	mutex_lock(&md->ptp_lock);
+	if (gxio_mpipe_get_timestamp(&md->context, ts))
+		ret = -EBUSY;
+	mutex_unlock(&md->ptp_lock);
+	return ret;
+}
+
+static int ptp_mpipe_settime(struct ptp_clock_info *ptp,
+			     const struct timespec *ts)
+{
+	int ret = 0;
+	struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
+	mutex_lock(&md->ptp_lock);
+	if (gxio_mpipe_set_timestamp(&md->context, ts))
+		ret = -EBUSY;
+	mutex_unlock(&md->ptp_lock);
+	return ret;
+}
+
+static int ptp_mpipe_enable(struct ptp_clock_info *ptp,
+			    struct ptp_clock_request *request, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info ptp_mpipe_caps = {
+	.owner		= THIS_MODULE,
+	.name		= "mPIPE clock",
+	.max_adj	= 999999999,
+	.n_ext_ts	= 0,
+	.pps		= 0,
+	.adjfreq	= ptp_mpipe_adjfreq,
+	.adjtime	= ptp_mpipe_adjtime,
+	.gettime	= ptp_mpipe_gettime,
+	.settime	= ptp_mpipe_settime,
+	.enable		= ptp_mpipe_enable,
+};
+
+#endif /* CONFIG_PTP_1588_CLOCK_TILEGX */
+
+/* Sync mPIPE's timestamp up with Linux system time and register PTP clock. */
+static void register_ptp_clock(struct net_device *dev, struct mpipe_data *md)
+{
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	struct timespec ts;
+
+	getnstimeofday(&ts);
+	gxio_mpipe_set_timestamp(&md->context, &ts);
+
+	mutex_init(&md->ptp_lock);
+	md->caps = ptp_mpipe_caps;
+	md->ptp_clock = ptp_clock_register(&md->caps, NULL);
+	if (IS_ERR(md->ptp_clock))
+		netdev_err(dev, "ptp_clock_register failed %ld\n",
+			   PTR_ERR(md->ptp_clock));
+#endif
+}
+
+/* Initialize PTP fields in a new device. */
+static void init_ptp_dev(struct tile_net_priv *priv)
+{
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+	priv->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+	priv->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
+#endif
+}
+
+/* Helper functions for "tile_net_update()". */
+static void enable_ingress_irq(void *irq)
+{
+	enable_percpu_irq((long)irq, 0);
+}
+
+static void disable_ingress_irq(void *irq)
+{
+	disable_percpu_irq((long)irq);
 }
 
 /* Helper function for tile_net_open() and tile_net_stop().
@@ -683,19 +929,22 @@ static int tile_net_update(struct net_device *dev)
 {
 	static gxio_mpipe_rules_t rules;  /* too big to fit on the stack */
 	bool saw_channel = false;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
 	int channel;
 	int rc;
 	int cpu;
 
-	gxio_mpipe_rules_init(&rules, &context);
+	saw_channel = false;
+	gxio_mpipe_rules_init(&rules, &md->context);
 
 	for (channel = 0; channel < TILE_NET_CHANNELS; channel++) {
-		if (tile_net_devs_for_channel[channel] == NULL)
+		if (md->tile_net_devs_for_channel[channel] == NULL)
 			continue;
 		if (!saw_channel) {
 			saw_channel = true;
-			gxio_mpipe_rules_begin(&rules, first_bucket,
-					       num_buckets, NULL);
+			gxio_mpipe_rules_begin(&rules, md->first_bucket,
+					       md->num_buckets, NULL);
 			gxio_mpipe_rules_set_headroom(&rules, NET_IP_ALIGN);
 		}
 		gxio_mpipe_rules_add_channel(&rules, channel);
@@ -706,102 +955,150 @@ static int tile_net_update(struct net_device *dev)
 	 */
 	rc = gxio_mpipe_rules_commit(&rules);
 	if (rc != 0) {
-		netdev_warn(dev, "gxio_mpipe_rules_commit failed: %d\n", rc);
+		netdev_warn(dev, "gxio_mpipe_rules_commit: mpipe[%d] %d\n",
+			    instance, rc);
 		return -EIO;
 	}
 
-	/* Update all cpus, sequentially (to protect "netif_napi_add()"). */
-	for_each_online_cpu(cpu)
-		smp_call_function_single(cpu, tile_net_update_cpu,
-					 (saw_channel ? dev : NULL), 1);
+	/* Update all cpus, sequentially (to protect "netif_napi_add()").
+	 * We use on_each_cpu to handle the IPI mask or unmask.
+	 */
+	if (!saw_channel)
+		on_each_cpu(disable_ingress_irq,
+			    (void *)(long)(md->ingress_irq), 1);
+	for_each_online_cpu(cpu) {
+		struct tile_net_info *info = &per_cpu(per_cpu_info, cpu);
+
+		if (!info->mpipe[instance].has_iqueue)
+			continue;
+		if (saw_channel) {
+			if (!info->mpipe[instance].napi_added) {
+				netif_napi_add(dev, &info->mpipe[instance].napi,
+					       tile_net_poll, TILE_NET_WEIGHT);
+				info->mpipe[instance].napi_added = true;
+			}
+			if (!info->mpipe[instance].napi_enabled) {
+				napi_enable(&info->mpipe[instance].napi);
+				info->mpipe[instance].napi_enabled = true;
+			}
+		} else {
+			if (info->mpipe[instance].napi_enabled) {
+				napi_disable(&info->mpipe[instance].napi);
+				info->mpipe[instance].napi_enabled = false;
+			}
+			/* FIXME: Drain the iqueue. */
+		}
+	}
+	if (saw_channel)
+		on_each_cpu(enable_ingress_irq,
+			    (void *)(long)(md->ingress_irq), 1);
 
 	/* HACK: Allow packets to flow in the simulator. */
 	if (saw_channel)
-		sim_enable_mpipe_links(0, -1);
+		sim_enable_mpipe_links(instance, -1);
 
 	return 0;
 }
 
-/* Allocate and initialize mpipe buffer stacks, and register them in
- * the mPIPE TLBs, for both small and large packet sizes.
- * This routine supports tile_net_init_mpipe(), below.
- */
-static int init_buffer_stacks(struct net_device *dev, int num_buffers)
+/* Initialize a buffer stack. */
+static int create_buffer_stack(struct net_device *dev,
+			       int kind, size_t num_buffers)
 {
 	pte_t hash_pte = pte_set_home((pte_t) { 0 }, PAGE_HOME_HASH);
-	int rc;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
+	size_t needed = gxio_mpipe_calc_buffer_stack_bytes(num_buffers);
+	int stack_idx = md->first_buffer_stack + kind;
+	void *va;
+	int i, rc;
 
-	/* Compute stack bytes; we round up to 64KB and then use
-	 * alloc_pages() so we get the required 64KB alignment as well.
+	/* Round up to 64KB and then use alloc_pages() so we get the
+	 * required 64KB alignment.
 	 */
-	buffer_stack_size =
-		ALIGN(gxio_mpipe_calc_buffer_stack_bytes(num_buffers),
-		      64 * 1024);
+	md->buffer_stack_bytes[kind] =
+		ALIGN(needed, 64 * 1024);
 
-	/* Allocate two buffer stack indices. */
-	rc = gxio_mpipe_alloc_buffer_stacks(&context, 2, 0, 0);
-	if (rc < 0) {
-		netdev_err(dev, "gxio_mpipe_alloc_buffer_stacks failed: %d\n",
-			   rc);
-		return rc;
-	}
-	small_buffer_stack = rc;
-	large_buffer_stack = rc + 1;
-
-	/* Allocate the small memory stack. */
-	small_buffer_stack_va =
-		alloc_pages_exact(buffer_stack_size, GFP_KERNEL);
-	if (small_buffer_stack_va == NULL) {
+	va = alloc_pages_exact(md->buffer_stack_bytes[kind], GFP_KERNEL);
+	if (va == NULL) {
 		netdev_err(dev,
-			   "Could not alloc %zd bytes for buffer stacks\n",
-			   buffer_stack_size);
+			   "Could not alloc %zd bytes for buffer stack %d\n",
+			   md->buffer_stack_bytes[kind], kind);
 		return -ENOMEM;
 	}
-	rc = gxio_mpipe_init_buffer_stack(&context, small_buffer_stack,
-					  BUFFER_SIZE_SMALL_ENUM,
-					  small_buffer_stack_va,
-					  buffer_stack_size, 0);
+
+	/* Initialize the buffer stack. */
+	rc = gxio_mpipe_init_buffer_stack(&md->context, stack_idx,
+					  buffer_size_enums[kind],  va,
+					  md->buffer_stack_bytes[kind], 0);
 	if (rc != 0) {
-		netdev_err(dev, "gxio_mpipe_init_buffer_stack: %d\n", rc);
+		netdev_err(dev, "gxio_mpipe_init_buffer_stack: mpipe[%d] %d\n",
+			   instance, rc);
+		free_pages_exact(va, md->buffer_stack_bytes[kind]);
 		return rc;
 	}
-	rc = gxio_mpipe_register_client_memory(&context, small_buffer_stack,
+
+	md->buffer_stack_vas[kind] = va;
+
+	rc = gxio_mpipe_register_client_memory(&md->context, stack_idx,
 					       hash_pte, 0);
 	if (rc != 0) {
 		netdev_err(dev,
-			   "gxio_mpipe_register_buffer_memory failed: %d\n",
-			   rc);
+			   "gxio_mpipe_register_client_memory: mpipe[%d] %d\n",
+			   instance, rc);
 		return rc;
 	}
 
-	/* Allocate the large buffer stack. */
-	large_buffer_stack_va =
-		alloc_pages_exact(buffer_stack_size, GFP_KERNEL);
-	if (large_buffer_stack_va == NULL) {
-		netdev_err(dev,
-			   "Could not alloc %zd bytes for buffer stacks\n",
-			   buffer_stack_size);
-		return -ENOMEM;
-	}
-	rc = gxio_mpipe_init_buffer_stack(&context, large_buffer_stack,
-					  BUFFER_SIZE_LARGE_ENUM,
-					  large_buffer_stack_va,
-					  buffer_stack_size, 0);
-	if (rc != 0) {
-		netdev_err(dev, "gxio_mpipe_init_buffer_stack failed: %d\n",
-			   rc);
-		return rc;
+	/* Provide initial buffers. */
+	for (i = 0; i < num_buffers; i++) {
+		if (!tile_net_provide_buffer(instance, kind)) {
+			netdev_err(dev, "Cannot allocate initial sk_bufs!\n");
+			return -ENOMEM;
+		}
 	}
-	rc = gxio_mpipe_register_client_memory(&context, large_buffer_stack,
-					       hash_pte, 0);
-	if (rc != 0) {
+
+	return 0;
+}
+
+/* Allocate and initialize mpipe buffer stacks, and register them in
+ * the mPIPE TLBs, for small, large, and (possibly) jumbo packet sizes.
+ * This routine supports tile_net_init_mpipe(), below.
+ */
+static int init_buffer_stacks(struct net_device *dev,
+			      int network_cpus_count)
+{
+	int num_kinds = MAX_KINDS - (jumbo_num == 0);
+	size_t num_buffers;
+	int rc;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
+
+	/* Allocate the buffer stacks. */
+	rc = gxio_mpipe_alloc_buffer_stacks(&md->context, num_kinds, 0, 0);
+	if (rc < 0) {
 		netdev_err(dev,
-			   "gxio_mpipe_register_buffer_memory failed: %d\n",
-			   rc);
+			   "gxio_mpipe_alloc_buffer_stacks: mpipe[%d] %d\n",
+			   instance, rc);
 		return rc;
 	}
+	md->first_buffer_stack = rc;
 
-	return 0;
+	/* Enough small/large buffers to (normally) avoid buffer errors. */
+	num_buffers =
+		network_cpus_count * (IQUEUE_ENTRIES + TILE_NET_BATCH);
+
+	/* Allocate the small memory stack. */
+	if (rc >= 0)
+		rc = create_buffer_stack(dev, 0, num_buffers);
+
+	/* Allocate the large buffer stack. */
+	if (rc >= 0)
+		rc = create_buffer_stack(dev, 1, num_buffers);
+
+	/* Allocate the jumbo buffer stack if needed. */
+	if (rc >= 0 && jumbo_num != 0)
+		rc = create_buffer_stack(dev, 2, jumbo_num);
+
+	return rc;
 }
 
 /* Allocate per-cpu resources (memory for completions and idescs).
@@ -812,6 +1109,8 @@ static int alloc_percpu_mpipe_resources(struct net_device *dev,
 {
 	struct tile_net_info *info = &per_cpu(per_cpu_info, cpu);
 	int order, i, rc;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
 	struct page *page;
 	void *addr;
 
@@ -826,7 +1125,7 @@ static int alloc_percpu_mpipe_resources(struct net_device *dev,
 	addr = pfn_to_kaddr(page_to_pfn(page));
 	memset(addr, 0, COMPS_SIZE);
 	for (i = 0; i < TILE_NET_CHANNELS; i++)
-		info->comps_for_echannel[i] =
+		info->mpipe[instance].comps_for_echannel[i] =
 			addr + i * sizeof(struct tile_net_comps);
 
 	/* If this is a network cpu, create an iqueue. */
@@ -840,14 +1139,15 @@ static int alloc_percpu_mpipe_resources(struct net_device *dev,
 			return -ENOMEM;
 		}
 		addr = pfn_to_kaddr(page_to_pfn(page));
-		rc = gxio_mpipe_iqueue_init(&info->iqueue, &context, ring++,
-					    addr, NOTIF_RING_SIZE, 0);
+		rc = gxio_mpipe_iqueue_init(&info->mpipe[instance].iqueue,
+					    &md->context, ring++, addr,
+					    NOTIF_RING_SIZE, 0);
 		if (rc < 0) {
 			netdev_err(dev,
 				   "gxio_mpipe_iqueue_init failed: %d\n", rc);
 			return rc;
 		}
-		info->has_iqueue = true;
+		info->mpipe[instance].has_iqueue = true;
 	}
 
 	return ring;
@@ -860,40 +1160,41 @@ static int init_notif_group_and_buckets(struct net_device *dev,
 					int ring, int network_cpus_count)
 {
 	int group, rc;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
 
 	/* Allocate one NotifGroup. */
-	rc = gxio_mpipe_alloc_notif_groups(&context, 1, 0, 0);
+	rc = gxio_mpipe_alloc_notif_groups(&md->context, 1, 0, 0);
 	if (rc < 0) {
-		netdev_err(dev, "gxio_mpipe_alloc_notif_groups failed: %d\n",
-			   rc);
+		netdev_err(dev, "gxio_mpipe_alloc_notif_groups: mpipe[%d] %d\n",
+			   instance, rc);
 		return rc;
 	}
 	group = rc;
 
 	/* Initialize global num_buckets value. */
 	if (network_cpus_count > 4)
-		num_buckets = 256;
+		md->num_buckets = 256;
 	else if (network_cpus_count > 1)
-		num_buckets = 16;
+		md->num_buckets = 16;
 
 	/* Allocate some buckets, and set global first_bucket value. */
-	rc = gxio_mpipe_alloc_buckets(&context, num_buckets, 0, 0);
+	rc = gxio_mpipe_alloc_buckets(&md->context, md->num_buckets, 0, 0);
 	if (rc < 0) {
-		netdev_err(dev, "gxio_mpipe_alloc_buckets failed: %d\n", rc);
+		netdev_err(dev, "gxio_mpipe_alloc_buckets: mpipe[%d] %d\n",
+			   instance, rc);
 		return rc;
 	}
-	first_bucket = rc;
+	md->first_bucket = rc;
 
 	/* Init group and buckets. */
 	rc = gxio_mpipe_init_notif_group_and_buckets(
-		&context, group, ring, network_cpus_count,
-		first_bucket, num_buckets,
+		&md->context, group, ring, network_cpus_count,
+		md->first_bucket, md->num_buckets,
 		GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY);
 	if (rc != 0) {
-		netdev_err(
-			dev,
-			"gxio_mpipe_init_notif_group_and_buckets failed: %d\n",
-			rc);
+		netdev_err(dev,	"gxio_mpipe_init_notif_group_and_buckets: "
+			   "mpipe[%d] %d\n", instance, rc);
 		return rc;
 	}
 
@@ -907,30 +1208,39 @@ static int init_notif_group_and_buckets(struct net_device *dev,
  */
 static int tile_net_setup_interrupts(struct net_device *dev)
 {
-	int cpu, rc;
+	int cpu, rc, irq;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
+
+	irq = md->ingress_irq;
+	if (irq < 0) {
+		irq = create_irq();
+		if (irq < 0) {
+			netdev_err(dev,
+				   "create_irq failed: mpipe[%d] %d\n",
+				   instance, irq);
+			return irq;
+		}
+		tile_irq_activate(irq, TILE_IRQ_PERCPU);
 
-	rc = create_irq();
-	if (rc < 0) {
-		netdev_err(dev, "create_irq failed: %d\n", rc);
-		return rc;
-	}
-	ingress_irq = rc;
-	tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU);
-	rc = request_irq(ingress_irq, tile_net_handle_ingress_irq,
-			 0, "tile_net", NULL);
-	if (rc != 0) {
-		netdev_err(dev, "request_irq failed: %d\n", rc);
-		destroy_irq(ingress_irq);
-		ingress_irq = -1;
-		return rc;
+		rc = request_irq(irq, tile_net_handle_ingress_irq,
+				 0, "tile_net", (void *)((uint64_t)instance));
+
+		if (rc != 0) {
+			netdev_err(dev, "request_irq failed: mpipe[%d] %d\n",
+				   instance, rc);
+			destroy_irq(irq);
+			return rc;
+		}
+		md->ingress_irq = irq;
 	}
 
 	for_each_online_cpu(cpu) {
 		struct tile_net_info *info = &per_cpu(per_cpu_info, cpu);
-		if (info->has_iqueue) {
-			gxio_mpipe_request_notif_ring_interrupt(
-				&context, cpu_x(cpu), cpu_y(cpu),
-				KERNEL_PL, ingress_irq, info->iqueue.ring);
+		if (info->mpipe[instance].has_iqueue) {
+			gxio_mpipe_request_notif_ring_interrupt(&md->context,
+				cpu_x(cpu), cpu_y(cpu), KERNEL_PL, irq,
+				info->mpipe[instance].iqueue.ring);
 		}
 	}
 
@@ -938,39 +1248,45 @@ static int tile_net_setup_interrupts(struct net_device *dev)
 }
 
 /* Undo any state set up partially by a failed call to tile_net_init_mpipe. */
-static void tile_net_init_mpipe_fail(void)
+static void tile_net_init_mpipe_fail(int instance)
 {
-	int cpu;
+	int kind, cpu;
+	struct mpipe_data *md = &mpipe_data[instance];
 
 	/* Do cleanups that require the mpipe context first. */
-	if (small_buffer_stack >= 0)
-		tile_net_pop_all_buffers(small_buffer_stack);
-	if (large_buffer_stack >= 0)
-		tile_net_pop_all_buffers(large_buffer_stack);
+	for (kind = 0; kind < MAX_KINDS; kind++) {
+		if (md->buffer_stack_vas[kind] != NULL) {
+			tile_net_pop_all_buffers(instance,
+						 md->first_buffer_stack +
+						 kind);
+		}
+	}
 
 	/* Destroy mpipe context so the hardware no longer owns any memory. */
-	gxio_mpipe_destroy(&context);
+	gxio_mpipe_destroy(&md->context);
 
 	for_each_online_cpu(cpu) {
 		struct tile_net_info *info = &per_cpu(per_cpu_info, cpu);
-		free_pages((unsigned long)(info->comps_for_echannel[0]),
-			   get_order(COMPS_SIZE));
-		info->comps_for_echannel[0] = NULL;
-		free_pages((unsigned long)(info->iqueue.idescs),
+		free_pages(
+			(unsigned long)(
+				info->mpipe[instance].comps_for_echannel[0]),
+			get_order(COMPS_SIZE));
+		info->mpipe[instance].comps_for_echannel[0] = NULL;
+		free_pages((unsigned long)(info->mpipe[instance].iqueue.idescs),
 			   get_order(NOTIF_RING_SIZE));
-		info->iqueue.idescs = NULL;
+		info->mpipe[instance].iqueue.idescs = NULL;
 	}
 
-	if (small_buffer_stack_va)
-		free_pages_exact(small_buffer_stack_va, buffer_stack_size);
-	if (large_buffer_stack_va)
-		free_pages_exact(large_buffer_stack_va, buffer_stack_size);
+	for (kind = 0; kind < MAX_KINDS; kind++) {
+		if (md->buffer_stack_vas[kind] != NULL) {
+			free_pages_exact(md->buffer_stack_vas[kind],
+					 md->buffer_stack_bytes[kind]);
+			md->buffer_stack_vas[kind] = NULL;
+		}
+	}
 
-	small_buffer_stack_va = NULL;
-	large_buffer_stack_va = NULL;
-	large_buffer_stack = -1;
-	small_buffer_stack = -1;
-	first_bucket = -1;
+	md->first_buffer_stack = -1;
+	md->first_bucket = -1;
 }
 
 /* The first time any tilegx network device is opened, we initialize
@@ -984,9 +1300,11 @@ static void tile_net_init_mpipe_fail(void)
  */
 static int tile_net_init_mpipe(struct net_device *dev)
 {
-	int i, num_buffers, rc;
+	int rc;
 	int cpu;
 	int first_ring, ring;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
 	int network_cpus_count = cpus_weight(network_cpus_map);
 
 	if (!hash_default) {
@@ -994,36 +1312,21 @@ static int tile_net_init_mpipe(struct net_device *dev)
 		return -EIO;
 	}
 
-	rc = gxio_mpipe_init(&context, 0);
+	rc = gxio_mpipe_init(&md->context, instance);
 	if (rc != 0) {
-		netdev_err(dev, "gxio_mpipe_init failed: %d\n", rc);
+		netdev_err(dev, "gxio_mpipe_init: mpipe[%d] %d\n",
+			   instance, rc);
 		return -EIO;
 	}
 
 	/* Set up the buffer stacks. */
-	num_buffers =
-		network_cpus_count * (IQUEUE_ENTRIES + TILE_NET_BATCH);
-	rc = init_buffer_stacks(dev, num_buffers);
+	rc = init_buffer_stacks(dev, network_cpus_count);
 	if (rc != 0)
 		goto fail;
 
-	/* Provide initial buffers. */
-	rc = -ENOMEM;
-	for (i = 0; i < num_buffers; i++) {
-		if (!tile_net_provide_buffer(true)) {
-			netdev_err(dev, "Cannot allocate initial sk_bufs!\n");
-			goto fail;
-		}
-	}
-	for (i = 0; i < num_buffers; i++) {
-		if (!tile_net_provide_buffer(false)) {
-			netdev_err(dev, "Cannot allocate initial sk_bufs!\n");
-			goto fail;
-		}
-	}
-
 	/* Allocate one NotifRing for each network cpu. */
-	rc = gxio_mpipe_alloc_notif_rings(&context, network_cpus_count, 0, 0);
+	rc = gxio_mpipe_alloc_notif_rings(&md->context,
+					  network_cpus_count, 0, 0);
 	if (rc < 0) {
 		netdev_err(dev, "gxio_mpipe_alloc_notif_rings failed %d\n",
 			   rc);
@@ -1050,10 +1353,13 @@ static int tile_net_init_mpipe(struct net_device *dev)
 	if (rc != 0)
 		goto fail;
 
+	/* Register PTP clock and set mPIPE timestamp, if configured. */
+	register_ptp_clock(dev, md);
+
 	return 0;
 
 fail:
-	tile_net_init_mpipe_fail();
+	tile_net_init_mpipe_fail(instance);
 	return rc;
 }
 
@@ -1063,17 +1369,19 @@ fail:
  */
 static int tile_net_init_egress(struct net_device *dev, int echannel)
 {
+	static int ering = -1;
 	struct page *headers_page, *edescs_page, *equeue_page;
 	gxio_mpipe_edesc_t *edescs;
 	gxio_mpipe_equeue_t *equeue;
 	unsigned char *headers;
 	int headers_order, edescs_order, equeue_order;
 	size_t edescs_size;
-	int edma;
 	int rc = -ENOMEM;
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
 
 	/* Only initialize once. */
-	if (egress_for_echannel[echannel].equeue != NULL)
+	if (md->egress_for_echannel[echannel].equeue != NULL)
 		return 0;
 
 	/* Allocate memory for the "headers". */
@@ -1110,28 +1418,41 @@ static int tile_net_init_egress(struct net_device *dev, int echannel)
 	}
 	equeue = pfn_to_kaddr(page_to_pfn(equeue_page));
 
-	/* Allocate an edma ring.  Note that in practice this can't
-	 * fail, which is good, because we will leak an edma ring if so.
-	 */
-	rc = gxio_mpipe_alloc_edma_rings(&context, 1, 0, 0);
-	if (rc < 0) {
-		netdev_warn(dev, "gxio_mpipe_alloc_edma_rings failed: %d\n",
-			    rc);
-		goto fail_equeue;
+	/* Allocate an edma ring (using a one entry "free list"). */
+	if (ering < 0) {
+		rc = gxio_mpipe_alloc_edma_rings(&md->context, 1, 0, 0);
+		if (rc < 0) {
+			netdev_warn(dev, "gxio_mpipe_alloc_edma_rings: "
+				    "mpipe[%d] %d\n", instance, rc);
+			goto fail_equeue;
+		}
+		ering = rc;
 	}
-	edma = rc;
 
 	/* Initialize the equeue. */
-	rc = gxio_mpipe_equeue_init(equeue, &context, edma, echannel,
+	rc = gxio_mpipe_equeue_init(equeue, &md->context, ering, echannel,
 				    edescs, edescs_size, 0);
 	if (rc != 0) {
-		netdev_err(dev, "gxio_mpipe_equeue_init failed: %d\n", rc);
+		netdev_err(dev, "gxio_mpipe_equeue_init: mpipe[%d] %d\n",
+			   instance, rc);
 		goto fail_equeue;
 	}
 
+	/* Don't reuse the ering later. */
+	ering = -1;
+
+	if (jumbo_num != 0) {
+		/* Make sure "jumbo" packets can be egressed safely. */
+		if (gxio_mpipe_equeue_set_snf_size(equeue, 10368) < 0) {
+			/* ISSUE: There is no "gxio_mpipe_equeue_destroy()". */
+			netdev_warn(dev, "Jumbo packets may not be egressed"
+				    " properly on channel %d\n", echannel);
+		}
+	}
+
 	/* Done. */
-	egress_for_echannel[echannel].equeue = equeue;
-	egress_for_echannel[echannel].headers = headers;
+	md->egress_for_echannel[echannel].equeue = equeue;
+	md->egress_for_echannel[echannel].headers = headers;
 	return 0;
 
 fail_equeue:
@@ -1151,11 +1472,25 @@ fail:
 static int tile_net_link_open(struct net_device *dev, gxio_mpipe_link_t *link,
 			      const char *link_name)
 {
-	int rc = gxio_mpipe_link_open(link, &context, link_name, 0);
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
+	int rc = gxio_mpipe_link_open(link, &md->context, link_name, 0);
 	if (rc < 0) {
-		netdev_err(dev, "Failed to open '%s'\n", link_name);
+		netdev_err(dev, "Failed to open '%s', mpipe[%d], %d\n",
+			   link_name, instance, rc);
 		return rc;
 	}
+	if (jumbo_num != 0) {
+		u32 attr = GXIO_MPIPE_LINK_RECEIVE_JUMBO;
+		rc = gxio_mpipe_link_set_attr(link, attr, 1);
+		if (rc != 0) {
+			netdev_err(dev,
+				   "Cannot receive jumbo packets on '%s'\n",
+				   link_name);
+			gxio_mpipe_link_close(link);
+			return rc;
+		}
+	}
 	rc = gxio_mpipe_link_channel(link);
 	if (rc < 0 || rc >= TILE_NET_CHANNELS) {
 		netdev_err(dev, "gxio_mpipe_link_channel bad value: %d\n", rc);
@@ -1169,12 +1504,23 @@ static int tile_net_link_open(struct net_device *dev, gxio_mpipe_link_t *link,
 static int tile_net_open(struct net_device *dev)
 {
 	struct tile_net_priv *priv = netdev_priv(dev);
-	int cpu, rc;
+	int cpu, rc, instance;
 
 	mutex_lock(&tile_net_devs_for_channel_mutex);
 
-	/* Do one-time initialization the first time any device is opened. */
-	if (ingress_irq < 0) {
+	/* Get the instance info. */
+	rc = gxio_mpipe_link_instance(dev->name);
+	if (rc < 0 || rc >= NR_MPIPE_MAX) {
+		mutex_unlock(&tile_net_devs_for_channel_mutex);
+		return -EIO;
+	}
+
+	priv->instance = rc;
+	instance = rc;
+	if (!mpipe_data[rc].context.mmio_fast_base) {
+		/* Do one-time initialization per instance the first time
+		 * any device is opened.
+		 */
 		rc = tile_net_init_mpipe(dev);
 		if (rc != 0)
 			goto fail;
@@ -1205,7 +1551,7 @@ static int tile_net_open(struct net_device *dev)
 	if (rc != 0)
 		goto fail;
 
-	tile_net_devs_for_channel[priv->channel] = dev;
+	mpipe_data[instance].tile_net_devs_for_channel[priv->channel] = dev;
 
 	rc = tile_net_update(dev);
 	if (rc != 0)
@@ -1217,7 +1563,7 @@ static int tile_net_open(struct net_device *dev)
 	for_each_online_cpu(cpu) {
 		struct tile_net_info *info = &per_cpu(per_cpu_info, cpu);
 		struct tile_net_tx_wake *tx_wake =
-			&info->tx_wake[priv->echannel];
+			&info->mpipe[instance].tx_wake[priv->echannel];
 
 		hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC,
 			     HRTIMER_MODE_REL);
@@ -1243,7 +1589,7 @@ fail:
 		priv->channel = -1;
 	}
 	priv->echannel = -1;
-	tile_net_devs_for_channel[priv->channel] = NULL;
+	mpipe_data[instance].tile_net_devs_for_channel[priv->channel] =	NULL;
 	mutex_unlock(&tile_net_devs_for_channel_mutex);
 
 	/* Don't return raw gxio error codes to generic Linux. */
@@ -1255,18 +1601,20 @@ static int tile_net_stop(struct net_device *dev)
 {
 	struct tile_net_priv *priv = netdev_priv(dev);
 	int cpu;
+	int instance = priv->instance;
+	struct mpipe_data *md = &mpipe_data[instance];
 
 	for_each_online_cpu(cpu) {
 		struct tile_net_info *info = &per_cpu(per_cpu_info, cpu);
 		struct tile_net_tx_wake *tx_wake =
-			&info->tx_wake[priv->echannel];
+			&info->mpipe[instance].tx_wake[priv->echannel];
 
 		hrtimer_cancel(&tx_wake->timer);
 		netif_stop_subqueue(dev, cpu);
 	}
 
 	mutex_lock(&tile_net_devs_for_channel_mutex);
-	tile_net_devs_for_channel[priv->channel] = NULL;
+	md->tile_net_devs_for_channel[priv->channel] = NULL;
 	(void)tile_net_update(dev);
 	if (priv->loopify_channel >= 0) {
 		if (gxio_mpipe_link_close(&priv->loopify_link) != 0)
@@ -1374,20 +1722,20 @@ static int tso_count_edescs(struct sk_buff *skb)
 	return num_edescs;
 }
 
-/* Prepare modified copies of the skbuff headers.
- * FIXME: add support for IPv6.
- */
+/* Prepare modified copies of the skbuff headers. */
 static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
 				s64 slot)
 {
 	struct skb_shared_info *sh = skb_shinfo(skb);
 	struct iphdr *ih;
+	struct ipv6hdr *ih6;
 	struct tcphdr *th;
 	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	unsigned int data_len = skb->len - sh_len;
 	unsigned char *data = skb->data;
 	unsigned int ih_off, th_off, p_len;
 	unsigned int isum_seed, tsum_seed, id, seq;
+	int is_ipv6;
 	long f_id = -1;    /* id of the current fragment */
 	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
 	long f_used = 0;  /* bytes used from the current fragment */
@@ -1395,18 +1743,24 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
 	int segment;
 
 	/* Locate original headers and compute various lengths. */
-	ih = ip_hdr(skb);
+	is_ipv6 = skb_is_gso_v6(skb);
+	if (is_ipv6) {
+		ih6 = ipv6_hdr(skb);
+		ih_off = skb_network_offset(skb);
+	} else {
+		ih = ip_hdr(skb);
+		ih_off = skb_network_offset(skb);
+		isum_seed = ((0xFFFF - ih->check) +
+			     (0xFFFF - ih->tot_len) +
+			     (0xFFFF - ih->id));
+		id = ntohs(ih->id);
+	}
+
 	th = tcp_hdr(skb);
-	ih_off = skb_network_offset(skb);
 	th_off = skb_transport_offset(skb);
 	p_len = sh->gso_size;
 
-	/* Set up seed values for IP and TCP csum and initialize id and seq. */
-	isum_seed = ((0xFFFF - ih->check) +
-		     (0xFFFF - ih->tot_len) +
-		     (0xFFFF - ih->id));
 	tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
-	id = ntohs(ih->id);
 	seq = ntohl(th->seq);
 
 	/* Prepare all the headers. */
@@ -1420,11 +1774,17 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
 		memcpy(buf, data, sh_len);
 
 		/* Update copied ip header. */
-		ih = (struct iphdr *)(buf + ih_off);
-		ih->tot_len = htons(sh_len + p_len - ih_off);
-		ih->id = htons(id);
-		ih->check = csum_long(isum_seed + ih->tot_len +
-				      ih->id) ^ 0xffff;
+		if (is_ipv6) {
+			ih6 = (struct ipv6hdr *)(buf + ih_off);
+			ih6->payload_len = htons(sh_len + p_len - ih_off -
+						 sizeof(*ih6));
+		} else {
+			ih = (struct iphdr *)(buf + ih_off);
+			ih->tot_len = htons(sh_len + p_len - ih_off);
+			ih->id = htons(id);
+			ih->check = csum_long(isum_seed + ih->tot_len +
+					      ih->id) ^ 0xffff;
+		}
 
 		/* Update copied tcp header. */
 		th = (struct tcphdr *)(buf + th_off);
@@ -1475,8 +1835,9 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
 static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 		       struct sk_buff *skb, unsigned char *headers, s64 slot)
 {
-	struct tile_net_priv *priv = netdev_priv(dev);
 	struct skb_shared_info *sh = skb_shinfo(skb);
+	int instance = mpipe_instance(dev);
+	struct mpipe_data *md = &mpipe_data[instance];
 	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	unsigned int data_len = skb->len - sh_len;
 	unsigned int p_len = sh->gso_size;
@@ -1499,8 +1860,8 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 	edesc_head.xfer_size = sh_len;
 
 	/* This is only used to specify the TLB. */
-	edesc_head.stack_idx = large_buffer_stack;
-	edesc_body.stack_idx = large_buffer_stack;
+	edesc_head.stack_idx = md->first_buffer_stack;
+	edesc_body.stack_idx = md->first_buffer_stack;
 
 	/* Egress all the edescs. */
 	for (segment = 0; segment < sh->gso_segs; segment++) {
@@ -1553,8 +1914,8 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 	}
 
 	/* Update stats. */
-	tile_net_stats_add(tx_packets, &priv->stats.tx_packets);
-	tile_net_stats_add(tx_bytes, &priv->stats.tx_bytes);
+	tile_net_stats_add(tx_packets, &dev->stats.tx_packets);
+	tile_net_stats_add(tx_bytes, &dev->stats.tx_bytes);
 }
 
 /* Do "TSO" handling for egress.
@@ -1575,8 +1936,11 @@ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
 	struct tile_net_priv *priv = netdev_priv(dev);
 	int channel = priv->echannel;
-	struct tile_net_egress *egress = &egress_for_echannel[channel];
-	struct tile_net_comps *comps = info->comps_for_echannel[channel];
+	int instance = priv->instance;
+	struct mpipe_data *md = &mpipe_data[instance];
+	struct tile_net_egress *egress = &md->egress_for_echannel[channel];
+	struct tile_net_comps *comps =
+		info->mpipe[instance].comps_for_echannel[channel];
 	gxio_mpipe_equeue_t *equeue = egress->equeue;
 	unsigned long irqflags;
 	int num_edescs;
@@ -1640,10 +2004,13 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
 	struct tile_net_priv *priv = netdev_priv(dev);
-	struct tile_net_egress *egress = &egress_for_echannel[priv->echannel];
+	int instance = priv->instance;
+	struct mpipe_data *md = &mpipe_data[instance];
+	struct tile_net_egress *egress =
+		&md->egress_for_echannel[priv->echannel];
 	gxio_mpipe_equeue_t *equeue = egress->equeue;
 	struct tile_net_comps *comps =
-		info->comps_for_echannel[priv->echannel];
+		info->mpipe[instance].comps_for_echannel[priv->echannel];
 	unsigned int len = skb->len;
 	unsigned char *data = skb->data;
 	unsigned int num_edescs;
@@ -1660,7 +2027,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 	num_edescs = tile_net_tx_frags(frags, skb, data, skb_headlen(skb));
 
 	/* This is only used to specify the TLB. */
-	edesc.stack_idx = large_buffer_stack;
+	edesc.stack_idx = md->first_buffer_stack;
 
 	/* Prepare the edescs. */
 	for (i = 0; i < num_edescs; i++) {
@@ -1693,13 +2060,16 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 	for (i = 0; i < num_edescs; i++)
 		gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++);
 
+	/* Store TX timestamp if needed. */
+	tile_tx_timestamp(skb, instance);
+
 	/* Add a completion record. */
 	add_comp(equeue, comps, slot - 1, skb);
 
 	/* NOTE: Use ETH_ZLEN for short packets (e.g. 42 < 60). */
-	tile_net_stats_add(1, &priv->stats.tx_packets);
+	tile_net_stats_add(1, &dev->stats.tx_packets);
 	tile_net_stats_add(max_t(unsigned int, len, ETH_ZLEN),
-			   &priv->stats.tx_bytes);
+			   &dev->stats.tx_bytes);
 
 	local_irq_restore(irqflags);
 
@@ -1727,20 +2097,18 @@ static void tile_net_tx_timeout(struct net_device *dev)
 /* Ioctl commands. */
 static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	return -EOPNOTSUPP;
-}
+	if (cmd == SIOCSHWTSTAMP)
+		return tile_hwtstamp_ioctl(dev, rq, cmd);
 
-/* Get system network statistics for device. */
-static struct net_device_stats *tile_net_get_stats(struct net_device *dev)
-{
-	struct tile_net_priv *priv = netdev_priv(dev);
-	return &priv->stats;
+	return -EOPNOTSUPP;
 }
 
 /* Change the MTU. */
 static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
 {
-	if ((new_mtu < 68) || (new_mtu > 1500))
+	if (new_mtu < 68)
+		return -EINVAL;
+	if (new_mtu > ((jumbo_num != 0) ? 9000 : 1500))
 		return -EINVAL;
 	dev->mtu = new_mtu;
 	return 0;
@@ -1772,9 +2140,13 @@ static int tile_net_set_mac_address(struct net_device *dev, void *p)
  */
 static void tile_net_netpoll(struct net_device *dev)
 {
-	disable_percpu_irq(ingress_irq);
-	tile_net_handle_ingress_irq(ingress_irq, NULL);
-	enable_percpu_irq(ingress_irq, 0);
+	int instance = mpipe_instance(dev);
+	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+	struct mpipe_data *md = &mpipe_data[instance];
+
+	disable_percpu_irq(md->ingress_irq);
+	napi_schedule(&info->mpipe[instance].napi);
+	enable_percpu_irq(md->ingress_irq, 0);
 }
 #endif
 
@@ -1784,7 +2156,6 @@ static const struct net_device_ops tile_net_ops = {
 	.ndo_start_xmit = tile_net_tx,
 	.ndo_select_queue = tile_net_select_queue,
 	.ndo_do_ioctl = tile_net_ioctl,
-	.ndo_get_stats = tile_net_get_stats,
 	.ndo_change_mtu = tile_net_change_mtu,
 	.ndo_tx_timeout = tile_net_tx_timeout,
 	.ndo_set_mac_address = tile_net_set_mac_address,
@@ -1800,14 +2171,21 @@ static const struct net_device_ops tile_net_ops = {
  */
 static void tile_net_setup(struct net_device *dev)
 {
+	netdev_features_t features = 0;
+
 	ether_setup(dev);
 	dev->netdev_ops = &tile_net_ops;
 	dev->watchdog_timeo = TILE_NET_TIMEOUT;
-	dev->features |= NETIF_F_LLTX;
-	dev->features |= NETIF_F_HW_CSUM;
-	dev->features |= NETIF_F_SG;
-	dev->features |= NETIF_F_TSO;
 	dev->mtu = 1500;
+
+	features |= NETIF_F_HW_CSUM;
+	features |= NETIF_F_SG;
+	features |= NETIF_F_TSO;
+	features |= NETIF_F_TSO6;
+
+	dev->hw_features   |= features;
+	dev->vlan_features |= features;
+	dev->features      |= features;
 }
 
 /* Allocate the device structure, register the device, and obtain the
@@ -1842,6 +2220,7 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac)
 	priv->channel = -1;
 	priv->loopify_channel = -1;
 	priv->echannel = -1;
+	init_ptp_dev(priv);
 
 	/* Get the MAC address and set it in the device struct; this must
 	 * be done before the device is opened.  If the MAC is all zeroes,
@@ -1871,9 +2250,12 @@ static void tile_net_init_module_percpu(void *unused)
 {
 	struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
 	int my_cpu = smp_processor_id();
+	int instance;
 
-	info->has_iqueue = false;
-
+	for (instance = 0; instance < NR_MPIPE_MAX; instance++) {
+		info->mpipe[instance].has_iqueue = false;
+		info->mpipe[instance].instance = instance;
+	}
 	info->my_cpu = my_cpu;
 
 	/* Initialize the egress timer. */
@@ -1890,6 +2272,8 @@ static int __init tile_net_init_module(void)
 
 	pr_info("Tilera Network Driver\n");
 
+	BUILD_BUG_ON(NR_MPIPE_MAX != 2);
+
 	mutex_init(&tile_net_devs_for_channel_mutex);
 
 	/* Initialize each CPU. */
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 3643549..106be47 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -31,6 +31,7 @@
 #include <linux/in6.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/u64_stats_sync.h>
 #include <asm/checksum.h>
 #include <asm/homecache.h>
 
@@ -88,13 +89,6 @@
 /* ISSUE: This has not been thoroughly tested (except at 1500). */
 #define TILE_NET_MTU 1500
 
-/* HACK: Define to support GSO. */
-/* ISSUE: This may actually hurt performance of the TCP blaster. */
-/* #define TILE_NET_GSO */
-
-/* Define this to collapse "duplicate" acks. */
-/* #define IGNORE_DUP_ACKS */
-
 /* HACK: Define this to verify incoming packets. */
 /* #define TILE_NET_VERIFY_INGRESS */
 
@@ -156,10 +150,13 @@ struct tile_netio_queue {
  * Statistics counters for a specific cpu and device.
  */
 struct tile_net_stats_t {
-	u32 rx_packets;
-	u32 rx_bytes;
-	u32 tx_packets;
-	u32 tx_bytes;
+	struct u64_stats_sync syncp;
+	u64 rx_packets;		/* total packets received	*/
+	u64 tx_packets;		/* total packets transmitted	*/
+	u64 rx_bytes;		/* total bytes received 	*/
+	u64 tx_bytes;		/* total bytes transmitted	*/
+	u64 rx_errors;		/* packets truncated or marked bad by hw */
+	u64 rx_dropped;		/* packets not for us or intf not up */
 };
 
 
@@ -218,8 +215,6 @@ struct tile_net_priv {
 	int network_cpus_count;
 	/* Credits per network cpu. */
 	int network_cpus_credits;
-	/* Network stats. */
-	struct net_device_stats stats;
 	/* For NetIO bringup retries. */
 	struct delayed_work retry_work;
 	/* Quick access to per cpu data. */
@@ -627,79 +622,6 @@ static void tile_net_handle_egress_timer(unsigned long arg)
 }
 
 
-#ifdef IGNORE_DUP_ACKS
-
-/*
- * Help detect "duplicate" ACKs.  These are sequential packets (for a
- * given flow) which are exactly 66 bytes long, sharing everything but
- * ID=2@0x12, Hsum=2@0x18, Ack=4@0x2a, WinSize=2@0x30, Csum=2@0x32,
- * Tstamps=10@0x38.  The ID's are +1, the Hsum's are -1, the Ack's are
- * +N, and the Tstamps are usually identical.
- *
- * NOTE: Apparently truly duplicate acks (with identical "ack" values),
- * should not be collapsed, as they are used for some kind of flow control.
- */
-static bool is_dup_ack(char *s1, char *s2, unsigned int len)
-{
-	int i;
-
-	unsigned long long ignorable = 0;
-
-	/* Identification. */
-	ignorable |= (1ULL << 0x12);
-	ignorable |= (1ULL << 0x13);
-
-	/* Header checksum. */
-	ignorable |= (1ULL << 0x18);
-	ignorable |= (1ULL << 0x19);
-
-	/* ACK. */
-	ignorable |= (1ULL << 0x2a);
-	ignorable |= (1ULL << 0x2b);
-	ignorable |= (1ULL << 0x2c);
-	ignorable |= (1ULL << 0x2d);
-
-	/* WinSize. */
-	ignorable |= (1ULL << 0x30);
-	ignorable |= (1ULL << 0x31);
-
-	/* Checksum. */
-	ignorable |= (1ULL << 0x32);
-	ignorable |= (1ULL << 0x33);
-
-	for (i = 0; i < len; i++, ignorable >>= 1) {
-
-		if ((ignorable & 1) || (s1[i] == s2[i]))
-			continue;
-
-#ifdef TILE_NET_DEBUG
-		/* HACK: Mention non-timestamp diffs. */
-		if (i < 0x38 && i != 0x2f &&
-		    net_ratelimit())
-			pr_info("Diff at 0x%x\n", i);
-#endif
-
-		return false;
-	}
-
-#ifdef TILE_NET_NO_SUPPRESS_DUP_ACKS
-	/* HACK: Do not suppress truly duplicate ACKs. */
-	/* ISSUE: Is this actually necessary or helpful? */
-	if (s1[0x2a] == s2[0x2a] &&
-	    s1[0x2b] == s2[0x2b] &&
-	    s1[0x2c] == s2[0x2c] &&
-	    s1[0x2d] == s2[0x2d]) {
-		return false;
-	}
-#endif
-
-	return true;
-}
-
-#endif
-
-
-
 static void tile_net_discard_aux(struct tile_net_cpu *info, int index)
 {
 	struct tile_netio_queue *queue = &info->queue;
@@ -774,6 +696,7 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 	netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index);
 
 	netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt);
+	netio_pkt_status_t pkt_status = NETIO_PKT_STATUS_M(metadata, pkt);
 
 	/* Extract the packet size.  FIXME: Shouldn't the second line */
 	/* get subtracted?  Mostly moot, since it should be "zero". */
@@ -806,40 +729,25 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 #endif /* TILE_NET_DUMP_PACKETS */
 
 #ifdef TILE_NET_VERIFY_INGRESS
-	if (!NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt) &&
-	    NETIO_PKT_L4_CSUM_CALCULATED_M(metadata, pkt)) {
-		/* Bug 6624: Includes UDP packets with a "zero" checksum. */
-		pr_warning("Bad L4 checksum on %d byte packet.\n", len);
-	}
-	if (!NETIO_PKT_L3_CSUM_CORRECT_M(metadata, pkt) &&
-	    NETIO_PKT_L3_CSUM_CALCULATED_M(metadata, pkt)) {
+	if (pkt_status == NETIO_PKT_STATUS_OVERSIZE && len >= 64) {
 		dump_packet(buf, len, "rx");
-		panic("Bad L3 checksum.");
-	}
-	switch (NETIO_PKT_STATUS_M(metadata, pkt)) {
-	case NETIO_PKT_STATUS_OVERSIZE:
-		if (len >= 64) {
-			dump_packet(buf, len, "rx");
-			panic("Unexpected OVERSIZE.");
-		}
-		break;
-	case NETIO_PKT_STATUS_BAD:
-		pr_warning("Unexpected BAD %ld byte packet.\n", len);
+		panic("Unexpected OVERSIZE.");
 	}
 #endif
 
 	filter = 0;
 
-	/* ISSUE: Filter TCP packets with "bad" checksums? */
-
-	if (!(dev->flags & IFF_UP)) {
+	if (pkt_status == NETIO_PKT_STATUS_BAD) {
+		/* Handle CRC error and hardware truncation. */
+		filter = 2;
+	} else if (!(dev->flags & IFF_UP)) {
 		/* Filter packets received before we're up. */
 		filter = 1;
-	} else if (NETIO_PKT_STATUS_M(metadata, pkt) == NETIO_PKT_STATUS_BAD) {
+	} else if (NETIO_PKT_ETHERTYPE_RECOGNIZED_M(metadata, pkt) &&
+		   pkt_status == NETIO_PKT_STATUS_UNDERSIZE) {
 		/* Filter "truncated" packets. */
-		filter = 1;
+		filter = 2;
 	} else if (!(dev->flags & IFF_PROMISC)) {
-		/* FIXME: Implement HW multicast filter. */
 		if (!is_multicast_ether_addr(buf)) {
 			/* Filter packets not for our address. */
 			const u8 *mine = dev->dev_addr;
@@ -847,9 +755,14 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 		}
 	}
 
-	if (filter) {
+	u64_stats_update_begin(&stats->syncp);
 
-		/* ISSUE: Update "drop" statistics? */
+	if (filter != 0) {
+
+		if (filter == 1)
+			stats->rx_dropped++;
+		else
+			stats->rx_errors++;
 
 		tile_net_provide_linux_buffer(info, va, small);
 
@@ -881,6 +794,8 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 		stats->rx_bytes += len;
 	}
 
+	u64_stats_update_end(&stats->syncp);
+
 	/* ISSUE: It would be nice to defer this until the packet has */
 	/* actually been processed. */
 	tile_net_return_credit(info);
@@ -1907,8 +1822,10 @@ busy:
 		kfree_skb(olds[i]);
 
 	/* Update stats. */
+	u64_stats_update_begin(&stats->syncp);
 	stats->tx_packets += num_segs;
 	stats->tx_bytes += (num_segs * sh_len) + d_len;
+	u64_stats_update_end(&stats->syncp);
 
 	/* Make sure the egress timer is scheduled. */
 	tile_net_schedule_egress_timer(info);
@@ -1936,7 +1853,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
 	unsigned int csum_start = skb_checksum_start_offset(skb);
 
-	lepp_frag_t frags[LEPP_MAX_FRAGS];
+	lepp_frag_t frags[1 + MAX_SKB_FRAGS];
 
 	unsigned int num_frags;
 
@@ -1951,7 +1868,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 	unsigned int cmd_head, cmd_tail, cmd_next;
 	unsigned int comp_tail;
 
-	lepp_cmd_t cmds[LEPP_MAX_FRAGS];
+	lepp_cmd_t cmds[1 + MAX_SKB_FRAGS];
 
 
 	/*
@@ -2089,8 +2006,10 @@ busy:
 		kfree_skb(olds[i]);
 
 	/* HACK: Track "expanded" size for short packets (e.g. 42 < 60). */
+	u64_stats_update_begin(&stats->syncp);
 	stats->tx_packets++;
 	stats->tx_bytes += ((len >= ETH_ZLEN) ? len : ETH_ZLEN);
+	u64_stats_update_end(&stats->syncp);
 
 	/* Make sure the egress timer is scheduled. */
 	tile_net_schedule_egress_timer(info);
@@ -2127,30 +2046,51 @@ static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  *
  * Returns the address of the device statistics structure.
  */
-static struct net_device_stats *tile_net_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *tile_net_get_stats64(struct net_device *dev,
+		struct rtnl_link_stats64 *stats)
 {
 	struct tile_net_priv *priv = netdev_priv(dev);
-	u32 rx_packets = 0;
-	u32 tx_packets = 0;
-	u32 rx_bytes = 0;
-	u32 tx_bytes = 0;
+	u64 rx_packets = 0, tx_packets = 0;
+	u64 rx_bytes = 0, tx_bytes = 0;
+	u64 rx_errors = 0, rx_dropped = 0;
 	int i;
 
 	for_each_online_cpu(i) {
-		if (priv->cpu[i]) {
-			rx_packets += priv->cpu[i]->stats.rx_packets;
-			rx_bytes += priv->cpu[i]->stats.rx_bytes;
-			tx_packets += priv->cpu[i]->stats.tx_packets;
-			tx_bytes += priv->cpu[i]->stats.tx_bytes;
-		}
+		struct tile_net_stats_t *cpu_stats;
+		u64 trx_packets, ttx_packets, trx_bytes, ttx_bytes;
+		u64 trx_errors, trx_dropped;
+		unsigned int start;
+
+		if (priv->cpu[i] == NULL)
+			continue;
+		cpu_stats = &priv->cpu[i]->stats;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&cpu_stats->syncp);
+			trx_packets = cpu_stats->rx_packets;
+			ttx_packets = cpu_stats->tx_packets;
+			trx_bytes   = cpu_stats->rx_bytes;
+			ttx_bytes   = cpu_stats->tx_bytes;
+			trx_errors  = cpu_stats->rx_errors;
+			trx_dropped = cpu_stats->rx_dropped;
+		} while (u64_stats_fetch_retry_bh(&cpu_stats->syncp, start));
+
+		rx_packets += trx_packets;
+		tx_packets += ttx_packets;
+		rx_bytes   += trx_bytes;
+		tx_bytes   += ttx_bytes;
+		rx_errors  += trx_errors;
+		rx_dropped += trx_dropped;
 	}
 
-	priv->stats.rx_packets = rx_packets;
-	priv->stats.rx_bytes = rx_bytes;
-	priv->stats.tx_packets = tx_packets;
-	priv->stats.tx_bytes = tx_bytes;
+	stats->rx_packets = rx_packets;
+	stats->tx_packets = tx_packets;
+	stats->rx_bytes   = rx_bytes;
+	stats->tx_bytes   = tx_bytes;
+	stats->rx_errors  = rx_errors;
+	stats->rx_dropped = rx_dropped;
 
-	return &priv->stats;
+	return stats;
 }
 
 
@@ -2287,7 +2227,7 @@ static const struct net_device_ops tile_net_ops = {
 	.ndo_stop = tile_net_stop,
 	.ndo_start_xmit = tile_net_tx,
 	.ndo_do_ioctl = tile_net_ioctl,
-	.ndo_get_stats = tile_net_get_stats,
+	.ndo_get_stats64 = tile_net_get_stats64,
 	.ndo_change_mtu = tile_net_change_mtu,
 	.ndo_tx_timeout = tile_net_tx_timeout,
 	.ndo_set_mac_address = tile_net_set_mac_address,
@@ -2305,39 +2245,30 @@ static const struct net_device_ops tile_net_ops = {
  */
 static void tile_net_setup(struct net_device *dev)
 {
-	PDEBUG("tile_net_setup()\n");
+	netdev_features_t features = 0;
 
 	ether_setup(dev);
-
 	dev->netdev_ops = &tile_net_ops;
-
 	dev->watchdog_timeo = TILE_NET_TIMEOUT;
+	dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN;
+	dev->mtu = TILE_NET_MTU;
 
-	/* We want lockless xmit. */
-	dev->features |= NETIF_F_LLTX;
-
-	/* We support hardware tx checksums. */
-	dev->features |= NETIF_F_HW_CSUM;
-
-	/* We support scatter/gather. */
-	dev->features |= NETIF_F_SG;
-
-	/* We support TSO. */
-	dev->features |= NETIF_F_TSO;
+	features |= NETIF_F_HW_CSUM;
+	features |= NETIF_F_SG;
 
-#ifdef TILE_NET_GSO
-	/* We support GSO. */
-	dev->features |= NETIF_F_GSO;
-#endif
+	/* We support TSO iff the HV supports sufficient frags. */
+	if (LEPP_MAX_FRAGS >= 1 + MAX_SKB_FRAGS)
+		features |= NETIF_F_TSO;
 
+	/* We can't support HIGHDMA without hash_default, since we need
+	 * to be able to finv() with a VA if we don't have hash_default.
+	 */
 	if (hash_default)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	/* ISSUE: We should support NETIF_F_UFO. */
+		features |= NETIF_F_HIGHDMA;
 
-	dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN;
-
-	dev->mtu = TILE_NET_MTU;
+	dev->hw_features   |= features;
+	dev->vlan_features |= features;
+	dev->features      |= features;
 }
 
 
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 1d6dc41..ef77631 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -2376,6 +2376,23 @@ out_0:
 	return ret;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ *  velocity_poll_controller		-	Velocity Poll controller function
+ *  @dev: network device
+ *
+ *
+ *  Used by NETCONSOLE and other diagnostic tools to allow network I/P
+ *  with interrupts disabled.
+ */
+static void velocity_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	velocity_intr(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
 /**
  *	velocity_mii_ioctl		-	MII ioctl handler
  *	@dev: network device
@@ -2641,6 +2658,9 @@ static const struct net_device_ops velocity_netdev_ops = {
 	.ndo_do_ioctl		= velocity_ioctl,
 	.ndo_vlan_rx_add_vid	= velocity_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= velocity_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = velocity_poll_controller,
+#endif
 };
 
 /**
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 23a0fff..524f713 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -306,7 +306,6 @@ static void netvsc_get_drvinfo(struct net_device *net,
 			       struct ethtool_drvinfo *info)
 {
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-	strlcpy(info->version, HV_DRV_VERSION, sizeof(info->version));
 	strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
 }
 
@@ -529,7 +528,6 @@ static int __init netvsc_drv_init(void)
 }
 
 MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V network driver");
 
 module_init(netvsc_drv_init);
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 510b9c8..c6bfc4a 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1755,17 +1755,4 @@ static struct pci_driver donauboe_pci_driver = {
 	.resume		= toshoboe_wakeup 
 };
 
-static int __init
-donauboe_init (void)
-{
-  return pci_register_driver(&donauboe_pci_driver);
-}
-
-static void __exit
-donauboe_cleanup (void)
-{
-  pci_unregister_driver(&donauboe_pci_driver);
-}
-
-module_init(donauboe_init);
-module_exit(donauboe_cleanup);
+module_pci_driver(donauboe_pci_driver);
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index a412671..177441a 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -123,14 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
 
 	tty = priv->tty;
 
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	old_termios = tty->termios;
 	cflag = tty->termios.c_cflag;
 	tty_encode_baud_rate(tty, speed, speed);
 	if (tty->ops->set_termios)
 		tty->ops->set_termios(tty, &old_termios);
 	priv->io.speed = speed;
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 
 	return 0;
 }
@@ -280,7 +280,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
 	struct ktermios old_termios;
 	int cflag;
 
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	old_termios = tty->termios;
 	cflag = tty->termios.c_cflag;
 	
@@ -292,7 +292,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
 	tty->termios.c_cflag = cflag;
 	if (tty->ops->set_termios)
 		tty->ops->set_termios(tty, &old_termios);
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 }
 
 /*****************************************************************/
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d0f9c2f..510a9b6 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -600,6 +600,9 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	if (!vlan->port->passthru)
 		return -EOPNOTSUPP;
 
+	if (flags & NLM_F_REPLACE)
+		return -EOPNOTSUPP;
+
 	if (is_unicast_ether_addr(addr))
 		err = dev_uc_add_excl(dev, addr);
 	else if (is_multicast_ether_addr(addr))
@@ -739,6 +742,10 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
 			return -EADDRNOTAVAIL;
 	}
 
+	if (data && data[IFLA_MACVLAN_FLAGS] &&
+	    nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~MACVLAN_FLAG_NOPROMISC)
+		return -EINVAL;
+
 	if (data && data[IFLA_MACVLAN_MODE]) {
 		switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) {
 		case MACVLAN_MODE_PRIVATE:
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index a98fb0e..182364a 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -536,86 +536,6 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
 	return skb;
 }
 
-/* set skb frags from iovec, this can move to core network code for reuse */
-static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
-				  int offset, size_t count)
-{
-	int len = iov_length(from, count) - offset;
-	int copy = skb_headlen(skb);
-	int size, offset1 = 0;
-	int i = 0;
-
-	/* Skip over from offset */
-	while (count && (offset >= from->iov_len)) {
-		offset -= from->iov_len;
-		++from;
-		--count;
-	}
-
-	/* copy up to skb headlen */
-	while (count && (copy > 0)) {
-		size = min_t(unsigned int, copy, from->iov_len - offset);
-		if (copy_from_user(skb->data + offset1, from->iov_base + offset,
-				   size))
-			return -EFAULT;
-		if (copy > size) {
-			++from;
-			--count;
-			offset = 0;
-		} else
-			offset += size;
-		copy -= size;
-		offset1 += size;
-	}
-
-	if (len == offset1)
-		return 0;
-
-	while (count--) {
-		struct page *page[MAX_SKB_FRAGS];
-		int num_pages;
-		unsigned long base;
-		unsigned long truesize;
-
-		len = from->iov_len - offset;
-		if (!len) {
-			offset = 0;
-			++from;
-			continue;
-		}
-		base = (unsigned long)from->iov_base + offset;
-		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
-		if (i + size > MAX_SKB_FRAGS)
-			return -EMSGSIZE;
-		num_pages = get_user_pages_fast(base, size, 0, &page[i]);
-		if (num_pages != size) {
-			int j;
-
-			for (j = 0; j < num_pages; j++)
-				put_page(page[i + j]);
-			return -EFAULT;
-		}
-		truesize = size * PAGE_SIZE;
-		skb->data_len += len;
-		skb->len += len;
-		skb->truesize += truesize;
-		atomic_add(truesize, &skb->sk->sk_wmem_alloc);
-		while (len) {
-			int off = base & ~PAGE_MASK;
-			int size = min_t(int, len, PAGE_SIZE - off);
-			__skb_fill_page_desc(skb, i, page[i], off, size);
-			skb_shinfo(skb)->nr_frags++;
-			/* increase sk_wmem_alloc */
-			base += size;
-			len -= size;
-			i++;
-		}
-		offset = 0;
-		++from;
-	}
-	return 0;
-}
-
 /*
  * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
  * be shared with the tun/tap driver.
@@ -698,29 +618,6 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
 	return 0;
 }
 
-static unsigned long iov_pages(const struct iovec *iv, int offset,
-			       unsigned long nr_segs)
-{
-	unsigned long seg, base;
-	int pages = 0, len, size;
-
-	while (nr_segs && (offset >= iv->iov_len)) {
-		offset -= iv->iov_len;
-		++iv;
-		--nr_segs;
-	}
-
-	for (seg = 0; seg < nr_segs; seg++) {
-		base = (unsigned long)iv[seg].iov_base + offset;
-		len = iv[seg].iov_len - offset;
-		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
-		pages += size;
-		offset = 0;
-	}
-
-	return pages;
-}
-
 /* Get packet from user space buffer */
 static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
 				const struct iovec *iv, unsigned long total_len,
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 4822aaf..2cf3ed8 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -757,7 +757,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 
 static struct console netconsole = {
 	.name	= "netcon",
-	.flags	= CON_ENABLED,
+	.flags	= CON_ENABLED | CON_ALLDATA,
 	.write	= write_msg,
 };
 
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 9733bd2..f8e305d 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -48,7 +48,7 @@ static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child,
 	struct mdio_mux_mmioreg_state *s = data;
 
 	if (current_child ^ desired_child) {
-		void *p = ioremap(s->phys, 1);
+		void __iomem *p = ioremap(s->phys, 1);
 		uint8_t x, y;
 
 		if (!p)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 2510435..9ca4945 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -144,7 +144,7 @@ static int ks8051_config_init(struct phy_device *phydev)
 #define KSZ8873MLL_GLOBAL_CONTROL_4	0x06
 #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX	(1 << 6)
 #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED	(1 << 4)
-int ksz8873mll_read_status(struct phy_device *phydev)
+static int ksz8873mll_read_status(struct phy_device *phydev)
 {
 	int regval;
 
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index bff7e0b..9ccccd4 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -622,6 +622,86 @@ static int team_change_mode(struct team *team, const char *kind)
 }
 
 
+/*********************
+ * Peers notification
+ *********************/
+
+static void team_notify_peers_work(struct work_struct *work)
+{
+	struct team *team;
+
+	team = container_of(work, struct team, notify_peers.dw.work);
+
+	if (!rtnl_trylock()) {
+		schedule_delayed_work(&team->notify_peers.dw, 0);
+		return;
+	}
+	call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, team->dev);
+	rtnl_unlock();
+	if (!atomic_dec_and_test(&team->notify_peers.count_pending))
+		schedule_delayed_work(&team->notify_peers.dw,
+				      msecs_to_jiffies(team->notify_peers.interval));
+}
+
+static void team_notify_peers(struct team *team)
+{
+	if (!team->notify_peers.count || !netif_running(team->dev))
+		return;
+	atomic_set(&team->notify_peers.count_pending, team->notify_peers.count);
+	schedule_delayed_work(&team->notify_peers.dw, 0);
+}
+
+static void team_notify_peers_init(struct team *team)
+{
+	INIT_DELAYED_WORK(&team->notify_peers.dw, team_notify_peers_work);
+}
+
+static void team_notify_peers_fini(struct team *team)
+{
+	cancel_delayed_work_sync(&team->notify_peers.dw);
+}
+
+
+/*******************************
+ * Send multicast group rejoins
+ *******************************/
+
+static void team_mcast_rejoin_work(struct work_struct *work)
+{
+	struct team *team;
+
+	team = container_of(work, struct team, mcast_rejoin.dw.work);
+
+	if (!rtnl_trylock()) {
+		schedule_delayed_work(&team->mcast_rejoin.dw, 0);
+		return;
+	}
+	call_netdevice_notifiers(NETDEV_RESEND_IGMP, team->dev);
+	rtnl_unlock();
+	if (!atomic_dec_and_test(&team->mcast_rejoin.count_pending))
+		schedule_delayed_work(&team->mcast_rejoin.dw,
+				      msecs_to_jiffies(team->mcast_rejoin.interval));
+}
+
+static void team_mcast_rejoin(struct team *team)
+{
+	if (!team->mcast_rejoin.count || !netif_running(team->dev))
+		return;
+	atomic_set(&team->mcast_rejoin.count_pending, team->mcast_rejoin.count);
+	schedule_delayed_work(&team->mcast_rejoin.dw, 0);
+}
+
+static void team_mcast_rejoin_init(struct team *team)
+{
+	INIT_DELAYED_WORK(&team->mcast_rejoin.dw, team_mcast_rejoin_work);
+}
+
+static void team_mcast_rejoin_fini(struct team *team)
+{
+	cancel_delayed_work_sync(&team->mcast_rejoin.dw);
+}
+
+
 /************************
  * Rx path frame handler
  ************************/
@@ -846,6 +926,8 @@ static void team_port_enable(struct team *team,
 	team_queue_override_port_add(team, port);
 	if (team->ops.port_enabled)
 		team->ops.port_enabled(team, port);
+	team_notify_peers(team);
+	team_mcast_rejoin(team);
 }
 
 static void __reconstruct_port_hlist(struct team *team, int rm_index)
@@ -875,6 +957,8 @@ static void team_port_disable(struct team *team,
 	team->en_port_count--;
 	team_queue_override_port_del(team, port);
 	team_adjust_ops(team);
+	team_notify_peers(team);
+	team_mcast_rejoin(team);
 }
 
 #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
@@ -953,6 +1037,9 @@ static int team_port_enable_netpoll(struct team *team, struct team_port *port,
 	struct netpoll *np;
 	int err;
 
+	if (!team->dev->npinfo)
+		return 0;
+
 	np = kzalloc(sizeof(*np), gfp);
 	if (!np)
 		return -ENOMEM;
@@ -979,12 +1066,6 @@ static void team_port_disable_netpoll(struct team_port *port)
 	__netpoll_cleanup(np);
 	kfree(np);
 }
-
-static struct netpoll_info *team_netpoll_info(struct team *team)
-{
-	return team->dev->npinfo;
-}
-
 #else
 static int team_port_enable_netpoll(struct team *team, struct team_port *port,
 				    gfp_t gfp)
@@ -994,10 +1075,6 @@ static int team_port_enable_netpoll(struct team *team, struct team_port *port,
 static void team_port_disable_netpoll(struct team_port *port)
 {
 }
-static struct netpoll_info *team_netpoll_info(struct team *team)
-{
-	return NULL;
-}
 #endif
 
 static void __team_port_change_port_added(struct team_port *port, bool linkup);
@@ -1079,13 +1156,11 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
 		goto err_vids_add;
 	}
 
-	if (team_netpoll_info(team)) {
-		err = team_port_enable_netpoll(team, port, GFP_KERNEL);
-		if (err) {
-			netdev_err(dev, "Failed to enable netpoll on device %s\n",
-				   portname);
-			goto err_enable_netpoll;
-		}
+	err = team_port_enable_netpoll(team, port, GFP_KERNEL);
+	if (err) {
+		netdev_err(dev, "Failed to enable netpoll on device %s\n",
+			   portname);
+		goto err_enable_netpoll;
 	}
 
 	err = netdev_master_upper_dev_link(port_dev, dev);
@@ -1205,6 +1280,62 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx)
 	return team_change_mode(team, ctx->data.str_val);
 }
 
+static int team_notify_peers_count_get(struct team *team,
+				       struct team_gsetter_ctx *ctx)
+{
+	ctx->data.u32_val = team->notify_peers.count;
+	return 0;
+}
+
+static int team_notify_peers_count_set(struct team *team,
+				       struct team_gsetter_ctx *ctx)
+{
+	team->notify_peers.count = ctx->data.u32_val;
+	return 0;
+}
+
+static int team_notify_peers_interval_get(struct team *team,
+					  struct team_gsetter_ctx *ctx)
+{
+	ctx->data.u32_val = team->notify_peers.interval;
+	return 0;
+}
+
+static int team_notify_peers_interval_set(struct team *team,
+					  struct team_gsetter_ctx *ctx)
+{
+	team->notify_peers.interval = ctx->data.u32_val;
+	return 0;
+}
+
+static int team_mcast_rejoin_count_get(struct team *team,
+				       struct team_gsetter_ctx *ctx)
+{
+	ctx->data.u32_val = team->mcast_rejoin.count;
+	return 0;
+}
+
+static int team_mcast_rejoin_count_set(struct team *team,
+				       struct team_gsetter_ctx *ctx)
+{
+	team->mcast_rejoin.count = ctx->data.u32_val;
+	return 0;
+}
+
+static int team_mcast_rejoin_interval_get(struct team *team,
+					  struct team_gsetter_ctx *ctx)
+{
+	ctx->data.u32_val = team->mcast_rejoin.interval;
+	return 0;
+}
+
+static int team_mcast_rejoin_interval_set(struct team *team,
+					  struct team_gsetter_ctx *ctx)
+{
+	team->mcast_rejoin.interval = ctx->data.u32_val;
+	return 0;
+}
+
 static int team_port_en_option_get(struct team *team,
 				   struct team_gsetter_ctx *ctx)
 {
@@ -1317,6 +1448,30 @@ static const struct team_option team_options[] = {
 		.setter = team_mode_option_set,
 	},
 	{
+		.name = "notify_peers_count",
+		.type = TEAM_OPTION_TYPE_U32,
+		.getter = team_notify_peers_count_get,
+		.setter = team_notify_peers_count_set,
+	},
+	{
+		.name = "notify_peers_interval",
+		.type = TEAM_OPTION_TYPE_U32,
+		.getter = team_notify_peers_interval_get,
+		.setter = team_notify_peers_interval_set,
+	},
+	{
+		.name = "mcast_rejoin_count",
+		.type = TEAM_OPTION_TYPE_U32,
+		.getter = team_mcast_rejoin_count_get,
+		.setter = team_mcast_rejoin_count_set,
+	},
+	{
+		.name = "mcast_rejoin_interval",
+		.type = TEAM_OPTION_TYPE_U32,
+		.getter = team_mcast_rejoin_interval_get,
+		.setter = team_mcast_rejoin_interval_set,
+	},
+	{
 		.name = "enabled",
 		.type = TEAM_OPTION_TYPE_BOOL,
 		.per_port = true,
@@ -1396,6 +1551,10 @@ static int team_init(struct net_device *dev)
 
 	INIT_LIST_HEAD(&team->option_list);
 	INIT_LIST_HEAD(&team->option_inst_list);
+
+	team_notify_peers_init(team);
+	team_mcast_rejoin_init(team);
+
 	err = team_options_register(team, team_options, ARRAY_SIZE(team_options));
 	if (err)
 		goto err_options_register;
@@ -1406,6 +1565,8 @@ static int team_init(struct net_device *dev)
 	return 0;
 
 err_options_register:
+	team_mcast_rejoin_fini(team);
+	team_notify_peers_fini(team);
 	team_queue_override_fini(team);
 err_team_queue_override_init:
 	free_percpu(team->pcpu_stats);
@@ -1425,6 +1586,8 @@ static void team_uninit(struct net_device *dev)
 
 	__team_change_mode(team, NULL); /* cleanup */
 	__team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
+	team_mcast_rejoin_fini(team);
+	team_notify_peers_fini(team);
 	team_queue_override_fini(team);
 	mutex_unlock(&team->lock);
 }
@@ -2698,6 +2861,10 @@ static int team_device_event(struct notifier_block *unused,
 	case NETDEV_PRE_TYPE_CHANGE:
 		/* Forbid to change type of underlaying device */
 		return NOTIFY_BAD;
+	case NETDEV_RESEND_IGMP:
+		/* Propagate to master device */
+		call_netdevice_notifiers(event, port->team->dev);
+		break;
 	}
 	return NOTIFY_DONE;
 }
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index db690a3..b163047 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -60,6 +60,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_tun.h>
+#include <linux/if_vlan.h>
 #include <linux/crc32.h>
 #include <linux/nsproxy.h>
 #include <linux/virtio_net.h>
@@ -739,6 +740,11 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 			  >= dev->tx_queue_len / tun->numqueues)
 		goto drop;
 
+	if (skb->sk) {
+		sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags);
+		sw_tx_timestamp(skb);
+	}
+
 	/* Orphan the skb - required as we might hang on to it
 	 * for indefinite time. */
 	if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
@@ -955,109 +961,6 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
 	return skb;
 }
 
-/* set skb frags from iovec, this can move to core network code for reuse */
-static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
-				  int offset, size_t count)
-{
-	int len = iov_length(from, count) - offset;
-	int copy = skb_headlen(skb);
-	int size, offset1 = 0;
-	int i = 0;
-
-	/* Skip over from offset */
-	while (count && (offset >= from->iov_len)) {
-		offset -= from->iov_len;
-		++from;
-		--count;
-	}
-
-	/* copy up to skb headlen */
-	while (count && (copy > 0)) {
-		size = min_t(unsigned int, copy, from->iov_len - offset);
-		if (copy_from_user(skb->data + offset1, from->iov_base + offset,
-				   size))
-			return -EFAULT;
-		if (copy > size) {
-			++from;
-			--count;
-			offset = 0;
-		} else
-			offset += size;
-		copy -= size;
-		offset1 += size;
-	}
-
-	if (len == offset1)
-		return 0;
-
-	while (count--) {
-		struct page *page[MAX_SKB_FRAGS];
-		int num_pages;
-		unsigned long base;
-		unsigned long truesize;
-
-		len = from->iov_len - offset;
-		if (!len) {
-			offset = 0;
-			++from;
-			continue;
-		}
-		base = (unsigned long)from->iov_base + offset;
-		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
-		if (i + size > MAX_SKB_FRAGS)
-			return -EMSGSIZE;
-		num_pages = get_user_pages_fast(base, size, 0, &page[i]);
-		if (num_pages != size) {
-			int j;
-
-			for (j = 0; j < num_pages; j++)
-				put_page(page[i + j]);
-			return -EFAULT;
-		}
-		truesize = size * PAGE_SIZE;
-		skb->data_len += len;
-		skb->len += len;
-		skb->truesize += truesize;
-		atomic_add(truesize, &skb->sk->sk_wmem_alloc);
-		while (len) {
-			int off = base & ~PAGE_MASK;
-			int size = min_t(int, len, PAGE_SIZE - off);
-			__skb_fill_page_desc(skb, i, page[i], off, size);
-			skb_shinfo(skb)->nr_frags++;
-			/* increase sk_wmem_alloc */
-			base += size;
-			len -= size;
-			i++;
-		}
-		offset = 0;
-		++from;
-	}
-	return 0;
-}
-
-static unsigned long iov_pages(const struct iovec *iv, int offset,
-			       unsigned long nr_segs)
-{
-	unsigned long seg, base;
-	int pages = 0, len, size;
-
-	while (nr_segs && (offset >= iv->iov_len)) {
-		offset -= iv->iov_len;
-		++iv;
-		--nr_segs;
-	}
-
-	for (seg = 0; seg < nr_segs; seg++) {
-		base = (unsigned long)iv[seg].iov_base + offset;
-		len = iv[seg].iov_len - offset;
-		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
-		pages += size;
-		offset = 0;
-	}
-
-	return pages;
-}
-
 /* Get packet from user space buffer */
 static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 			    void *msg_control, const struct iovec *iv,
@@ -1260,6 +1163,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 {
 	struct tun_pi pi = { 0, skb->protocol };
 	ssize_t total = 0;
+	int vlan_offset = 0;
 
 	if (!(tun->flags & TUN_NO_PI)) {
 		if ((len -= sizeof(pi)) < 0)
@@ -1323,11 +1227,40 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 		total += tun->vnet_hdr_sz;
 	}
 
-	len = min_t(int, skb->len, len);
+	if (!vlan_tx_tag_present(skb)) {
+		len = min_t(int, skb->len, len);
+	} else {
+		int copy, ret;
+		struct {
+			__be16 h_vlan_proto;
+			__be16 h_vlan_TCI;
+		} veth;
+
+		veth.h_vlan_proto = skb->vlan_proto;
+		veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
+
+		vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
+		len = min_t(int, skb->len + VLAN_HLEN, len);
+
+		copy = min_t(int, vlan_offset, len);
+		ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
+		len -= copy;
+		total += copy;
+		if (ret || !len)
+			goto done;
+
+		copy = min_t(int, sizeof(veth), len);
+		ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
+		len -= copy;
+		total += copy;
+		if (ret || !len)
+			goto done;
+	}
 
-	skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
-	total += skb->len;
+	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
+	total += len;
 
+done:
 	tun->dev->stats.tx_packets++;
 	tun->dev->stats.tx_bytes += len;
 
@@ -1476,7 +1409,6 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
 	return ret;
 }
 
-
 static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *m, size_t total_len,
 		       int flags)
@@ -1488,10 +1420,15 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
 	if (!tun)
 		return -EBADFD;
 
-	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) {
+	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) {
 		ret = -EINVAL;
 		goto out;
 	}
+	if (flags & MSG_ERRQUEUE) {
+		ret = sock_recv_errqueue(sock->sk, m, total_len,
+					 SOL_PACKET, TUN_TX_TIMESTAMP);
+		goto out;
+	}
 	ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len,
 			  flags & MSG_DONTWAIT);
 	if (ret > total_len) {
@@ -1682,7 +1619,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		tun_flow_init(tun);
 
 		dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
-			TUN_USER_FEATURES;
+				   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
+				   NETIF_F_HW_VLAN_STAG_TX;
 		dev->features = dev->hw_features;
 		dev->vlan_features = dev->features;
 
@@ -2274,6 +2212,7 @@ static const struct ethtool_ops tun_ethtool_ops = {
 	.get_msglevel	= tun_get_msglevel,
 	.set_msglevel	= tun_set_msglevel,
 	.get_link	= ethtool_op_get_link,
+	.get_ts_info	= ethtool_op_get_ts_info,
 };
 
 
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index ad5d1e4..b96ad4f 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -778,6 +778,9 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu)
 	dev->hard_mtu = net->mtu + net->hard_header_len;
 	ax88178_set_mfb(dev);
 
+	/* max qlen depend on hard_mtu and rx_urb_size */
+	usbnet_update_max_qlen(dev);
+
 	return 0;
 }
 
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 2bc87e3..fb0caa2 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -688,6 +688,9 @@ static int ax88179_change_mtu(struct net_device *net, int new_mtu)
 				  2, 2, &tmp16);
 	}
 
+	/* max qlen depend on hard_mtu and rx_urb_size */
+	usbnet_update_max_qlen(dev);
+
 	return 0;
 }
 
@@ -1166,31 +1169,18 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 	int frame_size = dev->maxpacket;
 	int mss = skb_shinfo(skb)->gso_size;
 	int headroom;
-	int tailroom;
 
 	tx_hdr1 = skb->len;
 	tx_hdr2 = mss;
 	if (((skb->len + 8) % frame_size) == 0)
 		tx_hdr2 |= 0x80008000;	/* Enable padding */
 
-	headroom = skb_headroom(skb);
-	tailroom = skb_tailroom(skb);
-
-	if (!skb_header_cloned(skb) &&
-	    !skb_cloned(skb) &&
-	    (headroom + tailroom) >= 8) {
-		if (headroom < 8) {
-			skb->data = memmove(skb->head + 8, skb->data, skb->len);
-			skb_set_tail_pointer(skb, skb->len);
-		}
-	} else {
-		struct sk_buff *skb2;
+	headroom = skb_headroom(skb) - 8;
 
-		skb2 = skb_copy_expand(skb, 8, 0, flags);
+	if ((skb_header_cloned(skb) || headroom < 0) &&
+	    pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) {
 		dev_kfree_skb_any(skb);
-		skb = skb2;
-		if (!skb)
-			return NULL;
+		return NULL;
 	}
 
 	skb_push(skb, 4);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 06ee82f..e4811d7 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -59,15 +59,13 @@
  * For high speed, each frame comfortably fits almost 36 max size
  * Ethernet packets (so queues should be bigger).
  *
- * REVISIT qlens should be members of 'struct usbnet'; the goal is to
- * let the USB host controller be busy for 5msec or more before an irq
- * is required, under load.  Jumbograms change the equation.
+ * The goal is to let the USB host controller be busy for 5msec or
+ * more before an irq is required, under load.  Jumbograms change
+ * the equation.
  */
-#define RX_MAX_QUEUE_MEMORY (60 * 1518)
-#define	RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
-			(RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
-#define	TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
-			(RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
+#define	MAX_QUEUE_MEMORY	(60 * 1518)
+#define	RX_QLEN(dev)		((dev)->rx_qlen)
+#define	TX_QLEN(dev)		((dev)->tx_qlen)
 
 // reawaken network queue this soon after stopping; else watchdog barks
 #define TX_TIMEOUT_JIFFIES	(5*HZ)
@@ -347,6 +345,31 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(usbnet_skb_return);
 
+/* must be called if hard_mtu or rx_urb_size changed */
+void usbnet_update_max_qlen(struct usbnet *dev)
+{
+	enum usb_device_speed speed = dev->udev->speed;
+
+	switch (speed) {
+	case USB_SPEED_HIGH:
+		dev->rx_qlen = MAX_QUEUE_MEMORY / dev->rx_urb_size;
+		dev->tx_qlen = MAX_QUEUE_MEMORY / dev->hard_mtu;
+		break;
+	case USB_SPEED_SUPER:
+		/*
+		 * Not take default 5ms qlen for super speed HC to
+		 * save memory, and iperf tests show 2.5ms qlen can
+		 * work well
+		 */
+		dev->rx_qlen = 5 * MAX_QUEUE_MEMORY / dev->rx_urb_size;
+		dev->tx_qlen = 5 * MAX_QUEUE_MEMORY / dev->hard_mtu;
+		break;
+	default:
+		dev->rx_qlen = dev->tx_qlen = 4;
+	}
+}
+EXPORT_SYMBOL_GPL(usbnet_update_max_qlen);
+
 
 /*-------------------------------------------------------------------------
  *
@@ -375,6 +398,9 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
 			usbnet_unlink_rx_urbs(dev);
 	}
 
+	/* max qlen depend on hard_mtu and rx_urb_size */
+	usbnet_update_max_qlen(dev);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_change_mtu);
@@ -843,6 +869,9 @@ int usbnet_open (struct net_device *net)
 		goto done;
 	}
 
+	/* hard_mtu or rx_urb_size may change in reset() */
+	usbnet_update_max_qlen(dev);
+
 	// insist peer be connected
 	if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
 		netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval);
@@ -927,6 +956,9 @@ int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd)
 	if (dev->driver_info->link_reset)
 		dev->driver_info->link_reset(dev);
 
+	/* hard_mtu or rx_urb_size may change in link_reset() */
+	usbnet_update_max_qlen(dev);
+
 	return retval;
 
 }
@@ -1020,6 +1052,9 @@ static void __handle_link_change(struct usbnet *dev)
 		tasklet_schedule(&dev->bh);
 	}
 
+	/* hard_mtu or rx_urb_size may change during link change */
+	usbnet_update_max_qlen(dev);
+
 	clear_bit(EVENT_LINK_CHANGE, &dev->flags);
 }
 
@@ -1599,6 +1634,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 	if ((dev->driver_info->flags & FLAG_WWAN) != 0)
 		SET_NETDEV_DEVTYPE(net, &wwan_type);
 
+	/* initialize max rx_qlen and tx_qlen */
+	usbnet_update_max_qlen(dev);
+
 	status = register_netdev (net);
 	if (status)
 		goto out4;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3d2a90a..f216002 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -106,6 +106,9 @@ struct virtnet_info {
 	/* Has control virtqueue */
 	bool has_cvq;
 
+	/* Host can handle any s/g split between our header and packet data */
+	bool any_header_sg;
+
 	/* enable config space updates */
 	bool config_enable;
 
@@ -669,12 +672,28 @@ static void free_old_xmit_skbs(struct send_queue *sq)
 
 static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 {
-	struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
+	struct skb_vnet_hdr *hdr;
 	const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
 	struct virtnet_info *vi = sq->vq->vdev->priv;
 	unsigned num_sg;
+	unsigned hdr_len;
+	bool can_push;
 
 	pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
+	if (vi->mergeable_rx_bufs)
+		hdr_len = sizeof hdr->mhdr;
+	else
+		hdr_len = sizeof hdr->hdr;
+
+	can_push = vi->any_header_sg &&
+		!((unsigned long)skb->data & (__alignof__(*hdr) - 1)) &&
+		!skb_header_cloned(skb) && skb_headroom(skb) >= hdr_len;
+	/* Even if we can, don't push here yet as this would skew
+	 * csum_start offset below. */
+	if (can_push)
+		hdr = (struct skb_vnet_hdr *)(skb->data - hdr_len);
+	else
+		hdr = skb_vnet_hdr(skb);
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
@@ -703,15 +722,18 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 		hdr->hdr.gso_size = hdr->hdr.hdr_len = 0;
 	}
 
-	hdr->mhdr.num_buffers = 0;
-
-	/* Encode metadata header at front. */
 	if (vi->mergeable_rx_bufs)
-		sg_set_buf(sq->sg, &hdr->mhdr, sizeof hdr->mhdr);
-	else
-		sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr);
+		hdr->mhdr.num_buffers = 0;
 
-	num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1;
+	if (can_push) {
+		__skb_push(skb, hdr_len);
+		num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len);
+		/* Pull header back to avoid skew in tx bytes calculations. */
+		__skb_pull(skb, hdr_len);
+	} else {
+		sg_set_buf(sq->sg, hdr, hdr_len);
+		num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1;
+	}
 	return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC);
 }
 
@@ -1552,6 +1574,9 @@ static int virtnet_probe(struct virtio_device *vdev)
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
 		vi->mergeable_rx_bufs = true;
 
+	if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT))
+		vi->any_header_sg = true;
+
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
 		vi->has_cvq = true;
 
@@ -1727,6 +1752,7 @@ static unsigned int features[] = {
 	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
 	VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
 	VIRTIO_NET_F_CTRL_MAC_ADDR,
+	VIRTIO_F_ANY_LAYOUT,
 };
 
 static struct virtio_driver virtio_net_driver = {
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index f4c6db4..8bf31d9 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -177,9 +177,14 @@ static inline struct hlist_head *vs_head(struct net *net, __be16 port)
 /* First remote destination for a forwarding entry.
  * Guaranteed to be non-NULL because remotes are never deleted.
  */
-static inline struct vxlan_rdst *first_remote(struct vxlan_fdb *fdb)
+static inline struct vxlan_rdst *first_remote_rcu(struct vxlan_fdb *fdb)
 {
-	return list_first_or_null_rcu(&fdb->remotes, struct vxlan_rdst, list);
+	return list_entry_rcu(fdb->remotes.next, struct vxlan_rdst, list);
+}
+
+static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
+{
+	return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
 }
 
 /* Find VXLAN socket based on network namespace and UDP port */
@@ -297,7 +302,8 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan,
 	if (skb == NULL)
 		goto errout;
 
-	err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, first_remote(fdb));
+	err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0,
+			     first_remote_rtnl(fdb));
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
@@ -408,6 +414,26 @@ static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f,
 	return NULL;
 }
 
+/* Replace destination of unicast mac */
+static int vxlan_fdb_replace(struct vxlan_fdb *f,
+			    __be32 ip, __be16 port, __u32 vni, __u32 ifindex)
+{
+	struct vxlan_rdst *rd;
+
+	rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex);
+	if (rd)
+		return 0;
+
+	rd = list_first_entry_or_null(&f->remotes, struct vxlan_rdst, list);
+	if (!rd)
+		return 0;
+	rd->remote_ip = ip;
+	rd->remote_port = port;
+	rd->remote_vni = vni;
+	rd->remote_ifindex = ifindex;
+	return 1;
+}
+
 /* Add/update destinations for multicast */
 static int vxlan_fdb_append(struct vxlan_fdb *f,
 			    __be32 ip, __be16 port, __u32 vni, __u32 ifindex)
@@ -458,6 +484,19 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 			f->updated = jiffies;
 			notify = 1;
 		}
+		if ((flags & NLM_F_REPLACE)) {
+			/* Only change unicasts */
+			if (!(is_multicast_ether_addr(f->eth_addr) ||
+			     is_zero_ether_addr(f->eth_addr))) {
+				int rc = vxlan_fdb_replace(f, ip, port, vni,
+							   ifindex);
+
+				if (rc < 0)
+					return rc;
+				notify |= rc;
+			} else
+				return -EOPNOTSUPP;
+		}
 		if ((flags & NLM_F_APPEND) &&
 		    (is_multicast_ether_addr(f->eth_addr) ||
 		     is_zero_ether_addr(f->eth_addr))) {
@@ -474,6 +513,11 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 		if (vxlan->addrmax && vxlan->addrcnt >= vxlan->addrmax)
 			return -ENOSPC;
 
+		/* Disallow replace to add a multicast entry */
+		if ((flags & NLM_F_REPLACE) &&
+		    (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
+			return -EOPNOTSUPP;
+
 		netdev_dbg(vxlan->dev, "add %pM -> %pI4\n", mac, &ip);
 		f = kmalloc(sizeof(*f), GFP_ATOMIC);
 		if (!f)
@@ -702,7 +746,7 @@ static bool vxlan_snoop(struct net_device *dev,
 
 	f = vxlan_find_mac(vxlan, src_mac);
 	if (likely(f)) {
-		struct vxlan_rdst *rdst = first_remote(f);
+		struct vxlan_rdst *rdst = first_remote_rcu(f);
 
 		if (likely(rdst->remote_ip == src_ip))
 			return false;
@@ -967,7 +1011,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 		}
 
 		f = vxlan_find_mac(vxlan, n->ha);
-		if (f && first_remote(f)->remote_ip == htonl(INADDR_ANY)) {
+		if (f && first_remote_rcu(f)->remote_ip == htonl(INADDR_ANY)) {
 			/* bridge-local neighbor */
 			neigh_release(n);
 			goto out;
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index daeafef..e0ba7cd 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -159,7 +159,7 @@ struct ath_common {
 
 	bool btcoex_enabled;
 	bool disable_ani;
-	bool antenna_diversity;
+	bool bt_ant_diversity;
 };
 
 struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index 1a2ef51..744da6d 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -20,6 +20,12 @@
 #include "debug.h"
 #include "htc.h"
 
+void ath10k_bmi_start(struct ath10k *ar)
+{
+	ath10k_dbg(ATH10K_DBG_CORE, "BMI started\n");
+	ar->bmi.done_sent = false;
+}
+
 int ath10k_bmi_done(struct ath10k *ar)
 {
 	struct bmi_cmd cmd;
@@ -105,7 +111,8 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
 		ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen,
 						  &resp, &rxlen);
 		if (ret) {
-			ath10k_warn("unable to read from the device\n");
+			ath10k_warn("unable to read from the device (%d)\n",
+				    ret);
 			return ret;
 		}
 
@@ -149,7 +156,8 @@ int ath10k_bmi_write_memory(struct ath10k *ar,
 		ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
 						  NULL, NULL);
 		if (ret) {
-			ath10k_warn("unable to write to the device\n");
+			ath10k_warn("unable to write to the device (%d)\n",
+				    ret);
 			return ret;
 		}
 
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 32c56aa..8d81ce1 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -184,6 +184,7 @@ struct bmi_target_info {
 #define BMI_CE_NUM_TO_TARG 0
 #define BMI_CE_NUM_TO_HOST 1
 
+void ath10k_bmi_start(struct ath10k *ar);
 int ath10k_bmi_done(struct ath10k *ar);
 int ath10k_bmi_get_target_info(struct ath10k *ar,
 			       struct bmi_target_info *target_info);
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 61a8ac7..b407929 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -79,7 +79,7 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	void __iomem *indicator_addr;
 
-	if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) {
+	if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) {
 		ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
 		return;
 	}
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 2b3426b..7226c23 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -100,7 +100,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar)
 		goto conn_fail;
 
 	/* Start HTC */
-	status = ath10k_htc_start(ar->htc);
+	status = ath10k_htc_start(&ar->htc);
 	if (status)
 		goto conn_fail;
 
@@ -116,7 +116,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar)
 	return 0;
 
 timeout:
-	ath10k_htc_stop(ar->htc);
+	ath10k_htc_stop(&ar->htc);
 conn_fail:
 	return status;
 }
@@ -247,19 +247,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar,
 
 static int ath10k_download_board_data(struct ath10k *ar)
 {
+	const struct firmware *fw = ar->board_data;
 	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
 	u32 address;
-	const struct firmware *fw;
 	int ret;
 
-	fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
-				  ar->hw_params.fw.board);
-	if (IS_ERR(fw)) {
-		ath10k_err("could not fetch board data fw file (%ld)\n",
-			   PTR_ERR(fw));
-		return PTR_ERR(fw);
-	}
-
 	ret = ath10k_push_board_ext_data(ar, fw);
 	if (ret) {
 		ath10k_err("could not push board ext data (%d)\n", ret);
@@ -286,32 +278,20 @@ static int ath10k_download_board_data(struct ath10k *ar)
 	}
 
 exit:
-	release_firmware(fw);
 	return ret;
 }
 
 static int ath10k_download_and_run_otp(struct ath10k *ar)
 {
-	const struct firmware *fw;
-	u32 address;
+	const struct firmware *fw = ar->otp;
+	u32 address = ar->hw_params.patch_load_addr;
 	u32 exec_param;
 	int ret;
 
 	/* OTP is optional */
 
-	if (ar->hw_params.fw.otp == NULL) {
-		ath10k_info("otp file not defined\n");
-		return 0;
-	}
-
-	address = ar->hw_params.patch_load_addr;
-
-	fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
-				  ar->hw_params.fw.otp);
-	if (IS_ERR(fw)) {
-		ath10k_warn("could not fetch otp (%ld)\n", PTR_ERR(fw));
+	if (!ar->otp)
 		return 0;
-	}
 
 	ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size);
 	if (ret) {
@@ -327,28 +307,17 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
 	}
 
 exit:
-	release_firmware(fw);
 	return ret;
 }
 
 static int ath10k_download_fw(struct ath10k *ar)
 {
-	const struct firmware *fw;
+	const struct firmware *fw = ar->firmware;
 	u32 address;
 	int ret;
 
-	if (ar->hw_params.fw.fw == NULL)
-		return -EINVAL;
-
 	address = ar->hw_params.patch_load_addr;
 
-	fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
-				  ar->hw_params.fw.fw);
-	if (IS_ERR(fw)) {
-		ath10k_err("could not fetch fw (%ld)\n", PTR_ERR(fw));
-		return PTR_ERR(fw);
-	}
-
 	ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size);
 	if (ret) {
 		ath10k_err("could not write fw (%d)\n", ret);
@@ -356,7 +325,74 @@ static int ath10k_download_fw(struct ath10k *ar)
 	}
 
 exit:
-	release_firmware(fw);
+	return ret;
+}
+
+static void ath10k_core_free_firmware_files(struct ath10k *ar)
+{
+	if (ar->board_data && !IS_ERR(ar->board_data))
+		release_firmware(ar->board_data);
+
+	if (ar->otp && !IS_ERR(ar->otp))
+		release_firmware(ar->otp);
+
+	if (ar->firmware && !IS_ERR(ar->firmware))
+		release_firmware(ar->firmware);
+
+	ar->board_data = NULL;
+	ar->otp = NULL;
+	ar->firmware = NULL;
+}
+
+static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
+{
+	int ret = 0;
+
+	if (ar->hw_params.fw.fw == NULL) {
+		ath10k_err("firmware file not defined\n");
+		return -EINVAL;
+	}
+
+	if (ar->hw_params.fw.board == NULL) {
+		ath10k_err("board data file not defined");
+		return -EINVAL;
+	}
+
+	ar->board_data = ath10k_fetch_fw_file(ar,
+					      ar->hw_params.fw.dir,
+					      ar->hw_params.fw.board);
+	if (IS_ERR(ar->board_data)) {
+		ret = PTR_ERR(ar->board_data);
+		ath10k_err("could not fetch board data (%d)\n", ret);
+		goto err;
+	}
+
+	ar->firmware = ath10k_fetch_fw_file(ar,
+					    ar->hw_params.fw.dir,
+					    ar->hw_params.fw.fw);
+	if (IS_ERR(ar->firmware)) {
+		ret = PTR_ERR(ar->firmware);
+		ath10k_err("could not fetch firmware (%d)\n", ret);
+		goto err;
+	}
+
+	/* OTP may be undefined. If so, don't fetch it at all */
+	if (ar->hw_params.fw.otp == NULL)
+		return 0;
+
+	ar->otp = ath10k_fetch_fw_file(ar,
+				       ar->hw_params.fw.dir,
+				       ar->hw_params.fw.otp);
+	if (IS_ERR(ar->otp)) {
+		ret = PTR_ERR(ar->otp);
+		ath10k_err("could not fetch otp (%d)\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	ath10k_core_free_firmware_files(ar);
 	return ret;
 }
 
@@ -440,8 +476,35 @@ static int ath10k_init_hw_params(struct ath10k *ar)
 	return 0;
 }
 
+static void ath10k_core_restart(struct work_struct *work)
+{
+	struct ath10k *ar = container_of(work, struct ath10k, restart_work);
+
+	mutex_lock(&ar->conf_mutex);
+
+	switch (ar->state) {
+	case ATH10K_STATE_ON:
+		ath10k_halt(ar);
+		ar->state = ATH10K_STATE_RESTARTING;
+		ieee80211_restart_hw(ar->hw);
+		break;
+	case ATH10K_STATE_OFF:
+		/* this can happen if driver is being unloaded */
+		ath10k_warn("cannot restart a device that hasn't been started\n");
+		break;
+	case ATH10K_STATE_RESTARTING:
+	case ATH10K_STATE_RESTARTED:
+		ar->state = ATH10K_STATE_WEDGED;
+		/* fall through */
+	case ATH10K_STATE_WEDGED:
+		ath10k_warn("device is wedged, will not restart\n");
+		break;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+}
+
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
-				  enum ath10k_bus bus,
 				  const struct ath10k_hif_ops *hif_ops)
 {
 	struct ath10k *ar;
@@ -458,9 +521,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 
 	ar->hif.priv = hif_priv;
 	ar->hif.ops = hif_ops;
-	ar->hif.bus = bus;
-
-	ar->free_vdev_map = 0xFF; /* 8 vdevs */
 
 	init_completion(&ar->scan.started);
 	init_completion(&ar->scan.completed);
@@ -487,6 +547,8 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 
 	init_waitqueue_head(&ar->event_queue);
 
+	INIT_WORK(&ar->restart_work, ath10k_core_restart);
+
 	return ar;
 
 err_wq:
@@ -504,24 +566,11 @@ void ath10k_core_destroy(struct ath10k *ar)
 }
 EXPORT_SYMBOL(ath10k_core_destroy);
 
-
-int ath10k_core_register(struct ath10k *ar)
+int ath10k_core_start(struct ath10k *ar)
 {
-	struct ath10k_htc_ops htc_ops;
-	struct bmi_target_info target_info;
 	int status;
 
-	memset(&target_info, 0, sizeof(target_info));
-	status = ath10k_bmi_get_target_info(ar, &target_info);
-	if (status)
-		goto err;
-
-	ar->target_version = target_info.version;
-	ar->hw->wiphy->hw_version = target_info.version;
-
-	status = ath10k_init_hw_params(ar);
-	if (status)
-		goto err;
+	ath10k_bmi_start(ar);
 
 	if (ath10k_init_configure_target(ar)) {
 		status = -EINVAL;
@@ -536,32 +585,32 @@ int ath10k_core_register(struct ath10k *ar)
 	if (status)
 		goto err;
 
-	htc_ops.target_send_suspend_complete = ath10k_send_suspend_complete;
+	ar->htc.htc_ops.target_send_suspend_complete =
+		ath10k_send_suspend_complete;
 
-	ar->htc = ath10k_htc_create(ar, &htc_ops);
-	if (IS_ERR(ar->htc)) {
-		status = PTR_ERR(ar->htc);
-		ath10k_err("could not create HTC (%d)\n", status);
+	status = ath10k_htc_init(ar);
+	if (status) {
+		ath10k_err("could not init HTC (%d)\n", status);
 		goto err;
 	}
 
 	status = ath10k_bmi_done(ar);
 	if (status)
-		goto err_htc_destroy;
+		goto err;
 
 	status = ath10k_wmi_attach(ar);
 	if (status) {
 		ath10k_err("WMI attach failed: %d\n", status);
-		goto err_htc_destroy;
+		goto err;
 	}
 
-	status = ath10k_htc_wait_target(ar->htc);
+	status = ath10k_htc_wait_target(&ar->htc);
 	if (status)
 		goto err_wmi_detach;
 
-	ar->htt = ath10k_htt_attach(ar);
-	if (!ar->htt) {
-		status = -ENOMEM;
+	status = ath10k_htt_attach(ar);
+	if (status) {
+		ath10k_err("could not attach htt (%d)\n", status);
 		goto err_wmi_detach;
 	}
 
@@ -588,77 +637,127 @@ int ath10k_core_register(struct ath10k *ar)
 		goto err_disconnect_htc;
 	}
 
-	status = ath10k_htt_attach_target(ar->htt);
-	if (status)
-		goto err_disconnect_htc;
-
-	status = ath10k_mac_register(ar);
+	status = ath10k_htt_attach_target(&ar->htt);
 	if (status)
 		goto err_disconnect_htc;
 
-	status = ath10k_debug_create(ar);
-	if (status) {
-		ath10k_err("unable to initialize debugfs\n");
-		goto err_unregister_mac;
-	}
+	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
 
 	return 0;
 
-err_unregister_mac:
-	ath10k_mac_unregister(ar);
 err_disconnect_htc:
-	ath10k_htc_stop(ar->htc);
+	ath10k_htc_stop(&ar->htc);
 err_htt_detach:
-	ath10k_htt_detach(ar->htt);
+	ath10k_htt_detach(&ar->htt);
 err_wmi_detach:
 	ath10k_wmi_detach(ar);
-err_htc_destroy:
-	ath10k_htc_destroy(ar->htc);
 err:
 	return status;
 }
-EXPORT_SYMBOL(ath10k_core_register);
+EXPORT_SYMBOL(ath10k_core_start);
 
-void ath10k_core_unregister(struct ath10k *ar)
+void ath10k_core_stop(struct ath10k *ar)
 {
-	/* We must unregister from mac80211 before we stop HTC and HIF.
-	 * Otherwise we will fail to submit commands to FW and mac80211 will be
-	 * unhappy about callback failures. */
-	ath10k_mac_unregister(ar);
-	ath10k_htc_stop(ar->htc);
-	ath10k_htt_detach(ar->htt);
+	ath10k_htc_stop(&ar->htc);
+	ath10k_htt_detach(&ar->htt);
 	ath10k_wmi_detach(ar);
-	ath10k_htc_destroy(ar->htc);
 }
-EXPORT_SYMBOL(ath10k_core_unregister);
+EXPORT_SYMBOL(ath10k_core_stop);
 
-int ath10k_core_target_suspend(struct ath10k *ar)
+/* mac80211 manages fw/hw initialization through start/stop hooks. However in
+ * order to know what hw capabilities should be advertised to mac80211 it is
+ * necessary to load the firmware (and tear it down immediately since start
+ * hook will try to init it again) before registering */
+static int ath10k_core_probe_fw(struct ath10k *ar)
 {
-	int ret;
+	struct bmi_target_info target_info;
+	int ret = 0;
+
+	ret = ath10k_hif_power_up(ar);
+	if (ret) {
+		ath10k_err("could not start pci hif (%d)\n", ret);
+		return ret;
+	}
 
-	ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__);
+	memset(&target_info, 0, sizeof(target_info));
+	ret = ath10k_bmi_get_target_info(ar, &target_info);
+	if (ret) {
+		ath10k_err("could not get target info (%d)\n", ret);
+		ath10k_hif_power_down(ar);
+		return ret;
+	}
 
-	ret = ath10k_wmi_pdev_suspend_target(ar);
-	if (ret)
-		ath10k_warn("could not suspend target (%d)\n", ret);
+	ar->target_version = target_info.version;
+	ar->hw->wiphy->hw_version = target_info.version;
 
-	return ret;
+	ret = ath10k_init_hw_params(ar);
+	if (ret) {
+		ath10k_err("could not get hw params (%d)\n", ret);
+		ath10k_hif_power_down(ar);
+		return ret;
+	}
+
+	ret = ath10k_core_fetch_firmware_files(ar);
+	if (ret) {
+		ath10k_err("could not fetch firmware files (%d)\n", ret);
+		ath10k_hif_power_down(ar);
+		return ret;
+	}
+
+	ret = ath10k_core_start(ar);
+	if (ret) {
+		ath10k_err("could not init core (%d)\n", ret);
+		ath10k_core_free_firmware_files(ar);
+		ath10k_hif_power_down(ar);
+		return ret;
+	}
+
+	ath10k_core_stop(ar);
+	ath10k_hif_power_down(ar);
+	return 0;
 }
-EXPORT_SYMBOL(ath10k_core_target_suspend);
 
-int ath10k_core_target_resume(struct ath10k *ar)
+int ath10k_core_register(struct ath10k *ar)
 {
-	int ret;
+	int status;
 
-	ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__);
+	status = ath10k_core_probe_fw(ar);
+	if (status) {
+		ath10k_err("could not probe fw (%d)\n", status);
+		return status;
+	}
 
-	ret = ath10k_wmi_pdev_resume_target(ar);
-	if (ret)
-		ath10k_warn("could not resume target (%d)\n", ret);
+	status = ath10k_mac_register(ar);
+	if (status) {
+		ath10k_err("could not register to mac80211 (%d)\n", status);
+		goto err_release_fw;
+	}
 
-	return ret;
+	status = ath10k_debug_create(ar);
+	if (status) {
+		ath10k_err("unable to initialize debugfs\n");
+		goto err_unregister_mac;
+	}
+
+	return 0;
+
+err_unregister_mac:
+	ath10k_mac_unregister(ar);
+err_release_fw:
+	ath10k_core_free_firmware_files(ar);
+	return status;
+}
+EXPORT_SYMBOL(ath10k_core_register);
+
+void ath10k_core_unregister(struct ath10k *ar)
+{
+	/* We must unregister from mac80211 before we stop HTC and HIF.
+	 * Otherwise we will fail to submit commands to FW and mac80211 will be
+	 * unhappy about callback failures. */
+	ath10k_mac_unregister(ar);
+	ath10k_core_free_firmware_files(ar);
 }
-EXPORT_SYMBOL(ath10k_core_target_resume);
+EXPORT_SYMBOL(ath10k_core_unregister);
 
 MODULE_AUTHOR("Qualcomm Atheros");
 MODULE_DESCRIPTION("Core module for QCA988X PCIe devices.");
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 539336d..9f21ecb 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
+#include "htt.h"
 #include "htc.h"
 #include "hw.h"
 #include "targaddrs.h"
@@ -43,10 +44,6 @@
 
 struct ath10k;
 
-enum ath10k_bus {
-	ATH10K_BUS_PCI,
-};
-
 struct ath10k_skb_cb {
 	dma_addr_t paddr;
 	bool is_mapped;
@@ -250,6 +247,28 @@ struct ath10k_debug {
 	struct completion event_stats_compl;
 };
 
+enum ath10k_state {
+	ATH10K_STATE_OFF = 0,
+	ATH10K_STATE_ON,
+
+	/* When doing firmware recovery the device is first powered down.
+	 * mac80211 is supposed to call in to start() hook later on. It is
+	 * however possible that driver unloading and firmware crash overlap.
+	 * mac80211 can wait on conf_mutex in stop() while the device is
+	 * stopped in ath10k_core_restart() work holding conf_mutex. The state
+	 * RESTARTED means that the device is up and mac80211 has started hw
+	 * reconfiguration. Once mac80211 is done with the reconfiguration we
+	 * set the state to STATE_ON in restart_complete(). */
+	ATH10K_STATE_RESTARTING,
+	ATH10K_STATE_RESTARTED,
+
+	/* The device has crashed while restarting hw. This state is like ON
+	 * but commands are blocked in HTC and -ECOMM response is given. This
+	 * prevents completion timeouts and makes the driver more responsive to
+	 * userspace commands. This is also prevents recursive recovery. */
+	ATH10K_STATE_WEDGED,
+};
+
 struct ath10k {
 	struct ath_common ath_common;
 	struct ieee80211_hw *hw;
@@ -274,19 +293,16 @@ struct ath10k {
 
 	struct {
 		void *priv;
-		enum ath10k_bus bus;
 		const struct ath10k_hif_ops *ops;
 	} hif;
 
-	struct ath10k_wmi wmi;
-
 	wait_queue_head_t event_queue;
 	bool is_target_paused;
 
 	struct ath10k_bmi bmi;
-
-	struct ath10k_htc *htc;
-	struct ath10k_htt *htt;
+	struct ath10k_wmi wmi;
+	struct ath10k_htc htc;
+	struct ath10k_htt htt;
 
 	struct ath10k_hw_params {
 		u32 id;
@@ -301,6 +317,10 @@ struct ath10k {
 		} fw;
 	} hw_params;
 
+	const struct firmware *board_data;
+	const struct firmware *otp;
+	const struct firmware *firmware;
+
 	struct {
 		struct completion started;
 		struct completion completed;
@@ -350,20 +370,22 @@ struct ath10k {
 	struct completion offchan_tx_completed;
 	struct sk_buff *offchan_tx_skb;
 
+	enum ath10k_state state;
+
+	struct work_struct restart_work;
+
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
-				  enum ath10k_bus bus,
 				  const struct ath10k_hif_ops *hif_ops);
 void ath10k_core_destroy(struct ath10k *ar);
 
+int ath10k_core_start(struct ath10k *ar);
+void ath10k_core_stop(struct ath10k *ar);
 int ath10k_core_register(struct ath10k *ar);
 void ath10k_core_unregister(struct ath10k *ar);
 
-int ath10k_core_target_suspend(struct ath10k *ar);
-int ath10k_core_target_resume(struct ath10k *ar);
-
 #endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 499034b..3d65594 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -161,7 +161,7 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
 	struct wmi_pdev_stats *ps;
 	int i;
 
-	mutex_lock(&ar->conf_mutex);
+	spin_lock_bh(&ar->data_lock);
 
 	stats = &ar->debug.target_stats;
 
@@ -259,6 +259,7 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
 		}
 	}
 
+	spin_unlock_bh(&ar->data_lock);
 	mutex_unlock(&ar->conf_mutex);
 	complete(&ar->debug.event_stats_compl);
 }
@@ -268,35 +269,35 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 {
 	struct ath10k *ar = file->private_data;
 	struct ath10k_target_stats *fw_stats;
-	char *buf;
+	char *buf = NULL;
 	unsigned int len = 0, buf_len = 2500;
-	ssize_t ret_cnt;
+	ssize_t ret_cnt = 0;
 	long left;
 	int i;
 	int ret;
 
 	fw_stats = &ar->debug.target_stats;
 
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_ON)
+		goto exit;
+
 	buf = kzalloc(buf_len, GFP_KERNEL);
 	if (!buf)
-		return -ENOMEM;
+		goto exit;
 
 	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
 	if (ret) {
 		ath10k_warn("could not request stats (%d)\n", ret);
-		kfree(buf);
-		return -EIO;
+		goto exit;
 	}
 
 	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
+	if (left <= 0)
+		goto exit;
 
-	if (left <= 0) {
-		kfree(buf);
-		return -ETIMEDOUT;
-	}
-
-	mutex_lock(&ar->conf_mutex);
-
+	spin_lock_bh(&ar->data_lock);
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
 			 "ath10k PDEV stats");
@@ -424,14 +425,15 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 				 fw_stats->peer_stat[i].peer_tx_rate);
 		len += scnprintf(buf + len, buf_len - len, "\n");
 	}
+	spin_unlock_bh(&ar->data_lock);
 
 	if (len > buf_len)
 		len = buf_len;
 
 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
 
+exit:
 	mutex_unlock(&ar->conf_mutex);
-
 	kfree(buf);
 	return ret_cnt;
 }
@@ -443,6 +445,60 @@ static const struct file_operations fops_fw_stats = {
 	.llseek = default_llseek,
 };
 
+static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
+					     char __user *user_buf,
+					     size_t count, loff_t *ppos)
+{
+	const char buf[] = "To simulate firmware crash write the keyword"
+			   " `crash` to this file.\nThis will force firmware"
+			   " to report a crash to the host system.\n";
+	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
+}
+
+static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
+					      const char __user *user_buf,
+					      size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32] = {};
+	int ret;
+
+	mutex_lock(&ar->conf_mutex);
+
+	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+	if (strcmp(buf, "crash") && strcmp(buf, "crash\n")) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (ar->state != ATH10K_STATE_ON &&
+	    ar->state != ATH10K_STATE_RESTARTED) {
+		ret = -ENETDOWN;
+		goto exit;
+	}
+
+	ath10k_info("simulating firmware crash\n");
+
+	ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
+	if (ret)
+		ath10k_warn("failed to force fw hang (%d)\n", ret);
+
+	if (ret == 0)
+		ret = count;
+
+exit:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static const struct file_operations fops_simulate_fw_crash = {
+	.read = ath10k_read_simulate_fw_crash,
+	.write = ath10k_write_simulate_fw_crash,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
@@ -459,6 +515,9 @@ int ath10k_debug_create(struct ath10k *ar)
 	debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
 			    &fops_wmi_services);
 
+	debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_simulate_fw_crash);
+
 	return 0;
 }
 #endif /* CONFIG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 73a24d4..dcdea68 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -46,8 +46,11 @@ struct ath10k_hif_ops {
 				void *request, u32 request_len,
 				void *response, u32 *response_len);
 
+	/* Post BMI phase, after FW is loaded. Starts regular operation */
 	int (*start)(struct ath10k *ar);
 
+	/* Clean up what start() did. This does not revert to BMI phase. If
+	 * desired so, call power_down() and power_up() */
 	void (*stop)(struct ath10k *ar);
 
 	int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
@@ -66,10 +69,20 @@ struct ath10k_hif_ops {
 	 */
 	void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force);
 
-	void (*init)(struct ath10k *ar,
-		     struct ath10k_hif_cb *callbacks);
+	void (*set_callbacks)(struct ath10k *ar,
+			      struct ath10k_hif_cb *callbacks);
 
 	u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
+
+	/* Power up the device and enter BMI transfer mode for FW download */
+	int (*power_up)(struct ath10k *ar);
+
+	/* Power down the device and free up resources. stop() must be called
+	 * before this if start() was called earlier */
+	void (*power_down)(struct ath10k *ar);
+
+	int (*suspend)(struct ath10k *ar);
+	int (*resume)(struct ath10k *ar);
 };
 
 
@@ -122,10 +135,10 @@ static inline void ath10k_hif_send_complete_check(struct ath10k *ar,
 	ar->hif.ops->send_complete_check(ar, pipe_id, force);
 }
 
-static inline void ath10k_hif_init(struct ath10k *ar,
-				   struct ath10k_hif_cb *callbacks)
+static inline void ath10k_hif_set_callbacks(struct ath10k *ar,
+					    struct ath10k_hif_cb *callbacks)
 {
-	ar->hif.ops->init(ar, callbacks);
+	ar->hif.ops->set_callbacks(ar, callbacks);
 }
 
 static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
@@ -134,4 +147,30 @@ static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
 	return ar->hif.ops->get_free_queue_number(ar, pipe_id);
 }
 
+static inline int ath10k_hif_power_up(struct ath10k *ar)
+{
+	return ar->hif.ops->power_up(ar);
+}
+
+static inline void ath10k_hif_power_down(struct ath10k *ar)
+{
+	ar->hif.ops->power_down(ar);
+}
+
+static inline int ath10k_hif_suspend(struct ath10k *ar)
+{
+	if (!ar->hif.ops->suspend)
+		return -EOPNOTSUPP;
+
+	return ar->hif.ops->suspend(ar);
+}
+
+static inline int ath10k_hif_resume(struct ath10k *ar)
+{
+	if (!ar->hif.ops->resume)
+		return -EOPNOTSUPP;
+
+	return ar->hif.ops->resume(ar);
+}
+
 #endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 74363c9..ef3329e 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -246,15 +246,22 @@ int ath10k_htc_send(struct ath10k_htc *htc,
 {
 	struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 
+	if (htc->ar->state == ATH10K_STATE_WEDGED)
+		return -ECOMM;
+
 	if (eid >= ATH10K_HTC_EP_COUNT) {
 		ath10k_warn("Invalid endpoint id: %d\n", eid);
 		return -ENOENT;
 	}
 
-	skb_push(skb, sizeof(struct ath10k_htc_hdr));
-
 	spin_lock_bh(&htc->tx_lock);
+	if (htc->stopped) {
+		spin_unlock_bh(&htc->tx_lock);
+		return -ESHUTDOWN;
+	}
+
 	__skb_queue_tail(&ep->tx_queue, skb);
+	skb_push(skb, sizeof(struct ath10k_htc_hdr));
 	spin_unlock_bh(&htc->tx_lock);
 
 	queue_work(htc->ar->workqueue, &ep->send_work);
@@ -265,25 +272,19 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
 					    struct sk_buff *skb,
 					    unsigned int eid)
 {
-	struct ath10k_htc *htc = ar->htc;
+	struct ath10k_htc *htc = &ar->htc;
 	struct ath10k_htc_ep *ep = &htc->endpoint[eid];
-	bool stopping;
 
 	ath10k_htc_notify_tx_completion(ep, skb);
 	/* the skb now belongs to the completion handler */
 
+	/* note: when using TX credit flow, the re-checking of queues happens
+	 * when credits flow back from the target.  in the non-TX credit case,
+	 * we recheck after the packet completes */
 	spin_lock_bh(&htc->tx_lock);
-	stopping = htc->stopping;
-	spin_unlock_bh(&htc->tx_lock);
-
-	if (!ep->tx_credit_flow_enabled && !stopping)
-		/*
-		 * note: when using TX credit flow, the re-checking of
-		 * queues happens when credits flow back from the target.
-		 * in the non-TX credit case, we recheck after the packet
-		 * completes
-		 */
+	if (!ep->tx_credit_flow_enabled && !htc->stopped)
 		queue_work(ar->workqueue, &ep->send_work);
+	spin_unlock_bh(&htc->tx_lock);
 
 	return 0;
 }
@@ -414,7 +415,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
 					    u8 pipe_id)
 {
 	int status = 0;
-	struct ath10k_htc *htc = ar->htc;
+	struct ath10k_htc *htc = &ar->htc;
 	struct ath10k_htc_hdr *hdr;
 	struct ath10k_htc_ep *ep;
 	u16 payload_len;
@@ -751,8 +752,9 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
 	tx_alloc = ath10k_htc_get_credit_allocation(htc,
 						    conn_req->service_id);
 	if (!tx_alloc)
-		ath10k_warn("HTC Service %s does not allocate target credits\n",
-			    htc_service_name(conn_req->service_id));
+		ath10k_dbg(ATH10K_DBG_HTC,
+			   "HTC Service %s does not allocate target credits\n",
+			   htc_service_name(conn_req->service_id));
 
 	skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
 	if (!skb) {
@@ -947,7 +949,7 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
 	struct ath10k_htc_ep *ep;
 
 	spin_lock_bh(&htc->tx_lock);
-	htc->stopping = true;
+	htc->stopped = true;
 	spin_unlock_bh(&htc->tx_lock);
 
 	for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
@@ -956,26 +958,18 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
 	}
 
 	ath10k_hif_stop(htc->ar);
-	ath10k_htc_reset_endpoint_states(htc);
 }
 
 /* registered target arrival callback from the HIF layer */
-struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
-				     struct ath10k_htc_ops *htc_ops)
+int ath10k_htc_init(struct ath10k *ar)
 {
 	struct ath10k_hif_cb htc_callbacks;
 	struct ath10k_htc_ep *ep = NULL;
-	struct ath10k_htc *htc = NULL;
-
-	/* FIXME: use struct ath10k instead */
-	htc = kzalloc(sizeof(struct ath10k_htc), GFP_KERNEL);
-	if (!htc)
-		return ERR_PTR(-ENOMEM);
+	struct ath10k_htc *htc = &ar->htc;
 
 	spin_lock_init(&htc->tx_lock);
 
-	memcpy(&htc->htc_ops, htc_ops, sizeof(struct ath10k_htc_ops));
-
+	htc->stopped = false;
 	ath10k_htc_reset_endpoint_states(htc);
 
 	/* setup HIF layer callbacks */
@@ -986,15 +980,10 @@ struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
 	/* Get HIF default pipe for HTC message exchange */
 	ep = &htc->endpoint[ATH10K_HTC_EP_0];
 
-	ath10k_hif_init(ar, &htc_callbacks);
+	ath10k_hif_set_callbacks(ar, &htc_callbacks);
 	ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
 
 	init_completion(&htc->ctl_resp);
 
-	return htc;
-}
-
-void ath10k_htc_destroy(struct ath10k_htc *htc)
-{
-	kfree(htc);
+	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index fa45844..e1dd8c7 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -335,7 +335,7 @@ struct ath10k_htc {
 	struct ath10k *ar;
 	struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
 
-	/* protects endpoint and stopping fields */
+	/* protects endpoint and stopped fields */
 	spinlock_t tx_lock;
 
 	struct ath10k_htc_ops htc_ops;
@@ -349,11 +349,10 @@ struct ath10k_htc {
 	struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
 	int target_credit_size;
 
-	bool stopping;
+	bool stopped;
 };
 
-struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
-				     struct ath10k_htc_ops *htc_ops);
+int ath10k_htc_init(struct ath10k *ar);
 int ath10k_htc_wait_target(struct ath10k_htc *htc);
 int ath10k_htc_start(struct ath10k_htc *htc);
 int ath10k_htc_connect_service(struct ath10k_htc *htc,
@@ -362,7 +361,6 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
 int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 		    struct sk_buff *packet);
 void ath10k_htc_stop(struct ath10k_htc *htc);
-void ath10k_htc_destroy(struct ath10k_htc *htc);
 struct sk_buff *ath10k_htc_alloc_skb(int size);
 
 #endif
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 185a546..39342c5 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/if_ether.h>
 
 #include "htt.h"
 #include "core.h"
@@ -36,7 +37,7 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
 	/* connect to control service */
 	conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG;
 
-	status = ath10k_htc_connect_service(htt->ar->htc, &conn_req,
+	status = ath10k_htc_connect_service(&htt->ar->htc, &conn_req,
 					    &conn_resp);
 
 	if (status)
@@ -47,15 +48,11 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
 	return 0;
 }
 
-struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
+int ath10k_htt_attach(struct ath10k *ar)
 {
-	struct ath10k_htt *htt;
+	struct ath10k_htt *htt = &ar->htt;
 	int ret;
 
-	htt = kzalloc(sizeof(*htt), GFP_KERNEL);
-	if (!htt)
-		return NULL;
-
 	htt->ar = ar;
 	htt->max_throughput_mbps = 800;
 
@@ -65,8 +62,11 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
 	 * since ath10k_htt_rx_attach involves sending a rx ring configure
 	 * message to the target.
 	 */
-	if (ath10k_htt_htc_attach(htt))
+	ret = ath10k_htt_htc_attach(htt);
+	if (ret) {
+		ath10k_err("could not attach htt htc (%d)\n", ret);
 		goto err_htc_attach;
+	}
 
 	ret = ath10k_htt_tx_attach(htt);
 	if (ret) {
@@ -74,8 +74,11 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
 		goto err_htc_attach;
 	}
 
-	if (ath10k_htt_rx_attach(htt))
+	ret = ath10k_htt_rx_attach(htt);
+	if (ret) {
+		ath10k_err("could not attach htt rx (%d)\n", ret);
 		goto err_rx_attach;
+	}
 
 	/*
 	 * Prefetch enough data to satisfy target
@@ -89,13 +92,12 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
 		8 + /* llc snap */
 		2; /* ip4 dscp or ip6 priority */
 
-	return htt;
+	return 0;
 
 err_rx_attach:
 	ath10k_htt_tx_detach(htt);
 err_htc_attach:
-	kfree(htt);
-	return NULL;
+	return ret;
 }
 
 #define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
@@ -148,5 +150,4 @@ void ath10k_htt_detach(struct ath10k_htt *htt)
 {
 	ath10k_htt_rx_detach(htt);
 	ath10k_htt_tx_detach(htt);
-	kfree(htt);
 }
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index a7a7aa0..318be46 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -20,7 +20,6 @@
 
 #include <linux/bug.h>
 
-#include "core.h"
 #include "htc.h"
 #include "rx_desc.h"
 
@@ -1317,7 +1316,7 @@ struct htt_rx_desc {
 #define HTT_LOG2_MAX_CACHE_LINE_SIZE 7	/* 2^7 = 128 */
 #define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
 
-struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar);
+int ath10k_htt_attach(struct ath10k *ar);
 int ath10k_htt_attach_target(struct ath10k_htt *htt);
 void ath10k_htt_detach(struct ath10k_htt *htt);
 
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index de058d7..04f08d9 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -15,6 +15,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "core.h"
 #include "htc.h"
 #include "htt.h"
 #include "txrx.h"
@@ -1036,7 +1037,7 @@ end:
 
 void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
-	struct ath10k_htt *htt = ar->htt;
+	struct ath10k_htt *htt = &ar->htt;
 	struct htt_resp *resp = (struct htt_resp *)skb->data;
 
 	/* confirm alignment */
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index ef79106..dc3f3e8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -92,7 +92,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt)
 
 	/* At the beginning free queue number should hint us the maximum
 	 * queue length */
-	pipe = htt->ar->htc->endpoint[htt->eid].ul_pipe_id;
+	pipe = htt->ar->htc.endpoint[htt->eid].ul_pipe_id;
 	htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar,
 								   pipe);
 
@@ -153,7 +153,7 @@ void ath10k_htt_tx_detach(struct ath10k_htt *htt)
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
-	struct ath10k_htt *htt = ar->htt;
+	struct ath10k_htt *htt = &ar->htt;
 
 	if (skb_cb->htt.is_conf) {
 		dev_kfree_skb_any(skb);
@@ -194,7 +194,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
 
 	ATH10K_SKB_CB(skb)->htt.is_conf = true;
 
-	ret = ath10k_htc_send(htt->ar->htc, htt->eid, skb);
+	ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
 	if (ret) {
 		dev_kfree_skb_any(skb);
 		return ret;
@@ -281,7 +281,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
 
 	ATH10K_SKB_CB(skb)->htt.is_conf = true;
 
-	ret = ath10k_htc_send(htt->ar->htc, htt->eid, skb);
+	ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
 	if (ret) {
 		dev_kfree_skb_any(skb);
 		return ret;
@@ -346,7 +346,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 	skb_cb->htt.refcount = 2;
 	skb_cb->htt.msdu = msdu;
 
-	res = ath10k_htc_send(htt->ar->htc, htt->eid, txdesc);
+	res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
 	if (res)
 		goto err;
 
@@ -486,7 +486,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 	skb_cb->htt.txfrag = txfrag;
 	skb_cb->htt.msdu = msdu;
 
-	res = ath10k_htc_send(htt->ar->htc, htt->eid, txdesc);
+	res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
 	if (res)
 		goto err;
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index da5c333..d0a7761 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -20,6 +20,7 @@
 #include <net/mac80211.h>
 #include <linux/etherdevice.h>
 
+#include "hif.h"
 #include "core.h"
 #include "debug.h"
 #include "wmi.h"
@@ -43,6 +44,8 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
 		.macaddr = macaddr,
 	};
 
+	lockdep_assert_held(&arvif->ar->conf_mutex);
+
 	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
 		arg.key_flags = WMI_KEY_PAIRWISE;
 	else
@@ -87,6 +90,8 @@ static int ath10k_install_key(struct ath10k_vif *arvif,
 	struct ath10k *ar = arvif->ar;
 	int ret;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	INIT_COMPLETION(ar->install_key_done);
 
 	ret = ath10k_send_key(arvif, key, cmd, macaddr);
@@ -327,6 +332,29 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
 	return 0;
 }
 
+static int  ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
+{
+	if (value != 0xFFFFFFFF)
+		value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold,
+			      ATH10K_RTS_MAX);
+
+	return ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id,
+					 WMI_VDEV_PARAM_RTS_THRESHOLD,
+					 value);
+}
+
+static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value)
+{
+	if (value != 0xFFFFFFFF)
+		value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold,
+				ATH10K_FRAGMT_THRESHOLD_MIN,
+				ATH10K_FRAGMT_THRESHOLD_MAX);
+
+	return ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id,
+					 WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
+					 value);
+}
+
 static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
 {
 	int ret;
@@ -364,6 +392,20 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 	spin_unlock_bh(&ar->data_lock);
 }
 
+static void ath10k_peer_cleanup_all(struct ath10k *ar)
+{
+	struct ath10k_peer *peer, *tmp;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	spin_lock_bh(&ar->data_lock);
+	list_for_each_entry_safe(peer, tmp, &ar->peers, list) {
+		list_del(&peer->list);
+		kfree(peer);
+	}
+	spin_unlock_bh(&ar->data_lock);
+}
+
 /************************/
 /* Interface management */
 /************************/
@@ -372,6 +414,8 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
 {
 	int ret;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	ret = wait_for_completion_timeout(&ar->vdev_setup_done,
 					  ATH10K_VDEV_SETUP_TIMEOUT_HZ);
 	if (ret == 0)
@@ -605,6 +649,8 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
 {
 	int ret = 0;
 
+	lockdep_assert_held(&arvif->ar->conf_mutex);
+
 	if (!info->enable_beacon) {
 		ath10k_vdev_stop(arvif);
 		return;
@@ -631,6 +677,8 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
 {
 	int ret = 0;
 
+	lockdep_assert_held(&arvif->ar->conf_mutex);
+
 	if (!info->ibss_joined) {
 		ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, self_peer);
 		if (ret)
@@ -680,6 +728,8 @@ static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	enum wmi_sta_ps_mode psmode;
 	int ret;
 
+	lockdep_assert_held(&arvif->ar->conf_mutex);
+
 	if (vif->type != NL80211_IFTYPE_STATION)
 		return;
 
@@ -722,6 +772,8 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
 				      struct ieee80211_bss_conf *bss_conf,
 				      struct wmi_peer_assoc_complete_arg *arg)
 {
+	lockdep_assert_held(&ar->conf_mutex);
+
 	memcpy(arg->addr, sta->addr, ETH_ALEN);
 	arg->vdev_id = arvif->vdev_id;
 	arg->peer_aid = sta->aid;
@@ -764,6 +816,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
 	const u8 *rsnie = NULL;
 	const u8 *wpaie = NULL;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	bss = cfg80211_get_bss(ar->hw->wiphy, ar->hw->conf.chandef.chan,
 			       info->bssid, NULL, 0, 0, 0);
 	if (bss) {
@@ -804,6 +858,8 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar,
 	u32 ratemask;
 	int i;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	sband = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
 	ratemask = sta->supp_rates[ar->hw->conf.chandef.chan->band];
 	rates = sband->bitrates;
@@ -827,6 +883,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
 	int smps;
 	int i, n;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	if (!ht_cap->ht_supported)
 		return;
 
@@ -905,6 +963,8 @@ static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar,
 	u32 uapsd = 0;
 	u32 max_sp = 0;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	if (sta->wme)
 		arg->peer_flags |= WMI_PEER_QOS;
 
@@ -1056,6 +1116,8 @@ static int ath10k_peer_assoc(struct ath10k *ar,
 {
 	struct wmi_peer_assoc_complete_arg arg;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	memset(&arg, 0, sizeof(struct wmi_peer_assoc_complete_arg));
 
 	ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, &arg);
@@ -1079,6 +1141,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
 	struct ieee80211_sta *ap_sta;
 	int ret;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	rcu_read_lock();
 
 	ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
@@ -1119,6 +1183,8 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	int ret;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	/*
 	 * For some reason, calling VDEV-DOWN before VDEV-STOP
 	 * makes the FW to send frames via HTT after disassociation.
@@ -1152,6 +1218,8 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
 {
 	int ret = 0;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	ret = ath10k_peer_assoc(ar, arvif, sta, NULL);
 	if (ret) {
 		ath10k_warn("WMI peer assoc failed for %pM\n", sta->addr);
@@ -1172,6 +1240,8 @@ static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
 {
 	int ret = 0;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	ret = ath10k_clear_peer_keys(arvif, sta->addr);
 	if (ret) {
 		ath10k_warn("could not clear all peer wep keys (%d)\n", ret);
@@ -1198,6 +1268,8 @@ static int ath10k_update_channel_list(struct ath10k *ar)
 	int ret;
 	int i;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	bands = hw->wiphy->bands;
 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 		if (!bands[band])
@@ -1276,21 +1348,19 @@ static int ath10k_update_channel_list(struct ath10k *ar)
 	return ret;
 }
 
-static void ath10k_reg_notifier(struct wiphy *wiphy,
-				struct regulatory_request *request)
+static void ath10k_regd_update(struct ath10k *ar)
 {
-	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 	struct reg_dmn_pair_mapping *regpair;
-	struct ath10k *ar = hw->priv;
 	int ret;
 
-	ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
+	lockdep_assert_held(&ar->conf_mutex);
 
 	ret = ath10k_update_channel_list(ar);
 	if (ret)
 		ath10k_warn("could not update channel list (%d)\n", ret);
 
 	regpair = ar->ath_common.regulatory.regpair;
+
 	/* Target allows setting up per-band regdomain but ath_common provides
 	 * a combined one only */
 	ret = ath10k_wmi_pdev_set_regdomain(ar,
@@ -1303,6 +1373,20 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
 		ath10k_warn("could not set pdev regdomain (%d)\n", ret);
 }
 
+static void ath10k_reg_notifier(struct wiphy *wiphy,
+				struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ath10k *ar = hw->priv;
+
+	ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
+
+	mutex_lock(&ar->conf_mutex);
+	if (ar->state == ATH10K_STATE_ON)
+		ath10k_regd_update(ar);
+	mutex_unlock(&ar->conf_mutex);
+}
+
 /***************/
 /* TX handlers */
 /***************/
@@ -1397,15 +1481,15 @@ static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb)
 	int ret;
 
 	if (ieee80211_is_mgmt(hdr->frame_control))
-		ret = ath10k_htt_mgmt_tx(ar->htt, skb);
+		ret = ath10k_htt_mgmt_tx(&ar->htt, skb);
 	else if (ieee80211_is_nullfunc(hdr->frame_control))
 		/* FW does not report tx status properly for NullFunc frames
 		 * unless they are sent through mgmt tx path. mac80211 sends
 		 * those frames when it detects link/beacon loss and depends on
 		 * the tx status to be correct. */
-		ret = ath10k_htt_mgmt_tx(ar->htt, skb);
+		ret = ath10k_htt_mgmt_tx(&ar->htt, skb);
 	else
-		ret = ath10k_htt_tx(ar->htt, skb);
+		ret = ath10k_htt_tx(&ar->htt, skb);
 
 	if (ret) {
 		ath10k_warn("tx failed (%d). dropping packet.\n", ret);
@@ -1552,6 +1636,10 @@ static int ath10k_abort_scan(struct ath10k *ar)
 	ret = ath10k_wmi_stop_scan(ar, &arg);
 	if (ret) {
 		ath10k_warn("could not submit wmi stop scan (%d)\n", ret);
+		spin_lock_bh(&ar->data_lock);
+		ar->scan.in_progress = false;
+		ath10k_offchan_tx_purge(ar);
+		spin_unlock_bh(&ar->data_lock);
 		return -EIO;
 	}
 
@@ -1645,10 +1733,14 @@ static void ath10k_tx(struct ieee80211_hw *hw,
 		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
 	}
 
-	ath10k_tx_h_qos_workaround(hw, control, skb);
-	ath10k_tx_h_update_wep_key(skb);
-	ath10k_tx_h_add_p2p_noa_ie(ar, skb);
-	ath10k_tx_h_seq_no(skb);
+	/* it makes no sense to process injected frames like that */
+	if (info->control.vif &&
+	    info->control.vif->type != NL80211_IFTYPE_MONITOR) {
+		ath10k_tx_h_qos_workaround(hw, control, skb);
+		ath10k_tx_h_update_wep_key(skb);
+		ath10k_tx_h_add_p2p_noa_ie(ar, skb);
+		ath10k_tx_h_seq_no(skb);
+	}
 
 	memset(ATH10K_SKB_CB(skb), 0, sizeof(*ATH10K_SKB_CB(skb)));
 	ATH10K_SKB_CB(skb)->htt.vdev_id = vdev_id;
@@ -1673,10 +1765,57 @@ static void ath10k_tx(struct ieee80211_hw *hw,
 /*
  * Initialize various parameters with default vaules.
  */
+void ath10k_halt(struct ath10k *ar)
+{
+	lockdep_assert_held(&ar->conf_mutex);
+
+	del_timer_sync(&ar->scan.timeout);
+	ath10k_offchan_tx_purge(ar);
+	ath10k_peer_cleanup_all(ar);
+	ath10k_core_stop(ar);
+	ath10k_hif_power_down(ar);
+
+	spin_lock_bh(&ar->data_lock);
+	if (ar->scan.in_progress) {
+		del_timer(&ar->scan.timeout);
+		ar->scan.in_progress = false;
+		ieee80211_scan_completed(ar->hw, true);
+	}
+	spin_unlock_bh(&ar->data_lock);
+}
+
 static int ath10k_start(struct ieee80211_hw *hw)
 {
 	struct ath10k *ar = hw->priv;
-	int ret;
+	int ret = 0;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_OFF &&
+	    ar->state != ATH10K_STATE_RESTARTING) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	ret = ath10k_hif_power_up(ar);
+	if (ret) {
+		ath10k_err("could not init hif (%d)\n", ret);
+		ar->state = ATH10K_STATE_OFF;
+		goto exit;
+	}
+
+	ret = ath10k_core_start(ar);
+	if (ret) {
+		ath10k_err("could not init core (%d)\n", ret);
+		ath10k_hif_power_down(ar);
+		ar->state = ATH10K_STATE_OFF;
+		goto exit;
+	}
+
+	if (ar->state == ATH10K_STATE_OFF)
+		ar->state = ATH10K_STATE_ON;
+	else if (ar->state == ATH10K_STATE_RESTARTING)
+		ar->state = ATH10K_STATE_RESTARTED;
 
 	ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1);
 	if (ret)
@@ -1688,6 +1827,10 @@ static int ath10k_start(struct ieee80211_hw *hw)
 		ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
 			    ret);
 
+	ath10k_regd_update(ar);
+
+exit:
+	mutex_unlock(&ar->conf_mutex);
 	return 0;
 }
 
@@ -1695,18 +1838,48 @@ static void ath10k_stop(struct ieee80211_hw *hw)
 {
 	struct ath10k *ar = hw->priv;
 
-	/* avoid leaks in case FW never confirms scan for offchannel */
+	mutex_lock(&ar->conf_mutex);
+	if (ar->state == ATH10K_STATE_ON ||
+	    ar->state == ATH10K_STATE_RESTARTED ||
+	    ar->state == ATH10K_STATE_WEDGED)
+		ath10k_halt(ar);
+
+	ar->state = ATH10K_STATE_OFF;
+	mutex_unlock(&ar->conf_mutex);
+
 	cancel_work_sync(&ar->offchan_tx_work);
-	ath10k_offchan_tx_purge(ar);
+	cancel_work_sync(&ar->restart_work);
 }
 
-static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
+static void ath10k_config_ps(struct ath10k *ar)
 {
 	struct ath10k_generic_iter ar_iter;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	/* During HW reconfiguration mac80211 reports all interfaces that were
+	 * running until reconfiguration was started. Since FW doesn't have any
+	 * vdevs at this point we must not iterate over this interface list.
+	 * This setting will be updated upon add_interface(). */
+	if (ar->state == ATH10K_STATE_RESTARTED)
+		return;
+
+	memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
+	ar_iter.ar = ar;
+
+	ieee80211_iterate_active_interfaces_atomic(
+		ar->hw, IEEE80211_IFACE_ITER_NORMAL,
+		ath10k_ps_iter, &ar_iter);
+
+	if (ar_iter.ret)
+		ath10k_warn("failed to set ps config (%d)\n", ar_iter.ret);
+}
+
+static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
+{
 	struct ath10k *ar = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	int ret = 0;
-	u32 flags;
 
 	mutex_lock(&ar->conf_mutex);
 
@@ -1718,18 +1891,8 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 		spin_unlock_bh(&ar->data_lock);
 	}
 
-	if (changed & IEEE80211_CONF_CHANGE_PS) {
-		memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
-		ar_iter.ar = ar;
-		flags = IEEE80211_IFACE_ITER_RESUME_ALL;
-
-		ieee80211_iterate_active_interfaces_atomic(hw,
-							   flags,
-							   ath10k_ps_iter,
-							   &ar_iter);
-
-		ret = ar_iter.ret;
-	}
+	if (changed & IEEE80211_CONF_CHANGE_PS)
+		ath10k_config_ps(ar);
 
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
 		if (conf->flags & IEEE80211_CONF_MONITOR)
@@ -1738,6 +1901,7 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 			ret = ath10k_monitor_destroy(ar);
 	}
 
+	ath10k_wmi_flush_tx(ar);
 	mutex_unlock(&ar->conf_mutex);
 	return ret;
 }
@@ -1859,6 +2023,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 			ath10k_warn("Failed to set PSPOLL count: %d\n", ret);
 	}
 
+	ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
+	if (ret)
+		ath10k_warn("failed to set rts threshold for vdev %d (%d)\n",
+			    arvif->vdev_id, ret);
+
+	ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold);
+	if (ret)
+		ath10k_warn("failed to set frag threshold for vdev %d (%d)\n",
+			    arvif->vdev_id, ret);
+
 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
 		ar->monitor_present = true;
 
@@ -2363,6 +2537,8 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
 	u32 value = 0;
 	int ret = 0;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
 	if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
 		return 0;
 
@@ -2558,11 +2734,16 @@ static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	u32 rts = ar_iter->ar->hw->wiphy->rts_threshold;
 
-	rts = min_t(u32, rts, ATH10K_RTS_MAX);
+	lockdep_assert_held(&arvif->ar->conf_mutex);
 
-	ar_iter->ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id,
-						 WMI_VDEV_PARAM_RTS_THRESHOLD,
-						 rts);
+	/* During HW reconfiguration mac80211 reports all interfaces that were
+	 * running until reconfiguration was started. Since FW doesn't have any
+	 * vdevs at this point we must not iterate over this interface list.
+	 * This setting will be updated upon add_interface(). */
+	if (ar_iter->ar->state == ATH10K_STATE_RESTARTED)
+		return;
+
+	ar_iter->ret = ath10k_mac_set_rts(arvif, rts);
 	if (ar_iter->ret)
 		ath10k_warn("Failed to set RTS threshold for VDEV: %d\n",
 			    arvif->vdev_id);
@@ -2581,8 +2762,9 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 	ar_iter.ar = ar;
 
 	mutex_lock(&ar->conf_mutex);
-	ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-					    ath10k_set_rts_iter, &ar_iter);
+	ieee80211_iterate_active_interfaces_atomic(
+		hw, IEEE80211_IFACE_ITER_NORMAL,
+		ath10k_set_rts_iter, &ar_iter);
 	mutex_unlock(&ar->conf_mutex);
 
 	return ar_iter.ret;
@@ -2593,17 +2775,17 @@ static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	struct ath10k_generic_iter *ar_iter = data;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	u32 frag = ar_iter->ar->hw->wiphy->frag_threshold;
-	int ret;
 
-	frag = clamp_t(u32, frag,
-		       ATH10K_FRAGMT_THRESHOLD_MIN,
-		       ATH10K_FRAGMT_THRESHOLD_MAX);
+	lockdep_assert_held(&arvif->ar->conf_mutex);
 
-	ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id,
-					WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
-					frag);
+	/* During HW reconfiguration mac80211 reports all interfaces that were
+	 * running until reconfiguration was started. Since FW doesn't have any
+	 * vdevs at this point we must not iterate over this interface list.
+	 * This setting will be updated upon add_interface(). */
+	if (ar_iter->ar->state == ATH10K_STATE_RESTARTED)
+		return;
 
-	ar_iter->ret = ret;
+	ar_iter->ret = ath10k_mac_set_frag(arvif, frag);
 	if (ar_iter->ret)
 		ath10k_warn("Failed to set frag threshold for VDEV: %d\n",
 			    arvif->vdev_id);
@@ -2622,8 +2804,9 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
 	ar_iter.ar = ar;
 
 	mutex_lock(&ar->conf_mutex);
-	ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-					    ath10k_set_frag_iter, &ar_iter);
+	ieee80211_iterate_active_interfaces_atomic(
+		hw, IEEE80211_IFACE_ITER_NORMAL,
+		ath10k_set_frag_iter, &ar_iter);
 	mutex_unlock(&ar->conf_mutex);
 
 	return ar_iter.ret;
@@ -2632,6 +2815,7 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
 static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct ath10k *ar = hw->priv;
+	bool skip;
 	int ret;
 
 	/* mac80211 doesn't care if we really xmit queued frames or not
@@ -2639,16 +2823,29 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 	if (drop)
 		return;
 
-	ret = wait_event_timeout(ar->htt->empty_tx_wq, ({
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_WEDGED)
+		goto skip;
+
+	ret = wait_event_timeout(ar->htt.empty_tx_wq, ({
 			bool empty;
-			spin_lock_bh(&ar->htt->tx_lock);
-			empty = bitmap_empty(ar->htt->used_msdu_ids,
-					     ar->htt->max_num_pending_tx);
-			spin_unlock_bh(&ar->htt->tx_lock);
-			(empty);
+
+			spin_lock_bh(&ar->htt.tx_lock);
+			empty = bitmap_empty(ar->htt.used_msdu_ids,
+					     ar->htt.max_num_pending_tx);
+			spin_unlock_bh(&ar->htt.tx_lock);
+
+			skip = (ar->state == ATH10K_STATE_WEDGED);
+
+			(empty || skip);
 		}), ATH10K_FLUSH_TIMEOUT_HZ);
-	if (ret <= 0)
+
+	if (ret <= 0 || skip)
 		ath10k_warn("tx not flushed\n");
+
+skip:
+	mutex_unlock(&ar->conf_mutex);
 }
 
 /* TODO: Implement this function properly
@@ -2660,6 +2857,83 @@ static int ath10k_tx_last_beacon(struct ieee80211_hw *hw)
 	return 1;
 }
 
+#ifdef CONFIG_PM
+static int ath10k_suspend(struct ieee80211_hw *hw,
+			  struct cfg80211_wowlan *wowlan)
+{
+	struct ath10k *ar = hw->priv;
+	int ret;
+
+	ar->is_target_paused = false;
+
+	ret = ath10k_wmi_pdev_suspend_target(ar);
+	if (ret) {
+		ath10k_warn("could not suspend target (%d)\n", ret);
+		return 1;
+	}
+
+	ret = wait_event_interruptible_timeout(ar->event_queue,
+					       ar->is_target_paused == true,
+					       1 * HZ);
+	if (ret < 0) {
+		ath10k_warn("suspend interrupted (%d)\n", ret);
+		goto resume;
+	} else if (ret == 0) {
+		ath10k_warn("suspend timed out - target pause event never came\n");
+		goto resume;
+	}
+
+	ret = ath10k_hif_suspend(ar);
+	if (ret) {
+		ath10k_warn("could not suspend hif (%d)\n", ret);
+		goto resume;
+	}
+
+	return 0;
+resume:
+	ret = ath10k_wmi_pdev_resume_target(ar);
+	if (ret)
+		ath10k_warn("could not resume target (%d)\n", ret);
+	return 1;
+}
+
+static int ath10k_resume(struct ieee80211_hw *hw)
+{
+	struct ath10k *ar = hw->priv;
+	int ret;
+
+	ret = ath10k_hif_resume(ar);
+	if (ret) {
+		ath10k_warn("could not resume hif (%d)\n", ret);
+		return 1;
+	}
+
+	ret = ath10k_wmi_pdev_resume_target(ar);
+	if (ret) {
+		ath10k_warn("could not resume target (%d)\n", ret);
+		return 1;
+	}
+
+	return 0;
+}
+#endif
+
+static void ath10k_restart_complete(struct ieee80211_hw *hw)
+{
+	struct ath10k *ar = hw->priv;
+
+	mutex_lock(&ar->conf_mutex);
+
+	/* If device failed to restart it will be in a different state, e.g.
+	 * ATH10K_STATE_WEDGED */
+	if (ar->state == ATH10K_STATE_RESTARTED) {
+		ath10k_info("device successfully recovered\n");
+		ar->state = ATH10K_STATE_ON;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+}
+
 static const struct ieee80211_ops ath10k_ops = {
 	.tx				= ath10k_tx,
 	.start				= ath10k_start,
@@ -2680,6 +2954,11 @@ static const struct ieee80211_ops ath10k_ops = {
 	.set_frag_threshold		= ath10k_set_frag_threshold,
 	.flush				= ath10k_flush,
 	.tx_last_beacon			= ath10k_tx_last_beacon,
+	.restart_complete		= ath10k_restart_complete,
+#ifdef CONFIG_PM
+	.suspend			= ath10k_suspend,
+	.resume				= ath10k_resume,
+#endif
 };
 
 #define RATETAB_ENT(_rate, _rateid, _flags) { \
@@ -2948,8 +3227,10 @@ int ath10k_mac_register(struct ath10k *ar)
 		channels = kmemdup(ath10k_2ghz_channels,
 				   sizeof(ath10k_2ghz_channels),
 				   GFP_KERNEL);
-		if (!channels)
-			return -ENOMEM;
+		if (!channels) {
+			ret = -ENOMEM;
+			goto err_free;
+		}
 
 		band = &ar->mac.sbands[IEEE80211_BAND_2GHZ];
 		band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels);
@@ -2968,11 +3249,8 @@ int ath10k_mac_register(struct ath10k *ar)
 				   sizeof(ath10k_5ghz_channels),
 				   GFP_KERNEL);
 		if (!channels) {
-			if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
-				band = &ar->mac.sbands[IEEE80211_BAND_2GHZ];
-				kfree(band->channels);
-			}
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto err_free;
 		}
 
 		band = &ar->mac.sbands[IEEE80211_BAND_5GHZ];
@@ -3036,25 +3314,30 @@ int ath10k_mac_register(struct ath10k *ar)
 			    ath10k_reg_notifier);
 	if (ret) {
 		ath10k_err("Regulatory initialization failed\n");
-		return ret;
+		goto err_free;
 	}
 
 	ret = ieee80211_register_hw(ar->hw);
 	if (ret) {
 		ath10k_err("ieee80211 registration failed: %d\n", ret);
-		return ret;
+		goto err_free;
 	}
 
 	if (!ath_is_world_regd(&ar->ath_common.regulatory)) {
 		ret = regulatory_hint(ar->hw->wiphy,
 				      ar->ath_common.regulatory.alpha2);
 		if (ret)
-			goto exit;
+			goto err_unregister;
 	}
 
 	return 0;
-exit:
+
+err_unregister:
 	ieee80211_unregister_hw(ar->hw);
+err_free:
+	kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels);
+	kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels);
+
 	return ret;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 27fc92e..6fce9bf 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -34,6 +34,7 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
 void ath10k_reset_scan(unsigned long ptr);
 void ath10k_offchan_tx_purge(struct ath10k *ar);
 void ath10k_offchan_tx_work(struct work_struct *work);
+void ath10k_halt(struct ath10k *ar);
 
 static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 {
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 33af467..c71b488 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -54,6 +54,8 @@ static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info,
 					     int num);
 static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info);
 static void ath10k_pci_stop_ce(struct ath10k *ar);
+static void ath10k_pci_device_reset(struct ath10k *ar);
+static int ath10k_pci_reset_target(struct ath10k *ar);
 
 static const struct ce_attr host_ce_config_wlan[] = {
 	/* host->target HTC control and raw streams */
@@ -718,6 +720,8 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 			   reg_dump_values[i + 1],
 			   reg_dump_values[i + 2],
 			   reg_dump_values[i + 3]);
+
+	ieee80211_queue_work(ar->hw, &ar->restart_work);
 }
 
 static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
@@ -744,8 +748,8 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
 	ath10k_ce_per_engine_service(ar, pipe);
 }
 
-static void ath10k_pci_hif_post_init(struct ath10k *ar,
-				     struct ath10k_hif_cb *callbacks)
+static void ath10k_pci_hif_set_callbacks(struct ath10k *ar,
+					 struct ath10k_hif_cb *callbacks)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
@@ -1263,7 +1267,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
 	ath10k_pci_process_ce(ar);
 	ath10k_pci_cleanup_ce(ar);
 	ath10k_pci_buffer_cleanup(ar);
-	ath10k_pci_ce_deinit(ar);
 }
 
 static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
@@ -1735,6 +1738,115 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
 	ath10k_pci_sleep(ar);
 }
 
+static int ath10k_pci_hif_power_up(struct ath10k *ar)
+{
+	int ret;
+
+	/*
+	 * Bring the target up cleanly.
+	 *
+	 * The target may be in an undefined state with an AUX-powered Target
+	 * and a Host in WoW mode. If the Host crashes, loses power, or is
+	 * restarted (without unloading the driver) then the Target is left
+	 * (aux) powered and running. On a subsequent driver load, the Target
+	 * is in an unexpected state. We try to catch that here in order to
+	 * reset the Target and retry the probe.
+	 */
+	ath10k_pci_device_reset(ar);
+
+	ret = ath10k_pci_reset_target(ar);
+	if (ret)
+		goto err;
+
+	if (ath10k_target_ps) {
+		ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
+	} else {
+		/* Force AWAKE forever */
+		ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
+		ath10k_do_pci_wake(ar);
+	}
+
+	ret = ath10k_pci_ce_init(ar);
+	if (ret)
+		goto err_ps;
+
+	ret = ath10k_pci_init_config(ar);
+	if (ret)
+		goto err_ce;
+
+	ret = ath10k_pci_wake_target_cpu(ar);
+	if (ret) {
+		ath10k_err("could not wake up target CPU (%d)\n", ret);
+		goto err_ce;
+	}
+
+	return 0;
+
+err_ce:
+	ath10k_pci_ce_deinit(ar);
+err_ps:
+	if (!ath10k_target_ps)
+		ath10k_do_pci_sleep(ar);
+err:
+	return ret;
+}
+
+static void ath10k_pci_hif_power_down(struct ath10k *ar)
+{
+	ath10k_pci_ce_deinit(ar);
+	if (!ath10k_target_ps)
+		ath10k_do_pci_sleep(ar);
+}
+
+#ifdef CONFIG_PM
+
+#define ATH10K_PCI_PM_CONTROL 0x44
+
+static int ath10k_pci_hif_suspend(struct ath10k *ar)
+{
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+	struct pci_dev *pdev = ar_pci->pdev;
+	u32 val;
+
+	pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
+
+	if ((val & 0x000000ff) != 0x3) {
+		pci_save_state(pdev);
+		pci_disable_device(pdev);
+		pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
+				       (val & 0xffffff00) | 0x03);
+	}
+
+	return 0;
+}
+
+static int ath10k_pci_hif_resume(struct ath10k *ar)
+{
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+	struct pci_dev *pdev = ar_pci->pdev;
+	u32 val;
+
+	pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
+
+	if ((val & 0x000000ff) != 0) {
+		pci_restore_state(pdev);
+		pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
+				       val & 0xffffff00);
+		/*
+		 * Suspend/Resume resets the PCI configuration space,
+		 * so we have to re-disable the RETRY_TIMEOUT register (0x41)
+		 * to keep PCI Tx retries from interfering with C3 CPU state
+		 */
+		pci_read_config_dword(pdev, 0x40, &val);
+
+		if ((val & 0x0000ff00) != 0)
+			pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+	}
+
+	return 0;
+}
+#endif
+
 static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.send_head		= ath10k_pci_hif_send_head,
 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
@@ -1743,8 +1855,14 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.map_service_to_pipe	= ath10k_pci_hif_map_service_to_pipe,
 	.get_default_pipe	= ath10k_pci_hif_get_default_pipe,
 	.send_complete_check	= ath10k_pci_hif_send_complete_check,
-	.init			= ath10k_pci_hif_post_init,
+	.set_callbacks		= ath10k_pci_hif_set_callbacks,
 	.get_free_queue_number	= ath10k_pci_hif_get_free_queue_number,
+	.power_up		= ath10k_pci_hif_power_up,
+	.power_down		= ath10k_pci_hif_power_down,
+#ifdef CONFIG_PM
+	.suspend		= ath10k_pci_hif_suspend,
+	.resume			= ath10k_pci_hif_resume,
+#endif
 };
 
 static void ath10k_pci_ce_tasklet(unsigned long ptr)
@@ -2059,9 +2177,9 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
 	return 0;
 }
 
-static void ath10k_pci_device_reset(struct ath10k_pci *ar_pci)
+static void ath10k_pci_device_reset(struct ath10k *ar)
 {
-	struct ath10k *ar = ar_pci->ar;
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	void __iomem *mem = ar_pci->mem;
 	int i;
 	u32 val;
@@ -2118,7 +2236,7 @@ static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
 		case ATH10K_PCI_FEATURE_MSI_X:
 			ath10k_dbg(ATH10K_DBG_PCI, "device supports MSI-X\n");
 			break;
-		case ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND:
+		case ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND:
 			ath10k_dbg(ATH10K_DBG_PCI, "QCA988X_1.0 workaround enabled\n");
 			break;
 		}
@@ -2145,7 +2263,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
 	switch (pci_dev->device) {
 	case QCA988X_1_0_DEVICE_ID:
-		set_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features);
+		set_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features);
 		break;
 	case QCA988X_2_0_DEVICE_ID:
 		set_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features);
@@ -2158,8 +2276,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
 	ath10k_pci_dump_features(ar_pci);
 
-	ar = ath10k_core_create(ar_pci, ar_pci->dev, ATH10K_BUS_PCI,
-				&ath10k_pci_hif_ops);
+	ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops);
 	if (!ar) {
 		ath10k_err("ath10k_core_create failed!\n");
 		ret = -EINVAL;
@@ -2167,7 +2284,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 	}
 
 	/* Enable QCA988X_1.0 HW workarounds */
-	if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features))
+	if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features))
 		spin_lock_init(&ar_pci->hw_v1_workaround_lock);
 
 	ar_pci->ar = ar;
@@ -2247,54 +2364,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 		goto err_iomap;
 	}
 
-	/*
-	 * Bring the target up cleanly.
-	 *
-	 * The target may be in an undefined state with an AUX-powered Target
-	 * and a Host in WoW mode. If the Host crashes, loses power, or is
-	 * restarted (without unloading the driver) then the Target is left
-	 * (aux) powered and running. On a subsequent driver load, the Target
-	 * is in an unexpected state. We try to catch that here in order to
-	 * reset the Target and retry the probe.
-	 */
-	ath10k_pci_device_reset(ar_pci);
-
-	ret = ath10k_pci_reset_target(ar);
-	if (ret)
-		goto err_intr;
-
-	if (ath10k_target_ps) {
-		ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
-	} else {
-		/* Force AWAKE forever */
-		ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
-		ath10k_do_pci_wake(ar);
-	}
-
-	ret = ath10k_pci_ce_init(ar);
-	if (ret)
-		goto err_intr;
-
-	ret = ath10k_pci_init_config(ar);
-	if (ret)
-		goto err_ce;
-
-	ret = ath10k_pci_wake_target_cpu(ar);
-	if (ret) {
-		ath10k_err("could not wake up target CPU (%d)\n", ret);
-		goto err_ce;
-	}
-
 	ret = ath10k_core_register(ar);
 	if (ret) {
 		ath10k_err("could not register driver core (%d)\n", ret);
-		goto err_ce;
+		goto err_intr;
 	}
 
 	return 0;
 
-err_ce:
-	ath10k_pci_ce_deinit(ar);
 err_intr:
 	ath10k_pci_stop_intr(ar);
 err_iomap:
@@ -2345,128 +2422,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
 	kfree(ar_pci);
 }
 
-#if defined(CONFIG_PM_SLEEP)
-
-#define ATH10K_PCI_PM_CONTROL 0x44
-
-static int ath10k_pci_suspend(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct ath10k *ar = pci_get_drvdata(pdev);
-	struct ath10k_pci *ar_pci;
-	u32 val;
-	int ret, retval;
-
-	ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
-
-	if (!ar)
-		return -ENODEV;
-
-	ar_pci = ath10k_pci_priv(ar);
-	if (!ar_pci)
-		return -ENODEV;
-
-	if (ath10k_core_target_suspend(ar))
-		return -EBUSY;
-
-	ret = wait_event_interruptible_timeout(ar->event_queue,
-						ar->is_target_paused == true,
-						1 * HZ);
-	if (ret < 0) {
-		ath10k_warn("suspend interrupted (%d)\n", ret);
-		retval = ret;
-		goto resume;
-	} else if (ret == 0) {
-		ath10k_warn("suspend timed out - target pause event never came\n");
-		retval = EIO;
-		goto resume;
-	}
-
-	/*
-	 * reset is_target_paused and host can check that in next time,
-	 * or it will always be TRUE and host just skip the waiting
-	 * condition, it causes target assert due to host already
-	 * suspend
-	 */
-	ar->is_target_paused = false;
-
-	pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
-
-	if ((val & 0x000000ff) != 0x3) {
-		pci_save_state(pdev);
-		pci_disable_device(pdev);
-		pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
-				       (val & 0xffffff00) | 0x03);
-	}
-
-	return 0;
-resume:
-	ret = ath10k_core_target_resume(ar);
-	if (ret)
-		ath10k_warn("could not resume (%d)\n", ret);
-
-	return retval;
-}
-
-static int ath10k_pci_resume(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct ath10k *ar = pci_get_drvdata(pdev);
-	struct ath10k_pci *ar_pci;
-	int ret;
-	u32 val;
-
-	ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
-
-	if (!ar)
-		return -ENODEV;
-	ar_pci = ath10k_pci_priv(ar);
-
-	if (!ar_pci)
-		return -ENODEV;
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		ath10k_warn("cannot enable PCI device: %d\n", ret);
-		return ret;
-	}
-
-	pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
-
-	if ((val & 0x000000ff) != 0) {
-		pci_restore_state(pdev);
-		pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
-				       val & 0xffffff00);
-		/*
-		 * Suspend/Resume resets the PCI configuration space,
-		 * so we have to re-disable the RETRY_TIMEOUT register (0x41)
-		 * to keep PCI Tx retries from interfering with C3 CPU state
-		 */
-		pci_read_config_dword(pdev, 0x40, &val);
-
-		if ((val & 0x0000ff00) != 0)
-			pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-	}
-
-	ret = ath10k_core_target_resume(ar);
-	if (ret)
-		ath10k_warn("target resume failed: %d\n", ret);
-
-	return ret;
-}
-
-static SIMPLE_DEV_PM_OPS(ath10k_dev_pm_ops,
-			 ath10k_pci_suspend,
-			 ath10k_pci_resume);
-
-#define ATH10K_PCI_PM_OPS (&ath10k_dev_pm_ops)
-
-#else
-
-#define ATH10K_PCI_PM_OPS NULL
-
-#endif /* CONFIG_PM_SLEEP */
-
 MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);
 
 static struct pci_driver ath10k_pci_driver = {
@@ -2474,7 +2429,6 @@ static struct pci_driver ath10k_pci_driver = {
 	.id_table = ath10k_pci_id_table,
 	.probe = ath10k_pci_probe,
 	.remove = ath10k_pci_remove,
-	.driver.pm = ATH10K_PCI_PM_OPS,
 };
 
 static int __init ath10k_pci_init(void)
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index d2a055a..d3a2e6c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -152,7 +152,7 @@ struct service_to_pipe {
 
 enum ath10k_pci_features {
 	ATH10K_PCI_FEATURE_MSI_X		= 0,
-	ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND	= 1,
+	ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND	= 1,
 
 	/* keep last */
 	ATH10K_PCI_FEATURE_COUNT
@@ -311,7 +311,7 @@ static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset,
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	void __iomem *addr = ar_pci->mem;
 
-	if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) {
+	if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) {
 		unsigned long irq_flags;
 
 		spin_lock_irqsave(&ar_pci->hw_v1_workaround_lock, irq_flags);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 7d4b798..5e42460 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -27,6 +27,13 @@ void ath10k_wmi_flush_tx(struct ath10k *ar)
 {
 	int ret;
 
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_WEDGED) {
+		ath10k_warn("wmi flush skipped - device is wedged anyway\n");
+		return;
+	}
+
 	ret = wait_event_timeout(ar->wmi.wq,
 				 atomic_read(&ar->wmi.pending_tx_count) == 0,
 				 5*HZ);
@@ -111,7 +118,7 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
 
 	trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len);
 
-	status = ath10k_htc_send(ar->htc, ar->wmi.eid, skb);
+	status = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
 	if (status) {
 		dev_kfree_skb_any(skb);
 		atomic_dec(&ar->wmi.pending_tx_count);
@@ -501,8 +508,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
 	ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies,
 				    (u8 *)skb_tail_pointer(bcn) - ies);
 	if (!ie) {
-		/* highly unlikely for mac80211 */
-		ath10k_warn("no tim ie found;\n");
+		if (arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
+			ath10k_warn("no tim ie found;\n");
 		return;
 	}
 
@@ -1114,7 +1121,7 @@ int ath10k_wmi_connect_htc_service(struct ath10k *ar)
 	/* connect to control service */
 	conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
 
-	status = ath10k_htc_connect_service(ar->htc, &conn_req, &conn_resp);
+	status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
 	if (status) {
 		ath10k_warn("failed to connect to WMI CONTROL service status: %d\n",
 			    status);
@@ -1748,6 +1755,9 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 	if (arg->key_data)
 		memcpy(cmd->key_data, arg->key_data, arg->key_len);
 
+	ath10k_dbg(ATH10K_DBG_WMI,
+		   "wmi vdev install key idx %d cipher %d len %d\n",
+		   arg->key_idx, arg->key_cipher, arg->key_len);
 	return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_INSTALL_KEY_CMDID);
 }
 
@@ -2011,6 +2021,9 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
 	cmd->peer_vht_rates.tx_mcs_set =
 		__cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
 
+	ath10k_dbg(ATH10K_DBG_WMI,
+		   "wmi peer assoc vdev %d addr %pM\n",
+		   arg->vdev_id, arg->addr);
 	return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID);
 }
 
@@ -2079,3 +2092,22 @@ int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
 	ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id);
 	return ath10k_wmi_cmd_send(ar, skb, WMI_REQUEST_STATS_CMDID);
 }
+
+int ath10k_wmi_force_fw_hang(struct ath10k *ar,
+			     enum wmi_force_fw_hang_type type, u32 delay_ms)
+{
+	struct wmi_force_fw_hang_cmd *cmd;
+	struct sk_buff *skb;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_force_fw_hang_cmd *)skb->data;
+	cmd->type = __cpu_to_le32(type);
+	cmd->delay_ms = __cpu_to_le32(delay_ms);
+
+	ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n",
+		   type, delay_ms);
+	return ath10k_wmi_cmd_send(ar, skb, WMI_FORCE_FW_HANG_CMDID);
+}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 9555f5a..da3b2bc 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -416,6 +416,7 @@ enum wmi_cmd_id {
 	WMI_PDEV_FTM_INTG_CMDID,
 	WMI_VDEV_SET_KEEPALIVE_CMDID,
 	WMI_VDEV_GET_KEEPALIVE_CMDID,
+	WMI_FORCE_FW_HANG_CMDID,
 
 	/* GPIO Configuration */
 	WMI_GPIO_CONFIG_CMDID = WMI_CMD_GRP(WMI_GRP_GPIO),
@@ -2972,6 +2973,22 @@ struct wmi_sta_keepalive_cmd {
 	struct wmi_sta_keepalive_arp_resp arp_resp;
 } __packed;
 
+enum wmi_force_fw_hang_type {
+	WMI_FORCE_FW_HANG_ASSERT = 1,
+	WMI_FORCE_FW_HANG_NO_DETECT,
+	WMI_FORCE_FW_HANG_CTRL_EP_FULL,
+	WMI_FORCE_FW_HANG_EMPTY_POINT,
+	WMI_FORCE_FW_HANG_STACK_OVERFLOW,
+	WMI_FORCE_FW_HANG_INFINITE_LOOP,
+};
+
+#define WMI_FORCE_FW_HANG_RANDOM_TIME 0xFFFFFFFF
+
+struct wmi_force_fw_hang_cmd {
+	__le32 type;
+	__le32 delay_ms;
+} __packed;
+
 #define ATH10K_RTS_MAX		2347
 #define ATH10K_FRAGMT_THRESHOLD_MIN	540
 #define ATH10K_FRAGMT_THRESHOLD_MAX	2346
@@ -3048,5 +3065,7 @@ int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg);
 int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
 			const struct wmi_pdev_set_wmm_params_arg *arg);
 int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
+int ath10k_wmi_force_fw_hang(struct ath10k *ar,
+			     enum wmi_force_fw_hang_type type, u32 delay_ms);
 
 #endif /* _WMI_H_ */
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index d491a31..c91bc61 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -96,6 +96,16 @@ config ATH9K_LEGACY_RATE_CONTROL
 	  has to be passed to mac80211 using the module parameter,
 	  ieee80211_default_rc_algo.
 
+config ATH9K_RFKILL
+	bool "Atheros ath9k rfkill support" if EXPERT
+	depends on ATH9K
+	depends on RFKILL=y || RFKILL=ATH9K
+	default y
+	help
+	  Say Y to have ath9k poll the RF-Kill GPIO every couple of
+	  seconds. Turn off to save power, but enable it if you have
+	  a platform that can toggle the RF-Kill GPIO.
+
 config ATH9K_HTC
        tristate "Atheros HTC based wireless cards support"
        depends on USB && MAC80211
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c
index 664844c..dd1cc73 100644
--- a/drivers/net/wireless/ath/ath9k/antenna.c
+++ b/drivers/net/wireless/ath/ath9k/antenna.c
@@ -16,37 +16,119 @@
 
 #include "ath9k.h"
 
-static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta,
+/*
+ * AR9285
+ * ======
+ *
+ * EEPROM has 2 4-bit fields containing the card configuration.
+ *
+ * antdiv_ctl1:
+ * ------------
+ * bb_enable_ant_div_lnadiv : 1
+ * bb_ant_div_alt_gaintb    : 1
+ * bb_ant_div_main_gaintb   : 1
+ * bb_enable_ant_fast_div   : 1
+ *
+ * antdiv_ctl2:
+ * -----------
+ * bb_ant_div_alt_lnaconf  : 2
+ * bb_ant_div_main_lnaconf : 2
+ *
+ * The EEPROM bits are used as follows:
+ * ------------------------------------
+ *
+ * bb_enable_ant_div_lnadiv      - Enable LNA path rx antenna diversity/combining.
+ *                                 Set in AR_PHY_MULTICHAIN_GAIN_CTL.
+ *
+ * bb_ant_div_[alt/main]_gaintb  - 0 -> Antenna config Alt/Main uses gaintable 0
+ *                                 1 -> Antenna config Alt/Main uses gaintable 1
+ *                                 Set in AR_PHY_MULTICHAIN_GAIN_CTL.
+ *
+ * bb_enable_ant_fast_div        - Enable fast antenna diversity.
+ *                                 Set in AR_PHY_CCK_DETECT.
+ *
+ * bb_ant_div_[alt/main]_lnaconf - Alt/Main LNA diversity/combining input config.
+ *                                 Set in AR_PHY_MULTICHAIN_GAIN_CTL.
+ *                                 10=LNA1
+ *                                 01=LNA2
+ *                                 11=LNA1+LNA2
+ *                                 00=LNA1-LNA2
+ *
+ * AR9485 / AR9565 / AR9331
+ * ========================
+ *
+ * The same bits are present in the EEPROM, but the location in the
+ * EEPROM is different (ant_div_control in ar9300_BaseExtension_1).
+ *
+ * ant_div_alt_lnaconf      ==> bit 0~1
+ * ant_div_main_lnaconf     ==> bit 2~3
+ * ant_div_alt_gaintb       ==> bit 4
+ * ant_div_main_gaintb      ==> bit 5
+ * enable_ant_div_lnadiv    ==> bit 6
+ * enable_ant_fast_div      ==> bit 7
+ */
+
+static inline bool ath_is_alt_ant_ratio_better(struct ath_ant_comb *antcomb,
+					       int alt_ratio, int maxdelta,
 					       int mindelta, int main_rssi_avg,
 					       int alt_rssi_avg, int pkt_count)
 {
-	return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
-		 (alt_rssi_avg > main_rssi_avg + maxdelta)) ||
-		(alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
+	if (pkt_count <= 50)
+		return false;
+
+	if (alt_rssi_avg > main_rssi_avg + mindelta)
+		return true;
+
+	if (alt_ratio >= antcomb->ant_ratio2 &&
+	    alt_rssi_avg >= antcomb->low_rssi_thresh &&
+	    (alt_rssi_avg > main_rssi_avg + maxdelta))
+		return true;
+
+	return false;
 }
 
-static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
-					      int curr_main_set, int curr_alt_set,
-					      int alt_rssi_avg, int main_rssi_avg)
+static inline bool ath_ant_div_comb_alt_check(struct ath_hw_antcomb_conf *conf,
+					      struct ath_ant_comb *antcomb,
+					      int alt_ratio, int alt_rssi_avg,
+					      int main_rssi_avg)
 {
-	bool result = false;
-	switch (div_group) {
+	bool result, set1, set2;
+
+	result = set1 = set2 = false;
+
+	if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2 &&
+	    conf->alt_lna_conf == ATH_ANT_DIV_COMB_LNA1)
+		set1 = true;
+
+	if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA1 &&
+	    conf->alt_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+		set2 = true;
+
+	switch (conf->div_group) {
 	case 0:
 		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
 			result = true;
 		break;
 	case 1:
 	case 2:
-		if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
-		      (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
-		      (alt_rssi_avg >= (main_rssi_avg - 5))) ||
-		     ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) &&
-		      (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) &&
-		      (alt_rssi_avg >= (main_rssi_avg - 2)))) &&
-		    (alt_rssi_avg >= 4))
+		if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh)
+			break;
+
+		if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 5))) ||
+		    (set2 && (alt_rssi_avg >= (main_rssi_avg - 2))) ||
+		    (alt_ratio > antcomb->ant_ratio))
 			result = true;
-		else
-			result = false;
+
+		break;
+	case 3:
+		if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh)
+			break;
+
+		if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 3))) ||
+		    (set2 && (alt_rssi_avg >= (main_rssi_avg + 3))) ||
+		    (alt_ratio > antcomb->ant_ratio))
+			result = true;
+
 		break;
 	}
 
@@ -108,6 +190,74 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
 	}
 }
 
+static void ath_ant_set_alt_ratio(struct ath_ant_comb *antcomb,
+				  struct ath_hw_antcomb_conf *conf)
+{
+	/* set alt to the conf with maximun ratio */
+	if (antcomb->first_ratio && antcomb->second_ratio) {
+		if (antcomb->rssi_second > antcomb->rssi_third) {
+			/* first alt*/
+			if ((antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
+			    (antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2))
+				/* Set alt LNA1 or LNA2*/
+				if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+					conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+				else
+					conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+			else
+				/* Set alt to A+B or A-B */
+				conf->alt_lna_conf =
+					antcomb->first_quick_scan_conf;
+		} else if ((antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
+			   (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2)) {
+			/* Set alt LNA1 or LNA2 */
+			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+			else
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		} else {
+			/* Set alt to A+B or A-B */
+			conf->alt_lna_conf = antcomb->second_quick_scan_conf;
+		}
+	} else if (antcomb->first_ratio) {
+		/* first alt */
+		if ((antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
+		    (antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2))
+			/* Set alt LNA1 or LNA2 */
+			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+			else
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		else
+			/* Set alt to A+B or A-B */
+			conf->alt_lna_conf = antcomb->first_quick_scan_conf;
+	} else if (antcomb->second_ratio) {
+		/* second alt */
+		if ((antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
+		    (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2))
+			/* Set alt LNA1 or LNA2 */
+			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+			else
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		else
+			/* Set alt to A+B or A-B */
+			conf->alt_lna_conf = antcomb->second_quick_scan_conf;
+	} else {
+		/* main is largest */
+		if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
+		    (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
+			/* Set alt LNA1 or LNA2 */
+			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+			else
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		else
+			/* Set alt to A+B or A-B */
+			conf->alt_lna_conf = antcomb->main_conf;
+	}
+}
+
 static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 				       struct ath_hw_antcomb_conf *div_ant_conf,
 				       int main_rssi_avg, int alt_rssi_avg,
@@ -129,7 +279,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 
 		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
 			/* main is LNA1 */
-			if (ath_is_alt_ant_ratio_better(alt_ratio,
+			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
@@ -138,7 +288,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 			else
 				antcomb->first_ratio = false;
 		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
-			if (ath_is_alt_ant_ratio_better(alt_ratio,
+			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
@@ -147,11 +297,11 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 			else
 				antcomb->first_ratio = false;
 		} else {
-			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
-			      (alt_rssi_avg > main_rssi_avg +
-			       ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
-			     (alt_rssi_avg > main_rssi_avg)) &&
-			    (antcomb->total_pkt_count > 50))
+			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+						0,
+						main_rssi_avg, alt_rssi_avg,
+						antcomb->total_pkt_count))
 				antcomb->first_ratio = true;
 			else
 				antcomb->first_ratio = false;
@@ -164,17 +314,21 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 		antcomb->rssi_first = main_rssi_avg;
 		antcomb->rssi_third = alt_rssi_avg;
 
-		if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1)
+		switch(antcomb->second_quick_scan_conf) {
+		case ATH_ANT_DIV_COMB_LNA1:
 			antcomb->rssi_lna1 = alt_rssi_avg;
-		else if (antcomb->second_quick_scan_conf ==
-			 ATH_ANT_DIV_COMB_LNA2)
+			break;
+		case ATH_ANT_DIV_COMB_LNA2:
 			antcomb->rssi_lna2 = alt_rssi_avg;
-		else if (antcomb->second_quick_scan_conf ==
-			 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
+			break;
+		case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
 			if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)
 				antcomb->rssi_lna2 = main_rssi_avg;
 			else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1)
 				antcomb->rssi_lna1 = main_rssi_avg;
+			break;
+		default:
+			break;
 		}
 
 		if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
@@ -184,7 +338,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
 
 		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
-			if (ath_is_alt_ant_ratio_better(alt_ratio,
+			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
@@ -193,7 +347,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 			else
 				antcomb->second_ratio = false;
 		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
-			if (ath_is_alt_ant_ratio_better(alt_ratio,
+			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
 						main_rssi_avg, alt_rssi_avg,
@@ -202,105 +356,18 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 			else
 				antcomb->second_ratio = false;
 		} else {
-			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
-			      (alt_rssi_avg > main_rssi_avg +
-			       ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
-			     (alt_rssi_avg > main_rssi_avg)) &&
-			    (antcomb->total_pkt_count > 50))
+			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+						0,
+						main_rssi_avg, alt_rssi_avg,
+						antcomb->total_pkt_count))
 				antcomb->second_ratio = true;
 			else
 				antcomb->second_ratio = false;
 		}
 
-		/* set alt to the conf with maximun ratio */
-		if (antcomb->first_ratio && antcomb->second_ratio) {
-			if (antcomb->rssi_second > antcomb->rssi_third) {
-				/* first alt*/
-				if ((antcomb->first_quick_scan_conf ==
-				    ATH_ANT_DIV_COMB_LNA1) ||
-				    (antcomb->first_quick_scan_conf ==
-				    ATH_ANT_DIV_COMB_LNA2))
-					/* Set alt LNA1 or LNA2*/
-					if (div_ant_conf->main_lna_conf ==
-					    ATH_ANT_DIV_COMB_LNA2)
-						div_ant_conf->alt_lna_conf =
-							ATH_ANT_DIV_COMB_LNA1;
-					else
-						div_ant_conf->alt_lna_conf =
-							ATH_ANT_DIV_COMB_LNA2;
-				else
-					/* Set alt to A+B or A-B */
-					div_ant_conf->alt_lna_conf =
-						antcomb->first_quick_scan_conf;
-			} else if ((antcomb->second_quick_scan_conf ==
-				   ATH_ANT_DIV_COMB_LNA1) ||
-				   (antcomb->second_quick_scan_conf ==
-				   ATH_ANT_DIV_COMB_LNA2)) {
-				/* Set alt LNA1 or LNA2 */
-				if (div_ant_conf->main_lna_conf ==
-				    ATH_ANT_DIV_COMB_LNA2)
-					div_ant_conf->alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-				else
-					div_ant_conf->alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-			} else {
-				/* Set alt to A+B or A-B */
-				div_ant_conf->alt_lna_conf =
-					antcomb->second_quick_scan_conf;
-			}
-		} else if (antcomb->first_ratio) {
-			/* first alt */
-			if ((antcomb->first_quick_scan_conf ==
-			    ATH_ANT_DIV_COMB_LNA1) ||
-			    (antcomb->first_quick_scan_conf ==
-			    ATH_ANT_DIV_COMB_LNA2))
-					/* Set alt LNA1 or LNA2 */
-				if (div_ant_conf->main_lna_conf ==
-				    ATH_ANT_DIV_COMB_LNA2)
-					div_ant_conf->alt_lna_conf =
-							ATH_ANT_DIV_COMB_LNA1;
-				else
-					div_ant_conf->alt_lna_conf =
-							ATH_ANT_DIV_COMB_LNA2;
-			else
-				/* Set alt to A+B or A-B */
-				div_ant_conf->alt_lna_conf =
-						antcomb->first_quick_scan_conf;
-		} else if (antcomb->second_ratio) {
-				/* second alt */
-			if ((antcomb->second_quick_scan_conf ==
-			    ATH_ANT_DIV_COMB_LNA1) ||
-			    (antcomb->second_quick_scan_conf ==
-			    ATH_ANT_DIV_COMB_LNA2))
-				/* Set alt LNA1 or LNA2 */
-				if (div_ant_conf->main_lna_conf ==
-				    ATH_ANT_DIV_COMB_LNA2)
-					div_ant_conf->alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-				else
-					div_ant_conf->alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-			else
-				/* Set alt to A+B or A-B */
-				div_ant_conf->alt_lna_conf =
-						antcomb->second_quick_scan_conf;
-		} else {
-			/* main is largest */
-			if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
-			    (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
-				/* Set alt LNA1 or LNA2 */
-				if (div_ant_conf->main_lna_conf ==
-				    ATH_ANT_DIV_COMB_LNA2)
-					div_ant_conf->alt_lna_conf =
-							ATH_ANT_DIV_COMB_LNA1;
-				else
-					div_ant_conf->alt_lna_conf =
-							ATH_ANT_DIV_COMB_LNA2;
-			else
-				/* Set alt to A+B or A-B */
-				div_ant_conf->alt_lna_conf = antcomb->main_conf;
-		}
+		ath_ant_set_alt_ratio(antcomb, div_ant_conf);
+
 		break;
 	default:
 		break;
@@ -430,8 +497,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->fast_div_bias = 0x1;
 			break;
 		case 0x10: /* LNA2 A-B */
-			if (!(antcomb->scan) &&
-				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
 				ant_conf->fast_div_bias = 0x1;
 			else
 				ant_conf->fast_div_bias = 0x2;
@@ -440,15 +506,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->fast_div_bias = 0x1;
 			break;
 		case 0x13: /* LNA2 A+B */
-			if (!(antcomb->scan) &&
-				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
 				ant_conf->fast_div_bias = 0x1;
 			else
 				ant_conf->fast_div_bias = 0x2;
 			break;
 		case 0x20: /* LNA1 A-B */
-			if (!(antcomb->scan) &&
-				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
 				ant_conf->fast_div_bias = 0x1;
 			else
 				ant_conf->fast_div_bias = 0x2;
@@ -457,8 +521,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->fast_div_bias = 0x1;
 			break;
 		case 0x23: /* LNA1 A+B */
-			if (!(antcomb->scan) &&
-				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
 				ant_conf->fast_div_bias = 0x1;
 			else
 				ant_conf->fast_div_bias = 0x2;
@@ -475,6 +538,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 		default:
 			break;
 		}
+
+		if (antcomb->fast_div_bias)
+			ant_conf->fast_div_bias = antcomb->fast_div_bias;
 	} else if (ant_conf->div_group == 3) {
 		switch ((ant_conf->main_lna_conf << 4) |
 			ant_conf->alt_lna_conf) {
@@ -540,6 +606,138 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 	}
 }
 
+static void ath_ant_try_scan(struct ath_ant_comb *antcomb,
+			     struct ath_hw_antcomb_conf *conf,
+			     int curr_alt_set, int alt_rssi_avg,
+			     int main_rssi_avg)
+{
+	switch (curr_alt_set) {
+	case ATH_ANT_DIV_COMB_LNA2:
+		antcomb->rssi_lna2 = alt_rssi_avg;
+		antcomb->rssi_lna1 = main_rssi_avg;
+		antcomb->scan = true;
+		/* set to A+B */
+		conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+		conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		break;
+	case ATH_ANT_DIV_COMB_LNA1:
+		antcomb->rssi_lna1 = alt_rssi_avg;
+		antcomb->rssi_lna2 = main_rssi_avg;
+		antcomb->scan = true;
+		/* set to A+B */
+		conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		break;
+	case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
+		antcomb->rssi_add = alt_rssi_avg;
+		antcomb->scan = true;
+		/* set to A-B */
+		conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		break;
+	case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
+		antcomb->rssi_sub = alt_rssi_avg;
+		antcomb->scan = false;
+		if (antcomb->rssi_lna2 >
+		    (antcomb->rssi_lna1 + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
+			/* use LNA2 as main LNA */
+			if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
+			    (antcomb->rssi_add > antcomb->rssi_sub)) {
+				/* set to A+B */
+				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+			} else if (antcomb->rssi_sub >
+				   antcomb->rssi_lna1) {
+				/* set to A-B */
+				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+			} else {
+				/* set to LNA1 */
+				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+			}
+		} else {
+			/* use LNA1 as main LNA */
+			if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
+			    (antcomb->rssi_add > antcomb->rssi_sub)) {
+				/* set to A+B */
+				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+			} else if (antcomb->rssi_sub >
+				   antcomb->rssi_lna1) {
+				/* set to A-B */
+				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+			} else {
+				/* set to LNA2 */
+				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static bool ath_ant_try_switch(struct ath_hw_antcomb_conf *div_ant_conf,
+			       struct ath_ant_comb *antcomb,
+			       int alt_ratio, int alt_rssi_avg,
+			       int main_rssi_avg, int curr_main_set,
+			       int curr_alt_set)
+{
+	bool ret = false;
+
+	if (ath_ant_div_comb_alt_check(div_ant_conf, antcomb, alt_ratio,
+				       alt_rssi_avg, main_rssi_avg)) {
+		if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
+			/*
+			 * Switch main and alt LNA.
+			 */
+			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+		} else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
+			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		}
+
+		ret = true;
+	} else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
+		   (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
+		/*
+		  Set alt to another LNA.
+		*/
+		if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
+			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+		else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
+			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+
+		ret = true;
+	}
+
+	return ret;
+}
+
+static bool ath_ant_short_scan_check(struct ath_ant_comb *antcomb)
+{
+	int alt_ratio;
+
+	if (!antcomb->scan || !antcomb->alt_good)
+		return false;
+
+	if (time_after(jiffies, antcomb->scan_start_time +
+		       msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
+		return true;
+
+	if (antcomb->total_pkt_count == ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
+		alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+			     antcomb->total_pkt_count);
+		if (alt_ratio < antcomb->ant_ratio)
+			return true;
+	}
+
+	return false;
+}
+
 void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
 {
 	struct ath_hw_antcomb_conf div_ant_conf;
@@ -549,41 +747,46 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
 	int main_rssi = rs->rs_rssi_ctl0;
 	int alt_rssi = rs->rs_rssi_ctl1;
 	int rx_ant_conf,  main_ant_conf;
-	bool short_scan = false;
+	bool short_scan = false, ret;
 
 	rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
 		       ATH_ANT_RX_MASK;
 	main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
 			 ATH_ANT_RX_MASK;
 
+	if (alt_rssi >= antcomb->low_rssi_thresh) {
+		antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO;
+		antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2;
+	} else {
+		antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI;
+		antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI;
+	}
+
 	/* Record packet only when both main_rssi and  alt_rssi is positive */
 	if (main_rssi > 0 && alt_rssi > 0) {
 		antcomb->total_pkt_count++;
 		antcomb->main_total_rssi += main_rssi;
 		antcomb->alt_total_rssi  += alt_rssi;
+
 		if (main_ant_conf == rx_ant_conf)
 			antcomb->main_recv_cnt++;
 		else
 			antcomb->alt_recv_cnt++;
 	}
 
-	/* Short scan check */
-	if (antcomb->scan && antcomb->alt_good) {
-		if (time_after(jiffies, antcomb->scan_start_time +
-		    msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
-			short_scan = true;
-		else
-			if (antcomb->total_pkt_count ==
-			    ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
-				alt_ratio = ((antcomb->alt_recv_cnt * 100) /
-					    antcomb->total_pkt_count);
-				if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
-					short_scan = true;
-			}
+	if (main_ant_conf == rx_ant_conf) {
+		ANT_STAT_INC(ANT_MAIN, recv_cnt);
+		ANT_LNA_INC(ANT_MAIN, rx_ant_conf);
+	} else {
+		ANT_STAT_INC(ANT_ALT, recv_cnt);
+		ANT_LNA_INC(ANT_ALT, rx_ant_conf);
 	}
 
+	/* Short scan check */
+	short_scan = ath_ant_short_scan_check(antcomb);
+
 	if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
-	    rs->rs_moreaggr) && !short_scan)
+	     rs->rs_moreaggr) && !short_scan)
 		return;
 
 	if (antcomb->total_pkt_count) {
@@ -595,15 +798,13 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
 				 antcomb->total_pkt_count);
 	}
 
-
 	ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf);
 	curr_alt_set = div_ant_conf.alt_lna_conf;
 	curr_main_set = div_ant_conf.main_lna_conf;
-
 	antcomb->count++;
 
 	if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
-		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+		if (alt_ratio > antcomb->ant_ratio) {
 			ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
 						  main_rssi_avg);
 			antcomb->alt_good = true;
@@ -617,153 +818,47 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
 	}
 
 	if (!antcomb->scan) {
-		if (ath_ant_div_comb_alt_check(div_ant_conf.div_group,
-					alt_ratio, curr_main_set, curr_alt_set,
-					alt_rssi_avg, main_rssi_avg)) {
-			if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
-				/* Switch main and alt LNA */
-				div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-				div_ant_conf.alt_lna_conf  =
-						ATH_ANT_DIV_COMB_LNA1;
-			} else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
-				div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-				div_ant_conf.alt_lna_conf  =
-						ATH_ANT_DIV_COMB_LNA2;
-			}
-
-			goto div_comb_done;
-		} else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
-			   (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
-			/* Set alt to another LNA */
-			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
-				div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-			else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
-				div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-
-			goto div_comb_done;
-		}
-
-		if ((alt_rssi_avg < (main_rssi_avg +
-				     div_ant_conf.lna1_lna2_delta)))
+		ret = ath_ant_try_switch(&div_ant_conf, antcomb, alt_ratio,
+					 alt_rssi_avg, main_rssi_avg,
+					 curr_main_set, curr_alt_set);
+		if (ret)
 			goto div_comb_done;
 	}
 
+	if (!antcomb->scan &&
+	    (alt_rssi_avg < (main_rssi_avg + div_ant_conf.lna1_lna2_delta)))
+		goto div_comb_done;
+
 	if (!antcomb->scan_not_start) {
-		switch (curr_alt_set) {
-		case ATH_ANT_DIV_COMB_LNA2:
-			antcomb->rssi_lna2 = alt_rssi_avg;
-			antcomb->rssi_lna1 = main_rssi_avg;
-			antcomb->scan = true;
-			/* set to A+B */
-			div_ant_conf.main_lna_conf =
-				ATH_ANT_DIV_COMB_LNA1;
-			div_ant_conf.alt_lna_conf  =
-				ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
-			break;
-		case ATH_ANT_DIV_COMB_LNA1:
-			antcomb->rssi_lna1 = alt_rssi_avg;
-			antcomb->rssi_lna2 = main_rssi_avg;
-			antcomb->scan = true;
-			/* set to A+B */
-			div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
-			div_ant_conf.alt_lna_conf  =
-				ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
-			break;
-		case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
-			antcomb->rssi_add = alt_rssi_avg;
-			antcomb->scan = true;
-			/* set to A-B */
-			div_ant_conf.alt_lna_conf =
-				ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
-			break;
-		case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
-			antcomb->rssi_sub = alt_rssi_avg;
-			antcomb->scan = false;
-			if (antcomb->rssi_lna2 >
-			    (antcomb->rssi_lna1 +
-			    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
-				/* use LNA2 as main LNA */
-				if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
-				    (antcomb->rssi_add > antcomb->rssi_sub)) {
-					/* set to A+B */
-					div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-					div_ant_conf.alt_lna_conf  =
-						ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
-				} else if (antcomb->rssi_sub >
-					   antcomb->rssi_lna1) {
-					/* set to A-B */
-					div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-					div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
-				} else {
-					/* set to LNA1 */
-					div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-					div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-				}
-			} else {
-				/* use LNA1 as main LNA */
-				if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
-				    (antcomb->rssi_add > antcomb->rssi_sub)) {
-					/* set to A+B */
-					div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-					div_ant_conf.alt_lna_conf  =
-						ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
-				} else if (antcomb->rssi_sub >
-					   antcomb->rssi_lna1) {
-					/* set to A-B */
-					div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-					div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
-				} else {
-					/* set to LNA2 */
-					div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
-					div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
-				}
-			}
-			break;
-		default:
-			break;
-		}
+		ath_ant_try_scan(antcomb, &div_ant_conf, curr_alt_set,
+				 alt_rssi_avg, main_rssi_avg);
 	} else {
 		if (!antcomb->alt_good) {
 			antcomb->scan_not_start = false;
 			/* Set alt to another LNA */
 			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) {
 				div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
+					ATH_ANT_DIV_COMB_LNA2;
 				div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
+					ATH_ANT_DIV_COMB_LNA1;
 			} else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
 				div_ant_conf.main_lna_conf =
-						ATH_ANT_DIV_COMB_LNA1;
+					ATH_ANT_DIV_COMB_LNA1;
 				div_ant_conf.alt_lna_conf =
-						ATH_ANT_DIV_COMB_LNA2;
+					ATH_ANT_DIV_COMB_LNA2;
 			}
 			goto div_comb_done;
 		}
+		ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
+						   main_rssi_avg, alt_rssi_avg,
+						   alt_ratio);
+		antcomb->quick_scan_cnt++;
 	}
 
-	ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
-					   main_rssi_avg, alt_rssi_avg,
-					   alt_ratio);
-
-	antcomb->quick_scan_cnt++;
-
 div_comb_done:
 	ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio);
 	ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
+	ath9k_debug_stat_ant(sc, &div_ant_conf, main_rssi_avg, alt_rssi_avg);
 
 	antcomb->scan_start_time = jiffies;
 	antcomb->total_pkt_count = 0;
@@ -772,26 +867,3 @@ div_comb_done:
 	antcomb->main_recv_cnt = 0;
 	antcomb->alt_recv_cnt = 0;
 }
-
-void ath_ant_comb_update(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	struct ath_hw_antcomb_conf div_ant_conf;
-	u8 lna_conf;
-
-	ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
-
-	if (sc->ant_rx == 1)
-		lna_conf = ATH_ANT_DIV_COMB_LNA1;
-	else
-		lna_conf = ATH_ANT_DIV_COMB_LNA2;
-
-	div_ant_conf.main_lna_conf = lna_conf;
-	div_ant_conf.alt_lna_conf = lna_conf;
-
-	ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
-
-	if (common->antenna_diversity)
-		ath9k_hw_antctrl_shared_chain_lnadiv(ah, true);
-}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index f400351..456d8b9 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -555,6 +555,65 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
 	REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
 }
 
+static void ar9002_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
+{
+	struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+	u8 antdiv_ctrl1, antdiv_ctrl2;
+	u32 regval;
+
+	if (enable) {
+		antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_ENABLE;
+		antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_ENABLE;
+
+		/*
+		 * Don't disable BT ant to allow BB to control SWCOM.
+		 */
+		btcoex->bt_coex_mode2 &= (~(AR_BT_DISABLE_BT_ANT));
+		REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
+
+		REG_WRITE(ah, AR_PHY_SWITCH_COM, ATH_BT_COEX_ANT_DIV_SWITCH_COM);
+		REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
+	} else {
+		/*
+		 * Disable antenna diversity, use LNA1 only.
+		 */
+		antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_FIXED_A;
+		antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_FIXED_A;
+
+		/*
+		 * Disable BT Ant. to allow concurrent BT and WLAN receive.
+		 */
+		btcoex->bt_coex_mode2 |= AR_BT_DISABLE_BT_ANT;
+		REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
+
+		/*
+		 * Program SWCOM table to make sure RF switch always parks
+		 * at BT side.
+		 */
+		REG_WRITE(ah, AR_PHY_SWITCH_COM, 0);
+		REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
+	}
+
+	regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+	regval &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
+        /*
+	 * Clear ant_fast_div_bias [14:9] since for WB195,
+	 * the main LNA is always LNA1.
+	 */
+	regval &= (~(AR_PHY_9285_FAST_DIV_BIAS));
+	regval |= SM(antdiv_ctrl1, AR_PHY_9285_ANT_DIV_CTL);
+	regval |= SM(antdiv_ctrl2, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+	regval |= SM((antdiv_ctrl2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+	regval |= SM((antdiv_ctrl1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB);
+	regval |= SM((antdiv_ctrl1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
+	REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
+
+	regval = REG_READ(ah, AR_PHY_CCK_DETECT);
+	regval &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+	regval |= SM((antdiv_ctrl1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+	REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
+}
+
 static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
 				    struct ath_spec_scan *param)
 {
@@ -630,6 +689,7 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
 
 	ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
 	ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
+	ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity;
 	ops->spectral_scan_config = ar9002_hw_spectral_scan_config;
 	ops->spectral_scan_trigger = ar9002_hw_spectral_scan_trigger;
 	ops->spectral_scan_wait = ar9002_hw_spectral_scan_wait;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
index f9eb2c3..6314ae2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
@@ -317,13 +317,15 @@
 #define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S    29
 #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB     0x40000000
 #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S   30
-#define AR_PHY_9285_ANT_DIV_LNA1            2
-#define AR_PHY_9285_ANT_DIV_LNA2            1
-#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2  3
-#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
 #define AR_PHY_9285_ANT_DIV_GAINTB_0        0
 #define AR_PHY_9285_ANT_DIV_GAINTB_1        1
 
+#define ATH_BT_COEX_ANTDIV_CONTROL1_ENABLE  0x0b
+#define ATH_BT_COEX_ANTDIV_CONTROL2_ENABLE  0x09
+#define ATH_BT_COEX_ANTDIV_CONTROL1_FIXED_A 0x04
+#define ATH_BT_COEX_ANTDIV_CONTROL2_FIXED_A 0x09
+#define ATH_BT_COEX_ANT_DIV_SWITCH_COM      0x66666666
+
 #define AR_PHY_EXT_CCA0             0x99b8
 #define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
 #define AR_PHY_EXT_CCA0_THRESH62_S  0
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index d105e43..abdc7ee 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3541,13 +3541,12 @@ static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is2ghz)
 	return le16_to_cpu(ar9003_modal_header(ah, is2ghz)->switchcomspdt);
 }
 
-
-static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
+u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
 {
 	return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon);
 }
 
-static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
+u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
 {
 	return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon2);
 }
@@ -3561,6 +3560,7 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, int chain,
 
 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 {
+	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	int chain;
 	u32 regval, value, gpio;
@@ -3614,6 +3614,11 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 	}
 
 	value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
+	if (AR_SREV_9485(ah) && common->bt_ant_diversity) {
+		regval &= ~AR_SWITCH_TABLE_COM2_ALL;
+		regval |= ah->config.ant_ctrl_comm2g_switch_enable;
+
+	}
 	REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
 
 	if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
@@ -3645,8 +3650,11 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 		regval &= (~AR_PHY_ANT_DIV_LNADIV);
 		regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
 
+		if (AR_SREV_9485(ah) && common->bt_ant_diversity)
+			regval |= AR_ANT_DIV_ENABLE;
+
 		if (AR_SREV_9565(ah)) {
-			if (ah->shared_chain_lnadiv) {
+			if (common->bt_ant_diversity) {
 				regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S);
 			} else {
 				regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S);
@@ -3656,10 +3664,14 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 
 		REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
 
-		/*enable fast_div */
+		/* enable fast_div */
 		regval = REG_READ(ah, AR_PHY_CCK_DETECT);
 		regval &= (~AR_FAST_DIV_ENABLE);
 		regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
+
+		if (AR_SREV_9485(ah) && common->bt_ant_diversity)
+			regval |= AR_FAST_DIV_ENABLE;
+
 		REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
 
 		if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
@@ -3673,9 +3685,9 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 				     AR_PHY_ANT_DIV_ALT_GAINTB |
 				     AR_PHY_ANT_DIV_MAIN_GAINTB));
 			/* by default use LNA1 for the main antenna */
-			regval |= (AR_PHY_ANT_DIV_LNA1 <<
+			regval |= (ATH_ANT_DIV_COMB_LNA1 <<
 				   AR_PHY_ANT_DIV_MAIN_LNACONF_S);
-			regval |= (AR_PHY_ANT_DIV_LNA2 <<
+			regval |= (ATH_ANT_DIV_COMB_LNA2 <<
 				   AR_PHY_ANT_DIV_ALT_LNACONF_S);
 			REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
 		}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index 874f657..75d4fb41 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -334,6 +334,8 @@ struct ar9300_eeprom {
 
 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
+u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz);
+u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz);
 
 u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz);
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 1f694ab..4898829 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -632,6 +632,22 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
 
 	REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
 		    AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+	if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+		REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
+			  AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
+
+		if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+				   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
+			ah->enabled_cals |= TX_IQ_CAL;
+		else
+			ah->enabled_cals &= ~TX_IQ_CAL;
+
+		if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+			ah->enabled_cals |= TX_CL_CAL;
+		else
+			ah->enabled_cals &= ~TX_CL_CAL;
+	}
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -814,29 +830,12 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
 	if (chan->channel == 2484)
 		ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
 
-	if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
-		REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
-			  AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
-
 	ah->modes_index = modesIndex;
 	ar9003_hw_override_ini(ah);
 	ar9003_hw_set_channel_regs(ah, chan);
 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
 	ath9k_hw_apply_txpower(ah, chan, false);
 
-	if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
-		if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
-				   AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
-			ah->enabled_cals |= TX_IQ_CAL;
-		else
-			ah->enabled_cals &= ~TX_IQ_CAL;
-
-		if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
-			ah->enabled_cals |= TX_CL_CAL;
-		else
-			ah->enabled_cals &= ~TX_CL_CAL;
-	}
-
 	return 0;
 }
 
@@ -1413,62 +1412,104 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
 	REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
 }
 
-static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah,
-						  bool enable)
+static void ar9003_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
 {
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	u8 ant_div_ctl1;
 	u32 regval;
 
-	if (!AR_SREV_9565(ah))
+	if (!AR_SREV_9485(ah) && !AR_SREV_9565(ah))
 		return;
 
-	ah->shared_chain_lnadiv = enable;
+	if (AR_SREV_9485(ah)) {
+		regval = ar9003_hw_ant_ctrl_common_2_get(ah,
+						 IS_CHAN_2GHZ(ah->curchan));
+		if (enable) {
+			regval &= ~AR_SWITCH_TABLE_COM2_ALL;
+			regval |= ah->config.ant_ctrl_comm2g_switch_enable;
+		}
+		REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2,
+			      AR_SWITCH_TABLE_COM2_ALL, regval);
+	}
+
 	ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
 
+	/*
+	 * Set MAIN/ALT LNA conf.
+	 * Set MAIN/ALT gain_tb.
+	 */
 	regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
 	regval &= (~AR_ANT_DIV_CTRL_ALL);
 	regval |= (ant_div_ctl1 & 0x3f) << AR_ANT_DIV_CTRL_ALL_S;
-	regval &= ~AR_PHY_ANT_DIV_LNADIV;
-	regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
-
-	if (enable)
-		regval |= AR_ANT_DIV_ENABLE;
-
 	REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
 
-	regval = REG_READ(ah, AR_PHY_CCK_DETECT);
-	regval &= ~AR_FAST_DIV_ENABLE;
-	regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
-
-	if (enable)
-		regval |= AR_FAST_DIV_ENABLE;
-
-	REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
-
-	if (enable) {
-		REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL,
-			    (1 << AR_PHY_ANT_SW_RX_PROT_S));
-		if (ah->curchan && IS_CHAN_2GHZ(ah->curchan))
-			REG_SET_BIT(ah, AR_PHY_RESTART,
-				    AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
-		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
-			    AR_BTCOEX_WL_LNADIV_FORCE_ON);
-	} else {
-		REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE);
-		REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
-			    (1 << AR_PHY_ANT_SW_RX_PROT_S));
-		REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE);
-		REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
-			    AR_BTCOEX_WL_LNADIV_FORCE_ON);
-
+	if (AR_SREV_9485_11(ah)) {
+		/*
+		 * Enable LNA diversity.
+		 */
 		regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
-		regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF |
-			AR_PHY_ANT_DIV_ALT_LNACONF |
-			AR_PHY_ANT_DIV_MAIN_GAINTB |
-			AR_PHY_ANT_DIV_ALT_GAINTB);
-		regval |= (AR_PHY_ANT_DIV_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S);
-		regval |= (AR_PHY_ANT_DIV_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S);
+		regval &= ~AR_PHY_ANT_DIV_LNADIV;
+		regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
+		if (enable)
+			regval |= AR_ANT_DIV_ENABLE;
+
 		REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+
+		/*
+		 * Enable fast antenna diversity.
+		 */
+		regval = REG_READ(ah, AR_PHY_CCK_DETECT);
+		regval &= ~AR_FAST_DIV_ENABLE;
+		regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
+		if (enable)
+			regval |= AR_FAST_DIV_ENABLE;
+
+		REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
+
+		if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
+			regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+			regval &= (~(AR_PHY_ANT_DIV_MAIN_LNACONF |
+				     AR_PHY_ANT_DIV_ALT_LNACONF |
+				     AR_PHY_ANT_DIV_ALT_GAINTB |
+				     AR_PHY_ANT_DIV_MAIN_GAINTB));
+			/*
+			 * Set MAIN to LNA1 and ALT to LNA2 at the
+			 * beginning.
+			 */
+			regval |= (ATH_ANT_DIV_COMB_LNA1 <<
+				   AR_PHY_ANT_DIV_MAIN_LNACONF_S);
+			regval |= (ATH_ANT_DIV_COMB_LNA2 <<
+				   AR_PHY_ANT_DIV_ALT_LNACONF_S);
+			REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+		}
+	} else if (AR_SREV_9565(ah)) {
+		if (enable) {
+			REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL,
+				    (1 << AR_PHY_ANT_SW_RX_PROT_S));
+			if (ah->curchan && IS_CHAN_2GHZ(ah->curchan))
+				REG_SET_BIT(ah, AR_PHY_RESTART,
+					    AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
+			REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
+				    AR_BTCOEX_WL_LNADIV_FORCE_ON);
+		} else {
+			REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE);
+			REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
+				    (1 << AR_PHY_ANT_SW_RX_PROT_S));
+			REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE);
+			REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
+				    AR_BTCOEX_WL_LNADIV_FORCE_ON);
+
+			regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+			regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF |
+				    AR_PHY_ANT_DIV_ALT_LNACONF |
+				    AR_PHY_ANT_DIV_MAIN_GAINTB |
+				    AR_PHY_ANT_DIV_ALT_GAINTB);
+			regval |= (ATH_ANT_DIV_COMB_LNA1 <<
+				   AR_PHY_ANT_DIV_MAIN_LNACONF_S);
+			regval |= (ATH_ANT_DIV_COMB_LNA2 <<
+				   AR_PHY_ANT_DIV_ALT_LNACONF_S);
+			REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+		}
 	}
 }
 
@@ -1518,6 +1559,18 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
 
 	REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
 
+	if (AR_SREV_9462_20_OR_LATER(ah)) {
+		/*
+		 * CUS217 mix LNA mode.
+		 */
+		if (ar9003_hw_get_rx_gain_idx(ah) == 2) {
+			REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core,
+					1, regWrites);
+			REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
+					modesIndex, regWrites);
+		}
+	}
+
 	/*
 	 * For 5GHz channels requiring Fast Clock, apply
 	 * different modal values.
@@ -1528,7 +1581,11 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
 	if (AR_SREV_9565(ah))
 		REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites);
 
-	REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
+	/*
+	 * JAPAN regulatory.
+	 */
+	if (chan->channel == 2484)
+		ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
 
 	ah->modes_index = modesIndex;
 	*ini_reloaded = true;
@@ -1631,7 +1688,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 
 	ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
 	ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
-	ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv;
+	ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity;
 	ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
 	ops->spectral_scan_trigger = ar9003_hw_spectral_scan_trigger;
 	ops->spectral_scan_wait = ar9003_hw_spectral_scan_wait;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index d4d39f3..23c019d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -296,11 +296,6 @@
 #define AR_PHY_ANT_DIV_MAIN_GAINTB              0x40000000
 #define AR_PHY_ANT_DIV_MAIN_GAINTB_S            30
 
-#define AR_PHY_ANT_DIV_LNA1_MINUS_LNA2          0x0
-#define AR_PHY_ANT_DIV_LNA2                     0x1
-#define AR_PHY_ANT_DIV_LNA1                     0x2
-#define AR_PHY_ANT_DIV_LNA1_PLUS_LNA2           0x3
-
 #define AR_PHY_EXTCHN_PWRTHR1   (AR_AGC_BASE + 0x2c)
 #define AR_PHY_EXT_CHN_WIN      (AR_AGC_BASE + 0x30)
 #define AR_PHY_20_40_DET_THR    (AR_AGC_BASE + 0x34)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c1224b5..c497d52 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -585,19 +585,14 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
 #define ATH_ANT_DIV_COMB_MAX_COUNT 100
 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50
 
 #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
 #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
 #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2
 #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2
 
-enum ath9k_ant_div_comb_lna_conf {
-	ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
-	ATH_ANT_DIV_COMB_LNA2,
-	ATH_ANT_DIV_COMB_LNA1,
-	ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
-};
-
 struct ath_ant_comb {
 	u16 count;
 	u16 total_pkt_count;
@@ -614,27 +609,35 @@ struct ath_ant_comb {
 	int rssi_first;
 	int rssi_second;
 	int rssi_third;
+	int ant_ratio;
+	int ant_ratio2;
 	bool alt_good;
 	int quick_scan_cnt;
-	int main_conf;
+	enum ath9k_ant_div_comb_lna_conf main_conf;
 	enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf;
 	enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf;
 	bool first_ratio;
 	bool second_ratio;
 	unsigned long scan_start_time;
+
+	/*
+	 * Card-specific config values.
+	 */
+	int low_rssi_thresh;
+	int fast_div_bias;
 };
 
 void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
-void ath_ant_comb_update(struct ath_softc *sc);
 
 /********************/
 /* Main driver core */
 /********************/
 
-#define ATH9K_PCI_CUS198 0x0001
-#define ATH9K_PCI_CUS230 0x0002
-#define ATH9K_PCI_CUS217 0x0004
-#define ATH9K_PCI_WOW    0x0008
+#define ATH9K_PCI_CUS198     0x0001
+#define ATH9K_PCI_CUS230     0x0002
+#define ATH9K_PCI_CUS217     0x0004
+#define ATH9K_PCI_WOW        0x0008
+#define ATH9K_PCI_BT_ANT_DIV 0x0010
 
 /*
  * Default cache line size, in bytes.
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 87454f6..a155190 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -270,25 +270,27 @@ static const struct file_operations fops_ani = {
 	.llseek = default_llseek,
 };
 
-static ssize_t read_file_ant_diversity(struct file *file, char __user *user_buf,
-				       size_t count, loff_t *ppos)
+static ssize_t read_file_bt_ant_diversity(struct file *file,
+					  char __user *user_buf,
+					  size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	char buf[32];
 	unsigned int len;
 
-	len = sprintf(buf, "%d\n", common->antenna_diversity);
+	len = sprintf(buf, "%d\n", common->bt_ant_diversity);
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
-static ssize_t write_file_ant_diversity(struct file *file,
-					const char __user *user_buf,
-					size_t count, loff_t *ppos)
+static ssize_t write_file_bt_ant_diversity(struct file *file,
+					   const char __user *user_buf,
+					   size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	unsigned long antenna_diversity;
+	struct ath9k_hw_capabilities *pCap = &sc->sc_ah->caps;
+	unsigned long bt_ant_diversity;
 	char buf[32];
 	ssize_t len;
 
@@ -296,26 +298,145 @@ static ssize_t write_file_ant_diversity(struct file *file,
 	if (copy_from_user(buf, user_buf, len))
 		return -EFAULT;
 
-	if (!AR_SREV_9565(sc->sc_ah))
+	if (!(pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV))
 		goto exit;
 
 	buf[len] = '\0';
-	if (kstrtoul(buf, 0, &antenna_diversity))
+	if (kstrtoul(buf, 0, &bt_ant_diversity))
 		return -EINVAL;
 
-	common->antenna_diversity = !!antenna_diversity;
+	common->bt_ant_diversity = !!bt_ant_diversity;
 	ath9k_ps_wakeup(sc);
-	ath_ant_comb_update(sc);
-	ath_dbg(common, CONFIG, "Antenna diversity: %d\n",
-		common->antenna_diversity);
+	ath9k_hw_set_bt_ant_diversity(sc->sc_ah, common->bt_ant_diversity);
+	ath_dbg(common, CONFIG, "Enable WLAN/BT RX Antenna diversity: %d\n",
+		common->bt_ant_diversity);
 	ath9k_ps_restore(sc);
 exit:
 	return count;
 }
 
-static const struct file_operations fops_ant_diversity = {
-	.read = read_file_ant_diversity,
-	.write = write_file_ant_diversity,
+static const struct file_operations fops_bt_ant_diversity = {
+	.read = read_file_bt_ant_diversity,
+	.write = write_file_bt_ant_diversity,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+void ath9k_debug_stat_ant(struct ath_softc *sc,
+			  struct ath_hw_antcomb_conf *div_ant_conf,
+			  int main_rssi_avg, int alt_rssi_avg)
+{
+	struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN];
+	struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT];
+
+	as_main->lna_attempt_cnt[div_ant_conf->main_lna_conf]++;
+	as_alt->lna_attempt_cnt[div_ant_conf->alt_lna_conf]++;
+
+	as_main->rssi_avg = main_rssi_avg;
+	as_alt->rssi_avg = alt_rssi_avg;
+}
+
+static ssize_t read_file_antenna_diversity(struct file *file,
+					   char __user *user_buf,
+					   size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN];
+	struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT];
+	struct ath_hw_antcomb_conf div_ant_conf;
+	unsigned int len = 0, size = 1024;
+	ssize_t retval = 0;
+	char *buf;
+	char *lna_conf_str[4] = {"LNA1_MINUS_LNA2",
+				 "LNA2",
+				 "LNA1",
+				 "LNA1_PLUS_LNA2"};
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) {
+		len += snprintf(buf + len, size - len, "%s\n",
+				"Antenna Diversity Combining is disabled");
+		goto exit;
+	}
+
+	ath9k_ps_wakeup(sc);
+	ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+	len += snprintf(buf + len, size - len, "Current MAIN config : %s\n",
+			lna_conf_str[div_ant_conf.main_lna_conf]);
+	len += snprintf(buf + len, size - len, "Current ALT config  : %s\n",
+			lna_conf_str[div_ant_conf.alt_lna_conf]);
+	len += snprintf(buf + len, size - len, "Average MAIN RSSI   : %d\n",
+			as_main->rssi_avg);
+	len += snprintf(buf + len, size - len, "Average ALT RSSI    : %d\n\n",
+			as_alt->rssi_avg);
+	ath9k_ps_restore(sc);
+
+	len += snprintf(buf + len, size - len, "Packet Receive Cnt:\n");
+	len += snprintf(buf + len, size - len, "-------------------\n");
+
+	len += snprintf(buf + len, size - len, "%30s%15s\n",
+			"MAIN", "ALT");
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"TOTAL COUNT",
+			as_main->recv_cnt,
+			as_alt->recv_cnt);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA2",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1 + LNA2",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1 - LNA2",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+
+	len += snprintf(buf + len, size - len, "\nLNA Config Attempts:\n");
+	len += snprintf(buf + len, size - len, "--------------------\n");
+
+	len += snprintf(buf + len, size - len, "%30s%15s\n",
+			"MAIN", "ALT");
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA2",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1 + LNA2",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1 - LNA2",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+
+exit:
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static const struct file_operations fops_antenna_diversity = {
+	.read = read_file_antenna_diversity,
 	.open = simple_open,
 	.owner = THIS_MODULE,
 	.llseek = default_llseek,
@@ -1814,8 +1935,10 @@ int ath9k_init_debug(struct ath_hw *ah)
 			   sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
 	debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
 			   sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
-	debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
-			    sc->debug.debugfs_phy, sc, &fops_ant_diversity);
+	debugfs_create_file("bt_ant_diversity", S_IRUSR | S_IWUSR,
+			    sc->debug.debugfs_phy, sc, &fops_bt_ant_diversity);
+	debugfs_create_file("antenna_diversity", S_IRUSR,
+			    sc->debug.debugfs_phy, sc, &fops_antenna_diversity);
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
 	debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_btcoex);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index fc67919..01c5c6a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -28,9 +28,13 @@ struct fft_sample_tlv;
 #ifdef CONFIG_ATH9K_DEBUGFS
 #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
 #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
+#define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++
+#define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++;
 #else
 #define TX_STAT_INC(q, c) do { } while (0)
 #define RESET_STAT_INC(sc, type) do { } while (0)
+#define ANT_STAT_INC(i, c) do { } while (0)
+#define ANT_LNA_INC(i, c) do { } while (0)
 #endif
 
 enum ath_reset_type {
@@ -243,11 +247,22 @@ struct ath_rx_stats {
 	u32 rx_spectral;
 };
 
+#define ANT_MAIN 0
+#define ANT_ALT  1
+
+struct ath_antenna_stats {
+	u32 recv_cnt;
+	u32 rssi_avg;
+	u32 lna_recv_cnt[4];
+	u32 lna_attempt_cnt[4];
+};
+
 struct ath_stats {
 	struct ath_interrupt_stats istats;
 	struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
 	struct ath_rx_stats rxstats;
 	struct ath_dfs_stats dfs_stats;
+	struct ath_antenna_stats ant_stats[2];
 	u32 reset[__RESET_TYPE_MAX];
 };
 
@@ -281,10 +296,11 @@ void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_sta *sta,
 			      struct dentry *dir);
-
 void ath_debug_send_fft_sample(struct ath_softc *sc,
 			       struct fft_sample_tlv *fft_sample);
-
+void ath9k_debug_stat_ant(struct ath_softc *sc,
+			  struct ath_hw_antcomb_conf *div_ant_conf,
+			  int main_rssi_avg, int alt_rssi_avg);
 #else
 
 #define RX_STAT_INC(c) /* NOP */
@@ -297,12 +313,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
 static inline void ath9k_deinit_debug(struct ath_softc *sc)
 {
 }
-
 static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 					    enum ath9k_int status)
 {
 }
-
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     struct ath_buf *bf,
 				     struct ath_tx_status *ts,
@@ -310,11 +324,16 @@ static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     unsigned int flags)
 {
 }
-
 static inline void ath_debug_stat_rx(struct ath_softc *sc,
 				     struct ath_rx_status *rs)
 {
 }
+static inline void ath9k_debug_stat_ant(struct ath_softc *sc,
+					struct ath_hw_antcomb_conf *div_ant_conf,
+					int main_rssi_avg, int alt_rssi_avg)
+{
+
+}
 
 #endif /* CONFIG_ATH9K_DEBUGFS */
 
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index c2bfd748..9ea8e4b 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -812,6 +812,7 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
 static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 					 struct ath9k_channel *chan)
 {
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct modal_eep_4k_header *pModal;
 	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
 	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
@@ -858,6 +859,24 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 
 		REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
 		regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+
+		if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
+			/*
+			 * If diversity combining is enabled,
+			 * set MAIN to LNA1 and ALT to LNA2 initially.
+			 */
+			regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+			regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
+				     AR_PHY_9285_ANT_DIV_ALT_LNACONF));
+
+			regVal |= (ATH_ANT_DIV_COMB_LNA1 <<
+				   AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S);
+			regVal |= (ATH_ANT_DIV_COMB_LNA2 <<
+				   AR_PHY_9285_ANT_DIV_ALT_LNACONF_S);
+			regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS));
+			regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S);
+			REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
+		}
 	}
 
 	if (pModal->version >= 2) {
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 14b7011..a78d48c 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -78,11 +78,10 @@ static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
 	ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf);
 }
 
-static inline void ath9k_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah,
-							bool enable)
+static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
 {
-	if (ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv)
-		ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv(ah, enable);
+	if (ath9k_hw_ops(ah)->set_bt_ant_diversity)
+		ath9k_hw_ops(ah)->set_bt_ant_diversity(ah, enable);
 }
 
 /* Private hardware call ops */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 4ca0cb0..151443b 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1496,16 +1496,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 				    struct ath9k_channel *chan)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	bool band_switch = false, mode_diff = false;
+	u8 ini_reloaded = 0;
 	u32 qnum;
 	int r;
-	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
-	bool band_switch, mode_diff;
-	u8 ini_reloaded;
 
-	band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) !=
-		      (ah->curchan->channelFlags & (CHANNEL_2GHZ |
-						    CHANNEL_5GHZ));
-	mode_diff = (chan->chanmode != ah->curchan->chanmode);
+	if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
+		u32 cur = ah->curchan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ);
+		u32 new = chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ);
+		band_switch = (cur != new);
+		mode_diff = (chan->chanmode != ah->curchan->chanmode);
+	}
 
 	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
 		if (ath9k_hw_numtxpending(ah, qnum)) {
@@ -1520,11 +1522,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 		return false;
 	}
 
-	if (edma && (band_switch || mode_diff)) {
+	if (band_switch || mode_diff) {
 		ath9k_hw_mark_phy_inactive(ah);
 		udelay(5);
 
-		ath9k_hw_init_pll(ah, NULL);
+		if (band_switch)
+			ath9k_hw_init_pll(ah, chan);
 
 		if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
 			ath_err(common, "Failed to do fast channel change\n");
@@ -1541,22 +1544,21 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 	}
 	ath9k_hw_set_clockrate(ah);
 	ath9k_hw_apply_txpower(ah, chan, false);
-	ath9k_hw_rfbus_done(ah);
 
 	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
 		ath9k_hw_set_delta_slope(ah, chan);
 
 	ath9k_hw_spur_mitigate_freq(ah, chan);
 
-	if (edma && (band_switch || mode_diff)) {
-		ah->ah_flags |= AH_FASTCC;
-		if (band_switch || ini_reloaded)
-			ah->eep_ops->set_board_values(ah, chan);
+	if (band_switch || ini_reloaded)
+		ah->eep_ops->set_board_values(ah, chan);
 
-		ath9k_hw_init_bb(ah, chan);
+	ath9k_hw_init_bb(ah, chan);
+	ath9k_hw_rfbus_done(ah);
 
-		if (band_switch || ini_reloaded)
-			ath9k_hw_init_cal(ah, chan);
+	if (band_switch || ini_reloaded) {
+		ah->ah_flags |= AH_FASTCC;
+		ath9k_hw_init_cal(ah, chan);
 		ah->ah_flags &= ~AH_FASTCC;
 	}
 
@@ -1778,16 +1780,11 @@ static void ath9k_hw_init_desc(struct ath_hw *ah)
 /*
  * Fast channel change:
  * (Change synthesizer based on channel freq without resetting chip)
- *
- * Don't do FCC when
- *   - Flag is not set
- *   - Chip is just coming out of full sleep
- *   - Channel to be set is same as current channel
- *   - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
  */
 static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	int ret;
 
 	if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
@@ -1806,9 +1803,21 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
 	    (CHANNEL_HALF | CHANNEL_QUARTER))
 		goto fail;
 
-	if ((chan->channelFlags & CHANNEL_ALL) !=
-	    (ah->curchan->channelFlags & CHANNEL_ALL))
-		goto fail;
+	/*
+	 * If cross-band fcc is not supoprted, bail out if
+	 * either channelFlags or chanmode differ.
+	 *
+	 * chanmode will be different if the HT operating mode
+	 * changes because of CSA.
+	 */
+	if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH)) {
+		if ((chan->channelFlags & CHANNEL_ALL) !=
+		    (ah->curchan->channelFlags & CHANNEL_ALL))
+			goto fail;
+
+		if (chan->chanmode != ah->curchan->chanmode)
+			goto fail;
+	}
 
 	if (!ath9k_hw_check_alive(ah))
 		goto fail;
@@ -2047,7 +2056,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	ath9k_hw_apply_gpio_override(ah);
 
-	if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv)
+	if (AR_SREV_9565(ah) && common->bt_ant_diversity)
 		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
 
 	return 0;
@@ -2504,7 +2513,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	else
 		pCap->rts_aggr_limit = (8 * 1024);
 
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+#ifdef CONFIG_ATH9K_RFKILL
 	ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
 	if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
 		ah->rfkill_gpio =
@@ -2550,34 +2559,28 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
 		pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
 
-	if (AR_SREV_9285(ah))
+	if (AR_SREV_9285(ah)) {
 		if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) {
 			ant_div_ctl1 =
 				ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
-			if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
+			if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) {
 				pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+				ath_info(common, "Enable LNA combining\n");
+			}
 		}
+	}
+
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
 		if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
 			pCap->hw_caps |= ATH9K_HW_CAP_APM;
 	}
 
-
 	if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
 		ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
-		/*
-		 * enable the diversity-combining algorithm only when
-		 * both enable_lna_div and enable_fast_div are set
-		 *		Table for Diversity
-		 * ant_div_alt_lnaconf		bit 0-1
-		 * ant_div_main_lnaconf		bit 2-3
-		 * ant_div_alt_gaintb		bit 4
-		 * ant_div_main_gaintb		bit 5
-		 * enable_ant_div_lnadiv	bit 6
-		 * enable_ant_fast_div		bit 7
-		 */
-		if ((ant_div_ctl1 >> 0x6) == 0x3)
+		if ((ant_div_ctl1 >> 0x6) == 0x3) {
 			pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+			ath_info(common, "Enable LNA combining\n");
+		}
 	}
 
 	if (ath9k_hw_dfs_tested(ah))
@@ -2610,6 +2613,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	    ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
 			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
 
+	/*
+	 * Fast channel change across bands is available
+	 * only for AR9462 and AR9565.
+	 */
+	if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+		pCap->hw_caps |= ATH9K_HW_CAP_FCC_BAND_SWITCH;
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index cd74b3a..38f461c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -247,6 +247,8 @@ enum ath9k_hw_caps {
 	ATH9K_HW_CAP_DFS			= BIT(16),
 	ATH9K_HW_WOW_DEVICE_CAPABLE		= BIT(17),
 	ATH9K_HW_CAP_PAPRD			= BIT(18),
+	ATH9K_HW_CAP_FCC_BAND_SWITCH		= BIT(19),
+	ATH9K_HW_CAP_BT_ANT_DIV			= BIT(20),
 };
 
 /*
@@ -310,6 +312,7 @@ struct ath9k_ops_config {
 
 	/* Platform specific config */
 	u32 xlna_gpio;
+	u32 ant_ctrl_comm2g_switch_enable;
 	bool xatten_margin_cfg;
 };
 
@@ -716,7 +719,7 @@ struct ath_hw_ops {
 			struct ath_hw_antcomb_conf *antconf);
 	void (*antdiv_comb_conf_set)(struct ath_hw *ah,
 			struct ath_hw_antcomb_conf *antconf);
-	void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable);
+	void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable);
 	void (*spectral_scan_config)(struct ath_hw *ah,
 				     struct ath_spec_scan *param);
 	void (*spectral_scan_trigger)(struct ath_hw *ah);
@@ -765,7 +768,6 @@ struct ath_hw {
 	bool aspm_enabled;
 	bool is_monitoring;
 	bool need_an_top2_fixup;
-	bool shared_chain_lnadiv;
 	u16 tx_trig_level;
 
 	u32 nf_regs[6];
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 16f8b20..4afe30e 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -53,9 +53,9 @@ static int ath9k_btcoex_enable;
 module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
 MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
 
-static int ath9k_enable_diversity;
-module_param_named(enable_diversity, ath9k_enable_diversity, int, 0444);
-MODULE_PARM_DESC(enable_diversity, "Enable Antenna diversity for AR9565");
+static int ath9k_bt_ant_diversity;
+module_param_named(bt_ant_diversity, ath9k_bt_ant_diversity, int, 0444);
+MODULE_PARM_DESC(bt_ant_diversity, "Enable WLAN/BT RX antenna diversity");
 
 bool is_ath9k_unloaded;
 /* We use the hw_value as an index into our private channel structure */
@@ -516,6 +516,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
 static void ath9k_init_platform(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_common *common = ath9k_hw_common(ah);
 
 	if (common->bus_ops->ath_bus_type != ATH_PCI)
@@ -525,12 +526,21 @@ static void ath9k_init_platform(struct ath_softc *sc)
 			       ATH9K_PCI_CUS230)) {
 		ah->config.xlna_gpio = 9;
 		ah->config.xatten_margin_cfg = true;
+		ah->config.ant_ctrl_comm2g_switch_enable = 0x000BBB88;
+		sc->ant_comb.low_rssi_thresh = 20;
+		sc->ant_comb.fast_div_bias = 3;
 
 		ath_info(common, "Set parameters for %s\n",
 			 (sc->driver_data & ATH9K_PCI_CUS198) ?
 			 "CUS198" : "CUS230");
-	} else if (sc->driver_data & ATH9K_PCI_CUS217) {
+	}
+
+	if (sc->driver_data & ATH9K_PCI_CUS217)
 		ath_info(common, "CUS217 card detected\n");
+
+	if (sc->driver_data & ATH9K_PCI_BT_ANT_DIV) {
+		pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV;
+		ath_info(common, "Set BT/WLAN RX diversity capability\n");
 	}
 }
 
@@ -584,6 +594,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 {
 	struct ath9k_platform_data *pdata = sc->dev->platform_data;
 	struct ath_hw *ah = NULL;
+	struct ath9k_hw_capabilities *pCap;
 	struct ath_common *common;
 	int ret = 0, i;
 	int csz = 0;
@@ -600,6 +611,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 	ah->reg_ops.rmw = ath9k_reg_rmw;
 	atomic_set(&ah->intr_ref_cnt, -1);
 	sc->sc_ah = ah;
+	pCap = &ah->caps;
 
 	sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET);
 
@@ -631,11 +643,15 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 	ath9k_init_platform(sc);
 
 	/*
-	 * Enable Antenna diversity only when BTCOEX is disabled
-	 * and the user manually requests the feature.
+	 * Enable WLAN/BT RX Antenna diversity only when:
+	 *
+	 * - BTCOEX is enabled
+	 * - the user manually requests the feature.
+	 * - the HW cap is set using the platform data.
 	 */
-	if (!common->btcoex_enabled && ath9k_enable_diversity)
-		common->antenna_diversity = 1;
+	if (common->btcoex_enabled && ath9k_bt_ant_diversity &&
+	    (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV))
+		common->bt_ant_diversity = 1;
 
 	spin_lock_init(&common->cc_lock);
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1737a3e..afeab3c 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -238,9 +238,6 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
 		ath_restart_work(sc);
 	}
 
-	if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3)
-		ath_ant_comb_update(sc);
-
 	ieee80211_wake_queues(sc->hw);
 
 	return true;
@@ -2094,7 +2091,7 @@ static void ath9k_wow_add_pattern(struct ath_softc *sc,
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath9k_wow_pattern *wow_pattern = NULL;
-	struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;
+	struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
 	int mask_len;
 	s8 i = 0;
 
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index c585c9b..76e8c35 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -29,6 +29,14 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
 	{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+
+	/* AR9285 card for Asus */
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002B,
+			 PCI_VENDOR_ID_AZWAVE,
+			 0x2C37),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+
 	{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
 	{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
 	{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI   */
@@ -40,29 +48,101 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
 			 0x0032,
 			 PCI_VENDOR_ID_AZWAVE,
 			 0x2086),
-	  .driver_data = ATH9K_PCI_CUS198 },
+	  .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x0032,
 			 PCI_VENDOR_ID_AZWAVE,
 			 0x1237),
-	  .driver_data = ATH9K_PCI_CUS198 },
+	  .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x0032,
 			 PCI_VENDOR_ID_AZWAVE,
 			 0x2126),
-	  .driver_data = ATH9K_PCI_CUS198 },
+	  .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV },
 
 	/* PCI-E CUS230 */
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x0032,
 			 PCI_VENDOR_ID_AZWAVE,
 			 0x2152),
-	  .driver_data = ATH9K_PCI_CUS230 },
+	  .driver_data = ATH9K_PCI_CUS230 | ATH9K_PCI_BT_ANT_DIV },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x0032,
 			 PCI_VENDOR_ID_FOXCONN,
 			 0xE075),
-	  .driver_data = ATH9K_PCI_CUS230 },
+	  .driver_data = ATH9K_PCI_CUS230 | ATH9K_PCI_BT_ANT_DIV },
+
+	/* WB225 */
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_ATHEROS,
+			 0x3119),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_ATHEROS,
+			 0x3122),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 0x185F, /* WNC */
+			 0x3119),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 0x185F, /* WNC */
+			 0x3027),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0x4105),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0x4106),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0x410D),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0x410E),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0x410F),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0xC706),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0xC680),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_SAMSUNG,
+			 0xC708),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_LENOVO,
+			 0x3218),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0032,
+			 PCI_VENDOR_ID_LENOVO,
+			 0x3219),
+	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
 
 	{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
 	{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index 8b38030..4a1b992 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -48,4 +48,11 @@
 #define AR_PHY_PLL_CONTROL 0x16180
 #define AR_PHY_PLL_MODE 0x16184
 
+enum ath9k_ant_div_comb_lna_conf {
+	ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+	ATH_ANT_DIV_COMB_LNA2,
+	ATH_ANT_DIV_COMB_LNA1,
+	ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
+};
+
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 7eb1f4b..a3c4ca0 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1275,6 +1275,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
 }
 
 static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
+			  struct cfg80211_chan_def *chandef,
                           struct ieee80211_sta *sta, void *priv_sta)
 {
 	struct ath_softc *sc = priv;
@@ -1313,6 +1314,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
 }
 
 static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
+			    struct cfg80211_chan_def *chandef,
 			    struct ieee80211_sta *sta, void *priv_sta,
 			    u32 changed)
 {
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 9279927..52cd521 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1023,7 +1023,7 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop)
 }
 
 static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
-			     struct ath_tx_info *info, int len)
+			     struct ath_tx_info *info, int len, bool rts)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct sk_buff *skb;
@@ -1032,6 +1032,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
 	const struct ieee80211_rate *rate;
 	struct ieee80211_hdr *hdr;
 	struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+	u32 rts_thresh = sc->hw->wiphy->rts_threshold;
 	int i;
 	u8 rix = 0;
 
@@ -1054,7 +1055,17 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
 		rix = rates[i].idx;
 		info->rates[i].Tries = rates[i].count;
 
-		    if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+		/*
+		 * Handle RTS threshold for unaggregated HT frames.
+		 */
+		if (bf_isampdu(bf) && !bf_isaggr(bf) &&
+		    (rates[i].flags & IEEE80211_TX_RC_MCS) &&
+		    unlikely(rts_thresh != (u32) -1)) {
+			if (!rts_thresh || (len > rts_thresh))
+				rts = true;
+		}
+
+		if (rts || rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 			info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
 			info->flags |= ATH9K_TXDESC_RTSENA;
 		} else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
@@ -1147,6 +1158,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_buf *bf_first = NULL;
 	struct ath_tx_info info;
+	u32 rts_thresh = sc->hw->wiphy->rts_threshold;
+	bool rts = false;
 
 	memset(&info, 0, sizeof(info));
 	info.is_first = true;
@@ -1183,7 +1196,22 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
 				info.flags |= (u32) bf->bf_state.bfs_paprd <<
 					      ATH9K_TXDESC_PAPRD_S;
 
-			ath_buf_set_rate(sc, bf, &info, len);
+			/*
+			 * mac80211 doesn't handle RTS threshold for HT because
+			 * the decision has to be taken based on AMPDU length
+			 * and aggregation is done entirely inside ath9k.
+			 * Set the RTS/CTS flag for the first subframe based
+			 * on the threshold.
+			 */
+			if (aggr && (bf == bf_first) &&
+			    unlikely(rts_thresh != (u32) -1)) {
+				/*
+				 * "len" is the size of the entire AMPDU.
+				 */
+				if (!rts_thresh || (len > rts_thresh))
+					rts = true;
+			}
+			ath_buf_set_rate(sc, bf, &info, len, rts);
 		}
 
 		info.buf_addr[0] = bf->bf_buf_addr;
@@ -2168,7 +2196,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 		bf->bf_lastbf = bf;
 		ath_set_rates(vif, NULL, bf);
-		ath_buf_set_rate(sc, bf, &info, fi->framelen);
+		ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
 		duration += info.rates[0].PktDuration;
 		if (bf_tail)
 			bf_tail->bf_next = bf;
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index f891d51..990dd42a 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -11,9 +11,6 @@ wil6210-y += txrx.o
 wil6210-y += debug.o
 wil6210-$(CONFIG_WIL6210_TRACING) += trace.o
 
-ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
-	subdir-ccflags-y += -Werror
-endif
 # for tracing framework to find trace.h
 CFLAGS_trace.o := -I$(src)
 
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index ab63676..1caa319 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -51,7 +51,7 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
 			if ((i % 64) == 0 && (i != 0))
 				seq_printf(s, "\n");
 			seq_printf(s, "%s", (d->dma.status & BIT(0)) ?
-					"S" : (vring->ctx[i] ? "H" : "h"));
+					"S" : (vring->ctx[i].skb ? "H" : "h"));
 		}
 		seq_printf(s, "\n");
 	}
@@ -406,7 +406,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
 		volatile struct vring_tx_desc *d =
 				&(vring->va[dbg_txdesc_index].tx);
 		volatile u32 *u = (volatile u32 *)d;
-		struct sk_buff *skb = vring->ctx[dbg_txdesc_index];
+		struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb;
 
 		seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index);
 		seq_printf(s, "  MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 29dd1e5..717178f 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -127,6 +127,8 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
 
 	ndev->netdev_ops = &wil_netdev_ops;
 	ndev->ieee80211_ptr = wdev;
+	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 	wdev->netdev = ndev;
 
diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h
index eff1239..e59239d 100644
--- a/drivers/net/wireless/ath/wil6210/trace.h
+++ b/drivers/net/wireless/ath/wil6210/trace.h
@@ -37,36 +37,40 @@ static inline void trace_ ## name(proto) {}
 #endif /* !CONFIG_WIL6210_TRACING || defined(__CHECKER__) */
 
 DECLARE_EVENT_CLASS(wil6210_wmi,
-	TP_PROTO(u16 id, void *buf, u16 buf_len),
+	TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
 
-	TP_ARGS(id, buf, buf_len),
+	TP_ARGS(wmi, buf, buf_len),
 
 	TP_STRUCT__entry(
+		__field(u8, mid)
 		__field(u16, id)
+		__field(u32, timestamp)
 		__field(u16, buf_len)
 		__dynamic_array(u8, buf, buf_len)
 	),
 
 	TP_fast_assign(
-		__entry->id = id;
+		__entry->mid = wmi->mid;
+		__entry->id = le16_to_cpu(wmi->id);
+		__entry->timestamp = le32_to_cpu(wmi->timestamp);
 		__entry->buf_len = buf_len;
 		memcpy(__get_dynamic_array(buf), buf, buf_len);
 	),
 
 	TP_printk(
-		"id 0x%04x len %d",
-		__entry->id, __entry->buf_len
+		"MID %d id 0x%04x len %d timestamp %d",
+		__entry->mid, __entry->id, __entry->buf_len, __entry->timestamp
 	)
 );
 
 DEFINE_EVENT(wil6210_wmi, wil6210_wmi_cmd,
-	TP_PROTO(u16 id, void *buf, u16 buf_len),
-	TP_ARGS(id, buf, buf_len)
+	TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+	TP_ARGS(wmi, buf, buf_len)
 );
 
 DEFINE_EVENT(wil6210_wmi, wil6210_wmi_event,
-	TP_PROTO(u16 id, void *buf, u16 buf_len),
-	TP_ARGS(id, buf, buf_len)
+	TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+	TP_ARGS(wmi, buf, buf_len)
 );
 
 #define WIL6210_MSG_MAX (200)
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index d240b24..ea1abeb 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -18,6 +18,9 @@
 #include <net/ieee80211_radiotap.h>
 #include <linux/if_arp.h>
 #include <linux/moduleparam.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
 
 #include "wil6210.h"
 #include "wmi.h"
@@ -70,7 +73,7 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
 
 	vring->swhead = 0;
 	vring->swtail = 0;
-	vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL);
+	vring->ctx = kcalloc(vring->size, sizeof(vring->ctx[0]), GFP_KERNEL);
 	if (!vring->ctx) {
 		vring->va = NULL;
 		return -ENOMEM;
@@ -108,39 +111,39 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
 
 	while (!wil_vring_is_empty(vring)) {
 		dma_addr_t pa;
-		struct sk_buff *skb;
 		u16 dmalen;
+		struct wil_ctx *ctx;
 
 		if (tx) {
 			struct vring_tx_desc dd, *d = &dd;
 			volatile struct vring_tx_desc *_d =
 					&vring->va[vring->swtail].tx;
 
+			ctx = &vring->ctx[vring->swtail];
 			*d = *_d;
 			pa = wil_desc_addr(&d->dma.addr);
 			dmalen = le16_to_cpu(d->dma.length);
-			skb = vring->ctx[vring->swtail];
-			if (skb) {
-				dma_unmap_single(dev, pa, dmalen,
-						 DMA_TO_DEVICE);
-				dev_kfree_skb_any(skb);
-				vring->ctx[vring->swtail] = NULL;
-			} else {
+			if (vring->ctx[vring->swtail].mapped_as_page) {
 				dma_unmap_page(dev, pa, dmalen,
 					       DMA_TO_DEVICE);
+			} else {
+				dma_unmap_single(dev, pa, dmalen,
+						 DMA_TO_DEVICE);
 			}
+			if (ctx->skb)
+				dev_kfree_skb_any(ctx->skb);
 			vring->swtail = wil_vring_next_tail(vring);
 		} else { /* rx */
 			struct vring_rx_desc dd, *d = &dd;
 			volatile struct vring_rx_desc *_d =
-					&vring->va[vring->swtail].rx;
+					&vring->va[vring->swhead].rx;
 
+			ctx = &vring->ctx[vring->swhead];
 			*d = *_d;
 			pa = wil_desc_addr(&d->dma.addr);
 			dmalen = le16_to_cpu(d->dma.length);
-			skb = vring->ctx[vring->swhead];
 			dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE);
-			kfree_skb(skb);
+			kfree_skb(ctx->skb);
 			wil_vring_advance_head(vring, 1);
 		}
 	}
@@ -187,7 +190,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
 	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
 	d->dma.length = cpu_to_le16(sz);
 	*_d = *d;
-	vring->ctx[i] = skb;
+	vring->ctx[i].skb = skb;
 
 	return 0;
 }
@@ -352,11 +355,11 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
 		return NULL;
 	}
 
-	skb = vring->ctx[vring->swhead];
+	skb = vring->ctx[vring->swhead].skb;
 	d = wil_skb_rxdesc(skb);
 	*d = *_d;
 	pa = wil_desc_addr(&d->dma.addr);
-	vring->ctx[vring->swhead] = NULL;
+	vring->ctx[vring->swhead].skb = NULL;
 	wil_vring_advance_head(vring, 1);
 
 	dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
@@ -407,6 +410,21 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
 		return NULL;
 	}
 
+	/* L4 IDENT is on when HW calculated checksum, check status
+	 * and in case of error drop the packet
+	 * higher stack layers will handle retransmission (if required)
+	 */
+	if (d->dma.status & RX_DMA_STATUS_L4_IDENT) {
+		/* L4 protocol identified, csum calculated */
+		if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		} else {
+			wil_err(wil, "Incorrect checksum reported\n");
+			kfree_skb(skb);
+			return NULL;
+		}
+	}
+
 	ds_bits = wil_rxdesc_ds_bits(d);
 	if (ds_bits == 1) {
 		/*
@@ -646,6 +664,53 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len,
 	return 0;
 }
 
+static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil,
+				struct vring_tx_desc *d,
+				struct sk_buff *skb)
+{
+	int protocol;
+
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return 0;
+
+	switch (skb->protocol) {
+	case cpu_to_be16(ETH_P_IP):
+		protocol = ip_hdr(skb)->protocol;
+		break;
+	case cpu_to_be16(ETH_P_IPV6):
+		protocol = ipv6_hdr(skb)->nexthdr;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (protocol) {
+	case IPPROTO_TCP:
+		d->dma.d0 |= (2 << DMA_CFG_DESC_TX_0_L4_TYPE_POS);
+		/* L4 header len: TCP header length */
+		d->dma.d0 |=
+		(tcp_hdrlen(skb) & DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+		break;
+	case IPPROTO_UDP:
+		/* L4 header len: UDP header length */
+		d->dma.d0 |=
+		(sizeof(struct udphdr) & DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	d->dma.ip_length = skb_network_header_len(skb);
+	d->dma.b11 = ETH_HLEN; /* MAC header length */
+	d->dma.b11 |= BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
+	/* Enable TCP/UDP checksum */
+	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS);
+	/* Calculate pseudo-header */
+	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS);
+
+	return 0;
+}
+
 static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 			struct sk_buff *skb)
 {
@@ -655,7 +720,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	u32 swhead = vring->swhead;
 	int avail = wil_vring_avail_tx(vring);
 	int nr_frags = skb_shinfo(skb)->nr_frags;
-	uint f;
+	uint f = 0;
 	int vring_index = vring - wil->vring_tx;
 	uint i = swhead;
 	dma_addr_t pa;
@@ -686,13 +751,20 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 		return -EINVAL;
 	/* 1-st segment */
 	wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index);
+	/* Process TCP/UDP checksum offloading */
+	if (wil_tx_desc_offload_cksum_set(wil, d, skb)) {
+		wil_err(wil, "VRING #%d Failed to set cksum, drop packet\n",
+			vring_index);
+		goto dma_error;
+	}
+
 	d->mac.d[2] |= ((nr_frags + 1) <<
 		       MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
 	if (nr_frags)
 		*_d = *d;
 
 	/* middle segments */
-	for (f = 0; f < nr_frags; f++) {
+	for (; f < nr_frags; f++) {
 		const struct skb_frag_struct *frag =
 				&skb_shinfo(skb)->frags[f];
 		int len = skb_frag_size(frag);
@@ -703,7 +775,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 		if (unlikely(dma_mapping_error(dev, pa)))
 			goto dma_error;
 		wil_tx_desc_map(d, pa, len, vring_index);
-		vring->ctx[i] = NULL;
+		vring->ctx[i].mapped_as_page = 1;
 		*_d = *d;
 	}
 	/* for the last seg only */
@@ -712,6 +784,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
 	*_d = *d;
 
+	/* hold reference to skb
+	 * to prevent skb release before accounting
+	 * in case of immediate "tx done"
+	 */
+	vring->ctx[i].skb = skb_get(skb);
+
 	wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
 			  (const void *)d, sizeof(*d), false);
 
@@ -720,29 +798,31 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
 	trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags);
 	iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
-	/* hold reference to skb
-	 * to prevent skb release before accounting
-	 * in case of immediate "tx done"
-	 */
-	vring->ctx[i] = skb_get(skb);
 
 	return 0;
  dma_error:
 	/* unmap what we have mapped */
-	/* Note: increment @f to operate with positive index */
-	for (f++; f > 0; f--) {
+	nr_frags = f + 1; /* frags mapped + one for skb head */
+	for (f = 0; f < nr_frags; f++) {
 		u16 dmalen;
+		struct wil_ctx *ctx;
 
 		i = (swhead + f) % vring->size;
+		ctx = &vring->ctx[i];
 		_d = &(vring->va[i].tx);
 		*d = *_d;
 		_d->dma.status = TX_DMA_STATUS_DU;
 		pa = wil_desc_addr(&d->dma.addr);
 		dmalen = le16_to_cpu(d->dma.length);
-		if (vring->ctx[i])
-			dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
-		else
+		if (ctx->mapped_as_page)
 			dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
+		else
+			dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
+
+		if (ctx->skb)
+			dev_kfree_skb_any(ctx->skb);
+
+		memset(ctx, 0, sizeof(*ctx));
 	}
 
 	return -EINVAL;
@@ -821,8 +901,9 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
 					      &vring->va[vring->swtail].tx;
 		struct vring_tx_desc dd, *d = &dd;
 		dma_addr_t pa;
-		struct sk_buff *skb;
 		u16 dmalen;
+		struct wil_ctx *ctx = &vring->ctx[vring->swtail];
+		struct sk_buff *skb = ctx->skb;
 
 		*d = *_d;
 
@@ -840,7 +921,11 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
 				  (const void *)d, sizeof(*d), false);
 
 		pa = wil_desc_addr(&d->dma.addr);
-		skb = vring->ctx[vring->swtail];
+		if (ctx->mapped_as_page)
+			dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
+		else
+			dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
+
 		if (skb) {
 			if (d->dma.error == 0) {
 				ndev->stats.tx_packets++;
@@ -849,16 +934,15 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
 				ndev->stats.tx_errors++;
 			}
 
-			dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
 			dev_kfree_skb_any(skb);
-			vring->ctx[vring->swtail] = NULL;
-		} else {
-			dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
 		}
-		d->dma.addr.addr_low = 0;
-		d->dma.addr.addr_high = 0;
-		d->dma.length = 0;
-		d->dma.status = TX_DMA_STATUS_DU;
+		memset(ctx, 0, sizeof(*ctx));
+		/*
+		 * There is no need to touch HW descriptor:
+		 * - ststus bit TX_DMA_STATUS_DU is set by design,
+		 *   so hardware will not try to process this desc.,
+		 * - rest of descriptor will be initialized on Tx.
+		 */
 		vring->swtail = wil_vring_next_tail(vring);
 		done++;
 	}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 859aea6..b382827 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -235,7 +235,16 @@ struct vring_tx_mac {
 
 #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30
 #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2
-#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000
+#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 /* L4 type: 0-UDP, 2-TCP */
+
+
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS 0
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_LEN 7
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_MSK 0x7F /* MAC hdr len */
+
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS 7
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_LEN 1
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_MSK 0x80 /* 1-IPv4, 0-IPv6 */
 
 
 #define TX_DMA_STATUS_DU         BIT(0)
@@ -334,8 +343,17 @@ struct vring_rx_mac {
 
 #define RX_DMA_D0_CMD_DMA_IT     BIT(10)
 
+/* Error field, offload bits */
+#define RX_DMA_ERROR_L3_ERR   BIT(4)
+#define RX_DMA_ERROR_L4_ERR   BIT(5)
+
+
+/* Status field */
 #define RX_DMA_STATUS_DU         BIT(0)
 #define RX_DMA_STATUS_ERROR      BIT(2)
+
+#define RX_DMA_STATUS_L3_IDENT   BIT(4)
+#define RX_DMA_STATUS_L4_IDENT   BIT(5)
 #define RX_DMA_STATUS_PHY_INFO   BIT(6)
 
 struct vring_rx_dma {
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 44fdab5..c4a5163 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -156,11 +156,22 @@ struct wil6210_mbox_hdr {
 /* max. value for wil6210_mbox_hdr.len */
 #define MAX_MBOXITEM_SIZE   (240)
 
+/**
+ * struct wil6210_mbox_hdr_wmi - WMI header
+ *
+ * @mid: MAC ID
+ *	00 - default, created by FW
+ *	01..0f - WiFi ports, driver to create
+ *	10..fe - debug
+ *	ff - broadcast
+ * @id: command/event ID
+ * @timestamp: FW fills for events, free-running msec timer
+ */
 struct wil6210_mbox_hdr_wmi {
-	u8 reserved0[2];
+	u8 mid;
+	u8 reserved;
 	__le16 id;
-	__le16 info1; /* bits [0..3] - device_id, rest - unused */
-	u8 reserved1[2];
+	__le32 timestamp;
 } __packed;
 
 struct pending_wmi_event {
@@ -172,6 +183,14 @@ struct pending_wmi_event {
 	} __packed event;
 };
 
+/**
+ * struct wil_ctx - software context for Vring descriptor
+ */
+struct wil_ctx {
+	struct sk_buff *skb;
+	u8 mapped_as_page:1;
+};
+
 union vring_desc;
 
 struct vring {
@@ -181,7 +200,7 @@ struct vring {
 	u32 swtail;
 	u32 swhead;
 	u32 hwtail; /* write here to inform hw */
-	void **ctx; /* void *ctx[size] - software context */
+	struct wil_ctx *ctx; /* ctx[size] - software context */
 };
 
 enum { /* for wil6210_priv.status */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index dc8059a..5220f15 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -172,8 +172,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 			.len = cpu_to_le16(sizeof(cmd.wmi) + len),
 		},
 		.wmi = {
+			.mid = 0,
 			.id = cpu_to_le16(cmdid),
-			.info1 = 0,
 		},
 	};
 	struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
@@ -248,7 +248,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 	iowrite32(r->head = next_head, wil->csr + HOST_MBOX +
 		  offsetof(struct wil6210_mbox_ctl, tx.head));
 
-	trace_wil6210_wmi_cmd(cmdid, buf, len);
+	trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
 
 	/* interrupt to FW */
 	iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT);
@@ -640,9 +640,13 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
 			    hdr.flags);
 		if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
 		    (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
-			u16 id = le16_to_cpu(evt->event.wmi.id);
-			wil_dbg_wmi(wil, "WMI event 0x%04x\n", id);
-			trace_wil6210_wmi_event(id, &evt->event.wmi, len);
+			struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
+			u16 id = le16_to_cpu(wmi->id);
+			u32 tstamp = le32_to_cpu(wmi->timestamp);
+			wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
+				    id, wmi->mid, tstamp);
+			trace_wil6210_wmi_event(wmi, &wmi[1],
+						len - sizeof(*wmi));
 		}
 		wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
 				 &evt->event.hdr, sizeof(hdr) + len, true);
@@ -920,6 +924,12 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
 		cmd.sniffer_cfg.phy_support =
 			cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
 				    ? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
+	} else {
+		/* Initialize offload (in non-sniffer mode).
+		 * Linux IP stack always calculates IP checksum
+		 * HW always calculate TCP/UDP checksum
+		 */
+		cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
 	}
 	/* typical time for secure PCP is 840ms */
 	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index c37b9d6..0f9e9057 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -50,7 +50,7 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
 		return -ENODEV;
 
 	drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
-	return PTR_RET(drvr->dbgfs_dir);
+	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
 }
 
 void brcmf_debugfs_detach(struct brcmf_pub *drvr)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index bd98285..fa391e4 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -928,9 +928,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 			}
 		} else if (txs->phyerr) {
 			update_rate = false;
-			brcms_err(wlc->hw->d11core,
-				  "%s: ampdu tx phy error (0x%x)\n",
-				  __func__, txs->phyerr);
+			brcms_dbg_ht(wlc->hw->d11core,
+				     "%s: ampdu tx phy error (0x%x)\n",
+				     __func__, txs->phyerr);
 		}
 	}
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
index 9761deb..a5d4add 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
@@ -56,7 +56,7 @@ int brcms_debugfs_attach(struct brcms_pub *drvr)
 
 	drvr->dbgfs_dir = debugfs_create_dir(
 		 dev_name(&drvr->wlc->hw->d11core->dev), root_folder);
-	return PTR_RET(drvr->dbgfs_dir);
+	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
 }
 
 void brcms_debugfs_detach(struct brcms_pub *drvr)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9fd6f2f..7ca10bf 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -882,8 +882,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 	mcl = le16_to_cpu(txh->MacTxControlLow);
 
 	if (txs->phyerr)
-		brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
-			  txs->phyerr, txh->MainRates);
+		brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
+			     txs->phyerr, txh->MainRates);
 
 	if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
 		brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c
index 7365674..010b252 100644
--- a/drivers/net/wireless/cw1200/sta.c
+++ b/drivers/net/wireless/cw1200/sta.c
@@ -1406,11 +1406,8 @@ static void cw1200_do_unjoin(struct cw1200_common *priv)
 	if (!priv->join_status)
 		goto done;
 
-	if (priv->join_status > CW1200_JOIN_STATUS_IBSS) {
-		wiphy_err(priv->hw->wiphy, "Unexpected: join status: %d\n",
-			  priv->join_status);
-		BUG_ON(1);
-	}
+	if (priv->join_status == CW1200_JOIN_STATUS_AP)
+		goto done;
 
 	cancel_work_sync(&priv->update_filtering_work);
 	cancel_work_sync(&priv->set_beacon_wakeup_period_work);
diff --git a/drivers/net/wireless/cw1200/wsm.h b/drivers/net/wireless/cw1200/wsm.h
index 7afc613..48086e8 100644
--- a/drivers/net/wireless/cw1200/wsm.h
+++ b/drivers/net/wireless/cw1200/wsm.h
@@ -832,7 +832,7 @@ struct wsm_tx {
 	/* the MSDU shall be terminated. Overrides the global */
 	/* dot11MaxTransmitMsduLifeTime setting [optional] */
 	/* Device will set the default value if this is 0. */
-	u32 expire_time;
+	__le32 expire_time;
 
 	/* WSM_HT_TX_... */
 	__le32 ht_tx_parameters;
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 15f0fad..e4f56ad 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -667,7 +667,7 @@ static int prism2_open(struct net_device *dev)
 	if (local->no_pri) {
 		printk(KERN_DEBUG "%s: could not set interface UP - no PRI "
 		       "f/w\n", dev->name);
-		return 1;
+		return -ENODEV;
 	}
 
 	if ((local->func->card_present && !local->func->card_present(local)) ||
@@ -682,7 +682,7 @@ static int prism2_open(struct net_device *dev)
 		printk(KERN_WARNING "%s: could not enable MAC port\n",
 		       dev->name);
 		prism2_close(dev);
-		return 1;
+		return -ENODEV;
 	}
 	if (!local->dev_enabled)
 		prism2_callback(local, PRISM2_CALLBACK_ENABLE);
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index fe31590..aea667b 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -887,6 +887,7 @@ il3945_remove_debugfs(void *il, void *il_sta)
  */
 static void
 il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
+			 struct cfg80211_chan_def *chandef,
 			 struct ieee80211_sta *sta, void *il_sta)
 {
 }
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c092033..f09e257 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -475,6 +475,8 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
 	}
 }
 
+#define SMALL_PACKET_SIZE 256
+
 static void
 il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
 			       struct ieee80211_rx_status *stats)
@@ -483,14 +485,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
 	struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
 	struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
-	u16 len = le16_to_cpu(rx_hdr->len);
+	u32 len = le16_to_cpu(rx_hdr->len);
 	struct sk_buff *skb;
 	__le16 fc = hdr->frame_control;
+	u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
 
 	/* We received data from the HW, so stop the watchdog */
-	if (unlikely
-	    (len + IL39_RX_FRAME_SIZE >
-	     PAGE_SIZE << il->hw_params.rx_page_order)) {
+	if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
 		D_DROP("Corruption detected!\n");
 		return;
 	}
@@ -506,26 +507,32 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
 		D_INFO("Woke queues - frame received on passive channel\n");
 	}
 
-	skb = dev_alloc_skb(128);
+	skb = dev_alloc_skb(SMALL_PACKET_SIZE);
 	if (!skb) {
 		IL_ERR("dev_alloc_skb failed\n");
 		return;
 	}
 
 	if (!il3945_mod_params.sw_crypto)
-		il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
+		il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
 				      le32_to_cpu(rx_end->status), stats);
 
-	skb_add_rx_frag(skb, 0, rxb->page,
-			(void *)rx_hdr->payload - (void *)pkt, len,
-			len);
-
+	/* If frame is small enough to fit into skb->head, copy it
+	 * and do not consume a full page
+	 */
+	if (len <= SMALL_PACKET_SIZE) {
+		memcpy(skb_put(skb, len), rx_hdr->payload, len);
+	} else {
+		skb_add_rx_frag(skb, 0, rxb->page,
+				(void *)rx_hdr->payload - (void *)pkt, len,
+				fraglen);
+		il->alloc_rxb_page--;
+		rxb->page = NULL;
+	}
 	il_update_stats(il, false, fc, len);
 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
 	ieee80211_rx(il->hw, skb);
-	il->alloc_rxb_page--;
-	rxb->page = NULL;
 }
 
 #define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index b9b2bb5..b411ab9 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -574,9 +574,11 @@ il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in)
 	return decrypt_out;
 }
 
+#define SMALL_PACKET_SIZE 256
+
 static void
 il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
-			       u16 len, u32 ampdu_status, struct il_rx_buf *rxb,
+			       u32 len, u32 ampdu_status, struct il_rx_buf *rxb,
 			       struct ieee80211_rx_status *stats)
 {
 	struct sk_buff *skb;
@@ -598,21 +600,25 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
 	    il_set_decrypted_flag(il, hdr, ampdu_status, stats))
 		return;
 
-	skb = dev_alloc_skb(128);
+	skb = dev_alloc_skb(SMALL_PACKET_SIZE);
 	if (!skb) {
 		IL_ERR("dev_alloc_skb failed\n");
 		return;
 	}
 
-	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len,
-			len);
+	if (len <= SMALL_PACKET_SIZE) {
+		memcpy(skb_put(skb, len), hdr, len);
+	} else {
+		skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb),
+				len, PAGE_SIZE << il->hw_params.rx_page_order);
+		il->alloc_rxb_page--;
+		rxb->page = NULL;
+	}
 
 	il_update_stats(il, false, fc, len);
 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
 	ieee80211_rx(il->hw, skb);
-	il->alloc_rxb_page--;
-	rxb->page = NULL;
 }
 
 /* Called for N_RX (legacy ABG frames), or
@@ -4460,12 +4466,12 @@ il4965_irq_tasklet(struct il_priv *il)
 		 * is killed. Hence update the killswitch state here. The
 		 * rfkill handler will care about restarting if needed.
 		 */
-		if (!test_bit(S_ALIVE, &il->status)) {
-			if (hw_rf_kill)
-				set_bit(S_RFKILL, &il->status);
-			else
-				clear_bit(S_RFKILL, &il->status);
+		if (hw_rf_kill) {
+			set_bit(S_RFKILL, &il->status);
+		} else {
+			clear_bit(S_RFKILL, &il->status);
 			wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
+			il_force_reset(il, true);
 		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
@@ -5334,6 +5340,9 @@ il4965_alive_start(struct il_priv *il)
 
 	il->active_rate = RATES_MASK;
 
+	il_power_update_mode(il, true);
+	D_INFO("Updated power mode\n");
+
 	if (il_is_associated(il)) {
 		struct il_rxon_cmd *active_rxon =
 		    (struct il_rxon_cmd *)&il->active;
@@ -5364,9 +5373,6 @@ il4965_alive_start(struct il_priv *il)
 	D_INFO("ALIVE processing complete.\n");
 	wake_up(&il->wait_command_queue);
 
-	il_power_update_mode(il, true);
-	D_INFO("Updated power mode\n");
-
 	return;
 
 restart:
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
index ed3c42a..3ccbaf7 100644
--- a/drivers/net/wireless/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/4965-rs.c
@@ -2803,6 +2803,7 @@ il4965_rs_remove_debugfs(void *il, void *il_sta)
  */
 static void
 il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
+			 struct cfg80211_chan_def *chandef,
 			 struct ieee80211_sta *sta, void *il_sta)
 {
 }
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 3195aad..b03e22e 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external)
 
 	return 0;
 }
+EXPORT_SYMBOL(il_force_reset);
 
 int
 il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index cbaa5c2..e5c133e 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -127,20 +127,3 @@ config IWLWIFI_DEVICE_TRACING
 	  If unsure, say Y so we can help you better when problems
 	  occur.
 endmenu
-
-config IWLWIFI_P2P
-	def_bool y
-	bool "iwlwifi experimental P2P support"
-	depends on IWLWIFI
-	help
-	  This option enables experimental P2P support for some devices
-	  based on microcode support. Since P2P support is still under
-	  development, this option may even enable it for some devices
-	  now that turn out to not support it in the future due to
-	  microcode restrictions.
-
-	  To determine if your microcode supports the experimental P2P
-	  offered by this option, check if the driver advertises AP
-	  support when it is loaded.
-
-	  Say Y only if you want to experiment with P2P.
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 1835511..f2a86ff 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -106,7 +106,6 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg;
 #define STATUS_CHANNEL_SWITCH_PENDING 11
 #define STATUS_SCAN_COMPLETE	12
 #define STATUS_POWER_PMI	13
-#define STATUS_SCAN_ROC_EXPIRED 14
 
 struct iwl_ucode_capabilities;
 
@@ -250,7 +249,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
 
 /* scan */
 void iwlagn_post_scan(struct iwl_priv *priv);
-void iwlagn_disable_roc(struct iwl_priv *priv);
 int iwl_force_rf_reset(struct iwl_priv *priv, bool external);
 void iwl_init_scan_params(struct iwl_priv *priv);
 int iwl_scan_cancel(struct iwl_priv *priv);
@@ -265,10 +263,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
 				   enum iwl_scan_type scan_type,
 				   enum ieee80211_band band);
 
-void iwl_scan_roc_expired(struct iwl_priv *priv);
-void iwl_scan_offchannel_skb(struct iwl_priv *priv);
-void iwl_scan_offchannel_skb_status(struct iwl_priv *priv);
-
 /* For faster active scanning, scan will move to the next channel if fewer than
  * PLCP_QUIET_THRESH packets are heard on this channel within
  * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index d532948..d94f8ab 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -69,19 +69,7 @@
 } while (0)
 
 /* file operation */
-#define DEBUGFS_READ_FUNC(name)                                         \
-static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
-					char __user *user_buf,          \
-					size_t count, loff_t *ppos);
-
-#define DEBUGFS_WRITE_FUNC(name)                                        \
-static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
-					const char __user *user_buf,    \
-					size_t count, loff_t *ppos);
-
-
 #define DEBUGFS_READ_FILE_OPS(name)                                     \
-	DEBUGFS_READ_FUNC(name);                                        \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.read = iwl_dbgfs_##name##_read,				\
 	.open = simple_open,						\
@@ -89,7 +77,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 };
 
 #define DEBUGFS_WRITE_FILE_OPS(name)                                    \
-	DEBUGFS_WRITE_FUNC(name);                                       \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.write = iwl_dbgfs_##name##_write,                              \
 	.open = simple_open,						\
@@ -98,8 +85,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 
 
 #define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \
-	DEBUGFS_READ_FUNC(name);                                        \
-	DEBUGFS_WRITE_FUNC(name);                                       \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.write = iwl_dbgfs_##name##_write,                              \
 	.read = iwl_dbgfs_##name##_read,                                \
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 60a4e0d..a79fdd1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -540,7 +540,6 @@ struct iwl_rxon_context {
 enum iwl_scan_type {
 	IWL_SCAN_NORMAL,
 	IWL_SCAN_RADIO_RESET,
-	IWL_SCAN_ROC,
 };
 
 /**
@@ -825,12 +824,6 @@ struct iwl_priv {
 	struct reply_tx_error_statistics reply_tx_stats;
 	struct reply_agg_tx_error_statistics reply_agg_tx_stats;
 
-	/* remain-on-channel offload support */
-	struct ieee80211_channel *hw_roc_channel;
-	struct delayed_work hw_roc_disable_work;
-	int hw_roc_duration;
-	bool hw_roc_setup, hw_roc_start_notified;
-
 	/* bt coex */
 	u8 bt_enable_flag;
 	u8 bt_status;
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 822f1a0..f0a2c95 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -76,29 +76,6 @@ static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
 	},
 };
 
-static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_STATION),
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_P2P_GO) |
-			 BIT(NL80211_IFTYPE_AP),
-	},
-};
-
-static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
-	{
-		.max = 2,
-		.types = BIT(NL80211_IFTYPE_STATION),
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_P2P_CLIENT),
-	},
-};
-
 static const struct ieee80211_iface_combination
 iwlagn_iface_combinations_dualmode[] = {
 	{ .num_different_channels = 1,
@@ -114,21 +91,6 @@ iwlagn_iface_combinations_dualmode[] = {
 	},
 };
 
-static const struct ieee80211_iface_combination
-iwlagn_iface_combinations_p2p[] = {
-	{ .num_different_channels = 1,
-	  .max_interfaces = 2,
-	  .beacon_int_infra_match = true,
-	  .limits = iwlagn_p2p_sta_go_limits,
-	  .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
-	},
-	{ .num_different_channels = 1,
-	  .max_interfaces = 2,
-	  .limits = iwlagn_p2p_2sta_limits,
-	  .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
-	},
-};
-
 /*
  * Not a mac80211 entry point function, but it fits in with all the
  * other mac80211 functions grouped here.
@@ -186,19 +148,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
 
 	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
 
-	if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
-		hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
-		hw->wiphy->n_iface_combinations =
-			ARRAY_SIZE(iwlagn_iface_combinations_p2p);
-	} else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
+	if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
 		hw->wiphy->iface_combinations =
 			iwlagn_iface_combinations_dualmode;
 		hw->wiphy->n_iface_combinations =
 			ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
 	}
 
-	hw->wiphy->max_remain_on_channel_duration = 500;
-
 	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
 			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
 			    WIPHY_FLAG_IBSS_RSN;
@@ -1156,126 +1112,6 @@ done:
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_channel *channel,
-				     int duration,
-				     enum ieee80211_roc_type type)
-{
-	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
-	int err = 0;
-
-	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
-		return -EOPNOTSUPP;
-
-	if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
-		return -EOPNOTSUPP;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->mutex);
-
-	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-		/* mac80211 should not scan while ROC or ROC while scanning */
-		if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) {
-			err = -EBUSY;
-			goto out;
-		}
-
-		iwl_scan_cancel_timeout(priv, 100);
-
-		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-			err = -EBUSY;
-			goto out;
-		}
-	}
-
-	priv->hw_roc_channel = channel;
-	/* convert from ms to TU */
-	priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024);
-	priv->hw_roc_start_notified = false;
-	cancel_delayed_work(&priv->hw_roc_disable_work);
-
-	if (!ctx->is_active) {
-		static const struct iwl_qos_info default_qos_data = {
-			.def_qos_parm = {
-				.ac[0] = {
-					.cw_min = cpu_to_le16(3),
-					.cw_max = cpu_to_le16(7),
-					.aifsn = 2,
-					.edca_txop = cpu_to_le16(1504),
-				},
-				.ac[1] = {
-					.cw_min = cpu_to_le16(7),
-					.cw_max = cpu_to_le16(15),
-					.aifsn = 2,
-					.edca_txop = cpu_to_le16(3008),
-				},
-				.ac[2] = {
-					.cw_min = cpu_to_le16(15),
-					.cw_max = cpu_to_le16(1023),
-					.aifsn = 3,
-				},
-				.ac[3] = {
-					.cw_min = cpu_to_le16(15),
-					.cw_max = cpu_to_le16(1023),
-					.aifsn = 7,
-				},
-			},
-		};
-
-		ctx->is_active = true;
-		ctx->qos_data = default_qos_data;
-		ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
-		memcpy(ctx->staging.node_addr,
-		       priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
-		       ETH_ALEN);
-		memcpy(ctx->staging.bssid_addr,
-		       priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
-		       ETH_ALEN);
-		err = iwlagn_commit_rxon(priv, ctx);
-		if (err)
-			goto out;
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK |
-					     RXON_FILTER_PROMISC_MSK |
-					     RXON_FILTER_CTL2HOST_MSK;
-
-		err = iwlagn_commit_rxon(priv, ctx);
-		if (err) {
-			iwlagn_disable_roc(priv);
-			goto out;
-		}
-		priv->hw_roc_setup = true;
-	}
-
-	err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band);
-	if (err)
-		iwlagn_disable_roc(priv);
-
- out:
-	mutex_unlock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return err;
-}
-
-static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-
-	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
-		return -EOPNOTSUPP;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->mutex);
-	iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
-	iwlagn_disable_roc(priv);
-	mutex_unlock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return 0;
-}
-
 static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     enum ieee80211_rssi_event rssi_event)
@@ -1431,12 +1267,8 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
 			   viftype, vif->addr);
 
-	cancel_delayed_work_sync(&priv->hw_roc_disable_work);
-
 	mutex_lock(&priv->mutex);
 
-	iwlagn_disable_roc(priv);
-
 	if (!iwl_is_ready_rf(priv)) {
 		IWL_WARN(priv, "Try to add interface when device not ready\n");
 		err = -EINVAL;
@@ -1763,8 +1595,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
 	.channel_switch = iwlagn_mac_channel_switch,
 	.flush = iwlagn_mac_flush,
 	.tx_last_beacon = iwlagn_mac_tx_last_beacon,
-	.remain_on_channel = iwlagn_mac_remain_on_channel,
-	.cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel,
 	.rssi_callback = iwlagn_mac_rssi_callback,
 	.set_tim = iwlagn_mac_set_tim,
 };
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 1531a4f..7aad766 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -587,11 +587,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
 	priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
 		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
 
-	if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P)
-		priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
-			BIT(NL80211_IFTYPE_P2P_CLIENT) |
-			BIT(NL80211_IFTYPE_P2P_GO);
-
 	priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
 	priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
 	priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
@@ -854,14 +849,6 @@ void iwl_down(struct iwl_priv *priv)
 
 	iwl_scan_cancel_timeout(priv, 200);
 
-	/*
-	 * If active, scanning won't cancel it, so say it expired.
-	 * No race since we hold the mutex here and a new one
-	 * can't come in at this time.
-	 */
-	if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT)
-		ieee80211_remain_on_channel_expired(priv->hw);
-
 	exit_pending =
 		test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
 
@@ -1002,41 +989,6 @@ static void iwl_bg_restart(struct work_struct *data)
 	}
 }
 
-
-
-
-void iwlagn_disable_roc(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (!priv->hw_roc_setup)
-		return;
-
-	ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-	priv->hw_roc_channel = NULL;
-
-	memset(ctx->staging.node_addr, 0, ETH_ALEN);
-
-	iwlagn_commit_rxon(priv, ctx);
-
-	ctx->is_active = false;
-	priv->hw_roc_setup = false;
-}
-
-static void iwlagn_disable_roc_work(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-					     hw_roc_disable_work.work);
-
-	mutex_lock(&priv->mutex);
-	iwlagn_disable_roc(priv);
-	mutex_unlock(&priv->mutex);
-}
-
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -1053,8 +1005,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 	INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
 	INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
 	INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
-	INIT_DELAYED_WORK(&priv->hw_roc_disable_work,
-			  iwlagn_disable_roc_work);
 
 	iwl_setup_scan_deferred_work(priv);
 
@@ -1082,7 +1032,6 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
 
 	cancel_work_sync(&priv->bt_full_concurrency);
 	cancel_work_sync(&priv->bt_runtime_config);
-	cancel_delayed_work_sync(&priv->hw_roc_disable_work);
 
 	del_timer_sync(&priv->statistics_periodic);
 	del_timer_sync(&priv->ucode_trace);
@@ -1169,12 +1118,6 @@ static void iwl_option_config(struct iwl_priv *priv)
 #else
 	IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
 #endif
-
-#ifdef CONFIG_IWLWIFI_P2P
-	IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
-#else
-	IWL_INFO(priv, "CONFIG_IWLWIFI_P2P disabled\n");
-#endif
 }
 
 static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
@@ -1315,10 +1258,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
 
 	ucode_flags = fw->ucode_capa.flags;
 
-#ifndef CONFIG_IWLWIFI_P2P
-	ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
-#endif
-
 	if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
 		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
 		trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
@@ -1413,7 +1352,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
 		 * if not PAN, then don't support P2P -- might be a uCode
 		 * packaging bug or due to the eeprom check above
 		 */
-		ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
 		priv->sta_key_max_num = STA_KEY_MAX_NUM;
 		trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index 1b69394..b647e50 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -2826,9 +2826,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
 
 	lq_sta->flush_timer = 0;
 	lq_sta->supp_rates = sta->supp_rates[sband->band];
-	for (j = 0; j < LQ_SIZE; j++)
-		for (i = 0; i < IWL_RATE_COUNT; i++)
-			rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
 
 	IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n",
 		       sta_id);
@@ -3319,7 +3316,8 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
  * station is added we ignore it.
  */
 static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
-			 struct ieee80211_sta *sta, void *priv_sta)
+			      struct cfg80211_chan_def *chandef,
+			      struct ieee80211_sta *sta, void *priv_sta)
 {
 }
 static struct rate_control_ops rs_ops = {
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index cd1ad001..d7ce2f1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -564,11 +564,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
 	cmd.slots[0].type = 0; /* BSS */
 	cmd.slots[1].type = 1; /* PAN */
 
-	if (priv->hw_roc_setup) {
-		/* both contexts must be used for this to happen */
-		slot1 = IWL_MIN_SLOT_TIME;
-		slot0 = 3000;
-	} else if (ctx_bss->vif && ctx_pan->vif) {
+	if (ctx_bss->vif && ctx_pan->vif) {
 		int bcnint = ctx_pan->beacon_int;
 		int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index 8c686a5..35e0ee8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -100,9 +100,6 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
 		ieee80211_scan_completed(priv->hw, aborted);
 	}
 
-	if (priv->scan_type == IWL_SCAN_ROC)
-		iwl_scan_roc_expired(priv);
-
 	priv->scan_type = IWL_SCAN_NORMAL;
 	priv->scan_vif = NULL;
 	priv->scan_request = NULL;
@@ -130,9 +127,6 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
 		goto out_settings;
 	}
 
-	if (priv->scan_type == IWL_SCAN_ROC)
-		iwl_scan_roc_expired(priv);
-
 	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
 		int err;
 
@@ -284,12 +278,6 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
 		       le32_to_cpu(notif->tsf_low),
 		       notif->status, notif->beacon_timer);
 
-	if (priv->scan_type == IWL_SCAN_ROC &&
-	    !priv->hw_roc_start_notified) {
-		ieee80211_ready_on_channel(priv->hw);
-		priv->hw_roc_start_notified = true;
-	}
-
 	return 0;
 }
 
@@ -697,8 +685,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
-	if (priv->scan_type != IWL_SCAN_ROC &&
-	    iwl_is_any_associated(priv)) {
+	if (iwl_is_any_associated(priv)) {
 		u16 interval = 0;
 		u32 extra;
 		u32 suspend_time = 100;
@@ -706,9 +693,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 
 		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
 		switch (priv->scan_type) {
-		case IWL_SCAN_ROC:
-			WARN_ON(1);
-			break;
 		case IWL_SCAN_RADIO_RESET:
 			interval = 0;
 			break;
@@ -728,11 +712,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		scan->suspend_time = cpu_to_le32(scan_suspend_time);
 		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
 			       scan_suspend_time, interval);
-	} else if (priv->scan_type == IWL_SCAN_ROC) {
-		scan->suspend_time = 0;
-		scan->max_out_time = 0;
-		scan->quiet_time = 0;
-		scan->quiet_plcp_th = 0;
 	}
 
 	switch (priv->scan_type) {
@@ -774,9 +753,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		} else
 			IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
 		break;
-	case IWL_SCAN_ROC:
-		IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
-		break;
 	}
 
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
@@ -898,7 +874,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 					scan_cmd_size - sizeof(*scan));
 		break;
 	case IWL_SCAN_RADIO_RESET:
-	case IWL_SCAN_ROC:
 		/* use bcast addr, will not be transmitted but must be valid */
 		cmd_len = iwl_fill_probe_req(
 					(struct ieee80211_mgmt *)scan->data,
@@ -926,46 +901,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 				is_active, n_probes,
 				(void *)&scan->data[cmd_len]);
 		break;
-	case IWL_SCAN_ROC: {
-		struct iwl_scan_channel *scan_ch;
-		int n_chan, i;
-		u16 dwell;
-
-		dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
-		n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
-
-		scan->channel_count = n_chan;
-
-		scan_ch = (void *)&scan->data[cmd_len];
-
-		for (i = 0; i < n_chan; i++) {
-			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-			scan_ch->channel =
-				cpu_to_le16(priv->hw_roc_channel->hw_value);
-
-			if (i == n_chan - 1)
-				dwell = priv->hw_roc_duration - i * dwell;
-
-			scan_ch->active_dwell =
-			scan_ch->passive_dwell = cpu_to_le16(dwell);
-
-			/* Set txpower levels to defaults */
-			scan_ch->dsp_atten = 110;
-
-			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
-			 * power level:
-			 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
-			 */
-			if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
-				scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-			else
-				scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-
-			scan_ch++;
-		}
-		}
-
-		break;
 	}
 
 	if (scan->channel_count == 0) {
@@ -1035,7 +970,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
 
 	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
 			scan_type == IWL_SCAN_NORMAL ? "" :
-			scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
 			"internal short ");
 
 	set_bit(STATUS_SCANNING, &priv->status);
@@ -1149,40 +1083,3 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
 		mutex_unlock(&priv->mutex);
 	}
 }
-
-void iwl_scan_roc_expired(struct iwl_priv *priv)
-{
-	/*
-	 * The status bit should be set here, to prevent a race
-	 * where the atomic_read returns 1, but before the execution continues
-	 * iwl_scan_offchannel_skb_status() checks if the status bit is set
-	 */
-	set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
-
-	if (atomic_read(&priv->num_aux_in_flight) == 0) {
-		ieee80211_remain_on_channel_expired(priv->hw);
-		priv->hw_roc_channel = NULL;
-		schedule_delayed_work(&priv->hw_roc_disable_work,
-				      10 * HZ);
-
-		clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
-	} else {
-		IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n",
-			       atomic_read(&priv->num_aux_in_flight));
-	}
-}
-
-void iwl_scan_offchannel_skb(struct iwl_priv *priv)
-{
-	WARN_ON(!priv->hw_roc_start_notified);
-	atomic_inc(&priv->num_aux_in_flight);
-}
-
-void iwl_scan_offchannel_skb_status(struct iwl_priv *priv)
-{
-	if (atomic_dec_return(&priv->num_aux_in_flight) == 0 &&
-	    test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n");
-		iwl_scan_roc_expired(priv);
-	}
-}
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 5ee983f..3db0bbb 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -478,9 +478,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 	if (sta_priv && sta_priv->client && !is_agg)
 		atomic_inc(&sta_priv->pending_frames);
 
-	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
-		iwl_scan_offchannel_skb(priv);
-
 	return 0;
 
 drop_unlock_sta:
@@ -1158,7 +1155,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 	struct sk_buff *skb;
 	struct iwl_rxon_context *ctx;
 	bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
-	bool is_offchannel_skb;
 
 	tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
 		IWLAGN_TX_RES_TID_POS;
@@ -1178,8 +1174,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 
 	__skb_queue_head_init(&skbs);
 
-	is_offchannel_skb = false;
-
 	if (tx_resp->frame_count == 1) {
 		u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
 		next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10);
@@ -1256,8 +1250,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			if (!is_agg)
 				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
 
-			is_offchannel_skb =
-				(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
 			freed++;
 		}
 
@@ -1271,14 +1263,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 		if (!is_agg && freed != 1)
 			IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed);
 
-		/*
-		 * An offchannel frame can be send only on the AUX queue, where
-		 * there is no aggregation (and reordering) so it only is single
-		 * skb is expected to be processed.
-		 */
-		if (is_offchannel_skb && freed != 1)
-			IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed);
-
 		IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id,
 				   iwl_get_tx_fail_reason(status), status);
 
@@ -1298,9 +1282,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 		ieee80211_tx_status_ni(priv->hw, skb);
 	}
 
-	if (is_offchannel_skb)
-		iwl_scan_offchannel_skb_status(priv);
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 22b7fa5..76e14c0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -99,6 +99,7 @@ static const struct iwl_base_params iwl7000_base_params = {
 	.wd_timeout = IWL_LONG_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.shadow_reg_enable = true,
+	.pcie_l1_allowed = true,
 };
 
 static const struct iwl_ht_params iwl7000_ht_params = {
@@ -126,6 +127,16 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
 	.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
 };
 
+const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
+	.name = "Intel(R) Dual Band Wireless AC 7260",
+	.fw_name_pre = IWL7260_FW_PRE,
+	IWL_DEVICE_7000,
+	.ht_params = &iwl7000_ht_params,
+	.nvm_ver = IWL7260_NVM_VERSION,
+	.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+	.high_temp = true,
+};
+
 const struct iwl_cfg iwl7260_2n_cfg = {
 	.name = "Intel(R) Dual Band Wireless N 7260",
 	.fw_name_pre = IWL7260_FW_PRE,
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 83b9ff6..e4d370b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -152,6 +152,7 @@ struct iwl_base_params {
 	unsigned int wd_timeout;
 	u32 max_event_log_size;
 	const bool shadow_reg_enable;
+	const bool pcie_l1_allowed;
 };
 
 /*
@@ -205,6 +206,7 @@ struct iwl_eeprom_params {
  * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
+ * @high_temp: Is this NIC is designated to be in high temperature.
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -233,6 +235,7 @@ struct iwl_cfg {
 	enum iwl_led_mode led_mode;
 	const bool rx_with_siso_diversity;
 	const bool internal_wimax_coex;
+	bool high_temp;
 };
 
 /*
@@ -283,6 +286,7 @@ extern const struct iwl_cfg iwl135_bgn_cfg;
 #endif /* CONFIG_IWLDVM */
 #if IS_ENABLED(CONFIG_IWLMVM)
 extern const struct iwl_cfg iwl7260_2ac_cfg;
+extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
 extern const struct iwl_cfg iwl7260_2n_cfg;
 extern const struct iwl_cfg iwl7260_n_cfg;
 extern const struct iwl_cfg iwl3160_2ac_cfg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index f844d5c..bd335f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -74,13 +74,22 @@
  * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
  * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
  * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
+ * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
+ * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
+ * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
+ *	(rather than two) IPv6 addresses
+ * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
  */
 enum iwl_ucode_tlv_flag {
-	IWL_UCODE_TLV_FLAGS_PAN		= BIT(0),
-	IWL_UCODE_TLV_FLAGS_NEWSCAN	= BIT(1),
-	IWL_UCODE_TLV_FLAGS_MFP		= BIT(2),
-	IWL_UCODE_TLV_FLAGS_P2P		= BIT(3),
-	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE	= BIT(4),
+	IWL_UCODE_TLV_FLAGS_PAN			= BIT(0),
+	IWL_UCODE_TLV_FLAGS_NEWSCAN		= BIT(1),
+	IWL_UCODE_TLV_FLAGS_MFP			= BIT(2),
+	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
+	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
+	IWL_UCODE_TLV_FLAGS_UAPSD		= BIT(6),
+	IWL_UCODE_TLV_FLAGS_RX_ENERGY_API	= BIT(8),
+	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
+	IWL_UCODE_TLV_FLAGS_BF_UPDATED		= BIT(11),
 };
 
 /* The default calibrate table size if not specified by firmware file */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 305c81f..dfa4d2e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -33,6 +33,8 @@
 #include "iwl-io.h"
 #include "iwl-csr.h"
 #include "iwl-debug.h"
+#include "iwl-fh.h"
+#include "iwl-csr.h"
 
 #define IWL_POLL_INTERVAL 10	/* microseconds */
 
@@ -166,3 +168,68 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
 	}
 }
 IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
+
+static const char *get_fh_string(int cmd)
+{
+#define IWL_CMD(x) case x: return #x
+	switch (cmd) {
+	IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
+	IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
+	IWL_CMD(FH_RSCSR_CHNL0_WPTR);
+	IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
+	IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
+	IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
+	IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+	IWL_CMD(FH_TSSR_TX_STATUS_REG);
+	IWL_CMD(FH_TSSR_TX_ERROR_REG);
+	default:
+		return "UNKNOWN";
+	}
+#undef IWL_CMD
+}
+
+int iwl_dump_fh(struct iwl_trans *trans, char **buf)
+{
+	int i;
+	static const u32 fh_tbl[] = {
+		FH_RSCSR_CHNL0_STTS_WPTR_REG,
+		FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+		FH_RSCSR_CHNL0_WPTR,
+		FH_MEM_RCSR_CHNL0_CONFIG_REG,
+		FH_MEM_RSSR_SHARED_CTRL_REG,
+		FH_MEM_RSSR_RX_STATUS_REG,
+		FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+		FH_TSSR_TX_STATUS_REG,
+		FH_TSSR_TX_ERROR_REG
+	};
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	if (buf) {
+		int pos = 0;
+		size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+
+		pos += scnprintf(*buf + pos, bufsz - pos,
+				"FH register values:\n");
+
+		for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
+			pos += scnprintf(*buf + pos, bufsz - pos,
+				"  %34s: 0X%08x\n",
+				get_fh_string(fh_tbl[i]),
+				iwl_read_direct32(trans, fh_tbl[i]));
+
+		return pos;
+	}
+#endif
+
+	IWL_ERR(trans, "FH register values:\n");
+	for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++)
+		IWL_ERR(trans, "  %34s: 0X%08x\n",
+			get_fh_string(fh_tbl[i]),
+			iwl_read_direct32(trans, fh_tbl[i]));
+
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index fd9f5b9..63d10ec0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -77,4 +77,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
 			    u32 bits, u32 mask);
 void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
 
+/* Error handling */
+int iwl_dump_fh(struct iwl_trans *trans, char **buf);
+
 #endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index acd2665..b76a9a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -118,6 +118,7 @@ static const u8 iwl_nvm_channels[] = {
 #define LAST_2GHZ_HT_PLUS	9
 #define LAST_5GHZ_HT		161
 
+#define DEFAULT_MAX_TX_POWER 16
 
 /* rate data (static) */
 static struct ieee80211_rate iwl_cfg80211_rates[] = {
@@ -232,8 +233,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 
 		/* Initialize regulatory-based run-time data */
 
-		/* TODO: read the real value from the NVM */
-		channel->max_power = 0;
+		/*
+		 * Default value - highest tx power value.  max_power
+		 * is not used in mvm, and is used for backwards compatibility
+		 */
+		channel->max_power = DEFAULT_MAX_TX_POWER;
 		is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
 		IWL_DEBUG_EEPROM(dev,
 				 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index ff856e5..6d73817 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM)   += iwlmvm.o
 iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
 iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
 iwlmvm-y += scan.o time-event.o rs.o
-iwlmvm-y += power.o bt-coex.o
+iwlmvm-y += power.o power_legacy.o bt-coex.o
 iwlmvm-y += led.o tt.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
 iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index dbd622a..0fad98b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -220,66 +220,87 @@ static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = {
 
 int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 {
-	struct iwl_bt_coex_cmd cmd = {
-		.max_kill = 5,
-		.bt3_time_t7_value = 1,
-		.bt3_prio_sample_time = 2,
-		.bt3_timer_t2_value = 0xc,
+	struct iwl_bt_coex_cmd *bt_cmd;
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+		.flags = CMD_SYNC,
 	};
 	int ret;
 
-	cmd.flags = iwlwifi_mod_params.bt_coex_active ?
+	/* go to CALIB state in internal BT-Coex state machine */
+	ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
+			      BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+	if (ret)
+		return ret;
+
+	ret  = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
+			       BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+	if (ret)
+		return ret;
+
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+	if (!bt_cmd)
+		return -ENOMEM;
+	cmd.data[0] = bt_cmd;
+
+	bt_cmd->max_kill = 5;
+	bt_cmd->bt3_time_t7_value = 1;
+	bt_cmd->bt3_prio_sample_time = 2;
+	bt_cmd->bt3_timer_t2_value = 0xc;
+
+	bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ?
 			BT_COEX_NW : BT_COEX_DISABLE;
-	cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
+	bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
 
-	cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
-					BT_VALID_BT_PRIO_BOOST |
-					BT_VALID_MAX_KILL |
-					BT_VALID_3W_TMRS |
-					BT_VALID_KILL_ACK |
-					BT_VALID_KILL_CTS |
-					BT_VALID_REDUCED_TX_POWER |
-					BT_VALID_LUT);
+	bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
+					    BT_VALID_BT_PRIO_BOOST |
+					    BT_VALID_MAX_KILL |
+					    BT_VALID_3W_TMRS |
+					    BT_VALID_KILL_ACK |
+					    BT_VALID_KILL_CTS |
+					    BT_VALID_REDUCED_TX_POWER |
+					    BT_VALID_LUT);
 
 	if (mvm->cfg->bt_shared_single_ant)
-		memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup,
+		memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup,
 		       sizeof(iwl_single_shared_ant_lookup));
 	else if (is_loose_coex())
-		memcpy(&cmd.decision_lut, iwl_loose_lookup,
+		memcpy(&bt_cmd->decision_lut, iwl_loose_lookup,
 		       sizeof(iwl_tight_lookup));
 	else
-		memcpy(&cmd.decision_lut, iwl_tight_lookup,
+		memcpy(&bt_cmd->decision_lut, iwl_tight_lookup,
 		       sizeof(iwl_tight_lookup));
 
-	cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
-	cmd.kill_ack_msk =
+	bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
+	bt_cmd->kill_ack_msk =
 		cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
-	cmd.kill_cts_msk =
+	bt_cmd->kill_cts_msk =
 		cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
 
 	memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
 
-	/* go to CALIB state in internal BT-Coex state machine */
-	ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
-			      BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
-	if (ret)
-		return ret;
-
-	ret  = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
-			       BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
-	if (ret)
-		return ret;
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
 
-	return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
-				    sizeof(cmd), &cmd);
+	kfree(bt_cmd);
+	return ret;
 }
 
 static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
 					   bool reduced_tx_power)
 {
 	enum iwl_bt_kill_msk bt_kill_msk;
-	struct iwl_bt_coex_cmd cmd = {};
+	struct iwl_bt_coex_cmd *bt_cmd;
 	struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.data[0] = &bt_cmd,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+		.flags = CMD_SYNC,
+	};
+	int ret = 0;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -308,24 +329,40 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
 		return 0;
 
 	mvm->bt_kill_msk = bt_kill_msk;
-	cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
-	cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
-	cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+	if (!bt_cmd)
+		return -ENOMEM;
+	cmd.data[0] = bt_cmd;
+
+	bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
+	bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+	bt_cmd->valid_bit_msk =
+		cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
 
 	IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
-	return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
-				    sizeof(cmd), &cmd);
+
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
 }
 
 static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
 				       bool enable)
 {
-	struct iwl_bt_coex_cmd cmd = {
-		.valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
-		.bt_reduced_tx_power = sta_id,
+	struct iwl_bt_coex_cmd *bt_cmd;
+	/* Send ASYNC since this can be sent from an atomic context */
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_DUP, },
+		.flags = CMD_ASYNC,
 	};
+
 	struct ieee80211_sta *sta;
 	struct iwl_mvm_sta *mvmsta;
+	int ret;
 
 	/* This can happen if the station has been removed right now */
 	if (sta_id == IWL_MVM_STATION_COUNT)
@@ -339,17 +376,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
 	if (mvmsta->bt_reduced_txpower == enable)
 		return 0;
 
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
+	if (!bt_cmd)
+		return -ENOMEM;
+	cmd.data[0] = bt_cmd;
+
+	bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
+	bt_cmd->bt_reduced_tx_power = sta_id;
+
 	if (enable)
-		cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+		bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
 
 	IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
 		       enable ? "en" : "dis", sta_id);
 
 	mvmsta->bt_reduced_txpower = enable;
 
-	/* Send ASYNC since this can be sent from an atomic context */
-	return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC,
-				    sizeof(cmd), &cmd);
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
 }
 
 struct iwl_bt_iterator_data {
@@ -384,6 +430,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
 
 	smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
+	/* non associated BSSes aren't to be considered */
+	if (!vif->bss_conf.assoc)
+		return;
+
 	if (band != IEEE80211_BAND_2GHZ) {
 		iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
 				    smps_mode);
@@ -523,6 +573,8 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
 					lockdep_is_held(&mvm->mutex));
 	mvmsta = (void *)sta->drv_priv;
 
+	data->num_bss_ifaces++;
+
 	/*
 	 * This interface doesn't support reduced Tx power (because of low
 	 * RSSI probably), then set bt_kill_msk to default values.
@@ -588,23 +640,5 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
-	struct ieee80211_chanctx_conf *chanctx_conf;
-	enum ieee80211_band band;
-
-	rcu_read_lock();
-	chanctx_conf = rcu_dereference(vif->chanctx_conf);
-	if (chanctx_conf && chanctx_conf->def.chan)
-		band = chanctx_conf->def.chan->band;
-	else
-		band = -1;
-	rcu_read_unlock();
-
-	/* if we are in 2GHz we will get a notification from the fw */
-	if (band == IEEE80211_BAND_2GHZ)
-		return;
-
-	/* else, we can remove all the constraints */
-	memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
-
 	iwl_mvm_bt_coex_notif_handle(mvm);
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
new file mode 100644
index 0000000..64656e0
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __MVM_CONSTANTS_H
+#define __MVM_CONSTANTS_H
+
+#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT	(100 * USEC_PER_MSEC)
+#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT	(100 * USEC_PER_MSEC)
+#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT	(10 * USEC_PER_MSEC)
+#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT	(10 * USEC_PER_MSEC)
+
+#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 83da884..d0d7a20 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -105,7 +105,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
 	list_for_each_entry(ifa, &idev->addr_list, if_list) {
 		mvmvif->target_ipv6_addrs[idx] = ifa->addr;
 		idx++;
-		if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS)
+		if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)
 			break;
 	}
 	read_unlock_bh(&idev->lock);
@@ -378,36 +378,68 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
 static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
 				      struct ieee80211_vif *vif)
 {
-	struct iwl_proto_offload_cmd cmd = {};
+	union {
+		struct iwl_proto_offload_cmd_v1 v1;
+		struct iwl_proto_offload_cmd_v2 v2;
+	} cmd = {};
+	struct iwl_proto_offload_cmd_common *common;
+	u32 enabled = 0, size;
 #if IS_ENABLED(CONFIG_IPV6)
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	int i;
 
-	if (mvmvif->num_target_ipv6_addrs) {
-		cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_NS);
-		memcpy(cmd.ndp_mac_addr, vif->addr, ETH_ALEN);
-	}
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
+		if (mvmvif->num_target_ipv6_addrs) {
+			enabled |= IWL_D3_PROTO_OFFLOAD_NS;
+			memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN);
+		}
+
+		BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) !=
+			     sizeof(mvmvif->target_ipv6_addrs[0]));
+
+		for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
+				    IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++)
+			memcpy(cmd.v2.target_ipv6_addr[i],
+			       &mvmvif->target_ipv6_addrs[i],
+			       sizeof(cmd.v2.target_ipv6_addr[i]));
+	} else {
+		if (mvmvif->num_target_ipv6_addrs) {
+			enabled |= IWL_D3_PROTO_OFFLOAD_NS;
+			memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN);
+		}
 
-	BUILD_BUG_ON(sizeof(cmd.target_ipv6_addr[i]) !=
-		     sizeof(mvmvif->target_ipv6_addrs[i]));
+		BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) !=
+			     sizeof(mvmvif->target_ipv6_addrs[0]));
 
-	for (i = 0; i < mvmvif->num_target_ipv6_addrs; i++)
-		memcpy(cmd.target_ipv6_addr[i],
-		       &mvmvif->target_ipv6_addrs[i],
-		       sizeof(cmd.target_ipv6_addr[i]));
+		for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
+				    IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++)
+			memcpy(cmd.v1.target_ipv6_addr[i],
+			       &mvmvif->target_ipv6_addrs[i],
+			       sizeof(cmd.v1.target_ipv6_addr[i]));
+	}
 #endif
 
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
+		common = &cmd.v2.common;
+		size = sizeof(cmd.v2);
+	} else {
+		common = &cmd.v1.common;
+		size = sizeof(cmd.v1);
+	}
+
 	if (vif->bss_conf.arp_addr_cnt) {
-		cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_ARP);
-		cmd.host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
-		memcpy(cmd.arp_mac_addr, vif->addr, ETH_ALEN);
+		enabled |= IWL_D3_PROTO_OFFLOAD_ARP;
+		common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
+		memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
 	}
 
-	if (!cmd.enabled)
+	if (!enabled)
 		return 0;
 
+	common->enabled = cpu_to_le32(enabled);
+
 	return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC,
-				    sizeof(cmd), &cmd);
+				    size, &cmd);
 }
 
 enum iwl_mvm_tcp_packet_type {
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index c24a744..56f6827 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -424,40 +424,11 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
 	struct ieee80211_vif *vif = file->private_data;
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_mvm *mvm = mvmvif->dbgfs_data;
-	struct iwl_powertable_cmd cmd = {};
 	char buf[256];
 	int bufsz = sizeof(buf);
-	int pos = 0;
+	int pos;
 
-	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
-
-	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
-			 (cmd.flags &
-			 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
-			 0 : 1);
-	pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
-			 le32_to_cpu(cmd.skip_dtim_periods));
-	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
-			 iwlmvm_mod_params.power_scheme);
-	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
-			 le16_to_cpu(cmd.flags));
-	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
-			 cmd.keep_alive_seconds);
-
-	if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
-		pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
-				 (cmd.flags &
-				 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
-				 1 : 0);
-		pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
-				 le32_to_cpu(cmd.rx_data_timeout));
-		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
-				 le32_to_cpu(cmd.tx_data_timeout));
-		if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
-			pos += scnprintf(buf+pos, bufsz-pos,
-					 "lprx_rssi_threshold = %d\n",
-					 le32_to_cpu(cmd.lprx_rssi_threshold));
-	}
+	pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
@@ -626,20 +597,19 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
 					  size_t count, loff_t *ppos)
 {
 	struct iwl_mvm *mvm = file->private_data;
-	bool restart_fw = iwlwifi_mod_params.restart_fw;
 	int ret;
 
-	iwlwifi_mod_params.restart_fw = true;
-
 	mutex_lock(&mvm->mutex);
 
+	/* allow one more restart that we're provoking here */
+	if (mvm->restart_fw >= 0)
+		mvm->restart_fw++;
+
 	/* take the return value to make compiler happy - it will fail anyway */
 	ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
 
 	mutex_unlock(&mvm->mutex);
 
-	iwlwifi_mod_params.restart_fw = restart_fw;
-
 	return count;
 }
 
@@ -661,8 +631,14 @@ static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
 	case MVM_DEBUGFS_BF_ROAMING_STATE:
 		dbgfs_bf->bf_roaming_state = value;
 		break;
-	case MVM_DEBUGFS_BF_TEMPERATURE_DELTA:
-		dbgfs_bf->bf_temperature_delta = value;
+	case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
+		dbgfs_bf->bf_temp_threshold = value;
+		break;
+	case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
+		dbgfs_bf->bf_temp_fast_filter = value;
+		break;
+	case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
+		dbgfs_bf->bf_temp_slow_filter = value;
 		break;
 	case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
 		dbgfs_bf->bf_enable_beacon_filter = value;
@@ -721,13 +697,27 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
 		    value > IWL_BF_ROAMING_STATE_MAX)
 			return -EINVAL;
 		param = MVM_DEBUGFS_BF_ROAMING_STATE;
-	} else if (!strncmp("bf_temperature_delta=", buf, 21)) {
-		if (sscanf(buf+21, "%d", &value) != 1)
+	} else if (!strncmp("bf_temp_threshold=", buf, 18)) {
+		if (sscanf(buf+18, "%d", &value) != 1)
+			return -EINVAL;
+		if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
+		    value > IWL_BF_TEMP_THRESHOLD_MAX)
+			return -EINVAL;
+		param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
+	} else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
+		if (sscanf(buf+20, "%d", &value) != 1)
+			return -EINVAL;
+		if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
+		    value > IWL_BF_TEMP_FAST_FILTER_MAX)
+			return -EINVAL;
+		param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
+	} else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
+		if (sscanf(buf+20, "%d", &value) != 1)
 			return -EINVAL;
-		if (value < IWL_BF_TEMPERATURE_DELTA_MIN ||
-		    value > IWL_BF_TEMPERATURE_DELTA_MAX)
+		if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
+		    value > IWL_BF_TEMP_SLOW_FILTER_MAX)
 			return -EINVAL;
-		param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA;
+		param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
 	} else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
 		if (sscanf(buf+24, "%d", &value) != 1)
 			return -EINVAL;
@@ -789,41 +779,41 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
 	int pos = 0;
 	const size_t bufsz = sizeof(buf);
 	struct iwl_beacon_filter_cmd cmd = {
-		.bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT,
-		.bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT,
-		.bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT,
-		.bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT,
-		.bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT,
-		.bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
-		.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
-		.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
-		.ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
+		IWL_BF_CMD_CONFIG_DEFAULTS,
+		.bf_enable_beacon_filter =
+			cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
+		.ba_enable_beacon_abort =
+			cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
 	};
 
 	iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
 	if (mvmvif->bf_enabled)
-		cmd.bf_enable_beacon_filter = 1;
+		cmd.bf_enable_beacon_filter = cpu_to_le32(1);
 	else
 		cmd.bf_enable_beacon_filter = 0;
 
 	pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
-			 cmd.bf_energy_delta);
+			 le32_to_cpu(cmd.bf_energy_delta));
 	pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
-			 cmd.bf_roaming_energy_delta);
+			 le32_to_cpu(cmd.bf_roaming_energy_delta));
 	pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
-			 cmd.bf_roaming_state);
-	pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n",
-			 cmd.bf_temperature_delta);
+			 le32_to_cpu(cmd.bf_roaming_state));
+	pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
+			 le32_to_cpu(cmd.bf_temp_threshold));
+	pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
+			 le32_to_cpu(cmd.bf_temp_fast_filter));
+	pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
+			 le32_to_cpu(cmd.bf_temp_slow_filter));
 	pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
-			 cmd.bf_enable_beacon_filter);
+			 le32_to_cpu(cmd.bf_enable_beacon_filter));
 	pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
-			 cmd.bf_debug_flag);
+			 le32_to_cpu(cmd.bf_debug_flag));
 	pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
-			 cmd.bf_escape_timer);
+			 le32_to_cpu(cmd.bf_escape_timer));
 	pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
-			 cmd.ba_escape_timer);
+			 le32_to_cpu(cmd.ba_escape_timer));
 	pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
-			 cmd.ba_enable_beacon_abort);
+			 le32_to_cpu(cmd.ba_enable_beacon_abort));
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 6f8b2c1..df72fcdf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -98,34 +98,63 @@ enum iwl_proto_offloads {
 	IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
 };
 
-#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS	2
+#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1	2
+#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2	6
+#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX	6
 
 /**
- * struct iwl_proto_offload_cmd - ARP/NS offload configuration
+ * struct iwl_proto_offload_cmd_common - ARP/NS offload common part
  * @enabled: enable flags
  * @remote_ipv4_addr: remote address to answer to (or zero if all)
  * @host_ipv4_addr: our IPv4 address to respond to queries for
  * @arp_mac_addr: our MAC address for ARP responses
- * @remote_ipv6_addr: remote address to answer to (or zero if all)
- * @solicited_node_ipv6_addr: broken -- solicited node address exists
- *	for each target address
- * @target_ipv6_addr: our target addresses
- * @ndp_mac_addr: neighbor soliciation response MAC address
+ * @reserved: unused
  */
-struct iwl_proto_offload_cmd {
+struct iwl_proto_offload_cmd_common {
 	__le32 enabled;
 	__be32 remote_ipv4_addr;
 	__be32 host_ipv4_addr;
 	u8 arp_mac_addr[ETH_ALEN];
-	__le16 reserved1;
+	__le16 reserved;
+} __packed;
 
+/**
+ * struct iwl_proto_offload_cmd_v1 - ARP/NS offload configuration
+ * @common: common/IPv4 configuration
+ * @remote_ipv6_addr: remote address to answer to (or zero if all)
+ * @solicited_node_ipv6_addr: broken -- solicited node address exists
+ *	for each target address
+ * @target_ipv6_addr: our target addresses
+ * @ndp_mac_addr: neighbor soliciation response MAC address
+ */
+struct iwl_proto_offload_cmd_v1 {
+	struct iwl_proto_offload_cmd_common common;
 	u8 remote_ipv6_addr[16];
 	u8 solicited_node_ipv6_addr[16];
-	u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16];
+	u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1][16];
 	u8 ndp_mac_addr[ETH_ALEN];
 	__le16 reserved2;
 } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
 
+/**
+ * struct iwl_proto_offload_cmd_v2 - ARP/NS offload configuration
+ * @common: common/IPv4 configuration
+ * @remote_ipv6_addr: remote address to answer to (or zero if all)
+ * @solicited_node_ipv6_addr: broken -- solicited node address exists
+ *	for each target address
+ * @target_ipv6_addr: our target addresses
+ * @ndp_mac_addr: neighbor soliciation response MAC address
+ */
+struct iwl_proto_offload_cmd_v2 {
+	struct iwl_proto_offload_cmd_common common;
+	u8 remote_ipv6_addr[16];
+	u8 solicited_node_ipv6_addr[16];
+	u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16];
+	u8 ndp_mac_addr[ETH_ALEN];
+	u8 numValidIPv6Addresses;
+	u8 reserved2[3];
+} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
+
 
 /*
  * WOWLAN_PATTERNS
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index a6da359..060e630 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -79,6 +79,10 @@
  *		'1' Driver enables PM (use rest of parameters)
  * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
  *		'1' PM could sleep over DTIM till listen Interval.
+ * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
+ *		access categories are both delivery and trigger enabled.
+ * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
+ *		PBW Snoozing enabled
  * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
  * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
 */
@@ -86,6 +90,8 @@ enum iwl_power_flags {
 	POWER_FLAGS_POWER_SAVE_ENA_MSK		= BIT(0),
 	POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK	= BIT(1),
 	POWER_FLAGS_SKIP_OVER_DTIM_MSK		= BIT(2),
+	POWER_FLAGS_SNOOZE_ENA_MSK		= BIT(5),
+	POWER_FLAGS_BT_SCO_ENA			= BIT(8),
 	POWER_FLAGS_ADVANCE_PM_ENA_MSK		= BIT(9),
 	POWER_FLAGS_LPRX_ENA_MSK		= BIT(11),
 };
@@ -93,7 +99,8 @@ enum iwl_power_flags {
 #define IWL_POWER_VEC_SIZE 5
 
 /**
- * struct iwl_powertable_cmd - Power Table Command
+ * struct iwl_powertable_cmd - legacy power command. Beside old API support this
+ *	is used also with a new	power API for device wide power settings.
  * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
  *
  * @flags:		Power table command flags from POWER_FLAGS_*
@@ -125,6 +132,72 @@ struct iwl_powertable_cmd {
 } __packed;
 
 /**
+ * struct iwl_mac_power_cmd - New power command containing uAPSD support
+ * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
+ * @id_and_color:	MAC contex identifier
+ * @flags:		Power table command flags from POWER_FLAGS_*
+ * @keep_alive_seconds:	Keep alive period in seconds. Default - 25 sec.
+ *			Minimum allowed:- 3 * DTIM. Keep alive period must be
+ *			set regardless of power scheme or current power state.
+ *			FW use this value also when PM is disabled.
+ * @rx_data_timeout:    Minimum time (usec) from last Rx packet for AM to
+ *			PSM transition - legacy PM
+ * @tx_data_timeout:    Minimum time (usec) from last Tx packet for AM to
+ *			PSM transition - legacy PM
+ * @sleep_interval:	not in use
+ * @skip_dtim_periods:	Number of DTIM periods to skip if Skip over DTIM flag
+ *			is set. For example, if it is required to skip over
+ *			one DTIM, this value need to be set to 2 (DTIM periods).
+ * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
+ *			PSM transition - uAPSD
+ * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
+ *			PSM transition - uAPSD
+ * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
+ *			Default: 80dbm
+ * @num_skip_dtim:	Number of DTIMs to skip if Skip over DTIM flag is set
+ * @snooze_interval:	TBD
+ * @snooze_window:	TBD
+ * @snooze_step:	TBD
+ * @qndp_tid:		TID client shall use for uAPSD QNDP triggers
+ * @uapsd_ac_flags:	Set trigger-enabled and delivery-enabled indication for
+ *			each corresponding AC.
+ *			Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.
+ * @uapsd_max_sp:	Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct
+ *			values.
+ * @heavy_traffic_thr_tx_pkts:	TX threshold measured in number of packets
+ * @heavy_traffic_thr_rx_pkts:	RX threshold measured in number of packets
+ * @heavy_traffic_thr_tx_load:	TX threshold measured in load's percentage
+ * @heavy_traffic_thr_rx_load:	RX threshold measured in load's percentage
+ * @limited_ps_threshold:
+*/
+struct iwl_mac_power_cmd {
+	/* CONTEXT_DESC_API_T_VER_1 */
+	__le32 id_and_color;
+
+	/* CLIENT_PM_POWER_TABLE_S_VER_1 */
+	__le16 flags;
+	__le16 keep_alive_seconds;
+	__le32 rx_data_timeout;
+	__le32 tx_data_timeout;
+	__le32 rx_data_timeout_uapsd;
+	__le32 tx_data_timeout_uapsd;
+	u8 lprx_rssi_threshold;
+	u8 skip_dtim_periods;
+	__le16 snooze_interval;
+	__le16 snooze_window;
+	u8 snooze_step;
+	u8 qndp_tid;
+	u8 uapsd_ac_flags;
+	u8 uapsd_max_sp;
+	u8 heavy_traffic_threshold_tx_packets;
+	u8 heavy_traffic_threshold_rx_packets;
+	u8 heavy_traffic_threshold_tx_percentage;
+	u8 heavy_traffic_threshold_rx_percentage;
+	u8 limited_ps_threshold;
+	u8 reserved;
+} __packed;
+
+/**
  * struct iwl_beacon_filter_cmd
  * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
  * @id_and_color: MAC contex identifier
@@ -143,11 +216,21 @@ struct iwl_powertable_cmd {
  *      calculated for current beacon is less than the threshold, use
  *      Roaming Energy Delta Threshold, otherwise use normal Energy Delta
  *      Threshold. Typical energy threshold is -72dBm.
- * @bf_temperature_delta: Send Beacon to driver if delta in temperature values
- *      calculated for this and the last passed beacon is greater than  this
- *      threshold. Zero value means that the temperature changeis ignored for
+ * @bf_temp_threshold: This threshold determines the type of temperature
+ *	filtering (Slow or Fast) that is selected (Units are in Celsuis):
+ *      If the current temperature is above this threshold - Fast filter
+ *	will be used, If the current temperature is below this threshold -
+ *	Slow filter will be used.
+ * @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values
+ *      calculated for this and the last passed beacon is greater than this
+ *      threshold. Zero value means that the temperature change is ignored for
  *      beacon filtering; beacons will not be  forced to be sent to driver
  *      regardless of whether its temerature has been changed.
+ * @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values
+ *      calculated for this and the last passed beacon is greater than this
+ *      threshold. Zero value means that the temperature change is ignored for
+ *      beacon filtering; beacons will not be forced to be sent to driver
+ *      regardless of whether its temerature has been changed.
  * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
  * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
  *      for a specific period of time. Units: Beacons.
@@ -156,17 +239,17 @@ struct iwl_powertable_cmd {
  * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
  */
 struct iwl_beacon_filter_cmd {
-	u8 bf_energy_delta;
-	u8 bf_roaming_energy_delta;
-	u8 bf_roaming_state;
-	u8 bf_temperature_delta;
-	u8 bf_enable_beacon_filter;
-	u8 bf_debug_flag;
-	__le16 reserved1;
+	__le32 bf_energy_delta;
+	__le32 bf_roaming_energy_delta;
+	__le32 bf_roaming_state;
+	__le32 bf_temp_threshold;
+	__le32 bf_temp_fast_filter;
+	__le32 bf_temp_slow_filter;
+	__le32 bf_enable_beacon_filter;
+	__le32 bf_debug_flag;
 	__le32 bf_escape_timer;
 	__le32 ba_escape_timer;
-	u8 ba_enable_beacon_abort;
-	u8 reserved2[3];
+	__le32 ba_enable_beacon_abort;
 } __packed;
 
 /* Beacon filtering and beacon abort */
@@ -182,9 +265,17 @@ struct iwl_beacon_filter_cmd {
 #define IWL_BF_ROAMING_STATE_MAX 255
 #define IWL_BF_ROAMING_STATE_MIN 0
 
-#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5
-#define IWL_BF_TEMPERATURE_DELTA_MAX 255
-#define IWL_BF_TEMPERATURE_DELTA_MIN 0
+#define IWL_BF_TEMP_THRESHOLD_DEFAULT 112
+#define IWL_BF_TEMP_THRESHOLD_MAX 255
+#define IWL_BF_TEMP_THRESHOLD_MIN 0
+
+#define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1
+#define IWL_BF_TEMP_FAST_FILTER_MAX 255
+#define IWL_BF_TEMP_FAST_FILTER_MIN 0
+
+#define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5
+#define IWL_BF_TEMP_SLOW_FILTER_MAX 255
+#define IWL_BF_TEMP_SLOW_FILTER_MIN 0
 
 #define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
 
@@ -194,19 +285,23 @@ struct iwl_beacon_filter_cmd {
 #define IWL_BF_ESCAPE_TIMER_MAX 1024
 #define IWL_BF_ESCAPE_TIMER_MIN 0
 
-#define IWL_BA_ESCAPE_TIMER_DEFAULT 3
+#define IWL_BA_ESCAPE_TIMER_DEFAULT 6
+#define IWL_BA_ESCAPE_TIMER_D3 6
 #define IWL_BA_ESCAPE_TIMER_MAX 1024
 #define IWL_BA_ESCAPE_TIMER_MIN 0
 
 #define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
 
-#define IWL_BF_CMD_CONFIG_DEFAULTS					\
-	.bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT,			\
-	.bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT,	\
-	.bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT,		\
-	.bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT,	\
-	.bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,			\
-	.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),	\
+#define IWL_BF_CMD_CONFIG_DEFAULTS					     \
+	.bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA_DEFAULT),	     \
+	.bf_roaming_energy_delta =					     \
+		cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT),	     \
+	.bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE_DEFAULT),	     \
+	.bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD_DEFAULT),     \
+	.bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER_DEFAULT), \
+	.bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER_DEFAULT), \
+	.bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG_DEFAULT),	     \
+	.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),	     \
 	.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
 
 #endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 365095a..83cb9b9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -137,6 +137,8 @@ struct iwl_ssid_ie {
  *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND:
  *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND:
  *@SCAN_FLAGS_FRAGMENTED_SCAN:
+ *@SCAN_FLAGS_PASSIVE2ACTIVE: use active scan on channels that was active
+ *	in the past hour, even if they are marked as passive.
  */
 enum iwl_scan_flags {
 	SCAN_FLAGS_PERIODIC_SCAN		= BIT(0),
@@ -144,6 +146,7 @@ enum iwl_scan_flags {
 	SCAN_FLAGS_DELAYED_SCAN_LOWBAND		= BIT(2),
 	SCAN_FLAGS_DELAYED_SCAN_HIGHBAND	= BIT(3),
 	SCAN_FLAGS_FRAGMENTED_SCAN		= BIT(4),
+	SCAN_FLAGS_PASSIVE2ACTIVE		= BIT(5),
 };
 
 /**
@@ -178,7 +181,7 @@ enum iwl_scan_type {
  * @quiet_time: in msecs, dwell this time for active scan on quiet channels
  * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
  *	this number of packets were received (typically 1)
- * @passive2active: is auto switching from passive to active allowed (0 or 1)
+ * @passive2active: is auto switching from passive to active during scan allowed
  * @rxchain_sel_flags: RXON_RX_CHAIN_*
  * @max_out_time: in usecs, max out of serving channel time
  * @suspend_time: how long to pause scan when returning to service channel:
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
index 700cce7..d606197 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
@@ -91,7 +91,6 @@
  * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
  * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration
  * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation
- * @TX_CMD_FLG_CTS_ONLY: send CTS only, no data after that
  * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id
  * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped
  * @TX_CMD_FLG_EXEC_PAPD: execute PAPD
@@ -120,7 +119,6 @@ enum iwl_tx_flags {
 	TX_CMD_FLG_RESP_TO_DRV		= BIT(21),
 	TX_CMD_FLG_CCMP_AGG		= BIT(22),
 	TX_CMD_FLG_TKIP_MIC_DONE	= BIT(23),
-	TX_CMD_FLG_CTS_ONLY		= BIT(24),
 	TX_CMD_FLG_DUR			= BIT(25),
 	TX_CMD_FLG_FW_DROP		= BIT(26),
 	TX_CMD_FLG_EXEC_PAPD		= BIT(27),
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index cbfb3be..55854a3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -136,7 +136,7 @@ enum {
 	CALIB_RES_NOTIF_PHY_DB = 0x6b,
 	/* PHY_DB_CMD = 0x6c, */
 
-	/* Power */
+	/* Power - legacy power table command */
 	POWER_TABLE_CMD = 0x77,
 
 	/* Thermal Throttling*/
@@ -159,6 +159,7 @@ enum {
 	TX_ANT_CONFIGURATION_CMD = 0x98,
 	BT_CONFIG = 0x9b,
 	STATISTICS_NOTIFICATION = 0x9d,
+	REDUCE_TX_POWER_CMD = 0x9f,
 
 	/* RF-KILL commands and notifications */
 	CARD_STATE_CMD = 0xa0,
@@ -166,6 +167,9 @@ enum {
 
 	MISSED_BEACONS_NOTIFICATION = 0xa2,
 
+	/* Power - new power table command */
+	MAC_PM_POWER_TABLE = 0xa9,
+
 	REPLY_RX_PHY_CMD = 0xc0,
 	REPLY_RX_MPDU_CMD = 0xc1,
 	BA_NOTIF = 0xc5,
@@ -223,6 +227,19 @@ struct iwl_tx_ant_cfg_cmd {
 	__le32 valid;
 } __packed;
 
+/**
+ * struct iwl_reduce_tx_power_cmd - TX power reduction command
+ * REDUCE_TX_POWER_CMD = 0x9f
+ * @flags: (reserved for future implementation)
+ * @mac_context_id: id of the mac ctx for which we are reducing TX power.
+ * @pwr_restriction: TX power restriction in dBms.
+ */
+struct iwl_reduce_tx_power_cmd {
+	u8 flags;
+	u8 mac_context_id;
+	__le16 pwr_restriction;
+} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
+
 /*
  * Calibration control struct.
  * Sent as part of the phy configuration command.
@@ -765,6 +782,14 @@ struct iwl_phy_context_cmd {
 } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
 
 #define IWL_RX_INFO_PHY_CNT 8
+#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
+#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
+#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
+#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
+#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
+#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
+#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
+
 #define IWL_RX_INFO_AGC_IDX 1
 #define IWL_RX_INFO_RSSI_AB_IDX 2
 #define IWL_OFDM_AGC_A_MSK 0x0000007f
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index cd7c003..c76299a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -78,22 +78,6 @@
 
 #define UCODE_VALID_OK	cpu_to_le32(0x1)
 
-/* Default calibration values for WkP - set to INIT image w/o running */
-static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
-static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
-
-struct iwl_calib_default_data {
-	u16 size;
-	void *data;
-};
-
-#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
-
-static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
-	[9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
-	[11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
-};
-
 struct iwl_mvm_alive_data {
 	bool valid;
 	u32 scd_base_addr;
@@ -248,40 +232,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
 				    sizeof(phy_cfg_cmd), &phy_cfg_cmd);
 }
 
-static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
-{
-	u8 cmd_raw[16]; /* holds the variable size commands */
-	struct iwl_set_calib_default_cmd *cmd =
-		(struct iwl_set_calib_default_cmd *)cmd_raw;
-	int ret, i;
-
-	/* Setting default values for calibrations we don't run */
-	for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
-		u16 cmd_len;
-
-		if (wkp_calib_default_data[i].size == 0)
-			continue;
-
-		memset(cmd_raw, 0, sizeof(cmd_raw));
-		cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
-		cmd->calib_index = cpu_to_le16(i);
-		cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
-		if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
-			      "Need to enlarge cmd_raw to %d\n", cmd_len))
-			break;
-		memcpy(cmd->data, wkp_calib_default_data[i].data,
-		       wkp_calib_default_data[i].size);
-		ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
-					   sizeof(*cmd) +
-					   wkp_calib_default_data[i].size,
-					   cmd);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 {
 	struct iwl_notification_wait calib_wait;
@@ -342,11 +292,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 	if (ret)
 		goto error;
 
-	/* need to set default values */
-	ret = iwl_set_default_calibrations(mvm);
-	if (ret)
-		goto error;
-
 	/*
 	 * Send phy configurations command to init uCode
 	 * to start the 16.0 uCode init image internal calibrations.
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 94aae9c..5fe23a5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -264,7 +264,8 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
 		return 0;
 
 	/* Therefore, in recovery, we can't get here */
-	WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
+	if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
+		return -EBUSY;
 
 	mvmvif->id = find_first_bit(data.available_mac_ids,
 				    NUM_MAC_INDEX_DRIVER);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index f19baf0..785c782 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -153,7 +153,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		    IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_TIMING_BEACON_ONLY |
-		    IEEE80211_HW_CONNECTION_MONITOR;
+		    IEEE80211_HW_CONNECTION_MONITOR |
+		    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
+		    IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
 	hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
 	hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
@@ -552,6 +554,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 			goto out_release;
 		}
 
+		iwl_mvm_vif_dbgfs_register(mvm, vif);
 		goto out_unlock;
 	}
 
@@ -567,7 +570,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 
 	/* beacon filtering */
 	if (!mvm->bf_allowed_vif &&
-	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p){
+	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
+	    mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
 		mvm->bf_allowed_vif = mvmvif;
 		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
 	}
@@ -719,6 +723,20 @@ out_release:
 	mutex_unlock(&mvm->mutex);
 }
 
+static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+				s8 tx_power)
+{
+	/* FW is in charge of regulatory enforcement */
+	struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
+		.mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
+		.pwr_restriction = cpu_to_le16(tx_power),
+	};
+
+	return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
+				    sizeof(reduce_txpwr_cmd),
+				    &reduce_txpwr_cmd);
+}
+
 static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
 {
 	return 0;
@@ -766,7 +784,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 				IWL_ERR(mvm, "failed to update quotas\n");
 				return;
 			}
-			iwl_mvm_bt_coex_vif_assoc(mvm, vif);
 			iwl_mvm_configure_mcast_filter(mvm, vif);
 		} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
 			/* remove AP station now that the MAC is unassoc */
@@ -779,9 +796,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 			if (ret)
 				IWL_ERR(mvm, "failed to update quotas\n");
 		}
-		ret = iwl_mvm_power_update_mode(mvm, vif);
-		if (ret)
-			IWL_ERR(mvm, "failed to update power mode\n");
+		if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) {
+			/* Workaround for FW bug, otherwise FW disables device
+			 * power save upon disassociation
+			 */
+			ret = iwl_mvm_power_update_mode(mvm, vif);
+			if (ret)
+				IWL_ERR(mvm, "failed to update power mode\n");
+		}
+		iwl_mvm_bt_coex_vif_assoc(mvm, vif);
 	} else if (changes & BSS_CHANGED_BEACON_INFO) {
 		/*
 		 * We received a beacon _after_ association so
@@ -794,6 +817,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 		if (ret)
 			IWL_ERR(mvm, "failed to update power mode\n");
 	}
+	if (changes & BSS_CHANGED_TXPOWER) {
+		IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
+				bss_conf->txpower);
+		iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
+	}
 }
 
 static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 420e82d..29bebae 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -76,6 +76,7 @@
 #include "iwl-trans.h"
 #include "sta.h"
 #include "fw-api.h"
+#include "constants.h"
 
 #define IWL_INVALID_MAC80211_QUEUE	0xff
 #define IWL_MVM_MAX_ADDRESSES		5
@@ -91,6 +92,9 @@ enum iwl_mvm_tx_fifo {
 };
 
 extern struct ieee80211_ops iwl_mvm_hw_ops;
+extern const struct iwl_mvm_power_ops pm_legacy_ops;
+extern const struct iwl_mvm_power_ops pm_mac_ops;
+
 /**
  * struct iwl_mvm_mod_params - module parameters for iwlmvm
  * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted.
@@ -150,6 +154,17 @@ enum iwl_power_scheme {
 
 #define IWL_CONN_MAX_LISTEN_INTERVAL	70
 
+struct iwl_mvm_power_ops {
+	int (*power_update_mode)(struct iwl_mvm *mvm,
+				 struct ieee80211_vif *vif);
+	int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+				char *buf, int bufsz);
+#endif
+};
+
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 enum iwl_dbgfs_pm_mask {
 	MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0),
@@ -163,7 +178,7 @@ enum iwl_dbgfs_pm_mask {
 };
 
 struct iwl_dbgfs_pm {
-	u8 keep_alive_seconds;
+	u16 keep_alive_seconds;
 	u32 rx_data_timeout;
 	u32 tx_data_timeout;
 	bool skip_over_dtim;
@@ -180,24 +195,28 @@ enum iwl_dbgfs_bf_mask {
 	MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0),
 	MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1),
 	MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2),
-	MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3),
-	MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4),
-	MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5),
-	MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6),
-	MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7),
-	MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8),
+	MVM_DEBUGFS_BF_TEMP_THRESHOLD = BIT(3),
+	MVM_DEBUGFS_BF_TEMP_FAST_FILTER = BIT(4),
+	MVM_DEBUGFS_BF_TEMP_SLOW_FILTER = BIT(5),
+	MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(6),
+	MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(7),
+	MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(8),
+	MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(9),
+	MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(10),
 };
 
 struct iwl_dbgfs_bf {
-	u8 bf_energy_delta;
-	u8 bf_roaming_energy_delta;
-	u8 bf_roaming_state;
-	u8 bf_temperature_delta;
-	u8 bf_enable_beacon_filter;
-	u8 bf_debug_flag;
+	u32 bf_energy_delta;
+	u32 bf_roaming_energy_delta;
+	u32 bf_roaming_state;
+	u32 bf_temp_threshold;
+	u32 bf_temp_fast_filter;
+	u32 bf_temp_slow_filter;
+	u32 bf_enable_beacon_filter;
+	u32 bf_debug_flag;
 	u32 bf_escape_timer;
 	u32 ba_escape_timer;
-	u8 ba_enable_beacon_abort;
+	u32 ba_enable_beacon_abort;
 	int mask;
 };
 #endif
@@ -268,7 +287,7 @@ struct iwl_mvm_vif {
 
 #if IS_ENABLED(CONFIG_IPV6)
 	/* IPv6 addresses for WoWLAN */
-	struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS];
+	struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
 	int num_target_ipv6_addrs;
 #endif
 #endif
@@ -459,6 +478,9 @@ struct iwl_mvm {
 	 */
 	u8 vif_count;
 
+	/* -1 for always, 0 for never, >0 for that many times */
+	s8 restart_fw;
+
 	struct led_classdev led;
 
 	struct ieee80211_vif *p2p_device_vif;
@@ -482,6 +504,8 @@ struct iwl_mvm {
 	/* Thermal Throttling and CTkill */
 	struct iwl_mvm_tt_mgmt thermal_throttle;
 	s32 temperature;	/* Celsius */
+
+	const struct iwl_mvm_power_ops *pm_ops;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -525,6 +549,7 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
 					enum ieee80211_band band);
 u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
 void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
+void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
 u8 first_antenna(u8 mask);
 u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
 
@@ -660,10 +685,26 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
 			u8 flags, bool init);
 
 /* power managment */
-int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-			     struct iwl_powertable_cmd *cmd);
+static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm,
+					    struct ieee80211_vif *vif)
+{
+	return mvm->pm_ops->power_update_mode(mvm, vif);
+}
+
+static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm,
+					struct ieee80211_vif *vif)
+{
+	return mvm->pm_ops->power_disable(mvm, vif);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
+					    struct ieee80211_vif *vif,
+					    char *buf, int bufsz)
+{
+	return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz);
+}
+#endif
 
 int iwl_mvm_leds_init(struct iwl_mvm *mvm);
 void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
@@ -707,6 +748,10 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
 				 struct ieee80211_vif *vif);
 int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
 				  struct ieee80211_vif *vif);
+int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
+				   struct iwl_beacon_filter_cmd *cmd);
+int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
+				struct ieee80211_vif *vif, bool enable);
 
 /* SMPS */
 void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index af79a14..65e5fb8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -275,6 +275,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 	CMD(BEACON_NOTIFICATION),
 	CMD(BEACON_TEMPLATE_CMD),
 	CMD(STATISTICS_NOTIFICATION),
+	CMD(REDUCE_TX_POWER_CMD),
 	CMD(TX_ANT_CONFIGURATION_CMD),
 	CMD(D3_CONFIG_CMD),
 	CMD(PROT_OFFLOAD_CONFIG_CMD),
@@ -301,6 +302,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 	CMD(MCAST_FILTER_CMD),
 	CMD(REPLY_BEACON_FILTERING_CMD),
 	CMD(REPLY_THERMAL_MNG_BACKOFF),
+	CMD(MAC_PM_POWER_TABLE),
 };
 #undef CMD
 
@@ -340,6 +342,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	mvm->fw = fw;
 	mvm->hw = hw;
 
+	mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
+
 	mutex_init(&mvm->mutex);
 	spin_lock_init(&mvm->async_handlers_lock);
 	INIT_LIST_HEAD(&mvm->time_event_list);
@@ -431,6 +435,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	if (err)
 		goto out_unregister;
 
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)
+		mvm->pm_ops = &pm_mac_ops;
+	else
+		mvm->pm_ops = &pm_legacy_ops;
+
 	return op_mode;
 
  out_unregister:
@@ -638,6 +647,22 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
 	ieee80211_free_txskb(mvm->hw, skb);
 }
 
+struct iwl_mvm_reprobe {
+	struct device *dev;
+	struct work_struct work;
+};
+
+static void iwl_mvm_reprobe_wk(struct work_struct *wk)
+{
+	struct iwl_mvm_reprobe *reprobe;
+
+	reprobe = container_of(wk, struct iwl_mvm_reprobe, work);
+	if (device_reprobe(reprobe->dev))
+		dev_err(reprobe->dev, "reprobe failed!\n");
+	kfree(reprobe);
+	module_put(THIS_MODULE);
+}
+
 static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 {
 	iwl_abort_notification_waits(&mvm->notif_wait);
@@ -649,9 +674,30 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 	 * can't recover this since we're already half suspended.
 	 */
 	if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
-		IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n");
-	} else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
-		   iwlwifi_mod_params.restart_fw) {
+		struct iwl_mvm_reprobe *reprobe;
+
+		IWL_ERR(mvm,
+			"Firmware error during reconfiguration - reprobe!\n");
+
+		/*
+		 * get a module reference to avoid doing this while unloading
+		 * anyway and to avoid scheduling a work with code that's
+		 * being removed.
+		 */
+		if (!try_module_get(THIS_MODULE)) {
+			IWL_ERR(mvm, "Module is being unloaded - abort\n");
+			return;
+		}
+
+		reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC);
+		if (!reprobe) {
+			module_put(THIS_MODULE);
+			return;
+		}
+		reprobe->dev = mvm->trans->dev;
+		INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
+		schedule_work(&reprobe->work);
+	} else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
 		/*
 		 * This is a bit racy, but worst case we tell mac80211 about
 		 * a stopped/aborted (sched) scan when that was already done
@@ -669,6 +715,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 			break;
 		}
 
+		if (mvm->restart_fw > 0)
+			mvm->restart_fw--;
 		ieee80211_restart_hw(mvm->hw);
 	}
 }
@@ -678,6 +726,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
 	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 
 	iwl_mvm_dump_nic_error_log(mvm);
+	if (!mvm->restart_fw)
+		iwl_mvm_dump_sram(mvm);
 
 	iwl_mvm_nic_restart(mvm);
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index e7ca965..4e7c9f2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -75,8 +75,8 @@
 
 #define POWER_KEEP_ALIVE_PERIOD_SEC    25
 
-static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
-					  struct iwl_beacon_filter_cmd *cmd)
+int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
+				   struct iwl_beacon_filter_cmd *cmd)
 {
 	int ret;
 
@@ -85,52 +85,60 @@ static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
 
 	if (!ret) {
 		IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
-				cmd->ba_enable_beacon_abort);
+				le32_to_cpu(cmd->ba_enable_beacon_abort));
 		IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
-				cmd->ba_escape_timer);
+				le32_to_cpu(cmd->ba_escape_timer));
 		IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
-				cmd->bf_debug_flag);
+				le32_to_cpu(cmd->bf_debug_flag));
 		IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
-				cmd->bf_enable_beacon_filter);
+				le32_to_cpu(cmd->bf_enable_beacon_filter));
 		IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
-				cmd->bf_energy_delta);
+				le32_to_cpu(cmd->bf_energy_delta));
 		IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
-				cmd->bf_escape_timer);
+				le32_to_cpu(cmd->bf_escape_timer));
 		IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
-				cmd->bf_roaming_energy_delta);
+				le32_to_cpu(cmd->bf_roaming_energy_delta));
 		IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
-				cmd->bf_roaming_state);
-		IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n",
-				cmd->bf_temperature_delta);
+				le32_to_cpu(cmd->bf_roaming_state));
+		IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
+				le32_to_cpu(cmd->bf_temp_threshold));
+		IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
+				le32_to_cpu(cmd->bf_temp_fast_filter));
+		IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
+				le32_to_cpu(cmd->bf_temp_slow_filter));
 	}
 	return ret;
 }
 
-static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
-				       struct ieee80211_vif *vif, bool enable)
+int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
+				struct ieee80211_vif *vif, bool enable)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_beacon_filter_cmd cmd = {
 		IWL_BF_CMD_CONFIG_DEFAULTS,
-		.bf_enable_beacon_filter = 1,
-		.ba_enable_beacon_abort = enable,
+		.bf_enable_beacon_filter = cpu_to_le32(1),
+		.ba_enable_beacon_abort = cpu_to_le32(enable),
 	};
 
 	if (!mvmvif->bf_enabled)
 		return 0;
 
+	if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
+		cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
+
 	iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
 	return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
 }
 
 static void iwl_mvm_power_log(struct iwl_mvm *mvm,
-			      struct iwl_powertable_cmd *cmd)
+			      struct iwl_mac_power_cmd *cmd)
 {
 	IWL_DEBUG_POWER(mvm,
-			"Sending power table command for power level %d, flags = 0x%X\n",
-			iwlmvm_mod_params.power_scheme,
+			"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
+			cmd->id_and_color, iwlmvm_mod_params.power_scheme,
 			le16_to_cpu(cmd->flags));
-	IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
+	IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
+			le16_to_cpu(cmd->keep_alive_seconds));
 
 	if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
 		IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
@@ -139,15 +147,16 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
 				le32_to_cpu(cmd->tx_data_timeout));
 		if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
 			IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
-					le32_to_cpu(cmd->skip_dtim_periods));
+					cmd->skip_dtim_periods);
 		if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
 			IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
-					le32_to_cpu(cmd->lprx_rssi_threshold));
+					cmd->lprx_rssi_threshold);
 	}
 }
 
-void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-			     struct iwl_powertable_cmd *cmd)
+static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
+				    struct ieee80211_vif *vif,
+				    struct iwl_mac_power_cmd *cmd)
 {
 	struct ieee80211_hw *hw = mvm->hw;
 	struct ieee80211_chanctx_conf *chanctx_conf;
@@ -158,19 +167,26 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	struct iwl_mvm_vif *mvmvif __maybe_unused =
 		iwl_mvm_vif_from_mac80211(vif);
 
+	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+							    mvmvif->color));
+	dtimper = hw->conf.ps_dtim_period ?: 1;
+
 	/*
 	 * Regardless of power management state the driver must set
 	 * keep alive period. FW will use it for sending keep alive NDPs
-	 * immediately after association.
+	 * immediately after association. Check that keep alive period
+	 * is at least 3 * DTIM
 	 */
-	cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
+	dtimper_msec = dtimper * vif->bss_conf.beacon_int;
+	keep_alive = max_t(int, 3 * dtimper_msec,
+			   MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
+	keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
+	cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
 
 	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
 		return;
 
 	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
-	if (!vif->bss_conf.assoc)
-		cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
@@ -186,12 +202,9 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	    (vif->bss_conf.beacon_rate->bitrate == 10 ||
 	     vif->bss_conf.beacon_rate->bitrate == 60)) {
 		cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
-		cmd->lprx_rssi_threshold =
-			cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
+		cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
 	}
 
-	dtimper = hw->conf.ps_dtim_period ?: 1;
-
 	/* Check if radar detection is required on current channel */
 	rcu_read_lock();
 	chanctx_conf = rcu_dereference(vif->chanctx_conf);
@@ -207,27 +220,25 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	    (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
 	     mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
 		cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
-		cmd->skip_dtim_periods = cpu_to_le32(3);
+		cmd->skip_dtim_periods = 3;
 	}
 
-	/* Check that keep alive period is at least 3 * DTIM */
-	dtimper_msec = dtimper * vif->bss_conf.beacon_int;
-	keep_alive = max_t(int, 3 * dtimper_msec,
-			   MSEC_PER_SEC * cmd->keep_alive_seconds);
-	keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
-	cmd->keep_alive_seconds = keep_alive;
-
 	if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
-		cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
-		cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
+		cmd->rx_data_timeout =
+			cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
+		cmd->tx_data_timeout =
+			cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
 	} else {
-		cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
-		cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
+		cmd->rx_data_timeout =
+			cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
+		cmd->tx_data_timeout =
+			cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
-		cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
+		cmd->keep_alive_seconds =
+			cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
 	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
 		if (mvmvif->dbgfs_pm.skip_over_dtim)
 			cmd->flags |=
@@ -243,8 +254,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 		cmd->tx_data_timeout =
 			cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
 	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
-		cmd->skip_dtim_periods =
-			cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
+		cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
 	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
 		if (mvmvif->dbgfs_pm.lprx_ena)
 			cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
@@ -252,16 +262,16 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
 	}
 	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
-		cmd->lprx_rssi_threshold =
-			cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
+		cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 }
 
-int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
+					 struct ieee80211_vif *vif)
 {
 	int ret;
 	bool ba_enable;
-	struct iwl_powertable_cmd cmd = {};
+	struct iwl_mac_power_cmd cmd = {};
 
 	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
@@ -280,7 +290,7 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
 	iwl_mvm_power_log(mvm, &cmd);
 
-	ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
+	ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
 				   sizeof(cmd), &cmd);
 	if (ret)
 		return ret;
@@ -291,15 +301,19 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 	return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
 }
 
-int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
+				     struct ieee80211_vif *vif)
 {
-	struct iwl_powertable_cmd cmd = {};
+	struct iwl_mac_power_cmd cmd = {};
 	struct iwl_mvm_vif *mvmvif __maybe_unused =
 		iwl_mvm_vif_from_mac80211(vif);
 
 	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
 
+	cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+							   mvmvif->color));
+
 	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
 		cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
 
@@ -310,11 +324,50 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 #endif
 	iwl_mvm_power_log(mvm, &cmd);
 
-	return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
+	return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC,
 				    sizeof(cmd), &cmd);
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
+static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
+					struct ieee80211_vif *vif, char *buf,
+					int bufsz)
+{
+	struct iwl_mac_power_cmd cmd = {};
+	int pos = 0;
+
+	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
+			 (cmd.flags &
+			 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
+			 0 : 1);
+	pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
+			 cmd.skip_dtim_periods);
+	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
+			 iwlmvm_mod_params.power_scheme);
+	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
+			 le16_to_cpu(cmd.flags));
+	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
+			 le16_to_cpu(cmd.keep_alive_seconds));
+
+	if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
+		pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
+				 (cmd.flags &
+				 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
+				 1 : 0);
+		pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
+				 le32_to_cpu(cmd.rx_data_timeout));
+		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
+				 le32_to_cpu(cmd.tx_data_timeout));
+		if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
+			pos += scnprintf(buf+pos, bufsz-pos,
+					 "lprx_rssi_threshold = %d\n",
+					 cmd.lprx_rssi_threshold);
+	}
+	return pos;
+}
+
 void
 iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
 					 struct iwl_beacon_filter_cmd *cmd)
@@ -323,22 +376,30 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
 	struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
 
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
-		cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta;
+		cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
 		cmd->bf_roaming_energy_delta =
-				 dbgfs_bf->bf_roaming_energy_delta;
+				cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
-		cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state;
-	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA)
-		cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta;
+		cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
+	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
+		cmd->bf_temp_threshold =
+				cpu_to_le32(dbgfs_bf->bf_temp_threshold);
+	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
+		cmd->bf_temp_fast_filter =
+				cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
+	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
+		cmd->bf_temp_slow_filter =
+				cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
-		cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag;
+		cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
 		cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
 		cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
 	if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
-		cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort;
+		cmd->ba_enable_beacon_abort =
+				cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
 }
 #endif
 
@@ -348,7 +409,7 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_beacon_filter_cmd cmd = {
 		IWL_BF_CMD_CONFIG_DEFAULTS,
-		.bf_enable_beacon_filter = 1,
+		.bf_enable_beacon_filter = cpu_to_le32(1),
 	};
 	int ret;
 
@@ -372,7 +433,8 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	int ret;
 
-	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) ||
+	    vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
 
 	ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
@@ -382,3 +444,11 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
 
 	return ret;
 }
+
+const struct iwl_mvm_power_ops pm_mac_ops = {
+	.power_update_mode = iwl_mvm_power_mac_update_mode,
+	.power_disable = iwl_mvm_power_mac_disable,
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	.power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
+#endif
+};
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
new file mode 100644
index 0000000..2ce79ba
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
@@ -0,0 +1,319 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-debug.h"
+#include "mvm.h"
+#include "iwl-modparams.h"
+#include "fw-api-power.h"
+
+#define POWER_KEEP_ALIVE_PERIOD_SEC    25
+
+static void iwl_mvm_power_log(struct iwl_mvm *mvm,
+			      struct iwl_powertable_cmd *cmd)
+{
+	IWL_DEBUG_POWER(mvm,
+			"Sending power table command for power level %d, flags = 0x%X\n",
+			iwlmvm_mod_params.power_scheme,
+			le16_to_cpu(cmd->flags));
+	IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
+
+	if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
+		IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
+				le32_to_cpu(cmd->rx_data_timeout));
+		IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
+				le32_to_cpu(cmd->tx_data_timeout));
+		if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
+			IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
+					le32_to_cpu(cmd->skip_dtim_periods));
+		if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
+			IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
+					le32_to_cpu(cmd->lprx_rssi_threshold));
+	}
+}
+
+static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
+				    struct ieee80211_vif *vif,
+				    struct iwl_powertable_cmd *cmd)
+{
+	struct ieee80211_hw *hw = mvm->hw;
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	struct ieee80211_channel *chan;
+	int dtimper, dtimper_msec;
+	int keep_alive;
+	bool radar_detect = false;
+	struct iwl_mvm_vif *mvmvif __maybe_unused =
+		iwl_mvm_vif_from_mac80211(vif);
+
+	/*
+	 * Regardless of power management state the driver must set
+	 * keep alive period. FW will use it for sending keep alive NDPs
+	 * immediately after association.
+	 */
+	cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
+
+	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
+		return;
+
+	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
+	if (!vif->bss_conf.assoc)
+		cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
+	    mvmvif->dbgfs_pm.disable_power_off)
+		cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
+#endif
+	if (!vif->bss_conf.ps)
+		return;
+
+	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
+
+	if (vif->bss_conf.beacon_rate &&
+	    (vif->bss_conf.beacon_rate->bitrate == 10 ||
+	     vif->bss_conf.beacon_rate->bitrate == 60)) {
+		cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
+		cmd->lprx_rssi_threshold =
+			cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
+	}
+
+	dtimper = hw->conf.ps_dtim_period ?: 1;
+
+	/* Check if radar detection is required on current channel */
+	rcu_read_lock();
+	chanctx_conf = rcu_dereference(vif->chanctx_conf);
+	WARN_ON(!chanctx_conf);
+	if (chanctx_conf) {
+		chan = chanctx_conf->def.chan;
+		radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
+	}
+	rcu_read_unlock();
+
+	/* Check skip over DTIM conditions */
+	if (!radar_detect && (dtimper <= 10) &&
+	    (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
+	     mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
+		cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+		cmd->skip_dtim_periods = cpu_to_le32(3);
+	}
+
+	/* Check that keep alive period is at least 3 * DTIM */
+	dtimper_msec = dtimper * vif->bss_conf.beacon_int;
+	keep_alive = max_t(int, 3 * dtimper_msec,
+			   MSEC_PER_SEC * cmd->keep_alive_seconds);
+	keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
+	cmd->keep_alive_seconds = keep_alive;
+
+	if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
+		cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
+		cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
+	} else {
+		cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
+		cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
+	}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
+		cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
+		if (mvmvif->dbgfs_pm.skip_over_dtim)
+			cmd->flags |=
+				cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+		else
+			cmd->flags &=
+				cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+	}
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
+		cmd->rx_data_timeout =
+			cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
+		cmd->tx_data_timeout =
+			cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
+		cmd->skip_dtim_periods =
+			cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
+		if (mvmvif->dbgfs_pm.lprx_ena)
+			cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
+		else
+			cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
+	}
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
+		cmd->lprx_rssi_threshold =
+			cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
+#endif /* CONFIG_IWLWIFI_DEBUGFS */
+}
+
+static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm,
+					    struct ieee80211_vif *vif)
+{
+	int ret;
+	bool ba_enable;
+	struct iwl_powertable_cmd cmd = {};
+
+	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+		return 0;
+
+	/*
+	 * TODO: The following vif_count verification is temporary condition.
+	 * Avoid power mode update if more than one interface is currently
+	 * active. Remove this condition when FW will support power management
+	 * on multiple MACs.
+	 */
+	IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
+			mvm->vif_count);
+	if (mvm->vif_count > 1)
+		return 0;
+
+	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+	iwl_mvm_power_log(mvm, &cmd);
+
+	ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
+				   sizeof(cmd), &cmd);
+	if (ret)
+		return ret;
+
+	ba_enable = !!(cmd.flags &
+		       cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
+
+	return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
+}
+
+static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm,
+					struct ieee80211_vif *vif)
+{
+	struct iwl_powertable_cmd cmd = {};
+	struct iwl_mvm_vif *mvmvif __maybe_unused =
+		iwl_mvm_vif_from_mac80211(vif);
+
+	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+		return 0;
+
+	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
+		cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
+	    mvmvif->dbgfs_pm.disable_power_off)
+		cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
+#endif
+	iwl_mvm_power_log(mvm, &cmd);
+
+	return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
+				    sizeof(cmd), &cmd);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm,
+					   struct ieee80211_vif *vif, char *buf,
+					   int bufsz)
+{
+	struct iwl_powertable_cmd cmd = {};
+	int pos = 0;
+
+	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
+			 (cmd.flags &
+			 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
+			 0 : 1);
+	pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
+			 le32_to_cpu(cmd.skip_dtim_periods));
+	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
+			 iwlmvm_mod_params.power_scheme);
+	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
+			 le16_to_cpu(cmd.flags));
+	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
+			 cmd.keep_alive_seconds);
+
+	if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
+		pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
+				 (cmd.flags &
+				 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
+				 1 : 0);
+		pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
+				 le32_to_cpu(cmd.rx_data_timeout));
+		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
+				 le32_to_cpu(cmd.tx_data_timeout));
+		if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
+			pos += scnprintf(buf+pos, bufsz-pos,
+					 "lprx_rssi_threshold = %d\n",
+					 le32_to_cpu(cmd.lprx_rssi_threshold));
+	}
+	return pos;
+}
+#endif
+
+const struct iwl_mvm_power_ops pm_legacy_ops = {
+	.power_update_mode = iwl_mvm_power_legacy_update_mode,
+	.power_disable = iwl_mvm_power_legacy_disable,
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	.power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read,
+#endif
+};
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index 29d49cf..1897387 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -132,7 +132,7 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
 int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 {
 	struct iwl_time_quota_cmd cmd;
-	int i, idx, ret, num_active_bindings, quota, quota_rem;
+	int i, idx, ret, num_active_macs, quota, quota_rem;
 	struct iwl_mvm_quota_iterator_data data = {
 		.n_interfaces = {},
 		.colors = { -1, -1, -1, -1 },
@@ -162,18 +162,17 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 	 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments
 	 * equally between all the bindings that require quota
 	 */
-	num_active_bindings = 0;
+	num_active_macs = 0;
 	for (i = 0; i < MAX_BINDINGS; i++) {
 		cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
-		if (data.n_interfaces[i] > 0)
-			num_active_bindings++;
+		num_active_macs += data.n_interfaces[i];
 	}
 
 	quota = 0;
 	quota_rem = 0;
-	if (num_active_bindings) {
-		quota = IWL_MVM_MAX_QUOTA / num_active_bindings;
-		quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings;
+	if (num_active_macs) {
+		quota = IWL_MVM_MAX_QUOTA / num_active_macs;
+		quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs;
 	}
 
 	for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
@@ -187,7 +186,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
 			cmd.quotas[idx].quota = cpu_to_le32(0);
 			cmd.quotas[idx].max_duration = cpu_to_le32(0);
 		} else {
-			cmd.quotas[idx].quota = cpu_to_le32(quota);
+			cmd.quotas[idx].quota =
+				cpu_to_le32(quota * data.n_interfaces[i]);
 			cmd.quotas[idx].max_duration =
 				cpu_to_le32(IWL_MVM_MAX_QUOTA);
 		}
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index b328a98..9eeb21f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -2688,9 +2688,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 
 	lq_sta->flush_timer = 0;
 	lq_sta->supp_rates = sta->supp_rates[sband->band];
-	for (j = 0; j < LQ_SIZE; j++)
-		for (i = 0; i < IWL_RATE_COUNT; i++)
-			rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
 
 	IWL_DEBUG_RATE(mvm,
 		       "LQ: *** rate scale station global init for station %d ***\n",
@@ -3159,8 +3156,9 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta)
  * station is added we ignore it.
  */
 static void rs_rate_init_stub(void *mvm_r,
-				 struct ieee80211_supported_band *sband,
-				 struct ieee80211_sta *sta, void *mvm_sta)
+			      struct ieee80211_supported_band *sband,
+			      struct cfg80211_chan_def *chandef,
+			      struct ieee80211_sta *sta, void *mvm_sta)
 {
 }
 static struct rate_control_ops rs_mvm_ops = {
@@ -3193,13 +3191,14 @@ void iwl_mvm_rate_control_unregister(void)
  * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
  * Tx protection, according to this rquest and previous requests,
  * and send the LQ command.
- * @lq: The LQ command
  * @mvmsta: The station
  * @enable: Enable Tx protection?
  */
-int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
-			  struct iwl_mvm_sta *mvmsta, bool enable)
+int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
+			  bool enable)
 {
+	struct iwl_lq_cmd *lq = &mvmsta->lq_sta.lq;
+
 	lockdep_assert_held(&mvm->mutex);
 
 	if (enable) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index cff4f6d..29d699a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -404,7 +404,7 @@ extern void iwl_mvm_rate_control_unregister(void);
 
 struct iwl_mvm_sta;
 
-int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
-			  struct iwl_mvm_sta *mvmsta, bool enable);
+int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
+			  bool enable);
 
 #endif /* __rs__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index e4930d5..6fd7fae 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -124,24 +124,15 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
 	ieee80211_rx_ni(mvm->hw, skb);
 }
 
-/*
- * iwl_mvm_calc_rssi - calculate the rssi in dBm
- * @phy_info: the phy information for the coming packet
- */
-static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
-			     struct iwl_rx_phy_info *phy_info)
+static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
+			      struct iwl_rx_phy_info *phy_info,
+			      struct ieee80211_rx_status *rx_status)
 {
 	int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
 	int rssi_all_band_a, rssi_all_band_b;
 	u32 agc_a, agc_b, max_agc;
 	u32 val;
 
-	/* Find max rssi among 2 possible receivers.
-	 * These values are measured by the Digital Signal Processor (DSP).
-	 * They should stay fairly constant even as the signal strength varies,
-	 * if the radio's Automatic Gain Control (AGC) is working right.
-	 * AGC value (see below) will provide the "interesting" info.
-	 */
 	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
 	agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
 	agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
@@ -166,7 +157,45 @@ static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
 	IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
 			rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
 
-	return max_rssi_dbm;
+	rx_status->signal = max_rssi_dbm;
+	rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
+				RX_RES_PHY_FLAGS_ANTENNA)
+					>> RX_RES_PHY_FLAGS_ANTENNA_POS;
+	rx_status->chain_signal[0] = rssi_a_dbm;
+	rx_status->chain_signal[1] = rssi_b_dbm;
+}
+
+/*
+ * iwl_mvm_get_signal_strength - use new rx PHY INFO API
+ */
+static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
+					struct iwl_rx_phy_info *phy_info,
+					struct ieee80211_rx_status *rx_status)
+{
+	int energy_a, energy_b, energy_c, max_energy;
+	u32 val;
+
+	val =
+	    le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]);
+	energy_a = -((val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >>
+						IWL_RX_INFO_ENERGY_ANT_A_POS);
+	energy_b = -((val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
+						IWL_RX_INFO_ENERGY_ANT_B_POS);
+	energy_c = -((val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
+						IWL_RX_INFO_ENERGY_ANT_C_POS);
+	max_energy = max(energy_a, energy_b);
+	max_energy = max(max_energy, energy_c);
+
+	IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n",
+			energy_a, energy_b, energy_c, max_energy);
+
+	rx_status->signal = max_energy;
+	rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
+				RX_RES_PHY_FLAGS_ANTENNA)
+					>> RX_RES_PHY_FLAGS_ANTENNA_POS;
+	rx_status->chain_signal[0] = energy_a;
+	rx_status->chain_signal[1] = energy_b;
+	rx_status->chain_signal[2] = energy_c;
 }
 
 /*
@@ -289,29 +318,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 	 */
 	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
 
-	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
-	rx_status.signal = iwl_mvm_calc_rssi(mvm, phy_info);
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API)
+		iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
+	else
+		iwl_mvm_calc_rssi(mvm, phy_info, &rx_status);
 
 	IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
 			      (unsigned long long)rx_status.mactime);
 
-	/*
-	 * "antenna number"
-	 *
-	 * It seems that the antenna field in the phy flags value
-	 * is actually a bit field. This is undefined by radiotap,
-	 * it wants an actual antenna number but I always get "7"
-	 * for most legacy frames I receive indicating that the
-	 * same frame was received on all three RX chains.
-	 *
-	 * I think this field should be removed in favor of a
-	 * new 802.11n radiotap field "RX chains" that is defined
-	 * as a bitmask.
-	 */
-	rx_status.antenna = (le16_to_cpu(phy_info->phy_flags) &
-				RX_RES_PHY_FLAGS_ANTENNA)
-				>> RX_RES_PHY_FLAGS_ANTENNA_POS;
-
 	/* set the preamble flag if appropriate */
 	if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
 		rx_status.flag |= RX_FLAG_SHORTPRE;
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index acdff6b..9a7ab84 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -301,10 +301,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
 	 */
 	if (req->n_ssids > 0) {
 		cmd->passive2active = cpu_to_le16(1);
+		cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE;
 		ssid = req->ssids[0].ssid;
 		ssid_len = req->ssids[0].ssid_len;
 	} else {
 		cmd->passive2active = 0;
+		cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE;
 	}
 
 	iwl_mvm_scan_fill_ssids(cmd, req);
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 563f559..44add29 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -826,8 +826,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 		 * method for HT traffic
 		 * this function also sends the LQ command
 		 */
-		return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
-					     mvmsta, true);
+		return iwl_mvm_tx_protection(mvm, mvmsta, true);
 		/*
 		 * TODO: remove the TLC_RTS flag when we tear down the last
 		 * AGG session (agg_tids_count in DVM)
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index d6ae7f1..1f3282d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -391,8 +391,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
 		mvmsta = (void *)sta->drv_priv;
 		if (enable == mvmsta->tt_tx_protection)
 			continue;
-		err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
-					    mvmsta, enable);
+		err = iwl_mvm_tx_protection(mvm, mvmsta, enable);
 		if (err) {
 			IWL_ERR(mvm, "Failed to %s Tx protection\n",
 				enable ? "enable" : "disable");
@@ -513,12 +512,39 @@ static const struct iwl_tt_params iwl7000_tt_params = {
 	.support_tx_backoff = true,
 };
 
+static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
+	.ct_kill_entry = 118,
+	.ct_kill_exit = 96,
+	.ct_kill_duration = 5,
+	.dynamic_smps_entry = 114,
+	.dynamic_smps_exit = 110,
+	.tx_protection_entry = 114,
+	.tx_protection_exit = 108,
+	.tx_backoff = {
+		{.temperature = 112, .backoff = 300},
+		{.temperature = 113, .backoff = 800},
+		{.temperature = 114, .backoff = 1500},
+		{.temperature = 115, .backoff = 3000},
+		{.temperature = 116, .backoff = 5000},
+		{.temperature = 117, .backoff = 10000},
+	},
+	.support_ct_kill = true,
+	.support_dynamic_smps = true,
+	.support_tx_protection = true,
+	.support_tx_backoff = true,
+};
+
 void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
 {
 	struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
 
 	IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
-	tt->params = &iwl7000_tt_params;
+
+	if (mvm->cfg->high_temp)
+		tt->params = &iwl7000_high_temp_tt_params;
+	else
+		tt->params = &iwl7000_tt_params;
+
 	tt->throttle = false;
 	INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index f0e96a9..7694b8f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -123,6 +123,8 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
 		 * it
 		 */
 		WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
+	} else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+		tx_cmd->pm_frame_timeout = cpu_to_le16(2);
 	} else {
 		tx_cmd->pm_frame_timeout = 0;
 	}
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 1e13328..a9c3574 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -453,6 +453,29 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
 	IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
 }
 
+void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
+{
+	const struct fw_img *img;
+	int ofs, len = 0;
+	u8 *buf;
+
+	if (!mvm->ucode_loaded)
+		return;
+
+	img = &mvm->fw->img[mvm->cur_ucode];
+	ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
+	len = img->sec[IWL_UCODE_SECTION_DATA].len;
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len);
+	iwl_print_hex_error(mvm->trans, buf, len);
+
+	kfree(buf);
+}
+
 /**
  * iwl_mvm_send_lq_cmd() - Send link quality command
  * @init: This command is sent as part of station initialization right
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index ff13458..c96070f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -273,9 +273,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
-	{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)},
-	{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)},
-	{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index b654dcd..fa22639 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -392,7 +392,6 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
 /*****************************************************
 * Error handling
 ******************************************************/
-int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf);
 void iwl_pcie_dump_csr(struct iwl_trans *trans);
 
 /*****************************************************
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index f600e68..68837d4 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -793,7 +793,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	}
 
 	iwl_pcie_dump_csr(trans);
-	iwl_pcie_dump_fh(trans, NULL);
+	iwl_dump_fh(trans, NULL);
 
 	set_bit(STATUS_FW_ERROR, &trans_pcie->status);
 	clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 96cfcdd..805e303 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1038,71 +1038,6 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
 	spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
 }
 
-static const char *get_fh_string(int cmd)
-{
-#define IWL_CMD(x) case x: return #x
-	switch (cmd) {
-	IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
-	IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
-	IWL_CMD(FH_RSCSR_CHNL0_WPTR);
-	IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
-	IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
-	IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
-	IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
-	IWL_CMD(FH_TSSR_TX_STATUS_REG);
-	IWL_CMD(FH_TSSR_TX_ERROR_REG);
-	default:
-		return "UNKNOWN";
-	}
-#undef IWL_CMD
-}
-
-int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf)
-{
-	int i;
-	static const u32 fh_tbl[] = {
-		FH_RSCSR_CHNL0_STTS_WPTR_REG,
-		FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-		FH_RSCSR_CHNL0_WPTR,
-		FH_MEM_RCSR_CHNL0_CONFIG_REG,
-		FH_MEM_RSSR_SHARED_CTRL_REG,
-		FH_MEM_RSSR_RX_STATUS_REG,
-		FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
-		FH_TSSR_TX_STATUS_REG,
-		FH_TSSR_TX_ERROR_REG
-	};
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (buf) {
-		int pos = 0;
-		size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
-
-		*buf = kmalloc(bufsz, GFP_KERNEL);
-		if (!*buf)
-			return -ENOMEM;
-
-		pos += scnprintf(*buf + pos, bufsz - pos,
-				"FH register values:\n");
-
-		for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
-			pos += scnprintf(*buf + pos, bufsz - pos,
-				"  %34s: 0X%08x\n",
-				get_fh_string(fh_tbl[i]),
-				iwl_read_direct32(trans, fh_tbl[i]));
-
-		return pos;
-	}
-#endif
-
-	IWL_ERR(trans, "FH register values:\n");
-	for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++)
-		IWL_ERR(trans, "  %34s: 0X%08x\n",
-			get_fh_string(fh_tbl[i]),
-			iwl_read_direct32(trans, fh_tbl[i]));
-
-	return 0;
-}
-
 static const char *get_csr_string(int cmd)
 {
 #define IWL_CMD(x) case x: return #x
@@ -1183,18 +1118,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans)
 } while (0)
 
 /* file operation */
-#define DEBUGFS_READ_FUNC(name)                                         \
-static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
-					char __user *user_buf,          \
-					size_t count, loff_t *ppos);
-
-#define DEBUGFS_WRITE_FUNC(name)                                        \
-static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
-					const char __user *user_buf,    \
-					size_t count, loff_t *ppos);
-
 #define DEBUGFS_READ_FILE_OPS(name)					\
-	DEBUGFS_READ_FUNC(name);					\
 static const struct file_operations iwl_dbgfs_##name##_ops = {		\
 	.read = iwl_dbgfs_##name##_read,				\
 	.open = simple_open,						\
@@ -1202,7 +1126,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {		\
 };
 
 #define DEBUGFS_WRITE_FILE_OPS(name)                                    \
-	DEBUGFS_WRITE_FUNC(name);                                       \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.write = iwl_dbgfs_##name##_write,                              \
 	.open = simple_open,						\
@@ -1210,8 +1133,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 };
 
 #define DEBUGFS_READ_WRITE_FILE_OPS(name)				\
-	DEBUGFS_READ_FUNC(name);					\
-	DEBUGFS_WRITE_FUNC(name);					\
 static const struct file_operations iwl_dbgfs_##name##_ops = {		\
 	.write = iwl_dbgfs_##name##_write,				\
 	.read = iwl_dbgfs_##name##_read,				\
@@ -1395,7 +1316,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
 	int pos = 0;
 	ssize_t ret = -EFAULT;
 
-	ret = pos = iwl_pcie_dump_fh(trans, &buf);
+	ret = pos = iwl_dump_fh(trans, &buf);
 	if (buf) {
 		ret = simple_read_from_buffer(user_buf,
 					      count, ppos, buf, pos);
@@ -1502,10 +1423,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 	spin_lock_init(&trans_pcie->reg_lock);
 	init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
-	/* W/A - seems to solve weird behavior. We need to remove this if we
-	 * don't want to stay in L1 all the time. This wastes a lot of power */
-	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-			       PCIE_LINK_STATE_CLKPM);
+	if (!cfg->base_params->pcie_l1_allowed) {
+		/*
+		 * W/A - seems to solve weird behavior. We need to remove this
+		 * if we don't want to stay in L1 all the time. This wastes a
+		 * lot of power.
+		 */
+		pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
+				       PCIE_LINK_STATE_L1 |
+				       PCIE_LINK_STATE_CLKPM);
+	}
 
 	if (pci_enable_device(pdev)) {
 		err = -ENODEV;
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index c47c921..134f7a1 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1619,10 +1619,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 	txq = &trans_pcie->txq[txq_id];
 	q = &txq->q;
 
-	if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) {
-		WARN_ON_ONCE(1);
+	if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
+		      "TX on unused queue %d\n", txq_id))
 		return -EINVAL;
-	}
 
 	spin_lock(&txq->lock);
 
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index cb34c78..7b2a622 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -867,7 +867,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
 
 	if (WARN_ON(skb->len < 10)) {
 		/* Should not happen; just a sanity check for addr1 use */
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(hw, skb);
 		return;
 	}
 
@@ -884,13 +884,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
 	}
 
 	if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) {
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(hw, skb);
 		return;
 	}
 
 	if (data->idle && !data->tmp_chan) {
 		wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(hw, skb);
 		return;
 	}
 
@@ -2309,7 +2309,9 @@ static int __init init_mac80211_hwsim(void)
 			hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
 
 		hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
-				    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+				    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+				    WIPHY_FLAG_AP_UAPSD;
+		hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
 
 		/* ask mac80211 to reserve space for magic */
 		hw->vif_data_size = sizeof(struct hwsim_vif_priv);
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index a78e065..8f9f542 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -189,7 +189,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 
 		skb_src = skb_dequeue(&pra_list->skb_head);
 
-		pra_list->total_pkts_size -= skb_src->len;
+		pra_list->total_pkt_count--;
 
 		atomic_dec(&priv->wmm.tx_pkts_queued);
 
@@ -268,7 +268,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 
 		skb_queue_tail(&pra_list->skb_head, skb_aggr);
 
-		pra_list->total_pkts_size += skb_aggr->len;
+		pra_list->total_pkt_count++;
 
 		atomic_inc(&priv->wmm.tx_pkts_queued);
 
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 89459db..c5e21ed 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -25,7 +25,9 @@ module_param(reg_alpha2, charp, 0);
 
 static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
 	{
-		.max = 2, .types = BIT(NL80211_IFTYPE_STATION),
+		.max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
+				   BIT(NL80211_IFTYPE_P2P_GO) |
+				   BIT(NL80211_IFTYPE_P2P_CLIENT),
 	},
 	{
 		.max = 1, .types = BIT(NL80211_IFTYPE_AP),
@@ -189,6 +191,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	struct sk_buff *skb;
 	u16 pkt_len;
 	const struct ieee80211_mgmt *mgmt;
+	struct mwifiex_txinfo *tx_info;
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 
 	if (!buf || !len) {
@@ -216,6 +219,10 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 		return -ENOMEM;
 	}
 
+	tx_info = MWIFIEX_SKB_TXCB(skb);
+	tx_info->bss_num = priv->bss_num;
+	tx_info->bss_type = priv->bss_type;
+
 	mwifiex_form_mgmt_frame(skb, buf, len);
 	mwifiex_queue_tx_pkt(priv, skb);
 
@@ -235,16 +242,20 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
 				     u16 frame_type, bool reg)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+	u32 mask;
 
 	if (reg)
-		priv->mgmt_frame_mask |= BIT(frame_type >> 4);
+		mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
 	else
-		priv->mgmt_frame_mask &= ~BIT(frame_type >> 4);
-
-	mwifiex_send_cmd_async(priv, HostCmd_CMD_MGMT_FRAME_REG,
-			       HostCmd_ACT_GEN_SET, 0, &priv->mgmt_frame_mask);
+		mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
 
-	wiphy_dbg(wiphy, "info: mgmt frame registered\n");
+	if (mask != priv->mgmt_frame_mask) {
+		priv->mgmt_frame_mask = mask;
+		mwifiex_send_cmd_async(priv, HostCmd_CMD_MGMT_FRAME_REG,
+				       HostCmd_ACT_GEN_SET, 0,
+				       &priv->mgmt_frame_mask);
+		wiphy_dbg(wiphy, "info: mgmt frame registered\n");
+	}
 }
 
 /*
@@ -2298,8 +2309,7 @@ EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
 
 #ifdef CONFIG_PM
 static bool
-mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
-			     s8 *byte_seq)
+mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq)
 {
 	int j, k, valid_byte_cnt = 0;
 	bool dont_care_byte = false;
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index 5178c46..9eefacb 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -404,11 +404,43 @@ mwifiex_is_rate_auto(struct mwifiex_private *priv)
 		return false;
 }
 
-/*
- * This function gets the supported data rates.
- *
- * The function works in both Ad-Hoc and infra mode by printing the
- * band and returning the data rates.
+/* This function gets the supported data rates from bitmask inside
+ * cfg80211_scan_request.
+ */
+u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
+				    u8 *rates, u8 radio_type)
+{
+	struct wiphy *wiphy = priv->adapter->wiphy;
+	struct cfg80211_scan_request *request = priv->scan_request;
+	u32 num_rates, rate_mask;
+	struct ieee80211_supported_band *sband;
+	int i;
+
+	if (radio_type) {
+		sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+		if (WARN_ON_ONCE(!sband))
+			return 0;
+		rate_mask = request->rates[IEEE80211_BAND_5GHZ];
+	} else {
+		sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+		if (WARN_ON_ONCE(!sband))
+			return 0;
+		rate_mask = request->rates[IEEE80211_BAND_2GHZ];
+	}
+
+	num_rates = 0;
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((BIT(i) & rate_mask) == 0)
+			continue; /* skip rate */
+		rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5);
+	}
+
+	return num_rates;
+}
+
+/* This function gets the supported data rates. The function works in
+ * both Ad-Hoc and infra mode by printing the band and returning the
+ * data rates.
  */
 u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
 {
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 94cc09d..a599347 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -75,7 +75,8 @@
 #define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
 #define MWIFIEX_BUF_FLAG_BRIDGED_PKT	   BIT(1)
 
-#define MWIFIEX_BRIDGED_PKTS_THRESHOLD     1024
+#define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
+#define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
 
 enum mwifiex_bss_type {
 	MWIFIEX_BSS_TYPE_STA = 0,
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 1b45aa5..c0dfc4d 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -85,9 +85,6 @@ enum KEY_TYPE_ID {
 #define WAPI_KEY_LEN			50
 
 #define MAX_POLL_TRIES			100
-
-#define MAX_MULTI_INTERFACE_POLL_TRIES  1000
-
 #define MAX_FIRMWARE_POLL_TRIES			100
 
 #define FIRMWARE_READY_SDIO				0xfedc
@@ -1369,11 +1366,6 @@ struct host_cmd_ds_802_11_eeprom_access {
 	u8 value;
 } __packed;
 
-struct host_cmd_tlv {
-	__le16 type;
-	__le16 len;
-} __packed;
-
 struct mwifiex_assoc_event {
 	u8 sta_addr[ETH_ALEN];
 	__le16 type;
@@ -1399,99 +1391,99 @@ struct host_cmd_11ac_vht_cfg {
 } __packed;
 
 struct host_cmd_tlv_akmp {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le16 key_mgmt;
 	__le16 key_mgmt_operation;
 } __packed;
 
 struct host_cmd_tlv_pwk_cipher {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le16 proto;
 	u8 cipher;
 	u8 reserved;
 } __packed;
 
 struct host_cmd_tlv_gwk_cipher {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 cipher;
 	u8 reserved;
 } __packed;
 
 struct host_cmd_tlv_passphrase {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 passphrase[0];
 } __packed;
 
 struct host_cmd_tlv_wep_key {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 key_index;
 	u8 is_default;
 	u8 key[1];
 };
 
 struct host_cmd_tlv_auth_type {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 auth_type;
 } __packed;
 
 struct host_cmd_tlv_encrypt_protocol {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le16 proto;
 } __packed;
 
 struct host_cmd_tlv_ssid {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 ssid[0];
 } __packed;
 
 struct host_cmd_tlv_rates {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 rates[0];
 } __packed;
 
 struct host_cmd_tlv_bcast_ssid {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 bcast_ctl;
 } __packed;
 
 struct host_cmd_tlv_beacon_period {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le16 period;
 } __packed;
 
 struct host_cmd_tlv_dtim_period {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 period;
 } __packed;
 
 struct host_cmd_tlv_frag_threshold {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le16 frag_thr;
 } __packed;
 
 struct host_cmd_tlv_rts_threshold {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le16 rts_thr;
 } __packed;
 
 struct host_cmd_tlv_retry_limit {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 limit;
 } __packed;
 
 struct host_cmd_tlv_mac_addr {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 mac_addr[ETH_ALEN];
 } __packed;
 
 struct host_cmd_tlv_channel_band {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	u8 band_config;
 	u8 channel;
 } __packed;
 
 struct host_cmd_tlv_ageout_timer {
-	struct host_cmd_tlv tlv;
+	struct mwifiex_ie_types_header header;
 	__le32 sta_ao_timer;
 } __packed;
 
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
index e38342f..220af4f 100644
--- a/drivers/net/wireless/mwifiex/ie.c
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -87,7 +87,7 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
 	u8 *tmp;
 
 	input_len = le16_to_cpu(ie_list->len);
-	travel_len = sizeof(struct host_cmd_tlv);
+	travel_len = sizeof(struct mwifiex_ie_types_header);
 
 	ie_list->len = 0;
 
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 2cf8b96..e021a58 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -135,6 +135,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
 
 	priv->csa_chan = 0;
 	priv->csa_expire_time = 0;
+	priv->del_list_idx = 0;
 
 	return mwifiex_add_bss_prio_tbl(priv);
 }
@@ -377,18 +378,11 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
 static void
 mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 {
-	int i;
-
 	if (!adapter) {
 		pr_err("%s: adapter is NULL\n", __func__);
 		return;
 	}
 
-	for (i = 0; i < adapter->priv_num; i++) {
-		if (adapter->priv[i])
-			del_timer_sync(&adapter->priv[i]->scan_delay_timer);
-	}
-
 	mwifiex_cancel_all_pending_cmd(adapter);
 
 	/* Free lock variables */
@@ -398,13 +392,8 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 	dev_dbg(adapter->dev, "info: free cmd buffer\n");
 	mwifiex_free_cmd_buffer(adapter);
 
-	del_timer(&adapter->cmd_timer);
-
 	dev_dbg(adapter->dev, "info: free scan table\n");
 
-	if (adapter->if_ops.cleanup_if)
-		adapter->if_ops.cleanup_if(adapter);
-
 	if (adapter->sleep_cfm)
 		dev_kfree_skb_any(adapter->sleep_cfm);
 }
@@ -702,7 +691,6 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
 		if (!adapter->winner) {
 			dev_notice(adapter->dev,
 				   "FW already running! Skip FW dnld\n");
-			poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
 			goto poll_fw;
 		}
 	}
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 12e7781..9d7c0e6 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -1427,6 +1427,7 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
 
 	switch (priv->bss_mode) {
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
 		return mwifiex_deauthenticate_infra(priv, mac);
 	case NL80211_IFTYPE_ADHOC:
 		return mwifiex_send_cmd_sync(priv,
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 1753431..3402bff 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -191,12 +191,16 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter)
 {
 	s32 i;
 
+	if (adapter->if_ops.cleanup_if)
+		adapter->if_ops.cleanup_if(adapter);
+
 	del_timer(&adapter->cmd_timer);
 
 	/* Free private structures */
 	for (i = 0; i < adapter->priv_num; i++) {
 		if (adapter->priv[i]) {
 			mwifiex_free_curr_bcn(adapter->priv[i]);
+			del_timer_sync(&adapter->priv[i]->scan_delay_timer);
 			kfree(adapter->priv[i]);
 		}
 	}
@@ -386,6 +390,17 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
 }
 
 /*
+ * This function cancels all works in the queue and destroys
+ * the main workqueue.
+ */
+static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
+{
+	flush_workqueue(adapter->workqueue);
+	destroy_workqueue(adapter->workqueue);
+	adapter->workqueue = NULL;
+}
+
+/*
  * This function gets firmware and initializes it.
  *
  * The main initialization steps followed are -
@@ -394,16 +409,18 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
  */
 static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 {
-	int ret;
+	int ret, i;
 	char fmt[64];
 	struct mwifiex_private *priv;
 	struct mwifiex_adapter *adapter = context;
 	struct mwifiex_fw_image fw;
+	struct semaphore *sem = adapter->card_sem;
+	bool init_failed = false;
 
 	if (!firmware) {
 		dev_err(adapter->dev,
 			"Failed to get firmware %s\n", adapter->fw_name);
-		goto done;
+		goto err_dnld_fw;
 	}
 
 	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
@@ -416,7 +433,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 	else
 		ret = mwifiex_dnld_fw(adapter, &fw);
 	if (ret == -1)
-		goto done;
+		goto err_dnld_fw;
 
 	dev_notice(adapter->dev, "WLAN FW is active\n");
 
@@ -428,13 +445,15 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 	}
 
 	/* enable host interrupt after fw dnld is successful */
-	if (adapter->if_ops.enable_int)
-		adapter->if_ops.enable_int(adapter);
+	if (adapter->if_ops.enable_int) {
+		if (adapter->if_ops.enable_int(adapter))
+			goto err_dnld_fw;
+	}
 
 	adapter->init_wait_q_woken = false;
 	ret = mwifiex_init_fw(adapter);
 	if (ret == -1) {
-		goto done;
+		goto err_init_fw;
 	} else if (!ret) {
 		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
 		goto done;
@@ -443,12 +462,12 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 	wait_event_interruptible(adapter->init_wait_q,
 				 adapter->init_wait_q_woken);
 	if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
-		goto done;
+		goto err_init_fw;
 
 	priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
 	if (mwifiex_register_cfg80211(adapter)) {
 		dev_err(adapter->dev, "cannot register with cfg80211\n");
-		goto err_init_fw;
+		goto err_register_cfg80211;
 	}
 
 	rtnl_lock();
@@ -479,20 +498,52 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 	goto done;
 
 err_add_intf:
-	mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
+	for (i = 0; i < adapter->priv_num; i++) {
+		priv = adapter->priv[i];
+
+		if (!priv)
+			continue;
+
+		if (priv->wdev && priv->netdev)
+			mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
+	}
 	rtnl_unlock();
+err_register_cfg80211:
+	wiphy_unregister(adapter->wiphy);
+	wiphy_free(adapter->wiphy);
 err_init_fw:
 	if (adapter->if_ops.disable_int)
 		adapter->if_ops.disable_int(adapter);
+err_dnld_fw:
 	pr_debug("info: %s: unregister device\n", __func__);
-	adapter->if_ops.unregister_dev(adapter);
+	if (adapter->if_ops.unregister_dev)
+		adapter->if_ops.unregister_dev(adapter);
+
+	if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
+	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
+		pr_debug("info: %s: shutdown mwifiex\n", __func__);
+		adapter->init_wait_q_woken = false;
+
+		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
+			wait_event_interruptible(adapter->init_wait_q,
+						 adapter->init_wait_q_woken);
+	}
+	adapter->surprise_removed = true;
+	mwifiex_terminate_workqueue(adapter);
+	init_failed = true;
 done:
 	if (adapter->cal_data) {
 		release_firmware(adapter->cal_data);
 		adapter->cal_data = NULL;
 	}
-	release_firmware(adapter->firmware);
+	if (adapter->firmware) {
+		release_firmware(adapter->firmware);
+		adapter->firmware = NULL;
+	}
 	complete(&adapter->fw_load);
+	if (init_failed)
+		mwifiex_free_adapter(adapter);
+	up(sem);
 	return;
 }
 
@@ -803,18 +854,6 @@ static void mwifiex_main_work_queue(struct work_struct *work)
 }
 
 /*
- * This function cancels all works in the queue and destroys
- * the main workqueue.
- */
-static void
-mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
-{
-	flush_workqueue(adapter->workqueue);
-	destroy_workqueue(adapter->workqueue);
-	adapter->workqueue = NULL;
-}
-
-/*
  * This function adds the card.
  *
  * This function follows the following major steps to set up the device -
@@ -842,6 +881,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
 	}
 
 	adapter->iface_type = iface_type;
+	adapter->card_sem = sem;
 
 	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
 	adapter->surprise_removed = false;
@@ -872,17 +912,12 @@ mwifiex_add_card(void *card, struct semaphore *sem,
 		goto err_init_fw;
 	}
 
-	up(sem);
 	return 0;
 
 err_init_fw:
 	pr_debug("info: %s: unregister device\n", __func__);
 	if (adapter->if_ops.unregister_dev)
 		adapter->if_ops.unregister_dev(adapter);
-err_registerdev:
-	adapter->surprise_removed = true;
-	mwifiex_terminate_workqueue(adapter);
-err_kmalloc:
 	if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
 	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
 		pr_debug("info: %s: shutdown mwifiex\n", __func__);
@@ -892,7 +927,10 @@ err_kmalloc:
 			wait_event_interruptible(adapter->init_wait_q,
 						 adapter->init_wait_q_woken);
 	}
-
+err_registerdev:
+	adapter->surprise_removed = true;
+	mwifiex_terminate_workqueue(adapter);
+err_kmalloc:
 	mwifiex_free_adapter(adapter);
 
 err_init_sw:
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 253e0bd..d2e5ccd 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -204,11 +204,11 @@ struct mwifiex_ra_list_tbl {
 	struct list_head list;
 	struct sk_buff_head skb_head;
 	u8 ra[ETH_ALEN];
-	u32 total_pkts_size;
 	u32 is_11n_enabled;
 	u16 max_amsdu;
-	u16 pkt_count;
+	u16 ba_pkt_count;
 	u8 ba_packet_thr;
+	u16 total_pkt_count;
 };
 
 struct mwifiex_tid_tbl {
@@ -515,6 +515,7 @@ struct mwifiex_private {
 	bool scan_aborting;
 	u8 csa_chan;
 	unsigned long csa_expire_time;
+	u8 del_list_idx;
 };
 
 enum mwifiex_ba_status {
@@ -748,6 +749,7 @@ struct mwifiex_adapter {
 
 	atomic_t is_tx_received;
 	atomic_t pending_bridged_pkts;
+	struct semaphore *card_sem;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -900,6 +902,8 @@ int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
 u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv,
 				    u8 *rates);
 u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates);
+u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
+				    u8 *rates, u8 radio_type);
 u8 mwifiex_is_rate_auto(struct mwifiex_private *priv);
 extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE];
 void mwifiex_save_curr_bcn(struct mwifiex_private *priv);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 20c9c4c..52da8ee 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -76,7 +76,7 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
 	return false;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 /*
  * Kernel needs to suspend all functions separately. Therefore all
  * registered functions must have drivers with suspend and resume
@@ -85,11 +85,12 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
  * If already not suspended, this function allocates and sends a host
  * sleep activate request to the firmware and turns off the traffic.
  */
-static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+static int mwifiex_pcie_suspend(struct device *dev)
 {
 	struct mwifiex_adapter *adapter;
 	struct pcie_service_card *card;
 	int hs_actived;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
 	if (pdev) {
 		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
@@ -120,10 +121,11 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
  * If already not resumed, this function turns on the traffic and
  * sends a host sleep cancel request to the firmware.
  */
-static int mwifiex_pcie_resume(struct pci_dev *pdev)
+static int mwifiex_pcie_resume(struct device *dev)
 {
 	struct mwifiex_adapter *adapter;
 	struct pcie_service_card *card;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
 	if (pdev) {
 		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
@@ -211,9 +213,9 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 	wait_for_completion(&adapter->fw_load);
 
 	if (user_rmmod) {
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 		if (adapter->is_suspended)
-			mwifiex_pcie_resume(pdev);
+			mwifiex_pcie_resume(&pdev->dev);
 #endif
 
 		for (i = 0; i < adapter->priv_num; i++)
@@ -233,6 +235,14 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 	kfree(card);
 }
 
+static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
+{
+	user_rmmod = 1;
+	mwifiex_pcie_remove(pdev);
+
+	return;
+}
+
 static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
 	{
 		PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
@@ -249,17 +259,24 @@ static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
 
 MODULE_DEVICE_TABLE(pci, mwifiex_ids);
 
+#ifdef CONFIG_PM_SLEEP
+/* Power Management Hooks */
+static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
+				mwifiex_pcie_resume);
+#endif
+
 /* PCI Device Driver */
 static struct pci_driver __refdata mwifiex_pcie = {
 	.name     = "mwifiex_pcie",
 	.id_table = mwifiex_ids,
 	.probe    = mwifiex_pcie_probe,
 	.remove   = mwifiex_pcie_remove,
-#ifdef CONFIG_PM
-	/* Power Management Hooks */
-	.suspend  = mwifiex_pcie_suspend,
-	.resume   = mwifiex_pcie_resume,
+#ifdef CONFIG_PM_SLEEP
+	.driver   = {
+		.pm = &mwifiex_pcie_pm_ops,
+	},
 #endif
+	.shutdown = mwifiex_pcie_shutdown,
 };
 
 /*
@@ -1925,7 +1942,7 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
 			ret = 0;
 			break;
 		} else {
-			mdelay(100);
+			msleep(100);
 			ret = -1;
 		}
 	}
@@ -1937,12 +1954,10 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
 		else if (!winner_status) {
 			dev_err(adapter->dev, "PCI-E is the winner\n");
 			adapter->winner = 1;
-			ret = -1;
 		} else {
 			dev_err(adapter->dev,
 				"PCI-E is not the winner <%#x,%d>, exit dnld\n",
 				ret, adapter->winner);
-			ret = 0;
 		}
 	}
 
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index c447d9b..8cf7d50 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -543,6 +543,37 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
 	return chan_idx;
 }
 
+/* This function appends rate TLV to scan config command. */
+static int
+mwifiex_append_rate_tlv(struct mwifiex_private *priv,
+			struct mwifiex_scan_cmd_config *scan_cfg_out,
+			u8 radio)
+{
+	struct mwifiex_ie_types_rates_param_set *rates_tlv;
+	u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
+	u32 rates_size;
+
+	memset(rates, 0, sizeof(rates));
+
+	tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
+
+	if (priv->scan_request)
+		rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
+							     radio);
+	else
+		rates_size = mwifiex_get_supported_rates(priv, rates);
+
+	dev_dbg(priv->adapter->dev, "info: SCAN_CMD: Rates size = %d\n",
+		rates_size);
+	rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
+	rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
+	rates_tlv->header.len = cpu_to_le16((u16) rates_size);
+	memcpy(rates_tlv->rates, rates, rates_size);
+	scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
+
+	return rates_size;
+}
+
 /*
  * This function constructs and sends multiple scan config commands to
  * the firmware.
@@ -564,9 +595,10 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 	struct mwifiex_chan_scan_param_set *tmp_chan_list;
 	struct mwifiex_chan_scan_param_set *start_chan;
 
-	u32 tlv_idx;
+	u32 tlv_idx, rates_size;
 	u32 total_scan_time;
 	u32 done_early;
+	u8 radio_type;
 
 	if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
 		dev_dbg(priv->adapter->dev,
@@ -591,6 +623,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 
 		tlv_idx = 0;
 		total_scan_time = 0;
+		radio_type = 0;
 		chan_tlv_out->header.len = 0;
 		start_chan = tmp_chan_list;
 		done_early = false;
@@ -612,6 +645,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 				continue;
 			}
 
+			radio_type = tmp_chan_list->radio_type;
 			dev_dbg(priv->adapter->dev,
 				"info: Scan: Chan(%3d), Radio(%d),"
 				" Mode(%d, %d), Dur(%d)\n",
@@ -692,6 +726,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 			break;
 		}
 
+		rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
+						     radio_type);
+
 		priv->adapter->scan_channels = start_chan;
 
 		/* Send the scan command to the firmware with the specified
@@ -699,6 +736,14 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
 		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN,
 					     HostCmd_ACT_GEN_SET, 0,
 					     scan_cfg_out);
+
+		/* rate IE is updated per scan command but same starting
+		 * pointer is used each time so that rate IE from earlier
+		 * scan_cfg_out->buf is overwritten with new one.
+		 */
+		scan_cfg_out->tlv_buf_len -=
+			    sizeof(struct mwifiex_ie_types_header) + rates_size;
+
 		if (ret)
 			break;
 	}
@@ -741,7 +786,6 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct mwifiex_ie_types_num_probes *num_probes_tlv;
 	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
-	struct mwifiex_ie_types_rates_param_set *rates_tlv;
 	u8 *tlv_pos;
 	u32 num_probes;
 	u32 ssid_len;
@@ -753,8 +797,6 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 	u8 radio_type;
 	int i;
 	u8 ssid_filter;
-	u8 rates[MWIFIEX_SUPPORTED_RATES];
-	u32 rates_size;
 	struct mwifiex_ie_types_htcap *ht_cap;
 
 	/* The tlv_buf_len is calculated for each scan command.  The TLVs added
@@ -889,19 +931,6 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 
 	}
 
-	/* Append rates tlv */
-	memset(rates, 0, sizeof(rates));
-
-	rates_size = mwifiex_get_supported_rates(priv, rates);
-
-	rates_tlv = (struct mwifiex_ie_types_rates_param_set *) tlv_pos;
-	rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
-	rates_tlv->header.len = cpu_to_le16((u16) rates_size);
-	memcpy(rates_tlv->rates, rates, rates_size);
-	tlv_pos += sizeof(rates_tlv->header) + rates_size;
-
-	dev_dbg(adapter->dev, "info: SCAN_CMD: Rates size = %d\n", rates_size);
-
 	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
 	    (priv->adapter->config_bands & BAND_GN ||
 	     priv->adapter->config_bands & BAND_AN)) {
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 09185c9..0e2070f 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -50,9 +50,6 @@ static struct mwifiex_if_ops sdio_ops;
 
 static struct semaphore add_remove_card_sem;
 
-static int mwifiex_sdio_resume(struct device *dev);
-static void mwifiex_sdio_interrupt(struct sdio_func *func);
-
 /*
  * SDIO probe.
  *
@@ -113,6 +110,51 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
 }
 
 /*
+ * SDIO resume.
+ *
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a host sleep cancel request to the firmware.
+ */
+static int mwifiex_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	struct sdio_mmc_card *card;
+	struct mwifiex_adapter *adapter;
+	mmc_pm_flag_t pm_flag = 0;
+
+	if (func) {
+		pm_flag = sdio_get_host_pm_caps(func);
+		card = sdio_get_drvdata(func);
+		if (!card || !card->adapter) {
+			pr_err("resume: invalid card or adapter\n");
+			return 0;
+		}
+	} else {
+		pr_err("resume: sdio_func is not specified\n");
+		return 0;
+	}
+
+	adapter = card->adapter;
+
+	if (!adapter->is_suspended) {
+		dev_warn(adapter->dev, "device already resumed\n");
+		return 0;
+	}
+
+	adapter->is_suspended = false;
+
+	/* Disable Host Sleep */
+	mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+			  MWIFIEX_ASYNC_CMD);
+
+	return 0;
+}
+
+/*
  * SDIO remove.
  *
  * This function removes the interface and frees up the card structure.
@@ -212,51 +254,6 @@ static int mwifiex_sdio_suspend(struct device *dev)
 	return ret;
 }
 
-/*
- * SDIO resume.
- *
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not resumed, this function turns on the traffic and
- * sends a host sleep cancel request to the firmware.
- */
-static int mwifiex_sdio_resume(struct device *dev)
-{
-	struct sdio_func *func = dev_to_sdio_func(dev);
-	struct sdio_mmc_card *card;
-	struct mwifiex_adapter *adapter;
-	mmc_pm_flag_t pm_flag = 0;
-
-	if (func) {
-		pm_flag = sdio_get_host_pm_caps(func);
-		card = sdio_get_drvdata(func);
-		if (!card || !card->adapter) {
-			pr_err("resume: invalid card or adapter\n");
-			return 0;
-		}
-	} else {
-		pr_err("resume: sdio_func is not specified\n");
-		return 0;
-	}
-
-	adapter = card->adapter;
-
-	if (!adapter->is_suspended) {
-		dev_warn(adapter->dev, "device already resumed\n");
-		return 0;
-	}
-
-	adapter->is_suspended = false;
-
-	/* Disable Host Sleep */
-	mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-			  MWIFIEX_ASYNC_CMD);
-
-	return 0;
-}
-
 /* Device ID for SD8786 */
 #define SDIO_DEVICE_ID_MARVELL_8786   (0x9116)
 /* Device ID for SD8787 */
@@ -707,6 +704,65 @@ static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
 }
 
 /*
+ * This function reads the interrupt status from card.
+ */
+static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
+{
+	struct sdio_mmc_card *card = adapter->card;
+	u8 sdio_ireg;
+	unsigned long flags;
+
+	if (mwifiex_read_data_sync(adapter, card->mp_regs,
+				   card->reg->max_mp_regs,
+				   REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
+		dev_err(adapter->dev, "read mp_regs failed\n");
+		return;
+	}
+
+	sdio_ireg = card->mp_regs[HOST_INTSTATUS_REG];
+	if (sdio_ireg) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * For SDIO new mode CMD port interrupts
+		 *	DN_LD_CMD_PORT_HOST_INT_STATUS and/or
+		 *	UP_LD_CMD_PORT_HOST_INT_STATUS
+		 * Clear the interrupt status register
+		 */
+		dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg);
+		spin_lock_irqsave(&adapter->int_lock, flags);
+		adapter->int_status |= sdio_ireg;
+		spin_unlock_irqrestore(&adapter->int_lock, flags);
+	}
+}
+
+/*
+ * SDIO interrupt handler.
+ *
+ * This function reads the interrupt status from firmware and handles
+ * the interrupt in current thread (ksdioirqd) right away.
+ */
+static void
+mwifiex_sdio_interrupt(struct sdio_func *func)
+{
+	struct mwifiex_adapter *adapter;
+	struct sdio_mmc_card *card;
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->adapter) {
+		pr_debug("int: func=%p card=%p adapter=%p\n",
+			 func, card, card ? card->adapter : NULL);
+		return;
+	}
+	adapter = card->adapter;
+
+	if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
+		adapter->ps_state = PS_STATE_AWAKE;
+
+	mwifiex_interrupt_status(adapter);
+	mwifiex_main_process(adapter);
+}
+
+/*
  * This function enables the host interrupt.
  *
  * The host interrupt enable mask is written to the card
@@ -944,7 +1000,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
 			ret = 0;
 			break;
 		} else {
-			mdelay(100);
+			msleep(100);
 			ret = -1;
 		}
 	}
@@ -963,65 +1019,6 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
 }
 
 /*
- * This function reads the interrupt status from card.
- */
-static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
-{
-	struct sdio_mmc_card *card = adapter->card;
-	u8 sdio_ireg;
-	unsigned long flags;
-
-	if (mwifiex_read_data_sync(adapter, card->mp_regs,
-				   card->reg->max_mp_regs,
-				   REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
-		dev_err(adapter->dev, "read mp_regs failed\n");
-		return;
-	}
-
-	sdio_ireg = card->mp_regs[HOST_INTSTATUS_REG];
-	if (sdio_ireg) {
-		/*
-		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
-		 * For SDIO new mode CMD port interrupts
-		 *	DN_LD_CMD_PORT_HOST_INT_STATUS and/or
-		 *	UP_LD_CMD_PORT_HOST_INT_STATUS
-		 * Clear the interrupt status register
-		 */
-		dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg);
-		spin_lock_irqsave(&adapter->int_lock, flags);
-		adapter->int_status |= sdio_ireg;
-		spin_unlock_irqrestore(&adapter->int_lock, flags);
-	}
-}
-
-/*
- * SDIO interrupt handler.
- *
- * This function reads the interrupt status from firmware and handles
- * the interrupt in current thread (ksdioirqd) right away.
- */
-static void
-mwifiex_sdio_interrupt(struct sdio_func *func)
-{
-	struct mwifiex_adapter *adapter;
-	struct sdio_mmc_card *card;
-
-	card = sdio_get_drvdata(func);
-	if (!card || !card->adapter) {
-		pr_debug("int: func=%p card=%p adapter=%p\n",
-			 func, card, card ? card->adapter : NULL);
-		return;
-	}
-	adapter = card->adapter;
-
-	if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
-		adapter->ps_state = PS_STATE_AWAKE;
-
-	mwifiex_interrupt_status(adapter);
-	mwifiex_main_process(adapter);
-}
-
-/*
  * This function decodes a received packet.
  *
  * Based on the type, the packet is treated as either a data, or
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 8ece485..9b75ed8 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -707,8 +707,9 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
 		if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
 			tlv_mac = (void *)((u8 *)&key_material->key_param_set +
 					   key_param_len);
-			tlv_mac->tlv.type = cpu_to_le16(TLV_TYPE_STA_MAC_ADDR);
-			tlv_mac->tlv.len = cpu_to_le16(ETH_ALEN);
+			tlv_mac->header.type =
+					cpu_to_le16(TLV_TYPE_STA_MAC_ADDR);
+			tlv_mac->header.len = cpu_to_le16(ETH_ALEN);
 			memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN);
 			cmd_size = key_param_len + S_DS_GEN +
 				   sizeof(key_material->action) +
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index ea265ec..8b05752 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -201,6 +201,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
 	case EVENT_DEAUTHENTICATED:
 		dev_dbg(adapter->dev, "event: Deauthenticated\n");
+		if (priv->wps.session_enable) {
+			dev_dbg(adapter->dev,
+				"info: receive deauth event in wps session\n");
+			break;
+		}
 		adapter->dbg.num_event_deauth++;
 		if (priv->media_connected) {
 			reason_code =
@@ -211,6 +216,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
 	case EVENT_DISASSOCIATED:
 		dev_dbg(adapter->dev, "event: Disassociated\n");
+		if (priv->wps.session_enable) {
+			dev_dbg(adapter->dev,
+				"info: receive disassoc event in wps session\n");
+			break;
+		}
 		adapter->dbg.num_event_disassoc++;
 		if (priv->media_connected) {
 			reason_code =
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 8af97ab..f084412 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -797,15 +797,16 @@ static int mwifiex_set_wps_ie(struct mwifiex_private *priv,
 			       u8 *ie_data_ptr, u16 ie_len)
 {
 	if (ie_len) {
-		priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL);
-		if (!priv->wps_ie)
-			return -ENOMEM;
-		if (ie_len > sizeof(priv->wps_ie)) {
+		if (ie_len > MWIFIEX_MAX_VSIE_LEN) {
 			dev_dbg(priv->adapter->dev,
 				"info: failed to copy WPS IE, too big\n");
-			kfree(priv->wps_ie);
 			return -1;
 		}
+
+		priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL);
+		if (!priv->wps_ie)
+			return -ENOMEM;
+
 		memcpy(priv->wps_ie, ie_data_ptr, ie_len);
 		priv->wps_ie_len = ie_len;
 		dev_dbg(priv->adapter->dev, "cmd: Set wps_ie_len=%d IE=%#x\n",
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 2de882d..64424c8 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -293,9 +293,9 @@ mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 	u8 *tlv = *tlv_buf;
 
 	tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
-	tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
-	tlv_akmp->tlv.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
-					sizeof(struct host_cmd_tlv));
+	tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
+	tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
+					sizeof(struct mwifiex_ie_types_header));
 	tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
 	tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
 	cmd_size += sizeof(struct host_cmd_tlv_akmp);
@@ -303,10 +303,10 @@ mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
 		pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
-		pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
-		pwk_cipher->tlv.len =
+		pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+		pwk_cipher->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
 		pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
 		cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
@@ -315,10 +315,10 @@ mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
 		pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
-		pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
-		pwk_cipher->tlv.len =
+		pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+		pwk_cipher->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
 		pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
 		cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
@@ -327,10 +327,10 @@ mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
 		gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
-		gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
-		gwk_cipher->tlv.len =
+		gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
+		gwk_cipher->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
 		cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
 		tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
@@ -338,13 +338,15 @@ mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->wpa_cfg.length) {
 		passphrase = (struct host_cmd_tlv_passphrase *)tlv;
-		passphrase->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
-		passphrase->tlv.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
+		passphrase->header.type =
+				cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
+		passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
 		memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
 		       bss_cfg->wpa_cfg.length);
-		cmd_size += sizeof(struct host_cmd_tlv) +
+		cmd_size += sizeof(struct mwifiex_ie_types_header) +
 			    bss_cfg->wpa_cfg.length;
-		tlv += sizeof(struct host_cmd_tlv) + bss_cfg->wpa_cfg.length;
+		tlv += sizeof(struct mwifiex_ie_types_header) +
+				bss_cfg->wpa_cfg.length;
 	}
 
 	*param_size = cmd_size;
@@ -403,16 +405,17 @@ mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 		    (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
 		     bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
 			wep_key = (struct host_cmd_tlv_wep_key *)tlv;
-			wep_key->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
-			wep_key->tlv.len =
+			wep_key->header.type =
+				cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+			wep_key->header.len =
 				cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
 			wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
 			wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
 			memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
 			       bss_cfg->wep_cfg[i].length);
-			cmd_size += sizeof(struct host_cmd_tlv) + 2 +
+			cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 +
 				    bss_cfg->wep_cfg[i].length;
-			tlv += sizeof(struct host_cmd_tlv) + 2 +
+			tlv += sizeof(struct mwifiex_ie_types_header) + 2 +
 				    bss_cfg->wep_cfg[i].length;
 		}
 	}
@@ -449,16 +452,17 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->ssid.ssid_len) {
 		ssid = (struct host_cmd_tlv_ssid *)tlv;
-		ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
-		ssid->tlv.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
+		ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
+		ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
 		memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
-		cmd_size += sizeof(struct host_cmd_tlv) +
+		cmd_size += sizeof(struct mwifiex_ie_types_header) +
 			    bss_cfg->ssid.ssid_len;
-		tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len;
+		tlv += sizeof(struct mwifiex_ie_types_header) +
+				bss_cfg->ssid.ssid_len;
 
 		bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
-		bcast_ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
-		bcast_ssid->tlv.len =
+		bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
+		bcast_ssid->header.len =
 				cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
 		bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
 		cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
@@ -466,13 +470,13 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 	}
 	if (bss_cfg->rates[0]) {
 		tlv_rates = (struct host_cmd_tlv_rates *)tlv;
-		tlv_rates->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
+		tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
 
 		for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i];
 		     i++)
 			tlv_rates->rates[i] = bss_cfg->rates[i];
 
-		tlv_rates->tlv.len = cpu_to_le16(i);
+		tlv_rates->header.len = cpu_to_le16(i);
 		cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
 		tlv += sizeof(struct host_cmd_tlv_rates) + i;
 	}
@@ -482,10 +486,10 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 	    (bss_cfg->band_cfg == BAND_CONFIG_A &&
 	     bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
 		chan_band = (struct host_cmd_tlv_channel_band *)tlv;
-		chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
-		chan_band->tlv.len =
+		chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
+		chan_band->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		chan_band->band_config = bss_cfg->band_cfg;
 		chan_band->channel = bss_cfg->channel;
 		cmd_size += sizeof(struct host_cmd_tlv_channel_band);
@@ -494,11 +498,11 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 	if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD &&
 	    bss_cfg->beacon_period <= MAX_BEACON_PERIOD) {
 		beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
-		beacon_period->tlv.type =
+		beacon_period->header.type =
 					cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
-		beacon_period->tlv.len =
+		beacon_period->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
 		cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
 		tlv += sizeof(struct host_cmd_tlv_beacon_period);
@@ -506,21 +510,22 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 	if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD &&
 	    bss_cfg->dtim_period <= MAX_DTIM_PERIOD) {
 		dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
-		dtim_period->tlv.type = cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
-		dtim_period->tlv.len =
+		dtim_period->header.type =
+			cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
+		dtim_period->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		dtim_period->period = bss_cfg->dtim_period;
 		cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
 		tlv += sizeof(struct host_cmd_tlv_dtim_period);
 	}
 	if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) {
 		rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
-		rts_threshold->tlv.type =
+		rts_threshold->header.type =
 					cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
-		rts_threshold->tlv.len =
+		rts_threshold->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
 		cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
 		tlv += sizeof(struct host_cmd_tlv_frag_threshold);
@@ -528,21 +533,22 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 	if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) &&
 	    (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) {
 		frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
-		frag_threshold->tlv.type =
+		frag_threshold->header.type =
 				cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
-		frag_threshold->tlv.len =
+		frag_threshold->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
 		cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
 		tlv += sizeof(struct host_cmd_tlv_frag_threshold);
 	}
 	if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) {
 		retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
-		retry_limit->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
-		retry_limit->tlv.len =
+		retry_limit->header.type =
+			cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
+		retry_limit->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
-				    sizeof(struct host_cmd_tlv));
+				    sizeof(struct mwifiex_ie_types_header));
 		retry_limit->limit = (u8)bss_cfg->retry_limit;
 		cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
 		tlv += sizeof(struct host_cmd_tlv_retry_limit);
@@ -557,21 +563,21 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 	if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
 	    (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
 		auth_type = (struct host_cmd_tlv_auth_type *)tlv;
-		auth_type->tlv.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
-		auth_type->tlv.len =
+		auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+		auth_type->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
-			sizeof(struct host_cmd_tlv));
+			sizeof(struct mwifiex_ie_types_header));
 		auth_type->auth_type = (u8)bss_cfg->auth_mode;
 		cmd_size += sizeof(struct host_cmd_tlv_auth_type);
 		tlv += sizeof(struct host_cmd_tlv_auth_type);
 	}
 	if (bss_cfg->protocol) {
 		encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
-		encrypt_protocol->tlv.type =
+		encrypt_protocol->header.type =
 			cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
-		encrypt_protocol->tlv.len =
+		encrypt_protocol->header.len =
 			cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
-			- sizeof(struct host_cmd_tlv));
+			- sizeof(struct mwifiex_ie_types_header));
 		encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
 		cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
 		tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
@@ -608,9 +614,9 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->sta_ao_timer) {
 		ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
-		ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
-		ao_timer->tlv.len = cpu_to_le16(sizeof(*ao_timer) -
-						sizeof(struct host_cmd_tlv));
+		ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
+		ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) -
+					sizeof(struct mwifiex_ie_types_header));
 		ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer);
 		cmd_size += sizeof(*ao_timer);
 		tlv += sizeof(*ao_timer);
@@ -618,9 +624,10 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 
 	if (bss_cfg->ps_sta_ao_timer) {
 		ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
-		ps_ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
-		ps_ao_timer->tlv.len = cpu_to_le16(sizeof(*ps_ao_timer) -
-						   sizeof(struct host_cmd_tlv));
+		ps_ao_timer->header.type =
+				cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
+		ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) -
+				sizeof(struct mwifiex_ie_types_header));
 		ps_ao_timer->sta_ao_timer =
 					cpu_to_le32(bss_cfg->ps_sta_ao_timer);
 		cmd_size += sizeof(*ps_ao_timer);
@@ -636,16 +643,17 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
 {
 	struct mwifiex_ie_list *ap_ie = cmd_buf;
-	struct host_cmd_tlv *tlv_ie = (struct host_cmd_tlv *)tlv;
+	struct mwifiex_ie_types_header *tlv_ie = (void *)tlv;
 
 	if (!ap_ie || !ap_ie->len || !ap_ie->ie_list)
 		return -1;
 
-	*ie_size += le16_to_cpu(ap_ie->len) + sizeof(struct host_cmd_tlv);
+	*ie_size += le16_to_cpu(ap_ie->len) +
+			sizeof(struct mwifiex_ie_types_header);
 
 	tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
 	tlv_ie->len = ap_ie->len;
-	tlv += sizeof(struct host_cmd_tlv);
+	tlv += sizeof(struct mwifiex_ie_types_header);
 
 	memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
 
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index a018e42..1cfe5a7 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -24,6 +24,69 @@
 #include "11n_aggr.h"
 #include "11n_rxreorder.h"
 
+/* This function checks if particular RA list has packets more than low bridge
+ * packet threshold and then deletes packet from this RA list.
+ * Function deletes packets from such RA list and returns true. If no such list
+ * is found, false is returned.
+ */
+static bool
+mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv,
+				  struct list_head *ra_list_head)
+{
+	struct mwifiex_ra_list_tbl *ra_list;
+	struct sk_buff *skb, *tmp;
+	bool pkt_deleted = false;
+	struct mwifiex_txinfo *tx_info;
+	struct mwifiex_adapter *adapter = priv->adapter;
+
+	list_for_each_entry(ra_list, ra_list_head, list) {
+		if (skb_queue_empty(&ra_list->skb_head))
+			continue;
+
+		skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
+			tx_info = MWIFIEX_SKB_TXCB(skb);
+			if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) {
+				__skb_unlink(skb, &ra_list->skb_head);
+				mwifiex_write_data_complete(adapter, skb, 0,
+							    -1);
+				atomic_dec(&priv->wmm.tx_pkts_queued);
+				pkt_deleted = true;
+			}
+			if ((atomic_read(&adapter->pending_bridged_pkts) <=
+					     MWIFIEX_BRIDGED_PKTS_THR_LOW))
+				break;
+		}
+	}
+
+	return pkt_deleted;
+}
+
+/* This function deletes packets from particular RA List. RA list index
+ * from which packets are deleted is preserved so that packets from next RA
+ * list are deleted upon subsequent call thus maintaining fairness.
+ */
+static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv)
+{
+	unsigned long flags;
+	struct list_head *ra_list;
+	int i;
+
+	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+	for (i = 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) {
+		if (priv->del_list_idx == MAX_NUM_TID)
+			priv->del_list_idx = 0;
+		ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list;
+		if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list)) {
+			priv->del_list_idx++;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+
 static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
 					 struct sk_buff *skb)
 {
@@ -40,10 +103,11 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
 	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
 
 	if ((atomic_read(&adapter->pending_bridged_pkts) >=
-					     MWIFIEX_BRIDGED_PKTS_THRESHOLD)) {
+					     MWIFIEX_BRIDGED_PKTS_THR_HIGH)) {
 		dev_err(priv->adapter->dev,
 			"Tx: Bridge packet limit reached. Drop packet!\n");
 		kfree_skb(skb);
+		mwifiex_uap_cleanup_tx_queues(priv);
 		return;
 	}
 
@@ -95,10 +159,6 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
 	atomic_inc(&adapter->tx_pending);
 	atomic_inc(&adapter->pending_bridged_pkts);
 
-	if ((atomic_read(&adapter->tx_pending) >= MAX_TX_PENDING)) {
-		mwifiex_set_trans_start(priv->netdev);
-		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
-	}
 	return;
 }
 
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index f90fe21..fca98b5 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -786,6 +786,13 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
 	return 0;
 }
 
+static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
+{
+	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+
+	usb_set_intfdata(card->intf, NULL);
+}
+
 static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 				    struct mwifiex_fw_image *fw)
 {
@@ -978,6 +985,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 
 static struct mwifiex_if_ops usb_ops = {
 	.register_dev =		mwifiex_register_dev,
+	.unregister_dev =	mwifiex_unregister_dev,
 	.wakeup =		mwifiex_pm_wakeup_card,
 	.wakeup_complete =	mwifiex_pm_wakeup_card_complete,
 
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 944e884..2e8f9cd 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -120,7 +120,7 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
 
 	memcpy(ra_list->ra, ra, ETH_ALEN);
 
-	ra_list->total_pkts_size = 0;
+	ra_list->total_pkt_count = 0;
 
 	dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list);
 
@@ -188,7 +188,7 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
 			ra_list, ra_list->is_11n_enabled);
 
 		if (ra_list->is_11n_enabled) {
-			ra_list->pkt_count = 0;
+			ra_list->ba_pkt_count = 0;
 			ra_list->ba_packet_thr =
 					      mwifiex_get_random_ba_threshold();
 		}
@@ -679,8 +679,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 
 	skb_queue_tail(&ra_list->skb_head, skb);
 
-	ra_list->total_pkts_size += skb->len;
-	ra_list->pkt_count++;
+	ra_list->ba_pkt_count++;
+	ra_list->total_pkt_count++;
 
 	if (atomic_read(&priv->wmm.highest_queued_prio) <
 						tos_to_tid_inv[tid_down])
@@ -1037,7 +1037,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
 	tx_info = MWIFIEX_SKB_TXCB(skb);
 	dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb);
 
-	ptr->total_pkts_size -= skb->len;
+	ptr->total_pkt_count--;
 
 	if (!skb_queue_empty(&ptr->skb_head))
 		skb_next = skb_peek(&ptr->skb_head);
@@ -1062,8 +1062,8 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
 
 		skb_queue_tail(&ptr->skb_head, skb);
 
-		ptr->total_pkts_size += skb->len;
-		ptr->pkt_count++;
+		ptr->total_pkt_count++;
+		ptr->ba_pkt_count++;
 		tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
 		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 				       ra_list_flags);
@@ -1224,7 +1224,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
 		   mwifiex_send_single_packet() */
 	} else {
 		if (mwifiex_is_ampdu_allowed(priv, tid) &&
-		    ptr->pkt_count > ptr->ba_packet_thr) {
+		    ptr->ba_pkt_count > ptr->ba_packet_thr) {
 			if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
 				mwifiex_create_ba_tbl(priv, ptr->ra, tid,
 						      BA_SETUP_INPROGRESS);
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 3e60a31..68dbbb9 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -166,6 +166,12 @@ config RT2800USB_RT35XX
 	  rt2800usb driver.
 	  Supported chips: RT3572
 
+config RT2800USB_RT3573
+	bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)"
+	---help---
+	  This enables support for RT3573 chipset based wireless USB devices
+	  in the rt2800usb driver.
+
 config RT2800USB_RT53XX
        bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
        ---help---
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index d78c495..a313241 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -88,6 +88,7 @@
 #define REV_RT3071E			0x0211
 #define REV_RT3090E			0x0211
 #define REV_RT3390E			0x0211
+#define REV_RT3593E			0x0211
 #define REV_RT5390F			0x0502
 #define REV_RT5390R			0x1502
 #define REV_RT5592C			0x0221
@@ -1082,6 +1083,15 @@
 #define TX_PWR_CFG_0_9MBS		FIELD32(0x00f00000)
 #define TX_PWR_CFG_0_12MBS		FIELD32(0x0f000000)
 #define TX_PWR_CFG_0_18MBS		FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_0_CCK1_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_CCK1_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_0_CCK5_CH0		FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_CCK5_CH1		FIELD32(0x0000f000)
+#define TX_PWR_CFG_0_OFDM6_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_OFDM6_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_0_OFDM12_CH0		FIELD32(0x0f000000)
+#define TX_PWR_CFG_0_OFDM12_CH1		FIELD32(0xf0000000)
 
 /*
  * TX_PWR_CFG_1:
@@ -1095,6 +1105,15 @@
 #define TX_PWR_CFG_1_MCS1		FIELD32(0x00f00000)
 #define TX_PWR_CFG_1_MCS2		FIELD32(0x0f000000)
 #define TX_PWR_CFG_1_MCS3		FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_1_OFDM24_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_OFDM24_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_1_OFDM48_CH0		FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_OFDM48_CH1		FIELD32(0x0000f000)
+#define TX_PWR_CFG_1_MCS0_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_MCS0_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_1_MCS2_CH0		FIELD32(0x0f000000)
+#define TX_PWR_CFG_1_MCS2_CH1		FIELD32(0xf0000000)
 
 /*
  * TX_PWR_CFG_2:
@@ -1108,6 +1127,15 @@
 #define TX_PWR_CFG_2_MCS9		FIELD32(0x00f00000)
 #define TX_PWR_CFG_2_MCS10		FIELD32(0x0f000000)
 #define TX_PWR_CFG_2_MCS11		FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_2_MCS4_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_MCS4_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_2_MCS6_CH0		FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_MCS6_CH1		FIELD32(0x0000f000)
+#define TX_PWR_CFG_2_MCS8_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_MCS8_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_2_MCS10_CH0		FIELD32(0x0f000000)
+#define TX_PWR_CFG_2_MCS10_CH1		FIELD32(0xf0000000)
 
 /*
  * TX_PWR_CFG_3:
@@ -1121,6 +1149,15 @@
 #define TX_PWR_CFG_3_UKNOWN2		FIELD32(0x00f00000)
 #define TX_PWR_CFG_3_UKNOWN3		FIELD32(0x0f000000)
 #define TX_PWR_CFG_3_UKNOWN4		FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_3_MCS12_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_MCS12_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_MCS14_CH0		FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_MCS14_CH1		FIELD32(0x0000f000)
+#define TX_PWR_CFG_3_STBC0_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_STBC0_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_3_STBC2_CH0		FIELD32(0x0f000000)
+#define TX_PWR_CFG_3_STBC2_CH1		FIELD32(0xf0000000)
 
 /*
  * TX_PWR_CFG_4:
@@ -1130,6 +1167,11 @@
 #define TX_PWR_CFG_4_UKNOWN6		FIELD32(0x000000f0)
 #define TX_PWR_CFG_4_UKNOWN7		FIELD32(0x00000f00)
 #define TX_PWR_CFG_4_UKNOWN8		FIELD32(0x0000f000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_3_STBC4_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_STBC4_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_STBC6_CH0		FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_STBC6_CH1		FIELD32(0x0000f000)
 
 /*
  * TX_PIN_CFG:
@@ -1451,6 +1493,81 @@
  */
 #define EXP_ACK_TIME			0x1380
 
+/* TX_PWR_CFG_5 */
+#define TX_PWR_CFG_5			0x1384
+#define TX_PWR_CFG_5_MCS16_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_5_MCS16_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_5_MCS16_CH2		FIELD32(0x00000f00)
+#define TX_PWR_CFG_5_MCS18_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_5_MCS18_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_5_MCS18_CH2		FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_6 */
+#define TX_PWR_CFG_6			0x1388
+#define TX_PWR_CFG_6_MCS20_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_6_MCS20_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_6_MCS20_CH2		FIELD32(0x00000f00)
+#define TX_PWR_CFG_6_MCS22_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_6_MCS22_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_6_MCS22_CH2		FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_0_EXT */
+#define TX_PWR_CFG_0_EXT		0x1390
+#define TX_PWR_CFG_0_EXT_CCK1_CH2	FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_EXT_CCK5_CH2	FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_EXT_OFDM6_CH2	FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_EXT_OFDM12_CH2	FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_1_EXT */
+#define TX_PWR_CFG_1_EXT		0x1394
+#define TX_PWR_CFG_1_EXT_OFDM24_CH2	FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_EXT_OFDM48_CH2	FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_EXT_MCS0_CH2	FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_EXT_MCS2_CH2	FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_2_EXT */
+#define TX_PWR_CFG_2_EXT		0x1398
+#define TX_PWR_CFG_2_EXT_MCS4_CH2	FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_EXT_MCS6_CH2	FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_EXT_MCS8_CH2	FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_EXT_MCS10_CH2	FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_3_EXT */
+#define TX_PWR_CFG_3_EXT		0x139c
+#define TX_PWR_CFG_3_EXT_MCS12_CH2	FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_EXT_MCS14_CH2	FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_EXT_STBC0_CH2	FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_EXT_STBC2_CH2	FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_4_EXT */
+#define TX_PWR_CFG_4_EXT		0x13a0
+#define TX_PWR_CFG_4_EXT_STBC4_CH2	FIELD32(0x0000000f)
+#define TX_PWR_CFG_4_EXT_STBC6_CH2	FIELD32(0x00000f00)
+
+/* TX_PWR_CFG_7 */
+#define TX_PWR_CFG_7			0x13d4
+#define TX_PWR_CFG_7_OFDM54_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_7_OFDM54_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_7_OFDM54_CH2		FIELD32(0x00000f00)
+#define TX_PWR_CFG_7_MCS7_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_7_MCS7_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_7_MCS7_CH2		FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_8 */
+#define TX_PWR_CFG_8			0x13d8
+#define TX_PWR_CFG_8_MCS15_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_8_MCS15_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_8_MCS15_CH2		FIELD32(0x00000f00)
+#define TX_PWR_CFG_8_MCS23_CH0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_8_MCS23_CH1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_8_MCS23_CH2		FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_9 */
+#define TX_PWR_CFG_9			0x13dc
+#define TX_PWR_CFG_9_STBC7_CH0		FIELD32(0x0000000f)
+#define TX_PWR_CFG_9_STBC7_CH1		FIELD32(0x000000f0)
+#define TX_PWR_CFG_9_STBC7_CH2		FIELD32(0x00000f00)
+
 /*
  * RX_FILTER_CFG: RX configuration register.
  */
@@ -1975,6 +2092,10 @@ struct mac_iveiv_entry {
 #define BBP109_TX0_POWER		FIELD8(0x0f)
 #define BBP109_TX1_POWER		FIELD8(0xf0)
 
+/* BBP 110 */
+#define BBP110_TX2_POWER		FIELD8(0x0f)
+
+
 /*
  * BBP 138: Unknown
  */
@@ -2024,6 +2145,12 @@ struct mac_iveiv_entry {
 #define RFCSR3_PA2_CASCODE_BIAS_CCKK	FIELD8(0x80)
 /* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */
 #define RFCSR3_VCOCAL_EN		FIELD8(0x80)
+/* Bits for RF3050 */
+#define RFCSR3_BIT1			FIELD8(0x02)
+#define RFCSR3_BIT2			FIELD8(0x04)
+#define RFCSR3_BIT3			FIELD8(0x08)
+#define RFCSR3_BIT4			FIELD8(0x10)
+#define RFCSR3_BIT5			FIELD8(0x20)
 
 /*
  * FRCSR 5:
@@ -2036,6 +2163,8 @@ struct mac_iveiv_entry {
 #define RFCSR6_R1			FIELD8(0x03)
 #define RFCSR6_R2			FIELD8(0x40)
 #define RFCSR6_TXDIV		FIELD8(0x0c)
+/* bits for RF3053 */
+#define RFCSR6_VCO_IC			FIELD8(0xc0)
 
 /*
  * RFCSR 7:
@@ -2060,7 +2189,12 @@ struct mac_iveiv_entry {
  * RFCSR 11:
  */
 #define RFCSR11_R			FIELD8(0x03)
+#define RFCSR11_PLL_MOD			FIELD8(0x0c)
 #define RFCSR11_MOD			FIELD8(0xc0)
+/* bits for RF3053 */
+/* TODO: verify RFCSR11_MOD usage on other chips */
+#define RFCSR11_PLL_IDOH		FIELD8(0x40)
+
 
 /*
  * RFCSR 12:
@@ -2092,6 +2226,10 @@ struct mac_iveiv_entry {
 #define RFCSR17_R			FIELD8(0x20)
 #define RFCSR17_CODE                   FIELD8(0x7f)
 
+/* RFCSR 18 */
+#define RFCSR18_XO_TUNE_BYPASS		FIELD8(0x40)
+
+
 /*
  * RFCSR 20:
  */
@@ -2152,6 +2290,12 @@ struct mac_iveiv_entry {
 #define RFCSR31_RX_H20M			FIELD8(0x20)
 #define RFCSR31_RX_CALIB		FIELD8(0x7f)
 
+/* RFCSR 32 bits for RF3053 */
+#define RFCSR32_TX_AGC_FC		FIELD8(0xf8)
+
+/* RFCSR 36 bits for RF3053 */
+#define RFCSR36_RF_BS			FIELD8(0x80)
+
 /*
  * RFCSR 38:
  */
@@ -2160,6 +2304,7 @@ struct mac_iveiv_entry {
 /*
  * RFCSR 39:
  */
+#define RFCSR39_RX_DIV			FIELD8(0x40)
 #define RFCSR39_RX_LO2_EN		FIELD8(0x80)
 
 /*
@@ -2167,12 +2312,36 @@ struct mac_iveiv_entry {
  */
 #define RFCSR49_TX			FIELD8(0x3f)
 #define RFCSR49_EP			FIELD8(0xc0)
+/* bits for RT3593 */
+#define RFCSR49_TX_LO1_IC		FIELD8(0x1c)
+#define RFCSR49_TX_DIV			FIELD8(0x20)
 
 /*
  * RFCSR 50:
  */
 #define RFCSR50_TX			FIELD8(0x3f)
 #define RFCSR50_EP			FIELD8(0xc0)
+/* bits for RT3593 */
+#define RFCSR50_TX_LO1_EN		FIELD8(0x20)
+#define RFCSR50_TX_LO2_EN		FIELD8(0x10)
+
+/* RFCSR 51 */
+/* bits for RT3593 */
+#define RFCSR51_BITS01			FIELD8(0x03)
+#define RFCSR51_BITS24			FIELD8(0x1c)
+#define RFCSR51_BITS57			FIELD8(0xe0)
+
+#define RFCSR53_TX_POWER		FIELD8(0x3f)
+#define RFCSR53_UNKNOWN			FIELD8(0xc0)
+
+#define RFCSR54_TX_POWER		FIELD8(0x3f)
+#define RFCSR54_UNKNOWN			FIELD8(0xc0)
+
+#define RFCSR55_TX_POWER		FIELD8(0x3f)
+#define RFCSR55_UNKNOWN			FIELD8(0xc0)
+
+#define RFCSR57_DRV_CC			FIELD8(0xfc)
+
 
 /*
  * RF registers
@@ -2206,28 +2375,67 @@ struct mac_iveiv_entry {
  * The wordsize of the EEPROM is 16 bits.
  */
 
-/*
- * Chip ID
- */
-#define EEPROM_CHIP_ID			0x0000
+enum rt2800_eeprom_word {
+	EEPROM_CHIP_ID = 0,
+	EEPROM_VERSION,
+	EEPROM_MAC_ADDR_0,
+	EEPROM_MAC_ADDR_1,
+	EEPROM_MAC_ADDR_2,
+	EEPROM_NIC_CONF0,
+	EEPROM_NIC_CONF1,
+	EEPROM_FREQ,
+	EEPROM_LED_AG_CONF,
+	EEPROM_LED_ACT_CONF,
+	EEPROM_LED_POLARITY,
+	EEPROM_NIC_CONF2,
+	EEPROM_LNA,
+	EEPROM_RSSI_BG,
+	EEPROM_RSSI_BG2,
+	EEPROM_TXMIXER_GAIN_BG,
+	EEPROM_RSSI_A,
+	EEPROM_RSSI_A2,
+	EEPROM_TXMIXER_GAIN_A,
+	EEPROM_EIRP_MAX_TX_POWER,
+	EEPROM_TXPOWER_DELTA,
+	EEPROM_TXPOWER_BG1,
+	EEPROM_TXPOWER_BG2,
+	EEPROM_TSSI_BOUND_BG1,
+	EEPROM_TSSI_BOUND_BG2,
+	EEPROM_TSSI_BOUND_BG3,
+	EEPROM_TSSI_BOUND_BG4,
+	EEPROM_TSSI_BOUND_BG5,
+	EEPROM_TXPOWER_A1,
+	EEPROM_TXPOWER_A2,
+	EEPROM_TSSI_BOUND_A1,
+	EEPROM_TSSI_BOUND_A2,
+	EEPROM_TSSI_BOUND_A3,
+	EEPROM_TSSI_BOUND_A4,
+	EEPROM_TSSI_BOUND_A5,
+	EEPROM_TXPOWER_BYRATE,
+	EEPROM_BBP_START,
+
+	/* IDs for extended EEPROM format used by three-chain devices */
+	EEPROM_EXT_LNA2,
+	EEPROM_EXT_TXPOWER_BG3,
+	EEPROM_EXT_TXPOWER_A3,
+
+	/* New values must be added before this */
+	EEPROM_WORD_COUNT
+};
 
 /*
  * EEPROM Version
  */
-#define EEPROM_VERSION			0x0001
 #define EEPROM_VERSION_FAE		FIELD16(0x00ff)
 #define EEPROM_VERSION_VERSION		FIELD16(0xff00)
 
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR_0		0x0002
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_1		0x0003
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2		0x0004
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
@@ -2237,7 +2445,6 @@ struct mac_iveiv_entry {
  * TXPATH: 1: 1T, 2: 2T, 3: 3T
  * RF_TYPE: RFIC type
  */
-#define	EEPROM_NIC_CONF0		0x001a
 #define EEPROM_NIC_CONF0_RXPATH		FIELD16(0x000f)
 #define EEPROM_NIC_CONF0_TXPATH		FIELD16(0x00f0)
 #define EEPROM_NIC_CONF0_RF_TYPE		FIELD16(0x0f00)
@@ -2261,7 +2468,6 @@ struct mac_iveiv_entry {
  * BT_COEXIST: 0: disable, 1: enable
  * DAC_TEST: 0: disable, 1: enable
  */
-#define	EEPROM_NIC_CONF1		0x001b
 #define EEPROM_NIC_CONF1_HW_RADIO		FIELD16(0x0001)
 #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC		FIELD16(0x0002)
 #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G		FIELD16(0x0004)
@@ -2281,7 +2487,6 @@ struct mac_iveiv_entry {
 /*
  * EEPROM frequency
  */
-#define	EEPROM_FREQ			0x001d
 #define EEPROM_FREQ_OFFSET		FIELD16(0x00ff)
 #define EEPROM_FREQ_LED_MODE		FIELD16(0x7f00)
 #define EEPROM_FREQ_LED_POLARITY	FIELD16(0x1000)
@@ -2298,9 +2503,6 @@ struct mac_iveiv_entry {
  * POLARITY_GPIO_4: Polarity GPIO4 setting.
  * LED_MODE: Led mode.
  */
-#define EEPROM_LED_AG_CONF		0x001e
-#define EEPROM_LED_ACT_CONF		0x001f
-#define EEPROM_LED_POLARITY		0x0020
 #define EEPROM_LED_POLARITY_RDY_BG	FIELD16(0x0001)
 #define EEPROM_LED_POLARITY_RDY_A	FIELD16(0x0002)
 #define EEPROM_LED_POLARITY_ACT		FIELD16(0x0004)
@@ -2317,7 +2519,6 @@ struct mac_iveiv_entry {
  * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
  * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved
  */
-#define EEPROM_NIC_CONF2		0x0021
 #define EEPROM_NIC_CONF2_RX_STREAM		FIELD16(0x000f)
 #define EEPROM_NIC_CONF2_TX_STREAM		FIELD16(0x00f0)
 #define EEPROM_NIC_CONF2_CRYSTAL		FIELD16(0x0600)
@@ -2325,54 +2526,46 @@ struct mac_iveiv_entry {
 /*
  * EEPROM LNA
  */
-#define EEPROM_LNA			0x0022
 #define EEPROM_LNA_BG			FIELD16(0x00ff)
 #define EEPROM_LNA_A0			FIELD16(0xff00)
 
 /*
  * EEPROM RSSI BG offset
  */
-#define EEPROM_RSSI_BG			0x0023
 #define EEPROM_RSSI_BG_OFFSET0		FIELD16(0x00ff)
 #define EEPROM_RSSI_BG_OFFSET1		FIELD16(0xff00)
 
 /*
  * EEPROM RSSI BG2 offset
  */
-#define EEPROM_RSSI_BG2			0x0024
 #define EEPROM_RSSI_BG2_OFFSET2		FIELD16(0x00ff)
 #define EEPROM_RSSI_BG2_LNA_A1		FIELD16(0xff00)
 
 /*
  * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2).
  */
-#define EEPROM_TXMIXER_GAIN_BG		0x0024
 #define EEPROM_TXMIXER_GAIN_BG_VAL	FIELD16(0x0007)
 
 /*
  * EEPROM RSSI A offset
  */
-#define EEPROM_RSSI_A			0x0025
 #define EEPROM_RSSI_A_OFFSET0		FIELD16(0x00ff)
 #define EEPROM_RSSI_A_OFFSET1		FIELD16(0xff00)
 
 /*
  * EEPROM RSSI A2 offset
  */
-#define EEPROM_RSSI_A2			0x0026
 #define EEPROM_RSSI_A2_OFFSET2		FIELD16(0x00ff)
 #define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)
 
 /*
  * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2).
  */
-#define EEPROM_TXMIXER_GAIN_A		0x0026
 #define EEPROM_TXMIXER_GAIN_A_VAL	FIELD16(0x0007)
 
 /*
  * EEPROM EIRP Maximum TX power values(unit: dbm)
  */
-#define EEPROM_EIRP_MAX_TX_POWER	0x0027
 #define EEPROM_EIRP_MAX_TX_POWER_2GHZ	FIELD16(0x00ff)
 #define EEPROM_EIRP_MAX_TX_POWER_5GHZ	FIELD16(0xff00)
 
@@ -2383,7 +2576,6 @@ struct mac_iveiv_entry {
  * TYPE: 1: Plus the delta value, 0: minus the delta value
  * ENABLE: enable tx power compensation for 40BW
  */
-#define EEPROM_TXPOWER_DELTA		0x0028
 #define EEPROM_TXPOWER_DELTA_VALUE_2G	FIELD16(0x003f)
 #define EEPROM_TXPOWER_DELTA_TYPE_2G	FIELD16(0x0040)
 #define EEPROM_TXPOWER_DELTA_ENABLE_2G	FIELD16(0x0080)
@@ -2394,8 +2586,6 @@ struct mac_iveiv_entry {
 /*
  * EEPROM TXPOWER 802.11BG
  */
-#define	EEPROM_TXPOWER_BG1		0x0029
-#define	EEPROM_TXPOWER_BG2		0x0030
 #define EEPROM_TXPOWER_BG_SIZE		7
 #define EEPROM_TXPOWER_BG_1		FIELD16(0x00ff)
 #define EEPROM_TXPOWER_BG_2		FIELD16(0xff00)
@@ -2407,7 +2597,6 @@ struct mac_iveiv_entry {
  * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
  *         reduced by (agc_step * -3)
  */
-#define EEPROM_TSSI_BOUND_BG1		0x0037
 #define EEPROM_TSSI_BOUND_BG1_MINUS4	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_BG1_MINUS3	FIELD16(0xff00)
 
@@ -2418,7 +2607,6 @@ struct mac_iveiv_entry {
  * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
  *         reduced by (agc_step * -1)
  */
-#define EEPROM_TSSI_BOUND_BG2		0x0038
 #define EEPROM_TSSI_BOUND_BG2_MINUS2	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_BG2_MINUS1	FIELD16(0xff00)
 
@@ -2428,7 +2616,6 @@ struct mac_iveiv_entry {
  * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
  *        increased by (agc_step * 1)
  */
-#define EEPROM_TSSI_BOUND_BG3		0x0039
 #define EEPROM_TSSI_BOUND_BG3_REF	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_BG3_PLUS1	FIELD16(0xff00)
 
@@ -2439,7 +2626,6 @@ struct mac_iveiv_entry {
  * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
  *        increased by (agc_step * 3)
  */
-#define EEPROM_TSSI_BOUND_BG4		0x003a
 #define EEPROM_TSSI_BOUND_BG4_PLUS2	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_BG4_PLUS3	FIELD16(0xff00)
 
@@ -2449,19 +2635,20 @@ struct mac_iveiv_entry {
  *        increased by (agc_step * 4)
  * AGC_STEP: Temperature compensation step.
  */
-#define EEPROM_TSSI_BOUND_BG5		0x003b
 #define EEPROM_TSSI_BOUND_BG5_PLUS4	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_BG5_AGC_STEP	FIELD16(0xff00)
 
 /*
  * EEPROM TXPOWER 802.11A
  */
-#define EEPROM_TXPOWER_A1		0x003c
-#define EEPROM_TXPOWER_A2		0x0053
 #define EEPROM_TXPOWER_A_SIZE		6
 #define EEPROM_TXPOWER_A_1		FIELD16(0x00ff)
 #define EEPROM_TXPOWER_A_2		FIELD16(0xff00)
 
+/* EEPROM_TXPOWER_{A,G} fields for RT3593 */
+#define EEPROM_TXPOWER_ALC		FIELD8(0x1f)
+#define EEPROM_TXPOWER_FINE_CTRL	FIELD8(0xe0)
+
 /*
  * EEPROM temperature compensation boundaries 802.11A
  * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
@@ -2469,7 +2656,6 @@ struct mac_iveiv_entry {
  * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
  *         reduced by (agc_step * -3)
  */
-#define EEPROM_TSSI_BOUND_A1		0x006a
 #define EEPROM_TSSI_BOUND_A1_MINUS4	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_A1_MINUS3	FIELD16(0xff00)
 
@@ -2480,7 +2666,6 @@ struct mac_iveiv_entry {
  * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
  *         reduced by (agc_step * -1)
  */
-#define EEPROM_TSSI_BOUND_A2		0x006b
 #define EEPROM_TSSI_BOUND_A2_MINUS2	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_A2_MINUS1	FIELD16(0xff00)
 
@@ -2490,7 +2675,6 @@ struct mac_iveiv_entry {
  * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
  *        increased by (agc_step * 1)
  */
-#define EEPROM_TSSI_BOUND_A3		0x006c
 #define EEPROM_TSSI_BOUND_A3_REF	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_A3_PLUS1	FIELD16(0xff00)
 
@@ -2501,7 +2685,6 @@ struct mac_iveiv_entry {
  * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
  *        increased by (agc_step * 3)
  */
-#define EEPROM_TSSI_BOUND_A4		0x006d
 #define EEPROM_TSSI_BOUND_A4_PLUS2	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_A4_PLUS3	FIELD16(0xff00)
 
@@ -2511,14 +2694,12 @@ struct mac_iveiv_entry {
  *        increased by (agc_step * 4)
  * AGC_STEP: Temperature compensation step.
  */
-#define EEPROM_TSSI_BOUND_A5		0x006e
 #define EEPROM_TSSI_BOUND_A5_PLUS4	FIELD16(0x00ff)
 #define EEPROM_TSSI_BOUND_A5_AGC_STEP	FIELD16(0xff00)
 
 /*
  * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode
  */
-#define EEPROM_TXPOWER_BYRATE		0x006f
 #define EEPROM_TXPOWER_BYRATE_SIZE	9
 
 #define EEPROM_TXPOWER_BYRATE_RATE0	FIELD16(0x000f)
@@ -2529,11 +2710,14 @@ struct mac_iveiv_entry {
 /*
  * EEPROM BBP.
  */
-#define	EEPROM_BBP_START		0x0078
 #define EEPROM_BBP_SIZE			16
 #define EEPROM_BBP_VALUE		FIELD16(0x00ff)
 #define EEPROM_BBP_REG_ID		FIELD16(0xff00)
 
+/* EEPROM_EXT_LNA2 */
+#define EEPROM_EXT_LNA2_A1		FIELD16(0x00ff)
+#define EEPROM_EXT_LNA2_A2		FIELD16(0xff00)
+
 /*
  * EEPROM IQ Calibration, unlike other entries those are byte addresses.
  */
@@ -2630,6 +2814,7 @@ struct mac_iveiv_entry {
 #define TXWI_DESC_SIZE_5WORDS		(5 * sizeof(__le32))
 
 #define RXWI_DESC_SIZE_4WORDS		(4 * sizeof(__le32))
+#define RXWI_DESC_SIZE_5WORDS		(5 * sizeof(__le32))
 #define RXWI_DESC_SIZE_6WORDS		(6 * sizeof(__le32))
 
 /*
@@ -2750,18 +2935,15 @@ struct mac_iveiv_entry {
 #define MAX_A_TXPOWER	15
 #define DEFAULT_TXPOWER	5
 
+#define MIN_A_TXPOWER_3593	0
+#define MAX_A_TXPOWER_3593	31
+
 #define TXPOWER_G_FROM_DEV(__txpower) \
 	((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
 
-#define TXPOWER_G_TO_DEV(__txpower) \
-	clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER)
-
 #define TXPOWER_A_FROM_DEV(__txpower) \
 	((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
 
-#define TXPOWER_A_TO_DEV(__txpower) \
-	clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
-
 /*
  *  Board's maximun TX power limitation
  */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 1f80ea5..dedc3d4 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -221,6 +221,157 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
 	mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
+static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
+	[EEPROM_CHIP_ID]		= 0x0000,
+	[EEPROM_VERSION]		= 0x0001,
+	[EEPROM_MAC_ADDR_0]		= 0x0002,
+	[EEPROM_MAC_ADDR_1]		= 0x0003,
+	[EEPROM_MAC_ADDR_2]		= 0x0004,
+	[EEPROM_NIC_CONF0]		= 0x001a,
+	[EEPROM_NIC_CONF1]		= 0x001b,
+	[EEPROM_FREQ]			= 0x001d,
+	[EEPROM_LED_AG_CONF]		= 0x001e,
+	[EEPROM_LED_ACT_CONF]		= 0x001f,
+	[EEPROM_LED_POLARITY]		= 0x0020,
+	[EEPROM_NIC_CONF2]		= 0x0021,
+	[EEPROM_LNA]			= 0x0022,
+	[EEPROM_RSSI_BG]		= 0x0023,
+	[EEPROM_RSSI_BG2]		= 0x0024,
+	[EEPROM_TXMIXER_GAIN_BG]	= 0x0024, /* overlaps with RSSI_BG2 */
+	[EEPROM_RSSI_A]			= 0x0025,
+	[EEPROM_RSSI_A2]		= 0x0026,
+	[EEPROM_TXMIXER_GAIN_A]		= 0x0026, /* overlaps with RSSI_A2 */
+	[EEPROM_EIRP_MAX_TX_POWER]	= 0x0027,
+	[EEPROM_TXPOWER_DELTA]		= 0x0028,
+	[EEPROM_TXPOWER_BG1]		= 0x0029,
+	[EEPROM_TXPOWER_BG2]		= 0x0030,
+	[EEPROM_TSSI_BOUND_BG1]		= 0x0037,
+	[EEPROM_TSSI_BOUND_BG2]		= 0x0038,
+	[EEPROM_TSSI_BOUND_BG3]		= 0x0039,
+	[EEPROM_TSSI_BOUND_BG4]		= 0x003a,
+	[EEPROM_TSSI_BOUND_BG5]		= 0x003b,
+	[EEPROM_TXPOWER_A1]		= 0x003c,
+	[EEPROM_TXPOWER_A2]		= 0x0053,
+	[EEPROM_TSSI_BOUND_A1]		= 0x006a,
+	[EEPROM_TSSI_BOUND_A2]		= 0x006b,
+	[EEPROM_TSSI_BOUND_A3]		= 0x006c,
+	[EEPROM_TSSI_BOUND_A4]		= 0x006d,
+	[EEPROM_TSSI_BOUND_A5]		= 0x006e,
+	[EEPROM_TXPOWER_BYRATE]		= 0x006f,
+	[EEPROM_BBP_START]		= 0x0078,
+};
+
+static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = {
+	[EEPROM_CHIP_ID]		= 0x0000,
+	[EEPROM_VERSION]		= 0x0001,
+	[EEPROM_MAC_ADDR_0]		= 0x0002,
+	[EEPROM_MAC_ADDR_1]		= 0x0003,
+	[EEPROM_MAC_ADDR_2]		= 0x0004,
+	[EEPROM_NIC_CONF0]		= 0x001a,
+	[EEPROM_NIC_CONF1]		= 0x001b,
+	[EEPROM_NIC_CONF2]		= 0x001c,
+	[EEPROM_EIRP_MAX_TX_POWER]	= 0x0020,
+	[EEPROM_FREQ]			= 0x0022,
+	[EEPROM_LED_AG_CONF]		= 0x0023,
+	[EEPROM_LED_ACT_CONF]		= 0x0024,
+	[EEPROM_LED_POLARITY]		= 0x0025,
+	[EEPROM_LNA]			= 0x0026,
+	[EEPROM_EXT_LNA2]		= 0x0027,
+	[EEPROM_RSSI_BG]		= 0x0028,
+	[EEPROM_TXPOWER_DELTA]		= 0x0028, /* Overlaps with RSSI_BG */
+	[EEPROM_RSSI_BG2]		= 0x0029,
+	[EEPROM_TXMIXER_GAIN_BG]	= 0x0029, /* Overlaps with RSSI_BG2 */
+	[EEPROM_RSSI_A]			= 0x002a,
+	[EEPROM_RSSI_A2]		= 0x002b,
+	[EEPROM_TXMIXER_GAIN_A]		= 0x002b, /* Overlaps with RSSI_A2 */
+	[EEPROM_TXPOWER_BG1]		= 0x0030,
+	[EEPROM_TXPOWER_BG2]		= 0x0037,
+	[EEPROM_EXT_TXPOWER_BG3]	= 0x003e,
+	[EEPROM_TSSI_BOUND_BG1]		= 0x0045,
+	[EEPROM_TSSI_BOUND_BG2]		= 0x0046,
+	[EEPROM_TSSI_BOUND_BG3]		= 0x0047,
+	[EEPROM_TSSI_BOUND_BG4]		= 0x0048,
+	[EEPROM_TSSI_BOUND_BG5]		= 0x0049,
+	[EEPROM_TXPOWER_A1]		= 0x004b,
+	[EEPROM_TXPOWER_A2]		= 0x0065,
+	[EEPROM_EXT_TXPOWER_A3]		= 0x007f,
+	[EEPROM_TSSI_BOUND_A1]		= 0x009a,
+	[EEPROM_TSSI_BOUND_A2]		= 0x009b,
+	[EEPROM_TSSI_BOUND_A3]		= 0x009c,
+	[EEPROM_TSSI_BOUND_A4]		= 0x009d,
+	[EEPROM_TSSI_BOUND_A5]		= 0x009e,
+	[EEPROM_TXPOWER_BYRATE]		= 0x00a0,
+};
+
+static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev,
+					     const enum rt2800_eeprom_word word)
+{
+	const unsigned int *map;
+	unsigned int index;
+
+	if (WARN_ONCE(word >= EEPROM_WORD_COUNT,
+		      "%s: invalid EEPROM word %d\n",
+		      wiphy_name(rt2x00dev->hw->wiphy), word))
+		return 0;
+
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		map = rt2800_eeprom_map_ext;
+	else
+		map = rt2800_eeprom_map;
+
+	index = map[word];
+
+	/* Index 0 is valid only for EEPROM_CHIP_ID.
+	 * Otherwise it means that the offset of the
+	 * given word is not initialized in the map,
+	 * or that the field is not usable on the
+	 * actual chipset.
+	 */
+	WARN_ONCE(word != EEPROM_CHIP_ID && index == 0,
+		  "%s: invalid access of EEPROM word %d\n",
+		  wiphy_name(rt2x00dev->hw->wiphy), word);
+
+	return index;
+}
+
+static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev,
+				const enum rt2800_eeprom_word word)
+{
+	unsigned int index;
+
+	index = rt2800_eeprom_word_index(rt2x00dev, word);
+	return rt2x00_eeprom_addr(rt2x00dev, index);
+}
+
+static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
+			       const enum rt2800_eeprom_word word, u16 *data)
+{
+	unsigned int index;
+
+	index = rt2800_eeprom_word_index(rt2x00dev, word);
+	rt2x00_eeprom_read(rt2x00dev, index, data);
+}
+
+static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
+				const enum rt2800_eeprom_word word, u16 data)
+{
+	unsigned int index;
+
+	index = rt2800_eeprom_word_index(rt2x00dev, word);
+	rt2x00_eeprom_write(rt2x00dev, index, data);
+}
+
+static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
+					  const enum rt2800_eeprom_word array,
+					  unsigned int offset,
+					  u16 *data)
+{
+	unsigned int index;
+
+	index = rt2800_eeprom_word_index(rt2x00dev, array);
+	rt2x00_eeprom_read(rt2x00dev, index + offset, data);
+}
+
 static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
@@ -609,16 +760,16 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
 	u8 offset2;
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
 		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
 		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
 		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
 	} else {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
 		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
 		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
 		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
 	}
 
@@ -890,6 +1041,9 @@ const struct rt2x00debug rt2800_rt2x00debug = {
 		.word_count	= CSR_REG_SIZE / sizeof(u32),
 	},
 	.eeprom	= {
+		/* NOTE: The local EEPROM access functions can't
+		 * be used here, use the generic versions instead.
+		 */
 		.read		= rt2x00_eeprom_read,
 		.write		= rt2x00_eeprom_write,
 		.word_base	= EEPROM_BASE,
@@ -1547,7 +1701,7 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
 	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
 	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
 	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
 		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
 		if (led_ctrl == 0 || led_ctrl > 0x40) {
 			rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
@@ -1609,7 +1763,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
 		break;
 	case 3:
-		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
 		break;
 	}
 
@@ -1622,7 +1776,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 		    rt2x00_rt(rt2x00dev, RT3090) ||
 		    rt2x00_rt(rt2x00dev, RT3352) ||
 		    rt2x00_rt(rt2x00dev, RT3390)) {
-			rt2x00_eeprom_read(rt2x00dev,
+			rt2800_eeprom_read(rt2x00dev,
 					   EEPROM_NIC_CONF1, &eeprom);
 			if (rt2x00_get_field16(eeprom,
 						EEPROM_NIC_CONF1_ANT_DIVERSITY))
@@ -1649,6 +1803,13 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 
 	rt2800_bbp_write(rt2x00dev, 3, r3);
 	rt2800_bbp_write(rt2x00dev, 1, r1);
+
+	if (rt2x00_rt(rt2x00dev, RT3593)) {
+		if (ant->rx_chain_num == 1)
+			rt2800_bbp_write(rt2x00dev, 86, 0x00);
+		else
+			rt2800_bbp_write(rt2x00dev, 86, 0x46);
+	}
 }
 EXPORT_SYMBOL_GPL(rt2800_config_ant);
 
@@ -1659,17 +1820,31 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
 	short lna_gain;
 
 	if (libconf->rf.channel <= 14) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
 		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
 	} else if (libconf->rf.channel <= 64) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
 		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
 	} else if (libconf->rf.channel <= 128) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
-		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);
+		if (rt2x00_rt(rt2x00dev, RT3593)) {
+			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+			lna_gain = rt2x00_get_field16(eeprom,
+						      EEPROM_EXT_LNA2_A1);
+		} else {
+			rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+			lna_gain = rt2x00_get_field16(eeprom,
+						      EEPROM_RSSI_BG2_LNA_A1);
+		}
 	} else {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
-		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);
+		if (rt2x00_rt(rt2x00dev, RT3593)) {
+			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+			lna_gain = rt2x00_get_field16(eeprom,
+						      EEPROM_EXT_LNA2_A2);
+		} else {
+			rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+			lna_gain = rt2x00_get_field16(eeprom,
+						      EEPROM_RSSI_A2_LNA_A2);
+		}
 	}
 
 	rt2x00dev->lna_gain = lna_gain;
@@ -1993,6 +2168,303 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
 	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
 
+static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+	u8 txrx_agc_fc;
+	u8 txrx_h20m;
+	u8 rfcsr;
+	u8 bbp;
+	const bool txbf_enabled = false; /* TODO */
+
+	/* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */
+	rt2800_bbp_read(rt2x00dev, 109, &bbp);
+	rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0);
+	rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0);
+	rt2800_bbp_write(rt2x00dev, 109, bbp);
+
+	rt2800_bbp_read(rt2x00dev, 110, &bbp);
+	rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0);
+	rt2800_bbp_write(rt2x00dev, 110, bbp);
+
+	if (rf->channel <= 14) {
+		/* Restore BBP 25 & 26 for 2.4 GHz */
+		rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);
+		rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);
+	} else {
+		/* Hard code BBP 25 & 26 for 5GHz */
+
+		/* Enable IQ Phase correction */
+		rt2800_bbp_write(rt2x00dev, 25, 0x09);
+		/* Setup IQ Phase correction value */
+		rt2800_bbp_write(rt2x00dev, 26, 0xff);
+	}
+
+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf);
+
+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3));
+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2);
+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr);
+	if (rf->channel <= 14) {
+		rfcsr = 0;
+		rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
+				  info->default_power1 & 0x1f);
+	} else {
+		if (rt2x00_is_usb(rt2x00dev))
+			rfcsr = 0x40;
+
+		rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
+				  ((info->default_power1 & 0x18) << 1) |
+				  (info->default_power1 & 7));
+	}
+	rt2800_rfcsr_write(rt2x00dev, 53, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr);
+	if (rf->channel <= 14) {
+		rfcsr = 0;
+		rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
+				  info->default_power2 & 0x1f);
+	} else {
+		if (rt2x00_is_usb(rt2x00dev))
+			rfcsr = 0x40;
+
+		rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
+				  ((info->default_power2 & 0x18) << 1) |
+				  (info->default_power2 & 7));
+	}
+	rt2800_rfcsr_write(rt2x00dev, 55, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr);
+	if (rf->channel <= 14) {
+		rfcsr = 0;
+		rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
+				  info->default_power3 & 0x1f);
+	} else {
+		if (rt2x00_is_usb(rt2x00dev))
+			rfcsr = 0x40;
+
+		rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
+				  ((info->default_power3 & 0x18) << 1) |
+				  (info->default_power3 & 7));
+	}
+	rt2800_rfcsr_write(rt2x00dev, 54, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+
+	switch (rt2x00dev->default_ant.tx_chain_num) {
+	case 3:
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+		/* fallthrough */
+	case 2:
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+		/* fallthrough */
+	case 1:
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+		break;
+	}
+
+	switch (rt2x00dev->default_ant.rx_chain_num) {
+	case 3:
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+		/* fallthrough */
+	case 2:
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+		/* fallthrough */
+	case 1:
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+		break;
+	}
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+	/* TODO: frequency calibration? */
+
+	if (conf_is_ht40(conf)) {
+		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
+						RFCSR24_TX_AGC_FC);
+		txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40,
+					      RFCSR24_TX_H20M);
+	} else {
+		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20,
+						RFCSR24_TX_AGC_FC);
+		txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20,
+					      RFCSR24_TX_H20M);
+	}
+
+	/* NOTE: the reference driver does not writes the new value
+	 * back to RFCSR 32
+	 */
+	rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc);
+
+	if (rf->channel <= 14)
+		rfcsr = 0xa0;
+	else
+		rfcsr = 0x80;
+	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m);
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	/* Band selection */
+	rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
+	rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr);
+	if (rf->channel <= 14)
+		rfcsr = 0x3c;
+	else
+		rfcsr = 0x20;
+	rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+	if (rf->channel <= 14)
+		rfcsr = 0x1a;
+	else
+		rfcsr = 0x12;
+	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+	if (rf->channel >= 1 && rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+	else if (rf->channel >= 36 && rf->channel <= 64)
+		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+	else if (rf->channel >= 100 && rf->channel <= 128)
+		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
+
+	if (rf->channel <= 14) {
+		rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+	} else {
+		rt2800_rfcsr_write(rt2x00dev, 10, 0xd8);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x23);
+	}
+
+	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1);
+	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+	if (rf->channel <= 14) {
+		rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5);
+		rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3);
+	} else {
+		rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4);
+		rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2);
+	}
+	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2);
+
+	if (txbf_enabled)
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1);
+
+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0);
+	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f);
+	rt2800_rfcsr_write(rt2x00dev, 57, rfcsr);
+
+	if (rf->channel <= 14) {
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+	} else {
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
+	}
+
+	/* Initiate VCO calibration */
+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+	if (rf->channel <= 14) {
+		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+	} else {
+		rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+	}
+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+	if (rf->channel >= 1 && rf->channel <= 14) {
+		rfcsr = 0x23;
+		if (txbf_enabled)
+			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+		rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
+	} else if (rf->channel >= 36 && rf->channel <= 64) {
+		rfcsr = 0x36;
+		if (txbf_enabled)
+			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+		rt2800_rfcsr_write(rt2x00dev, 39, 0x36);
+
+		rt2800_rfcsr_write(rt2x00dev, 45, 0xeb);
+	} else if (rf->channel >= 100 && rf->channel <= 128) {
+		rfcsr = 0x32;
+		if (txbf_enabled)
+			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+		rt2800_rfcsr_write(rt2x00dev, 45, 0xb3);
+	} else {
+		rfcsr = 0x30;
+		if (txbf_enabled)
+			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+		rt2800_rfcsr_write(rt2x00dev, 45, 0x9b);
+	}
+}
+
 #define POWER_BOUND		0x27
 #define POWER_BOUND_5G		0x2b
 #define FREQ_OFFSET_BOUND	0x5f
@@ -2563,6 +3035,23 @@ static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel)
 	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
 }
 
+static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev,
+				  unsigned int channel,
+				  char txpower)
+{
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
+
+	if (channel <= 14)
+		return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
+
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
+			       MAX_A_TXPOWER_3593);
+	else
+		return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
+}
+
 static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 				  struct ieee80211_conf *conf,
 				  struct rf_channel *rf,
@@ -2572,13 +3061,14 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	unsigned int tx_pin;
 	u8 bbp, rfcsr;
 
-	if (rf->channel <= 14) {
-		info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
-		info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);
-	} else {
-		info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);
-		info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);
-	}
+	info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+						     info->default_power1);
+	info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+						     info->default_power2);
+	if (rt2x00dev->default_ant.tx_chain_num > 2)
+		info->default_power3 =
+			rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+					      info->default_power3);
 
 	switch (rt2x00dev->chip.rf) {
 	case RF2020:
@@ -2591,6 +3081,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	case RF3052:
 		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
 		break;
+	case RF3053:
+		rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info);
+		break;
 	case RF3290:
 		rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
 		break;
@@ -2636,6 +3129,23 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
 		rt2800_bbp_write(rt2x00dev, 27, 0x20);
 		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+	} else if (rt2x00_rt(rt2x00dev, RT3593)) {
+		if (rf->channel > 14) {
+			/* Disable CCK Packet detection on 5GHz */
+			rt2800_bbp_write(rt2x00dev, 70, 0x00);
+		} else {
+			rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+		}
+
+		if (conf_is_ht40(conf))
+			rt2800_bbp_write(rt2x00dev, 105, 0x04);
+		else
+			rt2800_bbp_write(rt2x00dev, 105, 0x34);
+
+		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+		rt2800_bbp_write(rt2x00dev, 77, 0x98);
 	} else {
 		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
 		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
@@ -2651,16 +3161,27 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 				rt2800_bbp_write(rt2x00dev, 82, 0x62);
 				rt2800_bbp_write(rt2x00dev, 75, 0x46);
 			} else {
-				rt2800_bbp_write(rt2x00dev, 82, 0x84);
+				if (rt2x00_rt(rt2x00dev, RT3593))
+					rt2800_bbp_write(rt2x00dev, 82, 0x62);
+				else
+					rt2800_bbp_write(rt2x00dev, 82, 0x84);
 				rt2800_bbp_write(rt2x00dev, 75, 0x50);
 			}
+			if (rt2x00_rt(rt2x00dev, RT3593))
+				rt2800_bbp_write(rt2x00dev, 83, 0x8a);
 		}
+
 	} else {
 		if (rt2x00_rt(rt2x00dev, RT3572))
 			rt2800_bbp_write(rt2x00dev, 82, 0x94);
+		else if (rt2x00_rt(rt2x00dev, RT3593))
+			rt2800_bbp_write(rt2x00dev, 82, 0x82);
 		else
 			rt2800_bbp_write(rt2x00dev, 82, 0xf2);
 
+		if (rt2x00_rt(rt2x00dev, RT3593))
+			rt2800_bbp_write(rt2x00dev, 83, 0x9a);
+
 		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
 			rt2800_bbp_write(rt2x00dev, 75, 0x46);
 		else
@@ -2731,6 +3252,41 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	if (rt2x00_rt(rt2x00dev, RT3572))
 		rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
 
+	if (rt2x00_rt(rt2x00dev, RT3593)) {
+		if (rt2x00_is_usb(rt2x00dev)) {
+			rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+
+			/* Band selection. GPIO #8 controls all paths */
+			rt2x00_set_field32(&reg, GPIO_CTRL_DIR8, 0);
+			if (rf->channel <= 14)
+				rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 1);
+			else
+				rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 0);
+
+			rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
+
+			/* LNA PE control.
+			* GPIO #4 controls PE0 and PE1,
+			* GPIO #7 controls PE2
+			*/
+			rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
+			rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
+
+			rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+		}
+
+		/* AGC init */
+		if (rf->channel <= 14)
+			reg = 0x1c + 2 * rt2x00dev->lna_gain;
+		else
+			reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3);
+
+		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
+		usleep_range(1000, 1500);
+	}
+
 	if (rt2x00_rt(rt2x00dev, RT5592)) {
 		rt2800_bbp_write(rt2x00dev, 195, 141);
 		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);
@@ -2798,62 +3354,62 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
 	 * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00
 	 */
 	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
 		tssi_bounds[0] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG1_MINUS4);
 		tssi_bounds[1] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG1_MINUS3);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
 		tssi_bounds[2] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG2_MINUS2);
 		tssi_bounds[3] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG2_MINUS1);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
 		tssi_bounds[4] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG3_REF);
 		tssi_bounds[5] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG3_PLUS1);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
 		tssi_bounds[6] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG4_PLUS2);
 		tssi_bounds[7] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG4_PLUS3);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
 		tssi_bounds[8] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_BG5_PLUS4);
 
 		step = rt2x00_get_field16(eeprom,
 					  EEPROM_TSSI_BOUND_BG5_AGC_STEP);
 	} else {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
 		tssi_bounds[0] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A1_MINUS4);
 		tssi_bounds[1] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A1_MINUS3);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
 		tssi_bounds[2] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A2_MINUS2);
 		tssi_bounds[3] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A2_MINUS1);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
 		tssi_bounds[4] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A3_REF);
 		tssi_bounds[5] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A3_PLUS1);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
 		tssi_bounds[6] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A4_PLUS2);
 		tssi_bounds[7] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A4_PLUS3);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
 		tssi_bounds[8] = rt2x00_get_field16(eeprom,
 					EEPROM_TSSI_BOUND_A5_PLUS4);
 
@@ -2899,7 +3455,7 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
 	u8 comp_type;
 	int comp_value = 0;
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
 
 	/*
 	 * HT40 compensation not required.
@@ -2966,6 +3522,9 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 	u8 eirp_txpower_criterion;
 	u8 reg_limit;
 
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return min_t(u8, txpower, 0xc);
+
 	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
 		/*
 		 * Check if eirp txpower exceed txpower_limit.
@@ -2974,12 +3533,12 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 		 * .11b data rate need add additional 4dbm
 		 * when calculating eirp txpower.
 		 */
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,
-				   &eeprom);
+		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+					      1, &eeprom);
 		criterion = rt2x00_get_field16(eeprom,
 					       EEPROM_TXPOWER_BYRATE_RATE0);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
+		rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
 				   &eeprom);
 
 		if (band == IEEE80211_BAND_2GHZ)
@@ -3001,6 +3560,412 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 	return min_t(u8, txpower, 0xc);
 }
 
+
+enum {
+	TX_PWR_CFG_0_IDX,
+	TX_PWR_CFG_1_IDX,
+	TX_PWR_CFG_2_IDX,
+	TX_PWR_CFG_3_IDX,
+	TX_PWR_CFG_4_IDX,
+	TX_PWR_CFG_5_IDX,
+	TX_PWR_CFG_6_IDX,
+	TX_PWR_CFG_7_IDX,
+	TX_PWR_CFG_8_IDX,
+	TX_PWR_CFG_9_IDX,
+	TX_PWR_CFG_0_EXT_IDX,
+	TX_PWR_CFG_1_EXT_IDX,
+	TX_PWR_CFG_2_EXT_IDX,
+	TX_PWR_CFG_3_EXT_IDX,
+	TX_PWR_CFG_4_EXT_IDX,
+	TX_PWR_CFG_IDX_COUNT,
+};
+
+static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_channel *chan,
+					 int power_level)
+{
+	u8 txpower;
+	u16 eeprom;
+	u32 regs[TX_PWR_CFG_IDX_COUNT];
+	unsigned int offset;
+	enum ieee80211_band band = chan->band;
+	int delta;
+	int i;
+
+	memset(regs, '\0', sizeof(regs));
+
+	/* TODO: adapt TX power reduction from the rt28xx code */
+
+	/* calculate temperature compensation delta */
+	delta = rt2800_get_gain_calibration_delta(rt2x00dev);
+
+	if (band == IEEE80211_BAND_5GHZ)
+		offset = 16;
+	else
+		offset = 0;
+
+	if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+		offset += 8;
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset, &eeprom);
+
+	/* CCK 1MBS,2MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_CCK1_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_CCK1_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+			   TX_PWR_CFG_0_EXT_CCK1_CH2, txpower);
+
+	/* CCK 5.5MBS,11MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_CCK5_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_CCK5_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+			   TX_PWR_CFG_0_EXT_CCK5_CH2, txpower);
+
+	/* OFDM 6MBS,9MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_OFDM6_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_OFDM6_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+			   TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower);
+
+	/* OFDM 12MBS,18MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_OFDM12_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+			   TX_PWR_CFG_0_OFDM12_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+			   TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 1, &eeprom);
+
+	/* OFDM 24MBS,36MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_OFDM24_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_OFDM24_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+			   TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower);
+
+	/* OFDM 48MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_OFDM48_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_OFDM48_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+			   TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower);
+
+	/* OFDM 54MBS */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+			   TX_PWR_CFG_7_OFDM54_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+			   TX_PWR_CFG_7_OFDM54_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+			   TX_PWR_CFG_7_OFDM54_CH2, txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 2, &eeprom);
+
+	/* MCS 0,1 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_MCS0_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_MCS0_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+			   TX_PWR_CFG_1_EXT_MCS0_CH2, txpower);
+
+	/* MCS 2,3 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_MCS2_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+			   TX_PWR_CFG_1_MCS2_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+			   TX_PWR_CFG_1_EXT_MCS2_CH2, txpower);
+
+	/* MCS 4,5 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS4_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS4_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+			   TX_PWR_CFG_2_EXT_MCS4_CH2, txpower);
+
+	/* MCS 6 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS6_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS6_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+			   TX_PWR_CFG_2_EXT_MCS6_CH2, txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 3, &eeprom);
+
+	/* MCS 7 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+			   TX_PWR_CFG_7_MCS7_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+			   TX_PWR_CFG_7_MCS7_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+			   TX_PWR_CFG_7_MCS7_CH2, txpower);
+
+	/* MCS 8,9 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS8_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS8_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+			   TX_PWR_CFG_2_EXT_MCS8_CH2, txpower);
+
+	/* MCS 10,11 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS10_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+			   TX_PWR_CFG_2_MCS10_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+			   TX_PWR_CFG_2_EXT_MCS10_CH2, txpower);
+
+	/* MCS 12,13 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_MCS12_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_MCS12_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+			   TX_PWR_CFG_3_EXT_MCS12_CH2, txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 4, &eeprom);
+
+	/* MCS 14 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_MCS14_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_MCS14_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+			   TX_PWR_CFG_3_EXT_MCS14_CH2, txpower);
+
+	/* MCS 15 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+			   TX_PWR_CFG_8_MCS15_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+			   TX_PWR_CFG_8_MCS15_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+			   TX_PWR_CFG_8_MCS15_CH2, txpower);
+
+	/* MCS 16,17 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+			   TX_PWR_CFG_5_MCS16_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+			   TX_PWR_CFG_5_MCS16_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+			   TX_PWR_CFG_5_MCS16_CH2, txpower);
+
+	/* MCS 18,19 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+			   TX_PWR_CFG_5_MCS18_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+			   TX_PWR_CFG_5_MCS18_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+			   TX_PWR_CFG_5_MCS18_CH2, txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 5, &eeprom);
+
+	/* MCS 20,21 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+			   TX_PWR_CFG_6_MCS20_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+			   TX_PWR_CFG_6_MCS20_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+			   TX_PWR_CFG_6_MCS20_CH2, txpower);
+
+	/* MCS 22 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+			   TX_PWR_CFG_6_MCS22_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+			   TX_PWR_CFG_6_MCS22_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+			   TX_PWR_CFG_6_MCS22_CH2, txpower);
+
+	/* MCS 23 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+			   TX_PWR_CFG_8_MCS23_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+			   TX_PWR_CFG_8_MCS23_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+			   TX_PWR_CFG_8_MCS23_CH2, txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 6, &eeprom);
+
+	/* STBC, MCS 0,1 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_STBC0_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_STBC0_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+			   TX_PWR_CFG_3_EXT_STBC0_CH2, txpower);
+
+	/* STBC, MCS 2,3 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_STBC2_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+			   TX_PWR_CFG_3_STBC2_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+			   TX_PWR_CFG_3_EXT_STBC2_CH2, txpower);
+
+	/* STBC, MCS 4,5 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0,
+			   txpower);
+
+	/* STBC, MCS 6 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2,
+			   txpower);
+
+	/* read the next four txpower values */
+	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+				      offset + 7, &eeprom);
+
+	/* STBC, MCS 7 */
+	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+					    txpower, delta);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
+			   TX_PWR_CFG_9_STBC7_CH0, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
+			   TX_PWR_CFG_9_STBC7_CH1, txpower);
+	rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
+			   TX_PWR_CFG_9_STBC7_CH2, txpower);
+
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]);
+
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT,
+			      regs[TX_PWR_CFG_0_EXT_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT,
+			      regs[TX_PWR_CFG_1_EXT_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT,
+			      regs[TX_PWR_CFG_2_EXT_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT,
+			      regs[TX_PWR_CFG_3_EXT_IDX]);
+	rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT,
+			      regs[TX_PWR_CFG_4_EXT_IDX]);
+
+	for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++)
+		rt2x00_dbg(rt2x00dev,
+			   "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n",
+			   (band == IEEE80211_BAND_5GHZ) ? '5' : '2',
+			   (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ?
+								'4' : '2',
+			   (i > TX_PWR_CFG_9_IDX) ?
+					(i - TX_PWR_CFG_9_IDX - 1) : i,
+			   (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "",
+			   (unsigned long) regs[i]);
+}
+
 /*
  * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
  * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
@@ -3010,9 +3975,9 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
  * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
  * current conditions (i.e. band, bandwidth, temperature, user settings).
  */
-static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
-				  struct ieee80211_channel *chan,
-				  int power_level)
+static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_channel *chan,
+					 int power_level)
 {
 	u8 txpower, r1;
 	u16 eeprom;
@@ -3080,8 +4045,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
 		rt2800_register_read(rt2x00dev, offset, &reg);
 
 		/* read the next four txpower values */
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i,
-				   &eeprom);
+		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+					      i, &eeprom);
 
 		is_rate_b = i ? 0 : 1;
 		/*
@@ -3129,8 +4094,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
 
 		/* read the next four txpower values */
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1,
-				   &eeprom);
+		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+					      i + 1, &eeprom);
 
 		is_rate_b = 0;
 		/*
@@ -3184,6 +4149,16 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
+static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
+				  struct ieee80211_channel *chan,
+				  int power_level)
+{
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
+	else
+		rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);
+}
+
 void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
 {
 	rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan,
@@ -3219,6 +4194,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
 		rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
 		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 		break;
+	case RF3053:
 	case RF3290:
 	case RF5360:
 	case RF5370:
@@ -3528,7 +4504,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+					   &eeprom);
 			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
 				rt2800_register_write(rt2x00dev, TX_SW_CFG2,
 						      0x0000002c);
@@ -3559,6 +4536,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	} else if (rt2x00_rt(rt2x00dev, RT3572)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+	} else if (rt2x00_rt(rt2x00dev, RT3593)) {
+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+		if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) {
+			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+					   &eeprom);
+			if (rt2x00_get_field16(eeprom,
+					       EEPROM_NIC_CONF1_DAC_TEST))
+				rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+						      0x0000001f);
+			else
+				rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+						      0x0000000f);
+		} else {
+			rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+					      0x00000000);
+		}
 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
 		   rt2x00_rt(rt2x00dev, RT5392) ||
 		   rt2x00_rt(rt2x00dev, RT5592)) {
@@ -3989,7 +4983,7 @@ static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)
 	u8 value;
 
 	rt2800_bbp_read(rt2x00dev, 138, &value);
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
 		value |= 0x20;
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
@@ -4332,6 +5326,22 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev)
 	rt2800_disable_unused_dac_adc(rt2x00dev);
 }
 
+static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev)
+{
+	rt2800_init_bbp_early(rt2x00dev);
+
+	rt2800_bbp_write(rt2x00dev, 79, 0x13);
+	rt2800_bbp_write(rt2x00dev, 80, 0x05);
+	rt2800_bbp_write(rt2x00dev, 81, 0x33);
+	rt2800_bbp_write(rt2x00dev, 137, 0x0f);
+
+	rt2800_bbp_write(rt2x00dev, 84, 0x19);
+
+	/* Enable DC filter */
+	if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E))
+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+}
+
 static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 {
 	int ant, div_mode;
@@ -4402,7 +5412,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_disable_unused_dac_adc(rt2x00dev);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 	div_mode = rt2x00_get_field16(eeprom,
 				      EEPROM_NIC_CONF1_ANT_DIVERSITY);
 	ant = (div_mode == 3) ? 1 : 0;
@@ -4488,7 +5498,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_bbp4_mac_if_ctrl(rt2x00dev);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 	div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);
 	ant = (div_mode == 3) ? 1 : 0;
 	rt2800_bbp_read(rt2x00dev, 152, &value);
@@ -4547,6 +5557,9 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	case RT3572:
 		rt2800_init_bbp_3572(rt2x00dev);
 		break;
+	case RT3593:
+		rt2800_init_bbp_3593(rt2x00dev);
+		return;
 	case RT5390:
 	case RT5392:
 		rt2800_init_bbp_53xx(rt2x00dev);
@@ -4557,7 +5570,8 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	}
 
 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i,
+					      &eeprom);
 
 		if (eeprom != 0xffff && eeprom != 0x0000) {
 			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -4728,7 +5742,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt(rt2x00dev, RT3090)) {
 		/*  Turn off unused DAC1 and ADC1 to reduce power consumption */
 		rt2800_bbp_read(rt2x00dev, 138, &bbp);
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
 			rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
 		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
@@ -4771,6 +5785,42 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
 	}
 }
 
+static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+	u8 rfcsr;
+	u8 tx_gain;
+
+	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0);
+	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+	tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g,
+				    RFCSR17_TXMIXER_GAIN);
+	rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain);
+	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
+	rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
+	rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	/* TODO: enable stream mode */
+}
+
 static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
 {
 	u8 reg;
@@ -4778,7 +5828,7 @@ static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
 
 	/*  Turn off unused DAC1 and ADC1 to reduce power consumption */
 	rt2800_bbp_read(rt2x00dev, 138, &reg);
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
 		rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
@@ -4884,7 +5934,8 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
 		rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
 		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
-			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+					   &eeprom);
 			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
 				rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
 			else
@@ -5152,6 +6203,136 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
 	rt2800_normal_mode_setup_3xxx(rt2x00dev);
 }
 
+static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev)
+{
+	u8 bbp;
+	bool txbf_enabled = false; /* FIXME */
+
+	rt2800_bbp_read(rt2x00dev, 105, &bbp);
+	if (rt2x00dev->default_ant.rx_chain_num == 1)
+		rt2x00_set_field8(&bbp, BBP105_MLD, 0);
+	else
+		rt2x00_set_field8(&bbp, BBP105_MLD, 1);
+	rt2800_bbp_write(rt2x00dev, 105, bbp);
+
+	rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+	rt2800_bbp_write(rt2x00dev, 92, 0x02);
+	rt2800_bbp_write(rt2x00dev, 82, 0x82);
+	rt2800_bbp_write(rt2x00dev, 106, 0x05);
+	rt2800_bbp_write(rt2x00dev, 104, 0x92);
+	rt2800_bbp_write(rt2x00dev, 88, 0x90);
+	rt2800_bbp_write(rt2x00dev, 148, 0xc8);
+	rt2800_bbp_write(rt2x00dev, 47, 0x48);
+	rt2800_bbp_write(rt2x00dev, 120, 0x50);
+
+	if (txbf_enabled)
+		rt2800_bbp_write(rt2x00dev, 163, 0xbd);
+	else
+		rt2800_bbp_write(rt2x00dev, 163, 0x9d);
+
+	/* SNR mapping */
+	rt2800_bbp_write(rt2x00dev, 142, 6);
+	rt2800_bbp_write(rt2x00dev, 143, 160);
+	rt2800_bbp_write(rt2x00dev, 142, 7);
+	rt2800_bbp_write(rt2x00dev, 143, 161);
+	rt2800_bbp_write(rt2x00dev, 142, 8);
+	rt2800_bbp_write(rt2x00dev, 143, 162);
+
+	/* ADC/DAC control */
+	rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+	/* RX AGC energy lower bound in log2 */
+	rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+	/* FIXME: BBP 105 owerwrite? */
+	rt2800_bbp_write(rt2x00dev, 105, 0x04);
+
+}
+
+static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+	u32 reg;
+	u8 rfcsr;
+
+	/* Disable GPIO #4 and #7 function for LAN PE control */
+	rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+	rt2x00_set_field32(&reg, GPIO_SWITCH_4, 0);
+	rt2x00_set_field32(&reg, GPIO_SWITCH_7, 0);
+	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+	/* Initialize default register values */
+	rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
+	rt2800_rfcsr_write(rt2x00dev, 3, 0x80);
+	rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+	rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
+	rt2800_rfcsr_write(rt2x00dev, 11, 0x40);
+	rt2800_rfcsr_write(rt2x00dev, 12, 0x4e);
+	rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+	rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
+	rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+	rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+	rt2800_rfcsr_write(rt2x00dev, 32, 0x78);
+	rt2800_rfcsr_write(rt2x00dev, 33, 0x3b);
+	rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
+	rt2800_rfcsr_write(rt2x00dev, 35, 0xe0);
+	rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
+	rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
+	rt2800_rfcsr_write(rt2x00dev, 44, 0xd3);
+	rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
+	rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
+	rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
+	rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
+	rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
+	rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+	rt2800_rfcsr_write(rt2x00dev, 53, 0x18);
+	rt2800_rfcsr_write(rt2x00dev, 54, 0x18);
+	rt2800_rfcsr_write(rt2x00dev, 55, 0x18);
+	rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
+	rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
+
+	/* Initiate calibration */
+	/* TODO: use rt2800_rf_init_calibration ? */
+	rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
+	rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+
+	rt2800_adjust_freq_offset(rt2x00dev);
+
+	rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1);
+	rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
+
+	rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+	rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+	rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+	rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+	usleep_range(1000, 1500);
+	rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+	rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+	rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+	/* Set initial values for RX filter calibration */
+	drv_data->calibration_bw20 = 0x1f;
+	drv_data->calibration_bw40 = 0x2f;
+
+	/* Save BBP 25 & 26 values for later use in channel switching */
+	rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
+	rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+
+	rt2800_led_open_drain_enable(rt2x00dev);
+	rt2800_normal_mode_setup_3593(rt2x00dev);
+
+	rt3593_post_bbp_init(rt2x00dev);
+
+	/* TODO: enable stream mode support */
+}
+
 static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
 {
 	rt2800_rf_init_calibration(rt2x00dev, 2);
@@ -5380,6 +6561,9 @@ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	case RT3572:
 		rt2800_init_rfcsr_3572(rt2x00dev);
 		break;
+	case RT3593:
+		rt2800_init_rfcsr_3593(rt2x00dev);
+		break;
 	case RT5390:
 		rt2800_init_rfcsr_5390(rt2x00dev);
 		break;
@@ -5456,15 +6640,15 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Initialize LED control
 	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
 	rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,
 			   word & 0xff, (word >> 8) & 0xff);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
 	rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,
 			   word & 0xff, (word >> 8) & 0xff);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
 	rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,
 			   word & 0xff, (word >> 8) & 0xff);
 
@@ -5560,6 +6744,34 @@ int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
 
+static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
+{
+	u16 word;
+
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return 0;
+
+	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+	if ((word & 0x00ff) != 0x00ff)
+		return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
+
+	return 0;
+}
+
+static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
+{
+	u16 word;
+
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return 0;
+
+	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
+	if ((word & 0x00ff) != 0x00ff)
+		return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
+
+	return 0;
+}
+
 static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 {
 	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -5578,18 +6790,18 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Start validation of the data that has been read.
 	 */
-	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+	mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
 	if (!is_valid_ether_addr(mac)) {
 		eth_random_addr(mac);
 		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
 	}
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
 	if (word == 0xffff) {
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
 		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
 	} else if (rt2x00_rt(rt2x00dev, RT2860) ||
 		   rt2x00_rt(rt2x00dev, RT2872)) {
@@ -5598,10 +6810,10 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 		 */
 		if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2)
 			rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
 	}
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
 	if (word == 0xffff) {
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);
@@ -5618,24 +6830,24 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0);
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
 		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
 	}
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
 	if ((word & 0x00ff) == 0x00ff) {
 		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
 		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
 	}
 	if ((word & 0xff00) == 0xff00) {
 		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
 				   LED_MODE_TXRX_ACTIVITY);
 		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
 		rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);
 	}
 
@@ -5644,56 +6856,61 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * lna0 as correct value. Note that EEPROM_LNA
 	 * is never validated.
 	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
 	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
 		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
 		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
+	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
-	if ((word & 0x00ff) != 0x00ff) {
-		drv_data->txmixer_gain_24g =
-			rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
-	} else {
-		drv_data->txmixer_gain_24g = 0;
-	}
+	drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
 		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
-	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
-	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
-				   default_lna_gain);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
-	if ((word & 0x00ff) != 0x00ff) {
-		drv_data->txmixer_gain_5g =
-			rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
-	} else {
-		drv_data->txmixer_gain_5g = 0;
+	if (!rt2x00_rt(rt2x00dev, RT3593)) {
+		if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
+		    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
+			rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
+					   default_lna_gain);
 	}
+	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
+
+	drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
 		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
 		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
+	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
 		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
-	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
-	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
-				   default_lna_gain);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+	if (!rt2x00_rt(rt2x00dev, RT3593)) {
+		if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
+		    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
+			rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
+					   default_lna_gain);
+	}
+	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+
+	if (rt2x00_rt(rt2x00dev, RT3593)) {
+		rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word);
+		if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
+		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
+			rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
+					   default_lna_gain);
+		if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 ||
+		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff)
+			rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
+					   default_lna_gain);
+		rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word);
+	}
 
 	return 0;
 }
@@ -5707,7 +6924,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Read EEPROM word for configuration.
 	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 
 	/*
 	 * Identify RF chipset by EEPROM value
@@ -5717,7 +6934,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt(rt2x00dev, RT3290) ||
 	    rt2x00_rt(rt2x00dev, RT5390) ||
 	    rt2x00_rt(rt2x00dev, RT5392))
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 	else
 		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 
@@ -5731,6 +6948,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	case RF3021:
 	case RF3022:
 	case RF3052:
+	case RF3053:
 	case RF3290:
 	case RF3320:
 	case RF3322:
@@ -5757,7 +6975,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00dev->default_ant.rx_chain_num =
 	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 
 	if (rt2x00_rt(rt2x00dev, RT3070) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
@@ -5810,7 +7028,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Read frequency offset and RF programming sequence.
 	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
 	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
 
 	/*
@@ -5827,7 +7045,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Check if support EIRP tx power limit feature.
 	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
 					EIRP_MAX_TX_POWER_LIMIT)
@@ -6109,12 +7327,79 @@ static const struct rf_channel rf_vals_5592_xtal40[] = {
 	{196, 83, 0, 12, 1},
 };
 
+static const struct rf_channel rf_vals_3053[] = {
+	/* Channel, N, R, K */
+	{1, 241, 2, 2},
+	{2, 241, 2, 7},
+	{3, 242, 2, 2},
+	{4, 242, 2, 7},
+	{5, 243, 2, 2},
+	{6, 243, 2, 7},
+	{7, 244, 2, 2},
+	{8, 244, 2, 7},
+	{9, 245, 2, 2},
+	{10, 245, 2, 7},
+	{11, 246, 2, 2},
+	{12, 246, 2, 7},
+	{13, 247, 2, 2},
+	{14, 248, 2, 4},
+
+	{36, 0x56, 0, 4},
+	{38, 0x56, 0, 6},
+	{40, 0x56, 0, 8},
+	{44, 0x57, 0, 0},
+	{46, 0x57, 0, 2},
+	{48, 0x57, 0, 4},
+	{52, 0x57, 0, 8},
+	{54, 0x57, 0, 10},
+	{56, 0x58, 0, 0},
+	{60, 0x58, 0, 4},
+	{62, 0x58, 0, 6},
+	{64, 0x58, 0, 8},
+
+	{100, 0x5B, 0, 8},
+	{102, 0x5B, 0, 10},
+	{104, 0x5C, 0, 0},
+	{108, 0x5C, 0, 4},
+	{110, 0x5C, 0, 6},
+	{112, 0x5C, 0, 8},
+
+	/* NOTE: Channel 114 has been removed intentionally.
+	 * The EEPROM contains no TX power values for that,
+	 * and it is disabled in the vendor driver as well.
+	 */
+
+	{116, 0x5D, 0, 0},
+	{118, 0x5D, 0, 2},
+	{120, 0x5D, 0, 4},
+	{124, 0x5D, 0, 8},
+	{126, 0x5D, 0, 10},
+	{128, 0x5E, 0, 0},
+	{132, 0x5E, 0, 4},
+	{134, 0x5E, 0, 6},
+	{136, 0x5E, 0, 8},
+	{140, 0x5F, 0, 0},
+
+	{149, 0x5F, 0, 9},
+	{151, 0x5F, 0, 11},
+	{153, 0x60, 0, 1},
+	{157, 0x60, 0, 5},
+	{159, 0x60, 0, 7},
+	{161, 0x60, 0, 9},
+	{165, 0x61, 0, 1},
+	{167, 0x61, 0, 3},
+	{169, 0x61, 0, 5},
+	{171, 0x61, 0, 7},
+	{173, 0x61, 0, 9},
+};
+
 static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
 	struct channel_info *info;
 	char *default_power1;
 	char *default_power2;
+	char *default_power3;
 	unsigned int i;
 	u16 eeprom;
 	u32 reg;
@@ -6148,7 +7433,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-				rt2x00_eeprom_addr(rt2x00dev,
+				rt2800_eeprom_addr(rt2x00dev,
 						   EEPROM_MAC_ADDR_0));
 
 	/*
@@ -6164,7 +7449,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	rt2x00dev->hw->max_report_rates = 7;
 	rt2x00dev->hw->max_rate_tries = 1;
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 
 	/*
 	 * Initialize hw_mode information.
@@ -6199,6 +7484,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		spec->supported_bands |= SUPPORT_BAND_5GHZ;
 		spec->num_channels = ARRAY_SIZE(rf_vals_3x);
 		spec->channels = rf_vals_3x;
+	} else if (rt2x00_rf(rt2x00dev, RF3053)) {
+		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+		spec->num_channels = ARRAY_SIZE(rf_vals_3053);
+		spec->channels = rf_vals_3053;
 	} else if (rt2x00_rf(rt2x00dev, RF5592)) {
 		spec->supported_bands |= SUPPORT_BAND_5GHZ;
 
@@ -6264,21 +7553,40 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 
 	spec->channels_info = info;
 
-	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
-	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+	default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
+	default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+
+	if (rt2x00dev->default_ant.tx_chain_num > 2)
+		default_power3 = rt2800_eeprom_addr(rt2x00dev,
+						    EEPROM_EXT_TXPOWER_BG3);
+	else
+		default_power3 = NULL;
 
 	for (i = 0; i < 14; i++) {
 		info[i].default_power1 = default_power1[i];
 		info[i].default_power2 = default_power2[i];
+		if (default_power3)
+			info[i].default_power3 = default_power3[i];
 	}
 
 	if (spec->num_channels > 14) {
-		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
-		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
+		default_power1 = rt2800_eeprom_addr(rt2x00dev,
+						    EEPROM_TXPOWER_A1);
+		default_power2 = rt2800_eeprom_addr(rt2x00dev,
+						    EEPROM_TXPOWER_A2);
+
+		if (rt2x00dev->default_ant.tx_chain_num > 2)
+			default_power3 =
+				rt2800_eeprom_addr(rt2x00dev,
+						   EEPROM_EXT_TXPOWER_A3);
+		else
+			default_power3 = NULL;
 
 		for (i = 14; i < spec->num_channels; i++) {
 			info[i].default_power1 = default_power1[i - 14];
 			info[i].default_power2 = default_power2[i - 14];
+			if (default_power3)
+				info[i].default_power3 = default_power3[i - 14];
 		}
 	}
 
@@ -6289,6 +7597,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	case RF3022:
 	case RF3320:
 	case RF3052:
+	case RF3053:
 	case RF3290:
 	case RF5360:
 	case RF5370:
@@ -6327,6 +7636,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
 	case RT3352:
 	case RT3390:
 	case RT3572:
+	case RT3593:
 	case RT5390:
 	case RT5392:
 	case RT5592:
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 840833b..fc9efdf 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -854,7 +854,10 @@ static void rt2800usb_queue_init(struct data_queue *queue)
 	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	unsigned short txwi_size, rxwi_size;
 
-	if (rt2x00_rt(rt2x00dev, RT5592)) {
+	if (rt2x00_rt(rt2x00dev, RT3593)) {
+		txwi_size = TXWI_DESC_SIZE_4WORDS;
+		rxwi_size = RXWI_DESC_SIZE_5WORDS;
+	} else if (rt2x00_rt(rt2x00dev, RT5592)) {
 		txwi_size = TXWI_DESC_SIZE_5WORDS;
 		rxwi_size = RXWI_DESC_SIZE_6WORDS;
 	} else {
@@ -1194,6 +1197,40 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	/* Zinwell */
 	{ USB_DEVICE(0x5a57, 0x0284) },
 #endif
+#ifdef CONFIG_RT2800USB_RT3573
+	/* AirLive */
+	{ USB_DEVICE(0x1b75, 0x7733) },
+	/* ASUS */
+	{ USB_DEVICE(0x0b05, 0x17bc) },
+	{ USB_DEVICE(0x0b05, 0x17ad) },
+	/* Belkin */
+	{ USB_DEVICE(0x050d, 0x1103) },
+	/* Cameo */
+	{ USB_DEVICE(0x148f, 0xf301) },
+	/* Edimax */
+	{ USB_DEVICE(0x7392, 0x7733) },
+	/* Hawking */
+	{ USB_DEVICE(0x0e66, 0x0020) },
+	{ USB_DEVICE(0x0e66, 0x0021) },
+	/* I-O DATA */
+	{ USB_DEVICE(0x04bb, 0x094e) },
+	/* Linksys */
+	{ USB_DEVICE(0x13b1, 0x003b) },
+	/* Logitec */
+	{ USB_DEVICE(0x0789, 0x016b) },
+	/* NETGEAR */
+	{ USB_DEVICE(0x0846, 0x9012) },
+	{ USB_DEVICE(0x0846, 0x9019) },
+	/* Planex */
+	{ USB_DEVICE(0x2019, 0xed19) },
+	/* Ralink */
+	{ USB_DEVICE(0x148f, 0x3573) },
+	/* Sitecom */
+	{ USB_DEVICE(0x0df6, 0x0067) },
+	{ USB_DEVICE(0x0df6, 0x006a) },
+	/* ZyXEL */
+	{ USB_DEVICE(0x0586, 0x3421) },
+#endif
 #ifdef CONFIG_RT2800USB_RT53XX
 	/* Arcadyan */
 	{ USB_DEVICE(0x043e, 0x7a12) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index ee3fc57..fe4c572 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -211,6 +211,7 @@ struct channel_info {
 	short max_power;
 	short default_power1;
 	short default_power2;
+	short default_power3;
 };
 
 /*
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index f9f059d..a98acef 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -218,6 +218,7 @@ static void rtl_tx_status(void *ppriv,
 
 static void rtl_rate_init(void *ppriv,
 			  struct ieee80211_supported_band *sband,
+			  struct cfg80211_chan_def *chandef,
 			  struct ieee80211_sta *sta, void *priv_sta)
 {
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
index 8e3ec1e..0f7812e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
@@ -109,5 +109,8 @@ void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
 			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
 bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw);
+void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta,
+				 u8 rssi_level);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
index 262e1e4..a1310ab 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
@@ -49,8 +49,5 @@ bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
 			    enum radio_path rfpath, u32 regaddr, u32 bitmask);
 void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
-void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw,
-				 struct ieee80211_sta *sta,
-				 u8 rssi_level);
 
 #endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index b8db55c..d1b19c3 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1315,7 +1315,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
 
 #ifdef CONFIG_PM
 static int
-wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p)
+wl1271_validate_wowlan_pattern(struct cfg80211_pkt_pattern *p)
 {
 	int num_fields = 0, in_field = 0, fields_size = 0;
 	int i, pattern_len = 0;
@@ -1458,9 +1458,9 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
  * Allocates an RX filter returned through f
  * which needs to be freed using rx_filter_free()
  */
-static int wl1271_convert_wowlan_pattern_to_rx_filter(
-	struct cfg80211_wowlan_trig_pkt_pattern *p,
-	struct wl12xx_rx_filter **f)
+static int
+wl1271_convert_wowlan_pattern_to_rx_filter(struct cfg80211_pkt_pattern *p,
+					   struct wl12xx_rx_filter **f)
 {
 	int i, j, ret = 0;
 	struct wl12xx_rx_filter *filter;
@@ -1562,7 +1562,7 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,
 
 	/* Translate WoWLAN patterns into filters */
 	for (i = 0; i < wow->n_patterns; i++) {
-		struct cfg80211_wowlan_trig_pkt_pattern *p;
+		struct cfg80211_pkt_pattern *p;
 		struct wl12xx_rx_filter *filter = NULL;
 
 		p = &wow->patterns[i];
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 6bb7cf2..3f473d1 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -550,7 +550,8 @@ int __init of_flat_dt_match(unsigned long node, const char *const *compat)
  */
 void __init early_init_dt_check_for_initrd(unsigned long node)
 {
-	unsigned long start, end, len;
+	u64 start, end;
+	unsigned long len;
 	__be32 *prop;
 
 	pr_debug("Looking for initrd properties... ");
@@ -558,15 +559,16 @@ void __init early_init_dt_check_for_initrd(unsigned long node)
 	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
 	if (!prop)
 		return;
-	start = of_read_ulong(prop, len/4);
+	start = of_read_number(prop, len/4);
 
 	prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
 	if (!prop)
 		return;
-	end = of_read_ulong(prop, len/4);
+	end = of_read_number(prop, len/4);
 
 	early_init_dt_setup_initrd_arch(start, end);
-	pr_debug("initrd_start=0x%lx  initrd_end=0x%lx\n", start, end);
+	pr_debug("initrd_start=0x%llx  initrd_end=0x%llx\n",
+		 (unsigned long long)start, (unsigned long long)end);
 }
 #else
 inline void early_init_dt_check_for_initrd(unsigned long node)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index e0a6514..b0d1ff8 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -196,7 +196,7 @@ EXPORT_SYMBOL(of_device_alloc);
  * Returns pointer to created platform device, or NULL if a device was not
  * registered.  Unavailable devices will not get registered.
  */
-struct platform_device *of_platform_device_create_pdata(
+static struct platform_device *of_platform_device_create_pdata(
 					struct device_node *np,
 					const char *bus_id,
 					void *platform_data,
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 81944fb..b6a99f7 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -1,13 +1,9 @@
 #
 # PCI configuration
 #
-config ARCH_SUPPORTS_MSI
-	bool
-
 config PCI_MSI
 	bool "Message Signaled Interrupts (MSI and MSI-X)"
 	depends on PCI
-	depends on ARCH_SUPPORTS_MSI
 	help
 	   This allows device drivers to enable MSI (Message Signaled
 	   Interrupts).  Message Signaled Interrupts enable a device to
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 7bf3926..9b57792 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/mbus.h>
+#include <linux/msi.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
@@ -103,6 +104,7 @@ struct mvebu_pcie_port;
 struct mvebu_pcie {
 	struct platform_device *pdev;
 	struct mvebu_pcie_port *ports;
+	struct msi_chip *msi;
 	struct resource io;
 	struct resource realio;
 	struct resource mem;
@@ -119,6 +121,10 @@ struct mvebu_pcie_port {
 	u32 port;
 	u32 lane;
 	int devfn;
+	unsigned int mem_target;
+	unsigned int mem_attr;
+	unsigned int io_target;
+	unsigned int io_attr;
 	struct clk *clk;
 	struct mvebu_sw_pci_bridge bridge;
 	struct device_node *dn;
@@ -303,10 +309,9 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
 			    (port->bridge.iolimitupper << 16)) -
 			    iobase);
 
-	mvebu_mbus_add_window_remap_flags(port->name, port->iowin_base,
-					  port->iowin_size,
-					  iobase,
-					  MVEBU_MBUS_PCI_IO);
+	mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr,
+					  port->iowin_base, port->iowin_size,
+					  iobase);
 
 	pci_ioremap_io(iobase, port->iowin_base);
 }
@@ -338,10 +343,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
 		(((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
 		port->memwin_base;
 
-	mvebu_mbus_add_window_remap_flags(port->name, port->memwin_base,
-					  port->memwin_size,
-					  MVEBU_MBUS_NO_REMAP,
-					  MVEBU_MBUS_PCI_MEM);
+	mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr,
+				    port->memwin_base, port->memwin_size);
 }
 
 /*
@@ -636,6 +639,8 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 
 	for (i = 0; i < pcie->nports; i++) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		if (!port->base)
+			continue;
 		mvebu_pcie_setup_hw(port);
 	}
 
@@ -670,6 +675,12 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 	return bus;
 }
 
+void mvebu_pcie_add_bus(struct pci_bus *bus)
+{
+	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
+	bus->msi = pcie->msi;
+}
+
 resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 					  const struct resource *res,
 					  resource_size_t start,
@@ -706,6 +717,7 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
 	hw.map_irq        = mvebu_pcie_map_irq;
 	hw.ops            = &mvebu_pcie_ops;
 	hw.align_resource = mvebu_pcie_align_resource;
+	hw.add_bus        = mvebu_pcie_add_bus;
 
 	pci_common_init(&hw);
 }
@@ -730,12 +742,74 @@ mvebu_pcie_map_registers(struct platform_device *pdev,
 	return devm_request_and_ioremap(&pdev->dev, &regs);
 }
 
+#define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
+#define    DT_TYPE_IO                 0x1
+#define    DT_TYPE_MEM32              0x2
+#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF)
+#define DT_CPUADDR_TO_ATTR(cpuaddr)   (((cpuaddr) >> 48) & 0xFF)
+
+static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
+			      unsigned long type, int *tgt, int *attr)
+{
+	const int na = 3, ns = 2;
+	const __be32 *range;
+	int rlen, nranges, rangesz, pna, i;
+
+	range = of_get_property(np, "ranges", &rlen);
+	if (!range)
+		return -EINVAL;
+
+	pna = of_n_addr_cells(np);
+	rangesz = pna + na + ns;
+	nranges = rlen / sizeof(__be32) / rangesz;
+
+	for (i = 0; i < nranges; i++) {
+		u32 flags = of_read_number(range, 1);
+		u32 slot = of_read_number(range, 2);
+		u64 cpuaddr = of_read_number(range + na, pna);
+		unsigned long rtype;
+
+		if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO)
+			rtype = IORESOURCE_IO;
+		else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32)
+			rtype = IORESOURCE_MEM;
+
+		if (slot == PCI_SLOT(devfn) && type == rtype) {
+			*tgt = DT_CPUADDR_TO_TARGET(cpuaddr);
+			*attr = DT_CPUADDR_TO_ATTR(cpuaddr);
+			return 0;
+		}
+
+		range += rangesz;
+	}
+
+	return -ENOENT;
+}
+
+static void __init mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
+{
+	struct device_node *msi_node;
+	struct irq_domain *msi_domain;
+
+	msi_node = of_parse_phandle(pcie->pdev->dev.of_node,
+				    "msi-parent", 0);
+	if (!msi_node)
+		return;
+
+	msi_domain = irq_find_msi_host(msi_node);
+	if (!msi_domain)
+		return;
+
+	pcie->msi = msi_domain->msi_chip;
+
+	if (pcie->msi)
+		pcie->msi->dev = &pcie->pdev->dev;
+}
+
 static int __init mvebu_pcie_probe(struct platform_device *pdev)
 {
 	struct mvebu_pcie *pcie;
 	struct device_node *np = pdev->dev.of_node;
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
 	struct device_node *child;
 	int i, ret;
 
@@ -746,29 +820,25 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
 
 	pcie->pdev = pdev;
 
-	if (of_pci_range_parser_init(&parser, np))
+	/* Get the PCIe memory and I/O aperture */
+	mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
+	if (resource_size(&pcie->mem) == 0) {
+		dev_err(&pdev->dev, "invalid memory aperture size\n");
 		return -EINVAL;
+	}
 
-	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pcie->io);
-			of_pci_range_to_resource(&range, np, &pcie->realio);
-			pcie->io.name = "I/O";
-			pcie->realio.start = max_t(resource_size_t,
-						   PCIBIOS_MIN_IO,
-						   range.pci_addr);
-			pcie->realio.end = min_t(resource_size_t,
-						 IO_SPACE_LIMIT,
-						 range.pci_addr + range.size);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pcie->mem);
-			pcie->mem.name = "MEM";
-		}
+	mvebu_mbus_get_pcie_io_aperture(&pcie->io);
+	if (resource_size(&pcie->io) == 0) {
+		dev_err(&pdev->dev, "invalid I/O aperture size\n");
+		return -EINVAL;
 	}
 
+	pcie->realio.flags = pcie->io.flags;
+	pcie->realio.start = PCIBIOS_MIN_IO;
+	pcie->realio.end = min_t(resource_size_t,
+				  IO_SPACE_LIMIT,
+				  resource_size(&pcie->io));
+
 	/* Get the bus range */
 	ret = of_pci_parse_bus_range(np, &pcie->busn);
 	if (ret) {
@@ -816,6 +886,22 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
 		if (port->devfn < 0)
 			continue;
 
+		ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM,
+					 &port->mem_target, &port->mem_attr);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n",
+				port->port, port->lane);
+			continue;
+		}
+
+		ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
+					 &port->io_target, &port->io_attr);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n",
+				port->port, port->lane);
+			continue;
+		}
+
 		port->base = mvebu_pcie_map_registers(pdev, child, port);
 		if (!port->base) {
 			dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
@@ -854,6 +940,8 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
 		i++;
 	}
 
+	mvebu_pcie_msi_enable(pcie);
+
 	mvebu_pcie_enable(pcie);
 
 	return 0;
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 6fdd49c..f4e0289 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -49,6 +49,7 @@
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
+struct acpiphp_context;
 struct acpiphp_bridge;
 struct acpiphp_slot;
 
@@ -59,6 +60,7 @@ struct slot {
 	struct hotplug_slot	*hotplug_slot;
 	struct acpiphp_slot	*acpi_slot;
 	struct hotplug_slot_info info;
+	unsigned int sun;	/* ACPI _SUN (Slot User Number) value */
 };
 
 static inline const char *slot_name(struct slot *slot)
@@ -75,15 +77,11 @@ struct acpiphp_bridge {
 	struct list_head list;
 	struct list_head slots;
 	struct kref ref;
-	acpi_handle handle;
 
-	/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
-	struct acpiphp_func *func;
+	struct acpiphp_context *context;
 
 	int nr_slots;
 
-	u32 flags;
-
 	/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
 	struct pci_bus *pci_bus;
 
@@ -99,15 +97,13 @@ struct acpiphp_bridge {
  */
 struct acpiphp_slot {
 	struct list_head node;
-	struct acpiphp_bridge *bridge;	/* parent */
+	struct pci_bus *bus;
 	struct list_head funcs;		/* one slot may have different
 					   objects (i.e. for each function) */
 	struct slot *slot;
 	struct mutex crit_sect;
 
 	u8		device;		/* pci device# */
-
-	unsigned long long sun;		/* ACPI _SUN (slot unique number) */
 	u32		flags;		/* see below */
 };
 
@@ -119,16 +115,32 @@ struct acpiphp_slot {
  * typically 8 objects per slot (i.e. for each PCI function)
  */
 struct acpiphp_func {
-	struct acpiphp_slot *slot;	/* parent */
+	struct acpiphp_bridge *parent;
+	struct acpiphp_slot *slot;
 
 	struct list_head sibling;
-	struct notifier_block nb;
-	acpi_handle	handle;
 
 	u8		function;	/* pci function# */
 	u32		flags;		/* see below */
 };
 
+struct acpiphp_context {
+	acpi_handle handle;
+	struct acpiphp_func func;
+	struct acpiphp_bridge *bridge;
+	unsigned int refcount;
+};
+
+static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
+{
+	return container_of(func, struct acpiphp_context, func);
+}
+
+static inline acpi_handle func_to_handle(struct acpiphp_func *func)
+{
+	return func_to_context(func)->handle;
+}
+
 /*
  * struct acpiphp_attention_info - device specific attention registration
  *
@@ -142,45 +154,32 @@ struct acpiphp_attention_info
 	struct module *owner;
 };
 
-/* PCI bus bridge HID */
-#define ACPI_PCI_HOST_HID		"PNP0A03"
-
 /* ACPI _STA method value (ignore bit 4; battery present) */
 #define ACPI_STA_ALL			(0x0000000f)
 
-/* bridge flags */
-#define BRIDGE_HAS_EJ0		(0x00000001)
-
 /* slot flags */
 
-#define SLOT_POWEREDON		(0x00000001)
-#define SLOT_ENABLED		(0x00000002)
-#define SLOT_MULTIFUNCTION	(0x00000004)
+#define SLOT_ENABLED		(0x00000001)
 
 /* function flags */
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_PS0		(0x00000010)
-#define FUNC_HAS_PS1		(0x00000020)
-#define FUNC_HAS_PS2		(0x00000040)
-#define FUNC_HAS_PS3		(0x00000080)
-#define FUNC_HAS_DCK            (0x00000100)
+#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 
 /* acpiphp_core.c */
 int acpiphp_register_attention(struct acpiphp_attention_info*info);
 int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
-int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot, unsigned int sun);
 void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
 
 /* acpiphp_glue.c */
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 
 int acpiphp_enable_slot(struct acpiphp_slot *slot);
-int acpiphp_disable_slot(struct acpiphp_slot *slot);
-int acpiphp_eject_slot(struct acpiphp_slot *slot);
+int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
 u8 acpiphp_get_power_status(struct acpiphp_slot *slot);
 u8 acpiphp_get_attention_status(struct acpiphp_slot *slot);
 u8 acpiphp_get_latch_status(struct acpiphp_slot *slot);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index ca81279..bf2203e 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -155,15 +155,11 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
 	struct slot *slot = hotplug_slot->private;
-	int retval;
 
 	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
 	/* disable the specified slot */
-	retval = acpiphp_disable_slot(slot->acpi_slot);
-	if (!retval)
-		retval = acpiphp_eject_slot(slot->acpi_slot);
-	return retval;
+	return acpiphp_disable_and_eject_slot(slot->acpi_slot);
 }
 
 
@@ -290,7 +286,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 }
 
 /* callback routine to initialize 'struct slot' for each slot */
-int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,
+				  unsigned int sun)
 {
 	struct slot *slot;
 	int retval = -ENOMEM;
@@ -317,12 +314,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
 	slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
 
 	acpiphp_slot->slot = slot;
-	snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun);
+	slot->sun = sun;
+	snprintf(name, SLOT_NAME_SIZE, "%u", sun);
 
-	retval = pci_hp_register(slot->hotplug_slot,
-					acpiphp_slot->bridge->pci_bus,
-					acpiphp_slot->device,
-					name);
+	retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bus,
+				 acpiphp_slot->device, name);
 	if (retval == -EBUSY)
 		goto error_hpslot;
 	if (retval) {
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 59df857..05e463d 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -46,6 +46,7 @@
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/pci-acpi.h>
+#include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
@@ -55,28 +56,82 @@
 
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
+static DEFINE_MUTEX(acpiphp_context_lock);
 
 #define MY_NAME "acpiphp_glue"
 
-static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
+static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
-static void hotplug_event_func(acpi_handle handle, u32 type, void *context);
-static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
+static void hotplug_event(acpi_handle handle, u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
-/* callback routine to check for the existence of a pci dock device */
-static acpi_status
-is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
+static void acpiphp_context_handler(acpi_handle handle, void *context)
 {
-	int *count = (int *)context;
+	/* Intentionally empty. */
+}
 
-	if (is_dock_device(handle)) {
-		(*count)++;
-		return AE_CTRL_TERMINATE;
-	} else {
-		return AE_OK;
+/**
+ * acpiphp_init_context - Create hotplug context and grab a reference to it.
+ * @handle: ACPI object handle to create the context for.
+ *
+ * Call under acpiphp_context_lock.
+ */
+static struct acpiphp_context *acpiphp_init_context(acpi_handle handle)
+{
+	struct acpiphp_context *context;
+	acpi_status status;
+
+	context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (!context)
+		return NULL;
+
+	context->handle = handle;
+	context->refcount = 1;
+	status = acpi_attach_data(handle, acpiphp_context_handler, context);
+	if (ACPI_FAILURE(status)) {
+		kfree(context);
+		return NULL;
 	}
+	return context;
+}
+
+/**
+ * acpiphp_get_context - Get hotplug context and grab a reference to it.
+ * @handle: ACPI object handle to get the context for.
+ *
+ * Call under acpiphp_context_lock.
+ */
+static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+{
+	struct acpiphp_context *context = NULL;
+	acpi_status status;
+	void *data;
+
+	status = acpi_get_data(handle, acpiphp_context_handler, &data);
+	if (ACPI_SUCCESS(status)) {
+		context = data;
+		context->refcount++;
+	}
+	return context;
+}
+
+/**
+ * acpiphp_put_context - Drop a reference to ACPI hotplug context.
+ * @handle: ACPI object handle to put the context for.
+ *
+ * The context object is removed if there are no more references to it.
+ *
+ * Call under acpiphp_context_lock.
+ */
+static void acpiphp_put_context(struct acpiphp_context *context)
+{
+	if (--context->refcount)
+		return;
+
+	WARN_ON(context->bridge);
+	acpi_detach_data(context->handle, acpiphp_context_handler);
+	kfree(context);
 }
 
 static inline void get_bridge(struct acpiphp_bridge *bridge)
@@ -91,25 +146,36 @@ static inline void put_bridge(struct acpiphp_bridge *bridge)
 
 static void free_bridge(struct kref *kref)
 {
+	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge;
 	struct acpiphp_slot *slot, *next;
 	struct acpiphp_func *func, *tmp;
 
+	mutex_lock(&acpiphp_context_lock);
+
 	bridge = container_of(kref, struct acpiphp_bridge, ref);
 
 	list_for_each_entry_safe(slot, next, &bridge->slots, node) {
-		list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
-			kfree(func);
-		}
+		list_for_each_entry_safe(func, tmp, &slot->funcs, sibling)
+			acpiphp_put_context(func_to_context(func));
+
 		kfree(slot);
 	}
 
-	/* Release reference acquired by acpiphp_bridge_handle_to_function() */
-	if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)
-		put_bridge(bridge->func->slot->bridge);
+	context = bridge->context;
+	/* Root bridges will not have hotplug context. */
+	if (context) {
+		/* Release the reference taken by acpiphp_enumerate_slots(). */
+		put_bridge(context->func.parent);
+		context->bridge = NULL;
+		acpiphp_put_context(context);
+	}
+
 	put_device(&bridge->pci_bus->dev);
 	pci_dev_put(bridge->pci_dev);
 	kfree(bridge);
+
+	mutex_unlock(&acpiphp_context_lock);
 }
 
 /*
@@ -119,15 +185,14 @@ static void free_bridge(struct kref *kref)
  * TBD - figure out a way to only call fixups for
  * systems that require them.
  */
-static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
-	void *v)
+static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
 {
-	struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb);
-	struct pci_bus *bus = func->slot->bridge->pci_bus;
+	struct acpiphp_context *context = data;
+	struct pci_bus *bus = context->func.slot->bus;
 	u32 buses;
 
 	if (!bus->self)
-		return  NOTIFY_OK;
+		return;
 
 	/* fixup bad _DCK function that rewrites
 	 * secondary bridge on slot
@@ -143,12 +208,12 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
 			| ((unsigned int)(bus->busn_res.end) << 16);
 		pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
 	}
-	return NOTIFY_OK;
 }
 
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
-	.handler = hotplug_event_func,
+	.fixup = post_dock_fixups,
+	.handler = hotplug_event,
 };
 
 /* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -182,129 +247,117 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
 
 static void acpiphp_dock_init(void *data)
 {
-	struct acpiphp_func *func = data;
+	struct acpiphp_context *context = data;
 
-	get_bridge(func->slot->bridge);
+	get_bridge(context->func.parent);
 }
 
 static void acpiphp_dock_release(void *data)
 {
-	struct acpiphp_func *func = data;
+	struct acpiphp_context *context = data;
 
-	put_bridge(func->slot->bridge);
+	put_bridge(context->func.parent);
 }
 
 /* callback routine to register each ACPI PCI slot object */
-static acpi_status
-register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
+static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
+				 void **rv)
 {
-	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
+	struct acpiphp_bridge *bridge = data;
+	struct acpiphp_context *context;
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *newfunc;
-	acpi_handle tmp;
 	acpi_status status = AE_OK;
-	unsigned long long adr, sun;
-	int device, function, retval, found = 0;
+	unsigned long long adr;
+	int device, function;
 	struct pci_bus *pbus = bridge->pci_bus;
-	struct pci_dev *pdev;
+	struct pci_dev *pdev = bridge->pci_dev;
 	u32 val;
 
-	if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
+	if (pdev && device_is_managed_by_native_pciehp(pdev))
 		return AE_OK;
 
 	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
 	if (ACPI_FAILURE(status)) {
-		warn("can't evaluate _ADR (%#x)\n", status);
+		acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
 		return AE_OK;
 	}
 
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
-	pdev = bridge->pci_dev;
-	if (pdev && device_is_managed_by_native_pciehp(pdev))
-		return AE_OK;
-
-	newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
-	if (!newfunc)
-		return AE_NO_MEMORY;
-
-	newfunc->handle = handle;
+	mutex_lock(&acpiphp_context_lock);
+	context = acpiphp_init_context(handle);
+	if (!context) {
+		mutex_unlock(&acpiphp_context_lock);
+		acpi_handle_err(handle, "No hotplug context\n");
+		return AE_NOT_EXIST;
+	}
+	newfunc = &context->func;
 	newfunc->function = function;
+	newfunc->parent = bridge;
+	mutex_unlock(&acpiphp_context_lock);
 
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
+	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
 
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
+	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
-		newfunc->flags |= FUNC_HAS_PS0;
-
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
-		newfunc->flags |= FUNC_HAS_PS3;
-
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp)))
+	if (acpi_has_method(handle, "_DCK"))
 		newfunc->flags |= FUNC_HAS_DCK;
 
-	status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
-	if (ACPI_FAILURE(status)) {
-		/*
-		 * use the count of the number of slots we've found
-		 * for the number of the slot
-		 */
-		sun = bridge->nr_slots+1;
-	}
-
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
-		if (slot->device == device) {
-			if (slot->sun != sun)
-				warn("sibling found, but _SUN doesn't match!\n");
-			found = 1;
-			break;
-		}
+		if (slot->device == device)
+			goto slot_found;
 
-	if (!found) {
-		slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
-		if (!slot) {
-			kfree(newfunc);
-			return AE_NO_MEMORY;
-		}
+	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
+	if (!slot) {
+		status = AE_NO_MEMORY;
+		goto err;
+	}
 
-		slot->bridge = bridge;
-		slot->device = device;
-		slot->sun = sun;
-		INIT_LIST_HEAD(&slot->funcs);
-		mutex_init(&slot->crit_sect);
+	slot->bus = bridge->pci_bus;
+	slot->device = device;
+	INIT_LIST_HEAD(&slot->funcs);
+	mutex_init(&slot->crit_sect);
+
+	list_add_tail(&slot->node, &bridge->slots);
+
+	/* Register slots for ejectable funtions only. */
+	if (acpi_pci_check_ejectable(pbus, handle)  || is_dock_device(handle)) {
+		unsigned long long sun;
+		int retval;
 
-		mutex_lock(&bridge_mutex);
-		list_add_tail(&slot->node, &bridge->slots);
-		mutex_unlock(&bridge_mutex);
 		bridge->nr_slots++;
+		status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
+		if (ACPI_FAILURE(status))
+			sun = bridge->nr_slots;
 
 		dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
-		    slot->sun, pci_domain_nr(pbus), pbus->number, device);
-		retval = acpiphp_register_hotplug_slot(slot);
+		    sun, pci_domain_nr(pbus), pbus->number, device);
+
+		retval = acpiphp_register_hotplug_slot(slot, sun);
 		if (retval) {
+			bridge->nr_slots--;
 			if (retval == -EBUSY)
 				warn("Slot %llu already registered by another "
-					"hotplug driver\n", slot->sun);
+					"hotplug driver\n", sun);
 			else
 				warn("acpiphp_register_hotplug_slot failed "
 					"(err code = 0x%x)\n", retval);
-			goto err_exit;
 		}
+		/* Even if the slot registration fails, we can still use it. */
 	}
 
+ slot_found:
 	newfunc->slot = slot;
-	mutex_lock(&bridge_mutex);
 	list_add_tail(&newfunc->sibling, &slot->funcs);
-	mutex_unlock(&bridge_mutex);
 
 	if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function),
 				       &val, 60*1000))
-		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
+		slot->flags |= SLOT_ENABLED;
 
 	if (is_dock_device(handle)) {
 		/* we don't want to call this device's _EJ0
@@ -313,136 +366,46 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 		 */
 		newfunc->flags &= ~FUNC_HAS_EJ0;
 		if (register_hotplug_dock_device(handle,
-			&acpiphp_dock_ops, newfunc,
+			&acpiphp_dock_ops, context,
 			acpiphp_dock_init, acpiphp_dock_release))
 			dbg("failed to register dock device\n");
-
-		/* we need to be notified when dock events happen
-		 * outside of the hotplug operation, since we may
-		 * need to do fixups before we can hotplug.
-		 */
-		newfunc->nb.notifier_call = post_dock_fixups;
-		if (register_dock_notifier(&newfunc->nb))
-			dbg("failed to register a dock notifier");
 	}
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle,
-					     ACPI_SYSTEM_NOTIFY,
-					     handle_hotplug_event_func,
-					     newfunc);
-
+		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+						     handle_hotplug_event,
+						     context);
 		if (ACPI_FAILURE(status))
-			err("failed to register interrupt notify handler\n");
-	} else
-		status = AE_OK;
-
-	return status;
-
- err_exit:
-	bridge->nr_slots--;
-	mutex_lock(&bridge_mutex);
-	list_del(&slot->node);
-	mutex_unlock(&bridge_mutex);
-	kfree(slot);
-	kfree(newfunc);
-
-	return AE_OK;
-}
-
-
-/* see if it's worth looking at this bridge */
-static int detect_ejectable_slots(acpi_handle handle)
-{
-	int found = acpi_pci_detect_ejectable(handle);
-	if (!found) {
-		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-				    is_pci_dock_device, NULL, (void *)&found, NULL);
-	}
-	return found;
-}
-
-/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
-static void init_bridge_misc(struct acpiphp_bridge *bridge)
-{
-	acpi_status status;
-
-	/* must be added to the list prior to calling register_slot */
-	mutex_lock(&bridge_mutex);
-	list_add(&bridge->list, &bridge_list);
-	mutex_unlock(&bridge_mutex);
-
-	/* register all slot objects under this bridge */
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
-				     register_slot, NULL, bridge, NULL);
-	if (ACPI_FAILURE(status)) {
-		mutex_lock(&bridge_mutex);
-		list_del(&bridge->list);
-		mutex_unlock(&bridge_mutex);
-		return;
+			acpi_handle_err(handle,
+					"failed to install notify handler\n");
 	}
 
-	/* install notify handler for P2P bridges */
-	if (!pci_is_root_bus(bridge->pci_bus)) {
-		if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
-			status = acpi_remove_notify_handler(bridge->func->handle,
-						ACPI_SYSTEM_NOTIFY,
-						handle_hotplug_event_func);
-			if (ACPI_FAILURE(status))
-				err("failed to remove notify handler\n");
-		}
-		status = acpi_install_notify_handler(bridge->handle,
-					     ACPI_SYSTEM_NOTIFY,
-					     handle_hotplug_event_bridge,
-					     bridge);
-
-		if (ACPI_FAILURE(status)) {
-			err("failed to register interrupt notify handler\n");
-		}
-	}
-}
-
-
-/* find acpiphp_func from acpiphp_bridge */
-static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
-{
-	struct acpiphp_bridge *bridge;
-	struct acpiphp_slot *slot;
-	struct acpiphp_func *func = NULL;
-
-	mutex_lock(&bridge_mutex);
-	list_for_each_entry(bridge, &bridge_list, list) {
-		list_for_each_entry(slot, &bridge->slots, node) {
-			list_for_each_entry(func, &slot->funcs, sibling) {
-				if (func->handle == handle) {
-					get_bridge(func->slot->bridge);
-					mutex_unlock(&bridge_mutex);
-					return func;
-				}
-			}
-		}
-	}
-	mutex_unlock(&bridge_mutex);
+	return AE_OK;
 
-	return NULL;
+ err:
+	mutex_lock(&acpiphp_context_lock);
+	acpiphp_put_context(context);
+	mutex_unlock(&acpiphp_context_lock);
+	return status;
 }
 
-
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
-	struct acpiphp_bridge *bridge;
-
-	mutex_lock(&bridge_mutex);
-	list_for_each_entry(bridge, &bridge_list, list)
-		if (bridge->handle == handle) {
+	struct acpiphp_context *context;
+	struct acpiphp_bridge *bridge = NULL;
+
+	mutex_lock(&acpiphp_context_lock);
+	context = acpiphp_get_context(handle);
+	if (context) {
+		bridge = context->bridge;
+		if (bridge)
 			get_bridge(bridge);
-			mutex_unlock(&bridge_mutex);
-			return bridge;
-		}
-	mutex_unlock(&bridge_mutex);
 
-	return NULL;
+		acpiphp_put_context(context);
+	}
+	mutex_unlock(&acpiphp_context_lock);
+	return bridge;
 }
 
 static void cleanup_bridge(struct acpiphp_bridge *bridge)
@@ -450,35 +413,18 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
 	acpi_status status;
-	acpi_handle handle = bridge->handle;
-
-	if (!pci_is_root_bus(bridge->pci_bus)) {
-		status = acpi_remove_notify_handler(handle,
-					    ACPI_SYSTEM_NOTIFY,
-					    handle_hotplug_event_bridge);
-		if (ACPI_FAILURE(status))
-			err("failed to remove notify handler\n");
-	}
-
-	if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
-		status = acpi_install_notify_handler(bridge->func->handle,
-						ACPI_SYSTEM_NOTIFY,
-						handle_hotplug_event_func,
-						bridge->func);
-		if (ACPI_FAILURE(status))
-			err("failed to install interrupt notify handler\n");
-	}
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
-			if (is_dock_device(func->handle)) {
-				unregister_hotplug_dock_device(func->handle);
-				unregister_dock_notifier(&func->nb);
-			}
+			acpi_handle handle = func_to_handle(func);
+
+			if (is_dock_device(handle))
+				unregister_hotplug_dock_device(handle);
+
 			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(func->handle,
-						ACPI_SYSTEM_NOTIFY,
-						handle_hotplug_event_func);
+				status = acpi_remove_notify_handler(handle,
+							ACPI_SYSTEM_NOTIFY,
+							handle_hotplug_event);
 				if (ACPI_FAILURE(status))
 					err("failed to remove notify handler\n");
 			}
@@ -491,71 +437,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 	mutex_unlock(&bridge_mutex);
 }
 
-static int power_on_slot(struct acpiphp_slot *slot)
-{
-	acpi_status status;
-	struct acpiphp_func *func;
-	int retval = 0;
-
-	/* if already enabled, just skip */
-	if (slot->flags & SLOT_POWEREDON)
-		goto err_exit;
-
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		if (func->flags & FUNC_HAS_PS0) {
-			dbg("%s: executing _PS0\n", __func__);
-			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
-			if (ACPI_FAILURE(status)) {
-				warn("%s: _PS0 failed\n", __func__);
-				retval = -1;
-				goto err_exit;
-			} else
-				break;
-		}
-	}
-
-	/* TBD: evaluate _STA to check if the slot is enabled */
-
-	slot->flags |= SLOT_POWEREDON;
-
- err_exit:
-	return retval;
-}
-
-
-static int power_off_slot(struct acpiphp_slot *slot)
-{
-	acpi_status status;
-	struct acpiphp_func *func;
-
-	int retval = 0;
-
-	/* if already disabled, just skip */
-	if ((slot->flags & SLOT_POWEREDON) == 0)
-		goto err_exit;
-
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		if (func->flags & FUNC_HAS_PS3) {
-			status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
-			if (ACPI_FAILURE(status)) {
-				warn("%s: _PS3 failed\n", __func__);
-				retval = -1;
-				goto err_exit;
-			} else
-				break;
-		}
-	}
-
-	/* TBD: evaluate _STA to check if the slot is disabled */
-
-	slot->flags &= (~SLOT_POWEREDON);
-
- err_exit:
-	return retval;
-}
-
-
-
 /**
  * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
  * @bus: bus to start search with
@@ -583,52 +464,32 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
 	return max;
 }
 
-
 /**
- * acpiphp_bus_add - add a new bus to acpi subsystem
- * @func: acpiphp_func of the bridge
+ * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
+ * @handle: ACPI device object handle to start from.
  */
-static int acpiphp_bus_add(struct acpiphp_func *func)
+static void acpiphp_bus_trim(acpi_handle handle)
 {
-	struct acpi_device *device;
-	int ret_val;
-
-	if (!acpi_bus_get_device(func->handle, &device)) {
-		dbg("bus exists... trim\n");
-		/* this shouldn't be in here, so remove
-		 * the bus then re-add it...
-		 */
-		acpi_bus_trim(device);
-	}
-
-	ret_val = acpi_bus_scan(func->handle);
-	if (!ret_val)
-		ret_val = acpi_bus_get_device(func->handle, &device);
-
-	if (ret_val)
-		dbg("error adding bus, %x\n", -ret_val);
+	struct acpi_device *adev = NULL;
 
-	return ret_val;
+	acpi_bus_get_device(handle, &adev);
+	if (adev)
+		acpi_bus_trim(adev);
 }
 
-
 /**
- * acpiphp_bus_trim - trim a bus from acpi subsystem
- * @handle: handle to acpi namespace
+ * acpiphp_bus_add - Scan ACPI namespace subtree.
+ * @handle: ACPI object handle to start the scan from.
  */
-static int acpiphp_bus_trim(acpi_handle handle)
+static void acpiphp_bus_add(acpi_handle handle)
 {
-	struct acpi_device *device;
-	int retval;
-
-	retval = acpi_bus_get_device(handle, &device);
-	if (retval) {
-		dbg("acpi_device not found\n");
-		return retval;
-	}
+	struct acpi_device *adev = NULL;
 
-	acpi_bus_trim(device);
-	return 0;
+	acpiphp_bus_trim(handle);
+	acpi_bus_scan(handle);
+	acpi_bus_get_device(handle, &adev);
+	if (adev)
+		acpi_device_set_power(adev, ACPI_STATE_D0);
 }
 
 static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
@@ -645,7 +506,8 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
 		params[1].type = ACPI_TYPE_INTEGER;
 		params[1].integer.value = 1;
 		/* _REG is optional, we don't care about if there is failure */
-		acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL);
+		acpi_evaluate_object(func_to_handle(func), "_REG", &arg_list,
+				     NULL);
 	}
 }
 
@@ -653,59 +515,44 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
 {
 	struct acpiphp_func *func;
 
-	if (!dev->subordinate)
-		return;
-
 	/* quirk, or pcie could set it already */
 	if (dev->is_hotplug_bridge)
 		return;
 
-	if (PCI_SLOT(dev->devfn) != slot->device)
-		return;
-
 	list_for_each_entry(func, &slot->funcs, sibling) {
 		if (PCI_FUNC(dev->devfn) == func->function) {
-			/* check if this bridge has ejectable slots */
-			if ((detect_ejectable_slots(func->handle) > 0))
-				dev->is_hotplug_bridge = 1;
+			dev->is_hotplug_bridge = 1;
 			break;
 		}
 	}
 }
 
 /**
- * enable_device - enable, configure a slot
+ * enable_slot - enable, configure a slot
  * @slot: slot to be enabled
  *
  * This function should be called per *physical slot*,
  * not per each slot object in ACPI namespace.
  */
-static int __ref enable_device(struct acpiphp_slot *slot)
+static void __ref enable_slot(struct acpiphp_slot *slot)
 {
 	struct pci_dev *dev;
-	struct pci_bus *bus = slot->bridge->pci_bus;
+	struct pci_bus *bus = slot->bus;
 	struct acpiphp_func *func;
-	int num, max, pass;
+	int max, pass;
 	LIST_HEAD(add_list);
 
-	if (slot->flags & SLOT_ENABLED)
-		goto err_exit;
-
 	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_add(func);
+		acpiphp_bus_add(func_to_handle(func));
 
-	num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
-	if (num == 0) {
-		/* Maybe only part of funcs are added. */
-		dbg("No new device found\n");
-		goto err_exit;
-	}
+	pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
 
 	max = acpiphp_max_busnr(bus);
 	for (pass = 0; pass < 2; pass++) {
 		list_for_each_entry(dev, &bus->devices, bus_list) {
 			if (PCI_SLOT(dev->devfn) != slot->device)
 				continue;
+
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 				max = pci_scan_bridge(bus, dev, max, pass);
@@ -744,16 +591,12 @@ static int __ref enable_device(struct acpiphp_slot *slot)
 			continue;
 		}
 	}
-
-
- err_exit:
-	return 0;
 }
 
 /* return first device in slot, acquiring a reference on it */
 static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
 {
-	struct pci_bus *bus = slot->bridge->pci_bus;
+	struct pci_bus *bus = slot->bus;
 	struct pci_dev *dev;
 	struct pci_dev *ret = NULL;
 
@@ -769,16 +612,16 @@ static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
 }
 
 /**
- * disable_device - disable a slot
+ * disable_slot - disable a slot
  * @slot: ACPI PHP slot
  */
-static int disable_device(struct acpiphp_slot *slot)
+static void disable_slot(struct acpiphp_slot *slot)
 {
 	struct acpiphp_func *func;
 	struct pci_dev *pdev;
 
 	/*
-	 * enable_device() enumerates all functions in this device via
+	 * enable_slot() enumerates all functions in this device via
 	 * pci_scan_slot(), whether they have associated ACPI hotplug
 	 * methods (_EJ0, etc.) or not.  Therefore, we remove all functions
 	 * here.
@@ -788,13 +631,10 @@ static int disable_device(struct acpiphp_slot *slot)
 		pci_dev_put(pdev);
 	}
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		acpiphp_bus_trim(func->handle);
-	}
+	list_for_each_entry(func, &slot->funcs, sibling)
+		acpiphp_bus_trim(func_to_handle(func));
 
 	slot->flags &= (~SLOT_ENABLED);
-
-	return 0;
 }
 
 
@@ -812,18 +652,21 @@ static int disable_device(struct acpiphp_slot *slot)
  */
 static unsigned int get_slot_status(struct acpiphp_slot *slot)
 {
-	acpi_status status;
 	unsigned long long sta = 0;
-	u32 dvid;
 	struct acpiphp_func *func;
 
 	list_for_each_entry(func, &slot->funcs, sibling) {
 		if (func->flags & FUNC_HAS_STA) {
-			status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
+			acpi_status status;
+
+			status = acpi_evaluate_integer(func_to_handle(func),
+						       "_STA", NULL, &sta);
 			if (ACPI_SUCCESS(status) && sta)
 				break;
 		} else {
-			pci_bus_read_config_dword(slot->bridge->pci_bus,
+			u32 dvid;
+
+			pci_bus_read_config_dword(slot->bus,
 						  PCI_DEVFN(slot->device,
 							    func->function),
 						  PCI_VENDOR_ID, &dvid);
@@ -838,34 +681,42 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
 }
 
 /**
- * acpiphp_eject_slot - physically eject the slot
- * @slot: ACPI PHP slot
+ * trim_stale_devices - remove PCI devices that are not responding.
+ * @dev: PCI device to start walking the hierarchy from.
  */
-int acpiphp_eject_slot(struct acpiphp_slot *slot)
+static void trim_stale_devices(struct pci_dev *dev)
 {
-	acpi_status status;
-	struct acpiphp_func *func;
-	struct acpi_object_list arg_list;
-	union acpi_object arg;
+	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct pci_bus *bus = dev->subordinate;
+	bool alive = false;
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		/* We don't want to call _EJ0 on non-existing functions. */
-		if ((func->flags & FUNC_HAS_EJ0)) {
-			/* _EJ0 method take one argument */
-			arg_list.count = 1;
-			arg_list.pointer = &arg;
-			arg.type = ACPI_TYPE_INTEGER;
-			arg.integer.value = 1;
-
-			status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
-			if (ACPI_FAILURE(status)) {
-				warn("%s: _EJ0 failed\n", __func__);
-				return -1;
-			} else
-				break;
-		}
+	if (handle) {
+		acpi_status status;
+		unsigned long long sta;
+
+		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+		alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
+	}
+	if (!alive) {
+		u32 v;
+
+		/* Check if the device responds. */
+		alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0);
+	}
+	if (!alive) {
+		pci_stop_and_remove_bus_device(dev);
+		if (handle)
+			acpiphp_bus_trim(handle);
+	} else if (bus) {
+		struct pci_dev *child, *tmp;
+
+		/* The device is a bridge. so check the bus below it. */
+		pm_runtime_get_sync(&dev->dev);
+		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+			trim_stale_devices(child);
+
+		pm_runtime_put(&dev->dev);
 	}
-	return 0;
 }
 
 /**
@@ -875,43 +726,30 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
  * Iterate over all slots under this bridge and make sure that if a
  * card is present they are enabled, and if not they are disabled.
  */
-static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
+static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
 {
 	struct acpiphp_slot *slot;
-	int retval = 0;
-	int enabled, disabled;
-
-	enabled = disabled = 0;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
-		unsigned int status = get_slot_status(slot);
-		if (slot->flags & SLOT_ENABLED) {
-			if (status == ACPI_STA_ALL)
-				continue;
-			retval = acpiphp_disable_slot(slot);
-			if (retval) {
-				err("Error occurred in disabling\n");
-				goto err_exit;
-			} else {
-				acpiphp_eject_slot(slot);
-			}
-			disabled++;
+		struct pci_bus *bus = slot->bus;
+		struct pci_dev *dev, *tmp;
+
+		mutex_lock(&slot->crit_sect);
+		/* wake up all functions */
+		if (get_slot_status(slot) == ACPI_STA_ALL) {
+			/* remove stale devices if any */
+			list_for_each_entry_safe(dev, tmp, &bus->devices,
+						 bus_list)
+				if (PCI_SLOT(dev->devfn) == slot->device)
+					trim_stale_devices(dev);
+
+			/* configure all functions */
+			enable_slot(slot);
 		} else {
-			if (status != ACPI_STA_ALL)
-				continue;
-			retval = acpiphp_enable_slot(slot);
-			if (retval) {
-				err("Error occurred in enabling\n");
-				goto err_exit;
-			}
-			enabled++;
+			disable_slot(slot);
 		}
+		mutex_unlock(&slot->crit_sect);
 	}
-
-	dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled);
-
- err_exit:
-	return retval;
 }
 
 static void acpiphp_set_hpp_values(struct pci_bus *bus)
@@ -950,25 +788,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
  * ACPI event handlers
  */
 
-static acpi_status
-check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	struct acpiphp_bridge *bridge;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
-
-	bridge = acpiphp_handle_to_bridge(handle);
-	if (bridge) {
-		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-		dbg("%s: re-enumerating slots under %s\n",
-			__func__, objname);
-		acpiphp_check_bridge(bridge);
-		put_bridge(bridge);
-	}
-	return AE_OK ;
-}
-
 void acpiphp_check_host_bridge(acpi_handle handle)
 {
 	struct acpiphp_bridge *bridge;
@@ -978,27 +797,23 @@ void acpiphp_check_host_bridge(acpi_handle handle)
 		acpiphp_check_bridge(bridge);
 		put_bridge(bridge);
 	}
-
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-		ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
 }
 
-static void _handle_hotplug_event_bridge(struct work_struct *work)
+static void hotplug_event(acpi_handle handle, u32 type, void *data)
 {
+	struct acpiphp_context *context = data;
+	struct acpiphp_func *func = &context->func;
 	struct acpiphp_bridge *bridge;
 	char objname[64];
 	struct acpi_buffer buffer = { .length = sizeof(objname),
 				      .pointer = objname };
-	struct acpi_hp_work *hp_work;
-	acpi_handle handle;
-	u32 type;
 
-	hp_work = container_of(work, struct acpi_hp_work, work);
-	handle = hp_work->handle;
-	type = hp_work->type;
-	bridge = (struct acpiphp_bridge *)hp_work->context;
+	mutex_lock(&acpiphp_context_lock);
+	bridge = context->bridge;
+	if (bridge)
+		get_bridge(bridge);
 
-	acpi_scan_lock_acquire();
+	mutex_unlock(&acpiphp_context_lock);
 
 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
@@ -1007,188 +822,129 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
 		/* bus re-enumerate */
 		dbg("%s: Bus check notify on %s\n", __func__, objname);
 		dbg("%s: re-enumerating slots under %s\n", __func__, objname);
-		acpiphp_check_bridge(bridge);
-		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-			ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
+		if (bridge) {
+			acpiphp_check_bridge(bridge);
+		} else {
+			struct acpiphp_slot *slot = func->slot;
+
+			mutex_lock(&slot->crit_sect);
+			enable_slot(slot);
+			mutex_unlock(&slot->crit_sect);
+		}
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		/* device check */
 		dbg("%s: Device check notify on %s\n", __func__, objname);
-		acpiphp_check_bridge(bridge);
-		break;
+		if (bridge)
+			acpiphp_check_bridge(bridge);
+		else
+			acpiphp_check_bridge(func->parent);
 
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* wake event */
-		dbg("%s: Device wake notify on %s\n", __func__, objname);
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
 		dbg("%s: Device eject notify on %s\n", __func__, objname);
-		if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
-			struct acpiphp_slot *slot;
-			slot = bridge->func->slot;
-			if (!acpiphp_disable_slot(slot))
-				acpiphp_eject_slot(slot);
-		}
+		acpiphp_disable_and_eject_slot(func->slot);
 		break;
+	}
 
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		printk(KERN_ERR "Device %s cannot be configured due"
-				" to a frequency mismatch\n", objname);
-		break;
+	if (bridge)
+		put_bridge(bridge);
+}
 
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		printk(KERN_ERR "Device %s cannot be configured due"
-				" to a bus mode mismatch\n", objname);
-		break;
+static void hotplug_event_work(struct work_struct *work)
+{
+	struct acpiphp_context *context;
+	struct acpi_hp_work *hp_work;
 
-	case ACPI_NOTIFY_POWER_FAULT:
-		printk(KERN_ERR "Device %s has suffered a power fault\n",
-				objname);
-		break;
+	hp_work = container_of(work, struct acpi_hp_work, work);
+	context = hp_work->context;
+	acpi_scan_lock_acquire();
 
-	default:
-		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
-		break;
-	}
+	hotplug_event(hp_work->handle, hp_work->type, context);
 
 	acpi_scan_lock_release();
-	kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
-	put_bridge(bridge);
+	kfree(hp_work); /* allocated in handle_hotplug_event() */
+	put_bridge(context->func.parent);
 }
 
 /**
- * handle_hotplug_event_bridge - handle ACPI event on bridges
+ * handle_hotplug_event - handle ACPI hotplug event
  * @handle: Notify()'ed acpi_handle
  * @type: Notify code
- * @context: pointer to acpiphp_bridge structure
+ * @data: pointer to acpiphp_context structure
  *
- * Handles ACPI event notification on {host,p2p} bridges.
+ * Handles ACPI event notification on slots.
  */
-static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
-					void *context)
+static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 {
-	struct acpiphp_bridge *bridge = context;
-
-	/*
-	 * Currently the code adds all hotplug events to the kacpid_wq
-	 * queue when it should add hotplug events to the kacpi_hotplug_wq.
-	 * The proper way to fix this is to reorganize the code so that
-	 * drivers (dock, etc.) do not call acpi_os_execute(), etc.
-	 * For now just re-add this work to the kacpi_hotplug_wq so we
-	 * don't deadlock on hotplug actions.
-	 */
-	get_bridge(bridge);
-	alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
-}
-
-static void hotplug_event_func(acpi_handle handle, u32 type, void *context)
-{
-	struct acpiphp_func *func = context;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
-
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+	struct acpiphp_context *context;
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
-		/* bus re-enumerate */
-		dbg("%s: Bus check notify on %s\n", __func__, objname);
-		acpiphp_enable_slot(func->slot);
-		break;
-
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* device check : re-enumerate from parent bus */
-		dbg("%s: Device check notify on %s\n", __func__, objname);
-		acpiphp_check_bridge(func->slot->bridge);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* wake event */
-		dbg("%s: Device wake notify on %s\n", __func__, objname);
-		break;
-
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* request device eject */
-		dbg("%s: Device eject notify on %s\n", __func__, objname);
-		if (!(acpiphp_disable_slot(func->slot)))
-			acpiphp_eject_slot(func->slot);
 		break;
 
-	default:
-		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
-		break;
-	}
-}
-
-static void _handle_hotplug_event_func(struct work_struct *work)
-{
-	struct acpi_hp_work *hp_work;
-	struct acpiphp_func *func;
+	case ACPI_NOTIFY_DEVICE_WAKE:
+		return;
 
-	hp_work = container_of(work, struct acpi_hp_work, work);
-	func = hp_work->context;
-	acpi_scan_lock_acquire();
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		return;
 
-	hotplug_event_func(hp_work->handle, hp_work->type, func);
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		return;
 
-	acpi_scan_lock_release();
-	kfree(hp_work); /* allocated in handle_hotplug_event_func */
-	put_bridge(func->slot->bridge);
-}
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		return;
 
-/**
- * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @context: pointer to acpiphp_func structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event_func(acpi_handle handle, u32 type,
-				      void *context)
-{
-	struct acpiphp_func *func = context;
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		return;
+	}
 
-	/*
-	 * Currently the code adds all hotplug events to the kacpid_wq
-	 * queue when it should add hotplug events to the kacpi_hotplug_wq.
-	 * The proper way to fix this is to reorganize the code so that
-	 * drivers (dock, etc.) do not call acpi_os_execute(), etc.
-	 * For now just re-add this work to the kacpi_hotplug_wq so we
-	 * don't deadlock on hotplug actions.
-	 */
-	get_bridge(func->slot->bridge);
-	alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
+	mutex_lock(&acpiphp_context_lock);
+	context = acpiphp_get_context(handle);
+	if (context) {
+		get_bridge(context->func.parent);
+		acpiphp_put_context(context);
+		alloc_acpi_hp_work(handle, type, context, hotplug_event_work);
+	}
+	mutex_unlock(&acpiphp_context_lock);
 }
 
 /*
  * Create hotplug slots for the PCI bus.
  * It should always return 0 to avoid skipping following notifiers.
  */
-void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
+void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
-	acpi_handle dummy_handle;
 	struct acpiphp_bridge *bridge;
+	acpi_handle handle;
+	acpi_status status;
 
 	if (acpiphp_disabled)
 		return;
 
-	if (detect_ejectable_slots(handle) <= 0)
+	handle = ACPI_HANDLE(bus->bridge);
+	if (!handle)
 		return;
 
 	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
-	if (bridge == NULL) {
-		err("out of memory\n");
+	if (!bridge) {
+		acpi_handle_err(handle, "No memory for bridge object\n");
 		return;
 	}
 
 	INIT_LIST_HEAD(&bridge->slots);
 	kref_init(&bridge->ref);
-	bridge->handle = handle;
 	bridge->pci_dev = pci_dev_get(bus->self);
 	bridge->pci_bus = bus;
 
@@ -1199,31 +955,62 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
 	 */
 	get_device(&bus->dev);
 
-	if (!pci_is_root_bus(bridge->pci_bus) &&
-	    ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-					"_EJ0", &dummy_handle))) {
-		dbg("found ejectable p2p bridge\n");
-		bridge->flags |= BRIDGE_HAS_EJ0;
-		bridge->func = acpiphp_bridge_handle_to_function(handle);
+	if (!pci_is_root_bus(bridge->pci_bus)) {
+		struct acpiphp_context *context;
+
+		/*
+		 * This bridge should have been registered as a hotplug function
+		 * under its parent, so the context has to be there.  If not, we
+		 * are in deep goo.
+		 */
+		mutex_lock(&acpiphp_context_lock);
+		context = acpiphp_get_context(handle);
+		if (WARN_ON(!context)) {
+			mutex_unlock(&acpiphp_context_lock);
+			put_device(&bus->dev);
+			kfree(bridge);
+			return;
+		}
+		bridge->context = context;
+		context->bridge = bridge;
+		/* Get a reference to the parent bridge. */
+		get_bridge(context->func.parent);
+		mutex_unlock(&acpiphp_context_lock);
 	}
 
-	init_bridge_misc(bridge);
+	/* must be added to the list prior to calling register_slot */
+	mutex_lock(&bridge_mutex);
+	list_add(&bridge->list, &bridge_list);
+	mutex_unlock(&bridge_mutex);
+
+	/* register all slot objects under this bridge */
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				     register_slot, NULL, bridge, NULL);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_err(handle, "failed to register slots\n");
+		cleanup_bridge(bridge);
+		put_bridge(bridge);
+	}
 }
 
 /* Destroy hotplug slots associated with the PCI bus */
 void acpiphp_remove_slots(struct pci_bus *bus)
 {
-	struct acpiphp_bridge *bridge, *tmp;
+	struct acpiphp_bridge *bridge;
 
 	if (acpiphp_disabled)
 		return;
 
-	list_for_each_entry_safe(bridge, tmp, &bridge_list, list)
+	mutex_lock(&bridge_mutex);
+	list_for_each_entry(bridge, &bridge_list, list)
 		if (bridge->pci_bus == bus) {
+			mutex_unlock(&bridge_mutex);
 			cleanup_bridge(bridge);
 			put_bridge(bridge);
-			break;
+			return;
 		}
+
+	mutex_unlock(&bridge_mutex);
 }
 
 /**
@@ -1232,51 +1019,39 @@ void acpiphp_remove_slots(struct pci_bus *bus)
  */
 int acpiphp_enable_slot(struct acpiphp_slot *slot)
 {
-	int retval;
-
 	mutex_lock(&slot->crit_sect);
+	/* configure all functions */
+	if (!(slot->flags & SLOT_ENABLED))
+		enable_slot(slot);
 
-	/* wake up all functions */
-	retval = power_on_slot(slot);
-	if (retval)
-		goto err_exit;
-
-	if (get_slot_status(slot) == ACPI_STA_ALL) {
-		/* configure all functions */
-		retval = enable_device(slot);
-		if (retval)
-			power_off_slot(slot);
-	} else {
-		dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__);
-		power_off_slot(slot);
-	}
-
- err_exit:
 	mutex_unlock(&slot->crit_sect);
-	return retval;
+	return 0;
 }
 
 /**
- * acpiphp_disable_slot - power off slot
+ * acpiphp_disable_and_eject_slot - power off and eject slot
  * @slot: ACPI PHP slot
  */
-int acpiphp_disable_slot(struct acpiphp_slot *slot)
+int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
 {
+	struct acpiphp_func *func;
 	int retval = 0;
 
 	mutex_lock(&slot->crit_sect);
 
 	/* unconfigure all functions */
-	retval = disable_device(slot);
-	if (retval)
-		goto err_exit;
+	disable_slot(slot);
+
+	list_for_each_entry(func, &slot->funcs, sibling)
+		if (func->flags & FUNC_HAS_EJ0) {
+			acpi_handle handle = func_to_handle(func);
 
-	/* power off all functions */
-	retval = power_off_slot(slot);
-	if (retval)
-		goto err_exit;
+			if (ACPI_FAILURE(acpi_evaluate_ej0(handle)))
+				acpi_handle_err(handle, "_EJ0 failed\n");
+
+			break;
+		}
 
- err_exit:
 	mutex_unlock(&slot->crit_sect);
 	return retval;
 }
@@ -1288,7 +1063,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
 {
-	return (slot->flags & SLOT_POWEREDON);
+	return (slot->flags & SLOT_ENABLED);
 }
 
 
@@ -1298,11 +1073,7 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
 {
-	unsigned int sta;
-
-	sta = get_slot_status(slot);
-
-	return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1;
+	return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI);
 }
 
 
@@ -1312,9 +1083,5 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
 {
-	unsigned int sta;
-
-	sta = get_slot_status(slot);
-
-	return (sta == 0) ? 0 : 1;
+	return !!get_slot_status(slot);
 }
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index c35e8ad..2f5786c 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -66,7 +66,7 @@ do {							\
 #define IBM_HARDWARE_ID1 "IBM37D0"
 #define IBM_HARDWARE_ID2 "IBM37D4"
 
-#define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun)
+#define hpslot_to_sun(A) (((struct slot *)((A)->private))->sun)
 
 /* union apci_descriptor - allows access to the
  * various device descriptors that are embedded in the
@@ -270,7 +270,6 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
 
 	if (subevent == 0x80) {
 		dbg("%s: generationg bus event\n", __func__);
-		acpi_bus_generate_proc_event(note->device, note->event, detail);
 		acpi_bus_generate_netlink_event(note->device->pnp.device_class,
 						  dev_name(&note->device->dev),
 						  note->event, detail);
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index de8ffac..21a7182 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -286,7 +286,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 	    (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
 		return -EINVAL;
 
-	pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
 	pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset);
 	pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride);
 	if (!offset || (nr_virtfn > 1 && !stride))
@@ -324,7 +323,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 
 		if (!pdev->is_physfn) {
 			pci_dev_put(pdev);
-			return -ENODEV;
+			return -ENOSYS;
 		}
 
 		rc = sysfs_create_link(&dev->dev.kobj,
@@ -334,6 +333,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 			return rc;
 	}
 
+	pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
 	iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
 	pci_cfg_access_lock(dev);
 	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
@@ -368,6 +368,7 @@ failed:
 	iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
 	pci_cfg_access_lock(dev);
 	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
+	pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
 	ssleep(1);
 	pci_cfg_access_unlock(dev);
 
@@ -401,6 +402,7 @@ static void sriov_disable(struct pci_dev *dev)
 		sysfs_remove_link(&dev->dev.kobj, "dep_link");
 
 	iov->num_VFs = 0;
+	pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
 }
 
 static int sriov_init(struct pci_dev *dev, int pos)
@@ -662,7 +664,7 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 	might_sleep();
 
 	if (!dev->is_physfn)
-		return -ENODEV;
+		return -ENOSYS;
 
 	return sriov_enable(dev, nr_virtfn);
 }
@@ -722,7 +724,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf);
  * @dev: the PCI device
  *
  * Returns number of VFs belonging to this device that are assigned to a guest.
- * If device is not a physical function returns -ENODEV.
+ * If device is not a physical function returns 0.
  */
 int pci_vfs_assigned(struct pci_dev *dev)
 {
@@ -767,12 +769,15 @@ EXPORT_SYMBOL_GPL(pci_vfs_assigned);
  * device's mutex held.
  *
  * Returns 0 if PF is an SRIOV-capable device and
- * value of numvfs valid. If not a PF with VFS, return -EINVAL;
+ * value of numvfs valid. If not a PF return -ENOSYS;
+ * if numvfs is invalid return -EINVAL;
  * if VFs already enabled, return -EBUSY.
  */
 int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
 {
-	if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs))
+	if (!dev->is_physfn)
+		return -ENOSYS;
+	if (numvfs > dev->sriov->total_VFs)
 		return -EINVAL;
 
 	/* Shouldn't change if VFs already enabled */
@@ -786,17 +791,17 @@ int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
 EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
 
 /**
- * pci_sriov_get_totalvfs -- get total VFs supported on this devic3
+ * pci_sriov_get_totalvfs -- get total VFs supported on this device
  * @dev: the PCI PF device
  *
  * For a PCIe device with SRIOV support, return the PCIe
  * SRIOV capability value of TotalVFs or the value of driver_max_VFs
- * if the driver reduced it.  Otherwise, -EINVAL.
+ * if the driver reduced it.  Otherwise 0.
  */
 int pci_sriov_get_totalvfs(struct pci_dev *dev)
 {
 	if (!dev->is_physfn)
-		return -EINVAL;
+		return 0;
 
 	if (dev->sriov->driver_max_VFs)
 		return dev->sriov->driver_max_VFs;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index aca7578..2837285 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -30,20 +30,44 @@ static int pci_msi_enable = 1;
 
 /* Arch hooks */
 
-#ifndef arch_msi_check_device
-int arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
+	struct msi_chip *chip = dev->bus->msi;
+	int err;
+
+	if (!chip || !chip->setup_irq)
+		return -EINVAL;
+
+	err = chip->setup_irq(chip, dev, desc);
+	if (err < 0)
+		return err;
+
+	irq_set_chip_data(desc->irq, chip);
+
 	return 0;
 }
-#endif
 
-#ifndef arch_setup_msi_irqs
-# define arch_setup_msi_irqs default_setup_msi_irqs
-# define HAVE_DEFAULT_MSI_SETUP_IRQS
-#endif
+void __weak arch_teardown_msi_irq(unsigned int irq)
+{
+	struct msi_chip *chip = irq_get_chip_data(irq);
 
-#ifdef HAVE_DEFAULT_MSI_SETUP_IRQS
-int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+	if (!chip || !chip->teardown_irq)
+		return;
+
+	chip->teardown_irq(chip, irq);
+}
+
+int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	struct msi_chip *chip = dev->bus->msi;
+
+	if (!chip || !chip->check_device)
+		return 0;
+
+	return chip->check_device(chip, dev, nvec, type);
+}
+
+int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_desc *entry;
 	int ret;
@@ -65,14 +89,11 @@ int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 
 	return 0;
 }
-#endif
-
-#ifndef arch_teardown_msi_irqs
-# define arch_teardown_msi_irqs default_teardown_msi_irqs
-# define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
-#endif
 
-#ifdef HAVE_DEFAULT_MSI_TEARDOWN_IRQS
+/*
+ * We have a default implementation available as a separate non-weak
+ * function, as it is used by the Xen x86 PCI code
+ */
 void default_teardown_msi_irqs(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
@@ -89,14 +110,12 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
 			arch_teardown_msi_irq(entry->irq + i);
 	}
 }
-#endif
 
-#ifndef arch_restore_msi_irqs
-# define arch_restore_msi_irqs default_restore_msi_irqs
-# define HAVE_DEFAULT_MSI_RESTORE_IRQS
-#endif
+void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	return default_teardown_msi_irqs(dev);
+}
 
-#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
 void default_restore_msi_irqs(struct pci_dev *dev, int irq)
 {
 	struct msi_desc *entry;
@@ -114,7 +133,11 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
 	if (entry)
 		write_msi_msg(irq, &entry->msg);
 }
-#endif
+
+void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+	return default_restore_msi_irqs(dev, irq);
+}
 
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index dbdc5f7..7c29ee4 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -210,7 +210,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 	}
 
 	if (!error)
-		dev_info(&dev->dev, "power state changed by ACPI to %s\n",
+		dev_dbg(&dev->dev, "power state changed by ACPI to %s\n",
 			 acpi_power_state_string(state_conv[state]));
 
 	return error;
@@ -290,24 +290,16 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
 
 void acpi_pci_add_bus(struct pci_bus *bus)
 {
-	acpi_handle handle = NULL;
-
-	if (bus->bridge)
-		handle = ACPI_HANDLE(bus->bridge);
-	if (acpi_pci_disabled || handle == NULL)
+	if (acpi_pci_disabled || !bus->bridge)
 		return;
 
-	acpi_pci_slot_enumerate(bus, handle);
-	acpiphp_enumerate_slots(bus, handle);
+	acpi_pci_slot_enumerate(bus);
+	acpiphp_enumerate_slots(bus);
 }
 
 void acpi_pci_remove_bus(struct pci_bus *bus)
 {
-	/*
-	 * bus->bridge->acpi_node.handle has already been reset to NULL
-	 * when acpi_pci_remove_bus() is called, so don't check ACPI handle.
-	 */
-	if (acpi_pci_disabled)
+	if (acpi_pci_disabled || !bus->bridge)
 		return;
 
 	acpiphp_remove_slots(bus);
@@ -317,13 +309,20 @@ void acpi_pci_remove_bus(struct pci_bus *bus)
 /* ACPI bus type */
 static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 {
-	struct pci_dev * pci_dev;
-	u64	addr;
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	bool is_bridge;
+	u64 addr;
 
-	pci_dev = to_pci_dev(dev);
+	/*
+	 * pci_is_bridge() is not suitable here, because pci_dev->subordinate
+	 * is set only after acpi_pci_find_device() has been called for the
+	 * given device.
+	 */
+	is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE
+			|| pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS;
 	/* Please ref to ACPI spec for the syntax of _ADR */
 	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
-	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+	*handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge);
 	if (!*handle)
 		return -ENODEV;
 	return 0;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index c0dbe1f..7128cfd 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -131,19 +131,19 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
 	return ret;
 }
 
-static inline ssize_t pci_bus_show_cpumaskaffinity(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
+static ssize_t cpuaffinity_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
 }
+static DEVICE_ATTR_RO(cpuaffinity);
 
-static inline ssize_t pci_bus_show_cpulistaffinity(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
+static ssize_t cpulistaffinity_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
 {
 	return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
 }
+static DEVICE_ATTR_RO(cpulistaffinity);
 
 /* show resources */
 static ssize_t
@@ -379,6 +379,7 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
 	}
 	return count;
 }
+static DEVICE_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store);
 
 #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
 static ssize_t d3cold_allowed_store(struct device *dev,
@@ -514,11 +515,20 @@ struct device_attribute pci_dev_attrs[] = {
 	__ATTR_NULL,
 };
 
-struct device_attribute pcibus_dev_attrs[] = {
-	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
-	__ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL),
-	__ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL),
-	__ATTR_NULL,
+static struct attribute *pcibus_attrs[] = {
+	&dev_attr_rescan.attr,
+	&dev_attr_cpuaffinity.attr,
+	&dev_attr_cpulistaffinity.attr,
+	NULL,
+};
+
+static const struct attribute_group pcibus_group = {
+	.attrs = pcibus_attrs,
+};
+
+const struct attribute_group *pcibus_groups[] = {
+	&pcibus_group,
+	NULL,
 };
 
 static ssize_t
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e37fea6..726f167 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1992,7 +1992,7 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,
 }
 
 /**
- * pci_add_save_buffer - allocate buffer for saving given capability registers
+ * pci_add_cap_save_buffer - allocate buffer for saving given capability registers
  * @dev: the PCI device
  * @cap: the capability to allocate the buffer for
  * @size: requested size of the buffer
@@ -2359,6 +2359,27 @@ void pci_enable_acs(struct pci_dev *dev)
 	pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
 }
 
+static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
+{
+	int pos;
+	u16 cap, ctrl;
+
+	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
+	if (!pos)
+		return false;
+
+	/*
+	 * Except for egress control, capabilities are either required
+	 * or only required if controllable.  Features missing from the
+	 * capability field can therefore be assumed as hard-wired enabled.
+	 */
+	pci_read_config_word(pdev, pos + PCI_ACS_CAP, &cap);
+	acs_flags &= (cap | PCI_ACS_EC);
+
+	pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl);
+	return (ctrl & acs_flags) == acs_flags;
+}
+
 /**
  * pci_acs_enabled - test ACS against required flags for a given device
  * @pdev: device to test
@@ -2366,36 +2387,76 @@ void pci_enable_acs(struct pci_dev *dev)
  *
  * Return true if the device supports the provided flags.  Automatically
  * filters out flags that are not implemented on multifunction devices.
+ *
+ * Note that this interface checks the effective ACS capabilities of the
+ * device rather than the actual capabilities.  For instance, most single
+ * function endpoints are not required to support ACS because they have no
+ * opportunity for peer-to-peer access.  We therefore return 'true'
+ * regardless of whether the device exposes an ACS capability.  This makes
+ * it much easier for callers of this function to ignore the actual type
+ * or topology of the device when testing ACS support.
  */
 bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
 {
-	int pos, ret;
-	u16 ctrl;
+	int ret;
 
 	ret = pci_dev_specific_acs_enabled(pdev, acs_flags);
 	if (ret >= 0)
 		return ret > 0;
 
+	/*
+	 * Conventional PCI and PCI-X devices never support ACS, either
+	 * effectively or actually.  The shared bus topology implies that
+	 * any device on the bus can receive or snoop DMA.
+	 */
 	if (!pci_is_pcie(pdev))
 		return false;
 
-	/* Filter out flags not applicable to multifunction */
-	if (pdev->multifunction)
-		acs_flags &= (PCI_ACS_RR | PCI_ACS_CR |
-			      PCI_ACS_EC | PCI_ACS_DT);
-
-	if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM ||
-	    pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
-	    pdev->multifunction) {
-		pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
-		if (!pos)
-			return false;
+	switch (pci_pcie_type(pdev)) {
+	/*
+	 * PCI/X-to-PCIe bridges are not specifically mentioned by the spec,
+	 * but since their primary inteface is PCI/X, we conservatively
+	 * handle them as we would a non-PCIe device.
+	 */
+	case PCI_EXP_TYPE_PCIE_BRIDGE:
+	/*
+	 * PCIe 3.0, 6.12.1 excludes ACS on these devices.  "ACS is never
+	 * applicable... must never implement an ACS Extended Capability...".
+	 * This seems arbitrary, but we take a conservative interpretation
+	 * of this statement.
+	 */
+	case PCI_EXP_TYPE_PCI_BRIDGE:
+	case PCI_EXP_TYPE_RC_EC:
+		return false;
+	/*
+	 * PCIe 3.0, 6.12.1.1 specifies that downstream and root ports should
+	 * implement ACS in order to indicate their peer-to-peer capabilities,
+	 * regardless of whether they are single- or multi-function devices.
+	 */
+	case PCI_EXP_TYPE_DOWNSTREAM:
+	case PCI_EXP_TYPE_ROOT_PORT:
+		return pci_acs_flags_enabled(pdev, acs_flags);
+	/*
+	 * PCIe 3.0, 6.12.1.2 specifies ACS capabilities that should be
+	 * implemented by the remaining PCIe types to indicate peer-to-peer
+	 * capabilities, but only when they are part of a multifunciton
+	 * device.  The footnote for section 6.12 indicates the specific
+	 * PCIe types included here.
+	 */
+	case PCI_EXP_TYPE_ENDPOINT:
+	case PCI_EXP_TYPE_UPSTREAM:
+	case PCI_EXP_TYPE_LEG_END:
+	case PCI_EXP_TYPE_RC_END:
+		if (!pdev->multifunction)
+			break;
 
-		pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl);
-		if ((ctrl & acs_flags) != acs_flags)
-			return false;
+		return pci_acs_flags_enabled(pdev, acs_flags);
 	}
 
+	/*
+	 * PCIe 3.0, 6.12.1.3 specifies no ACS capabilties are applicable
+	 * to single function devices with the exception of downstream ports.
+	 */
 	return true;
 }
 
@@ -3579,6 +3640,49 @@ int pcie_set_mps(struct pci_dev *dev, int mps)
 }
 
 /**
+ * pcie_get_minimum_link - determine minimum link settings of a PCI device
+ * @dev: PCI device to query
+ * @speed: storage for minimum speed
+ * @width: storage for minimum width
+ *
+ * This function will walk up the PCI device chain and determine the minimum
+ * link width and speed of the device.
+ */
+int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
+			  enum pcie_link_width *width)
+{
+	int ret;
+
+	*speed = PCI_SPEED_UNKNOWN;
+	*width = PCIE_LNK_WIDTH_UNKNOWN;
+
+	while (dev) {
+		u16 lnksta;
+		enum pci_bus_speed next_speed;
+		enum pcie_link_width next_width;
+
+		ret = pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
+		if (ret)
+			return ret;
+
+		next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS];
+		next_width = (lnksta & PCI_EXP_LNKSTA_NLW) >>
+			PCI_EXP_LNKSTA_NLW_SHIFT;
+
+		if (next_speed < *speed)
+			*speed = next_speed;
+
+		if (next_width < *width)
+			*width = next_width;
+
+		dev = dev->bus->self;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(pcie_get_minimum_link);
+
+/**
  * pci_select_bars - Make BAR mask from the type of resource
  * @dev: the PCI device for which BAR mask is made
  * @flags: resource type mask to be selected
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d1182c4..8a00c06 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -6,6 +6,9 @@
 #define PCI_CFG_SPACE_SIZE	256
 #define PCI_CFG_SPACE_EXP_SIZE	4096
 
+extern const unsigned char pcix_bus_speed[];
+extern const unsigned char pcie_link_speed[];
+
 /* Functions internal to the PCI core code */
 
 int pci_create_sysfs_dev_files(struct pci_dev *pdev);
@@ -151,7 +154,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
 
 }
 extern struct device_attribute pci_dev_attrs[];
-extern struct device_attribute pcibus_dev_attrs[];
+extern const struct attribute_group *pcibus_groups[];
 extern struct device_type pci_dev_type;
 extern struct bus_attribute pci_bus_attrs[];
 
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 3b94cfc..7958e59 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -2,7 +2,7 @@
 # PCI Express Port Bus Configuration
 #
 config PCIEPORTBUS
-	bool "PCI Express support"
+	bool "PCI Express Port Bus support"
 	depends on PCI
 	help
 	  This automatically enables PCI Express Port Bus support. Users can
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 46ada5c..ead4e29 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -96,7 +96,7 @@ static void release_pcibus_dev(struct device *dev)
 static struct class pcibus_class = {
 	.name		= "pci_bus",
 	.dev_release	= &release_pcibus_dev,
-	.dev_attrs	= pcibus_dev_attrs,
+	.dev_groups	= pcibus_groups,
 };
 
 static int __init pcibus_class_init(void)
@@ -513,7 +513,7 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
 	return bridge;
 }
 
-static unsigned char pcix_bus_speed[] = {
+const unsigned char pcix_bus_speed[] = {
 	PCI_SPEED_UNKNOWN,		/* 0 */
 	PCI_SPEED_66MHz_PCIX,		/* 1 */
 	PCI_SPEED_100MHz_PCIX,		/* 2 */
@@ -532,7 +532,7 @@ static unsigned char pcix_bus_speed[] = {
 	PCI_SPEED_133MHz_PCIX_533	/* F */
 };
 
-static unsigned char pcie_link_speed[] = {
+const unsigned char pcie_link_speed[] = {
 	PCI_SPEED_UNKNOWN,		/* 0 */
 	PCIE_SPEED_2_5GT,		/* 1 */
 	PCIE_SPEED_5_0GT,		/* 2 */
@@ -666,6 +666,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 
 	child->parent = parent;
 	child->ops = parent->ops;
+	child->msi = parent->msi;
 	child->sysdata = parent->sysdata;
 	child->bus_flags = parent->bus_flags;
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e85d230..2e2ea22 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3295,11 +3295,61 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
 	return pci_dev_get(dev);
 }
 
+/*
+ * AMD has indicated that the devices below do not support peer-to-peer
+ * in any system where they are found in the southbridge with an AMD
+ * IOMMU in the system.  Multifunction devices that do not support
+ * peer-to-peer between functions can claim to support a subset of ACS.
+ * Such devices effectively enable request redirect (RR) and completion
+ * redirect (CR) since all transactions are redirected to the upstream
+ * root complex.
+ *
+ * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94086
+ * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94102
+ * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/99402
+ *
+ * 1002:4385 SBx00 SMBus Controller
+ * 1002:439c SB7x0/SB8x0/SB9x0 IDE Controller
+ * 1002:4383 SBx00 Azalia (Intel HDA)
+ * 1002:439d SB7x0/SB8x0/SB9x0 LPC host controller
+ * 1002:4384 SBx00 PCI to PCI Bridge
+ * 1002:4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
+ */
+static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
+{
+#ifdef CONFIG_ACPI
+	struct acpi_table_header *header = NULL;
+	acpi_status status;
+
+	/* Targeting multifunction devices on the SB (appears on root bus) */
+	if (!dev->multifunction || !pci_is_root_bus(dev->bus))
+		return -ENODEV;
+
+	/* The IVRS table describes the AMD IOMMU */
+	status = acpi_get_table("IVRS", 0, &header);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	/* Filter out flags not applicable to multifunction */
+	acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT);
+
+	return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1;
+#else
+	return -ENODEV;
+#endif
+}
+
 static const struct pci_dev_acs_enabled {
 	u16 vendor;
 	u16 device;
 	int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags);
 } pci_dev_acs_enabled[] = {
+	{ PCI_VENDOR_ID_ATI, 0x4385, pci_quirk_amd_sb_acs },
+	{ PCI_VENDOR_ID_ATI, 0x439c, pci_quirk_amd_sb_acs },
+	{ PCI_VENDOR_ID_ATI, 0x4383, pci_quirk_amd_sb_acs },
+	{ PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
+	{ PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
+	{ PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
 	{ 0 }
 };
 
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 64a7de2..fc1aebd 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -814,14 +814,14 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 {
 	struct pci_dev *dev;
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
-	unsigned long size = 0, size0 = 0, size1 = 0;
+	resource_size_t size = 0, size0 = 0, size1 = 0;
 	resource_size_t children_add_size = 0;
-	resource_size_t min_align, io_align, align;
+	resource_size_t min_align, align;
 
 	if (!b_res)
  		return;
 
-	io_align = min_align = window_alignment(bus, IORESOURCE_IO);
+	min_align = window_alignment(bus, IORESOURCE_IO);
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		int i;
 
@@ -848,9 +848,6 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 		}
 	}
 
-	if (min_align > io_align)
-		min_align = io_align;
-
 	size0 = calculate_iosize(size, min_size, size1,
 			resource_size(b_res), min_align);
 	if (children_add_size > add_size)
@@ -874,8 +871,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 		add_to_list(realloc_head, bus->self, b_res, size1-size0,
 			    min_align);
 		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
-				 "%pR to %pR add_size %lx\n", b_res,
-				 &bus->busn_res, size1-size0);
+				 "%pR to %pR add_size %llx\n", b_res,
+				 &bus->busn_res,
+				 (unsigned long long)size1-size0);
 	}
 }
 
@@ -905,6 +903,8 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
  * pbus_size_mem() - size the memory window of a given bus
  *
  * @bus : the bus
+ * @mask: mask the resource flag, then compare it with type
+ * @type: the type of free resource from bridge
  * @min_size : the minimum memory window that must to be allocated
  * @add_size : additional optional memory window
  * @realloc_head : track the additional memory window on this list
@@ -1367,15 +1367,12 @@ static void pci_bus_dump_resources(struct pci_bus *bus)
 static int __init pci_bus_get_depth(struct pci_bus *bus)
 {
 	int depth = 0;
-	struct pci_dev *dev;
+	struct pci_bus *child_bus;
 
-	list_for_each_entry(dev, &bus->devices, bus_list) {
+	list_for_each_entry(child_bus, &bus->children, node){
 		int ret;
-		struct pci_bus *b = dev->subordinate;
-		if (!b)
-			continue;
 
-		ret = pci_bus_get_depth(b);
+		ret = pci_bus_get_depth(child_bus);
 		if (ret + 1 > depth)
 			depth = ret + 1;
 	}
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index a4c16ee..622dd6f 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -777,15 +777,4 @@ static struct pci_driver pd6729_pci_driver = {
 	.remove		= pd6729_pci_remove,
 };
 
-static int pd6729_module_init(void)
-{
-	return pci_register_driver(&pd6729_pci_driver);
-}
-
-static void pd6729_module_exit(void)
-{
-	pci_unregister_driver(&pd6729_pci_driver);
-}
-
-module_init(pd6729_module_init);
-module_exit(pd6729_module_exit);
+module_pci_driver(pd6729_pci_driver);
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 6b4ff09..dc18a3a 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1439,20 +1439,6 @@ static struct pci_driver yenta_cardbus_driver = {
 	.driver.pm	= YENTA_PM_OPS,
 };
 
-
-static int __init yenta_socket_init(void)
-{
-	return pci_register_driver(&yenta_cardbus_driver);
-}
-
-
-static void __exit yenta_socket_exit(void)
-{
-	pci_unregister_driver(&yenta_cardbus_driver);
-}
-
-
-module_init(yenta_socket_init);
-module_exit(yenta_socket_exit);
+module_pci_driver(yenta_cardbus_driver);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 5a8ad51..bc830af 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -61,7 +61,7 @@ config PINCTRL_AT91
 config PINCTRL_BAYTRAIL
 	bool "Intel Baytrail GPIO pin control"
 	depends on GPIOLIB && ACPI && X86
-        select IRQ_DOMAIN
+	select IRQ_DOMAIN
 	help
 	  driver for memory mapped GPIO functionality on Intel Baytrail
 	  platforms. Supports 3 banks with 102, 28 and 44 gpios.
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 2a00239..c8fcedb 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1228,23 +1228,36 @@ EXPORT_SYMBOL_GPL(pinctrl_force_default);
 #ifdef CONFIG_PM
 
 /**
- * pinctrl_pm_select_default_state() - select default pinctrl state for PM
+ * pinctrl_pm_select_state() - select pinctrl state for PM
  * @dev: device to select default state for
+ * @state: state to set
  */
-int pinctrl_pm_select_default_state(struct device *dev)
+static int pinctrl_pm_select_state(struct device *dev,
+				   struct pinctrl_state *state)
 {
 	struct dev_pin_info *pins = dev->pins;
 	int ret;
 
-	if (!pins)
-		return 0;
-	if (IS_ERR(pins->default_state))
-		return 0; /* No default state */
-	ret = pinctrl_select_state(pins->p, pins->default_state);
+	if (IS_ERR(state))
+		return 0; /* No such state */
+	ret = pinctrl_select_state(pins->p, state);
 	if (ret)
-		dev_err(dev, "failed to activate default pinctrl state\n");
+		dev_err(dev, "failed to activate pinctrl state %s\n",
+			state->name);
 	return ret;
 }
+
+/**
+ * pinctrl_pm_select_default_state() - select default pinctrl state for PM
+ * @dev: device to select default state for
+ */
+int pinctrl_pm_select_default_state(struct device *dev)
+{
+	if (!dev->pins)
+		return 0;
+
+	return pinctrl_pm_select_state(dev, dev->pins->default_state);
+}
 EXPORT_SYMBOL_GPL(pinctrl_pm_select_default_state);
 
 /**
@@ -1253,17 +1266,10 @@ EXPORT_SYMBOL_GPL(pinctrl_pm_select_default_state);
  */
 int pinctrl_pm_select_sleep_state(struct device *dev)
 {
-	struct dev_pin_info *pins = dev->pins;
-	int ret;
-
-	if (!pins)
+	if (!dev->pins)
 		return 0;
-	if (IS_ERR(pins->sleep_state))
-		return 0; /* No sleep state */
-	ret = pinctrl_select_state(pins->p, pins->sleep_state);
-	if (ret)
-		dev_err(dev, "failed to activate pinctrl sleep state\n");
-	return ret;
+
+	return pinctrl_pm_select_state(dev, dev->pins->sleep_state);
 }
 EXPORT_SYMBOL_GPL(pinctrl_pm_select_sleep_state);
 
@@ -1273,17 +1279,10 @@ EXPORT_SYMBOL_GPL(pinctrl_pm_select_sleep_state);
  */
 int pinctrl_pm_select_idle_state(struct device *dev)
 {
-	struct dev_pin_info *pins = dev->pins;
-	int ret;
-
-	if (!pins)
+	if (!dev->pins)
 		return 0;
-	if (IS_ERR(pins->idle_state))
-		return 0; /* No idle state */
-	ret = pinctrl_select_state(pins->p, pins->idle_state);
-	if (ret)
-		dev_err(dev, "failed to activate pinctrl idle state\n");
-	return ret;
+
+	return pinctrl_pm_select_state(dev, dev->pins->idle_state);
 }
 EXPORT_SYMBOL_GPL(pinctrl_pm_select_idle_state);
 #endif
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index 048ae80..29f7e4f 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -785,7 +785,7 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
 	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "Unable to get pdma clock");
-		return PTR_RET(clk);
+		return PTR_ERR(clk);
 	}
 	clk_prepare_enable(clk);
 
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index e875f21..8da2d6d 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -428,12 +428,11 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
 {
 	struct pinctrl_maps *maps_node;
 	const struct pinctrl_map *map;
-	struct pinctrl_dev *pctldev = NULL;
+	const struct pinctrl_map *found = NULL;
+	struct pinctrl_dev *pctldev;
 	const struct pinconf_ops *confops = NULL;
-	const struct pinctrl_map_configs *configs;
 	struct dbg_cfg *dbg = &pinconf_dbg_conf;
 	int i, j;
-	bool found = false;
 	unsigned long config;
 
 	mutex_lock(&pinctrl_maps_mutex);
@@ -450,14 +449,8 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
 		for (j = 0; j < map->data.configs.num_configs; j++) {
 			if (!strcmp(map->data.configs.group_or_pin,
 					dbg->pin_name)) {
-				/*
-				 * We found the right pin / state, read the
-				 * config and he pctldev for later use
-				 */
-				configs = &map->data.configs;
-				pctldev = get_pinctrl_dev_from_devname
-					(map->ctrl_dev_name);
-				found = true;
+				/* We found the right pin / state */
+				found = map;
 				break;
 			}
 		}
@@ -473,7 +466,8 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
 		goto exit;
 	}
 
-	config = *(configs->configs);
+	pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
+	config = *found->data.configs.configs;
 	seq_printf(s, "Dev %s has config of %s in state %s: 0x%08lX\n",
 			dbg->dev_name, dbg->pin_name,
 			dbg->state_name, config);
@@ -505,12 +499,12 @@ static int pinconf_dbg_config_write(struct file *file,
 {
 	struct pinctrl_maps *maps_node;
 	const struct pinctrl_map *map;
-	struct pinctrl_dev *pctldev = NULL;
+	const struct pinctrl_map *found = NULL;
+	struct pinctrl_dev *pctldev;
 	const struct pinconf_ops *confops = NULL;
 	struct dbg_cfg *dbg = &pinconf_dbg_conf;
 	const struct pinctrl_map_configs *configs;
 	char config[MAX_NAME_LEN+1];
-	bool found = false;
 	char buf[128];
 	char *b = &buf[0];
 	int buf_size;
@@ -518,7 +512,7 @@ static int pinconf_dbg_config_write(struct file *file,
 	int i;
 
 	/* Get userspace string and assure termination */
-	buf_size = min(count, (sizeof(buf)-1));
+	buf_size = min(count, (size_t)(sizeof(buf)-1));
 	if (copy_from_user(buf, user_buf, buf_size))
 		return -EFAULT;
 	buf[buf_size] = 0;
@@ -588,10 +582,7 @@ static int pinconf_dbg_config_write(struct file *file,
 
 		/*  we found the right pin / state, so overwrite config */
 		if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
-			found = true;
-			pctldev = get_pinctrl_dev_from_devname(
-					map->ctrl_dev_name);
-			configs = &map->data.configs;
+			found = map;
 			break;
 		}
 	}
@@ -601,10 +592,12 @@ static int pinconf_dbg_config_write(struct file *file,
 		goto exit;
 	}
 
+	pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
 	if (pctldev)
 		confops = pctldev->desc->confops;
 
 	if (confops && confops->pin_config_dbg_parse_modify) {
+		configs = &found->data.configs;
 		for (i = 0; i < configs->num_configs; i++) {
 			confops->pin_config_dbg_parse_modify(pctldev,
 						     config,
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index b90a3a0..7cce066 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1241,18 +1241,22 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
+		irq_set_handler(d->irq, handle_simple_irq);
 		writel_relaxed(mask, pio + PIO_ESR);
 		writel_relaxed(mask, pio + PIO_REHLSR);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
+		irq_set_handler(d->irq, handle_simple_irq);
 		writel_relaxed(mask, pio + PIO_ESR);
 		writel_relaxed(mask, pio + PIO_FELLSR);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
+		irq_set_handler(d->irq, handle_level_irq);
 		writel_relaxed(mask, pio + PIO_LSR);
 		writel_relaxed(mask, pio + PIO_FELLSR);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
+		irq_set_handler(d->irq, handle_level_irq);
 		writel_relaxed(mask, pio + PIO_LSR);
 		writel_relaxed(mask, pio + PIO_REHLSR);
 		break;
@@ -1261,6 +1265,7 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
 		 * disable additional interrupt modes:
 		 * fall back to default behavior
 		 */
+		irq_set_handler(d->irq, handle_simple_irq);
 		writel_relaxed(mask, pio + PIO_AIMDR);
 		return 0;
 	case IRQ_TYPE_NONE:
@@ -1402,6 +1407,8 @@ static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
 							irq_hw_number_t hw)
 {
 	struct at91_gpio_chip	*at91_gpio = h->host_data;
+	void __iomem		*pio = at91_gpio->regbase;
+	u32			mask = 1 << hw;
 
 	irq_set_lockdep_class(virq, &gpio_lock_class);
 
@@ -1409,8 +1416,13 @@ static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
 	 * Can use the "simple" and not "edge" handler since it's
 	 * shorter, and the AIC handles interrupts sanely.
 	 */
-	irq_set_chip_and_handler(virq, &gpio_irqchip,
-				 handle_simple_irq);
+	irq_set_chip(virq, &gpio_irqchip);
+	if ((at91_gpio->ops == &at91sam9x5_ops) &&
+	    (readl_relaxed(pio + PIO_AIMMR) & mask) &&
+	    (readl_relaxed(pio + PIO_ELSR) & mask))
+		irq_set_handler(virq, handle_level_irq);
+	else
+		irq_set_handler(virq, handle_simple_irq);
 	set_irq_flags(virq, IRQF_VALID);
 	irq_set_chip_data(virq, at91_gpio);
 
diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
index e9d735d..2832576 100644
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -130,25 +130,25 @@ struct byt_gpio {
 	struct pinctrl_gpio_range	*range;
 };
 
+#define to_byt_gpio(c)	container_of(c, struct byt_gpio, chip)
+
 static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
 				 int reg)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	u32 reg_offset;
-	void __iomem *ptr;
 
 	if (reg == BYT_INT_STAT_REG)
 		reg_offset = (offset / 32) * 4;
 	else
 		reg_offset = vg->range->pins[offset] * 16;
 
-	ptr = (void __iomem *) (vg->reg_base + reg_offset + reg);
-	return ptr;
+	return vg->reg_base + reg_offset + reg;
 }
 
 static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 
 	pm_runtime_get(&vg->pdev->dev);
 
@@ -157,7 +157,7 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 
 static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
 	u32 value;
 
@@ -218,7 +218,7 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
 
 static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
 	unsigned long flags;
 	u32 old_val;
@@ -237,7 +237,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
 	unsigned long flags;
 	u32 value;
@@ -245,7 +245,7 @@ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	spin_lock_irqsave(&vg->lock, flags);
 
 	value = readl(reg) | BYT_DIR_MASK;
-	value = value & (~BYT_INPUT_EN); /* active low */
+	value &= ~BYT_INPUT_EN;		/* active low */
 	writel(value, reg);
 
 	spin_unlock_irqrestore(&vg->lock, flags);
@@ -256,16 +256,20 @@ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 static int byt_gpio_direction_output(struct gpio_chip *chip,
 				     unsigned gpio, int value)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
 	unsigned long flags;
 	u32 reg_val;
 
 	spin_lock_irqsave(&vg->lock, flags);
 
-	reg_val = readl(reg) | (BYT_DIR_MASK | !!value);
-	reg_val &= ~(BYT_OUTPUT_EN | !value);
-	writel(reg_val, reg);
+	reg_val = readl(reg) | BYT_DIR_MASK;
+	reg_val &= ~BYT_OUTPUT_EN;
+
+	if (value)
+		writel(reg_val | BYT_LEVEL, reg);
+	else
+		writel(reg_val & ~BYT_LEVEL, reg);
 
 	spin_unlock_irqrestore(&vg->lock, flags);
 
@@ -274,7 +278,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
 
 static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	int i;
 	unsigned long flags;
 	u32 conf0, val, offs;
@@ -294,16 +298,16 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 			   val & BYT_LEVEL ? "hi" : "lo",
 			   vg->range->pins[i], offs,
 			   conf0 & 0x7,
-			   conf0 & BYT_TRIG_NEG ? "fall " : "",
-			   conf0 & BYT_TRIG_POS ? "rise " : "",
-			   conf0 & BYT_TRIG_LVL ? "lvl " : "");
+			   conf0 & BYT_TRIG_NEG ? " fall" : "",
+			   conf0 & BYT_TRIG_POS ? " rise" : "",
+			   conf0 & BYT_TRIG_LVL ? " level" : "");
 	}
 	spin_unlock_irqrestore(&vg->lock, flags);
 }
 
 static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
+	struct byt_gpio *vg = to_byt_gpio(chip);
 	return irq_create_mapping(vg->domain, offset);
 }
 
@@ -516,6 +520,7 @@ static int byt_gpio_remove(struct platform_device *pdev)
 {
 	struct byt_gpio *vg = platform_get_drvdata(pdev);
 	int err;
+
 	pm_runtime_disable(&pdev->dev);
 	err = gpiochip_remove(&vg->chip);
 	if (err)
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 57a4eb0..df80ab6 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -239,8 +239,38 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
 			pin_reg->mux_reg, mux[i]);
 
-		/* some pins also need select input setting, set it if found */
-		if (input_reg[i]) {
+		/*
+		 * If the select input value begins with 0xff, it's a quirky
+		 * select input and the value should be interpreted as below.
+		 *     31     23      15      7        0
+		 *     | 0xff | shift | width | select |
+		 * It's used to work around the problem that the select
+		 * input for some pin is not implemented in the select
+		 * input register but in some general purpose register.
+		 * We encode the select input value, width and shift of
+		 * the bit field into input_val cell of pin function ID
+		 * in device tree, and then decode them here for setting
+		 * up the select input bits in general purpose register.
+		 */
+		if (input_val[i] >> 24 == 0xff) {
+			u32 val = input_val[i];
+			u8 select = val & 0xff;
+			u8 width = (val >> 8) & 0xff;
+			u8 shift = (val >> 16) & 0xff;
+			u32 mask = ((1 << width) - 1) << shift;
+			/*
+			 * The input_reg[i] here is actually some IOMUXC general
+			 * purpose register, not regular select input register.
+			 */
+			val = readl(ipctl->base + input_reg[i]);
+			val &= ~mask;
+			val |= select << shift;
+			writel(val, ipctl->base + input_reg[i]);
+		} else if (input_reg[i]) {
+			/*
+			 * Regular select input register can never be at offset
+			 * 0, and we only print register value for regular case.
+			 */
 			writel(input_val[i], ipctl->base + input_reg[i]);
 			dev_dbg(ipctl->dev,
 				"==>select_input: offset 0x%x val 0x%x\n",
@@ -580,9 +610,6 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOENT;
-
 	ipctl->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(ipctl->base))
 		return PTR_ERR(ipctl->base);
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 4a1cfdc..89280bc 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -337,97 +337,6 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
 	nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit));
 }
 
-static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
-			     pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
-{
-	static const char *afnames[] = {
-		[NMK_GPIO_ALT_GPIO]	= "GPIO",
-		[NMK_GPIO_ALT_A]	= "A",
-		[NMK_GPIO_ALT_B]	= "B",
-		[NMK_GPIO_ALT_C]	= "C"
-	};
-	static const char *pullnames[] = {
-		[NMK_GPIO_PULL_NONE]	= "none",
-		[NMK_GPIO_PULL_UP]	= "up",
-		[NMK_GPIO_PULL_DOWN]	= "down",
-		[3] /* illegal */	= "??"
-	};
-	static const char *slpmnames[] = {
-		[NMK_GPIO_SLPM_INPUT]		= "input/wakeup",
-		[NMK_GPIO_SLPM_NOCHANGE]	= "no-change/no-wakeup",
-	};
-
-	int pin = PIN_NUM(cfg);
-	int pull = PIN_PULL(cfg);
-	int af = PIN_ALT(cfg);
-	int slpm = PIN_SLPM(cfg);
-	int output = PIN_DIR(cfg);
-	int val = PIN_VAL(cfg);
-	bool glitch = af == NMK_GPIO_ALT_C;
-
-	dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
-		pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
-		output ? "output " : "input",
-		output ? (val ? "high" : "low") : "");
-
-	if (sleep) {
-		int slpm_pull = PIN_SLPM_PULL(cfg);
-		int slpm_output = PIN_SLPM_DIR(cfg);
-		int slpm_val = PIN_SLPM_VAL(cfg);
-
-		af = NMK_GPIO_ALT_GPIO;
-
-		/*
-		 * The SLPM_* values are normal values + 1 to allow zero to
-		 * mean "same as normal".
-		 */
-		if (slpm_pull)
-			pull = slpm_pull - 1;
-		if (slpm_output)
-			output = slpm_output - 1;
-		if (slpm_val)
-			val = slpm_val - 1;
-
-		dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
-			pin,
-			slpm_pull ? pullnames[pull] : "same",
-			slpm_output ? (output ? "output" : "input") : "same",
-			slpm_val ? (val ? "high" : "low") : "same");
-	}
-
-	if (output)
-		__nmk_gpio_make_output(nmk_chip, offset, val);
-	else {
-		__nmk_gpio_make_input(nmk_chip, offset);
-		__nmk_gpio_set_pull(nmk_chip, offset, pull);
-	}
-
-	__nmk_gpio_set_lowemi(nmk_chip, offset, PIN_LOWEMI(cfg));
-
-	/*
-	 * If the pin is switching to altfunc, and there was an interrupt
-	 * installed on it which has been lazy disabled, actually mask the
-	 * interrupt to prevent spurious interrupts that would occur while the
-	 * pin is under control of the peripheral.  Only SKE does this.
-	 */
-	if (af != NMK_GPIO_ALT_GPIO)
-		nmk_gpio_disable_lazy_irq(nmk_chip, offset);
-
-	/*
-	 * If we've backed up the SLPM registers (glitch workaround), modify
-	 * the backups since they will be restored.
-	 */
-	if (slpmregs) {
-		if (slpm == NMK_GPIO_SLPM_NOCHANGE)
-			slpmregs[nmk_chip->bank] |= BIT(offset);
-		else
-			slpmregs[nmk_chip->bank] &= ~BIT(offset);
-	} else
-		__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
-
-	__nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
-}
-
 /*
  * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
  *  - Save SLPM registers
@@ -474,210 +383,6 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
 	}
 }
 
-static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
-{
-	static unsigned int slpm[NUM_BANKS];
-	unsigned long flags;
-	bool glitch = false;
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < num; i++) {
-		if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
-			glitch = true;
-			break;
-		}
-	}
-
-	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-
-	if (glitch) {
-		memset(slpm, 0xff, sizeof(slpm));
-
-		for (i = 0; i < num; i++) {
-			int pin = PIN_NUM(cfgs[i]);
-			int offset = pin % NMK_GPIO_PER_CHIP;
-
-			if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
-				slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
-		}
-
-		nmk_gpio_glitch_slpm_init(slpm);
-	}
-
-	for (i = 0; i < num; i++) {
-		struct nmk_gpio_chip *nmk_chip;
-		int pin = PIN_NUM(cfgs[i]);
-
-		nmk_chip = nmk_gpio_chips[pin / NMK_GPIO_PER_CHIP];
-		if (!nmk_chip) {
-			ret = -EINVAL;
-			break;
-		}
-
-		clk_enable(nmk_chip->clk);
-		spin_lock(&nmk_chip->lock);
-		__nmk_config_pin(nmk_chip, pin % NMK_GPIO_PER_CHIP,
-				 cfgs[i], sleep, glitch ? slpm : NULL);
-		spin_unlock(&nmk_chip->lock);
-		clk_disable(nmk_chip->clk);
-	}
-
-	if (glitch)
-		nmk_gpio_glitch_slpm_restore(slpm);
-
-	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-
-	return ret;
-}
-
-/**
- * nmk_config_pin - configure a pin's mux attributes
- * @cfg: pin confguration
- * @sleep: Non-zero to apply the sleep mode configuration
- * Configures a pin's mode (alternate function or GPIO), its pull up status,
- * and its sleep mode based on the specified configuration.  The @cfg is
- * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
- * are constructed using, and can be further enhanced with, the macros in
- * <linux/platform_data/pinctrl-nomadik.h>
- *
- * If a pin's mode is set to GPIO, it is configured as an input to avoid
- * side-effects.  The gpio can be manipulated later using standard GPIO API
- * calls.
- */
-int nmk_config_pin(pin_cfg_t cfg, bool sleep)
-{
-	return __nmk_config_pins(&cfg, 1, sleep);
-}
-EXPORT_SYMBOL(nmk_config_pin);
-
-/**
- * nmk_config_pins - configure several pins at once
- * @cfgs: array of pin configurations
- * @num: number of elments in the array
- *
- * Configures several pins using nmk_config_pin().  Refer to that function for
- * further information.
- */
-int nmk_config_pins(pin_cfg_t *cfgs, int num)
-{
-	return __nmk_config_pins(cfgs, num, false);
-}
-EXPORT_SYMBOL(nmk_config_pins);
-
-int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
-{
-	return __nmk_config_pins(cfgs, num, true);
-}
-EXPORT_SYMBOL(nmk_config_pins_sleep);
-
-/**
- * nmk_gpio_set_slpm() - configure the sleep mode of a pin
- * @gpio: pin number
- * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE,
- *
- * This register is actually in the pinmux layer, not the GPIO block itself.
- * The GPIO1B_SLPM register defines the GPIO mode when SLEEP/DEEP-SLEEP
- * mode is entered (i.e. when signal IOFORCE is HIGH by the platform code).
- * Each GPIO can be configured to be forced into GPIO mode when IOFORCE is
- * HIGH, overriding the normal setting defined by GPIO_AFSELx registers.
- * When IOFORCE returns LOW (by software, after SLEEP/DEEP-SLEEP exit),
- * the GPIOs return to the normal setting defined by GPIO_AFSELx registers.
- *
- * If @mode is NMK_GPIO_SLPM_INPUT, the corresponding GPIO is switched to GPIO
- * mode when signal IOFORCE is HIGH (i.e. when SLEEP/DEEP-SLEEP mode is
- * entered) regardless of the altfunction selected. Also wake-up detection is
- * ENABLED.
- *
- * If @mode is NMK_GPIO_SLPM_NOCHANGE, the corresponding GPIO remains
- * controlled by NMK_GPIO_DATC, NMK_GPIO_DATS, NMK_GPIO_DIR, NMK_GPIO_PDIS
- * (for altfunction GPIO) or respective on-chip peripherals (for other
- * altfuncs) when IOFORCE is HIGH. Also wake-up detection DISABLED.
- *
- * Note that enable_irq_wake() will automatically enable wakeup detection.
- */
-int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	unsigned long flags;
-
-	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
-	if (!nmk_chip)
-		return -EINVAL;
-
-	clk_enable(nmk_chip->clk);
-	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-	spin_lock(&nmk_chip->lock);
-
-	__nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, mode);
-
-	spin_unlock(&nmk_chip->lock);
-	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-/**
- * nmk_gpio_set_pull() - enable/disable pull up/down on a gpio
- * @gpio: pin number
- * @pull: one of NMK_GPIO_PULL_DOWN, NMK_GPIO_PULL_UP, and NMK_GPIO_PULL_NONE
- *
- * Enables/disables pull up/down on a specified pin.  This only takes effect if
- * the pin is configured as an input (either explicitly or by the alternate
- * function).
- *
- * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
- * configured as an input.  Otherwise, due to the way the controller registers
- * work, this function will change the value output on the pin.
- */
-int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	unsigned long flags;
-
-	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
-	if (!nmk_chip)
-		return -EINVAL;
-
-	clk_enable(nmk_chip->clk);
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_gpio_set_pull(nmk_chip, gpio % NMK_GPIO_PER_CHIP, pull);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-/* Mode functions */
-/**
- * nmk_gpio_set_mode() - set the mux mode of a gpio pin
- * @gpio: pin number
- * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
- *	       NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
- *
- * Sets the mode of the specified pin to one of the alternate functions or
- * plain GPIO.
- */
-int nmk_gpio_set_mode(int gpio, int gpio_mode)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	unsigned long flags;
-
-	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
-	if (!nmk_chip)
-		return -EINVAL;
-
-	clk_enable(nmk_chip->clk);
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_gpio_set_mode(nmk_chip, gpio % NMK_GPIO_PER_CHIP, gpio_mode);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-EXPORT_SYMBOL(nmk_gpio_set_mode);
-
 static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
 {
 	int i;
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 1eb5a2e..c22457d 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -36,7 +36,7 @@
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/pinconf-generic.h>
 #include <linux/irqchip/chained_irq.h>
-#include <linux/clk-provider.h>
+#include <linux/clk.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 
 #include "core.h"
@@ -1270,11 +1270,6 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
 	info->dev = dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "cannot find IO resource\n");
-		return -ENOENT;
-	}
-
 	info->reg_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(info->reg_base))
 		return PTR_ERR(info->reg_base);
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 04d4506..2a10a31 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -288,8 +288,8 @@ struct st_pinctrl {
 
 /* SOC specific data */
 /* STiH415 data */
-unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
-unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};
+static unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
+static unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};
 
 #define STIH415_PCTRL_COMMON_DATA				\
 	.rt_style	= st_retime_style_packed,		\
@@ -324,7 +324,7 @@ static const struct st_pctl_data  stih415_right_data = {
 };
 
 /* STiH416 data */
-unsigned int stih416_delays[] = {0, 300, 500, 750, 1000, 1250, 1500,
+static unsigned int stih416_delays[] = {0, 300, 500, 750, 1000, 1250, 1500,
 			1750, 2000, 2250, 2500, 2750, 3000, 3250 };
 
 static const struct st_pctl_data  stih416_data = {
@@ -811,7 +811,7 @@ static int st_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
 	return info->nfunctions;
 }
 
-const char *st_pmx_get_fname(struct pinctrl_dev *pctldev,
+static const char *st_pmx_get_fname(struct pinctrl_dev *pctldev,
 	unsigned selector)
 {
 	struct st_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
@@ -1222,11 +1222,9 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
 	if (of_address_to_resource(np, 0, &res))
 		return -ENODEV;
 
-	bank->base = devm_request_and_ioremap(dev, &res);
-	if (!bank->base) {
-		dev_err(dev, "Can't get IO memory mapping!\n");
-		return -ENODEV;
-	}
+	bank->base = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(bank->base))
+		return PTR_ERR(bank->base);
 
 	bank->gpio_chip = st_gpio_template;
 	bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK;
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index c47fd1e..8b15e99 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -175,7 +175,7 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 	}
 
 	*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
-	if (!map)
+	if (!*map)
 		return -ENOMEM;
 
 	of_property_for_each_string(node, "allwinner,pins", prop, group) {
@@ -278,6 +278,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
 {
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
 	struct sunxi_pinctrl_group *g = &pctl->groups[group];
+	unsigned long flags;
 	u32 val, mask;
 	u16 strength;
 	u8 dlevel;
@@ -295,22 +296,35 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
 		 *   3: 40mA
 		 */
 		dlevel = strength / 10 - 1;
+
+		spin_lock_irqsave(&pctl->lock, flags);
+
 		val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
 	        mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
 		writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
 			pctl->membase + sunxi_dlevel_reg(g->pin));
+
+		spin_unlock_irqrestore(&pctl->lock, flags);
 		break;
 	case PIN_CONFIG_BIAS_PULL_UP:
+		spin_lock_irqsave(&pctl->lock, flags);
+
 		val = readl(pctl->membase + sunxi_pull_reg(g->pin));
 		mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
 		writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
 			pctl->membase + sunxi_pull_reg(g->pin));
+
+		spin_unlock_irqrestore(&pctl->lock, flags);
 		break;
 	case PIN_CONFIG_BIAS_PULL_DOWN:
+		spin_lock_irqsave(&pctl->lock, flags);
+
 		val = readl(pctl->membase + sunxi_pull_reg(g->pin));
 		mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
 		writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
 			pctl->membase + sunxi_pull_reg(g->pin));
+
+		spin_unlock_irqrestore(&pctl->lock, flags);
 		break;
 	default:
 		break;
@@ -360,11 +374,17 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
 				 u8 config)
 {
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned long flags;
+	u32 val, mask;
+
+	spin_lock_irqsave(&pctl->lock, flags);
 
-	u32 val = readl(pctl->membase + sunxi_mux_reg(pin));
-	u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
+	val = readl(pctl->membase + sunxi_mux_reg(pin));
+	mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
 	writel((val & ~mask) | config << sunxi_mux_offset(pin),
 		pctl->membase + sunxi_mux_reg(pin));
+
+	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
@@ -464,8 +484,21 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
 	struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
 	u32 reg = sunxi_data_reg(offset);
 	u8 index = sunxi_data_offset(offset);
+	unsigned long flags;
+	u32 regval;
+
+	spin_lock_irqsave(&pctl->lock, flags);
+
+	regval = readl(pctl->membase + reg);
 
-	writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
+	if (value)
+		regval |= BIT(index);
+	else
+		regval &= ~(BIT(index));
+
+	writel(regval, pctl->membase + reg);
+
+	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
@@ -526,6 +559,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
 	u32 reg = sunxi_irq_cfg_reg(d->hwirq);
 	u8 index = sunxi_irq_cfg_offset(d->hwirq);
+	unsigned long flags;
+	u32 regval;
 	u8 mode;
 
 	switch (type) {
@@ -548,7 +583,13 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
 		return -EINVAL;
 	}
 
-	writel((mode & IRQ_CFG_IRQ_MASK) << index, pctl->membase + reg);
+	spin_lock_irqsave(&pctl->lock, flags);
+
+	regval = readl(pctl->membase + reg);
+	regval &= ~IRQ_CFG_IRQ_MASK;
+	writel(regval | (mode << index), pctl->membase + reg);
+
+	spin_unlock_irqrestore(&pctl->lock, flags);
 
 	return 0;
 }
@@ -560,14 +601,19 @@ static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
 	u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
 	u32 status_reg = sunxi_irq_status_reg(d->hwirq);
 	u8 status_idx = sunxi_irq_status_offset(d->hwirq);
+	unsigned long flags;
 	u32 val;
 
+	spin_lock_irqsave(&pctl->lock, flags);
+
 	/* Mask the IRQ */
 	val = readl(pctl->membase + ctrl_reg);
 	writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
 
 	/* Clear the IRQ */
 	writel(1 << status_idx, pctl->membase + status_reg);
+
+	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -575,11 +621,16 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
 	u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
 	u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+	unsigned long flags;
 	u32 val;
 
+	spin_lock_irqsave(&pctl->lock, flags);
+
 	/* Mask the IRQ */
 	val = readl(pctl->membase + reg);
 	writel(val & ~(1 << idx), pctl->membase + reg);
+
+	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
@@ -588,6 +639,7 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
 	struct sunxi_desc_function *func;
 	u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
 	u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+	unsigned long flags;
 	u32 val;
 
 	func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
@@ -597,9 +649,13 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
 	/* Change muxing to INT mode */
 	sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
 
+	spin_lock_irqsave(&pctl->lock, flags);
+
 	/* Unmask the IRQ */
 	val = readl(pctl->membase + reg);
 	writel(val | (1 << idx), pctl->membase + reg);
+
+	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static struct irq_chip sunxi_pinctrl_irq_chip = {
@@ -752,6 +808,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	platform_set_drvdata(pdev, pctl);
 
+	spin_lock_init(&pctl->lock);
+
 	pctl->membase = of_iomap(node, 0);
 	if (!pctl->membase)
 		return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index d68047d..01c494f 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -14,6 +14,7 @@
 #define __PINCTRL_SUNXI_H
 
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 
 #define PA_BASE	0
 #define PB_BASE	32
@@ -407,6 +408,7 @@ struct sunxi_pinctrl {
 	unsigned			ngroups;
 	int				irq;
 	int				irq_array[SUNXI_IRQ_NUMBER];
+	spinlock_t			lock;
 	struct pinctrl_dev		*pctl_dev;
 };
 
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 46a152d..6fbdc06 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -1075,9 +1075,6 @@ static int u300_pmx_probe(struct platform_device *pdev)
 	upmx->dev = &pdev->dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOENT;
-
 	upmx->virtbase = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(upmx->virtbase))
 		return PTR_ERR(upmx->virtbase);
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index f3fc66b..9e66614 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -82,24 +82,20 @@ int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
 	unsigned int offset;
 	unsigned int i;
 
-	if (pfc->info->ranges == NULL)
-		return pin;
-
-	for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) {
-		const struct pinmux_range *range = &pfc->info->ranges[i];
+	for (i = 0, offset = 0; i < pfc->nr_ranges; ++i) {
+		const struct sh_pfc_pin_range *range = &pfc->ranges[i];
 
 		if (pin <= range->end)
-			return pin >= range->begin
-			     ? offset + pin - range->begin : -1;
+			return pin >= range->start
+			     ? offset + pin - range->start : -1;
 
-		offset += range->end - range->begin + 1;
+		offset += range->end - range->start + 1;
 	}
 
 	return -EINVAL;
 }
 
-static int sh_pfc_enum_in_range(pinmux_enum_t enum_id,
-				const struct pinmux_range *r)
+static int sh_pfc_enum_in_range(u16 enum_id, const struct pinmux_range *r)
 {
 	if (enum_id < r->begin)
 		return 0;
@@ -194,7 +190,7 @@ static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
 	sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
 }
 
-static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
+static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
 				 const struct pinmux_cfg_reg **crp, int *fieldp,
 				 int *valuep)
 {
@@ -238,10 +234,10 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
 	return -EINVAL;
 }
 
-static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, pinmux_enum_t mark, int pos,
-			      pinmux_enum_t *enum_idp)
+static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
+			      u16 *enum_idp)
 {
-	const pinmux_enum_t *data = pfc->info->gpio_data;
+	const u16 *data = pfc->info->gpio_data;
 	int k;
 
 	if (pos) {
@@ -264,7 +260,7 @@ static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, pinmux_enum_t mark, int pos,
 int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
 {
 	const struct pinmux_cfg_reg *cr = NULL;
-	pinmux_enum_t enum_id;
+	u16 enum_id;
 	const struct pinmux_range *range;
 	int in_range, pos, field, value;
 	int ret;
@@ -283,14 +279,6 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
 		range = &pfc->info->input;
 		break;
 
-	case PINMUX_TYPE_INPUT_PULLUP:
-		range = &pfc->info->input_pu;
-		break;
-
-	case PINMUX_TYPE_INPUT_PULLDOWN:
-		range = &pfc->info->input_pd;
-		break;
-
 	default:
 		return -EINVAL;
 	}
@@ -350,6 +338,67 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
 	return 0;
 }
 
+static int sh_pfc_init_ranges(struct sh_pfc *pfc)
+{
+	struct sh_pfc_pin_range *range;
+	unsigned int nr_ranges;
+	unsigned int i;
+
+	if (pfc->info->pins[0].pin == (u16)-1) {
+		/* Pin number -1 denotes that the SoC doesn't report pin numbers
+		 * in its pin arrays yet. Consider the pin numbers range as
+		 * continuous and allocate a single range.
+		 */
+		pfc->nr_ranges = 1;
+		pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges),
+					   GFP_KERNEL);
+		if (pfc->ranges == NULL)
+			return -ENOMEM;
+
+		pfc->ranges->start = 0;
+		pfc->ranges->end = pfc->info->nr_pins - 1;
+		pfc->nr_gpio_pins = pfc->info->nr_pins;
+
+		return 0;
+	}
+
+	/* Count, allocate and fill the ranges. The PFC SoC data pins array must
+	 * be sorted by pin numbers, and pins without a GPIO port must come
+	 * last.
+	 */
+	for (i = 1, nr_ranges = 1; i < pfc->info->nr_pins; ++i) {
+		if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1)
+			nr_ranges++;
+	}
+
+	pfc->nr_ranges = nr_ranges;
+	pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges,
+				   GFP_KERNEL);
+	if (pfc->ranges == NULL)
+		return -ENOMEM;
+
+	range = pfc->ranges;
+	range->start = pfc->info->pins[0].pin;
+
+	for (i = 1; i < pfc->info->nr_pins; ++i) {
+		if (pfc->info->pins[i-1].pin == pfc->info->pins[i].pin - 1)
+			continue;
+
+		range->end = pfc->info->pins[i-1].pin;
+		if (!(pfc->info->pins[i-1].configs & SH_PFC_PIN_CFG_NO_GPIO))
+			pfc->nr_gpio_pins = range->end + 1;
+
+		range++;
+		range->start = pfc->info->pins[i].pin;
+	}
+
+	range->end = pfc->info->pins[i-1].pin;
+	if (!(pfc->info->pins[i-1].configs & SH_PFC_PIN_CFG_NO_GPIO))
+		pfc->nr_gpio_pins = range->end + 1;
+
+	return 0;
+}
+
 #ifdef CONFIG_OF
 static const struct of_device_id sh_pfc_of_table[] = {
 #ifdef CONFIG_PINCTRL_PFC_R8A73A4
@@ -440,6 +489,10 @@ static int sh_pfc_probe(struct platform_device *pdev)
 
 	pinctrl_provide_dummies();
 
+	ret = sh_pfc_init_ranges(pfc);
+	if (ret < 0)
+		return ret;
+
 	/*
 	 * Initialize pinctrl bindings first
 	 */
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index f02ba1d..a1b2376 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -25,6 +25,11 @@ struct sh_pfc_window {
 struct sh_pfc_chip;
 struct sh_pfc_pinctrl;
 
+struct sh_pfc_pin_range {
+	u16 start;
+	u16 end;
+};
+
 struct sh_pfc {
 	struct device *dev;
 	const struct sh_pfc_soc_info *info;
@@ -34,7 +39,10 @@ struct sh_pfc {
 	unsigned int num_windows;
 	struct sh_pfc_window *window;
 
-	unsigned int nr_pins;
+	struct sh_pfc_pin_range *ranges;
+	unsigned int nr_ranges;
+
+	unsigned int nr_gpio_pins;
 
 	struct sh_pfc_chip *gpio;
 	struct sh_pfc_chip *func;
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index d37efa7..04bf52b 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -48,11 +48,11 @@ static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)
 	return gpio_to_pfc_chip(gc)->pfc;
 }
 
-static void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int gpio,
+static void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int offset,
 			      struct sh_pfc_gpio_data_reg **reg,
 			      unsigned int *bit)
 {
-	int idx = sh_pfc_get_pin_index(chip->pfc, gpio);
+	int idx = sh_pfc_get_pin_index(chip->pfc, offset);
 	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
 
 	*reg = &chip->regs[gpio_pin->dreg];
@@ -76,11 +76,11 @@ static void gpio_write_data_reg(struct sh_pfc_chip *chip,
 	sh_pfc_write_raw_reg(mem, dreg->reg_width, value);
 }
 
-static void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned gpio)
+static void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned idx)
 {
 	struct sh_pfc *pfc = chip->pfc;
-	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[gpio];
-	const struct sh_pfc_pin *pin = &pfc->info->pins[gpio];
+	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
+	const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
 	const struct pinmux_data_reg *dreg;
 	unsigned int bit;
 	unsigned int i;
@@ -224,8 +224,8 @@ static int gpio_pin_setup(struct sh_pfc_chip *chip)
 	struct gpio_chip *gc = &chip->gpio_chip;
 	int ret;
 
-	chip->pins = devm_kzalloc(pfc->dev, pfc->nr_pins * sizeof(*chip->pins),
-				  GFP_KERNEL);
+	chip->pins = devm_kzalloc(pfc->dev, pfc->info->nr_pins *
+				  sizeof(*chip->pins), GFP_KERNEL);
 	if (chip->pins == NULL)
 		return -ENOMEM;
 
@@ -245,7 +245,7 @@ static int gpio_pin_setup(struct sh_pfc_chip *chip)
 	gc->dev = pfc->dev;
 	gc->owner = THIS_MODULE;
 	gc->base = 0;
-	gc->ngpio = pfc->nr_pins;
+	gc->ngpio = pfc->nr_gpio_pins;
 
 	return 0;
 }
@@ -293,7 +293,7 @@ static int gpio_function_setup(struct sh_pfc_chip *chip)
 
 	gc->label = pfc->info->name;
 	gc->owner = THIS_MODULE;
-	gc->base = pfc->nr_pins;
+	gc->base = pfc->nr_gpio_pins;
 	gc->ngpio = pfc->info->nr_func_gpios;
 
 	return 0;
@@ -334,10 +334,7 @@ sh_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *),
 
 int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
 {
-	const struct pinmux_range *ranges;
-	struct pinmux_range def_range;
 	struct sh_pfc_chip *chip;
-	unsigned int nr_ranges;
 	unsigned int i;
 	int ret;
 
@@ -367,24 +364,20 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
 
 	pfc->gpio = chip;
 
-	/* Register the GPIO to pin mappings. */
-	if (pfc->info->ranges == NULL) {
-		def_range.begin = 0;
-		def_range.end = pfc->info->nr_pins - 1;
-		ranges = &def_range;
-		nr_ranges = 1;
-	} else {
-		ranges = pfc->info->ranges;
-		nr_ranges = pfc->info->nr_ranges;
-	}
+	/* Register the GPIO to pin mappings. As pins with GPIO ports must come
+	 * first in the ranges, skip the pins without GPIO ports by stopping at
+	 * the first range that contains such a pin.
+	 */
+	for (i = 0; i < pfc->nr_ranges; ++i) {
+		const struct sh_pfc_pin_range *range = &pfc->ranges[i];
 
-	for (i = 0; i < nr_ranges; ++i) {
-		const struct pinmux_range *range = &ranges[i];
+		if (range->start >= pfc->nr_gpio_pins)
+			break;
 
 		ret = gpiochip_add_pin_range(&chip->gpio_chip,
 					     dev_name(pfc->dev),
-					     range->begin, range->begin,
-					     range->end - range->begin + 1);
+					     range->start, range->start,
+					     range->end - range->start + 1);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
index 82bf6ab..d25fd4e 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
@@ -21,85 +21,84 @@
 #include <linux/kernel.h>
 #include <linux/pinctrl/pinconf-generic.h>
 #include <mach/irqs.h>
-#include <mach/r8a73a4.h>
 
 #include "core.h"
 #include "sh_pfc.h"
 
 #define CPU_ALL_PORT(fn, pfx, sfx)					\
 	/*  Port0 - Port30 */						\
-	PORT_10(fn, pfx, sfx),						\
-	PORT_10(fn, pfx##1, sfx),					\
-	PORT_10(fn, pfx##2, sfx),					\
-	PORT_1(fn,  pfx##30, sfx),					\
+	PORT_10(0, fn, pfx, sfx),					\
+	PORT_10(10, fn, pfx##1, sfx),					\
+	PORT_10(20, fn, pfx##2, sfx),					\
+	PORT_1(30, fn, pfx##30, sfx),					\
 	/* Port32 - Port40 */						\
-	PORT_1(fn,  pfx##32, sfx),	PORT_1(fn,  pfx##33, sfx),	\
-	PORT_1(fn,  pfx##34, sfx),	PORT_1(fn,  pfx##35, sfx),	\
-	PORT_1(fn,  pfx##36, sfx),	PORT_1(fn,  pfx##37, sfx),	\
-	PORT_1(fn,  pfx##38, sfx),	PORT_1(fn,  pfx##39, sfx),	\
-	PORT_1(fn,  pfx##40, sfx),					\
+	PORT_1(32, fn, pfx##32, sfx),	PORT_1(33, fn, pfx##33, sfx),	\
+	PORT_1(34, fn, pfx##34, sfx),	PORT_1(35, fn, pfx##35, sfx),	\
+	PORT_1(36, fn, pfx##36, sfx),	PORT_1(37, fn, pfx##37, sfx),	\
+	PORT_1(38, fn, pfx##38, sfx),	PORT_1(39, fn, pfx##39, sfx),	\
+	PORT_1(40, fn, pfx##40, sfx),					\
 	/* Port64  - Port85 */						\
-	PORT_1(fn, pfx##64, sfx),	PORT_1(fn, pfx##65, sfx),	\
-	PORT_1(fn, pfx##66, sfx),	PORT_1(fn, pfx##67, sfx),	\
-	PORT_1(fn, pfx##68, sfx),	PORT_1(fn, pfx##69, sfx),	\
-	PORT_10(fn, pfx##7, sfx),					\
-	PORT_1(fn, pfx##80, sfx),	PORT_1(fn, pfx##81, sfx),	\
-	PORT_1(fn, pfx##82, sfx),	PORT_1(fn, pfx##83, sfx),	\
-	PORT_1(fn, pfx##84, sfx),	PORT_1(fn, pfx##85, sfx),	\
+	PORT_1(64, fn, pfx##64, sfx),	PORT_1(65, fn, pfx##65, sfx),	\
+	PORT_1(66, fn, pfx##66, sfx),	PORT_1(67, fn, pfx##67, sfx),	\
+	PORT_1(68, fn, pfx##68, sfx),	PORT_1(69, fn, pfx##69, sfx),	\
+	PORT_10(70, fn, pfx##7, sfx),					\
+	PORT_1(80, fn, pfx##80, sfx),	PORT_1(81, fn, pfx##81, sfx),	\
+	PORT_1(82, fn, pfx##82, sfx),	PORT_1(83, fn, pfx##83, sfx),	\
+	PORT_1(84, fn, pfx##84, sfx),	PORT_1(85, fn, pfx##85, sfx),	\
 	/* Port96  - Port126 */						\
-	PORT_1(fn, pfx##96, sfx),	PORT_1(fn, pfx##97, sfx),	\
-	PORT_1(fn, pfx##98, sfx),	PORT_1(fn, pfx##99, sfx),	\
-	PORT_10(fn, pfx##10, sfx),					\
-	PORT_10(fn, pfx##11, sfx),					\
-	PORT_1(fn, pfx##120, sfx),	PORT_1(fn, pfx##121, sfx),	\
-	PORT_1(fn, pfx##122, sfx),	PORT_1(fn, pfx##123, sfx),	\
-	PORT_1(fn, pfx##124, sfx),	PORT_1(fn, pfx##125, sfx),	\
-	PORT_1(fn, pfx##126, sfx),					\
+	PORT_1(96, fn, pfx##96, sfx),	PORT_1(97, fn, pfx##97, sfx),	\
+	PORT_1(98, fn, pfx##98, sfx),	PORT_1(99, fn, pfx##99, sfx),	\
+	PORT_10(100, fn, pfx##10, sfx),					\
+	PORT_10(110, fn, pfx##11, sfx),					\
+	PORT_1(120, fn, pfx##120, sfx),	PORT_1(121, fn, pfx##121, sfx),	\
+	PORT_1(122, fn, pfx##122, sfx),	PORT_1(123, fn, pfx##123, sfx),	\
+	PORT_1(124, fn, pfx##124, sfx),	PORT_1(125, fn, pfx##125, sfx),	\
+	PORT_1(126, fn, pfx##126, sfx),					\
 	/* Port128 - Port134 */						\
-	PORT_1(fn, pfx##128, sfx),	PORT_1(fn, pfx##129, sfx),	\
-	PORT_1(fn, pfx##130, sfx),	PORT_1(fn, pfx##131, sfx),	\
-	PORT_1(fn, pfx##132, sfx),	PORT_1(fn, pfx##133, sfx),	\
-	PORT_1(fn, pfx##134, sfx),					\
+	PORT_1(128, fn, pfx##128, sfx),	PORT_1(129, fn, pfx##129, sfx),	\
+	PORT_1(130, fn, pfx##130, sfx),	PORT_1(131, fn, pfx##131, sfx),	\
+	PORT_1(132, fn, pfx##132, sfx),	PORT_1(133, fn, pfx##133, sfx),	\
+	PORT_1(134, fn, pfx##134, sfx),					\
 	/* Port160 - Port178 */						\
-	PORT_10(fn, pfx##16, sfx),					\
-	PORT_1(fn, pfx##170, sfx),	PORT_1(fn, pfx##171, sfx),	\
-	PORT_1(fn, pfx##172, sfx),	PORT_1(fn, pfx##173, sfx),	\
-	PORT_1(fn, pfx##174, sfx),	PORT_1(fn, pfx##175, sfx),	\
-	PORT_1(fn, pfx##176, sfx),	PORT_1(fn, pfx##177, sfx),	\
-	PORT_1(fn, pfx##178, sfx),					\
+	PORT_10(160, fn, pfx##16, sfx),					\
+	PORT_1(170, fn, pfx##170, sfx),	PORT_1(171, fn, pfx##171, sfx),	\
+	PORT_1(172, fn, pfx##172, sfx),	PORT_1(173, fn, pfx##173, sfx),	\
+	PORT_1(174, fn, pfx##174, sfx),	PORT_1(175, fn, pfx##175, sfx),	\
+	PORT_1(176, fn, pfx##176, sfx),	PORT_1(177, fn, pfx##177, sfx),	\
+	PORT_1(178, fn, pfx##178, sfx),					\
 	/* Port192 - Port222 */						\
-	PORT_1(fn, pfx##192, sfx),	PORT_1(fn, pfx##193, sfx),	\
-	PORT_1(fn, pfx##194, sfx),	PORT_1(fn, pfx##195, sfx),	\
-	PORT_1(fn, pfx##196, sfx),	PORT_1(fn, pfx##197, sfx),	\
-	PORT_1(fn, pfx##198, sfx),	PORT_1(fn, pfx##199, sfx),	\
-	PORT_10(fn, pfx##20, sfx),					\
-	PORT_10(fn, pfx##21, sfx),					\
-	PORT_1(fn, pfx##220, sfx),	PORT_1(fn, pfx##221, sfx),	\
-	PORT_1(fn, pfx##222, sfx),					\
+	PORT_1(192, fn, pfx##192, sfx),	PORT_1(193, fn, pfx##193, sfx),	\
+	PORT_1(194, fn, pfx##194, sfx),	PORT_1(195, fn, pfx##195, sfx),	\
+	PORT_1(196, fn, pfx##196, sfx),	PORT_1(197, fn, pfx##197, sfx),	\
+	PORT_1(198, fn, pfx##198, sfx),	PORT_1(199, fn, pfx##199, sfx),	\
+	PORT_10(200, fn, pfx##20, sfx),					\
+	PORT_10(210, fn, pfx##21, sfx),					\
+	PORT_1(220, fn, pfx##220, sfx),	PORT_1(221, fn, pfx##221, sfx),	\
+	PORT_1(222, fn, pfx##222, sfx),					\
 	/* Port224 - Port250 */						\
-	PORT_1(fn, pfx##224, sfx),	PORT_1(fn, pfx##225, sfx),	\
-	PORT_1(fn, pfx##226, sfx),	PORT_1(fn, pfx##227, sfx),	\
-	PORT_1(fn, pfx##228, sfx),	PORT_1(fn, pfx##229, sfx),	\
-	PORT_10(fn, pfx##23, sfx),					\
-	PORT_10(fn, pfx##24, sfx),					\
-	PORT_1(fn, pfx##250, sfx),					\
+	PORT_1(224, fn, pfx##224, sfx),	PORT_1(225, fn, pfx##225, sfx),	\
+	PORT_1(226, fn, pfx##226, sfx),	PORT_1(227, fn, pfx##227, sfx),	\
+	PORT_1(228, fn, pfx##228, sfx),	PORT_1(229, fn, pfx##229, sfx),	\
+	PORT_10(230, fn, pfx##23, sfx),					\
+	PORT_10(240, fn, pfx##24, sfx),					\
+	PORT_1(250, fn, pfx##250, sfx),					\
 	/* Port256 - Port283 */						\
-	PORT_1(fn, pfx##256, sfx),	PORT_1(fn, pfx##257, sfx),	\
-	PORT_1(fn, pfx##258, sfx),	PORT_1(fn, pfx##259, sfx),	\
-	PORT_10(fn, pfx##26, sfx),					\
-	PORT_10(fn, pfx##27, sfx),					\
-	PORT_1(fn, pfx##280, sfx),	PORT_1(fn, pfx##281, sfx),	\
-	PORT_1(fn, pfx##282, sfx),	PORT_1(fn, pfx##283, sfx),	\
+	PORT_1(256, fn, pfx##256, sfx),	PORT_1(257, fn, pfx##257, sfx),	\
+	PORT_1(258, fn, pfx##258, sfx),	PORT_1(259, fn, pfx##259, sfx),	\
+	PORT_10(260, fn, pfx##26, sfx),					\
+	PORT_10(270, fn, pfx##27, sfx),					\
+	PORT_1(280, fn, pfx##280, sfx),	PORT_1(281, fn, pfx##281, sfx),	\
+	PORT_1(282, fn, pfx##282, sfx),	PORT_1(283, fn, pfx##283, sfx),	\
 	/* Port288 - Port308 */						\
-	PORT_1(fn, pfx##288, sfx),	PORT_1(fn, pfx##289, sfx),	\
-	PORT_10(fn, pfx##29, sfx),					\
-	PORT_1(fn, pfx##300, sfx),	PORT_1(fn, pfx##301, sfx),	\
-	PORT_1(fn, pfx##302, sfx),	PORT_1(fn, pfx##303, sfx),	\
-	PORT_1(fn, pfx##304, sfx),	PORT_1(fn, pfx##305, sfx),	\
-	PORT_1(fn, pfx##306, sfx),	PORT_1(fn, pfx##307, sfx),	\
-	PORT_1(fn, pfx##308, sfx),					\
+	PORT_1(288, fn, pfx##288, sfx),	PORT_1(289, fn, pfx##289, sfx),	\
+	PORT_10(290, fn, pfx##29, sfx),					\
+	PORT_1(300, fn, pfx##300, sfx),	PORT_1(301, fn, pfx##301, sfx),	\
+	PORT_1(302, fn, pfx##302, sfx),	PORT_1(303, fn, pfx##303, sfx),	\
+	PORT_1(304, fn, pfx##304, sfx),	PORT_1(305, fn, pfx##305, sfx),	\
+	PORT_1(306, fn, pfx##306, sfx),	PORT_1(307, fn, pfx##307, sfx),	\
+	PORT_1(308, fn, pfx##308, sfx),					\
 	/* Port320 - Port329 */						\
-	PORT_10(fn, pfx##32, sfx)
+	PORT_10(320, fn, pfx##32, sfx)
 
 
 enum {
@@ -428,10 +427,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define _PORT_DATA(pfx, sfx)	PORT_DATA_IO(pfx)
-#define PINMUX_DATA_ALL()    CPU_ALL_PORT(_PORT_DATA, , unused)
-
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
 	PINMUX_DATA_ALL(),
 
@@ -1269,19 +1265,12 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(IRQ57_MARK,			PORT329_FN0),
 };
 
-#define R8A73A4_PIN(pin, cfgs)			\
-	{					\
-		.name = __stringify(PORT##pin),	\
-		.enum_id = PORT##pin##_DATA,	\
-		.configs = cfgs,		\
-	}
-
 #define __O	(SH_PFC_PIN_CFG_OUTPUT)
 #define __IO	(SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
 #define __PUD	(SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
 
-#define R8A73A4_PIN_IO_PU_PD(pin)       R8A73A4_PIN(pin, __IO | __PUD)
-#define R8A73A4_PIN_O(pin)              R8A73A4_PIN(pin, __O)
+#define R8A73A4_PIN_IO_PU_PD(pin)       SH_PFC_PIN_CFG(pin, __IO | __PUD)
+#define R8A73A4_PIN_O(pin)              SH_PFC_PIN_CFG(pin, __O)
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	R8A73A4_PIN_IO_PU_PD(0), R8A73A4_PIN_IO_PU_PD(1),
@@ -1408,20 +1397,6 @@ static struct sh_pfc_pin pinmux_pins[] = {
 	R8A73A4_PIN_IO_PU_PD(328), R8A73A4_PIN_IO_PU_PD(329),
 };
 
-static const struct pinmux_range pinmux_ranges[] = {
-	{.begin = 0, .end = 30,},
-	{.begin = 32, .end = 40,},
-	{.begin = 64, .end = 85,},
-	{.begin = 96, .end = 126,},
-	{.begin = 128, .end = 134,},
-	{.begin = 160, .end = 178,},
-	{.begin = 192, .end = 222,},
-	{.begin = 224, .end = 250,},
-	{.begin = 256, .end = 283,},
-	{.begin = 288, .end = 308,},
-	{.begin = 320, .end = 329,},
-};
-
 /* - IRQC ------------------------------------------------------------------- */
 #define IRQC_PINS_MUX(pin, irq_mark)				\
 static const unsigned int irqc_irq##irq_mark##_pins[] = {	\
@@ -2766,9 +2741,6 @@ const struct sh_pfc_soc_info r8a73a4_pinmux_info = {
 	.pins = pinmux_pins,
 	.nr_pins = ARRAY_SIZE(pinmux_pins),
 
-	.ranges = pinmux_ranges,
-	.nr_ranges = ARRAY_SIZE(pinmux_ranges),
-
 	.groups = pinmux_groups,
 	.nr_groups = ARRAY_SIZE(pinmux_groups),
 	.functions = pinmux_functions,
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
index f6ea47c..009174d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
@@ -22,24 +22,16 @@
 #include <linux/kernel.h>
 #include <linux/pinctrl/pinconf-generic.h>
 
-#include <mach/r8a7740.h>
 #include <mach/irqs.h>
 
 #include "core.h"
 #include "sh_pfc.h"
 
 #define CPU_ALL_PORT(fn, pfx, sfx)					\
-	PORT_10(fn, pfx, sfx),		PORT_90(fn, pfx, sfx),		\
-	PORT_10(fn, pfx##10, sfx),	PORT_90(fn, pfx##1, sfx),	\
-	PORT_10(fn, pfx##20, sfx),					\
-	PORT_1(fn, pfx##210, sfx),	PORT_1(fn, pfx##211, sfx)
-
-#undef _GPIO_PORT
-#define _GPIO_PORT(gpio, sfx)						\
-	[gpio] = {							\
-		.name = __stringify(PORT##gpio),			\
-		.enum_id = PORT##gpio##_DATA,				\
-	}
+	PORT_10(0,  fn, pfx, sfx),	PORT_90(0,   fn, pfx, sfx),	\
+	PORT_10(100, fn, pfx##10, sfx),	PORT_90(100, fn, pfx##1, sfx),	\
+	PORT_10(200, fn, pfx##20, sfx),					\
+	PORT_1(210, fn, pfx##210, sfx),	PORT_1(211, fn, pfx##211, sfx)
 
 #define IRQC_PIN_MUX(irq, pin)						\
 static const unsigned int intc_irq##irq##_pins[] = {			\
@@ -590,11 +582,8 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define _PORT_DATA(pfx, sfx)	PORT_DATA_IO(pfx)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_PORT_DATA, , unused)
-
-static const pinmux_enum_t pinmux_data[] = {
-	PINMUX_DATA_GP_ALL(),
+static const u16 pinmux_data[] = {
+	PINMUX_DATA_ALL(),
 
 	/* Port0 */
 	PINMUX_DATA(DBGMDT2_MARK,		PORT0_FN1),
@@ -1537,13 +1526,6 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(TRACEAUD_FROM_MEMC_MARK,			MSEL5CR_30_1,	MSEL5CR_29_0),
 };
 
-#define R8A7740_PIN(pin, cfgs)						\
-	{								\
-		.name = __stringify(PORT##pin),				\
-		.enum_id = PORT##pin##_DATA,				\
-		.configs = cfgs,					\
-	}
-
 #define __I		(SH_PFC_PIN_CFG_INPUT)
 #define __O		(SH_PFC_PIN_CFG_OUTPUT)
 #define __IO		(SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
@@ -1551,15 +1533,15 @@ static const pinmux_enum_t pinmux_data[] = {
 #define __PU		(SH_PFC_PIN_CFG_PULL_UP)
 #define __PUD		(SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
 
-#define R8A7740_PIN_I_PD(pin)		R8A7740_PIN(pin, __I | __PD)
-#define R8A7740_PIN_I_PU(pin)		R8A7740_PIN(pin, __I | __PU)
-#define R8A7740_PIN_I_PU_PD(pin)		R8A7740_PIN(pin, __I | __PUD)
-#define R8A7740_PIN_IO(pin)		R8A7740_PIN(pin, __IO)
-#define R8A7740_PIN_IO_PD(pin)		R8A7740_PIN(pin, __IO | __PD)
-#define R8A7740_PIN_IO_PU(pin)		R8A7740_PIN(pin, __IO | __PU)
-#define R8A7740_PIN_IO_PU_PD(pin)	R8A7740_PIN(pin, __IO | __PUD)
-#define R8A7740_PIN_O(pin)		R8A7740_PIN(pin, __O)
-#define R8A7740_PIN_O_PU_PD(pin)		R8A7740_PIN(pin, __O | __PUD)
+#define R8A7740_PIN_I_PD(pin)		SH_PFC_PIN_CFG(pin, __I | __PD)
+#define R8A7740_PIN_I_PU(pin)		SH_PFC_PIN_CFG(pin, __I | __PU)
+#define R8A7740_PIN_I_PU_PD(pin)	SH_PFC_PIN_CFG(pin, __I | __PUD)
+#define R8A7740_PIN_IO(pin)		SH_PFC_PIN_CFG(pin, __IO)
+#define R8A7740_PIN_IO_PD(pin)		SH_PFC_PIN_CFG(pin, __IO | __PD)
+#define R8A7740_PIN_IO_PU(pin)		SH_PFC_PIN_CFG(pin, __IO | __PU)
+#define R8A7740_PIN_IO_PU_PD(pin)	SH_PFC_PIN_CFG(pin, __IO | __PUD)
+#define R8A7740_PIN_O(pin)		SH_PFC_PIN_CFG(pin, __O)
+#define R8A7740_PIN_O_PU_PD(pin)	SH_PFC_PIN_CFG(pin, __O | __PUD)
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* Table 56-1 (I/O and Pull U/D) */
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
index f903910..428d2a6 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -23,26 +23,6 @@
 #include <linux/kernel.h>
 #include "sh_pfc.h"
 
-#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
-
-#define PORT_GP_32(bank, fn, sfx)					\
-	PORT_GP_1(bank, 0,  fn, sfx), PORT_GP_1(bank, 1,  fn, sfx),	\
-	PORT_GP_1(bank, 2,  fn, sfx), PORT_GP_1(bank, 3,  fn, sfx),	\
-	PORT_GP_1(bank, 4,  fn, sfx), PORT_GP_1(bank, 5,  fn, sfx),	\
-	PORT_GP_1(bank, 6,  fn, sfx), PORT_GP_1(bank, 7,  fn, sfx),	\
-	PORT_GP_1(bank, 8,  fn, sfx), PORT_GP_1(bank, 9,  fn, sfx),	\
-	PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx),	\
-	PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx),	\
-	PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx),	\
-	PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx),	\
-	PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx),	\
-	PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx),	\
-	PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx),	\
-	PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx),	\
-	PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx),	\
-	PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx),	\
-	PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
-
 #define PORT_GP_27(bank, fn, sfx)					\
 	PORT_GP_1(bank, 0,  fn, sfx), PORT_GP_1(bank, 1,  fn, sfx),	\
 	PORT_GP_1(bank, 2,  fn, sfx), PORT_GP_1(bank, 3,  fn, sfx),	\
@@ -66,26 +46,6 @@
 	PORT_GP_32(3, fn, sfx),		\
 	PORT_GP_27(4, fn, sfx)
 
-#define _GP_PORT_ALL(bank, pin, name, sfx)	name##_##sfx
-
-#define _GP_GPIO(bank, pin, _name, sfx)		\
-	[RCAR_GP_PIN(bank, pin)] = {		\
-		.name = __stringify(_name),	\
-		.enum_id = _name##_DATA,	\
-	}
-
-#define _GP_DATA(bank, pin, name, sfx)		\
-	PINMUX_DATA(name##_DATA, name##_FN)
-
-#define GP_ALL(str)		CPU_ALL_PORT(_GP_PORT_ALL, str)
-#define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, unused)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, unused)
-
-#define PINMUX_IPSR_NOGP(ispr, fn)	PINMUX_DATA(fn##_MARK, FN_##fn)
-#define PINMUX_IPSR_DATA(ipsr, fn)	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)
-#define PINMUX_IPSR_MSEL(ipsr, fn, ms)	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr, FN_##ms)
-#define PINMUX_IPSR_NOGM(ispr, fn, ms)	PINMUX_DATA(fn##_MARK, FN_##fn,            FN_##ms)
-
 enum {
 	PINMUX_RESERVED = 0,
 
@@ -579,7 +539,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
 
 	PINMUX_DATA(PENC0_MARK,		FN_PENC0),
@@ -1294,16 +1254,21 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MSEL(IP10_24_22,	CAN_CLK_C,	SEL_CANCLK_C),
 };
 
-static struct sh_pfc_pin pinmux_pins[] = {
-	PINMUX_GPIO_GP_ALL(),
-};
-
 /* Pin numbers for pins without a corresponding GPIO port number are computed
  * from the row and column numbers with a 1000 offset to avoid collisions with
  * GPIO port numbers.
  */
 #define PIN_NUMBER(row, col)		(1000+((row)-1)*25+(col)-1)
 
+static struct sh_pfc_pin pinmux_pins[] = {
+	PINMUX_GPIO_GP_ALL(),
+
+	/* Pins not associated with a GPIO port */
+	SH_PFC_PIN_NAMED(3, 20, C20),
+	SH_PFC_PIN_NAMED(20, 1, T1),
+	SH_PFC_PIN_NAMED(25, 2, Y2),
+};
+
 /* - macro */
 #define SH_PFC_PINS(name, args...) \
 	static const unsigned int name ##_pins[] = { args }
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
index 8e22ca6..d3e94e3 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
@@ -24,51 +24,13 @@
 
 #include "sh_pfc.h"
 
-#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
-
-#define PORT_GP_32(bank, fn, sfx)					\
-	PORT_GP_1(bank, 0,  fn, sfx), PORT_GP_1(bank, 1,  fn, sfx),	\
-	PORT_GP_1(bank, 2,  fn, sfx), PORT_GP_1(bank, 3,  fn, sfx),	\
-	PORT_GP_1(bank, 4,  fn, sfx), PORT_GP_1(bank, 5,  fn, sfx),	\
-	PORT_GP_1(bank, 6,  fn, sfx), PORT_GP_1(bank, 7,  fn, sfx),	\
-	PORT_GP_1(bank, 8,  fn, sfx), PORT_GP_1(bank, 9,  fn, sfx),	\
-	PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx),	\
-	PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx),	\
-	PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx),	\
-	PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx),	\
-	PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx),	\
-	PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx),	\
-	PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx),	\
-	PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx),	\
-	PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx),	\
-	PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx),	\
-	PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
-
-#define PORT_GP_32_9(bank, fn, sfx)					\
+#define PORT_GP_9(bank, fn, sfx)					\
 	PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx),	\
 	PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx),	\
 	PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx),	\
 	PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx),	\
 	PORT_GP_1(bank, 8, fn, sfx)
 
-#define PORT_GP_32_REV(bank, fn, sfx)					\
-	PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx),	\
-	PORT_GP_1(bank, 29, fn, sfx), PORT_GP_1(bank, 28, fn, sfx),	\
-	PORT_GP_1(bank, 27, fn, sfx), PORT_GP_1(bank, 26, fn, sfx),	\
-	PORT_GP_1(bank, 25, fn, sfx), PORT_GP_1(bank, 24, fn, sfx),	\
-	PORT_GP_1(bank, 23, fn, sfx), PORT_GP_1(bank, 22, fn, sfx),	\
-	PORT_GP_1(bank, 21, fn, sfx), PORT_GP_1(bank, 20, fn, sfx),	\
-	PORT_GP_1(bank, 19, fn, sfx), PORT_GP_1(bank, 18, fn, sfx),	\
-	PORT_GP_1(bank, 17, fn, sfx), PORT_GP_1(bank, 16, fn, sfx),	\
-	PORT_GP_1(bank, 15, fn, sfx), PORT_GP_1(bank, 14, fn, sfx),	\
-	PORT_GP_1(bank, 13, fn, sfx), PORT_GP_1(bank, 12, fn, sfx),	\
-	PORT_GP_1(bank, 11, fn, sfx), PORT_GP_1(bank, 10, fn, sfx),	\
-	PORT_GP_1(bank, 9,  fn, sfx), PORT_GP_1(bank, 8,  fn, sfx),	\
-	PORT_GP_1(bank, 7,  fn, sfx), PORT_GP_1(bank, 6,  fn, sfx),	\
-	PORT_GP_1(bank, 5,  fn, sfx), PORT_GP_1(bank, 4,  fn, sfx),	\
-	PORT_GP_1(bank, 3,  fn, sfx), PORT_GP_1(bank, 2,  fn, sfx),	\
-	PORT_GP_1(bank, 1,  fn, sfx), PORT_GP_1(bank, 0,  fn, sfx)
-
 #define CPU_ALL_PORT(fn, sfx)						\
 	PORT_GP_32(0, fn, sfx),						\
 	PORT_GP_32(1, fn, sfx),						\
@@ -76,26 +38,7 @@
 	PORT_GP_32(3, fn, sfx),						\
 	PORT_GP_32(4, fn, sfx),						\
 	PORT_GP_32(5, fn, sfx),						\
-	PORT_GP_32_9(6, fn, sfx)
-
-#define _GP_PORT_ALL(bank, pin, name, sfx)	name##_##sfx
-
-#define _GP_GPIO(bank, pin, _name, sfx)					\
-	[RCAR_GP_PIN(bank, pin)] = {					\
-		.name = __stringify(_name),				\
-		.enum_id = _name##_DATA,				\
-	}
-
-#define _GP_DATA(bank, pin, name, sfx)					\
-	PINMUX_DATA(name##_DATA, name##_FN)
-
-#define GP_ALL(str)		CPU_ALL_PORT(_GP_PORT_ALL, str)
-#define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, unused)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, unused)
-
-#define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn)
-#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \
-							  FN_##ipsr, FN_##fn)
+	PORT_GP_9(6, fn, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
@@ -664,7 +607,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
 
 	PINMUX_DATA(AVS1_MARK, FN_AVS1),
@@ -1731,6 +1674,79 @@ static const unsigned int hspi2_b_pins[] = {
 static const unsigned int hspi2_b_mux[] = {
 	HSPI_CLK2_B_MARK, HSPI_CS2_B_MARK, HSPI_RX2_B_MARK, HSPI_TX2_B_MARK,
 };
+/* - I2C1 ------------------------------------------------------------------ */
+static const unsigned int i2c1_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(0, 27), RCAR_GP_PIN(0, 28),
+};
+static const unsigned int i2c1_mux[] = {
+	SCL1_MARK, SDA1_MARK,
+};
+static const unsigned int i2c1_b_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 11),
+};
+static const unsigned int i2c1_b_mux[] = {
+	SCL1_B_MARK, SDA1_B_MARK,
+};
+static const unsigned int i2c1_c_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13),
+};
+static const unsigned int i2c1_c_mux[] = {
+	SCL1_C_MARK, SDA1_C_MARK,
+};
+static const unsigned int i2c1_d_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 27),
+};
+static const unsigned int i2c1_d_mux[] = {
+	SCL1_D_MARK, SDA1_D_MARK,
+};
+/* - I2C2 ------------------------------------------------------------------ */
+static const unsigned int i2c2_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(0, 25), RCAR_GP_PIN(0, 26),
+};
+static const unsigned int i2c2_mux[] = {
+	SCL2_MARK, SDA2_MARK,
+};
+static const unsigned int i2c2_b_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(1, 18), RCAR_GP_PIN(1, 19),
+};
+static const unsigned int i2c2_b_mux[] = {
+	SCL2_B_MARK, SDA2_B_MARK,
+};
+static const unsigned int i2c2_c_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(0, 31), RCAR_GP_PIN(0, 30),
+};
+static const unsigned int i2c2_c_mux[] = {
+	SCL2_C_MARK, SDA2_C_MARK,
+};
+static const unsigned int i2c2_d_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 25),
+};
+static const unsigned int i2c2_d_mux[] = {
+	SCL2_D_MARK, SDA2_D_MARK,
+};
+/* - I2C3 ------------------------------------------------------------------ */
+static const unsigned int i2c3_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(3, 0), RCAR_GP_PIN(2, 30),
+};
+static const unsigned int i2c3_mux[] = {
+	SCL3_MARK, SDA3_MARK,
+};
+static const unsigned int i2c3_b_pins[] = {
+	/* SCL, SDA, */
+	RCAR_GP_PIN(0, 29), RCAR_GP_PIN(0, 30),
+};
+static const unsigned int i2c3_b_mux[] = {
+	SCL3_B_MARK, SDA3_B_MARK,
+};
 /* - INTC ------------------------------------------------------------------- */
 static const unsigned int intc_irq0_pins[] = {
 	/* IRQ */
@@ -2600,6 +2616,16 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(hspi1_d),
 	SH_PFC_PIN_GROUP(hspi2),
 	SH_PFC_PIN_GROUP(hspi2_b),
+	SH_PFC_PIN_GROUP(i2c1),
+	SH_PFC_PIN_GROUP(i2c1_b),
+	SH_PFC_PIN_GROUP(i2c1_c),
+	SH_PFC_PIN_GROUP(i2c1_d),
+	SH_PFC_PIN_GROUP(i2c2),
+	SH_PFC_PIN_GROUP(i2c2_b),
+	SH_PFC_PIN_GROUP(i2c2_c),
+	SH_PFC_PIN_GROUP(i2c2_d),
+	SH_PFC_PIN_GROUP(i2c3),
+	SH_PFC_PIN_GROUP(i2c3_b),
 	SH_PFC_PIN_GROUP(intc_irq0),
 	SH_PFC_PIN_GROUP(intc_irq0_b),
 	SH_PFC_PIN_GROUP(intc_irq1),
@@ -2760,6 +2786,25 @@ static const char * const hspi2_groups[] = {
 	"hspi2_b",
 };
 
+static const char * const i2c1_groups[] = {
+	"i2c1",
+	"i2c1_b",
+	"i2c1_c",
+	"i2c1_d",
+};
+
+static const char * const i2c2_groups[] = {
+	"i2c2",
+	"i2c2_b",
+	"i2c2_c",
+	"i2c2_d",
+};
+
+static const char * const i2c3_groups[] = {
+	"i2c3",
+	"i2c3_b",
+};
+
 static const char * const intc_groups[] = {
 	"intc_irq0",
 	"intc_irq0_b",
@@ -2943,6 +2988,9 @@ static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(hspi0),
 	SH_PFC_FUNCTION(hspi1),
 	SH_PFC_FUNCTION(hspi2),
+	SH_PFC_FUNCTION(i2c1),
+	SH_PFC_FUNCTION(i2c2),
+	SH_PFC_FUNCTION(i2c3),
 	SH_PFC_FUNCTION(intc),
 	SH_PFC_FUNCTION(lbsc),
 	SH_PFC_FUNCTION(mmc0),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index 14f3ec2..763c031 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -27,44 +27,6 @@
 #include "core.h"
 #include "sh_pfc.h"
 
-#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
-
-#define PORT_GP_32(bank, fn, sfx)					\
-	PORT_GP_1(bank, 0,  fn, sfx), PORT_GP_1(bank, 1,  fn, sfx),	\
-	PORT_GP_1(bank, 2,  fn, sfx), PORT_GP_1(bank, 3,  fn, sfx),	\
-	PORT_GP_1(bank, 4,  fn, sfx), PORT_GP_1(bank, 5,  fn, sfx),	\
-	PORT_GP_1(bank, 6,  fn, sfx), PORT_GP_1(bank, 7,  fn, sfx),	\
-	PORT_GP_1(bank, 8,  fn, sfx), PORT_GP_1(bank, 9,  fn, sfx),	\
-	PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx),	\
-	PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx),	\
-	PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx),	\
-	PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx),	\
-	PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx),	\
-	PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx),	\
-	PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx),	\
-	PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx),	\
-	PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx),	\
-	PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx),	\
-	PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
-
-#define PORT_GP_32_REV(bank, fn, sfx)					\
-	PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx),	\
-	PORT_GP_1(bank, 29, fn, sfx), PORT_GP_1(bank, 28, fn, sfx),	\
-	PORT_GP_1(bank, 27, fn, sfx), PORT_GP_1(bank, 26, fn, sfx),	\
-	PORT_GP_1(bank, 25, fn, sfx), PORT_GP_1(bank, 24, fn, sfx),	\
-	PORT_GP_1(bank, 23, fn, sfx), PORT_GP_1(bank, 22, fn, sfx),	\
-	PORT_GP_1(bank, 21, fn, sfx), PORT_GP_1(bank, 20, fn, sfx),	\
-	PORT_GP_1(bank, 19, fn, sfx), PORT_GP_1(bank, 18, fn, sfx),	\
-	PORT_GP_1(bank, 17, fn, sfx), PORT_GP_1(bank, 16, fn, sfx),	\
-	PORT_GP_1(bank, 15, fn, sfx), PORT_GP_1(bank, 14, fn, sfx),	\
-	PORT_GP_1(bank, 13, fn, sfx), PORT_GP_1(bank, 12, fn, sfx),	\
-	PORT_GP_1(bank, 11, fn, sfx), PORT_GP_1(bank, 10, fn, sfx),	\
-	PORT_GP_1(bank, 9,  fn, sfx), PORT_GP_1(bank, 8,  fn, sfx),	\
-	PORT_GP_1(bank, 7,  fn, sfx), PORT_GP_1(bank, 6,  fn, sfx),	\
-	PORT_GP_1(bank, 5,  fn, sfx), PORT_GP_1(bank, 4,  fn, sfx),	\
-	PORT_GP_1(bank, 3,  fn, sfx), PORT_GP_1(bank, 2,  fn, sfx),	\
-	PORT_GP_1(bank, 1,  fn, sfx), PORT_GP_1(bank, 0,  fn, sfx)
-
 #define CPU_ALL_PORT(fn, sfx)						\
 	PORT_GP_32(0, fn, sfx),						\
 	PORT_GP_32(1, fn, sfx),						\
@@ -73,25 +35,6 @@
 	PORT_GP_32(4, fn, sfx),						\
 	PORT_GP_32(5, fn, sfx)
 
-#define _GP_PORT_ALL(bank, pin, name, sfx)	name##_##sfx
-
-#define _GP_GPIO(bank, pin, _name, sfx)					\
-	[(bank * 32) + pin] = {						\
-		.name = __stringify(_name),				\
-		.enum_id = _name##_DATA,				\
-	}
-
-#define _GP_DATA(bank, pin, name, sfx)					\
-	PINMUX_DATA(name##_DATA, name##_FN)
-
-#define GP_ALL(str)		CPU_ALL_PORT(_GP_PORT_ALL, str)
-#define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, unused)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, unused)
-
-#define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn)
-#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \
-							  FN_##ipsr, FN_##fn)
-
 enum {
 	PINMUX_RESERVED = 0,
 
@@ -168,18 +111,18 @@ enum {
 	FN_VI0_R0, FN_VI0_R0_B, FN_RX0_B, FN_D5,
 	FN_SCIFB1_TXD_F, FN_SCIFB0_TXD_C, FN_VI3_DATA5,
 	FN_VI0_R1, FN_VI0_R1_B, FN_TX0_B, FN_D6,
-	FN_SCL2_C, FN_VI3_DATA6, FN_VI0_R2, FN_VI0_R2_B,
-	FN_SCL2_CIS_C, FN_D7, FN_AD_DI_B, FN_SDA2_C,
-	FN_VI3_DATA7, FN_VI0_R3, FN_VI0_R3_B, FN_SDA2_CIS_C,
-	FN_D8, FN_SCIFA1_SCK_C, FN_AVB_TXD0, FN_MII_TXD0,
+	FN_IIC2_SCL_C, FN_VI3_DATA6, FN_VI0_R2, FN_VI0_R2_B,
+	FN_I2C2_SCL_C, FN_D7, FN_AD_DI_B, FN_IIC2_SDA_C,
+	FN_VI3_DATA7, FN_VI0_R3, FN_VI0_R3_B, FN_I2C2_SDA_C, FN_TCLK1,
+	FN_D8, FN_SCIFA1_SCK_C, FN_AVB_TXD0,
 	FN_VI0_G0, FN_VI0_G0_B, FN_VI2_DATA0_VI2_B0,
 
 	/* IPSR1 */
-	FN_D9, FN_SCIFA1_RXD_C, FN_AVB_TXD1, FN_MII_TXD1,
+	FN_D9, FN_SCIFA1_RXD_C, FN_AVB_TXD1,
 	FN_VI0_G1, FN_VI0_G1_B, FN_VI2_DATA1_VI2_B1, FN_D10,
-	FN_SCIFA1_TXD_C, FN_AVB_TXD2, FN_MII_TXD2,
+	FN_SCIFA1_TXD_C, FN_AVB_TXD2,
 	FN_VI0_G2, FN_VI0_G2_B, FN_VI2_DATA2_VI2_B2, FN_D11,
-	FN_SCIFA1_CTS_N_C, FN_AVB_TXD3, FN_MII_TXD3,
+	FN_SCIFA1_CTS_N_C, FN_AVB_TXD3,
 	FN_VI0_G3, FN_VI0_G3_B, FN_VI2_DATA3_VI2_B3,
 	FN_D12, FN_SCIFA1_RTS_N_C, FN_AVB_TXD4,
 	FN_VI0_HSYNC_N, FN_VI0_HSYNC_N_B, FN_VI2_DATA4_VI2_B4,
@@ -198,9 +141,9 @@ enum {
 	FN_A6, FN_SCIFA1_RTS_N_B, FN_TPU0TO2, FN_A7,
 	FN_SCIFA1_SCK_B, FN_AUDIO_CLKOUT_B, FN_TPU0TO3,
 	FN_A8, FN_SCIFA1_RXD_B, FN_SSI_SCK5_B, FN_VI0_R4,
-	FN_VI0_R4_B, FN_SCIFB2_RXD_C, FN_VI2_DATA0_VI2_B0_B,
+	FN_VI0_R4_B, FN_SCIFB2_RXD_C, FN_RX2_B, FN_VI2_DATA0_VI2_B0_B,
 	FN_A9, FN_SCIFA1_CTS_N_B, FN_SSI_WS5_B, FN_VI0_R5,
-	FN_VI0_R5_B, FN_SCIFB2_TXD_C, FN_VI2_DATA1_VI2_B1_B,
+	FN_VI0_R5_B, FN_SCIFB2_TXD_C, FN_TX2_B, FN_VI2_DATA1_VI2_B1_B,
 	FN_A10, FN_SSI_SDATA5_B, FN_MSIOF2_SYNC, FN_VI0_R6,
 	FN_VI0_R6_B, FN_VI2_DATA2_VI2_B2_B,
 
@@ -239,11 +182,11 @@ enum {
 	/* IPSR5 */
 	FN_EX_CS3_N, FN_GPS_MAG, FN_VI3_FIELD, FN_VI1_G1, FN_VI1_G1_B,
 	FN_VI2_R3, FN_EX_CS4_N, FN_MSIOF1_SCK_B, FN_VI3_HSYNC_N,
-	FN_VI2_HSYNC_N, FN_SCL1, FN_VI2_HSYNC_N_B,
-	FN_INTC_EN0_N, FN_SCL1_CIS, FN_EX_CS5_N, FN_CAN0_RX,
+	FN_VI2_HSYNC_N, FN_IIC1_SCL, FN_VI2_HSYNC_N_B,
+	FN_INTC_EN0_N, FN_I2C1_SCL, FN_EX_CS5_N, FN_CAN0_RX,
 	FN_MSIOF1_RXD_B, FN_VI3_VSYNC_N, FN_VI1_G2,
-	FN_VI1_G2_B, FN_VI2_R4, FN_SDA1, FN_INTC_EN1_N,
-	FN_SDA1_CIS, FN_BS_N, FN_IETX, FN_HTX1_B,
+	FN_VI1_G2_B, FN_VI2_R4, FN_IIC1_SDA, FN_INTC_EN1_N,
+	FN_I2C1_SDA, FN_BS_N, FN_IETX, FN_HTX1_B,
 	FN_CAN1_TX, FN_DRACK0, FN_IETX_C, FN_RD_N,
 	FN_CAN0_TX, FN_SCIFA0_SCK_B, FN_RD_WR_N, FN_VI1_G3,
 	FN_VI1_G3_B, FN_VI2_R5, FN_SCIFA0_RXD_B,
@@ -266,29 +209,29 @@ enum {
 	FN_DREQ2_N, FN_HSCK1_B, FN_HCTS0_N_B,
 	FN_MSIOF0_TXD_B, FN_DACK2, FN_IRQ2, FN_INTC_IRQ2_N,
 	FN_SSI_SDATA6_B, FN_HRTS0_N_B, FN_MSIOF0_RXD_B,
-	FN_ETH_CRS_DV, FN_RMII_CRS_DV, FN_STP_ISCLK_0_B,
-	FN_TS_SDEN0_D, FN_GLO_Q0_C, FN_SCL2_E,
-	FN_SCL2_CIS_E, FN_ETH_RX_ER, FN_RMII_RX_ER,
+	FN_ETH_CRS_DV, FN_STP_ISCLK_0_B,
+	FN_TS_SDEN0_D, FN_GLO_Q0_C, FN_IIC2_SCL_E,
+	FN_I2C2_SCL_E, FN_ETH_RX_ER,
 	FN_STP_ISD_0_B, FN_TS_SPSYNC0_D, FN_GLO_Q1_C,
-	FN_SDA2_E, FN_SDA2_CIS_E, FN_ETH_RXD0, FN_RMII_RXD0,
+	FN_IIC2_SDA_E, FN_I2C2_SDA_E, FN_ETH_RXD0,
 	FN_STP_ISEN_0_B, FN_TS_SDAT0_D, FN_GLO_I0_C,
 	FN_SCIFB1_SCK_G, FN_SCK1_E, FN_ETH_RXD1,
-	FN_RMII_RXD1, FN_HRX0_E, FN_STP_ISSYNC_0_B,
+	FN_HRX0_E, FN_STP_ISSYNC_0_B,
 	FN_TS_SCK0_D, FN_GLO_I1_C, FN_SCIFB1_RXD_G,
-	FN_RX1_E, FN_ETH_LINK, FN_RMII_LINK, FN_HTX0_E,
+	FN_RX1_E, FN_ETH_LINK, FN_HTX0_E,
 	FN_STP_IVCXO27_0_B, FN_SCIFB1_TXD_G, FN_TX1_E,
-	FN_ETH_REF_CLK, FN_RMII_REF_CLK, FN_HCTS0_N_E,
+	FN_ETH_REF_CLK, FN_HCTS0_N_E,
 	FN_STP_IVCXO27_1_B, FN_HRX0_F,
 
 	/* IPSR7 */
-	FN_ETH_MDIO, FN_RMII_MDIO, FN_HRTS0_N_E,
+	FN_ETH_MDIO, FN_HRTS0_N_E,
 	FN_SIM0_D_C, FN_HCTS0_N_F, FN_ETH_TXD1,
-	FN_RMII_TXD1, FN_HTX0_F, FN_BPFCLK_G, FN_RDS_CLK_F,
-	FN_ETH_TX_EN, FN_RMII_TX_EN, FN_SIM0_CLK_C,
-	FN_HRTS0_N_F, FN_ETH_MAGIC, FN_RMII_MAGIC,
-	FN_SIM0_RST_C, FN_ETH_TXD0, FN_RMII_TXD0,
+	FN_HTX0_F, FN_BPFCLK_G,
+	FN_ETH_TX_EN, FN_SIM0_CLK_C,
+	FN_HRTS0_N_F, FN_ETH_MAGIC,
+	FN_SIM0_RST_C, FN_ETH_TXD0,
 	FN_STP_ISCLK_1_B, FN_TS_SDEN1_C, FN_GLO_SCLK_C,
-	FN_ETH_MDC, FN_RMII_MDC, FN_STP_ISD_1_B,
+	FN_ETH_MDC, FN_STP_ISD_1_B,
 	FN_TS_SPSYNC1_C, FN_GLO_SDATA_C, FN_PWM0,
 	FN_SCIFA2_SCK_C, FN_STP_ISEN_1_B, FN_TS_SDAT1_C,
 	FN_GLO_SS_C, FN_PWM1, FN_SCIFA2_TXD_C,
@@ -296,26 +239,25 @@ enum {
 	FN_PCMOE_N, FN_PWM2, FN_PWMFSW0, FN_SCIFA2_RXD_C,
 	FN_PCMWE_N, FN_IECLK_C, FN_DU1_DOTCLKIN,
 	FN_AUDIO_CLKC, FN_AUDIO_CLKOUT_C, FN_VI0_CLK,
-	FN_ATACS00_N, FN_AVB_RXD1, FN_MII_RXD1,
+	FN_ATACS00_N, FN_AVB_RXD1,
 	FN_VI0_DATA0_VI0_B0, FN_ATACS10_N, FN_AVB_RXD2,
-	FN_MII_RXD2,
 
 	/* IPSR8 */
 	FN_VI0_DATA1_VI0_B1, FN_ATARD0_N, FN_AVB_RXD3,
-	FN_MII_RXD3, FN_VI0_DATA2_VI0_B2, FN_ATAWR0_N,
+	FN_VI0_DATA2_VI0_B2, FN_ATAWR0_N,
 	FN_AVB_RXD4, FN_VI0_DATA3_VI0_B3, FN_ATADIR0_N,
 	FN_AVB_RXD5, FN_VI0_DATA4_VI0_B4, FN_ATAG0_N,
 	FN_AVB_RXD6, FN_VI0_DATA5_VI0_B5, FN_EX_WAIT1,
 	FN_AVB_RXD7, FN_VI0_DATA6_VI0_B6, FN_AVB_RX_ER,
-	FN_MII_RX_ER, FN_VI0_DATA7_VI0_B7, FN_AVB_RX_CLK,
-	FN_MII_RX_CLK, FN_VI1_CLK, FN_AVB_RX_DV,
-	FN_MII_RX_DV, FN_VI1_DATA0_VI1_B0, FN_SCIFA1_SCK_D,
-	FN_AVB_CRS, FN_MII_CRS, FN_VI1_DATA1_VI1_B1,
-	FN_SCIFA1_RXD_D, FN_AVB_MDC, FN_MII_MDC,
+	FN_VI0_DATA7_VI0_B7, FN_AVB_RX_CLK,
+	FN_VI1_CLK, FN_AVB_RX_DV,
+	FN_VI1_DATA0_VI1_B0, FN_SCIFA1_SCK_D,
+	FN_AVB_CRS, FN_VI1_DATA1_VI1_B1,
+	FN_SCIFA1_RXD_D, FN_AVB_MDC,
 	FN_VI1_DATA2_VI1_B2, FN_SCIFA1_TXD_D, FN_AVB_MDIO,
-	FN_MII_MDIO, FN_VI1_DATA3_VI1_B3, FN_SCIFA1_CTS_N_D,
+	FN_VI1_DATA3_VI1_B3, FN_SCIFA1_CTS_N_D,
 	FN_AVB_GTX_CLK, FN_VI1_DATA4_VI1_B4, FN_SCIFA1_RTS_N_D,
-	FN_AVB_MAGIC, FN_MII_MAGIC, FN_VI1_DATA5_VI1_B5,
+	FN_AVB_MAGIC, FN_VI1_DATA5_VI1_B5,
 	FN_AVB_PHY_INT, FN_VI1_DATA6_VI1_B6, FN_AVB_GTXREFCLK,
 	FN_SD0_CLK, FN_VI1_DATA0_VI1_B0_B, FN_SD0_CMD,
 	FN_SCIFB1_SCK_B, FN_VI1_DATA1_VI1_B1_B,
@@ -326,26 +268,26 @@ enum {
 	FN_SD0_DAT2, FN_SCIFB1_CTS_N_B, FN_VI1_DATA4_VI1_B4_B,
 	FN_SD0_DAT3, FN_SCIFB1_RTS_N_B, FN_VI1_DATA5_VI1_B5_B,
 	FN_SD0_CD, FN_MMC0_D6, FN_TS_SDEN0_B, FN_USB0_EXTP,
-	FN_GLO_SCLK, FN_VI1_DATA6_VI1_B6_B, FN_SCL1_B,
-	FN_SCL1_CIS_B, FN_VI2_DATA6_VI2_B6_B, FN_SD0_WP,
+	FN_GLO_SCLK, FN_VI1_DATA6_VI1_B6_B, FN_IIC1_SCL_B,
+	FN_I2C1_SCL_B, FN_VI2_DATA6_VI2_B6_B, FN_SD0_WP,
 	FN_MMC0_D7, FN_TS_SPSYNC0_B, FN_USB0_IDIN,
-	FN_GLO_SDATA, FN_VI1_DATA7_VI1_B7_B, FN_SDA1_B,
-	FN_SDA1_CIS_B, FN_VI2_DATA7_VI2_B7_B, FN_SD1_CLK,
-	FN_AVB_TX_EN, FN_MII_TX_EN, FN_SD1_CMD,
-	FN_AVB_TX_ER, FN_MII_TX_ER, FN_SCIFB0_SCK_B,
-	FN_SD1_DAT0, FN_AVB_TX_CLK, FN_MII_TX_CLK,
+	FN_GLO_SDATA, FN_VI1_DATA7_VI1_B7_B, FN_IIC1_SDA_B,
+	FN_I2C1_SDA_B, FN_VI2_DATA7_VI2_B7_B, FN_SD1_CLK,
+	FN_AVB_TX_EN, FN_SD1_CMD,
+	FN_AVB_TX_ER, FN_SCIFB0_SCK_B,
+	FN_SD1_DAT0, FN_AVB_TX_CLK,
 	FN_SCIFB0_RXD_B, FN_SD1_DAT1, FN_AVB_LINK,
-	FN_MII_LINK, FN_SCIFB0_TXD_B, FN_SD1_DAT2,
-	FN_AVB_COL, FN_MII_COL, FN_SCIFB0_CTS_N_B,
-	FN_SD1_DAT3, FN_AVB_RXD0, FN_MII_RXD0,
+	FN_SCIFB0_TXD_B, FN_SD1_DAT2,
+	FN_AVB_COL, FN_SCIFB0_CTS_N_B,
+	FN_SD1_DAT3, FN_AVB_RXD0,
 	FN_SCIFB0_RTS_N_B, FN_SD1_CD, FN_MMC1_D6,
 	FN_TS_SDEN1, FN_USB1_EXTP, FN_GLO_SS, FN_VI0_CLK_B,
-	FN_SCL2_D, FN_SCL2_CIS_D, FN_SIM0_CLK_B,
+	FN_IIC2_SCL_D, FN_I2C2_SCL_D, FN_SIM0_CLK_B,
 	FN_VI3_CLK_B,
 
 	/* IPSR10 */
 	FN_SD1_WP, FN_MMC1_D7, FN_TS_SPSYNC1, FN_USB1_IDIN,
-	FN_GLO_RFON, FN_VI1_CLK_B, FN_SDA2_D, FN_SDA2_CIS_D,
+	FN_GLO_RFON, FN_VI1_CLK_B, FN_IIC2_SDA_D, FN_I2C2_SDA_D,
 	FN_SIM0_D_B, FN_SD2_CLK, FN_MMC0_CLK, FN_SIM0_CLK,
 	FN_VI0_DATA0_VI0_B0_B, FN_TS_SDEN0_C, FN_GLO_SCLK_B,
 	FN_VI3_DATA0_B, FN_SD2_CMD, FN_MMC0_CMD, FN_SIM0_D,
@@ -354,10 +296,10 @@ enum {
 	FN_SD2_DAT0, FN_MMC0_D0, FN_FMCLK_B,
 	FN_VI0_DATA2_VI0_B2_B, FN_SCIFB1_RXD_E, FN_RX1_D,
 	FN_TS_SDAT0_C, FN_GLO_SS_B, FN_VI3_DATA2_B,
-	FN_SD2_DAT1, FN_MMC0_D1, FN_FMIN_B, FN_RDS_DATA,
+	FN_SD2_DAT1, FN_MMC0_D1, FN_FMIN_B,
 	FN_VI0_DATA3_VI0_B3_B, FN_SCIFB1_TXD_E, FN_TX1_D,
 	FN_TS_SCK0_C, FN_GLO_RFON_B, FN_VI3_DATA3_B,
-	FN_SD2_DAT2, FN_MMC0_D2, FN_BPFCLK_B, FN_RDS_CLK,
+	FN_SD2_DAT2, FN_MMC0_D2, FN_BPFCLK_B,
 	FN_VI0_DATA4_VI0_B4_B, FN_HRX0_D, FN_TS_SDEN1_B,
 	FN_GLO_Q0_B, FN_VI3_DATA4_B, FN_SD2_DAT3,
 	FN_MMC0_D3, FN_SIM0_RST, FN_VI0_DATA5_VI0_B5_B,
@@ -378,12 +320,12 @@ enum {
 	FN_SCKZ, FN_SD3_CD, FN_MMC1_D4, FN_TS_SDAT1,
 	FN_VSP, FN_GLO_Q0, FN_SIM0_RST_B, FN_SD3_WP,
 	FN_MMC1_D5, FN_TS_SCK1, FN_GLO_Q1, FN_FMIN_C,
-	FN_RDS_DATA_B, FN_FMIN_E, FN_RDS_DATA_D, FN_FMIN_F,
-	FN_RDS_DATA_E, FN_MLB_CLK, FN_SCL2_B, FN_SCL2_CIS_B,
-	FN_MLB_SIG, FN_SCIFB1_RXD_D, FN_RX1_C, FN_SDA2_B,
-	FN_SDA2_CIS_B, FN_MLB_DAT, FN_SPV_EVEN,
+	FN_FMIN_E, FN_FMIN_F,
+	FN_MLB_CLK, FN_IIC2_SCL_B, FN_I2C2_SCL_B,
+	FN_MLB_SIG, FN_SCIFB1_RXD_D, FN_RX1_C, FN_IIC2_SDA_B,
+	FN_I2C2_SDA_B, FN_MLB_DAT,
 	FN_SCIFB1_TXD_D, FN_TX1_C, FN_BPFCLK_C,
-	FN_RDS_CLK_B, FN_SSI_SCK0129, FN_CAN_CLK_B,
+	FN_SSI_SCK0129, FN_CAN_CLK_B,
 	FN_MOUT0,
 
 	/* IPSR12 */
@@ -410,12 +352,12 @@ enum {
 	/* IPSR13 */
 	FN_SSI_SDATA5, FN_SCIFB1_TXD, FN_IETX_B, FN_DU2_DR2,
 	FN_LCDOUT2, FN_CAN_DEBUGOUT5, FN_SSI_SCK6,
-	FN_SCIFB1_CTS_N, FN_BPFCLK_D, FN_RDS_CLK_C,
+	FN_SCIFB1_CTS_N, FN_BPFCLK_D,
 	FN_DU2_DR3, FN_LCDOUT3, FN_CAN_DEBUGOUT6,
-	FN_BPFCLK_F, FN_RDS_CLK_E, FN_SSI_WS6,
+	FN_BPFCLK_F, FN_SSI_WS6,
 	FN_SCIFB1_RTS_N, FN_CAN0_TX_D, FN_DU2_DR4,
 	FN_LCDOUT4, FN_CAN_DEBUGOUT7, FN_SSI_SDATA6,
-	FN_FMIN_D, FN_RDS_DATA_C, FN_DU2_DR5, FN_LCDOUT5,
+	FN_FMIN_D, FN_DU2_DR5, FN_LCDOUT5,
 	FN_CAN_DEBUGOUT8, FN_SSI_SCK78, FN_STP_IVCXO27_1,
 	FN_SCK1, FN_SCIFA1_SCK, FN_DU2_DR6, FN_LCDOUT6,
 	FN_CAN_DEBUGOUT9, FN_SSI_WS78, FN_STP_ISCLK_1,
@@ -423,8 +365,8 @@ enum {
 	FN_LCDOUT7, FN_CAN_DEBUGOUT10, FN_SSI_SDATA7,
 	FN_STP_ISD_1, FN_SCIFB2_RXD, FN_SCIFA2_RTS_N,
 	FN_TCLK2, FN_QSTVA_QVS, FN_CAN_DEBUGOUT11,
-	FN_BPFCLK_E, FN_RDS_CLK_D, FN_SSI_SDATA7_B,
-	FN_FMIN_G, FN_RDS_DATA_F, FN_SSI_SDATA8,
+	FN_BPFCLK_E, FN_SSI_SDATA7_B,
+	FN_FMIN_G, FN_SSI_SDATA8,
 	FN_STP_ISEN_1, FN_SCIFB2_TXD, FN_CAN0_TX_C,
 	FN_CAN_DEBUGOUT12, FN_SSI_SDATA8_B, FN_SSI_SDATA9,
 	FN_STP_ISSYNC_1, FN_SCIFB2_CTS_N, FN_SSI_WS1,
@@ -435,29 +377,29 @@ enum {
 	FN_AUDIO_CLKB, FN_SCIF_CLK, FN_CAN0_RX_D,
 	FN_DVC_MUTE, FN_CAN0_RX_C, FN_CAN_DEBUGOUT15,
 	FN_REMOCON, FN_SCIFA0_SCK, FN_HSCK1, FN_SCK0,
-	FN_MSIOF3_SS2, FN_DU2_DG2, FN_LCDOUT10, FN_SDA1_C,
-	FN_SDA1_CIS_C, FN_SCIFA0_RXD, FN_HRX1, FN_RX0,
+	FN_MSIOF3_SS2, FN_DU2_DG2, FN_LCDOUT10, FN_IIC1_SDA_C,
+	FN_I2C1_SDA_C, FN_SCIFA0_RXD, FN_HRX1, FN_RX0,
 	FN_DU2_DR0, FN_LCDOUT0, FN_SCIFA0_TXD, FN_HTX1,
 	FN_TX0, FN_DU2_DR1, FN_LCDOUT1, FN_SCIFA0_CTS_N,
 	FN_HCTS1_N, FN_CTS0_N, FN_MSIOF3_SYNC, FN_DU2_DG3,
-	FN_LCDOUT11, FN_PWM0_B, FN_SCL1_C, FN_SCL1_CIS_C,
-	FN_SCIFA0_RTS_N, FN_HRTS1_N, FN_RTS0_N_TANS,
+	FN_LCDOUT11, FN_PWM0_B, FN_IIC1_SCL_C, FN_I2C1_SCL_C,
+	FN_SCIFA0_RTS_N, FN_HRTS1_N, FN_RTS0_N,
 	FN_MSIOF3_SS1, FN_DU2_DG0, FN_LCDOUT8, FN_PWM1_B,
 	FN_SCIFA1_RXD, FN_AD_DI, FN_RX1,
 	FN_DU2_EXODDF_DU2_ODDF_DISP_CDE, FN_QCPV_QDE,
 	FN_SCIFA1_TXD, FN_AD_DO, FN_TX1, FN_DU2_DG1,
 	FN_LCDOUT9, FN_SCIFA1_CTS_N, FN_AD_CLK,
 	FN_CTS1_N, FN_MSIOF3_RXD, FN_DU0_DOTCLKOUT, FN_QCLK,
-	FN_SCIFA1_RTS_N, FN_AD_NCS_N, FN_RTS1_N_TANS,
+	FN_SCIFA1_RTS_N, FN_AD_NCS_N, FN_RTS1_N,
 	FN_MSIOF3_TXD, FN_DU1_DOTCLKOUT, FN_QSTVB_QVE,
 	FN_HRTS0_N_C,
 
 	/* IPSR15 */
-	FN_SCIFA2_SCK, FN_FMCLK, FN_MSIOF3_SCK, FN_DU2_DG7,
+	FN_SCIFA2_SCK, FN_FMCLK, FN_SCK2, FN_MSIOF3_SCK, FN_DU2_DG7,
 	FN_LCDOUT15, FN_SCIF_CLK_B, FN_SCIFA2_RXD, FN_FMIN,
-	FN_DU2_DB0, FN_LCDOUT16, FN_SCL2, FN_SCL2_CIS,
-	FN_SCIFA2_TXD, FN_BPFCLK, FN_DU2_DB1, FN_LCDOUT17,
-	FN_SDA2, FN_SDA2_CIS, FN_HSCK0, FN_TS_SDEN0,
+	FN_TX2, FN_DU2_DB0, FN_LCDOUT16, FN_IIC2_SCL, FN_I2C2_SCL,
+	FN_SCIFA2_TXD, FN_BPFCLK, FN_RX2, FN_DU2_DB1, FN_LCDOUT17,
+	FN_IIC2_SDA, FN_I2C2_SDA, FN_HSCK0, FN_TS_SDEN0,
 	FN_DU2_DG4, FN_LCDOUT12, FN_HCTS0_N_C, FN_HRX0,
 	FN_DU2_DB2, FN_LCDOUT18, FN_HTX0, FN_DU2_DB3,
 	FN_LCDOUT19, FN_HCTS0_N, FN_SSI_SCK9, FN_DU2_DB4,
@@ -465,7 +407,7 @@ enum {
 	FN_LCDOUT21, FN_MSIOF0_SCK, FN_TS_SDAT0, FN_ADICLK,
 	FN_DU2_DB6, FN_LCDOUT22, FN_MSIOF0_SYNC, FN_TS_SCK0,
 	FN_SSI_SCK2, FN_ADIDATA, FN_DU2_DB7, FN_LCDOUT23,
-	FN_SCIFA2_RXD_B, FN_MSIOF0_SS1, FN_ADICHS0,
+	FN_HRX0_C, FN_MSIOF0_SS1, FN_ADICHS0,
 	FN_DU2_DG5, FN_LCDOUT13, FN_MSIOF0_TXD, FN_ADICHS1,
 	FN_DU2_DG6, FN_LCDOUT14,
 
@@ -473,7 +415,7 @@ enum {
 	FN_MSIOF0_SS2, FN_AUDIO_CLKOUT, FN_ADICHS2,
 	FN_DU2_DISP, FN_QPOLA, FN_HTX0_C, FN_SCIFA2_TXD_B,
 	FN_MSIOF0_RXD, FN_TS_SPSYNC0, FN_SSI_WS2,
-	FN_ADICS_SAMP, FN_DU2_CDE, FN_QPOLB, FN_HRX0_C,
+	FN_ADICS_SAMP, FN_DU2_CDE, FN_QPOLB, FN_SCIFA2_RXD_B,
 	FN_USB1_PWEN, FN_AUDIO_CLKOUT_D, FN_USB1_OVC,
 	FN_TCLK1_B,
 
@@ -508,6 +450,7 @@ enum {
 	FN_SEL_CANCLK_0, FN_SEL_CANCLK_1,
 	FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1, FN_SEL_SCIFA2_2,
 	FN_SEL_CAN1_0, FN_SEL_CAN1_1,
+	FN_SEL_SCIF2_0, FN_SEL_SCIF2_1,
 	FN_SEL_ADI_0, FN_SEL_ADI_1,
 	FN_SEL_SSP_0, FN_SEL_SSP_1,
 	FN_SEL_FM_0, FN_SEL_FM_1, FN_SEL_FM_2, FN_SEL_FM_3,
@@ -515,8 +458,6 @@ enum {
 	FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, FN_SEL_HSCIF0_2, FN_SEL_HSCIF0_3,
 	FN_SEL_HSCIF0_4, FN_SEL_HSCIF0_5,
 	FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2,
-	FN_SEL_RDS_0, FN_SEL_RDS_1, FN_SEL_RDS_2,
-	FN_SEL_RDS_3, FN_SEL_RDS_4, FN_SEL_RDS_5,
 	FN_SEL_SIM_0, FN_SEL_SIM_1, FN_SEL_SIM_2,
 	FN_SEL_SSI8_0, FN_SEL_SSI8_1, FN_SEL_SSI8_2,
 
@@ -548,17 +489,17 @@ enum {
 	VI0_R0_MARK, VI0_R0_B_MARK, RX0_B_MARK, D5_MARK,
 	SCIFB1_TXD_F_MARK, SCIFB0_TXD_C_MARK, VI3_DATA5_MARK,
 	VI0_R1_MARK, VI0_R1_B_MARK, TX0_B_MARK, D6_MARK,
-	SCL2_C_MARK, VI3_DATA6_MARK, VI0_R2_MARK, VI0_R2_B_MARK,
-	SCL2_CIS_C_MARK, D7_MARK, AD_DI_B_MARK, SDA2_C_MARK,
-	VI3_DATA7_MARK, VI0_R3_MARK, VI0_R3_B_MARK, SDA2_CIS_C_MARK,
-	D8_MARK, SCIFA1_SCK_C_MARK, AVB_TXD0_MARK, MII_TXD0_MARK,
+	IIC2_SCL_C_MARK, VI3_DATA6_MARK, VI0_R2_MARK, VI0_R2_B_MARK,
+	I2C2_SCL_C_MARK, D7_MARK, AD_DI_B_MARK, IIC2_SDA_C_MARK,
+	VI3_DATA7_MARK, VI0_R3_MARK, VI0_R3_B_MARK, I2C2_SDA_C_MARK, TCLK1_MARK,
+	D8_MARK, SCIFA1_SCK_C_MARK, AVB_TXD0_MARK,
 	VI0_G0_MARK, VI0_G0_B_MARK, VI2_DATA0_VI2_B0_MARK,
 
-	D9_MARK, SCIFA1_RXD_C_MARK, AVB_TXD1_MARK, MII_TXD1_MARK,
+	D9_MARK, SCIFA1_RXD_C_MARK, AVB_TXD1_MARK,
 	VI0_G1_MARK, VI0_G1_B_MARK, VI2_DATA1_VI2_B1_MARK, D10_MARK,
-	SCIFA1_TXD_C_MARK, AVB_TXD2_MARK, MII_TXD2_MARK,
+	SCIFA1_TXD_C_MARK, AVB_TXD2_MARK,
 	VI0_G2_MARK, VI0_G2_B_MARK, VI2_DATA2_VI2_B2_MARK, D11_MARK,
-	SCIFA1_CTS_N_C_MARK, AVB_TXD3_MARK, MII_TXD3_MARK,
+	SCIFA1_CTS_N_C_MARK, AVB_TXD3_MARK,
 	VI0_G3_MARK, VI0_G3_B_MARK, VI2_DATA3_VI2_B3_MARK,
 	D12_MARK, SCIFA1_RTS_N_C_MARK, AVB_TXD4_MARK,
 	VI0_HSYNC_N_MARK, VI0_HSYNC_N_B_MARK, VI2_DATA4_VI2_B4_MARK,
@@ -576,9 +517,9 @@ enum {
 	A6_MARK, SCIFA1_RTS_N_B_MARK, TPU0TO2_MARK, A7_MARK,
 	SCIFA1_SCK_B_MARK, AUDIO_CLKOUT_B_MARK, TPU0TO3_MARK,
 	A8_MARK, SCIFA1_RXD_B_MARK, SSI_SCK5_B_MARK, VI0_R4_MARK,
-	VI0_R4_B_MARK, SCIFB2_RXD_C_MARK, VI2_DATA0_VI2_B0_B_MARK,
+	VI0_R4_B_MARK, SCIFB2_RXD_C_MARK, RX2_B_MARK, VI2_DATA0_VI2_B0_B_MARK,
 	A9_MARK, SCIFA1_CTS_N_B_MARK, SSI_WS5_B_MARK, VI0_R5_MARK,
-	VI0_R5_B_MARK, SCIFB2_TXD_C_MARK, VI2_DATA1_VI2_B1_B_MARK,
+	VI0_R5_B_MARK, SCIFB2_TXD_C_MARK, TX2_B_MARK, VI2_DATA1_VI2_B1_B_MARK,
 	A10_MARK, SSI_SDATA5_B_MARK, MSIOF2_SYNC_MARK, VI0_R6_MARK,
 	VI0_R6_B_MARK, VI2_DATA2_VI2_B2_B_MARK,
 
@@ -615,11 +556,11 @@ enum {
 	EX_CS3_N_MARK, GPS_MAG_MARK, VI3_FIELD_MARK,
 	VI1_G1_MARK, VI1_G1_B_MARK, VI2_R3_MARK,
 	EX_CS4_N_MARK, MSIOF1_SCK_B_MARK, VI3_HSYNC_N_MARK,
-	VI2_HSYNC_N_MARK, SCL1_MARK, VI2_HSYNC_N_B_MARK,
-	INTC_EN0_N_MARK, SCL1_CIS_MARK, EX_CS5_N_MARK, CAN0_RX_MARK,
+	VI2_HSYNC_N_MARK, IIC1_SCL_MARK, VI2_HSYNC_N_B_MARK,
+	INTC_EN0_N_MARK, I2C1_SCL_MARK, EX_CS5_N_MARK, CAN0_RX_MARK,
 	MSIOF1_RXD_B_MARK, VI3_VSYNC_N_MARK, VI1_G2_MARK,
-	VI1_G2_B_MARK, VI2_R4_MARK, SDA1_MARK, INTC_EN1_N_MARK,
-	SDA1_CIS_MARK, BS_N_MARK, IETX_MARK, HTX1_B_MARK,
+	VI1_G2_B_MARK, VI2_R4_MARK, IIC1_SDA_MARK, INTC_EN1_N_MARK,
+	I2C1_SDA_MARK, BS_N_MARK, IETX_MARK, HTX1_B_MARK,
 	CAN1_TX_MARK, DRACK0_MARK, IETX_C_MARK, RD_N_MARK,
 	CAN0_TX_MARK, SCIFA0_SCK_B_MARK, RD_WR_N_MARK, VI1_G3_MARK,
 	VI1_G3_B_MARK, VI2_R5_MARK, SCIFA0_RXD_B_MARK,
@@ -641,28 +582,28 @@ enum {
 	DREQ2_N_MARK, HSCK1_B_MARK, HCTS0_N_B_MARK,
 	MSIOF0_TXD_B_MARK, DACK2_MARK, IRQ2_MARK, INTC_IRQ2_N_MARK,
 	SSI_SDATA6_B_MARK, HRTS0_N_B_MARK, MSIOF0_RXD_B_MARK,
-	ETH_CRS_DV_MARK, RMII_CRS_DV_MARK, STP_ISCLK_0_B_MARK,
-	TS_SDEN0_D_MARK, GLO_Q0_C_MARK, SCL2_E_MARK,
-	SCL2_CIS_E_MARK, ETH_RX_ER_MARK, RMII_RX_ER_MARK,
+	ETH_CRS_DV_MARK, STP_ISCLK_0_B_MARK,
+	TS_SDEN0_D_MARK, GLO_Q0_C_MARK, IIC2_SCL_E_MARK,
+	I2C2_SCL_E_MARK, ETH_RX_ER_MARK,
 	STP_ISD_0_B_MARK, TS_SPSYNC0_D_MARK, GLO_Q1_C_MARK,
-	SDA2_E_MARK, SDA2_CIS_E_MARK, ETH_RXD0_MARK, RMII_RXD0_MARK,
+	IIC2_SDA_E_MARK, I2C2_SDA_E_MARK, ETH_RXD0_MARK,
 	STP_ISEN_0_B_MARK, TS_SDAT0_D_MARK, GLO_I0_C_MARK,
 	SCIFB1_SCK_G_MARK, SCK1_E_MARK, ETH_RXD1_MARK,
-	RMII_RXD1_MARK, HRX0_E_MARK, STP_ISSYNC_0_B_MARK,
+	HRX0_E_MARK, STP_ISSYNC_0_B_MARK,
 	TS_SCK0_D_MARK, GLO_I1_C_MARK, SCIFB1_RXD_G_MARK,
-	RX1_E_MARK, ETH_LINK_MARK, RMII_LINK_MARK, HTX0_E_MARK,
+	RX1_E_MARK, ETH_LINK_MARK, HTX0_E_MARK,
 	STP_IVCXO27_0_B_MARK, SCIFB1_TXD_G_MARK, TX1_E_MARK,
-	ETH_REF_CLK_MARK, RMII_REF_CLK_MARK, HCTS0_N_E_MARK,
+	ETH_REF_CLK_MARK, HCTS0_N_E_MARK,
 	STP_IVCXO27_1_B_MARK, HRX0_F_MARK,
 
-	ETH_MDIO_MARK, RMII_MDIO_MARK, HRTS0_N_E_MARK,
+	ETH_MDIO_MARK, HRTS0_N_E_MARK,
 	SIM0_D_C_MARK, HCTS0_N_F_MARK, ETH_TXD1_MARK,
-	RMII_TXD1_MARK, HTX0_F_MARK, BPFCLK_G_MARK, RDS_CLK_F_MARK,
-	ETH_TX_EN_MARK, RMII_TX_EN_MARK, SIM0_CLK_C_MARK,
-	HRTS0_N_F_MARK, ETH_MAGIC_MARK, RMII_MAGIC_MARK,
-	SIM0_RST_C_MARK, ETH_TXD0_MARK, RMII_TXD0_MARK,
+	HTX0_F_MARK, BPFCLK_G_MARK,
+	ETH_TX_EN_MARK, SIM0_CLK_C_MARK,
+	HRTS0_N_F_MARK, ETH_MAGIC_MARK,
+	SIM0_RST_C_MARK, ETH_TXD0_MARK,
 	STP_ISCLK_1_B_MARK, TS_SDEN1_C_MARK, GLO_SCLK_C_MARK,
-	ETH_MDC_MARK, RMII_MDC_MARK, STP_ISD_1_B_MARK,
+	ETH_MDC_MARK, STP_ISD_1_B_MARK,
 	TS_SPSYNC1_C_MARK, GLO_SDATA_C_MARK, PWM0_MARK,
 	SCIFA2_SCK_C_MARK, STP_ISEN_1_B_MARK, TS_SDAT1_C_MARK,
 	GLO_SS_C_MARK, PWM1_MARK, SCIFA2_TXD_C_MARK,
@@ -670,25 +611,24 @@ enum {
 	PCMOE_N_MARK, PWM2_MARK, PWMFSW0_MARK, SCIFA2_RXD_C_MARK,
 	PCMWE_N_MARK, IECLK_C_MARK, DU1_DOTCLKIN_MARK,
 	AUDIO_CLKC_MARK, AUDIO_CLKOUT_C_MARK, VI0_CLK_MARK,
-	ATACS00_N_MARK, AVB_RXD1_MARK, MII_RXD1_MARK,
+	ATACS00_N_MARK, AVB_RXD1_MARK,
 	VI0_DATA0_VI0_B0_MARK, ATACS10_N_MARK, AVB_RXD2_MARK,
-	MII_RXD2_MARK,
 
 	VI0_DATA1_VI0_B1_MARK, ATARD0_N_MARK, AVB_RXD3_MARK,
-	MII_RXD3_MARK, VI0_DATA2_VI0_B2_MARK, ATAWR0_N_MARK,
+	VI0_DATA2_VI0_B2_MARK, ATAWR0_N_MARK,
 	AVB_RXD4_MARK, VI0_DATA3_VI0_B3_MARK, ATADIR0_N_MARK,
 	AVB_RXD5_MARK, VI0_DATA4_VI0_B4_MARK, ATAG0_N_MARK,
 	AVB_RXD6_MARK, VI0_DATA5_VI0_B5_MARK, EX_WAIT1_MARK,
 	AVB_RXD7_MARK, VI0_DATA6_VI0_B6_MARK, AVB_RX_ER_MARK,
-	MII_RX_ER_MARK, VI0_DATA7_VI0_B7_MARK, AVB_RX_CLK_MARK,
-	MII_RX_CLK_MARK, VI1_CLK_MARK, AVB_RX_DV_MARK,
-	MII_RX_DV_MARK, VI1_DATA0_VI1_B0_MARK, SCIFA1_SCK_D_MARK,
-	AVB_CRS_MARK, MII_CRS_MARK, VI1_DATA1_VI1_B1_MARK,
-	SCIFA1_RXD_D_MARK, AVB_MDC_MARK, MII_MDC_MARK,
+	VI0_DATA7_VI0_B7_MARK, AVB_RX_CLK_MARK,
+	VI1_CLK_MARK, AVB_RX_DV_MARK,
+	VI1_DATA0_VI1_B0_MARK, SCIFA1_SCK_D_MARK,
+	AVB_CRS_MARK, VI1_DATA1_VI1_B1_MARK,
+	SCIFA1_RXD_D_MARK, AVB_MDC_MARK,
 	VI1_DATA2_VI1_B2_MARK, SCIFA1_TXD_D_MARK, AVB_MDIO_MARK,
-	MII_MDIO_MARK, VI1_DATA3_VI1_B3_MARK, SCIFA1_CTS_N_D_MARK,
+	VI1_DATA3_VI1_B3_MARK, SCIFA1_CTS_N_D_MARK,
 	AVB_GTX_CLK_MARK, VI1_DATA4_VI1_B4_MARK, SCIFA1_RTS_N_D_MARK,
-	AVB_MAGIC_MARK, MII_MAGIC_MARK, VI1_DATA5_VI1_B5_MARK,
+	AVB_MAGIC_MARK, VI1_DATA5_VI1_B5_MARK,
 	AVB_PHY_INT_MARK, VI1_DATA6_VI1_B6_MARK, AVB_GTXREFCLK_MARK,
 	SD0_CLK_MARK, VI1_DATA0_VI1_B0_B_MARK, SD0_CMD_MARK,
 	SCIFB1_SCK_B_MARK, VI1_DATA1_VI1_B1_B_MARK,
@@ -698,25 +638,25 @@ enum {
 	SD0_DAT2_MARK, SCIFB1_CTS_N_B_MARK, VI1_DATA4_VI1_B4_B_MARK,
 	SD0_DAT3_MARK, SCIFB1_RTS_N_B_MARK, VI1_DATA5_VI1_B5_B_MARK,
 	SD0_CD_MARK, MMC0_D6_MARK, TS_SDEN0_B_MARK, USB0_EXTP_MARK,
-	GLO_SCLK_MARK, VI1_DATA6_VI1_B6_B_MARK, SCL1_B_MARK,
-	SCL1_CIS_B_MARK, VI2_DATA6_VI2_B6_B_MARK, SD0_WP_MARK,
+	GLO_SCLK_MARK, VI1_DATA6_VI1_B6_B_MARK, IIC1_SCL_B_MARK,
+	I2C1_SCL_B_MARK, VI2_DATA6_VI2_B6_B_MARK, SD0_WP_MARK,
 	MMC0_D7_MARK, TS_SPSYNC0_B_MARK, USB0_IDIN_MARK,
-	GLO_SDATA_MARK, VI1_DATA7_VI1_B7_B_MARK, SDA1_B_MARK,
-	SDA1_CIS_B_MARK, VI2_DATA7_VI2_B7_B_MARK, SD1_CLK_MARK,
-	AVB_TX_EN_MARK, MII_TX_EN_MARK, SD1_CMD_MARK,
-	AVB_TX_ER_MARK, MII_TX_ER_MARK, SCIFB0_SCK_B_MARK,
-	SD1_DAT0_MARK, AVB_TX_CLK_MARK, MII_TX_CLK_MARK,
+	GLO_SDATA_MARK, VI1_DATA7_VI1_B7_B_MARK, IIC1_SDA_B_MARK,
+	I2C1_SDA_B_MARK, VI2_DATA7_VI2_B7_B_MARK, SD1_CLK_MARK,
+	AVB_TX_EN_MARK, SD1_CMD_MARK,
+	AVB_TX_ER_MARK, SCIFB0_SCK_B_MARK,
+	SD1_DAT0_MARK, AVB_TX_CLK_MARK,
 	SCIFB0_RXD_B_MARK, SD1_DAT1_MARK, AVB_LINK_MARK,
-	MII_LINK_MARK, SCIFB0_TXD_B_MARK, SD1_DAT2_MARK,
-	AVB_COL_MARK, MII_COL_MARK, SCIFB0_CTS_N_B_MARK,
-	SD1_DAT3_MARK, AVB_RXD0_MARK, MII_RXD0_MARK,
+	SCIFB0_TXD_B_MARK, SD1_DAT2_MARK,
+	AVB_COL_MARK, SCIFB0_CTS_N_B_MARK,
+	SD1_DAT3_MARK, AVB_RXD0_MARK,
 	SCIFB0_RTS_N_B_MARK, SD1_CD_MARK, MMC1_D6_MARK,
 	TS_SDEN1_MARK, USB1_EXTP_MARK, GLO_SS_MARK, VI0_CLK_B_MARK,
-	SCL2_D_MARK, SCL2_CIS_D_MARK, SIM0_CLK_B_MARK,
+	IIC2_SCL_D_MARK, I2C2_SCL_D_MARK, SIM0_CLK_B_MARK,
 	VI3_CLK_B_MARK,
 
 	SD1_WP_MARK, MMC1_D7_MARK, TS_SPSYNC1_MARK, USB1_IDIN_MARK,
-	GLO_RFON_MARK, VI1_CLK_B_MARK, SDA2_D_MARK, SDA2_CIS_D_MARK,
+	GLO_RFON_MARK, VI1_CLK_B_MARK, IIC2_SDA_D_MARK, I2C2_SDA_D_MARK,
 	SIM0_D_B_MARK, SD2_CLK_MARK, MMC0_CLK_MARK, SIM0_CLK_MARK,
 	VI0_DATA0_VI0_B0_B_MARK, TS_SDEN0_C_MARK, GLO_SCLK_B_MARK,
 	VI3_DATA0_B_MARK, SD2_CMD_MARK, MMC0_CMD_MARK, SIM0_D_MARK,
@@ -725,10 +665,10 @@ enum {
 	SD2_DAT0_MARK, MMC0_D0_MARK, FMCLK_B_MARK,
 	VI0_DATA2_VI0_B2_B_MARK, SCIFB1_RXD_E_MARK, RX1_D_MARK,
 	TS_SDAT0_C_MARK, GLO_SS_B_MARK, VI3_DATA2_B_MARK,
-	SD2_DAT1_MARK, MMC0_D1_MARK, FMIN_B_MARK, RDS_DATA_MARK,
+	SD2_DAT1_MARK, MMC0_D1_MARK, FMIN_B_MARK,
 	VI0_DATA3_VI0_B3_B_MARK, SCIFB1_TXD_E_MARK, TX1_D_MARK,
 	TS_SCK0_C_MARK, GLO_RFON_B_MARK, VI3_DATA3_B_MARK,
-	SD2_DAT2_MARK, MMC0_D2_MARK, BPFCLK_B_MARK, RDS_CLK_MARK,
+	SD2_DAT2_MARK, MMC0_D2_MARK, BPFCLK_B_MARK,
 	VI0_DATA4_VI0_B4_B_MARK, HRX0_D_MARK, TS_SDEN1_B_MARK,
 	GLO_Q0_B_MARK, VI3_DATA4_B_MARK, SD2_DAT3_MARK,
 	MMC0_D3_MARK, SIM0_RST_MARK, VI0_DATA5_VI0_B5_B_MARK,
@@ -748,12 +688,12 @@ enum {
 	SCKZ_MARK, SD3_CD_MARK, MMC1_D4_MARK, TS_SDAT1_MARK,
 	VSP_MARK, GLO_Q0_MARK, SIM0_RST_B_MARK, SD3_WP_MARK,
 	MMC1_D5_MARK, TS_SCK1_MARK, GLO_Q1_MARK, FMIN_C_MARK,
-	RDS_DATA_B_MARK, FMIN_E_MARK, RDS_DATA_D_MARK, FMIN_F_MARK,
-	RDS_DATA_E_MARK, MLB_CLK_MARK, SCL2_B_MARK, SCL2_CIS_B_MARK,
-	MLB_SIG_MARK, SCIFB1_RXD_D_MARK, RX1_C_MARK, SDA2_B_MARK,
-	SDA2_CIS_B_MARK, MLB_DAT_MARK, SPV_EVEN_MARK,
+	FMIN_E_MARK, FMIN_F_MARK,
+	MLB_CLK_MARK, IIC2_SCL_B_MARK, I2C2_SCL_B_MARK,
+	MLB_SIG_MARK, SCIFB1_RXD_D_MARK, RX1_C_MARK, IIC2_SDA_B_MARK,
+	I2C2_SDA_B_MARK, MLB_DAT_MARK,
 	SCIFB1_TXD_D_MARK, TX1_C_MARK, BPFCLK_C_MARK,
-	RDS_CLK_B_MARK, SSI_SCK0129_MARK, CAN_CLK_B_MARK,
+	SSI_SCK0129_MARK, CAN_CLK_B_MARK,
 	MOUT0_MARK,
 
 	SSI_WS0129_MARK, CAN0_TX_B_MARK, MOUT1_MARK,
@@ -778,12 +718,12 @@ enum {
 
 	SSI_SDATA5_MARK, SCIFB1_TXD_MARK, IETX_B_MARK, DU2_DR2_MARK,
 	LCDOUT2_MARK, CAN_DEBUGOUT5_MARK, SSI_SCK6_MARK,
-	SCIFB1_CTS_N_MARK, BPFCLK_D_MARK, RDS_CLK_C_MARK,
+	SCIFB1_CTS_N_MARK, BPFCLK_D_MARK,
 	DU2_DR3_MARK, LCDOUT3_MARK, CAN_DEBUGOUT6_MARK,
-	BPFCLK_F_MARK, RDS_CLK_E_MARK, SSI_WS6_MARK,
+	BPFCLK_F_MARK, SSI_WS6_MARK,
 	SCIFB1_RTS_N_MARK, CAN0_TX_D_MARK, DU2_DR4_MARK,
 	LCDOUT4_MARK, CAN_DEBUGOUT7_MARK, SSI_SDATA6_MARK,
-	FMIN_D_MARK, RDS_DATA_C_MARK, DU2_DR5_MARK, LCDOUT5_MARK,
+	FMIN_D_MARK, DU2_DR5_MARK, LCDOUT5_MARK,
 	CAN_DEBUGOUT8_MARK, SSI_SCK78_MARK, STP_IVCXO27_1_MARK,
 	SCK1_MARK, SCIFA1_SCK_MARK, DU2_DR6_MARK, LCDOUT6_MARK,
 	CAN_DEBUGOUT9_MARK, SSI_WS78_MARK, STP_ISCLK_1_MARK,
@@ -791,8 +731,8 @@ enum {
 	LCDOUT7_MARK, CAN_DEBUGOUT10_MARK, SSI_SDATA7_MARK,
 	STP_ISD_1_MARK, SCIFB2_RXD_MARK, SCIFA2_RTS_N_MARK,
 	TCLK2_MARK, QSTVA_QVS_MARK, CAN_DEBUGOUT11_MARK,
-	BPFCLK_E_MARK, RDS_CLK_D_MARK, SSI_SDATA7_B_MARK,
-	FMIN_G_MARK, RDS_DATA_F_MARK, SSI_SDATA8_MARK,
+	BPFCLK_E_MARK, SSI_SDATA7_B_MARK,
+	FMIN_G_MARK, SSI_SDATA8_MARK,
 	STP_ISEN_1_MARK, SCIFB2_TXD_MARK, CAN0_TX_C_MARK,
 	CAN_DEBUGOUT12_MARK, SSI_SDATA8_B_MARK, SSI_SDATA9_MARK,
 	STP_ISSYNC_1_MARK, SCIFB2_CTS_N_MARK, SSI_WS1_MARK,
@@ -802,28 +742,28 @@ enum {
 	AUDIO_CLKB_MARK, SCIF_CLK_MARK, CAN0_RX_D_MARK,
 	DVC_MUTE_MARK, CAN0_RX_C_MARK, CAN_DEBUGOUT15_MARK,
 	REMOCON_MARK, SCIFA0_SCK_MARK, HSCK1_MARK, SCK0_MARK,
-	MSIOF3_SS2_MARK, DU2_DG2_MARK, LCDOUT10_MARK, SDA1_C_MARK,
-	SDA1_CIS_C_MARK, SCIFA0_RXD_MARK, HRX1_MARK, RX0_MARK,
+	MSIOF3_SS2_MARK, DU2_DG2_MARK, LCDOUT10_MARK, IIC1_SDA_C_MARK,
+	I2C1_SDA_C_MARK, SCIFA0_RXD_MARK, HRX1_MARK, RX0_MARK,
 	DU2_DR0_MARK, LCDOUT0_MARK, SCIFA0_TXD_MARK, HTX1_MARK,
 	TX0_MARK, DU2_DR1_MARK, LCDOUT1_MARK, SCIFA0_CTS_N_MARK,
 	HCTS1_N_MARK, CTS0_N_MARK, MSIOF3_SYNC_MARK, DU2_DG3_MARK,
-	LCDOUT11_MARK, PWM0_B_MARK, SCL1_C_MARK, SCL1_CIS_C_MARK,
-	SCIFA0_RTS_N_MARK, HRTS1_N_MARK, RTS0_N_TANS_MARK,
+	LCDOUT11_MARK, PWM0_B_MARK, IIC1_SCL_C_MARK, I2C1_SCL_C_MARK,
+	SCIFA0_RTS_N_MARK, HRTS1_N_MARK, RTS0_N_MARK,
 	MSIOF3_SS1_MARK, DU2_DG0_MARK, LCDOUT8_MARK, PWM1_B_MARK,
 	SCIFA1_RXD_MARK, AD_DI_MARK, RX1_MARK,
 	DU2_EXODDF_DU2_ODDF_DISP_CDE_MARK, QCPV_QDE_MARK,
 	SCIFA1_TXD_MARK, AD_DO_MARK, TX1_MARK, DU2_DG1_MARK,
 	LCDOUT9_MARK, SCIFA1_CTS_N_MARK, AD_CLK_MARK,
 	CTS1_N_MARK, MSIOF3_RXD_MARK, DU0_DOTCLKOUT_MARK, QCLK_MARK,
-	SCIFA1_RTS_N_MARK, AD_NCS_N_MARK, RTS1_N_TANS_MARK,
+	SCIFA1_RTS_N_MARK, AD_NCS_N_MARK, RTS1_N_MARK,
 	MSIOF3_TXD_MARK, DU1_DOTCLKOUT_MARK, QSTVB_QVE_MARK,
 	HRTS0_N_C_MARK,
 
-	SCIFA2_SCK_MARK, FMCLK_MARK, MSIOF3_SCK_MARK, DU2_DG7_MARK,
+	SCIFA2_SCK_MARK, FMCLK_MARK, SCK2_MARK, MSIOF3_SCK_MARK, DU2_DG7_MARK,
 	LCDOUT15_MARK, SCIF_CLK_B_MARK, SCIFA2_RXD_MARK, FMIN_MARK,
-	DU2_DB0_MARK, LCDOUT16_MARK, SCL2_MARK, SCL2_CIS_MARK,
-	SCIFA2_TXD_MARK, BPFCLK_MARK, DU2_DB1_MARK, LCDOUT17_MARK,
-	SDA2_MARK, SDA2_CIS_MARK, HSCK0_MARK, TS_SDEN0_MARK,
+	TX2_MARK, DU2_DB0_MARK, LCDOUT16_MARK, IIC2_SCL_MARK, I2C2_SCL_MARK,
+	SCIFA2_TXD_MARK, BPFCLK_MARK, RX2_MARK, DU2_DB1_MARK, LCDOUT17_MARK,
+	IIC2_SDA_MARK, I2C2_SDA_MARK, HSCK0_MARK, TS_SDEN0_MARK,
 	DU2_DG4_MARK, LCDOUT12_MARK, HCTS0_N_C_MARK, HRX0_MARK,
 	DU2_DB2_MARK, LCDOUT18_MARK, HTX0_MARK, DU2_DB3_MARK,
 	LCDOUT19_MARK, HCTS0_N_MARK, SSI_SCK9_MARK, DU2_DB4_MARK,
@@ -831,20 +771,20 @@ enum {
 	LCDOUT21_MARK, MSIOF0_SCK_MARK, TS_SDAT0_MARK, ADICLK_MARK,
 	DU2_DB6_MARK, LCDOUT22_MARK, MSIOF0_SYNC_MARK, TS_SCK0_MARK,
 	SSI_SCK2_MARK, ADIDATA_MARK, DU2_DB7_MARK, LCDOUT23_MARK,
-	SCIFA2_RXD_B_MARK, MSIOF0_SS1_MARK, ADICHS0_MARK,
+	HRX0_C_MARK, MSIOF0_SS1_MARK, ADICHS0_MARK,
 	DU2_DG5_MARK, LCDOUT13_MARK, MSIOF0_TXD_MARK, ADICHS1_MARK,
 	DU2_DG6_MARK, LCDOUT14_MARK,
 
 	MSIOF0_SS2_MARK, AUDIO_CLKOUT_MARK, ADICHS2_MARK,
 	DU2_DISP_MARK, QPOLA_MARK, HTX0_C_MARK, SCIFA2_TXD_B_MARK,
 	MSIOF0_RXD_MARK, TS_SPSYNC0_MARK, SSI_WS2_MARK,
-	ADICS_SAMP_MARK, DU2_CDE_MARK, QPOLB_MARK, HRX0_C_MARK,
+	ADICS_SAMP_MARK, DU2_CDE_MARK, QPOLB_MARK, SCIFA2_RXD_B_MARK,
 	USB1_PWEN_MARK, AUDIO_CLKOUT_D_MARK, USB1_OVC_MARK,
 	TCLK1_B_MARK,
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
 
 	PINMUX_DATA(VI1_DATA7_VI1_B7_MARK, FN_VI1_DATA7_VI1_B7),
@@ -892,22 +832,22 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP0_19_16, VI0_R1_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP0_19_16, TX0_B, SEL_SCIF0_1),
 	PINMUX_IPSR_DATA(IP0_22_20, D6),
-	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, SCL2_C, SEL_IIC2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, IIC2_SCL_C, SEL_IIC2_2),
 	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, VI3_DATA6, SEL_VI3_0),
 	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, VI0_R2, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, VI0_R2_B, SEL_VI0_1),
-	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, SCL2_CIS_C, SEL_I2C2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_22_20, I2C2_SCL_C, SEL_I2C2_2),
 	PINMUX_IPSR_DATA(IP0_26_23, D7),
 	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, AD_DI_B, SEL_ADI_1),
-	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, SDA2_C, SEL_IIC2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, IIC2_SDA_C, SEL_IIC2_2),
 	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, VI3_DATA7, SEL_VI3_0),
 	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, VI0_R3, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, VI0_R3_B, SEL_VI0_1),
-	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, SDA2_CIS_C, SEL_I2C2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, I2C2_SDA_C, SEL_I2C2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_26_23, TCLK1, SEL_TMU1_0),
 	PINMUX_IPSR_DATA(IP0_30_27, D8),
 	PINMUX_IPSR_MODSEL_DATA(IP0_30_27, SCIFA1_SCK_C, SEL_SCIFA1_2),
 	PINMUX_IPSR_DATA(IP0_30_27, AVB_TXD0),
-	PINMUX_IPSR_DATA(IP0_30_27, MII_TXD0),
 	PINMUX_IPSR_MODSEL_DATA(IP0_30_27, VI0_G0, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP0_30_27, VI0_G0_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP0_30_27, VI2_DATA0_VI2_B0, SEL_VI2_0),
@@ -915,21 +855,18 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP1_3_0, D9),
 	PINMUX_IPSR_MODSEL_DATA(IP1_3_0, SCIFA1_RXD_C, SEL_SCIFA1_2),
 	PINMUX_IPSR_DATA(IP1_3_0, AVB_TXD1),
-	PINMUX_IPSR_DATA(IP1_3_0, MII_TXD1),
 	PINMUX_IPSR_MODSEL_DATA(IP1_3_0, VI0_G1, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP1_3_0, VI0_G1_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP1_3_0, VI2_DATA1_VI2_B1, SEL_VI2_0),
 	PINMUX_IPSR_DATA(IP1_7_4, D10),
 	PINMUX_IPSR_MODSEL_DATA(IP1_7_4, SCIFA1_TXD_C, SEL_SCIFA1_2),
 	PINMUX_IPSR_DATA(IP1_7_4, AVB_TXD2),
-	PINMUX_IPSR_DATA(IP1_7_4, MII_TXD2),
 	PINMUX_IPSR_MODSEL_DATA(IP1_7_4, VI0_G2, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP1_7_4, VI0_G2_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP1_7_4, VI2_DATA2_VI2_B2, SEL_VI2_0),
 	PINMUX_IPSR_DATA(IP1_11_8, D11),
 	PINMUX_IPSR_MODSEL_DATA(IP1_11_8, SCIFA1_CTS_N_C, SEL_SCIFA1_2),
 	PINMUX_IPSR_DATA(IP1_11_8, AVB_TXD3),
-	PINMUX_IPSR_DATA(IP1_11_8, MII_TXD3),
 	PINMUX_IPSR_MODSEL_DATA(IP1_11_8, VI0_G3, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP1_11_8, VI0_G3_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP1_11_8, VI2_DATA3_VI2_B3, SEL_VI2_0),
@@ -940,7 +877,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP1_14_12, VI0_HSYNC_N_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP1_14_12, VI2_DATA4_VI2_B4, SEL_VI2_0),
 	PINMUX_IPSR_DATA(IP1_17_15, D13),
-	PINMUX_IPSR_MODSEL_DATA(IP1_17_15, AVB_TXD5, SEL_SCIFA1_2),
+	PINMUX_IPSR_DATA(IP1_17_15, AVB_TXD5),
 	PINMUX_IPSR_MODSEL_DATA(IP1_17_15, VI0_VSYNC_N, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP1_17_15, VI0_VSYNC_N_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP1_17_15, VI2_DATA5_VI2_B5, SEL_VI2_0),
@@ -988,6 +925,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP2_21_18, VI0_R4, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP2_21_18, VI0_R4_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP2_21_18, SCIFB2_RXD_C, SEL_SCIFB2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP2_21_18, RX2_B, SEL_SCIF2_1),
 	PINMUX_IPSR_MODSEL_DATA(IP2_21_18, VI2_DATA0_VI2_B0_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP2_25_22, A9),
 	PINMUX_IPSR_MODSEL_DATA(IP2_25_22, SCIFA1_CTS_N_B, SEL_SCIFA1_1),
@@ -995,6 +933,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP2_25_22, VI0_R5, SEL_VI0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP2_25_22, VI0_R5_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP2_25_22, SCIFB2_TXD_C, SEL_SCIFB2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP2_25_22, TX2_B, SEL_SCIF2_1),
 	PINMUX_IPSR_MODSEL_DATA(IP2_25_22, VI2_DATA1_VI2_B1_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP2_28_26, A10),
 	PINMUX_IPSR_MODSEL_DATA(IP2_28_26, SSI_SDATA5_B, SEL_SSI5_1),
@@ -1009,14 +948,14 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP3_3_0, VI1_R0, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP3_3_0, VI1_R0_B, SEL_VI1_1),
 	PINMUX_IPSR_DATA(IP3_3_0, VI2_G0),
-	PINMUX_IPSR_DATA(IP3_3_0, VI2_DATA3_VI2_B3_B),
+	PINMUX_IPSR_MODSEL_DATA(IP3_3_0, VI2_DATA3_VI2_B3_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP3_7_4, A12),
 	PINMUX_IPSR_MODSEL_DATA(IP3_7_4, SCIFB2_RXD_B, SEL_SCIFB2_1),
 	PINMUX_IPSR_DATA(IP3_7_4, MSIOF2_TXD),
 	PINMUX_IPSR_MODSEL_DATA(IP3_7_4, VI1_R1, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP3_7_4, VI1_R1_B, SEL_VI1_1),
 	PINMUX_IPSR_DATA(IP3_7_4, VI2_G1),
-	PINMUX_IPSR_DATA(IP3_7_4, VI2_DATA4_VI2_B4_B),
+	PINMUX_IPSR_MODSEL_DATA(IP3_7_4, VI2_DATA4_VI2_B4_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP3_11_8, A13),
 	PINMUX_IPSR_MODSEL_DATA(IP3_11_8, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
 	PINMUX_IPSR_DATA(IP3_11_8, EX_WAIT2),
@@ -1024,7 +963,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI1_R2, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI1_R2_B, SEL_VI1_1),
 	PINMUX_IPSR_DATA(IP3_11_8, VI2_G2),
-	PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI2_DATA5_VI2_B5_B, SEL_VI2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_11_8, VI2_DATA5_VI2_B5_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP3_14_12, A14),
 	PINMUX_IPSR_MODSEL_DATA(IP3_14_12, SCIFB2_TXD_B, SEL_SCIFB2_1),
 	PINMUX_IPSR_DATA(IP3_14_12, ATACS11_N),
@@ -1116,14 +1055,14 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP5_2_0, VI1_G1, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP5_2_0, VI1_G1_B, SEL_VI1_1),
 	PINMUX_IPSR_DATA(IP5_2_0, VI2_R3),
-	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, EX_CS4_N, SEL_I2C1_0),
+	PINMUX_IPSR_DATA(IP5_5_3, EX_CS4_N),
 	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, MSIOF1_SCK_B, SEL_SOF1_1),
 	PINMUX_IPSR_DATA(IP5_5_3, VI3_HSYNC_N),
 	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, VI2_HSYNC_N, SEL_VI2_0),
-	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, SCL1, SEL_IIC1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, IIC1_SCL, SEL_IIC1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, VI2_HSYNC_N_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP5_5_3, INTC_EN0_N),
-	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, SCL1_CIS, SEL_I2C1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, I2C1_SCL, SEL_I2C1_0),
 	PINMUX_IPSR_DATA(IP5_9_6, EX_CS5_N),
 	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, CAN0_RX, SEL_CAN0_0),
 	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, MSIOF1_RXD_B, SEL_SOF1_1),
@@ -1131,9 +1070,9 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, VI1_G2, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, VI1_G2_B, SEL_VI1_1),
 	PINMUX_IPSR_DATA(IP5_9_6, VI2_R4),
-	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, SDA1, SEL_IIC1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, IIC1_SDA, SEL_IIC1_0),
 	PINMUX_IPSR_DATA(IP5_9_6, INTC_EN1_N),
-	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, SDA1_CIS, SEL_I2C1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_9_6, I2C1_SDA, SEL_I2C1_0),
 	PINMUX_IPSR_DATA(IP5_12_10, BS_N),
 	PINMUX_IPSR_MODSEL_DATA(IP5_12_10, IETX, SEL_IEB_0),
 	PINMUX_IPSR_MODSEL_DATA(IP5_12_10, HTX1_B, SEL_HSCIF1_1),
@@ -1163,7 +1102,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP5_23_21, VI2_R6),
 	PINMUX_IPSR_MODSEL_DATA(IP5_23_21, SCIFA0_CTS_N_B, SEL_SCFA_1),
 	PINMUX_IPSR_MODSEL_DATA(IP5_23_21, IERX_C, SEL_IEB_2),
-	PINMUX_IPSR_DATA(IP5_26_24, EX_WAIT0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_26_24, EX_WAIT0, SEL_LBS_0),
 	PINMUX_IPSR_DATA(IP5_26_24, IRQ3),
 	PINMUX_IPSR_DATA(IP5_26_24, INTC_IRQ3_N),
 	PINMUX_IPSR_MODSEL_DATA(IP5_26_24, VI3_CLK, SEL_VI3_0),
@@ -1205,28 +1144,24 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP6_13_11, HRTS0_N_B, SEL_HSCIF0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_13_11, MSIOF0_RXD_B, SEL_SOF0_1),
 	PINMUX_IPSR_DATA(IP6_16_14, ETH_CRS_DV),
-	PINMUX_IPSR_DATA(IP6_16_14, RMII_CRS_DV),
 	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, STP_ISCLK_0_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, TS_SDEN0_D, SEL_TSIF0_3),
 	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, GLO_Q0_C, SEL_GPS_2),
-	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, SCL2_E, SEL_IIC2_4),
-	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, SCL2_CIS_E, SEL_I2C2_4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, IIC2_SCL_E, SEL_IIC2_4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_16_14, I2C2_SCL_E, SEL_I2C2_4),
 	PINMUX_IPSR_DATA(IP6_19_17, ETH_RX_ER),
-	PINMUX_IPSR_DATA(IP6_19_17, RMII_RX_ER),
 	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, STP_ISD_0_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, TS_SPSYNC0_D, SEL_TSIF0_3),
 	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, GLO_Q1_C, SEL_GPS_2),
-	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, SDA2_E, SEL_IIC2_4),
-	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, SDA2_CIS_E, SEL_I2C2_4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, IIC2_SDA_E, SEL_IIC2_4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_19_17, I2C2_SDA_E, SEL_I2C2_4),
 	PINMUX_IPSR_DATA(IP6_22_20, ETH_RXD0),
-	PINMUX_IPSR_DATA(IP6_22_20, RMII_RXD0),
 	PINMUX_IPSR_MODSEL_DATA(IP6_22_20, STP_ISEN_0_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_22_20, TS_SDAT0_D, SEL_TSIF0_3),
 	PINMUX_IPSR_MODSEL_DATA(IP6_22_20, GLO_I0_C, SEL_GPS_2),
 	PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCIFB1_SCK_G, SEL_SCIFB1_6),
 	PINMUX_IPSR_MODSEL_DATA(IP6_22_20, SCK1_E, SEL_SCIF1_4),
 	PINMUX_IPSR_DATA(IP6_25_23, ETH_RXD1),
-	PINMUX_IPSR_DATA(IP6_25_23, RMII_RXD1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_25_23, HRX0_E, SEL_HSCIF0_4),
 	PINMUX_IPSR_MODSEL_DATA(IP6_25_23, STP_ISSYNC_0_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_25_23, TS_SCK0_D, SEL_TSIF0_3),
@@ -1234,41 +1169,32 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP6_25_23, SCIFB1_RXD_G, SEL_SCIFB1_6),
 	PINMUX_IPSR_MODSEL_DATA(IP6_25_23, RX1_E, SEL_SCIF1_4),
 	PINMUX_IPSR_DATA(IP6_28_26, ETH_LINK),
-	PINMUX_IPSR_DATA(IP6_28_26, RMII_LINK),
 	PINMUX_IPSR_MODSEL_DATA(IP6_28_26, HTX0_E, SEL_HSCIF0_4),
 	PINMUX_IPSR_MODSEL_DATA(IP6_28_26, STP_IVCXO27_0_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_28_26, SCIFB1_TXD_G, SEL_SCIFB1_6),
 	PINMUX_IPSR_MODSEL_DATA(IP6_28_26, TX1_E, SEL_SCIF1_4),
 	PINMUX_IPSR_DATA(IP6_31_29, ETH_REF_CLK),
-	PINMUX_IPSR_DATA(IP6_31_29, RMII_REF_CLK),
 	PINMUX_IPSR_MODSEL_DATA(IP6_31_29, HCTS0_N_E, SEL_HSCIF0_4),
 	PINMUX_IPSR_MODSEL_DATA(IP6_31_29, STP_IVCXO27_1_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP6_31_29, HRX0_F, SEL_HSCIF0_5),
 
 	PINMUX_IPSR_DATA(IP7_2_0, ETH_MDIO),
-	PINMUX_IPSR_DATA(IP7_2_0, RMII_MDIO),
 	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, HRTS0_N_E, SEL_HSCIF0_4),
 	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, SIM0_D_C, SEL_SIM_2),
 	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, HCTS0_N_F, SEL_HSCIF0_5),
 	PINMUX_IPSR_DATA(IP7_5_3, ETH_TXD1),
-	PINMUX_IPSR_DATA(IP7_5_3, RMII_TXD1),
-	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, HTX0_F, SEL_HSCIF0_4),
-	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, BPFCLK_G, SEL_SIM_2),
-	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, RDS_CLK_F, SEL_HSCIF0_5),
+	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, HTX0_F, SEL_HSCIF0_5),
+	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, BPFCLK_G, SEL_FM_6),
 	PINMUX_IPSR_DATA(IP7_7_6, ETH_TX_EN),
-	PINMUX_IPSR_DATA(IP7_7_6, RMII_TX_EN),
 	PINMUX_IPSR_MODSEL_DATA(IP7_7_6, SIM0_CLK_C, SEL_SIM_2),
 	PINMUX_IPSR_MODSEL_DATA(IP7_7_6, HRTS0_N_F, SEL_HSCIF0_5),
 	PINMUX_IPSR_DATA(IP7_9_8, ETH_MAGIC),
-	PINMUX_IPSR_DATA(IP7_9_8, RMII_MAGIC),
 	PINMUX_IPSR_MODSEL_DATA(IP7_9_8, SIM0_RST_C, SEL_SIM_2),
 	PINMUX_IPSR_DATA(IP7_12_10, ETH_TXD0),
-	PINMUX_IPSR_DATA(IP7_12_10, RMII_TXD0),
 	PINMUX_IPSR_MODSEL_DATA(IP7_12_10, STP_ISCLK_1_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP7_12_10, TS_SDEN1_C, SEL_TSIF1_2),
 	PINMUX_IPSR_MODSEL_DATA(IP7_12_10, GLO_SCLK_C, SEL_GPS_2),
 	PINMUX_IPSR_DATA(IP7_15_13, ETH_MDC),
-	PINMUX_IPSR_DATA(IP7_15_13, RMII_MDC),
 	PINMUX_IPSR_MODSEL_DATA(IP7_15_13, STP_ISD_1_B, SEL_SSP_1),
 	PINMUX_IPSR_MODSEL_DATA(IP7_15_13, TS_SPSYNC1_C, SEL_TSIF1_2),
 	PINMUX_IPSR_MODSEL_DATA(IP7_15_13, GLO_SDATA_C, SEL_GPS_2),
@@ -1294,16 +1220,13 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP7_28_27, VI0_CLK, SEL_VI0_0),
 	PINMUX_IPSR_DATA(IP7_28_27, ATACS00_N),
 	PINMUX_IPSR_DATA(IP7_28_27, AVB_RXD1),
-	PINMUX_IPSR_DATA(IP7_28_27, MII_RXD1),
 	PINMUX_IPSR_MODSEL_DATA(IP7_30_29, VI0_DATA0_VI0_B0, SEL_VI0_0),
 	PINMUX_IPSR_DATA(IP7_30_29, ATACS10_N),
 	PINMUX_IPSR_DATA(IP7_30_29, AVB_RXD2),
-	PINMUX_IPSR_DATA(IP7_30_29, MII_RXD2),
 
 	PINMUX_IPSR_MODSEL_DATA(IP8_1_0, VI0_DATA1_VI0_B1, SEL_VI0_0),
 	PINMUX_IPSR_DATA(IP8_1_0, ATARD0_N),
 	PINMUX_IPSR_DATA(IP8_1_0, AVB_RXD3),
-	PINMUX_IPSR_DATA(IP8_1_0, MII_RXD3),
 	PINMUX_IPSR_MODSEL_DATA(IP8_3_2, VI0_DATA2_VI0_B2, SEL_VI0_0),
 	PINMUX_IPSR_DATA(IP8_3_2, ATAWR0_N),
 	PINMUX_IPSR_DATA(IP8_3_2, AVB_RXD4),
@@ -1318,34 +1241,27 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP8_9_8, AVB_RXD7),
 	PINMUX_IPSR_MODSEL_DATA(IP8_11_10, VI0_DATA6_VI0_B6, SEL_VI0_0),
 	PINMUX_IPSR_DATA(IP8_11_10, AVB_RX_ER),
-	PINMUX_IPSR_DATA(IP8_11_10, MII_RX_ER),
 	PINMUX_IPSR_MODSEL_DATA(IP8_13_12, VI0_DATA7_VI0_B7, SEL_VI0_0),
 	PINMUX_IPSR_DATA(IP8_13_12, AVB_RX_CLK),
-	PINMUX_IPSR_DATA(IP8_13_12, MII_RX_CLK),
 	PINMUX_IPSR_MODSEL_DATA(IP8_15_14, VI1_CLK, SEL_VI1_0),
 	PINMUX_IPSR_DATA(IP8_15_14, AVB_RX_DV),
-	PINMUX_IPSR_DATA(IP8_15_14, MII_RX_DV),
 	PINMUX_IPSR_MODSEL_DATA(IP8_17_16, VI1_DATA0_VI1_B0, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP8_17_16, SCIFA1_SCK_D, SEL_SCIFA1_3),
 	PINMUX_IPSR_DATA(IP8_17_16, AVB_CRS),
-	PINMUX_IPSR_DATA(IP8_17_16, MII_CRS),
 	PINMUX_IPSR_MODSEL_DATA(IP8_19_18, VI1_DATA1_VI1_B1, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP8_19_18, SCIFA1_RXD_D, SEL_SCIFA1_3),
 	PINMUX_IPSR_DATA(IP8_19_18, AVB_MDC),
-	PINMUX_IPSR_DATA(IP8_19_18, MII_MDC),
 	PINMUX_IPSR_MODSEL_DATA(IP8_21_20, VI1_DATA2_VI1_B2, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP8_21_20, SCIFA1_TXD_D, SEL_SCIFA1_3),
 	PINMUX_IPSR_DATA(IP8_21_20, AVB_MDIO),
-	PINMUX_IPSR_DATA(IP8_21_20, MII_MDIO),
 	PINMUX_IPSR_MODSEL_DATA(IP8_23_22, VI1_DATA3_VI1_B3, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP8_23_22, SCIFA1_CTS_N_D, SEL_SCIFA1_3),
 	PINMUX_IPSR_DATA(IP8_23_22, AVB_GTX_CLK),
 	PINMUX_IPSR_MODSEL_DATA(IP8_25_24, VI1_DATA4_VI1_B4, SEL_VI1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP8_25_24, SCIFA1_RTS_N_D, SEL_SCIFA1_3),
 	PINMUX_IPSR_DATA(IP8_25_24, AVB_MAGIC),
-	PINMUX_IPSR_DATA(IP8_25_24, MII_MAGIC),
 	PINMUX_IPSR_MODSEL_DATA(IP8_26, VI1_DATA5_VI1_B5, SEL_VI1_0),
-	PINMUX_IPSR_MODSEL_DATA(IP8_26, AVB_PHY_INT, SEL_SCIFA1_3),
+	PINMUX_IPSR_DATA(IP8_26, AVB_PHY_INT),
 	PINMUX_IPSR_MODSEL_DATA(IP8_27, VI1_DATA6_VI1_B6, SEL_VI1_0),
 	PINMUX_IPSR_DATA(IP8_27, AVB_GTXREFCLK),
 	PINMUX_IPSR_DATA(IP8_28, SD0_CLK),
@@ -1372,8 +1288,8 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP9_11_8, USB0_EXTP),
 	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, GLO_SCLK, SEL_GPS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, VI1_DATA6_VI1_B6_B, SEL_VI1_1),
-	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, SCL1_B, SEL_IIC1_1),
-	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, SCL1_CIS_B, SEL_I2C1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, IIC1_SCL_B, SEL_IIC1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, I2C1_SCL_B, SEL_I2C1_1),
 	PINMUX_IPSR_MODSEL_DATA(IP9_11_8, VI2_DATA6_VI2_B6_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP9_15_12, SD0_WP),
 	PINMUX_IPSR_DATA(IP9_15_12, MMC0_D7),
@@ -1381,31 +1297,25 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP9_15_12, USB0_IDIN),
 	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, GLO_SDATA, SEL_GPS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, VI1_DATA7_VI1_B7_B, SEL_VI1_1),
-	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, SDA1_B, SEL_IIC1_1),
-	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, SDA1_CIS_B, SEL_I2C1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, IIC1_SDA_B, SEL_IIC1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, I2C1_SDA_B, SEL_I2C1_1),
 	PINMUX_IPSR_MODSEL_DATA(IP9_15_12, VI2_DATA7_VI2_B7_B, SEL_VI2_1),
 	PINMUX_IPSR_DATA(IP9_17_16, SD1_CLK),
 	PINMUX_IPSR_DATA(IP9_17_16, AVB_TX_EN),
-	PINMUX_IPSR_DATA(IP9_17_16, MII_TX_EN),
 	PINMUX_IPSR_DATA(IP9_19_18, SD1_CMD),
 	PINMUX_IPSR_DATA(IP9_19_18, AVB_TX_ER),
-	PINMUX_IPSR_DATA(IP9_19_18, MII_TX_ER),
 	PINMUX_IPSR_MODSEL_DATA(IP9_19_18, SCIFB0_SCK_B, SEL_SCIFB_1),
 	PINMUX_IPSR_DATA(IP9_21_20, SD1_DAT0),
 	PINMUX_IPSR_DATA(IP9_21_20, AVB_TX_CLK),
-	PINMUX_IPSR_DATA(IP9_21_20, MII_TX_CLK),
 	PINMUX_IPSR_MODSEL_DATA(IP9_21_20, SCIFB0_RXD_B, SEL_SCIFB_1),
 	PINMUX_IPSR_DATA(IP9_23_22, SD1_DAT1),
 	PINMUX_IPSR_DATA(IP9_23_22, AVB_LINK),
-	PINMUX_IPSR_DATA(IP9_23_22, MII_LINK),
 	PINMUX_IPSR_MODSEL_DATA(IP9_23_22, SCIFB0_TXD_B, SEL_SCIFB_1),
 	PINMUX_IPSR_DATA(IP9_25_24, SD1_DAT2),
 	PINMUX_IPSR_DATA(IP9_25_24, AVB_COL),
-	PINMUX_IPSR_DATA(IP9_25_24, MII_COL),
 	PINMUX_IPSR_MODSEL_DATA(IP9_25_24, SCIFB0_CTS_N_B, SEL_SCIFB_1),
 	PINMUX_IPSR_DATA(IP9_27_26, SD1_DAT3),
 	PINMUX_IPSR_DATA(IP9_27_26, AVB_RXD0),
-	PINMUX_IPSR_DATA(IP9_27_26, MII_RXD0),
 	PINMUX_IPSR_MODSEL_DATA(IP9_27_26, SCIFB0_RTS_N_B, SEL_SCIFB_1),
 	PINMUX_IPSR_DATA(IP9_31_28, SD1_CD),
 	PINMUX_IPSR_DATA(IP9_31_28, MMC1_D6),
@@ -1413,8 +1323,8 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP9_31_28, USB1_EXTP),
 	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, GLO_SS, SEL_GPS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, VI0_CLK_B, SEL_VI0_1),
-	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, SCL2_D, SEL_IIC2_3),
-	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, SCL2_CIS_D, SEL_I2C2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, IIC2_SCL_D, SEL_IIC2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, I2C2_SCL_D, SEL_I2C2_3),
 	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, SIM0_CLK_B, SEL_SIM_1),
 	PINMUX_IPSR_MODSEL_DATA(IP9_31_28, VI3_CLK_B, SEL_VI3_1),
 
@@ -1424,8 +1334,8 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP10_3_0, USB1_IDIN),
 	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, GLO_RFON, SEL_GPS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, VI1_CLK_B, SEL_VI1_1),
-	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, SDA2_D, SEL_IIC2_3),
-	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, SDA2_CIS_D, SEL_I2C2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, IIC2_SDA_D, SEL_IIC2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, I2C2_SDA_D, SEL_I2C2_3),
 	PINMUX_IPSR_MODSEL_DATA(IP10_3_0, SIM0_D_B, SEL_SIM_1),
 	PINMUX_IPSR_DATA(IP10_6_4, SD2_CLK),
 	PINMUX_IPSR_DATA(IP10_6_4, MMC0_CLK),
@@ -1455,7 +1365,6 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP10_18_15, SD2_DAT1),
 	PINMUX_IPSR_DATA(IP10_18_15, MMC0_D1),
 	PINMUX_IPSR_MODSEL_DATA(IP10_18_15, FMIN_B, SEL_FM_1),
-	PINMUX_IPSR_MODSEL_DATA(IP10_18_15, RDS_DATA, SEL_RDS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP10_18_15, VI0_DATA3_VI0_B3_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP10_18_15, SCIFB1_TXD_E, SEL_SCIFB1_4),
 	PINMUX_IPSR_MODSEL_DATA(IP10_18_15, TX1_D, SEL_SCIF1_3),
@@ -1465,7 +1374,6 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP10_22_19, SD2_DAT2),
 	PINMUX_IPSR_DATA(IP10_22_19, MMC0_D2),
 	PINMUX_IPSR_MODSEL_DATA(IP10_22_19, BPFCLK_B, SEL_FM_1),
-	PINMUX_IPSR_MODSEL_DATA(IP10_22_19, RDS_CLK, SEL_RDS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP10_22_19, VI0_DATA4_VI0_B4_B, SEL_VI0_1),
 	PINMUX_IPSR_MODSEL_DATA(IP10_22_19, HRX0_D, SEL_HSCIF0_3),
 	PINMUX_IPSR_MODSEL_DATA(IP10_22_19, TS_SDEN1_B, SEL_TSIF1_1),
@@ -1528,25 +1436,20 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, TS_SCK1, SEL_TSIF1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, GLO_Q1, SEL_GPS_0),
 	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, FMIN_C, SEL_FM_2),
-	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, RDS_DATA_B, SEL_RDS_1),
 	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, FMIN_E, SEL_FM_4),
-	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, RDS_DATA_D, SEL_RDS_3),
 	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, FMIN_F, SEL_FM_5),
-	PINMUX_IPSR_MODSEL_DATA(IP11_21_18, RDS_DATA_E, SEL_RDS_4),
 	PINMUX_IPSR_DATA(IP11_23_22, MLB_CLK),
-	PINMUX_IPSR_MODSEL_DATA(IP11_23_22, SCL2_B, SEL_IIC2_1),
-	PINMUX_IPSR_MODSEL_DATA(IP11_23_22, SCL2_CIS_B, SEL_I2C2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_23_22, IIC2_SCL_B, SEL_IIC2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_23_22, I2C2_SCL_B, SEL_I2C2_1),
 	PINMUX_IPSR_DATA(IP11_26_24, MLB_SIG),
 	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, SCIFB1_RXD_D, SEL_SCIFB1_3),
 	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, RX1_C, SEL_SCIF1_2),
-	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, SDA2_B, SEL_IIC2_1),
-	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, SDA2_CIS_B, SEL_I2C2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, IIC2_SDA_B, SEL_IIC2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, I2C2_SDA_B, SEL_I2C2_1),
 	PINMUX_IPSR_DATA(IP11_29_27, MLB_DAT),
-	PINMUX_IPSR_DATA(IP11_29_27, SPV_EVEN),
 	PINMUX_IPSR_MODSEL_DATA(IP11_29_27, SCIFB1_TXD_D, SEL_SCIFB1_3),
 	PINMUX_IPSR_MODSEL_DATA(IP11_29_27, TX1_C, SEL_SCIF1_2),
 	PINMUX_IPSR_MODSEL_DATA(IP11_29_27, BPFCLK_C, SEL_FM_2),
-	PINMUX_IPSR_MODSEL_DATA(IP11_29_27, RDS_CLK_B, SEL_RDS_1),
 	PINMUX_IPSR_DATA(IP11_31_30, SSI_SCK0129),
 	PINMUX_IPSR_MODSEL_DATA(IP11_31_30, CAN_CLK_B, SEL_CANCLK_1),
 	PINMUX_IPSR_DATA(IP11_31_30, MOUT0),
@@ -1562,7 +1465,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP12_5_4, MOUT5),
 	PINMUX_IPSR_DATA(IP12_7_6, SSI_SDATA2),
 	PINMUX_IPSR_MODSEL_DATA(IP12_7_6, CAN1_RX_B, SEL_CAN1_1),
-	PINMUX_IPSR_MODSEL_DATA(IP12_7_6, CAN1_TX_B, SEL_CAN1_1),
+	PINMUX_IPSR_DATA(IP12_7_6, SSI_SCK1),
 	PINMUX_IPSR_DATA(IP12_7_6, MOUT6),
 	PINMUX_IPSR_DATA(IP12_10_8, SSI_SCK34),
 	PINMUX_IPSR_DATA(IP12_10_8, STP_OPWM_0),
@@ -1617,12 +1520,10 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP13_6_3, SSI_SCK6, SEL_SSI6_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_6_3, SCIFB1_CTS_N, SEL_SCIFB1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_6_3, BPFCLK_D, SEL_FM_3),
-	PINMUX_IPSR_MODSEL_DATA(IP13_6_3, RDS_CLK_C, SEL_RDS_2),
 	PINMUX_IPSR_DATA(IP13_6_3, DU2_DR3),
 	PINMUX_IPSR_DATA(IP13_6_3, LCDOUT3),
 	PINMUX_IPSR_DATA(IP13_6_3, CAN_DEBUGOUT6),
 	PINMUX_IPSR_MODSEL_DATA(IP13_6_3, BPFCLK_F, SEL_FM_5),
-	PINMUX_IPSR_MODSEL_DATA(IP13_6_3, RDS_CLK_E, SEL_RDS_4),
 	PINMUX_IPSR_MODSEL_DATA(IP13_9_7, SSI_WS6, SEL_SSI6_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_9_7, SCIFB1_RTS_N, SEL_SCIFB1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_9_7, CAN0_TX_D, SEL_CAN0_3),
@@ -1631,7 +1532,6 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP13_9_7, CAN_DEBUGOUT7),
 	PINMUX_IPSR_MODSEL_DATA(IP13_12_10, SSI_SDATA6, SEL_SSI6_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_12_10, FMIN_D, SEL_FM_3),
-	PINMUX_IPSR_MODSEL_DATA(IP13_12_10, RDS_DATA_C, SEL_RDS_2),
 	PINMUX_IPSR_DATA(IP13_12_10, DU2_DR5),
 	PINMUX_IPSR_DATA(IP13_12_10, LCDOUT5),
 	PINMUX_IPSR_DATA(IP13_12_10, CAN_DEBUGOUT8),
@@ -1657,10 +1557,8 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP13_22_19, QSTVA_QVS),
 	PINMUX_IPSR_DATA(IP13_22_19, CAN_DEBUGOUT11),
 	PINMUX_IPSR_MODSEL_DATA(IP13_22_19, BPFCLK_E, SEL_FM_4),
-	PINMUX_IPSR_MODSEL_DATA(IP13_22_19, RDS_CLK_D, SEL_RDS_3),
 	PINMUX_IPSR_MODSEL_DATA(IP13_22_19, SSI_SDATA7_B, SEL_SSI7_1),
 	PINMUX_IPSR_MODSEL_DATA(IP13_22_19, FMIN_G, SEL_FM_6),
-	PINMUX_IPSR_MODSEL_DATA(IP13_22_19, RDS_DATA_F, SEL_RDS_5),
 	PINMUX_IPSR_MODSEL_DATA(IP13_25_23, SSI_SDATA8, SEL_SSI8_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_25_23, STP_ISEN_1, SEL_SSP_0),
 	PINMUX_IPSR_MODSEL_DATA(IP13_25_23, SCIFB2_TXD, SEL_SCIFB2_0),
@@ -1690,8 +1588,8 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP14_5_3, MSIOF3_SS2),
 	PINMUX_IPSR_DATA(IP14_5_3, DU2_DG2),
 	PINMUX_IPSR_DATA(IP14_5_3, LCDOUT10),
-	PINMUX_IPSR_MODSEL_DATA(IP14_5_3, SDA1_C, SEL_IIC1_2),
-	PINMUX_IPSR_MODSEL_DATA(IP14_5_3, SDA1_CIS_C, SEL_I2C1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_5_3, IIC1_SDA_C, SEL_IIC1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_5_3, I2C1_SDA_C, SEL_I2C1_2),
 	PINMUX_IPSR_MODSEL_DATA(IP14_8_6, SCIFA0_RXD, SEL_SCFA_0),
 	PINMUX_IPSR_MODSEL_DATA(IP14_8_6, HRX1, SEL_HSCIF1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP14_8_6, RX0, SEL_SCIF0_0),
@@ -1704,16 +1602,16 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP14_11_9, LCDOUT1),
 	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, SCIFA0_CTS_N, SEL_SCFA_0),
 	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, HCTS1_N, SEL_HSCIF1_0),
-	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, CTS0_N, SEL_SCIF0_0),
+	PINMUX_IPSR_DATA(IP14_15_12, CTS0_N),
 	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, MSIOF3_SYNC, SEL_SOF3_0),
 	PINMUX_IPSR_DATA(IP14_15_12, DU2_DG3),
-	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, LCDOUT11, SEL_HSCIF1_0),
-	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, PWM0_B, SEL_SCIF0_0),
-	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, SCL1_C, SEL_IIC1_2),
-	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, SCL1_CIS_C, SEL_I2C1_2),
+	PINMUX_IPSR_DATA(IP14_15_12, LCDOUT11),
+	PINMUX_IPSR_DATA(IP14_15_12, PWM0_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, IIC1_SCL_C, SEL_IIC1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_15_12, I2C1_SCL_C, SEL_I2C1_2),
 	PINMUX_IPSR_MODSEL_DATA(IP14_18_16, SCIFA0_RTS_N, SEL_SCFA_0),
 	PINMUX_IPSR_MODSEL_DATA(IP14_18_16, HRTS1_N, SEL_HSCIF1_0),
-	PINMUX_IPSR_DATA(IP14_18_16, RTS0_N_TANS),
+	PINMUX_IPSR_DATA(IP14_18_16, RTS0_N),
 	PINMUX_IPSR_DATA(IP14_18_16, MSIOF3_SS1),
 	PINMUX_IPSR_DATA(IP14_18_16, DU2_DG0),
 	PINMUX_IPSR_DATA(IP14_18_16, LCDOUT8),
@@ -1736,7 +1634,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP14_27_25, QCLK),
 	PINMUX_IPSR_MODSEL_DATA(IP14_30_28, SCIFA1_RTS_N, SEL_SCIFA1_0),
 	PINMUX_IPSR_MODSEL_DATA(IP14_30_28, AD_NCS_N, SEL_ADI_0),
-	PINMUX_IPSR_DATA(IP14_30_28, RTS1_N_TANS),
+	PINMUX_IPSR_DATA(IP14_30_28, RTS1_N),
 	PINMUX_IPSR_MODSEL_DATA(IP14_30_28, MSIOF3_TXD, SEL_SOF3_0),
 	PINMUX_IPSR_DATA(IP14_30_28, DU1_DOTCLKOUT),
 	PINMUX_IPSR_DATA(IP14_30_28, QSTVB_QVE),
@@ -1744,28 +1642,30 @@ static const pinmux_enum_t pinmux_data[] = {
 
 	PINMUX_IPSR_MODSEL_DATA(IP15_2_0, SCIFA2_SCK, SEL_SCIFA2_0),
 	PINMUX_IPSR_MODSEL_DATA(IP15_2_0, FMCLK, SEL_FM_0),
+	PINMUX_IPSR_DATA(IP15_2_0, SCK2),
 	PINMUX_IPSR_MODSEL_DATA(IP15_2_0, MSIOF3_SCK, SEL_SOF3_0),
 	PINMUX_IPSR_DATA(IP15_2_0, DU2_DG7),
 	PINMUX_IPSR_DATA(IP15_2_0, LCDOUT15),
-	PINMUX_IPSR_MODSEL_DATA(IP15_2_0, SCIF_CLK_B, SEL_SCIFCLK_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_2_0, SCIF_CLK_B, SEL_SCIFCLK_1),
 	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
 	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, FMIN, SEL_FM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, TX2, SEL_SCIF2_0),
 	PINMUX_IPSR_DATA(IP15_5_3, DU2_DB0),
 	PINMUX_IPSR_DATA(IP15_5_3, LCDOUT16),
-	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, SCL2, SEL_IIC2_0),
-	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, SCL2_CIS, SEL_I2C2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, IIC2_SCL, SEL_IIC2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_5_3, I2C2_SCL, SEL_I2C2_0),
 	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, SCIFA2_TXD, SEL_SCIFA2_0),
 	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, BPFCLK, SEL_FM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, RX2, SEL_SCIF2_0),
 	PINMUX_IPSR_DATA(IP15_8_6, DU2_DB1),
 	PINMUX_IPSR_DATA(IP15_8_6, LCDOUT17),
-	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, SDA2, SEL_IIC2_0),
-	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, SDA2_CIS, SEL_I2C2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, IIC2_SDA, SEL_IIC2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, I2C2_SDA, SEL_I2C2_0),
 	PINMUX_IPSR_DATA(IP15_11_9, HSCK0),
 	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, TS_SDEN0, SEL_TSIF0_0),
 	PINMUX_IPSR_DATA(IP15_11_9, DU2_DG4),
 	PINMUX_IPSR_DATA(IP15_11_9, LCDOUT12),
-	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, HCTS0_N_C, SEL_IIC2_0),
-	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, SDA2_CIS, SEL_I2C2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, HCTS0_N_C, SEL_HSCIF0_2),
 	PINMUX_IPSR_MODSEL_DATA(IP15_13_12, HRX0, SEL_HSCIF0_0),
 	PINMUX_IPSR_DATA(IP15_13_12, DU2_DB2),
 	PINMUX_IPSR_DATA(IP15_13_12, LCDOUT18),
@@ -1791,7 +1691,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP15_25_23, ADIDATA),
 	PINMUX_IPSR_DATA(IP15_25_23, DU2_DB7),
 	PINMUX_IPSR_DATA(IP15_25_23, LCDOUT23),
-	PINMUX_IPSR_MODSEL_DATA(IP15_25_23, SCIFA2_RXD_B, SEL_SCIFA2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP15_25_23, HRX0_C, SEL_SCIFA2_1),
 	PINMUX_IPSR_MODSEL_DATA(IP15_27_26, MSIOF0_SS1, SEL_SOF0_0),
 	PINMUX_IPSR_DATA(IP15_27_26, ADICHS0),
 	PINMUX_IPSR_DATA(IP15_27_26, DU2_DG5),
@@ -1814,7 +1714,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP16_5_3, ADICS_SAMP),
 	PINMUX_IPSR_DATA(IP16_5_3, DU2_CDE),
 	PINMUX_IPSR_DATA(IP16_5_3, QPOLB),
-	PINMUX_IPSR_MODSEL_DATA(IP16_5_3, HRX0_C, SEL_HSCIF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP16_5_3, SCIFA2_RXD_B, SEL_HSCIF0_2),
 	PINMUX_IPSR_DATA(IP16_6, USB1_PWEN),
 	PINMUX_IPSR_DATA(IP16_6, AUDIO_CLKOUT_D),
 	PINMUX_IPSR_DATA(IP16_7, USB1_OVC),
@@ -1857,128 +1757,6 @@ static const unsigned int eth_rmii_mux[] = {
 	ETH_RXD0_MARK, ETH_RXD1_MARK, ETH_RX_ER_MARK, ETH_CRS_DV_MARK,
 	ETH_TXD0_MARK, ETH_TXD1_MARK, ETH_TX_EN_MARK, ETH_REF_CLK_MARK,
 };
-/* - INTC ------------------------------------------------------------------- */
-static const unsigned int intc_irq0_pins[] = {
-	/* IRQ */
-	RCAR_GP_PIN(1, 25),
-};
-static const unsigned int intc_irq0_mux[] = {
-	IRQ0_MARK,
-};
-static const unsigned int intc_irq1_pins[] = {
-	/* IRQ */
-	RCAR_GP_PIN(1, 27),
-};
-static const unsigned int intc_irq1_mux[] = {
-	IRQ1_MARK,
-};
-static const unsigned int intc_irq2_pins[] = {
-	/* IRQ */
-	RCAR_GP_PIN(1, 29),
-};
-static const unsigned int intc_irq2_mux[] = {
-	IRQ2_MARK,
-};
-static const unsigned int intc_irq3_pins[] = {
-	/* IRQ */
-	RCAR_GP_PIN(1, 23),
-};
-static const unsigned int intc_irq3_mux[] = {
-	IRQ3_MARK,
-};
-/* - SCIF0 ----------------------------------------------------------------- */
-static const unsigned int scif0_data_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 29),
-};
-static const unsigned int scif0_data_mux[] = {
-	RX0_MARK, TX0_MARK,
-};
-static const unsigned int scif0_clk_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(4, 27),
-};
-static const unsigned int scif0_clk_mux[] = {
-	SCK0_MARK,
-};
-static const unsigned int scif0_ctrl_pins[] = {
-	/* RTS, CTS */
-	RCAR_GP_PIN(4, 31), RCAR_GP_PIN(4, 30),
-};
-static const unsigned int scif0_ctrl_mux[] = {
-	RTS0_N_TANS_MARK, CTS0_N_MARK,
-};
-static const unsigned int scif0_data_b_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5),
-};
-static const unsigned int scif0_data_b_mux[] = {
-	RX0_B_MARK, TX0_B_MARK,
-};
-/* - SCIF1 ----------------------------------------------------------------- */
-static const unsigned int scif1_data_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 1),
-};
-static const unsigned int scif1_data_mux[] = {
-	RX1_MARK, TX1_MARK,
-};
-static const unsigned int scif1_clk_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(4, 20),
-};
-static const unsigned int scif1_clk_mux[] = {
-	SCK1_MARK,
-};
-static const unsigned int scif1_ctrl_pins[] = {
-	/* RTS, CTS */
-	RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 2),
-};
-static const unsigned int scif1_ctrl_mux[] = {
-	RTS1_N_TANS_MARK, CTS1_N_MARK,
-};
-static const unsigned int scif1_data_b_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15),
-};
-static const unsigned int scif1_data_b_mux[] = {
-	RX1_B_MARK, TX1_B_MARK,
-};
-static const unsigned int scif1_data_c_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 2),
-};
-static const unsigned int scif1_data_c_mux[] = {
-	RX1_C_MARK, TX1_C_MARK,
-};
-static const unsigned int scif1_data_d_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
-};
-static const unsigned int scif1_data_d_mux[] = {
-	RX1_D_MARK, TX1_D_MARK,
-};
-static const unsigned int scif1_clk_d_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(3, 17),
-};
-static const unsigned int scif1_clk_d_mux[] = {
-	SCK1_D_MARK,
-};
-static const unsigned int scif1_data_e_pins[] = {
-	/* RX, TX */
-	RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22),
-};
-static const unsigned int scif1_data_e_mux[] = {
-	RX1_E_MARK, TX1_E_MARK,
-};
-static const unsigned int scif1_clk_e_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(2, 20),
-};
-static const unsigned int scif1_clk_e_mux[] = {
-	SCK1_E_MARK,
-};
 /* - HSCIF0 ----------------------------------------------------------------- */
 static const unsigned int hscif0_data_pins[] = {
 	/* RX, TX */
@@ -2114,90 +1892,474 @@ static const unsigned int hscif1_ctrl_b_pins[] = {
 static const unsigned int hscif1_ctrl_b_mux[] = {
 	HRTS1_N_B_MARK, HCTS1_N_B_MARK,
 };
-/* - SCIFA0 ----------------------------------------------------------------- */
-static const unsigned int scifa0_data_pins[] = {
-	/* RXD, TXD */
-	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 29),
+/* - INTC ------------------------------------------------------------------- */
+static const unsigned int intc_irq0_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(1, 25),
 };
-static const unsigned int scifa0_data_mux[] = {
-	SCIFA0_RXD_MARK, SCIFA0_TXD_MARK,
+static const unsigned int intc_irq0_mux[] = {
+	IRQ0_MARK,
 };
-static const unsigned int scifa0_clk_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(4, 27),
+static const unsigned int intc_irq1_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(1, 27),
 };
-static const unsigned int scifa0_clk_mux[] = {
-	SCIFA0_SCK_MARK,
+static const unsigned int intc_irq1_mux[] = {
+	IRQ1_MARK,
 };
-static const unsigned int scifa0_ctrl_pins[] = {
-	/* RTS, CTS */
-	RCAR_GP_PIN(4, 31), RCAR_GP_PIN(4, 30),
+static const unsigned int intc_irq2_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(1, 29),
 };
-static const unsigned int scifa0_ctrl_mux[] = {
-	SCIFA0_RTS_N_MARK, SCIFA0_CTS_N_MARK,
+static const unsigned int intc_irq2_mux[] = {
+	IRQ2_MARK,
 };
-static const unsigned int scifa0_data_b_pins[] = {
-	/* RXD, TXD */
-	RCAR_GP_PIN(1, 20), RCAR_GP_PIN(1, 21),
+static const unsigned int intc_irq3_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(1, 23),
 };
-static const unsigned int scifa0_data_b_mux[] = {
-	SCIFA0_RXD_B_MARK, SCIFA0_TXD_B_MARK
+static const unsigned int intc_irq3_mux[] = {
+	IRQ3_MARK,
 };
-static const unsigned int scifa0_clk_b_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(1, 19),
+/* - MMCIF0 ----------------------------------------------------------------- */
+static const unsigned int mmc0_data1_pins[] = {
+	/* D[0] */
+	RCAR_GP_PIN(3, 18),
 };
-static const unsigned int scifa0_clk_b_mux[] = {
-	SCIFA0_SCK_B_MARK,
+static const unsigned int mmc0_data1_mux[] = {
+	MMC0_D0_MARK,
 };
-static const unsigned int scifa0_ctrl_b_pins[] = {
-	/* RTS, CTS */
-	RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 22),
+static const unsigned int mmc0_data4_pins[] = {
+	/* D[0:3] */
+	RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
+	RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 21),
 };
-static const unsigned int scifa0_ctrl_b_mux[] = {
-	SCIFA0_RTS_N_B_MARK, SCIFA0_CTS_N_B_MARK,
+static const unsigned int mmc0_data4_mux[] = {
+	MMC0_D0_MARK, MMC0_D1_MARK, MMC0_D2_MARK, MMC0_D3_MARK,
 };
-/* - SCIFA1 ----------------------------------------------------------------- */
-static const unsigned int scifa1_data_pins[] = {
-	/* RXD, TXD */
-	RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 1),
+static const unsigned int mmc0_data8_pins[] = {
+	/* D[0:7] */
+	RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
+	RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 21),
+	RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 23),
+	RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
 };
-static const unsigned int scifa1_data_mux[] = {
-	SCIFA1_RXD_MARK, SCIFA1_TXD_MARK,
+static const unsigned int mmc0_data8_mux[] = {
+	MMC0_D0_MARK, MMC0_D1_MARK, MMC0_D2_MARK, MMC0_D3_MARK,
+	MMC0_D4_MARK, MMC0_D5_MARK, MMC0_D6_MARK, MMC0_D7_MARK,
 };
-static const unsigned int scifa1_clk_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(4, 20),
+static const unsigned int mmc0_ctrl_pins[] = {
+	/* CLK, CMD */
+	RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 17),
 };
-static const unsigned int scifa1_clk_mux[] = {
-	SCIFA1_SCK_MARK,
+static const unsigned int mmc0_ctrl_mux[] = {
+	MMC0_CLK_MARK, MMC0_CMD_MARK,
 };
-static const unsigned int scifa1_ctrl_pins[] = {
-	/* RTS, CTS */
-	RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 2),
+/* - MMCIF1 ----------------------------------------------------------------- */
+static const unsigned int mmc1_data1_pins[] = {
+	/* D[0] */
+	RCAR_GP_PIN(3, 26),
 };
-static const unsigned int scifa1_ctrl_mux[] = {
-	SCIFA1_RTS_N_MARK, SCIFA1_CTS_N_MARK,
+static const unsigned int mmc1_data1_mux[] = {
+	MMC1_D0_MARK,
 };
-static const unsigned int scifa1_data_b_pins[] = {
-	/* RXD, TXD */
-	RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 21),
+static const unsigned int mmc1_data4_pins[] = {
+	/* D[0:3] */
+	RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 27),
+	RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 29),
 };
-static const unsigned int scifa1_data_b_mux[] = {
-	SCIFA1_RXD_B_MARK, SCIFA1_TXD_B_MARK,
+static const unsigned int mmc1_data4_mux[] = {
+	MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK,
 };
-static const unsigned int scifa1_clk_b_pins[] = {
-	/* SCK */
-	RCAR_GP_PIN(0, 23),
+static const unsigned int mmc1_data8_pins[] = {
+	/* D[0:7] */
+	RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 27),
+	RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 29),
+	RCAR_GP_PIN(3, 30), RCAR_GP_PIN(3, 31),
+	RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15),
 };
-static const unsigned int scifa1_clk_b_mux[] = {
-	SCIFA1_SCK_B_MARK,
+static const unsigned int mmc1_data8_mux[] = {
+	MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK,
+	MMC1_D4_MARK, MMC1_D5_MARK, MMC1_D6_MARK, MMC1_D7_MARK,
 };
-static const unsigned int scifa1_ctrl_b_pins[] = {
-	/* RTS, CTS */
-	RCAR_GP_PIN(0, 22), RCAR_GP_PIN(0, 25),
+static const unsigned int mmc1_ctrl_pins[] = {
+	/* CLK, CMD */
+	RCAR_GP_PIN(3, 24), RCAR_GP_PIN(3, 25),
 };
-static const unsigned int scifa1_ctrl_b_mux[] = {
+static const unsigned int mmc1_ctrl_mux[] = {
+	MMC1_CLK_MARK, MMC1_CMD_MARK,
+};
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 12),
+};
+static const unsigned int msiof0_clk_mux[] = {
+	MSIOF0_SCK_MARK,
+};
+static const unsigned int msiof0_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(5, 13),
+};
+static const unsigned int msiof0_sync_mux[] = {
+	MSIOF0_SYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(5, 14),
+};
+static const unsigned int msiof0_ss1_mux[] = {
+	MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(5, 16),
+};
+static const unsigned int msiof0_ss2_mux[] = {
+	MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(5, 17),
+};
+static const unsigned int msiof0_rx_mux[] = {
+	MSIOF0_RXD_MARK,
+};
+static const unsigned int msiof0_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(5, 15),
+};
+static const unsigned int msiof0_tx_mux[] = {
+	MSIOF0_TXD_MARK,
+};
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 8),
+};
+static const unsigned int msiof1_clk_mux[] = {
+	MSIOF1_SCK_MARK,
+};
+static const unsigned int msiof1_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(4, 9),
+};
+static const unsigned int msiof1_sync_mux[] = {
+	MSIOF1_SYNC_MARK,
+};
+static const unsigned int msiof1_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(4, 10),
+};
+static const unsigned int msiof1_ss1_mux[] = {
+	MSIOF1_SS1_MARK,
+};
+static const unsigned int msiof1_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(4, 11),
+};
+static const unsigned int msiof1_ss2_mux[] = {
+	MSIOF1_SS2_MARK,
+};
+static const unsigned int msiof1_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(4, 13),
+};
+static const unsigned int msiof1_rx_mux[] = {
+	MSIOF1_RXD_MARK,
+};
+static const unsigned int msiof1_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(4, 12),
+};
+static const unsigned int msiof1_tx_mux[] = {
+	MSIOF1_TXD_MARK,
+};
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(0, 27),
+};
+static const unsigned int msiof2_clk_mux[] = {
+	MSIOF2_SCK_MARK,
+};
+static const unsigned int msiof2_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(0, 26),
+};
+static const unsigned int msiof2_sync_mux[] = {
+	MSIOF2_SYNC_MARK,
+};
+static const unsigned int msiof2_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(0, 30),
+};
+static const unsigned int msiof2_ss1_mux[] = {
+	MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(0, 31),
+};
+static const unsigned int msiof2_ss2_mux[] = {
+	MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(0, 29),
+};
+static const unsigned int msiof2_rx_mux[] = {
+	MSIOF2_RXD_MARK,
+};
+static const unsigned int msiof2_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(0, 28),
+};
+static const unsigned int msiof2_tx_mux[] = {
+	MSIOF2_TXD_MARK,
+};
+/* - MSIOF3 ----------------------------------------------------------------- */
+static const unsigned int msiof3_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 4),
+};
+static const unsigned int msiof3_clk_mux[] = {
+	MSIOF3_SCK_MARK,
+};
+static const unsigned int msiof3_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(4, 30),
+};
+static const unsigned int msiof3_sync_mux[] = {
+	MSIOF3_SYNC_MARK,
+};
+static const unsigned int msiof3_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(4, 31),
+};
+static const unsigned int msiof3_ss1_mux[] = {
+	MSIOF3_SS1_MARK,
+};
+static const unsigned int msiof3_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(4, 27),
+};
+static const unsigned int msiof3_ss2_mux[] = {
+	MSIOF3_SS2_MARK,
+};
+static const unsigned int msiof3_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(5, 2),
+};
+static const unsigned int msiof3_rx_mux[] = {
+	MSIOF3_RXD_MARK,
+};
+static const unsigned int msiof3_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(5, 3),
+};
+static const unsigned int msiof3_tx_mux[] = {
+	MSIOF3_TXD_MARK,
+};
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 29),
+};
+static const unsigned int scif0_data_mux[] = {
+	RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 27),
+};
+static const unsigned int scif0_clk_mux[] = {
+	SCK0_MARK,
+};
+static const unsigned int scif0_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(4, 31), RCAR_GP_PIN(4, 30),
+};
+static const unsigned int scif0_ctrl_mux[] = {
+	RTS0_N_MARK, CTS0_N_MARK,
+};
+static const unsigned int scif0_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5),
+};
+static const unsigned int scif0_data_b_mux[] = {
+	RX0_B_MARK, TX0_B_MARK,
+};
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 1),
+};
+static const unsigned int scif1_data_mux[] = {
+	RX1_MARK, TX1_MARK,
+};
+static const unsigned int scif1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 20),
+};
+static const unsigned int scif1_clk_mux[] = {
+	SCK1_MARK,
+};
+static const unsigned int scif1_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 2),
+};
+static const unsigned int scif1_ctrl_mux[] = {
+	RTS1_N_MARK, CTS1_N_MARK,
+};
+static const unsigned int scif1_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15),
+};
+static const unsigned int scif1_data_b_mux[] = {
+	RX1_B_MARK, TX1_B_MARK,
+};
+static const unsigned int scif1_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 2),
+};
+static const unsigned int scif1_data_c_mux[] = {
+	RX1_C_MARK, TX1_C_MARK,
+};
+static const unsigned int scif1_data_d_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
+};
+static const unsigned int scif1_data_d_mux[] = {
+	RX1_D_MARK, TX1_D_MARK,
+};
+static const unsigned int scif1_clk_d_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 17),
+};
+static const unsigned int scif1_clk_d_mux[] = {
+	SCK1_D_MARK,
+};
+static const unsigned int scif1_data_e_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22),
+};
+static const unsigned int scif1_data_e_mux[] = {
+	RX1_E_MARK, TX1_E_MARK,
+};
+static const unsigned int scif1_clk_e_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(2, 20),
+};
+static const unsigned int scif1_clk_e_mux[] = {
+	SCK1_E_MARK,
+};
+/* - SCIF2 ------------------------------------------------------------------ */
+static const unsigned int scif2_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 5),
+};
+static const unsigned int scif2_data_mux[] = {
+	RX2_MARK, TX2_MARK,
+};
+static const unsigned int scif2_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 4),
+};
+static const unsigned int scif2_clk_mux[] = {
+	SCK2_MARK,
+};
+static const unsigned int scif2_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25),
+};
+static const unsigned int scif2_data_b_mux[] = {
+	RX2_B_MARK, TX2_B_MARK,
+};
+/* - SCIFA0 ----------------------------------------------------------------- */
+static const unsigned int scifa0_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 29),
+};
+static const unsigned int scifa0_data_mux[] = {
+	SCIFA0_RXD_MARK, SCIFA0_TXD_MARK,
+};
+static const unsigned int scifa0_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 27),
+};
+static const unsigned int scifa0_clk_mux[] = {
+	SCIFA0_SCK_MARK,
+};
+static const unsigned int scifa0_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(4, 31), RCAR_GP_PIN(4, 30),
+};
+static const unsigned int scifa0_ctrl_mux[] = {
+	SCIFA0_RTS_N_MARK, SCIFA0_CTS_N_MARK,
+};
+static const unsigned int scifa0_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 20), RCAR_GP_PIN(1, 21),
+};
+static const unsigned int scifa0_data_b_mux[] = {
+	SCIFA0_RXD_B_MARK, SCIFA0_TXD_B_MARK
+};
+static const unsigned int scifa0_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(1, 19),
+};
+static const unsigned int scifa0_clk_b_mux[] = {
+	SCIFA0_SCK_B_MARK,
+};
+static const unsigned int scifa0_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 22),
+};
+static const unsigned int scifa0_ctrl_b_mux[] = {
+	SCIFA0_RTS_N_B_MARK, SCIFA0_CTS_N_B_MARK,
+};
+/* - SCIFA1 ----------------------------------------------------------------- */
+static const unsigned int scifa1_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 1),
+};
+static const unsigned int scifa1_data_mux[] = {
+	SCIFA1_RXD_MARK, SCIFA1_TXD_MARK,
+};
+static const unsigned int scifa1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 20),
+};
+static const unsigned int scifa1_clk_mux[] = {
+	SCIFA1_SCK_MARK,
+};
+static const unsigned int scifa1_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 2),
+};
+static const unsigned int scifa1_ctrl_mux[] = {
+	SCIFA1_RTS_N_MARK, SCIFA1_CTS_N_MARK,
+};
+static const unsigned int scifa1_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 21),
+};
+static const unsigned int scifa1_data_b_mux[] = {
+	SCIFA1_RXD_B_MARK, SCIFA1_TXD_B_MARK,
+};
+static const unsigned int scifa1_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(0, 23),
+};
+static const unsigned int scifa1_clk_b_mux[] = {
+	SCIFA1_SCK_B_MARK,
+};
+static const unsigned int scifa1_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(0, 22), RCAR_GP_PIN(0, 25),
+};
+static const unsigned int scifa1_ctrl_b_mux[] = {
 	SCIFA1_RTS_N_B_MARK, SCIFA1_CTS_N_B_MARK,
 };
 static const unsigned int scifa1_data_c_pins[] = {
@@ -2477,103 +2639,6 @@ static const unsigned int scifb2_data_c_pins[] = {
 static const unsigned int scifb2_data_c_mux[] = {
 	SCIFB2_RXD_C_MARK, SCIFB2_TXD_C_MARK,
 };
-/* - TPU0 ------------------------------------------------------------------- */
-static const unsigned int tpu0_to0_pins[] = {
-	/* TO */
-	RCAR_GP_PIN(0, 20),
-};
-static const unsigned int tpu0_to0_mux[] = {
-	TPU0TO0_MARK,
-};
-static const unsigned int tpu0_to1_pins[] = {
-	/* TO */
-	RCAR_GP_PIN(0, 21),
-};
-static const unsigned int tpu0_to1_mux[] = {
-	TPU0TO1_MARK,
-};
-static const unsigned int tpu0_to2_pins[] = {
-	/* TO */
-	RCAR_GP_PIN(0, 22),
-};
-static const unsigned int tpu0_to2_mux[] = {
-	TPU0TO2_MARK,
-};
-static const unsigned int tpu0_to3_pins[] = {
-	/* TO */
-	RCAR_GP_PIN(0, 23),
-};
-static const unsigned int tpu0_to3_mux[] = {
-	TPU0TO3_MARK,
-};
-/* - MMCIF0 ----------------------------------------------------------------- */
-static const unsigned int mmc0_data1_pins[] = {
-	/* D[0] */
-	RCAR_GP_PIN(3, 18),
-};
-static const unsigned int mmc0_data1_mux[] = {
-	MMC0_D0_MARK,
-};
-static const unsigned int mmc0_data4_pins[] = {
-	/* D[0:3] */
-	RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
-	RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 21),
-};
-static const unsigned int mmc0_data4_mux[] = {
-	MMC0_D0_MARK, MMC0_D1_MARK, MMC0_D2_MARK, MMC0_D3_MARK,
-};
-static const unsigned int mmc0_data8_pins[] = {
-	/* D[0:7] */
-	RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
-	RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 21),
-	RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 23),
-	RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
-};
-static const unsigned int mmc0_data8_mux[] = {
-	MMC0_D0_MARK, MMC0_D1_MARK, MMC0_D2_MARK, MMC0_D3_MARK,
-	MMC0_D4_MARK, MMC0_D5_MARK, MMC0_D6_MARK, MMC0_D7_MARK,
-};
-static const unsigned int mmc0_ctrl_pins[] = {
-	/* CLK, CMD */
-	RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 17),
-};
-static const unsigned int mmc0_ctrl_mux[] = {
-	MMC0_CLK_MARK, MMC0_CMD_MARK,
-};
-/* - MMCIF1 ----------------------------------------------------------------- */
-static const unsigned int mmc1_data1_pins[] = {
-	/* D[0] */
-	RCAR_GP_PIN(3, 26),
-};
-static const unsigned int mmc1_data1_mux[] = {
-	MMC1_D0_MARK,
-};
-static const unsigned int mmc1_data4_pins[] = {
-	/* D[0:3] */
-	RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 27),
-	RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 29),
-};
-static const unsigned int mmc1_data4_mux[] = {
-	MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK,
-};
-static const unsigned int mmc1_data8_pins[] = {
-	/* D[0:7] */
-	RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 27),
-	RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 29),
-	RCAR_GP_PIN(3, 30), RCAR_GP_PIN(3, 31),
-	RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15),
-};
-static const unsigned int mmc1_data8_mux[] = {
-	MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK,
-	MMC1_D4_MARK, MMC1_D5_MARK, MMC1_D6_MARK, MMC1_D7_MARK,
-};
-static const unsigned int mmc1_ctrl_pins[] = {
-	/* CLK, CMD */
-	RCAR_GP_PIN(3, 24), RCAR_GP_PIN(3, 25),
-};
-static const unsigned int mmc1_ctrl_mux[] = {
-	MMC1_CLK_MARK, MMC1_CMD_MARK,
-};
 /* - SDHI0 ------------------------------------------------------------------ */
 static const unsigned int sdhi0_data1_pins[] = {
 	/* D0 */
@@ -2718,6 +2783,137 @@ static const unsigned int sdhi3_wp_pins[] = {
 static const unsigned int sdhi3_wp_mux[] = {
 	SD3_WP_MARK,
 };
+/* - TPU0 ------------------------------------------------------------------- */
+static const unsigned int tpu0_to0_pins[] = {
+	/* TO */
+	RCAR_GP_PIN(0, 20),
+};
+static const unsigned int tpu0_to0_mux[] = {
+	TPU0TO0_MARK,
+};
+static const unsigned int tpu0_to1_pins[] = {
+	/* TO */
+	RCAR_GP_PIN(0, 21),
+};
+static const unsigned int tpu0_to1_mux[] = {
+	TPU0TO1_MARK,
+};
+static const unsigned int tpu0_to2_pins[] = {
+	/* TO */
+	RCAR_GP_PIN(0, 22),
+};
+static const unsigned int tpu0_to2_mux[] = {
+	TPU0TO2_MARK,
+};
+static const unsigned int tpu0_to3_pins[] = {
+	/* TO */
+	RCAR_GP_PIN(0, 23),
+};
+static const unsigned int tpu0_to3_mux[] = {
+	TPU0TO3_MARK,
+};
+/* - USB0 ------------------------------------------------------------------- */
+static const unsigned int usb0_pins[] = {
+	/* PWEN, OVC/VBUS */
+	RCAR_GP_PIN(5, 18), RCAR_GP_PIN(5, 19),
+};
+static const unsigned int usb0_mux[] = {
+	USB0_PWEN_MARK, USB0_OVC_VBUS_MARK,
+};
+/* - USB1 ------------------------------------------------------------------- */
+static const unsigned int usb1_pins[] = {
+	/* PWEN, OVC */
+	RCAR_GP_PIN(5, 20), RCAR_GP_PIN(5, 21),
+};
+static const unsigned int usb1_mux[] = {
+	USB1_PWEN_MARK, USB1_OVC_MARK,
+};
+/* - USB2 ------------------------------------------------------------------- */
+static const unsigned int usb2_pins[] = {
+	/* PWEN, OVC */
+	RCAR_GP_PIN(5, 22), RCAR_GP_PIN(5, 23),
+};
+static const unsigned int usb2_mux[] = {
+	USB2_PWEN_MARK, USB2_OVC_MARK,
+};
+/* - VIN0 ------------------------------------------------------------------- */
+static const unsigned int vin0_data_g_pins[] = {
+	RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10),
+	RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1),
+	RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3),
+};
+static const unsigned int vin0_data_g_mux[] = {
+	VI0_G0_MARK, VI0_G1_MARK, VI0_G2_MARK,
+	VI0_G3_MARK, VI0_G4_MARK, VI0_G5_MARK,
+	VI0_G6_MARK, VI0_G7_MARK,
+};
+static const unsigned int vin0_data_r_pins[] = {
+	RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 6),
+	RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25),
+	RCAR_GP_PIN(0, 26), RCAR_GP_PIN(1, 11),
+};
+static const unsigned int vin0_data_r_mux[] = {
+	VI0_R0_MARK, VI0_R1_MARK, VI0_R2_MARK,
+	VI0_R3_MARK, VI0_R4_MARK, VI0_R5_MARK,
+	VI0_R6_MARK, VI0_R7_MARK,
+};
+static const unsigned int vin0_data_b_pins[] = {
+	RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3),
+	RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6),
+	RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+};
+static const unsigned int vin0_data_b_mux[] = {
+	VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK, VI0_DATA2_VI0_B2_MARK,
+	VI0_DATA3_VI0_B3_MARK, VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK,
+	VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK,
+};
+static const unsigned int vin0_hsync_signal_pins[] = {
+	RCAR_GP_PIN(0, 12),
+};
+static const unsigned int vin0_hsync_signal_mux[] = {
+	VI0_HSYNC_N_MARK,
+};
+static const unsigned int vin0_vsync_signal_pins[] = {
+	RCAR_GP_PIN(0, 13),
+};
+static const unsigned int vin0_vsync_signal_mux[] = {
+	VI0_VSYNC_N_MARK,
+};
+static const unsigned int vin0_field_signal_pins[] = {
+	RCAR_GP_PIN(0, 15),
+};
+static const unsigned int vin0_field_signal_mux[] = {
+	VI0_FIELD_MARK,
+};
+static const unsigned int vin0_data_enable_pins[] = {
+	RCAR_GP_PIN(0, 14),
+};
+static const unsigned int vin0_data_enable_mux[] = {
+	VI0_CLKENB_MARK,
+};
+static const unsigned int vin0_clk_pins[] = {
+	RCAR_GP_PIN(2, 0),
+};
+static const unsigned int vin0_clk_mux[] = {
+	VI0_CLK_MARK,
+};
+/* - VIN1 ------------------------------------------------------------------- */
+static const unsigned int vin1_data_pins[] = {
+	RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 12),
+	RCAR_GP_PIN(2, 13), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15),
+	RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17),
+};
+static const unsigned int vin1_data_mux[] = {
+	VI1_DATA0_VI1_B0_MARK, VI1_DATA1_VI1_B1_MARK, VI1_DATA2_VI1_B2_MARK,
+	VI1_DATA3_VI1_B3_MARK, VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK,
+	VI1_DATA6_VI1_B6_MARK, VI1_DATA7_VI1_B7_MARK,
+};
+static const unsigned int vin1_clk_pins[] = {
+	RCAR_GP_PIN(2, 9),
+};
+static const unsigned int vin1_clk_mux[] = {
+	VI1_CLK_MARK,
+};
 
 static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(eth_link),
@@ -2755,6 +2951,30 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(mmc1_data4),
 	SH_PFC_PIN_GROUP(mmc1_data8),
 	SH_PFC_PIN_GROUP(mmc1_ctrl),
+	SH_PFC_PIN_GROUP(msiof0_clk),
+	SH_PFC_PIN_GROUP(msiof0_sync),
+	SH_PFC_PIN_GROUP(msiof0_ss1),
+	SH_PFC_PIN_GROUP(msiof0_ss2),
+	SH_PFC_PIN_GROUP(msiof0_rx),
+	SH_PFC_PIN_GROUP(msiof0_tx),
+	SH_PFC_PIN_GROUP(msiof1_clk),
+	SH_PFC_PIN_GROUP(msiof1_sync),
+	SH_PFC_PIN_GROUP(msiof1_ss1),
+	SH_PFC_PIN_GROUP(msiof1_ss2),
+	SH_PFC_PIN_GROUP(msiof1_rx),
+	SH_PFC_PIN_GROUP(msiof1_tx),
+	SH_PFC_PIN_GROUP(msiof2_clk),
+	SH_PFC_PIN_GROUP(msiof2_sync),
+	SH_PFC_PIN_GROUP(msiof2_ss1),
+	SH_PFC_PIN_GROUP(msiof2_ss2),
+	SH_PFC_PIN_GROUP(msiof2_rx),
+	SH_PFC_PIN_GROUP(msiof2_tx),
+	SH_PFC_PIN_GROUP(msiof3_clk),
+	SH_PFC_PIN_GROUP(msiof3_sync),
+	SH_PFC_PIN_GROUP(msiof3_ss1),
+	SH_PFC_PIN_GROUP(msiof3_ss2),
+	SH_PFC_PIN_GROUP(msiof3_rx),
+	SH_PFC_PIN_GROUP(msiof3_tx),
 	SH_PFC_PIN_GROUP(scif0_data),
 	SH_PFC_PIN_GROUP(scif0_clk),
 	SH_PFC_PIN_GROUP(scif0_ctrl),
@@ -2768,6 +2988,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(scif1_clk_d),
 	SH_PFC_PIN_GROUP(scif1_data_e),
 	SH_PFC_PIN_GROUP(scif1_clk_e),
+	SH_PFC_PIN_GROUP(scif2_data),
+	SH_PFC_PIN_GROUP(scif2_clk),
+	SH_PFC_PIN_GROUP(scif2_data_b),
 	SH_PFC_PIN_GROUP(scifa0_data),
 	SH_PFC_PIN_GROUP(scifa0_clk),
 	SH_PFC_PIN_GROUP(scifa0_ctrl),
@@ -2843,6 +3066,19 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(tpu0_to1),
 	SH_PFC_PIN_GROUP(tpu0_to2),
 	SH_PFC_PIN_GROUP(tpu0_to3),
+	SH_PFC_PIN_GROUP(usb0),
+	SH_PFC_PIN_GROUP(usb1),
+	SH_PFC_PIN_GROUP(usb2),
+	SH_PFC_PIN_GROUP(vin0_data_g),
+	SH_PFC_PIN_GROUP(vin0_data_r),
+	SH_PFC_PIN_GROUP(vin0_data_b),
+	SH_PFC_PIN_GROUP(vin0_hsync_signal),
+	SH_PFC_PIN_GROUP(vin0_vsync_signal),
+	SH_PFC_PIN_GROUP(vin0_field_signal),
+	SH_PFC_PIN_GROUP(vin0_data_enable),
+	SH_PFC_PIN_GROUP(vin0_clk),
+	SH_PFC_PIN_GROUP(vin1_data),
+	SH_PFC_PIN_GROUP(vin1_clk),
 };
 
 static const char * const eth_groups[] = {
@@ -2852,6 +3088,31 @@ static const char * const eth_groups[] = {
 	"eth_rmii",
 };
 
+static const char * const hscif0_groups[] = {
+	"hscif0_data",
+	"hscif0_clk",
+	"hscif0_ctrl",
+	"hscif0_data_b",
+	"hscif0_ctrl_b",
+	"hscif0_data_c",
+	"hscif0_ctrl_c",
+	"hscif0_data_d",
+	"hscif0_ctrl_d",
+	"hscif0_data_e",
+	"hscif0_ctrl_e",
+	"hscif0_data_f",
+	"hscif0_ctrl_f",
+};
+
+static const char * const hscif1_groups[] = {
+	"hscif1_data",
+	"hscif1_clk",
+	"hscif1_ctrl",
+	"hscif1_data_b",
+	"hscif1_clk_b",
+	"hscif1_ctrl_b",
+};
+
 static const char * const intc_groups[] = {
 	"intc_irq0",
 	"intc_irq1",
@@ -2859,6 +3120,56 @@ static const char * const intc_groups[] = {
 	"intc_irq3",
 };
 
+static const char * const mmc0_groups[] = {
+	"mmc0_data1",
+	"mmc0_data4",
+	"mmc0_data8",
+	"mmc0_ctrl",
+};
+
+static const char * const mmc1_groups[] = {
+	"mmc1_data1",
+	"mmc1_data4",
+	"mmc1_data8",
+	"mmc1_ctrl",
+};
+
+static const char * const msiof0_groups[] = {
+	"msiof0_clk",
+	"msiof0_sync",
+	"msiof0_ss1",
+	"msiof0_ss2",
+	"msiof0_rx",
+	"msiof0_tx",
+};
+
+static const char * const msiof1_groups[] = {
+	"msiof1_clk",
+	"msiof1_sync",
+	"msiof1_ss1",
+	"msiof1_ss2",
+	"msiof1_rx",
+	"msiof1_tx",
+};
+
+static const char * const msiof2_groups[] = {
+	"msiof2_clk",
+	"msiof2_sync",
+	"msiof2_ss1",
+	"msiof2_ss2",
+	"msiof2_rx",
+	"msiof2_tx",
+};
+
+static const char * const msiof3_groups[] = {
+	"msiof3_clk",
+	"msiof3_sync",
+	"msiof3_ss1",
+	"msiof3_ss2",
+	"msiof3_rx",
+	"msiof3_tx",
+};
+
 static const char * const scif0_groups[] = {
 	"scif0_data",
 	"scif0_clk",
@@ -2878,29 +3189,10 @@ static const char * const scif1_groups[] = {
 	"scif1_clk_e",
 };
 
-static const char * const hscif0_groups[] = {
-	"hscif0_data",
-	"hscif0_clk",
-	"hscif0_ctrl",
-	"hscif0_data_b",
-	"hscif0_ctrl_b",
-	"hscif0_data_c",
-	"hscif0_ctrl_c",
-	"hscif0_data_d",
-	"hscif0_ctrl_d",
-	"hscif0_data_e",
-	"hscif0_ctrl_e",
-	"hscif0_data_f",
-	"hscif0_ctrl_f",
-};
-
-static const char * const hscif1_groups[] = {
-	"hscif1_data",
-	"hscif1_clk",
-	"hscif1_ctrl",
-	"hscif1_data_b",
-	"hscif1_clk_b",
-	"hscif1_ctrl_b",
+static const char * const scif2_groups[] = {
+	"scif2_data",
+	"scif2_clk",
+	"scif2_data_b",
 };
 
 static const char * const scifa0_groups[] = {
@@ -2972,27 +3264,6 @@ static const char * const scifb2_groups[] = {
 	"scifb2_data_c",
 };
 
-static const char * const tpu0_groups[] = {
-	"tpu0_to0",
-	"tpu0_to1",
-	"tpu0_to2",
-	"tpu0_to3",
-};
-
-static const char * const mmc0_groups[] = {
-	"mmc0_data1",
-	"mmc0_data4",
-	"mmc0_data8",
-	"mmc0_ctrl",
-};
-
-static const char * const mmc1_groups[] = {
-	"mmc1_data1",
-	"mmc1_data4",
-	"mmc1_data8",
-	"mmc1_ctrl",
-};
-
 static const char * const sdhi0_groups[] = {
 	"sdhi0_data1",
 	"sdhi0_data4",
@@ -3025,6 +3296,41 @@ static const char * const sdhi3_groups[] = {
 	"sdhi3_wp",
 };
 
+static const char * const tpu0_groups[] = {
+	"tpu0_to0",
+	"tpu0_to1",
+	"tpu0_to2",
+	"tpu0_to3",
+};
+
+static const char * const usb0_groups[] = {
+	"usb0",
+};
+
+static const char * const usb1_groups[] = {
+	"usb1",
+};
+
+static const char * const usb2_groups[] = {
+	"usb2",
+};
+
+static const char * const vin0_groups[] = {
+	"vin0_data_g",
+	"vin0_data_r",
+	"vin0_data_b",
+	"vin0_hsync_signal",
+	"vin0_vsync_signal",
+	"vin0_field_signal",
+	"vin0_data_enable",
+	"vin0_clk",
+};
+
+static const char * const vin1_groups[] = {
+	"vin1_data",
+	"vin1_clk",
+};
+
 static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(eth),
 	SH_PFC_FUNCTION(hscif0),
@@ -3032,8 +3338,13 @@ static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(intc),
 	SH_PFC_FUNCTION(mmc0),
 	SH_PFC_FUNCTION(mmc1),
+	SH_PFC_FUNCTION(msiof0),
+	SH_PFC_FUNCTION(msiof1),
+	SH_PFC_FUNCTION(msiof2),
+	SH_PFC_FUNCTION(msiof3),
 	SH_PFC_FUNCTION(scif0),
 	SH_PFC_FUNCTION(scif1),
+	SH_PFC_FUNCTION(scif2),
 	SH_PFC_FUNCTION(scifa0),
 	SH_PFC_FUNCTION(scifa1),
 	SH_PFC_FUNCTION(scifa2),
@@ -3045,6 +3356,11 @@ static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(sdhi2),
 	SH_PFC_FUNCTION(sdhi3),
 	SH_PFC_FUNCTION(tpu0),
+	SH_PFC_FUNCTION(usb0),
+	SH_PFC_FUNCTION(usb1),
+	SH_PFC_FUNCTION(usb2),
+	SH_PFC_FUNCTION(vin0),
+	SH_PFC_FUNCTION(vin1),
 };
 
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
@@ -3257,16 +3573,16 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		/* IP0_31 [1] */
 		0, 0,
 		/* IP0_30_27 [4] */
-		FN_D8, FN_SCIFA1_SCK_C, FN_AVB_TXD0, FN_MII_TXD0,
+		FN_D8, FN_SCIFA1_SCK_C, FN_AVB_TXD0, 0,
 		FN_VI0_G0, FN_VI0_G0_B, FN_VI2_DATA0_VI2_B0,
 		0, 0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP0_26_23 [4] */
-		FN_D7, FN_AD_DI_B, FN_SDA2_C,
-		FN_VI3_DATA7, FN_VI0_R3, FN_VI0_R3_B, FN_SDA2_CIS_C,
-		0, 0, 0, 0, 0, 0, 0, 0, 0,
+		FN_D7, FN_AD_DI_B, FN_IIC2_SDA_C,
+		FN_VI3_DATA7, FN_VI0_R3, FN_VI0_R3_B, FN_I2C2_SDA_C,
+		FN_TCLK1, 0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP0_22_20 [3] */
-		FN_D6, FN_SCL2_C, FN_VI3_DATA6, FN_VI0_R2, FN_VI0_R2_B,
-		FN_SCL2_CIS_C, 0, 0,
+		FN_D6, FN_IIC2_SCL_C, FN_VI3_DATA6, FN_VI0_R2, FN_VI0_R2_B,
+		FN_I2C2_SCL_C, 0, 0,
 		/* IP0_19_16 [4] */
 		FN_D5, FN_SCIFB1_TXD_F, FN_SCIFB0_TXD_C, FN_VI3_DATA5,
 		FN_VI0_R1, FN_VI0_R1_B, FN_TX0_B,
@@ -3313,15 +3629,15 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_VI0_HSYNC_N, FN_VI0_HSYNC_N_B, FN_VI2_DATA4_VI2_B4,
 		0, 0,
 		/* IP1_11_8 [4] */
-		FN_D11, FN_SCIFA1_CTS_N_C, FN_AVB_TXD3, FN_MII_TXD3,
+		FN_D11, FN_SCIFA1_CTS_N_C, FN_AVB_TXD3, 0,
 		FN_VI0_G3, FN_VI0_G3_B, FN_VI2_DATA3_VI2_B3,
 		0, 0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP1_7_4 [4] */
-		FN_D10, FN_SCIFA1_TXD_C, FN_AVB_TXD2, FN_MII_TXD2,
+		FN_D10, FN_SCIFA1_TXD_C, FN_AVB_TXD2, 0,
 		FN_VI0_G2, FN_VI0_G2_B, FN_VI2_DATA2_VI2_B2,
 		0, 0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP1_3_0 [4] */
-		FN_D9, FN_SCIFA1_RXD_C, FN_AVB_TXD1, FN_MII_TXD1,
+		FN_D9, FN_SCIFA1_RXD_C, FN_AVB_TXD1, 0,
 		FN_VI0_G1, FN_VI0_G1_B, FN_VI2_DATA1_VI2_B1,
 		0, 0, 0, 0, 0, 0, 0, 0, 0, }
 	},
@@ -3334,11 +3650,11 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_VI0_R6_B, FN_VI2_DATA2_VI2_B2_B, 0, 0,
 		/* IP2_25_22 [4] */
 		FN_A9, FN_SCIFA1_CTS_N_B, FN_SSI_WS5_B, FN_VI0_R5,
-		FN_VI0_R5_B, FN_SCIFB2_TXD_C, 0, FN_VI2_DATA1_VI2_B1_B,
+		FN_VI0_R5_B, FN_SCIFB2_TXD_C, FN_TX2_B, FN_VI2_DATA1_VI2_B1_B,
 		0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP2_21_18 [4] */
 		FN_A8, FN_SCIFA1_RXD_B, FN_SSI_SCK5_B, FN_VI0_R4,
-		FN_VI0_R4_B, FN_SCIFB2_RXD_C, 0, FN_VI2_DATA0_VI2_B0_B,
+		FN_VI0_R4_B, FN_SCIFB2_RXD_C, FN_RX2_B, FN_VI2_DATA0_VI2_B0_B,
 		0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP2_17_15 [3] */
 		FN_A7, FN_SCIFA1_SCK_B, FN_AUDIO_CLKOUT_B, FN_TPU0TO3,
@@ -3448,12 +3764,12 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0,
 		/* IP5_9_6 [4] */
 		FN_EX_CS5_N, FN_CAN0_RX, FN_MSIOF1_RXD_B, FN_VI3_VSYNC_N,
-		FN_VI1_G2, FN_VI1_G2_B, FN_VI2_R4, FN_SDA1, FN_INTC_EN1_N,
-		FN_SDA1_CIS, 0, 0, 0, 0, 0, 0,
+		FN_VI1_G2, FN_VI1_G2_B, FN_VI2_R4, FN_IIC1_SDA, FN_INTC_EN1_N,
+		FN_I2C1_SDA, 0, 0, 0, 0, 0, 0,
 		/* IP5_5_3 [3] */
 		FN_EX_CS4_N, FN_MSIOF1_SCK_B, FN_VI3_HSYNC_N,
-		FN_VI2_HSYNC_N, FN_SCL1, FN_VI2_HSYNC_N_B,
-		FN_INTC_EN0_N, FN_SCL1_CIS,
+		FN_VI2_HSYNC_N, FN_IIC1_SCL, FN_VI2_HSYNC_N_B,
+		FN_INTC_EN0_N, FN_I2C1_SCL,
 		/* IP5_2_0 [3] */
 		FN_EX_CS3_N, FN_GPS_MAG, FN_VI3_FIELD, FN_VI1_G1, FN_VI1_G1_B,
 		FN_VI2_R3, 0, 0, }
@@ -3461,24 +3777,24 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG_VAR("IPSR6", 0xE6060038, 32,
 			     3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3) {
 		/* IP6_31_29 [3] */
-		FN_ETH_REF_CLK, FN_RMII_REF_CLK, FN_HCTS0_N_E,
+		FN_ETH_REF_CLK, 0, FN_HCTS0_N_E,
 		FN_STP_IVCXO27_1_B, FN_HRX0_F, 0, 0, 0,
 		/* IP6_28_26 [3] */
-		FN_ETH_LINK, FN_RMII_LINK, FN_HTX0_E,
+		FN_ETH_LINK, 0, FN_HTX0_E,
 		FN_STP_IVCXO27_0_B, FN_SCIFB1_TXD_G, FN_TX1_E, 0, 0,
 		/* IP6_25_23 [3] */
-		FN_ETH_RXD1, FN_RMII_RXD1, FN_HRX0_E, FN_STP_ISSYNC_0_B,
+		FN_ETH_RXD1, 0, FN_HRX0_E, FN_STP_ISSYNC_0_B,
 		FN_TS_SCK0_D, FN_GLO_I1_C, FN_SCIFB1_RXD_G, FN_RX1_E,
 		/* IP6_22_20 [3] */
-		FN_ETH_RXD0, FN_RMII_RXD0, FN_STP_ISEN_0_B, FN_TS_SDAT0_D,
+		FN_ETH_RXD0, 0, FN_STP_ISEN_0_B, FN_TS_SDAT0_D,
 		FN_GLO_I0_C, FN_SCIFB1_SCK_G, FN_SCK1_E, 0,
 		/* IP6_19_17 [3] */
-		FN_ETH_RX_ER, FN_RMII_RX_ER, FN_STP_ISD_0_B,
-		FN_TS_SPSYNC0_D, FN_GLO_Q1_C, FN_SDA2_E, FN_SDA2_CIS_E, 0,
+		FN_ETH_RX_ER, 0, FN_STP_ISD_0_B,
+		FN_TS_SPSYNC0_D, FN_GLO_Q1_C, FN_IIC2_SDA_E, FN_I2C2_SDA_E, 0,
 		/* IP6_16_14 [3] */
-		FN_ETH_CRS_DV, FN_RMII_CRS_DV, FN_STP_ISCLK_0_B,
-		FN_TS_SDEN0_D, FN_GLO_Q0_C, FN_SCL2_E,
-		FN_SCL2_CIS_E, 0,
+		FN_ETH_CRS_DV, 0, FN_STP_ISCLK_0_B,
+		FN_TS_SDEN0_D, FN_GLO_Q0_C, FN_IIC2_SCL_E,
+		FN_I2C2_SCL_E, 0,
 		/* IP6_13_11 [3] */
 		FN_DACK2, FN_IRQ2, FN_INTC_IRQ2_N,
 		FN_SSI_SDATA6_B, FN_HRTS0_N_B, FN_MSIOF0_RXD_B, 0, 0,
@@ -3499,10 +3815,9 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		/* IP7_31 [1] */
 		0, 0,
 		/* IP7_30_29 [2] */
-		FN_VI0_DATA0_VI0_B0, FN_ATACS10_N, FN_AVB_RXD2,
-		FN_MII_RXD2,
+		FN_VI0_DATA0_VI0_B0, FN_ATACS10_N, FN_AVB_RXD2, 0,
 		/* IP7_28_27 [2] */
-		FN_VI0_CLK, FN_ATACS00_N, FN_AVB_RXD1, FN_MII_RXD1,
+		FN_VI0_CLK, FN_ATACS00_N, FN_AVB_RXD1, 0,
 		/* IP7_26_25 [2] */
 		FN_DU1_DOTCLKIN, FN_AUDIO_CLKC, FN_AUDIO_CLKOUT_C, 0,
 		/* IP7_24_22 [3] */
@@ -3515,20 +3830,19 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_PWM0, FN_SCIFA2_SCK_C, FN_STP_ISEN_1_B, FN_TS_SDAT1_C,
 		FN_GLO_SS_C, 0, 0, 0,
 		/* IP7_15_13 [3] */
-		FN_ETH_MDC, FN_RMII_MDC, FN_STP_ISD_1_B,
+		FN_ETH_MDC, 0, FN_STP_ISD_1_B,
 		FN_TS_SPSYNC1_C, FN_GLO_SDATA_C, 0, 0, 0,
 		/* IP7_12_10 [3] */
-		FN_ETH_TXD0, FN_RMII_TXD0, FN_STP_ISCLK_1_B, FN_TS_SDEN1_C,
+		FN_ETH_TXD0, 0, FN_STP_ISCLK_1_B, FN_TS_SDEN1_C,
 		FN_GLO_SCLK_C, 0, 0, 0,
 		/* IP7_9_8 [2] */
-		FN_ETH_MAGIC, FN_RMII_MAGIC, FN_SIM0_RST_C, 0,
+		FN_ETH_MAGIC, 0, FN_SIM0_RST_C, 0,
 		/* IP7_7_6 [2] */
-		FN_ETH_TX_EN, FN_RMII_TX_EN, FN_SIM0_CLK_C, FN_HRTS0_N_F,
+		FN_ETH_TX_EN, 0, FN_SIM0_CLK_C, FN_HRTS0_N_F,
 		/* IP7_5_3 [3] */
-		FN_ETH_TXD1, FN_RMII_TXD1, FN_HTX0_F, FN_BPFCLK_G, FN_RDS_CLK_F,
-		0, 0, 0,
+		FN_ETH_TXD1, 0, FN_HTX0_F, FN_BPFCLK_G, 0, 0, 0, 0,
 		/* IP7_2_0 [3] */
-		FN_ETH_MDIO, FN_RMII_MDIO, FN_HRTS0_N_E,
+		FN_ETH_MDIO, 0, FN_HRTS0_N_E,
 		FN_SIM0_D_C, FN_HCTS0_N_F, 0, 0, 0, }
 	},
 	{ PINMUX_CFG_REG_VAR("IPSR8", 0xE6060040, 32,
@@ -3546,22 +3860,21 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_VI1_DATA5_VI1_B5, FN_AVB_PHY_INT,
 		/* IP8_25_24 [2] */
 		FN_VI1_DATA4_VI1_B4, FN_SCIFA1_RTS_N_D,
-		FN_AVB_MAGIC, FN_MII_MAGIC,
+		FN_AVB_MAGIC, 0,
 		/* IP8_23_22 [2] */
 		FN_VI1_DATA3_VI1_B3, FN_SCIFA1_CTS_N_D, FN_AVB_GTX_CLK, 0,
 		/* IP8_21_20 [2] */
-		FN_VI1_DATA2_VI1_B2, FN_SCIFA1_TXD_D, FN_AVB_MDIO,
-		FN_MII_MDIO,
+		FN_VI1_DATA2_VI1_B2, FN_SCIFA1_TXD_D, FN_AVB_MDIO, 0,
 		/* IP8_19_18 [2] */
-		FN_VI1_DATA1_VI1_B1, FN_SCIFA1_RXD_D, FN_AVB_MDC, FN_MII_MDC,
+		FN_VI1_DATA1_VI1_B1, FN_SCIFA1_RXD_D, FN_AVB_MDC, 0,
 		/* IP8_17_16 [2] */
-		FN_VI1_DATA0_VI1_B0, FN_SCIFA1_SCK_D, FN_AVB_CRS, FN_MII_CRS,
+		FN_VI1_DATA0_VI1_B0, FN_SCIFA1_SCK_D, FN_AVB_CRS, 0,
 		/* IP8_15_14 [2] */
-		FN_VI1_CLK, FN_AVB_RX_DV, FN_MII_RX_DV, 0,
+		FN_VI1_CLK, FN_AVB_RX_DV, 0, 0,
 		/* IP8_13_12 [2] */
-		FN_VI0_DATA7_VI0_B7, FN_AVB_RX_CLK, FN_MII_RX_CLK, 0,
+		FN_VI0_DATA7_VI0_B7, FN_AVB_RX_CLK, 0, 0,
 		/* IP8_11_10 [2] */
-		FN_VI0_DATA6_VI0_B6, FN_AVB_RX_ER, FN_MII_RX_ER, 0,
+		FN_VI0_DATA6_VI0_B6, FN_AVB_RX_ER, 0, 0,
 		/* IP8_9_8 [2] */
 		FN_VI0_DATA5_VI0_B5, FN_EX_WAIT1, FN_AVB_RXD7, 0,
 		/* IP8_7_6 [2] */
@@ -3571,34 +3884,34 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		/* IP8_3_2 [2] */
 		FN_VI0_DATA2_VI0_B2, FN_ATAWR0_N, FN_AVB_RXD4, 0,
 		/* IP8_1_0 [2] */
-		FN_VI0_DATA1_VI0_B1, FN_ATARD0_N, FN_AVB_RXD3, FN_MII_RXD3, }
+		FN_VI0_DATA1_VI0_B1, FN_ATARD0_N, FN_AVB_RXD3, 0, }
 	},
 	{ PINMUX_CFG_REG_VAR("IPSR9", 0xE6060044, 32,
 			     4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2) {
 		/* IP9_31_28 [4] */
 		FN_SD1_CD, FN_MMC1_D6, FN_TS_SDEN1, FN_USB1_EXTP,
-		FN_GLO_SS, FN_VI0_CLK_B, FN_SCL2_D, FN_SCL2_CIS_D,
+		FN_GLO_SS, FN_VI0_CLK_B, FN_IIC2_SCL_D, FN_I2C2_SCL_D,
 		FN_SIM0_CLK_B, FN_VI3_CLK_B, 0, 0, 0, 0, 0, 0,
 		/* IP9_27_26 [2] */
-		FN_SD1_DAT3, FN_AVB_RXD0, FN_MII_RXD0, FN_SCIFB0_RTS_N_B,
+		FN_SD1_DAT3, FN_AVB_RXD0, 0, FN_SCIFB0_RTS_N_B,
 		/* IP9_25_24 [2] */
-		FN_SD1_DAT2, FN_AVB_COL, FN_MII_COL, FN_SCIFB0_CTS_N_B,
+		FN_SD1_DAT2, FN_AVB_COL, 0, FN_SCIFB0_CTS_N_B,
 		/* IP9_23_22 [2] */
-		FN_SD1_DAT1, FN_AVB_LINK, FN_MII_LINK, FN_SCIFB0_TXD_B,
+		FN_SD1_DAT1, FN_AVB_LINK, 0, FN_SCIFB0_TXD_B,
 		/* IP9_21_20 [2] */
-		FN_SD1_DAT0, FN_AVB_TX_CLK, FN_MII_TX_CLK, FN_SCIFB0_RXD_B,
+		FN_SD1_DAT0, FN_AVB_TX_CLK, 0, FN_SCIFB0_RXD_B,
 		/* IP9_19_18 [2] */
-		FN_SD1_CMD, FN_AVB_TX_ER, FN_MII_TX_ER, FN_SCIFB0_SCK_B,
+		FN_SD1_CMD, FN_AVB_TX_ER, 0, FN_SCIFB0_SCK_B,
 		/* IP9_17_16 [2] */
-		FN_SD1_CLK, FN_AVB_TX_EN, FN_MII_TX_EN, 0,
+		FN_SD1_CLK, FN_AVB_TX_EN, 0, 0,
 		/* IP9_15_12 [4] */
 		FN_SD0_WP, FN_MMC0_D7, FN_TS_SPSYNC0_B, FN_USB0_IDIN,
-		FN_GLO_SDATA, FN_VI1_DATA7_VI1_B7_B, FN_SDA1_B,
-		FN_SDA1_CIS_B, FN_VI2_DATA7_VI2_B7_B, 0, 0, 0, 0, 0, 0, 0,
+		FN_GLO_SDATA, FN_VI1_DATA7_VI1_B7_B, FN_IIC1_SDA_B,
+		FN_I2C1_SDA_B, FN_VI2_DATA7_VI2_B7_B, 0, 0, 0, 0, 0, 0, 0,
 		/* IP9_11_8 [4] */
 		FN_SD0_CD, FN_MMC0_D6, FN_TS_SDEN0_B, FN_USB0_EXTP,
-		FN_GLO_SCLK, FN_VI1_DATA6_VI1_B6_B, FN_SCL1_B,
-		FN_SCL1_CIS_B, FN_VI2_DATA6_VI2_B6_B, 0, 0, 0, 0, 0, 0, 0,
+		FN_GLO_SCLK, FN_VI1_DATA6_VI1_B6_B, FN_IIC1_SCL_B,
+		FN_I2C1_SCL_B, FN_VI2_DATA6_VI2_B6_B, 0, 0, 0, 0, 0, 0, 0,
 		/* IP9_7_6 [2] */
 		FN_SD0_DAT3, FN_SCIFB1_RTS_N_B, FN_VI1_DATA5_VI1_B5_B, 0,
 		/* IP9_5_4 [2] */
@@ -3620,11 +3933,11 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_SD2_DAT3, FN_MMC0_D3, FN_SIM0_RST, FN_VI0_DATA5_VI0_B5_B,
 		FN_HTX0_D, FN_TS_SPSYNC1_B, FN_GLO_Q1_B, FN_VI3_DATA5_B,
 		/* IP10_22_19 [4] */
-		FN_SD2_DAT2, FN_MMC0_D2, FN_BPFCLK_B, FN_RDS_CLK,
+		FN_SD2_DAT2, FN_MMC0_D2, FN_BPFCLK_B, 0,
 		FN_VI0_DATA4_VI0_B4_B, FN_HRX0_D, FN_TS_SDEN1_B,
 		FN_GLO_Q0_B, FN_VI3_DATA4_B, 0, 0, 0, 0, 0, 0, 0,
 		/* IP10_18_15 [4] */
-		FN_SD2_DAT1, FN_MMC0_D1, FN_FMIN_B, FN_RDS_DATA,
+		FN_SD2_DAT1, FN_MMC0_D1, FN_FMIN_B, 0,
 		FN_VI0_DATA3_VI0_B3_B, FN_SCIFB1_TXD_E, FN_TX1_D,
 		FN_TS_SCK0_C, FN_GLO_RFON_B, FN_VI3_DATA3_B,
 		0, 0, 0, 0, 0, 0,
@@ -3644,7 +3957,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_VI3_DATA0_B, 0,
 		/* IP10_3_0 [4] */
 		FN_SD1_WP, FN_MMC1_D7, FN_TS_SPSYNC1, FN_USB1_IDIN,
-		FN_GLO_RFON, FN_VI1_CLK_B, FN_SDA2_D, FN_SDA2_CIS_D,
+		FN_GLO_RFON, FN_VI1_CLK_B, FN_IIC2_SDA_D, FN_I2C2_SDA_D,
 		FN_SIM0_D_B, 0, 0, 0, 0, 0, 0, 0, }
 	},
 	{ PINMUX_CFG_REG_VAR("IPSR11", 0xE606004C, 32,
@@ -3652,17 +3965,16 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		/* IP11_31_30 [2] */
 		FN_SSI_SCK0129, FN_CAN_CLK_B, FN_MOUT0, 0,
 		/* IP11_29_27 [3] */
-		FN_MLB_DAT, FN_SPV_EVEN, FN_SCIFB1_TXD_D, FN_TX1_C, FN_BPFCLK_C,
-		FN_RDS_CLK_B, 0, 0,
+		FN_MLB_DAT, 0, FN_SCIFB1_TXD_D, FN_TX1_C, FN_BPFCLK_C,
+		0, 0, 0,
 		/* IP11_26_24 [3] */
-		FN_MLB_SIG, FN_SCIFB1_RXD_D, FN_RX1_C, FN_SDA2_B, FN_SDA2_CIS_B,
+		FN_MLB_SIG, FN_SCIFB1_RXD_D, FN_RX1_C, FN_IIC2_SDA_B, FN_I2C2_SDA_B,
 		0, 0, 0,
 		/* IP11_23_22 [2] */
-		FN_MLB_CLK, FN_SCL2_B, FN_SCL2_CIS_B, 0,
+		FN_MLB_CLK, FN_IIC2_SCL_B, FN_I2C2_SCL_B, 0,
 		/* IP11_21_18 [4] */
 		FN_SD3_WP, FN_MMC1_D5, FN_TS_SCK1, FN_GLO_Q1, FN_FMIN_C,
-		FN_RDS_DATA_B, FN_FMIN_E, FN_RDS_DATA_D, FN_FMIN_F,
-		FN_RDS_DATA_E, 0, 0, 0, 0, 0, 0,
+		0, FN_FMIN_E, 0, FN_FMIN_F, 0, 0, 0, 0, 0, 0, 0,
 		/* IP11_17_15 [3] */
 		FN_SD3_CD, FN_MMC1_D4, FN_TS_SDAT1,
 		FN_VSP, FN_GLO_Q0, FN_SIM0_RST_B, 0, 0,
@@ -3737,8 +4049,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		/* IP13_22_19 [4] */
 		FN_SSI_SDATA7, FN_STP_ISD_1, FN_SCIFB2_RXD, FN_SCIFA2_RTS_N,
 		FN_TCLK2, FN_QSTVA_QVS, FN_CAN_DEBUGOUT11, FN_BPFCLK_E,
-		FN_RDS_CLK_D, FN_SSI_SDATA7_B, FN_FMIN_G, FN_RDS_DATA_F,
-		0, 0, 0, 0,
+		0, FN_SSI_SDATA7_B, FN_FMIN_G, 0, 0, 0, 0, 0,
 		/* IP13_18_16 [3] */
 		FN_SSI_WS78, FN_STP_ISCLK_1, FN_SCIFB2_SCK, FN_SCIFA2_CTS_N,
 		FN_DU2_DR7, FN_LCDOUT7, FN_CAN_DEBUGOUT10, 0,
@@ -3746,15 +4057,15 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_SSI_SCK78, FN_STP_IVCXO27_1, FN_SCK1, FN_SCIFA1_SCK,
 		FN_DU2_DR6, FN_LCDOUT6, FN_CAN_DEBUGOUT9, 0,
 		/* IP13_12_10 [3] */
-		FN_SSI_SDATA6, FN_FMIN_D, FN_RDS_DATA_C, FN_DU2_DR5, FN_LCDOUT5,
+		FN_SSI_SDATA6, FN_FMIN_D, 0, FN_DU2_DR5, FN_LCDOUT5,
 		FN_CAN_DEBUGOUT8, 0, 0,
 		/* IP13_9_7 [3] */
 		FN_SSI_WS6, FN_SCIFB1_RTS_N, FN_CAN0_TX_D, FN_DU2_DR4,
 		FN_LCDOUT4, FN_CAN_DEBUGOUT7, 0, 0,
 		/* IP13_6_3 [4] */
-		FN_SSI_SCK6, FN_SCIFB1_CTS_N, FN_BPFCLK_D, FN_RDS_CLK_C,
+		FN_SSI_SCK6, FN_SCIFB1_CTS_N, FN_BPFCLK_D, 0,
 		FN_DU2_DR3, FN_LCDOUT3, FN_CAN_DEBUGOUT6,
-		FN_BPFCLK_F, FN_RDS_CLK_E, 0, 0, 0, 0, 0, 0, 0,
+		FN_BPFCLK_F, 0, 0, 0, 0, 0, 0, 0, 0,
 		/* IP13_2_0 [3] */
 		FN_SSI_SDATA5, FN_SCIFB1_TXD, FN_IETX_B, FN_DU2_DR2,
 		FN_LCDOUT2, FN_CAN_DEBUGOUT5, 0, 0, }
@@ -3764,7 +4075,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		/* IP14_30 [1] */
 		0, 0,
 		/* IP14_30_28 [3] */
-		FN_SCIFA1_RTS_N, FN_AD_NCS_N, FN_RTS1_N_TANS,
+		FN_SCIFA1_RTS_N, FN_AD_NCS_N, FN_RTS1_N,
 		FN_MSIOF3_TXD, FN_DU1_DOTCLKOUT, FN_QSTVB_QVE,
 		FN_HRTS0_N_C, 0,
 		/* IP14_27_25 [3] */
@@ -3777,11 +4088,11 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_SCIFA1_RXD, FN_AD_DI, FN_RX1,
 		FN_DU2_EXODDF_DU2_ODDF_DISP_CDE, FN_QCPV_QDE, 0, 0, 0,
 		/* IP14_18_16 [3] */
-		FN_SCIFA0_RTS_N, FN_HRTS1_N, FN_RTS0_N_TANS,
+		FN_SCIFA0_RTS_N, FN_HRTS1_N, FN_RTS0_N,
 		FN_MSIOF3_SS1, FN_DU2_DG0, FN_LCDOUT8, FN_PWM1_B, 0,
 		/* IP14_15_12 [4] */
 		FN_SCIFA0_CTS_N, FN_HCTS1_N, FN_CTS0_N, FN_MSIOF3_SYNC,
-		FN_DU2_DG3, FN_LCDOUT11, FN_PWM0_B, FN_SCL1_C, FN_SCL1_CIS_C,
+		FN_DU2_DG3, FN_LCDOUT11, FN_PWM0_B, FN_IIC1_SCL_C, FN_I2C1_SCL_C,
 		0, 0, 0, 0, 0, 0, 0,
 		/* IP14_11_9 [3] */
 		FN_SCIFA0_TXD, FN_HTX1, FN_TX0, FN_DU2_DR1, FN_LCDOUT1,
@@ -3791,7 +4102,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0, 0,
 		/* IP14_5_3 [3] */
 		FN_SCIFA0_SCK, FN_HSCK1, FN_SCK0, FN_MSIOF3_SS2, FN_DU2_DG2,
-		FN_LCDOUT10, FN_SDA1_C, FN_SDA1_CIS_C,
+		FN_LCDOUT10, FN_IIC1_SDA_C, FN_I2C1_SDA_C,
 		/* IP14_2_0 [3] */
 		FN_AUDIO_CLKB, FN_SCIF_CLK, FN_CAN0_RX_D,
 		FN_DVC_MUTE, FN_CAN0_RX_C, FN_CAN_DEBUGOUT15,
@@ -3807,7 +4118,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_MSIOF0_SS1, FN_ADICHS0, FN_DU2_DG5, FN_LCDOUT13,
 		/* IP15_25_23 [3] */
 		FN_MSIOF0_SYNC, FN_TS_SCK0, FN_SSI_SCK2, FN_ADIDATA,
-		FN_DU2_DB7, FN_LCDOUT23, FN_SCIFA2_RXD_B, 0,
+		FN_DU2_DB7, FN_LCDOUT23, FN_HRX0_C, 0,
 		/* IP15_22_20 [3] */
 		FN_MSIOF0_SCK, FN_TS_SDAT0, FN_ADICLK,
 		FN_DU2_DB6, FN_LCDOUT22, 0, 0, 0,
@@ -3823,13 +4134,13 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_HSCK0, FN_TS_SDEN0, FN_DU2_DG4, FN_LCDOUT12, FN_HCTS0_N_C,
 		0, 0, 0,
 		/* IP15_8_6 [3] */
-		FN_SCIFA2_TXD, FN_BPFCLK, 0, FN_DU2_DB1, FN_LCDOUT17,
-		FN_SDA2, FN_SDA2_CIS, 0,
+		FN_SCIFA2_TXD, FN_BPFCLK, FN_RX2, FN_DU2_DB1, FN_LCDOUT17,
+		FN_IIC2_SDA, FN_I2C2_SDA, 0,
 		/* IP15_5_3 [3] */
-		FN_SCIFA2_RXD, FN_FMIN, 0, FN_DU2_DB0, FN_LCDOUT16,
-		FN_SCL2, FN_SCL2_CIS, 0,
+		FN_SCIFA2_RXD, FN_FMIN, FN_TX2, FN_DU2_DB0, FN_LCDOUT16,
+		FN_IIC2_SCL, FN_I2C2_SCL, 0,
 		/* IP15_2_0 [3] */
-		FN_SCIFA2_SCK, FN_FMCLK, 0, FN_MSIOF3_SCK, FN_DU2_DG7,
+		FN_SCIFA2_SCK, FN_FMCLK, FN_SCK2, FN_MSIOF3_SCK, FN_DU2_DG7,
 		FN_LCDOUT15, FN_SCIF_CLK_B, 0, }
 	},
 	{ PINMUX_CFG_REG_VAR("IPSR16", 0xE6060160, 32,
@@ -3858,7 +4169,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_USB1_PWEN, FN_AUDIO_CLKOUT_D,
 		/* IP16_5_3 [3] */
 		FN_MSIOF0_RXD, FN_TS_SPSYNC0, FN_SSI_WS2,
-		FN_ADICS_SAMP, FN_DU2_CDE, FN_QPOLB, FN_HRX0_C, 0,
+		FN_ADICS_SAMP, FN_DU2_CDE, FN_QPOLB, FN_SCIFA2_RXD_B, 0,
 		/* IP16_2_0 [3] */
 		FN_MSIOF0_SS2, FN_AUDIO_CLKOUT, FN_ADICHS2,
 		FN_DU2_DISP, FN_QPOLA, FN_HTX0_C, FN_SCIFA2_TXD_B, 0, }
@@ -3934,8 +4245,8 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_SEL_CAN1_0, FN_SEL_CAN1_1,
 		/* RESERVED [2] */
 		0, 0, 0, 0,
-		/* RESERVED [1] (actually TX2, RX2 vs. TX2_B, RX2_B of SCIF2) */
-		0, 0,
+		/* SEL_SCIF2 [1] */
+		FN_SEL_SCIF2_0, FN_SEL_SCIF2_1,
 		/* SEL_ADI [1] */
 		FN_SEL_ADI_0, FN_SEL_ADI_1,
 		/* SEL_SSP [1] */
@@ -3948,9 +4259,8 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_SEL_HSCIF0_3, FN_SEL_HSCIF0_4, FN_SEL_HSCIF0_5, 0, 0,
 		/* SEL_GPS [2] */
 		FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, 0,
-		/* SEL_RDS [3] */
-		FN_SEL_RDS_0, FN_SEL_RDS_1, FN_SEL_RDS_2,
-		FN_SEL_RDS_3, FN_SEL_RDS_4, FN_SEL_RDS_5, 0, 0,
+		/* RESERVED [3] */
+		0, 0, 0, 0, 0, 0, 0, 0,
 		/* SEL_SIM [2] */
 		FN_SEL_SIM_0, FN_SEL_SIM_1, FN_SEL_SIM_2, 0,
 		/* SEL_SSI8 [2] */
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7203.c b/drivers/pinctrl/sh-pfc/pfc-sh7203.c
index f63d51d..bf3d8f2 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7203.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7203.c
@@ -272,8 +272,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
-
+static const u16 pinmux_data[] = {
 	/* PA */
 	PINMUX_DATA(PA7_DATA, PA7_IN),
 	PINMUX_DATA(PA6_DATA, PA6_IN),
@@ -704,117 +703,116 @@ static const pinmux_enum_t pinmux_data[] = {
 };
 
 static struct sh_pfc_pin pinmux_pins[] = {
-
 	/* 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),
+	PINMUX_GPIO(PA7),
+	PINMUX_GPIO(PA6),
+	PINMUX_GPIO(PA5),
+	PINMUX_GPIO(PA4),
+	PINMUX_GPIO(PA3),
+	PINMUX_GPIO(PA2),
+	PINMUX_GPIO(PA1),
+	PINMUX_GPIO(PA0),
 
 	/* PB */
-	PINMUX_GPIO(GPIO_PB12, PB12_DATA),
-	PINMUX_GPIO(GPIO_PB11, PB11_DATA),
-	PINMUX_GPIO(GPIO_PB10, PB10_DATA),
-	PINMUX_GPIO(GPIO_PB9, PB9_DATA),
-	PINMUX_GPIO(GPIO_PB8, PB8_DATA),
-	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),
+	PINMUX_GPIO(PB12),
+	PINMUX_GPIO(PB11),
+	PINMUX_GPIO(PB10),
+	PINMUX_GPIO(PB9),
+	PINMUX_GPIO(PB8),
+	PINMUX_GPIO(PB7),
+	PINMUX_GPIO(PB6),
+	PINMUX_GPIO(PB5),
+	PINMUX_GPIO(PB4),
+	PINMUX_GPIO(PB3),
+	PINMUX_GPIO(PB2),
+	PINMUX_GPIO(PB1),
+	PINMUX_GPIO(PB0),
 
 	/* PC */
-	PINMUX_GPIO(GPIO_PC14, PC14_DATA),
-	PINMUX_GPIO(GPIO_PC13, PC13_DATA),
-	PINMUX_GPIO(GPIO_PC12, PC12_DATA),
-	PINMUX_GPIO(GPIO_PC11, PC11_DATA),
-	PINMUX_GPIO(GPIO_PC10, PC10_DATA),
-	PINMUX_GPIO(GPIO_PC9, PC9_DATA),
-	PINMUX_GPIO(GPIO_PC8, PC8_DATA),
-	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),
+	PINMUX_GPIO(PC14),
+	PINMUX_GPIO(PC13),
+	PINMUX_GPIO(PC12),
+	PINMUX_GPIO(PC11),
+	PINMUX_GPIO(PC10),
+	PINMUX_GPIO(PC9),
+	PINMUX_GPIO(PC8),
+	PINMUX_GPIO(PC7),
+	PINMUX_GPIO(PC6),
+	PINMUX_GPIO(PC5),
+	PINMUX_GPIO(PC4),
+	PINMUX_GPIO(PC3),
+	PINMUX_GPIO(PC2),
+	PINMUX_GPIO(PC1),
+	PINMUX_GPIO(PC0),
 
 	/* PD */
-	PINMUX_GPIO(GPIO_PD15, PD15_DATA),
-	PINMUX_GPIO(GPIO_PD14, PD14_DATA),
-	PINMUX_GPIO(GPIO_PD13, PD13_DATA),
-	PINMUX_GPIO(GPIO_PD12, PD12_DATA),
-	PINMUX_GPIO(GPIO_PD11, PD11_DATA),
-	PINMUX_GPIO(GPIO_PD10, PD10_DATA),
-	PINMUX_GPIO(GPIO_PD9, PD9_DATA),
-	PINMUX_GPIO(GPIO_PD8, PD8_DATA),
-	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),
+	PINMUX_GPIO(PD15),
+	PINMUX_GPIO(PD14),
+	PINMUX_GPIO(PD13),
+	PINMUX_GPIO(PD12),
+	PINMUX_GPIO(PD11),
+	PINMUX_GPIO(PD10),
+	PINMUX_GPIO(PD9),
+	PINMUX_GPIO(PD8),
+	PINMUX_GPIO(PD7),
+	PINMUX_GPIO(PD6),
+	PINMUX_GPIO(PD5),
+	PINMUX_GPIO(PD4),
+	PINMUX_GPIO(PD3),
+	PINMUX_GPIO(PD2),
+	PINMUX_GPIO(PD1),
+	PINMUX_GPIO(PD0),
 
 	/* PE */
-	PINMUX_GPIO(GPIO_PE15, PE15_DATA),
-	PINMUX_GPIO(GPIO_PE14, PE14_DATA),
-	PINMUX_GPIO(GPIO_PE13, PE13_DATA),
-	PINMUX_GPIO(GPIO_PE12, PE12_DATA),
-	PINMUX_GPIO(GPIO_PE11, PE11_DATA),
-	PINMUX_GPIO(GPIO_PE10, PE10_DATA),
-	PINMUX_GPIO(GPIO_PE9, PE9_DATA),
-	PINMUX_GPIO(GPIO_PE8, PE8_DATA),
-	PINMUX_GPIO(GPIO_PE7, PE7_DATA),
-	PINMUX_GPIO(GPIO_PE6, PE6_DATA),
-	PINMUX_GPIO(GPIO_PE5, PE5_DATA),
-	PINMUX_GPIO(GPIO_PE4, PE4_DATA),
-	PINMUX_GPIO(GPIO_PE3, PE3_DATA),
-	PINMUX_GPIO(GPIO_PE2, PE2_DATA),
-	PINMUX_GPIO(GPIO_PE1, PE1_DATA),
-	PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+	PINMUX_GPIO(PE15),
+	PINMUX_GPIO(PE14),
+	PINMUX_GPIO(PE13),
+	PINMUX_GPIO(PE12),
+	PINMUX_GPIO(PE11),
+	PINMUX_GPIO(PE10),
+	PINMUX_GPIO(PE9),
+	PINMUX_GPIO(PE8),
+	PINMUX_GPIO(PE7),
+	PINMUX_GPIO(PE6),
+	PINMUX_GPIO(PE5),
+	PINMUX_GPIO(PE4),
+	PINMUX_GPIO(PE3),
+	PINMUX_GPIO(PE2),
+	PINMUX_GPIO(PE1),
+	PINMUX_GPIO(PE0),
 
 	/* PF */
-	PINMUX_GPIO(GPIO_PF30, PF30_DATA),
-	PINMUX_GPIO(GPIO_PF29, PF29_DATA),
-	PINMUX_GPIO(GPIO_PF28, PF28_DATA),
-	PINMUX_GPIO(GPIO_PF27, PF27_DATA),
-	PINMUX_GPIO(GPIO_PF26, PF26_DATA),
-	PINMUX_GPIO(GPIO_PF25, PF25_DATA),
-	PINMUX_GPIO(GPIO_PF24, PF24_DATA),
-	PINMUX_GPIO(GPIO_PF23, PF23_DATA),
-	PINMUX_GPIO(GPIO_PF22, PF22_DATA),
-	PINMUX_GPIO(GPIO_PF21, PF21_DATA),
-	PINMUX_GPIO(GPIO_PF20, PF20_DATA),
-	PINMUX_GPIO(GPIO_PF19, PF19_DATA),
-	PINMUX_GPIO(GPIO_PF18, PF18_DATA),
-	PINMUX_GPIO(GPIO_PF17, PF17_DATA),
-	PINMUX_GPIO(GPIO_PF16, PF16_DATA),
-	PINMUX_GPIO(GPIO_PF15, PF15_DATA),
-	PINMUX_GPIO(GPIO_PF14, PF14_DATA),
-	PINMUX_GPIO(GPIO_PF13, PF13_DATA),
-	PINMUX_GPIO(GPIO_PF12, PF12_DATA),
-	PINMUX_GPIO(GPIO_PF11, PF11_DATA),
-	PINMUX_GPIO(GPIO_PF10, PF10_DATA),
-	PINMUX_GPIO(GPIO_PF9, PF9_DATA),
-	PINMUX_GPIO(GPIO_PF8, PF8_DATA),
-	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),
+	PINMUX_GPIO(PF30),
+	PINMUX_GPIO(PF29),
+	PINMUX_GPIO(PF28),
+	PINMUX_GPIO(PF27),
+	PINMUX_GPIO(PF26),
+	PINMUX_GPIO(PF25),
+	PINMUX_GPIO(PF24),
+	PINMUX_GPIO(PF23),
+	PINMUX_GPIO(PF22),
+	PINMUX_GPIO(PF21),
+	PINMUX_GPIO(PF20),
+	PINMUX_GPIO(PF19),
+	PINMUX_GPIO(PF18),
+	PINMUX_GPIO(PF17),
+	PINMUX_GPIO(PF16),
+	PINMUX_GPIO(PF15),
+	PINMUX_GPIO(PF14),
+	PINMUX_GPIO(PF13),
+	PINMUX_GPIO(PF12),
+	PINMUX_GPIO(PF11),
+	PINMUX_GPIO(PF10),
+	PINMUX_GPIO(PF9),
+	PINMUX_GPIO(PF8),
+	PINMUX_GPIO(PF7),
+	PINMUX_GPIO(PF6),
+	PINMUX_GPIO(PF5),
+	PINMUX_GPIO(PF4),
+	PINMUX_GPIO(PF3),
+	PINMUX_GPIO(PF2),
+	PINMUX_GPIO(PF1),
+	PINMUX_GPIO(PF0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7264.c b/drivers/pinctrl/sh-pfc/pfc-sh7264.c
index 2846752..673a595 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7264.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7264.c
@@ -604,8 +604,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
-
+static const u16 pinmux_data[] = {
 	/* Port A */
 	PINMUX_DATA(PA3_DATA, PA3_IN),
 	PINMUX_DATA(PA2_DATA, PA2_IN),
@@ -1073,149 +1072,148 @@ static const pinmux_enum_t pinmux_data[] = {
 };
 
 static struct sh_pfc_pin pinmux_pins[] = {
-
 	/* Port A */
-	PINMUX_GPIO(GPIO_PA3, PA3_DATA),
-	PINMUX_GPIO(GPIO_PA2, PA2_DATA),
-	PINMUX_GPIO(GPIO_PA1, PA1_DATA),
-	PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+	PINMUX_GPIO(PA3),
+	PINMUX_GPIO(PA2),
+	PINMUX_GPIO(PA1),
+	PINMUX_GPIO(PA0),
 
 	/* Port B */
-	PINMUX_GPIO(GPIO_PB22, PB22_DATA),
-	PINMUX_GPIO(GPIO_PB21, PB21_DATA),
-	PINMUX_GPIO(GPIO_PB20, PB20_DATA),
-	PINMUX_GPIO(GPIO_PB19, PB19_DATA),
-	PINMUX_GPIO(GPIO_PB18, PB18_DATA),
-	PINMUX_GPIO(GPIO_PB17, PB17_DATA),
-	PINMUX_GPIO(GPIO_PB16, PB16_DATA),
-	PINMUX_GPIO(GPIO_PB15, PB15_DATA),
-	PINMUX_GPIO(GPIO_PB14, PB14_DATA),
-	PINMUX_GPIO(GPIO_PB13, PB13_DATA),
-	PINMUX_GPIO(GPIO_PB12, PB12_DATA),
-	PINMUX_GPIO(GPIO_PB11, PB11_DATA),
-	PINMUX_GPIO(GPIO_PB10, PB10_DATA),
-	PINMUX_GPIO(GPIO_PB9, PB9_DATA),
-	PINMUX_GPIO(GPIO_PB8, PB8_DATA),
-	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(PB22),
+	PINMUX_GPIO(PB21),
+	PINMUX_GPIO(PB20),
+	PINMUX_GPIO(PB19),
+	PINMUX_GPIO(PB18),
+	PINMUX_GPIO(PB17),
+	PINMUX_GPIO(PB16),
+	PINMUX_GPIO(PB15),
+	PINMUX_GPIO(PB14),
+	PINMUX_GPIO(PB13),
+	PINMUX_GPIO(PB12),
+	PINMUX_GPIO(PB11),
+	PINMUX_GPIO(PB10),
+	PINMUX_GPIO(PB9),
+	PINMUX_GPIO(PB8),
+	PINMUX_GPIO(PB7),
+	PINMUX_GPIO(PB6),
+	PINMUX_GPIO(PB5),
+	PINMUX_GPIO(PB4),
+	PINMUX_GPIO(PB3),
+	PINMUX_GPIO(PB2),
+	PINMUX_GPIO(PB1),
 
 	/* Port C */
-	PINMUX_GPIO(GPIO_PC10, PC10_DATA),
-	PINMUX_GPIO(GPIO_PC9, PC9_DATA),
-	PINMUX_GPIO(GPIO_PC8, PC8_DATA),
-	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),
+	PINMUX_GPIO(PC10),
+	PINMUX_GPIO(PC9),
+	PINMUX_GPIO(PC8),
+	PINMUX_GPIO(PC7),
+	PINMUX_GPIO(PC6),
+	PINMUX_GPIO(PC5),
+	PINMUX_GPIO(PC4),
+	PINMUX_GPIO(PC3),
+	PINMUX_GPIO(PC2),
+	PINMUX_GPIO(PC1),
+	PINMUX_GPIO(PC0),
 
 	/* Port D */
-	PINMUX_GPIO(GPIO_PD15, PD15_DATA),
-	PINMUX_GPIO(GPIO_PD14, PD14_DATA),
-	PINMUX_GPIO(GPIO_PD13, PD13_DATA),
-	PINMUX_GPIO(GPIO_PD12, PD12_DATA),
-	PINMUX_GPIO(GPIO_PD11, PD11_DATA),
-	PINMUX_GPIO(GPIO_PD10, PD10_DATA),
-	PINMUX_GPIO(GPIO_PD9, PD9_DATA),
-	PINMUX_GPIO(GPIO_PD8, PD8_DATA),
-	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),
+	PINMUX_GPIO(PD15),
+	PINMUX_GPIO(PD14),
+	PINMUX_GPIO(PD13),
+	PINMUX_GPIO(PD12),
+	PINMUX_GPIO(PD11),
+	PINMUX_GPIO(PD10),
+	PINMUX_GPIO(PD9),
+	PINMUX_GPIO(PD8),
+	PINMUX_GPIO(PD7),
+	PINMUX_GPIO(PD6),
+	PINMUX_GPIO(PD5),
+	PINMUX_GPIO(PD4),
+	PINMUX_GPIO(PD3),
+	PINMUX_GPIO(PD2),
+	PINMUX_GPIO(PD1),
+	PINMUX_GPIO(PD0),
 
 	/* Port E */
-	PINMUX_GPIO(GPIO_PE5, PE5_DATA),
-	PINMUX_GPIO(GPIO_PE4, PE4_DATA),
-	PINMUX_GPIO(GPIO_PE3, PE3_DATA),
-	PINMUX_GPIO(GPIO_PE2, PE2_DATA),
-	PINMUX_GPIO(GPIO_PE1, PE1_DATA),
-	PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+	PINMUX_GPIO(PE5),
+	PINMUX_GPIO(PE4),
+	PINMUX_GPIO(PE3),
+	PINMUX_GPIO(PE2),
+	PINMUX_GPIO(PE1),
+	PINMUX_GPIO(PE0),
 
 	/* Port F */
-	PINMUX_GPIO(GPIO_PF12, PF12_DATA),
-	PINMUX_GPIO(GPIO_PF11, PF11_DATA),
-	PINMUX_GPIO(GPIO_PF10, PF10_DATA),
-	PINMUX_GPIO(GPIO_PF9, PF9_DATA),
-	PINMUX_GPIO(GPIO_PF8, PF8_DATA),
-	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),
+	PINMUX_GPIO(PF12),
+	PINMUX_GPIO(PF11),
+	PINMUX_GPIO(PF10),
+	PINMUX_GPIO(PF9),
+	PINMUX_GPIO(PF8),
+	PINMUX_GPIO(PF7),
+	PINMUX_GPIO(PF6),
+	PINMUX_GPIO(PF5),
+	PINMUX_GPIO(PF4),
+	PINMUX_GPIO(PF3),
+	PINMUX_GPIO(PF2),
+	PINMUX_GPIO(PF1),
+	PINMUX_GPIO(PF0),
 
 	/* Port G */
-	PINMUX_GPIO(GPIO_PG24, PG24_DATA),
-	PINMUX_GPIO(GPIO_PG23, PG23_DATA),
-	PINMUX_GPIO(GPIO_PG22, PG22_DATA),
-	PINMUX_GPIO(GPIO_PG21, PG21_DATA),
-	PINMUX_GPIO(GPIO_PG20, PG20_DATA),
-	PINMUX_GPIO(GPIO_PG19, PG19_DATA),
-	PINMUX_GPIO(GPIO_PG18, PG18_DATA),
-	PINMUX_GPIO(GPIO_PG17, PG17_DATA),
-	PINMUX_GPIO(GPIO_PG16, PG16_DATA),
-	PINMUX_GPIO(GPIO_PG15, PG15_DATA),
-	PINMUX_GPIO(GPIO_PG14, PG14_DATA),
-	PINMUX_GPIO(GPIO_PG13, PG13_DATA),
-	PINMUX_GPIO(GPIO_PG12, PG12_DATA),
-	PINMUX_GPIO(GPIO_PG11, PG11_DATA),
-	PINMUX_GPIO(GPIO_PG10, PG10_DATA),
-	PINMUX_GPIO(GPIO_PG9, PG9_DATA),
-	PINMUX_GPIO(GPIO_PG8, PG8_DATA),
-	PINMUX_GPIO(GPIO_PG7, PG7_DATA),
-	PINMUX_GPIO(GPIO_PG6, PG6_DATA),
-	PINMUX_GPIO(GPIO_PG5, PG5_DATA),
-	PINMUX_GPIO(GPIO_PG4, PG4_DATA),
-	PINMUX_GPIO(GPIO_PG3, PG3_DATA),
-	PINMUX_GPIO(GPIO_PG2, PG2_DATA),
-	PINMUX_GPIO(GPIO_PG1, PG1_DATA),
-	PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+	PINMUX_GPIO(PG24),
+	PINMUX_GPIO(PG23),
+	PINMUX_GPIO(PG22),
+	PINMUX_GPIO(PG21),
+	PINMUX_GPIO(PG20),
+	PINMUX_GPIO(PG19),
+	PINMUX_GPIO(PG18),
+	PINMUX_GPIO(PG17),
+	PINMUX_GPIO(PG16),
+	PINMUX_GPIO(PG15),
+	PINMUX_GPIO(PG14),
+	PINMUX_GPIO(PG13),
+	PINMUX_GPIO(PG12),
+	PINMUX_GPIO(PG11),
+	PINMUX_GPIO(PG10),
+	PINMUX_GPIO(PG9),
+	PINMUX_GPIO(PG8),
+	PINMUX_GPIO(PG7),
+	PINMUX_GPIO(PG6),
+	PINMUX_GPIO(PG5),
+	PINMUX_GPIO(PG4),
+	PINMUX_GPIO(PG3),
+	PINMUX_GPIO(PG2),
+	PINMUX_GPIO(PG1),
+	PINMUX_GPIO(PG0),
 
 	/* Port H - Port H does not have a Data Register */
 
 	/* Port I - not on device */
 
 	/* Port J */
-	PINMUX_GPIO(GPIO_PJ11, PJ11_DATA),
-	PINMUX_GPIO(GPIO_PJ10, PJ10_DATA),
-	PINMUX_GPIO(GPIO_PJ9, PJ9_DATA),
-	PINMUX_GPIO(GPIO_PJ8, PJ8_DATA),
-	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),
-	PINMUX_GPIO(GPIO_PJ0, PJ0_DATA),
+	PINMUX_GPIO(PJ11),
+	PINMUX_GPIO(PJ10),
+	PINMUX_GPIO(PJ9),
+	PINMUX_GPIO(PJ8),
+	PINMUX_GPIO(PJ7),
+	PINMUX_GPIO(PJ6),
+	PINMUX_GPIO(PJ5),
+	PINMUX_GPIO(PJ4),
+	PINMUX_GPIO(PJ3),
+	PINMUX_GPIO(PJ2),
+	PINMUX_GPIO(PJ1),
+	PINMUX_GPIO(PJ0),
 
 	/* Port K */
-	PINMUX_GPIO(GPIO_PK11, PK11_DATA),
-	PINMUX_GPIO(GPIO_PK10, PK10_DATA),
-	PINMUX_GPIO(GPIO_PK9, PK9_DATA),
-	PINMUX_GPIO(GPIO_PK8, PK8_DATA),
-	PINMUX_GPIO(GPIO_PK7, PK7_DATA),
-	PINMUX_GPIO(GPIO_PK6, PK6_DATA),
-	PINMUX_GPIO(GPIO_PK5, PK5_DATA),
-	PINMUX_GPIO(GPIO_PK4, PK4_DATA),
-	PINMUX_GPIO(GPIO_PK3, PK3_DATA),
-	PINMUX_GPIO(GPIO_PK2, PK2_DATA),
-	PINMUX_GPIO(GPIO_PK1, PK1_DATA),
-	PINMUX_GPIO(GPIO_PK0, PK0_DATA),
+	PINMUX_GPIO(PK11),
+	PINMUX_GPIO(PK10),
+	PINMUX_GPIO(PK9),
+	PINMUX_GPIO(PK8),
+	PINMUX_GPIO(PK7),
+	PINMUX_GPIO(PK6),
+	PINMUX_GPIO(PK5),
+	PINMUX_GPIO(PK4),
+	PINMUX_GPIO(PK3),
+	PINMUX_GPIO(PK2),
+	PINMUX_GPIO(PK1),
+	PINMUX_GPIO(PK0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7269.c b/drivers/pinctrl/sh-pfc/pfc-sh7269.c
index 4c401a7..a19b60f 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7269.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7269.c
@@ -781,8 +781,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
-
+static const u16 pinmux_data[] = {
 	/* Port A */
 	PINMUX_DATA(PA1_DATA, PA1_IN),
 	PINMUX_DATA(PA0_DATA, PA0_IN),
@@ -1454,165 +1453,165 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* Port A */
-	PINMUX_GPIO(GPIO_PA1, PA1_DATA),
-	PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+	PINMUX_GPIO(PA1),
+	PINMUX_GPIO(PA0),
 
 	/* Port B */
-	PINMUX_GPIO(GPIO_PB22, PB22_DATA),
-	PINMUX_GPIO(GPIO_PB21, PB21_DATA),
-	PINMUX_GPIO(GPIO_PB20, PB20_DATA),
-	PINMUX_GPIO(GPIO_PB19, PB19_DATA),
-	PINMUX_GPIO(GPIO_PB18, PB18_DATA),
-	PINMUX_GPIO(GPIO_PB17, PB17_DATA),
-	PINMUX_GPIO(GPIO_PB16, PB16_DATA),
-	PINMUX_GPIO(GPIO_PB15, PB15_DATA),
-	PINMUX_GPIO(GPIO_PB14, PB14_DATA),
-	PINMUX_GPIO(GPIO_PB13, PB13_DATA),
-	PINMUX_GPIO(GPIO_PB12, PB12_DATA),
-	PINMUX_GPIO(GPIO_PB11, PB11_DATA),
-	PINMUX_GPIO(GPIO_PB10, PB10_DATA),
-	PINMUX_GPIO(GPIO_PB9, PB9_DATA),
-	PINMUX_GPIO(GPIO_PB8, PB8_DATA),
-	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(PB22),
+	PINMUX_GPIO(PB21),
+	PINMUX_GPIO(PB20),
+	PINMUX_GPIO(PB19),
+	PINMUX_GPIO(PB18),
+	PINMUX_GPIO(PB17),
+	PINMUX_GPIO(PB16),
+	PINMUX_GPIO(PB15),
+	PINMUX_GPIO(PB14),
+	PINMUX_GPIO(PB13),
+	PINMUX_GPIO(PB12),
+	PINMUX_GPIO(PB11),
+	PINMUX_GPIO(PB10),
+	PINMUX_GPIO(PB9),
+	PINMUX_GPIO(PB8),
+	PINMUX_GPIO(PB7),
+	PINMUX_GPIO(PB6),
+	PINMUX_GPIO(PB5),
+	PINMUX_GPIO(PB4),
+	PINMUX_GPIO(PB3),
+	PINMUX_GPIO(PB2),
+	PINMUX_GPIO(PB1),
 
 	/* Port C */
-	PINMUX_GPIO(GPIO_PC8, PC8_DATA),
-	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),
+	PINMUX_GPIO(PC8),
+	PINMUX_GPIO(PC7),
+	PINMUX_GPIO(PC6),
+	PINMUX_GPIO(PC5),
+	PINMUX_GPIO(PC4),
+	PINMUX_GPIO(PC3),
+	PINMUX_GPIO(PC2),
+	PINMUX_GPIO(PC1),
+	PINMUX_GPIO(PC0),
 
 	/* Port D */
-	PINMUX_GPIO(GPIO_PD15, PD15_DATA),
-	PINMUX_GPIO(GPIO_PD14, PD14_DATA),
-	PINMUX_GPIO(GPIO_PD13, PD13_DATA),
-	PINMUX_GPIO(GPIO_PD12, PD12_DATA),
-	PINMUX_GPIO(GPIO_PD11, PD11_DATA),
-	PINMUX_GPIO(GPIO_PD10, PD10_DATA),
-	PINMUX_GPIO(GPIO_PD9, PD9_DATA),
-	PINMUX_GPIO(GPIO_PD8, PD8_DATA),
-	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),
+	PINMUX_GPIO(PD15),
+	PINMUX_GPIO(PD14),
+	PINMUX_GPIO(PD13),
+	PINMUX_GPIO(PD12),
+	PINMUX_GPIO(PD11),
+	PINMUX_GPIO(PD10),
+	PINMUX_GPIO(PD9),
+	PINMUX_GPIO(PD8),
+	PINMUX_GPIO(PD7),
+	PINMUX_GPIO(PD6),
+	PINMUX_GPIO(PD5),
+	PINMUX_GPIO(PD4),
+	PINMUX_GPIO(PD3),
+	PINMUX_GPIO(PD2),
+	PINMUX_GPIO(PD1),
+	PINMUX_GPIO(PD0),
 
 	/* Port E */
-	PINMUX_GPIO(GPIO_PE7, PE7_DATA),
-	PINMUX_GPIO(GPIO_PE6, PE6_DATA),
-	PINMUX_GPIO(GPIO_PE5, PE5_DATA),
-	PINMUX_GPIO(GPIO_PE4, PE4_DATA),
-	PINMUX_GPIO(GPIO_PE3, PE3_DATA),
-	PINMUX_GPIO(GPIO_PE2, PE2_DATA),
-	PINMUX_GPIO(GPIO_PE1, PE1_DATA),
-	PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+	PINMUX_GPIO(PE7),
+	PINMUX_GPIO(PE6),
+	PINMUX_GPIO(PE5),
+	PINMUX_GPIO(PE4),
+	PINMUX_GPIO(PE3),
+	PINMUX_GPIO(PE2),
+	PINMUX_GPIO(PE1),
+	PINMUX_GPIO(PE0),
 
 	/* Port F */
-	PINMUX_GPIO(GPIO_PF23, PF23_DATA),
-	PINMUX_GPIO(GPIO_PF22, PF22_DATA),
-	PINMUX_GPIO(GPIO_PF21, PF21_DATA),
-	PINMUX_GPIO(GPIO_PF20, PF20_DATA),
-	PINMUX_GPIO(GPIO_PF19, PF19_DATA),
-	PINMUX_GPIO(GPIO_PF18, PF18_DATA),
-	PINMUX_GPIO(GPIO_PF17, PF17_DATA),
-	PINMUX_GPIO(GPIO_PF16, PF16_DATA),
-	PINMUX_GPIO(GPIO_PF15, PF15_DATA),
-	PINMUX_GPIO(GPIO_PF14, PF14_DATA),
-	PINMUX_GPIO(GPIO_PF13, PF13_DATA),
-	PINMUX_GPIO(GPIO_PF12, PF12_DATA),
-	PINMUX_GPIO(GPIO_PF11, PF11_DATA),
-	PINMUX_GPIO(GPIO_PF10, PF10_DATA),
-	PINMUX_GPIO(GPIO_PF9, PF9_DATA),
-	PINMUX_GPIO(GPIO_PF8, PF8_DATA),
-	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),
+	PINMUX_GPIO(PF23),
+	PINMUX_GPIO(PF22),
+	PINMUX_GPIO(PF21),
+	PINMUX_GPIO(PF20),
+	PINMUX_GPIO(PF19),
+	PINMUX_GPIO(PF18),
+	PINMUX_GPIO(PF17),
+	PINMUX_GPIO(PF16),
+	PINMUX_GPIO(PF15),
+	PINMUX_GPIO(PF14),
+	PINMUX_GPIO(PF13),
+	PINMUX_GPIO(PF12),
+	PINMUX_GPIO(PF11),
+	PINMUX_GPIO(PF10),
+	PINMUX_GPIO(PF9),
+	PINMUX_GPIO(PF8),
+	PINMUX_GPIO(PF7),
+	PINMUX_GPIO(PF6),
+	PINMUX_GPIO(PF5),
+	PINMUX_GPIO(PF4),
+	PINMUX_GPIO(PF3),
+	PINMUX_GPIO(PF2),
+	PINMUX_GPIO(PF1),
+	PINMUX_GPIO(PF0),
 
 	/* Port G */
-	PINMUX_GPIO(GPIO_PG27, PG27_DATA),
-	PINMUX_GPIO(GPIO_PG26, PG26_DATA),
-	PINMUX_GPIO(GPIO_PG25, PG25_DATA),
-	PINMUX_GPIO(GPIO_PG24, PG24_DATA),
-	PINMUX_GPIO(GPIO_PG23, PG23_DATA),
-	PINMUX_GPIO(GPIO_PG22, PG22_DATA),
-	PINMUX_GPIO(GPIO_PG21, PG21_DATA),
-	PINMUX_GPIO(GPIO_PG20, PG20_DATA),
-	PINMUX_GPIO(GPIO_PG19, PG19_DATA),
-	PINMUX_GPIO(GPIO_PG18, PG18_DATA),
-	PINMUX_GPIO(GPIO_PG17, PG17_DATA),
-	PINMUX_GPIO(GPIO_PG16, PG16_DATA),
-	PINMUX_GPIO(GPIO_PG15, PG15_DATA),
-	PINMUX_GPIO(GPIO_PG14, PG14_DATA),
-	PINMUX_GPIO(GPIO_PG13, PG13_DATA),
-	PINMUX_GPIO(GPIO_PG12, PG12_DATA),
-	PINMUX_GPIO(GPIO_PG11, PG11_DATA),
-	PINMUX_GPIO(GPIO_PG10, PG10_DATA),
-	PINMUX_GPIO(GPIO_PG9, PG9_DATA),
-	PINMUX_GPIO(GPIO_PG8, PG8_DATA),
-	PINMUX_GPIO(GPIO_PG7, PG7_DATA),
-	PINMUX_GPIO(GPIO_PG6, PG6_DATA),
-	PINMUX_GPIO(GPIO_PG5, PG5_DATA),
-	PINMUX_GPIO(GPIO_PG4, PG4_DATA),
-	PINMUX_GPIO(GPIO_PG3, PG3_DATA),
-	PINMUX_GPIO(GPIO_PG2, PG2_DATA),
-	PINMUX_GPIO(GPIO_PG1, PG1_DATA),
-	PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+	PINMUX_GPIO(PG27),
+	PINMUX_GPIO(PG26),
+	PINMUX_GPIO(PG25),
+	PINMUX_GPIO(PG24),
+	PINMUX_GPIO(PG23),
+	PINMUX_GPIO(PG22),
+	PINMUX_GPIO(PG21),
+	PINMUX_GPIO(PG20),
+	PINMUX_GPIO(PG19),
+	PINMUX_GPIO(PG18),
+	PINMUX_GPIO(PG17),
+	PINMUX_GPIO(PG16),
+	PINMUX_GPIO(PG15),
+	PINMUX_GPIO(PG14),
+	PINMUX_GPIO(PG13),
+	PINMUX_GPIO(PG12),
+	PINMUX_GPIO(PG11),
+	PINMUX_GPIO(PG10),
+	PINMUX_GPIO(PG9),
+	PINMUX_GPIO(PG8),
+	PINMUX_GPIO(PG7),
+	PINMUX_GPIO(PG6),
+	PINMUX_GPIO(PG5),
+	PINMUX_GPIO(PG4),
+	PINMUX_GPIO(PG3),
+	PINMUX_GPIO(PG2),
+	PINMUX_GPIO(PG1),
+	PINMUX_GPIO(PG0),
 
 	/* Port H - Port H does not have a Data Register */
 
 	/* Port I - not on device */
 
 	/* Port J */
-	PINMUX_GPIO(GPIO_PJ31, PJ31_DATA),
-	PINMUX_GPIO(GPIO_PJ30, PJ30_DATA),
-	PINMUX_GPIO(GPIO_PJ29, PJ29_DATA),
-	PINMUX_GPIO(GPIO_PJ28, PJ28_DATA),
-	PINMUX_GPIO(GPIO_PJ27, PJ27_DATA),
-	PINMUX_GPIO(GPIO_PJ26, PJ26_DATA),
-	PINMUX_GPIO(GPIO_PJ25, PJ25_DATA),
-	PINMUX_GPIO(GPIO_PJ24, PJ24_DATA),
-	PINMUX_GPIO(GPIO_PJ23, PJ23_DATA),
-	PINMUX_GPIO(GPIO_PJ22, PJ22_DATA),
-	PINMUX_GPIO(GPIO_PJ21, PJ21_DATA),
-	PINMUX_GPIO(GPIO_PJ20, PJ20_DATA),
-	PINMUX_GPIO(GPIO_PJ19, PJ19_DATA),
-	PINMUX_GPIO(GPIO_PJ18, PJ18_DATA),
-	PINMUX_GPIO(GPIO_PJ17, PJ17_DATA),
-	PINMUX_GPIO(GPIO_PJ16, PJ16_DATA),
-	PINMUX_GPIO(GPIO_PJ15, PJ15_DATA),
-	PINMUX_GPIO(GPIO_PJ14, PJ14_DATA),
-	PINMUX_GPIO(GPIO_PJ13, PJ13_DATA),
-	PINMUX_GPIO(GPIO_PJ12, PJ12_DATA),
-	PINMUX_GPIO(GPIO_PJ11, PJ11_DATA),
-	PINMUX_GPIO(GPIO_PJ10, PJ10_DATA),
-	PINMUX_GPIO(GPIO_PJ9, PJ9_DATA),
-	PINMUX_GPIO(GPIO_PJ8, PJ8_DATA),
-	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),
-	PINMUX_GPIO(GPIO_PJ0, PJ0_DATA),
+	PINMUX_GPIO(PJ31),
+	PINMUX_GPIO(PJ30),
+	PINMUX_GPIO(PJ29),
+	PINMUX_GPIO(PJ28),
+	PINMUX_GPIO(PJ27),
+	PINMUX_GPIO(PJ26),
+	PINMUX_GPIO(PJ25),
+	PINMUX_GPIO(PJ24),
+	PINMUX_GPIO(PJ23),
+	PINMUX_GPIO(PJ22),
+	PINMUX_GPIO(PJ21),
+	PINMUX_GPIO(PJ20),
+	PINMUX_GPIO(PJ19),
+	PINMUX_GPIO(PJ18),
+	PINMUX_GPIO(PJ17),
+	PINMUX_GPIO(PJ16),
+	PINMUX_GPIO(PJ15),
+	PINMUX_GPIO(PJ14),
+	PINMUX_GPIO(PJ13),
+	PINMUX_GPIO(PJ12),
+	PINMUX_GPIO(PJ11),
+	PINMUX_GPIO(PJ10),
+	PINMUX_GPIO(PJ9),
+	PINMUX_GPIO(PJ8),
+	PINMUX_GPIO(PJ7),
+	PINMUX_GPIO(PJ6),
+	PINMUX_GPIO(PJ5),
+	PINMUX_GPIO(PJ4),
+	PINMUX_GPIO(PJ3),
+	PINMUX_GPIO(PJ2),
+	PINMUX_GPIO(PJ1),
+	PINMUX_GPIO(PJ0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c
index 6dfb187..70b522d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c
@@ -23,27 +23,18 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/pinctrl/pinconf-generic.h>
-
-#include <mach/irqs.h>
-#include <mach/sh7372.h>
+#include <linux/sh_intc.h>
 
 #include "core.h"
 #include "sh_pfc.h"
 
-#define CPU_ALL_PORT(fn, pfx, sfx) \
-	PORT_10(fn, pfx, sfx),		PORT_90(fn, pfx, sfx), \
-	PORT_10(fn, pfx##10, sfx),	PORT_10(fn, pfx##11, sfx), \
-	PORT_10(fn, pfx##12, sfx),	PORT_10(fn, pfx##13, sfx), \
-	PORT_10(fn, pfx##14, sfx),	PORT_10(fn, pfx##15, sfx), \
-	PORT_10(fn, pfx##16, sfx),	PORT_10(fn, pfx##17, sfx), \
-	PORT_10(fn, pfx##18, sfx),	PORT_1(fn, pfx##190, sfx)
-
-#undef _GPIO_PORT
-#define _GPIO_PORT(gpio, sfx)						\
-	[gpio] = {							\
-		.name = __stringify(PORT##gpio),			\
-		.enum_id = PORT##gpio##_DATA,				\
-	}
+#define CPU_ALL_PORT(fn, pfx, sfx)					\
+	PORT_10(0,  fn, pfx, sfx),	PORT_90(0,  fn, pfx, sfx),	\
+	PORT_10(100, fn, pfx##10, sfx),	PORT_10(110, fn, pfx##11, sfx),	\
+	PORT_10(120, fn, pfx##12, sfx),	PORT_10(130, fn, pfx##13, sfx),	\
+	PORT_10(140, fn, pfx##14, sfx),	PORT_10(150, fn, pfx##15, sfx),	\
+	PORT_10(160, fn, pfx##16, sfx),	PORT_10(170, fn, pfx##17, sfx),	\
+	PORT_10(180, fn, pfx##18, sfx),	PORT_1(190, fn, pfx##190, sfx)
 
 #define IRQC_PIN_MUX(irq, pin)						\
 static const unsigned int intc_irq##irq##_pins[] = {			\
@@ -391,11 +382,8 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define _PORT_DATA(pfx, sfx)	PORT_DATA_IO(pfx)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_PORT_DATA, , unused)
-
-static const pinmux_enum_t pinmux_data[] = {
-	PINMUX_DATA_GP_ALL(),
+static const u16 pinmux_data[] = {
+	PINMUX_DATA_ALL(),
 
 	/* IRQ */
 	PINMUX_DATA(IRQ0_6_MARK,	PORT6_FN0, 	MSEL1CR_0_0),
@@ -839,13 +827,6 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(MFIv4_MARK,		MSEL4CR_6_1),
 };
 
-#define SH7372_PIN(pin, cfgs)						\
-	{								\
-		.name = __stringify(PORT##pin),				\
-		.enum_id = PORT##pin##_DATA,				\
-		.configs = cfgs,					\
-	}
-
 #define __I		(SH_PFC_PIN_CFG_INPUT)
 #define __O		(SH_PFC_PIN_CFG_OUTPUT)
 #define __IO		(SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
@@ -853,15 +834,15 @@ static const pinmux_enum_t pinmux_data[] = {
 #define __PU		(SH_PFC_PIN_CFG_PULL_UP)
 #define __PUD		(SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
 
-#define SH7372_PIN_I_PD(pin)		SH7372_PIN(pin, __I | __PD)
-#define SH7372_PIN_I_PU(pin)		SH7372_PIN(pin, __I | __PU)
-#define SH7372_PIN_I_PU_PD(pin)		SH7372_PIN(pin, __I | __PUD)
-#define SH7372_PIN_IO(pin)		SH7372_PIN(pin, __IO)
-#define SH7372_PIN_IO_PD(pin)		SH7372_PIN(pin, __IO | __PD)
-#define SH7372_PIN_IO_PU(pin)		SH7372_PIN(pin, __IO | __PU)
-#define SH7372_PIN_IO_PU_PD(pin)	SH7372_PIN(pin, __IO | __PUD)
-#define SH7372_PIN_O(pin)		SH7372_PIN(pin, __O)
-#define SH7372_PIN_O_PU_PD(pin)		SH7372_PIN(pin, __O | __PUD)
+#define SH7372_PIN_I_PD(pin)		SH_PFC_PIN_CFG(pin, __I | __PD)
+#define SH7372_PIN_I_PU(pin)		SH_PFC_PIN_CFG(pin, __I | __PU)
+#define SH7372_PIN_I_PU_PD(pin)		SH_PFC_PIN_CFG(pin, __I | __PUD)
+#define SH7372_PIN_IO(pin)		SH_PFC_PIN_CFG(pin, __IO)
+#define SH7372_PIN_IO_PD(pin)		SH_PFC_PIN_CFG(pin, __IO | __PD)
+#define SH7372_PIN_IO_PU(pin)		SH_PFC_PIN_CFG(pin, __IO | __PU)
+#define SH7372_PIN_IO_PU_PD(pin)	SH_PFC_PIN_CFG(pin, __IO | __PUD)
+#define SH7372_PIN_O(pin)		SH_PFC_PIN_CFG(pin, __O)
+#define SH7372_PIN_O_PU_PD(pin)		SH_PFC_PIN_CFG(pin, __O | __PUD)
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* Table 57-1 (I/O and Pull U/D) */
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index 31f7d0e..7e278a9 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -31,32 +31,32 @@
 #include "core.h"
 #include "sh_pfc.h"
 
-#define CPU_ALL_PORT(fn, pfx, sfx)				\
-	PORT_10(fn, pfx,    sfx), PORT_90(fn, pfx, sfx),	\
-	PORT_10(fn, pfx##10, sfx),				\
-	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
-	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
-	PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),	\
-	PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),	\
-	PORT_1(fn, pfx##118, sfx),				\
-	PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),	\
-	PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),	\
-	PORT_10(fn, pfx##15, sfx),				\
-	PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),	\
-	PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),	\
-	PORT_1(fn, pfx##164, sfx),				\
-	PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),	\
-	PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),	\
-	PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),	\
-	PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),	\
-	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
-	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
-	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
-	PORT_10(fn, pfx##26, sfx), PORT_10(fn, pfx##27, sfx),	\
-	PORT_1(fn, pfx##280, sfx), PORT_1(fn, pfx##281, sfx),	\
-	PORT_1(fn, pfx##282, sfx),				\
-	PORT_1(fn, pfx##288, sfx), PORT_1(fn, pfx##289, sfx),	\
-	PORT_10(fn, pfx##29, sfx), PORT_10(fn, pfx##30, sfx)
+#define CPU_ALL_PORT(fn, pfx, sfx)					\
+	PORT_10(0,  fn, pfx, sfx), PORT_90(0, fn, pfx, sfx),		\
+	PORT_10(100, fn, pfx##10, sfx),					\
+	PORT_1(110, fn, pfx##110, sfx), PORT_1(111, fn, pfx##111, sfx),	\
+	PORT_1(112, fn, pfx##112, sfx), PORT_1(113, fn, pfx##113, sfx),	\
+	PORT_1(114, fn, pfx##114, sfx), PORT_1(115, fn, pfx##115, sfx),	\
+	PORT_1(116, fn, pfx##116, sfx), PORT_1(117, fn, pfx##117, sfx),	\
+	PORT_1(118, fn, pfx##118, sfx),					\
+	PORT_1(128, fn, pfx##128, sfx), PORT_1(129, fn, pfx##129, sfx),	\
+	PORT_10(130, fn, pfx##13, sfx), PORT_10(140, fn, pfx##14, sfx),	\
+	PORT_10(150, fn, pfx##15, sfx),					\
+	PORT_1(160, fn, pfx##160, sfx), PORT_1(161, fn, pfx##161, sfx),	\
+	PORT_1(162, fn, pfx##162, sfx), PORT_1(163, fn, pfx##163, sfx),	\
+	PORT_1(164, fn, pfx##164, sfx),					\
+	PORT_1(192, fn, pfx##192, sfx), PORT_1(193, fn, pfx##193, sfx),	\
+	PORT_1(194, fn, pfx##194, sfx), PORT_1(195, fn, pfx##195, sfx),	\
+	PORT_1(196, fn, pfx##196, sfx), PORT_1(197, fn, pfx##197, sfx),	\
+	PORT_1(198, fn, pfx##198, sfx), PORT_1(199, fn, pfx##199, sfx),	\
+	PORT_10(200, fn, pfx##20, sfx), PORT_10(210, fn, pfx##21, sfx),	\
+	PORT_10(220, fn, pfx##22, sfx), PORT_10(230, fn, pfx##23, sfx),	\
+	PORT_10(240, fn, pfx##24, sfx), PORT_10(250, fn, pfx##25, sfx),	\
+	PORT_10(260, fn, pfx##26, sfx), PORT_10(270, fn, pfx##27, sfx),	\
+	PORT_1(280, fn, pfx##280, sfx), PORT_1(281, fn, pfx##281, sfx),	\
+	PORT_1(282, fn, pfx##282, sfx),					\
+	PORT_1(288, fn, pfx##288, sfx), PORT_1(289, fn, pfx##289, sfx),	\
+	PORT_10(290, fn, pfx##29, sfx), PORT_10(300, fn, pfx##30, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
@@ -466,12 +466,9 @@ enum {
 	PINMUX_MARK_END,
 };
 
-#define _PORT_DATA(pfx, sfx)	PORT_DATA_IO(pfx)
-#define PINMUX_DATA_GP_ALL()    CPU_ALL_PORT(_PORT_DATA, , unused)
-
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
-	PINMUX_DATA_GP_ALL(),
+	PINMUX_DATA_ALL(),
 
 	/* Table 25-1 (Function 0-7) */
 	PINMUX_DATA(VBUS_0_MARK, PORT0_FN1),
@@ -1160,13 +1157,6 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(EDBGREQ_PU_MARK, MSEL4CR_MSEL1_1),
 };
 
-#define SH73A0_PIN(pin, cfgs)						\
-	{								\
-		.name = __stringify(PORT##pin),				\
-		.enum_id = PORT##pin##_DATA,				\
-		.configs = cfgs,					\
-	}
-
 #define __I		(SH_PFC_PIN_CFG_INPUT)
 #define __O		(SH_PFC_PIN_CFG_OUTPUT)
 #define __IO		(SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
@@ -1174,14 +1164,20 @@ static const pinmux_enum_t pinmux_data[] = {
 #define __PU		(SH_PFC_PIN_CFG_PULL_UP)
 #define __PUD		(SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
 
-#define SH73A0_PIN_I_PD(pin)		SH73A0_PIN(pin, __I | __PD)
-#define SH73A0_PIN_I_PU(pin)		SH73A0_PIN(pin, __I | __PU)
-#define SH73A0_PIN_I_PU_PD(pin)		SH73A0_PIN(pin, __I | __PUD)
-#define SH73A0_PIN_IO(pin)		SH73A0_PIN(pin, __IO)
-#define SH73A0_PIN_IO_PD(pin)		SH73A0_PIN(pin, __IO | __PD)
-#define SH73A0_PIN_IO_PU(pin)		SH73A0_PIN(pin, __IO | __PU)
-#define SH73A0_PIN_IO_PU_PD(pin)	SH73A0_PIN(pin, __IO | __PUD)
-#define SH73A0_PIN_O(pin)		SH73A0_PIN(pin, __O)
+#define SH73A0_PIN_I_PD(pin)		SH_PFC_PIN_CFG(pin, __I | __PD)
+#define SH73A0_PIN_I_PU(pin)		SH_PFC_PIN_CFG(pin, __I | __PU)
+#define SH73A0_PIN_I_PU_PD(pin)		SH_PFC_PIN_CFG(pin, __I | __PUD)
+#define SH73A0_PIN_IO(pin)		SH_PFC_PIN_CFG(pin, __IO)
+#define SH73A0_PIN_IO_PD(pin)		SH_PFC_PIN_CFG(pin, __IO | __PD)
+#define SH73A0_PIN_IO_PU(pin)		SH_PFC_PIN_CFG(pin, __IO | __PU)
+#define SH73A0_PIN_IO_PU_PD(pin)	SH_PFC_PIN_CFG(pin, __IO | __PUD)
+#define SH73A0_PIN_O(pin)		SH_PFC_PIN_CFG(pin, __O)
+
+/* Pin numbers for pins without a corresponding GPIO port number are computed
+ * from the row and column numbers with a 1000 offset to avoid collisions with
+ * GPIO port numbers.
+ */
+#define PIN_NUMBER(row, col)		(1000+((row)-1)*34+(col)-1)
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* Table 25-1 (I/O and Pull U/D) */
@@ -1454,21 +1450,11 @@ static struct sh_pfc_pin pinmux_pins[] = {
 	SH73A0_PIN_O(307),
 	SH73A0_PIN_I_PU(308),
 	SH73A0_PIN_O(309),
-};
 
-static const struct pinmux_range pinmux_ranges[] = {
-	{.begin = 0, .end = 118,},
-	{.begin = 128, .end = 164,},
-	{.begin = 192, .end = 282,},
-	{.begin = 288, .end = 309,},
+	/* Pins not associated with a GPIO port */
+	SH_PFC_PIN_NAMED(6, 26, F26),
 };
 
-/* Pin numbers for pins without a corresponding GPIO port number are computed
- * from the row and column numbers with a 1000 offset to avoid collisions with
- * GPIO port numbers.
- */
-#define PIN_NUMBER(row, col)		(1000+((row)-1)*34+(col)-1)
-
 /* - BSC -------------------------------------------------------------------- */
 static const unsigned int bsc_data_0_7_pins[] = {
 	/* D[0:7] */
@@ -3674,43 +3660,39 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-/* External IRQ pins mapped at IRQPIN_BASE */
-#define EXT_IRQ16L(n) irq_pin(n)
-#define EXT_IRQ16H(n) irq_pin(n)
-
 static const struct pinmux_irq pinmux_irqs[] = {
-	PINMUX_IRQ(EXT_IRQ16H(19), 9),
-	PINMUX_IRQ(EXT_IRQ16L(1), 10),
-	PINMUX_IRQ(EXT_IRQ16L(0), 11),
-	PINMUX_IRQ(EXT_IRQ16H(18), 13),
-	PINMUX_IRQ(EXT_IRQ16H(20), 14),
-	PINMUX_IRQ(EXT_IRQ16H(21), 15),
-	PINMUX_IRQ(EXT_IRQ16H(31), 26),
-	PINMUX_IRQ(EXT_IRQ16H(30), 27),
-	PINMUX_IRQ(EXT_IRQ16H(29), 28),
-	PINMUX_IRQ(EXT_IRQ16H(22), 40),
-	PINMUX_IRQ(EXT_IRQ16H(23), 53),
-	PINMUX_IRQ(EXT_IRQ16L(10), 54),
-	PINMUX_IRQ(EXT_IRQ16L(9), 56),
-	PINMUX_IRQ(EXT_IRQ16H(26), 115),
-	PINMUX_IRQ(EXT_IRQ16H(27), 116),
-	PINMUX_IRQ(EXT_IRQ16H(28), 117),
-	PINMUX_IRQ(EXT_IRQ16H(24), 118),
-	PINMUX_IRQ(EXT_IRQ16L(6), 147),
-	PINMUX_IRQ(EXT_IRQ16L(2), 149),
-	PINMUX_IRQ(EXT_IRQ16L(7), 150),
-	PINMUX_IRQ(EXT_IRQ16L(12), 156),
-	PINMUX_IRQ(EXT_IRQ16L(4), 159),
-	PINMUX_IRQ(EXT_IRQ16H(25), 164),
-	PINMUX_IRQ(EXT_IRQ16L(8), 223),
-	PINMUX_IRQ(EXT_IRQ16L(3), 224),
-	PINMUX_IRQ(EXT_IRQ16L(5), 227),
-	PINMUX_IRQ(EXT_IRQ16H(17), 234),
-	PINMUX_IRQ(EXT_IRQ16L(11), 238),
-	PINMUX_IRQ(EXT_IRQ16L(13), 239),
-	PINMUX_IRQ(EXT_IRQ16H(16), 249),
-	PINMUX_IRQ(EXT_IRQ16L(14), 251),
-	PINMUX_IRQ(EXT_IRQ16L(9), 308),
+	PINMUX_IRQ(irq_pin(19), 9),
+	PINMUX_IRQ(irq_pin(1), 10),
+	PINMUX_IRQ(irq_pin(0), 11),
+	PINMUX_IRQ(irq_pin(18), 13),
+	PINMUX_IRQ(irq_pin(20), 14),
+	PINMUX_IRQ(irq_pin(21), 15),
+	PINMUX_IRQ(irq_pin(31), 26),
+	PINMUX_IRQ(irq_pin(30), 27),
+	PINMUX_IRQ(irq_pin(29), 28),
+	PINMUX_IRQ(irq_pin(22), 40),
+	PINMUX_IRQ(irq_pin(23), 53),
+	PINMUX_IRQ(irq_pin(10), 54),
+	PINMUX_IRQ(irq_pin(9), 56),
+	PINMUX_IRQ(irq_pin(26), 115),
+	PINMUX_IRQ(irq_pin(27), 116),
+	PINMUX_IRQ(irq_pin(28), 117),
+	PINMUX_IRQ(irq_pin(24), 118),
+	PINMUX_IRQ(irq_pin(6), 147),
+	PINMUX_IRQ(irq_pin(2), 149),
+	PINMUX_IRQ(irq_pin(7), 150),
+	PINMUX_IRQ(irq_pin(12), 156),
+	PINMUX_IRQ(irq_pin(4), 159),
+	PINMUX_IRQ(irq_pin(25), 164),
+	PINMUX_IRQ(irq_pin(8), 223),
+	PINMUX_IRQ(irq_pin(3), 224),
+	PINMUX_IRQ(irq_pin(5), 227),
+	PINMUX_IRQ(irq_pin(17), 234),
+	PINMUX_IRQ(irq_pin(11), 238),
+	PINMUX_IRQ(irq_pin(13), 239),
+	PINMUX_IRQ(irq_pin(16), 249),
+	PINMUX_IRQ(irq_pin(14), 251),
+	PINMUX_IRQ(irq_pin(9), 308),
 };
 
 /* -----------------------------------------------------------------------------
@@ -3905,8 +3887,6 @@ const struct sh_pfc_soc_info sh73a0_pinmux_info = {
 
 	.pins = pinmux_pins,
 	.nr_pins = ARRAY_SIZE(pinmux_pins),
-	.ranges = pinmux_ranges,
-	.nr_ranges = ARRAY_SIZE(pinmux_ranges),
 	.groups = pinmux_groups,
 	.nr_groups = ARRAY_SIZE(pinmux_groups),
 	.functions = pinmux_functions,
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7720.c b/drivers/pinctrl/sh-pfc/pfc-sh7720.c
index 52e9f6b..7a26809 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7720.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7720.c
@@ -81,36 +81,6 @@ enum {
 	PTV4_IN, PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
 	PINMUX_INPUT_END,
 
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
-	PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
-	PTB7_IN_PU, PTB6_IN_PU, PTB5_IN_PU, PTB4_IN_PU,
-	PTB3_IN_PU, PTB2_IN_PU, PTB1_IN_PU, PTB0_IN_PU,
-	PTC7_IN_PU, PTC6_IN_PU, PTC5_IN_PU, PTC4_IN_PU,
-	PTC3_IN_PU, PTC2_IN_PU, PTC1_IN_PU, PTC0_IN_PU,
-	PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
-	PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
-	PTE4_IN_PU, PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
-	PTF0_IN_PU,
-	PTG6_IN_PU, PTG5_IN_PU, PTG4_IN_PU,
-	PTG3_IN_PU, PTG2_IN_PU, PTG1_IN_PU, PTG0_IN_PU,
-	PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
-	PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
-	PTJ6_IN_PU, PTJ5_IN_PU, PTJ4_IN_PU,
-	PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
-	PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
-	PTL7_IN_PU, PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU, PTL3_IN_PU,
-	PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
-	PTM3_IN_PU, PTM2_IN_PU, PTM1_IN_PU, PTM0_IN_PU,
-	PTP4_IN_PU, PTP3_IN_PU, PTP2_IN_PU, PTP1_IN_PU, PTP0_IN_PU,
-	PTR7_IN_PU, PTR6_IN_PU, PTR5_IN_PU, PTR4_IN_PU,
-	PTR3_IN_PU, PTR2_IN_PU, PTR1_IN_PU, PTR0_IN_PU,
-	PTS4_IN_PU, PTS3_IN_PU, PTS2_IN_PU, PTS1_IN_PU, PTS0_IN_PU,
-	PTT4_IN_PU, PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
-	PTU4_IN_PU, PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
-	PTV4_IN_PU, PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
-	PINMUX_INPUT_PULLUP_END,
-
 	PINMUX_OUTPUT_BEGIN,
 	PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
 	PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
@@ -262,55 +232,55 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* PTA GPIO */
-	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
-	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
-	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT, PTA5_IN_PU),
-	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
-	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
-	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
-	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
-	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
+	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
+	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT),
+	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT),
+	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT),
+	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT),
+	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT),
+	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT),
 
 	/* PTB GPIO */
-	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT, PTB7_IN_PU),
-	PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT, PTB6_IN_PU),
-	PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT, PTB5_IN_PU),
-	PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT, PTB4_IN_PU),
-	PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT, PTB3_IN_PU),
-	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
-	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
-	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT, PTB0_IN_PU),
+	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
+	PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT),
+	PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT),
+	PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT),
+	PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT),
+	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT),
+	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT),
+	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
 
 	/* PTC GPIO */
-	PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT, PTC7_IN_PU),
-	PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT, PTC6_IN_PU),
-	PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT, PTC5_IN_PU),
-	PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT, PTC4_IN_PU),
-	PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT, PTC3_IN_PU),
-	PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT, PTC2_IN_PU),
-	PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT, PTC1_IN_PU),
-	PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT, PTC0_IN_PU),
+	PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT),
+	PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT),
+	PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT),
+	PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT),
+	PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT),
+	PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT),
+	PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT),
+	PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT),
 
 	/* PTD GPIO */
-	PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT, PTD7_IN_PU),
-	PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT, PTD6_IN_PU),
-	PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT, PTD5_IN_PU),
-	PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT, PTD4_IN_PU),
-	PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT, PTD3_IN_PU),
-	PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT, PTD2_IN_PU),
-	PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT, PTD1_IN_PU),
-	PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT, PTD0_IN_PU),
+	PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT),
+	PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT),
+	PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT),
+	PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT),
+	PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT),
+	PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT),
+	PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT),
+	PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT),
 
 	/* PTE GPIO */
 	PINMUX_DATA(PTE6_DATA, PTE6_IN),
 	PINMUX_DATA(PTE5_DATA, PTE5_IN),
-	PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT, PTE4_IN_PU),
-	PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT, PTE3_IN_PU),
-	PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT, PTE2_IN_PU),
-	PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT, PTE1_IN_PU),
-	PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT, PTE0_IN_PU),
+	PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT),
+	PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT),
+	PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT),
+	PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT),
+	PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT),
 
 	/* PTF GPIO */
 	PINMUX_DATA(PTF6_DATA, PTF6_IN),
@@ -319,102 +289,102 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(PTF3_DATA, PTF3_IN),
 	PINMUX_DATA(PTF2_DATA, PTF2_IN),
 	PINMUX_DATA(PTF1_DATA, PTF1_IN),
-	PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT, PTF0_IN_PU),
+	PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT),
 
 	/* PTG GPIO */
-	PINMUX_DATA(PTG6_DATA, PTG6_IN, PTG6_OUT, PTG6_IN_PU),
-	PINMUX_DATA(PTG5_DATA, PTG5_IN, PTG5_OUT, PTG5_IN_PU),
-	PINMUX_DATA(PTG4_DATA, PTG4_IN, PTG4_OUT, PTG4_IN_PU),
-	PINMUX_DATA(PTG3_DATA, PTG3_IN, PTG3_OUT, PTG3_IN_PU),
-	PINMUX_DATA(PTG2_DATA, PTG2_IN, PTG2_OUT, PTG2_IN_PU),
-	PINMUX_DATA(PTG1_DATA, PTG1_IN, PTG1_OUT, PTG1_IN_PU),
-	PINMUX_DATA(PTG0_DATA, PTG0_IN, PTG0_OUT, PTG0_IN_PU),
+	PINMUX_DATA(PTG6_DATA, PTG6_IN, PTG6_OUT),
+	PINMUX_DATA(PTG5_DATA, PTG5_IN, PTG5_OUT),
+	PINMUX_DATA(PTG4_DATA, PTG4_IN, PTG4_OUT),
+	PINMUX_DATA(PTG3_DATA, PTG3_IN, PTG3_OUT),
+	PINMUX_DATA(PTG2_DATA, PTG2_IN, PTG2_OUT),
+	PINMUX_DATA(PTG1_DATA, PTG1_IN, PTG1_OUT),
+	PINMUX_DATA(PTG0_DATA, PTG0_IN, PTG0_OUT),
 
 	/* PTH GPIO */
-	PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT, PTH6_IN_PU),
-	PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT, PTH5_IN_PU),
-	PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT, PTH4_IN_PU),
-	PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT, PTH3_IN_PU),
-	PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT, PTH2_IN_PU),
-	PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT, PTH1_IN_PU),
-	PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT, PTH0_IN_PU),
+	PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT),
+	PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT),
+	PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT),
+	PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT),
+	PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT),
+	PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT),
+	PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT),
 
 	/* PTJ GPIO */
-	PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT, PTJ6_IN_PU),
-	PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT, PTJ5_IN_PU),
-	PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT, PTJ4_IN_PU),
-	PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT, PTJ3_IN_PU),
-	PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT, PTJ2_IN_PU),
-	PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT, PTJ1_IN_PU),
-	PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT, PTJ0_IN_PU),
+	PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT),
+	PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT),
+	PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT),
+	PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT),
+	PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT),
+	PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT),
+	PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT),
 
 	/* PTK GPIO */
-	PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT, PTK3_IN_PU),
-	PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT, PTK2_IN_PU),
-	PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT, PTK1_IN_PU),
-	PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT, PTK0_IN_PU),
+	PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT),
+	PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT),
+	PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT),
+	PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT),
 
 	/* PTL GPIO */
-	PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT, PTL7_IN_PU),
-	PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT, PTL6_IN_PU),
-	PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT, PTL5_IN_PU),
-	PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT, PTL4_IN_PU),
-	PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT, PTL3_IN_PU),
+	PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT),
+	PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT),
+	PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT),
+	PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT),
+	PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT),
 
 	/* PTM GPIO */
-	PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT, PTM7_IN_PU),
-	PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT, PTM6_IN_PU),
-	PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT, PTM5_IN_PU),
-	PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT, PTM4_IN_PU),
-	PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT, PTM3_IN_PU),
-	PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT, PTM2_IN_PU),
-	PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT, PTM1_IN_PU),
-	PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT, PTM0_IN_PU),
+	PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT),
+	PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT),
+	PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT),
+	PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT),
+	PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT),
+	PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT),
+	PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT),
+	PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT),
 
 	/* PTP GPIO */
-	PINMUX_DATA(PTP4_DATA, PTP4_IN, PTP4_OUT, PTP4_IN_PU),
-	PINMUX_DATA(PTP3_DATA, PTP3_IN, PTP3_OUT, PTP3_IN_PU),
-	PINMUX_DATA(PTP2_DATA, PTP2_IN, PTP2_OUT, PTP2_IN_PU),
-	PINMUX_DATA(PTP1_DATA, PTP1_IN, PTP1_OUT, PTP1_IN_PU),
-	PINMUX_DATA(PTP0_DATA, PTP0_IN, PTP0_OUT, PTP0_IN_PU),
+	PINMUX_DATA(PTP4_DATA, PTP4_IN, PTP4_OUT),
+	PINMUX_DATA(PTP3_DATA, PTP3_IN, PTP3_OUT),
+	PINMUX_DATA(PTP2_DATA, PTP2_IN, PTP2_OUT),
+	PINMUX_DATA(PTP1_DATA, PTP1_IN, PTP1_OUT),
+	PINMUX_DATA(PTP0_DATA, PTP0_IN, PTP0_OUT),
 
 	/* PTR GPIO */
-	PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT, PTR7_IN_PU),
-	PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT, PTR6_IN_PU),
-	PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT, PTR5_IN_PU),
-	PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT, PTR4_IN_PU),
-	PINMUX_DATA(PTR3_DATA, PTR3_IN, PTR3_OUT, PTR3_IN_PU),
-	PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_OUT, PTR2_IN_PU),
-	PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT, PTR1_IN_PU),
-	PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT, PTR0_IN_PU),
+	PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT),
+	PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT),
+	PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT),
+	PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT),
+	PINMUX_DATA(PTR3_DATA, PTR3_IN, PTR3_OUT),
+	PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_OUT),
+	PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT),
+	PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT),
 
 	/* PTS GPIO */
-	PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT, PTS4_IN_PU),
-	PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT, PTS3_IN_PU),
-	PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT, PTS2_IN_PU),
-	PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT, PTS1_IN_PU),
-	PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT, PTS0_IN_PU),
+	PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT),
+	PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT),
+	PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT),
+	PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT),
+	PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT),
 
 	/* PTT GPIO */
-	PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT, PTT4_IN_PU),
-	PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT, PTT3_IN_PU),
-	PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT, PTT2_IN_PU),
-	PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT, PTT1_IN_PU),
-	PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT, PTT0_IN_PU),
+	PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT),
+	PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT),
+	PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT),
+	PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT),
+	PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT),
 
 	/* PTU GPIO */
-	PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT, PTU4_IN_PU),
-	PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT, PTU3_IN_PU),
-	PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT, PTU2_IN_PU),
-	PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT, PTU1_IN_PU),
-	PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT, PTU0_IN_PU),
+	PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT),
+	PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT),
+	PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT),
+	PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT),
+	PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT),
 
 	/* PTV GPIO */
-	PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT, PTV4_IN_PU),
-	PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT, PTV3_IN_PU),
-	PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT, PTV2_IN_PU),
-	PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT, PTV1_IN_PU),
-	PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT, PTV0_IN_PU),
+	PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT),
+	PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT),
+	PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT),
+	PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT),
+	PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT),
 
 	/* PTA FN */
 	PINMUX_DATA(D23_MARK, PTA7_FN),
@@ -608,157 +578,157 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
-	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
-	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
-	PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
-	PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
-	PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
-	PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
-	PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
-	PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+	PINMUX_GPIO(PTA7),
+	PINMUX_GPIO(PTA6),
+	PINMUX_GPIO(PTA5),
+	PINMUX_GPIO(PTA4),
+	PINMUX_GPIO(PTA3),
+	PINMUX_GPIO(PTA2),
+	PINMUX_GPIO(PTA1),
+	PINMUX_GPIO(PTA0),
 
 	/* PTB */
-	PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
-	PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
-	PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
-	PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
-	PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
-	PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
-	PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
-	PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+	PINMUX_GPIO(PTB7),
+	PINMUX_GPIO(PTB6),
+	PINMUX_GPIO(PTB5),
+	PINMUX_GPIO(PTB4),
+	PINMUX_GPIO(PTB3),
+	PINMUX_GPIO(PTB2),
+	PINMUX_GPIO(PTB1),
+	PINMUX_GPIO(PTB0),
 
 	/* PTC */
-	PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
-	PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
-	PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
-	PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
-	PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
-	PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
-	PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
-	PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+	PINMUX_GPIO(PTC7),
+	PINMUX_GPIO(PTC6),
+	PINMUX_GPIO(PTC5),
+	PINMUX_GPIO(PTC4),
+	PINMUX_GPIO(PTC3),
+	PINMUX_GPIO(PTC2),
+	PINMUX_GPIO(PTC1),
+	PINMUX_GPIO(PTC0),
 
 	/* PTD */
-	PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
-	PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
-	PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
-	PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
-	PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
-	PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
-	PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
-	PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+	PINMUX_GPIO(PTD7),
+	PINMUX_GPIO(PTD6),
+	PINMUX_GPIO(PTD5),
+	PINMUX_GPIO(PTD4),
+	PINMUX_GPIO(PTD3),
+	PINMUX_GPIO(PTD2),
+	PINMUX_GPIO(PTD1),
+	PINMUX_GPIO(PTD0),
 
 	/* PTE */
-	PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
-	PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
-	PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
-	PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
-	PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
-	PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
-	PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+	PINMUX_GPIO(PTE6),
+	PINMUX_GPIO(PTE5),
+	PINMUX_GPIO(PTE4),
+	PINMUX_GPIO(PTE3),
+	PINMUX_GPIO(PTE2),
+	PINMUX_GPIO(PTE1),
+	PINMUX_GPIO(PTE0),
 
 	/* PTF */
-	PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
-	PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
-	PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
-	PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
-	PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
-	PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
-	PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+	PINMUX_GPIO(PTF6),
+	PINMUX_GPIO(PTF5),
+	PINMUX_GPIO(PTF4),
+	PINMUX_GPIO(PTF3),
+	PINMUX_GPIO(PTF2),
+	PINMUX_GPIO(PTF1),
+	PINMUX_GPIO(PTF0),
 
 	/* PTG */
-	PINMUX_GPIO(GPIO_PTG6, PTG6_DATA),
-	PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
-	PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
-	PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
-	PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
-	PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
-	PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+	PINMUX_GPIO(PTG6),
+	PINMUX_GPIO(PTG5),
+	PINMUX_GPIO(PTG4),
+	PINMUX_GPIO(PTG3),
+	PINMUX_GPIO(PTG2),
+	PINMUX_GPIO(PTG1),
+	PINMUX_GPIO(PTG0),
 
 	/* PTH */
-	PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
-	PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
-	PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
-	PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
-	PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
-	PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
-	PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+	PINMUX_GPIO(PTH6),
+	PINMUX_GPIO(PTH5),
+	PINMUX_GPIO(PTH4),
+	PINMUX_GPIO(PTH3),
+	PINMUX_GPIO(PTH2),
+	PINMUX_GPIO(PTH1),
+	PINMUX_GPIO(PTH0),
 
 	/* PTJ */
-	PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
-	PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
-	PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA),
-	PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
-	PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
-	PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
-	PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+	PINMUX_GPIO(PTJ6),
+	PINMUX_GPIO(PTJ5),
+	PINMUX_GPIO(PTJ4),
+	PINMUX_GPIO(PTJ3),
+	PINMUX_GPIO(PTJ2),
+	PINMUX_GPIO(PTJ1),
+	PINMUX_GPIO(PTJ0),
 
 	/* PTK */
-	PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
-	PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
-	PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
-	PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+	PINMUX_GPIO(PTK3),
+	PINMUX_GPIO(PTK2),
+	PINMUX_GPIO(PTK1),
+	PINMUX_GPIO(PTK0),
 
 	/* PTL */
-	PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
-	PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
-	PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
-	PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
-	PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+	PINMUX_GPIO(PTL7),
+	PINMUX_GPIO(PTL6),
+	PINMUX_GPIO(PTL5),
+	PINMUX_GPIO(PTL4),
+	PINMUX_GPIO(PTL3),
 
 	/* PTM */
-	PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
-	PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
-	PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
-	PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
-	PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
-	PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
-	PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
-	PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+	PINMUX_GPIO(PTM7),
+	PINMUX_GPIO(PTM6),
+	PINMUX_GPIO(PTM5),
+	PINMUX_GPIO(PTM4),
+	PINMUX_GPIO(PTM3),
+	PINMUX_GPIO(PTM2),
+	PINMUX_GPIO(PTM1),
+	PINMUX_GPIO(PTM0),
 
 	/* PTP */
-	PINMUX_GPIO(GPIO_PTP4, PTP4_DATA),
-	PINMUX_GPIO(GPIO_PTP3, PTP3_DATA),
-	PINMUX_GPIO(GPIO_PTP2, PTP2_DATA),
-	PINMUX_GPIO(GPIO_PTP1, PTP1_DATA),
-	PINMUX_GPIO(GPIO_PTP0, PTP0_DATA),
+	PINMUX_GPIO(PTP4),
+	PINMUX_GPIO(PTP3),
+	PINMUX_GPIO(PTP2),
+	PINMUX_GPIO(PTP1),
+	PINMUX_GPIO(PTP0),
 
 	/* PTR */
-	PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
-	PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
-	PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
-	PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
-	PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
-	PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
-	PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
-	PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+	PINMUX_GPIO(PTR7),
+	PINMUX_GPIO(PTR6),
+	PINMUX_GPIO(PTR5),
+	PINMUX_GPIO(PTR4),
+	PINMUX_GPIO(PTR3),
+	PINMUX_GPIO(PTR2),
+	PINMUX_GPIO(PTR1),
+	PINMUX_GPIO(PTR0),
 
 	/* PTS */
-	PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
-	PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
-	PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
-	PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
-	PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+	PINMUX_GPIO(PTS4),
+	PINMUX_GPIO(PTS3),
+	PINMUX_GPIO(PTS2),
+	PINMUX_GPIO(PTS1),
+	PINMUX_GPIO(PTS0),
 
 	/* PTT */
-	PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
-	PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
-	PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
-	PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
-	PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+	PINMUX_GPIO(PTT4),
+	PINMUX_GPIO(PTT3),
+	PINMUX_GPIO(PTT2),
+	PINMUX_GPIO(PTT1),
+	PINMUX_GPIO(PTT0),
 
 	/* PTU */
-	PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
-	PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
-	PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
-	PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
-	PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+	PINMUX_GPIO(PTU4),
+	PINMUX_GPIO(PTU3),
+	PINMUX_GPIO(PTU2),
+	PINMUX_GPIO(PTU1),
+	PINMUX_GPIO(PTU0),
 
 	/* PTV */
-	PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
-	PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
-	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
-	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
-	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+	PINMUX_GPIO(PTV4),
+	PINMUX_GPIO(PTV3),
+	PINMUX_GPIO(PTV2),
+	PINMUX_GPIO(PTV1),
+	PINMUX_GPIO(PTV0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -959,54 +929,54 @@ static const struct pinmux_func pinmux_func_gpios[] = {
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
-		PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
-		PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
-		PTA5_FN, PTA5_OUT, PTA5_IN_PU, PTA5_IN,
-		PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
-		PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
-		PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
-		PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
-		PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+		PTA7_FN, PTA7_OUT, 0, PTA7_IN,
+		PTA6_FN, PTA6_OUT, 0, PTA6_IN,
+		PTA5_FN, PTA5_OUT, 0, PTA5_IN,
+		PTA4_FN, PTA4_OUT, 0, PTA4_IN,
+		PTA3_FN, PTA3_OUT, 0, PTA3_IN,
+		PTA2_FN, PTA2_OUT, 0, PTA2_IN,
+		PTA1_FN, PTA1_OUT, 0, PTA1_IN,
+		PTA0_FN, PTA0_OUT, 0, PTA0_IN }
 	},
 	{ PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
-		PTB7_FN, PTB7_OUT, PTB7_IN_PU, PTB7_IN,
-		PTB6_FN, PTB6_OUT, PTB6_IN_PU, PTB6_IN,
-		PTB5_FN, PTB5_OUT, PTB5_IN_PU, PTB5_IN,
-		PTB4_FN, PTB4_OUT, PTB4_IN_PU, PTB4_IN,
-		PTB3_FN, PTB3_OUT, PTB3_IN_PU, PTB3_IN,
-		PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
-		PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
-		PTB0_FN, PTB0_OUT, PTB0_IN_PU, PTB0_IN }
+		PTB7_FN, PTB7_OUT, 0, PTB7_IN,
+		PTB6_FN, PTB6_OUT, 0, PTB6_IN,
+		PTB5_FN, PTB5_OUT, 0, PTB5_IN,
+		PTB4_FN, PTB4_OUT, 0, PTB4_IN,
+		PTB3_FN, PTB3_OUT, 0, PTB3_IN,
+		PTB2_FN, PTB2_OUT, 0, PTB2_IN,
+		PTB1_FN, PTB1_OUT, 0, PTB1_IN,
+		PTB0_FN, PTB0_OUT, 0, PTB0_IN }
 	},
 	{ PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
-		PTC7_FN, PTC7_OUT, PTC7_IN_PU, PTC7_IN,
-		PTC6_FN, PTC6_OUT, PTC6_IN_PU, PTC6_IN,
-		PTC5_FN, PTC5_OUT, PTC5_IN_PU, PTC5_IN,
-		PTC4_FN, PTC4_OUT, PTC4_IN_PU, PTC4_IN,
-		PTC3_FN, PTC3_OUT, PTC3_IN_PU, PTC3_IN,
-		PTC2_FN, PTC2_OUT, PTC2_IN_PU, PTC2_IN,
-		PTC1_FN, PTC1_OUT, PTC1_IN_PU, PTC1_IN,
-		PTC0_FN, PTC0_OUT, PTC0_IN_PU, PTC0_IN }
+		PTC7_FN, PTC7_OUT, 0, PTC7_IN,
+		PTC6_FN, PTC6_OUT, 0, PTC6_IN,
+		PTC5_FN, PTC5_OUT, 0, PTC5_IN,
+		PTC4_FN, PTC4_OUT, 0, PTC4_IN,
+		PTC3_FN, PTC3_OUT, 0, PTC3_IN,
+		PTC2_FN, PTC2_OUT, 0, PTC2_IN,
+		PTC1_FN, PTC1_OUT, 0, PTC1_IN,
+		PTC0_FN, PTC0_OUT, 0, PTC0_IN }
 	},
 	{ PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
-		PTD7_FN, PTD7_OUT, PTD7_IN_PU, PTD7_IN,
-		PTD6_FN, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
-		PTD5_FN, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
-		PTD4_FN, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
-		PTD3_FN, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
-		PTD2_FN, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
-		PTD1_FN, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
-		PTD0_FN, PTD0_OUT, PTD0_IN_PU, PTD0_IN }
+		PTD7_FN, PTD7_OUT, 0, PTD7_IN,
+		PTD6_FN, PTD6_OUT, 0, PTD6_IN,
+		PTD5_FN, PTD5_OUT, 0, PTD5_IN,
+		PTD4_FN, PTD4_OUT, 0, PTD4_IN,
+		PTD3_FN, PTD3_OUT, 0, PTD3_IN,
+		PTD2_FN, PTD2_OUT, 0, PTD2_IN,
+		PTD1_FN, PTD1_OUT, 0, PTD1_IN,
+		PTD0_FN, PTD0_OUT, 0, PTD0_IN }
 	},
 	{ PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
 		0, 0, 0, 0,
 		PTE6_FN, 0, 0, PTE6_IN,
 		PTE5_FN, 0, 0, PTE5_IN,
-		PTE4_FN, PTE4_OUT, PTE4_IN_PU, PTE4_IN,
-		PTE3_FN, PTE3_OUT, PTE3_IN_PU, PTE3_IN,
-		PTE2_FN, PTE2_OUT, PTE2_IN_PU, PTE2_IN,
-		PTE1_FN, PTE1_OUT, PTE1_IN_PU, PTE1_IN,
-		PTE0_FN, PTE0_OUT, PTE0_IN_PU, PTE0_IN }
+		PTE4_FN, PTE4_OUT, 0, PTE4_IN,
+		PTE3_FN, PTE3_OUT, 0, PTE3_IN,
+		PTE2_FN, PTE2_OUT, 0, PTE2_IN,
+		PTE1_FN, PTE1_OUT, 0, PTE1_IN,
+		PTE0_FN, PTE0_OUT, 0, PTE0_IN }
 	},
 	{ PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
 		0, 0, 0, 0,
@@ -1020,123 +990,123 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	},
 	{ PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
 		0, 0, 0, 0,
-		PTG6_FN, PTG6_OUT, PTG6_IN_PU, PTG6_IN,
-		PTG5_FN, PTG5_OUT, PTG5_IN_PU, PTG5_IN,
-		PTG4_FN, PTG4_OUT, PTG4_IN_PU, PTG4_IN,
-		PTG3_FN, PTG3_OUT, PTG3_IN_PU, PTG3_IN,
-		PTG2_FN, PTG2_OUT, PTG2_IN_PU, PTG2_IN,
-		PTG1_FN, PTG1_OUT, PTG1_IN_PU, PTG1_IN,
-		PTG0_FN, PTG0_OUT, PTG0_IN_PU, PTG0_IN }
+		PTG6_FN, PTG6_OUT, 0, PTG6_IN,
+		PTG5_FN, PTG5_OUT, 0, PTG5_IN,
+		PTG4_FN, PTG4_OUT, 0, PTG4_IN,
+		PTG3_FN, PTG3_OUT, 0, PTG3_IN,
+		PTG2_FN, PTG2_OUT, 0, PTG2_IN,
+		PTG1_FN, PTG1_OUT, 0, PTG1_IN,
+		PTG0_FN, PTG0_OUT, 0, PTG0_IN }
 	},
 	{ PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
 		0, 0, 0, 0,
-		PTH6_FN, PTH6_OUT, PTH6_IN_PU, PTH6_IN,
-		PTH5_FN, PTH5_OUT, PTH5_IN_PU, PTH5_IN,
-		PTH4_FN, PTH4_OUT, PTH4_IN_PU, PTH4_IN,
-		PTH3_FN, PTH3_OUT, PTH3_IN_PU, PTH3_IN,
-		PTH2_FN, PTH2_OUT, PTH2_IN_PU, PTH2_IN,
-		PTH1_FN, PTH1_OUT, PTH1_IN_PU, PTH1_IN,
-		PTH0_FN, PTH0_OUT, PTH0_IN_PU, PTH0_IN }
+		PTH6_FN, PTH6_OUT, 0, PTH6_IN,
+		PTH5_FN, PTH5_OUT, 0, PTH5_IN,
+		PTH4_FN, PTH4_OUT, 0, PTH4_IN,
+		PTH3_FN, PTH3_OUT, 0, PTH3_IN,
+		PTH2_FN, PTH2_OUT, 0, PTH2_IN,
+		PTH1_FN, PTH1_OUT, 0, PTH1_IN,
+		PTH0_FN, PTH0_OUT, 0, PTH0_IN }
 	},
 	{ PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
 		0, 0, 0, 0,
-		PTJ6_FN, PTJ6_OUT, PTJ6_IN_PU, PTJ6_IN,
-		PTJ5_FN, PTJ5_OUT, PTJ5_IN_PU, PTJ5_IN,
-		PTJ4_FN, PTJ4_OUT, PTJ4_IN_PU, PTJ4_IN,
-		PTJ3_FN, PTJ3_OUT, PTJ3_IN_PU, PTJ3_IN,
-		PTJ2_FN, PTJ2_OUT, PTJ2_IN_PU, PTJ2_IN,
-		PTJ1_FN, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
-		PTJ0_FN, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+		PTJ6_FN, PTJ6_OUT, 0, PTJ6_IN,
+		PTJ5_FN, PTJ5_OUT, 0, PTJ5_IN,
+		PTJ4_FN, PTJ4_OUT, 0, PTJ4_IN,
+		PTJ3_FN, PTJ3_OUT, 0, PTJ3_IN,
+		PTJ2_FN, PTJ2_OUT, 0, PTJ2_IN,
+		PTJ1_FN, PTJ1_OUT, 0, PTJ1_IN,
+		PTJ0_FN, PTJ0_OUT, 0, PTJ0_IN }
 	},
 	{ PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PTK3_FN, PTK3_OUT, PTK3_IN_PU, PTK3_IN,
-		PTK2_FN, PTK2_OUT, PTK2_IN_PU, PTK2_IN,
-		PTK1_FN, PTK1_OUT, PTK1_IN_PU, PTK1_IN,
-		PTK0_FN, PTK0_OUT, PTK0_IN_PU, PTK0_IN }
+		PTK3_FN, PTK3_OUT, 0, PTK3_IN,
+		PTK2_FN, PTK2_OUT, 0, PTK2_IN,
+		PTK1_FN, PTK1_OUT, 0, PTK1_IN,
+		PTK0_FN, PTK0_OUT, 0, PTK0_IN }
 	},
 	{ PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
-		PTL7_FN, PTL7_OUT, PTL7_IN_PU, PTL7_IN,
-		PTL6_FN, PTL6_OUT, PTL6_IN_PU, PTL6_IN,
-		PTL5_FN, PTL5_OUT, PTL5_IN_PU, PTL5_IN,
-		PTL4_FN, PTL4_OUT, PTL4_IN_PU, PTL4_IN,
-		PTL3_FN, PTL3_OUT, PTL3_IN_PU, PTL3_IN,
+		PTL7_FN, PTL7_OUT, 0, PTL7_IN,
+		PTL6_FN, PTL6_OUT, 0, PTL6_IN,
+		PTL5_FN, PTL5_OUT, 0, PTL5_IN,
+		PTL4_FN, PTL4_OUT, 0, PTL4_IN,
+		PTL3_FN, PTL3_OUT, 0, PTL3_IN,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
-		PTM7_FN, PTM7_OUT, PTM7_IN_PU, PTM7_IN,
-		PTM6_FN, PTM6_OUT, PTM6_IN_PU, PTM6_IN,
-		PTM5_FN, PTM5_OUT, PTM5_IN_PU, PTM5_IN,
-		PTM4_FN, PTM4_OUT, PTM4_IN_PU, PTM4_IN,
-		PTM3_FN, PTM3_OUT, PTM3_IN_PU, PTM3_IN,
-		PTM2_FN, PTM2_OUT, PTM2_IN_PU, PTM2_IN,
-		PTM1_FN, PTM1_OUT, PTM1_IN_PU, PTM1_IN,
-		PTM0_FN, PTM0_OUT, PTM0_IN_PU, PTM0_IN }
+		PTM7_FN, PTM7_OUT, 0, PTM7_IN,
+		PTM6_FN, PTM6_OUT, 0, PTM6_IN,
+		PTM5_FN, PTM5_OUT, 0, PTM5_IN,
+		PTM4_FN, PTM4_OUT, 0, PTM4_IN,
+		PTM3_FN, PTM3_OUT, 0, PTM3_IN,
+		PTM2_FN, PTM2_OUT, 0, PTM2_IN,
+		PTM1_FN, PTM1_OUT, 0, PTM1_IN,
+		PTM0_FN, PTM0_OUT, 0, PTM0_IN }
 	},
 	{ PINMUX_CFG_REG("PPCR", 0xa4050118, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PTP4_FN, PTP4_OUT, PTP4_IN_PU, PTP4_IN,
-		PTP3_FN, PTP3_OUT, PTP3_IN_PU, PTP3_IN,
-		PTP2_FN, PTP2_OUT, PTP2_IN_PU, PTP2_IN,
-		PTP1_FN, PTP1_OUT, PTP1_IN_PU, PTP1_IN,
-		PTP0_FN, PTP0_OUT, PTP0_IN_PU, PTP0_IN }
+		PTP4_FN, PTP4_OUT, 0, PTP4_IN,
+		PTP3_FN, PTP3_OUT, 0, PTP3_IN,
+		PTP2_FN, PTP2_OUT, 0, PTP2_IN,
+		PTP1_FN, PTP1_OUT, 0, PTP1_IN,
+		PTP0_FN, PTP0_OUT, 0, PTP0_IN }
 	},
 	{ PINMUX_CFG_REG("PRCR", 0xa405011a, 16, 2) {
-		PTR7_FN, PTR7_OUT, PTR7_IN_PU, PTR7_IN,
-		PTR6_FN, PTR6_OUT, PTR6_IN_PU, PTR6_IN,
-		PTR5_FN, PTR5_OUT, PTR5_IN_PU, PTR5_IN,
-		PTR4_FN, PTR4_OUT, PTR4_IN_PU, PTR4_IN,
-		PTR3_FN, PTR3_OUT, PTR3_IN_PU, PTR3_IN,
-		PTR2_FN, PTR2_OUT, PTR2_IN_PU, PTR2_IN,
-		PTR1_FN, PTR1_OUT, PTR1_IN_PU, PTR1_IN,
-		PTR0_FN, PTR0_OUT, PTR0_IN_PU, PTR0_IN }
+		PTR7_FN, PTR7_OUT, 0, PTR7_IN,
+		PTR6_FN, PTR6_OUT, 0, PTR6_IN,
+		PTR5_FN, PTR5_OUT, 0, PTR5_IN,
+		PTR4_FN, PTR4_OUT, 0, PTR4_IN,
+		PTR3_FN, PTR3_OUT, 0, PTR3_IN,
+		PTR2_FN, PTR2_OUT, 0, PTR2_IN,
+		PTR1_FN, PTR1_OUT, 0, PTR1_IN,
+		PTR0_FN, PTR0_OUT, 0, PTR0_IN }
 	},
 	{ PINMUX_CFG_REG("PSCR", 0xa405011c, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PTS4_FN, PTS4_OUT, PTS4_IN_PU, PTS4_IN,
-		PTS3_FN, PTS3_OUT, PTS3_IN_PU, PTS3_IN,
-		PTS2_FN, PTS2_OUT, PTS2_IN_PU, PTS2_IN,
-		PTS1_FN, PTS1_OUT, PTS1_IN_PU, PTS1_IN,
-		PTS0_FN, PTS0_OUT, PTS0_IN_PU, PTS0_IN }
+		PTS4_FN, PTS4_OUT, 0, PTS4_IN,
+		PTS3_FN, PTS3_OUT, 0, PTS3_IN,
+		PTS2_FN, PTS2_OUT, 0, PTS2_IN,
+		PTS1_FN, PTS1_OUT, 0, PTS1_IN,
+		PTS0_FN, PTS0_OUT, 0, PTS0_IN }
 	},
 	{ PINMUX_CFG_REG("PTCR", 0xa405011e, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PTT4_FN, PTT4_OUT, PTT4_IN_PU, PTT4_IN,
-		PTT3_FN, PTT3_OUT, PTT3_IN_PU, PTT3_IN,
-		PTT2_FN, PTT2_OUT, PTT2_IN_PU, PTT2_IN,
-		PTT1_FN, PTT1_OUT, PTT1_IN_PU, PTT1_IN,
-		PTT0_FN, PTT0_OUT, PTT0_IN_PU, PTT0_IN }
+		PTT4_FN, PTT4_OUT, 0, PTT4_IN,
+		PTT3_FN, PTT3_OUT, 0, PTT3_IN,
+		PTT2_FN, PTT2_OUT, 0, PTT2_IN,
+		PTT1_FN, PTT1_OUT, 0, PTT1_IN,
+		PTT0_FN, PTT0_OUT, 0, PTT0_IN }
 	},
 	{ PINMUX_CFG_REG("PUCR", 0xa4050120, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PTU4_FN, PTU4_OUT, PTU4_IN_PU, PTU4_IN,
-		PTU3_FN, PTU3_OUT, PTU3_IN_PU, PTU3_IN,
-		PTU2_FN, PTU2_OUT, PTU2_IN_PU, PTU2_IN,
-		PTU1_FN, PTU1_OUT, PTU1_IN_PU, PTU1_IN,
-		PTU0_FN, PTU0_OUT, PTU0_IN_PU, PTU0_IN }
+		PTU4_FN, PTU4_OUT, 0, PTU4_IN,
+		PTU3_FN, PTU3_OUT, 0, PTU3_IN,
+		PTU2_FN, PTU2_OUT, 0, PTU2_IN,
+		PTU1_FN, PTU1_OUT, 0, PTU1_IN,
+		PTU0_FN, PTU0_OUT, 0, PTU0_IN }
 	},
 	{ PINMUX_CFG_REG("PVCR", 0xa4050122, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PTV4_FN, PTV4_OUT, PTV4_IN_PU, PTV4_IN,
-		PTV3_FN, PTV3_OUT, PTV3_IN_PU, PTV3_IN,
-		PTV2_FN, PTV2_OUT, PTV2_IN_PU, PTV2_IN,
-		PTV1_FN, PTV1_OUT, PTV1_IN_PU, PTV1_IN,
-		PTV0_FN, PTV0_OUT, PTV0_IN_PU, PTV0_IN }
+		PTV4_FN, PTV4_OUT, 0, PTV4_IN,
+		PTV3_FN, PTV3_OUT, 0, PTV3_IN,
+		PTV2_FN, PTV2_OUT, 0, PTV2_IN,
+		PTV1_FN, PTV1_OUT, 0, PTV1_IN,
+		PTV0_FN, PTV0_OUT, 0, PTV0_IN }
 	},
 	{}
 };
@@ -1220,7 +1190,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7720_pinmux_info = {
 	.name = "sh7720_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7722.c b/drivers/pinctrl/sh-pfc/pfc-sh7722.c
index 3203438..add3093 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7722.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7722.c
@@ -77,39 +77,6 @@ enum {
 	PTZ5_IN, PTZ4_IN, PTZ3_IN, PTZ2_IN, PTZ1_IN,
 	PINMUX_INPUT_END,
 
-	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PTA7_IN_PD, PTA6_IN_PD, PTA5_IN_PD, PTA4_IN_PD,
-	PTA3_IN_PD, PTA2_IN_PD, PTA1_IN_PD, PTA0_IN_PD,
-	PTE7_IN_PD, PTE6_IN_PD, PTE5_IN_PD, PTE4_IN_PD,	PTE1_IN_PD, PTE0_IN_PD,
-	PTF6_IN_PD, PTF5_IN_PD, PTF4_IN_PD, PTF3_IN_PD, PTF2_IN_PD, PTF1_IN_PD,
-	PTH6_IN_PD, PTH5_IN_PD, PTH1_IN_PD, PTH0_IN_PD,
-	PTK6_IN_PD, PTK5_IN_PD, PTK4_IN_PD, PTK3_IN_PD, PTK2_IN_PD, PTK0_IN_PD,
-	PTL7_IN_PD, PTL6_IN_PD, PTL5_IN_PD, PTL4_IN_PD,
-	PTL3_IN_PD, PTL2_IN_PD, PTL1_IN_PD, PTL0_IN_PD,
-	PTM7_IN_PD, PTM6_IN_PD, PTM5_IN_PD, PTM4_IN_PD,
-	PTM3_IN_PD, PTM2_IN_PD, PTM1_IN_PD, PTM0_IN_PD,
-	PTQ5_IN_PD, PTQ4_IN_PD, PTQ3_IN_PD, PTQ2_IN_PD,
-	PTS4_IN_PD, PTS2_IN_PD, PTS1_IN_PD,
-	PTT4_IN_PD, PTT3_IN_PD, PTT2_IN_PD, PTT1_IN_PD,
-	PTU4_IN_PD, PTU3_IN_PD, PTU2_IN_PD, PTU1_IN_PD, PTU0_IN_PD,
-	PTV4_IN_PD, PTV3_IN_PD, PTV2_IN_PD, PTV1_IN_PD, PTV0_IN_PD,
-	PTW6_IN_PD, PTW4_IN_PD,	PTW3_IN_PD, PTW2_IN_PD, PTW1_IN_PD, PTW0_IN_PD,
-	PTX6_IN_PD, PTX5_IN_PD, PTX4_IN_PD,
-	PTX3_IN_PD, PTX2_IN_PD, PTX1_IN_PD, PTX0_IN_PD,
-	PINMUX_INPUT_PULLDOWN_END,
-
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PTC7_IN_PU, PTC5_IN_PU,
-	PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
-	PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU,
-	PTJ1_IN_PU, PTJ0_IN_PU,
-	PTQ0_IN_PU,
-	PTR2_IN_PU,
-	PTX6_IN_PU,
-	PTY5_IN_PU, PTY4_IN_PU, PTY3_IN_PU, PTY2_IN_PU, PTY0_IN_PU,
-	PTZ5_IN_PU, PTZ4_IN_PU, PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU,
-	PINMUX_INPUT_PULLUP_END,
-
 	PINMUX_OUTPUT_BEGIN,
 	PTA7_OUT, PTA5_OUT,
 	PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
@@ -296,16 +263,16 @@ enum {
 	PINMUX_FUNCTION_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* PTA */
-	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_IN_PD, PTA7_OUT),
-	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_IN_PD),
-	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_IN_PD, PTA5_OUT),
-	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_IN_PD),
-	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_IN_PD),
-	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_IN_PD),
-	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_IN_PD),
-	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_IN_PD),
+	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
+	PINMUX_DATA(PTA6_DATA, PTA6_IN),
+	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT),
+	PINMUX_DATA(PTA4_DATA, PTA4_IN),
+	PINMUX_DATA(PTA3_DATA, PTA3_IN),
+	PINMUX_DATA(PTA2_DATA, PTA2_IN),
+	PINMUX_DATA(PTA1_DATA, PTA1_IN),
+	PINMUX_DATA(PTA0_DATA, PTA0_IN),
 
 	/* PTB */
 	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
@@ -318,38 +285,38 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
 
 	/* PTC */
-	PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_IN_PU),
-	PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_IN_PU),
+	PINMUX_DATA(PTC7_DATA, PTC7_IN),
+	PINMUX_DATA(PTC5_DATA, PTC5_IN),
 	PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT),
 	PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT),
 	PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT),
 	PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT),
 
 	/* PTD */
-	PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_IN_PU),
-	PINMUX_DATA(PTD6_DATA, PTD6_OUT, PTD6_IN, PTD6_IN_PU),
-	PINMUX_DATA(PTD5_DATA, PTD5_OUT, PTD5_IN, PTD5_IN_PU),
-	PINMUX_DATA(PTD4_DATA, PTD4_OUT, PTD4_IN, PTD4_IN_PU),
-	PINMUX_DATA(PTD3_DATA, PTD3_OUT, PTD3_IN, PTD3_IN_PU),
-	PINMUX_DATA(PTD2_DATA, PTD2_OUT, PTD2_IN, PTD2_IN_PU),
-	PINMUX_DATA(PTD1_DATA, PTD1_OUT, PTD1_IN, PTD1_IN_PU),
+	PINMUX_DATA(PTD7_DATA, PTD7_IN),
+	PINMUX_DATA(PTD6_DATA, PTD6_OUT, PTD6_IN),
+	PINMUX_DATA(PTD5_DATA, PTD5_OUT, PTD5_IN),
+	PINMUX_DATA(PTD4_DATA, PTD4_OUT, PTD4_IN),
+	PINMUX_DATA(PTD3_DATA, PTD3_OUT, PTD3_IN),
+	PINMUX_DATA(PTD2_DATA, PTD2_OUT, PTD2_IN),
+	PINMUX_DATA(PTD1_DATA, PTD1_OUT, PTD1_IN),
 	PINMUX_DATA(PTD0_DATA, PTD0_OUT),
 
 	/* PTE */
-	PINMUX_DATA(PTE7_DATA, PTE7_OUT, PTE7_IN, PTE7_IN_PD),
-	PINMUX_DATA(PTE6_DATA, PTE6_OUT, PTE6_IN, PTE6_IN_PD),
-	PINMUX_DATA(PTE5_DATA, PTE5_OUT, PTE5_IN, PTE5_IN_PD),
-	PINMUX_DATA(PTE4_DATA, PTE4_OUT, PTE4_IN, PTE4_IN_PD),
-	PINMUX_DATA(PTE1_DATA, PTE1_OUT, PTE1_IN, PTE1_IN_PD),
-	PINMUX_DATA(PTE0_DATA, PTE0_OUT, PTE0_IN, PTE0_IN_PD),
+	PINMUX_DATA(PTE7_DATA, PTE7_OUT, PTE7_IN),
+	PINMUX_DATA(PTE6_DATA, PTE6_OUT, PTE6_IN),
+	PINMUX_DATA(PTE5_DATA, PTE5_OUT, PTE5_IN),
+	PINMUX_DATA(PTE4_DATA, PTE4_OUT, PTE4_IN),
+	PINMUX_DATA(PTE1_DATA, PTE1_OUT, PTE1_IN),
+	PINMUX_DATA(PTE0_DATA, PTE0_OUT, PTE0_IN),
 
 	/* PTF */
-	PINMUX_DATA(PTF6_DATA, PTF6_OUT, PTF6_IN, PTF6_IN_PD),
-	PINMUX_DATA(PTF5_DATA, PTF5_OUT, PTF5_IN, PTF5_IN_PD),
-	PINMUX_DATA(PTF4_DATA, PTF4_OUT, PTF4_IN, PTF4_IN_PD),
-	PINMUX_DATA(PTF3_DATA, PTF3_OUT, PTF3_IN, PTF3_IN_PD),
-	PINMUX_DATA(PTF2_DATA, PTF2_OUT, PTF2_IN, PTF2_IN_PD),
-	PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_IN_PD),
+	PINMUX_DATA(PTF6_DATA, PTF6_OUT, PTF6_IN),
+	PINMUX_DATA(PTF5_DATA, PTF5_OUT, PTF5_IN),
+	PINMUX_DATA(PTF4_DATA, PTF4_OUT, PTF4_IN),
+	PINMUX_DATA(PTF3_DATA, PTF3_OUT, PTF3_IN),
+	PINMUX_DATA(PTF2_DATA, PTF2_OUT, PTF2_IN),
+	PINMUX_DATA(PTF1_DATA, PTF1_IN),
 	PINMUX_DATA(PTF0_DATA, PTF0_OUT),
 
 	/* PTG */
@@ -361,49 +328,49 @@ static const pinmux_enum_t pinmux_data[] = {
 
 	/* PTH */
 	PINMUX_DATA(PTH7_DATA, PTH7_OUT),
-	PINMUX_DATA(PTH6_DATA, PTH6_OUT, PTH6_IN, PTH6_IN_PD),
-	PINMUX_DATA(PTH5_DATA, PTH5_OUT, PTH5_IN, PTH5_IN_PD),
+	PINMUX_DATA(PTH6_DATA, PTH6_OUT, PTH6_IN),
+	PINMUX_DATA(PTH5_DATA, PTH5_OUT, PTH5_IN),
 	PINMUX_DATA(PTH4_DATA, PTH4_OUT),
 	PINMUX_DATA(PTH3_DATA, PTH3_OUT),
 	PINMUX_DATA(PTH2_DATA, PTH2_OUT),
-	PINMUX_DATA(PTH1_DATA, PTH1_OUT, PTH1_IN, PTH1_IN_PD),
-	PINMUX_DATA(PTH0_DATA, PTH0_OUT, PTH0_IN, PTH0_IN_PD),
+	PINMUX_DATA(PTH1_DATA, PTH1_OUT, PTH1_IN),
+	PINMUX_DATA(PTH0_DATA, PTH0_OUT, PTH0_IN),
 
 	/* PTJ */
 	PINMUX_DATA(PTJ7_DATA, PTJ7_OUT),
 	PINMUX_DATA(PTJ6_DATA, PTJ6_OUT),
 	PINMUX_DATA(PTJ5_DATA, PTJ5_OUT),
-	PINMUX_DATA(PTJ1_DATA, PTJ1_OUT, PTJ1_IN, PTJ1_IN_PU),
-	PINMUX_DATA(PTJ0_DATA, PTJ0_OUT, PTJ0_IN, PTJ0_IN_PU),
+	PINMUX_DATA(PTJ1_DATA, PTJ1_OUT, PTJ1_IN),
+	PINMUX_DATA(PTJ0_DATA, PTJ0_OUT, PTJ0_IN),
 
 	/* PTK */
-	PINMUX_DATA(PTK6_DATA, PTK6_OUT, PTK6_IN, PTK6_IN_PD),
-	PINMUX_DATA(PTK5_DATA, PTK5_OUT, PTK5_IN, PTK5_IN_PD),
-	PINMUX_DATA(PTK4_DATA, PTK4_OUT, PTK4_IN, PTK4_IN_PD),
-	PINMUX_DATA(PTK3_DATA, PTK3_OUT, PTK3_IN, PTK3_IN_PD),
-	PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_IN_PD),
+	PINMUX_DATA(PTK6_DATA, PTK6_OUT, PTK6_IN),
+	PINMUX_DATA(PTK5_DATA, PTK5_OUT, PTK5_IN),
+	PINMUX_DATA(PTK4_DATA, PTK4_OUT, PTK4_IN),
+	PINMUX_DATA(PTK3_DATA, PTK3_OUT, PTK3_IN),
+	PINMUX_DATA(PTK2_DATA, PTK2_IN),
 	PINMUX_DATA(PTK1_DATA, PTK1_OUT),
-	PINMUX_DATA(PTK0_DATA, PTK0_OUT, PTK0_IN, PTK0_IN_PD),
+	PINMUX_DATA(PTK0_DATA, PTK0_OUT, PTK0_IN),
 
 	/* PTL */
-	PINMUX_DATA(PTL7_DATA, PTL7_OUT, PTL7_IN, PTL7_IN_PD),
-	PINMUX_DATA(PTL6_DATA, PTL6_OUT, PTL6_IN, PTL6_IN_PD),
-	PINMUX_DATA(PTL5_DATA, PTL5_OUT, PTL5_IN, PTL5_IN_PD),
-	PINMUX_DATA(PTL4_DATA, PTL4_OUT, PTL4_IN, PTL4_IN_PD),
-	PINMUX_DATA(PTL3_DATA, PTL3_OUT, PTL3_IN, PTL3_IN_PD),
-	PINMUX_DATA(PTL2_DATA, PTL2_OUT, PTL2_IN, PTL2_IN_PD),
-	PINMUX_DATA(PTL1_DATA, PTL1_OUT, PTL1_IN, PTL1_IN_PD),
-	PINMUX_DATA(PTL0_DATA, PTL0_OUT, PTL0_IN, PTL0_IN_PD),
+	PINMUX_DATA(PTL7_DATA, PTL7_OUT, PTL7_IN),
+	PINMUX_DATA(PTL6_DATA, PTL6_OUT, PTL6_IN),
+	PINMUX_DATA(PTL5_DATA, PTL5_OUT, PTL5_IN),
+	PINMUX_DATA(PTL4_DATA, PTL4_OUT, PTL4_IN),
+	PINMUX_DATA(PTL3_DATA, PTL3_OUT, PTL3_IN),
+	PINMUX_DATA(PTL2_DATA, PTL2_OUT, PTL2_IN),
+	PINMUX_DATA(PTL1_DATA, PTL1_OUT, PTL1_IN),
+	PINMUX_DATA(PTL0_DATA, PTL0_OUT, PTL0_IN),
 
 	/* PTM */
-	PINMUX_DATA(PTM7_DATA, PTM7_OUT, PTM7_IN, PTM7_IN_PD),
-	PINMUX_DATA(PTM6_DATA, PTM6_OUT, PTM6_IN, PTM6_IN_PD),
-	PINMUX_DATA(PTM5_DATA, PTM5_OUT, PTM5_IN, PTM5_IN_PD),
-	PINMUX_DATA(PTM4_DATA, PTM4_OUT, PTM4_IN, PTM4_IN_PD),
-	PINMUX_DATA(PTM3_DATA, PTM3_OUT, PTM3_IN, PTM3_IN_PD),
-	PINMUX_DATA(PTM2_DATA, PTM2_OUT, PTM2_IN, PTM2_IN_PD),
-	PINMUX_DATA(PTM1_DATA, PTM1_OUT, PTM1_IN, PTM1_IN_PD),
-	PINMUX_DATA(PTM0_DATA, PTM0_OUT, PTM0_IN, PTM0_IN_PD),
+	PINMUX_DATA(PTM7_DATA, PTM7_OUT, PTM7_IN),
+	PINMUX_DATA(PTM6_DATA, PTM6_OUT, PTM6_IN),
+	PINMUX_DATA(PTM5_DATA, PTM5_OUT, PTM5_IN),
+	PINMUX_DATA(PTM4_DATA, PTM4_OUT, PTM4_IN),
+	PINMUX_DATA(PTM3_DATA, PTM3_OUT, PTM3_IN),
+	PINMUX_DATA(PTM2_DATA, PTM2_OUT, PTM2_IN),
+	PINMUX_DATA(PTM1_DATA, PTM1_OUT, PTM1_IN),
+	PINMUX_DATA(PTM0_DATA, PTM0_OUT, PTM0_IN),
 
 	/* PTN */
 	PINMUX_DATA(PTN7_DATA, PTN7_OUT, PTN7_IN),
@@ -417,80 +384,80 @@ static const pinmux_enum_t pinmux_data[] = {
 
 	/* PTQ */
 	PINMUX_DATA(PTQ6_DATA, PTQ6_OUT),
-	PINMUX_DATA(PTQ5_DATA, PTQ5_OUT, PTQ5_IN, PTQ5_IN_PD),
-	PINMUX_DATA(PTQ4_DATA, PTQ4_OUT, PTQ4_IN, PTQ4_IN_PD),
-	PINMUX_DATA(PTQ3_DATA, PTQ3_OUT, PTQ3_IN, PTQ3_IN_PD),
-	PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_IN_PD),
+	PINMUX_DATA(PTQ5_DATA, PTQ5_OUT, PTQ5_IN),
+	PINMUX_DATA(PTQ4_DATA, PTQ4_OUT, PTQ4_IN),
+	PINMUX_DATA(PTQ3_DATA, PTQ3_OUT, PTQ3_IN),
+	PINMUX_DATA(PTQ2_DATA, PTQ2_IN),
 	PINMUX_DATA(PTQ1_DATA, PTQ1_OUT),
-	PINMUX_DATA(PTQ0_DATA, PTQ0_OUT, PTQ0_IN, PTQ0_IN_PU),
+	PINMUX_DATA(PTQ0_DATA, PTQ0_OUT, PTQ0_IN),
 
 	/* PTR */
 	PINMUX_DATA(PTR4_DATA, PTR4_OUT),
 	PINMUX_DATA(PTR3_DATA, PTR3_OUT),
-	PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_IN_PU),
+	PINMUX_DATA(PTR2_DATA, PTR2_IN),
 	PINMUX_DATA(PTR1_DATA, PTR1_OUT),
 	PINMUX_DATA(PTR0_DATA, PTR0_OUT),
 
 	/* PTS */
-	PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_IN_PD),
+	PINMUX_DATA(PTS4_DATA, PTS4_IN),
 	PINMUX_DATA(PTS3_DATA, PTS3_OUT),
-	PINMUX_DATA(PTS2_DATA, PTS2_OUT, PTS2_IN, PTS2_IN_PD),
-	PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_IN_PD),
+	PINMUX_DATA(PTS2_DATA, PTS2_OUT, PTS2_IN),
+	PINMUX_DATA(PTS1_DATA, PTS1_IN),
 	PINMUX_DATA(PTS0_DATA, PTS0_OUT),
 
 	/* PTT */
-	PINMUX_DATA(PTT4_DATA, PTT4_OUT, PTT4_IN, PTT4_IN_PD),
-	PINMUX_DATA(PTT3_DATA, PTT3_OUT, PTT3_IN, PTT3_IN_PD),
-	PINMUX_DATA(PTT2_DATA, PTT2_OUT, PTT2_IN, PTT2_IN_PD),
-	PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_IN_PD),
+	PINMUX_DATA(PTT4_DATA, PTT4_OUT, PTT4_IN),
+	PINMUX_DATA(PTT3_DATA, PTT3_OUT, PTT3_IN),
+	PINMUX_DATA(PTT2_DATA, PTT2_OUT, PTT2_IN),
+	PINMUX_DATA(PTT1_DATA, PTT1_IN),
 	PINMUX_DATA(PTT0_DATA, PTT0_OUT),
 
 	/* PTU */
-	PINMUX_DATA(PTU4_DATA, PTU4_OUT, PTU4_IN, PTU4_IN_PD),
-	PINMUX_DATA(PTU3_DATA, PTU3_OUT, PTU3_IN, PTU3_IN_PD),
-	PINMUX_DATA(PTU2_DATA, PTU2_OUT, PTU2_IN, PTU2_IN_PD),
-	PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_IN_PD),
-	PINMUX_DATA(PTU0_DATA, PTU0_OUT, PTU0_IN, PTU0_IN_PD),
+	PINMUX_DATA(PTU4_DATA, PTU4_OUT, PTU4_IN),
+	PINMUX_DATA(PTU3_DATA, PTU3_OUT, PTU3_IN),
+	PINMUX_DATA(PTU2_DATA, PTU2_OUT, PTU2_IN),
+	PINMUX_DATA(PTU1_DATA, PTU1_IN),
+	PINMUX_DATA(PTU0_DATA, PTU0_OUT, PTU0_IN),
 
 	/* PTV */
-	PINMUX_DATA(PTV4_DATA, PTV4_OUT, PTV4_IN, PTV4_IN_PD),
-	PINMUX_DATA(PTV3_DATA, PTV3_OUT, PTV3_IN, PTV3_IN_PD),
-	PINMUX_DATA(PTV2_DATA, PTV2_OUT, PTV2_IN, PTV2_IN_PD),
-	PINMUX_DATA(PTV1_DATA, PTV1_OUT, PTV1_IN, PTV1_IN_PD),
-	PINMUX_DATA(PTV0_DATA, PTV0_OUT, PTV0_IN, PTV0_IN_PD),
+	PINMUX_DATA(PTV4_DATA, PTV4_OUT, PTV4_IN),
+	PINMUX_DATA(PTV3_DATA, PTV3_OUT, PTV3_IN),
+	PINMUX_DATA(PTV2_DATA, PTV2_OUT, PTV2_IN),
+	PINMUX_DATA(PTV1_DATA, PTV1_OUT, PTV1_IN),
+	PINMUX_DATA(PTV0_DATA, PTV0_OUT, PTV0_IN),
 
 	/* PTW */
-	PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_IN_PD),
+	PINMUX_DATA(PTW6_DATA, PTW6_IN),
 	PINMUX_DATA(PTW5_DATA, PTW5_OUT),
-	PINMUX_DATA(PTW4_DATA, PTW4_OUT, PTW4_IN, PTW4_IN_PD),
-	PINMUX_DATA(PTW3_DATA, PTW3_OUT, PTW3_IN, PTW3_IN_PD),
-	PINMUX_DATA(PTW2_DATA, PTW2_OUT, PTW2_IN, PTW2_IN_PD),
-	PINMUX_DATA(PTW1_DATA, PTW1_OUT, PTW1_IN, PTW1_IN_PD),
-	PINMUX_DATA(PTW0_DATA, PTW0_OUT, PTW0_IN, PTW0_IN_PD),
+	PINMUX_DATA(PTW4_DATA, PTW4_OUT, PTW4_IN),
+	PINMUX_DATA(PTW3_DATA, PTW3_OUT, PTW3_IN),
+	PINMUX_DATA(PTW2_DATA, PTW2_OUT, PTW2_IN),
+	PINMUX_DATA(PTW1_DATA, PTW1_OUT, PTW1_IN),
+	PINMUX_DATA(PTW0_DATA, PTW0_OUT, PTW0_IN),
 
 	/* PTX */
-	PINMUX_DATA(PTX6_DATA, PTX6_OUT, PTX6_IN, PTX6_IN_PD),
-	PINMUX_DATA(PTX5_DATA, PTX5_OUT, PTX5_IN, PTX5_IN_PD),
-	PINMUX_DATA(PTX4_DATA, PTX4_OUT, PTX4_IN, PTX4_IN_PD),
-	PINMUX_DATA(PTX3_DATA, PTX3_OUT, PTX3_IN, PTX3_IN_PD),
-	PINMUX_DATA(PTX2_DATA, PTX2_OUT, PTX2_IN, PTX2_IN_PD),
-	PINMUX_DATA(PTX1_DATA, PTX1_OUT, PTX1_IN, PTX1_IN_PD),
-	PINMUX_DATA(PTX0_DATA, PTX0_OUT, PTX0_IN, PTX0_IN_PD),
+	PINMUX_DATA(PTX6_DATA, PTX6_OUT, PTX6_IN),
+	PINMUX_DATA(PTX5_DATA, PTX5_OUT, PTX5_IN),
+	PINMUX_DATA(PTX4_DATA, PTX4_OUT, PTX4_IN),
+	PINMUX_DATA(PTX3_DATA, PTX3_OUT, PTX3_IN),
+	PINMUX_DATA(PTX2_DATA, PTX2_OUT, PTX2_IN),
+	PINMUX_DATA(PTX1_DATA, PTX1_OUT, PTX1_IN),
+	PINMUX_DATA(PTX0_DATA, PTX0_OUT, PTX0_IN),
 
 	/* PTY */
-	PINMUX_DATA(PTY5_DATA, PTY5_OUT, PTY5_IN, PTY5_IN_PU),
-	PINMUX_DATA(PTY4_DATA, PTY4_OUT, PTY4_IN, PTY4_IN_PU),
-	PINMUX_DATA(PTY3_DATA, PTY3_OUT, PTY3_IN, PTY3_IN_PU),
-	PINMUX_DATA(PTY2_DATA, PTY2_OUT, PTY2_IN, PTY2_IN_PU),
+	PINMUX_DATA(PTY5_DATA, PTY5_OUT, PTY5_IN),
+	PINMUX_DATA(PTY4_DATA, PTY4_OUT, PTY4_IN),
+	PINMUX_DATA(PTY3_DATA, PTY3_OUT, PTY3_IN),
+	PINMUX_DATA(PTY2_DATA, PTY2_OUT, PTY2_IN),
 	PINMUX_DATA(PTY1_DATA, PTY1_OUT),
-	PINMUX_DATA(PTY0_DATA, PTY0_OUT, PTY0_IN, PTY0_IN_PU),
+	PINMUX_DATA(PTY0_DATA, PTY0_OUT, PTY0_IN),
 
 	/* PTZ */
-	PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_IN_PU),
-	PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_IN_PU),
-	PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_IN_PU),
-	PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_IN_PU),
-	PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_IN_PU),
+	PINMUX_DATA(PTZ5_DATA, PTZ5_IN),
+	PINMUX_DATA(PTZ4_DATA, PTZ4_IN),
+	PINMUX_DATA(PTZ3_DATA, PTZ3_IN),
+	PINMUX_DATA(PTZ2_DATA, PTZ2_IN),
+	PINMUX_DATA(PTZ1_DATA, PTZ1_IN),
 
 	/* SCIF0 */
 	PINMUX_DATA(SCIF0_TXD_MARK, SCIF0_TXD),
@@ -789,199 +756,199 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
-	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
-	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
-	PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
-	PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
-	PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
-	PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
-	PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
-	PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+	PINMUX_GPIO(PTA7),
+	PINMUX_GPIO(PTA6),
+	PINMUX_GPIO(PTA5),
+	PINMUX_GPIO(PTA4),
+	PINMUX_GPIO(PTA3),
+	PINMUX_GPIO(PTA2),
+	PINMUX_GPIO(PTA1),
+	PINMUX_GPIO(PTA0),
 
 	/* PTB */
-	PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
-	PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
-	PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
-	PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
-	PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
-	PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
-	PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
-	PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+	PINMUX_GPIO(PTB7),
+	PINMUX_GPIO(PTB6),
+	PINMUX_GPIO(PTB5),
+	PINMUX_GPIO(PTB4),
+	PINMUX_GPIO(PTB3),
+	PINMUX_GPIO(PTB2),
+	PINMUX_GPIO(PTB1),
+	PINMUX_GPIO(PTB0),
 
 	/* PTC */
-	PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
-	PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
-	PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
-	PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
-	PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
-	PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+	PINMUX_GPIO(PTC7),
+	PINMUX_GPIO(PTC5),
+	PINMUX_GPIO(PTC4),
+	PINMUX_GPIO(PTC3),
+	PINMUX_GPIO(PTC2),
+	PINMUX_GPIO(PTC0),
 
 	/* PTD */
-	PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
-	PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
-	PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
-	PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
-	PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
-	PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
-	PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
-	PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+	PINMUX_GPIO(PTD7),
+	PINMUX_GPIO(PTD6),
+	PINMUX_GPIO(PTD5),
+	PINMUX_GPIO(PTD4),
+	PINMUX_GPIO(PTD3),
+	PINMUX_GPIO(PTD2),
+	PINMUX_GPIO(PTD1),
+	PINMUX_GPIO(PTD0),
 
 	/* PTE */
-	PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
-	PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
-	PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
-	PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
-	PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
-	PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+	PINMUX_GPIO(PTE7),
+	PINMUX_GPIO(PTE6),
+	PINMUX_GPIO(PTE5),
+	PINMUX_GPIO(PTE4),
+	PINMUX_GPIO(PTE1),
+	PINMUX_GPIO(PTE0),
 
 	/* PTF */
-	PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
-	PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
-	PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
-	PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
-	PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
-	PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
-	PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+	PINMUX_GPIO(PTF6),
+	PINMUX_GPIO(PTF5),
+	PINMUX_GPIO(PTF4),
+	PINMUX_GPIO(PTF3),
+	PINMUX_GPIO(PTF2),
+	PINMUX_GPIO(PTF1),
+	PINMUX_GPIO(PTF0),
 
 	/* PTG */
-	PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
-	PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
-	PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
-	PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
-	PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+	PINMUX_GPIO(PTG4),
+	PINMUX_GPIO(PTG3),
+	PINMUX_GPIO(PTG2),
+	PINMUX_GPIO(PTG1),
+	PINMUX_GPIO(PTG0),
 
 	/* PTH */
-	PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
-	PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
-	PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
-	PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
-	PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
-	PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
-	PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
-	PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+	PINMUX_GPIO(PTH7),
+	PINMUX_GPIO(PTH6),
+	PINMUX_GPIO(PTH5),
+	PINMUX_GPIO(PTH4),
+	PINMUX_GPIO(PTH3),
+	PINMUX_GPIO(PTH2),
+	PINMUX_GPIO(PTH1),
+	PINMUX_GPIO(PTH0),
 
 	/* PTJ */
-	PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
-	PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
-	PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
-	PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
-	PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+	PINMUX_GPIO(PTJ7),
+	PINMUX_GPIO(PTJ6),
+	PINMUX_GPIO(PTJ5),
+	PINMUX_GPIO(PTJ1),
+	PINMUX_GPIO(PTJ0),
 
 	/* PTK */
-	PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
-	PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
-	PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
-	PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
-	PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
-	PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
-	PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+	PINMUX_GPIO(PTK6),
+	PINMUX_GPIO(PTK5),
+	PINMUX_GPIO(PTK4),
+	PINMUX_GPIO(PTK3),
+	PINMUX_GPIO(PTK2),
+	PINMUX_GPIO(PTK1),
+	PINMUX_GPIO(PTK0),
 
 	/* PTL */
-	PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
-	PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
-	PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
-	PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
-	PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
-	PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
-	PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
-	PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+	PINMUX_GPIO(PTL7),
+	PINMUX_GPIO(PTL6),
+	PINMUX_GPIO(PTL5),
+	PINMUX_GPIO(PTL4),
+	PINMUX_GPIO(PTL3),
+	PINMUX_GPIO(PTL2),
+	PINMUX_GPIO(PTL1),
+	PINMUX_GPIO(PTL0),
 
 	/* PTM */
-	PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
-	PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
-	PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
-	PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
-	PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
-	PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
-	PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
-	PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+	PINMUX_GPIO(PTM7),
+	PINMUX_GPIO(PTM6),
+	PINMUX_GPIO(PTM5),
+	PINMUX_GPIO(PTM4),
+	PINMUX_GPIO(PTM3),
+	PINMUX_GPIO(PTM2),
+	PINMUX_GPIO(PTM1),
+	PINMUX_GPIO(PTM0),
 
 	/* PTN */
-	PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
-	PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
-	PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
-	PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
-	PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
-	PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
-	PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
-	PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+	PINMUX_GPIO(PTN7),
+	PINMUX_GPIO(PTN6),
+	PINMUX_GPIO(PTN5),
+	PINMUX_GPIO(PTN4),
+	PINMUX_GPIO(PTN3),
+	PINMUX_GPIO(PTN2),
+	PINMUX_GPIO(PTN1),
+	PINMUX_GPIO(PTN0),
 
 	/* PTQ */
-	PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
-	PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
-	PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
-	PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
-	PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
-	PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
-	PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+	PINMUX_GPIO(PTQ6),
+	PINMUX_GPIO(PTQ5),
+	PINMUX_GPIO(PTQ4),
+	PINMUX_GPIO(PTQ3),
+	PINMUX_GPIO(PTQ2),
+	PINMUX_GPIO(PTQ1),
+	PINMUX_GPIO(PTQ0),
 
 	/* PTR */
-	PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
-	PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
-	PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
-	PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
-	PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+	PINMUX_GPIO(PTR4),
+	PINMUX_GPIO(PTR3),
+	PINMUX_GPIO(PTR2),
+	PINMUX_GPIO(PTR1),
+	PINMUX_GPIO(PTR0),
 
 	/* PTS */
-	PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
-	PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
-	PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
-	PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
-	PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+	PINMUX_GPIO(PTS4),
+	PINMUX_GPIO(PTS3),
+	PINMUX_GPIO(PTS2),
+	PINMUX_GPIO(PTS1),
+	PINMUX_GPIO(PTS0),
 
 	/* PTT */
-	PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
-	PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
-	PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
-	PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
-	PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+	PINMUX_GPIO(PTT4),
+	PINMUX_GPIO(PTT3),
+	PINMUX_GPIO(PTT2),
+	PINMUX_GPIO(PTT1),
+	PINMUX_GPIO(PTT0),
 
 	/* PTU */
-	PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
-	PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
-	PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
-	PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
-	PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+	PINMUX_GPIO(PTU4),
+	PINMUX_GPIO(PTU3),
+	PINMUX_GPIO(PTU2),
+	PINMUX_GPIO(PTU1),
+	PINMUX_GPIO(PTU0),
 
 	/* PTV */
-	PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
-	PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
-	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
-	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
-	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+	PINMUX_GPIO(PTV4),
+	PINMUX_GPIO(PTV3),
+	PINMUX_GPIO(PTV2),
+	PINMUX_GPIO(PTV1),
+	PINMUX_GPIO(PTV0),
 
 	/* PTW */
-	PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
-	PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
-	PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
-	PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
-	PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
-	PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
-	PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+	PINMUX_GPIO(PTW6),
+	PINMUX_GPIO(PTW5),
+	PINMUX_GPIO(PTW4),
+	PINMUX_GPIO(PTW3),
+	PINMUX_GPIO(PTW2),
+	PINMUX_GPIO(PTW1),
+	PINMUX_GPIO(PTW0),
 
 	/* PTX */
-	PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
-	PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
-	PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
-	PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
-	PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
-	PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
-	PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+	PINMUX_GPIO(PTX6),
+	PINMUX_GPIO(PTX5),
+	PINMUX_GPIO(PTX4),
+	PINMUX_GPIO(PTX3),
+	PINMUX_GPIO(PTX2),
+	PINMUX_GPIO(PTX1),
+	PINMUX_GPIO(PTX0),
 
 	/* PTY */
-	PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
-	PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
-	PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
-	PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
-	PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
-	PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+	PINMUX_GPIO(PTY5),
+	PINMUX_GPIO(PTY4),
+	PINMUX_GPIO(PTY3),
+	PINMUX_GPIO(PTY2),
+	PINMUX_GPIO(PTY1),
+	PINMUX_GPIO(PTY0),
 
 	/* PTZ */
-	PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
-	PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
-	PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
-	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
-	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+	PINMUX_GPIO(PTZ5),
+	PINMUX_GPIO(PTZ4),
+	PINMUX_GPIO(PTZ3),
+	PINMUX_GPIO(PTZ2),
+	PINMUX_GPIO(PTZ1),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -1270,14 +1237,14 @@ static const struct pinmux_func pinmux_func_gpios[] = {
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
-		VIO_D7_SCIF1_SCK, PTA7_OUT, PTA7_IN_PD, PTA7_IN,
-		VIO_D6_SCIF1_RXD, 0, PTA6_IN_PD, PTA6_IN,
-		VIO_D5_SCIF1_TXD, PTA5_OUT, PTA5_IN_PD, PTA5_IN,
-		VIO_D4, 0, PTA4_IN_PD, PTA4_IN,
-		VIO_D3, 0, PTA3_IN_PD, PTA3_IN,
-		VIO_D2, 0, PTA2_IN_PD, PTA2_IN,
-		VIO_D1, 0, PTA1_IN_PD, PTA1_IN,
-		VIO_D0_LCDLCLK, 0, PTA0_IN_PD, PTA0_IN }
+		VIO_D7_SCIF1_SCK, PTA7_OUT, 0, PTA7_IN,
+		VIO_D6_SCIF1_RXD, 0, 0, PTA6_IN,
+		VIO_D5_SCIF1_TXD, PTA5_OUT, 0, PTA5_IN,
+		VIO_D4, 0, 0, PTA4_IN,
+		VIO_D3, 0, 0, PTA3_IN,
+		VIO_D2, 0, 0, PTA2_IN,
+		VIO_D1, 0, 0, PTA1_IN,
+		VIO_D0_LCDLCLK, 0, 0, PTA0_IN }
 	},
 	{ PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
 		HPD55, PTB7_OUT, 0, PTB7_IN,
@@ -1290,9 +1257,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		HPD48, PTB0_OUT, 0, PTB0_IN }
 	},
 	{ PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
-		0, 0, PTC7_IN_PU, PTC7_IN,
+		0, 0, 0, PTC7_IN,
 		0, 0, 0, 0,
-		IOIS16, 0, PTC5_IN_PU, PTC5_IN,
+		IOIS16, 0, 0, PTC5_IN,
 		HPDQM7, PTC4_OUT, 0, PTC4_IN,
 		HPDQM6, PTC3_OUT, 0, PTC3_IN,
 		HPDQM5, PTC2_OUT, 0, PTC2_IN,
@@ -1300,33 +1267,33 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		HPDQM4, PTC0_OUT, 0, PTC0_IN }
 	},
 	{ PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
-		SDHICD, 0, PTD7_IN_PU, PTD7_IN,
-		SDHIWP, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
-		SDHID3, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
-		IRQ2_SDHID2, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
-		SDHID1, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
-		SDHID0, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
-		SDHICMD, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
+		SDHICD, 0, 0, PTD7_IN,
+		SDHIWP, PTD6_OUT, 0, PTD6_IN,
+		SDHID3, PTD5_OUT, 0, PTD5_IN,
+		IRQ2_SDHID2, PTD4_OUT, 0, PTD4_IN,
+		SDHID1, PTD3_OUT, 0, PTD3_IN,
+		SDHID0, PTD2_OUT, 0, PTD2_IN,
+		SDHICMD, PTD1_OUT, 0, PTD1_IN,
 		SDHICLK, PTD0_OUT, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
-		A25, PTE7_OUT, PTE7_IN_PD, PTE7_IN,
-		A24, PTE6_OUT, PTE6_IN_PD, PTE6_IN,
-		A23, PTE5_OUT, PTE5_IN_PD, PTE5_IN,
-		A22, PTE4_OUT, PTE4_IN_PD, PTE4_IN,
+		A25, PTE7_OUT, 0, PTE7_IN,
+		A24, PTE6_OUT, 0, PTE6_IN,
+		A23, PTE5_OUT, 0, PTE5_IN,
+		A22, PTE4_OUT, 0, PTE4_IN,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		IRQ5, PTE1_OUT, PTE1_IN_PD, PTE1_IN,
-		IRQ4_BS, PTE0_OUT, PTE0_IN_PD, PTE0_IN }
+		IRQ5, PTE1_OUT, 0, PTE1_IN,
+		IRQ4_BS, PTE0_OUT, 0, PTE0_IN }
 	},
 	{ PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
 		0, 0, 0, 0,
-		PTF6, PTF6_OUT, PTF6_IN_PD, PTF6_IN,
-		SIOSCK_SIUBOBT, PTF5_OUT, PTF5_IN_PD, PTF5_IN,
-		SIOSTRB1_SIUBOLR, PTF4_OUT, PTF4_IN_PD, PTF4_IN,
-		SIOSTRB0_SIUBIBT, PTF3_OUT, PTF3_IN_PD, PTF3_IN,
-		SIOD_SIUBILR, PTF2_OUT, PTF2_IN_PD, PTF2_IN,
-		SIORXD_SIUBISLD, 0, PTF1_IN_PD, PTF1_IN,
+		PTF6, PTF6_OUT, 0, PTF6_IN,
+		SIOSCK_SIUBOBT, PTF5_OUT, 0, PTF5_IN,
+		SIOSTRB1_SIUBOLR, PTF4_OUT, 0, PTF4_IN,
+		SIOSTRB0_SIUBIBT, PTF3_OUT, 0, PTF3_IN,
+		SIOD_SIUBILR, PTF2_OUT, 0, PTF2_IN,
+		SIORXD_SIUBISLD, 0, 0, PTF1_IN,
 		SIOTXD_SIUBOSLD, PTF0_OUT, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
@@ -1341,13 +1308,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	},
 	{ PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
 		LCDVCPWC_LCDVCPWC2, PTH7_OUT, 0, 0,
-		LCDVSYN2_DACK, PTH6_OUT, PTH6_IN_PD, PTH6_IN,
-		LCDVSYN, PTH5_OUT, PTH5_IN_PD, PTH5_IN,
+		LCDVSYN2_DACK, PTH6_OUT, 0, PTH6_IN,
+		LCDVSYN, PTH5_OUT, 0, PTH5_IN,
 		LCDDISP_LCDRS, PTH4_OUT, 0, 0,
 		LCDHSYN_LCDCS, PTH3_OUT, 0, 0,
 		LCDDON_LCDDON2, PTH2_OUT, 0, 0,
-		LCDD17_DV_HSYNC, PTH1_OUT, PTH1_IN_PD, PTH1_IN,
-		LCDD16_DV_VSYNC, PTH0_OUT, PTH0_IN_PD, PTH0_IN }
+		LCDD17_DV_HSYNC, PTH1_OUT, 0, PTH1_IN,
+		LCDD16_DV_VSYNC, PTH0_OUT, 0, PTH0_IN }
 	},
 	{ PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
 		STATUS0, PTJ7_OUT, 0, 0,
@@ -1356,38 +1323,38 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		IRQ1, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
-		IRQ0, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+		IRQ1, PTJ1_OUT, 0, PTJ1_IN,
+		IRQ0, PTJ0_OUT, 0, PTJ0_IN }
 	},
 	{ PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
 		0, 0, 0, 0,
-		SIUAILR_SIOF1_SS2, PTK6_OUT, PTK6_IN_PD, PTK6_IN,
-		SIUAIBT_SIOF1_SS1, PTK5_OUT, PTK5_IN_PD, PTK5_IN,
-		SIUAOLR_SIOF1_SYNC, PTK4_OUT, PTK4_IN_PD, PTK4_IN,
-		SIUAOBT_SIOF1_SCK, PTK3_OUT, PTK3_IN_PD, PTK3_IN,
-		SIUAISLD_SIOF1_RXD, 0, PTK2_IN_PD, PTK2_IN,
+		SIUAILR_SIOF1_SS2, PTK6_OUT, 0, PTK6_IN,
+		SIUAIBT_SIOF1_SS1, PTK5_OUT, 0, PTK5_IN,
+		SIUAOLR_SIOF1_SYNC, PTK4_OUT, 0, PTK4_IN,
+		SIUAOBT_SIOF1_SCK, PTK3_OUT, 0, PTK3_IN,
+		SIUAISLD_SIOF1_RXD, 0, 0, PTK2_IN,
 		SIUAOSLD_SIOF1_TXD, PTK1_OUT, 0, 0,
-		PTK0, PTK0_OUT, PTK0_IN_PD, PTK0_IN }
+		PTK0, PTK0_OUT, 0, PTK0_IN }
 	},
 	{ PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
-		LCDD15_DV_D15, PTL7_OUT, PTL7_IN_PD, PTL7_IN,
-		LCDD14_DV_D14, PTL6_OUT, PTL6_IN_PD, PTL6_IN,
-		LCDD13_DV_D13, PTL5_OUT, PTL5_IN_PD, PTL5_IN,
-		LCDD12_DV_D12, PTL4_OUT, PTL4_IN_PD, PTL4_IN,
-		LCDD11_DV_D11, PTL3_OUT, PTL3_IN_PD, PTL3_IN,
-		LCDD10_DV_D10, PTL2_OUT, PTL2_IN_PD, PTL2_IN,
-		LCDD9_DV_D9, PTL1_OUT, PTL1_IN_PD, PTL1_IN,
-		LCDD8_DV_D8, PTL0_OUT, PTL0_IN_PD, PTL0_IN }
+		LCDD15_DV_D15, PTL7_OUT, 0, PTL7_IN,
+		LCDD14_DV_D14, PTL6_OUT, 0, PTL6_IN,
+		LCDD13_DV_D13, PTL5_OUT, 0, PTL5_IN,
+		LCDD12_DV_D12, PTL4_OUT, 0, PTL4_IN,
+		LCDD11_DV_D11, PTL3_OUT, 0, PTL3_IN,
+		LCDD10_DV_D10, PTL2_OUT, 0, PTL2_IN,
+		LCDD9_DV_D9, PTL1_OUT, 0, PTL1_IN,
+		LCDD8_DV_D8, PTL0_OUT, 0, PTL0_IN }
 	},
 	{ PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
-		LCDD7_DV_D7, PTM7_OUT, PTM7_IN_PD, PTM7_IN,
-		LCDD6_DV_D6, PTM6_OUT, PTM6_IN_PD, PTM6_IN,
-		LCDD5_DV_D5, PTM5_OUT, PTM5_IN_PD, PTM5_IN,
-		LCDD4_DV_D4, PTM4_OUT, PTM4_IN_PD, PTM4_IN,
-		LCDD3_DV_D3, PTM3_OUT, PTM3_IN_PD, PTM3_IN,
-		LCDD2_DV_D2, PTM2_OUT, PTM2_IN_PD, PTM2_IN,
-		LCDD1_DV_D1, PTM1_OUT, PTM1_IN_PD, PTM1_IN,
-		LCDD0_DV_D0, PTM0_OUT, PTM0_IN_PD, PTM0_IN }
+		LCDD7_DV_D7, PTM7_OUT, 0, PTM7_IN,
+		LCDD6_DV_D6, PTM6_OUT, 0, PTM6_IN,
+		LCDD5_DV_D5, PTM5_OUT, 0, PTM5_IN,
+		LCDD4_DV_D4, PTM4_OUT, 0, PTM4_IN,
+		LCDD3_DV_D3, PTM3_OUT, 0, PTM3_IN,
+		LCDD2_DV_D2, PTM2_OUT, 0, PTM2_IN,
+		LCDD1_DV_D1, PTM1_OUT, 0, PTM1_IN,
+		LCDD0_DV_D0, PTM0_OUT, 0, PTM0_IN }
 	},
 	{ PINMUX_CFG_REG("PNCR", 0xa4050118, 16, 2) {
 		HPD63, PTN7_OUT, 0, PTN7_IN,
@@ -1402,12 +1369,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2) {
 		0, 0, 0, 0,
 		SIOF0_SS2_SIM_RST, PTQ6_OUT, 0, 0,
-		SIOF0_SS1_TS_SPSYNC, PTQ5_OUT, PTQ5_IN_PD, PTQ5_IN,
-		SIOF0_SYNC_TS_SDEN, PTQ4_OUT, PTQ4_IN_PD, PTQ4_IN,
-		SIOF0_SCK_TS_SCK, PTQ3_OUT, PTQ3_IN_PD, PTQ3_IN,
-		PTQ2, 0, PTQ2_IN_PD, PTQ2_IN,
+		SIOF0_SS1_TS_SPSYNC, PTQ5_OUT, 0, PTQ5_IN,
+		SIOF0_SYNC_TS_SDEN, PTQ4_OUT, 0, PTQ4_IN,
+		SIOF0_SCK_TS_SCK, PTQ3_OUT, 0, PTQ3_IN,
+		PTQ2, 0, 0, PTQ2_IN,
 		PTQ1, PTQ1_OUT, 0, 0,
-		PTQ0, PTQ0_OUT, PTQ0_IN_PU, PTQ0_IN }
+		PTQ0, PTQ0_OUT, 0, PTQ0_IN }
 	},
 	{ PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2) {
 		0, 0, 0, 0,
@@ -1415,7 +1382,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0, 0, 0,
 		LCDRD, PTR4_OUT, 0, 0,
 		CS6B_CE1B_LCDCS2, PTR3_OUT, 0, 0,
-		WAIT, 0, PTR2_IN_PU, PTR2_IN,
+		WAIT, 0, 0, PTR2_IN,
 		LCDDCK_LCDWR, PTR1_OUT, 0, 0,
 		LCDVEPWC_LCDVEPWC2, PTR0_OUT, 0, 0 }
 	},
@@ -1423,80 +1390,80 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		SCIF0_CTS_SIUAISPD, 0, PTS4_IN_PD, PTS4_IN,
+		SCIF0_CTS_SIUAISPD, 0, 0, PTS4_IN,
 		SCIF0_RTS_SIUAOSPD, PTS3_OUT, 0, 0,
-		SCIF0_SCK_TPUTO, PTS2_OUT, PTS2_IN_PD, PTS2_IN,
-		SCIF0_RXD, 0, PTS1_IN_PD, PTS1_IN,
+		SCIF0_SCK_TPUTO, PTS2_OUT, 0, PTS2_IN,
+		SCIF0_RXD, 0, 0, PTS1_IN,
 		SCIF0_TXD, PTS0_OUT, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		FOE_VIO_VD2, PTT4_OUT, PTT4_IN_PD, PTT4_IN,
-		FWE, PTT3_OUT, PTT3_IN_PD, PTT3_IN,
-		FSC, PTT2_OUT, PTT2_IN_PD, PTT2_IN,
-		DREQ0, 0, PTT1_IN_PD, PTT1_IN,
+		FOE_VIO_VD2, PTT4_OUT, 0, PTT4_IN,
+		FWE, PTT3_OUT, 0, PTT3_IN,
+		FSC, PTT2_OUT, 0, PTT2_IN,
+		DREQ0, 0, 0, PTT1_IN,
 		FCDE, PTT0_OUT, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		NAF2_VIO_D10, PTU4_OUT, PTU4_IN_PD, PTU4_IN,
-		NAF1_VIO_D9, PTU3_OUT, PTU3_IN_PD, PTU3_IN,
-		NAF0_VIO_D8, PTU2_OUT, PTU2_IN_PD, PTU2_IN,
-		FRB_VIO_CLK2, 0, PTU1_IN_PD, PTU1_IN,
-		FCE_VIO_HD2, PTU0_OUT, PTU0_IN_PD, PTU0_IN }
+		NAF2_VIO_D10, PTU4_OUT, 0, PTU4_IN,
+		NAF1_VIO_D9, PTU3_OUT, 0, PTU3_IN,
+		NAF0_VIO_D8, PTU2_OUT, 0, PTU2_IN,
+		FRB_VIO_CLK2, 0, 0, PTU1_IN,
+		FCE_VIO_HD2, PTU0_OUT, 0, PTU0_IN }
 	},
 	{ PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		NAF7_VIO_D15, PTV4_OUT, PTV4_IN_PD, PTV4_IN,
-		NAF6_VIO_D14, PTV3_OUT, PTV3_IN_PD, PTV3_IN,
-		NAF5_VIO_D13, PTV2_OUT, PTV2_IN_PD, PTV2_IN,
-		NAF4_VIO_D12, PTV1_OUT, PTV1_IN_PD, PTV1_IN,
-		NAF3_VIO_D11, PTV0_OUT, PTV0_IN_PD, PTV0_IN }
+		NAF7_VIO_D15, PTV4_OUT, 0, PTV4_IN,
+		NAF6_VIO_D14, PTV3_OUT, 0, PTV3_IN,
+		NAF5_VIO_D13, PTV2_OUT, 0, PTV2_IN,
+		NAF4_VIO_D12, PTV1_OUT, 0, PTV1_IN,
+		NAF3_VIO_D11, PTV0_OUT, 0, PTV0_IN }
 	},
 	{ PINMUX_CFG_REG("PWCR", 0xa4050146, 16, 2) {
 		0, 0, 0, 0,
-		VIO_FLD_SCIF2_CTS, 0, PTW6_IN_PD, PTW6_IN,
+		VIO_FLD_SCIF2_CTS, 0, 0, PTW6_IN,
 		VIO_CKO_SCIF2_RTS, PTW5_OUT, 0, 0,
-		VIO_STEX_SCIF2_SCK, PTW4_OUT, PTW4_IN_PD, PTW4_IN,
-		VIO_STEM_SCIF2_TXD, PTW3_OUT, PTW3_IN_PD, PTW3_IN,
-		VIO_HD_SCIF2_RXD, PTW2_OUT, PTW2_IN_PD, PTW2_IN,
-		VIO_VD_SCIF1_CTS, PTW1_OUT, PTW1_IN_PD, PTW1_IN,
-		VIO_CLK_SCIF1_RTS, PTW0_OUT, PTW0_IN_PD, PTW0_IN }
+		VIO_STEX_SCIF2_SCK, PTW4_OUT, 0, PTW4_IN,
+		VIO_STEM_SCIF2_TXD, PTW3_OUT, 0, PTW3_IN,
+		VIO_HD_SCIF2_RXD, PTW2_OUT, 0, PTW2_IN,
+		VIO_VD_SCIF1_CTS, PTW1_OUT, 0, PTW1_IN,
+		VIO_CLK_SCIF1_RTS, PTW0_OUT, 0, PTW0_IN }
 	},
 	{ PINMUX_CFG_REG("PXCR", 0xa4050148, 16, 2) {
 		0, 0, 0, 0,
-		CS6A_CE2B, PTX6_OUT, PTX6_IN_PU, PTX6_IN,
-		LCDD23, PTX5_OUT, PTX5_IN_PD, PTX5_IN,
-		LCDD22, PTX4_OUT, PTX4_IN_PD, PTX4_IN,
-		LCDD21, PTX3_OUT, PTX3_IN_PD, PTX3_IN,
-		LCDD20, PTX2_OUT, PTX2_IN_PD, PTX2_IN,
-		LCDD19_DV_CLKI, PTX1_OUT, PTX1_IN_PD, PTX1_IN,
-		LCDD18_DV_CLK, PTX0_OUT, PTX0_IN_PD, PTX0_IN }
+		CS6A_CE2B, PTX6_OUT, 0, PTX6_IN,
+		LCDD23, PTX5_OUT, 0, PTX5_IN,
+		LCDD22, PTX4_OUT, 0, PTX4_IN,
+		LCDD21, PTX3_OUT, 0, PTX3_IN,
+		LCDD20, PTX2_OUT, 0, PTX2_IN,
+		LCDD19_DV_CLKI, PTX1_OUT, 0, PTX1_IN,
+		LCDD18_DV_CLK, PTX0_OUT, 0, PTX0_IN }
 	},
 	{ PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		KEYOUT5_IN5, PTY5_OUT, PTY5_IN_PU, PTY5_IN,
-		KEYOUT4_IN6, PTY4_OUT, PTY4_IN_PU, PTY4_IN,
-		KEYOUT3, PTY3_OUT, PTY3_IN_PU, PTY3_IN,
-		KEYOUT2, PTY2_OUT, PTY2_IN_PU, PTY2_IN,
+		KEYOUT5_IN5, PTY5_OUT, 0, PTY5_IN,
+		KEYOUT4_IN6, PTY4_OUT, 0, PTY4_IN,
+		KEYOUT3, PTY3_OUT, 0, PTY3_IN,
+		KEYOUT2, PTY2_OUT, 0, PTY2_IN,
 		KEYOUT1, PTY1_OUT, 0, 0,
-		KEYOUT0, PTY0_OUT, PTY0_IN_PU, PTY0_IN }
+		KEYOUT0, PTY0_OUT, 0, PTY0_IN }
 	},
 	{ PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		KEYIN4_IRQ7, 0, PTZ5_IN_PU, PTZ5_IN,
-		KEYIN3, 0, PTZ4_IN_PU, PTZ4_IN,
-		KEYIN2, 0, PTZ3_IN_PU, PTZ3_IN,
-		KEYIN1, 0, PTZ2_IN_PU, PTZ2_IN,
-		KEYIN0_IRQ6, 0, PTZ1_IN_PU, PTZ1_IN,
+		KEYIN4_IRQ7, 0, 0, PTZ5_IN,
+		KEYIN3, 0, 0, PTZ4_IN,
+		KEYIN2, 0, 0, PTZ3_IN,
+		KEYIN1, 0, 0, PTZ2_IN,
+		KEYIN0_IRQ6, 0, 0, PTZ1_IN,
 		0, 0, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 1) {
@@ -1763,8 +1730,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7722_pinmux_info = {
 	.name = "sh7722_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7723.c b/drivers/pinctrl/sh-pfc/pfc-sh7723.c
index 07ad1d8..1cecc91 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7723.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7723.c
@@ -102,12 +102,6 @@ enum {
 	PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
 	PINMUX_INPUT_END,
 
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PTA4_IN_PU, PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
-	PTB2_IN_PU, PTB1_IN_PU,
-	PTR2_IN_PU,
-	PINMUX_INPUT_PULLUP_END,
-
 	PINMUX_OUTPUT_BEGIN,
 	PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
 	PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
@@ -350,16 +344,16 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* PTA GPIO */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
 	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT),
-	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
-	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
-	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
-	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
-	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT),
+	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT),
+	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT),
+	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT),
+	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT),
 
 	/* PTB GPIO */
 	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
@@ -367,8 +361,8 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT),
 	PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT),
 	PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT),
-	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
-	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
+	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT),
+	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT),
 	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
 
 	/* PTC GPIO */
@@ -487,7 +481,7 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT),
 	PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT),
 	PINMUX_DATA(PTR3_DATA, PTR3_IN),
-	PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_IN_PU),
+	PINMUX_DATA(PTR2_DATA, PTR2_IN),
 	PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT),
 	PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT),
 
@@ -925,220 +919,220 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
-	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
-	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
-	PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
-	PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
-	PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
-	PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
-	PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
-	PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+	PINMUX_GPIO(PTA7),
+	PINMUX_GPIO(PTA6),
+	PINMUX_GPIO(PTA5),
+	PINMUX_GPIO(PTA4),
+	PINMUX_GPIO(PTA3),
+	PINMUX_GPIO(PTA2),
+	PINMUX_GPIO(PTA1),
+	PINMUX_GPIO(PTA0),
 
 	/* PTB */
-	PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
-	PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
-	PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
-	PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
-	PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
-	PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
-	PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
-	PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+	PINMUX_GPIO(PTB7),
+	PINMUX_GPIO(PTB6),
+	PINMUX_GPIO(PTB5),
+	PINMUX_GPIO(PTB4),
+	PINMUX_GPIO(PTB3),
+	PINMUX_GPIO(PTB2),
+	PINMUX_GPIO(PTB1),
+	PINMUX_GPIO(PTB0),
 
 	/* PTC */
-	PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
-	PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
-	PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
-	PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
-	PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
-	PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
-	PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
-	PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+	PINMUX_GPIO(PTC7),
+	PINMUX_GPIO(PTC6),
+	PINMUX_GPIO(PTC5),
+	PINMUX_GPIO(PTC4),
+	PINMUX_GPIO(PTC3),
+	PINMUX_GPIO(PTC2),
+	PINMUX_GPIO(PTC1),
+	PINMUX_GPIO(PTC0),
 
 	/* PTD */
-	PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
-	PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
-	PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
-	PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
-	PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
-	PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
-	PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
-	PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+	PINMUX_GPIO(PTD7),
+	PINMUX_GPIO(PTD6),
+	PINMUX_GPIO(PTD5),
+	PINMUX_GPIO(PTD4),
+	PINMUX_GPIO(PTD3),
+	PINMUX_GPIO(PTD2),
+	PINMUX_GPIO(PTD1),
+	PINMUX_GPIO(PTD0),
 
 	/* PTE */
-	PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
-	PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
-	PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
-	PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
-	PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
-	PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+	PINMUX_GPIO(PTE5),
+	PINMUX_GPIO(PTE4),
+	PINMUX_GPIO(PTE3),
+	PINMUX_GPIO(PTE2),
+	PINMUX_GPIO(PTE1),
+	PINMUX_GPIO(PTE0),
 
 	/* PTF */
-	PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
-	PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
-	PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
-	PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
-	PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
-	PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
-	PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
-	PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+	PINMUX_GPIO(PTF7),
+	PINMUX_GPIO(PTF6),
+	PINMUX_GPIO(PTF5),
+	PINMUX_GPIO(PTF4),
+	PINMUX_GPIO(PTF3),
+	PINMUX_GPIO(PTF2),
+	PINMUX_GPIO(PTF1),
+	PINMUX_GPIO(PTF0),
 
 	/* PTG */
-	PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
-	PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
-	PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
-	PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
-	PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
-	PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+	PINMUX_GPIO(PTG5),
+	PINMUX_GPIO(PTG4),
+	PINMUX_GPIO(PTG3),
+	PINMUX_GPIO(PTG2),
+	PINMUX_GPIO(PTG1),
+	PINMUX_GPIO(PTG0),
 
 	/* PTH */
-	PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
-	PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
-	PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
-	PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
-	PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
-	PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
-	PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
-	PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+	PINMUX_GPIO(PTH7),
+	PINMUX_GPIO(PTH6),
+	PINMUX_GPIO(PTH5),
+	PINMUX_GPIO(PTH4),
+	PINMUX_GPIO(PTH3),
+	PINMUX_GPIO(PTH2),
+	PINMUX_GPIO(PTH1),
+	PINMUX_GPIO(PTH0),
 
 	/* PTJ */
-	PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
-	PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
-	PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
-	PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
-	PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
-	PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+	PINMUX_GPIO(PTJ7),
+	PINMUX_GPIO(PTJ5),
+	PINMUX_GPIO(PTJ3),
+	PINMUX_GPIO(PTJ2),
+	PINMUX_GPIO(PTJ1),
+	PINMUX_GPIO(PTJ0),
 
 	/* PTK */
-	PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
-	PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
-	PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
-	PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
-	PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
-	PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
-	PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
-	PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+	PINMUX_GPIO(PTK7),
+	PINMUX_GPIO(PTK6),
+	PINMUX_GPIO(PTK5),
+	PINMUX_GPIO(PTK4),
+	PINMUX_GPIO(PTK3),
+	PINMUX_GPIO(PTK2),
+	PINMUX_GPIO(PTK1),
+	PINMUX_GPIO(PTK0),
 
 	/* PTL */
-	PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
-	PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
-	PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
-	PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
-	PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
-	PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
-	PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
-	PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+	PINMUX_GPIO(PTL7),
+	PINMUX_GPIO(PTL6),
+	PINMUX_GPIO(PTL5),
+	PINMUX_GPIO(PTL4),
+	PINMUX_GPIO(PTL3),
+	PINMUX_GPIO(PTL2),
+	PINMUX_GPIO(PTL1),
+	PINMUX_GPIO(PTL0),
 
 	/* PTM */
-	PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
-	PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
-	PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
-	PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
-	PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
-	PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
-	PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
-	PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+	PINMUX_GPIO(PTM7),
+	PINMUX_GPIO(PTM6),
+	PINMUX_GPIO(PTM5),
+	PINMUX_GPIO(PTM4),
+	PINMUX_GPIO(PTM3),
+	PINMUX_GPIO(PTM2),
+	PINMUX_GPIO(PTM1),
+	PINMUX_GPIO(PTM0),
 
 	/* PTN */
-	PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
-	PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
-	PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
-	PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
-	PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
-	PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
-	PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
-	PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+	PINMUX_GPIO(PTN7),
+	PINMUX_GPIO(PTN6),
+	PINMUX_GPIO(PTN5),
+	PINMUX_GPIO(PTN4),
+	PINMUX_GPIO(PTN3),
+	PINMUX_GPIO(PTN2),
+	PINMUX_GPIO(PTN1),
+	PINMUX_GPIO(PTN0),
 
 	/* PTQ */
-	PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
-	PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
-	PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
-	PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+	PINMUX_GPIO(PTQ3),
+	PINMUX_GPIO(PTQ2),
+	PINMUX_GPIO(PTQ1),
+	PINMUX_GPIO(PTQ0),
 
 	/* PTR */
-	PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
-	PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
-	PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
-	PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
-	PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
-	PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
-	PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
-	PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+	PINMUX_GPIO(PTR7),
+	PINMUX_GPIO(PTR6),
+	PINMUX_GPIO(PTR5),
+	PINMUX_GPIO(PTR4),
+	PINMUX_GPIO(PTR3),
+	PINMUX_GPIO(PTR2),
+	PINMUX_GPIO(PTR1),
+	PINMUX_GPIO(PTR0),
 
 	/* PTS */
-	PINMUX_GPIO(GPIO_PTS7, PTS7_DATA),
-	PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
-	PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
-	PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
-	PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
-	PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
-	PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
-	PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+	PINMUX_GPIO(PTS7),
+	PINMUX_GPIO(PTS6),
+	PINMUX_GPIO(PTS5),
+	PINMUX_GPIO(PTS4),
+	PINMUX_GPIO(PTS3),
+	PINMUX_GPIO(PTS2),
+	PINMUX_GPIO(PTS1),
+	PINMUX_GPIO(PTS0),
 
 	/* PTT */
-	PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
-	PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
-	PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
-	PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
-	PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
-	PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+	PINMUX_GPIO(PTT5),
+	PINMUX_GPIO(PTT4),
+	PINMUX_GPIO(PTT3),
+	PINMUX_GPIO(PTT2),
+	PINMUX_GPIO(PTT1),
+	PINMUX_GPIO(PTT0),
 
 	/* PTU */
-	PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
-	PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
-	PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
-	PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
-	PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
-	PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+	PINMUX_GPIO(PTU5),
+	PINMUX_GPIO(PTU4),
+	PINMUX_GPIO(PTU3),
+	PINMUX_GPIO(PTU2),
+	PINMUX_GPIO(PTU1),
+	PINMUX_GPIO(PTU0),
 
 	/* PTV */
-	PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
-	PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
-	PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
-	PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
-	PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
-	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
-	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
-	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+	PINMUX_GPIO(PTV7),
+	PINMUX_GPIO(PTV6),
+	PINMUX_GPIO(PTV5),
+	PINMUX_GPIO(PTV4),
+	PINMUX_GPIO(PTV3),
+	PINMUX_GPIO(PTV2),
+	PINMUX_GPIO(PTV1),
+	PINMUX_GPIO(PTV0),
 
 	/* PTW */
-	PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
-	PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
-	PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
-	PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
-	PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
-	PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
-	PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
-	PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+	PINMUX_GPIO(PTW7),
+	PINMUX_GPIO(PTW6),
+	PINMUX_GPIO(PTW5),
+	PINMUX_GPIO(PTW4),
+	PINMUX_GPIO(PTW3),
+	PINMUX_GPIO(PTW2),
+	PINMUX_GPIO(PTW1),
+	PINMUX_GPIO(PTW0),
 
 	/* PTX */
-	PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
-	PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
-	PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
-	PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
-	PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
-	PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
-	PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
-	PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+	PINMUX_GPIO(PTX7),
+	PINMUX_GPIO(PTX6),
+	PINMUX_GPIO(PTX5),
+	PINMUX_GPIO(PTX4),
+	PINMUX_GPIO(PTX3),
+	PINMUX_GPIO(PTX2),
+	PINMUX_GPIO(PTX1),
+	PINMUX_GPIO(PTX0),
 
 	/* PTY */
-	PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
-	PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
-	PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
-	PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
-	PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
-	PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
-	PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
-	PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+	PINMUX_GPIO(PTY7),
+	PINMUX_GPIO(PTY6),
+	PINMUX_GPIO(PTY5),
+	PINMUX_GPIO(PTY4),
+	PINMUX_GPIO(PTY3),
+	PINMUX_GPIO(PTY2),
+	PINMUX_GPIO(PTY1),
+	PINMUX_GPIO(PTY0),
 
 	/* PTZ */
-	PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
-	PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
-	PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
-	PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
-	PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
-	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
-	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
-	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+	PINMUX_GPIO(PTZ7),
+	PINMUX_GPIO(PTZ6),
+	PINMUX_GPIO(PTZ5),
+	PINMUX_GPIO(PTZ4),
+	PINMUX_GPIO(PTZ3),
+	PINMUX_GPIO(PTZ2),
+	PINMUX_GPIO(PTZ1),
+	PINMUX_GPIO(PTZ0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -1520,11 +1514,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTA7_FN, PTA7_OUT, 0, PTA7_IN,
 		PTA6_FN, PTA6_OUT, 0, PTA6_IN,
 		PTA5_FN, PTA5_OUT, 0, PTA5_IN,
-		PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
-		PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
-		PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
-		PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
-		PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+		PTA4_FN, PTA4_OUT, 0, PTA4_IN,
+		PTA3_FN, PTA3_OUT, 0, PTA3_IN,
+		PTA2_FN, PTA2_OUT, 0, PTA2_IN,
+		PTA1_FN, PTA1_OUT, 0, PTA1_IN,
+		PTA0_FN, PTA0_OUT, 0, PTA0_IN }
 	},
 	{ PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
 		PTB7_FN, PTB7_OUT, 0, PTB7_IN,
@@ -1532,8 +1526,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTB5_FN, PTB5_OUT, 0, PTB5_IN,
 		PTB4_FN, PTB4_OUT, 0, PTB4_IN,
 		PTB3_FN, PTB3_OUT, 0, PTB3_IN,
-		PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
-		PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
+		PTB2_FN, PTB2_OUT, 0, PTB2_IN,
+		PTB1_FN, PTB1_OUT, 0, PTB1_IN,
 		PTB0_FN, PTB0_OUT, 0, PTB0_IN }
 	},
 	{ PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
@@ -1662,7 +1656,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTR5_FN, PTR5_OUT, 0, PTR5_IN,
 		PTR4_FN, PTR4_OUT, 0, PTR4_IN,
 		PTR3_FN, 0, 0, PTR3_IN,
-		PTR2_FN, 0, PTR2_IN_PU, PTR2_IN,
+		PTR2_FN, 0, 0, PTR2_IN,
 		PTR1_FN, PTR1_OUT, 0, PTR1_IN,
 		PTR0_FN, PTR0_OUT, 0, PTR0_IN }
 	},
@@ -1888,7 +1882,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7723_pinmux_info = {
 	.name = "sh7723_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7724.c b/drivers/pinctrl/sh-pfc/pfc-sh7724.c
index 35e5516..1085ab5 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7724.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7724.c
@@ -117,52 +117,6 @@ enum {
 	PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
 	PINMUX_INPUT_END,
 
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
-	PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
-	PTB7_IN_PU, PTB6_IN_PU, PTB5_IN_PU, PTB4_IN_PU,
-	PTB3_IN_PU, PTB2_IN_PU, PTB1_IN_PU, PTB0_IN_PU,
-	PTC7_IN_PU, PTC6_IN_PU, PTC5_IN_PU, PTC4_IN_PU,
-	PTC3_IN_PU, PTC2_IN_PU, PTC1_IN_PU, PTC0_IN_PU,
-	PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
-	PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
-	PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU,
-	PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
-	PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU,
-	PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU,
-	PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
-	PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
-	PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
-	PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU,
-	PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
-	PTL7_IN_PU, PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU,
-	PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU,
-	PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
-	PTM3_IN_PU, PTM2_IN_PU, PTM1_IN_PU, PTM0_IN_PU,
-	PTN7_IN_PU, PTN6_IN_PU, PTN5_IN_PU, PTN4_IN_PU,
-	PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU,
-	PTQ7_IN_PU, PTQ6_IN_PU, PTQ5_IN_PU, PTQ4_IN_PU,
-	PTQ3_IN_PU, PTQ2_IN_PU, PTQ1_IN_PU, PTQ0_IN_PU,
-	PTR7_IN_PU, PTR6_IN_PU, PTR5_IN_PU, PTR4_IN_PU,
-	PTR3_IN_PU, PTR2_IN_PU, PTR1_IN_PU, PTR0_IN_PU,
-		    PTS6_IN_PU, PTS5_IN_PU, PTS4_IN_PU,
-	PTS3_IN_PU, PTS2_IN_PU, PTS1_IN_PU, PTS0_IN_PU,
-	PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU,
-	PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
-	PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
-	PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
-	PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
-	PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
-	PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU,
-	PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU,
-	PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
-	PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
-	PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
-	PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
-	PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU,
-	PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU,
-	PINMUX_INPUT_PULLUP_END,
-
 	PINMUX_OUTPUT_BEGIN,
 	PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
 	PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
@@ -572,66 +526,66 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* PTA GPIO */
-	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
-	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
-	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT, PTA5_IN_PU),
-	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
-	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
-	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
-	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
-	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
+	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
+	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT),
+	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT),
+	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT),
+	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT),
+	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT),
+	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT),
 
 	/* PTB GPIO */
-	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT, PTB7_IN_PU),
-	PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT, PTB6_IN_PU),
-	PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT, PTB5_IN_PU),
-	PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT, PTB4_IN_PU),
-	PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT, PTB3_IN_PU),
-	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
-	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
-	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT, PTB0_IN_PU),
+	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
+	PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT),
+	PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT),
+	PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT),
+	PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT),
+	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT),
+	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT),
+	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
 
 	/* PTC GPIO */
-	PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT, PTC7_IN_PU),
-	PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT, PTC6_IN_PU),
-	PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT, PTC5_IN_PU),
-	PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT, PTC4_IN_PU),
-	PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT, PTC3_IN_PU),
-	PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT, PTC2_IN_PU),
-	PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT, PTC1_IN_PU),
-	PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT, PTC0_IN_PU),
+	PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT),
+	PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT),
+	PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT),
+	PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT),
+	PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT),
+	PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT),
+	PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT),
+	PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT),
 
 	/* PTD GPIO */
-	PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT, PTD7_IN_PU),
-	PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT, PTD6_IN_PU),
-	PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT, PTD5_IN_PU),
-	PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT, PTD4_IN_PU),
-	PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT, PTD3_IN_PU),
-	PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT, PTD2_IN_PU),
-	PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT, PTD1_IN_PU),
-	PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT, PTD0_IN_PU),
+	PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT),
+	PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT),
+	PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT),
+	PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT),
+	PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT),
+	PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT),
+	PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT),
+	PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT),
 
 	/* PTE GPIO */
-	PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT, PTE7_IN_PU),
-	PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT, PTE6_IN_PU),
-	PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT, PTE5_IN_PU),
-	PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT, PTE4_IN_PU),
-	PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT, PTE3_IN_PU),
-	PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT, PTE2_IN_PU),
-	PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT, PTE1_IN_PU),
-	PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT, PTE0_IN_PU),
+	PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT),
+	PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT),
+	PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT),
+	PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT),
+	PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT),
+	PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT),
+	PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT),
+	PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT),
 
 	/* PTF GPIO */
-	PINMUX_DATA(PTF7_DATA, PTF7_IN, PTF7_OUT, PTF7_IN_PU),
-	PINMUX_DATA(PTF6_DATA, PTF6_IN, PTF6_OUT, PTF6_IN_PU),
-	PINMUX_DATA(PTF5_DATA, PTF5_IN, PTF5_OUT, PTF5_IN_PU),
-	PINMUX_DATA(PTF4_DATA, PTF4_IN, PTF4_OUT, PTF4_IN_PU),
-	PINMUX_DATA(PTF3_DATA, PTF3_IN, PTF3_OUT, PTF3_IN_PU),
-	PINMUX_DATA(PTF2_DATA, PTF2_IN, PTF2_OUT, PTF2_IN_PU),
-	PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_OUT, PTF1_IN_PU),
-	PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT, PTF0_IN_PU),
+	PINMUX_DATA(PTF7_DATA, PTF7_IN, PTF7_OUT),
+	PINMUX_DATA(PTF6_DATA, PTF6_IN, PTF6_OUT),
+	PINMUX_DATA(PTF5_DATA, PTF5_IN, PTF5_OUT),
+	PINMUX_DATA(PTF4_DATA, PTF4_IN, PTF4_OUT),
+	PINMUX_DATA(PTF3_DATA, PTF3_IN, PTF3_OUT),
+	PINMUX_DATA(PTF2_DATA, PTF2_IN, PTF2_OUT),
+	PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_OUT),
+	PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT),
 
 	/* PTG GPIO */
 	PINMUX_DATA(PTG5_DATA, PTG5_OUT),
@@ -642,162 +596,162 @@ static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(PTG0_DATA, PTG0_OUT),
 
 	/* PTH GPIO */
-	PINMUX_DATA(PTH7_DATA, PTH7_IN, PTH7_OUT, PTH7_IN_PU),
-	PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT, PTH6_IN_PU),
-	PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT, PTH5_IN_PU),
-	PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT, PTH4_IN_PU),
-	PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT, PTH3_IN_PU),
-	PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT, PTH2_IN_PU),
-	PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT, PTH1_IN_PU),
-	PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT, PTH0_IN_PU),
+	PINMUX_DATA(PTH7_DATA, PTH7_IN, PTH7_OUT),
+	PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT),
+	PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT),
+	PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT),
+	PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT),
+	PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT),
+	PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT),
+	PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT),
 
 	/* PTJ GPIO */
 	PINMUX_DATA(PTJ7_DATA, PTJ7_OUT),
 	PINMUX_DATA(PTJ6_DATA, PTJ6_OUT),
 	PINMUX_DATA(PTJ5_DATA, PTJ5_OUT),
-	PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT, PTJ3_IN_PU),
-	PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT, PTJ2_IN_PU),
-	PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT, PTJ1_IN_PU),
-	PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT, PTJ0_IN_PU),
+	PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT),
+	PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT),
+	PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT),
+	PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT),
 
 	/* PTK GPIO */
-	PINMUX_DATA(PTK7_DATA, PTK7_IN, PTK7_OUT, PTK7_IN_PU),
-	PINMUX_DATA(PTK6_DATA, PTK6_IN, PTK6_OUT, PTK6_IN_PU),
-	PINMUX_DATA(PTK5_DATA, PTK5_IN, PTK5_OUT, PTK5_IN_PU),
-	PINMUX_DATA(PTK4_DATA, PTK4_IN, PTK4_OUT, PTK4_IN_PU),
-	PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT, PTK3_IN_PU),
-	PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT, PTK2_IN_PU),
-	PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT, PTK1_IN_PU),
-	PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT, PTK0_IN_PU),
+	PINMUX_DATA(PTK7_DATA, PTK7_IN, PTK7_OUT),
+	PINMUX_DATA(PTK6_DATA, PTK6_IN, PTK6_OUT),
+	PINMUX_DATA(PTK5_DATA, PTK5_IN, PTK5_OUT),
+	PINMUX_DATA(PTK4_DATA, PTK4_IN, PTK4_OUT),
+	PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT),
+	PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT),
+	PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT),
+	PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT),
 
 	/* PTL GPIO */
-	PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT, PTL7_IN_PU),
-	PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT, PTL6_IN_PU),
-	PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT, PTL5_IN_PU),
-	PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT, PTL4_IN_PU),
-	PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT, PTL3_IN_PU),
-	PINMUX_DATA(PTL2_DATA, PTL2_IN, PTL2_OUT, PTL2_IN_PU),
-	PINMUX_DATA(PTL1_DATA, PTL1_IN, PTL1_OUT, PTL1_IN_PU),
-	PINMUX_DATA(PTL0_DATA, PTL0_IN, PTL0_OUT, PTL0_IN_PU),
+	PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT),
+	PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT),
+	PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT),
+	PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT),
+	PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT),
+	PINMUX_DATA(PTL2_DATA, PTL2_IN, PTL2_OUT),
+	PINMUX_DATA(PTL1_DATA, PTL1_IN, PTL1_OUT),
+	PINMUX_DATA(PTL0_DATA, PTL0_IN, PTL0_OUT),
 
 	/* PTM GPIO */
-	PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT, PTM7_IN_PU),
-	PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT, PTM6_IN_PU),
-	PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT, PTM5_IN_PU),
-	PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT, PTM4_IN_PU),
-	PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT, PTM3_IN_PU),
-	PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT, PTM2_IN_PU),
-	PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT, PTM1_IN_PU),
-	PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT, PTM0_IN_PU),
+	PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT),
+	PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT),
+	PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT),
+	PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT),
+	PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT),
+	PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT),
+	PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT),
+	PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT),
 
 	/* PTN GPIO */
-	PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT, PTN7_IN_PU),
-	PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT, PTN6_IN_PU),
-	PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT, PTN5_IN_PU),
-	PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT, PTN4_IN_PU),
-	PINMUX_DATA(PTN3_DATA, PTN3_IN, PTN3_OUT, PTN3_IN_PU),
-	PINMUX_DATA(PTN2_DATA, PTN2_IN, PTN2_OUT, PTN2_IN_PU),
-	PINMUX_DATA(PTN1_DATA, PTN1_IN, PTN1_OUT, PTN1_IN_PU),
-	PINMUX_DATA(PTN0_DATA, PTN0_IN, PTN0_OUT, PTN0_IN_PU),
+	PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT),
+	PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT),
+	PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT),
+	PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT),
+	PINMUX_DATA(PTN3_DATA, PTN3_IN, PTN3_OUT),
+	PINMUX_DATA(PTN2_DATA, PTN2_IN, PTN2_OUT),
+	PINMUX_DATA(PTN1_DATA, PTN1_IN, PTN1_OUT),
+	PINMUX_DATA(PTN0_DATA, PTN0_IN, PTN0_OUT),
 
 	/* PTQ GPIO */
-	PINMUX_DATA(PTQ7_DATA, PTQ7_IN, PTQ7_OUT, PTQ7_IN_PU),
-	PINMUX_DATA(PTQ6_DATA, PTQ6_IN, PTQ6_OUT, PTQ6_IN_PU),
-	PINMUX_DATA(PTQ5_DATA, PTQ5_IN, PTQ5_OUT, PTQ5_IN_PU),
-	PINMUX_DATA(PTQ4_DATA, PTQ4_IN, PTQ4_OUT, PTQ4_IN_PU),
-	PINMUX_DATA(PTQ3_DATA, PTQ3_IN, PTQ3_OUT, PTQ3_IN_PU),
-	PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_OUT, PTQ2_IN_PU),
-	PINMUX_DATA(PTQ1_DATA, PTQ1_IN, PTQ1_OUT, PTQ1_IN_PU),
-	PINMUX_DATA(PTQ0_DATA, PTQ0_IN, PTQ0_OUT, PTQ0_IN_PU),
+	PINMUX_DATA(PTQ7_DATA, PTQ7_IN, PTQ7_OUT),
+	PINMUX_DATA(PTQ6_DATA, PTQ6_IN, PTQ6_OUT),
+	PINMUX_DATA(PTQ5_DATA, PTQ5_IN, PTQ5_OUT),
+	PINMUX_DATA(PTQ4_DATA, PTQ4_IN, PTQ4_OUT),
+	PINMUX_DATA(PTQ3_DATA, PTQ3_IN, PTQ3_OUT),
+	PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_OUT),
+	PINMUX_DATA(PTQ1_DATA, PTQ1_IN, PTQ1_OUT),
+	PINMUX_DATA(PTQ0_DATA, PTQ0_IN, PTQ0_OUT),
 
 	/* PTR GPIO */
-	PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT, PTR7_IN_PU),
-	PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT, PTR6_IN_PU),
-	PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT, PTR5_IN_PU),
-	PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT, PTR4_IN_PU),
-	PINMUX_DATA(PTR3_DATA, PTR3_IN,           PTR3_IN_PU),
-	PINMUX_DATA(PTR2_DATA, PTR2_IN,           PTR2_IN_PU),
-	PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT, PTR1_IN_PU),
-	PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT, PTR0_IN_PU),
+	PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT),
+	PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT),
+	PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT),
+	PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT),
+	PINMUX_DATA(PTR3_DATA, PTR3_IN),
+	PINMUX_DATA(PTR2_DATA, PTR2_IN),
+	PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT),
+	PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT),
 
 	/* PTS GPIO */
-	PINMUX_DATA(PTS6_DATA, PTS6_IN, PTS6_OUT, PTS6_IN_PU),
-	PINMUX_DATA(PTS5_DATA, PTS5_IN, PTS5_OUT, PTS5_IN_PU),
-	PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT, PTS4_IN_PU),
-	PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT, PTS3_IN_PU),
-	PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT, PTS2_IN_PU),
-	PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT, PTS1_IN_PU),
-	PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT, PTS0_IN_PU),
+	PINMUX_DATA(PTS6_DATA, PTS6_IN, PTS6_OUT),
+	PINMUX_DATA(PTS5_DATA, PTS5_IN, PTS5_OUT),
+	PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT),
+	PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT),
+	PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT),
+	PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT),
+	PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT),
 
 	/* PTT GPIO */
-	PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT, PTT7_IN_PU),
-	PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT, PTT6_IN_PU),
-	PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT, PTT5_IN_PU),
-	PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT, PTT4_IN_PU),
-	PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT, PTT3_IN_PU),
-	PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT, PTT2_IN_PU),
-	PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT, PTT1_IN_PU),
-	PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT, PTT0_IN_PU),
+	PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT),
+	PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT),
+	PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT),
+	PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT),
+	PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT),
+	PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT),
+	PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT),
+	PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT),
 
 	/* PTU GPIO */
-	PINMUX_DATA(PTU7_DATA, PTU7_IN, PTU7_OUT, PTU7_IN_PU),
-	PINMUX_DATA(PTU6_DATA, PTU6_IN, PTU6_OUT, PTU6_IN_PU),
-	PINMUX_DATA(PTU5_DATA, PTU5_IN, PTU5_OUT, PTU5_IN_PU),
-	PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT, PTU4_IN_PU),
-	PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT, PTU3_IN_PU),
-	PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT, PTU2_IN_PU),
-	PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT, PTU1_IN_PU),
-	PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT, PTU0_IN_PU),
+	PINMUX_DATA(PTU7_DATA, PTU7_IN, PTU7_OUT),
+	PINMUX_DATA(PTU6_DATA, PTU6_IN, PTU6_OUT),
+	PINMUX_DATA(PTU5_DATA, PTU5_IN, PTU5_OUT),
+	PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT),
+	PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT),
+	PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT),
+	PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT),
+	PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT),
 
 	/* PTV GPIO */
-	PINMUX_DATA(PTV7_DATA, PTV7_IN, PTV7_OUT, PTV7_IN_PU),
-	PINMUX_DATA(PTV6_DATA, PTV6_IN, PTV6_OUT, PTV6_IN_PU),
-	PINMUX_DATA(PTV5_DATA, PTV5_IN, PTV5_OUT, PTV5_IN_PU),
-	PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT, PTV4_IN_PU),
-	PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT, PTV3_IN_PU),
-	PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT, PTV2_IN_PU),
-	PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT, PTV1_IN_PU),
-	PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT, PTV0_IN_PU),
+	PINMUX_DATA(PTV7_DATA, PTV7_IN, PTV7_OUT),
+	PINMUX_DATA(PTV6_DATA, PTV6_IN, PTV6_OUT),
+	PINMUX_DATA(PTV5_DATA, PTV5_IN, PTV5_OUT),
+	PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT),
+	PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT),
+	PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT),
+	PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT),
+	PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT),
 
 	/* PTW GPIO */
-	PINMUX_DATA(PTW7_DATA, PTW7_IN, PTW7_OUT, PTW7_IN_PU),
-	PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_OUT, PTW6_IN_PU),
-	PINMUX_DATA(PTW5_DATA, PTW5_IN, PTW5_OUT, PTW5_IN_PU),
-	PINMUX_DATA(PTW4_DATA, PTW4_IN, PTW4_OUT, PTW4_IN_PU),
-	PINMUX_DATA(PTW3_DATA, PTW3_IN, PTW3_OUT, PTW3_IN_PU),
-	PINMUX_DATA(PTW2_DATA, PTW2_IN, PTW2_OUT, PTW2_IN_PU),
-	PINMUX_DATA(PTW1_DATA, PTW1_IN, PTW1_OUT, PTW1_IN_PU),
-	PINMUX_DATA(PTW0_DATA, PTW0_IN, PTW0_OUT, PTW0_IN_PU),
+	PINMUX_DATA(PTW7_DATA, PTW7_IN, PTW7_OUT),
+	PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_OUT),
+	PINMUX_DATA(PTW5_DATA, PTW5_IN, PTW5_OUT),
+	PINMUX_DATA(PTW4_DATA, PTW4_IN, PTW4_OUT),
+	PINMUX_DATA(PTW3_DATA, PTW3_IN, PTW3_OUT),
+	PINMUX_DATA(PTW2_DATA, PTW2_IN, PTW2_OUT),
+	PINMUX_DATA(PTW1_DATA, PTW1_IN, PTW1_OUT),
+	PINMUX_DATA(PTW0_DATA, PTW0_IN, PTW0_OUT),
 
 	/* PTX GPIO */
-	PINMUX_DATA(PTX7_DATA, PTX7_IN, PTX7_OUT, PTX7_IN_PU),
-	PINMUX_DATA(PTX6_DATA, PTX6_IN, PTX6_OUT, PTX6_IN_PU),
-	PINMUX_DATA(PTX5_DATA, PTX5_IN, PTX5_OUT, PTX5_IN_PU),
-	PINMUX_DATA(PTX4_DATA, PTX4_IN, PTX4_OUT, PTX4_IN_PU),
-	PINMUX_DATA(PTX3_DATA, PTX3_IN, PTX3_OUT, PTX3_IN_PU),
-	PINMUX_DATA(PTX2_DATA, PTX2_IN, PTX2_OUT, PTX2_IN_PU),
-	PINMUX_DATA(PTX1_DATA, PTX1_IN, PTX1_OUT, PTX1_IN_PU),
-	PINMUX_DATA(PTX0_DATA, PTX0_IN, PTX0_OUT, PTX0_IN_PU),
+	PINMUX_DATA(PTX7_DATA, PTX7_IN, PTX7_OUT),
+	PINMUX_DATA(PTX6_DATA, PTX6_IN, PTX6_OUT),
+	PINMUX_DATA(PTX5_DATA, PTX5_IN, PTX5_OUT),
+	PINMUX_DATA(PTX4_DATA, PTX4_IN, PTX4_OUT),
+	PINMUX_DATA(PTX3_DATA, PTX3_IN, PTX3_OUT),
+	PINMUX_DATA(PTX2_DATA, PTX2_IN, PTX2_OUT),
+	PINMUX_DATA(PTX1_DATA, PTX1_IN, PTX1_OUT),
+	PINMUX_DATA(PTX0_DATA, PTX0_IN, PTX0_OUT),
 
 	/* PTY GPIO */
-	PINMUX_DATA(PTY7_DATA, PTY7_IN, PTY7_OUT, PTY7_IN_PU),
-	PINMUX_DATA(PTY6_DATA, PTY6_IN, PTY6_OUT, PTY6_IN_PU),
-	PINMUX_DATA(PTY5_DATA, PTY5_IN, PTY5_OUT, PTY5_IN_PU),
-	PINMUX_DATA(PTY4_DATA, PTY4_IN, PTY4_OUT, PTY4_IN_PU),
-	PINMUX_DATA(PTY3_DATA, PTY3_IN, PTY3_OUT, PTY3_IN_PU),
-	PINMUX_DATA(PTY2_DATA, PTY2_IN, PTY2_OUT, PTY2_IN_PU),
-	PINMUX_DATA(PTY1_DATA, PTY1_IN, PTY1_OUT, PTY1_IN_PU),
-	PINMUX_DATA(PTY0_DATA, PTY0_IN, PTY0_OUT, PTY0_IN_PU),
+	PINMUX_DATA(PTY7_DATA, PTY7_IN, PTY7_OUT),
+	PINMUX_DATA(PTY6_DATA, PTY6_IN, PTY6_OUT),
+	PINMUX_DATA(PTY5_DATA, PTY5_IN, PTY5_OUT),
+	PINMUX_DATA(PTY4_DATA, PTY4_IN, PTY4_OUT),
+	PINMUX_DATA(PTY3_DATA, PTY3_IN, PTY3_OUT),
+	PINMUX_DATA(PTY2_DATA, PTY2_IN, PTY2_OUT),
+	PINMUX_DATA(PTY1_DATA, PTY1_IN, PTY1_OUT),
+	PINMUX_DATA(PTY0_DATA, PTY0_IN, PTY0_OUT),
 
 	/* PTZ GPIO */
-	PINMUX_DATA(PTZ7_DATA, PTZ7_IN, PTZ7_OUT, PTZ7_IN_PU),
-	PINMUX_DATA(PTZ6_DATA, PTZ6_IN, PTZ6_OUT, PTZ6_IN_PU),
-	PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_OUT, PTZ5_IN_PU),
-	PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_OUT, PTZ4_IN_PU),
-	PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_OUT, PTZ3_IN_PU),
-	PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_OUT, PTZ2_IN_PU),
-	PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_OUT, PTZ1_IN_PU),
-	PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT, PTZ0_IN_PU),
+	PINMUX_DATA(PTZ7_DATA, PTZ7_IN, PTZ7_OUT),
+	PINMUX_DATA(PTZ6_DATA, PTZ6_IN, PTZ6_OUT),
+	PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_OUT),
+	PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_OUT),
+	PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_OUT),
+	PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_OUT),
+	PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_OUT),
+	PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT),
 
 	/* PTA FN */
 	PINMUX_DATA(D23_MARK,	PSA15_0, PSA14_0, PTA7_FN),
@@ -1194,230 +1148,230 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
-	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
-	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
-	PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
-	PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
-	PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
-	PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
-	PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
-	PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+	PINMUX_GPIO(PTA7),
+	PINMUX_GPIO(PTA6),
+	PINMUX_GPIO(PTA5),
+	PINMUX_GPIO(PTA4),
+	PINMUX_GPIO(PTA3),
+	PINMUX_GPIO(PTA2),
+	PINMUX_GPIO(PTA1),
+	PINMUX_GPIO(PTA0),
 
 	/* PTB */
-	PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
-	PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
-	PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
-	PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
-	PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
-	PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
-	PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
-	PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+	PINMUX_GPIO(PTB7),
+	PINMUX_GPIO(PTB6),
+	PINMUX_GPIO(PTB5),
+	PINMUX_GPIO(PTB4),
+	PINMUX_GPIO(PTB3),
+	PINMUX_GPIO(PTB2),
+	PINMUX_GPIO(PTB1),
+	PINMUX_GPIO(PTB0),
 
 	/* PTC */
-	PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
-	PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
-	PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
-	PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
-	PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
-	PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
-	PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
-	PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+	PINMUX_GPIO(PTC7),
+	PINMUX_GPIO(PTC6),
+	PINMUX_GPIO(PTC5),
+	PINMUX_GPIO(PTC4),
+	PINMUX_GPIO(PTC3),
+	PINMUX_GPIO(PTC2),
+	PINMUX_GPIO(PTC1),
+	PINMUX_GPIO(PTC0),
 
 	/* PTD */
-	PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
-	PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
-	PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
-	PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
-	PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
-	PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
-	PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
-	PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+	PINMUX_GPIO(PTD7),
+	PINMUX_GPIO(PTD6),
+	PINMUX_GPIO(PTD5),
+	PINMUX_GPIO(PTD4),
+	PINMUX_GPIO(PTD3),
+	PINMUX_GPIO(PTD2),
+	PINMUX_GPIO(PTD1),
+	PINMUX_GPIO(PTD0),
 
 	/* PTE */
-	PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
-	PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
-	PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
-	PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
-	PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
-	PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
-	PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
-	PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+	PINMUX_GPIO(PTE7),
+	PINMUX_GPIO(PTE6),
+	PINMUX_GPIO(PTE5),
+	PINMUX_GPIO(PTE4),
+	PINMUX_GPIO(PTE3),
+	PINMUX_GPIO(PTE2),
+	PINMUX_GPIO(PTE1),
+	PINMUX_GPIO(PTE0),
 
 	/* PTF */
-	PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
-	PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
-	PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
-	PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
-	PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
-	PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
-	PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
-	PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+	PINMUX_GPIO(PTF7),
+	PINMUX_GPIO(PTF6),
+	PINMUX_GPIO(PTF5),
+	PINMUX_GPIO(PTF4),
+	PINMUX_GPIO(PTF3),
+	PINMUX_GPIO(PTF2),
+	PINMUX_GPIO(PTF1),
+	PINMUX_GPIO(PTF0),
 
 	/* PTG */
-	PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
-	PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
-	PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
-	PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
-	PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
-	PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+	PINMUX_GPIO(PTG5),
+	PINMUX_GPIO(PTG4),
+	PINMUX_GPIO(PTG3),
+	PINMUX_GPIO(PTG2),
+	PINMUX_GPIO(PTG1),
+	PINMUX_GPIO(PTG0),
 
 	/* PTH */
-	PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
-	PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
-	PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
-	PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
-	PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
-	PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
-	PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
-	PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+	PINMUX_GPIO(PTH7),
+	PINMUX_GPIO(PTH6),
+	PINMUX_GPIO(PTH5),
+	PINMUX_GPIO(PTH4),
+	PINMUX_GPIO(PTH3),
+	PINMUX_GPIO(PTH2),
+	PINMUX_GPIO(PTH1),
+	PINMUX_GPIO(PTH0),
 
 	/* PTJ */
-	PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
-	PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
-	PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
-	PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
-	PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
-	PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
-	PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+	PINMUX_GPIO(PTJ7),
+	PINMUX_GPIO(PTJ6),
+	PINMUX_GPIO(PTJ5),
+	PINMUX_GPIO(PTJ3),
+	PINMUX_GPIO(PTJ2),
+	PINMUX_GPIO(PTJ1),
+	PINMUX_GPIO(PTJ0),
 
 	/* PTK */
-	PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
-	PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
-	PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
-	PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
-	PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
-	PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
-	PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
-	PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+	PINMUX_GPIO(PTK7),
+	PINMUX_GPIO(PTK6),
+	PINMUX_GPIO(PTK5),
+	PINMUX_GPIO(PTK4),
+	PINMUX_GPIO(PTK3),
+	PINMUX_GPIO(PTK2),
+	PINMUX_GPIO(PTK1),
+	PINMUX_GPIO(PTK0),
 
 	/* PTL */
-	PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
-	PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
-	PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
-	PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
-	PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
-	PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
-	PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
-	PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+	PINMUX_GPIO(PTL7),
+	PINMUX_GPIO(PTL6),
+	PINMUX_GPIO(PTL5),
+	PINMUX_GPIO(PTL4),
+	PINMUX_GPIO(PTL3),
+	PINMUX_GPIO(PTL2),
+	PINMUX_GPIO(PTL1),
+	PINMUX_GPIO(PTL0),
 
 	/* PTM */
-	PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
-	PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
-	PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
-	PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
-	PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
-	PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
-	PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
-	PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+	PINMUX_GPIO(PTM7),
+	PINMUX_GPIO(PTM6),
+	PINMUX_GPIO(PTM5),
+	PINMUX_GPIO(PTM4),
+	PINMUX_GPIO(PTM3),
+	PINMUX_GPIO(PTM2),
+	PINMUX_GPIO(PTM1),
+	PINMUX_GPIO(PTM0),
 
 	/* PTN */
-	PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
-	PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
-	PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
-	PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
-	PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
-	PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
-	PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
-	PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+	PINMUX_GPIO(PTN7),
+	PINMUX_GPIO(PTN6),
+	PINMUX_GPIO(PTN5),
+	PINMUX_GPIO(PTN4),
+	PINMUX_GPIO(PTN3),
+	PINMUX_GPIO(PTN2),
+	PINMUX_GPIO(PTN1),
+	PINMUX_GPIO(PTN0),
 
 	/* PTQ */
-	PINMUX_GPIO(GPIO_PTQ7, PTQ7_DATA),
-	PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
-	PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
-	PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
-	PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
-	PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
-	PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
-	PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+	PINMUX_GPIO(PTQ7),
+	PINMUX_GPIO(PTQ6),
+	PINMUX_GPIO(PTQ5),
+	PINMUX_GPIO(PTQ4),
+	PINMUX_GPIO(PTQ3),
+	PINMUX_GPIO(PTQ2),
+	PINMUX_GPIO(PTQ1),
+	PINMUX_GPIO(PTQ0),
 
 	/* PTR */
-	PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
-	PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
-	PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
-	PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
-	PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
-	PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
-	PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
-	PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+	PINMUX_GPIO(PTR7),
+	PINMUX_GPIO(PTR6),
+	PINMUX_GPIO(PTR5),
+	PINMUX_GPIO(PTR4),
+	PINMUX_GPIO(PTR3),
+	PINMUX_GPIO(PTR2),
+	PINMUX_GPIO(PTR1),
+	PINMUX_GPIO(PTR0),
 
 	/* PTS */
-	PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
-	PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
-	PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
-	PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
-	PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
-	PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
-	PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+	PINMUX_GPIO(PTS6),
+	PINMUX_GPIO(PTS5),
+	PINMUX_GPIO(PTS4),
+	PINMUX_GPIO(PTS3),
+	PINMUX_GPIO(PTS2),
+	PINMUX_GPIO(PTS1),
+	PINMUX_GPIO(PTS0),
 
 	/* PTT */
-	PINMUX_GPIO(GPIO_PTT7, PTT7_DATA),
-	PINMUX_GPIO(GPIO_PTT6, PTT6_DATA),
-	PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
-	PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
-	PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
-	PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
-	PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
-	PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+	PINMUX_GPIO(PTT7),
+	PINMUX_GPIO(PTT6),
+	PINMUX_GPIO(PTT5),
+	PINMUX_GPIO(PTT4),
+	PINMUX_GPIO(PTT3),
+	PINMUX_GPIO(PTT2),
+	PINMUX_GPIO(PTT1),
+	PINMUX_GPIO(PTT0),
 
 	/* PTU */
-	PINMUX_GPIO(GPIO_PTU7, PTU7_DATA),
-	PINMUX_GPIO(GPIO_PTU6, PTU6_DATA),
-	PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
-	PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
-	PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
-	PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
-	PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
-	PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+	PINMUX_GPIO(PTU7),
+	PINMUX_GPIO(PTU6),
+	PINMUX_GPIO(PTU5),
+	PINMUX_GPIO(PTU4),
+	PINMUX_GPIO(PTU3),
+	PINMUX_GPIO(PTU2),
+	PINMUX_GPIO(PTU1),
+	PINMUX_GPIO(PTU0),
 
 	/* PTV */
-	PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
-	PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
-	PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
-	PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
-	PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
-	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
-	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
-	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+	PINMUX_GPIO(PTV7),
+	PINMUX_GPIO(PTV6),
+	PINMUX_GPIO(PTV5),
+	PINMUX_GPIO(PTV4),
+	PINMUX_GPIO(PTV3),
+	PINMUX_GPIO(PTV2),
+	PINMUX_GPIO(PTV1),
+	PINMUX_GPIO(PTV0),
 
 	/* PTW */
-	PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
-	PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
-	PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
-	PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
-	PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
-	PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
-	PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
-	PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+	PINMUX_GPIO(PTW7),
+	PINMUX_GPIO(PTW6),
+	PINMUX_GPIO(PTW5),
+	PINMUX_GPIO(PTW4),
+	PINMUX_GPIO(PTW3),
+	PINMUX_GPIO(PTW2),
+	PINMUX_GPIO(PTW1),
+	PINMUX_GPIO(PTW0),
 
 	/* PTX */
-	PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
-	PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
-	PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
-	PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
-	PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
-	PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
-	PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
-	PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+	PINMUX_GPIO(PTX7),
+	PINMUX_GPIO(PTX6),
+	PINMUX_GPIO(PTX5),
+	PINMUX_GPIO(PTX4),
+	PINMUX_GPIO(PTX3),
+	PINMUX_GPIO(PTX2),
+	PINMUX_GPIO(PTX1),
+	PINMUX_GPIO(PTX0),
 
 	/* PTY */
-	PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
-	PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
-	PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
-	PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
-	PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
-	PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
-	PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
-	PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+	PINMUX_GPIO(PTY7),
+	PINMUX_GPIO(PTY6),
+	PINMUX_GPIO(PTY5),
+	PINMUX_GPIO(PTY4),
+	PINMUX_GPIO(PTY3),
+	PINMUX_GPIO(PTY2),
+	PINMUX_GPIO(PTY1),
+	PINMUX_GPIO(PTY0),
 
 	/* PTZ */
-	PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
-	PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
-	PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
-	PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
-	PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
-	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
-	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
-	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+	PINMUX_GPIO(PTZ7),
+	PINMUX_GPIO(PTZ6),
+	PINMUX_GPIO(PTZ5),
+	PINMUX_GPIO(PTZ4),
+	PINMUX_GPIO(PTZ3),
+	PINMUX_GPIO(PTZ2),
+	PINMUX_GPIO(PTZ1),
+	PINMUX_GPIO(PTZ0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -1789,64 +1743,64 @@ static const struct pinmux_func pinmux_func_gpios[] = {
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
-		PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
-		PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
-		PTA5_FN, PTA5_OUT, PTA5_IN_PU, PTA5_IN,
-		PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
-		PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
-		PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
-		PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
-		PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+		PTA7_FN, PTA7_OUT, 0, PTA7_IN,
+		PTA6_FN, PTA6_OUT, 0, PTA6_IN,
+		PTA5_FN, PTA5_OUT, 0, PTA5_IN,
+		PTA4_FN, PTA4_OUT, 0, PTA4_IN,
+		PTA3_FN, PTA3_OUT, 0, PTA3_IN,
+		PTA2_FN, PTA2_OUT, 0, PTA2_IN,
+		PTA1_FN, PTA1_OUT, 0, PTA1_IN,
+		PTA0_FN, PTA0_OUT, 0, PTA0_IN }
 	},
 	{ PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
-		PTB7_FN, PTB7_OUT, PTB7_IN_PU, PTB7_IN,
-		PTB6_FN, PTB6_OUT, PTB6_IN_PU, PTB6_IN,
-		PTB5_FN, PTB5_OUT, PTB5_IN_PU, PTB5_IN,
-		PTB4_FN, PTB4_OUT, PTB4_IN_PU, PTB4_IN,
-		PTB3_FN, PTB3_OUT, PTB3_IN_PU, PTB3_IN,
-		PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
-		PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
-		PTB0_FN, PTB0_OUT, PTB0_IN_PU, PTB0_IN }
+		PTB7_FN, PTB7_OUT, 0, PTB7_IN,
+		PTB6_FN, PTB6_OUT, 0, PTB6_IN,
+		PTB5_FN, PTB5_OUT, 0, PTB5_IN,
+		PTB4_FN, PTB4_OUT, 0, PTB4_IN,
+		PTB3_FN, PTB3_OUT, 0, PTB3_IN,
+		PTB2_FN, PTB2_OUT, 0, PTB2_IN,
+		PTB1_FN, PTB1_OUT, 0, PTB1_IN,
+		PTB0_FN, PTB0_OUT, 0, PTB0_IN }
 	},
 	{ PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
-		PTC7_FN, PTC7_OUT, PTC7_IN_PU, PTC7_IN,
-		PTC6_FN, PTC6_OUT, PTC6_IN_PU, PTC6_IN,
-		PTC5_FN, PTC5_OUT, PTC5_IN_PU, PTC5_IN,
-		PTC4_FN, PTC4_OUT, PTC4_IN_PU, PTC4_IN,
-		PTC3_FN, PTC3_OUT, PTC3_IN_PU, PTC3_IN,
-		PTC2_FN, PTC2_OUT, PTC2_IN_PU, PTC2_IN,
-		PTC1_FN, PTC1_OUT, PTC1_IN_PU, PTC1_IN,
-		PTC0_FN, PTC0_OUT, PTC0_IN_PU, PTC0_IN }
+		PTC7_FN, PTC7_OUT, 0, PTC7_IN,
+		PTC6_FN, PTC6_OUT, 0, PTC6_IN,
+		PTC5_FN, PTC5_OUT, 0, PTC5_IN,
+		PTC4_FN, PTC4_OUT, 0, PTC4_IN,
+		PTC3_FN, PTC3_OUT, 0, PTC3_IN,
+		PTC2_FN, PTC2_OUT, 0, PTC2_IN,
+		PTC1_FN, PTC1_OUT, 0, PTC1_IN,
+		PTC0_FN, PTC0_OUT, 0, PTC0_IN }
 	},
 	{ PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
-		PTD7_FN, PTD7_OUT, PTD7_IN_PU, PTD7_IN,
-		PTD6_FN, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
-		PTD5_FN, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
-		PTD4_FN, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
-		PTD3_FN, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
-		PTD2_FN, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
-		PTD1_FN, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
-		PTD0_FN, PTD0_OUT, PTD0_IN_PU, PTD0_IN }
+		PTD7_FN, PTD7_OUT, 0, PTD7_IN,
+		PTD6_FN, PTD6_OUT, 0, PTD6_IN,
+		PTD5_FN, PTD5_OUT, 0, PTD5_IN,
+		PTD4_FN, PTD4_OUT, 0, PTD4_IN,
+		PTD3_FN, PTD3_OUT, 0, PTD3_IN,
+		PTD2_FN, PTD2_OUT, 0, PTD2_IN,
+		PTD1_FN, PTD1_OUT, 0, PTD1_IN,
+		PTD0_FN, PTD0_OUT, 0, PTD0_IN }
 	},
 	{ PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
-		PTE7_FN, PTE7_OUT, PTE7_IN_PU, PTE7_IN,
-		PTE6_FN, PTE6_OUT, PTE6_IN_PU, PTE6_IN,
-		PTE5_FN, PTE5_OUT, PTE5_IN_PU, PTE5_IN,
-		PTE4_FN, PTE4_OUT, PTE4_IN_PU, PTE4_IN,
-		PTE3_FN, PTE3_OUT, PTE3_IN_PU, PTE3_IN,
-		PTE2_FN, PTE2_OUT, PTE2_IN_PU, PTE2_IN,
-		PTE1_FN, PTE1_OUT, PTE1_IN_PU, PTE1_IN,
-		PTE0_FN, PTE0_OUT, PTE0_IN_PU, PTE0_IN }
+		PTE7_FN, PTE7_OUT, 0, PTE7_IN,
+		PTE6_FN, PTE6_OUT, 0, PTE6_IN,
+		PTE5_FN, PTE5_OUT, 0, PTE5_IN,
+		PTE4_FN, PTE4_OUT, 0, PTE4_IN,
+		PTE3_FN, PTE3_OUT, 0, PTE3_IN,
+		PTE2_FN, PTE2_OUT, 0, PTE2_IN,
+		PTE1_FN, PTE1_OUT, 0, PTE1_IN,
+		PTE0_FN, PTE0_OUT, 0, PTE0_IN }
 	},
 	{ PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
-		PTF7_FN, PTF7_OUT, PTF7_IN_PU, PTF7_IN,
-		PTF6_FN, PTF6_OUT, PTF6_IN_PU, PTF6_IN,
-		PTF5_FN, PTF5_OUT, PTF5_IN_PU, PTF5_IN,
-		PTF4_FN, PTF4_OUT, PTF4_IN_PU, PTF4_IN,
-		PTF3_FN, PTF3_OUT, PTF3_IN_PU, PTF3_IN,
-		PTF2_FN, PTF2_OUT, PTF2_IN_PU, PTF2_IN,
-		PTF1_FN, PTF1_OUT, PTF1_IN_PU, PTF1_IN,
-		PTF0_FN, PTF0_OUT, PTF0_IN_PU, PTF0_IN }
+		PTF7_FN, PTF7_OUT, 0, PTF7_IN,
+		PTF6_FN, PTF6_OUT, 0, PTF6_IN,
+		PTF5_FN, PTF5_OUT, 0, PTF5_IN,
+		PTF4_FN, PTF4_OUT, 0, PTF4_IN,
+		PTF3_FN, PTF3_OUT, 0, PTF3_IN,
+		PTF2_FN, PTF2_OUT, 0, PTF2_IN,
+		PTF1_FN, PTF1_OUT, 0, PTF1_IN,
+		PTF0_FN, PTF0_OUT, 0, PTF0_IN }
 	},
 	{ PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
 		0, 0, 0, 0,
@@ -1859,164 +1813,164 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTG0_FN, PTG0_OUT, 0, 0 }
 	},
 	{ PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
-		PTH7_FN, PTH7_OUT, PTH7_IN_PU, PTH7_IN,
-		PTH6_FN, PTH6_OUT, PTH6_IN_PU, PTH6_IN,
-		PTH5_FN, PTH5_OUT, PTH5_IN_PU, PTH5_IN,
-		PTH4_FN, PTH4_OUT, PTH4_IN_PU, PTH4_IN,
-		PTH3_FN, PTH3_OUT, PTH3_IN_PU, PTH3_IN,
-		PTH2_FN, PTH2_OUT, PTH2_IN_PU, PTH2_IN,
-		PTH1_FN, PTH1_OUT, PTH1_IN_PU, PTH1_IN,
-		PTH0_FN, PTH0_OUT, PTH0_IN_PU, PTH0_IN }
+		PTH7_FN, PTH7_OUT, 0, PTH7_IN,
+		PTH6_FN, PTH6_OUT, 0, PTH6_IN,
+		PTH5_FN, PTH5_OUT, 0, PTH5_IN,
+		PTH4_FN, PTH4_OUT, 0, PTH4_IN,
+		PTH3_FN, PTH3_OUT, 0, PTH3_IN,
+		PTH2_FN, PTH2_OUT, 0, PTH2_IN,
+		PTH1_FN, PTH1_OUT, 0, PTH1_IN,
+		PTH0_FN, PTH0_OUT, 0, PTH0_IN }
 	},
 	{ PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
 		PTJ7_FN, PTJ7_OUT, 0, 0,
 		PTJ6_FN, PTJ6_OUT, 0, 0,
 		PTJ5_FN, PTJ5_OUT, 0, 0,
 		0, 0, 0, 0,
-		PTJ3_FN, PTJ3_OUT, PTJ3_IN_PU, PTJ3_IN,
-		PTJ2_FN, PTJ2_OUT, PTJ2_IN_PU, PTJ2_IN,
-		PTJ1_FN, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
-		PTJ0_FN, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+		PTJ3_FN, PTJ3_OUT, 0, PTJ3_IN,
+		PTJ2_FN, PTJ2_OUT, 0, PTJ2_IN,
+		PTJ1_FN, PTJ1_OUT, 0, PTJ1_IN,
+		PTJ0_FN, PTJ0_OUT, 0, PTJ0_IN }
 	},
 	{ PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
-		PTK7_FN, PTK7_OUT, PTK7_IN_PU, PTK7_IN,
-		PTK6_FN, PTK6_OUT, PTK6_IN_PU, PTK6_IN,
-		PTK5_FN, PTK5_OUT, PTK5_IN_PU, PTK5_IN,
-		PTK4_FN, PTK4_OUT, PTK4_IN_PU, PTK4_IN,
-		PTK3_FN, PTK3_OUT, PTK3_IN_PU, PTK3_IN,
-		PTK2_FN, PTK2_OUT, PTK2_IN_PU, PTK2_IN,
-		PTK1_FN, PTK1_OUT, PTK1_IN_PU, PTK1_IN,
-		PTK0_FN, PTK0_OUT, PTK0_IN_PU, PTK0_IN }
+		PTK7_FN, PTK7_OUT, 0, PTK7_IN,
+		PTK6_FN, PTK6_OUT, 0, PTK6_IN,
+		PTK5_FN, PTK5_OUT, 0, PTK5_IN,
+		PTK4_FN, PTK4_OUT, 0, PTK4_IN,
+		PTK3_FN, PTK3_OUT, 0, PTK3_IN,
+		PTK2_FN, PTK2_OUT, 0, PTK2_IN,
+		PTK1_FN, PTK1_OUT, 0, PTK1_IN,
+		PTK0_FN, PTK0_OUT, 0, PTK0_IN }
 	},
 	{ PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
-		PTL7_FN, PTL7_OUT, PTL7_IN_PU, PTL7_IN,
-		PTL6_FN, PTL6_OUT, PTL6_IN_PU, PTL6_IN,
-		PTL5_FN, PTL5_OUT, PTL5_IN_PU, PTL5_IN,
-		PTL4_FN, PTL4_OUT, PTL4_IN_PU, PTL4_IN,
-		PTL3_FN, PTL3_OUT, PTL3_IN_PU, PTL3_IN,
-		PTL2_FN, PTL2_OUT, PTL2_IN_PU, PTL2_IN,
-		PTL1_FN, PTL1_OUT, PTL1_IN_PU, PTL1_IN,
-		PTL0_FN, PTL0_OUT, PTL0_IN_PU, PTL0_IN }
+		PTL7_FN, PTL7_OUT, 0, PTL7_IN,
+		PTL6_FN, PTL6_OUT, 0, PTL6_IN,
+		PTL5_FN, PTL5_OUT, 0, PTL5_IN,
+		PTL4_FN, PTL4_OUT, 0, PTL4_IN,
+		PTL3_FN, PTL3_OUT, 0, PTL3_IN,
+		PTL2_FN, PTL2_OUT, 0, PTL2_IN,
+		PTL1_FN, PTL1_OUT, 0, PTL1_IN,
+		PTL0_FN, PTL0_OUT, 0, PTL0_IN }
 	},
 	{ PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
-		PTM7_FN, PTM7_OUT, PTM7_IN_PU, PTM7_IN,
-		PTM6_FN, PTM6_OUT, PTM6_IN_PU, PTM6_IN,
-		PTM5_FN, PTM5_OUT, PTM5_IN_PU, PTM5_IN,
-		PTM4_FN, PTM4_OUT, PTM4_IN_PU, PTM4_IN,
-		PTM3_FN, PTM3_OUT, PTM3_IN_PU, PTM3_IN,
-		PTM2_FN, PTM2_OUT, PTM2_IN_PU, PTM2_IN,
-		PTM1_FN, PTM1_OUT, PTM1_IN_PU, PTM1_IN,
-		PTM0_FN, PTM0_OUT, PTM0_IN_PU, PTM0_IN }
+		PTM7_FN, PTM7_OUT, 0, PTM7_IN,
+		PTM6_FN, PTM6_OUT, 0, PTM6_IN,
+		PTM5_FN, PTM5_OUT, 0, PTM5_IN,
+		PTM4_FN, PTM4_OUT, 0, PTM4_IN,
+		PTM3_FN, PTM3_OUT, 0, PTM3_IN,
+		PTM2_FN, PTM2_OUT, 0, PTM2_IN,
+		PTM1_FN, PTM1_OUT, 0, PTM1_IN,
+		PTM0_FN, PTM0_OUT, 0, PTM0_IN }
 	},
 	{ PINMUX_CFG_REG("PNCR", 0xa4050118, 16, 2) {
-		PTN7_FN, PTN7_OUT, PTN7_IN_PU, PTN7_IN,
-		PTN6_FN, PTN6_OUT, PTN6_IN_PU, PTN6_IN,
-		PTN5_FN, PTN5_OUT, PTN5_IN_PU, PTN5_IN,
-		PTN4_FN, PTN4_OUT, PTN4_IN_PU, PTN4_IN,
-		PTN3_FN, PTN3_OUT, PTN3_IN_PU, PTN3_IN,
-		PTN2_FN, PTN2_OUT, PTN2_IN_PU, PTN2_IN,
-		PTN1_FN, PTN1_OUT, PTN1_IN_PU, PTN1_IN,
-		PTN0_FN, PTN0_OUT, PTN0_IN_PU, PTN0_IN }
+		PTN7_FN, PTN7_OUT, 0, PTN7_IN,
+		PTN6_FN, PTN6_OUT, 0, PTN6_IN,
+		PTN5_FN, PTN5_OUT, 0, PTN5_IN,
+		PTN4_FN, PTN4_OUT, 0, PTN4_IN,
+		PTN3_FN, PTN3_OUT, 0, PTN3_IN,
+		PTN2_FN, PTN2_OUT, 0, PTN2_IN,
+		PTN1_FN, PTN1_OUT, 0, PTN1_IN,
+		PTN0_FN, PTN0_OUT, 0, PTN0_IN }
 	},
 	{ PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2) {
-		PTQ7_FN, PTQ7_OUT, PTQ7_IN_PU, PTQ7_IN,
-		PTQ6_FN, PTQ6_OUT, PTQ6_IN_PU, PTQ6_IN,
-		PTQ5_FN, PTQ5_OUT, PTQ5_IN_PU, PTQ5_IN,
-		PTQ4_FN, PTQ4_OUT, PTQ4_IN_PU, PTQ4_IN,
-		PTQ3_FN, PTQ3_OUT, PTQ3_IN_PU, PTQ3_IN,
-		PTQ2_FN, PTQ2_OUT, PTQ2_IN_PU, PTQ2_IN,
-		PTQ1_FN, PTQ1_OUT, PTQ1_IN_PU, PTQ1_IN,
-		PTQ0_FN, PTQ0_OUT, PTQ0_IN_PU, PTQ0_IN }
+		PTQ7_FN, PTQ7_OUT, 0, PTQ7_IN,
+		PTQ6_FN, PTQ6_OUT, 0, PTQ6_IN,
+		PTQ5_FN, PTQ5_OUT, 0, PTQ5_IN,
+		PTQ4_FN, PTQ4_OUT, 0, PTQ4_IN,
+		PTQ3_FN, PTQ3_OUT, 0, PTQ3_IN,
+		PTQ2_FN, PTQ2_OUT, 0, PTQ2_IN,
+		PTQ1_FN, PTQ1_OUT, 0, PTQ1_IN,
+		PTQ0_FN, PTQ0_OUT, 0, PTQ0_IN }
 	},
 	{ PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2) {
-		PTR7_FN, PTR7_OUT, PTR7_IN_PU, PTR7_IN,
-		PTR6_FN, PTR6_OUT, PTR6_IN_PU, PTR6_IN,
-		PTR5_FN, PTR5_OUT, PTR5_IN_PU, PTR5_IN,
-		PTR4_FN, PTR4_OUT, PTR4_IN_PU, PTR4_IN,
-		PTR3_FN, 0,        PTR3_IN_PU, PTR3_IN,
-		PTR2_FN, 0,        PTR2_IN_PU, PTR2_IN,
-		PTR1_FN, PTR1_OUT, PTR1_IN_PU, PTR1_IN,
-		PTR0_FN, PTR0_OUT, PTR0_IN_PU, PTR0_IN }
+		PTR7_FN, PTR7_OUT, 0, PTR7_IN,
+		PTR6_FN, PTR6_OUT, 0, PTR6_IN,
+		PTR5_FN, PTR5_OUT, 0, PTR5_IN,
+		PTR4_FN, PTR4_OUT, 0, PTR4_IN,
+		PTR3_FN, 0,        0, PTR3_IN,
+		PTR2_FN, 0,        0, PTR2_IN,
+		PTR1_FN, PTR1_OUT, 0, PTR1_IN,
+		PTR0_FN, PTR0_OUT, 0, PTR0_IN }
 	},
 	{ PINMUX_CFG_REG("PSCR", 0xa405011e, 16, 2) {
 		0, 0, 0, 0,
-		PTS6_FN, PTS6_OUT, PTS6_IN_PU, PTS6_IN,
-		PTS5_FN, PTS5_OUT, PTS5_IN_PU, PTS5_IN,
-		PTS4_FN, PTS4_OUT, PTS4_IN_PU, PTS4_IN,
-		PTS3_FN, PTS3_OUT, PTS3_IN_PU, PTS3_IN,
-		PTS2_FN, PTS2_OUT, PTS2_IN_PU, PTS2_IN,
-		PTS1_FN, PTS1_OUT, PTS1_IN_PU, PTS1_IN,
-		PTS0_FN, PTS0_OUT, PTS0_IN_PU, PTS0_IN }
+		PTS6_FN, PTS6_OUT, 0, PTS6_IN,
+		PTS5_FN, PTS5_OUT, 0, PTS5_IN,
+		PTS4_FN, PTS4_OUT, 0, PTS4_IN,
+		PTS3_FN, PTS3_OUT, 0, PTS3_IN,
+		PTS2_FN, PTS2_OUT, 0, PTS2_IN,
+		PTS1_FN, PTS1_OUT, 0, PTS1_IN,
+		PTS0_FN, PTS0_OUT, 0, PTS0_IN }
 	},
 	{ PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2) {
-		PTT7_FN, PTT7_OUT, PTT7_IN_PU, PTT7_IN,
-		PTT6_FN, PTT6_OUT, PTT6_IN_PU, PTT6_IN,
-		PTT5_FN, PTT5_OUT, PTT5_IN_PU, PTT5_IN,
-		PTT4_FN, PTT4_OUT, PTT4_IN_PU, PTT4_IN,
-		PTT3_FN, PTT3_OUT, PTT3_IN_PU, PTT3_IN,
-		PTT2_FN, PTT2_OUT, PTT2_IN_PU, PTT2_IN,
-		PTT1_FN, PTT1_OUT, PTT1_IN_PU, PTT1_IN,
-		PTT0_FN, PTT0_OUT, PTT0_IN_PU, PTT0_IN }
+		PTT7_FN, PTT7_OUT, 0, PTT7_IN,
+		PTT6_FN, PTT6_OUT, 0, PTT6_IN,
+		PTT5_FN, PTT5_OUT, 0, PTT5_IN,
+		PTT4_FN, PTT4_OUT, 0, PTT4_IN,
+		PTT3_FN, PTT3_OUT, 0, PTT3_IN,
+		PTT2_FN, PTT2_OUT, 0, PTT2_IN,
+		PTT1_FN, PTT1_OUT, 0, PTT1_IN,
+		PTT0_FN, PTT0_OUT, 0, PTT0_IN }
 	},
 	{ PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2) {
-		PTU7_FN, PTU7_OUT, PTU7_IN_PU, PTU7_IN,
-		PTU6_FN, PTU6_OUT, PTU6_IN_PU, PTU6_IN,
-		PTU5_FN, PTU5_OUT, PTU5_IN_PU, PTU5_IN,
-		PTU4_FN, PTU4_OUT, PTU4_IN_PU, PTU4_IN,
-		PTU3_FN, PTU3_OUT, PTU3_IN_PU, PTU3_IN,
-		PTU2_FN, PTU2_OUT, PTU2_IN_PU, PTU2_IN,
-		PTU1_FN, PTU1_OUT, PTU1_IN_PU, PTU1_IN,
-		PTU0_FN, PTU0_OUT, PTU0_IN_PU, PTU0_IN }
+		PTU7_FN, PTU7_OUT, 0, PTU7_IN,
+		PTU6_FN, PTU6_OUT, 0, PTU6_IN,
+		PTU5_FN, PTU5_OUT, 0, PTU5_IN,
+		PTU4_FN, PTU4_OUT, 0, PTU4_IN,
+		PTU3_FN, PTU3_OUT, 0, PTU3_IN,
+		PTU2_FN, PTU2_OUT, 0, PTU2_IN,
+		PTU1_FN, PTU1_OUT, 0, PTU1_IN,
+		PTU0_FN, PTU0_OUT, 0, PTU0_IN }
 	},
 	{ PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2) {
-		PTV7_FN, PTV7_OUT, PTV7_IN_PU, PTV7_IN,
-		PTV6_FN, PTV6_OUT, PTV6_IN_PU, PTV6_IN,
-		PTV5_FN, PTV5_OUT, PTV5_IN_PU, PTV5_IN,
-		PTV4_FN, PTV4_OUT, PTV4_IN_PU, PTV4_IN,
-		PTV3_FN, PTV3_OUT, PTV3_IN_PU, PTV3_IN,
-		PTV2_FN, PTV2_OUT, PTV2_IN_PU, PTV2_IN,
-		PTV1_FN, PTV1_OUT, PTV1_IN_PU, PTV1_IN,
-		PTV0_FN, PTV0_OUT, PTV0_IN_PU, PTV0_IN }
+		PTV7_FN, PTV7_OUT, 0, PTV7_IN,
+		PTV6_FN, PTV6_OUT, 0, PTV6_IN,
+		PTV5_FN, PTV5_OUT, 0, PTV5_IN,
+		PTV4_FN, PTV4_OUT, 0, PTV4_IN,
+		PTV3_FN, PTV3_OUT, 0, PTV3_IN,
+		PTV2_FN, PTV2_OUT, 0, PTV2_IN,
+		PTV1_FN, PTV1_OUT, 0, PTV1_IN,
+		PTV0_FN, PTV0_OUT, 0, PTV0_IN }
 	},
 	{ PINMUX_CFG_REG("PWCR", 0xa4050146, 16, 2) {
-		PTW7_FN, PTW7_OUT, PTW7_IN_PU, PTW7_IN,
-		PTW6_FN, PTW6_OUT, PTW6_IN_PU, PTW6_IN,
-		PTW5_FN, PTW5_OUT, PTW5_IN_PU, PTW5_IN,
-		PTW4_FN, PTW4_OUT, PTW4_IN_PU, PTW4_IN,
-		PTW3_FN, PTW3_OUT, PTW3_IN_PU, PTW3_IN,
-		PTW2_FN, PTW2_OUT, PTW2_IN_PU, PTW2_IN,
-		PTW1_FN, PTW1_OUT, PTW1_IN_PU, PTW1_IN,
-		PTW0_FN, PTW0_OUT, PTW0_IN_PU, PTW0_IN }
+		PTW7_FN, PTW7_OUT, 0, PTW7_IN,
+		PTW6_FN, PTW6_OUT, 0, PTW6_IN,
+		PTW5_FN, PTW5_OUT, 0, PTW5_IN,
+		PTW4_FN, PTW4_OUT, 0, PTW4_IN,
+		PTW3_FN, PTW3_OUT, 0, PTW3_IN,
+		PTW2_FN, PTW2_OUT, 0, PTW2_IN,
+		PTW1_FN, PTW1_OUT, 0, PTW1_IN,
+		PTW0_FN, PTW0_OUT, 0, PTW0_IN }
 	},
 	{ PINMUX_CFG_REG("PXCR", 0xa4050148, 16, 2) {
-		PTX7_FN, PTX7_OUT, PTX7_IN_PU, PTX7_IN,
-		PTX6_FN, PTX6_OUT, PTX6_IN_PU, PTX6_IN,
-		PTX5_FN, PTX5_OUT, PTX5_IN_PU, PTX5_IN,
-		PTX4_FN, PTX4_OUT, PTX4_IN_PU, PTX4_IN,
-		PTX3_FN, PTX3_OUT, PTX3_IN_PU, PTX3_IN,
-		PTX2_FN, PTX2_OUT, PTX2_IN_PU, PTX2_IN,
-		PTX1_FN, PTX1_OUT, PTX1_IN_PU, PTX1_IN,
-		PTX0_FN, PTX0_OUT, PTX0_IN_PU, PTX0_IN }
+		PTX7_FN, PTX7_OUT, 0, PTX7_IN,
+		PTX6_FN, PTX6_OUT, 0, PTX6_IN,
+		PTX5_FN, PTX5_OUT, 0, PTX5_IN,
+		PTX4_FN, PTX4_OUT, 0, PTX4_IN,
+		PTX3_FN, PTX3_OUT, 0, PTX3_IN,
+		PTX2_FN, PTX2_OUT, 0, PTX2_IN,
+		PTX1_FN, PTX1_OUT, 0, PTX1_IN,
+		PTX0_FN, PTX0_OUT, 0, PTX0_IN }
 	},
 	{ PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2) {
-		PTY7_FN, PTY7_OUT, PTY7_IN_PU, PTY7_IN,
-		PTY6_FN, PTY6_OUT, PTY6_IN_PU, PTY6_IN,
-		PTY5_FN, PTY5_OUT, PTY5_IN_PU, PTY5_IN,
-		PTY4_FN, PTY4_OUT, PTY4_IN_PU, PTY4_IN,
-		PTY3_FN, PTY3_OUT, PTY3_IN_PU, PTY3_IN,
-		PTY2_FN, PTY2_OUT, PTY2_IN_PU, PTY2_IN,
-		PTY1_FN, PTY1_OUT, PTY1_IN_PU, PTY1_IN,
-		PTY0_FN, PTY0_OUT, PTY0_IN_PU, PTY0_IN }
+		PTY7_FN, PTY7_OUT, 0, PTY7_IN,
+		PTY6_FN, PTY6_OUT, 0, PTY6_IN,
+		PTY5_FN, PTY5_OUT, 0, PTY5_IN,
+		PTY4_FN, PTY4_OUT, 0, PTY4_IN,
+		PTY3_FN, PTY3_OUT, 0, PTY3_IN,
+		PTY2_FN, PTY2_OUT, 0, PTY2_IN,
+		PTY1_FN, PTY1_OUT, 0, PTY1_IN,
+		PTY0_FN, PTY0_OUT, 0, PTY0_IN }
 	},
 	{ PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2) {
-		PTZ7_FN, PTZ7_OUT, PTZ7_IN_PU, PTZ7_IN,
-		PTZ6_FN, PTZ6_OUT, PTZ6_IN_PU, PTZ6_IN,
-		PTZ5_FN, PTZ5_OUT, PTZ5_IN_PU, PTZ5_IN,
-		PTZ4_FN, PTZ4_OUT, PTZ4_IN_PU, PTZ4_IN,
-		PTZ3_FN, PTZ3_OUT, PTZ3_IN_PU, PTZ3_IN,
-		PTZ2_FN, PTZ2_OUT, PTZ2_IN_PU, PTZ2_IN,
-		PTZ1_FN, PTZ1_OUT, PTZ1_IN_PU, PTZ1_IN,
-		PTZ0_FN, PTZ0_OUT, PTZ0_IN_PU, PTZ0_IN }
+		PTZ7_FN, PTZ7_OUT, 0, PTZ7_IN,
+		PTZ6_FN, PTZ6_OUT, 0, PTZ6_IN,
+		PTZ5_FN, PTZ5_OUT, 0, PTZ5_IN,
+		PTZ4_FN, PTZ4_OUT, 0, PTZ4_IN,
+		PTZ3_FN, PTZ3_OUT, 0, PTZ3_IN,
+		PTZ2_FN, PTZ2_OUT, 0, PTZ2_IN,
+		PTZ1_FN, PTZ1_OUT, 0, PTZ1_IN,
+		PTZ0_FN, PTZ0_OUT, 0, PTZ0_IN }
 	},
 	{ PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 1) {
 		PSA15_0, PSA15_1,
@@ -2210,7 +2164,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7724_pinmux_info = {
 	.name = "sh7724_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7734.c b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
index 2fd5b7d..ec0c47c 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7734.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
@@ -14,40 +14,30 @@
 
 #include "sh_pfc.h"
 
-#define CPU_32_PORT5(fn, pfx, sfx)				\
-	PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx),	\
-	PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx),	\
-	PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx),	\
-	PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx),	\
-	PORT_1(fn, pfx##8, sfx), PORT_1(fn, pfx##9, sfx),	\
-	PORT_1(fn, pfx##10, sfx), PORT_1(fn, pfx##11, sfx)
-
-/* GPSR0 - GPSR5 */
-#define CPU_ALL_PORT(fn, pfx, sfx)				\
-	PORT_32(fn, pfx##_0_, sfx),			\
-	PORT_32(fn, pfx##_1_, sfx),				\
-	PORT_32(fn, pfx##_2_, sfx),				\
-	PORT_32(fn, pfx##_3_, sfx),				\
-	PORT_32(fn, pfx##_4_, sfx),				\
-	CPU_32_PORT5(fn, pfx##_5_, sfx)
-
-#define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA)
-#define _GP_DATA(pfx, sfx) PINMUX_DATA(GP##pfx##_DATA, GP##pfx##_FN,	\
-				       GP##pfx##_IN, GP##pfx##_OUT)
-
-#define _GP_INOUTSEL(pfx, sfx) GP##pfx##_IN, GP##pfx##_OUT
-#define _GP_INDT(pfx, sfx) GP##pfx##_DATA
-
-#define GP_ALL(str)	CPU_ALL_PORT(_PORT_ALL, GP, str)
-#define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, , unused)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, , unused)
-
-#define GP_INOUTSEL(bank) PORT_32_REV(_GP_INOUTSEL, _##bank##_, unused)
-#define GP_INDT(bank) PORT_32_REV(_GP_INDT, _##bank##_, unused)
-
-#define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn)
-#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \
-							  FN_##ipsr, FN_##fn)
+#define PORT_GP_12(bank, fn, sfx)					\
+	PORT_GP_1(bank, 0, fn, sfx),  PORT_GP_1(bank, 1, fn, sfx),	\
+	PORT_GP_1(bank, 2, fn, sfx),  PORT_GP_1(bank, 3, fn, sfx),	\
+	PORT_GP_1(bank, 4, fn, sfx),  PORT_GP_1(bank, 5, fn, sfx),	\
+	PORT_GP_1(bank, 6, fn, sfx),  PORT_GP_1(bank, 7, fn, sfx),	\
+	PORT_GP_1(bank, 8, fn, sfx),  PORT_GP_1(bank, 9, fn, sfx),	\
+	PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx)
+
+#define CPU_ALL_PORT(fn, sfx)						\
+	PORT_GP_32(0, fn, sfx),						\
+	PORT_GP_32(1, fn, sfx),						\
+	PORT_GP_32(2, fn, sfx),						\
+	PORT_GP_32(3, fn, sfx),						\
+	PORT_GP_32(4, fn, sfx),						\
+	PORT_GP_12(5, fn, sfx)
+
+#undef _GP_DATA
+#define _GP_DATA(bank, pin, name, sfx)					\
+	PINMUX_DATA(name##_DATA, name##_FN, name##_IN, name##_OUT)
+
+#define _GP_INOUTSEL(bank, pin, name, sfx)	name##_IN, name##_OUT
+#define _GP_INDT(bank, pin, name, sfx)		name##_DATA
+#define GP_INOUTSEL(bank)	PORT_GP_32_REV(bank, _GP_INOUTSEL, unused)
+#define GP_INDT(bank)		PORT_GP_32_REV(bank, _GP_INDT, unused)
 
 enum {
 	PINMUX_RESERVED = 0,
@@ -592,7 +582,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
 
 	PINMUX_DATA(CLKOUT_MARK, FN_CLKOUT),
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7757.c b/drivers/pinctrl/sh-pfc/pfc-sh7757.c
index e074230..33d75e5 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7757.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7757.c
@@ -132,46 +132,6 @@ enum {
 	PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
 	PINMUX_INPUT_END,
 
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
-	PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
-	PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
-	PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
-	PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU,
-	PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
-	PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU,
-	PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU,
-	PTG7_IN_PU, PTG6_IN_PU,		    PTG4_IN_PU,
-	PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
-	PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
-	PTI7_IN_PU, PTI6_IN_PU,		    PTI4_IN_PU,
-	PTI3_IN_PU, PTI2_IN_PU, PTI1_IN_PU, PTI0_IN_PU,
-		    PTJ6_IN_PU, PTJ5_IN_PU, PTJ4_IN_PU,
-	PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
-	PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU,
-	PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
-		    PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU,
-	PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU,
-	PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
-					    PTN4_IN_PU,
-	PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU,
-	PTO7_IN_PU, PTO6_IN_PU, PTO5_IN_PU, PTO4_IN_PU,
-	PTO3_IN_PU, PTO2_IN_PU, PTO1_IN_PU, PTO0_IN_PU,
-	PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU,
-	PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
-	PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
-	PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
-	PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
-	PTV3_IN_PU, PTV2_IN_PU,
-				PTW1_IN_PU, PTW0_IN_PU,
-	PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
-	PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
-	PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
-	PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
-	PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU,
-	PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU,
-	PINMUX_INPUT_PULLUP_END,
-
 	PINMUX_OUTPUT_BEGIN,
 	PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
 	PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
@@ -526,7 +486,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
+static const u16 pinmux_data[] = {
 	/* PTA GPIO */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
@@ -1116,260 +1076,260 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
-	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
-	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
-	PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
-	PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
-	PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
-	PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
-	PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
-	PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+	PINMUX_GPIO(PTA7),
+	PINMUX_GPIO(PTA6),
+	PINMUX_GPIO(PTA5),
+	PINMUX_GPIO(PTA4),
+	PINMUX_GPIO(PTA3),
+	PINMUX_GPIO(PTA2),
+	PINMUX_GPIO(PTA1),
+	PINMUX_GPIO(PTA0),
 
 	/* PTB */
-	PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
-	PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
-	PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
-	PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
-	PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
-	PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
-	PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
-	PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+	PINMUX_GPIO(PTB7),
+	PINMUX_GPIO(PTB6),
+	PINMUX_GPIO(PTB5),
+	PINMUX_GPIO(PTB4),
+	PINMUX_GPIO(PTB3),
+	PINMUX_GPIO(PTB2),
+	PINMUX_GPIO(PTB1),
+	PINMUX_GPIO(PTB0),
 
 	/* PTC */
-	PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
-	PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
-	PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
-	PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
-	PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
-	PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
-	PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
-	PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+	PINMUX_GPIO(PTC7),
+	PINMUX_GPIO(PTC6),
+	PINMUX_GPIO(PTC5),
+	PINMUX_GPIO(PTC4),
+	PINMUX_GPIO(PTC3),
+	PINMUX_GPIO(PTC2),
+	PINMUX_GPIO(PTC1),
+	PINMUX_GPIO(PTC0),
 
 	/* PTD */
-	PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
-	PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
-	PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
-	PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
-	PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
-	PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
-	PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
-	PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+	PINMUX_GPIO(PTD7),
+	PINMUX_GPIO(PTD6),
+	PINMUX_GPIO(PTD5),
+	PINMUX_GPIO(PTD4),
+	PINMUX_GPIO(PTD3),
+	PINMUX_GPIO(PTD2),
+	PINMUX_GPIO(PTD1),
+	PINMUX_GPIO(PTD0),
 
 	/* PTE */
-	PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
-	PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
-	PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
-	PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
-	PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
-	PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
-	PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
-	PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+	PINMUX_GPIO(PTE7),
+	PINMUX_GPIO(PTE6),
+	PINMUX_GPIO(PTE5),
+	PINMUX_GPIO(PTE4),
+	PINMUX_GPIO(PTE3),
+	PINMUX_GPIO(PTE2),
+	PINMUX_GPIO(PTE1),
+	PINMUX_GPIO(PTE0),
 
 	/* PTF */
-	PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
-	PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
-	PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
-	PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
-	PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
-	PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
-	PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
-	PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+	PINMUX_GPIO(PTF7),
+	PINMUX_GPIO(PTF6),
+	PINMUX_GPIO(PTF5),
+	PINMUX_GPIO(PTF4),
+	PINMUX_GPIO(PTF3),
+	PINMUX_GPIO(PTF2),
+	PINMUX_GPIO(PTF1),
+	PINMUX_GPIO(PTF0),
 
 	/* PTG */
-	PINMUX_GPIO(GPIO_PTG7, PTG7_DATA),
-	PINMUX_GPIO(GPIO_PTG6, PTG6_DATA),
-	PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
-	PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
-	PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
-	PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
-	PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
-	PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+	PINMUX_GPIO(PTG7),
+	PINMUX_GPIO(PTG6),
+	PINMUX_GPIO(PTG5),
+	PINMUX_GPIO(PTG4),
+	PINMUX_GPIO(PTG3),
+	PINMUX_GPIO(PTG2),
+	PINMUX_GPIO(PTG1),
+	PINMUX_GPIO(PTG0),
 
 	/* PTH */
-	PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
-	PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
-	PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
-	PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
-	PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
-	PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
-	PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
-	PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+	PINMUX_GPIO(PTH7),
+	PINMUX_GPIO(PTH6),
+	PINMUX_GPIO(PTH5),
+	PINMUX_GPIO(PTH4),
+	PINMUX_GPIO(PTH3),
+	PINMUX_GPIO(PTH2),
+	PINMUX_GPIO(PTH1),
+	PINMUX_GPIO(PTH0),
 
 	/* PTI */
-	PINMUX_GPIO(GPIO_PTI7, PTI7_DATA),
-	PINMUX_GPIO(GPIO_PTI6, PTI6_DATA),
-	PINMUX_GPIO(GPIO_PTI5, PTI5_DATA),
-	PINMUX_GPIO(GPIO_PTI4, PTI4_DATA),
-	PINMUX_GPIO(GPIO_PTI3, PTI3_DATA),
-	PINMUX_GPIO(GPIO_PTI2, PTI2_DATA),
-	PINMUX_GPIO(GPIO_PTI1, PTI1_DATA),
-	PINMUX_GPIO(GPIO_PTI0, PTI0_DATA),
+	PINMUX_GPIO(PTI7),
+	PINMUX_GPIO(PTI6),
+	PINMUX_GPIO(PTI5),
+	PINMUX_GPIO(PTI4),
+	PINMUX_GPIO(PTI3),
+	PINMUX_GPIO(PTI2),
+	PINMUX_GPIO(PTI1),
+	PINMUX_GPIO(PTI0),
 
 	/* PTJ */
-	PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
-	PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
-	PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA),
-	PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
-	PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
-	PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
-	PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+	PINMUX_GPIO(PTJ6),
+	PINMUX_GPIO(PTJ5),
+	PINMUX_GPIO(PTJ4),
+	PINMUX_GPIO(PTJ3),
+	PINMUX_GPIO(PTJ2),
+	PINMUX_GPIO(PTJ1),
+	PINMUX_GPIO(PTJ0),
 
 	/* PTK */
-	PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
-	PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
-	PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
-	PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
-	PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
-	PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
-	PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
-	PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+	PINMUX_GPIO(PTK7),
+	PINMUX_GPIO(PTK6),
+	PINMUX_GPIO(PTK5),
+	PINMUX_GPIO(PTK4),
+	PINMUX_GPIO(PTK3),
+	PINMUX_GPIO(PTK2),
+	PINMUX_GPIO(PTK1),
+	PINMUX_GPIO(PTK0),
 
 	/* PTL */
-	PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
-	PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
-	PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
-	PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
-	PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
-	PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
-	PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+	PINMUX_GPIO(PTL6),
+	PINMUX_GPIO(PTL5),
+	PINMUX_GPIO(PTL4),
+	PINMUX_GPIO(PTL3),
+	PINMUX_GPIO(PTL2),
+	PINMUX_GPIO(PTL1),
+	PINMUX_GPIO(PTL0),
 
 	/* PTM */
-	PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
-	PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
-	PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
-	PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
-	PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
-	PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
-	PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
-	PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+	PINMUX_GPIO(PTM7),
+	PINMUX_GPIO(PTM6),
+	PINMUX_GPIO(PTM5),
+	PINMUX_GPIO(PTM4),
+	PINMUX_GPIO(PTM3),
+	PINMUX_GPIO(PTM2),
+	PINMUX_GPIO(PTM1),
+	PINMUX_GPIO(PTM0),
 
 	/* PTN */
-	PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
-	PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
-	PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
-	PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
-	PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
-	PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
-	PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+	PINMUX_GPIO(PTN6),
+	PINMUX_GPIO(PTN5),
+	PINMUX_GPIO(PTN4),
+	PINMUX_GPIO(PTN3),
+	PINMUX_GPIO(PTN2),
+	PINMUX_GPIO(PTN1),
+	PINMUX_GPIO(PTN0),
 
 	/* PTO */
-	PINMUX_GPIO(GPIO_PTO7, PTO7_DATA),
-	PINMUX_GPIO(GPIO_PTO6, PTO6_DATA),
-	PINMUX_GPIO(GPIO_PTO5, PTO5_DATA),
-	PINMUX_GPIO(GPIO_PTO4, PTO4_DATA),
-	PINMUX_GPIO(GPIO_PTO3, PTO3_DATA),
-	PINMUX_GPIO(GPIO_PTO2, PTO2_DATA),
-	PINMUX_GPIO(GPIO_PTO1, PTO1_DATA),
-	PINMUX_GPIO(GPIO_PTO0, PTO0_DATA),
+	PINMUX_GPIO(PTO7),
+	PINMUX_GPIO(PTO6),
+	PINMUX_GPIO(PTO5),
+	PINMUX_GPIO(PTO4),
+	PINMUX_GPIO(PTO3),
+	PINMUX_GPIO(PTO2),
+	PINMUX_GPIO(PTO1),
+	PINMUX_GPIO(PTO0),
 
 	/* PTP */
-	PINMUX_GPIO(GPIO_PTP7, PTP7_DATA),
-	PINMUX_GPIO(GPIO_PTP6, PTP6_DATA),
-	PINMUX_GPIO(GPIO_PTP5, PTP5_DATA),
-	PINMUX_GPIO(GPIO_PTP4, PTP4_DATA),
-	PINMUX_GPIO(GPIO_PTP3, PTP3_DATA),
-	PINMUX_GPIO(GPIO_PTP2, PTP2_DATA),
-	PINMUX_GPIO(GPIO_PTP1, PTP1_DATA),
-	PINMUX_GPIO(GPIO_PTP0, PTP0_DATA),
+	PINMUX_GPIO(PTP7),
+	PINMUX_GPIO(PTP6),
+	PINMUX_GPIO(PTP5),
+	PINMUX_GPIO(PTP4),
+	PINMUX_GPIO(PTP3),
+	PINMUX_GPIO(PTP2),
+	PINMUX_GPIO(PTP1),
+	PINMUX_GPIO(PTP0),
 
 	/* PTQ */
-	PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
-	PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
-	PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
-	PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
-	PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
-	PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
-	PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+	PINMUX_GPIO(PTQ6),
+	PINMUX_GPIO(PTQ5),
+	PINMUX_GPIO(PTQ4),
+	PINMUX_GPIO(PTQ3),
+	PINMUX_GPIO(PTQ2),
+	PINMUX_GPIO(PTQ1),
+	PINMUX_GPIO(PTQ0),
 
 	/* PTR */
-	PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
-	PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
-	PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
-	PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
-	PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
-	PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
-	PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
-	PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+	PINMUX_GPIO(PTR7),
+	PINMUX_GPIO(PTR6),
+	PINMUX_GPIO(PTR5),
+	PINMUX_GPIO(PTR4),
+	PINMUX_GPIO(PTR3),
+	PINMUX_GPIO(PTR2),
+	PINMUX_GPIO(PTR1),
+	PINMUX_GPIO(PTR0),
 
 	/* PTS */
-	PINMUX_GPIO(GPIO_PTS7, PTS7_DATA),
-	PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
-	PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
-	PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
-	PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
-	PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
-	PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
-	PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+	PINMUX_GPIO(PTS7),
+	PINMUX_GPIO(PTS6),
+	PINMUX_GPIO(PTS5),
+	PINMUX_GPIO(PTS4),
+	PINMUX_GPIO(PTS3),
+	PINMUX_GPIO(PTS2),
+	PINMUX_GPIO(PTS1),
+	PINMUX_GPIO(PTS0),
 
 	/* PTT */
-	PINMUX_GPIO(GPIO_PTT7, PTT7_DATA),
-	PINMUX_GPIO(GPIO_PTT6, PTT6_DATA),
-	PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
-	PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
-	PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
-	PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
-	PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
-	PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+	PINMUX_GPIO(PTT7),
+	PINMUX_GPIO(PTT6),
+	PINMUX_GPIO(PTT5),
+	PINMUX_GPIO(PTT4),
+	PINMUX_GPIO(PTT3),
+	PINMUX_GPIO(PTT2),
+	PINMUX_GPIO(PTT1),
+	PINMUX_GPIO(PTT0),
 
 	/* PTU */
-	PINMUX_GPIO(GPIO_PTU7, PTU7_DATA),
-	PINMUX_GPIO(GPIO_PTU6, PTU6_DATA),
-	PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
-	PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
-	PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
-	PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
-	PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
-	PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+	PINMUX_GPIO(PTU7),
+	PINMUX_GPIO(PTU6),
+	PINMUX_GPIO(PTU5),
+	PINMUX_GPIO(PTU4),
+	PINMUX_GPIO(PTU3),
+	PINMUX_GPIO(PTU2),
+	PINMUX_GPIO(PTU1),
+	PINMUX_GPIO(PTU0),
 
 	/* PTV */
-	PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
-	PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
-	PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
-	PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
-	PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
-	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
-	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
-	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+	PINMUX_GPIO(PTV7),
+	PINMUX_GPIO(PTV6),
+	PINMUX_GPIO(PTV5),
+	PINMUX_GPIO(PTV4),
+	PINMUX_GPIO(PTV3),
+	PINMUX_GPIO(PTV2),
+	PINMUX_GPIO(PTV1),
+	PINMUX_GPIO(PTV0),
 
 	/* PTW */
-	PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
-	PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
-	PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
-	PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
-	PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
-	PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
-	PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
-	PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+	PINMUX_GPIO(PTW7),
+	PINMUX_GPIO(PTW6),
+	PINMUX_GPIO(PTW5),
+	PINMUX_GPIO(PTW4),
+	PINMUX_GPIO(PTW3),
+	PINMUX_GPIO(PTW2),
+	PINMUX_GPIO(PTW1),
+	PINMUX_GPIO(PTW0),
 
 	/* PTX */
-	PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
-	PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
-	PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
-	PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
-	PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
-	PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
-	PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
-	PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+	PINMUX_GPIO(PTX7),
+	PINMUX_GPIO(PTX6),
+	PINMUX_GPIO(PTX5),
+	PINMUX_GPIO(PTX4),
+	PINMUX_GPIO(PTX3),
+	PINMUX_GPIO(PTX2),
+	PINMUX_GPIO(PTX1),
+	PINMUX_GPIO(PTX0),
 
 	/* PTY */
-	PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
-	PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
-	PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
-	PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
-	PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
-	PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
-	PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
-	PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+	PINMUX_GPIO(PTY7),
+	PINMUX_GPIO(PTY6),
+	PINMUX_GPIO(PTY5),
+	PINMUX_GPIO(PTY4),
+	PINMUX_GPIO(PTY3),
+	PINMUX_GPIO(PTY2),
+	PINMUX_GPIO(PTY1),
+	PINMUX_GPIO(PTY0),
 
 	/* PTZ */
-	PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
-	PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
-	PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
-	PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
-	PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
-	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
-	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
-	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+	PINMUX_GPIO(PTZ7),
+	PINMUX_GPIO(PTZ6),
+	PINMUX_GPIO(PTZ5),
+	PINMUX_GPIO(PTZ4),
+	PINMUX_GPIO(PTZ3),
+	PINMUX_GPIO(PTZ2),
+	PINMUX_GPIO(PTZ1),
+	PINMUX_GPIO(PTZ0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -1728,14 +1688,14 @@ static const struct pinmux_func pinmux_func_gpios[] = {
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xffec0000, 16, 2) {
-		PTA7_FN, PTA7_OUT, PTA7_IN, PTA7_IN_PU,
-		PTA6_FN, PTA6_OUT, PTA6_IN, PTA6_IN_PU,
-		PTA5_FN, PTA5_OUT, PTA5_IN, PTA5_IN_PU,
-		PTA4_FN, PTA4_OUT, PTA4_IN, PTA4_IN_PU,
-		PTA3_FN, PTA3_OUT, PTA3_IN, PTA3_IN_PU,
-		PTA2_FN, PTA2_OUT, PTA2_IN, PTA2_IN_PU,
-		PTA1_FN, PTA1_OUT, PTA1_IN, PTA1_IN_PU,
-		PTA0_FN, PTA0_OUT, PTA0_IN, PTA0_IN_PU }
+		PTA7_FN, PTA7_OUT, PTA7_IN, 0,
+		PTA6_FN, PTA6_OUT, PTA6_IN, 0,
+		PTA5_FN, PTA5_OUT, PTA5_IN, 0,
+		PTA4_FN, PTA4_OUT, PTA4_IN, 0,
+		PTA3_FN, PTA3_OUT, PTA3_IN, 0,
+		PTA2_FN, PTA2_OUT, PTA2_IN, 0,
+		PTA1_FN, PTA1_OUT, PTA1_IN, 0,
+		PTA0_FN, PTA0_OUT, PTA0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PBCR", 0xffec0002, 16, 2) {
 		PTB7_FN, PTB7_OUT, PTB7_IN, 0,
@@ -1758,100 +1718,100 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTC0_FN, PTC0_OUT, PTC0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PDCR", 0xffec0006, 16, 2) {
-		PTD7_FN, PTD7_OUT, PTD7_IN, PTD7_IN_PU,
-		PTD6_FN, PTD6_OUT, PTD6_IN, PTD6_IN_PU,
-		PTD5_FN, PTD5_OUT, PTD5_IN, PTD5_IN_PU,
-		PTD4_FN, PTD4_OUT, PTD4_IN, PTD4_IN_PU,
-		PTD3_FN, PTD3_OUT, PTD3_IN, PTD3_IN_PU,
-		PTD2_FN, PTD2_OUT, PTD2_IN, PTD2_IN_PU,
-		PTD1_FN, PTD1_OUT, PTD1_IN, PTD1_IN_PU,
-		PTD0_FN, PTD0_OUT, PTD0_IN, PTD0_IN_PU }
+		PTD7_FN, PTD7_OUT, PTD7_IN, 0,
+		PTD6_FN, PTD6_OUT, PTD6_IN, 0,
+		PTD5_FN, PTD5_OUT, PTD5_IN, 0,
+		PTD4_FN, PTD4_OUT, PTD4_IN, 0,
+		PTD3_FN, PTD3_OUT, PTD3_IN, 0,
+		PTD2_FN, PTD2_OUT, PTD2_IN, 0,
+		PTD1_FN, PTD1_OUT, PTD1_IN, 0,
+		PTD0_FN, PTD0_OUT, PTD0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PECR", 0xffec0008, 16, 2) {
-		PTE7_FN, PTE7_OUT, PTE7_IN, PTE7_IN_PU,
-		PTE6_FN, PTE6_OUT, PTE6_IN, PTE6_IN_PU,
-		PTE5_FN, PTE5_OUT, PTE5_IN, PTE5_IN_PU,
-		PTE4_FN, PTE4_OUT, PTE4_IN, PTE4_IN_PU,
-		PTE3_FN, PTE3_OUT, PTE3_IN, PTE3_IN_PU,
-		PTE2_FN, PTE2_OUT, PTE2_IN, PTE2_IN_PU,
-		PTE1_FN, PTE1_OUT, PTE1_IN, PTE1_IN_PU,
-		PTE0_FN, PTE0_OUT, PTE0_IN, PTE0_IN_PU }
+		PTE7_FN, PTE7_OUT, PTE7_IN, 0,
+		PTE6_FN, PTE6_OUT, PTE6_IN, 0,
+		PTE5_FN, PTE5_OUT, PTE5_IN, 0,
+		PTE4_FN, PTE4_OUT, PTE4_IN, 0,
+		PTE3_FN, PTE3_OUT, PTE3_IN, 0,
+		PTE2_FN, PTE2_OUT, PTE2_IN, 0,
+		PTE1_FN, PTE1_OUT, PTE1_IN, 0,
+		PTE0_FN, PTE0_OUT, PTE0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PFCR", 0xffec000a, 16, 2) {
-		PTF7_FN, PTF7_OUT, PTF7_IN, PTF7_IN_PU,
-		PTF6_FN, PTF6_OUT, PTF6_IN, PTF6_IN_PU,
-		PTF5_FN, PTF5_OUT, PTF5_IN, PTF5_IN_PU,
-		PTF4_FN, PTF4_OUT, PTF4_IN, PTF4_IN_PU,
-		PTF3_FN, PTF3_OUT, PTF3_IN, PTF3_IN_PU,
-		PTF2_FN, PTF2_OUT, PTF2_IN, PTF2_IN_PU,
-		PTF1_FN, PTF1_OUT, PTF1_IN, PTF1_IN_PU,
-		PTF0_FN, PTF0_OUT, PTF0_IN, PTF0_IN_PU }
+		PTF7_FN, PTF7_OUT, PTF7_IN, 0,
+		PTF6_FN, PTF6_OUT, PTF6_IN, 0,
+		PTF5_FN, PTF5_OUT, PTF5_IN, 0,
+		PTF4_FN, PTF4_OUT, PTF4_IN, 0,
+		PTF3_FN, PTF3_OUT, PTF3_IN, 0,
+		PTF2_FN, PTF2_OUT, PTF2_IN, 0,
+		PTF1_FN, PTF1_OUT, PTF1_IN, 0,
+		PTF0_FN, PTF0_OUT, PTF0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PGCR", 0xffec000c, 16, 2) {
-		PTG7_FN, PTG7_OUT, PTG7_IN, PTG7_IN_PU ,
-		PTG6_FN, PTG6_OUT, PTG6_IN, PTG6_IN_PU ,
+		PTG7_FN, PTG7_OUT, PTG7_IN, 0,
+		PTG6_FN, PTG6_OUT, PTG6_IN, 0,
 		PTG5_FN, PTG5_OUT, PTG5_IN, 0,
-		PTG4_FN, PTG4_OUT, PTG4_IN, PTG4_IN_PU ,
+		PTG4_FN, PTG4_OUT, PTG4_IN, 0,
 		PTG3_FN, PTG3_OUT, PTG3_IN, 0,
 		PTG2_FN, PTG2_OUT, PTG2_IN, 0,
 		PTG1_FN, PTG1_OUT, PTG1_IN, 0,
 		PTG0_FN, PTG0_OUT, PTG0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PHCR", 0xffec000e, 16, 2) {
-		PTH7_FN, PTH7_OUT, PTH7_IN, PTH7_IN_PU,
-		PTH6_FN, PTH6_OUT, PTH6_IN, PTH6_IN_PU,
-		PTH5_FN, PTH5_OUT, PTH5_IN, PTH5_IN_PU,
-		PTH4_FN, PTH4_OUT, PTH4_IN, PTH4_IN_PU,
-		PTH3_FN, PTH3_OUT, PTH3_IN, PTH3_IN_PU,
-		PTH2_FN, PTH2_OUT, PTH2_IN, PTH2_IN_PU,
-		PTH1_FN, PTH1_OUT, PTH1_IN, PTH1_IN_PU,
-		PTH0_FN, PTH0_OUT, PTH0_IN, PTH0_IN_PU }
+		PTH7_FN, PTH7_OUT, PTH7_IN, 0,
+		PTH6_FN, PTH6_OUT, PTH6_IN, 0,
+		PTH5_FN, PTH5_OUT, PTH5_IN, 0,
+		PTH4_FN, PTH4_OUT, PTH4_IN, 0,
+		PTH3_FN, PTH3_OUT, PTH3_IN, 0,
+		PTH2_FN, PTH2_OUT, PTH2_IN, 0,
+		PTH1_FN, PTH1_OUT, PTH1_IN, 0,
+		PTH0_FN, PTH0_OUT, PTH0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PICR", 0xffec0010, 16, 2) {
-		PTI7_FN, PTI7_OUT, PTI7_IN, PTI7_IN_PU,
-		PTI6_FN, PTI6_OUT, PTI6_IN, PTI6_IN_PU,
+		PTI7_FN, PTI7_OUT, PTI7_IN, 0,
+		PTI6_FN, PTI6_OUT, PTI6_IN, 0,
 		PTI5_FN, PTI5_OUT, PTI5_IN, 0,
-		PTI4_FN, PTI4_OUT, PTI4_IN, PTI4_IN_PU,
-		PTI3_FN, PTI3_OUT, PTI3_IN, PTI3_IN_PU,
-		PTI2_FN, PTI2_OUT, PTI2_IN, PTI2_IN_PU,
-		PTI1_FN, PTI1_OUT, PTI1_IN, PTI1_IN_PU,
-		PTI0_FN, PTI0_OUT, PTI0_IN, PTI0_IN_PU }
+		PTI4_FN, PTI4_OUT, PTI4_IN, 0,
+		PTI3_FN, PTI3_OUT, PTI3_IN, 0,
+		PTI2_FN, PTI2_OUT, PTI2_IN, 0,
+		PTI1_FN, PTI1_OUT, PTI1_IN, 0,
+		PTI0_FN, PTI0_OUT, PTI0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PJCR", 0xffec0012, 16, 2) {
 		0, 0, 0, 0,	/* reserved: always set 1 */
-		PTJ6_FN, PTJ6_OUT, PTJ6_IN, PTJ6_IN_PU,
-		PTJ5_FN, PTJ5_OUT, PTJ5_IN, PTJ5_IN_PU,
-		PTJ4_FN, PTJ4_OUT, PTJ4_IN, PTJ4_IN_PU,
-		PTJ3_FN, PTJ3_OUT, PTJ3_IN, PTJ3_IN_PU,
-		PTJ2_FN, PTJ2_OUT, PTJ2_IN, PTJ2_IN_PU,
-		PTJ1_FN, PTJ1_OUT, PTJ1_IN, PTJ1_IN_PU,
-		PTJ0_FN, PTJ0_OUT, PTJ0_IN, PTJ0_IN_PU }
+		PTJ6_FN, PTJ6_OUT, PTJ6_IN, 0,
+		PTJ5_FN, PTJ5_OUT, PTJ5_IN, 0,
+		PTJ4_FN, PTJ4_OUT, PTJ4_IN, 0,
+		PTJ3_FN, PTJ3_OUT, PTJ3_IN, 0,
+		PTJ2_FN, PTJ2_OUT, PTJ2_IN, 0,
+		PTJ1_FN, PTJ1_OUT, PTJ1_IN, 0,
+		PTJ0_FN, PTJ0_OUT, PTJ0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PKCR", 0xffec0014, 16, 2) {
-		PTK7_FN, PTK7_OUT, PTK7_IN, PTK7_IN_PU,
-		PTK6_FN, PTK6_OUT, PTK6_IN, PTK6_IN_PU,
-		PTK5_FN, PTK5_OUT, PTK5_IN, PTK5_IN_PU,
-		PTK4_FN, PTK4_OUT, PTK4_IN, PTK4_IN_PU,
-		PTK3_FN, PTK3_OUT, PTK3_IN, PTK3_IN_PU,
-		PTK2_FN, PTK2_OUT, PTK2_IN, PTK2_IN_PU,
-		PTK1_FN, PTK1_OUT, PTK1_IN, PTK1_IN_PU,
-		PTK0_FN, PTK0_OUT, PTK0_IN, PTK0_IN_PU }
+		PTK7_FN, PTK7_OUT, PTK7_IN, 0,
+		PTK6_FN, PTK6_OUT, PTK6_IN, 0,
+		PTK5_FN, PTK5_OUT, PTK5_IN, 0,
+		PTK4_FN, PTK4_OUT, PTK4_IN, 0,
+		PTK3_FN, PTK3_OUT, PTK3_IN, 0,
+		PTK2_FN, PTK2_OUT, PTK2_IN, 0,
+		PTK1_FN, PTK1_OUT, PTK1_IN, 0,
+		PTK0_FN, PTK0_OUT, PTK0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PLCR", 0xffec0016, 16, 2) {
 		0, 0, 0, 0,	/* reserved: always set 1 */
-		PTL6_FN, PTL6_OUT, PTL6_IN, PTL6_IN_PU,
-		PTL5_FN, PTL5_OUT, PTL5_IN, PTL5_IN_PU,
-		PTL4_FN, PTL4_OUT, PTL4_IN, PTL4_IN_PU,
-		PTL3_FN, PTL3_OUT, PTL3_IN, PTL3_IN_PU,
-		PTL2_FN, PTL2_OUT, PTL2_IN, PTL2_IN_PU,
-		PTL1_FN, PTL1_OUT, PTL1_IN, PTL1_IN_PU,
-		PTL0_FN, PTL0_OUT, PTL0_IN, PTL0_IN_PU }
+		PTL6_FN, PTL6_OUT, PTL6_IN, 0,
+		PTL5_FN, PTL5_OUT, PTL5_IN, 0,
+		PTL4_FN, PTL4_OUT, PTL4_IN, 0,
+		PTL3_FN, PTL3_OUT, PTL3_IN, 0,
+		PTL2_FN, PTL2_OUT, PTL2_IN, 0,
+		PTL1_FN, PTL1_OUT, PTL1_IN, 0,
+		PTL0_FN, PTL0_OUT, PTL0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PMCR", 0xffec0018, 16, 2) {
-		PTM7_FN, PTM7_OUT, PTM7_IN, PTM7_IN_PU,
-		PTM6_FN, PTM6_OUT, PTM6_IN, PTM6_IN_PU,
-		PTM5_FN, PTM5_OUT, PTM5_IN, PTM5_IN_PU,
-		PTM4_FN, PTM4_OUT, PTM4_IN, PTM4_IN_PU,
+		PTM7_FN, PTM7_OUT, PTM7_IN, 0,
+		PTM6_FN, PTM6_OUT, PTM6_IN, 0,
+		PTM5_FN, PTM5_OUT, PTM5_IN, 0,
+		PTM4_FN, PTM4_OUT, PTM4_IN, 0,
 		PTM3_FN, PTM3_OUT, PTM3_IN, 0,
 		PTM2_FN, PTM2_OUT, PTM2_IN, 0,
 		PTM1_FN, PTM1_OUT, PTM1_IN, 0,
@@ -1861,21 +1821,21 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0, 0, 0,	/* reserved: always set 1 */
 		PTN6_FN, PTN6_OUT, PTN6_IN, 0,
 		PTN5_FN, PTN5_OUT, PTN5_IN, 0,
-		PTN4_FN, PTN4_OUT, PTN4_IN, PTN4_IN_PU,
-		PTN3_FN, PTN3_OUT, PTN3_IN, PTN3_IN_PU,
-		PTN2_FN, PTN2_OUT, PTN2_IN, PTN2_IN_PU,
-		PTN1_FN, PTN1_OUT, PTN1_IN, PTN1_IN_PU,
-		PTN0_FN, PTN0_OUT, PTN0_IN, PTN0_IN_PU }
+		PTN4_FN, PTN4_OUT, PTN4_IN, 0,
+		PTN3_FN, PTN3_OUT, PTN3_IN, 0,
+		PTN2_FN, PTN2_OUT, PTN2_IN, 0,
+		PTN1_FN, PTN1_OUT, PTN1_IN, 0,
+		PTN0_FN, PTN0_OUT, PTN0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("POCR", 0xffec001c, 16, 2) {
-		PTO7_FN, PTO7_OUT, PTO7_IN, PTO7_IN_PU,
-		PTO6_FN, PTO6_OUT, PTO6_IN, PTO6_IN_PU,
-		PTO5_FN, PTO5_OUT, PTO5_IN, PTO5_IN_PU,
-		PTO4_FN, PTO4_OUT, PTO4_IN, PTO4_IN_PU,
-		PTO3_FN, PTO3_OUT, PTO3_IN, PTO3_IN_PU,
-		PTO2_FN, PTO2_OUT, PTO2_IN, PTO2_IN_PU,
-		PTO1_FN, PTO1_OUT, PTO1_IN, PTO1_IN_PU,
-		PTO0_FN, PTO0_OUT, PTO0_IN, PTO0_IN_PU }
+		PTO7_FN, PTO7_OUT, PTO7_IN, 0,
+		PTO6_FN, PTO6_OUT, PTO6_IN, 0,
+		PTO5_FN, PTO5_OUT, PTO5_IN, 0,
+		PTO4_FN, PTO4_OUT, PTO4_IN, 0,
+		PTO3_FN, PTO3_OUT, PTO3_IN, 0,
+		PTO2_FN, PTO2_OUT, PTO2_IN, 0,
+		PTO1_FN, PTO1_OUT, PTO1_IN, 0,
+		PTO0_FN, PTO0_OUT, PTO0_IN, 0 }
 	},
 #if 0	/* FIXME: Remove it? */
 	{ PINMUX_CFG_REG("PPCR", 0xffec001e, 16, 2) {
@@ -1920,32 +1880,32 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTS0_FN, PTS0_OUT, PTS0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PTCR", 0xffec0026, 16, 2) {
-		PTT7_FN, PTT7_OUT, PTT7_IN, PTO7_IN_PU,
-		PTT6_FN, PTT6_OUT, PTT6_IN, PTO6_IN_PU,
-		PTT5_FN, PTT5_OUT, PTT5_IN, PTO5_IN_PU,
-		PTT4_FN, PTT4_OUT, PTT4_IN, PTO4_IN_PU,
-		PTT3_FN, PTT3_OUT, PTT3_IN, PTO3_IN_PU,
-		PTT2_FN, PTT2_OUT, PTT2_IN, PTO2_IN_PU,
-		PTT1_FN, PTT1_OUT, PTT1_IN, PTO1_IN_PU,
-		PTT0_FN, PTT0_OUT, PTT0_IN, PTO0_IN_PU }
+		PTT7_FN, PTT7_OUT, PTT7_IN, 0,
+		PTT6_FN, PTT6_OUT, PTT6_IN, 0,
+		PTT5_FN, PTT5_OUT, PTT5_IN, 0,
+		PTT4_FN, PTT4_OUT, PTT4_IN, 0,
+		PTT3_FN, PTT3_OUT, PTT3_IN, 0,
+		PTT2_FN, PTT2_OUT, PTT2_IN, 0,
+		PTT1_FN, PTT1_OUT, PTT1_IN, 0,
+		PTT0_FN, PTT0_OUT, PTT0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PUCR", 0xffec0028, 16, 2) {
-		PTU7_FN, PTU7_OUT, PTU7_IN, PTU7_IN_PU,
-		PTU6_FN, PTU6_OUT, PTU6_IN, PTU6_IN_PU,
-		PTU5_FN, PTU5_OUT, PTU5_IN, PTU5_IN_PU,
-		PTU4_FN, PTU4_OUT, PTU4_IN, PTU4_IN_PU,
-		PTU3_FN, PTU3_OUT, PTU3_IN, PTU3_IN_PU,
-		PTU2_FN, PTU2_OUT, PTU2_IN, PTU2_IN_PU,
-		PTU1_FN, PTU1_OUT, PTU1_IN, PTU1_IN_PU,
-		PTU0_FN, PTU0_OUT, PTU0_IN, PTU0_IN_PU }
+		PTU7_FN, PTU7_OUT, PTU7_IN, 0,
+		PTU6_FN, PTU6_OUT, PTU6_IN, 0,
+		PTU5_FN, PTU5_OUT, PTU5_IN, 0,
+		PTU4_FN, PTU4_OUT, PTU4_IN, 0,
+		PTU3_FN, PTU3_OUT, PTU3_IN, 0,
+		PTU2_FN, PTU2_OUT, PTU2_IN, 0,
+		PTU1_FN, PTU1_OUT, PTU1_IN, 0,
+		PTU0_FN, PTU0_OUT, PTU0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PVCR", 0xffec002a, 16, 2) {
-		PTV7_FN, PTV7_OUT, PTV7_IN, PTV7_IN_PU,
-		PTV6_FN, PTV6_OUT, PTV6_IN, PTV6_IN_PU,
-		PTV5_FN, PTV5_OUT, PTV5_IN, PTV5_IN_PU,
-		PTV4_FN, PTV4_OUT, PTV4_IN, PTV4_IN_PU,
-		PTV3_FN, PTV3_OUT, PTV3_IN, PTV3_IN_PU,
-		PTV2_FN, PTV2_OUT, PTV2_IN, PTV2_IN_PU,
+		PTV7_FN, PTV7_OUT, PTV7_IN, 0,
+		PTV6_FN, PTV6_OUT, PTV6_IN, 0,
+		PTV5_FN, PTV5_OUT, PTV5_IN, 0,
+		PTV4_FN, PTV4_OUT, PTV4_IN, 0,
+		PTV3_FN, PTV3_OUT, PTV3_IN, 0,
+		PTV2_FN, PTV2_OUT, PTV2_IN, 0,
 		PTV1_FN, PTV1_OUT, PTV1_IN, 0,
 		PTV0_FN, PTV0_OUT, PTV0_IN, 0 }
 	},
@@ -1956,28 +1916,28 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		PTW4_FN, PTW4_OUT, PTW4_IN, 0,
 		PTW3_FN, PTW3_OUT, PTW3_IN, 0,
 		PTW2_FN, PTW2_OUT, PTW2_IN, 0,
-		PTW1_FN, PTW1_OUT, PTW1_IN, PTW1_IN_PU,
-		PTW0_FN, PTW0_OUT, PTW0_IN, PTW0_IN_PU }
+		PTW1_FN, PTW1_OUT, PTW1_IN, 0,
+		PTW0_FN, PTW0_OUT, PTW0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PXCR", 0xffec002e, 16, 2) {
-		PTX7_FN, PTX7_OUT, PTX7_IN, PTX7_IN_PU,
-		PTX6_FN, PTX6_OUT, PTX6_IN, PTX6_IN_PU,
-		PTX5_FN, PTX5_OUT, PTX5_IN, PTX5_IN_PU,
-		PTX4_FN, PTX4_OUT, PTX4_IN, PTX4_IN_PU,
-		PTX3_FN, PTX3_OUT, PTX3_IN, PTX3_IN_PU,
-		PTX2_FN, PTX2_OUT, PTX2_IN, PTX2_IN_PU,
-		PTX1_FN, PTX1_OUT, PTX1_IN, PTX1_IN_PU,
-		PTX0_FN, PTX0_OUT, PTX0_IN, PTX0_IN_PU }
+		PTX7_FN, PTX7_OUT, PTX7_IN, 0,
+		PTX6_FN, PTX6_OUT, PTX6_IN, 0,
+		PTX5_FN, PTX5_OUT, PTX5_IN, 0,
+		PTX4_FN, PTX4_OUT, PTX4_IN, 0,
+		PTX3_FN, PTX3_OUT, PTX3_IN, 0,
+		PTX2_FN, PTX2_OUT, PTX2_IN, 0,
+		PTX1_FN, PTX1_OUT, PTX1_IN, 0,
+		PTX0_FN, PTX0_OUT, PTX0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PYCR", 0xffec0030, 16, 2) {
-		PTY7_FN, PTY7_OUT, PTY7_IN, PTY7_IN_PU,
-		PTY6_FN, PTY6_OUT, PTY6_IN, PTY6_IN_PU,
-		PTY5_FN, PTY5_OUT, PTY5_IN, PTY5_IN_PU,
-		PTY4_FN, PTY4_OUT, PTY4_IN, PTY4_IN_PU,
-		PTY3_FN, PTY3_OUT, PTY3_IN, PTY3_IN_PU,
-		PTY2_FN, PTY2_OUT, PTY2_IN, PTY2_IN_PU,
-		PTY1_FN, PTY1_OUT, PTY1_IN, PTY1_IN_PU,
-		PTY0_FN, PTY0_OUT, PTY0_IN, PTY0_IN_PU }
+		PTY7_FN, PTY7_OUT, PTY7_IN, 0,
+		PTY6_FN, PTY6_OUT, PTY6_IN, 0,
+		PTY5_FN, PTY5_OUT, PTY5_IN, 0,
+		PTY4_FN, PTY4_OUT, PTY4_IN, 0,
+		PTY3_FN, PTY3_OUT, PTY3_IN, 0,
+		PTY2_FN, PTY2_OUT, PTY2_IN, 0,
+		PTY1_FN, PTY1_OUT, PTY1_IN, 0,
+		PTY0_FN, PTY0_OUT, PTY0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PZCR", 0xffec0032, 16, 2) {
 		PTZ7_FN, PTZ7_OUT, PTZ7_IN, 0,
@@ -2267,7 +2227,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7757_pinmux_info = {
 	.name = "sh7757_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7785.c b/drivers/pinctrl/sh-pfc/pfc-sh7785.c
index c176b79..517eb49 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7785.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7785.c
@@ -77,36 +77,6 @@ enum {
 	PR3_IN, PR2_IN, PR1_IN, PR0_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,
-	PE5_IN_PU, PE4_IN_PU, PE3_IN_PU, PE2_IN_PU, PE1_IN_PU, PE0_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, PG4_IN_PU,
-	PG3_IN_PU, PG2_IN_PU, PG1_IN_PU, PG0_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, PJ0_IN_PU,
-	PK7_IN_PU, PK6_IN_PU, PK5_IN_PU, PK4_IN_PU,
-	PK3_IN_PU, PK2_IN_PU, PK1_IN_PU, PK0_IN_PU,
-	PL7_IN_PU, PL6_IN_PU, PL5_IN_PU, PL4_IN_PU,
-	PL3_IN_PU, PL2_IN_PU, PL1_IN_PU, PL0_IN_PU,
-	PM1_IN_PU, PM0_IN_PU,
-	PN7_IN_PU, PN6_IN_PU, PN5_IN_PU, PN4_IN_PU,
-	PN3_IN_PU, PN2_IN_PU, PN1_IN_PU, PN0_IN_PU,
-	PP5_IN_PU, PP4_IN_PU, PP3_IN_PU, PP2_IN_PU, PP1_IN_PU, PP0_IN_PU,
-	PQ4_IN_PU, PQ3_IN_PU, PQ2_IN_PU, PQ1_IN_PU, PQ0_IN_PU,
-	PR3_IN_PU, PR2_IN_PU, PR1_IN_PU, PR0_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,
@@ -355,150 +325,149 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
-
+static const u16 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),
+	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT),
+	PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT),
+	PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT),
+	PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT),
+	PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT),
+	PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT),
+	PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT),
+	PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT),
+	PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT),
+	PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT),
+	PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT),
+	PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT),
+	PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT),
+	PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT),
+	PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT),
+	PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT),
+	PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT),
+	PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT),
+	PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT),
+	PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT),
+	PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT),
+	PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT),
+	PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT),
+	PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT),
+	PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT),
+	PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT),
+	PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT),
+	PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT),
+	PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT),
 
 	/* PE GPIO */
-	PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT, PE5_IN_PU),
-	PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT, PE4_IN_PU),
-	PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT, PE3_IN_PU),
-	PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT, PE2_IN_PU),
-	PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT, PE1_IN_PU),
-	PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT, PE0_IN_PU),
+	PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT),
+	PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT),
+	PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT),
+	PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT),
+	PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT),
+	PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT),
+	PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT),
+	PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT),
+	PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT),
+	PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT),
+	PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT),
+	PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT),
+	PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT),
 
 	/* 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),
-	PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT, PG4_IN_PU),
-	PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT, PG3_IN_PU),
-	PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT, PG2_IN_PU),
-	PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT, PG1_IN_PU),
-	PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT, PG0_IN_PU),
+	PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT),
+	PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT),
+	PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT),
+	PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT),
+	PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT),
+	PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT),
+	PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT),
+	PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PH7_DATA, PH7_IN, PH7_OUT),
+	PINMUX_DATA(PH6_DATA, PH6_IN, PH6_OUT),
+	PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT),
+	PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT),
+	PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT),
+	PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT),
+	PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT),
+	PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT),
 
 	/* 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),
-	PINMUX_DATA(PJ0_DATA, PJ0_IN, PJ0_OUT, PJ0_IN_PU),
+	PINMUX_DATA(PJ7_DATA, PJ7_IN, PJ7_OUT),
+	PINMUX_DATA(PJ6_DATA, PJ6_IN, PJ6_OUT),
+	PINMUX_DATA(PJ5_DATA, PJ5_IN, PJ5_OUT),
+	PINMUX_DATA(PJ4_DATA, PJ4_IN, PJ4_OUT),
+	PINMUX_DATA(PJ3_DATA, PJ3_IN, PJ3_OUT),
+	PINMUX_DATA(PJ2_DATA, PJ2_IN, PJ2_OUT),
+	PINMUX_DATA(PJ1_DATA, PJ1_IN, PJ1_OUT),
+	PINMUX_DATA(PJ0_DATA, PJ0_IN, PJ0_OUT),
 
 	/* PK GPIO */
-	PINMUX_DATA(PK7_DATA, PK7_IN, PK7_OUT, PK7_IN_PU),
-	PINMUX_DATA(PK6_DATA, PK6_IN, PK6_OUT, PK6_IN_PU),
-	PINMUX_DATA(PK5_DATA, PK5_IN, PK5_OUT, PK5_IN_PU),
-	PINMUX_DATA(PK4_DATA, PK4_IN, PK4_OUT, PK4_IN_PU),
-	PINMUX_DATA(PK3_DATA, PK3_IN, PK3_OUT, PK3_IN_PU),
-	PINMUX_DATA(PK2_DATA, PK2_IN, PK2_OUT, PK2_IN_PU),
-	PINMUX_DATA(PK1_DATA, PK1_IN, PK1_OUT, PK1_IN_PU),
-	PINMUX_DATA(PK0_DATA, PK0_IN, PK0_OUT, PK0_IN_PU),
+	PINMUX_DATA(PK7_DATA, PK7_IN, PK7_OUT),
+	PINMUX_DATA(PK6_DATA, PK6_IN, PK6_OUT),
+	PINMUX_DATA(PK5_DATA, PK5_IN, PK5_OUT),
+	PINMUX_DATA(PK4_DATA, PK4_IN, PK4_OUT),
+	PINMUX_DATA(PK3_DATA, PK3_IN, PK3_OUT),
+	PINMUX_DATA(PK2_DATA, PK2_IN, PK2_OUT),
+	PINMUX_DATA(PK1_DATA, PK1_IN, PK1_OUT),
+	PINMUX_DATA(PK0_DATA, PK0_IN, PK0_OUT),
 
 	/* PL GPIO */
-	PINMUX_DATA(PL7_DATA, PL7_IN, PL7_OUT, PL7_IN_PU),
-	PINMUX_DATA(PL6_DATA, PL6_IN, PL6_OUT, PL6_IN_PU),
-	PINMUX_DATA(PL5_DATA, PL5_IN, PL5_OUT, PL5_IN_PU),
-	PINMUX_DATA(PL4_DATA, PL4_IN, PL4_OUT, PL4_IN_PU),
-	PINMUX_DATA(PL3_DATA, PL3_IN, PL3_OUT, PL3_IN_PU),
-	PINMUX_DATA(PL2_DATA, PL2_IN, PL2_OUT, PL2_IN_PU),
-	PINMUX_DATA(PL1_DATA, PL1_IN, PL1_OUT, PL1_IN_PU),
-	PINMUX_DATA(PL0_DATA, PL0_IN, PL0_OUT, PL0_IN_PU),
+	PINMUX_DATA(PL7_DATA, PL7_IN, PL7_OUT),
+	PINMUX_DATA(PL6_DATA, PL6_IN, PL6_OUT),
+	PINMUX_DATA(PL5_DATA, PL5_IN, PL5_OUT),
+	PINMUX_DATA(PL4_DATA, PL4_IN, PL4_OUT),
+	PINMUX_DATA(PL3_DATA, PL3_IN, PL3_OUT),
+	PINMUX_DATA(PL2_DATA, PL2_IN, PL2_OUT),
+	PINMUX_DATA(PL1_DATA, PL1_IN, PL1_OUT),
+	PINMUX_DATA(PL0_DATA, PL0_IN, PL0_OUT),
 
 	/* PM GPIO */
-	PINMUX_DATA(PM1_DATA, PM1_IN, PM1_OUT, PM1_IN_PU),
-	PINMUX_DATA(PM0_DATA, PM0_IN, PM0_OUT, PM0_IN_PU),
+	PINMUX_DATA(PM1_DATA, PM1_IN, PM1_OUT),
+	PINMUX_DATA(PM0_DATA, PM0_IN, PM0_OUT),
 
 	/* PN GPIO */
-	PINMUX_DATA(PN7_DATA, PN7_IN, PN7_OUT, PN7_IN_PU),
-	PINMUX_DATA(PN6_DATA, PN6_IN, PN6_OUT, PN6_IN_PU),
-	PINMUX_DATA(PN5_DATA, PN5_IN, PN5_OUT, PN5_IN_PU),
-	PINMUX_DATA(PN4_DATA, PN4_IN, PN4_OUT, PN4_IN_PU),
-	PINMUX_DATA(PN3_DATA, PN3_IN, PN3_OUT, PN3_IN_PU),
-	PINMUX_DATA(PN2_DATA, PN2_IN, PN2_OUT, PN2_IN_PU),
-	PINMUX_DATA(PN1_DATA, PN1_IN, PN1_OUT, PN1_IN_PU),
-	PINMUX_DATA(PN0_DATA, PN0_IN, PN0_OUT, PN0_IN_PU),
+	PINMUX_DATA(PN7_DATA, PN7_IN, PN7_OUT),
+	PINMUX_DATA(PN6_DATA, PN6_IN, PN6_OUT),
+	PINMUX_DATA(PN5_DATA, PN5_IN, PN5_OUT),
+	PINMUX_DATA(PN4_DATA, PN4_IN, PN4_OUT),
+	PINMUX_DATA(PN3_DATA, PN3_IN, PN3_OUT),
+	PINMUX_DATA(PN2_DATA, PN2_IN, PN2_OUT),
+	PINMUX_DATA(PN1_DATA, PN1_IN, PN1_OUT),
+	PINMUX_DATA(PN0_DATA, PN0_IN, PN0_OUT),
 
 	/* PP GPIO */
-	PINMUX_DATA(PP5_DATA, PP5_IN, PP5_OUT, PP5_IN_PU),
-	PINMUX_DATA(PP4_DATA, PP4_IN, PP4_OUT, PP4_IN_PU),
-	PINMUX_DATA(PP3_DATA, PP3_IN, PP3_OUT, PP3_IN_PU),
-	PINMUX_DATA(PP2_DATA, PP2_IN, PP2_OUT, PP2_IN_PU),
-	PINMUX_DATA(PP1_DATA, PP1_IN, PP1_OUT, PP1_IN_PU),
-	PINMUX_DATA(PP0_DATA, PP0_IN, PP0_OUT, PP0_IN_PU),
+	PINMUX_DATA(PP5_DATA, PP5_IN, PP5_OUT),
+	PINMUX_DATA(PP4_DATA, PP4_IN, PP4_OUT),
+	PINMUX_DATA(PP3_DATA, PP3_IN, PP3_OUT),
+	PINMUX_DATA(PP2_DATA, PP2_IN, PP2_OUT),
+	PINMUX_DATA(PP1_DATA, PP1_IN, PP1_OUT),
+	PINMUX_DATA(PP0_DATA, PP0_IN, PP0_OUT),
 
 	/* PQ GPIO */
-	PINMUX_DATA(PQ4_DATA, PQ4_IN, PQ4_OUT, PQ4_IN_PU),
-	PINMUX_DATA(PQ3_DATA, PQ3_IN, PQ3_OUT, PQ3_IN_PU),
-	PINMUX_DATA(PQ2_DATA, PQ2_IN, PQ2_OUT, PQ2_IN_PU),
-	PINMUX_DATA(PQ1_DATA, PQ1_IN, PQ1_OUT, PQ1_IN_PU),
-	PINMUX_DATA(PQ0_DATA, PQ0_IN, PQ0_OUT, PQ0_IN_PU),
+	PINMUX_DATA(PQ4_DATA, PQ4_IN, PQ4_OUT),
+	PINMUX_DATA(PQ3_DATA, PQ3_IN, PQ3_OUT),
+	PINMUX_DATA(PQ2_DATA, PQ2_IN, PQ2_OUT),
+	PINMUX_DATA(PQ1_DATA, PQ1_IN, PQ1_OUT),
+	PINMUX_DATA(PQ0_DATA, PQ0_IN, PQ0_OUT),
 
 	/* PR GPIO */
-	PINMUX_DATA(PR3_DATA, PR3_IN, PR3_OUT, PR3_IN_PU),
-	PINMUX_DATA(PR2_DATA, PR2_IN, PR2_OUT, PR2_IN_PU),
-	PINMUX_DATA(PR1_DATA, PR1_IN, PR1_OUT, PR1_IN_PU),
-	PINMUX_DATA(PR0_DATA, PR0_IN, PR0_OUT, PR0_IN_PU),
+	PINMUX_DATA(PR3_DATA, PR3_IN, PR3_OUT),
+	PINMUX_DATA(PR2_DATA, PR2_IN, PR2_OUT),
+	PINMUX_DATA(PR1_DATA, PR1_IN, PR1_OUT),
+	PINMUX_DATA(PR0_DATA, PR0_IN, PR0_OUT),
 
 	/* PA FN */
 	PINMUX_DATA(D63_AD31_MARK, PA7_FN),
@@ -704,147 +673,147 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* 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),
+	PINMUX_GPIO(PA7),
+	PINMUX_GPIO(PA6),
+	PINMUX_GPIO(PA5),
+	PINMUX_GPIO(PA4),
+	PINMUX_GPIO(PA3),
+	PINMUX_GPIO(PA2),
+	PINMUX_GPIO(PA1),
+	PINMUX_GPIO(PA0),
 
 	/* 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),
+	PINMUX_GPIO(PB7),
+	PINMUX_GPIO(PB6),
+	PINMUX_GPIO(PB5),
+	PINMUX_GPIO(PB4),
+	PINMUX_GPIO(PB3),
+	PINMUX_GPIO(PB2),
+	PINMUX_GPIO(PB1),
+	PINMUX_GPIO(PB0),
 
 	/* 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),
+	PINMUX_GPIO(PC7),
+	PINMUX_GPIO(PC6),
+	PINMUX_GPIO(PC5),
+	PINMUX_GPIO(PC4),
+	PINMUX_GPIO(PC3),
+	PINMUX_GPIO(PC2),
+	PINMUX_GPIO(PC1),
+	PINMUX_GPIO(PC0),
 
 	/* 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),
+	PINMUX_GPIO(PD7),
+	PINMUX_GPIO(PD6),
+	PINMUX_GPIO(PD5),
+	PINMUX_GPIO(PD4),
+	PINMUX_GPIO(PD3),
+	PINMUX_GPIO(PD2),
+	PINMUX_GPIO(PD1),
+	PINMUX_GPIO(PD0),
 
 	/* PE */
-	PINMUX_GPIO(GPIO_PE5, PE5_DATA),
-	PINMUX_GPIO(GPIO_PE4, PE4_DATA),
-	PINMUX_GPIO(GPIO_PE3, PE3_DATA),
-	PINMUX_GPIO(GPIO_PE2, PE2_DATA),
-	PINMUX_GPIO(GPIO_PE1, PE1_DATA),
-	PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+	PINMUX_GPIO(PE5),
+	PINMUX_GPIO(PE4),
+	PINMUX_GPIO(PE3),
+	PINMUX_GPIO(PE2),
+	PINMUX_GPIO(PE1),
+	PINMUX_GPIO(PE0),
 
 	/* 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),
+	PINMUX_GPIO(PF7),
+	PINMUX_GPIO(PF6),
+	PINMUX_GPIO(PF5),
+	PINMUX_GPIO(PF4),
+	PINMUX_GPIO(PF3),
+	PINMUX_GPIO(PF2),
+	PINMUX_GPIO(PF1),
+	PINMUX_GPIO(PF0),
 
 	/* PG */
-	PINMUX_GPIO(GPIO_PG7, PG7_DATA),
-	PINMUX_GPIO(GPIO_PG6, PG6_DATA),
-	PINMUX_GPIO(GPIO_PG5, PG5_DATA),
-	PINMUX_GPIO(GPIO_PG4, PG4_DATA),
-	PINMUX_GPIO(GPIO_PG3, PG3_DATA),
-	PINMUX_GPIO(GPIO_PG2, PG2_DATA),
-	PINMUX_GPIO(GPIO_PG1, PG1_DATA),
-	PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+	PINMUX_GPIO(PG7),
+	PINMUX_GPIO(PG6),
+	PINMUX_GPIO(PG5),
+	PINMUX_GPIO(PG4),
+	PINMUX_GPIO(PG3),
+	PINMUX_GPIO(PG2),
+	PINMUX_GPIO(PG1),
+	PINMUX_GPIO(PG0),
 
 	/* 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),
+	PINMUX_GPIO(PH7),
+	PINMUX_GPIO(PH6),
+	PINMUX_GPIO(PH5),
+	PINMUX_GPIO(PH4),
+	PINMUX_GPIO(PH3),
+	PINMUX_GPIO(PH2),
+	PINMUX_GPIO(PH1),
+	PINMUX_GPIO(PH0),
 
 	/* 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),
-	PINMUX_GPIO(GPIO_PJ0, PJ0_DATA),
+	PINMUX_GPIO(PJ7),
+	PINMUX_GPIO(PJ6),
+	PINMUX_GPIO(PJ5),
+	PINMUX_GPIO(PJ4),
+	PINMUX_GPIO(PJ3),
+	PINMUX_GPIO(PJ2),
+	PINMUX_GPIO(PJ1),
+	PINMUX_GPIO(PJ0),
 
 	/* PK */
-	PINMUX_GPIO(GPIO_PK7, PK7_DATA),
-	PINMUX_GPIO(GPIO_PK6, PK6_DATA),
-	PINMUX_GPIO(GPIO_PK5, PK5_DATA),
-	PINMUX_GPIO(GPIO_PK4, PK4_DATA),
-	PINMUX_GPIO(GPIO_PK3, PK3_DATA),
-	PINMUX_GPIO(GPIO_PK2, PK2_DATA),
-	PINMUX_GPIO(GPIO_PK1, PK1_DATA),
-	PINMUX_GPIO(GPIO_PK0, PK0_DATA),
+	PINMUX_GPIO(PK7),
+	PINMUX_GPIO(PK6),
+	PINMUX_GPIO(PK5),
+	PINMUX_GPIO(PK4),
+	PINMUX_GPIO(PK3),
+	PINMUX_GPIO(PK2),
+	PINMUX_GPIO(PK1),
+	PINMUX_GPIO(PK0),
 
 	/* PL */
-	PINMUX_GPIO(GPIO_PL7, PL7_DATA),
-	PINMUX_GPIO(GPIO_PL6, PL6_DATA),
-	PINMUX_GPIO(GPIO_PL5, PL5_DATA),
-	PINMUX_GPIO(GPIO_PL4, PL4_DATA),
-	PINMUX_GPIO(GPIO_PL3, PL3_DATA),
-	PINMUX_GPIO(GPIO_PL2, PL2_DATA),
-	PINMUX_GPIO(GPIO_PL1, PL1_DATA),
-	PINMUX_GPIO(GPIO_PL0, PL0_DATA),
+	PINMUX_GPIO(PL7),
+	PINMUX_GPIO(PL6),
+	PINMUX_GPIO(PL5),
+	PINMUX_GPIO(PL4),
+	PINMUX_GPIO(PL3),
+	PINMUX_GPIO(PL2),
+	PINMUX_GPIO(PL1),
+	PINMUX_GPIO(PL0),
 
 	/* PM */
-	PINMUX_GPIO(GPIO_PM1, PM1_DATA),
-	PINMUX_GPIO(GPIO_PM0, PM0_DATA),
+	PINMUX_GPIO(PM1),
+	PINMUX_GPIO(PM0),
 
 	/* PN */
-	PINMUX_GPIO(GPIO_PN7, PN7_DATA),
-	PINMUX_GPIO(GPIO_PN6, PN6_DATA),
-	PINMUX_GPIO(GPIO_PN5, PN5_DATA),
-	PINMUX_GPIO(GPIO_PN4, PN4_DATA),
-	PINMUX_GPIO(GPIO_PN3, PN3_DATA),
-	PINMUX_GPIO(GPIO_PN2, PN2_DATA),
-	PINMUX_GPIO(GPIO_PN1, PN1_DATA),
-	PINMUX_GPIO(GPIO_PN0, PN0_DATA),
+	PINMUX_GPIO(PN7),
+	PINMUX_GPIO(PN6),
+	PINMUX_GPIO(PN5),
+	PINMUX_GPIO(PN4),
+	PINMUX_GPIO(PN3),
+	PINMUX_GPIO(PN2),
+	PINMUX_GPIO(PN1),
+	PINMUX_GPIO(PN0),
 
 	/* PP */
-	PINMUX_GPIO(GPIO_PP5, PP5_DATA),
-	PINMUX_GPIO(GPIO_PP4, PP4_DATA),
-	PINMUX_GPIO(GPIO_PP3, PP3_DATA),
-	PINMUX_GPIO(GPIO_PP2, PP2_DATA),
-	PINMUX_GPIO(GPIO_PP1, PP1_DATA),
-	PINMUX_GPIO(GPIO_PP0, PP0_DATA),
+	PINMUX_GPIO(PP5),
+	PINMUX_GPIO(PP4),
+	PINMUX_GPIO(PP3),
+	PINMUX_GPIO(PP2),
+	PINMUX_GPIO(PP1),
+	PINMUX_GPIO(PP0),
 
 	/* PQ */
-	PINMUX_GPIO(GPIO_PQ4, PQ4_DATA),
-	PINMUX_GPIO(GPIO_PQ3, PQ3_DATA),
-	PINMUX_GPIO(GPIO_PQ2, PQ2_DATA),
-	PINMUX_GPIO(GPIO_PQ1, PQ1_DATA),
-	PINMUX_GPIO(GPIO_PQ0, PQ0_DATA),
+	PINMUX_GPIO(PQ4),
+	PINMUX_GPIO(PQ3),
+	PINMUX_GPIO(PQ2),
+	PINMUX_GPIO(PQ1),
+	PINMUX_GPIO(PQ0),
 
 	/* PR */
-	PINMUX_GPIO(GPIO_PR3, PR3_DATA),
-	PINMUX_GPIO(GPIO_PR2, PR2_DATA),
-	PINMUX_GPIO(GPIO_PR1, PR1_DATA),
-	PINMUX_GPIO(GPIO_PR0, PR0_DATA),
+	PINMUX_GPIO(PR3),
+	PINMUX_GPIO(PR2),
+	PINMUX_GPIO(PR1),
+	PINMUX_GPIO(PR0),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -1020,114 +989,114 @@ static const struct pinmux_func pinmux_func_gpios[] = {
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xffe70000, 16, 2) {
-		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
-		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
-		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 }
+		PA7_FN, PA7_OUT, PA7_IN, 0,
+		PA6_FN, PA6_OUT, PA6_IN, 0,
+		PA5_FN, PA5_OUT, PA5_IN, 0,
+		PA4_FN, PA4_OUT, PA4_IN, 0,
+		PA3_FN, PA3_OUT, PA3_IN, 0,
+		PA2_FN, PA2_OUT, PA2_IN, 0,
+		PA1_FN, PA1_OUT, PA1_IN, 0,
+		PA0_FN, PA0_OUT, PA0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PBCR", 0xffe70002, 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 }
+		PB7_FN, PB7_OUT, PB7_IN, 0,
+		PB6_FN, PB6_OUT, PB6_IN, 0,
+		PB5_FN, PB5_OUT, PB5_IN, 0,
+		PB4_FN, PB4_OUT, PB4_IN, 0,
+		PB3_FN, PB3_OUT, PB3_IN, 0,
+		PB2_FN, PB2_OUT, PB2_IN, 0,
+		PB1_FN, PB1_OUT, PB1_IN, 0,
+		PB0_FN, PB0_OUT, PB0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PCCR", 0xffe70004, 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 }
+		PC7_FN, PC7_OUT, PC7_IN, 0,
+		PC6_FN, PC6_OUT, PC6_IN, 0,
+		PC5_FN, PC5_OUT, PC5_IN, 0,
+		PC4_FN, PC4_OUT, PC4_IN, 0,
+		PC3_FN, PC3_OUT, PC3_IN, 0,
+		PC2_FN, PC2_OUT, PC2_IN, 0,
+		PC1_FN, PC1_OUT, PC1_IN, 0,
+		PC0_FN, PC0_OUT, PC0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PDCR", 0xffe70006, 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 }
+		PD7_FN, PD7_OUT, PD7_IN, 0,
+		PD6_FN, PD6_OUT, PD6_IN, 0,
+		PD5_FN, PD5_OUT, PD5_IN, 0,
+		PD4_FN, PD4_OUT, PD4_IN, 0,
+		PD3_FN, PD3_OUT, PD3_IN, 0,
+		PD2_FN, PD2_OUT, PD2_IN, 0,
+		PD1_FN, PD1_OUT, PD1_IN, 0,
+		PD0_FN, PD0_OUT, PD0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PECR", 0xffe70008, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PE5_FN, PE5_OUT, PE5_IN, PE5_IN_PU,
-		PE4_FN, PE4_OUT, PE4_IN, PE4_IN_PU,
-		PE3_FN, PE3_OUT, PE3_IN, PE3_IN_PU,
-		PE2_FN, PE2_OUT, PE2_IN, PE2_IN_PU,
-		PE1_FN, PE1_OUT, PE1_IN, PE1_IN_PU,
-		PE0_FN, PE0_OUT, PE0_IN, PE0_IN_PU }
+		PE5_FN, PE5_OUT, PE5_IN, 0,
+		PE4_FN, PE4_OUT, PE4_IN, 0,
+		PE3_FN, PE3_OUT, PE3_IN, 0,
+		PE2_FN, PE2_OUT, PE2_IN, 0,
+		PE1_FN, PE1_OUT, PE1_IN, 0,
+		PE0_FN, PE0_OUT, PE0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PFCR", 0xffe7000a, 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 }
+		PF7_FN, PF7_OUT, PF7_IN, 0,
+		PF6_FN, PF6_OUT, PF6_IN, 0,
+		PF5_FN, PF5_OUT, PF5_IN, 0,
+		PF4_FN, PF4_OUT, PF4_IN, 0,
+		PF3_FN, PF3_OUT, PF3_IN, 0,
+		PF2_FN, PF2_OUT, PF2_IN, 0,
+		PF1_FN, PF1_OUT, PF1_IN, 0,
+		PF0_FN, PF0_OUT, PF0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PGCR", 0xffe7000c, 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,
-		PG4_FN, PG4_OUT, PG4_IN, PG4_IN_PU,
-		PG3_FN, PG3_OUT, PG3_IN, PG3_IN_PU,
-		PG2_FN, PG2_OUT, PG2_IN, PG2_IN_PU,
-		PG1_FN, PG1_OUT, PG1_IN, PG1_IN_PU,
-		PG0_FN, PG0_OUT, PG0_IN, PG0_IN_PU }
+		PG7_FN, PG7_OUT, PG7_IN, 0,
+		PG6_FN, PG6_OUT, PG6_IN, 0,
+		PG5_FN, PG5_OUT, PG5_IN, 0,
+		PG4_FN, PG4_OUT, PG4_IN, 0,
+		PG3_FN, PG3_OUT, PG3_IN, 0,
+		PG2_FN, PG2_OUT, PG2_IN, 0,
+		PG1_FN, PG1_OUT, PG1_IN, 0,
+		PG0_FN, PG0_OUT, PG0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PHCR", 0xffe7000e, 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 }
+		PH7_FN, PH7_OUT, PH7_IN, 0,
+		PH6_FN, PH6_OUT, PH6_IN, 0,
+		PH5_FN, PH5_OUT, PH5_IN, 0,
+		PH4_FN, PH4_OUT, PH4_IN, 0,
+		PH3_FN, PH3_OUT, PH3_IN, 0,
+		PH2_FN, PH2_OUT, PH2_IN, 0,
+		PH1_FN, PH1_OUT, PH1_IN, 0,
+		PH0_FN, PH0_OUT, PH0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PJCR", 0xffe70010, 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,
-		PJ0_FN, PJ0_OUT, PJ0_IN, PJ0_IN_PU }
+		PJ7_FN, PJ7_OUT, PJ7_IN, 0,
+		PJ6_FN, PJ6_OUT, PJ6_IN, 0,
+		PJ5_FN, PJ5_OUT, PJ5_IN, 0,
+		PJ4_FN, PJ4_OUT, PJ4_IN, 0,
+		PJ3_FN, PJ3_OUT, PJ3_IN, 0,
+		PJ2_FN, PJ2_OUT, PJ2_IN, 0,
+		PJ1_FN, PJ1_OUT, PJ1_IN, 0,
+		PJ0_FN, PJ0_OUT, PJ0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PKCR", 0xffe70012, 16, 2) {
-		PK7_FN, PK7_OUT, PK7_IN, PK7_IN_PU,
-		PK6_FN, PK6_OUT, PK6_IN, PK6_IN_PU,
-		PK5_FN, PK5_OUT, PK5_IN, PK5_IN_PU,
-		PK4_FN, PK4_OUT, PK4_IN, PK4_IN_PU,
-		PK3_FN, PK3_OUT, PK3_IN, PK3_IN_PU,
-		PK2_FN, PK2_OUT, PK2_IN, PK2_IN_PU,
-		PK1_FN, PK1_OUT, PK1_IN, PK1_IN_PU,
-		PK0_FN, PK0_OUT, PK0_IN, PK0_IN_PU }
+		PK7_FN, PK7_OUT, PK7_IN, 0,
+		PK6_FN, PK6_OUT, PK6_IN, 0,
+		PK5_FN, PK5_OUT, PK5_IN, 0,
+		PK4_FN, PK4_OUT, PK4_IN, 0,
+		PK3_FN, PK3_OUT, PK3_IN, 0,
+		PK2_FN, PK2_OUT, PK2_IN, 0,
+		PK1_FN, PK1_OUT, PK1_IN, 0,
+		PK0_FN, PK0_OUT, PK0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PLCR", 0xffe70014, 16, 2) {
-		PL7_FN, PL7_OUT, PL7_IN, PL7_IN_PU,
-		PL6_FN, PL6_OUT, PL6_IN, PL6_IN_PU,
-		PL5_FN, PL5_OUT, PL5_IN, PL5_IN_PU,
-		PL4_FN, PL4_OUT, PL4_IN, PL4_IN_PU,
-		PL3_FN, PL3_OUT, PL3_IN, PL3_IN_PU,
-		PL2_FN, PL2_OUT, PL2_IN, PL2_IN_PU,
-		PL1_FN, PL1_OUT, PL1_IN, PL1_IN_PU,
-		PL0_FN, PL0_OUT, PL0_IN, PL0_IN_PU }
+		PL7_FN, PL7_OUT, PL7_IN, 0,
+		PL6_FN, PL6_OUT, PL6_IN, 0,
+		PL5_FN, PL5_OUT, PL5_IN, 0,
+		PL4_FN, PL4_OUT, PL4_IN, 0,
+		PL3_FN, PL3_OUT, PL3_IN, 0,
+		PL2_FN, PL2_OUT, PL2_IN, 0,
+		PL1_FN, PL1_OUT, PL1_IN, 0,
+		PL0_FN, PL0_OUT, PL0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PMCR", 0xffe70016, 16, 2) {
 		0, 0, 0, 0,
@@ -1136,48 +1105,48 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PM1_FN, PM1_OUT, PM1_IN, PM1_IN_PU,
-		PM0_FN, PM0_OUT, PM0_IN, PM0_IN_PU }
+		PM1_FN, PM1_OUT, PM1_IN, 0,
+		PM0_FN, PM0_OUT, PM0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PNCR", 0xffe70018, 16, 2) {
-		PN7_FN, PN7_OUT, PN7_IN, PN7_IN_PU,
-		PN6_FN, PN6_OUT, PN6_IN, PN6_IN_PU,
-		PN5_FN, PN5_OUT, PN5_IN, PN5_IN_PU,
-		PN4_FN, PN4_OUT, PN4_IN, PN4_IN_PU,
-		PN3_FN, PN3_OUT, PN3_IN, PN3_IN_PU,
-		PN2_FN, PN2_OUT, PN2_IN, PN2_IN_PU,
-		PN1_FN, PN1_OUT, PN1_IN, PN1_IN_PU,
-		PN0_FN, PN0_OUT, PN0_IN, PN0_IN_PU }
+		PN7_FN, PN7_OUT, PN7_IN, 0,
+		PN6_FN, PN6_OUT, PN6_IN, 0,
+		PN5_FN, PN5_OUT, PN5_IN, 0,
+		PN4_FN, PN4_OUT, PN4_IN, 0,
+		PN3_FN, PN3_OUT, PN3_IN, 0,
+		PN2_FN, PN2_OUT, PN2_IN, 0,
+		PN1_FN, PN1_OUT, PN1_IN, 0,
+		PN0_FN, PN0_OUT, PN0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PPCR", 0xffe7001a, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PP5_FN, PP5_OUT, PP5_IN, PP5_IN_PU,
-		PP4_FN, PP4_OUT, PP4_IN, PP4_IN_PU,
-		PP3_FN, PP3_OUT, PP3_IN, PP3_IN_PU,
-		PP2_FN, PP2_OUT, PP2_IN, PP2_IN_PU,
-		PP1_FN, PP1_OUT, PP1_IN, PP1_IN_PU,
-		PP0_FN, PP0_OUT, PP0_IN, PP0_IN_PU }
+		PP5_FN, PP5_OUT, PP5_IN, 0,
+		PP4_FN, PP4_OUT, PP4_IN, 0,
+		PP3_FN, PP3_OUT, PP3_IN, 0,
+		PP2_FN, PP2_OUT, PP2_IN, 0,
+		PP1_FN, PP1_OUT, PP1_IN, 0,
+		PP0_FN, PP0_OUT, PP0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PQCR", 0xffe7001c, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PQ4_FN, PQ4_OUT, PQ4_IN, PQ4_IN_PU,
-		PQ3_FN, PQ3_OUT, PQ3_IN, PQ3_IN_PU,
-		PQ2_FN, PQ2_OUT, PQ2_IN, PQ2_IN_PU,
-		PQ1_FN, PQ1_OUT, PQ1_IN, PQ1_IN_PU,
-		PQ0_FN, PQ0_OUT, PQ0_IN, PQ0_IN_PU }
+		PQ4_FN, PQ4_OUT, PQ4_IN, 0,
+		PQ3_FN, PQ3_OUT, PQ3_IN, 0,
+		PQ2_FN, PQ2_OUT, PQ2_IN, 0,
+		PQ1_FN, PQ1_OUT, PQ1_IN, 0,
+		PQ0_FN, PQ0_OUT, PQ0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("PRCR", 0xffe7001e, 16, 2) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		PR3_FN, PR3_OUT, PR3_IN, PR3_IN_PU,
-		PR2_FN, PR2_OUT, PR2_IN, PR2_IN_PU,
-		PR1_FN, PR1_OUT, PR1_IN, PR1_IN_PU,
-		PR0_FN, PR0_OUT, PR0_IN, PR0_IN_PU }
+		PR3_FN, PR3_OUT, PR3_IN, 0,
+		PR2_FN, PR2_OUT, PR2_IN, 0,
+		PR1_FN, PR1_OUT, PR1_IN, 0,
+		PR0_FN, PR0_OUT, PR0_IN, 0 }
 	},
 	{ PINMUX_CFG_REG("P1MSELR", 0xffe70080, 16, 1) {
 		P1MSEL15_0, P1MSEL15_1,
@@ -1289,7 +1258,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7785_pinmux_info = {
 	.name = "sh7785_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7786.c b/drivers/pinctrl/sh-pfc/pfc-sh7786.c
index 8ae0e32..623345f 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7786.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7786.c
@@ -60,25 +60,6 @@ enum {
 	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,
@@ -191,85 +172,84 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t pinmux_data[] = {
-
+static const u16 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),
+	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT),
+	PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT),
+	PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT),
+	PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT),
+	PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT),
+	PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT),
+	PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT),
+	PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT),
+	PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT),
+	PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT),
+	PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT),
+	PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT),
+	PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT),
+	PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT),
+	PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT),
+	PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT),
+	PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT),
+	PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT),
+	PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT),
+	PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT),
+	PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT),
+	PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT),
+	PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT),
+	PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT),
+	PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT),
+	PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT),
+	PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT),
+	PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT),
+	PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT),
 
 	/* PE GPIO */
-	PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT, PE7_IN_PU),
-	PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT, PE6_IN_PU),
+	PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT),
+	PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT),
 
 	/* 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),
+	PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT),
+	PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT),
+	PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT),
+	PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT),
+	PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT),
+	PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT),
+	PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT),
+	PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT),
+	PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT),
+	PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT),
 
 	/* 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),
+	PINMUX_DATA(PH7_DATA, PH7_IN, PH7_OUT),
+	PINMUX_DATA(PH6_DATA, PH6_IN, PH6_OUT),
+	PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT),
+	PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT),
+	PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT),
+	PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT),
+	PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT),
+	PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PJ7_DATA, PJ7_IN, PJ7_OUT),
+	PINMUX_DATA(PJ6_DATA, PJ6_IN, PJ6_OUT),
+	PINMUX_DATA(PJ5_DATA, PJ5_IN, PJ5_OUT),
+	PINMUX_DATA(PJ4_DATA, PJ4_IN, PJ4_OUT),
+	PINMUX_DATA(PJ3_DATA, PJ3_IN, PJ3_OUT),
+	PINMUX_DATA(PJ2_DATA, PJ2_IN, PJ2_OUT),
+	PINMUX_DATA(PJ1_DATA, PJ1_IN, PJ1_OUT),
 
 	/* PA FN */
 	PINMUX_DATA(CDE_MARK,		P1MSEL2_0, PA7_FN),
@@ -429,82 +409,82 @@ static const pinmux_enum_t pinmux_data[] = {
 
 static struct sh_pfc_pin pinmux_pins[] = {
 	/* 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),
+	PINMUX_GPIO(PA7),
+	PINMUX_GPIO(PA6),
+	PINMUX_GPIO(PA5),
+	PINMUX_GPIO(PA4),
+	PINMUX_GPIO(PA3),
+	PINMUX_GPIO(PA2),
+	PINMUX_GPIO(PA1),
+	PINMUX_GPIO(PA0),
 
 	/* 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),
+	PINMUX_GPIO(PB7),
+	PINMUX_GPIO(PB6),
+	PINMUX_GPIO(PB5),
+	PINMUX_GPIO(PB4),
+	PINMUX_GPIO(PB3),
+	PINMUX_GPIO(PB2),
+	PINMUX_GPIO(PB1),
+	PINMUX_GPIO(PB0),
 
 	/* 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),
+	PINMUX_GPIO(PC7),
+	PINMUX_GPIO(PC6),
+	PINMUX_GPIO(PC5),
+	PINMUX_GPIO(PC4),
+	PINMUX_GPIO(PC3),
+	PINMUX_GPIO(PC2),
+	PINMUX_GPIO(PC1),
+	PINMUX_GPIO(PC0),
 
 	/* 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),
+	PINMUX_GPIO(PD7),
+	PINMUX_GPIO(PD6),
+	PINMUX_GPIO(PD5),
+	PINMUX_GPIO(PD4),
+	PINMUX_GPIO(PD3),
+	PINMUX_GPIO(PD2),
+	PINMUX_GPIO(PD1),
+	PINMUX_GPIO(PD0),
 
 	/* PE */
-	PINMUX_GPIO(GPIO_PE7, PE7_DATA),
-	PINMUX_GPIO(GPIO_PE6, PE6_DATA),
+	PINMUX_GPIO(PE7),
+	PINMUX_GPIO(PE6),
 
 	/* 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),
+	PINMUX_GPIO(PF7),
+	PINMUX_GPIO(PF6),
+	PINMUX_GPIO(PF5),
+	PINMUX_GPIO(PF4),
+	PINMUX_GPIO(PF3),
+	PINMUX_GPIO(PF2),
+	PINMUX_GPIO(PF1),
+	PINMUX_GPIO(PF0),
 
 	/* PG */
-	PINMUX_GPIO(GPIO_PG7, PG7_DATA),
-	PINMUX_GPIO(GPIO_PG6, PG6_DATA),
-	PINMUX_GPIO(GPIO_PG5, PG5_DATA),
+	PINMUX_GPIO(PG7),
+	PINMUX_GPIO(PG6),
+	PINMUX_GPIO(PG5),
 
 	/* 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),
+	PINMUX_GPIO(PH7),
+	PINMUX_GPIO(PH6),
+	PINMUX_GPIO(PH5),
+	PINMUX_GPIO(PH4),
+	PINMUX_GPIO(PH3),
+	PINMUX_GPIO(PH2),
+	PINMUX_GPIO(PH1),
+	PINMUX_GPIO(PH0),
 
 	/* 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),
+	PINMUX_GPIO(PJ7),
+	PINMUX_GPIO(PJ6),
+	PINMUX_GPIO(PJ5),
+	PINMUX_GPIO(PJ4),
+	PINMUX_GPIO(PJ3),
+	PINMUX_GPIO(PJ2),
+	PINMUX_GPIO(PJ1),
 };
 
 #define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
@@ -651,48 +631,48 @@ static const struct pinmux_func pinmux_func_gpios[] = {
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xffcc0000, 16, 2) {
-		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
-		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
-		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 }
+		PA7_FN, PA7_OUT, PA7_IN, 0,
+		PA6_FN, PA6_OUT, PA6_IN, 0,
+		PA5_FN, PA5_OUT, PA5_IN, 0,
+		PA4_FN, PA4_OUT, PA4_IN, 0,
+		PA3_FN, PA3_OUT, PA3_IN, 0,
+		PA2_FN, PA2_OUT, PA2_IN, 0,
+		PA1_FN, PA1_OUT, PA1_IN, 0,
+		PA0_FN, PA0_OUT, PA0_IN, 0 }
 	},
 	{ 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 }
+		PB7_FN, PB7_OUT, PB7_IN, 0,
+		PB6_FN, PB6_OUT, PB6_IN, 0,
+		PB5_FN, PB5_OUT, PB5_IN, 0,
+		PB4_FN, PB4_OUT, PB4_IN, 0,
+		PB3_FN, PB3_OUT, PB3_IN, 0,
+		PB2_FN, PB2_OUT, PB2_IN, 0,
+		PB1_FN, PB1_OUT, PB1_IN, 0,
+		PB0_FN, PB0_OUT, PB0_IN, 0 }
 	},
 	{ 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 }
+		PC7_FN, PC7_OUT, PC7_IN, 0,
+		PC6_FN, PC6_OUT, PC6_IN, 0,
+		PC5_FN, PC5_OUT, PC5_IN, 0,
+		PC4_FN, PC4_OUT, PC4_IN, 0,
+		PC3_FN, PC3_OUT, PC3_IN, 0,
+		PC2_FN, PC2_OUT, PC2_IN, 0,
+		PC1_FN, PC1_OUT, PC1_IN, 0,
+		PC0_FN, PC0_OUT, PC0_IN, 0 }
 	},
 	{ 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 }
+		PD7_FN, PD7_OUT, PD7_IN, 0,
+		PD6_FN, PD6_OUT, PD6_IN, 0,
+		PD5_FN, PD5_OUT, PD5_IN, 0,
+		PD4_FN, PD4_OUT, PD4_IN, 0,
+		PD3_FN, PD3_OUT, PD3_IN, 0,
+		PD2_FN, PD2_OUT, PD2_IN, 0,
+		PD1_FN, PD1_OUT, PD1_IN, 0,
+		PD0_FN, PD0_OUT, PD0_IN, 0 }
 	},
 	{ 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,
+		PE7_FN, PE7_OUT, PE7_IN, 0,
+		PE6_FN, PE6_OUT, PE6_IN, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
@@ -701,19 +681,19 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		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 }
+		PF7_FN, PF7_OUT, PF7_IN, 0,
+		PF6_FN, PF6_OUT, PF6_IN, 0,
+		PF5_FN, PF5_OUT, PF5_IN, 0,
+		PF4_FN, PF4_OUT, PF4_IN, 0,
+		PF3_FN, PF3_OUT, PF3_IN, 0,
+		PF2_FN, PF2_OUT, PF2_IN, 0,
+		PF1_FN, PF1_OUT, PF1_IN, 0,
+		PF0_FN, PF0_OUT, PF0_IN, 0 }
 	},
 	{ 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,
+		PG7_FN, PG7_OUT, PG7_IN, 0,
+		PG6_FN, PG6_OUT, PG6_IN, 0,
+		PG5_FN, PG5_OUT, PG5_IN, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
@@ -721,23 +701,23 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 		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 }
+		PH7_FN, PH7_OUT, PH7_IN, 0,
+		PH6_FN, PH6_OUT, PH6_IN, 0,
+		PH5_FN, PH5_OUT, PH5_IN, 0,
+		PH4_FN, PH4_OUT, PH4_IN, 0,
+		PH3_FN, PH3_OUT, PH3_IN, 0,
+		PH2_FN, PH2_OUT, PH2_IN, 0,
+		PH1_FN, PH1_OUT, PH1_IN, 0,
+		PH0_FN, PH0_OUT, PH0_IN, 0 }
 	},
 	{ 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,
+		PJ7_FN, PJ7_OUT, PJ7_IN, 0,
+		PJ6_FN, PJ6_OUT, PJ6_IN, 0,
+		PJ5_FN, PJ5_OUT, PJ5_IN, 0,
+		PJ4_FN, PJ4_OUT, PJ4_IN, 0,
+		PJ3_FN, PJ3_OUT, PJ3_IN, 0,
+		PJ2_FN, PJ2_OUT, PJ2_IN, 0,
+		PJ1_FN, PJ1_OUT, PJ1_IN, 0,
 		0, 0, 0, 0, }
 	},
 	{ PINMUX_CFG_REG("P1MSELR", 0xffcc0080, 16, 1) {
@@ -822,7 +802,6 @@ static const struct pinmux_data_reg pinmux_data_regs[] = {
 const struct sh_pfc_soc_info sh7786_pinmux_info = {
 	.name = "sh7786_pfc",
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-shx3.c b/drivers/pinctrl/sh-pfc/pfc-shx3.c
index 6594c8c..55262bd 100644
--- a/drivers/pinctrl/sh-pfc/pfc-shx3.c
+++ b/drivers/pinctrl/sh-pfc/pfc-shx3.c
@@ -56,26 +56,6 @@ enum {
 	PH3_IN, PH2_IN, PH1_IN, PH0_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, PE5_IN_PU, PE4_IN_PU,
-	PE3_IN_PU, PE2_IN_PU, PE1_IN_PU, PE0_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, PG4_IN_PU,
-	PG3_IN_PU, PG2_IN_PU, PG1_IN_PU, PG0_IN_PU,
-
-	PH5_IN_PU, PH4_IN_PU,
-	PH3_IN_PU, PH2_IN_PU, PH1_IN_PU, PH0_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,
@@ -147,85 +127,84 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static const pinmux_enum_t shx3_pinmux_data[] = {
-
+static const u16 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),
+	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT),
+	PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT),
+	PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT),
+	PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT),
+	PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT),
+	PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT),
+	PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT),
+	PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT),
+	PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT),
+	PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT),
+	PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT),
+	PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT),
+	PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT),
+	PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT),
+	PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT),
+	PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT),
+	PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT),
+	PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT),
+	PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT),
+	PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT),
+	PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT),
+	PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT),
+	PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT),
+	PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT),
+	PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT),
+	PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT),
+	PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT),
+	PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT),
+	PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT),
 
 	/* PE GPIO */
-	PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT, PE7_IN_PU),
-	PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT, PE6_IN_PU),
-	PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT, PE5_IN_PU),
-	PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT, PE4_IN_PU),
-	PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT, PE3_IN_PU),
-	PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT, PE2_IN_PU),
-	PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT, PE1_IN_PU),
-	PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT, PE0_IN_PU),
+	PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT),
+	PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT),
+	PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT),
+	PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT),
+	PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT),
+	PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT),
+	PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT),
+	PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT),
 
 	/* 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),
+	PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT),
+	PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT),
+	PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT),
+	PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT),
+	PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT),
+	PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT),
+	PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT),
+	PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT),
 
 	/* 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),
-	PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT, PG4_IN_PU),
-	PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT, PG3_IN_PU),
-	PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT, PG2_IN_PU),
-	PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT, PG1_IN_PU),
-	PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT, PG0_IN_PU),
+	PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT),
+	PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT),
+	PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT),
+	PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT),
+	PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT),
+	PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT),
+	PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT),
+	PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT),
 
 	/* PH GPIO */
-	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),
+	PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT),
+	PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT),
+	PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT),
+	PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT),
+	PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT),
+	PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT),
 
 	/* PA FN */
 	PINMUX_DATA(D31_MARK, PA7_FN),
@@ -306,89 +285,89 @@ static const pinmux_enum_t shx3_pinmux_data[] = {
 	PINMUX_DATA(IRQOUT_MARK,	PH0_FN),
 };
 
-static struct sh_pfc_pin shx3_pinmux_pins[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* 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),
+	PINMUX_GPIO(PA7),
+	PINMUX_GPIO(PA6),
+	PINMUX_GPIO(PA5),
+	PINMUX_GPIO(PA4),
+	PINMUX_GPIO(PA3),
+	PINMUX_GPIO(PA2),
+	PINMUX_GPIO(PA1),
+	PINMUX_GPIO(PA0),
 
 	/* 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),
+	PINMUX_GPIO(PB7),
+	PINMUX_GPIO(PB6),
+	PINMUX_GPIO(PB5),
+	PINMUX_GPIO(PB4),
+	PINMUX_GPIO(PB3),
+	PINMUX_GPIO(PB2),
+	PINMUX_GPIO(PB1),
+	PINMUX_GPIO(PB0),
 
 	/* 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),
+	PINMUX_GPIO(PC7),
+	PINMUX_GPIO(PC6),
+	PINMUX_GPIO(PC5),
+	PINMUX_GPIO(PC4),
+	PINMUX_GPIO(PC3),
+	PINMUX_GPIO(PC2),
+	PINMUX_GPIO(PC1),
+	PINMUX_GPIO(PC0),
 
 	/* 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),
+	PINMUX_GPIO(PD7),
+	PINMUX_GPIO(PD6),
+	PINMUX_GPIO(PD5),
+	PINMUX_GPIO(PD4),
+	PINMUX_GPIO(PD3),
+	PINMUX_GPIO(PD2),
+	PINMUX_GPIO(PD1),
+	PINMUX_GPIO(PD0),
 
 	/* PE */
-	PINMUX_GPIO(GPIO_PE7, PE7_DATA),
-	PINMUX_GPIO(GPIO_PE6, PE6_DATA),
-	PINMUX_GPIO(GPIO_PE5, PE5_DATA),
-	PINMUX_GPIO(GPIO_PE4, PE4_DATA),
-	PINMUX_GPIO(GPIO_PE3, PE3_DATA),
-	PINMUX_GPIO(GPIO_PE2, PE2_DATA),
-	PINMUX_GPIO(GPIO_PE1, PE1_DATA),
-	PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+	PINMUX_GPIO(PE7),
+	PINMUX_GPIO(PE6),
+	PINMUX_GPIO(PE5),
+	PINMUX_GPIO(PE4),
+	PINMUX_GPIO(PE3),
+	PINMUX_GPIO(PE2),
+	PINMUX_GPIO(PE1),
+	PINMUX_GPIO(PE0),
 
 	/* 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),
+	PINMUX_GPIO(PF7),
+	PINMUX_GPIO(PF6),
+	PINMUX_GPIO(PF5),
+	PINMUX_GPIO(PF4),
+	PINMUX_GPIO(PF3),
+	PINMUX_GPIO(PF2),
+	PINMUX_GPIO(PF1),
+	PINMUX_GPIO(PF0),
 
 	/* PG */
-	PINMUX_GPIO(GPIO_PG7, PG7_DATA),
-	PINMUX_GPIO(GPIO_PG6, PG6_DATA),
-	PINMUX_GPIO(GPIO_PG5, PG5_DATA),
-	PINMUX_GPIO(GPIO_PG4, PG4_DATA),
-	PINMUX_GPIO(GPIO_PG3, PG3_DATA),
-	PINMUX_GPIO(GPIO_PG2, PG2_DATA),
-	PINMUX_GPIO(GPIO_PG1, PG1_DATA),
-	PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+	PINMUX_GPIO(PG7),
+	PINMUX_GPIO(PG6),
+	PINMUX_GPIO(PG5),
+	PINMUX_GPIO(PG4),
+	PINMUX_GPIO(PG3),
+	PINMUX_GPIO(PG2),
+	PINMUX_GPIO(PG1),
+	PINMUX_GPIO(PG0),
 
 	/* PH */
-	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),
+	PINMUX_GPIO(PH5),
+	PINMUX_GPIO(PH4),
+	PINMUX_GPIO(PH3),
+	PINMUX_GPIO(PH2),
+	PINMUX_GPIO(PH1),
+	PINMUX_GPIO(PH0),
 };
 
-#define PINMUX_FN_BASE	ARRAY_SIZE(shx3_pinmux_pins)
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
-static const struct pinmux_func shx3_pinmux_func_gpios[] = {
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* FN */
 	GPIO_FN(D31),
 	GPIO_FN(D30),
@@ -454,83 +433,83 @@ static const struct pinmux_func shx3_pinmux_func_gpios[] = {
 	GPIO_FN(IRQOUT),
 };
 
-static const struct pinmux_cfg_reg shx3_pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PABCR", 0xffc70000, 32, 2) {
-		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
-		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
-		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,
-		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, },
+		PA7_FN, PA7_OUT, PA7_IN, 0,
+		PA6_FN, PA6_OUT, PA6_IN, 0,
+		PA5_FN, PA5_OUT, PA5_IN, 0,
+		PA4_FN, PA4_OUT, PA4_IN, 0,
+		PA3_FN, PA3_OUT, PA3_IN, 0,
+		PA2_FN, PA2_OUT, PA2_IN, 0,
+		PA1_FN, PA1_OUT, PA1_IN, 0,
+		PA0_FN, PA0_OUT, PA0_IN, 0,
+		PB7_FN, PB7_OUT, PB7_IN, 0,
+		PB6_FN, PB6_OUT, PB6_IN, 0,
+		PB5_FN, PB5_OUT, PB5_IN, 0,
+		PB4_FN, PB4_OUT, PB4_IN, 0,
+		PB3_FN, PB3_OUT, PB3_IN, 0,
+		PB2_FN, PB2_OUT, PB2_IN, 0,
+		PB1_FN, PB1_OUT, PB1_IN, 0,
+		PB0_FN, PB0_OUT, PB0_IN, 0, },
 	},
 	{ PINMUX_CFG_REG("PCDCR", 0xffc70004, 32, 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,
-		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, },
+		PC7_FN, PC7_OUT, PC7_IN, 0,
+		PC6_FN, PC6_OUT, PC6_IN, 0,
+		PC5_FN, PC5_OUT, PC5_IN, 0,
+		PC4_FN, PC4_OUT, PC4_IN, 0,
+		PC3_FN, PC3_OUT, PC3_IN, 0,
+		PC2_FN, PC2_OUT, PC2_IN, 0,
+		PC1_FN, PC1_OUT, PC1_IN, 0,
+		PC0_FN, PC0_OUT, PC0_IN, 0,
+		PD7_FN, PD7_OUT, PD7_IN, 0,
+		PD6_FN, PD6_OUT, PD6_IN, 0,
+		PD5_FN, PD5_OUT, PD5_IN, 0,
+		PD4_FN, PD4_OUT, PD4_IN, 0,
+		PD3_FN, PD3_OUT, PD3_IN, 0,
+		PD2_FN, PD2_OUT, PD2_IN, 0,
+		PD1_FN, PD1_OUT, PD1_IN, 0,
+		PD0_FN, PD0_OUT, PD0_IN, 0, },
 	},
 	{ PINMUX_CFG_REG("PEFCR", 0xffc70008, 32, 2) {
-		PE7_FN, PE7_OUT, PE7_IN, PE7_IN_PU,
-		PE6_FN, PE6_OUT, PE6_IN, PE6_IN_PU,
-		PE5_FN, PE5_OUT, PE5_IN, PE5_IN_PU,
-		PE4_FN, PE4_OUT, PE4_IN, PE4_IN_PU,
-		PE3_FN, PE3_OUT, PE3_IN, PE3_IN_PU,
-		PE2_FN, PE2_OUT, PE2_IN, PE2_IN_PU,
-		PE1_FN, PE1_OUT, PE1_IN, PE1_IN_PU,
-		PE0_FN, PE0_OUT, PE0_IN, PE0_IN_PU,
-		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, },
+		PE7_FN, PE7_OUT, PE7_IN, 0,
+		PE6_FN, PE6_OUT, PE6_IN, 0,
+		PE5_FN, PE5_OUT, PE5_IN, 0,
+		PE4_FN, PE4_OUT, PE4_IN, 0,
+		PE3_FN, PE3_OUT, PE3_IN, 0,
+		PE2_FN, PE2_OUT, PE2_IN, 0,
+		PE1_FN, PE1_OUT, PE1_IN, 0,
+		PE0_FN, PE0_OUT, PE0_IN, 0,
+		PF7_FN, PF7_OUT, PF7_IN, 0,
+		PF6_FN, PF6_OUT, PF6_IN, 0,
+		PF5_FN, PF5_OUT, PF5_IN, 0,
+		PF4_FN, PF4_OUT, PF4_IN, 0,
+		PF3_FN, PF3_OUT, PF3_IN, 0,
+		PF2_FN, PF2_OUT, PF2_IN, 0,
+		PF1_FN, PF1_OUT, PF1_IN, 0,
+		PF0_FN, PF0_OUT, PF0_IN, 0, },
 	},
 	{ PINMUX_CFG_REG("PGHCR", 0xffc7000c, 32, 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,
-		PG4_FN, PG4_OUT, PG4_IN, PG4_IN_PU,
-		PG3_FN, PG3_OUT, PG3_IN, PG3_IN_PU,
-		PG2_FN, PG2_OUT, PG2_IN, PG2_IN_PU,
-		PG1_FN, PG1_OUT, PG1_IN, PG1_IN_PU,
-		PG0_FN, PG0_OUT, PG0_IN, PG0_IN_PU,
+		PG7_FN, PG7_OUT, PG7_IN, 0,
+		PG6_FN, PG6_OUT, PG6_IN, 0,
+		PG5_FN, PG5_OUT, PG5_IN, 0,
+		PG4_FN, PG4_OUT, PG4_IN, 0,
+		PG3_FN, PG3_OUT, PG3_IN, 0,
+		PG2_FN, PG2_OUT, PG2_IN, 0,
+		PG1_FN, PG1_OUT, PG1_IN, 0,
+		PG0_FN, PG0_OUT, PG0_IN, 0,
 		0, 0, 0, 0,
 		0, 0, 0, 0,
-		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, },
+		PH5_FN, PH5_OUT, PH5_IN, 0,
+		PH4_FN, PH4_OUT, PH4_IN, 0,
+		PH3_FN, PH3_OUT, PH3_IN, 0,
+		PH2_FN, PH2_OUT, PH2_IN, 0,
+		PH1_FN, PH1_OUT, PH1_IN, 0,
+		PH0_FN, PH0_OUT, PH0_IN, 0, },
 	},
 	{ },
 };
 
-static const struct pinmux_data_reg shx3_pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PABDR", 0xffc70010, 32) {
 		0, 0, 0, 0, 0, 0, 0, 0,
 		PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
@@ -569,16 +548,14 @@ static const struct pinmux_data_reg shx3_pinmux_data_regs[] = {
 const struct sh_pfc_soc_info shx3_pinmux_info = {
 	.name		= "shx3_pfc",
 	.input		= { PINMUX_INPUT_BEGIN,	   PINMUX_INPUT_END },
-	.input_pu	= { PINMUX_INPUT_PULLUP_BEGIN,
-			    PINMUX_INPUT_PULLUP_END },
 	.output		= { PINMUX_OUTPUT_BEGIN,   PINMUX_OUTPUT_END },
 	.function	= { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
-	.pins		= shx3_pinmux_pins,
-	.nr_pins	= ARRAY_SIZE(shx3_pinmux_pins),
-	.func_gpios	= shx3_pinmux_func_gpios,
-	.nr_func_gpios	= ARRAY_SIZE(shx3_pinmux_func_gpios),
-	.gpio_data	= shx3_pinmux_data,
-	.gpio_data_size	= ARRAY_SIZE(shx3_pinmux_data),
-	.cfg_regs	= shx3_pinmux_config_regs,
-	.data_regs	= shx3_pinmux_data_regs,
+	.pins		= pinmux_pins,
+	.nr_pins	= ARRAY_SIZE(pinmux_pins),
+	.func_gpios	= pinmux_func_gpios,
+	.nr_func_gpios	= ARRAY_SIZE(pinmux_func_gpios),
+	.gpio_data	= pinmux_data,
+	.gpio_data_size	= ARRAY_SIZE(pinmux_data),
+	.cfg_regs	= pinmux_config_regs,
+	.data_regs	= pinmux_data_regs,
 };
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index bc8b028..8649ec3 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -587,22 +587,9 @@ static const struct pinconf_ops sh_pfc_pinconf_ops = {
 /* PFC ranges -> pinctrl pin descs */
 static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
 {
-	const struct pinmux_range *ranges;
-	struct pinmux_range def_range;
-	unsigned int nr_ranges;
-	unsigned int nr_pins;
 	unsigned int i;
 
-	if (pfc->info->ranges == NULL) {
-		def_range.begin = 0;
-		def_range.end = pfc->info->nr_pins - 1;
-		ranges = &def_range;
-		nr_ranges = 1;
-	} else {
-		ranges = pfc->info->ranges;
-		nr_ranges = pfc->info->nr_ranges;
-	}
-
+	/* Allocate and initialize the pins and configs arrays. */
 	pmx->pins = devm_kzalloc(pfc->dev,
 				 sizeof(*pmx->pins) * pfc->info->nr_pins,
 				 GFP_KERNEL);
@@ -615,32 +602,24 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
 	if (unlikely(!pmx->configs))
 		return -ENOMEM;
 
-	for (i = 0, nr_pins = 0; i < nr_ranges; ++i) {
-		const struct pinmux_range *range = &ranges[i];
-		unsigned int number;
+	for (i = 0; i < pfc->info->nr_pins; ++i) {
+		const struct sh_pfc_pin *info = &pfc->info->pins[i];
+		struct sh_pfc_pin_config *cfg = &pmx->configs[i];
+		struct pinctrl_pin_desc *pin = &pmx->pins[i];
 
-		for (number = range->begin; number <= range->end;
-		     number++, nr_pins++) {
-			struct sh_pfc_pin_config *cfg = &pmx->configs[nr_pins];
-			struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins];
-			const struct sh_pfc_pin *info =
-				&pfc->info->pins[nr_pins];
-
-			pin->number = number;
-			pin->name = info->name;
-			cfg->type = PINMUX_TYPE_NONE;
-		}
+		/* If the pin number is equal to -1 all pins are considered */
+		pin->number = info->pin != (u16)-1 ? info->pin : i;
+		pin->name = info->name;
+		cfg->type = PINMUX_TYPE_NONE;
 	}
 
-	pfc->nr_pins = ranges[nr_ranges-1].end + 1;
-
-	return nr_ranges;
+	return 0;
 }
 
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 {
 	struct sh_pfc_pinctrl *pmx;
-	int nr_ranges;
+	int ret;
 
 	pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL);
 	if (unlikely(!pmx))
@@ -649,9 +628,9 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 	pmx->pfc = pfc;
 	pfc->pinctrl = pmx;
 
-	nr_ranges = sh_pfc_map_pins(pfc, pmx);
-	if (unlikely(nr_ranges < 0))
-		return nr_ranges;
+	ret = sh_pfc_map_pins(pfc, pmx);
+	if (ret < 0)
+		return ret;
 
 	pmx->pctl_desc.name = DRV_NAME;
 	pmx->pctl_desc.owner = THIS_MODULE;
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 830ae1f..11bd0d9 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -14,30 +14,23 @@
 #include <linux/bug.h>
 #include <linux/stringify.h>
 
-typedef unsigned short pinmux_enum_t;
-
-#define SH_PFC_MARK_INVALID	((pinmux_enum_t)-1)
-
 enum {
 	PINMUX_TYPE_NONE,
-
 	PINMUX_TYPE_FUNCTION,
 	PINMUX_TYPE_GPIO,
 	PINMUX_TYPE_OUTPUT,
 	PINMUX_TYPE_INPUT,
-	PINMUX_TYPE_INPUT_PULLUP,
-	PINMUX_TYPE_INPUT_PULLDOWN,
-
-	PINMUX_FLAG_TYPE,	/* must be last */
 };
 
 #define SH_PFC_PIN_CFG_INPUT		(1 << 0)
 #define SH_PFC_PIN_CFG_OUTPUT		(1 << 1)
 #define SH_PFC_PIN_CFG_PULL_UP		(1 << 2)
 #define SH_PFC_PIN_CFG_PULL_DOWN	(1 << 3)
+#define SH_PFC_PIN_CFG_NO_GPIO		(1 << 31)
 
 struct sh_pfc_pin {
-	const pinmux_enum_t enum_id;
+	u16 pin;
+	u16 enum_id;
 	const char *name;
 	unsigned int configs;
 };
@@ -71,46 +64,33 @@ struct sh_pfc_function {
 };
 
 struct pinmux_func {
-	const pinmux_enum_t enum_id;
+	u16 enum_id;
 	const char *name;
 };
 
-#define PINMUX_GPIO(gpio, data_or_mark)			\
-	[gpio] = {					\
-		.name = __stringify(gpio),		\
-		.enum_id = data_or_mark,		\
-	}
-#define PINMUX_GPIO_FN(gpio, base, data_or_mark)	\
-	[gpio - (base)] = {				\
-		.name = __stringify(gpio),		\
-		.enum_id = data_or_mark,		\
-	}
-
-#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
-
 struct pinmux_cfg_reg {
 	unsigned long reg, reg_width, field_width;
-	const pinmux_enum_t *enum_ids;
+	const u16 *enum_ids;
 	const unsigned long *var_field_width;
 };
 
 #define PINMUX_CFG_REG(name, r, r_width, f_width) \
 	.reg = r, .reg_width = r_width, .field_width = f_width,		\
-	.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)])
+	.enum_ids = (u16 [(r_width / f_width) * (1 << f_width)])
 
 #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
 	.reg = r, .reg_width = r_width,	\
 	.var_field_width = (unsigned long [r_width]) { var_fw0, var_fwn, 0 }, \
-	.enum_ids = (pinmux_enum_t [])
+	.enum_ids = (u16 [])
 
 struct pinmux_data_reg {
 	unsigned long reg, reg_width;
-	const pinmux_enum_t *enum_ids;
+	const u16 *enum_ids;
 };
 
 #define PINMUX_DATA_REG(name, r, r_width) \
 	.reg = r, .reg_width = r_width,	\
-	.enum_ids = (pinmux_enum_t [r_width]) \
+	.enum_ids = (u16 [r_width]) \
 
 struct pinmux_irq {
 	int irq;
@@ -121,9 +101,9 @@ struct pinmux_irq {
 	{ .irq = irq_nr, .gpios = (unsigned short []) { ids, 0 } }	\
 
 struct pinmux_range {
-	pinmux_enum_t begin;
-	pinmux_enum_t end;
-	pinmux_enum_t force;
+	u16 begin;
+	u16 end;
+	u16 force;
 };
 
 struct sh_pfc;
@@ -141,15 +121,11 @@ struct sh_pfc_soc_info {
 	const struct sh_pfc_soc_operations *ops;
 
 	struct pinmux_range input;
-	struct pinmux_range input_pd;
-	struct pinmux_range input_pu;
 	struct pinmux_range output;
 	struct pinmux_range function;
 
 	const struct sh_pfc_pin *pins;
 	unsigned int nr_pins;
-	const struct pinmux_range *ranges;
-	unsigned int nr_ranges;
 	const struct sh_pfc_pin_group *groups;
 	unsigned int nr_groups;
 	const struct sh_pfc_function *functions;
@@ -161,7 +137,7 @@ struct sh_pfc_soc_info {
 	const struct pinmux_cfg_reg *cfg_regs;
 	const struct pinmux_data_reg *data_regs;
 
-	const pinmux_enum_t *gpio_data;
+	const u16 *gpio_data;
 	unsigned int gpio_data_size;
 
 	const struct pinmux_irq *gpio_irq;
@@ -170,84 +146,155 @@ struct sh_pfc_soc_info {
 	unsigned long unlock_reg;
 };
 
-enum { GPIO_CFG_REQ, GPIO_CFG_FREE };
-
-/* helper macro for port */
-#define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define PORT_10(fn, pfx, sfx) \
-	PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx),	\
-	PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx),	\
-	PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx),	\
-	PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx),	\
-	PORT_1(fn, pfx##8, sfx), PORT_1(fn, pfx##9, sfx)
-
-#define PORT_10_REV(fn, pfx, sfx)	\
-	PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx),	\
-	PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx),	\
-	PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx),	\
-	PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx),	\
-	PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx)
-
-#define PORT_32(fn, pfx, sfx)					\
-	PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx),	\
-	PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx),	\
-	PORT_1(fn, pfx##31, sfx)
-
-#define PORT_32_REV(fn, pfx, sfx)					\
-	PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx),		\
-	PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx),	\
-	PORT_10_REV(fn, pfx, sfx)
-
-#define PORT_90(fn, pfx, sfx) \
-	PORT_10(fn, pfx##1, sfx), PORT_10(fn, pfx##2, sfx),	\
-	PORT_10(fn, pfx##3, sfx), PORT_10(fn, pfx##4, sfx),	\
-	PORT_10(fn, pfx##5, sfx), PORT_10(fn, pfx##6, sfx),	\
-	PORT_10(fn, pfx##7, sfx), PORT_10(fn, pfx##8, sfx),	\
-	PORT_10(fn, pfx##9, sfx)
-
-#define _PORT_ALL(pfx, sfx) pfx##_##sfx
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define PORT_ALL(str)	CPU_ALL_PORT(_PORT_ALL, PORT, str)
-#define GPIO_PORT_ALL()	CPU_ALL_PORT(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
-
-/* helper macro for pinmux_enum_t */
-#define PORT_DATA_I(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,			\
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)		\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,	\
-		    PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,	\
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,	\
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,	\
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-/* helper macro for top 4 bits in PORTnCR */
+/* -----------------------------------------------------------------------------
+ * Helper macros to create pin and port lists
+ */
+
+/*
+ * sh_pfc_soc_info gpio_data array macros
+ */
+
+#define PINMUX_DATA(data_or_mark, ids...)	data_or_mark, ids, 0
+
+#define PINMUX_IPSR_NOGP(ispr, fn)					\
+	PINMUX_DATA(fn##_MARK, FN_##fn)
+#define PINMUX_IPSR_DATA(ipsr, fn)					\
+	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)
+#define PINMUX_IPSR_NOGM(ispr, fn, ms)					\
+	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)
+#define PINMUX_IPSR_MSEL(ipsr, fn, ms)					\
+	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr, FN_##ms)
+#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms)				\
+	PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
+
+/*
+ * GP port style (32 ports banks)
+ */
+
+#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
+
+#define PORT_GP_32(bank, fn, sfx)					\
+	PORT_GP_1(bank, 0,  fn, sfx), PORT_GP_1(bank, 1,  fn, sfx),	\
+	PORT_GP_1(bank, 2,  fn, sfx), PORT_GP_1(bank, 3,  fn, sfx),	\
+	PORT_GP_1(bank, 4,  fn, sfx), PORT_GP_1(bank, 5,  fn, sfx),	\
+	PORT_GP_1(bank, 6,  fn, sfx), PORT_GP_1(bank, 7,  fn, sfx),	\
+	PORT_GP_1(bank, 8,  fn, sfx), PORT_GP_1(bank, 9,  fn, sfx),	\
+	PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx),	\
+	PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx),	\
+	PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx),	\
+	PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx),	\
+	PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx),	\
+	PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx),	\
+	PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx),	\
+	PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx),	\
+	PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx),	\
+	PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx),	\
+	PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
+
+#define PORT_GP_32_REV(bank, fn, sfx)					\
+	PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx),	\
+	PORT_GP_1(bank, 29, fn, sfx), PORT_GP_1(bank, 28, fn, sfx),	\
+	PORT_GP_1(bank, 27, fn, sfx), PORT_GP_1(bank, 26, fn, sfx),	\
+	PORT_GP_1(bank, 25, fn, sfx), PORT_GP_1(bank, 24, fn, sfx),	\
+	PORT_GP_1(bank, 23, fn, sfx), PORT_GP_1(bank, 22, fn, sfx),	\
+	PORT_GP_1(bank, 21, fn, sfx), PORT_GP_1(bank, 20, fn, sfx),	\
+	PORT_GP_1(bank, 19, fn, sfx), PORT_GP_1(bank, 18, fn, sfx),	\
+	PORT_GP_1(bank, 17, fn, sfx), PORT_GP_1(bank, 16, fn, sfx),	\
+	PORT_GP_1(bank, 15, fn, sfx), PORT_GP_1(bank, 14, fn, sfx),	\
+	PORT_GP_1(bank, 13, fn, sfx), PORT_GP_1(bank, 12, fn, sfx),	\
+	PORT_GP_1(bank, 11, fn, sfx), PORT_GP_1(bank, 10, fn, sfx),	\
+	PORT_GP_1(bank, 9,  fn, sfx), PORT_GP_1(bank, 8,  fn, sfx),	\
+	PORT_GP_1(bank, 7,  fn, sfx), PORT_GP_1(bank, 6,  fn, sfx),	\
+	PORT_GP_1(bank, 5,  fn, sfx), PORT_GP_1(bank, 4,  fn, sfx),	\
+	PORT_GP_1(bank, 3,  fn, sfx), PORT_GP_1(bank, 2,  fn, sfx),	\
+	PORT_GP_1(bank, 1,  fn, sfx), PORT_GP_1(bank, 0,  fn, sfx)
+
+/* GP_ALL(suffix) - Expand to a list of GP_#_#_suffix */
+#define _GP_ALL(bank, pin, name, sfx)	name##_##sfx
+#define GP_ALL(str)			CPU_ALL_PORT(_GP_ALL, str)
+
+/* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */
+#define _GP_GPIO(bank, _pin, _name, sfx)				\
+	[(bank * 32) + _pin] = {					\
+		.pin = (bank * 32) + _pin,				\
+		.name = __stringify(_name),				\
+		.enum_id = _name##_DATA,				\
+	}
+#define PINMUX_GPIO_GP_ALL()		CPU_ALL_PORT(_GP_GPIO, unused)
+
+/* PINMUX_DATA_GP_ALL -  Expand to a list of name_DATA, name_FN marks */
+#define _GP_DATA(bank, pin, name, sfx)	PINMUX_DATA(name##_DATA, name##_FN)
+#define PINMUX_DATA_GP_ALL()		CPU_ALL_PORT(_GP_DATA, unused)
+
+/*
+ * PORT style (linear pin space)
+ */
+
+#define PORT_1(pn, fn, pfx, sfx) fn(pn, pfx, sfx)
+
+#define PORT_10(pn, fn, pfx, sfx)					  \
+	PORT_1(pn,   fn, pfx##0, sfx), PORT_1(pn+1, fn, pfx##1, sfx),	  \
+	PORT_1(pn+2, fn, pfx##2, sfx), PORT_1(pn+3, fn, pfx##3, sfx),	  \
+	PORT_1(pn+4, fn, pfx##4, sfx), PORT_1(pn+5, fn, pfx##5, sfx),	  \
+	PORT_1(pn+6, fn, pfx##6, sfx), PORT_1(pn+7, fn, pfx##7, sfx),	  \
+	PORT_1(pn+8, fn, pfx##8, sfx), PORT_1(pn+9, fn, pfx##9, sfx)
+
+#define PORT_90(pn, fn, pfx, sfx)					  \
+	PORT_10(pn+10, fn, pfx##1, sfx), PORT_10(pn+20, fn, pfx##2, sfx), \
+	PORT_10(pn+30, fn, pfx##3, sfx), PORT_10(pn+40, fn, pfx##4, sfx), \
+	PORT_10(pn+50, fn, pfx##5, sfx), PORT_10(pn+60, fn, pfx##6, sfx), \
+	PORT_10(pn+70, fn, pfx##7, sfx), PORT_10(pn+80, fn, pfx##8, sfx), \
+	PORT_10(pn+90, fn, pfx##9, sfx)
+
+/* PORT_ALL(suffix) - Expand to a list of PORT_#_suffix */
+#define _PORT_ALL(pn, pfx, sfx)		pfx##_##sfx
+#define PORT_ALL(str)			CPU_ALL_PORT(_PORT_ALL, PORT, str)
+
+/* PINMUX_GPIO - Expand to a sh_pfc_pin entry */
+#define PINMUX_GPIO(_pin)						\
+	[GPIO_##_pin] = {						\
+		.pin = (u16)-1,						\
+		.name = __stringify(name),				\
+		.enum_id = _pin##_DATA,					\
+	}
+
+/* SH_PFC_PIN_CFG - Expand to a sh_pfc_pin entry (named PORT#) with config */
+#define SH_PFC_PIN_CFG(_pin, cfgs)					\
+	{								\
+		.pin = _pin,						\
+		.name = __stringify(PORT##_pin),			\
+		.enum_id = PORT##_pin##_DATA,				\
+		.configs = cfgs,					\
+	}
+
+/* SH_PFC_PIN_NAMED - Expand to a sh_pfc_pin entry with the given name */
+#define SH_PFC_PIN_NAMED(row, col, _name)				\
+	{								\
+		.pin = PIN_NUMBER(row, col),				\
+		.name = __stringify(PIN_##_name),			\
+		.configs = SH_PFC_PIN_CFG_NO_GPIO,			\
+	}
+
+/* PINMUX_DATA_ALL - Expand to a list of PORT_name_DATA, PORT_name_FN0,
+ *		     PORT_name_OUT, PORT_name_IN marks
+ */
+#define _PORT_DATA(pn, pfx, sfx)					\
+	PINMUX_DATA(PORT##pfx##_DATA, PORT##pfx##_FN0,			\
+		    PORT##pfx##_OUT, PORT##pfx##_IN)
+#define PINMUX_DATA_ALL()		CPU_ALL_PORT(_PORT_DATA, , unused)
+
+/* GPIO_FN(name) - Expand to a sh_pfc_pin entry for a function GPIO */
+#define PINMUX_GPIO_FN(gpio, base, data_or_mark)			\
+	[gpio - (base)] = {						\
+		.name = __stringify(gpio),				\
+		.enum_id = data_or_mark,				\
+	}
+#define GPIO_FN(str)							\
+	PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
+
+/*
+ * PORTnCR macro
+ */
 #define _PCRH(in, in_pd, in_pu, out)	\
 	0, (out), (in), 0,		\
 	0, 0, 0, 0,			\
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index 0677e19..26f946a 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -306,13 +306,13 @@ static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
        u32 *flags)
 {
        if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
-               return -EINVAL;
+		return -EINVAL;
 
        if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc)
-               return -EINVAL;
+		return -EINVAL;
 
        if (flags)
-               *flags = gpiospec->args[1];
+		*flags = gpiospec->args[1];
 
        return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE;
 }
@@ -440,6 +440,8 @@ static int sirfsoc_pinmux_resume_noirq(struct device *dev)
 static const struct dev_pm_ops sirfsoc_pinmux_pm_ops = {
 	.suspend_noirq = sirfsoc_pinmux_suspend_noirq,
 	.resume_noirq = sirfsoc_pinmux_resume_noirq,
+	.freeze_noirq = sirfsoc_pinmux_suspend_noirq,
+	.restore_noirq = sirfsoc_pinmux_resume_noirq,
 };
 #endif
 
@@ -831,7 +833,7 @@ static int sirfsoc_gpio_probe(struct device_node *np)
 {
 	int i, err = 0;
 	struct sirfsoc_gpio_bank *bank;
-	void *regs;
+	void __iomem *regs;
 	struct platform_device *pdev;
 	bool is_marco = false;
 
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 69616ae..57811ea 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -4,4 +4,3 @@ endif
 if GOLDFISH
 source "drivers/platform/goldfish/Kconfig"
 endif
-
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 8e268da..0e9c169 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -1543,7 +1543,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
 
 	/* TODO Find a better way to handle events count. */
 	count = asus->event_count[event % 128]++;
-	acpi_bus_generate_proc_event(asus->device, event, count);
 	acpi_bus_generate_netlink_event(asus->device->pnp.device_class,
 					dev_name(&asus->device->dev), event,
 					count);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 5d26e70..a6afd41 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1269,7 +1269,6 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
 	if (event > ACPI_MAX_SYS_NOTIFY)
 		return;
 	count = eeepc->event_count[event % 128]++;
-	acpi_bus_generate_proc_event(device, event, count);
 	acpi_bus_generate_netlink_event(device->pnp.device_class,
 					dev_name(&device->dev), event,
 					count);
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 1c9386e..52b8a97 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -773,8 +773,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
 				else
 					set_lcd_level(newb);
 			}
-			acpi_bus_generate_proc_event(fujitsu->dev,
-				ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
 			keycode = KEY_BRIGHTNESSUP;
 		} else if (oldb > newb) {
 			if (disable_brightness_adjust != 1) {
@@ -783,8 +781,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
 				else
 					set_lcd_level(newb);
 			}
-			acpi_bus_generate_proc_event(fujitsu->dev,
-				ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
 			keycode = KEY_BRIGHTNESSDOWN;
 		}
 		break;
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 4add9a3..984253d 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -464,9 +464,6 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 				 "error getting hotkey status\n"));
 		return;
 	}
-
-	acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
-
 	if (!sparse_keymap_report_event(hotk_input_dev,
 					result & 0xf, result & 0x80, false))
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c
index 1a90b62..4430b8c 100644
--- a/drivers/platform/x86/samsung-q10.c
+++ b/drivers/platform/x86/samsung-q10.c
@@ -176,7 +176,7 @@ static int __init samsungq10_init(void)
 						   samsungq10_probe,
 						   NULL, 0, NULL, 0);
 
-	return PTR_RET(samsungq10_device);
+	return PTR_ERR_OR_ZERO(samsungq10_device);
 }
 
 static void __exit samsungq10_exit(void)
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 2ac045f..069821b 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1275,9 +1275,6 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
 		ev_type = HOTKEY;
 		sony_laptop_report_input_event(real_ev);
 	}
-
-	acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev);
-
 	acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class,
 			dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev);
 }
@@ -4243,7 +4240,6 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
 
 found:
 	sony_laptop_report_input_event(device_event);
-	acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
 	sonypi_compat_report_event(device_event);
 	return IRQ_HANDLED;
 }
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 54d31c0..be67e5e 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -2022,8 +2022,6 @@ static u32 hotkey_driver_mask;		/* events needed by the driver */
 static u32 hotkey_user_mask;		/* events visible to userspace */
 static u32 hotkey_acpi_mask;		/* events enabled in firmware */
 
-static unsigned int hotkey_report_mode;
-
 static u16 *hotkey_keycode_map;
 
 static struct attribute_set *hotkey_dev_attributes;
@@ -2282,10 +2280,6 @@ static struct tp_acpi_drv_struct ibm_hotkey_acpidriver;
 static void tpacpi_hotkey_send_key(unsigned int scancode)
 {
 	tpacpi_input_send_key_masked(scancode);
-	if (hotkey_report_mode < 2) {
-		acpi_bus_generate_proc_event(ibm_hotkey_acpidriver.device,
-				0x80, TP_HKEY_EV_HOTKEY_BASE + scancode);
-	}
 }
 
 static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m)
@@ -2882,18 +2876,6 @@ static void hotkey_tablet_mode_notify_change(void)
 			     "hotkey_tablet_mode");
 }
 
-/* sysfs hotkey report_mode -------------------------------------------- */
-static ssize_t hotkey_report_mode_show(struct device *dev,
-			   struct device_attribute *attr,
-			   char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-		(hotkey_report_mode != 0) ? hotkey_report_mode : 1);
-}
-
-static struct device_attribute dev_attr_hotkey_report_mode =
-	__ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
-
 /* sysfs wakeup reason (pollable) -------------------------------------- */
 static ssize_t hotkey_wakeup_reason_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -2935,7 +2917,6 @@ static struct attribute *hotkey_attributes[] __initdata = {
 	&dev_attr_hotkey_enable.attr,
 	&dev_attr_hotkey_bios_enabled.attr,
 	&dev_attr_hotkey_bios_mask.attr,
-	&dev_attr_hotkey_report_mode.attr,
 	&dev_attr_hotkey_wakeup_reason.attr,
 	&dev_attr_hotkey_wakeup_hotunplug_complete.attr,
 	&dev_attr_hotkey_mask.attr,
@@ -3439,11 +3420,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		"initial masks: user=0x%08x, fw=0x%08x, poll=0x%08x\n",
 		hotkey_user_mask, hotkey_acpi_mask, hotkey_source_mask);
 
-	dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
-			"legacy ibm/hotkey event reporting over procfs %s\n",
-			(hotkey_report_mode < 2) ?
-				"enabled" : "disabled");
-
 	tpacpi_inputdev->open = &hotkey_inputdev_open;
 	tpacpi_inputdev->close = &hotkey_inputdev_close;
 
@@ -3737,13 +3713,6 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 				  "event happened to %s\n", TPACPI_MAIL);
 		}
 
-		/* Legacy events */
-		if (!ignore_acpi_ev &&
-		    (send_acpi_ev || hotkey_report_mode < 2)) {
-			acpi_bus_generate_proc_event(ibm->acpi->device,
-						     event, hkey);
-		}
-
 		/* netlink events */
 		if (!ignore_acpi_ev && send_acpi_ev) {
 			acpi_bus_generate_netlink_event(
@@ -8840,11 +8809,6 @@ module_param(brightness_enable, uint, 0444);
 MODULE_PARM_DESC(brightness_enable,
 		 "Enables backlight control when 1, disables when 0");
 
-module_param(hotkey_report_mode, uint, 0444);
-MODULE_PARM_DESC(hotkey_report_mode,
-		 "used for backwards compatibility with userspace, "
-		 "see documentation");
-
 #ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
 module_param_named(volume_mode, volume_mode, uint, 0444);
 MODULE_PARM_DESC(volume_mode,
@@ -8975,10 +8939,6 @@ static int __init thinkpad_acpi_module_init(void)
 
 	tpacpi_lifecycle = TPACPI_LIFE_INIT;
 
-	/* Parameter checking */
-	if (hotkey_report_mode > 2)
-		return -EINVAL;
-
 	/* Driver-level probe */
 
 	ret = get_thinkpad_model_data(&thinkpad_id);
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 00e9403..12adb43 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -154,7 +154,7 @@ static int pnp_bus_match(struct device *dev, struct device_driver *drv)
 	return 1;
 }
 
-static int pnp_bus_suspend(struct device *dev, pm_message_t state)
+static int __pnp_bus_suspend(struct device *dev, pm_message_t state)
 {
 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
 	struct pnp_driver *pnp_drv = pnp_dev->driver;
@@ -180,6 +180,16 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state)
 	return 0;
 }
 
+static int pnp_bus_suspend(struct device *dev)
+{
+	return __pnp_bus_suspend(dev, PMSG_SUSPEND);
+}
+
+static int pnp_bus_freeze(struct device *dev)
+{
+	return __pnp_bus_suspend(dev, PMSG_FREEZE);
+}
+
 static int pnp_bus_resume(struct device *dev)
 {
 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
@@ -210,14 +220,19 @@ static int pnp_bus_resume(struct device *dev)
 	return 0;
 }
 
+static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
+	.suspend = pnp_bus_suspend,
+	.freeze = pnp_bus_freeze,
+	.resume = pnp_bus_resume,
+};
+
 struct bus_type pnp_bus_type = {
 	.name    = "pnp",
 	.match   = pnp_bus_match,
 	.probe   = pnp_device_probe,
 	.remove  = pnp_device_remove,
 	.shutdown = pnp_device_shutdown,
-	.suspend = pnp_bus_suspend,
-	.resume  = pnp_bus_resume,
+	.pm	 = &pnp_bus_dev_pm_ops,
 	.dev_attrs = pnp_interface_attrs,
 };
 
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 55cd459..34049b0 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -131,7 +131,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
 	/* acpi_unregister_gsi(pnp_irq(dev, 0)); */
 	ret = 0;
 	if (acpi_bus_power_manageable(handle))
-		acpi_bus_set_power(handle, ACPI_STATE_D3);
+		acpi_bus_set_power(handle, ACPI_STATE_D3_COLD);
 		/* continue even if acpi_bus_set_power() fails */
 	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL)))
 		ret = -ENODEV;
@@ -174,10 +174,10 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
 
 	if (acpi_bus_power_manageable(handle)) {
 		int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
-							     ACPI_STATE_D3);
+							ACPI_STATE_D3_COLD);
 		if (power_state < 0)
 			power_state = (state.event == PM_EVENT_ON) ?
-					ACPI_STATE_D0 : ACPI_STATE_D3;
+					ACPI_STATE_D0 : ACPI_STATE_D3_COLD;
 
 		/*
 		 * acpi_bus_set_power() often fails (keyboard port can't be
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 4a8c388..a8319b2 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -330,7 +330,7 @@ static int __init ptp_init(void)
 		goto no_region;
 	}
 
-	ptp_class->dev_attrs = ptp_dev_attrs;
+	ptp_class->dev_groups = ptp_groups;
 	pr_info("PTP clock support registered\n");
 	return 0;
 
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 69d3207..df03f2e 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -84,7 +84,7 @@ uint ptp_poll(struct posix_clock *pc,
  * see ptp_sysfs.c
  */
 
-extern struct device_attribute ptp_dev_attrs[];
+extern const struct attribute_group *ptp_groups[];
 
 int ptp_cleanup_sysfs(struct ptp_clock *ptp);
 
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index 2f93926..13ec531 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -27,36 +27,43 @@ static ssize_t clock_name_show(struct device *dev,
 	struct ptp_clock *ptp = dev_get_drvdata(dev);
 	return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
 }
+static DEVICE_ATTR(clock_name, 0444, clock_name_show, NULL);
 
-#define PTP_SHOW_INT(name)						\
-static ssize_t name##_show(struct device *dev,				\
+#define PTP_SHOW_INT(name, var)						\
+static ssize_t var##_show(struct device *dev,				\
 			   struct device_attribute *attr, char *page)	\
 {									\
 	struct ptp_clock *ptp = dev_get_drvdata(dev);			\
-	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->name);	\
-}
-
-PTP_SHOW_INT(max_adj);
-PTP_SHOW_INT(n_alarm);
-PTP_SHOW_INT(n_ext_ts);
-PTP_SHOW_INT(n_per_out);
-PTP_SHOW_INT(pps);
+	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->var);	\
+}									\
+static DEVICE_ATTR(name, 0444, var##_show, NULL);
+
+PTP_SHOW_INT(max_adjustment, max_adj);
+PTP_SHOW_INT(n_alarms, n_alarm);
+PTP_SHOW_INT(n_external_timestamps, n_ext_ts);
+PTP_SHOW_INT(n_periodic_outputs, n_per_out);
+PTP_SHOW_INT(pps_available, pps);
+
+static struct attribute *ptp_attrs[] = {
+	&dev_attr_clock_name.attr,
+	&dev_attr_max_adjustment.attr,
+	&dev_attr_n_alarms.attr,
+	&dev_attr_n_external_timestamps.attr,
+	&dev_attr_n_periodic_outputs.attr,
+	&dev_attr_pps_available.attr,
+	NULL,
+};
 
-#define PTP_RO_ATTR(_var, _name) {				\
-	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
-	.show	= _var##_show,					\
-}
+static const struct attribute_group ptp_group = {
+	.attrs = ptp_attrs,
+};
 
-struct device_attribute ptp_dev_attrs[] = {
-	PTP_RO_ATTR(clock_name,	clock_name),
-	PTP_RO_ATTR(max_adj,	max_adjustment),
-	PTP_RO_ATTR(n_alarm,	n_alarms),
-	PTP_RO_ATTR(n_ext_ts,	n_external_timestamps),
-	PTP_RO_ATTR(n_per_out,	n_periodic_outputs),
-	PTP_RO_ATTR(pps,	pps_available),
-	__ATTR_NULL,
+const struct attribute_group *ptp_groups[] = {
+	&ptp_group,
+	NULL,
 };
 
+
 static ssize_t extts_enable_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index dfbfbc5..2ca9504 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -30,10 +30,9 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
-#define MAX_PWMS 1024
+#include <dt-bindings/pwm/pwm.h>
 
-/* flags in the third cell of the DT PWM specifier */
-#define PWM_SPEC_POLARITY	(1 << 0)
+#define MAX_PWMS 1024
 
 static DEFINE_MUTEX(pwm_lookup_lock);
 static LIST_HEAD(pwm_lookup_list);
@@ -149,7 +148,7 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 
 	pwm_set_period(pwm, args->args[1]);
 
-	if (args->args[2] & PWM_SPEC_POLARITY)
+	if (args->args[2] & PWM_POLARITY_INVERTED)
 		pwm_set_polarity(pwm, PWM_POLARITY_INVERSED);
 	else
 		pwm_set_polarity(pwm, PWM_POLARITY_NORMAL);
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index 2c77b81..c2c5a4f 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -161,9 +161,15 @@ static int mxs_pwm_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mxs);
 
-	stmp_reset_block(mxs->base);
+	ret = stmp_reset_block(mxs->base);
+	if (ret)
+		goto pwm_remove;
 
 	return 0;
+
+pwm_remove:
+	pwmchip_remove(&mxs->chip);
+	return ret;
 }
 
 static int mxs_pwm_remove(struct platform_device *pdev)
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 8ca5de3..8c20332 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -268,6 +268,7 @@ static ssize_t pwm_export_store(struct device *parent,
 
 	return ret ? : len;
 }
+static DEVICE_ATTR(export, 0200, NULL, pwm_export_store);
 
 static ssize_t pwm_unexport_store(struct device *parent,
 				  struct device_attribute *attr,
@@ -288,27 +289,29 @@ static ssize_t pwm_unexport_store(struct device *parent,
 
 	return ret ? : len;
 }
+static DEVICE_ATTR(unexport, 0200, NULL, pwm_unexport_store);
 
-static ssize_t pwm_npwm_show(struct device *parent,
-			     struct device_attribute *attr,
-			     char *buf)
+static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
+			 char *buf)
 {
 	const struct pwm_chip *chip = dev_get_drvdata(parent);
 
 	return sprintf(buf, "%u\n", chip->npwm);
 }
+static DEVICE_ATTR_RO(npwm);
 
-static struct device_attribute pwm_chip_attrs[] = {
-	__ATTR(export, 0200, NULL, pwm_export_store),
-	__ATTR(unexport, 0200, NULL, pwm_unexport_store),
-	__ATTR(npwm, 0444, pwm_npwm_show, NULL),
-	__ATTR_NULL,
+static struct attribute *pwm_chip_attrs[] = {
+	&dev_attr_export.attr,
+	&dev_attr_unexport.attr,
+	&dev_attr_npwm.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(pwm_chip);
 
 static struct class pwm_class = {
 	.name		= "pwm",
 	.owner		= THIS_MODULE,
-	.dev_attrs	= pwm_chip_attrs,
+	.dev_groups	= pwm_chip_groups,
 };
 
 static int pwmchip_sysfs_match(struct device *parent, const void *data)
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
new file mode 100644
index 0000000..c72fe95
--- /dev/null
+++ b/drivers/regulator/88pm800.c
@@ -0,0 +1,380 @@
+/*
+ * Regulators driver for Marvell 88PM800
+ *
+ * Copyright (C) 2012 Marvell International Ltd.
+ * Joseph(Yossi) Hanin <yhanin@marvell.com>
+ * Yi Zhang <yizhang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/88pm80x.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
+
+/* LDO1 with DVC[0..3] */
+#define PM800_LDO1_VOUT		(0x08) /* VOUT1 */
+#define PM800_LDO1_VOUT_2	(0x09)
+#define PM800_LDO1_VOUT_3	(0x0A)
+#define PM800_LDO2_VOUT		(0x0B)
+#define PM800_LDO3_VOUT		(0x0C)
+#define PM800_LDO4_VOUT		(0x0D)
+#define PM800_LDO5_VOUT		(0x0E)
+#define PM800_LDO6_VOUT		(0x0F)
+#define PM800_LDO7_VOUT		(0x10)
+#define PM800_LDO8_VOUT		(0x11)
+#define PM800_LDO9_VOUT		(0x12)
+#define PM800_LDO10_VOUT	(0x13)
+#define PM800_LDO11_VOUT	(0x14)
+#define PM800_LDO12_VOUT	(0x15)
+#define PM800_LDO13_VOUT	(0x16)
+#define PM800_LDO14_VOUT	(0x17)
+#define PM800_LDO15_VOUT	(0x18)
+#define PM800_LDO16_VOUT	(0x19)
+#define PM800_LDO17_VOUT	(0x1A)
+#define PM800_LDO18_VOUT	(0x1B)
+#define PM800_LDO19_VOUT	(0x1C)
+
+/* BUCK1 with DVC[0..3] */
+#define PM800_BUCK1		(0x3C)
+#define PM800_BUCK1_1		(0x3D)
+#define PM800_BUCK1_2		(0x3E)
+#define PM800_BUCK1_3		(0x3F)
+#define PM800_BUCK2		(0x40)
+#define PM800_BUCK3		(0x41)
+#define PM800_BUCK3		(0x41)
+#define PM800_BUCK4		(0x42)
+#define PM800_BUCK4_1		(0x43)
+#define PM800_BUCK4_2		(0x44)
+#define PM800_BUCK4_3		(0x45)
+#define PM800_BUCK5		(0x46)
+
+#define PM800_BUCK_ENA		(0x50)
+#define PM800_LDO_ENA1_1	(0x51)
+#define PM800_LDO_ENA1_2	(0x52)
+#define PM800_LDO_ENA1_3	(0x53)
+
+#define PM800_LDO_ENA2_1	(0x56)
+#define PM800_LDO_ENA2_2	(0x57)
+#define PM800_LDO_ENA2_3	(0x58)
+
+#define PM800_BUCK1_MISC1	(0x78)
+#define PM800_BUCK3_MISC1	(0x7E)
+#define PM800_BUCK4_MISC1	(0x81)
+#define PM800_BUCK5_MISC1	(0x84)
+
+struct pm800_regulator_info {
+	struct regulator_desc desc;
+	int max_ua;
+};
+
+struct pm800_regulators {
+	struct regulator_dev *regulators[PM800_ID_RG_MAX];
+	struct pm80x_chip *chip;
+	struct regmap *map;
+};
+
+/*
+ * vreg - the buck regs string.
+ * ereg - the string for the enable register.
+ * ebit - the bit number in the enable register.
+ * amax - the current
+ * Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges,
+ * not the constant voltage table.
+ * n_volt - Number of available selectors
+ */
+#define PM800_BUCK(vreg, ereg, ebit, amax, volt_ranges, n_volt)		\
+{									\
+	.desc	= {							\
+		.name	= #vreg,					\
+		.ops	= &pm800_volt_range_ops,			\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= PM800_ID_##vreg,				\
+		.owner	= THIS_MODULE,					\
+		.n_voltages		= n_volt,			\
+		.linear_ranges		= volt_ranges,			\
+		.n_linear_ranges	= ARRAY_SIZE(volt_ranges),	\
+		.vsel_reg		= PM800_##vreg,			\
+		.vsel_mask		= 0x7f,				\
+		.enable_reg		= PM800_##ereg,			\
+		.enable_mask		= 1 << (ebit),			\
+	},								\
+	.max_ua		= (amax),					\
+}
+
+/*
+ * vreg - the LDO regs string
+ * ereg -  the string for the enable register.
+ * ebit - the bit number in the enable register.
+ * amax - the current
+ * volt_table - the LDO voltage table
+ * For all the LDOes, there are too many ranges. Using volt_table will be
+ * simpler and faster.
+ */
+#define PM800_LDO(vreg, ereg, ebit, amax, ldo_volt_table)		\
+{									\
+	.desc	= {							\
+		.name	= #vreg,					\
+		.ops	= &pm800_volt_table_ops,			\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= PM800_ID_##vreg,				\
+		.owner	= THIS_MODULE,					\
+		.n_voltages = ARRAY_SIZE(ldo_volt_table),		\
+		.vsel_reg	= PM800_##vreg##_VOUT,			\
+		.vsel_mask	= 0x1f,					\
+		.enable_reg	= PM800_##ereg,				\
+		.enable_mask	= 1 << (ebit),				\
+		.volt_table	= ldo_volt_table,			\
+	},								\
+	.max_ua		= (amax),					\
+}
+
+/* Ranges are sorted in ascending order. */
+static const struct regulator_linear_range buck1_volt_range[] = {
+	{ .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
+	  .uV_step = 12500 },
+	{ .min_uV = 1600000, .max_uV = 1800000, .min_sel = 0x50,
+	  .max_sel = 0x54, .uV_step = 50000 },
+};
+
+/* BUCK 2~5 have same ranges. */
+static const struct regulator_linear_range buck2_5_volt_range[] = {
+	{ .min_uV = 600000, .max_uV = 1587500,	.min_sel = 0, .max_sel = 0x4f,
+	  .uV_step = 12500 },
+	{ .min_uV = 1600000, .max_uV = 3300000, .min_sel = 0x50,
+	  .max_sel = 0x72, .uV_step = 50000 },
+};
+
+static const unsigned int ldo1_volt_table[] = {
+	600000,  650000,  700000,  750000,  800000,  850000,  900000,  950000,
+	1000000, 1050000, 1100000, 1150000, 1200000, 1300000, 1400000, 1500000,
+};
+
+static const unsigned int ldo2_volt_table[] = {
+	1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000,
+};
+
+/* LDO 3~17 have same voltage table. */
+static const unsigned int ldo3_17_volt_table[] = {
+	1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000,
+	2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
+};
+
+/* LDO 18~19 have same voltage table. */
+static const unsigned int ldo18_19_volt_table[] = {
+	1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000,
+};
+
+static int pm800_get_current_limit(struct regulator_dev *rdev)
+{
+	struct pm800_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return info->max_ua;
+}
+
+static struct regulator_ops pm800_volt_range_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.get_current_limit = pm800_get_current_limit,
+};
+
+static struct regulator_ops pm800_volt_table_ops = {
+	.list_voltage = regulator_list_voltage_table,
+	.map_voltage = regulator_map_voltage_iterate,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.get_current_limit = pm800_get_current_limit,
+};
+
+/* The array is indexed by id(PM800_ID_XXX) */
+static struct pm800_regulator_info pm800_regulator_info[] = {
+	PM800_BUCK(BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55),
+	PM800_BUCK(BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73),
+	PM800_BUCK(BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73),
+	PM800_BUCK(BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73),
+	PM800_BUCK(BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73),
+
+	PM800_LDO(LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table),
+	PM800_LDO(LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table),
+	PM800_LDO(LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table),
+	PM800_LDO(LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table),
+	PM800_LDO(LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table),
+};
+
+#define PM800_REGULATOR_OF_MATCH(_name, _id)				\
+	[PM800_ID_##_id] = {						\
+		.name = #_name,						\
+		.driver_data = &pm800_regulator_info[PM800_ID_##_id],	\
+	}
+
+static struct of_regulator_match pm800_regulator_matches[] = {
+	PM800_REGULATOR_OF_MATCH(buck1, BUCK1),
+	PM800_REGULATOR_OF_MATCH(buck2, BUCK2),
+	PM800_REGULATOR_OF_MATCH(buck3, BUCK3),
+	PM800_REGULATOR_OF_MATCH(buck4, BUCK4),
+	PM800_REGULATOR_OF_MATCH(buck5, BUCK5),
+	PM800_REGULATOR_OF_MATCH(ldo1, LDO1),
+	PM800_REGULATOR_OF_MATCH(ldo2, LDO2),
+	PM800_REGULATOR_OF_MATCH(ldo3, LDO3),
+	PM800_REGULATOR_OF_MATCH(ldo4, LDO4),
+	PM800_REGULATOR_OF_MATCH(ldo5, LDO5),
+	PM800_REGULATOR_OF_MATCH(ldo6, LDO6),
+	PM800_REGULATOR_OF_MATCH(ldo7, LDO7),
+	PM800_REGULATOR_OF_MATCH(ldo8, LDO8),
+	PM800_REGULATOR_OF_MATCH(ldo9, LDO9),
+	PM800_REGULATOR_OF_MATCH(ldo10, LDO10),
+	PM800_REGULATOR_OF_MATCH(ldo11, LDO11),
+	PM800_REGULATOR_OF_MATCH(ldo12, LDO12),
+	PM800_REGULATOR_OF_MATCH(ldo13, LDO13),
+	PM800_REGULATOR_OF_MATCH(ldo14, LDO14),
+	PM800_REGULATOR_OF_MATCH(ldo15, LDO15),
+	PM800_REGULATOR_OF_MATCH(ldo16, LDO16),
+	PM800_REGULATOR_OF_MATCH(ldo17, LDO17),
+	PM800_REGULATOR_OF_MATCH(ldo18, LDO18),
+	PM800_REGULATOR_OF_MATCH(ldo19, LDO19),
+};
+
+static int pm800_regulator_dt_init(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	ret = of_regulator_match(&pdev->dev, np,
+				 pm800_regulator_matches,
+				 ARRAY_SIZE(pm800_regulator_matches));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int pm800_regulator_probe(struct platform_device *pdev)
+{
+	struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm80x_platform_data *pdata = dev_get_platdata(pdev->dev.parent);
+	struct pm800_regulators *pm800_data;
+	struct pm800_regulator_info *info;
+	struct regulator_config config = { };
+	struct regulator_init_data *init_data;
+	int i, ret;
+
+	if (!pdata || pdata->num_regulators == 0) {
+		if (IS_ENABLED(CONFIG_OF)) {
+			ret = pm800_regulator_dt_init(pdev);
+			if (ret)
+				return ret;
+		} else {
+			return -ENODEV;
+		}
+	} else if (pdata->num_regulators) {
+		/* Check whether num_regulator is valid. */
+		unsigned int count = 0;
+		for (i = 0; pdata->regulators[i]; i++)
+			count++;
+		if (count != pdata->num_regulators)
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
+
+	pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data),
+					GFP_KERNEL);
+	if (!pm800_data) {
+		dev_err(&pdev->dev, "Failed to allocate pm800_regualtors");
+		return -ENOMEM;
+	}
+
+	pm800_data->map = chip->subchip->regmap_power;
+	pm800_data->chip = chip;
+
+	platform_set_drvdata(pdev, pm800_data);
+
+	for (i = 0; i < PM800_ID_RG_MAX; i++) {
+		if (!pdata || pdata->num_regulators == 0)
+			init_data = pm800_regulator_matches[i].init_data;
+		else
+			init_data = pdata->regulators[i];
+		if (!init_data)
+			continue;
+		info = pm800_regulator_matches[i].driver_data;
+		config.dev = &pdev->dev;
+		config.init_data = init_data;
+		config.driver_data = info;
+		config.regmap = pm800_data->map;
+		config.of_node = pm800_regulator_matches[i].of_node;
+
+		pm800_data->regulators[i] =
+				regulator_register(&info->desc, &config);
+		if (IS_ERR(pm800_data->regulators[i])) {
+			ret = PTR_ERR(pm800_data->regulators[i]);
+			dev_err(&pdev->dev, "Failed to register %s\n",
+				info->desc.name);
+
+			while (--i >= 0)
+				regulator_unregister(pm800_data->regulators[i]);
+
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int pm800_regulator_remove(struct platform_device *pdev)
+{
+	struct pm800_regulators *pm800_data = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < PM800_ID_RG_MAX; i++)
+		regulator_unregister(pm800_data->regulators[i]);
+
+	return 0;
+}
+
+static struct platform_driver pm800_regulator_driver = {
+	.driver		= {
+		.name	= "88pm80x-regulator",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pm800_regulator_probe,
+	.remove		= pm800_regulator_remove,
+};
+
+module_platform_driver(pm800_regulator_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Joseph(Yossi) Hanin <yhanin@marvell.com>");
+MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM800 PMIC");
+MODULE_ALIAS("platform:88pm800-regulator");
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 8a7cb1f..7023097 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -346,7 +346,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm8607_regulator_info *info = NULL;
-	struct regulator_init_data *pdata = pdev->dev.platform_data;
+	struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
 	struct regulator_config config = { };
 	struct resource *res;
 	int i;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index f1e6ad9..a0f0bc4 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -64,15 +64,21 @@ config REGULATOR_USERSPACE_CONSUMER
 
 	  If unsure, say no.
 
-config REGULATOR_GPIO
-	tristate "GPIO regulator support"
-	depends on GPIOLIB
+config REGULATOR_88PM800
+	tristate "Marvell 88PM800 Power regulators"
+	depends on MFD_88PM800
 	help
-	  This driver provides support for regulators that can be
-	  controlled via gpios.
-	  It is capable of supporting current and voltage regulators
-	  and the platform has to provide a mapping of GPIO-states
-	  to target volts/amps.
+	  This driver supports Marvell 88PM800 voltage regulator chips.
+	  It delivers digitally programmable output,
+	  the voltage is programmed via I2C interface.
+	  It's suitable to support PXA988 chips to control VCC_MAIN and
+	  various voltages.
+
+config REGULATOR_88PM8607
+	bool "Marvell 88PM8607 Power regulators"
+	depends on MFD_88PM860X=y
+	help
+	  This driver supports 88PM8607 voltage regulator chips.
 
 config REGULATOR_AD5398
 	tristate "Analog Devices AD5398/AD5821 regulators"
@@ -81,6 +87,14 @@ config REGULATOR_AD5398
 	  This driver supports AD5398 and AD5821 current regulator chips.
 	  If building into module, its name is ad5398.ko.
 
+config REGULATOR_ANATOP
+	tristate "Freescale i.MX on-chip ANATOP LDO regulators"
+	depends on MFD_SYSCON
+	help
+	  Say y here to support Freescale i.MX on-chip ANATOP LDOs
+	  regulators. It is recommended that this option be
+	  enabled on i.MX6 platform.
+
 config REGULATOR_AAT2870
 	tristate "AnalogicTech AAT2870 Regulators"
 	depends on MFD_AAT2870_CORE
@@ -88,6 +102,22 @@ config REGULATOR_AAT2870
 	  If you have a AnalogicTech AAT2870 say Y to enable the
 	  regulator driver.
 
+config REGULATOR_AB3100
+	tristate "ST-Ericsson AB3100 Regulator functions"
+	depends on AB3100_CORE
+	default y if AB3100_CORE
+	help
+	 These regulators correspond to functionality in the
+	 AB3100 analog baseband dealing with power regulators
+	 for the system.
+
+config REGULATOR_AB8500
+	bool "ST-Ericsson AB8500 Power Regulators"
+	depends on AB8500_CORE
+	help
+	  This driver supports the regulators found on the ST-Ericsson mixed
+	  signal AB8500 PMIC
+
 config REGULATOR_ARIZONA
 	tristate "Wolfson Arizona class devices"
 	depends on MFD_ARIZONA
@@ -96,6 +126,13 @@ config REGULATOR_ARIZONA
 	  Support for the regulators found on Wolfson Arizona class
 	  devices.
 
+config REGULATOR_AS3711
+	tristate "AS3711 PMIC"
+	depends on MFD_AS3711
+	help
+	  This driver provides support for the voltage regulators on the
+	  AS3711 PMIC
+
 config REGULATOR_DA903X
 	tristate "Dialog Semiconductor DA9030/DA9034 regulators"
 	depends on PMIC_DA903X
@@ -120,6 +157,27 @@ config REGULATOR_DA9055
 	  This driver can also be built as a module. If so, the module
 	  will be called da9055-regulator.
 
+config REGULATOR_DA9210
+	tristate "Dialog Semiconductor DA9210 regulator"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Say y here to support for the Dialog Semiconductor DA9210.
+	  The DA9210 is a multi-phase synchronous step down
+	  converter 12A DC-DC Buck controlled through an I2C
+	  interface.
+
+config REGULATOR_DBX500_PRCMU
+	bool
+
+config REGULATOR_DB8500_PRCMU
+	bool "ST-Ericsson DB8500 Voltage Domain Regulators"
+	depends on MFD_DB8500_PRCMU
+	select REGULATOR_DBX500_PRCMU
+	help
+	  This driver supports the voltage domain regulators controlled by the
+	  DB8500 PRCMU
+
 config REGULATOR_FAN53555
 	tristate "Fairchild FAN53555 Regulator"
 	depends on I2C
@@ -131,44 +189,57 @@ config REGULATOR_FAN53555
 	  input voltage supply of 2.5V to 5.5V. The output voltage is
 	  programmed through an I2C interface.
 
-config REGULATOR_ANATOP
-	tristate "Freescale i.MX on-chip ANATOP LDO regulators"
-	depends on MFD_SYSCON
+config REGULATOR_GPIO
+	tristate "GPIO regulator support"
+	depends on GPIOLIB
 	help
-	  Say y here to support Freescale i.MX on-chip ANATOP LDOs
-	  regulators. It is recommended that this option be
-	  enabled on i.MX6 platform.
+	  This driver provides support for regulators that can be
+	  controlled via gpios.
+	  It is capable of supporting current and voltage regulators
+	  and the platform has to provide a mapping of GPIO-states
+	  to target volts/amps.
 
-config REGULATOR_MC13XXX_CORE
-	tristate
+config REGULATOR_ISL6271A
+	tristate "Intersil ISL6271A Power regulator"
+	depends on I2C
+	help
+	  This driver supports ISL6271A voltage regulator chip.
 
-config REGULATOR_MC13783
-	tristate "Freescale MC13783 regulator driver"
-	depends on MFD_MC13783
-	select REGULATOR_MC13XXX_CORE
+config REGULATOR_LP3971
+	tristate "National Semiconductors LP3971 PMIC regulator driver"
+	depends on I2C
 	help
-	  Say y here to support the regulators found on the Freescale MC13783
-	  PMIC.
+	 Say Y here to support the voltage regulators and convertors
+	 on National Semiconductors LP3971 PMIC
 
-config REGULATOR_MC13892
-	tristate "Freescale MC13892 regulator driver"
-	depends on MFD_MC13XXX
-	select REGULATOR_MC13XXX_CORE
+config REGULATOR_LP3972
+	tristate "National Semiconductors LP3972 PMIC regulator driver"
+	depends on I2C
 	help
-	  Say y here to support the regulators found on the Freescale MC13892
-	  PMIC.
+	 Say Y here to support the voltage regulators and convertors
+	 on National Semiconductors LP3972 PMIC
 
-config REGULATOR_ISL6271A
-	tristate "Intersil ISL6271A Power regulator"
+config REGULATOR_LP872X
+	bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
+	depends on I2C=y
+	select REGMAP_I2C
+	help
+	  This driver supports LP8720/LP8725 PMIC
+
+config REGULATOR_LP8755
+	tristate "TI LP8755 High Performance PMU driver"
 	depends on I2C
+	select REGMAP_I2C
 	help
-	  This driver supports ISL6271A voltage regulator chip.
+	  This driver supports LP8755 High Performance PMU driver. This
+	  chip contains six step-down DC/DC converters which can support
+	  9 mode multiphase configuration.
 
-config REGULATOR_88PM8607
-	bool "Marvell 88PM8607 Power regulators"
-	depends on MFD_88PM860X=y
+config REGULATOR_LP8788
+	bool "TI LP8788 Power Regulators"
+	depends on MFD_LP8788
 	help
-	  This driver supports 88PM8607 voltage regulator chips.
+	  This driver supports LP8788 voltage regulator chip.
 
 config REGULATOR_MAX1586
 	tristate "Maxim 1586/1587 voltage regulator"
@@ -259,48 +330,43 @@ config REGULATOR_MAX77693
 	  and one current regulator 'CHARGER'. This is suitable for
 	  Exynos-4x12 chips.
 
-config REGULATOR_PCAP
-	tristate "Motorola PCAP2 regulator driver"
-	depends on EZX_PCAP
-	help
-	 This driver provides support for the voltage regulators of the
-	 PCAP2 PMIC.
+config REGULATOR_MC13XXX_CORE
+	tristate
 
-config REGULATOR_LP3971
-	tristate "National Semiconductors LP3971 PMIC regulator driver"
-	depends on I2C
+config REGULATOR_MC13783
+	tristate "Freescale MC13783 regulator driver"
+	depends on MFD_MC13783
+	select REGULATOR_MC13XXX_CORE
 	help
-	 Say Y here to support the voltage regulators and convertors
-	 on National Semiconductors LP3971 PMIC
+	  Say y here to support the regulators found on the Freescale MC13783
+	  PMIC.
 
-config REGULATOR_LP3972
-	tristate "National Semiconductors LP3972 PMIC regulator driver"
-	depends on I2C
+config REGULATOR_MC13892
+	tristate "Freescale MC13892 regulator driver"
+	depends on MFD_MC13XXX
+	select REGULATOR_MC13XXX_CORE
 	help
-	 Say Y here to support the voltage regulators and convertors
-	 on National Semiconductors LP3972 PMIC
+	  Say y here to support the regulators found on the Freescale MC13892
+	  PMIC.
 
-config REGULATOR_LP872X
-	bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
-	depends on I2C=y
-	select REGMAP_I2C
+config REGULATOR_PALMAS
+	tristate "TI Palmas PMIC Regulators"
+	depends on MFD_PALMAS
 	help
-	  This driver supports LP8720/LP8725 PMIC
+	  If you wish to control the regulators on the Palmas series of
+	  chips say Y here. This will enable support for all the software
+	  controllable SMPS/LDO regulators.
 
-config REGULATOR_LP8755
-	tristate "TI LP8755 High Performance PMU driver"
-	depends on I2C
-	select REGMAP_I2C
-	help
-	  This driver supports LP8755 High Performance PMU driver. This
-	  chip contains six step-down DC/DC converters which can support
-	  9 mode multiphase configuration.
+	  The regulators available on Palmas series chips vary depending
+	  on the muxing. This is handled automatically in the driver by
+	  reading the mux info from OTP.
 
-config REGULATOR_LP8788
-	bool "TI LP8788 Power Regulators"
-	depends on MFD_LP8788
+config REGULATOR_PCAP
+	tristate "Motorola PCAP2 regulator driver"
+	depends on EZX_PCAP
 	help
-	  This driver supports LP8788 voltage regulator chip.
+	 This driver provides support for the voltage regulators of the
+	 PCAP2 PMIC.
 
 config REGULATOR_PCF50633
 	tristate "NXP PCF50633 regulator driver"
@@ -309,6 +375,14 @@ config REGULATOR_PCF50633
 	 Say Y here to support the voltage regulators and convertors
 	 on PCF50633
 
+config REGULATOR_PFUZE100
+	tristate "Support regulators on Freescale PFUZE100 PMIC"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Say y here to support the regulators found on the Freescale PFUZE100
+	  PMIC.
+
 config REGULATOR_RC5T583
 	tristate "RICOH RC5T583 Power regulators"
 	depends on MFD_RC5T583
@@ -335,44 +409,15 @@ config REGULATOR_S5M8767
 	 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
 	 supports DVS mode with 8bits of output voltage control.
 
-config REGULATOR_AB3100
-	tristate "ST-Ericsson AB3100 Regulator functions"
-	depends on AB3100_CORE
-	default y if AB3100_CORE
-	help
-	 These regulators correspond to functionality in the
-	 AB3100 analog baseband dealing with power regulators
-	 for the system.
-
-config REGULATOR_AB8500
-	bool "ST-Ericsson AB8500 Power Regulators"
-	depends on AB8500_CORE
-	help
-	  This driver supports the regulators found on the ST-Ericsson mixed
-	  signal AB8500 PMIC
-
-config REGULATOR_DBX500_PRCMU
-	bool
-
-config REGULATOR_DB8500_PRCMU
-	bool "ST-Ericsson DB8500 Voltage Domain Regulators"
-	depends on MFD_DB8500_PRCMU
-	select REGULATOR_DBX500_PRCMU
-	help
-	  This driver supports the voltage domain regulators controlled by the
-	  DB8500 PRCMU
-
-config REGULATOR_PALMAS
-	tristate "TI Palmas PMIC Regulators"
-	depends on MFD_PALMAS
+config REGULATOR_TI_ABB
+	bool "TI Adaptive Body Bias on-chip LDO"
+	depends on ARCH_OMAP
 	help
-	  If you wish to control the regulators on the Palmas series of
-	  chips say Y here. This will enable support for all the software
-	  controllable SMPS/LDO regulators.
-
-	  The regulators available on Palmas series chips vary depending
-	  on the muxing. This is handled automatically in the driver by
-	  reading the mux info from OTP.
+	  Select this option to support Texas Instruments' on-chip Adaptive Body
+	  Bias (ABB) LDO regulators. It is recommended that this option be
+	  enabled on required TI SoC. Certain Operating Performance Points
+	  on TI SoCs may be unstable without enabling this as it provides
+	  device specific optimized bias to allow/optimize functionality.
 
 config REGULATOR_TPS51632
 	tristate "TI TPS51632 Power Regulator"
@@ -481,16 +526,6 @@ config REGULATOR_TWL4030
 	  This driver supports the voltage regulators provided by
 	  this family of companion chips.
 
-config REGULATOR_TI_ABB
-	bool "TI Adaptive Body Bias on-chip LDO"
-	depends on ARCH_OMAP
-	help
-	  Select this option to support Texas Instruments' on-chip Adaptive Body
-	  Bias (ABB) LDO regulators. It is recommended that this option be
-	  enabled on required TI SoC. Certain Operating Performance Points
-	  on TI SoCs may be unstable without enabling this as it provides
-	  device specific optimized bias to allow/optimize functionality.
-
 config REGULATOR_VEXPRESS
 	tristate "Versatile Express regulators"
 	depends on VEXPRESS_CONFIG
@@ -526,12 +561,5 @@ config REGULATOR_WM8994
 	  This driver provides support for the voltage regulators on the
 	  WM8994 CODEC.
 
-config REGULATOR_AS3711
-	tristate "AS3711 PMIC"
-	depends on MFD_AS3711
-	help
-	  This driver provides support for the voltage regulators on the
-	  AS3711 PMIC
-
 endif
 
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ba4a3cf..6d141a9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -3,12 +3,13 @@
 #
 
 
-obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o
+obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o
 obj-$(CONFIG_OF) += of_regulator.o
 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
 
+obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o
 obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
 obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DA9055)	+= da9055-regulator.o
+obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
@@ -46,12 +48,14 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
 obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
@@ -64,7 +68,6 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
-obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index 8b58763..881159d 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -174,7 +174,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
 
 	config.dev = &pdev->dev;
 	config.driver_data = ri;
-	config.init_data = pdev->dev.platform_data;
+	config.init_data = dev_get_platdata(&pdev->dev);
 
 	rdev = regulator_register(&ri->desc, &config);
 	if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 3be9e46..7d5eaa8 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -660,7 +660,7 @@ ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 
 static int ab3100_regulators_probe(struct platform_device *pdev)
 {
-	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
+	struct ab3100_platform_data *plfdata = dev_get_platdata(&pdev->dev);
 	struct device_node *np = pdev->dev.of_node;
 	int err = 0;
 	u8 data;
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index 6b981b5..b2b203c 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -214,7 +214,7 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id);
 static int ad5398_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
-	struct regulator_init_data *init_data = client->dev.platform_data;
+	struct regulator_init_data *init_data = dev_get_platdata(&client->dev);
 	struct regulator_config config = { };
 	struct ad5398_chip_info *chip;
 	const struct ad5398_current_data_format *df =
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index 3da6bd6..8406cd7 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -30,102 +30,6 @@ struct as3711_regulator {
 	struct regulator_dev *rdev;
 };
 
-static int as3711_list_voltage_sd(struct regulator_dev *rdev,
-				  unsigned int selector)
-{
-	if (selector >= rdev->desc->n_voltages)
-		return -EINVAL;
-
-	if (!selector)
-		return 0;
-	if (selector < 0x41)
-		return 600000 + selector * 12500;
-	if (selector < 0x71)
-		return 1400000 + (selector - 0x40) * 25000;
-	return 2600000 + (selector - 0x70) * 50000;
-}
-
-static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
-				    unsigned int selector)
-{
-	if (selector >= rdev->desc->n_voltages)
-		return -EINVAL;
-
-	if (selector < 0x10)
-		return 1200000 + selector * 50000;
-	return 1800000 + (selector - 0x10) * 100000;
-}
-
-static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
-				    unsigned int selector)
-{
-	if (selector >= rdev->desc->n_voltages ||
-	    (selector > 0x10 && selector < 0x20))
-		return -EINVAL;
-
-	if (selector < 0x11)
-		return 900000 + selector * 50000;
-	return 1750000 + (selector - 0x20) * 50000;
-}
-
-static int as3711_bound_check(struct regulator_dev *rdev,
-			      int *min_uV, int *max_uV)
-{
-	struct as3711_regulator *reg = rdev_get_drvdata(rdev);
-	struct as3711_regulator_info *info = reg->reg_info;
-
-	dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
-		*min_uV, rdev->desc->min_uV, info->max_uV);
-
-	if (*max_uV < *min_uV ||
-	    *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
-		return -EINVAL;
-
-	if (rdev->desc->n_voltages == 1)
-		return 0;
-
-	if (*max_uV > info->max_uV)
-		*max_uV = info->max_uV;
-
-	if (*min_uV < rdev->desc->min_uV)
-		*min_uV = rdev->desc->min_uV;
-
-	return *min_uV;
-}
-
-static int as3711_sel_check(int min, int max, int bottom, int step)
-{
-	int sel, voltage;
-
-	/* Round up min, when dividing: keeps us within the range */
-	sel = DIV_ROUND_UP(min - bottom, step);
-	voltage = sel * step + bottom;
-	pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
-	       min, max, bottom, step, sel);
-	if (voltage > max)
-		return -EINVAL;
-
-	return sel;
-}
-
-static int as3711_map_voltage_sd(struct regulator_dev *rdev,
-				 int min_uV, int max_uV)
-{
-	int ret;
-
-	ret = as3711_bound_check(rdev, &min_uV, &max_uV);
-	if (ret <= 0)
-		return ret;
-
-	if (min_uV <= 1400000)
-		return as3711_sel_check(min_uV, max_uV, 600000, 12500);
-
-	if (min_uV <= 2600000)
-		return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
-
-	return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
-}
-
 /*
  * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
  * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
@@ -180,44 +84,14 @@ static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
 	return -EINVAL;
 }
 
-static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
-				  int min_uV, int max_uV)
-{
-	int ret;
-
-	ret = as3711_bound_check(rdev, &min_uV, &max_uV);
-	if (ret <= 0)
-		return ret;
-
-	if (min_uV <= 1800000)
-		return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
-
-	return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
-}
-
-static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
-				  int min_uV, int max_uV)
-{
-	int ret;
-
-	ret = as3711_bound_check(rdev, &min_uV, &max_uV);
-	if (ret <= 0)
-		return ret;
-
-	if (min_uV <= 1700000)
-		return as3711_sel_check(min_uV, max_uV, 900000, 50000);
-
-	return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
-}
-
 static struct regulator_ops as3711_sd_ops = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.list_voltage		= as3711_list_voltage_sd,
-	.map_voltage		= as3711_map_voltage_sd,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
 	.get_mode		= as3711_get_mode_sd,
 	.set_mode		= as3711_set_mode_sd,
 };
@@ -228,8 +102,8 @@ static struct regulator_ops as3711_aldo_ops = {
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.list_voltage		= as3711_list_voltage_aldo,
-	.map_voltage		= as3711_map_voltage_aldo,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
 };
 
 static struct regulator_ops as3711_dldo_ops = {
@@ -238,8 +112,31 @@ static struct regulator_ops as3711_dldo_ops = {
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.list_voltage		= as3711_list_voltage_dldo,
-	.map_voltage		= as3711_map_voltage_dldo,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+};
+
+static const struct regulator_linear_range as3711_sd_ranges[] = {
+	{ .min_uV = 612500, .max_uV = 1400000,
+	  .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 },
+	{ .min_uV = 1425000, .max_uV = 2600000,
+	  .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 },
+	{ .min_uV = 2650000, .max_uV = 3350000,
+	  .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 },
+};
+
+static const struct regulator_linear_range as3711_aldo_ranges[] = {
+	{ .min_uV = 1200000, .max_uV = 1950000,
+	  .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 },
+	{ .min_uV = 1800000, .max_uV = 3300000,
+	  .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 },
+};
+
+static const struct regulator_linear_range as3711_dldo_ranges[] = {
+	{ .min_uV = 900000, .max_uV = 1700000,
+	  .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 },
+	{ .min_uV = 1750000, .max_uV = 3300000,
+	  .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 },
 };
 
 #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)	\
@@ -256,6 +153,8 @@ static struct regulator_ops as3711_dldo_ops = {
 		.enable_reg = AS3711_ ## _en_reg,					\
 		.enable_mask = BIT(_en_bit),						\
 		.min_uV	= _min_uV,							\
+		.linear_ranges = as3711_ ## _sfx ## _ranges,				\
+		.n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges),		\
 	},										\
 	.max_uV = _max_uV,								\
 }
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 288c75a..78b8dea 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -323,13 +323,14 @@ static ssize_t regulator_uA_show(struct device *dev,
 }
 static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
 
-static ssize_t regulator_name_show(struct device *dev,
-			     struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%s\n", rdev_get_name(rdev));
 }
+static DEVICE_ATTR_RO(name);
 
 static ssize_t regulator_print_opmode(char *buf, int mode)
 {
@@ -489,15 +490,16 @@ static ssize_t regulator_total_uA_show(struct device *dev,
 }
 static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
 
-static ssize_t regulator_num_users_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
+static ssize_t num_users_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	return sprintf(buf, "%d\n", rdev->use_count);
 }
+static DEVICE_ATTR_RO(num_users);
 
-static ssize_t regulator_type_show(struct device *dev,
-				  struct device_attribute *attr, char *buf)
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
@@ -509,6 +511,7 @@ static ssize_t regulator_type_show(struct device *dev,
 	}
 	return sprintf(buf, "unknown\n");
 }
+static DEVICE_ATTR_RO(type);
 
 static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -632,12 +635,13 @@ static DEVICE_ATTR(bypass, 0444,
  * These are the only attributes are present for all regulators.
  * Other attributes are a function of regulator functionality.
  */
-static struct device_attribute regulator_dev_attrs[] = {
-	__ATTR(name, 0444, regulator_name_show, NULL),
-	__ATTR(num_users, 0444, regulator_num_users_show, NULL),
-	__ATTR(type, 0444, regulator_type_show, NULL),
-	__ATTR_NULL,
+static struct attribute *regulator_dev_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_num_users.attr,
+	&dev_attr_type.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(regulator_dev);
 
 static void regulator_dev_release(struct device *dev)
 {
@@ -648,7 +652,7 @@ static void regulator_dev_release(struct device *dev)
 static struct class regulator_class = {
 	.name = "regulator",
 	.dev_release = regulator_dev_release,
-	.dev_attrs = regulator_dev_attrs,
+	.dev_groups = regulator_dev_groups,
 };
 
 /* Calculate the new optimum regulator operating mode based on the new total
@@ -984,7 +988,8 @@ static int set_machine_constraints(struct regulator_dev *rdev,
 		}
 	}
 
-	if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
+	if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
+		&& ops->set_ramp_delay) {
 		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
 		if (ret < 0) {
 			rdev_err(rdev, "failed to set ramp_delay\n");
@@ -1409,6 +1414,65 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
+/**
+ * regulator_get_optional - obtain optional access to a regulator.
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Returns a struct regulator corresponding to the regulator producer,
+ * or IS_ERR() condition containing errno.  Other consumers will be
+ * unable to obtain this reference is held and the use count for the
+ * regulator will be initialised to reflect the current state of the
+ * regulator.
+ *
+ * This is intended for use by consumers for devices which can have
+ * some supplies unconnected in normal use, such as some MMC devices.
+ * It can allow the regulator core to provide stub supplies for other
+ * supplies requested using normal regulator_get() calls without
+ * disrupting the operation of drivers that can handle absent
+ * supplies.
+ *
+ * Use of supply names configured via regulator_set_device_supply() is
+ * strongly encouraged.  It is recommended that the supply name used
+ * should match the name used for the supply and/or the relevant
+ * device pins in the datasheet.
+ */
+struct regulator *regulator_get_optional(struct device *dev, const char *id)
+{
+	return _regulator_get(dev, id, 0);
+}
+EXPORT_SYMBOL_GPL(regulator_get_optional);
+
+/**
+ * devm_regulator_get_optional - Resource managed regulator_get_optional()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_optional(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * regulator_get_optional() for more information.
+ */
+struct regulator *devm_regulator_get_optional(struct device *dev,
+					      const char *id)
+{
+	struct regulator **ptr, *regulator;
+
+	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	regulator = regulator_get_optional(dev, id);
+	if (!IS_ERR(regulator)) {
+		*ptr = regulator;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return regulator;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
+
 /* Locks held by regulator_put() */
 static void _regulator_put(struct regulator *regulator)
 {
@@ -1890,8 +1954,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
 	rdev->deferred_disables++;
 	mutex_unlock(&rdev->mutex);
 
-	ret = schedule_delayed_work(&rdev->disable_work,
-				    msecs_to_jiffies(ms));
+	ret = queue_delayed_work(system_power_efficient_wq,
+				 &rdev->disable_work,
+				 msecs_to_jiffies(ms));
 	if (ret < 0)
 		return ret;
 	else
@@ -1899,77 +1964,6 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
 }
 EXPORT_SYMBOL_GPL(regulator_disable_deferred);
 
-/**
- * regulator_is_enabled_regmap - standard is_enabled() for regmap users
- *
- * @rdev: regulator to operate on
- *
- * Regulators that use regmap for their register I/O can set the
- * enable_reg and enable_mask fields in their descriptor and then use
- * this as their is_enabled operation, saving some code.
- */
-int regulator_is_enabled_regmap(struct regulator_dev *rdev)
-{
-	unsigned int val;
-	int ret;
-
-	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
-	if (ret != 0)
-		return ret;
-
-	if (rdev->desc->enable_is_inverted)
-		return (val & rdev->desc->enable_mask) == 0;
-	else
-		return (val & rdev->desc->enable_mask) != 0;
-}
-EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
-
-/**
- * regulator_enable_regmap - standard enable() for regmap users
- *
- * @rdev: regulator to operate on
- *
- * Regulators that use regmap for their register I/O can set the
- * enable_reg and enable_mask fields in their descriptor and then use
- * this as their enable() operation, saving some code.
- */
-int regulator_enable_regmap(struct regulator_dev *rdev)
-{
-	unsigned int val;
-
-	if (rdev->desc->enable_is_inverted)
-		val = 0;
-	else
-		val = rdev->desc->enable_mask;
-
-	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-				  rdev->desc->enable_mask, val);
-}
-EXPORT_SYMBOL_GPL(regulator_enable_regmap);
-
-/**
- * regulator_disable_regmap - standard disable() for regmap users
- *
- * @rdev: regulator to operate on
- *
- * Regulators that use regmap for their register I/O can set the
- * enable_reg and enable_mask fields in their descriptor and then use
- * this as their disable() operation, saving some code.
- */
-int regulator_disable_regmap(struct regulator_dev *rdev)
-{
-	unsigned int val;
-
-	if (rdev->desc->enable_is_inverted)
-		val = rdev->desc->enable_mask;
-	else
-		val = 0;
-
-	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-				  rdev->desc->enable_mask, val);
-}
-EXPORT_SYMBOL_GPL(regulator_disable_regmap);
-
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
 	/* A GPIO control always takes precedence */
@@ -2079,6 +2073,43 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
 EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
 
 /**
+ * regulator_list_voltage_linear_range - List voltages for linear ranges
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a series of simple linear mappings between voltages
+ * and selectors can set linear_ranges in the regulator descriptor and
+ * then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
+					unsigned int selector)
+{
+	const struct regulator_linear_range *range;
+	int i;
+
+	if (!rdev->desc->n_linear_ranges) {
+		BUG_ON(!rdev->desc->n_linear_ranges);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
+		range = &rdev->desc->linear_ranges[i];
+
+		if (!(selector >= range->min_sel &&
+		      selector <= range->max_sel))
+			continue;
+
+		selector -= range->min_sel;
+
+		return range->min_uV + (range->uV_step * selector);
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
+
+/**
  * regulator_list_voltage_table - List voltages with table based mapping
  *
  * @rdev: Regulator device
@@ -2197,177 +2228,6 @@ int regulator_is_supported_voltage(struct regulator *regulator,
 }
 EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
 
-/**
- * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
- *
- * @rdev: regulator to operate on
- *
- * Regulators that use regmap for their register I/O can set the
- * vsel_reg and vsel_mask fields in their descriptor and then use this
- * as their get_voltage_vsel operation, saving some code.
- */
-int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
-{
-	unsigned int val;
-	int ret;
-
-	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
-	if (ret != 0)
-		return ret;
-
-	val &= rdev->desc->vsel_mask;
-	val >>= ffs(rdev->desc->vsel_mask) - 1;
-
-	return val;
-}
-EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
-
-/**
- * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
- *
- * @rdev: regulator to operate on
- * @sel: Selector to set
- *
- * Regulators that use regmap for their register I/O can set the
- * vsel_reg and vsel_mask fields in their descriptor and then use this
- * as their set_voltage_vsel operation, saving some code.
- */
-int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
-{
-	int ret;
-
-	sel <<= ffs(rdev->desc->vsel_mask) - 1;
-
-	ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
-				  rdev->desc->vsel_mask, sel);
-	if (ret)
-		return ret;
-
-	if (rdev->desc->apply_bit)
-		ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
-					 rdev->desc->apply_bit,
-					 rdev->desc->apply_bit);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
-
-/**
- * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
- *
- * @rdev: Regulator to operate on
- * @min_uV: Lower bound for voltage
- * @max_uV: Upper bound for voltage
- *
- * Drivers implementing set_voltage_sel() and list_voltage() can use
- * this as their map_voltage() operation.  It will find a suitable
- * voltage by calling list_voltage() until it gets something in bounds
- * for the requested voltages.
- */
-int regulator_map_voltage_iterate(struct regulator_dev *rdev,
-				  int min_uV, int max_uV)
-{
-	int best_val = INT_MAX;
-	int selector = 0;
-	int i, ret;
-
-	/* Find the smallest voltage that falls within the specified
-	 * range.
-	 */
-	for (i = 0; i < rdev->desc->n_voltages; i++) {
-		ret = rdev->desc->ops->list_voltage(rdev, i);
-		if (ret < 0)
-			continue;
-
-		if (ret < best_val && ret >= min_uV && ret <= max_uV) {
-			best_val = ret;
-			selector = i;
-		}
-	}
-
-	if (best_val != INT_MAX)
-		return selector;
-	else
-		return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
-
-/**
- * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list
- *
- * @rdev: Regulator to operate on
- * @min_uV: Lower bound for voltage
- * @max_uV: Upper bound for voltage
- *
- * Drivers that have ascendant voltage list can use this as their
- * map_voltage() operation.
- */
-int regulator_map_voltage_ascend(struct regulator_dev *rdev,
-				 int min_uV, int max_uV)
-{
-	int i, ret;
-
-	for (i = 0; i < rdev->desc->n_voltages; i++) {
-		ret = rdev->desc->ops->list_voltage(rdev, i);
-		if (ret < 0)
-			continue;
-
-		if (ret > max_uV)
-			break;
-
-		if (ret >= min_uV && ret <= max_uV)
-			return i;
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
-
-/**
- * regulator_map_voltage_linear - map_voltage() for simple linear mappings
- *
- * @rdev: Regulator to operate on
- * @min_uV: Lower bound for voltage
- * @max_uV: Upper bound for voltage
- *
- * Drivers providing min_uV and uV_step in their regulator_desc can
- * use this as their map_voltage() operation.
- */
-int regulator_map_voltage_linear(struct regulator_dev *rdev,
-				 int min_uV, int max_uV)
-{
-	int ret, voltage;
-
-	/* Allow uV_step to be 0 for fixed voltage */
-	if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
-		if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
-			return 0;
-		else
-			return -EINVAL;
-	}
-
-	if (!rdev->desc->uV_step) {
-		BUG_ON(!rdev->desc->uV_step);
-		return -EINVAL;
-	}
-
-	if (min_uV < rdev->desc->min_uV)
-		min_uV = rdev->desc->min_uV;
-
-	ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
-	if (ret < 0)
-		return ret;
-
-	ret += rdev->desc->linear_min_sel;
-
-	/* Map back into a voltage to verify we're still in bounds */
-	voltage = rdev->desc->ops->list_voltage(rdev, ret);
-	if (voltage < min_uV || voltage > max_uV)
-		return -EINVAL;
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
-
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 				     int min_uV, int max_uV)
 {
@@ -2438,8 +2298,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 	}
 
 	/* Call set_voltage_time_sel if successfully obtained old_selector */
-	if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
-	    old_selector != selector && rdev->desc->ops->set_voltage_time_sel) {
+	if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0
+		&& old_selector != selector) {
 
 		delay = rdev->desc->ops->set_voltage_time_sel(rdev,
 						old_selector, selector);
@@ -2971,47 +2831,6 @@ out:
 EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
 
 /**
- * regulator_set_bypass_regmap - Default set_bypass() using regmap
- *
- * @rdev: device to operate on.
- * @enable: state to set.
- */
-int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
-{
-	unsigned int val;
-
-	if (enable)
-		val = rdev->desc->bypass_mask;
-	else
-		val = 0;
-
-	return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
-				  rdev->desc->bypass_mask, val);
-}
-EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
-
-/**
- * regulator_get_bypass_regmap - Default get_bypass() using regmap
- *
- * @rdev: device to operate on.
- * @enable: current state.
- */
-int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
-{
-	unsigned int val;
-	int ret;
-
-	ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
-	if (ret != 0)
-		return ret;
-
-	*enable = val & rdev->desc->bypass_mask;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
-
-/**
  * regulator_allow_bypass - allow the regulator to go into bypass mode
  *
  * @regulator: Regulator to configure
@@ -3740,8 +3559,11 @@ void regulator_unregister(struct regulator_dev *rdev)
 	if (rdev == NULL)
 		return;
 
-	if (rdev->supply)
+	if (rdev->supply) {
+		while (rdev->use_count--)
+			regulator_disable(rdev->supply);
 		regulator_put(rdev->supply);
+	}
 	mutex_lock(&regulator_list_mutex);
 	debugfs_remove_recursive(rdev->debugfs);
 	flush_work(&rdev->disable_work.work);
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 2afa573..f06854c 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -252,39 +252,12 @@ static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
 	return ret;
 }
 
-static int da9034_map_ldo12_voltage(struct regulator_dev *rdev,
-				    int min_uV, int max_uV)
-{
-	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-	int sel;
-
-	if (check_range(info, min_uV, max_uV)) {
-		pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
-		return -EINVAL;
-	}
-
-	sel = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step);
-	sel = (sel >= 20) ? sel - 12 : ((sel > 7) ? 8 : sel);
-
-	return sel;
-}
-
-static int da9034_list_ldo12_voltage(struct regulator_dev *rdev,
-				     unsigned selector)
-{
-	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
-	int volt;
-
-	if (selector >= 8)
-		volt = 2700000 + rdev->desc->uV_step * (selector - 8);
-	else
-		volt = rdev->desc->min_uV + rdev->desc->uV_step * selector;
-
-	if (volt > info->max_uV)
-		return -EINVAL;
-
-	return volt;
-}
+static const struct regulator_linear_range da9034_ldo12_ranges[] = {
+	{ .min_uV = 1700000, .max_uV = 2050000, .min_sel =  0, .max_sel = 7,
+	  .uV_step =  50000 },
+	{ .min_uV = 2700000, .max_uV = 3050000, .min_sel =  8, .max_sel = 15,
+	  .uV_step =  50000 },
+};
 
 static struct regulator_ops da903x_regulator_ldo_ops = {
 	.set_voltage_sel = da903x_set_voltage_sel,
@@ -332,8 +305,8 @@ static struct regulator_ops da9034_regulator_dvc_ops = {
 static struct regulator_ops da9034_regulator_ldo12_ops = {
 	.set_voltage_sel = da903x_set_voltage_sel,
 	.get_voltage_sel = da903x_get_voltage_sel,
-	.list_voltage	= da9034_list_ldo12_voltage,
-	.map_voltage	= da9034_map_ldo12_voltage,
+	.list_voltage	= regulator_list_voltage_linear_range,
+	.map_voltage	= regulator_map_voltage_linear_range,
 	.enable		= da903x_enable,
 	.disable	= da903x_disable,
 	.is_enabled	= da903x_is_enabled,
@@ -476,6 +449,8 @@ static int da903x_regulator_probe(struct platform_device *pdev)
 	if (ri->desc.id == DA9034_ID_LDO12) {
 		ri->desc.ops = &da9034_regulator_ldo12_ops;
 		ri->desc.n_voltages = 16;
+		ri->desc.linear_ranges = da9034_ldo12_ranges;
+		ri->desc.n_linear_ranges = ARRAY_SIZE(da9034_ldo12_ranges);
 	}
 
 	if (ri->desc.id == DA9030_ID_LDO14)
@@ -485,7 +460,7 @@ static int da903x_regulator_probe(struct platform_device *pdev)
 		ri->desc.ops = &da9030_regulator_ldo1_15_ops;
 
 	config.dev = &pdev->dev;
-	config.init_data = pdev->dev.platform_data;
+	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = ri;
 
 	rdev = regulator_register(&ri->desc, &config);
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 96b569a..1e4d483 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -349,7 +349,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	da9052 = dev_get_drvdata(pdev->dev.parent);
-	pdata = da9052->dev->platform_data;
+	pdata = dev_get_platdata(da9052->dev);
 	regulator->da9052 = da9052;
 
 	regulator->info = find_regulator_info(regulator->da9052->chip_id,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index 3022109..77b53e5 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -535,7 +535,7 @@ static int da9055_regulator_probe(struct platform_device *pdev)
 	struct regulator_config config = { };
 	struct da9055_regulator *regulator;
 	struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
-	struct da9055_pdata *pdata = da9055->dev->platform_data;
+	struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
 	int ret, irq;
 
 	if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
new file mode 100644
index 0000000..bf492bc
--- /dev/null
+++ b/drivers/regulator/da9210-regulator.c
@@ -0,0 +1,197 @@
+/*
+ * da9210-regulator.c - Regulator device driver for DA9210
+ * Copyright (C) 2013  Dialog Semiconductor Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regmap.h>
+
+#include "da9210-regulator.h"
+
+struct da9210 {
+	struct regulator_dev *rdev;
+	struct regmap *regmap;
+};
+
+static const struct regmap_config da9210_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
+				    int max_uA);
+static int da9210_get_current_limit(struct regulator_dev *rdev);
+
+static struct regulator_ops da9210_buck_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.set_current_limit = da9210_set_current_limit,
+	.get_current_limit = da9210_get_current_limit,
+};
+
+/* Default limits measured in millivolts and milliamps */
+#define DA9210_MIN_MV		300
+#define DA9210_MAX_MV		1570
+#define DA9210_STEP_MV		10
+
+/* Current limits for buck (uA) indices corresponds with register values */
+static const int da9210_buck_limits[] = {
+	1600000, 1800000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000,
+	3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000
+};
+
+static const struct regulator_desc da9210_reg = {
+	.name = "DA9210",
+	.id = 0,
+	.ops = &da9210_buck_ops,
+	.type = REGULATOR_VOLTAGE,
+	.n_voltages = ((DA9210_MAX_MV - DA9210_MIN_MV) / DA9210_STEP_MV) + 1,
+	.min_uV = (DA9210_MIN_MV * 1000),
+	.uV_step = (DA9210_STEP_MV * 1000),
+	.vsel_reg = DA9210_REG_VBUCK_A,
+	.vsel_mask = DA9210_VBUCK_MASK,
+	.enable_reg = DA9210_REG_BUCK_CONT,
+	.enable_mask = DA9210_BUCK_EN,
+	.owner = THIS_MODULE,
+};
+
+static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
+				    int max_uA)
+{
+	struct da9210 *chip = rdev_get_drvdata(rdev);
+	unsigned int sel;
+	int i;
+
+	/* search for closest to maximum */
+	for (i = ARRAY_SIZE(da9210_buck_limits)-1; i >= 0; i--) {
+		if (min_uA <= da9210_buck_limits[i] &&
+		    max_uA >= da9210_buck_limits[i]) {
+			sel = i;
+			sel = sel << DA9210_BUCK_ILIM_SHIFT;
+			return regmap_update_bits(chip->regmap,
+						  DA9210_REG_BUCK_ILIM,
+						  DA9210_BUCK_ILIM_MASK, sel);
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int da9210_get_current_limit(struct regulator_dev *rdev)
+{
+	struct da9210 *chip = rdev_get_drvdata(rdev);
+	unsigned int data;
+	unsigned int sel;
+	int ret;
+
+	ret = regmap_read(chip->regmap, DA9210_REG_BUCK_ILIM, &data);
+	if (ret < 0)
+		return ret;
+
+	/* select one of 16 values: 0000 (1600mA) to 1111 (4600mA) */
+	sel = (data & DA9210_BUCK_ILIM_MASK) >> DA9210_BUCK_ILIM_SHIFT;
+
+	return da9210_buck_limits[sel];
+}
+
+/*
+ * I2C driver interface functions
+ */
+static int da9210_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct da9210 *chip;
+	struct da9210_pdata *pdata = i2c->dev.platform_data;
+	struct regulator_dev *rdev = NULL;
+	struct regulator_config config = { };
+	int error;
+
+	chip = devm_kzalloc(&i2c->dev, sizeof(struct da9210), GFP_KERNEL);
+	if (NULL == chip) {
+		dev_err(&i2c->dev,
+			"Cannot kzalloc memory for regulator structure\n");
+		return -ENOMEM;
+	}
+
+	chip->regmap = devm_regmap_init_i2c(i2c, &da9210_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		error = PTR_ERR(chip->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			error);
+		return error;
+	}
+
+	config.dev = &i2c->dev;
+	if (pdata)
+		config.init_data = &pdata->da9210_constraints;
+	config.driver_data = chip;
+	config.regmap = chip->regmap;
+
+	rdev = regulator_register(&da9210_reg, &config);
+	if (IS_ERR(rdev)) {
+		dev_err(&i2c->dev, "Failed to register DA9210 regulator\n");
+		return PTR_ERR(rdev);
+	}
+
+	chip->rdev = rdev;
+
+	i2c_set_clientdata(i2c, chip);
+
+	return 0;
+}
+
+static int da9210_i2c_remove(struct i2c_client *i2c)
+{
+	struct da9210 *chip = i2c_get_clientdata(i2c);
+	regulator_unregister(chip->rdev);
+	return 0;
+}
+
+static const struct i2c_device_id da9210_i2c_id[] = {
+	{"da9210", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, da9210_i2c_id);
+
+static struct i2c_driver da9210_regulator_driver = {
+	.driver = {
+		.name = "da9210",
+		.owner = THIS_MODULE,
+	},
+	.probe = da9210_i2c_probe,
+	.remove = da9210_i2c_remove,
+	.id_table = da9210_i2c_id,
+};
+
+module_i2c_driver(da9210_regulator_driver);
+
+MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
+MODULE_DESCRIPTION("Regulator device driver for Dialog DA9210");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:da9210");
diff --git a/drivers/regulator/da9210-regulator.h b/drivers/regulator/da9210-regulator.h
new file mode 100644
index 0000000..749c550
--- /dev/null
+++ b/drivers/regulator/da9210-regulator.h
@@ -0,0 +1,288 @@
+
+/*
+ * da9210-regulator.h - Regulator definitions for DA9210
+ * Copyright (C) 2013  Dialog Semiconductor Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __DA9210_REGISTERS_H__
+#define __DA9210_REGISTERS_H__
+
+struct da9210_pdata {
+	struct regulator_init_data da9210_constraints;
+};
+
+/* Page selection */
+#define	DA9210_REG_PAGE_CON			0x00
+
+/* System Control and Event Registers */
+#define	DA9210_REG_STATUS_A			0x50
+#define	DA9210_REG_STATUS_B			0x51
+#define	DA9210_REG_EVENT_A			0x52
+#define	DA9210_REG_EVENT_B			0x53
+#define	DA9210_REG_MASK_A			0x54
+#define	DA9210_REG_MASK_B			0x55
+#define	DA9210_REG_CONTROL_A			0x56
+
+/* GPIO Control Registers */
+#define	DA9210_REG_GPIO_0_1			0x58
+#define	DA9210_REG_GPIO_2_3			0x59
+#define	DA9210_REG_GPIO_4_5			0x5A
+#define	DA9210_REG_GPIO_6			0x5B
+
+/* Regulator Registers */
+#define	DA9210_REG_BUCK_CONT			0x5D
+#define	DA9210_REG_BUCK_ILIM			0xD0
+#define	DA9210_REG_BUCK_CONF1			0xD1
+#define	DA9210_REG_BUCK_CONF2			0xD2
+#define DA9210_REG_VBACK_AUTO			0xD4
+#define DA9210_REG_VBACK_BASE			0xD5
+#define DA9210_REG_VBACK_MAX_DVC_IF		0xD6
+#define DA9210_REG_VBACK_DVC			0xD7
+#define	DA9210_REG_VBUCK_A			0xD8
+#define	DA9210_REG_VBUCK_B			0xD9
+
+/* I2C Interface Settings */
+#define DA9210_REG_INTERFACE			0x105
+
+/* OTP */
+#define	DA9210_REG_OPT_COUNT			0x140
+#define	DA9210_REG_OPT_ADDR			0x141
+#define	DA9210_REG_OPT_DATA			0x142
+
+/* Customer Trim and Configuration */
+#define	DA9210_REG_CONFIG_A			0x143
+#define	DA9210_REG_CONFIG_B			0x144
+#define	DA9210_REG_CONFIG_C			0x145
+#define	DA9210_REG_CONFIG_D			0x146
+#define	DA9210_REG_CONFIG_E			0x147
+
+
+/*
+ * Registers bits
+ */
+/* DA9210_REG_PAGE_CON (addr=0x00) */
+#define	DA9210_PEG_PAGE_SHIFT			0
+#define	DA9210_REG_PAGE_MASK			0x0F
+/* On I2C registers 0x00 - 0xFF */
+#define	DA9210_REG_PAGE0			0
+/* On I2C registers 0x100 - 0x1FF */
+#define	DA9210_REG_PAGE2			2
+#define	DA9210_PAGE_WRITE_MODE			0x00
+#define	DA9210_REPEAT_WRITE_MODE		0x40
+#define	DA9210_PAGE_REVERT			0x80
+
+/* DA9210_REG_STATUS_A (addr=0x50) */
+#define	DA9210_GPI0				0x01
+#define	DA9210_GPI1				0x02
+#define	DA9210_GPI2				0x04
+#define	DA9210_GPI3				0x08
+#define	DA9210_GPI4				0x10
+#define	DA9210_GPI5				0x20
+#define	DA9210_GPI6				0x40
+
+/* DA9210_REG_EVENT_A (addr=0x52) */
+#define	DA9210_E_GPI0				0x01
+#define	DA9210_E_GPI1				0x02
+#define	DA9210_E_GPI2				0x04
+#define	DA9210_E_GPI3				0x08
+#define	DA9210_E_GPI4				0x10
+#define	DA9210_E_GPI5				0x20
+#define	DA9210_E_GPI6				0x40
+
+/* DA9210_REG_EVENT_B (addr=0x53) */
+#define	DA9210_E_OVCURR				0x01
+#define	DA9210_E_NPWRGOOD			0x02
+#define	DA9210_E_TEMP_WARN			0x04
+#define	DA9210_E_TEMP_CRIT			0x08
+#define	DA9210_E_VMAX				0x10
+
+/* DA9210_REG_MASK_A (addr=0x54) */
+#define	DA9210_M_GPI0				0x01
+#define	DA9210_M_GPI1				0x02
+#define	DA9210_M_GPI2				0x04
+#define	DA9210_M_GPI3				0x08
+#define	DA9210_M_GPI4				0x10
+#define	DA9210_M_GPI5				0x20
+#define	DA9210_M_GPI6				0x40
+
+/* DA9210_REG_MASK_B (addr=0x55) */
+#define	DA9210_M_OVCURR				0x01
+#define	DA9210_M_NPWRGOOD			0x02
+#define	DA9210_M_TEMP_WARN			0x04
+#define	DA9210_M_TEMP_CRIT			0x08
+#define	DA9210_M_VMAX				0x10
+
+/* DA9210_REG_CONTROL_A (addr=0x56) */
+#define	DA9210_DEBOUNCING_SHIFT			0
+#define	DA9210_DEBOUNCING_MASK			0x07
+#define	DA9210_SLEW_RATE_SHIFT			3
+#define	DA9210_SLEW_RATE_MASK			0x18
+#define	DA9210_V_LOCK				0x20
+
+/* DA9210_REG_GPIO_0_1 (addr=0x58) */
+#define	DA9210_GPIO0_PIN_SHIFT			0
+#define	DA9210_GPIO0_PIN_MASK			0x03
+#define		DA9210_GPIO0_PIN_GPI		0x00
+#define		DA9210_GPIO0_PIN_GPO_OD		0x02
+#define		DA9210_GPIO0_PIN_GPO		0x03
+#define	DA9210_GPIO0_TYPE			0x04
+#define		DA9210_GPIO0_TYPE_GPI		0x00
+#define		DA9210_GPIO0_TYPE_GPO		0x04
+#define	DA9210_GPIO0_MODE			0x08
+#define	DA9210_GPIO1_PIN_SHIFT			4
+#define	DA9210_GPIO1_PIN_MASK			0x30
+#define		DA9210_GPIO1_PIN_GPI		0x00
+#define		DA9210_GPIO1_PIN_VERROR		0x10
+#define		DA9210_GPIO1_PIN_GPO_OD		0x20
+#define		DA9210_GPIO1_PIN_GPO		0x30
+#define	DA9210_GPIO1_TYPE_SHIFT			0x40
+#define		DA9210_GPIO1_TYPE_GPI		0x00
+#define		DA9210_GPIO1_TYPE_GPO		0x40
+#define	DA9210_GPIO1_MODE			0x80
+
+/* DA9210_REG_GPIO_2_3 (addr=0x59) */
+#define	DA9210_GPIO2_PIN_SHIFT			0
+#define	DA9210_GPIO2_PIN_MASK			0x03
+#define		DA9210_GPIO2_PIN_GPI		0x00
+#define		DA9210_GPIO5_PIN_BUCK_CLK	0x10
+#define		DA9210_GPIO2_PIN_GPO_OD		0x02
+#define		DA9210_GPIO2_PIN_GPO		0x03
+#define	DA9210_GPIO2_TYPE			0x04
+#define		DA9210_GPIO2_TYPE_GPI		0x00
+#define		DA9210_GPIO2_TYPE_GPO		0x04
+#define	DA9210_GPIO2_MODE			0x08
+#define	DA9210_GPIO3_PIN_SHIFT			4
+#define	DA9210_GPIO3_PIN_MASK			0x30
+#define		DA9210_GPIO3_PIN_GPI		0x00
+#define		DA9210_GPIO3_PIN_IERROR		0x10
+#define		DA9210_GPIO3_PIN_GPO_OD		0x20
+#define		DA9210_GPIO3_PIN_GPO		0x30
+#define	DA9210_GPIO3_TYPE_SHIFT			0x40
+#define		DA9210_GPIO3_TYPE_GPI		0x00
+#define		DA9210_GPIO3_TYPE_GPO		0x40
+#define	DA9210_GPIO3_MODE			0x80
+
+/* DA9210_REG_GPIO_4_5 (addr=0x5A) */
+#define	DA9210_GPIO4_PIN_SHIFT			0
+#define	DA9210_GPIO4_PIN_MASK			0x03
+#define		DA9210_GPIO4_PIN_GPI		0x00
+#define		DA9210_GPIO4_PIN_GPO_OD		0x02
+#define		DA9210_GPIO4_PIN_GPO		0x03
+#define	DA9210_GPIO4_TYPE			0x04
+#define		DA9210_GPIO4_TYPE_GPI		0x00
+#define		DA9210_GPIO4_TYPE_GPO		0x04
+#define	DA9210_GPIO4_MODE			0x08
+#define	DA9210_GPIO5_PIN_SHIFT			4
+#define	DA9210_GPIO5_PIN_MASK			0x30
+#define		DA9210_GPIO5_PIN_GPI		0x00
+#define		DA9210_GPIO5_PIN_INTERFACE	0x01
+#define		DA9210_GPIO5_PIN_GPO_OD		0x20
+#define		DA9210_GPIO5_PIN_GPO		0x30
+#define	DA9210_GPIO5_TYPE_SHIFT			0x40
+#define		DA9210_GPIO5_TYPE_GPI		0x00
+#define		DA9210_GPIO5_TYPE_GPO		0x40
+#define	DA9210_GPIO5_MODE			0x80
+
+/* DA9210_REG_GPIO_6 (addr=0x5B) */
+#define	DA9210_GPIO6_PIN_SHIFT			0
+#define	DA9210_GPIO6_PIN_MASK			0x03
+#define		DA9210_GPIO6_PIN_GPI		0x00
+#define		DA9210_GPIO6_PIN_INTERFACE	0x01
+#define		DA9210_GPIO6_PIN_GPO_OD		0x02
+#define		DA9210_GPIO6_PIN_GPO		0x03
+#define	DA9210_GPIO6_TYPE			0x04
+#define		DA9210_GPIO6_TYPE_GPI		0x00
+#define		DA9210_GPIO6_TYPE_GPO		0x04
+#define	DA9210_GPIO6_MODE			0x08
+
+/* DA9210_REG_BUCK_CONT (addr=0x5D) */
+#define	DA9210_BUCK_EN				0x01
+#define	DA9210_BUCK_GPI_SHIFT			1
+#define DA9210_BUCK_GPI_MASK			0x06
+#define		DA9210_BUCK_GPI_OFF		0x00
+#define		DA9210_BUCK_GPI_GPIO0		0x02
+#define		DA9210_BUCK_GPI_GPIO3		0x04
+#define		DA9210_BUCK_GPI_GPIO4		0x06
+#define	DA9210_BUCK_PD_DIS			0x08
+#define	DA9210_VBUCK_SEL			0x10
+#define		DA9210_VBUCK_SEL_A		0x00
+#define		DA9210_VBUCK_SEL_B		0x10
+#define	DA9210_VBUCK_GPI_SHIFT			5
+#define	DA9210_VBUCK_GPI_MASK			0x60
+#define		DA9210_VBUCK_GPI_OFF		0x00
+#define		DA9210_VBUCK_GPI_GPIO0		0x20
+#define		DA9210_VBUCK_GPI_GPIO3		0x40
+#define		DA9210_VBUCK_GPI_GPIO4		0x60
+#define	DA9210_DVC_CTRL_EN			0x80
+
+/* DA9210_REG_BUCK_ILIM (addr=0xD0) */
+#define DA9210_BUCK_ILIM_SHIFT			0
+#define DA9210_BUCK_ILIM_MASK			0x0F
+#define DA9210_BUCK_IALARM			0x10
+
+/* DA9210_REG_BUCK_CONF1 (addr=0xD1) */
+#define DA9210_BUCK_MODE_SHIFT			0
+#define DA9210_BUCK_MODE_MASK			0x03
+#define		DA9210_BUCK_MODE_MANUAL		0x00
+#define		DA9210_BUCK_MODE_SLEEP		0x01
+#define		DA9210_BUCK_MODE_SYNC		0x02
+#define		DA9210_BUCK_MODE_AUTO		0x03
+#define DA9210_STARTUP_CTRL_SHIFT		2
+#define DA9210_STARTUP_CTRL_MASK		0x1C
+#define DA9210_PWR_DOWN_CTRL_SHIFT		5
+#define DA9210_PWR_DOWN_CTRL_MASK		0xE0
+
+/* DA9210_REG_BUCK_CONF2 (addr=0xD2) */
+#define DA9210_PHASE_SEL_SHIFT			0
+#define DA9210_PHASE_SEL_MASK			0x03
+#define DA9210_FREQ_SEL				0x40
+
+/* DA9210_REG_BUCK_AUTO (addr=0xD4) */
+#define DA9210_VBUCK_AUTO_SHIFT			0
+#define DA9210_VBUCK_AUTO_MASK			0x7F
+
+/* DA9210_REG_BUCK_BASE (addr=0xD5) */
+#define DA9210_VBUCK_BASE_SHIFT			0
+#define DA9210_VBUCK_BASE_MASK			0x7F
+
+/* DA9210_REG_VBUCK_MAX_DVC_IF (addr=0xD6) */
+#define DA9210_VBUCK_MAX_SHIFT			0
+#define DA9210_VBUCK_MAX_MASK			0x7F
+#define DA9210_DVC_STEP_SIZE			0x80
+#define		DA9210_DVC_STEP_SIZE_10MV	0x00
+#define		DA9210_DVC_STEP_SIZE_20MV	0x80
+
+/* DA9210_REG_VBUCK_DVC (addr=0xD7) */
+#define DA9210_VBUCK_DVC_SHIFT			0
+#define DA9210_VBUCK_DVC_MASK			0x7F
+
+/* DA9210_REG_VBUCK_A/B (addr=0xD8/0xD9) */
+#define DA9210_VBUCK_SHIFT			0
+#define DA9210_VBUCK_MASK			0x7F
+#define DA9210_VBUCK_BIAS			0
+#define DA9210_BUCK_SL				0x80
+
+/* DA9210_REG_INTERFACE (addr=0x105) */
+#define DA9210_IF_BASE_ADDR_SHIFT		4
+#define DA9210_IF_BASE_ADDR_MASK		0xF0
+
+/* DA9210_REG_CONFIG_E (addr=0x147) */
+#define DA9210_STAND_ALONE			0x01
+
+#endif	/* __DA9210_REGISTERS_H__ */
+
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index f0e1ae5..70b7220 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -219,7 +219,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
 	rdesc->owner = THIS_MODULE;
 
 	di->rdev = regulator_register(&di->desc, config);
-	return PTR_RET(di->rdev);
+	return PTR_ERR_OR_ZERO(di->rdev);
 
 }
 
@@ -237,7 +237,7 @@ static int fan53555_regulator_probe(struct i2c_client *client,
 	unsigned int val;
 	int ret;
 
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 	if (!pdata || !pdata->regulator) {
 		dev_err(&client->dev, "Platform data not found!\n");
 		return -ENODEV;
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index e5c03b5..7610920 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -146,7 +146,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 		if (IS_ERR(config))
 			return PTR_ERR(config);
 	} else {
-		config = pdev->dev.platform_data;
+		config = dev_get_platdata(&pdev->dev);
 	}
 
 	if (!config)
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 9d39eb4..98a98ff 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -219,7 +219,7 @@ static struct regulator_ops gpio_regulator_current_ops = {
 
 static int gpio_regulator_probe(struct platform_device *pdev)
 {
-	struct gpio_regulator_config *config = pdev->dev.platform_data;
+	struct gpio_regulator_config *config = dev_get_platdata(&pdev->dev);
 	struct device_node *np = pdev->dev.of_node;
 	struct gpio_regulator_data *drvdata;
 	struct regulator_config cfg = { };
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
new file mode 100644
index 0000000..d13cf8f
--- /dev/null
+++ b/drivers/regulator/helpers.c
@@ -0,0 +1,361 @@
+/*
+ * helpers.c  --  Voltage/Current Regulator framework helper functions.
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/module.h>
+
+/**
+ * regulator_is_enabled_regmap - standard is_enabled() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their is_enabled operation, saving some code.
+ */
+int regulator_is_enabled_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+	if (ret != 0)
+		return ret;
+
+	if (rdev->desc->enable_is_inverted)
+		return (val & rdev->desc->enable_mask) == 0;
+	else
+		return (val & rdev->desc->enable_mask) != 0;
+}
+EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
+
+/**
+ * regulator_enable_regmap - standard enable() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their enable() operation, saving some code.
+ */
+int regulator_enable_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+
+	if (rdev->desc->enable_is_inverted)
+		val = 0;
+	else
+		val = rdev->desc->enable_mask;
+
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				  rdev->desc->enable_mask, val);
+}
+EXPORT_SYMBOL_GPL(regulator_enable_regmap);
+
+/**
+ * regulator_disable_regmap - standard disable() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their disable() operation, saving some code.
+ */
+int regulator_disable_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+
+	if (rdev->desc->enable_is_inverted)
+		val = rdev->desc->enable_mask;
+	else
+		val = 0;
+
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				  rdev->desc->enable_mask, val);
+}
+EXPORT_SYMBOL_GPL(regulator_disable_regmap);
+
+/**
+ * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their get_voltage_vsel operation, saving some code.
+ */
+int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+	if (ret != 0)
+		return ret;
+
+	val &= rdev->desc->vsel_mask;
+	val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
+
+/**
+ * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ * @sel: Selector to set
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their set_voltage_vsel operation, saving some code.
+ */
+int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
+{
+	int ret;
+
+	sel <<= ffs(rdev->desc->vsel_mask) - 1;
+
+	ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
+				  rdev->desc->vsel_mask, sel);
+	if (ret)
+		return ret;
+
+	if (rdev->desc->apply_bit)
+		ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
+					 rdev->desc->apply_bit,
+					 rdev->desc->apply_bit);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
+
+/**
+ * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers implementing set_voltage_sel() and list_voltage() can use
+ * this as their map_voltage() operation.  It will find a suitable
+ * voltage by calling list_voltage() until it gets something in bounds
+ * for the requested voltages.
+ */
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	int best_val = INT_MAX;
+	int selector = 0;
+	int i, ret;
+
+	/* Find the smallest voltage that falls within the specified
+	 * range.
+	 */
+	for (i = 0; i < rdev->desc->n_voltages; i++) {
+		ret = rdev->desc->ops->list_voltage(rdev, i);
+		if (ret < 0)
+			continue;
+
+		if (ret < best_val && ret >= min_uV && ret <= max_uV) {
+			best_val = ret;
+			selector = i;
+		}
+	}
+
+	if (best_val != INT_MAX)
+		return selector;
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
+
+/**
+ * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers that have ascendant voltage list can use this as their
+ * map_voltage() operation.
+ */
+int regulator_map_voltage_ascend(struct regulator_dev *rdev,
+				 int min_uV, int max_uV)
+{
+	int i, ret;
+
+	for (i = 0; i < rdev->desc->n_voltages; i++) {
+		ret = rdev->desc->ops->list_voltage(rdev, i);
+		if (ret < 0)
+			continue;
+
+		if (ret > max_uV)
+			break;
+
+		if (ret >= min_uV && ret <= max_uV)
+			return i;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
+
+/**
+ * regulator_map_voltage_linear - map_voltage() for simple linear mappings
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers providing min_uV and uV_step in their regulator_desc can
+ * use this as their map_voltage() operation.
+ */
+int regulator_map_voltage_linear(struct regulator_dev *rdev,
+				 int min_uV, int max_uV)
+{
+	int ret, voltage;
+
+	/* Allow uV_step to be 0 for fixed voltage */
+	if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
+		if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
+			return 0;
+		else
+			return -EINVAL;
+	}
+
+	if (!rdev->desc->uV_step) {
+		BUG_ON(!rdev->desc->uV_step);
+		return -EINVAL;
+	}
+
+	if (min_uV < rdev->desc->min_uV)
+		min_uV = rdev->desc->min_uV;
+
+	ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+	if (ret < 0)
+		return ret;
+
+	ret += rdev->desc->linear_min_sel;
+
+	/* Map back into a voltage to verify we're still in bounds */
+	voltage = rdev->desc->ops->list_voltage(rdev, ret);
+	if (voltage < min_uV || voltage > max_uV)
+		return -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
+
+/**
+ * regulator_map_voltage_linear - map_voltage() for multiple linear ranges
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers providing linear_ranges in their descriptor can use this as
+ * their map_voltage() callback.
+ */
+int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
+				       int min_uV, int max_uV)
+{
+	const struct regulator_linear_range *range;
+	int ret = -EINVAL;
+	int voltage, i;
+
+	if (!rdev->desc->n_linear_ranges) {
+		BUG_ON(!rdev->desc->n_linear_ranges);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
+		range = &rdev->desc->linear_ranges[i];
+
+		if (!(min_uV <= range->max_uV && max_uV >= range->min_uV))
+			continue;
+
+		if (min_uV <= range->min_uV)
+			min_uV = range->min_uV;
+
+		/* range->uV_step == 0 means fixed voltage range */
+		if (range->uV_step == 0) {
+			ret = 0;
+		} else {
+			ret = DIV_ROUND_UP(min_uV - range->min_uV,
+					   range->uV_step);
+			if (ret < 0)
+				return ret;
+		}
+
+		ret += range->min_sel;
+
+		break;
+	}
+
+	if (i == rdev->desc->n_linear_ranges)
+		return -EINVAL;
+
+	/* Map back into a voltage to verify we're still in bounds */
+	voltage = rdev->desc->ops->list_voltage(rdev, ret);
+	if (voltage < min_uV || voltage > max_uV)
+		return -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
+
+/**
+ * regulator_set_bypass_regmap - Default set_bypass() using regmap
+ *
+ * @rdev: device to operate on.
+ * @enable: state to set.
+ */
+int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
+{
+	unsigned int val;
+
+	if (enable)
+		val = rdev->desc->bypass_mask;
+	else
+		val = 0;
+
+	return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
+				  rdev->desc->bypass_mask, val);
+}
+EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
+
+/**
+ * regulator_get_bypass_regmap - Default get_bypass() using regmap
+ *
+ * @rdev: device to operate on.
+ * @enable: current state.
+ */
+int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
+	if (ret != 0)
+		return ret;
+
+	*enable = val & rdev->desc->bypass_mask;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index b99c49b..88c1a3a 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -110,7 +110,7 @@ static int isl6271a_probe(struct i2c_client *i2c,
 				     const struct i2c_device_id *id)
 {
 	struct regulator_config config = { };
-	struct regulator_init_data *init_data	= i2c->dev.platform_data;
+	struct regulator_init_data *init_data	= dev_get_platdata(&i2c->dev);
 	struct isl_pmic *pmic;
 	int err, i;
 
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 3809b43..5a4604e 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -425,7 +425,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct lp3971 *lp3971;
-	struct lp3971_platform_data *pdata = i2c->dev.platform_data;
+	struct lp3971_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	int ret;
 	u16 val;
 
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 5730240..093e6f4 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -519,7 +519,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct lp3972 *lp3972;
-	struct lp3972_platform_data *pdata = i2c->dev.platform_data;
+	struct lp3972_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	int ret;
 	u16 val;
 
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index b16336b..2b84b72 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -373,7 +373,7 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
 		return -EINVAL;
 	}
 
-	for (i = ARRAY_SIZE(lp8725_buck_uA) - 1 ; i >= 0; i--) {
+	for (i = ARRAY_SIZE(lp8725_buck_uA) - 1; i >= 0; i--) {
 		if (lp8725_buck_uA[i] >= min_uA &&
 			lp8725_buck_uA[i] <= max_uA)
 			return lp872x_update_bits(lp, addr,
@@ -787,7 +787,7 @@ static int lp872x_regulator_register(struct lp872x *lp)
 	struct regulator_dev *rdev;
 	int i, ret;
 
-	for (i = 0 ; i < lp->num_regulators ; i++) {
+	for (i = 0; i < lp->num_regulators; i++) {
 		desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
 						&lp8725_regulator_desc[i];
 
@@ -820,7 +820,7 @@ static void lp872x_regulator_unregister(struct lp872x *lp)
 	struct regulator_dev *rdev;
 	int i;
 
-	for (i = 0 ; i < lp->num_regulators ; i++) {
+	for (i = 0; i < lp->num_regulators; i++) {
 		rdev = *(lp->regulators + i);
 		regulator_unregister(rdev);
 	}
@@ -907,7 +907,8 @@ static struct lp872x_platform_data
 		goto out;
 
 	for (i = 0; i < num_matches; i++) {
-		pdata->regulator_data[i].id = (int)match[i].driver_data;
+		pdata->regulator_data[i].id =
+				(enum lp872x_regulator_id)match[i].driver_data;
 		pdata->regulator_data[i].init_data = match[i].init_data;
 
 		/* Operation mode configuration for buck/buck1/buck2 */
@@ -961,7 +962,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 	}
 
 	lp->dev = &cl->dev;
-	lp->pdata = cl->dev.platform_data;
+	lp->pdata = dev_get_platdata(&cl->dev);
 	lp->chipid = id->driver_data;
 	lp->num_regulators = num_regulators;
 	i2c_set_clientdata(cl, lp);
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index d9e38b4..785a25e 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -228,6 +228,7 @@ err_i2c:
 }
 
 static struct regulator_ops lp8755_buck_ops = {
+	.map_voltage = regulator_map_voltage_linear,
 	.list_voltage = regulator_list_voltage_linear,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -449,7 +450,7 @@ static int lp8755_probe(struct i2c_client *client,
 {
 	int ret, icnt;
 	struct lp8755_chip *pchip;
-	struct lp8755_platform_data *pdata = client->dev.platform_data;
+	struct lp8755_platform_data *pdata = dev_get_platdata(&client->dev);
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		dev_err(&client->dev, "i2c functionality check fail.\n");
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 54af610..3a599ee 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -163,7 +163,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
 					const struct i2c_device_id *i2c_id)
 {
 	struct regulator_dev **rdev;
-	struct max1586_platform_data *pdata = client->dev.platform_data;
+	struct max1586_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct regulator_config config = { };
 	struct max1586_data *max1586;
 	int i, id, ret = -ENOMEM;
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index db6c9be..19c6f08 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -152,7 +152,7 @@ static struct regmap_config max8649_regmap_config = {
 static int max8649_regulator_probe(struct i2c_client *client,
 					     const struct i2c_device_id *id)
 {
-	struct max8649_platform_data *pdata = client->dev.platform_data;
+	struct max8649_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct max8649_regulator_info *info = NULL;
 	struct regulator_config config = { };
 	unsigned int val;
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index d428ef9..144bcac 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -44,6 +44,9 @@
 #include <linux/regulator/driver.h>
 #include <linux/slab.h>
 #include <linux/regulator/max8660.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/of_regulator.h>
 
 #define MAX8660_DCDC_MIN_UV	 725000
 #define MAX8660_DCDC_MAX_UV	1800000
@@ -305,21 +308,105 @@ static const struct regulator_desc max8660_reg[] = {
 	},
 };
 
+enum {
+	MAX8660 = 0,
+	MAX8661 = 1,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id max8660_dt_ids[] = {
+	{ .compatible = "maxim,max8660", .data = (void *) MAX8660 },
+	{ .compatible = "maxim,max8661", .data = (void *) MAX8661 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max8660_dt_ids);
+
+static int max8660_pdata_from_dt(struct device *dev,
+				 struct device_node **of_node,
+				 struct max8660_platform_data *pdata)
+{
+	int matched, i;
+	struct device_node *np;
+	struct max8660_subdev_data *sub;
+	struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)];
+
+	np = of_find_node_by_name(dev->of_node, "regulators");
+	if (!np) {
+		dev_err(dev, "missing 'regulators' subnode in DT\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(rmatch); i++)
+		rmatch[i].name = max8660_reg[i].name;
+
+	matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch));
+	if (matched <= 0)
+		return matched;
+
+	pdata->subdevs = devm_kzalloc(dev, sizeof(struct max8660_subdev_data) *
+						matched, GFP_KERNEL);
+	if (!pdata->subdevs)
+		return -ENOMEM;
+
+	pdata->num_subdevs = matched;
+	sub = pdata->subdevs;
+
+	for (i = 0; i < matched; i++) {
+		sub->id = i;
+		sub->name = rmatch[i].name;
+		sub->platform_data = rmatch[i].init_data;
+		of_node[i] = rmatch[i].of_node;
+		sub++;
+	}
+
+	return 0;
+}
+#else
+static inline int max8660_pdata_from_dt(struct device *dev,
+					struct device_node **of_node,
+					struct max8660_platform_data *pdata)
+{
+	return 0;
+}
+#endif
+
 static int max8660_probe(struct i2c_client *client,
 				   const struct i2c_device_id *i2c_id)
 {
 	struct regulator_dev **rdev;
-	struct max8660_platform_data *pdata = client->dev.platform_data;
+	struct device *dev = &client->dev;
+	struct max8660_platform_data *pdata = dev_get_platdata(dev);
 	struct regulator_config config = { };
 	struct max8660 *max8660;
 	int boot_on, i, id, ret = -EINVAL;
+	struct device_node *of_node[MAX8660_V_END];
+	unsigned long type;
+
+	if (dev->of_node && !pdata) {
+		const struct of_device_id *id;
+		struct max8660_platform_data pdata_of;
+
+		id = of_match_device(of_match_ptr(max8660_dt_ids), dev);
+		if (!id)
+			return -ENODEV;
+
+		ret = max8660_pdata_from_dt(dev, of_node, &pdata_of);
+		if (ret < 0)
+			return ret;
+
+		pdata = &pdata_of;
+		type = (unsigned long) id->data;
+	} else {
+		type = i2c_id->driver_data;
+		memset(of_node, 0, sizeof(of_node));
+	}
 
 	if (pdata->num_subdevs > MAX8660_V_END) {
-		dev_err(&client->dev, "Too many regulators found!\n");
+		dev_err(dev, "Too many regulators found!\n");
 		return -EINVAL;
 	}
 
-	max8660 = devm_kzalloc(&client->dev, sizeof(struct max8660) +
+	max8660 = devm_kzalloc(dev, sizeof(struct max8660) +
 			sizeof(struct regulator_dev *) * MAX8660_V_END,
 			GFP_KERNEL);
 	if (!max8660)
@@ -376,8 +463,8 @@ static int max8660_probe(struct i2c_client *client,
 			break;
 
 		case MAX8660_V7:
-			if (!strcmp(i2c_id->name, "max8661")) {
-				dev_err(&client->dev, "Regulator not on this chip!\n");
+			if (type == MAX8661) {
+				dev_err(dev, "Regulator not on this chip!\n");
 				goto err_out;
 			}
 
@@ -386,7 +473,7 @@ static int max8660_probe(struct i2c_client *client,
 			break;
 
 		default:
-			dev_err(&client->dev, "invalid regulator %s\n",
+			dev_err(dev, "invalid regulator %s\n",
 				 pdata->subdevs[i].name);
 			goto err_out;
 		}
@@ -397,14 +484,15 @@ static int max8660_probe(struct i2c_client *client,
 
 		id = pdata->subdevs[i].id;
 
-		config.dev = &client->dev;
+		config.dev = dev;
 		config.init_data = pdata->subdevs[i].platform_data;
+		config.of_node = of_node[i];
 		config.driver_data = max8660;
 
 		rdev[i] = regulator_register(&max8660_reg[id], &config);
 		if (IS_ERR(rdev[i])) {
 			ret = PTR_ERR(rdev[i]);
-			dev_err(&client->dev, "failed to register %s\n",
+			dev_err(dev, "failed to register %s\n",
 				max8660_reg[id].name);
 			goto err_unregister;
 		}
@@ -431,8 +519,8 @@ static int max8660_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max8660_id[] = {
-	{ "max8660", 0 },
-	{ "max8661", 0 },
+	{ .name = "max8660", .driver_data = MAX8660 },
+	{ .name = "max8661", .driver_data = MAX8661 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max8660_id);
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
index e6d54a5..d80b5fa 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -277,7 +277,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
 static int max8925_regulator_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct regulator_init_data *pdata = pdev->dev.platform_data;
+	struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
 	struct regulator_config config = { };
 	struct max8925_regulator_info *ri;
 	struct resource *res;
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 5259c2f..788e5ae 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -196,7 +196,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
 		const struct i2c_device_id *i2c_id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct max8952_platform_data *pdata = client->dev.platform_data;
+	struct max8952_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct regulator_config config = { };
 	struct max8952_data *max8952;
 
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 0c5195a..5b77ab7 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -371,7 +371,7 @@ static int max8973_probe(struct i2c_client *client,
 	struct max8973_chip *max;
 	int ret;
 
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	if (!pdata && !client->dev.of_node) {
 		dev_err(&client->dev, "No Platform data");
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index f3c8f8f..7827384 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -21,6 +21,7 @@ static void of_get_regulation_constraints(struct device_node *np,
 {
 	const __be32 *min_uV, *max_uV, *uV_offset;
 	const __be32 *min_uA, *max_uA, *ramp_delay;
+	struct property *prop;
 	struct regulation_constraints *constraints = &(*init_data)->constraints;
 
 	constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -64,9 +65,14 @@ static void of_get_regulation_constraints(struct device_node *np,
 	if (of_property_read_bool(np, "regulator-allow-bypass"))
 		constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
 
-	ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL);
-	if (ramp_delay)
-		constraints->ramp_delay = be32_to_cpu(*ramp_delay);
+	prop = of_find_property(np, "regulator-ramp-delay", NULL);
+	if (prop && prop->value) {
+		ramp_delay = prop->value;
+		if (*ramp_delay)
+			constraints->ramp_delay = be32_to_cpu(*ramp_delay);
+		else
+			constraints->ramp_disable = true;
+	}
 }
 
 /**
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index d0c8785..e8877e4 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -765,7 +765,7 @@ static void palmas_dt_to_pdata(struct device *dev,
 static int palmas_regulators_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
-	struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
+	struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device_node *node = pdev->dev.of_node;
 	struct regulator_dev *rdev;
 	struct regulator_config config = { };
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index 1a73a29..b49eaee 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -243,7 +243,7 @@ static int pcap_regulator_probe(struct platform_device *pdev)
 	struct regulator_config config = { };
 
 	config.dev = &pdev->dev;
-	config.init_data = pdev->dev.platform_data;
+	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = pcap;
 
 	rdev = regulator_register(&pcap_regulators[pdev->id], &config);
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
index 54df9f7..0f3576d 100644
--- a/drivers/regulator/pcf50633-regulator.c
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -86,7 +86,7 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
 	pcf = dev_to_pcf50633(pdev->dev.parent);
 
 	config.dev = &pdev->dev;
-	config.init_data = pdev->dev.platform_data;
+	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = pcf;
 	config.regmap = pcf->regmap;
 
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
new file mode 100644
index 0000000..ba67b2c
--- /dev/null
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/pfuze100.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+#define PFUZE_NUMREGS		128
+#define PFUZE100_VOL_OFFSET	0
+#define PFUZE100_STANDBY_OFFSET	1
+#define PFUZE100_MODE_OFFSET	3
+#define PFUZE100_CONF_OFFSET	4
+
+#define PFUZE100_DEVICEID	0x0
+#define PFUZE100_REVID		0x3
+#define PFUZE100_FABID		0x3
+
+#define PFUZE100_SW1ABVOL	0x20
+#define PFUZE100_SW1CVOL	0x2e
+#define PFUZE100_SW2VOL		0x35
+#define PFUZE100_SW3AVOL	0x3c
+#define PFUZE100_SW3BVOL	0x43
+#define PFUZE100_SW4VOL		0x4a
+#define PFUZE100_SWBSTCON1	0x66
+#define PFUZE100_VREFDDRCON	0x6a
+#define PFUZE100_VSNVSVOL	0x6b
+#define PFUZE100_VGEN1VOL	0x6c
+#define PFUZE100_VGEN2VOL	0x6d
+#define PFUZE100_VGEN3VOL	0x6e
+#define PFUZE100_VGEN4VOL	0x6f
+#define PFUZE100_VGEN5VOL	0x70
+#define PFUZE100_VGEN6VOL	0x71
+
+struct pfuze_regulator {
+	struct regulator_desc desc;
+	unsigned char stby_reg;
+	unsigned char stby_mask;
+};
+
+struct pfuze_chip {
+	struct regmap *regmap;
+	struct device *dev;
+	struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR];
+	struct regulator_dev *regulators[PFUZE100_MAX_REGULATOR];
+};
+
+static const int pfuze100_swbst[] = {
+	5000000, 5050000, 5100000, 5150000,
+};
+
+static const int pfuze100_vsnvs[] = {
+	1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000,
+};
+
+static const struct i2c_device_id pfuze_device_id[] = {
+	{.name = "pfuze100"},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, pfuze_device_id);
+
+static const struct of_device_id pfuze_dt_ids[] = {
+	{ .compatible = "fsl,pfuze100" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pfuze_dt_ids);
+
+static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+	struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev);
+	int id = rdev->desc->id;
+	unsigned int ramp_bits;
+	int ret;
+
+	if (id < PFUZE100_SWBST) {
+		ramp_delay = 12500 / ramp_delay;
+		ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3);
+		ret = regmap_update_bits(pfuze100->regmap,
+					 rdev->desc->vsel_reg + 4,
+					 0xc0, ramp_bits << 6);
+		if (ret < 0)
+			dev_err(pfuze100->dev, "ramp failed, err %d\n", ret);
+	} else
+		ret = -EACCES;
+
+	return ret;
+}
+
+static struct regulator_ops pfuze100_ldo_regulator_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static struct regulator_ops pfuze100_fixed_regulator_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+};
+
+static struct regulator_ops pfuze100_sw_regulator_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_time_sel = regulator_set_voltage_time_sel,
+	.set_ramp_delay = pfuze100_set_ramp_delay,
+};
+
+static struct regulator_ops pfuze100_swb_regulator_ops = {
+	.list_voltage = regulator_list_voltage_table,
+	.map_voltage = regulator_map_voltage_ascend,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+
+};
+
+#define PFUZE100_FIXED_REG(_name, base, voltage)	\
+	[PFUZE100_ ## _name] = {	\
+		.desc = {	\
+			.name = #_name,	\
+			.n_voltages = 1,	\
+			.ops = &pfuze100_fixed_regulator_ops,	\
+			.type = REGULATOR_VOLTAGE,	\
+			.id = PFUZE100_ ## _name,	\
+			.owner = THIS_MODULE,	\
+			.min_uV = (voltage),	\
+			.enable_reg = (base),	\
+			.enable_mask = 0x10,	\
+		},	\
+	}
+
+#define PFUZE100_SW_REG(_name, base, min, max, step)	\
+	[PFUZE100_ ## _name] = {	\
+		.desc = {	\
+			.name = #_name,\
+			.n_voltages = ((max) - (min)) / (step) + 1,	\
+			.ops = &pfuze100_sw_regulator_ops,	\
+			.type = REGULATOR_VOLTAGE,	\
+			.id = PFUZE100_ ## _name,	\
+			.owner = THIS_MODULE,	\
+			.min_uV = (min),	\
+			.uV_step = (step),	\
+			.vsel_reg = (base) + PFUZE100_VOL_OFFSET,	\
+			.vsel_mask = 0x3f,	\
+		},	\
+		.stby_reg = (base) + PFUZE100_STANDBY_OFFSET,	\
+		.stby_mask = 0x3f,	\
+	}
+
+#define PFUZE100_SWB_REG(_name, base, mask, voltages)	\
+	[PFUZE100_ ## _name] = {	\
+		.desc = {	\
+			.name = #_name,	\
+			.n_voltages = ARRAY_SIZE(voltages),	\
+			.ops = &pfuze100_swb_regulator_ops,	\
+			.type = REGULATOR_VOLTAGE,	\
+			.id = PFUZE100_ ## _name,	\
+			.owner = THIS_MODULE,	\
+			.volt_table = voltages,	\
+			.vsel_reg = (base),	\
+			.vsel_mask = (mask),	\
+		},	\
+	}
+
+#define PFUZE100_VGEN_REG(_name, base, min, max, step)	\
+	[PFUZE100_ ## _name] = {	\
+		.desc = {	\
+			.name = #_name,	\
+			.n_voltages = ((max) - (min)) / (step) + 1,	\
+			.ops = &pfuze100_ldo_regulator_ops,	\
+			.type = REGULATOR_VOLTAGE,	\
+			.id = PFUZE100_ ## _name,	\
+			.owner = THIS_MODULE,	\
+			.min_uV = (min),	\
+			.uV_step = (step),	\
+			.vsel_reg = (base),	\
+			.vsel_mask = 0xf,	\
+			.enable_reg = (base),	\
+			.enable_mask = 0x10,	\
+		},	\
+		.stby_reg = (base),	\
+		.stby_mask = 0x20,	\
+	}
+
+static struct pfuze_regulator pfuze100_regulators[] = {
+	PFUZE100_SW_REG(SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000),
+	PFUZE100_SW_REG(SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000),
+	PFUZE100_SW_REG(SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000),
+	PFUZE100_SW_REG(SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000),
+	PFUZE100_SW_REG(SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000),
+	PFUZE100_SW_REG(SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000),
+	PFUZE100_SWB_REG(SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst),
+	PFUZE100_SWB_REG(VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
+	PFUZE100_FIXED_REG(VREFDDR, PFUZE100_VREFDDRCON, 750000),
+	PFUZE100_VGEN_REG(VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000),
+	PFUZE100_VGEN_REG(VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000),
+	PFUZE100_VGEN_REG(VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000),
+	PFUZE100_VGEN_REG(VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
+	PFUZE100_VGEN_REG(VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
+	PFUZE100_VGEN_REG(VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
+};
+
+#ifdef CONFIG_OF
+static struct of_regulator_match pfuze100_matches[] = {
+	{ .name = "sw1ab",	},
+	{ .name = "sw1c",	},
+	{ .name = "sw2",	},
+	{ .name = "sw3a",	},
+	{ .name = "sw3b",	},
+	{ .name = "sw4",	},
+	{ .name = "swbst",	},
+	{ .name = "vsnvs",	},
+	{ .name = "vrefddr",	},
+	{ .name = "vgen1",	},
+	{ .name = "vgen2",	},
+	{ .name = "vgen3",	},
+	{ .name = "vgen4",	},
+	{ .name = "vgen5",	},
+	{ .name = "vgen6",	},
+};
+
+static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
+{
+	struct device *dev = chip->dev;
+	struct device_node *np, *parent;
+	int ret;
+
+	np = of_node_get(dev->parent->of_node);
+	if (!np)
+		return 0;
+
+	parent = of_find_node_by_name(np, "regulators");
+	if (!parent) {
+		dev_err(dev, "regulators node not found\n");
+		return -EINVAL;
+	}
+
+	ret = of_regulator_match(dev, parent, pfuze100_matches,
+				 ARRAY_SIZE(pfuze100_matches));
+
+	of_node_put(parent);
+	if (ret < 0) {
+		dev_err(dev, "Error parsing regulator init data: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static inline struct regulator_init_data *match_init_data(int index)
+{
+	return pfuze100_matches[index].init_data;
+}
+
+static inline struct device_node *match_of_node(int index)
+{
+	return pfuze100_matches[index].of_node;
+}
+#else
+static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
+{
+	return 0;
+}
+
+static inline struct regulator_init_data *match_init_data(int index)
+{
+	return NULL;
+}
+
+static inline struct device_node *match_of_node(int index)
+{
+	return NULL;
+}
+#endif
+
+static int pfuze_identify(struct pfuze_chip *pfuze_chip)
+{
+	unsigned int value;
+	int ret;
+
+	ret = regmap_read(pfuze_chip->regmap, PFUZE100_DEVICEID, &value);
+	if (ret)
+		return ret;
+
+	if (value & 0x0f) {
+		dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value);
+		return -ENODEV;
+	}
+
+	ret = regmap_read(pfuze_chip->regmap, PFUZE100_REVID, &value);
+	if (ret)
+		return ret;
+	dev_info(pfuze_chip->dev,
+		 "Full lay: %x, Metal lay: %x\n",
+		 (value & 0xf0) >> 4, value & 0x0f);
+
+	ret = regmap_read(pfuze_chip->regmap, PFUZE100_FABID, &value);
+	if (ret)
+		return ret;
+	dev_info(pfuze_chip->dev, "FAB: %x, FIN: %x\n",
+		 (value & 0xc) >> 2, value & 0x3);
+
+	return 0;
+}
+
+static const struct regmap_config pfuze_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = PFUZE_NUMREGS - 1,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int pfuze100_regulator_probe(struct i2c_client *client,
+				    const struct i2c_device_id *id)
+{
+	struct pfuze_chip *pfuze_chip;
+	struct pfuze_regulator_platform_data *pdata =
+	    dev_get_platdata(&client->dev);
+	struct regulator_config config = { };
+	int i, ret;
+
+	pfuze_chip = devm_kzalloc(&client->dev, sizeof(*pfuze_chip),
+			GFP_KERNEL);
+	if (!pfuze_chip)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, pfuze_chip);
+
+	memcpy(pfuze_chip->regulator_descs, pfuze100_regulators,
+		sizeof(pfuze_chip->regulator_descs));
+
+	pfuze_chip->dev = &client->dev;
+
+	pfuze_chip->regmap = devm_regmap_init_i2c(client, &pfuze_regmap_config);
+	if (IS_ERR(pfuze_chip->regmap)) {
+		ret = PTR_ERR(pfuze_chip->regmap);
+		dev_err(&client->dev,
+			"regmap allocation failed with err %d\n", ret);
+		return ret;
+	}
+
+	ret = pfuze_identify(pfuze_chip);
+	if (ret) {
+		dev_err(&client->dev, "unrecognized pfuze chip ID!\n");
+		return ret;
+	}
+
+	ret = pfuze_parse_regulators_dt(pfuze_chip);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) {
+		struct regulator_init_data *init_data;
+		struct regulator_desc *desc;
+		int val;
+
+		desc = &pfuze_chip->regulator_descs[i].desc;
+
+		if (pdata)
+			init_data = pdata->init_data[i];
+		else
+			init_data = match_init_data(i);
+
+		/* SW2~SW4 high bit check and modify the voltage value table */
+		if (i > PFUZE100_SW1C && i < PFUZE100_SWBST) {
+			regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val);
+			if (val & 0x40) {
+				desc->min_uV = 800000;
+				desc->uV_step = 50000;
+				desc->n_voltages = 51;
+			}
+		}
+
+		config.dev = &client->dev;
+		config.init_data = init_data;
+		config.driver_data = pfuze_chip;
+		config.of_node = match_of_node(i);
+
+		pfuze_chip->regulators[i] = regulator_register(desc, &config);
+		if (IS_ERR(pfuze_chip->regulators[i])) {
+			dev_err(&client->dev, "register regulator%s failed\n",
+				pfuze100_regulators[i].desc.name);
+			ret = PTR_ERR(pfuze_chip->regulators[i]);
+			while (--i >= 0)
+				regulator_unregister(pfuze_chip->regulators[i]);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int pfuze100_regulator_remove(struct i2c_client *client)
+{
+	int i;
+	struct pfuze_chip *pfuze_chip = i2c_get_clientdata(client);
+
+	for (i = 0; i < PFUZE100_MAX_REGULATOR; i++)
+		regulator_unregister(pfuze_chip->regulators[i]);
+
+	return 0;
+}
+
+static struct i2c_driver pfuze_driver = {
+	.id_table = pfuze_device_id,
+	.driver = {
+		.name = "pfuze100-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = pfuze_dt_ids,
+	},
+	.probe = pfuze100_regulator_probe,
+	.remove = pfuze100_regulator_remove,
+};
+module_i2c_driver(pfuze_driver);
+
+MODULE_AUTHOR("Robin Gong <b38343@freescale.com>");
+MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:pfuze100-regulator");
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 2f62564..f047d36 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -16,12 +16,17 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
 
+#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
+
 struct s2mps11_info {
 	struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
 
@@ -31,11 +36,6 @@ struct s2mps11_info {
 	int ramp_delay16;
 	int ramp_delay7810;
 	int ramp_delay9;
-
-	bool buck6_ramp;
-	bool buck2_ramp;
-	bool buck3_ramp;
-	bool buck4_ramp;
 };
 
 static int get_ramp_delay(int ramp_delay)
@@ -53,6 +53,164 @@ static int get_ramp_delay(int ramp_delay)
 	return cnt;
 }
 
+static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+				   unsigned int old_selector,
+				   unsigned int new_selector)
+{
+	struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+	unsigned int ramp_delay = 0;
+	int old_volt, new_volt;
+
+	switch (rdev->desc->id) {
+	case S2MPS11_BUCK2:
+		ramp_delay = s2mps11->ramp_delay2;
+		break;
+	case S2MPS11_BUCK3:
+		ramp_delay = s2mps11->ramp_delay34;
+		break;
+	case S2MPS11_BUCK4:
+		ramp_delay = s2mps11->ramp_delay34;
+		break;
+	case S2MPS11_BUCK5:
+		ramp_delay = s2mps11->ramp_delay5;
+		break;
+	case S2MPS11_BUCK6:
+	case S2MPS11_BUCK1:
+		ramp_delay = s2mps11->ramp_delay16;
+		break;
+	case S2MPS11_BUCK7:
+	case S2MPS11_BUCK8:
+	case S2MPS11_BUCK10:
+		ramp_delay = s2mps11->ramp_delay7810;
+		break;
+	case S2MPS11_BUCK9:
+		ramp_delay = s2mps11->ramp_delay9;
+	}
+
+	if (ramp_delay == 0)
+		ramp_delay = rdev->desc->ramp_delay;
+
+	old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector);
+	new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector);
+
+	return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
+}
+
+static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+	struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+	unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK;
+	unsigned int ramp_enable = 1, enable_shift = 0;
+	int ret;
+
+	switch (rdev->desc->id) {
+	case S2MPS11_BUCK1:
+		if (ramp_delay > s2mps11->ramp_delay16)
+			s2mps11->ramp_delay16 = ramp_delay;
+		else
+			ramp_delay = s2mps11->ramp_delay16;
+
+		ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT;
+		break;
+	case S2MPS11_BUCK2:
+		enable_shift = S2MPS11_BUCK2_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		s2mps11->ramp_delay2 = ramp_delay;
+		ramp_shift = S2MPS11_BUCK2_RAMP_SHIFT;
+		ramp_reg = S2MPS11_REG_RAMP;
+		break;
+	case S2MPS11_BUCK3:
+		enable_shift = S2MPS11_BUCK3_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		if (ramp_delay > s2mps11->ramp_delay34)
+			s2mps11->ramp_delay34 = ramp_delay;
+		else
+			ramp_delay = s2mps11->ramp_delay34;
+
+		ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
+		ramp_reg = S2MPS11_REG_RAMP;
+		break;
+	case S2MPS11_BUCK4:
+		enable_shift = S2MPS11_BUCK4_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		if (ramp_delay > s2mps11->ramp_delay34)
+			s2mps11->ramp_delay34 = ramp_delay;
+		else
+			ramp_delay = s2mps11->ramp_delay34;
+
+		ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
+		ramp_reg = S2MPS11_REG_RAMP;
+		break;
+	case S2MPS11_BUCK5:
+		s2mps11->ramp_delay5 = ramp_delay;
+		ramp_shift = S2MPS11_BUCK5_RAMP_SHIFT;
+		break;
+	case S2MPS11_BUCK6:
+		enable_shift = S2MPS11_BUCK6_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		if (ramp_delay > s2mps11->ramp_delay16)
+			s2mps11->ramp_delay16 = ramp_delay;
+		else
+			ramp_delay = s2mps11->ramp_delay16;
+
+		ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT;
+		break;
+	case S2MPS11_BUCK7:
+	case S2MPS11_BUCK8:
+	case S2MPS11_BUCK10:
+		if (ramp_delay > s2mps11->ramp_delay7810)
+			s2mps11->ramp_delay7810 = ramp_delay;
+		else
+			ramp_delay = s2mps11->ramp_delay7810;
+
+		ramp_shift = S2MPS11_BUCK7810_RAMP_SHIFT;
+		break;
+	case S2MPS11_BUCK9:
+		s2mps11->ramp_delay9 = ramp_delay;
+		ramp_shift = S2MPS11_BUCK9_RAMP_SHIFT;
+		break;
+	default:
+		return 0;
+	}
+
+	if (!ramp_enable)
+		goto ramp_disable;
+
+	if (enable_shift) {
+		ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP,
+					1 << enable_shift, 1 << enable_shift);
+		if (ret) {
+			dev_err(&rdev->dev, "failed to enable ramp rate\n");
+			return ret;
+		}
+	}
+
+	ramp_val = get_ramp_delay(ramp_delay);
+
+	return regmap_update_bits(rdev->regmap, ramp_reg,
+				  ramp_val << ramp_shift, 1 << ramp_shift);
+
+ramp_disable:
+	return regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, 0,
+				  1 << enable_shift);
+}
+
 static struct regulator_ops s2mps11_ldo_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
@@ -72,7 +230,8 @@ static struct regulator_ops s2mps11_buck_ops = {
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_voltage_time_sel	= s2mps11_regulator_set_voltage_time_sel,
+	.set_ramp_delay		= s2mps11_set_ramp_delay,
 };
 
 #define regulator_desc_ldo1(num)	{		\
@@ -239,59 +398,51 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+	struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
+	struct device_node *reg_np = NULL;
 	struct regulator_config config = { };
 	struct s2mps11_info *s2mps11;
 	int i, ret;
-	unsigned char ramp_enable, ramp_reg = 0;
-
-	if (!pdata) {
-		dev_err(pdev->dev.parent, "Platform data not supplied\n");
-		return -ENODEV;
-	}
 
 	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
 				GFP_KERNEL);
 	if (!s2mps11)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, s2mps11);
+	if (!iodev->dev->of_node) {
+		if (pdata) {
+			goto common_reg;
+		} else {
+			dev_err(pdev->dev.parent,
+				"Platform data or DT node not supplied\n");
+			return -ENODEV;
+		}
+	}
 
-	s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
-	s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
-	s2mps11->ramp_delay5 = pdata->buck5_ramp_delay;
-	s2mps11->ramp_delay16 = pdata->buck16_ramp_delay;
-	s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay;
-	s2mps11->ramp_delay9 = pdata->buck9_ramp_delay;
-
-	s2mps11->buck6_ramp = pdata->buck6_ramp_enable;
-	s2mps11->buck2_ramp = pdata->buck2_ramp_enable;
-	s2mps11->buck3_ramp = pdata->buck3_ramp_enable;
-	s2mps11->buck4_ramp = pdata->buck4_ramp_enable;
-
-	ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) |
-		(s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ;
-
-	if (ramp_enable) {
-		if (s2mps11->buck2_ramp)
-			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
-		if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
-			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
-		sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
+	for (i = 0; i < S2MPS11_REGULATOR_CNT; i++)
+		rdata[i].name = regulators[i].name;
+
+	reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators");
+	if (!reg_np) {
+		dev_err(&pdev->dev, "could not find regulators sub-node\n");
+		return -EINVAL;
 	}
 
-	ramp_reg &= 0x00;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
-	sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
+	of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
 
-	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+common_reg:
+	platform_set_drvdata(pdev, s2mps11);
 
-		config.dev = &pdev->dev;
-		config.regmap = iodev->regmap;
-		config.init_data = pdata->regulators[i].initdata;
-		config.driver_data = s2mps11;
+	config.dev = &pdev->dev;
+	config.regmap = iodev->regmap;
+	config.driver_data = s2mps11;
+	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+		if (!reg_np) {
+			config.init_data = pdata->regulators[i].initdata;
+		} else {
+			config.init_data = rdata[i].init_data;
+			config.of_node = rdata[i].of_node;
+		}
 
 		s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
 		if (IS_ERR(s2mps11->rdev[i])) {
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index 6e67be7..9392a7c 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -275,7 +275,7 @@ static int tps51632_probe(struct i2c_client *client,
 		}
 	}
 
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 	if (!pdata && client->dev.of_node)
 		pdata = of_get_tps51632_platform_data(&client->dev);
 	if (!pdata) {
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index a490d5b..0b7ebb1 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -350,7 +350,7 @@ static int tps62360_probe(struct i2c_client *client,
 	int i;
 	int chip_id;
 
-	pdata = client->dev.platform_data;
+	pdata = dev_get_platdata(&client->dev);
 
 	if (client->dev.of_node) {
 		const struct of_device_id *match;
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 9d053e2..a15263d 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -218,7 +218,7 @@ static int tps_65023_probe(struct i2c_client *client,
 	 * init_data points to array of regulator_init structures
 	 * coming from the board-evm file.
 	 */
-	init_data = client->dev.platform_data;
+	init_data = dev_get_platdata(&client->dev);
 	if (!init_data)
 		return -EIO;
 
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 1094393..62e8d28 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -601,7 +601,7 @@ static int pmic_probe(struct spi_device *spi)
 	struct regulator_config config = { };
 	int ret = 0, i;
 
-	init_data = dev->platform_data;
+	init_data = dev_get_platdata(dev);
 	if (!init_data) {
 		dev_err(dev, "could not find regulator platform data\n");
 		return -EINVAL;
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 17e994e..281e52a 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -118,6 +118,15 @@ struct tps65912_reg {
 	int eco_reg;
 };
 
+static const struct regulator_linear_range tps65912_ldo_ranges[] = {
+	{ .min_uV = 800000, .max_uV = 1600000, .min_sel =  0, .max_sel = 32,
+	  .uV_step = 25000 },
+	{ .min_uV = 1650000, .max_uV = 3000000, .min_sel = 33, .max_sel = 60,
+	  .uV_step = 50000 },
+	{ .min_uV = 3100000, .max_uV = 3300000, .min_sel = 61, .max_sel = 63,
+	  .uV_step = 100000 },
+};
+
 static int tps65912_get_range(struct tps65912_reg *pmic, int id)
 {
 	struct tps65912 *mfd = pmic->mfd;
@@ -184,20 +193,6 @@ static unsigned long tps65912_vsel_to_uv_range3(u8 vsel)
 	return uv;
 }
 
-static unsigned long tps65912_vsel_to_uv_ldo(u8 vsel)
-{
-	unsigned long uv = 0;
-
-	if (vsel <= 32)
-		uv = ((vsel * 25000) + 800000);
-	else if (vsel > 32 && vsel <= 60)
-		uv = (((vsel - 32) * 50000) + 1600000);
-	else if (vsel > 60)
-		uv = (((vsel - 60) * 100000) + 3000000);
-
-	return uv;
-}
-
 static int tps65912_get_ctrl_register(int id)
 {
 	if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4)
@@ -376,9 +371,6 @@ static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector)
 	struct tps65912_reg *pmic = rdev_get_drvdata(dev);
 	int range, voltage = 0, id = rdev_get_id(dev);
 
-	if (id >= TPS65912_REG_LDO1 && id <= TPS65912_REG_LDO10)
-		return tps65912_vsel_to_uv_ldo(selector);
-
 	if (id > TPS65912_REG_DCDC4)
 		return -EINVAL;
 
@@ -456,7 +448,8 @@ static struct regulator_ops tps65912_ops_ldo = {
 	.disable = tps65912_reg_disable,
 	.get_voltage_sel = tps65912_get_voltage_sel,
 	.set_voltage_sel = tps65912_set_voltage_sel,
-	.list_voltage = tps65912_list_voltage,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
 };
 
 static int tps65912_probe(struct platform_device *pdev)
@@ -495,8 +488,14 @@ static int tps65912_probe(struct platform_device *pdev)
 		pmic->desc[i].name = info->name;
 		pmic->desc[i].id = i;
 		pmic->desc[i].n_voltages = 64;
-		pmic->desc[i].ops = (i > TPS65912_REG_DCDC4 ?
-			&tps65912_ops_ldo : &tps65912_ops_dcdc);
+		if (i > TPS65912_REG_DCDC4) {
+			pmic->desc[i].ops = &tps65912_ops_ldo;
+			pmic->desc[i].linear_ranges = tps65912_ldo_ranges;
+			pmic->desc[i].n_linear_ranges =
+					ARRAY_SIZE(tps65912_ldo_ranges);
+		} else {
+			pmic->desc[i].ops = &tps65912_ops_dcdc;
+		}
 		pmic->desc[i].type = REGULATOR_VOLTAGE;
 		pmic->desc[i].owner = THIS_MODULE;
 		range = tps65912_get_range(pmic, i);
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 93bc4f4..78aae4c 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1108,7 +1108,7 @@ static int twlreg_probe(struct platform_device *pdev)
 		drvdata = NULL;
 	} else {
 		id = pdev->id;
-		initdata = pdev->dev.platform_data;
+		initdata = dev_get_platdata(&pdev->dev);
 		for (i = 0, template = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
 			template = twl_of_match[i].data;
 			if (template && template->desc.id == id)
diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c
index a7c8deb..765acc1 100644
--- a/drivers/regulator/userspace-consumer.c
+++ b/drivers/regulator/userspace-consumer.c
@@ -111,7 +111,7 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
 	struct userspace_consumer_data *drvdata;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata)
 		return -EINVAL;
 
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
index a9d4284..f53e78b 100644
--- a/drivers/regulator/virtual.c
+++ b/drivers/regulator/virtual.c
@@ -287,7 +287,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
 
 static int regulator_virtual_probe(struct platform_device *pdev)
 {
-	char *reg_id = pdev->dev.platform_data;
+	char *reg_id = dev_get_platdata(&pdev->dev);
 	struct virtual_consumer_data *drvdata;
 	int ret;
 
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 46938cf..11861cb 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -451,7 +451,7 @@ static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
 static int wm831x_buckv_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id;
 	struct wm831x_dcdc *dcdc;
@@ -624,7 +624,7 @@ static struct regulator_ops wm831x_buckp_ops = {
 static int wm831x_buckp_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id;
 	struct wm831x_dcdc *dcdc;
@@ -770,7 +770,7 @@ static struct regulator_ops wm831x_boostp_ops = {
 static int wm831x_boostp_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
 	struct wm831x_dcdc *dcdc;
@@ -880,7 +880,7 @@ static struct regulator_ops wm831x_epe_ops = {
 static int wm831x_epe_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id = pdev->id % ARRAY_SIZE(pdata->epe);
 	struct wm831x_dcdc *dcdc;
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 16ebdf9..4eb373d 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -151,7 +151,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
 static int wm831x_isink_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct wm831x_isink *isink;
 	int id = pdev->id % ARRAY_SIZE(pdata->isink);
 	struct regulator_config config = { };
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 9ff883f..1432b26 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -62,41 +62,12 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
  * General purpose LDOs
  */
 
-#define WM831X_GP_LDO_SELECTOR_LOW 0xe
-#define WM831X_GP_LDO_MAX_SELECTOR 0x1f
-
-static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
-				      unsigned int selector)
-{
-	/* 0.9-1.6V in 50mV steps */
-	if (selector <= WM831X_GP_LDO_SELECTOR_LOW)
-		return 900000 + (selector * 50000);
-	/* 1.7-3.3V in 100mV steps */
-	if (selector <= WM831X_GP_LDO_MAX_SELECTOR)
-		return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW)
-				  * 100000);
-	return -EINVAL;
-}
-
-static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev,
-				     int min_uV, int max_uV)
-{
-	int volt, vsel;
-
-	if (min_uV < 900000)
-		vsel = 0;
-	else if (min_uV < 1700000)
-		vsel = ((min_uV - 900000) / 50000);
-	else
-		vsel = ((min_uV - 1700000) / 100000)
-			+ WM831X_GP_LDO_SELECTOR_LOW + 1;
-
-	volt = wm831x_gp_ldo_list_voltage(rdev, vsel);
-	if (volt < min_uV || volt > max_uV)
-		return -EINVAL;
-
-	return vsel;
-}
+static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
+	{ .min_uV =  900000, .max_uV = 1650000, .min_sel =  0, .max_sel = 14,
+	  .uV_step =  50000 },
+	{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
+	  .uV_step = 100000 },
+};
 
 static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
 					     int uV)
@@ -105,7 +76,7 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
 	struct wm831x *wm831x = ldo->wm831x;
 	int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
 
-	sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV);
+	sel = regulator_map_voltage_linear_range(rdev, uV, uV);
 	if (sel < 0)
 		return sel;
 
@@ -230,8 +201,8 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
 
 
 static struct regulator_ops wm831x_gp_ldo_ops = {
-	.list_voltage = wm831x_gp_ldo_list_voltage,
-	.map_voltage = wm831x_gp_ldo_map_voltage,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
@@ -250,7 +221,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
 static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id;
 	struct wm831x_ldo *ldo;
@@ -290,7 +261,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 
 	ldo->desc.id = id;
 	ldo->desc.type = REGULATOR_VOLTAGE;
-	ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1;
+	ldo->desc.n_voltages = 32;
 	ldo->desc.ops = &wm831x_gp_ldo_ops;
 	ldo->desc.owner = THIS_MODULE;
 	ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
@@ -299,6 +270,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 	ldo->desc.enable_mask = 1 << id;
 	ldo->desc.bypass_reg = ldo->base;
 	ldo->desc.bypass_mask = WM831X_LDO1_SWI;
+	ldo->desc.linear_ranges = wm831x_gp_ldo_ranges;
+	ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges);
 
 	config.dev = pdev->dev.parent;
 	if (pdata)
@@ -358,43 +331,12 @@ static struct platform_driver wm831x_gp_ldo_driver = {
  * Analogue LDOs
  */
 
-
-#define WM831X_ALDO_SELECTOR_LOW 0xc
-#define WM831X_ALDO_MAX_SELECTOR 0x1f
-
-static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
-				      unsigned int selector)
-{
-	/* 1-1.6V in 50mV steps */
-	if (selector <= WM831X_ALDO_SELECTOR_LOW)
-		return 1000000 + (selector * 50000);
-	/* 1.7-3.5V in 100mV steps */
-	if (selector <= WM831X_ALDO_MAX_SELECTOR)
-		return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW)
-				  * 100000);
-	return -EINVAL;
-}
-
-static int wm831x_aldo_map_voltage(struct regulator_dev *rdev,
-				   int min_uV, int max_uV)
-{
-	int volt, vsel;
-
-	if (min_uV < 1000000)
-		vsel = 0;
-	else if (min_uV < 1700000)
-		vsel = ((min_uV - 1000000) / 50000);
-	else
-		vsel = ((min_uV - 1700000) / 100000)
-			+ WM831X_ALDO_SELECTOR_LOW + 1;
-
-	volt = wm831x_aldo_list_voltage(rdev, vsel);
-	if (volt < min_uV || volt > max_uV)
-		return -EINVAL;
-
-	return vsel;
-
-}
+static const struct regulator_linear_range wm831x_aldo_ranges[] = {
+	{ .min_uV = 1000000, .max_uV = 1650000, .min_sel =  0, .max_sel = 12,
+	  .uV_step =  50000 },
+	{ .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
+	  .uV_step = 100000 },
+};
 
 static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
 					     int uV)
@@ -403,7 +345,7 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
 	struct wm831x *wm831x = ldo->wm831x;
 	int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
 
-	sel = wm831x_aldo_map_voltage(rdev, uV, uV);
+	sel = regulator_map_voltage_linear_range(rdev, uV, uV);
 	if (sel < 0)
 		return sel;
 
@@ -486,8 +428,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops wm831x_aldo_ops = {
-	.list_voltage = wm831x_aldo_list_voltage,
-	.map_voltage = wm831x_aldo_map_voltage,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
@@ -505,7 +447,7 @@ static struct regulator_ops wm831x_aldo_ops = {
 static int wm831x_aldo_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id;
 	struct wm831x_ldo *ldo;
@@ -545,7 +487,9 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
 
 	ldo->desc.id = id;
 	ldo->desc.type = REGULATOR_VOLTAGE;
-	ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1;
+	ldo->desc.n_voltages = 32;
+	ldo->desc.linear_ranges = wm831x_aldo_ranges;
+	ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges);
 	ldo->desc.ops = &wm831x_aldo_ops;
 	ldo->desc.owner = THIS_MODULE;
 	ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
@@ -661,7 +605,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
 static int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
 	struct regulator_config config = { };
 	int id;
 	struct wm831x_ldo *ldo;
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 7f0fa22..835b5f0 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -542,41 +542,12 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
 	return 0;
 }
 
-static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
-				    unsigned selector)
-{
-	if (selector > WM8350_LDO1_VSEL_MASK)
-		return -EINVAL;
-
-	if (selector < 16)
-		return (selector * 50000) + 900000;
-	else
-		return ((selector - 16) * 100000) + 1800000;
-}
-
-static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV,
-				  int max_uV)
-{
-	int volt, sel;
-	int min_mV = min_uV / 1000;
-	int max_mV = max_uV / 1000;
-
-	if (min_mV < 900 || min_mV > 3300)
-		return -EINVAL;
-	if (max_mV < 900 || max_mV > 3300)
-		return -EINVAL;
-
-	if (min_mV < 1800) /* step size is 50mV < 1800mV */
-		sel = DIV_ROUND_UP(min_uV - 900, 50);
-	else /* step size is 100mV > 1800mV */
-		sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16;
-
-	volt = wm8350_ldo_list_voltage(rdev, sel);
-	if (volt < min_uV || volt > max_uV)
-		return -EINVAL;
-
-	return sel;
-}
+static const struct regulator_linear_range wm8350_ldo_ranges[] = {
+	{ .min_uV =  900000, .max_uV = 1750000, .min_sel =  0, .max_sel = 15,
+	  .uV_step =  50000 },
+	{ .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
+	  .uV_step = 100000 },
+};
 
 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
@@ -603,7 +574,7 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 		return -EINVAL;
 	}
 
-	sel = wm8350_ldo_map_voltage(rdev, uV, uV);
+	sel = regulator_map_voltage_linear_range(rdev, uV, uV);
 	if (sel < 0)
 		return -EINVAL;
 
@@ -998,10 +969,10 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
 };
 
 static struct regulator_ops wm8350_ldo_ops = {
-	.map_voltage = wm8350_ldo_map_voltage,
+	.map_voltage = regulator_map_voltage_linear_range,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
-	.list_voltage = wm8350_ldo_list_voltage,
+	.list_voltage = regulator_list_voltage_linear_range,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
@@ -1108,6 +1079,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_LDO1,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_LDO1_VSEL_MASK + 1,
+		.linear_ranges = wm8350_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
 		.vsel_reg = WM8350_LDO1_CONTROL,
 		.vsel_mask = WM8350_LDO1_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@@ -1121,6 +1094,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_LDO2,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_LDO2_VSEL_MASK + 1,
+		.linear_ranges = wm8350_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
 		.vsel_reg = WM8350_LDO2_CONTROL,
 		.vsel_mask = WM8350_LDO2_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@@ -1134,6 +1109,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_LDO3,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_LDO3_VSEL_MASK + 1,
+		.linear_ranges = wm8350_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
 		.vsel_reg = WM8350_LDO3_CONTROL,
 		.vsel_mask = WM8350_LDO3_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@@ -1147,6 +1124,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_LDO4,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_LDO4_VSEL_MASK + 1,
+		.linear_ranges = wm8350_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
 		.vsel_reg = WM8350_LDO4_CONTROL,
 		.vsel_mask = WM8350_LDO4_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@@ -1222,7 +1201,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
 	}
 
 	config.dev = &pdev->dev;
-	config.init_data = pdev->dev.platform_data;
+	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = dev_get_drvdata(&pdev->dev);
 	config.regmap = wm8350->regmap;
 
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index a09f03e..58f51be 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -19,47 +19,21 @@
 #include <linux/regulator/driver.h>
 #include <linux/mfd/wm8400-private.h>
 
-static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
-				   unsigned selector)
-{
-	if (selector > WM8400_LDO1_VSEL_MASK)
-		return -EINVAL;
-
-	if (selector < 15)
-		return 900000 + (selector * 50000);
-	else
-		return 1700000 + ((selector - 15) * 100000);
-}
-
-static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
-				  int min_uV, int max_uV)
-{
-	u16 val;
-	int volt;
-
-	if (min_uV < 900000 || min_uV > 3300000)
-		return -EINVAL;
-
-	if (min_uV < 1700000) /* Steps of 50mV from 900mV;  */
-		val = DIV_ROUND_UP(min_uV - 900000, 50000);
-	else /* Steps of 100mV from 1700mV */
-		val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15;
-
-	volt = wm8400_ldo_list_voltage(dev, val);
-	if (volt < min_uV || volt > max_uV)
-		return -EINVAL;
-
-	return val;
-}
+static const struct regulator_linear_range wm8400_ldo_ranges[] = {
+	{ .min_uV =  900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
+	  .uV_step =  50000 },
+	{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
+	  .uV_step = 100000 },
+};
 
 static struct regulator_ops wm8400_ldo_ops = {
 	.is_enabled = regulator_is_enabled_regmap,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
-	.list_voltage = wm8400_ldo_list_voltage,
+	.list_voltage = regulator_list_voltage_linear_range,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
-	.map_voltage = wm8400_ldo_map_voltage,
+	.map_voltage = regulator_map_voltage_linear_range,
 };
 
 static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
@@ -155,6 +129,8 @@ static struct regulator_desc regulators[] = {
 		.enable_reg = WM8400_LDO1_CONTROL,
 		.enable_mask = WM8400_LDO1_ENA,
 		.n_voltages = WM8400_LDO1_VSEL_MASK + 1,
+		.linear_ranges = wm8400_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 		.vsel_reg = WM8400_LDO1_CONTROL,
 		.vsel_mask = WM8400_LDO1_VSEL_MASK,
 		.type = REGULATOR_VOLTAGE,
@@ -167,6 +143,8 @@ static struct regulator_desc regulators[] = {
 		.enable_reg = WM8400_LDO2_CONTROL,
 		.enable_mask = WM8400_LDO2_ENA,
 		.n_voltages = WM8400_LDO2_VSEL_MASK + 1,
+		.linear_ranges = wm8400_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 		.type = REGULATOR_VOLTAGE,
 		.vsel_reg = WM8400_LDO2_CONTROL,
 		.vsel_mask = WM8400_LDO2_VSEL_MASK,
@@ -179,6 +157,8 @@ static struct regulator_desc regulators[] = {
 		.enable_reg = WM8400_LDO3_CONTROL,
 		.enable_mask = WM8400_LDO3_ENA,
 		.n_voltages = WM8400_LDO3_VSEL_MASK + 1,
+		.linear_ranges = wm8400_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 		.vsel_reg = WM8400_LDO3_CONTROL,
 		.vsel_mask = WM8400_LDO3_VSEL_MASK,
 		.type = REGULATOR_VOLTAGE,
@@ -191,6 +171,8 @@ static struct regulator_desc regulators[] = {
 		.enable_reg = WM8400_LDO4_CONTROL,
 		.enable_mask = WM8400_LDO4_ENA,
 		.n_voltages = WM8400_LDO4_VSEL_MASK + 1,
+		.linear_ranges = wm8400_ldo_ranges,
+		.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 		.vsel_reg = WM8400_LDO4_CONTROL,
 		.vsel_mask = WM8400_LDO4_VSEL_MASK,
 		.type = REGULATOR_VOLTAGE,
@@ -233,7 +215,7 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
 	struct regulator_dev *rdev;
 
 	config.dev = &pdev->dev;
-	config.init_data = pdev->dev.platform_data;
+	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = wm8400;
 	config.regmap = wm8400->regmap;
 
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 8f2a8a7..5ee2a20 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -125,7 +125,7 @@ static const struct regulator_init_data wm8994_ldo_default[] = {
 static int wm8994_ldo_probe(struct platform_device *pdev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
-	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev);
 	int id = pdev->id % ARRAY_SIZE(pdata->ldo);
 	struct regulator_config config = { };
 	struct wm8994_ldo *ldo;
diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c
index 9b2e60a..129f7b9 100644
--- a/drivers/remoteproc/da8xx_remoteproc.c
+++ b/drivers/remoteproc/da8xx_remoteproc.c
@@ -165,7 +165,7 @@ static int reset_assert(struct device *dev)
 	dsp_clk = clk_get(dev, NULL);
 	if (IS_ERR(dsp_clk)) {
 		dev_err(dev, "clk_get error: %ld\n", PTR_ERR(dsp_clk));
-		return PTR_RET(dsp_clk);
+		return PTR_ERR(dsp_clk);
 	}
 
 	davinci_clk_reset_assert(dsp_clk);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9e3498b..9654aa3 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1249,6 +1249,15 @@ config RTC_DRV_SIRFSOC
 	  Say "yes" here to support the real time clock on SiRF SOC chips.
 	  This driver can also be built as a module called rtc-sirfsoc.
 
+config RTC_DRV_MOXART
+	tristate "MOXA ART RTC"
+	help
+	   If you say yes here you get support for the MOXA ART
+	   RTC module.
+
+	   This driver can also be built as a module. If so, the module
+	   will be called rtc-moxart
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index d3b4488..2dff3d2 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -130,3 +130,4 @@ obj-$(CONFIG_RTC_DRV_WM831X)	+= rtc-wm831x.o
 obj-$(CONFIG_RTC_DRV_WM8350)	+= rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_SIRFSOC)	+= rtc-sirfsoc.o
+obj-$(CONFIG_RTC_DRV_MOXART)	+= rtc-moxart.o
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c
index 9c8c194..4385ca4 100644
--- a/drivers/rtc/rtc-da9052.c
+++ b/drivers/rtc/rtc-da9052.c
@@ -250,7 +250,7 @@ static int da9052_rtc_probe(struct platform_device *pdev)
 
 	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				       &da9052_rtc_ops, THIS_MODULE);
-	return PTR_RET(rtc->rtc);
+	return PTR_ERR_OR_ZERO(rtc->rtc);
 }
 
 static struct platform_driver da9052_rtc_driver = {
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index 7273b01..b5a2874 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -23,10 +23,6 @@
 #include <linux/iio/iio.h>
 #include <linux/rtc.h>
 
-/* Format: HID-SENSOR-usage_id_in_hex */
-/* Usage ID from spec for Time: 0x2000A0 */
-#define DRIVER_NAME "HID-SENSOR-2000a0" /* must be lowercase */
-
 enum hid_time_channel {
 	CHANNEL_SCAN_INDEX_YEAR,
 	CHANNEL_SCAN_INDEX_MONTH,
@@ -300,9 +296,19 @@ static int hid_time_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static struct platform_device_id hid_time_ids[] = {
+	{
+		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+		.name = "HID-SENSOR-2000a0",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_time_ids);
+
 static struct platform_driver hid_time_platform_driver = {
+	.id_table = hid_time_ids,
 	.driver = {
-		.name	= DRIVER_NAME,
+		.name	= KBUILD_MODNAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= hid_time_probe,
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index 5dbdc44..03b8911 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -268,7 +268,7 @@ static int isl12022_probe(struct i2c_client *client,
 	isl12022->rtc = devm_rtc_device_register(&client->dev,
 					isl12022_driver.driver.name,
 					&isl12022_rtc_ops, THIS_MODULE);
-	return PTR_RET(isl12022->rtc);
+	return PTR_ERR_OR_ZERO(isl12022->rtc);
 }
 
 static const struct i2c_device_id isl12022_id[] = {
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index 23c3779..411adb3 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -175,7 +175,7 @@ static int m48t35_probe(struct platform_device *pdev)
 
 	priv->rtc = devm_rtc_device_register(&pdev->dev, "m48t35",
 				  &m48t35_ops, THIS_MODULE);
-	return PTR_RET(priv->rtc);
+	return PTR_ERR_OR_ZERO(priv->rtc);
 }
 
 static struct platform_driver m48t35_platform_driver = {
diff --git a/drivers/rtc/rtc-moxart.c b/drivers/rtc/rtc-moxart.c
new file mode 100644
index 0000000..c29dee0
--- /dev/null
+++ b/drivers/rtc/rtc-moxart.c
@@ -0,0 +1,330 @@
+/*
+ * MOXA ART RTC driver.
+ *
+ * Copyright (C) 2013 Jonas Jensen
+ *
+ * Jonas Jensen <jonas.jensen@gmail.com>
+ *
+ * Based on code from
+ * Moxa Technology Co., Ltd. <www.moxa.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#define GPIO_RTC_RESERVED			0x0C
+#define GPIO_RTC_DATA_SET			0x10
+#define GPIO_RTC_DATA_CLEAR			0x14
+#define GPIO_RTC_PIN_PULL_ENABLE		0x18
+#define GPIO_RTC_PIN_PULL_TYPE			0x1C
+#define GPIO_RTC_INT_ENABLE			0x20
+#define GPIO_RTC_INT_RAW_STATE			0x24
+#define GPIO_RTC_INT_MASKED_STATE		0x28
+#define GPIO_RTC_INT_MASK			0x2C
+#define GPIO_RTC_INT_CLEAR			0x30
+#define GPIO_RTC_INT_TRIGGER			0x34
+#define GPIO_RTC_INT_BOTH			0x38
+#define GPIO_RTC_INT_RISE_NEG			0x3C
+#define GPIO_RTC_BOUNCE_ENABLE			0x40
+#define GPIO_RTC_BOUNCE_PRE_SCALE		0x44
+#define GPIO_RTC_PROTECT_W			0x8E
+#define GPIO_RTC_PROTECT_R			0x8F
+#define GPIO_RTC_YEAR_W				0x8C
+#define GPIO_RTC_YEAR_R				0x8D
+#define GPIO_RTC_DAY_W				0x8A
+#define GPIO_RTC_DAY_R				0x8B
+#define GPIO_RTC_MONTH_W			0x88
+#define GPIO_RTC_MONTH_R			0x89
+#define GPIO_RTC_DATE_W				0x86
+#define GPIO_RTC_DATE_R				0x87
+#define GPIO_RTC_HOURS_W			0x84
+#define GPIO_RTC_HOURS_R			0x85
+#define GPIO_RTC_MINUTES_W			0x82
+#define GPIO_RTC_MINUTES_R			0x83
+#define GPIO_RTC_SECONDS_W			0x80
+#define GPIO_RTC_SECONDS_R			0x81
+#define GPIO_RTC_DELAY_TIME			8
+
+struct moxart_rtc {
+	struct rtc_device *rtc;
+	spinlock_t rtc_lock;
+	int gpio_data, gpio_sclk, gpio_reset;
+};
+
+static int day_of_year[12] =	{ 0, 31, 59, 90, 120, 151, 181,
+				  212, 243, 273, 304, 334 };
+
+static void moxart_rtc_write_byte(struct device *dev, u8 data)
+{
+	struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < 8; i++, data >>= 1) {
+		gpio_set_value(moxart_rtc->gpio_sclk, 0);
+		gpio_set_value(moxart_rtc->gpio_data, ((data & 1) == 1));
+		udelay(GPIO_RTC_DELAY_TIME);
+		gpio_set_value(moxart_rtc->gpio_sclk, 1);
+		udelay(GPIO_RTC_DELAY_TIME);
+	}
+}
+
+static u8 moxart_rtc_read_byte(struct device *dev)
+{
+	struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+	int i;
+	u8 data = 0;
+
+	for (i = 0; i < 8; i++) {
+		gpio_set_value(moxart_rtc->gpio_sclk, 0);
+		udelay(GPIO_RTC_DELAY_TIME);
+		gpio_set_value(moxart_rtc->gpio_sclk, 1);
+		udelay(GPIO_RTC_DELAY_TIME);
+		if (gpio_get_value(moxart_rtc->gpio_data))
+			data |= (1 << i);
+		udelay(GPIO_RTC_DELAY_TIME);
+	}
+	return data;
+}
+
+static u8 moxart_rtc_read_register(struct device *dev, u8 cmd)
+{
+	struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+	u8 data;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	gpio_direction_output(moxart_rtc->gpio_data, 0);
+	gpio_set_value(moxart_rtc->gpio_reset, 1);
+	udelay(GPIO_RTC_DELAY_TIME);
+	moxart_rtc_write_byte(dev, cmd);
+	gpio_direction_input(moxart_rtc->gpio_data);
+	udelay(GPIO_RTC_DELAY_TIME);
+	data = moxart_rtc_read_byte(dev);
+	gpio_set_value(moxart_rtc->gpio_sclk, 0);
+	gpio_set_value(moxart_rtc->gpio_reset, 0);
+	udelay(GPIO_RTC_DELAY_TIME);
+
+	local_irq_restore(flags);
+
+	return data;
+}
+
+static void moxart_rtc_write_register(struct device *dev, u8 cmd, u8 data)
+{
+	struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	gpio_direction_output(moxart_rtc->gpio_data, 0);
+	gpio_set_value(moxart_rtc->gpio_reset, 1);
+	udelay(GPIO_RTC_DELAY_TIME);
+	moxart_rtc_write_byte(dev, cmd);
+	moxart_rtc_write_byte(dev, data);
+	gpio_set_value(moxart_rtc->gpio_sclk, 0);
+	gpio_set_value(moxart_rtc->gpio_reset, 0);
+	udelay(GPIO_RTC_DELAY_TIME);
+
+	local_irq_restore(flags);
+}
+
+static int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+
+	spin_lock_irq(&moxart_rtc->rtc_lock);
+
+	moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0);
+	moxart_rtc_write_register(dev, GPIO_RTC_YEAR_W,
+				  (((tm->tm_year - 100) / 10) << 4) |
+				  ((tm->tm_year - 100) % 10));
+
+	moxart_rtc_write_register(dev, GPIO_RTC_MONTH_W,
+				  (((tm->tm_mon + 1) / 10) << 4) |
+				  ((tm->tm_mon + 1) % 10));
+
+	moxart_rtc_write_register(dev, GPIO_RTC_DATE_W,
+				  ((tm->tm_mday / 10) << 4) |
+				  (tm->tm_mday % 10));
+
+	moxart_rtc_write_register(dev, GPIO_RTC_HOURS_W,
+				  ((tm->tm_hour / 10) << 4) |
+				  (tm->tm_hour % 10));
+
+	moxart_rtc_write_register(dev, GPIO_RTC_MINUTES_W,
+				  ((tm->tm_min / 10) << 4) |
+				  (tm->tm_min % 10));
+
+	moxart_rtc_write_register(dev, GPIO_RTC_SECONDS_W,
+				  ((tm->tm_sec / 10) << 4) |
+				  (tm->tm_sec % 10));
+
+	moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0x80);
+
+	spin_unlock_irq(&moxart_rtc->rtc_lock);
+
+	dev_dbg(dev, "%s: success tm_year=%d tm_mon=%d\n"
+		"tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n",
+		__func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	return 0;
+}
+
+static int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+	unsigned char v;
+
+	spin_lock_irq(&moxart_rtc->rtc_lock);
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_SECONDS_R);
+	tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_MINUTES_R);
+	tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_HOURS_R);
+	if (v & 0x80) { /* 12-hour mode */
+		tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
+		if (v & 0x20) { /* PM mode */
+			tm->tm_hour += 12;
+			if (tm->tm_hour >= 24)
+				tm->tm_hour = 0;
+		}
+	} else { /* 24-hour mode */
+		tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
+	}
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_DATE_R);
+	tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_MONTH_R);
+	tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
+	tm->tm_mon--;
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_YEAR_R);
+	tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F);
+	tm->tm_year += 100;
+	if (tm->tm_year <= 69)
+		tm->tm_year += 100;
+
+	v = moxart_rtc_read_register(dev, GPIO_RTC_DAY_R);
+	tm->tm_wday = (v & 0x0f) - 1;
+	tm->tm_yday = day_of_year[tm->tm_mon];
+	tm->tm_yday += (tm->tm_mday - 1);
+	if (tm->tm_mon >= 2) {
+		if (!(tm->tm_year % 4) && (tm->tm_year % 100))
+			tm->tm_yday++;
+	}
+
+	tm->tm_isdst = 0;
+
+	spin_unlock_irq(&moxart_rtc->rtc_lock);
+
+	return 0;
+}
+
+static const struct rtc_class_ops moxart_rtc_ops = {
+	.read_time	= moxart_rtc_read_time,
+	.set_time	= moxart_rtc_set_time,
+};
+
+static int moxart_rtc_probe(struct platform_device *pdev)
+{
+	struct moxart_rtc *moxart_rtc;
+	int ret = 0;
+
+	moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL);
+	if (!moxart_rtc) {
+		dev_err(&pdev->dev, "devm_kzalloc failed\n");
+		return -ENOMEM;
+	}
+
+	moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node,
+						  "gpio-rtc-data", 0);
+	if (!gpio_is_valid(moxart_rtc->gpio_data)) {
+		dev_err(&pdev->dev, "invalid gpio (data): %d\n",
+			moxart_rtc->gpio_data);
+		return moxart_rtc->gpio_data;
+	}
+
+	moxart_rtc->gpio_sclk = of_get_named_gpio(pdev->dev.of_node,
+						  "gpio-rtc-sclk", 0);
+	if (!gpio_is_valid(moxart_rtc->gpio_sclk)) {
+		dev_err(&pdev->dev, "invalid gpio (sclk): %d\n",
+			moxart_rtc->gpio_sclk);
+		return moxart_rtc->gpio_sclk;
+	}
+
+	moxart_rtc->gpio_reset = of_get_named_gpio(pdev->dev.of_node,
+						   "gpio-rtc-reset", 0);
+	if (!gpio_is_valid(moxart_rtc->gpio_reset)) {
+		dev_err(&pdev->dev, "invalid gpio (reset): %d\n",
+			moxart_rtc->gpio_reset);
+		return moxart_rtc->gpio_reset;
+	}
+
+	spin_lock_init(&moxart_rtc->rtc_lock);
+	platform_set_drvdata(pdev, moxart_rtc);
+
+	ret = devm_gpio_request(&pdev->dev, moxart_rtc->gpio_data, "rtc_data");
+	if (ret) {
+		dev_err(&pdev->dev, "can't get rtc_data gpio\n");
+		return ret;
+	}
+
+	ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_sclk,
+				    GPIOF_DIR_OUT, "rtc_sclk");
+	if (ret) {
+		dev_err(&pdev->dev, "can't get rtc_sclk gpio\n");
+		return ret;
+	}
+
+	ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_reset,
+				    GPIOF_DIR_OUT, "rtc_reset");
+	if (ret) {
+		dev_err(&pdev->dev, "can't get rtc_reset gpio\n");
+		return ret;
+	}
+
+	moxart_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+						   &moxart_rtc_ops,
+						   THIS_MODULE);
+	if (IS_ERR(moxart_rtc->rtc)) {
+		dev_err(&pdev->dev, "devm_rtc_device_register failed\n");
+		return PTR_ERR(moxart_rtc->rtc);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id moxart_rtc_match[] = {
+	{ .compatible = "moxa,moxart-rtc" },
+	{ },
+};
+
+static struct platform_driver moxart_rtc_driver = {
+	.probe	= moxart_rtc_probe,
+	.driver	= {
+		.name		= "moxart-rtc",
+		.owner		= THIS_MODULE,
+		.of_match_table	= moxart_rtc_match,
+	},
+};
+module_platform_driver(moxart_rtc_driver);
+
+MODULE_DESCRIPTION("MOXART RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index c6ffbae..c7d97ee 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -70,6 +70,8 @@
 #define OMAP_RTC_KICK0_REG		0x6c
 #define OMAP_RTC_KICK1_REG		0x70
 
+#define OMAP_RTC_IRQWAKEEN		0x7c
+
 /* OMAP_RTC_CTRL_REG bit fields: */
 #define OMAP_RTC_CTRL_SPLIT		(1<<7)
 #define OMAP_RTC_CTRL_DISABLE		(1<<6)
@@ -94,12 +96,21 @@
 #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
 #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
 
+/* OMAP_RTC_IRQWAKEEN bit fields: */
+#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN    (1<<1)
+
 /* OMAP_RTC_KICKER values */
 #define	KICK0_VALUE			0x83e70b13
 #define	KICK1_VALUE			0x95a4f1e0
 
 #define	OMAP_RTC_HAS_KICKER		0x1
 
+/*
+ * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
+ * generation for event Alarm.
+ */
+#define	OMAP_RTC_HAS_IRQWAKEEN		0x2
+
 static void __iomem	*rtc_base;
 
 #define rtc_read(addr)		readb(rtc_base + (addr))
@@ -299,12 +310,18 @@ static struct rtc_class_ops omap_rtc_ops = {
 static int omap_rtc_alarm;
 static int omap_rtc_timer;
 
-#define	OMAP_RTC_DATA_DA830_IDX	1
+#define	OMAP_RTC_DATA_AM3352_IDX	1
+#define	OMAP_RTC_DATA_DA830_IDX		2
 
 static struct platform_device_id omap_rtc_devtype[] = {
 	{
 		.name	= DRIVER_NAME,
-	}, {
+	},
+	[OMAP_RTC_DATA_AM3352_IDX] = {
+		.name	= "am3352-rtc",
+		.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
+	},
+	[OMAP_RTC_DATA_DA830_IDX] = {
 		.name	= "da830-rtc",
 		.driver_data = OMAP_RTC_HAS_KICKER,
 	},
@@ -316,6 +333,9 @@ static const struct of_device_id omap_rtc_of_match[] = {
 	{	.compatible	= "ti,da830-rtc",
 		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
 	},
+	{	.compatible	= "ti,am3352-rtc",
+		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
@@ -464,16 +484,28 @@ static u8 irqstat;
 
 static int omap_rtc_suspend(struct device *dev)
 {
+	u8 irqwake_stat;
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct platform_device_id *id_entry =
+					platform_get_device_id(pdev);
+
 	irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
 
 	/* FIXME the RTC alarm is not currently acting as a wakeup event
-	 * source, and in fact this enable() call is just saving a flag
-	 * that's never used...
+	 * source on some platforms, and in fact this enable() call is just
+	 * saving a flag that's never used...
 	 */
-	if (device_may_wakeup(dev))
+	if (device_may_wakeup(dev)) {
 		enable_irq_wake(omap_rtc_alarm);
-	else
+
+		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
+			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
+			irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
+			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
+		}
+	} else {
 		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	}
 
 	/* Disable the clock/module */
 	pm_runtime_put_sync(dev);
@@ -483,13 +515,25 @@ static int omap_rtc_suspend(struct device *dev)
 
 static int omap_rtc_resume(struct device *dev)
 {
+	u8 irqwake_stat;
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(pdev);
+
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_get_sync(dev);
 
-	if (device_may_wakeup(dev))
+	if (device_may_wakeup(dev)) {
 		disable_irq_wake(omap_rtc_alarm);
-	else
+
+		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
+			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
+			irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
+			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
+		}
+	} else {
 		rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
+	}
 	return 0;
 }
 #endif
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 205b9f7..1ee514a 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -203,11 +203,6 @@ static int pcf2127_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int pcf2127_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
 static const struct i2c_device_id pcf2127_id[] = {
 	{ "pcf2127", 0 },
 	{ }
@@ -229,7 +224,6 @@ static struct i2c_driver pcf2127_driver = {
 		.of_match_table = of_match_ptr(pcf2127_of_match),
 	},
 	.probe		= pcf2127_probe,
-	.remove		= pcf2127_remove,
 	.id_table	= pcf2127_id,
 };
 
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 710c3a5..63b558c 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -264,7 +264,7 @@ static int pcf8563_probe(struct i2c_client *client,
 				pcf8563_driver.driver.name,
 				&pcf8563_rtc_ops, THIS_MODULE);
 
-	return PTR_RET(pcf8563->rtc);
+	return PTR_ERR_OR_ZERO(pcf8563->rtc);
 }
 
 static const struct i2c_device_id pcf8563_id[] = {
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 843a745..c263984 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -285,7 +285,7 @@ static int pcf8583_probe(struct i2c_client *client,
 				pcf8583_driver.driver.name,
 				&pcf8583_rtc_ops, THIS_MODULE);
 
-	return PTR_RET(pcf8583->rtc);
+	return PTR_ERR_OR_ZERO(pcf8583->rtc);
 }
 
 static const struct i2c_device_id pcf8583_id[] = {
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 4b26f86..babd43b 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -25,15 +25,14 @@
  */
 
 static ssize_t
-rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr,
-		char *buf)
+name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
 }
+static DEVICE_ATTR_RO(name);
 
 static ssize_t
-rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
-		char *buf)
+date_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t retval;
 	struct rtc_time tm;
@@ -46,10 +45,10 @@ rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
 
 	return retval;
 }
+static DEVICE_ATTR_RO(date);
 
 static ssize_t
-rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
-		char *buf)
+time_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t retval;
 	struct rtc_time tm;
@@ -62,10 +61,10 @@ rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
 
 	return retval;
 }
+static DEVICE_ATTR_RO(time);
 
 static ssize_t
-rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
-		char *buf)
+since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t retval;
 	struct rtc_time tm;
@@ -79,16 +78,16 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
 
 	return retval;
 }
+static DEVICE_ATTR_RO(since_epoch);
 
 static ssize_t
-rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr,
-		char *buf)
+max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq);
 }
 
 static ssize_t
-rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
+max_user_freq_store(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t n)
 {
 	struct rtc_device *rtc = to_rtc_device(dev);
@@ -101,6 +100,7 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
 
 	return n;
 }
+static DEVICE_ATTR_RW(max_user_freq);
 
 /**
  * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time
@@ -109,8 +109,7 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
  * boot or resume event.
  */
 static ssize_t
-rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
-		char *buf)
+hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 #ifdef CONFIG_RTC_HCTOSYS_DEVICE
 	if (rtc_hctosys_ret == 0 &&
@@ -121,17 +120,18 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
 #endif
 		return sprintf(buf, "0\n");
 }
-
-static struct device_attribute rtc_attrs[] = {
-	__ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),
-	__ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),
-	__ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),
-	__ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),
-	__ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq,
-			rtc_sysfs_set_max_user_freq),
-	__ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL),
-	{ },
+static DEVICE_ATTR_RO(hctosys);
+
+static struct attribute *rtc_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_date.attr,
+	&dev_attr_time.attr,
+	&dev_attr_since_epoch.attr,
+	&dev_attr_max_user_freq.attr,
+	&dev_attr_hctosys.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(rtc);
 
 static ssize_t
 rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
@@ -261,5 +261,5 @@ void rtc_sysfs_del_device(struct rtc_device *rtc)
 
 void __init rtc_sysfs_init(struct class *rtc_class)
 {
-	rtc_class->dev_attrs = rtc_attrs;
+	rtc_class->dev_groups = rtc_groups;
 }
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 17150a7..451bf99 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2392,6 +2392,12 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
 		rc = cqr->intrc;
 	else
 		rc = -EIO;
+
+	/* kick tasklets */
+	dasd_schedule_device_bh(device);
+	if (device->block)
+		dasd_schedule_block_bh(device->block);
+
 	return rc;
 }
 
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 58bc6eb..2ead7e7 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -930,7 +930,7 @@ dasd_use_raw_store(struct device *dev, struct device_attribute *attr,
 	if (IS_ERR(devmap))
 		return PTR_ERR(devmap);
 
-	if ((strict_strtoul(buf, 10, &val) != 0) || val > 1)
+	if ((kstrtoul(buf, 10, &val) != 0) || val > 1)
 		return -EINVAL;
 
 	spin_lock(&dasd_devmap_lock);
@@ -1225,7 +1225,7 @@ dasd_expires_store(struct device *dev, struct device_attribute *attr,
 	if (IS_ERR(device))
 		return -ENODEV;
 
-	if ((strict_strtoul(buf, 10, &val) != 0) ||
+	if ((kstrtoul(buf, 10, &val) != 0) ||
 	    (val > DASD_EXPIRES_MAX) || val == 0) {
 		dasd_put_device(device);
 		return -EINVAL;
@@ -1265,7 +1265,7 @@ dasd_retries_store(struct device *dev, struct device_attribute *attr,
 	if (IS_ERR(device))
 		return -ENODEV;
 
-	if ((strict_strtoul(buf, 10, &val) != 0) ||
+	if ((kstrtoul(buf, 10, &val) != 0) ||
 	    (val > DASD_RETRIES_MAX)) {
 		dasd_put_device(device);
 		return -EINVAL;
@@ -1307,7 +1307,7 @@ dasd_timeout_store(struct device *dev, struct device_attribute *attr,
 	if (IS_ERR(device) || !device->block)
 		return -ENODEV;
 
-	if ((strict_strtoul(buf, 10, &val) != 0) ||
+	if ((kstrtoul(buf, 10, &val) != 0) ||
 	    val > UINT_MAX / HZ) {
 		dasd_put_device(device);
 		return -EINVAL;
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 8d11f77..ba99b64 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -160,11 +160,13 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
 
 	device = cqr->startdev;
 	if (cqr->intrc == -ETIMEDOUT) {
-		dev_err(&device->cdev->dev, "cqr %p timeout error", cqr);
+		dev_err(&device->cdev->dev,
+			"A timeout error occurred for cqr %p", cqr);
 		return;
 	}
 	if (cqr->intrc == -ENOLINK) {
-		dev_err(&device->cdev->dev, "cqr %p transport error", cqr);
+		dev_err(&device->cdev->dev,
+			"A transport error occurred for cqr %p", cqr);
 		return;
 	}
 	/* dump sense data */
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 444d361..9441562 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -32,7 +32,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
 	struct device *dev;
 
 	s390_adjust_jiffies();
-	pr_warning("cpu capability changed.\n");
+	pr_info("CPU capability may have changed\n");
 	get_online_cpus();
 	for_each_online_cpu(cpu) {
 		dev = get_cpu_device(cpu);
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 9e5e146..794820a 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -30,8 +30,8 @@
 
 #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
 
-#define TO_USER		0
-#define TO_KERNEL	1
+#define TO_USER		1
+#define TO_KERNEL	0
 #define CHUNK_INFO_SIZE	34 /* 2 16-byte char, each followed by blank */
 
 enum arch_id {
@@ -73,7 +73,7 @@ static struct ipl_parameter_block *ipl_block;
  * @count: Size of buffer, which should be copied
  * @mode:  Either TO_KERNEL or TO_USER
  */
-static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
+int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
 {
 	int offs, blk_num;
 	static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 91edbd7..d028fd8 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -81,15 +81,185 @@ void unregister_adapter_interrupt(struct airq_struct *airq)
 }
 EXPORT_SYMBOL(unregister_adapter_interrupt);
 
-void do_adapter_IO(u8 isc)
+static irqreturn_t do_airq_interrupt(int irq, void *dummy)
 {
+	struct tpi_info *tpi_info;
 	struct airq_struct *airq;
 	struct hlist_head *head;
 
-	head = &airq_lists[isc];
+	__this_cpu_write(s390_idle.nohz_delay, 1);
+	tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
+	head = &airq_lists[tpi_info->isc];
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(airq, head, list)
 		if ((*airq->lsi_ptr & airq->lsi_mask) != 0)
 			airq->handler(airq);
 	rcu_read_unlock();
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction airq_interrupt = {
+	.name	 = "AIO",
+	.handler = do_airq_interrupt,
+};
+
+void __init init_airq_interrupts(void)
+{
+	irq_set_chip_and_handler(THIN_INTERRUPT,
+				 &dummy_irq_chip, handle_percpu_irq);
+	setup_irq(THIN_INTERRUPT, &airq_interrupt);
+}
+
+/**
+ * airq_iv_create - create an interrupt vector
+ * @bits: number of bits in the interrupt vector
+ * @flags: allocation flags
+ *
+ * Returns a pointer to an interrupt vector structure
+ */
+struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
+{
+	struct airq_iv *iv;
+	unsigned long size;
+
+	iv = kzalloc(sizeof(*iv), GFP_KERNEL);
+	if (!iv)
+		goto out;
+	iv->bits = bits;
+	size = BITS_TO_LONGS(bits) * sizeof(unsigned long);
+	iv->vector = kzalloc(size, GFP_KERNEL);
+	if (!iv->vector)
+		goto out_free;
+	if (flags & AIRQ_IV_ALLOC) {
+		iv->avail = kmalloc(size, GFP_KERNEL);
+		if (!iv->avail)
+			goto out_free;
+		memset(iv->avail, 0xff, size);
+		iv->end = 0;
+	} else
+		iv->end = bits;
+	if (flags & AIRQ_IV_BITLOCK) {
+		iv->bitlock = kzalloc(size, GFP_KERNEL);
+		if (!iv->bitlock)
+			goto out_free;
+	}
+	if (flags & AIRQ_IV_PTR) {
+		size = bits * sizeof(unsigned long);
+		iv->ptr = kzalloc(size, GFP_KERNEL);
+		if (!iv->ptr)
+			goto out_free;
+	}
+	if (flags & AIRQ_IV_DATA) {
+		size = bits * sizeof(unsigned int);
+		iv->data = kzalloc(size, GFP_KERNEL);
+		if (!iv->data)
+			goto out_free;
+	}
+	spin_lock_init(&iv->lock);
+	return iv;
+
+out_free:
+	kfree(iv->ptr);
+	kfree(iv->bitlock);
+	kfree(iv->avail);
+	kfree(iv->vector);
+	kfree(iv);
+out:
+	return NULL;
+}
+EXPORT_SYMBOL(airq_iv_create);
+
+/**
+ * airq_iv_release - release an interrupt vector
+ * @iv: pointer to interrupt vector structure
+ */
+void airq_iv_release(struct airq_iv *iv)
+{
+	kfree(iv->data);
+	kfree(iv->ptr);
+	kfree(iv->bitlock);
+	kfree(iv->vector);
+	kfree(iv->avail);
+	kfree(iv);
+}
+EXPORT_SYMBOL(airq_iv_release);
+
+/**
+ * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector
+ * @iv: pointer to an interrupt vector structure
+ *
+ * Returns the bit number of the allocated irq, or -1UL if no bit
+ * is available or the AIRQ_IV_ALLOC flag has not been specified
+ */
+unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
+{
+	const unsigned long be_to_le = BITS_PER_LONG - 1;
+	unsigned long bit;
+
+	if (!iv->avail)
+		return -1UL;
+	spin_lock(&iv->lock);
+	bit = find_first_bit_left(iv->avail, iv->bits);
+	if (bit < iv->bits) {
+		clear_bit(bit ^ be_to_le, iv->avail);
+		if (bit >= iv->end)
+			iv->end = bit + 1;
+	} else
+		bit = -1UL;
+	spin_unlock(&iv->lock);
+	return bit;
+
+}
+EXPORT_SYMBOL(airq_iv_alloc_bit);
+
+/**
+ * airq_iv_free_bit - free an irq bit of an interrupt vector
+ * @iv: pointer to interrupt vector structure
+ * @bit: number of the irq bit to free
+ */
+void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
+{
+	const unsigned long be_to_le = BITS_PER_LONG - 1;
+
+	if (!iv->avail)
+		return;
+	spin_lock(&iv->lock);
+	/* Clear (possibly left over) interrupt bit */
+	clear_bit(bit ^ be_to_le, iv->vector);
+	/* Make the bit position available again */
+	set_bit(bit ^ be_to_le, iv->avail);
+	if (bit == iv->end - 1) {
+		/* Find new end of bit-field */
+		while (--iv->end > 0)
+			if (!test_bit((iv->end - 1) ^ be_to_le, iv->avail))
+				break;
+	}
+	spin_unlock(&iv->lock);
+}
+EXPORT_SYMBOL(airq_iv_free_bit);
+
+/**
+ * airq_iv_scan - scan interrupt vector for non-zero bits
+ * @iv: pointer to interrupt vector structure
+ * @start: bit number to start the search
+ * @end: bit number to end the search
+ *
+ * Returns the bit number of the next non-zero interrupt bit, or
+ * -1UL if the scan completed without finding any more any non-zero bits.
+ */
+unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
+			   unsigned long end)
+{
+	const unsigned long be_to_le = BITS_PER_LONG - 1;
+	unsigned long bit;
+
+	/* Find non-zero bit starting from 'ivs->next'. */
+	bit = find_next_bit_left(iv->vector, end, start);
+	if (bit >= end)
+		return -1UL;
+	/* Clear interrupt bit (find left uses big-endian bit numbers) */
+	clear_bit(bit ^ be_to_le, iv->vector);
+	return bit;
 }
+EXPORT_SYMBOL(airq_iv_scan);
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 84846c2..959135a 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -137,7 +137,7 @@ static ssize_t ccwgroup_online_store(struct device *dev,
 	if (!try_module_get(gdrv->driver.owner))
 		return -EINVAL;
 
-	ret = strict_strtoul(buf, 0, &value);
+	ret = kstrtoul(buf, 0, &value);
 	if (ret)
 		goto out;
 
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 4eeb4a6..d7da67a 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -561,37 +561,23 @@ out:
 }
 
 /*
- * do_IRQ() handles all normal I/O device IRQ's (the special
- *	    SMP cross-CPU interrupts have their own specific
- *	    handlers).
- *
+ * do_cio_interrupt() handles all normal I/O device IRQ's
  */
-void __irq_entry do_IRQ(struct pt_regs *regs)
+static irqreturn_t do_cio_interrupt(int irq, void *dummy)
 {
-	struct tpi_info *tpi_info = (struct tpi_info *) &regs->int_code;
+	struct tpi_info *tpi_info;
 	struct subchannel *sch;
 	struct irb *irb;
-	struct pt_regs *old_regs;
 
-	old_regs = set_irq_regs(regs);
-	irq_enter();
 	__this_cpu_write(s390_idle.nohz_delay, 1);
-	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
-		/* Serve timer interrupts first. */
-		clock_comparator_work();
-
-	kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
+	tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
 	irb = (struct irb *) &S390_lowcore.irb;
-	if (tpi_info->adapter_IO) {
-		do_adapter_IO(tpi_info->isc);
-		goto out;
-	}
 	sch = (struct subchannel *)(unsigned long) tpi_info->intparm;
 	if (!sch) {
 		/* Clear pending interrupt condition. */
 		inc_irq_stat(IRQIO_CIO);
 		tsch(tpi_info->schid, irb);
-		goto out;
+		return IRQ_HANDLED;
 	}
 	spin_lock(sch->lock);
 	/* Store interrupt response block to lowcore. */
@@ -606,9 +592,23 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
 	} else
 		inc_irq_stat(IRQIO_CIO);
 	spin_unlock(sch->lock);
-out:
-	irq_exit();
-	set_irq_regs(old_regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irq_desc *irq_desc_io;
+
+static struct irqaction io_interrupt = {
+	.name	 = "IO",
+	.handler = do_cio_interrupt,
+};
+
+void __init init_cio_interrupts(void)
+{
+	irq_set_chip_and_handler(IO_INTERRUPT,
+				 &dummy_irq_chip, handle_percpu_irq);
+	setup_irq(IO_INTERRUPT, &io_interrupt);
+	irq_desc_io = irq_to_desc(IO_INTERRUPT);
 }
 
 #ifdef CONFIG_CCW_CONSOLE
@@ -635,7 +635,7 @@ void cio_tsch(struct subchannel *sch)
 		local_bh_disable();
 		irq_enter();
 	}
-	kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
+	kstat_incr_irqs_this_cpu(IO_INTERRUPT, irq_desc_io);
 	if (sch->driver && sch->driver->irq)
 		sch->driver->irq(sch);
 	else
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index d62f5e7..d42f674 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -121,9 +121,6 @@ extern int cio_commit_config(struct subchannel *sch);
 int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
 int cio_tm_intrg(struct subchannel *sch);
 
-void do_adapter_IO(u8 isc);
-void do_IRQ(struct pt_regs *);
-
 /* Use with care. */
 #ifdef CONFIG_CCW_CONSOLE
 extern struct subchannel *cio_probe_console(void);
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 4495e06..23054f8 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1182,7 +1182,7 @@ static ssize_t cmb_enable_store(struct device *dev,
 	int ret;
 	unsigned long val;
 
-	ret = strict_strtoul(buf, 16, &val);
+	ret = kstrtoul(buf, 16, &val);
 	if (ret)
 		return ret;
 
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 1ebe5d3..4eb2a54 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -740,7 +740,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
 	int ret;
 	unsigned long val;
 
-	ret = strict_strtoul(buf, 16, &val);
+	ret = kstrtoul(buf, 16, &val);
 	if (ret)
 		return ret;
 	mutex_lock(&css->mutex);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 1ab5f6c..e4a7ab2 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -564,7 +564,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
 		ret = 0;
 	} else {
 		force = 0;
-		ret = strict_strtoul(buf, 16, &i);
+		ret = kstrtoul(buf, 16, &i);
 	}
 	if (ret)
 		goto out;
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index d1c8025..adef5f5 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -208,7 +208,7 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
 		goto out;
 	}
 
-	rc = strict_strtoul(buf, 16, &i);
+	rc = kstrtoul(buf, 16, &i);
 	if (rc) {
 		rc = -EINVAL;
 		goto out;
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 0163457..db3710f 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1227,19 +1227,9 @@ static struct pci_driver inia100_pci_driver = {
 	.remove		= inia100_remove_one,
 };
 
-static int __init inia100_init(void)
-{
-	return pci_register_driver(&inia100_pci_driver);
-}
-
-static void __exit inia100_exit(void)
-{
-	pci_unregister_driver(&inia100_pci_driver);
-}
+module_pci_driver(inia100_pci_driver);
 
 MODULE_DESCRIPTION("Initio A100U2W SCSI driver");
 MODULE_AUTHOR("Initio Corporation");
 MODULE_LICENSE("Dual BSD/GPL");
 
-module_init(inia100_init);
-module_exit(inia100_exit);
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index f2db5fe..62f00da 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -581,8 +581,10 @@ struct iscsi_kwqe_init1 {
 #define ISCSI_KWQE_INIT1_DELAYED_ACK_ENABLE_SHIFT 4
 #define ISCSI_KWQE_INIT1_KEEP_ALIVE_ENABLE (0x1<<5)
 #define ISCSI_KWQE_INIT1_KEEP_ALIVE_ENABLE_SHIFT 5
-#define ISCSI_KWQE_INIT1_RESERVED1 (0x3<<6)
-#define ISCSI_KWQE_INIT1_RESERVED1_SHIFT 6
+#define ISCSI_KWQE_INIT1_TIME_STAMPS_ENABLE (0x1<<6)
+#define ISCSI_KWQE_INIT1_TIME_STAMPS_ENABLE_SHIFT 6
+#define ISCSI_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define ISCSI_KWQE_INIT1_RESERVED1_SHIFT 7
 	u16 cq_num_wqes;
 #elif defined(__LITTLE_ENDIAN)
 	u16 cq_num_wqes;
@@ -593,8 +595,10 @@ struct iscsi_kwqe_init1 {
 #define ISCSI_KWQE_INIT1_DELAYED_ACK_ENABLE_SHIFT 4
 #define ISCSI_KWQE_INIT1_KEEP_ALIVE_ENABLE (0x1<<5)
 #define ISCSI_KWQE_INIT1_KEEP_ALIVE_ENABLE_SHIFT 5
-#define ISCSI_KWQE_INIT1_RESERVED1 (0x3<<6)
-#define ISCSI_KWQE_INIT1_RESERVED1_SHIFT 6
+#define ISCSI_KWQE_INIT1_TIME_STAMPS_ENABLE (0x1<<6)
+#define ISCSI_KWQE_INIT1_TIME_STAMPS_ENABLE_SHIFT 6
+#define ISCSI_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define ISCSI_KWQE_INIT1_RESERVED1_SHIFT 7
 	u8 cq_log_wqes_per_page;
 #endif
 #if defined(__BIG_ENDIAN)
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 50fef69..3104202 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -172,16 +172,14 @@ void bnx2i_start(void *handle)
 	struct bnx2i_hba *hba = handle;
 	int i = HZ;
 
-	/*
-	 * We should never register devices that don't support iSCSI
-	 * (see bnx2i_init_one), so something is wrong if we try to
-	 * start a iSCSI adapter on hardware with 0 supported iSCSI
-	 * connections
+	/* On some bnx2x devices, it is possible that iSCSI is no
+	 * longer supported after firmware is downloaded.  In that
+	 * case, the iscsi_init_msg will return failure.
 	 */
-	BUG_ON(!hba->cnic->max_iscsi_conn);
 
 	bnx2i_send_fw_iscsi_init_msg(hba);
-	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
+	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) &&
+	       !test_bit(ADAPTER_STATE_INIT_FAILED, &hba->adapter_state) && i--)
 		msleep(BNX2I_INIT_POLL_TIME);
 }
 
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 694e13c..e73445b 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4882,29 +4882,7 @@ static struct pci_driver dc395x_driver = {
 	.remove         = dc395x_remove_one,
 };
 
-
-/**
- * dc395x_module_init - Module initialization function
- *
- * Used by both module and built-in driver to initialise this driver.
- **/
-static int __init dc395x_module_init(void)
-{
-	return pci_register_driver(&dc395x_driver);
-}
-
-
-/**
- * dc395x_module_exit - Module cleanup function.
- **/
-static void __exit dc395x_module_exit(void)
-{
-	pci_unregister_driver(&dc395x_driver);
-}
-
-
-module_init(dc395x_module_init);
-module_exit(dc395x_module_exit);
+module_pci_driver(dc395x_driver);
 
 MODULE_AUTHOR("C.L. Huang / Erich Chen / Kurt Garloff");
 MODULE_DESCRIPTION("SCSI host adapter driver for Tekram TRM-S1040 based adapters: Tekram DC395 and DC315 series");
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 4b0dd8c..bb28062 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -153,18 +153,7 @@ static struct pci_driver dmx3191d_pci_driver = {
 	.remove		= dmx3191d_remove_one,
 };
 
-static int __init dmx3191d_init(void)
-{
-	return pci_register_driver(&dmx3191d_pci_driver);
-}
-
-static void __exit dmx3191d_exit(void)
-{
-	pci_unregister_driver(&dmx3191d_pci_driver);
-}
-
-module_init(dmx3191d_init);
-module_exit(dmx3191d_exit);
+module_pci_driver(dmx3191d_pci_driver);
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Domex DMX3191D SCSI driver");
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 34552bf..55548dc 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -530,7 +530,7 @@ static int esp_need_to_nego_sync(struct esp_target_data *tp)
 static int esp_alloc_lun_tag(struct esp_cmd_entry *ent,
 			     struct esp_lun_data *lp)
 {
-	if (!ent->tag[0]) {
+	if (!ent->orig_tag[0]) {
 		/* Non-tagged, slot already taken?  */
 		if (lp->non_tagged_cmd)
 			return -EBUSY;
@@ -564,9 +564,9 @@ static int esp_alloc_lun_tag(struct esp_cmd_entry *ent,
 			return -EBUSY;
 	}
 
-	BUG_ON(lp->tagged_cmds[ent->tag[1]]);
+	BUG_ON(lp->tagged_cmds[ent->orig_tag[1]]);
 
-	lp->tagged_cmds[ent->tag[1]] = ent;
+	lp->tagged_cmds[ent->orig_tag[1]] = ent;
 	lp->num_tagged++;
 
 	return 0;
@@ -575,9 +575,9 @@ static int esp_alloc_lun_tag(struct esp_cmd_entry *ent,
 static void esp_free_lun_tag(struct esp_cmd_entry *ent,
 			     struct esp_lun_data *lp)
 {
-	if (ent->tag[0]) {
-		BUG_ON(lp->tagged_cmds[ent->tag[1]] != ent);
-		lp->tagged_cmds[ent->tag[1]] = NULL;
+	if (ent->orig_tag[0]) {
+		BUG_ON(lp->tagged_cmds[ent->orig_tag[1]] != ent);
+		lp->tagged_cmds[ent->orig_tag[1]] = NULL;
 		lp->num_tagged--;
 	} else {
 		BUG_ON(lp->non_tagged_cmd != ent);
@@ -667,6 +667,8 @@ static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
 			ent->tag[0] = 0;
 			ent->tag[1] = 0;
 		}
+		ent->orig_tag[0] = ent->tag[0];
+		ent->orig_tag[1] = ent->tag[1];
 
 		if (esp_alloc_lun_tag(ent, lp) < 0)
 			continue;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 28e22ac..cd68805 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -271,6 +271,7 @@ struct esp_cmd_entry {
 #define ESP_CMD_FLAG_AUTOSENSE	0x04 /* Doing automatic REQUEST_SENSE */
 
 	u8			tag[2];
+	u8			orig_tag[2];
 
 	u8			status;
 	u8			message;
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index b6d1f92..c18c681 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -38,7 +38,7 @@
 
 #define DRV_NAME		"fnic"
 #define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
-#define DRV_VERSION		"1.5.0.22"
+#define DRV_VERSION		"1.5.0.23"
 #define PFX			DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 5f09d18..42e15ee 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -642,19 +642,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
 		INIT_WORK(&fnic->event_work, fnic_handle_event);
 		skb_queue_head_init(&fnic->fip_frame_queue);
-		spin_lock_irqsave(&fnic_list_lock, flags);
-		if (!fnic_fip_queue) {
-			fnic_fip_queue =
-				create_singlethread_workqueue("fnic_fip_q");
-			if (!fnic_fip_queue) {
-				spin_unlock_irqrestore(&fnic_list_lock, flags);
-				printk(KERN_ERR PFX "fnic FIP work queue "
-						 "create failed\n");
-				err = -ENOMEM;
-				goto err_out_free_max_pool;
-			}
-		}
-		spin_unlock_irqrestore(&fnic_list_lock, flags);
 		INIT_LIST_HEAD(&fnic->evlist);
 		INIT_LIST_HEAD(&fnic->vlans);
 	} else {
@@ -960,6 +947,13 @@ static int __init fnic_init_module(void)
 	spin_lock_init(&fnic_list_lock);
 	INIT_LIST_HEAD(&fnic_list);
 
+	fnic_fip_queue = create_singlethread_workqueue("fnic_fip_q");
+	if (!fnic_fip_queue) {
+		printk(KERN_ERR PFX "fnic FIP work queue create failed\n");
+		err = -ENOMEM;
+		goto err_create_fip_workq;
+	}
+
 	fnic_fc_transport = fc_attach_transport(&fnic_fc_functions);
 	if (!fnic_fc_transport) {
 		printk(KERN_ERR PFX "fc_attach_transport error\n");
@@ -978,6 +972,8 @@ static int __init fnic_init_module(void)
 err_pci_register:
 	fc_release_transport(fnic_fc_transport);
 err_fc_transport:
+	destroy_workqueue(fnic_fip_queue);
+err_create_fip_workq:
 	destroy_workqueue(fnic_event_queue);
 err_create_fnic_workq:
 	kmem_cache_destroy(fnic_io_req_cache);
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 280d5af..1befc26 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2995,19 +2995,8 @@ static struct pci_driver initio_pci_driver = {
 	.remove		= initio_remove_one,
 };
 
-static int __init initio_init_driver(void)
-{
-	return pci_register_driver(&initio_pci_driver);
-}
-
-static void __exit initio_exit_driver(void)
-{
-	pci_unregister_driver(&initio_pci_driver);
-}
+module_pci_driver(initio_pci_driver);
 
 MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
 MODULE_AUTHOR("Initio Corporation");
 MODULE_LICENSE("GPL");
-
-module_init(initio_init_driver);
-module_exit(initio_exit_driver);
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 0177295..1f0ca68 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -3547,11 +3547,21 @@ static int megasas_init_fw(struct megasas_instance *instance)
 		break;
 	}
 
-	/*
-	 * We expect the FW state to be READY
-	 */
-	if (megasas_transition_to_ready(instance, 0))
-		goto fail_ready_state;
+	if (megasas_transition_to_ready(instance, 0)) {
+		atomic_set(&instance->fw_reset_no_pci_access, 1);
+		instance->instancet->adp_reset
+			(instance, instance->reg_set);
+		atomic_set(&instance->fw_reset_no_pci_access, 0);
+		dev_info(&instance->pdev->dev,
+			"megasas: FW restarted successfully from %s!\n",
+			__func__);
+
+		/*waitting for about 30 second before retry*/
+		ssleep(30);
+
+		if (megasas_transition_to_ready(instance, 0))
+			goto fail_ready_state;
+	}
 
 	/*
 	 * MSI-X host index 0 is common for all adapter.
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index c3601b5..d0b6a03 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -2735,22 +2735,4 @@ static struct pci_driver mvumi_pci_driver = {
 #endif
 };
 
-/**
- * mvumi_init - Driver load entry point
- */
-static int __init mvumi_init(void)
-{
-	return pci_register_driver(&mvumi_pci_driver);
-}
-
-/**
- * mvumi_exit - Driver unload entry point
- */
-static void __exit mvumi_exit(void)
-{
-
-	pci_unregister_driver(&mvumi_pci_driver);
-}
-
-module_init(mvumi_init);
-module_exit(mvumi_exit);
+module_pci_driver(mvumi_pci_driver);
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 9d86947..e1d9a4c 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -107,6 +107,7 @@ static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
 						   class_dev);
 	return sprintf(buf, "%s\n", ould->odi.osdname);
 }
+static DEVICE_ATTR_RO(osdname);
 
 static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
 			    char *buf)
@@ -117,17 +118,19 @@ static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
 	memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
 	return ould->odi.systemid_len;
 }
+static DEVICE_ATTR_RO(systemid);
 
-static struct device_attribute osd_uld_attrs[] = {
-	__ATTR(osdname, S_IRUGO, osdname_show, NULL),
-	__ATTR(systemid, S_IRUGO, systemid_show, NULL),
-	__ATTR_NULL,
+static struct attribute *osd_uld_attrs[] = {
+	&dev_attr_osdname.attr,
+	&dev_attr_systemid.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(osd_uld);
 
 static struct class osd_uld_class = {
 	.owner		= THIS_MODULE,
 	.name		= "scsi_osd",
-	.dev_attrs	= osd_uld_attrs,
+	.dev_groups	= osd_uld_groups,
 };
 
 /*
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 3b1ea34..eaa808e 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1031,6 +1031,9 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 {
 	int i, result;
 
+	if (sdev->skip_vpd_pages)
+		goto fail;
+
 	/* Ask for all the pages supported by this device */
 	result = scsi_vpd_inquiry(sdev, buf, 0, buf_len);
 	if (result)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 86fcf2c..b58e8f8 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -132,8 +132,8 @@ static const char *sd_cache_types[] = {
 };
 
 static ssize_t
-sd_store_cache_type(struct device *dev, struct device_attribute *attr,
-		    const char *buf, size_t count)
+cache_type_store(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
 {
 	int i, ct = -1, rcd, wce, sp;
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
@@ -199,8 +199,18 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-sd_store_manage_start_stop(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
+manage_start_stop_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+	struct scsi_device *sdp = sdkp->device;
+
+	return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+}
+
+static ssize_t
+manage_start_stop_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	struct scsi_device *sdp = sdkp->device;
@@ -212,10 +222,19 @@ sd_store_manage_start_stop(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
+static DEVICE_ATTR_RW(manage_start_stop);
 
 static ssize_t
-sd_store_allow_restart(struct device *dev, struct device_attribute *attr,
-		       const char *buf, size_t count)
+allow_restart_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+	return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
+}
+
+static ssize_t
+allow_restart_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	struct scsi_device *sdp = sdkp->device;
@@ -230,47 +249,30 @@ sd_store_allow_restart(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
+static DEVICE_ATTR_RW(allow_restart);
 
 static ssize_t
-sd_show_cache_type(struct device *dev, struct device_attribute *attr,
-		   char *buf)
+cache_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	int ct = sdkp->RCD + 2*sdkp->WCE;
 
 	return snprintf(buf, 40, "%s\n", sd_cache_types[ct]);
 }
+static DEVICE_ATTR_RW(cache_type);
 
 static ssize_t
-sd_show_fua(struct device *dev, struct device_attribute *attr, char *buf)
+FUA_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
 	return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
 }
+static DEVICE_ATTR_RO(FUA);
 
 static ssize_t
-sd_show_manage_start_stop(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	struct scsi_disk *sdkp = to_scsi_disk(dev);
-	struct scsi_device *sdp = sdkp->device;
-
-	return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
-}
-
-static ssize_t
-sd_show_allow_restart(struct device *dev, struct device_attribute *attr,
-		      char *buf)
-{
-	struct scsi_disk *sdkp = to_scsi_disk(dev);
-
-	return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
-}
-
-static ssize_t
-sd_show_protection_type(struct device *dev, struct device_attribute *attr,
-			char *buf)
+protection_type_show(struct device *dev, struct device_attribute *attr,
+		     char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
@@ -278,8 +280,8 @@ sd_show_protection_type(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-sd_store_protection_type(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count)
+protection_type_store(struct device *dev, struct device_attribute *attr,
+		      const char *buf, size_t count)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	unsigned int val;
@@ -298,10 +300,11 @@ sd_store_protection_type(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
+static DEVICE_ATTR_RW(protection_type);
 
 static ssize_t
-sd_show_protection_mode(struct device *dev, struct device_attribute *attr,
-			char *buf)
+protection_mode_show(struct device *dev, struct device_attribute *attr,
+		     char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	struct scsi_device *sdp = sdkp->device;
@@ -320,24 +323,26 @@ sd_show_protection_mode(struct device *dev, struct device_attribute *attr,
 
 	return snprintf(buf, 20, "%s%u\n", dix ? "dix" : "dif", dif);
 }
+static DEVICE_ATTR_RO(protection_mode);
 
 static ssize_t
-sd_show_app_tag_own(struct device *dev, struct device_attribute *attr,
-		    char *buf)
+app_tag_own_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
 	return snprintf(buf, 20, "%u\n", sdkp->ATO);
 }
+static DEVICE_ATTR_RO(app_tag_own);
 
 static ssize_t
-sd_show_thin_provisioning(struct device *dev, struct device_attribute *attr,
-			  char *buf)
+thin_provisioning_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
 	return snprintf(buf, 20, "%u\n", sdkp->lbpme);
 }
+static DEVICE_ATTR_RO(thin_provisioning);
 
 static const char *lbp_mode[] = {
 	[SD_LBP_FULL]		= "full",
@@ -349,8 +354,8 @@ static const char *lbp_mode[] = {
 };
 
 static ssize_t
-sd_show_provisioning_mode(struct device *dev, struct device_attribute *attr,
-			  char *buf)
+provisioning_mode_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
@@ -358,8 +363,8 @@ sd_show_provisioning_mode(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-sd_store_provisioning_mode(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
+provisioning_mode_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	struct scsi_device *sdp = sdkp->device;
@@ -385,10 +390,11 @@ sd_store_provisioning_mode(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
+static DEVICE_ATTR_RW(provisioning_mode);
 
 static ssize_t
-sd_show_max_medium_access_timeouts(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+max_medium_access_timeouts_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
@@ -396,9 +402,9 @@ sd_show_max_medium_access_timeouts(struct device *dev,
 }
 
 static ssize_t
-sd_store_max_medium_access_timeouts(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
+max_medium_access_timeouts_store(struct device *dev,
+				 struct device_attribute *attr, const char *buf,
+				 size_t count)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	int err;
@@ -410,10 +416,11 @@ sd_store_max_medium_access_timeouts(struct device *dev,
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(max_medium_access_timeouts);
 
 static ssize_t
-sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
-			  char *buf)
+max_write_same_blocks_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
@@ -421,8 +428,8 @@ sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
+max_write_same_blocks_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 	struct scsi_device *sdp = sdkp->device;
@@ -451,35 +458,29 @@ sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
 
 	return count;
 }
-
-static struct device_attribute sd_disk_attrs[] = {
-	__ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
-	       sd_store_cache_type),
-	__ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
-	__ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart,
-	       sd_store_allow_restart),
-	__ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop,
-	       sd_store_manage_start_stop),
-	__ATTR(protection_type, S_IRUGO|S_IWUSR, sd_show_protection_type,
-	       sd_store_protection_type),
-	__ATTR(protection_mode, S_IRUGO, sd_show_protection_mode, NULL),
-	__ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
-	__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
-	__ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
-	       sd_store_provisioning_mode),
-	__ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
-	       sd_show_write_same_blocks, sd_store_write_same_blocks),
-	__ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
-	       sd_show_max_medium_access_timeouts,
-	       sd_store_max_medium_access_timeouts),
-	__ATTR_NULL,
+static DEVICE_ATTR_RW(max_write_same_blocks);
+
+static struct attribute *sd_disk_attrs[] = {
+	&dev_attr_cache_type.attr,
+	&dev_attr_FUA.attr,
+	&dev_attr_allow_restart.attr,
+	&dev_attr_manage_start_stop.attr,
+	&dev_attr_protection_type.attr,
+	&dev_attr_protection_mode.attr,
+	&dev_attr_app_tag_own.attr,
+	&dev_attr_thin_provisioning.attr,
+	&dev_attr_provisioning_mode.attr,
+	&dev_attr_max_write_same_blocks.attr,
+	&dev_attr_max_medium_access_timeouts.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(sd_disk);
 
 static struct class sd_disk_class = {
 	.name		= "scsi_disk",
 	.owner		= THIS_MODULE,
 	.dev_release	= scsi_disk_release,
-	.dev_attrs	= sd_disk_attrs,
+	.dev_groups	= sd_disk_groups,
 };
 
 static const struct dev_pm_ops sd_pm_ops = {
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 2a32036..ff44b3c 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -82,7 +82,7 @@ static int try_rdio = 1;
 static int try_wdio = 1;
 
 static struct class st_sysfs_class;
-static struct device_attribute st_dev_attrs[];
+static const struct attribute_group *st_dev_groups[];
 
 MODULE_AUTHOR("Kai Makisara");
 MODULE_DESCRIPTION("SCSI tape (st) driver");
@@ -4274,7 +4274,7 @@ static void scsi_tape_release(struct kref *kref)
 
 static struct class st_sysfs_class = {
 	.name = "scsi_tape",
-	.dev_attrs = st_dev_attrs,
+	.dev_groups = st_dev_groups,
 };
 
 static int __init init_st(void)
@@ -4408,6 +4408,7 @@ defined_show(struct device *dev, struct device_attribute *attr, char *buf)
 	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
 	return l;
 }
+static DEVICE_ATTR_RO(defined);
 
 static ssize_t
 default_blksize_show(struct device *dev, struct device_attribute *attr,
@@ -4419,7 +4420,7 @@ default_blksize_show(struct device *dev, struct device_attribute *attr,
 	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
 	return l;
 }
-
+static DEVICE_ATTR_RO(default_blksize);
 
 static ssize_t
 default_density_show(struct device *dev, struct device_attribute *attr,
@@ -4433,6 +4434,7 @@ default_density_show(struct device *dev, struct device_attribute *attr,
 	l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density);
 	return l;
 }
+static DEVICE_ATTR_RO(default_density);
 
 static ssize_t
 default_compression_show(struct device *dev, struct device_attribute *attr,
@@ -4444,6 +4446,7 @@ default_compression_show(struct device *dev, struct device_attribute *attr,
 	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
 	return l;
 }
+static DEVICE_ATTR_RO(default_compression);
 
 static ssize_t
 options_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -4472,15 +4475,17 @@ options_show(struct device *dev, struct device_attribute *attr, char *buf)
 	l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
 	return l;
 }
-
-static struct device_attribute st_dev_attrs[] = {
-	__ATTR_RO(defined),
-	__ATTR_RO(default_blksize),
-	__ATTR_RO(default_density),
-	__ATTR_RO(default_compression),
-	__ATTR_RO(options),
-	__ATTR_NULL,
+static DEVICE_ATTR_RO(options);
+
+static struct attribute *st_dev_attrs[] = {
+	&dev_attr_defined.attr,
+	&dev_attr_default_blksize.attr,
+	&dev_attr_default_density.attr,
+	&dev_attr_default_compression.attr,
+	&dev_attr_options.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(st_dev);
 
 /* The following functions may be useful for a larger audience. */
 static int sgl_map_user_pages(struct st_buffer *STbp,
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 83ec1aa..1a28f56 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1879,7 +1879,6 @@ static void __exit storvsc_drv_exit(void)
 }
 
 MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver");
 module_init(storvsc_drv_init);
 module_exit(storvsc_drv_exit);
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 2168258..74b88ef 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -751,7 +751,7 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
 
 		vscsi->affinity_hint_set = true;
 	} else {
-		for (i = 0; i < vscsi->num_queues - VIRTIO_SCSI_VQ_BASE; i++)
+		for (i = 0; i < vscsi->num_queues; i++)
 			virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1);
 
 		vscsi->affinity_hint_set = false;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 89cbbab..733d3d3 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -70,14 +70,14 @@ config SPI_ATH79
 
 config SPI_ATMEL
 	tristate "Atmel SPI Controller"
-	depends on (ARCH_AT91 || AVR32)
+	depends on (ARCH_AT91 || AVR32 || COMPILE_TEST)
 	help
 	  This selects a driver for the Atmel SPI Controller, present on
 	  many AT32 (AVR32) and AT91 (ARM) chips.
 
 config SPI_BCM2835
 	tristate "BCM2835 SPI controller"
-	depends on ARCH_BCM2835
+	depends on ARCH_BCM2835 || COMPILE_TEST
 	help
 	  This selects a driver for the Broadcom BCM2835 SPI master.
 
@@ -88,10 +88,17 @@ config SPI_BCM2835
 
 config SPI_BFIN5XX
 	tristate "SPI controller driver for ADI Blackfin5xx"
-	depends on BLACKFIN
+	depends on BLACKFIN && !BF60x
 	help
 	  This is the SPI controller master driver for Blackfin 5xx processor.
 
+config SPI_BFIN_V3
+	tristate "SPI controller v3 for Blackfin"
+	depends on BF60x
+	help
+	  This is the SPI controller v3 master driver
+	  found on Blackfin 60x processor.
+
 config SPI_BFIN_SPORT
 	tristate "SPI bus via Blackfin SPORT"
 	depends on BLACKFIN
@@ -151,7 +158,7 @@ config SPI_COLDFIRE_QSPI
 
 config SPI_DAVINCI
 	tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
-	depends on ARCH_DAVINCI
+	depends on ARCH_DAVINCI || ARCH_KEYSTONE
 	select SPI_BITBANG
 	select TI_EDMA
 	help
@@ -159,7 +166,7 @@ config SPI_DAVINCI
 
 config SPI_EP93XX
 	tristate "Cirrus Logic EP93xx SPI controller"
-	depends on ARCH_EP93XX
+	depends on ARCH_EP93XX || COMPILE_TEST
 	help
 	  This enables using the Cirrus EP93xx SPI controller in master
 	  mode.
@@ -191,7 +198,7 @@ config SPI_GPIO
 
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
-	depends on ARCH_MXC
+	depends on ARCH_MXC || COMPILE_TEST
 	select SPI_BITBANG
 	default m if IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -280,20 +287,20 @@ config SPI_OMAP_UWIRE
 
 config SPI_OMAP24XX
 	tristate "McSPI driver for OMAP"
-	depends on ARCH_OMAP2PLUS
+	depends on ARCH_OMAP2PLUS || COMPILE_TEST
 	help
 	  SPI master controller for OMAP24XX and later Multichannel SPI
 	  (McSPI) modules.
 
 config SPI_OMAP_100K
 	tristate "OMAP SPI 100K"
-	depends on ARCH_OMAP850 || ARCH_OMAP730
+	depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST
 	help
 	  OMAP SPI 100K master controller for omap7xx boards.
 
 config SPI_ORION
 	tristate "Orion SPI master"
-	depends on PLAT_ORION
+	depends on PLAT_ORION || COMPILE_TEST
 	help
 	  This enables using the SPI master controller on the Orion chips.
 
@@ -341,7 +348,7 @@ config SPI_PXA2XX_PCI
 
 config SPI_RSPI
 	tristate "Renesas RSPI controller"
-	depends on SUPERH
+	depends on SUPERH && SH_DMAE_BASE
 	help
 	  SPI driver for Renesas RSPI blocks.
 
@@ -385,7 +392,7 @@ config SPI_SH_MSIOF
 
 config SPI_SH
 	tristate "SuperH SPI controller"
-	depends on SUPERH
+	depends on SUPERH || COMPILE_TEST
 	help
 	  SPI driver for SuperH SPI blocks.
 
@@ -398,13 +405,13 @@ config SPI_SH_SCI
 
 config SPI_SH_HSPI
 	tristate "SuperH HSPI controller"
-	depends on ARCH_SHMOBILE
+	depends on ARCH_SHMOBILE || COMPILE_TEST
 	help
 	  SPI driver for SuperH HSPI blocks.
 
 config SPI_SIRF
 	tristate "CSR SiRFprimaII SPI controller"
-	depends on ARCH_SIRF
+	depends on SIRF_DMA
 	select SPI_BITBANG
 	help
 	  SPI driver for CSR SiRFprimaII SoCs
@@ -418,7 +425,7 @@ config SPI_MXS
 
 config SPI_TEGRA114
 	tristate "NVIDIA Tegra114 SPI Controller"
-	depends on ARCH_TEGRA && TEGRA20_APB_DMA
+	depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
 	help
 	  SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
 	  is different than the older SoCs SPI controller and also register interface
@@ -426,7 +433,7 @@ config SPI_TEGRA114
 
 config SPI_TEGRA20_SFLASH
 	tristate "Nvidia Tegra20 Serial flash Controller"
-	depends on ARCH_TEGRA
+	depends on ARCH_TEGRA || COMPILE_TEST
 	help
 	  SPI driver for Nvidia Tegra20 Serial flash Controller interface.
 	  The main usecase of this controller is to use spi flash as boot
@@ -434,7 +441,7 @@ config SPI_TEGRA20_SFLASH
 
 config SPI_TEGRA20_SLINK
 	tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
-	depends on ARCH_TEGRA && TEGRA20_APB_DMA
+	depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
 	help
 	  SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
 
@@ -457,7 +464,7 @@ config SPI_TOPCLIFF_PCH
 
 config SPI_TXX9
 	tristate "Toshiba TXx9 SPI controller"
-	depends on GPIOLIB && CPU_TX49XX
+	depends on GPIOLIB && (CPU_TX49XX || COMPILE_TEST)
 	help
 	  SPI driver for Toshiba TXx9 MIPS SoCs
 
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 33f9c09..7c41702 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550)		+= spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)		+= spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)		+= spi-bcm63xx.o
 obj-$(CONFIG_SPI_BFIN5XX)		+= spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o
 obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.o
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index ea1ec00..fd7cc56 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -360,12 +360,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 		gpio_set_value(asd->npcs_pin, !active);
 }
 
-static void atmel_spi_lock(struct atmel_spi *as)
+static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
 {
 	spin_lock_irqsave(&as->lock, as->flags);
 }
 
-static void atmel_spi_unlock(struct atmel_spi *as)
+static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
 {
 	spin_unlock_irqrestore(&as->lock, as->flags);
 }
@@ -629,9 +629,9 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 		goto err_dma;
 
 	dev_dbg(master->dev.parent,
-		"  start dma xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-		xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-		xfer->rx_buf, xfer->rx_dma);
+		"  start dma xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+		xfer, xfer->len, xfer->tx_buf, (unsigned long long)xfer->tx_dma,
+		xfer->rx_buf, (unsigned long long)xfer->rx_dma);
 
 	/* Enable relevant interrupts */
 	spi_writel(as, IER, SPI_BIT(OVRES));
@@ -732,9 +732,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
 		spi_writel(as, TCR, len);
 
 		dev_dbg(&msg->spi->dev,
-			"  start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-			xfer->rx_buf, xfer->rx_dma);
+			"  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+			xfer, xfer->len, xfer->tx_buf,
+			(unsigned long long)xfer->tx_dma, xfer->rx_buf,
+			(unsigned long long)xfer->rx_dma);
 	} else {
 		xfer = as->next_transfer;
 		remaining = as->next_remaining_bytes;
@@ -771,9 +772,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
 		spi_writel(as, TNCR, len);
 
 		dev_dbg(&msg->spi->dev,
-			"  next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-			xfer->rx_buf, xfer->rx_dma);
+			"  next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+			xfer, xfer->len, xfer->tx_buf,
+			(unsigned long long)xfer->tx_dma, xfer->rx_buf,
+			(unsigned long long)xfer->rx_dma);
 		ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
 	} else {
 		spi_writel(as, RNCR, 0);
@@ -1579,7 +1581,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
 		goto out_unmap_regs;
 
 	/* Initialize the hardware */
-	clk_enable(clk);
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		goto out_unmap_regs;
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
 	if (as->caps.has_wdrbt) {
@@ -1609,7 +1613,7 @@ out_free_dma:
 
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 	free_irq(irq, master);
 out_unmap_regs:
 	iounmap(as->regs);
@@ -1661,7 +1665,7 @@ static int atmel_spi_remove(struct platform_device *pdev)
 	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
 			as->buffer_dma);
 
-	clk_disable(as->clk);
+	clk_disable_unprepare(as->clk);
 	clk_put(as->clk);
 	free_irq(as->irq, master);
 	iounmap(as->regs);
@@ -1678,7 +1682,7 @@ static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
 	struct spi_master	*master = platform_get_drvdata(pdev);
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 
-	clk_disable(as->clk);
+	clk_disable_unprepare(as->clk);
 	return 0;
 }
 
@@ -1687,7 +1691,7 @@ static int atmel_spi_resume(struct platform_device *pdev)
 	struct spi_master	*master = platform_get_drvdata(pdev);
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 
-	clk_enable(as->clk);
+	return clk_prepare_enable(as->clk);
 	return 0;
 }
 
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index a4185e4..7de617a 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -314,7 +314,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	master->mode_bits = BCM2835_SPI_MODE_BITS;
-	master->bits_per_word_mask = BIT(8 - 1);
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
 	master->bus_num = -1;
 	master->num_chipselect = 3;
 	master->transfer_one_message = bcm2835_spi_transfer_one;
@@ -325,12 +325,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 	init_completion(&bs->done);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "could not get memory resource\n");
-		err = -ENODEV;
-		goto out_master_put;
-	}
-
 	bs->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(bs->regs)) {
 		err = PTR_ERR(bs->regs);
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 9fd7a39..4ac028d 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -231,24 +231,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
 	return 0;
 }
 
-static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
-{
-	struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
-	pm_runtime_get_sync(&bs->pdev->dev);
-
-	return 0;
-}
-
-static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
-{
-	struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
-	pm_runtime_put(&bs->pdev->dev);
-
-	return 0;
-}
-
 static int bcm63xx_spi_transfer_one(struct spi_master *master,
 					struct spi_message *m)
 {
@@ -412,11 +394,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 
 	master->bus_num = pdata->bus_num;
 	master->num_chipselect = pdata->num_chipselect;
-	master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
-	master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
 	master->transfer_one_message = bcm63xx_spi_transfer_one;
 	master->mode_bits = MODEBITS;
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
+	master->auto_runtime_pm = true;
 	bs->msg_type_shift = pdata->msg_type_shift;
 	bs->msg_ctl_width = pdata->msg_ctl_width;
 	bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
new file mode 100644
index 0000000..603d7e9
--- /dev/null
+++ b/drivers/spi/spi-bfin-v3.c
@@ -0,0 +1,973 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2013 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+
+#include <asm/bfin_spi3.h>
+#include <asm/cacheflush.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+enum bfin_spi_state {
+	START_STATE,
+	RUNNING_STATE,
+	DONE_STATE,
+	ERROR_STATE
+};
+
+struct bfin_spi_master;
+
+struct bfin_spi_transfer_ops {
+	void (*write) (struct bfin_spi_master *);
+	void (*read) (struct bfin_spi_master *);
+	void (*duplex) (struct bfin_spi_master *);
+};
+
+/* runtime info for spi master */
+struct bfin_spi_master {
+	/* SPI framework hookup */
+	struct spi_master *master;
+
+	/* Regs base of SPI controller */
+	struct bfin_spi_regs __iomem *regs;
+
+	/* Pin request list */
+	u16 *pin_req;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message *cur_msg;
+	struct spi_transfer *cur_transfer;
+	struct bfin_spi_device *cur_chip;
+	unsigned transfer_len;
+
+	/* transfer buffer */
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+
+	/* dma info */
+	unsigned int tx_dma;
+	unsigned int rx_dma;
+	dma_addr_t tx_dma_addr;
+	dma_addr_t rx_dma_addr;
+	unsigned long dummy_buffer; /* used in unidirectional transfer */
+	unsigned long tx_dma_size;
+	unsigned long rx_dma_size;
+	int tx_num;
+	int rx_num;
+
+	/* store register value for suspend/resume */
+	u32 control;
+	u32 ssel;
+
+	unsigned long sclk;
+	enum bfin_spi_state state;
+
+	const struct bfin_spi_transfer_ops *ops;
+};
+
+struct bfin_spi_device {
+	u32 control;
+	u32 clock;
+	u32 ssel;
+
+	u8 cs;
+	u16 cs_chg_udelay; /* Some devices require > 255usec delay */
+	u32 cs_gpio;
+	u32 tx_dummy_val; /* tx value for rx only transfer */
+	bool enable_dma;
+	const struct bfin_spi_transfer_ops *ops;
+};
+
+static void bfin_spi_enable(struct bfin_spi_master *drv_data)
+{
+	bfin_write_or(&drv_data->regs->control, SPI_CTL_EN);
+}
+
+static void bfin_spi_disable(struct bfin_spi_master *drv_data)
+{
+	bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN);
+}
+
+/* Caculate the SPI_CLOCK register value based on input HZ */
+static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)
+{
+	u32 spi_clock = sclk / speed_hz;
+
+	if (spi_clock)
+		spi_clock--;
+	return spi_clock;
+}
+
+static int bfin_spi_flush(struct bfin_spi_master *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	/* wait for stop and clear stat */
+	while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)
+		cpu_relax();
+
+	bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+
+	return limit;
+}
+
+/* Chip select operation functions for cs_change flag */
+static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip)
+{
+	if (likely(chip->cs < MAX_CTRL_CS))
+		bfin_write_and(&drv_data->regs->ssel, ~chip->ssel);
+	else
+		gpio_set_value(chip->cs_gpio, 0);
+}
+
+static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data,
+				struct bfin_spi_device *chip)
+{
+	if (likely(chip->cs < MAX_CTRL_CS))
+		bfin_write_or(&drv_data->regs->ssel, chip->ssel);
+	else
+		gpio_set_value(chip->cs_gpio, 1);
+
+	/* Move delay here for consistency */
+	if (chip->cs_chg_udelay)
+		udelay(chip->cs_chg_udelay);
+}
+
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data,
+					struct bfin_spi_device *chip)
+{
+	if (chip->cs < MAX_CTRL_CS)
+		bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8);
+}
+
+static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data,
+					struct bfin_spi_device *chip)
+{
+	if (chip->cs < MAX_CTRL_CS)
+		bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8));
+}
+
+/* stop controller and re-config current chip*/
+static void bfin_spi_restore_state(struct bfin_spi_master *drv_data)
+{
+	struct bfin_spi_device *chip = drv_data->cur_chip;
+
+	/* Clear status and disable clock */
+	bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+	bfin_write(&drv_data->regs->rx_control, 0x0);
+	bfin_write(&drv_data->regs->tx_control, 0x0);
+	bfin_spi_disable(drv_data);
+
+	SSYNC();
+
+	/* Load the registers */
+	bfin_write(&drv_data->regs->control, chip->control);
+	bfin_write(&drv_data->regs->clock, chip->clock);
+
+	bfin_spi_enable(drv_data);
+	drv_data->tx_num = drv_data->rx_num = 0;
+	/* we always choose tx transfer initiate */
+	bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN);
+	bfin_write(&drv_data->regs->tx_control,
+			SPI_TXCTL_TEN | SPI_TXCTL_TTI);
+	bfin_spi_cs_active(drv_data, chip);
+}
+
+/* discard invalid rx data and empty rfifo */
+static inline void dummy_read(struct bfin_spi_master *drv_data)
+{
+	while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE))
+		bfin_read(&drv_data->regs->rfifo);
+}
+
+static void bfin_spi_u8_write(struct bfin_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		bfin_read(&drv_data->regs->rfifo);
+	}
+}
+
+static void bfin_spi_u8_read(struct bfin_spi_master *drv_data)
+{
+	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tfifo, tx_val);
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
+	}
+}
+
+static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
+	}
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
+	.write  = bfin_spi_u8_write,
+	.read   = bfin_spi_u8_read,
+	.duplex = bfin_spi_u8_duplex,
+};
+
+static void bfin_spi_u16_write(struct bfin_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
+		drv_data->tx += 2;
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		bfin_read(&drv_data->regs->rfifo);
+	}
+}
+
+static void bfin_spi_u16_read(struct bfin_spi_master *drv_data)
+{
+	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tfifo, tx_val);
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+		drv_data->rx += 2;
+	}
+}
+
+static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
+		drv_data->tx += 2;
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+		drv_data->rx += 2;
+	}
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
+	.write  = bfin_spi_u16_write,
+	.read   = bfin_spi_u16_read,
+	.duplex = bfin_spi_u16_duplex,
+};
+
+static void bfin_spi_u32_write(struct bfin_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
+		drv_data->tx += 4;
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		bfin_read(&drv_data->regs->rfifo);
+	}
+}
+
+static void bfin_spi_u32_read(struct bfin_spi_master *drv_data)
+{
+	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tfifo, tx_val);
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+		drv_data->rx += 4;
+	}
+}
+
+static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
+		drv_data->tx += 4;
+		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+		drv_data->rx += 4;
+	}
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = {
+	.write  = bfin_spi_u32_write,
+	.read   = bfin_spi_u32_read,
+	.duplex = bfin_spi_u32_duplex,
+};
+
+
+/* test if there is more transfer to be done */
+static void bfin_spi_next_transfer(struct bfin_spi_master *drv)
+{
+	struct spi_message *msg = drv->cur_msg;
+	struct spi_transfer *t = drv->cur_transfer;
+
+	/* Move to next transfer */
+	if (t->transfer_list.next != &msg->transfers) {
+		drv->cur_transfer = list_entry(t->transfer_list.next,
+			       struct spi_transfer, transfer_list);
+		drv->state = RUNNING_STATE;
+	} else {
+		drv->state = DONE_STATE;
+		drv->cur_transfer = NULL;
+	}
+}
+
+static void bfin_spi_giveback(struct bfin_spi_master *drv_data)
+{
+	struct bfin_spi_device *chip = drv_data->cur_chip;
+
+	bfin_spi_cs_deactive(drv_data, chip);
+	spi_finalize_current_message(drv_data->master);
+}
+
+static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)
+{
+	struct spi_transfer *t = drv->cur_transfer;
+	u32 cr, cr_width;
+
+	if (t->tx_buf) {
+		drv->tx = (void *)t->tx_buf;
+		drv->tx_end = drv->tx + t->len;
+	} else {
+		drv->tx = NULL;
+	}
+
+	if (t->rx_buf) {
+		drv->rx = t->rx_buf;
+		drv->rx_end = drv->rx + t->len;
+	} else {
+		drv->rx = NULL;
+	}
+
+	drv->transfer_len = t->len;
+
+	/* bits per word setup */
+	switch (t->bits_per_word) {
+	case 8:
+		cr_width = SPI_CTL_SIZE08;
+		drv->ops = &bfin_bfin_spi_transfer_ops_u8;
+		break;
+	case 16:
+		cr_width = SPI_CTL_SIZE16;
+		drv->ops = &bfin_bfin_spi_transfer_ops_u16;
+		break;
+	case 32:
+		cr_width = SPI_CTL_SIZE32;
+		drv->ops = &bfin_bfin_spi_transfer_ops_u32;
+		break;
+	default:
+		return -EINVAL;
+	}
+	cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE;
+	cr |= cr_width;
+	bfin_write(&drv->regs->control, cr);
+
+	/* speed setup */
+	bfin_write(&drv->regs->clock,
+			hz_to_spi_clock(drv->sclk, t->speed_hz));
+	return 0;
+}
+
+static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)
+{
+	struct spi_transfer *t = drv_data->cur_transfer;
+	struct spi_message *msg = drv_data->cur_msg;
+	struct bfin_spi_device *chip = drv_data->cur_chip;
+	u32 dma_config;
+	unsigned long word_count, word_size;
+	void *tx_buf, *rx_buf;
+
+	switch (t->bits_per_word) {
+	case 8:
+		dma_config = WDSIZE_8 | PSIZE_8;
+		word_count = drv_data->transfer_len;
+		word_size = 1;
+		break;
+	case 16:
+		dma_config = WDSIZE_16 | PSIZE_16;
+		word_count = drv_data->transfer_len / 2;
+		word_size = 2;
+		break;
+	default:
+		dma_config = WDSIZE_32 | PSIZE_32;
+		word_count = drv_data->transfer_len / 4;
+		word_size = 4;
+		break;
+	}
+
+	if (!drv_data->rx) {
+		tx_buf = drv_data->tx;
+		rx_buf = &drv_data->dummy_buffer;
+		drv_data->tx_dma_size = drv_data->transfer_len;
+		drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer);
+		set_dma_x_modify(drv_data->tx_dma, word_size);
+		set_dma_x_modify(drv_data->rx_dma, 0);
+	} else if (!drv_data->tx) {
+		drv_data->dummy_buffer = chip->tx_dummy_val;
+		tx_buf = &drv_data->dummy_buffer;
+		rx_buf = drv_data->rx;
+		drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer);
+		drv_data->rx_dma_size = drv_data->transfer_len;
+		set_dma_x_modify(drv_data->tx_dma, 0);
+		set_dma_x_modify(drv_data->rx_dma, word_size);
+	} else {
+		tx_buf = drv_data->tx;
+		rx_buf = drv_data->rx;
+		drv_data->tx_dma_size = drv_data->rx_dma_size
+					= drv_data->transfer_len;
+		set_dma_x_modify(drv_data->tx_dma, word_size);
+		set_dma_x_modify(drv_data->rx_dma, word_size);
+	}
+
+	drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev,
+				(void *)tx_buf,
+				drv_data->tx_dma_size,
+				DMA_TO_DEVICE);
+	if (dma_mapping_error(&msg->spi->dev,
+				drv_data->tx_dma_addr))
+		return -ENOMEM;
+
+	drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev,
+				(void *)rx_buf,
+				drv_data->rx_dma_size,
+				DMA_FROM_DEVICE);
+	if (dma_mapping_error(&msg->spi->dev,
+				drv_data->rx_dma_addr)) {
+		dma_unmap_single(&msg->spi->dev,
+				drv_data->tx_dma_addr,
+				drv_data->tx_dma_size,
+				DMA_TO_DEVICE);
+		return -ENOMEM;
+	}
+
+	dummy_read(drv_data);
+	set_dma_x_count(drv_data->tx_dma, word_count);
+	set_dma_x_count(drv_data->rx_dma, word_count);
+	set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr);
+	set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr);
+	dma_config |= DMAFLOW_STOP | RESTART | DI_EN;
+	set_dma_config(drv_data->tx_dma, dma_config);
+	set_dma_config(drv_data->rx_dma, dma_config | WNR);
+	enable_dma(drv_data->tx_dma);
+	enable_dma(drv_data->rx_dma);
+	SSYNC();
+
+	bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE);
+	SSYNC();
+	bfin_write(&drv_data->regs->tx_control,
+			SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF);
+
+	return 0;
+}
+
+static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+
+	if (!drv_data->rx) {
+		/* write only half duplex */
+		drv_data->ops->write(drv_data);
+		if (drv_data->tx != drv_data->tx_end)
+			return -EIO;
+	} else if (!drv_data->tx) {
+		/* read only half duplex */
+		drv_data->ops->read(drv_data);
+		if (drv_data->rx != drv_data->rx_end)
+			return -EIO;
+	} else {
+		/* full duplex mode */
+		drv_data->ops->duplex(drv_data);
+		if (drv_data->tx != drv_data->tx_end)
+			return -EIO;
+	}
+
+	if (!bfin_spi_flush(drv_data))
+		return -EIO;
+	msg->actual_length += drv_data->transfer_len;
+	tasklet_schedule(&drv_data->pump_transfers);
+	return 0;
+}
+
+static void bfin_spi_pump_transfers(unsigned long data)
+{
+	struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data;
+	struct spi_message *msg = NULL;
+	struct spi_transfer *t = NULL;
+	struct bfin_spi_device *chip = NULL;
+	int ret;
+
+	/* Get current state information */
+	msg = drv_data->cur_msg;
+	t = drv_data->cur_transfer;
+	chip = drv_data->cur_chip;
+
+	/* Handle for abort */
+	if (drv_data->state == ERROR_STATE) {
+		msg->status = -EIO;
+		bfin_spi_giveback(drv_data);
+		return;
+	}
+
+	if (drv_data->state == RUNNING_STATE) {
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+		if (t->cs_change)
+			bfin_spi_cs_deactive(drv_data, chip);
+		bfin_spi_next_transfer(drv_data);
+		t = drv_data->cur_transfer;
+	}
+	/* Handle end of message */
+	if (drv_data->state == DONE_STATE) {
+		msg->status = 0;
+		bfin_spi_giveback(drv_data);
+		return;
+	}
+
+	if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) {
+		/* Schedule next transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+		return;
+	}
+
+	ret = bfin_spi_setup_transfer(drv_data);
+	if (ret) {
+		msg->status = ret;
+		bfin_spi_giveback(drv_data);
+	}
+
+	bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+	bfin_spi_cs_active(drv_data, chip);
+	drv_data->state = RUNNING_STATE;
+
+	if (chip->enable_dma)
+		ret = bfin_spi_dma_xfer(drv_data);
+	else
+		ret = bfin_spi_pio_xfer(drv_data);
+	if (ret) {
+		msg->status = ret;
+		bfin_spi_giveback(drv_data);
+	}
+}
+
+static int bfin_spi_transfer_one_message(struct spi_master *master,
+					struct spi_message *m)
+{
+	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+	drv_data->cur_msg = m;
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+	bfin_spi_restore_state(drv_data);
+
+	drv_data->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+					    struct spi_transfer, transfer_list);
+
+	tasklet_schedule(&drv_data->pump_transfers);
+	return 0;
+}
+
+#define MAX_SPI_SSEL	7
+
+static const u16 ssel[][MAX_SPI_SSEL] = {
+	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
+	P_SPI0_SSEL4, P_SPI0_SSEL5,
+	P_SPI0_SSEL6, P_SPI0_SSEL7},
+
+	{P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
+	P_SPI1_SSEL4, P_SPI1_SSEL5,
+	P_SPI1_SSEL6, P_SPI1_SSEL7},
+
+	{P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
+	P_SPI2_SSEL4, P_SPI2_SSEL5,
+	P_SPI2_SSEL6, P_SPI2_SSEL7},
+};
+
+static int bfin_spi_setup(struct spi_device *spi)
+{
+	struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
+	struct bfin_spi_device *chip = spi_get_ctldata(spi);
+	u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
+	int ret = -EINVAL;
+
+	if (!chip) {
+		struct bfin_spi3_chip *chip_info = spi->controller_data;
+
+		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev, "can not allocate chip data\n");
+			return -ENOMEM;
+		}
+		if (chip_info) {
+			if (chip_info->control & ~bfin_ctl_reg) {
+				dev_err(&spi->dev,
+					"do not set bits that the SPI framework manages\n");
+				goto error;
+			}
+			chip->control = chip_info->control;
+			chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+			chip->tx_dummy_val = chip_info->tx_dummy_val;
+			chip->enable_dma = chip_info->enable_dma;
+		}
+		chip->cs = spi->chip_select;
+		if (chip->cs < MAX_CTRL_CS) {
+			chip->ssel = (1 << chip->cs) << 8;
+			ret = peripheral_request(ssel[spi->master->bus_num]
+					[chip->cs-1], dev_name(&spi->dev));
+			if (ret) {
+				dev_err(&spi->dev, "peripheral_request() error\n");
+				goto error;
+			}
+		} else {
+			chip->cs_gpio = chip->cs - MAX_CTRL_CS;
+			ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH,
+						dev_name(&spi->dev));
+			if (ret) {
+				dev_err(&spi->dev, "gpio_request_one() error\n");
+				goto error;
+			}
+		}
+		spi_set_ctldata(spi, chip);
+	}
+
+	/* force a default base state */
+	chip->control &= bfin_ctl_reg;
+
+	if (spi->mode & SPI_CPOL)
+		chip->control |= SPI_CTL_CPOL;
+	if (spi->mode & SPI_CPHA)
+		chip->control |= SPI_CTL_CPHA;
+	if (spi->mode & SPI_LSB_FIRST)
+		chip->control |= SPI_CTL_LSBF;
+	chip->control |= SPI_CTL_MSTR;
+	/* we choose software to controll cs */
+	chip->control &= ~SPI_CTL_ASSEL;
+
+	chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz);
+
+	bfin_spi_cs_enable(drv_data, chip);
+	bfin_spi_cs_deactive(drv_data, chip);
+
+	return 0;
+error:
+	if (chip) {
+		kfree(chip);
+		spi_set_ctldata(spi, NULL);
+	}
+
+	return ret;
+}
+
+static void bfin_spi_cleanup(struct spi_device *spi)
+{
+	struct bfin_spi_device *chip = spi_get_ctldata(spi);
+	struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
+
+	if (!chip)
+		return;
+
+	if (chip->cs < MAX_CTRL_CS) {
+		peripheral_free(ssel[spi->master->bus_num]
+					[chip->cs-1]);
+		bfin_spi_cs_disable(drv_data, chip);
+	} else {
+		gpio_free(chip->cs_gpio);
+	}
+
+	kfree(chip);
+	spi_set_ctldata(spi, NULL);
+}
+
+static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)
+{
+	struct bfin_spi_master *drv_data = dev_id;
+	u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma);
+
+	clear_dma_irqstat(drv_data->tx_dma);
+	if (dma_stat & DMA_DONE) {
+		drv_data->tx_num++;
+	} else {
+		dev_err(&drv_data->master->dev,
+				"spi tx dma error: %d\n", dma_stat);
+		if (drv_data->tx)
+			drv_data->state = ERROR_STATE;
+	}
+	bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
+{
+	struct bfin_spi_master *drv_data = dev_id;
+	struct spi_message *msg = drv_data->cur_msg;
+	u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma);
+
+	clear_dma_irqstat(drv_data->rx_dma);
+	if (dma_stat & DMA_DONE) {
+		drv_data->rx_num++;
+		/* we may fail on tx dma */
+		if (drv_data->state != ERROR_STATE)
+			msg->actual_length += drv_data->transfer_len;
+	} else {
+		drv_data->state = ERROR_STATE;
+		dev_err(&drv_data->master->dev,
+				"spi rx dma error: %d\n", dma_stat);
+	}
+	bfin_write(&drv_data->regs->tx_control, 0);
+	bfin_write(&drv_data->regs->rx_control, 0);
+	if (drv_data->rx_num != drv_data->tx_num)
+		dev_dbg(&drv_data->master->dev,
+				"dma interrupt missing: tx=%d,rx=%d\n",
+				drv_data->tx_num, drv_data->rx_num);
+	tasklet_schedule(&drv_data->pump_transfers);
+	return IRQ_HANDLED;
+}
+
+static int bfin_spi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct bfin_spi3_master *info = dev->platform_data;
+	struct spi_master *master;
+	struct bfin_spi_master *drv_data;
+	struct resource *mem, *res;
+	unsigned int tx_dma, rx_dma;
+	unsigned long sclk;
+	int ret;
+
+	if (!info) {
+		dev_err(dev, "platform data missing!\n");
+		return -ENODEV;
+	}
+
+	sclk = get_sclk1();
+	if (!sclk) {
+		dev_err(dev, "can not get sclk1\n");
+		return -ENXIO;
+	}
+
+	/* get register base and tx/rx dma */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(dev, "can not get register base\n");
+		return -ENXIO;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!res) {
+		dev_err(dev, "can not get tx dma resource\n");
+		return -ENXIO;
+	}
+	tx_dma = res->start;
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!res) {
+		dev_err(dev, "can not get rx dma resource\n");
+		return -ENXIO;
+	}
+	rx_dma = res->start;
+
+	/* allocate master with space for drv_data */
+	master = spi_alloc_master(dev, sizeof(*drv_data));
+	if (!master) {
+		dev_err(dev, "can not alloc spi_master\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, master);
+
+	/* the mode bits supported by this driver */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = info->num_chipselect;
+	master->cleanup = bfin_spi_cleanup;
+	master->setup = bfin_spi_setup;
+	master->transfer_one_message = bfin_spi_transfer_one_message;
+	master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
+
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->tx_dma = tx_dma;
+	drv_data->rx_dma = rx_dma;
+	drv_data->pin_req = info->pin_req;
+	drv_data->sclk = sclk;
+
+	drv_data->regs = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(drv_data->regs)) {
+		ret = PTR_ERR(drv_data->regs);
+		goto err_put_master;
+	}
+
+	/* request tx and rx dma */
+	ret = request_dma(tx_dma, "SPI_TX_DMA");
+	if (ret) {
+		dev_err(dev, "can not request SPI TX DMA channel\n");
+		goto err_put_master;
+	}
+	set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data);
+
+	ret = request_dma(rx_dma, "SPI_RX_DMA");
+	if (ret) {
+		dev_err(dev, "can not request SPI RX DMA channel\n");
+		goto err_free_tx_dma;
+	}
+	set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data);
+
+	/* request CLK, MOSI and MISO */
+	ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3");
+	if (ret < 0) {
+		dev_err(dev, "can not request spi pins\n");
+		goto err_free_rx_dma;
+	}
+
+	bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
+	bfin_write(&drv_data->regs->ssel, 0x0000FE00);
+	bfin_write(&drv_data->regs->delay, 0x0);
+
+	tasklet_init(&drv_data->pump_transfers,
+			bfin_spi_pump_transfers, (unsigned long)drv_data);
+	/* register with the SPI framework */
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(dev, "can not  register spi master\n");
+		goto err_free_peripheral;
+	}
+
+	return ret;
+
+err_free_peripheral:
+	peripheral_free_list(drv_data->pin_req);
+err_free_rx_dma:
+	free_dma(rx_dma);
+err_free_tx_dma:
+	free_dma(tx_dma);
+err_put_master:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int bfin_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+	bfin_spi_disable(drv_data);
+
+	peripheral_free_list(drv_data->pin_req);
+	free_dma(drv_data->rx_dma);
+	free_dma(drv_data->tx_dma);
+
+	platform_set_drvdata(pdev, NULL);
+	spi_unregister_master(drv_data->master);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_spi_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+	spi_master_suspend(master);
+
+	drv_data->control = bfin_read(&drv_data->regs->control);
+	drv_data->ssel = bfin_read(&drv_data->regs->ssel);
+
+	bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
+	bfin_write(&drv_data->regs->ssel, 0x0000FE00);
+	dma_disable_irq(drv_data->rx_dma);
+	dma_disable_irq(drv_data->tx_dma);
+
+	return 0;
+}
+
+static int bfin_spi_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+	int ret = 0;
+
+	/* bootrom may modify spi and dma status when resume in spi boot mode */
+	disable_dma(drv_data->rx_dma);
+
+	dma_enable_irq(drv_data->rx_dma);
+	dma_enable_irq(drv_data->tx_dma);
+	bfin_write(&drv_data->regs->control, drv_data->control);
+	bfin_write(&drv_data->regs->ssel, drv_data->ssel);
+
+	ret = spi_master_resume(master);
+	if (ret) {
+		free_dma(drv_data->rx_dma);
+		free_dma(drv_data->tx_dma);
+	}
+
+	return ret;
+}
+#endif
+static const struct dev_pm_ops bfin_spi_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume)
+};
+
+MODULE_ALIAS("platform:bfin-spi3");
+static struct platform_driver bfin_spi_driver = {
+	.driver	= {
+		.name	= "bfin-spi3",
+		.owner	= THIS_MODULE,
+		.pm     = &bfin_spi_pm_ops,
+	},
+	.remove		= bfin_spi_remove,
+};
+
+module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe);
+
+MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index a63d7da..a89178d 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -255,150 +255,142 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
  * Drivers can provide word-at-a-time i/o primitives, or provide
  * transfer-at-a-time ones to leverage dma or fifo hardware.
  */
-static void bitbang_work(struct work_struct *work)
+
+static int spi_bitbang_prepare_hardware(struct spi_master *spi)
 {
-	struct spi_bitbang	*bitbang =
-		container_of(work, struct spi_bitbang, work);
+	struct spi_bitbang 	*bitbang;
 	unsigned long		flags;
-	struct spi_message	*m, *_m;
+
+	bitbang = spi_master_get_devdata(spi);
 
 	spin_lock_irqsave(&bitbang->lock, flags);
 	bitbang->busy = 1;
-	list_for_each_entry_safe(m, _m, &bitbang->queue, queue) {
-		struct spi_device	*spi;
-		unsigned		nsecs;
-		struct spi_transfer	*t = NULL;
-		unsigned		tmp;
-		unsigned		cs_change;
-		int			status;
-		int			do_setup = -1;
-
-		list_del(&m->queue);
-		spin_unlock_irqrestore(&bitbang->lock, flags);
-
-		/* FIXME this is made-up ... the correct value is known to
-		 * word-at-a-time bitbang code, and presumably chipselect()
-		 * should enforce these requirements too?
-		 */
-		nsecs = 100;
+	spin_unlock_irqrestore(&bitbang->lock, flags);
 
-		spi = m->spi;
-		tmp = 0;
-		cs_change = 1;
-		status = 0;
+	return 0;
+}
 
-		list_for_each_entry (t, &m->transfers, transfer_list) {
-
-			/* override speed or wordsize? */
-			if (t->speed_hz || t->bits_per_word)
-				do_setup = 1;
-
-			/* init (-1) or override (1) transfer params */
-			if (do_setup != 0) {
-				status = bitbang->setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (do_setup == -1)
-					do_setup = 0;
-			}
-
-			/* set up default clock polarity, and activate chip;
-			 * this implicitly updates clock and spi modes as
-			 * previously recorded for this device via setup().
-			 * (and also deselects any other chip that might be
-			 * selected ...)
-			 */
-			if (cs_change) {
-				bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
-				ndelay(nsecs);
-			}
-			cs_change = t->cs_change;
-			if (!t->tx_buf && !t->rx_buf && t->len) {
-				status = -EINVAL;
-				break;
-			}
+static int spi_bitbang_transfer_one(struct spi_master *master,
+				    struct spi_message *m)
+{
+	struct spi_bitbang 	*bitbang;
+	unsigned		nsecs;
+	struct spi_transfer	*t = NULL;
+	unsigned		tmp;
+	unsigned		cs_change;
+	int			status;
+	int			do_setup = -1;
+	struct spi_device	*spi = m->spi;
+
+	bitbang = spi_master_get_devdata(master);
+
+	/* FIXME this is made-up ... the correct value is known to
+	 * word-at-a-time bitbang code, and presumably chipselect()
+	 * should enforce these requirements too?
+	 */
+	nsecs = 100;
 
-			/* transfer data.  the lower level code handles any
-			 * new dma mappings it needs. our caller always gave
-			 * us dma-safe buffers.
-			 */
-			if (t->len) {
-				/* REVISIT dma API still needs a designated
-				 * DMA_ADDR_INVALID; ~0 might be better.
-				 */
-				if (!m->is_dma_mapped)
-					t->rx_dma = t->tx_dma = 0;
-				status = bitbang->txrx_bufs(spi, t);
-			}
-			if (status > 0)
-				m->actual_length += status;
-			if (status != t->len) {
-				/* always report some kind of error */
-				if (status >= 0)
-					status = -EREMOTEIO;
+	tmp = 0;
+	cs_change = 1;
+	status = 0;
+
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+
+		/* override speed or wordsize? */
+		if (t->speed_hz || t->bits_per_word)
+			do_setup = 1;
+
+		/* init (-1) or override (1) transfer params */
+		if (do_setup != 0) {
+			status = bitbang->setup_transfer(spi, t);
+			if (status < 0)
 				break;
-			}
-			status = 0;
-
-			/* protocol tweaks before next transfer */
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
-				/* sometimes a short mid-message deselect of the chip
-				 * may be needed to terminate a mode or command
-				 */
-				ndelay(nsecs);
-				bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-				ndelay(nsecs);
-			}
+			if (do_setup == -1)
+				do_setup = 0;
 		}
 
-		m->status = status;
-		m->complete(m->context);
+		/* set up default clock polarity, and activate chip;
+		 * this implicitly updates clock and spi modes as
+		 * previously recorded for this device via setup().
+		 * (and also deselects any other chip that might be
+		 * selected ...)
+		 */
+		if (cs_change) {
+			bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
+			ndelay(nsecs);
+		}
+		cs_change = t->cs_change;
+		if (!t->tx_buf && !t->rx_buf && t->len) {
+			status = -EINVAL;
+			break;
+		}
 
-		/* normally deactivate chipselect ... unless no error and
-		 * cs_change has hinted that the next message will probably
-		 * be for this chip too.
+		/* transfer data.  the lower level code handles any
+		 * new dma mappings it needs. our caller always gave
+		 * us dma-safe buffers.
 		 */
-		if (!(status == 0 && cs_change)) {
+		if (t->len) {
+			/* REVISIT dma API still needs a designated
+			 * DMA_ADDR_INVALID; ~0 might be better.
+			 */
+			if (!m->is_dma_mapped)
+				t->rx_dma = t->tx_dma = 0;
+			status = bitbang->txrx_bufs(spi, t);
+		}
+		if (status > 0)
+			m->actual_length += status;
+		if (status != t->len) {
+			/* always report some kind of error */
+			if (status >= 0)
+				status = -EREMOTEIO;
+			break;
+		}
+		status = 0;
+
+		/* protocol tweaks before next transfer */
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
+			/* sometimes a short mid-message deselect of the chip
+			 * may be needed to terminate a mode or command
+			 */
 			ndelay(nsecs);
 			bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
 			ndelay(nsecs);
 		}
+	}
+
+	m->status = status;
 
-		spin_lock_irqsave(&bitbang->lock, flags);
+	/* normally deactivate chipselect ... unless no error and
+	 * cs_change has hinted that the next message will probably
+	 * be for this chip too.
+	 */
+	if (!(status == 0 && cs_change)) {
+		ndelay(nsecs);
+		bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+		ndelay(nsecs);
 	}
-	bitbang->busy = 0;
-	spin_unlock_irqrestore(&bitbang->lock, flags);
+
+	spi_finalize_current_message(master);
+
+	return status;
 }
 
-/**
- * spi_bitbang_transfer - default submit to transfer queue
- */
-int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
+static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
 {
-	struct spi_bitbang	*bitbang;
+	struct spi_bitbang 	*bitbang;
 	unsigned long		flags;
-	int			status = 0;
 
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	bitbang = spi_master_get_devdata(spi->master);
+	bitbang = spi_master_get_devdata(spi);
 
 	spin_lock_irqsave(&bitbang->lock, flags);
-	if (!spi->max_speed_hz)
-		status = -ENETDOWN;
-	else {
-		list_add_tail(&m->queue, &bitbang->queue);
-		queue_work(bitbang->workqueue, &bitbang->work);
-	}
+	bitbang->busy = 0;
 	spin_unlock_irqrestore(&bitbang->lock, flags);
 
-	return status;
+	return 0;
 }
-EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
 
 /*----------------------------------------------------------------------*/
 
@@ -428,20 +420,22 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
 int spi_bitbang_start(struct spi_bitbang *bitbang)
 {
 	struct spi_master *master = bitbang->master;
-	int status;
 
 	if (!master || !bitbang->chipselect)
 		return -EINVAL;
 
-	INIT_WORK(&bitbang->work, bitbang_work);
 	spin_lock_init(&bitbang->lock);
-	INIT_LIST_HEAD(&bitbang->queue);
 
 	if (!master->mode_bits)
 		master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
 
-	if (!master->transfer)
-		master->transfer = spi_bitbang_transfer;
+	if (master->transfer || master->transfer_one_message)
+		return -EINVAL;
+
+	master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
+	master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
+	master->transfer_one_message = spi_bitbang_transfer_one;
+
 	if (!bitbang->txrx_bufs) {
 		bitbang->use_dma = 0;
 		bitbang->txrx_bufs = spi_bitbang_bufs;
@@ -454,32 +448,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
 		}
 	} else if (!master->setup)
 		return -EINVAL;
-	if (master->transfer == spi_bitbang_transfer &&
-			!bitbang->setup_transfer)
-		return -EINVAL;
-
-	/* this task is the only thing to touch the SPI bits */
-	bitbang->busy = 0;
-	bitbang->workqueue = create_singlethread_workqueue(
-			dev_name(master->dev.parent));
-	if (bitbang->workqueue == NULL) {
-		status = -EBUSY;
-		goto err1;
-	}
 
 	/* driver may get busy before register() returns, especially
 	 * if someone registered boardinfo for devices
 	 */
-	status = spi_register_master(master);
-	if (status < 0)
-		goto err2;
-
-	return status;
-
-err2:
-	destroy_workqueue(bitbang->workqueue);
-err1:
-	return status;
+	return spi_register_master(master);
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_start);
 
@@ -490,10 +463,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang)
 {
 	spi_unregister_master(bitbang->master);
 
-	WARN_ON(!list_empty(&bitbang->queue));
-
-	destroy_workqueue(bitbang->workqueue);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_stop);
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 17965fe..5655acf 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -239,11 +239,8 @@ static int spi_clps711x_probe(struct platform_device *pdev)
 	}
 
 	dev_err(&pdev->dev, "Failed to register master\n");
-	devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
 
 clk_out:
-	devm_clk_put(&pdev->dev, hw->spi_clk);
-
 err_out:
 	while (--i >= 0)
 		if (gpio_is_valid(hw->chipselect[i]))
@@ -261,13 +258,10 @@ static int spi_clps711x_remove(struct platform_device *pdev)
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
 
-	devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
-
 	for (i = 0; i < master->num_chipselect; i++)
 		if (gpio_is_valid(hw->chipselect[i]))
 			gpio_free(hw->chipselect[i]);
 
-	devm_clk_put(&pdev->dev, hw->spi_clk);
 	spi_unregister_master(master);
 	kfree(master);
 
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index 0631b9d..e4265ea 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -354,24 +354,6 @@ static int mcfqspi_transfer_one_message(struct spi_master *master,
 
 }
 
-static int mcfqspi_prepare_transfer_hw(struct spi_master *master)
-{
-	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-
-	pm_runtime_get_sync(mcfqspi->dev);
-
-	return 0;
-}
-
-static int mcfqspi_unprepare_transfer_hw(struct spi_master *master)
-{
-	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-
-	pm_runtime_put_sync(mcfqspi->dev);
-
-	return 0;
-}
-
 static int mcfqspi_setup(struct spi_device *spi)
 {
 	if (spi->chip_select >= spi->master->num_chipselect) {
@@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
 	master->setup = mcfqspi_setup;
 	master->transfer_one_message = mcfqspi_transfer_one_message;
-	master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw;
-	master->unprepare_transfer_hardware = mcfqspi_unprepare_transfer_hw;
+	master->auto_runtime_pm = true;
 
 	platform_set_drvdata(pdev, master);
 
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 222d3e3..707966b 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -609,7 +609,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 		else
 			buf = (void *)t->tx_buf;
 		t->tx_dma = dma_map_single(&spi->dev, buf,
-				t->len, DMA_FROM_DEVICE);
+				t->len, DMA_TO_DEVICE);
 		if (!t->tx_dma) {
 			ret = -EFAULT;
 			goto err_tx_map;
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index cad30b8..31611f7 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/workqueue.h>
 #include <linux/sched.h>
 #include <linux/scatterlist.h>
 #include <linux/spi/spi.h>
@@ -70,19 +69,13 @@
 
 /**
  * struct ep93xx_spi - EP93xx SPI controller structure
- * @lock: spinlock that protects concurrent accesses to fields @running,
- *        @current_msg and @msg_queue
  * @pdev: pointer to platform device
  * @clk: clock for the controller
  * @regs_base: pointer to ioremap()'d registers
  * @sspdr_phys: physical address of the SSPDR register
  * @min_rate: minimum clock rate (in Hz) supported by the controller
  * @max_rate: maximum clock rate (in Hz) supported by the controller
- * @running: is the queue running
- * @wq: workqueue used by the driver
- * @msg_work: work that is queued for the driver
  * @wait: wait here until given transfer is completed
- * @msg_queue: queue for the messages
  * @current_msg: message that is currently processed (or %NULL if none)
  * @tx: current byte in transfer to transmit
  * @rx: current byte in transfer to receive
@@ -96,30 +89,15 @@
  * @tx_sgt: sg table for TX transfers
  * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
  *            the client
- *
- * This structure holds EP93xx SPI controller specific information. When
- * @running is %true, driver accepts transfer requests from protocol drivers.
- * @current_msg is used to hold pointer to the message that is currently
- * processed. If @current_msg is %NULL, it means that no processing is going
- * on.
- *
- * Most of the fields are only written once and they can be accessed without
- * taking the @lock. Fields that are accessed concurrently are: @current_msg,
- * @running, and @msg_queue.
  */
 struct ep93xx_spi {
-	spinlock_t			lock;
 	const struct platform_device	*pdev;
 	struct clk			*clk;
 	void __iomem			*regs_base;
 	unsigned long			sspdr_phys;
 	unsigned long			min_rate;
 	unsigned long			max_rate;
-	bool				running;
-	struct workqueue_struct		*wq;
-	struct work_struct		msg_work;
 	struct completion		wait;
-	struct list_head		msg_queue;
 	struct spi_message		*current_msg;
 	size_t				tx;
 	size_t				rx;
@@ -136,50 +114,36 @@ struct ep93xx_spi {
 /**
  * struct ep93xx_spi_chip - SPI device hardware settings
  * @spi: back pointer to the SPI device
- * @rate: max rate in hz this chip supports
- * @div_cpsr: cpsr (pre-scaler) divider
- * @div_scr: scr divider
- * @dss: bits per word (4 - 16 bits)
  * @ops: private chip operations
- *
- * This structure is used to store hardware register specific settings for each
- * SPI device. Settings are written to hardware by function
- * ep93xx_spi_chip_setup().
  */
 struct ep93xx_spi_chip {
 	const struct spi_device		*spi;
-	unsigned long			rate;
-	u8				div_cpsr;
-	u8				div_scr;
-	u8				dss;
 	struct ep93xx_spi_chip_ops	*ops;
 };
 
 /* converts bits per word to CR0.DSS value */
 #define bits_per_word_to_dss(bpw)	((bpw) - 1)
 
-static inline void
-ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value)
+static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi,
+				u16 reg, u8 value)
 {
-	__raw_writeb(value, espi->regs_base + reg);
+	writeb(value, espi->regs_base + reg);
 }
 
-static inline u8
-ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
+static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
 {
-	return __raw_readb(spi->regs_base + reg);
+	return readb(spi->regs_base + reg);
 }
 
-static inline void
-ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value)
+static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi,
+				 u16 reg, u16 value)
 {
-	__raw_writew(value, espi->regs_base + reg);
+	writew(value, espi->regs_base + reg);
 }
 
-static inline u16
-ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
+static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
 {
-	return __raw_readw(spi->regs_base + reg);
+	return readw(spi->regs_base + reg);
 }
 
 static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
@@ -230,17 +194,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
 /**
  * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
  * @espi: ep93xx SPI controller struct
- * @chip: divisors are calculated for this chip
  * @rate: desired SPI output clock rate
- *
- * Function calculates cpsr (clock pre-scaler) and scr divisors based on
- * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
- * for some reason, divisors cannot be calculated nothing is stored and
- * %-EINVAL is returned.
+ * @div_cpsr: pointer to return the cpsr (pre-scaler) divider
+ * @div_scr: pointer to return the scr divider
  */
 static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
-				    struct ep93xx_spi_chip *chip,
-				    unsigned long rate)
+				    unsigned long rate,
+				    u8 *div_cpsr, u8 *div_scr)
 {
 	unsigned long spi_clk_rate = clk_get_rate(espi->clk);
 	int cpsr, scr;
@@ -248,7 +208,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
 	/*
 	 * Make sure that max value is between values supported by the
 	 * controller. Note that minimum value is already checked in
-	 * ep93xx_spi_transfer().
+	 * ep93xx_spi_transfer_one_message().
 	 */
 	rate = clamp(rate, espi->min_rate, espi->max_rate);
 
@@ -263,8 +223,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
 	for (cpsr = 2; cpsr <= 254; cpsr += 2) {
 		for (scr = 0; scr <= 255; scr++) {
 			if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
-				chip->div_scr = (u8)scr;
-				chip->div_cpsr = (u8)cpsr;
+				*div_scr = (u8)scr;
+				*div_cpsr = (u8)cpsr;
 				return 0;
 			}
 		}
@@ -319,73 +279,11 @@ static int ep93xx_spi_setup(struct spi_device *spi)
 		spi_set_ctldata(spi, chip);
 	}
 
-	if (spi->max_speed_hz != chip->rate) {
-		int err;
-
-		err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz);
-		if (err != 0) {
-			spi_set_ctldata(spi, NULL);
-			kfree(chip);
-			return err;
-		}
-		chip->rate = spi->max_speed_hz;
-	}
-
-	chip->dss = bits_per_word_to_dss(spi->bits_per_word);
-
 	ep93xx_spi_cs_control(spi, false);
 	return 0;
 }
 
 /**
- * ep93xx_spi_transfer() - queue message to be transferred
- * @spi: target SPI device
- * @msg: message to be transferred
- *
- * This function is called by SPI device drivers when they are going to transfer
- * a new message. It simply puts the message in the queue and schedules
- * workqueue to perform the actual transfer later on.
- *
- * Returns %0 on success and negative error in case of failure.
- */
-static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
-	struct spi_transfer *t;
-	unsigned long flags;
-
-	if (!msg || !msg->complete)
-		return -EINVAL;
-
-	/* first validate each transfer */
-	list_for_each_entry(t, &msg->transfers, transfer_list) {
-		if (t->speed_hz && t->speed_hz < espi->min_rate)
-				return -EINVAL;
-	}
-
-	/*
-	 * Now that we own the message, let's initialize it so that it is
-	 * suitable for us. We use @msg->status to signal whether there was
-	 * error in transfer and @msg->state is used to hold pointer to the
-	 * current transfer (or %NULL if no active current transfer).
-	 */
-	msg->state = NULL;
-	msg->status = 0;
-	msg->actual_length = 0;
-
-	spin_lock_irqsave(&espi->lock, flags);
-	if (!espi->running) {
-		spin_unlock_irqrestore(&espi->lock, flags);
-		return -ESHUTDOWN;
-	}
-	list_add_tail(&msg->queue, &espi->msg_queue);
-	queue_work(espi->wq, &espi->msg_work);
-	spin_unlock_irqrestore(&espi->lock, flags);
-
-	return 0;
-}
-
-/**
  * ep93xx_spi_cleanup() - cleans up master controller specific state
  * @spi: SPI device to cleanup
  *
@@ -409,39 +307,40 @@ static void ep93xx_spi_cleanup(struct spi_device *spi)
  * ep93xx_spi_chip_setup() - configures hardware according to given @chip
  * @espi: ep93xx SPI controller struct
  * @chip: chip specific settings
- *
- * This function sets up the actual hardware registers with settings given in
- * @chip. Note that no validation is done so make sure that callers validate
- * settings before calling this.
+ * @speed_hz: transfer speed
+ * @bits_per_word: transfer bits_per_word
  */
-static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
-				  const struct ep93xx_spi_chip *chip)
+static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
+				 const struct ep93xx_spi_chip *chip,
+				 u32 speed_hz, u8 bits_per_word)
 {
+	u8 dss = bits_per_word_to_dss(bits_per_word);
+	u8 div_cpsr = 0;
+	u8 div_scr = 0;
 	u16 cr0;
+	int err;
 
-	cr0 = chip->div_scr << SSPCR0_SCR_SHIFT;
+	err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr);
+	if (err)
+		return err;
+
+	cr0 = div_scr << SSPCR0_SCR_SHIFT;
 	cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT;
-	cr0 |= chip->dss;
+	cr0 |= dss;
 
 	dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
-		chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss);
+		chip->spi->mode, div_cpsr, div_scr, dss);
 	dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
 
-	ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr);
+	ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr);
 	ep93xx_spi_write_u16(espi, SSPCR0, cr0);
-}
-
-static inline int bits_per_word(const struct ep93xx_spi *espi)
-{
-	struct spi_message *msg = espi->current_msg;
-	struct spi_transfer *t = msg->state;
 
-	return t->bits_per_word;
+	return 0;
 }
 
 static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
 {
-	if (bits_per_word(espi) > 8) {
+	if (t->bits_per_word > 8) {
 		u16 tx_val = 0;
 
 		if (t->tx_buf)
@@ -460,7 +359,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
 
 static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
 {
-	if (bits_per_word(espi) > 8) {
+	if (t->bits_per_word > 8) {
 		u16 rx_val;
 
 		rx_val = ep93xx_spi_read_u16(espi, SSPDR);
@@ -546,7 +445,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
 	size_t len = t->len;
 	int i, ret, nents;
 
-	if (bits_per_word(espi) > 8)
+	if (t->bits_per_word > 8)
 		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
 	else
 		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
@@ -610,7 +509,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
 	}
 
 	if (WARN_ON(len)) {
-		dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
+		dev_warn(&espi->pdev->dev, "len = %zu expected 0!", len);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -708,37 +607,16 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
 					struct spi_transfer *t)
 {
 	struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
+	int err;
 
 	msg->state = t;
 
-	/*
-	 * Handle any transfer specific settings if needed. We use
-	 * temporary chip settings here and restore original later when
-	 * the transfer is finished.
-	 */
-	if (t->speed_hz || t->bits_per_word) {
-		struct ep93xx_spi_chip tmp_chip = *chip;
-
-		if (t->speed_hz) {
-			int err;
-
-			err = ep93xx_spi_calc_divisors(espi, &tmp_chip,
-						       t->speed_hz);
-			if (err) {
-				dev_err(&espi->pdev->dev,
-					"failed to adjust speed\n");
-				msg->status = err;
-				return;
-			}
-		}
-
-		if (t->bits_per_word)
-			tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word);
-
-		/*
-		 * Set up temporary new hw settings for this transfer.
-		 */
-		ep93xx_spi_chip_setup(espi, &tmp_chip);
+	err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word);
+	if (err) {
+		dev_err(&espi->pdev->dev,
+			"failed to setup chip for transfer\n");
+		msg->status = err;
+		return;
 	}
 
 	espi->rx = 0;
@@ -783,9 +661,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
 			ep93xx_spi_cs_control(msg->spi, true);
 		}
 	}
-
-	if (t->speed_hz || t->bits_per_word)
-		ep93xx_spi_chip_setup(espi, chip);
 }
 
 /*
@@ -838,10 +713,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
 	espi->fifo_level = 0;
 
 	/*
-	 * Update SPI controller registers according to spi device and assert
-	 * the chipselect.
+	 * Assert the chipselect.
 	 */
-	ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
 	ep93xx_spi_cs_control(msg->spi, true);
 
 	list_for_each_entry(t, &msg->transfers, transfer_list) {
@@ -858,50 +731,29 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
 	ep93xx_spi_disable(espi);
 }
 
-#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work))
-
-/**
- * ep93xx_spi_work() - EP93xx SPI workqueue worker function
- * @work: work struct
- *
- * Workqueue worker function. This function is called when there are new
- * SPI messages to be processed. Message is taken out from the queue and then
- * passed to ep93xx_spi_process_message().
- *
- * After message is transferred, protocol driver is notified by calling
- * @msg->complete(). In case of error, @msg->status is set to negative error
- * number, otherwise it contains zero (and @msg->actual_length is updated).
- */
-static void ep93xx_spi_work(struct work_struct *work)
+static int ep93xx_spi_transfer_one_message(struct spi_master *master,
+					   struct spi_message *msg)
 {
-	struct ep93xx_spi *espi = work_to_espi(work);
-	struct spi_message *msg;
+	struct ep93xx_spi *espi = spi_master_get_devdata(master);
+	struct spi_transfer *t;
 
-	spin_lock_irq(&espi->lock);
-	if (!espi->running || espi->current_msg ||
-		list_empty(&espi->msg_queue)) {
-		spin_unlock_irq(&espi->lock);
-		return;
+	/* first validate each transfer */
+	list_for_each_entry(t, &msg->transfers, transfer_list) {
+		if (t->speed_hz < espi->min_rate)
+			return -EINVAL;
 	}
-	msg = list_first_entry(&espi->msg_queue, struct spi_message, queue);
-	list_del_init(&msg->queue);
-	espi->current_msg = msg;
-	spin_unlock_irq(&espi->lock);
 
-	ep93xx_spi_process_message(espi, msg);
+	msg->state = NULL;
+	msg->status = 0;
+	msg->actual_length = 0;
 
-	/*
-	 * Update the current message and re-schedule ourselves if there are
-	 * more messages in the queue.
-	 */
-	spin_lock_irq(&espi->lock);
+	espi->current_msg = msg;
+	ep93xx_spi_process_message(espi, msg);
 	espi->current_msg = NULL;
-	if (espi->running && !list_empty(&espi->msg_queue))
-		queue_work(espi->wq, &espi->msg_work);
-	spin_unlock_irq(&espi->lock);
 
-	/* notify the protocol driver that we are done with this message */
-	msg->complete(msg->context);
+	spi_finalize_current_message(master);
+
+	return 0;
 }
 
 static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
@@ -1024,14 +876,24 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 
 	info = pdev->dev.platform_data;
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq resources\n");
+		return -EBUSY;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "unable to get iomem resource\n");
+		return -ENODEV;
+	}
+
 	master = spi_alloc_master(&pdev->dev, sizeof(*espi));
-	if (!master) {
-		dev_err(&pdev->dev, "failed to allocate spi master\n");
+	if (!master)
 		return -ENOMEM;
-	}
 
 	master->setup = ep93xx_spi_setup;
-	master->transfer = ep93xx_spi_transfer;
+	master->transfer_one_message = ep93xx_spi_transfer_one_message;
 	master->cleanup = ep93xx_spi_cleanup;
 	master->bus_num = pdev->id;
 	master->num_chipselect = info->num_chipselect;
@@ -1042,14 +904,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 
 	espi = spi_master_get_devdata(master);
 
-	espi->clk = clk_get(&pdev->dev, NULL);
+	espi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(espi->clk)) {
 		dev_err(&pdev->dev, "unable to get spi clock\n");
 		error = PTR_ERR(espi->clk);
 		goto fail_release_master;
 	}
 
-	spin_lock_init(&espi->lock);
 	init_completion(&espi->wait);
 
 	/*
@@ -1060,55 +921,31 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 	espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
 	espi->pdev = pdev;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		error = -EBUSY;
-		dev_err(&pdev->dev, "failed to get irq resources\n");
-		goto fail_put_clock;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "unable to get iomem resource\n");
-		error = -ENODEV;
-		goto fail_put_clock;
-	}
-
 	espi->sspdr_phys = res->start + SSPDR;
 
 	espi->regs_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(espi->regs_base)) {
 		error = PTR_ERR(espi->regs_base);
-		goto fail_put_clock;
+		goto fail_release_master;
 	}
 
 	error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt,
 				0, "ep93xx-spi", espi);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request irq\n");
-		goto fail_put_clock;
+		goto fail_release_master;
 	}
 
 	if (info->use_dma && ep93xx_spi_setup_dma(espi))
 		dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
 
-	espi->wq = create_singlethread_workqueue("ep93xx_spid");
-	if (!espi->wq) {
-		dev_err(&pdev->dev, "unable to create workqueue\n");
-		error = -ENOMEM;
-		goto fail_free_dma;
-	}
-	INIT_WORK(&espi->msg_work, ep93xx_spi_work);
-	INIT_LIST_HEAD(&espi->msg_queue);
-	espi->running = true;
-
 	/* make sure that the hardware is disabled */
 	ep93xx_spi_write_u8(espi, SSPCR1, 0);
 
 	error = spi_register_master(master);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register SPI master\n");
-		goto fail_free_queue;
+		goto fail_free_dma;
 	}
 
 	dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
@@ -1116,12 +953,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 
 	return 0;
 
-fail_free_queue:
-	destroy_workqueue(espi->wq);
 fail_free_dma:
 	ep93xx_spi_release_dma(espi);
-fail_put_clock:
-	clk_put(espi->clk);
 fail_release_master:
 	spi_master_put(master);
 
@@ -1133,31 +966,7 @@ static int ep93xx_spi_remove(struct platform_device *pdev)
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct ep93xx_spi *espi = spi_master_get_devdata(master);
 
-	spin_lock_irq(&espi->lock);
-	espi->running = false;
-	spin_unlock_irq(&espi->lock);
-
-	destroy_workqueue(espi->wq);
-
-	/*
-	 * Complete remaining messages with %-ESHUTDOWN status.
-	 */
-	spin_lock_irq(&espi->lock);
-	while (!list_empty(&espi->msg_queue)) {
-		struct spi_message *msg;
-
-		msg = list_first_entry(&espi->msg_queue,
-				       struct spi_message, queue);
-		list_del_init(&msg->queue);
-		msg->status = -ESHUTDOWN;
-		spin_unlock_irq(&espi->lock);
-		msg->complete(msg->context);
-		spin_lock_irq(&espi->lock);
-	}
-	spin_unlock_irq(&espi->lock);
-
 	ep93xx_spi_release_dma(espi);
-	clk_put(espi->clk);
 
 	spi_unregister_master(master);
 	return 0;
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 41e89c3..ca0ddb8 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -901,7 +901,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	master = fsl_spi_probe(&pdev->dev, mem, irq);
-	return PTR_RET(master);
+	return PTR_ERR_OR_ZERO(master);
 }
 
 static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 7db4f43..15323d8 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -619,6 +619,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
 	{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
 	{ /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
 
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 {
@@ -796,10 +797,11 @@ static int spi_imx_probe(struct platform_device *pdev)
 		if (!gpio_is_valid(cs_gpio))
 			continue;
 
-		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
+		ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i],
+					DRIVER_NAME);
 		if (ret) {
 			dev_err(&pdev->dev, "can't get cs gpios\n");
-			goto out_gpio_free;
+			goto out_master_put;
 		}
 	}
 
@@ -816,50 +818,44 @@ static int spi_imx_probe(struct platform_device *pdev)
 		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't get platform resource\n");
-		ret = -ENOMEM;
-		goto out_gpio_free;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "request_mem_region failed\n");
-		ret = -EBUSY;
-		goto out_gpio_free;
-	}
-
-	spi_imx->base = ioremap(res->start, resource_size(res));
-	if (!spi_imx->base) {
-		ret = -EINVAL;
-		goto out_release_mem;
+	spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(spi_imx->base)) {
+		ret = PTR_ERR(spi_imx->base);
+		goto out_master_put;
 	}
 
 	spi_imx->irq = platform_get_irq(pdev, 0);
 	if (spi_imx->irq < 0) {
 		ret = -EINVAL;
-		goto out_iounmap;
+		goto out_master_put;
 	}
 
-	ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
+	ret = devm_request_irq(&pdev->dev, spi_imx->irq, spi_imx_isr, 0,
+			       DRIVER_NAME, spi_imx);
 	if (ret) {
 		dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
-		goto out_iounmap;
+		goto out_master_put;
 	}
 
 	spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(spi_imx->clk_ipg)) {
 		ret = PTR_ERR(spi_imx->clk_ipg);
-		goto out_free_irq;
+		goto out_master_put;
 	}
 
 	spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(spi_imx->clk_per)) {
 		ret = PTR_ERR(spi_imx->clk_per);
-		goto out_free_irq;
+		goto out_master_put;
 	}
 
-	clk_prepare_enable(spi_imx->clk_per);
-	clk_prepare_enable(spi_imx->clk_ipg);
+	ret = clk_prepare_enable(spi_imx->clk_per);
+	if (ret)
+		goto out_master_put;
+
+	ret = clk_prepare_enable(spi_imx->clk_ipg);
+	if (ret)
+		goto out_put_per;
 
 	spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
 
@@ -879,47 +875,27 @@ static int spi_imx_probe(struct platform_device *pdev)
 	return ret;
 
 out_clk_put:
-	clk_disable_unprepare(spi_imx->clk_per);
 	clk_disable_unprepare(spi_imx->clk_ipg);
-out_free_irq:
-	free_irq(spi_imx->irq, spi_imx);
-out_iounmap:
-	iounmap(spi_imx->base);
-out_release_mem:
-	release_mem_region(res->start, resource_size(res));
-out_gpio_free:
-	while (--i >= 0) {
-		if (gpio_is_valid(spi_imx->chipselect[i]))
-			gpio_free(spi_imx->chipselect[i]);
-	}
+out_put_per:
+	clk_disable_unprepare(spi_imx->clk_per);
+out_master_put:
 	spi_master_put(master);
-	kfree(master);
+
 	return ret;
 }
 
 static int spi_imx_remove(struct platform_device *pdev)
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
-	int i;
 
 	spi_bitbang_stop(&spi_imx->bitbang);
 
 	writel(0, spi_imx->base + MXC_CSPICTRL);
-	clk_disable_unprepare(spi_imx->clk_per);
 	clk_disable_unprepare(spi_imx->clk_ipg);
-	free_irq(spi_imx->irq, spi_imx);
-	iounmap(spi_imx->base);
-
-	for (i = 0; i < master->num_chipselect; i++)
-		if (gpio_is_valid(spi_imx->chipselect[i]))
-			gpio_free(spi_imx->chipselect[i]);
-
+	clk_disable_unprepare(spi_imx->clk_per);
 	spi_master_put(master);
 
-	release_mem_region(res->start, resource_size(res));
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 424d38e..de7b114 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -67,13 +67,8 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
 {
 	struct mxs_spi *spi = spi_master_get_devdata(dev->master);
 	struct mxs_ssp *ssp = &spi->ssp;
-	uint8_t bits_per_word;
 	uint32_t hz = 0;
 
-	bits_per_word = dev->bits_per_word;
-	if (t && t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
 	hz = dev->max_speed_hz;
 	if (t && t->speed_hz)
 		hz = min(hz, t->speed_hz);
@@ -513,7 +508,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq_err = platform_get_irq(pdev, 0);
-	if (!iores || irq_err < 0)
+	if (irq_err < 0)
 		return -EINVAL;
 
 	base = devm_ioremap_resource(&pdev->dev, iores);
@@ -563,25 +558,31 @@ static int mxs_spi_probe(struct platform_device *pdev)
 		goto out_master_free;
 	}
 
-	clk_prepare_enable(ssp->clk);
+	ret = clk_prepare_enable(ssp->clk);
+	if (ret)
+		goto out_dma_release;
+
 	clk_set_rate(ssp->clk, clk_freq);
 	ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
 
-	stmp_reset_block(ssp->base);
+	ret = stmp_reset_block(ssp->base);
+	if (ret)
+		goto out_disable_clk;
 
 	platform_set_drvdata(pdev, master);
 
 	ret = spi_register_master(master);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
-		goto out_free_dma;
+		goto out_disable_clk;
 	}
 
 	return 0;
 
-out_free_dma:
-	dma_release_channel(ssp->dmach);
+out_disable_clk:
 	clk_disable_unprepare(ssp->clk);
+out_dma_release:
+	dma_release_channel(ssp->dmach);
 out_master_free:
 	spi_master_put(master);
 	return ret;
@@ -598,11 +599,8 @@ static int mxs_spi_remove(struct platform_device *pdev)
 	ssp = &spi->ssp;
 
 	spi_unregister_master(master);
-
-	dma_release_channel(ssp->dmach);
-
 	clk_disable_unprepare(ssp->clk);
-
+	dma_release_channel(ssp->dmach);
 	spi_master_put(master);
 
 	return 0;
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
index 24daf96..ad924a1 100644
--- a/drivers/spi/spi-octeon.c
+++ b/drivers/spi/spi-octeon.c
@@ -28,7 +28,6 @@
 #define OCTEON_SPI_MAX_CLOCK_HZ 16000000
 
 struct octeon_spi {
-	struct spi_master *my_master;
 	u64 register_base;
 	u64 last_cfg;
 	u64 cs_enax;
@@ -268,7 +267,6 @@ static int octeon_spi_nop_transfer_hardware(struct spi_master *master)
 
 static int octeon_spi_probe(struct platform_device *pdev)
 {
-
 	struct resource *res_mem;
 	struct spi_master *master;
 	struct octeon_spi *p;
@@ -278,8 +276,7 @@ static int octeon_spi_probe(struct platform_device *pdev)
 	if (!master)
 		return -ENOMEM;
 	p = spi_master_get_devdata(master);
-	platform_set_drvdata(pdev, p);
-	p->my_master = master;
+	platform_set_drvdata(pdev, master);
 
 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -328,10 +325,11 @@ fail:
 
 static int octeon_spi_remove(struct platform_device *pdev)
 {
-	struct octeon_spi *p = platform_get_drvdata(pdev);
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct octeon_spi *p = spi_master_get_devdata(master);
 	u64 register_base = p->register_base;
 
-	spi_unregister_master(p->my_master);
+	spi_unregister_master(master);
 
 	/* Clear the CSENA* and put everything in a known state. */
 	cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
index ee25670..cdcc72c 100644
--- a/drivers/spi/spi-omap-100k.c
+++ b/drivers/spi/spi-omap-100k.c
@@ -83,11 +83,6 @@
 #define SPI_SHUTDOWN	1
 
 struct omap1_spi100k {
-	struct work_struct      work;
-
-	/* lock protects queue and registers */
-	spinlock_t              lock;
-	struct list_head        msg_queue;
 	struct spi_master       *master;
 	struct clk              *ick;
 	struct clk              *fck;
@@ -104,8 +99,6 @@ struct omap1_spi100k_cs {
 	int                     word_len;
 };
 
-static struct workqueue_struct *omap1_spi100k_wq;
-
 #define MOD_REG_BIT(val, mask, set) do { \
 	if (set) \
 		val |= mask; \
@@ -310,170 +303,102 @@ static int omap1_spi100k_setup(struct spi_device *spi)
 
 	spi100k_open(spi->master);
 
-	clk_enable(spi100k->ick);
-	clk_enable(spi100k->fck);
+	clk_prepare_enable(spi100k->ick);
+	clk_prepare_enable(spi100k->fck);
 
 	ret = omap1_spi100k_setup_transfer(spi, NULL);
 
-	clk_disable(spi100k->ick);
-	clk_disable(spi100k->fck);
+	clk_disable_unprepare(spi100k->ick);
+	clk_disable_unprepare(spi100k->fck);
 
 	return ret;
 }
 
-static void omap1_spi100k_work(struct work_struct *work)
+static int omap1_spi100k_prepare_hardware(struct spi_master *master)
 {
-	struct omap1_spi100k    *spi100k;
-	int status = 0;
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
 
-	spi100k = container_of(work, struct omap1_spi100k, work);
-	spin_lock_irq(&spi100k->lock);
+	clk_prepare_enable(spi100k->ick);
+	clk_prepare_enable(spi100k->fck);
 
-	clk_enable(spi100k->ick);
-	clk_enable(spi100k->fck);
+	return 0;
+}
 
-	/* We only enable one channel at a time -- the one whose message is
-	 * at the head of the queue -- although this controller would gladly
-	 * arbitrate among multiple channels.  This corresponds to "single
-	 * channel" master mode.  As a side effect, we need to manage the
-	 * chipselect with the FORCE bit ... CS != channel enable.
-	 */
-	 while (!list_empty(&spi100k->msg_queue)) {
-		struct spi_message              *m;
-		struct spi_device               *spi;
-		struct spi_transfer             *t = NULL;
-		int                             cs_active = 0;
-		struct omap1_spi100k_cs         *cs;
-		int                             par_override = 0;
-
-		m = container_of(spi100k->msg_queue.next, struct spi_message,
-				 queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&spi100k->lock);
-
-		spi = m->spi;
-		cs = spi->controller_state;
-
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-				status = -EINVAL;
+static int omap1_spi100k_transfer_one_message(struct spi_master *master,
+					      struct spi_message *m)
+{
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t = NULL;
+	int cs_active = 0;
+	int par_override = 0;
+	int status = 0;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+			status = -EINVAL;
+			break;
+		}
+		if (par_override || t->speed_hz || t->bits_per_word) {
+			par_override = 1;
+			status = omap1_spi100k_setup_transfer(spi, t);
+			if (status < 0)
 				break;
-			}
-			if (par_override || t->speed_hz || t->bits_per_word) {
-				par_override = 1;
-				status = omap1_spi100k_setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (!t->speed_hz && !t->bits_per_word)
-					par_override = 0;
-			}
+			if (!t->speed_hz && !t->bits_per_word)
+				par_override = 0;
+		}
 
-			if (!cs_active) {
-				omap1_spi100k_force_cs(spi100k, 1);
-				cs_active = 1;
-			}
+		if (!cs_active) {
+			omap1_spi100k_force_cs(spi100k, 1);
+			cs_active = 1;
+		}
 
-			if (t->len) {
-				unsigned count;
+		if (t->len) {
+			unsigned count;
 
-				count = omap1_spi100k_txrx_pio(spi, t);
-				m->actual_length += count;
+			count = omap1_spi100k_txrx_pio(spi, t);
+			m->actual_length += count;
 
-				if (count != t->len) {
-					status = -EIO;
-					break;
-				}
+			if (count != t->len) {
+				status = -EIO;
+				break;
 			}
+		}
 
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
 
-			/* ignore the "leave it on after last xfer" hint */
+		/* ignore the "leave it on after last xfer" hint */
 
-			if (t->cs_change) {
-				omap1_spi100k_force_cs(spi100k, 0);
-				cs_active = 0;
-			}
-		}
-
-		/* Restore defaults if they were overriden */
-		if (par_override) {
-			par_override = 0;
-			status = omap1_spi100k_setup_transfer(spi, NULL);
+		if (t->cs_change) {
+			omap1_spi100k_force_cs(spi100k, 0);
+			cs_active = 0;
 		}
+	}
 
-		if (cs_active)
-			omap1_spi100k_force_cs(spi100k, 0);
+	/* Restore defaults if they were overriden */
+	if (par_override) {
+		par_override = 0;
+		status = omap1_spi100k_setup_transfer(spi, NULL);
+	}
 
-		m->status = status;
-		m->complete(m->context);
+	if (cs_active)
+		omap1_spi100k_force_cs(spi100k, 0);
 
-		spin_lock_irq(&spi100k->lock);
-	}
+	m->status = status;
 
-	clk_disable(spi100k->ick);
-	clk_disable(spi100k->fck);
-	spin_unlock_irq(&spi100k->lock);
+	spi_finalize_current_message(master);
 
-	if (status < 0)
-		printk(KERN_WARNING "spi transfer failed with %d\n", status);
+	return status;
 }
 
-static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
+static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
 {
-	struct omap1_spi100k    *spi100k;
-	unsigned long           flags;
-	struct spi_transfer     *t;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spi100k = spi_master_get_devdata(spi->master);
-
-	/* Don't accept new work if we're shutting down */
-	if (spi100k->state == SPI_SHUTDOWN)
-		return -ESHUTDOWN;
-
-	/* reject invalid messages and transfers */
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		const void      *tx_buf = t->tx_buf;
-		void            *rx_buf = t->rx_buf;
-		unsigned        len = t->len;
-
-		if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
-				|| (len && !(rx_buf || tx_buf))) {
-			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
-					t->speed_hz,
-					len,
-					tx_buf ? "tx" : "",
-					rx_buf ? "rx" : "",
-					t->bits_per_word);
-			return -EINVAL;
-		}
-
-		if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
-			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
-					t->speed_hz,
-					OMAP1_SPI100K_MAX_FREQ/(1<<16));
-			return -EINVAL;
-		}
-
-	}
-
-	spin_lock_irqsave(&spi100k->lock, flags);
-	list_add_tail(&m->queue, &spi100k->msg_queue);
-	queue_work(omap1_spi100k_wq, &spi100k->work);
-	spin_unlock_irqrestore(&spi100k->lock, flags);
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
 
-	return 0;
-}
+	clk_disable_unprepare(spi100k->ick);
+	clk_disable_unprepare(spi100k->fck);
 
-static int omap1_spi100k_reset(struct omap1_spi100k *spi100k)
-{
 	return 0;
 }
 
@@ -496,11 +421,15 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
 	       master->bus_num = pdev->id;
 
 	master->setup = omap1_spi100k_setup;
-	master->transfer = omap1_spi100k_transfer;
+	master->transfer_one_message = omap1_spi100k_transfer_one_message;
+	master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
+	master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
 	master->cleanup = NULL;
 	master->num_chipselect = 2;
 	master->mode_bits = MODEBITS;
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+	master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
+	master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
 
 	platform_set_drvdata(pdev, master);
 
@@ -514,40 +443,29 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
 	 */
 	spi100k->base = (void __iomem *) pdev->dev.platform_data;
 
-	INIT_WORK(&spi100k->work, omap1_spi100k_work);
-
-	spin_lock_init(&spi100k->lock);
-	INIT_LIST_HEAD(&spi100k->msg_queue);
-	spi100k->ick = clk_get(&pdev->dev, "ick");
+	spi100k->ick = devm_clk_get(&pdev->dev, "ick");
 	if (IS_ERR(spi100k->ick)) {
 		dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
 		status = PTR_ERR(spi100k->ick);
-		goto err1;
+		goto err;
 	}
 
-	spi100k->fck = clk_get(&pdev->dev, "fck");
+	spi100k->fck = devm_clk_get(&pdev->dev, "fck");
 	if (IS_ERR(spi100k->fck)) {
 		dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
 		status = PTR_ERR(spi100k->fck);
-		goto err2;
+		goto err;
 	}
 
-	if (omap1_spi100k_reset(spi100k) < 0)
-		goto err3;
-
 	status = spi_register_master(master);
 	if (status < 0)
-		goto err3;
+		goto err;
 
 	spi100k->state = SPI_RUNNING;
 
 	return status;
 
-err3:
-	clk_put(spi100k->fck);
-err2:
-	clk_put(spi100k->ick);
-err1:
+err:
 	spi_master_put(master);
 	return status;
 }
@@ -557,33 +475,14 @@ static int omap1_spi100k_remove(struct platform_device *pdev)
 	struct spi_master       *master;
 	struct omap1_spi100k    *spi100k;
 	struct resource         *r;
-	unsigned		limit = 500;
-	unsigned long		flags;
 	int			status = 0;
 
 	master = platform_get_drvdata(pdev);
 	spi100k = spi_master_get_devdata(master);
 
-	spin_lock_irqsave(&spi100k->lock, flags);
-
-	spi100k->state = SPI_SHUTDOWN;
-	while (!list_empty(&spi100k->msg_queue) && limit--) {
-		spin_unlock_irqrestore(&spi100k->lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&spi100k->lock, flags);
-	}
-
-	if (!list_empty(&spi100k->msg_queue))
-		status = -EBUSY;
-
-	spin_unlock_irqrestore(&spi100k->lock, flags);
-
 	if (status != 0)
 		return status;
 
-	clk_put(spi100k->fck);
-	clk_put(spi100k->ick);
-
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	spi_unregister_master(master);
@@ -596,30 +495,11 @@ static struct platform_driver omap1_spi100k_driver = {
 		.name		= "omap1_spi100k",
 		.owner		= THIS_MODULE,
 	},
+	.probe		= omap1_spi100k_probe,
 	.remove		= omap1_spi100k_remove,
 };
 
-
-static int __init omap1_spi100k_init(void)
-{
-	omap1_spi100k_wq = create_singlethread_workqueue(
-			omap1_spi100k_driver.driver.name);
-
-	if (omap1_spi100k_wq == NULL)
-		return -1;
-
-	return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
-}
-
-static void __exit omap1_spi100k_exit(void)
-{
-	platform_driver_unregister(&omap1_spi100k_driver);
-
-	destroy_workqueue(omap1_spi100k_wq);
-}
-
-module_init(omap1_spi100k_init);
-module_exit(omap1_spi100k_exit);
+module_platform_driver(omap1_spi100k_driver);
 
 MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
 MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 5994039..973c1cb 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -335,23 +335,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
 		__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 }
 
-static int omap2_prepare_transfer(struct spi_master *master)
-{
-	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
-	pm_runtime_get_sync(mcspi->dev);
-	return 0;
-}
-
-static int omap2_unprepare_transfer(struct spi_master *master)
-{
-	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
-	pm_runtime_mark_last_busy(mcspi->dev);
-	pm_runtime_put_autosuspend(mcspi->dev);
-	return 0;
-}
-
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
 {
 	unsigned long timeout;
@@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
 	master->setup = omap2_mcspi_setup;
-	master->prepare_transfer_hardware = omap2_prepare_transfer;
-	master->unprepare_transfer_hardware = omap2_unprepare_transfer;
+	master->auto_runtime_pm = true;
 	master->transfer_one_message = omap2_mcspi_transfer_one_message;
 	master->cleanup = omap2_mcspi_cleanup;
 	master->dev.of_node = node;
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 5d90beb..1d1d321 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/clk.h>
+#include <linux/sizes.h>
 #include <asm/unaligned.h>
 
 #define DRIVER_NAME			"orion_spi"
@@ -446,30 +447,22 @@ static int orion_spi_probe(struct platform_device *pdev)
 	spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		status = -ENODEV;
+	spi->base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(spi->base)) {
+		status = PTR_ERR(spi->base);
 		goto out_rel_clk;
 	}
 
-	if (!request_mem_region(r->start, resource_size(r),
-				dev_name(&pdev->dev))) {
-		status = -EBUSY;
-		goto out_rel_clk;
-	}
-	spi->base = ioremap(r->start, SZ_1K);
-
 	if (orion_spi_reset(spi) < 0)
-		goto out_rel_mem;
+		goto out_rel_clk;
 
 	master->dev.of_node = pdev->dev.of_node;
 	status = spi_register_master(master);
 	if (status < 0)
-		goto out_rel_mem;
+		goto out_rel_clk;
 
 	return status;
 
-out_rel_mem:
-	release_mem_region(r->start, resource_size(r));
 out_rel_clk:
 	clk_disable_unprepare(spi->clk);
 	clk_put(spi->clk);
@@ -482,7 +475,6 @@ out:
 static int orion_spi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master;
-	struct resource *r;
 	struct orion_spi *spi;
 
 	master = platform_get_drvdata(pdev);
@@ -491,9 +483,6 @@ static int orion_spi_remove(struct platform_device *pdev)
 	clk_disable_unprepare(spi->clk);
 	clk_put(spi->clk);
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, resource_size(r));
-
 	spi_unregister_master(master);
 
 	return 0;
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index abef061..07e6db6 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1555,18 +1555,6 @@ static int pl022_transfer_one_message(struct spi_master *master,
 	return 0;
 }
 
-static int pl022_prepare_transfer_hardware(struct spi_master *master)
-{
-	struct pl022 *pl022 = spi_master_get_devdata(master);
-
-	/*
-	 * Just make sure we have all we need to run the transfer by syncing
-	 * with the runtime PM framework.
-	 */
-	pm_runtime_get_sync(&pl022->adev->dev);
-	return 0;
-}
-
 static int pl022_unprepare_transfer_hardware(struct spi_master *master)
 {
 	struct pl022 *pl022 = spi_master_get_devdata(master);
@@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
 	writew((readw(SSP_CR1(pl022->virtbase)) &
 		(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
 
-	if (pl022->master_info->autosuspend_delay > 0) {
-		pm_runtime_mark_last_busy(&pl022->adev->dev);
-		pm_runtime_put_autosuspend(&pl022->adev->dev);
-	} else {
-		pm_runtime_put(&pl022->adev->dev);
-	}
-
 	return 0;
 }
 
@@ -2139,7 +2120,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	master->num_chipselect = num_cs;
 	master->cleanup = pl022_cleanup;
 	master->setup = pl022_setup;
-	master->prepare_transfer_hardware = pl022_prepare_transfer_hardware;
+	master->auto_runtime_pm = true;
 	master->transfer_one_message = pl022_transfer_one_message;
 	master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
 	master->rt = platform_info->rt;
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index f440dce..2eb06ee 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -69,6 +69,8 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 #define LPSS_TX_HITHRESH_DFLT	224
 
 /* Offset from drv_data->lpss_base */
+#define GENERAL_REG		0x08
+#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
 #define SSP_REG			0x0c
 #define SPI_CS_CONTROL		0x18
 #define SPI_CS_CONTROL_SW_MODE	BIT(0)
@@ -142,8 +144,13 @@ detection_done:
 	__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
 
 	/* Enable multiblock DMA transfers */
-	if (drv_data->master_info->enable_dma)
+	if (drv_data->master_info->enable_dma) {
 		__lpss_ssp_write_priv(drv_data, SSP_REG, 1);
+
+		value = __lpss_ssp_read_priv(drv_data, GENERAL_REG);
+		value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
+		__lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
+	}
 }
 
 static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
@@ -804,14 +811,6 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
 	return 0;
 }
 
-static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
-{
-	struct driver_data *drv_data = spi_master_get_devdata(master);
-
-	pm_runtime_get_sync(&drv_data->pdev->dev);
-	return 0;
-}
-
 static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
 {
 	struct driver_data *drv_data = spi_master_get_devdata(master);
@@ -820,8 +819,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
 	write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
 		    drv_data->ioaddr);
 
-	pm_runtime_mark_last_busy(&drv_data->pdev->dev);
-	pm_runtime_put_autosuspend(&drv_data->pdev->dev);
 	return 0;
 }
 
@@ -1134,8 +1131,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
 	master->cleanup = cleanup;
 	master->setup = setup;
 	master->transfer_one_message = pxa2xx_spi_transfer_one_message;
-	master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
 	master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
+	master->auto_runtime_pm = true;
 
 	drv_data->ssp_type = ssp->type;
 	drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index b44a6ac..5f122d9 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -664,12 +664,13 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
 static int rspi_request_dma(struct rspi_data *rspi,
 				      struct platform_device *pdev)
 {
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
 	dma_cap_mask_t mask;
 	struct dma_slave_config cfg;
 	int ret;
 
-	if (!rspi_pd)
+	if (!res || !rspi_pd)
 		return 0;	/* The driver assumes no error. */
 
 	rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
@@ -683,6 +684,8 @@ static int rspi_request_dma(struct rspi_data *rspi,
 		if (rspi->chan_rx) {
 			cfg.slave_id = rspi_pd->dma_rx_id;
 			cfg.direction = DMA_DEV_TO_MEM;
+			cfg.dst_addr = 0;
+			cfg.src_addr = res->start + RSPI_SPDR;
 			ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
 			if (!ret)
 				dev_info(&pdev->dev, "Use DMA when rx.\n");
@@ -698,6 +701,8 @@ static int rspi_request_dma(struct rspi_data *rspi,
 		if (rspi->chan_tx) {
 			cfg.slave_id = rspi_pd->dma_tx_id;
 			cfg.direction = DMA_MEM_TO_DEV;
+			cfg.dst_addr = res->start + RSPI_SPDR;
+			cfg.src_addr = 0;
 			ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
 			if (!ret)
 				dev_info(&pdev->dev, "Use DMA when tx\n");
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 63e2070..62f32c4 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -172,7 +172,6 @@ struct s3c64xx_spi_port_config {
  * @master: Pointer to the SPI Protocol master.
  * @cntrlr_info: Platform specific data for the controller this driver manages.
  * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
- * @queue: To log SPI xfer requests.
  * @lock: Controller specific lock.
  * @state: Set of FLAGS to indicate status.
  * @rx_dmach: Controller's DMA channel for Rx.
@@ -193,7 +192,6 @@ struct s3c64xx_spi_driver_data {
 	struct spi_master               *master;
 	struct s3c64xx_spi_info  *cntrlr_info;
 	struct spi_device               *tgl_spi;
-	struct list_head                queue;
 	spinlock_t                      lock;
 	unsigned long                   sfr_start;
 	struct completion               xfer_completion;
@@ -338,8 +336,10 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
 	req.cap = DMA_SLAVE;
 	req.client = &s3c64xx_spi_dma_client;
 
-	sdd->rx_dma.ch = (void *)sdd->ops->request(sdd->rx_dma.dmach, &req, dev, "rx");
-	sdd->tx_dma.ch = (void *)sdd->ops->request(sdd->tx_dma.dmach, &req, dev, "tx");
+	sdd->rx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
+					sdd->rx_dma.dmach, &req, dev, "rx");
+	sdd->tx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
+					sdd->tx_dma.dmach, &req, dev, "tx");
 
 	return 1;
 }
@@ -356,8 +356,6 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 	while (!is_polling(sdd) && !acquire_dma(sdd))
 		usleep_range(10000, 11000);
 
-	pm_runtime_get_sync(&sdd->pdev->dev);
-
 	return 0;
 }
 
@@ -372,7 +370,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
 		sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
 					&s3c64xx_spi_dma_client);
 	}
-	pm_runtime_put(&sdd->pdev->dev);
 
 	return 0;
 }
@@ -442,7 +439,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 
 	/* Acquire DMA channels */
 	sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-				(void*)sdd->rx_dma.dmach, dev, "rx");
+				(void *)sdd->rx_dma.dmach, dev, "rx");
 	if (!sdd->rx_dma.ch) {
 		dev_err(dev, "Failed to get RX DMA channel\n");
 		ret = -EBUSY;
@@ -450,7 +447,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 	}
 
 	sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-				(void*)sdd->tx_dma.dmach, dev, "tx");
+				(void *)sdd->tx_dma.dmach, dev, "tx");
 	if (!sdd->tx_dma.ch) {
 		dev_err(dev, "Failed to get TX DMA channel\n");
 		ret = -EBUSY;
@@ -1056,8 +1053,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
 	struct s3c64xx_spi_driver_data *sdd;
 	struct s3c64xx_spi_info *sci;
-	struct spi_message *msg;
-	unsigned long flags;
 	int err;
 
 	sdd = spi_master_get_devdata(spi->master);
@@ -1088,21 +1083,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 
 	sci = sdd->cntrlr_info;
 
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	list_for_each_entry(msg, &sdd->queue, queue) {
-		/* Is some mssg is already queued for this device */
-		if (msg->spi == spi) {
-			dev_err(&spi->dev,
-				"setup: attempt while mssg in queue!\n");
-			spin_unlock_irqrestore(&sdd->lock, flags);
-			err = -EBUSY;
-			goto err_msgq;
-		}
-	}
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
 	pm_runtime_get_sync(&sdd->pdev->dev);
 
 	/* Check if we can provide the requested rate */
@@ -1149,7 +1129,6 @@ setup_exit:
 	/* setup() returns with device de-selected */
 	disable_cs(sdd, spi);
 
-err_msgq:
 	gpio_free(cs->line);
 	spi_set_ctldata(spi, NULL);
 
@@ -1364,16 +1343,14 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 	if (!sdd->pdev->dev.of_node) {
 		res = platform_get_resource(pdev, IORESOURCE_DMA,  0);
 		if (!res) {
-			dev_warn(&pdev->dev, "Unable to get SPI tx dma "
-					"resource. Switching to poll mode\n");
+			dev_warn(&pdev->dev, "Unable to get SPI tx dma resource. Switching to poll mode\n");
 			sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL;
 		} else
 			sdd->tx_dma.dmach = res->start;
 
 		res = platform_get_resource(pdev, IORESOURCE_DMA,  1);
 		if (!res) {
-			dev_warn(&pdev->dev, "Unable to get SPI rx dma "
-					"resource. Switching to poll mode\n");
+			dev_warn(&pdev->dev, "Unable to get SPI rx dma resource. Switching to poll mode\n");
 			sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL;
 		} else
 			sdd->rx_dma.dmach = res->start;
@@ -1395,6 +1372,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 					SPI_BPW_MASK(8);
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	master->auto_runtime_pm = true;
 
 	sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
 	if (IS_ERR(sdd->regs)) {
@@ -1442,7 +1420,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 
 	spin_lock_init(&sdd->lock);
 	init_completion(&sdd->xfer_completion);
-	INIT_LIST_HEAD(&sdd->queue);
 
 	ret = devm_request_irq(&pdev->dev, irq, s3c64xx_spi_irq, 0,
 				"spi-s3c64xx", sdd);
@@ -1464,8 +1441,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 
 	dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n",
 					sdd->port_id, master->num_chipselect);
-	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
-					mem_res->end, mem_res->start,
+	dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tDMA=[Rx-%d, Tx-%d]\n",
+					mem_res,
 					sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
 	pm_runtime_enable(&pdev->dev);
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 716edf9..0b68cb5 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -99,21 +99,6 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
 /*
  *		spi master function
  */
-static int hspi_prepare_transfer(struct spi_master *master)
-{
-	struct hspi_priv *hspi = spi_master_get_devdata(master);
-
-	pm_runtime_get_sync(hspi->dev);
-	return 0;
-}
-
-static int hspi_unprepare_transfer(struct spi_master *master)
-{
-	struct hspi_priv *hspi = spi_master_get_devdata(master);
-
-	pm_runtime_put_sync(hspi->dev);
-	return 0;
-}
 
 #define hspi_hw_cs_enable(hspi)		hspi_hw_cs_ctrl(hspi, 0)
 #define hspi_hw_cs_disable(hspi)	hspi_hw_cs_ctrl(hspi, 1)
@@ -316,9 +301,8 @@ static int hspi_probe(struct platform_device *pdev)
 	master->setup		= hspi_setup;
 	master->cleanup		= hspi_cleanup;
 	master->mode_bits	= SPI_CPOL | SPI_CPHA;
-	master->prepare_transfer_hardware	= hspi_prepare_transfer;
+	master->auto_runtime_pm = true;
 	master->transfer_one_message		= hspi_transfer_one_message;
-	master->unprepare_transfer_hardware	= hspi_unprepare_transfer;
 	ret = spi_register_master(master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "spi_register_master error.\n");
@@ -327,8 +311,6 @@ static int hspi_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(&pdev->dev);
 
-	dev_info(&pdev->dev, "probed\n");
-
 	return 0;
 
  error1:
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 2bc5a6b..6688ce7 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -745,18 +745,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
 	return ret;
 }
 
-static int sh_msiof_spi_runtime_nop(struct device *dev)
-{
-	/* Runtime PM callback shared between ->runtime_suspend()
-	 * and ->runtime_resume(). Simply returns success.
-	 *
-	 * This driver re-initializes all registers after
-	 * pm_runtime_get_sync() anyway so there is no need
-	 * to save and restore registers here.
-	 */
-	return 0;
-}
-
 #ifdef CONFIG_OF
 static const struct of_device_id sh_msiof_match[] = {
 	{ .compatible = "renesas,sh-msiof", },
@@ -766,18 +754,12 @@ static const struct of_device_id sh_msiof_match[] = {
 MODULE_DEVICE_TABLE(of, sh_msiof_match);
 #endif
 
-static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
-	.runtime_suspend = sh_msiof_spi_runtime_nop,
-	.runtime_resume = sh_msiof_spi_runtime_nop,
-};
-
 static struct platform_driver sh_msiof_spi_drv = {
 	.probe		= sh_msiof_spi_probe,
 	.remove		= sh_msiof_spi_remove,
 	.driver		= {
 		.name		= "spi_sh_msiof",
 		.owner		= THIS_MODULE,
-		.pm		= &sh_msiof_spi_dev_pm_ops,
 		.of_match_table = of_match_ptr(sh_msiof_match),
 	},
 };
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index fc20bcf..62c92c3 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -19,6 +19,10 @@
 #include <linux/of_gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
+#include <linux/sirfsoc_dma.h>
 
 #define DRIVER_NAME "sirfsoc_spi"
 
@@ -119,9 +123,20 @@
 #define SIRFSOC_SPI_FIFO_HC(x)		(((x) & 0x3F) << 20)
 #define SIRFSOC_SPI_FIFO_THD(x)		(((x) & 0xFF) << 2)
 
+/*
+ * only if the rx/tx buffer and transfer size are 4-bytes aligned, we use dma
+ * due to the limitation of dma controller
+ */
+
+#define ALIGNED(x) (!((u32)x & 0x3))
+#define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \
+	ALIGNED(x->len * sspi->word_width) && (x->len * sspi->word_width < \
+		2 * PAGE_SIZE))
+
 struct sirfsoc_spi {
 	struct spi_bitbang bitbang;
-	struct completion done;
+	struct completion rx_done;
+	struct completion tx_done;
 
 	void __iomem *base;
 	u32 ctrl_freq;  /* SPI controller clock speed */
@@ -140,6 +155,14 @@ struct sirfsoc_spi {
 	unsigned int left_tx_cnt;
 	unsigned int left_rx_cnt;
 
+	/* rx & tx DMA channels */
+	struct dma_chan *rx_chan;
+	struct dma_chan *tx_chan;
+	dma_addr_t src_start;
+	dma_addr_t dst_start;
+	void *dummypage;
+	int word_width; /* in bytes */
+
 	int chipselect[0];
 };
 
@@ -241,7 +264,7 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
 	/* Error Conditions */
 	if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
 			spi_stat & SIRFSOC_SPI_TX_UFLOW) {
-		complete(&sspi->done);
+		complete(&sspi->rx_done);
 		writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
 	}
 
@@ -261,22 +284,30 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
 
 	/* Received all words */
 	if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) {
-		complete(&sspi->done);
+		complete(&sspi->rx_done);
 		writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
 	}
 	return IRQ_HANDLED;
 }
 
+static void spi_sirfsoc_dma_fini_callback(void *data)
+{
+	struct completion *dma_complete = data;
+
+	complete(dma_complete);
+}
+
 static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
 {
 	struct sirfsoc_spi *sspi;
 	int timeout = t->len * 10;
 	sspi = spi_master_get_devdata(spi->master);
 
-	sspi->tx = t->tx_buf;
-	sspi->rx = t->rx_buf;
+	sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage;
+	sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage;
 	sspi->left_tx_cnt = sspi->left_rx_cnt = t->len;
-	INIT_COMPLETION(sspi->done);
+	INIT_COMPLETION(sspi->rx_done);
+	INIT_COMPLETION(sspi->tx_done);
 
 	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
 
@@ -305,17 +336,65 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
 	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
 	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
 
-	/* Send the first word to trigger the whole tx/rx process */
-	sspi->tx_word(sspi);
+	if (IS_DMA_VALID(t)) {
+		struct dma_async_tx_descriptor *rx_desc, *tx_desc;
+		unsigned int size = t->len * sspi->word_width;
+
+		sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, DMA_FROM_DEVICE);
+		rx_desc = dmaengine_prep_slave_single(sspi->rx_chan,
+			sspi->dst_start, size, DMA_DEV_TO_MEM,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		rx_desc->callback = spi_sirfsoc_dma_fini_callback;
+		rx_desc->callback_param = &sspi->rx_done;
+
+		sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, DMA_TO_DEVICE);
+		tx_desc = dmaengine_prep_slave_single(sspi->tx_chan,
+			sspi->src_start, size, DMA_MEM_TO_DEV,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		tx_desc->callback = spi_sirfsoc_dma_fini_callback;
+		tx_desc->callback_param = &sspi->tx_done;
+
+		dmaengine_submit(tx_desc);
+		dmaengine_submit(rx_desc);
+		dma_async_issue_pending(sspi->tx_chan);
+		dma_async_issue_pending(sspi->rx_chan);
+	} else {
+		/* Send the first word to trigger the whole tx/rx process */
+		sspi->tx_word(sspi);
+
+		writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
+			SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
+			SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
+			SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
+	}
 
-	writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
-		SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
-		SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
-		SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
 	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN);
 
-	if (wait_for_completion_timeout(&sspi->done, timeout) == 0)
+	if (!IS_DMA_VALID(t)) { /* for PIO */
+		if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0)
+			dev_err(&spi->dev, "transfer timeout\n");
+	} else if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
 		dev_err(&spi->dev, "transfer timeout\n");
+		dmaengine_terminate_all(sspi->rx_chan);
+	} else
+		sspi->left_rx_cnt = 0;
+
+	/*
+	 * we only wait tx-done event if transferring by DMA. for PIO,
+	 * we get rx data by writing tx data, so if rx is done, tx has
+	 * done earlier
+	 */
+	if (IS_DMA_VALID(t)) {
+		if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
+			dev_err(&spi->dev, "transfer timeout\n");
+			dmaengine_terminate_all(sspi->tx_chan);
+		}
+	}
+
+	if (IS_DMA_VALID(t)) {
+		dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE);
+		dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);
+	}
 
 	/* TX, RX FIFO stop */
 	writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
@@ -332,7 +411,6 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
 
 	if (sspi->chipselect[spi->chip_select] == 0) {
 		u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL);
-		regval |= SIRFSOC_SPI_CS_IO_OUT;
 		switch (value) {
 		case BITBANG_CS_ACTIVE:
 			if (spi->mode & SPI_CS_HIGH)
@@ -369,11 +447,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
 	hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz;
 
-	/* Enable IO mode for RX, TX */
-	writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
-	writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
 	regval = (sspi->ctrl_freq / (2 * hz)) - 1;
-
 	if (regval > 0xFFFF || regval < 0) {
 		dev_err(&spi->dev, "Speed %d not supported\n", hz);
 		return -EINVAL;
@@ -388,6 +462,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 					SIRFSOC_SPI_FIFO_WIDTH_BYTE;
 		rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
 					SIRFSOC_SPI_FIFO_WIDTH_BYTE;
+		sspi->word_width = 1;
 		break;
 	case 12:
 	case 16:
@@ -399,6 +474,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 					SIRFSOC_SPI_FIFO_WIDTH_WORD;
 		rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
 					SIRFSOC_SPI_FIFO_WIDTH_WORD;
+		sspi->word_width = 2;
 		break;
 	case 32:
 		regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
@@ -408,6 +484,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 					SIRFSOC_SPI_FIFO_WIDTH_DWORD;
 		rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
 					SIRFSOC_SPI_FIFO_WIDTH_DWORD;
+		sspi->word_width = 4;
 		break;
 	default:
 		BUG();
@@ -442,6 +519,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 	writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL);
 
 	writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
+
+	if (IS_DMA_VALID(t)) {
+		/* Enable DMA mode for RX, TX */
+		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
+		writel(SIRFSOC_SPI_RX_DMA_FLUSH, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
+	} else {
+		/* Enable IO mode for RX, TX */
+		writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
+		writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
+	}
+
 	return 0;
 }
 
@@ -466,6 +554,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 	struct spi_master *master;
 	struct resource *mem_res;
 	int num_cs, cs_gpio, irq;
+	u32 rx_dma_ch, tx_dma_ch;
+	dma_cap_mask_t dma_cap_mask;
 	int i;
 	int ret;
 
@@ -476,6 +566,20 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 		goto err_cs;
 	}
 
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"sirf,spi-dma-rx-channel", &rx_dma_ch);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to get rx dma channel\n");
+		goto err_cs;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"sirf,spi-dma-tx-channel", &tx_dma_ch);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to get tx dma channel\n");
+		goto err_cs;
+	}
+
 	master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs);
 	if (!master) {
 		dev_err(&pdev->dev, "Unable to allocate SPI master\n");
@@ -538,19 +642,38 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 	sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
 	sspi->bitbang.master->setup = spi_sirfsoc_setup;
 	master->bus_num = pdev->id;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
 	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
 					SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
 	sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
 
+	/* request DMA channels */
+	dma_cap_zero(dma_cap_mask);
+	dma_cap_set(DMA_INTERLEAVE, dma_cap_mask);
+
+	sspi->rx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
+		(void *)rx_dma_ch);
+	if (!sspi->rx_chan) {
+		dev_err(&pdev->dev, "can not allocate rx dma channel\n");
+		goto free_master;
+	}
+	sspi->tx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
+		(void *)tx_dma_ch);
+	if (!sspi->tx_chan) {
+		dev_err(&pdev->dev, "can not allocate tx dma channel\n");
+		goto free_rx_dma;
+	}
+
 	sspi->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(sspi->clk)) {
-		ret = -EINVAL;
-		goto free_master;
+		ret = PTR_ERR(sspi->clk);
+		goto free_tx_dma;
 	}
 	clk_prepare_enable(sspi->clk);
 	sspi->ctrl_freq = clk_get_rate(sspi->clk);
 
-	init_completion(&sspi->done);
+	init_completion(&sspi->rx_done);
+	init_completion(&sspi->tx_done);
 
 	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
 	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
@@ -559,17 +682,26 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 	/* We are not using dummy delay between command and data */
 	writel(0, sspi->base + SIRFSOC_SPI_DUMMY_DELAY_CTL);
 
+	sspi->dummypage = kmalloc(2 * PAGE_SIZE, GFP_KERNEL);
+	if (!sspi->dummypage)
+		goto free_clk;
+
 	ret = spi_bitbang_start(&sspi->bitbang);
 	if (ret)
-		goto free_clk;
+		goto free_dummypage;
 
 	dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num);
 
 	return 0;
-
+free_dummypage:
+	kfree(sspi->dummypage);
 free_clk:
 	clk_disable_unprepare(sspi->clk);
 	clk_put(sspi->clk);
+free_tx_dma:
+	dma_release_channel(sspi->tx_chan);
+free_rx_dma:
+	dma_release_channel(sspi->rx_chan);
 free_master:
 	spi_master_put(master);
 err_cs:
@@ -590,8 +722,11 @@ static int  spi_sirfsoc_remove(struct platform_device *pdev)
 		if (sspi->chipselect[i] > 0)
 			gpio_free(sspi->chipselect[i]);
 	}
+	kfree(sspi->dummypage);
 	clk_disable_unprepare(sspi->clk);
 	clk_put(sspi->clk);
+	dma_release_channel(sspi->rx_chan);
+	dma_release_channel(sspi->tx_chan);
 	spi_master_put(master);
 	return 0;
 }
diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index e8f542a..2e208dc 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -816,14 +816,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
 	msg->status = 0;
 	msg->actual_length = 0;
 
-	ret = pm_runtime_get_sync(tspi->dev);
-	if (ret < 0) {
-		dev_err(tspi->dev, "runtime PM get failed: %d\n", ret);
-		msg->status = ret;
-		spi_finalize_current_message(master);
-		return ret;
-	}
-
 	single_xfer = list_is_singular(&msg->transfers);
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		INIT_COMPLETION(tspi->xfer_completion);
@@ -859,7 +851,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
 	ret = 0;
 exit:
 	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
-	pm_runtime_put(tspi->dev);
 	msg->status = ret;
 	spi_finalize_current_message(master);
 	return ret;
@@ -1053,6 +1044,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
 	master->transfer_one_message = tegra_spi_transfer_one_message;
 	master->num_chipselect = MAX_CHIP_SELECT;
 	master->bus_num = -1;
+	master->auto_runtime_pm = true;
 
 	tspi->master = master;
 	tspi->dev = &pdev->dev;
@@ -1068,7 +1060,6 @@ static int tegra_spi_probe(struct platform_device *pdev)
 	tspi->base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(tspi->base)) {
 		ret = PTR_ERR(tspi->base);
-		dev_err(&pdev->dev, "ioremap failed: err = %d\n", ret);
 		goto exit_free_master;
 	}
 
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index c1d5d95..1d814dc 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -335,12 +335,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
 	struct spi_device *spi = msg->spi;
 	int ret;
 
-	ret = pm_runtime_get_sync(tsd->dev);
-	if (ret < 0) {
-		dev_err(tsd->dev, "pm_runtime_get() failed, err = %d\n", ret);
-		return ret;
-	}
-
 	msg->status = 0;
 	msg->actual_length = 0;
 	single_xfer = list_is_singular(&msg->transfers);
@@ -380,7 +374,6 @@ exit:
 	tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
 	msg->status = ret;
 	spi_finalize_current_message(master);
-	pm_runtime_put(tsd->dev);
 	return ret;
 }
 
@@ -477,6 +470,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
 	master->mode_bits = SPI_CPOL | SPI_CPHA;
 	master->setup = tegra_sflash_setup;
 	master->transfer_one_message = tegra_sflash_transfer_one_message;
+	master->auto_runtime_pm = true;
 	master->num_chipselect = MAX_CHIP_SELECT;
 	master->bus_num = -1;
 
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index 80490cc..c703536 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -836,11 +836,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 
 	msg->status = 0;
 	msg->actual_length = 0;
-	ret = pm_runtime_get_sync(tspi->dev);
-	if (ret < 0) {
-		dev_err(tspi->dev, "runtime get failed: %d\n", ret);
-		goto done;
-	}
 
 	single_xfer = list_is_singular(&msg->transfers);
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
@@ -878,8 +873,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 exit:
 	tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
 	tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
-	pm_runtime_put(tspi->dev);
-done:
 	msg->status = ret;
 	spi_finalize_current_message(master);
 	return ret;
@@ -1086,6 +1079,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->setup = tegra_slink_setup;
 	master->transfer_one_message = tegra_slink_transfer_one_message;
+	master->auto_runtime_pm = true;
 	master->num_chipselect = MAX_CHIP_SELECT;
 	master->bus_num = -1;
 
diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c
index 6b0874d..3e528c0 100644
--- a/drivers/spi/spi-tle62x0.c
+++ b/drivers/spi/spi-tle62x0.c
@@ -52,8 +52,7 @@ static inline int tle62x0_write(struct tle62x0_state *st)
 		buff[1] = gpio_state;
 	}
 
-	dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
-		buff[0], buff[1], buff[2]);
+	dev_dbg(&st->us->dev, "buff %3ph\n", buff);
 
 	return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
 }
diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c
index e9b7681..7c6d157 100644
--- a/drivers/spi/spi-txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -26,7 +26,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 
 #define SPI_FIFO_SIZE 4
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 09a9428..0f4a093 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -80,10 +80,9 @@ struct xilinx_spi {
 	/* bitbang has to be first */
 	struct spi_bitbang bitbang;
 	struct completion done;
-	struct resource mem; /* phys mem */
 	void __iomem	*regs;	/* virt. address of the control registers */
 
-	u32		irq;
+	int		irq;
 
 	u8 *rx_ptr;		/* pointer in the Tx buffer */
 	const u8 *tx_ptr;	/* pointer in the Rx buffer */
@@ -355,17 +354,34 @@ static const struct of_device_id xilinx_spi_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
 
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-	u32 irq, s16 bus_num, int num_cs, int bits_per_word)
+static int xilinx_spi_probe(struct platform_device *pdev)
 {
-	struct spi_master *master;
 	struct xilinx_spi *xspi;
-	int ret;
+	struct xspi_platform_data *pdata;
+	struct resource *res;
+	int ret, num_cs = 0, bits_per_word = 8;
+	struct spi_master *master;
 	u32 tmp;
+	u8 i;
+
+	pdata = pdev->dev.platform_data;
+	if (pdata) {
+		num_cs = pdata->num_chipselect;
+		bits_per_word = pdata->bits_per_word;
+	} else {
+		of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
+					  &num_cs);
+	}
 
-	master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
+	if (!num_cs) {
+		dev_err(&pdev->dev,
+			"Missing slave select configuration data\n");
+		return -EINVAL;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi));
 	if (!master)
-		return NULL;
+		return -ENODEV;
 
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA;
@@ -378,22 +394,16 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 	xspi->bitbang.master->setup = xilinx_spi_setup;
 	init_completion(&xspi->done);
 
-	if (!request_mem_region(mem->start, resource_size(mem),
-		XILINX_SPI_NAME))
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xspi->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(xspi->regs)) {
+		ret = PTR_ERR(xspi->regs);
 		goto put_master;
-
-	xspi->regs = ioremap(mem->start, resource_size(mem));
-	if (xspi->regs == NULL) {
-		dev_warn(dev, "ioremap failure\n");
-		goto map_failed;
 	}
 
-	master->bus_num = bus_num;
+	master->bus_num = pdev->dev.id;
 	master->num_chipselect = num_cs;
-	master->dev.of_node = dev->of_node;
-
-	xspi->mem = *mem;
-	xspi->irq = irq;
+	master->dev.of_node = pdev->dev.of_node;
 
 	/*
 	 * Detect endianess on the IP via loop bit in CR. Detection
@@ -423,113 +433,63 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 	} else if (xspi->bits_per_word == 32) {
 		xspi->tx_fn = xspi_tx32;
 		xspi->rx_fn = xspi_rx32;
-	} else
-		goto unmap_io;
-
+	} else {
+		ret = -EINVAL;
+		goto put_master;
+	}
 
 	/* SPI controller initializations */
 	xspi_init_hw(xspi);
 
+	xspi->irq = platform_get_irq(pdev, 0);
+	if (xspi->irq < 0) {
+		ret = xspi->irq;
+		goto put_master;
+	}
+
 	/* Register for SPI Interrupt */
-	ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+	ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
+			       dev_name(&pdev->dev), xspi);
 	if (ret)
-		goto unmap_io;
+		goto put_master;
 
 	ret = spi_bitbang_start(&xspi->bitbang);
 	if (ret) {
-		dev_err(dev, "spi_bitbang_start FAILED\n");
-		goto free_irq;
-	}
-
-	dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
-		(unsigned long long)mem->start, xspi->regs, xspi->irq);
-	return master;
-
-free_irq:
-	free_irq(xspi->irq, xspi);
-unmap_io:
-	iounmap(xspi->regs);
-map_failed:
-	release_mem_region(mem->start, resource_size(mem));
-put_master:
-	spi_master_put(master);
-	return NULL;
-}
-EXPORT_SYMBOL(xilinx_spi_init);
-
-void xilinx_spi_deinit(struct spi_master *master)
-{
-	struct xilinx_spi *xspi;
-
-	xspi = spi_master_get_devdata(master);
-
-	spi_bitbang_stop(&xspi->bitbang);
-	free_irq(xspi->irq, xspi);
-	iounmap(xspi->regs);
-
-	release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
-	spi_master_put(xspi->bitbang.master);
-}
-EXPORT_SYMBOL(xilinx_spi_deinit);
-
-static int xilinx_spi_probe(struct platform_device *dev)
-{
-	struct xspi_platform_data *pdata;
-	struct resource *r;
-	int irq, num_cs = 0, bits_per_word = 8;
-	struct spi_master *master;
-	u8 i;
-
-	pdata = dev->dev.platform_data;
-	if (pdata) {
-		num_cs = pdata->num_chipselect;
-		bits_per_word = pdata->bits_per_word;
-	}
-
-#ifdef CONFIG_OF
-	if (dev->dev.of_node) {
-		const __be32 *prop;
-		int len;
-
-		/* number of slave select bits is required */
-		prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
-				       &len);
-		if (prop && len >= sizeof(*prop))
-			num_cs = __be32_to_cpup(prop);
-	}
-#endif
-
-	if (!num_cs) {
-		dev_err(&dev->dev, "Missing slave select configuration data\n");
-		return -EINVAL;
+		dev_err(&pdev->dev, "spi_bitbang_start FAILED\n");
+		goto put_master;
 	}
 
-
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -ENODEV;
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0)
-		return -ENXIO;
-
-	master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
-				 bits_per_word);
-	if (!master)
-		return -ENODEV;
+	dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
+		(unsigned long long)res->start, xspi->regs, xspi->irq);
 
 	if (pdata) {
 		for (i = 0; i < pdata->num_devices; i++)
 			spi_new_device(master, pdata->devices + i);
 	}
 
-	platform_set_drvdata(dev, master);
+	platform_set_drvdata(pdev, master);
 	return 0;
+
+put_master:
+	spi_master_put(master);
+
+	return ret;
 }
 
-static int xilinx_spi_remove(struct platform_device *dev)
+static int xilinx_spi_remove(struct platform_device *pdev)
 {
-	xilinx_spi_deinit(platform_get_drvdata(dev));
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct xilinx_spi *xspi = spi_master_get_devdata(master);
+	void __iomem *regs_base = xspi->regs;
+
+	spi_bitbang_stop(&xspi->bitbang);
+
+	/* Disable all the interrupts just in case */
+	xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
+	/* Disable the global IPIF interrupt */
+	xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
+
+	spi_master_put(xspi->bitbang.master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 978dda2..61f71b9 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work)
 		    master->unprepare_transfer_hardware(master))
 			dev_err(&master->dev,
 				"failed to unprepare transfer hardware\n");
+		if (master->auto_runtime_pm) {
+			pm_runtime_mark_last_busy(master->dev.parent);
+			pm_runtime_put_autosuspend(master->dev.parent);
+		}
 		return;
 	}
 
@@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work)
 		master->busy = true;
 	spin_unlock_irqrestore(&master->queue_lock, flags);
 
+	if (!was_busy && master->auto_runtime_pm) {
+		ret = pm_runtime_get_sync(master->dev.parent);
+		if (ret < 0) {
+			dev_err(&master->dev, "Failed to power device: %d\n",
+				ret);
+			return;
+		}
+	}
+
 	if (!was_busy && master->prepare_transfer_hardware) {
 		ret = master->prepare_transfer_hardware(master);
 		if (ret) {
 			dev_err(&master->dev,
 				"failed to prepare transfer hardware\n");
+
+			if (master->auto_runtime_pm)
+				pm_runtime_put(master->dev.parent);
 			return;
 		}
 	}
@@ -1351,6 +1367,11 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 	struct spi_master *master = spi->master;
 	struct spi_transfer *xfer;
 
+	if (list_empty(&message->transfers))
+		return -EINVAL;
+	if (!message->complete)
+		return -EINVAL;
+
 	/* Half-duplex links include original MicroWire, and ones with
 	 * only one data pin like SPI_3WIRE (switches direction) or where
 	 * either MOSI or MISO is missing.  They can also be caused by
@@ -1375,6 +1396,7 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 	 * it is not set for this transfer.
 	 */
 	list_for_each_entry(xfer, &message->transfers, transfer_list) {
+		message->frame_length += xfer->len;
 		if (!xfer->bits_per_word)
 			xfer->bits_per_word = spi->bits_per_word;
 		if (!xfer->speed_hz)
@@ -1387,6 +1409,13 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 					BIT(xfer->bits_per_word - 1)))
 				return -EINVAL;
 		}
+
+		if (xfer->speed_hz && master->min_speed_hz &&
+		    xfer->speed_hz < master->min_speed_hz)
+			return -EINVAL;
+		if (xfer->speed_hz && master->max_speed_hz &&
+		    xfer->speed_hz > master->max_speed_hz)
+			return -EINVAL;
 	}
 
 	message->spi = spi;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 911e9e0..ca5bcfe 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -603,7 +603,7 @@ static int spidev_probe(struct spi_device *spi)
 		dev = device_create(spidev_class, &spi->dev, spidev->devt,
 				    spidev, "spidev%d.%d",
 				    spi->master->bus_num, spi->chip_select);
-		status = PTR_RET(dev);
+		status = PTR_ERR_OR_ZERO(dev);
 	} else {
 		dev_dbg(&spi->dev, "no minor number available!\n");
 		status = -ENODEV;
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 36171fd..2cd9b0e 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -138,7 +138,7 @@ config SSB_DRIVER_MIPS
 
 config SSB_SFLASH
 	bool "SSB serial flash support"
-	depends on SSB_DRIVER_MIPS && BROKEN
+	depends on SSB_DRIVER_MIPS
 	default y
 
 # Assumption: We are on embedded, if we compile the MIPS core.
diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c
index e84cf04..50328de 100644
--- a/drivers/ssb/driver_chipcommon_sflash.c
+++ b/drivers/ssb/driver_chipcommon_sflash.c
@@ -151,8 +151,8 @@ int ssb_sflash_init(struct ssb_chipcommon *cc)
 	sflash->size = sflash->blocksize * sflash->numblocks;
 	sflash->present = true;
 
-	pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n",
-		e->name, e->blocksize, e->numblocks);
+	pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
+		e->name, sflash->size / 1024, e->blocksize, e->numblocks);
 
 	/* Prepare platform device, but don't register it yet. It's too early,
 	 * malloc (required by device_private_init) is not available yet. */
@@ -160,7 +160,5 @@ int ssb_sflash_init(struct ssb_chipcommon *cc)
 					 sflash->size;
 	ssb_sflash_dev.dev.platform_data = sflash;
 
-	pr_err("Serial flash support is not implemented yet!\n");
-
-	return -ENOTSUPP;
+	return 0;
 }
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 57d8b34..869c488 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -40,8 +40,6 @@ source "drivers/staging/comedi/Kconfig"
 
 source "drivers/staging/olpc_dcon/Kconfig"
 
-source "drivers/staging/asus_oled/Kconfig"
-
 source "drivers/staging/panel/Kconfig"
 
 source "drivers/staging/rtl8187se/Kconfig"
@@ -118,6 +116,8 @@ source "drivers/staging/ozwpan/Kconfig"
 
 source "drivers/staging/gdm72xx/Kconfig"
 
+source "drivers/staging/gdm724x/Kconfig"
+
 source "drivers/staging/silicom/Kconfig"
 
 source "drivers/staging/ced1401/Kconfig"
@@ -142,4 +142,6 @@ source "drivers/staging/lustre/Kconfig"
 
 source "drivers/staging/btmtk_usb/Kconfig"
 
+source "drivers/staging/xillybus/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 429321f..ca14ab70 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB)	+= wlan-ng/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_FB_OLPC_DCON)	+= olpc_dcon/
-obj-$(CONFIG_ASUS_OLED)		+= asus_oled/
 obj-$(CONFIG_PANEL)		+= panel/
 obj-$(CONFIG_R8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192U)		+= rtl8192u/
@@ -52,6 +51,7 @@ obj-$(CONFIG_MFD_NVEC)		+= nvec/
 obj-$(CONFIG_ANDROID)		+= android/
 obj-$(CONFIG_USB_WPAN_HCD)	+= ozwpan/
 obj-$(CONFIG_WIMAX_GDM72XX)	+= gdm72xx/
+obj-$(CONFIG_LTE_GDM724X)	+= gdm724x/
 obj-$(CONFIG_NET_VENDOR_SILICOM)	+= silicom/
 obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
@@ -63,3 +63,4 @@ obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_USB_DWC2)		+= dwc2/
 obj-$(CONFIG_LUSTRE_FS)		+= lustre/
 obj-$(CONFIG_USB_BTMTK)		+= btmtk_usb/
+obj-$(CONFIG_XILLYBUS)		+= xillybus/
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 21a3f72..8e76ddc 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -341,27 +341,26 @@ out:
 /*
  * ashmem_shrink - our cache shrinker, called from mm/vmscan.c :: shrink_slab
  *
- * 'nr_to_scan' is the number of objects (pages) to prune, or 0 to query how
- * many objects (pages) we have in total.
+ * 'nr_to_scan' is the number of objects to scan for freeing.
  *
  * 'gfp_mask' is the mask of the allocation that got us into this mess.
  *
- * Return value is the number of objects (pages) remaining, or -1 if we cannot
+ * Return value is the number of objects freed or -1 if we cannot
  * proceed without risk of deadlock (due to gfp_mask).
  *
  * We approximate LRU via least-recently-unpinned, jettisoning unpinned partial
  * chunks of ashmem regions LRU-wise one-at-a-time until we hit 'nr_to_scan'
  * pages freed.
  */
-static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
+static unsigned long
+ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	struct ashmem_range *range, *next;
+	unsigned long freed = 0;
 
 	/* We might recurse into filesystem code, so bail out if necessary */
-	if (sc->nr_to_scan && !(sc->gfp_mask & __GFP_FS))
-		return -1;
-	if (!sc->nr_to_scan)
-		return lru_count;
+	if (!(sc->gfp_mask & __GFP_FS))
+		return SHRINK_STOP;
 
 	mutex_lock(&ashmem_mutex);
 	list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
@@ -374,17 +373,32 @@ static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
 		range->purged = ASHMEM_WAS_PURGED;
 		lru_del(range);
 
-		sc->nr_to_scan -= range_size(range);
-		if (sc->nr_to_scan <= 0)
+		freed += range_size(range);
+		if (--sc->nr_to_scan <= 0)
 			break;
 	}
 	mutex_unlock(&ashmem_mutex);
+	return freed;
+}
 
+static unsigned long
+ashmem_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+	/*
+	 * note that lru_count is count of pages on the lru, not a count of
+	 * objects on the list. This means the scan function needs to return the
+	 * number of pages freed, not the number of objects scanned.
+	 */
 	return lru_count;
 }
 
 static struct shrinker ashmem_shrinker = {
-	.shrink = ashmem_shrink,
+	.count_objects = ashmem_shrink_count,
+	.scan_objects = ashmem_shrink_scan,
+	/*
+	 * XXX (dchinner): I wish people would comment on why they need on
+	 * significant changes to the default value here
+	 */
 	.seeks = DEFAULT_SEEKS * 4,
 };
 
@@ -690,11 +704,11 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if (capable(CAP_SYS_ADMIN)) {
 			struct shrink_control sc = {
 				.gfp_mask = GFP_KERNEL,
-				.nr_to_scan = 0,
+				.nr_to_scan = LONG_MAX,
 			};
-			ret = ashmem_shrink(&ashmem_shrinker, &sc);
-			sc.nr_to_scan = ret;
-			ashmem_shrink(&ashmem_shrinker, &sc);
+
+			nodes_setall(sc.nodes_to_scan);
+			ashmem_shrink_scan(&ashmem_shrinker, &sc);
 		}
 		break;
 	}
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 119d486..98ac020 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -1248,7 +1248,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		struct flat_binder_object *fp;
 		if (*offp > buffer->data_size - sizeof(*fp) ||
 		    buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(void *))) {
+		    !IS_ALIGNED(*offp, sizeof(u32))) {
 			pr_err("transaction release %d bad offset %zd, size %zd\n",
 			 debug_id, *offp, buffer->data_size);
 			continue;
@@ -1272,7 +1272,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		case BINDER_TYPE_WEAK_HANDLE: {
 			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
 			if (ref == NULL) {
-				pr_err("transaction release %d bad handle %ld\n",
+				pr_err("transaction release %d bad handle %d\n",
 				 debug_id, fp->handle);
 				break;
 			}
@@ -1284,13 +1284,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 
 		case BINDER_TYPE_FD:
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %ld\n", fp->handle);
+				     "        fd %d\n", fp->handle);
 			if (failed_at)
 				task_close_fd(proc, fp->handle);
 			break;
 
 		default:
-			pr_err("transaction release %d bad object type %lx\n",
+			pr_err("transaction release %d bad object type %x\n",
 				debug_id, fp->type);
 			break;
 		}
@@ -1497,7 +1497,7 @@ static void binder_transaction(struct binder_proc *proc,
 		struct flat_binder_object *fp;
 		if (*offp > t->buffer->data_size - sizeof(*fp) ||
 		    t->buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(void *))) {
+		    !IS_ALIGNED(*offp, sizeof(u32))) {
 			binder_user_error("%d:%d got transaction with invalid offset, %zd\n",
 					proc->pid, thread->pid, *offp);
 			return_error = BR_FAILED_REPLY;
@@ -1548,7 +1548,7 @@ static void binder_transaction(struct binder_proc *proc,
 		case BINDER_TYPE_WEAK_HANDLE: {
 			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
 			if (ref == NULL) {
-				binder_user_error("%d:%d got transaction with invalid handle, %ld\n",
+				binder_user_error("%d:%d got transaction with invalid handle, %d\n",
 						proc->pid,
 						thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
@@ -1591,13 +1591,13 @@ static void binder_transaction(struct binder_proc *proc,
 
 			if (reply) {
 				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
-					binder_user_error("%d:%d got reply with fd, %ld, but target does not allow fds\n",
+					binder_user_error("%d:%d got reply with fd, %d, but target does not allow fds\n",
 						proc->pid, thread->pid, fp->handle);
 					return_error = BR_FAILED_REPLY;
 					goto err_fd_not_allowed;
 				}
 			} else if (!target_node->accept_fds) {
-				binder_user_error("%d:%d got transaction with fd, %ld, but target does not allow fds\n",
+				binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fds\n",
 					proc->pid, thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
 				goto err_fd_not_allowed;
@@ -1605,7 +1605,7 @@ static void binder_transaction(struct binder_proc *proc,
 
 			file = fget(fp->handle);
 			if (file == NULL) {
-				binder_user_error("%d:%d got transaction with invalid fd, %ld\n",
+				binder_user_error("%d:%d got transaction with invalid fd, %d\n",
 					proc->pid, thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
 				goto err_fget_failed;
@@ -1619,13 +1619,13 @@ static void binder_transaction(struct binder_proc *proc,
 			task_fd_install(target_proc, target_fd, file);
 			trace_binder_transaction_fd(t, fp->handle, target_fd);
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %ld -> %d\n", fp->handle, target_fd);
+				     "        fd %d -> %d\n", fp->handle, target_fd);
 			/* TODO: fput? */
 			fp->handle = target_fd;
 		} break;
 
 		default:
-			binder_user_error("%d:%d got transaction with invalid object type, %lx\n",
+			binder_user_error("%d:%d got transaction with invalid object type, %x\n",
 				proc->pid, thread->pid, fp->type);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_object_type;
@@ -1701,7 +1701,7 @@ err_no_context_mgr_node:
 }
 
 int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
-			void __user *buffer, int size, signed long *consumed)
+			void __user *buffer, size_t size, size_t *consumed)
 {
 	uint32_t cmd;
 	void __user *ptr = buffer + *consumed;
@@ -2081,8 +2081,8 @@ static int binder_has_thread_work(struct binder_thread *thread)
 
 static int binder_thread_read(struct binder_proc *proc,
 			      struct binder_thread *thread,
-			      void  __user *buffer, int size,
-			      signed long *consumed, int non_block)
+			      void  __user *buffer, size_t size,
+			      size_t *consumed, int non_block)
 {
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
@@ -2579,7 +2579,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			goto err;
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d write %ld at %08lx, read %ld at %08lx\n",
+			     "%d:%d write %zd at %016lx, read %zd at %016lx\n",
 			     proc->pid, thread->pid, bwr.write_size,
 			     bwr.write_buffer, bwr.read_size, bwr.read_buffer);
 
@@ -2605,7 +2605,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			}
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d wrote %ld of %ld, read return %ld of %ld\n",
+			     "%d:%d wrote %zd of %zd, read return %zd of %zd\n",
 			     proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
 			     bwr.read_consumed, bwr.read_size);
 		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
index dbe81ce..cbe3451 100644
--- a/drivers/staging/android/binder.h
+++ b/drivers/staging/android/binder.h
@@ -48,13 +48,13 @@ enum {
  */
 struct flat_binder_object {
 	/* 8 bytes for large_flat_header. */
-	unsigned long		type;
-	unsigned long		flags;
+	__u32		type;
+	__u32		flags;
 
 	/* 8 bytes of data. */
 	union {
 		void __user	*binder;	/* local object */
-		signed long	handle;		/* remote object */
+		__u32	    handle;		/* remote object */
 	};
 
 	/* extra data associated with local object */
@@ -67,18 +67,18 @@ struct flat_binder_object {
  */
 
 struct binder_write_read {
-	signed long	write_size;	/* bytes to write */
-	signed long	write_consumed;	/* bytes consumed by driver */
+	size_t write_size;	/* bytes to write */
+	size_t write_consumed;	/* bytes consumed by driver */
 	unsigned long	write_buffer;
-	signed long	read_size;	/* bytes to read */
-	signed long	read_consumed;	/* bytes consumed by driver */
+	size_t read_size;	/* bytes to read */
+	size_t read_consumed;	/* bytes consumed by driver */
 	unsigned long	read_buffer;
 };
 
 /* Use with BINDER_VERSION, driver fills in fields. */
 struct binder_version {
 	/* driver protocol version -- increment with incompatible change */
-	signed long	protocol_version;
+	__s32       protocol_version;
 };
 
 /* This is the current protocol version. */
@@ -86,7 +86,7 @@ struct binder_version {
 
 #define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
 #define	BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
-#define	BINDER_SET_MAX_THREADS		_IOW('b', 5, size_t)
+#define	BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
 #define	BINDER_SET_IDLE_PRIORITY	_IOW('b', 6, __s32)
 #define	BINDER_SET_CONTEXT_MGR		_IOW('b', 7, __s32)
 #define	BINDER_THREAD_EXIT		_IOW('b', 8, __s32)
@@ -119,14 +119,14 @@ struct binder_transaction_data {
 	 * identifying the target and contents of the transaction.
 	 */
 	union {
-		size_t	handle;	/* target descriptor of command transaction */
+		__u32	handle;	/* target descriptor of command transaction */
 		void	*ptr;	/* target descriptor of return transaction */
 	} target;
 	void		*cookie;	/* target object cookie */
-	unsigned int	code;		/* transaction command */
+	__u32		code;		/* transaction command */
 
 	/* General information about the transaction. */
-	unsigned int	flags;
+	__u32	        flags;
 	pid_t		sender_pid;
 	uid_t		sender_euid;
 	size_t		data_size;	/* number of bytes of data */
@@ -143,7 +143,7 @@ struct binder_transaction_data {
 			/* offsets from buffer to flat_binder_object structs */
 			const void __user	*offsets;
 		} ptr;
-		uint8_t	buf[8];
+		__u8	buf[8];
 	} data;
 };
 
@@ -153,18 +153,18 @@ struct binder_ptr_cookie {
 };
 
 struct binder_pri_desc {
-	int priority;
-	int desc;
+	__s32 priority;
+	__u32 desc;
 };
 
 struct binder_pri_ptr_cookie {
-	int priority;
+	__s32 priority;
 	void *ptr;
 	void *cookie;
 };
 
 enum binder_driver_return_protocol {
-	BR_ERROR = _IOR('r', 0, int),
+	BR_ERROR = _IOR('r', 0, __s32),
 	/*
 	 * int: error code
 	 */
@@ -178,7 +178,7 @@ enum binder_driver_return_protocol {
 	 * binder_transaction_data: the received command.
 	 */
 
-	BR_ACQUIRE_RESULT = _IOR('r', 4, int),
+	BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
 	/*
 	 * not currently supported
 	 * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
@@ -258,22 +258,22 @@ enum binder_driver_command_protocol {
 	 * binder_transaction_data: the sent command.
 	 */
 
-	BC_ACQUIRE_RESULT = _IOW('c', 2, int),
+	BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
 	/*
 	 * not currently supported
 	 * int:  0 if the last BR_ATTEMPT_ACQUIRE was not successful.
 	 * Else you have acquired a primary reference on the object.
 	 */
 
-	BC_FREE_BUFFER = _IOW('c', 3, int),
+	BC_FREE_BUFFER = _IOW('c', 3, void *),
 	/*
 	 * void *: ptr to transaction data received on a read
 	 */
 
-	BC_INCREFS = _IOW('c', 4, int),
-	BC_ACQUIRE = _IOW('c', 5, int),
-	BC_RELEASE = _IOW('c', 6, int),
-	BC_DECREFS = _IOW('c', 7, int),
+	BC_INCREFS = _IOW('c', 4, __u32),
+	BC_ACQUIRE = _IOW('c', 5, __u32),
+	BC_RELEASE = _IOW('c', 6, __u32),
+	BC_DECREFS = _IOW('c', 7, __u32),
 	/*
 	 * int:	descriptor
 	 */
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index a8c3444..d42f578 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -481,7 +481,7 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	header.sec = now.tv_sec;
 	header.nsec = now.tv_nsec;
 	header.euid = current_euid();
-	header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
+	header.len = min_t(size_t, iocb->ki_nbytes, LOGGER_ENTRY_MAX_PAYLOAD);
 	header.hdr_size = sizeof(struct logger_entry);
 
 	/* null writes succeed, return zero */
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index fe74494..6f094b3 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -66,11 +66,20 @@ static unsigned long lowmem_deathpending_timeout;
 			pr_info(x);			\
 	} while (0)
 
-static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
+static unsigned long lowmem_count(struct shrinker *s,
+				  struct shrink_control *sc)
+{
+	return global_page_state(NR_ACTIVE_ANON) +
+		global_page_state(NR_ACTIVE_FILE) +
+		global_page_state(NR_INACTIVE_ANON) +
+		global_page_state(NR_INACTIVE_FILE);
+}
+
+static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
 {
 	struct task_struct *tsk;
 	struct task_struct *selected = NULL;
-	int rem = 0;
+	unsigned long rem = 0;
 	int tasksize;
 	int i;
 	short min_score_adj = OOM_SCORE_ADJ_MAX + 1;
@@ -92,19 +101,17 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 			break;
 		}
 	}
-	if (sc->nr_to_scan > 0)
-		lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %hd\n",
-				sc->nr_to_scan, sc->gfp_mask, other_free,
-				other_file, min_score_adj);
-	rem = global_page_state(NR_ACTIVE_ANON) +
-		global_page_state(NR_ACTIVE_FILE) +
-		global_page_state(NR_INACTIVE_ANON) +
-		global_page_state(NR_INACTIVE_FILE);
-	if (sc->nr_to_scan <= 0 || min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
-		lowmem_print(5, "lowmem_shrink %lu, %x, return %d\n",
-			     sc->nr_to_scan, sc->gfp_mask, rem);
-		return rem;
+
+	lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n",
+			sc->nr_to_scan, sc->gfp_mask, other_free,
+			other_file, min_score_adj);
+
+	if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
+		lowmem_print(5, "lowmem_scan %lu, %x, return 0\n",
+			     sc->nr_to_scan, sc->gfp_mask);
+		return 0;
 	}
+
 	selected_oom_score_adj = min_score_adj;
 
 	rcu_read_lock();
@@ -154,16 +161,18 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 		lowmem_deathpending_timeout = jiffies + HZ;
 		send_sig(SIGKILL, selected, 0);
 		set_tsk_thread_flag(selected, TIF_MEMDIE);
-		rem -= selected_tasksize;
+		rem += selected_tasksize;
 	}
-	lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
+
+	lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
 		     sc->nr_to_scan, sc->gfp_mask, rem);
 	rcu_read_unlock();
 	return rem;
 }
 
 static struct shrinker lowmem_shrinker = {
-	.shrink = lowmem_shrink,
+	.scan_objects = lowmem_scan,
+	.count_objects = lowmem_count,
 	.seeks = DEFAULT_SEEKS * 16
 };
 
diff --git a/drivers/staging/asus_oled/Kconfig b/drivers/staging/asus_oled/Kconfig
deleted file mode 100644
index e56dbb2..0000000
--- a/drivers/staging/asus_oled/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config ASUS_OLED
-	tristate "Asus OLED driver"
-	depends on USB
-	default N
-	---help---
-	  Enable support for the OLED display present in some Asus laptops.
diff --git a/drivers/staging/asus_oled/Makefile b/drivers/staging/asus_oled/Makefile
deleted file mode 100644
index e71f9aa..0000000
--- a/drivers/staging/asus_oled/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_ASUS_OLED)		+= asus_oled.o
diff --git a/drivers/staging/asus_oled/README b/drivers/staging/asus_oled/README
deleted file mode 100644
index 2d72123..0000000
--- a/drivers/staging/asus_oled/README
+++ /dev/null
@@ -1,156 +0,0 @@
-
-    Driver for Asus OLED display present in some Asus laptops.
-
-    The code of this driver is based on 'asusoled' program taken from
-    <http://lapsus.berlios.de/asus_oled.html>. I just wanted to have a simple
-    kernel driver for controlling this device, but I didn't know how
-    to do that. Now I know ;) Also, that program can not be used
-    with usbhid loaded, which means no USB mouse/keyboard while
-    controlling OLED display :(
-
-    It has been tested on Asus G1 and didn't cause any problems,
-    but I don't guarantee that it won't do anything wrong :)
-
-    It can (and probably does) have errors. It is usable
-    in my case, and I hope others will find it useful too!
-
-*******
-
-Building the module
-
-   To build the module you need kernel 2.6 include files and some C compiler.
-
-   Just run:
-   make
-   make install (as a root)
-
-   It will build (hopefully) the module and install it in
-   /lib/modules/'uname -r'/extra/asus_oled.ko.
-
-   To load it just use:
-   modprobe asus_oled
-
-   You can check if it has detected your OLED display by looking into dmesg output.
-   There should be something like this:
-   asus-oled 2-7:1.0: Attached Asus OLED device
-
-   If it doesn't find your display, you can try removing usbhid module.
-   If you add asus_oled into the list of modules loaded during system boot
-   before usbhid, it will work even when usbhid is present.
-
-   If it still doesn't detect your hardware, check lsusb output.
-   There should be similar line:
-   Bus 002 Device 005: ID 0b05:1726 ASUSTek Computer, Inc.
-
-   If you don't see any lines with '0b05:1726' it means that you have different
-   type of hardware that is not detected (it may or may not work, but the driver
-   knows only '0b05:1726' device).
-
-*******
-
-Configuration
-
-   There is only one option: start_off.
-   You can use it by: 'modprobe asus_oled start_off=1', or by adding this
-   line to /etc/modprobe.d/asus_oled.conf:
-   options asus_oled start_off=1
-
-   With this option provided, asus_oled driver will switch off the display
-   when it is detected and attached. It is nice feature to just switch off the 'ASUS'
-   logo. If you don't use the display, it is probably the good idea to switch it off,
-   to protect OLEDs from "wearing off".
-
-*******
-
-Usage
-
-   This module can be controlled with two special files:
-   /sys/class/asus_oled/oled_N/enabled
-   /sys/class/asus_oled/oled_N/picture
-
-   (N is the device number, the first, and probably the only, has number 1,
-    so it is /sys/class/asus_oled/oled_1/enabled
-    and /sys/class/asus_oled/oled_1/picture)
-
-   'enabled' files is for reading and writing, 'picture' is writeable only.
-
-   You can write 0 or 1 to 'enabled' file, which will switch
-   on and off the display. Reading from this file will tell you the last
-   status set, either 0 or 1. By default it is 1, so if the device was set to 'off',
-   and the computer was rebooted without power-off, this file will contain wrong
-   value - because the device is off, but hasn't been disabled this time and is
-   assumed to be on...
-
-   To 'picture' file you write pictures to be displayed by the OLED device.
-   The format of the file:
-   <M:WxH>
-   00001110010111000
-   00010101010101010
-   ....
-
-   First line is a configuration parameter. Meaning of fields in <M:WxH>:
-   M - picture mode. It can be either 's' for static pictures,
-       'r' for rolling pictures, and 'f' for flashing pictures.
-   W - width of the picture. May be between 1 and 1792
-   H - height of the picture. May be between 1 and 32
-
-   For example <s:128x32> means static picture, 128 pixels long and 32 pixels high.
-
-   The physical size of the display is 128x32 pixels. Static and flashing pictures
-   can't be larger than that (actually they can, but only part of them will be displayed ;) )
-
-   If the picture is smaller than 128x32 it will be centered. Rolling pictures wider than
-   128 pixels will be centered too, unless their width = n*128. Vertically they will be
-   centered just like static pictures, if their height is smaller than 32.
-
-   Flashing pictures will be centered horizontally if their width < 128, but they were
-   centered vertically in a different way. If their height < 16, they will be centered
-   in the upper half of the display (rows 0-15). This is because only the first half
-   of flashing pictures is used for flashing. When the picture with heigh = 32 is
-   displayed in flashing mode, its upper 16 rows will be flashing in the upper half
-   of the display, and the lower half will be empty. After few seconds upper part will
-   stop flashing (but that part of the picture will remain there), and the lower
-   half of the display will start displayin the lower half of the picture
-   in rolling mode, unless it is empty, or the picture was small enough to fit in
-   upper part. It is not mine idea, this is just the way Asus' display work ;)
-   So if you need just flashing, use at most 128x16 picture. If you need flashing and
-   rolling, use whole size of the display.
-
-   Lines following the first, configuration, line are picture data. Each '1' means
-   that the pixel is lit, and '0' means that it is not. You can also use '#' as ON,
-   and ' ' (space) as OFF. Empty lines and all other characters are ignored.
-
-   It is possible to write everything in one line <M:WxH>01010101010101010...,
-   and W*H characters will be used. If there is not enough characters, nothing will be
-   displayed. However, the 'line mode' is easier to read (and write), and it also
-   lets to omit parts of data. Whenever End-Of-Line character is found, but
-   the line is not W characters long, it is assumed that all missing characters
-   are equal to the last character in the line.
-
-   Following line represents '0', '1' and a lots of '0's, dependng on the width of the picture
-   provided in configuration data:
-   010
-
-   So if you need empty line, it is sufficient to write line with only one '0' in it.
-   The same works with '1' (or ' ' and '#').
-
-   If there are too many data in the file, they will be ignored. If you are not sure
-   how many characters you are missing, you can add few lines with one zero in each of them.
-
-   There are some example pictures in .txt format, that can be used as follows:
-   cat foo.txt > /sys/class/asus_oled/oled_1/picture
-
-   If the display is switched off you also need to run:
-   echo 1 > /sys/class/asus_oled/oled_1/enabled
-   To switch it off, just use:
-   echo 0 > /sys/class/asus_oled/oled_1/enabled
-
-
-*******
-
-   For any additional info please have a look at http://lapsus.berlios.de/asus_oled.html
-
-
-
-   Jakub Schmidtke (sjakub@gmail.com)
-
diff --git a/drivers/staging/asus_oled/TODO b/drivers/staging/asus_oled/TODO
deleted file mode 100644
index 2514131..0000000
--- a/drivers/staging/asus_oled/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-TODO:
-	- checkpatch.pl cleanups
-	- sparse fixes
-	- audit the userspace interface
-		- sysfs vs. char?
-	- Documentation/ABI/ needs to be added
-	- put the sample .txt files and README file somewhere.
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-Cc: Jakub Schmidtke <sjakub@gmail.com>
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
deleted file mode 100644
index 3654dc3..0000000
--- a/drivers/staging/asus_oled/asus_oled.c
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
- *  Asus OLED USB driver
- *
- *  Copyright (C) 2007,2008 Jakub Schmidtke (sjakub@gmail.com)
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *
- *
- *  This module is based on usbled and asus-laptop modules.
- *
- *
- *  Asus OLED support is based on asusoled program taken from
- *  <http://lapsus.berlios.de/asus_oled.html>.
- *
- *
- */
-
-#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 <linux/platform_device.h>
-#include <linux/ctype.h>
-
-#define ASUS_OLED_VERSION		"0.04-dev"
-#define ASUS_OLED_NAME			"asus-oled"
-#define ASUS_OLED_UNDERSCORE_NAME	"asus_oled"
-
-#define ASUS_OLED_STATIC		's'
-#define ASUS_OLED_ROLL			'r'
-#define ASUS_OLED_FLASH			'f'
-
-#define ASUS_OLED_MAX_WIDTH		1792
-#define ASUS_OLED_DISP_HEIGHT		32
-#define ASUS_OLED_PACKET_BUF_SIZE	256
-
-#define USB_VENDOR_ID_ASUS		0x0b05
-#define USB_DEVICE_ID_ASUS_LCM		0x1726
-#define USB_DEVICE_ID_ASUS_LCM2		0x175b
-
-MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
-MODULE_DESCRIPTION("Asus OLED Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(ASUS_OLED_VERSION);
-
-static struct class *oled_class;
-static int oled_num;
-
-static uint start_off;
-
-module_param(start_off, uint, 0644);
-
-MODULE_PARM_DESC(start_off,
-		 "Set to 1 to switch off OLED display after it is attached");
-
-enum oled_pack_mode {
-	PACK_MODE_G1,
-	PACK_MODE_G50,
-	PACK_MODE_LAST
-};
-
-struct oled_dev_desc_str {
-	uint16_t		idVendor;
-	uint16_t		idProduct;
-	/* width of display */
-	uint16_t		devWidth;
-	/* formula to be used while packing the picture */
-	enum oled_pack_mode	packMode;
-	const char		*devDesc;
-};
-
-/* table of devices that work with this driver */
-static const struct usb_device_id id_table[] = {
-	/* Asus G1/G2 (and variants)*/
-	{ USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM) },
-	/* Asus G50V (and possibly others - G70? G71?)*/
-	{ USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2) },
-	{ },
-};
-
-/* parameters of specific devices */
-static struct oled_dev_desc_str oled_dev_desc_table[] = {
-	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, 128, PACK_MODE_G1,
-		"G1/G2" },
-	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2, 256, PACK_MODE_G50,
-		"G50" },
-	{ },
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-struct asus_oled_header {
-	uint8_t		magic1;
-	uint8_t		magic2;
-	uint8_t		flags;
-	uint8_t		value3;
-	uint8_t		buffer1;
-	uint8_t		buffer2;
-	uint8_t		value6;
-	uint8_t		value7;
-	uint8_t		value8;
-	uint8_t		padding2[7];
-} __attribute((packed));
-
-struct asus_oled_packet {
-	struct asus_oled_header		header;
-	uint8_t				bitmap[ASUS_OLED_PACKET_BUF_SIZE];
-} __attribute((packed));
-
-struct asus_oled_dev {
-	struct usb_device       *udev;
-	uint8_t			pic_mode;
-	uint16_t		dev_width;
-	enum oled_pack_mode	pack_mode;
-	size_t			height;
-	size_t			width;
-	size_t			x_shift;
-	size_t			y_shift;
-	size_t			buf_offs;
-	uint8_t			last_val;
-	size_t			buf_size;
-	char			*buf;
-	uint8_t			enabled;
-	uint8_t			enabled_post_resume;
-	struct device		*dev;
-};
-
-static void setup_packet_header(struct asus_oled_packet *packet, char flags,
-			 char value3, char buffer1, char buffer2, char value6,
-			 char value7, char value8)
-{
-	memset(packet, 0, sizeof(struct asus_oled_header));
-	packet->header.magic1 = 0x55;
-	packet->header.magic2 = 0xaa;
-	packet->header.flags = flags;
-	packet->header.value3 = value3;
-	packet->header.buffer1 = buffer1;
-	packet->header.buffer2 = buffer2;
-	packet->header.value6 = value6;
-	packet->header.value7 = value7;
-	packet->header.value8 = value8;
-}
-
-static void enable_oled(struct asus_oled_dev *odev, uint8_t enabl)
-{
-	int retval;
-	int act_len;
-	struct asus_oled_packet *packet;
-
-	packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL);
-	if (!packet)
-		return;
-
-	setup_packet_header(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
-
-	if (enabl)
-		packet->bitmap[0] = 0xaf;
-	else
-		packet->bitmap[0] = 0xae;
-
-	retval = usb_bulk_msg(odev->udev,
-		usb_sndbulkpipe(odev->udev, 2),
-		packet,
-		sizeof(struct asus_oled_header) + 1,
-		&act_len,
-		-1);
-
-	if (retval)
-		dev_dbg(&odev->udev->dev, "retval = %d\n", retval);
-
-	odev->enabled = enabl;
-
-	kfree(packet);
-}
-
-static ssize_t set_enabled(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct asus_oled_dev *odev = usb_get_intfdata(intf);
-	unsigned long value;
-	if (kstrtoul(buf, 10, &value))
-		return -EINVAL;
-
-	enable_oled(odev, value);
-
-	return count;
-}
-
-static ssize_t class_set_enabled(struct device *device,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct asus_oled_dev *odev =
-		(struct asus_oled_dev *) dev_get_drvdata(device);
-	unsigned long value;
-
-	if (kstrtoul(buf, 10, &value))
-		return -EINVAL;
-
-	enable_oled(odev, value);
-
-	return count;
-}
-
-static ssize_t get_enabled(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct asus_oled_dev *odev = usb_get_intfdata(intf);
-
-	return sprintf(buf, "%d\n", odev->enabled);
-}
-
-static ssize_t class_get_enabled(struct device *device,
-				 struct device_attribute *attr, char *buf)
-{
-	struct asus_oled_dev *odev =
-		(struct asus_oled_dev *) dev_get_drvdata(device);
-
-	return sprintf(buf, "%d\n", odev->enabled);
-}
-
-static void send_packets(struct usb_device *udev,
-			 struct asus_oled_packet *packet,
-			 char *buf, uint8_t p_type, size_t p_num)
-{
-	size_t i;
-	int act_len;
-
-	for (i = 0; i < p_num; i++) {
-		int retval;
-
-		switch (p_type) {
-		case ASUS_OLED_ROLL:
-			setup_packet_header(packet, 0x40, 0x80, p_num,
-					    i + 1, 0x00, 0x01, 0xff);
-			break;
-		case ASUS_OLED_STATIC:
-			setup_packet_header(packet, 0x10 + i, 0x80, 0x01,
-					    0x01, 0x00, 0x01, 0x00);
-			break;
-		case ASUS_OLED_FLASH:
-			setup_packet_header(packet, 0x10 + i, 0x80, 0x01,
-					    0x01, 0x00, 0x00, 0xff);
-			break;
-		}
-
-		memcpy(packet->bitmap, buf + (ASUS_OLED_PACKET_BUF_SIZE*i),
-		       ASUS_OLED_PACKET_BUF_SIZE);
-
-		retval = usb_bulk_msg(udev, usb_sndctrlpipe(udev, 2),
-				      packet, sizeof(struct asus_oled_packet),
-				      &act_len, -1);
-
-		if (retval)
-			dev_dbg(&udev->dev, "retval = %d\n", retval);
-	}
-}
-
-static void send_packet(struct usb_device *udev,
-			struct asus_oled_packet *packet,
-			size_t offset, size_t len, char *buf, uint8_t b1,
-			uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
-			uint8_t b6) {
-	int retval;
-	int act_len;
-
-	setup_packet_header(packet, b1, b2, b3, b4, b5, b6, 0x00);
-	memcpy(packet->bitmap, buf + offset, len);
-
-	retval = usb_bulk_msg(udev,
-			      usb_sndctrlpipe(udev, 2),
-			      packet,
-			      sizeof(struct asus_oled_packet),
-			      &act_len,
-			      -1);
-
-	if (retval)
-		dev_dbg(&udev->dev, "retval = %d\n", retval);
-}
-
-
-static void send_packets_g50(struct usb_device *udev,
-			     struct asus_oled_packet *packet, char *buf)
-{
-	send_packet(udev, packet,     0, 0x100, buf,
-		    0x10, 0x00, 0x02, 0x01, 0x00, 0x01);
-	send_packet(udev, packet, 0x100, 0x080, buf,
-		    0x10, 0x00, 0x02, 0x02, 0x80, 0x00);
-
-	send_packet(udev, packet, 0x180, 0x100, buf,
-		    0x11, 0x00, 0x03, 0x01, 0x00, 0x01);
-	send_packet(udev, packet, 0x280, 0x100, buf,
-		    0x11, 0x00, 0x03, 0x02, 0x00, 0x01);
-	send_packet(udev, packet, 0x380, 0x080, buf,
-		    0x11, 0x00, 0x03, 0x03, 0x80, 0x00);
-}
-
-
-static void send_data(struct asus_oled_dev *odev)
-{
-	size_t packet_num = odev->buf_size / ASUS_OLED_PACKET_BUF_SIZE;
-	struct asus_oled_packet *packet;
-
-	packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL);
-	if (!packet)
-		return;
-
-	if (odev->pack_mode == PACK_MODE_G1) {
-		/*
-		 * When sending roll-mode data the display updated only
-		 * first packet.  I have no idea why, but when static picture
-		 * is sent just before rolling picture everything works fine.
-		 */
-		if (odev->pic_mode == ASUS_OLED_ROLL)
-			send_packets(odev->udev, packet, odev->buf,
-				     ASUS_OLED_STATIC, 2);
-
-		/* Only ROLL mode can use more than 2 packets.*/
-		if (odev->pic_mode != ASUS_OLED_ROLL && packet_num > 2)
-			packet_num = 2;
-
-		send_packets(odev->udev, packet, odev->buf,
-			     odev->pic_mode, packet_num);
-	} else if (odev->pack_mode == PACK_MODE_G50) {
-		send_packets_g50(odev->udev, packet, odev->buf);
-	}
-
-	kfree(packet);
-}
-
-static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
-{
-	odev->last_val = val;
-
-	if (val == 0) {
-		odev->buf_offs += count;
-		return 0;
-	}
-
-	while (count-- > 0) {
-		size_t x = odev->buf_offs % odev->width;
-		size_t y = odev->buf_offs / odev->width;
-		size_t i;
-
-		x += odev->x_shift;
-		y += odev->y_shift;
-
-		switch (odev->pack_mode) {
-		case PACK_MODE_G1:
-			/*
-			 * i = (x/128)*640 + 127 - x + (y/8)*128;
-			 * This one for 128 is the same, but might be better
-			 * for different widths?
-			 */
-			i = (x/odev->dev_width)*640 +
-				odev->dev_width - 1 - x +
-				(y/8)*odev->dev_width;
-			break;
-
-		case PACK_MODE_G50:
-			i =  (odev->dev_width - 1 - x)/8 + y*odev->dev_width/8;
-			break;
-
-		default:
-			i = 0;
-			dev_err(odev->dev, "Unknown OLED Pack Mode: %d!\n",
-			       odev->pack_mode);
-			break;
-		}
-
-		if (i >= odev->buf_size) {
-			dev_err(odev->dev, "Buffer overflow! Report a bug: offs: %zu >= %zu i: %zu (x: %zu y: %zu)\n",
-			       odev->buf_offs, odev->buf_size, i, x, y);
-			return -EIO;
-		}
-
-		switch (odev->pack_mode) {
-		case PACK_MODE_G1:
-			odev->buf[i] &= ~(1<<(y%8));
-			break;
-
-		case PACK_MODE_G50:
-			odev->buf[i] &= ~(1<<(x%8));
-			break;
-
-		default:
-			/* cannot get here; stops gcc complaining*/
-			break;
-		}
-
-		odev->buf_offs++;
-	}
-
-	return 0;
-}
-
-static ssize_t odev_set_picture(struct asus_oled_dev *odev,
-				const char *buf, size_t count)
-{
-	size_t offs = 0, max_offs;
-
-	if (count < 1)
-		return 0;
-
-	if (tolower(buf[0]) == 'b') {
-		/* binary mode, set the entire memory*/
-
-		size_t i;
-
-		odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8;
-
-		kfree(odev->buf);
-		odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
-		if (odev->buf == NULL) {
-			odev->buf_size = 0;
-			dev_err(odev->dev, "Out of memory!\n");
-			return -ENOMEM;
-		}
-
-		memset(odev->buf, 0xff, odev->buf_size);
-
-		for (i = 1; i < count && i <= 32 * 32; i++) {
-			odev->buf[i-1] = buf[i];
-			odev->buf_offs = i-1;
-		}
-
-		odev->width = odev->dev_width / 8;
-		odev->height = ASUS_OLED_DISP_HEIGHT;
-		odev->x_shift = 0;
-		odev->y_shift = 0;
-		odev->last_val =  0;
-
-		send_data(odev);
-
-		return count;
-	}
-
-	if (buf[0] == '<') {
-		size_t i;
-		size_t w = 0, h = 0;
-		size_t w_mem, h_mem;
-
-		if (count < 10 || buf[2] != ':')
-			goto error_header;
-
-
-		switch (tolower(buf[1])) {
-		case ASUS_OLED_STATIC:
-		case ASUS_OLED_ROLL:
-		case ASUS_OLED_FLASH:
-			odev->pic_mode = buf[1];
-			break;
-		default:
-			dev_err(odev->dev, "Wrong picture mode: '%c'.\n",
-			       buf[1]);
-			return -EIO;
-			break;
-		}
-
-		for (i = 3; i < count; ++i) {
-			if (buf[i] >= '0' && buf[i] <= '9') {
-				w = 10*w + (buf[i] - '0');
-
-				if (w > ASUS_OLED_MAX_WIDTH)
-					goto error_width;
-			} else if (tolower(buf[i]) == 'x') {
-				break;
-			} else {
-				goto error_width;
-			}
-		}
-
-		for (++i; i < count; ++i) {
-			if (buf[i] >= '0' && buf[i] <= '9') {
-				h = 10*h + (buf[i] - '0');
-
-				if (h > ASUS_OLED_DISP_HEIGHT)
-					goto error_height;
-			} else if (tolower(buf[i]) == '>') {
-				break;
-			} else {
-				goto error_height;
-			}
-		}
-
-		if (w < 1 || w > ASUS_OLED_MAX_WIDTH)
-			goto error_width;
-
-		if (h < 1 || h > ASUS_OLED_DISP_HEIGHT)
-			goto error_height;
-
-		if (i >= count || buf[i] != '>')
-			goto error_header;
-
-		offs = i+1;
-
-		if (w % (odev->dev_width) != 0)
-			w_mem = (w/(odev->dev_width) + 1)*(odev->dev_width);
-		else
-			w_mem = w;
-
-		if (h < ASUS_OLED_DISP_HEIGHT)
-			h_mem = ASUS_OLED_DISP_HEIGHT;
-		else
-			h_mem = h;
-
-		odev->buf_size = w_mem * h_mem / 8;
-
-		kfree(odev->buf);
-		odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
-
-		if (odev->buf == NULL) {
-			odev->buf_size = 0;
-			dev_err(odev->dev, "Out of memory!\n");
-			return -ENOMEM;
-		}
-
-		memset(odev->buf, 0xff, odev->buf_size);
-
-		odev->buf_offs = 0;
-		odev->width = w;
-		odev->height = h;
-		odev->x_shift = 0;
-		odev->y_shift = 0;
-		odev->last_val = 0;
-
-		if (odev->pic_mode == ASUS_OLED_FLASH) {
-			if (h < ASUS_OLED_DISP_HEIGHT/2)
-				odev->y_shift = (ASUS_OLED_DISP_HEIGHT/2 - h)/2;
-		} else {
-			if (h < ASUS_OLED_DISP_HEIGHT)
-				odev->y_shift = (ASUS_OLED_DISP_HEIGHT - h)/2;
-		}
-
-		if (w < (odev->dev_width))
-			odev->x_shift = ((odev->dev_width) - w)/2;
-	}
-
-	max_offs = odev->width * odev->height;
-
-	while (offs < count && odev->buf_offs < max_offs) {
-		int ret = 0;
-
-		if (buf[offs] == '1' || buf[offs] == '#') {
-			ret = append_values(odev, 1, 1);
-			if (ret < 0)
-				return ret;
-		} else if (buf[offs] == '0' || buf[offs] == ' ') {
-			ret = append_values(odev, 0, 1);
-			if (ret < 0)
-				return ret;
-		} else if (buf[offs] == '\n') {
-			/*
-			 * New line detected. Lets assume, that all characters
-			 * till the end of the line were equal to the last
-			 * character in this line.
-			 */
-			if (odev->buf_offs % odev->width != 0)
-				ret = append_values(odev, odev->last_val,
-						    odev->width -
-						    (odev->buf_offs %
-						     odev->width));
-			if (ret < 0)
-				return ret;
-		}
-
-		offs++;
-	}
-
-	if (odev->buf_offs >= max_offs)
-		send_data(odev);
-
-	return count;
-
-error_width:
-	dev_err(odev->dev, "Wrong picture width specified.\n");
-	return -EIO;
-
-error_height:
-	dev_err(odev->dev, "Wrong picture height specified.\n");
-	return -EIO;
-
-error_header:
-	dev_err(odev->dev, "Wrong picture header.\n");
-	return -EIO;
-}
-
-static ssize_t set_picture(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct usb_interface *intf = to_usb_interface(dev);
-
-	return odev_set_picture(usb_get_intfdata(intf), buf, count);
-}
-
-static ssize_t class_set_picture(struct device *device,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	return odev_set_picture((struct asus_oled_dev *)
-				dev_get_drvdata(device), buf, count);
-}
-
-#define ASUS_OLED_DEVICE_ATTR(_file)		dev_attr_asus_oled_##_file
-
-static DEVICE_ATTR(asus_oled_enabled, S_IWUSR | S_IRUGO,
-		   get_enabled, set_enabled);
-static DEVICE_ATTR(asus_oled_picture, S_IWUSR , NULL, set_picture);
-
-static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO,
-		   class_get_enabled, class_set_enabled);
-static DEVICE_ATTR(picture, S_IWUSR, NULL, class_set_picture);
-
-static int asus_oled_probe(struct usb_interface *interface,
-			   const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct asus_oled_dev *odev = NULL;
-	int retval = -ENOMEM;
-	uint16_t dev_width = 0;
-	enum oled_pack_mode pack_mode = PACK_MODE_LAST;
-	const struct oled_dev_desc_str *dev_desc = oled_dev_desc_table;
-	const char *desc = NULL;
-
-	if (!id) {
-		/* Even possible? Just to make sure...*/
-		dev_err(&interface->dev, "No usb_device_id provided!\n");
-		return -ENODEV;
-	}
-
-	for (; dev_desc->idVendor; dev_desc++) {
-		if (dev_desc->idVendor == id->idVendor
-		    && dev_desc->idProduct == id->idProduct) {
-			dev_width = dev_desc->devWidth;
-			desc = dev_desc->devDesc;
-			pack_mode = dev_desc->packMode;
-			break;
-		}
-	}
-
-	if (!desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) {
-		dev_err(&interface->dev,
-			"Missing or incomplete device description!\n");
-		return -ENODEV;
-	}
-
-	odev = kzalloc(sizeof(struct asus_oled_dev), GFP_KERNEL);
-	if (odev == NULL)
-		return -ENOMEM;
-
-	odev->udev = usb_get_dev(udev);
-	odev->pic_mode = ASUS_OLED_STATIC;
-	odev->dev_width = dev_width;
-	odev->pack_mode = pack_mode;
-	odev->height = 0;
-	odev->width = 0;
-	odev->x_shift = 0;
-	odev->y_shift = 0;
-	odev->buf_offs = 0;
-	odev->buf_size = 0;
-	odev->last_val = 0;
-	odev->buf = NULL;
-	odev->enabled = 1;
-	odev->dev = NULL;
-
-	usb_set_intfdata(interface, odev);
-
-	retval = device_create_file(&interface->dev,
-				    &ASUS_OLED_DEVICE_ATTR(enabled));
-	if (retval)
-		goto err_files;
-
-	retval = device_create_file(&interface->dev,
-				    &ASUS_OLED_DEVICE_ATTR(picture));
-	if (retval)
-		goto err_files;
-
-	odev->dev = device_create(oled_class, &interface->dev, MKDEV(0, 0),
-				  NULL, "oled_%d", ++oled_num);
-
-	if (IS_ERR(odev->dev)) {
-		retval = PTR_ERR(odev->dev);
-		goto err_files;
-	}
-
-	dev_set_drvdata(odev->dev, odev);
-
-	retval = device_create_file(odev->dev, &dev_attr_enabled);
-	if (retval)
-		goto err_class_enabled;
-
-	retval = device_create_file(odev->dev, &dev_attr_picture);
-	if (retval)
-		goto err_class_picture;
-
-	dev_info(&interface->dev,
-		 "Attached Asus OLED device: %s [width %u, pack_mode %d]\n",
-		 desc, odev->dev_width, odev->pack_mode);
-
-	if (start_off)
-		enable_oled(odev, 0);
-
-	return 0;
-
-err_class_picture:
-	device_remove_file(odev->dev, &dev_attr_picture);
-
-err_class_enabled:
-	device_remove_file(odev->dev, &dev_attr_enabled);
-	device_unregister(odev->dev);
-
-err_files:
-	device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
-	device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
-
-	usb_set_intfdata(interface, NULL);
-	usb_put_dev(odev->udev);
-	kfree(odev);
-
-	return retval;
-}
-
-static void asus_oled_disconnect(struct usb_interface *interface)
-{
-	struct asus_oled_dev *odev;
-
-	odev = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-
-	device_remove_file(odev->dev, &dev_attr_picture);
-	device_remove_file(odev->dev, &dev_attr_enabled);
-	device_unregister(odev->dev);
-
-	device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
-	device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
-
-	usb_put_dev(odev->udev);
-
-	kfree(odev->buf);
-
-	kfree(odev);
-
-	dev_info(&interface->dev, "Disconnected Asus OLED device\n");
-}
-
-#ifdef CONFIG_PM
-static int asus_oled_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct asus_oled_dev *odev;
-
-	odev = usb_get_intfdata(intf);
-	if (!odev)
-		return -ENODEV;
-
-	odev->enabled_post_resume = odev->enabled;
-	enable_oled(odev, 0);
-
-	return 0;
-}
-
-static int asus_oled_resume(struct usb_interface *intf)
-{
-	struct asus_oled_dev *odev;
-
-	odev = usb_get_intfdata(intf);
-	if (!odev)
-		return -ENODEV;
-
-	enable_oled(odev, odev->enabled_post_resume);
-
-	return 0;
-}
-#else
-#define asus_oled_suspend NULL
-#define asus_oled_resume NULL
-#endif
-
-static struct usb_driver oled_driver = {
-	.name =		ASUS_OLED_NAME,
-	.probe =	asus_oled_probe,
-	.disconnect =	asus_oled_disconnect,
-	.id_table =	id_table,
-	.suspend =	asus_oled_suspend,
-	.resume =	asus_oled_resume,
-};
-
-static CLASS_ATTR_STRING(version, S_IRUGO,
-			ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
-
-static int __init asus_oled_init(void)
-{
-	int retval = 0;
-	oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME);
-
-	if (IS_ERR(oled_class)) {
-		pr_err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n");
-		return PTR_ERR(oled_class);
-	}
-
-	retval = class_create_file(oled_class, &class_attr_version.attr);
-	if (retval) {
-		pr_err("Error creating class version file\n");
-		goto error;
-	}
-
-	retval = usb_register(&oled_driver);
-
-	if (retval) {
-		pr_err("usb_register failed. Error number %d\n", retval);
-		goto error;
-	}
-
-	return retval;
-
-error:
-	class_destroy(oled_class);
-	return retval;
-}
-
-static void __exit asus_oled_exit(void)
-{
-	usb_deregister(&oled_driver);
-	class_remove_file(oled_class, &class_attr_version.attr);
-	class_destroy(oled_class);
-}
-
-module_init(asus_oled_init);
-module_exit(asus_oled_exit);
-
diff --git a/drivers/staging/asus_oled/linux.txt b/drivers/staging/asus_oled/linux.txt
deleted file mode 100644
index dc758b0..0000000
--- a/drivers/staging/asus_oled/linux.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-<s:74x32>
-0
-0
-00000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000
-01111111111000000000000000000000000000000000000000000000000000000000000000
-00011111100000000000000111000000000000000000000000000000000000000000000000
-00001111000000000000000111000000000000000000000000000000000000000000000000
-00001111000000000000000111000000000000000000000000000000000000000000000000
-00001111000000000000000000000000000000000000000000000000000000000000000000
-00001111000000000000000000000000000000000000000000000000000000000000000000
-00001111000000000000011100001111111111100000111110011111100011111101111000
-00001111000000000000111110000011111000111000111110000111100001111000110000
-00001111000000000001101110000011111000111000001111000111100000111100100000
-00001111000000000001001110000011110000111100001111000111100000111101100000
-00001111000000000100001110000011110000111100001111000111100000011111000000
-00001111000000000100011110000011110000111100001111000111100000001111000000
-00001111000000000100011110000011110000111100001111000111100000001111000000
-00001111000000000100011100100011110000111100001111000111100000001111100000
-00001111000000001100111100100011110000111100001111000111100000001111110000
-00001111000000001100111101100011110000111100001111000111100000011011110000
-00001111000000011100111101000011110000111100001111000111100000010001111000
-00011111000001111100111011000011110000111100001111001111100000110000111100
-11111111111111111100011110001111111011111110000111110111111011111011111110
-00000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000
-0
-0
-0
-0
diff --git a/drivers/staging/asus_oled/linux_f.txt b/drivers/staging/asus_oled/linux_f.txt
deleted file mode 100644
index b4bb85c..0000000
--- a/drivers/staging/asus_oled/linux_f.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-<f:128x16>
-00000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000011000111111111100001111001111100111110111000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000111100001111000110001111000111100011100010000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000001011100001111000111000111100111100001110110000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000011100001110000111000111100111100001111100000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000100111001001110000111000111100111100000111110000000000000000000000000000000000000
-00000000000000000000000000000000000011110000001100111011001110000111000111100111100000111110000000000000000000000000000000000000
-00000000000000000000000000000000000011110000001100111010001110000111000111100111100000100111000000000000000000000000000000000000
-00000000000000000000000000000000000011110000111100110110001110000111000111100111100001000011100000000000000000000000000000000000
-00000000000000000000000000000000001111111111111100111100111111011111100011110111110111101111110000000000000000000000000000000000
-
diff --git a/drivers/staging/asus_oled/linux_fr.txt b/drivers/staging/asus_oled/linux_fr.txt
deleted file mode 100644
index f88e2b3..0000000
--- a/drivers/staging/asus_oled/linux_fr.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-<f:128x32>
-00000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000011000111111111100001111001111100111110111000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000111100001111000110001111000111100011100010000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000001011100001111000111000111100111100001110110000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000000011100001110000111000111100111100001111100000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
-00000000000000000000000000000000000011110000000100111001001110000111000111100111100000111110000000000000000000000000000000000000
-00000000000000000000000000000000000011110000001100111011001110000111000111100111100000111110000000000000000000000000000000000000
-00000000000000000000000000000000000011110000001100111010001110000111000111100111100000100111000000000000000000000000000000000000
-00000000000000000000000000000000000011110000111100110110001110000111000111100111100001000011100000000000000000000000000000000000
-00000000000000000000000000000000001111111111111100111100111111011111100011110111110111101111110000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000
-00000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000
-00000000000000000000000000011111100000000000000000000000000000000000000000000000000000000000011111100000000000000000000000000000
-00000000000000000000000000011111100000000000000000000000000000000000000000000000000000000000011111100000000000000000000000000000
-00000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000
-00000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
diff --git a/drivers/staging/asus_oled/tux.txt b/drivers/staging/asus_oled/tux.txt
deleted file mode 100644
index 9d20528..0000000
--- a/drivers/staging/asus_oled/tux.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-<s:32x32>
-00000000000001111111000000000000
-0000000000001       100000000000
-000000000001         10000000000
-000000000001         10000000000
-000000000001         10000000000
-000000000001 1  111  10000000000
-000000000001    1 1   1000000000
-000000000001  111     1000000000
-000000000001 111111   1000000000
-000000000001 111111   1000000000
-000000000001    1 1    100000000
-00000000001      11    100000000
-00000000001 11111111    10000000
-0000000001  11111111     1000000
-000000001   111111111    1000000
-000000001  1111111111     100000
-00000001   11111111111    100000
-00000001  111111111111     10000
-0000001   111111111111     10000
-0000001   111111111111     10000
-0000001   111111111111     10000
-0000001   111111111111     10000
-000000011 11111111111      10000
-000011 11  11111111111    100000
-0001  1111  111111111111111 1000
-001 1111111  11111111111111 1000
-001 1111111  1111111  111111 100
-001 11111111 111111   1111111 10
-001 11111111          11111  100
-001  1111111          111  11100
-000111   111   11111  11  100000
-000000111   111111111    1000000
diff --git a/drivers/staging/asus_oled/tux_r.txt b/drivers/staging/asus_oled/tux_r.txt
deleted file mode 100644
index fd81a3e..0000000
--- a/drivers/staging/asus_oled/tux_r.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-<r:32x32>
-00000000000001111111000000000000
-0000000000001       100000000000
-000000000001         10000000000
-000000000001         10000000000
-000000000001         10000000000
-000000000001 1  111  10000000000
-000000000001    1 1   1000000000
-000000000001  111     1000000000
-000000000001 111111   1000000000
-000000000001 111111   1000000000
-000000000001    1 1    100000000
-00000000001      11    100000000
-00000000001 11111111    10000000
-0000000001  11111111     1000000
-000000001   111111111    1000000
-000000001  1111111111     100000
-00000001   11111111111    100000
-00000001  111111111111     10000
-0000001   111111111111     10000
-0000001   111111111111     10000
-0000001   111111111111     10000
-0000001   111111111111     10000
-000000011 11111111111      10000
-000011 11  11111111111    100000
-0001  1111  111111111111111 1000
-001 1111111  11111111111111 1000
-001 1111111  1111111  111111 100
-001 11111111 111111   1111111 10
-001 11111111          11111  100
-001  1111111          111  11100
-000111   111   11111  11  100000
-000000111   111111111    1000000
diff --git a/drivers/staging/asus_oled/tux_r2.txt b/drivers/staging/asus_oled/tux_r2.txt
deleted file mode 100644
index e94d84e..0000000
--- a/drivers/staging/asus_oled/tux_r2.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-<r:256x32>
-000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000001       1000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001         1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001         1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001         1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001 1  111  1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001    1 1   100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001  111     100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111100000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001 111111   100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001 111111   100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000001    1 1    10000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000001      11    10000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000001 11111111    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000011100001111111111100000111110011111100011111101111000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000001  11111111     100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000111110000011111000111000111110000111100001111000110000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000001   111111111    100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000001101110000011111000111000001111000111100000111100100000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000001  1111111111     10000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000001001110000011110000111100001111000111100000111101100000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000001   11111111111    10000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100001110000011110000111100001111000111100000011111000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000001  111111111111     10000000000000000000000000000000000000000000000000000000000000000000000000000000000011110000000001000111100000111100001111000011110001111000000011110000000
-0000000000000000000000000000000000000000000000000000001   111111111111     1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100011110000011110000111100001111000111100000001111000000
-0000000000000000000000000000000000000000000000000000001   111111111111     1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100011100100011110000111100001111000111100000001111100000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000001   111111111111     1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000001100111100100011110000111100001111000111100000001111110000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000001   111111111111     1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000001100111101100011110000111100001111000111100000011011110000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000011 11111111111      1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000011100111101000011110000111100001111000111100000010001111000000000000000000000000000000
-000000000000000000000000000000000000000000000000000011 11  11111111111    10000000000000000000000000000000000000000000000000000000000000000000000000000000000011111000001111100111011000011110000111100001111001111100000110000111100000000000000000000000000000
-0000000000000000000000000000000000000000000000000001  1111  111111111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111100011110001111111011111110000111110111111011111011111110000000000000000000000000000
-000000000000000000000000000000000000000000000000001 1111111  11111111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000001 1111111  1111111  111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000001 11111111 111111   1111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000001 11111111          11111  1000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000001  1111111          111  111000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000111   111   11111  11  10
-000000000000000000000000000000000000000000000000000000111   111111111    10
diff --git a/drivers/staging/asus_oled/zig.txt b/drivers/staging/asus_oled/zig.txt
deleted file mode 100644
index 31573d8..0000000
--- a/drivers/staging/asus_oled/zig.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-<r:128x32>
-10000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001
-01000000000000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000010
-00100000000000000000000000000000000000000000000000000000000001000010000000000000000000000000000000000000000000000000000000000100
-00010000000000000000000000000000000000000000000000000000000010000001000000000000000000000000000000000000000000000000000000001000
-00001000000000000000000000000000000000000000000000000000000100000000100000000000000000000000000000000000000000000000000000010000
-00000100000000000000000000000000000000000000000000000000001000000000010000000000000000000000000000000000000000000000000000100000
-00000010000000000000000000000000000000000000000000000000010000000000001000000000000000000000000000000000000000000000000001000000
-00000001000000000000000000000000000000000000000000000000100000000000000100000000000000000000000000000000000000000000000010000000
-00000000100000000000000000000000000000000000000000000001000000000000000010000000000000000000000000000000000000000000000100000000
-00000000010000000000000000000000000000000000000000000010000000000000000001000000000000000000000000000000000000000000001000000000
-00000000001000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000000000010000000000
-00000000000100000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000100000000000
-00000000000010000000000000000000000000000000000000010000000000000000000000001000000000000000000000000000000000000001000000000000
-00000000000001000000000000000000000000000000000000100000000000000000000000000100000000000000000000000000000000000010000000000000
-00000000000000100000000000000000000000000000000001000000000000000000000000000010000000000000000000000000000000000100000000000000
-00000000000000010000000000000000000000000000000010000000000000000000000000000001000000000000000000000000000000001000000000000000
-00000000000000001000000000000000000000000000000100000000000000000000000000000000100000000000000000000000000000010000000000000000
-00000000000000000100000000000000000000000000001000000000000000000000000000000000010000000000000000000000000000100000000000000000
-00000000000000000010000000000000000000000000010000000000000000000000000000000000001000000000000000000000000001000000000000000000
-00000000000000000001000000000000000000000000100000000000000000000000000000000000000100000000000000000000000010000000000000000000
-00000000000000000000100000000000000000000001000000000000000000000000000000000000000010000000000000000000000100000000000000000000
-00000000000000000000010000000000000000000010000000000000000000000000000000000000000001000000000000000000001000000000000000000000
-00000000000000000000001000000000000000000100000000000000000000000000000000000000000000100000000000000000010000000000000000000000
-00000000000000000000000100000000000000001000000000000000000000000000000000000000000000010000000000000000100000000000000000000000
-00000000000000000000000010000000000000010000000000000000000000000000000000000000000000001000000000000001000000000000000000000000
-00000000000000000000000001000000000000100000000000000000000000000000000000000000000000000100000000000010000000000000000000000000
-00000000000000000000000000100000000001000000000000000000000000000000000000000000000000000010000000000100000000000000000000000000
-00000000000000000000000000010000000010000000000000000000000000000000000000000000000000000001000000001000000000000000000000000000
-00000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000100000010000000000000000000000000000
-00000000000000000000000000000100001000000000000000000000000000000000000000000000000000000000010000100000000000000000000000000000
-00000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000
-00000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000
diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c
index 877cf0b..bc48616 100644
--- a/drivers/staging/bcm/LeakyBucket.c
+++ b/drivers/staging/bcm/LeakyBucket.c
@@ -17,47 +17,42 @@
 
 static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
 {
-	ULONG 	liCurrentTime;
-	INT 	i = 0;
+	ULONG liCurrentTime;
+	INT i = 0;
 	struct timeval tv;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
 			"=====>\n");
-	if(NULL == Adapter)
-	{
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, 
+	if (NULL == Adapter) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
 				DBG_LVL_ALL, "Adapter found NULL!\n");
 		return;
 	}
 
 	do_gettimeofday(&tv);
-	for(i = 0; i < NO_OF_QUEUES; i++)
-	{
-		if(TRUE == Adapter->PackInfo[i].bValid &&
-			(1 == Adapter->PackInfo[i].ucDirection))
-		{
+	for (i = 0; i < NO_OF_QUEUES; i++) {
+		if (TRUE == Adapter->PackInfo[i].bValid &&
+		    (1 == Adapter->PackInfo[i].ucDirection)) {
 			liCurrentTime = ((tv.tv_sec-
 				Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
 				(tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
 				1000);
-			if(0!=liCurrentTime)
-			{
+			if (0 != liCurrentTime) {
 				Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG)
 					((Adapter->PackInfo[i].uiMaxAllowedRate) *
 					((ULONG)((liCurrentTime)))/1000);
 				memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt,
 					&tv, sizeof(struct timeval));
 				Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime;
-				if((Adapter->PackInfo[i].uiCurrentTokenCount) >=
-				Adapter->PackInfo[i].uiMaxBucketSize)
-				{
+				if (Adapter->PackInfo[i].uiCurrentTokenCount >=
+				    Adapter->PackInfo[i].uiMaxBucketSize) {
 					Adapter->PackInfo[i].uiCurrentTokenCount =
 						Adapter->PackInfo[i].uiMaxBucketSize;
 				}
 			}
 		}
 	}
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
 	return;
 
 }
@@ -79,33 +74,26 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
 ***********************************************************************/
 static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
 {
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
 	/* Validate the parameters */
-	if(NULL == Adapter || (psSF < Adapter->PackInfo &&
-		(uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority]))
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo));
+	if (NULL == Adapter || (psSF < Adapter->PackInfo &&
+	    (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo));
 		return 0;
 	}
 
-	if(FALSE != psSF->bValid && psSF->ucDirection)
-	{
-		if(0 != psSF->uiCurrentTokenCount)
-		{
+	if (FALSE != psSF->bValid && psSF->ucDirection) {
+		if (0 != psSF->uiCurrentTokenCount) {
 				return psSF->uiCurrentTokenCount;
-		}
-		else
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
+		} else {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
 				psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
 			psSF->uiPendedLast = 1;
 		}
+	} else {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
 	}
-	else
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
-	}
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
 	return 0;
 }
 
@@ -116,33 +104,29 @@ This function despatches packet from the specified queue.
 */
 static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
 			struct bcm_packet_info *psSF, /**<Queue identifier*/
-			       struct sk_buff*  Packet)	/**<Pointer to the packet to be sent*/
+			       struct sk_buff *Packet)	/**<Pointer to the packet to be sent*/
 {
-	INT  	Status=STATUS_FAILURE;
-	UINT uiIndex =0,PktLen = 0;
+	INT Status = STATUS_FAILURE;
+	UINT uiIndex = 0, PktLen = 0;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
-	if(!Adapter || !Packet || !psSF)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
+	if (!Adapter || !Packet || !psSF) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
 		return -EINVAL;
 	}
 
-	if(psSF->liDrainCalculated==0)
-	{
+	if (psSF->liDrainCalculated == 0)
 		psSF->liDrainCalculated = jiffies;
-	}
-	///send the packet to the fifo..
+	/* send the packet to the fifo.. */
 	PktLen = Packet->len;
 	Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
-	if(Status == 0)
-	{
-		for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
-		{	if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
+	if (Status == 0) {
+		for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
+			if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
 				Adapter->aTxPktSizeHist[uiIndex]++;
 		}
 	}
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
 	return Status;
 }
 
@@ -160,107 +144,93 @@ static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adap
 ****************************************************************************/
 static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
 {
-	struct sk_buff	*QueuePacket=NULL;
-	char 			*pControlPacket = NULL;
-	INT				Status=0;
-	int				iPacketLen=0;
+	struct sk_buff *QueuePacket = NULL;
+	char *pControlPacket = NULL;
+	INT Status = 0;
+	int iPacketLen = 0;
 
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
-	if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet
-  	{
-		if(!psSF->ucDirection )
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
+	if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
+		if (!psSF->ucDirection)
 			return;
 
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
-		if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
+		if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
 			return;	/* in idle mode */
 
-		// Check for Free Descriptors
-		if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..",atomic_read(&Adapter->CurrNumFreeTxDesc));
-			return ;
+		/* Check for Free Descriptors */
+		if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc));
+			return;
 		}
 
 		spin_lock_bh(&psSF->SFQueueLock);
-		QueuePacket=psSF->FirstTxQueue;
+		QueuePacket = psSF->FirstTxQueue;
 
-		if(QueuePacket)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
+		if (QueuePacket) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
 
-			if(psSF->bEthCSSupport)
+			if (psSF->bEthCSSupport)
 				iPacketLen = QueuePacket->len;
 			else
 				iPacketLen = QueuePacket->len-ETH_HLEN;
 
-			iPacketLen<<=3;
-			if(iPacketLen <= GetSFTokenCount(Adapter, psSF))
-			{
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
+			iPacketLen <<= 3;
+			if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) {
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
 					(iPacketLen >> 3));
 
-				DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue);
+				DEQUEUEPACKET(psSF->FirstTxQueue, psSF->LastTxQueue);
 				psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
 				psSF->uiCurrentPacketsOnHost--;
 				atomic_dec(&Adapter->TotalPacketCount);
 				spin_unlock_bh(&psSF->SFQueueLock);
 
-			   	Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
+				Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
 				psSF->uiPendedLast = FALSE;
-			}
-			else
-			{
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
+			} else {
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
 					psSF->uiCurrentTokenCount, iPacketLen);
-				//this part indicates that because of non-availability of the tokens
-				//pkt has not been send out hence setting the pending flag indicating the host to send it out
-				//first next iteration  .
+				/*
+				this part indicates that because of non-availability of the tokens
+				pkt has not been send out hence setting the pending flag indicating the host to send it out
+				first next iteration.
+				*/
 				psSF->uiPendedLast = TRUE;
 				spin_unlock_bh(&psSF->SFQueueLock);
 			}
-		}
-		else
-		{
+		} else {
 			spin_unlock_bh(&psSF->SFQueueLock);
 		}
-	}
-	else
-	{
-
-		if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) &&
-			(atomic_read(&Adapter->index_rd_txcntrlpkt) !=
-			 atomic_read(&Adapter->index_wr_txcntrlpkt))
-			)
-		{
+	} else {
+
+		if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) &&
+		    (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
+		     atomic_read(&Adapter->index_wr_txcntrlpkt))) {
 			pControlPacket = Adapter->txctlpacket
 			[(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
-			if(pControlPacket)
-			{
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
+			if (pControlPacket) {
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
 				Status = SendControlPacket(Adapter, pControlPacket);
-				if(STATUS_SUCCESS==Status)
-				{
+				if (STATUS_SUCCESS == Status) {
 					spin_lock_bh(&psSF->SFQueueLock);
 					psSF->NumOfPacketsSent++;
-					psSF->uiSentBytes+=((struct bcm_leader *)pControlPacket)->PLength;
+					psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength;
 					psSF->uiSentPackets++;
 					atomic_dec(&Adapter->TotalPacketCount);
 					psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength;
 					psSF->uiCurrentPacketsOnHost--;
 					atomic_inc(&Adapter->index_rd_txcntrlpkt);
 					spin_unlock_bh(&psSF->SFQueueLock);
+				} else {
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
 				}
-				else
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
-			}
-			else
-			{
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
+			} else {
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
 			}
-	   	}
+		}
 	}
 }
 
@@ -277,79 +247,71 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct
 ********************************************************************/
 VOID transmit_packets(struct bcm_mini_adapter *Adapter)
 {
-	UINT 	uiPrevTotalCount = 0;
+	UINT uiPrevTotalCount = 0;
 	int iIndex = 0;
 
-	BOOLEAN exit_flag = TRUE ;
+	BOOLEAN exit_flag = TRUE;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
 
-	if(NULL == Adapter)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
+	if (NULL == Adapter) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
 		return;
 	}
-	if(Adapter->device_removed == TRUE)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
+	if (Adapter->device_removed == TRUE) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
 		return;
 	}
 
-    BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
 
 	UpdateTokenCount(Adapter);
 
-    BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
 
 	PruneQueueAllSF(Adapter);
 
 	uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
 
-	for(iIndex=HiPriority;iIndex>=0;iIndex--)
-	{
-		if(	!uiPrevTotalCount || (TRUE == Adapter->device_removed))
+	for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
+		if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
 				break;
 
-		if(Adapter->PackInfo[iIndex].bValid &&
-			Adapter->PackInfo[iIndex].uiPendedLast &&
-			Adapter->PackInfo[iIndex].uiCurrentBytesOnHost)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+		if (Adapter->PackInfo[iIndex].bValid &&
+		    Adapter->PackInfo[iIndex].uiPendedLast &&
+		    Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
 			CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
 			uiPrevTotalCount--;
 		}
 	}
 
-	while(uiPrevTotalCount > 0 && !Adapter->device_removed)
-	{
-		exit_flag = TRUE ;
-			//second iteration to parse non-pending queues
-		for(iIndex=HiPriority;iIndex>=0;iIndex--)
-		{
-			if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
-					break;
-
-			if(Adapter->PackInfo[iIndex].bValid &&
-				Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
-				!Adapter->PackInfo[iIndex].uiPendedLast )
-			{
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+	while (uiPrevTotalCount > 0 && !Adapter->device_removed) {
+		exit_flag = TRUE;
+		/* second iteration to parse non-pending queues */
+		for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
+			if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
+				break;
+
+			if (Adapter->PackInfo[iIndex].bValid &&
+			    Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
+			    !Adapter->PackInfo[iIndex].uiPendedLast) {
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
 				CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
 				uiPrevTotalCount--;
 				exit_flag = FALSE;
 			}
 		}
 
-		if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
+		if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
 			break;
 		}
-		if(exit_flag == TRUE )
-		    break ;
-	}/* end of inner while loop */
+		if (exit_flag == TRUE)
+			break;
+	} /* end of inner while loop */
 
-	update_per_cid_rx  (Adapter);
+	update_per_cid_rx(Adapter);
 	Adapter->txtransmit_running = 0;
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
 }
diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c
index 8d142a5..2d4a77c 100644
--- a/drivers/staging/bcm/Qos.c
+++ b/drivers/staging/bcm/Qos.c
@@ -4,11 +4,11 @@ This file contains the routines related to Quality of Service.
 */
 #include "headers.h"
 
-static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo);
-static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo,struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport);
+static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo);
+static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo, struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport);
 
 static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd,
-			   struct bcm_classifier_rule *pstClassifierRule );
+			   struct bcm_classifier_rule *pstClassifierRule);
 
 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex);
 
@@ -20,30 +20,30 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex);
 *				matches with that of Queue.
 *
 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
-* 			  - ulSrcIP	    : Source IP address from the packet.
+*		- ulSrcIP	    : Source IP address from the packet.
 *
 * Returns     - TRUE(If address matches) else FAIL .
 *********************************************************************/
-BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulSrcIP)
+BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulSrcIP)
 {
-    UCHAR 	ucLoopIndex=0;
-
-    struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-
-    ulSrcIP=ntohl(ulSrcIP);
-    if(0 == pstClassifierRule->ucIPSourceAddressLength)
-       	return TRUE;
-    for(ucLoopIndex=0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);ucLoopIndex++)
-    {
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]);
-		if((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP)==
-				(pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] ))
-       	{
-       		return TRUE;
-       	}
-    }
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
-   	return FALSE;
+	UCHAR ucLoopIndex = 0;
+
+	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+	ulSrcIP = ntohl(ulSrcIP);
+	if (0 == pstClassifierRule->ucIPSourceAddressLength)
+		return TRUE;
+	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); ucLoopIndex++)
+	{
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]);
+		if ((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
+				(pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]))
+		{
+			return TRUE;
+		}
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
+	return FALSE;
 }
 
 
@@ -54,30 +54,30 @@ BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ul
 *				matches with that of Queue.
 *
 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
-* 			  - ulDestIP    : Destination IP address from the packet.
+*		- ulDestIP    : Destination IP address from the packet.
 *
 * Returns     - TRUE(If address matches) else FAIL .
 *********************************************************************/
-BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulDestIP)
+BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP)
 {
-	UCHAR 	ucLoopIndex=0;
+	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	ulDestIP=ntohl(ulDestIP);
-    if(0 == pstClassifierRule->ucIPDestinationAddressLength)
-       	return TRUE;
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x  ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]);
-
-    for(ucLoopIndex=0;ucLoopIndex<(pstClassifierRule->ucIPDestinationAddressLength);ucLoopIndex++)
-    {
-		if((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP)==
-					(pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex]))
-       	{
-       		return TRUE;
-       	}
-    }
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
-    return FALSE;
+	ulDestIP = ntohl(ulDestIP);
+	if (0 == pstClassifierRule->ucIPDestinationAddressLength)
+		return TRUE;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x  ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]);
+
+	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); ucLoopIndex++)
+	{
+		if ((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP) ==
+				(pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex]))
+		{
+			return TRUE;
+		}
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
+	return FALSE;
 }
 
 
@@ -87,23 +87,23 @@ BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG u
 * Description - Checks the TOS from the packet matches with that of queue.
 *
 * Parameters  - pstClassifierRule   : Pointer to the packet info structure.
-* 			  - ucTypeOfService: TOS from the packet.
+*		- ucTypeOfService: TOS from the packet.
 *
 * Returns     - TRUE(If address matches) else FAIL.
 **************************************************************************/
-BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfService)
+BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucTypeOfService)
 {
 
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    if( 3 != pstClassifierRule->ucIPTypeOfServiceLength )
-       	return TRUE;
-
-    if(((pstClassifierRule->ucTosMask & ucTypeOfService)<=pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService)>=pstClassifierRule->ucTosLow))
-    {
-       	return TRUE;
-    }
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
-    return FALSE;
+	if (3 != pstClassifierRule->ucIPTypeOfServiceLength)
+		return TRUE;
+
+	if (((pstClassifierRule->ucTosMask & ucTypeOfService) <= pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService) >= pstClassifierRule->ucTosLow))
+	{
+		return TRUE;
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
+	return FALSE;
 }
 
 
@@ -113,26 +113,26 @@ BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfSer
 * Description - Checks the protocol from the packet matches with that of queue.
 *
 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
-* 			  - ucProtocol	: Protocol from the packet.
+*		- ucProtocol	: Protocol from the packet.
 *
 * Returns     - TRUE(If address matches) else FAIL.
 ****************************************************************************/
-bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol)
+bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucProtocol)
 {
-   	UCHAR 	ucLoopIndex=0;
+	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	if(0 == pstClassifierRule->ucProtocolLength)
-      	return TRUE;
-	for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucProtocolLength;ucLoopIndex++)
-    {
-       	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X",ucProtocol,pstClassifierRule->ucProtocol[ucLoopIndex]);
-       	if(pstClassifierRule->ucProtocol[ucLoopIndex]==ucProtocol)
-       	{
-       		return TRUE;
-       	}
-    }
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
-   	return FALSE;
+	if (0 == pstClassifierRule->ucProtocolLength)
+		return TRUE;
+	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucProtocolLength; ucLoopIndex++)
+	{
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X", ucProtocol, pstClassifierRule->ucProtocol[ucLoopIndex]);
+		if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol)
+		{
+			return TRUE;
+		}
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
+	return FALSE;
 }
 
 
@@ -142,29 +142,29 @@ bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtoco
 * Description - Checks, Source port from the packet matches with that of queue.
 *
 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
-* 			  - ushSrcPort	: Source port from the packet.
+*		- ushSrcPort	: Source port from the packet.
 *
 * Returns     - TRUE(If address matches) else FAIL.
 ***************************************************************************/
-bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort)
+bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPort)
 {
-    	UCHAR 	ucLoopIndex=0;
+	UCHAR ucLoopIndex = 0;
 
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
 
-    	if(0 == pstClassifierRule->ucSrcPortRangeLength)
-        	return TRUE;
-    	for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucSrcPortRangeLength;ucLoopIndex++)
-    	{
-        	if(ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
-		    ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
-	    	{
-		    	return TRUE;
-	    	}
-    	}
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ",ushSrcPort);
-    	return FALSE;
+	if (0 == pstClassifierRule->ucSrcPortRangeLength)
+		return TRUE;
+	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; ucLoopIndex++)
+	{
+		if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
+			ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
+		{
+			return TRUE;
+		}
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ", ushSrcPort);
+	return FALSE;
 }
 
 
@@ -174,30 +174,30 @@ bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPor
 * Description - Checks, Destination port from packet matches with that of queue.
 *
 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
-* 			  - ushDestPort	: Destination port from the packet.
+*		- ushDestPort	: Destination port from the packet.
 *
 * Returns     - TRUE(If address matches) else FAIL.
 ***************************************************************************/
-bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushDestPort)
+bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushDestPort)
 {
-    	UCHAR 	ucLoopIndex=0;
+	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-    	if(0 == pstClassifierRule->ucDestPortRangeLength)
-        	return TRUE;
-
-    	for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucDestPortRangeLength;ucLoopIndex++)
-    	{
-        	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X   0x%X  0x%X",ushDestPort,pstClassifierRule->usDestPortRangeLo[ucLoopIndex],pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
-
- 		if(ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
-		    ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
-	    	{
-		    return TRUE;
-	    	}
-    	}
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched",ushDestPort);
-    	return FALSE;
+	if (0 == pstClassifierRule->ucDestPortRangeLength)
+		return TRUE;
+
+	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; ucLoopIndex++)
+	{
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X   0x%X  0x%X", ushDestPort, pstClassifierRule->usDestPortRangeLo[ucLoopIndex], pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
+
+		if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
+			ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
+		{
+			return TRUE;
+		}
+	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched", ushDestPort);
+	return FALSE;
 }
 /**
 @ingroup tx_functions
@@ -209,95 +209,95 @@ static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter,
 			   struct bcm_classifier_rule *pstClassifierRule)
 {
 	struct bcm_transport_header *xprt_hdr = NULL;
-	BOOLEAN	bClassificationSucceed=FALSE;
+	BOOLEAN	bClassificationSucceed = FALSE;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>");
 
-	xprt_hdr=(struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr));
+	xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr));
 
 	do {
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d",
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d",
 			pstClassifierRule->ucDirection,
 			pstClassifierRule->usVCID_Value);
 
 		//Checking classifier validity
-		if(!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
+		if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
 		{
 			bClassificationSucceed = FALSE;
 			break;
 		}
 
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
-		if(pstClassifierRule->bIpv6Protocol)
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
+		if (pstClassifierRule->bIpv6Protocol)
 			break;
 
 		//**************Checking IP header parameter**************************//
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
-		if(FALSE == (bClassificationSucceed =
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
+		if (FALSE == (bClassificationSucceed =
 			MatchSrcIpAddress(pstClassifierRule, iphd->saddr)))
 			break;
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
 
-		if(FALSE == (bClassificationSucceed =
+		if (FALSE == (bClassificationSucceed =
 			MatchDestIpAddress(pstClassifierRule, iphd->daddr)))
 			break;
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
 
-		if(FALSE == (bClassificationSucceed =
+		if (FALSE == (bClassificationSucceed =
 			MatchTos(pstClassifierRule, iphd->tos)))
 		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
 			break;
 		}
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
 
-		if(FALSE == (bClassificationSucceed =
-			MatchProtocol(pstClassifierRule,iphd->protocol)))
+		if (FALSE == (bClassificationSucceed =
+			MatchProtocol(pstClassifierRule, iphd->protocol)))
 			break;
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
 
 		//if protocol is not TCP or UDP then no need of comparing source port and destination port
-		if(iphd->protocol!=TCP && iphd->protocol!=UDP)
+		if (iphd->protocol != TCP && iphd->protocol != UDP)
 			break;
 		//******************Checking Transport Layer Header field if present *****************//
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
-			(iphd->protocol==UDP)?xprt_hdr->uhdr.source:xprt_hdr->thdr.source);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
+			(iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
 
-		if(FALSE == (bClassificationSucceed =
+		if (FALSE == (bClassificationSucceed =
 			MatchSrcPort(pstClassifierRule,
-				ntohs((iphd->protocol == UDP)?
-				xprt_hdr->uhdr.source:xprt_hdr->thdr.source))))
+				ntohs((iphd->protocol == UDP) ?
+				xprt_hdr->uhdr.source : xprt_hdr->thdr.source))))
 			break;
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
 
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
-			(iphd->protocol==UDP)?xprt_hdr->uhdr.dest:
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
+			(iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
 			xprt_hdr->thdr.dest);
-		if(FALSE == (bClassificationSucceed =
+		if (FALSE == (bClassificationSucceed =
 			MatchDestPort(pstClassifierRule,
-			ntohs((iphd->protocol == UDP)?
-			xprt_hdr->uhdr.dest:xprt_hdr->thdr.dest))))
+			ntohs((iphd->protocol == UDP) ?
+			xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest))))
 			break;
-	} while(0);
+	} while (0);
 
-	if(TRUE==bClassificationSucceed)
+	if (TRUE == bClassificationSucceed)
 	{
 		INT iMatchedSFQueueIndex = 0;
-		iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID);
-		if(iMatchedSFQueueIndex >= NO_OF_QUEUES)
+		iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+		if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
 		{
 			bClassificationSucceed = FALSE;
 		}
 		else
 		{
-			if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
+			if (FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
 			{
 				bClassificationSucceed = FALSE;
 			}
 		}
 	}
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <==========");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <==========");
 
 	return bClassificationSucceed;
 }
@@ -306,9 +306,9 @@ VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter)
 {
 	UINT iIndex = 0;
 
-	for(iIndex = 0; iIndex < HiPriority; iIndex++)
+	for (iIndex = 0; iIndex < HiPriority; iIndex++)
 	{
-		if(!Adapter->PackInfo[iIndex].bValid)
+		if (!Adapter->PackInfo[iIndex].bValid)
 			continue;
 
 		PruneQueue(Adapter, iIndex);
@@ -325,15 +325,15 @@ less than or equal to max queue size for the queue.
 */
 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 {
-	struct sk_buff* PacketToDrop=NULL;
+	struct sk_buff* PacketToDrop = NULL;
 	struct net_device_stats *netstats;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d",iIndex);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d", iIndex);
 
-   	if(iIndex == HiPriority)
+	if (iIndex == HiPriority)
 		return;
 
-	if(!Adapter || (iIndex < 0) || (iIndex > HiPriority))
+	if (!Adapter || (iIndex < 0) || (iIndex > HiPriority))
 		return;
 
 	/* To Store the netdevice statistic */
@@ -341,26 +341,26 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 
 	spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
 
-	while(1)
+	while (1)
 //	while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
 //		SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
 		Adapter->PackInfo[iIndex].uiCurrentBytesOnHost,
 		Adapter->PackInfo[iIndex].uiMaxBucketSize);
 
 		PacketToDrop = Adapter->PackInfo[iIndex].FirstTxQueue;
 
-		if(PacketToDrop == NULL)
+		if (PacketToDrop == NULL)
 			break;
-		if((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
+		if ((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
 			((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb)+SKB_CB_LATENCY_OFFSET))/HZ) <= Adapter->PackInfo[iIndex].uiMaxLatency))
 			break;
 
-		if(PacketToDrop)
+		if (PacketToDrop)
 		{
 			if (netif_msg_tx_err(Adapter))
-				pr_info(PFX "%s: tx queue %d overlimit\n", 
+				pr_info(PFX "%s: tx queue %d overlimit\n",
 					Adapter->dev->name, iIndex);
 
 			netstats->tx_dropped++;
@@ -378,7 +378,7 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 
 		}
 
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
 			Adapter->PackInfo[iIndex].uiDroppedCountBytes,
 			Adapter->PackInfo[iIndex].uiDroppedCountPackets);
 
@@ -387,29 +387,29 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 
 	spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x",
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x",
 		atomic_read(&Adapter->TotalPacketCount));
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<=====");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<=====");
 }
 
 VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
 {
 	INT		iQIndex;
 	UINT	uiTotalPacketLength;
-	struct sk_buff*			PacketToDrop=NULL;
+	struct sk_buff*			PacketToDrop = NULL;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>");
 
 //	down(&Adapter->data_packet_queue_lock);
-	for(iQIndex=LowPriority; iQIndex<HiPriority; iQIndex++)
+	for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++)
 	{
 		struct net_device_stats *netstats = &Adapter->dev->stats;
 
 		spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
-		while(Adapter->PackInfo[iQIndex].FirstTxQueue)
+		while (Adapter->PackInfo[iQIndex].FirstTxQueue)
 		{
 			PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
-			if(PacketToDrop)
+			if (PacketToDrop)
 			{
 				uiTotalPacketLength = PacketToDrop->len;
 				netstats->tx_dropped++;
@@ -431,7 +431,7 @@ VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
 			Adapter->PackInfo[iQIndex].uiDroppedCountBytes += uiTotalPacketLength;
 			Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
 
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
 					Adapter->PackInfo[iQIndex].uiDroppedCountBytes,
 					Adapter->PackInfo[iQIndex].uiDroppedCountPackets);
 			atomic_dec(&Adapter->TotalPacketCount);
@@ -439,30 +439,30 @@ VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
 		spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
 	}
 //	up(&Adapter->data_packet_queue_lock);
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<=====");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<=====");
 }
 
-USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb)
+USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 {
-	INT			uiLoopIndex=0;
+	INT			uiLoopIndex = 0;
 	struct bcm_classifier_rule *pstClassifierRule = NULL;
 	struct bcm_eth_packet_info stEthCsPktInfo;
 	PVOID pvEThPayload = NULL;
-	struct iphdr 		*pIpHeader = NULL;
-	INT	  uiSfIndex=0;
-	USHORT	usIndex=Adapter->usBestEffortQueueIndex;
-	BOOLEAN	bFragmentedPkt=FALSE,bClassificationSucceed=FALSE;
-	USHORT	usCurrFragment =0;
+	struct iphdr *pIpHeader = NULL;
+	INT	  uiSfIndex = 0;
+	USHORT	usIndex = Adapter->usBestEffortQueueIndex;
+	BOOLEAN	bFragmentedPkt = FALSE, bClassificationSucceed = FALSE;
+	USHORT	usCurrFragment = 0;
 
 	struct bcm_tcp_header *pTcpHeader;
 	UCHAR IpHeaderLength;
 	UCHAR TcpHeaderLength;
 
 	pvEThPayload = skb->data;
-	*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = 0;
-	EThCSGetPktInfo(Adapter,pvEThPayload,&stEthCsPktInfo);
+	*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET) = 0;
+	EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo);
 
-	switch(stEthCsPktInfo.eNwpktEthFrameType)
+	switch (stEthCsPktInfo.eNwpktEthFrameType)
 	{
 		case eEth802LLCFrame:
 		{
@@ -497,75 +497,75 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb)
 		}
 	}
 
-	if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
+	if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
 	{
 		usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET);
-		if((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
+		if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
 			bFragmentedPkt = TRUE;
 
-		if(bFragmentedPkt)
+		if (bFragmentedPkt)
 		{
 				//Fragmented  Packet. Get Frag Classifier Entry.
-			pstClassifierRule = GetFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr);
-			if(pstClassifierRule)
+			pstClassifierRule = GetFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
+			if (pstClassifierRule)
 			{
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"It is next Fragmented pkt");
-					bClassificationSucceed=TRUE;
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "It is next Fragmented pkt");
+					bClassificationSucceed = TRUE;
 			}
-			if(!(ntohs(pIpHeader->frag_off) & IP_MF))
+			if (!(ntohs(pIpHeader->frag_off) & IP_MF))
 			{
 				//Fragmented Last packet . Remove Frag Classifier Entry
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"This is the last fragmented Pkt");
-				DelFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr);
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "This is the last fragmented Pkt");
+				DelFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
 			}
 		}
 	}
 
-	for(uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--)
+	for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--)
 	{
-		if(bClassificationSucceed)
+		if (bClassificationSucceed)
 			break;
 		//Iterate through all classifiers which are already in order of priority
 		//to classify the packet until match found
 		do
 		{
-			if(FALSE==Adapter->astClassifierTable[uiLoopIndex].bUsed)
+			if (FALSE == Adapter->astClassifierTable[uiLoopIndex].bUsed)
 			{
-				bClassificationSucceed=FALSE;
+				bClassificationSucceed = FALSE;
 				break;
 			}
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Adapter->PackInfo[%d].bvalid=True\n",uiLoopIndex);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex);
 
-			if(0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection)
+			if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection)
 			{
-				bClassificationSucceed=FALSE;//cannot be processed for classification.
+				bClassificationSucceed = FALSE;//cannot be processed for classification.
 				break;						// it is a down link connection
 			}
 
 			pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
 
-			uiSfIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID);
+			uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
 			if (uiSfIndex >= NO_OF_QUEUES) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Queue Not Valid. SearchSfid for this classifier Failed\n");
 				break;
 			}
 
-			if(Adapter->PackInfo[uiSfIndex].bEthCSSupport)
+			if (Adapter->PackInfo[uiSfIndex].bEthCSSupport)
 			{
 
-				if(eEthUnsupportedFrame==stEthCsPktInfo.eNwpktEthFrameType)
+				if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType)
 				{
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame \n");
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
 					bClassificationSucceed = FALSE;
 					break;
 				}
 
 
 
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n",pstClassifierRule->uiClassifierRuleIndex,Adapter->PackInfo[uiSfIndex].ulSFID);
-				bClassificationSucceed = EThCSClassifyPkt(Adapter,skb,&stEthCsPktInfo,pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport);
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", pstClassifierRule->uiClassifierRuleIndex, Adapter->PackInfo[uiSfIndex].ulSFID);
+				bClassificationSucceed = EThCSClassifyPkt(Adapter, skb, &stEthCsPktInfo, pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport);
 
-				if(!bClassificationSucceed)
+				if (!bClassificationSucceed)
 				{
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ClassifyPacket : Ethernet CS Classification Failed\n");
 					break;
@@ -574,9 +574,9 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb)
 
 			else // No ETH Supported on this SF
 			{
-				if(eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType)
+				if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType)
 				{
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF \n");
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
 					bClassificationSucceed = FALSE;
 					break;
 				}
@@ -584,51 +584,51 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb)
 
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Proceeding to IP CS Clasification");
 
-			if(Adapter->PackInfo[uiSfIndex].bIPCSSupport)
+			if (Adapter->PackInfo[uiSfIndex].bIPCSSupport)
 			{
 
-				if(stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket)
+				if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket)
 				{
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  " ClassifyPacket : Packet is Not an IP Packet \n");
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n");
 					bClassificationSucceed = FALSE;
 					break;
 				}
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Dump IP Header : \n");
-				DumpFullPacket((PUCHAR)pIpHeader,20);
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header :\n");
+				DumpFullPacket((PUCHAR)pIpHeader, 20);
 
-				if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
-					bClassificationSucceed = IpVersion4(Adapter,pIpHeader,pstClassifierRule);
-				else if(stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
-					bClassificationSucceed = IpVersion6(Adapter,pIpHeader,pstClassifierRule);
+				if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
+					bClassificationSucceed = IpVersion4(Adapter, pIpHeader, pstClassifierRule);
+				else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
+					bClassificationSucceed = IpVersion6(Adapter, pIpHeader, pstClassifierRule);
 			}
 
-		}while(0);
+		} while (0);
 	}
 
-	if(bClassificationSucceed == TRUE)
+	if (bClassificationSucceed == TRUE)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu",pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu", pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
 
 		//Store The matched Classifier in SKB
 		*((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex;
-		if((TCP == pIpHeader->protocol ) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len) )
+		if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len))
 		{
 			 IpHeaderLength   = pIpHeader->ihl;
 			 pTcpHeader = (struct bcm_tcp_header *)(((PUCHAR)pIpHeader)+(IpHeaderLength*4));
 			 TcpHeaderLength  = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
 
-			if((pTcpHeader->ucFlags & TCP_ACK) &&
+			if ((pTcpHeader->ucFlags & TCP_ACK) &&
 			   (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4)))
 			{
-    			*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = TCP_ACK;
+				*((UINT32*) (skb->cb) + SKB_CB_TCPACK_OFFSET) = TCP_ACK;
 			}
 		}
 
 		usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is	=%d", usIndex);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is	=%d", usIndex);
 
 		//If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt.
-		if(bFragmentedPkt && (usCurrFragment == 0))
+		if (bFragmentedPkt && (usCurrFragment == 0))
 		{
 			//First Fragment of Fragmented Packet. Create Frag CLS Entry
 			struct bcm_fragmented_packet_info stFragPktInfo;
@@ -637,77 +637,77 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb)
 			stFragPktInfo.usIpIdentification = pIpHeader->id;
 			stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule;
 			stFragPktInfo.bOutOfOrderFragment = FALSE;
-			AddFragIPClsEntry(Adapter,&stFragPktInfo);
+			AddFragIPClsEntry(Adapter, &stFragPktInfo);
 		}
 
 
 	}
 
-	if(bClassificationSucceed)
+	if (bClassificationSucceed)
 		return usIndex;
 	else
 		return INVALID_QUEUE_INDEX;
 }
 
-static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac)
+static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
 {
-	UINT i=0;
+	UINT i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	if(pstClassifierRule->ucEthCSSrcMACLen==0)
+	if (pstClassifierRule->ucEthCSSrcMACLen == 0)
 		return TRUE;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s \n",__FUNCTION__);
-	for(i=0;i<MAC_ADDRESS_SIZE;i++)
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s\n", __FUNCTION__);
+	for (i = 0; i < MAC_ADDRESS_SIZE; i++)
 	{
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",i,Mac[i],pstClassifierRule->au8EThCSSrcMAC[i],pstClassifierRule->au8EThCSSrcMACMask[i]);
-		if((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i])!=
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]);
+		if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) !=
 			(Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
 			return FALSE;
 	}
 	return TRUE;
 }
 
-static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac)
+static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
 {
-	UINT i=0;
+	UINT i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	if(pstClassifierRule->ucEthCSDestMACLen==0)
+	if (pstClassifierRule->ucEthCSDestMACLen == 0)
 		return TRUE;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s \n",__FUNCTION__);
-	for(i=0;i<MAC_ADDRESS_SIZE;i++)
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __FUNCTION__);
+	for (i = 0; i < MAC_ADDRESS_SIZE; i++)
 	{
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",i,Mac[i],pstClassifierRule->au8EThCSDestMAC[i],pstClassifierRule->au8EThCSDestMACMask[i]);
-		if((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i])!=
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]);
+		if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) !=
 			(Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
 			return FALSE;
 	}
 	return TRUE;
 }
 
-static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	if((pstClassifierRule->ucEtherTypeLen==0)||
+	if ((pstClassifierRule->ucEtherTypeLen == 0) ||
 		(pstClassifierRule->au8EthCSEtherType[0] == 0))
 		return TRUE;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s SrcEtherType:%x CLS EtherType[0]:%x\n",__FUNCTION__,pstEthCsPktInfo->usEtherType,pstClassifierRule->au8EthCSEtherType[0]);
-	if(pstClassifierRule->au8EthCSEtherType[0] == 1)
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __FUNCTION__, pstEthCsPktInfo->usEtherType, pstClassifierRule->au8EthCSEtherType[0]);
+	if (pstClassifierRule->au8EthCSEtherType[0] == 1)
 	{
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS EtherType[1]:%x EtherType[2]:%x\n",__FUNCTION__,pstClassifierRule->au8EthCSEtherType[1],pstClassifierRule->au8EthCSEtherType[2]);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS EtherType[1]:%x EtherType[2]:%x\n", __FUNCTION__, pstClassifierRule->au8EthCSEtherType[1], pstClassifierRule->au8EthCSEtherType[2]);
 
-		if(memcmp(&pstEthCsPktInfo->usEtherType,&pstClassifierRule->au8EthCSEtherType[1],2)==0)
+		if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0)
 			return TRUE;
 		else
 			return FALSE;
 	}
 
-	if(pstClassifierRule->au8EthCSEtherType[0] == 2)
+	if (pstClassifierRule->au8EthCSEtherType[0] == 2)
 	{
-		if(eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
+		if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
 			return FALSE;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  EthCS DSAP:%x EtherType[2]:%x\n",__FUNCTION__,pstEthCsPktInfo->ucDSAP,pstClassifierRule->au8EthCSEtherType[2]);
-		if(pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2])
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  EthCS DSAP:%x EtherType[2]:%x\n", __FUNCTION__, pstEthCsPktInfo->ucDSAP, pstClassifierRule->au8EthCSEtherType[2]);
+		if (pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2])
 			return TRUE;
 		else
 			return FALSE;
@@ -718,27 +718,27 @@ static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRul
 
 }
 
-static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
 	BOOLEAN bClassificationSucceed = FALSE;
 	USHORT usVLANID;
 	B_UINT8 uPriority = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS UserPrio:%x CLS VLANID:%x\n", __FUNCTION__, ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), pstClassifierRule->usVLANID);
 
 	/* In case FW didn't receive the TLV, the priority field should be ignored */
-	if(pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID))
+	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID))
 	{
-		if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame)
+		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
 				return FALSE;
 
 		uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13;
 
-		if((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1]))
+		if ((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1]))
 				bClassificationSucceed = TRUE;
 
-		if(!bClassificationSucceed)
+		if (!bClassificationSucceed)
 			return FALSE;
 	}
 
@@ -746,19 +746,19 @@ static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule
 
 	bClassificationSucceed = FALSE;
 
-	if(pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID))
+	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID))
 	{
-		if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame)
+		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
 				return FALSE;
 
 		usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  Pkt VLANID %x Priority: %d\n",__FUNCTION__,usVLANID, uPriority);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  Pkt VLANID %x Priority: %d\n", __FUNCTION__, usVLANID, uPriority);
 
-		if(usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
+		if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
 			bClassificationSucceed = TRUE;
 
-		if(!bClassificationSucceed)
+		if (!bClassificationSucceed)
 			return FALSE;
 	}
 
@@ -768,50 +768,50 @@ static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule
 }
 
 
-static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb,
+static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb,
 				struct bcm_eth_packet_info *pstEthCsPktInfo,
 				struct bcm_classifier_rule *pstClassifierRule,
 				B_UINT8 EthCSCupport)
 {
 	BOOLEAN bClassificationSucceed = FALSE;
-	bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
-	if(!bClassificationSucceed)
+	bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
+	if (!bClassificationSucceed)
 		return FALSE;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS SrcMAC Matched\n");
 
-	bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
-	if(!bClassificationSucceed)
+	bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
+	if (!bClassificationSucceed)
 		return FALSE;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS DestMAC Matched\n");
 
 	//classify on ETHType/802.2SAP TLV
-	bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,skb,pstEthCsPktInfo);
-	if(!bClassificationSucceed)
+	bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, skb, pstEthCsPktInfo);
+	if (!bClassificationSucceed)
 		return FALSE;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS EthType/802.2SAP Matched\n");
 
 	//classify on 802.1VLAN Header Parameters
 
-	bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,skb,pstEthCsPktInfo);
-	if(!bClassificationSucceed)
+	bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, skb, pstEthCsPktInfo);
+	if (!bClassificationSucceed)
 		return FALSE;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 VLAN Rules Matched\n");
 
 	return bClassificationSucceed;
 }
 
-static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload,
+static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload,
 			    struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
 	USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype);
-	if(u16Etype > 0x5dc)
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype);
+	if (u16Etype > 0x5dc)
 	{
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : ETH2 Frame \n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame\n");
 		//ETH2 Frame
-		if(u16Etype == ETHERNET_FRAMETYPE_802QVLAN)
+		if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN)
 		{
 			//802.1Q VLAN Header
 			pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
@@ -828,27 +828,27 @@ static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload,
 	else
 	{
 		//802.2 LLC
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "802.2 LLC Frame \n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame\n");
 		pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame;
 		pstEthCsPktInfo->ucDSAP = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
-		if(pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA)
+		if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA)
 		{
 			//SNAP Frame
 			pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
 			u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType;
 		}
 	}
-	if(u16Etype == ETHERNET_FRAMETYPE_IPV4)
+	if (u16Etype == ETHERNET_FRAMETYPE_IPV4)
 		pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet;
-	else if(u16Etype == ETHERNET_FRAMETYPE_IPV6)
+	else if (u16Etype == ETHERNET_FRAMETYPE_IPV6)
 		pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet;
 	else
 		pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket;
 
 	pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->eNwpktIPFrameType : %x\n",pstEthCsPktInfo->eNwpktIPFrameType);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->eNwpktEthFrameType : %x\n",pstEthCsPktInfo->eNwpktEthFrameType);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->usEtherType : %x\n",pstEthCsPktInfo->usEtherType);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo->eNwpktIPFrameType);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo->eNwpktEthFrameType);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo->usEtherType);
 }
 
 
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 8c8a551..a84aab4 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -100,7 +100,6 @@ endif # COMEDI_MISC_DRIVERS
 
 menuconfig COMEDI_ISA_DRIVERS
 	bool "Comedi ISA and PC/104 drivers"
-	depends on ISA
 	---help---
 	  Enable comedi ISA and PC/104 drivers to be built
 
@@ -122,8 +121,18 @@ config COMEDI_PCL724
 	tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO"
 	select COMEDI_8255
 	---help---
-	  Enable support for Advantech PCL-724, PCL-722, PCL-731 and
-	  ADlink ACL-7122, ACL-7124, PET-48DIO ISA cards
+	  Enable support for ISA and PC/104 based 8255 digital i/o boards. This
+	  driver provides a legacy comedi driver wrapper for the generic 8255
+	  support driver.
+
+	  Supported boards include:
+	    Advantech PCL-724    24 channels
+	    Advantech PCL-722    144 (or 96) channels
+	    Advantech PCL-731    48 channels
+	    ADlink ACL-7122      144 (or 96) channels
+	    ADlink ACL-7124      24 channels
+	    ADlink PET-48DIO     48 channels
+	    WinSystems PCM-IO48  48 channels (PC/104)
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called pcl724.
@@ -403,6 +412,15 @@ config COMEDI_AIO_IIRO_16
 	  To compile this driver as a module, choose M here: the module will be
 	  called aio_iiro_16.
 
+config COMEDI_II_PCI20KC
+	tristate "Intelligent Instruments PCI-20001C carrier support"
+	---help---
+	  Enable support for Intelligent Instruments PCI-20001C carrier
+	  PCI-20001, PCI-20006 and PCI-20341
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ii_pci20kc.
+
 config COMEDI_C6XDIGIO
 	tristate "Mechatronic Systems Inc. C6x_DIGIO DSP daughter card support"
 	---help---
@@ -448,7 +466,6 @@ config COMEDI_NI_AT_AO
 
 config COMEDI_NI_ATMIO
 	tristate "NI AT-MIO E series ISA-PNP card support"
-	depends on ISAPNP
 	select COMEDI_8255
 	select COMEDI_NI_TIO
 	---help---
@@ -461,11 +478,10 @@ config COMEDI_NI_ATMIO
 	  called ni_atmio.
 
 config COMEDI_NI_ATMIO16D
-	tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support"
-	depends on ISAPNP
+	tristate "NI AT-MIO-16/AT-MIO-16D series ISA card support"
 	select COMEDI_8255
 	---help---
-	  Enable support for National Instruments AT-MIO16/AT-MIO16D cards.
+	  Enable support for National Instruments AT-MIO-16/AT-MIO-16D cards.
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called ni_atmio16d.
@@ -473,7 +489,7 @@ config COMEDI_NI_ATMIO16D
 config COMEDI_NI_LABPC_ISA
 	tristate "NI Lab-PC and compatibles ISA support"
 	select COMEDI_NI_LABPC
-	depends on VIRT_TO_BUS
+	select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API && VIRT_TO_BUS
 	---help---
 	  Enable support for National Instruments Lab-PC and compatibles
 	  Lab-PC-1200, Lab-PC-1200AI, Lab-PC+.
@@ -866,15 +882,6 @@ config COMEDI_ICP_MULTI
 	  To compile this driver as a module, choose M here: the module will be
 	  called icp_multi.
 
-config COMEDI_II_PCI20KC
-	tristate "Intelligent Instruments PCI-20001C carrier support"
-	---help---
-	  Enable support for Intelligent Instruments PCI-20001C carrier
-	  PCI-20001, PCI-20006 and PCI-20341
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called ii_pci20kc.
-
 config COMEDI_DAQBOARD2000
 	tristate "IOtech DAQboard/2000 support"
 	select COMEDI_8255
@@ -1262,6 +1269,9 @@ config COMEDI_NI_LABPC
 	select COMEDI_8255
 	select COMEDI_FC
 
+config COMEDI_NI_LABPC_ISADMA
+	tristate
+
 config COMEDI_NI_TIO
 	tristate
 
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index b4c001b..94b2385f 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -15,6 +15,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/vmalloc.h>
+
 #include "comedidev.h"
 #include "comedi_internal.h"
 
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index f4a197b..1636c7c 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -26,7 +26,6 @@
 #include <linux/sched.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
-#include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
@@ -262,7 +261,7 @@ static int resize_async_buffer(struct comedi_device *dev,
 
 /* sysfs attribute files */
 
-static ssize_t show_max_read_buffer_kb(struct device *csdev,
+static ssize_t max_read_buffer_kb_show(struct device *csdev,
 				       struct device_attribute *attr, char *buf)
 {
 	unsigned int minor = MINOR(csdev->devt);
@@ -283,7 +282,7 @@ static ssize_t show_max_read_buffer_kb(struct device *csdev,
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_max_read_buffer_kb(struct device *csdev,
+static ssize_t max_read_buffer_kb_store(struct device *csdev,
 					struct device_attribute *attr,
 					const char *buf, size_t count)
 {
@@ -314,8 +313,9 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev,
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(max_read_buffer_kb);
 
-static ssize_t show_read_buffer_kb(struct device *csdev,
+static ssize_t read_buffer_kb_show(struct device *csdev,
 				   struct device_attribute *attr, char *buf)
 {
 	unsigned int minor = MINOR(csdev->devt);
@@ -336,7 +336,7 @@ static ssize_t show_read_buffer_kb(struct device *csdev,
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_read_buffer_kb(struct device *csdev,
+static ssize_t read_buffer_kb_store(struct device *csdev,
 				    struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
@@ -367,8 +367,9 @@ static ssize_t store_read_buffer_kb(struct device *csdev,
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(read_buffer_kb);
 
-static ssize_t show_max_write_buffer_kb(struct device *csdev,
+static ssize_t max_write_buffer_kb_show(struct device *csdev,
 					struct device_attribute *attr,
 					char *buf)
 {
@@ -390,7 +391,7 @@ static ssize_t show_max_write_buffer_kb(struct device *csdev,
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_max_write_buffer_kb(struct device *csdev,
+static ssize_t max_write_buffer_kb_store(struct device *csdev,
 					 struct device_attribute *attr,
 					 const char *buf, size_t count)
 {
@@ -421,8 +422,9 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev,
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(max_write_buffer_kb);
 
-static ssize_t show_write_buffer_kb(struct device *csdev,
+static ssize_t write_buffer_kb_show(struct device *csdev,
 				    struct device_attribute *attr, char *buf)
 {
 	unsigned int minor = MINOR(csdev->devt);
@@ -443,7 +445,7 @@ static ssize_t show_write_buffer_kb(struct device *csdev,
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_write_buffer_kb(struct device *csdev,
+static ssize_t write_buffer_kb_store(struct device *csdev,
 				     struct device_attribute *attr,
 				     const char *buf, size_t count)
 {
@@ -474,18 +476,16 @@ static ssize_t store_write_buffer_kb(struct device *csdev,
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(write_buffer_kb);
 
-static struct device_attribute comedi_dev_attrs[] = {
-	__ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR,
-		show_max_read_buffer_kb, store_max_read_buffer_kb),
-	__ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
-		show_read_buffer_kb, store_read_buffer_kb),
-	__ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR,
-		show_max_write_buffer_kb, store_max_write_buffer_kb),
-	__ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
-		show_write_buffer_kb, store_write_buffer_kb),
-	__ATTR_NULL
+static struct attribute *comedi_dev_attrs[] = {
+	&dev_attr_max_read_buffer_kb.attr,
+	&dev_attr_read_buffer_kb.attr,
+	&dev_attr_max_write_buffer_kb.attr,
+	&dev_attr_write_buffer_kb.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(comedi_dev);
 
 static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
 					  unsigned mask, unsigned bits)
@@ -2564,7 +2564,7 @@ static int __init comedi_init(void)
 		return PTR_ERR(comedi_class);
 	}
 
-	comedi_class->dev_attrs = comedi_dev_attrs;
+	comedi_class->dev_groups = comedi_dev_groups;
 
 	/* XXX requires /proc interface */
 	comedi_proc_init();
diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h
index d5e03e5..fda1a7b 100644
--- a/drivers/staging/comedi/comedi_internal.h
+++ b/drivers/staging/comedi/comedi_internal.h
@@ -24,6 +24,7 @@ extern unsigned int comedi_default_buf_maxsize_kb;
 /* drivers.c */
 
 extern struct comedi_driver *comedi_drivers;
+extern struct mutex comedi_drivers_list_lock;
 
 int insn_inval(struct comedi_device *, struct comedi_subdevice *,
 	       struct comedi_insn *, unsigned int *);
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index b75915f..76a5c2b 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -19,22 +19,7 @@
 #ifndef _COMEDIDEV_H
 #define _COMEDIDEV_H
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
 #include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/timer.h>
 
 #include "comedi.h"
 
@@ -357,6 +342,7 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
 
 /* drivers.c - general comedi driver functions */
 
+void *comedi_alloc_devpriv(struct comedi_device *, size_t);
 int comedi_alloc_subdevices(struct comedi_device *, int);
 
 int comedi_load_firmware(struct comedi_device *, struct device *,
@@ -377,7 +363,7 @@ int comedi_auto_config(struct device *, struct comedi_driver *,
 void comedi_auto_unconfig(struct device *);
 
 int comedi_driver_register(struct comedi_driver *);
-int comedi_driver_unregister(struct comedi_driver *);
+void comedi_driver_unregister(struct comedi_driver *);
 
 /**
  * module_comedi_driver() - Helper macro for registering a comedi driver
@@ -400,7 +386,6 @@ int comedi_driver_unregister(struct comedi_driver *);
  */
 #define PCI_VENDOR_ID_KOLTER		0x1001
 #define PCI_VENDOR_ID_ICP		0x104c
-#define PCI_VENDOR_ID_AMCC		0x10e8
 #define PCI_VENDOR_ID_DT		0x1116
 #define PCI_VENDOR_ID_IOTECH		0x1616
 #define PCI_VENDOR_ID_CONTEC		0x1221
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index e25eba5..791a26b 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -23,7 +23,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fcntl.h>
-#include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -39,6 +38,7 @@
 #include "comedi_internal.h"
 
 struct comedi_driver *comedi_drivers;
+DEFINE_MUTEX(comedi_drivers_list_lock);
 
 int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
 {
@@ -57,6 +57,18 @@ static void comedi_clear_hw_dev(struct comedi_device *dev)
 	dev->hw_dev = NULL;
 }
 
+/**
+ * comedi_alloc_devpriv() - Allocate memory for the device private data.
+ * @dev: comedi_device struct
+ * @size: size of the memory to allocate
+ */
+void *comedi_alloc_devpriv(struct comedi_device *dev, size_t size)
+{
+	dev->private = kzalloc(size, GFP_KERNEL);
+	return dev->private;
+}
+EXPORT_SYMBOL_GPL(comedi_alloc_devpriv);
+
 int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
 {
 	struct comedi_subdevice *s;
@@ -442,6 +454,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (dev->attached)
 		return -EBUSY;
 
+	mutex_lock(&comedi_drivers_list_lock);
 	for (driv = comedi_drivers; driv; driv = driv->next) {
 		if (!try_module_get(driv->module))
 			continue;
@@ -462,7 +475,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 			comedi_report_boards(driv);
 			module_put(driv->module);
 		}
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	if (driv->attach == NULL) {
 		/* driver does not support manual configuration */
@@ -470,7 +484,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 			 "driver '%s' does not support attach using comedi_config\n",
 			 driv->driver_name);
 		module_put(driv->module);
-		return -ENOSYS;
+		ret = -ENOSYS;
+		goto out;
 	}
 	/* initialize dev->driver here so
 	 * comedi_error() can be called from attach */
@@ -485,6 +500,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		module_put(dev->driver->module);
 	}
 	/* On success, the driver module count has been incremented. */
+out:
+	mutex_unlock(&comedi_drivers_list_lock);
 	return ret;
 }
 
@@ -541,18 +558,34 @@ EXPORT_SYMBOL_GPL(comedi_auto_unconfig);
 
 int comedi_driver_register(struct comedi_driver *driver)
 {
+	mutex_lock(&comedi_drivers_list_lock);
 	driver->next = comedi_drivers;
 	comedi_drivers = driver;
+	mutex_unlock(&comedi_drivers_list_lock);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(comedi_driver_register);
 
-int comedi_driver_unregister(struct comedi_driver *driver)
+void comedi_driver_unregister(struct comedi_driver *driver)
 {
 	struct comedi_driver *prev;
 	int i;
 
+	/* unlink the driver */
+	mutex_lock(&comedi_drivers_list_lock);
+	if (comedi_drivers == driver) {
+		comedi_drivers = driver->next;
+	} else {
+		for (prev = comedi_drivers; prev->next; prev = prev->next) {
+			if (prev->next == driver) {
+				prev->next = driver->next;
+				break;
+			}
+		}
+	}
+	mutex_unlock(&comedi_drivers_list_lock);
+
 	/* check for devices using this driver */
 	for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
 		struct comedi_device *dev = comedi_dev_from_minor(i);
@@ -570,18 +603,5 @@ int comedi_driver_unregister(struct comedi_driver *driver)
 		}
 		mutex_unlock(&dev->mutex);
 	}
-
-	if (comedi_drivers == driver) {
-		comedi_drivers = driver->next;
-		return 0;
-	}
-
-	for (prev = comedi_drivers; prev->next; prev = prev->next) {
-		if (prev->next == driver) {
-			prev->next = driver->next;
-			return 0;
-		}
-	}
-	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(comedi_driver_unregister);
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 94e1750..1fa29ac 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -73,10 +73,9 @@ I/O port base address can be found in the output of 'lspci -v'.
    will copy the latched value to a Comedi buffer.
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #include "comedi_fc.h"
 #include "8255.h"
 
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
index 3d3547c..432e3f9 100644
--- a/drivers/staging/comedi/drivers/8255_pci.c
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -50,6 +50,7 @@ Interrupt support for these boards is also not currently supported.
 Configuration Options: not applicable, uses PCI auto config
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -186,10 +187,9 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index dbb93e3..94cbd26 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_COMEDI_DMM32AT)		+= dmm32at.o
 obj-$(CONFIG_COMEDI_FL512)		+= fl512.o
 obj-$(CONFIG_COMEDI_AIO_AIO12_8)	+= aio_aio12_8.o
 obj-$(CONFIG_COMEDI_AIO_IIRO_16)	+= aio_iiro_16.o
+obj-$(CONFIG_COMEDI_II_PCI20KC)		+= ii_pci20kc.o
 obj-$(CONFIG_COMEDI_C6XDIGIO)		+= c6xdigio.o
 obj-$(CONFIG_COMEDI_MPC624)		+= mpc624.o
 obj-$(CONFIG_COMEDI_ADQ12B)		+= adq12b.o
@@ -89,7 +90,6 @@ obj-$(CONFIG_COMEDI_DYNA_PCI10XX)	+= dyna_pci10xx.o
 obj-$(CONFIG_COMEDI_UNIOXX5)		+= unioxx5.o
 obj-$(CONFIG_COMEDI_GSC_HPDI)		+= gsc_hpdi.o
 obj-$(CONFIG_COMEDI_ICP_MULTI)		+= icp_multi.o
-obj-$(CONFIG_COMEDI_II_PCI20KC)		+= ii_pci20kc.o
 obj-$(CONFIG_COMEDI_DAQBOARD2000)	+= daqboard2000.o
 obj-$(CONFIG_COMEDI_JR3_PCI)		+= jr3_pci.o
 obj-$(CONFIG_COMEDI_KE_COUNTER)		+= ke_counter.o
@@ -132,6 +132,7 @@ obj-$(CONFIG_COMEDI_MITE)		+= mite.o
 obj-$(CONFIG_COMEDI_NI_TIO)		+= ni_tio.o
 obj-$(CONFIG_COMEDI_NI_TIOCMD)		+= ni_tiocmd.o
 obj-$(CONFIG_COMEDI_NI_LABPC)		+= ni_labpc.o
+obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA)	+= ni_labpc_isadma.o
 
 obj-$(CONFIG_COMEDI_8255)		+= 8255.o
 obj-$(CONFIG_COMEDI_AMPLC_DIO200)	+= amplc_dio200_common.o
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
deleted file mode 100644
index d070208..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+++ /dev/null
@@ -1,1068 +0,0 @@
-/*
- *  Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.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.
- */
-/*
-  | Description :   APCI-1710 82X54 timer module                          |
-*/
-
-#define APCI1710_PCI_BUS_CLOCK			0
-#define APCI1710_FRONT_CONNECTOR_INPUT		1
-#define APCI1710_TIMER_READVALUE		0
-#define APCI1710_TIMER_GETOUTPUTLEVEL		1
-#define APCI1710_TIMER_GETPROGRESSSTATUS	2
-#define APCI1710_TIMER_WRITEVALUE		3
-
-#define APCI1710_TIMER_READINTERRUPT		1
-#define APCI1710_TIMER_READALLTIMER		2
-
-#ifndef APCI1710_10MHZ
-#define APCI1710_10MHZ				10
-#endif
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_InitTimer                         |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char_   b_TimerNbr,                         |
-|                                unsigned char_   b_TimerMode,                        |
-|                                ULONG_ ul_ReloadValue,                      |
-|                                unsigned char_   b_InputClockSelection,              |
-|                                unsigned char_   b_InputClockLevel,                  |
-|                                unsigned char_   b_OutputLevel,                      |
-|                                unsigned char_   b_HardwareGateLevel)
-int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
-	struct comedi_insn *insn,unsigned int *data)
-|
-+----------------------------------------------------------------------------+
-| Task              : Configure the Timer (b_TimerNbr) operating mode        |
-|                     (b_TimerMode) from selected module (b_ModulNbr).       |
-|                     You must calling this function be for you call any     |
-|                     other function witch access of the timer.              |
-|                                                                            |
-|                                                                            |
-|                       Timer mode description table                         |
-|                                                                            |
-|+--------+-----------------------------+--------------+--------------------+|
-||Selected+      Mode description       +u_ReloadValue | Hardware gate input||
-||  mode  |                             |  description |      action        ||
-|+--------+-----------------------------+--------------+--------------------+|
-||        |Mode 0 is typically used     |              |                    ||
-||        |for event counting. After    |              |                    ||
-||        |the initialisation, OUT      |              |                    ||
-||        |is initially low, and        |              |                    ||
-||   0    |will remain low until the    |Start counting|   Hardware gate    ||
-||        |counter reaches zero.        |   value      |                    ||
-||        |OUT then goes high and       |              |                    ||
-||        |remains high until a new     |              |                    ||
-||        |count is written. See        |              |                    ||
-||        |"i_APCI1710_WriteTimerValue" |              |                    ||
-||        |function.                    |              |                    ||
-|+--------+-----------------------------+--------------+--------------------+|
-||        |Mode 1 is similar to mode 0  |              |                    ||
-||        |except for the gate input    |              |                    ||
-||   1    |action. The gate input is not|Start counting|  Hardware trigger  ||
-||        |used for enabled or disabled |   value      |                    ||
-||        |the timer.                   |              |                    ||
-||        |The gate input is used for   |              |                    ||
-||        |triggered the timer.         |              |                    ||
-|+--------+-----------------------------+--------------+--------------------+|
-||        |This mode functions like a   |              |                    ||
-||        |divide-by-ul_ReloadValue     |              |                    ||
-||        |counter. It is typically used|              |                    ||
-||        |to generate a real time clock|              |                    ||
-||        |interrupt. OUT will initially|              |                    ||
-||   2    |be high after the            |   Division   |  Hardware gate     ||
-||        |initialisation. When the     |    factor    |                    ||
-||        |initial count has decremented|              |                    ||
-||        |to 1, OUT goes low for one   |              |                    ||
-||        |CLK pule. OUT then goes high |              |                    ||
-||        |again, the counter reloads   |              |                    ||
-||        |the initial count            |              |                    ||
-||        |(ul_ReloadValue) and the     |              |                    ||
-||        |process is repeated.         |              |                    ||
-||        |This action can generated a  |              |                    ||
-||        |interrupt. See function      |              |                    ||
-||        |"i_APCI1710_SetBoardInt-     |              |                    ||
-||        |RoutineX"                    |              |                    ||
-||        |and "i_APCI1710_EnableTimer" |              |                    ||
-|+--------+-----------------------------+--------------+--------------------+|
-||        |Mode 3 is typically used for |              |                    ||
-||        |baud rate generation. This   |              |                    ||
-||        |mode is similar to mode 2    |              |                    ||
-||        |except for the duty cycle of |              |                    ||
-||   3    |OUT. OUT will initially be   |  Division    |   Hardware gate    ||
-||        |high after the initialisation|   factor     |                    ||
-||        |When half the initial count  |              |                    ||
-||        |(ul_ReloadValue) has expired,|              |                    ||
-||        |OUT goes low for the         |              |                    ||
-||        |remainder of the count. The  |              |                    ||
-||        |mode is periodic; the        |              |                    ||
-||        |sequence above is repeated   |              |                    ||
-||        |indefinitely.                |              |                    ||
-|+--------+-----------------------------+--------------+--------------------+|
-||        |OUT will be initially high   |              |                    ||
-||        |after the initialisation.    |              |                    ||
-||        |When the initial count       |              |                    ||
-||   4    |expires OUT will go low for  |Start counting|  Hardware gate     ||
-||        |one CLK pulse and then go    |    value     |                    ||
-||        |high again.                  |              |                    ||
-||        |The counting sequences is    |              |                    ||
-||        |triggered by writing a new   |              |                    ||
-||        |value. See                   |              |                    ||
-||        |"i_APCI1710_WriteTimerValue" |              |                    ||
-||        |function. If a new count is  |              |                    ||
-||        |written during counting,     |              |                    ||
-||        |it will be loaded on the     |              |                    ||
-||        |next CLK pulse               |              |                    ||
-|+--------+-----------------------------+--------------+--------------------+|
-||        |Mode 5 is similar to mode 4  |              |                    ||
-||        |except for the gate input    |              |                    ||
-||        |action. The gate input is not|              |                    ||
-||   5    |used for enabled or disabled |Start counting|  Hardware trigger  ||
-||        |the timer. The gate input is |    value     |                    ||
-||        |used for triggered the timer.|              |                    ||
-|+--------+-----------------------------+--------------+--------------------+|
-|                                                                            |
-|                                                                            |
-|                                                                            |
-|                      Input clock selection table                           |
-|                                                                            |
-|  +--------------------------------+------------------------------------+   |
-|  |       b_InputClockSelection    |           Description              |   |
-|  |           parameter            |                                    |   |
-|  +--------------------------------+------------------------------------+   |
-|  |    APCI1710_PCI_BUS_CLOCK      | For the timer input clock, the PCI |   |
-|  |                                | bus clock / 4 is used. This PCI bus|   |
-|  |                                | clock can be 30MHz or 33MHz. For   |   |
-|  |                                | Timer 0 only this selection are    |   |
-|  |                                | available.                         |   |
-|  +--------------------------------+------------------------------------+   |
-|  | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the|   |
-|  |                                | possibility to inject a input clock|   |
-|  |                                | for Timer 1 or Timer 2. The source |   |
-|  |                                | from this clock can eat the output |   |
-|  |                                | clock from Timer 0 or any other    |   |
-|  |                                | clock source.                      |   |
-|  +--------------------------------+------------------------------------+   |
-|                                                                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle        : Handle of board         |
-|                                                    APCI-1710               |
-|                     unsigned char_   b_ModulNbr           : Module number to        |
-|                                                    configure (0 to 3)      |
-|                     unsigned char_   b_TimerNbr           : Timer number to         |
-|                                                    configure (0 to 2)      |
-|                     unsigned char_   b_TimerMode          : Timer mode selection    |
-|                                                    (0 to 5)                |
-|                                                    0: Interrupt on terminal|
-|                                                       count                |
-|                                                    1: Hardware             |
-|                                                       retriggerable one-   |
-|                                                       shot                 |
-|                                                    2: Rate generator       |
-|                                                    3: Square wave mode     |
-|                                                    4: Software triggered   |
-|                                                       strobe               |
-|                                                    5: Hardware triggered   |
-|                                                       strobe               |
-|                                                       See timer mode       |
-|                                                       description table.   |
-|                     ULONG_ ul_ReloadValue         : Start counting value   |
-|                                                     or division factor     |
-|                                                     See timer mode         |
-|                                                     description table.     |
-|                     unsigned char_   b_InputClockSelection : Selection from input   |
-|                                                     timer clock.           |
-|                                                     See input clock        |
-|                                                     selection table.       |
-|                     unsigned char_   b_InputClockLevel     : Selection from input   |
-|                                                     clock level.           |
-|                                                     0 : Low active         |
-|                                                         (Input inverted)   |
-|                                                     1 : High active        |
-|                     unsigned char_   b_OutputLevel,        : Selection from output  |
-|                                                     clock level.           |
-|                                                     0 : Low active         |
-|                                                     1 : High active        |
-|                                                         (Output inverted)  |
-|                     unsigned char_   b_HardwareGateLevel   : Selection from         |
-|                                                     hardware gate level.   |
-|                                                     0 : Low active         |
-|                                                         (Input inverted)   |
-|                                                     1 : High active        |
-|                                                     If you will not used   |
-|                                                     the hardware gate set  |
-|                                                     this value to 0.
-|b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
-	b_TimerNbr		  = (unsigned char) CR_CHAN(insn->chanspec);
-	b_TimerMode		  = (unsigned char) data[0];
-	ul_ReloadValue	  = (unsigned int) data[1];
-	b_InputClockSelection	=(unsigned char) data[2];
-	b_InputClockLevel		=(unsigned char) data[3];
-	b_OutputLevel			=(unsigned char) data[4];
-	b_HardwareGateLevel		=(unsigned char) data[5];
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: Timer selection wrong                               |
-|                    -4: The module is not a TIMER module                    |
-|                    -5: Timer mode selection is wrong                       |
-|                    -6: Input timer clock selection is wrong                |
-|                    -7: Selection from input clock level is wrong           |
-|                    -8: Selection from output clock level is wrong          |
-|                    -9: Selection from hardware gate level is wrong         |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn,
-					  unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_ModulNbr;
-	unsigned char b_TimerNbr;
-	unsigned char b_TimerMode;
-	unsigned int ul_ReloadValue;
-	unsigned char b_InputClockSelection;
-	unsigned char b_InputClockLevel;
-	unsigned char b_OutputLevel;
-	unsigned char b_HardwareGateLevel;
-
-	/* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
-	unsigned int dw_Test = 0;
-	/* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
-	b_TimerMode = (unsigned char) data[0];
-	ul_ReloadValue = (unsigned int) data[1];
-	b_InputClockSelection = (unsigned char) data[2];
-	b_InputClockLevel = (unsigned char) data[3];
-	b_OutputLevel = (unsigned char) data[4];
-	b_HardwareGateLevel = (unsigned char) data[5];
-
-	/* Test the module number */
-	if (b_ModulNbr < 4) {
-		/* Test if 82X54 timer */
-		if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-			/* Test the timer number */
-
-			if (b_TimerNbr <= 2) {
-				/* Test the timer mode */
-				if (b_TimerMode <= 5) {
-					/* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
-					/* Test te imput clock selection */
-					/*
-					   if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
-					   ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))
-					 */
-
-					if (((b_TimerNbr == 0) &&
-					     (b_InputClockSelection == APCI1710_PCI_BUS_CLOCK)) ||
-					    ((b_TimerNbr == 0) &&
-					     (b_InputClockSelection == APCI1710_10MHZ)) ||
-					    ((b_TimerNbr != 0) &&
-					     ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) ||
-					      (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) ||
-					      (b_InputClockSelection == APCI1710_10MHZ)))) {
-						/* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
-						if (((b_InputClockSelection == APCI1710_10MHZ) &&
-						     ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) ||
-						     (b_InputClockSelection != APCI1710_10MHZ)) {
-							/* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
-							/* Test the input clock level selection */
-
-							if ((b_InputClockLevel == 0) ||
-							    (b_InputClockLevel == 1)) {
-								/* Test the output clock level selection */
-								if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) {
-									/* Test the hardware gate level selection */
-									if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) {
-										/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-										/* Test if version > 1.1 and clock selection = 10MHz */
-										if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) {
-											/* Test if 40MHz quartz on board */
-											dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)));
-
-											dw_Test = (dw_Test >> 16) & 1;
-										} else {
-											dw_Test = 1;
-										}
-
-										/* Test if detection OK */
-										if (dw_Test == 1) {
-											/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-											/* Initialisation OK */
-											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1;
-
-											/* Save the input clock selection */
-											devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection;
-
-											/* Save the input clock level */
-											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1;
-
-											/* Save the output level */
-											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1;
-
-											/* Save the gate level */
-											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel;
-
-											/* Set the configuration word and disable the timer */
-											/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-											/*
-											   devpriv->s_ModuleInfo [b_ModulNbr].
-											   s_82X54ModuleInfo.
-											   s_82X54TimerInfo  [b_TimerNbr].
-											   dw_ConfigurationWord = (unsigned int) (((b_HardwareGateLevel         << 0) & 0x1) |
-											   ((b_InputClockLevel           << 1) & 0x2) |
-											   (((~b_OutputLevel       & 1)  << 2) & 0x4) |
-											   ((b_InputClockSelection       << 4) & 0x10));
-											 */
-											/* Test if 10MHz selected */
-											if (b_InputClockSelection == APCI1710_10MHZ) {
-												b_InputClockSelection = 2;
-											}
-
-											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (unsigned int)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30));
-											/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-											outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-											/* Initialise the 82X54 Timer */
-											outl((unsigned int) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-											/* Write the reload value */
-											outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-											/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-										}	/*  if (dw_Test == 1) */
-										else {
-											/* Input timer clock selection is wrong */
-											i_ReturnValue = -6;
-										}	/*  if (dw_Test == 1) */
-										/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-									}	/*  if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
-									else {
-										/* Selection from hardware gate level is wrong */
-										DPRINTK("Selection from hardware gate level is wrong\n");
-										i_ReturnValue = -9;
-									}	/*  if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
-								}	/*  if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
-								else {
-									/* Selection from output clock level is wrong */
-									DPRINTK("Selection from output clock level is wrong\n");
-									i_ReturnValue = -8;
-								}	/*  if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
-							}	/*  if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
-							else {
-								/* Selection from input clock level is wrong */
-								DPRINTK("Selection from input clock level is wrong\n");
-								i_ReturnValue = -7;
-							}	/*  if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
-						} else {
-							/* Input timer clock selection is wrong */
-							DPRINTK("Input timer clock selection is wrong\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-						/* Input timer clock selection is wrong */
-						DPRINTK("Input timer clock selection is wrong\n");
-						i_ReturnValue = -6;
-					}
-				}	/*  if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
-				else {
-					/* Timer mode selection is wrong */
-					DPRINTK("Timer mode selection is wrong\n");
-					i_ReturnValue = -5;
-				}	/*  if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-			else {
-				/* Timer selection wrong */
-				DPRINTK("Timer selection wrong\n");
-				i_ReturnValue = -3;
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-		} else {
-			/* The module is not a TIMER module */
-			DPRINTK("The module is not a TIMER module\n");
-			i_ReturnValue = -4;
-		}
-	} else {
-		/* Module number error */
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_EnableTimer                       |
-|                               (unsigned char_ b_BoardHandle,                        |
-|                                unsigned char_ b_ModulNbr,                           |
-|                                unsigned char_ b_TimerNbr,                           |
-|                                unsigned char_ b_InterruptEnable)
-int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
-	struct comedi_insn *insn,unsigned int *data)                |
-+----------------------------------------------------------------------------+
-| Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
-|                     (b_ModulNbr). You must calling the                     |
-|                     "i_APCI1710_InitTimer" function be for you call this   |
-|                     function. If you enable the timer interrupt, the timer |
-|                     generate a interrupt after the timer value reach       |
-|                     the zero. See function "i_APCI1710_SetBoardIntRoutineX"|
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
-|                                                 APCI-1710                  |
-|                     unsigned char_   b_ModulNbr        : Selected module number     |
-|                                                 (0 to 3)                   |
-|                     unsigned char_   b_TimerNbr        : Timer number to enable     |
-|                                                 (0 to 2)                   |
-|                     unsigned char_   b_InterruptEnable : Enable or disable the      |
-|                                                 timer interrupt.           |
-|                                                 APCI1710_ENABLE :          |
-|                                                 Enable the timer interrupt |
-|                                                 APCI1710_DISABLE :         |
-|                                                 Disable the timer interrupt|
-i_ReturnValue=insn->n;
-	b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
-	b_TimerNbr		  = (unsigned char) CR_CHAN(insn->chanspec);
-	b_ActionType      = (unsigned char) data[0]; /*  enable disable */
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: Timer selection wrong                               |
-|                    -4: The module is not a TIMER module                    |
-|                    -5: Timer not initialised see function                  |
-|                        "i_APCI1710_InitTimer"                              |
-|                    -6: Interrupt parameter is wrong                        |
-|                    -7: Interrupt function not initialised.                 |
-|                        See function "i_APCI1710_SetBoardIntRoutineX"       |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
-						 struct comedi_subdevice *s,
-						 struct comedi_insn *insn,
-						 unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_DummyRead;
-	unsigned char b_ModulNbr;
-	unsigned char b_TimerNbr;
-	unsigned char b_ActionType;
-	unsigned char b_InterruptEnable;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
-	b_ActionType = (unsigned char) data[0];	/*  enable disable */
-
-	/* Test the module number */
-	if (b_ModulNbr < 4) {
-		/* Test if 82X54 timer */
-		if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-			/* Test the timer number */
-			if (b_TimerNbr <= 2) {
-				/* Test if timer initialised */
-				if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
-
-					switch (b_ActionType) {
-					case APCI1710_ENABLE:
-						b_InterruptEnable = (unsigned char) data[1];
-						/* Test the interrupt selection */
-						if ((b_InterruptEnable == APCI1710_ENABLE) ||
-						    (b_InterruptEnable == APCI1710_DISABLE)) {
-							if (b_InterruptEnable == APCI1710_ENABLE) {
-
-								dw_DummyRead = inl(devpriv->s_BoardInfos.ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-								/* Enable the interrupt */
-								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord | 0x8;
-
-								outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-								devpriv->tsk_Current = current;	/*  Save the current process task structure */
-
-							}	/*  if (b_InterruptEnable == APCI1710_ENABLE) */
-							else {
-								/* Disable the interrupt */
-								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7;
-
-								outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-								/* Save the interrupt flag */
-								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
-							}	/*  if (b_InterruptEnable == APCI1710_ENABLE) */
-
-							/* Test if error occur */
-							if (i_ReturnValue >= 0) {
-								/* Save the interrupt flag */
-								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr);
-
-								/* Enable the timer */
-								outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-							}
-						} else {
-							/* Interrupt parameter is wrong */
-							DPRINTK("\n");
-							i_ReturnValue = -6;
-						}
-						break;
-					case APCI1710_DISABLE:
-						/* Test the interrupt flag */
-						if (((devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask >> b_TimerNbr) & 1) == 1) {
-							/* Disable the interrupt */
-
-							devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr]. dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7;
-
-							outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-							/* Save the interrupt flag */
-							devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
-						}
-
-						/* Disable the timer */
-						outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-						break;
-					}	/*  Switch end */
-				} else {
-					/* Timer not initialised see function */
-					DPRINTK ("Timer not initialised see function\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-				/* Timer selection wrong */
-				DPRINTK("Timer selection wrong\n");
-				i_ReturnValue = -3;
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-		} else {
-			/* The module is not a TIMER module */
-			DPRINTK("The module is not a TIMER module\n");
-			i_ReturnValue = -4;
-		}
-	} else {
-		/* Module number error */
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_ReadAllTimerValue                 |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        PULONG_ pul_TimerValueArray)
-int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
-	struct comedi_insn *insn,unsigned int *data)        |
-+----------------------------------------------------------------------------+
-| Task              : Return the all timer values from selected timer        |
-|                     module (b_ModulNbr).                                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
-|                                                 APCI-1710                  |
-|                     unsigned char_   b_ModulNbr        : Selected module number     |
-|                                                 (0 to 3)                   |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array.       |
-|                           Element 0 contain the timer 0 value.             |
-|                           Element 1 contain the timer 1 value.             |
-|                           Element 2 contain the timer 2 value.             |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: The module is not a TIMER module                    |
-|                    -4: Timer 0 not initialised see function                |
-|                        "i_APCI1710_InitTimer"                              |
-|                    -5: Timer 1 not initialised see function                |
-|                        "i_APCI1710_InitTimer"                              |
-|                    -6: Timer 2 not initialised see function                |
-|                        "i_APCI1710_InitTimer"                              |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,
-					    struct comedi_subdevice *s,
-					    struct comedi_insn *insn,
-					    unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_ModulNbr, b_ReadType;
-	unsigned int *pul_TimerValueArray;
-
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_ReadType = CR_CHAN(insn->chanspec);
-	pul_TimerValueArray = (unsigned int *) data;
-	i_ReturnValue = insn->n;
-
-	switch (b_ReadType) {
-	case APCI1710_TIMER_READINTERRUPT:
-
-		data[0] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].b_OldModuleMask;
-		data[1] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-		data[2] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-		/* Increment the read FIFO */
-		devpriv->s_InterruptParameters.ui_Read = (devpriv->s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-
-		break;
-
-	case APCI1710_TIMER_READALLTIMER:
-		/* Test the module number */
-		if (b_ModulNbr < 4) {
-			/* Test if 82X54 timer */
-			if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-				/* Test if timer 0 iniutialised */
-				if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[0].b_82X54Init == 1) {
-					/* Test if timer 1 iniutialised */
-					if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[1].b_82X54Init == 1) {
-						/* Test if timer 2 iniutialised */
-						if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[2].b_82X54Init == 1) {
-							/* Latch all counter */
-							outl(0x17, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
-
-							/* Read the timer 0 value */
-							pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr));
-
-							/* Read the timer 1 value */
-							pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
-
-							/* Read the timer 2 value */
-							pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr));
-						} else {
-							/* Timer 2 not initialised see function */
-							DPRINTK("Timer 2 not initialised see function\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-						/* Timer 1 not initialised see function */
-						DPRINTK("Timer 1 not initialised see function\n");
-						i_ReturnValue = -5;
-					}
-				} else {
-					/* Timer 0 not initialised see function */
-					DPRINTK("Timer 0 not initialised see function\n");
-					i_ReturnValue = -4;
-				}
-			} else {
-				/* The module is not a TIMER module */
-				DPRINTK("The module is not a TIMER module\n");
-				i_ReturnValue = -3;
-			}
-		} else {
-			/* Module number error */
-			DPRINTK("Module number error\n");
-			i_ReturnValue = -2;
-		}
-
-	}			/*  End of Switch */
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_ReadTimerValue                    |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_TimerNbr,               |
-|                                        PULONG_ pul_TimerValue)             |
-+----------------------------------------------------------------------------+
-| Task              : Return the timer value from selected digital timer     |
-|                     (b_TimerNbr) from selected timer  module (b_ModulNbr). |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
-|                                                 APCI-1710                  |
-|                     unsigned char_   b_ModulNbr        : Selected module number     |
-|                                                 (0 to 3)                   |
-|                     unsigned char_   b_TimerNbr        : Timer number to read       |
-|                                                 (0 to 2)                   |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_ pul_TimerValue    : Timer value                |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: Timer selection wrong                               |
-|                    -4: The module is not a TIMER module                    |
-|                    -5: Timer not initialised see function                  |
-|                        "i_APCI1710_InitTimer"                              |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
-				     unsigned char b_ModulNbr,
-				     unsigned char b_TimerNbr,
-				     unsigned int *pul_TimerValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/* Test the module number */
-	if (b_ModulNbr < 4) {
-		/* Test if 82X54 timer */
-		if ((devpriv->s_BoardInfos.
-		     dw_MolduleConfiguration[b_ModulNbr] &
-		     0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-			/* Test the timer number */
-			if (b_TimerNbr <= 2) {
-				/* Test if timer initialised */
-				if (devpriv->
-				    s_ModuleInfo[b_ModulNbr].
-				    s_82X54ModuleInfo.
-				    s_82X54TimerInfo[b_TimerNbr].
-				    b_82X54Init == 1) {
-					/* Latch the timer value */
-					outl((2 << b_TimerNbr) | 0xD0,
-					     devpriv->s_BoardInfos.
-					     ui_Address + 12 +
-					     (64 * b_ModulNbr));
-
-					/* Read the counter value */
-					*pul_TimerValue =
-					    inl(devpriv->s_BoardInfos.
-						ui_Address + (b_TimerNbr * 4) +
-						(64 * b_ModulNbr));
-				} else {
-					/* Timer not initialised see function */
-					DPRINTK("Timer not initialised see function\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-				/* Timer selection wrong */
-				DPRINTK("Timer selection wrong\n");
-				i_ReturnValue = -3;
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-		} else {
-			/* The module is not a TIMER module */
-			DPRINTK("The module is not a TIMER module\n");
-			i_ReturnValue = -4;
-		}
-	} else {
-		/* Module number error */
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-	/*
-	   +----------------------------------------------------------------------------+
-	   | Function Name     : _INT_     i_APCI1710_GetTimerOutputLevel               |
-	   |                                       (unsigned char_     b_BoardHandle,            |
-	   |                                        unsigned char_     b_ModulNbr,               |
-	   |                                        unsigned char_     b_TimerNbr,               |
-	   |                                        unsigned char *_   pb_OutputLevel)            |
-	   +----------------------------------------------------------------------------+
-	   | Task              : Return the output signal level (pb_OutputLevel) from   |
-	   |                     selected digital timer (b_TimerNbr) from selected timer|
-	   |                     module (b_ModulNbr).                                   |
-	   +----------------------------------------------------------------------------+
-	   | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
-	   |                                                 APCI-1710                  |
-	   |                     unsigned char_   b_ModulNbr        : Selected module number     |
-	   |                                                 (0 to 3)                   |
-	   |                     unsigned char_   b_TimerNbr        : Timer number to test       |
-	   |                                                 (0 to 2)                   |
-	   +----------------------------------------------------------------------------+
-	   | Output Parameters : unsigned char *_ pb_OutputLevel     : Output signal level        |
-	   |                                                 0 : The output is low      |
-	   |                                                 1 : The output is high     |
-	   +----------------------------------------------------------------------------+
-	   | Return Value      : 0: No error                                            |
-	   |                    -1: The handle parameter of the board is wrong          |
-	   |                    -2: Module selection wrong                              |
-	   |                    -3: Timer selection wrong                               |
-	   |                    -4: The module is not a TIMER module                    |
-	   |                    -5: Timer not initialised see function                  |
-	   |                        "i_APCI1710_InitTimer"                              |
-	   +----------------------------------------------------------------------------+
-	 */
-static int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
-					  unsigned char b_ModulNbr,
-					  unsigned char b_TimerNbr,
-					  unsigned char *pb_OutputLevel)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_TimerStatus;
-
-	/* Test the module number */
-	if (b_ModulNbr < 4) {
-		/* Test if 82X54 timer */
-		if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-			/* Test the timer number */
-			if (b_TimerNbr <= 2) {
-				/* Test if timer initialised */
-				if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
-					/* Latch the timer value */
-					outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
-
-					/* Read the timer status */
-					dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-					*pb_OutputLevel = (unsigned char) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel);
-				} else {
-					/* Timer not initialised see function */
-					DPRINTK("Timer not initialised see function\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-				/* Timer selection wrong */
-				DPRINTK("Timer selection wrong\n");
-				i_ReturnValue = -3;
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-		} else {
-			/* The module is not a TIMER module */
-			DPRINTK("The module is not a TIMER module\n");
-			i_ReturnValue = -4;
-		}
-	} else {
-		/* Module number error */
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_GetTimerProgressStatus            |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_TimerNbr,               |
-|                                        unsigned char *_   pb_TimerStatus)            |
-+----------------------------------------------------------------------------+
-| Task              : Return the progress status (pb_TimerStatus) from       |
-|                     selected digital timer (b_TimerNbr) from selected timer|
-|                     module (b_ModulNbr).                                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
-|                                                 APCI-1710                  |
-|                     unsigned char_   b_ModulNbr        : Selected module number     |
-|                                                 (0 to 3)                   |
-|                     unsigned char_   b_TimerNbr        : Timer number to test       |
-|                                                 (0 to 2)                   |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_TimerStatus     : Output signal level        |
-|                                                 0 : Timer not in progress  |
-|                                                 1 : Timer in progress      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: Timer selection wrong                               |
-|                    -4: The module is not a TIMER module                    |
-|                    -5: Timer not initialised see function                  |
-|                        "i_APCI1710_InitTimer"                              |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
-					     unsigned char b_ModulNbr,
-					     unsigned char b_TimerNbr,
-					     unsigned char *pb_TimerStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_TimerStatus;
-
-	/* Test the module number */
-	if (b_ModulNbr < 4) {
-		/* Test if 82X54 timer */
-
-		if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-			/* Test the timer number */
-			if (b_TimerNbr <= 2) {
-				/* Test if timer initialised */
-				if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
-					/* Latch the timer value */
-					outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
-
-					/* Read the timer status */
-					dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-
-					*pb_TimerStatus = (unsigned char) ((dw_TimerStatus) >> 8) & 1;
-					printk("ProgressStatus : %d", *pb_TimerStatus);
-				} else {
-					/* Timer not initialised see function */
-					i_ReturnValue = -5;
-				}
-			} else {
-				/* Timer selection wrong */
-				i_ReturnValue = -3;
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-		} else {
-			/* The module is not a TIMER module */
-
-			i_ReturnValue = -4;
-		}
-	} else {
-		/* Module number error */
-
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_WriteTimerValue                   |
-|                                       (unsigned char_   b_BoardHandle,              |
-|                                        unsigned char_   b_ModulNbr,                 |
-|                                        unsigned char_   b_TimerNbr,                 |
-|                                        ULONG_ ul_WriteValue)               |
-+----------------------------------------------------------------------------+
-| Task              : Write the value (ul_WriteValue) into the selected timer|
-|                     (b_TimerNbr) from selected timer module (b_ModulNbr).  |
-|                     The action in depend of the time mode selection.       |
-|                     See timer mode description table.                      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
-|                                                 APCI-1710                  |
-|                     unsigned char_   b_ModulNbr        : Selected module number     |
-|                                                 (0 to 3)                   |
-|                     unsigned char_   b_TimerNbr        : Timer number to write      |
-|                                                 (0 to 2)                   |
-|                     ULONG_ ul_WriteValue      : Value to write             |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: Timer selection wrong                               |
-|                    -4: The module is not a TIMER module                    |
-|                    -5: Timer not initialised see function                  |
-|                        "i_APCI1710_InitTimer"                              |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
-				      unsigned char b_ModulNbr,
-				      unsigned char b_TimerNbr,
-				      unsigned int ul_WriteValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/* Test the module number */
-	if (b_ModulNbr < 4) {
-		/* Test if 82X54 timer */
-		if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-			/* Test the timer number */
-			if (b_TimerNbr <= 2) {
-				/* Test if timer initialised */
-				if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
-					/* Write the value */
-					outl(ul_WriteValue, devpriv->s_BoardInfos.ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr));
-				} else {
-					/* Timer not initialised see function */
-					DPRINTK("Timer not initialised see function\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-				/* Timer selection wrong */
-				DPRINTK("Timer selection wrong\n");
-				i_ReturnValue = -3;
-			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
-		} else {
-			/* The module is not a TIMER module */
-			DPRINTK("The module is not a TIMER module\n");
-			i_ReturnValue = -4;
-		}
-	} else {
-		/* Module number error */
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
-struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Read write functions for Timer                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data)
-{
-	unsigned char b_BitsType;
-	int i_ReturnValue = 0;
-	b_BitsType = data[0];
-
-	printk("\n82X54");
-
-	switch (b_BitsType) {
-	case APCI1710_TIMER_READVALUE:
-		i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
-							  (unsigned char)CR_AREF(insn->chanspec),
-							  (unsigned char)CR_CHAN(insn->chanspec),
-							  (unsigned int *) &data[0]);
-		break;
-
-	case APCI1710_TIMER_GETOUTPUTLEVEL:
-		i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
-							       (unsigned char)CR_AREF(insn->chanspec),
-							       (unsigned char)CR_CHAN(insn->chanspec),
-							       (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_TIMER_GETPROGRESSSTATUS:
-		i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
-								  (unsigned char)CR_AREF(insn->chanspec),
-								  (unsigned char)CR_CHAN(insn->chanspec),
-								  (unsigned char *)&data[0]);
-		break;
-
-	case APCI1710_TIMER_WRITEVALUE:
-		i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
-							   (unsigned char)CR_AREF(insn->chanspec),
-							   (unsigned char)CR_CHAN(insn->chanspec),
-							   (unsigned int)data[1]);
-
-		break;
-
-	default:
-		printk("Bits Config Parameter Wrong\n");
-		i_ReturnValue = -1;
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
deleted file mode 100644
index d91f586..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+++ /dev/null
@@ -1,2050 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : CHRONO.C        | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 chronometer module                          |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  | 29/06/98 | S. Weber  | Digital input / output implementation          |
-  |----------|-----------|------------------------------------------------|
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_30MHZ			30
-#define APCI1710_33MHZ			33
-#define APCI1710_40MHZ			40
-
-#define APCI1710_SINGLE			0
-#define APCI1710_CONTINUOUS		1
-
-#define APCI1710_CHRONO_PROGRESS_STATUS	0
-#define APCI1710_CHRONO_READVALUE	1
-#define APCI1710_CHRONO_CONVERTVALUE	2
-#define APCI1710_CHRONO_READINTERRUPT	3
-
-#define APCI1710_CHRONO_SET_CHANNELON	0
-#define APCI1710_CHRONO_SET_CHANNELOFF	1
-#define APCI1710_CHRONO_READ_CHANNEL	2
-#define APCI1710_CHRONO_READ_PORT	3
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_InitChrono                        |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_ChronoMode,             |
-|                                        unsigned char_     b_PCIInputClock,          |
-|                                        unsigned char_     b_TimingUnit,             |
-|                                        ULONG_   ul_TimingInterval,         |
-|                                        PULONG_ pul_RealTimingInterval)
-
-+----------------------------------------------------------------------------+
-| Task              : Configure the chronometer operating mode (b_ChronoMode)|
-|                     from selected module (b_ModulNbr).                     |
-|                     The ul_TimingInterval and ul_TimingUnit determine the  |
-|                     timing base for the measurement.                       |
-|                     The pul_RealTimingInterval return the real timing      |
-|                     value. You must calling this function be for you call  |
-|                     any other function witch access of the chronometer.    |
-|                                                                            |
-|                     Witch this functionality from the APCI-1710 you have   |
-|                     the possibility to measure the timing witch two event. |
-|                                                                            |
-|                     The mode 0 and 1 is appropriate for period measurement.|
-|                     The mode 2 and 3 is appropriate for frequent           |
-|                     measurement.                                           |
-|                     The mode 4 to 7 is appropriate for measuring the timing|
-|                     between  two event.                                    |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle    : Handle of board APCI-1710   |
-| unsigned char_   b_ModulNbr  CR_AREF(insn->chanspec)  : Module number to configure  |
-|                                                (0 to 3)                    |
-| unsigned char_   b_ChronoMode				data[0]    : Chronometer action mode     |
-|                                                (0 to 7).                   |
-| unsigned char_   b_PCIInputClock			data[1] : Selection from PCI bus clock|
-|                                                - APCI1710_30MHZ :          |
-|                                                  The PC have a PCI bus     |
-|                                                  clock from 30 MHz         |
-|                                                - APCI1710_33MHZ :          |
-|                                                  The PC have a PCI bus     |
-|                                                  clock from 33 MHz         |
-|                                                - APCI1710_40MHZ            |
-|                                                  The APCI-1710 have a      |
-|                                                  integrated 40Mhz          |
-|                                                  quartz.                   |
-|               unsigned char_   b_TimingUnit	data[2]    : Base timing unity (0 to 4) |
-|                                                 0 : ns                     |
-|                                                 1 : µs                     |
-|                                                 2 : ms                     |
-|                                                 3 : s                      |
-|                                                 4 : mn                     |
-|         ULONG_ ul_TimingInterval : data[3]	 Base timing value.          |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |
-|                                                       value.
-|                     data[0]
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: Chronometer mode selection is wrong                |
-|                     -5: The selected PCI input clock is wrong              |
-|                     -6: Timing unity selection is wrong                    |
-|                     -7: Base timing selection is wrong                     |
-|                     -8: You can not used the 40MHz clock selection with    |
-|                         this board                                         |
-|                     -9: You can not used the 40MHz clock selection with    |
-|                         this CHRONOS version                               |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn,
-					   unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ul_TimerValue = 0;
-	unsigned int ul_TimingInterval = 0;
-	unsigned int ul_RealTimingInterval = 0;
-	double d_RealTimingInterval = 0;
-	unsigned int dw_ModeArray[8] =
-		{ 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
-	unsigned char b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
-
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_ChronoMode = (unsigned char) data[0];
-	b_PCIInputClock = (unsigned char) data[1];
-	b_TimingUnit = (unsigned char) data[2];
-	ul_TimingInterval = (unsigned int) data[3];
-	i_ReturnValue = insn->n;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if chronometer */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-	      /*****************************/
-			/* Test the chronometer mode */
-	      /*****************************/
-
-			if (b_ChronoMode <= 7) {
-		 /**************************/
-				/* Test the PCI bus clock */
-		 /**************************/
-
-				if ((b_PCIInputClock == APCI1710_30MHZ) ||
-					(b_PCIInputClock == APCI1710_33MHZ) ||
-					(b_PCIInputClock == APCI1710_40MHZ)) {
-		    /*************************/
-					/* Test the timing unity */
-		    /*************************/
-
-					if (b_TimingUnit <= 4) {
-		       /**********************************/
-						/* Test the base timing selection */
-		       /**********************************/
-
-						if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165576UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150240UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374182UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 1UL))) {
-			  /**************************/
-							/* Test the board version */
-			  /**************************/
-
-							if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
-			     /************************/
-								/* Test the TOR version */
-			     /************************/
-
-								if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || (b_PCIInputClock != APCI1710_40MHZ)) {
-									fpu_begin
-										();
-
-				/****************************************/
-									/* Calculate the timer 0 division fator */
-				/****************************************/
-
-									switch (b_TimingUnit) {
-				   /******/
-										/* ns */
-				   /******/
-
-									case 0:
-
-					   /******************/
-										/* Timer 0 factor */
-					   /******************/
-
-										ul_TimerValue
-											=
-											(unsigned int)
-											(ul_TimingInterval
-											*
-											(0.001 * b_PCIInputClock));
-
-					   /*******************/
-										/* Round the value */
-					   /*******************/
-
-										if ((double)((double)ul_TimingInterval * (0.001 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-											ul_TimerValue
-												=
-												ul_TimerValue
-												+
-												1;
-										}
-
-					   /*****************************/
-										/* Calculate the real timing */
-					   /*****************************/
-
-										ul_RealTimingInterval
-											=
-											(unsigned int)
-											(ul_TimerValue
-											/
-											(0.001 * (double)b_PCIInputClock));
-										d_RealTimingInterval
-											=
-											(double)
-											ul_TimerValue
-											/
-											(0.001
-											*
-											(double)
-											b_PCIInputClock);
-
-										if ((double)((double)ul_TimerValue / (0.001 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-											ul_RealTimingInterval
-												=
-												ul_RealTimingInterval
-												+
-												1;
-										}
-
-										ul_TimingInterval
-											=
-											ul_TimingInterval
-											-
-											1;
-										ul_TimerValue
-											=
-											ul_TimerValue
-											-
-											2;
-										if (b_PCIInputClock != APCI1710_40MHZ) {
-											ul_TimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_TimerValue)
-												*
-												0.99392);
-										}
-
-										break;
-
-				   /******/
-										/* æs */
-				   /******/
-
-									case 1:
-
-					   /******************/
-										/* Timer 0 factor */
-					   /******************/
-
-										ul_TimerValue
-											=
-											(unsigned int)
-											(ul_TimingInterval
-											*
-											(1.0 * b_PCIInputClock));
-
-					   /*******************/
-										/* Round the value */
-					   /*******************/
-
-										if ((double)((double)ul_TimingInterval * (1.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-											ul_TimerValue
-												=
-												ul_TimerValue
-												+
-												1;
-										}
-
-					   /*****************************/
-										/* Calculate the real timing */
-					   /*****************************/
-
-										ul_RealTimingInterval
-											=
-											(unsigned int)
-											(ul_TimerValue
-											/
-											(1.0 * (double)b_PCIInputClock));
-										d_RealTimingInterval
-											=
-											(double)
-											ul_TimerValue
-											/
-											(
-											(double)
-											1.0
-											*
-											(double)
-											b_PCIInputClock);
-
-										if ((double)((double)ul_TimerValue / (1.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-											ul_RealTimingInterval
-												=
-												ul_RealTimingInterval
-												+
-												1;
-										}
-
-										ul_TimingInterval
-											=
-											ul_TimingInterval
-											-
-											1;
-										ul_TimerValue
-											=
-											ul_TimerValue
-											-
-											2;
-										if (b_PCIInputClock != APCI1710_40MHZ) {
-											ul_TimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_TimerValue)
-												*
-												0.99392);
-										}
-
-										break;
-
-				   /******/
-										/* ms */
-				   /******/
-
-									case 2:
-
-					   /******************/
-										/* Timer 0 factor */
-					   /******************/
-
-										ul_TimerValue
-											=
-											ul_TimingInterval
-											*
-											(1000
-											*
-											b_PCIInputClock);
-
-					   /*******************/
-										/* Round the value */
-					   /*******************/
-
-										if ((double)((double)ul_TimingInterval * (1000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-											ul_TimerValue
-												=
-												ul_TimerValue
-												+
-												1;
-										}
-
-					   /*****************************/
-										/* Calculate the real timing */
-					   /*****************************/
-
-										ul_RealTimingInterval
-											=
-											(unsigned int)
-											(ul_TimerValue
-											/
-											(1000.0 * (double)b_PCIInputClock));
-										d_RealTimingInterval
-											=
-											(double)
-											ul_TimerValue
-											/
-											(1000.0
-											*
-											(double)
-											b_PCIInputClock);
-
-										if ((double)((double)ul_TimerValue / (1000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-											ul_RealTimingInterval
-												=
-												ul_RealTimingInterval
-												+
-												1;
-										}
-
-										ul_TimingInterval
-											=
-											ul_TimingInterval
-											-
-											1;
-										ul_TimerValue
-											=
-											ul_TimerValue
-											-
-											2;
-										if (b_PCIInputClock != APCI1710_40MHZ) {
-											ul_TimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_TimerValue)
-												*
-												0.99392);
-										}
-
-										break;
-
-				   /*****/
-										/* s */
-				   /*****/
-
-									case 3:
-
-					   /******************/
-										/* Timer 0 factor */
-					   /******************/
-
-										ul_TimerValue
-											=
-											(unsigned int)
-											(ul_TimingInterval
-											*
-											(1000000.0
-												*
-												b_PCIInputClock));
-
-					   /*******************/
-										/* Round the value */
-					   /*******************/
-
-										if ((double)((double)ul_TimingInterval * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-											ul_TimerValue
-												=
-												ul_TimerValue
-												+
-												1;
-										}
-
-					   /*****************************/
-										/* Calculate the real timing */
-					   /*****************************/
-
-										ul_RealTimingInterval
-											=
-											(unsigned int)
-											(ul_TimerValue
-											/
-											(1000000.0
-												*
-												(double)
-												b_PCIInputClock));
-										d_RealTimingInterval
-											=
-											(double)
-											ul_TimerValue
-											/
-											(1000000.0
-											*
-											(double)
-											b_PCIInputClock);
-
-										if ((double)((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-											ul_RealTimingInterval
-												=
-												ul_RealTimingInterval
-												+
-												1;
-										}
-
-										ul_TimingInterval
-											=
-											ul_TimingInterval
-											-
-											1;
-										ul_TimerValue
-											=
-											ul_TimerValue
-											-
-											2;
-										if (b_PCIInputClock != APCI1710_40MHZ) {
-											ul_TimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_TimerValue)
-												*
-												0.99392);
-										}
-
-										break;
-
-				   /******/
-										/* mn */
-				   /******/
-
-									case 4:
-
-					   /******************/
-										/* Timer 0 factor */
-					   /******************/
-
-										ul_TimerValue
-											=
-											(unsigned int)
-											(
-											(ul_TimingInterval
-												*
-												60)
-											*
-											(1000000.0
-												*
-												b_PCIInputClock));
-
-					   /*******************/
-										/* Round the value */
-					   /*******************/
-
-										if ((double)((double)(ul_TimingInterval * 60.0) * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-											ul_TimerValue
-												=
-												ul_TimerValue
-												+
-												1;
-										}
-
-					   /*****************************/
-										/* Calculate the real timing */
-					   /*****************************/
-
-										ul_RealTimingInterval
-											=
-											(unsigned int)
-											(ul_TimerValue
-											/
-											(1000000.0
-												*
-												(double)
-												b_PCIInputClock))
-											/
-											60;
-										d_RealTimingInterval
-											=
-											(
-											(double)
-											ul_TimerValue
-											/
-											(0.001 * (double)b_PCIInputClock)) / 60.0;
-
-										if ((double)(((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-											ul_RealTimingInterval
-												=
-												ul_RealTimingInterval
-												+
-												1;
-										}
-
-										ul_TimingInterval
-											=
-											ul_TimingInterval
-											-
-											1;
-										ul_TimerValue
-											=
-											ul_TimerValue
-											-
-											2;
-										if (b_PCIInputClock != APCI1710_40MHZ) {
-											ul_TimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_TimerValue)
-												*
-												0.99392);
-										}
-
-										break;
-									}
-
-									fpu_end();
-
-				/****************************/
-									/* Save the PCI input clock */
-				/****************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_ChronoModuleInfo.
-										b_PCIInputClock
-										=
-										b_PCIInputClock;
-
-				/*************************/
-									/* Save the timing unity */
-				/*************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_ChronoModuleInfo.
-										b_TimingUnit
-										=
-										b_TimingUnit;
-
-				/************************/
-									/* Save the base timing */
-				/************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_ChronoModuleInfo.
-										d_TimingInterval
-										=
-										d_RealTimingInterval;
-
-				/****************************/
-									/* Set the chronometer mode */
-				/****************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_ChronoModuleInfo.
-										dw_ConfigReg
-										=
-										dw_ModeArray
-										[b_ChronoMode];
-
-				/***********************/
-									/* Test if 40 MHz used */
-				/***********************/
-
-									if (b_PCIInputClock == APCI1710_40MHZ) {
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_ChronoModuleInfo.
-											dw_ConfigReg
-											=
-											devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_ChronoModuleInfo.
-											dw_ConfigReg
-											|
-											0x80;
-									}
-
-									outl(devpriv->s_ModuleInfo[b_ModulNbr].s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr));
-
-				/***********************/
-									/* Write timer 0 value */
-				/***********************/
-
-									outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
-
-				/*********************/
-									/* Chronometer init. */
-				/*********************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_ChronoModuleInfo.
-										b_ChronoInit
-										=
-										1;
-								} else {
-				/***********************************************/
-									/* TOR version error for 40MHz clock selection */
-				/***********************************************/
-
-									DPRINTK("TOR version error for 40MHz clock selection\n");
-									i_ReturnValue
-										=
-										-9;
-								}
-							} else {
-			     /**************************************************************/
-								/* You can not use the 40MHz clock selection with this board */
-			     /**************************************************************/
-
-								DPRINTK("You can not used the 40MHz clock selection with this board\n");
-								i_ReturnValue =
-									-8;
-							}
-						} else {
-			  /**********************************/
-							/* Base timing selection is wrong */
-			  /**********************************/
-
-							DPRINTK("Base timing selection is wrong\n");
-							i_ReturnValue = -7;
-						}
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-					else {
-		       /***********************************/
-						/* Timing unity selection is wrong */
-		       /***********************************/
-
-						DPRINTK("Timing unity selection is wrong\n");
-						i_ReturnValue = -6;
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
-				else {
-		    /*****************************************/
-					/* The selected PCI input clock is wrong */
-		    /*****************************************/
-
-					DPRINTK("The selected PCI input clock is wrong\n");
-					i_ReturnValue = -5;
-				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
-			}	/*  if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */
-			else {
-		 /***************************************/
-				/* Chronometer mode selection is wrong */
-		 /***************************************/
-
-				DPRINTK("Chronometer mode selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */
-		} else {
-	      /******************************************/
-			/* The module is not a Chronometer module */
-	      /******************************************/
-
-			DPRINTK("The module is not a Chronometer module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-	data[0] = ul_RealTimingInterval;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_EnableChrono                          |
-|                                               (unsigned char_ b_BoardHandle,        |
-|                                                unsigned char_ b_ModulNbr,           |
-|                                                unsigned char_ b_CycleMode,          |
-|                                                unsigned char_ b_InterruptEnable)
-int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
-struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
-+----------------------------------------------------------------------------+
-| Task              : Enable the chronometer from selected module            |
-|                     (b_ModulNbr). You must calling the                     |
-|                     "i_APCI1710_InitChrono" function be for you call this  |
-|                     function.                                              |
-|                     If you enable the chronometer interrupt, the           |
-|                     chronometer generate a interrupt after the stop signal.|
-|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
-|                     Interrupt mask description chapter from this manual.   |
-|                     The b_CycleMode parameter determine if you will        |
-|                     measured a single or more cycle.
-
-|					  Disable the chronometer from selected module           |
-|                     (b_ModulNbr). If you disable the chronometer after a   |
-|                     start signal occur and you restart the chronometer     |
-|                     witch the " i_APCI1710_EnableChrono" function, if no   |
-|                     stop signal occur this start signal is ignored.
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr   CR_AREF(chanspec)  : Selected module number (0 to 3) |
-                                  data[0]  ENABle/Disable chrono
-|                     unsigned char_ b_CycleMode    : Selected the chronometer        |
-|                                  data[1]           acquisition mode                |
-|                     unsigned char_ b_InterruptEnable : Enable or disable the        |
-|                                   data[2]            chronometer interrupt.       |
-|                                               APCI1710_ENABLE:             |
-|                                               Enable the chronometer       |
-|                                               interrupt                    |
-|                                               APCI1710_DISABLE:            |
-|                                               Disable the chronometer      |
-|                                               interrupt                    |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-|                     -5: Chronometer acquisition mode cycle is wrong        |
-|                     -6: Interrupt parameter is wrong                       |
-|                     -7: Interrupt function not initialised.                |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"
-                      -8: data[0] wrong input    |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
-						   struct comedi_subdevice *s,
-						   struct comedi_insn *insn,
-						   unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_Action = (unsigned char) data[0];
-	b_CycleMode = (unsigned char) data[1];
-	b_InterruptEnable = (unsigned char) data[2];
-	i_ReturnValue = insn->n;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if chronometer */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-	      /***********************************/
-			/* Test if chronometer initialised */
-	      /***********************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_ChronoModuleInfo.b_ChronoInit == 1) {
-
-				switch (b_Action) {
-
-				case APCI1710_ENABLE:
-
-		 /*********************************/
-					/* Test the cycle mode parameter */
-		 /*********************************/
-
-					if ((b_CycleMode == APCI1710_SINGLE)
-						|| (b_CycleMode ==
-							APCI1710_CONTINUOUS)) {
-		    /***************************/
-						/* Test the interrupt flag */
-		    /***************************/
-
-						if ((b_InterruptEnable ==
-								APCI1710_ENABLE)
-							|| (b_InterruptEnable ==
-								APCI1710_DISABLE))
-						{
-
-			  /***************************/
-							/* Save the interrupt flag */
-			  /***************************/
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_ChronoModuleInfo.
-								b_InterruptMask
-								=
-								b_InterruptEnable;
-
-			  /***********************/
-							/* Save the cycle mode */
-			  /***********************/
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_ChronoModuleInfo.
-								b_CycleMode =
-								b_CycleMode;
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_ChronoModuleInfo.
-								dw_ConfigReg =
-								(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_ChronoModuleInfo.
-								dw_ConfigReg &
-								0x8F) | ((1 &
-									b_InterruptEnable)
-								<< 5) | ((1 &
-									b_CycleMode)
-								<< 6) | 0x10;
-
-			  /*****************************/
-							/* Test if interrupt enabled */
-			  /*****************************/
-
-							if (b_InterruptEnable ==
-								APCI1710_ENABLE)
-							{
-			     /****************************/
-								/* Clear the interrupt flag */
-			     /****************************/
-
-								outl(devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_ChronoModuleInfo.
-									dw_ConfigReg,
-									devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 32 +
-									(64 * b_ModulNbr));
-								devpriv->tsk_Current = current;	/*  Save the current process task structure */
-							}
-
-			  /***********************************/
-							/* Enable or disable the interrupt */
-							/* Enable the chronometer          */
-			  /***********************************/
-
-							outl(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_ChronoModuleInfo.
-								dw_ConfigReg,
-								devpriv->
-								s_BoardInfos.
-								ui_Address +
-								16 +
-								(64 * b_ModulNbr));
-
-			  /*************************/
-							/* Clear status register */
-			  /*************************/
-
-							outl(0, devpriv->
-								s_BoardInfos.
-								ui_Address +
-								36 +
-								(64 * b_ModulNbr));
-
-						}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
-						else {
-		       /********************************/
-							/* Interrupt parameter is wrong */
-		       /********************************/
-
-							DPRINTK("Interrupt parameter is wrong\n");
-							i_ReturnValue = -6;
-						}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
-					}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
-					else {
-		    /***********************************************/
-						/* Chronometer acquisition mode cycle is wrong */
-		    /***********************************************/
-
-						DPRINTK("Chronometer acquisition mode cycle is wrong\n");
-						i_ReturnValue = -5;
-					}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
-					break;
-
-				case APCI1710_DISABLE:
-
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_ChronoModuleInfo.
-						b_InterruptMask = 0;
-
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_ChronoModuleInfo.
-						dw_ConfigReg =
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_ChronoModuleInfo.
-						dw_ConfigReg & 0x2F;
-
-		 /***************************/
-					/* Disable the interrupt   */
-					/* Disable the chronometer */
-		 /***************************/
-
-					outl(devpriv->s_ModuleInfo[b_ModulNbr].
-						s_ChronoModuleInfo.dw_ConfigReg,
-						devpriv->s_BoardInfos.
-						ui_Address + 16 +
-						(64 * b_ModulNbr));
-
-		 /***************************/
-					/* Test if continuous mode */
-		 /***************************/
-
-					if (devpriv->s_ModuleInfo[b_ModulNbr].
-						s_ChronoModuleInfo.
-						b_CycleMode ==
-						APCI1710_CONTINUOUS) {
-		    /*************************/
-						/* Clear status register */
-		    /*************************/
-
-						outl(0, devpriv->s_BoardInfos.
-							ui_Address + 36 +
-							(64 * b_ModulNbr));
-					}
-					break;
-
-				default:
-					DPRINTK("Inputs wrong! Enable or Disable chrono\n");
-					i_ReturnValue = -8;
-				}	/*  switch ENABLE/DISABLE */
-			} else {
-		 /*******************************/
-				/* Chronometer not initialised */
-		 /*******************************/
-
-				DPRINTK("Chronometer not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a Chronometer module */
-	      /******************************************/
-
-			DPRINTK("The module is not a Chronometer module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetChronoProgressStatus               |
-|                               (unsigned char_    b_BoardHandle,                     |
-|                                unsigned char_    b_ModulNbr,                        |
-|                                unsigned char *_  pb_ChronoStatus)                    |
-+----------------------------------------------------------------------------+
-| Task              : Return the chronometer status (pb_ChronoStatus) from   |
-|                     selected chronometer module (b_ModulNbr).              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
-|                                                status.                     |
-|                                                0 : Measurement not started.|
-|                                                    No start signal occur.  |
-|                                                1 : Measurement started.    |
-|                                                    A start signal occur.   |
-|                                                2 : Measurement stopped.    |
-|                                                    A stop signal occur.    |
-|                                                    The measurement is      |
-|                                                    terminate.              |
-|                                                3: A overflow occur. You    |
-|                                                   must change the base     |
-|                                                   timing witch the         |
-|                                                   function                 |
-|                                                   "i_APCI1710_InitChrono"  |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
-					      unsigned char b_ModulNbr,
-					      unsigned char *pb_ChronoStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if chronometer */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-	      /***********************************/
-			/* Test if chronometer initialised */
-	      /***********************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_ChronoModuleInfo.b_ChronoInit == 1) {
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 8 + (64 * b_ModulNbr));
-
-		 /********************/
-				/* Test if overflow */
-		 /********************/
-
-				if ((dw_Status & 8) == 8) {
-		    /******************/
-					/* Overflow occur */
-		    /******************/
-
-					*pb_ChronoStatus = 3;
-				}	/*  if ((dw_Status & 8) == 8) */
-				else {
-		    /*******************************/
-					/* Test if measurement stopped */
-		    /*******************************/
-
-					if ((dw_Status & 2) == 2) {
-		       /***********************/
-						/* A stop signal occur */
-		       /***********************/
-
-						*pb_ChronoStatus = 2;
-					}	/*  if ((dw_Status & 2) == 2) */
-					else {
-		       /*******************************/
-						/* Test if measurement started */
-		       /*******************************/
-
-						if ((dw_Status & 1) == 1) {
-			  /************************/
-							/* A start signal occur */
-			  /************************/
-
-							*pb_ChronoStatus = 1;
-						}	/*  if ((dw_Status & 1) == 1) */
-						else {
-			  /***************************/
-							/* Measurement not started */
-			  /***************************/
-
-							*pb_ChronoStatus = 0;
-						}	/*  if ((dw_Status & 1) == 1) */
-					}	/*  if ((dw_Status & 2) == 2) */
-				}	/*  if ((dw_Status & 8) == 8) */
-			} else {
-		 /*******************************/
-				/* Chronometer not initialised */
-		 /*******************************/
-				DPRINTK("Chronometer not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a Chronometer module */
-	      /******************************************/
-			DPRINTK("The module is not a Chronometer module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadChronoValue                       |
-|                               (unsigned char_     b_BoardHandle,                    |
-|                                unsigned char_     b_ModulNbr,                       |
-|                                unsigned int_    ui_TimeOut,                        |
-|                                unsigned char *_   pb_ChronoStatus,                   |
-|                                PULONG_ pul_ChronoValue)                    |
-+----------------------------------------------------------------------------+
-| Task              : Return the chronometer status (pb_ChronoStatus) and the|
-|                     timing value (pul_ChronoValue) after a stop signal     |
-|                     occur from selected chronometer module (b_ModulNbr).   |
-|                     This function are only avaible if you have disabled    |
-|                     the interrupt functionality. See function              |
-|                     "i_APCI1710_EnableChrono" and the Interrupt mask       |
-|                     description chapter.                                   |
-|                     You can test the chronometer status witch the          |
-|                     "i_APCI1710_GetChronoProgressStatus" function.         |
-|                                                                            |
-|                     The returned value from pul_ChronoValue parameter is   |
-|                     not real measured timing.                              |
-|                     You must used the "i_APCI1710_ConvertChronoValue"      |
-|                     function or make this operation for calculate the      |
-|                     timing:                                                |
-|                                                                            |
-|                     Timing = pul_ChronoValue * pul_RealTimingInterval.     |
-|                                                                            |
-|                     pul_RealTimingInterval is the returned parameter from  |
-|                     "i_APCI1710_InitChrono" function and the time unity is |
-|                     the b_TimingUnit from "i_APCI1710_InitChrono" function|
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
-|                                                status.                     |
-|                                                0 : Measurement not started.|
-|                                                    No start signal occur.  |
-|                                                1 : Measurement started.    |
-|                                                    A start signal occur.   |
-|                                                2 : Measurement stopped.    |
-|                                                    A stop signal occur.    |
-|                                                    The measurement is      |
-|                                                    terminate.              |
-|                                                3: A overflow occur. You    |
-|                                                   must change the base     |
-|                                                   timing witch the         |
-|                                                   function                 |
-|                                                   "i_APCI1710_InitChrono"  |
-|                     unsigned int *  pul_ChronoValue  : Chronometer timing value.   |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-|                     -5: Timeout parameter is wrong (0 to 65535)            |
-|                     -6: Interrupt routine installed. You can not read      |
-|                         directly the chronometer measured timing.          |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
-				      unsigned char b_ModulNbr,
-				      unsigned int ui_TimeOut,
-				      unsigned char *pb_ChronoStatus,
-				      unsigned int *pul_ChronoValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned int dw_TimeOut = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if chronometer */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-	      /***********************************/
-			/* Test if chronometer initialised */
-	      /***********************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_ChronoModuleInfo.b_ChronoInit == 1) {
-		 /*****************************/
-				/* Test the timout parameter */
-		 /*****************************/
-
-				if (ui_TimeOut <= 65535UL) {
-
-					for (;;) {
-			  /*******************/
-						/* Read the status */
-			  /*******************/
-
-						dw_Status =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 8 +
-							(64 * b_ModulNbr));
-
-			  /********************/
-						/* Test if overflow */
-			  /********************/
-
-						if ((dw_Status & 8) == 8) {
-			     /******************/
-							/* Overflow occur */
-			     /******************/
-
-							*pb_ChronoStatus = 3;
-
-			     /***************************/
-							/* Test if continuous mode */
-			     /***************************/
-
-							if (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_ChronoModuleInfo.
-								b_CycleMode ==
-								APCI1710_CONTINUOUS)
-							{
-				/*************************/
-								/* Clear status register */
-				/*************************/
-
-								outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
-							}
-
-							break;
-						}	/*  if ((dw_Status & 8) == 8) */
-						else {
-			     /*******************************/
-							/* Test if measurement stopped */
-			     /*******************************/
-
-							if ((dw_Status & 2) ==
-								2) {
-				/***********************/
-								/* A stop signal occur */
-				/***********************/
-
-								*pb_ChronoStatus
-									= 2;
-
-				/***************************/
-								/* Test if continnous mode */
-				/***************************/
-
-								if (devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_ChronoModuleInfo.
-									b_CycleMode
-									==
-									APCI1710_CONTINUOUS)
-								{
-				   /*************************/
-									/* Clear status register */
-				   /*************************/
-
-									outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
-								}
-								break;
-							}	/*  if ((dw_Status & 2) == 2) */
-							else {
-				/*******************************/
-								/* Test if measurement started */
-				/*******************************/
-
-								if ((dw_Status & 1) == 1) {
-				   /************************/
-									/* A start signal occur */
-				   /************************/
-
-									*pb_ChronoStatus
-										=
-										1;
-								}	/*  if ((dw_Status & 1) == 1) */
-								else {
-				   /***************************/
-									/* Measurement not started */
-				   /***************************/
-
-									*pb_ChronoStatus
-										=
-										0;
-								}	/*  if ((dw_Status & 1) == 1) */
-							}	/*  if ((dw_Status & 2) == 2) */
-						}	/*  if ((dw_Status & 8) == 8) */
-
-						if (dw_TimeOut == ui_TimeOut) {
-			     /*****************/
-							/* Timeout occur */
-			     /*****************/
-
-							break;
-						} else {
-			     /*************************/
-							/* Increment the timeout */
-			     /*************************/
-
-							dw_TimeOut =
-								dw_TimeOut + 1;
-							mdelay(1000);
-
-						}
-					}	/*  for (;;) */
-
-		       /*****************************/
-					/* Test if stop signal occur */
-		       /*****************************/
-
-					if (*pb_ChronoStatus == 2) {
-			  /**********************************/
-						/* Read the measured timing value */
-			  /**********************************/
-
-						*pul_ChronoValue =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 4 +
-							(64 * b_ModulNbr));
-
-						if (*pul_ChronoValue != 0) {
-							*pul_ChronoValue =
-								*pul_ChronoValue
-								- 1;
-						}
-					} else {
-			  /*************************/
-						/* Test if timeout occur */
-			  /*************************/
-
-						if ((*pb_ChronoStatus != 3)
-							&& (dw_TimeOut ==
-								ui_TimeOut)
-							&& (ui_TimeOut != 0)) {
-			     /*****************/
-							/* Timeout occur */
-			     /*****************/
-
-							*pb_ChronoStatus = 4;
-						}
-					}
-
-				} else {
-		    /******************************/
-					/* Timeout parameter is wrong */
-		    /******************************/
-					DPRINTK("Timeout parameter is wrong\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /*******************************/
-				/* Chronometer not initialised */
-		 /*******************************/
-				DPRINTK("Chronometer not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a Chronometer module */
-	      /******************************************/
-			DPRINTK("The module is not a Chronometer module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ConvertChronoValue                    |
-|                               (unsigned char_     b_BoardHandle,                    |
-|                                unsigned char_     b_ModulNbr,                       |
-|                                ULONG_   ul_ChronoValue,                    |
-|                                PULONG_ pul_Hour,                           |
-|                                unsigned char *_   pb_Minute,                         |
-|                                unsigned char *_   pb_Second,                         |
-|                                unsigned int *_  pui_MilliSecond,                    |
-|                                unsigned int *_  pui_MicroSecond,                    |
-|                                unsigned int *_  pui_NanoSecond)                     |
-+----------------------------------------------------------------------------+
-| Task              : Convert the chronometer measured timing                |
-|                     (ul_ChronoValue) in to h, mn, s, ms, µs, ns.           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle : Handle of board APCI-1710      |
-|                     unsigned char_   b_ModulNbr    : Selected module number (0 to 3)|
-|                     ULONG_ ul_ChronoValue : Measured chronometer timing    |
-|                                             value.                         |
-|                                             See"i_APCI1710_ReadChronoValue"|
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_   pul_Hour        : Chronometer timing hour    |
-|                     unsigned char *_     pb_Minute      : Chronometer timing minute  |
-|                     unsigned char *_     pb_Second      : Chronometer timing second  |
-|                     unsigned int *_    pui_MilliSecond  : Chronometer timing mini   |
-|                                                 second                     |
-|                     unsigned int *_    pui_MicroSecond : Chronometer timing micro   |
-|                                                 second                     |
-|                     unsigned int *_    pui_NanoSecond  : Chronometer timing nano    |
-|                                                 second                     |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
-					 unsigned char b_ModulNbr,
-					 unsigned int ul_ChronoValue,
-					 unsigned int *pul_Hour,
-					 unsigned char *pb_Minute,
-					 unsigned char *pb_Second,
-					 unsigned int *pui_MilliSecond,
-					 unsigned int *pui_MicroSecond,
-					 unsigned int *pui_NanoSecond)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	double d_Hour;
-	double d_Minute;
-	double d_Second;
-	double d_MilliSecond;
-	double d_MicroSecond;
-	double d_NanoSecond;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if chronometer */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-	      /***********************************/
-			/* Test if chronometer initialised */
-	      /***********************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_ChronoModuleInfo.b_ChronoInit == 1) {
-				fpu_begin();
-
-				d_Hour = (double)ul_ChronoValue *(double)
-					devpriv->s_ModuleInfo[b_ModulNbr].
-					s_ChronoModuleInfo.d_TimingInterval;
-
-				switch (devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_ChronoModuleInfo.b_TimingUnit) {
-				case 0:
-					d_Hour = d_Hour / (double)1000.0;
-
-				case 1:
-					d_Hour = d_Hour / (double)1000.0;
-
-				case 2:
-					d_Hour = d_Hour / (double)1000.0;
-
-				case 3:
-					d_Hour = d_Hour / (double)60.0;
-
-				case 4:
-			    /**********************/
-					/* Calculate the hour */
-			    /**********************/
-
-					d_Hour = d_Hour / (double)60.0;
-					*pul_Hour = (unsigned int) d_Hour;
-
-			    /************************/
-					/* Calculate the minute */
-			    /************************/
-
-					d_Minute = d_Hour - *pul_Hour;
-					d_Minute = d_Minute * 60;
-					*pb_Minute = (unsigned char) d_Minute;
-
-			    /************************/
-					/* Calculate the second */
-			    /************************/
-
-					d_Second = d_Minute - *pb_Minute;
-					d_Second = d_Second * 60;
-					*pb_Second = (unsigned char) d_Second;
-
-			    /*****************************/
-					/* Calculate the mini second */
-			    /*****************************/
-
-					d_MilliSecond = d_Second - *pb_Second;
-					d_MilliSecond = d_MilliSecond * 1000;
-					*pui_MilliSecond = (unsigned int) d_MilliSecond;
-
-			    /******************************/
-					/* Calculate the micro second */
-			    /******************************/
-
-					d_MicroSecond =
-						d_MilliSecond -
-						*pui_MilliSecond;
-					d_MicroSecond = d_MicroSecond * 1000;
-					*pui_MicroSecond = (unsigned int) d_MicroSecond;
-
-			    /******************************/
-					/* Calculate the micro second */
-			    /******************************/
-
-					d_NanoSecond =
-						d_MicroSecond -
-						*pui_MicroSecond;
-					d_NanoSecond = d_NanoSecond * 1000;
-					*pui_NanoSecond = (unsigned int) d_NanoSecond;
-					break;
-				}
-
-				fpu_end();
-			} else {
-		 /*******************************/
-				/* Chronometer not initialised */
-		 /*******************************/
-				DPRINTK("Chronometer not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a Chronometer module */
-	      /******************************************/
-			DPRINTK("The module is not a Chronometer module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
-struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Read  functions for Timer                                     |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnReadChrono(struct comedi_device *dev,
-				     struct comedi_subdevice *s,
-				     struct comedi_insn *insn,
-				     unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned char b_ReadType;
-	int i_ReturnValue = insn->n;
-
-	b_ReadType = CR_CHAN(insn->chanspec);
-
-	switch (b_ReadType) {
-	case APCI1710_CHRONO_PROGRESS_STATUS:
-		i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_CHRONO_READVALUE:
-		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned int) insn->unused[0],
-			(unsigned char *) &data[0], (unsigned int *) &data[1]);
-		break;
-
-	case APCI1710_CHRONO_CONVERTVALUE:
-		i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned int) insn->unused[0],
-			(unsigned int *) &data[0],
-			(unsigned char *) &data[1],
-			(unsigned char *) &data[2],
-			(unsigned int *) &data[3],
-			(unsigned int *) &data[4], (unsigned int *) &data[5]);
-		break;
-
-	case APCI1710_CHRONO_READINTERRUPT:
-		printk("In Chrono Read Interrupt\n");
-
-		data[0] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].b_OldModuleMask;
-		data[1] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-		data[2] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-			     /**************************/
-		/* Increment the read FIFO */
-			     /***************************/
-
-		devpriv->
-			s_InterruptParameters.
-			ui_Read = (devpriv->
-			s_InterruptParameters.
-			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-		break;
-
-	default:
-		printk("ReadType Parameter wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
-	struct comedi_insn *insn,unsigned int *data)                    |
-+----------------------------------------------------------------------------+
-| Task              : Sets the output witch has been passed with the         |
-|                     parameter b_Channel. Setting an output means setting an|
-|                     output high.                                           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
-|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
-|                     unsigned char_ b_OutputChannel : Selection from digital output  |
-|                           CR_CHAN()                  channel (0 to 2)               |
-|                                              0 : Channel H                 |
-|                                              1 : Channel A                 |
-|                                              2 : Channel B                 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: The selected digital output is wrong               |
-|                     -5: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_SetChronoChlOff                       |
-|                               (unsigned char_  b_BoardHandle,                       |
-|                                unsigned char_  b_ModulNbr,                          |
-|                                unsigned char_  b_OutputChannel)                     |
-+----------------------------------------------------------------------------+
-| Task              : Resets the output witch has been passed with the       |
-|                     parameter b_Channel. Resetting an output means setting |
-|                     an output low.                                         |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710
-                        data[0] : Chl ON, Chl OFF , Chl Read , Port Read
-
-|                     unsigned char_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|
-|                     unsigned char_ b_OutputChannel CR_CHAN : Selection from digital output  |
-|                                             channel (0 to 2)               |
-|                                              0 : Channel H                 |
-|                                              1 : Channel A                 |
-|                                              2 : Channel B                 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: The selected digital output is wrong               |
-|                     -5: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadChronoChlValue                    |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char_   b_InputChannel,                     |
-|                                unsigned char *_ pb_ChannelStatus)                    |
-+----------------------------------------------------------------------------+
-| Task              : Return the status from selected digital input          |
-|                     (b_InputChannel) from selected chronometer             |
-|                     module (b_ModulNbr).                                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
-|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
-|                     unsigned char_ b_InputChannel  : Selection from digital input   |
-|                                             channel (0 to 2)               |
-|                                   CR_CHAN()             0 : Channel E               |
-|                                                1 : Channel F               |
-|                                                2 : Channel G               |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel status.|
-|                                data[0]                0 : Channel is not active   |
-|                                                1 : Channel is active       |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: The selected digital input is wrong                |
-|                     -5: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadChronoPortValue                   |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char *_ pb_PortValue)                        |
-+----------------------------------------------------------------------------+
-| Task              : Return the status from digital inputs port from        |
-|                     selected  (b_ModulNbr) chronometer module.             |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
-|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_PortValue   : Digital inputs port status.
-|                     data[0]
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a Chronometer module             |
-|                     -4: Chronometer not initialised see function           |
-|                         "i_APCI1710_InitChrono"                            |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
-					      struct comedi_subdevice *s,
-					      struct comedi_insn *insn,
-					      unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
-	unsigned int dw_Status;
-	unsigned char *pb_ChannelStatus;
-	unsigned char *pb_PortValue;
-
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	i_ReturnValue = insn->n;
-	b_IOType = (unsigned char) data[0];
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if chronometer */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-	      /***********************************/
-			/* Test if chronometer initialised */
-	      /***********************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_ChronoModuleInfo.b_ChronoInit == 1) {
-		 /***********************************/
-				/* Test the digital output channel */
-		 /***********************************/
-				switch (b_IOType) {
-
-				case APCI1710_CHRONO_SET_CHANNELOFF:
-
-					b_OutputChannel =
-						(unsigned char) CR_CHAN(insn->chanspec);
-					if (b_OutputChannel <= 2) {
-
-						outl(0, devpriv->s_BoardInfos.
-							ui_Address + 20 +
-							(b_OutputChannel * 4) +
-							(64 * b_ModulNbr));
-					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
-					else {
-		    /****************************************/
-						/* The selected digital output is wrong */
-		    /****************************************/
-
-						DPRINTK("The selected digital output is wrong\n");
-						i_ReturnValue = -4;
-
-					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
-
-					break;
-
-				case APCI1710_CHRONO_SET_CHANNELON:
-
-					b_OutputChannel =
-						(unsigned char) CR_CHAN(insn->chanspec);
-					if (b_OutputChannel <= 2) {
-
-						outl(1, devpriv->s_BoardInfos.
-							ui_Address + 20 +
-							(b_OutputChannel * 4) +
-							(64 * b_ModulNbr));
-					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
-					else {
-		    /****************************************/
-						/* The selected digital output is wrong */
-		    /****************************************/
-
-						DPRINTK("The selected digital output is wrong\n");
-						i_ReturnValue = -4;
-
-					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
-
-					break;
-
-				case APCI1710_CHRONO_READ_CHANNEL:
-		 /**********************************/
-					/* Test the digital input channel */
-		 /**********************************/
-					pb_ChannelStatus = (unsigned char *) &data[0];
-					b_InputChannel =
-						(unsigned char) CR_CHAN(insn->chanspec);
-
-					if (b_InputChannel <= 2) {
-
-						dw_Status =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 12 +
-							(64 * b_ModulNbr));
-
-						*pb_ChannelStatus =
-							(unsigned char) (((dw_Status >>
-									b_InputChannel)
-								& 1) ^ 1);
-					}	/*  if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */
-					else {
-		    /***************************************/
-						/* The selected digital input is wrong */
-		    /***************************************/
-
-						DPRINTK("The selected digital input is wrong\n");
-						i_ReturnValue = -4;
-					}	/*  if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */
-
-					break;
-
-				case APCI1710_CHRONO_READ_PORT:
-
-					pb_PortValue = (unsigned char *) &data[0];
-
-					dw_Status =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 12 +
-						(64 * b_ModulNbr));
-
-					*pb_PortValue =
-						(unsigned char) ((dw_Status & 0x7) ^ 7);
-					break;
-				}
-			} else {
-		 /*******************************/
-				/* Chronometer not initialised */
-		 /*******************************/
-
-				DPRINTK("Chronometer not initialised\n");
-				i_ReturnValue = -5;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a Chronometer module */
-	      /******************************************/
-
-			DPRINTK("The module is not a Chronometer module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
deleted file mode 100644
index 27de18e..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+++ /dev/null
@@ -1,1037 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : DIG_IO.C        | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 digital I/O module                          |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  | 16/06/98 | S. Weber  | Digital input / output implementation          |
-  |----------|-----------|------------------------------------------------|
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  +-----------------------------------------------------------------------+
-*/
-
-/* Digital Output ON or OFF */
-#define APCI1710_ON			1
-#define APCI1710_OFF			0
-
-/* Digital I/O */
-#define APCI1710_INPUT			0
-#define APCI1710_OUTPUT			1
-
-#define APCI1710_DIGIO_MEMORYONOFF	0x10
-#define APCI1710_DIGIO_INIT		0x11
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
-|						struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
-+----------------------------------------------------------------------------+
-| Task              : Configure the digital I/O operating mode from selected |
-|                     module  (b_ModulNbr). You must calling this function be|
-|                     for you call any other function witch access of digital|
-|                     I/O.                                                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  :													     |
-|                  unsigned char_ b_ModulNbr      data[0]: Module number to               |
-|                                             configure (0 to 3)             |
-|                     unsigned char_ b_ChannelAMode data[1]  : Channel A mode selection       |
-|                                             0 : Channel used for digital   |
-|                                                 input                      |
-|                                             1 : Channel used for digital   |
-|                                                 output                     |
-|                     unsigned char_ b_ChannelBMode data[2] : Channel B mode selection       |
-|                                             0 : Channel used for digital   |
-|                                                 input                      |
-|                                             1 : Channel used for digital   |
-|                                                 output					 |
-						data[0]	  memory on/off
-Activates and deactivates the digital output memory.
-						After having      |
-|                 called up this function with memory on,the output you have previously|
-|                     activated with the function are not reset
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a digital I/O module              |
-|                    -4: Bi-directional channel A configuration error        |
-|                    -5: Bi-directional channel B configuration error        |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn,
-					  unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
-	unsigned char b_MemoryOnOff, b_ConfigType;
-	int i_ReturnValue = 0;
-	unsigned int dw_WriteConfig = 0;
-
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_ConfigType = (unsigned char) data[0];	/*  Memory or  Init */
-	b_ChannelAMode = (unsigned char) data[1];
-	b_ChannelBMode = (unsigned char) data[2];
-	b_MemoryOnOff = (unsigned char) data[1];	/*  if memory operation */
-	i_ReturnValue = insn->n;
-
-		/**************************/
-	/* Test the module number */
-		/**************************/
-
-	if (b_ModulNbr >= 4) {
-		DPRINTK("Module Number invalid\n");
-		i_ReturnValue = -2;
-		return i_ReturnValue;
-	}
-	switch (b_ConfigType) {
-	case APCI1710_DIGIO_MEMORYONOFF:
-
-		if (b_MemoryOnOff)	/*  If Memory ON */
-		{
-		 /****************************/
-			/* Set the output memory on */
-		 /****************************/
-
-			devpriv->s_ModuleInfo[b_ModulNbr].
-				s_DigitalIOInfo.b_OutputMemoryEnabled = 1;
-
-		 /***************************/
-			/* Clear the output memory */
-		 /***************************/
-			devpriv->s_ModuleInfo[b_ModulNbr].
-				s_DigitalIOInfo.dw_OutputMemory = 0;
-		} else		/*  If memory off */
-		{
-		 /*****************************/
-			/* Set the output memory off */
-		 /*****************************/
-
-			devpriv->s_ModuleInfo[b_ModulNbr].
-				s_DigitalIOInfo.b_OutputMemoryEnabled = 0;
-		}
-		break;
-
-	case APCI1710_DIGIO_INIT:
-
-	/*******************************/
-		/* Test if digital I/O counter */
-	/*******************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
-
-	/***************************************************/
-			/* Test the bi-directional channel A configuration */
-	/***************************************************/
-
-			if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1)) {
-	/***************************************************/
-				/* Test the bi-directional channel B configuration */
-	/***************************************************/
-
-				if ((b_ChannelBMode == 0)
-					|| (b_ChannelBMode == 1)) {
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_DigitalIOInfo.b_DigitalInit =
-						1;
-
-	/********************************/
-					/* Save channel A configuration */
-	/********************************/
-
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_DigitalIOInfo.
-						b_ChannelAMode = b_ChannelAMode;
-
-	/********************************/
-					/* Save channel B configuration */
-	/********************************/
-
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_DigitalIOInfo.
-						b_ChannelBMode = b_ChannelBMode;
-
-	/*****************************************/
-					/* Set the channel A and B configuration */
-	/*****************************************/
-
-					dw_WriteConfig =
-						(unsigned int) (b_ChannelAMode |
-						(b_ChannelBMode * 2));
-
-	/***************************/
-					/* Write the configuration */
-	/***************************/
-
-					outl(dw_WriteConfig,
-						devpriv->s_BoardInfos.
-						ui_Address + 4 +
-						(64 * b_ModulNbr));
-
-				} else {
-	/************************************************/
-					/* Bi-directional channel B configuration error */
-	/************************************************/
-					DPRINTK("Bi-directional channel B configuration error\n");
-					i_ReturnValue = -5;
-				}
-
-			} else {
-	/************************************************/
-				/* Bi-directional channel A configuration error */
-	/************************************************/
-				DPRINTK("Bi-directional channel A configuration error\n");
-				i_ReturnValue = -4;
-
-			}
-
-		} else {
-	/******************************************/
-			/* The module is not a digital I/O module */
-	/******************************************/
-			DPRINTK("The module is not a digital I/O module\n");
-			i_ReturnValue = -3;
-		}
-	}			/*  end of Switch */
-	printk("Return Value %d\n", i_ReturnValue);
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-|                            INPUT FUNCTIONS                                 |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-
-|INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,comedi_subdevice
-*s,	struct comedi_insn *insn,unsigned int *data)
-
-+----------------------------------------------------------------------------+
-| Task              : Read the status from selected digital I/O digital input|
-|                     (b_InputChannel)                                       |
-+----------------------------------------------------------------------------|
-
-
-|
-|  unsigned char_ b_ModulNbr  CR_AREF(chanspec)          : Selected module number   |
-|                                                   (0 to 3)                 |
-|  unsigned char_ b_InputChannel CR_CHAN(chanspec)        : Selection from digital   |
-|                                                   input ( 0 to 6)          |
-|                                                      0 : Channel C         |
-|                                                      1 : Channel D         |
-|                                                      2 : Channel E         |
-|                                                      3 : Channel F         |
-|                                                      4 : Channel G         |
-|                                                      5 : Channel A         |
-|                                                      6 : Channel B
-
-
-	|
-+----------------------------------------------------------------------------+
-| Output Parameters :					 data[0]   : Digital input channel    |
-|                                                   status                   |
-|                                                   0 : Channle is not active|
-|                                                   1 : Channle is active    |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a digital I/O module              |
-|                    -4: The selected digital I/O digital input is wrong     |
-|                    -5: Digital I/O not initialised                         |
-|                    -6: The digital channel A is used for output            |
-|                    -7: The digital channel B is used for output            |
-+----------------------------------------------------------------------------+
-*/
-
-/* _INT_   i_APCI1710_ReadDigitalIOChlValue      (unsigned char_    b_BoardHandle, */
-/*
-* unsigned char_ b_ModulNbr, unsigned char_ b_InputChannel,
-* unsigned char *_ pb_ChannelStatus)
-*/
-static int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
-						struct comedi_subdevice *s,
-						struct comedi_insn *insn,
-						unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg;
-	unsigned char b_ModulNbr, b_InputChannel;
-	unsigned char *pb_ChannelStatus;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
-	data[0] = 0;
-	pb_ChannelStatus = (unsigned char *) &data[0];
-	i_ReturnValue = insn->n;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if digital I/O counter */
-	   /*******************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
-	      /******************************************/
-			/* Test the digital imnput channel number */
-	      /******************************************/
-
-			if (b_InputChannel <= 6) {
-		 /**********************************************/
-				/* Test if the digital I/O module initialised */
-		 /**********************************************/
-
-				if (devpriv->s_ModuleInfo[b_ModulNbr].
-					s_DigitalIOInfo.b_DigitalInit == 1) {
-		    /**********************************/
-					/* Test if channel A or channel B */
-		    /**********************************/
-
-					if (b_InputChannel > 4) {
-		       /*********************/
-						/* Test if channel A */
-		       /*********************/
-
-						if (b_InputChannel == 5) {
-			  /***************************/
-							/* Test the channel A mode */
-			  /***************************/
-
-							if (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								b_ChannelAMode
-								!= 0) {
-			     /********************************************/
-								/* The digital channel A is used for output */
-			     /********************************************/
-
-								i_ReturnValue =
-									-6;
-							}
-						}	/*  if (b_InputChannel == 5) */
-						else {
-			  /***************************/
-							/* Test the channel B mode */
-			  /***************************/
-
-							if (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								b_ChannelBMode
-								!= 0) {
-			     /********************************************/
-								/* The digital channel B is used for output */
-			     /********************************************/
-
-								i_ReturnValue =
-									-7;
-							}
-						}	/*  if (b_InputChannel == 5) */
-					}	/*  if (b_InputChannel > 4) */
-
-		    /***********************/
-					/* Test if error occur */
-		    /***********************/
-
-					if (i_ReturnValue >= 0) {
-		       /**************************/
-						/* Read all digital input */
-		       /**************************/
-
-/*
-* INPDW (ps_APCI1710Variable-> s_Board [b_BoardHandle].
-* s_BoardInfos. ui_Address + (64 * b_ModulNbr), &dw_StatusReg);
-*/
-
-						dw_StatusReg =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address +
-							(64 * b_ModulNbr));
-
-						*pb_ChannelStatus =
-							(unsigned char) ((dw_StatusReg ^
-								0x1C) >>
-							b_InputChannel) & 1;
-
-					}	/*  if (i_ReturnValue == 0) */
-				} else {
-		    /*******************************/
-					/* Digital I/O not initialised */
-		    /*******************************/
-					DPRINTK("Digital I/O not initialised\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /********************************/
-				/* Selected digital input error */
-		 /********************************/
-				DPRINTK("Selected digital input error\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a digital I/O module */
-	      /******************************************/
-			DPRINTK("The module is not a digital I/O module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-|                            OUTPUT FUNCTIONS                                |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : int i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
-|*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
-
-+----------------------------------------------------------------------------+
-| Task              : Sets or resets the output witch has been passed with the         |
-|                     parameter b_Channel. Setting an output means setting   |
-|                     an ouput high.                                         |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
-|                     unsigned char_ b_ModulNbr (aref )    : Selected module number (0 to 3)|
-|                     unsigned char_ b_OutputChannel (CR_CHAN) : Selection from digital output  |
-|                                             channel (0 to 2)               |
-|                                                0 : Channel H               |
-|                                                1 : Channel A               |
-|                                                2 : Channel B               |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a digital I/O module              |
-|                    -4: The selected digital output is wrong                |
-|                    -5: digital I/O not initialised see function            |
-|                        " i_APCI1710_InitDigitalIO"                         |
-|                    -6: The digital channel A is used for input             |
-|                    -7: The digital channel B is used for input
-					 -8: Digital Output Memory OFF.                          |
-|                        Use previously the function                         |
-|                        "i_APCI1710_SetDigitalIOMemoryOn".            |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-* _INT_ i_APCI1710_SetDigitalIOChlOn (unsigned char_ b_BoardHandle,
-* unsigned char_ b_ModulNbr, unsigned char_ b_OutputChannel)
-*/
-static int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
-						 struct comedi_subdevice *s,
-						 struct comedi_insn *insn,
-						 unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_WriteValue = 0;
-	unsigned char b_ModulNbr, b_OutputChannel;
-	i_ReturnValue = insn->n;
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_OutputChannel = CR_CHAN(insn->chanspec);
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if digital I/O counter */
-	   /*******************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
-	      /**********************************************/
-			/* Test if the digital I/O module initialised */
-	      /**********************************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_DigitalIOInfo.b_DigitalInit == 1) {
-		 /******************************************/
-				/* Test the digital output channel number */
-		 /******************************************/
-
-				switch (b_OutputChannel) {
-		    /*************/
-					/* Channel H */
-		    /*************/
-
-				case 0:
-					break;
-
-		    /*************/
-					/* Channel A */
-		    /*************/
-
-				case 1:
-					if (devpriv->s_ModuleInfo[b_ModulNbr].
-						s_DigitalIOInfo.
-						b_ChannelAMode != 1) {
-			    /*******************************************/
-						/* The digital channel A is used for input */
-			    /*******************************************/
-
-						i_ReturnValue = -6;
-					}
-					break;
-
-		    /*************/
-					/* Channel B */
-		    /*************/
-
-				case 2:
-					if (devpriv->s_ModuleInfo[b_ModulNbr].
-						s_DigitalIOInfo.
-						b_ChannelBMode != 1) {
-			    /*******************************************/
-						/* The digital channel B is used for input */
-			    /*******************************************/
-
-						i_ReturnValue = -7;
-					}
-					break;
-
-				default:
-			 /****************************************/
-					/* The selected digital output is wrong */
-			 /****************************************/
-
-					i_ReturnValue = -4;
-					break;
-				}
-
-		 /***********************/
-				/* Test if error occur */
-		 /***********************/
-
-				if (i_ReturnValue >= 0) {
-
-			/*********************************/
-					/* Test if set channel ON        */
-		    /*********************************/
-					if (data[0]) {
-		    /*********************************/
-						/* Test if output memory enabled */
-		    /*********************************/
-
-						if (devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_DigitalIOInfo.
-							b_OutputMemoryEnabled ==
-							1) {
-							dw_WriteValue =
-								devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								dw_OutputMemory
-								| (1 <<
-								b_OutputChannel);
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								dw_OutputMemory
-								= dw_WriteValue;
-						} else {
-							dw_WriteValue =
-								1 <<
-								b_OutputChannel;
-						}
-					}	/*  set channel off */
-					else {
-						if (devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_DigitalIOInfo.
-							b_OutputMemoryEnabled ==
-							1) {
-							dw_WriteValue =
-								devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								dw_OutputMemory
-								& (0xFFFFFFFFUL
-								-
-								(1 << b_OutputChannel));
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								dw_OutputMemory
-								= dw_WriteValue;
-						} else {
-							/*****************************/
-							/* Digital Output Memory OFF */
-							/*****************************/
-							/*  +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn" */
-							i_ReturnValue = -8;
-						}
-
-					}
-					/*******************/
-					/* Write the value */
-					/*******************/
-
-					/* OUTPDW (ps_APCI1710Variable->
-					 * s_Board [b_BoardHandle].
-					 * s_BoardInfos. ui_Address + (64 * b_ModulNbr),
-					 * dw_WriteValue);
-					 */
-*/
-					outl(dw_WriteValue,
-						devpriv->s_BoardInfos.
-						ui_Address + (64 * b_ModulNbr));
-				}
-			} else {
-		 /*******************************/
-				/* Digital I/O not initialised */
-		 /*******************************/
-
-				i_ReturnValue = -5;
-			}
-		} else {
-	      /******************************************/
-			/* The module is not a digital I/O module */
-	      /******************************************/
-
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-
-|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,comedi_subdevice
-	*s,	struct comedi_insn *insn,unsigned int *data)
-+----------------------------------------------------------------------------+
-| Task              : write:
-					  Sets or resets one or several outputs from port.                 |
-|                     Setting an output means setting an output high.        |
-|                     If you have switched OFF the digital output memory     |
-|                     (OFF), all the other output are set to "0".
-
-|                      read:
-					  Read the status from digital input port                |
-|                     from selected digital I/O module (b_ModulNbr)
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-	unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
-|   unsigned char_ b_ModulNbr  CR_AREF(aref)    : Selected module number (0 to 3)|
-|   unsigned char_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )
-|                       data[0]           read or write port
-|                       data[1]            if write then indicate ON or OFF
-
-|                       if read : data[1] will return port status.
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-
-|                INPUT :
-
-					  0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a digital I/O module              |
-|                    -4: Digital I/O not initialised
-
-				OUTPUT:	  0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a digital I/O module              |
-|                    -4: Output value wrong                                  |
-|                    -5: digital I/O not initialised see function            |
-|                        " i_APCI1710_InitDigitalIO"                         |
-|                    -6: The digital channel A is used for input             |
-|                    -7: The digital channel B is used for input
-					-8: Digital Output Memory OFF.                          |
-|                        Use previously the function                         |
-|                        "i_APCI1710_SetDigitalIOMemoryOn".               |
-+----------------------------------------------------------------------------+
-*/
-
-/*
- * _INT_ i_APCI1710_SetDigitalIOPortOn (unsigned char_
- * b_BoardHandle, unsigned char_ b_ModulNbr, unsigned char_
- * b_PortValue)
-*/
-static int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
-						 struct comedi_subdevice *s,
-						 struct comedi_insn *insn,
-						 unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_WriteValue = 0;
-	unsigned int dw_StatusReg;
-	unsigned char b_ModulNbr, b_PortValue;
-	unsigned char b_PortOperation, b_PortOnOFF;
-
-	unsigned char *pb_PortValue;
-
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_PortOperation = (unsigned char) data[0];	/*  Input or output */
-	b_PortOnOFF = (unsigned char) data[1];	/*  if output then On or Off */
-	b_PortValue = (unsigned char) data[2];	/*  if out put then Value */
-	i_ReturnValue = insn->n;
-	pb_PortValue = (unsigned char *) &data[0];
-/* if input then read value */
-
-	switch (b_PortOperation) {
-	case APCI1710_INPUT:
-		/**************************/
-		/* Test the module number */
-		/**************************/
-
-		if (b_ModulNbr < 4) {
-			/*******************************/
-			/* Test if digital I/O counter */
-			/*******************************/
-
-			if ((devpriv->s_BoardInfos.
-					dw_MolduleConfiguration[b_ModulNbr] &
-					0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
-				/**********************************************/
-				/* Test if the digital I/O module initialised */
-				/**********************************************/
-
-				if (devpriv->s_ModuleInfo[b_ModulNbr].
-					s_DigitalIOInfo.b_DigitalInit == 1) {
-					/**************************/
-					/* Read all digital input */
-					/**************************/
-
-					/* INPDW (ps_APCI1710Variable->
-					 * s_Board [b_BoardHandle].
-					 * s_BoardInfos.
-					 * ui_Address + (64 * b_ModulNbr),
-					 * &dw_StatusReg);
-					 */
-
-					dw_StatusReg =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + (64 * b_ModulNbr));
-					*pb_PortValue =
-						(unsigned char) (dw_StatusReg ^ 0x1C);
-
-				} else {
-					/*******************************/
-					/* Digital I/O not initialised */
-					/*******************************/
-
-					i_ReturnValue = -4;
-				}
-			} else {
-				/******************************************/
-				/* The module is not a digital I/O module */
-				/******************************************/
-
-				i_ReturnValue = -3;
-			}
-		} else {
-	   /***********************/
-			/* Module number error */
-	   /***********************/
-
-			i_ReturnValue = -2;
-		}
-
-		break;
-
-	case APCI1710_OUTPUT:
-	/**************************/
-		/* Test the module number */
-	/**************************/
-
-		if (b_ModulNbr < 4) {
-	   /*******************************/
-			/* Test if digital I/O counter */
-	   /*******************************/
-
-			if ((devpriv->s_BoardInfos.
-					dw_MolduleConfiguration[b_ModulNbr] &
-					0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
-	      /**********************************************/
-				/* Test if the digital I/O module initialised */
-	      /**********************************************/
-
-				if (devpriv->s_ModuleInfo[b_ModulNbr].
-					s_DigitalIOInfo.b_DigitalInit == 1) {
-		 /***********************/
-					/* Test the port value */
-		 /***********************/
-
-					if (b_PortValue <= 7) {
-		    /***********************************/
-						/* Test the digital output channel */
-		    /***********************************/
-
-		    /**************************/
-						/* Test if channel A used */
-		    /**************************/
-
-						if ((b_PortValue & 2) == 2) {
-							if (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								b_ChannelAMode
-								!= 1) {
-			  /*******************************************/
-								/* The digital channel A is used for input */
-			  /*******************************************/
-
-								i_ReturnValue =
-									-6;
-							}
-						}	/*  if ((b_PortValue & 2) == 2) */
-
-						/**************************/
-						/* Test if channel B used */
-						/**************************/
-
-						if ((b_PortValue & 4) == 4) {
-							if (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_DigitalIOInfo.
-								b_ChannelBMode
-								!= 1) {
-								/*******************************************/
-								/* The digital channel B is used for input */
-								/*******************************************/
-
-								i_ReturnValue =
-									-7;
-							}
-						}	/*  if ((b_PortValue & 4) == 4) */
-
-						/***********************/
-						/* Test if error occur */
-						/***********************/
-
-						if (i_ReturnValue >= 0) {
-
-							/* if(data[1]) { */
-
-							switch (b_PortOnOFF) {
-								/*********************************/
-								/* Test if set Port ON                   */
-								/*********************************/
-
-							case APCI1710_ON:
-
-								/*********************************/
-								/* Test if output memory enabled */
-								/*********************************/
-
-								if (devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_DigitalIOInfo.
-									b_OutputMemoryEnabled
-									== 1) {
-									dw_WriteValue
-										=
-										devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_DigitalIOInfo.
-										dw_OutputMemory
-										|
-										b_PortValue;
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_DigitalIOInfo.
-										dw_OutputMemory
-										=
-										dw_WriteValue;
-								} else {
-									dw_WriteValue
-										=
-										b_PortValue;
-								}
-								break;
-
-								/*  If Set PORT  OFF */
-							case APCI1710_OFF:
-
-			   /*********************************/
-								/* Test if output memory enabled */
-		       /*********************************/
-
-								if (devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_DigitalIOInfo.
-									b_OutputMemoryEnabled
-									== 1) {
-									dw_WriteValue
-										=
-										devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_DigitalIOInfo.
-										dw_OutputMemory
-										&
-										(0xFFFFFFFFUL
-										-
-										b_PortValue);
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_DigitalIOInfo.
-										dw_OutputMemory
-										=
-										dw_WriteValue;
-								} else {
-									/*****************************/
-									/* Digital Output Memory OFF */
-									/*****************************/
-
-									i_ReturnValue
-										=
-										-8;
-								}
-							}	/*  switch */
-
-							/*******************/
-							/* Write the value */
-							/*******************/
-
-							/* OUTPDW (ps_APCI1710Variable->
-							 * s_Board [b_BoardHandle].
-							 * s_BoardInfos.
-							 * ui_Address + (64 * b_ModulNbr),
-							 * dw_WriteValue); */
-
-							outl(dw_WriteValue,
-								devpriv->
-								s_BoardInfos.
-								ui_Address +
-								(64 * b_ModulNbr));
-						}
-					} else {
-						/**********************/
-						/* Output value wrong */
-						/**********************/
-
-						i_ReturnValue = -4;
-					}
-				} else {
-					/*******************************/
-					/* Digital I/O not initialised */
-					/*******************************/
-
-					i_ReturnValue = -5;
-				}
-			} else {
-	      /******************************************/
-				/* The module is not a digital I/O module */
-	      /******************************************/
-
-				i_ReturnValue = -3;
-			}
-		} else {
-	   /***********************/
-			/* Module number error */
-	   /***********************/
-
-			i_ReturnValue = -2;
-		}
-		break;
-
-	default:
-		i_ReturnValue = -9;
-		DPRINTK("NO INPUT/OUTPUT specified\n");
-	}			/* switch INPUT / OUTPUT */
-	return i_ReturnValue;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
deleted file mode 100644
index c9db601..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+++ /dev/null
@@ -1,5461 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : INC_CPT.C       | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 incremental counter module                  |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          |           |                                                |
-  |----------|-----------|------------------------------------------------|
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-  | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232                       |
-  |          |           | See i_APCI1710_DisableFrequencyMeasurement     |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_16BIT_COUNTER			0x10
-#define APCI1710_32BIT_COUNTER			0x0
-#define APCI1710_QUADRUPLE_MODE			0x0
-#define APCI1710_DOUBLE_MODE			0x3
-#define APCI1710_SIMPLE_MODE			0xF
-#define APCI1710_DIRECT_MODE			0x80
-#define APCI1710_HYSTERESIS_ON			0x60
-#define APCI1710_HYSTERESIS_OFF			0x0
-#define APCI1710_INCREMENT			0x60
-#define APCI1710_DECREMENT			0x0
-#define APCI1710_LATCH_COUNTER			0x1
-#define APCI1710_CLEAR_COUNTER			0x0
-#define APCI1710_LOW				0x0
-#define APCI1710_HIGH				0x1
-
-/*********************/
-/* Version 0600-0229 */
-/*********************/
-#define APCI1710_HIGH_EDGE_CLEAR_COUNTER		0x0
-#define APCI1710_HIGH_EDGE_LATCH_COUNTER		0x1
-#define APCI1710_LOW_EDGE_CLEAR_COUNTER			0x2
-#define APCI1710_LOW_EDGE_LATCH_COUNTER			0x3
-#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER	0x4
-#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER	0x5
-#define APCI1710_SOURCE_0				0x0
-#define APCI1710_SOURCE_1				0x1
-
-#define APCI1710_30MHZ				30
-#define APCI1710_33MHZ				33
-#define APCI1710_40MHZ				40
-
-#define APCI1710_ENABLE_LATCH_INT    		0x80
-#define APCI1710_DISABLE_LATCH_INT   		(~APCI1710_ENABLE_LATCH_INT)
-
-#define APCI1710_INDEX_LATCH_COUNTER		0x10
-#define APCI1710_INDEX_AUTO_MODE		0x8
-#define APCI1710_ENABLE_INDEX			0x4
-#define APCI1710_DISABLE_INDEX			(~APCI1710_ENABLE_INDEX)
-#define APCI1710_ENABLE_LATCH_AND_CLEAR		0x8
-#define APCI1710_DISABLE_LATCH_AND_CLEAR	(~APCI1710_ENABLE_LATCH_AND_CLEAR)
-#define APCI1710_SET_LOW_INDEX_LEVEL		0x4
-#define APCI1710_SET_HIGH_INDEX_LEVEL		(~APCI1710_SET_LOW_INDEX_LEVEL)
-#define APCI1710_INVERT_INDEX_RFERENCE		0x2
-#define APCI1710_DEFAULT_INDEX_RFERENCE         (~APCI1710_INVERT_INDEX_RFERENCE)
-
-#define APCI1710_ENABLE_INDEX_INT		0x1
-#define APCI1710_DISABLE_INDEX_INT		(~APCI1710_ENABLE_INDEX_INT)
-
-#define APCI1710_ENABLE_FREQUENCY		0x4
-#define APCI1710_DISABLE_FREQUENCY		(~APCI1710_ENABLE_FREQUENCY)
-
-#define APCI1710_ENABLE_FREQUENCY_INT		0x8
-#define APCI1710_DISABLE_FREQUENCY_INT		(~APCI1710_ENABLE_FREQUENCY_INT)
-
-#define APCI1710_ENABLE_40MHZ_FREQUENCY		0x40
-#define APCI1710_DISABLE_40MHZ_FREQUENCY	(~APCI1710_ENABLE_40MHZ_FREQUENCY)
-
-#define APCI1710_ENABLE_40MHZ_FILTER		0x80
-#define APCI1710_DISABLE_40MHZ_FILTER		(~APCI1710_ENABLE_40MHZ_FILTER)
-
-#define APCI1710_ENABLE_COMPARE_INT		0x2
-#define APCI1710_DISABLE_COMPARE_INT		(~APCI1710_ENABLE_COMPARE_INT)
-
-#define APCI1710_ENABLE_INDEX_ACTION		0x20
-#define APCI1710_DISABLE_INDEX_ACTION		(~APCI1710_ENABLE_INDEX_ACTION)
-#define APCI1710_REFERENCE_HIGH			0x40
-#define APCI1710_REFERENCE_LOW			(~APCI1710_REFERENCE_HIGH)
-
-#define APCI1710_TOR_GATE_LOW			0x40
-#define APCI1710_TOR_GATE_HIGH			(~APCI1710_TOR_GATE_LOW)
-
-/* INSN CONFIG */
-#define	APCI1710_INCCPT_INITCOUNTER			100
-#define APCI1710_INCCPT_COUNTERAUTOTEST			101
-#define APCI1710_INCCPT_INITINDEX			102
-#define APCI1710_INCCPT_INITREFERENCE			103
-#define APCI1710_INCCPT_INITEXTERNALSTROBE		104
-#define APCI1710_INCCPT_INITCOMPARELOGIC		105
-#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT	106
-
-/* INSN READ */
-#define APCI1710_INCCPT_READLATCHREGISTERSTATUS		200
-#define APCI1710_INCCPT_READLATCHREGISTERVALUE		201
-#define APCI1710_INCCPT_READ16BITCOUNTERVALUE		202
-#define APCI1710_INCCPT_READ32BITCOUNTERVALUE		203
-#define APCI1710_INCCPT_GETINDEXSTATUS			204
-#define APCI1710_INCCPT_GETREFERENCESTATUS		205
-#define APCI1710_INCCPT_GETUASSTATUS			206
-#define APCI1710_INCCPT_GETCBSTATUS			207
-#define APCI1710_INCCPT_GET16BITCBSTATUS		208
-#define APCI1710_INCCPT_GETUDSTATUS			209
-#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS	210
-#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT	211
-#define APCI1710_INCCPT_READINTERRUPT			212
-
-/* INSN BITS */
-#define APCI1710_INCCPT_CLEARCOUNTERVALUE		300
-#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE		301
-#define APCI1710_INCCPT_SETINPUTFILTER			302
-#define APCI1710_INCCPT_LATCHCOUNTER			303
-#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE	304
-#define APCI1710_INCCPT_SETDIGITALCHLON			305
-#define APCI1710_INCCPT_SETDIGITALCHLOFF		306
-
-/* INSN WRITE */
-#define APCI1710_INCCPT_ENABLELATCHINTERRUPT		400
-#define APCI1710_INCCPT_DISABLELATCHINTERRUPT		401
-#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE		402
-#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE		403
-#define APCI1710_INCCPT_ENABLEINDEX			404
-#define APCI1710_INCCPT_DISABLEINDEX			405
-#define APCI1710_INCCPT_ENABLECOMPARELOGIC		406
-#define APCI1710_INCCPT_DISABLECOMPARELOGIC		407
-#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT	408
-#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT	409
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitCounter                           |
-|                               (unsigned char_          b_BoardHandle,               |
-|                                unsigned char_          b_ModulNbr,                  |
-|                                unsigned char_          b_CounterRange,              |
-|                                unsigned char_          b_FirstCounterModus,         |
-|                                unsigned char_          b_FirstCounterOption,        |
-|                                unsigned char_          b_SecondCounterModus,        |
-|                                unsigned char_          b_SecondCounterOption)       |
-+----------------------------------------------------------------------------+
-| Task              : Configure the counter operating mode from selected     |
-|                     module (b_ModulNbr). You must calling this function be |
-|                     for you call any other function witch access of        |
-|                     counters.                                              |
-|                                                                            |
-|                          Counter range                                     |
-|                          -------------                                     |
-| +------------------------------------+-----------------------------------+ |
-| | Parameter       Passed value       |        Description                | |
-| |------------------------------------+-----------------------------------| |
-| |b_ModulNbr   APCI1710_16BIT_COUNTER |  The module is configured for     | |
-| |                                    |  two 16-bit counter.              | |
-| |                                    |  - b_FirstCounterModus and        | |
-| |                                    |    b_FirstCounterOption           | |
-| |                                    |    configure the first 16 bit     | |
-| |                                    |    counter.                       | |
-| |                                    |  - b_SecondCounterModus and       | |
-| |                                    |    b_SecondCounterOption          | |
-| |                                    |    configure the second 16 bit    | |
-| |                                    |    counter.                       | |
-| |------------------------------------+-----------------------------------| |
-| |b_ModulNbr   APCI1710_32BIT_COUNTER |  The module is configured for one | |
-| |                                    |  32-bit counter.                  | |
-| |                                    |  - b_FirstCounterModus and        | |
-| |                                    |    b_FirstCounterOption           | |
-| |                                    |    configure the 32 bit counter.  | |
-| |                                    |  - b_SecondCounterModus and       | |
-| |                                    |    b_SecondCounterOption          | |
-| |                                    |    are not used and have no       | |
-| |                                    |    importance.                    | |
-| +------------------------------------+-----------------------------------+ |
-|                                                                            |
-|                      Counter operating mode                                |
-|                      ----------------------                                |
-|                                                                            |
-| +--------------------+-------------------------+-------------------------+ |
-| |    Parameter       |     Passed value        |    Description          | |
-| |--------------------+-------------------------+-------------------------| |
-| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode,  | |
-| |       or           |                         | the edge analysis       | |
-| |b_SecondCounterModus|                         | circuit generates a     | |
-| |                    |                         | counting pulse from     | |
-| |                    |                         | each edge of 2 signals  | |
-| |                    |                         | which are phase shifted | |
-| |                    |                         | in relation to each     | |
-| |                    |                         | other.                  | |
-| |--------------------+-------------------------+-------------------------| |
-| |b_FirstCounterModus |   APCI1710_DOUBLE_MODE  | Functions in the same   | |
-| |       or           |                         | way as the quadruple    | |
-| |b_SecondCounterModus|                         | mode, except that only  | |
-| |                    |                         | two of the four edges   | |
-| |                    |                         | are analysed per        | |
-| |                    |                         | period                  | |
-| |--------------------+-------------------------+-------------------------| |
-| |b_FirstCounterModus |   APCI1710_SIMPLE_MODE  | Functions in the same   | |
-| |       or           |                         | way as the quadruple    | |
-| |b_SecondCounterModus|                         | mode, except that only  | |
-| |                    |                         | one of the four edges   | |
-| |                    |                         | is analysed per         | |
-| |                    |                         | period.                 | |
-| |--------------------+-------------------------+-------------------------| |
-| |b_FirstCounterModus |   APCI1710_DIRECT_MODE  | In the direct mode the  | |
-| |       or           |                         | both edge analysis      | |
-| |b_SecondCounterModus|                         | circuits are inactive.  | |
-| |                    |                         | The inputs A, B in the  | |
-| |                    |                         | 32-bit mode or A, B and | |
-| |                    |                         | C, D in the 16-bit mode | |
-| |                    |                         | represent, each, one    | |
-| |                    |                         | clock pulse gate circuit| |
-| |                    |                         | There by frequency and  | |
-| |                    |                         | pulse duration          | |
-| |                    |                         | measurements can be     | |
-| |                    |                         | performed.              | |
-| +--------------------+-------------------------+-------------------------+ |
-|                                                                            |
-|                                                                            |
-|       IMPORTANT!                                                           |
-|       If you have configured the module for two 16-bit counter, a mixed    |
-|       mode with a counter in quadruple/double/single mode                  |
-|       and the other counter in direct mode is not possible!                |
-|                                                                            |
-|                                                                            |
-|         Counter operating option for quadruple/double/simple mode          |
-|         ---------------------------------------------------------          |
-|                                                                            |
-| +----------------------+-------------------------+------------------------+|
-| |       Parameter      |     Passed value        |  Description           ||
-| |----------------------+-------------------------+------------------------||
-| |b_FirstCounterOption  | APCI1710_HYSTERESIS_ON  | In both edge analysis  ||
-| |        or            |                         | circuits is available  ||
-| |b_SecondCounterOption |                         | one hysteresis circuit.||
-| |                      |                         | It suppresses each     ||
-| |                      |                         | time the first counting||
-| |                      |                         | pulse after a change   ||
-| |                      |                         | of rotation.           ||
-| |----------------------+-------------------------+------------------------||
-| |b_FirstCounterOption  | APCI1710_HYSTERESIS_OFF | The first counting     ||
-| |       or             |                         | pulse is not suppress  ||
-| |b_SecondCounterOption |                         | after a change of      ||
-| |                      |                         | rotation.              ||
-| +----------------------+-------------------------+------------------------+|
-|                                                                            |
-|                                                                            |
-|       IMPORTANT!                                                           |
-|       This option are only avaible if you have selected the direct mode.   |
-|                                                                            |
-|                                                                            |
-|               Counter operating option for direct mode                     |
-|               ----------------------------------------                     |
-|                                                                            |
-| +----------------------+--------------------+----------------------------+ |
-| |      Parameter       |     Passed value   |       Description          | |
-| |----------------------+--------------------+----------------------------| |
-| |b_FirstCounterOption  | APCI1710_INCREMENT | The counter increment for  | |
-| |       or             |                    | each counting pulse        | |
-| |b_SecondCounterOption |                    |                            | |
-| |----------------------+--------------------+----------------------------| |
-| |b_FirstCounterOption  | APCI1710_DECREMENT | The counter decrement for  | |
-| |       or             |                    | each counting pulse        | |
-| |b_SecondCounterOption |                    |                            | |
-| +----------------------+--------------------+----------------------------+ |
-|                                                                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 3)       |
-|                     unsigned char_ b_CounterRange        : Selection form counter   |
-|                                                   range.                   |
-|                     unsigned char_ b_FirstCounterModus   : First counter operating  |
-|                                                   mode.                    |
-|                     unsigned char_ b_FirstCounterOption  : First counter  option.   |
-|                     unsigned char_ b_SecondCounterModus  : Second counter operating |
-|                                                   mode.                    |
-|                     unsigned char_ b_SecondCounterOption : Second counter  option.  |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module is not a counter module                  |
-|                    -3: The selected counter range is wrong.                |
-|                    -4: The selected first counter operating mode is wrong. |
-|                    -5: The selected first counter operating option is wrong|
-|                    -6: The selected second counter operating mode is wrong.|
-|                    -7: The selected second counter operating option is     |
-|                        wrong.                                              |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InitCounter(struct comedi_device *dev,
-				  unsigned char b_ModulNbr,
-				  unsigned char b_CounterRange,
-				  unsigned char b_FirstCounterModus,
-				  unsigned char b_FirstCounterOption,
-				  unsigned char b_SecondCounterModus,
-				  unsigned char b_SecondCounterOption)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/*******************************/
-	/* Test if incremental counter */
-	/*******************************/
-
-	if ((devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER) {
-	   /**************************/
-		/* Test the counter range */
-	   /**************************/
-
-		if (b_CounterRange == APCI1710_16BIT_COUNTER
-			|| b_CounterRange == APCI1710_32BIT_COUNTER) {
-	      /********************************/
-			/* Test the first counter modus */
-	      /********************************/
-
-			if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE ||
-				b_FirstCounterModus == APCI1710_DOUBLE_MODE ||
-				b_FirstCounterModus == APCI1710_SIMPLE_MODE ||
-				b_FirstCounterModus == APCI1710_DIRECT_MODE) {
-		 /*********************************/
-				/* Test the first counter option */
-		 /*********************************/
-
-				if ((b_FirstCounterModus == APCI1710_DIRECT_MODE
-						&& (b_FirstCounterOption ==
-							APCI1710_INCREMENT
-							|| b_FirstCounterOption
-							== APCI1710_DECREMENT))
-					|| (b_FirstCounterModus !=
-						APCI1710_DIRECT_MODE
-						&& (b_FirstCounterOption ==
-							APCI1710_HYSTERESIS_ON
-							|| b_FirstCounterOption
-							==
-							APCI1710_HYSTERESIS_OFF)))
-				{
-		    /**************************/
-					/* Test if 16-bit counter */
-		    /**************************/
-
-					if (b_CounterRange ==
-						APCI1710_16BIT_COUNTER) {
-		       /*********************************/
-						/* Test the second counter modus */
-		       /*********************************/
-
-						if ((b_FirstCounterModus !=
-								APCI1710_DIRECT_MODE
-								&&
-								(b_SecondCounterModus
-									==
-									APCI1710_QUADRUPLE_MODE
-									||
-									b_SecondCounterModus
-									==
-									APCI1710_DOUBLE_MODE
-									||
-									b_SecondCounterModus
-									==
-									APCI1710_SIMPLE_MODE))
-							|| (b_FirstCounterModus
-								==
-								APCI1710_DIRECT_MODE
-								&&
-								b_SecondCounterModus
-								==
-								APCI1710_DIRECT_MODE))
-						{
-			  /**********************************/
-							/* Test the second counter option */
-			  /**********************************/
-
-							if ((b_SecondCounterModus == APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_INCREMENT || b_SecondCounterOption == APCI1710_DECREMENT)) || (b_SecondCounterModus != APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_HYSTERESIS_ON || b_SecondCounterOption == APCI1710_HYSTERESIS_OFF))) {
-								i_ReturnValue =
-									0;
-							} else {
-			     /*********************************************************/
-								/* The selected second counter operating option is wrong */
-			     /*********************************************************/
-
-								DPRINTK("The selected second counter operating option is wrong\n");
-								i_ReturnValue =
-									-7;
-							}
-						} else {
-			  /*******************************************************/
-							/* The selected second counter operating mode is wrong */
-			  /*******************************************************/
-
-							DPRINTK("The selected second counter operating mode is wrong\n");
-							i_ReturnValue = -6;
-						}
-					}
-				} else {
-		    /********************************************************/
-					/* The selected first counter operating option is wrong */
-		    /********************************************************/
-
-					DPRINTK("The selected first counter operating option is wrong\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /******************************************************/
-				/* The selected first counter operating mode is wrong */
-		 /******************************************************/
-				DPRINTK("The selected first counter operating mode is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /***************************************/
-			/* The selected counter range is wrong */
-	      /***************************************/
-
-			DPRINTK("The selected counter range is wrong\n");
-			i_ReturnValue = -3;
-		}
-
-	   /*************************/
-		/* Test if a error occur */
-	   /*************************/
-
-		if (i_ReturnValue == 0) {
-	      /**************************/
-			/* Test if 16-Bit counter */
-	      /**************************/
-
-			if (b_CounterRange == APCI1710_32BIT_COUNTER) {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister1 = b_CounterRange |
-					b_FirstCounterModus |
-					b_FirstCounterOption;
-			} else {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister1 = b_CounterRange |
-					(b_FirstCounterModus & 0x5) |
-					(b_FirstCounterOption & 0x20) |
-					(b_SecondCounterModus & 0xA) |
-					(b_SecondCounterOption & 0x40);
-
-		 /***********************/
-				/* Test if direct mode */
-		 /***********************/
-
-				if (b_FirstCounterModus == APCI1710_DIRECT_MODE) {
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister1 = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister1 |
-						APCI1710_DIRECT_MODE;
-				}
-			}
-
-	      /***************************/
-			/* Write the configuration */
-	      /***************************/
-
-			outl(devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				dw_ModeRegister1_2_3_4,
-				devpriv->s_BoardInfos.
-				ui_Address + 20 + (64 * b_ModulNbr));
-
-			devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_CounterInit = 1;
-		}
-	} else {
-	   /**************************************/
-		/* The module is not a counter module */
-	   /**************************************/
-
-		DPRINTK("The module is not a counter module\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_CounterAutoTest                       |
-|                                               (unsigned char_     b_BoardHandle,    |
-|                                                unsigned char *_   pb_TestStatus)     |
-+----------------------------------------------------------------------------+
-| Task              : A test mode is intended for testing the component and  |
-|                     the connected periphery. All the 8-bit counter chains  |
-|                     are operated internally as down counters.              |
-|                     Independently from the external signals,               |
-|                     all the four 8-bit counter chains are decremented in   |
-|                     parallel by each negative clock pulse edge of CLKX.    |
-|                                                                            |
-|                       Counter auto test conclusion                         |
-|                       ----------------------------                         |
-|              +-----------------+-----------------------------+             |
-|              | pb_TestStatus   |    Error description        |             |
-|              |     mask        |                             |             |
-|              |-----------------+-----------------------------|             |
-|              |    0000         |     No error detected       |             |
-|              |-----------------|-----------------------------|             |
-|              |    0001         | Error detected of counter 0 |             |
-|              |-----------------|-----------------------------|             |
-|              |    0010         | Error detected of counter 1 |             |
-|              |-----------------|-----------------------------|             |
-|              |    0100         | Error detected of counter 2 |             |
-|              |-----------------|-----------------------------|             |
-|              |    1000         | Error detected of counter 3 |             |
-|              +-----------------+-----------------------------+             |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle : Handle of board APCI-1710      |  |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_TestStatus  : Auto test conclusion. See table|
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_CounterAutoTest(struct comedi_device *dev,
-				      unsigned char *pb_TestStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned char b_ModulCpt = 0;
-	int i_ReturnValue = 0;
-	unsigned int dw_LathchValue;
-
-	*pb_TestStatus = 0;
-
-	/********************************/
-	/* Test if counter module found */
-	/********************************/
-
-	if ((devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[0] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER
-		|| (devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[1] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER
-		|| (devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[2] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER
-		|| (devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[3] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER) {
-		for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) {
-	      /*******************************/
-			/* Test if incremental counter */
-	      /*******************************/
-
-			if ((devpriv->s_BoardInfos.
-					dw_MolduleConfiguration[b_ModulCpt] &
-					0xFFFF0000UL) ==
-				APCI1710_INCREMENTAL_COUNTER) {
-		 /******************/
-				/* Start the test */
-		 /******************/
-
-				outl(3, devpriv->s_BoardInfos.
-					ui_Address + 16 + (64 * b_ModulCpt));
-
-		 /*********************/
-				/* Tatch the counter */
-		 /*********************/
-
-				outl(1, devpriv->s_BoardInfos.
-					ui_Address + (64 * b_ModulCpt));
-
-		 /************************/
-				/* Read the latch value */
-		 /************************/
-
-				dw_LathchValue = inl(devpriv->s_BoardInfos.
-					ui_Address + 4 + (64 * b_ModulCpt));
-
-				if ((dw_LathchValue & 0xFF) !=
-					((dw_LathchValue >> 8) & 0xFF)
-					&& (dw_LathchValue & 0xFF) !=
-					((dw_LathchValue >> 16) & 0xFF)
-					&& (dw_LathchValue & 0xFF) !=
-					((dw_LathchValue >> 24) & 0xFF)) {
-					*pb_TestStatus =
-						*pb_TestStatus | (1 <<
-						b_ModulCpt);
-				}
-
-		 /*****************/
-				/* Stop the test */
-		 /*****************/
-
-				outl(0, devpriv->s_BoardInfos.
-					ui_Address + 16 + (64 * b_ModulCpt));
-			}
-		}
-	} else {
-	   /***************************/
-		/* No counter module found */
-	   /***************************/
-
-		DPRINTK("No counter module found\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitIndex (unsigned char_ b_BoardHandle,       |
-|                                                 unsigned char_ b_ModulNbr,          |
-|                                                 unsigned char_ b_ReferenceAction,   |
-|                                                 unsigned char_ b_IndexOperation,    |
-|                                                 unsigned char_ b_AutoMode,          |
-|                                                 unsigned char_ b_InterruptEnable)   |
-+----------------------------------------------------------------------------+
-| Task              : Initialise the index corresponding to the selected     |
-|                     module (b_ModulNbr). If a INDEX flag occur, you have   |
-|                     the possibility to clear the 32-Bit counter or to latch|
-|                     the current 32-Bit value in to the first latch         |
-|                     register. The b_IndexOperation parameter give the      |
-|                     possibility to choice the INDEX action.                |
-|                     If you have enabled the automatic mode, each INDEX     |
-|                     action is cleared automatically, else you must read    |
-|                     the index status ("i_APCI1710_ReadIndexStatus")        |
-|                     after each INDEX action.                               |
-|                                                                            |
-|                                                                            |
-|                               Index action                                 |
-|                               ------------                                 |
-|                                                                            |
-|           +------------------------+------------------------------------+  |
-|           |   b_IndexOperation     |         Operation                  |  |
-|           |------------------------+------------------------------------|  |
-|           |APCI1710_LATCH_COUNTER  | After a index signal, the counter  |  |
-|           |                        | value (32-Bit) is latched in to    |  |
-|           |                        | the first latch register           |  |
-|           |------------------------|------------------------------------|  |
-|           |APCI1710_CLEAR_COUNTER  | After a index signal, the counter  |  |
-|           |                        | value is cleared (32-Bit)          |  |
-|           +------------------------+------------------------------------+  |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-|                     unsigned char_ b_ReferenceAction : Determine if the reference   |
-|                                               must set or no for the       |
-|                                               acceptance from index        |
-|                                               APCI1710_ENABLE :            |
-|                                                  Reference must be set for |
-|                                                  accepted the index        |
-|                                               APCI1710_DISABLE :           |
-|                                                  Reference have not        |
-|                                                  importance                |
-|                     unsigned char_ b_IndexOperation  : Index operating mode.        |
-|                                               See table.                   |
-|                     unsigned char_ b_AutoMode        : Enable or disable the        |
-|                                               automatic index reset.       |
-|                                               APCI1710_ENABLE :            |
-|                                                 Enable the automatic mode  |
-|                                               APCI1710_DISABLE :           |
-|                                                 Disable the automatic mode |
-|                     unsigned char_ b_InterruptEnable : Enable or disable the        |
-|                                               interrupt.                   |
-|                                               APCI1710_ENABLE :            |
-|                                               Enable the interrupt         |
-|                                               APCI1710_DISABLE :           |
-|                                               Disable the interrupt        |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4  The reference action parameter is wrong            |
-|                     -5: The index operating mode parameter is wrong        |
-|                     -6: The auto mode parameter is wrong                   |
-|                     -7: Interrupt parameter is wrong                       |
-|                     -8: Interrupt function not initialised.                |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InitIndex(struct comedi_device *dev,
-				unsigned char b_ModulNbr,
-				unsigned char b_ReferenceAction,
-				unsigned char b_IndexOperation,
-				unsigned char b_AutoMode,
-				unsigned char b_InterruptEnable)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /********************************/
-			/* Test the reference parameter */
-	      /********************************/
-
-			if (b_ReferenceAction == APCI1710_ENABLE ||
-				b_ReferenceAction == APCI1710_DISABLE) {
-		 /****************************/
-				/* Test the index parameter */
-		 /****************************/
-
-				if (b_IndexOperation ==
-					APCI1710_HIGH_EDGE_LATCH_COUNTER
-					|| b_IndexOperation ==
-					APCI1710_LOW_EDGE_LATCH_COUNTER
-					|| b_IndexOperation ==
-					APCI1710_HIGH_EDGE_CLEAR_COUNTER
-					|| b_IndexOperation ==
-					APCI1710_LOW_EDGE_CLEAR_COUNTER
-					|| b_IndexOperation ==
-					APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER
-					|| b_IndexOperation ==
-					APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
-				{
-		    /********************************/
-					/* Test the auto mode parameter */
-		    /********************************/
-
-					if (b_AutoMode == APCI1710_ENABLE ||
-						b_AutoMode == APCI1710_DISABLE)
-					{
-		       /***************************/
-						/* Test the interrupt mode */
-		       /***************************/
-
-						if (b_InterruptEnable ==
-							APCI1710_ENABLE
-							|| b_InterruptEnable ==
-							APCI1710_DISABLE) {
-
-			     /************************************/
-							/* Makte the configuration commando */
-			     /************************************/
-
-							if (b_ReferenceAction ==
-								APCI1710_ENABLE)
-							{
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									|
-									APCI1710_ENABLE_INDEX_ACTION;
-							} else {
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									&
-									APCI1710_DISABLE_INDEX_ACTION;
-							}
-
-			     /****************************************/
-							/* Test if low level latch or/and clear */
-			     /****************************************/
-
-							if (b_IndexOperation ==
-								APCI1710_LOW_EDGE_LATCH_COUNTER
-								||
-								b_IndexOperation
-								==
-								APCI1710_LOW_EDGE_CLEAR_COUNTER
-								||
-								b_IndexOperation
-								==
-								APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
-							{
-				/*************************************/
-								/* Set the index level to low (DQ26) */
-				/*************************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									|
-									APCI1710_SET_LOW_INDEX_LEVEL;
-							} else {
-				/**************************************/
-								/* Set the index level to high (DQ26) */
-				/**************************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									&
-									APCI1710_SET_HIGH_INDEX_LEVEL;
-							}
-
-			     /***********************************/
-							/* Test if latch and clear counter */
-			     /***********************************/
-
-							if (b_IndexOperation ==
-								APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER
-								||
-								b_IndexOperation
-								==
-								APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
-							{
-				/***************************************/
-								/* Set the latch and clear flag (DQ27) */
-				/***************************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									|
-									APCI1710_ENABLE_LATCH_AND_CLEAR;
-							}	/*  if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) */
-							else {
-				/*****************************************/
-								/* Clear the latch and clear flag (DQ27) */
-				/*****************************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									&
-									APCI1710_DISABLE_LATCH_AND_CLEAR;
-
-				/*************************/
-								/* Test if latch counter */
-				/*************************/
-
-								if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER) {
-				   /*********************************/
-									/* Enable the latch from counter */
-				   /*********************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister2
-										=
-										devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister2
-										|
-										APCI1710_INDEX_LATCH_COUNTER;
-								} else {
-				   /*********************************/
-									/* Enable the clear from counter */
-				   /*********************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister2
-										=
-										devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister2
-										&
-										(~APCI1710_INDEX_LATCH_COUNTER);
-								}
-							}	/*  // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) */
-
-							if (b_AutoMode ==
-								APCI1710_DISABLE)
-							{
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									|
-									APCI1710_INDEX_AUTO_MODE;
-							} else {
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister2
-									&
-									(~APCI1710_INDEX_AUTO_MODE);
-							}
-
-							if (b_InterruptEnable ==
-								APCI1710_ENABLE)
-							{
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister3
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister3
-									|
-									APCI1710_ENABLE_INDEX_INT;
-							} else {
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister3
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister3
-									&
-									APCI1710_DISABLE_INDEX_INT;
-							}
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_SiemensCounterInfo.
-								s_InitFlag.
-								b_IndexInit = 1;
-
-						} else {
-			  /********************************/
-							/* Interrupt parameter is wrong */
-			  /********************************/
-							DPRINTK("Interrupt parameter is wrong\n");
-							i_ReturnValue = -7;
-						}
-					} else {
-		       /************************************/
-						/* The auto mode parameter is wrong */
-		       /************************************/
-
-						DPRINTK("The auto mode parameter is wrong\n");
-						i_ReturnValue = -6;
-					}
-				} else {
-		    /***********************************************/
-					/* The index operating mode parameter is wrong */
-		    /***********************************************/
-
-					DPRINTK("The index operating mode parameter is wrong\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /*******************************************/
-				/* The reference action parameter is wrong */
-		 /*******************************************/
-
-				DPRINTK("The reference action parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitReference                         |
-|                                                (unsigned char_ b_BoardHandle,       |
-|                                                 unsigned char_ b_ModulNbr,          |
-|                                                 unsigned char_ b_ReferenceLevel)    |
-+----------------------------------------------------------------------------+
-| Task              : Initialise the reference corresponding to the selected |
-|                     module (b_ModulNbr).                                   |
-|                                                                            |
-|                               Reference level                              |
-|                               ---------------                              |
-|             +--------------------+-------------------------+               |
-|             | b_ReferenceLevel   |         Operation       |               |
-|             +--------------------+-------------------------+               |
-|             |   APCI1710_LOW     |  Reference occur if "0" |               |
-|             |--------------------|-------------------------|               |
-|             |   APCI1710_HIGH    |  Reference occur if "1" |               |
-|             +--------------------+-------------------------+               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-|                     unsigned char_ b_ReferenceLevel  : Reference level.             |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number parameter is wrong      |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Reference level parameter is wrong                 |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InitReference(struct comedi_device *dev,
-				    unsigned char b_ModulNbr,
-				    unsigned char b_ReferenceLevel)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /**************************************/
-			/* Test the reference level parameter */
-	      /**************************************/
-
-			if (b_ReferenceLevel == 0 || b_ReferenceLevel == 1) {
-				if (b_ReferenceLevel == 1) {
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister2 = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister2 |
-						APCI1710_REFERENCE_HIGH;
-				} else {
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister2 = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister2 &
-						APCI1710_REFERENCE_LOW;
-				}
-
-				outl(devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					dw_ModeRegister1_2_3_4,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_InitFlag.b_ReferenceInit = 1;
-			} else {
-		 /**************************************/
-				/* Reference level parameter is wrong */
-		 /**************************************/
-
-				DPRINTK("Reference level parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_	i_APCI1710_InitExternalStrobe                |
-|					(unsigned char_ b_BoardHandle,                |
-|					 unsigned char_ b_ModulNbr,                   |
-|					 unsigned char_ b_ExternalStrobe,             |
-|					 unsigned char_ b_ExternalStrobeLevel)        |
-+----------------------------------------------------------------------------+
-| Task              : Initialises the external strobe level corresponding to |
-|		      the selected module (b_ModulNbr).                      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-|		      unsigned char_ b_ExternalStrobe  : External strobe selection    |
-|						0 : External strobe A        |
-|						1 : External strobe B        |
-|		      unsigned char_ b_ExternalStrobeLevel : External strobe level    |
-|						APCI1710_LOW :               |
-|						External latch occurs if "0" |
-|						APCI1710_HIGH :              |
-|						External latch occurs if "1" |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number is wrong                |
-|                     -3: Counter not initialised.                           |
-|			  See function "i_APCI1710_InitCounter"              |
-|                     -4: External strobe selection is wrong                 |
-|                     -5: External strobe level parameter is wrong           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
-					 unsigned char b_ModulNbr,
-					 unsigned char b_ExternalStrobe,
-					 unsigned char b_ExternalStrobeLevel)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /**************************************/
-			/* Test the external strobe selection */
-	      /**************************************/
-
-			if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) {
-		 /******************/
-				/* Test the level */
-		 /******************/
-
-				if ((b_ExternalStrobeLevel == APCI1710_HIGH) ||
-					((b_ExternalStrobeLevel == APCI1710_LOW
-							&& (devpriv->
-								s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) >=
-							0x3135))) {
-		    /*****************/
-					/* Set the level */
-		    /*****************/
-
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister4 = (devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister4 & (0xFF -
-							(0x10 << b_ExternalStrobe))) | ((b_ExternalStrobeLevel ^ 1) << (4 + b_ExternalStrobe));
-				} else {
-		    /********************************************/
-					/* External strobe level parameter is wrong */
-		    /********************************************/
-
-					DPRINTK("External strobe level parameter is wrong\n");
-					i_ReturnValue = -5;
-				}
-			}	/*  if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) */
-			else {
-		 /**************************************/
-				/* External strobe selection is wrong */
-		 /**************************************/
-
-				DPRINTK("External strobe selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) */
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-	/*
-	   +----------------------------------------------------------------------------+
-	   | Function Name     : _INT_ i_APCI1710_InitCompareLogic                      |
-	   |                               (unsigned char_   b_BoardHandle,                      |
-	   |                                unsigned char_   b_ModulNbr,                         |
-	   |                                unsigned int_  ui_CompareValue)                     |
-	   +----------------------------------------------------------------------------+
-	   | Task              : Set the 32-Bit compare value. At that moment that the  |
-	   |                     incremental counter arrive to the compare value        |
-	   |                     (ui_CompareValue) a interrupt is generated.            |
-	   +----------------------------------------------------------------------------+
-	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-	   |                     unsigned char_  b_ModulNbr       : Module number to configure   |
-	   |                                               (0 to 3)                     |
-	   |                     unsigned int_ ui_CompareValue   : 32-Bit compare value         |
-	   +----------------------------------------------------------------------------+
-	   | Output Parameters : -
-	   +----------------------------------------------------------------------------+
-	   | Return Value      :  0: No error                                           |
-	   |                     -1: The handle parameter of the board is wrong         |
-	   |                     -2: No counter module found                            |
-	   |                     -3: Counter not initialised see function               |
-	   |                         "i_APCI1710_InitCounter"                           |
-	   +----------------------------------------------------------------------------+
-	 */
-static int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
-				       unsigned char b_ModulNbr,
-				       unsigned int ui_CompareValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-
-			outl(ui_CompareValue, devpriv->s_BoardInfos.
-				ui_Address + 28 + (64 * b_ModulNbr));
-
-			devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_CompareLogicInit = 1;
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitFrequencyMeasurement              |
-|				(unsigned char_		 b_BoardHandle,              |
-|				 unsigned char_		 b_ModulNbr,                 |
-|				 unsigned char_		 b_PCIInputClock,            |
-|				 unsigned char_		 b_TimingUnity,              |
-|				 ULONG_ 	ul_TimingInterval,           |
-|				 PULONG_       pul_RealTimingInterval)       |
-+----------------------------------------------------------------------------+
-| Task              : Sets the time for the frequency measurement.           |
-|		      Configures the selected TOR incremental counter of the |
-|		      selected module (b_ModulNbr). The ul_TimingInterval and|
-|		      ul_TimingUnity determine the time base for the         |
-|		      measurement. The pul_RealTimingInterval returns the    |
-|		      real time value. You must call up this function before |
-|		      you call up any other function which gives access to   |
-|		      the frequency measurement.                             |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
-|						configured (0 to 3)          |
-|		      unsigned char_  b_PCIInputClock  :	Selection of the PCI bus     |
-|						clock                        |
-|						- APCI1710_30MHZ :           |
-|						  The PC has a PCI bus clock |
-|						  of 30 MHz                  |
-|						- APCI1710_33MHZ :           |
-|						  The PC has a PCI bus clock |
-|						  of 33 MHz                  |
-|		      unsigned char_  b_TimingUnity    : Base time unit (0 to 2)      |
-|						  0 : ns                     |
-|						  1 : æs                     |
-|						  2 : ms                     |
-|		      ULONG_ ul_TimingInterval: Base time value.             |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number is wrong                |
-|                     -3: Counter not initialised see function               |
-|			  "i_APCI1710_InitCounter"                           |
-|                     -4: The selected PCI input clock is wrong              |
-|                     -5: Timing unity selection is wrong                    |
-|                     -6: Base timing selection is wrong                     |
-|		      -7: 40MHz quartz not on board                          |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
-					       unsigned char b_ModulNbr,
-					       unsigned char b_PCIInputClock,
-					       unsigned char b_TimingUnity,
-					       unsigned int ul_TimingInterval,
-					       unsigned int *pul_RealTimingInterval)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ul_TimerValue = 0;
-	double d_RealTimingInterval;
-	unsigned int dw_Status = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /**************************/
-			/* Test the PCI bus clock */
-	      /**************************/
-
-			if ((b_PCIInputClock == APCI1710_30MHZ) ||
-				(b_PCIInputClock == APCI1710_33MHZ) ||
-				(b_PCIInputClock == APCI1710_40MHZ)) {
-		 /************************/
-				/* Test the timing unit */
-		 /************************/
-
-				if (b_TimingUnity <= 2) {
-		    /**********************************/
-					/* Test the base timing selection */
-		    /**********************************/
-
-					if (((b_PCIInputClock == APCI1710_30MHZ)
-							&& (b_TimingUnity == 0)
-							&& (ul_TimingInterval >=
-								266)
-							&& (ul_TimingInterval <=
-								8738133UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_30MHZ)
-							&& (b_TimingUnity == 1)
-							&& (ul_TimingInterval >=
-								1)
-							&& (ul_TimingInterval <=
-								8738UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_30MHZ)
-							&& (b_TimingUnity == 2)
-							&& (ul_TimingInterval >=
-								1)
-							&& (ul_TimingInterval <=
-								8UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_33MHZ)
-							&& (b_TimingUnity == 0)
-							&& (ul_TimingInterval >=
-								242)
-							&& (ul_TimingInterval <=
-								7943757UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_33MHZ)
-							&& (b_TimingUnity == 1)
-							&& (ul_TimingInterval >=
-								1)
-							&& (ul_TimingInterval <=
-								7943UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_33MHZ)
-							&& (b_TimingUnity == 2)
-							&& (ul_TimingInterval >=
-								1)
-							&& (ul_TimingInterval <=
-								7UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_40MHZ)
-							&& (b_TimingUnity == 0)
-							&& (ul_TimingInterval >=
-								200)
-							&& (ul_TimingInterval <=
-								6553500UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_40MHZ)
-							&& (b_TimingUnity == 1)
-							&& (ul_TimingInterval >=
-								1)
-							&& (ul_TimingInterval <=
-								6553UL))
-						|| ((b_PCIInputClock ==
-								APCI1710_40MHZ)
-							&& (b_TimingUnity == 2)
-							&& (ul_TimingInterval >=
-								1)
-							&& (ul_TimingInterval <=
-								6UL))) {
-		       /**********************/
-						/* Test if 40MHz used */
-		       /**********************/
-
-						if (b_PCIInputClock ==
-							APCI1710_40MHZ) {
-			  /******************************/
-							/* Test if firmware >= Rev1.5 */
-			  /******************************/
-
-							if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3135) {
-			     /*********************************/
-								/* Test if 40MHz quartz on board */
-			     /*********************************/
-
-								/*INPDW (ps_APCI1710Variable->
-								   s_Board [b_BoardHandle].
-								   s_BoardInfos.
-								   ui_Address + 36 + (64 * b_ModulNbr), &dw_Status); */
-								dw_Status =
-									inl
-									(devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 36 +
-									(64 * b_ModulNbr));
-
-			     /******************************/
-								/* Test the quartz flag (DQ0) */
-			     /******************************/
-
-								if ((dw_Status & 1) != 1) {
-				/*****************************/
-									/* 40MHz quartz not on board */
-				/*****************************/
-
-									DPRINTK("40MHz quartz not on board\n");
-									i_ReturnValue
-										=
-										-7;
-								}
-							} else {
-			     /*****************************/
-								/* 40MHz quartz not on board */
-			     /*****************************/
-								DPRINTK("40MHz quartz not on board\n");
-								i_ReturnValue =
-									-7;
-							}
-						}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
-
-		       /***************************/
-						/* Test if not error occur */
-		       /***************************/
-
-						if (i_ReturnValue == 0) {
-			  /****************************/
-							/* Test the INC_CPT version */
-			  /****************************/
-
-							if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131) {
-
-				/**********************/
-								/* Test if 40MHz used */
-				/**********************/
-
-								if (b_PCIInputClock == APCI1710_40MHZ) {
-				   /*********************************/
-									/* Enable the 40MHz quarz (DQ30) */
-				   /*********************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister4
-										=
-										devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister4
-										|
-										APCI1710_ENABLE_40MHZ_FREQUENCY;
-								}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
-								else {
-				   /**********************************/
-									/* Disable the 40MHz quarz (DQ30) */
-				   /**********************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister4
-										=
-										devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_SiemensCounterInfo.
-										s_ModeRegister.
-										s_ByteModeRegister.
-										b_ModeRegister4
-										&
-										APCI1710_DISABLE_40MHZ_FREQUENCY;
-
-								}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
-
-			     /********************************/
-								/* Calculate the division fator */
-			     /********************************/
-
-								fpu_begin();
-								switch (b_TimingUnity) {
-				/******/
-									/* ns */
-				/******/
-
-								case 0:
-
-					/******************/
-									/* Timer 0 factor */
-					/******************/
-
-									ul_TimerValue
-										=
-										(unsigned int)
-										(ul_TimingInterval
-										*
-										(0.00025 * b_PCIInputClock));
-
-					/*******************/
-									/* Round the value */
-					/*******************/
-
-									if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-										ul_TimerValue
-											=
-											ul_TimerValue
-											+
-											1;
-									}
-
-					/*****************************/
-									/* Calculate the real timing */
-					/*****************************/
-
-									*pul_RealTimingInterval
-										=
-										(unsigned int)
-										(ul_TimerValue
-										/
-										(0.00025 * (double)b_PCIInputClock));
-									d_RealTimingInterval
-										=
-										(double)
-										ul_TimerValue
-										/
-										(0.00025
-										*
-										(double)
-										b_PCIInputClock);
-
-									if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
-										*pul_RealTimingInterval
-											=
-											*pul_RealTimingInterval
-											+
-											1;
-									}
-
-									ul_TimingInterval
-										=
-										ul_TimingInterval
-										-
-										1;
-									ul_TimerValue
-										=
-										ul_TimerValue
-										-
-										2;
-
-									break;
-
-				/******/
-									/* æs */
-				/******/
-
-								case 1:
-
-					/******************/
-									/* Timer 0 factor */
-					/******************/
-
-									ul_TimerValue
-										=
-										(unsigned int)
-										(ul_TimingInterval
-										*
-										(0.25 * b_PCIInputClock));
-
-					/*******************/
-									/* Round the value */
-					/*******************/
-
-									if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-										ul_TimerValue
-											=
-											ul_TimerValue
-											+
-											1;
-									}
-
-					/*****************************/
-									/* Calculate the real timing */
-					/*****************************/
-
-									*pul_RealTimingInterval
-										=
-										(unsigned int)
-										(ul_TimerValue
-										/
-										(0.25 * (double)b_PCIInputClock));
-									d_RealTimingInterval
-										=
-										(double)
-										ul_TimerValue
-										/
-										(
-										(double)
-										0.25
-										*
-										(double)
-										b_PCIInputClock);
-
-									if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
-										*pul_RealTimingInterval
-											=
-											*pul_RealTimingInterval
-											+
-											1;
-									}
-
-									ul_TimingInterval
-										=
-										ul_TimingInterval
-										-
-										1;
-									ul_TimerValue
-										=
-										ul_TimerValue
-										-
-										2;
-
-									break;
-
-				/******/
-									/* ms */
-				/******/
-
-								case 2:
-
-					/******************/
-									/* Timer 0 factor */
-					/******************/
-
-									ul_TimerValue
-										=
-										ul_TimingInterval
-										*
-										(250.0
-										*
-										b_PCIInputClock);
-
-					/*******************/
-									/* Round the value */
-					/*******************/
-
-									if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-										ul_TimerValue
-											=
-											ul_TimerValue
-											+
-											1;
-									}
-
-					/*****************************/
-									/* Calculate the real timing */
-					/*****************************/
-
-									*pul_RealTimingInterval
-										=
-										(unsigned int)
-										(ul_TimerValue
-										/
-										(250.0 * (double)b_PCIInputClock));
-									d_RealTimingInterval
-										=
-										(double)
-										ul_TimerValue
-										/
-										(250.0
-										*
-										(double)
-										b_PCIInputClock);
-
-									if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
-										*pul_RealTimingInterval
-											=
-											*pul_RealTimingInterval
-											+
-											1;
-									}
-
-									ul_TimingInterval
-										=
-										ul_TimingInterval
-										-
-										1;
-									ul_TimerValue
-										=
-										ul_TimerValue
-										-
-										2;
-
-									break;
-								}
-
-								fpu_end();
-			     /*************************/
-								/* Write the timer value */
-			     /*************************/
-
-								outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 32 + (64 * b_ModulNbr));
-
-			     /*******************************/
-								/* Set the initialisation flag */
-			     /*******************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_InitFlag.
-									b_FrequencyMeasurementInit
-									= 1;
-							} else {
-			     /***************************/
-								/* Counter not initialised */
-			     /***************************/
-
-								DPRINTK("Counter not initialised\n");
-								i_ReturnValue =
-									-3;
-							}
-						}	/*  if (i_ReturnValue == 0) */
-					} else {
-		       /**********************************/
-						/* Base timing selection is wrong */
-		       /**********************************/
-
-						DPRINTK("Base timing selection is wrong\n");
-						i_ReturnValue = -6;
-					}
-				} else {
-		    /***********************************/
-					/* Timing unity selection is wrong */
-		    /***********************************/
-
-					DPRINTK("Timing unity selection is wrong\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /*****************************************/
-				/* The selected PCI input clock is wrong */
-		 /*****************************************/
-
-				DPRINTK("The selected PCI input clock is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
- * Configuration function for INC_CPT
- */
-static int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,
-				       struct comedi_subdevice *s,
-				       struct comedi_insn *insn,
-				       unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned int ui_ConfigType;
-	int i_ReturnValue = 0;
-
-	ui_ConfigType = CR_CHAN(insn->chanspec);
-
-	printk("\nINC_CPT");
-
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-	switch (ui_ConfigType) {
-	case APCI1710_INCCPT_INITCOUNTER:
-		i_ReturnValue = i_APCI1710_InitCounter(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1],
-			(unsigned char) data[2], (unsigned char) data[3], (unsigned char) data[4]);
-		break;
-
-	case APCI1710_INCCPT_COUNTERAUTOTEST:
-		i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
-			(unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_INITINDEX:
-		i_ReturnValue = i_APCI1710_InitIndex(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1], (unsigned char) data[2], (unsigned char) data[3]);
-		break;
-
-	case APCI1710_INCCPT_INITREFERENCE:
-		i_ReturnValue = i_APCI1710_InitReference(dev,
-			CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_INCCPT_INITEXTERNALSTROBE:
-		i_ReturnValue = i_APCI1710_InitExternalStrobe(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0], (unsigned char) data[1]);
-		break;
-
-	case APCI1710_INCCPT_INITCOMPARELOGIC:
-		i_ReturnValue = i_APCI1710_InitCompareLogic(dev,
-			CR_AREF(insn->chanspec), (unsigned int) data[0]);
-		break;
-
-	case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1], (unsigned int) data[2], (unsigned int *) &data[0]);
-		break;
-
-	default:
-		printk("Insn Config : Config Parameter Wrong\n");
-
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ClearCounterValue                     |
-|                               (unsigned char_      b_BoardHandle,                   |
-|                                unsigned char_       b_ModulNbr)                     |
-+----------------------------------------------------------------------------+
-| Task              : Clear the counter value from selected module           |
-|                     (b_ModulNbr).                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Module number to configure       |
-|                                           (0 to 3)                         |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number parameter is wrong      |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ClearCounterValue(struct comedi_device *dev,
-					unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*********************/
-			/* Clear the counter */
-	      /*********************/
-
-			outl(1, devpriv->s_BoardInfos.
-				ui_Address + 16 + (64 * b_ModulNbr));
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ClearAllCounterValue                  |
-|                               (unsigned char_      b_BoardHandle)                   |
-+----------------------------------------------------------------------------+
-| Task              : Clear all counter value.                               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned char b_ModulCpt = 0;
-	int i_ReturnValue = 0;
-
-	/********************************/
-	/* Test if counter module found */
-	/********************************/
-
-	if ((devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[0] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER
-		|| (devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[1] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER
-		|| (devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[2] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER
-		|| (devpriv->s_BoardInfos.
-			dw_MolduleConfiguration[3] & 0xFFFF0000UL) ==
-		APCI1710_INCREMENTAL_COUNTER) {
-		for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) {
-	      /*******************************/
-			/* Test if incremental counter */
-	      /*******************************/
-
-			if ((devpriv->s_BoardInfos.
-					dw_MolduleConfiguration[b_ModulCpt] &
-					0xFFFF0000UL) ==
-				APCI1710_INCREMENTAL_COUNTER) {
-		 /*********************/
-				/* Clear the counter */
-		 /*********************/
-
-				outl(1, devpriv->s_BoardInfos.
-					ui_Address + 16 + (64 * b_ModulCpt));
-			}
-		}
-	} else {
-	   /***************************/
-		/* No counter module found */
-	   /***************************/
-
-		DPRINTK("No counter module found\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_SetInputFilter                        |
-|					(unsigned char_ b_BoardHandle,                |
-|					 unsigned char_ b_Module,                     |
-|					 unsigned char_ b_PCIInputClock,              |
-|					 unsigned char_ b_Filter)     		     |
-+----------------------------------------------------------------------------+
-| Task              : Disable or enable the software filter from selected    |
-|		      module (b_ModulNbr). b_Filter determine the filter time|
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
-|						configured (0 to 3)          |
-|		      unsigned char_  b_PCIInputClock  :	Selection of the PCI bus     |
-|						clock                        |
-|						- APCI1710_30MHZ :           |
-|						  The PC has a PCI bus clock |
-|						  of 30 MHz                  |
-|						- APCI1710_33MHZ :           |
-|						  The PC has a PCI bus clock |
-|						  of 33 MHz                  |
-|						- APCI1710_40MHZ :           |
-|						  The APCI1710 has a 40MHz    |
-|						  quartz		     |
-|		      unsigned char_  b_Filter	      : Filter selection             |
-|                                                                            |
-|				30 MHz                                       |
-|				------                                       |
-|					0:  Software filter not used         |
-|					1:  Filter from 266ns  (3.750000MHz) |
-|					2:  Filter from 400ns  (2.500000MHz) |
-|					3:  Filter from 533ns  (1.876170MHz) |
-|					4:  Filter from 666ns  (1.501501MHz) |
-|					5:  Filter from 800ns  (1.250000MHz) |
-|					6:  Filter from 933ns  (1.071800MHz) |
-|					7:  Filter from 1066ns (0.938080MHz) |
-|					8:  Filter from 1200ns (0.833333MHz) |
-|					9:  Filter from 1333ns (0.750000MHz) |
-|					10: Filter from 1466ns (0.682100MHz) |
-|					11: Filter from 1600ns (0.625000MHz) |
-|					12: Filter from 1733ns (0.577777MHz) |
-|					13: Filter from 1866ns (0.535900MHz) |
-|					14: Filter from 2000ns (0.500000MHz) |
-|					15: Filter from 2133ns (0.468800MHz) |
-|									     |
-|				33 MHz                                       |
-|				------                                       |
-|					0:  Software filter not used         |
-|					1:  Filter from 242ns  (4.125000MHz) |
-|					2:  Filter from 363ns  (2.754820MHz) |
-|					3:  Filter from 484ns  (2.066115MHz) |
-|					4:  Filter from 605ns  (1.652892MHz) |
-|					5:  Filter from 726ns  (1.357741MHz) |
-|					6:  Filter from 847ns  (1.180637MHz) |
-|					7:  Filter from 968ns  (1.033055MHz) |
-|					8:  Filter from 1089ns (0.918273MHz) |
-|					9:  Filter from 1210ns (0.826446MHz) |
-|					10: Filter from 1331ns (0.751314MHz) |
-|					11: Filter from 1452ns (0.688705MHz) |
-|					12: Filter from 1573ns (0.635727MHz) |
-|					13: Filter from 1694ns (0.590318MHz) |
-|					14: Filter from 1815ns (0.550964MHz) |
-|					15: Filter from 1936ns (0.516528MHz) |
-|									     |
-|				40 MHz                                       |
-|				------                                       |
-|					0:  Software filter not used         |
-|					1:  Filter from 200ns  (5.000000MHz) |
-|					2:  Filter from 300ns  (3.333333MHz) |
-|					3:  Filter from 400ns  (2.500000MHz) |
-|					4:  Filter from 500ns  (2.000000MHz) |
-|					5:  Filter from 600ns  (1.666666MHz) |
-|					6:  Filter from 700ns  (1.428500MHz) |
-|					7:  Filter from 800ns  (1.250000MHz) |
-|					8:  Filter from 900ns  (1.111111MHz) |
-|					9:  Filter from 1000ns (1.000000MHz) |
-|					10: Filter from 1100ns (0.909090MHz) |
-|					11: Filter from 1200ns (0.833333MHz) |
-|					12: Filter from 1300ns (0.769200MHz) |
-|					13: Filter from 1400ns (0.714200MHz) |
-|					14: Filter from 1500ns (0.666666MHz) |
-|					15: Filter from 1600ns (0.625000MHz) |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number is wrong                |
-|                     -3: The module is not a counter module                 |
-|					  -4: The selected PCI input clock is wrong              |
-|					  -5: The selected filter value is wrong                 |
-|					  -6: 40MHz quartz not on board                          |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_SetInputFilter(struct comedi_device *dev,
-				     unsigned char b_ModulNbr,
-				     unsigned char b_PCIInputClock,
-				     unsigned char b_Filter)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if incremental counter */
-	   /*******************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
-	      /******************************/
-			/* Test if firmware >= Rev1.5 */
-	      /******************************/
-
-			if ((devpriv->s_BoardInfos.
-					dw_MolduleConfiguration[b_ModulNbr] &
-					0xFFFF) >= 0x3135) {
-		 /**************************/
-				/* Test the PCI bus clock */
-		 /**************************/
-
-				if ((b_PCIInputClock == APCI1710_30MHZ) ||
-					(b_PCIInputClock == APCI1710_33MHZ) ||
-					(b_PCIInputClock == APCI1710_40MHZ)) {
-		    /*************************/
-					/* Test the filter value */
-		    /*************************/
-
-					if (b_Filter < 16) {
-		       /**********************/
-						/* Test if 40MHz used */
-		       /**********************/
-
-						if (b_PCIInputClock ==
-							APCI1710_40MHZ) {
-			  /*********************************/
-							/* Test if 40MHz quartz on board */
-			  /*********************************/
-
-							dw_Status =
-								inl(devpriv->
-								s_BoardInfos.
-								ui_Address +
-								36 +
-								(64 * b_ModulNbr));
-
-			  /******************************/
-							/* Test the quartz flag (DQ0) */
-			  /******************************/
-
-							if ((dw_Status & 1) !=
-								1) {
-			     /*****************************/
-								/* 40MHz quartz not on board */
-			     /*****************************/
-
-								DPRINTK("40MHz quartz not on board\n");
-								i_ReturnValue =
-									-6;
-							}
-						}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
-
-		       /***************************/
-						/* Test if error not occur */
-		       /***************************/
-
-						if (i_ReturnValue == 0) {
-			  /**********************/
-							/* Test if 40MHz used */
-			  /**********************/
-
-							if (b_PCIInputClock ==
-								APCI1710_40MHZ)
-							{
-			     /*********************************/
-								/* Enable the 40MHz quarz (DQ31) */
-			     /*********************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									|
-									APCI1710_ENABLE_40MHZ_FILTER;
-
-							}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
-							else {
-			     /**********************************/
-								/* Disable the 40MHz quarz (DQ31) */
-			     /**********************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_SiemensCounterInfo.
-									s_ModeRegister.
-									s_ByteModeRegister.
-									b_ModeRegister4
-									&
-									APCI1710_DISABLE_40MHZ_FILTER;
-
-							}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
-
-			  /************************/
-							/* Set the filter value */
-			  /************************/
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_SiemensCounterInfo.
-								s_ModeRegister.
-								s_ByteModeRegister.
-								b_ModeRegister3
-								=
-								(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_SiemensCounterInfo.
-								s_ModeRegister.
-								s_ByteModeRegister.
-								b_ModeRegister3
-								& 0x1F) |
-								((b_Filter &
-									0x7) <<
-								5);
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_SiemensCounterInfo.
-								s_ModeRegister.
-								s_ByteModeRegister.
-								b_ModeRegister4
-								=
-								(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_SiemensCounterInfo.
-								s_ModeRegister.
-								s_ByteModeRegister.
-								b_ModeRegister4
-								& 0xFE) |
-								((b_Filter &
-									0x8) >>
-								3);
-
-			  /***************************/
-							/* Write the configuration */
-			  /***************************/
-
-							outl(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_SiemensCounterInfo.
-								s_ModeRegister.
-								dw_ModeRegister1_2_3_4,
-								devpriv->
-								s_BoardInfos.
-								ui_Address +
-								20 +
-								(64 * b_ModulNbr));
-						}	/*  if (i_ReturnValue == 0) */
-					}	/*  if (b_Filter < 16) */
-					else {
-		       /**************************************/
-						/* The selected filter value is wrong */
-		       /**************************************/
-
-						DPRINTK("The selected filter value is wrong\n");
-						i_ReturnValue = -5;
-					}	/*  if (b_Filter < 16) */
-				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) */
-				else {
-		    /*****************************************/
-					/* The selected PCI input clock is wrong */
-		    /*****************************************/
-
-					DPRINTK("The selected PCI input clock is wrong\n");
-					i_ReturnValue = 4;
-				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) */
-			} else {
-		 /**************************************/
-				/* The module is not a counter module */
-		 /**************************************/
-
-				DPRINTK("The module is not a counter module\n");
-				i_ReturnValue = -3;
-			}
-		} else {
-	      /**************************************/
-			/* The module is not a counter module */
-	      /**************************************/
-
-			DPRINTK("The module is not a counter module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_LatchCounter (unsigned char_ b_BoardHandle,    |
-|                                                    unsigned char_ b_ModulNbr,       |
-|                                                    unsigned char_ b_LatchReg)       |
-+----------------------------------------------------------------------------+
-| Task              : Latch the courant value from selected module           |
-|                     (b_ModulNbr) in to the selected latch register         |
-|                     (b_LatchReg).                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Module number to configure       |
-|                                           (0 to 3)                         |
-|                     unsigned char_ b_LatchReg    : Selected latch register          |
-|                               0 : for the first latch register             |
-|                               1 : for the second latch register            |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: The selected latch register parameter is wrong     |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_LatchCounter(struct comedi_device *dev,
-				   unsigned char b_ModulNbr,
-				   unsigned char b_LatchReg)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*************************************/
-			/* Test the latch register parameter */
-	      /*************************************/
-
-			if (b_LatchReg < 2) {
-		 /*********************/
-				/* Tatch the counter */
-		 /*********************/
-
-				outl(1 << (b_LatchReg * 4),
-					devpriv->s_BoardInfos.ui_Address +
-					(64 * b_ModulNbr));
-			} else {
-		 /**************************************************/
-				/* The selected latch register parameter is wrong */
-		 /**************************************************/
-
-				DPRINTK("The selected latch register parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_	i_APCI1710_SetIndexAndReferenceSource        |
-|					(unsigned char_ b_BoardHandle,                |
-|					 unsigned char_ b_ModulNbr,                   |
-|					 unsigned char_ b_SourceSelection)            |
-+----------------------------------------------------------------------------+
-| Task              : Determine the hardware source for the index and the    |
-|		      reference logic. Per default the index logic is        |
-|		      connected to the difference input C and the reference  |
-|		      logic is connected to the 24V input E                  |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-|		      unsigned char_ b_SourceSelection : APCI1710_SOURCE_0 :          |
-|						The index logic is connected |
-|						to the difference input C and|
-|						the reference logic is       |
-|						connected to the 24V input E.|
-|						This is the default          |
-|						configuration.               |
-|						APCI1710_SOURCE_1 :          |
-|						The reference logic is       |
-|						connected to the difference  |
-|						input C and the index logic  |
-|						is connected to the 24V      |
-|						input E                      |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|		      -2: The selected module number is wrong                |
-|		      -3: The module is not a counter module.                |
-|		      -4: The source selection is wrong                      |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
-						 unsigned char b_ModulNbr,
-						 unsigned char b_SourceSelection)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if incremental counter */
-	   /*******************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
-	      /******************************/
-			/* Test if firmware >= Rev1.5 */
-	      /******************************/
-
-			if ((devpriv->s_BoardInfos.
-					dw_MolduleConfiguration[b_ModulNbr] &
-					0xFFFF) >= 0x3135) {
-		 /*****************************/
-				/* Test the source selection */
-		 /*****************************/
-
-				if (b_SourceSelection == APCI1710_SOURCE_0 ||
-					b_SourceSelection == APCI1710_SOURCE_1)
-				{
-		    /******************************************/
-					/* Test if invert the index and reference */
-		    /******************************************/
-
-					if (b_SourceSelection ==
-						APCI1710_SOURCE_1) {
-		       /********************************************/
-						/* Invert index and reference source (DQ25) */
-		       /********************************************/
-
-						devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SiemensCounterInfo.
-							s_ModeRegister.
-							s_ByteModeRegister.
-							b_ModeRegister4 =
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SiemensCounterInfo.
-							s_ModeRegister.
-							s_ByteModeRegister.
-							b_ModeRegister4 |
-							APCI1710_INVERT_INDEX_RFERENCE;
-					} else {
-		       /****************************************/
-						/* Set the default configuration (DQ25) */
-		       /****************************************/
-
-						devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SiemensCounterInfo.
-							s_ModeRegister.
-							s_ByteModeRegister.
-							b_ModeRegister4 =
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SiemensCounterInfo.
-							s_ModeRegister.
-							s_ByteModeRegister.
-							b_ModeRegister4 &
-							APCI1710_DEFAULT_INDEX_RFERENCE;
-					}
-				}	/*  if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) */
-				else {
-		    /*********************************/
-					/* The source selection is wrong */
-		    /*********************************/
-
-					DPRINTK("The source selection is wrong\n");
-					i_ReturnValue = -4;
-				}	/*  if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) */
-			} else {
-		 /**************************************/
-				/* The module is not a counter module */
-		 /**************************************/
-
-				DPRINTK("The module is not a counter module\n");
-				i_ReturnValue = -3;
-			}
-		} else {
-	      /**************************************/
-			/* The module is not a counter module */
-	      /**************************************/
-
-			DPRINTK("The module is not a counter module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***************************************/
-		/* The selected module number is wrong */
-	   /***************************************/
-
-		DPRINTK("The selected module number is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_	i_APCI1710_SetDigitalChlOn                   |
-|				   (unsigned char_  b_BoardHandle,                    |
-|				    unsigned char_  b_ModulNbr)                       |
-+----------------------------------------------------------------------------+
-| Task              : Sets the digital output H Setting an output means      |
-|		      setting an ouput high.                                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
-|						configured (0 to 3)          |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number is wrong                |
-|                     -3: Counter not initialised see function               |
-|			  "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev,
-				      unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-			devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.
-				b_ModeRegister3 = devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.b_ModeRegister3 | 0x10;
-
-	      /*********************/
-			/* Set the output On */
-	      /*********************/
-
-			outl(devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
-				ui_Address + 20 + (64 * b_ModulNbr));
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_	i_APCI1710_SetDigitalChlOff                  |
-|				   (unsigned char_  b_BoardHandle,                    |
-|				    unsigned char_  b_ModulNbr)                       |
-+----------------------------------------------------------------------------+
-| Task              : Resets the digital output H. Resetting an output means |
-|		      setting an ouput low.                                  |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
-|						configured (0 to 3)          |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: The selected module number is wrong                |
-|                     -3: Counter not initialised see function               |
-|			  "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev,
-				       unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-			devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.
-				b_ModeRegister3 = devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.b_ModeRegister3 & 0xEF;
-
-	      /**********************/
-			/* Set the output Off */
-	      /**********************/
-
-			outl(devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
-				ui_Address + 20 + (64 * b_ModulNbr));
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
- * Set & Clear Functions for INC_CPT
- */
-static int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,
-				     struct comedi_subdevice *s,
-				     struct comedi_insn *insn,
-				     unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned int ui_BitsType;
-	int i_ReturnValue = 0;
-
-	ui_BitsType = CR_CHAN(insn->chanspec);
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-
-	switch (ui_BitsType) {
-	case APCI1710_INCCPT_CLEARCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_ClearCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev);
-		break;
-
-	case APCI1710_INCCPT_SETINPUTFILTER:
-		i_ReturnValue = i_APCI1710_SetInputFilter(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0], (unsigned char) data[1]);
-		break;
-
-	case APCI1710_INCCPT_LATCHCOUNTER:
-		i_ReturnValue = i_APCI1710_LatchCounter(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:
-		i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_INCCPT_SETDIGITALCHLON:
-		i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_SETDIGITALCHLOFF:
-		i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	default:
-		printk("Bits Config Parameter Wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_EnableLatchInterrupt                  |
-|                               (unsigned char_ b_BoardHandle,                        |
-|                                unsigned char_ b_ModulNbr)                           |
-+----------------------------------------------------------------------------+
-| Task              : Enable the latch interrupt from selected module        |
-|                     (b_ModulNbr). Each software or hardware latch occur a  |
-|                     interrupt.                                             |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Module number to configure       |
-|                                           (0 to 3)                         |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Interrupt routine not installed see function       |
-|                         "i_APCI1710_SetBoardIntRoutine"                    |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev,
-					   unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-
-		 /********************/
-			/* Enable interrupt */
-		 /********************/
-
-			devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.
-				b_ModeRegister2 = devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.
-				b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT;
-
-		 /***************************/
-			/* Write the configuration */
-		 /***************************/
-
-			outl(devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
-				ui_Address + 20 + (64 * b_ModulNbr));
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_DisableLatchInterrupt                 |
-|                               (unsigned char_ b_BoardHandle,                        |
-|                                unsigned char_ b_ModulNbr)                           |
-+----------------------------------------------------------------------------+
-| Task              : Disable the latch interrupt from selected module       |
-|                     (b_ModulNbr).                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Module number to configure       |
-|                                           (0 to 3)                         |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Interrupt routine not installed see function       |
-|                         "i_APCI1710_SetBoardIntRoutine"                    |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev,
-					    unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-
-		 /***************************/
-			/* Write the configuration */
-		 /***************************/
-
-			outl(devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				dw_ModeRegister1_2_3_4 &
-				((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF),
-				devpriv->s_BoardInfos.ui_Address + 20 +
-				(64 * b_ModulNbr));
-
-			mdelay(1000);
-
-		 /*********************/
-			/* Disable interrupt */
-		 /*********************/
-
-			devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.
-				b_ModeRegister2 = devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_ModeRegister.
-				s_ByteModeRegister.
-				b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT;
-
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_Write16BitCounterValue                |
-|                                               (unsigned char_  b_BoardHandle        |
-|                                                unsigned char_  b_ModulNbr,          |
-|                                                unsigned char_  b_SelectedCounter,   |
-|                                                unsigned int_ ui_WriteValue)        |
-+----------------------------------------------------------------------------+
-| Task              : Write a 16-Bit value (ui_WriteValue) in to the selected|
-|                     16-Bit counter (b_SelectedCounter) from selected module|
-|                     (b_ModulNbr).                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                              (0 to 3)                      |
-|                     unsigned char_ b_SelectedCounter : Selected 16-Bit counter      |
-|                                               (0 or 1)                     |
-|                     unsigned int_ ui_WriteValue     : 16-Bit write value           |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: The selected 16-Bit counter parameter is wrong     |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
-					     unsigned char b_ModulNbr,
-					     unsigned char b_SelectedCounter,
-					     unsigned int ui_WriteValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /******************************/
-			/* Test the counter selection */
-	      /******************************/
-
-			if (b_SelectedCounter < 2) {
-		 /*******************/
-				/* Write the value */
-		 /*******************/
-
-				outl((unsigned int) ((unsigned int) (ui_WriteValue) << (16 *
-							b_SelectedCounter)),
-					devpriv->s_BoardInfos.ui_Address + 8 +
-					(b_SelectedCounter * 4) +
-					(64 * b_ModulNbr));
-			} else {
-		 /**************************************************/
-				/* The selected 16-Bit counter parameter is wrong */
-		 /**************************************************/
-
-				DPRINTK("The selected 16-Bit counter parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_Write32BitCounterValue                |
-|                                               (unsigned char_   b_BoardHandle       |
-|                                                unsigned char_   b_ModulNbr,         |
-|                                                ULONG_ ul_WriteValue)       |
-+----------------------------------------------------------------------------+
-| Task              : Write a 32-Bit value (ui_WriteValue) in to the selected|
-|                     module (b_ModulNbr).                                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                              (0 to 3)                      |
-|                     ULONG_ ul_WriteValue    : 32-Bit write value           |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
-					     unsigned char b_ModulNbr,
-					     unsigned int ul_WriteValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*******************/
-			/* Write the value */
-	      /*******************/
-
-			outl(ul_WriteValue, devpriv->s_BoardInfos.
-				ui_Address + 4 + (64 * b_ModulNbr));
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_EnableIndex (unsigned char_  b_BoardHandle,    |
-|                                                   unsigned char_  b_ModulNbr)       |
-+----------------------------------------------------------------------------+
-| Task              : Enable the INDEX actions                               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Index not initialised see function                 |
-|                         "i_APCI1710_InitIndex"                             |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_EnableIndex(struct comedi_device *dev,
-				  unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ul_InterruptLatchReg;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*****************************/
-			/* Test if index initialised */
-	      /*****************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister2 = devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister2 | APCI1710_ENABLE_INDEX;
-
-				ul_InterruptLatchReg =
-					inl(devpriv->s_BoardInfos.ui_Address +
-					24 + (64 * b_ModulNbr));
-
-				outl(devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					dw_ModeRegister1_2_3_4,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-			} else {
-		 /*************************************************************/
-				/* Index not initialised see function "i_APCI1710_InitIndex" */
-		 /*************************************************************/
-
-				DPRINTK("Index not initialised \n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_DisableIndex (unsigned char_  b_BoardHandle,   |
-|                                                    unsigned char_  b_ModulNbr)      |
-+----------------------------------------------------------------------------+
-| Task              : Disable the INDEX actions                              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Index not initialised see function                 |
-|                         "i_APCI1710_InitIndex"                             |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_DisableIndex(struct comedi_device *dev,
-				   unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*****************************/
-			/* Test if index initialised */
-	      /*****************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister2 = devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister2 &
-					APCI1710_DISABLE_INDEX;
-
-				outl(devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					dw_ModeRegister1_2_3_4,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-			} else {
-		 /*************************************************************/
-				/* Index not initialised see function "i_APCI1710_InitIndex" */
-		 /*************************************************************/
-
-				DPRINTK("Index not initialised  \n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_EnableCompareLogic                    |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr)                         |
-+----------------------------------------------------------------------------+
-| Task              : Enable the 32-Bit compare logic. At that moment that   |
-|                     the incremental counter arrive to the compare value a  |
-|                     interrupt is generated.                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-|                     unsigned char_  b_ModulNbr       : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : -
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Compare logic not initialised.                     |
-|                         See function "i_APCI1710_InitCompareLogic"         |
-|                     -5: Interrupt function not initialised.                |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_EnableCompareLogic(struct comedi_device *dev,
-					 unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*************************************/
-			/* Test if compare logic initialised */
-	      /*************************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_CompareLogicInit == 1) {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister3 = devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister3 |
-					APCI1710_ENABLE_COMPARE_INT;
-
-		    /***************************/
-				/* Write the configuration */
-		    /***************************/
-
-				outl(devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					dw_ModeRegister1_2_3_4,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-			} else {
-		 /*********************************/
-				/* Compare logic not initialised */
-		 /*********************************/
-
-				DPRINTK("Compare logic not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_DisableCompareLogic                   |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr)                         |
-+----------------------------------------------------------------------------+
-| Task              : Disable the 32-Bit compare logic.
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-|                     unsigned char_  b_ModulNbr       : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : -
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Compare logic not initialised.                     |
-|                         See function "i_APCI1710_InitCompareLogic"         |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_DisableCompareLogic(struct comedi_device *dev,
-					  unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*************************************/
-			/* Test if compare logic initialised */
-	      /*************************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_CompareLogicInit == 1) {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister3 = devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister3 &
-					APCI1710_DISABLE_COMPARE_INT;
-
-		 /***************************/
-				/* Write the configuration */
-		 /***************************/
-
-				outl(devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					dw_ModeRegister1_2_3_4,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-			} else {
-		 /*********************************/
-				/* Compare logic not initialised */
-		 /*********************************/
-
-				DPRINTK("Compare logic not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-	/*
-	   +----------------------------------------------------------------------------+
-	   | Function Name     : _INT_ i_APCI1710_EnableFrequencyMeasurement            |
-	   |                            (unsigned char_   b_BoardHandle,                      |
-	   |                             unsigned char_   b_ModulNbr,                         |
-	   |                             unsigned char_   b_InterruptEnable)                  |
-	   +----------------------------------------------------------------------------+
-	   | Task              : Enables the frequency measurement function             |
-	   +----------------------------------------------------------------------------+
-	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-	   |                  unsigned char_  b_ModulNbr       : Number of the module to be   |
-	   |                                            configured (0 to 3)          |
-	   |                  unsigned char_  b_InterruptEnable: Enable or disable the        |
-	   |                                            interrupt.                   |
-	   |                                            APCI1710_ENABLE:             |
-	   |                                            Enable the interrupt         |
-	   |                                            APCI1710_DISABLE:            |
-	   |                                            Disable the interrupt        |
-	   +----------------------------------------------------------------------------+
-	   | Output Parameters : -                                                      |
-	   +----------------------------------------------------------------------------+
-	   | Return Value      :  0: No error                                           |
-	   |                     -1: The handle parameter of the board is wrong         |
-	   |                     -2: The selected module number is wrong                |
-	   |                     -3: Counter not initialised see function               |
-	   |                      "i_APCI1710_InitCounter"                           |
-	   |                     -4: Frequency measurement logic not initialised.       |
-	   |                      See function "i_APCI1710_InitFrequencyMeasurement" |
-	   |                     -5: Interrupt parameter is wrong                       |
-	   |                     -6: Interrupt function not initialised.                |
-	   +----------------------------------------------------------------------------+
-	 */
-static int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
-						 unsigned char b_ModulNbr,
-						 unsigned char b_InterruptEnable)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /********************************************/
-			/* Test if frequency measurement initialised */
-	      /********************************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_FrequencyMeasurementInit == 1) {
-		 /***************************/
-				/* Test the interrupt mode */
-		 /***************************/
-
-				if ((b_InterruptEnable == APCI1710_DISABLE) ||
-					(b_InterruptEnable == APCI1710_ENABLE))
-				{
-
-		       /************************************/
-					/* Enable the frequency measurement */
-		       /************************************/
-
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister3 = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister3 |
-						APCI1710_ENABLE_FREQUENCY;
-
-		       /*********************************************/
-					/* Disable or enable the frequency interrupt */
-		       /*********************************************/
-
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister3 = (devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister3 &
-						APCI1710_DISABLE_FREQUENCY_INT)
-						| (b_InterruptEnable << 3);
-
-		       /***************************/
-					/* Write the configuration */
-		       /***************************/
-
-					outl(devpriv->s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						dw_ModeRegister1_2_3_4,
-						devpriv->s_BoardInfos.
-						ui_Address + 20 +
-						(64 * b_ModulNbr));
-
-					devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SiemensCounterInfo.
-						s_InitFlag.
-						b_FrequencyMeasurementEnable =
-						1;
-				} else {
-		    /********************************/
-					/* Interrupt parameter is wrong */
-		    /********************************/
-
-					DPRINTK("Interrupt parameter is wrong\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /***********************************************/
-				/* Frequency measurement logic not initialised */
-		 /***********************************************/
-
-				DPRINTK("Frequency measurement logic not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-	/*
-	   +----------------------------------------------------------------------------+
-	   | Function Name     : _INT_ i_APCI1710_DisableFrequencyMeasurement           |
-	   |                            (unsigned char_   b_BoardHandle,                      |
-	   |                             unsigned char_   b_ModulNbr)                         |
-	   +----------------------------------------------------------------------------+
-	   | Task              : Disables the frequency measurement function             |
-	   +----------------------------------------------------------------------------+
-	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-	   |                  unsigned char_  b_ModulNbr       : Number of the module to be   |
-	   |                                            configured (0 to 3)          |
-	   +----------------------------------------------------------------------------+
-	   | Output Parameters : -                                                      |
-	   +----------------------------------------------------------------------------+
-	   | Return Value      :  0: No error                                           |
-	   |                     -1: The handle parameter of the board is wrong         |
-	   |                     -2: The selected module number is wrong                |
-	   |                     -3: Counter not initialised see function               |
-	   |                      "i_APCI1710_InitCounter"                           |
-	   |                     -4: Frequency measurement logic not initialised.       |
-	   |                      See function "i_APCI1710_InitFrequencyMeasurement" |
-	   +----------------------------------------------------------------------------+
-	 */
-static int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
-						  unsigned char b_ModulNbr)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /********************************************/
-			/* Test if frequency measurement initialised */
-	      /********************************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_FrequencyMeasurementInit == 1) {
-		 /*************************************/
-				/* Disable the frequency measurement */
-		 /*************************************/
-
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister3 = devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister3 &
-					APCI1710_DISABLE_FREQUENCY
-					/*  Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared */
-					& APCI1710_DISABLE_FREQUENCY_INT;
-				/*  End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared */
-
-		 /***************************/
-				/* Write the configuration */
-		 /***************************/
-
-				outl(devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					dw_ModeRegister1_2_3_4,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-
-		 /*************************************/
-				/* Disable the frequency measurement */
-		 /*************************************/
-
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_InitFlag.
-					b_FrequencyMeasurementEnable = 0;
-			} else {
-		 /***********************************************/
-				/* Frequency measurement logic not initialised */
-		 /***********************************************/
-
-				DPRINTK("Frequency measurement logic not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
- * Enable Disable functions for INC_CPT
- */
-static int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned int ui_WriteType;
-	int i_ReturnValue = 0;
-
-	ui_WriteType = CR_CHAN(insn->chanspec);
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-
-	switch (ui_WriteType) {
-	case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
-		i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_DISABLELATCHINTERRUPT:
-		i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0], (unsigned int) data[1]);
-		break;
-
-	case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned int) data[0]);
-
-		break;
-
-	case APCI1710_INCCPT_ENABLEINDEX:
-		i_APCI1710_EnableIndex(dev, (unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_DISABLEINDEX:
-		i_ReturnValue = i_APCI1710_DisableIndex(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_ENABLECOMPARELOGIC:
-		i_ReturnValue = i_APCI1710_EnableCompareLogic(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_DISABLECOMPARELOGIC:
-		i_ReturnValue = i_APCI1710_DisableCompareLogic(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
-		break;
-
-	default:
-		printk("Write Config Parameter Wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadLatchRegisterStatus               |
-|                                                   (unsigned char_   b_BoardHandle,  |
-|                                                    unsigned char_   b_ModulNbr,     |
-|                                                    unsigned char_   b_LatchReg,     |
-|                                                    unsigned char *_ pb_LatchStatus)  |
-+----------------------------------------------------------------------------+
-| Task              : Read the latch register status from selected module    |
-|                     (b_ModulNbr) and selected latch register (b_LatchReg). |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Module number to configure       |
-|                                           (0 to 3)                         |
-|                     unsigned char_ b_LatchReg    : Selected latch register          |
-|                               0 : for the first latch register             |
-|                               1 : for the second latch register            |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_LatchStatus :   Latch register status.       |
-|                                               0 : No latch occur           |
-|                                               1 : A software latch occur   |
-|                                               2 : A hardware latch occur   |
-|                                               3 : A software and hardware  |
-|                                                   latch occur              |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: The selected latch register parameter is wrong     |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
-					      unsigned char b_ModulNbr,
-					      unsigned char b_LatchReg,
-					      unsigned char *pb_LatchStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_LatchReg;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*************************************/
-			/* Test the latch register parameter */
-	      /*************************************/
-
-			if (b_LatchReg < 2) {
-				dw_LatchReg = inl(devpriv->s_BoardInfos.
-					ui_Address + (64 * b_ModulNbr));
-
-				*pb_LatchStatus =
-					(unsigned char) ((dw_LatchReg >> (b_LatchReg *
-							4)) & 0x3);
-			} else {
-		 /**************************************************/
-				/* The selected latch register parameter is wrong */
-		 /**************************************************/
-
-				DPRINTK("The selected latch register parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadLatchRegisterValue                |
-|                                                   (unsigned char_     b_BoardHandle,|
-|                                                    unsigned char_     b_ModulNbr,   |
-|                                                    unsigned char_     b_LatchReg,   |
-|                                                    PULONG_ pul_LatchValue) |
-+----------------------------------------------------------------------------+
-| Task              : Read the latch register value from selected module     |
-|                     (b_ModulNbr) and selected latch register (b_LatchReg). |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Module number to configure       |
-|                                           (0 to 3)                         |
-|                     unsigned char_ b_LatchReg    : Selected latch register          |
-|                               0 : for the first latch register             |
-|                               1 : for the second latch register            |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_ pul_LatchValue : Latch register value          |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: The selected latch register parameter is wrong     |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
-					     unsigned char b_ModulNbr,
-					     unsigned char b_LatchReg,
-					     unsigned int *pul_LatchValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*************************************/
-			/* Test the latch register parameter */
-	      /*************************************/
-
-			if (b_LatchReg < 2) {
-				*pul_LatchValue = inl(devpriv->s_BoardInfos.
-					ui_Address + ((b_LatchReg + 1) * 4) +
-					(64 * b_ModulNbr));
-
-			} else {
-		 /**************************************************/
-				/* The selected latch register parameter is wrong */
-		 /**************************************************/
-
-				DPRINTK("The selected latch register parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_Read16BitCounterValue                 |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_SelectedCounter,        |
-|                                        unsigned int *_   pui_CounterValue)          |
-+----------------------------------------------------------------------------+
-| Task              : Latch the selected 16-Bit counter (b_SelectedCounter)  |
-|                     from selected module (b_ModulNbr) in to the first      |
-|                     latch register and return the latched value.           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                              (0 to 3)                      |
-|                     unsigned char_ b_SelectedCounter : Selected 16-Bit counter      |
-|                                               (0 or 1)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned int *_ pui_CounterValue : 16-Bit counter value         |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: The selected 16-Bit counter parameter is wrong     |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
-					    unsigned char b_ModulNbr,
-					    unsigned char b_SelectedCounter,
-					    unsigned int *pui_CounterValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_LathchValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /******************************/
-			/* Test the counter selection */
-	      /******************************/
-
-			if (b_SelectedCounter < 2) {
-		 /*********************/
-				/* Latch the counter */
-		 /*********************/
-
-				outl(1, devpriv->s_BoardInfos.
-					ui_Address + (64 * b_ModulNbr));
-
-		 /************************/
-				/* Read the latch value */
-		 /************************/
-
-				dw_LathchValue = inl(devpriv->s_BoardInfos.
-					ui_Address + 4 + (64 * b_ModulNbr));
-
-				*pui_CounterValue =
-					(unsigned int) ((dw_LathchValue >> (16 *
-							b_SelectedCounter)) &
-					0xFFFFU);
-			} else {
-		 /**************************************************/
-				/* The selected 16-Bit counter parameter is wrong */
-		 /**************************************************/
-
-				DPRINTK("The selected 16-Bit counter parameter is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_Read32BitCounterValue                 |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        PULONG_ pul_CounterValue)           |
-+----------------------------------------------------------------------------+
-| Task              : Latch the 32-Bit counter from selected module          |
-|                     (b_ModulNbr) in to the first latch register and return |
-|                     the latched value.                                     |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                              (0 to 3)                      |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pul_CounterValue : 32-Bit counter value       |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
-					    unsigned char b_ModulNbr,
-					    unsigned int *pul_CounterValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*********************/
-			/* Tatch the counter */
-	      /*********************/
-
-			outl(1, devpriv->s_BoardInfos.
-				ui_Address + (64 * b_ModulNbr));
-
-	      /************************/
-			/* Read the latch value */
-	      /************************/
-
-			*pul_CounterValue = inl(devpriv->s_BoardInfos.
-				ui_Address + 4 + (64 * b_ModulNbr));
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetIndexStatus (unsigned char_   b_BoardHandle,|
-|                                                      unsigned char_   b_ModulNbr,   |
-|                                                      unsigned char *_ pb_IndexStatus)|
-+----------------------------------------------------------------------------+
-| Task              : Return the index status                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_IndexStatus   : 0 : No INDEX occur           |
-|                                               1 : A INDEX occur            |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Index not initialised see function                 |
-|                         "i_APCI1710_InitIndex"                             |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
-				     unsigned char b_ModulNbr,
-				     unsigned char *pb_IndexStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*****************************/
-			/* Test if index initialised */
-	      /*****************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
-				dw_StatusReg = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (64 * b_ModulNbr));
-
-				*pb_IndexStatus = (unsigned char) (dw_StatusReg & 1);
-			} else {
-		 /*************************************************************/
-				/* Index not initialised see function "i_APCI1710_InitIndex" */
-		 /*************************************************************/
-
-				DPRINTK("Index not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetReferenceStatus                    |
-|                                                (unsigned char_   b_BoardHandle,     |
-|                                                 unsigned char_   b_ModulNbr,        |
-|                                                 unsigned char *_ pb_ReferenceStatus) |
-+----------------------------------------------------------------------------+
-| Task              : Return the reference status                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_ReferenceStatus   : 0 : No REFERENCE occur   |
-|                                                   1 : A REFERENCE occur    |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Reference not initialised see function             |
-|                         "i_APCI1710_InitReference"                         |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
-					 unsigned char b_ModulNbr,
-					 unsigned char *pb_ReferenceStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*********************************/
-			/* Test if reference initialised */
-	      /*********************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_ReferenceInit) {
-				dw_StatusReg = inl(devpriv->s_BoardInfos.
-					ui_Address + 24 + (64 * b_ModulNbr));
-
-				*pb_ReferenceStatus =
-					(unsigned char) (~dw_StatusReg & 1);
-			} else {
-		 /*********************************************************************/
-				/* Reference not initialised see function "i_APCI1710_InitReference" */
-		 /*********************************************************************/
-
-				DPRINTK("Reference not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetUASStatus                          |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char *_ pb_UASStatus)                        |
-+----------------------------------------------------------------------------+
-| Task              : Return the error signal (UAS) status                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_UASStatus      : 0 : UAS is low "0"          |
-|                                                1 : UAS is high "1"         |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetUASStatus(struct comedi_device *dev,
-				   unsigned char b_ModulNbr,
-				   unsigned char *pb_UASStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-			dw_StatusReg = inl(devpriv->s_BoardInfos.
-				ui_Address + 24 + (64 * b_ModulNbr));
-
-			*pb_UASStatus = (unsigned char) ((dw_StatusReg >> 1) & 1);
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetCBStatus                           |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char *_ pb_CBStatus)                         |
-+----------------------------------------------------------------------------+
-| Task              : Return the counter overflow status                     |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_CBStatus      : 0 : Counter no overflow      |
-|                                               1 : Counter overflow         |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetCBStatus(struct comedi_device *dev,
-				  unsigned char b_ModulNbr,
-				  unsigned char *pb_CBStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-			dw_StatusReg = inl(devpriv->s_BoardInfos.
-				ui_Address + 16 + (64 * b_ModulNbr));
-
-			*pb_CBStatus = (unsigned char) (dw_StatusReg & 1);
-
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_Get16BitCBStatus                      |
-|					(unsigned char_     b_BoardHandle,            |
-|					 unsigned char_     b_ModulNbr,               |
-|					 unsigned char *_ pb_CBStatusCounter0,         |
-|					 unsigned char *_ pb_CBStatusCounter1)         |
-+----------------------------------------------------------------------------+
-| Task              : Returns the counter overflow (counter initialised to   |
-|		      2*16-bit) status from selected incremental counter     |
-|		      module                                                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_CBStatusCounter0 : 0 : No overflow occur for |
-|						       the first 16-bit      |
-|						       counter               |
-|						   1 : Overflow occur for the|
-|						       first 16-bit counter  |
-|		      unsigned char *_ pb_CBStatusCounter1 : 0 : No overflow occur for |
-|						       the second 16-bit     |
-|						       counter               |
-|						   1 : Overflow occur for the|
-|						       second 16-bit counter |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Counter not initialised to 2*16-bit mode.          |
-|			  See function "i_APCI1710_InitCounter"              |
-|                     -5: Firmware revision error                            |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
-				       unsigned char b_ModulNbr,
-				       unsigned char *pb_CBStatusCounter0,
-				       unsigned char *pb_CBStatusCounter1)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /*************************/
-			/* Test if 2*16-Bit mode */
-	      /*************************/
-
-			if ((devpriv->s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister1 & 0x10) == 0x10) {
-		 /*****************************/
-				/* Test the Firmware version */
-		 /*****************************/
-
-				if ((devpriv->s_BoardInfos.
-						dw_MolduleConfiguration
-						[b_ModulNbr] & 0xFFFF) >=
-					0x3136) {
-					dw_StatusReg =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 16 +
-						(64 * b_ModulNbr));
-
-					*pb_CBStatusCounter1 =
-						(unsigned char) ((dw_StatusReg >> 0) &
-						1);
-					*pb_CBStatusCounter0 =
-						(unsigned char) ((dw_StatusReg >> 1) &
-						1);
-				}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) */
-				else {
-		    /****************************/
-					/* Firmware revision error  */
-		    /****************************/
-
-					i_ReturnValue = -5;
-				}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) */
-			}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) */
-			else {
-		 /********************************************/
-				/* Counter not initialised to 2*16-bit mode */
-				/* "i_APCI1710_InitCounter"                 */
-		 /********************************************/
-
-				DPRINTK("Counter not initialised\n");
-				i_ReturnValue = -4;
-			}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) */
-		}		/*  if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) */
-		else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}		/*  if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) */
-	}			/*  if (b_ModulNbr < 4) */
-	else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}			/*  if (b_ModulNbr < 4) */
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetUDStatus                           |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char *_ pb_UDStatus)                         |
-+----------------------------------------------------------------------------+
-| Task              : Return the counter progress status                     |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_UDStatus      : 0 : Counter progress in the  |
-|                                                   selected mode down       |
-|                                               1 : Counter progress in the  |
-|                                                   selected mode up         |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetUDStatus(struct comedi_device *dev,
-				  unsigned char b_ModulNbr,
-				  unsigned char *pb_UDStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-			dw_StatusReg = inl(devpriv->s_BoardInfos.
-				ui_Address + 24 + (64 * b_ModulNbr));
-
-			*pb_UDStatus = (unsigned char) ((dw_StatusReg >> 2) & 1);
-
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetInterruptUDLatchedStatus           |
-|                               (unsigned char_   b_BoardHandle,                      |
-|                                unsigned char_   b_ModulNbr,                         |
-|                                unsigned char *_ pb_UDStatus)                         |
-+----------------------------------------------------------------------------+
-| Task              : Return the counter progress latched status after a     |
-|                     index interrupt occur.                                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Module number to configure   |
-|                                               (0 to 3)                     |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_UDStatus      : 0 : Counter progress in the  |
-|                                                   selected mode down       |
-|                                               1 : Counter progress in the  |
-|                                                   selected mode up         |
-|                                               2 : No index interrupt occur |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: No counter module found                            |
-|                     -3: Counter not initialised see function               |
-|                         "i_APCI1710_InitCounter"                           |
-|                     -4: Interrupt function not initialised.                |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
-						  unsigned char b_ModulNbr,
-						  unsigned char *pb_UDStatus)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-		 /*********************************/
-			/* Test if index interrupt occur */
-		 /*********************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_IndexInterruptOccur == 1) {
-				devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_InitFlag.b_IndexInterruptOccur = 0;
-
-				dw_StatusReg = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (64 * b_ModulNbr));
-
-				*pb_UDStatus = (unsigned char) ((dw_StatusReg >> 1) & 1);
-			} else {
-		    /****************************/
-				/* No index interrupt occur */
-		    /****************************/
-
-				*pb_UDStatus = 2;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-	/*
-	   +----------------------------------------------------------------------------+
-	   | Function Name     : _INT_ i_APCI1710_ReadFrequencyMeasurement              |
-	   |                            (unsigned char_            b_BoardHandle,             |
-	   |                             unsigned char_            b_ModulNbr,                |
-	   |                             unsigned char *_          pb_Status,                  |
-	   |                             PULONG_        pul_ReadValue)               |
-	   +----------------------------------------------------------------------------+
-	   | Task              : Returns the status (pb_Status) and the number of       |
-	   |                  increments in the set time.                            |
-	   |                  See function " i_APCI1710_InitFrequencyMeasurement "   |
-	   +----------------------------------------------------------------------------+
-	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
-	   |                  unsigned char_  b_ModulNbr       : Number of the module to be   |
-	   |                                            configured (0 to 3)          |
-	   +----------------------------------------------------------------------------+
-	   | Output Parameters : unsigned char *_ pb_Status     : Returns the frequency        |
-	   |                                            measurement status           |
-	   |                                            0 : Counting cycle not       |
-	   |                                                started.                 |
-	   |                                            1 : Counting cycle started.  |
-	   |                                            2 : Counting cycle stopped.  |
-	   |                                                The measurement cycle is |
-	   |                                                completed.               |
-	   |                  unsigned char *_ pb_UDStatus      : 0 : Counter progress in the  |
-	   |                                                   selected mode down       |
-	   |                                               1 : Counter progress in the  |
-	   |                                                   selected mode up         |
-	   |                  PULONG_ pul_ReadValue   : Return the number of         |
-	   |                                            increments in the defined    |
-	   |                                            time base.                   |
-	   +----------------------------------------------------------------------------+
-	   | Return Value      :  0: No error                                           |
-	   |                     -1: The handle parameter of the board is wrong         |
-	   |                     -2: The selected module number is wrong                |
-	   |                     -3: Counter not initialised see function               |
-	   |                      "i_APCI1710_InitCounter"                           |
-	   |                     -4: Frequency measurement logic not initialised.       |
-	   |                      See function "i_APCI1710_InitFrequencyMeasurement" |
-	   +----------------------------------------------------------------------------+
-	 */
-static int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
-					       unsigned char b_ModulNbr,
-					       unsigned char *pb_Status,
-					       unsigned char *pb_UDStatus,
-					       unsigned int *pul_ReadValue)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ui_16BitValue;
-	unsigned int dw_StatusReg;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /*******************************/
-		/* Test if counter initialised */
-	   /*******************************/
-
-		if (devpriv->
-			s_ModuleInfo[b_ModulNbr].
-			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
-	      /********************************************/
-			/* Test if frequency measurement initialised */
-	      /********************************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_SiemensCounterInfo.
-				s_InitFlag.b_FrequencyMeasurementInit == 1) {
-		 /******************/
-				/* Test if enable */
-		 /******************/
-
-				if (devpriv->
-					s_ModuleInfo[b_ModulNbr].
-					s_SiemensCounterInfo.
-					s_InitFlag.
-					b_FrequencyMeasurementEnable == 1) {
-		    /*******************/
-					/* Read the status */
-		    /*******************/
-
-					dw_StatusReg =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 32 +
-						(64 * b_ModulNbr));
-
-		    /**************************/
-					/* Test if frequency stop */
-		    /**************************/
-
-					if (dw_StatusReg & 1) {
-						*pb_Status = 2;
-						*pb_UDStatus =
-							(unsigned char) ((dw_StatusReg >>
-								1) & 3);
-
-		       /******************/
-						/* Read the value */
-		       /******************/
-
-						*pul_ReadValue =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 28 +
-							(64 * b_ModulNbr));
-
-						if (*pb_UDStatus == 0) {
-			  /*************************/
-							/* Test the counter mode */
-			  /*************************/
-
-							if ((devpriv->s_ModuleInfo[b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) {
-			     /****************************************/
-								/* Test if 16-bit counter 1 pulse occur */
-			     /****************************************/
-
-								if ((*pul_ReadValue & 0xFFFFU) != 0) {
-									ui_16BitValue
-										=
-										(unsigned int)
-										*
-										pul_ReadValue
-										&
-										0xFFFFU;
-									*pul_ReadValue
-										=
-										(*pul_ReadValue
-										&
-										0xFFFF0000UL)
-										|
-										(0xFFFFU
-										-
-										ui_16BitValue);
-								}
-
-			     /****************************************/
-								/* Test if 16-bit counter 2 pulse occur */
-			     /****************************************/
-
-								if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
-									ui_16BitValue
-										=
-										(unsigned int)
-										(
-										(*pul_ReadValue
-											>>
-											16)
-										&
-										0xFFFFU);
-									*pul_ReadValue
-										=
-										(*pul_ReadValue
-										&
-										0xFFFFUL)
-										|
-										(
-										(0xFFFFU - ui_16BitValue) << 16);
-								}
-							} else {
-								if (*pul_ReadValue != 0) {
-									*pul_ReadValue
-										=
-										0xFFFFFFFFUL
-										-
-										*pul_ReadValue;
-								}
-							}
-						} else {
-							if (*pb_UDStatus == 1) {
-			     /****************************************/
-								/* Test if 16-bit counter 2 pulse occur */
-			     /****************************************/
-
-								if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
-									ui_16BitValue
-										=
-										(unsigned int)
-										(
-										(*pul_ReadValue
-											>>
-											16)
-										&
-										0xFFFFU);
-									*pul_ReadValue
-										=
-										(*pul_ReadValue
-										&
-										0xFFFFUL)
-										|
-										(
-										(0xFFFFU - ui_16BitValue) << 16);
-								}
-							} else {
-								if (*pb_UDStatus
-									== 2) {
-				/****************************************/
-									/* Test if 16-bit counter 1 pulse occur */
-				/****************************************/
-
-									if ((*pul_ReadValue & 0xFFFFU) != 0) {
-										ui_16BitValue
-											=
-											(unsigned int)
-											*
-											pul_ReadValue
-											&
-											0xFFFFU;
-										*pul_ReadValue
-											=
-											(*pul_ReadValue
-											&
-											0xFFFF0000UL)
-											|
-											(0xFFFFU
-											-
-											ui_16BitValue);
-									}
-								}
-							}
-						}
-					} else {
-						*pb_Status = 1;
-						*pb_UDStatus = 0;
-					}
-				} else {
-					*pb_Status = 0;
-					*pb_UDStatus = 0;
-				}
-			} else {
-		 /***********************************************/
-				/* Frequency measurement logic not initialised */
-		 /***********************************************/
-
-				DPRINTK("Frequency measurement logic not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /****************************************/
-			/* Counter not initialised see function */
-			/* "i_APCI1710_InitCounter"             */
-	      /****************************************/
-
-			DPRINTK("Counter not initialised\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*************************************************/
-		/* The selected module number parameter is wrong */
-	   /*************************************************/
-
-		DPRINTK("The selected module number parameter is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-/*
- * Read and Get functions for INC_CPT
- */
-static int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev,
-				     struct comedi_subdevice *s,
-				     struct comedi_insn *insn,
-				     unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned int ui_ReadType;
-	int i_ReturnValue = 0;
-
-	ui_ReadType = CR_CHAN(insn->chanspec);
-
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-	switch (ui_ReadType) {
-	case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
-		i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_READLATCHREGISTERVALUE:
-		i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
-		printk("Latch Register Value %d\n", data[0]);
-		break;
-
-	case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned int *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_GETINDEXSTATUS:
-		i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_GETREFERENCESTATUS:
-		i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_GETUASSTATUS:
-		i_ReturnValue = i_APCI1710_GetUASStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_GETCBSTATUS:
-		i_ReturnValue = i_APCI1710_GetCBStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_GET16BITCBSTATUS:
-		i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char *) &data[0], (unsigned char *) &data[1]);
-		break;
-
-	case APCI1710_INCCPT_GETUDSTATUS:
-		i_ReturnValue = i_APCI1710_GetUDStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-
-		break;
-
-	case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
-		i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char *) &data[0],
-			(unsigned char *) &data[1], (unsigned int *) &data[2]);
-		break;
-
-	case APCI1710_INCCPT_READINTERRUPT:
-		data[0] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].b_OldModuleMask;
-		data[1] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-		data[2] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-		/**************************/
-		/* Increment the read FIFO */
-		/***************************/
-
-		devpriv->
-			s_InterruptParameters.
-			ui_Read = (devpriv->s_InterruptParameters.
-			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-
-		break;
-
-	default:
-		printk("ReadType Parameter wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
deleted file mode 100644
index 6bbcb06..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : Inp_CPT.C       | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 pulse encoder module                        |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          |           |                                                |
-  |----------|-----------|------------------------------------------------|
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_SINGLE			0
-#define APCI1710_CONTINUOUS		1
-
-#define APCI1710_PULSEENCODER_READ	0
-#define APCI1710_PULSEENCODER_WRITE	1
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitPulseEncoder                      |
-|                               (unsigned char_          b_BoardHandle,               |
-|                                unsigned char_          b_ModulNbr,                  |
-|                                unsigned char_          b_PulseEncoderNbr,           |
-|                                unsigned char_          b_InputLevelSelection,       |
-|                                unsigned char_          b_TriggerOutputAction,       |
-|                                ULONG_        ul_StartValue)                |
-+----------------------------------------------------------------------------+
-| Task              : Configure the pulse encoder operating mode selected via|
-|                     b_ModulNbr and b_PulseEncoderNbr. The pulse encoder    |
-|                     after each pulse decrement the counter value from 1.   |
-|                                                                            |
-|                     You must calling this function be for you call any     |
-|                     other function witch access of pulse encoders.         |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 3)       |
-|                     unsigned char_ b_PulseEncoderNbr     : Pulse encoder selection  |
-|                                                   (0 to 3)                 |
-|                     unsigned char_ b_InputLevelSelection : Input level selection    |
-|                                                   (0 or 1)                 |
-|                                                       0 : Set pulse encoder|
-|                                                           count the the low|
-|                                                           level pulse.     |
-|                                                       1 : Set pulse encoder|
-|                                                           count the the    |
-|                                                           high level pulse.|
-|                     unsigned char_ b_TriggerOutputAction : Digital TRIGGER output   |
-|                                                   action                   |
-|                                                       0 : No action        |
-|                                                       1 : Set the trigger  |
-|                                                           output to "1"    |
-|                                                           (high) after the |
-|                                                           passage from 1 to|
-|                                                           0 from pulse     |
-|                                                           encoder.         |
-|                                                       2 : Set the trigger  |
-|                                                           output to "0"    |
-|                                                           (low) after the  |
-|                                                           passage from 1 to|
-|                                                           0 from pulse     |
-|                                                           encoder          |
-|                     ULONG_ ul_StartValue        : Pulse encoder start value|
-|                                                   (1 to 4294967295)
-	b_ModulNbr				=(unsigned char) CR_AREF(insn->chanspec);
-	b_PulseEncoderNbr		=(unsigned char) data[0];
-	b_InputLevelSelection	=(unsigned char) data[1];
-	b_TriggerOutputAction	=(unsigned char) data[2];
-	ul_StartValue			=(unsigned int) data[3];
-       |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module is not a pulse encoder module            |
-|                    -3: Pulse encoder selection is wrong                    |
-|                    -4: Input level selection is wrong                      |
-|                    -5: Digital TRIGGER output action selection is wrong    |
-|                    -6: Pulse encoder start value is wrong                  |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
-						 struct comedi_subdevice *s,
-						 struct comedi_insn *insn,
-						 unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_IntRegister;
-	unsigned char b_ModulNbr;
-	unsigned char b_PulseEncoderNbr;
-	unsigned char b_InputLevelSelection;
-	unsigned char b_TriggerOutputAction;
-	unsigned int ul_StartValue;
-
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_PulseEncoderNbr = (unsigned char) data[0];
-	b_InputLevelSelection = (unsigned char) data[1];
-	b_TriggerOutputAction = (unsigned char) data[2];
-	ul_StartValue = (unsigned int) data[3];
-
-	i_ReturnValue = insn->n;
-
-	/***********************************/
-	/* Test the selected module number */
-	/***********************************/
-
-	if (b_ModulNbr <= 3) {
-	   /*************************/
-		/* Test if pulse encoder */
-	   /*************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				APCI1710_PULSE_ENCODER) ==
-			APCI1710_PULSE_ENCODER) {
-	      /******************************************/
-			/* Test the selected pulse encoder number */
-	      /******************************************/
-
-			if (b_PulseEncoderNbr <= 3) {
-		 /************************/
-				/* Test the input level */
-		 /************************/
-
-				if ((b_InputLevelSelection == 0)
-					|| (b_InputLevelSelection == 1)) {
-		    /*******************************************/
-					/* Test the ouput TRIGGER action selection */
-		    /*******************************************/
-
-					if ((b_TriggerOutputAction <= 2)
-						|| (b_PulseEncoderNbr > 0)) {
-						if (ul_StartValue > 1) {
-
-							dw_IntRegister =
-								inl(devpriv->
-								s_BoardInfos.
-								ui_Address +
-								20 +
-								(64 * b_ModulNbr));
-
-			  /***********************/
-							/* Set the start value */
-			  /***********************/
-
-							outl(ul_StartValue,
-								devpriv->
-								s_BoardInfos.
-								ui_Address +
-								(b_PulseEncoderNbr
-									* 4) +
-								(64 * b_ModulNbr));
-
-			  /***********************/
-							/* Set the input level */
-			  /***********************/
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_PulseEncoderModuleInfo.
-								dw_SetRegister =
-								(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_PulseEncoderModuleInfo.
-								dw_SetRegister &
-								(0xFFFFFFFFUL -
-									(1UL << (8 + b_PulseEncoderNbr)))) | ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr));
-
-			  /*******************************/
-							/* Test if output trigger used */
-			  /*******************************/
-
-							if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) {
-			     /****************************/
-								/* Enable the output action */
-			     /****************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									| (1UL
-									<< (4 + b_PulseEncoderNbr));
-
-			     /*********************************/
-								/* Set the output TRIGGER action */
-			     /*********************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									=
-									(devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									&
-									(0xFFFFFFFFUL
-										-
-										(1UL << (12 + b_PulseEncoderNbr)))) | ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr));
-							} else {
-			     /*****************************/
-								/* Disable the output action */
-			     /*****************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									&
-									(0xFFFFFFFFUL
-									-
-									(1UL << (4 + b_PulseEncoderNbr)));
-							}
-
-			  /*************************/
-							/* Set the configuration */
-			  /*************************/
-
-							outl(devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_PulseEncoderModuleInfo.
-								dw_SetRegister,
-								devpriv->
-								s_BoardInfos.
-								ui_Address +
-								20 +
-								(64 * b_ModulNbr));
-
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_PulseEncoderModuleInfo.
-								s_PulseEncoderInfo
-								[b_PulseEncoderNbr].
-								b_PulseEncoderInit
-								= 1;
-						} else {
-			  /**************************************/
-							/* Pulse encoder start value is wrong */
-			  /**************************************/
-
-							DPRINTK("Pulse encoder start value is wrong\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-		       /****************************************************/
-						/* Digital TRIGGER output action selection is wrong */
-		       /****************************************************/
-
-						DPRINTK("Digital TRIGGER output action selection is wrong\n");
-						i_ReturnValue = -5;
-					}
-				} else {
-		    /**********************************/
-					/* Input level selection is wrong */
-		    /**********************************/
-
-					DPRINTK("Input level selection is wrong\n");
-					i_ReturnValue = -4;
-				}
-			} else {
-		 /************************************/
-				/* Pulse encoder selection is wrong */
-		 /************************************/
-
-				DPRINTK("Pulse encoder selection is wrong\n");
-				i_ReturnValue = -3;
-			}
-		} else {
-	      /********************************************/
-			/* The module is not a pulse encoder module */
-	      /********************************************/
-
-			DPRINTK("The module is not a pulse encoder module\n");
-			i_ReturnValue = -2;
-		}
-	} else {
-	   /********************************************/
-		/* The module is not a pulse encoder module */
-	   /********************************************/
-
-		DPRINTK("The module is not a pulse encoder module\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_EnablePulseEncoder                    |
-|                                       (unsigned char_  b_BoardHandle,               |
-|                                        unsigned char_  b_ModulNbr,                  |
-|                                        unsigned char_  b_PulseEncoderNbr,           |
-|                                        unsigned char_  b_CycleSelection,            |
-|                                        unsigned char_  b_InterruptHandling)         |
-+----------------------------------------------------------------------------+
-| Task              : Enableor disable  the selected pulse encoder (b_PulseEncoderNbr)  |
-|                     from selected module (b_ModulNbr). Each input pulse    |
-|                     decrement the pulse encoder counter value from 1.      |
-|                     If you enabled the interrupt (b_InterruptHandling), a  |
-|                     interrupt is generated when the pulse encoder has run  |
-|                     down.                                                  |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_   b_BoardHandle       : Handle of board APCI-1710|
-|                     unsigned char_   b_ModulNbr          : Module number to         |
-|                                                   configure (0 to 3)       |
-|                     unsigned char_   b_PulseEncoderNbr   : Pulse encoder selection  |
-|                                                   (0 to 3)                 |
-|                     unsigned char_   b_CycleSelection    : APCI1710_CONTINUOUS:     |
-|                                                       Each time the        |
-|                                                       counting value is set|
-|                                                       on "0", the pulse    |
-|                                                       encoder load the     |
-|                                                       start value after    |
-|                                                       the next pulse.      |
-|                                                   APCI1710_SINGLE:         |
-|                                                       If the counter is set|
-|                                                       on "0", the pulse    |
-|                                                       encoder is stopped.  |
-|                     unsigned char_   b_InterruptHandling : Interrupts can be        |
-|                                                   generated, when the pulse|
-|                                                   encoder has run down.    |
-|                                                   With this parameter the  |
-|                                                   user decides if          |
-|                                                   interrupts are used or   |
-|                                                   not.                     |
-|                                                     APCI1710_ENABLE:       |
-|                                                     Interrupts are enabled |
-|                                                     APCI1710_DISABLE:      |
-|                                                     Interrupts are disabled
-
-	b_ModulNbr			=(unsigned char) CR_AREF(insn->chanspec);
-	b_Action			=(unsigned char) data[0];
-	b_PulseEncoderNbr	=(unsigned char) data[1];
-	b_CycleSelection	=(unsigned char) data[2];
-	b_InterruptHandling	=(unsigned char) data[3];|
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection is wrong                          |
-|                     -3: Pulse encoder selection is wrong                   |
-|                     -4: Pulse encoder not initialised.                     |
-|                         See function "i_APCI1710_InitPulseEncoder"         |
-|                     -5: Cycle selection mode is wrong                      |
-|                     -6: Interrupt handling mode is wrong                   |
-|                     -7: Interrupt routine not installed.                   |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
-							 struct comedi_subdevice *s,
-							 struct comedi_insn *insn,
-							 unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_ModulNbr;
-	unsigned char b_PulseEncoderNbr;
-	unsigned char b_CycleSelection;
-	unsigned char b_InterruptHandling;
-	unsigned char b_Action;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_Action = (unsigned char) data[0];
-	b_PulseEncoderNbr = (unsigned char) data[1];
-	b_CycleSelection = (unsigned char) data[2];
-	b_InterruptHandling = (unsigned char) data[3];
-
-	/***********************************/
-	/* Test the selected module number */
-	/***********************************/
-
-	if (b_ModulNbr <= 3) {
-	   /******************************************/
-		/* Test the selected pulse encoder number */
-	   /******************************************/
-
-		if (b_PulseEncoderNbr <= 3) {
-	      /*************************************/
-			/* Test if pulse encoder initialised */
-	      /*************************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_PulseEncoderModuleInfo.
-				s_PulseEncoderInfo[b_PulseEncoderNbr].
-				b_PulseEncoderInit == 1) {
-				switch (b_Action) {
-
-				case APCI1710_ENABLE:
-		 /****************************/
-					/* Test the cycle selection */
-		 /****************************/
-
-					if (b_CycleSelection ==
-						APCI1710_CONTINUOUS
-						|| b_CycleSelection ==
-						APCI1710_SINGLE) {
-		    /*******************************/
-						/* Test the interrupt handling */
-		    /*******************************/
-
-						if (b_InterruptHandling ==
-							APCI1710_ENABLE
-							|| b_InterruptHandling
-							== APCI1710_DISABLE) {
-		       /******************************/
-							/* Test if interrupt not used */
-		       /******************************/
-
-							if (b_InterruptHandling
-								==
-								APCI1710_DISABLE)
-							{
-			  /*************************/
-								/* Disable the interrupt */
-			  /*************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									&
-									(0xFFFFFFFFUL
-									-
-									(1UL << b_PulseEncoderNbr));
-							} else {
-
-			     /************************/
-								/* Enable the interrupt */
-			     /************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister
-									| (1UL
-									<<
-									b_PulseEncoderNbr);
-								devpriv->tsk_Current = current;	/*  Save the current process task structure */
-
-							}
-
-							if (i_ReturnValue >= 0) {
-			  /***********************************/
-								/* Enable or disable the interrupt */
-			  /***********************************/
-
-								outl(devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_SetRegister,
-									devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 20 +
-									(64 * b_ModulNbr));
-
-			  /****************************/
-								/* Enable the pulse encoder */
-			  /****************************/
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_ControlRegister
-									=
-									devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_ControlRegister
-									| (1UL
-									<<
-									b_PulseEncoderNbr);
-
-			  /**********************/
-								/* Set the cycle mode */
-			  /**********************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_ControlRegister
-									=
-									(devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_ControlRegister
-									&
-									(0xFFFFFFFFUL
-										-
-										(1 << (b_PulseEncoderNbr + 4)))) | ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr));
-
-			  /****************************/
-								/* Enable the pulse encoder */
-			  /****************************/
-
-								outl(devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PulseEncoderModuleInfo.
-									dw_ControlRegister,
-									devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 16 +
-									(64 * b_ModulNbr));
-							}
-						} else {
-		       /************************************/
-							/* Interrupt handling mode is wrong */
-		       /************************************/
-
-							DPRINTK("Interrupt handling mode is wrong\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-		    /*********************************/
-						/* Cycle selection mode is wrong */
-		    /*********************************/
-
-						DPRINTK("Cycle selection mode is wrong\n");
-						i_ReturnValue = -5;
-					}
-					break;
-
-				case APCI1710_DISABLE:
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_ControlRegister =
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_ControlRegister &
-						(0xFFFFFFFFUL -
-						(1UL << b_PulseEncoderNbr));
-
-		 /*****************************/
-					/* Disable the pulse encoder */
-		 /*****************************/
-
-					outl(devpriv->s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_ControlRegister,
-						devpriv->s_BoardInfos.
-						ui_Address + 16 +
-						(64 * b_ModulNbr));
-
-					break;
-				}	/*  switch End */
-
-			} else {
-		 /*********************************/
-				/* Pulse encoder not initialised */
-		 /*********************************/
-
-				DPRINTK("Pulse encoder not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /************************************/
-			/* Pulse encoder selection is wrong */
-	      /************************************/
-
-			DPRINTK("Pulse encoder selection is wrong\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*****************************/
-		/* Module selection is wrong */
-	   /*****************************/
-
-		DPRINTK("Module selection is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadPulseEncoderStatus                |
-|                                       (unsigned char_  b_BoardHandle,               |
-|                                        unsigned char_  b_ModulNbr,                  |
-|                                        unsigned char_  b_PulseEncoderNbr,           |
-|                                        unsigned char *_ pb_Status)                   |
-+----------------------------------------------------------------------------+
-| Task    APCI1710_PULSEENCODER_READ          : Reads the pulse encoder status
-											and valuefrom selected pulse     |
-|                     encoder (b_PulseEncoderNbr) from selected module       |
-|                     (b_ModulNbr).                                          |
-+----------------------------------------------------------------------------+
-	unsigned char   b_Type; data[0]
-   APCI1710_PULSEENCODER_WRITE
- Writes a 32-bit value (ul_WriteValue) into the selected|
-|                     pulse encoder (b_PulseEncoderNbr) from selected module |
-|                     (b_ModulNbr). This operation set the new start pulse   |
-|                     encoder value.
- APCI1710_PULSEENCODER_READ
-| Input Parameters  : unsigned char_   b_BoardHandle       : Handle of board APCI-1710|
-|            CRAREF()         unsigned char_   b_ModulNbr          : Module number to         |
-|                                                   configure (0 to 3)       |
-|              data[1]       unsigned char_   b_PulseEncoderNbr   : Pulse encoder selection  |
-|                                                   (0 to 3)
-   APCI1710_PULSEENCODER_WRITE
-				data[2]		ULONG_ ul_WriteValue        : 32-bit value to be       |
-|                                                   written             |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_ pb_Status            : Pulse encoder status.    |
-|                                                       0 : No overflow occur|
-|                                                       1 : Overflow occur
-						PULONG_ pul_ReadValue       : Pulse encoder value      |  |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection is wrong                          |
-|                     -3: Pulse encoder selection is wrong                   |
-|                     -4: Pulse encoder not initialised.                     |
-|                         See function "i_APCI1710_InitPulseEncoder"         |
-+----------------------------------------------------------------------------+
-*/
-
-/*_INT_   i_APCI1710_ReadPulseEncoderStatus       (unsigned char_   b_BoardHandle,
-						 unsigned char_   b_ModulNbr,
-						 unsigned char_   b_PulseEncoderNbr,
-
-						 unsigned char *_ pb_Status)
-						 */
-static int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
-						    struct comedi_subdevice *s,
-						    struct comedi_insn *insn,
-						    unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusRegister;
-	unsigned char b_ModulNbr;
-	unsigned char b_PulseEncoderNbr;
-	unsigned char *pb_Status;
-	unsigned char b_Type;
-	unsigned int *pul_ReadValue;
-	unsigned int ul_WriteValue;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_Type = (unsigned char) data[0];
-	b_PulseEncoderNbr = (unsigned char) data[1];
-	pb_Status = (unsigned char *) &data[0];
-	pul_ReadValue = (unsigned int *) &data[1];
-
-	/***********************************/
-	/* Test the selected module number */
-	/***********************************/
-
-	if (b_ModulNbr <= 3) {
-	   /******************************************/
-		/* Test the selected pulse encoder number */
-	   /******************************************/
-
-		if (b_PulseEncoderNbr <= 3) {
-	      /*************************************/
-			/* Test if pulse encoder initialised */
-	      /*************************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_PulseEncoderModuleInfo.
-				s_PulseEncoderInfo[b_PulseEncoderNbr].
-				b_PulseEncoderInit == 1) {
-
-				switch (b_Type) {
-				case APCI1710_PULSEENCODER_READ:
-		 /****************************/
-					/* Read the status register */
-		 /****************************/
-
-					dw_StatusRegister =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 16 +
-						(64 * b_ModulNbr));
-
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_StatusRegister = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_StatusRegister |
-						dw_StatusRegister;
-
-					*pb_Status =
-						(unsigned char) (devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_StatusRegister >> (1 +
-							b_PulseEncoderNbr)) & 1;
-
-					devpriv->s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_StatusRegister =
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_PulseEncoderModuleInfo.
-						dw_StatusRegister &
-						(0xFFFFFFFFUL - (1 << (1 +
-								b_PulseEncoderNbr)));
-
-		 /******************/
-					/* Read the value */
-		 /******************/
-
-					*pul_ReadValue =
-						inl(devpriv->s_BoardInfos.
-						ui_Address +
-						(4 * b_PulseEncoderNbr) +
-						(64 * b_ModulNbr));
-					break;
-
-				case APCI1710_PULSEENCODER_WRITE:
-					ul_WriteValue = (unsigned int) data[2];
-			/*******************/
-					/* Write the value */
-			/*******************/
-
-					outl(ul_WriteValue,
-						devpriv->s_BoardInfos.
-						ui_Address +
-						(4 * b_PulseEncoderNbr) +
-						(64 * b_ModulNbr));
-
-				}	/* end of switch */
-			} else {
-		 /*********************************/
-				/* Pulse encoder not initialised */
-		 /*********************************/
-
-				DPRINTK("Pulse encoder not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /************************************/
-			/* Pulse encoder selection is wrong */
-	      /************************************/
-
-			DPRINTK("Pulse encoder selection is wrong\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*****************************/
-		/* Module selection is wrong */
-	   /*****************************/
-
-		DPRINTK("Module selection is wrong\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-static int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
-						    struct comedi_subdevice *s,
-						    struct comedi_insn *insn,
-						    unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-
-	data[0] = devpriv->s_InterruptParameters.
-		s_FIFOInterruptParameters[devpriv->
-		s_InterruptParameters.ui_Read].b_OldModuleMask;
-	data[1] = devpriv->s_InterruptParameters.
-		s_FIFOInterruptParameters[devpriv->
-		s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-	data[2] = devpriv->s_InterruptParameters.
-		s_FIFOInterruptParameters[devpriv->
-		s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-	/***************************/
-	/* Increment the read FIFO */
-	/***************************/
-
-	devpriv->s_InterruptParameters.
-		ui_Read = (devpriv->
-		s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-
-	return insn->n;
-
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
deleted file mode 100644
index 5c83033..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+++ /dev/null
@@ -1,3582 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : PWM.C           | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 Wulse wide modulation module                |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +-----------------------------------------------------------------------+
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_30MHZ			30
-#define APCI1710_33MHZ			33
-#define APCI1710_40MHZ			40
-
-#define APCI1710_PWM_INIT		0
-#define APCI1710_PWM_GETINITDATA	1
-
-#define APCI1710_PWM_DISABLE		0
-#define APCI1710_PWM_ENABLE		1
-#define APCI1710_PWM_NEWTIMING		2
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitPWM                               |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_PWM,                    |
-|                                        unsigned char_     b_ClockSelection,         |
-|                                        unsigned char_     b_TimingUnit,             |
-|                                        ULONG_   ul_LowTiming,              |
-|                                        ULONG_   ul_HighTiming,             |
-|                                        PULONG_ pul_RealLowTiming,          |
-|                                        PULONG_ pul_RealHighTiming)         |
-+----------------------------------------------------------------------------+
-| Task              : Configure the selected PWM (b_PWM) from selected module|
-|                     (b_ModulNbr). The ul_LowTiming, ul_HighTiming and      |
-|                     ul_TimingUnit determine the low/high timing base for   |
-|                     the period. pul_RealLowTiming, pul_RealHighTiming      |
-|                     return the real timing value.                          |
-|                     You must calling this function be for you call any     |
-|                     other function witch access of the PWM.                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_     b_BoardHandle    : Handle of board APCI-1710 |
-|                     unsigned char_     b_ModulNbr       : Module number to configure|
-|                                                  (0 to 3)                  |
-|                     unsigned char_     b_PWM            : Selected PWM (0 or 1).    |
-|                     unsigned char_     b_ClockSelection : Selection from PCI bus    |
-|                                                  clock                     |
-|                                                   - APCI1710_30MHZ :       |
-|                                                     The PC have a 30 MHz   |
-|                                                     PCI bus clock          |
-|                                                   - APCI1710_33MHZ :       |
-|                                                     The PC have a 33 MHz   |
-|                                                     PCI bus clock          |
-|                                                   - APCI1710_40MHZ         |
-|                                                     The APCI-1710 have a   |
-|                                                     integrated 40Mhz       |
-|                                                     quartz.                |
-|                     unsigned char_     b_TimingUnit     : Base timing Unit (0 to 4) |
-|                                                       0 : ns               |
-|                                                       1 : æs               |
-|                                                       2 : ms               |
-|                                                       3 : s                |
-|                                                       4 : mn               |
-|                     ULONG_    ul_LowTiming     : Low base timing value.    |
-|                     ULONG_    ul_HighTiming    : High base timing value.   |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pul_RealLowTiming  : Real low base timing     |
-|                                                   value.                   |
-|                     PULONG_  pul_RealHighTiming : Real high base timing    |
-|                                                   value.                   |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: The module is not a PWM module                      |
-|                    -4: PWM selection is wrong                              |
-|                    -5: The selected input clock is wrong                   |
-|                    -6: Timing Unit selection is wrong                      |
-|                    -7: Low base timing selection is wrong                  |
-|                    -8: High base timing selection is wrong                 |
-|                    -9: You can not used the 40MHz clock selection with     |
-|                        this board                                          |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InitPWM(struct comedi_device *dev,
-			      unsigned char b_ModulNbr,
-			      unsigned char b_PWM,
-			      unsigned char b_ClockSelection,
-			      unsigned char b_TimingUnit,
-			      unsigned int ul_LowTiming,
-			      unsigned int ul_HighTiming,
-			      unsigned int *pul_RealLowTiming,
-			      unsigned int *pul_RealHighTiming)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ul_LowTimerValue = 0;
-	unsigned int ul_HighTimerValue = 0;
-	unsigned int dw_Command;
-	double d_RealLowTiming = 0;
-	double d_RealHighTiming = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***************/
-		/* Test if PWM */
-		/***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			/**************************/
-			/* Test the PWM selection */
-			/**************************/
-
-			if (b_PWM <= 1) {
-				/******************/
-				/* Test the clock */
-				/******************/
-
-				if ((b_ClockSelection == APCI1710_30MHZ) ||
-					(b_ClockSelection == APCI1710_33MHZ) ||
-					(b_ClockSelection == APCI1710_40MHZ)) {
-					/************************/
-					/* Test the timing unit */
-					/************************/
-
-					if (b_TimingUnit <= 4) {
-						/*********************************/
-						/* Test the low timing selection */
-						/*********************************/
-
-						if (((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 0)
-								&& (ul_LowTiming
-									>= 266)
-								&& (ul_LowTiming
-									<=
-									0xFFFFFFFFUL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 1)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									571230650UL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 2)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									571230UL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 3)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									571UL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 4)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<= 9UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 0)
-								&& (ul_LowTiming
-									>= 242)
-								&& (ul_LowTiming
-									<=
-									0xFFFFFFFFUL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 1)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									519691043UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 2)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									519691UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 3)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									520UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 4)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<= 8UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 0)
-								&& (ul_LowTiming
-									>= 200)
-								&& (ul_LowTiming
-									<=
-									0xFFFFFFFFUL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 1)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									429496729UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 2)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									429496UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 3)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									429UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 4)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									7UL))) {
-							/**********************************/
-							/* Test the High timing selection */
-							/**********************************/
-
-							if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
-								/**************************/
-								/* Test the board version */
-								/**************************/
-
-								if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) {
-
-									/************************************/
-									/* Calculate the low division fator */
-									/************************************/
-
-									fpu_begin
-										();
-
-									switch (b_TimingUnit) {
-										/******/
-										/* ns */
-										/******/
-
-									case 0:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(ul_LowTiming
-											*
-											(0.00025 * b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-											ul_LowTimerValue
-												=
-												ul_LowTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealLowTiming
-											=
-											(unsigned int)
-											(ul_LowTimerValue
-											/
-											(0.00025 * (double)b_ClockSelection));
-										d_RealLowTiming
-											=
-											(double)
-											ul_LowTimerValue
-											/
-											(0.00025
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
-											*pul_RealLowTiming
-												=
-												*pul_RealLowTiming
-												+
-												1;
-										}
-
-										ul_LowTiming
-											=
-											ul_LowTiming
-											-
-											1;
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_LowTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_LowTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/******/
-										/* æs */
-										/******/
-
-									case 1:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(ul_LowTiming
-											*
-											(0.25 * b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-											ul_LowTimerValue
-												=
-												ul_LowTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealLowTiming
-											=
-											(unsigned int)
-											(ul_LowTimerValue
-											/
-											(0.25 * (double)b_ClockSelection));
-										d_RealLowTiming
-											=
-											(double)
-											ul_LowTimerValue
-											/
-											(
-											(double)
-											0.25
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
-											*pul_RealLowTiming
-												=
-												*pul_RealLowTiming
-												+
-												1;
-										}
-
-										ul_LowTiming
-											=
-											ul_LowTiming
-											-
-											1;
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_LowTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_LowTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/******/
-										/* ms */
-										/******/
-
-									case 2:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_LowTimerValue
-											=
-											ul_LowTiming
-											*
-											(250.0
-											*
-											b_ClockSelection);
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-											ul_LowTimerValue
-												=
-												ul_LowTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealLowTiming
-											=
-											(unsigned int)
-											(ul_LowTimerValue
-											/
-											(250.0 * (double)b_ClockSelection));
-										d_RealLowTiming
-											=
-											(double)
-											ul_LowTimerValue
-											/
-											(250.0
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
-											*pul_RealLowTiming
-												=
-												*pul_RealLowTiming
-												+
-												1;
-										}
-
-										ul_LowTiming
-											=
-											ul_LowTiming
-											-
-											1;
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_LowTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_LowTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/*****/
-										/* s */
-										/*****/
-
-									case 3:
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(ul_LowTiming
-											*
-											(250000.0
-												*
-												b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-											ul_LowTimerValue
-												=
-												ul_LowTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealLowTiming
-											=
-											(unsigned int)
-											(ul_LowTimerValue
-											/
-											(250000.0
-												*
-												(double)
-												b_ClockSelection));
-										d_RealLowTiming
-											=
-											(double)
-											ul_LowTimerValue
-											/
-											(250000.0
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
-											*pul_RealLowTiming
-												=
-												*pul_RealLowTiming
-												+
-												1;
-										}
-
-										ul_LowTiming
-											=
-											ul_LowTiming
-											-
-											1;
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_LowTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_LowTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/******/
-										/* mn */
-										/******/
-
-									case 4:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(
-											(ul_LowTiming
-												*
-												60)
-											*
-											(250000.0
-												*
-												b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-											ul_LowTimerValue
-												=
-												ul_LowTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealLowTiming
-											=
-											(unsigned int)
-											(ul_LowTimerValue
-											/
-											(250000.0
-												*
-												(double)
-												b_ClockSelection))
-											/
-											60;
-										d_RealLowTiming
-											=
-											(
-											(double)
-											ul_LowTimerValue
-											/
-											(250000.0
-												*
-												(double)
-												b_ClockSelection))
-											/
-											60.0;
-
-										if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealLowTiming + 0.5)) {
-											*pul_RealLowTiming
-												=
-												*pul_RealLowTiming
-												+
-												1;
-										}
-
-										ul_LowTiming
-											=
-											ul_LowTiming
-											-
-											1;
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_LowTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_LowTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-									}
-
-									/*************************************/
-									/* Calculate the high division fator */
-									/*************************************/
-
-									switch (b_TimingUnit) {
-										/******/
-										/* ns */
-										/******/
-
-									case 0:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(ul_HighTiming
-											*
-											(0.00025 * b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-											ul_HighTimerValue
-												=
-												ul_HighTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealHighTiming
-											=
-											(unsigned int)
-											(ul_HighTimerValue
-											/
-											(0.00025 * (double)b_ClockSelection));
-										d_RealHighTiming
-											=
-											(double)
-											ul_HighTimerValue
-											/
-											(0.00025
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
-											*pul_RealHighTiming
-												=
-												*pul_RealHighTiming
-												+
-												1;
-										}
-
-										ul_HighTiming
-											=
-											ul_HighTiming
-											-
-											1;
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_HighTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_HighTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/******/
-										/* æs */
-										/******/
-
-									case 1:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(ul_HighTiming
-											*
-											(0.25 * b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-											ul_HighTimerValue
-												=
-												ul_HighTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealHighTiming
-											=
-											(unsigned int)
-											(ul_HighTimerValue
-											/
-											(0.25 * (double)b_ClockSelection));
-										d_RealHighTiming
-											=
-											(double)
-											ul_HighTimerValue
-											/
-											(
-											(double)
-											0.25
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
-											*pul_RealHighTiming
-												=
-												*pul_RealHighTiming
-												+
-												1;
-										}
-
-										ul_HighTiming
-											=
-											ul_HighTiming
-											-
-											1;
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_HighTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_HighTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/******/
-										/* ms */
-										/******/
-
-									case 2:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_HighTimerValue
-											=
-											ul_HighTiming
-											*
-											(250.0
-											*
-											b_ClockSelection);
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-											ul_HighTimerValue
-												=
-												ul_HighTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealHighTiming
-											=
-											(unsigned int)
-											(ul_HighTimerValue
-											/
-											(250.0 * (double)b_ClockSelection));
-										d_RealHighTiming
-											=
-											(double)
-											ul_HighTimerValue
-											/
-											(250.0
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
-											*pul_RealHighTiming
-												=
-												*pul_RealHighTiming
-												+
-												1;
-										}
-
-										ul_HighTiming
-											=
-											ul_HighTiming
-											-
-											1;
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_HighTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_HighTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/*****/
-										/* s */
-										/*****/
-
-									case 3:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(ul_HighTiming
-											*
-											(250000.0
-												*
-												b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-											ul_HighTimerValue
-												=
-												ul_HighTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealHighTiming
-											=
-											(unsigned int)
-											(ul_HighTimerValue
-											/
-											(250000.0
-												*
-												(double)
-												b_ClockSelection));
-										d_RealHighTiming
-											=
-											(double)
-											ul_HighTimerValue
-											/
-											(250000.0
-											*
-											(double)
-											b_ClockSelection);
-
-										if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
-											*pul_RealHighTiming
-												=
-												*pul_RealHighTiming
-												+
-												1;
-										}
-
-										ul_HighTiming
-											=
-											ul_HighTiming
-											-
-											1;
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_HighTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_HighTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-
-										/******/
-										/* mn */
-										/******/
-
-									case 4:
-
-										/******************/
-										/* Timer 0 factor */
-										/******************/
-
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(
-											(ul_HighTiming
-												*
-												60)
-											*
-											(250000.0
-												*
-												b_ClockSelection));
-
-										/*******************/
-										/* Round the value */
-										/*******************/
-
-										if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-											ul_HighTimerValue
-												=
-												ul_HighTimerValue
-												+
-												1;
-										}
-
-										/*****************************/
-										/* Calculate the real timing */
-										/*****************************/
-
-										*pul_RealHighTiming
-											=
-											(unsigned int)
-											(ul_HighTimerValue
-											/
-											(250000.0
-												*
-												(double)
-												b_ClockSelection))
-											/
-											60;
-										d_RealHighTiming
-											=
-											(
-											(double)
-											ul_HighTimerValue
-											/
-											(250000.0
-												*
-												(double)
-												b_ClockSelection))
-											/
-											60.0;
-
-										if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealHighTiming + 0.5)) {
-											*pul_RealHighTiming
-												=
-												*pul_RealHighTiming
-												+
-												1;
-										}
-
-										ul_HighTiming
-											=
-											ul_HighTiming
-											-
-											1;
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											-
-											2;
-
-										if (b_ClockSelection != APCI1710_40MHZ) {
-											ul_HighTimerValue
-												=
-												(unsigned int)
-												(
-												(double)
-												(ul_HighTimerValue)
-												*
-												1.007752288);
-										}
-
-										break;
-									}
-
-									fpu_end();
-									/****************************/
-									/* Save the clock selection */
-									/****************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										b_ClockSelection
-										=
-										b_ClockSelection;
-
-									/************************/
-									/* Save the timing unit */
-									/************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										s_PWMInfo
-										[b_PWM].
-										b_TimingUnit
-										=
-										b_TimingUnit;
-
-									/****************************/
-									/* Save the low base timing */
-									/****************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										s_PWMInfo
-										[b_PWM].
-										d_LowTiming
-										=
-										d_RealLowTiming;
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										s_PWMInfo
-										[b_PWM].
-										ul_RealLowTiming
-										=
-										*pul_RealLowTiming;
-
-									/****************************/
-									/* Save the high base timing */
-									/****************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										s_PWMInfo
-										[b_PWM].
-										d_HighTiming
-										=
-										d_RealHighTiming;
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										s_PWMInfo
-										[b_PWM].
-										ul_RealHighTiming
-										=
-										*pul_RealHighTiming;
-
-									/************************/
-									/* Write the low timing */
-									/************************/
-
-									outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
-
-									/*************************/
-									/* Write the high timing */
-									/*************************/
-
-									outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
-
-									/***************************/
-									/* Set the clock selection */
-									/***************************/
-
-									dw_Command
-										=
-										inl
-										(devpriv->
-										s_BoardInfos.
-										ui_Address
-										+
-										8
-										+
-										(20 * b_PWM) + (64 * b_ModulNbr));
-
-									dw_Command
-										=
-										dw_Command
-										&
-										0x7F;
-
-									if (b_ClockSelection == APCI1710_40MHZ) {
-										dw_Command
-											=
-											dw_Command
-											|
-											0x80;
-									}
-
-									/***************************/
-									/* Set the clock selection */
-									/***************************/
-
-									outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
-
-									/*************/
-									/* PWM init. */
-									/*************/
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_PWMModuleInfo.
-										s_PWMInfo
-										[b_PWM].
-										b_PWMInit
-										=
-										1;
-								} else {
-									/***************************************************/
-									/* You can not used the 40MHz clock selection with */
-									/* this board                                      */
-									/***************************************************/
-									DPRINTK("You can not used the 40MHz clock selection with this board\n");
-									i_ReturnValue
-										=
-										-9;
-								}
-							} else {
-								/***************************************/
-								/* High base timing selection is wrong */
-								/***************************************/
-								DPRINTK("High base timing selection is wrong\n");
-								i_ReturnValue =
-									-8;
-							}
-						} else {
-							/**************************************/
-							/* Low base timing selection is wrong */
-							/**************************************/
-							DPRINTK("Low base timing selection is wrong\n");
-							i_ReturnValue = -7;
-						}
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-					else {
-						/**********************************/
-						/* Timing unit selection is wrong */
-						/**********************************/
-						DPRINTK("Timing unit selection is wrong\n");
-						i_ReturnValue = -6;
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-				}	/*  if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) */
-				else {
-					/*******************************/
-					/* The selected clock is wrong */
-					/*******************************/
-					DPRINTK("The selected clock is wrong\n");
-					i_ReturnValue = -5;
-				}	/*  if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) */
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-			else {
-				/******************************/
-				/* Tor PWM selection is wrong */
-				/******************************/
-				DPRINTK("Tor PWM selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-		} else {
-			/**********************************/
-			/* The module is not a PWM module */
-			/**********************************/
-			DPRINTK("The module is not a PWM module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-		/***********************/
-		/* Module number error */
-		/***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetPWMInitialisation                  |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_PWM,                    |
-|                                        unsigned char *_   pb_TimingUnit,             |
-|                                        PULONG_ pul_LowTiming,              |
-|                                        PULONG_ pul_HighTiming,             |
-|                                        unsigned char *_   pb_StartLevel,             |
-|                                        unsigned char *_   pb_StopMode,               |
-|                                        unsigned char *_   pb_StopLevel,              |
-|                                        unsigned char *_   pb_ExternGate,             |
-|                                        unsigned char *_   pb_InterruptEnable,        |
-|                                        unsigned char *_   pb_Enable)                 |
-+----------------------------------------------------------------------------+
-| Task              : Return the PWM (b_PWM) initialisation from selected    |
-|                     module (b_ModulNbr). You must calling the              |
-|                     "i_APCI1710_InitPWM" function be for you call this     |
-|                     function.                                              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
-|                     unsigned char_ b_ModulNbr    : Selected module number (0 to 3)  |
-|                     unsigned char_ b_PWM         : Selected PWM (0 or 1)            |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_  pb_TimingUnit      : Base timing Unit (0 to 4) |
-|                                                       0 : ns               |
-|                                                       1 : æs               |
-|                                                       2 : ms               |
-|                                                       3 : s                |
-|                                                       4 : mn               |
-|                     PULONG_ pul_LowTiming      : Low base timing value.    |
-|                     PULONG_ pul_HighTiming     : High base timing value.   |
-|                     unsigned char *_  pb_StartLevel      : Start period level        |
-|                                                  selection                 |
-|                                                       0 : The period start |
-|                                                           with a low level |
-|                                                       1 : The period start |
-|                                                           with a high level|
-|                     unsigned char *_  pb_StopMode        : Stop mode selection       |
-|                                                  0 : The PWM is stopped    |
-|                                                      directly after the    |
-|                                                     "i_APCI1710_DisablePWM"|
-|                                                      function and break the|
-|                                                      last period           |
-|                                                  1 : After the             |
-|                                                     "i_APCI1710_DisablePWM"|
-|                                                      function the PWM is   |
-|                                                      stopped at the end    |
-|                                                      from last period cycle|
-|                     unsigned char *_  pb_StopLevel        : Stop PWM level selection |
-|                                                    0 : The output signal   |
-|                                                        keep the level after|
-|                                                        the                 |
-|                                                     "i_APCI1710_DisablePWM"|
-|                                                        function            |
-|                                                    1 : The output signal is|
-|                                                        set to low after the|
-|                                                     "i_APCI1710_DisablePWM"|
-|                                                        function            |
-|                                                    2 : The output signal is|
-|                                                        set to high after   |
-|                                                        the                 |
-|                                                     "i_APCI1710_DisablePWM"|
-|                                                        function            |
-|                     unsigned char *_  pb_ExternGate      : Extern gate action        |
-|                                                  selection                 |
-|                                                   0 : Extern gate signal   |
-|                                                       not used.            |
-|                                                   1 : Extern gate signal   |
-|                                                       used.                |
-|                     unsigned char *_  pb_InterruptEnable : Enable or disable the PWM |
-|                                                  interrupt.                |
-|                                                  - APCI1710_ENABLE :       |
-|                                                    Enable the PWM interrupt|
-|                                                    A interrupt occur after |
-|                                                    each period             |
-|                                                  - APCI1710_DISABLE :      |
-|                                                    Disable the PWM         |
-|                                                    interrupt               |
-|                     unsigned char *_  pb_Enable          : Indicate if the PWM is    |
-|                                                  enabled or no             |
-|                                                       0 : PWM not enabled  |
-|                                                       1 : PWM enabled      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a PWM module                     |
-|                     -4: PWM selection is wrong                             |
-|                     -5: PWM not initialised see function                   |
-|                         "i_APCI1710_InitPWM"                               |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
-					   unsigned char b_ModulNbr,
-					   unsigned char b_PWM,
-					   unsigned char *pb_TimingUnit,
-					   unsigned int *pul_LowTiming,
-					   unsigned int *pul_HighTiming,
-					   unsigned char *pb_StartLevel,
-					   unsigned char *pb_StopMode,
-					   unsigned char *pb_StopLevel,
-					   unsigned char *pb_ExternGate,
-					   unsigned char *pb_InterruptEnable,
-					   unsigned char *pb_Enable)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned int dw_Command;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***************/
-		/* Test if PWM */
-		/***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			/**************************/
-			/* Test the PWM selection */
-			/**************************/
-
-			if (b_PWM <= 1) {
-				/***************************/
-				/* Test if PWM initialised */
-				/***************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (20 * b_PWM) +
-					(64 * b_ModulNbr));
-
-				if (dw_Status & 0x10) {
-					/***********************/
-					/* Read the low timing */
-					/***********************/
-
-					*pul_LowTiming =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 0 + (20 * b_PWM) +
-						(64 * b_ModulNbr));
-
-					/************************/
-					/* Read the high timing */
-					/************************/
-
-					*pul_HighTiming =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 4 + (20 * b_PWM) +
-						(64 * b_ModulNbr));
-
-					/********************/
-					/* Read the command */
-					/********************/
-
-					dw_Command = inl(devpriv->s_BoardInfos.
-						ui_Address + 8 + (20 * b_PWM) +
-						(64 * b_ModulNbr));
-
-					*pb_StartLevel =
-						(unsigned char) ((dw_Command >> 5) & 1);
-					*pb_StopMode =
-						(unsigned char) ((dw_Command >> 0) & 1);
-					*pb_StopLevel =
-						(unsigned char) ((dw_Command >> 1) & 1);
-					*pb_ExternGate =
-						(unsigned char) ((dw_Command >> 4) & 1);
-					*pb_InterruptEnable =
-						(unsigned char) ((dw_Command >> 3) & 1);
-
-					if (*pb_StopLevel) {
-						*pb_StopLevel =
-							*pb_StopLevel +
-							(unsigned char) ((dw_Command >>
-								2) & 1);
-					}
-
-					/********************/
-					/* Read the command */
-					/********************/
-
-					dw_Command = inl(devpriv->s_BoardInfos.
-						ui_Address + 8 + (20 * b_PWM) +
-						(64 * b_ModulNbr));
-
-					*pb_Enable =
-						(unsigned char) ((dw_Command >> 0) & 1);
-
-					*pb_TimingUnit = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_PWMModuleInfo.
-						s_PWMInfo[b_PWM].b_TimingUnit;
-				}	/*  if (dw_Status & 0x10) */
-				else {
-					/***********************/
-					/* PWM not initialised */
-					/***********************/
-					DPRINTK("PWM not initialised\n");
-					i_ReturnValue = -5;
-				}	/*  if (dw_Status & 0x10) */
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-			else {
-				/******************************/
-				/* Tor PWM selection is wrong */
-				/******************************/
-				DPRINTK("Tor PWM selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-		} else {
-			/**********************************/
-			/* The module is not a PWM module */
-			/**********************************/
-			DPRINTK("The module is not a PWM module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-		/***********************/
-		/* Module number error */
-		/***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
- * Pwm Init and Get Pwm Initialisation
- */
-static int i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data)
-{
-	unsigned char b_ConfigType;
-	int i_ReturnValue = 0;
-	b_ConfigType = CR_CHAN(insn->chanspec);
-
-	switch (b_ConfigType) {
-	case APCI1710_PWM_INIT:
-		i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec),	/*   b_ModulNbr */
-			(unsigned char) data[0],	/* b_PWM */
-			(unsigned char) data[1],	/*  b_ClockSelection */
-			(unsigned char) data[2],	/*  b_TimingUnit */
-			(unsigned int) data[3],	/* ul_LowTiming */
-			(unsigned int) data[4],	/* ul_HighTiming */
-			(unsigned int *) &data[0],	/* pul_RealLowTiming */
-			(unsigned int *) &data[1]	/* pul_RealHighTiming */
-			);
-		break;
-
-	case APCI1710_PWM_GETINITDATA:
-		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	/*  b_ModulNbr */
-			(unsigned char) data[0],	/* b_PWM */
-			(unsigned char *) &data[0],	/* pb_TimingUnit */
-			(unsigned int *) &data[1],	/* pul_LowTiming */
-			(unsigned int *) &data[2],	/* pul_HighTiming */
-			(unsigned char *) &data[3],	/*  pb_StartLevel */
-			(unsigned char *) &data[4],	/*  pb_StopMode */
-			(unsigned char *) &data[5],	/*  pb_StopLevel */
-			(unsigned char *) &data[6],	/*  pb_ExternGate */
-			(unsigned char *) &data[7],	/*  pb_InterruptEnable */
-			(unsigned char *) &data[8]	/*  pb_Enable */
-			);
-		break;
-
-	default:
-		printk(" Config Parameter Wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_EnablePWM                         |
-|                                       (unsigned char_  b_BoardHandle,               |
-|                                        unsigned char_  b_ModulNbr,                  |
-|                                        unsigned char_  b_PWM,                       |
-|                                        unsigned char_  b_StartLevel,                |
-|                                        unsigned char_  b_StopMode,                  |
-|                                        unsigned char_  b_StopLevel,                 |
-|                                        unsigned char_  b_ExternGate,                |
-|                                        unsigned char_  b_InterruptEnable)           |
-+----------------------------------------------------------------------------+
-| Task              : Enable the selected PWM (b_PWM) from selected module   |
-|                     (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"|
-|                     function be for you call this function.                |
-|                     If you enable the PWM interrupt, the PWM generate a    |
-|                     interrupt after each period.                           |
-|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
-|                     Interrupt mask description chapter.                    |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
-|                     unsigned char_ b_ModulNbr        : Selected module number       |
-|                                               (0 to 3)                     |
-|                     unsigned char_ b_PWM             : Selected PWM (0 or 1)        |
-|                     unsigned char_ b_StartLevel      : Start period level selection |
-|                                                0 : The period start with a |
-|                                                    low level               |
-|                                                1 : The period start with a |
-|                                                    high level              |
-|                     unsigned char_ b_StopMode        : Stop mode selection          |
-|                                                0 : The PWM is stopped      |
-|                                                    directly after the      |
-|                                                    "i_APCI1710_DisablePWM" |
-|                                                    function and break the  |
-|                                                    last period             |
-|                                                1 : After the               |
-|                                                    "i_APCI1710_DisablePWM" |
-|                                                     function the PWM is    |
-|                                                     stopped at the end from|
-|                                                     last period cycle.     |
-|                     unsigned char_ b_StopLevel       : Stop PWM level selection     |
-|                                                0 : The output signal keep  |
-|                                                    the level after the     |
-|                                                    "i_APCI1710_DisablePWM" |
-|                                                    function                |
-|                                                1 : The output signal is set|
-|                                                    to low after the        |
-|                                                    "i_APCI1710_DisablePWM" |
-|                                                    function                |
-|                                                2 : The output signal is set|
-|                                                    to high after the       |
-|                                                    "i_APCI1710_DisablePWM" |
-|                                                    function                |
-|                     unsigned char_ b_ExternGate      : Extern gate action selection |
-|                                                0 : Extern gate signal not  |
-|                                                    used.                   |
-|                                                1 : Extern gate signal used.|
-|                     unsigned char_ b_InterruptEnable : Enable or disable the PWM    |
-|                                               interrupt.                   |
-|                                               - APCI1710_ENABLE :          |
-|                                                 Enable the PWM interrupt   |
-|                                                 A interrupt occur after    |
-|                                                 each period                |
-|                                               - APCI1710_DISABLE :         |
-|                                                 Disable the PWM interrupt  |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0:  No error                                           |
-|                    -1:  The handle parameter of the board is wrong         |
-|                    -2:  Module selection wrong                             |
-|                    -3:  The module is not a PWM module                     |
-|                    -4:  PWM selection is wrong                             |
-|                    -5:  PWM not initialised see function                   |
-|                         "i_APCI1710_InitPWM"                               |
-|                    -6:  PWM start level selection is wrong                 |
-|                    -7:  PWM stop mode selection is wrong                   |
-|                    -8:  PWM stop level selection is wrong                  |
-|                    -9:  Extern gate signal selection is wrong              |
-|                    -10: Interrupt parameter is wrong                       |
-|                    -11: Interrupt function not initialised.                |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_EnablePWM(struct comedi_device *dev,
-				unsigned char b_ModulNbr,
-				unsigned char b_PWM,
-				unsigned char b_StartLevel,
-				unsigned char b_StopMode,
-				unsigned char b_StopLevel,
-				unsigned char b_ExternGate,
-				unsigned char b_InterruptEnable)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned int dw_Command;
-
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***************/
-		/* Test if PWM */
-		/***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			/**************************/
-			/* Test the PWM selection */
-			/**************************/
-
-			if (b_PWM <= 1) {
-				/***************************/
-				/* Test if PWM initialised */
-				/***************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (20 * b_PWM) +
-					(64 * b_ModulNbr));
-
-				if (dw_Status & 0x10) {
-					/**********************************/
-					/* Test the start level selection */
-					/**********************************/
-
-					if (b_StartLevel <= 1) {
-						/**********************/
-						/* Test the stop mode */
-						/**********************/
-
-						if (b_StopMode <= 1) {
-							/***********************/
-							/* Test the stop level */
-							/***********************/
-
-							if (b_StopLevel <= 2) {
-								/*****************************/
-								/* Test the extern gate mode */
-								/*****************************/
-
-								if (b_ExternGate
-									<= 1) {
-									/*****************************/
-									/* Test the interrupt action */
-									/*****************************/
-
-									if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) {
-										/******************************************/
-										/* Test if interrupt function initialised */
-										/******************************************/
-
-										/********************/
-										/* Read the command */
-										/********************/
-
-										dw_Command
-											=
-											inl
-											(devpriv->
-											s_BoardInfos.
-											ui_Address
-											+
-											8
-											+
-											(20 * b_PWM) + (64 * b_ModulNbr));
-
-										dw_Command
-											=
-											dw_Command
-											&
-											0x80;
-
-										/********************/
-										/* Make the command */
-										/********************/
-
-										dw_Command
-											=
-											dw_Command
-											|
-											b_StopMode
-											|
-											(b_InterruptEnable
-											<<
-											3)
-											|
-											(b_ExternGate
-											<<
-											4)
-											|
-											(b_StartLevel
-											<<
-											5);
-
-										if (b_StopLevel & 3) {
-											dw_Command
-												=
-												dw_Command
-												|
-												2;
-
-											if (b_StopLevel & 2) {
-												dw_Command
-													=
-													dw_Command
-													|
-													4;
-											}
-										}
-
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_PWMModuleInfo.
-											s_PWMInfo
-											[b_PWM].
-											b_InterruptEnable
-											=
-											b_InterruptEnable;
-
-										/*******************/
-										/* Set the command */
-										/*******************/
-
-										outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
-
-										/******************/
-										/* Enable the PWM */
-										/******************/
-										outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr));
-									}	/*  if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) */
-									else {
-										/********************************/
-										/* Interrupt parameter is wrong */
-										/********************************/
-										DPRINTK("Interrupt parameter is wrong\n");
-										i_ReturnValue
-											=
-											-10;
-									}	/*  if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) */
-								}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
-								else {
-									/*****************************************/
-									/* Extern gate signal selection is wrong */
-									/*****************************************/
-									DPRINTK("Extern gate signal selection is wrong\n");
-									i_ReturnValue
-										=
-										-9;
-								}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
-							}	/*  if (b_StopLevel >= 0 && b_StopLevel <= 2) */
-							else {
-								/*************************************/
-								/* PWM stop level selection is wrong */
-								/*************************************/
-								DPRINTK("PWM stop level selection is wrong\n");
-								i_ReturnValue =
-									-8;
-							}	/*  if (b_StopLevel >= 0 && b_StopLevel <= 2) */
-						}	/*  if (b_StopMode >= 0 && b_StopMode <= 1) */
-						else {
-							/************************************/
-							/* PWM stop mode selection is wrong */
-							/************************************/
-							DPRINTK("PWM stop mode selection is wrong\n");
-							i_ReturnValue = -7;
-						}	/*  if (b_StopMode >= 0 && b_StopMode <= 1) */
-					}	/*  if (b_StartLevel >= 0 && b_StartLevel <= 1) */
-					else {
-						/**************************************/
-						/* PWM start level selection is wrong */
-						/**************************************/
-						DPRINTK("PWM start level selection is wrong\n");
-						i_ReturnValue = -6;
-					}	/*  if (b_StartLevel >= 0 && b_StartLevel <= 1) */
-				}	/*  if (dw_Status & 0x10) */
-				else {
-					/***********************/
-					/* PWM not initialised */
-					/***********************/
-					DPRINTK("PWM not initialised\n");
-					i_ReturnValue = -5;
-				}	/*  if (dw_Status & 0x10) */
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-			else {
-				/******************************/
-				/* Tor PWM selection is wrong */
-				/******************************/
-				DPRINTK("Tor PWM selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-		} else {
-			/**********************************/
-			/* The module is not a PWM module */
-			/**********************************/
-			DPRINTK("The module is not a PWM module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-		/***********************/
-		/* Module number error */
-		/***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_DisablePWM (unsigned char_  b_BoardHandle,     |
-|                                                  unsigned char_  b_ModulNbr,        |
-|                                                  unsigned char_  b_PWM)             |
-+----------------------------------------------------------------------------+
-| Task              : Disable the selected PWM (b_PWM) from selected module  |
-|                     (b_ModulNbr). The output signal level depend of the    |
-|                     initialisation by the "i_APCI1710_EnablePWM".          |
-|                     See the b_StartLevel, b_StopMode and b_StopLevel       |
-|                     parameters from this function.                         |
-+----------------------------------------------------------------------------+
-| Input Parameters  :BYTE_ b_BoardHandle : Handle of board APCI-1710         |
-|                    unsigned char_ b_ModulNbr    : Selected module number (0 to 3)   |
-|                    unsigned char_ b_PWM         : Selected PWM (0 or 1)             |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a PWM module                     |
-|                     -4: PWM selection is wrong                             |
-|                     -5: PWM not initialised see function                   |
-|                         "i_APCI1710_InitPWM"                               |
-|                     -6: PWM not enabled see function                       |
-|                         "i_APCI1710_EnablePWM"                             |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_DisablePWM(struct comedi_device *dev,
-				 unsigned char b_ModulNbr,
-				 unsigned char b_PWM)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***************/
-		/* Test if PWM */
-		/***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			/**************************/
-			/* Test the PWM selection */
-			/**************************/
-
-			if (b_PWM <= 1) {
-				/***************************/
-				/* Test if PWM initialised */
-				/***************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (20 * b_PWM) +
-					(64 * b_ModulNbr));
-
-				if (dw_Status & 0x10) {
-					/***********************/
-					/* Test if PWM enabled */
-					/***********************/
-
-					if (dw_Status & 0x1) {
-						/*******************/
-						/* Disable the PWM */
-						/*******************/
-						outl(0, devpriv->s_BoardInfos.
-							ui_Address + 12 +
-							(20 * b_PWM) +
-							(64 * b_ModulNbr));
-					}	/*  if (dw_Status & 0x1) */
-					else {
-						/*******************/
-						/* PWM not enabled */
-						/*******************/
-						DPRINTK("PWM not enabled\n");
-						i_ReturnValue = -6;
-					}	/*  if (dw_Status & 0x1) */
-				}	/*  if (dw_Status & 0x10) */
-				else {
-					/***********************/
-					/* PWM not initialised */
-					/***********************/
-					DPRINTK(" PWM not initialised\n");
-					i_ReturnValue = -5;
-				}	/*  if (dw_Status & 0x10) */
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-			else {
-				/******************************/
-				/* Tor PWM selection is wrong */
-				/******************************/
-				DPRINTK("Tor PWM selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-		} else {
-			/**********************************/
-			/* The module is not a PWM module */
-			/**********************************/
-			DPRINTK("The module is not a PWM module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-		/***********************/
-		/* Module number error */
-		/***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_SetNewPWMTiming                       |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_PWM,                    |
-|                                        unsigned char_     b_ClockSelection,         |
-|                                        unsigned char_     b_TimingUnit,             |
-|                                        ULONG_   ul_LowTiming,              |
-|                                        ULONG_   ul_HighTiming)             |
-+----------------------------------------------------------------------------+
-| Task              : Set a new timing. The ul_LowTiming, ul_HighTiming and  |
-|                     ul_TimingUnit determine the low/high timing base for   |
-|                     the period.                                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_     b_BoardHandle    : Handle of board APCI-1710 |
-|                     unsigned char_     b_ModulNbr       : Module number to configure|
-|                                                  (0 to 3)                  |
-|                     unsigned char_     b_PWM            : Selected PWM (0 or 1).    |
-|                     unsigned char_     b_TimingUnit     : Base timing Unit (0 to 4) |
-|                                                       0 : ns               |
-|                                                       1 : æs               |
-|                                                       2 : ms               |
-|                                                       3 : s                |
-|                                                       4 : mn               |
-|                     ULONG_    ul_LowTiming     : Low base timing value.    |
-|                     ULONG_    ul_HighTiming    : High base timing value.   |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: Module selection wrong                              |
-|                    -3: The module is not a PWM module                      |
-|                    -4: PWM selection is wrong                              |
-|                    -5: PWM not initialised                                 |
-|                    -6: Timing Unit selection is wrong                      |
-|                    -7: Low base timing selection is wrong                  |
-|                    -8: High base timing selection is wrong                 |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
-				      unsigned char b_ModulNbr,
-				      unsigned char b_PWM,
-				      unsigned char b_TimingUnit,
-				      unsigned int ul_LowTiming,
-				      unsigned int ul_HighTiming)
-{
-	struct addi_private *devpriv = dev->private;
-	unsigned char b_ClockSelection;
-	int i_ReturnValue = 0;
-	unsigned int ul_LowTimerValue = 0;
-	unsigned int ul_HighTimerValue = 0;
-	unsigned int ul_RealLowTiming = 0;
-	unsigned int ul_RealHighTiming = 0;
-	unsigned int dw_Status;
-	unsigned int dw_Command;
-	double d_RealLowTiming = 0;
-	double d_RealHighTiming = 0;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***************/
-		/* Test if PWM */
-		/***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			/**************************/
-			/* Test the PWM selection */
-			/**************************/
-
-			if (b_PWM <= 1) {
-				/***************************/
-				/* Test if PWM initialised */
-				/***************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (20 * b_PWM) +
-					(64 * b_ModulNbr));
-
-				if (dw_Status & 0x10) {
-					b_ClockSelection = devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_PWMModuleInfo.
-						b_ClockSelection;
-
-					/************************/
-					/* Test the timing unit */
-					/************************/
-
-					if (b_TimingUnit <= 4) {
-						/*********************************/
-						/* Test the low timing selection */
-						/*********************************/
-
-						if (((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 0)
-								&& (ul_LowTiming
-									>= 266)
-								&& (ul_LowTiming
-									<=
-									0xFFFFFFFFUL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 1)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									571230650UL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 2)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									571230UL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 3)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									571UL))
-							|| ((b_ClockSelection ==
-									APCI1710_30MHZ)
-								&& (b_TimingUnit
-									== 4)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<= 9UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 0)
-								&& (ul_LowTiming
-									>= 242)
-								&& (ul_LowTiming
-									<=
-									0xFFFFFFFFUL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 1)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									519691043UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 2)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									519691UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 3)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									520UL))
-							|| ((b_ClockSelection ==
-									APCI1710_33MHZ)
-								&& (b_TimingUnit
-									== 4)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<= 8UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 0)
-								&& (ul_LowTiming
-									>= 200)
-								&& (ul_LowTiming
-									<=
-									0xFFFFFFFFUL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 1)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									429496729UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 2)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									429496UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 3)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									429UL))
-							|| ((b_ClockSelection ==
-									APCI1710_40MHZ)
-								&& (b_TimingUnit
-									== 4)
-								&& (ul_LowTiming
-									>= 1)
-								&& (ul_LowTiming
-									<=
-									7UL))) {
-							/**********************************/
-							/* Test the High timing selection */
-							/**********************************/
-
-							if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
-								/************************************/
-								/* Calculate the low division fator */
-								/************************************/
-
-								fpu_begin();
-								switch (b_TimingUnit) {
-									/******/
-									/* ns */
-									/******/
-
-								case 0:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_LowTimerValue
-										=
-										(unsigned int)
-										(ul_LowTiming
-										*
-										(0.00025 * b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealLowTiming
-										=
-										(unsigned int)
-										(ul_LowTimerValue
-										/
-										(0.00025 * (double)b_ClockSelection));
-									d_RealLowTiming
-										=
-										(double)
-										ul_LowTimerValue
-										/
-										(0.00025
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
-										ul_RealLowTiming
-											=
-											ul_RealLowTiming
-											+
-											1;
-									}
-
-									ul_LowTiming
-										=
-										ul_LowTiming
-										-
-										1;
-									ul_LowTimerValue
-										=
-										ul_LowTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_LowTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/******/
-									/* æs */
-									/******/
-
-								case 1:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_LowTimerValue
-										=
-										(unsigned int)
-										(ul_LowTiming
-										*
-										(0.25 * b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealLowTiming
-										=
-										(unsigned int)
-										(ul_LowTimerValue
-										/
-										(0.25 * (double)b_ClockSelection));
-									d_RealLowTiming
-										=
-										(double)
-										ul_LowTimerValue
-										/
-										(
-										(double)
-										0.25
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
-										ul_RealLowTiming
-											=
-											ul_RealLowTiming
-											+
-											1;
-									}
-
-									ul_LowTiming
-										=
-										ul_LowTiming
-										-
-										1;
-									ul_LowTimerValue
-										=
-										ul_LowTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_LowTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/******/
-									/* ms */
-									/******/
-
-								case 2:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_LowTimerValue
-										=
-										ul_LowTiming
-										*
-										(250.0
-										*
-										b_ClockSelection);
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealLowTiming
-										=
-										(unsigned int)
-										(ul_LowTimerValue
-										/
-										(250.0 * (double)b_ClockSelection));
-									d_RealLowTiming
-										=
-										(double)
-										ul_LowTimerValue
-										/
-										(250.0
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
-										ul_RealLowTiming
-											=
-											ul_RealLowTiming
-											+
-											1;
-									}
-
-									ul_LowTiming
-										=
-										ul_LowTiming
-										-
-										1;
-									ul_LowTimerValue
-										=
-										ul_LowTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_LowTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/*****/
-									/* s */
-									/*****/
-
-								case 3:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_LowTimerValue
-										=
-										(unsigned int)
-										(ul_LowTiming
-										*
-										(250000.0
-											*
-											b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealLowTiming
-										=
-										(unsigned int)
-										(ul_LowTimerValue
-										/
-										(250000.0
-											*
-											(double)
-											b_ClockSelection));
-									d_RealLowTiming
-										=
-										(double)
-										ul_LowTimerValue
-										/
-										(250000.0
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
-										ul_RealLowTiming
-											=
-											ul_RealLowTiming
-											+
-											1;
-									}
-
-									ul_LowTiming
-										=
-										ul_LowTiming
-										-
-										1;
-									ul_LowTimerValue
-										=
-										ul_LowTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_LowTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/******/
-									/* mn */
-									/******/
-
-								case 4:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_LowTimerValue
-										=
-										(unsigned int)
-										(
-										(ul_LowTiming
-											*
-											60)
-										*
-										(250000.0
-											*
-											b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
-										ul_LowTimerValue
-											=
-											ul_LowTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealLowTiming
-										=
-										(unsigned int)
-										(ul_LowTimerValue
-										/
-										(250000.0
-											*
-											(double)
-											b_ClockSelection))
-										/
-										60;
-									d_RealLowTiming
-										=
-										(
-										(double)
-										ul_LowTimerValue
-										/
-										(250000.0
-											*
-											(double)
-											b_ClockSelection))
-										/
-										60.0;
-
-									if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealLowTiming + 0.5)) {
-										ul_RealLowTiming
-											=
-											ul_RealLowTiming
-											+
-											1;
-									}
-
-									ul_LowTiming
-										=
-										ul_LowTiming
-										-
-										1;
-									ul_LowTimerValue
-										=
-										ul_LowTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_LowTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_LowTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-								}
-
-								/*************************************/
-								/* Calculate the high division fator */
-								/*************************************/
-
-								switch (b_TimingUnit) {
-									/******/
-									/* ns */
-									/******/
-
-								case 0:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_HighTimerValue
-										=
-										(unsigned int)
-										(ul_HighTiming
-										*
-										(0.00025 * b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealHighTiming
-										=
-										(unsigned int)
-										(ul_HighTimerValue
-										/
-										(0.00025 * (double)b_ClockSelection));
-									d_RealHighTiming
-										=
-										(double)
-										ul_HighTimerValue
-										/
-										(0.00025
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
-										ul_RealHighTiming
-											=
-											ul_RealHighTiming
-											+
-											1;
-									}
-
-									ul_HighTiming
-										=
-										ul_HighTiming
-										-
-										1;
-									ul_HighTimerValue
-										=
-										ul_HighTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_HighTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/******/
-									/* æs */
-									/******/
-
-								case 1:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_HighTimerValue
-										=
-										(unsigned int)
-										(ul_HighTiming
-										*
-										(0.25 * b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealHighTiming
-										=
-										(unsigned int)
-										(ul_HighTimerValue
-										/
-										(0.25 * (double)b_ClockSelection));
-									d_RealHighTiming
-										=
-										(double)
-										ul_HighTimerValue
-										/
-										(
-										(double)
-										0.25
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
-										ul_RealHighTiming
-											=
-											ul_RealHighTiming
-											+
-											1;
-									}
-
-									ul_HighTiming
-										=
-										ul_HighTiming
-										-
-										1;
-									ul_HighTimerValue
-										=
-										ul_HighTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_HighTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/******/
-									/* ms */
-									/******/
-
-								case 2:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_HighTimerValue
-										=
-										ul_HighTiming
-										*
-										(250.0
-										*
-										b_ClockSelection);
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealHighTiming
-										=
-										(unsigned int)
-										(ul_HighTimerValue
-										/
-										(250.0 * (double)b_ClockSelection));
-									d_RealHighTiming
-										=
-										(double)
-										ul_HighTimerValue
-										/
-										(250.0
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
-										ul_RealHighTiming
-											=
-											ul_RealHighTiming
-											+
-											1;
-									}
-
-									ul_HighTiming
-										=
-										ul_HighTiming
-										-
-										1;
-									ul_HighTimerValue
-										=
-										ul_HighTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_HighTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/*****/
-									/* s */
-									/*****/
-
-								case 3:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_HighTimerValue
-										=
-										(unsigned int)
-										(ul_HighTiming
-										*
-										(250000.0
-											*
-											b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealHighTiming
-										=
-										(unsigned int)
-										(ul_HighTimerValue
-										/
-										(250000.0
-											*
-											(double)
-											b_ClockSelection));
-									d_RealHighTiming
-										=
-										(double)
-										ul_HighTimerValue
-										/
-										(250000.0
-										*
-										(double)
-										b_ClockSelection);
-
-									if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
-										ul_RealHighTiming
-											=
-											ul_RealHighTiming
-											+
-											1;
-									}
-
-									ul_HighTiming
-										=
-										ul_HighTiming
-										-
-										1;
-									ul_HighTimerValue
-										=
-										ul_HighTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_HighTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-
-									/******/
-									/* mn */
-									/******/
-
-								case 4:
-
-									/******************/
-									/* Timer 0 factor */
-									/******************/
-
-									ul_HighTimerValue
-										=
-										(unsigned int)
-										(
-										(ul_HighTiming
-											*
-											60)
-										*
-										(250000.0
-											*
-											b_ClockSelection));
-
-									/*******************/
-									/* Round the value */
-									/*******************/
-
-									if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
-										ul_HighTimerValue
-											=
-											ul_HighTimerValue
-											+
-											1;
-									}
-
-									/*****************************/
-									/* Calculate the real timing */
-									/*****************************/
-
-									ul_RealHighTiming
-										=
-										(unsigned int)
-										(ul_HighTimerValue
-										/
-										(250000.0
-											*
-											(double)
-											b_ClockSelection))
-										/
-										60;
-									d_RealHighTiming
-										=
-										(
-										(double)
-										ul_HighTimerValue
-										/
-										(250000.0
-											*
-											(double)
-											b_ClockSelection))
-										/
-										60.0;
-
-									if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealHighTiming + 0.5)) {
-										ul_RealHighTiming
-											=
-											ul_RealHighTiming
-											+
-											1;
-									}
-
-									ul_HighTiming
-										=
-										ul_HighTiming
-										-
-										1;
-									ul_HighTimerValue
-										=
-										ul_HighTimerValue
-										-
-										2;
-
-									if (b_ClockSelection != APCI1710_40MHZ) {
-										ul_HighTimerValue
-											=
-											(unsigned int)
-											(
-											(double)
-											(ul_HighTimerValue)
-											*
-											1.007752288);
-									}
-
-									break;
-								}
-
-								fpu_end();
-
-								/************************/
-								/* Save the timing unit */
-								/************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PWMModuleInfo.
-									s_PWMInfo
-									[b_PWM].
-									b_TimingUnit
-									=
-									b_TimingUnit;
-
-								/****************************/
-								/* Save the low base timing */
-								/****************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PWMModuleInfo.
-									s_PWMInfo
-									[b_PWM].
-									d_LowTiming
-									=
-									d_RealLowTiming;
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PWMModuleInfo.
-									s_PWMInfo
-									[b_PWM].
-									ul_RealLowTiming
-									=
-									ul_RealLowTiming;
-
-								/****************************/
-								/* Save the high base timing */
-								/****************************/
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PWMModuleInfo.
-									s_PWMInfo
-									[b_PWM].
-									d_HighTiming
-									=
-									d_RealHighTiming;
-
-								devpriv->
-									s_ModuleInfo
-									[b_ModulNbr].
-									s_PWMModuleInfo.
-									s_PWMInfo
-									[b_PWM].
-									ul_RealHighTiming
-									=
-									ul_RealHighTiming;
-
-								/************************/
-								/* Write the low timing */
-								/************************/
-
-								outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
-
-								/*************************/
-								/* Write the high timing */
-								/*************************/
-
-								outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
-
-								/***************************/
-								/* Set the clock selection */
-								/***************************/
-
-								dw_Command =
-									inl
-									(devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 8 +
-									(20 * b_PWM) + (64 * b_ModulNbr));
-
-								dw_Command =
-									dw_Command
-									& 0x7F;
-
-								if (b_ClockSelection == APCI1710_40MHZ) {
-									dw_Command
-										=
-										dw_Command
-										|
-										0x80;
-								}
-
-								/***************************/
-								/* Set the clock selection */
-								/***************************/
-
-								outl(dw_Command,
-									devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 8 +
-									(20 * b_PWM) + (64 * b_ModulNbr));
-							} else {
-								/***************************************/
-								/* High base timing selection is wrong */
-								/***************************************/
-								DPRINTK("High base timing selection is wrong\n");
-								i_ReturnValue =
-									-8;
-							}
-						} else {
-							/**************************************/
-							/* Low base timing selection is wrong */
-							/**************************************/
-							DPRINTK("Low base timing selection is wrong\n");
-							i_ReturnValue = -7;
-						}
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-					else {
-						/**********************************/
-						/* Timing unit selection is wrong */
-						/**********************************/
-						DPRINTK("Timing unit selection is wrong\n");
-						i_ReturnValue = -6;
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-				}	/*  if (dw_Status & 0x10) */
-				else {
-					/***********************/
-					/* PWM not initialised */
-					/***********************/
-					DPRINTK("PWM not initialised\n");
-					i_ReturnValue = -5;
-				}	/*  if (dw_Status & 0x10) */
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-			else {
-				/******************************/
-				/* Tor PWM selection is wrong */
-				/******************************/
-				DPRINTK("Tor PWM selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-		} else {
-			/**********************************/
-			/* The module is not a PWM module */
-			/**********************************/
-			DPRINTK("The module is not a PWM module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-		/***********************/
-		/* Module number error */
-		/***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
- * Pwm Enable Disable and Set New Timing
- */
-static int i_APCI1710_InsnWritePWM(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn,
-				   unsigned int *data)
-{
-	unsigned char b_WriteType;
-	int i_ReturnValue = 0;
-	b_WriteType = CR_CHAN(insn->chanspec);
-
-	switch (b_WriteType) {
-	case APCI1710_PWM_ENABLE:
-		i_ReturnValue = i_APCI1710_EnablePWM(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1],
-			(unsigned char) data[2],
-			(unsigned char) data[3], (unsigned char) data[4], (unsigned char) data[5]);
-		break;
-
-	case APCI1710_PWM_DISABLE:
-		i_ReturnValue = i_APCI1710_DisablePWM(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_PWM_NEWTIMING:
-		i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1], (unsigned int) data[2], (unsigned int) data[3]);
-		break;
-
-	default:
-		printk("Write Config Parameter Wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetPWMStatus                          |
-|                               (unsigned char_    b_BoardHandle,                     |
-|                                unsigned char_    b_ModulNbr,                        |
-|                                unsigned char_    b_PWM,                             |
-|                                unsigned char *_  pb_PWMOutputStatus,                 |
-|                                unsigned char *_  pb_ExternGateStatus)                |
-+----------------------------------------------------------------------------+
-| Task              : Return the status from selected PWM (b_PWM) from       |
-|                     selected module (b_ModulNbr).                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_  b_BoardHandle : Handle of board APCI-1710       |
-|                     unsigned char_  b_PWM         : Selected PWM (0 or 1)           |
-|                     unsigned char_  b_ModulNbr    : Selected module number (0 to 3)
-	b_ModulNbr			=(unsigned char)  CR_AREF(insn->chanspec);
-	b_PWM				=(unsigned char)  data[0];
-
- |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_  pb_PWMOutputStatus  : Return the PWM output    |
-|                                                   level status.            |
-|                                                    0 : The PWM output level|
-|                                                        is low.             |
-|                                                    1 : The PWM output level|
-|                                                        is high.            |
-|                     unsigned char *_  pb_ExternGateStatus : Return the extern gate   |
-|                                                   level status.            |
-|                                                    0 : The extern gate is  |
-|                                                        low.                |
-|                                                    1 : The extern gate is  |
-|                                                        high.
-    pb_PWMOutputStatus	=(unsigned char *) data[0];
-	pb_ExternGateStatus =(unsigned char *) data[1];             |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a PWM module                     |
-|                     -4: PWM selection is wrong                             |
-|                     -5: PWM not initialised see function                   |
-|                         "i_APCI1710_InitPWM"                               |
-|                     -6: PWM not enabled see function "i_APCI1710_EnablePWM"|
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn,
-					   unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned char b_ModulNbr;
-	unsigned char b_PWM;
-	unsigned char *pb_PWMOutputStatus;
-	unsigned char *pb_ExternGateStatus;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_PWM = (unsigned char) CR_CHAN(insn->chanspec);
-	pb_PWMOutputStatus = (unsigned char *) &data[0];
-	pb_ExternGateStatus = (unsigned char *) &data[1];
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***************/
-		/* Test if PWM */
-		/***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			/**************************/
-			/* Test the PWM selection */
-			/**************************/
-
-			if (b_PWM <= 1) {
-				/***************************/
-				/* Test if PWM initialised */
-				/***************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 12 + (20 * b_PWM) +
-					(64 * b_ModulNbr));
-
-				if (dw_Status & 0x10) {
-					/***********************/
-					/* Test if PWM enabled */
-					/***********************/
-
-					if (dw_Status & 0x1) {
-						*pb_PWMOutputStatus =
-							(unsigned char) ((dw_Status >> 7)
-							& 1);
-						*pb_ExternGateStatus =
-							(unsigned char) ((dw_Status >> 6)
-							& 1);
-					}	/*  if (dw_Status & 0x1) */
-					else {
-						/*******************/
-						/* PWM not enabled */
-						/*******************/
-
-						DPRINTK("PWM not enabled \n");
-						i_ReturnValue = -6;
-					}	/*  if (dw_Status & 0x1) */
-				}	/*  if (dw_Status & 0x10) */
-				else {
-					/***********************/
-					/* PWM not initialised */
-					/***********************/
-
-					DPRINTK("PWM not initialised\n");
-					i_ReturnValue = -5;
-				}	/*  if (dw_Status & 0x10) */
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-			else {
-				/******************************/
-				/* Tor PWM selection is wrong */
-				/******************************/
-
-				DPRINTK("Tor PWM selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
-		} else {
-			/**********************************/
-			/* The module is not a PWM module */
-			/**********************************/
-
-			DPRINTK("The module is not a PWM module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-		/***********************/
-		/* Module number error */
-		/***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-static int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
-					       struct comedi_subdevice *s,
-					       struct comedi_insn *insn,
-					       unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-
-	data[0] = devpriv->s_InterruptParameters.
-		s_FIFOInterruptParameters[devpriv->
-		s_InterruptParameters.ui_Read].b_OldModuleMask;
-	data[1] = devpriv->s_InterruptParameters.
-		s_FIFOInterruptParameters[devpriv->
-		s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-	data[2] = devpriv->s_InterruptParameters.
-		s_FIFOInterruptParameters[devpriv->
-		s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-	/**************************/
-	/* Increment the read FIFO */
-	/***************************/
-
-	devpriv->
-		s_InterruptParameters.
-		ui_Read = (devpriv->
-		s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-
-	return insn->n;
-
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
deleted file mode 100644
index 6ef1d6a..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : SSI.C           | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 SSI counter module                          |
-  +-----------------------------------------------------------------------+
-  | several changes done by S. Weber in 1998 and C. Guinot in 2000        |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_30MHZ			30
-#define APCI1710_33MHZ			33
-#define APCI1710_40MHZ			40
-
-#define APCI1710_BINARY_MODE		0x1
-#define APCI1710_GRAY_MODE		0x0
-
-#define APCI1710_SSI_READ1VALUE		1
-#define APCI1710_SSI_READALLVALUE	2
-
-#define APCI1710_SSI_SET_CHANNELON	0
-#define APCI1710_SSI_SET_CHANNELOFF	1
-#define APCI1710_SSI_READ_1CHANNEL	2
-#define APCI1710_SSI_READ_ALLCHANNEL	3
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitSSI                               |
-|                               (unsigned char_    b_BoardHandle,                     |
-|                                unsigned char_    b_ModulNbr,                        |
-|                                unsigned char_    b_SSIProfile,                      |
-|                                unsigned char_    b_PositionTurnLength,              |
-|                                unsigned char_    b_TurnCptLength,                   |
-|                                unsigned char_    b_PCIInputClock,                   |
-|                                ULONG_  ul_SSIOutputClock,                  |
-|                                unsigned char_    b_SSICountingMode)                 |
-+----------------------------------------------------------------------------+
-| Task              : Configure the SSI operating mode from selected module  |
-|                     (b_ModulNbr). You must calling this function be for you|
-|                     call any other function witch access of SSI.           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 3)       |
-|                     unsigned char_  b_SSIProfile         : Selection from SSI       |
-|                                                   profile length (2 to 32).|
-|                     unsigned char_  b_PositionTurnLength : Selection from SSI       |
-|                                                   position data length     |
-|                                                   (1 to 31).               |
-|                     unsigned char_  b_TurnCptLength      : Selection from SSI turn  |
-|                                                   counter data length      |
-|                                                   (1 to 31).               |
-|                     unsigned char   b_PCIInputClock      : Selection from PCI bus   |
-|                                                   clock                    |
-|                                                 - APCI1710_30MHZ :         |
-|                                                   The PC have a PCI bus    |
-|                                                   clock from 30 MHz        |
-|                                                 - APCI1710_33MHZ :         |
-|                                                   The PC have a PCI bus    |
-|                                                   clock from 33 MHz        |
-|                     ULONG_ ul_SSIOutputClock    : Selection from SSI output|
-|                                                   clock.                   |
-|                                                   From  229 to 5 000 000 Hz|
-|                                                   for 30 MHz selection.    |
-|                                                   From  252 to 5 000 000 Hz|
-|                                                   for 33 MHz selection.    |
-|                     unsigned char   b_SSICountingMode    : SSI counting mode        |
-|                                                   selection                |
-|                                                 - APCI1710_BINARY_MODE :   |
-|                                                    Binary counting mode.   |
-|                                                 - APCI1710_GRAY_MODE :     |
-|                                                    Gray counting mode.
-
-	b_ModulNbr			= CR_AREF(insn->chanspec);
-	b_SSIProfile		= (unsigned char) data[0];
-	b_PositionTurnLength= (unsigned char) data[1];
-	b_TurnCptLength		= (unsigned char) data[2];
-	b_PCIInputClock		= (unsigned char) data[3];
-	ul_SSIOutputClock	= (unsigned int) data[4];
-	b_SSICountingMode	= (unsigned char)  data[5];     |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a SSI module                      |
-|                    -4: The selected SSI profile length is wrong            |
-|                    -5: The selected SSI position data length is wrong      |
-|                    -6: The selected SSI turn counter data length is wrong  |
-|                    -7: The selected PCI input clock is wrong               |
-|                    -8: The selected SSI output clock is wrong              |
-|                    -9: The selected SSI counting mode parameter is wrong   |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn,
-					unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ui_TimerValue;
-	unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
-		b_PCIInputClock, b_SSICountingMode;
-	unsigned int ul_SSIOutputClock;
-
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_SSIProfile = (unsigned char) data[0];
-	b_PositionTurnLength = (unsigned char) data[1];
-	b_TurnCptLength = (unsigned char) data[2];
-	b_PCIInputClock = (unsigned char) data[3];
-	ul_SSIOutputClock = (unsigned int) data[4];
-	b_SSICountingMode = (unsigned char) data[5];
-
-	i_ReturnValue = insn->n;
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if SSI counter */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
-	      /*******************************/
-			/* Test the SSI profile length */
-	      /*******************************/
-
-			/*  CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */
-			if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
-		 /*************************************/
-				/* Test the SSI position data length */
-		 /*************************************/
-
-				if (b_PositionTurnLength > 0
-					&& b_PositionTurnLength < 32) {
-		    /*****************************************/
-					/* Test the SSI turn counter data length */
-		    /*****************************************/
-
-					if (b_TurnCptLength > 0
-						&& b_TurnCptLength < 32) {
-		       /***************************/
-						/* Test the profile length */
-		       /***************************/
-
-						if ((b_TurnCptLength +
-								b_PositionTurnLength)
-							<= b_SSIProfile) {
-			  /****************************/
-							/* Test the PCI input clock */
-			  /****************************/
-
-							if (b_PCIInputClock ==
-								APCI1710_30MHZ
-								||
-								b_PCIInputClock
-								==
-								APCI1710_33MHZ)
-							{
-			     /*************************/
-								/* Test the output clock */
-			     /*************************/
-
-								if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
-									if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
-				   /**********************/
-										/* Save configuration */
-				   /**********************/
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_SSICounterInfo.
-											b_SSIProfile
-											=
-											b_SSIProfile;
-
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_SSICounterInfo.
-											b_PositionTurnLength
-											=
-											b_PositionTurnLength;
-
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_SSICounterInfo.
-											b_TurnCptLength
-											=
-											b_TurnCptLength;
-
-				   /*********************************/
-										/* Initialise the profile length */
-				   /*********************************/
-
-										if (b_SSICountingMode == APCI1710_BINARY_MODE) {
-
-											outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
-										} else {
-
-											outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
-										}
-
-				   /******************************/
-										/* Calculate the output clock */
-				   /******************************/
-
-										ui_TimerValue
-											=
-											(unsigned int)
-											(
-											((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
-
-				   /************************/
-										/* Initialise the timer */
-				   /************************/
-
-										outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
-
-				   /********************************/
-										/* Initialise the counting mode */
-				   /********************************/
-
-										outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
-
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_SSICounterInfo.
-											b_SSIInit
-											=
-											1;
-									} else {
-				   /*****************************************************/
-										/* The selected SSI counting mode parameter is wrong */
-				   /*****************************************************/
-
-										DPRINTK("The selected SSI counting mode parameter is wrong\n");
-										i_ReturnValue
-											=
-											-9;
-									}
-								} else {
-				/******************************************/
-									/* The selected SSI output clock is wrong */
-				/******************************************/
-
-									DPRINTK("The selected SSI output clock is wrong\n");
-									i_ReturnValue
-										=
-										-8;
-								}
-							} else {
-			     /*****************************************/
-								/* The selected PCI input clock is wrong */
-			     /*****************************************/
-
-								DPRINTK("The selected PCI input clock is wrong\n");
-								i_ReturnValue =
-									-7;
-							}
-						} else {
-			  /********************************************/
-							/* The selected SSI profile length is wrong */
-			  /********************************************/
-
-							DPRINTK("The selected SSI profile length is wrong\n");
-							i_ReturnValue = -4;
-						}
-					} else {
-		       /******************************************************/
-						/* The selected SSI turn counter data length is wrong */
-		       /******************************************************/
-
-						DPRINTK("The selected SSI turn counter data length is wrong\n");
-						i_ReturnValue = -6;
-					}
-				} else {
-		    /**************************************************/
-					/* The selected SSI position data length is wrong */
-		    /**************************************************/
-
-					DPRINTK("The selected SSI position data length is wrong\n");
-					i_ReturnValue = -5;
-				}
-			} else {
-		 /********************************************/
-				/* The selected SSI profile length is wrong */
-		 /********************************************/
-
-				DPRINTK("The selected SSI profile length is wrong\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /**********************************/
-			/* The module is not a SSI module */
-	      /**********************************/
-
-			DPRINTK("The module is not a SSI module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_  i_APCI1710_Read1SSIValue                        |
-|                               (unsigned char_     b_BoardHandle,                    |
-|                                unsigned char_     b_ModulNbr,                       |
-|                                unsigned char_     b_SelectedSSI,                    |
-|                                PULONG_ pul_Position,                       |
-|                                PULONG_ pul_TurnCpt)
- int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
-	struct comedi_insn *insn,unsigned int *data)                       |
-+----------------------------------------------------------------------------+
-| Task              :
-
-
-						Read the selected SSI counter (b_SelectedSSI) from     |
-|                     selected module (b_ModulNbr).
-						or Read all SSI counter (b_SelectedSSI) from              |
-|                     selected module (b_ModulNbr).                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 3)       |
-|                     unsigned char_ b_SelectedSSI         : Selection from SSI       |
-|                                                   counter (0 to 2)
-
-    b_ModulNbr		=   (unsigned char) CR_AREF(insn->chanspec);
-	b_SelectedSSI	=	(unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
-	b_ReadType		=	(unsigned char) CR_RANGE(insn->chanspec);
-|
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pul_Position       : SSI position in the turn |
-|                     PULONG_  pul_TurnCpt        : Number of turns
-
-pul_Position	=	(unsigned int *) &data[0];
-	pul_TurnCpt		=	(unsigned int *) &data[1];         |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a SSI module                      |
-|                    -4: SSI not initialised see function                    |
-|                        "i_APCI1710_InitSSI"                                |
-|                    -5: The selected SSI is wrong                           |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev,
-				       struct comedi_subdevice *s,
-				       struct comedi_insn *insn,
-				       unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_Cpt;
-	unsigned char b_Length;
-	unsigned char b_Schift;
-	unsigned char b_SSICpt;
-	unsigned int dw_And;
-	unsigned int dw_And1;
-	unsigned int dw_And2;
-	unsigned int dw_StatusReg;
-	unsigned int dw_CounterValue;
-	unsigned char b_ModulNbr;
-	unsigned char b_SelectedSSI;
-	unsigned char b_ReadType;
-	unsigned int *pul_Position;
-	unsigned int *pul_TurnCpt;
-	unsigned int *pul_Position1;
-	unsigned int *pul_TurnCpt1;
-
-	i_ReturnValue = insn->n;
-	pul_Position1 = (unsigned int *) &data[0];
-/* For Read1 */
-	pul_TurnCpt1 = (unsigned int *) &data[1];
-/* For Read all */
-	pul_Position = (unsigned int *) &data[0];	/* 0-2 */
-	pul_TurnCpt = (unsigned int *) &data[3];	/* 3-5 */
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
-	b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if SSI counter */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
-	      /***************************/
-			/* Test if SSI initialised */
-	      /***************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_SSICounterInfo.b_SSIInit == 1) {
-
-				switch (b_ReadType) {
-
-				case APCI1710_SSI_READ1VALUE:
-		 /****************************************/
-					/* Test the selected SSI counter number */
-		 /****************************************/
-
-					if (b_SelectedSSI < 3) {
-		    /************************/
-						/* Start the conversion */
-		    /************************/
-
-						outl(0, devpriv->s_BoardInfos.
-							ui_Address + 8 +
-							(64 * b_ModulNbr));
-
-						do {
-		       /*******************/
-							/* Read the status */
-		       /*******************/
-
-							dw_StatusReg =
-								inl(devpriv->
-								s_BoardInfos.
-								ui_Address +
-								(64 * b_ModulNbr));
-						} while ((dw_StatusReg & 0x1)
-							 != 0);
-
-		    /******************************/
-						/* Read the SSI counter value */
-		    /******************************/
-
-						dw_CounterValue =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 4 +
-							(b_SelectedSSI * 4) +
-							(64 * b_ModulNbr));
-
-						b_Length =
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_SSIProfile / 2;
-
-						if ((b_Length * 2) !=
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_SSIProfile) {
-							b_Length++;
-						}
-
-						b_Schift =
-							b_Length -
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_PositionTurnLength;
-
-						*pul_Position1 =
-							dw_CounterValue >>
-							b_Schift;
-
-						dw_And = 1;
-
-						for (b_Cpt = 0;
-							b_Cpt <
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_PositionTurnLength;
-							b_Cpt++) {
-							dw_And = dw_And * 2;
-						}
-
-						*pul_Position1 =
-							*pul_Position1 &
-							((dw_And) - 1);
-
-						*pul_TurnCpt1 =
-							dw_CounterValue >>
-							b_Length;
-
-						dw_And = 1;
-
-						for (b_Cpt = 0;
-							b_Cpt <
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_TurnCptLength;
-							b_Cpt++) {
-							dw_And = dw_And * 2;
-						}
-
-						*pul_TurnCpt1 =
-							*pul_TurnCpt1 &
-							((dw_And) - 1);
-					} else {
-		    /*****************************/
-						/* The selected SSI is wrong */
-		    /*****************************/
-
-						DPRINTK("The selected SSI is wrong\n");
-						i_ReturnValue = -5;
-					}
-					break;
-
-				case APCI1710_SSI_READALLVALUE:
-					dw_And1 = 1;
-
-					for (b_Cpt = 0;
-						b_Cpt <
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SSICounterInfo.
-						b_PositionTurnLength; b_Cpt++) {
-						dw_And1 = dw_And1 * 2;
-					}
-
-					dw_And2 = 1;
-
-					for (b_Cpt = 0;
-						b_Cpt <
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_SSICounterInfo.
-						b_TurnCptLength; b_Cpt++) {
-						dw_And2 = dw_And2 * 2;
-					}
-
-		 /************************/
-					/* Start the conversion */
-		 /************************/
-
-					outl(0, devpriv->s_BoardInfos.
-						ui_Address + 8 +
-						(64 * b_ModulNbr));
-
-					do {
-		    /*******************/
-						/* Read the status */
-		    /*******************/
-
-						dw_StatusReg =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address +
-							(64 * b_ModulNbr));
-					} while ((dw_StatusReg & 0x1) != 0);
-
-					for (b_SSICpt = 0; b_SSICpt < 3;
-						b_SSICpt++) {
-		    /******************************/
-						/* Read the SSI counter value */
-		    /******************************/
-
-						dw_CounterValue =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 4 +
-							(b_SSICpt * 4) +
-							(64 * b_ModulNbr));
-
-						b_Length =
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_SSIProfile / 2;
-
-						if ((b_Length * 2) !=
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_SSIProfile) {
-							b_Length++;
-						}
-
-						b_Schift =
-							b_Length -
-							devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_SSICounterInfo.
-							b_PositionTurnLength;
-
-						pul_Position[b_SSICpt] =
-							dw_CounterValue >>
-							b_Schift;
-						pul_Position[b_SSICpt] =
-							pul_Position[b_SSICpt] &
-							((dw_And1) - 1);
-
-						pul_TurnCpt[b_SSICpt] =
-							dw_CounterValue >>
-							b_Length;
-						pul_TurnCpt[b_SSICpt] =
-							pul_TurnCpt[b_SSICpt] &
-							((dw_And2) - 1);
-					}
-					break;
-
-				default:
-					printk("Read Type Inputs Wrong\n");
-
-				}	/*  switch  ending */
-
-			} else {
-		 /***********************/
-				/* SSI not initialised */
-		 /***********************/
-
-				DPRINTK("SSI not initialised\n");
-				i_ReturnValue = -4;
-			}
-		} else {
-	      /**********************************/
-			/* The module is not a SSI module */
-	      /**********************************/
-
-			DPRINTK("The module is not a SSI module\n");
-			i_ReturnValue = -3;
-
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_   i_APCI1710_ReadSSI1DigitalInput                |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_InputChannel,           |
-|                                        unsigned char *_   pb_ChannelStatus)          |
-+----------------------------------------------------------------------------+
-| Task              :
-					(0) Set the digital output from selected SSI module         |
-|                     (b_ModuleNbr) ON
-                    (1) Set the digital output from selected SSI module         |
-|                     (b_ModuleNbr) OFF
-					(2)Read the status from selected SSI digital input        |
-|                     (b_InputChannel)
-                    (3)Read the status from all SSI digital inputs from       |
-|                     selected SSI module (b_ModulNbr)                   |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr    CR_AREF        : Module number to         |
-|                                                   configure (0 to 3)       |
-|                     unsigned char_ b_InputChannel CR_CHAN       : Selection from digital   |
-|                        data[0] which IOTYPE                           input ( 0 to 2)          |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_  pb_ChannelStatus    : Digital input channel    |
-|                                 data[0]                  status                   |
-|                                                   0 : Channle is not active|
-|                                                   1 : Channle is active    |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a SSI module                      |
-|                    -4: The selected SSI digital input is wrong             |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn,
-					   unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg;
-	unsigned char b_ModulNbr;
-	unsigned char b_InputChannel;
-	unsigned char *pb_ChannelStatus;
-	unsigned char *pb_InputStatus;
-	unsigned char b_IOType;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_IOType = (unsigned char) data[0];
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if SSI counter */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
-			switch (b_IOType) {
-			case APCI1710_SSI_SET_CHANNELON:
-					/*****************************/
-				/* Set the digital output ON */
-					/*****************************/
-
-				outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
-					(64 * b_ModulNbr));
-				break;
-
-			case APCI1710_SSI_SET_CHANNELOFF:
-					/******************************/
-				/* Set the digital output OFF */
-					/******************************/
-
-				outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
-					(64 * b_ModulNbr));
-				break;
-
-			case APCI1710_SSI_READ_1CHANNEL:
-				   /******************************************/
-				/* Test the digital imnput channel number */
-				   /******************************************/
-
-				b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
-				pb_ChannelStatus = (unsigned char *) &data[0];
-
-				if (b_InputChannel <= 2) {
-					/**************************/
-					/* Read all digital input */
-					/**************************/
-
-					dw_StatusReg =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + (64 * b_ModulNbr));
-					*pb_ChannelStatus =
-						(unsigned char) (((~dw_StatusReg) >> (4 +
-								b_InputChannel))
-						& 1);
-				} else {
-					/********************************/
-					/* Selected digital input error */
-					/********************************/
-
-					DPRINTK("Selected digital input error\n");
-					i_ReturnValue = -4;
-				}
-				break;
-
-			case APCI1710_SSI_READ_ALLCHANNEL:
-					/**************************/
-				/* Read all digital input */
-					/**************************/
-				pb_InputStatus = (unsigned char *) &data[0];
-
-				dw_StatusReg =
-					inl(devpriv->s_BoardInfos.ui_Address +
-					(64 * b_ModulNbr));
-				*pb_InputStatus =
-					(unsigned char) (((~dw_StatusReg) >> 4) & 7);
-				break;
-
-			default:
-				printk("IO type wrong\n");
-
-			}	/* switch end */
-		} else {
-	      /**********************************/
-			/* The module is not a SSI module */
-	      /**********************************/
-
-			DPRINTK("The module is not a SSI module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
deleted file mode 100644
index 0b79531..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+++ /dev/null
@@ -1,2065 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : TOR.C           | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 tor counter module                          |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  | 27/01/99 | S. Weber  | 40 MHz implementation                          |
-  +-----------------------------------------------------------------------+
-  | 28/04/00 | S. Weber  | Simple,double and quadruple mode implementation|
-  |          |           | Extern clock implementation                    |
-  +-----------------------------------------------------------------------+
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_30MHZ			30
-#define APCI1710_33MHZ			33
-#define APCI1710_40MHZ			40
-
-#define APCI1710_GATE_INPUT		10
-
-#define APCI1710_TOR_SIMPLE_MODE	2
-#define APCI1710_TOR_DOUBLE_MODE	3
-#define APCI1710_TOR_QUADRUPLE_MODE	4
-
-#define APCI1710_SINGLE			0
-#define APCI1710_CONTINUOUS		1
-
-#define APCI1710_TOR_GETPROGRESSSTATUS	0
-#define APCI1710_TOR_GETCOUNTERVALUE	1
-#define APCI1710_TOR_READINTERRUPT	2
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_     i_APCI1710_InitTorCounter                    |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_TorCounter,             |
-|                                        unsigned char_     b_PCIInputClock,          |
-|                                        unsigned char_     b_TimingUnit,             |
-|                                        ULONG_   ul_TimingInterval,         |
-|                                        PULONG_ pul_RealTimingInterval)     |
-+----------------------------------------------------------------------------+
-| Task              : Configure the selected tor counter (b_TorCounter)      |
-|                     from selected module (b_ModulNbr).                     |
-|                     The ul_TimingInterval and ul_TimingUnit determine the  |
-|                     timing base for the measurement.                       |
-|                     The pul_RealTimingInterval return the real timing      |
-|                     value. You must calling this function be for you call  |
-|                     any other function witch access of the tor counter.    |
-|                                                                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  :    |
-|
-		CR_AREF	unsigned char_   b_ModulNbr       : Module number to configure  |
-|                                                (0 to 3)                    |
-|           data[0] unsigned char_   b_TorCounter     : Tor counter selection       |
-|                                                (0 or 1).                   |
-|           data[1] unsigned char_   b_PCIInputClock  : Selection from PCI bus clock|
-|                                                - APCI1710_30MHZ :          |
-|                                                  The PC have a PCI bus     |
-|                                                  clock from 30 MHz         |
-|                                                - APCI1710_33MHZ :          |
-|                                                  The PC have a PCI bus     |
-|                                                  clock from 33 MHz         |
-|                                                - APCI1710_40MHZ            |
-|                                                  The APCI-1710 have a      |
-|                                                  integrated 40Mhz          |
-|                                                  quartz.                   |
-|                                                - APCI1710_GATE_INPUT       |
-|                                                  Used the gate input for   |
-|						   the base clock. If you    |
-|						   have selected this option,|
-|						   than it is not possibl to |
-|						   used the gate input for   |
-|						   enabled the acquisition   |
-|           data[2] unsigned char_   b_TimingUnit    : Base timing unit (0 to 4)    |
-|                                                 0 : ns                     |
-|                                                 1 : µs                     |
-|                                                 2 : ms                     |
-|                                                 3 : s                      |
-|                                                 4 : mn                     |
-|           data[3]          ULONG_ ul_TimingInterval : Base timing value.          |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |
-|                     data[0]                                  value.               |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a tor counter module             |
-|                     -4: Tor counter selection is wrong                     |
-|                     -5: The selected PCI input clock is wrong              |
-|                     -6: Timing unit selection is wrong                     |
-|                     -7: Base timing selection is wrong                     |
-|                     -8: You can not used the 40MHz clock selection wich    |
-|                         this board                                         |
-|                     -9: You can not used the 40MHz clock selection wich    |
-|                         this TOR version                                   |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
-					       struct comedi_subdevice *s,
-					       struct comedi_insn *insn,
-					       unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int ul_TimerValue = 0;
-	unsigned int dw_Command;
-	double d_RealTimingInterval = 0;
-	unsigned char b_ModulNbr;
-	unsigned char b_TorCounter;
-	unsigned char b_PCIInputClock;
-	unsigned char b_TimingUnit;
-	unsigned int ul_TimingInterval;
-	unsigned int ul_RealTimingInterval = 0;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-
-	b_TorCounter = (unsigned char) data[0];
-	b_PCIInputClock = (unsigned char) data[1];
-	b_TimingUnit = (unsigned char) data[2];
-	ul_TimingInterval = (unsigned int) data[3];
-	printk("INPUT clock %d\n", b_PCIInputClock);
-
-		/**************************/
-	/* Test the module number */
-		/**************************/
-
-	if (b_ModulNbr < 4) {
-		/***********************/
-		/* Test if tor counter */
-		/***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
-	      /**********************************/
-			/* Test the tor counter selection */
-	      /**********************************/
-
-			if (b_TorCounter <= 1) {
-		 /**************************/
-				/* Test the PCI bus clock */
-		 /**************************/
-
-				if ((b_PCIInputClock == APCI1710_30MHZ) ||
-					(b_PCIInputClock == APCI1710_33MHZ) ||
-					(b_PCIInputClock == APCI1710_40MHZ) ||
-					(b_PCIInputClock ==
-						APCI1710_GATE_INPUT)) {
-		    /************************/
-					/* Test the timing unit */
-		    /************************/
-
-					if ((b_TimingUnit <= 4)
-						|| (b_PCIInputClock ==
-							APCI1710_GATE_INPUT)) {
-		       /**********************************/
-						/* Test the base timing selection */
-		       /**********************************/
-
-						if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 133) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230650UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 9UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 121) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691043UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 520UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 8UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 100) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496729UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 7UL)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && (ul_TimingInterval >= 2))) {
-				/**************************/
-							/* Test the board version */
-				/**************************/
-
-							if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
-			     /************************/
-								/* Test the TOR version */
-			     /************************/
-
-								if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3132)) || (b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) {
-				/*********************************/
-									/* Test if not extern clock used */
-				/*********************************/
-
-									if (b_PCIInputClock != APCI1710_GATE_INPUT) {
-										fpu_begin
-											();
-				   /****************************************/
-										/* Calculate the timer 0 division fator */
-				   /****************************************/
-
-										switch (b_TimingUnit) {
-				      /******/
-											/* ns */
-				      /******/
-
-										case 0:
-
-					      /******************/
-											/* Timer 0 factor */
-					      /******************/
-
-											ul_TimerValue
-												=
-												(unsigned int)
-												(ul_TimingInterval
-												*
-												(0.00025 * b_PCIInputClock));
-
-					      /*******************/
-											/* Round the value */
-					      /*******************/
-
-											if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-												ul_TimerValue
-													=
-													ul_TimerValue
-													+
-													1;
-											}
-
-					      /*****************************/
-											/* Calculate the real timing */
-					      /*****************************/
-
-											ul_RealTimingInterval
-												=
-												(unsigned int)
-												(ul_TimerValue
-												/
-												(0.00025 * (double)b_PCIInputClock));
-											d_RealTimingInterval
-												=
-												(double)
-												ul_TimerValue
-												/
-												(0.00025
-												*
-												(double)
-												b_PCIInputClock);
-
-											if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-												ul_RealTimingInterval
-													=
-													ul_RealTimingInterval
-													+
-													1;
-											}
-
-											ul_TimingInterval
-												=
-												ul_TimingInterval
-												-
-												1;
-											ul_TimerValue
-												=
-												ul_TimerValue
-												-
-												2;
-
-											if (b_PCIInputClock != APCI1710_40MHZ) {
-												ul_TimerValue
-													=
-													(unsigned int)
-													(
-													(double)
-													(ul_TimerValue)
-													*
-													1.007752288);
-											}
-
-											break;
-
-				      /******/
-											/* æs */
-				      /******/
-
-										case 1:
-
-					      /******************/
-											/* Timer 0 factor */
-					      /******************/
-
-											ul_TimerValue
-												=
-												(unsigned int)
-												(ul_TimingInterval
-												*
-												(0.25 * b_PCIInputClock));
-
-					      /*******************/
-											/* Round the value */
-					      /*******************/
-
-											if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-												ul_TimerValue
-													=
-													ul_TimerValue
-													+
-													1;
-											}
-
-					      /*****************************/
-											/* Calculate the real timing */
-					      /*****************************/
-
-											ul_RealTimingInterval
-												=
-												(unsigned int)
-												(ul_TimerValue
-												/
-												(0.25 * (double)b_PCIInputClock));
-											d_RealTimingInterval
-												=
-												(double)
-												ul_TimerValue
-												/
-												(
-												(double)
-												0.25
-												*
-												(double)
-												b_PCIInputClock);
-
-											if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-												ul_RealTimingInterval
-													=
-													ul_RealTimingInterval
-													+
-													1;
-											}
-
-											ul_TimingInterval
-												=
-												ul_TimingInterval
-												-
-												1;
-											ul_TimerValue
-												=
-												ul_TimerValue
-												-
-												2;
-
-											if (b_PCIInputClock != APCI1710_40MHZ) {
-												ul_TimerValue
-													=
-													(unsigned int)
-													(
-													(double)
-													(ul_TimerValue)
-													*
-													1.007752288);
-											}
-
-											break;
-
-				      /******/
-											/* ms */
-				      /******/
-
-										case 2:
-
-					      /******************/
-											/* Timer 0 factor */
-					      /******************/
-
-											ul_TimerValue
-												=
-												ul_TimingInterval
-												*
-												(250.0
-												*
-												b_PCIInputClock);
-
-					      /*******************/
-											/* Round the value */
-					      /*******************/
-
-											if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-												ul_TimerValue
-													=
-													ul_TimerValue
-													+
-													1;
-											}
-
-					      /*****************************/
-											/* Calculate the real timing */
-					      /*****************************/
-
-											ul_RealTimingInterval
-												=
-												(unsigned int)
-												(ul_TimerValue
-												/
-												(250.0 * (double)b_PCIInputClock));
-											d_RealTimingInterval
-												=
-												(double)
-												ul_TimerValue
-												/
-												(250.0
-												*
-												(double)
-												b_PCIInputClock);
-
-											if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-												ul_RealTimingInterval
-													=
-													ul_RealTimingInterval
-													+
-													1;
-											}
-
-											ul_TimingInterval
-												=
-												ul_TimingInterval
-												-
-												1;
-											ul_TimerValue
-												=
-												ul_TimerValue
-												-
-												2;
-
-											if (b_PCIInputClock != APCI1710_40MHZ) {
-												ul_TimerValue
-													=
-													(unsigned int)
-													(
-													(double)
-													(ul_TimerValue)
-													*
-													1.007752288);
-											}
-
-											break;
-
-				      /*****/
-											/* s */
-				      /*****/
-
-										case 3:
-
-					      /******************/
-											/* Timer 0 factor */
-					      /******************/
-
-											ul_TimerValue
-												=
-												(unsigned int)
-												(ul_TimingInterval
-												*
-												(250000.0
-													*
-													b_PCIInputClock));
-
-					      /*******************/
-											/* Round the value */
-					      /*******************/
-
-											if ((double)((double)ul_TimingInterval * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-												ul_TimerValue
-													=
-													ul_TimerValue
-													+
-													1;
-											}
-
-					      /*****************************/
-											/* Calculate the real timing */
-					      /*****************************/
-
-											ul_RealTimingInterval
-												=
-												(unsigned int)
-												(ul_TimerValue
-												/
-												(250000.0
-													*
-													(double)
-													b_PCIInputClock));
-											d_RealTimingInterval
-												=
-												(double)
-												ul_TimerValue
-												/
-												(250000.0
-												*
-												(double)
-												b_PCIInputClock);
-
-											if ((double)((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-												ul_RealTimingInterval
-													=
-													ul_RealTimingInterval
-													+
-													1;
-											}
-
-											ul_TimingInterval
-												=
-												ul_TimingInterval
-												-
-												1;
-											ul_TimerValue
-												=
-												ul_TimerValue
-												-
-												2;
-
-											if (b_PCIInputClock != APCI1710_40MHZ) {
-												ul_TimerValue
-													=
-													(unsigned int)
-													(
-													(double)
-													(ul_TimerValue)
-													*
-													1.007752288);
-											}
-
-											break;
-
-				      /******/
-											/* mn */
-				      /******/
-
-										case 4:
-
-					      /******************/
-											/* Timer 0 factor */
-					      /******************/
-
-											ul_TimerValue
-												=
-												(unsigned int)
-												(
-												(ul_TimingInterval
-													*
-													60)
-												*
-												(250000.0
-													*
-													b_PCIInputClock));
-
-					      /*******************/
-											/* Round the value */
-					      /*******************/
-
-											if ((double)((double)(ul_TimingInterval * 60.0) * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
-												ul_TimerValue
-													=
-													ul_TimerValue
-													+
-													1;
-											}
-
-					      /*****************************/
-											/* Calculate the real timing */
-					      /*****************************/
-
-											ul_RealTimingInterval
-												=
-												(unsigned int)
-												(ul_TimerValue
-												/
-												(250000.0
-													*
-													(double)
-													b_PCIInputClock))
-												/
-												60;
-											d_RealTimingInterval
-												=
-												(
-												(double)
-												ul_TimerValue
-												/
-												(250000.0
-													*
-													(double)
-													b_PCIInputClock))
-												/
-												60.0;
-
-											if ((double)(((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
-												ul_RealTimingInterval
-													=
-													ul_RealTimingInterval
-													+
-													1;
-											}
-
-											ul_TimingInterval
-												=
-												ul_TimingInterval
-												-
-												1;
-											ul_TimerValue
-												=
-												ul_TimerValue
-												-
-												2;
-
-											if (b_PCIInputClock != APCI1710_40MHZ) {
-												ul_TimerValue
-													=
-													(unsigned int)
-													(
-													(double)
-													(ul_TimerValue)
-													*
-													1.007752288);
-											}
-
-											break;
-										}
-
-										fpu_end();
-									}	/*  if (b_PCIInputClock != APCI1710_GATE_INPUT) */
-									else {
-				   /*************************************************************/
-										/* 2 Clock used for the overflow and the reload from counter */
-				   /*************************************************************/
-
-										ul_TimerValue
-											=
-											ul_TimingInterval
-											-
-											2;
-									}	/*  if (b_PCIInputClock != APCI1710_GATE_INPUT) */
-
-				/****************************/
-									/* Save the PCI input clock */
-				/****************************/
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TorCounterModuleInfo.
-										b_PCIInputClock
-										=
-										b_PCIInputClock;
-
-				/************************/
-									/* Save the timing unit */
-				/************************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TorCounterModuleInfo.
-										s_TorCounterInfo
-										[b_TorCounter].
-										b_TimingUnit
-										=
-										b_TimingUnit;
-
-				/************************/
-									/* Save the base timing */
-				/************************/
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TorCounterModuleInfo.
-										s_TorCounterInfo
-										[b_TorCounter].
-										d_TimingInterval
-										=
-										d_RealTimingInterval;
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TorCounterModuleInfo.
-										s_TorCounterInfo
-										[b_TorCounter].
-										ul_RealTimingInterval
-										=
-										ul_RealTimingInterval;
-
-				/*******************/
-									/* Get the command */
-				/*******************/
-
-									dw_Command
-										=
-										inl
-										(devpriv->
-										s_BoardInfos.
-										ui_Address
-										+
-										4
-										+
-										(16 * b_TorCounter) + (64 * b_ModulNbr));
-
-									dw_Command
-										=
-										(dw_Command
-										>>
-										4)
-										&
-										0xF;
-
-				/******************/
-									/* Test if 40 MHz */
-				/******************/
-
-									if (b_PCIInputClock == APCI1710_40MHZ) {
-				   /****************************/
-										/* Set the 40 MHz selection */
-				   /****************************/
-
-										dw_Command
-											=
-											dw_Command
-											|
-											0x10;
-									}
-
-				/*****************************/
-									/* Test if extern clock used */
-				/*****************************/
-
-									if (b_PCIInputClock == APCI1710_GATE_INPUT) {
-				   /****************************/
-										/* Set the 40 MHz selection */
-				   /****************************/
-
-										dw_Command
-											=
-											dw_Command
-											|
-											0x20;
-									}
-
-				/*************************/
-									/* Write the new command */
-				/*************************/
-
-									outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));
-
-				/*******************/
-									/* Disable the tor */
-				/*******************/
-
-									outl(0, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
-				/*************************/
-									/* Set the timer 1 value */
-				/*************************/
-
-									outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));
-
-				/*********************/
-									/* Tor counter init. */
-				/*********************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TorCounterModuleInfo.
-										s_TorCounterInfo
-										[b_TorCounter].
-										b_TorCounterInit
-										=
-										1;
-								} else {
-				/***********************************************/
-									/* TOR version error for 40MHz clock selection */
-				/***********************************************/
-
-									DPRINTK("TOR version error for 40MHz clock selection\n");
-									i_ReturnValue
-										=
-										-9;
-								}
-							} else {
-			     /**************************************************************/
-								/* You can not used the 40MHz clock selection wich this board */
-			     /**************************************************************/
-
-								DPRINTK("You can not used the 40MHz clock selection wich this board\n");
-								i_ReturnValue =
-									-8;
-							}
-						} else {
-			  /**********************************/
-							/* Base timing selection is wrong */
-			  /**********************************/
-
-							DPRINTK("Base timing selection is wrong\n");
-							i_ReturnValue = -7;
-						}
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-					else {
-		       /**********************************/
-						/* Timing unit selection is wrong */
-		       /**********************************/
-
-						DPRINTK("Timing unit selection is wrong\n");
-						i_ReturnValue = -6;
-					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
-				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
-				else {
-		    /*****************************************/
-					/* The selected PCI input clock is wrong */
-		    /*****************************************/
-
-					DPRINTK("The selected PCI input clock is wrong\n");
-					i_ReturnValue = -5;
-				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
-			}	/*  if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) */
-			else {
-		 /**********************************/
-				/* Tor Counter selection is wrong */
-		 /**********************************/
-
-				DPRINTK("Tor Counter selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) */
-		} else {
-	      /******************************************/
-			/* The module is not a tor counter module */
-	      /******************************************/
-
-			DPRINTK("The module is not a tor counter module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-	data[0] = (unsigned int) ul_RealTimingInterval;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_EnableTorCounter                      |
-|                                               (unsigned char_ b_BoardHandle,        |
-|                                                unsigned char_ b_ModulNbr,           |
-|						 unsigned char_ b_TorCounter,         |
-|						 unsigned char_ b_InputMode,          |
-|						 unsigned char_ b_ExternGate,         |
-|                                                unsigned char_ b_CycleMode,          |
-|                                                unsigned char_ b_InterruptEnable)    |
-+----------------------------------------------------------------------------+
-| Task              : Enable the tor counter (b_TorCounter) from selected    |
-|		      module (b_ModulNbr). You must calling the              |
-|                     "i_APCI1710_InitTorCounter" function be for you call   |
-|		      this function.                                         |
-|                     If you enable the tor counter interrupt, the           |
-|                     tor counter generate a interrupt after the timing cycle|
-|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
-|                     Interrupt mask description chapter from this manual.   |
-|                     The b_CycleMode parameter determine if you will        |
-|                     measured a single or more cycle.                       |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
-|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1). |
-|		      unsigned char_ b_InputMode    : Input signal level selection    |
-|						0 : Tor count each low level |
-|						1 : Tor count each high level|
-|		      unsigned char_ b_ExternGate   : Extern gate action selection    |
-|						0 : Extern gate signal not   |
-|						    used                     |
-|						1 : Extern gate signal used. |
-|						    If you selected the      |
-|						    single mode, each high   |
-|						    level signal start the   |
-|						    counter.                 |
-|						    If you selected the      |
-|						    continuous mode, the     |
-|						    first high level signal  |
-|						    start the tor counter    |
-|									     |
-|					      APCI1710_TOR_QUADRUPLE _MODE : |
-|					      In the quadruple mode, the edge|
-|					      analysis circuit generates a   |
-|					      counting pulse from each edge  |
-|					      of 2 signals which are phase   |
-|					      shifted in relation to each    |
-|					      other.                         |
-|					      The gate input is used for the |
-|					      signal B                       |
-|									     |
-|					      APCI1710_TOR_DOUBLE_MODE:      |
-|					      Functions in the same way as   |
-|					      the quadruple mode, except that|
-|					      only two of the four edges are |
-|					      analysed per period.           |
-|					      The gate input is used for the |
-|					      signal B                       |
-|									     |
-|					      APCI1710_TOR_SIMPLE_MODE:      |
-|					      Functions in the same way as   |
-|					      the quadruple mode, except that|
-|					      only one of the four edges is  |
-|					      analysed per period.           |
-|					      The gate input is used for the |
-|					      signal B                       |
-|									     |
-|                     unsigned char_ b_CycleMode    : Selected the tor counter        |
-|                                            acquisition mode                |
-|                     unsigned char_ b_InterruptEnable : Enable or disable the        |
-|                                               tor counter interrupt.       |
-|                                               APCI1710_ENABLE:             |
-|                                               Enable the tor counter       |
-|                                               interrupt                    |
-|                                               APCI1710_DISABLE:            |
-|                                               Disable the tor counter      |
-|                                               interrupt                    |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a tor counter module             |
-|                     -4: Tor counter selection is wrong                     |
-|                     -5: Tor counter not initialised see function           |
-|                         "i_APCI1710_InitTorCounter"                        |
-|                     -6: Tor input signal selection is wrong                |
-|                     -7: Extern gate signal mode is wrong                   |
-|                     -8: Tor counter acquisition mode cycle is wrong        |
-|                     -9: Interrupt parameter is wrong                       |
-|                     -10:Interrupt function not initialised.                |
-|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
-+----------------------------------------------------------------------------+
-*/
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_DisableTorCounter                     |
-|                                               (unsigned char_  b_BoardHandle,       |
-|                                                unsigned char_  b_ModulNbr,          |
-|						 unsigned char_  b_TorCounter)        |
-+----------------------------------------------------------------------------+
-| Task              : Disable the tor counter (b_TorCounter) from selected   |
-|		      module (b_ModulNbr). If you disable the tor counter    |
-|		      after a start cycle occur and you restart the tor      |
-|		      counter witch the " i_APCI1710_EnableTorCounter"       |
-|		      function, the status register is cleared               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
-|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1). |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a tor counter module             |
-|                     -4: Tor counter selection is wrong                     |
-|                     -5: Tor counter not initialised see function           |
-|                         "i_APCI1710_InitTorCounter"                        |
-|                     -6: Tor counter not enabled see function               |
-|                         "i_APCI1710_EnableTorCounter"                      |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
-						       struct comedi_subdevice *s,
-						       struct comedi_insn *insn,
-						       unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned int dw_DummyRead;
-	unsigned int dw_ConfigReg;
-	unsigned char b_ModulNbr, b_Action;
-	unsigned char b_TorCounter;
-	unsigned char b_InputMode;
-	unsigned char b_ExternGate;
-	unsigned char b_CycleMode;
-	unsigned char b_InterruptEnable;
-
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_Action = (unsigned char) data[0];	/*  enable or disable */
-	b_TorCounter = (unsigned char) data[1];
-	b_InputMode = (unsigned char) data[2];
-	b_ExternGate = (unsigned char) data[3];
-	b_CycleMode = (unsigned char) data[4];
-	b_InterruptEnable = (unsigned char) data[5];
-	i_ReturnValue = insn->n;
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if tor counter */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
-	      /**********************************/
-			/* Test the tor counter selection */
-	      /**********************************/
-
-			if (b_TorCounter <= 1) {
-				switch (b_Action)	/*  Enable or Disable */
-				{
-				case APCI1710_ENABLE:
-		 /***********************************/
-					/* Test if tor counter initialised */
-		 /***********************************/
-
-					dw_Status =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 8 +
-						(16 * b_TorCounter) +
-						(64 * b_ModulNbr));
-
-					if (dw_Status & 0x10) {
-		    /******************************/
-						/* Test the input signal mode */
-		    /******************************/
-
-						if (b_InputMode == 0 ||
-							b_InputMode == 1 ||
-							b_InputMode ==
-							APCI1710_TOR_SIMPLE_MODE
-							|| b_InputMode ==
-							APCI1710_TOR_DOUBLE_MODE
-							|| b_InputMode ==
-							APCI1710_TOR_QUADRUPLE_MODE)
-						{
-		       /************************************/
-							/* Test the extern gate signal mode */
-		       /************************************/
-
-							if (b_ExternGate == 0
-								|| b_ExternGate
-								== 1
-								|| b_InputMode >
-								1) {
-			  /*********************************/
-								/* Test the cycle mode parameter */
-			  /*********************************/
-
-								if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) {
-			     /***************************/
-									/* Test the interrupt flag */
-			     /***************************/
-
-									if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) {
-
-				   /***************************/
-										/* Save the interrupt mode */
-				   /***************************/
-
-										devpriv->
-											s_ModuleInfo
-											[b_ModulNbr].
-											s_TorCounterModuleInfo.
-											s_TorCounterInfo
-											[b_TorCounter].
-											b_InterruptEnable
-											=
-											b_InterruptEnable;
-
-				   /*******************/
-										/* Get the command */
-				   /*******************/
-
-										dw_ConfigReg
-											=
-											inl
-											(devpriv->
-											s_BoardInfos.
-											ui_Address
-											+
-											4
-											+
-											(16 * b_TorCounter) + (64 * b_ModulNbr));
-
-										dw_ConfigReg
-											=
-											(dw_ConfigReg
-											>>
-											4)
-											&
-											0x30;
-
-				   /********************************/
-										/* Test if not direct mode used */
-				   /********************************/
-
-										if (b_InputMode > 1) {
-				      /*******************************/
-											/* Extern gate can not be used */
-				      /*******************************/
-
-											b_ExternGate
-												=
-												0;
-
-				      /*******************************************/
-											/* Enable the extern gate for the Signal B */
-				      /*******************************************/
-
-											dw_ConfigReg
-												=
-												dw_ConfigReg
-												|
-												0x40;
-
-				      /***********************/
-											/* Test if simple mode */
-				      /***********************/
-
-											if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) {
-					 /**************************/
-												/* Enable the sinple mode */
-					 /**************************/
-
-												dw_ConfigReg
-													=
-													dw_ConfigReg
-													|
-													0x780;
-
-											}	/*  if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) */
-
-				      /***********************/
-											/* Test if double mode */
-				      /***********************/
-
-											if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) {
-					 /**************************/
-												/* Enable the double mode */
-					 /**************************/
-
-												dw_ConfigReg
-													=
-													dw_ConfigReg
-													|
-													0x180;
-
-											}	/*  if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) */
-
-											b_InputMode
-												=
-												0;
-										}	/*  if (b_InputMode > 1) */
-
-				   /*******************/
-										/* Set the command */
-				   /*******************/
-
-										dw_ConfigReg
-											=
-											dw_ConfigReg
-											|
-											b_CycleMode
-											|
-											(b_InterruptEnable
-											*
-											2)
-											|
-											(b_InputMode
-											*
-											4)
-											|
-											(b_ExternGate
-											*
-											8);
-
-				   /*****************************/
-										/* Clear the status register */
-				   /*****************************/
-
-										dw_DummyRead
-											=
-											inl
-											(devpriv->
-											s_BoardInfos.
-											ui_Address
-											+
-											0
-											+
-											(16 * b_TorCounter) + (64 * b_ModulNbr));
-
-				   /***************************************/
-										/* Clear the interrupt status register */
-				   /***************************************/
-
-										dw_DummyRead
-											=
-											inl
-											(devpriv->
-											s_BoardInfos.
-											ui_Address
-											+
-											12
-											+
-											(16 * b_TorCounter) + (64 * b_ModulNbr));
-
-				   /********************/
-										/* Set the commando */
-				   /********************/
-
-										outl(dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));
-
-				   /****************/
-										/* Set the gate */
-				   /****************/
-
-										outl(1, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
-
-									}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
-									else {
-				/********************************/
-										/* Interrupt parameter is wrong */
-				/********************************/
-
-										DPRINTK("Interrupt parameter is wrong\n");
-										i_ReturnValue
-											=
-											-9;
-									}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
-								}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
-								else {
-			     /***********************************************/
-									/* Tor counter acquisition mode cycle is wrong */
-			     /***********************************************/
-
-									DPRINTK("Tor counter acquisition mode cycle is wrong\n");
-									i_ReturnValue
-										=
-										-8;
-								}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
-							}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
-							else {
-			  /***********************************/
-								/* Extern gate input mode is wrong */
-			  /***********************************/
-
-								DPRINTK("Extern gate input mode is wrong\n");
-								i_ReturnValue =
-									-7;
-							}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
-						}	/*  if (b_InputMode >= 0 && b_InputMode <= 1) */
-						else {
-		       /***************************************/
-							/* Tor input signal selection is wrong */
-		       /***************************************/
-
-							DPRINTK("Tor input signal selection is wrong\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-		    /*******************************/
-						/* Tor counter not initialised */
-		    /*******************************/
-
-						DPRINTK("Tor counter not initialised\n");
-						i_ReturnValue = -5;
-					}
-					break;
-
-				case APCI1710_DISABLE:
-			 /***********************************/
-					/* Test if tor counter initialised */
-		 /***********************************/
-
-					dw_Status = inl(devpriv->s_BoardInfos.
-						ui_Address + 8 +
-						(16 * b_TorCounter) +
-						(64 * b_ModulNbr));
-
-		 /*******************************/
-					/* Test if counter initialised */
-		 /*******************************/
-
-					if (dw_Status & 0x10) {
-		    /***************************/
-						/* Test if counter enabled */
-		    /***************************/
-
-						if (dw_Status & 0x1) {
-		       /****************************/
-							/* Clear the interrupt mode */
-		       /****************************/
-							devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_TorCounterModuleInfo.
-								s_TorCounterInfo
-								[b_TorCounter].
-								b_InterruptEnable
-								=
-								APCI1710_DISABLE;
-
-		       /******************/
-							/* Clear the gate */
-		       /******************/
-
-							outl(0, devpriv->
-								s_BoardInfos.
-								ui_Address + 8 +
-								(16 * b_TorCounter) + (64 * b_ModulNbr));
-						}	/*  if (dw_Status & 0x1) */
-						else {
-		       /***************************/
-							/* Tor counter not enabled */
-		       /***************************/
-
-							DPRINTK("Tor counter not enabled \n");
-							i_ReturnValue = -6;
-						}	/*  if (dw_Status & 0x1) */
-					}	/*  if (dw_Status & 0x10) */
-					else {
-		    /*******************************/
-						/* Tor counter not initialised */
-		    /*******************************/
-
-						DPRINTK("Tor counter not initialised\n");
-						i_ReturnValue = -5;
-					}	/*  // if (dw_Status & 0x10) */
-
-				}	/*  switch */
-			}	/*  if (b_TorCounter <= 1) */
-			else {
-		 /**********************************/
-				/* Tor counter selection is wrong */
-		 /**********************************/
-
-				DPRINTK("Tor counter selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_TorCounter <= 1) */
-		} else {
-	      /******************************************/
-			/* The module is not a tor counter module */
-	      /******************************************/
-
-			DPRINTK("The module is not a tor counter module \n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error \n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_GetTorCounterInitialisation           |
-|                                               (unsigned char_     b_BoardHandle,    |
-|                                                unsigned char_     b_ModulNbr,       |
-|						 unsigned char_     b_TorCounter,     |
-|                                        	 unsigned char *_   pb_TimingUnit,     |
-|                                        	 PULONG_ pul_TimingInterval, |
-|						 unsigned char *_   pb_InputMode,      |
-|						 unsigned char *_   pb_ExternGate,     |
-|                                                unsigned char *_   pb_CycleMode,      |
-|						 unsigned char *_   pb_Enable,         |
-|                                                unsigned char *_   pb_InterruptEnable)|
-+----------------------------------------------------------------------------+
-| Task              : Enable the tor counter (b_TorCounter) from selected    |
-|		      module (b_ModulNbr). You must calling the              |
-|                     "i_APCI1710_InitTorCounter" function be for you call   |
-|		      this function.                                         |
-|                     If you enable the tor counter interrupt, the           |
-|                     tor counter generate a interrupt after the timing cycle|
-|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
-|                     Interrupt mask description chapter from this manual.   |
-|                     The b_CycleMode parameter determine if you will        |
-|                     measured a single or more cycle.                       |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
-|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1)
-
-	b_ModulNbr			=	CR_AREF(insn->chanspec);
-	b_TorCounter		=	CR_CHAN(insn->chanspec);
-. |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_  pb_TimingUnit    : Base timing unit (0 to 4)   |
-|                                                 0 : ns                     |
-|                                                 1 : µs                     |
-|                                                 2 : ms                     |
-|                                                 3 : s                      |
-|                                                 4 : mn                     |
-|                     PULONG_ pul_TimingInterval : Base timing value.        |
-|		      unsigned char *_ pb_InputMode        : Input signal level        |
-|						   selection  		     |
-|						0 : Tor count each low level |
-|						1 : Tor count each high level|
-|		      unsigned char *_ pb_ExternGate	: Extern gate action         |
-|						  selection                  |
-|						  0 : Extern gate signal not |
-|						      used                   |
-|						  1 : Extern gate signal used|
-|                     unsigned char *_ pb_CycleMode       : Tor counter acquisition    |
-|						  mode           	     |
-|		      unsigned char *_ pb_Enable		: Indicate if the tor counter|
-|						  is enabled or no           |
-|						  0 : Tor counter disabled   |
-|						  1 : Tor counter enabled    |
-|                     unsigned char *_ pb_InterruptEnable : Enable or disable the      |
-|                                                 tor counter interrupt.     |
-|                                                 APCI1710_ENABLE:           |
-|                                                 Enable the tor counter     |
-|                                                 interrupt                  |
-|                                                 APCI1710_DISABLE:          |
-|                                                 Disable the tor counter    |
-|                                                 interrupt
-	pb_TimingUnit		=	(unsigned char *) &data[0];
-	pul_TimingInterval	=  (unsigned int *) &data[1];
-	pb_InputMode		=	(unsigned char *) &data[2];
-	pb_ExternGate		=	(unsigned char *) &data[3];
-	pb_CycleMode		=	(unsigned char *) &data[4];
-	pb_Enable			=	(unsigned char *) &data[5];
-	pb_InterruptEnable	=	(unsigned char *) &data[6];
-                 |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a tor counter module             |
-|                     -4: Tor counter selection is wrong                     |
-|                     -5: Tor counter not initialised see function           |
-|                         "i_APCI1710_InitTorCounter"                        |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
-							  struct comedi_subdevice *s,
-							  struct comedi_insn *insn,
-							  unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned char b_ModulNbr;
-	unsigned char b_TorCounter;
-	unsigned char *pb_TimingUnit;
-	unsigned int *pul_TimingInterval;
-	unsigned char *pb_InputMode;
-	unsigned char *pb_ExternGate;
-	unsigned char *pb_CycleMode;
-	unsigned char *pb_Enable;
-	unsigned char *pb_InterruptEnable;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_TorCounter = CR_CHAN(insn->chanspec);
-
-	pb_TimingUnit = (unsigned char *) &data[0];
-	pul_TimingInterval = (unsigned int *) &data[1];
-	pb_InputMode = (unsigned char *) &data[2];
-	pb_ExternGate = (unsigned char *) &data[3];
-	pb_CycleMode = (unsigned char *) &data[4];
-	pb_Enable = (unsigned char *) &data[5];
-	pb_InterruptEnable = (unsigned char *) &data[6];
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if tor counter */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
-	      /**********************************/
-			/* Test the tor counter selection */
-	      /**********************************/
-
-			if (b_TorCounter <= 1) {
-
-		 /***********************************/
-				/* Test if tor counter initialised */
-		 /***********************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 8 + (16 * b_TorCounter) +
-					(64 * b_ModulNbr));
-
-				if (dw_Status & 0x10) {
-					*pb_Enable = dw_Status & 1;
-
-		    /********************/
-					/* Get the commando */
-		    /********************/
-
-					dw_Status = inl(devpriv->s_BoardInfos.
-						ui_Address + 4 +
-						(16 * b_TorCounter) +
-						(64 * b_ModulNbr));
-
-					*pb_CycleMode =
-						(unsigned char) ((dw_Status >> 4) & 1);
-					*pb_InterruptEnable =
-						(unsigned char) ((dw_Status >> 5) & 1);
-
-		    /******************************************************/
-					/* Test if extern gate used for clock or for signal B */
-		    /******************************************************/
-
-					if (dw_Status & 0x600) {
-		       /*****************************************/
-						/* Test if extern gate used for signal B */
-		       /*****************************************/
-
-						if (dw_Status & 0x400) {
-			  /***********************/
-							/* Test if simple mode */
-			  /***********************/
-
-							if ((dw_Status & 0x7800)
-								== 0x7800) {
-								*pb_InputMode =
-									APCI1710_TOR_SIMPLE_MODE;
-							}
-
-			  /***********************/
-							/* Test if double mode */
-			  /***********************/
-
-							if ((dw_Status & 0x7800)
-								== 0x1800) {
-								*pb_InputMode =
-									APCI1710_TOR_DOUBLE_MODE;
-							}
-
-			  /**************************/
-							/* Test if quadruple mode */
-			  /**************************/
-
-							if ((dw_Status & 0x7800)
-								== 0x0000) {
-								*pb_InputMode =
-									APCI1710_TOR_QUADRUPLE_MODE;
-							}
-						}	/*  if (dw_Status & 0x400) */
-						else {
-							*pb_InputMode = 1;
-						}	/*  // if (dw_Status & 0x400) */
-
-		       /************************/
-						/* Extern gate not used */
-		       /************************/
-
-						*pb_ExternGate = 0;
-					}	/*  if (dw_Status & 0x600) */
-					else {
-						*pb_InputMode =
-							(unsigned char) ((dw_Status >> 6)
-							& 1);
-						*pb_ExternGate =
-							(unsigned char) ((dw_Status >> 7)
-							& 1);
-					}	/*  if (dw_Status & 0x600) */
-
-					*pb_TimingUnit =
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_TorCounterModuleInfo.
-						s_TorCounterInfo[b_TorCounter].
-						b_TimingUnit;
-
-					*pul_TimingInterval =
-						devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_TorCounterModuleInfo.
-						s_TorCounterInfo[b_TorCounter].
-						ul_RealTimingInterval;
-				} else {
-		    /*******************************/
-					/* Tor counter not initialised */
-		    /*******************************/
-
-					DPRINTK("Tor counter not initialised\n");
-					i_ReturnValue = -5;
-				}
-
-			}	/*  if (b_TorCounter <= 1) */
-			else {
-		 /**********************************/
-				/* Tor counter selection is wrong */
-		 /**********************************/
-
-				DPRINTK("Tor counter selection is wrong \n");
-				i_ReturnValue = -4;
-			}	/*  if (b_TorCounter <= 1) */
-		} else {
-	      /******************************************/
-			/* The module is not a tor counter module */
-	      /******************************************/
-
-			DPRINTK("The module is not a tor counter module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_ReadTorCounterValue                   |
-|                               (unsigned char_     b_BoardHandle,                    |
-|                                unsigned char_     b_ModulNbr,                       |
-|				 unsigned char_     b_TorCounter,                     |
-|                                unsigned int_    ui_TimeOut,                        |
-|                                unsigned char *_   pb_TorCounterStatus,               |
-|                                PULONG_ pul_TorCounterValue)                |
-+----------------------------------------------------------------------------+
-| Task        	case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter
-(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter        |
-|		      module (b_ModulNbr).
-
-				 case APCI1710_TOR_GETCOUNTERVALUE :
-  Return the tor counter (b_TorCounter) status           |
-|		      (pb_TorCounterStatus) and the timing value             |
-|		      (pul_TorCounterValue) after a conting cycle stop       |
-|                     from selected tor counter module (b_ModulNbr).         |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
-|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
-|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1).
-	b_ModulNbr    = CR_AREF(insn->chanspec);
-	b_ReadType    = (unsigned char) data[0];
-	b_TorCounter  =	(unsigned char) data[1];
-	ui_TimeOut	  = (unsigned int) data[2]; |
-+----------------------------------------------------------------------------+
-| Output Parameters : unsigned char *_  pb_TorCounterStatus : Return the tor counter   |
-|                                                    status.                 |
-|                                               0 : Conting cycle not started|
-|                                                   Software gate not set.   |
-|                                               1 : Conting cycle started.   |
-|                                                   Software gate set.       |
-|                                               2 : Conting cycle stopped.   |
-|                                                   The conting cycle is     |
-|                                                   terminate.               |
-|                                               3 : A overflow occur. You    |
-|                                                   must change the base     |
-|                                                   timing witch the         |
-|                                                   function                 |
-|                                                 "i_APCI1710_InitTorCounter"|
-|						4 : Timeeout occur           |
-|                     unsigned int *  pul_TorCounterValue  : Tor counter value.
-	pb_TorCounterStatus=(unsigned char *) &data[0];
-	pul_TorCounterValue=(unsigned int *) &data[1];    |
-+----------------------------------------------------------------------------+
-| Return Value      :  0: No error                                           |
-|                     -1: The handle parameter of the board is wrong         |
-|                     -2: Module selection wrong                             |
-|                     -3: The module is not a tor counter module             |
-|                     -4: Tor counter selection is wrong                     |
-|                     -5: Tor counter not initialised see function           |
-|                         "i_APCI1710_InitTorCounter"                        |
-|                     -6: Tor counter not enabled see function               |
-|                         "i_APCI1710_EnableTorCounter"                      |
-|                     -7: Timeout parameter is wrong (0 to 65535)            |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
-								  struct comedi_subdevice *s,
-								  struct comedi_insn *insn,
-								  unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_Status;
-	unsigned int dw_TimeOut = 0;
-	unsigned char b_ModulNbr;
-	unsigned char b_TorCounter;
-	unsigned char b_ReadType;
-	unsigned int ui_TimeOut;
-	unsigned char *pb_TorCounterStatus;
-	unsigned int *pul_TorCounterValue;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_ReadType = (unsigned char) data[0];
-	b_TorCounter = (unsigned char) data[1];
-	ui_TimeOut = (unsigned int) data[2];
-	pb_TorCounterStatus = (unsigned char *) &data[0];
-	pul_TorCounterValue = (unsigned int *) &data[1];
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ReadType == APCI1710_TOR_READINTERRUPT) {
-
-		data[0] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].b_OldModuleMask;
-		data[1] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-		data[2] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-			   /**************************/
-		/* Increment the read FIFO */
-			   /***************************/
-
-		devpriv->
-			s_InterruptParameters.
-			ui_Read = (devpriv->
-			s_InterruptParameters.
-			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-
-		return insn->n;
-	}
-
-	if (b_ModulNbr < 4) {
-	   /***********************/
-		/* Test if tor counter */
-	   /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
-	      /**********************************/
-			/* Test the tor counter selection */
-	      /**********************************/
-
-			if (b_TorCounter <= 1) {
-		 /***********************************/
-				/* Test if tor counter initialised */
-		 /***********************************/
-
-				dw_Status = inl(devpriv->s_BoardInfos.
-					ui_Address + 8 + (16 * b_TorCounter) +
-					(64 * b_ModulNbr));
-
-		 /*******************************/
-				/* Test if counter initialised */
-		 /*******************************/
-
-				if (dw_Status & 0x10) {
-		    /***************************/
-					/* Test if counter enabled */
-		    /***************************/
-
-					if (dw_Status & 0x1) {
-
-						switch (b_ReadType) {
-
-						case APCI1710_TOR_GETPROGRESSSTATUS:
-		       /*******************/
-							/* Read the status */
-		       /*******************/
-
-							dw_Status =
-								inl(devpriv->
-								s_BoardInfos.
-								ui_Address + 4 +
-								(16 * b_TorCounter) + (64 * b_ModulNbr));
-
-							dw_Status =
-								dw_Status & 0xF;
-
-		       /*****************/
-							/* Test if start */
-		       /*****************/
-
-							if (dw_Status & 1) {
-								if (dw_Status &
-									2) {
-									if (dw_Status & 4) {
-				/************************/
-										/* Tor counter overflow */
-				/************************/
-
-										*pb_TorCounterStatus
-											=
-											3;
-									} else {
-				/***********************/
-										/* Tor counter started */
-				/***********************/
-
-										*pb_TorCounterStatus
-											=
-											2;
-									}
-								} else {
-			     /***********************/
-									/* Tor counter started */
-			     /***********************/
-
-									*pb_TorCounterStatus
-										=
-										1;
-								}
-							} else {
-			  /***************************/
-								/* Tor counter not started */
-			  /***************************/
-
-								*pb_TorCounterStatus
-									= 0;
-							}
-							break;
-
-						case APCI1710_TOR_GETCOUNTERVALUE:
-
-		       /*****************************/
-							/* Test the timout parameter */
-		       /*****************************/
-
-							if ((ui_TimeOut >= 0)
-								&& (ui_TimeOut
-									<=
-									65535UL))
-							{
-								for (;;) {
-			     /*******************/
-									/* Read the status */
-			     /*******************/
-
-									dw_Status
-										=
-										inl
-										(devpriv->
-										s_BoardInfos.
-										ui_Address
-										+
-										4
-										+
-										(16 * b_TorCounter) + (64 * b_ModulNbr));
-			     /********************/
-									/* Test if overflow */
-			     /********************/
-
-									if ((dw_Status & 4) == 4) {
-				/******************/
-										/* Overflow occur */
-				/******************/
-
-										*pb_TorCounterStatus
-											=
-											3;
-
-				/******************/
-										/* Read the value */
-				/******************/
-
-										*pul_TorCounterValue
-											=
-											inl
-											(devpriv->
-											s_BoardInfos.
-											ui_Address
-											+
-											0
-											+
-											(16 * b_TorCounter) + (64 * b_ModulNbr));
-										break;
-									}	/*  if ((dw_Status & 4) == 4) */
-									else {
-				/*******************************/
-										/* Test if measurement stopped */
-				/*******************************/
-
-										if ((dw_Status & 2) == 2) {
-				   /***********************/
-											/* A stop signal occur */
-				   /***********************/
-
-											*pb_TorCounterStatus
-												=
-												2;
-
-				   /******************/
-											/* Read the value */
-				   /******************/
-
-											*pul_TorCounterValue
-												=
-												inl
-												(devpriv->
-												s_BoardInfos.
-												ui_Address
-												+
-												0
-												+
-												(16 * b_TorCounter) + (64 * b_ModulNbr));
-
-											break;
-										}	/*  if ((dw_Status & 2) == 2) */
-										else {
-				   /*******************************/
-											/* Test if measurement started */
-				   /*******************************/
-
-											if ((dw_Status & 1) == 1) {
-				      /************************/
-												/* A start signal occur */
-				      /************************/
-
-												*pb_TorCounterStatus
-													=
-													1;
-											}	/*  if ((dw_Status & 1) == 1) */
-											else {
-				      /***************************/
-												/* Measurement not started */
-				      /***************************/
-
-												*pb_TorCounterStatus
-													=
-													0;
-											}	/*  if ((dw_Status & 1) == 1) */
-										}	/*  if ((dw_Status & 2) == 2) */
-									}	/*  if ((dw_Status & 8) == 8) */
-
-									if (dw_TimeOut == ui_TimeOut) {
-				/*****************/
-										/* Timeout occur */
-				/*****************/
-
-										break;
-									} else {
-				/*************************/
-										/* Increment the timeout */
-				/*************************/
-
-										dw_TimeOut
-											=
-											dw_TimeOut
-											+
-											1;
-
-										mdelay(1000);
-									}
-								}	/*  for (;;) */
-
-			  /*************************/
-								/* Test if timeout occur */
-			  /*************************/
-
-								if ((*pb_TorCounterStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0)) {
-			     /*****************/
-									/* Timeout occur */
-			     /*****************/
-
-									*pb_TorCounterStatus
-										=
-										4;
-								}
-							} else {
-			  /******************************/
-								/* Timeout parameter is wrong */
-			  /******************************/
-
-								DPRINTK("Timeout parameter is wrong\n");
-								i_ReturnValue =
-									-7;
-							}
-							break;
-
-						default:
-							printk("Inputs wrong\n");
-						}	/*  switch end */
-					}	/*  if (dw_Status & 0x1) */
-					else {
-		       /***************************/
-						/* Tor counter not enabled */
-		       /***************************/
-
-						DPRINTK("Tor counter not enabled\n");
-						i_ReturnValue = -6;
-					}	/*  if (dw_Status & 0x1) */
-				} else {
-		    /*******************************/
-					/* Tor counter not initialised */
-		    /*******************************/
-
-					DPRINTK("Tor counter not initialised\n");
-					i_ReturnValue = -5;
-				}
-			}	/*  if (b_TorCounter <= 1) */
-			else {
-		 /**********************************/
-				/* Tor counter selection is wrong */
-		 /**********************************/
-
-				DPRINTK("Tor counter selection is wrong\n");
-				i_ReturnValue = -4;
-			}	/*  if (b_TorCounter <= 1) */
-		} else {
-	      /******************************************/
-			/* The module is not a tor counter module */
-	      /******************************************/
-
-			DPRINTK("The module is not a tor counter module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
deleted file mode 100644
index fb56360..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project     : API APCI1710    | Compiler : gcc                        |
-  | Module name : TTL.C           | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description :   APCI-1710 TTL I/O module                              |
-  |                                                                       |
-  |                                                                       |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  | 13/05/98 | S. Weber  | TTL digital input / output implementation      |
-  |----------|-----------|------------------------------------------------|
-  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
-  |          |           |   available                                    |
-  +-----------------------------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  +-----------------------------------------------------------------------+
-*/
-
-#define APCI1710_TTL_INIT		0
-#define APCI1710_TTL_INITDIRECTION	1
-
-#define APCI1710_TTL_READCHANNEL	0
-#define APCI1710_TTL_READPORT		1
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_InitTTLIODirection                    |
-|                               (unsigned char_    b_BoardHandle,                     |
-|				 unsigned char_    b_ModulNbr,                        |
-|				 unsigned char_    b_PortAMode,                       |
-|				 unsigned char_    b_PortBMode,                       |
-|				 unsigned char_    b_PortCMode,                       |
-|				 unsigned char_    b_PortDMode)                       |
-+----------------------------------------------------------------------------+
-| Task           APCI1710_TTL_INIT (using defaults)   : Configure the TTL I/O operating mode from selected     |
-|                     module  (b_ModulNbr). You must calling this function be|
-|                     for you call any other function witch access of TTL.   |
-				 APCI1710_TTL_INITDIRECTION(user inputs for direction)
-
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 3)
-		b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-		b_InitType = (unsigned char) data[0];
-		b_PortAMode	= (unsigned char) data[1];
-		b_PortBMode = (unsigned char) data[2];
-		b_PortCMode = (unsigned char) data[3];
-		b_PortDMode	= (unsigned char) data[4];|
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a TTL module                      |
-|		     -4: Function not available for this version             |
-|		     -5: Port A mode selection is wrong                      |
-|		     -6: Port B mode selection is wrong                      |
-|		     -7: Port C mode selection is wrong                      |
-|		     -8: Port D mode selection is wrong                      |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn,
-					  unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned char b_ModulNbr;
-	unsigned char b_InitType;
-	unsigned char b_PortAMode;
-	unsigned char b_PortBMode;
-	unsigned char b_PortCMode;
-	unsigned char b_PortDMode;
-
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	b_InitType = (unsigned char) data[0];
-	i_ReturnValue = insn->n;
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /**************************/
-		/* Test if TTL I/O module */
-	   /**************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TTL_IO) {
-			switch (b_InitType) {
-			case APCI1710_TTL_INIT:
-
-				devpriv->s_ModuleInfo[b_ModulNbr].
-					s_TTLIOInfo.b_TTLInit = 1;
-
-	      /***************************/
-				/* Set TTL port A to input */
-	      /***************************/
-
-				devpriv->s_ModuleInfo[b_ModulNbr].
-					s_TTLIOInfo.b_PortConfiguration[0] = 0;
-
-	      /***************************/
-				/* Set TTL port B to input */
-	      /***************************/
-
-				devpriv->s_ModuleInfo[b_ModulNbr].
-					s_TTLIOInfo.b_PortConfiguration[1] = 0;
-
-	      /***************************/
-				/* Set TTL port C to input */
-	      /***************************/
-
-				devpriv->s_ModuleInfo[b_ModulNbr].
-					s_TTLIOInfo.b_PortConfiguration[2] = 0;
-
-	      /****************************/
-				/* Set TTL port D to output */
-	      /****************************/
-
-				devpriv->s_ModuleInfo[b_ModulNbr].
-					s_TTLIOInfo.b_PortConfiguration[3] = 1;
-
-	      /*************************/
-				/* Set the configuration */
-	      /*************************/
-
-				outl(0x8,
-					devpriv->s_BoardInfos.ui_Address + 20 +
-					(64 * b_ModulNbr));
-				break;
-
-			case APCI1710_TTL_INITDIRECTION:
-
-				b_PortAMode = (unsigned char) data[1];
-				b_PortBMode = (unsigned char) data[2];
-				b_PortCMode = (unsigned char) data[3];
-				b_PortDMode = (unsigned char) data[4];
-
-	      /********************/
-				/* Test the version */
-	      /********************/
-
-				if ((devpriv->s_BoardInfos.
-						dw_MolduleConfiguration
-						[b_ModulNbr] & 0xFFFF) >=
-					0x3230) {
-		 /************************/
-					/* Test the port A mode */
-		 /************************/
-
-					if ((b_PortAMode == 0)
-						|| (b_PortAMode == 1)) {
-		    /************************/
-						/* Test the port B mode */
-		    /************************/
-
-						if ((b_PortBMode == 0)
-							|| (b_PortBMode == 1)) {
-		       /************************/
-							/* Test the port C mode */
-		       /************************/
-
-							if ((b_PortCMode == 0)
-								|| (b_PortCMode
-									== 1)) {
-			  /************************/
-								/* Test the port D mode */
-			  /************************/
-
-								if ((b_PortDMode == 0) || (b_PortDMode == 1)) {
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TTLIOInfo.
-										b_TTLInit
-										=
-										1;
-
-			     /***********************/
-									/* Set TTL port A mode */
-			     /***********************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TTLIOInfo.
-										b_PortConfiguration
-										[0]
-										=
-										b_PortAMode;
-
-			     /***********************/
-									/* Set TTL port B mode */
-			     /***********************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TTLIOInfo.
-										b_PortConfiguration
-										[1]
-										=
-										b_PortBMode;
-
-			     /***********************/
-									/* Set TTL port C mode */
-			     /***********************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TTLIOInfo.
-										b_PortConfiguration
-										[2]
-										=
-										b_PortCMode;
-
-			     /***********************/
-									/* Set TTL port D mode */
-			     /***********************/
-
-									devpriv->
-										s_ModuleInfo
-										[b_ModulNbr].
-										s_TTLIOInfo.
-										b_PortConfiguration
-										[3]
-										=
-										b_PortDMode;
-
-			     /*************************/
-									/* Set the configuration */
-			     /*************************/
-
-									outl((b_PortAMode << 0) | (b_PortBMode << 1) | (b_PortCMode << 2) | (b_PortDMode << 3), devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr));
-								} else {
-			     /**********************************/
-									/* Port D mode selection is wrong */
-			     /**********************************/
-
-									DPRINTK("Port D mode selection is wrong\n");
-									i_ReturnValue
-										=
-										-8;
-								}
-							} else {
-			  /**********************************/
-								/* Port C mode selection is wrong */
-			  /**********************************/
-
-								DPRINTK("Port C mode selection is wrong\n");
-								i_ReturnValue =
-									-7;
-							}
-						} else {
-		       /**********************************/
-							/* Port B mode selection is wrong */
-		       /**********************************/
-
-							DPRINTK("Port B mode selection is wrong\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-		    /**********************************/
-						/* Port A mode selection is wrong */
-		    /**********************************/
-
-						DPRINTK("Port A mode selection is wrong\n");
-						i_ReturnValue = -5;
-					}
-				} else {
-		 /*******************************************/
-					/* Function not available for this version */
-		 /*******************************************/
-
-					DPRINTK("Function not available for this version\n");
-					i_ReturnValue = -4;
-				}
-				break;
-
-				DPRINTK("\n");
-			default:
-				printk("Bad Config Type\n");
-			}	/*  switch end */
-		} else {
-	      /**********************************/
-			/* The module is not a TTL module */
-	      /**********************************/
-
-			DPRINTK("The module is not a TTL module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-|                            INPUT FUNCTIONS                                 |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_   i_APCI1710_ReadTTLIOChannelValue               |
-|                                       (unsigned char_     b_BoardHandle,            |
-|                                        unsigned char_     b_ModulNbr,               |
-|                                        unsigned char_     b_SelectedPort,           |
-|                                        unsigned char_     b_InputChannel,           |
-|                                        unsigned char *_   pb_ChannelStatus)          |
-+----------------------------------------------------------------------------+
-| Task              : Read the status from selected TTL digital input        |
-|                     (b_InputChannel)
-+----------------------------------------------------------------------------+
-| Task              : Read the status from digital input port                |
-|                     (b_SelectedPort) from selected TTL module (b_ModulNbr) |
-+----------------------------------------------------------------------------+
-
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 7)       |
-|                     unsigned char_ b_SelectedPort,       : Selection from TTL I/O   |
-|                                                   port (0 to 2)            |
-|                                                      0 : Port A selection  |
-|                                                      1 : Port B selection  |
-|                                                      2 : Port C selection  |
-|                                                      3 : Port D selection  |
-|                     unsigned char_ b_InputChannel        : Selection from digital   |
-|                                                   input ( 0 to 2)
-APCI1710_TTL_READCHANNEL
-	b_ModulNbr	  = CR_AREF(insn->chanspec);
-	b_SelectedPort= CR_RANGE(insn->chanspec);
-	b_InputChannel= CR_CHAN(insn->chanspec);
-	b_ReadType	  = (unsigned char) data[0];
-
- APCI1710_TTL_READPORT|
-	b_ModulNbr	  = CR_AREF(insn->chanspec);
-	b_SelectedPort= CR_RANGE(insn->chanspec);
-	b_ReadType	  = (unsigned char) data[0];
-
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0]
-
-	unsigned char *_  pb_ChannelStatus    : Digital input channel    |
-|                                                   status                   |
-|                                                   0 : Channle is not active|
-|                                                   1 : Channle is active    |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a TTL module                      |
-|                    -4: The selected TTL input port is wrong                |
-|                    -5: The selected TTL digital input is wrong             |
-|                    -6: TTL I/O not initialised                             |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn,
-					unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg;
-	unsigned char b_ModulNbr;
-	unsigned char b_SelectedPort;
-	unsigned char b_InputChannel;
-	unsigned char b_ReadType;
-	unsigned char *pb_ChannelStatus;
-	unsigned char *pb_PortValue;
-
-	i_ReturnValue = insn->n;
-	b_ReadType = (unsigned char) data[0];
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_SelectedPort = CR_RANGE(insn->chanspec);
-	b_InputChannel = CR_CHAN(insn->chanspec);
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /**************************/
-		/* Test if TTL I/O module */
-	   /**************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TTL_IO) {
-			switch (b_ReadType) {
-
-			case APCI1710_TTL_READCHANNEL:
-				pb_ChannelStatus = (unsigned char *) &data[0];
-	      /********************************/
-				/* Test the TTL I/O port number */
-	      /********************************/
-
-				if (((b_SelectedPort <= 2)
-						&& ((devpriv->s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) ==
-							0x3130))
-					|| ((b_SelectedPort <= 3)
-						&& ((devpriv->s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) >=
-							0x3230))) {
-		 /******************************************/
-					/* Test the digital imnput channel number */
-		 /******************************************/
-
-					if (((b_InputChannel <= 7)
-							&& (b_SelectedPort < 3))
-						|| ((b_InputChannel <= 1)
-							&& (b_SelectedPort ==
-								3))) {
-		    /******************************************/
-						/* Test if the TTL I/O module initialised */
-		    /******************************************/
-
-						if (devpriv->
-							s_ModuleInfo
-							[b_ModulNbr].
-							s_TTLIOInfo.b_TTLInit ==
-							1) {
-		       /***********************************/
-							/* Test if TTL port used for input */
-		       /***********************************/
-
-							if (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) == 0x3130) || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) {
-			  /**************************/
-								/* Read all digital input */
-			  /**************************/
-
-								dw_StatusReg =
-									inl
-									(devpriv->
-									s_BoardInfos.
-									ui_Address
-									+
-									(64 * b_ModulNbr));
-
-								*pb_ChannelStatus
-									=
-									(unsigned char) (
-									(dw_StatusReg
-										>>
-										(8 * b_SelectedPort)) >> b_InputChannel) & 1;
-							} else {
-			  /*******************************/
-								/* Selected TTL I/O port error */
-			  /*******************************/
-
-								DPRINTK("Selected TTL I/O port error\n");
-								i_ReturnValue =
-									-4;
-							}
-						} else {
-		       /***************************/
-							/* TTL I/O not initialised */
-		       /***************************/
-
-							DPRINTK("TTL I/O not initialised\n");
-							i_ReturnValue = -6;
-						}
-					} else {
-		    /********************************/
-						/* Selected digital input error */
-		    /********************************/
-
-						DPRINTK("Selected digital input error\n");
-						i_ReturnValue = -5;
-					}
-				} else {
-		 /*******************************/
-					/* Selected TTL I/O port error */
-		 /*******************************/
-
-					DPRINTK("Selected TTL I/O port error\n");
-					i_ReturnValue = -4;
-				}
-				break;
-
-			case APCI1710_TTL_READPORT:
-				pb_PortValue = (unsigned char *) &data[0];
-			  /********************************/
-				/* Test the TTL I/O port number */
-			  /********************************/
-
-				if (((b_SelectedPort <= 2)
-						&& ((devpriv->s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) ==
-							0x3130))
-					|| ((b_SelectedPort <= 3)
-						&& ((devpriv->s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) >=
-							0x3230))) {
-		 /******************************************/
-					/* Test if the TTL I/O module initialised */
-		 /******************************************/
-
-					if (devpriv->s_ModuleInfo[b_ModulNbr].
-						s_TTLIOInfo.b_TTLInit == 1) {
-		    /***********************************/
-						/* Test if TTL port used for input */
-		    /***********************************/
-
-						if (((devpriv->s_BoardInfos.
-									dw_MolduleConfiguration
-									[b_ModulNbr]
-									&
-									0xFFFF)
-								== 0x3130)
-							|| (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) {
-		       /**************************/
-							/* Read all digital input */
-		       /**************************/
-
-							dw_StatusReg =
-								inl(devpriv->
-								s_BoardInfos.
-								ui_Address +
-								(64 * b_ModulNbr));
-
-							*pb_PortValue =
-								(unsigned char) (
-								(dw_StatusReg >>
-									(8 * b_SelectedPort)) & 0xFF);
-						} else {
-		       /*******************************/
-							/* Selected TTL I/O port error */
-		       /*******************************/
-
-							DPRINTK("Selected TTL I/O port error\n");
-							i_ReturnValue = -4;
-						}
-					} else {
-		    /***************************/
-						/* TTL I/O not initialised */
-		    /***************************/
-
-						DPRINTK("TTL I/O not initialised\n");
-						i_ReturnValue = -5;
-					}
-				} else {
-		 /*******************************/
-					/* Selected TTL I/O port error */
-		 /*******************************/
-
-					DPRINTK("Selected TTL I/O port error\n");
-					i_ReturnValue = -4;
-				}
-				break;
-
-			default:
-				printk("Bad ReadType\n");
-
-			}	/* End Switch */
-		} else {
-	      /**********************************/
-			/* The module is not a TTL module */
-	      /**********************************/
-
-			DPRINTK("The module is not a TTL module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : int i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
-*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)              |
-+----------------------------------------------------------------------------+
-| Task              : Read the status from all digital input ports           |
-|                     (port A, port B and port C) from selected TTL          |
-|		      module (b_ModulNbr) 				     |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
-|                     unsigned char_ b_ModulNbr            : Module number to         |
-|                                                   configure (0 to 3)       |
-+----------------------------------------------------------------------------+
-| Output Parameters : PULONG_  pul_PortValue      : Digital TTL inputs port  |
-|                                                   status                   |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a TTL module                      |
-|                    -4: TTL I/O not initialised                             |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
-						struct comedi_subdevice *s,
-						struct comedi_insn *insn,
-						unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg;
-	unsigned char b_ModulNbr;
-	unsigned int *pul_PortValue;
-
-	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
-	i_ReturnValue = insn->n;
-	pul_PortValue = (unsigned int *) &data[0];
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /**************************/
-		/* Test if TTL I/O module */
-	   /**************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TTL_IO) {
-	      /******************************************/
-			/* Test if the TTL I/O module initialised */
-	      /******************************************/
-
-			if (devpriv->
-				s_ModuleInfo[b_ModulNbr].
-				s_TTLIOInfo.b_TTLInit == 1) {
-		 /**************************/
-				/* Read all digital input */
-		 /**************************/
-
-				dw_StatusReg = inl(devpriv->s_BoardInfos.
-					ui_Address + (64 * b_ModulNbr));
-
-		 /**********************/
-				/* Test if TTL Rev1.0 */
-		 /**********************/
-
-				if ((devpriv->s_BoardInfos.
-						dw_MolduleConfiguration
-						[b_ModulNbr] & 0xFFFF) ==
-					0x3130) {
-					*pul_PortValue =
-						dw_StatusReg & 0xFFFFFFUL;
-				} else {
-		    /**************************************/
-					/* Test if port A not used for output */
-		    /**************************************/
-
-					if (devpriv->s_ModuleInfo[b_ModulNbr].
-						s_TTLIOInfo.
-						b_PortConfiguration[0] == 1) {
-						*pul_PortValue =
-							dw_StatusReg &
-							0x3FFFF00UL;
-					}
-
-		    /**************************************/
-					/* Test if port B not used for output */
-		    /**************************************/
-
-					if (devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_TTLIOInfo.
-						b_PortConfiguration[1] == 1) {
-						*pul_PortValue =
-							dw_StatusReg &
-							0x3FF00FFUL;
-					}
-
-		    /**************************************/
-					/* Test if port C not used for output */
-		    /**************************************/
-
-					if (devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_TTLIOInfo.
-						b_PortConfiguration[2] == 1) {
-						*pul_PortValue =
-							dw_StatusReg &
-							0x300FFFFUL;
-					}
-
-		    /**************************************/
-					/* Test if port D not used for output */
-		    /**************************************/
-
-					if (devpriv->
-						s_ModuleInfo[b_ModulNbr].
-						s_TTLIOInfo.
-						b_PortConfiguration[3] == 1) {
-						*pul_PortValue =
-							dw_StatusReg &
-							0xFFFFFFUL;
-					}
-				}
-			} else {
-		 /***************************/
-				/* TTL I/O not initialised */
-		 /***************************/
-				DPRINTK("TTL I/O not initialised\n");
-				i_ReturnValue = -5;
-			}
-		} else {
-	      /**********************************/
-			/* The module is not a TTL module */
-	      /**********************************/
-			DPRINTK("The module is not a TTL module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-|                            OUTPUT FUNCTIONS                                |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     : _INT_ i_APCI1710_SetTTLIOChlOn                         |
-|                               (unsigned char_           b_BoardHandle,              |
-|                                unsigned char_           b_ModulNbr,                 |
-|                                unsigned char_           b_OutputChannel)
-int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
-	struct comedi_insn *insn,unsigned int *data)           |
-+----------------------------------------------------------------------------+
-| Task              : Sets or resets  the output witch has been passed with the         |
-|                     parameter b_Channel. Setting an output means setting   |
-|                     an ouput high.                                         |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
-|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
-|                     unsigned char_ b_OutputChannel : Selection from digital output  |
-|                                             channel (0 or 1)               |
-|                                                0      : PD0                |
-|                                                1      : PD1                |
-|						 2 to 9 : PA                 |
-|						10 to 17: PB                 |
-|						18 to 25: PC                 |
-
-  b_ModulNbr	   = CR_AREF(insn->chanspec);
-	b_OutputChannel= CR_CHAN(insn->chanspec);
-	ui_State	   = data[0]; /*  ON or OFF */
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0: No error                                            |
-|                    -1: The handle parameter of the board is wrong          |
-|                    -2: The module parameter is wrong                       |
-|                    -3: The module is not a TTL I/O module                  |
-|                    -4: The selected digital output is wrong                |
-|                    -5: TTL I/O not initialised see function                |
-|                        " i_APCI1710_InitTTLIO"
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
-						struct comedi_subdevice *s,
-						struct comedi_insn *insn,
-						unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-	int i_ReturnValue = 0;
-	unsigned int dw_StatusReg = 0;
-	unsigned char b_ModulNbr;
-	unsigned char b_OutputChannel;
-	unsigned int ui_State;
-
-	i_ReturnValue = insn->n;
-	b_ModulNbr = CR_AREF(insn->chanspec);
-	b_OutputChannel = CR_CHAN(insn->chanspec);
-	ui_State = data[0];	/*  ON or OFF */
-
-	/**************************/
-	/* Test the module number */
-	/**************************/
-
-	if (b_ModulNbr < 4) {
-	   /**************************/
-		/* Test if TTL I/O module */
-	   /**************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModulNbr] &
-				0xFFFF0000UL) == APCI1710_TTL_IO) {
-	      /******************************************/
-			/* Test if the TTL I/O module initialised */
-	      /******************************************/
-
-			if (devpriv->s_ModuleInfo[b_ModulNbr].
-				s_TTLIOInfo.b_TTLInit == 1) {
-		 /***********************************/
-				/* Test the TTL I/O channel number */
-		 /***********************************/
-
-				if (((b_OutputChannel <= 1)
-						&& ((devpriv->s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) ==
-							0x3130))
-					|| ((b_OutputChannel <= 25)
-						&& ((devpriv->s_BoardInfos.
-								dw_MolduleConfiguration
-								[b_ModulNbr] &
-								0xFFFF) >=
-							0x3230))) {
-		    /****************************************************/
-					/* Test if the selected channel is a output channel */
-		    /****************************************************/
-
-					if (((b_OutputChannel <= 1)
-							&& (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_TTLIOInfo.
-								b_PortConfiguration
-								[3] == 1))
-						|| ((b_OutputChannel >= 2)
-							&& (b_OutputChannel <=
-								9)
-							&& (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_TTLIOInfo.
-								b_PortConfiguration
-								[0] == 1))
-						|| ((b_OutputChannel >= 10)
-							&& (b_OutputChannel <=
-								17)
-							&& (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_TTLIOInfo.
-								b_PortConfiguration
-								[1] == 1))
-						|| ((b_OutputChannel >= 18)
-							&& (b_OutputChannel <=
-								25)
-							&& (devpriv->
-								s_ModuleInfo
-								[b_ModulNbr].
-								s_TTLIOInfo.
-								b_PortConfiguration
-								[2] == 1))) {
-		       /************************/
-						/* Test if PD0 selected */
-		       /************************/
-
-						if (b_OutputChannel == 0) {
-
-							outl(ui_State,
-								devpriv->
-								s_BoardInfos.
-								ui_Address +
-								(64 * b_ModulNbr));
-						} else {
-			  /************************/
-							/* Test if PD1 selected */
-			  /************************/
-
-							if (b_OutputChannel ==
-								1) {
-
-								outl(ui_State,
-									devpriv->
-									s_BoardInfos.
-									ui_Address
-									+ 4 +
-									(64 * b_ModulNbr));
-							} else {
-								b_OutputChannel
-									=
-									b_OutputChannel
-									- 2;
-
-			     /********************/
-								/* Read all channel */
-			     /********************/
-
-								dw_StatusReg =
-									inl
-									(devpriv->
-									s_BoardInfos.
-									ui_Address
-									+
-									(64 * b_ModulNbr));
-								if (ui_State)	/*  ON */
-								{
-									dw_StatusReg
-										=
-										(dw_StatusReg
-										>>
-										((b_OutputChannel / 8) * 8)) & 0xFF;
-									dw_StatusReg
-										=
-										dw_StatusReg
-										|
-										(1
-										<<
-										(b_OutputChannel
-											%
-											8));
-								} else	/*  Off */
-								{
-									dw_StatusReg
-										=
-										(dw_StatusReg
-										>>
-										((b_OutputChannel / 8) * 8)) & 0xFF;
-									dw_StatusReg
-										=
-										dw_StatusReg
-										&
-										(0xFF
-										-
-										(1 << (b_OutputChannel % 8)));
-
-								}
-
-			     /****************************/
-								/* Set the new output value */
-			     /****************************/
-
-								outl(dw_StatusReg, devpriv->s_BoardInfos.ui_Address + 8 + ((b_OutputChannel / 8) * 4) + (64 * b_ModulNbr));
-							}
-						}
-					} else {
-		       /************************************/
-						/* The selected TTL output is wrong */
-		       /************************************/
-
-						DPRINTK(" The selected TTL output is wrong\n");
-						i_ReturnValue = -4;
-					}
-				} else {
-		    /************************************/
-					/* The selected TTL output is wrong */
-		    /************************************/
-
-					DPRINTK("The selected TTL output is wrong\n");
-					i_ReturnValue = -4;
-				}
-			} else {
-		 /***************************/
-				/* TTL I/O not initialised */
-		 /***************************/
-
-				DPRINTK("TTL I/O not initialised\n");
-				i_ReturnValue = -5;
-			}
-		} else {
-	      /**************************************/
-			/* The module is not a TTL I/O module */
-	      /**************************************/
-
-			DPRINTK("The module is not a TTL I/O module\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /***********************/
-		/* Module number error */
-	   /***********************/
-
-		DPRINTK("Module number error\n");
-		i_ReturnValue = -2;
-	}
-
-	return i_ReturnValue;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index f25e008..63dff77 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -85,10 +85,9 @@ static int addi_auto_attach(struct comedi_device *dev,
 
 	dev->board_name = this_board->pc_DriverName;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index f1be5ad..dfd1e66 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -113,150 +113,6 @@ struct addi_board {
 			  struct comedi_insn *, unsigned int *);
 };
 
-/* MODULE INFO STRUCTURE */
-
-union str_ModuleInfo {
-	/* Incremental counter infos */
-	struct {
-		union {
-			struct {
-				unsigned char b_ModeRegister1;
-				unsigned char b_ModeRegister2;
-				unsigned char b_ModeRegister3;
-				unsigned char b_ModeRegister4;
-			} s_ByteModeRegister;
-			unsigned int dw_ModeRegister1_2_3_4;
-		} s_ModeRegister;
-
-		struct {
-			unsigned int b_IndexInit:1;
-			unsigned int b_CounterInit:1;
-			unsigned int b_ReferenceInit:1;
-			unsigned int b_IndexInterruptOccur:1;
-			unsigned int b_CompareLogicInit:1;
-			unsigned int b_FrequencyMeasurementInit:1;
-			unsigned int b_FrequencyMeasurementEnable:1;
-		} s_InitFlag;
-
-	} s_SiemensCounterInfo;
-
-	/* SSI infos */
-	struct {
-		unsigned char b_SSIProfile;
-		unsigned char b_PositionTurnLength;
-		unsigned char b_TurnCptLength;
-		unsigned char b_SSIInit;
-	} s_SSICounterInfo;
-
-	/* TTL I/O infos */
-	struct {
-		unsigned char b_TTLInit;
-		unsigned char b_PortConfiguration[4];
-	} s_TTLIOInfo;
-
-	/* Digital I/O infos */
-	struct {
-		unsigned char b_DigitalInit;
-		unsigned char b_ChannelAMode;
-		unsigned char b_ChannelBMode;
-		unsigned char b_OutputMemoryEnabled;
-		unsigned int dw_OutputMemory;
-	} s_DigitalIOInfo;
-
-      /*********************/
-	/* 82X54 timer infos */
-      /*********************/
-
-	struct {
-		struct {
-			unsigned char b_82X54Init;
-			unsigned char b_InputClockSelection;
-			unsigned char b_InputClockLevel;
-			unsigned char b_OutputLevel;
-			unsigned char b_HardwareGateLevel;
-			unsigned int dw_ConfigurationWord;
-		} s_82X54TimerInfo[3];
-		unsigned char b_InterruptMask;
-	} s_82X54ModuleInfo;
-
-      /*********************/
-	/* Chronometer infos */
-      /*********************/
-
-	struct {
-		unsigned char b_ChronoInit;
-		unsigned char b_InterruptMask;
-		unsigned char b_PCIInputClock;
-		unsigned char b_TimingUnit;
-		unsigned char b_CycleMode;
-		double d_TimingInterval;
-		unsigned int dw_ConfigReg;
-	} s_ChronoModuleInfo;
-
-      /***********************/
-	/* Pulse encoder infos */
-      /***********************/
-
-	struct {
-		struct {
-			unsigned char b_PulseEncoderInit;
-		} s_PulseEncoderInfo[4];
-		unsigned int dw_SetRegister;
-		unsigned int dw_ControlRegister;
-		unsigned int dw_StatusRegister;
-	} s_PulseEncoderModuleInfo;
-
-	/* Tor conter infos */
-	struct {
-		struct {
-			unsigned char b_TorCounterInit;
-			unsigned char b_TimingUnit;
-			unsigned char b_InterruptEnable;
-			double d_TimingInterval;
-			unsigned int ul_RealTimingInterval;
-		} s_TorCounterInfo[2];
-		unsigned char b_PCIInputClock;
-	} s_TorCounterModuleInfo;
-
-	/* PWM infos */
-	struct {
-		struct {
-			unsigned char b_PWMInit;
-			unsigned char b_TimingUnit;
-			unsigned char b_InterruptEnable;
-			double d_LowTiming;
-			double d_HighTiming;
-			unsigned int ul_RealLowTiming;
-			unsigned int ul_RealHighTiming;
-		} s_PWMInfo[2];
-		unsigned char b_ClockSelection;
-	} s_PWMModuleInfo;
-
-	/* ETM infos */
-	struct {
-		struct {
-			unsigned char b_ETMEnable;
-			unsigned char b_ETMInterrupt;
-		} s_ETMInfo[2];
-		unsigned char b_ETMInit;
-		unsigned char b_TimingUnit;
-		unsigned char b_ClockSelection;
-		double d_TimingInterval;
-		unsigned int ul_Timing;
-	} s_ETMModuleInfo;
-
-	/* CDA infos */
-	struct {
-		unsigned char b_CDAEnable;
-		unsigned char b_CDAInterrupt;
-		unsigned char b_CDAInit;
-		unsigned char b_FctSelection;
-		unsigned char b_CDAReadFIFOOverflow;
-	} s_CDAModuleInfo;
-
-};
-
-/* Private structure for the addi_apci3120 driver */
 struct addi_private {
 	int iobase;
 	int i_IobaseAmcc;	/*  base+size for AMCC chip */
@@ -299,31 +155,6 @@ struct addi_private {
 	/* Pointer to the current process */
 	struct task_struct *tsk_Current;
 
-	/* Hardware board infos for 1710 */
-	struct {
-		unsigned int ui_Address;	/* Board address */
-		unsigned int ui_FlashAddress;
-		unsigned char b_InterruptNbr;	/* Board interrupt number */
-		unsigned char b_SlotNumber;	/* PCI slot number */
-		unsigned char b_BoardVersion;
-		unsigned int dw_MolduleConfiguration[4];	/* Module config */
-	} s_BoardInfos;
-
-	/* Interrupt infos */
-	struct {
-		unsigned int ul_InterruptOccur;	/* 0   : No interrupt occur */
-						/* > 0 : Interrupt occur */
-		unsigned int ui_Read;	/* Read FIFO */
-		unsigned int ui_Write;	/* Write FIFO */
-		struct {
-			unsigned char b_OldModuleMask;
-			unsigned int ul_OldInterruptMask;	/* Interrupt mask */
-			unsigned int ul_OldCounterLatchValue;	/* Interrupt counter value */
-		} s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
-	} s_InterruptParameters;
-
-	union str_ModuleInfo s_ModuleInfo[4];
-
 	/* Parameters read from EEPROM overriding static board info */
 	struct {
 		int i_NbrAiChannel;	/*  num of A/D chans */
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
index dc031c4..aafc172 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
@@ -22,6 +22,8 @@
  * for more details.
  */
 
+#include <linux/delay.h>
+
 #define NVRAM_USER_DATA_START	0x100
 
 #define NVCMD_BEGIN_READ	(0x7 << 5)	/* nvRam begin read command */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
deleted file mode 100644
index b1a7ec1..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+++ /dev/null
@@ -1,1314 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.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.
-
-@endverbatim
-*/
-/*
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-------------------------------+---------------------------------------+
-  | Project     : APCI-1710       | Compiler   : GCC                      |
-  | Module name : hwdrv_apci1710.c| Version    : 2.96                     |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
-  +-------------------------------+---------------------------------------+
-  | Description :   Hardware Layer Access For APCI-1710                   |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +----------+-----------+------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  |          |           |                                                |
-  +----------+-----------+------------------------------------------------+
-*/
-
-#define COMEDI_SUBD_TTLIO		11	/* Digital Input Output But TTL */
-#define COMEDI_SUBD_PWM			12	/* Pulse width Measurement */
-#define COMEDI_SUBD_SSI			13	/* Synchronous serial interface */
-#define COMEDI_SUBD_TOR			14	/* Tor counter */
-#define COMEDI_SUBD_CHRONO		15	/* Chrono meter */
-#define COMEDI_SUBD_PULSEENCODER	16	/* Pulse Encoder INP CPT */
-#define COMEDI_SUBD_INCREMENTALCOUNTER	17	/* Incremental Counter */
-
-#define APCI1710_BOARD_NAME		"apci1710"
-#define APCI1710_BOARD_DEVICE_ID	0x818F
-#define APCI1710_ADDRESS_RANGE		256
-#define APCI1710_CONFIG_ADDRESS_RANGE	8
-#define APCI1710_INCREMENTAL_COUNTER	0x53430000UL
-#define APCI1710_SSI_COUNTER		0x53490000UL
-#define APCI1710_TTL_IO			0x544C0000UL
-#define APCI1710_DIGITAL_IO		0x44490000UL
-#define APCI1710_82X54_TIMER		0x49430000UL
-#define APCI1710_CHRONOMETER		0x43480000UL
-#define APCI1710_PULSE_ENCODER		0x495A0000UL
-#define APCI1710_TOR_COUNTER		0x544F0000UL
-#define APCI1710_PWM			0x50570000UL
-#define APCI1710_ETM			0x45540000UL
-#define APCI1710_CDA			0x43440000UL
-#define APCI1710_DISABLE		0
-#define APCI1710_ENABLE			1
-#define APCI1710_SYNCHRONOUS_MODE	1
-#define APCI1710_ASYNCHRONOUS_MODE	0
-
-#include "APCI1710_Inp_cpt.c"
-
-#include "APCI1710_Ssi.c"
-#include "APCI1710_Tor.c"
-#include "APCI1710_Ttl.c"
-#include "APCI1710_Dig_io.c"
-#include "APCI1710_82x54.c"
-#include "APCI1710_Chrono.c"
-#include "APCI1710_Pwm.c"
-#include "APCI1710_INCCPT.c"
-
-static const struct comedi_lrange range_apci1710_ttl = {
-	4, {
-		BIP_RANGE(10),
-		BIP_RANGE(5),
-		BIP_RANGE(2),
-		BIP_RANGE(1)
-	}
-};
-
-static const struct comedi_lrange range_apci1710_ssi = {
-	4, {
-		BIP_RANGE(10),
-		BIP_RANGE(5),
-		BIP_RANGE(2),
-		BIP_RANGE(1)
-	}
-};
-
-static const struct comedi_lrange range_apci1710_inccpt = {
-	4, {
-		BIP_RANGE(10),
-		BIP_RANGE(5),
-		BIP_RANGE(2),
-		BIP_RANGE(1)
-	}
-};
-
-static void i_ADDI_AttachPCI1710(struct comedi_device *dev)
-{
-	struct comedi_subdevice *s;
-	int ret = 0;
-	int n_subdevices = 9;
-
-	ret = comedi_alloc_subdevices(dev, n_subdevices);
-	if (ret)
-		return;
-
-	/*  Allocate and Initialise Timer Subdevice Structures */
-	s = &dev->subdevices[0];
-
-	s->type = COMEDI_SUBD_TIMER;
-	s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 3;
-	s->maxdata = 0;
-	s->len_chanlist = 3;
-	s->range_table = &range_digital;
-	s->insn_write = i_APCI1710_InsnWriteEnableDisableTimer;
-	s->insn_read = i_APCI1710_InsnReadAllTimerValue;
-	s->insn_config = i_APCI1710_InsnConfigInitTimer;
-	s->insn_bits = i_APCI1710_InsnBitsTimer;
-
-	/*  Allocate and Initialise DIO Subdevice Structures */
-	s = &dev->subdevices[1];
-
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 7;
-	s->maxdata = 1;
-	s->len_chanlist = 7;
-	s->range_table = &range_digital;
-	s->insn_config = i_APCI1710_InsnConfigDigitalIO;
-	s->insn_read = i_APCI1710_InsnReadDigitalIOChlValue;
-	s->insn_bits = i_APCI1710_InsnBitsDigitalIOPortOnOff;
-	s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff;
-
-	/*  Allocate and Initialise Chrono Subdevice Structures */
-	s = &dev->subdevices[2];
-
-	s->type = COMEDI_SUBD_CHRONO;
-	s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 4;
-	s->maxdata = 0;
-	s->len_chanlist = 4;
-	s->range_table = &range_digital;
-	s->insn_write = i_APCI1710_InsnWriteEnableDisableChrono;
-	s->insn_read = i_APCI1710_InsnReadChrono;
-	s->insn_config = i_APCI1710_InsnConfigInitChrono;
-	s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO;
-
-	/*  Allocate and Initialise PWM Subdevice Structures */
-	s = &dev->subdevices[3];
-	s->type = COMEDI_SUBD_PWM;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 3;
-	s->maxdata = 1;
-	s->len_chanlist = 3;
-	s->range_table = &range_digital;
-	s->io_bits = 0;		/* all bits input */
-	s->insn_config = i_APCI1710_InsnConfigPWM;
-	s->insn_read = i_APCI1710_InsnReadGetPWMStatus;
-	s->insn_write = i_APCI1710_InsnWritePWM;
-	s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt;
-
-	/*  Allocate and Initialise TTLIO Subdevice Structures */
-	s = &dev->subdevices[4];
-	s->type = COMEDI_SUBD_TTLIO;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->len_chanlist = 8;
-	s->range_table = &range_apci1710_ttl;	/*  to pass arguments in range */
-	s->insn_config = i_APCI1710_InsnConfigInitTTLIO;
-	s->insn_bits = i_APCI1710_InsnBitsReadTTLIO;
-	s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff;
-	s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue;
-
-	/*  Allocate and Initialise TOR Subdevice Structures */
-	s = &dev->subdevices[5];
-	s->type = COMEDI_SUBD_TOR;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->len_chanlist = 8;
-	s->range_table = &range_digital;
-	s->io_bits = 0;		/* all bits input */
-	s->insn_config = i_APCI1710_InsnConfigInitTorCounter;
-	s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation;
-	s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter;
-	s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue;
-
-	/*  Allocate and Initialise SSI Subdevice Structures */
-	s = &dev->subdevices[6];
-	s->type = COMEDI_SUBD_SSI;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 4;
-	s->maxdata = 1;
-	s->len_chanlist = 4;
-	s->range_table = &range_apci1710_ssi;
-	s->insn_config = i_APCI1710_InsnConfigInitSSI;
-	s->insn_read = i_APCI1710_InsnReadSSIValue;
-	s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO;
-
-	/*  Allocate and Initialise PULSEENCODER Subdevice Structures */
-	s = &dev->subdevices[7];
-	s->type = COMEDI_SUBD_PULSEENCODER;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 4;
-	s->maxdata = 1;
-	s->len_chanlist = 4;
-	s->range_table = &range_digital;
-	s->insn_config = i_APCI1710_InsnConfigInitPulseEncoder;
-	s->insn_write = i_APCI1710_InsnWriteEnableDisablePulseEncoder;
-	s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder;
-	s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder;
-
-	/*  Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures */
-	s = &dev->subdevices[8];
-	s->type = COMEDI_SUBD_INCREMENTALCOUNTER;
-	s->subdev_flags =
-		SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-	s->n_chan = 500;
-	s->maxdata = 1;
-	s->len_chanlist = 500;
-	s->range_table = &range_apci1710_inccpt;
-	s->insn_config = i_APCI1710_InsnConfigINCCPT;
-	s->insn_write = i_APCI1710_InsnWriteINCCPT;
-	s->insn_read = i_APCI1710_InsnReadINCCPT;
-	s->insn_bits = i_APCI1710_InsnBitsINCCPT;
-}
-
-static int i_APCI1710_Reset(struct comedi_device *dev)
-{
-	struct addi_private *devpriv = dev->private;
-	int ret;
-	unsigned int dw_Dummy;
-
-	/*********************************/
-	/* Read all module configuration */
-	/*********************************/
-	ret = inl(devpriv->s_BoardInfos.ui_Address + 60);
-	devpriv->s_BoardInfos.dw_MolduleConfiguration[0] = ret;
-
-	ret = inl(devpriv->s_BoardInfos.ui_Address + 124);
-	devpriv->s_BoardInfos.dw_MolduleConfiguration[1] = ret;
-
-	ret = inl(devpriv->s_BoardInfos.ui_Address + 188);
-	devpriv->s_BoardInfos.dw_MolduleConfiguration[2] = ret;
-
-	ret = inl(devpriv->s_BoardInfos.ui_Address + 252);
-	devpriv->s_BoardInfos.dw_MolduleConfiguration[3] = ret;
-
-	/*  outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60); */
-	outl(0x83838383, devpriv->s_BoardInfos.ui_Address + 0x60);
-
-	devpriv->s_BoardInfos.b_BoardVersion = 1;
-
-	/*  Enable the interrupt for the controller */
-	dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38);
-	outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38);
-
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function's Name   : __void__ v_APCI1710_InterruptFunction                  |
-|				(unsigned char b_Interrupt, __CPPARGS)                |
-+----------------------------------------------------------------------------+
-| Task              : APCI-1710 interrupt function                           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned char b_Interrupt : Interrupt number                    |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0 : OK                                                 |
-|                    -1 : Error                                              |
-+----------------------------------------------------------------------------+
-*/
-
-static void v_APCI1710_Interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	struct addi_private *devpriv = dev->private;
-	unsigned char b_ModuleCpt = 0;
-	unsigned char b_InterruptFlag = 0;
-	unsigned char b_PWMCpt = 0;
-	unsigned char b_TorCounterCpt = 0;
-	unsigned char b_PulseIncoderCpt = 0;
-	unsigned int ui_16BitValue;
-	unsigned int ul_InterruptLatchReg = 0;
-	unsigned int ul_LatchRegisterValue = 0;
-	unsigned int ul_82X54InterruptStatus;
-	unsigned int ul_StatusRegister;
-
-	union str_ModuleInfo *ps_ModuleInfo;
-
-	printk("APCI1710 Interrupt\n");
-	for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt++, ps_ModuleInfo++) {
-
-		 /**************************/
-		/* 1199/0225 to 0100/0226 */
-		 /**************************/
-		ps_ModuleInfo = &devpriv->s_ModuleInfo[b_ModuleCpt];
-
-		 /***********************/
-		/* Test if 82X54 timer */
-		 /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_82X54_TIMER) {
-
-			/* printk("TIMER Interrupt Occurred\n"); */
-			ul_82X54InterruptStatus = inl(devpriv->s_BoardInfos.
-				ui_Address + 12 + (64 * b_ModuleCpt));
-
-		    /***************************/
-			/* Test if interrupt occur */
-		    /***************************/
-
-			if ((ul_82X54InterruptStatus & ps_ModuleInfo->
-					s_82X54ModuleInfo.
-					b_InterruptMask) != 0) {
-				devpriv->
-					s_InterruptParameters.
-					s_FIFOInterruptParameters[devpriv->
-					s_InterruptParameters.
-					ui_Write].
-					ul_OldInterruptMask =
-					(ul_82X54InterruptStatus &
-					ps_ModuleInfo->s_82X54ModuleInfo.
-					b_InterruptMask) << 4;
-
-				devpriv->
-					s_InterruptParameters.
-					s_FIFOInterruptParameters[devpriv->
-					s_InterruptParameters.
-					ui_Write].
-					b_OldModuleMask = 1 << b_ModuleCpt;
-
-				devpriv->
-					s_InterruptParameters.
-					s_FIFOInterruptParameters[devpriv->
-					s_InterruptParameters.
-					ui_Write].ul_OldCounterLatchValue = 0;
-
-				devpriv->
-					s_InterruptParameters.
-					ul_InterruptOccur++;
-
-		       /****************************/
-				/* Increment the write FIFO */
-		       /****************************/
-
-				devpriv->
-					s_InterruptParameters.
-					ui_Write = (devpriv->
-					s_InterruptParameters.
-					ui_Write + 1) % APCI1710_SAVE_INTERRUPT;
-
-				b_InterruptFlag = 1;
-
-			     /**********************/
-				/* Call user function */
-			     /**********************/
-				/* Send a signal to from kernel to user space */
-				send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			}	/*  if ((ul_82X54InterruptStatus & 0x7) != 0) */
-		}		/*  82X54 timer */
-
-		 /***************************/
-		/* Test if increm. counter */
-		 /***************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
-
-			ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
-				ui_Address + (64 * b_ModuleCpt));
-
-		    /*********************/
-			/* Test if interrupt */
-		    /*********************/
-
-			if ((ul_InterruptLatchReg & 0x22) && (ps_ModuleInfo->
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister2 & 0x80)) {
-		       /************************************/
-				/* Test if strobe latch I interrupt */
-		       /************************************/
-
-				if (ul_InterruptLatchReg & 2) {
-					ul_LatchRegisterValue =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 4 +
-						(64 * b_ModuleCpt));
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].ul_OldInterruptMask =
-						1UL;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].b_OldModuleMask =
-						1 << b_ModuleCpt;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].
-						ul_OldCounterLatchValue =
-						ul_LatchRegisterValue;
-
-					devpriv->
-						s_InterruptParameters.
-						ul_InterruptOccur++;
-
-			  /****************************/
-					/* 0899/0224 to 1199/0225   */
-			  /****************************/
-					/* Increment the write FIFO */
-		      /****************************/
-
-					devpriv->
-						s_InterruptParameters.
-						ui_Write = (devpriv->
-						s_InterruptParameters.
-						ui_Write +
-						1) % APCI1710_SAVE_INTERRUPT;
-
-					b_InterruptFlag = 1;
-
-				/**********************/
-					/* Call user function */
-				/**********************/
-					/* Send a signal to from kernel to user space */
-					send_sig(SIGIO, devpriv->tsk_Current,
-						0);
-
-				}
-
-		       /*************************************/
-				/* Test if strobe latch II interrupt */
-		       /*************************************/
-
-				if (ul_InterruptLatchReg & 0x20) {
-
-					ul_LatchRegisterValue =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 8 +
-						(64 * b_ModuleCpt));
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].ul_OldInterruptMask =
-						2UL;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].b_OldModuleMask =
-						1 << b_ModuleCpt;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].
-						ul_OldCounterLatchValue =
-						ul_LatchRegisterValue;
-
-					devpriv->
-						s_InterruptParameters.
-						ul_InterruptOccur++;
-
-			  /****************************/
-					/* 0899/0224 to 1199/0225   */
-			  /****************************/
-					/* Increment the write FIFO */
-			  /****************************/
-
-					devpriv->
-						s_InterruptParameters.
-						ui_Write = (devpriv->
-						s_InterruptParameters.
-						ui_Write +
-						1) % APCI1710_SAVE_INTERRUPT;
-
-					b_InterruptFlag = 1;
-
-			    /**********************/
-					/* Call user function */
-				/**********************/
-					/* Send a signal to from kernel to user space */
-					send_sig(SIGIO, devpriv->tsk_Current,
-						0);
-
-				}
-			}
-
-			ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
-				ui_Address + 24 + (64 * b_ModuleCpt));
-
-		    /***************************/
-			/* Test if index interrupt */
-		    /***************************/
-
-			if (ul_InterruptLatchReg & 0x8) {
-				ps_ModuleInfo->
-					s_SiemensCounterInfo.
-					s_InitFlag.b_IndexInterruptOccur = 1;
-
-				if (ps_ModuleInfo->
-					s_SiemensCounterInfo.
-					s_ModeRegister.
-					s_ByteModeRegister.
-					b_ModeRegister2 &
-					APCI1710_INDEX_AUTO_MODE) {
-
-					outl(ps_ModuleInfo->
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						dw_ModeRegister1_2_3_4,
-						devpriv->s_BoardInfos.
-						ui_Address + 20 +
-						(64 * b_ModuleCpt));
-				}
-
-		       /*****************************/
-				/* Test if interrupt enabled */
-		       /*****************************/
-
-				if ((ps_ModuleInfo->
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister3 &
-						APCI1710_ENABLE_INDEX_INT) ==
-					APCI1710_ENABLE_INDEX_INT) {
-					devpriv->s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].ul_OldInterruptMask =
-						4UL;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].b_OldModuleMask =
-						1 << b_ModuleCpt;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].
-						ul_OldCounterLatchValue =
-						ul_LatchRegisterValue;
-
-					devpriv->
-						s_InterruptParameters.
-						ul_InterruptOccur++;
-
-			  /****************************/
-					/* 0899/0224 to 1199/0225   */
-			  /****************************/
-					/* Increment the write FIFO */
-			  /****************************/
-
-					devpriv->
-						s_InterruptParameters.
-						ui_Write = (devpriv->
-						s_InterruptParameters.
-						ui_Write +
-						1) % APCI1710_SAVE_INTERRUPT;
-
-					b_InterruptFlag = 1;
-
-				/**********************/
-					/* Call user function */
-				/**********************/
-					/* Send a signal to from kernel to user space */
-					send_sig(SIGIO, devpriv->tsk_Current,
-						0);
-
-				}
-			}
-
-		    /*****************************/
-			/* Test if compare interrupt */
-		    /*****************************/
-
-			if (ul_InterruptLatchReg & 0x10) {
-		       /*****************************/
-				/* Test if interrupt enabled */
-		       /*****************************/
-
-				if ((ps_ModuleInfo->
-						s_SiemensCounterInfo.
-						s_ModeRegister.
-						s_ByteModeRegister.
-						b_ModeRegister3 &
-						APCI1710_ENABLE_COMPARE_INT) ==
-					APCI1710_ENABLE_COMPARE_INT) {
-					devpriv->s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].ul_OldInterruptMask =
-						8UL;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].b_OldModuleMask =
-						1 << b_ModuleCpt;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].
-						ul_OldCounterLatchValue =
-						ul_LatchRegisterValue;
-
-					devpriv->
-						s_InterruptParameters.
-						ul_InterruptOccur++;
-
-			  /****************************/
-					/* 0899/0224 to 1199/0225   */
-			  /****************************/
-					/* Increment the write FIFO */
-		      /****************************/
-
-					devpriv->
-						s_InterruptParameters.
-						ui_Write = (devpriv->
-						s_InterruptParameters.
-						ui_Write +
-						1) % APCI1710_SAVE_INTERRUPT;
-
-					b_InterruptFlag = 1;
-
-				/**********************/
-					/* Call user function */
-				/**********************/
-					/* Send a signal to from kernel to user space */
-					send_sig(SIGIO, devpriv->tsk_Current,
-						0);
-
-				}
-			}
-
-		    /*******************************************/
-			/* Test if frequency measurement interrupt */
-		    /*******************************************/
-
-			if (ul_InterruptLatchReg & 0x20) {
-		       /*******************/
-				/* Read the status */
-		       /*******************/
-
-				ul_StatusRegister = inl(devpriv->s_BoardInfos.
-					ui_Address + 32 + (64 * b_ModuleCpt));
-
-		       /******************/
-				/* Read the value */
-		       /******************/
-
-				ul_LatchRegisterValue =
-					inl(devpriv->s_BoardInfos.ui_Address +
-					28 + (64 * b_ModuleCpt));
-
-				switch ((ul_StatusRegister >> 1) & 3) {
-				case 0:
-			       /*************************/
-					/* Test the counter mode */
-			       /*************************/
-
-					if ((devpriv->s_ModuleInfo[b_ModuleCpt].
-							s_SiemensCounterInfo.
-							s_ModeRegister.
-							s_ByteModeRegister.
-							b_ModeRegister1 &
-							APCI1710_16BIT_COUNTER)
-						== APCI1710_16BIT_COUNTER) {
-				  /****************************************/
-						/* Test if 16-bit counter 1 pulse occur */
-				  /****************************************/
-
-						if ((ul_LatchRegisterValue &
-								0xFFFFU) != 0) {
-							ui_16BitValue =
-								(unsigned int)
-								ul_LatchRegisterValue
-								& 0xFFFFU;
-							ul_LatchRegisterValue =
-								(ul_LatchRegisterValue
-								& 0xFFFF0000UL)
-								| (0xFFFFU -
-								ui_16BitValue);
-						}
-
-				  /****************************************/
-						/* Test if 16-bit counter 2 pulse occur */
-				  /****************************************/
-
-						if ((ul_LatchRegisterValue &
-								0xFFFF0000UL) !=
-							0) {
-							ui_16BitValue =
-								(unsigned int) (
-								(ul_LatchRegisterValue
-									>> 16) &
-								0xFFFFU);
-							ul_LatchRegisterValue =
-								(ul_LatchRegisterValue
-								& 0xFFFFUL) |
-								((0xFFFFU -
-									ui_16BitValue)
-								<< 16);
-						}
-					} else {
-						if (ul_LatchRegisterValue != 0) {
-							ul_LatchRegisterValue =
-								0xFFFFFFFFUL -
-								ul_LatchRegisterValue;
-						}
-					}
-					break;
-
-				case 1:
-			       /****************************************/
-					/* Test if 16-bit counter 2 pulse occur */
-			       /****************************************/
-
-					if ((ul_LatchRegisterValue &
-							0xFFFF0000UL) != 0) {
-						ui_16BitValue =
-							(unsigned int) (
-							(ul_LatchRegisterValue
-								>> 16) &
-							0xFFFFU);
-						ul_LatchRegisterValue =
-							(ul_LatchRegisterValue &
-							0xFFFFUL) | ((0xFFFFU -
-								ui_16BitValue)
-							<< 16);
-					}
-					break;
-
-				case 2:
-			       /****************************************/
-					/* Test if 16-bit counter 1 pulse occur */
-			       /****************************************/
-
-					if ((ul_LatchRegisterValue & 0xFFFFU) !=
-						0) {
-						ui_16BitValue =
-							(unsigned int)
-							ul_LatchRegisterValue &
-							0xFFFFU;
-						ul_LatchRegisterValue =
-							(ul_LatchRegisterValue &
-							0xFFFF0000UL) | (0xFFFFU
-							- ui_16BitValue);
-					}
-					break;
-				}
-
-				devpriv->
-					s_InterruptParameters.
-					s_FIFOInterruptParameters[devpriv->
-					s_InterruptParameters.
-					ui_Write].
-					ul_OldInterruptMask = 0x10000UL;
-
-				devpriv->
-					s_InterruptParameters.
-					s_FIFOInterruptParameters[devpriv->
-					s_InterruptParameters.
-					ui_Write].
-					b_OldModuleMask = 1 << b_ModuleCpt;
-
-				devpriv->
-					s_InterruptParameters.
-					s_FIFOInterruptParameters[devpriv->
-					s_InterruptParameters.
-					ui_Write].
-					ul_OldCounterLatchValue =
-					ul_LatchRegisterValue;
-
-				devpriv->
-					s_InterruptParameters.
-					ul_InterruptOccur++;
-
-		       /****************************/
-				/* 0899/0224 to 1199/0225   */
-		       /****************************/
-				/* Increment the write FIFO */
-		       /****************************/
-
-				devpriv->
-					s_InterruptParameters.
-					ui_Write = (devpriv->
-					s_InterruptParameters.
-					ui_Write + 1) % APCI1710_SAVE_INTERRUPT;
-
-				b_InterruptFlag = 1;
-
-			     /**********************/
-				/* Call user function */
-			     /**********************/
-				/* Send a signal to from kernel to user space */
-				send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			}
-		}		/*  Incremental counter */
-
-		 /***************/
-		/* Test if CDA */
-		 /***************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_CDA) {
-		    /******************************************/
-			/* Test if CDA enable and functionality 0 */
-		    /******************************************/
-
-			if ((devpriv->s_ModuleInfo[b_ModuleCpt].
-					s_CDAModuleInfo.
-					b_CDAEnable == APCI1710_ENABLE)
-				&& (devpriv->s_ModuleInfo[b_ModuleCpt].
-					s_CDAModuleInfo.b_FctSelection == 0)) {
-		       /****************************/
-				/* Get the interrupt status */
-		       /****************************/
-
-				ul_StatusRegister = inl(devpriv->s_BoardInfos.
-					ui_Address + 16 + (64 * b_ModuleCpt));
-		       /***************************/
-				/* Test if interrupt occur */
-		       /***************************/
-
-				if (ul_StatusRegister & 1) {
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].ul_OldInterruptMask =
-						0x80000UL;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].b_OldModuleMask =
-						1 << b_ModuleCpt;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].
-						ul_OldCounterLatchValue = 0;
-
-					devpriv->
-						s_InterruptParameters.
-						ul_InterruptOccur++;
-
-			  /****************************/
-					/* Increment the write FIFO */
-			  /****************************/
-
-					devpriv->
-						s_InterruptParameters.
-						ui_Write = (devpriv->
-						s_InterruptParameters.
-						ui_Write +
-						1) % APCI1710_SAVE_INTERRUPT;
-
-					b_InterruptFlag = 1;
-
-				/**********************/
-					/* Call user function */
-				/**********************/
-
-					/* Send a signal to from kernel to user space */
-					send_sig(SIGIO, devpriv->tsk_Current,
-						0);
-
-				}	/*  if (ul_StatusRegister & 1) */
-
-			}
-		}		/*  CDA */
-
-		 /***********************/
-		/* Test if PWM counter */
-		 /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_PWM) {
-			for (b_PWMCpt = 0; b_PWMCpt < 2; b_PWMCpt++) {
-		       /*************************************/
-				/* Test if PWM interrupt initialised */
-		       /*************************************/
-
-				if (devpriv->
-					s_ModuleInfo[b_ModuleCpt].
-					s_PWMModuleInfo.
-					s_PWMInfo[b_PWMCpt].
-					b_InterruptEnable == APCI1710_ENABLE) {
-			  /*****************************/
-					/* Read the interrupt status */
-			  /*****************************/
-
-					ul_StatusRegister =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 16 +
-						(20 * b_PWMCpt) +
-						(64 * b_ModuleCpt));
-
-			  /***************************/
-					/* Test if interrupt occur */
-			  /***************************/
-
-					if (ul_StatusRegister & 0x1) {
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							ul_OldInterruptMask =
-							0x4000UL << b_PWMCpt;
-
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							b_OldModuleMask =
-							1 << b_ModuleCpt;
-
-						devpriv->
-							s_InterruptParameters.
-							ul_InterruptOccur++;
-
-			     /****************************/
-						/* Increment the write FIFO */
-			     /****************************/
-
-						devpriv->
-							s_InterruptParameters.
-							ui_Write = (devpriv->
-							s_InterruptParameters.
-							ui_Write +
-							1) %
-							APCI1710_SAVE_INTERRUPT;
-
-						b_InterruptFlag = 1;
-
-				   /**********************/
-						/* Call user function */
-				   /**********************/
-						/* Send a signal to from kernel to user space */
-						send_sig(SIGIO,
-							devpriv->tsk_Current,
-							0);
-
-					}	/*  if (ul_StatusRegister & 0x1) */
-				}	/*  if (APCI1710_ENABLE) */
-			}	/*  for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++) */
-		}		/*  PWM counter */
-
-		 /***********************/
-		/* Test if tor counter */
-		 /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
-			for (b_TorCounterCpt = 0; b_TorCounterCpt < 2;
-				b_TorCounterCpt++) {
-		       /*************************************/
-				/* Test if tor interrupt initialised */
-		       /*************************************/
-
-				if (devpriv->
-					s_ModuleInfo[b_ModuleCpt].
-					s_TorCounterModuleInfo.
-					s_TorCounterInfo[b_TorCounterCpt].
-					b_InterruptEnable == APCI1710_ENABLE) {
-			  /*****************************/
-					/* Read the interrupt status */
-			  /*****************************/
-
-					ul_StatusRegister =
-						inl(devpriv->s_BoardInfos.
-						ui_Address + 12 +
-						(16 * b_TorCounterCpt) +
-						(64 * b_ModuleCpt));
-
-			  /***************************/
-					/* Test if interrupt occur */
-			  /***************************/
-
-					if (ul_StatusRegister & 0x1) {
-			     /******************************/
-						/* Read the tor counter value */
-			     /******************************/
-
-						ul_LatchRegisterValue =
-							inl(devpriv->
-							s_BoardInfos.
-							ui_Address + 0 +
-							(16 * b_TorCounterCpt) +
-							(64 * b_ModuleCpt));
-
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							ul_OldInterruptMask =
-							0x1000UL <<
-							b_TorCounterCpt;
-
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							b_OldModuleMask =
-							1 << b_ModuleCpt;
-
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							ul_OldCounterLatchValue
-							= ul_LatchRegisterValue;
-
-						devpriv->
-							s_InterruptParameters.
-							ul_InterruptOccur++;
-
-			     /****************************/
-						/* Increment the write FIFO */
-			     /****************************/
-
-						devpriv->
-							s_InterruptParameters.
-							ui_Write = (devpriv->
-							s_InterruptParameters.
-							ui_Write +
-							1) %
-							APCI1710_SAVE_INTERRUPT;
-
-						b_InterruptFlag = 1;
-
-				   /**********************/
-						/* Call user function */
-				   /**********************/
-
-						/* Send a signal to from kernel to user space */
-						send_sig(SIGIO,
-							devpriv->tsk_Current,
-							0);
-					}	/*  if (ul_StatusRegister & 0x1) */
-				}	/*  if (APCI1710_ENABLE) */
-			}	/*  for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++) */
-		}		/*  Tor counter */
-
-		 /***********************/
-		/* Test if chronometer */
-		 /***********************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
-
-			/* printk("APCI1710 Chrono Interrupt\n"); */
-		    /*****************************/
-			/* Read the interrupt status */
-		    /*****************************/
-
-			ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
-				ui_Address + 12 + (64 * b_ModuleCpt));
-
-		    /***************************/
-			/* Test if interrupt occur */
-		    /***************************/
-
-			if ((ul_InterruptLatchReg & 0x8) == 0x8) {
-		       /****************************/
-				/* Clear the interrupt flag */
-		       /****************************/
-
-				outl(0, devpriv->s_BoardInfos.
-					ui_Address + 32 + (64 * b_ModuleCpt));
-
-		       /***************************/
-				/* Test if continuous mode */
-		       /***************************/
-
-				if (ps_ModuleInfo->
-					s_ChronoModuleInfo.
-					b_CycleMode == APCI1710_ENABLE) {
-			  /********************/
-					/* Clear the status */
-			  /********************/
-
-					outl(0, devpriv->s_BoardInfos.
-						ui_Address + 36 +
-						(64 * b_ModuleCpt));
-				}
-
-		       /*************************/
-				/* Read the timing value */
-		       /*************************/
-
-				ul_LatchRegisterValue =
-					inl(devpriv->s_BoardInfos.ui_Address +
-					4 + (64 * b_ModuleCpt));
-
-		       /*****************************/
-				/* Test if interrupt enabled */
-		       /*****************************/
-
-				if (ps_ModuleInfo->
-					s_ChronoModuleInfo.b_InterruptMask) {
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].ul_OldInterruptMask =
-						0x80;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].b_OldModuleMask =
-						1 << b_ModuleCpt;
-
-					devpriv->
-						s_InterruptParameters.
-						s_FIFOInterruptParameters
-						[devpriv->s_InterruptParameters.
-						ui_Write].
-						ul_OldCounterLatchValue =
-						ul_LatchRegisterValue;
-
-					devpriv->
-						s_InterruptParameters.
-						ul_InterruptOccur++;
-
-			  /****************************/
-					/* Increment the write FIFO */
-		      /****************************/
-
-					devpriv->
-						s_InterruptParameters.
-						ui_Write = (devpriv->
-						s_InterruptParameters.
-						ui_Write +
-						1) % APCI1710_SAVE_INTERRUPT;
-
-					b_InterruptFlag = 1;
-
-				/**********************/
-					/* Call user function */
-				/**********************/
-					/* Send a signal to from kernel to user space */
-					send_sig(SIGIO, devpriv->tsk_Current,
-						0);
-
-				}
-			}
-		}		/*  Chronometer */
-
-		 /*************************/
-		/* Test if pulse encoder */
-		 /*************************/
-
-		if ((devpriv->s_BoardInfos.
-				dw_MolduleConfiguration[b_ModuleCpt] &
-				0xFFFF0000UL) == APCI1710_PULSE_ENCODER) {
-		    /****************************/
-			/* Read the status register */
-		    /****************************/
-
-			ul_StatusRegister = inl(devpriv->s_BoardInfos.
-				ui_Address + 20 + (64 * b_ModuleCpt));
-
-			if (ul_StatusRegister & 0xF) {
-				for (b_PulseIncoderCpt = 0;
-					b_PulseIncoderCpt < 4;
-					b_PulseIncoderCpt++) {
-			  /*************************************/
-					/* Test if pulse encoder initialised */
-			  /*************************************/
-
-					if ((ps_ModuleInfo->
-							s_PulseEncoderModuleInfo.
-							s_PulseEncoderInfo
-							[b_PulseIncoderCpt].
-							b_PulseEncoderInit == 1)
-						&& (((ps_ModuleInfo->s_PulseEncoderModuleInfo.dw_SetRegister >> b_PulseIncoderCpt) & 1) == 1) && (((ul_StatusRegister >> (b_PulseIncoderCpt)) & 1) == 1)) {
-						devpriv->s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							ul_OldInterruptMask =
-							0x100UL <<
-							b_PulseIncoderCpt;
-
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							b_OldModuleMask =
-							1 << b_ModuleCpt;
-
-						devpriv->
-							s_InterruptParameters.
-							s_FIFOInterruptParameters
-							[devpriv->
-							s_InterruptParameters.
-							ui_Write].
-							ul_OldCounterLatchValue
-							= ul_LatchRegisterValue;
-
-						devpriv->
-							s_InterruptParameters.
-							ul_InterruptOccur++;
-
-			     /****************************/
-						/* 0899/0224 to 1199/0225   */
-			     /****************************/
-						/* Increment the write FIFO */
-			     /****************************/
-
-						devpriv->
-							s_InterruptParameters.
-							ui_Write = (devpriv->
-							s_InterruptParameters.
-							ui_Write +
-							1) %
-							APCI1710_SAVE_INTERRUPT;
-
-						b_InterruptFlag = 1;
-
-				   /**********************/
-						/* Call user function */
-				   /**********************/
-						/* Send a signal to from kernel to user space */
-						send_sig(SIGIO,
-							devpriv->tsk_Current,
-							0);
-
-					}
-				}
-			}
-		}		/* pulse encoder */
-
-	}
-	return;
-
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index a89e505..1449b92 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -40,6 +40,8 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
   +----------+-----------+------------------------------------------------+
 */
 
+#include <linux/delay.h>
+
 /*
  * ADDON RELATED ADDITIONS
  */
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
index 43c2c10..8d229b2 100644
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ b/drivers/staging/comedi/drivers/addi_apci_035.c
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 8a93542..34ab067 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -22,6 +22,7 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -289,10 +290,9 @@ static int apci1032_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index b52cfe0..ae9ded6 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index b626738..08674c1 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -22,6 +22,7 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -136,10 +137,9 @@ static int apci1516_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 22bace6..c5717d6 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 1f7bed9..43296a6 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -22,6 +22,7 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
deleted file mode 100644
index c9e6471..0000000
--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include <linux/pci.h>
-
-#include <asm/i387.h>
-
-#include "../comedidev.h"
-#include "comedi_fc.h"
-#include "amcc_s5933.h"
-
-#include "addi-data/addi_common.h"
-
-static void fpu_begin(void)
-{
-	kernel_fpu_begin();
-}
-
-static void fpu_end(void)
-{
-	kernel_fpu_end();
-}
-
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_APCI1710.c"
-
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
-{
-	v_APCI1710_Interrupt(irq, d);
-	return IRQ_RETVAL(1);
-}
-
-static int apci1710_auto_attach(struct comedi_device *dev,
-					  unsigned long context_unused)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	struct addi_private *devpriv;
-	struct comedi_subdevice *s;
-	int ret;
-
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-	if (!devpriv)
-		return -ENOMEM;
-	dev->private = devpriv;
-
-	ret = comedi_pci_enable(dev);
-	if (ret)
-		return ret;
-	devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2);
-
-	if (pcidev->irq > 0) {
-		ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
-				  dev->board_name, dev);
-		if (ret == 0)
-			dev->irq = pcidev->irq;
-	}
-
-	i_ADDI_AttachPCI1710(dev);
-
-	i_APCI1710_Reset(dev);
-	return 0;
-}
-
-static void apci1710_detach(struct comedi_device *dev)
-{
-	if (dev->iobase)
-		i_APCI1710_Reset(dev);
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-	comedi_pci_disable(dev);
-}
-
-static struct comedi_driver apci1710_driver = {
-	.driver_name	= "addi_apci_1710",
-	.module		= THIS_MODULE,
-	.auto_attach	= apci1710_auto_attach,
-	.detach		= apci1710_detach,
-};
-
-static int apci1710_pci_probe(struct pci_dev *dev,
-			      const struct pci_device_id *id)
-{
-	return comedi_pci_auto_config(dev, &apci1710_driver, id->driver_data);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(apci1710_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMCC, APCI1710_BOARD_DEVICE_ID) },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, apci1710_pci_table);
-
-static struct pci_driver apci1710_pci_driver = {
-	.name		= "addi_apci_1710",
-	.id_table	= apci1710_pci_table,
-	.probe		= apci1710_pci_probe,
-	.remove		= comedi_pci_auto_unconfig,
-};
-module_comedi_pci_driver(apci1710_driver, apci1710_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 89ead8e..6b0ea16 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -22,8 +22,10 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 
 #include "../comedidev.h"
 #include "addi_watchdog.h"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index ca1bd92..92ac8ec 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -22,6 +22,7 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index 6145284..d804957 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -65,10 +66,9 @@ static int apci3120_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->pc_DriverName;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
index 17b540d..1213d5a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include <asm/i387.h>
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index f9b6368..d9650ff 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -22,6 +22,7 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
@@ -332,10 +333,9 @@ static int apci3501_auto_attach(struct comedi_device *dev,
 	int ao_n_chan;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index 5b37cbf..dbc0678 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -22,6 +22,7 @@
  * more details.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -801,10 +802,9 @@ static int apci3xxx_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c
index 7b21acc..23031fe 100644
--- a/drivers/staging/comedi/drivers/addi_watchdog.c
+++ b/drivers/staging/comedi/drivers/addi_watchdog.c
@@ -18,6 +18,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 #include "addi_watchdog.h"
 
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index b5e4e53..a67ad57 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -38,6 +38,7 @@ References:
 	- adl_pci9118.c
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -172,10 +173,9 @@ static int pci6208_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = boardinfo;
 	dev->board_name = boardinfo->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 0d9243a..81b7203 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -44,6 +44,7 @@ driver.
 Configuration Options: not applicable, uses comedi PCI auto config
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index 0b591b0..b3d0092 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -27,6 +27,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index af51c74..78cea19 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -64,6 +64,7 @@ TODO:
 
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -855,10 +856,9 @@ static int pci9111_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL);
+	dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private));
 	if (!dev_private)
 		return -ENOMEM;
-	dev->private = dev_private;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index cb4ef2d..22196ad 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -77,6 +77,7 @@ Configuration options:
  * manual attachment.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
@@ -2140,10 +2141,9 @@ static int pci9118_attach(struct comedi_device *dev,
 	softsshdelay = it->options[4];
 	hw_err_mask = it->options[5];
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	pcidev = pci9118_find_pci(dev, it);
 	if (!pcidev)
@@ -2160,10 +2160,9 @@ static int pci9118_auto_attach(struct comedi_device *dev,
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct pci9118_private *devpriv;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	dev->board_ptr = pci9118_find_boardinfo(pcidev);
 	if (dev->board_ptr == NULL) {
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index d187a7b..cdf5ba2 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -73,6 +73,9 @@ If you do not specify any options, they will default to
 
 */
 
+#include <linux/module.h>
+#include <linux/delay.h>
+
 #include "../comedidev.h"
 
 /* address scheme (page 2.17 of the manual) */
@@ -214,10 +217,9 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->unipolar = it->options[1];
 	devpriv->differential = it->options[2];
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index f847bbc..f84df46 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -41,6 +41,7 @@ Configuration options:
 	device will be used.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -1233,10 +1234,9 @@ static int pci1710_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 8430a27..f914fb1 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -43,6 +43,7 @@ TODO:
 3. Implement calibration.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -237,10 +238,9 @@ static int pci1723_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c
index da7462e..009a303 100644
--- a/drivers/staging/comedi/drivers/adv_pci1724.c
+++ b/drivers/staging/comedi/drivers/adv_pci1724.c
@@ -52,6 +52,8 @@ supported PCI devices are configured as comedi devices automatically.
 
 */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -123,10 +125,6 @@ static const struct comedi_lrange ao_ranges_1724 = { 4,
 	}
 };
 
-static const struct comedi_lrange *const ao_range_list_1724[NUM_AO_CHANNELS] = {
-	[0 ... NUM_AO_CHANNELS - 1] = &ao_ranges_1724,
-};
-
 /* this structure is for data unique to this hardware driver. */
 struct adv_pci1724_private {
 	int ao_value[NUM_AO_CHANNELS];
@@ -306,7 +304,7 @@ static int setup_subdevices(struct comedi_device *dev)
 	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
 	s->n_chan = NUM_AO_CHANNELS;
 	s->maxdata = 0x3fff;
-	s->range_table_list = ao_range_list_1724;
+	s->range_table = &ao_ranges_1724;
 	s->insn_read = ao_readback_insn;
 	s->insn_write = ao_winsn;
 
@@ -340,10 +338,9 @@ static int adv_pci1724_auto_attach(struct comedi_device *dev,
 	int retval;
 	unsigned int board_id;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* init software copies of output values to indicate we don't know
 	 * what the output value is since it has never been written. */
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 8e6ec75..f091fa0 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -29,6 +29,7 @@ Configuration options:
 
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 
@@ -1107,10 +1108,9 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index 279dfe8..abb2849 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -35,8 +35,8 @@ Notes:
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
-#include <linux/ioport.h>
 #include "8255.h"
 
 /*
@@ -202,10 +202,9 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index 029834d..afe87cc 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -30,8 +30,8 @@ Configuration Options:
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
-#include <linux/ioport.h>
 
 #define AIO_IIRO_16_SIZE	0x08
 #define AIO_IIRO_16_RELAY_0_7	0x00
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index e247810..dc1dee7 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -192,8 +192,7 @@
  * order they appear in the channel list.
  */
 
-#include <linux/slab.h>
-
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include "amplc_dio200.h"
@@ -272,10 +271,9 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	irq = it->options[1];
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], thisboard->mainsize);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
index 649fc69..32c490b 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -19,8 +19,8 @@
     GNU General Public License for more details.
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 
 #include "../comedidev.h"
 
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c
index d7d9f5c..a810a24 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c
@@ -220,9 +220,9 @@
  * order they appear in the channel list.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 
 #include "../comedidev.h"
 
@@ -380,10 +380,9 @@ static int dio200_pci_auto_attach(struct comedi_device *dev,
 	dev_info(dev->class_dev, "%s: attach pci %s (%s)\n",
 		 dev->driver->driver_name, pci_name(pci_dev), dev->board_name);
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 4e889b8..98075f9 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -47,6 +47,7 @@ the IRQ jumper.  If no interrupt is connected, then subdevice 1 is
 unused.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -467,10 +468,9 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	struct pc236_private *devpriv;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* Process options according to bus type. */
 	if (is_isa_board(thisboard)) {
@@ -510,10 +510,9 @@ static int pc236_auto_attach(struct comedi_device *dev,
 	dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n",
 		 pci_name(pci_dev));
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	dev->board_ptr = pc236_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 6546095..e710804 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -33,6 +33,7 @@ connected to a reed-relay. Relay contacts are closed when output is 1.
 The state of the outputs can be read.
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #define PC263_DRIVER_NAME	"amplc_pc263"
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index f1e36f0..179de53 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -98,6 +98,7 @@ Caveats:
      correctly.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -1419,10 +1420,9 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	dev_info(dev->class_dev, DRIVER_NAME ": attach\n");
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	pci_dev = pci224_find_pci_dev(dev, it);
 	if (!pci_dev)
@@ -1440,10 +1440,9 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused)
 	dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n",
 		 pci_name(pci_dev));
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	dev->board_ptr = pci224_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 846d644..43059c2 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -184,6 +184,7 @@ Support for PCI230+/260+, more triggered scan functionality, and workarounds
 for (or detection of) various hardware problems added by Ian Abbott.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -2615,10 +2616,9 @@ static int pci230_alloc_private(struct comedi_device *dev)
 {
 	struct pci230_private *devpriv;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	spin_lock_init(&devpriv->isr_spinlock);
 	spin_lock_init(&devpriv->res_spinlock);
diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c
index 4da900c..145bb48 100644
--- a/drivers/staging/comedi/drivers/amplc_pci263.c
+++ b/drivers/staging/comedi/drivers/amplc_pci263.c
@@ -32,6 +32,7 @@ connected to a reed-relay. Relay contacts are closed when output is 1.
 The state of the outputs can be read.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index 929218a3..217aa19c 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -35,8 +35,6 @@ http://robot0.ge.uiuc.edu/~spong/mecha/
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/timer.h>
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index ae9a208..05e01a3 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -34,8 +34,8 @@ Status: experimental
 
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 
 #include "../comedidev.h"
@@ -420,10 +420,9 @@ static int das16cs_auto_attach(struct comedi_device *dev,
 		return ret;
 	dev->irq = link->irq;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 58bca18..41d89ee 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -61,6 +61,7 @@ TODO:
 analog triggering on 1602 series
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -1444,10 +1445,9 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
 	dev->board_ptr  = thisboard;
 	dev->board_name = thisboard->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 43c0bf5..e6e4561 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -82,6 +82,7 @@ TODO:
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -4034,10 +4035,9 @@ static int auto_attach(struct comedi_device *dev,
 		return -ENODEV;
 	dev->board_ptr = thisboard;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	retval = comedi_pci_enable(dev);
 	if (retval)
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 2d3e920..94f1158 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -37,6 +37,7 @@
  * Only simple analog output writing is supported.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -348,10 +349,9 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = thisboard;
 	dev->board_name = thisboard->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 8b5c198..30520d4 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -35,8 +35,8 @@ No interrupts, multi channel or FIFO AI, although the card looks like it could s
 See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
 #include <linux/interrupt.h>
 
 #include "../comedidev.h"
@@ -210,10 +210,9 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
 	unsigned long iobase_8255;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 406cba8c..edf17b6 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -74,6 +74,7 @@ Configuration Options: not applicable, uses PCI auto config
     -Calin Culianu <calin@ajvar.org>
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -156,10 +157,9 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index 1a51866..7e20bf0 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -45,6 +45,7 @@ Configuration Options:
   within each minor will be concatenated together in the order given here.
 */
 
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include "../comedi.h"
@@ -298,10 +299,9 @@ static int bonding_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/*
 	 * Setup our bonding from config params.. sets up our private struct..
diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
index b3d89c8..26d9dbc 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.c
+++ b/drivers/staging/comedi/drivers/comedi_fc.c
@@ -19,6 +19,7 @@
     GNU General Public License for more details.
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index 772a8f5..f28a15f 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -76,9 +76,9 @@ pin, which can be used to wake up tasks.
    or http://www.linux-magazin.de/ausgabe/1999/10/IO/io.html
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 #include <linux/interrupt.h>
-#include <linux/ioport.h>
 
 #include "comedi_fc.h"
 
@@ -279,10 +279,9 @@ static int parport_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	s->type = COMEDI_SUBD_DIO;
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 907e7a3..16c0780 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -45,6 +45,7 @@ zero volts).
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include <asm/div64.h>
@@ -379,10 +380,9 @@ static int waveform_attach(struct comedi_device *dev,
 	int i;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* set default amplitude and period */
 	if (amplitude <= 0)
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 0fb9027..e781716 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -25,6 +25,7 @@ Status: works
 Configuration Options: not applicable, uses comedi PCI auto config
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 44c912b..de920cc 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -102,6 +102,7 @@ Configuration options: not applicable, uses PCI auto config
 
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -683,10 +684,9 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	result = comedi_pci_enable(dev);
 	if (result)
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 2e7e3e2..5f66970 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -33,7 +33,7 @@
  * cheap das08 hardware doesn't really support them.
  */
 
-#include <linux/delay.h>
+#include <linux/module.h>
 
 #include "../comedidev.h"
 
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 885fb17..f3ccc2c 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -39,8 +39,7 @@ Options (for pcm-das08):
 Command support does not exist, but could be added for this board.
 */
 
-#include <linux/delay.h>
-#include <linux/slab.h>
+#include <linux/module.h>
 
 #include "../comedidev.h"
 
@@ -78,10 +77,9 @@ static int das08_cs_auto_attach(struct comedi_device *dev,
 		return ret;
 	iobase = link->resource[0]->start;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	return das08_common_attach(dev, iobase);
 }
diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c
index 21a9438..4fb03d3 100644
--- a/drivers/staging/comedi/drivers/das08_isa.c
+++ b/drivers/staging/comedi/drivers/das08_isa.c
@@ -43,6 +43,7 @@
  *	[0] - base io address
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include "das08.h"
@@ -177,10 +178,9 @@ static int das08_isa_attach(struct comedi_device *dev,
 	struct das08_private_struct *devpriv;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], thisboard->iosize);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c
index 9c5d234..3a6d372 100644
--- a/drivers/staging/comedi/drivers/das08_pci.c
+++ b/drivers/staging/comedi/drivers/das08_pci.c
@@ -31,6 +31,7 @@
  * Configuration Options: not applicable, uses PCI auto config
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -59,10 +60,9 @@ static int das08_pci_auto_attach(struct comedi_device *dev,
 	struct das08_private_struct *devpriv;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* The das08 driver needs the board_ptr */
 	dev->board_ptr = &das08_pci_boards[0];
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index dbec3ba..93a8f09 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -1,80 +1,88 @@
 /*
-    comedi/drivers/das16.c
-    DAS16 driver
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-    Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
-    Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
-/*
-Driver: das16
-Description: DAS16 compatible boards
-Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
-Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
-  DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
-  DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
-  DAS-1602 (das-1602),
-  [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
-  PC104-DAS16JR/16 (pc104-das16jr/16),
-  CIO-DAS16JR/16 (cio-das16jr/16),
-  CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12),
-  CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
-  CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
-  CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
-Status: works
-Updated: 2003-10-12
-
-A rewrite of the das16 and das1600 drivers.
-Options:
-	[0] - base io address
-	[1] - irq (does nothing, irq is not used anymore)
-	[2] - dma (optional, required for comedi_command support)
-	[3] - master clock speed in MHz (optional, 1 or 10, ignored if
-		board can probe clock, defaults to 1)
-	[4] - analog input range lowest voltage in microvolts (optional,
-		only useful if your board does not have software
-		programmable gain)
-	[5] - analog input range highest voltage in microvolts (optional,
-		only useful if board does not have software programmable
-		gain)
-	[6] - analog output range lowest voltage in microvolts (optional)
-	[7] - analog output range highest voltage in microvolts (optional)
-	[8] - use timer mode for DMA.  Timer mode is needed e.g. for
-		buggy DMA controllers in NS CS5530A (Geode Companion), and for
-		'jr' cards that lack a hardware fifo.  This option is no
-		longer needed, since timer mode is _always_ used.
-
-Passing a zero for an option is the same as leaving it unspecified.
+ * das16.c
+ * DAS16 driver
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
+ * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-*/
 /*
+ * Driver: das16
+ * Description: DAS16 compatible boards
+ * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
+ * Devices: (Keithley Metrabyte) DAS-16 [das-16]
+ *	    (Keithley Metrabyte) DAS-16G [das-16g]
+ *	    (Keithley Metrabyte) DAS-16F [das-16f]
+ *	    (Keithley Metrabyte) DAS-1201 [das-1201]
+ *	    (Keithley Metrabyte) DAS-1202 [das-1202]
+ *	    (Keithley Metrabyte) DAS-1401 [das-1401]
+ *	    (Keithley Metrabyte) DAS-1402 [das-1402]
+ *	    (Keithley Metrabyte) DAS-1601 [das-1601]
+ *	    (Keithley Metrabyte) DAS-1602 [das-1602]
+ *	    (ComputerBoards) PC104-DAS16/JR [pc104-das16jr]
+ *	    (ComputerBoards) PC104-DAS16JR/16 [pc104-das16jr/16]
+ *	    (ComputerBoards) CIO-DAS16 [cio-das16]
+ *	    (ComputerBoards) CIO-DAS16F [cio-das16/f]
+ *	    (ComputerBoards) CIO-DAS16/JR [cio-das16/jr]
+ *	    (ComputerBoards) CIO-DAS16JR/16 [cio-das16jr/16]
+ *	    (ComputerBoards) CIO-DAS1401/12 [cio-das1401/12]
+ *	    (ComputerBoards) CIO-DAS1402/12 [cio-das1402/12]
+ *	    (ComputerBoards) CIO-DAS1402/16 [cio-das1402/16]
+ *	    (ComputerBoards) CIO-DAS1601/12 [cio-das1601/12]
+ *	    (ComputerBoards) CIO-DAS1602/12 [cio-das1602/12]
+ *	    (ComputerBoards) CIO-DAS1602/16 [cio-das1602/16]
+ *	    (ComputerBoards) CIO-DAS16/330 [cio-das16/330]
+ * Status: works
+ * Updated: 2003-10-12
+ *
+ * A rewrite of the das16 and das1600 drivers.
+ *
+ * Options:
+ *	[0] - base io address
+ *	[1] - irq (does nothing, irq is not used anymore)
+ *	[2] - dma channel (optional, required for comedi_command support)
+ *	[3] - master clock speed in MHz (optional, 1 or 10, ignored if
+ *		board can probe clock, defaults to 1)
+ *	[4] - analog input range lowest voltage in microvolts (optional,
+ *		only useful if your board does not have software
+ *		programmable gain)
+ *	[5] - analog input range highest voltage in microvolts (optional,
+ *		only useful if board does not have software programmable
+ *		gain)
+ *	[6] - analog output range lowest voltage in microvolts (optional)
+ *	[7] - analog output range highest voltage in microvolts (optional)
+ *
+ * Passing a zero for an option is the same as leaving it unspecified.
+ */
 
-Testing and debugging help provided by Daniel Koch.
-
-Keithley Manuals:
-	2309.PDF (das16)
-	4919.PDF (das1400, 1600)
-	4922.PDF (das-1400)
-	4923.PDF (das1200, 1400, 1600)
-
-Computer boards manuals also available from their website
-www.measurementcomputing.com
-
-*/
+/*
+ * Testing and debugging help provided by Daniel Koch.
+ *
+ * Keithley Manuals:
+ *	2309.PDF (das16)
+ *	4919.PDF (das1400, 1600)
+ *	4922.PDF (das-1400)
+ *	4923.PDF (das1200, 1400, 1600)
+ *
+ * Computer boards manuals also available from their website
+ * www.measurementcomputing.com
+ */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/slab.h>
 #include <linux/interrupt.h>
 
 #include <asm/dma.h>
@@ -85,214 +93,112 @@ www.measurementcomputing.com
 #include "8255.h"
 #include "comedi_fc.h"
 
-#undef DEBUG
-/* #define DEBUG */
-
-#ifdef DEBUG
-#define DEBUG_PRINT(format, args...)	\
-	printk(KERN_DEBUG "das16: " format, ## args)
-#else
-#define DEBUG_PRINT(format, args...)
-#endif
-
-#define DAS16_SIZE 20		/*  number of ioports */
 #define DAS16_DMA_SIZE 0xff00	/*  size in bytes of allocated dma buffer */
 
 /*
-    cio-das16.pdf
-
-    "das16"
-    "das16/f"
-
-  0	a/d bits 0-3		start 12 bit
-  1	a/d bits 4-11		unused
-  2	mux read		mux set
-  3	di 4 bit		do 4 bit
-  4	unused			ao0_lsb
-  5	unused			ao0_msb
-  6	unused			ao1_lsb
-  7	unused			ao1_msb
-  8	status eoc uni/bip	interrupt reset
-  9	dma, int, trig ctrl	set dma, int
-  a	pacer control		unused
-  b	reserved		reserved
-  cdef	8254
-  0123	8255
-
-*/
-
-/*
-    cio-das16jr.pdf
-
-    "das16jr"
-
-  0	a/d bits 0-3		start 12 bit
-  1	a/d bits 4-11		unused
-  2	mux read		mux set
-  3	di 4 bit		do 4 bit
-  4567	unused			unused
-  8	status eoc uni/bip	interrupt reset
-  9	dma, int, trig ctrl	set dma, int
-  a	pacer control		unused
-  b	gain status		gain control
-  cdef	8254
-
-*/
-
-/*
-    cio-das16jr_16.pdf
-
-    "das16jr_16"
-
-  0	a/d bits 0-7		start 16 bit
-  1	a/d bits 8-15		unused
-  2	mux read		mux set
-  3	di 4 bit		do 4 bit
-  4567	unused			unused
-  8	status eoc uni/bip	interrupt reset
-  9	dma, int, trig ctrl	set dma, int
-  a	pacer control		unused
-  b	gain status		gain control
-  cdef	8254
-
-*/
-/*
-    cio-das160x-1x.pdf
-
-    "das1601/12"
-    "das1602/12"
-    "das1602/16"
-
-  0	a/d bits 0-3		start 12 bit
-  1	a/d bits 4-11		unused
-  2	mux read		mux set
-  3	di 4 bit		do 4 bit
-  4	unused			ao0_lsb
-  5	unused			ao0_msb
-  6	unused			ao1_lsb
-  7	unused			ao1_msb
-  8	status eoc uni/bip	interrupt reset
-  9	dma, int, trig ctrl	set dma, int
-  a	pacer control		unused
-  b	gain status		gain control
-  cdef	8254
-  400	8255
-  404	unused			conversion enable
-  405	unused			burst enable
-  406	unused			das1600 enable
-  407	status
-
-*/
-
-/*  size in bytes of a sample from board */
-static const int sample_size = 2;
-
-#define DAS16_TRIG		0
-#define DAS16_AI_LSB		0
-#define DAS16_AI_MSB		1
-#define DAS16_MUX		2
-#define DAS16_DIO		3
-#define DAS16_AO_LSB(x)	((x) ? 6 : 4)
-#define DAS16_AO_MSB(x)	((x) ? 7 : 5)
-#define DAS16_STATUS		8
-#define   BUSY			(1<<7)
-#define   UNIPOLAR			(1<<6)
-#define   DAS16_MUXBIT			(1<<5)
-#define   DAS16_INT			(1<<4)
-#define DAS16_CONTROL		9
-#define   DAS16_INTE			(1<<7)
-#define   DAS16_IRQ(x)			(((x) & 0x7) << 4)
-#define   DMA_ENABLE			(1<<2)
-#define   PACING_MASK	0x3
-#define   INT_PACER		0x03
-#define   EXT_PACER			0x02
-#define   DAS16_SOFT		0x00
-#define DAS16_PACER		0x0A
-#define   DAS16_CTR0			(1<<1)
-#define   DAS16_TRIG0			(1<<0)
-#define   BURST_LEN_BITS(x)			(((x) & 0xf) << 4)
-#define DAS16_GAIN		0x0B
-#define DAS16_CNTR0_DATA		0x0C
-#define DAS16_CNTR1_DATA		0x0D
-#define DAS16_CNTR2_DATA		0x0E
-#define DAS16_CNTR_CONTROL	0x0F
-#define   DAS16_TERM_CNT	0x00
-#define   DAS16_ONE_SHOT	0x02
-#define   DAS16_RATE_GEN	0x04
-#define   DAS16_CNTR_LSB_MSB	0x30
-#define   DAS16_CNTR0		0x00
-#define   DAS16_CNTR1		0x40
-#define   DAS16_CNTR2		0x80
-
-#define DAS1600_CONV		0x404
-#define   DAS1600_CONV_DISABLE		0x40
-#define DAS1600_BURST		0x405
-#define   DAS1600_BURST_VAL		0x40
-#define DAS1600_ENABLE		0x406
-#define   DAS1600_ENABLE_VAL		0x40
-#define DAS1600_STATUS_B	0x407
-#define   DAS1600_BME		0x40
-#define   DAS1600_ME		0x20
-#define   DAS1600_CD			0x10
-#define   DAS1600_WS			0x02
-#define   DAS1600_CLK_10MHZ		0x01
-
-static const struct comedi_lrange range_das1x01_bip = { 4, {
-							    BIP_RANGE(10),
-							    BIP_RANGE(1),
-							    BIP_RANGE(0.1),
-							    BIP_RANGE(0.01),
-							    }
+ * Register I/O map
+ */
+#define DAS16_TRIG_REG			0x00
+#define DAS16_AI_LSB_REG		0x00
+#define DAS16_AI_MSB_REG		0x01
+#define DAS16_MUX_REG			0x02
+#define DAS16_DIO_REG			0x03
+#define DAS16_AO_LSB_REG(x)		((x) ? 0x06 : 0x04)
+#define DAS16_AO_MSB_REG(x)		((x) ? 0x07 : 0x05)
+#define DAS16_STATUS_REG		0x08
+#define DAS16_STATUS_BUSY		(1 << 7)
+#define DAS16_STATUS_UNIPOLAR		(1 << 6)
+#define DAS16_STATUS_MUXBIT		(1 << 5)
+#define DAS16_STATUS_INT		(1 << 4)
+#define DAS16_CTRL_REG			0x09
+#define DAS16_CTRL_INTE			(1 << 7)
+#define DAS16_CTRL_IRQ(x)		(((x) & 0x7) << 4)
+#define DAS16_CTRL_DMAE			(1 << 2)
+#define DAS16_CTRL_PACING_MASK		(3 << 0)
+#define DAS16_CTRL_INT_PACER		(3 << 0)
+#define DAS16_CTRL_EXT_PACER		(2 << 0)
+#define DAS16_CTRL_SOFT_PACER		(0 << 0)
+#define DAS16_PACER_REG			0x0a
+#define DAS16_PACER_BURST_LEN(x)	(((x) & 0xf) << 4)
+#define DAS16_PACER_CTR0		(1 << 1)
+#define DAS16_PACER_TRIG0		(1 << 0)
+#define DAS16_GAIN_REG			0x0b
+#define DAS16_TIMER_BASE_REG		0x0c	/* to 0x0f */
+
+#define DAS1600_CONV_REG		0x404
+#define DAS1600_CONV_DISABLE		(1 << 6)
+#define DAS1600_BURST_REG		0x405
+#define DAS1600_BURST_VAL		(1 << 6)
+#define DAS1600_ENABLE_REG		0x406
+#define DAS1600_ENABLE_VAL		(1 << 6)
+#define DAS1600_STATUS_REG		0x407
+#define DAS1600_STATUS_BME		(1 << 6)
+#define DAS1600_STATUS_ME		(1 << 5)
+#define DAS1600_STATUS_CD		(1 << 4)
+#define DAS1600_STATUS_WS		(1 << 1)
+#define DAS1600_STATUS_CLK_10MHZ	(1 << 0)
+
+static const struct comedi_lrange range_das1x01_bip = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(1),
+		BIP_RANGE(0.1),
+		BIP_RANGE(0.01)
+	}
 };
 
-static const struct comedi_lrange range_das1x01_unip = { 4, {
-							     UNI_RANGE(10),
-							     UNI_RANGE(1),
-							     UNI_RANGE(0.1),
-							     UNI_RANGE(0.01),
-							     }
+static const struct comedi_lrange range_das1x01_unip = {
+	4, {
+		UNI_RANGE(10),
+		UNI_RANGE(1),
+		UNI_RANGE(0.1),
+		UNI_RANGE(0.01)
+	}
 };
 
-static const struct comedi_lrange range_das1x02_bip = { 4, {
-							    BIP_RANGE(10),
-							    BIP_RANGE(5),
-							    BIP_RANGE(2.5),
-							    BIP_RANGE(1.25),
-							    }
+static const struct comedi_lrange range_das1x02_bip = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25)
+	}
 };
 
-static const struct comedi_lrange range_das1x02_unip = { 4, {
-							     UNI_RANGE(10),
-							     UNI_RANGE(5),
-							     UNI_RANGE(2.5),
-							     UNI_RANGE(1.25),
-							     }
+static const struct comedi_lrange range_das1x02_unip = {
+	4, {
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2.5),
+		UNI_RANGE(1.25)
+	}
 };
 
-static const struct comedi_lrange range_das16jr = { 9, {
-						/*  also used by 16/330 */
-							BIP_RANGE(10),
-							BIP_RANGE(5),
-							BIP_RANGE(2.5),
-							BIP_RANGE(1.25),
-							BIP_RANGE(0.625),
-							UNI_RANGE(10),
-							UNI_RANGE(5),
-							UNI_RANGE(2.5),
-							UNI_RANGE(1.25),
-							}
+static const struct comedi_lrange range_das16jr = {
+	9, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25),
+		BIP_RANGE(0.625),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2.5),
+		UNI_RANGE(1.25)
+	}
 };
 
-static const struct comedi_lrange range_das16jr_16 = { 8, {
-							   BIP_RANGE(10),
-							   BIP_RANGE(5),
-							   BIP_RANGE(2.5),
-							   BIP_RANGE(1.25),
-							   UNI_RANGE(10),
-							   UNI_RANGE(5),
-							   UNI_RANGE(2.5),
-							   UNI_RANGE(1.25),
-							   }
+static const struct comedi_lrange range_das16jr_16 = {
+	8, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2.5),
+		UNI_RANGE(1.25)
+	}
 };
 
 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
@@ -330,30 +236,211 @@ static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
 	&range_das1x02_bip,
 };
 
-struct munge_info {
-	uint8_t byte;
-	unsigned have_byte:1;
-};
-
 struct das16_board {
 	const char *name;
-	void *ai;
-	unsigned int ai_nbits;
+	unsigned int ai_maxdata;
 	unsigned int ai_speed;	/*  max conversion speed in nanosec */
 	unsigned int ai_pg;
-	void *ao;
-	unsigned int ao_nbits;
-	void *di;
-	void *do_;
+	unsigned int has_ao:1;
+	unsigned int has_8255:1;
 
 	unsigned int i8255_offset;
-	unsigned int i8254_offset;
 
 	unsigned int size;
 	unsigned int id;
 };
 
-#define DAS16_TIMEOUT 1000
+static const struct das16_board das16_boards[] = {
+	{
+		.name		= "das-16",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 15000,
+		.ai_pg		= das16_pg_none,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x10,
+		.size		= 0x14,
+		.id		= 0x00,
+	}, {
+		.name		= "das-16g",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 15000,
+		.ai_pg		= das16_pg_none,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x10,
+		.size		= 0x14,
+		.id		= 0x00,
+	}, {
+		.name		= "das-16f",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 8500,
+		.ai_pg		= das16_pg_none,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x10,
+		.size		= 0x14,
+		.id		= 0x00,
+	}, {
+		.name		= "cio-das16",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 20000,
+		.ai_pg		= das16_pg_none,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x10,
+		.size		= 0x14,
+		.id		= 0x80,
+	}, {
+		.name		= "cio-das16/f",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_none,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x10,
+		.size		= 0x14,
+		.id		= 0x80,
+	}, {
+		.name		= "cio-das16/jr",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 7692,
+		.ai_pg		= das16_pg_16jr,
+		.size		= 0x10,
+		.id		= 0x00,
+	}, {
+		.name		= "pc104-das16jr",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 3300,
+		.ai_pg		= das16_pg_16jr,
+		.size		= 0x10,
+		.id		= 0x00,
+	}, {
+		.name		= "cio-das16jr/16",
+		.ai_maxdata	= 0xffff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_16jr_16,
+		.size		= 0x10,
+		.id		= 0x00,
+	}, {
+		.name		= "pc104-das16jr/16",
+		.ai_maxdata	= 0xffff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_16jr_16,
+		.size		= 0x10,
+		.id		= 0x00,
+	}, {
+		.name		= "das-1201",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 20000,
+		.ai_pg		= das16_pg_none,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0x20,
+	}, {
+		.name		= "das-1202",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_none,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0x20,
+	}, {
+		.name		= "das-1401",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1601,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "das-1402",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1602,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "das-1601",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1601,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "das-1602",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1602,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das1401/12",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 6250,
+		.ai_pg		= das16_pg_1601,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das1402/12",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 6250,
+		.ai_pg		= das16_pg_1602,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das1402/16",
+		.ai_maxdata	= 0xffff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1602,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das1601/12",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 6250,
+		.ai_pg		= das16_pg_1601,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das1602/12",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1602,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das1602/16",
+		.ai_maxdata	= 0xffff,
+		.ai_speed	= 10000,
+		.ai_pg		= das16_pg_1602,
+		.has_ao		= 1,
+		.has_8255	= 1,
+		.i8255_offset	= 0x400,
+		.size		= 0x408,
+		.id		= 0xc0,
+	}, {
+		.name		= "cio-das16/330",
+		.ai_maxdata	= 0x0fff,
+		.ai_speed	= 3030,
+		.ai_pg		= das16_pg_16jr,
+		.size		= 0x14,
+		.id		= 0xf0,
+	},
+};
 
 /* Period for timer interrupt in jiffies.  It's a function
  * to deal with possibility of dynamic HZ patches  */
@@ -363,34 +450,155 @@ static inline int timer_period(void)
 }
 
 struct das16_private_struct {
-	unsigned int ai_unipolar;	/*  unipolar flag */
-	unsigned int ai_singleended;	/*  single ended flag */
-	unsigned int clockbase;	/*  master clock speed in ns */
-	volatile unsigned int control_state;	/*  dma, interrupt and trigger control bits */
-	volatile unsigned long adc_byte_count;	/*  number of bytes remaining */
-	/*  divisor dividing master clock to get conversion frequency */
-	unsigned int divisor1;
-	/*  divisor dividing master clock to get conversion frequency */
-	unsigned int divisor2;
-	unsigned int dma_chan;	/*  dma channel */
-	uint16_t *dma_buffer[2];
-	dma_addr_t dma_buffer_addr[2];
-	unsigned int current_buffer;
-	volatile unsigned int dma_transfer_size;	/*  target number of bytes to transfer per dma shot */
-	/**
-	 * user-defined analog input and output ranges
-	 * defined from config options
-	 */
-	struct comedi_lrange *user_ai_range_table;
-	struct comedi_lrange *user_ao_range_table;
-
-	struct timer_list timer;	/*  for timed interrupt */
-	volatile short timer_running;
-	volatile short timer_mode;	/*  true if using timer mode */
-
-	unsigned long extra_iobase;
+	unsigned int		clockbase;
+	unsigned int		ctrl_reg;
+	unsigned long		adc_byte_count;
+	unsigned int		divisor1;
+	unsigned int		divisor2;
+	unsigned int		dma_chan;
+	uint16_t		*dma_buffer[2];
+	dma_addr_t		dma_buffer_addr[2];
+	unsigned int		current_buffer;
+	unsigned int		dma_transfer_size;
+	struct comedi_lrange	*user_ai_range_table;
+	struct comedi_lrange	*user_ao_range_table;
+	struct timer_list	timer;
+	short			timer_running;
+	unsigned long		extra_iobase;
+	unsigned int		can_burst:1;
 };
 
+static void das16_ai_enable(struct comedi_device *dev,
+			    unsigned int mode, unsigned int src)
+{
+	struct das16_private_struct *devpriv = dev->private;
+
+	devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE |
+			       DAS16_CTRL_DMAE |
+			       DAS16_CTRL_PACING_MASK);
+	devpriv->ctrl_reg |= mode;
+
+	if (src == TRIG_EXT)
+		devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
+	else
+		devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
+	outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
+}
+
+static void das16_ai_disable(struct comedi_device *dev)
+{
+	struct das16_private_struct *devpriv = dev->private;
+
+	/* disable interrupts, dma and pacer clocked conversions */
+	devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE |
+			       DAS16_CTRL_DMAE |
+			       DAS16_CTRL_PACING_MASK);
+	outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
+}
+
+/* the pc104-das16jr (at least) has problems if the dma
+	transfer is interrupted in the middle of transferring
+	a 16 bit sample, so this function takes care to get
+	an even transfer count after disabling dma
+	channel.
+*/
+static int disable_dma_on_even(struct comedi_device *dev)
+{
+	struct das16_private_struct *devpriv = dev->private;
+	int residue;
+	int i;
+	static const int disable_limit = 100;
+	static const int enable_timeout = 100;
+
+	disable_dma(devpriv->dma_chan);
+	residue = get_dma_residue(devpriv->dma_chan);
+	for (i = 0; i < disable_limit && (residue % 2); ++i) {
+		int j;
+		enable_dma(devpriv->dma_chan);
+		for (j = 0; j < enable_timeout; ++j) {
+			int new_residue;
+			udelay(2);
+			new_residue = get_dma_residue(devpriv->dma_chan);
+			if (new_residue != residue)
+				break;
+		}
+		disable_dma(devpriv->dma_chan);
+		residue = get_dma_residue(devpriv->dma_chan);
+	}
+	if (i == disable_limit) {
+		dev_err(dev->class_dev,
+			"failed to get an even dma transfer, could be trouble\n");
+	}
+	return residue;
+}
+
+static void das16_interrupt(struct comedi_device *dev)
+{
+	struct das16_private_struct *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	unsigned long spin_flags;
+	unsigned long dma_flags;
+	int num_bytes, residue;
+	int buffer_index;
+
+	spin_lock_irqsave(&dev->spinlock, spin_flags);
+	if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
+		spin_unlock_irqrestore(&dev->spinlock, spin_flags);
+		return;
+	}
+
+	dma_flags = claim_dma_lock();
+	clear_dma_ff(devpriv->dma_chan);
+	residue = disable_dma_on_even(dev);
+
+	/*  figure out how many points to read */
+	if (residue > devpriv->dma_transfer_size) {
+		dev_err(dev->class_dev, "residue > transfer size!\n");
+		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+		num_bytes = 0;
+	} else
+		num_bytes = devpriv->dma_transfer_size - residue;
+
+	if (cmd->stop_src == TRIG_COUNT &&
+					num_bytes >= devpriv->adc_byte_count) {
+		num_bytes = devpriv->adc_byte_count;
+		async->events |= COMEDI_CB_EOA;
+	}
+
+	buffer_index = devpriv->current_buffer;
+	devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
+	devpriv->adc_byte_count -= num_bytes;
+
+	/*  re-enable  dma */
+	if ((async->events & COMEDI_CB_EOA) == 0) {
+		set_dma_addr(devpriv->dma_chan,
+			     devpriv->dma_buffer_addr[devpriv->current_buffer]);
+		set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
+		enable_dma(devpriv->dma_chan);
+	}
+	release_dma_lock(dma_flags);
+
+	spin_unlock_irqrestore(&dev->spinlock, spin_flags);
+
+	cfc_write_array_to_buffer(s,
+				  devpriv->dma_buffer[buffer_index], num_bytes);
+
+	cfc_handle_events(dev, s);
+}
+
+static void das16_timer_interrupt(unsigned long arg)
+{
+	struct comedi_device *dev = (struct comedi_device *)arg;
+	struct das16_private_struct *devpriv = dev->private;
+
+	das16_interrupt(dev);
+
+	if (devpriv->timer_running)
+		mod_timer(&devpriv->timer, jiffies + timer_period());
+}
+
 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_cmd *cmd)
 {
@@ -405,15 +613,13 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
 
 	mask = TRIG_FOLLOW;
-	/*  if board supports burst mode */
-	if (board->size > 0x400)
+	if (devpriv->can_burst)
 		mask |= TRIG_TIMER | TRIG_EXT;
 	err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
 
 	tmp = cmd->convert_src;
 	mask = TRIG_TIMER | TRIG_EXT;
-	/*  if board supports burst mode */
-	if (board->size > 0x400)
+	if (devpriv->can_burst)
 		mask |= TRIG_NOW;
 	err |= cfc_check_trigger_src(&cmd->convert_src, mask);
 
@@ -469,9 +675,9 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 		unsigned int tmp = cmd->scan_begin_arg;
 		/*  set divisors, correct timing arguments */
 		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
-					       &(devpriv->divisor1),
-					       &(devpriv->divisor2),
-					       &(cmd->scan_begin_arg),
+					       &devpriv->divisor1,
+					       &devpriv->divisor2,
+					       &cmd->scan_begin_arg,
 					       cmd->flags & TRIG_ROUND_MASK);
 		err += (tmp != cmd->scan_begin_arg);
 	}
@@ -479,9 +685,9 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 		unsigned int tmp = cmd->convert_arg;
 		/*  set divisors, correct timing arguments */
 		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
-					       &(devpriv->divisor1),
-					       &(devpriv->divisor2),
-					       &(cmd->convert_arg),
+					       &devpriv->divisor1,
+					       &devpriv->divisor2,
+					       &cmd->convert_arg,
 					       cmd->flags & TRIG_ROUND_MASK);
 		err += (tmp != cmd->convert_arg);
 	}
@@ -495,16 +701,13 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 		for (i = 1; i < cmd->chanlist_len; i++) {
 			if (CR_CHAN(cmd->chanlist[i]) !=
 			    (start_chan + i) % s->n_chan) {
-				comedi_error(dev,
-						"entries in chanlist must be "
-						"consecutive channels, "
-						"counting upwards\n");
+				dev_err(dev->class_dev,
+					"entries in chanlist must be consecutive channels, counting upwards\n");
 				err++;
 			}
 			if (CR_RANGE(cmd->chanlist[i]) != gain) {
-				comedi_error(dev,
-						"entries in chanlist must all "
-						"have the same gain\n");
+				dev_err(dev->class_dev,
+					"entries in chanlist must all have the same gain\n");
 				err++;
 			}
 		}
@@ -515,61 +718,21 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 	return 0;
 }
 
-/* utility function that suggests a dma transfer size in bytes */
-static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
-						const struct comedi_cmd *cmd)
-{
-	struct das16_private_struct *devpriv = dev->private;
-	unsigned int size;
-	unsigned int freq;
-
-	/* if we are using timer interrupt, we don't care how long it
-	 * will take to complete transfer since it will be interrupted
-	 * by timer interrupt */
-	if (devpriv->timer_mode)
-		return DAS16_DMA_SIZE;
-
-	/* otherwise, we are relying on dma terminal count interrupt,
-	 * so pick a reasonable size */
-	if (cmd->convert_src == TRIG_TIMER)
-		freq = 1000000000 / cmd->convert_arg;
-	else if (cmd->scan_begin_src == TRIG_TIMER)
-		freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len;
-	/*  return some default value */
-	else
-		freq = 0xffffffff;
-
-	if (cmd->flags & TRIG_WAKE_EOS) {
-		size = sample_size * cmd->chanlist_len;
-	} else {
-		/*  make buffer fill in no more than 1/3 second */
-		size = (freq / 3) * sample_size;
-	}
-
-	/*  set a minimum and maximum size allowed */
-	if (size > DAS16_DMA_SIZE)
-		size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
-	else if (size < sample_size)
-		size = sample_size;
-
-	if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
-		size = devpriv->adc_byte_count;
-
-	return size;
-}
-
 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 				    int rounding_flags)
 {
 	struct das16_private_struct *devpriv = dev->private;
+	unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
 
-	i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
-				       &(devpriv->divisor2), &ns,
+	i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
+				       &devpriv->divisor1,
+				       &devpriv->divisor2,
+				       &ns,
 				       rounding_flags & TRIG_ROUND_MASK);
 
 	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
-	i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
-	i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
+	i8254_load(timer_base, 0, 1, devpriv->divisor1, 2);
+	i8254_load(timer_base, 0, 2, devpriv->divisor2, 2);
 
 	return ns;
 }
@@ -584,30 +747,22 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 	unsigned long flags;
 	int range;
 
-	if (devpriv->dma_chan == 0 || (dev->irq == 0
-				       && devpriv->timer_mode == 0)) {
-		comedi_error(dev,
-				"irq (or use of 'timer mode') dma required to "
-							"execute comedi_cmd");
-		return -1;
-	}
 	if (cmd->flags & TRIG_RT) {
-		comedi_error(dev, "isa dma transfers cannot be performed with "
-							"TRIG_RT, aborting");
+		dev_err(dev->class_dev,
+			 "isa dma transfers cannot be performed with TRIG_RT, aborting\n");
 		return -1;
 	}
 
 	devpriv->adc_byte_count =
 	    cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
 
-	/*  disable conversions for das1600 mode */
-	if (board->size > 0x400)
-		outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
+	if (devpriv->can_burst)
+		outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
 
 	/*  set scan limits */
 	byte = CR_CHAN(cmd->chanlist[0]);
 	byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
-	outb(byte, dev->iobase + DAS16_MUX);
+	outb(byte, dev->iobase + DAS16_MUX_REG);
 
 	/* set gain (this is also burst rate register but according to
 	 * computer boards manual, burst rate does nothing, even on
@@ -615,28 +770,27 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 	if (board->ai_pg != das16_pg_none) {
 		range = CR_RANGE(cmd->chanlist[0]);
 		outb((das16_gainlists[board->ai_pg])[range],
-		     dev->iobase + DAS16_GAIN);
+		     dev->iobase + DAS16_GAIN_REG);
 	}
 
 	/* set counter mode and counts */
 	cmd->convert_arg =
 	    das16_set_pacer(dev, cmd->convert_arg,
 			    cmd->flags & TRIG_ROUND_MASK);
-	DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
 
 	/* enable counters */
 	byte = 0;
-	/* Enable burst mode if appropriate. */
-	if (board->size > 0x400) {
+	if (devpriv->can_burst) {
 		if (cmd->convert_src == TRIG_NOW) {
-			outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
+			outb(DAS1600_BURST_VAL,
+			     dev->iobase + DAS1600_BURST_REG);
 			/*  set burst length */
-			byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
+			byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
 		} else {
-			outb(0, dev->iobase + DAS1600_BURST);
+			outb(0, dev->iobase + DAS1600_BURST_REG);
 		}
 	}
-	outb(byte, dev->iobase + DAS16_PACER);
+	outb(byte, dev->iobase + DAS16_PACER_REG);
 
 	/*  set up dma transfer */
 	flags = claim_dma_lock();
@@ -647,465 +801,220 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->current_buffer = 0;
 	set_dma_addr(devpriv->dma_chan,
 		     devpriv->dma_buffer_addr[devpriv->current_buffer]);
-	/*  set appropriate size of transfer */
-	devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd);
+	devpriv->dma_transfer_size = DAS16_DMA_SIZE;
 	set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
 	enable_dma(devpriv->dma_chan);
 	release_dma_lock(flags);
 
 	/*  set up interrupt */
-	if (devpriv->timer_mode) {
-		devpriv->timer_running = 1;
-		devpriv->timer.expires = jiffies + timer_period();
-		add_timer(&devpriv->timer);
-		devpriv->control_state &= ~DAS16_INTE;
-	} else {
-		/* clear interrupt bit */
-		outb(0x00, dev->iobase + DAS16_STATUS);
-		/* enable interrupts */
-		devpriv->control_state |= DAS16_INTE;
-	}
-	devpriv->control_state |= DMA_ENABLE;
-	devpriv->control_state &= ~PACING_MASK;
-	if (cmd->convert_src == TRIG_EXT)
-		devpriv->control_state |= EXT_PACER;
-	else
-		devpriv->control_state |= INT_PACER;
-	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
+	devpriv->timer_running = 1;
+	devpriv->timer.expires = jiffies + timer_period();
+	add_timer(&devpriv->timer);
 
-	/* Enable conversions if using das1600 mode */
-	if (board->size > 0x400)
-		outb(0, dev->iobase + DAS1600_CONV);
+	das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src);
 
+	if (devpriv->can_burst)
+		outb(0, dev->iobase + DAS1600_CONV_REG);
 
 	return 0;
 }
 
 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct das16_board *board = comedi_board(dev);
 	struct das16_private_struct *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->spinlock, flags);
-	/* disable interrupts, dma and pacer clocked conversions */
-	devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
-	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
-	if (devpriv->dma_chan)
-		disable_dma(devpriv->dma_chan);
+
+	das16_ai_disable(dev);
+	disable_dma(devpriv->dma_chan);
 
 	/*  disable SW timer */
-	if (devpriv->timer_mode && devpriv->timer_running) {
+	if (devpriv->timer_running) {
 		devpriv->timer_running = 0;
 		del_timer(&devpriv->timer);
 	}
 
-	/* disable burst mode */
-	if (board->size > 0x400)
-		outb(0, dev->iobase + DAS1600_BURST);
-
+	if (devpriv->can_burst)
+		outb(0, dev->iobase + DAS1600_BURST_REG);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	return 0;
 }
 
-static void das16_reset(struct comedi_device *dev)
-{
-	outb(0, dev->iobase + DAS16_STATUS);
-	outb(0, dev->iobase + DAS16_CONTROL);
-	outb(0, dev->iobase + DAS16_PACER);
-	outb(0, dev->iobase + DAS16_CNTR_CONTROL);
-}
-
-static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
-{
-	const struct das16_board *board = comedi_board(dev);
-	struct das16_private_struct *devpriv = dev->private;
-	int i, n;
-	int range;
-	int chan;
-	int msb, lsb;
-
-	/*  disable interrupts and pacing */
-	devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
-	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
-
-	/* set multiplexer */
-	chan = CR_CHAN(insn->chanspec);
-	chan |= CR_CHAN(insn->chanspec) << 4;
-	outb(chan, dev->iobase + DAS16_MUX);
-
-	/* set gain */
-	if (board->ai_pg != das16_pg_none) {
-		range = CR_RANGE(insn->chanspec);
-		outb((das16_gainlists[board->ai_pg])[range],
-		     dev->iobase + DAS16_GAIN);
-	}
-
-	for (n = 0; n < insn->n; n++) {
-		/* trigger conversion */
-		outb_p(0, dev->iobase + DAS16_TRIG);
-
-		for (i = 0; i < DAS16_TIMEOUT; i++) {
-			if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
-				break;
-		}
-		if (i == DAS16_TIMEOUT) {
-			printk("das16: timeout\n");
-			return -ETIME;
-		}
-		msb = inb(dev->iobase + DAS16_AI_MSB);
-		lsb = inb(dev->iobase + DAS16_AI_LSB);
-		if (board->ai_nbits == 12)
-			data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
-		else
-			data[n] = lsb | (msb << 8);
-
-	}
-
-	return n;
-}
-
-static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int bits;
-
-	bits = inb(dev->iobase + DAS16_DIO) & 0xf;
-	data[1] = bits;
-	data[0] = 0;
-
-	return insn->n;
-}
-
-static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int wbits;
-
-	/*  only set bits that have been masked */
-	data[0] &= 0xf;
-	wbits = s->state;
-	/*  zero bits that have been masked */
-	wbits &= ~data[0];
-	/*  set masked bits */
-	wbits |= data[0] & data[1];
-	s->state = wbits;
-	data[1] = wbits;
-
-	outb(s->state, dev->iobase + DAS16_DIO);
-
-	return insn->n;
-}
-
-static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static void das16_ai_munge(struct comedi_device *dev,
+			   struct comedi_subdevice *s, void *array,
+			   unsigned int num_bytes,
+			   unsigned int start_chan_index)
 {
-	const struct das16_board *board = comedi_board(dev);
-	int i;
-	int lsb, msb;
-	int chan;
-
-	chan = CR_CHAN(insn->chanspec);
+	unsigned int i, num_samples = num_bytes / sizeof(short);
+	short *data = array;
 
-	for (i = 0; i < insn->n; i++) {
-		if (board->ao_nbits == 12) {
-			lsb = (data[i] << 4) & 0xff;
-			msb = (data[i] >> 4) & 0xff;
-		} else {
-			lsb = data[i] & 0xff;
-			msb = (data[i] >> 8) & 0xff;
-		}
-		outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
-		outb(msb, dev->iobase + DAS16_AO_MSB(chan));
+	for (i = 0; i < num_samples; i++) {
+		data[i] = le16_to_cpu(data[i]);
+		if (s->maxdata == 0x0fff)
+			data[i] >>= 4;
+		data[i] &= s->maxdata;
 	}
-
-	return i;
 }
 
-/* the pc104-das16jr (at least) has problems if the dma
-	transfer is interrupted in the middle of transferring
-	a 16 bit sample, so this function takes care to get
-	an even transfer count after disabling dma
-	channel.
-*/
-static int disable_dma_on_even(struct comedi_device *dev)
+static int das16_ai_wait_for_conv(struct comedi_device *dev,
+				  unsigned int timeout)
 {
-	struct das16_private_struct *devpriv = dev->private;
-	int residue;
+	unsigned int status;
 	int i;
-	static const int disable_limit = 100;
-	static const int enable_timeout = 100;
 
-	disable_dma(devpriv->dma_chan);
-	residue = get_dma_residue(devpriv->dma_chan);
-	for (i = 0; i < disable_limit && (residue % 2); ++i) {
-		int j;
-		enable_dma(devpriv->dma_chan);
-		for (j = 0; j < enable_timeout; ++j) {
-			int new_residue;
-			udelay(2);
-			new_residue = get_dma_residue(devpriv->dma_chan);
-			if (new_residue != residue)
-				break;
-		}
-		disable_dma(devpriv->dma_chan);
-		residue = get_dma_residue(devpriv->dma_chan);
-	}
-	if (i == disable_limit) {
-		comedi_error(dev, "failed to get an even dma transfer, "
-							"could be trouble.");
+	for (i = 0; i < timeout; i++) {
+		status = inb(dev->iobase + DAS16_STATUS_REG);
+		if (!(status & DAS16_STATUS_BUSY))
+			return 0;
 	}
-	return residue;
+	return -ETIME;
 }
 
-static void das16_interrupt(struct comedi_device *dev)
+static int das16_ai_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
 	const struct das16_board *board = comedi_board(dev);
-	struct das16_private_struct *devpriv = dev->private;
-	unsigned long dma_flags, spin_flags;
-	struct comedi_subdevice *s = dev->read_subdev;
-	struct comedi_async *async;
-	struct comedi_cmd *cmd;
-	int num_bytes, residue;
-	int buffer_index;
-
-	if (!dev->attached) {
-		comedi_error(dev, "premature interrupt");
-		return;
-	}
-	/*  initialize async here to make sure it is not NULL */
-	async = s->async;
-	cmd = &async->cmd;
-
-	if (devpriv->dma_chan == 0) {
-		comedi_error(dev, "interrupt with no dma channel?");
-		return;
-	}
-
-	spin_lock_irqsave(&dev->spinlock, spin_flags);
-	if ((devpriv->control_state & DMA_ENABLE) == 0) {
-		spin_unlock_irqrestore(&dev->spinlock, spin_flags);
-		DEBUG_PRINT("interrupt while dma disabled?\n");
-		return;
-	}
-
-	dma_flags = claim_dma_lock();
-	clear_dma_ff(devpriv->dma_chan);
-	residue = disable_dma_on_even(dev);
-
-	/*  figure out how many points to read */
-	if (residue > devpriv->dma_transfer_size) {
-		comedi_error(dev, "residue > transfer size!\n");
-		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
-		num_bytes = 0;
-	} else
-		num_bytes = devpriv->dma_transfer_size - residue;
-
-	if (cmd->stop_src == TRIG_COUNT &&
-					num_bytes >= devpriv->adc_byte_count) {
-		num_bytes = devpriv->adc_byte_count;
-		async->events |= COMEDI_CB_EOA;
-	}
-
-	buffer_index = devpriv->current_buffer;
-	devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
-	devpriv->adc_byte_count -= num_bytes;
-
-	/*  figure out how many bytes for next transfer */
-	if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
-	    devpriv->dma_transfer_size > devpriv->adc_byte_count)
-		devpriv->dma_transfer_size = devpriv->adc_byte_count;
-
-	/*  re-enable  dma */
-	if ((async->events & COMEDI_CB_EOA) == 0) {
-		set_dma_addr(devpriv->dma_chan,
-			     devpriv->dma_buffer_addr[devpriv->current_buffer]);
-		set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
-		enable_dma(devpriv->dma_chan);
-		/* reenable conversions for das1600 mode, (stupid hardware) */
-		if (board->size > 0x400 && devpriv->timer_mode == 0)
-			outb(0x00, dev->iobase + DAS1600_CONV);
-
-	}
-	release_dma_lock(dma_flags);
-
-	spin_unlock_irqrestore(&dev->spinlock, spin_flags);
-
-	cfc_write_array_to_buffer(s,
-				  devpriv->dma_buffer[buffer_index], num_bytes);
-
-	cfc_handle_events(dev, s);
-}
-
-static irqreturn_t das16_dma_interrupt(int irq, void *d)
-{
-	int status;
-	struct comedi_device *dev = d;
-
-	status = inb(dev->iobase + DAS16_STATUS);
-
-	if ((status & DAS16_INT) == 0) {
-		DEBUG_PRINT("spurious interrupt\n");
-		return IRQ_NONE;
-	}
-
-	/* clear interrupt */
-	outb(0x00, dev->iobase + DAS16_STATUS);
-	das16_interrupt(dev);
-	return IRQ_HANDLED;
-}
-
-static void das16_timer_interrupt(unsigned long arg)
-{
-	struct comedi_device *dev = (struct comedi_device *)arg;
-	struct das16_private_struct *devpriv = dev->private;
-
-	das16_interrupt(dev);
-
-	if (devpriv->timer_running)
-		mod_timer(&devpriv->timer, jiffies + timer_period());
-}
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int val;
+	int ret;
+	int i;
 
-static void reg_dump(struct comedi_device *dev)
-{
-	DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
-	DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
-	DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
-	DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
-	DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
-	DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
-	DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
-	DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
-		    inb(dev->iobase + DAS16_CNTR_CONTROL));
-	DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
-	DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
-	DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
-	DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
-		    inb(dev->iobase + DAS1600_STATUS_B));
-}
+	das16_ai_disable(dev);
 
-static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
-{
-	const struct das16_board *board = comedi_board(dev);
-	struct das16_private_struct *devpriv = dev->private;
-	int status;
-	int diobits;
+	/* set multiplexer */
+	outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG);
 
-	/* status is available on all boards */
+	/* set gain */
+	if (board->ai_pg != das16_pg_none) {
+		outb((das16_gainlists[board->ai_pg])[range],
+		     dev->iobase + DAS16_GAIN_REG);
+	}
 
-	status = inb(dev->iobase + DAS16_STATUS);
+	for (i = 0; i < insn->n; i++) {
+		/* trigger conversion */
+		outb_p(0, dev->iobase + DAS16_TRIG_REG);
 
-	if ((status & UNIPOLAR))
-		devpriv->ai_unipolar = 1;
-	else
-		devpriv->ai_unipolar = 0;
+		ret = das16_ai_wait_for_conv(dev, 1000);
+		if (ret)
+			return ret;
 
+		val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
+		val |= inb(dev->iobase + DAS16_AI_LSB_REG);
+		if (s->maxdata == 0x0fff)
+			val >>= 4;
+		val &= s->maxdata;
 
-	if ((status & DAS16_MUXBIT))
-		devpriv->ai_singleended = 1;
-	else
-		devpriv->ai_singleended = 0;
+		data[i] = val;
+	}
 
+	return insn->n;
+}
 
-	/* diobits indicates boards */
+static int das16_ao_insn_write(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
+{
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val;
+	int i;
 
-	diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
+	for (i = 0; i < insn->n; i++) {
+		val = data[i];
+		val <<= 4;
 
-	printk(KERN_INFO " id bits are 0x%02x\n", diobits);
-	if (board->id != diobits) {
-		printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
-		       board->id);
+		outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
+		outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
 	}
 
-	return 0;
+	return insn->n;
 }
 
-static int das1600_mode_detect(struct comedi_device *dev)
+static int das16_di_insn_bits(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	struct das16_private_struct *devpriv = dev->private;
-	int status = 0;
+	data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
+
+	return insn->n;
+}
 
-	status = inb(dev->iobase + DAS1600_STATUS_B);
+static int das16_do_insn_bits(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
+{
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-	if (status & DAS1600_CLK_10MHZ) {
-		devpriv->clockbase = 100;
-		printk(KERN_INFO " 10MHz pacer clock\n");
-	} else {
-		devpriv->clockbase = 1000;
-		printk(KERN_INFO " 1MHz pacer clock\n");
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
+
+		outb(s->state, dev->iobase + DAS16_DIO_REG);
 	}
 
-	reg_dump(dev);
+	data[1] = s->state;
 
-	return 0;
+	return insn->n;
 }
 
-static void das16_ai_munge(struct comedi_device *dev,
-			   struct comedi_subdevice *s, void *array,
-			   unsigned int num_bytes,
-			   unsigned int start_chan_index)
+static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct das16_board *board = comedi_board(dev);
-	unsigned int i, num_samples = num_bytes / sizeof(short);
-	short *data = array;
-
-	for (i = 0; i < num_samples; i++) {
-		data[i] = le16_to_cpu(data[i]);
-		if (board->ai_nbits == 12)
-			data[i] = (data[i] >> 4) & 0xfff;
+	int diobits;
 
+	/* diobits indicates boards */
+	diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
+	if (board->id != diobits) {
+		dev_err(dev->class_dev,
+			"requested board's id bits are incorrect (0x%x != 0x%x)\n",
+			board->id, diobits);
+		return -EINVAL;
 	}
+
+	return 0;
+}
+
+static void das16_reset(struct comedi_device *dev)
+{
+	outb(0, dev->iobase + DAS16_STATUS_REG);
+	outb(0, dev->iobase + DAS16_CTRL_REG);
+	outb(0, dev->iobase + DAS16_PACER_REG);
+	outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg);
 }
 
-/*
- *
- * Options list:
- *   0  I/O base
- *   1  IRQ
- *   2  DMA
- *   3  Clock speed (in MHz)
- */
 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct das16_board *board = comedi_board(dev);
 	struct das16_private_struct *devpriv;
 	struct comedi_subdevice *s;
+	struct comedi_lrange *lrange;
+	struct comedi_krange *krange;
+	unsigned int dma_chan = it->options[2];
+	unsigned int status;
 	int ret;
-	unsigned int irq;
-	unsigned int dma_chan;
-	int timer_mode;
-	unsigned long flags;
-	struct comedi_krange *user_ai_range, *user_ao_range;
-
-#if 0
-	irq = it->options[1];
-	timer_mode = it->options[8];
-#endif
-	/* always use time_mode since using irq can drop samples while
-	 * waiting for dma done interrupt (due to hardware limitations) */
-	irq = 0;
-	timer_mode = 1;
-	if (timer_mode)
-		irq = 0;
 
 	/*  check that clock setting is valid */
 	if (it->options[3]) {
 		if (it->options[3] != 0 &&
 		    it->options[3] != 1 && it->options[3] != 10) {
-			printk
-			    ("\n Invalid option.  Master clock must be set "
-							"to 1 or 10 (MHz)\n");
+			dev_err(dev->class_dev,
+				"Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
 			return -EINVAL;
 		}
 	}
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	if (board->size < 0x400) {
 		ret = comedi_request_region(dev, it->options[0], board->size);
@@ -1121,207 +1030,183 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		if (ret)
 			return ret;
 		devpriv->extra_iobase = dev->iobase + 0x400;
+		devpriv->can_burst = 1;
 	}
 
 	/*  probe id bits to make sure they are consistent */
-	if (das16_probe(dev, it)) {
-		printk(KERN_ERR " id bits do not match selected board, aborting\n");
+	if (das16_probe(dev, it))
 		return -EINVAL;
-	}
 
 	/*  get master clock speed */
-	if (board->size < 0x400) {
+	if (devpriv->can_burst) {
+		status = inb(dev->iobase + DAS1600_STATUS_REG);
+
+		if (status & DAS1600_STATUS_CLK_10MHZ)
+			devpriv->clockbase = 100;
+		else
+			devpriv->clockbase = 1000;
+	} else {
 		if (it->options[3])
 			devpriv->clockbase = 1000 / it->options[3];
 		else
 			devpriv->clockbase = 1000;	/*  1 MHz default */
-	} else {
-		das1600_mode_detect(dev);
-	}
-
-	/* now for the irq */
-	if (irq > 1 && irq < 8) {
-		ret = request_irq(irq, das16_dma_interrupt, 0,
-				  dev->board_name, dev);
-
-		if (ret < 0)
-			return ret;
-		dev->irq = irq;
-		printk(KERN_INFO " ( irq = %u )", irq);
-	} else if (irq == 0) {
-		printk(" ( no irq )");
-	} else {
-		printk(" invalid irq\n");
-		return -EINVAL;
 	}
 
-	/*  initialize dma */
-	dma_chan = it->options[2];
+	/* initialize dma */
 	if (dma_chan == 1 || dma_chan == 3) {
-		/*  allocate dma buffers */
+		unsigned long flags;
 		int i;
-		for (i = 0; i < 2; i++) {
-			devpriv->dma_buffer[i] = pci_alloc_consistent(
-						NULL, DAS16_DMA_SIZE,
-						&devpriv->dma_buffer_addr[i]);
 
-			if (devpriv->dma_buffer[i] == NULL)
-				return -ENOMEM;
-		}
 		if (request_dma(dma_chan, dev->board_name)) {
-			printk(KERN_ERR " failed to allocate dma channel %i\n",
-			       dma_chan);
+			dev_err(dev->class_dev,
+				"failed to request dma channel %i\n",
+				dma_chan);
 			return -EINVAL;
 		}
 		devpriv->dma_chan = dma_chan;
+
+		/* allocate dma buffers */
+		for (i = 0; i < 2; i++) {
+			void *p;
+
+			p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
+						 &devpriv->dma_buffer_addr[i]);
+			if (!p)
+				return -ENOMEM;
+			devpriv->dma_buffer[i] = p;
+		}
+
 		flags = claim_dma_lock();
 		disable_dma(devpriv->dma_chan);
 		set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
 		release_dma_lock(flags);
-		printk(KERN_INFO " ( dma = %u)\n", dma_chan);
-	} else if (dma_chan == 0) {
-		printk(KERN_INFO " ( no dma )\n");
-	} else {
-		printk(KERN_ERR " invalid dma channel\n");
-		return -EINVAL;
+
+		init_timer(&devpriv->timer);
+		devpriv->timer.function = das16_timer_interrupt;
+		devpriv->timer.data = (unsigned long)dev;
 	}
 
-	/*  get any user-defined input range */
+	/* get any user-defined input range */
 	if (board->ai_pg == das16_pg_none &&
 	    (it->options[4] || it->options[5])) {
-		/*  allocate single-range range table */
-		devpriv->user_ai_range_table =
-		    kmalloc(sizeof(struct comedi_lrange) +
-			    sizeof(struct comedi_krange), GFP_KERNEL);
-		/*  initialize ai range */
-		devpriv->user_ai_range_table->length = 1;
-		user_ai_range = devpriv->user_ai_range_table->range;
-		user_ai_range->min = it->options[4];
-		user_ai_range->max = it->options[5];
-		user_ai_range->flags = UNIT_volt;
-	}
-	/*  get any user-defined output range */
-	if (it->options[6] || it->options[7]) {
-		/*  allocate single-range range table */
-		devpriv->user_ao_range_table =
-		    kmalloc(sizeof(struct comedi_lrange) +
-			    sizeof(struct comedi_krange), GFP_KERNEL);
-		/*  initialize ao range */
-		devpriv->user_ao_range_table->length = 1;
-		user_ao_range = devpriv->user_ao_range_table->range;
-		user_ao_range->min = it->options[6];
-		user_ao_range->max = it->options[7];
-		user_ao_range->flags = UNIT_volt;
+		/* allocate single-range range table */
+		lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL);
+		if (!lrange)
+			return -ENOMEM;
+
+		/* initialize ai range */
+		devpriv->user_ai_range_table = lrange;
+		lrange->length = 1;
+		krange = devpriv->user_ai_range_table->range;
+		krange->min = it->options[4];
+		krange->max = it->options[5];
+		krange->flags = UNIT_volt;
 	}
 
-	if (timer_mode) {
-		init_timer(&(devpriv->timer));
-		devpriv->timer.function = das16_timer_interrupt;
-		devpriv->timer.data = (unsigned long)dev;
+	/* get any user-defined output range */
+	if (it->options[6] || it->options[7]) {
+		/* allocate single-range range table */
+		lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL);
+		if (!lrange)
+			return -ENOMEM;
+
+		/* initialize ao range */
+		devpriv->user_ao_range_table = lrange;
+		lrange->length = 1;
+		krange = devpriv->user_ao_range_table->range;
+		krange->min = it->options[6];
+		krange->max = it->options[7];
+		krange->flags = UNIT_volt;
 	}
-	devpriv->timer_mode = timer_mode ? 1 : 0;
 
-	ret = comedi_alloc_subdevices(dev, 5);
+	ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
 	if (ret)
 		return ret;
 
+	status = inb(dev->iobase + DAS16_STATUS_REG);
+
+	/* Analog Input subdevice */
 	s = &dev->subdevices[0];
-	dev->read_subdev = s;
-	/* ai */
-	if (board->ai) {
-		s->type = COMEDI_SUBD_AI;
-		s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-		if (devpriv->ai_singleended) {
-			s->n_chan = 16;
-			s->len_chanlist = 16;
-			s->subdev_flags |= SDF_GROUND;
-		} else {
-			s->n_chan = 8;
-			s->len_chanlist = 8;
-			s->subdev_flags |= SDF_DIFF;
-		}
-		s->maxdata = (1 << board->ai_nbits) - 1;
-		if (devpriv->user_ai_range_table) { /*  user defined ai range */
-			s->range_table = devpriv->user_ai_range_table;
-		} else if (devpriv->ai_unipolar) {
-			s->range_table = das16_ai_uni_lranges[board->ai_pg];
-		} else {
-			s->range_table = das16_ai_bip_lranges[board->ai_pg];
-		}
-		s->insn_read = board->ai;
-		s->do_cmdtest = das16_cmd_test;
-		s->do_cmd = das16_cmd_exec;
-		s->cancel = das16_cancel;
-		s->munge = das16_ai_munge;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE;
+	if (status & DAS16_STATUS_MUXBIT) {
+		s->subdev_flags	|= SDF_GROUND;
+		s->n_chan	= 16;
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->subdev_flags	|= SDF_DIFF;
+		s->n_chan	= 8;
 	}
-
-	s = &dev->subdevices[1];
-	/* ao */
-	if (board->ao) {
-		s->type = COMEDI_SUBD_AO;
-		s->subdev_flags = SDF_WRITABLE;
-		s->n_chan = 2;
-		s->maxdata = (1 << board->ao_nbits) - 1;
-		/*  user defined ao range */
-		if (devpriv->user_ao_range_table)
-			s->range_table = devpriv->user_ao_range_table;
-		else
-			s->range_table = &range_unknown;
-
-		s->insn_write = board->ao;
+	s->len_chanlist	= s->n_chan;
+	s->maxdata	= board->ai_maxdata;
+	if (devpriv->user_ai_range_table) { /*  user defined ai range */
+		s->range_table	= devpriv->user_ai_range_table;
+	} else if (status & DAS16_STATUS_UNIPOLAR) {
+		s->range_table	= das16_ai_uni_lranges[board->ai_pg];
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->range_table	= das16_ai_bip_lranges[board->ai_pg];
 	}
-
-	s = &dev->subdevices[2];
-	/* di */
-	if (board->di) {
-		s->type = COMEDI_SUBD_DI;
-		s->subdev_flags = SDF_READABLE;
-		s->n_chan = 4;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = board->di;
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+	s->insn_read	= das16_ai_insn_read;
+	if (devpriv->dma_chan) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->do_cmdtest	= das16_cmd_test;
+		s->do_cmd	= das16_cmd_exec;
+		s->cancel	= das16_cancel;
+		s->munge	= das16_ai_munge;
 	}
 
-	s = &dev->subdevices[3];
-	/* do */
-	if (board->do_) {
-		s->type = COMEDI_SUBD_DO;
-		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-		s->n_chan = 4;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = board->do_;
-		/*  initialize digital output lines */
-		outb(s->state, dev->iobase + DAS16_DIO);
+	/* Analog Output subdevice */
+	s = &dev->subdevices[1];
+	if (board->has_ao) {
+		s->type		= COMEDI_SUBD_AO;
+		s->subdev_flags	= SDF_WRITABLE;
+		s->n_chan	= 2;
+		s->maxdata	= 0x0fff;
+		s->range_table	= devpriv->user_ao_range_table;
+		s->insn_write	= das16_ao_insn_write;
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
 
-	s = &dev->subdevices[4];
-	/* 8255 */
-	if (board->i8255_offset != 0) {
-		subdev_8255_init(dev, s, NULL, (dev->iobase +
-						board->i8255_offset));
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+	/* Digital Input subdevice */
+	s = &dev->subdevices[2];
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= das16_di_insn_bits;
+
+	/* Digital Output subdevice */
+	s = &dev->subdevices[3];
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= das16_do_insn_bits;
+
+	/* initialize digital output lines */
+	outb(s->state, dev->iobase + DAS16_DIO_REG);
+
+	/* 8255 Digital I/O subdevice */
+	if (board->has_8255) {
+		s = &dev->subdevices[4];
+		ret = subdev_8255_init(dev, s, NULL,
+				       dev->iobase + board->i8255_offset);
+		if (ret)
+			return ret;
 	}
 
 	das16_reset(dev);
 	/* set the interrupt level */
-	devpriv->control_state = DAS16_IRQ(dev->irq);
-	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
-
-	/*  turn on das1600 mode if available */
-	if (board->size > 0x400) {
-		outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
-		outb(0, dev->iobase + DAS1600_CONV);
-		outb(0, dev->iobase + DAS1600_BURST);
+	devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
+	outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
+
+	if (devpriv->can_burst) {
+		outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
+		outb(0, dev->iobase + DAS1600_CONV_REG);
+		outb(0, dev->iobase + DAS1600_BURST_REG);
 	}
 
 	return 0;
@@ -1331,10 +1216,12 @@ static void das16_detach(struct comedi_device *dev)
 {
 	const struct das16_board *board = comedi_board(dev);
 	struct das16_private_struct *devpriv = dev->private;
+	int i;
 
-	das16_reset(dev);
 	if (devpriv) {
-		int i;
+		if (dev->iobase)
+			das16_reset(dev);
+
 		for (i = 0; i < 2; i++) {
 			if (devpriv->dma_buffer[i])
 				pci_free_consistent(NULL, DAS16_DMA_SIZE,
@@ -1346,312 +1233,15 @@ static void das16_detach(struct comedi_device *dev)
 			free_dma(devpriv->dma_chan);
 		kfree(devpriv->user_ai_range_table);
 		kfree(devpriv->user_ao_range_table);
+
+		if (devpriv->extra_iobase)
+			release_region(devpriv->extra_iobase,
+				       board->size & 0x3ff);
 	}
-	if (devpriv->extra_iobase)
-		release_region(devpriv->extra_iobase, board->size & 0x3ff);
+
 	comedi_legacy_detach(dev);
 }
 
-static const struct das16_board das16_boards[] = {
-	{
-		.name		= "das-16",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 15000,
-		.ai_pg		= das16_pg_none,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x10,
-		.i8254_offset	= 0x0c,
-		.size		= 0x14,
-		.id		= 0x00,
-	}, {
-		.name		= "das-16g",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 15000,
-		.ai_pg		= das16_pg_none,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x10,
-		.i8254_offset	= 0x0c,
-		.size		= 0x14,
-		.id		= 0x00,
-	}, {
-		.name		= "das-16f",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 8500,
-		.ai_pg		= das16_pg_none,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x10,
-		.i8254_offset	= 0x0c,
-		.size		= 0x14,
-		.id		= 0x00,
-	}, {
-		.name		= "cio-das16",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 20000,
-		.ai_pg		= das16_pg_none,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x10,
-		.i8254_offset	= 0x0c,
-		.size		= 0x14,
-		.id		= 0x80,
-	}, {
-		.name		= "cio-das16/f",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_none,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x10,
-		.i8254_offset	= 0x0c,
-		.size		= 0x14,
-		.id		= 0x80,
-	}, {
-		.name		= "cio-das16/jr",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 7692,
-		.ai_pg		= das16_pg_16jr,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x10,
-		.id		= 0x00,
-	}, {
-		.name		= "pc104-das16jr",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 3300,
-		.ai_pg		= das16_pg_16jr,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x10,
-		.id		= 0x00,
-	}, {
-		.name		= "cio-das16jr/16",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 16,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_16jr_16,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x10,
-		.id		= 0x00,
-	}, {
-		.name		= "pc104-das16jr/16",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 16,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_16jr_16,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x10,
-		.id		= 0x00,
-	}, {
-		.name		= "das-1201",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 20000,
-		.ai_pg		= das16_pg_none,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0x20,
-	}, {
-		.name		= "das-1202",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_none,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0x20,
-	}, {
-		.name		= "das-1401",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1601,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "das-1402",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1602,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "das-1601",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1601,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "das-1602",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1602,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das1401/12",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 6250,
-		.ai_pg		= das16_pg_1601,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das1402/12",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 6250,
-		.ai_pg		= das16_pg_1602,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das1402/16",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 16,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1602,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das1601/12",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 6250,
-		.ai_pg		= das16_pg_1601,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das1602/12",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1602,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das1602/16",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 16,
-		.ai_speed	= 10000,
-		.ai_pg		= das16_pg_1602,
-		.ao		= das16_ao_winsn,
-		.ao_nbits	= 12,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0x400,
-		.i8254_offset	= 0x0c,
-		.size		= 0x408,
-		.id		= 0xc0,
-	}, {
-		.name		= "cio-das16/330",
-		.ai		= das16_ai_rinsn,
-		.ai_nbits	= 12,
-		.ai_speed	= 3030,
-		.ai_pg		= das16_pg_16jr,
-		.ao		= NULL,
-		.di		= das16_di_rbits,
-		.do_		= das16_do_wbits,
-		.i8255_offset	= 0,
-		.i8254_offset	= 0x0c,
-		.size		= 0x14,
-		.id		= 0xf0,
-	},
-};
-
 static struct comedi_driver das16_driver = {
 	.driver_name	= "das16",
 	.module		= THIS_MODULE,
@@ -1664,5 +1254,5 @@ static struct comedi_driver das16_driver = {
 module_comedi_driver(das16_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index 0b33808..b943c44 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -52,7 +52,7 @@ Options:
 irq can be omitted, although the cmd interface will not work without it.
 */
 
-#include <linux/ioport.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
@@ -567,10 +567,9 @@ static int das16m1_attach(struct comedi_device *dev,
 	int ret;
 	unsigned int irq;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], DAS16M1_SIZE);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 23b4a66..5b30029 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -94,12 +94,12 @@ TODO:
 	read insn for analog out
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <asm/dma.h>
 
 #include "8253.h"
@@ -1511,10 +1511,9 @@ static int das1800_attach(struct comedi_device *dev,
 	int board;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index f053077..fb25cb8 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -33,11 +33,10 @@ Devices: [Keithley Metrabyte] DAS6402 (das6402)
 This driver has suffered bitrot.
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #define DAS6402_SIZE 16
 
 #define N_WORDS (3000*64)
@@ -294,10 +293,9 @@ static int das6402_attach(struct comedi_device *dev,
 
 	dev->irq = irq;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 1);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 091cd91..11e1611 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -56,10 +56,10 @@ cmd triggers supported:
 
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/delay.h>
 
 #include "8253.h"
@@ -700,10 +700,9 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	int board;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], DAS800_SIZE);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index e29847d..5237f47 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -32,9 +32,10 @@ Configuration Options:
   comedi_config /dev/comedi0 dmm32at baseaddr,irq
 */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
-#include <linux/ioport.h>
 
 #include "comedi_fc.h"
 
@@ -753,10 +754,9 @@ static int dmm32at_attach(struct comedi_device *dev,
 		dev->irq = irq;
 	}
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index 8f5006d..e0e7bea 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -29,9 +29,9 @@ Configuration options:
   [5] - D/A 1 range (same choices)
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 #include <linux/delay.h>
-#include <linux/ioport.h>
 
 #define DT2801_TIMEOUT 1000
 
@@ -627,10 +627,9 @@ havetype:
 	if (ret)
 		goto out;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	dev->board_name = board->name;
 
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index 5348cda..a41a571 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -41,11 +41,10 @@ Configuration options:
   [4] - D/A 1 range (same choices)
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = {
 	4, {
 		RANGE(0, 5),
@@ -450,10 +449,9 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	switch (it->options[2]) {
 	case 0:
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 87e9749..6514b9e 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -34,10 +34,10 @@ a power of 10, from 1 to 10^7, of which only 3 or 4 are useful.  In
 addition, the clock does not seem to be very accurate.
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/delay.h>
 
 #include "comedi_fc.h"
@@ -298,10 +298,9 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	dev->read_subdev = s;
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index 0fcd4fe..34040f0 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -51,9 +51,9 @@ Configuration options:
   [12] - Analog output 7 range configuration (same options)
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/delay.h>
 
 #define DT2815_SIZE 2
@@ -165,10 +165,9 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	/* ao subdevice */
diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
index 2f46be7..51cf121 100644
--- a/drivers/staging/comedi/drivers/dt2817.c
+++ b/drivers/staging/comedi/drivers/dt2817.c
@@ -33,10 +33,9 @@ Configuration options:
   [0] - I/O port base base address
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #define DT2817_SIZE 5
 
 #define DT2817_CR 0
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index c1950e3..23cb0335 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -51,13 +51,16 @@ Notes:
     be fixed to check for this situation and return an error.
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
+#include <linux/delay.h>
 #include <linux/gfp.h>
-#include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+
 #include <asm/dma.h>
+
 #include "comedi_fc.h"
 
 #define DEBUG
@@ -1188,10 +1191,9 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 #endif
 	}
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = dt282x_grab_dma(dev, it->options[opt_dma1],
 			      it->options[opt_dma2]);
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 01a2f88..e4748da 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -50,6 +50,7 @@ AO commands are not supported.
 
 #define DEBUG 1
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -722,10 +723,9 @@ static int dt3000_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret < 0)
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 6c60949..b5e6f33 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -39,10 +39,9 @@ for my needs.
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 
@@ -188,8 +187,8 @@ enum {
 };
 
 struct dt9812_flash_data {
-	u16 numbytes;
-	u16 address;
+	__le16 numbytes;
+	__le16 address;
 };
 
 #define DT9812_MAX_NUM_MULTI_BYTE_RDS  \
@@ -230,7 +229,7 @@ struct dt9812_rmw_multi {
 };
 
 struct dt9812_usb_cmd {
-	u32 cmd;
+	__le32 cmd;
 	union {
 		struct dt9812_flash_data flash_data_info;
 		struct dt9812_read_multi read_multi_info;
@@ -707,8 +706,9 @@ static int dt9812_reset_device(struct comedi_device *dev)
 	u32 serial;
 	u16 vendor;
 	u16 product;
-	u16 tmp16;
 	u8 tmp8;
+	__le16 tmp16;
+	__le32 tmp32;
 	int ret;
 	int i;
 
@@ -731,19 +731,19 @@ static int dt9812_reset_device(struct comedi_device *dev)
 		}
 	}
 
-	ret = dt9812_read_info(dev, 1, &vendor, sizeof(vendor));
+	ret = dt9812_read_info(dev, 1, &tmp16, sizeof(tmp16));
 	if (ret) {
 		dev_err(dev->class_dev, "failed to read vendor id\n");
 		return ret;
 	}
-	vendor = le16_to_cpu(vendor);
+	vendor = le16_to_cpu(tmp16);
 
-	ret = dt9812_read_info(dev, 3, &product, sizeof(product));
+	ret = dt9812_read_info(dev, 3, &tmp16, sizeof(tmp16));
 	if (ret) {
 		dev_err(dev->class_dev, "failed to read product id\n");
 		return ret;
 	}
-	product = le16_to_cpu(product);
+	product = le16_to_cpu(tmp16);
 
 	ret = dt9812_read_info(dev, 5, &tmp16, sizeof(tmp16));
 	if (ret) {
@@ -752,12 +752,12 @@ static int dt9812_reset_device(struct comedi_device *dev)
 	}
 	devpriv->device = le16_to_cpu(tmp16);
 
-	ret = dt9812_read_info(dev, 7, &serial, sizeof(serial));
+	ret = dt9812_read_info(dev, 7, &tmp32, sizeof(tmp32));
 	if (ret) {
 		dev_err(dev->class_dev, "failed to read serial number\n");
 		return ret;
 	}
-	serial = le32_to_cpu(serial);
+	serial = le32_to_cpu(tmp32);
 
 	/* let the user know what node this device is now attached to */
 	dev_info(dev->class_dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n",
@@ -781,10 +781,9 @@ static int dt9812_auto_attach(struct comedi_device *dev,
 	bool is_unipolar;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	sema_init(&devpriv->sem, 1);
 	usb_set_intfdata(intf, devpriv);
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index e14dd3a..fd525f4 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -33,6 +33,8 @@
  their cards in their manuals.
 */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/mutex.h>
 
@@ -183,10 +185,9 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index ff6f0bd..8d70f64 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -18,10 +18,10 @@ Configuration options:
 
 #define DEBUG 0
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include <linux/delay.h>
-#include <linux/ioport.h>
 
 #define FL512_SIZE 16		/* the size of the used memory */
 struct fl512_private {
@@ -118,10 +118,9 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 2);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index 2fceff9..cdcc8f4 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -42,6 +42,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -483,10 +484,9 @@ static int hpdi_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = thisboard;
 	dev->board_name = thisboard->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	retval = comedi_pci_enable(dev);
 	if (retval)
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index a11e015..3889d23 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -42,6 +42,7 @@ There are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
 Configuration options: not applicable, uses PCI auto config
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -495,10 +496,9 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index ee7537d..954c539 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -1,517 +1,358 @@
 /*
- *	comedi/drivers/ii_pci20kc.c
- *	Driver for Intelligent Instruments PCI-20001C carrier board
- *	and modules.
+ * ii_pci20kc.c
+ * Driver for Intelligent Instruments PCI-20001C carrier board and modules.
  *
- *	Copyright (C) 2000 Markus Kempf <kempf@matsci.uni-sb.de>
- *	with suggestions from David Schleef
- *			16.06.2000
- *
- *	Linux device driver for COMEDI
- *	Intelligent Instrumentation
- *	PCI-20001 C-2A Carrier Board
- *	PCI-20341 M-1A 16-Bit analog input module
- *				- differential
- *				- range (-5V - +5V)
- *				- 16 bit
- *	PCI-20006 M-2 16-Bit analog output module
- *				- ranges (-10V - +10V) (0V - +10V) (-5V - +5V)
- *				- 16 bit
- *
- *	only ONE PCI-20341 module possible
- *	only ONE PCI-20006 module possible
- *	no extern trigger implemented
- *
- *	NOT WORKING (but soon) only 4 on-board differential channels supported
- *	NOT WORKING (but soon) only ONE di-port and ONE do-port supported
- *			       instead of 4 digital ports
- *	di-port == Port 0
- *	do-port == Port 1
- *
- *	The state of this driver is only a starting point for a complete
- *	COMEDI-driver. The final driver should support all features of the
- *	carrier board and modules.
+ * Copyright (C) 2000 Markus Kempf <kempf@matsci.uni-sb.de>
+ * with suggestions from David Schleef		16.06.2000
+ */
+
+/*
+ * Driver: ii_pci20kc
+ * Description: Intelligent Instruments PCI-20001C carrier board
+ * Devices: (Intelligent Instrumentation) PCI-20001C [ii_pci20kc]
+ * Author: Markus Kempf <kempf@matsci.uni-sb.de>
+ * Status: works
  *
- *	The test configuration:
+ * Supports the PCI-20001C-1a and PCI-20001C-2a carrier boards. The
+ * -2a version has 32 on-board DIO channels. Three add-on modules
+ * can be added to the carrier board for additional functionality.
  *
- *	kernel 2.2.14 with RTAI v1.2  and patch-2.2.14rthal2
- *	COMEDI 0.7.45
- *	COMEDILIB 0.7.9
+ * Supported add-on modules:
+ *	PCI-20006M-1   1 channel, 16-bit analog output module
+ *	PCI-20006M-2   2 channel, 16-bit analog output module
+ *	PCI-20341M-1A  4 channel, 16-bit analog input module
  *
+ * Options:
+ *   0   Board base address
+ *   1   IRQ (not-used)
  */
-/*
-Driver: ii_pci20kc
-Description: Intelligent Instruments PCI-20001C carrier board
-Author: Markus Kempf <kempf@matsci.uni-sb.de>
-Devices: [Intelligent Instrumentation] PCI-20001C (ii_pci20kc)
-Status: works
-
-Supports the PCI-20001 C-2a Carrier board, and could probably support
-the other carrier boards with small modifications.  Modules supported
-are:
-	PCI-20006 M-2 16-bit analog output module
-	PCI-20341 M-1A 16-bit analog input module
-
-Options:
-  0   Board base address
-  1   IRQ
-  2   first option for module 1
-  3   second option for module 1
-  4   first option for module 2
-  5   second option for module 2
-  6   first option for module 3
-  7   second option for module 3
-
-options for PCI-20006M:
-  first:   Analog output channel 0 range configuration
-	     0  bipolar 10  (-10V -- +10V)
-	     1  unipolar 10  (0V -- +10V)
-	     2  bipolar 5  (-5V -- 5V)
-  second:  Analog output channel 1 range configuration
-
-options for PCI-20341M:
-  first:   Analog input gain configuration
-	     0  1
-	     1  10
-	     2  100
-	     3  200
-*/
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#define PCI20000_ID			0x1d
-#define PCI20341_ID			0x77
-#define PCI20006_ID			0xe3
-#define PCI20xxx_EMPTY_ID		0xff
-
-#define PCI20000_OFFSET			0x100
-#define PCI20000_MODULES		3
-
-#define PCI20000_DIO_0			0x80
-#define PCI20000_DIO_1			0x81
-#define PCI20000_DIO_2			0xc0
-#define PCI20000_DIO_3			0xc1
-#define PCI20000_DIO_CONTROL_01		0x83	/* port 0, 1 control */
-#define PCI20000_DIO_CONTROL_23		0xc3	/* port 2, 3 control */
-#define PCI20000_DIO_BUFFER		0x82	/* buffer direction & enable */
-#define PCI20000_DIO_EOC		0xef	/* even port, control output */
-#define PCI20000_DIO_OOC		0xfd	/* odd port, control output */
-#define PCI20000_DIO_EIC		0x90	/* even port, control input */
-#define PCI20000_DIO_OIC		0x82	/* odd port, control input */
-#define DIO_CAND			0x12	/* and bit 1 & 4 of control */
-#define DIO_BE				0x01	/* buffer: port enable */
-#define DIO_BO				0x04	/* buffer: output */
-#define DIO_BI				0x05	/* buffer: input */
-#define DIO_PS_0			0x00	/* buffer: port shift 0 */
-#define DIO_PS_1			0x01	/* buffer: port shift 1 */
-#define DIO_PS_2			0x04	/* buffer: port shift 2 */
-#define DIO_PS_3			0x05	/* buffer: port shift 3 */
-
-#define PCI20006_LCHAN0			0x0d
-#define PCI20006_STROBE0		0x0b
-#define PCI20006_LCHAN1			0x15
-#define PCI20006_STROBE1		0x13
-
-#define PCI20341_INIT			0x04
-#define PCI20341_REPMODE		0x00	/* single shot mode */
-#define PCI20341_PACER			0x00	/* Hardware Pacer disabled */
-#define PCI20341_CHAN_NR		0x04	/* number of input channels */
-#define PCI20341_CONFIG_REG		0x10
-#define PCI20341_MOD_STATUS		0x01
-#define PCI20341_OPT_REG		0x11
-#define PCI20341_SET_TIME_REG		0x15
-#define PCI20341_LCHAN_ADDR_REG		0x13
-#define PCI20341_CHAN_LIST		0x80
-#define PCI20341_CC_RESET		0x1b
-#define PCI20341_CHAN_RESET		0x19
-#define PCI20341_SOFT_PACER		0x04
-#define PCI20341_STATUS_REG		0x12
-#define PCI20341_LDATA			0x02
-#define PCI20341_DAISY_CHAIN		0x20	/* On-board inputs only */
-#define PCI20341_MUX			0x04	/* Enable on-board MUX */
-#define PCI20341_SCANLIST		0x80	/* Channel/Gain Scan List */
-
-union pci20xxx_subdev_private {
-	void __iomem *iobase;
-	struct {
-		void __iomem *iobase;
-		const struct comedi_lrange *ao_range_list[2];
-					/* range of channels of ao module */
-		unsigned int last_data[2];
-	} pci20006;
-	struct {
-		void __iomem *iobase;
-		int timebase;
-		int settling_time;
-		int ai_gain;
-	} pci20341;
+/*
+ * Register I/O map
+ */
+#define II20K_MOD_OFFSET		0x100
+#define II20K_ID_REG			0x00
+#define II20K_ID_MOD1_EMPTY		(1 << 7)
+#define II20K_ID_MOD2_EMPTY		(1 << 6)
+#define II20K_ID_MOD3_EMPTY		(1 << 5)
+#define II20K_ID_MASK			0x1f
+#define II20K_ID_PCI20001C_1A		0x1b	/* no on-board DIO */
+#define II20K_ID_PCI20001C_2A		0x1d	/* on-board DIO */
+#define II20K_MOD_STATUS_REG		0x40
+#define II20K_MOD_STATUS_IRQ_MOD1	(1 << 7)
+#define II20K_MOD_STATUS_IRQ_MOD2	(1 << 6)
+#define II20K_MOD_STATUS_IRQ_MOD3	(1 << 5)
+#define II20K_DIO0_REG			0x80
+#define II20K_DIO1_REG			0x81
+#define II20K_DIR_ENA_REG		0x82
+#define II20K_DIR_DIO3_OUT		(1 << 7)
+#define II20K_DIR_DIO2_OUT		(1 << 6)
+#define II20K_BUF_DISAB_DIO3		(1 << 5)
+#define II20K_BUF_DISAB_DIO2		(1 << 4)
+#define II20K_DIR_DIO1_OUT		(1 << 3)
+#define II20K_DIR_DIO0_OUT		(1 << 2)
+#define II20K_BUF_DISAB_DIO1		(1 << 1)
+#define II20K_BUF_DISAB_DIO0		(1 << 0)
+#define II20K_CTRL01_REG		0x83
+#define II20K_CTRL01_SET		(1 << 7)
+#define II20K_CTRL01_DIO0_IN		(1 << 4)
+#define II20K_CTRL01_DIO1_IN		(1 << 1)
+#define II20K_DIO2_REG			0xc0
+#define II20K_DIO3_REG			0xc1
+#define II20K_CTRL23_REG		0xc3
+#define II20K_CTRL23_SET		(1 << 7)
+#define II20K_CTRL23_DIO2_IN		(1 << 4)
+#define II20K_CTRL23_DIO3_IN		(1 << 1)
+
+#define II20K_ID_PCI20006M_1		0xe2	/* 1 AO channels */
+#define II20K_ID_PCI20006M_2		0xe3	/* 2 AO channels */
+#define II20K_AO_STRB_REG(x)		(0x0b + ((x) * 0x08))
+#define II20K_AO_LSB_REG(x)		(0x0d + ((x) * 0x08))
+#define II20K_AO_MSB_REG(x)		(0x0e + ((x) * 0x08))
+#define II20K_AO_STRB_BOTH_REG		0x1b
+
+#define II20K_ID_PCI20341M_1		0x77	/* 4 AI channels */
+#define II20K_AI_STATUS_CMD_REG		0x01
+#define II20K_AI_STATUS_CMD_BUSY	(1 << 7)
+#define II20K_AI_STATUS_CMD_HW_ENA	(1 << 1)
+#define II20K_AI_STATUS_CMD_EXT_START	(1 << 0)
+#define II20K_AI_LSB_REG		0x02
+#define II20K_AI_MSB_REG		0x03
+#define II20K_AI_PACER_RESET_REG	0x04
+#define II20K_AI_16BIT_DATA_REG		0x06
+#define II20K_AI_CONF_REG		0x10
+#define II20K_AI_CONF_ENA		(1 << 2)
+#define II20K_AI_OPT_REG		0x11
+#define II20K_AI_OPT_TRIG_ENA		(1 << 5)
+#define II20K_AI_OPT_TRIG_INV		(1 << 4)
+#define II20K_AI_OPT_TIMEBASE(x)	(((x) & 0x3) << 1)
+#define II20K_AI_OPT_BURST_MODE		(1 << 0)
+#define II20K_AI_STATUS_REG		0x12
+#define II20K_AI_STATUS_INT		(1 << 7)
+#define II20K_AI_STATUS_TRIG		(1 << 6)
+#define II20K_AI_STATUS_TRIG_ENA	(1 << 5)
+#define II20K_AI_STATUS_PACER_ERR	(1 << 2)
+#define II20K_AI_STATUS_DATA_ERR	(1 << 1)
+#define II20K_AI_STATUS_SET_TIME_ERR	(1 << 0)
+#define II20K_AI_LAST_CHAN_ADDR_REG	0x13
+#define II20K_AI_CUR_ADDR_REG		0x14
+#define II20K_AI_SET_TIME_REG		0x15
+#define II20K_AI_DELAY_LSB_REG		0x16
+#define II20K_AI_DELAY_MSB_REG		0x17
+#define II20K_AI_CHAN_ADV_REG		0x18
+#define II20K_AI_CHAN_RESET_REG		0x19
+#define II20K_AI_START_TRIG_REG		0x1a
+#define II20K_AI_COUNT_RESET_REG	0x1b
+#define II20K_AI_CHANLIST_REG		0x80
+#define II20K_AI_CHANLIST_ONBOARD_ONLY	(1 << 5)
+#define II20K_AI_CHANLIST_GAIN(x)	(((x) & 0x3) << 3)
+#define II20K_AI_CHANLIST_MUX_ENA	(1 << 2)
+#define II20K_AI_CHANLIST_CHAN(x)	(((x) & 0x3) << 0)
+#define II20K_AI_CHANLIST_LEN		0x80
+
+/* the AO range is set by jumpers on the 20006M module */
+static const struct comedi_lrange ii20k_ao_ranges = {
+	3, {
+		BIP_RANGE(5),	/* Chan 0 - W1/W3 in   Chan 1 - W2/W4 in  */
+		UNI_RANGE(10),	/* Chan 0 - W1/W3 out  Chan 1 - W2/W4 in  */
+		BIP_RANGE(10)	/* Chan 0 - W1/W3 in   Chan 1 - W2/W4 out */
+	}
+};
+
+static const struct comedi_lrange ii20k_ai_ranges = {
+	4, {
+		BIP_RANGE(5),		/* gain 1 */
+		BIP_RANGE(0.5),		/* gain 10 */
+		BIP_RANGE(0.05),	/* gain 100 */
+		BIP_RANGE(0.025)	/* gain 200 */
+	},
 };
 
-struct pci20xxx_private {
+struct ii20k_ao_private {
+	unsigned int last_data[2];
+};
 
+struct ii20k_private {
 	void __iomem *ioaddr;
-	union pci20xxx_subdev_private subdev_private[PCI20000_MODULES];
 };
 
-#define CHAN (CR_CHAN(it->chanlist[0]))
-
-static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			 int opt0, int opt1);
-static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			 int opt0, int opt1);
-static int pci20xxx_dio_init(struct comedi_device *dev,
-			     struct comedi_subdevice *s);
-
-/*
-  options[0]	Board base address
-  options[1]	IRQ
-  options[2]	first option for module 1
-  options[3]	second option for module 1
-  options[4]	first option for module 2
-  options[5]	second option for module 2
-  options[6]	first option for module 3
-  options[7]	second option for module 3
-
-  options for PCI-20341M:
-  first		Analog input gain configuration
-		0 == 1
-		1 == 10
-		2 == 100
-		3 == 200
-
-  options for PCI-20006M:
-  first		Analog output channel 0 range configuration
-		0 == bipolar 10  (-10V -- +10V)
-		1 == unipolar 10V  (0V -- +10V)
-		2 == bipolar 5V  (-5V -- +5V)
-  second	Analog output channel 1 range configuration
-		0 == bipolar 10  (-10V -- +10V)
-		1 == unipolar 10V  (0V -- +10V)
-		2 == bipolar 5V  (-5V -- +5V)
-*/
-static int pci20xxx_attach(struct comedi_device *dev,
-			   struct comedi_devconfig *it)
+static void __iomem *ii20k_module_iobase(struct comedi_device *dev,
+					 struct comedi_subdevice *s)
 {
-	struct pci20xxx_private *devpriv;
-	unsigned char i;
-	int ret;
-	int id;
-	struct comedi_subdevice *s;
-	union pci20xxx_subdev_private *sdp;
+	struct ii20k_private *devpriv = dev->private;
 
-	ret = comedi_alloc_subdevices(dev, 1 + PCI20000_MODULES);
-	if (ret)
-		return ret;
-
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-	if (!devpriv)
-		return -ENOMEM;
-	dev->private = devpriv;
-
-	devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0];
+	return devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET;
+}
 
-	/* Check PCI-20001 C-2A Carrier Board ID */
-	if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) {
-		dev_warn(dev->class_dev,
-			 "PCI-20001 C-2A Carrier Board at base=0x%p not found !\n",
-			 devpriv->ioaddr);
-		return -EINVAL;
-	}
-	dev_info(dev->class_dev, "PCI-20001 C-2A at base=0x%p\n",
-		 devpriv->ioaddr);
-
-	for (i = 0; i < PCI20000_MODULES; i++) {
-		s = &dev->subdevices[i];
-		id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET);
-		s->private = devpriv->subdev_private + i;
-		sdp = s->private;
-		switch (id) {
-		case PCI20006_ID:
-			sdp->pci20006.iobase =
-			    devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
-			pci20006_init(dev, s, it->options[2 * i + 2],
-				      it->options[2 * i + 3]);
-			dev_info(dev->class_dev,
-				 "PCI-20006 module in slot %d\n", i + 1);
-			break;
-		case PCI20341_ID:
-			sdp->pci20341.iobase =
-			    devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
-			pci20341_init(dev, s, it->options[2 * i + 2],
-				      it->options[2 * i + 3]);
-			dev_info(dev->class_dev,
-				 "PCI-20341 module in slot %d\n", i + 1);
-			break;
-		default:
-			dev_warn(dev->class_dev,
-				 "unknown module code 0x%02x in slot %d: module disabled\n",
-				 id, i); /* XXX this looks like a bug! i + 1 ?? */
-			/* fall through */
-		case PCI20xxx_EMPTY_ID:
-			s->type = COMEDI_SUBD_UNUSED;
-			break;
-		}
-	}
+static int ii20k_ao_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
+{
+	struct ii20k_ao_private *ao_spriv = s->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-	/* initialize struct pci20xxx_private */
-	pci20xxx_dio_init(dev, &dev->subdevices[PCI20000_MODULES]);
+	for (i = 0; i < insn->n; i++)
+		data[i] = ao_spriv->last_data[chan];
 
-	return 1;
+	return insn->n;
 }
 
-static void pci20xxx_detach(struct comedi_device *dev)
+static int ii20k_ao_insn_write(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	/* Nothing to cleanup */
-}
+	struct ii20k_ao_private *ao_spriv = s->private;
+	void __iomem *iobase = ii20k_module_iobase(dev, s);
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val = ao_spriv->last_data[chan];
+	int i;
+
+	for (i = 0; i < insn->n; i++) {
+		val = data[i];
 
-/* pci20006m */
+		/* munge data */
+		val += ((s->maxdata + 1) >> 1);
+		val &= s->maxdata;
 
-static int pci20006_insn_read(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-static int pci20006_insn_write(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
+		writeb(val & 0xff, iobase + II20K_AO_LSB_REG(chan));
+		writeb((val >> 8) & 0xff, iobase + II20K_AO_MSB_REG(chan));
+		writeb(0x00, iobase + II20K_AO_STRB_REG(chan));
+	}
 
-static const struct comedi_lrange *pci20006_range_list[] = {
-	&range_bipolar10,
-	&range_unipolar10,
-	&range_bipolar5,
-};
+	ao_spriv->last_data[chan] = val;
 
-static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			 int opt0, int opt1)
-{
-	union pci20xxx_subdev_private *sdp = s->private;
-
-	if (opt0 < 0 || opt0 > 2)
-		opt0 = 0;
-	if (opt1 < 0 || opt1 > 2)
-		opt1 = 0;
-
-	sdp->pci20006.ao_range_list[0] = pci20006_range_list[opt0];
-	sdp->pci20006.ao_range_list[1] = pci20006_range_list[opt1];
-
-	/* ao subdevice */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 2;
-	s->len_chanlist = 2;
-	s->insn_read = pci20006_insn_read;
-	s->insn_write = pci20006_insn_write;
-	s->maxdata = 0xffff;
-	s->range_table_list = sdp->pci20006.ao_range_list;
-	return 0;
+	return insn->n;
 }
 
-static int pci20006_insn_read(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+static int ii20k_ai_wait_eoc(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     int timeout)
 {
-	union pci20xxx_subdev_private *sdp = s->private;
+	void __iomem *iobase = ii20k_module_iobase(dev, s);
+	unsigned char status;
 
-	data[0] = sdp->pci20006.last_data[CR_CHAN(insn->chanspec)];
+	do {
+		status = readb(iobase + II20K_AI_STATUS_REG);
+		if ((status & II20K_AI_STATUS_INT) == 0)
+			return 0;
+	} while (timeout--);
 
-	return 1;
+	return -ETIME;
 }
 
-static int pci20006_insn_write(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+static void ii20k_ai_setup(struct comedi_device *dev,
+			   struct comedi_subdevice *s,
+			   unsigned int chanspec)
 {
-	union pci20xxx_subdev_private *sdp = s->private;
-	int hi, lo;
-	unsigned int boarddata;
-
-	sdp->pci20006.last_data[CR_CHAN(insn->chanspec)] = data[0];
-	boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff);
-						/* comedi-data -> board-data */
-	lo = (boarddata & 0xff);
-	hi = ((boarddata >> 8) & 0xff);
-
-	switch (CR_CHAN(insn->chanspec)) {
-	case 0:
-		writeb(lo, sdp->iobase + PCI20006_LCHAN0);
-		writeb(hi, sdp->iobase + PCI20006_LCHAN0 + 1);
-		writeb(0x00, sdp->iobase + PCI20006_STROBE0);
-		break;
-	case 1:
-		writeb(lo, sdp->iobase + PCI20006_LCHAN1);
-		writeb(hi, sdp->iobase + PCI20006_LCHAN1 + 1);
-		writeb(0x00, sdp->iobase + PCI20006_STROBE1);
-		break;
-	default:
-		dev_warn(dev->class_dev, "ao channel Error!\n");
-		return -EINVAL;
-	}
-
-	return 1;
-}
+	void __iomem *iobase = ii20k_module_iobase(dev, s);
+	unsigned int chan = CR_CHAN(chanspec);
+	unsigned int range = CR_RANGE(chanspec);
+	unsigned char val;
 
-/* PCI20341M */
+	/* initialize module */
+	writeb(II20K_AI_CONF_ENA, iobase + II20K_AI_CONF_REG);
 
-static int pci20341_insn_read(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
+	/* software conversion */
+	writeb(0, iobase + II20K_AI_STATUS_CMD_REG);
 
-static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
-static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 };
+	/* set the time base for the settling time counter based on the gain */
+	val = (range < 3) ? II20K_AI_OPT_TIMEBASE(0) : II20K_AI_OPT_TIMEBASE(2);
+	writeb(val, iobase + II20K_AI_OPT_REG);
 
-static const struct comedi_lrange range_bipolar0_5 = {
-	1,
-	{BIP_RANGE(0.5)}
-};
+	/* set the settling time counter based on the gain */
+	val = (range < 2) ? 0x58 : (range < 3) ? 0x93 : 0x99;
+	writeb(val, iobase + II20K_AI_SET_TIME_REG);
 
-static const struct comedi_lrange range_bipolar0_05 = {
-	1,
-	{BIP_RANGE(0.05)}
-};
+	/* set number of input channels */
+	writeb(1, iobase + II20K_AI_LAST_CHAN_ADDR_REG);
 
-static const struct comedi_lrange range_bipolar0_025 = {
-	1,
-	{BIP_RANGE(0.025)}
-};
+	/* set the channel list byte */
+	val = II20K_AI_CHANLIST_ONBOARD_ONLY |
+	      II20K_AI_CHANLIST_MUX_ENA |
+	      II20K_AI_CHANLIST_GAIN(range) |
+	      II20K_AI_CHANLIST_CHAN(chan);
+	writeb(val, iobase + II20K_AI_CHANLIST_REG);
 
-static const struct comedi_lrange *const pci20341_ranges[] = {
-	&range_bipolar5,
-	&range_bipolar0_5,
-	&range_bipolar0_05,
-	&range_bipolar0_025,
-};
+	/* reset settling time counter and trigger delay counter */
+	writeb(0, iobase + II20K_AI_COUNT_RESET_REG);
 
-static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			 int opt0, int opt1)
-{
-	union pci20xxx_subdev_private *sdp = s->private;
-	int option;
-
-	/* options handling */
-	if (opt0 < 0 || opt0 > 3)
-		opt0 = 0;
-	sdp->pci20341.timebase = pci20341_timebase[opt0];
-	sdp->pci20341.settling_time = pci20341_settling_time[opt0];
-
-	/* ai subdevice */
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE;
-	s->n_chan = PCI20341_CHAN_NR;
-	s->len_chanlist = PCI20341_SCANLIST;
-	s->insn_read = pci20341_insn_read;
-	s->maxdata = 0xffff;
-	s->range_table = pci20341_ranges[opt0];
-
-	/* depends on gain, trigger, repetition mode */
-	option = sdp->pci20341.timebase | PCI20341_REPMODE;
-
-	/* initialize Module */
-	writeb(PCI20341_INIT, sdp->iobase + PCI20341_CONFIG_REG);
-	/* set Pacer */
-	writeb(PCI20341_PACER, sdp->iobase + PCI20341_MOD_STATUS);
-	/* option register */
-	writeb(option, sdp->iobase + PCI20341_OPT_REG);
-	/* settling time counter */
-	writeb(sdp->pci20341.settling_time,
-		sdp->iobase + PCI20341_SET_TIME_REG);
-	/* trigger not implemented */
-	return 0;
+	/* reset channel scanner */
+	writeb(0, iobase + II20K_AI_CHAN_RESET_REG);
 }
 
-static int pci20341_insn_read(struct comedi_device *dev,
+static int ii20k_ai_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	union pci20xxx_subdev_private *sdp = s->private;
-	unsigned int i = 0, j = 0;
-	int lo, hi;
-	unsigned char eoc;	/* end of conversion */
-	unsigned int clb;	/* channel list byte */
-	unsigned int boarddata;
-
-	/* write number of input channels */
-	writeb(1, sdp->iobase + PCI20341_LCHAN_ADDR_REG);
-	clb = PCI20341_DAISY_CHAIN | PCI20341_MUX | (sdp->pci20341.ai_gain << 3)
-	    | CR_CHAN(insn->chanspec);
-	writeb(clb, sdp->iobase + PCI20341_CHAN_LIST);
+	void __iomem *iobase = ii20k_module_iobase(dev, s);
+	int ret;
+	int i;
 
-	/* reset settling time counter and trigger delay counter */
-	writeb(0x00, sdp->iobase + PCI20341_CC_RESET);
+	ii20k_ai_setup(dev, s, insn->chanspec);
 
-	writeb(0x00, sdp->iobase + PCI20341_CHAN_RESET);
+	for (i = 0; i < insn->n; i++) {
+		unsigned int val;
 
-	/* generate Pacer */
+		/* generate a software start convert signal */
+		readb(iobase + II20K_AI_PACER_RESET_REG);
 
-	for (i = 0; i < insn->n; i++) {
-		/* data polling isn't the niciest way to get the data, I know,
-		 * but there are only 6 cycles (mean) and it is easier than
-		 * the whole interrupt stuff
-		 */
-		j = 0;
-		/* generate Pacer */
-		readb(sdp->iobase + PCI20341_SOFT_PACER);
-
-		eoc = readb(sdp->iobase + PCI20341_STATUS_REG);
-		/* poll Interrupt Flag */
-		while ((eoc < 0x80) && j < 100) {
-			j++;
-			eoc = readb(sdp->iobase + PCI20341_STATUS_REG);
-		}
-		if (j >= 100) {
-			dev_warn(dev->class_dev,
-				 "AI interrupt channel %i polling exit !\n", i);
-			return -EINVAL;
-		}
-		lo = readb(sdp->iobase + PCI20341_LDATA);
-		hi = readb(sdp->iobase + PCI20341_LDATA + 1);
-		boarddata = lo + 0x100 * hi;
-
-		/* board-data -> comedi-data */
-		data[i] = (short)((boarddata + 0x8000) & 0xffff);
-	}
+		ret = ii20k_ai_wait_eoc(dev, s, 100);
+		if (ret)
+			return ret;
 
-	return i;
-}
+		val = readb(iobase + II20K_AI_LSB_REG);
+		val |= (readb(iobase + II20K_AI_MSB_REG) << 8);
 
-/* native DIO */
+		/* munge two's complement data */
+		val += ((s->maxdata + 1) >> 1);
+		val &= s->maxdata;
 
-static void pci20xxx_dio_config(struct comedi_device *dev,
-				struct comedi_subdevice *s);
-static int pci20xxx_dio_insn_bits(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-static int pci20xxx_dio_insn_config(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data);
+		data[i] = val;
+	}
 
-/* initialize struct pci20xxx_private */
-static int pci20xxx_dio_init(struct comedi_device *dev,
+	return insn->n;
+}
+
+static void ii20k_dio_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	struct ii20k_private *devpriv = dev->private;
+	unsigned char ctrl01 = 0;
+	unsigned char ctrl23 = 0;
+	unsigned char dir_ena = 0;
+
+	/* port 0 - channels 0-7 */
+	if (s->io_bits & 0x000000ff) {
+		/* output port */
+		ctrl01 &= ~II20K_CTRL01_DIO0_IN;
+		dir_ena &= ~II20K_BUF_DISAB_DIO0;
+		dir_ena |= II20K_DIR_DIO0_OUT;
+	} else {
+		/* input port */
+		ctrl01 |= II20K_CTRL01_DIO0_IN;
+		dir_ena &= ~II20K_DIR_DIO0_OUT;
+	}
+
+	/* port 1 - channels 8-15 */
+	if (s->io_bits & 0x0000ff00) {
+		/* output port */
+		ctrl01 &= ~II20K_CTRL01_DIO1_IN;
+		dir_ena &= ~II20K_BUF_DISAB_DIO1;
+		dir_ena |= II20K_DIR_DIO1_OUT;
+	} else {
+		/* input port */
+		ctrl01 |= II20K_CTRL01_DIO1_IN;
+		dir_ena &= ~II20K_DIR_DIO1_OUT;
+	}
+
+	/* port 2 - channels 16-23 */
+	if (s->io_bits & 0x00ff0000) {
+		/* output port */
+		ctrl23 &= ~II20K_CTRL23_DIO2_IN;
+		dir_ena &= ~II20K_BUF_DISAB_DIO2;
+		dir_ena |= II20K_DIR_DIO2_OUT;
+	} else {
+		/* input port */
+		ctrl23 |= II20K_CTRL23_DIO2_IN;
+		dir_ena &= ~II20K_DIR_DIO2_OUT;
+	}
 
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 32;
-	s->insn_bits = pci20xxx_dio_insn_bits;
-	s->insn_config = pci20xxx_dio_insn_config;
-	s->maxdata = 1;
-	s->len_chanlist = 32;
-	s->range_table = &range_digital;
-	s->io_bits = 0;
+	/* port 3 - channels 24-31 */
+	if (s->io_bits & 0xff000000) {
+		/* output port */
+		ctrl23 &= ~II20K_CTRL23_DIO3_IN;
+		dir_ena &= ~II20K_BUF_DISAB_DIO3;
+		dir_ena |= II20K_DIR_DIO3_OUT;
+	} else {
+		/* input port */
+		ctrl23 |= II20K_CTRL23_DIO3_IN;
+		dir_ena &= ~II20K_DIR_DIO3_OUT;
+	}
 
-	/* digital I/O lines default to input on board reset. */
-	pci20xxx_dio_config(dev, s);
+	ctrl23 |= II20K_CTRL01_SET;
+	ctrl23 |= II20K_CTRL23_SET;
 
-	return 0;
+	/* order is important */
+	writeb(ctrl01, devpriv->ioaddr + II20K_CTRL01_REG);
+	writeb(ctrl23, devpriv->ioaddr + II20K_CTRL23_REG);
+	writeb(dir_ena, devpriv->ioaddr + II20K_DIR_ENA_REG);
 }
 
-static int pci20xxx_dio_insn_config(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data)
+static int ii20k_dio_insn_config(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	int mask, bits;
+	unsigned int mask = 1 << CR_CHAN(insn->chanspec);
+	unsigned int bits;
 
-	mask = 1 << CR_CHAN(insn->chanspec);
 	if (mask & 0x000000ff)
 		bits = 0x000000ff;
 	else if (mask & 0x0000ff00)
@@ -520,143 +361,186 @@ static int pci20xxx_dio_insn_config(struct comedi_device *dev,
 		bits = 0x00ff0000;
 	else
 		bits = 0xff000000;
-	if (data[0])
-		s->io_bits |= bits;
-	else
+
+	switch (data[0]) {
+	case INSN_CONFIG_DIO_INPUT:
 		s->io_bits &= ~bits;
-	pci20xxx_dio_config(dev, s);
+		break;
+	case INSN_CONFIG_DIO_OUTPUT:
+		s->io_bits |= bits;
+		break;
+	case INSN_CONFIG_DIO_QUERY:
+		data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+		return insn->n;
+	default:
+		return -EINVAL;
+	}
 
-	return 1;
+	ii20k_dio_config(dev, s);
+
+	return insn->n;
 }
 
-static int pci20xxx_dio_insn_bits(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+static int ii20k_dio_insn_bits(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	struct pci20xxx_private *devpriv = dev->private;
-	unsigned int mask = data[0];
+	struct ii20k_private *devpriv = dev->private;
+	unsigned int mask = data[0] & s->io_bits;	/* outputs only */
+	unsigned int bits = data[1];
+
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
+
+		if (mask & 0x000000ff)
+			writeb((s->state >> 0) & 0xff,
+			       devpriv->ioaddr + II20K_DIO0_REG);
+		if (mask & 0x0000ff00)
+			writeb((s->state >> 8) & 0xff,
+			       devpriv->ioaddr + II20K_DIO1_REG);
+		if (mask & 0x00ff0000)
+			writeb((s->state >> 16) & 0xff,
+			       devpriv->ioaddr + II20K_DIO2_REG);
+		if (mask & 0xff000000)
+			writeb((s->state >> 24) & 0xff,
+			       devpriv->ioaddr + II20K_DIO3_REG);
+	}
 
-	s->state &= ~mask;
-	s->state |= (mask & data[1]);
-
-	mask &= s->io_bits;
-	if (mask & 0x000000ff)
-		writeb((s->state >> 0) & 0xff,
-		       devpriv->ioaddr + PCI20000_DIO_0);
-	if (mask & 0x0000ff00)
-		writeb((s->state >> 8) & 0xff,
-		       devpriv->ioaddr + PCI20000_DIO_1);
-	if (mask & 0x00ff0000)
-		writeb((s->state >> 16) & 0xff,
-		       devpriv->ioaddr + PCI20000_DIO_2);
-	if (mask & 0xff000000)
-		writeb((s->state >> 24) & 0xff,
-		       devpriv->ioaddr + PCI20000_DIO_3);
-
-	data[1] = readb(devpriv->ioaddr + PCI20000_DIO_0);
-	data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8;
-	data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16;
-	data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24;
+	data[1] = readb(devpriv->ioaddr + II20K_DIO0_REG);
+	data[1] |= readb(devpriv->ioaddr + II20K_DIO1_REG) << 8;
+	data[1] |= readb(devpriv->ioaddr + II20K_DIO2_REG) << 16;
+	data[1] |= readb(devpriv->ioaddr + II20K_DIO3_REG) << 24;
 
 	return insn->n;
 }
 
-static void pci20xxx_dio_config(struct comedi_device *dev,
-				struct comedi_subdevice *s)
+static int ii20k_init_module(struct comedi_device *dev,
+			     struct comedi_subdevice *s)
+{
+	struct ii20k_ao_private *ao_spriv;
+	void __iomem *iobase = ii20k_module_iobase(dev, s);
+	unsigned char id;
+
+	id = readb(iobase + II20K_ID_REG);
+	switch (id) {
+	case II20K_ID_PCI20006M_1:
+	case II20K_ID_PCI20006M_2:
+		ao_spriv = comedi_alloc_spriv(s, sizeof(*ao_spriv));
+		if (!ao_spriv)
+			return -ENOMEM;
+
+		/* Analog Output subdevice */
+		s->type		= COMEDI_SUBD_AO;
+		s->subdev_flags	= SDF_WRITABLE;
+		s->n_chan	= (id == II20K_ID_PCI20006M_2) ? 2 : 1;
+		s->maxdata	= 0xffff;
+		s->range_table	= &ii20k_ao_ranges;
+		s->insn_read	= ii20k_ao_insn_read;
+		s->insn_write	= ii20k_ao_insn_write;
+		break;
+	case II20K_ID_PCI20341M_1:
+		/* Analog Input subdevice */
+		s->type		= COMEDI_SUBD_AI;
+		s->subdev_flags	= SDF_READABLE | SDF_DIFF;
+		s->n_chan	= 4;
+		s->maxdata	= 0xffff;
+		s->range_table	= &ii20k_ai_ranges;
+		s->insn_read	= ii20k_ai_insn_read;
+		break;
+	default:
+		s->type = COMEDI_SUBD_UNUSED;
+		break;
+	}
+
+	return 0;
+}
+
+static int ii20k_attach(struct comedi_device *dev,
+			struct comedi_devconfig *it)
 {
-	struct pci20xxx_private *devpriv = dev->private;
-	unsigned char control_01;
-	unsigned char control_23;
-	unsigned char buffer;
+	struct ii20k_private *devpriv;
+	struct comedi_subdevice *s;
+	unsigned char id;
+	bool has_dio;
+	int ret;
+
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+	if (!devpriv)
+		return -ENOMEM;
 
-	control_01 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_01);
-	control_23 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_23);
-	buffer = readb(devpriv->ioaddr + PCI20000_DIO_BUFFER);
+	devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0];
 
-	if (s->io_bits & 0x000000ff) {
-		/* output port 0 */
-		control_01 &= PCI20000_DIO_EOC;
-		buffer = (buffer & (~(DIO_BE << DIO_PS_0))) | (DIO_BO <<
-							       DIO_PS_0);
-	} else {
-		/* input port 0 */
-		control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_EIC;
-		buffer = (buffer & (~(DIO_BI << DIO_PS_0)));
+	id = readb(devpriv->ioaddr + II20K_ID_REG);
+	switch (id & II20K_ID_MASK) {
+	case II20K_ID_PCI20001C_1A:
+		break;
+	case II20K_ID_PCI20001C_2A:
+		has_dio = true;
+		break;
+	default:
+		return -ENODEV;
 	}
-	if (s->io_bits & 0x0000ff00) {
-		/* output port 1 */
-		control_01 &= PCI20000_DIO_OOC;
-		buffer = (buffer & (~(DIO_BE << DIO_PS_1))) | (DIO_BO <<
-							       DIO_PS_1);
+
+	ret = comedi_alloc_subdevices(dev, 4);
+	if (ret)
+		return ret;
+
+	s = &dev->subdevices[0];
+	if (id & II20K_ID_MOD1_EMPTY) {
+		s->type = COMEDI_SUBD_UNUSED;
 	} else {
-		/* input port 1 */
-		control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_OIC;
-		buffer = (buffer & (~(DIO_BI << DIO_PS_1)));
+		ret = ii20k_init_module(dev, s);
+		if (ret)
+			return ret;
 	}
-	if (s->io_bits & 0x00ff0000) {
-		/* output port 2 */
-		control_23 &= PCI20000_DIO_EOC;
-		buffer = (buffer & (~(DIO_BE << DIO_PS_2))) | (DIO_BO <<
-							       DIO_PS_2);
+
+	s = &dev->subdevices[1];
+	if (id & II20K_ID_MOD2_EMPTY) {
+		s->type = COMEDI_SUBD_UNUSED;
 	} else {
-		/* input port 2 */
-		control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_EIC;
-		buffer = (buffer & (~(DIO_BI << DIO_PS_2)));
+		ret = ii20k_init_module(dev, s);
+		if (ret)
+			return ret;
 	}
-	if (s->io_bits & 0xff000000) {
-		/* output port 3 */
-		control_23 &= PCI20000_DIO_OOC;
-		buffer = (buffer & (~(DIO_BE << DIO_PS_3))) | (DIO_BO <<
-							       DIO_PS_3);
+
+	s = &dev->subdevices[2];
+	if (id & II20K_ID_MOD3_EMPTY) {
+		s->type = COMEDI_SUBD_UNUSED;
 	} else {
-		/* input port 3 */
-		control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_OIC;
-		buffer = (buffer & (~(DIO_BI << DIO_PS_3)));
+		ret = ii20k_init_module(dev, s);
+		if (ret)
+			return ret;
 	}
-	writeb(control_01, devpriv->ioaddr + PCI20000_DIO_CONTROL_01);
-	writeb(control_23, devpriv->ioaddr + PCI20000_DIO_CONTROL_23);
-	writeb(buffer, devpriv->ioaddr + PCI20000_DIO_BUFFER);
-}
 
-#if 0
-static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct pci20xxx_private *devpriv = dev->private;
-
-	/* XXX if the channel is configured for input, does this
-	   do bad things? */
-	/* XXX it would be a good idea to only update the registers
-	   that _need_ to be updated.  This requires changes to
-	   comedi, however. */
-	writeb((s->state >> 0) & 0xff, devpriv->ioaddr + PCI20000_DIO_0);
-	writeb((s->state >> 8) & 0xff, devpriv->ioaddr + PCI20000_DIO_1);
-	writeb((s->state >> 16) & 0xff, devpriv->ioaddr + PCI20000_DIO_2);
-	writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3);
-}
-
-static unsigned int pci20xxx_di(struct comedi_device *dev,
-				struct comedi_subdevice *s)
-{
-	struct pci20xxx_private *devpriv = dev->private;
-	unsigned int bits;
-
-	/* XXX same note as above */
-	bits = readb(devpriv->ioaddr + PCI20000_DIO_0);
-	bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8;
-	bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16;
-	bits |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24;
+	/* Digital I/O subdevice */
+	s = &dev->subdevices[3];
+	if (has_dio) {
+		s->type		= COMEDI_SUBD_DIO;
+		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+		s->n_chan	= 32;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= ii20k_dio_insn_bits;
+		s->insn_config	= ii20k_dio_insn_config;
+
+		/* default all channels to input */
+		ii20k_dio_config(dev, s);
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
-	return bits;
+	return 0;
 }
-#endif
 
-static struct comedi_driver pci20xxx_driver = {
+static struct comedi_driver ii20k_driver = {
 	.driver_name	= "ii_pci20kc",
 	.module		= THIS_MODULE,
-	.attach		= pci20xxx_attach,
-	.detach		= pci20xxx_detach,
+	.attach		= ii20k_attach,
+	.detach		= comedi_legacy_detach,
 };
-module_comedi_driver(pci20xxx_driver);
+module_comedi_driver(ii20k_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 94609f4..b52d58e 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -38,6 +38,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
@@ -638,10 +639,9 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
 		return -EINVAL;
 	}
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	init_timer(&devpriv->timer);
 	switch (pcidev->device) {
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index f10cf10..15589f6 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -29,6 +29,7 @@ This driver is a simple driver to read the counter values from
 Kolter Electronic PCI Counter Card.
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index c2308fd..1eda40a 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -40,6 +40,7 @@ broken.
 
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -1544,10 +1545,9 @@ static int me4000_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = thisboard;
 	dev->board_name = thisboard->name;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = comedi_alloc_devpriv(dev, sizeof(*info));
 	if (!info)
 		return -ENOMEM;
-	dev->private = info;
 
 	result = comedi_pci_enable(dev);
 	if (result)
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 7533ece..e8a743c 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -30,6 +30,7 @@
  *    Analog Input, Analog Output, Digital I/O
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
@@ -490,10 +491,9 @@ static int me_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL);
+	dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private));
 	if (!dev_private)
 		return -ENOMEM;
-	dev->private = dev_private;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index 12c34db..35cb4ac 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -46,6 +46,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
index d4487e8..8423b8b 100644
--- a/drivers/staging/comedi/drivers/mite.h
+++ b/drivers/staging/comedi/drivers/mite.h
@@ -21,6 +21,7 @@
 
 #include <linux/pci.h>
 #include <linux/log2.h>
+#include <linux/slab.h>
 #include "../comedidev.h"
 
 /*  #define DEBUG_MITE */
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index 713842a..acbaeee 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -51,9 +51,9 @@ Configuration Options:
 	1      -10.1V .. +10.1V
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/delay.h>
 
 /* Consecutive I/O port addresses */
@@ -286,10 +286,9 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	switch (it->options[1]) {
 	case 0:
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index 5ecd1b1..9d75ea4 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -24,11 +24,10 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
 
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #define MULTIQ3_SIZE 16
 
 /*
@@ -232,10 +231,9 @@ static int multiq3_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	/* ai subdevice */
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index 903c2ef..c2745f2 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -36,6 +36,7 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
 #define DEBUG 1
 #define DEBUG_FLAGS
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -335,10 +336,9 @@ static int ni6527_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 42a78de..3ba4c57 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -46,9 +46,9 @@ except maybe the 6514.
 #define DEBUG 1
 #define DEBUG_FLAGS
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 
 #include "../comedidev.h"
 
@@ -591,10 +591,9 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index a9e0004..3607336 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -34,6 +34,7 @@
  * DAQ 6601/6602 User Manual (NI 322137B-01)
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -929,10 +930,9 @@ static int ni_660x_allocate_private(struct comedi_device *dev)
 	struct ni_660x_private *devpriv;
 	unsigned i;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	spin_lock_init(&devpriv->mite_channel_lock);
 	spin_lock_init(&devpriv->interrupt_lock);
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 1a185b9..0201625 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -36,9 +36,9 @@ Commands are not supported.
 
 */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 
 #include "../comedidev.h"
 
@@ -205,10 +205,9 @@ static int ni_670x_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 7ea5aa3..2512ce8 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -58,12 +58,14 @@ TRIG_WAKE_EOS
 
 */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/io.h>
+
 #include <asm/dma.h>
 
 #include "8253.h"
@@ -719,10 +721,9 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	int i;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], A2150_SIZE);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index e080053..0025496 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -36,10 +36,9 @@ Configuration options:
  * document 320379.pdf.
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 /* board egisters */
 /* registers with _2_ are accessed when GRP2WR is set in CFG1 */
 
@@ -341,10 +340,9 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 713edd5..856c73d 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -89,10 +89,10 @@ are not supported.
 
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/delay.h>
 #include <linux/isapnp.h>
 
 #include "ni_stc.h"
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index da7396f..8520d83 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -30,11 +30,10 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
  *
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #include "comedi_fc.h"
 #include "8255.h"
 
@@ -645,10 +644,9 @@ static int atmio16d_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* reset the atmio16d hardware */
 	reset_atmio16d(dev);
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 3c50e31..4165965 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -45,9 +45,9 @@ Manuals:	Register level:	http://www.ni.com/pdf/manuals/340698.pdf
 		User Manual:	http://www.ni.com/pdf/manuals/320676d.pdf
 */
 
-#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 
 #include "../comedidev.h"
 
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index d3d4eb9..335ea34 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -31,6 +31,7 @@ This is just a wrapper around the 8255.o driver to properly handle
 the PCMCIA interface.
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include <pcmcia/cistpl.h>
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index f161e70..1add114 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -57,6 +57,7 @@
  * 320502b (lab-pc+)
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -64,79 +65,12 @@
 
 #include "../comedidev.h"
 
-#include <asm/dma.h>
-
 #include "8253.h"
 #include "8255.h"
 #include "comedi_fc.h"
 #include "ni_labpc.h"
-
-/*
- * Register map (all registers are 8-bit)
- */
-#define STAT1_REG		0x00	/* R: Status 1 reg */
-#define STAT1_DAVAIL		(1 << 0)
-#define STAT1_OVERRUN		(1 << 1)
-#define STAT1_OVERFLOW		(1 << 2)
-#define STAT1_CNTINT		(1 << 3)
-#define STAT1_GATA0		(1 << 5)
-#define STAT1_EXTGATA0		(1 << 6)
-#define CMD1_REG		0x00	/* W: Command 1 reg */
-#define CMD1_MA(x)		(((x) & 0x7) << 0)
-#define CMD1_TWOSCMP		(1 << 3)
-#define CMD1_GAIN(x)		(((x) & 0x7) << 4)
-#define CMD1_SCANEN		(1 << 7)
-#define CMD2_REG		0x01	/* W: Command 2 reg */
-#define CMD2_PRETRIG		(1 << 0)
-#define CMD2_HWTRIG		(1 << 1)
-#define CMD2_SWTRIG		(1 << 2)
-#define CMD2_TBSEL		(1 << 3)
-#define CMD2_2SDAC0		(1 << 4)
-#define CMD2_2SDAC1		(1 << 5)
-#define CMD2_LDAC(x)		(1 << (6 + (x)))
-#define CMD3_REG		0x02	/* W: Command 3 reg */
-#define CMD3_DMAEN		(1 << 0)
-#define CMD3_DIOINTEN		(1 << 1)
-#define CMD3_DMATCINTEN		(1 << 2)
-#define CMD3_CNTINTEN		(1 << 3)
-#define CMD3_ERRINTEN		(1 << 4)
-#define CMD3_FIFOINTEN		(1 << 5)
-#define ADC_START_CONVERT_REG	0x03	/* W: Start Convert reg */
-#define DAC_LSB_REG(x)		(0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */
-#define DAC_MSB_REG(x)		(0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */
-#define ADC_FIFO_CLEAR_REG	0x08	/* W: A/D FIFO Clear reg */
-#define ADC_FIFO_REG		0x0a	/* R: A/D FIFO reg */
-#define DMATC_CLEAR_REG		0x0a	/* W: DMA Interrupt Clear reg */
-#define TIMER_CLEAR_REG		0x0c	/* W: Timer Interrupt Clear reg */
-#define CMD6_REG		0x0e	/* W: Command 6 reg */
-#define CMD6_NRSE		(1 << 0)
-#define CMD6_ADCUNI		(1 << 1)
-#define CMD6_DACUNI(x)		(1 << (2 + (x)))
-#define CMD6_HFINTEN		(1 << 5)
-#define CMD6_DQINTEN		(1 << 6)
-#define CMD6_SCANUP		(1 << 7)
-#define CMD4_REG		0x0f	/* W: Command 3 reg */
-#define CMD4_INTSCAN		(1 << 0)
-#define CMD4_EOIRCV		(1 << 1)
-#define CMD4_ECLKDRV		(1 << 2)
-#define CMD4_SEDIFF		(1 << 3)
-#define CMD4_ECLKRCV		(1 << 4)
-#define DIO_BASE_REG		0x10	/* R/W: 8255 DIO base reg */
-#define COUNTER_A_BASE_REG	0x14	/* R/W: 8253 Counter A base reg */
-#define COUNTER_B_BASE_REG	0x18	/* R/W: 8253 Counter B base reg */
-#define CMD5_REG		0x1c	/* W: Command 5 reg */
-#define CMD5_WRTPRT		(1 << 2)
-#define CMD5_DITHEREN		(1 << 3)
-#define CMD5_CALDACLD		(1 << 4)
-#define CMD5_SCLK		(1 << 5)
-#define CMD5_SDATA		(1 << 6)
-#define CMD5_EEPROMCS		(1 << 7)
-#define STAT2_REG		0x1d	/* R: Status 2 reg */
-#define STAT2_PROMOUT		(1 << 0)
-#define STAT2_OUTA1		(1 << 1)
-#define STAT2_FIFONHF		(1 << 2)
-#define INTERVAL_COUNT_REG	0x1e	/* W: Interval Counter Data reg */
-#define INTERVAL_STROBE_REG	0x1f	/* W: Interval Counter Strobe reg */
+#include "ni_labpc_regs.h"
+#include "ni_labpc_isadma.h"
 
 #define LABPC_SIZE		0x20	/* size of ISA io region */
 #define LABPC_TIMER_BASE	500	/* 2 MHz master clock */
@@ -239,11 +173,6 @@ static const struct labpc_boardinfo labpc_boards[] = {
 };
 #endif
 
-/* size in bytes of dma buffer */
-static const int dma_buffer_size = 0xff00;
-/* 2 bytes per sample */
-static const int sample_size = 2;
-
 static int labpc_counter_load(struct comedi_device *dev,
 			      unsigned long base_address,
 			      unsigned int counter_number,
@@ -451,32 +380,6 @@ static int labpc_ai_insn_read(struct comedi_device *dev,
 	return insn->n;
 }
 
-#ifdef CONFIG_ISA_DMA_API
-/* utility function that suggests a dma transfer size in bytes */
-static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
-{
-	unsigned int size;
-	unsigned int freq;
-
-	if (cmd->convert_src == TRIG_TIMER)
-		freq = 1000000000 / cmd->convert_arg;
-	/* return some default value */
-	else
-		freq = 0xffffffff;
-
-	/* make buffer fill in no more than 1/3 second */
-	size = (freq / 3) * sample_size;
-
-	/* set a minimum and maximum size allowed */
-	if (size > dma_buffer_size)
-		size = dma_buffer_size - dma_buffer_size % sample_size;
-	else if (size < sample_size)
-		size = sample_size;
-
-	return size;
-}
-#endif
-
 static bool labpc_use_continuous_mode(const struct comedi_cmd *cmd,
 				      enum scan_mode mode)
 {
@@ -869,25 +772,20 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		return ret;
 	}
 
-#ifdef CONFIG_ISA_DMA_API
-	/*  figure out what method we will use to transfer data */
-	if (devpriv->dma_chan &&	/*  need a dma channel allocated */
-		/*
-		 * dma unsafe at RT priority,
-		 * and too much setup time for TRIG_WAKE_EOS for
-		 */
-	    (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0) {
+	/* figure out what method we will use to transfer data */
+	if (labpc_have_dma_chan(dev) &&
+	    /* dma unsafe at RT priority,
+	     * and too much setup time for TRIG_WAKE_EOS */
+	    (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0)
 		xfer = isa_dma_transfer;
-		/* pc-plus has no fifo-half full interrupt */
-	} else
-#endif
-	if (board->is_labpc1200 &&
-		   /*  wake-end-of-scan should interrupt on fifo not empty */
-		   (cmd->flags & TRIG_WAKE_EOS) == 0 &&
-		   /*  make sure we are taking more than just a few points */
-		   (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) {
+	else if (/* pc-plus has no fifo-half full interrupt */
+		 board->is_labpc1200 &&
+		 /* wake-end-of-scan should interrupt on fifo not empty */
+		 (cmd->flags & TRIG_WAKE_EOS) == 0 &&
+		 /* make sure we are taking more than just a few points */
+		 (cmd->stop_src != TRIG_COUNT || devpriv->count > 256))
 		xfer = fifo_half_full_transfer;
-	} else
+	else
 		xfer = fifo_not_empty_transfer;
 	devpriv->current_transfer = xfer;
 
@@ -952,40 +850,14 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	labpc_clear_adc_fifo(dev);
 
-#ifdef CONFIG_ISA_DMA_API
-	/*  set up dma transfer */
-	if (xfer == isa_dma_transfer) {
-		unsigned long irq_flags;
-
-		irq_flags = claim_dma_lock();
-		disable_dma(devpriv->dma_chan);
-		/* clear flip-flop to make sure 2-byte registers for
-		 * count and address get set correctly */
-		clear_dma_ff(devpriv->dma_chan);
-		set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
-		/*  set appropriate size of transfer */
-		devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd);
-		if (cmd->stop_src == TRIG_COUNT &&
-		    devpriv->count * sample_size < devpriv->dma_transfer_size) {
-			devpriv->dma_transfer_size =
-			    devpriv->count * sample_size;
-		}
-		set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
-		enable_dma(devpriv->dma_chan);
-		release_dma_lock(irq_flags);
-		/*  enable board's dma */
-		devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN);
-	} else
-		devpriv->cmd3 &= ~(CMD3_DMAEN | CMD3_DMATCINTEN);
-#endif
+	if (xfer == isa_dma_transfer)
+		labpc_setup_dma(dev, s);
 
 	/*  enable error interrupts */
 	devpriv->cmd3 |= CMD3_ERRINTEN;
 	/*  enable fifo not empty interrupt? */
 	if (xfer == fifo_not_empty_transfer)
 		devpriv->cmd3 |= CMD3_FIFOINTEN;
-	else
-		devpriv->cmd3 &= ~CMD3_FIFOINTEN;
 	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
 
 	/*  setup any external triggering/pacing (cmd4 register) */
@@ -1026,74 +898,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	return 0;
 }
 
-#ifdef CONFIG_ISA_DMA_API
-static void labpc_drain_dma(struct comedi_device *dev)
-{
-	struct labpc_private *devpriv = dev->private;
-	struct comedi_subdevice *s = dev->read_subdev;
-	struct comedi_async *async = s->async;
-	int status;
-	unsigned long flags;
-	unsigned int max_points, num_points, residue, leftover;
-	int i;
-
-	status = devpriv->stat1;
-
-	flags = claim_dma_lock();
-	disable_dma(devpriv->dma_chan);
-	/* clear flip-flop to make sure 2-byte registers for
-	 * count and address get set correctly */
-	clear_dma_ff(devpriv->dma_chan);
-
-	/*  figure out how many points to read */
-	max_points = devpriv->dma_transfer_size / sample_size;
-	/* residue is the number of points left to be done on the dma
-	 * transfer.  It should always be zero at this point unless
-	 * the stop_src is set to external triggering.
-	 */
-	residue = get_dma_residue(devpriv->dma_chan) / sample_size;
-	num_points = max_points - residue;
-	if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT)
-		num_points = devpriv->count;
-
-	/*  figure out how many points will be stored next time */
-	leftover = 0;
-	if (async->cmd.stop_src != TRIG_COUNT) {
-		leftover = devpriv->dma_transfer_size / sample_size;
-	} else if (devpriv->count > num_points) {
-		leftover = devpriv->count - num_points;
-		if (leftover > max_points)
-			leftover = max_points;
-	}
-
-	/* write data to comedi buffer */
-	for (i = 0; i < num_points; i++)
-		cfc_write_to_buffer(s, devpriv->dma_buffer[i]);
-
-	if (async->cmd.stop_src == TRIG_COUNT)
-		devpriv->count -= num_points;
-
-	/*  set address and count for next transfer */
-	set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
-	set_dma_count(devpriv->dma_chan, leftover * sample_size);
-	release_dma_lock(flags);
-
-	async->events |= COMEDI_CB_BLOCK;
-}
-
-static void handle_isa_dma(struct comedi_device *dev)
-{
-	struct labpc_private *devpriv = dev->private;
-
-	labpc_drain_dma(dev);
-
-	enable_dma(devpriv->dma_chan);
-
-	/*  clear dma tc interrupt */
-	devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
-}
-#endif
-
 /* read all available samples from ai fifo */
 static int labpc_drain_fifo(struct comedi_device *dev)
 {
@@ -1130,12 +934,10 @@ static int labpc_drain_fifo(struct comedi_device *dev)
  * when acquisition is terminated by stop_src == TRIG_EXT). */
 static void labpc_drain_dregs(struct comedi_device *dev)
 {
-#ifdef CONFIG_ISA_DMA_API
 	struct labpc_private *devpriv = dev->private;
 
 	if (devpriv->current_transfer == isa_dma_transfer)
 		labpc_drain_dma(dev);
-#endif
 
 	labpc_drain_fifo(dev);
 }
@@ -1180,18 +982,9 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
 		return IRQ_HANDLED;
 	}
 
-#ifdef CONFIG_ISA_DMA_API
-	if (devpriv->current_transfer == isa_dma_transfer) {
-		/*
-		 * if a dma terminal count of external stop trigger
-		 * has occurred
-		 */
-		if (devpriv->stat1 & STAT1_GATA0 ||
-		    (board->is_labpc1200 && devpriv->stat2 & STAT2_OUTA1)) {
-			handle_isa_dma(dev);
-		}
-	} else
-#endif
+	if (devpriv->current_transfer == isa_dma_transfer)
+		labpc_handle_dma_status(dev);
+	else
 		labpc_drain_fifo(dev);
 
 	if (devpriv->stat1 & STAT1_CNTINT) {
@@ -1697,10 +1490,9 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	unsigned int dma_chan = it->options[2];
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_request_region(dev, it->options[0], LABPC_SIZE);
 	if (ret)
@@ -1710,29 +1502,8 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_ISA_DMA_API
-	if (dev->irq && (dma_chan == 1 || dma_chan == 3)) {
-		devpriv->dma_buffer = kmalloc(dma_buffer_size,
-					      GFP_KERNEL | GFP_DMA);
-		if (devpriv->dma_buffer) {
-			ret = request_dma(dma_chan, dev->board_name);
-			if (ret == 0) {
-				unsigned long dma_flags;
-
-				devpriv->dma_chan = dma_chan;
-				devpriv->dma_addr =
-					virt_to_bus(devpriv->dma_buffer);
-
-				dma_flags = claim_dma_lock();
-				disable_dma(devpriv->dma_chan);
-				set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
-				release_dma_lock(dma_flags);
-			} else {
-				kfree(devpriv->dma_buffer);
-			}
-		}
-	}
-#endif
+	if (dev->irq)
+		labpc_init_dma_chan(dev, dma_chan);
 
 	return 0;
 }
@@ -1741,11 +1512,9 @@ static void labpc_detach(struct comedi_device *dev)
 {
 	struct labpc_private *devpriv = dev->private;
 
-	if (devpriv) {
-		kfree(devpriv->dma_buffer);
-		if (devpriv->dma_chan)
-			free_dma(devpriv->dma_chan);
-	}
+	if (devpriv)
+		labpc_free_dma_chan(dev);
+
 	comedi_legacy_detach(dev);
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index ce67f4b..0a8b322 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -53,10 +53,10 @@ NI manuals:
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include <linux/delay.h>
-#include <linux/slab.h>
 
 #include "8253.h"
 #include "8255.h"
@@ -96,10 +96,9 @@ static int labpc_auto_attach(struct comedi_device *dev,
 	if (!link->irq)
 		return -EINVAL;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	return labpc_common_attach(dev, link->irq, IRQF_SHARED);
 }
diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c
new file mode 100644
index 0000000..2149596
--- /dev/null
+++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c
@@ -0,0 +1,226 @@
+/*
+ * comedi/drivers/ni_labpc_isadma.c
+ * ISA DMA support for National Instruments Lab-PC series boards and
+ * compatibles.
+ *
+ * Extracted from ni_labpc.c:
+ * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "../comedidev.h"
+
+#include <asm/dma.h>
+
+#include "comedi_fc.h"
+#include "ni_labpc.h"
+#include "ni_labpc_regs.h"
+#include "ni_labpc_isadma.h"
+
+/* size in bytes of dma buffer */
+static const int dma_buffer_size = 0xff00;
+/* 2 bytes per sample */
+static const int sample_size = 2;
+
+/* utility function that suggests a dma transfer size in bytes */
+static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
+{
+	unsigned int size;
+	unsigned int freq;
+
+	if (cmd->convert_src == TRIG_TIMER)
+		freq = 1000000000 / cmd->convert_arg;
+	else
+		/* return some default value */
+		freq = 0xffffffff;
+
+	/* make buffer fill in no more than 1/3 second */
+	size = (freq / 3) * sample_size;
+
+	/* set a minimum and maximum size allowed */
+	if (size > dma_buffer_size)
+		size = dma_buffer_size - dma_buffer_size % sample_size;
+	else if (size < sample_size)
+		size = sample_size;
+
+	return size;
+}
+
+void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct labpc_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned long irq_flags;
+
+	irq_flags = claim_dma_lock();
+	disable_dma(devpriv->dma_chan);
+	/* clear flip-flop to make sure 2-byte registers for
+	 * count and address get set correctly */
+	clear_dma_ff(devpriv->dma_chan);
+	set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
+	/* set appropriate size of transfer */
+	devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd);
+	if (cmd->stop_src == TRIG_COUNT &&
+	    devpriv->count * sample_size < devpriv->dma_transfer_size)
+		devpriv->dma_transfer_size = devpriv->count * sample_size;
+	set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
+	enable_dma(devpriv->dma_chan);
+	release_dma_lock(irq_flags);
+	/* set CMD3 bits for caller to enable DMA and interrupt */
+	devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN);
+}
+EXPORT_SYMBOL_GPL(labpc_setup_dma);
+
+void labpc_drain_dma(struct comedi_device *dev)
+{
+	struct labpc_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_async *async = s->async;
+	int status;
+	unsigned long flags;
+	unsigned int max_points, num_points, residue, leftover;
+	int i;
+
+	status = devpriv->stat1;
+
+	flags = claim_dma_lock();
+	disable_dma(devpriv->dma_chan);
+	/* clear flip-flop to make sure 2-byte registers for
+	 * count and address get set correctly */
+	clear_dma_ff(devpriv->dma_chan);
+
+	/* figure out how many points to read */
+	max_points = devpriv->dma_transfer_size / sample_size;
+	/* residue is the number of points left to be done on the dma
+	 * transfer.  It should always be zero at this point unless
+	 * the stop_src is set to external triggering.
+	 */
+	residue = get_dma_residue(devpriv->dma_chan) / sample_size;
+	num_points = max_points - residue;
+	if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT)
+		num_points = devpriv->count;
+
+	/* figure out how many points will be stored next time */
+	leftover = 0;
+	if (async->cmd.stop_src != TRIG_COUNT) {
+		leftover = devpriv->dma_transfer_size / sample_size;
+	} else if (devpriv->count > num_points) {
+		leftover = devpriv->count - num_points;
+		if (leftover > max_points)
+			leftover = max_points;
+	}
+
+	/* write data to comedi buffer */
+	for (i = 0; i < num_points; i++)
+		cfc_write_to_buffer(s, devpriv->dma_buffer[i]);
+
+	if (async->cmd.stop_src == TRIG_COUNT)
+		devpriv->count -= num_points;
+
+	/* set address and count for next transfer */
+	set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
+	set_dma_count(devpriv->dma_chan, leftover * sample_size);
+	release_dma_lock(flags);
+
+	async->events |= COMEDI_CB_BLOCK;
+}
+EXPORT_SYMBOL_GPL(labpc_drain_dma);
+
+static void handle_isa_dma(struct comedi_device *dev)
+{
+	struct labpc_private *devpriv = dev->private;
+
+	labpc_drain_dma(dev);
+
+	enable_dma(devpriv->dma_chan);
+
+	/* clear dma tc interrupt */
+	devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
+}
+
+void labpc_handle_dma_status(struct comedi_device *dev)
+{
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	struct labpc_private *devpriv = dev->private;
+
+	/*
+	 * if a dma terminal count of external stop trigger
+	 * has occurred
+	 */
+	if (devpriv->stat1 & STAT1_GATA0 ||
+	    (board->is_labpc1200 && devpriv->stat2 & STAT2_OUTA1))
+		handle_isa_dma(dev);
+}
+EXPORT_SYMBOL_GPL(labpc_handle_dma_status);
+
+int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan)
+{
+	struct labpc_private *devpriv = dev->private;
+	void *dma_buffer;
+	unsigned long dma_flags;
+	int ret;
+
+	if (dma_chan != 1 && dma_chan != 3)
+		return -EINVAL;
+
+	dma_buffer = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA);
+	if (!dma_buffer)
+		return -ENOMEM;
+
+	ret = request_dma(dma_chan, dev->board_name);
+	if (ret) {
+		kfree(dma_buffer);
+		return ret;
+	}
+
+	devpriv->dma_buffer = dma_buffer;
+	devpriv->dma_chan = dma_chan;
+	devpriv->dma_addr = virt_to_bus(devpriv->dma_buffer);
+
+	dma_flags = claim_dma_lock();
+	disable_dma(devpriv->dma_chan);
+	set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
+	release_dma_lock(dma_flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(labpc_init_dma_chan);
+
+void labpc_free_dma_chan(struct comedi_device *dev)
+{
+	struct labpc_private *devpriv = dev->private;
+
+	kfree(devpriv->dma_buffer);
+	devpriv->dma_buffer = NULL;
+	if (devpriv->dma_chan) {
+		free_dma(devpriv->dma_chan);
+		devpriv->dma_chan = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(labpc_free_dma_chan);
+
+static int __init ni_labpc_isadma_init_module(void)
+{
+	return 0;
+}
+module_init(ni_labpc_isadma_init_module);
+
+static void __exit ni_labpc_isadma_cleanup_module(void)
+{
+}
+module_exit(ni_labpc_isadma_cleanup_module);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi NI Lab-PC ISA DMA support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h
new file mode 100644
index 0000000..771af4b
--- /dev/null
+++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h
@@ -0,0 +1,57 @@
+/*
+ * ni_labpc ISA DMA support.
+*/
+
+#ifndef _NI_LABPC_ISADMA_H
+#define _NI_LABPC_ISADMA_H
+
+#define NI_LABPC_HAVE_ISA_DMA	IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISADMA)
+
+#if NI_LABPC_HAVE_ISA_DMA
+
+static inline bool labpc_have_dma_chan(struct comedi_device *dev)
+{
+	struct labpc_private *devpriv = dev->private;
+
+	return (bool)devpriv->dma_chan;
+}
+
+int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan);
+void labpc_free_dma_chan(struct comedi_device *dev);
+void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s);
+void labpc_drain_dma(struct comedi_device *dev);
+void labpc_handle_dma_status(struct comedi_device *dev);
+
+#else
+
+static inline bool labpc_have_dma_chan(struct comedi_device *dev)
+{
+	return false;
+}
+
+static inline int labpc_init_dma_chan(struct comedi_device *dev,
+				      unsigned int dma_chan)
+{
+	return -ENOTSUPP;
+}
+
+static inline void labpc_free_dma_chan(struct comedi_device *dev)
+{
+}
+
+static inline void labpc_setup_dma(struct comedi_device *dev,
+				   struct comedi_subdevice *s)
+{
+}
+
+static inline void labpc_drain_dma(struct comedi_device *dev)
+{
+}
+
+static inline void labpc_handle_dma_status(struct comedi_device *dev)
+{
+}
+
+#endif
+
+#endif /* _NI_LABPC_ISADMA_H */
diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c
index 6c79237..8be681f 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_pci.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c
@@ -29,8 +29,8 @@
  * 340914a (pci-1200)
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -72,10 +72,9 @@ static int labpc_pci_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
diff --git a/drivers/staging/comedi/drivers/ni_labpc_regs.h b/drivers/staging/comedi/drivers/ni_labpc_regs.h
new file mode 100644
index 0000000..2a274a3
--- /dev/null
+++ b/drivers/staging/comedi/drivers/ni_labpc_regs.h
@@ -0,0 +1,75 @@
+/*
+ * ni_labpc register definitions.
+*/
+
+#ifndef _NI_LABPC_REGS_H
+#define _NI_LABPC_REGS_H
+
+/*
+ * Register map (all registers are 8-bit)
+ */
+#define STAT1_REG		0x00	/* R: Status 1 reg */
+#define STAT1_DAVAIL		(1 << 0)
+#define STAT1_OVERRUN		(1 << 1)
+#define STAT1_OVERFLOW		(1 << 2)
+#define STAT1_CNTINT		(1 << 3)
+#define STAT1_GATA0		(1 << 5)
+#define STAT1_EXTGATA0		(1 << 6)
+#define CMD1_REG		0x00	/* W: Command 1 reg */
+#define CMD1_MA(x)		(((x) & 0x7) << 0)
+#define CMD1_TWOSCMP		(1 << 3)
+#define CMD1_GAIN(x)		(((x) & 0x7) << 4)
+#define CMD1_SCANEN		(1 << 7)
+#define CMD2_REG		0x01	/* W: Command 2 reg */
+#define CMD2_PRETRIG		(1 << 0)
+#define CMD2_HWTRIG		(1 << 1)
+#define CMD2_SWTRIG		(1 << 2)
+#define CMD2_TBSEL		(1 << 3)
+#define CMD2_2SDAC0		(1 << 4)
+#define CMD2_2SDAC1		(1 << 5)
+#define CMD2_LDAC(x)		(1 << (6 + (x)))
+#define CMD3_REG		0x02	/* W: Command 3 reg */
+#define CMD3_DMAEN		(1 << 0)
+#define CMD3_DIOINTEN		(1 << 1)
+#define CMD3_DMATCINTEN		(1 << 2)
+#define CMD3_CNTINTEN		(1 << 3)
+#define CMD3_ERRINTEN		(1 << 4)
+#define CMD3_FIFOINTEN		(1 << 5)
+#define ADC_START_CONVERT_REG	0x03	/* W: Start Convert reg */
+#define DAC_LSB_REG(x)		(0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */
+#define DAC_MSB_REG(x)		(0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */
+#define ADC_FIFO_CLEAR_REG	0x08	/* W: A/D FIFO Clear reg */
+#define ADC_FIFO_REG		0x0a	/* R: A/D FIFO reg */
+#define DMATC_CLEAR_REG		0x0a	/* W: DMA Interrupt Clear reg */
+#define TIMER_CLEAR_REG		0x0c	/* W: Timer Interrupt Clear reg */
+#define CMD6_REG		0x0e	/* W: Command 6 reg */
+#define CMD6_NRSE		(1 << 0)
+#define CMD6_ADCUNI		(1 << 1)
+#define CMD6_DACUNI(x)		(1 << (2 + (x)))
+#define CMD6_HFINTEN		(1 << 5)
+#define CMD6_DQINTEN		(1 << 6)
+#define CMD6_SCANUP		(1 << 7)
+#define CMD4_REG		0x0f	/* W: Command 3 reg */
+#define CMD4_INTSCAN		(1 << 0)
+#define CMD4_EOIRCV		(1 << 1)
+#define CMD4_ECLKDRV		(1 << 2)
+#define CMD4_SEDIFF		(1 << 3)
+#define CMD4_ECLKRCV		(1 << 4)
+#define DIO_BASE_REG		0x10	/* R/W: 8255 DIO base reg */
+#define COUNTER_A_BASE_REG	0x14	/* R/W: 8253 Counter A base reg */
+#define COUNTER_B_BASE_REG	0x18	/* R/W: 8253 Counter B base reg */
+#define CMD5_REG		0x1c	/* W: Command 5 reg */
+#define CMD5_WRTPRT		(1 << 2)
+#define CMD5_DITHEREN		(1 << 3)
+#define CMD5_CALDACLD		(1 << 4)
+#define CMD5_SCLK		(1 << 5)
+#define CMD5_SDATA		(1 << 6)
+#define CMD5_EEPROMCS		(1 << 7)
+#define STAT2_REG		0x1d	/* R: Status 2 reg */
+#define STAT2_PROMOUT		(1 << 0)
+#define STAT2_OUTA1		(1 << 1)
+#define STAT2_FIFONHF		(1 << 2)
+#define INTERVAL_COUNT_REG	0x1e	/* W: Interval Counter Data reg */
+#define INTERVAL_STROBE_REG	0x1f	/* W: Interval Counter Strobe reg */
+
+#endif /* _NI_LABPC_REGS_H */
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 3e9f544..04f4b7d 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -58,6 +58,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 #include "8255.h"
 #include "mite.h"
 #include "comedi_fc.h"
@@ -4363,10 +4364,9 @@ static int ni_alloc_private(struct comedi_device *dev)
 {
 	struct ni_private *devpriv;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	spin_lock_init(&devpriv->window_lock);
 	spin_lock_init(&devpriv->soft_reg_copy_lock);
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index f813f57..229a273 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -36,6 +36,7 @@ See the notes in the ni_atmio.o driver.
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include <linux/delay.h>
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 5b2f72e..8ac7a7c 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -50,6 +50,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
 /* #define DEBUG 1 */
 /* #define DEBUG_FLAGS */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
@@ -1108,10 +1109,9 @@ static int nidio_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	spin_lock_init(&devpriv->mite_channel_lock);
 
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 35681ba..536be83 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -106,6 +106,7 @@ Bugs:
 
 */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 
 #include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
index f2cf76d..9b120c7 100644
--- a/drivers/staging/comedi/drivers/ni_tio.c
+++ b/drivers/staging/comedi/drivers/ni_tio.c
@@ -44,6 +44,9 @@ TODO:
 	Support use of both banks X and Y
 */
 
+#include <linux/module.h>
+#include <linux/slab.h>
+
 #include "ni_tio_internal.h"
 
 static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter,
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index cff50bc..45691ef 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -44,6 +44,7 @@ TODO:
 	Support use of both banks X and Y
 */
 
+#include <linux/module.h>
 #include "comedi_fc.h"
 #include "ni_tio_internal.h"
 #include "mite.h"
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 7abf3f7..e859f85 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -53,10 +53,10 @@ supported.
 
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/delay.h>
 
 #include "comedi_fc.h"
@@ -474,10 +474,9 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	/* AI subdevice */
diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
index cea657c..8af13e7 100644
--- a/drivers/staging/comedi/drivers/pcl724.c
+++ b/drivers/staging/comedi/drivers/pcl724.c
@@ -1,6 +1,6 @@
 /*
  * pcl724.c
- * Comedi driver for 8255 based ISA DIO boards
+ * Comedi driver for 8255 based ISA and PC/104 DIO boards
  *
  * Michal Dobes <dobes@tesnet.cz>
  */
@@ -14,6 +14,7 @@
  *	    (ADLink) ACL-7122 [acl7122]
  *	    (ADLink) ACL-7124 [acl7124]
  *	    (ADLink) PET-48DIO [pet48dio]
+ *	    (WinSystems) PCM-IO48 [pcmio48]
  * Author: Michal Dobes <dobes@tesnet.cz>
  * Status: untested
  *
@@ -25,11 +26,9 @@
  *	   1,  96:  96 DIO configuration
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-#include <linux/delay.h>
-
 #include "8255.h"
 
 #define SIZE_8255	4
@@ -70,6 +69,10 @@ static const struct pcl724_board boardtypes[] = {
 		.io_range	= 0x02,
 		.is_pet48	= 1,
 		.numofports	= 2,	/* 48 DIO channels */
+	}, {
+		.name		= "pcmio48",
+		.io_range	= 0x08,
+		.numofports	= 2,	/* 48 DIO channels */
 	},
 };
 
@@ -148,5 +151,5 @@ static struct comedi_driver pcl724_driver = {
 module_comedi_driver(pcl724_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi driver for 8255 based ISA DIO boards");
+MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index 893f012..a4d0bcc 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -62,10 +62,9 @@ Interrupts are not supported.
     their web page.  (http://www.cir.com/)
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #undef ACL6126_IRQ		/* no interrupt support (yet) */
 
 #define PCL726_SIZE 16
@@ -229,10 +228,9 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	for (i = 0; i < 12; i++) {
 		devpriv->bipolar[i] = 0;
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index 862e75f..2a659f2 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -27,10 +27,9 @@
  * The ACL-7130 card has an 8254 timer/counter not supported by this driver.
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 /*
  * Register map
  *
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index cd02786..35251e7 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -108,12 +108,12 @@
  *	   3= 20V unipolar inputs
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/gfp.h>
 #include "../comedidev.h"
 
 #include <linux/delay.h>
-#include <linux/ioport.h>
 #include <linux/io.h>
 #include <asm/dma.h>
 
@@ -1110,10 +1110,9 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	irq = 0;
 	if (board->IRQbits != 0) {	/* board support IRQ */
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 91bd207..f031349 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -32,9 +32,9 @@ Configuration Options:
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
 #include <linux/gfp.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -922,10 +922,9 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		return -EIO;
 	}
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* grab our IRQ */
 	irq = 0;
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 91cb1bd..a52ba82 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -98,7 +98,7 @@ A word or two about DMA. Driver support DMA operations at two ways:
 
 */
 
-#include <linux/ioport.h>
+#include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -1227,10 +1227,9 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	unsigned long pages;
 	struct comedi_subdevice *s;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->io_range = board->io_range;
 	if ((board->fifo) && (it->options[2] == -1)) {
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index 5a9cd38..cca972e 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -28,11 +28,9 @@ Copy/pasted/hacked from pcm724.c
  *   struct comedi_insn
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-#include <linux/delay.h>
-
 #include "8255.h"
 
 #define PCM3724_SIZE   16
@@ -228,10 +226,9 @@ static int pcm3724_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret, i;
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	priv = comedi_alloc_devpriv(dev, sizeof(*priv));
 	if (!priv)
 		return -ENOMEM;
-	dev->private = priv;
 
 	ret = comedi_request_region(dev, it->options[0], PCM3724_SIZE);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index d5c728d..423f236 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -38,6 +38,7 @@
  *	   1 = two's complement (+-10V input range)
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #define PCMAD_STATUS		0
diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
index 774a63d..1c7a135 100644
--- a/drivers/staging/comedi/drivers/pcmda12.c
+++ b/drivers/staging/comedi/drivers/pcmda12.c
@@ -48,6 +48,7 @@
  *   [1] - Do Simultaneous Xfer (see description)
  */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 /* AI range is not configurable, it's set by jumpers on the board */
@@ -138,10 +139,9 @@ static int pcmda12_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->simultaneous_xfer_mode = it->options[1];
 
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 9f76b1f..fab93a7 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -72,6 +72,7 @@ Configuration Options:
 	leave out if you don't need this feature)
 */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
@@ -1039,10 +1040,9 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	for (asic = 0; asic < MAX_ASICS; ++asic) {
 		devpriv->asics[asic].num = asic;
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index c43b633..13f1943 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -73,6 +73,7 @@
  *             can be the same as first irq!)
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
@@ -609,10 +610,9 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic)
 		spin_lock_init(&devpriv->asics[asic].spinlock);
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index 005fbef..2ae4ee1 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -30,10 +30,9 @@ Configuration options:
   [0] - I/O port base
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 struct boarddef_struct {
 	const char *name;
 	unsigned int iosize;
@@ -109,10 +108,9 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* analog output subdevice */
 	s = &dev->subdevices[0];
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index e092ce8..9775d36 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -47,6 +47,7 @@ Status: works
 Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 #include <linux/semaphore.h>
 
@@ -715,10 +716,9 @@ static int daqp_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
 	ret = comedi_pcmcia_enable(dev, NULL);
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 9b93a1f..635c8f5 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -95,6 +95,7 @@
  * Digital-IO and Analog-Out only support instruction mode.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -1338,10 +1339,9 @@ static int rtd_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index f698c7f..cbb4ba5 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -49,11 +49,11 @@
  *   [8] - DAC 1 encoding (same as DAC 0)
  */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 /*
  * Register map
  */
@@ -298,10 +298,9 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	inb(dev->iobase + RTI800_ADCHI);
 	outb(0, dev->iobase + RTI800_CLRFLAGS);
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->adc_2comp = (it->options[4] == 0);
 	devpriv->dac_2comp[0] = (it->options[6] == 0);
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index 9e74450..a3fa2a4 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -32,10 +32,9 @@ Configuration Options:
     [17] - dac#7 ...
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
-#include <linux/ioport.h>
-
 #define RTI802_SIZE 4
 
 #define RTI802_SELECT 0
@@ -93,10 +92,9 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 1);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index e1587e5..6670b86 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -36,8 +36,8 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
-#include <linux/ioport.h>
 #include <asm/byteorder.h>
 
 #define S526_SIZE 64
@@ -553,10 +553,9 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 48c4b70..b0ba9b9 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -59,6 +59,8 @@ INSN_CONFIG instructions:
    comedi_do_insn(cf,&insn); //executing configuration
 */
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -2585,10 +2587,9 @@ static int s626_auto_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	ret = comedi_pci_enable(dev);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
index d2756b8..a85e6bd 100644
--- a/drivers/staging/comedi/drivers/s626.h
+++ b/drivers/staging/comedi/drivers/s626.h
@@ -65,8 +65,6 @@
 #define FALSE   (0)
 #endif
 
-#include <linux/slab.h>
-
 #define S626_SIZE 0x0200
 #define DMABUF_SIZE			4096	/*  4k pages */
 
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index b4f5fe3..441813f 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -26,10 +26,10 @@ Status: in development
 
 */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 #include <linux/delay.h>
-#include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -719,10 +719,9 @@ static int serial2002_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->port = it->options[0];
 	devpriv->speed = it->options[1];
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index 06aee30..f76fd09 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -67,6 +67,7 @@ Configuration Options:
  * options that are used with comedi_config.
  */
 
+#include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -484,10 +485,9 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* dev->board_name = thisboard->name; */
 
 	/* Allocate the private data */
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 /*
  * Supported boards are usually either auto-attached via the
@@ -558,10 +558,9 @@ static int skel_auto_attach(struct comedi_device *dev,
 	dev->board_name = thisboard->name;
 
 	/* Allocate the private data */
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	/* Enable the PCI device. */
 	ret = comedi_pci_enable(dev);
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 45c661c..4da4d32 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -26,6 +26,7 @@ Status: unknown
 
 /* include files ----------------------------------------------------------- */
 
+#include <linux/module.h>
 #include "../comedidev.h"
 
 /* Some global definitions: the registers of the DNP ----------------------- */
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index c9201d8..93eec2f 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -40,9 +40,9 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
+#include <linux/delay.h>
 #include "../comedidev.h"
-#include <linux/ioport.h>
-#include <linux/slab.h>
 
 #define DRIVER_NAME "unioxx5"
 #define UNIOXX5_SIZE 0x10
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 279e5bd..689b452 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -78,9 +78,6 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  *
  */
 
-/* generates loads of debug info */
-/* #define NOISY_DUX_DEBUGBUG */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -94,42 +91,29 @@ sampling rate. If you sample two channels you get 4kHz and so on.
 
 #include "comedi_fc.h"
 
-/* timeout for the USB-transfer in ms*/
-#define BULK_TIMEOUT 1000
-
-/* constants for "firmware" upload and download */
-#define FIRMWARE "usbdux_firmware.bin"
-#define USBDUXSUB_FIRMWARE 0xA0
-#define VENDOR_DIR_IN  0xC0
-#define VENDOR_DIR_OUT 0x40
-
-/* internal addresses of the 8051 processor */
-#define USBDUXSUB_CPUCS 0xE600
-
-/*
- * the minor device number, major is 180 only for debugging purposes and to
- * upload special firmware (programming the eeprom etc) which is not compatible
- * with the comedi framwork
- */
-#define USBDUXSUB_MINOR 32
-
-/* max lenghth of the transfer-buffer for software upload */
-#define TB_LEN 0x2000
-
-/* Input endpoint number: ISO/IRQ */
-#define ISOINEP           6
-
-/* Output endpoint number: ISO/IRQ */
-#define ISOOUTEP          2
-
-/* This EP sends DUX commands to USBDUX */
-#define COMMAND_OUT_EP     1
-
-/* This EP receives the DUX commands from USBDUX */
-#define COMMAND_IN_EP        8
-
-/* Output endpoint for PWM */
-#define PWM_EP         4
+/* constants for firmware upload and download */
+#define USBDUX_FIRMWARE		"usbdux_firmware.bin"
+#define USBDUX_FIRMWARE_MAX_LEN	0x2000
+#define USBDUX_FIRMWARE_CMD	0xa0
+#define VENDOR_DIR_IN		0xc0
+#define VENDOR_DIR_OUT		0x40
+#define USBDUX_CPU_CS		0xe600
+
+/* usbdux bulk transfer commands */
+#define USBDUX_CMD_MULT_AI	0
+#define USBDUX_CMD_AO		1
+#define USBDUX_CMD_DIO_CFG	2
+#define USBDUX_CMD_DIO_BITS	3
+#define USBDUX_CMD_SINGLE_AI	4
+#define USBDUX_CMD_TIMER_RD	5
+#define USBDUX_CMD_TIMER_WR	6
+#define USBDUX_CMD_PWM_ON	7
+#define USBDUX_CMD_PWM_OFF	8
+
+#define USBDUX_NUM_AO_CHAN	4
+
+/* timeout for the USB-transfer in ms */
+#define BULK_TIMEOUT		1000
 
 /* 300Hz max frequ under PWM */
 #define MIN_PWM_PERIOD  ((long)(1E9/300))
@@ -137,9 +121,6 @@ sampling rate. If you sample two channels you get 4kHz and so on.
 /* Default PWM frequency */
 #define PWM_DEFAULT_PERIOD ((long)(1E9/100))
 
-/* Number of channels */
-#define NUMCHANNELS       8
-
 /* Size of one A/D value */
 #define SIZEADIN          ((sizeof(int16_t)))
 
@@ -152,9 +133,6 @@ sampling rate. If you sample two channels you get 4kHz and so on.
 /* 16 bytes. */
 #define SIZEINSNBUF       16
 
-/* Number of DA channels */
-#define NUMOUTCHANNELS    8
-
 /* size of one value for the D/A converter: channel and value */
 #define SIZEDAOUT          ((sizeof(int8_t)+sizeof(int16_t)))
 
@@ -185,101 +163,56 @@ sampling rate. If you sample two channels you get 4kHz and so on.
 /* must have more buffers due to buggy USB ctr */
 #define NUMOFOUTBUFFERSHIGH    10
 
-/* Total number of usbdux devices */
-#define NUMUSBDUX             16
-
-/* Analogue in subdevice */
-#define SUBDEV_AD             0
-
-/* Analogue out subdevice */
-#define SUBDEV_DA             1
-
-/* Digital I/O */
-#define SUBDEV_DIO            2
-
-/* counter */
-#define SUBDEV_COUNTER        3
-
-/* timer aka pwm output */
-#define SUBDEV_PWM            4
-
 /* number of retries to get the right dux command */
 #define RETRIES 10
 
-/**************************************************/
-/* comedi constants */
-static const struct comedi_lrange range_usbdux_ai_range = { 4, {
-								BIP_RANGE
-								(4.096),
-								BIP_RANGE(4.096
-									  / 2),
-								UNI_RANGE
-								(4.096),
-								UNI_RANGE(4.096
-									  / 2)
-								}
+static const struct comedi_lrange range_usbdux_ai_range = {
+	4, {
+		BIP_RANGE(4.096),
+		BIP_RANGE(4.096 / 2),
+		UNI_RANGE(4.096),
+		UNI_RANGE(4.096 / 2)
+	}
 };
 
-static const struct comedi_lrange range_usbdux_ao_range = { 2, {
-								BIP_RANGE
-								(4.096),
-								UNI_RANGE
-								(4.096),
-								}
+static const struct comedi_lrange range_usbdux_ao_range = {
+	2, {
+		BIP_RANGE(4.096),
+		UNI_RANGE(4.096)
+	}
 };
 
-/*
- * private structure of one subdevice
- */
-
-/*
- * This is the structure which holds all the data of
- * this driver one sub device just now: A/D
- */
-struct usbduxsub {
-	/* attached? */
-	int attached;
-	/* is it associated with a subdevice? */
-	int probed;
-	/* pointer to the usb-device */
-	struct usb_device *usbdev;
+struct usbdux_private {
 	/* actual number of in-buffers */
-	int num_in_buffers;
+	int n_ai_urbs;
 	/* actual number of out-buffers */
-	int num_out_buffers;
+	int n_ao_urbs;
 	/* ISO-transfer handling: buffers */
-	struct urb **urb_in;
-	struct urb **urb_out;
+	struct urb **ai_urbs;
+	struct urb **ao_urbs;
 	/* pwm-transfer handling */
-	struct urb *urb_pwm;
+	struct urb *pwm_urb;
 	/* PWM period */
 	unsigned int pwm_period;
 	/* PWM internal delay for the GPIF in the FX2 */
-	int8_t pwn_delay;
+	int8_t pwm_delay;
 	/* size of the PWM buffer which holds the bit pattern */
-	int size_pwm_buf;
+	int pwm_buf_sz;
 	/* input buffer for the ISO-transfer */
-	int16_t *in_buffer;
+	int16_t *in_buf;
 	/* input buffer for single insn */
-	int16_t *insn_buffer;
-	/* output buffer for single DA outputs */
-	int16_t *out_buffer;
-	/* interface number */
-	int ifnum;
-	/* interface structure in 2.6 */
-	struct usb_interface *interface;
-	/* comedi device for the interrupt context */
-	struct comedi_device *comedidev;
-	/* is it USB_SPEED_HIGH or not? */
-	short int high_speed;
-	/* asynchronous command is running */
-	short int ai_cmd_running;
-	short int ao_cmd_running;
-	/* pwm is running */
-	short int pwm_cmd_running;
-	/* continous acquisition */
-	short int ai_continous;
-	short int ao_continous;
+	int16_t *insn_buf;
+
+	int8_t ao_chanlist[USBDUX_NUM_AO_CHAN];
+	unsigned int ao_readback[USBDUX_NUM_AO_CHAN];
+
+	unsigned int high_speed:1;
+	unsigned int ai_cmd_running:1;
+	unsigned int ai_continous:1;
+	unsigned int ao_cmd_running:1;
+	unsigned int ao_continous:1;
+	unsigned int pwm_cmd_running:1;
+
 	/* number of samples to acquire */
 	int ai_sample_count;
 	int ao_sample_count;
@@ -291,132 +224,62 @@ struct usbduxsub {
 	unsigned int ao_counter;
 	/* interval in frames/uframes */
 	unsigned int ai_interval;
-	/* D/A commands */
-	int8_t *dac_commands;
 	/* commands */
 	int8_t *dux_commands;
 	struct semaphore sem;
 };
 
-/*
- * The pointer to the private usb-data of the driver is also the private data
- * for the comedi-device.  This has to be global as the usb subsystem needs
- * global variables. The other reason is that this structure must be there
- * _before_ any comedi command is issued. The usb subsystem must be initialised
- * before comedi can access it.
- */
-static struct usbduxsub usbduxsub[NUMUSBDUX];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
-/*
- * Stops the data acquision
- * It should be safe to call this function from any context
- */
-static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp)
+static void usbdux_unlink_urbs(struct urb **urbs, int num_urbs)
 {
-	int i = 0;
-	int err = 0;
+	int i;
 
-	if (usbduxsub_tmp && usbduxsub_tmp->urb_in) {
-		for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
-			if (usbduxsub_tmp->urb_in[i]) {
-				/* We wait here until all transfers have been
-				 * cancelled. */
-				usb_kill_urb(usbduxsub_tmp->urb_in[i]);
-			}
-			dev_dbg(&usbduxsub_tmp->interface->dev,
-				"comedi: usbdux: unlinked InURB %d, err=%d\n",
-				i, err);
-		}
-	}
-	return err;
+	for (i = 0; i < num_urbs; i++)
+		usb_kill_urb(urbs[i]);
 }
 
-/*
- * This will stop a running acquisition operation
- * Is called from within this driver from both the
- * interrupt context and from comedi
- */
-static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+static void usbdux_ai_stop(struct comedi_device *dev, int do_unlink)
 {
-	int ret = 0;
-
-	if (!this_usbduxsub) {
-		pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
-		return -EFAULT;
-	}
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
-
-	if (do_unlink) {
-		/* stop aquistion */
-		ret = usbduxsub_unlink_inurbs(this_usbduxsub);
-	}
+	struct usbdux_private *devpriv = dev->private;
 
-	this_usbduxsub->ai_cmd_running = 0;
+	if (do_unlink && devpriv->ai_urbs)
+		usbdux_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);
 
-	return ret;
+	devpriv->ai_cmd_running = 0;
 }
 
-/*
- * This will cancel a running acquisition operation.
- * This is called by comedi but never from inside the driver.
- */
 static int usbdux_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	struct usbduxsub *this_usbduxsub;
-	int res = 0;
-
-	/* force unlink of all urbs */
-	this_usbduxsub = dev->private;
-	if (!this_usbduxsub)
-		return -EFAULT;
-
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
+	struct usbdux_private *devpriv = dev->private;
 
 	/* prevent other CPUs from submitting new commands just now */
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
+	down(&devpriv->sem);
 	/* unlink only if the urb really has been submitted */
-	res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
-	up(&this_usbduxsub->sem);
-	return res;
+	usbdux_ai_stop(dev, devpriv->ai_cmd_running);
+	up(&devpriv->sem);
+
+	return 0;
 }
 
 /* analogue IN - interrupt service routine */
 static void usbduxsub_ai_isoc_irq(struct urb *urb)
 {
+	struct comedi_device *dev = urb->context;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct usbdux_private *devpriv = dev->private;
 	int i, err, n;
-	struct usbduxsub *this_usbduxsub;
-	struct comedi_device *this_comedidev;
-	struct comedi_subdevice *s;
-
-	/* the context variable points to the subdevice */
-	this_comedidev = urb->context;
-	/* the private structure of the subdevice is struct usbduxsub */
-	this_usbduxsub = this_comedidev->private;
-	/* subdevice which is the AD converter */
-	s = &this_comedidev->subdevices[SUBDEV_AD];
 
 	/* first we test if something unusual has just happened */
 	switch (urb->status) {
 	case 0:
 		/* copy the result in the transfer buffer */
-		memcpy(this_usbduxsub->in_buffer,
-		       urb->transfer_buffer, SIZEINBUF);
+		memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
 		break;
 	case -EILSEQ:
 		/* error in the ISOchronous data */
 		/* we don't copy the data into the transfer buffer */
 		/* and recycle the last data byte */
-		dev_dbg(&urb->dev->dev,
-			"comedi%d: usbdux: CRC error in ISO IN stream.\n",
-			this_usbduxsub->comedidev->minor);
-
+		dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
 		break;
 
 	case -ECONNRESET:
@@ -424,29 +287,27 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
 	case -ESHUTDOWN:
 	case -ECONNABORTED:
 		/* happens after an unlink command */
-		if (this_usbduxsub->ai_cmd_running) {
-			/* we are still running a command */
-			/* tell this comedi */
+		if (devpriv->ai_cmd_running) {
 			s->async->events |= COMEDI_CB_EOA;
 			s->async->events |= COMEDI_CB_ERROR;
-			comedi_event(this_usbduxsub->comedidev, s);
+			comedi_event(dev, s);
 			/* stop the transfer w/o unlink */
-			usbdux_ai_stop(this_usbduxsub, 0);
+			usbdux_ai_stop(dev, 0);
 		}
 		return;
 
 	default:
 		/* a real error on the bus */
 		/* pass error to comedi if we are really running a command */
-		if (this_usbduxsub->ai_cmd_running) {
-			dev_err(&urb->dev->dev,
-				"Non-zero urb status received in ai intr "
-				"context: %d\n", urb->status);
+		if (devpriv->ai_cmd_running) {
+			dev_err(dev->class_dev,
+				"Non-zero urb status received in ai intr context: %d\n",
+				urb->status);
 			s->async->events |= COMEDI_CB_EOA;
 			s->async->events |= COMEDI_CB_ERROR;
-			comedi_event(this_usbduxsub->comedidev, s);
+			comedi_event(dev, s);
 			/* don't do an unlink here */
-			usbdux_ai_stop(this_usbduxsub, 0);
+			usbdux_ai_stop(dev, 0);
 		}
 		return;
 	}
@@ -455,7 +316,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
 	 * at this point we are reasonably sure that nothing dodgy has happened
 	 * are we running a command?
 	 */
-	if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
+	if (unlikely(!devpriv->ai_cmd_running)) {
 		/*
 		 * not running a command, do not continue execution if no
 		 * asynchronous command is running in particular not resubmit
@@ -463,144 +324,101 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
 		return;
 	}
 
-	urb->dev = this_usbduxsub->usbdev;
+	urb->dev = comedi_to_usb_dev(dev);
 
 	/* resubmit the urb */
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (unlikely(err < 0)) {
-		dev_err(&urb->dev->dev,
-			"comedi_: urb resubmit failed in int-context! err=%d\n",
-			err);
+		dev_err(dev->class_dev,
+			"urb resubmit failed in int-context! err=%d\n", err);
 		if (err == -EL2NSYNC)
-			dev_err(&urb->dev->dev,
-				"buggy USB host controller or bug in IRQ "
-				"handler!\n");
+			dev_err(dev->class_dev,
+				"buggy USB host controller or bug in IRQ handler!\n");
 		s->async->events |= COMEDI_CB_EOA;
 		s->async->events |= COMEDI_CB_ERROR;
-		comedi_event(this_usbduxsub->comedidev, s);
+		comedi_event(dev, s);
 		/* don't do an unlink here */
-		usbdux_ai_stop(this_usbduxsub, 0);
+		usbdux_ai_stop(dev, 0);
 		return;
 	}
 
-	this_usbduxsub->ai_counter--;
-	if (likely(this_usbduxsub->ai_counter > 0))
+	devpriv->ai_counter--;
+	if (likely(devpriv->ai_counter > 0))
 		return;
 
 	/* timer zero, transfer measurements to comedi */
-	this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+	devpriv->ai_counter = devpriv->ai_timer;
 
 	/* test, if we transmit only a fixed number of samples */
-	if (!(this_usbduxsub->ai_continous)) {
+	if (!devpriv->ai_continous) {
 		/* not continuous, fixed number of samples */
-		this_usbduxsub->ai_sample_count--;
+		devpriv->ai_sample_count--;
 		/* all samples received? */
-		if (this_usbduxsub->ai_sample_count < 0) {
+		if (devpriv->ai_sample_count < 0) {
 			/* prevent a resubmit next time */
-			usbdux_ai_stop(this_usbduxsub, 0);
+			usbdux_ai_stop(dev, 0);
 			/* say comedi that the acquistion is over */
 			s->async->events |= COMEDI_CB_EOA;
-			comedi_event(this_usbduxsub->comedidev, s);
+			comedi_event(dev, s);
 			return;
 		}
 	}
 	/* get the data from the USB bus and hand it over to comedi */
 	n = s->async->cmd.chanlist_len;
 	for (i = 0; i < n; i++) {
+		unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]);
+		int16_t val = le16_to_cpu(devpriv->in_buf[i]);
+
+		/* bipolar data is two's-complement */
+		if (comedi_range_is_bipolar(s, range))
+			val ^= ((s->maxdata + 1) >> 1);
+
 		/* transfer data */
-		if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
-			err = comedi_buf_put
-			    (s->async,
-			     le16_to_cpu(this_usbduxsub->in_buffer[i]) ^ 0x800);
-		} else {
-			err = comedi_buf_put
-			    (s->async,
-			     le16_to_cpu(this_usbduxsub->in_buffer[i]));
-		}
+		err = comedi_buf_put(s->async, val);
 		if (unlikely(err == 0)) {
 			/* buffer overflow */
-			usbdux_ai_stop(this_usbduxsub, 0);
+			usbdux_ai_stop(dev, 0);
 			return;
 		}
 	}
 	/* tell comedi that data is there */
 	s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
-	comedi_event(this_usbduxsub->comedidev, s);
-}
-
-static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp)
-{
-	int i = 0;
-	int err = 0;
-
-	if (usbduxsub_tmp && usbduxsub_tmp->urb_out) {
-		for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
-			if (usbduxsub_tmp->urb_out[i])
-				usb_kill_urb(usbduxsub_tmp->urb_out[i]);
-
-			dev_dbg(&usbduxsub_tmp->interface->dev,
-				"comedi: usbdux: unlinked OutURB %d: res=%d\n",
-				i, err);
-		}
-	}
-	return err;
+	comedi_event(dev, s);
 }
 
-/* This will cancel a running acquisition operation
- * in any context.
- */
-static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+static void usbdux_ao_stop(struct comedi_device *dev, int do_unlink)
 {
-	int ret = 0;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
+	struct usbdux_private *devpriv = dev->private;
 
-	if (do_unlink)
-		ret = usbduxsub_unlink_outurbs(this_usbduxsub);
-
-	this_usbduxsub->ao_cmd_running = 0;
+	if (do_unlink && devpriv->ao_urbs)
+		usbdux_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs);
 
-	return ret;
+	devpriv->ao_cmd_running = 0;
 }
 
-/* force unlink, is called by comedi */
 static int usbdux_ao_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int res = 0;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
+	struct usbdux_private *devpriv = dev->private;
 
 	/* prevent other CPUs from submitting a command just now */
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
+	down(&devpriv->sem);
 	/* unlink only if it is really running */
-	res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
-	up(&this_usbduxsub->sem);
-	return res;
+	usbdux_ao_stop(dev, devpriv->ao_cmd_running);
+	up(&devpriv->sem);
+
+	return 0;
 }
 
 static void usbduxsub_ao_isoc_irq(struct urb *urb)
 {
-	int i, ret;
+	struct comedi_device *dev = urb->context;
+	struct comedi_subdevice *s = dev->write_subdev;
+	struct usbdux_private *devpriv = dev->private;
 	int8_t *datap;
-	struct usbduxsub *this_usbduxsub;
-	struct comedi_device *this_comedidev;
-	struct comedi_subdevice *s;
-
-	/* the context variable points to the subdevice */
-	this_comedidev = urb->context;
-	/* the private structure of the subdevice is struct usbduxsub */
-	this_usbduxsub = this_comedidev->private;
-
-	s = &this_comedidev->subdevices[SUBDEV_DA];
+	int len;
+	int ret;
+	int i;
 
 	switch (urb->status) {
 	case 0:
@@ -613,246 +431,131 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
 	case -ECONNABORTED:
 		/* after an unlink command, unplug, ... etc */
 		/* no unlink needed here. Already shutting down. */
-		if (this_usbduxsub->ao_cmd_running) {
+		if (devpriv->ao_cmd_running) {
 			s->async->events |= COMEDI_CB_EOA;
-			comedi_event(this_usbduxsub->comedidev, s);
-			usbdux_ao_stop(this_usbduxsub, 0);
+			comedi_event(dev, s);
+			usbdux_ao_stop(dev, 0);
 		}
 		return;
 
 	default:
 		/* a real error */
-		if (this_usbduxsub->ao_cmd_running) {
-			dev_err(&urb->dev->dev,
-				"comedi_: Non-zero urb status received in ao "
-				"intr context: %d\n", urb->status);
+		if (devpriv->ao_cmd_running) {
+			dev_err(dev->class_dev,
+				"Non-zero urb status received in ao intr context: %d\n",
+				urb->status);
 			s->async->events |= COMEDI_CB_ERROR;
 			s->async->events |= COMEDI_CB_EOA;
-			comedi_event(this_usbduxsub->comedidev, s);
+			comedi_event(dev, s);
 			/* we do an unlink if we are in the high speed mode */
-			usbdux_ao_stop(this_usbduxsub, 0);
+			usbdux_ao_stop(dev, 0);
 		}
 		return;
 	}
 
 	/* are we actually running? */
-	if (!(this_usbduxsub->ao_cmd_running))
+	if (!devpriv->ao_cmd_running)
 		return;
 
 	/* normal operation: executing a command in this subdevice */
-	this_usbduxsub->ao_counter--;
-	if ((int)this_usbduxsub->ao_counter <= 0) {
+	devpriv->ao_counter--;
+	if ((int)devpriv->ao_counter <= 0) {
 		/* timer zero */
-		this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+		devpriv->ao_counter = devpriv->ao_timer;
 
 		/* handle non continous acquisition */
-		if (!(this_usbduxsub->ao_continous)) {
+		if (!devpriv->ao_continous) {
 			/* fixed number of samples */
-			this_usbduxsub->ao_sample_count--;
-			if (this_usbduxsub->ao_sample_count < 0) {
+			devpriv->ao_sample_count--;
+			if (devpriv->ao_sample_count < 0) {
 				/* all samples transmitted */
-				usbdux_ao_stop(this_usbduxsub, 0);
+				usbdux_ao_stop(dev, 0);
 				s->async->events |= COMEDI_CB_EOA;
-				comedi_event(this_usbduxsub->comedidev, s);
+				comedi_event(dev, s);
 				/* no resubmit of the urb */
 				return;
 			}
 		}
+
 		/* transmit data to the USB bus */
-		((uint8_t *) (urb->transfer_buffer))[0] =
-		    s->async->cmd.chanlist_len;
+		datap = urb->transfer_buffer;
+		len = s->async->cmd.chanlist_len;
+		*datap++ = len;
 		for (i = 0; i < s->async->cmd.chanlist_len; i++) {
-			short temp;
-			if (i >= NUMOUTCHANNELS)
-				break;
+			unsigned int chan = devpriv->ao_chanlist[i];
+			short val;
 
-			/* pointer to the DA */
-			datap =
-			    (&(((int8_t *) urb->transfer_buffer)[i * 3 + 1]));
-			/* get the data from comedi */
-			ret = comedi_buf_get(s->async, &temp);
-			datap[0] = temp;
-			datap[1] = temp >> 8;
-			datap[2] = this_usbduxsub->dac_commands[i];
-			/* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
-			/* datap[0],datap[1],datap[2]); */
+			ret = comedi_buf_get(s->async, &val);
 			if (ret < 0) {
-				dev_err(&urb->dev->dev,
-					"comedi: buffer underflow\n");
-				s->async->events |= COMEDI_CB_EOA;
-				s->async->events |= COMEDI_CB_OVERFLOW;
+				dev_err(dev->class_dev, "buffer underflow\n");
+				s->async->events |= (COMEDI_CB_EOA |
+						     COMEDI_CB_OVERFLOW);
 			}
-			/* transmit data to comedi */
+			/* pointer to the DA */
+			*datap++ = val & 0xff;
+			*datap++ = (val >> 8) & 0xff;
+			*datap++ = chan;
+			devpriv->ao_readback[chan] = val;
+
 			s->async->events |= COMEDI_CB_BLOCK;
-			comedi_event(this_usbduxsub->comedidev, s);
+			comedi_event(dev, s);
 		}
 	}
 	urb->transfer_buffer_length = SIZEOUTBUF;
-	urb->dev = this_usbduxsub->usbdev;
+	urb->dev = comedi_to_usb_dev(dev);
 	urb->status = 0;
-	if (this_usbduxsub->ao_cmd_running) {
-		if (this_usbduxsub->high_speed) {
-			/* uframes */
-			urb->interval = 8;
-		} else {
-			/* frames */
-			urb->interval = 1;
-		}
+	if (devpriv->ao_cmd_running) {
+		if (devpriv->high_speed)
+			urb->interval = 8;	/* uframes */
+		else
+			urb->interval = 1;	/* frames */
 		urb->number_of_packets = 1;
 		urb->iso_frame_desc[0].offset = 0;
 		urb->iso_frame_desc[0].length = SIZEOUTBUF;
 		urb->iso_frame_desc[0].status = 0;
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		if (ret < 0) {
-			dev_err(&urb->dev->dev,
-				"comedi_: ao urb resubm failed in int-cont. "
-				"ret=%d", ret);
+			dev_err(dev->class_dev,
+				"ao urb resubm failed in int-cont. ret=%d",
+				ret);
 			if (ret == EL2NSYNC)
-				dev_err(&urb->dev->dev,
-					"buggy USB host controller or bug in "
-					"IRQ handling!\n");
+				dev_err(dev->class_dev,
+					"buggy USB host controller or bug in IRQ handling!\n");
 
 			s->async->events |= COMEDI_CB_EOA;
 			s->async->events |= COMEDI_CB_ERROR;
-			comedi_event(this_usbduxsub->comedidev, s);
+			comedi_event(dev, s);
 			/* don't do an unlink here */
-			usbdux_ao_stop(this_usbduxsub, 0);
+			usbdux_ao_stop(dev, 0);
 		}
 	}
 }
 
-#define FIRMWARE_MAX_LEN 0x2000
-
-static int usbdux_firmware_upload(struct comedi_device *dev,
-				  const u8 *data, size_t size,
-				  unsigned long context)
+static int usbdux_submit_urbs(struct comedi_device *dev,
+			      struct urb **urbs, int num_urbs,
+			      int input_urb)
 {
-	struct usbduxsub *usbduxsub = dev->private;
-	struct usb_device *usb = usbduxsub->usbdev;
-	uint8_t *buf;
-	uint8_t *tmp;
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	struct usbdux_private *devpriv = dev->private;
+	struct urb *urb;
 	int ret;
-
-	if (!data)
-		return 0;
-
-	if (size > FIRMWARE_MAX_LEN) {
-		dev_err(&usbduxsub->interface->dev,
-			"usbdux firmware binary it too large for FX2.\n");
-		return -ENOMEM;
-	}
-
-	/* we generate a local buffer for the firmware */
-	buf = kmemdup(data, size, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	/* we need a malloc'ed buffer for usb_control_msg() */
-	tmp = kmalloc(1, GFP_KERNEL);
-	if (!tmp) {
-		kfree(buf);
-		return -ENOMEM;
-	}
-
-	/* stop the current firmware on the device */
-	*tmp = 1;	/* 7f92 to one */
-	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
-			      USBDUXSUB_FIRMWARE,
-			      VENDOR_DIR_OUT,
-			      USBDUXSUB_CPUCS, 0x0000,
-			      tmp, 1,
-			      BULK_TIMEOUT);
-	if (ret < 0) {
-		dev_err(&usbduxsub->interface->dev,
-			"comedi_: can not stop firmware\n");
-		goto done;
-	}
-
-	/* upload the new firmware to the device */
-	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
-			      USBDUXSUB_FIRMWARE,
-			      VENDOR_DIR_OUT,
-			      0, 0x0000,
-			      buf, size,
-			      BULK_TIMEOUT);
-	if (ret < 0) {
-		dev_err(&usbduxsub->interface->dev,
-			"comedi_: firmware upload failed\n");
-		goto done;
-	}
-
-	/* start the new firmware on the device */
-	*tmp = 0;	/* 7f92 to zero */
-	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
-			      USBDUXSUB_FIRMWARE,
-			      VENDOR_DIR_OUT,
-			      USBDUXSUB_CPUCS, 0x0000,
-			      tmp, 1,
-			      BULK_TIMEOUT);
-	if (ret < 0)
-		dev_err(&usbduxsub->interface->dev,
-			"comedi_: can not start firmware\n");
-
-done:
-	kfree(tmp);
-	kfree(buf);
-	return ret;
-}
-
-static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub)
-{
-	int i, err_flag;
-
-	if (!usbduxsub)
-		return -EFAULT;
+	int i;
 
 	/* Submit all URBs and start the transfer on the bus */
-	for (i = 0; i < usbduxsub->num_in_buffers; i++) {
-		/* in case of a resubmission after an unlink... */
-		usbduxsub->urb_in[i]->interval = usbduxsub->ai_interval;
-		usbduxsub->urb_in[i]->context = usbduxsub->comedidev;
-		usbduxsub->urb_in[i]->dev = usbduxsub->usbdev;
-		usbduxsub->urb_in[i]->status = 0;
-		usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP;
-		dev_dbg(&usbduxsub->interface->dev,
-			"comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
-			usbduxsub->comedidev->minor, i,
-			(usbduxsub->urb_in[i]->context),
-			(usbduxsub->urb_in[i]->dev),
-			(usbduxsub->urb_in[i]->interval));
-		err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC);
-		if (err_flag) {
-			dev_err(&usbduxsub->interface->dev,
-				"comedi_: ai: usb_submit_urb(%d) error %d\n",
-				i, err_flag);
-			return err_flag;
-		}
-	}
-	return 0;
-}
-
-static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub)
-{
-	int i, err_flag;
-
-	if (!usbduxsub)
-		return -EFAULT;
+	for (i = 0; i < num_urbs; i++) {
+		urb = urbs[i];
 
-	for (i = 0; i < usbduxsub->num_out_buffers; i++) {
-		dev_dbg(&usbduxsub->interface->dev,
-			"comedi_: submitting out-urb[%d]\n", i);
 		/* in case of a resubmission after an unlink... */
-		usbduxsub->urb_out[i]->context = usbduxsub->comedidev;
-		usbduxsub->urb_out[i]->dev = usbduxsub->usbdev;
-		usbduxsub->urb_out[i]->status = 0;
-		usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP;
-		err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC);
-		if (err_flag) {
-			dev_err(&usbduxsub->interface->dev,
-				"comedi_: ao: usb_submit_urb(%d) error %d\n",
-				i, err_flag);
-			return err_flag;
-		}
+		if (input_urb)
+			urb->interval = devpriv->ai_interval;
+		urb->context = dev;
+		urb->dev = usb;
+		urb->status = 0;
+		urb->transfer_flags = URB_ISO_ASAP;
+
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret)
+			return ret;
 	}
 	return 0;
 }
@@ -860,13 +563,10 @@ static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub)
 static int usbdux_ai_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *this_usbduxsub = dev->private;
 	int err = 0, i;
 	unsigned int tmp_timer;
 
-	if (!(this_usbduxsub->probed))
-		return -ENODEV;
-
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -956,221 +656,143 @@ static int8_t create_adc_command(unsigned int chan, int range)
 	return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
 }
 
-/* bulk transfers to usbdux */
+static int send_dux_commands(struct comedi_device *dev, int cmd_type)
+{
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	struct usbdux_private *devpriv = dev->private;
+	int nsent;
 
-#define SENDADCOMMANDS            0
-#define SENDDACOMMANDS            1
-#define SENDDIOCONFIGCOMMAND      2
-#define SENDDIOBITSCOMMAND        3
-#define SENDSINGLEAD              4
-#define READCOUNTERCOMMAND        5
-#define WRITECOUNTERCOMMAND       6
-#define SENDPWMON                 7
-#define SENDPWMOFF                8
+	devpriv->dux_commands[0] = cmd_type;
 
-static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
-{
-	int result, nsent;
-
-	this_usbduxsub->dux_commands[0] = cmd_type;
-#ifdef NOISY_DUX_DEBUGBUG
-	printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
-	       this_usbduxsub->comedidev->minor);
-	for (result = 0; result < SIZEOFDUXBUFFER; result++)
-		printk(" %02x", this_usbduxsub->dux_commands[result]);
-	printk("\n");
-#endif
-	result = usb_bulk_msg(this_usbduxsub->usbdev,
-			      usb_sndbulkpipe(this_usbduxsub->usbdev,
-					      COMMAND_OUT_EP),
-			      this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
-			      &nsent, BULK_TIMEOUT);
-	if (result < 0)
-		dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
-			"could not transmit dux_command to the usb-device, "
-			"err=%d\n", this_usbduxsub->comedidev->minor, result);
-
-	return result;
+	return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1),
+			    devpriv->dux_commands, SIZEOFDUXBUFFER,
+			    &nsent, BULK_TIMEOUT);
 }
 
-static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
+static int receive_dux_commands(struct comedi_device *dev, int command)
 {
-	int result = (-EFAULT);
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	struct usbdux_private *devpriv = dev->private;
+	int ret;
 	int nrec;
 	int i;
 
 	for (i = 0; i < RETRIES; i++) {
-		result = usb_bulk_msg(this_usbduxsub->usbdev,
-				      usb_rcvbulkpipe(this_usbduxsub->usbdev,
-						      COMMAND_IN_EP),
-				      this_usbduxsub->insn_buffer, SIZEINSNBUF,
+		ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
+				      devpriv->insn_buf, SIZEINSNBUF,
 				      &nrec, BULK_TIMEOUT);
-		if (result < 0) {
-			dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
-				"insn: USB error %d while receiving DUX command"
-				"\n", this_usbduxsub->comedidev->minor, result);
-			return result;
-		}
-		if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command)
-			return result;
+		if (ret < 0)
+			return ret;
+		if (le16_to_cpu(devpriv->insn_buf[0]) == command)
+			return ret;
 	}
-	/* this is only reached if the data has been requested a couple of
-	 * times */
-	dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
-		"wrong data returned from firmware: want cmd %d, got cmd %d.\n",
-		this_usbduxsub->comedidev->minor, command,
-		le16_to_cpu(this_usbduxsub->insn_buffer[0]));
+	/* command not received */
 	return -EFAULT;
 }
 
 static int usbdux_ai_inttrig(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned int trignum)
+			     struct comedi_subdevice *s,
+			     unsigned int trignum)
 {
-	int ret;
-	struct usbduxsub *this_usbduxsub = dev->private;
-	if (!this_usbduxsub)
-		return -EFAULT;
+	struct usbdux_private *devpriv = dev->private;
+	int ret = -EINVAL;
 
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: usbdux_ai_inttrig\n", dev->minor);
-
-	if (trignum != 0) {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: usbdux_ai_inttrig: invalid trignum\n",
-			dev->minor);
-		up(&this_usbduxsub->sem);
-		return -EINVAL;
-	}
-	if (!(this_usbduxsub->ai_cmd_running)) {
-		this_usbduxsub->ai_cmd_running = 1;
-		ret = usbduxsub_submit_inurbs(this_usbduxsub);
+	down(&devpriv->sem);
+
+	if (trignum != 0)
+		goto ai_trig_exit;
+
+	if (!devpriv->ai_cmd_running) {
+		devpriv->ai_cmd_running = 1;
+		ret = usbdux_submit_urbs(dev, devpriv->ai_urbs,
+					 devpriv->n_ai_urbs, 1);
 		if (ret < 0) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi%d: usbdux_ai_inttrig: "
-				"urbSubmit: err=%d\n", dev->minor, ret);
-			this_usbduxsub->ai_cmd_running = 0;
-			up(&this_usbduxsub->sem);
-			return ret;
+			devpriv->ai_cmd_running = 0;
+			goto ai_trig_exit;
 		}
 		s->async->inttrig = NULL;
 	} else {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: ai_inttrig but acqu is already running\n",
-			dev->minor);
+		ret = -EBUSY;
 	}
-	up(&this_usbduxsub->sem);
-	return 1;
+
+ai_trig_exit:
+	up(&devpriv->sem);
+	return ret;
 }
 
 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct usbdux_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
-	unsigned int chan, range;
-	int i, ret;
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int result;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
-
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: usbdux_ai_cmd\n", dev->minor);
+	int len = cmd->chanlist_len;
+	int ret = -EBUSY;
+	int i;
 
 	/* block other CPUs from starting an ai_cmd */
-	down(&this_usbduxsub->sem);
+	down(&devpriv->sem);
+
+	if (devpriv->ai_cmd_running)
+		goto ai_cmd_exit;
 
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
-	if (this_usbduxsub->ai_cmd_running) {
-		dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
-			"ai_cmd not possible. Another ai_cmd is running.\n",
-			dev->minor);
-		up(&this_usbduxsub->sem);
-		return -EBUSY;
-	}
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
 
-	this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
-	for (i = 0; i < cmd->chanlist_len; ++i) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		range = CR_RANGE(cmd->chanlist[i]);
-		if (i >= NUMCHANNELS) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi%d: channel list too long\n",
-				dev->minor);
-			break;
-		}
-		this_usbduxsub->dux_commands[i + 2] =
-		    create_adc_command(chan, range);
-	}
-
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi %d: sending commands to the usb device: size=%u\n",
-		dev->minor, NUMCHANNELS);
+	devpriv->dux_commands[1] = len;
+	for (i = 0; i < len; ++i) {
+		unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+		unsigned int range = CR_RANGE(cmd->chanlist[i]);
 
-	result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
-	if (result < 0) {
-		up(&this_usbduxsub->sem);
-		return result;
+		devpriv->dux_commands[i + 2] = create_adc_command(chan, range);
 	}
 
-	if (this_usbduxsub->high_speed) {
+	ret = send_dux_commands(dev, USBDUX_CMD_MULT_AI);
+	if (ret < 0)
+		goto ai_cmd_exit;
+
+	if (devpriv->high_speed) {
 		/*
 		 * every channel gets a time window of 125us. Thus, if we
 		 * sample all 8 channels we need 1ms. If we sample only one
 		 * channel we need only 125us
 		 */
-		this_usbduxsub->ai_interval = 1;
+		devpriv->ai_interval = 1;
 		/* find a power of 2 for the interval */
-		while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
-			this_usbduxsub->ai_interval =
-			    (this_usbduxsub->ai_interval) * 2;
-		}
-		this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
-							  (this_usbduxsub->
-							   ai_interval));
+		while (devpriv->ai_interval < len)
+			devpriv->ai_interval *= 2;
+
+		devpriv->ai_timer = cmd->scan_begin_arg /
+				    (125000 * devpriv->ai_interval);
 	} else {
 		/* interval always 1ms */
-		this_usbduxsub->ai_interval = 1;
-		this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
+		devpriv->ai_interval = 1;
+		devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
 	}
-	if (this_usbduxsub->ai_timer < 1) {
-		dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
-			"timer=%d, scan_begin_arg=%d. "
-			"Not properly tested by cmdtest?\n", dev->minor,
-			this_usbduxsub->ai_timer, cmd->scan_begin_arg);
-		up(&this_usbduxsub->sem);
-		return -EINVAL;
+	if (devpriv->ai_timer < 1) {
+		ret = -EINVAL;
+		goto ai_cmd_exit;
 	}
-	this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+
+	devpriv->ai_counter = devpriv->ai_timer;
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* data arrives as one packet */
-		this_usbduxsub->ai_sample_count = cmd->stop_arg;
-		this_usbduxsub->ai_continous = 0;
+		devpriv->ai_sample_count = cmd->stop_arg;
+		devpriv->ai_continous = 0;
 	} else {
 		/* continous acquisition */
-		this_usbduxsub->ai_continous = 1;
-		this_usbduxsub->ai_sample_count = 0;
+		devpriv->ai_continous = 1;
+		devpriv->ai_sample_count = 0;
 	}
 
 	if (cmd->start_src == TRIG_NOW) {
 		/* enable this acquisition operation */
-		this_usbduxsub->ai_cmd_running = 1;
-		ret = usbduxsub_submit_inurbs(this_usbduxsub);
+		devpriv->ai_cmd_running = 1;
+		ret = usbdux_submit_urbs(dev, devpriv->ai_urbs,
+					 devpriv->n_ai_urbs, 1);
 		if (ret < 0) {
-			this_usbduxsub->ai_cmd_running = 0;
+			devpriv->ai_cmd_running = 0;
 			/* fixme: unlink here?? */
-			up(&this_usbduxsub->sem);
-			return ret;
+			goto ai_cmd_exit;
 		}
 		s->async->inttrig = NULL;
 	} else {
@@ -1179,202 +801,156 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/* wait for an internal signal */
 		s->async->inttrig = usbdux_ai_inttrig;
 	}
-	up(&this_usbduxsub->sem);
-	return 0;
+
+ai_cmd_exit:
+	up(&devpriv->sem);
+
+	return ret;
 }
 
 /* Mode 0 is used to get a single conversion on demand */
 static int usbdux_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int val;
+	int ret = -EBUSY;
 	int i;
-	unsigned int one = 0;
-	int chan, range;
-	int err;
-	struct usbduxsub *this_usbduxsub = dev->private;
-
-	if (!this_usbduxsub)
-		return 0;
 
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
-		dev->minor, insn->n, insn->subdev);
+	down(&devpriv->sem);
 
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
-	if (this_usbduxsub->ai_cmd_running) {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: ai_insn_read not possible. "
-			"Async Command is running.\n", dev->minor);
-		up(&this_usbduxsub->sem);
-		return 0;
-	}
+	if (devpriv->ai_cmd_running)
+		goto ai_read_exit;
 
-	/* sample one channel */
-	chan = CR_CHAN(insn->chanspec);
-	range = CR_RANGE(insn->chanspec);
 	/* set command for the first channel */
-	this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
+	devpriv->dux_commands[1] = create_adc_command(chan, range);
 
 	/* adc commands */
-	err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
-	if (err < 0) {
-		up(&this_usbduxsub->sem);
-		return err;
-	}
+	ret = send_dux_commands(dev, USBDUX_CMD_SINGLE_AI);
+	if (ret < 0)
+		goto ai_read_exit;
 
 	for (i = 0; i < insn->n; i++) {
-		err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
-		if (err < 0) {
-			up(&this_usbduxsub->sem);
-			return 0;
-		}
-		one = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
-		if (CR_RANGE(insn->chanspec) <= 1)
-			one = one ^ 0x800;
+		ret = receive_dux_commands(dev, USBDUX_CMD_SINGLE_AI);
+		if (ret < 0)
+			goto ai_read_exit;
+
+		val = le16_to_cpu(devpriv->insn_buf[1]);
 
-		data[i] = one;
+		/* bipolar data is two's-complement */
+		if (comedi_range_is_bipolar(s, range))
+			val ^= ((s->maxdata + 1) >> 1);
+
+		data[i] = val;
 	}
-	up(&this_usbduxsub->sem);
-	return i;
-}
 
-/************************************/
-/* analog out */
+ai_read_exit:
+	up(&devpriv->sem);
+
+	return ret ? ret : insn->n;
+}
 
 static int usbdux_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
 	int i;
-	int chan = CR_CHAN(insn->chanspec);
-	struct usbduxsub *this_usbduxsub = dev->private;
 
-	if (!this_usbduxsub)
-		return -EFAULT;
-
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
+	down(&devpriv->sem);
 	for (i = 0; i < insn->n; i++)
-		data[i] = this_usbduxsub->out_buffer[chan];
+		data[i] = devpriv->ao_readback[chan];
+	up(&devpriv->sem);
 
-	up(&this_usbduxsub->sem);
-	return i;
+	return insn->n;
 }
 
 static int usbdux_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	int i, err;
-	int chan = CR_CHAN(insn->chanspec);
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val = devpriv->ao_readback[chan];
+	int16_t *p = (int16_t *)&devpriv->dux_commands[2];
+	int ret = -EBUSY;
+	int i;
 
-	if (!this_usbduxsub)
-		return -EFAULT;
+	down(&devpriv->sem);
 
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: ao_insn_write\n", dev->minor);
+	if (devpriv->ao_cmd_running)
+		goto ao_write_exit;
 
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
-	if (this_usbduxsub->ao_cmd_running) {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: ao_insn_write: "
-			"ERROR: asynchronous ao_cmd is running\n", dev->minor);
-		up(&this_usbduxsub->sem);
-		return 0;
-	}
+	/* number of channels: 1 */
+	devpriv->dux_commands[1] = 1;
+	/* channel number */
+	devpriv->dux_commands[4] = chan << 6;
 
 	for (i = 0; i < insn->n; i++) {
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
-			dev->minor, chan, i, data[i]);
+		val = data[i];
 
-		/* number of channels: 1 */
-		this_usbduxsub->dux_commands[1] = 1;
 		/* one 16 bit value */
-		*((int16_t *) (this_usbduxsub->dux_commands + 2)) =
-		    cpu_to_le16(data[i]);
-		this_usbduxsub->out_buffer[chan] = data[i];
-		/* channel number */
-		this_usbduxsub->dux_commands[4] = (chan << 6);
-		err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
-		if (err < 0) {
-			up(&this_usbduxsub->sem);
-			return err;
-		}
+		*p = cpu_to_le16(val);
+
+		ret = send_dux_commands(dev, USBDUX_CMD_AO);
+		if (ret < 0)
+			goto ao_write_exit;
 	}
-	up(&this_usbduxsub->sem);
+	devpriv->ao_readback[chan] = val;
+
+ao_write_exit:
+	up(&devpriv->sem);
 
-	return i;
+	return ret ? ret : insn->n;
 }
 
 static int usbdux_ao_inttrig(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned int trignum)
+			     struct comedi_subdevice *s,
+			     unsigned int trignum)
 {
-	int ret;
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *devpriv = dev->private;
+	int ret = -EINVAL;
 
-	if (!this_usbduxsub)
-		return -EFAULT;
+	down(&devpriv->sem);
 
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
-	if (trignum != 0) {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: usbdux_ao_inttrig: invalid trignum\n",
-			dev->minor);
-		up(&this_usbduxsub->sem);
-		return -EINVAL;
-	}
-	if (!(this_usbduxsub->ao_cmd_running)) {
-		this_usbduxsub->ao_cmd_running = 1;
-		ret = usbduxsub_submit_outurbs(this_usbduxsub);
+	if (trignum != 0)
+		goto ao_trig_exit;
+
+	if (!devpriv->ao_cmd_running) {
+		devpriv->ao_cmd_running = 1;
+		ret = usbdux_submit_urbs(dev, devpriv->ao_urbs,
+					 devpriv->n_ao_urbs, 0);
 		if (ret < 0) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi%d: usbdux_ao_inttrig: submitURB: "
-				"err=%d\n", dev->minor, ret);
-			this_usbduxsub->ao_cmd_running = 0;
-			up(&this_usbduxsub->sem);
-			return ret;
+			devpriv->ao_cmd_running = 0;
+			goto ao_trig_exit;
 		}
 		s->async->inttrig = NULL;
 	} else {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: ao_inttrig but acqu is already running.\n",
-			dev->minor);
+		ret = -EBUSY;
 	}
-	up(&this_usbduxsub->sem);
-	return 1;
+
+ao_trig_exit:
+	up(&devpriv->sem);
+	return ret;
 }
 
 static int usbdux_ao_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *this_usbduxsub = dev->private;
 	int err = 0;
 	unsigned int flags;
 
 	if (!this_usbduxsub)
 		return -EFAULT;
 
-	if (!(this_usbduxsub->probed))
-		return -ENODEV;
-
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -1451,99 +1027,72 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 
 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct usbdux_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
-	unsigned int chan, gain;
-	int i, ret;
-	struct usbduxsub *this_usbduxsub = dev->private;
+	int ret = -EBUSY;
+	int i;
 
-	if (!this_usbduxsub)
-		return -EFAULT;
+	down(&devpriv->sem);
 
-	down(&this_usbduxsub->sem);
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: %s\n", dev->minor, __func__);
+	if (devpriv->ao_cmd_running)
+		goto ao_cmd_exit;
 
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
+
 	for (i = 0; i < cmd->chanlist_len; ++i) {
-		chan = CR_CHAN(cmd->chanlist[i]);
-		gain = CR_RANGE(cmd->chanlist[i]);
-		if (i >= NUMOUTCHANNELS) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi%d: %s: channel list too long\n",
-				dev->minor, __func__);
-			break;
-		}
-		this_usbduxsub->dac_commands[i] = (chan << 6);
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: dac command for ch %d is %x\n",
-			dev->minor, i, this_usbduxsub->dac_commands[i]);
+		unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+
+		devpriv->ao_chanlist[i] = chan << 6;
 	}
 
 	/* we count in steps of 1ms (125us) */
 	/* 125us mode not used yet */
-	if (0) {		/* (this_usbduxsub->high_speed) */
+	if (0) {		/* (devpriv->high_speed) */
 		/* 125us */
 		/* timing of the conversion itself: every 125 us */
-		this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
+		devpriv->ao_timer = cmd->convert_arg / 125000;
 	} else {
 		/* 1ms */
 		/* timing of the scan: we get all channels at once */
-		this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
-			"convert_src=%d, convert_arg=%d\n", dev->minor,
-			cmd->scan_begin_src, cmd->scan_begin_arg,
-			cmd->convert_src, cmd->convert_arg);
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: ao_timer=%d (ms)\n",
-			dev->minor, this_usbduxsub->ao_timer);
-		if (this_usbduxsub->ao_timer < 1) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi%d: usbdux: ao_timer=%d, "
-				"scan_begin_arg=%d. "
-				"Not properly tested by cmdtest?\n",
-				dev->minor, this_usbduxsub->ao_timer,
-				cmd->scan_begin_arg);
-			up(&this_usbduxsub->sem);
-			return -EINVAL;
+		devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
+		if (devpriv->ao_timer < 1) {
+			ret = -EINVAL;
+			goto ao_cmd_exit;
 		}
 	}
-	this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+
+	devpriv->ao_counter = devpriv->ao_timer;
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* not continuous */
 		/* counter */
 		/* high speed also scans everything at once */
-		if (0) {	/* (this_usbduxsub->high_speed) */
-			this_usbduxsub->ao_sample_count =
-			    (cmd->stop_arg) * (cmd->scan_end_arg);
+		if (0) {	/* (devpriv->high_speed) */
+			devpriv->ao_sample_count = cmd->stop_arg *
+						   cmd->scan_end_arg;
 		} else {
 			/* there's no scan as the scan has been */
 			/* perf inside the FX2 */
 			/* data arrives as one packet */
-			this_usbduxsub->ao_sample_count = cmd->stop_arg;
+			devpriv->ao_sample_count = cmd->stop_arg;
 		}
-		this_usbduxsub->ao_continous = 0;
+		devpriv->ao_continous = 0;
 	} else {
 		/* continous acquisition */
-		this_usbduxsub->ao_continous = 1;
-		this_usbduxsub->ao_sample_count = 0;
+		devpriv->ao_continous = 1;
+		devpriv->ao_sample_count = 0;
 	}
 
 	if (cmd->start_src == TRIG_NOW) {
 		/* enable this acquisition operation */
-		this_usbduxsub->ao_cmd_running = 1;
-		ret = usbduxsub_submit_outurbs(this_usbduxsub);
+		devpriv->ao_cmd_running = 1;
+		ret = usbdux_submit_urbs(dev, devpriv->ao_urbs,
+					 devpriv->n_ao_urbs, 0);
 		if (ret < 0) {
-			this_usbduxsub->ao_cmd_running = 0;
+			devpriv->ao_cmd_running = 0;
 			/* fixme: unlink here?? */
-			up(&this_usbduxsub->sem);
-			return ret;
+			goto ao_cmd_exit;
 		}
 		s->async->inttrig = NULL;
 	} else {
@@ -1553,149 +1102,134 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		s->async->inttrig = usbdux_ao_inttrig;
 	}
 
-	up(&this_usbduxsub->sem);
-	return 0;
+ao_cmd_exit:
+	up(&devpriv->sem);
+
+	return ret;
 }
 
 static int usbdux_dio_insn_config(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
-	int chan = CR_CHAN(insn->chanspec);
-
-	/* The input or output configuration of each digital line is
-	 * configured by a special insn_config instruction.  chanspec
-	 * contains the channel to be changed, and data[0] contains the
-	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
+	unsigned int mask = 1 << CR_CHAN(insn->chanspec);
 
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_OUTPUT:
-		s->io_bits |= 1 << chan;	/* 1 means Out */
+		s->io_bits |= mask;
 		break;
 	case INSN_CONFIG_DIO_INPUT:
-		s->io_bits &= ~(1 << chan);
+		s->io_bits &= ~mask;
 		break;
 	case INSN_CONFIG_DIO_QUERY:
-		data[1] =
-		    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+		data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
 		break;
 	default:
 		return -EINVAL;
 		break;
 	}
-	/* we don't tell the firmware here as it would take 8 frames */
-	/* to submit the information. We do it in the insn_bits. */
+
+	/*
+	 * We don't tell the firmware here as it would take 8 frames
+	 * to submit the information. We do it in the insn_bits.
+	 */
 	return insn->n;
 }
 
 static int usbdux_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
 
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int err;
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
+	int ret;
 
-	if (!this_usbduxsub)
-		return -EFAULT;
+	down(&devpriv->sem);
 
-	down(&this_usbduxsub->sem);
+	s->state &= ~mask;
+	s->state |= (bits & mask);
 
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
+	devpriv->dux_commands[1] = s->io_bits;
+	devpriv->dux_commands[2] = s->state;
 
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit. */
-	s->state &= ~data[0];
-	s->state |= data[0] & data[1];
-	this_usbduxsub->dux_commands[1] = s->io_bits;
-	this_usbduxsub->dux_commands[2] = s->state;
-
-	/* This command also tells the firmware to return */
-	/* the digital input lines */
-	err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
-	if (err < 0) {
-		up(&this_usbduxsub->sem);
-		return err;
-	}
-	err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
-	if (err < 0) {
-		up(&this_usbduxsub->sem);
-		return err;
-	}
+	/*
+	 * This command also tells the firmware to return
+	 * the digital input lines.
+	 */
+	ret = send_dux_commands(dev, USBDUX_CMD_DIO_BITS);
+	if (ret < 0)
+		goto dio_exit;
+	ret = receive_dux_commands(dev, USBDUX_CMD_DIO_BITS);
+	if (ret < 0)
+		goto dio_exit;
 
-	data[1] = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
-	up(&this_usbduxsub->sem);
-	return insn->n;
+	data[1] = le16_to_cpu(devpriv->insn_buf[1]);
+
+dio_exit:
+	up(&devpriv->sem);
+
+	return ret ? ret : insn->n;
 }
 
-/* reads the 4 counters, only two are used just now */
 static int usbdux_counter_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int chan = insn->chanspec;
-	int err;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int ret = 0;
+	int i;
 
-	down(&this_usbduxsub->sem);
+	down(&devpriv->sem);
 
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
+	for (i = 0; i < insn->n; i++) {
+		ret = send_dux_commands(dev, USBDUX_CMD_TIMER_RD);
+		if (ret < 0)
+			goto counter_read_exit;
+		ret = receive_dux_commands(dev, USBDUX_CMD_TIMER_RD);
+		if (ret < 0)
+			goto counter_read_exit;
 
-	err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
-	if (err < 0) {
-		up(&this_usbduxsub->sem);
-		return err;
+		data[i] = le16_to_cpu(devpriv->insn_buf[chan + 1]);
 	}
 
-	err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
-	if (err < 0) {
-		up(&this_usbduxsub->sem);
-		return err;
-	}
+counter_read_exit:
+	up(&devpriv->sem);
 
-	data[0] = le16_to_cpu(this_usbduxsub->insn_buffer[chan + 1]);
-	up(&this_usbduxsub->sem);
-	return 1;
+	return ret ? ret : insn->n;
 }
 
 static int usbdux_counter_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int err;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int16_t *p = (int16_t *)&devpriv->dux_commands[2];
+	int ret = 0;
+	int i;
 
-	down(&this_usbduxsub->sem);
+	down(&devpriv->sem);
 
-	if (!(this_usbduxsub->probed)) {
-		up(&this_usbduxsub->sem);
-		return -ENODEV;
-	}
+	devpriv->dux_commands[1] = chan;
 
-	this_usbduxsub->dux_commands[1] = insn->chanspec;
-	*((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
+	for (i = 0; i < insn->n; i++) {
+		*p = cpu_to_le16(data[i]);
 
-	err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND);
-	if (err < 0) {
-		up(&this_usbduxsub->sem);
-		return err;
+		ret = send_dux_commands(dev, USBDUX_CMD_TIMER_WR);
+		if (ret < 0)
+			break;
 	}
 
-	up(&this_usbduxsub->sem);
+	up(&devpriv->sem);
 
-	return 1;
+	return ret ? ret : insn->n;
 }
 
 static int usbdux_counter_config(struct comedi_device *dev,
@@ -1706,73 +1240,43 @@ static int usbdux_counter_config(struct comedi_device *dev,
 	return 2;
 }
 
-/***********************************/
-/* PWM */
-
-static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp)
+static void usbduxsub_unlink_pwm_urbs(struct comedi_device *dev)
 {
-	int err = 0;
+	struct usbdux_private *devpriv = dev->private;
 
-	if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) {
-		if (usbduxsub_tmp->urb_pwm)
-			usb_kill_urb(usbduxsub_tmp->urb_pwm);
-		dev_dbg(&usbduxsub_tmp->interface->dev,
-			"comedi: unlinked PwmURB: res=%d\n", err);
-	}
-	return err;
+	usb_kill_urb(devpriv->pwm_urb);
 }
 
-/* This cancels a running acquisition operation
- * in any context.
- */
-static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+static void usbdux_pwm_stop(struct comedi_device *dev, int do_unlink)
 {
-	int ret = 0;
+	struct usbdux_private *devpriv = dev->private;
 
-	if (!this_usbduxsub)
-		return -EFAULT;
-
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
 	if (do_unlink)
-		ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub);
+		usbduxsub_unlink_pwm_urbs(dev);
 
-	this_usbduxsub->pwm_cmd_running = 0;
-
-	return ret;
+	devpriv->pwm_cmd_running = 0;
 }
 
-/* force unlink - is called by comedi */
 static int usbdux_pwm_cancel(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int res = 0;
+	struct usbdux_private *devpriv = dev->private;
+	int ret;
 
+	down(&devpriv->sem);
 	/* unlink only if it is really running */
-	res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
-
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi %d: sending pwm off command to the usb device.\n",
-		dev->minor);
+	usbdux_pwm_stop(dev, devpriv->pwm_cmd_running);
+	ret = send_dux_commands(dev, USBDUX_CMD_PWM_OFF);
+	up(&devpriv->sem);
 
-	return send_dux_commands(this_usbduxsub, SENDPWMOFF);
+	return ret;
 }
 
 static void usbduxsub_pwm_irq(struct urb *urb)
 {
+	struct comedi_device *dev = urb->context;
+	struct usbdux_private *devpriv = dev->private;
 	int ret;
-	struct usbduxsub *this_usbduxsub;
-	struct comedi_device *this_comedidev;
-	struct comedi_subdevice *s;
-
-	/* printk(KERN_DEBUG "PWM: IRQ\n"); */
-
-	/* the context variable points to the subdevice */
-	this_comedidev = urb->context;
-	/* the private structure of the subdevice is struct usbduxsub */
-	this_usbduxsub = this_comedidev->private;
-
-	s = &this_comedidev->subdevices[SUBDEV_DA];
 
 	switch (urb->status) {
 	case 0:
@@ -1787,220 +1291,171 @@ static void usbduxsub_pwm_irq(struct urb *urb)
 		 * after an unlink command, unplug, ... etc
 		 * no unlink needed here. Already shutting down.
 		 */
-		if (this_usbduxsub->pwm_cmd_running)
-			usbdux_pwm_stop(this_usbduxsub, 0);
+		if (devpriv->pwm_cmd_running)
+			usbdux_pwm_stop(dev, 0);
 
 		return;
 
 	default:
 		/* a real error */
-		if (this_usbduxsub->pwm_cmd_running) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi_: Non-zero urb status received in "
-				"pwm intr context: %d\n", urb->status);
-			usbdux_pwm_stop(this_usbduxsub, 0);
+		if (devpriv->pwm_cmd_running) {
+			dev_err(dev->class_dev,
+				"Non-zero urb status received in pwm intr context: %d\n",
+				urb->status);
+			usbdux_pwm_stop(dev, 0);
 		}
 		return;
 	}
 
 	/* are we actually running? */
-	if (!(this_usbduxsub->pwm_cmd_running))
+	if (!devpriv->pwm_cmd_running)
 		return;
 
-	urb->transfer_buffer_length = this_usbduxsub->size_pwm_buf;
-	urb->dev = this_usbduxsub->usbdev;
+	urb->transfer_buffer_length = devpriv->pwm_buf_sz;
+	urb->dev = comedi_to_usb_dev(dev);
 	urb->status = 0;
-	if (this_usbduxsub->pwm_cmd_running) {
+	if (devpriv->pwm_cmd_running) {
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		if (ret < 0) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi_: pwm urb resubm failed in int-cont. "
-				"ret=%d", ret);
+			dev_err(dev->class_dev,
+				"pwm urb resubm failed in int-cont. ret=%d",
+				ret);
 			if (ret == EL2NSYNC)
-				dev_err(&this_usbduxsub->interface->dev,
-					"buggy USB host controller or bug in "
-					"IRQ handling!\n");
+				dev_err(dev->class_dev,
+					"buggy USB host controller or bug in IRQ handling!\n");
 
 			/* don't do an unlink here */
-			usbdux_pwm_stop(this_usbduxsub, 0);
+			usbdux_pwm_stop(dev, 0);
 		}
 	}
 }
 
-static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev)
 {
-	int err_flag;
-
-	if (!usbduxsub)
-		return -EFAULT;
-
-	dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	struct usbdux_private *devpriv = dev->private;
+	struct urb *urb = devpriv->pwm_urb;
 
 	/* in case of a resubmission after an unlink... */
-	usb_fill_bulk_urb(usbduxsub->urb_pwm,
-			  usbduxsub->usbdev,
-			  usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
-			  usbduxsub->urb_pwm->transfer_buffer,
-			  usbduxsub->size_pwm_buf, usbduxsub_pwm_irq,
-			  usbduxsub->comedidev);
-
-	err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC);
-	if (err_flag) {
-		dev_err(&usbduxsub->interface->dev,
-			"comedi_: usbdux: pwm: usb_submit_urb error %d\n",
-			err_flag);
-		return err_flag;
-	}
-	return 0;
+	usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4),
+			  urb->transfer_buffer,
+			  devpriv->pwm_buf_sz,
+			  usbduxsub_pwm_irq,
+			  dev);
+
+	return usb_submit_urb(urb, GFP_ATOMIC);
 }
 
 static int usbdux_pwm_period(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned int period)
+			     struct comedi_subdevice *s,
+			     unsigned int period)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *devpriv = dev->private;
 	int fx2delay = 255;
 
 	if (period < MIN_PWM_PERIOD) {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi%d: illegal period setting for pwm.\n",
-			dev->minor);
 		return -EAGAIN;
 	} else {
-		fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
-		if (fx2delay > 255) {
-			dev_err(&this_usbduxsub->interface->dev,
-				"comedi%d: period %d for pwm is too low.\n",
-				dev->minor, period);
+		fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
+		if (fx2delay > 255)
 			return -EAGAIN;
-		}
 	}
-	this_usbduxsub->pwn_delay = fx2delay;
-	this_usbduxsub->pwm_period = period;
-	dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
-		__func__, period, fx2delay);
+	devpriv->pwm_delay = fx2delay;
+	devpriv->pwm_period = period;
+
 	return 0;
 }
 
-/* is called from insn so there's no need to do all the sanity checks */
 static int usbdux_pwm_start(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	int ret, i;
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *devpriv = dev->private;
+	int ret = 0;
 
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
-		dev->minor, __func__);
+	down(&devpriv->sem);
 
-	if (this_usbduxsub->pwm_cmd_running) {
-		/* already running */
-		return 0;
-	}
+	if (devpriv->pwm_cmd_running)
+		goto pwm_start_exit;
 
-	this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay);
-	ret = send_dux_commands(this_usbduxsub, SENDPWMON);
+	devpriv->dux_commands[1] = devpriv->pwm_delay;
+	ret = send_dux_commands(dev, USBDUX_CMD_PWM_ON);
 	if (ret < 0)
-		return ret;
+		goto pwm_start_exit;
 
 	/* initialise the buffer */
-	for (i = 0; i < this_usbduxsub->size_pwm_buf; i++)
-		((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0;
+	memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
 
-	this_usbduxsub->pwm_cmd_running = 1;
-	ret = usbduxsub_submit_pwm_urbs(this_usbduxsub);
-	if (ret < 0) {
-		this_usbduxsub->pwm_cmd_running = 0;
-		return ret;
-	}
-	return 0;
+	devpriv->pwm_cmd_running = 1;
+	ret = usbduxsub_submit_pwm_urbs(dev);
+	if (ret < 0)
+		devpriv->pwm_cmd_running = 0;
+
+pwm_start_exit:
+	up(&devpriv->sem);
+
+	return ret;
 }
 
-/* generates the bit pattern for PWM with the optional sign bit */
-static int usbdux_pwm_pattern(struct comedi_device *dev,
-			      struct comedi_subdevice *s, int channel,
-			      unsigned int value, unsigned int sign)
+static void usbdux_pwm_pattern(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       unsigned int chan,
+			       unsigned int value,
+			       unsigned int sign)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
-	int i, szbuf;
-	char *p_buf;
-	char pwm_mask;
-	char sgn_mask;
-	char c;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
+	struct usbdux_private *devpriv = dev->private;
+	char pwm_mask = (1 << chan);	/* DIO bit for the PWM data */
+	char sgn_mask = (16 << chan);	/* DIO bit for the sign */
+	char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
+	int szbuf = devpriv->pwm_buf_sz;
+	int i;
 
-	/* this is the DIO bit which carries the PWM data */
-	pwm_mask = (1 << channel);
-	/* this is the DIO bit which carries the optional direction bit */
-	sgn_mask = (16 << channel);
-	/* this is the buffer which will be filled with the with bit */
-	/* pattern for one period */
-	szbuf = this_usbduxsub->size_pwm_buf;
-	p_buf = (char *)(this_usbduxsub->urb_pwm->transfer_buffer);
 	for (i = 0; i < szbuf; i++) {
-		c = *p_buf;
-		/* reset bits */
-		c = c & (~pwm_mask);
-		/* set the bit as long as the index is lower than the value */
+		char c = *buf;
+
+		c &= ~pwm_mask;
 		if (i < value)
-			c = c | pwm_mask;
-		/* set the optional sign bit for a relay */
-		if (!sign) {
-			/* positive value */
-			c = c & (~sgn_mask);
-		} else {
-			/* negative value */
-			c = c | sgn_mask;
-		}
-		*(p_buf++) = c;
+			c |= pwm_mask;
+		if (!sign)
+			c &= ~sgn_mask;
+		else
+			c |= sgn_mask;
+		*buf++ = c;
 	}
-	return 1;
 }
 
 static int usbdux_pwm_write(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
-
-	if (!this_usbduxsub)
-		return -EFAULT;
+	unsigned int chan = CR_CHAN(insn->chanspec);
 
-	if ((insn->n) != 1) {
-		/*
-		 * doesn't make sense to have more than one value here because
-		 * it would just overwrite the PWM buffer a couple of times
-		 */
+	/*
+	 * It doesn't make sense to support more than one value here
+	 * because it would just overwrite the PWM buffer.
+	 */
+	if (insn->n != 1)
 		return -EINVAL;
-	}
 
 	/*
-	 * the sign is set via a special INSN only, this gives us 8 bits for
-	 * normal operation
-	 * relay sign 0 by default
+	 * The sign is set via a special INSN only, this gives us 8 bits
+	 * for normal operation, sign is 0 by default.
 	 */
-	return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0);
-}
+	usbdux_pwm_pattern(dev, s, chan, data[0], 0);
 
-static int usbdux_pwm_read(struct comedi_device *x1,
-			   struct comedi_subdevice *x2, struct comedi_insn *x3,
-			   unsigned int *x4)
-{
-	/* not needed */
-	return -EINVAL;
-};
+	return insn->n;
+}
 
-/* switches on/off PWM */
 static int usbdux_pwm_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
+			     struct comedi_insn *insn,
+			     unsigned int *data)
 {
-	struct usbduxsub *this_usbduxsub = dev->private;
+	struct usbdux_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+
 	switch (data[0]) {
 	case INSN_CONFIG_ARM:
-		/* switch it on */
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: %s: pwm on\n", dev->minor, __func__);
 		/*
 		 * if not zero the PWM is limited to a certain time which is
 		 * not supported here
@@ -2009,33 +1464,22 @@ static int usbdux_pwm_config(struct comedi_device *dev,
 			return -EINVAL;
 		return usbdux_pwm_start(dev, s);
 	case INSN_CONFIG_DISARM:
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: %s: pwm off\n", dev->minor, __func__);
 		return usbdux_pwm_cancel(dev, s);
 	case INSN_CONFIG_GET_PWM_STATUS:
-		/*
-		 * to check if the USB transmission has failed or in case PWM
-		 * was limited to n cycles to check if it has terminated
-		 */
-		data[1] = this_usbduxsub->pwm_cmd_running;
+		data[1] = devpriv->pwm_cmd_running;
 		return 0;
 	case INSN_CONFIG_PWM_SET_PERIOD:
-		dev_dbg(&this_usbduxsub->interface->dev,
-			"comedi%d: %s: setting period\n", dev->minor, __func__);
 		return usbdux_pwm_period(dev, s, data[1]);
 	case INSN_CONFIG_PWM_GET_PERIOD:
-		data[1] = this_usbduxsub->pwm_period;
+		data[1] = devpriv->pwm_period;
 		return 0;
 	case INSN_CONFIG_PWM_SET_H_BRIDGE:
-		/* value in the first byte and the sign in the second for a
-		   relay */
-		return usbdux_pwm_pattern(dev, s,
-					  /* the channel number */
-					  CR_CHAN(insn->chanspec),
-					  /* actual PWM data */
-					  data[1],
-					  /* just a sign */
-					  (data[2] != 0));
+		/*
+		 * data[1] = value
+		 * data[2] = sign (for a relay)
+		 */
+		usbdux_pwm_pattern(dev, s, chan, data[1], (data[2] != 0));
+		return 0;
 	case INSN_CONFIG_PWM_GET_H_BRIDGE:
 		/* values are not kept in this driver, nothing to return here */
 		return -EINVAL;
@@ -2043,253 +1487,331 @@ static int usbdux_pwm_config(struct comedi_device *dev,
 	return -EINVAL;
 }
 
-/* end of PWM */
-/*****************************************************************/
-
-static void tidy_up(struct usbduxsub *usbduxsub_tmp)
+static int usbdux_firmware_upload(struct comedi_device *dev,
+				  const u8 *data, size_t size,
+				  unsigned long context)
 {
-	int i;
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	uint8_t *buf;
+	uint8_t *tmp;
+	int ret;
 
-	if (!usbduxsub_tmp)
-		return;
-	dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
+	if (!data)
+		return 0;
 
-	/* shows the usb subsystem that the driver is down */
-	if (usbduxsub_tmp->interface)
-		usb_set_intfdata(usbduxsub_tmp->interface, NULL);
+	if (size > USBDUX_FIRMWARE_MAX_LEN) {
+		dev_err(dev->class_dev,
+			"usbdux firmware binary it too large for FX2.\n");
+		return -ENOMEM;
+	}
 
-	usbduxsub_tmp->probed = 0;
+	/* we generate a local buffer for the firmware */
+	buf = kmemdup(data, size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
-	if (usbduxsub_tmp->urb_in) {
-		if (usbduxsub_tmp->ai_cmd_running) {
-			usbduxsub_tmp->ai_cmd_running = 0;
-			usbduxsub_unlink_inurbs(usbduxsub_tmp);
-		}
-		for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
-			kfree(usbduxsub_tmp->urb_in[i]->transfer_buffer);
-			usbduxsub_tmp->urb_in[i]->transfer_buffer = NULL;
-			usb_kill_urb(usbduxsub_tmp->urb_in[i]);
-			usb_free_urb(usbduxsub_tmp->urb_in[i]);
-			usbduxsub_tmp->urb_in[i] = NULL;
-		}
-		kfree(usbduxsub_tmp->urb_in);
-		usbduxsub_tmp->urb_in = NULL;
+	/* we need a malloc'ed buffer for usb_control_msg() */
+	tmp = kmalloc(1, GFP_KERNEL);
+	if (!tmp) {
+		kfree(buf);
+		return -ENOMEM;
 	}
-	if (usbduxsub_tmp->urb_out) {
-		if (usbduxsub_tmp->ao_cmd_running) {
-			usbduxsub_tmp->ao_cmd_running = 0;
-			usbduxsub_unlink_outurbs(usbduxsub_tmp);
-		}
-		for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
-			kfree(usbduxsub_tmp->urb_out[i]->transfer_buffer);
-			usbduxsub_tmp->urb_out[i]->transfer_buffer = NULL;
-			if (usbduxsub_tmp->urb_out[i]) {
-				usb_kill_urb(usbduxsub_tmp->urb_out[i]);
-				usb_free_urb(usbduxsub_tmp->urb_out[i]);
-				usbduxsub_tmp->urb_out[i] = NULL;
-			}
-		}
-		kfree(usbduxsub_tmp->urb_out);
-		usbduxsub_tmp->urb_out = NULL;
+
+	/* stop the current firmware on the device */
+	*tmp = 1;	/* 7f92 to one */
+	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+			      USBDUX_FIRMWARE_CMD,
+			      VENDOR_DIR_OUT,
+			      USBDUX_CPU_CS, 0x0000,
+			      tmp, 1,
+			      BULK_TIMEOUT);
+	if (ret < 0) {
+		dev_err(dev->class_dev, "can not stop firmware\n");
+		goto done;
 	}
-	if (usbduxsub_tmp->urb_pwm) {
-		if (usbduxsub_tmp->pwm_cmd_running) {
-			usbduxsub_tmp->pwm_cmd_running = 0;
-			usbduxsub_unlink_pwm_urbs(usbduxsub_tmp);
-		}
-		kfree(usbduxsub_tmp->urb_pwm->transfer_buffer);
-		usbduxsub_tmp->urb_pwm->transfer_buffer = NULL;
-		usb_kill_urb(usbduxsub_tmp->urb_pwm);
-		usb_free_urb(usbduxsub_tmp->urb_pwm);
-		usbduxsub_tmp->urb_pwm = NULL;
+
+	/* upload the new firmware to the device */
+	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+			      USBDUX_FIRMWARE_CMD,
+			      VENDOR_DIR_OUT,
+			      0, 0x0000,
+			      buf, size,
+			      BULK_TIMEOUT);
+	if (ret < 0) {
+		dev_err(dev->class_dev, "firmware upload failed\n");
+		goto done;
 	}
-	kfree(usbduxsub_tmp->in_buffer);
-	usbduxsub_tmp->in_buffer = NULL;
-	kfree(usbduxsub_tmp->insn_buffer);
-	usbduxsub_tmp->insn_buffer = NULL;
-	kfree(usbduxsub_tmp->out_buffer);
-	usbduxsub_tmp->out_buffer = NULL;
-	kfree(usbduxsub_tmp->dac_commands);
-	usbduxsub_tmp->dac_commands = NULL;
-	kfree(usbduxsub_tmp->dux_commands);
-	usbduxsub_tmp->dux_commands = NULL;
-	usbduxsub_tmp->ai_cmd_running = 0;
-	usbduxsub_tmp->ao_cmd_running = 0;
-	usbduxsub_tmp->pwm_cmd_running = 0;
+
+	/* start the new firmware on the device */
+	*tmp = 0;	/* 7f92 to zero */
+	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+			      USBDUX_FIRMWARE_CMD,
+			      VENDOR_DIR_OUT,
+			      USBDUX_CPU_CS, 0x0000,
+			      tmp, 1,
+			      BULK_TIMEOUT);
+	if (ret < 0)
+		dev_err(dev->class_dev, "can not start firmware\n");
+
+done:
+	kfree(tmp);
+	kfree(buf);
+	return ret;
 }
 
-static int usbdux_attach_common(struct comedi_device *dev,
-				struct usbduxsub *udev)
+static int usbdux_alloc_usb_buffers(struct comedi_device *dev)
 {
-	int ret;
-	struct comedi_subdevice *s = NULL;
-	int n_subdevs;
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	struct usbdux_private *devpriv = dev->private;
+	struct urb *urb;
+	int i;
 
-	down(&udev->sem);
-	/* pointer back to the corresponding comedi device */
-	udev->comedidev = dev;
+	devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
+	devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
+	devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
+	devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb),
+				   GFP_KERNEL);
+	devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb),
+				   GFP_KERNEL);
+	if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf ||
+	    !devpriv->ai_urbs || !devpriv->ao_urbs)
+		return -ENOMEM;
 
-	/* set number of subdevices */
-	if (udev->high_speed) {
-		/* with pwm */
-		n_subdevs = 5;
-	} else {
-		/* without pwm */
-		n_subdevs = 4;
-	}
+	for (i = 0; i < devpriv->n_ai_urbs; i++) {
+		/* one frame: 1ms */
+		urb = usb_alloc_urb(1, GFP_KERNEL);
+		if (!urb)
+			return -ENOMEM;
+		devpriv->ai_urbs[i] = urb;
+
+		urb->dev = usb;
+		urb->context = dev;
+		urb->pipe = usb_rcvisocpipe(usb, 6);
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
+		if (!urb->transfer_buffer)
+			return -ENOMEM;
 
-	ret = comedi_alloc_subdevices(dev, n_subdevs);
-	if (ret) {
-		up(&udev->sem);
-		return ret;
+		urb->complete = usbduxsub_ai_isoc_irq;
+		urb->number_of_packets = 1;
+		urb->transfer_buffer_length = SIZEINBUF;
+		urb->iso_frame_desc[0].offset = 0;
+		urb->iso_frame_desc[0].length = SIZEINBUF;
 	}
 
-	/* private structure is also simply the usb-structure */
-	dev->private = udev;
+	for (i = 0; i < devpriv->n_ao_urbs; i++) {
+		/* one frame: 1ms */
+		urb = usb_alloc_urb(1, GFP_KERNEL);
+		if (!urb)
+			return -ENOMEM;
+		devpriv->ao_urbs[i] = urb;
+
+		urb->dev = usb;
+		urb->context = dev;
+		urb->pipe = usb_sndisocpipe(usb, 2);
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
+		if (!urb->transfer_buffer)
+			return -ENOMEM;
 
-	/* the first subdevice is the A/D converter */
-	s = &dev->subdevices[SUBDEV_AD];
-	/* the URBs get the comedi subdevice */
-	/* which is responsible for reading */
-	/* this is the subdevice which reads data */
-	dev->read_subdev = s;
-	/* the subdevice receives as private structure the */
-	/* usb-structure */
-	s->private = NULL;
-	/* analog input */
-	s->type = COMEDI_SUBD_AI;
-	/* readable and ref is to ground */
-	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
-	/* 8 channels */
-	s->n_chan = 8;
-	/* length of the channellist */
-	s->len_chanlist = 8;
-	/* callback functions */
-	s->insn_read = usbdux_ai_insn_read;
-	s->do_cmdtest = usbdux_ai_cmdtest;
-	s->do_cmd = usbdux_ai_cmd;
-	s->cancel = usbdux_ai_cancel;
-	/* max value from the A/D converter (12bit) */
-	s->maxdata = 0xfff;
-	/* range table to convert to physical units */
-	s->range_table = (&range_usbdux_ai_range);
-
-	/* analog out */
-	s = &dev->subdevices[SUBDEV_DA];
-	/* analog out */
-	s->type = COMEDI_SUBD_AO;
-	/* backward pointer */
-	dev->write_subdev = s;
-	/* the subdevice receives as private structure the */
-	/* usb-structure */
-	s->private = NULL;
-	/* are writable */
-	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
-	/* 4 channels */
-	s->n_chan = 4;
-	/* length of the channellist */
-	s->len_chanlist = 4;
-	/* 12 bit resolution */
-	s->maxdata = 0x0fff;
-	/* bipolar range */
-	s->range_table = (&range_usbdux_ao_range);
-	/* callback */
-	s->do_cmdtest = usbdux_ao_cmdtest;
-	s->do_cmd = usbdux_ao_cmd;
-	s->cancel = usbdux_ao_cancel;
-	s->insn_read = usbdux_ao_insn_read;
-	s->insn_write = usbdux_ao_insn_write;
-
-	/* digital I/O */
-	s = &dev->subdevices[SUBDEV_DIO];
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->range_table = (&range_digital);
-	s->insn_bits = usbdux_dio_insn_bits;
-	s->insn_config = usbdux_dio_insn_config;
-	/* we don't use it */
-	s->private = NULL;
-
-	/* counter */
-	s = &dev->subdevices[SUBDEV_COUNTER];
-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = 4;
-	s->maxdata = 0xFFFF;
-	s->insn_read = usbdux_counter_read;
-	s->insn_write = usbdux_counter_write;
-	s->insn_config = usbdux_counter_config;
-
-	if (udev->high_speed) {
-		/* timer / pwm */
-		s = &dev->subdevices[SUBDEV_PWM];
-		s->type = COMEDI_SUBD_PWM;
-		s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
-		s->n_chan = 8;
-		/* this defines the max duty cycle resolution */
-		s->maxdata = udev->size_pwm_buf;
-		s->insn_write = usbdux_pwm_write;
-		s->insn_read = usbdux_pwm_read;
-		s->insn_config = usbdux_pwm_config;
-		usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
+		urb->complete = usbduxsub_ao_isoc_irq;
+		urb->number_of_packets = 1;
+		urb->transfer_buffer_length = SIZEOUTBUF;
+		urb->iso_frame_desc[0].offset = 0;
+		urb->iso_frame_desc[0].length = SIZEOUTBUF;
+		if (devpriv->high_speed)
+			urb->interval = 8;	/* uframes */
+		else
+			urb->interval = 1;	/* frames */
 	}
-	/* finally decide that it's attached */
-	udev->attached = 1;
 
-	up(&udev->sem);
+	/* pwm */
+	if (devpriv->pwm_buf_sz) {
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb)
+			return -ENOMEM;
+		devpriv->pwm_urb = urb;
 
-	dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
-		 dev->minor);
+		/* max bulk ep size in high speed */
+		urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz,
+					       GFP_KERNEL);
+		if (!urb->transfer_buffer)
+			return -ENOMEM;
+	}
 
 	return 0;
 }
 
+static void usbdux_free_usb_buffers(struct comedi_device *dev)
+{
+	struct usbdux_private *devpriv = dev->private;
+	struct urb *urb;
+	int i;
+
+	urb = devpriv->pwm_urb;
+	if (urb) {
+		kfree(urb->transfer_buffer);
+		usb_free_urb(urb);
+	}
+	if (devpriv->ao_urbs) {
+		for (i = 0; i < devpriv->n_ao_urbs; i++) {
+			urb = devpriv->ao_urbs[i];
+			if (urb) {
+				kfree(urb->transfer_buffer);
+				usb_free_urb(urb);
+			}
+		}
+		kfree(devpriv->ao_urbs);
+	}
+	if (devpriv->ai_urbs) {
+		for (i = 0; i < devpriv->n_ai_urbs; i++) {
+			urb = devpriv->ai_urbs[i];
+			if (urb) {
+				kfree(urb->transfer_buffer);
+				usb_free_urb(urb);
+			}
+		}
+		kfree(devpriv->ai_urbs);
+	}
+	kfree(devpriv->insn_buf);
+	kfree(devpriv->in_buf);
+	kfree(devpriv->dux_commands);
+}
+
 static int usbdux_auto_attach(struct comedi_device *dev,
 			      unsigned long context_unused)
 {
-	struct usb_interface *uinterf = comedi_to_usb_interface(dev);
-	struct usbduxsub *this_usbduxsub = usb_get_intfdata(uinterf);
-	struct usb_device *usb = usbduxsub->usbdev;
+	struct usb_interface *intf = comedi_to_usb_interface(dev);
+	struct usb_device *usb = comedi_to_usb_dev(dev);
+	struct usbdux_private *devpriv;
+	struct comedi_subdevice *s;
 	int ret;
 
-	dev->private = this_usbduxsub;	/* This is temporary... */
-	ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
-				   usbdux_firmware_upload, 0);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+	if (!devpriv)
+		return -ENOMEM;
+
+	sema_init(&devpriv->sem, 1);
+
+	usb_set_intfdata(intf, devpriv);
+
+	devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
+	if (devpriv->high_speed) {
+		devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
+		devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
+		devpriv->pwm_buf_sz = 512;
+	} else {
+		devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
+		devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
+	}
+
+	ret = usbdux_alloc_usb_buffers(dev);
+	if (ret)
+		return ret;
+
+	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
+	ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
+				3);
 	if (ret < 0) {
-		dev->private = NULL;
+		dev_err(dev->class_dev,
+			"could not set alternate setting 3 in high speed\n");
 		return ret;
 	}
 
-	dev->private = NULL;
+	ret = comedi_load_firmware(dev, &usb->dev, USBDUX_FIRMWARE,
+				   usbdux_firmware_upload, 0);
+	if (ret < 0)
+		return ret;
 
-	down(&start_stop_sem);
-	if (!this_usbduxsub || !this_usbduxsub->probed) {
-		dev_err(dev->class_dev,
-			"usbdux: error: auto_attach failed, not connected\n");
-		ret = -ENODEV;
-	} else if (this_usbduxsub->attached) {
-		dev_err(dev->class_dev,
-			"error: auto_attach failed, already attached\n");
-		ret = -ENODEV;
-	} else
-		ret = usbdux_attach_common(dev, this_usbduxsub);
-	up(&start_stop_sem);
-	return ret;
+	ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4);
+	if (ret)
+		return ret;
+
+	/* Analog Input subdevice */
+	s = &dev->subdevices[0];
+	dev->read_subdev = s;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+	s->n_chan	= 8;
+	s->maxdata	= 0x0fff;
+	s->len_chanlist	= 8;
+	s->range_table	= &range_usbdux_ai_range;
+	s->insn_read	= usbdux_ai_insn_read;
+	s->do_cmdtest	= usbdux_ai_cmdtest;
+	s->do_cmd	= usbdux_ai_cmd;
+	s->cancel	= usbdux_ai_cancel;
+
+	/* Analog Output subdevice */
+	s = &dev->subdevices[1];
+	dev->write_subdev = s;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
+	s->n_chan	= USBDUX_NUM_AO_CHAN;
+	s->maxdata	= 0x0fff;
+	s->len_chanlist	= s->n_chan;
+	s->range_table	= &range_usbdux_ao_range;
+	s->do_cmdtest	= usbdux_ao_cmdtest;
+	s->do_cmd	= usbdux_ao_cmd;
+	s->cancel	= usbdux_ao_cancel;
+	s->insn_read	= usbdux_ao_insn_read;
+	s->insn_write	= usbdux_ao_insn_write;
+
+	/* Digital I/O subdevice */
+	s = &dev->subdevices[2];
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 8;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= usbdux_dio_insn_bits;
+	s->insn_config	= usbdux_dio_insn_config;
+
+	/* Counter subdevice */
+	s = &dev->subdevices[3];
+	s->type		= COMEDI_SUBD_COUNTER;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 0xffff;
+	s->insn_read	= usbdux_counter_read;
+	s->insn_write	= usbdux_counter_write;
+	s->insn_config	= usbdux_counter_config;
+
+	if (devpriv->high_speed) {
+		/* PWM subdevice */
+		s = &dev->subdevices[4];
+		s->type		= COMEDI_SUBD_PWM;
+		s->subdev_flags	= SDF_WRITABLE | SDF_PWM_HBRIDGE;
+		s->n_chan	= 8;
+		s->maxdata	= devpriv->pwm_buf_sz;
+		s->insn_write	= usbdux_pwm_write;
+		s->insn_config	= usbdux_pwm_config;
+
+		usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
+	}
+
+	return 0;
 }
 
 static void usbdux_detach(struct comedi_device *dev)
 {
-	struct usbduxsub *usb = dev->private;
-
-	if (usb) {
-		down(&usb->sem);
-		dev->private = NULL;
-		usb->attached = 0;
-		usb->comedidev = NULL;
-		up(&usb->sem);
-	}
+	struct usb_interface *intf = comedi_to_usb_interface(dev);
+	struct usbdux_private *devpriv = dev->private;
+
+	usb_set_intfdata(intf, NULL);
+
+	if (!devpriv)
+		return;
+
+	down(&devpriv->sem);
+
+	/* force unlink all urbs */
+	usbdux_pwm_stop(dev, 1);
+	usbdux_ao_stop(dev, 1);
+	usbdux_ai_stop(dev, 1);
+
+	usbdux_free_usb_buffers(dev);
+
+	up(&devpriv->sem);
 }
 
 static struct comedi_driver usbdux_driver = {
@@ -2299,253 +1821,10 @@ static struct comedi_driver usbdux_driver = {
 	.detach		= usbdux_detach,
 };
 
-static int usbdux_usb_probe(struct usb_interface *uinterf,
+static int usbdux_usb_probe(struct usb_interface *intf,
 			    const struct usb_device_id *id)
 {
-	struct usb_device *udev = interface_to_usbdev(uinterf);
-	struct device *dev = &uinterf->dev;
-	int i;
-	int index;
-
-	dev_dbg(dev, "comedi_: usbdux_: "
-		"finding a free structure for the usb-device\n");
-
-	down(&start_stop_sem);
-	/* look for a free place in the usbdux array */
-	index = -1;
-	for (i = 0; i < NUMUSBDUX; i++) {
-		if (!(usbduxsub[i].probed)) {
-			index = i;
-			break;
-		}
-	}
-
-	/* no more space */
-	if (index == -1) {
-		dev_err(dev, "Too many usbdux-devices connected.\n");
-		up(&start_stop_sem);
-		return -EMFILE;
-	}
-	dev_dbg(dev, "comedi_: usbdux: "
-		"usbduxsub[%d] is ready to connect to comedi.\n", index);
-
-	sema_init(&(usbduxsub[index].sem), 1);
-	/* save a pointer to the usb device */
-	usbduxsub[index].usbdev = udev;
-
-	/* 2.6: save the interface itself */
-	usbduxsub[index].interface = uinterf;
-	/* get the interface number from the interface */
-	usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
-	/* hand the private data over to the usb subsystem */
-	/* will be needed for disconnect */
-	usb_set_intfdata(uinterf, &(usbduxsub[index]));
-
-	dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
-
-	/* test if it is high speed (USB 2.0) */
-	usbduxsub[index].high_speed =
-	    (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
-
-	/* create space for the commands of the DA converter */
-	usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
-	if (!usbduxsub[index].dac_commands) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	/* create space for the commands going to the usb device */
-	usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
-	if (!usbduxsub[index].dux_commands) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	/* create space for the in buffer and set it to zero */
-	usbduxsub[index].in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
-	if (!(usbduxsub[index].in_buffer)) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	/* create space of the instruction buffer */
-	usbduxsub[index].insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
-	if (!(usbduxsub[index].insn_buffer)) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	/* create space for the outbuffer */
-	usbduxsub[index].out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
-	if (!(usbduxsub[index].out_buffer)) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
-	i = usb_set_interface(usbduxsub[index].usbdev,
-			      usbduxsub[index].ifnum, 3);
-	if (i < 0) {
-		dev_err(dev, "comedi_: usbdux%d: "
-			"could not set alternate setting 3 in high speed.\n",
-			index);
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENODEV;
-	}
-	if (usbduxsub[index].high_speed)
-		usbduxsub[index].num_in_buffers = NUMOFINBUFFERSHIGH;
-	else
-		usbduxsub[index].num_in_buffers = NUMOFINBUFFERSFULL;
-
-	usbduxsub[index].urb_in =
-		kcalloc(usbduxsub[index].num_in_buffers, sizeof(struct urb *),
-			GFP_KERNEL);
-	if (!(usbduxsub[index].urb_in)) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	for (i = 0; i < usbduxsub[index].num_in_buffers; i++) {
-		/* one frame: 1ms */
-		usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL);
-		if (usbduxsub[index].urb_in[i] == NULL) {
-			dev_err(dev, "comedi_: usbdux%d: "
-				"Could not alloc. urb(%d)\n", index, i);
-			tidy_up(&(usbduxsub[index]));
-			up(&start_stop_sem);
-			return -ENOMEM;
-		}
-		usbduxsub[index].urb_in[i]->dev = usbduxsub[index].usbdev;
-		/* will be filled later with a pointer to the comedi-device */
-		/* and ONLY then the urb should be submitted */
-		usbduxsub[index].urb_in[i]->context = NULL;
-		usbduxsub[index].urb_in[i]->pipe =
-		    usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
-		usbduxsub[index].urb_in[i]->transfer_flags = URB_ISO_ASAP;
-		usbduxsub[index].urb_in[i]->transfer_buffer =
-		    kzalloc(SIZEINBUF, GFP_KERNEL);
-		if (!(usbduxsub[index].urb_in[i]->transfer_buffer)) {
-			tidy_up(&(usbduxsub[index]));
-			up(&start_stop_sem);
-			return -ENOMEM;
-		}
-		usbduxsub[index].urb_in[i]->complete = usbduxsub_ai_isoc_irq;
-		usbduxsub[index].urb_in[i]->number_of_packets = 1;
-		usbduxsub[index].urb_in[i]->transfer_buffer_length = SIZEINBUF;
-		usbduxsub[index].urb_in[i]->iso_frame_desc[0].offset = 0;
-		usbduxsub[index].urb_in[i]->iso_frame_desc[0].length = SIZEINBUF;
-	}
-
-	/* out */
-	if (usbduxsub[index].high_speed)
-		usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSHIGH;
-	else
-		usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSFULL;
-
-	usbduxsub[index].urb_out =
-		kcalloc(usbduxsub[index].num_out_buffers, sizeof(struct urb *),
-			GFP_KERNEL);
-	if (!(usbduxsub[index].urb_out)) {
-		tidy_up(&(usbduxsub[index]));
-		up(&start_stop_sem);
-		return -ENOMEM;
-	}
-	for (i = 0; i < usbduxsub[index].num_out_buffers; i++) {
-		/* one frame: 1ms */
-		usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL);
-		if (usbduxsub[index].urb_out[i] == NULL) {
-			dev_err(dev, "comedi_: usbdux%d: "
-				"Could not alloc. urb(%d)\n", index, i);
-			tidy_up(&(usbduxsub[index]));
-			up(&start_stop_sem);
-			return -ENOMEM;
-		}
-		usbduxsub[index].urb_out[i]->dev = usbduxsub[index].usbdev;
-		/* will be filled later with a pointer to the comedi-device */
-		/* and ONLY then the urb should be submitted */
-		usbduxsub[index].urb_out[i]->context = NULL;
-		usbduxsub[index].urb_out[i]->pipe =
-		    usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
-		usbduxsub[index].urb_out[i]->transfer_flags = URB_ISO_ASAP;
-		usbduxsub[index].urb_out[i]->transfer_buffer =
-		    kzalloc(SIZEOUTBUF, GFP_KERNEL);
-		if (!(usbduxsub[index].urb_out[i]->transfer_buffer)) {
-			tidy_up(&(usbduxsub[index]));
-			up(&start_stop_sem);
-			return -ENOMEM;
-		}
-		usbduxsub[index].urb_out[i]->complete = usbduxsub_ao_isoc_irq;
-		usbduxsub[index].urb_out[i]->number_of_packets = 1;
-		usbduxsub[index].urb_out[i]->transfer_buffer_length = SIZEOUTBUF;
-		usbduxsub[index].urb_out[i]->iso_frame_desc[0].offset = 0;
-		usbduxsub[index].urb_out[i]->iso_frame_desc[0].length =
-		    SIZEOUTBUF;
-		if (usbduxsub[index].high_speed) {
-			/* uframes */
-			usbduxsub[index].urb_out[i]->interval = 8;
-		} else {
-			/* frames */
-			usbduxsub[index].urb_out[i]->interval = 1;
-		}
-	}
-
-	/* pwm */
-	if (usbduxsub[index].high_speed) {
-		/* max bulk ep size in high speed */
-		usbduxsub[index].size_pwm_buf = 512;
-		usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL);
-		if (usbduxsub[index].urb_pwm == NULL) {
-			dev_err(dev, "comedi_: usbdux%d: "
-				"Could not alloc. pwm urb\n", index);
-			tidy_up(&(usbduxsub[index]));
-			up(&start_stop_sem);
-			return -ENOMEM;
-		}
-		usbduxsub[index].urb_pwm->transfer_buffer =
-		    kzalloc(usbduxsub[index].size_pwm_buf, GFP_KERNEL);
-		if (!(usbduxsub[index].urb_pwm->transfer_buffer)) {
-			tidy_up(&(usbduxsub[index]));
-			up(&start_stop_sem);
-			return -ENOMEM;
-		}
-	} else {
-		usbduxsub[index].urb_pwm = NULL;
-		usbduxsub[index].size_pwm_buf = 0;
-	}
-
-	usbduxsub[index].ai_cmd_running = 0;
-	usbduxsub[index].ao_cmd_running = 0;
-	usbduxsub[index].pwm_cmd_running = 0;
-
-	/* we've reached the bottom of the function */
-	usbduxsub[index].probed = 1;
-	up(&start_stop_sem);
-
-	return comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
-}
-
-static void usbdux_usb_disconnect(struct usb_interface *intf)
-{
-	struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	if (!usbduxsub_tmp) {
-		dev_err(&intf->dev,
-			"comedi_: disconnect called with null pointer.\n");
-		return;
-	}
-	if (usbduxsub_tmp->usbdev != udev) {
-		dev_err(&intf->dev, "comedi_: BUG! called with wrong ptr!!!\n");
-		return;
-	}
-	comedi_usb_auto_unconfig(intf);
-	down(&start_stop_sem);
-	down(&usbduxsub_tmp->sem);
-	tidy_up(usbduxsub_tmp);
-	up(&usbduxsub_tmp->sem);
-	up(&start_stop_sem);
-	dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
+	return comedi_usb_auto_config(intf, &usbdux_driver, 0);
 }
 
 static const struct usb_device_id usbdux_usb_table[] = {
@@ -2553,13 +1832,12 @@ static const struct usb_device_id usbdux_usb_table[] = {
 	{ USB_DEVICE(0x13d8, 0x0002) },
 	{ }
 };
-
 MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
 
 static struct usb_driver usbdux_usb_driver = {
 	.name		= "usbdux",
 	.probe		= usbdux_usb_probe,
-	.disconnect	= usbdux_usb_disconnect,
+	.disconnect	= comedi_usb_auto_unconfig,
 	.id_table	= usbdux_usb_table,
 };
 module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);
@@ -2567,4 +1845,4 @@ module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);
 MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
 MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");
 MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(FIRMWARE);
+MODULE_FIRMWARE(USBDUX_FIRMWARE);
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 27898c4..9707dd1 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -1061,10 +1061,9 @@ static int usbduxfast_auto_attach(struct comedi_device *dev,
 		return -ENODEV;
 	}
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	sema_init(&devpriv->sem, 1);
 	usb_set_intfdata(intf, devpriv);
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index 898c3c4..fca89c3 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -66,13 +66,6 @@
 /* internal addresses of the 8051 processor */
 #define USBDUXSUB_CPUCS 0xE600
 
-/* USB endpoints */
-#define USBDUXSIGMA_CMD_OUT_EP		1	/* command output */
-#define USBDUXSIGMA_ISO_OUT_EP		2	/* analog output ISO/IRQ */
-#define USBDUXSIGMA_PWM_OUT_EP		4	/* pwm output */
-#define USBDUXSIGMA_ISO_IN_EP		6	/* analog input ISO/IRQ */
-#define USBDUXSIGMA_CMD_IN_EP		8	/* command input */
-
 /* 300Hz max frequ under PWM */
 #define MIN_PWM_PERIOD  ((long)(1E9/300))
 
@@ -168,6 +161,7 @@ struct usbduxsigma_private {
 	/* input buffer for single insn */
 	int8_t *insn_buf;
 
+	int8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN];
 	unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN];
 
 	unsigned high_speed:1;
@@ -188,25 +182,25 @@ struct usbduxsigma_private {
 	unsigned int ao_counter;
 	/* interval in frames/uframes */
 	unsigned int ai_interval;
-	/* D/A commands */
-	uint8_t *dac_commands;
 	/* commands */
 	uint8_t *dux_commands;
 	struct semaphore sem;
 };
 
+static void usbduxsigma_unlink_urbs(struct urb **urbs, int num_urbs)
+{
+	int i;
+
+	for (i = 0; i < num_urbs; i++)
+		usb_kill_urb(urbs[i]);
+}
+
 static void usbduxsigma_ai_stop(struct comedi_device *dev, int do_unlink)
 {
 	struct usbduxsigma_private *devpriv = dev->private;
 
-	if (do_unlink) {
-		int i;
-
-		for (i = 0; i < devpriv->n_ai_urbs; i++) {
-			if (devpriv->ai_urbs[i])
-				usb_kill_urb(devpriv->ai_urbs[i]);
-		}
-	}
+	if (do_unlink && devpriv->ai_urbs)
+		usbduxsigma_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);
 
 	devpriv->ai_cmd_running = 0;
 }
@@ -342,14 +336,8 @@ static void usbduxsigma_ao_stop(struct comedi_device *dev, int do_unlink)
 {
 	struct usbduxsigma_private *devpriv = dev->private;
 
-	if (do_unlink) {
-		int i;
-
-		for (i = 0; i < devpriv->n_ao_urbs; i++) {
-			if (devpriv->ao_urbs[i])
-				usb_kill_urb(devpriv->ao_urbs[i]);
-		}
-	}
+	if (do_unlink && devpriv->ao_urbs)
+		usbduxsigma_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs);
 
 	devpriv->ao_cmd_running = 0;
 }
@@ -432,7 +420,7 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb)
 		len = s->async->cmd.chanlist_len;
 		*datap++ = len;
 		for (i = 0; i < len; i++) {
-			unsigned int chan = devpriv->dac_commands[i];
+			unsigned int chan = devpriv->ao_chanlist[i];
 			short val;
 
 			ret = comedi_buf_get(s->async, &val);
@@ -643,7 +631,7 @@ static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type)
 
 	devpriv->dux_commands[0] = cmd_type;
 
-	return usb_bulk_msg(usb, usb_sndbulkpipe(usb, USBDUXSIGMA_CMD_OUT_EP),
+	return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1),
 			    devpriv->dux_commands, SIZEOFDUXBUFFER,
 			    &nsent, BULK_TIMEOUT);
 }
@@ -657,8 +645,7 @@ static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command)
 	int i;
 
 	for (i = 0; i < RETRIES; i++) {
-		ret = usb_bulk_msg(usb,
-				   usb_rcvbulkpipe(usb, USBDUXSIGMA_CMD_IN_EP),
+		ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
 				   devpriv->insn_buf, SIZEINSNBUF,
 				   &nrec, BULK_TIMEOUT);
 		if (ret < 0)
@@ -686,13 +673,14 @@ static int usbduxsigma_ai_inttrig(struct comedi_device *dev,
 
 	down(&devpriv->sem);
 	if (!devpriv->ai_cmd_running) {
+		devpriv->ai_cmd_running = 1;
 		ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
 					      devpriv->n_ai_urbs, 1);
 		if (ret < 0) {
+			devpriv->ai_cmd_running = 0;
 			up(&devpriv->sem);
 			return ret;
 		}
-		devpriv->ai_cmd_running = 1;
 		s->async->inttrig = NULL;
 	}
 	up(&devpriv->sem);
@@ -740,14 +728,15 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev,
 
 	if (cmd->start_src == TRIG_NOW) {
 		/* enable this acquisition operation */
+		devpriv->ai_cmd_running = 1;
 		ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
 					      devpriv->n_ai_urbs, 1);
 		if (ret < 0) {
+			devpriv->ai_cmd_running = 0;
 			up(&devpriv->sem);
 			return ret;
 		}
 		s->async->inttrig = NULL;
-		devpriv->ai_cmd_running = 1;
 	} else {	/* TRIG_INT */
 		/* wait for an internal signal and submit the urbs later */
 		s->async->inttrig = usbduxsigma_ai_inttrig;
@@ -876,13 +865,14 @@ static int usbduxsigma_ao_inttrig(struct comedi_device *dev,
 
 	down(&devpriv->sem);
 	if (!devpriv->ao_cmd_running) {
+		devpriv->ao_cmd_running = 1;
 		ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
 					      devpriv->n_ao_urbs, 0);
 		if (ret < 0) {
+			devpriv->ao_cmd_running = 0;
 			up(&devpriv->sem);
 			return ret;
 		}
-		devpriv->ao_cmd_running = 1;
 		s->async->inttrig = NULL;
 	}
 	up(&devpriv->sem);
@@ -1020,20 +1010,21 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev,
 	/* set current channel of the running acquisition to zero */
 	s->async->cur_chan = 0;
 	for (i = 0; i < cmd->chanlist_len; ++i)
-		devpriv->dac_commands[i] = CR_CHAN(cmd->chanlist[i]);
+		devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]);
 
 	devpriv->ao_counter = devpriv->ao_timer;
 
 	if (cmd->start_src == TRIG_NOW) {
 		/* enable this acquisition operation */
+		devpriv->ao_cmd_running = 1;
 		ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
 					      devpriv->n_ao_urbs, 0);
 		if (ret < 0) {
+			devpriv->ao_cmd_running = 0;
 			up(&devpriv->sem);
 			return ret;
 		}
 		s->async->inttrig = NULL;
-		devpriv->ao_cmd_running = 1;
 	} else {	/* TRIG_INT */
 		/* wait for an internal signal and submit the urbs later */
 		s->async->inttrig = usbduxsigma_ao_inttrig;
@@ -1194,8 +1185,7 @@ static int usbduxsigma_submit_pwm_urb(struct comedi_device *dev)
 	struct urb *urb = devpriv->pwm_urb;
 
 	/* in case of a resubmission after an unlink... */
-	usb_fill_bulk_urb(urb,
-			  usb, usb_sndbulkpipe(usb, USBDUXSIGMA_PWM_OUT_EP),
+	usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4),
 			  urb->transfer_buffer, devpriv->pwm_buf_sz,
 			  usbduxsigma_pwm_urb_complete, dev);
 
@@ -1237,19 +1227,21 @@ static int usbduxsigma_pwm_start(struct comedi_device *dev,
 
 	memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
 
+	devpriv->pwm_cmd_running = 1;
 	ret = usbduxsigma_submit_pwm_urb(dev);
-	if (ret < 0)
+	if (ret < 0) {
+		devpriv->pwm_cmd_running = 0;
 		return ret;
-	devpriv->pwm_cmd_running = 1;
+	}
 
 	return 0;
 }
 
-static int usbduxsigma_pwm_pattern(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   unsigned int chan,
-				   unsigned int value,
-				   unsigned int sign)
+static void usbduxsigma_pwm_pattern(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    unsigned int chan,
+				    unsigned int value,
+				    unsigned int sign)
 {
 	struct usbduxsigma_private *devpriv = dev->private;
 	char pwm_mask = (1 << chan);	/* DIO bit for the PWM data */
@@ -1270,7 +1262,6 @@ static int usbduxsigma_pwm_pattern(struct comedi_device *dev,
 			c |= sgn_mask;
 		*buf++ = c;
 	}
-	return 1;
 }
 
 static int usbduxsigma_pwm_write(struct comedi_device *dev,
@@ -1291,7 +1282,9 @@ static int usbduxsigma_pwm_write(struct comedi_device *dev,
 	 * The sign is set via a special INSN only, this gives us 8 bits
 	 * for normal operation, sign is 0 by default.
 	 */
-	return usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0);
+	usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0);
+
+	return insn->n;
 }
 
 static int usbduxsigma_pwm_config(struct comedi_device *dev,
@@ -1326,8 +1319,8 @@ static int usbduxsigma_pwm_config(struct comedi_device *dev,
 		 * data[1] = value
 		 * data[2] = sign (for a relay)
 		 */
-		return usbduxsigma_pwm_pattern(dev, s, chan,
-					       data[1], (data[2] != 0));
+		usbduxsigma_pwm_pattern(dev, s, chan, data[1], (data[2] != 0));
+		return 0;
 	case INSN_CONFIG_PWM_GET_H_BRIDGE:
 		/* values are not kept in this driver, nothing to return */
 		return -EINVAL;
@@ -1386,90 +1379,6 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan)
 	return (int)val;
 }
 
-static int usbduxsigma_attach_common(struct comedi_device *dev)
-{
-	struct usbduxsigma_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
-	int n_subdevs;
-	int offset;
-	int ret;
-
-	down(&devpriv->sem);
-
-	if (devpriv->high_speed)
-		n_subdevs = 4;	/* with pwm */
-	else
-		n_subdevs = 3;	/* without pwm */
-	ret = comedi_alloc_subdevices(dev, n_subdevs);
-	if (ret) {
-		up(&devpriv->sem);
-		return ret;
-	}
-
-	/* Analog Input subdevice */
-	s = &dev->subdevices[0];
-	dev->read_subdev = s;
-	s->type		= COMEDI_SUBD_AI;
-	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL;
-	s->n_chan	= NUMCHANNELS;
-	s->len_chanlist	= NUMCHANNELS;
-	s->maxdata	= 0x00ffffff;
-	s->range_table	= &usbduxsigma_ai_range;
-	s->insn_read	= usbduxsigma_ai_insn_read;
-	s->do_cmdtest	= usbduxsigma_ai_cmdtest;
-	s->do_cmd	= usbduxsigma_ai_cmd;
-	s->cancel	= usbduxsigma_ai_cancel;
-
-	/* Analog Output subdevice */
-	s = &dev->subdevices[1];
-	dev->write_subdev = s;
-	s->type		= COMEDI_SUBD_AO;
-	s->subdev_flags	= SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
-	s->n_chan	= USBDUXSIGMA_NUM_AO_CHAN;
-	s->len_chanlist	= s->n_chan;
-	s->maxdata	= 0x00ff;
-	s->range_table	= &range_unipolar2_5;
-	s->insn_write	= usbduxsigma_ao_insn_write;
-	s->insn_read	= usbduxsigma_ao_insn_read;
-	s->do_cmdtest	= usbduxsigma_ao_cmdtest;
-	s->do_cmd	= usbduxsigma_ao_cmd;
-	s->cancel	= usbduxsigma_ao_cancel;
-
-	/* Digital I/O subdevice */
-	s = &dev->subdevices[2];
-	s->type		= COMEDI_SUBD_DIO;
-	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
-	s->n_chan	= 24;
-	s->maxdata	= 1;
-	s->range_table	= &range_digital;
-	s->insn_bits	= usbduxsigma_dio_insn_bits;
-	s->insn_config	= usbduxsigma_dio_insn_config;
-
-	if (devpriv->high_speed) {
-		/* Timer / pwm subdevice */
-		s = &dev->subdevices[3];
-		s->type		= COMEDI_SUBD_PWM;
-		s->subdev_flags	= SDF_WRITABLE | SDF_PWM_HBRIDGE;
-		s->n_chan	= 8;
-		s->maxdata	= devpriv->pwm_buf_sz;
-		s->insn_write	= usbduxsigma_pwm_write;
-		s->insn_config	= usbduxsigma_pwm_config;
-
-		usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
-	}
-
-	up(&devpriv->sem);
-
-	offset = usbduxsigma_getstatusinfo(dev, 0);
-	if (offset < 0)
-		dev_err(dev->class_dev,
-			"Communication to USBDUXSIGMA failed! Check firmware and cabling\n");
-
-	dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset);
-
-	return 0;
-}
-
 static int usbduxsigma_firmware_upload(struct comedi_device *dev,
 				       const u8 *data, size_t size,
 				       unsigned long context)
@@ -1548,7 +1457,6 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
 	struct urb *urb;
 	int i;
 
-	devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
 	devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
 	devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
 	devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
@@ -1556,8 +1464,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
 				   GFP_KERNEL);
 	devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb),
 				   GFP_KERNEL);
-	if (!devpriv->dac_commands || !devpriv->dux_commands ||
-	    !devpriv->in_buf || !devpriv->insn_buf ||
+	if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf ||
 	    !devpriv->ai_urbs || !devpriv->ao_urbs)
 		return -ENOMEM;
 
@@ -1571,7 +1478,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
 		/* will be filled later with a pointer to the comedi-device */
 		/* and ONLY then the urb should be submitted */
 		urb->context = NULL;
-		urb->pipe = usb_rcvisocpipe(usb, USBDUXSIGMA_ISO_IN_EP);
+		urb->pipe = usb_rcvisocpipe(usb, 6);
 		urb->transfer_flags = URB_ISO_ASAP;
 		urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
 		if (!urb->transfer_buffer)
@@ -1593,7 +1500,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
 		/* will be filled later with a pointer to the comedi-device */
 		/* and ONLY then the urb should be submitted */
 		urb->context = NULL;
-		urb->pipe = usb_sndisocpipe(usb, USBDUXSIGMA_ISO_OUT_EP);
+		urb->pipe = usb_sndisocpipe(usb, 2);
 		urb->transfer_flags = URB_ISO_ASAP;
 		urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
 		if (!urb->transfer_buffer)
@@ -1609,19 +1516,16 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
 			urb->interval = 1;	/* frames */
 	}
 
-	if (devpriv->high_speed) {
-		/* max bulk ep size in high speed */
-		devpriv->pwm_buf_sz = 512;
+	if (devpriv->pwm_buf_sz) {
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!urb)
 			return -ENOMEM;
 		devpriv->pwm_urb = urb;
-		urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, GFP_KERNEL);
+
+		urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz,
+					       GFP_KERNEL);
 		if (!urb->transfer_buffer)
 			return -ENOMEM;
-	} else {
-		devpriv->pwm_urb = NULL;
-		devpriv->pwm_buf_sz = 0;
 	}
 
 	return 0;
@@ -1633,11 +1537,6 @@ static void usbduxsigma_free_usb_buffers(struct comedi_device *dev)
 	struct urb *urb;
 	int i;
 
-	/* force unlink all urbs */
-	usbduxsigma_ai_stop(dev, 1);
-	usbduxsigma_ao_stop(dev, 1);
-	usbduxsigma_pwm_stop(dev, 1);
-
 	urb = devpriv->pwm_urb;
 	if (urb) {
 		kfree(urb->transfer_buffer);
@@ -1666,7 +1565,6 @@ static void usbduxsigma_free_usb_buffers(struct comedi_device *dev)
 	kfree(devpriv->insn_buf);
 	kfree(devpriv->in_buf);
 	kfree(devpriv->dux_commands);
-	kfree(devpriv->dac_commands);
 }
 
 static int usbduxsigma_auto_attach(struct comedi_device *dev,
@@ -1675,29 +1573,23 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev,
 	struct usb_interface *intf = comedi_to_usb_interface(dev);
 	struct usb_device *usb = comedi_to_usb_dev(dev);
 	struct usbduxsigma_private *devpriv;
+	struct comedi_subdevice *s;
+	int offset;
 	int ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	sema_init(&devpriv->sem, 1);
-	usb_set_intfdata(intf, devpriv);
 
-	ret = usb_set_interface(usb,
-				intf->altsetting->desc.bInterfaceNumber, 3);
-	if (ret < 0) {
-		dev_err(dev->class_dev,
-			"could not set alternate setting 3 in high speed\n");
-		return -ENODEV;
-	}
+	usb_set_intfdata(intf, devpriv);
 
-	/* test if it is high speed (USB 2.0) */
 	devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
 	if (devpriv->high_speed) {
 		devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
 		devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
+		devpriv->pwm_buf_sz = 512;
 	} else {
 		devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
 		devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
@@ -1707,12 +1599,84 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
+	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
+	ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
+				3);
+	if (ret < 0) {
+		dev_err(dev->class_dev,
+			"could not set alternate setting 3 in high speed\n");
+		return ret;
+	}
+
 	ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
 				   usbduxsigma_firmware_upload, 0);
 	if (ret)
 		return ret;
 
-	return usbduxsigma_attach_common(dev);
+	ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 4 : 3);
+	if (ret)
+		return ret;
+
+	/* Analog Input subdevice */
+	s = &dev->subdevices[0];
+	dev->read_subdev = s;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL;
+	s->n_chan	= NUMCHANNELS;
+	s->len_chanlist	= NUMCHANNELS;
+	s->maxdata	= 0x00ffffff;
+	s->range_table	= &usbduxsigma_ai_range;
+	s->insn_read	= usbduxsigma_ai_insn_read;
+	s->do_cmdtest	= usbduxsigma_ai_cmdtest;
+	s->do_cmd	= usbduxsigma_ai_cmd;
+	s->cancel	= usbduxsigma_ai_cancel;
+
+	/* Analog Output subdevice */
+	s = &dev->subdevices[1];
+	dev->write_subdev = s;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
+	s->n_chan	= USBDUXSIGMA_NUM_AO_CHAN;
+	s->len_chanlist	= s->n_chan;
+	s->maxdata	= 0x00ff;
+	s->range_table	= &range_unipolar2_5;
+	s->insn_write	= usbduxsigma_ao_insn_write;
+	s->insn_read	= usbduxsigma_ao_insn_read;
+	s->do_cmdtest	= usbduxsigma_ao_cmdtest;
+	s->do_cmd	= usbduxsigma_ao_cmd;
+	s->cancel	= usbduxsigma_ao_cancel;
+
+	/* Digital I/O subdevice */
+	s = &dev->subdevices[2];
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 24;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= usbduxsigma_dio_insn_bits;
+	s->insn_config	= usbduxsigma_dio_insn_config;
+
+	if (devpriv->high_speed) {
+		/* Timer / pwm subdevice */
+		s = &dev->subdevices[3];
+		s->type		= COMEDI_SUBD_PWM;
+		s->subdev_flags	= SDF_WRITABLE | SDF_PWM_HBRIDGE;
+		s->n_chan	= 8;
+		s->maxdata	= devpriv->pwm_buf_sz;
+		s->insn_write	= usbduxsigma_pwm_write;
+		s->insn_config	= usbduxsigma_pwm_config;
+
+		usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
+	}
+
+	offset = usbduxsigma_getstatusinfo(dev, 0);
+	if (offset < 0)
+		dev_err(dev->class_dev,
+			"Communication to USBDUXSIGMA failed! Check firmware and cabling\n");
+
+	dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset);
+
+	return 0;
 }
 
 static void usbduxsigma_detach(struct comedi_device *dev)
@@ -1720,13 +1684,20 @@ static void usbduxsigma_detach(struct comedi_device *dev)
 	struct usb_interface *intf = comedi_to_usb_interface(dev);
 	struct usbduxsigma_private *devpriv = dev->private;
 
+	usb_set_intfdata(intf, NULL);
+
 	if (!devpriv)
 		return;
 
-	usb_set_intfdata(intf, NULL);
-
 	down(&devpriv->sem);
+
+	/* force unlink all urbs */
+	usbduxsigma_ai_stop(dev, 1);
+	usbduxsigma_ao_stop(dev, 1);
+	usbduxsigma_pwm_stop(dev, 1);
+
 	usbduxsigma_free_usb_buffers(dev);
+
 	up(&devpriv->sem);
 }
 
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 0ab04c0..06efa16 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -875,10 +875,9 @@ static int vmk80xx_auto_attach(struct comedi_device *dev,
 	dev->board_ptr = boardinfo;
 	dev->board_name = boardinfo->name;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
-	dev->private = devpriv;
 
 	devpriv->model = boardinfo->model;
 
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index da8988c..066083c 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -22,8 +22,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/io.h>
 
diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
index 8ee9442..ade0003 100644
--- a/drivers/staging/comedi/proc.c
+++ b/drivers/staging/comedi/proc.c
@@ -55,6 +55,7 @@ static int comedi_read(struct seq_file *m, void *v)
 	if (!devices_q)
 		seq_puts(m, "no devices\n");
 
+	mutex_lock(&comedi_drivers_list_lock);
 	for (driv = comedi_drivers; driv; driv = driv->next) {
 		seq_printf(m, "%s:\n", driv->driver_name);
 		for (i = 0; i < driv->num_names; i++)
@@ -65,6 +66,7 @@ static int comedi_read(struct seq_file *m, void *v)
 		if (!driv->num_names)
 			seq_printf(m, " %s\n", driv->driver_name);
 	}
+	mutex_unlock(&comedi_drivers_list_lock);
 
 	return 0;
 }
diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
index 1f20332..8fde554 100644
--- a/drivers/staging/comedi/range.c
+++ b/drivers/staging/comedi/range.c
@@ -127,38 +127,35 @@ static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec)
 	return 1;
 }
 
-/*
-   This function checks each element in a channel/gain list to make
-   make sure it is valid.
+/**
+ * comedi_check_chanlist() - Validate each element in a chanlist.
+ * @s: comedi_subdevice struct
+ * @n: number of elements in the chanlist
+ * @chanlist: the chanlist to validate
 */
 int comedi_check_chanlist(struct comedi_subdevice *s, int n,
 			  unsigned int *chanlist)
 {
 	struct comedi_device *dev = s->device;
-	int i;
-	int chan;
+	unsigned int chanspec;
+	int chan, range_len, i;
 
-	if (s->range_table) {
-		for (i = 0; i < n; i++)
-			if (CR_CHAN(chanlist[i]) >= s->n_chan ||
-			    CR_RANGE(chanlist[i]) >= s->range_table->length
-			    || aref_invalid(s, chanlist[i])) {
-				dev_warn(dev->class_dev,
-					 "bad chanlist[%d]=0x%08x in_chan=%d range length=%d\n",
-					 i, chanlist[i], s->n_chan,
-					 s->range_table->length);
-				return -EINVAL;
-			}
-	} else if (s->range_table_list) {
+	if (s->range_table || s->range_table_list) {
 		for (i = 0; i < n; i++) {
-			chan = CR_CHAN(chanlist[i]);
+			chanspec = chanlist[i];
+			chan = CR_CHAN(chanspec);
+			if (s->range_table)
+				range_len = s->range_table->length;
+			else if (s->range_table_list && chan < s->n_chan)
+				range_len = s->range_table_list[chan]->length;
+			else
+				range_len = 0;
 			if (chan >= s->n_chan ||
-			    CR_RANGE(chanlist[i]) >=
-			    s->range_table_list[chan]->length
-			    || aref_invalid(s, chanlist[i])) {
+			    CR_RANGE(chanspec) >= range_len ||
+			    aref_invalid(s, chanspec)) {
 				dev_warn(dev->class_dev,
-					 "bad chanlist[%d]=0x%08x\n",
-					 i, chanlist[i]);
+					 "bad chanlist[%d]=0x%08x chan=%d range length=%d\n",
+					 i, chanspec, chan, range_len);
 				return -EINVAL;
 			}
 		}
diff --git a/drivers/staging/dgnc/Kconfig b/drivers/staging/dgnc/Kconfig
new file mode 100644
index 0000000..23daaa5
--- /dev/null
+++ b/drivers/staging/dgnc/Kconfig
@@ -0,0 +1,6 @@
+config DGNC
+       tristate "Digi Neo and Classic PCI Products"
+       default n
+       depends on TTY
+       ---help---
+       Driver for the Digi International Neo and Classic PCI based product line.
diff --git a/drivers/staging/dgnc/Makefile b/drivers/staging/dgnc/Makefile
new file mode 100644
index 0000000..c4c96dc
--- /dev/null
+++ b/drivers/staging/dgnc/Makefile
@@ -0,0 +1,7 @@
+EXTRA_CFLAGS += -DDG_NAME=\"dgnc-1.3-16\" -DDG_PART=\"40002369_F\"
+
+obj-$(CONFIG_DGNC) += dgnc.o
+
+dgnc-objs :=   dgnc_cls.o dgnc_driver.o\
+               dgnc_mgmt.o dgnc_neo.o\
+               dgnc_proc.o dgnc_trace.o dgnc_tty.o dgnc_sysfs.o
diff --git a/drivers/staging/dgnc/Makefile.inc b/drivers/staging/dgnc/Makefile.inc
new file mode 100644
index 0000000..6ca38c7
--- /dev/null
+++ b/drivers/staging/dgnc/Makefile.inc
@@ -0,0 +1,133 @@
+#
+# From Makefile.inc
+#
+
+#
+# Common definitions go here.
+#
+
+#
+# TRUE_VERSION is the version string used in the driver build,
+# it is intended to be in the form:
+#
+#   2.0-0
+#
+# A string noting a particular special modification could be
+# used as well.  This string will be reported when the driver
+# is loaded, and will be exposed by its /proc/dgnc/info
+# interface.
+#
+TRUE_VERSION="1.3-16"
+
+#
+# DGNC_PART_NUM is the part number string for the driver package.
+# It should be in the form:
+#
+#   40002369_A
+#
+DGNC_PART_NUM=40002369_F
+
+#
+# DGNC_REL_NOTE is the part number string for the driver release
+# notes.  It should be in the form:
+#
+#   93000517_A
+#
+DGNC_REL_NOTE=93000517_F
+
+#
+# DGNC_PKG_VER is the "version" number string included in the
+# various documentation and packaging files.  It should be
+# in the form:
+#
+#   1.0
+#
+DGNC_PKG_VER=1.3
+
+#
+# DGNC_PKG_REV is the "revision" of this version.  Together,
+# a linux module revision is built with:
+#
+#   ${DGNC_PKG_VER}-${DGNC_PKG_REV}
+#
+DGNC_PKG_REV=16
+
+#
+# DRP_PKG_DATE is the "date" string included in (for now) the
+# release notes.  It should be in the form:
+#
+#   11/04/2003
+#
+DGNC_PKG_DATE=10/17/2008
+
+INIT_DIR= $(shell \
+	if [ -d /etc/rc.d/init.d ]; \
+	then echo "$(RPM_BUILD_ROOT)/etc/rc.d/init.d"; \
+	else echo "$(RPM_BUILD_ROOT)/etc/init.d"; fi)
+
+#
+#	Miscelaneous path macro's
+#
+
+PACKAGE=	dgnc
+DEVDIR=		/dev/dg/$(PACKAGE)
+SRCDIR=		/usr/src/dg/$(PACKAGE)
+BINDIR=		/usr/bin
+DRVLIBDIR=	/etc/$(PACKAGE)
+MANDIR=		/usr/man
+USRLIBDIR=	/usr/lib
+DGNCDIR=	/etc/dgnc
+
+
+INIT_DIR= $(shell \
+	if [ -d /etc/rc.d/init.d ]; \
+	then echo "/etc/rc.d/init.d"; \
+	else echo "/etc/init.d"; fi)
+
+
+#
+# From Makefile
+#
+ifndef MYPWD
+MYPWD = $(shell pwd)
+endif
+
+ifeq ($(KERNDIR),)
+  KERNVERS       := $(shell uname -r)
+  KERNDIR         :=/lib/modules/${KERNVERS}/
+endif
+
+# Grab version and other important stuff
+
+RPMNAME := $(PACKAGE)-$(TRUE_VERSION)
+
+PARTNUM := $(DGNC_PART_NUM)
+
+RELNOTES := $(DGNC_REL_NOTE)
+
+MODDIR = $(shell echo $(BUILDROOT)/lib/modules/3.4.36-lcrs/misc)
+LSMOD = /sbin/lsmod
+RMMOD = /sbin/rmmod
+INSMOD = /sbin/insmod
+NEW_TTY_LOCKING = No
+NEW_TTY_BUFFERING = No
+REGISTER_TTYS_WITH_SYSFS = No
+
+# Send in some extra things...
+EXTRA_CFLAGS += -I${MYPWD} -I${MYPWD}/include -I${MYPWD}/../../commoninc\
+	-I${MYPWD}/../../dpa -DLINUX -DDG_NAME=\"$(RPMNAME)\"\
+	-DDG_PART=\"$(PARTNUM)\" -DDGNC_TRACER
+
+ifeq ($(NEW_TTY_LOCKING),Yes)
+	EXTRA_CFLAGS += -DNEW_TTY_LOCKING
+endif
+
+ifeq ($(NEW_TTY_BUFFERING),Yes)
+	EXTRA_CFLAGS += -DNEW_TTY_BUFFERING
+endif
+
+ifeq ($(REGISTER_TTYS_WITH_SYSFS),Yes)
+	EXTRA_CFLAGS += -DREGISTER_TTYS_WITH_SYSFS
+endif
+
+# Conform to correct kbuild conventions...
diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c
new file mode 100644
index 0000000..83c0575
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_cls.c
@@ -0,0 +1,1411 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *	Thank you.
+ *
+ *
+ * $Id: dgnc_cls.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>	/* For jiffies, task states */
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/delay.h>	/* For udelay */
+#include <asm/io.h>		/* For read[bwl]/write[bwl] */
+#include <linux/serial.h>	/* For struct async_serial */
+#include <linux/serial_reg.h>	/* For the various UART offsets */
+#include <linux/pci.h>
+
+#include "dgnc_driver.h"	/* Driver main header file */
+#include "dgnc_cls.h"
+#include "dgnc_tty.h"
+#include "dgnc_trace.h"
+
+static inline void cls_parse_isr(struct board_t *brd, uint port);
+static inline void cls_clear_break(struct channel_t *ch, int force);
+static inline void cls_set_cts_flow_control(struct channel_t *ch);
+static inline void cls_set_rts_flow_control(struct channel_t *ch);
+static inline void cls_set_ixon_flow_control(struct channel_t *ch);
+static inline void cls_set_ixoff_flow_control(struct channel_t *ch);
+static inline void cls_set_no_output_flow_control(struct channel_t *ch);
+static inline void cls_set_no_input_flow_control(struct channel_t *ch);
+static void cls_parse_modem(struct channel_t *ch, uchar signals);
+static void cls_tasklet(unsigned long data);
+static void cls_vpd(struct board_t *brd);
+static void cls_uart_init(struct channel_t *ch);
+static void cls_uart_off(struct channel_t *ch);
+static int cls_drain(struct tty_struct *tty, uint seconds);
+static void cls_param(struct tty_struct *tty);
+static void cls_assert_modem_signals(struct channel_t *ch);
+static void cls_flush_uart_write(struct channel_t *ch);
+static void cls_flush_uart_read(struct channel_t *ch);
+static void cls_disable_receiver(struct channel_t *ch);
+static void cls_enable_receiver(struct channel_t *ch);
+static void cls_send_break(struct channel_t *ch, int msecs);
+static void cls_send_start_character(struct channel_t *ch);
+static void cls_send_stop_character(struct channel_t *ch);
+static void cls_copy_data_from_uart_to_queue(struct channel_t *ch);
+static void cls_copy_data_from_queue_to_uart(struct channel_t *ch);
+static uint cls_get_uart_bytes_left(struct channel_t *ch);
+static void cls_send_immediate_char(struct channel_t *ch, unsigned char);
+static irqreturn_t cls_intr(int irq, void *voidbrd);
+
+struct board_ops dgnc_cls_ops = {
+	.tasklet =			cls_tasklet,
+	.intr =				cls_intr,
+	.uart_init =			cls_uart_init,
+	.uart_off =			cls_uart_off,
+	.drain =			cls_drain,
+	.param =			cls_param,
+	.vpd =				cls_vpd,
+	.assert_modem_signals =		cls_assert_modem_signals,
+	.flush_uart_write =		cls_flush_uart_write,
+	.flush_uart_read =		cls_flush_uart_read,
+	.disable_receiver =		cls_disable_receiver,
+	.enable_receiver =		cls_enable_receiver,
+	.send_break =			cls_send_break,
+	.send_start_character =		cls_send_start_character,
+	.send_stop_character =		cls_send_stop_character,
+	.copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart,
+	.get_uart_bytes_left =		cls_get_uart_bytes_left,
+	.send_immediate_char =		cls_send_immediate_char
+};
+
+
+static inline void cls_set_cts_flow_control(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar ier = readb(&ch->ch_cls_uart->ier);
+	uchar isr_fcr = 0;
+
+	DPR_PARAM(("Setting CTSFLOW\n"));
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn on CTS flow control, turn off IXON flow control */
+	isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_CTSDSR);
+	isr_fcr &= ~(UART_EXAR654_EFR_IXON);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+	/* Enable interrupts for CTS flow, turn off interrupts for received XOFF chars */
+	ier |= (UART_EXAR654_IER_CTSDSR);
+	ier &= ~(UART_EXAR654_IER_XOFF);
+	writeb(ier, &ch->ch_cls_uart->ier);
+
+	/* Set the usual FIFO values */
+	writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
+		UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
+		&ch->ch_cls_uart->isr_fcr);
+
+	ch->ch_t_tlevel = 16;
+
+}
+
+
+static inline void cls_set_ixon_flow_control(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar ier = readb(&ch->ch_cls_uart->ier);
+	uchar isr_fcr = 0;
+
+	DPR_PARAM(("Setting IXON FLOW\n"));
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn on IXON flow control, turn off CTS flow control */
+	isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXON);
+	isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Now set our current start/stop chars while in enhanced mode */
+	writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
+	writeb(0, &ch->ch_cls_uart->lsr);
+	writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
+	writeb(0, &ch->ch_cls_uart->spr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+	/* Disable interrupts for CTS flow, turn on interrupts for received XOFF chars */
+	ier &= ~(UART_EXAR654_IER_CTSDSR);
+	ier |= (UART_EXAR654_IER_XOFF);
+	writeb(ier, &ch->ch_cls_uart->ier);
+
+	/* Set the usual FIFO values */
+	writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
+		UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
+		&ch->ch_cls_uart->isr_fcr);
+
+}
+
+
+static inline void cls_set_no_output_flow_control(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar ier = readb(&ch->ch_cls_uart->ier);
+	uchar isr_fcr = 0;
+
+	DPR_PARAM(("Unsetting Output FLOW\n"));
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn off IXON flow control, turn off CTS flow control */
+	isr_fcr |= (UART_EXAR654_EFR_ECB);
+	isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR | UART_EXAR654_EFR_IXON);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+	/* Disable interrupts for CTS flow, turn off interrupts for received XOFF chars */
+	ier &= ~(UART_EXAR654_IER_CTSDSR);
+	ier &= ~(UART_EXAR654_IER_XOFF);
+	writeb(ier, &ch->ch_cls_uart->ier);
+
+	/* Set the usual FIFO values */
+	writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
+		UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
+		&ch->ch_cls_uart->isr_fcr);
+
+	ch->ch_r_watermark = 0;
+        ch->ch_t_tlevel = 16;
+        ch->ch_r_tlevel = 16;
+
+}
+
+
+static inline void cls_set_rts_flow_control(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar ier = readb(&ch->ch_cls_uart->ier);
+	uchar isr_fcr = 0;
+
+	DPR_PARAM(("Setting RTSFLOW\n"));
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn on RTS flow control, turn off IXOFF flow control */
+	isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_RTSDTR);
+	isr_fcr &= ~(UART_EXAR654_EFR_IXOFF);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+	/* Enable interrupts for RTS flow */
+	ier |= (UART_EXAR654_IER_RTSDTR);
+	writeb(ier, &ch->ch_cls_uart->ier);
+
+	/* Set the usual FIFO values */
+	writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
+		UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
+		&ch->ch_cls_uart->isr_fcr);
+
+
+	ch->ch_r_watermark = 4;
+	ch->ch_r_tlevel = 8;
+
+}
+
+
+static inline void cls_set_ixoff_flow_control(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar ier = readb(&ch->ch_cls_uart->ier);
+	uchar isr_fcr = 0;
+
+	DPR_PARAM(("Setting IXOFF FLOW\n"));
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn on IXOFF flow control, turn off RTS flow control */
+	isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXOFF);
+	isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Now set our current start/stop chars while in enhanced mode */
+	writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
+	writeb(0, &ch->ch_cls_uart->lsr);
+	writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
+	writeb(0, &ch->ch_cls_uart->spr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+	/* Disable interrupts for RTS flow */
+	ier &= ~(UART_EXAR654_IER_RTSDTR);
+	writeb(ier, &ch->ch_cls_uart->ier);
+
+	/* Set the usual FIFO values */
+	writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
+		UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
+		&ch->ch_cls_uart->isr_fcr);
+
+}
+
+
+static inline void cls_set_no_input_flow_control(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar ier = readb(&ch->ch_cls_uart->ier);
+	uchar isr_fcr = 0;
+
+	DPR_PARAM(("Unsetting Input FLOW\n"));
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn off IXOFF flow control, turn off RTS flow control */
+	isr_fcr |= (UART_EXAR654_EFR_ECB);
+	isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR | UART_EXAR654_EFR_IXOFF);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+	/* Disable interrupts for RTS flow */
+	ier &= ~(UART_EXAR654_IER_RTSDTR);
+	writeb(ier, &ch->ch_cls_uart->ier);
+
+	/* Set the usual FIFO values */
+	writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
+		UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
+		&ch->ch_cls_uart->isr_fcr);
+
+        ch->ch_t_tlevel = 16;
+        ch->ch_r_tlevel = 16;
+
+}
+
+
+/*
+ * cls_clear_break.
+ * Determines whether its time to shut off break condition.
+ *
+ * No locks are assumed to be held when calling this function.
+ * channel lock is held and released in this function.
+ */
+static inline void cls_clear_break(struct channel_t *ch, int force)
+{
+	ulong lock_flags;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* Bail if we aren't currently sending a break. */
+	if (!ch->ch_stop_sending_break) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/* Turn break off, and unset some variables */
+	if (ch->ch_flags & CH_BREAK_SENDING) {
+		if ((jiffies >= ch->ch_stop_sending_break) || force) {
+			uchar temp = readb(&ch->ch_cls_uart->lcr);
+        	        writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);
+			ch->ch_flags &= ~(CH_BREAK_SENDING);
+			ch->ch_stop_sending_break = 0;
+			DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
+		}
+	}
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+/* Parse the ISR register for the specific port */
+static inline void cls_parse_isr(struct board_t *brd, uint port)
+{
+	struct channel_t *ch;
+	uchar isr = 0;
+	ulong lock_flags;
+
+	/*
+	 * No need to verify board pointer, it was already
+	 * verified in the interrupt routine.
+	 */
+
+	if (port > brd->nasync)
+		return;
+
+	ch = brd->channels[port];
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	/* Here we try to figure out what caused the interrupt to happen */
+	while (1) {
+
+		isr = readb(&ch->ch_cls_uart->isr_fcr);
+
+		/* Bail if no pending interrupt on port */
+		if (isr & UART_IIR_NO_INT)  {
+			break;
+		}
+
+		DPR_INTR(("%s:%d port: %x isr: %x\n", __FILE__, __LINE__, port, isr));
+
+		/* Receive Interrupt pending */
+		if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) {
+			/* Read data from uart -> queue */
+			brd->intr_rx++;
+			ch->ch_intr_rx++;
+			cls_copy_data_from_uart_to_queue(ch);
+			dgnc_check_queue_flow_control(ch);
+		}
+
+		/* Transmit Hold register empty pending */
+		if (isr & UART_IIR_THRI) {
+			/* Transfer data (if any) from Write Queue -> UART. */
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+			brd->intr_tx++;
+			ch->ch_intr_tx++;
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			cls_copy_data_from_queue_to_uart(ch);
+		}
+
+		/* Received Xoff signal/Special character */
+		if (isr & UART_IIR_XOFF) {
+			/* Empty */
+		}
+
+		/* CTS/RTS change of state */
+		if (isr & UART_IIR_CTSRTS) {
+			brd->intr_modem++;
+			ch->ch_intr_modem++;
+			/*
+			 * Don't need to do anything, the cls_parse_modem
+			 * below will grab the updated modem signals.
+			 */
+		}
+
+		/* Parse any modem signal changes */
+		DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n"));
+		cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
+	}
+}
+
+
+/*
+ * cls_param()
+ * Send any/all changes to the line to the UART.
+ */
+static void cls_param(struct tty_struct *tty)
+{
+	uchar lcr = 0;
+	uchar uart_lcr = 0;
+	uchar ier = 0;
+	uchar uart_ier = 0;
+        uint baud = 9600;
+	int quot = 0;
+        struct board_t *bd;
+	struct channel_t *ch;
+        struct un_t   *un;
+
+	if (!tty || tty->magic != TTY_MAGIC) {
+		return;
+	}
+
+	un = (struct un_t *) tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC) {
+		return;
+	}
+
+	ch = un->un_ch;   
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return;
+	}
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
+		return;
+	}
+
+	DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
+		ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
+
+	/*
+	 * If baud rate is zero, flush queues, and set mval to drop DTR.
+	 */
+	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+		ch->ch_r_head = ch->ch_r_tail = 0;
+		ch->ch_e_head = ch->ch_e_tail = 0;
+		ch->ch_w_head = ch->ch_w_tail = 0;
+
+		cls_flush_uart_write(ch);
+                cls_flush_uart_read(ch);
+
+		/* The baudrate is B0 so all modem lines are to be dropped. */
+		ch->ch_flags |= (CH_BAUD0);
+		ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
+		cls_assert_modem_signals(ch);
+		ch->ch_old_baud = 0;
+		return;
+	} else if (ch->ch_custom_speed) {
+
+		baud = ch->ch_custom_speed;
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+
+			/*
+			 * Bring back up RTS and DTR...
+			 * Also handle RTS or DTR toggle if set.
+			 */
+			if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_RTS);
+			if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_DTR);
+		}
+
+	} else {
+		int iindex = 0;
+		int jindex = 0;
+
+		ulong bauds[4][16] = {
+			{ /* slowbaud */
+				0,      50,     75,     110,
+				134,    150,    200,    300,
+				600,    1200,   1800,   2400,
+				4800,   9600,   19200,  38400 },
+			{ /* slowbaud & CBAUDEX */
+				0,      57600,  115200, 230400,
+				460800, 150,    200,    921600,
+				600,    1200,   1800,   2400,
+				4800,   9600,   19200,  38400 },
+			{ /* fastbaud */
+				0,      57600,   76800, 115200,
+				131657, 153600, 230400, 460800,
+				921600, 1200,   1800,   2400,
+				4800,   9600,   19200,  38400 },
+			{ /* fastbaud & CBAUDEX */
+				0,      57600,  115200, 230400,
+				460800, 150,    200,    921600,
+				600,    1200,   1800,   2400,
+				4800,   9600,   19200,  38400 }
+		};
+
+		/* Only use the TXPrint baud rate if the terminal unit is NOT open */
+		if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT))
+			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
+		else
+			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
+
+		if (ch->ch_c_cflag & CBAUDEX)
+			iindex = 1;
+
+		if (ch->ch_digi.digi_flags & DIGI_FAST)
+			iindex += 2;
+
+		jindex = baud;
+
+		if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
+			baud = bauds[iindex][jindex];  
+		} else {
+			DPR_IOCTL(("baud indices were out of range (%d)(%d)",
+				iindex, jindex));
+			baud = 0;
+		}
+
+		if (baud == 0)
+			baud = 9600;
+
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+
+			/*
+			 * Bring back up RTS and DTR...
+			 * Also handle RTS or DTR toggle if set.
+			 */
+			if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_RTS);
+			if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_DTR);
+		}
+	}
+
+	if (ch->ch_c_cflag & PARENB) {
+		lcr |= UART_LCR_PARITY;
+	}
+
+	if (!(ch->ch_c_cflag & PARODD)) {
+		lcr |= UART_LCR_EPAR;
+	}
+
+	/*
+	 * Not all platforms support mark/space parity,
+	 * so this will hide behind an ifdef.
+	 */
+#ifdef CMSPAR
+	if (ch->ch_c_cflag & CMSPAR)
+		lcr |= UART_LCR_SPAR;    
+#endif
+
+	if (ch->ch_c_cflag & CSTOPB)
+		lcr |= UART_LCR_STOP;
+
+	switch (ch->ch_c_cflag & CSIZE) {
+	case CS5:
+		lcr |= UART_LCR_WLEN5;
+		break;
+	case CS6:
+		lcr |= UART_LCR_WLEN6;
+		break;
+	case CS7:
+		lcr |= UART_LCR_WLEN7;
+		break;
+	case CS8:
+	default:
+		lcr |= UART_LCR_WLEN8;
+		break;
+	}
+
+	ier = uart_ier = readb(&ch->ch_cls_uart->ier);
+	uart_lcr = readb(&ch->ch_cls_uart->lcr);
+
+	if (baud == 0)
+		baud = 9600;
+
+	quot = ch->ch_bd->bd_dividend / baud;
+
+	if (quot != 0 && ch->ch_old_baud != baud) {
+		ch->ch_old_baud = baud;
+		writeb(UART_LCR_DLAB, &ch->ch_cls_uart->lcr);
+		writeb((quot & 0xff), &ch->ch_cls_uart->txrx);
+		writeb((quot >> 8), &ch->ch_cls_uart->ier);
+		writeb(lcr, &ch->ch_cls_uart->lcr);
+        }
+
+	if (uart_lcr != lcr)
+		writeb(lcr, &ch->ch_cls_uart->lcr);
+
+	if (ch->ch_c_cflag & CREAD) {
+		ier |= (UART_IER_RDI | UART_IER_RLSI);
+	}       
+	else {
+		ier &= ~(UART_IER_RDI | UART_IER_RLSI);
+	}
+
+	/*
+	 * Have the UART interrupt on modem signal changes ONLY when
+	 * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set.
+	 */
+	if ((ch->ch_digi.digi_flags & CTSPACE) || (ch->ch_digi.digi_flags & RTSPACE) ||
+		(ch->ch_c_cflag & CRTSCTS) || !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
+		!(ch->ch_c_cflag & CLOCAL))
+	{
+		ier |= UART_IER_MSI;
+	}
+	else {
+		ier &= ~UART_IER_MSI;
+	}
+
+	ier |= UART_IER_THRI;
+
+	if (ier != uart_ier)
+		writeb(ier, &ch->ch_cls_uart->ier);
+
+	if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
+		cls_set_cts_flow_control(ch);
+	}
+	else if (ch->ch_c_iflag & IXON) {
+		/* If start/stop is set to disable, then we should disable flow control */
+		if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
+			cls_set_no_output_flow_control(ch);
+		else
+			cls_set_ixon_flow_control(ch);
+	}
+	else {
+		cls_set_no_output_flow_control(ch);
+	}
+
+	if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
+		cls_set_rts_flow_control(ch);
+	}
+	else if (ch->ch_c_iflag & IXOFF) {
+		/* If start/stop is set to disable, then we should disable flow control */
+		if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
+			cls_set_no_input_flow_control(ch);
+		else
+			cls_set_ixoff_flow_control(ch);
+	} 
+	else {
+		cls_set_no_input_flow_control(ch);
+	}
+
+	cls_assert_modem_signals(ch);
+
+	/* Get current status of the modem signals now */
+	cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
+}
+
+
+/*
+ * Our board poller function.
+ */
+static void cls_tasklet(unsigned long data)
+{
+        struct board_t *bd = (struct board_t *) data;
+	struct channel_t *ch;
+	ulong  lock_flags;
+	int i;
+	int state = 0;
+	int ports = 0;
+
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
+		APR(("poll_tasklet() - NULL or bad bd.\n"));
+		return;
+	}
+
+	/* Cache a couple board values */
+	DGNC_LOCK(bd->bd_lock, lock_flags);
+	state = bd->state;
+	ports = bd->nasync;
+	DGNC_UNLOCK(bd->bd_lock, lock_flags);
+
+	/*
+	 * Do NOT allow the interrupt routine to read the intr registers
+	 * Until we release this lock.
+	 */
+	DGNC_LOCK(bd->bd_intr_lock, lock_flags);
+
+	/*
+	 * If board is ready, parse deeper to see if there is anything to do.
+	 */
+	if ((state == BOARD_READY) && (ports > 0)) {
+
+		/* Loop on each port */
+		for (i = 0; i < ports; i++) {
+			ch = bd->channels[i];
+			if (!ch)
+				continue;
+
+			/*
+			 * NOTE: Remember you CANNOT hold any channel
+			 * locks when calling input.
+			 * During input processing, its possible we
+			 * will call ld, which might do callbacks back
+			 * into us.
+			 */
+			dgnc_input(ch);
+
+			/*
+			 * Channel lock is grabbed and then released
+			 * inside this routine.
+			 */
+			cls_copy_data_from_queue_to_uart(ch);
+			dgnc_wakeup_writes(ch);
+
+			/*
+			 * Check carrier function.
+			 */
+			dgnc_carrier(ch);
+
+			/*
+			 * The timing check of turning off the break is done
+			 * inside clear_break()
+			 */
+			if (ch->ch_stop_sending_break)
+				cls_clear_break(ch, 0);
+		}
+	}
+
+	DGNC_UNLOCK(bd->bd_intr_lock, lock_flags);
+
+}
+
+
+/*
+ * cls_intr()
+ *
+ * Classic specific interrupt handler.
+ */
+static irqreturn_t cls_intr(int irq, void *voidbrd)
+{
+	struct board_t *brd = (struct board_t *) voidbrd;
+	uint i = 0;
+	uchar poll_reg;
+	unsigned long lock_flags;
+
+	if (!brd) {
+		APR(("Received interrupt (%d) with null board associated\n", irq));
+		return IRQ_NONE;
+	}
+
+	/*
+	 * Check to make sure its for us.
+	 */
+	if (brd->magic != DGNC_BOARD_MAGIC) {
+		APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
+		return IRQ_NONE;
+	}
+
+	DGNC_LOCK(brd->bd_intr_lock, lock_flags);
+
+	brd->intr_count++;
+
+	/*
+	 * Check the board's global interrupt offset to see if we 
+	 * we actually do have an interrupt pending for us.
+	 */
+	poll_reg = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET);
+
+	/* If 0, no interrupts pending */
+	if (!poll_reg) {
+		DPR_INTR(("Kernel interrupted to me, but no pending interrupts...\n"));
+		DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
+		return IRQ_NONE;
+	}
+
+	DPR_INTR(("%s:%d poll_reg: %x\n", __FILE__, __LINE__, poll_reg));
+
+	/* Parse each port to find out what caused the interrupt */
+	for (i = 0; i < brd->nasync; i++) {
+		cls_parse_isr(brd, i);
+	}
+
+	/*
+	 * Schedule tasklet to more in-depth servicing at a better time.
+	 */
+	tasklet_schedule(&brd->helper_tasklet);
+
+	DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
+
+	DPR_INTR(("dgnc_intr finish.\n"));
+	return IRQ_HANDLED;
+}
+
+
+static void cls_disable_receiver(struct channel_t *ch)
+{
+	uchar tmp = readb(&ch->ch_cls_uart->ier);
+	tmp &= ~(UART_IER_RDI);
+	writeb(tmp, &ch->ch_cls_uart->ier);
+}
+
+
+static void cls_enable_receiver(struct channel_t *ch)
+{
+	uchar tmp = readb(&ch->ch_cls_uart->ier);
+	tmp |= (UART_IER_RDI);
+	writeb(tmp, &ch->ch_cls_uart->ier);
+}
+
+
+static void cls_copy_data_from_uart_to_queue(struct channel_t *ch)
+{
+        int qleft = 0;
+        uchar linestatus = 0;
+	uchar error_mask = 0;
+	ushort head;
+	ushort tail;
+	ulong lock_flags;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* cache head and tail of queue */
+	head = ch->ch_r_head;
+	tail = ch->ch_r_tail;
+
+	/* Store how much space we have left in the queue */
+	if ((qleft = tail - head - 1) < 0)
+		qleft += RQUEUEMASK + 1;
+
+	/*
+	 * Create a mask to determine whether we should
+	 * insert the character (if any) into our queue.
+	 */
+	if (ch->ch_c_iflag & IGNBRK)
+		error_mask |= UART_LSR_BI;
+
+	while (1) {
+		linestatus = readb(&ch->ch_cls_uart->lsr);
+
+		if (!(linestatus & (UART_LSR_DR)))
+			break;
+
+		/*
+		 * Discard character if we are ignoring the error mask.
+		*/
+		if (linestatus & error_mask)  {
+			uchar discard;
+			linestatus = 0;
+			discard = readb(&ch->ch_cls_uart->txrx);
+			continue;
+		}
+
+		/*
+		 * If our queue is full, we have no choice but to drop some data.
+		 * The assumption is that HWFLOW or SWFLOW should have stopped
+		 * things way way before we got to this point.
+		 *
+		 * I decided that I wanted to ditch the oldest data first,
+		 * I hope thats okay with everyone? Yes? Good.
+		 */
+		while (qleft < 1) {
+			DPR_READ(("Queue full, dropping DATA:%x LSR:%x\n",
+				ch->ch_rqueue[tail], ch->ch_equeue[tail]));
+
+			ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
+			ch->ch_err_overrun++;
+			qleft++;
+		}
+
+		ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE);
+		ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx);
+		dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, 1);
+
+		qleft--;
+
+		DPR_READ(("DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]));
+
+		if (ch->ch_equeue[head] & UART_LSR_PE)
+			ch->ch_err_parity++;
+		if (ch->ch_equeue[head] & UART_LSR_BI)
+			ch->ch_err_break++;
+		if (ch->ch_equeue[head] & UART_LSR_FE)
+			ch->ch_err_frame++;
+
+		/* Add to, and flip head if needed */
+		head = (head + 1) & RQUEUEMASK;
+		ch->ch_rxcount++;
+	}
+
+	/*
+	 * Write new final heads to channel structure.
+	 */
+	ch->ch_r_head = head & RQUEUEMASK;
+	ch->ch_e_head = head & EQUEUEMASK;
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+/*
+ * This function basically goes to sleep for secs, or until
+ * it gets signalled that the port has fully drained.
+ */
+static int cls_drain(struct tty_struct *tty, uint seconds)
+{
+	ulong lock_flags;
+	struct channel_t *ch;
+        struct un_t *un;
+	int rc = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC) {
+		return (-ENXIO);
+	}
+
+	un = (struct un_t *) tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC) {
+		return (-ENXIO);
+	}
+
+	ch = un->un_ch;   
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return (-ENXIO);
+	}
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	un->un_flags |= UN_EMPTY;
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * NOTE: Do something with time passed in.
+	 */
+	rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
+
+	/* If ret is non-zero, user ctrl-c'ed us */
+	if (rc)
+		DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__));
+
+        return (rc);
+}
+        
+
+/* Channel lock MUST be held before calling this function! */
+static void cls_flush_uart_write(struct channel_t *ch)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return;
+	}
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr);
+	udelay(10);
+
+	ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+}
+
+
+/* Channel lock MUST be held before calling this function! */
+static void cls_flush_uart_read(struct channel_t *ch)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return;
+	}
+
+	/*
+	 * For complete POSIX compatibility, we should be purging the
+	 * read FIFO in the UART here.
+	 * 
+	 * However, doing the statement below also incorrectly flushes
+	 * write data as well as just basically trashing the FIFO.
+	 *
+	 * I believe this is a BUG in this UART.
+	 * So for now, we will leave the code #ifdef'ed out...
+	 */
+#if 0
+	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_cls_uart->isr_fcr);
+#endif
+	udelay(10);
+}
+
+
+static void cls_copy_data_from_queue_to_uart(struct channel_t *ch)
+{
+	ushort head;
+	ushort tail;
+	int n;
+	int qlen;
+	uint len_written = 0;
+	ulong lock_flags;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* No data to write to the UART */
+	if (ch->ch_w_tail == ch->ch_w_head) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/* If port is "stopped", don't send any data to the UART */
+	if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	n = 32;
+
+        /* cache head and tail of queue */
+        head = ch->ch_w_head & WQUEUEMASK;
+        tail = ch->ch_w_tail & WQUEUEMASK;
+        qlen = (head - tail) & WQUEUEMASK;
+
+	/* Find minimum of the FIFO space, versus queue length */
+	n = min(n, qlen);
+
+	while (n > 0) {
+
+		/*
+		 * If RTS Toggle mode is on, turn on RTS now if not already set,
+		 * and make sure we get an event when the data transfer has completed.
+		 */
+		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
+			if (!(ch->ch_mostat & UART_MCR_RTS)) {
+				ch->ch_mostat |= (UART_MCR_RTS);
+				cls_assert_modem_signals(ch);
+			}
+			ch->ch_tun.un_flags |= (UN_EMPTY);
+		}
+
+		/*
+		 * If DTR Toggle mode is on, turn on DTR now if not already set,
+		 * and make sure we get an event when the data transfer has completed.
+		 */
+		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
+			if (!(ch->ch_mostat & UART_MCR_DTR)) {
+				ch->ch_mostat |= (UART_MCR_DTR);
+				cls_assert_modem_signals(ch);
+			}
+			ch->ch_tun.un_flags |= (UN_EMPTY);
+		}
+		writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx);
+		dgnc_sniff_nowait_nolock(ch, "UART WRITE", ch->ch_wqueue + ch->ch_w_tail, 1);
+		DPR_WRITE(("Tx data: %x\n", ch->ch_wqueue[ch->ch_w_tail]));
+		ch->ch_w_tail++;
+		ch->ch_w_tail &= WQUEUEMASK;
+		ch->ch_txcount++;
+		len_written++;
+		n--;
+	}
+
+	if (len_written > 0)
+		ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	return;
+}
+
+
+static void cls_parse_modem(struct channel_t *ch, uchar signals)
+{
+	volatile uchar msignals = signals;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DPR_MSIGS(("cls_parse_modem: port: %d signals: %d\n", ch->ch_portnum, msignals));
+
+	/*
+	 * Do altpin switching. Altpin switches DCD and DSR.
+	 * This prolly breaks DSRPACE, so we should be more clever here.
+	 */
+	if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
+		uchar mswap = signals;
+		if (mswap & UART_MSR_DDCD) {
+			msignals &= ~UART_MSR_DDCD;
+			msignals |= UART_MSR_DDSR;
+		}
+		if (mswap & UART_MSR_DDSR) {
+			msignals &= ~UART_MSR_DDSR;
+			msignals |= UART_MSR_DDCD;
+		}
+		if (mswap & UART_MSR_DCD) {
+			msignals &= ~UART_MSR_DCD;
+			msignals |= UART_MSR_DSR;
+		}
+		if (mswap & UART_MSR_DSR) {
+			msignals &= ~UART_MSR_DSR;
+			msignals |= UART_MSR_DCD;
+		}
+	}
+                        
+	/* Scrub off lower bits. They signify delta's, which I don't care about */
+	signals &= 0xf0;
+
+	if (msignals & UART_MSR_DCD)
+		ch->ch_mistat |= UART_MSR_DCD;
+	else
+		ch->ch_mistat &= ~UART_MSR_DCD;
+
+	if (msignals & UART_MSR_DSR)
+		ch->ch_mistat |= UART_MSR_DSR;
+	else
+		ch->ch_mistat &= ~UART_MSR_DSR;
+
+	if (msignals & UART_MSR_RI)
+		ch->ch_mistat |= UART_MSR_RI;
+	else
+		ch->ch_mistat &= ~UART_MSR_RI;
+
+	if (msignals & UART_MSR_CTS)
+		ch->ch_mistat |= UART_MSR_CTS;
+	else
+		ch->ch_mistat &= ~UART_MSR_CTS;
+
+
+	DPR_MSIGS(("Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
+		ch->ch_portnum,
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS), 
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR), 
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD)));
+}
+
+
+/* Make the UART raise any of the output signals we want up */
+static void cls_assert_modem_signals(struct channel_t *ch)
+{
+	uchar out;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	out = ch->ch_mostat;
+
+	if (ch->ch_flags & CH_LOOPBACK)
+		out |= UART_MCR_LOOP;
+
+        writeb(out, &ch->ch_cls_uart->mcr);
+
+	/* Give time for the UART to actually drop the signals */
+	udelay(10);
+}
+
+
+static void cls_send_start_character(struct channel_t *ch)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	if (ch->ch_startc != _POSIX_VDISABLE) {
+		ch->ch_xon_sends++;
+		writeb(ch->ch_startc, &ch->ch_cls_uart->txrx);
+        }
+}
+
+
+static void cls_send_stop_character(struct channel_t *ch)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	if (ch->ch_stopc != _POSIX_VDISABLE) {
+		ch->ch_xoff_sends++;
+		writeb(ch->ch_stopc, &ch->ch_cls_uart->txrx);
+        }
+}
+
+
+/* Inits UART */
+static void cls_uart_init(struct channel_t *ch)
+{
+	uchar lcrb = readb(&ch->ch_cls_uart->lcr);
+	uchar isr_fcr = 0;
+
+	writeb(0, &ch->ch_cls_uart->ier);
+
+	/*
+	 * The Enhanced Register Set may only be accessed when
+	 * the Line Control Register is set to 0xBFh.
+	 */
+	writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
+
+	isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
+	
+	/* Turn on Enhanced/Extended controls */
+	isr_fcr |= (UART_EXAR654_EFR_ECB);
+
+	writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
+
+	/* Write old LCR value back out, which turns enhanced access off */
+	writeb(lcrb, &ch->ch_cls_uart->lcr);
+
+        /* Clear out UART and FIFO */
+	readb(&ch->ch_cls_uart->txrx);
+
+	writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr);
+	udelay(10);
+
+	ch->ch_flags |= (CH_FIFO_ENABLED | CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+	readb(&ch->ch_cls_uart->lsr);
+	readb(&ch->ch_cls_uart->msr);
+}
+
+
+/*
+ * Turns off UART.
+ */
+static void cls_uart_off(struct channel_t *ch)
+{
+	writeb(0, &ch->ch_cls_uart->ier);
+}
+
+
+/*
+ * cls_get_uarts_bytes_left.
+ * Returns 0 is nothing left in the FIFO, returns 1 otherwise.
+ *
+ * The channel lock MUST be held by the calling function.
+ */
+static uint cls_get_uart_bytes_left(struct channel_t *ch)
+{
+	uchar left = 0;
+	uchar lsr = 0;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return 0;
+
+	lsr = readb(&ch->ch_cls_uart->lsr);
+
+	/* Determine whether the Transmitter is empty or not */
+	if (!(lsr & UART_LSR_TEMT)) {
+		if (ch->ch_flags & CH_TX_FIFO_EMPTY) {
+			tasklet_schedule(&ch->ch_bd->helper_tasklet);
+		}
+		left = 1;
+	}
+	else {
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		left = 0;
+	}
+
+	return left;
+}
+
+
+/*
+ * cls_send_break.
+ * Starts sending a break thru the UART.
+ *
+ * The channel lock MUST be held by the calling function.
+ */
+static void cls_send_break(struct channel_t *ch, int msecs)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * If we receive a time of 0, this means turn off the break.
+	 */
+	if (msecs == 0) {
+		/* Turn break off, and unset some variables */
+		if (ch->ch_flags & CH_BREAK_SENDING) {
+			uchar temp = readb(&ch->ch_cls_uart->lcr);
+			writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);
+			ch->ch_flags &= ~(CH_BREAK_SENDING);
+			ch->ch_stop_sending_break = 0;
+			DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
+		}
+		return;
+        }
+
+	/*
+	 * Set the time we should stop sending the break.
+	 * If we are already sending a break, toss away the existing
+	 * time to stop, and use this new value instead.
+	 */
+	ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs);
+
+	/* Tell the UART to start sending the break */
+	if (!(ch->ch_flags & CH_BREAK_SENDING)) {
+		uchar temp = readb(&ch->ch_cls_uart->lcr);
+		writeb((temp | UART_LCR_SBC), &ch->ch_cls_uart->lcr);
+		ch->ch_flags |= (CH_BREAK_SENDING);
+		DPR_IOCTL(("Port %d. Starting UART_LCR_SBC! start: %lx should end: %lx\n",
+			ch->ch_portnum, jiffies, ch->ch_stop_sending_break));
+	}
+}
+
+
+/*
+ * cls_send_immediate_char.
+ * Sends a specific character as soon as possible to the UART,
+ * jumping over any bytes that might be in the write queue.
+ *
+ * The channel lock MUST be held by the calling function.
+ */
+static void cls_send_immediate_char(struct channel_t *ch, unsigned char c)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	writeb(c, &ch->ch_cls_uart->txrx);
+}
+
+static void cls_vpd(struct board_t *brd) 
+{
+        ulong           vpdbase;        /* Start of io base of the card */
+        uchar           *re_map_vpdbase;/* Remapped memory of the card */
+	int i = 0;
+
+
+	vpdbase = pci_resource_start(brd->pdev, 3);
+
+	/* No VPD */
+	if (!vpdbase)
+		return;
+
+	re_map_vpdbase = ioremap(vpdbase, 0x400);
+
+	if (!re_map_vpdbase)
+		return;
+
+        /* Store the VPD into our buffer */
+        for (i = 0; i < 0x40; i++) {
+		brd->vpd[i] = readb(re_map_vpdbase + i);
+		printk("%x ", brd->vpd[i]);
+        }
+	printk("\n");
+
+	if (re_map_vpdbase)
+		iounmap(re_map_vpdbase);
+}
+
diff --git a/drivers/staging/dgnc/dgnc_cls.h b/drivers/staging/dgnc/dgnc_cls.h
new file mode 100644
index 0000000..dca5ea3
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_cls.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ */
+
+#ifndef __DGNC_CLS_H
+#define __DGNC_CLS_H
+
+#include "dgnc_types.h"
+
+
+/************************************************************************ 
+ * Per channel/port Classic UART structure				*
+ ************************************************************************
+ *		Base Structure Entries Usage Meanings to Host		*
+ *									*
+ *	W = read write		R = read only				* 
+ *			U = Unused.					*
+ ************************************************************************/
+
+struct cls_uart_struct {
+	volatile uchar txrx;		/* WR  RHR/THR - Holding Reg */
+	volatile uchar ier;		/* WR  IER - Interrupt Enable Reg */
+	volatile uchar isr_fcr;		/* WR  ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
+	volatile uchar lcr;		/* WR  LCR - Line Control Reg */
+	volatile uchar mcr;		/* WR  MCR - Modem Control Reg */
+	volatile uchar lsr;		/* WR  LSR - Line Status Reg */
+	volatile uchar msr;		/* WR  MSR - Modem Status Reg */
+	volatile uchar spr;		/* WR  SPR - Scratch Pad Reg */
+};
+
+/* Where to read the interrupt register (8bits) */
+#define	UART_CLASSIC_POLL_ADDR_OFFSET	0x40
+
+#define UART_EXAR654_ENHANCED_REGISTER_SET 0xBF
+
+#define UART_16654_FCR_TXTRIGGER_8	0x0
+#define UART_16654_FCR_TXTRIGGER_16	0x10
+#define UART_16654_FCR_TXTRIGGER_32	0x20
+#define UART_16654_FCR_TXTRIGGER_56	0x30
+
+#define UART_16654_FCR_RXTRIGGER_8	0x0
+#define UART_16654_FCR_RXTRIGGER_16	0x40
+#define UART_16654_FCR_RXTRIGGER_56	0x80
+#define UART_16654_FCR_RXTRIGGER_60     0xC0
+
+#define UART_IIR_XOFF			0x10	/* Received Xoff signal/Special character */
+#define UART_IIR_CTSRTS			0x20	/* Received CTS/RTS change of state */
+#define UART_IIR_RDI_TIMEOUT		0x0C    /* Receiver data TIMEOUT */
+
+/*
+ * These are the EXTENDED definitions for the Exar 654's Interrupt
+ * Enable Register.
+ */
+#define UART_EXAR654_EFR_ECB      0x10    /* Enhanced control bit */
+#define UART_EXAR654_EFR_IXON     0x2     /* Receiver compares Xon1/Xoff1 */
+#define UART_EXAR654_EFR_IXOFF    0x8     /* Transmit Xon1/Xoff1 */
+#define UART_EXAR654_EFR_RTSDTR   0x40    /* Auto RTS/DTR Flow Control Enable */
+#define UART_EXAR654_EFR_CTSDSR   0x80    /* Auto CTS/DSR Flow COntrol Enable */
+
+#define UART_EXAR654_XOFF_DETECT  0x1     /* Indicates whether chip saw an incoming XOFF char  */
+#define UART_EXAR654_XON_DETECT   0x2     /* Indicates whether chip saw an incoming XON char */
+
+#define UART_EXAR654_IER_XOFF     0x20    /* Xoff Interrupt Enable */
+#define UART_EXAR654_IER_RTSDTR   0x40    /* Output Interrupt Enable */
+#define UART_EXAR654_IER_CTSDSR   0x80    /* Input Interrupt Enable */
+
+/* 
+ * Our Global Variables
+ */
+extern struct board_ops dgnc_cls_ops;
+
+#endif
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
new file mode 100644
index 0000000..7c88de7
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -0,0 +1,1028 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *	Thank you.
+ *
+ * $Id: dgnc_driver.c,v 1.3 2011/06/23 12:47:35 markh Exp $
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+#include <linux/sched.h>
+#endif
+
+#include "dgnc_driver.h"
+#include "dgnc_pci.h"
+#include "dgnc_proc.h"
+#include "dpacompat.h"
+#include "dgnc_mgmt.h"
+#include "dgnc_tty.h"
+#include "dgnc_trace.h"
+#include "dgnc_cls.h"
+#include "dgnc_neo.h"
+#include "dgnc_sysfs.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Digi International, http://www.digi.com");
+MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
+MODULE_SUPPORTED_DEVICE("dgnc");
+
+/*
+ * insmod command line overrideable parameters
+ *
+ * NOTE: we use a set of macros to create the variables, which allows
+ * us to specify the variable type, name, initial value, and description.
+ */
+PARM_INT(debug,		0x00,		0644,	"Driver debugging level");
+PARM_INT(rawreadok,	1,		0644,	"Bypass flip buffers on input");
+PARM_INT(trcbuf_size,	0x100000,	0644, 	"Debugging trace buffer size.");
+
+/**************************************************************************
+ *
+ * protos for this file
+ *
+ */
+static int		dgnc_start(void);
+static int		dgnc_finalize_board_init(struct board_t *brd);
+static void		dgnc_init_globals(void);
+static int		dgnc_found_board(struct pci_dev *pdev, int id);
+static void		dgnc_cleanup_board(struct board_t *brd);
+static void		dgnc_poll_handler(ulong dummy);
+static int		dgnc_init_pci(void);
+static int		dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void		dgnc_remove_one(struct pci_dev *dev);
+static int		dgnc_probe1(struct pci_dev *pdev, int card_type);
+static void		dgnc_do_remap(struct board_t *brd);
+static void		dgnc_mbuf(struct board_t *brd, const char *fmt, ...);
+
+
+/* Driver load/unload functions */
+int		dgnc_init_module(void);
+void		dgnc_cleanup_module(void);
+
+module_init(dgnc_init_module);
+module_exit(dgnc_cleanup_module);
+
+
+/*
+ * File operations permitted on Control/Management major.
+ */
+static struct file_operations dgnc_BoardFops =
+{
+	.owner		=	THIS_MODULE,
+#ifdef HAVE_UNLOCKED_IOCTL
+        .unlocked_ioctl =  	dgnc_mgmt_ioctl,
+#else
+        .ioctl          =       dgnc_mgmt_ioctl,
+#endif
+	.open		=	dgnc_mgmt_open,
+	.release	=	dgnc_mgmt_close
+};
+
+
+/*
+ * Globals
+ */
+uint			dgnc_NumBoards;
+struct board_t		*dgnc_Board[MAXBOARDS];
+DEFINE_SPINLOCK(dgnc_global_lock);
+int			dgnc_driver_state = DRIVER_INITIALIZED;
+ulong			dgnc_poll_counter;
+uint			dgnc_Major;
+int			dgnc_poll_tick = 20;	/* Poll interval - 20 ms */
+
+/*
+ * Static vars.
+ */
+static uint		dgnc_Major_Control_Registered = FALSE;
+static uint		dgnc_driver_start = FALSE;
+
+static struct class *dgnc_class;
+
+/*
+ * Poller stuff
+ */
+static 			DEFINE_SPINLOCK(dgnc_poll_lock);	/* Poll scheduling lock */
+static ulong		dgnc_poll_time;				/* Time of next poll */
+static uint		dgnc_poll_stop;				/* Used to tell poller to stop */
+static struct timer_list dgnc_poll_timer;
+
+
+static struct pci_device_id dgnc_pci_tbl[] = {
+	{	DIGI_VID, PCI_DEVICE_CLASSIC_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	0 },
+	{	DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	1 },
+	{	DIGI_VID, PCI_DEVICE_CLASSIC_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	2 },
+	{	DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	3 },
+	{	DIGI_VID, PCI_DEVICE_NEO_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,		4 },
+	{	DIGI_VID, PCI_DEVICE_NEO_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,		5 },
+	{	DIGI_VID, PCI_DEVICE_NEO_2DB9_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	6 },
+	{	DIGI_VID, PCI_DEVICE_NEO_2DB9PRI_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	7 },
+	{	DIGI_VID, PCI_DEVICE_NEO_2RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	8 },
+	{	DIGI_VID, PCI_DEVICE_NEO_2RJ45PRI_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	9 },
+	{	DIGI_VID, PCI_DEVICE_NEO_1_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	10 },
+	{	DIGI_VID, PCI_DEVICE_NEO_1_422_485_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	11 },
+	{	DIGI_VID, PCI_DEVICE_NEO_2_422_485_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	12 },
+	{	DIGI_VID, PCI_DEVICE_NEO_EXPRESS_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	 13 },
+	{	DIGI_VID, PCI_DEVICE_NEO_EXPRESS_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	14 },
+	{	DIGI_VID, PCI_DEVICE_NEO_EXPRESS_4RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	15 },
+	{	DIGI_VID, PCI_DEVICE_NEO_EXPRESS_8RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	16 },
+	{0,}						/* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, dgnc_pci_tbl);
+
+struct board_id {
+	uchar *name;
+	uint maxports;
+	unsigned int is_pci_express;
+};
+
+static struct board_id dgnc_Ids[] =
+{
+	{	PCI_DEVICE_CLASSIC_4_PCI_NAME,		4,	0	},
+	{	PCI_DEVICE_CLASSIC_4_422_PCI_NAME,	4,	0	},
+	{	PCI_DEVICE_CLASSIC_8_PCI_NAME,		8,	0	},
+	{	PCI_DEVICE_CLASSIC_8_422_PCI_NAME,	8,	0	},
+	{	PCI_DEVICE_NEO_4_PCI_NAME,		4,	0	},
+	{	PCI_DEVICE_NEO_8_PCI_NAME,		8,	0	},
+	{	PCI_DEVICE_NEO_2DB9_PCI_NAME,		2,	0	},
+	{	PCI_DEVICE_NEO_2DB9PRI_PCI_NAME,	2,	0	},
+	{	PCI_DEVICE_NEO_2RJ45_PCI_NAME,		2,	0	},
+	{	PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME,	2,	0	},
+	{	PCI_DEVICE_NEO_1_422_PCI_NAME,		1,	0	},
+	{	PCI_DEVICE_NEO_1_422_485_PCI_NAME,	1,	0	},
+	{	PCI_DEVICE_NEO_2_422_485_PCI_NAME,	2,	0	},
+	{	PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME,	8,	1	},
+	{	PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME,	4,	1	},
+	{	PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME,	4,	1	},
+	{	PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME,	8,	1	},
+	{	NULL,					0,	0	}
+};
+
+static struct pci_driver dgnc_driver = {
+	.name		= "dgnc",
+	.probe		= dgnc_init_one,
+	.id_table       = dgnc_pci_tbl,
+	.remove		= dgnc_remove_one,
+};
+
+
+char *dgnc_state_text[] = {
+	"Board Failed",
+	"Board Found",
+	"Board READY",
+};
+
+char *dgnc_driver_state_text[] = {
+	"Driver Initialized",
+	"Driver Ready."
+};
+
+
+
+/************************************************************************
+ *
+ * Driver load/unload functions
+ *
+ ************************************************************************/
+
+
+/*
+ * init_module()
+ *
+ * Module load.  This is where it all starts.
+ */
+int dgnc_init_module(void)
+{
+	int rc = 0;
+
+	APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));
+
+	/*
+	 * Initialize global stuff
+	 */
+	rc = dgnc_start();
+
+	if (rc < 0) {
+		return(rc);
+	}
+
+	/*
+	 * Find and configure all the cards
+	 */
+	rc = dgnc_init_pci();
+
+	/*
+	 * If something went wrong in the scan, bail out of driver.
+	 */
+	if (rc < 0) {
+		/* Only unregister the pci driver if it was actually registered. */
+		if (dgnc_NumBoards)
+			pci_unregister_driver(&dgnc_driver);
+		else
+			printk("WARNING: dgnc driver load failed.  No Digi Neo or Classic boards found.\n");
+
+		dgnc_cleanup_module();
+	}
+	else {
+		dgnc_create_driver_sysfiles(&dgnc_driver);
+	}
+
+	DPR_INIT(("Finished init_module. Returning %d\n", rc));
+	return (rc);
+}
+
+
+/*
+ * Start of driver.
+ */
+static int dgnc_start(void)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	if (dgnc_driver_start == FALSE) {
+
+		dgnc_driver_start = TRUE;
+
+		/* make sure that the globals are init'd before we do anything else */
+		dgnc_init_globals();
+
+		dgnc_NumBoards = 0;
+
+		APR(("For the tools package or updated drivers please visit http://www.digi.com\n"));
+
+		/*
+		 * Register our base character device into the kernel.
+		 * This allows the download daemon to connect to the downld device
+		 * before any of the boards are init'ed.
+		 */
+		if (!dgnc_Major_Control_Registered) {
+			/*
+			 * Register management/dpa devices
+			 */
+			rc = register_chrdev(0, "dgnc", &dgnc_BoardFops);
+			if (rc <= 0) {
+				APR(("Can't register dgnc driver device (%d)\n", rc));
+				rc = -ENXIO;
+				return(rc);
+			}
+			dgnc_Major = rc;
+
+			dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+			device_create_drvdata(dgnc_class, NULL,
+				MKDEV(dgnc_Major, 0),
+				NULL, "dgnc_mgmt");
+#else
+                        device_create(dgnc_class, NULL,
+                                MKDEV(dgnc_Major, 0),
+                                NULL, "dgnc_mgmt");
+#endif
+
+			dgnc_Major_Control_Registered = TRUE;
+		}
+
+		/*
+		 * Register our basic stuff in /proc/dgnc
+		 */
+		dgnc_proc_register_basic_prescan();
+
+		/*
+		 * Init any global tty stuff.
+		 */
+		rc = dgnc_tty_preinit();
+
+		if (rc < 0) {
+			APR(("tty preinit - not enough memory (%d)\n", rc));
+			return(rc);
+		}
+
+		/* Start the poller */
+		DGNC_LOCK(dgnc_poll_lock, flags);
+		init_timer(&dgnc_poll_timer);
+		dgnc_poll_timer.function = dgnc_poll_handler;
+		dgnc_poll_timer.data = 0;
+		dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick);
+		dgnc_poll_timer.expires = dgnc_poll_time;
+		DGNC_UNLOCK(dgnc_poll_lock, flags);
+
+		add_timer(&dgnc_poll_timer);
+
+		dgnc_driver_state = DRIVER_READY;
+	}
+
+	return(rc);
+}
+
+/*
+ * Register pci driver, and return how many boards we have.
+ */
+static int dgnc_init_pci(void)
+{
+	return pci_register_driver(&dgnc_driver);
+}
+
+
+/* returns count (>= 0), or negative on error */
+static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{       
+	int rc;
+
+	/* wake up and enable device */
+	rc = pci_enable_device(pdev);
+
+	if (rc < 0) {
+		rc = -EIO;
+	} else {
+		rc = dgnc_probe1(pdev, ent->driver_data);
+		if (rc == 0) {
+			dgnc_NumBoards++;
+	                DPR_INIT(("Incrementing numboards to %d\n", dgnc_NumBoards));
+		}
+	}
+	return rc;
+}
+
+static int dgnc_probe1(struct pci_dev *pdev, int card_type)
+{
+	return dgnc_found_board(pdev, card_type);
+}
+
+
+static void dgnc_remove_one(struct pci_dev *dev)
+{
+	/* Do Nothing */
+}
+
+/*
+ * dgnc_cleanup_module()
+ *
+ * Module unload.  This is where it all ends.
+ */
+void dgnc_cleanup_module(void)
+{
+	int i;
+	ulong lock_flags;
+
+	DGNC_LOCK(dgnc_poll_lock, lock_flags);
+	dgnc_poll_stop = 1;
+	DGNC_UNLOCK(dgnc_poll_lock, lock_flags);
+
+	/* Turn off poller right away. */
+	del_timer_sync(&dgnc_poll_timer);
+
+	dgnc_proc_unregister_all();
+
+	dgnc_remove_driver_sysfiles(&dgnc_driver);
+
+	if (dgnc_Major_Control_Registered) {
+		device_destroy(dgnc_class, MKDEV(dgnc_Major, 0));
+		class_destroy(dgnc_class);
+		unregister_chrdev(dgnc_Major, "dgnc");
+	}
+
+	for (i = 0; i < dgnc_NumBoards; ++i) {
+		dgnc_remove_ports_sysfiles(dgnc_Board[i]);
+		dgnc_tty_uninit(dgnc_Board[i]);
+		dgnc_cleanup_board(dgnc_Board[i]);
+	}
+
+	dgnc_tty_post_uninit();
+
+#if defined(DGNC_TRACER)
+	/* last thing, make sure we release the tracebuffer */
+	dgnc_tracer_free();
+#endif
+	if (dgnc_NumBoards)
+		pci_unregister_driver(&dgnc_driver);
+}
+
+
+/*
+ * dgnc_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void dgnc_cleanup_board(struct board_t *brd)
+{
+	int i = 0;
+
+        if(!brd || brd->magic != DGNC_BOARD_MAGIC)
+                return;
+
+	switch (brd->device) {
+	case PCI_DEVICE_CLASSIC_4_DID:
+	case PCI_DEVICE_CLASSIC_8_DID:
+	case PCI_DEVICE_CLASSIC_4_422_DID:
+	case PCI_DEVICE_CLASSIC_8_422_DID:
+
+		/* Tell card not to interrupt anymore. */
+		outb(0, brd->iobase + 0x4c);
+		break;
+
+	default:
+		break;
+	}
+
+	if (brd->irq)
+		free_irq(brd->irq, brd);
+
+	tasklet_kill(&brd->helper_tasklet);
+
+	if (brd->re_map_membase) {
+		iounmap(brd->re_map_membase);
+		brd->re_map_membase = NULL;
+	}
+
+	if (brd->msgbuf_head) {
+		unsigned long flags;
+
+		DGNC_LOCK(dgnc_global_lock, flags);
+		brd->msgbuf = NULL;
+		printk(brd->msgbuf_head);
+		kfree(brd->msgbuf_head);
+		brd->msgbuf_head = NULL;
+		DGNC_UNLOCK(dgnc_global_lock, flags);
+        }
+
+	/* Free all allocated channels structs */
+	for (i = 0; i < MAXPORTS ; i++) {
+		if (brd->channels[i]) {
+			if (brd->channels[i]->ch_rqueue)
+				kfree(brd->channels[i]->ch_rqueue);
+			if (brd->channels[i]->ch_equeue)
+				kfree(brd->channels[i]->ch_equeue);
+			if (brd->channels[i]->ch_wqueue)
+				kfree(brd->channels[i]->ch_wqueue);
+
+			kfree(brd->channels[i]);
+			brd->channels[i] = NULL;
+		}
+	}
+
+	if (brd->flipbuf)
+		kfree(brd->flipbuf);
+
+	dgnc_Board[brd->boardnum] = NULL;
+
+        kfree(brd);
+}
+
+
+/*
+ * dgnc_found_board()
+ *
+ * A board has been found, init it.
+ */
+static int dgnc_found_board(struct pci_dev *pdev, int id)
+{
+        struct board_t *brd;
+	unsigned int pci_irq;
+	int i = 0;
+	int rc = 0;
+	unsigned long flags;
+
+        /* get the board structure and prep it */
+        brd = dgnc_Board[dgnc_NumBoards] =
+        (struct board_t *) dgnc_driver_kzmalloc(sizeof(struct board_t), GFP_KERNEL);
+	if (!brd) {
+		APR(("memory allocation for board structure failed\n"));
+		return(-ENOMEM);
+	}
+
+        /* make a temporary message buffer for the boot messages */
+        brd->msgbuf = brd->msgbuf_head =
+                (char *) dgnc_driver_kzmalloc(sizeof(char) * 8192, GFP_KERNEL);
+        if (!brd->msgbuf) {
+		kfree(brd);
+		APR(("memory allocation for board msgbuf failed\n"));
+		return(-ENOMEM);
+        }
+        
+	/* store the info for the board we've found */
+	brd->magic = DGNC_BOARD_MAGIC;
+	brd->boardnum = dgnc_NumBoards;
+	brd->vendor = dgnc_pci_tbl[id].vendor;
+	brd->device = dgnc_pci_tbl[id].device;
+	brd->pdev = pdev;
+	brd->pci_bus = pdev->bus->number;
+	brd->pci_slot = PCI_SLOT(pdev->devfn);
+	brd->name = dgnc_Ids[id].name;
+	brd->maxports = dgnc_Ids[id].maxports;
+	if (dgnc_Ids[i].is_pci_express)
+		brd->bd_flags |= BD_IS_PCI_EXPRESS;
+	brd->dpastatus = BD_NOFEP;
+	init_waitqueue_head(&brd->state_wait);
+
+	DGNC_SPINLOCK_INIT(brd->bd_lock);
+	DGNC_SPINLOCK_INIT(brd->bd_intr_lock);
+
+	brd->state		= BOARD_FOUND;
+
+	for (i = 0; i < MAXPORTS; i++) {
+		brd->channels[i] = NULL;
+	}
+
+	/* store which card & revision we have */
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+
+	pci_irq = pdev->irq;
+	brd->irq = pci_irq;
+
+
+	switch(brd->device) {
+
+	case PCI_DEVICE_CLASSIC_4_DID:
+	case PCI_DEVICE_CLASSIC_8_DID:
+	case PCI_DEVICE_CLASSIC_4_422_DID:
+	case PCI_DEVICE_CLASSIC_8_422_DID:
+
+		brd->dpatype = T_CLASSIC | T_PCIBUS;
+
+                DPR_INIT(("dgnc_found_board - Classic.\n"));
+
+		/*
+		 * For PCI ClassicBoards
+		 * PCI Local Address (i.e. "resource" number) space
+		 * 0        PLX Memory Mapped Config
+		 * 1        PLX I/O Mapped Config
+		 * 2        I/O Mapped UARTs and Status   
+		 * 3        Memory Mapped VPD
+		 * 4        Memory Mapped UARTs and Status
+		 */
+
+
+		/* get the PCI Base Address Registers */
+		brd->membase = pci_resource_start(pdev, 4);
+
+		if (!brd->membase) {
+			APR(("card has no PCI IO resources, failing board.\n"));
+			return -ENODEV;
+		}
+
+		brd->membase_end = pci_resource_end(pdev, 4);
+
+		if (brd->membase & 1)
+			brd->membase &= ~3;
+		else
+			brd->membase &= ~15;
+
+		brd->iobase     = pci_resource_start(pdev, 1);
+		brd->iobase_end = pci_resource_end(pdev, 1);
+ 		brd->iobase     = ((unsigned int) (brd->iobase)) & 0xFFFE;
+
+		/* Assign the board_ops struct */
+		brd->bd_ops = &dgnc_cls_ops;
+
+		brd->bd_uart_offset = 0x8;
+		brd->bd_dividend = 921600;
+
+		dgnc_do_remap(brd);
+
+		/* Get and store the board VPD, if it exists */
+		brd->bd_ops->vpd(brd);
+
+		/*
+		 * Enable Local Interrupt 1		  (0x1),
+		 * Local Interrupt 1 Polarity Active high (0x2),
+		 * Enable PCI interrupt			  (0x40)
+		 */
+		outb(0x43, brd->iobase + 0x4c);
+
+		break;
+
+
+	case PCI_DEVICE_NEO_4_DID:
+	case PCI_DEVICE_NEO_8_DID:
+	case PCI_DEVICE_NEO_2DB9_DID:
+	case PCI_DEVICE_NEO_2DB9PRI_DID:
+	case PCI_DEVICE_NEO_2RJ45_DID:
+	case PCI_DEVICE_NEO_2RJ45PRI_DID:
+	case PCI_DEVICE_NEO_1_422_DID:
+	case PCI_DEVICE_NEO_1_422_485_DID:
+	case PCI_DEVICE_NEO_2_422_485_DID:
+	case PCI_DEVICE_NEO_EXPRESS_8_DID:
+	case PCI_DEVICE_NEO_EXPRESS_4_DID:
+	case PCI_DEVICE_NEO_EXPRESS_4RJ45_DID:
+	case PCI_DEVICE_NEO_EXPRESS_8RJ45_DID:
+
+		/*
+		 * This chip is set up 100% when we get to it.
+		 * No need to enable global interrupts or anything. 
+		 */
+		if (brd->bd_flags & BD_IS_PCI_EXPRESS)
+			brd->dpatype = T_NEO_EXPRESS | T_PCIBUS;
+		else
+			brd->dpatype = T_NEO | T_PCIBUS;
+
+                DPR_INIT(("dgnc_found_board - NEO.\n"));
+
+		/* get the PCI Base Address Registers */
+		brd->membase     = pci_resource_start(pdev, 0);
+		brd->membase_end = pci_resource_end(pdev, 0);
+
+		if (brd->membase & 1)
+			brd->membase &= ~3;
+		else
+			brd->membase &= ~15;
+
+		/* Assign the board_ops struct */
+		brd->bd_ops = &dgnc_neo_ops;
+
+		brd->bd_uart_offset = 0x200;
+		brd->bd_dividend = 921600;
+
+		dgnc_do_remap(brd);
+
+		if (brd->re_map_membase) {
+
+			/* After remap is complete, we need to read and store the dvid */
+			brd->dvid = readb(brd->re_map_membase + 0x8D);
+
+			/* Get and store the board VPD, if it exists */
+			brd->bd_ops->vpd(brd);
+		}
+		break;
+
+	default:
+		APR(("Did not find any compatible Neo or Classic PCI boards in system.\n"));
+		return (-ENXIO);
+
+	}
+
+	/*
+	 * Do tty device initialization.
+	 */
+
+	rc = dgnc_tty_register(brd);
+	if (rc < 0) {
+		dgnc_tty_uninit(brd);
+		APR(("Can't register tty devices (%d)\n", rc));
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+		goto failed;
+	}
+
+	rc = dgnc_finalize_board_init(brd);
+	if (rc < 0) {
+		APR(("Can't finalize board init (%d)\n", rc));
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+
+		goto failed;
+	}
+
+	rc = dgnc_tty_init(brd);
+	if (rc < 0) {
+		dgnc_tty_uninit(brd);
+		APR(("Can't init tty devices (%d)\n", rc));
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+
+		goto failed;
+	}
+
+	brd->state = BOARD_READY;
+	brd->dpastatus = BD_RUNNING;
+
+	dgnc_create_ports_sysfiles(brd);
+
+	/* init our poll helper tasklet */
+	tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, (unsigned long) brd);
+
+	 /* Log the information about the board */
+	dgnc_mbuf(brd, DRVSTR": board %d: %s (rev %d), irq %d\n",
+		dgnc_NumBoards, brd->name, brd->rev, brd->irq);
+
+	DPR_INIT(("dgnc_scan(%d) - printing out the msgbuf\n", i));
+	DGNC_LOCK(dgnc_global_lock, flags);
+	brd->msgbuf = NULL;
+	printk(brd->msgbuf_head);
+	kfree(brd->msgbuf_head);
+	brd->msgbuf_head = NULL;
+	DGNC_UNLOCK(dgnc_global_lock, flags);
+
+	/*
+	 * allocate flip buffer for board.
+	 *
+	 * Okay to malloc with GFP_KERNEL, we are not at interrupt
+	 * context, and there are no locks held.
+	 */
+	brd->flipbuf = dgnc_driver_kzmalloc(MYFLIPLEN, GFP_KERNEL);
+
+	dgnc_proc_register_basic_postscan(dgnc_NumBoards);
+
+	wake_up_interruptible(&brd->state_wait);
+
+        return(0);
+
+failed:
+
+	return (-ENXIO);
+
+}
+
+
+static int dgnc_finalize_board_init(struct board_t *brd) {
+	int rc = 0;
+
+        DPR_INIT(("dgnc_finalize_board_init() - start\n"));
+
+	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
+                return(-ENODEV);
+
+        DPR_INIT(("dgnc_finalize_board_init() - start #2\n"));
+
+	if (brd->irq) {
+		rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "DGNC", brd);
+
+		if (rc) {
+			printk("Failed to hook IRQ %d\n",brd->irq);
+			brd->state = BOARD_FAILED;
+			brd->dpastatus = BD_NOFEP;
+			rc = -ENODEV;
+		} else {
+			DPR_INIT(("Requested and received usage of IRQ %d\n", brd->irq));
+		}
+	}
+	return(rc);
+}
+
+/*
+ * Remap PCI memory.
+ */
+static void dgnc_do_remap(struct board_t *brd)
+{
+
+	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	brd->re_map_membase = ioremap(brd->membase, 0x1000);
+
+	DPR_INIT(("remapped mem: 0x%p\n", brd->re_map_membase));
+}
+
+
+/*****************************************************************************
+*
+* Function:
+*                                       
+*    dgnc_poll_handler
+*
+* Author:
+*
+*    Scott H Kilau
+*       
+* Parameters:
+*
+*    dummy -- ignored                    
+*
+* Return Values:
+*
+*    none
+*
+* Description:   
+*                                       
+*    As each timer expires, it determines (a) whether the "transmit"
+*    waiter needs to be woken up, and (b) whether the poller needs to
+*    be rescheduled.
+*
+******************************************************************************/
+
+static void dgnc_poll_handler(ulong dummy)
+{
+        struct board_t *brd;
+        unsigned long lock_flags;
+	int i;
+	unsigned long new_time;
+
+	dgnc_poll_counter++;
+
+	/*
+	 * Do not start the board state machine until
+	 * driver tells us its up and running, and has
+	 * everything it needs.
+	 */
+	if (dgnc_driver_state != DRIVER_READY) {
+		goto schedule_poller;
+	}
+
+	/* Go thru each board, kicking off a tasklet for each if needed */
+	for (i = 0; i < dgnc_NumBoards; i++) {
+		brd = dgnc_Board[i];
+
+		DGNC_LOCK(brd->bd_lock, lock_flags);
+
+		/* If board is in a failed state, don't bother scheduling a tasklet */
+		if (brd->state == BOARD_FAILED) {
+			DGNC_UNLOCK(brd->bd_lock, lock_flags);
+			continue;
+		}
+
+		/* Schedule a poll helper task */
+		tasklet_schedule(&brd->helper_tasklet);
+
+		DGNC_UNLOCK(brd->bd_lock, lock_flags);
+	}
+
+schedule_poller:
+
+	/*
+	 * Schedule ourself back at the nominal wakeup interval.
+	 */
+	DGNC_LOCK(dgnc_poll_lock, lock_flags);
+	dgnc_poll_time += dgnc_jiffies_from_ms(dgnc_poll_tick);
+
+	new_time = dgnc_poll_time - jiffies;
+
+	if ((ulong) new_time >= 2 * dgnc_poll_tick) {
+		dgnc_poll_time = jiffies +  dgnc_jiffies_from_ms(dgnc_poll_tick);
+	}
+
+	init_timer(&dgnc_poll_timer);
+	dgnc_poll_timer.function = dgnc_poll_handler;
+	dgnc_poll_timer.data = 0;
+	dgnc_poll_timer.expires = dgnc_poll_time;
+	DGNC_UNLOCK(dgnc_poll_lock, lock_flags);
+
+	if (!dgnc_poll_stop)
+		add_timer(&dgnc_poll_timer);
+}
+
+/*
+ * dgnc_init_globals()
+ *
+ * This is where we initialize the globals from the static insmod
+ * configuration variables.  These are declared near the head of
+ * this file.
+ */
+static void dgnc_init_globals(void)
+{
+	int i = 0;
+
+	dgnc_rawreadok		= rawreadok;
+        dgnc_trcbuf_size	= trcbuf_size;
+	dgnc_debug		= debug;
+
+	for (i = 0; i < MAXBOARDS; i++) {
+		dgnc_Board[i] = NULL;
+	}
+
+	init_timer(&dgnc_poll_timer);
+}
+
+
+/************************************************************************
+ *
+ * Utility functions
+ *
+ ************************************************************************/
+
+
+/*
+ * dgnc_driver_kzmalloc()
+ *
+ * Malloc and clear memory,
+ */
+void *dgnc_driver_kzmalloc(size_t size, int priority)
+{
+ 	void *p = kmalloc(size, priority);
+	if(p)
+		memset(p, 0, size);
+	return(p);
+}
+
+
+/*
+ * dgnc_mbuf()
+ *
+ * Used to print to the message buffer during board init.
+ */
+static void dgnc_mbuf(struct board_t *brd, const char *fmt, ...) {
+	va_list		ap;
+	char		buf[1024];
+	int		i;
+	unsigned long	flags;
+
+	DGNC_LOCK(dgnc_global_lock, flags);
+
+	/* Format buf using fmt and arguments contained in ap. */
+	va_start(ap, fmt);
+	i = vsprintf(buf, fmt,  ap);
+	va_end(ap);
+
+	DPR((buf));
+
+	if (!brd || !brd->msgbuf) {
+		printk(buf);
+		DGNC_UNLOCK(dgnc_global_lock, flags);
+		return;
+	}
+
+	memcpy(brd->msgbuf, buf, strlen(buf));
+	brd->msgbuf += strlen(buf);
+	*brd->msgbuf = (char) NULL;
+
+	DGNC_UNLOCK(dgnc_global_lock, flags);
+}
+
+
+/*
+ * dgnc_ms_sleep()
+ *
+ * Put the driver to sleep for x ms's
+ *
+ * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
+ */
+int dgnc_ms_sleep(ulong ms)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((ms * HZ) / 1000);
+	return (signal_pending(current));
+}
+
+
+
+/*
+ *      dgnc_ioctl_name() : Returns a text version of each ioctl value.
+ */
+char *dgnc_ioctl_name(int cmd)
+{
+	switch(cmd) {
+
+	case TCGETA:		return("TCGETA");
+	case TCGETS:		return("TCGETS");
+	case TCSETA:		return("TCSETA");
+	case TCSETS:		return("TCSETS");
+	case TCSETAW:		return("TCSETAW");
+	case TCSETSW:		return("TCSETSW");
+	case TCSETAF:		return("TCSETAF");
+	case TCSETSF:		return("TCSETSF");
+	case TCSBRK:		return("TCSBRK");
+	case TCXONC:		return("TCXONC");
+	case TCFLSH:		return("TCFLSH");
+	case TIOCGSID:		return("TIOCGSID");
+
+	case TIOCGETD:		return("TIOCGETD");
+	case TIOCSETD:		return("TIOCSETD");
+	case TIOCGWINSZ:	return("TIOCGWINSZ");
+	case TIOCSWINSZ:	return("TIOCSWINSZ");
+
+	case TIOCMGET:		return("TIOCMGET");
+	case TIOCMSET:		return("TIOCMSET");
+	case TIOCMBIS:		return("TIOCMBIS");
+	case TIOCMBIC:		return("TIOCMBIC");
+
+	/* from digi.h */
+	case DIGI_SETA:		return("DIGI_SETA");
+	case DIGI_SETAW:	return("DIGI_SETAW");
+	case DIGI_SETAF:	return("DIGI_SETAF");
+	case DIGI_SETFLOW:	return("DIGI_SETFLOW");
+	case DIGI_SETAFLOW:	return("DIGI_SETAFLOW");
+	case DIGI_GETFLOW:	return("DIGI_GETFLOW");
+	case DIGI_GETAFLOW:	return("DIGI_GETAFLOW");
+	case DIGI_GETA:		return("DIGI_GETA");
+	case DIGI_GEDELAY:	return("DIGI_GEDELAY");
+	case DIGI_SEDELAY:	return("DIGI_SEDELAY");
+	case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
+	case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
+	case TIOCMODG:		return("TIOCMODG");
+	case TIOCMODS:		return("TIOCMODS");
+	case TIOCSDTR:		return("TIOCSDTR");
+	case TIOCCDTR:		return("TIOCCDTR");
+
+	default:		return("unknown");
+	}
+}
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
new file mode 100644
index 0000000..334faae
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -0,0 +1,565 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *************************************************************************
+ *
+ * Driver includes
+ *
+ *************************************************************************/
+
+#ifndef __DGNC_DRIVER_H
+#define __DGNC_DRIVER_H
+
+#include <linux/types.h>	/* To pick up the varions Linux types */
+#include <linux/tty.h>          /* To pick up the various tty structs/defines */
+#include <linux/interrupt.h>	/* For irqreturn_t type */
+
+#include "dgnc_types.h"		/* Additional types needed by the Digi header files */
+#include "digi.h"		/* Digi specific ioctl header */  
+#include "dgnc_kcompat.h"	/* Kernel 2.4/2.6 compat includes */
+#include "dgnc_sysfs.h"		/* Support for SYSFS */
+
+/*************************************************************************
+ *
+ * Driver defines
+ *
+ *************************************************************************/
+
+/*
+ * Driver identification, error and debugging statments
+ *
+ * In theory, you can change all occurances of "digi" in the next
+ * three lines, and the driver printk's will all automagically change.
+ *
+ * APR((fmt, args, ...));	Always prints message
+ * DPR((fmt, args, ...));	Only prints if DGNC_TRACER is defined at
+ *				  compile time and dgnc_debug!=0
+ */
+#define	PROCSTR		"dgnc"			/* /proc entries	 */
+#define	DEVSTR		"/dev/dg/dgnc"		/* /dev entries		 */
+#define	DRVSTR		"dgnc"			/* Driver name string 
+						 * displayed by APR	 */
+#define	APR(args)	do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
+			   } while (0)
+#define	RAPR(args)	do { PRINTF_TO_KMEM(args); printk args; } while (0)
+
+#define TRC_TO_CONSOLE 1
+
+/*
+ * Debugging levels can be set using debug insmod variable
+ * They can also be compiled out completely.
+ */
+
+#define	DBG_INIT		(dgnc_debug & 0x01)
+#define	DBG_BASIC		(dgnc_debug & 0x02)
+#define	DBG_CORE		(dgnc_debug & 0x04)
+
+#define	DBG_OPEN		(dgnc_debug & 0x08)
+#define	DBG_CLOSE		(dgnc_debug & 0x10)
+#define	DBG_READ		(dgnc_debug & 0x20)
+#define	DBG_WRITE		(dgnc_debug & 0x40)
+
+#define	DBG_IOCTL		(dgnc_debug & 0x80)
+
+#define	DBG_PROC		(dgnc_debug & 0x100)
+#define	DBG_PARAM		(dgnc_debug & 0x200)
+#define	DBG_PSCAN		(dgnc_debug & 0x400)
+#define	DBG_EVENT		(dgnc_debug & 0x800)
+
+#define	DBG_DRAIN		(dgnc_debug & 0x1000)
+#define	DBG_MSIGS		(dgnc_debug & 0x2000)
+
+#define	DBG_MGMT		(dgnc_debug & 0x4000)
+#define	DBG_INTR		(dgnc_debug & 0x8000)
+
+#define	DBG_CARR		(dgnc_debug & 0x10000)
+
+
+#if defined(DGNC_TRACER)
+
+# if defined(TRC_TO_KMEM)
+/* Choose one: */
+#  define TRC_ON_OVERFLOW_WRAP_AROUND
+#  undef  TRC_ON_OVERFLOW_SHIFT_BUFFER
+# endif //TRC_TO_KMEM
+
+# define TRC_MAXMSG		1024
+# define TRC_OVERFLOW		"(OVERFLOW)"
+# define TRC_DTRC		"/usr/bin/dtrc"
+
+#if defined TRC_TO_CONSOLE
+#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
+#else //!defined TRACE_TO_CONSOLE
+#define PRINTF_TO_CONSOLE(args)
+#endif
+
+#if defined TRC_TO_KMEM
+#define PRINTF_TO_KMEM(args) dgnc_tracef args 
+#else //!defined TRC_TO_KMEM
+#define PRINTF_TO_KMEM(args)
+#endif
+
+#define	TRC(args)	{ PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
+
+# define DPR_INIT(ARGS)		if (DBG_INIT) TRC(ARGS)
+# define DPR_BASIC(ARGS)	if (DBG_BASIC) TRC(ARGS)
+# define DPR_CORE(ARGS)		if (DBG_CORE) TRC(ARGS)
+# define DPR_OPEN(ARGS)		if (DBG_OPEN)  TRC(ARGS)
+# define DPR_CLOSE(ARGS)	if (DBG_CLOSE)  TRC(ARGS)
+# define DPR_READ(ARGS)		if (DBG_READ)  TRC(ARGS)
+# define DPR_WRITE(ARGS)	if (DBG_WRITE) TRC(ARGS)
+# define DPR_IOCTL(ARGS)	if (DBG_IOCTL) TRC(ARGS)
+# define DPR_PROC(ARGS)		if (DBG_PROC)  TRC(ARGS)
+# define DPR_PARAM(ARGS)	if (DBG_PARAM)  TRC(ARGS)
+# define DPR_PSCAN(ARGS)	if (DBG_PSCAN)  TRC(ARGS)
+# define DPR_EVENT(ARGS)	if (DBG_EVENT)  TRC(ARGS)
+# define DPR_DRAIN(ARGS)	if (DBG_DRAIN)  TRC(ARGS)
+# define DPR_CARR(ARGS)		if (DBG_CARR)  TRC(ARGS)
+# define DPR_MGMT(ARGS)		if (DBG_MGMT)  TRC(ARGS)
+# define DPR_INTR(ARGS)		if (DBG_INTR)  TRC(ARGS)
+# define DPR_MSIGS(ARGS)	if (DBG_MSIGS)  TRC(ARGS)
+
+# define DPR(ARGS)		if (dgnc_debug) TRC(ARGS)
+# define P(X)			dgnc_tracef(#X "=%p\n", X)
+# define X(X)			dgnc_tracef(#X "=%x\n", X)
+
+#else//!defined DGNC_TRACER
+
+#define PRINTF_TO_KMEM(args)
+# define TRC(ARGS)
+# define DPR_INIT(ARGS)
+# define DPR_BASIC(ARGS)
+# define DPR_CORE(ARGS)
+# define DPR_OPEN(ARGS)
+# define DPR_CLOSE(ARGS)
+# define DPR_READ(ARGS)
+# define DPR_WRITE(ARGS)
+# define DPR_IOCTL(ARGS)
+# define DPR_PROC(ARGS)
+# define DPR_PARAM(ARGS)
+# define DPR_PSCAN(ARGS)
+# define DPR_EVENT(ARGS)
+# define DPR_DRAIN(ARGS)
+# define DPR_CARR(ARGS)
+# define DPR_MGMT(ARGS)
+# define DPR_INTR(ARGS)
+# define DPR_MSIGS(ARGS)
+
+# define DPR(args)
+
+#endif//DGNC_TRACER
+
+/* Number of boards we support at once. */
+#define	MAXBOARDS	20
+#define	MAXPORTS	8
+#define MAXTTYNAMELEN	200
+
+/* Our 3 magic numbers for our board, channel and unit structs */
+#define DGNC_BOARD_MAGIC	0x5c6df104
+#define DGNC_CHANNEL_MAGIC	0x6c6df104
+#define DGNC_UNIT_MAGIC		0x7c6df104
+
+/* Serial port types */
+#define DGNC_SERIAL		0
+#define DGNC_PRINT		1
+
+#define	SERIAL_TYPE_NORMAL	1
+
+#define PORT_NUM(dev)	((dev) & 0x7f)
+#define IS_PRINT(dev)	(((dev) & 0xff) >= 0x80)
+
+/* MAX number of stop characters we will send when our read queue is getting full */
+#define MAX_STOPS_SENT 5
+
+/* 4 extra for alignment play space */
+#define WRITEBUFLEN		((4096) + 4)
+#define MYFLIPLEN		N_TTY_BUF_SIZE
+
+#define dgnc_jiffies_from_ms(a) (((a) * HZ) / 1000)
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.  This is the same structure that is defined
+ * as the default in tty_io.c with the same settings overriden as in serial.c
+ *
+ * In short, this should match the internal serial ports' defaults.
+ */
+#define	DEFAULT_IFLAGS	(ICRNL | IXON)
+#define	DEFAULT_OFLAGS	(OPOST | ONLCR)
+#define	DEFAULT_CFLAGS	(B9600 | CS8 | CREAD | HUPCL | CLOCAL)
+#define	DEFAULT_LFLAGS	(ISIG | ICANON | ECHO | ECHOE | ECHOK | \
+			ECHOCTL | ECHOKE | IEXTEN)
+
+#ifndef _POSIX_VDISABLE
+#define   _POSIX_VDISABLE '\0'
+#endif
+
+#define SNIFF_MAX	65536		/* Sniff buffer size (2^n) */
+#define SNIFF_MASK	(SNIFF_MAX - 1)	/* Sniff wrap mask */
+
+/*
+ * Lock function/defines.
+ * Makes spotting lock/unlock locations easier.
+ */
+# define DGNC_SPINLOCK_INIT(x)		spin_lock_init(&(x))
+# define DGNC_LOCK(x,y)			spin_lock_irqsave(&(x), y)
+# define DGNC_UNLOCK(x,y)		spin_unlock_irqrestore(&(x), y)
+
+/*
+ * All the possible states the driver can be while being loaded.
+ */
+enum {
+	DRIVER_INITIALIZED = 0,
+	DRIVER_READY
+};
+
+/*
+ * All the possible states the board can be while booting up.
+ */
+enum {
+	BOARD_FAILED = 0,
+	BOARD_FOUND,
+	BOARD_READY
+};
+
+
+/*************************************************************************
+ *
+ * Structures and closely related defines.
+ *
+ *************************************************************************/
+
+struct board_t;
+struct channel_t;
+
+/************************************************************************
+ * Per board operations structure                                       *
+ ************************************************************************/
+struct board_ops {
+	void (*tasklet) (unsigned long data);
+	irqreturn_t (*intr) (int irq, void *voidbrd);
+	void (*uart_init) (struct channel_t *ch);
+	void (*uart_off) (struct channel_t *ch);
+	int  (*drain) (struct tty_struct *tty, uint seconds);
+	void (*param) (struct tty_struct *tty);
+	void (*vpd) (struct board_t *brd);
+	void (*assert_modem_signals) (struct channel_t *ch);
+	void (*flush_uart_write) (struct channel_t *ch);
+	void (*flush_uart_read) (struct channel_t *ch);
+	void (*disable_receiver) (struct channel_t *ch);
+	void (*enable_receiver) (struct channel_t *ch);
+	void (*send_break) (struct channel_t *ch, int);
+	void (*send_start_character) (struct channel_t *ch);
+	void (*send_stop_character) (struct channel_t *ch);
+	void (*copy_data_from_queue_to_uart) (struct channel_t *ch);
+	uint (*get_uart_bytes_left) (struct channel_t *ch);
+	void (*send_immediate_char) (struct channel_t *ch, unsigned char);
+};
+
+/************************************************************************ 
+ * Device flag definitions for bd_flags.
+ ************************************************************************/
+#define BD_IS_PCI_EXPRESS     0x0001          /* Is a PCI Express board */
+
+
+/*
+ *	Per-board information
+ */
+struct board_t
+{
+	int		magic;		/* Board Magic number.  */
+	int		boardnum;	/* Board number: 0-32 */
+
+	int		type;		/* Type of board */
+	char		*name;		/* Product Name */
+	struct pci_dev	*pdev;		/* Pointer to the pci_dev struct */
+	unsigned long	bd_flags;	/* Board flags */
+	u16		vendor;		/* PCI vendor ID */
+	u16		device;		/* PCI device ID */
+	u16		subvendor;	/* PCI subsystem vendor ID */
+	u16		subdevice;	/* PCI subsystem device ID */
+	uchar		rev;		/* PCI revision ID */
+	uint		pci_bus;	/* PCI bus value */
+	uint		pci_slot;	/* PCI slot value */
+	uint		maxports;	/* MAX ports this board can handle */
+	uchar		dvid;		/* Board specific device id */
+	uchar		vpd[128];	/* VPD of board, if found */
+	uchar		serial_num[20];	/* Serial number of board, if found in VPD */
+
+	spinlock_t	bd_lock;	/* Used to protect board */
+
+	spinlock_t	bd_intr_lock;	/* Used to protect the poller tasklet and
+					 * the interrupt routine from each other.
+					 */
+
+	uint		state;		/* State of card. */
+	wait_queue_head_t state_wait;	/* Place to sleep on for state change */
+
+	struct		tasklet_struct helper_tasklet; /* Poll helper tasklet */
+
+	uint		nasync;		/* Number of ports on card */
+
+	uint		irq;		/* Interrupt request number */
+	ulong		intr_count;	/* Count of interrupts */
+	ulong		intr_modem;	/* Count of interrupts */
+	ulong		intr_tx;	/* Count of interrupts */
+	ulong		intr_rx;	/* Count of interrupts */
+
+	ulong		membase;	/* Start of base memory of the card */
+	ulong		membase_end;	/* End of base memory of the card */
+
+	uchar		*re_map_membase;/* Remapped memory of the card */
+
+	ulong		iobase;		/* Start of io base of the card */
+	ulong		iobase_end;	/* End of io base of the card */
+
+	uint		bd_uart_offset;	/* Space between each UART */
+
+	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
+
+	struct tty_driver	SerialDriver;
+	char		SerialName[200];
+	struct tty_driver	PrintDriver;
+	char		PrintName[200];
+
+	uint		dgnc_Major_Serial_Registered;
+	uint		dgnc_Major_TransparentPrint_Registered;
+
+	uint		dgnc_Serial_Major;
+	uint		dgnc_TransparentPrint_Major;
+
+	uint		TtyRefCnt;
+
+	char		*flipbuf;	/* Our flip buffer, alloced if board is found */
+
+	u16		dpatype;	/* The board "type", as defined by DPA */
+	u16		dpastatus;	/* The board "status", as defined by DPA */
+
+	/*
+	 *	Mgmt data.
+	 */
+        char		*msgbuf_head;
+        char		*msgbuf;
+
+	uint		bd_dividend;	/* Board/UARTs specific dividend */
+
+	struct board_ops *bd_ops;
+
+	/* /proc/<board> entries */
+	struct proc_dir_entry *proc_entry_pointer;
+	struct dgnc_proc_entry *dgnc_board_table;
+
+};
+
+
+/************************************************************************ 
+ * Unit flag definitions for un_flags.
+ ************************************************************************/
+#define UN_ISOPEN	0x0001		/* Device is open		*/
+#define UN_CLOSING	0x0002		/* Line is being closed		*/
+#define UN_IMM		0x0004		/* Service immediately		*/
+#define UN_BUSY		0x0008		/* Some work this channel	*/
+#define UN_BREAKI	0x0010		/* Input break received		*/
+#define UN_PWAIT	0x0020		/* Printer waiting for terminal	*/
+#define UN_TIME		0x0040		/* Waiting on time		*/
+#define UN_EMPTY	0x0080		/* Waiting output queue empty	*/
+#define UN_LOW		0x0100		/* Waiting output low water mark*/
+#define UN_EXCL_OPEN	0x0200		/* Open for exclusive use	*/
+#define UN_WOPEN	0x0400		/* Device waiting for open	*/
+#define UN_WIOCTL	0x0800		/* Device waiting for open	*/
+#define UN_HANGUP	0x8000		/* Carrier lost			*/
+
+struct device;
+
+/************************************************************************
+ * Structure for terminal or printer unit. 
+ ************************************************************************/
+struct un_t {
+	int	magic;		/* Unit Magic Number.			*/
+	struct	channel_t *un_ch;
+	ulong	un_time;
+	uint	un_type;
+	uint	un_open_count;	/* Counter of opens to port		*/
+	struct tty_struct *un_tty;/* Pointer to unit tty structure	*/
+	uint	un_flags;	/* Unit flags				*/
+	wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
+	uint	un_dev;		/* Minor device number			*/
+	struct device *un_sysfs;
+};
+
+
+/************************************************************************ 
+ * Device flag definitions for ch_flags.
+ ************************************************************************/
+#define CH_PRON		0x0001		/* Printer on string		*/
+#define CH_STOP		0x0002		/* Output is stopped		*/
+#define CH_STOPI	0x0004		/* Input is stopped		*/
+#define CH_CD		0x0008		/* Carrier is present		*/
+#define CH_FCAR		0x0010		/* Carrier forced on		*/
+#define CH_HANGUP       0x0020		/* Hangup received		*/
+
+#define CH_RECEIVER_OFF	0x0040		/* Receiver is off		*/
+#define CH_OPENING	0x0080		/* Port in fragile open state	*/
+#define CH_CLOSING	0x0100		/* Port in fragile close state	*/
+#define CH_FIFO_ENABLED 0x0200		/* Port has FIFOs enabled	*/
+#define CH_TX_FIFO_EMPTY 0x0400		/* TX Fifo is completely empty	*/
+#define CH_TX_FIFO_LWM  0x0800		/* TX Fifo is below Low Water	*/
+#define CH_BREAK_SENDING 0x1000		/* Break is being sent		*/
+#define CH_LOOPBACK 0x2000		/* Channel is in lookback mode	*/
+#define CH_FLIPBUF_IN_USE 0x4000	/* Channel's flipbuf is in use	*/
+#define CH_BAUD0	0x08000		/* Used for checking B0 transitions */
+#define CH_FORCED_STOP  0x20000		/* Output is forcibly stopped	*/ 
+#define CH_FORCED_STOPI 0x40000		/* Input is forcibly stopped	*/
+
+/*
+ * Definitions for ch_sniff_flags
+ */
+#define SNIFF_OPEN	0x1
+#define SNIFF_WAIT_DATA	0x2
+#define SNIFF_WAIT_SPACE 0x4
+
+
+/* Our Read/Error/Write queue sizes */
+#define RQUEUEMASK	0x1FFF		/* 8 K - 1 */
+#define EQUEUEMASK	0x1FFF		/* 8 K - 1 */
+#define WQUEUEMASK	0x0FFF		/* 4 K - 1 */
+#define RQUEUESIZE	(RQUEUEMASK + 1)
+#define EQUEUESIZE	RQUEUESIZE
+#define WQUEUESIZE	(WQUEUEMASK + 1)
+
+
+/************************************************************************ 
+ * Channel information structure.
+ ************************************************************************/
+struct channel_t {
+	int magic;			/* Channel Magic Number		*/
+	struct board_t	*ch_bd;		/* Board structure pointer      */
+	struct digi_t	ch_digi;	/* Transparent Print structure  */
+	struct un_t	ch_tun;		/* Terminal unit info           */
+	struct un_t	ch_pun;		/* Printer unit info            */
+
+	spinlock_t	ch_lock;	/* provide for serialization */
+	wait_queue_head_t ch_flags_wait;
+
+	uint		ch_portnum;	/* Port number, 0 offset.	*/
+	uint		ch_open_count;	/* open count			*/
+	uint		ch_flags;	/* Channel flags                */
+
+	ulong		ch_close_delay;	/* How long we should drop RTS/DTR for */
+
+	ulong		ch_cpstime;	/* Time for CPS calculations    */
+
+	tcflag_t	ch_c_iflag;	/* channel iflags               */
+	tcflag_t	ch_c_cflag;	/* channel cflags               */
+	tcflag_t	ch_c_oflag;	/* channel oflags               */
+	tcflag_t	ch_c_lflag;	/* channel lflags               */
+	uchar		ch_stopc;	/* Stop character               */
+	uchar		ch_startc;	/* Start character              */
+
+	uint		ch_old_baud;	/* Cache of the current baud */
+	uint		ch_custom_speed;/* Custom baud, if set */
+
+	uint		ch_wopen;	/* Waiting for open process cnt */
+
+	uchar		ch_mostat;	/* FEP output modem status      */
+	uchar		ch_mistat;	/* FEP input modem status       */
+
+	struct neo_uart_struct *ch_neo_uart;	/* Pointer to the "mapped" UART struct */
+	struct cls_uart_struct *ch_cls_uart;	/* Pointer to the "mapped" UART struct */
+
+	uchar		ch_cached_lsr;	/* Cached value of the LSR register */
+
+	uchar		*ch_rqueue;	/* Our read queue buffer - malloc'ed */
+	ushort		ch_r_head;	/* Head location of the read queue */
+	ushort		ch_r_tail;	/* Tail location of the read queue */
+
+	uchar		*ch_equeue;	/* Our error queue buffer - malloc'ed */
+	ushort		ch_e_head;	/* Head location of the error queue */
+	ushort		ch_e_tail;	/* Tail location of the error queue */
+
+	uchar		*ch_wqueue;	/* Our write queue buffer - malloc'ed */
+	ushort		ch_w_head;	/* Head location of the write queue */
+	ushort		ch_w_tail;	/* Tail location of the write queue */
+
+	ulong		ch_rxcount;	/* total of data received so far */
+	ulong		ch_txcount;	/* total of data transmitted so far */
+
+	uchar		ch_r_tlevel;	/* Receive Trigger level */
+	uchar		ch_t_tlevel;	/* Transmit Trigger level */
+
+	uchar		ch_r_watermark;	/* Receive Watermark */
+
+	ulong		ch_stop_sending_break;	/* Time we should STOP sending a break */
+
+	uint		ch_stops_sent;	/* How many times I have sent a stop character
+					 * to try to stop the other guy sending.
+					 */
+	ulong		ch_err_parity;	/* Count of parity errors on channel */
+	ulong		ch_err_frame;	/* Count of framing errors on channel */
+	ulong		ch_err_break;	/* Count of breaks on channel */
+	ulong		ch_err_overrun; /* Count of overruns on channel */
+
+	ulong		ch_xon_sends;	/* Count of xons transmitted */
+	ulong		ch_xoff_sends;	/* Count of xoffs transmitted */
+
+	ulong		ch_intr_modem;	/* Count of interrupts */
+	ulong		ch_intr_tx;	/* Count of interrupts */
+	ulong		ch_intr_rx;	/* Count of interrupts */
+
+
+	/* /proc/<board>/<channel> entries */
+	struct proc_dir_entry *proc_entry_pointer;
+	struct dgnc_proc_entry *dgnc_channel_table;
+
+	uint ch_sniff_in;
+	uint ch_sniff_out;
+	char *ch_sniff_buf;		/* Sniff buffer for proc */
+	ulong ch_sniff_flags;		/* Channel flags                */
+	wait_queue_head_t ch_sniff_wait;
+};
+
+
+/*************************************************************************
+ *
+ * Prototypes for non-static functions used in more than one module
+ *
+ *************************************************************************/
+
+extern int		dgnc_ms_sleep(ulong ms);
+extern void		*dgnc_driver_kzmalloc(size_t size, int priority);
+extern char		*dgnc_ioctl_name(int cmd);
+
+/*
+ * Our Global Variables.
+ */
+extern int		dgnc_driver_state;	/* The state of the driver	*/
+extern uint		dgnc_Major;		/* Our driver/mgmt major	*/
+extern int		dgnc_debug;		/* Debug variable		*/
+extern int		dgnc_rawreadok;		/* Set if user wants rawreads	*/
+extern int		dgnc_poll_tick;		/* Poll interval - 20 ms	*/
+extern int		dgnc_trcbuf_size;	/* Size of the ringbuffer	*/
+extern spinlock_t	dgnc_global_lock;	/* Driver global spinlock	*/
+extern uint		dgnc_NumBoards;		/* Total number of boards	*/
+extern struct board_t	*dgnc_Board[MAXBOARDS];	/* Array of board structs	*/
+extern ulong		dgnc_poll_counter;	/* Times the poller has run	*/
+extern char		*dgnc_state_text[];	/* Array of state text		*/
+extern char		*dgnc_driver_state_text[];/* Array of driver state text */
+
+#endif
diff --git a/drivers/staging/dgnc/dgnc_kcompat.h b/drivers/staging/dgnc/dgnc_kcompat.h
new file mode 100644
index 0000000..a0f5874
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_kcompat.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2004 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *************************************************************************
+ *
+ * This file is intended to contain all the kernel "differences" between the
+ * various kernels that we support.
+ *
+ *************************************************************************/
+
+#ifndef __DGNC_KCOMPAT_H
+#define __DGNC_KCOMPAT_H
+
+#include <linux/version.h>
+
+# ifndef KERNEL_VERSION
+#  define KERNEL_VERSION(a,b,c)  (((a) << 16) + ((b) << 8) + (c))
+# endif
+
+
+#if !defined(TTY_FLIPBUF_SIZE)        
+# define TTY_FLIPBUF_SIZE 512        
+#endif
+
+
+/* Sparse stuff */
+# ifndef __user
+#  define __user
+#  define __kernel
+#  define __safe
+#  define __force
+#  define __chk_user_ptr(x) (void)0
+# endif
+
+
+#  define PARM_STR(VAR, INIT, PERM, DESC) \
+		static char *VAR = INIT; \
+		char *dgnc_##VAR; \
+		module_param(VAR, charp, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_INT(VAR, INIT, PERM, DESC) \
+		static int VAR = INIT; \
+		int dgnc_##VAR; \
+		module_param(VAR, int, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
+		static ulong VAR = INIT; \
+		ulong dgnc_##VAR; \
+		module_param(VAR, long, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+
+
+
+/* NOTHING YET */
+
+
+
+# else
+
+
+
+# error "this driver does not support anything below the 2.6.27 kernel series."
+
+
+
+# endif
+
+#endif /* ! __DGNC_KCOMPAT_H */
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c
new file mode 100644
index 0000000..96cf58b
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_mgmt.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE! 
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com. 
+ *	Thank you. 
+ *
+ */
+
+/************************************************************************
+ * 
+ * This file implements the mgmt functionality for the
+ * Neo and ClassicBoard based product lines.
+ * 
+ ************************************************************************
+ * $Id: dgnc_mgmt.c,v 1.2 2010/12/14 20:08:29 markh Exp $
+ */
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/sched.h>	/* For jiffies, task states */
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/serial_reg.h>
+#include <linux/termios.h>
+#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
+
+#include "dgnc_driver.h"
+#include "dgnc_pci.h"
+#include "dgnc_proc.h"
+#include "dgnc_kcompat.h"	/* Kernel 2.4/2.6 compat includes */
+#include "dgnc_mgmt.h"
+#include "dpacompat.h"
+
+
+/* Our "in use" variables, to enforce 1 open only */
+static int dgnc_mgmt_in_use[MAXMGMTDEVICES];
+
+
+/*
+ * dgnc_mgmt_open()  
+ *
+ * Open the mgmt/downld/dpa device
+ */  
+int dgnc_mgmt_open(struct inode *inode, struct file *file)
+{
+	unsigned long lock_flags;
+	unsigned int minor = iminor(inode);
+
+	DPR_MGMT(("dgnc_mgmt_open start.\n"));
+
+	DGNC_LOCK(dgnc_global_lock, lock_flags); 
+
+	/* mgmt device */
+	if (minor < MAXMGMTDEVICES) {
+		/* Only allow 1 open at a time on mgmt device */
+		if (dgnc_mgmt_in_use[minor]) {
+			DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
+			return (-EBUSY);
+		}
+		dgnc_mgmt_in_use[minor]++;
+	}
+	else {
+		DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
+		return (-ENXIO);
+	}
+
+	DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
+
+	DPR_MGMT(("dgnc_mgmt_open finish.\n"));
+
+	return 0;
+}
+
+
+/*
+ * dgnc_mgmt_close()
+ *
+ * Open the mgmt/dpa device
+ */  
+int dgnc_mgmt_close(struct inode *inode, struct file *file)
+{
+	unsigned long lock_flags;
+	unsigned int minor = iminor(inode);
+
+	DPR_MGMT(("dgnc_mgmt_close start.\n"));
+
+	DGNC_LOCK(dgnc_global_lock, lock_flags); 
+
+	/* mgmt device */
+	if (minor < MAXMGMTDEVICES) {
+		if (dgnc_mgmt_in_use[minor]) {
+			dgnc_mgmt_in_use[minor] = 0;
+		}
+	}
+	DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
+
+	DPR_MGMT(("dgnc_mgmt_close finish.\n"));
+
+	return 0;
+}
+
+
+/*
+ * dgnc_mgmt_ioctl()
+ *
+ * ioctl the mgmt/dpa device
+ */  
+#ifdef HAVE_UNLOCKED_IOCTL
+long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+#else        
+int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+#endif
+	unsigned long lock_flags;
+	void __user *uarg = (void __user *) arg;
+
+	DPR_MGMT(("dgnc_mgmt_ioctl start.\n"));
+
+	switch (cmd) {
+
+	case DIGI_GETDD:
+	{
+		/*
+		 * This returns the total number of boards
+		 * in the system, as well as driver version
+		 * and has space for a reserved entry
+		 */
+		struct digi_dinfo ddi;
+
+		DGNC_LOCK(dgnc_global_lock, lock_flags); 
+
+		ddi.dinfo_nboards = dgnc_NumBoards;
+		sprintf(ddi.dinfo_version, "%s", DG_PART);
+
+		DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
+
+		DPR_MGMT(("DIGI_GETDD returning numboards: %d version: %s\n",
+			ddi.dinfo_nboards, ddi.dinfo_version));
+
+		if (copy_to_user(uarg, &ddi, sizeof (ddi)))
+			return(-EFAULT);
+
+		break;
+	}
+
+	case DIGI_GETBD:
+	{
+		int brd;
+
+		struct digi_info di;
+
+		if (copy_from_user(&brd, uarg, sizeof(int))) {
+			return(-EFAULT);
+		}
+
+		DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd));
+
+		if ((brd < 0) || (brd > dgnc_NumBoards) || (dgnc_NumBoards == 0))
+			return (-ENODEV);
+
+		memset(&di, 0, sizeof(di));
+
+		di.info_bdnum = brd;
+
+		DGNC_LOCK(dgnc_Board[brd]->bd_lock, lock_flags); 
+
+		di.info_bdtype = dgnc_Board[brd]->dpatype;
+		di.info_bdstate = dgnc_Board[brd]->dpastatus;
+		di.info_ioport = 0;
+		di.info_physaddr = (ulong) dgnc_Board[brd]->membase;
+		di.info_physsize = (ulong) dgnc_Board[brd]->membase - dgnc_Board[brd]->membase_end;
+		if (dgnc_Board[brd]->state != BOARD_FAILED)
+			di.info_nports = dgnc_Board[brd]->nasync;
+		else
+			di.info_nports = 0;
+
+		DGNC_UNLOCK(dgnc_Board[brd]->bd_lock, lock_flags); 
+
+		DPR_MGMT(("DIGI_GETBD returning type: %x state: %x ports: %x size: %x\n",
+			di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize));
+
+		if (copy_to_user(uarg, &di, sizeof (di)))
+			return (-EFAULT);
+
+		break;
+	}
+
+	case DIGI_GET_NI_INFO:
+	{
+		struct channel_t *ch;
+		struct ni_info ni;
+		uchar mstat = 0;
+		uint board = 0;
+		uint channel = 0;
+
+		if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) {
+			return(-EFAULT);
+		}
+
+		DPR_MGMT(("DIGI_GETBD asking about board: %d channel: %d\n",
+			ni.board, ni.channel));
+
+		board = ni.board;
+		channel = ni.channel;
+
+		/* Verify boundaries on board */
+		if ((board < 0) || (board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
+			return (-ENODEV);
+
+		/* Verify boundaries on channel */
+		if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
+			return (-ENODEV);
+
+		ch = dgnc_Board[board]->channels[channel];
+
+		if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+			return (-ENODEV);
+
+		memset(&ni, 0, sizeof(ni));
+		ni.board = board;
+		ni.channel = channel;
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		mstat = (ch->ch_mostat | ch->ch_mistat);
+
+		if (mstat & UART_MCR_DTR) {
+			ni.mstat |= TIOCM_DTR;
+			ni.dtr = TIOCM_DTR;
+		}
+		if (mstat & UART_MCR_RTS) {
+			ni.mstat |= TIOCM_RTS;
+			ni.rts = TIOCM_RTS;
+		}
+		if (mstat & UART_MSR_CTS) {
+			ni.mstat |= TIOCM_CTS;
+			ni.cts = TIOCM_CTS;
+		}
+		if (mstat & UART_MSR_RI) {
+			ni.mstat |= TIOCM_RI;
+			ni.ri = TIOCM_RI;
+		}
+		if (mstat & UART_MSR_DCD) {
+			ni.mstat |= TIOCM_CD;
+			ni.dcd = TIOCM_CD;
+		}
+		if (mstat & UART_MSR_DSR)
+			ni.mstat |= TIOCM_DSR;
+
+		ni.iflag = ch->ch_c_iflag;
+		ni.oflag = ch->ch_c_oflag;
+		ni.cflag = ch->ch_c_cflag;
+		ni.lflag = ch->ch_c_lflag;
+
+		if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS)
+			ni.hflow = 1;
+		else
+			ni.hflow = 0;
+
+		if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI))
+			ni.recv_stopped = 1;
+		else
+			ni.recv_stopped = 0;
+
+		if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP))
+			ni.xmit_stopped = 1;
+		else
+			ni.xmit_stopped = 0;
+
+		ni.curtx = ch->ch_txcount;
+		ni.currx = ch->ch_rxcount;
+
+		ni.baud = ch->ch_old_baud;
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		if (copy_to_user(uarg, &ni, sizeof(ni)))
+			return (-EFAULT);
+
+		break;
+	}
+
+
+	}
+
+	DPR_MGMT(("dgnc_mgmt_ioctl finish.\n"));
+
+	return 0;
+}
diff --git a/drivers/staging/dgnc/dgnc_mgmt.h b/drivers/staging/dgnc/dgnc_mgmt.h
new file mode 100644
index 0000000..a0d1338
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_mgmt.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+#ifndef __DGNC_MGMT_H
+#define __DGNC_MGMT_H
+
+#define MAXMGMTDEVICES 8
+
+int dgnc_mgmt_open(struct inode *inode, struct file *file);
+int dgnc_mgmt_close(struct inode *inode, struct file *file);
+
+#ifdef HAVE_UNLOCKED_IOCTL
+long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+#endif
+
diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c
new file mode 100644
index 0000000..9ac7149
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_neo.c
@@ -0,0 +1,1976 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *	Thank you.
+ *
+ *
+ * $Id: dgnc_neo.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>	/* For jiffies, task states */
+#include <linux/interrupt.h>    /* For tasklet and interrupt structs/defines */
+#include <linux/delay.h>	/* For udelay */
+#include <asm/io.h>		/* For read[bwl]/write[bwl] */
+#include <linux/serial.h>	/* For struct async_serial */
+#include <linux/serial_reg.h>	/* For the various UART offsets */
+
+#include "dgnc_driver.h"	/* Driver main header file */
+#include "dgnc_neo.h"		/* Our header file */
+#include "dgnc_tty.h"
+#include "dgnc_trace.h"
+
+static inline void neo_parse_lsr(struct board_t *brd, uint port);
+static inline void neo_parse_isr(struct board_t *brd, uint port);
+static void neo_copy_data_from_uart_to_queue(struct channel_t *ch);
+static inline void neo_clear_break(struct channel_t *ch, int force);
+static inline void neo_set_cts_flow_control(struct channel_t *ch);
+static inline void neo_set_rts_flow_control(struct channel_t *ch);
+static inline void neo_set_ixon_flow_control(struct channel_t *ch);
+static inline void neo_set_ixoff_flow_control(struct channel_t *ch);
+static inline void neo_set_no_output_flow_control(struct channel_t *ch);
+static inline void neo_set_no_input_flow_control(struct channel_t *ch);
+static inline void neo_set_new_start_stop_chars(struct channel_t *ch);
+static void neo_parse_modem(struct channel_t *ch, uchar signals);
+static void neo_tasklet(unsigned long data);
+static void neo_vpd(struct board_t *brd);
+static void neo_uart_init(struct channel_t *ch);
+static void neo_uart_off(struct channel_t *ch);
+static int neo_drain(struct tty_struct *tty, uint seconds);
+static void neo_param(struct tty_struct *tty);
+static void neo_assert_modem_signals(struct channel_t *ch);
+static void neo_flush_uart_write(struct channel_t *ch);
+static void neo_flush_uart_read(struct channel_t *ch);
+static void neo_disable_receiver(struct channel_t *ch);
+static void neo_enable_receiver(struct channel_t *ch);
+static void neo_send_break(struct channel_t *ch, int msecs);
+static void neo_send_start_character(struct channel_t *ch);
+static void neo_send_stop_character(struct channel_t *ch);
+static void neo_copy_data_from_queue_to_uart(struct channel_t *ch);
+static uint neo_get_uart_bytes_left(struct channel_t *ch);
+static void neo_send_immediate_char(struct channel_t *ch, unsigned char c);
+static irqreturn_t neo_intr(int irq, void *voidbrd);
+
+
+struct board_ops dgnc_neo_ops = {
+	.tasklet =			neo_tasklet,
+	.intr =				neo_intr,
+	.uart_init =			neo_uart_init,
+	.uart_off =			neo_uart_off,
+	.drain =			neo_drain,
+	.param =			neo_param,
+	.vpd =				neo_vpd,
+	.assert_modem_signals =		neo_assert_modem_signals,
+	.flush_uart_write =		neo_flush_uart_write,
+	.flush_uart_read =		neo_flush_uart_read,
+	.disable_receiver =		neo_disable_receiver,
+	.enable_receiver =		neo_enable_receiver,
+	.send_break =			neo_send_break,
+	.send_start_character =		neo_send_start_character,
+	.send_stop_character =		neo_send_stop_character,
+	.copy_data_from_queue_to_uart =	neo_copy_data_from_queue_to_uart,
+	.get_uart_bytes_left =		neo_get_uart_bytes_left,
+	.send_immediate_char =		neo_send_immediate_char
+};
+        
+static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+
+/*
+ * This function allows calls to ensure that all outstanding
+ * PCI writes have been completed, by doing a PCI read against
+ * a non-destructive, read-only location on the Neo card.
+ *
+ * In this case, we are reading the DVID (Read-only Device Identification)
+ * value of the Neo card.
+ */
+static inline void neo_pci_posting_flush(struct board_t *bd)
+{
+	readb(bd->re_map_membase + 0x8D);
+}
+
+static inline void neo_set_cts_flow_control(struct channel_t *ch)
+{
+	uchar ier = readb(&ch->ch_neo_uart->ier);
+	uchar efr = readb(&ch->ch_neo_uart->efr);
+
+
+	DPR_PARAM(("Setting CTSFLOW\n"));
+
+	/* Turn on auto CTS flow control */
+#if 1
+	ier |= (UART_17158_IER_CTSDSR);
+#else
+	ier &= ~(UART_17158_IER_CTSDSR);
+#endif
+
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
+
+	/* Turn off auto Xon flow control */   
+	efr &= ~(UART_17158_EFR_IXON);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
+
+	/* Feed the UART our trigger levels */
+	writeb(8, &ch->ch_neo_uart->tfifo);
+	ch->ch_t_tlevel = 8;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static inline void neo_set_rts_flow_control(struct channel_t *ch)
+{
+	uchar ier = readb(&ch->ch_neo_uart->ier);
+	uchar efr = readb(&ch->ch_neo_uart->efr);
+
+	DPR_PARAM(("Setting RTSFLOW\n"));
+
+	/* Turn on auto RTS flow control */
+#if 1
+	ier |= (UART_17158_IER_RTSDTR);
+#else
+	ier &= ~(UART_17158_IER_RTSDTR);
+#endif
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
+
+	/* Turn off auto Xoff flow control */
+	ier &= ~(UART_17158_IER_XOFF);
+	efr &= ~(UART_17158_EFR_IXOFF);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
+	ch->ch_r_watermark = 4;
+
+	writeb(32, &ch->ch_neo_uart->rfifo);
+	ch->ch_r_tlevel = 32;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	/*
+	 * From the Neo UART spec sheet:
+	 * The auto RTS/DTR function must be started by asserting
+	 * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
+	 * it is enabled.
+	 */
+	ch->ch_mostat |= (UART_MCR_RTS);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static inline void neo_set_ixon_flow_control(struct channel_t *ch)
+{
+	uchar ier = readb(&ch->ch_neo_uart->ier);
+	uchar efr = readb(&ch->ch_neo_uart->efr);
+
+	DPR_PARAM(("Setting IXON FLOW\n"));
+
+	/* Turn off auto CTS flow control */
+	ier &= ~(UART_17158_IER_CTSDSR);
+	efr &= ~(UART_17158_EFR_CTSDSR);
+
+	/* Turn on auto Xon flow control */
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+	ch->ch_r_watermark = 4;
+
+	writeb(32, &ch->ch_neo_uart->rfifo);
+	ch->ch_r_tlevel = 32;
+
+	/* Tell UART what start/stop chars it should be looking for */
+	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+	writeb(0, &ch->ch_neo_uart->xonchar2);
+
+	writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+	writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static inline void neo_set_ixoff_flow_control(struct channel_t *ch)
+{
+	uchar ier = readb(&ch->ch_neo_uart->ier);
+	uchar efr = readb(&ch->ch_neo_uart->efr);
+
+	DPR_PARAM(("Setting IXOFF FLOW\n"));
+
+	/* Turn off auto RTS flow control */
+	ier &= ~(UART_17158_IER_RTSDTR);
+	efr &= ~(UART_17158_EFR_RTSDTR);
+
+	/* Turn on auto Xoff flow control */
+	ier |= (UART_17158_IER_XOFF);
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+	writeb(8, &ch->ch_neo_uart->tfifo);
+        ch->ch_t_tlevel = 8;
+
+	/* Tell UART what start/stop chars it should be looking for */
+	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+	writeb(0, &ch->ch_neo_uart->xonchar2);
+
+	writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+	writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static inline void neo_set_no_input_flow_control(struct channel_t *ch)
+{
+	uchar ier = readb(&ch->ch_neo_uart->ier);
+	uchar efr = readb(&ch->ch_neo_uart->efr);
+
+	DPR_PARAM(("Unsetting Input FLOW\n"));
+
+	/* Turn off auto RTS flow control */
+	ier &= ~(UART_17158_IER_RTSDTR);
+	efr &= ~(UART_17158_EFR_RTSDTR);
+
+	/* Turn off auto Xoff flow control */
+	ier &= ~(UART_17158_IER_XOFF);
+	if (ch->ch_c_iflag & IXON)
+		efr &= ~(UART_17158_EFR_IXOFF);
+	else
+		efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
+
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+	ch->ch_r_watermark = 0;
+
+	writeb(16, &ch->ch_neo_uart->tfifo);
+        ch->ch_t_tlevel = 16;
+
+	writeb(16, &ch->ch_neo_uart->rfifo);
+        ch->ch_r_tlevel = 16;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static inline void neo_set_no_output_flow_control(struct channel_t *ch)
+{
+	uchar ier = readb(&ch->ch_neo_uart->ier);
+	uchar efr = readb(&ch->ch_neo_uart->efr);
+
+	DPR_PARAM(("Unsetting Output FLOW\n"));
+
+	/* Turn off auto CTS flow control */
+	ier &= ~(UART_17158_IER_CTSDSR);
+	efr &= ~(UART_17158_EFR_CTSDSR);
+
+	/* Turn off auto Xon flow control */
+	if (ch->ch_c_iflag & IXOFF)
+		efr &= ~(UART_17158_EFR_IXON);
+	else
+		efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+	ch->ch_r_watermark = 0;
+
+	writeb(16, &ch->ch_neo_uart->tfifo);
+        ch->ch_t_tlevel = 16;
+
+	writeb(16, &ch->ch_neo_uart->rfifo);
+        ch->ch_r_tlevel = 16;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+/* change UARTs start/stop chars */
+static inline void neo_set_new_start_stop_chars(struct channel_t *ch)
+{
+
+	/* if hardware flow control is set, then skip this whole thing */
+	if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) || ch->ch_c_cflag & CRTSCTS)
+		return;
+
+	DPR_PARAM(("In new start stop chars\n"));
+
+	/* Tell UART what start/stop chars it should be looking for */
+	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+	writeb(0, &ch->ch_neo_uart->xonchar2);
+
+	writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+	writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+/*
+ * No locks are assumed to be held when calling this function.
+ */
+static inline void neo_clear_break(struct channel_t *ch, int force)
+{
+	ulong lock_flags;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* Bail if we aren't currently sending a break. */
+	if (!ch->ch_stop_sending_break) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/* Turn break off, and unset some variables */
+	if (ch->ch_flags & CH_BREAK_SENDING) {
+		if ((jiffies >= ch->ch_stop_sending_break) || force) {
+			uchar temp = readb(&ch->ch_neo_uart->lcr);
+        	        writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+			neo_pci_posting_flush(ch->ch_bd);
+			ch->ch_flags &= ~(CH_BREAK_SENDING);
+			ch->ch_stop_sending_break = 0;
+			DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
+                }
+        }
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+/*
+ * Parse the ISR register.
+ */
+static inline void neo_parse_isr(struct board_t *brd, uint port)
+{
+	struct channel_t *ch;
+	uchar isr;
+	uchar cause;
+	ulong lock_flags;
+
+	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	if (port > brd->maxports)
+		return;
+
+	ch = brd->channels[port];
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	/* Here we try to figure out what caused the interrupt to happen */
+	while (1) {
+
+		isr = readb(&ch->ch_neo_uart->isr_fcr);
+
+		/* Bail if no pending interrupt */
+		if (isr & UART_IIR_NO_INT)  {
+			break;
+		}
+
+		/*
+		 * Yank off the upper 2 bits, which just show that the FIFO's are enabled.
+		 */
+		isr &= ~(UART_17158_IIR_FIFO_ENABLED);
+
+		DPR_INTR(("%s:%d isr: %x\n", __FILE__, __LINE__, isr));
+
+		if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
+			/* Read data from uart -> queue */
+			brd->intr_rx++;
+			ch->ch_intr_rx++;
+			neo_copy_data_from_uart_to_queue(ch);
+
+			/* Call our tty layer to enforce queue flow control if needed. */
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+			dgnc_check_queue_flow_control(ch);
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		}
+
+		if (isr & UART_IIR_THRI) {
+			brd->intr_tx++;
+			ch->ch_intr_tx++;
+			/* Transfer data (if any) from Write Queue -> UART. */
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			neo_copy_data_from_queue_to_uart(ch);
+		}
+
+		if (isr & UART_17158_IIR_XONXOFF) {
+			cause = readb(&ch->ch_neo_uart->xoffchar1);
+
+			DPR_INTR(("Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause));
+
+			/*
+			 * Since the UART detected either an XON or
+			 * XOFF match, we need to figure out which
+			 * one it was, so we can suspend or resume data flow.
+			 */
+			if (cause == UART_17158_XON_DETECT) {
+				/* Is output stopped right now, if so, resume it */
+				if (brd->channels[port]->ch_flags & CH_STOP) {
+					DGNC_LOCK(ch->ch_lock, lock_flags);
+					ch->ch_flags &= ~(CH_STOP);
+					DGNC_UNLOCK(ch->ch_lock, lock_flags);
+				}
+				DPR_INTR(("Port %d. XON detected in incoming data\n", port));
+			} 
+			else if (cause == UART_17158_XOFF_DETECT) {
+				if (!(brd->channels[port]->ch_flags & CH_STOP)) {
+					DGNC_LOCK(ch->ch_lock, lock_flags);
+					ch->ch_flags |= CH_STOP;
+					DGNC_UNLOCK(ch->ch_lock, lock_flags);
+					DPR_INTR(("Setting CH_STOP\n"));
+				}
+				DPR_INTR(("Port: %d. XOFF detected in incoming data\n", port));
+			}
+		}
+
+		if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
+			/*
+			 * If we get here, this means the hardware is doing auto flow control.
+			 * Check to see whether RTS/DTR or CTS/DSR caused this interrupt.
+			 */
+			brd->intr_modem++;
+			ch->ch_intr_modem++;
+			cause = readb(&ch->ch_neo_uart->mcr);
+			/* Which pin is doing auto flow? RTS or DTR? */
+			if ((cause & 0x4) == 0) {
+				if (cause & UART_MCR_RTS) {
+					DGNC_LOCK(ch->ch_lock, lock_flags);
+					ch->ch_mostat |= UART_MCR_RTS;
+					DGNC_UNLOCK(ch->ch_lock, lock_flags);
+				}
+				else {
+					DGNC_LOCK(ch->ch_lock, lock_flags);
+					ch->ch_mostat &= ~(UART_MCR_RTS);
+					DGNC_UNLOCK(ch->ch_lock, lock_flags);
+				}
+			} else {
+				if (cause & UART_MCR_DTR) {
+					DGNC_LOCK(ch->ch_lock, lock_flags);
+					ch->ch_mostat |= UART_MCR_DTR;
+					DGNC_UNLOCK(ch->ch_lock, lock_flags);
+				}
+				else {
+					DGNC_LOCK(ch->ch_lock, lock_flags);
+					ch->ch_mostat &= ~(UART_MCR_DTR);
+					DGNC_UNLOCK(ch->ch_lock, lock_flags);
+				}
+			}
+		}
+
+		/* Parse any modem signal changes */
+		DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n"));
+		neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+	}
+}
+
+
+static inline void neo_parse_lsr(struct board_t *brd, uint port)
+{
+	struct channel_t *ch;
+	int linestatus;
+	ulong lock_flags;
+
+	if (!brd)
+		return;
+
+	if (brd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	if (port > brd->maxports)
+		return;
+
+	ch = brd->channels[port];
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	linestatus = readb(&ch->ch_neo_uart->lsr);
+
+	DPR_INTR(("%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus));
+
+	ch->ch_cached_lsr |= linestatus;
+
+	if (ch->ch_cached_lsr & UART_LSR_DR) {
+		brd->intr_rx++;
+		ch->ch_intr_rx++;
+		/* Read data from uart -> queue */
+		neo_copy_data_from_uart_to_queue(ch);
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		dgnc_check_queue_flow_control(ch);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+	}
+
+	/*
+	 * This is a special flag. It indicates that at least 1
+	 * RX error (parity, framing, or break) has happened.
+	 * Mark this in our struct, which will tell me that I have
+	 *to do the special RX+LSR read for this FIFO load.
+	 */
+	if (linestatus & UART_17158_RX_FIFO_DATA_ERROR) {
+		DPR_INTR(("%s:%d Port: %d Got an RX error, need to parse LSR\n",
+			__FILE__, __LINE__, port));
+	}
+
+	/*
+	 * The next 3 tests should *NOT* happen, as the above test
+	 * should encapsulate all 3... At least, thats what Exar says.
+	 */
+
+	if (linestatus & UART_LSR_PE) {
+		ch->ch_err_parity++;
+		DPR_INTR(("%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port));
+	}
+
+	if (linestatus & UART_LSR_FE) {
+		ch->ch_err_frame++;
+		DPR_INTR(("%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port));
+	}
+
+	if (linestatus & UART_LSR_BI) {
+		ch->ch_err_break++;
+		DPR_INTR(("%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port));
+	}
+
+	if (linestatus & UART_LSR_OE) {
+		/*
+		 * Rx Oruns. Exar says that an orun will NOT corrupt
+		 * the FIFO. It will just replace the holding register
+		 * with this new data byte. So basically just ignore this.
+		 * Probably we should eventually have an orun stat in our driver...
+		 */
+		ch->ch_err_overrun++;
+		DPR_INTR(("%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port));
+	}
+
+	if (linestatus & UART_LSR_THRE) {
+		brd->intr_tx++;
+		ch->ch_intr_tx++;
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* Transfer data (if any) from Write Queue -> UART. */
+		neo_copy_data_from_queue_to_uart(ch);
+	}
+	else if (linestatus & UART_17158_TX_AND_FIFO_CLR) {
+		brd->intr_tx++;
+		ch->ch_intr_tx++;
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* Transfer data (if any) from Write Queue -> UART. */
+		neo_copy_data_from_queue_to_uart(ch);
+	}
+}
+
+
+/*
+ * neo_param()
+ * Send any/all changes to the line to the UART.
+ */
+static void neo_param(struct tty_struct *tty)
+{
+	uchar lcr = 0;
+	uchar uart_lcr = 0;
+	uchar ier = 0;
+	uchar uart_ier = 0;
+        uint baud = 9600;
+	int quot = 0;
+        struct board_t *bd;
+	struct channel_t *ch;
+        struct un_t   *un;
+
+	if (!tty || tty->magic != TTY_MAGIC) {
+		return;
+	}
+
+	un = (struct un_t *) tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC) {
+		return;
+	}
+
+	ch = un->un_ch;   
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return;
+	}
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
+		return;
+	}
+
+	DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
+		ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
+         
+	/*
+	 * If baud rate is zero, flush queues, and set mval to drop DTR.
+	 */
+	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+		ch->ch_r_head = ch->ch_r_tail = 0;
+		ch->ch_e_head = ch->ch_e_tail = 0;
+		ch->ch_w_head = ch->ch_w_tail = 0;
+
+		neo_flush_uart_write(ch);
+		neo_flush_uart_read(ch);
+
+		/* The baudrate is B0 so all modem lines are to be dropped. */
+		ch->ch_flags |= (CH_BAUD0);
+		ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
+		neo_assert_modem_signals(ch);
+		ch->ch_old_baud = 0;
+		return;
+
+	} else if (ch->ch_custom_speed) {
+
+		baud = ch->ch_custom_speed;
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+
+			/*
+			 * Bring back up RTS and DTR...
+			 * Also handle RTS or DTR toggle if set.
+			 */
+			if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_RTS);
+			if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_DTR);
+		}
+	} else {
+		int iindex = 0;
+		int jindex = 0;
+
+		ulong bauds[4][16] = {
+			{ /* slowbaud */
+				0,      50,     75,     110,
+				134,    150,    200,    300,
+				600,    1200,   1800,   2400,
+				4800,   9600,   19200,  38400 },
+			{ /* slowbaud & CBAUDEX */
+				0,      57600,  115200, 230400,
+				460800, 150,    200,    921600,
+				600,    1200,   1800,   2400,
+				4800,   9600,   19200,  38400 },
+			{ /* fastbaud */
+				0,      57600,   76800, 115200,
+				131657, 153600, 230400, 460800,
+				921600, 1200,   1800,   2400,
+				4800,   9600,   19200,  38400 },
+			{ /* fastbaud & CBAUDEX */
+				0,      57600,  115200, 230400,
+				460800, 150,    200,    921600,
+				600,    1200,   1800,   2400,
+				4800,   9600,   19200,  38400 }
+		};
+
+		/* Only use the TXPrint baud rate if the terminal unit is NOT open */
+		if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT))
+			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
+		else
+			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
+
+		if (ch->ch_c_cflag & CBAUDEX)
+			iindex = 1;
+
+		if (ch->ch_digi.digi_flags & DIGI_FAST)
+			iindex += 2;
+
+		jindex = baud;
+
+		if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
+			baud = bauds[iindex][jindex];  
+		} else {
+			DPR_IOCTL(("baud indices were out of range (%d)(%d)",
+				iindex, jindex));
+			baud = 0;
+		}
+
+		if (baud == 0)
+			baud = 9600;
+
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+
+			/*
+			 * Bring back up RTS and DTR...
+			 * Also handle RTS or DTR toggle if set.
+			 */
+			if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_RTS);
+			if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
+				ch->ch_mostat |= (UART_MCR_DTR);
+		}
+	}
+
+	if (ch->ch_c_cflag & PARENB) {
+		lcr |= UART_LCR_PARITY;
+	}
+
+	if (!(ch->ch_c_cflag & PARODD)) {
+		lcr |= UART_LCR_EPAR;
+	}
+
+	/* 
+	 * Not all platforms support mark/space parity,
+	 * so this will hide behind an ifdef.
+	 */
+#ifdef CMSPAR
+	if (ch->ch_c_cflag & CMSPAR) 
+		lcr |= UART_LCR_SPAR;
+#endif
+
+	if (ch->ch_c_cflag & CSTOPB)
+		lcr |= UART_LCR_STOP;
+
+	switch (ch->ch_c_cflag & CSIZE) {
+	case CS5:
+		lcr |= UART_LCR_WLEN5;
+		break;
+	case CS6:
+		lcr |= UART_LCR_WLEN6;
+		break;
+	case CS7:
+		lcr |= UART_LCR_WLEN7;
+		break;
+	case CS8:
+	default:
+		lcr |= UART_LCR_WLEN8;
+		break;
+	}
+
+	ier = uart_ier = readb(&ch->ch_neo_uart->ier);
+	uart_lcr = readb(&ch->ch_neo_uart->lcr);
+
+	if (baud == 0)
+		baud = 9600;
+
+	quot = ch->ch_bd->bd_dividend / baud;
+
+	if (quot != 0 && ch->ch_old_baud != baud) {
+		ch->ch_old_baud = baud;
+		writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
+		writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
+		writeb((quot >> 8), &ch->ch_neo_uart->ier);
+		writeb(lcr, &ch->ch_neo_uart->lcr);
+        }
+
+	if (uart_lcr != lcr)
+		writeb(lcr, &ch->ch_neo_uart->lcr);
+
+	if (ch->ch_c_cflag & CREAD) {
+		ier |= (UART_IER_RDI | UART_IER_RLSI);
+	}
+	else {
+		ier &= ~(UART_IER_RDI | UART_IER_RLSI);
+	}
+
+	/*
+	 * Have the UART interrupt on modem signal changes ONLY when
+	 * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set.
+	 */
+	if ((ch->ch_digi.digi_flags & CTSPACE) || (ch->ch_digi.digi_flags & RTSPACE) ||
+		(ch->ch_c_cflag & CRTSCTS) || !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
+		!(ch->ch_c_cflag & CLOCAL))
+	{
+		ier |= UART_IER_MSI;
+	}
+	else {
+		ier &= ~UART_IER_MSI;
+	}
+
+	ier |= UART_IER_THRI;
+
+	if (ier != uart_ier)
+		writeb(ier, &ch->ch_neo_uart->ier);
+
+	/* Set new start/stop chars */
+	neo_set_new_start_stop_chars(ch);
+
+	if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
+		neo_set_cts_flow_control(ch);
+	}
+	else if (ch->ch_c_iflag & IXON) {
+		/* If start/stop is set to disable, then we should disable flow control */
+		if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
+			neo_set_no_output_flow_control(ch);
+		else
+			neo_set_ixon_flow_control(ch);
+	}
+	else {
+		neo_set_no_output_flow_control(ch);
+	}
+
+	if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
+		neo_set_rts_flow_control(ch);
+	}
+	else if (ch->ch_c_iflag & IXOFF) {
+		/* If start/stop is set to disable, then we should disable flow control */
+		if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
+			neo_set_no_input_flow_control(ch);
+		else
+			neo_set_ixoff_flow_control(ch);
+	} 
+	else {
+		neo_set_no_input_flow_control(ch);
+	}
+
+	/*
+	 * Adjust the RX FIFO Trigger level if baud is less than 9600.
+	 * Not exactly elegant, but this is needed because of the Exar chip's
+	 * delay on firing off the RX FIFO interrupt on slower baud rates.
+	 */
+	if (baud < 9600) {
+		writeb(1, &ch->ch_neo_uart->rfifo);
+		ch->ch_r_tlevel = 1;
+	}
+
+	neo_assert_modem_signals(ch);
+
+	/* Get current status of the modem signals now */
+	neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+}
+
+
+/*
+ * Our board poller function.
+ */
+static void neo_tasklet(unsigned long data)
+{
+        struct board_t *bd = (struct board_t *) data;
+	struct channel_t *ch;
+	ulong  lock_flags;
+	int i;
+	int state = 0;
+	int ports = 0;
+
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
+		APR(("poll_tasklet() - NULL or bad bd.\n"));
+		return;
+	}
+
+	/* Cache a couple board values */
+	DGNC_LOCK(bd->bd_lock, lock_flags);
+	state = bd->state;
+	ports = bd->nasync;
+	DGNC_UNLOCK(bd->bd_lock, lock_flags);
+
+	/*
+	 * Do NOT allow the interrupt routine to read the intr registers
+	 * Until we release this lock.
+	 */
+	DGNC_LOCK(bd->bd_intr_lock, lock_flags);
+
+	/*
+	 * If board is ready, parse deeper to see if there is anything to do.
+	 */
+	if ((state == BOARD_READY) && (ports > 0)) {
+		/* Loop on each port */
+		for (i = 0; i < ports; i++) {
+			ch = bd->channels[i];
+
+			/* Just being careful... */
+			if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+				continue;
+
+			/*
+			 * NOTE: Remember you CANNOT hold any channel
+			 * locks when calling the input routine.
+			 *
+			 * During input processing, its possible we
+			 * will call the Linux ld, which might in turn,
+			 * do a callback right back into us, resulting
+			 * in us trying to grab the channel lock twice!
+			 */
+			dgnc_input(ch);
+
+			/*
+			 * Channel lock is grabbed and then released
+			 * inside both of these routines, but neither
+			 * call anything else that could call back into us.
+			 */
+			neo_copy_data_from_queue_to_uart(ch);
+			dgnc_wakeup_writes(ch);
+
+			/*
+			 * Call carrier carrier function, in case something
+			 * has changed.
+			 */
+			dgnc_carrier(ch);
+
+			/*
+			 * Check to see if we need to turn off a sending break.
+			 * The timing check is done inside clear_break()
+			 */
+			if (ch->ch_stop_sending_break)
+				neo_clear_break(ch, 0);
+		}
+	}
+
+	/* Allow interrupt routine to access the interrupt register again */
+	DGNC_UNLOCK(bd->bd_intr_lock, lock_flags);
+
+}
+
+
+/*
+ * dgnc_neo_intr()
+ *
+ * Neo specific interrupt handler.
+ */
+static irqreturn_t neo_intr(int irq, void *voidbrd)
+{
+	struct board_t *brd = (struct board_t *) voidbrd;
+	struct channel_t *ch;
+	int port = 0;
+	int type = 0;
+	int current_port;
+	u32 tmp;
+	u32 uart_poll;
+	unsigned long lock_flags;
+	unsigned long lock_flags2;
+
+	if (!brd) {
+		APR(("Received interrupt (%d) with null board associated\n", irq));
+		return IRQ_NONE;
+	}
+
+	/*
+	 * Check to make sure its for us.
+	 */
+	if (brd->magic != DGNC_BOARD_MAGIC) {
+		APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
+		return IRQ_NONE;
+	}
+
+	brd->intr_count++;
+
+	/* Lock out the slow poller from running on this board. */
+	DGNC_LOCK(brd->bd_intr_lock, lock_flags);
+
+	/*
+	 * Read in "extended" IRQ information from the 32bit Neo register.
+	 * Bits 0-7: What port triggered the interrupt.
+	 * Bits 8-31: Each 3bits indicate what type of interrupt occurred.
+	 */
+	uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
+
+	DPR_INTR(("%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll));
+
+	/*
+	 * If 0, no interrupts pending.
+	 * This can happen if the IRQ is shared among a couple Neo/Classic boards.
+	 */
+	if (!uart_poll) {
+		DPR_INTR(("Kernel interrupted to me, but no pending interrupts...\n"));
+		DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
+		return IRQ_NONE;
+	}
+
+	/* At this point, we have at least SOMETHING to service, dig further... */
+
+	current_port = 0;
+
+	/* Loop on each port */
+	while ((uart_poll & 0xff) != 0) {
+
+		tmp = uart_poll;
+
+		/* Check current port to see if it has interrupt pending */
+		if ((tmp & dgnc_offset_table[current_port]) != 0) {
+			port = current_port;
+			type = tmp >> (8 + (port * 3));
+			type &= 0x7;
+		} else {
+			current_port++;
+			continue;
+		}
+
+		DPR_INTR(("%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type));
+
+		/* Remove this port + type from uart_poll */
+		uart_poll &= ~(dgnc_offset_table[port]);
+
+		if (!type) {
+			/* If no type, just ignore it, and move onto next port */
+			DPR_INTR(("Interrupt with no type! port: %d\n", port));
+			continue;
+		}
+
+		/* Switch on type of interrupt we have */
+		switch (type) {
+
+		case UART_17158_RXRDY_TIMEOUT:
+			/*
+			 * RXRDY Time-out is cleared by reading data in the
+                	 * RX FIFO until it falls below the trigger level.
+			 */
+
+			/* Verify the port is in range. */
+			if (port > brd->nasync)
+				continue;
+
+			ch = brd->channels[port];
+			neo_copy_data_from_uart_to_queue(ch);
+
+			/* Call our tty layer to enforce queue flow control if needed. */
+			DGNC_LOCK(ch->ch_lock, lock_flags2);
+			dgnc_check_queue_flow_control(ch);
+			DGNC_UNLOCK(ch->ch_lock, lock_flags2);
+
+			continue;
+
+		case UART_17158_RX_LINE_STATUS:
+			/*
+			 * RXRDY and RX LINE Status (logic OR of LSR[4:1])
+			 */
+			neo_parse_lsr(brd, port);
+			continue;
+
+		case UART_17158_TXRDY:
+			/*
+			 * TXRDY interrupt clears after reading ISR register for the UART channel.
+			 */
+
+			/*
+			 * Yes, this is odd...
+			 * Why would I check EVERY possibility of type of
+			 * interrupt, when we know its TXRDY???
+			 * Becuz for some reason, even tho we got triggered for TXRDY,
+			 * it seems to be occassionally wrong. Instead of TX, which
+			 * it should be, I was getting things like RXDY too. Weird.
+			 */
+			neo_parse_isr(brd, port);
+			continue;
+
+		case UART_17158_MSR:
+			/*
+			 * MSR or flow control was seen.
+			 */
+			neo_parse_isr(brd, port);
+			continue;
+                   
+		default:
+			/*
+			 * The UART triggered us with a bogus interrupt type.
+			 * It appears the Exar chip, when REALLY bogged down, will throw
+			 * these once and awhile.
+			 * Its harmless, just ignore it and move on.
+			 */
+			DPR_INTR(("%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type));
+			continue;
+		}
+	}
+
+	/*
+	 * Schedule tasklet to more in-depth servicing at a better time.
+	 */
+	tasklet_schedule(&brd->helper_tasklet);
+
+	DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
+
+	DPR_INTR(("dgnc_intr finish.\n"));
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * Neo specific way of turning off the receiver.
+ * Used as a way to enforce queue flow control when in
+ * hardware flow control mode.
+ */
+static void neo_disable_receiver(struct channel_t *ch)
+{
+	uchar tmp = readb(&ch->ch_neo_uart->ier);
+	tmp &= ~(UART_IER_RDI);
+	writeb(tmp, &ch->ch_neo_uart->ier);
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+/*
+ * Neo specific way of turning on the receiver.
+ * Used as a way to un-enforce queue flow control when in
+ * hardware flow control mode.
+ */
+static void neo_enable_receiver(struct channel_t *ch)
+{
+	uchar tmp = readb(&ch->ch_neo_uart->ier);
+	tmp |= (UART_IER_RDI);
+	writeb(tmp, &ch->ch_neo_uart->ier);
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static void neo_copy_data_from_uart_to_queue(struct channel_t *ch)
+{
+        int qleft = 0;
+	uchar linestatus = 0;
+	uchar error_mask = 0;
+        int n = 0;
+        int total = 0;  
+	ushort head;
+	ushort tail;
+	ulong lock_flags;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* cache head and tail of queue */
+	head = ch->ch_r_head & RQUEUEMASK;
+	tail = ch->ch_r_tail & RQUEUEMASK;
+
+	/* Get our cached LSR */
+	linestatus = ch->ch_cached_lsr;
+	ch->ch_cached_lsr = 0;
+
+	/* Store how much space we have left in the queue */
+	if ((qleft = tail - head - 1) < 0)
+		qleft += RQUEUEMASK + 1;
+
+	/*
+	 * If the UART is not in FIFO mode, force the FIFO copy to
+	 * NOT be run, by setting total to 0.
+	 *
+	 * On the other hand, if the UART IS in FIFO mode, then ask
+	 * the UART to give us an approximation of data it has RX'ed.
+	 */
+	if (!(ch->ch_flags & CH_FIFO_ENABLED))
+		total = 0;
+	else {
+		total = readb(&ch->ch_neo_uart->rfifo);
+
+		/*
+		 * EXAR chip bug - RX FIFO COUNT - Fudge factor.
+		 *
+		 * This resolves a problem/bug with the Exar chip that sometimes
+		 * returns a bogus value in the rfifo register.
+		 * The count can be any where from 0-3 bytes "off".
+		 * Bizarre, but true.
+		 */
+		if ((ch->ch_bd->dvid & 0xf0) >= UART_XR17E158_DVID) {
+			total -= 1;
+		}
+		else {
+			total -= 3;
+		}
+	}
+
+
+	/*
+	 * Finally, bound the copy to make sure we don't overflow
+	 * our own queue...
+	 * The byte by byte copy loop below this loop this will
+	 * deal with the queue overflow possibility.
+	 */
+	total = min(total, qleft);
+
+	while (total > 0) { 
+
+		/*
+		 * Grab the linestatus register, we need to check
+		 * to see if there are any errors in the FIFO.
+		 */
+		linestatus = readb(&ch->ch_neo_uart->lsr);
+
+		/*
+		 * Break out if there is a FIFO error somewhere.
+		 * This will allow us to go byte by byte down below,
+		 * finding the exact location of the error.
+		 */
+		if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
+			break;
+
+		/* Make sure we don't go over the end of our queue */
+		n = min(((uint) total), (RQUEUESIZE - (uint) head));
+
+		/*
+		 * Cut down n even further if needed, this is to fix
+		 * a problem with memcpy_fromio() with the Neo on the
+		 * IBM pSeries platform.
+		 * 15 bytes max appears to be the magic number.
+		 */
+		n = min((uint) n, (uint) 12);
+
+		/*
+		 * Since we are grabbing the linestatus register, which
+		 * will reset some bits after our read, we need to ensure
+		 * we don't miss our TX FIFO emptys.
+		 */
+		if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		}
+
+		linestatus = 0;
+
+		/* Copy data from uart to the queue */
+		memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n);
+		dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, n);
+
+		/*
+		 * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed
+		 * that all the data currently in the FIFO is free of
+		 * breaks and parity/frame/orun errors.
+		 */
+		memset(ch->ch_equeue + head, 0, n);
+
+		/* Add to and flip head if needed */
+		head = (head + n) & RQUEUEMASK;
+		total -= n;
+		qleft -= n;
+		ch->ch_rxcount += n;
+	}
+
+	/*
+	 * Create a mask to determine whether we should
+	 * insert the character (if any) into our queue.
+	 */
+	if (ch->ch_c_iflag & IGNBRK)
+		error_mask |= UART_LSR_BI;
+
+	/*
+	 * Now cleanup any leftover bytes still in the UART.
+	 * Also deal with any possible queue overflow here as well.
+	 */
+	while (1) {
+
+		/*
+		 * Its possible we have a linestatus from the loop above
+		 * this, so we "OR" on any extra bits.
+		 */
+		linestatus |= readb(&ch->ch_neo_uart->lsr);
+
+		/*
+		 * If the chip tells us there is no more data pending to
+		 * be read, we can then leave.
+		 * But before we do, cache the linestatus, just in case.
+		 */
+		if (!(linestatus & UART_LSR_DR)) {
+			ch->ch_cached_lsr = linestatus;
+			break;
+		}
+
+		/* No need to store this bit */
+		linestatus &= ~UART_LSR_DR;
+
+		/*
+		 * Since we are grabbing the linestatus register, which
+		 * will reset some bits after our read, we need to ensure
+		 * we don't miss our TX FIFO emptys.
+		 */
+		if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
+			linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR);
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		}
+
+		/*
+		 * Discard character if we are ignoring the error mask.
+		 */
+		if (linestatus & error_mask)  {
+			uchar discard;
+			linestatus = 0;
+			memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
+			continue;
+		}
+
+		/*
+		 * If our queue is full, we have no choice but to drop some data.
+		 * The assumption is that HWFLOW or SWFLOW should have stopped
+		 * things way way before we got to this point.
+		 *
+		 * I decided that I wanted to ditch the oldest data first,
+		 * I hope thats okay with everyone? Yes? Good.
+		 */
+		while (qleft < 1) {
+			DPR_READ(("Queue full, dropping DATA:%x LSR:%x\n",
+				ch->ch_rqueue[tail], ch->ch_equeue[tail]));
+
+			ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
+			ch->ch_err_overrun++;
+			qleft++;
+		}
+
+		memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
+		ch->ch_equeue[head] = (uchar) linestatus;
+		dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, 1);
+
+		DPR_READ(("DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]));
+
+		/* Ditch any remaining linestatus value. */
+		linestatus = 0;
+
+		/* Add to and flip head if needed */
+		head = (head + 1) & RQUEUEMASK;
+
+		qleft--;
+		ch->ch_rxcount++;
+	}
+
+	/*
+	 * Write new final heads to channel structure.
+	 */
+	ch->ch_r_head = head & RQUEUEMASK;
+	ch->ch_e_head = head & EQUEUEMASK;
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+/*
+ * This function basically goes to sleep for secs, or until
+ * it gets signalled that the port has fully drained.
+ */
+static int neo_drain(struct tty_struct *tty, uint seconds)
+{
+	ulong lock_flags;
+	struct channel_t *ch;
+        struct un_t *un;
+	int rc = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC) {
+		return (-ENXIO);
+	}
+
+	un = (struct un_t *) tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC) {
+		return (-ENXIO);
+	}
+
+	ch = un->un_ch;   
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return (-ENXIO);
+	}
+
+	DPR_IOCTL(("%d Drain wait started.\n", __LINE__));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	un->un_flags |= UN_EMPTY;
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * Go to sleep waiting for the tty layer to wake me back up when
+	 * the empty flag goes away.
+	 *
+	 * NOTE: TODO: Do something with time passed in.
+	 */
+	rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
+
+	/* If ret is non-zero, user ctrl-c'ed us */
+	if (rc) {
+		DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__));
+	}
+	else {
+		DPR_IOCTL(("%d Drain wait finished.\n", __LINE__));
+	}
+
+        return (rc);
+}
+        
+
+/*
+ * Flush the WRITE FIFO on the Neo.
+ *
+ * NOTE: Channel lock MUST be held before calling this function!
+ */
+static void neo_flush_uart_write(struct channel_t *ch)
+{
+	uchar tmp = 0;
+	int i = 0;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return;
+	}
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
+	neo_pci_posting_flush(ch->ch_bd);
+
+	for (i = 0; i < 10; i++) {
+
+		/* Check to see if the UART feels it completely flushed the FIFO. */
+		tmp = readb(&ch->ch_neo_uart->isr_fcr);
+		if (tmp & 4) {
+			DPR_IOCTL(("Still flushing TX UART... i: %d\n", i));
+			udelay(10);
+		}
+		else
+			break;
+	}
+
+	ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+}
+
+
+/*
+ * Flush the READ FIFO on the Neo.
+ *
+ * NOTE: Channel lock MUST be held before calling this function!
+ */
+static void neo_flush_uart_read(struct channel_t *ch)
+{
+	uchar tmp = 0;
+	int i = 0;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return;
+	}
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr);
+	neo_pci_posting_flush(ch->ch_bd);
+
+	for (i = 0; i < 10; i++) {
+
+		/* Check to see if the UART feels it completely flushed the FIFO. */
+		tmp = readb(&ch->ch_neo_uart->isr_fcr);
+		if (tmp & 2) {
+			DPR_IOCTL(("Still flushing RX UART... i: %d\n", i));
+			udelay(10);
+		}
+		else
+			break;
+	}
+}
+
+
+static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
+{
+	ushort head;
+	ushort tail;
+	int n;
+	int s;
+	int qlen;
+	uint len_written = 0;
+	ulong lock_flags;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* No data to write to the UART */
+	if (ch->ch_w_tail == ch->ch_w_head) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/* If port is "stopped", don't send any data to the UART */
+	if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If FIFOs are disabled. Send data directly to txrx register
+	 */
+	if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
+		uchar lsrbits = readb(&ch->ch_neo_uart->lsr);
+
+		/* Cache the LSR bits for later parsing */
+		ch->ch_cached_lsr |= lsrbits;
+		if (ch->ch_cached_lsr & UART_LSR_THRE) {
+			ch->ch_cached_lsr &= ~(UART_LSR_THRE);
+
+			/*
+			 * If RTS Toggle mode is on, turn on RTS now if not already set,
+			 * and make sure we get an event when the data transfer has completed.
+			 */
+			if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
+				if (!(ch->ch_mostat & UART_MCR_RTS)) {
+					ch->ch_mostat |= (UART_MCR_RTS);
+					neo_assert_modem_signals(ch);
+				}
+				ch->ch_tun.un_flags |= (UN_EMPTY);
+			}
+			/*
+			 * If DTR Toggle mode is on, turn on DTR now if not already set,
+			 * and make sure we get an event when the data transfer has completed.
+			 */
+			if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
+				if (!(ch->ch_mostat & UART_MCR_DTR)) {
+					ch->ch_mostat |= (UART_MCR_DTR);
+					neo_assert_modem_signals(ch);
+				}
+				ch->ch_tun.un_flags |= (UN_EMPTY);
+			}
+
+			writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
+			DPR_WRITE(("Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]));
+			ch->ch_w_tail++;
+			ch->ch_w_tail &= WQUEUEMASK;
+			ch->ch_txcount++;
+		}
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * We have to do it this way, because of the EXAR TXFIFO count bug.
+	 */
+	if ((ch->ch_bd->dvid & 0xf0) < UART_XR17E158_DVID) {
+		if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) {
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			return;
+		}
+
+		len_written = 0;
+
+		n = readb(&ch->ch_neo_uart->tfifo);
+
+		if ((unsigned int) n > ch->ch_t_tlevel) {
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			return;
+		}
+
+		n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
+	}
+	else {
+		n = UART_17158_TX_FIFOSIZE - readb(&ch->ch_neo_uart->tfifo);
+	}
+
+	/* cache head and tail of queue */
+	head = ch->ch_w_head & WQUEUEMASK;
+	tail = ch->ch_w_tail & WQUEUEMASK;
+	qlen = (head - tail) & WQUEUEMASK;
+
+	/* Find minimum of the FIFO space, versus queue length */
+	n = min(n, qlen);
+
+	while (n > 0) {
+
+		s = ((head >= tail) ? head : WQUEUESIZE) - tail;
+		s = min(s, n);
+
+		if (s <= 0)
+			break;
+
+		/*
+		 * If RTS Toggle mode is on, turn on RTS now if not already set,
+		 * and make sure we get an event when the data transfer has completed.
+		 */
+		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
+			if (!(ch->ch_mostat & UART_MCR_RTS)) {
+				ch->ch_mostat |= (UART_MCR_RTS);
+				neo_assert_modem_signals(ch);
+			}
+			ch->ch_tun.un_flags |= (UN_EMPTY);
+		}
+
+		/*
+		 * If DTR Toggle mode is on, turn on DTR now if not already set,
+		 * and make sure we get an event when the data transfer has completed.
+		 */
+		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
+			if (!(ch->ch_mostat & UART_MCR_DTR)) {
+				ch->ch_mostat |= (UART_MCR_DTR);
+				neo_assert_modem_signals(ch);
+			}
+			ch->ch_tun.un_flags |= (UN_EMPTY);
+		}
+
+		memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
+		dgnc_sniff_nowait_nolock(ch, "UART WRITE", ch->ch_wqueue + tail, s);
+
+		/* Add and flip queue if needed */
+		tail = (tail + s) & WQUEUEMASK;
+		n -= s;
+		ch->ch_txcount += s;
+		len_written += s;
+	}
+
+	/* Update the final tail */
+	ch->ch_w_tail = tail & WQUEUEMASK;
+
+	if (len_written > 0) {
+		neo_pci_posting_flush(ch->ch_bd);
+		ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+	}
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+static void neo_parse_modem(struct channel_t *ch, uchar signals)
+{
+	volatile uchar msignals = signals;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DPR_MSIGS(("neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals));
+
+	/*
+	 * Do altpin switching. Altpin switches DCD and DSR.
+	 * This prolly breaks DSRPACE, so we should be more clever here.
+	 */
+	if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
+		uchar mswap = msignals;
+
+		if (mswap & UART_MSR_DDCD) {
+			msignals &= ~UART_MSR_DDCD;
+			msignals |= UART_MSR_DDSR;
+		}
+		if (mswap & UART_MSR_DDSR) {
+			msignals &= ~UART_MSR_DDSR;
+			msignals |= UART_MSR_DDCD;
+		}
+		if (mswap & UART_MSR_DCD) {
+			msignals &= ~UART_MSR_DCD;
+			msignals |= UART_MSR_DSR;
+		}
+		if (mswap & UART_MSR_DSR) {
+			msignals &= ~UART_MSR_DSR;
+			msignals |= UART_MSR_DCD;
+		}
+	}
+
+	/* Scrub off lower bits. They signify delta's, which I don't care about */
+	msignals &= 0xf0;
+
+	if (msignals & UART_MSR_DCD)
+		ch->ch_mistat |= UART_MSR_DCD;
+	else
+		ch->ch_mistat &= ~UART_MSR_DCD;
+
+	if (msignals & UART_MSR_DSR)
+		ch->ch_mistat |= UART_MSR_DSR;
+	else
+		ch->ch_mistat &= ~UART_MSR_DSR;
+
+	if (msignals & UART_MSR_RI)
+		ch->ch_mistat |= UART_MSR_RI;
+	else
+		ch->ch_mistat &= ~UART_MSR_RI;
+
+	if (msignals & UART_MSR_CTS)
+		ch->ch_mistat |= UART_MSR_CTS;
+	else
+		ch->ch_mistat &= ~UART_MSR_CTS;
+
+	DPR_MSIGS(("Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
+		ch->ch_portnum,
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS), 
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR), 
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD)));
+}
+
+
+/* Make the UART raise any of the output signals we want up */
+static void neo_assert_modem_signals(struct channel_t *ch)
+{
+	uchar out;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	out = ch->ch_mostat;
+
+	if (ch->ch_flags & CH_LOOPBACK)
+		out |= UART_MCR_LOOP;
+
+	writeb(out, &ch->ch_neo_uart->mcr);
+	neo_pci_posting_flush(ch->ch_bd);
+
+	/* Give time for the UART to actually raise/drop the signals */
+	udelay(10);
+}
+
+
+static void neo_send_start_character(struct channel_t *ch)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	if (ch->ch_startc != _POSIX_VDISABLE) {
+		ch->ch_xon_sends++;
+		writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
+		neo_pci_posting_flush(ch->ch_bd);
+		udelay(10);
+	}
+}
+
+
+static void neo_send_stop_character(struct channel_t *ch)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	if (ch->ch_stopc != _POSIX_VDISABLE) {
+		ch->ch_xoff_sends++;
+		writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
+		neo_pci_posting_flush(ch->ch_bd);
+		udelay(10);
+	}
+}
+
+
+/*
+ * neo_uart_init
+ */
+static void neo_uart_init(struct channel_t *ch)
+{
+
+	writeb(0, &ch->ch_neo_uart->ier);
+	writeb(0, &ch->ch_neo_uart->efr);
+	writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
+        
+
+        /* Clear out UART and FIFO */
+	readb(&ch->ch_neo_uart->txrx);
+	writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
+	readb(&ch->ch_neo_uart->lsr);
+	readb(&ch->ch_neo_uart->msr);
+
+	ch->ch_flags |= CH_FIFO_ENABLED;
+
+	/* Assert any signals we want up */
+	writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+/*
+ * Make the UART completely turn off.
+ */
+static void neo_uart_off(struct channel_t *ch)
+{
+	/* Turn off UART enhanced bits */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Stop all interrupts from occurring. */
+	writeb(0, &ch->ch_neo_uart->ier);
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static uint neo_get_uart_bytes_left(struct channel_t *ch)
+{
+	uchar left = 0;
+	uchar lsr = readb(&ch->ch_neo_uart->lsr);
+
+	/* We must cache the LSR as some of the bits get reset once read... */
+	ch->ch_cached_lsr |= lsr;
+ 
+	/* Determine whether the Transmitter is empty or not */
+	if (!(lsr & UART_LSR_TEMT)) {
+		if (ch->ch_flags & CH_TX_FIFO_EMPTY) {
+                	tasklet_schedule(&ch->ch_bd->helper_tasklet);
+		}
+		left = 1;
+	} else {
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		left = 0;
+	}
+
+	return left;
+}
+
+
+/* Channel lock MUST be held by the calling function! */
+static void neo_send_break(struct channel_t *ch, int msecs)
+{
+	/*
+	 * If we receive a time of 0, this means turn off the break.
+	 */
+	if (msecs == 0) {
+		if (ch->ch_flags & CH_BREAK_SENDING) {
+			uchar temp = readb(&ch->ch_neo_uart->lcr);
+			writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+			neo_pci_posting_flush(ch->ch_bd);
+			ch->ch_flags &= ~(CH_BREAK_SENDING);
+			ch->ch_stop_sending_break = 0;
+			DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
+		}
+		return;
+	}
+
+	/*
+	 * Set the time we should stop sending the break.
+	 * If we are already sending a break, toss away the existing
+	 * time to stop, and use this new value instead.
+	 */
+	ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs);
+
+	/* Tell the UART to start sending the break */
+	if (!(ch->ch_flags & CH_BREAK_SENDING)) {
+		uchar temp = readb(&ch->ch_neo_uart->lcr);
+                writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+		neo_pci_posting_flush(ch->ch_bd);
+		ch->ch_flags |= (CH_BREAK_SENDING);
+		DPR_IOCTL(("Port %d. Starting UART_LCR_SBC! start: %lx should end: %lx\n",
+			ch->ch_portnum, jiffies, ch->ch_stop_sending_break));
+        }
+}
+
+
+/*
+ * neo_send_immediate_char.
+ *
+ * Sends a specific character as soon as possible to the UART,   
+ * jumping over any bytes that might be in the write queue.
+ *
+ * The channel lock MUST be held by the calling function.
+ */
+static void neo_send_immediate_char(struct channel_t *ch, unsigned char c)
+{
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	writeb(c, &ch->ch_neo_uart->txrx);
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+static unsigned int neo_read_eeprom(unsigned char *base, unsigned int address)
+{
+	unsigned int enable;
+	unsigned int bits;
+	unsigned int databit;
+	unsigned int val;
+
+	/* enable chip select */
+	writeb(NEO_EECS, base + NEO_EEREG);
+	/* READ */
+	enable = (address | 0x180);
+
+	for (bits = 9; bits--; ) {
+		databit = (enable & (1 << bits)) ? NEO_EEDI : 0;
+		/* Set read address */
+		writeb(databit | NEO_EECS, base + NEO_EEREG);
+		writeb(databit | NEO_EECS | NEO_EECK, base + NEO_EEREG);
+	}
+
+	val = 0;
+
+	for (bits = 17; bits--; ) {
+		/* clock to EEPROM */
+		writeb(NEO_EECS, base + NEO_EEREG);
+		writeb(NEO_EECS | NEO_EECK, base + NEO_EEREG);
+		val <<= 1;
+		/* read EEPROM */
+		if (readb(base + NEO_EEREG) & NEO_EEDO)
+			val |= 1;
+	}
+
+	/* clock falling edge */
+	writeb(NEO_EECS, base + NEO_EEREG);
+
+	/* drop chip select */
+	writeb(0x00, base + NEO_EEREG);
+
+	return val;
+}
+
+
+static void neo_vpd(struct board_t *brd)
+{
+	unsigned int i = 0;
+	unsigned int a;
+
+	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	if (!brd->re_map_membase)
+		return;
+
+	/* Store the VPD into our buffer */
+	for (i = 0; i < NEO_VPD_IMAGESIZE; i++) {
+		a = neo_read_eeprom(brd->re_map_membase, i);
+		brd->vpd[i*2] = a & 0xff;
+		brd->vpd[(i*2)+1] = (a >> 8) & 0xff;
+	}
+
+	if  (((brd->vpd[0x08] != 0x82)	   /* long resource name tag */
+		&&  (brd->vpd[0x10] != 0x82))   /* long resource name tag (PCI-66 files)*/
+		||  (brd->vpd[0x7F] != 0x78))   /* small resource end tag */
+	{
+		memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE);
+	}
+	else {
+		/* Search for the serial number */
+		for (i = 0; i < NEO_VPD_IMAGESIZE * 2; i++) {
+			if (brd->vpd[i] == 'S' && brd->vpd[i + 1] == 'N') {
+				strncpy(brd->serial_num, &(brd->vpd[i + 3]), 9);
+			}
+		}
+	}
+}
diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h
new file mode 100644
index 0000000..ffb4209
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_neo.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ */
+
+#ifndef __DGNC_NEO_H
+#define __DGNC_NEO_H
+
+#include "dgnc_types.h"
+#include "dgnc_driver.h"
+
+/************************************************************************ 
+ * Per channel/port NEO UART structure					*
+ ************************************************************************
+ *		Base Structure Entries Usage Meanings to Host		*
+ *									*
+ *	W = read write		R = read only				* 
+ *			U = Unused.					*
+ ************************************************************************/
+
+struct neo_uart_struct {
+	volatile uchar txrx;		/* WR  RHR/THR - Holding Reg */
+	volatile uchar ier;		/* WR  IER - Interrupt Enable Reg */
+	volatile uchar isr_fcr;		/* WR  ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
+	volatile uchar lcr;		/* WR  LCR - Line Control Reg */
+	volatile uchar mcr;		/* WR  MCR - Modem Control Reg */
+	volatile uchar lsr;		/* WR  LSR - Line Status Reg */
+	volatile uchar msr;		/* WR  MSR - Modem Status Reg */
+	volatile uchar spr;		/* WR  SPR - Scratch Pad Reg */
+	volatile uchar fctr;		/* WR  FCTR - Feature Control Reg */
+	volatile uchar efr;		/* WR  EFR - Enhanced Function Reg */
+	volatile uchar tfifo;		/* WR  TXCNT/TXTRG - Transmit FIFO Reg */	
+	volatile uchar rfifo;		/* WR  RXCNT/RXTRG - Recieve  FIFO Reg */
+	volatile uchar xoffchar1;	/* WR  XOFF 1 - XOff Character 1 Reg */
+	volatile uchar xoffchar2;	/* WR  XOFF 2 - XOff Character 2 Reg */
+	volatile uchar xonchar1;	/* WR  XON 1 - Xon Character 1 Reg */
+	volatile uchar xonchar2;	/* WR  XON 2 - XOn Character 2 Reg */
+
+	volatile uchar reserved1[0x2ff - 0x200]; /* U   Reserved by Exar */
+	volatile uchar txrxburst[64];	/* RW  64 bytes of RX/TX FIFO Data */
+	volatile uchar reserved2[0x37f - 0x340]; /* U   Reserved by Exar */
+	volatile uchar rxburst_with_errors[64];	/* R  64 bytes of RX FIFO Data + LSR */
+};
+
+/* Where to read the extended interrupt register (32bits instead of 8bits) */
+#define	UART_17158_POLL_ADDR_OFFSET	0x80
+
+/* These are the current dvid's of the Neo boards */
+#define UART_XR17C158_DVID 0x20
+#define UART_XR17D158_DVID 0x20
+#define UART_XR17E158_DVID 0x40
+
+#define NEO_EECK  0x10		/* Clock */
+#define NEO_EECS  0x20		/* Chip Select */
+#define NEO_EEDI  0x40		/* Data In  is an Output Pin */
+#define NEO_EEDO  0x80		/* Data Out is an Input Pin */
+#define NEO_EEREG 0x8E		/* offset to EEPROM control reg */
+
+
+#define NEO_VPD_IMAGESIZE 0x40	/* size of image to read from EEPROM in words */           
+#define NEO_VPD_IMAGEBYTES (NEO_VPD_IMAGESIZE * 2)
+
+/*
+ * These are the redefinitions for the FCTR on the XR17C158, since
+ * Exar made them different than their earlier design. (XR16C854)
+ */
+
+/* These are only applicable when table D is selected */
+#define UART_17158_FCTR_RTS_NODELAY	0x00
+#define UART_17158_FCTR_RTS_4DELAY	0x01
+#define UART_17158_FCTR_RTS_6DELAY	0x02
+#define UART_17158_FCTR_RTS_8DELAY	0x03
+#define UART_17158_FCTR_RTS_12DELAY	0x12
+#define UART_17158_FCTR_RTS_16DELAY	0x05
+#define UART_17158_FCTR_RTS_20DELAY	0x13
+#define UART_17158_FCTR_RTS_24DELAY	0x06
+#define UART_17158_FCTR_RTS_28DELAY	0x14
+#define UART_17158_FCTR_RTS_32DELAY	0x07
+#define UART_17158_FCTR_RTS_36DELAY	0x16
+#define UART_17158_FCTR_RTS_40DELAY	0x08
+#define UART_17158_FCTR_RTS_44DELAY	0x09
+#define UART_17158_FCTR_RTS_48DELAY	0x10
+#define UART_17158_FCTR_RTS_52DELAY	0x11
+
+#define UART_17158_FCTR_RTS_IRDA	0x10
+#define UART_17158_FCTR_RS485		0x20
+#define UART_17158_FCTR_TRGA		0x00
+#define UART_17158_FCTR_TRGB		0x40
+#define UART_17158_FCTR_TRGC		0x80
+#define UART_17158_FCTR_TRGD		0xC0
+
+/* 17158 trigger table selects.. */
+#define UART_17158_FCTR_BIT6		0x40
+#define UART_17158_FCTR_BIT7		0x80
+
+/* 17158 TX/RX memmapped buffer offsets */
+#define UART_17158_RX_FIFOSIZE		64  
+#define UART_17158_TX_FIFOSIZE		64  
+
+/* 17158 Extended IIR's */
+#define UART_17158_IIR_RDI_TIMEOUT	0x0C	/* Receiver data TIMEOUT */
+#define UART_17158_IIR_XONXOFF		0x10	/* Received an XON/XOFF char */
+#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20	/* CTS/DSR or RTS/DTR state change */
+#define UART_17158_IIR_FIFO_ENABLED	0xC0	/* 16550 FIFOs are Enabled */
+
+/*
+ * These are the extended interrupts that get sent
+ * back to us from the UART's 32bit interrupt register
+ */
+#define UART_17158_RX_LINE_STATUS	0x1	/* RX Ready */
+#define UART_17158_RXRDY_TIMEOUT	0x2	/* RX Ready Timeout */
+#define UART_17158_TXRDY		0x3	/* TX Ready */
+#define UART_17158_MSR			0x4	/* Modem State Change */
+#define UART_17158_TX_AND_FIFO_CLR	0x40	/* Transmitter Holding Reg Empty */
+#define UART_17158_RX_FIFO_DATA_ERROR	0x80	/* UART detected an RX FIFO Data error */
+
+/*
+ * These are the EXTENDED definitions for the 17C158's Interrupt
+ * Enable Register.
+ */
+#define UART_17158_EFR_ECB	0x10	/* Enhanced control bit */
+#define UART_17158_EFR_IXON	0x2	/* Receiver compares Xon1/Xoff1 */
+#define UART_17158_EFR_IXOFF	0x8	/* Transmit Xon1/Xoff1 */
+#define UART_17158_EFR_RTSDTR	0x40	/* Auto RTS/DTR Flow Control Enable */
+#define UART_17158_EFR_CTSDSR	0x80	/* Auto CTS/DSR Flow COntrol Enable */
+
+#define UART_17158_XOFF_DETECT	0x1	/* Indicates whether chip saw an incoming XOFF char  */
+#define UART_17158_XON_DETECT	0x2	/* Indicates whether chip saw an incoming XON char */
+
+#define UART_17158_IER_RSVD1	0x10	/* Reserved by Exar */
+#define UART_17158_IER_XOFF	0x20	/* Xoff Interrupt Enable */
+#define UART_17158_IER_RTSDTR	0x40	/* Output Interrupt Enable */
+#define UART_17158_IER_CTSDSR	0x80	/* Input Interrupt Enable */
+
+/*
+ * Our Global Variables
+ */
+extern struct board_ops dgnc_neo_ops;
+
+#endif
diff --git a/drivers/staging/dgnc/dgnc_pci.h b/drivers/staging/dgnc/dgnc_pci.h
new file mode 100644
index 0000000..5550707
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_pci.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+/* $Id: dgnc_pci.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ */
+
+#ifndef __DGNC_PCI_H
+#define __DGNC_PCI_H
+
+#define PCIMAX 32			/* maximum number of PCI boards */
+
+#define DIGI_VID				0x114F
+
+#define PCI_DEVICE_CLASSIC_4_DID		0x0028
+#define PCI_DEVICE_CLASSIC_8_DID		0x0029
+#define PCI_DEVICE_CLASSIC_4_422_DID		0x00D0
+#define PCI_DEVICE_CLASSIC_8_422_DID		0x00D1
+#define PCI_DEVICE_NEO_4_DID			0x00B0
+#define PCI_DEVICE_NEO_8_DID			0x00B1
+#define PCI_DEVICE_NEO_2DB9_DID			0x00C8
+#define PCI_DEVICE_NEO_2DB9PRI_DID		0x00C9
+#define PCI_DEVICE_NEO_2RJ45_DID		0x00CA
+#define PCI_DEVICE_NEO_2RJ45PRI_DID		0x00CB
+#define PCI_DEVICE_NEO_1_422_DID		0x00CC
+#define PCI_DEVICE_NEO_1_422_485_DID		0x00CD
+#define PCI_DEVICE_NEO_2_422_485_DID		0x00CE
+#define PCI_DEVICE_NEO_EXPRESS_8_DID		0x00F0
+#define PCI_DEVICE_NEO_EXPRESS_4_DID		0x00F1
+#define PCI_DEVICE_NEO_EXPRESS_4RJ45_DID	0x00F2
+#define PCI_DEVICE_NEO_EXPRESS_8RJ45_DID	0x00F3
+#define PCI_DEVICE_NEO_EXPRESS_4_IBM_DID	0x00F4
+
+#define PCI_DEVICE_CLASSIC_4_PCI_NAME		"ClassicBoard 4 PCI"
+#define PCI_DEVICE_CLASSIC_8_PCI_NAME		"ClassicBoard 8 PCI"
+#define PCI_DEVICE_CLASSIC_4_422_PCI_NAME	"ClassicBoard 4 422 PCI"
+#define PCI_DEVICE_CLASSIC_8_422_PCI_NAME	"ClassicBoard 8 422 PCI"
+#define PCI_DEVICE_NEO_4_PCI_NAME		"Neo 4 PCI"
+#define PCI_DEVICE_NEO_8_PCI_NAME		"Neo 8 PCI"
+#define PCI_DEVICE_NEO_2DB9_PCI_NAME		"Neo 2 - DB9 Universal PCI"
+#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME		"Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
+#define PCI_DEVICE_NEO_2RJ45_PCI_NAME		"Neo 2 - RJ45 Universal PCI"
+#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME	"Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
+#define PCI_DEVICE_NEO_1_422_PCI_NAME		"Neo 1 422 PCI"
+#define PCI_DEVICE_NEO_1_422_485_PCI_NAME	"Neo 1 422/485 PCI"
+#define PCI_DEVICE_NEO_2_422_485_PCI_NAME	"Neo 2 422/485 PCI"
+
+#define PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME	"Neo 8 PCI Express"
+#define PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME	"Neo 4 PCI Express"
+#define PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME	"Neo 4 PCI Express RJ45"
+#define PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME	"Neo 8 PCI Express RJ45"
+#define PCI_DEVICE_NEO_EXPRESS_4_IBM_PCI_NAME	"Neo 4 PCI Express IBM"
+
+
+/* Size of Memory and I/O for PCI (4 K) */
+#define PCI_RAM_SIZE				0x1000
+
+/* Size of Memory (2MB) */
+#define PCI_MEM_SIZE				0x1000
+
+#endif
diff --git a/drivers/staging/dgnc/dgnc_proc.c b/drivers/staging/dgnc/dgnc_proc.c
new file mode 100644
index 0000000..c59c833
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_proc.c
@@ -0,0 +1,1550 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *	Thank you.
+ *
+ *
+ * $Id: dgnc_proc.c,v 1.3 2011/06/22 12:16:35 markh Exp $
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/sched.h>	/* For jiffies, task states */
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/serial_reg.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>		/* For copy_from_user/copy_to_user */
+
+#include "dgnc_driver.h"
+#include "dgnc_proc.h"
+#include "dgnc_mgmt.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+#define init_MUTEX(sem)         sema_init(sem, 1)
+#define DECLARE_MUTEX(name)     \
+        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
+#endif
+
+
+/* The /proc/dgnc directory */
+static struct proc_dir_entry *ProcDGNC;
+
+
+/* File operation declarations */
+static int	dgnc_gen_proc_open(struct inode *, struct file *);
+static int	dgnc_gen_proc_close(struct inode *, struct file *);
+static ssize_t	dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+static ssize_t	dgnc_gen_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+
+static int dgnc_proc_chk_perm(struct inode *, int);
+
+static const struct file_operations dgnc_proc_file_ops =
+{
+	.owner =	THIS_MODULE,
+	.read =		dgnc_gen_proc_read,	/* read		*/
+	.write =	dgnc_gen_proc_write,	/* write	*/
+	.open =		dgnc_gen_proc_open,	/* open		*/
+	.release =	dgnc_gen_proc_close,	/* release	*/
+};
+
+
+static struct inode_operations dgnc_proc_inode_ops =
+{
+	.permission =	dgnc_proc_chk_perm
+};
+
+
+static void dgnc_register_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *);
+static void dgnc_unregister_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *);
+static void dgnc_remove_proc_entry(struct proc_dir_entry *pde);
+
+
+/* Stuff in /proc/ */
+static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				const char __user *buffer, ssize_t *lenp, loff_t *ppos);
+
+static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+
+static struct dgnc_proc_entry dgnc_table[] = {
+	{DGNC_INFO,	"info", 0600, NULL, NULL, NULL, &dgnc_read_info, &dgnc_write_info,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_table[0].excl_sem, 1), 0, NULL },
+	{DGNC_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_mknod, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_table[1].excl_sem, 1), 0, NULL },
+	{0}
+};
+
+
+/* Stuff in /proc/<board>/ */
+static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+
+static struct dgnc_proc_entry dgnc_board_table[] = {
+	{DGNC_BOARD_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_board_info, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[0].excl_sem, 1), 0, NULL },
+	{DGNC_BOARD_VPD, "vpd", 0600, NULL, NULL, NULL, &dgnc_read_board_vpd, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[1].excl_sem, 1), 0, NULL },
+	{DGNC_BOARD_TTYSTATS, "stats", 0600, NULL, NULL, NULL, &dgnc_read_board_ttystats, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[2].excl_sem, 1), 0, NULL },
+	{DGNC_BOARD_TTYINTR, "intr", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyintr, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[3].excl_sem, 1), 0, NULL },
+	{DGNC_BOARD_TTYFLAGS, "flags", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyflags, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[4].excl_sem, 1), 0, NULL },
+	{DGNC_BOARD_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_board_mknod, NULL,
+			NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[5].excl_sem, 1), 0, NULL },
+	{0}
+};
+
+
+/* Stuff in /proc/<board>/<channel> */
+static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				void *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				void *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user  *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos);
+
+static struct dgnc_proc_entry dgnc_channel_table[] = {
+	{DGNC_PORT_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_channel_info, NULL,
+		NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[0].excl_sem, 1), 0, NULL },
+	{DGNC_PORT_SNIFF, "sniff", 0600, NULL, &dgnc_open_channel_sniff, &dgnc_close_channel_sniff, &dgnc_read_channel_sniff, NULL,
+		NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[1].excl_sem, 1), 0, NULL},
+        {DGNC_PORT_CUSTOM_TTYNAME, "ttyname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_ttyname, NULL,
+		NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[2].excl_sem, 1), 0, NULL },
+        {DGNC_PORT_CUSTOM_PRNAME, "prname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_prname, NULL,
+		NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[3].excl_sem, 1), 0, NULL },
+	{0}
+};
+
+
+/*
+ * dgnc_test_perm does NOT grant the superuser all rights automatically, because
+ * some entries are readonly even to root.
+ */
+static inline int dgnc_test_perm(int mode, int op)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+	if (!current->euid)
+#else
+	if (!current_euid())
+#endif
+		mode >>= 6;
+	else if (in_egroup_p(0))
+		mode >>= 3;
+	if ((mode & op & 0007) == op)
+		return 0;
+	if (capable(CAP_SYS_ADMIN))
+		return 0;
+	return -EACCES;
+}
+
+
+/*
+ * /proc/sys support
+ */
+static inline int dgnc_proc_match(int len, const char *name, struct proc_dir_entry *de)
+{
+	if (!de || !de->low_ino)
+		return 0;
+	if (de->namelen != len)  
+		return 0;
+	return !memcmp(name, de->name, len);
+}
+
+
+/*
+ *  Scan the entries in table and add them all to /proc at the position
+ *  referred to by "root"
+ */
+static void dgnc_register_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root)
+{
+	struct proc_dir_entry *de;
+	int len;
+	mode_t mode;
+
+	for (; table->magic; table++) {
+		/* Can't do anything without a proc name. */
+		if (!table->name) {
+			DPR_PROC(("dgnc_register_proc_table, no name...\n"));
+			continue;
+		}
+
+		/* Maybe we can't do anything with it... */
+		if (!table->read_handler && !table->write_handler && !table->child) {
+			DPR_PROC((KERN_WARNING "DGNC PROC: Can't register %s\n", table->name));
+			continue;
+		}
+
+		len = strlen(table->name);
+		mode = table->mode;
+		de = NULL;
+
+		if (!table->child) {
+			mode |= S_IFREG;
+		} else {
+			mode |= S_IFDIR;
+			for (de = root->subdir; de; de = de->next) {
+				if (dgnc_proc_match(len, table->name, de))
+					break;
+			}
+
+			/* If the subdir exists already, de is non-NULL */
+		}
+
+		if (!de) {
+			de = create_proc_entry(table->name, mode, root);
+			if (!de)
+				continue;
+			de->data = (void *) table;
+			if (!table->child) {
+				de->proc_iops = &dgnc_proc_inode_ops;
+				de->proc_fops = &dgnc_proc_file_ops;		
+			}
+		}
+
+		table->de = de;
+
+		if (de->mode & S_IFDIR)
+			dgnc_register_proc_table(table->child, de);
+
+	}
+}
+
+
+
+/*
+ * Unregister a /proc sysctl table and any subdirectories.
+ */
+static void dgnc_unregister_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root)
+{
+	struct proc_dir_entry *de;
+
+	for (; table->magic; table++) {
+		if (!(de = table->de))
+			continue;
+
+		if (de->mode & S_IFDIR) {
+			if (!table->child) {
+				DPR_PROC((KERN_ALERT "Help - malformed sysctl tree on free\n"));
+				continue;
+			}
+
+			/* recurse down into subdirectory... */
+			DPR_PROC(("Recursing down a directory...\n"));
+			dgnc_unregister_proc_table(table->child, de);
+
+			/* Don't unregister directories which still have entries.. */
+			if (de->subdir)
+				continue;
+		}   
+
+		/* Don't unregister proc entries that are still being used.. */
+		if ((atomic_read(&de->count)) != 1) {
+			DPR_PROC(("proc entry in use... Not removing...\n"));
+			continue;
+		}
+
+		dgnc_remove_proc_entry(de);
+		table->de = NULL;
+	}
+}
+
+
+
+static int dgnc_gen_proc_open(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *de;
+	struct dgnc_proc_entry *entry;
+	int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
+		void *buffer, ssize_t *lenp, loff_t *ppos);
+	int ret = 0, error = 0;
+
+	de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
+	if (!de || !de->data) {
+		ret = -ENXIO;
+		goto done;
+	}
+
+	entry = (struct dgnc_proc_entry *) de->data;
+	if (!entry) {
+		ret = -ENXIO;
+		goto done;
+	}
+
+	down(&entry->excl_sem);
+
+	if (entry->excl_cnt) {
+		ret = -EBUSY;
+	} else {
+		entry->excl_cnt++;
+
+		handler = entry->open_handler;
+		if (handler) {
+			error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL);
+			if (error) {
+				entry->excl_cnt--;
+				ret = error;
+			}
+		}
+	}
+
+	up(&entry->excl_sem);
+
+done:
+
+	return ret;
+}
+
+
+static int dgnc_gen_proc_close(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *de;
+	int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
+		void *buffer, ssize_t *lenp, loff_t *ppos);
+	struct dgnc_proc_entry *entry;
+	int error = 0;
+
+	de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
+	if (!de || !de->data)
+		goto done;
+
+	entry = (struct dgnc_proc_entry *) de->data;
+	if (!entry)
+		goto done;
+
+	down(&entry->excl_sem);
+
+	if (entry->excl_cnt)
+		entry->excl_cnt = 0;
+
+
+	handler = entry->close_handler;
+	if (handler) {
+		error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL);
+	}
+
+	up(&entry->excl_sem);
+
+done:
+	return 0;
+}
+
+
+static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *de;
+	struct dgnc_proc_entry *entry;
+	int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
+		char __user *buffer, ssize_t *lenp, loff_t *ppos2);
+	ssize_t res;
+	ssize_t error;
+
+	de = (struct proc_dir_entry*) PDE(file->f_dentry->d_inode);
+	if (!de || !de->data)
+		return -ENXIO; 
+
+	entry = (struct dgnc_proc_entry *) de->data;
+	if (!entry)
+		return -ENXIO;
+
+	/* Test for read permission */
+	if (dgnc_test_perm(entry->mode, 4))
+		return -EPERM;
+
+	res = count;
+
+	handler = entry->read_handler;
+	if (!handler)
+		return -ENXIO;
+
+	error = (*handler) (entry, OUTBOUND, file, buf, &res, ppos);
+	if (error)
+		return error;
+
+	return res;
+}
+
+
+static ssize_t	dgnc_gen_proc_write(struct file *file, const char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *de;
+	struct dgnc_proc_entry *entry;
+	int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
+		const char __user *buffer, ssize_t *lenp, loff_t *ppos2);
+	ssize_t res;   
+	ssize_t error;
+
+	de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
+	if (!de || !de->data)
+		return -ENXIO;
+
+	entry = (struct dgnc_proc_entry *) de->data;
+	if (!entry)
+		return -ENXIO;
+
+	/* Test for write permission */
+	if (dgnc_test_perm(entry->mode, 2))
+		return -EPERM;
+
+	res = count;
+
+	handler = entry->write_handler;
+	if (!handler)
+		return -ENXIO;
+
+	error = (*handler) (entry, INBOUND, file, buf, &res, ppos);
+	if (error)
+		return error; 
+
+	return res;
+}
+
+
+static int dgnc_proc_chk_perm(struct inode *inode, int op)
+{               
+	return dgnc_test_perm(inode->i_mode, op);
+}
+
+
+/*               
+ *  Return what is (hopefully) useful information about the
+ *  driver. 
+ */
+static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+
+	DPR_PROC(("dgnc_proc_info\n"));
+
+	if (done) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	p += sprintf(p, "Driver:\t\t%s\n", DG_NAME);
+	p += sprintf(p, "\n");
+	p += sprintf(p, "Debug:\t\t0x%x\n", dgnc_debug);
+	p += sprintf(p, "Sysfs Support:\t0x1\n");
+	p += sprintf(p, "Rawreadok:\t0x%x\n", dgnc_rawreadok);
+	p += sprintf(p, "Max Boards:\t%d\n", MAXBOARDS);
+	p += sprintf(p, "Total Boards:\t%d\n", dgnc_NumBoards);
+	p += sprintf(p, "Poll rate:\t%dms\n", dgnc_poll_tick);
+	p += sprintf(p, "Poll counter:\t%ld\n", dgnc_poll_counter);
+	p += sprintf(p, "State:\t\t%s\n", dgnc_driver_state_text[dgnc_driver_state]);
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  When writing to the "info" entry point, I actually allow one
+ *  to modify certain variables.  This may be a sleazy overload
+ *  of this /proc entry, but I don't want:
+ *
+ *     a. to clutter /proc more than I have to
+ *     b. to overload the "config" entry, which would be somewhat
+ *        more natural
+ *     c. necessarily advertise the fact this ability exists
+ *
+ *  The continued support of this feature has not yet been
+ *  guaranteed.
+ *
+ *  Writing operates on a "state machine" principle.
+ *
+ *  State 0: waiting for a symbol to start.  Waiting for anything
+ *           which isn't " ' = or whitespace.
+ *  State 1: reading a symbol.  If the character is a space, move
+ *           to state 2.  If =, move to state 3.  If " or ', move
+ *           to state 0.
+ *  State 2: Waiting for =... suck whitespace.  If anything other
+ *           than whitespace, drop to state 0.
+ *  State 3: Got =.  Suck whitespace waiting for value to start.
+ *           If " or ', go to state 4 (and remember which quote it
+ *           was).  Otherwise, go to state 5.
+ *  State 4: Reading value, within quotes.  Everything is added to
+ *           value up until the matching quote.  When you hit the
+ *           matching quote, try to set the variable, then state 0.
+ *  State 5: Reading value, outside quotes.  Everything not " ' =
+ *           or whitespace goes in value.  Hitting one of the
+ *           terminators tosses us back to state 0 after trying to
+ *           set the variable.
+ */
+typedef enum {
+	INFO_NONE, INFO_INT, INFO_CHAR, INFO_SHORT,
+	INFO_LONG, INFO_PTR, INFO_STRING, INFO_END
+} info_proc_var_val;
+
+static struct {
+	char              *name;
+	info_proc_var_val  type;
+	int                rw;       /* 0=readonly */
+	void              *val_ptr;
+} dgnc_info_vars[] = {
+	{ "rawreadok",   INFO_INT,    1, (void *) &dgnc_rawreadok },
+        { "pollrate",    INFO_INT,    1, (void *) &dgnc_poll_tick },
+	{ NULL, INFO_NONE, 0, NULL },
+	{ "debug",   INFO_LONG,   1, (void *) &dgnc_debug },
+	{ NULL, INFO_END, 0, NULL }
+};
+
+static void dgnc_set_info_var(char *name, char *val)
+{
+	int i;
+	unsigned long newval;
+	unsigned char charval;
+	unsigned short shortval;
+	unsigned int intval;
+
+	for (i = 0; dgnc_info_vars[i].type != INFO_END; i++) {
+		if (dgnc_info_vars[i].name)
+			if (!strcmp(name, dgnc_info_vars[i].name))
+				break;
+	}
+
+	if (dgnc_info_vars[i].type == INFO_END)
+		return;
+	if (dgnc_info_vars[i].rw == 0)
+		return;
+	if (dgnc_info_vars[i].val_ptr == NULL)
+		return;
+
+	newval = simple_strtoul(val, NULL, 0 ); 
+
+	switch (dgnc_info_vars[i].type) {
+	case INFO_CHAR:
+		charval = newval & 0xff;
+		APR(("Modifying %s (%lx) <= 0x%02x  (%d)\n",
+		           name, (long)(dgnc_info_vars[i].val_ptr ),
+		           charval, charval));
+		*(uchar *)(dgnc_info_vars[i].val_ptr) = charval;
+		break;
+	case INFO_SHORT:
+		shortval = newval & 0xffff;
+		APR(("Modifying %s (%lx) <= 0x%04x  (%d)\n",
+		           name, (long)(dgnc_info_vars[i].val_ptr),
+		           shortval, shortval));
+		*(ushort *)(dgnc_info_vars[i].val_ptr) = shortval;
+		break;
+	case INFO_INT:
+		intval = newval & 0xffffffff;
+		APR(("Modifying %s (%lx) <= 0x%08x  (%d)\n",
+		           name, (long)(dgnc_info_vars[i].val_ptr),
+		           intval, intval));
+		*(uint *)(dgnc_info_vars[i].val_ptr) = intval;
+		break;
+	case INFO_LONG:
+		APR(("Modifying %s (%lx) <= 0x%lx  (%ld)\n",
+		           name, (long)(dgnc_info_vars[i].val_ptr),
+		           newval, newval));
+		*(ulong *)(dgnc_info_vars[i].val_ptr) = newval;
+		break;
+	case INFO_PTR:
+	case INFO_STRING:
+	case INFO_END:
+	case INFO_NONE:
+	default:
+		break;
+	}
+}
+
+static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				const char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	static int state = 0;
+	#define MAXSYM 255
+	static int sympos, valpos;
+	static char sym[MAXSYM + 1];
+	static char val[MAXSYM + 1];
+	static int quotchar = 0;
+
+	int i;
+
+	long len;
+	#define INBUFLEN 256
+	char inbuf[INBUFLEN];
+
+	if (*ppos == 0) {
+		state = 0;
+		sympos = 0; sym[0] = 0;
+		valpos = 0; val[0] = 0;
+		quotchar = 0;
+	}
+
+	if ((!*lenp) || (dir != INBOUND)) {
+		*lenp = 0;
+		return 0;
+	}
+
+	len = *lenp;
+
+	if (len > INBUFLEN - 1)
+		len = INBUFLEN - 1;
+
+	if (copy_from_user(inbuf, buffer, len))
+		return -EFAULT;
+
+	inbuf[len] = 0;
+
+	for (i = 0; i < len; i++) {
+		unsigned char c = inbuf[i];
+
+		switch (state) {
+		case 0:
+			quotchar = sympos = valpos = sym[0] = val[0] = 0;
+			if (!isspace(c) && (c != '\"') &&
+			    (c != '\'') && (c != '=')) {
+				sym[sympos++] = c;
+				state = 1;
+				break;
+			}
+			break;
+		case 1:
+			if (isspace(c)) {
+				sym[sympos] = 0;
+				state = 2;
+				break;
+			}
+			if (c == '=') {
+				sym[sympos] = 0;
+				state = 3;
+				break;
+			}
+			if ((c == '\"' ) || ( c == '\'' )) {
+				state = 0;
+				break;
+			}
+			if (sympos < MAXSYM) sym[sympos++] = c;
+			break;
+		case 2:
+			if (isspace(c)) break;
+			if (c == '=') {
+				state = 3;
+				break;
+			}
+			if ((c != '\"') && (c != '\'')) {
+				quotchar = sympos = valpos = sym[0] = val[0] = 0;
+				sym[sympos++] = c;
+				state = 1;
+				break;
+			}
+			state = 0;
+			break;
+		case 3:
+			if (isspace(c)) break;
+			if (c == '=') {
+				state = 0;
+				break;
+			}
+			if ((c == '\"') || (c == '\'')) {
+				state = 4;
+				quotchar = c;
+				break;
+			}
+			val[valpos++] = c;
+			state = 5;
+			break;
+		case 4:
+			if (c == quotchar) {
+				val[valpos] = 0;
+				dgnc_set_info_var(sym, val);
+				state = 0;
+				break;
+			}
+			if (valpos < MAXSYM) val[valpos++] = c;
+			break;
+		case 5:
+			if (isspace(c) || (c == '\"') ||
+			    (c == '\'') || (c == '=')) {
+				val[valpos] = 0;
+				dgnc_set_info_var(sym, val);
+				state = 0;
+				break;
+			}
+			if (valpos < MAXSYM) val[valpos++] = c;
+			break;
+		default:
+			break;
+		}
+	}
+
+	*lenp = len;
+	*ppos += len;
+		
+	return len;
+}
+
+
+/*
+ *  Return mknod information for the driver's devices.
+ */                                             
+static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	int i = 0;
+
+	DPR_PROC(("dgnc_proc_info\n"));
+
+	if (done) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	DPR_PROC(("dgnc_proc_mknod\n"));
+
+	p += sprintf(p, "#\tCreate the management devices.\n");
+
+	for (i = 0; i < MAXMGMTDEVICES; i++) {
+		char tmp[100];
+		sprintf(tmp, "/dev/dg/dgnc/mgmt%d", i);
+		p += sprintf(p, "%s\t%d\t%d\t%d\n",
+			tmp, dgnc_Major, i, 1);
+	}
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*               
+ *  Return what is (hopefully) useful information about the specific board.
+ */
+static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct board_t	*brd;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	char *name;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	brd = (struct board_t *) table->data;
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	name = brd->name;
+
+	p += sprintf(p, "Board Name = %s\n", name);
+	if (brd->serial_num[0] == '\0')
+		p += sprintf(p, "Serial number = <UNKNOWN>\n");
+	else
+		p += sprintf(p, "Serial number = %s\n", brd->serial_num);
+
+	p += sprintf(p, "Board Type = %d\n", brd->type);
+	p += sprintf(p, "Number of Ports = %d\n", brd->nasync);
+
+	/*
+	 * report some things about the PCI bus that are important
+	 * to some applications
+	 */
+        p += sprintf(p, "Vendor ID = 0x%x\n", brd->vendor);
+        p += sprintf(p, "Device ID = 0x%x\n", brd->device);
+        p += sprintf(p, "Subvendor ID = 0x%x\n", brd->subvendor);
+        p += sprintf(p, "Subdevice ID = 0x%x\n", brd->subdevice);
+        p += sprintf(p, "Bus = %d\n", brd->pci_bus);
+        p += sprintf(p, "Slot = %d\n", brd->pci_slot);
+
+	/*
+	 * report the physical addresses assigned to us when we got
+	 * registered
+	 */	
+        p += sprintf(p, "Memory Base Address = 0x%lx\n", brd->membase);
+        p += sprintf(p, "Remapped Memory Base Address = 0x%p\n", brd->re_map_membase);
+
+        p += sprintf(p, "Current state of board = %s\n", dgnc_state_text[brd->state]);
+        p += sprintf(p, "Interrupt #: %d. Times interrupted: %ld\n",
+		brd->irq, brd->intr_count);
+
+        p += sprintf(p, "TX interrupts: %ld  RX interrupts: %ld\n",
+		brd->intr_tx, brd->intr_rx);
+        p += sprintf(p, "Modem interrupts: %ld\n", brd->intr_modem);
+
+        p += sprintf(p, "Majors allocated to board = TTY: %d PR: %d\n",
+		brd->SerialDriver.major, brd->PrintDriver.major);
+
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+
+static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct board_t	*brd;
+	static int done = 0;
+	static char buf[4096];
+	int i = 0, j = 0;
+	char *p = buf;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	brd = (struct board_t *) table->data;
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	p += sprintf(p, "\n      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          ASCII\n");
+
+	for (i = 0; i < 0x40 * 2; i++) {
+		j = i;
+		if (!(i % 16)) {
+			if (j > 0) {
+				p += sprintf(p, "    ");
+				for (j = i - 16; j < i; j++) {
+					if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e)
+						p += sprintf(p, "%c", brd->vpd[j]);
+					else
+						p += sprintf(p, ".");
+				}
+				p += sprintf(p, "\n");
+			}
+			p += sprintf(p, "%04X ", i);
+		}
+		p += sprintf(p, "%02X ", brd->vpd[i]);
+	}
+	if (!(i % 16)) {
+		p += sprintf(p, "    ");
+		for (j = i - 16; j < i; j++) {
+			if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e)
+				p += sprintf(p, "%c", brd->vpd[j]);
+			else
+				p += sprintf(p, ".");
+		}
+		p += sprintf(p, "\n");
+	}
+
+	p += sprintf(p, "\n");
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  Return what is (hopefully) useful stats about the specific board's ttys
+ */
+static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct board_t	*brd;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	int i = 0;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	brd = (struct board_t *) table->data;
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	/* Prepare the Header Labels */
+	p += sprintf(p, "%2s %10s %23s %10s %9s\n",
+		"Ch", "Chars Rx", "  Rx Par--Brk--Frm--Ovr", 
+		"Chars Tx", "XON XOFF");
+
+        for (i = 0; i < brd->nasync; i++) {
+
+		struct channel_t *ch = brd->channels[i];
+
+		p += sprintf(p, "%2d ", i);
+		p += sprintf(p, "%10ld ", ch->ch_rxcount);
+		p += sprintf(p, "    %4ld %4ld %4ld %4ld ", ch->ch_err_parity,
+			ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun);
+		p += sprintf(p, "%10ld ", ch->ch_txcount);
+		p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends);
+
+		p += sprintf(p, "\n");
+	}
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  Return what is (hopefully) useful stats about the specific board's tty intrs
+ */
+static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct board_t	*brd;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	int i = 0;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	brd = (struct board_t *) table->data;
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	/* Prepare the Header Labels */
+	p += sprintf(p, "%2s     %14s  %14s  %14s\n",
+		"Ch", "TX interrupts", "RX interrupts", "Modem interrupts");
+
+        for (i = 0; i < brd->nasync; i++) {
+
+		struct channel_t *ch = brd->channels[i];
+
+		p += sprintf(p, "%2d ", i);
+
+	        p += sprintf(p, "    %14ld  %14ld    %14ld",
+			ch->ch_intr_tx, ch->ch_intr_rx, ch->ch_intr_modem);
+
+		p += sprintf(p, "\n");
+	}
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  Return what is (hopefully) useful flags about the specific board's ttys
+ */
+static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct board_t	*brd;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	int i = 0;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	brd = (struct board_t *) table->data;
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	/* Prepare the Header Labels */
+	p += sprintf(p, "%2s %5s %5s %5s %5s %5s %10s  Line Status Flags\n",
+		"Ch", "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud");
+
+        for (i = 0; i < brd->nasync; i++) {
+
+		struct channel_t *ch = brd->channels[i];
+
+		p += sprintf(p, "%2d ", i);
+		p += sprintf(p, "%5x ", ch->ch_c_cflag);
+		p += sprintf(p, "%5x ", ch->ch_c_iflag);
+		p += sprintf(p, "%5x ", ch->ch_c_oflag);
+		p += sprintf(p, "%5x ", ch->ch_c_lflag);
+		p += sprintf(p, "%5x ", ch->ch_digi.digi_flags);
+		p += sprintf(p, "%10d ", ch->ch_old_baud);
+
+		if (!ch->ch_open_count) {
+			p += sprintf(p, " -- -- -- -- -- -- --") ;
+		} else {
+			p += sprintf(p, " op %s %s %s %s %s %s",
+				(ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--",
+				(ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--",
+				(ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--",
+				(ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--",
+				(ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--",
+				(ch->ch_mistat & UART_MSR_RI)  ? "ri" : "--");
+		}
+
+		p += sprintf(p, "\n");
+	}
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  Return mknod information for the board's devices.
+ */                                             
+static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct board_t	*brd;
+	static int done = 0;
+	static char buf[4096];
+	char str[MAXTTYNAMELEN];
+	char *p = buf;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	brd = (struct board_t *) table->data;
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	/*
+	 * For each board, output the device information in
+	 * a handy table format...
+	 */
+	p += sprintf(p,	"# Create the TTY and PR devices\n");
+
+	/* TTY devices */
+	sprintf(str, "ttyn%d%%p", brd->boardnum + 1);
+	p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str,
+		brd->dgnc_Serial_Major, 0, brd->maxports);
+
+	/* PR devices */
+	sprintf(str, "prn%d%%p", brd->boardnum + 1);
+	p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str,
+		brd->dgnc_TransparentPrint_Major, 128, brd->maxports);
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  Return what is (hopefully) useful information about the specific channel.
+ */
+static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct channel_t *ch;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+
+	DPR_PROC(("dgnc_proc_info\n"));
+
+	ch = (struct channel_t *) table->data;
+
+	if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	p += sprintf(p, "Port number:\t\t%d\n", ch->ch_portnum);
+	p += sprintf(p, "\n");
+
+	/* Prepare the Header Labels */
+	p += sprintf(p, "%10s %23s %10s %9s\n",
+		"Chars Rx", "  Rx Par--Brk--Frm--Ovr",
+		"Chars Tx", "XON XOFF");
+	p += sprintf(p, "%10ld ", ch->ch_rxcount);
+	p += sprintf(p, "    %4ld %4ld %4ld %4ld ", ch->ch_err_parity,
+		ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun);
+	p += sprintf(p, "%10ld ", ch->ch_txcount);  
+	p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends);
+	p += sprintf(p, "\n\n");
+
+	/* Prepare the Header Labels */
+	p += sprintf(p, "%5s %5s %5s %5s %5s %10s  Line Status Flags\n",
+		"CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud");
+
+	p += sprintf(p, "%5x ", ch->ch_c_cflag);
+	p += sprintf(p, "%5x ", ch->ch_c_iflag);
+	p += sprintf(p, "%5x ", ch->ch_c_oflag);
+	p += sprintf(p, "%5x ", ch->ch_c_lflag);
+	p += sprintf(p, "%5x ", ch->ch_digi.digi_flags);
+	p += sprintf(p, "%10d ", ch->ch_old_baud);
+	if (!ch->ch_open_count) {
+		p += sprintf(p, " -- -- -- -- -- -- --") ;
+	} else {
+		p += sprintf(p, " op %s %s %s %s %s %s",
+			(ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--",
+			(ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--",
+			(ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--",
+			(ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--",
+			(ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--",
+			(ch->ch_mistat & UART_MSR_RI)  ? "ri" : "--");
+	}
+	p += sprintf(p, "\n\n");
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf; 
+	done = 1;
+	return 0;
+}
+
+
+/*
+ *  Return mknod information for the board's devices.
+ */
+static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct channel_t *ch;
+	struct board_t  *brd;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	int     cn;
+	int     bn;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	ch = (struct channel_t *) table->data;
+
+	if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	brd = ch->ch_bd;        
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	bn = brd->boardnum;
+	cn = ch->ch_portnum;
+
+	p += sprintf(p, "ttyn%d%c\n", bn + 1, 'a' + cn);
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf;
+	done = 1;
+	return 0;
+}
+
+
+
+
+/*
+ *  Return mknod information for the board's devices.
+ */
+static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct channel_t *ch;
+	struct board_t  *brd;
+	static int done = 0;
+	static char buf[4096];
+	char *p = buf;
+	int     cn;
+	int     bn;
+
+	DPR_PROC(("dgnc_proc_brd_info\n"));
+
+	ch = (struct channel_t *) table->data;
+
+	if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	brd = ch->ch_bd;        
+
+	if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
+		done = 0;
+		*lenp = 0;
+		return 0;
+	}
+
+	bn = brd->boardnum;
+	cn = ch->ch_portnum;
+
+	p += sprintf(p, "prn%d%c\n", bn + 1, 'a' + cn);
+
+	if (copy_to_user(buffer, buf, (p - (char *) buf)))
+		return -EFAULT;
+
+	*lenp = p - (char *) buf;
+	*ppos += p - (char *) buf;
+	done = 1;
+	return 0;
+}
+
+
+static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				void *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct channel_t *ch;
+	ulong  lock_flags;
+
+	ch = (struct channel_t *) table->data;
+
+	if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC))
+		return 0;
+
+	ch->ch_sniff_buf = dgnc_driver_kzmalloc(SNIFF_MAX, GFP_KERNEL);
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	ch->ch_sniff_flags |= SNIFF_OPEN;
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	return 0;
+}
+
+static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				void *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct channel_t *ch;
+	ulong  lock_flags;
+
+	ch = (struct channel_t *) table->data;
+
+	if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC))
+		return 0;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	ch->ch_sniff_flags &= ~(SNIFF_OPEN);
+	kfree(ch->ch_sniff_buf);
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	return 0;
+}
+
+
+/*
+ *    Copy data from the monitoring buffer to the user, freeing space
+ *    in the monitoring buffer for more messages
+ *
+ */
+static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
+				char __user *buffer, ssize_t *lenp, loff_t *ppos)
+{
+	struct channel_t *ch;
+	int n;
+	int r;
+	int offset = 0;
+	int res = 0;
+	ssize_t rtn = 0;
+	ulong  lock_flags;
+
+	ch = (struct channel_t *) table->data;
+
+	if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
+		rtn = -ENXIO;
+		goto done;
+	}
+
+	/*
+	 *  Wait for some data to appear in the buffer.
+	 */
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	for (;;) {
+		n = (ch->ch_sniff_in - ch->ch_sniff_out) & SNIFF_MASK;
+
+		if (n != 0)
+			break;
+
+		ch->ch_sniff_flags |= SNIFF_WAIT_DATA;
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * Go to sleep waiting until the condition becomes true.
+		 */
+		rtn = wait_event_interruptible(ch->ch_sniff_wait,
+			((ch->ch_sniff_flags & SNIFF_WAIT_DATA) == 0));
+
+		if (rtn)
+			goto done;
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+	}
+
+	/*
+	 *  Read whatever is there.
+	 */
+
+	if (n > *lenp)
+		n = *lenp;
+
+	res = n;
+
+	r = SNIFF_MAX - ch->ch_sniff_out;
+
+	if (r <= n) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rtn = copy_to_user(buffer, ch->ch_sniff_buf + ch->ch_sniff_out, r);
+		if (rtn) {
+			rtn = -EFAULT;
+			goto done;
+		}
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		ch->ch_sniff_out = 0;
+		n -= r;
+		offset = r;
+	}
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+	rtn = copy_to_user(buffer + offset, ch->ch_sniff_buf + ch->ch_sniff_out, n);
+	if (rtn) {
+		rtn = -EFAULT;
+		goto done;
+	}
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_sniff_out += n;
+	*ppos += res;
+	rtn = res;
+//	rtn = 0;
+
+	/*
+	 *  Wakeup any thread waiting for buffer space.
+	 */
+
+	if (ch->ch_sniff_flags & SNIFF_WAIT_SPACE) {
+		ch->ch_sniff_flags &= ~SNIFF_WAIT_SPACE;
+		wake_up_interruptible(&ch->ch_sniff_wait);
+	}
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+done:
+	return rtn;
+}
+
+
+/*
+ * Register the basic /proc/dgnc files that appear whenever
+ * the driver is loaded.
+ */
+void dgnc_proc_register_basic_prescan(void)
+{
+	/*
+	 *      Register /proc/dgnc
+	 */
+	ProcDGNC = proc_create("dgnc", (0700 | S_IFDIR), NULL, &dgnc_proc_file_ops);
+	dgnc_register_proc_table(dgnc_table, ProcDGNC);
+}
+
+
+/*
+ * Register the basic /proc/dgnc files that appear whenever
+ * the driver is loaded.
+ */
+void dgnc_proc_register_basic_postscan(int board_num)
+{
+	int i, j;
+	char board[10];
+	sprintf(board, "%d", board_num);
+
+	/* Set proc board entry pointer */
+	dgnc_Board[board_num]->proc_entry_pointer = create_proc_entry(board, (0700 | S_IFDIR), ProcDGNC);
+
+	/* Create a new copy of the board_table... */
+	dgnc_Board[board_num]->dgnc_board_table = dgnc_driver_kzmalloc(sizeof(dgnc_board_table), 
+		GFP_KERNEL);
+
+	/* Now copy the default table into that memory */
+	memcpy(dgnc_Board[board_num]->dgnc_board_table, dgnc_board_table, sizeof(dgnc_board_table));
+
+	/* Initialize semaphores in each table slot */
+	for (i = 0; i < 999; i++) {
+		if (!dgnc_Board[board_num]->dgnc_board_table[i].magic) {
+			break;
+		}
+
+		init_MUTEX(&(dgnc_Board[board_num]->dgnc_board_table[i].excl_sem));
+		dgnc_Board[board_num]->dgnc_board_table[i].data = dgnc_Board[board_num];
+
+	}
+
+	/* Register board table into proc */
+	dgnc_register_proc_table(dgnc_Board[board_num]->dgnc_board_table, 
+		dgnc_Board[board_num]->proc_entry_pointer);
+
+	/*
+	 * Add new entries for each port.
+	 */
+	for (i = 0; i < dgnc_Board[board_num]->nasync; i++) {
+
+		char channel[10];
+		sprintf(channel, "%d", i);
+
+		/* Set proc channel entry pointer */
+		dgnc_Board[board_num]->channels[i]->proc_entry_pointer =
+			create_proc_entry(channel, (0700 | S_IFDIR), 
+			dgnc_Board[board_num]->proc_entry_pointer);
+
+		/* Create a new copy of the channel_table... */
+		dgnc_Board[board_num]->channels[i]->dgnc_channel_table =
+			dgnc_driver_kzmalloc(sizeof(dgnc_channel_table), GFP_KERNEL);
+
+		/* Now copy the default table into that memory */
+		memcpy(dgnc_Board[board_num]->channels[i]->dgnc_channel_table,
+			dgnc_channel_table, sizeof(dgnc_channel_table));
+
+		/* Initialize semaphores in each table slot */
+		for (j = 0; j < 999; j++) {
+			if (!dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].magic) {
+				break;
+			}
+
+			init_MUTEX(&(dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].excl_sem));
+			dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].data = 
+				dgnc_Board[board_num]->channels[i];
+		}
+
+		/* Register channel table into proc */
+		dgnc_register_proc_table(dgnc_Board[board_num]->channels[i]->dgnc_channel_table, 
+			dgnc_Board[board_num]->channels[i]->proc_entry_pointer);
+	}
+}
+
+
+static void dgnc_remove_proc_entry(struct proc_dir_entry *pde)
+{ 
+	if (!pde) {
+		DPR_PROC(("dgnc_remove_proc_entry... NULL entry... not removing...\n"));
+		return;
+	}
+
+	remove_proc_entry(pde->name, pde->parent);
+}
+
+
+void dgnc_proc_unregister_all(void)
+{
+	int i = 0, j = 0;
+
+	/* Walk each board, blowing away their proc entries... */
+	for (i = 0; i < dgnc_NumBoards; i++) {
+
+		/* Walk each channel, blowing away their proc entries... */
+		for (j = 0; j < dgnc_Board[i]->nasync; j++) {
+
+			dgnc_unregister_proc_table(dgnc_Board[i]->channels[j]->dgnc_channel_table, 
+				dgnc_Board[i]->channels[j]->proc_entry_pointer);
+			dgnc_remove_proc_entry(dgnc_Board[i]->channels[j]->proc_entry_pointer);
+			kfree(dgnc_Board[i]->channels[j]->dgnc_channel_table);
+		}
+
+		dgnc_unregister_proc_table(dgnc_Board[i]->dgnc_board_table, 
+			dgnc_Board[i]->proc_entry_pointer);
+		dgnc_remove_proc_entry(dgnc_Board[i]->proc_entry_pointer);
+		kfree(dgnc_Board[i]->dgnc_board_table);
+	}
+
+	/* Blow away the top proc entry */
+	dgnc_unregister_proc_table(dgnc_table, ProcDGNC);
+	dgnc_remove_proc_entry(ProcDGNC);
+}
diff --git a/drivers/staging/dgnc/dgnc_proc.h b/drivers/staging/dgnc/dgnc_proc.h
new file mode 100644
index 0000000..19670e2
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_proc.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *      NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *
+ *     $Id: dgnc_proc.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
+ *
+ *  Description:
+ *
+ *     Describes the private structures used to manipulate the "special"
+ *     proc constructs (not read-only) used by the Digi Neo software.
+ *     The concept is borrowed heavily from the "sysctl" interface of
+ *     the kernel.  I decided not to use the structures and functions
+ *     provided by the kernel for two reasons:
+ *
+ *       1. Due to the planned use of "/proc" in the Neo driver, many
+ *          of the functions of the "sysctl" interface would go unused.
+ *          A simpler interface will be easier to maintain.
+ *
+ *       2. I'd rather divorce our "added package" from the kernel internals.
+ *          If the "sysctl" structures should change, I will be insulated
+ *          from those changes.  These "/proc" entries won't be under the
+ *          "sys" tree anyway, so there is no need to maintain a strict
+ *          dependence relationship.
+ *
+ *  Author:
+ *
+ *     Scott H Kilau
+ *
+ */
+
+#ifndef _DGNC_RW_PROC_H
+#define _DGNC_RW_PROC_H
+
+/*
+ *  The list of DGNC entries with r/w capabilities. 
+ *  These magic numbers are used for identification purposes.
+ */
+enum {
+	DGNC_INFO = 1,			/* Get info about the running module	*/
+	DGNC_MKNOD = 2,			/* Get info about driver devices	*/
+	DGNC_BOARD_INFO = 3,		/* Get info about the specific board	*/
+	DGNC_BOARD_VPD = 4,		/* Get info about the board's VPD	*/
+	DGNC_BOARD_TTYSTATS = 5,	/* Get info about the board's tty stats	*/
+	DGNC_BOARD_TTYINTR = 6,		/* Get info about the board's tty intrs	*/
+	DGNC_BOARD_TTYFLAGS = 7,	/* Get info about the board's tty flags	*/
+	DGNC_BOARD_MKNOD = 8,		/* Get info about board devices		*/
+	DGNC_PORT_INFO = 9,		/* Get info about the specific port	*/
+	DGNC_PORT_SNIFF = 10,		/* Sniff data in/out of specific port	*/
+	DGNC_PORT_CUSTOM_TTYNAME = 11,	/* Get info about UDEV tty name		*/
+	DGNC_PORT_CUSTOM_PRNAME = 12,	/* Get info about UDEV pr name		*/
+};
+
+/*
+ *  Directions for proc handlers
+ */
+enum {
+        INBOUND = 1,		/* Data being written to kernel */
+        OUTBOUND = 2,		/* Data being read from the kernel */
+};
+
+/*
+ *  Each entry in a DGNC proc directory is described with a
+ *  "dgnc_proc_entry" structure.  A collection of these
+ *  entries (in an array) represents the members associated
+ *  with a particular "/proc" directory, and is referred to
+ *  as a table.  All "tables" are terminated by an entry with
+ *  zeros for every member.
+ *
+ *  The structure members are as follows:
+ *
+ *    int magic              -- ID number associated with this particular
+ *                              entry.  Should be unique across all of
+ *                              DGNC.
+ *
+ *    const char *name       -- ASCII name associated with the /proc entry.
+ *
+ *    mode_t mode            -- File access permisssions for the /proc entry.
+ *
+ *    dgnc_proc_entry *child -- When set, this entry refers to a directory,
+ *                              and points to the table which describes the
+ *                              entries in the subdirectory
+ *
+ *    dgnc_proc_handler *open_handler -- When set, points to the fxn which
+ *                                       does any "extra" open stuff.
+ *
+ *    dgnc_proc_handler *close_handler -- When set, points to the fxn which
+ *                                        does any "extra" close stuff.
+ *
+ *    dgnc_proc_handler *read_handler -- When set, points to the fxn which
+ *                                       handle outbound data flow
+ *
+ *    dgnc_proc_handler *write_handler -- When set, points to the fxn which
+ *                                        handles inbound data flow
+ *
+ *    struct proc_dir_entry *de -- Pointer to the directory entry for this
+ *                                 object once registered.  Used to grab
+ *                                 the handle of the object for
+ *                                 unregistration
+ *
+ *    void *data;		   When set, points to the parent structure
+ *
+ */
+
+struct dgnc_proc_entry {
+	int		magic;		/* Integer identifier	*/
+	const char	*name;		/* ASCII identifier	*/
+	mode_t		mode;		/* File access permissions */
+	struct dgnc_proc_entry *child;	/* Child pointer	*/
+
+	int (*open_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,   
+		void *buffer, ssize_t *lenp, loff_t *ppos); 
+	int (*close_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,   
+		void *buffer, ssize_t *lenp, loff_t *ppos); 
+	int (*read_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,   
+		char __user *buffer, ssize_t *lenp, loff_t *ppos); 
+	int (*write_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,   
+		const char __user *buffer, ssize_t *lenp, loff_t *ppos); 
+
+	struct proc_dir_entry *de;	/* proc entry pointer	*/
+	struct semaphore excl_sem;	/* Protects exclusive access var	*/
+	int		excl_cnt;	/* Counts number of curr accesses	*/
+	void		*data;		/* Allows storing a pointer to parent	*/
+};
+
+void dgnc_proc_register_basic_prescan(void);
+void dgnc_proc_register_basic_postscan(int board_num);
+void dgnc_proc_unregister_all(void);
+
+
+#endif /* _DGNC_RW_PROC_H */
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c
new file mode 100644
index 0000000..690d451
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_sysfs.c
@@ -0,0 +1,760 @@
+/*
+ * Copyright 2004 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot com>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * 
+ *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *      This is shared code between Digi's CVS archive and the
+ *      Linux Kernel sources.
+ *      Changing the source just for reformatting needlessly breaks
+ *      our CVS diff history.
+ *
+ *      Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *      Thank you.
+ *
+ *
+ * 
+ * $Id: dgnc_sysfs.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $   
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/serial_reg.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+  
+#include "dgnc_driver.h"
+#include "dgnc_proc.h"
+#include "dgnc_mgmt.h"
+
+
+static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
+}
+static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL);
+
+
+static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards);
+}
+static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL);
+
+
+static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
+}
+static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL);
+
+
+static ssize_t dgnc_driver_pollcounter_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%ld\n", dgnc_poll_counter);
+}
+static DRIVER_ATTR(pollcounter, S_IRUSR, dgnc_driver_pollcounter_show, NULL);
+
+
+static ssize_t dgnc_driver_state_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", dgnc_driver_state_text[dgnc_driver_state]);
+}
+static DRIVER_ATTR(state, S_IRUSR, dgnc_driver_state_show, NULL);
+
+
+static ssize_t dgnc_driver_debug_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_debug);
+}
+
+static ssize_t dgnc_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "0x%x\n", &dgnc_debug);
+	return count;
+}
+static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgnc_driver_debug_show, dgnc_driver_debug_store);
+
+
+static ssize_t dgnc_driver_rawreadok_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_rawreadok);
+}
+
+static ssize_t dgnc_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "0x%x\n", &dgnc_rawreadok);
+	return count;
+}
+static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgnc_driver_rawreadok_show, dgnc_driver_rawreadok_store);
+
+
+static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick);
+}
+
+static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "%d\n", &dgnc_poll_tick);
+	return count;
+}
+static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store);
+
+
+void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
+{
+	int rc = 0;
+	struct device_driver *driverfs = &dgnc_driver->driver;
+
+	rc |= driver_create_file(driverfs, &driver_attr_version);
+	rc |= driver_create_file(driverfs, &driver_attr_boards);
+	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
+	rc |= driver_create_file(driverfs, &driver_attr_debug);
+	rc |= driver_create_file(driverfs, &driver_attr_rawreadok); 
+	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
+	rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
+	rc |= driver_create_file(driverfs, &driver_attr_state);
+	if (rc) {
+		printk(KERN_ERR "DGNC: sysfs driver_create_file failed!\n");
+	}
+}
+
+
+void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
+{
+	struct device_driver *driverfs = &dgnc_driver->driver;
+	driver_remove_file(driverfs, &driver_attr_version);
+	driver_remove_file(driverfs, &driver_attr_boards);
+	driver_remove_file(driverfs, &driver_attr_maxboards);
+	driver_remove_file(driverfs, &driver_attr_debug);
+	driver_remove_file(driverfs, &driver_attr_rawreadok);
+	driver_remove_file(driverfs, &driver_attr_pollrate);
+	driver_remove_file(driverfs, &driver_attr_pollcounter);
+	driver_remove_file(driverfs, &driver_attr_state);
+}
+
+
+#define DGNC_VERIFY_BOARD(p, bd)			\
+	if (!p)						\
+		return (0);				\
+							\
+	bd = dev_get_drvdata(p);			\
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)	\
+		return (0);				\
+	if (bd->state != BOARD_READY)			\
+		return (0);				\
+
+
+
+static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	count += sprintf(buf + count, "\n      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
+	for (i = 0; i < 0x40 * 2; i++) {
+		if (!(i % 16))
+			count += sprintf(buf + count, "\n%04X ", i * 2);
+		count += sprintf(buf + count, "%02X ", bd->vpd[i]);
+	}
+	count += sprintf(buf + count, "\n");
+
+	return count;
+}
+static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL);
+
+static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	if (bd->serial_num[0] == '\0')
+		count += sprintf(buf + count, "<UNKNOWN>\n");
+	else
+		count += sprintf(buf + count, "%s\n", bd->serial_num);
+
+	return count;
+}
+static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL);
+
+
+static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count,
+			"%d %s\n", bd->channels[i]->ch_portnum,
+			bd->channels[i]->ch_open_count ? "Open" : "Closed");
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL);
+
+
+static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count +=  snprintf(buf + count, PAGE_SIZE - count,
+			"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_old_baud);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL);
+
+
+static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		if (bd->channels[i]->ch_open_count) {
+			count += snprintf(buf + count, PAGE_SIZE - count,
+				"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
+				(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+				(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+		} else {
+			count += snprintf(buf + count, PAGE_SIZE - count,
+				"%d\n", bd->channels[i]->ch_portnum);
+		}
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL);
+
+
+static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL);
+
+
+static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL);
+
+
+static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL);
+
+
+static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL);
+
+
+static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL);
+
+
+static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL);
+
+
+static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGNC_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL);
+
+
+/* this function creates the sys files that will export each signal status
+ * to sysfs each value will be put in a separate filename
+ */
+void dgnc_create_ports_sysfiles(struct board_t *bd)
+{
+	int rc = 0;
+
+	dev_set_drvdata(&bd->pdev->dev, bd);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_vpd);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_serial_number);
+	if (rc) {
+		printk(KERN_ERR "DGNC: sysfs device_create_file failed!\n");
+	}
+}
+
+
+/* removes all the sys files created for that port */
+void dgnc_remove_ports_sysfiles(struct board_t *bd)
+{
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_vpd);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_serial_number);
+}
+
+
+static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
+}
+static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL);
+
+
+static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
+}
+static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL);
+
+
+static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	if (ch->ch_open_count) {
+		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
+			(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+			(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+			(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+			(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+			(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+			(ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+	}
+	return 0;
+}
+static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL);
+
+
+static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
+}
+static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL);
+
+
+static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
+}
+static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL);
+
+
+static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
+}
+static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL);
+
+
+static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
+}
+static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL);
+
+
+static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
+}
+static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL);
+
+
+static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
+}
+static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL);
+
+
+static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
+}
+static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL);
+
+
+static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return (0);
+	un = (struct un_t *) dev_get_drvdata(d);
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (0);
+	if (bd->state != BOARD_READY)
+		return (0);
+
+	return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
+		(un->un_type == DGNC_PRINT) ? "pr" : "tty",
+		bd->boardnum + 1, 'a' + ch->ch_portnum);
+}
+static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL);
+
+
+static struct attribute *dgnc_sysfs_tty_entries[] = {
+	&dev_attr_state.attr,
+	&dev_attr_baud.attr,
+	&dev_attr_msignals.attr,
+	&dev_attr_iflag.attr,
+	&dev_attr_cflag.attr,
+	&dev_attr_oflag.attr,          
+	&dev_attr_lflag.attr,
+	&dev_attr_digi_flag.attr,
+	&dev_attr_rxcount.attr,
+	&dev_attr_txcount.attr,
+	&dev_attr_custom_name.attr,
+	NULL
+};
+
+
+static struct attribute_group dgnc_tty_attribute_group = {
+        .name = NULL,
+        .attrs = dgnc_sysfs_tty_entries,
+};
+
+
+void dgnc_create_tty_sysfs(struct un_t *un, struct device *c)
+{
+	int ret;
+
+	ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group);
+	if (ret) {
+		printk(KERN_ERR "dgnc: failed to create sysfs tty device attributes.\n");
+		sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
+		return;
+	}
+
+	dev_set_drvdata(c, un);
+
+}
+
+ 
+void dgnc_remove_tty_sysfs(struct device *c)
+{
+	sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
+}
+
diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h
new file mode 100644
index 0000000..fe99110
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_sysfs.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+#ifndef __DGNC_SYSFS_H
+#define __DGNC_SYSFS_H
+
+#include "dgnc_driver.h"
+
+#include <linux/device.h>
+
+struct board_t;
+struct channel_t;
+struct un_t;
+struct pci_driver;
+struct class_device;
+
+extern void dgnc_create_ports_sysfiles(struct board_t *bd); 
+extern void dgnc_remove_ports_sysfiles(struct board_t *bd);
+
+extern void dgnc_create_driver_sysfiles(struct pci_driver *);
+extern void dgnc_remove_driver_sysfiles(struct pci_driver *);
+
+extern int dgnc_tty_class_init(void);
+extern int dgnc_tty_class_destroy(void);
+
+extern void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
+extern void dgnc_remove_tty_sysfs(struct device *c);
+
+
+
+#endif
diff --git a/drivers/staging/dgnc/dgnc_trace.c b/drivers/staging/dgnc/dgnc_trace.c
new file mode 100644
index 0000000..e613a28
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_trace.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE! 
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com. 
+ *	Thank you. 
+ *
+ */
+
+/* $Id: dgnc_trace.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>	/* For jiffies, task states */
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/vmalloc.h>
+
+#include "dgnc_driver.h"
+
+#define TRC_TO_CONSOLE 1
+
+/* file level globals */
+static char *dgnc_trcbuf;		/* the ringbuffer */
+
+#if defined(TRC_TO_KMEM)
+static int dgnc_trcbufi = 0;		/* index of the tilde at the end of */
+#endif
+
+#if defined(TRC_TO_KMEM)
+static DEFINE_SPINLOCK(dgnc_tracef_lock);
+#endif
+
+
+#if 0
+
+#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
+
+void dgnc_tracef(const char *fmt, ...)
+{
+	return;
+}
+
+#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
+
+void dgnc_tracef(const char *fmt, ...)
+{
+	va_list	         ap;
+	char  	         buf[TRC_MAXMSG+1];
+	size_t		 lenbuf;
+	int		 i;
+	static int	 failed = FALSE;
+# if defined(TRC_TO_KMEM)
+	unsigned long	 flags;
+#endif
+
+	if(failed)
+		return;
+# if defined(TRC_TO_KMEM)
+	DGNC_LOCK(dgnc_tracef_lock, flags);
+#endif
+
+	/* Format buf using fmt and arguments contained in ap. */
+	va_start(ap, fmt);
+	i = vsprintf(buf, fmt,  ap);
+	va_end(ap);
+	lenbuf = strlen(buf);
+
+# if defined(TRC_TO_KMEM)
+	{
+		static int	 initd=0;
+
+		/*
+		 * Now, in addition to (or instead of) printing this stuff out
+		 * (which is a buffered operation), also tuck it away into a
+		 * corner of memory which can be examined post-crash in kdb.
+		 */
+		if (!initd) {
+			dgnc_trcbuf = (char *) vmalloc(dgnc_trcbuf_size);
+			if(!dgnc_trcbuf) {
+				failed = TRUE;
+				printk("dgnc: tracing init failed!\n");
+				return;
+			}
+
+			memset(dgnc_trcbuf, '\0',  dgnc_trcbuf_size);
+			dgnc_trcbufi = 0;
+			initd++;
+
+			printk("dgnc: tracing enabled - " TRC_DTRC 
+				" 0x%lx 0x%x\n",
+				(unsigned long)dgnc_trcbuf, 
+				dgnc_trcbuf_size);
+		}
+
+#  if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
+		/*
+		 * This is the less CPU-intensive way to do things.  We simply
+		 * wrap around before we fall off the end of the buffer.  A 
+		 * tilde (~) demarcates the current end of the trace.
+		 *
+		 * This method should be used if you are concerned about race
+		 * conditions as it is less likely to affect the timing of
+		 * things.
+		 */
+
+		if (dgnc_trcbufi + lenbuf >= dgnc_trcbuf_size) {
+			/* We are wrapping, so wipe out the last tilde. */
+			dgnc_trcbuf[dgnc_trcbufi] = '\0';
+			/* put the new string at the beginning of the buffer */
+			dgnc_trcbufi = 0;
+		}
+
+		strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);	
+		dgnc_trcbufi += lenbuf;
+		dgnc_trcbuf[dgnc_trcbufi] = '~';
+
+#  elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
+		/*
+		 * This is the more CPU-intensive way to do things.  If we
+		 * venture into the last 1/8 of the buffer, we shift the 
+		 * last 7/8 of the buffer forward, wiping out the first 1/8.
+		 * Advantage: No wrap-around, only truncation from the
+		 * beginning.
+		 *
+		 * This method should not be used if you are concerned about
+		 * timing changes affecting the behaviour of the driver (ie,
+		 * race conditions).
+		 */
+		strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
+		dgnc_trcbufi += lenbuf;
+		dgnc_trcbuf[dgnc_trcbufi] = '~';
+		dgnc_trcbuf[dgnc_trcbufi+1] = '\0';
+
+		/* If we're near the end of the trace buffer... */
+		if (dgnc_trcbufi > (dgnc_trcbuf_size/8)*7) {
+			/* Wipe out the first eighth to make some more room. */
+			strcpy(dgnc_trcbuf, &dgnc_trcbuf[dgnc_trcbuf_size/8]);
+			dgnc_trcbufi = strlen(dgnc_trcbuf)-1;
+			/* Plop overflow message at the top of the buffer. */
+			bcopy(TRC_OVERFLOW, dgnc_trcbuf, strlen(TRC_OVERFLOW));
+		}
+#  else
+#   error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
+#  endif
+	}
+	DGNC_UNLOCK(dgnc_tracef_lock, flags);
+
+# endif /* defined(TRC_TO_KMEM) */
+}
+
+#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
+
+#endif
+
+
+/*
+ * dgnc_tracer_free()
+ *
+ *
+ */
+void dgnc_tracer_free(void)
+{
+	if(dgnc_trcbuf)
+		vfree(dgnc_trcbuf);
+}
diff --git a/drivers/staging/dgnc/dgnc_trace.h b/drivers/staging/dgnc/dgnc_trace.h
new file mode 100644
index 0000000..1e8870b
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_trace.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *****************************************************************************
+ * Header file for dgnc_trace.c
+ *
+ * $Id: dgnc_trace.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
+ */
+
+#ifndef __DGNC_TRACE_H
+#define __DGNC_TRACE_H
+
+#include "dgnc_driver.h"
+
+#if 0
+
+# if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
+   void dgnc_tracef(const char *fmt, ...);
+# else
+   void dgnc_tracef(const char *fmt, ...);
+# endif
+
+#endif
+
+void dgnc_tracer_free(void);
+
+#endif
+
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c
new file mode 100644
index 0000000..461e881
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_tty.c
@@ -0,0 +1,3648 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE! 
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com. 
+ *	Thank you. 
+ */
+
+/************************************************************************
+ * 
+ * This file implements the tty driver functionality for the
+ * Neo and ClassicBoard PCI based product lines.
+ * 
+ ************************************************************************
+ *
+ * $Id: dgnc_tty.c,v 1.5 2013/04/30 19:18:30 markh Exp $
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/sched.h>	/* For jiffies, task states */
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/slab.h>
+#include <linux/delay.h>        /* For udelay */
+#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
+#include <linux/pci.h>
+
+#include "dgnc_driver.h"
+#include "dgnc_tty.h"
+#include "dgnc_types.h"
+#include "dgnc_trace.h"
+#include "dgnc_neo.h"
+#include "dgnc_cls.h"
+#include "dpacompat.h"
+#include "dgnc_sysfs.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+#define init_MUTEX(sem)         sema_init(sem, 1)
+#define DECLARE_MUTEX(name)     \
+        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
+#endif
+
+/*
+ * internal variables
+ */
+static struct board_t	*dgnc_BoardsByMajor[256];
+static uchar		*dgnc_TmpWriteBuf = NULL;
+static DECLARE_MUTEX(dgnc_TmpWriteSem);
+
+/*
+ * Default transparent print information.
+ */
+static struct digi_t dgnc_digi_init = {
+	.digi_flags =	DIGI_COOK,	/* Flags			*/
+	.digi_maxcps =	100,		/* Max CPS			*/
+	.digi_maxchar =	50,		/* Max chars in print queue	*/
+	.digi_bufsize =	100,		/* Printer buffer size		*/
+	.digi_onlen =	4,		/* size of printer on string	*/
+	.digi_offlen =	4,		/* size of printer off string	*/
+	.digi_onstr =	"\033[5i",	/* ANSI printer on string ]	*/
+	.digi_offstr =	"\033[4i",	/* ANSI printer off string ]	*/
+	.digi_term =	"ansi"		/* default terminal type	*/
+};
+
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.
+ *
+ * This defines a raw port at 9600 baud, 8 data bits, no parity,
+ * 1 stop bit.
+ */
+static struct ktermios DgncDefaultTermios =
+{
+	.c_iflag =	(DEFAULT_IFLAGS),	/* iflags */
+	.c_oflag =	(DEFAULT_OFLAGS),	/* oflags */
+	.c_cflag =	(DEFAULT_CFLAGS),	/* cflags */
+	.c_lflag =	(DEFAULT_LFLAGS),	/* lflags */
+	.c_cc =		INIT_C_CC,
+	.c_line =	0,
+};
+
+
+/* Our function prototypes */
+static int dgnc_tty_open(struct tty_struct *tty, struct file *file);
+static void dgnc_tty_close(struct tty_struct *tty, struct file *file);
+static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch);
+static int dgnc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
+static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
+static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
+static int dgnc_tty_write_room(struct tty_struct* tty);
+static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c);
+static int dgnc_tty_chars_in_buffer(struct tty_struct* tty);
+static void dgnc_tty_start(struct tty_struct *tty);
+static void dgnc_tty_stop(struct tty_struct *tty);
+static void dgnc_tty_throttle(struct tty_struct *tty);
+static void dgnc_tty_unthrottle(struct tty_struct *tty);
+static void dgnc_tty_flush_chars(struct tty_struct *tty);
+static void dgnc_tty_flush_buffer(struct tty_struct *tty);
+static void dgnc_tty_hangup(struct tty_struct *tty);
+static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
+static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+static int dgnc_tty_tiocmget(struct tty_struct *tty);
+static int dgnc_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
+#else
+static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file);
+static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
+#endif
+static int dgnc_tty_send_break(struct tty_struct *tty, int msec);
+static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout);
+static int dgnc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
+static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+static void dgnc_tty_send_xchar(struct tty_struct *tty, char ch);
+
+
+static const struct tty_operations dgnc_tty_ops = {
+	.open = dgnc_tty_open,
+	.close = dgnc_tty_close,
+	.write = dgnc_tty_write,
+	.write_room = dgnc_tty_write_room,
+	.flush_buffer = dgnc_tty_flush_buffer,
+	.chars_in_buffer = dgnc_tty_chars_in_buffer,
+	.flush_chars = dgnc_tty_flush_chars,
+	.ioctl = dgnc_tty_ioctl,
+	.set_termios = dgnc_tty_set_termios,
+	.stop = dgnc_tty_stop,
+	.start = dgnc_tty_start,
+	.throttle = dgnc_tty_throttle,
+	.unthrottle = dgnc_tty_unthrottle,
+	.hangup = dgnc_tty_hangup,
+	.put_char = dgnc_tty_put_char,
+	.tiocmget = dgnc_tty_tiocmget,
+	.tiocmset = dgnc_tty_tiocmset,
+	.break_ctl = dgnc_tty_send_break,
+	.wait_until_sent = dgnc_tty_wait_until_sent,
+	.send_xchar = dgnc_tty_send_xchar
+};
+
+/************************************************************************
+ *                      
+ * TTY Initialization/Cleanup Functions
+ *      
+ ************************************************************************/
+         
+/*
+ * dgnc_tty_preinit()
+ *
+ * Initialize any global tty related data before we download any boards.
+ */
+int dgnc_tty_preinit(void)
+{
+	/*
+	 * Allocate a buffer for doing the copy from user space to
+	 * kernel space in dgnc_write().  We only use one buffer and
+	 * control access to it with a semaphore.  If we are paging, we
+	 * are already in trouble so one buffer won't hurt much anyway.
+	 *
+	 * We are okay to sleep in the malloc, as this routine
+	 * is only called during module load, (not in interrupt context),
+	 * and with no locks held.
+	 */
+	dgnc_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_KERNEL);
+
+	if (!dgnc_TmpWriteBuf) {
+		DPR_INIT(("unable to allocate tmp write buf"));
+		return (-ENOMEM);
+	}
+
+	return(0);
+}
+
+
+/*
+ * dgnc_tty_register()
+ *
+ * Init the tty subsystem for this board.
+ */
+int dgnc_tty_register(struct board_t *brd)
+{
+	int rc = 0;
+
+	DPR_INIT(("tty_register start\n"));
+
+        memset(&brd->SerialDriver, 0, sizeof(struct tty_driver));
+	memset(&brd->PrintDriver, 0, sizeof(struct tty_driver));
+
+	brd->SerialDriver.magic = TTY_DRIVER_MAGIC;
+	
+	snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum);
+
+	brd->SerialDriver.name = brd->SerialName;
+	brd->SerialDriver.name_base = 0;
+	brd->SerialDriver.major = 0;
+	brd->SerialDriver.minor_start = 0;
+	brd->SerialDriver.num = brd->maxports;
+	brd->SerialDriver.type = TTY_DRIVER_TYPE_SERIAL; 
+	brd->SerialDriver.subtype = SERIAL_TYPE_NORMAL;   
+	brd->SerialDriver.init_termios = DgncDefaultTermios;
+	brd->SerialDriver.driver_name = DRVSTR;
+	brd->SerialDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+	/* 
+	 * The kernel wants space to store pointers to
+	 * tty_struct's and termios's. 
+	 */
+	brd->SerialDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
+	if (!brd->SerialDriver.ttys)
+		return(-ENOMEM);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+        brd->SerialDriver.refcount = brd->TtyRefCnt;
+#else
+        kref_init(&brd->SerialDriver.kref);
+#endif
+
+	brd->SerialDriver.termios = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+	if (!brd->SerialDriver.termios)
+		return(-ENOMEM);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
+	brd->SerialDriver.termios_locked = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+	if (!brd->SerialDriver.termios_locked)
+		return(-ENOMEM);
+#endif
+	/*
+	 * Entry points for driver.  Called by the kernel from
+	 * tty_io.c and n_tty.c.
+	 */
+	tty_set_operations(&brd->SerialDriver, &dgnc_tty_ops);
+
+	if (!brd->dgnc_Major_Serial_Registered) {
+		/* Register tty devices */
+		rc = tty_register_driver(&brd->SerialDriver);
+		if (rc < 0) {
+			APR(("Can't register tty device (%d)\n", rc));
+			return(rc);
+		}
+		brd->dgnc_Major_Serial_Registered = TRUE;
+	}
+
+	/*
+	 * If we're doing transparent print, we have to do all of the above
+	 * again, seperately so we don't get the LD confused about what major
+	 * we are when we get into the dgnc_tty_open() routine.
+	 */
+	brd->PrintDriver.magic = TTY_DRIVER_MAGIC;
+	snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum);
+
+	brd->PrintDriver.name = brd->PrintName;
+	brd->PrintDriver.name_base = 0;
+	brd->PrintDriver.major = brd->SerialDriver.major;
+	brd->PrintDriver.minor_start = 0x80;
+	brd->PrintDriver.num = brd->maxports;
+	brd->PrintDriver.type = TTY_DRIVER_TYPE_SERIAL;   
+	brd->PrintDriver.subtype = SERIAL_TYPE_NORMAL;
+	brd->PrintDriver.init_termios = DgncDefaultTermios;
+	brd->PrintDriver.driver_name = DRVSTR;
+	brd->PrintDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+	/*
+	 * The kernel wants space to store pointers to
+	 * tty_struct's and termios's.  Must be seperate from
+	 * the Serial Driver so we don't get confused
+	 */
+	brd->PrintDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
+	if (!brd->PrintDriver.ttys)
+		return(-ENOMEM);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+        brd->PrintDriver.refcount = brd->TtyRefCnt;
+#else
+        kref_init(&brd->PrintDriver.kref);
+#endif
+
+	brd->PrintDriver.termios = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+	if (!brd->PrintDriver.termios)
+		return(-ENOMEM);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
+	brd->PrintDriver.termios_locked = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+	if (!brd->PrintDriver.termios_locked)
+		return(-ENOMEM);
+#endif
+
+	/*
+	 * Entry points for driver.  Called by the kernel from
+	 * tty_io.c and n_tty.c.
+	 */
+	tty_set_operations(&brd->PrintDriver, &dgnc_tty_ops);
+
+	if (!brd->dgnc_Major_TransparentPrint_Registered) {
+		/* Register Transparent Print devices */
+ 		rc = tty_register_driver(&brd->PrintDriver);
+		if (rc < 0) {
+			APR(("Can't register Transparent Print device (%d)\n", rc));
+			return(rc);
+		}
+		brd->dgnc_Major_TransparentPrint_Registered = TRUE;
+	}
+
+	dgnc_BoardsByMajor[brd->SerialDriver.major] = brd;
+	brd->dgnc_Serial_Major = brd->SerialDriver.major;
+	brd->dgnc_TransparentPrint_Major = brd->PrintDriver.major;
+
+	DPR_INIT(("DGNC REGISTER TTY: MAJOR: %d\n", brd->SerialDriver.major));
+
+	return (rc);
+}
+
+
+/*
+ * dgnc_tty_init()
+ *
+ * Init the tty subsystem.  Called once per board after board has been
+ * downloaded and init'ed.
+ */
+int dgnc_tty_init(struct board_t *brd)
+{
+	int i;
+	uchar *vaddr;
+	struct channel_t *ch;
+
+	if (!brd)
+		return (-ENXIO);
+
+	DPR_INIT(("dgnc_tty_init start\n"));
+
+	/*
+	 * Initialize board structure elements.
+	 */
+
+	vaddr = brd->re_map_membase;
+
+	brd->nasync = brd->maxports;
+
+	/*
+	 * Allocate channel memory that might not have been allocated
+	 * when the driver was first loaded.
+	 */
+	for (i = 0; i < brd->nasync; i++) {
+		if (!brd->channels[i]) {
+
+			/*
+			 * Okay to malloc with GFP_KERNEL, we are not at
+			 * interrupt context, and there are no locks held.
+			 */
+			brd->channels[i] = dgnc_driver_kzmalloc(sizeof(struct channel_t), GFP_KERNEL);
+			if (!brd->channels[i]) {
+				DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
+				    __FILE__, __LINE__));
+			}
+		}
+	}
+
+	ch = brd->channels[0];
+	vaddr = brd->re_map_membase;
+
+	/* Set up channel variables */
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+		if (!brd->channels[i])
+			continue;
+
+		DGNC_SPINLOCK_INIT(ch->ch_lock);
+
+		/* Store all our magic numbers */
+		ch->magic = DGNC_CHANNEL_MAGIC;
+		ch->ch_tun.magic = DGNC_UNIT_MAGIC;
+		ch->ch_tun.un_ch = ch;
+		ch->ch_tun.un_type = DGNC_SERIAL;
+		ch->ch_tun.un_dev = i;
+
+		ch->ch_pun.magic = DGNC_UNIT_MAGIC;
+		ch->ch_pun.un_ch = ch;
+		ch->ch_pun.un_type = DGNC_PRINT;
+		ch->ch_pun.un_dev = i + 128;
+
+		if (brd->bd_uart_offset == 0x200)
+			ch->ch_neo_uart = (struct neo_uart_struct *) ((ulong) vaddr + (brd->bd_uart_offset * i));
+		else
+			ch->ch_cls_uart = (struct cls_uart_struct *) ((ulong) vaddr + (brd->bd_uart_offset * i));
+
+		ch->ch_bd = brd;
+		ch->ch_portnum = i;
+		ch->ch_digi = dgnc_digi_init;
+
+		/* .25 second delay */
+		ch->ch_close_delay = 250;
+
+		init_waitqueue_head(&ch->ch_flags_wait);
+		init_waitqueue_head(&ch->ch_tun.un_flags_wait);
+		init_waitqueue_head(&ch->ch_pun.un_flags_wait);
+		init_waitqueue_head(&ch->ch_sniff_wait);
+
+		{
+			struct device *classp;
+			classp = tty_register_device(&brd->SerialDriver, i,
+				&(ch->ch_bd->pdev->dev));
+			ch->ch_tun.un_sysfs = classp;
+			dgnc_create_tty_sysfs(&ch->ch_tun, classp);
+
+			classp = tty_register_device(&brd->PrintDriver, i,
+				&(ch->ch_bd->pdev->dev));
+			ch->ch_pun.un_sysfs = classp;
+			dgnc_create_tty_sysfs(&ch->ch_pun, classp);
+		}
+
+	}
+
+	DPR_INIT(("dgnc_tty_init finish\n"));
+
+	return (0);
+}
+
+
+/*
+ * dgnc_tty_post_uninit()
+ *
+ * UnInitialize any global tty related data.
+ */
+void dgnc_tty_post_uninit(void)
+{
+	if (dgnc_TmpWriteBuf) {
+		kfree(dgnc_TmpWriteBuf);
+		dgnc_TmpWriteBuf = NULL;
+	}
+}
+
+
+/*
+ * dgnc_tty_uninit()
+ *
+ * Uninitialize the TTY portion of this driver.  Free all memory and
+ * resources. 
+ */
+void dgnc_tty_uninit(struct board_t *brd)
+{
+	int i = 0;
+
+	if (brd->dgnc_Major_Serial_Registered) {
+		dgnc_BoardsByMajor[brd->SerialDriver.major] = NULL;
+		brd->dgnc_Serial_Major = 0;
+		for (i = 0; i < brd->nasync; i++) {
+			dgnc_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
+			tty_unregister_device(&brd->SerialDriver, i);
+		}
+		tty_unregister_driver(&brd->SerialDriver);
+		brd->dgnc_Major_Serial_Registered = FALSE;
+	}
+
+	if (brd->dgnc_Major_TransparentPrint_Registered) {
+		dgnc_BoardsByMajor[brd->PrintDriver.major] = NULL;
+		brd->dgnc_TransparentPrint_Major = 0;
+		for (i = 0; i < brd->nasync; i++) {
+			dgnc_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
+			tty_unregister_device(&brd->PrintDriver, i);
+		}
+		tty_unregister_driver(&brd->PrintDriver);
+		brd->dgnc_Major_TransparentPrint_Registered = FALSE;
+	}
+
+	if (brd->SerialDriver.ttys) {
+		kfree(brd->SerialDriver.ttys);
+		brd->SerialDriver.ttys = NULL;
+	}
+	if (brd->PrintDriver.ttys) {
+		kfree(brd->PrintDriver.ttys);
+		brd->PrintDriver.ttys = NULL;
+        }
+}
+
+
+#define TMPBUFLEN (1024)
+
+/*
+ * dgnc_sniff - Dump data out to the "sniff" buffer if the
+ * proc sniff file is opened...
+ */
+void dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len)
+{
+	struct timeval tv;
+	int n;
+	int r;
+	int nbuf;
+	int i;
+	int tmpbuflen;
+	char tmpbuf[TMPBUFLEN];
+	char *p = tmpbuf;
+	int too_much_data;
+
+	/* Leave if sniff not open */
+	if (!(ch->ch_sniff_flags & SNIFF_OPEN))
+		return;
+
+	do_gettimeofday(&tv);
+
+	/* Create our header for data dump */
+	p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
+	tmpbuflen = p - tmpbuf;
+
+	do {
+		too_much_data = 0;
+
+		for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
+			p += sprintf(p, "%02x ", *buf);
+			buf++;
+			tmpbuflen = p - tmpbuf;
+		}
+
+		if (tmpbuflen < (TMPBUFLEN - 4)) {
+			if (i > 0)
+				p += sprintf(p - 1, "%s\n", ">");
+			else
+				p += sprintf(p, "%s\n", ">");
+		} else {
+			too_much_data = 1;
+			len -= i;
+		}
+
+		nbuf = strlen(tmpbuf);
+		p = tmpbuf;
+
+		/*
+		 *  Loop while data remains.
+		 */
+		while (nbuf > 0 && ch->ch_sniff_buf != 0) {
+			/*
+			 *  Determine the amount of available space left in the
+			 *  buffer.  If there's none, wait until some appears.
+			 */
+			n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
+
+			/*
+			 * If there is no space left to write to in our sniff buffer,
+			 * we have no choice but to drop the data.
+			 * We *cannot* sleep here waiting for space, because this
+			 * function was probably called by the interrupt/timer routines!
+			 */
+			if (n == 0) {
+				return;
+			}
+	
+			/*
+			 * Copy as much data as will fit.
+			 */
+
+			if (n > nbuf)
+				n = nbuf;
+
+			r = SNIFF_MAX - ch->ch_sniff_in;
+
+			if (r <= n) {
+				memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
+
+				n -= r;
+				ch->ch_sniff_in = 0;
+				p += r;
+				nbuf -= r;
+			}
+
+			memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
+
+			ch->ch_sniff_in += n;
+			p += n;
+			nbuf -= n;
+
+			/*
+			 *  Wakeup any thread waiting for data
+			 */
+			if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
+				ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
+				wake_up_interruptible(&ch->ch_sniff_wait);
+			}
+		}
+
+		/*
+		 * If the user sent us too much data to push into our tmpbuf,
+		 * we need to keep looping around on all the data.
+		 */
+		if (too_much_data) {
+			p = tmpbuf;
+			tmpbuflen = 0;
+		}
+
+	} while (too_much_data);
+}
+
+
+/*=======================================================================
+ *
+ *	dgnc_wmove - Write data to transmit queue.
+ *
+ *		ch	- Pointer to channel structure.
+ *		buf	- Poiter to characters to be moved.
+ *		n	- Number of characters to move.
+ *
+ *=======================================================================*/
+static void dgnc_wmove(struct channel_t *ch, char *buf, uint n)
+{
+	int	remain;
+	uint	head;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+ 
+	head = ch->ch_w_head & WQUEUEMASK;
+
+	/*
+	 * If the write wraps over the top of the circular buffer,
+	 * move the portion up to the wrap point, and reset the
+	 * pointers to the bottom.
+	 */
+	remain = WQUEUESIZE - head;
+
+	if (n >= remain) {
+		n -= remain;  
+		memcpy(ch->ch_wqueue + head, buf, remain);
+		head = 0;
+		buf += remain;
+	}
+
+	if (n > 0) {
+		/*
+		 * Move rest of data.
+		 */
+		remain = n;
+		memcpy(ch->ch_wqueue + head, buf, remain);
+		head += remain;
+	}
+
+	head &= WQUEUEMASK;
+	ch->ch_w_head = head;
+}
+
+
+
+
+/*=======================================================================
+ *
+ *      dgnc_input - Process received data.
+ * 
+ *              ch      - Pointer to channel structure.
+ * 
+ *=======================================================================*/
+void dgnc_input(struct channel_t *ch)
+{
+	struct board_t *bd;
+	struct tty_struct *tp;
+	struct tty_ldisc *ld;
+	uint	rmask;
+	ushort	head;
+	ushort	tail;
+	int	data_len;
+	ulong	lock_flags;
+	int flip_len;
+	int len = 0;
+	int n = 0;
+	char *buf = NULL;
+	int s = 0;
+	int i = 0;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	tp = ch->ch_tun.un_tty;
+
+	bd = ch->ch_bd;
+	if(!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* 
+	 *      Figure the number of characters in the buffer.   
+	 *      Exit immediately if none.
+	 */
+	rmask = RQUEUEMASK;
+	head = ch->ch_r_head & rmask;
+	tail = ch->ch_r_tail & rmask;
+	data_len = (head - tail) & rmask;
+
+	if (data_len == 0) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	DPR_READ(("dgnc_input start\n"));
+
+	/*
+	 * If the device is not open, or CREAD is off,
+         * flush input data and return immediately.
+	 */
+	if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || 
+	    !(tp->termios->c_cflag & CREAD) || (ch->ch_tun.un_flags & UN_CLOSING)) {
+
+		DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum));
+		DPR_READ(("input. tp: %p tp->magic: %x MAGIC:%x ch flags: %x\n",
+			tp, tp ? tp->magic : 0, TTY_MAGIC, ch->ch_tun.un_flags));
+
+		ch->ch_r_head = tail;
+
+		/* Force queue flow control to be released, if needed */
+		dgnc_check_queue_flow_control(ch);
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If we are throttled, simply don't read any data.
+	 */
+	if (ch->ch_flags & CH_FORCED_STOPI) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		DPR_READ(("Port %d throttled, not reading any data. head: %x tail: %x\n",
+			ch->ch_portnum, head, tail));
+		return;
+	}
+
+	DPR_READ(("dgnc_input start 2\n"));
+
+	/* Decide how much data we can send into the tty layer */
+	if (dgnc_rawreadok && tp->real_raw)
+		flip_len = MYFLIPLEN;
+	else
+		flip_len = TTY_FLIPBUF_SIZE;
+
+	/* Chop down the length, if needed */
+	len = min(data_len, flip_len);
+	len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
+
+	ld = tty_ldisc_ref(tp);
+
+#ifdef TTY_DONT_FLIP
+	/*
+	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
+	 * like the ld doesn't have any space to put the data right now.
+	 */
+	if (test_bit(TTY_DONT_FLIP, &tp->flags))
+		len = 0;
+#endif
+
+	/*
+	 * If we were unable to get a reference to the ld,
+	 * don't flush our buffer, and act like the ld doesn't
+	 * have any space to put the data right now.
+	 */
+	if (!ld) {
+		len = 0;
+	} else {
+		/*
+		 * If ld doesn't have a pointer to a receive_buf function,
+		 * flush the data, then act like the ld doesn't have any
+		 * space to put the data right now.
+		 */
+		if (!ld->ops->receive_buf) {
+			ch->ch_r_head = ch->ch_r_tail;
+			len = 0;
+		} 
+	}
+
+	if (len <= 0) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		if (ld)
+			tty_ldisc_deref(ld);
+		return;
+	}
+
+	/*
+	 * The tty layer in the kernel has changed in 2.6.16+.
+	 *
+	 * The flip buffers in the tty structure are no longer exposed,
+	 * and probably will be going away eventually.
+	 * 
+	 * If we are completely raw, we don't need to go through a lot
+	 * of the tty layers that exist.
+	 * In this case, we take the shortest and fastest route we
+	 * can to relay the data to the user.
+	 *
+	 * On the other hand, if we are not raw, we need to go through
+	 * the new 2.6.16+ tty layer, which has its API more well defined.
+	 */
+	if (dgnc_rawreadok && tp->real_raw) {
+
+		if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
+			DPR_READ(("DGNC - FLIPBUF in use. delaying input\n"));
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			if (ld)
+				tty_ldisc_deref(ld);
+			return;
+		}
+
+		ch->ch_flags |= CH_FLIPBUF_IN_USE;
+		buf = ch->ch_bd->flipbuf;
+
+		n = len;
+
+		/*
+		 * n now contains the most amount of data we can copy,
+		 * bounded either by the flip buffer size or the amount
+		 * of data the card actually has pending...
+		 */
+		while (n) {
+			s = ((head >= tail) ? head : RQUEUESIZE) - tail;
+			s = min(s, n);
+
+			if (s <= 0)
+				break;
+
+			memcpy(buf, ch->ch_rqueue + tail, s);
+			dgnc_sniff_nowait_nolock(ch, "USER READ", ch->ch_rqueue + tail, s);
+
+			tail += s;
+			buf += s;
+
+			n -= s;
+			/* Flip queue if needed */
+			tail &= rmask;
+		}
+
+		ch->ch_r_tail = tail & rmask;
+		ch->ch_e_tail = tail & rmask;
+
+		dgnc_check_queue_flow_control(ch);
+
+		/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		DPR_READ(("dgnc_input. %d real_raw len:%d calling receive_buf for buffer for board %d\n", 
+			 __LINE__, len, ch->ch_bd->boardnum));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+		tp->ldisc->ops->receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
+#else
+		tp->ldisc.ops->receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
+#endif
+
+		/* Allow use of channel flip buffer again */
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	}
+	else {
+		len = tty_buffer_request_room(tp, len);
+		n = len;
+
+		/*
+		 * n now contains the most amount of data we can copy,
+		 * bounded either by how much the Linux tty layer can handle,
+		 * or the amount of data the card actually has pending...
+		 */
+		while (n) {
+			s = ((head >= tail) ? head : RQUEUESIZE) - tail;
+			s = min(s, n);
+
+			if (s <= 0)
+				break;
+
+			/*
+			 * If conditions are such that ld needs to see all 
+			 * UART errors, we will have to walk each character
+			 * and error byte and send them to the buffer one at
+			 * a time.
+			 */
+			if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+				for (i = 0; i < s; i++) {
+					if (*(ch->ch_equeue + tail + i) & UART_LSR_BI)
+						tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_BREAK);
+					else if (*(ch->ch_equeue + tail + i) & UART_LSR_PE)
+						tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_PARITY);
+					else if (*(ch->ch_equeue + tail + i) & UART_LSR_FE)
+						tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_FRAME);
+					else
+						tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_NORMAL);
+				}
+			}
+			else {
+				tty_insert_flip_string(tp, ch->ch_rqueue + tail, s);
+			}
+
+			dgnc_sniff_nowait_nolock(ch, "USER READ", ch->ch_rqueue + tail, s);
+
+			tail += s;
+			n -= s;
+			/* Flip queue if needed */
+			tail &= rmask;
+		}
+
+		ch->ch_r_tail = tail & rmask;
+		ch->ch_e_tail = tail & rmask;
+		dgnc_check_queue_flow_control(ch);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* Tell the tty layer its okay to "eat" the data now */
+		tty_flip_buffer_push(tp);
+	}
+
+	if (ld)
+		tty_ldisc_deref(ld);
+
+	DPR_READ(("dgnc_input - finish\n"));
+}
+
+
+/************************************************************************   
+ * Determines when CARRIER changes state and takes appropriate
+ * action. 
+ ************************************************************************/
+void dgnc_carrier(struct channel_t *ch)
+{
+	struct board_t *bd;
+
+        int virt_carrier = 0;
+        int phys_carrier = 0;
+ 
+	DPR_CARR(("dgnc_carrier called...\n"));
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	if (ch->ch_mistat & UART_MSR_DCD) {
+		DPR_CARR(("mistat: %x  D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD));
+		phys_carrier = 1;
+	}
+
+	if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) {
+		virt_carrier = 1;
+	}  
+
+	if (ch->ch_c_cflag & CLOCAL) {
+		virt_carrier = 1;
+	}  
+
+
+	DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier));
+
+	/*
+	 * Test for a VIRTUAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		DPR_CARR(("carrier: virt DCD rose\n"));
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 * Test for a PHYSICAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		DPR_CARR(("carrier: physical DCD rose\n"));
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 *  Test for a PHYSICAL transition to low, so long as we aren't
+	 *  currently ignoring physical transitions (which is what "virtual
+	 *  carrier" indicates).
+	 *
+	 *  The transition of the virtual carrier to low really doesn't
+	 *  matter... it really only means "ignore carrier state", not
+	 *  "make pretend that carrier is there".
+	 */
+	if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) &&
+	    (phys_carrier == 0)) 
+	{
+
+		/*
+		 *   When carrier drops:
+		 *
+		 *   Drop carrier on all open units.
+		 *
+		 *   Flush queues, waking up any task waiting in the
+		 *   line discipline.
+		 *
+		 *   Send a hangup to the control terminal.
+		 *
+		 *   Enable all select calls.
+		 */
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+
+		if (ch->ch_tun.un_open_count > 0) {
+			DPR_CARR(("Sending tty hangup\n"));
+			tty_hangup(ch->ch_tun.un_tty);
+		}
+
+		if (ch->ch_pun.un_open_count > 0) { 
+			DPR_CARR(("Sending pr hangup\n"));
+			tty_hangup(ch->ch_pun.un_tty);
+		}
+	}
+
+	/*
+	 *  Make sure that our cached values reflect the current reality.
+	 */
+	if (virt_carrier == 1)
+		ch->ch_flags |= CH_FCAR;
+	else      
+		ch->ch_flags &= ~CH_FCAR;
+
+	if (phys_carrier == 1)
+		ch->ch_flags |= CH_CD;
+	else
+		ch->ch_flags &= ~CH_CD;
+}
+
+/*
+ *  Assign the custom baud rate to the channel structure
+ */
+static void dgnc_set_custom_speed(struct channel_t *ch, uint newrate)
+{
+	int testdiv;
+	int testrate_high;
+	int testrate_low;  
+	int deltahigh;
+	int deltalow;
+
+	if (newrate < 0)
+		newrate = 0;
+
+	/*
+	 *  Since the divisor is stored in a 16-bit integer, we make sure
+	 *  we don't allow any rates smaller than a 16-bit integer would allow.
+	 *  And of course, rates above the dividend won't fly.
+	 */
+	if (newrate && newrate < ((ch->ch_bd->bd_dividend / 0xFFFF) + 1))
+		newrate = ((ch->ch_bd->bd_dividend / 0xFFFF) + 1);
+
+	if (newrate && newrate > ch->ch_bd->bd_dividend)
+                newrate = ch->ch_bd->bd_dividend;
+
+	while (newrate > 0) {
+		testdiv = ch->ch_bd->bd_dividend / newrate;
+
+		/*
+		 *  If we try to figure out what rate the board would use
+		 *  with the test divisor, it will be either equal or higher
+		 *  than the requested baud rate.  If we then determine the
+		 *  rate with a divisor one higher, we will get the next lower 
+		 *  supported rate below the requested.
+		 */
+		testrate_high = ch->ch_bd->bd_dividend / testdiv;
+		testrate_low  = ch->ch_bd->bd_dividend / (testdiv + 1);
+
+		/*
+		 *  If the rate for the requested divisor is correct, just
+		 *  use it and be done.
+		 */
+		if (testrate_high == newrate )
+			break;
+
+		/*
+		 *  Otherwise, pick the rate that is closer (i.e. whichever rate
+		 *  has a smaller delta).
+		 */
+		deltahigh = testrate_high - newrate;
+		deltalow = newrate - testrate_low;
+
+		if (deltahigh < deltalow) {
+			newrate = testrate_high;
+                } else {
+			newrate = testrate_low;
+		}
+
+		break;
+	}
+                 
+	ch->ch_custom_speed = newrate;
+
+	return;
+}
+
+
+void dgnc_check_queue_flow_control(struct channel_t *ch)
+{
+	int qleft = 0;
+
+	/* Store how much space we have left in the queue */
+	if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0)
+		qleft += RQUEUEMASK + 1;
+
+	/*
+	 * Check to see if we should enforce flow control on our queue because
+	 * the ld (or user) isn't reading data out of our queue fast enuf.
+	 *
+	 * NOTE: This is done based on what the current flow control of the
+	 * port is set for.
+	 *
+	 * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt.
+	 *	This will cause the UART's FIFO to back up, and force
+	 *	the RTS signal to be dropped.
+	 * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to
+	 *	the other side, in hopes it will stop sending data to us.
+	 * 3) NONE - Nothing we can do.  We will simply drop any extra data
+	 *	that gets sent into us when the queue fills up.
+	 */
+	if (qleft < 256) {
+		/* HWFLOW */
+		if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
+			if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
+				ch->ch_bd->bd_ops->disable_receiver(ch);
+				ch->ch_flags |= (CH_RECEIVER_OFF);
+				DPR_READ(("Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
+					qleft));
+			}
+		}
+		/* SWFLOW */
+		else if (ch->ch_c_iflag & IXOFF) {
+			if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
+				ch->ch_bd->bd_ops->send_stop_character(ch);
+				ch->ch_stops_sent++;
+				DPR_READ(("Sending stop char!  Times sent: %x\n", ch->ch_stops_sent));
+			}
+		}
+		/* No FLOW */
+		else {
+			/* Empty... Can't do anything about the impending overflow... */
+		}
+	}
+
+	/*
+	 * Check to see if we should unenforce flow control because
+	 * ld (or user) finally read enuf data out of our queue.
+	 *
+	 * NOTE: This is done based on what the current flow control of the
+	 * port is set for.
+	 *
+	 * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt.
+	 *	This will cause the UART's FIFO to raise RTS back up,
+	 *	which will allow the other side to start sending data again.
+	 * 2) SWFLOW (IXOFF) - Send a start character to
+	 *	the other side, so it will start sending data to us again.
+	 * 3) NONE - Do nothing. Since we didn't do anything to turn off the
+	 *	other side, we don't need to do anything now.
+	 */
+	if (qleft > (RQUEUESIZE / 2)) {
+		/* HWFLOW */
+		if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
+			if (ch->ch_flags & CH_RECEIVER_OFF) {
+				ch->ch_bd->bd_ops->enable_receiver(ch);
+				ch->ch_flags &= ~(CH_RECEIVER_OFF);
+				DPR_READ(("Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
+					qleft));
+			}
+		}
+		/* SWFLOW */
+		else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
+			ch->ch_stops_sent = 0;
+			ch->ch_bd->bd_ops->send_start_character(ch);
+			DPR_READ(("Sending start char!\n"));
+		}
+		/* No FLOW */
+		else {
+			/* Nothing needed. */
+		}
+	}
+}
+
+
+void dgnc_wakeup_writes(struct channel_t *ch)
+{
+	int qlen = 0;
+	ulong lock_flags;
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * If channel now has space, wake up anyone waiting on the condition.
+	 */
+	if ((qlen = ch->ch_w_head - ch->ch_w_tail) < 0)
+                qlen += WQUEUESIZE;
+
+	if (qlen >= (WQUEUESIZE - 256)) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	if (ch->ch_tun.un_flags & UN_ISOPEN) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+                if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+                        ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
+                {
+                        DGNC_UNLOCK(ch->ch_lock, lock_flags);
+                        (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+                        DGNC_LOCK(ch->ch_lock, lock_flags);
+                }
+#else
+		if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+			ch->ch_tun.un_tty->ldisc.ops->write_wakeup)
+		{
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			(ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty);
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+		}
+#endif
+
+		wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+
+		/*
+		 * If unit is set to wait until empty, check to make sure
+		 * the queue AND FIFO are both empty.
+		 */
+		if (ch->ch_tun.un_flags & UN_EMPTY) {
+			if ((qlen == 0) && (ch->ch_bd->bd_ops->get_uart_bytes_left(ch) == 0)) {
+				ch->ch_tun.un_flags &= ~(UN_EMPTY);
+
+				/*
+				 * If RTS Toggle mode is on, whenever
+				 * the queue and UART is empty, keep RTS low.
+				 */
+				if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
+					ch->ch_mostat &= ~(UART_MCR_RTS);
+					ch->ch_bd->bd_ops->assert_modem_signals(ch);
+				}
+
+				/*
+				 * If DTR Toggle mode is on, whenever
+				 * the queue and UART is empty, keep DTR low.
+				 */
+				if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
+					ch->ch_mostat &= ~(UART_MCR_DTR);
+					ch->ch_bd->bd_ops->assert_modem_signals(ch);
+				}
+			}
+		}
+
+		wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+	}
+
+	if (ch->ch_pun.un_flags & UN_ISOPEN) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+                if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+                        ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
+                {
+                        DGNC_UNLOCK(ch->ch_lock, lock_flags);
+                        (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+                        DGNC_LOCK(ch->ch_lock, lock_flags);
+                }
+#else
+		if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+			ch->ch_pun.un_tty->ldisc.ops->write_wakeup)
+		{
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			(ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty);
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+		}
+#endif
+
+		wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+
+		/*
+		 * If unit is set to wait until empty, check to make sure
+		 * the queue AND FIFO are both empty.
+		 */
+		if (ch->ch_pun.un_flags & UN_EMPTY) {
+			if ((qlen == 0) && (ch->ch_bd->bd_ops->get_uart_bytes_left(ch) == 0)) {
+				ch->ch_pun.un_flags &= ~(UN_EMPTY);
+			}
+		}
+
+		wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+	}
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+
+/************************************************************************
+ *      
+ * TTY Entry points and helper functions
+ *              
+ ************************************************************************/
+
+/*
+ * dgnc_tty_open()
+ *
+ */
+static int dgnc_tty_open(struct tty_struct *tty, struct file *file)
+{
+	struct board_t	*brd;
+	struct channel_t *ch;
+	struct un_t	*un;
+	uint		major = 0;
+	uint		minor = 0;
+	int		rc = 0;
+	ulong		lock_flags;
+
+	rc = 0;
+
+	major = MAJOR(tty_devnum(tty));
+	minor = MINOR(tty_devnum(tty));
+
+	if (major > 255) {
+		return -ENXIO;
+	}
+
+	/* Get board pointer from our array of majors we have allocated */
+	brd = dgnc_BoardsByMajor[major];
+	if (!brd) {
+		return -ENXIO;
+	}
+
+	/*
+	 * If board is not yet up to a state of READY, go to
+	 * sleep waiting for it to happen or they cancel the open.
+	 */
+	rc = wait_event_interruptible(brd->state_wait,
+		(brd->state & BOARD_READY));
+
+	if (rc) {
+		return rc;
+	}
+
+	DGNC_LOCK(brd->bd_lock, lock_flags);
+
+	/* If opened device is greater than our number of ports, bail. */
+	if (PORT_NUM(minor) > brd->nasync) {
+		DGNC_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	ch = brd->channels[PORT_NUM(minor)];
+	if (!ch) {
+		DGNC_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* Drop board lock */
+	DGNC_UNLOCK(brd->bd_lock, lock_flags);
+
+	/* Grab channel lock */
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* Figure out our type */
+	if (!IS_PRINT(minor)) {
+		un = &brd->channels[PORT_NUM(minor)]->ch_tun;
+		un->un_type = DGNC_SERIAL;
+	}
+	else if (IS_PRINT(minor)) {
+		un = &brd->channels[PORT_NUM(minor)]->ch_pun;
+		un->un_type = DGNC_PRINT;
+	}
+	else {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		DPR_OPEN(("%d Unknown TYPE!\n", __LINE__));
+		return -ENXIO;
+	}
+
+	/*
+	 * If the port is still in a previous open, and in a state
+	 * where we simply cannot safely keep going, wait until the
+	 * state clears.
+	 */
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	rc = wait_event_interruptible(ch->ch_flags_wait, ((ch->ch_flags & CH_OPENING) == 0));
+
+	/* If ret is non-zero, user ctrl-c'ed us */
+	if (rc) {
+		DPR_OPEN(("%d User ctrl c'ed\n", __LINE__));
+		return -EINTR;
+	}
+
+	/*
+	 * If either unit is in the middle of the fragile part of close,
+	 * we just cannot touch the channel safely.
+	 * Go to sleep, knowing that when the channel can be
+	 * touched safely, the close routine will signal the
+	 * ch_flags_wait to wake us back up.
+	 */
+	rc = wait_event_interruptible(ch->ch_flags_wait,
+		(((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING) == 0));
+
+	/* If ret is non-zero, user ctrl-c'ed us */
+	if (rc) {
+		DPR_OPEN(("%d User ctrl c'ed\n", __LINE__));
+		return -EINTR;
+	}
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+
+	/* Store our unit into driver_data, so we always have it available. */
+	tty->driver_data = un;
+
+	DPR_OPEN(("Open called. MAJOR: %d MINOR:%d PORT_NUM: %x unit: %p NAME: %s\n",
+		MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), PORT_NUM(minor), un, brd->name));
+
+	DPR_OPEN(("%d: tflag=%x  pflag=%x\n", __LINE__, ch->ch_tun.un_flags, ch->ch_pun.un_flags));
+
+	/*
+	 * Initialize tty's
+	 */
+	if (!(un->un_flags & UN_ISOPEN)) {
+		/* Store important variables. */
+		un->un_tty     = tty;
+
+		/* Maybe do something here to the TTY struct as well? */
+	}
+
+
+	/*
+	 * Allocate channel buffers for read/write/error.
+	 * Set flag, so we don't get trounced on.
+	 */
+	ch->ch_flags |= (CH_OPENING);
+
+	/* Drop locks, as malloc with GFP_KERNEL can sleep */
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (!ch->ch_rqueue)
+		ch->ch_rqueue = dgnc_driver_kzmalloc(RQUEUESIZE, GFP_KERNEL);
+	if (!ch->ch_equeue)
+		ch->ch_equeue = dgnc_driver_kzmalloc(EQUEUESIZE, GFP_KERNEL);
+	if (!ch->ch_wqueue)
+		ch->ch_wqueue = dgnc_driver_kzmalloc(WQUEUESIZE, GFP_KERNEL);
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_flags &= ~(CH_OPENING);
+	wake_up_interruptible(&ch->ch_flags_wait);
+
+	/*
+	 * Initialize if neither terminal or printer is open.
+	 */
+	if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
+
+		DPR_OPEN(("dgnc_open: initializing channel in open...\n"));
+
+		/*
+		 * Flush input queues.
+		 */
+		ch->ch_r_head = ch->ch_r_tail = 0;
+		ch->ch_e_head = ch->ch_e_tail = 0;
+		ch->ch_w_head = ch->ch_w_tail = 0;
+
+		brd->bd_ops->flush_uart_write(ch);
+		brd->bd_ops->flush_uart_read(ch);
+
+		ch->ch_flags = 0;
+		ch->ch_cached_lsr = 0;
+		ch->ch_stop_sending_break = 0;
+		ch->ch_stops_sent = 0;
+
+		ch->ch_c_cflag   = tty->termios->c_cflag;
+		ch->ch_c_iflag   = tty->termios->c_iflag;
+		ch->ch_c_oflag   = tty->termios->c_oflag;
+		ch->ch_c_lflag   = tty->termios->c_lflag;
+		ch->ch_startc = tty->termios->c_cc[VSTART];
+		ch->ch_stopc  = tty->termios->c_cc[VSTOP];
+
+		/*
+		 * Bring up RTS and DTR...
+		 * Also handle RTS or DTR toggle if set.
+		 */
+		if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
+			ch->ch_mostat |= (UART_MCR_RTS);
+		if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
+			ch->ch_mostat |= (UART_MCR_DTR);
+
+		/* Tell UART to init itself */
+		brd->bd_ops->uart_init(ch);
+	}
+
+	/*
+	 * Run param in case we changed anything
+	 */
+	brd->bd_ops->param(tty);
+
+	dgnc_carrier(ch);
+
+	/*                              
+	 * follow protocol for opening port
+	 */
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	rc = dgnc_block_til_ready(tty, file, ch);
+
+	if (rc) {
+		DPR_OPEN(("dgnc_tty_open returning after dgnc_block_til_ready "
+			"with %d\n", rc));
+	}
+
+	/* No going back now, increment our unit and channel counters */
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	ch->ch_open_count++;
+	un->un_open_count++;
+	un->un_flags |= (UN_ISOPEN);
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_OPEN(("dgnc_tty_open finished\n"));
+	return (rc);
+}
+
+
+/*   
+ * dgnc_block_til_ready()
+ *
+ * Wait for DCD, if needed.
+ */
+static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
+{ 
+	int retval = 0;
+	struct un_t *un = NULL;
+	ulong   lock_flags;
+	uint	old_flags = 0;
+	int	sleep_on_un_flags = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+		return (-ENXIO);
+	}
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC) {
+		return (-ENXIO);
+	}
+
+	DPR_OPEN(("dgnc_block_til_ready - before block.\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_wopen++;
+
+	/* Loop forever */
+	while (1) {
+
+		sleep_on_un_flags = 0;
+
+		/*
+		 * If board has failed somehow during our sleep, bail with error.
+		 */
+		if (ch->ch_bd->state == BOARD_FAILED) {
+			retval = -ENXIO;
+			break;
+		}
+
+		/* If tty was hung up, break out of loop and set error. */
+		if (tty_hung_up_p(file)) {
+			retval = -EAGAIN;
+			break;
+		}
+
+		/*
+		 * If either unit is in the middle of the fragile part of close,
+		 * we just cannot touch the channel safely.
+		 * Go back to sleep, knowing that when the channel can be
+		 * touched safely, the close routine will signal the 
+		 * ch_wait_flags to wake us back up.
+		 */
+		if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
+
+			/*
+			 * Our conditions to leave cleanly and happily:
+			 * 1) NONBLOCKING on the tty is set.
+			 * 2) CLOCAL is set.
+			 * 3) DCD (fake or real) is active.
+			 */
+
+			if (file->f_flags & O_NONBLOCK) {
+				break;
+			}
+
+			if (tty->flags & (1 << TTY_IO_ERROR)) {
+				retval = -EIO;
+				break;
+			}
+
+			if (ch->ch_flags & CH_CD) {
+				DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
+				break;
+			}
+
+			if (ch->ch_flags & CH_FCAR) {
+				DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
+				break;
+			}
+		}
+		else {
+			sleep_on_un_flags = 1;
+		}
+
+		/*
+		 * If there is a signal pending, the user probably
+		 * interrupted (ctrl-c) us.
+		 * Leave loop with error set.
+		 */
+		if (signal_pending(current)) {
+			DPR_OPEN(("%d: signal pending...\n", __LINE__));
+			retval = -ERESTARTSYS;
+			break;
+		}
+
+		DPR_OPEN(("dgnc_block_til_ready - blocking.\n"));
+
+		/*
+		 * Store the flags before we let go of channel lock
+		 */
+		if (sleep_on_un_flags)
+			old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
+		else
+			old_flags = ch->ch_flags;
+
+		/*
+		 * Let go of channel lock before calling schedule.
+		 * Our poller will get any FEP events and wake us up when DCD
+		 * eventually goes active.
+		 */
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		DPR_OPEN(("Going to sleep on %s flags...\n",
+			(sleep_on_un_flags ? "un" : "ch")));
+
+		/*
+		 * Wait for something in the flags to change from the current value.
+		 */
+		if (sleep_on_un_flags) {
+			retval = wait_event_interruptible(un->un_flags_wait,
+				(old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
+		}
+		else {
+			retval = wait_event_interruptible(ch->ch_flags_wait,
+				(old_flags != ch->ch_flags));
+		}
+
+		DPR_OPEN(("After sleep... retval: %x\n", retval));
+
+		/*
+		 * We got woken up for some reason.
+		 * Before looping around, grab our channel lock.
+		 */
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+	}
+
+	ch->ch_wopen--;
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_OPEN(("dgnc_block_til_ready - after blocking.\n"));
+
+	if (retval) {
+		DPR_OPEN(("dgnc_block_til_ready - done. error. retval: %x\n", retval));
+		return(retval);
+	}
+
+	DPR_OPEN(("dgnc_block_til_ready - done no error. jiffies: %lu\n", jiffies));
+
+	return(0);
+}
+
+
+/*
+ * dgnc_tty_hangup()
+ *
+ * Hangup the port.  Like a close, but don't wait for output to drain.
+ */     
+static void dgnc_tty_hangup(struct tty_struct *tty)
+{
+	struct un_t	*un;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+
+	DPR_CLOSE(("dgnc_hangup called. ch->ch_open_count: %d un->un_open_count: %d\n",
+		un->un_ch->ch_open_count, un->un_open_count));
+
+	/* flush the transmit queues */
+	dgnc_tty_flush_buffer(tty);
+
+	DPR_CLOSE(("dgnc_hangup finished. ch->ch_open_count: %d un->un_open_count: %d\n",
+		un->un_ch->ch_open_count, un->un_open_count));
+}
+
+
+/*
+ * dgnc_tty_close()
+ *
+ */
+static void dgnc_tty_close(struct tty_struct *tty, struct file *file)
+{
+	struct ktermios *ts;
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+	int rc = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	ts = tty->termios;
+
+	DPR_CLOSE(("Close called\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * Determine if this is the last close or not - and if we agree about
+	 * which type of close it is with the Line Discipline
+	 */
+	if ((tty->count == 1) && (un->un_open_count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  un_open_count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		APR(("tty->count is 1, un open count is %d\n", un->un_open_count));
+		un->un_open_count = 1;
+	}  
+
+	if (--un->un_open_count < 0) {
+		APR(("bad serial port open count of %d\n", un->un_open_count));
+		un->un_open_count = 0;
+	}
+
+	ch->ch_open_count--;
+
+	if (ch->ch_open_count && un->un_open_count) {
+		DPR_CLOSE(("dgnc_tty_close: not last close ch: %d un:%d\n",
+			ch->ch_open_count, un->un_open_count));
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+                return;
+        }
+
+	/* OK, its the last close on the unit */
+	DPR_CLOSE(("dgnc_tty_close - last close on unit procedures\n"));
+
+	un->un_flags |= UN_CLOSING;
+
+	tty->closing = 1;
+
+
+	/*
+	 * Only officially close channel if count is 0 and
+         * DIGI_PRINTER bit is not set.
+	 */
+	if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
+
+		ch->ch_flags &= ~(CH_STOPI | CH_FORCED_STOPI);
+
+		/*
+		 * turn off print device when closing print device.
+		 */
+		if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON) ) {
+			dgnc_wmove(ch, ch->ch_digi.digi_offstr,
+				(int) ch->ch_digi.digi_offlen);
+			ch->ch_flags &= ~CH_PRON;
+		}
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		/* wait for output to drain */
+		/* This will also return if we take an interrupt */
+
+		DPR_CLOSE(("Calling wait_for_drain\n"));
+		rc = bd->bd_ops->drain(tty, 0);
+
+		DPR_CLOSE(("After calling wait_for_drain\n"));
+
+		if (rc) {
+			DPR_BASIC(("dgnc_tty_close - bad return: %d ", rc));
+		}
+
+		dgnc_tty_flush_buffer(tty);
+		tty_ldisc_flush(tty);
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		tty->closing = 0;
+
+		/*
+		 * If we have HUPCL set, lower DTR and RTS
+		 */
+		if (ch->ch_c_cflag & HUPCL) {
+			DPR_CLOSE(("Close. HUPCL set, dropping DTR/RTS\n"));
+
+			/* Drop RTS/DTR */
+			ch->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS);
+			bd->bd_ops->assert_modem_signals(ch);
+
+			/*
+			 * Go to sleep to ensure RTS/DTR 
+			 * have been dropped for modems to see it.
+			 */
+			if (ch->ch_close_delay) {
+				DPR_CLOSE(("Close. Sleeping for RTS/DTR drop\n"));
+
+				DGNC_UNLOCK(ch->ch_lock, lock_flags);
+				dgnc_ms_sleep(ch->ch_close_delay);
+				DGNC_LOCK(ch->ch_lock, lock_flags);
+
+				DPR_CLOSE(("Close. After sleeping for RTS/DTR drop\n"));
+			}
+		}
+
+		ch->ch_old_baud = 0;
+
+		/* Turn off UART interrupts for this port */
+		ch->ch_bd->bd_ops->uart_off(ch);
+	}
+	else {
+		/*
+		 * turn off print device when closing print device.
+		 */
+		if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON) ) {
+			dgnc_wmove(ch, ch->ch_digi.digi_offstr,
+				(int) ch->ch_digi.digi_offlen);
+			ch->ch_flags &= ~CH_PRON;
+		}
+	}
+
+	un->un_tty = NULL;
+	un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
+
+	DPR_CLOSE(("Close. Doing wakeups\n"));
+	wake_up_interruptible(&ch->ch_flags_wait);
+	wake_up_interruptible(&un->un_flags_wait);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+        DPR_BASIC(("dgnc_tty_close - complete\n"));
+}
+
+
+/*
+ * dgnc_tty_chars_in_buffer()
+ *
+ * Return number of characters that have not been transmitted yet.
+ *
+ * This routine is used by the line discipline to determine if there
+ * is data waiting to be transmitted/drained/flushed or not.
+ */
+static int dgnc_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	ushort thead;
+	ushort ttail;
+	uint tmask;
+	uint chars = 0;
+	ulong   lock_flags = 0;
+
+	if (tty == NULL)
+		return(0);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	tmask = WQUEUEMASK;
+	thead = ch->ch_w_head & tmask;
+	ttail = ch->ch_w_tail & tmask;
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (ttail == thead) {
+		chars = 0;
+	} else {
+		if (thead >= ttail)
+			chars = thead - ttail;
+		else
+			chars = thead - ttail + WQUEUESIZE;
+	}
+
+ 	DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n", 
+		ch->ch_portnum, chars, thead, ttail));
+
+        return(chars);
+}
+
+
+/*       
+ * dgnc_maxcps_room
+ *
+ * Reduces bytes_available to the max number of characters
+ * that can be sent currently given the maxcps value, and
+ * returns the new bytes_available.  This only affects printer
+ * output.
+ */                     
+static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+
+	if (!tty)
+		return (bytes_available);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (bytes_available);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (bytes_available);
+
+	/*
+	 * If its not the Transparent print device, return
+	 * the full data amount.
+	 */
+	if (un->un_type != DGNC_PRINT)
+		return (bytes_available);
+
+	if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
+		int cps_limit = 0;
+		unsigned long current_time = jiffies;
+		unsigned long buffer_time = current_time +
+			(HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
+
+		if (ch->ch_cpstime < current_time) {
+			/* buffer is empty */
+			ch->ch_cpstime = current_time;            /* reset ch_cpstime */
+			cps_limit = ch->ch_digi.digi_bufsize;
+		}
+		else if (ch->ch_cpstime < buffer_time) {
+			/* still room in the buffer */
+			cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
+		}
+		else {
+			/* no room in the buffer */
+			cps_limit = 0; 
+		}
+
+		bytes_available = min(cps_limit, bytes_available);
+	}
+
+	return (bytes_available);
+}
+
+
+/*
+ * dgnc_tty_write_room()
+ *
+ * Return space available in Tx buffer
+ */        
+static int dgnc_tty_write_room(struct tty_struct *tty)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	ushort head;
+	ushort tail;
+	ushort tmask;
+	int ret = 0;
+	ulong   lock_flags = 0;
+
+	if (tty == NULL || dgnc_TmpWriteBuf == NULL)
+		return(0);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (0);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (0);
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	tmask = WQUEUEMASK;
+	head = (ch->ch_w_head) & tmask;
+	tail = (ch->ch_w_tail) & tmask;
+
+	if ((ret = tail - head - 1) < 0)
+		ret += WQUEUESIZE;
+
+	/* Limit printer to maxcps */
+	ret = dgnc_maxcps_room(tty, ret);
+
+	/*
+	 * If we are printer device, leave space for 
+	 * possibly both the on and off strings.
+	 */
+	if (un->un_type == DGNC_PRINT) {
+		if (!(ch->ch_flags & CH_PRON))
+			ret -= ch->ch_digi.digi_onlen;
+		ret -= ch->ch_digi.digi_offlen;
+	}
+	else {
+		if (ch->ch_flags & CH_PRON)
+			ret -= ch->ch_digi.digi_offlen;
+	}
+
+	if (ret < 0)
+		ret = 0;
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+ 
+	DPR_WRITE(("dgnc_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
+
+        return(ret);
+}
+
+
+/*
+ * dgnc_tty_put_char()
+ *
+ * Put a character into ch->ch_buf
+ *                              
+ *      - used by the line discipline for OPOST processing
+ */
+static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c)
+{
+	/*
+	 * Simply call tty_write.
+	 */
+	DPR_WRITE(("dgnc_tty_put_char called\n"));
+	dgnc_tty_write(tty, &c, 1);
+	return 1;
+}
+
+
+/*
+ * dgnc_tty_write()
+ *
+ * Take data from the user or kernel and send it out to the FEP.
+ * In here exists all the Transparent Print magic as well.
+ */
+static int dgnc_tty_write(struct tty_struct *tty,
+		const unsigned char *buf, int count)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	int bufcount = 0, n = 0;
+	int orig_count = 0;
+	ulong lock_flags;
+	ushort head;
+	ushort tail;
+	ushort tmask;
+	uint remain;
+	int from_user = 0;
+
+	if (tty == NULL || dgnc_TmpWriteBuf == NULL)
+		return(0);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return(0);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return(0);
+
+	if (!count)
+		return(0);
+
+	DPR_WRITE(("dgnc_tty_write: Port: %x tty=%p user=%d len=%d\n",
+		ch->ch_portnum, tty, from_user, count));
+
+	/*
+	 * Store original amount of characters passed in.
+	 * This helps to figure out if we should ask the FEP
+	 * to send us an event when it has more space available.
+	 */
+	orig_count = count;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* Get our space available for the channel from the board */
+	tmask = WQUEUEMASK;
+	head = (ch->ch_w_head) & tmask;
+	tail = (ch->ch_w_tail) & tmask;
+
+	if ((bufcount = tail - head - 1) < 0)
+		bufcount += WQUEUESIZE;
+
+	DPR_WRITE(("%d: bufcount: %x count: %x tail: %x head: %x tmask: %x\n",
+		__LINE__, bufcount, count, tail, head, tmask));
+
+	/*
+	 * Limit printer output to maxcps overall, with bursts allowed
+	 * up to bufsize characters.
+	 */
+	bufcount = dgnc_maxcps_room(tty, bufcount);
+
+	/*
+	 * Take minimum of what the user wants to send, and the
+	 * space available in the FEP buffer.
+	 */
+	count = min(count, bufcount);
+
+	/*
+	 * Bail if no space left.
+	 */
+	if (count <= 0) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(0);
+	}
+
+	/*
+	 * Output the printer ON string, if we are in terminal mode, but
+	 * need to be in printer mode.
+	 */
+	if ((un->un_type == DGNC_PRINT) && !(ch->ch_flags & CH_PRON)) {
+		dgnc_wmove(ch, ch->ch_digi.digi_onstr,
+		    (int) ch->ch_digi.digi_onlen);
+		head = (ch->ch_w_head) & tmask;
+		ch->ch_flags |= CH_PRON;
+	}
+
+	/*
+	 * On the other hand, output the printer OFF string, if we are
+	 * currently in printer mode, but need to output to the terminal.
+	 */
+	if ((un->un_type != DGNC_PRINT) && (ch->ch_flags & CH_PRON)) {
+		dgnc_wmove(ch, ch->ch_digi.digi_offstr,
+			(int) ch->ch_digi.digi_offlen);
+		head = (ch->ch_w_head) & tmask;
+		ch->ch_flags &= ~CH_PRON;
+	}
+
+	/*
+	 * If there is nothing left to copy, or I can't handle any more data, leave.
+	 */     
+	if (count <= 0) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(0);
+	}
+
+	if (from_user) {
+
+		count = min(count, WRITEBUFLEN);
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * If data is coming from user space, copy it into a temporary
+		 * buffer so we don't get swapped out while doing the copy to
+		 * the board.
+		 */
+		/* we're allowed to block if it's from_user */
+		if (down_interruptible(&dgnc_TmpWriteSem)) {
+			return (-EINTR);
+		}
+
+		/*
+		 * copy_from_user() returns the number
+		 * of bytes that could *NOT* be copied.
+		 */
+		count -= copy_from_user(dgnc_TmpWriteBuf, (const uchar __user *) buf, count);
+
+		if (!count) {
+			up(&dgnc_TmpWriteSem);
+			return(-EFAULT);
+		}
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		buf = dgnc_TmpWriteBuf;
+
+	}
+
+	n = count;
+
+	/*
+	 * If the write wraps over the top of the circular buffer,
+	 * move the portion up to the wrap point, and reset the
+	 * pointers to the bottom.
+	 */
+	remain = WQUEUESIZE - head;
+
+	if (n >= remain) {
+		n -= remain;
+		memcpy(ch->ch_wqueue + head, buf, remain);
+		dgnc_sniff_nowait_nolock(ch, "USER WRITE", ch->ch_wqueue + head, remain);
+		head = 0;
+		buf += remain;
+	}
+
+	if (n > 0) {
+		/*
+		 * Move rest of data.
+		 */
+		remain = n;
+		memcpy(ch->ch_wqueue + head, buf, remain);
+		dgnc_sniff_nowait_nolock(ch, "USER WRITE", ch->ch_wqueue + head, remain);
+		head += remain;
+	}
+
+	if (count) {
+		head &= tmask;
+		ch->ch_w_head = head;
+	}
+
+#if 0
+	/*
+	 * If this is the print device, and the
+	 * printer is still on, we need to turn it
+	 * off before going idle.
+	 */
+	if (count == orig_count) {
+		if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON)) {
+			head &= tmask;
+			ch->ch_w_head = head;
+			dgnc_wmove(ch, ch->ch_digi.digi_offstr,
+				(int) ch->ch_digi.digi_offlen);
+			head = (ch->ch_w_head) & tmask;
+			ch->ch_flags &= ~CH_PRON;
+		}
+	}
+#endif
+
+	/* Update printer buffer empty time. */
+	if ((un->un_type == DGNC_PRINT) && (ch->ch_digi.digi_maxcps > 0)
+	    && (ch->ch_digi.digi_bufsize > 0)) {
+                ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
+	}
+
+	if (from_user) {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		up(&dgnc_TmpWriteSem);
+	} else {
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+	}
+
+	DPR_WRITE(("Write finished - Write %d bytes of %d.\n", count, orig_count));
+
+	if (count) {
+		/*
+		 * Channel lock is grabbed and then released
+		 * inside this routine.
+		 */
+		ch->ch_bd->bd_ops->copy_data_from_queue_to_uart(ch);
+	}
+
+	return (count);
+}
+
+
+/*
+ * Return modem signals to ld.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+static int dgnc_tty_tiocmget(struct tty_struct *tty)
+#else
+static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file)
+#endif
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int result = -EIO;
+	uchar mstat = 0;
+	ulong   lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return result;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return result;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return result;
+
+	DPR_IOCTL(("dgnc_tty_tiocmget start\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	mstat = (ch->ch_mostat | ch->ch_mistat);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	result = 0;
+
+	if (mstat & UART_MCR_DTR)
+		result |= TIOCM_DTR;
+	if (mstat & UART_MCR_RTS)
+		result |= TIOCM_RTS;
+	if (mstat & UART_MSR_CTS)
+		result |= TIOCM_CTS;
+	if (mstat & UART_MSR_DSR)
+		result |= TIOCM_DSR;
+	if (mstat & UART_MSR_RI)
+		result |= TIOCM_RI;
+	if (mstat & UART_MSR_DCD)
+		result |= TIOCM_CD;
+
+	DPR_IOCTL(("dgnc_tty_tiocmget finish\n"));
+
+	return result;
+}
+
+
+/*
+ * dgnc_tty_tiocmset()
+ *
+ * Set modem signals, called by ld.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+static int dgnc_tty_tiocmset(struct tty_struct *tty,
+                unsigned int set, unsigned int clear)
+#else
+static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file,
+		unsigned int set, unsigned int clear)
+#endif
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -EIO;
+	ulong   lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return ret;
+
+	DPR_IOCTL(("dgnc_tty_tiocmset start\n"));
+
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	if (set & TIOCM_RTS) {
+		ch->ch_mostat |= UART_MCR_RTS;
+        }         
+
+	if (set & TIOCM_DTR) {
+		ch->ch_mostat |= UART_MCR_DTR;
+        }         
+
+	if (clear & TIOCM_RTS) {
+		ch->ch_mostat &= ~(UART_MCR_RTS);
+        }
+
+	if (clear & TIOCM_DTR) {
+		ch->ch_mostat &= ~(UART_MCR_DTR);
+        }
+
+	ch->ch_bd->bd_ops->assert_modem_signals(ch);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_tiocmset finish\n"));
+
+	return (0);
+}
+
+
+/*
+ * dgnc_tty_send_break()
+ *
+ * Send a Break, called by ld.
+ */
+static int dgnc_tty_send_break(struct tty_struct *tty, int msec)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -EIO;
+	ulong   lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return ret;
+
+	switch (msec) {
+	case -1:
+		msec = 0xFFFF;
+		break;
+	case 0:
+		msec = 0;
+		break;
+	default:
+		break;
+	}
+
+	DPR_IOCTL(("dgnc_tty_send_break start 1.  %lx\n", jiffies));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_bd->bd_ops->send_break(ch, msec);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_send_break finish\n"));
+
+	return (0);
+
+}
+
+
+/*
+ * dgnc_tty_wait_until_sent()
+ *
+ * wait until data has been transmitted, called by ld.
+ */
+static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int rc;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	rc = bd->bd_ops->drain(tty, 0);
+	if (rc) {
+		DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
+		return;
+	}
+	return;
+}       
+
+
+/*
+ * dgnc_send_xchar()
+ *
+ * send a high priority character, called by ld.
+ */
+static void dgnc_tty_send_xchar(struct tty_struct *tty, char c)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	DPR_IOCTL(("dgnc_tty_send_xchar start\n"));
+	printk("dgnc_tty_send_xchar start\n");
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	bd->bd_ops->send_immediate_char(ch, c);
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_send_xchar finish\n"));
+	printk("dgnc_tty_send_xchar finish\n");
+	return;
+}       
+
+
+
+
+/*
+ * Return modem signals to ld.
+ */
+static inline int dgnc_get_mstat(struct channel_t *ch)
+{
+	unsigned char mstat;
+	int result = -EIO;
+	ulong   lock_flags;
+
+	DPR_IOCTL(("dgnc_getmstat start\n"));
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return(-ENXIO);
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	mstat = (ch->ch_mostat | ch->ch_mistat);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	result = 0;
+
+	if (mstat & UART_MCR_DTR)
+		result |= TIOCM_DTR;
+	if (mstat & UART_MCR_RTS)
+		result |= TIOCM_RTS;
+	if (mstat & UART_MSR_CTS)
+		result |= TIOCM_CTS;
+	if (mstat & UART_MSR_DSR)
+		result |= TIOCM_DSR;
+	if (mstat & UART_MSR_RI)
+		result |= TIOCM_RI;
+	if (mstat & UART_MSR_DCD)
+		result |= TIOCM_CD;
+
+	DPR_IOCTL(("dgnc_getmstat finish\n"));
+
+	return(result);
+}
+
+
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgnc_get_modem_info(struct channel_t *ch, unsigned int  __user *value)
+{
+	int result;
+	int rc;
+
+	DPR_IOCTL(("dgnc_get_modem_info start\n"));
+
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return(-ENXIO);
+
+	result = dgnc_get_mstat(ch);
+
+	if (result < 0)
+		return (-ENXIO);
+
+	rc = put_user(result, value);
+
+	DPR_IOCTL(("dgnc_get_modem_info finish\n"));
+	return(rc);
+}
+
+
+/*
+ * dgnc_set_modem_info()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -ENXIO;
+	unsigned int arg = 0;
+	ulong   lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return ret;
+
+	ret = 0;
+
+	DPR_IOCTL(("dgnc_set_modem_info() start\n"));
+
+	ret = get_user(arg, value);
+	if (ret)
+		return(ret);
+
+	switch (command) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS) {
+			ch->ch_mostat |= UART_MCR_RTS;
+        	}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mostat |= UART_MCR_DTR;
+        	}
+
+		break;
+
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS) {
+			ch->ch_mostat &= ~(UART_MCR_RTS);
+        	}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mostat &= ~(UART_MCR_DTR);
+        	}
+
+		break;
+
+        case TIOCMSET:
+
+		if (arg & TIOCM_RTS) {
+			ch->ch_mostat |= UART_MCR_RTS;
+        	}
+		else {
+			ch->ch_mostat &= ~(UART_MCR_RTS);
+		}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mostat |= UART_MCR_DTR;
+        	}
+		else {
+			ch->ch_mostat &= ~(UART_MCR_DTR);
+		}
+
+		break;
+
+	default:
+		return(-EINVAL);
+	}
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_bd->bd_ops->assert_modem_signals(ch);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_set_modem_info finish\n"));
+
+	return (0);
+}
+
+
+/*
+ * dgnc_tty_digigeta() 
+ *
+ * Ioctl to get the information for ditty.
+ *
+ *
+ *
+ */
+static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	struct digi_t tmp;
+	ulong   lock_flags;
+
+	if (!retinfo)
+		return (-EFAULT);
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return (-EFAULT);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (-EFAULT);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (-EFAULT);
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+	memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return (-EFAULT);
+
+	return (0);
+}
+
+
+/*
+ * dgnc_tty_digiseta() 
+ *
+ * Ioctl to set the information for ditty.
+ *
+ *
+ *
+ */
+static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	struct digi_t new_digi;
+	ulong lock_flags;
+
+	DPR_IOCTL(("DIGI_SETA start\n"));
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return (-EFAULT);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (-EFAULT);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (-EFAULT);
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (-EFAULT);
+
+        if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
+		DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
+                return(-EFAULT);
+	}
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * Handle transistions to and from RTS Toggle.
+	 */
+	if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) && (new_digi.digi_flags & DIGI_RTS_TOGGLE))
+		ch->ch_mostat &= ~(UART_MCR_RTS);
+	if ((ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) && !(new_digi.digi_flags & DIGI_RTS_TOGGLE))
+		ch->ch_mostat |= (UART_MCR_RTS);
+
+	/*
+	 * Handle transistions to and from DTR Toggle.
+	 */
+	if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && (new_digi.digi_flags & DIGI_DTR_TOGGLE))
+		ch->ch_mostat &= ~(UART_MCR_DTR);
+	if ((ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && !(new_digi.digi_flags & DIGI_DTR_TOGGLE))
+		ch->ch_mostat |= (UART_MCR_DTR);
+
+	memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
+
+	if (ch->ch_digi.digi_maxcps < 1) 
+		ch->ch_digi.digi_maxcps = 1;
+
+	if (ch->ch_digi.digi_maxcps > 10000) 
+		ch->ch_digi.digi_maxcps = 10000;
+
+	if (ch->ch_digi.digi_bufsize < 10)
+		ch->ch_digi.digi_bufsize = 10;
+
+	if (ch->ch_digi.digi_maxchar < 1)
+		ch->ch_digi.digi_maxchar = 1;
+
+	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
+		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
+
+	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
+		ch->ch_digi.digi_onlen = DIGI_PLEN;
+
+	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
+		ch->ch_digi.digi_offlen = DIGI_PLEN;
+
+	ch->ch_bd->bd_ops->param(tty);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("DIGI_SETA finish\n"));
+
+	return(0);
+}
+
+
+/*
+ * dgnc_set_termios()
+ */
+static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	unsigned long lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_c_cflag   = tty->termios->c_cflag;
+	ch->ch_c_iflag   = tty->termios->c_iflag;
+	ch->ch_c_oflag   = tty->termios->c_oflag;
+	ch->ch_c_lflag   = tty->termios->c_lflag;
+	ch->ch_startc = tty->termios->c_cc[VSTART];
+	ch->ch_stopc  = tty->termios->c_cc[VSTOP];
+
+	ch->ch_bd->bd_ops->param(tty);
+	dgnc_carrier(ch);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+
+static void dgnc_tty_throttle(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+        
+        ch = un->un_ch;
+        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+                return;
+
+	DPR_IOCTL(("dgnc_tty_throttle start\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_flags |= (CH_FORCED_STOPI);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_throttle finish\n"));
+}
+
+
+static void dgnc_tty_unthrottle(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+        
+        ch = un->un_ch;
+        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+                return;
+
+	DPR_IOCTL(("dgnc_tty_unthrottle start\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_flags &= ~(CH_FORCED_STOPI);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_unthrottle finish\n"));
+}
+
+
+static void dgnc_tty_start(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+        
+        ch = un->un_ch;
+        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+                return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	DPR_IOCTL(("dgcn_tty_start start\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_flags &= ~(CH_FORCED_STOP);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_start finish\n"));
+}
+
+
+static void dgnc_tty_stop(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+        
+        ch = un->un_ch;
+        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+                return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	DPR_IOCTL(("dgnc_tty_stop start\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_flags |= (CH_FORCED_STOP);
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_stop finish\n"));
+}
+
+
+/* 
+ * dgnc_tty_flush_chars()
+ *
+ * Flush the cook buffer
+ *
+ * Note to self, and any other poor souls who venture here:
+ *
+ * flush in this case DOES NOT mean dispose of the data.
+ * instead, it means "stop buffering and send it if you
+ * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
+ *
+ * It is also always called in interrupt context - JAR 8-Sept-99
+ */
+static void dgnc_tty_flush_chars(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+        
+        ch = un->un_ch;
+        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+                return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return;
+
+	DPR_IOCTL(("dgnc_tty_flush_chars start\n"));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	/* Do something maybe here */
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_flush_chars finish\n"));
+}
+
+
+
+/*
+ * dgnc_tty_flush_buffer()
+ *              
+ * Flush Tx buffer (make in == out)
+ */
+static void dgnc_tty_flush_buffer(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return;
+        
+        ch = un->un_ch;
+        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+                return;
+
+	DPR_IOCTL(("dgnc_tty_flush_buffer on port: %d start\n", ch->ch_portnum));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_flags &= ~CH_STOP;
+
+	/* Flush our write queue */
+	ch->ch_w_head = ch->ch_w_tail;
+
+	/* Flush UARTs transmit FIFO */
+	ch->ch_bd->bd_ops->flush_uart_write(ch);
+
+	if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+		ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+		wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+	}
+	if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+		ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+		wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+	}
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_flush_buffer finish\n"));
+}
+
+
+
+/*****************************************************************************
+ *
+ * The IOCTL function and all of its helpers
+ *
+ *****************************************************************************/
+                        
+/*
+ * dgnc_tty_ioctl()
+ *
+ * The usual assortment of ioctl's
+ */
+static int dgnc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int rc;
+	ulong lock_flags;
+	void __user *uarg = (void __user *) arg;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return (-ENODEV);
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
+		return (-ENODEV);
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
+		return (-ENODEV);
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
+		return (-ENODEV);
+
+	DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n", 
+		ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+
+	DGNC_LOCK(ch->ch_lock, lock_flags);
+
+	if (un->un_open_count <= 0) {
+		DPR_BASIC(("dgnc_tty_ioctl - unit not open.\n"));
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(-EIO);
+	}
+
+	switch (cmd) {
+
+	/* Here are all the standard ioctl's that we MUST implement */
+
+	case TCSBRK:
+		/*
+		 * TCSBRK is SVID version: non-zero arg --> no break  
+		 * this behaviour is exploited by tcdrain().
+		 *
+		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+		 * between 0.25 and 0.5 seconds so we'll ask for something
+		 * in the middle: 0.375 seconds.
+		 */
+		rc = tty_check_change(tty);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		if (rc) {
+			return(rc);
+		}
+
+		rc = ch->ch_bd->bd_ops->drain(tty, 0);
+
+		if (rc) {
+			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
+			return(-EINTR);
+		}
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		if(((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) {
+			ch->ch_bd->bd_ops->send_break(ch, 250);
+		}
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", 
+			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+
+		return(0);
+
+
+	case TCSBRKP:
+ 		/* support for POSIX tcsendbreak()
+		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+		 * between 0.25 and 0.5 seconds so we'll ask for something
+		 * in the middle: 0.375 seconds.
+		 */
+		rc = tty_check_change(tty);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		if (rc) {
+			return(rc);
+		}
+
+		rc = ch->ch_bd->bd_ops->drain(tty, 0);
+		if (rc) {
+			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
+			return(-EINTR);
+		}
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		ch->ch_bd->bd_ops->send_break(ch, 250);
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", 
+			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+
+		return(0);
+
+	case TIOCSBRK:
+		rc = tty_check_change(tty);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		if (rc) {
+			return(rc);
+		}
+
+		rc = ch->ch_bd->bd_ops->drain(tty, 0);
+		if (rc) {
+			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
+			return(-EINTR);
+		}
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		ch->ch_bd->bd_ops->send_break(ch, 250);
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", 
+			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+
+		return(0);
+
+	case TIOCCBRK:
+		/* Do Nothing */
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return 0;
+
+	case TIOCGSOFTCAR:
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
+		return(rc);
+
+	case TIOCSSOFTCAR:
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = get_user(arg, (unsigned long __user *) arg);
+		if (rc)
+			return(rc);
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+		ch->ch_bd->bd_ops->param(tty);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		return(0);
+                        
+	case TIOCMGET:
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+                return(dgnc_get_modem_info(ch, uarg));
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(dgnc_set_modem_info(tty, cmd, uarg));
+
+		/*
+		 * Here are any additional ioctl's that we want to implement
+		 */
+                        
+	case TCFLSH:  
+		/*
+		 * The linux tty driver doesn't have a flush
+		 * input routine for the driver, assuming all backed
+		 * up data is in the line disc. buffers.  However,
+		 * we all know that's not the case.  Here, we
+		 * act on the ioctl, but then lie and say we didn't
+		 * so the line discipline will process the flush
+		 * also.
+		 */   
+		rc = tty_check_change(tty);
+		if (rc) {
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			return(rc);
+		}
+
+		if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
+			ch->ch_r_head = ch->ch_r_tail;
+			ch->ch_bd->bd_ops->flush_uart_read(ch);
+			/* Force queue flow control to be released, if needed */
+			dgnc_check_queue_flow_control(ch);
+		}
+
+		if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
+			if (!(un->un_type == DGNC_PRINT)) {
+				ch->ch_w_head = ch->ch_w_tail;
+				ch->ch_bd->bd_ops->flush_uart_write(ch);
+
+				if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+					ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+				}
+
+				if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+					ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+				}
+
+			}
+		}
+
+		/* pretend we didn't recognize this IOCTL */  
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(-ENOIOCTLCMD);
+
+#ifdef TIOCGETP
+	case TIOCGETP:
+#endif
+	case TCGETS:
+	case TCGETA:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+		if (tty->ldisc->ops->ioctl) {
+#else
+		if (tty->ldisc.ops->ioctl) {
+#endif
+			int retval = (-ENXIO);
+
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+			if (tty->termios) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+				retval = ((tty->ldisc->ops->ioctl) (tty, file, cmd, arg));
+#else
+				retval = ((tty->ldisc.ops->ioctl) (tty, file, cmd, arg));
+#endif
+			}
+
+			DPR_IOCTL(("dgnc_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n", 
+				__LINE__, ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+			return(retval);
+		}
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		DPR_IOCTL(("dgnc_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n", 
+			__LINE__, ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+
+		return(-ENOIOCTLCMD);
+
+	case TCSETSF:
+	case TCSETSW:
+		/*
+		 * The linux tty driver doesn't have a flush
+		 * input routine for the driver, assuming all backed
+		 * up data is in the line disc. buffers.  However,
+		 * we all know that's not the case.  Here, we
+		 * act on the ioctl, but then lie and say we didn't
+		 * so the line discipline will process the flush
+		 * also.
+		 */
+		if (cmd == TCSETSF) {
+			/* flush rx */
+			ch->ch_flags &= ~CH_STOP;
+			ch->ch_r_head = ch->ch_r_tail;
+			ch->ch_bd->bd_ops->flush_uart_read(ch);
+			/* Force queue flow control to be released, if needed */
+			dgnc_check_queue_flow_control(ch);
+		}
+
+		/* now wait for all the output to drain */
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = ch->ch_bd->bd_ops->drain(tty, 0);
+		if (rc) {
+			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d\n", rc));
+			return(-EINTR);
+		}
+
+		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", 
+			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
+
+		/* pretend we didn't recognize this */
+		return(-ENOIOCTLCMD);
+
+	case TCSETAW:
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = ch->ch_bd->bd_ops->drain(tty, 0);
+		if (rc) {
+			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
+			return(-EINTR);
+		}
+
+		/* pretend we didn't recognize this */
+		return(-ENOIOCTLCMD);  
+
+	case TCXONC:
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		/* Make the ld do it */
+		return(-ENOIOCTLCMD);
+
+	case DIGI_GETA:
+		/* get information for ditty */
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(dgnc_tty_digigeta(tty, uarg));
+
+	case DIGI_SETAW:
+	case DIGI_SETAF:
+
+		/* set information for ditty */
+		if (cmd == (DIGI_SETAW)) {
+
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			rc = ch->ch_bd->bd_ops->drain(tty, 0);
+			if (rc) {
+				DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
+				return(-EINTR);
+			}
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+		}
+		else {
+			tty_ldisc_flush(tty);
+		}
+		/* fall thru */
+
+	case DIGI_SETA:
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(dgnc_tty_digiseta(tty, uarg));
+                
+	case DIGI_LOOPBACK:
+		{
+			uint loopback = 0;
+			/* Let go of locks when accessing user space, could sleep */
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			rc = get_user(loopback, (unsigned int __user *) arg);
+			if (rc)
+				return(rc);
+			DGNC_LOCK(ch->ch_lock, lock_flags);
+
+			/* Enable/disable internal loopback for this port */   
+			if (loopback)
+				ch->ch_flags |= CH_LOOPBACK;
+			else
+				ch->ch_flags &= ~(CH_LOOPBACK);
+
+			ch->ch_bd->bd_ops->param(tty);
+			DGNC_UNLOCK(ch->ch_lock, lock_flags);
+			return(0);
+                }
+
+	case DIGI_GETCUSTOMBAUD:
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
+		return(rc);
+
+	case DIGI_SETCUSTOMBAUD:
+	{
+		uint new_rate;
+		/* Let go of locks when accessing user space, could sleep */
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = get_user(new_rate, (unsigned int __user *) arg);
+		if (rc)
+			return(rc);
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		dgnc_set_custom_speed(ch, new_rate);
+		ch->ch_bd->bd_ops->param(tty);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(0);
+        }
+
+	/*
+	 * This ioctl allows insertion of a character into the front
+	 * of any pending data to be transmitted.
+	 *
+	 * This ioctl is to satify the "Send Character Immediate"
+	 * call that the RealPort protocol spec requires.
+	 */
+	case DIGI_REALPORT_SENDIMMEDIATE:
+	{
+		unsigned char c;
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = get_user(c, (unsigned char __user *) arg);
+		if (rc)
+			return(rc);
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+		ch->ch_bd->bd_ops->send_immediate_char(ch, c);
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		return(0);
+	}
+
+	/*
+	 * This ioctl returns all the current counts for the port.
+	 *
+	 * This ioctl is to satify the "Line Error Counters"
+	 * call that the RealPort protocol spec requires.
+	 */
+	case DIGI_REALPORT_GETCOUNTERS:
+	{
+		struct digi_getcounter buf;
+
+		buf.norun = ch->ch_err_overrun;
+		buf.noflow = 0;  	/* The driver doesn't keep this stat */
+		buf.nframe = ch->ch_err_frame;
+		buf.nparity = ch->ch_err_parity;
+		buf.nbreak = ch->ch_err_break;
+		buf.rbytes = ch->ch_rxcount;
+		buf.tbytes = ch->ch_txcount;
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		if (copy_to_user(uarg, &buf, sizeof(struct digi_getcounter))) {
+			return (-EFAULT);
+		}
+		return(0);
+	}
+
+	/*
+	 * This ioctl returns all current events.
+	 *
+	 * This ioctl is to satify the "Event Reporting"
+	 * call that the RealPort protocol spec requires.
+         */
+	case DIGI_REALPORT_GETEVENTS:
+	{
+		unsigned int events = 0;
+
+		/* NOTE: MORE EVENTS NEEDS TO BE ADDED HERE */
+		if (ch->ch_flags & CH_BREAK_SENDING)
+			events |= EV_TXB;
+		if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP)) {
+			events |= (EV_OPU | EV_OPS);
+		}
+		if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI)) {
+			events |= (EV_IPU | EV_IPS);
+		}
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+		rc = put_user(events, (unsigned int __user *) arg);
+		return(rc);
+	}
+
+	/*
+	 * This ioctl returns TOUT and TIN counters based
+	 * upon the values passed in by the RealPort Server.
+	 * It also passes back whether the UART Transmitter is
+	 * empty as well.
+         */
+	case DIGI_REALPORT_GETBUFFERS:
+	{
+		struct digi_getbuffer buf;
+		int tdist;
+		int count;
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * Get data from user first.
+		 */
+		if (copy_from_user(&buf, uarg, sizeof(struct digi_getbuffer))) {
+			return (-EFAULT);
+		}
+
+		DGNC_LOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * Figure out how much data is in our RX and TX queues.
+		 */
+		buf.rxbuf = (ch->ch_r_head - ch->ch_r_tail) & RQUEUEMASK;
+		buf.txbuf = (ch->ch_w_head - ch->ch_w_tail) & WQUEUEMASK;
+
+		/*
+		 * Is the UART empty? Add that value to whats in our TX queue.
+		 */
+		count = buf.txbuf + ch->ch_bd->bd_ops->get_uart_bytes_left(ch);
+
+		/*
+		 * Figure out how much data the RealPort Server believes should
+		 * be in our TX queue.
+		 */
+		tdist = (buf.tIn - buf.tOut) & 0xffff;
+
+		/*
+		 * If we have more data than the RealPort Server believes we
+		 * should have, reduce our count to its amount.
+		 *
+		 * This count difference CAN happen because the Linux LD can
+		 * insert more characters into our queue for OPOST processing
+		 * that the RealPort Server doesn't know about.
+		 */
+		if (buf.txbuf > tdist) {
+			buf.txbuf = tdist;
+		}
+
+		/*
+		 * Report whether our queue and UART TX are completely empty.
+		 */
+		if (count) {
+			buf.txdone = 0;
+		} else {
+			buf.txdone = 1;
+		}
+
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		if (copy_to_user(uarg, &buf, sizeof(struct digi_getbuffer))) {
+			return (-EFAULT);
+		}
+		return(0);
+	}
+	default:
+		DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+		DPR_IOCTL(("dgnc_tty_ioctl - in default\n"));
+		DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n", 
+			dgnc_ioctl_name(cmd), cmd, arg));
+
+		return(-ENOIOCTLCMD);
+	}
+
+	DGNC_UNLOCK(ch->ch_lock, lock_flags);
+
+	DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n", 
+		dgnc_ioctl_name(cmd), cmd, arg));
+                        
+	return(0);
+}
diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h
new file mode 100644
index 0000000..deb388d
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_tty.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+#ifndef __DGNC_TTY_H
+#define __DGNC_TTY_H
+
+#include "dgnc_driver.h"
+
+int	dgnc_tty_register(struct board_t *brd);
+
+int	dgnc_tty_preinit(void);
+int     dgnc_tty_init(struct board_t *);
+
+void	dgnc_tty_post_uninit(void);
+void	dgnc_tty_uninit(struct board_t *);
+
+void	dgnc_input(struct channel_t *ch);
+void	dgnc_carrier(struct channel_t *ch);
+void	dgnc_wakeup_writes(struct channel_t *ch);
+void	dgnc_check_queue_flow_control(struct channel_t *ch);
+
+void	dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int nbuf);
+
+#endif
diff --git a/drivers/staging/dgnc/dgnc_types.h b/drivers/staging/dgnc/dgnc_types.h
new file mode 100644
index 0000000..4fa3585
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_types.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+#ifndef __DGNC_TYPES_H
+#define __DGNC_TYPES_H
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/* Required for our shared headers! */
+typedef unsigned char uchar;
+
+#endif
diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h
new file mode 100644
index 0000000..ab90382
--- /dev/null
+++ b/drivers/staging/dgnc/digi.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * $Id: digi.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+#ifndef __DIGI_H
+#define __DIGI_H
+
+/************************************************************************
+ ***	Definitions for Digi ditty(1) command.
+ ************************************************************************/
+
+
+/*
+ * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
+ */
+
+/************************************************************************
+ * This module provides application access to special Digi
+ * serial line enhancements which are not standard UNIX(tm) features.
+ ************************************************************************/
+
+#if !defined(TIOCMODG)
+
+#define	TIOCMODG	('d'<<8) | 250		/* get modem ctrl state	*/
+#define	TIOCMODS	('d'<<8) | 251		/* set modem ctrl state	*/
+
+#ifndef TIOCM_LE 
+#define		TIOCM_LE	0x01		/* line enable		*/
+#define		TIOCM_DTR	0x02		/* data terminal ready	*/
+#define		TIOCM_RTS	0x04		/* request to send	*/
+#define		TIOCM_ST	0x08		/* secondary transmit	*/
+#define		TIOCM_SR	0x10		/* secondary receive	*/
+#define		TIOCM_CTS	0x20		/* clear to send	*/
+#define		TIOCM_CAR	0x40		/* carrier detect	*/
+#define		TIOCM_RNG	0x80		/* ring	indicator	*/
+#define		TIOCM_DSR	0x100		/* data set ready	*/
+#define		TIOCM_RI	TIOCM_RNG	/* ring (alternate)	*/
+#define		TIOCM_CD	TIOCM_CAR	/* carrier detect (alt)	*/
+#endif
+
+#endif
+
+#if !defined(TIOCMSET)
+#define	TIOCMSET	('d'<<8) | 252		/* set modem ctrl state	*/
+#define	TIOCMGET	('d'<<8) | 253		/* set modem ctrl state	*/
+#endif
+
+#if !defined(TIOCMBIC)
+#define	TIOCMBIC	('d'<<8) | 254		/* set modem ctrl state */
+#define	TIOCMBIS	('d'<<8) | 255		/* set modem ctrl state */
+#endif
+
+
+#if !defined(TIOCSDTR)
+#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
+#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
+
+#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
+#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
+#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
+
+#define DIGI_KME	('e'<<8) | 98		/* Read/Write Host	*/
+						/* Adapter Memory	*/
+
+#define	DIGI_GETFLOW	('e'<<8) | 99		/* Get startc/stopc flow */
+						/* control characters 	 */
+#define	DIGI_SETFLOW	('e'<<8) | 100		/* Set startc/stopc flow */
+						/* control characters	 */
+#define	DIGI_GETAFLOW	('e'<<8) | 101		/* Get Aux. startc/stopc */
+						/* flow control chars 	 */
+#define	DIGI_SETAFLOW	('e'<<8) | 102		/* Set Aux. startc/stopc */
+						/* flow control chars	 */
+
+#define DIGI_GEDELAY	('d'<<8) | 246		/* Get edelay */
+#define DIGI_SEDELAY	('d'<<8) | 247		/* Set edelay */
+
+struct	digiflow_t {
+	unsigned char	startc;				/* flow cntl start char	*/
+	unsigned char	stopc;				/* flow cntl stop char	*/
+};
+
+
+#ifdef	FLOW_2200
+#define	F2200_GETA	('e'<<8) | 104		/* Get 2x36 flow cntl flags */
+#define	F2200_SETAW	('e'<<8) | 105		/* Set 2x36 flow cntl flags */
+#define		F2200_MASK	0x03		/* 2200 flow cntl bit mask  */
+#define		FCNTL_2200	0x01		/* 2x36 terminal flow cntl  */
+#define		PCNTL_2200	0x02		/* 2x36 printer flow cntl   */
+#define	F2200_XON	0xf8
+#define	P2200_XON	0xf9
+#define	F2200_XOFF	0xfa
+#define	P2200_XOFF	0xfb
+
+#define	FXOFF_MASK	0x03			/* 2200 flow status mask    */
+#define	RCVD_FXOFF	0x01			/* 2x36 Terminal XOFF rcvd  */
+#define	RCVD_PXOFF	0x02			/* 2x36 Printer XOFF rcvd   */
+#endif
+
+/************************************************************************
+ * Values for digi_flags 
+ ************************************************************************/
+#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
+#define DIGI_FAST	0x0002		/* Fast baud rates		*/
+#define RTSPACE		0x0004		/* RTS input flow control	*/
+#define CTSPACE		0x0008		/* CTS output flow control	*/
+#define DSRPACE		0x0010		/* DSR output flow control	*/
+#define DCDPACE		0x0020		/* DCD output flow control	*/
+#define DTRPACE		0x0040		/* DTR input flow control	*/
+#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
+#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
+#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
+#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
+#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl*/
+#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input*/
+#define DIGI_DTR_TOGGLE	0x2000		/* Support DTR Toggle           */
+#define DIGI_422	0x4000		/* for 422/232 selectable panel */
+#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		*/
+
+/************************************************************************
+ * These options are not supported on the comxi.
+ ************************************************************************/
+#define	DIGI_COMXI	(DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
+
+#define DIGI_PLEN	28		/* String length		*/
+#define	DIGI_TSIZ	10		/* Terminal string len		*/
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_t {
+	unsigned short	digi_flags;		/* Flags (see above)	*/
+	unsigned short	digi_maxcps;		/* Max printer CPS	*/
+	unsigned short	digi_maxchar;		/* Max chars in print queue */
+	unsigned short	digi_bufsize;		/* Buffer size		*/
+	unsigned char	digi_onlen;		/* Length of ON string	*/
+	unsigned char	digi_offlen;		/* Length of OFF string	*/
+	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
+	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
+	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
+};
+
+/************************************************************************
+ * KME definitions and structures.
+ ************************************************************************/
+#define	RW_IDLE		0	/* Operation complete			*/
+#define	RW_READ		1	/* Read Concentrator Memory		*/
+#define	RW_WRITE	2	/* Write Concentrator Memory		*/
+
+struct rw_t {
+	unsigned char	rw_req;		/* Request type			*/
+	unsigned char	rw_board;	/* Host Adapter board number	*/
+	unsigned char	rw_conc;	/* Concentrator number		*/
+	unsigned char	rw_reserved;	/* Reserved for expansion	*/
+	unsigned int	rw_addr;	/* Address in concentrator	*/
+	unsigned short	rw_size;	/* Read/write request length	*/
+	unsigned char	rw_data[128];	/* Data to read/write		*/
+};
+
+/***********************************************************************
+ * Shrink Buffer and Board Information definitions and structures.
+
+ ************************************************************************/
+			/* Board type return codes */
+#define	PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
+#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
+#define	PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
+#define	MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
+#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
+
+			 /* Non-Zero Result codes. */
+#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */ 
+#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */ 
+#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
+#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
+#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
+
+struct shrink_buf_struct {
+	unsigned int	shrink_buf_vaddr;	/* Virtual address of board */
+	unsigned int	shrink_buf_phys;	/* Physical address of board */
+	unsigned int	shrink_buf_bseg;	/* Amount of board memory */
+	unsigned int	shrink_buf_hseg;	/* '186 Begining of Dual-Port */
+
+	unsigned int	shrink_buf_lseg;	/* '186 Begining of freed memory */ 
+	unsigned int	shrink_buf_mseg;	/* Linear address from start of
+						   dual-port were freed memory
+						   begins, host viewpoint. */
+
+	unsigned int	shrink_buf_bdparam;	/* Parameter for xxmemon and
+						   xxmemoff */
+
+	unsigned int	shrink_buf_reserva;	/* Reserved */
+	unsigned int	shrink_buf_reservb;	/* Reserved */
+	unsigned int	shrink_buf_reservc;	/* Reserved */
+	unsigned int	shrink_buf_reservd;	/* Reserved */
+
+	unsigned char	shrink_buf_result;	/* Reason for call failing
+						   Zero is Good return */
+	unsigned char	shrink_buf_init;	/* Non-Zero if it caused an     
+						   xxinit call. */
+
+	unsigned char	shrink_buf_anports;	/* Number of async ports  */
+	unsigned char	shrink_buf_snports; 	/* Number of sync  ports */
+	unsigned char	shrink_buf_type;	/* Board type 1 = PC/Xi,
+							      2 = PC/Xm,
+							      3 = PC/Xe  
+							      4 = MC/Xi  
+							      5 = COMX/i */
+	unsigned char	shrink_buf_card;	/* Card number */
+	
+};
+
+/************************************************************************
+ * Structure to get driver status information
+ ************************************************************************/
+struct digi_dinfo {
+	unsigned int	dinfo_nboards;		/* # boards configured	*/
+	char		dinfo_reserved[12];	/* for future expansion */
+	char		dinfo_version[16];	/* driver version       */
+};
+
+#define	DIGI_GETDD	('d'<<8) | 248		/* get driver info      */
+ 
+/************************************************************************
+ * Structure used with ioctl commands for per-board information
+ *
+ * physsize and memsize differ when board has "windowed" memory
+ ************************************************************************/
+struct digi_info {
+	unsigned int	info_bdnum;		/* Board number (0 based)  */
+	unsigned int	info_ioport;		/* io port address         */
+	unsigned int	info_physaddr;		/* memory address          */
+	unsigned int	info_physsize;		/* Size of host mem window */
+	unsigned int	info_memsize;		/* Amount of dual-port mem */
+						/* on board                */
+	unsigned short	info_bdtype;		/* Board type              */
+	unsigned short	info_nports;		/* number of ports         */
+	char		info_bdstate;		/* board state             */
+	char		info_reserved[7];	/* for future expansion    */
+};
+
+#define	DIGI_GETBD	('d'<<8) | 249		/* get board info          */
+ 
+struct digi_stat {
+	unsigned int	info_chan;		/* Channel number (0 based)  */
+	unsigned int	info_brd;		/* Board number (0 based)  */
+	unsigned int	info_cflag;		/* cflag for channel       */
+	unsigned int	info_iflag;		/* iflag for channel       */
+	unsigned int	info_oflag;		/* oflag for channel       */
+	unsigned int	info_mstat;		/* mstat for channel       */
+	unsigned int	info_tx_data;		/* tx_data for channel       */
+	unsigned int	info_rx_data;		/* rx_data for channel       */
+	unsigned int	info_hflow;		/* hflow for channel       */
+	unsigned int	info_reserved[8];	/* for future expansion    */
+};
+
+#define	DIGI_GETSTAT	('d'<<8) | 244		/* get board info          */
+/************************************************************************
+ *
+ * Structure used with ioctl commands for per-channel information
+ *
+ ************************************************************************/
+struct digi_ch {
+	unsigned int	info_bdnum;		/* Board number (0 based)  */
+	unsigned int	info_channel;		/* Channel index number    */
+	unsigned int	info_ch_cflag;		/* Channel cflag   	   */
+	unsigned int	info_ch_iflag;		/* Channel iflag   	   */
+	unsigned int	info_ch_oflag;		/* Channel oflag   	   */
+	unsigned int	info_chsize;		/* Channel structure size  */
+	unsigned int	info_sleep_stat;	/* sleep status		   */
+	dev_t		info_dev;		/* device number	   */
+	unsigned char	info_initstate;		/* Channel init state	   */
+	unsigned char	info_running;		/* Channel running state   */
+	int		reserved[8];		/* reserved for future use */
+};
+
+/*
+* This structure is used with the DIGI_FEPCMD ioctl to 
+* tell the driver which port to send the command for.
+*/
+struct digi_cmd {
+	int	cmd;
+	int	word;
+	int	ncmds;
+	int	chan; /* channel index (zero based) */
+	int	bdid; /* board index (zero based) */
+};
+
+
+struct digi_getbuffer /* Struct for holding buffer use counts */
+{
+	unsigned long tIn;
+	unsigned long tOut;
+	unsigned long rxbuf;
+	unsigned long txbuf;
+	unsigned long txdone;
+};
+
+struct digi_getcounter
+{
+	unsigned long norun;		/* number of UART overrun errors */
+	unsigned long noflow;		/* number of buffer overflow errors */
+	unsigned long nframe;		/* number of framing errors */
+	unsigned long nparity;		/* number of parity errors */
+	unsigned long nbreak;		/* number of breaks received */
+	unsigned long rbytes;		/* number of received bytes */
+	unsigned long tbytes;		/* number of bytes transmitted fully */
+};
+
+/*
+*  info_sleep_stat defines
+*/
+#define INFO_RUNWAIT	0x0001
+#define INFO_WOPEN	0x0002
+#define INFO_TTIOW	0x0004
+#define INFO_CH_RWAIT	0x0008
+#define INFO_CH_WEMPTY	0x0010
+#define INFO_CH_WLOW	0x0020
+#define INFO_XXBUF_BUSY 0x0040
+
+#define	DIGI_GETCH	('d'<<8) | 245		/* get board info          */
+
+/* Board type definitions */
+
+#define	SUBTYPE		0007
+#define	T_PCXI		0000
+#define T_PCXM		0001
+#define T_PCXE		0002
+#define T_PCXR		0003
+#define T_SP		0004
+#define T_SP_PLUS	0005
+#	define T_HERC	0000
+#	define T_HOU	0001
+#	define T_LON	0002
+#	define T_CHA	0003
+#define FAMILY		0070
+#define T_COMXI		0000
+#define T_PCXX		0010
+#define T_CX		0020
+#define T_EPC		0030
+#define	T_PCLITE	0040
+#define	T_SPXX		0050
+#define	T_AVXX		0060
+#define T_DXB		0070
+#define T_A2K_4_8	0070
+#define BUSTYPE		0700
+#define T_ISABUS	0000
+#define T_MCBUS		0100
+#define	T_EISABUS	0200
+#define	T_PCIBUS	0400
+
+/* Board State Definitions */
+
+#define	BD_RUNNING	0x0
+#define	BD_REASON	0x7f
+#define	BD_NOTFOUND	0x1
+#define	BD_NOIOPORT	0x2
+#define	BD_NOMEM	0x3
+#define	BD_NOBIOS	0x4
+#define	BD_NOFEP	0x5
+#define	BD_FAILED	0x6
+#define BD_ALLOCATED	0x7
+#define BD_TRIBOOT	0x8
+#define	BD_BADKME	0x80
+
+#define DIGI_SPOLL            ('d'<<8) | 254  /* change poller rate   */
+
+#define DIGI_SETCUSTOMBAUD	_IOW('e', 106, int)	/* Set integer baud rate */
+#define DIGI_GETCUSTOMBAUD	_IOR('e', 107, int)	/* Get integer baud rate */
+
+#define DIGI_REALPORT_GETBUFFERS ('e'<<8 ) | 108
+#define DIGI_REALPORT_SENDIMMEDIATE ('e'<<8 ) | 109
+#define DIGI_REALPORT_GETCOUNTERS ('e'<<8 ) | 110
+#define DIGI_REALPORT_GETEVENTS ('e'<<8 ) | 111
+
+#define EV_OPU		0x0001		//!<Output paused by client
+#define EV_OPS		0x0002		//!<Output paused by reqular sw flowctrl  
+#define EV_OPX		0x0004		//!<Output paused by extra sw flowctrl
+#define EV_OPH		0x0008		//!<Output paused by hw flowctrl
+#define EV_OPT		0x0800		//!<Output paused for RTS Toggle predelay
+
+#define EV_IPU		0x0010		//!<Input paused unconditionally by user
+#define EV_IPS		0x0020		//!<Input paused by high/low water marks
+//#define EV_IPH	0x0040		//!<Input paused w/ hardware  
+#define EV_IPA		0x0400		//!<Input paused by pattern alarm module
+                                        
+#define EV_TXB		0x0040		//!<Transmit break pending
+#define EV_TXI		0x0080		//!<Transmit immediate pending
+#define EV_TXF		0x0100		//!<Transmit flowctrl char pending
+#define EV_RXB		0x0200		//!<Break received
+
+#define EV_OPALL	0x080f		//!<Output pause flags
+#define EV_IPALL	0x0430		//!<Input pause flags
+
+#endif /* DIGI_H */
diff --git a/drivers/staging/dgnc/dpacompat.h b/drivers/staging/dgnc/dpacompat.h
new file mode 100644
index 0000000..44379eb
--- /dev/null
+++ b/drivers/staging/dgnc/dpacompat.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *      NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ */
+
+
+/* 
+ * This structure holds data needed for the intelligent <--> nonintelligent 
+ * DPA translation
+ */
+ struct ni_info {
+	int board;
+	int channel;
+	int dtr;
+	int rts;
+	int cts;
+	int dsr;
+	int ri;
+	int dcd;
+	int curtx;
+	int currx;
+	unsigned short iflag;
+	unsigned short oflag;
+	unsigned short cflag;
+	unsigned short lflag;
+
+	unsigned int mstat;
+	unsigned char hflow;
+
+	unsigned char xmit_stopped;
+	unsigned char recv_stopped;
+
+	unsigned int baud;
+};
+
+#define RW_READ		1
+#define RW_WRITE        2
+#define DIGI_KME        ('e'<<8) | 98           /* Read/Write Host */
+
+#define SUBTYPE         0007
+#define T_PCXI          0000
+#define T_PCXEM         0001
+#define T_PCXE          0002
+#define T_PCXR          0003
+#define T_SP            0004
+#define T_SP_PLUS       0005
+
+#define T_HERC   0000
+#define T_HOU    0001
+#define T_LON    0002
+#define T_CHA    0003
+
+#define T_NEO	 0000
+#define T_NEO_EXPRESS  0001
+#define T_CLASSIC 0002
+
+#define FAMILY          0070
+#define T_COMXI         0000
+#define	T_NI		0000
+#define T_PCXX          0010
+#define T_CX            0020
+#define T_EPC           0030
+#define T_PCLITE        0040
+#define T_SPXX          0050
+#define T_AVXX          0060
+#define T_DXB           0070
+#define T_A2K_4_8       0070
+
+#define BUSTYPE         0700
+#define T_ISABUS        0000
+#define T_MCBUS         0100
+#define T_EISABUS       0200
+#define T_PCIBUS        0400
+
+/* Board State Definitions */
+
+#define BD_RUNNING      0x0
+#define BD_REASON       0x7f
+#define BD_NOTFOUND     0x1
+#define BD_NOIOPORT     0x2
+#define BD_NOMEM        0x3
+#define BD_NOBIOS       0x4
+#define BD_NOFEP        0x5
+#define BD_FAILED       0x6
+#define BD_ALLOCATED    0x7
+#define BD_TRIBOOT      0x8
+#define BD_BADKME       0x80
+
+#define DIGI_AIXON      0x0400          /* Aux flow control in fep */
+
+/* Ioctls needed for dpa operation */
+
+#define DIGI_GETDD      ('d'<<8) | 248          /* get driver info      */
+#define DIGI_GETBD      ('d'<<8) | 249          /* get board info       */
+#define DIGI_GET_NI_INFO ('d'<<8) | 250		/* nonintelligent state snfo */
+
+/* Other special ioctls */
+#define DIGI_TIMERIRQ ('d'<<8) | 251		/* Enable/disable RS_TIMER use */
+#define DIGI_LOOPBACK ('d'<<8) | 252		/* Enable/disable UART internal loopback */
diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c
index 654f601..0d52de3 100644
--- a/drivers/staging/dgrp/dgrp_tty.c
+++ b/drivers/staging/dgrp/dgrp_tty.c
@@ -1120,7 +1120,9 @@ static void dgrp_tty_close(struct tty_struct *tty, struct file *file)
 				if (!sent_printer_offstr)
 					dgrp_tty_flush_buffer(tty);
 
+				spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
 				tty_ldisc_flush(tty);
+				spin_lock_irqsave(&nd->nd_lock, lock_flags);
 				break;
 		}
 
diff --git a/drivers/staging/dwc2/Kconfig b/drivers/staging/dwc2/Kconfig
index d15d9d5..be947d6 100644
--- a/drivers/staging/dwc2/Kconfig
+++ b/drivers/staging/dwc2/Kconfig
@@ -1,7 +1,6 @@
 config USB_DWC2
 	tristate "DesignWare USB2 DRD Core Support"
 	depends on USB
-	depends on VIRT_TO_BUS
 	help
 	  Say Y or M here if your system has a Dual Role HighSpeed
 	  USB controller based on the DesignWare HSOTG IP Core.
diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
index e3a0e77..a090f79 100644
--- a/drivers/staging/dwc2/core.c
+++ b/drivers/staging/dwc2/core.c
@@ -277,7 +277,7 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 
 static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
 {
-	u32 ahbcfg = 0;
+	u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
 
 	switch (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) {
 	case GHWCFG2_EXT_DMA_ARCH:
@@ -286,11 +286,11 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
 
 	case GHWCFG2_INT_DMA_ARCH:
 		dev_dbg(hsotg->dev, "Internal DMA Mode\n");
-		/*
-		 * Old value was GAHBCFG_HBSTLEN_INCR - done for
-		 * Host mode ISOC in issue fix - vahrama
-		 */
-		ahbcfg |= GAHBCFG_HBSTLEN_INCR4;
+		if (hsotg->core_params->ahbcfg != -1) {
+			ahbcfg &= GAHBCFG_CTRL_MASK;
+			ahbcfg |= hsotg->core_params->ahbcfg &
+				  ~GAHBCFG_CTRL_MASK;
+		}
 		break;
 
 	case GHWCFG2_SLAVE_ONLY_ARCH:
@@ -313,9 +313,6 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
 		hsotg->core_params->dma_desc_enable = 0;
 	}
 
-	if (hsotg->core_params->ahb_single > 0)
-		ahbcfg |= GAHBCFG_AHB_SINGLE;
-
 	if (hsotg->core_params->dma_enable > 0)
 		ahbcfg |= GAHBCFG_DMA_EN;
 
@@ -2586,35 +2583,13 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val)
 	return retval;
 }
 
-int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val)
+int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val)
 {
-	int valid = 1;
-	int retval = 0;
-
-	if (DWC2_PARAM_TEST(val, 0, 1)) {
-		if (val >= 0) {
-			dev_err(hsotg->dev,
-				"'%d' invalid for parameter ahb_single\n", val);
-			dev_err(hsotg->dev, "ahb_single must be 0 or 1\n");
-		}
-		valid = 0;
-	}
-
-	if (val > 0 && hsotg->snpsid < DWC2_CORE_REV_2_94a)
-		valid = 0;
-
-	if (!valid) {
-		if (val >= 0)
-			dev_err(hsotg->dev,
-				"%d invalid for parameter ahb_single. Check HW configuration.\n",
-				val);
-		val = 0;
-		dev_dbg(hsotg->dev, "Setting ahb_single to %d\n", val);
-		retval = -EINVAL;
-	}
-
-	hsotg->core_params->ahb_single = val;
-	return retval;
+	if (val != -1)
+		hsotg->core_params->ahbcfg = val;
+	else
+		hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4;
+	return 0;
 }
 
 int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val)
@@ -2681,7 +2656,7 @@ int dwc2_set_parameters(struct dwc2_hsotg *hsotg,
 	retval |= dwc2_set_param_en_multiple_tx_fifo(hsotg,
 			params->en_multiple_tx_fifo);
 	retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl);
-	retval |= dwc2_set_param_ahb_single(hsotg, params->ahb_single);
+	retval |= dwc2_set_param_ahbcfg(hsotg, params->ahbcfg);
 	retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver);
 
 	return retval;
diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h
index fc075a7..e771e40 100644
--- a/drivers/staging/dwc2/core.h
+++ b/drivers/staging/dwc2/core.h
@@ -150,10 +150,11 @@ enum dwc2_lx_state {
  *                      are enabled
  * @reload_ctl:         True to allow dynamic reloading of HFIR register during
  *                      runtime
- * @ahb_single:         This bit enables SINGLE transfers for remainder data in
- *                      a transfer for DMA mode of operation.
- *                       0 - remainder data will be sent using INCR burst size
- *                       1 - remainder data will be sent using SINGLE burst size
+ * @ahbcfg:             This field allows the default value of the GAHBCFG
+ *                      register to be overridden
+ *                       -1         - GAHBCFG value will not be overridden
+ *                       all others - GAHBCFG value will be overridden with
+ *                                    this value
  * @otg_ver:            OTG version supported
  *                       0 - 1.3
  *                       1 - 2.0
@@ -189,7 +190,7 @@ struct dwc2_core_params {
 	int host_ls_low_power_phy_clk;
 	int ts_dline;
 	int reload_ctl;
-	int ahb_single;
+	int ahbcfg;
 };
 
 /**
@@ -643,7 +644,7 @@ extern int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg,
 
 extern int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val);
 
-extern int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val);
+extern int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val);
 
 extern int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val);
 
diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c
index 2ed54b1..32b52ad 100644
--- a/drivers/staging/dwc2/hcd.c
+++ b/drivers/staging/dwc2/hcd.c
@@ -134,11 +134,8 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg,
 	list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
 		list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
 					 qtd_list_entry) {
-			if (qtd->urb != NULL) {
-				dwc2_host_complete(hsotg, qtd->urb->priv,
-						   qtd->urb, -ETIMEDOUT);
-				dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
-			}
+			dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
+			dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
 		}
 	}
 }
@@ -421,6 +418,8 @@ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg,
 		return -EINVAL;
 	}
 
+	urb->priv = NULL;
+
 	if (urb_qtd->in_process && qh->channel) {
 		dwc2_dump_channel_info(hsotg, qh->channel);
 
@@ -2088,23 +2087,29 @@ static void dwc2_free_bus_bandwidth(struct usb_hcd *hcd, u16 bw,
  *
  * Must be called with interrupt disabled and spinlock held
  */
-void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context,
-			struct dwc2_hcd_urb *dwc2_urb, int status)
+void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
+			int status)
 {
-	struct urb *urb = context;
+	struct urb *urb;
 	int i;
 
-	if (!urb) {
-		dev_dbg(hsotg->dev, "## %s: context is NULL ##\n", __func__);
+	if (!qtd) {
+		dev_dbg(hsotg->dev, "## %s: qtd is NULL ##\n", __func__);
+		return;
+	}
+
+	if (!qtd->urb) {
+		dev_dbg(hsotg->dev, "## %s: qtd->urb is NULL ##\n", __func__);
 		return;
 	}
 
-	if (!dwc2_urb) {
-		dev_dbg(hsotg->dev, "## %s: dwc2_urb is NULL ##\n", __func__);
+	urb = qtd->urb->priv;
+	if (!urb) {
+		dev_dbg(hsotg->dev, "## %s: urb->priv is NULL ##\n", __func__);
 		return;
 	}
 
-	urb->actual_length = dwc2_hcd_urb_get_actual_length(dwc2_urb);
+	urb->actual_length = dwc2_hcd_urb_get_actual_length(qtd->urb);
 
 	if (dbg_urb(urb))
 		dev_vdbg(hsotg->dev,
@@ -2121,18 +2126,17 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context,
 	}
 
 	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-		urb->error_count = dwc2_hcd_urb_get_error_count(dwc2_urb);
+		urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
 		for (i = 0; i < urb->number_of_packets; ++i) {
 			urb->iso_frame_desc[i].actual_length =
 				dwc2_hcd_urb_get_iso_desc_actual_length(
-						dwc2_urb, i);
+						qtd->urb, i);
 			urb->iso_frame_desc[i].status =
-				dwc2_hcd_urb_get_iso_desc_status(dwc2_urb, i);
+				dwc2_hcd_urb_get_iso_desc_status(qtd->urb, i);
 		}
 	}
 
 	urb->status = status;
-	urb->hcpriv = NULL;
 	if (!status) {
 		if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
 		    urb->actual_length < urb->transfer_buffer_length)
@@ -2149,7 +2153,10 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context,
 					urb);
 	}
 
-	kfree(dwc2_urb);
+	usb_hcd_unlink_urb_from_ep(dwc2_hsotg_to_hcd(hsotg), urb);
+	urb->hcpriv = NULL;
+	kfree(qtd->urb);
+	qtd->urb = NULL;
 
 	spin_unlock(&hsotg->lock);
 	usb_hcd_giveback_urb(dwc2_hsotg_to_hcd(hsotg), urb, status);
@@ -2337,8 +2344,8 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 	struct usb_host_endpoint *ep = urb->ep;
 	struct dwc2_hcd_urb *dwc2_urb;
 	int i;
+	int retval;
 	int alloc_bandwidth = 0;
-	int retval = 0;
 	u8 ep_type = 0;
 	u32 tflags = 0;
 	void *buf;
@@ -2389,14 +2396,15 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 						!(usb_pipein(urb->pipe))));
 
 	buf = urb->transfer_buffer;
+
 	if (hcd->self.uses_dma) {
-		/*
-		 * Calculate virtual address from physical address, because
-		 * some class driver may not fill transfer_buffer.
-		 * In Buffer DMA mode virtual address is used, when handling
-		 * non-DWORD aligned buffers.
-		 */
-		buf = bus_to_virt(urb->transfer_dma);
+		if (!buf && (urb->transfer_dma & 3)) {
+			dev_err(hsotg->dev,
+				"%s: unaligned transfer with no transfer_buffer",
+				__func__);
+			retval = -EINVAL;
+			goto fail1;
+		}
 	}
 
 	if (!(urb->transfer_flags & URB_NO_INTERRUPT))
@@ -2420,21 +2428,36 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 						 urb->iso_frame_desc[i].length);
 
 	urb->hcpriv = dwc2_urb;
-	retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv,
-				      mem_flags);
-	if (retval) {
-		urb->hcpriv = NULL;
-		kfree(dwc2_urb);
-	} else {
-		if (alloc_bandwidth) {
-			spin_lock_irqsave(&hsotg->lock, flags);
-			dwc2_allocate_bus_bandwidth(hcd,
-					dwc2_hcd_get_ep_bandwidth(hsotg, ep),
-					urb);
-			spin_unlock_irqrestore(&hsotg->lock, flags);
-		}
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+	retval = usb_hcd_link_urb_to_ep(hcd, urb);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+	if (retval)
+		goto fail1;
+
+	retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, mem_flags);
+	if (retval)
+		goto fail2;
+
+	if (alloc_bandwidth) {
+		spin_lock_irqsave(&hsotg->lock, flags);
+		dwc2_allocate_bus_bandwidth(hcd,
+				dwc2_hcd_get_ep_bandwidth(hsotg, ep),
+				urb);
+		spin_unlock_irqrestore(&hsotg->lock, flags);
 	}
 
+	return 0;
+
+fail2:
+	spin_lock_irqsave(&hsotg->lock, flags);
+	dwc2_urb->priv = NULL;
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+fail1:
+	urb->hcpriv = NULL;
+	kfree(dwc2_urb);
+
 	return retval;
 }
 
@@ -2445,7 +2468,7 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 				 int status)
 {
 	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
-	int rc = 0;
+	int rc;
 	unsigned long flags;
 
 	dev_dbg(hsotg->dev, "DWC OTG HCD URB Dequeue\n");
@@ -2453,6 +2476,10 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
 	spin_lock_irqsave(&hsotg->lock, flags);
 
+	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+	if (rc)
+		goto out;
+
 	if (!urb->hcpriv) {
 		dev_dbg(hsotg->dev, "## urb->hcpriv is NULL ##\n");
 		goto out;
@@ -2460,6 +2487,8 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
 	rc = dwc2_hcd_urb_dequeue(hsotg, urb->hcpriv);
 
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+
 	kfree(urb->hcpriv);
 	urb->hcpriv = NULL;
 
@@ -2690,7 +2719,7 @@ void dwc2_set_all_params(struct dwc2_core_params *params, int value)
 	int i;
 
 	for (i = 0; i < size; i++)
-		p[i] = -1;
+		p[i] = value;
 }
 EXPORT_SYMBOL_GPL(dwc2_set_all_params);
 
@@ -2801,22 +2830,30 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
 	/* Validate parameter values */
 	dwc2_set_parameters(hsotg, params);
 
+	/* Check if the bus driver or platform code has setup a dma_mask */
+	if (hsotg->core_params->dma_enable > 0 &&
+	    hsotg->dev->dma_mask == NULL) {
+		dev_warn(hsotg->dev,
+			 "dma_mask not set, disabling DMA\n");
+		hsotg->core_params->dma_enable = 0;
+		hsotg->core_params->dma_desc_enable = 0;
+	}
+
 	/* Set device flags indicating whether the HCD supports DMA */
 	if (hsotg->core_params->dma_enable > 0) {
 		if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
 			dev_warn(hsotg->dev, "can't set DMA mask\n");
-		if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0)
-			dev_warn(hsotg->dev,
-				 "can't enable workaround for >2GB RAM\n");
-	} else {
-		dma_set_mask(hsotg->dev, 0);
-		dma_set_coherent_mask(hsotg->dev, 0);
+		if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
+			dev_warn(hsotg->dev, "can't set coherent DMA mask\n");
 	}
 
 	hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev));
 	if (!hcd)
 		goto error1;
 
+	if (hsotg->core_params->dma_enable <= 0)
+		hcd->self.uses_dma = 0;
+
 	hcd->has_tt = 1;
 
 	spin_lock_init(&hsotg->lock);
@@ -2922,8 +2959,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
 	if (retval < 0)
 		goto error3;
 
-	dwc2_dump_global_registers(hsotg);
-	dwc2_dump_host_registers(hsotg);
 	dwc2_hcd_dump_state(hsotg);
 
 	dwc2_enable_global_interrupts(hsotg);
diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h
index cf6c055..933e8d1 100644
--- a/drivers/staging/dwc2/hcd.h
+++ b/drivers/staging/dwc2/hcd.h
@@ -716,8 +716,8 @@ extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg);
 extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context,
 			       int *hub_addr, int *hub_port);
 extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
-extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context,
-			       struct dwc2_hcd_urb *dwc2_urb, int status);
+extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
+			       int status);
 
 #ifdef DEBUG
 /*
diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c
index 5c0fd27..de5af1b 100644
--- a/drivers/staging/dwc2/hcd_ddma.c
+++ b/drivers/staging/dwc2/hcd_ddma.c
@@ -800,6 +800,9 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
 	u16 remain = 0;
 	int rc = 0;
 
+	if (!qtd->urb)
+		return -EINVAL;
+
 	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
 	dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
 	if (chan->ep_is_in)
@@ -826,7 +829,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
 		 * urb->status is not used for isoc transfers here. The
 		 * individual frame_desc status are used instead.
 		 */
-		dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0);
+		dwc2_host_complete(hsotg, qtd, 0);
 		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
 
 		/*
@@ -884,13 +887,16 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
 
 		list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
 					 qtd_list_entry) {
-			for (idx = 0; idx < qtd->urb->packet_count; idx++) {
-				frame_desc = &qtd->urb->iso_descs[idx];
-				frame_desc->status = err;
+			if (qtd->urb) {
+				for (idx = 0; idx < qtd->urb->packet_count;
+				     idx++) {
+					frame_desc = &qtd->urb->iso_descs[idx];
+					frame_desc->status = err;
+				}
+
+				dwc2_host_complete(hsotg, qtd, err);
 			}
 
-			dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
-					   err);
 			dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
 		}
 
@@ -1015,6 +1021,9 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
 
 	dev_vdbg(hsotg->dev, "%s()\n", __func__);
 
+	if (!urb)
+		return -EINVAL;
+
 	dma_desc = &qh->desc_list[desc_num];
 	n_bytes = qh->n_bytes[desc_num];
 	dev_vdbg(hsotg->dev,
@@ -1024,7 +1033,7 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
 						     halt_status, n_bytes,
 						     xfer_done);
 	if (failed || (*xfer_done && urb->status != -EINPROGRESS)) {
-		dwc2_host_complete(hsotg, urb->priv, urb, urb->status);
+		dwc2_host_complete(hsotg, qtd, urb->status);
 		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
 		dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n",
 			 failed, *xfer_done, urb->status);
diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c
index e75dccb..9e68ef1 100644
--- a/drivers/staging/dwc2/hcd_intr.c
+++ b/drivers/staging/dwc2/hcd_intr.c
@@ -89,15 +89,20 @@ static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg,
 {
 	struct urb *usb_urb;
 
-	if (!chan->qh || !qtd->urb)
+	if (!chan->qh)
+		return;
+
+	if (chan->qh->dev_speed == USB_SPEED_HIGH)
+		return;
+
+	if (!qtd->urb)
 		return;
 
 	usb_urb = qtd->urb->priv;
-	if (!usb_urb || !usb_urb->dev)
+	if (!usb_urb || !usb_urb->dev || !usb_urb->dev->tt)
 		return;
 
-	if (chan->qh->dev_speed != USB_SPEED_HIGH &&
-	    qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) {
+	if (qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) {
 		chan->qh->tt_buffer_dirty = 1;
 		if (usb_hub_clear_tt_buffer(usb_urb))
 			/* Clear failed; let's hope things work anyway */
@@ -462,7 +467,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
 
 	/* Non DWORD-aligned buffer case handling */
 	if (chan->align_buf && xfer_length && chan->ep_is_in) {
-		dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
 		dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length,
 					DMA_FROM_DEVICE);
 		memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
@@ -557,8 +562,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
 		/* Non DWORD-aligned buffer case handling */
 		if (chan->align_buf && frame_desc->actual_length &&
 		    chan->ep_is_in) {
-			dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n",
-				__func__);
+			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
+				 __func__);
 			dma_sync_single_for_cpu(hsotg->dev, urb->dma,
 						urb->length, DMA_FROM_DEVICE);
 			memcpy(urb->buf + frame_desc->offset +
@@ -591,8 +596,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
 		/* Non DWORD-aligned buffer case handling */
 		if (chan->align_buf && frame_desc->actual_length &&
 		    chan->ep_is_in) {
-			dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n",
-				__func__);
+			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
+				 __func__);
 			dma_sync_single_for_cpu(hsotg->dev, urb->dma,
 						urb->length, DMA_FROM_DEVICE);
 			memcpy(urb->buf + frame_desc->offset +
@@ -623,7 +628,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
 		 * urb->status is not used for isoc transfers. The individual
 		 * frame_desc statuses are used instead.
 		 */
-		dwc2_host_complete(hsotg, urb->priv, urb, 0);
+		dwc2_host_complete(hsotg, qtd, 0);
 		halt_status = DWC2_HC_XFER_URB_COMPLETE;
 	} else {
 		halt_status = DWC2_HC_XFER_COMPLETE;
@@ -714,11 +719,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg,
 			dev_vdbg(hsotg->dev,
 				 "  Complete URB with transaction error\n");
 			free_qtd = 1;
-			if (qtd->urb) {
-				qtd->urb->status = -EPROTO;
-				dwc2_host_complete(hsotg, qtd->urb->priv,
-						   qtd->urb, -EPROTO);
-			}
+			dwc2_host_complete(hsotg, qtd, -EPROTO);
 		}
 		break;
 	case DWC2_HC_XFER_URB_DEQUEUE:
@@ -731,11 +732,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg,
 	case DWC2_HC_XFER_PERIODIC_INCOMPLETE:
 		dev_vdbg(hsotg->dev, "  Complete URB with I/O error\n");
 		free_qtd = 1;
-		if (qtd && qtd->urb) {
-			qtd->urb->status = -EIO;
-			dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
-					   -EIO);
-		}
+		dwc2_host_complete(hsotg, qtd, -EIO);
 		break;
 	case DWC2_HC_XFER_NO_HALT_STATUS:
 	default:
@@ -938,7 +935,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
 	frame_desc->actual_length += len;
 
 	if (chan->align_buf && len) {
-		dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
 		dma_sync_single_for_cpu(hsotg->dev, qtd->urb->dma,
 					qtd->urb->length, DMA_FROM_DEVICE);
 		memcpy(qtd->urb->buf + frame_desc->offset +
@@ -957,7 +954,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
 	}
 
 	if (qtd->isoc_frame_index == qtd->urb->packet_count) {
-		dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0);
+		dwc2_host_complete(hsotg, qtd, 0);
 		dwc2_release_channel(hsotg, chan, qtd,
 				     DWC2_HC_XFER_URB_COMPLETE);
 	} else {
@@ -1040,7 +1037,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
 			dev_vdbg(hsotg->dev, "  Control transfer complete\n");
 			if (urb->status == -EINPROGRESS)
 				urb->status = 0;
-			dwc2_host_complete(hsotg, urb->priv, urb, urb->status);
+			dwc2_host_complete(hsotg, qtd, urb->status);
 			halt_status = DWC2_HC_XFER_URB_COMPLETE;
 			break;
 		}
@@ -1053,7 +1050,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
 		urb_xfer_done = dwc2_update_urb_state(hsotg, chan, chnum, urb,
 						      qtd);
 		if (urb_xfer_done) {
-			dwc2_host_complete(hsotg, urb->priv, urb, urb->status);
+			dwc2_host_complete(hsotg, qtd, urb->status);
 			halt_status = DWC2_HC_XFER_URB_COMPLETE;
 		} else {
 			halt_status = DWC2_HC_XFER_COMPLETE;
@@ -1073,11 +1070,10 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
 		 * interrupt
 		 */
 		if (urb_xfer_done) {
-				dwc2_host_complete(hsotg, urb->priv, urb,
-						   urb->status);
-				halt_status = DWC2_HC_XFER_URB_COMPLETE;
+			dwc2_host_complete(hsotg, qtd, urb->status);
+			halt_status = DWC2_HC_XFER_URB_COMPLETE;
 		} else {
-				halt_status = DWC2_HC_XFER_COMPLETE;
+			halt_status = DWC2_HC_XFER_COMPLETE;
 		}
 
 		dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
@@ -1123,11 +1119,11 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg,
 		goto handle_stall_halt;
 
 	if (pipe_type == USB_ENDPOINT_XFER_CONTROL)
-		dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE);
+		dwc2_host_complete(hsotg, qtd, -EPIPE);
 
 	if (pipe_type == USB_ENDPOINT_XFER_BULK ||
 	    pipe_type == USB_ENDPOINT_XFER_INT) {
-		dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE);
+		dwc2_host_complete(hsotg, qtd, -EPIPE);
 		/*
 		 * USB protocol requires resetting the data toggle for bulk
 		 * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
@@ -1168,7 +1164,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
 
 	/* Non DWORD-aligned buffer case handling */
 	if (chan->align_buf && xfer_length && chan->ep_is_in) {
-		dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
 		dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length,
 					DMA_FROM_DEVICE);
 		memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
@@ -1372,10 +1368,10 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
 		    hsotg->core_params->dma_enable > 0) {
 			qtd->complete_split = 0;
 			qtd->isoc_split_offset = 0;
+			qtd->isoc_frame_index++;
 			if (qtd->urb &&
-			    ++qtd->isoc_frame_index == qtd->urb->packet_count) {
-				dwc2_host_complete(hsotg, qtd->urb->priv,
-						   qtd->urb, 0);
+			    qtd->isoc_frame_index == qtd->urb->packet_count) {
+				dwc2_host_complete(hsotg, qtd, 0);
 				dwc2_release_channel(hsotg, chan, qtd,
 						     DWC2_HC_XFER_URB_COMPLETE);
 			} else {
@@ -1445,16 +1441,16 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg,
 	dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Babble Error--\n",
 		chnum);
 
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+
 	if (hsotg->core_params->dma_desc_enable > 0) {
 		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
 					    DWC2_HC_XFER_BABBLE_ERR);
-		goto handle_babble_done;
+		goto disable_int;
 	}
 
 	if (chan->ep_type != USB_ENDPOINT_XFER_ISOC) {
-		if (qtd->urb)
-			dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
-					   -EOVERFLOW);
+		dwc2_host_complete(hsotg, qtd, -EOVERFLOW);
 		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_BABBLE_ERR);
 	} else {
 		enum dwc2_halt_status halt_status;
@@ -1464,8 +1460,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg,
 		dwc2_halt_channel(hsotg, chan, qtd, halt_status);
 	}
 
-handle_babble_done:
-	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+disable_int:
 	disable_hc_int(hsotg, chnum, HCINTMSK_BBLERR);
 }
 
@@ -1490,6 +1485,8 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
 	if (!urb)
 		goto handle_ahberr_halt;
 
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+
 	hcchar = readl(hsotg->regs + HCCHAR(chnum));
 	hcsplt = readl(hsotg->regs + HCSPLT(chnum));
 	hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
@@ -1557,7 +1554,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
 		goto handle_ahberr_done;
 	}
 
-	dwc2_host_complete(hsotg, urb->priv, urb, -EIO);
+	dwc2_host_complete(hsotg, qtd, -EIO);
 
 handle_ahberr_halt:
 	/*
@@ -1567,7 +1564,6 @@ handle_ahberr_halt:
 	dwc2_hc_halt(hsotg, chan, DWC2_HC_XFER_AHB_ERR);
 
 handle_ahberr_done:
-	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
 	disable_hc_int(hsotg, chnum, HCINTMSK_AHBERR);
 }
 
@@ -1582,6 +1578,8 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
 	dev_dbg(hsotg->dev,
 		"--Host Channel %d Interrupt: Transaction Error--\n", chnum);
 
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+
 	if (hsotg->core_params->dma_desc_enable > 0) {
 		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
 					    DWC2_HC_XFER_XACT_ERR);
@@ -1625,7 +1623,6 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
 	}
 
 handle_xacterr_done:
-	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
 	disable_hc_int(hsotg, chnum, HCINTMSK_XACTERR);
 }
 
@@ -1643,6 +1640,8 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg,
 		dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Frame Overrun--\n",
 			chnum);
 
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+
 	switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 	case USB_ENDPOINT_XFER_BULK:
@@ -1657,7 +1656,6 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg,
 		break;
 	}
 
-	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
 	disable_hc_int(hsotg, chnum, HCINTMSK_FRMOVRUN);
 }
 
diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c
index b36f783..5461e3b 100644
--- a/drivers/staging/dwc2/hcd_queue.c
+++ b/drivers/staging/dwc2/hcd_queue.c
@@ -197,6 +197,9 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
 {
 	struct dwc2_qh *qh;
 
+	if (!urb->priv)
+		return NULL;
+
 	/* Allocate memory */
 	qh = kzalloc(sizeof(*qh), mem_flags);
 	if (!qh)
@@ -638,7 +641,7 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
 	struct dwc2_hcd_urb *urb = qtd->urb;
 	unsigned long flags;
 	int allocated = 0;
-	int retval = 0;
+	int retval;
 
 	/*
 	 * Get the QH which holds the QTD-list to insert to. Create QH if it
@@ -652,8 +655,19 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
 	}
 
 	spin_lock_irqsave(&hsotg->lock, flags);
+
 	retval = dwc2_hcd_qh_add(hsotg, *qh);
-	if (retval && allocated) {
+	if (retval)
+		goto fail;
+
+	qtd->qh = *qh;
+	list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
+	return 0;
+
+fail:
+	if (allocated) {
 		struct dwc2_qtd *qtd2, *qtd2_tmp;
 		struct dwc2_qh *qh_tmp = *qh;
 
@@ -668,8 +682,6 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
 		spin_unlock_irqrestore(&hsotg->lock, flags);
 		dwc2_hcd_qh_free(hsotg, qh_tmp);
 	} else {
-		qtd->qh = *qh;
-		list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
 		spin_unlock_irqrestore(&hsotg->lock, flags);
 	}
 
diff --git a/drivers/staging/dwc2/hw.h b/drivers/staging/dwc2/hw.h
index 382a1d7..cf0dc97 100644
--- a/drivers/staging/dwc2/hw.h
+++ b/drivers/staging/dwc2/hw.h
@@ -78,6 +78,10 @@
 #define GAHBCFG_HBSTLEN_INCR8			(5 << 1)
 #define GAHBCFG_HBSTLEN_INCR16			(7 << 1)
 #define GAHBCFG_GLBL_INTR_EN		(1 << 0)
+#define GAHBCFG_CTRL_MASK		(GAHBCFG_P_TXF_EMP_LVL | \
+					 GAHBCFG_NP_TXF_EMP_LVL | \
+					 GAHBCFG_DMA_EN | \
+					 GAHBCFG_GLBL_INTR_EN)
 
 #define GUSBCFG				HSOTG_REG(0x00C)
 #define GUSBCFG_FORCEDEVMODE		(1 << 30)
diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c
index 3ca54d6..fdfbc71 100644
--- a/drivers/staging/dwc2/pci.c
+++ b/drivers/staging/dwc2/pci.c
@@ -83,7 +83,7 @@ static const struct dwc2_core_params dwc2_module_params = {
 	.host_ls_low_power_phy_clk	= -1,
 	.ts_dline			= -1,
 	.reload_ctl			= -1,
-	.ahb_single			= -1,
+	.ahbcfg				= -1,
 };
 
 /**
diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig
new file mode 100644
index 0000000..0a1f090
--- /dev/null
+++ b/drivers/staging/gdm724x/Kconfig
@@ -0,0 +1,15 @@
+#
+# GCT GDM724x LTE driver configuration
+#
+
+config LTE_GDM724X
+	tristate "GCT GDM724x LTE support"
+	depends on NET && USB && TTY && m
+	help
+	  This driver supports GCT GDM724x LTE chip based USB modem devices.
+	  It exposes 4 network devices to be used per PDN and 2 tty devices to be
+	  used for AT commands and DM monitoring applications.
+	  The modules will be called gdmulte.ko and gdmtty.ko
+
+	  GCT-ATCx can be used for AT Commands
+	  GCT-DMx can be used for LTE protocol monitoring
diff --git a/drivers/staging/gdm724x/Makefile b/drivers/staging/gdm724x/Makefile
new file mode 100644
index 0000000..ba7f11a
--- /dev/null
+++ b/drivers/staging/gdm724x/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_LTE_GDM724X) := gdmulte.o
+gdmulte-y += gdm_lte.o netlink_k.o
+gdmulte-y += gdm_usb.o gdm_endian.o
+
+obj-$(CONFIG_LTE_GDM724X) += gdmtty.o
+gdmtty-y := gdm_tty.o gdm_mux.o
+
diff --git a/drivers/staging/gdm724x/TODO b/drivers/staging/gdm724x/TODO
new file mode 100644
index 0000000..b2b571e
--- /dev/null
+++ b/drivers/staging/gdm724x/TODO
@@ -0,0 +1,16 @@
+TODO:
+- Clean up coding style to meet kernel standard. (80 line limit, netdev_err)
+- Remove test for host endian
+- Remove confusing macros (endian, hci_send, sdu_send, rcv_with_cb)
+- Fixes for every instances of function returning -1
+- Check for skb->len in gdm_lte_emulate_arp()
+- Use ALIGN() macro for dummy_cnt in up_to_host()
+- Error handling in init_usb()
+- Explain reason for multiples of 512 bytes in alloc_tx_struct()
+- Review use of atomic allocation for tx structs
+- No error checking for alloc_tx_struct in do_tx()
+- fix up static tty port allocation to be dynamic
+
+Patches to:
+	Jonathan Kim <jonathankim@gctsemi.com>
+	Dean ahn <deanahn@gctsemi.com>
diff --git a/drivers/staging/gdm724x/gdm_endian.c b/drivers/staging/gdm724x/gdm_endian.c
new file mode 100644
index 0000000..f6cc90a
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_endian.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include "gdm_endian.h"
+
+void gdm_set_endian(struct gdm_endian *ed, u8 dev_endian)
+{
+	u8 a[2] = {0x12, 0x34};
+	u8 b[2] = {0, };
+	u16 c = 0x1234;
+
+	if (dev_endian == ENDIANNESS_BIG)
+		ed->dev_ed = ENDIANNESS_BIG;
+	else
+		ed->dev_ed = ENDIANNESS_LITTLE;
+
+	memcpy(b, &c, 2);
+
+	if (a[0] != b[0])
+		ed->host_ed = ENDIANNESS_LITTLE;
+	else
+		ed->host_ed = ENDIANNESS_BIG;
+
+}
+
+u16 gdm_cpu_to_dev16(struct gdm_endian *ed, u16 x)
+{
+	if (ed->dev_ed == ed->host_ed)
+		return x;
+
+	return Endian16_Swap(x);
+}
+
+u16 gdm_dev16_to_cpu(struct gdm_endian *ed, u16 x)
+{
+	if (ed->dev_ed == ed->host_ed)
+		return x;
+
+	return Endian16_Swap(x);
+}
+
+u32 gdm_cpu_to_dev32(struct gdm_endian *ed, u32 x)
+{
+	if (ed->dev_ed == ed->host_ed)
+		return x;
+
+	return Endian32_Swap(x);
+}
+
+u32 gdm_dev32_to_cpu(struct gdm_endian *ed, u32 x)
+{
+	if (ed->dev_ed == ed->host_ed)
+		return x;
+
+	return Endian32_Swap(x);
+}
diff --git a/drivers/staging/gdm724x/gdm_endian.h b/drivers/staging/gdm724x/gdm_endian.h
new file mode 100644
index 0000000..9b2531f
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_endian.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __GDM_ENDIAN_H__
+#define __GDM_ENDIAN_H__
+
+#include <linux/types.h>
+
+#define Endian16_Swap(value) \
+	((((u16)((value) & 0x00FF)) << 8) | \
+	 (((u16)((value) & 0xFF00)) >> 8))
+
+#define Endian32_Swap(value) \
+	((((u32)((value) & 0x000000FF)) << 24) | \
+	 (((u32)((value) & 0x0000FF00)) << 8) | \
+	 (((u32)((value) & 0x00FF0000)) >> 8) | \
+	 (((u32)((value) & 0xFF000000)) >> 24))
+
+enum {
+	ENDIANNESS_MIN = 0,
+	ENDIANNESS_UNKNOWN,
+	ENDIANNESS_LITTLE,
+	ENDIANNESS_BIG,
+	ENDIANNESS_MIDDLE,
+	ENDIANNESS_MAX
+};
+
+struct gdm_endian {
+	u8 dev_ed;
+	u8 host_ed;
+};
+
+void gdm_set_endian(struct gdm_endian *ed, u8 dev_endian);
+u16 gdm_cpu_to_dev16(struct gdm_endian *ed, u16 x);
+u16 gdm_dev16_to_cpu(struct gdm_endian *ed, u16 x);
+u32 gdm_cpu_to_dev32(struct gdm_endian *ed, u32 x);
+u32 gdm_dev32_to_cpu(struct gdm_endian *ed, u32 x);
+
+#endif /*__GDM_ENDIAN_H__*/
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
new file mode 100644
index 0000000..7165d3a
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_lte.c
@@ -0,0 +1,877 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+#include <linux/uaccess.h>
+#include <net/ndisc.h>
+
+#include "gdm_lte.h"
+#include "netlink_k.h"
+#include "hci.h"
+#include "hci_packet.h"
+#include "gdm_endian.h"
+
+/*
+ * Netlink protocol number
+ */
+#define NETLINK_LTE 30
+
+/*
+ * Default MTU Size
+ */
+#define DEFAULT_MTU_SIZE 1500
+
+#define gdm_dev_endian(n) (\
+	n->phy_dev->get_endian(n->phy_dev->priv_dev))
+
+#define gdm_lte_hci_send(n, d, l) (\
+	n->phy_dev->send_hci_func(n->phy_dev->priv_dev, d, l, NULL, NULL))
+
+#define gdm_lte_sdu_send(n, d, l, c, b, i, t) (\
+	n->phy_dev->send_sdu_func(n->phy_dev->priv_dev, d, l, n->pdn_table.dft_eps_id, 0, c, b, i, t))
+
+#define gdm_lte_rcv_with_cb(n, c, b, e) (\
+	n->rcv_func(n->priv_dev, c, b, e))
+
+#define IP_VERSION_4	4
+#define IP_VERSION_6	6
+
+static struct {
+	int ref_cnt;
+	struct sock *sock;
+} lte_event;
+
+static struct device_type wwan_type = {
+	.name   = "wwan",
+};
+
+static int gdm_lte_open(struct net_device *dev)
+{
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int gdm_lte_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static int gdm_lte_set_config(struct net_device *dev, struct ifmap *map)
+{
+	if (dev->flags & IFF_UP)
+		return -EBUSY;
+	return 0;
+}
+
+static void tx_complete(void *arg)
+{
+	struct nic *nic = arg;
+
+	if (netif_queue_stopped(nic->netdev))
+		netif_wake_queue(nic->netdev);
+}
+
+static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type)
+{
+	int ret;
+
+	ret = netif_rx_ni(skb);
+	if (ret == NET_RX_DROP) {
+		nic->stats.rx_dropped++;
+	} else {
+		nic->stats.rx_packets++;
+		nic->stats.rx_bytes += skb->len + ETH_HLEN;
+	}
+
+	return 0;
+}
+
+int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type)
+{
+	struct nic *nic = netdev_priv(skb_in->dev);
+	struct sk_buff *skb_out;
+	struct ethhdr eth;
+	struct vlan_ethhdr vlan_eth;
+	struct arphdr *arp_in;
+	struct arphdr *arp_out;
+	struct arpdata {
+		u8 ar_sha[ETH_ALEN];
+		u8 ar_sip[4];
+		u8 ar_tha[ETH_ALEN];
+		u8 ar_tip[4];
+	};
+	struct arpdata *arp_data_in;
+	struct arpdata *arp_data_out;
+	u8 arp_temp[60];
+	void *mac_header_data;
+	u32 mac_header_len;
+
+	/* Format the mac header so that it can be put to skb */
+	if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) {
+		memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr));
+		mac_header_data = &vlan_eth;
+		mac_header_len = VLAN_ETH_HLEN;
+	} else {
+		memcpy(&eth, skb_in->data, sizeof(struct ethhdr));
+		mac_header_data = &eth;
+		mac_header_len = ETH_HLEN;
+	}
+
+	/* Get the pointer of the original request */
+	arp_in = (struct arphdr *)(skb_in->data + mac_header_len);
+	arp_data_in = (struct arpdata *)(skb_in->data + mac_header_len + sizeof(struct arphdr));
+
+	/* Get the pointer of the outgoing response */
+	arp_out = (struct arphdr *)arp_temp;
+	arp_data_out = (struct arpdata *)(arp_temp + sizeof(struct arphdr));
+
+	/* Copy the arp header */
+	memcpy(arp_out, arp_in, sizeof(struct arphdr));
+	arp_out->ar_op = htons(ARPOP_REPLY);
+
+	/* Copy the arp payload: based on 2 bytes of mac and fill the IP */
+	arp_data_out->ar_sha[0] = arp_data_in->ar_sha[0];
+	arp_data_out->ar_sha[1] = arp_data_in->ar_sha[1];
+	memcpy(&arp_data_out->ar_sha[2], &arp_data_in->ar_tip[0], 4);
+	memcpy(&arp_data_out->ar_sip[0], &arp_data_in->ar_tip[0], 4);
+	memcpy(&arp_data_out->ar_tha[0], &arp_data_in->ar_sha[0], 6);
+	memcpy(&arp_data_out->ar_tip[0], &arp_data_in->ar_sip[0], 4);
+
+	/* Fill the destination mac with source mac of the received packet */
+	memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN);
+	/* Fill the source mac with nic's source mac */
+	memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
+
+	/* Alloc skb and reserve align */
+	skb_out = dev_alloc_skb(skb_in->len);
+	if (!skb_out)
+		return -ENOMEM;
+	skb_reserve(skb_out, NET_IP_ALIGN);
+
+	memcpy(skb_put(skb_out, mac_header_len), mac_header_data, mac_header_len);
+	memcpy(skb_put(skb_out, sizeof(struct arphdr)), arp_out, sizeof(struct arphdr));
+	memcpy(skb_put(skb_out, sizeof(struct arpdata)), arp_data_out, sizeof(struct arpdata));
+
+	skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
+	skb_out->dev = skb_in->dev;
+	skb_reset_mac_header(skb_out);
+	skb_pull(skb_out, ETH_HLEN);
+
+	gdm_lte_rx(skb_out, nic, nic_type);
+
+	return 0;
+}
+
+int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len)
+{
+	unsigned short *w = ptr;
+	int sum = 0;
+	int i;
+
+	union {
+		struct {
+			u8 ph_src[16];
+			u8 ph_dst[16];
+			u32 ph_len;
+			u8 ph_zero[3];
+			u8 ph_nxt;
+		} ph __packed;
+		u16 pa[20];
+	} pseudo_header;
+
+	memset(&pseudo_header, 0, sizeof(pseudo_header));
+	memcpy(&pseudo_header.ph.ph_src, &ipv6->saddr.in6_u.u6_addr8, 16);
+	memcpy(&pseudo_header.ph.ph_dst, &ipv6->daddr.in6_u.u6_addr8, 16);
+	pseudo_header.ph.ph_len = ipv6->payload_len;
+	pseudo_header.ph.ph_nxt = ipv6->nexthdr;
+
+	w = (u16 *)&pseudo_header;
+	for (i = 0; i < sizeof(pseudo_header.pa) / sizeof(pseudo_header.pa[0]); i++)
+		sum += pseudo_header.pa[i];
+
+	w = ptr;
+	while (len > 1) {
+		sum += *w++;
+		len -= 2;
+	}
+
+	sum = (sum >> 16) + (sum & 0xFFFF);
+	sum += (sum >> 16);
+	sum = ~sum & 0xffff;
+
+	return sum;
+}
+
+int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
+{
+	struct nic *nic = netdev_priv(skb_in->dev);
+	struct sk_buff *skb_out;
+	struct ethhdr eth;
+	struct vlan_ethhdr vlan_eth;
+	struct neighbour_advertisement {
+		u8 target_address[16];
+		u8 type;
+		u8 length;
+		u8 link_layer_address[6];
+	};
+	struct neighbour_advertisement na;
+	struct neighbour_solicitation {
+		u8 target_address[16];
+	};
+	struct neighbour_solicitation *ns;
+	struct ipv6hdr *ipv6_in;
+	struct ipv6hdr ipv6_out;
+	struct icmp6hdr *icmp6_in;
+	struct icmp6hdr icmp6_out;
+
+	void *mac_header_data;
+	u32 mac_header_len;
+
+	/* Format the mac header so that it can be put to skb */
+	if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) {
+		memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr));
+		if (ntohs(vlan_eth.h_vlan_encapsulated_proto) != ETH_P_IPV6)
+			return -1;
+		mac_header_data = &vlan_eth;
+		mac_header_len = VLAN_ETH_HLEN;
+	} else {
+		memcpy(&eth, skb_in->data, sizeof(struct ethhdr));
+		if (ntohs(eth.h_proto) != ETH_P_IPV6)
+			return -1;
+		mac_header_data = &eth;
+		mac_header_len = ETH_HLEN;
+	}
+
+	/* Check if this is IPv6 ICMP packet */
+	ipv6_in = (struct ipv6hdr *)(skb_in->data + mac_header_len);
+	if (ipv6_in->version != 6 || ipv6_in->nexthdr != IPPROTO_ICMPV6)
+		return -1;
+
+	/* Check if this is NDP packet */
+	icmp6_in = (struct icmp6hdr *)(skb_in->data + mac_header_len + sizeof(struct ipv6hdr));
+	if (icmp6_in->icmp6_type == NDISC_ROUTER_SOLICITATION) { /* Check RS */
+		return -1;
+	} else if (icmp6_in->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { /* Check NS */
+		u8 icmp_na[sizeof(struct icmp6hdr) + sizeof(struct neighbour_advertisement)];
+		u8 zero_addr8[16] = {0,};
+
+		if (memcmp(ipv6_in->saddr.in6_u.u6_addr8, zero_addr8, 16) == 0)
+			/* Duplicate Address Detection: Source IP is all zero */
+			return 0;
+
+		icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
+		icmp6_out.icmp6_code = 0;
+		icmp6_out.icmp6_cksum = 0;
+		icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); /* R=0, S=1, O=1 */
+
+		ns = (struct neighbour_solicitation *)(skb_in->data + mac_header_len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr));
+		memcpy(&na.target_address, ns->target_address, 16);
+		na.type = 0x02;
+		na.length = 1;
+		na.link_layer_address[0] = 0x00;
+		na.link_layer_address[1] = 0x0a;
+		na.link_layer_address[2] = 0x3b;
+		na.link_layer_address[3] = 0xaf;
+		na.link_layer_address[4] = 0x63;
+		na.link_layer_address[5] = 0xc7;
+
+		memcpy(&ipv6_out, ipv6_in, sizeof(struct ipv6hdr));
+		memcpy(ipv6_out.saddr.in6_u.u6_addr8, &na.target_address, 16);
+		memcpy(ipv6_out.daddr.in6_u.u6_addr8, ipv6_in->saddr.in6_u.u6_addr8, 16);
+		ipv6_out.payload_len = htons(sizeof(struct icmp6hdr) + sizeof(struct neighbour_advertisement));
+
+		memcpy(icmp_na, &icmp6_out, sizeof(struct icmp6hdr));
+		memcpy(icmp_na + sizeof(struct icmp6hdr), &na, sizeof(struct neighbour_advertisement));
+
+		icmp6_out.icmp6_cksum = icmp6_checksum(&ipv6_out, (u16 *)icmp_na, sizeof(icmp_na));
+	} else {
+		return -1;
+	}
+
+	/* Fill the destination mac with source mac of the received packet */
+	memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN);
+	/* Fill the source mac with nic's source mac */
+	memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
+
+	/* Alloc skb and reserve align */
+	skb_out = dev_alloc_skb(skb_in->len);
+	if (!skb_out)
+		return -ENOMEM;
+	skb_reserve(skb_out, NET_IP_ALIGN);
+
+	memcpy(skb_put(skb_out, mac_header_len), mac_header_data, mac_header_len);
+	memcpy(skb_put(skb_out, sizeof(struct ipv6hdr)), &ipv6_out, sizeof(struct ipv6hdr));
+	memcpy(skb_put(skb_out, sizeof(struct icmp6hdr)), &icmp6_out, sizeof(struct icmp6hdr));
+	memcpy(skb_put(skb_out, sizeof(struct neighbour_advertisement)), &na, sizeof(struct neighbour_advertisement));
+
+	skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
+	skb_out->dev = skb_in->dev;
+	skb_reset_mac_header(skb_out);
+	skb_pull(skb_out, ETH_HLEN);
+
+	gdm_lte_rx(skb_out, nic, nic_type);
+
+	return 0;
+}
+
+static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb)
+{
+	struct nic *nic = netdev_priv(dev);
+	struct ethhdr *eth;
+	struct vlan_ethhdr *vlan_eth;
+	struct iphdr *ip;
+	struct ipv6hdr *ipv6;
+	int mac_proto;
+	void *network_data;
+	u32 nic_type = 0;
+
+	/* NIC TYPE is based on the nic_id of this net_device */
+	nic_type = 0x00000010 | nic->nic_id;
+
+	/* Get ethernet protocol */
+	eth = (struct ethhdr *)skb->data;
+	if (ntohs(eth->h_proto) == ETH_P_8021Q) {
+		vlan_eth = (struct vlan_ethhdr *)skb->data;
+		mac_proto = ntohs(vlan_eth->h_vlan_encapsulated_proto);
+		network_data = skb->data + VLAN_ETH_HLEN;
+		nic_type |= NIC_TYPE_F_VLAN;
+	} else {
+		mac_proto = ntohs(eth->h_proto);
+		network_data = skb->data + ETH_HLEN;
+	}
+
+	/* Process packet for nic type */
+	switch (mac_proto) {
+	case ETH_P_ARP:
+		nic_type |= NIC_TYPE_ARP;
+		break;
+	case ETH_P_IP:
+		nic_type |= NIC_TYPE_F_IPV4;
+		ip = (struct iphdr *)network_data;
+
+		/* Check DHCPv4 */
+		if (ip->protocol == IPPROTO_UDP) {
+			struct udphdr *udp = (struct udphdr *)(network_data + sizeof(struct iphdr));
+			if (ntohs(udp->dest) == 67 || ntohs(udp->dest) == 68)
+				nic_type |= NIC_TYPE_F_DHCP;
+		}
+		break;
+	case ETH_P_IPV6:
+		nic_type |= NIC_TYPE_F_IPV6;
+		ipv6 = (struct ipv6hdr *)network_data;
+
+		if (ipv6->nexthdr == IPPROTO_ICMPV6) /* Check NDP request */ {
+			struct icmp6hdr *icmp6 = (struct icmp6hdr *)(network_data + sizeof(struct ipv6hdr));
+			if (/*icmp6->icmp6_type == NDISC_ROUTER_SOLICITATION || */
+				icmp6->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
+				nic_type |= NIC_TYPE_ICMPV6;
+		} else if (ipv6->nexthdr == IPPROTO_UDP) /* Check DHCPv6 */ {
+			struct udphdr *udp = (struct udphdr *)(network_data + sizeof(struct ipv6hdr));
+			if (ntohs(udp->dest) == 546 || ntohs(udp->dest) == 547)
+				nic_type |= NIC_TYPE_F_DHCP;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return nic_type;
+}
+
+static int gdm_lte_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct nic *nic = netdev_priv(dev);
+	u32 nic_type;
+	void *data_buf;
+	int data_len;
+	int idx;
+	int ret = 0;
+
+	nic_type = gdm_lte_tx_nic_type(dev, skb);
+	if (nic_type == 0) {
+		netdev_err(dev, "tx - invalid nic_type\n");
+		return -1;
+	}
+
+	if (nic_type & NIC_TYPE_ARP) {
+		if (gdm_lte_emulate_arp(skb, nic_type) == 0) {
+			dev_kfree_skb(skb);
+			return 0;
+		}
+	}
+
+	if (nic_type & NIC_TYPE_ICMPV6) {
+		if (gdm_lte_emulate_ndp(skb, nic_type) == 0) {
+			dev_kfree_skb(skb);
+			return 0;
+		}
+	}
+
+	/*
+	Need byte shift (that is, remove VLAN tag) if there is one
+	For the case of ARP, this breaks the offset as vlan_ethhdr+4 is treated as ethhdr
+	However, it shouldn't be a problem as the reponse starts from arp_hdr and ethhdr
+	is created by this driver based on the NIC mac
+	*/
+	if (nic_type & NIC_TYPE_F_VLAN) {
+		struct vlan_ethhdr *vlan_eth = (struct vlan_ethhdr *)skb->data;
+		nic->vlan_id = ntohs(vlan_eth->h_vlan_TCI) & VLAN_VID_MASK;
+		data_buf = skb->data + (VLAN_ETH_HLEN - ETH_HLEN);
+		data_len = skb->len - (VLAN_ETH_HLEN - ETH_HLEN);
+	} else {
+		nic->vlan_id = 0;
+		data_buf = skb->data;
+		data_len = skb->len;
+	}
+
+	/* If it is a ICMPV6 packet, clear all the other bits : for backward compatibilty with the firmware */
+	if (nic_type & NIC_TYPE_ICMPV6)
+		nic_type = NIC_TYPE_ICMPV6;
+
+	/* If it is not a dhcp packet, clear all the flag bits : original NIC, otherwise the special flag (IPVX | DHCP) */
+	if (!(nic_type & NIC_TYPE_F_DHCP))
+		nic_type &= NIC_TYPE_MASK;
+
+	sscanf(dev->name, "lte%d", &idx);
+
+	ret = gdm_lte_sdu_send(nic,
+			       data_buf,
+			       data_len,
+			       tx_complete,
+			       nic,
+			       idx,
+			       nic_type);
+
+	if (ret == TX_NO_BUFFER || ret == TX_NO_SPC) {
+		netif_stop_queue(dev);
+		if (ret == TX_NO_BUFFER)
+			ret = 0;
+		else
+			ret = -ENOSPC;
+	} else if (ret == TX_NO_DEV) {
+		ret = -ENODEV;
+	}
+
+	/* Updates tx stats */
+	if (ret) {
+		nic->stats.tx_dropped++;
+	} else {
+		nic->stats.tx_packets++;
+		nic->stats.tx_bytes += data_len;
+	}
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static struct net_device_stats *gdm_lte_stats(struct net_device *dev)
+{
+	struct nic *nic = netdev_priv(dev);
+	return &nic->stats;
+}
+
+static int gdm_lte_event_send(struct net_device *dev, char *buf, int len)
+{
+	struct nic *nic = netdev_priv(dev);
+	struct hci_packet *hci = (struct hci_packet *)buf;
+	int idx;
+
+	sscanf(dev->name, "lte%d", &idx);
+
+	return netlink_send(lte_event.sock, idx, 0, buf,
+			    gdm_dev16_to_cpu(gdm_dev_endian(nic), hci->len) + HCI_HEADER_SIZE);
+}
+
+static void gdm_lte_event_rcv(struct net_device *dev, u16 type, void *msg, int len)
+{
+	struct nic *nic = netdev_priv(dev);
+
+	gdm_lte_hci_send(nic, msg, len);
+}
+
+int gdm_lte_event_init(void)
+{
+	if (lte_event.ref_cnt == 0)
+		lte_event.sock = netlink_init(NETLINK_LTE, gdm_lte_event_rcv);
+
+	if (lte_event.sock) {
+		lte_event.ref_cnt++;
+		return 0;
+	}
+
+	pr_err("event init failed\n");
+	return -1;
+}
+
+void gdm_lte_event_exit(void)
+{
+	if (lte_event.sock && --lte_event.ref_cnt == 0) {
+		netlink_exit(lte_event.sock);
+		lte_event.sock = NULL;
+	}
+}
+
+static u8 find_dev_index(u32 nic_type)
+{
+	u8 index;
+
+	index = (u8)(nic_type & 0x0000000f);
+	if (index > MAX_NIC_TYPE)
+		index = 0;
+
+	return index;
+}
+
+static void gdm_lte_netif_rx(struct net_device *dev, char *buf, int len, int flagged_nic_type)
+{
+	u32 nic_type;
+	struct nic *nic;
+	struct sk_buff *skb;
+	struct ethhdr eth;
+	struct vlan_ethhdr vlan_eth;
+	void *mac_header_data;
+	u32 mac_header_len;
+	char ip_version = 0;
+
+	nic_type = flagged_nic_type & NIC_TYPE_MASK;
+	nic = netdev_priv(dev);
+
+	if (flagged_nic_type & NIC_TYPE_F_DHCP) {
+		/* Change the destination mac address with the one requested the IP */
+		if (flagged_nic_type & NIC_TYPE_F_IPV4) {
+			struct dhcp_packet {
+				u8 op;      /* BOOTREQUEST or BOOTREPLY */
+				u8 htype;   /* hardware address type. 1 = 10mb ethernet */
+				u8 hlen;    /* hardware address length */
+				u8 hops;    /* used by relay agents only */
+				u32 xid;    /* unique id */
+				u16 secs;   /* elapsed since client began acquisition/renewal */
+				u16 flags;  /* only one flag so far: */
+				#define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */
+				u32 ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */
+				u32 yiaddr; /* 'your' (client) IP address */
+				/* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */
+				u32 siaddr_nip;
+				u32 gateway_nip; /* relay agent IP address */
+				u8 chaddr[16];   /* link-layer client hardware address (MAC) */
+				u8 sname[64];    /* server host name (ASCIZ) */
+				u8 file[128];    /* boot file name (ASCIZ) */
+				u32 cookie;      /* fixed first four option bytes (99,130,83,99 dec) */
+			} __packed;
+			void *addr = buf + sizeof(struct iphdr) + sizeof(struct udphdr) + offsetof(struct dhcp_packet, chaddr);
+			memcpy(nic->dest_mac_addr, addr, ETH_ALEN);
+		}
+	}
+
+	if (nic->vlan_id > 0) {
+		mac_header_data = (void *)&vlan_eth;
+		mac_header_len = VLAN_ETH_HLEN;
+	} else {
+		mac_header_data = (void *)&eth;
+		mac_header_len = ETH_HLEN;
+	}
+
+	/* Format the data so that it can be put to skb */
+	memcpy(mac_header_data, nic->dest_mac_addr, ETH_ALEN);
+	memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
+
+	vlan_eth.h_vlan_TCI = htons(nic->vlan_id);
+	vlan_eth.h_vlan_proto = htons(ETH_P_8021Q);
+
+	if (nic_type == NIC_TYPE_ARP) {
+		/* Should be response: Only happens because there was a request from the host */
+		eth.h_proto = htons(ETH_P_ARP);
+		vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_ARP);
+	} else {
+		ip_version = buf[0] >> 4;
+		if (ip_version == IP_VERSION_4) {
+			eth.h_proto = htons(ETH_P_IP);
+			vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IP);
+		} else if (ip_version == IP_VERSION_6) {
+			eth.h_proto = htons(ETH_P_IPV6);
+			vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IPV6);
+		} else {
+			netdev_err(dev, "Unknown IP version %d\n", ip_version);
+			return;
+		}
+	}
+
+	/* Alloc skb and reserve align */
+	skb = dev_alloc_skb(len + mac_header_len + NET_IP_ALIGN);
+	if (!skb)
+		return;
+	skb_reserve(skb, NET_IP_ALIGN);
+
+	memcpy(skb_put(skb, mac_header_len), mac_header_data, mac_header_len);
+	memcpy(skb_put(skb, len), buf, len);
+
+	skb->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
+	skb->dev = dev;
+	skb_reset_mac_header(skb);
+	skb_pull(skb, ETH_HLEN);
+
+	gdm_lte_rx(skb, nic, nic_type);
+}
+
+static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
+{
+	struct net_device *dev;
+	struct multi_sdu *multi_sdu = (struct multi_sdu *)buf;
+	struct sdu *sdu = NULL;
+	u8 *data = (u8 *)multi_sdu->data;
+	u16 i = 0;
+	u16 num_packet;
+	u16 hci_len;
+	u16 cmd_evt;
+	u32 nic_type;
+	u8 index;
+
+	hci_len = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), multi_sdu->len);
+	num_packet = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), multi_sdu->num_packet);
+
+	for (i = 0; i < num_packet; i++) {
+		sdu = (struct sdu *)data;
+
+		cmd_evt = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->cmd_evt);
+		hci_len = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->len);
+		nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->nic_type);
+
+		if (cmd_evt != LTE_RX_SDU) {
+			pr_err("rx sdu wrong hci %04x\n", cmd_evt);
+			return;
+		}
+		if (hci_len < 12) {
+			pr_err("rx sdu invalid len %d\n", hci_len);
+			return;
+		}
+
+		index = find_dev_index(nic_type);
+		if (index < MAX_NIC_TYPE) {
+			dev = phy_dev->dev[index];
+			gdm_lte_netif_rx(dev, (char *)sdu->data, (int)(hci_len-12), nic_type);
+		} else {
+			pr_err("rx sdu invalid nic_type :%x\n", nic_type);
+		}
+
+		data += ((hci_len+3) & 0xfffc) + HCI_HEADER_SIZE;
+	}
+}
+
+static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len)
+{
+	struct nic *nic = netdev_priv(dev);
+	struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf;
+
+	if (pdn_table->activate) {
+		nic->pdn_table.activate = pdn_table->activate;
+		nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->dft_eps_id);
+		nic->pdn_table.nic_type = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->nic_type);
+
+		netdev_info(dev, "pdn activated, nic_type=0x%x\n",
+			    nic->pdn_table.nic_type);
+	} else {
+		memset(&nic->pdn_table, 0x00, sizeof(struct pdn_table));
+		netdev_info(dev, "pdn deactivated\n");
+	}
+}
+
+static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len)
+{
+	struct hci_packet *hci = (struct hci_packet *)buf;
+	struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf;
+	struct sdu *sdu;
+	struct net_device *dev;
+	int ret = 0;
+	u16 cmd_evt;
+	u32 nic_type;
+	u8 index;
+
+	if (!len)
+		return ret;
+
+	cmd_evt = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), hci->cmd_evt);
+
+	dev = phy_dev->dev[0];
+	if (dev == NULL)
+		return 0;
+
+	switch (cmd_evt) {
+	case LTE_RX_SDU:
+		sdu = (struct sdu *)hci->data;
+		nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->nic_type);
+		index = find_dev_index(nic_type);
+		dev = phy_dev->dev[index];
+		gdm_lte_netif_rx(dev, hci->data, len, nic_type);
+		break;
+	case LTE_RX_MULTI_SDU:
+		gdm_lte_multi_sdu_pkt(phy_dev, buf, len);
+		break;
+	case LTE_LINK_ON_OFF_INDICATION:
+		netdev_info(dev, "link %s\n",
+			    ((struct hci_connect_ind *)buf)->connect
+			    ? "on" : "off");
+		break;
+	case LTE_PDN_TABLE_IND:
+		pdn_table = (struct hci_pdn_table_ind *)buf;
+		nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), pdn_table->nic_type);
+		index = find_dev_index(nic_type);
+		dev = phy_dev->dev[index];
+		gdm_lte_pdn_table(dev, buf, len);
+		/* Fall through */
+	default:
+		ret = gdm_lte_event_send(dev, buf, len);
+		break;
+	}
+
+	return ret;
+}
+
+static int rx_complete(void *arg, void *data, int len, int context)
+{
+	struct phy_dev *phy_dev = (struct phy_dev *)arg;
+
+	return gdm_lte_receive_pkt(phy_dev, (char *)data, len);
+}
+
+void start_rx_proc(struct phy_dev *phy_dev)
+{
+	int i;
+
+	for (i = 0; i < MAX_RX_SUBMIT_COUNT; i++)
+		gdm_lte_rcv_with_cb(phy_dev, rx_complete, phy_dev, USB_COMPLETE);
+}
+
+static struct net_device_ops gdm_netdev_ops = {
+	.ndo_open			= gdm_lte_open,
+	.ndo_stop			= gdm_lte_close,
+	.ndo_set_config			= gdm_lte_set_config,
+	.ndo_start_xmit			= gdm_lte_tx,
+	.ndo_get_stats			= gdm_lte_stats,
+};
+
+static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00};
+
+static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest, u8 *mac_address, u8 index)
+{
+	/* Form the dev_addr */
+	if (!mac_address)
+		memcpy(dev_addr, gdm_lte_macaddr, ETH_ALEN);
+	else
+		memcpy(dev_addr, mac_address, ETH_ALEN);
+
+	/* The last byte of the mac address should be less than or equal to 0xFC */
+	dev_addr[ETH_ALEN-1] += index;
+
+	/* Create random nic src and copy the first 3 bytes to be the same as dev_addr */
+	random_ether_addr(nic_src);
+	memcpy(nic_src, dev_addr, 3);
+
+	/* Copy the nic_dest from dev_addr*/
+	memcpy(nic_dest, dev_addr, ETH_ALEN);
+}
+
+static void validate_mac_address(u8 *mac_address)
+{
+	/* if zero address or multicast bit set, restore the default value */
+	if (is_zero_ether_addr(mac_address) || (mac_address[0] & 0x01)) {
+		pr_err("MAC invalid, restoring default\n");
+		memcpy(mac_address, gdm_lte_macaddr, 6);
+	}
+}
+
+int register_lte_device(struct phy_dev *phy_dev, struct device *dev, u8 *mac_address)
+{
+	struct nic *nic;
+	struct net_device *net;
+	char pdn_dev_name[16];
+	int ret = 0;
+	u8 index;
+
+	validate_mac_address(mac_address);
+
+	for (index = 0; index < MAX_NIC_TYPE; index++) {
+		/* Create device name lteXpdnX */
+		sprintf(pdn_dev_name, "lte%%dpdn%d", index);
+
+		/* Allocate netdev */
+		net = alloc_netdev(sizeof(struct nic), pdn_dev_name, ether_setup);
+		if (net == NULL) {
+			pr_err("alloc_netdev failed\n");
+			ret = -ENOMEM;
+			goto err;
+		}
+		net->netdev_ops = &gdm_netdev_ops;
+		net->flags &= ~IFF_MULTICAST;
+		net->mtu = DEFAULT_MTU_SIZE;
+
+		nic = netdev_priv(net);
+		memset(nic, 0, sizeof(struct nic));
+		nic->netdev = net;
+		nic->phy_dev = phy_dev;
+		nic->nic_id = index;
+
+		form_mac_address(
+				net->dev_addr,
+				nic->src_mac_addr,
+				nic->dest_mac_addr,
+				mac_address,
+				index);
+
+		SET_NETDEV_DEV(net, dev);
+		SET_NETDEV_DEVTYPE(net, &wwan_type);
+
+		ret = register_netdev(net);
+		if (ret)
+			goto err;
+
+		netif_carrier_on(net);
+
+		phy_dev->dev[index] = net;
+	}
+
+	return 0;
+
+err:
+	unregister_lte_device(phy_dev);
+
+	return ret;
+}
+
+void unregister_lte_device(struct phy_dev *phy_dev)
+{
+	struct net_device *net;
+	int index;
+
+	for (index = 0; index < MAX_NIC_TYPE; index++) {
+		net = phy_dev->dev[index];
+		if (net == NULL)
+			continue;
+
+		unregister_netdev(net);
+		free_netdev(net);
+	}
+}
diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h
new file mode 100644
index 0000000..9287d31
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_lte.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _GDM_LTE_H_
+#define _GDM_LTE_H_
+
+#include <linux/netdevice.h>
+#include <linux/types.h>
+
+#include "gdm_endian.h"
+
+#define MAX_NIC_TYPE		4
+#define MAX_RX_SUBMIT_COUNT	3
+#define DRIVER_VERSION		"3.7.17.0"
+
+enum TX_ERROR_CODE {
+	TX_NO_ERROR = 0,
+	TX_NO_DEV,
+	TX_NO_SPC,
+	TX_NO_BUFFER,
+};
+
+enum CALLBACK_CONTEXT {
+	KERNEL_THREAD = 0,
+	USB_COMPLETE,
+};
+
+struct pdn_table {
+	u8 activate;
+	u32 dft_eps_id;
+	u32 nic_type;
+} __packed;
+
+struct nic;
+
+struct phy_dev {
+	void	*priv_dev;
+	struct net_device *dev[MAX_NIC_TYPE];
+	int	(*send_hci_func)(void *priv_dev, void *data, int len,
+			void (*cb)(void *cb_data), void *cb_data);
+	int	(*send_sdu_func)(void *priv_dev, void *data, int len,
+			unsigned int dftEpsId, unsigned int epsId,
+			void (*cb)(void *cb_data), void *cb_data,
+			int dev_idx, int nic_type);
+	int	(*rcv_func)(void *priv_dev,
+			int (*cb)(void *cb_data, void *data, int len,
+				  int context),
+			void *cb_data, int context);
+	struct gdm_endian *(*get_endian)(void *priv_dev);
+};
+
+struct nic {
+	struct net_device *netdev;
+	struct phy_dev *phy_dev;
+	struct net_device_stats stats;
+	struct pdn_table pdn_table;
+	u8 dest_mac_addr[ETH_ALEN];
+	u8 src_mac_addr[ETH_ALEN];
+	u32 nic_id;
+	u16 vlan_id;
+};
+
+int gdm_lte_event_init(void);
+void gdm_lte_event_exit(void);
+
+void start_rx_proc(struct phy_dev *phy_dev);
+int register_lte_device(struct phy_dev *phy_dev, struct device *dev,
+			u8 *mac_address);
+void unregister_lte_device(struct phy_dev *phy_dev);
+
+#endif /* _GDM_LTE_H_ */
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
new file mode 100644
index 0000000..b630bab
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_mux.c
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/usb/cdc.h>
+
+#include "gdm_mux.h"
+#include "gdm_tty.h"
+
+struct workqueue_struct *mux_rx_wq;
+
+static u16 packet_type[TTY_MAX_COUNT] = {0xF011, 0xF010};
+
+#define USB_DEVICE_CDC_DATA(vid, pid) \
+	.match_flags = \
+		USB_DEVICE_ID_MATCH_DEVICE |\
+		USB_DEVICE_ID_MATCH_INT_CLASS |\
+		USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
+	.idVendor = vid,\
+	.idProduct = pid,\
+	.bInterfaceClass = USB_CLASS_COMM,\
+	.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM
+
+static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE_CDC_DATA(0x1076, 0x8000) }, /* GCT GDM7240 */
+	{ USB_DEVICE_CDC_DATA(0x1076, 0x8f00) }, /* GCT GDM7243 */
+	{ USB_DEVICE_CDC_DATA(0x1076, 0x9000) }, /* GCT GDM7243 */
+	{ USB_DEVICE_CDC_DATA(0x1d74, 0x2300) }, /* LGIT Phoenix */
+	{}
+};
+
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+int packet_type_to_index(u16 packetType)
+{
+	int i;
+
+	for (i = 0; i < TTY_MAX_COUNT; i++) {
+		if (packet_type[i] == packetType)
+			return i;
+	}
+
+	return -1;
+}
+
+static struct mux_tx *alloc_mux_tx(int len)
+{
+	struct mux_tx *t = NULL;
+
+	t = kzalloc(sizeof(struct mux_tx), GFP_ATOMIC);
+	if (!t)
+		return NULL;
+
+	t->urb = usb_alloc_urb(0, GFP_ATOMIC);
+	t->buf = kmalloc(MUX_TX_MAX_SIZE, GFP_ATOMIC);
+	if (!t->urb || !t->buf) {
+		usb_free_urb(t->urb);
+		kfree(t->buf);
+		kfree(t);
+		return NULL;
+	}
+
+	return t;
+}
+
+static void free_mux_tx(struct mux_tx *t)
+{
+	if (t) {
+		usb_free_urb(t->urb);
+		kfree(t->buf);
+		kfree(t);
+	}
+}
+
+static struct mux_rx *alloc_mux_rx(void)
+{
+	struct mux_rx *r = NULL;
+
+	r = kzalloc(sizeof(struct mux_rx), GFP_ATOMIC);
+	if (!r)
+		return NULL;
+
+	r->urb = usb_alloc_urb(0, GFP_ATOMIC);
+	r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_ATOMIC);
+	if (!r->urb || !r->buf) {
+		usb_free_urb(r->urb);
+		kfree(r->buf);
+		kfree(r);
+		return NULL;
+	}
+
+	return r;
+}
+
+static void free_mux_rx(struct mux_rx *r)
+{
+	if (r) {
+		usb_free_urb(r->urb);
+		kfree(r->buf);
+		kfree(r);
+	}
+}
+
+static struct mux_rx *get_rx_struct(struct rx_cxt *rx)
+{
+	struct mux_rx *r;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rx->free_list_lock, flags);
+
+	if (list_empty(&rx->rx_free_list)) {
+		spin_unlock_irqrestore(&rx->free_list_lock, flags);
+		return NULL;
+	}
+
+	r = list_entry(rx->rx_free_list.prev, struct mux_rx, free_list);
+	list_del(&r->free_list);
+
+	spin_unlock_irqrestore(&rx->free_list_lock, flags);
+
+	return r;
+}
+
+static void put_rx_struct(struct rx_cxt *rx, struct mux_rx *r)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rx->free_list_lock, flags);
+	list_add_tail(&r->free_list, &rx->rx_free_list);
+	spin_unlock_irqrestore(&rx->free_list_lock, flags);
+}
+
+
+static int up_to_host(struct mux_rx *r)
+{
+	struct mux_dev *mux_dev = (struct mux_dev *)r->mux_dev;
+	struct mux_pkt_header *mux_header;
+	unsigned int start_flag;
+	unsigned int payload_size;
+	unsigned short packet_type;
+	int remain;
+	int dummy_cnt;
+	u32 packet_size_sum = r->offset;
+	int index;
+	int ret = TO_HOST_INVALID_PACKET;
+	int len = r->len;
+
+	while (1) {
+		mux_header = (struct mux_pkt_header *)(r->buf + packet_size_sum);
+		start_flag = __le32_to_cpu(mux_header->start_flag);
+		payload_size = __le32_to_cpu(mux_header->payload_size);
+		packet_type = __le16_to_cpu(mux_header->packet_type);
+
+		if (start_flag != START_FLAG) {
+			pr_err("invalid START_FLAG %x\n", start_flag);
+			break;
+		}
+
+		remain = (MUX_HEADER_SIZE + payload_size) % 4;
+		dummy_cnt = remain ? (4-remain) : 0;
+
+		if (len - packet_size_sum <
+			MUX_HEADER_SIZE + payload_size + dummy_cnt) {
+			pr_err("invalid payload : %d %d %04x\n",
+			       payload_size, len, packet_type);
+			break;
+		}
+
+		index = packet_type_to_index(packet_type);
+		if (index < 0) {
+			pr_err("invalid index %d\n", index);
+			break;
+		}
+
+		ret = r->callback(mux_header->data,
+				payload_size,
+				index,
+				mux_dev->minor[index],
+				RECV_PACKET_PROCESS_CONTINUE
+				);
+		if (ret == TO_HOST_BUFFER_REQUEST_FAIL) {
+			r->offset += packet_size_sum;
+			break;
+		}
+
+		packet_size_sum += MUX_HEADER_SIZE + payload_size + dummy_cnt;
+		if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) {
+			ret = r->callback(NULL,
+					0,
+					index,
+					mux_dev->minor[index],
+					RECV_PACKET_PROCESS_COMPLETE
+					);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void do_rx(struct work_struct *work)
+{
+	struct mux_dev *mux_dev =
+		container_of(work, struct mux_dev , work_rx.work);
+	struct mux_rx *r;
+	struct rx_cxt *rx = (struct rx_cxt *)&mux_dev->rx;
+	unsigned long flags;
+	int ret = 0;
+
+	while (1) {
+		spin_lock_irqsave(&rx->to_host_lock, flags);
+		if (list_empty(&rx->to_host_list)) {
+			spin_unlock_irqrestore(&rx->to_host_lock, flags);
+			break;
+		}
+		r = list_entry(rx->to_host_list.next, struct mux_rx, to_host_list);
+		list_del(&r->to_host_list);
+		spin_unlock_irqrestore(&rx->to_host_lock, flags);
+
+		ret = up_to_host(r);
+		if (ret == TO_HOST_BUFFER_REQUEST_FAIL)
+			pr_err("failed to send mux data to host\n");
+		else
+			put_rx_struct(rx, r);
+	}
+}
+
+static void remove_rx_submit_list(struct mux_rx *r, struct rx_cxt *rx)
+{
+	unsigned long flags;
+	struct mux_rx	*r_remove, *r_remove_next;
+
+	spin_lock_irqsave(&rx->submit_list_lock, flags);
+	list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list, rx_submit_list) {
+		if (r == r_remove)
+			list_del(&r->rx_submit_list);
+	}
+	spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+}
+
+static void gdm_mux_rcv_complete(struct urb *urb)
+{
+	struct mux_rx *r = urb->context;
+	struct mux_dev *mux_dev = (struct mux_dev *)r->mux_dev;
+	struct rx_cxt *rx = &mux_dev->rx;
+	unsigned long flags;
+
+	remove_rx_submit_list(r, rx);
+
+	if (urb->status) {
+		if (mux_dev->usb_state == PM_NORMAL)
+			pr_err("%s: urb status error %d\n",
+			       __func__, urb->status);
+		put_rx_struct(rx, r);
+	} else {
+		r->len = r->urb->actual_length;
+		spin_lock_irqsave(&rx->to_host_lock, flags);
+		list_add_tail(&r->to_host_list, &rx->to_host_list);
+		queue_work(mux_rx_wq, &mux_dev->work_rx.work);
+		spin_unlock_irqrestore(&rx->to_host_lock, flags);
+	}
+}
+
+static int gdm_mux_recv(void *priv_dev,
+			int (*cb)(void *data, int len, int tty_index, int minor, int complete)
+			)
+{
+	struct mux_dev *mux_dev = priv_dev;
+	struct usb_device *usbdev = mux_dev->usbdev;
+	struct mux_rx *r;
+	struct rx_cxt *rx = &mux_dev->rx;
+	unsigned long flags;
+	int ret;
+
+	if (!usbdev) {
+		pr_err("device is disconnected\n");
+		return -ENODEV;
+	}
+
+	r = get_rx_struct(rx);
+	if (!r) {
+		pr_err("get_rx_struct fail\n");
+		return -ENOMEM;
+	}
+
+	r->offset = 0;
+	r->mux_dev = (void *)mux_dev;
+	r->callback = cb;
+	mux_dev->rx_cb = cb;
+
+	usb_fill_bulk_urb(r->urb,
+			  usbdev,
+			  usb_rcvbulkpipe(usbdev, 0x86),
+			  r->buf,
+			  MUX_RX_MAX_SIZE,
+			  gdm_mux_rcv_complete,
+			  r);
+
+	spin_lock_irqsave(&rx->submit_list_lock, flags);
+	list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
+	spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+
+	ret = usb_submit_urb(r->urb, GFP_KERNEL);
+
+	if (ret) {
+		spin_lock_irqsave(&rx->submit_list_lock, flags);
+		list_del(&r->rx_submit_list);
+		spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+
+		put_rx_struct(rx, r);
+
+		pr_err("usb_submit_urb ret=%d\n", ret);
+	}
+
+	usb_mark_last_busy(usbdev);
+
+	return ret;
+}
+
+static void gdm_mux_send_complete(struct urb *urb)
+{
+	struct mux_tx *t = urb->context;
+
+	if (urb->status == -ECONNRESET) {
+		pr_info("CONNRESET\n");
+		free_mux_tx(t);
+		return;
+	}
+
+	if (t->callback)
+		t->callback(t->cb_data);
+
+	free_mux_tx(t);
+}
+
+static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index,
+			void (*cb)(void *data), void *cb_data)
+{
+	struct mux_dev *mux_dev = priv_dev;
+	struct usb_device *usbdev = mux_dev->usbdev;
+	struct mux_pkt_header *mux_header;
+	struct mux_tx *t = NULL;
+	static u32 seq_num = 1;
+	int remain;
+	int dummy_cnt;
+	int total_len;
+	int ret;
+	unsigned long flags;
+
+	if (mux_dev->usb_state == PM_SUSPEND) {
+		ret = usb_autopm_get_interface(mux_dev->intf);
+		if (!ret)
+			usb_autopm_put_interface(mux_dev->intf);
+	}
+
+	spin_lock_irqsave(&mux_dev->write_lock, flags);
+
+	remain = (MUX_HEADER_SIZE + len) % 4;
+	dummy_cnt = remain ? (4 - remain) : 0;
+
+	total_len = len + MUX_HEADER_SIZE + dummy_cnt;
+
+	t = alloc_mux_tx(total_len);
+	if (!t) {
+		pr_err("alloc_mux_tx fail\n");
+		spin_unlock_irqrestore(&mux_dev->write_lock, flags);
+		return -ENOMEM;
+	}
+
+	mux_header = (struct mux_pkt_header *)t->buf;
+	mux_header->start_flag = __cpu_to_le32(START_FLAG);
+	mux_header->seq_num = __cpu_to_le32(seq_num++);
+	mux_header->payload_size = __cpu_to_le32((u32)len);
+	mux_header->packet_type = __cpu_to_le16(packet_type[tty_index]);
+
+	memcpy(t->buf+MUX_HEADER_SIZE, data, len);
+	memset(t->buf+MUX_HEADER_SIZE+len, 0, dummy_cnt);
+
+	t->len = total_len;
+	t->callback = cb;
+	t->cb_data = cb_data;
+
+	usb_fill_bulk_urb(t->urb,
+			  usbdev,
+			  usb_sndbulkpipe(usbdev, 5),
+			  t->buf,
+			  total_len,
+			  gdm_mux_send_complete,
+			  t);
+
+	ret = usb_submit_urb(t->urb, GFP_ATOMIC);
+
+	spin_unlock_irqrestore(&mux_dev->write_lock, flags);
+
+	if (ret)
+		pr_err("usb_submit_urb Error: %d\n", ret);
+
+	usb_mark_last_busy(usbdev);
+
+	return ret;
+}
+
+static int gdm_mux_send_control(void *priv_dev, int request, int value, void *buf, int len)
+{
+	struct mux_dev *mux_dev = priv_dev;
+	struct usb_device *usbdev = mux_dev->usbdev;
+	int ret;
+
+	ret = usb_control_msg(usbdev,
+			      usb_sndctrlpipe(usbdev, 0),
+			      request,
+			      USB_RT_ACM,
+			      value,
+			      2,
+			      buf,
+			      len,
+			      5000
+			     );
+
+	if (ret < 0)
+		pr_err("usb_control_msg error: %d\n", ret);
+
+	return ret < 0 ? ret : 0;
+}
+
+static void release_usb(struct mux_dev *mux_dev)
+{
+	struct rx_cxt		*rx = &mux_dev->rx;
+	struct mux_rx		*r, *r_next;
+	unsigned long		flags;
+
+	cancel_delayed_work(&mux_dev->work_rx);
+
+	spin_lock_irqsave(&rx->submit_list_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list) {
+		spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+		usb_kill_urb(r->urb);
+		spin_lock_irqsave(&rx->submit_list_lock, flags);
+	}
+	spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+
+	spin_lock_irqsave(&rx->free_list_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->rx_free_list, free_list) {
+		list_del(&r->free_list);
+		free_mux_rx(r);
+	}
+	spin_unlock_irqrestore(&rx->free_list_lock, flags);
+
+	spin_lock_irqsave(&rx->to_host_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
+		if (r->mux_dev == (void *)mux_dev) {
+			list_del(&r->to_host_list);
+			free_mux_rx(r);
+		}
+	}
+	spin_unlock_irqrestore(&rx->to_host_lock, flags);
+}
+
+
+static int init_usb(struct mux_dev *mux_dev)
+{
+	struct mux_rx *r;
+	struct rx_cxt *rx = &mux_dev->rx;
+	int ret = 0;
+	int i;
+
+	spin_lock_init(&mux_dev->write_lock);
+	INIT_LIST_HEAD(&rx->to_host_list);
+	INIT_LIST_HEAD(&rx->rx_submit_list);
+	INIT_LIST_HEAD(&rx->rx_free_list);
+	spin_lock_init(&rx->to_host_lock);
+	spin_lock_init(&rx->submit_list_lock);
+	spin_lock_init(&rx->free_list_lock);
+
+	for (i = 0; i < MAX_ISSUE_NUM * 2; i++) {
+		r = alloc_mux_rx();
+		if (r == NULL) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		list_add(&r->free_list, &rx->rx_free_list);
+	}
+
+	INIT_DELAYED_WORK(&mux_dev->work_rx, do_rx);
+
+	return ret;
+}
+
+static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct mux_dev *mux_dev = NULL;
+	struct tty_dev *tty_dev = NULL;
+	u16 idVendor, idProduct;
+	int bInterfaceNumber;
+	int ret = 0;
+	int i;
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
+
+	idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
+	idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
+
+	pr_info("mux vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
+
+	if (bInterfaceNumber != 2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	mux_dev = kzalloc(sizeof(struct mux_dev), GFP_KERNEL);
+	if (!mux_dev) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	tty_dev = kzalloc(sizeof(struct tty_dev), GFP_KERNEL);
+	if (!tty_dev) {
+		kfree(mux_dev);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mux_dev->usbdev = usbdev;
+	mux_dev->control_intf = intf;
+
+	ret = init_usb(mux_dev);
+	if (ret < 0)
+		goto out;
+
+	tty_dev->priv_dev = (void *)mux_dev;
+	tty_dev->send_func = gdm_mux_send;
+	tty_dev->recv_func = gdm_mux_recv;
+	tty_dev->send_control = gdm_mux_send_control;
+
+	if (register_lte_tty_device(tty_dev, &intf->dev) < 0) {
+		unregister_lte_tty_device(tty_dev);
+		mux_dev = tty_dev->priv_dev;
+
+		ret = -1;
+		goto out;
+	}
+	for (i = 0; i < TTY_MAX_COUNT; i++)
+		mux_dev->minor[i] = tty_dev->minor[i];
+
+out:
+	if (ret < 0) {
+		kfree(tty_dev);
+		if (mux_dev) {
+			release_usb(mux_dev);
+			kfree(mux_dev);
+		}
+	} else {
+		mux_dev->intf = intf;
+		mux_dev->usb_state = PM_NORMAL;
+	}
+
+	usb_get_dev(usbdev);
+	usb_set_intfdata(intf, tty_dev);
+
+	return ret;
+}
+
+static void gdm_mux_disconnect(struct usb_interface *intf)
+{
+	struct tty_dev *tty_dev;
+	struct mux_dev *mux_dev;
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+
+	tty_dev = usb_get_intfdata(intf);
+
+	mux_dev = tty_dev->priv_dev;
+
+	release_usb(mux_dev);
+	unregister_lte_tty_device(tty_dev);
+
+	kfree(mux_dev);
+	kfree(tty_dev);
+
+	usb_put_dev(usbdev);
+}
+
+static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg)
+{
+	struct tty_dev *tty_dev;
+	struct mux_dev *mux_dev;
+	struct rx_cxt *rx;
+	struct mux_rx *r, *r_next;
+	unsigned long flags;
+
+	tty_dev = usb_get_intfdata(intf);
+	mux_dev = tty_dev->priv_dev;
+	rx = &mux_dev->rx;
+
+	if (mux_dev->usb_state != PM_NORMAL) {
+		pr_err("usb suspend - invalid state\n");
+		return -1;
+	}
+
+	mux_dev->usb_state = PM_SUSPEND;
+
+
+	spin_lock_irqsave(&rx->submit_list_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list) {
+		spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+		usb_kill_urb(r->urb);
+		spin_lock_irqsave(&rx->submit_list_lock, flags);
+	}
+	spin_unlock_irqrestore(&rx->submit_list_lock, flags);
+
+	return 0;
+}
+
+static int gdm_mux_resume(struct usb_interface *intf)
+{
+	struct tty_dev *tty_dev;
+	struct mux_dev *mux_dev;
+	u8 i;
+
+	tty_dev = usb_get_intfdata(intf);
+	mux_dev = tty_dev->priv_dev;
+
+	if (mux_dev->usb_state != PM_SUSPEND) {
+		pr_err("usb resume - invalid state\n");
+		return -1;
+	}
+
+	mux_dev->usb_state = PM_NORMAL;
+
+	for (i = 0; i < MAX_ISSUE_NUM; i++)
+		gdm_mux_recv(mux_dev, mux_dev->rx_cb);
+
+	return 0;
+}
+
+static struct usb_driver gdm_mux_driver = {
+	.name = "gdm_mux",
+	.probe = gdm_mux_probe,
+	.disconnect = gdm_mux_disconnect,
+	.id_table = id_table,
+	.supports_autosuspend = 1,
+	.suspend = gdm_mux_suspend,
+	.resume = gdm_mux_resume,
+	.reset_resume = gdm_mux_resume,
+};
+
+static int __init gdm_usb_mux_init(void)
+{
+
+	mux_rx_wq = create_workqueue("mux_rx_wq");
+	if (mux_rx_wq == NULL) {
+		pr_err("work queue create fail\n");
+		return -1;
+	}
+
+	register_lte_tty_driver();
+
+	return usb_register(&gdm_mux_driver);
+}
+
+static void __exit gdm_usb_mux_exit(void)
+{
+	unregister_lte_tty_driver();
+
+	if (mux_rx_wq) {
+		flush_workqueue(mux_rx_wq);
+		destroy_workqueue(mux_rx_wq);
+	}
+
+	usb_deregister(&gdm_mux_driver);
+}
+
+module_init(gdm_usb_mux_init);
+module_exit(gdm_usb_mux_exit);
+
+MODULE_DESCRIPTION("GCT LTE TTY Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h
new file mode 100644
index 0000000..d5b0b54
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_mux.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _GDM_MUX_H_
+#define _GDM_MUX_H_
+
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/list.h>
+
+#define PM_NORMAL 0
+#define PM_SUSPEND 1
+
+#define USB_RT_ACM          (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
+
+#define START_FLAG 0xA512485A
+#define MUX_HEADER_SIZE 14
+#define MUX_TX_MAX_SIZE (1024*10)
+#define MUX_RX_MAX_SIZE (1024*30)
+#define AT_PKT_TYPE 0xF011
+#define DM_PKT_TYPE 0xF010
+
+#define RETRY_TIMER 30 /* msec */
+
+struct mux_pkt_header {
+	unsigned int start_flag;
+	unsigned int seq_num;
+	unsigned int payload_size;
+	unsigned short packet_type;
+	unsigned char data[0];
+};
+
+struct mux_tx {
+	struct urb *urb;
+	u8 *buf;
+	int  len;
+	void (*callback)(void *cb_data);
+	void *cb_data;
+};
+
+struct mux_rx {
+	struct list_head free_list;
+	struct list_head rx_submit_list;
+	struct list_head to_host_list;
+	struct urb *urb;
+	u8 *buf;
+	void *mux_dev;
+	u32 offset;
+	u32 len;
+	int (*callback)(void *data, int len, int tty_index, int minor,
+			int complete);
+};
+
+struct rx_cxt {
+	struct list_head to_host_list;
+	struct list_head rx_submit_list;
+	struct list_head rx_free_list;
+	spinlock_t to_host_lock;
+	spinlock_t submit_list_lock;
+	spinlock_t free_list_lock;
+};
+
+struct mux_dev {
+	struct usb_device *usbdev;
+	struct usb_interface *control_intf;
+	struct usb_interface *data_intf;
+	struct rx_cxt	rx;
+	struct delayed_work work_rx;
+	struct usb_interface *intf;
+	int usb_state;
+	int (*rx_cb)(void *data, int len, int tty_index, int minor,
+		     int complete);
+	spinlock_t write_lock;
+	u8 minor[2];
+};
+
+#endif /* _GDM_MUX_H_ */
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
new file mode 100644
index 0000000..912022b
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.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/slab.h>
+#include <linux/usb/cdc.h>
+#include <linux/serial.h>
+#include "gdm_tty.h"
+
+#define GDM_TTY_MAJOR 0
+#define GDM_TTY_MINOR 32
+
+#define ACM_CTRL_DTR 0x01
+#define ACM_CTRL_RTS 0x02
+#define ACM_CTRL_DSR 0x02
+#define ACM_CTRL_RI  0x08
+#define ACM_CTRL_DCD 0x01
+
+#define WRITE_SIZE 2048
+
+#define MUX_TX_MAX_SIZE 2048
+
+#define gdm_tty_send(n, d, l, i, c, b) (\
+	n->tty_dev->send_func(n->tty_dev->priv_dev, d, l, i, c, b))
+#define gdm_tty_recv(n, c) (\
+	n->tty_dev->recv_func(n->tty_dev->priv_dev, c))
+#define gdm_tty_send_control(n, r, v, d, l) (\
+	n->tty_dev->send_control(n->tty_dev->priv_dev, r, v, d, l))
+
+#define acm_set_comm_feature(n, v)	\
+	gdm_tty_send_control(n, 0x02, v, NULL, 0)
+
+#define GDM_TTY_READY(tty_str) (tty_str && tty_str->tty_dev && tty_str->port.count)
+
+struct tty_driver *g_tty_drv[TTY_MAX_COUNT] = {NULL, };
+struct tty_str *g_tty_str[TTY_MAX_COUNT][GDM_TTY_MINOR] = {{NULL, }, };
+
+static char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"};
+static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"};
+
+static DEFINE_MUTEX(open_mutex);
+
+static struct tty_port_operations gdm_tty_port_ops = {
+};
+
+static int gdm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct tty_str *tty_str = NULL;
+	int i;
+	int ret = 0;
+
+	mutex_lock(&open_mutex);
+
+	for (i = 0; i < TTY_MAX_COUNT; i++) {
+		if (!strcmp(tty->driver->driver_name, DRIVER_STRING[i])) {
+			tty_str = g_tty_str[i][tty->index];
+			break;
+		}
+	}
+
+	if (!tty_str) {
+		pr_info("no tty device\n");
+		mutex_unlock(&open_mutex);
+		return -ENODEV;
+	}
+
+	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
+
+	tty->driver_data = tty_str;
+	tty_port_tty_set(&tty_str->port, tty);
+	tty_str->port.count++;
+	set_bit(ASYNCB_INITIALIZED, &tty_str->port.flags);
+	ret = tty_port_block_til_ready(&tty_str->port, tty, filp);
+
+	mutex_unlock(&open_mutex);
+
+	return ret;
+}
+
+static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct tty_str *tty_str = tty->driver_data;
+	int i;
+
+	if (!tty_str) {
+		pr_info("tty device already closed\n");
+		return;
+	}
+
+	if (tty_str->port.count != 0) {
+		tty_port_close_start(&tty_str->port, tty, filp);
+		tty_port_close_end(&tty_str->port, tty);
+
+		if (tty_str->port.count == 0)
+			tty_port_tty_set(&tty_str->port, NULL);
+			tty_str->port.tty = NULL;
+	}
+
+	if (!tty_str->tty_dev) {
+		for (i = 0; i < TTY_MAX_COUNT; i++) {
+			if (!strcmp(tty->driver->driver_name, DRIVER_STRING[i]))
+				break;
+		}
+
+		if (i < TTY_MAX_COUNT) {
+			tty_unregister_device(g_tty_drv[i], tty->index);
+			tty_port_tty_set(&tty_str->port, NULL);
+			kfree(tty_str);
+			g_tty_str[i][tty->index] = NULL;
+		}
+	}
+}
+
+static int gdm_tty_recv_complete(void *data, int len, int index, int minor, int complete)
+{
+	struct tty_str *tty_str = g_tty_str[index][minor];
+	struct tty_port *tty_port;
+
+	if (!GDM_TTY_READY(tty_str)) {
+		if (complete == RECV_PACKET_PROCESS_COMPLETE)
+			gdm_tty_recv(tty_str, gdm_tty_recv_complete);
+		return TO_HOST_PORT_CLOSE;
+	}
+
+	if (!data || !len)
+		goto complete_routine;
+
+	tty_port = &tty_str->port;
+
+	if (tty_buffer_request_room(tty_port, len) == len) {
+		tty_insert_flip_string(tty_port, data, len);
+		tty_flip_buffer_push(tty_port);
+	} else {
+		return TO_HOST_BUFFER_REQUEST_FAIL;
+	}
+
+complete_routine:
+	if (complete == RECV_PACKET_PROCESS_COMPLETE)
+		gdm_tty_recv(tty_str, gdm_tty_recv_complete);
+
+	return 0;
+}
+
+static void gdm_tty_send_complete(void *arg)
+{
+	struct tty_str *tty_str = (struct tty_str *)arg;
+	struct tty_struct *tty;
+
+	if (!GDM_TTY_READY(tty_str))
+		return;
+
+	tty = tty_port_tty_get(&tty_str->port);
+	tty_wakeup(tty);
+	tty_kref_put(tty);
+}
+
+static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, int len)
+{
+	struct tty_str *tty_str = tty->driver_data;
+	int remain = len;
+	int sent_len = 0;
+	int sending_len = 0;
+
+	if (!GDM_TTY_READY(tty_str))
+		return -ENODEV;
+
+	if (!len)
+		return 0;
+
+	while (1) {
+		sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE : remain;
+		gdm_tty_send(tty_str,
+			     (void *)(buf+sent_len),
+			     sending_len,
+			     tty_str->tty_drv_index,
+			     gdm_tty_send_complete,
+			     tty_str
+			    );
+		sent_len += sending_len;
+		remain -= sending_len;
+		if (remain <= 0)
+			break;
+	}
+
+	return len;
+}
+
+static int gdm_tty_write_room(struct tty_struct *tty)
+{
+	struct tty_str *tty_str = tty->driver_data;
+
+	if (!GDM_TTY_READY(tty_str))
+		return -ENODEV;
+
+	return WRITE_SIZE;
+}
+
+static int gdm_tty_tiocmget(struct tty_struct *tty)
+{
+	struct tty_str *tty_str = tty->driver_data;
+
+	if (!GDM_TTY_READY(tty_str))
+		return -ENODEV;
+
+	return (0 & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
+	       (0 & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
+	       (0 & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
+	       (0 & ACM_CTRL_RI  ? TIOCM_RI  : 0) |
+	       (0 & ACM_CTRL_DCD ? TIOCM_CD  : 0) |
+	       TIOCM_CTS;
+}
+
+static int gdm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
+{
+	struct tty_str *tty_str = tty->driver_data;
+
+	if (!GDM_TTY_READY(tty_str))
+		return -ENODEV;
+
+	return 1;
+}
+
+int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev)
+{
+	struct tty_str *tty_str;
+	int i, j;
+
+	for (i = 0; i < TTY_MAX_COUNT; i++) {
+		for (j = 0; j < GDM_TTY_MINOR; j++) {
+			if (!g_tty_str[i][j])
+				break;
+		}
+
+		if (j == GDM_TTY_MINOR) {
+			tty_dev->minor[i] = j;
+			return -1;
+		}
+
+		tty_str = kmalloc(sizeof(struct tty_str), GFP_KERNEL);
+		if (!tty_str)
+			return -ENOMEM;
+
+		g_tty_str[i][j] = tty_str;
+
+		tty_str->tty_dev = tty_dev;
+		tty_str->tty_drv_index = i;
+		tty_dev->minor[i] = j;
+		tty_port_init(&tty_str->port);
+		tty_str->port.ops = &gdm_tty_port_ops;
+
+		if (strcmp(DEVICE_STRING[i], "GCT-ATC") != 0)
+			dev = NULL;
+		tty_register_device(g_tty_drv[i], j, dev);
+	}
+
+	acm_set_comm_feature(tty_str, 1);
+
+	for (i = 0; i < MAX_ISSUE_NUM; i++)
+		gdm_tty_recv(tty_str, gdm_tty_recv_complete);
+
+	return 0;
+}
+
+void unregister_lte_tty_device(struct tty_dev *tty_dev)
+{
+	struct tty_str *tty_str;
+	int i;
+
+	for (i = 0; i < TTY_MAX_COUNT; i++) {
+		if (tty_dev->minor[i] >= GDM_TTY_MINOR)
+			continue;
+
+		tty_str = g_tty_str[i][tty_dev->minor[i]];
+		if (!tty_str)
+			continue;
+
+		tty_str->tty_dev = NULL;
+
+		if (!tty_str->port.count) {
+			tty_unregister_device(g_tty_drv[i], tty_dev->minor[i]);
+			tty_port_tty_set(&tty_str->port, NULL);
+			kfree(tty_str);
+			g_tty_str[i][tty_dev->minor[i]] = NULL;
+		}
+	}
+}
+
+static void gdm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old)
+{
+	return;
+}
+
+static const struct tty_operations gdm_tty_ops = {
+	.open = gdm_tty_open,
+	.close = gdm_tty_close,
+	.write = gdm_tty_write,
+	.write_room = gdm_tty_write_room,
+	.tiocmget = gdm_tty_tiocmget,
+	.tiocmset = gdm_tty_tiocmset,
+	.set_termios = gdm_tty_set_termios,
+};
+
+int register_lte_tty_driver(void)
+{
+	struct tty_driver *tty_driver = NULL;
+	int i;
+	int ret;
+
+	for (i = 0; i < TTY_MAX_COUNT; i++) {
+		tty_driver = alloc_tty_driver(GDM_TTY_MINOR);
+		if (!tty_driver) {
+			pr_err("alloc_tty_driver fail\n");
+			return -ENOMEM;
+		}
+
+		tty_driver->owner = THIS_MODULE;
+		tty_driver->driver_name = DRIVER_STRING[i];
+		tty_driver->name = DEVICE_STRING[i];
+		tty_driver->major = GDM_TTY_MAJOR;
+		tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+		tty_driver->subtype = SERIAL_TYPE_NORMAL;
+		tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+		tty_driver->init_termios = tty_std_termios;
+		tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
+		tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
+		tty_set_operations(tty_driver, &gdm_tty_ops);
+
+		ret = tty_register_driver(tty_driver);
+
+		g_tty_drv[i] = tty_driver;
+	}
+
+	return ret;
+}
+
+void unregister_lte_tty_driver(void)
+{
+	struct tty_driver *tty_driver;
+	int i;
+
+	for (i = 0; i < TTY_MAX_COUNT; i++) {
+		tty_driver = g_tty_drv[i];
+		if (tty_driver) {
+			tty_unregister_driver(tty_driver);
+			put_tty_driver(tty_driver);
+		}
+	}
+}
diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h
new file mode 100644
index 0000000..a75be1d
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_tty.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _GDM_TTY_H_
+#define _GDM_TTY_H_
+
+#include <linux/types.h>
+#include <linux/tty.h>
+
+
+#define TTY_MAX_COUNT		2
+
+#define MAX_ISSUE_NUM 3
+
+enum TO_HOST_RESULT {
+	TO_HOST_BUFFER_REQUEST_FAIL = 1,
+	TO_HOST_PORT_CLOSE = 2,
+	TO_HOST_INVALID_PACKET = 3,
+};
+
+enum RECV_PACKET_PROCESS {
+	RECV_PACKET_PROCESS_COMPLETE = 0,
+	RECV_PACKET_PROCESS_CONTINUE = 1,
+};
+
+struct tty_dev {
+	void *priv_dev;
+	int (*send_func)(void *priv_dev, void *data, int len, int tty_index,
+			void (*cb)(void *cb_data), void *cb_data);
+	int (*recv_func)(void *priv_dev, int (*cb)(void *data, int len,
+			 int tty_index, int minor, int complete));
+	int (*send_control)(void *priv_dev, int request, int value, void *data,
+			    int len);
+	u8 minor[2];
+};
+
+struct tty_str {
+	struct tty_dev *tty_dev;
+	int tty_drv_index;
+	struct tty_port port;
+};
+
+int register_lte_tty_driver(void);
+void unregister_lte_tty_driver(void);
+int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev);
+void unregister_lte_tty_device(struct tty_dev *tty_dev);
+
+#endif /* _GDM_USB_H_ */
+
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
new file mode 100644
index 0000000..bdc9637
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_usb.c
@@ -0,0 +1,1049 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/usb/cdc.h>
+#include <linux/wait.h>
+#include <linux/if_ether.h>
+#include <linux/pm_runtime.h>
+
+#include "gdm_usb.h"
+#include "gdm_lte.h"
+#include "hci.h"
+#include "hci_packet.h"
+#include "gdm_endian.h"
+
+#define USB_DEVICE_CDC_DATA(vid, pid) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
+	.idVendor = vid,\
+	.idProduct = pid,\
+	.bInterfaceClass = USB_CLASS_COMM,\
+	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET
+
+#define USB_DEVICE_MASS_DATA(vid, pid) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,\
+	.idVendor = vid,\
+	.idProduct = pid,\
+	.bInterfaceSubClass = USB_SC_SCSI, \
+	.bInterfaceClass = USB_CLASS_MASS_STORAGE,\
+	.bInterfaceProtocol = USB_PR_BULK
+
+static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7240) }, /* GCT GDM7240 */
+	{ USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7243) }, /* GCT GDM7243 */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct workqueue_struct *usb_tx_wq;
+static struct workqueue_struct *usb_rx_wq;
+
+static void do_tx(struct work_struct *work);
+static void do_rx(struct work_struct *work);
+
+static int gdm_usb_recv(void *priv_dev,
+			int (*cb)(void *cb_data, void *data, int len, int context),
+			void *cb_data,
+			int context);
+
+static int request_mac_address(struct lte_udev *udev)
+{
+	u8 buf[16] = {0,};
+	struct hci_packet *hci = (struct hci_packet *)buf;
+	struct usb_device *usbdev = udev->usbdev;
+	int actual;
+	int ret = -1;
+
+	hci->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_GET_INFORMATION);
+	hci->len = gdm_cpu_to_dev16(&udev->gdm_ed, 1);
+	hci->data[0] = MAC_ADDRESS;
+
+	ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), buf, 5,
+		     &actual, 1000);
+
+	udev->request_mac_addr = 1;
+
+	return ret;
+}
+
+static struct usb_tx *alloc_tx_struct(int len)
+{
+	struct usb_tx *t = NULL;
+	int ret = 0;
+
+	t = kmalloc(sizeof(struct usb_tx), GFP_ATOMIC);
+	if (!t) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	memset(t, 0, sizeof(struct usb_tx));
+
+	t->urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!(len % 512))
+		len++;
+
+	t->buf = kmalloc(len, GFP_ATOMIC);
+	if (!t->urb || !t->buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+out:
+	if (ret < 0) {
+		if (t) {
+			usb_free_urb(t->urb);
+			kfree(t->buf);
+			kfree(t);
+		}
+		return NULL;
+	}
+
+	return t;
+}
+
+static struct usb_tx_sdu *alloc_tx_sdu_struct(void)
+{
+	struct usb_tx_sdu *t_sdu = NULL;
+	int ret = 0;
+
+
+	t_sdu = kmalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC);
+	if (!t_sdu) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	memset(t_sdu, 0, sizeof(struct usb_tx_sdu));
+
+	t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_ATOMIC);
+	if (!t_sdu->buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+out:
+
+	if (ret < 0) {
+		if (t_sdu) {
+			kfree(t_sdu->buf);
+			kfree(t_sdu);
+		}
+		return NULL;
+	}
+
+	return t_sdu;
+}
+
+static void free_tx_struct(struct usb_tx *t)
+{
+	if (t) {
+		usb_free_urb(t->urb);
+		kfree(t->buf);
+		kfree(t);
+	}
+}
+
+static void free_tx_sdu_struct(struct usb_tx_sdu *t_sdu)
+{
+	if (t_sdu) {
+		kfree(t_sdu->buf);
+		kfree(t_sdu);
+	}
+}
+
+static struct usb_tx_sdu *get_tx_sdu_struct(struct tx_cxt *tx, int *no_spc)
+{
+	struct usb_tx_sdu *t_sdu;
+
+	if (list_empty(&tx->free_list))
+		return NULL;
+
+	t_sdu = list_entry(tx->free_list.next, struct usb_tx_sdu, list);
+	list_del(&t_sdu->list);
+
+	tx->avail_count--;
+
+	*no_spc = list_empty(&tx->free_list) ? 1 : 0;
+
+	return t_sdu;
+}
+
+static void put_tx_struct(struct tx_cxt *tx, struct usb_tx_sdu *t_sdu)
+{
+	list_add_tail(&t_sdu->list, &tx->free_list);
+	tx->avail_count++;
+}
+
+static struct usb_rx *alloc_rx_struct(void)
+{
+	struct usb_rx *r = NULL;
+	int ret = 0;
+
+	r = kmalloc(sizeof(struct usb_rx), GFP_ATOMIC);
+	if (!r) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	r->urb = usb_alloc_urb(0, GFP_ATOMIC);
+	r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC);
+	if (!r->urb || !r->buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+out:
+
+	if (ret < 0) {
+		if (r) {
+			usb_free_urb(r->urb);
+			kfree(r->buf);
+			kfree(r);
+		}
+		return NULL;
+	}
+
+	return r;
+}
+
+static void free_rx_struct(struct usb_rx *r)
+{
+	if (r) {
+		usb_free_urb(r->urb);
+		kfree(r->buf);
+		kfree(r);
+	}
+}
+
+static struct usb_rx *get_rx_struct(struct rx_cxt *rx, int *no_spc)
+{
+	struct usb_rx *r;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rx->rx_lock, flags);
+
+	if (list_empty(&rx->free_list)) {
+		spin_unlock_irqrestore(&rx->rx_lock, flags);
+		return NULL;
+	}
+
+	r = list_entry(rx->free_list.next, struct usb_rx, free_list);
+	list_del(&r->free_list);
+
+	rx->avail_count--;
+
+	*no_spc = list_empty(&rx->free_list) ? 1 : 0;
+
+	spin_unlock_irqrestore(&rx->rx_lock, flags);
+
+	return r;
+}
+
+static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rx->rx_lock, flags);
+
+	list_add_tail(&r->free_list, &rx->free_list);
+	rx->avail_count++;
+
+	spin_unlock_irqrestore(&rx->rx_lock, flags);
+}
+
+static void release_usb(struct lte_udev *udev)
+{
+	struct rx_cxt	*rx = &udev->rx;
+	struct tx_cxt	*tx = &udev->tx;
+	struct usb_tx	*t, *t_next;
+	struct usb_rx	*r, *r_next;
+	struct usb_tx_sdu	*t_sdu, *t_sdu_next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx->lock, flags);
+	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list)
+	{
+		list_del(&t_sdu->list);
+		free_tx_sdu_struct(t_sdu);
+	}
+
+	list_for_each_entry_safe(t, t_next, &tx->hci_list, list)
+	{
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list)
+	{
+		list_del(&t_sdu->list);
+		free_tx_sdu_struct(t_sdu);
+	}
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	spin_lock_irqsave(&rx->submit_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list)
+	{
+		spin_unlock_irqrestore(&rx->submit_lock, flags);
+		usb_kill_urb(r->urb);
+		spin_lock_irqsave(&rx->submit_lock, flags);
+	}
+	spin_unlock_irqrestore(&rx->submit_lock, flags);
+
+	spin_lock_irqsave(&rx->rx_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->free_list, free_list)
+	{
+		list_del(&r->free_list);
+		free_rx_struct(r);
+	}
+	spin_unlock_irqrestore(&rx->rx_lock, flags);
+
+	spin_lock_irqsave(&rx->to_host_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list)
+	{
+		if (r->index == (void *)udev) {
+			list_del(&r->to_host_list);
+			free_rx_struct(r);
+		}
+	}
+	spin_unlock_irqrestore(&rx->to_host_lock, flags);
+}
+
+static int init_usb(struct lte_udev *udev)
+{
+	int ret = 0;
+	int i;
+	struct tx_cxt *tx = &udev->tx;
+	struct rx_cxt *rx = &udev->rx;
+	struct usb_tx_sdu *t_sdu = NULL;
+	struct usb_rx *r = NULL;
+
+	udev->send_complete = 1;
+	udev->tx_stop = 0;
+	udev->request_mac_addr = 0;
+	udev->usb_state = PM_NORMAL;
+
+	INIT_LIST_HEAD(&tx->sdu_list);
+	INIT_LIST_HEAD(&tx->hci_list);
+	INIT_LIST_HEAD(&tx->free_list);
+	INIT_LIST_HEAD(&rx->rx_submit_list);
+	INIT_LIST_HEAD(&rx->free_list);
+	INIT_LIST_HEAD(&rx->to_host_list);
+	spin_lock_init(&tx->lock);
+	spin_lock_init(&rx->rx_lock);
+	spin_lock_init(&rx->submit_lock);
+	spin_lock_init(&rx->to_host_lock);
+
+	tx->avail_count = 0;
+	rx->avail_count = 0;
+
+	udev->rx_cb = NULL;
+
+	for (i = 0; i < MAX_NUM_SDU_BUF; i++) {
+		t_sdu = alloc_tx_sdu_struct();
+		if (t_sdu == NULL) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		list_add(&t_sdu->list, &tx->free_list);
+		tx->avail_count++;
+	}
+
+	for (i = 0; i < MAX_RX_SUBMIT_COUNT*2; i++) {
+		r = alloc_rx_struct();
+		if (r == NULL) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		list_add(&r->free_list, &rx->free_list);
+		rx->avail_count++;
+	}
+	INIT_DELAYED_WORK(&udev->work_tx, do_tx);
+	INIT_DELAYED_WORK(&udev->work_rx, do_rx);
+	return 0;
+fail:
+	return ret;
+}
+
+static int set_mac_address(u8 *data, void *arg)
+{
+	struct phy_dev *phy_dev = (struct phy_dev *)arg;
+	struct lte_udev *udev = phy_dev->priv_dev;
+	struct tlv *tlv = (struct tlv *)data;
+	u8 mac_address[ETH_ALEN] = {0, };
+
+	if (tlv->type == MAC_ADDRESS && udev->request_mac_addr) {
+		memcpy(mac_address, tlv->data, tlv->len);
+
+		if (register_lte_device(phy_dev, &udev->intf->dev, mac_address) < 0)
+			pr_err("register lte device failed\n");
+
+		udev->request_mac_addr = 0;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static void do_rx(struct work_struct *work)
+{
+	struct lte_udev *udev = container_of(work, struct lte_udev, work_rx.work);
+	struct rx_cxt *rx = &udev->rx;
+	struct usb_rx *r;
+	struct hci_packet *hci;
+	struct phy_dev *phy_dev;
+	u16 cmd_evt;
+	int ret;
+	unsigned long flags;
+
+	while (1) {
+		spin_lock_irqsave(&rx->to_host_lock, flags);
+		if (list_empty(&rx->to_host_list)) {
+			spin_unlock_irqrestore(&rx->to_host_lock, flags);
+			break;
+		}
+		r = list_entry(rx->to_host_list.next, struct usb_rx, to_host_list);
+		list_del(&r->to_host_list);
+		spin_unlock_irqrestore(&rx->to_host_lock, flags);
+
+		phy_dev = (struct phy_dev *)r->cb_data;
+		udev = (struct lte_udev *)phy_dev->priv_dev;
+		hci = (struct hci_packet *)r->buf;
+		cmd_evt = gdm_dev16_to_cpu(&udev->gdm_ed, hci->cmd_evt);
+
+		switch (cmd_evt) {
+		case LTE_GET_INFORMATION_RESULT:
+			if (set_mac_address(hci->data, r->cb_data) == 0) {
+				ret = r->callback(r->cb_data,
+						  r->buf,
+						  r->urb->actual_length,
+						  KERNEL_THREAD);
+			}
+			break;
+
+		default:
+			if (r->callback) {
+				ret = r->callback(r->cb_data,
+						  r->buf,
+						  r->urb->actual_length,
+						  KERNEL_THREAD);
+
+				if (ret == -EAGAIN)
+					pr_err("failed to send received data\n");
+			}
+			break;
+		}
+
+		put_rx_struct(rx, r);
+
+		gdm_usb_recv(udev,
+			     r->callback,
+			     r->cb_data,
+			     USB_COMPLETE);
+	}
+}
+
+static void remove_rx_submit_list(struct usb_rx *r, struct rx_cxt *rx)
+{
+	unsigned long flags;
+	struct usb_rx	*r_remove, *r_remove_next;
+
+	spin_lock_irqsave(&rx->submit_lock, flags);
+	list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list, rx_submit_list)
+	{
+		if (r == r_remove) {
+			list_del(&r->rx_submit_list);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&rx->submit_lock, flags);
+}
+
+static void gdm_usb_rcv_complete(struct urb *urb)
+{
+	struct usb_rx *r = urb->context;
+	struct rx_cxt *rx = r->rx;
+	unsigned long flags;
+	struct lte_udev *udev = container_of(r->rx, struct lte_udev, rx);
+	struct usb_device *usbdev = udev->usbdev;
+
+	remove_rx_submit_list(r, rx);
+
+	if (!urb->status && r->callback) {
+		spin_lock_irqsave(&rx->to_host_lock, flags);
+		list_add_tail(&r->to_host_list, &rx->to_host_list);
+		queue_work(usb_rx_wq, &udev->work_rx.work);
+		spin_unlock_irqrestore(&rx->to_host_lock, flags);
+	} else {
+		if (urb->status && udev->usb_state == PM_NORMAL)
+			pr_err("%s: urb status error %d\n",
+			       __func__, urb->status);
+
+		put_rx_struct(rx, r);
+	}
+
+	usb_mark_last_busy(usbdev);
+}
+
+static int gdm_usb_recv(void *priv_dev,
+			int (*cb)(void *cb_data, void *data, int len, int context),
+			void *cb_data,
+			int context)
+{
+	struct lte_udev *udev = priv_dev;
+	struct usb_device *usbdev = udev->usbdev;
+	struct rx_cxt *rx = &udev->rx;
+	struct usb_rx *r;
+	int no_spc;
+	int ret;
+	unsigned long flags;
+
+	if (!udev->usbdev) {
+		pr_err("invalid device\n");
+		return -ENODEV;
+	}
+
+	r = get_rx_struct(rx, &no_spc);
+	if (!r) {
+		pr_err("Out of Memory\n");
+		return -ENOMEM;
+	}
+
+	udev->rx_cb = cb;
+	r->callback = cb;
+	r->cb_data = cb_data;
+	r->index = (void *)udev;
+	r->rx = rx;
+
+	usb_fill_bulk_urb(r->urb,
+			  usbdev,
+			  usb_rcvbulkpipe(usbdev, 0x83),
+			  r->buf,
+			  RX_BUF_SIZE,
+			  gdm_usb_rcv_complete,
+			  r);
+
+	spin_lock_irqsave(&rx->submit_lock, flags);
+	list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
+	spin_unlock_irqrestore(&rx->submit_lock, flags);
+
+	if (context == KERNEL_THREAD)
+		ret = usb_submit_urb(r->urb, GFP_KERNEL);
+	else
+		ret = usb_submit_urb(r->urb, GFP_ATOMIC);
+
+	if (ret) {
+		spin_lock_irqsave(&rx->submit_lock, flags);
+		list_del(&r->rx_submit_list);
+		spin_unlock_irqrestore(&rx->submit_lock, flags);
+
+		pr_err("usb_submit_urb failed (%p)\n", r);
+		put_rx_struct(rx, r);
+	}
+
+	return ret;
+}
+
+static void gdm_usb_send_complete(struct urb *urb)
+{
+	struct usb_tx *t = urb->context;
+	struct tx_cxt *tx = t->tx;
+	struct lte_udev *udev = container_of(tx, struct lte_udev, tx);
+	unsigned long flags;
+
+	if (urb->status == -ECONNRESET) {
+		pr_info("CONNRESET\n");
+		return;
+	}
+
+	if (t->callback)
+		t->callback(t->cb_data);
+
+	free_tx_struct(t);
+
+	spin_lock_irqsave(&tx->lock, flags);
+	udev->send_complete = 1;
+	queue_work(usb_tx_wq, &udev->work_tx.work);
+	spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len)
+{
+	int ret = 0;
+
+	if (!(len%512))
+		len++;
+
+	usb_fill_bulk_urb(t->urb,
+			  usbdev,
+			  usb_sndbulkpipe(usbdev, 2),
+			  t->buf,
+			  len,
+			  gdm_usb_send_complete,
+			  t);
+
+	ret = usb_submit_urb(t->urb, GFP_ATOMIC);
+
+	if (ret)
+		pr_err("usb_submit_urb failed: %d\n", ret);
+
+	usb_mark_last_busy(usbdev);
+
+	return ret;
+}
+
+static u32 packet_aggregation(struct lte_udev *udev, u8 *send_buf)
+{
+	struct tx_cxt *tx = &udev->tx;
+	struct usb_tx_sdu *t_sdu = NULL;
+	struct multi_sdu *multi_sdu = (struct multi_sdu *)send_buf;
+	u16 send_len = 0;
+	u16 num_packet = 0;
+	unsigned long flags;
+
+	multi_sdu->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_TX_MULTI_SDU);
+
+	while (num_packet < MAX_PACKET_IN_MULTI_SDU) {
+		spin_lock_irqsave(&tx->lock, flags);
+		if (list_empty(&tx->sdu_list)) {
+			spin_unlock_irqrestore(&tx->lock, flags);
+			break;
+		}
+
+		t_sdu = list_entry(tx->sdu_list.next, struct usb_tx_sdu, list);
+		if (send_len + t_sdu->len > MAX_SDU_SIZE) {
+			spin_unlock_irqrestore(&tx->lock, flags);
+			break;
+		}
+
+		list_del(&t_sdu->list);
+		spin_unlock_irqrestore(&tx->lock, flags);
+
+		memcpy(multi_sdu->data + send_len, t_sdu->buf, t_sdu->len);
+
+		send_len += (t_sdu->len + 3) & 0xfffc;
+		num_packet++;
+
+		if (tx->avail_count > 10)
+			t_sdu->callback(t_sdu->cb_data);
+
+		spin_lock_irqsave(&tx->lock, flags);
+		put_tx_struct(tx, t_sdu);
+		spin_unlock_irqrestore(&tx->lock, flags);
+	}
+
+	multi_sdu->len = gdm_cpu_to_dev16(&udev->gdm_ed, send_len);
+	multi_sdu->num_packet = gdm_cpu_to_dev16(&udev->gdm_ed, num_packet);
+
+	return send_len + offsetof(struct multi_sdu, data);
+}
+
+static void do_tx(struct work_struct *work)
+{
+	struct lte_udev *udev = container_of(work, struct lte_udev, work_tx.work);
+	struct usb_device *usbdev = udev->usbdev;
+	struct tx_cxt *tx = &udev->tx;
+	struct usb_tx *t = NULL;
+	int is_send = 0;
+	u32 len = 0;
+	unsigned long flags;
+
+	if (!usb_autopm_get_interface(udev->intf))
+		usb_autopm_put_interface(udev->intf);
+
+	if (udev->usb_state == PM_SUSPEND)
+		return;
+
+	spin_lock_irqsave(&tx->lock, flags);
+	if (!udev->send_complete) {
+		spin_unlock_irqrestore(&tx->lock, flags);
+		return;
+	} else {
+		udev->send_complete = 0;
+	}
+
+	if (!list_empty(&tx->hci_list)) {
+		t = list_entry(tx->hci_list.next, struct usb_tx, list);
+		list_del(&t->list);
+		len = t->len;
+		t->is_sdu = 0;
+		is_send = 1;
+	} else if (!list_empty(&tx->sdu_list)) {
+		if (udev->tx_stop) {
+			udev->send_complete = 1;
+			spin_unlock_irqrestore(&tx->lock, flags);
+			return;
+		}
+
+		t = alloc_tx_struct(TX_BUF_SIZE);
+		t->callback = NULL;
+		t->tx = tx;
+		t->is_sdu = 1;
+		is_send = 1;
+	}
+
+	if (!is_send) {
+		udev->send_complete = 1;
+		spin_unlock_irqrestore(&tx->lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	if (t->is_sdu)
+		len = packet_aggregation(udev, t->buf);
+
+	if (send_tx_packet(usbdev, t, len)) {
+		pr_err("send_tx_packet failed\n");
+		t->callback = NULL;
+		gdm_usb_send_complete(t->urb);
+	}
+}
+
+#define SDU_PARAM_LEN 12
+static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
+				unsigned int dftEpsId, unsigned int epsId,
+				void (*cb)(void *data), void *cb_data,
+			    int dev_idx, int nic_type)
+{
+	struct lte_udev *udev = priv_dev;
+	struct tx_cxt *tx = &udev->tx;
+	struct usb_tx_sdu *t_sdu;
+	struct sdu *sdu = NULL;
+	unsigned long flags;
+	int no_spc = 0;
+	u16 send_len;
+
+	if (!udev->usbdev) {
+		pr_err("sdu send - invalid device\n");
+		return TX_NO_DEV;
+	}
+
+	spin_lock_irqsave(&tx->lock, flags);
+	t_sdu = get_tx_sdu_struct(tx, &no_spc);
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	if (t_sdu == NULL) {
+		pr_err("sdu send - free list empty\n");
+		return TX_NO_SPC;
+	}
+
+	sdu = (struct sdu *)t_sdu->buf;
+	sdu->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_TX_SDU);
+	if (nic_type == NIC_TYPE_ARP) {
+		send_len = len + SDU_PARAM_LEN;
+	    memcpy(sdu->data, data, len);
+	} else {
+	    send_len = len - ETH_HLEN;
+	    send_len += SDU_PARAM_LEN;
+	    memcpy(sdu->data, data+ETH_HLEN, len-ETH_HLEN);
+	}
+
+	sdu->len = gdm_cpu_to_dev16(&udev->gdm_ed, send_len);
+	sdu->dftEpsId = gdm_cpu_to_dev32(&udev->gdm_ed, dftEpsId);
+	sdu->bearer_ID = gdm_cpu_to_dev32(&udev->gdm_ed, epsId);
+	sdu->nic_type = gdm_cpu_to_dev32(&udev->gdm_ed, nic_type);
+
+	t_sdu->len = send_len + HCI_HEADER_SIZE;
+	t_sdu->callback = cb;
+	t_sdu->cb_data = cb_data;
+
+	spin_lock_irqsave(&tx->lock, flags);
+	list_add_tail(&t_sdu->list, &tx->sdu_list);
+	queue_work(usb_tx_wq, &udev->work_tx.work);
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	if (no_spc)
+		return TX_NO_BUFFER;
+
+	return 0;
+}
+
+static int gdm_usb_hci_send(void *priv_dev, void *data, int len,
+			void (*cb)(void *data), void *cb_data)
+{
+	struct lte_udev *udev = priv_dev;
+	struct tx_cxt *tx = &udev->tx;
+	struct usb_tx *t;
+	unsigned long flags;
+
+	if (!udev->usbdev) {
+		pr_err("hci send - invalid device\n");
+		return -ENODEV;
+	}
+
+	t = alloc_tx_struct(len);
+	if (t == NULL) {
+		pr_err("hci_send - out of memory\n");
+		return -ENOMEM;
+	}
+
+	memcpy(t->buf, data, len);
+	t->callback = cb;
+	t->cb_data = cb_data;
+	t->len = len;
+	t->tx = tx;
+	t->is_sdu = 0;
+
+	spin_lock_irqsave(&tx->lock, flags);
+	list_add_tail(&t->list, &tx->hci_list);
+	queue_work(usb_tx_wq, &udev->work_tx.work);
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	return 0;
+}
+
+static struct gdm_endian *gdm_usb_get_endian(void *priv_dev)
+{
+	struct lte_udev *udev = priv_dev;
+
+	return &udev->gdm_ed;
+}
+
+static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int ret = 0;
+	struct phy_dev *phy_dev = NULL;
+	struct lte_udev *udev = NULL;
+	u16 idVendor, idProduct;
+	int bInterfaceNumber;
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+
+	bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
+	idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
+	idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
+
+	pr_info("net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
+
+	if (bInterfaceNumber > NETWORK_INTERFACE) {
+		pr_info("not a network device\n");
+		return -1;
+	}
+
+	phy_dev = kmalloc(sizeof(struct phy_dev), GFP_ATOMIC);
+	if (!phy_dev) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	udev = kmalloc(sizeof(struct lte_udev), GFP_ATOMIC);
+	if (!udev) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(phy_dev, 0, sizeof(struct phy_dev));
+	memset(udev, 0, sizeof(struct lte_udev));
+
+	phy_dev->priv_dev = (void *)udev;
+	phy_dev->send_hci_func = gdm_usb_hci_send;
+	phy_dev->send_sdu_func = gdm_usb_sdu_send;
+	phy_dev->rcv_func = gdm_usb_recv;
+	phy_dev->get_endian = gdm_usb_get_endian;
+
+	udev->usbdev = usbdev;
+	ret = init_usb(udev);
+	if (ret < 0) {
+		pr_err("init_usb func failed\n");
+		goto out;
+	}
+	udev->intf = intf;
+
+	intf->needs_remote_wakeup = 1;
+	usb_enable_autosuspend(usbdev);
+	pm_runtime_set_autosuspend_delay(&usbdev->dev, AUTO_SUSPEND_TIMER);
+
+	/* List up hosts with big endians, otherwise, defaults to little endian */
+	if (idProduct == PID_GDM7243)
+		gdm_set_endian(&udev->gdm_ed, ENDIANNESS_BIG);
+	else
+		gdm_set_endian(&udev->gdm_ed, ENDIANNESS_LITTLE);
+
+	ret = request_mac_address(udev);
+	if (ret < 0) {
+		pr_err("request Mac address failed\n");
+		goto out;
+	}
+
+	start_rx_proc(phy_dev);
+out:
+
+	if (ret < 0) {
+		kfree(phy_dev);
+		if (udev) {
+			release_usb(udev);
+			kfree(udev);
+		}
+	}
+
+	usb_get_dev(usbdev);
+	usb_set_intfdata(intf, phy_dev);
+
+	return ret;
+}
+
+static void gdm_usb_disconnect(struct usb_interface *intf)
+{
+	struct phy_dev *phy_dev;
+	struct lte_udev *udev;
+	u16 idVendor, idProduct;
+	struct usb_device *usbdev;
+	usbdev = interface_to_usbdev(intf);
+
+	idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
+	idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
+
+	phy_dev = usb_get_intfdata(intf);
+
+	udev = phy_dev->priv_dev;
+	unregister_lte_device(phy_dev);
+
+	release_usb(udev);
+
+	kfree(udev);
+	udev = NULL;
+
+	kfree(phy_dev);
+	phy_dev = NULL;
+
+	usb_put_dev(usbdev);
+}
+
+static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg)
+{
+	struct phy_dev *phy_dev;
+	struct lte_udev *udev;
+	struct rx_cxt *rx;
+	struct usb_rx *r;
+	struct usb_rx *r_next;
+	unsigned long flags;
+
+	phy_dev = usb_get_intfdata(intf);
+	udev = phy_dev->priv_dev;
+	rx = &udev->rx;
+	if (udev->usb_state != PM_NORMAL) {
+		pr_err("usb suspend - invalid state\n");
+		return -1;
+	}
+
+	udev->usb_state = PM_SUSPEND;
+
+	spin_lock_irqsave(&rx->submit_lock, flags);
+	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list)
+	{
+		spin_unlock_irqrestore(&rx->submit_lock, flags);
+		usb_kill_urb(r->urb);
+		spin_lock_irqsave(&rx->submit_lock, flags);
+	}
+	spin_unlock_irqrestore(&rx->submit_lock, flags);
+
+	return 0;
+}
+
+static int gdm_usb_resume(struct usb_interface *intf)
+{
+	struct phy_dev *phy_dev;
+	struct lte_udev *udev;
+	struct tx_cxt *tx;
+	struct rx_cxt *rx;
+	unsigned long flags;
+	int issue_count;
+	int i;
+
+	phy_dev = usb_get_intfdata(intf);
+	udev = phy_dev->priv_dev;
+	rx = &udev->rx;
+
+	if (udev->usb_state != PM_SUSPEND) {
+		pr_err("usb resume - invalid state\n");
+		return -1;
+	}
+	udev->usb_state = PM_NORMAL;
+
+	spin_lock_irqsave(&rx->rx_lock, flags);
+	issue_count = rx->avail_count - MAX_RX_SUBMIT_COUNT;
+	spin_unlock_irqrestore(&rx->rx_lock, flags);
+
+	if (issue_count >= 0) {
+		for (i = 0; i < issue_count; i++)
+			gdm_usb_recv(phy_dev->priv_dev,
+				     udev->rx_cb,
+				     phy_dev,
+				     USB_COMPLETE);
+	}
+
+	tx = &udev->tx;
+	spin_lock_irqsave(&tx->lock, flags);
+	queue_work(usb_tx_wq, &udev->work_tx.work);
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	return 0;
+}
+
+static struct usb_driver gdm_usb_lte_driver = {
+	.name = "gdm_lte",
+	.probe = gdm_usb_probe,
+	.disconnect = gdm_usb_disconnect,
+	.id_table = id_table,
+	.supports_autosuspend = 1,
+	.suspend = gdm_usb_suspend,
+	.resume = gdm_usb_resume,
+	.reset_resume = gdm_usb_resume,
+};
+
+static int __init gdm_usb_lte_init(void)
+{
+	if (gdm_lte_event_init() < 0) {
+		pr_err("error creating event\n");
+		return -1;
+	}
+
+	usb_tx_wq = create_workqueue("usb_tx_wq");
+	if (usb_tx_wq == NULL)
+		return -1;
+
+	usb_rx_wq = create_workqueue("usb_rx_wq");
+	if (usb_rx_wq == NULL)
+		return -1;
+
+	return usb_register(&gdm_usb_lte_driver);
+}
+
+static void __exit gdm_usb_lte_exit(void)
+{
+	gdm_lte_event_exit();
+
+	usb_deregister(&gdm_usb_lte_driver);
+
+	if (usb_tx_wq) {
+		flush_workqueue(usb_tx_wq);
+		destroy_workqueue(usb_tx_wq);
+	}
+
+	if (usb_rx_wq) {
+		flush_workqueue(usb_rx_wq);
+		destroy_workqueue(usb_rx_wq);
+	}
+}
+
+module_init(gdm_usb_lte_init);
+module_exit(gdm_usb_lte_exit);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_DESCRIPTION("GCT LTE USB Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h
new file mode 100644
index 0000000..e6486e7
--- /dev/null
+++ b/drivers/staging/gdm724x/gdm_usb.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _GDM_USB_H_
+#define _GDM_USB_H_
+
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/list.h>
+#include <linux/time.h>
+
+#include "gdm_endian.h"
+#include "hci_packet.h"
+
+#define PM_NORMAL 0
+#define PM_SUSPEND 1
+#define AUTO_SUSPEND_TIMER 5000 /* ms */
+
+#define RX_BUF_SIZE		(1024*32)
+#define TX_BUF_SIZE		(1024*32)
+#define SDU_BUF_SIZE	2048
+#define MAX_SDU_SIZE	(1024*30)
+#define MAX_PACKET_IN_MULTI_SDU	256
+
+#define VID_GCT			0x1076
+#define PID_GDM7240		0x8000
+#define PID_GDM7243		0x9000
+
+#define NETWORK_INTERFACE 1
+#define USB_SC_SCSI 0x06
+#define USB_PR_BULK 0x50
+
+#define MAX_NUM_SDU_BUF	64
+
+struct usb_tx {
+	struct list_head list;
+	struct urb *urb;
+	u8 *buf;
+	u32 len;
+	void (*callback)(void *cb_data);
+	void *cb_data;
+	struct tx_cxt *tx;
+	u8 is_sdu;
+};
+
+struct usb_tx_sdu {
+	struct list_head list;
+	u8 *buf;
+	u32 len;
+	void (*callback)(void *cb_data);
+	void *cb_data;
+};
+
+struct usb_rx {
+	struct list_head to_host_list;
+	struct list_head free_list;
+	struct list_head rx_submit_list;
+	struct rx_cxt	*rx;
+	struct urb *urb;
+	u8 *buf;
+	int (*callback)(void *cb_data, void *data, int len, int context);
+	void *cb_data;
+	void *index;
+};
+
+struct tx_cxt {
+	struct list_head sdu_list;
+	struct list_head hci_list;
+	struct list_head free_list;
+	u32 avail_count;
+	spinlock_t lock;
+};
+
+struct rx_cxt {
+	struct list_head to_host_list;
+	struct list_head rx_submit_list;
+	struct list_head free_list;
+	u32	avail_count;
+	spinlock_t to_host_lock;
+	spinlock_t rx_lock;
+	spinlock_t submit_lock;
+};
+
+struct lte_udev {
+	struct usb_device *usbdev;
+	struct gdm_endian gdm_ed;
+	struct tx_cxt tx;
+	struct rx_cxt rx;
+	struct delayed_work work_tx;
+	struct delayed_work work_rx;
+	u8 send_complete;
+	u8 tx_stop;
+	struct usb_interface *intf;
+	int (*rx_cb)(void *cb_data, void *data, int len, int context);
+	int usb_state;
+	u8 request_mac_addr;
+};
+
+#endif /* _GDM_USB_H_ */
diff --git a/drivers/staging/gdm724x/hci.h b/drivers/staging/gdm724x/hci.h
new file mode 100644
index 0000000..9a591b0
--- /dev/null
+++ b/drivers/staging/gdm724x/hci.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _HCI_H_
+#define _HCI_H_
+
+#define LTE_GET_INFORMATION		0x3002
+#define LTE_GET_INFORMATION_RESULT	0xB003
+	#define MAC_ADDRESS		0xA2
+
+#define LTE_LINK_ON_OFF_INDICATION	0xB133
+#define LTE_PDN_TABLE_IND		0xB143
+
+#define LTE_TX_SDU			0x3200
+#define LTE_RX_SDU			0xB201
+#define LTE_TX_MULTI_SDU		0x3202
+#define LTE_RX_MULTI_SDU		0xB203
+
+#define LTE_DL_SDU_FLOW_CONTROL		0x3305
+#define LTE_UL_SDU_FLOW_CONTROL		0xB306
+
+#define LTE_AT_CMD_TO_DEVICE		0x3307
+#define LTE_AT_CMD_FROM_DEVICE		0xB308
+
+#define LTE_SDIO_DM_SEND_PKT		0x3312
+#define LTE_SDIO_DM_RECV_PKT		0xB313
+
+#define LTE_NV_RESTORE_REQUEST		0xB30C
+#define LTE_NV_RESTORE_RESPONSE		0x330D
+#define LTE_NV_SAVE_REQUEST		0xB30E
+	#define NV_TYPE_LTE_INFO	0x00
+	#define NV_TYPE_BOARD_CONFIG	0x01
+	#define NV_TYPE_RF_CAL		0x02
+	#define NV_TYPE_TEMP		0x03
+	#define NV_TYPE_NET_INFO	0x04
+	#define NV_TYPE_SAFETY_INFO	0x05
+	#define NV_TYPE_CDMA_CAL	0x06
+	#define NV_TYPE_VENDOR		0x07
+	#define NV_TYPE_ALL		0xff
+#define LTE_NV_SAVE_RESPONSE		0x330F
+
+#define LTE_AT_CMD_TO_DEVICE_EXT	0x3323
+#define LTE_AT_CMD_FROM_DEVICE_EXT	0xB324
+
+#endif /* _HCI_H_ */
diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h
new file mode 100644
index 0000000..7fba8a6
--- /dev/null
+++ b/drivers/staging/gdm724x/hci_packet.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _HCI_PACKET_H_
+#define _HCI_PACKET_H_
+
+#define HCI_HEADER_SIZE 4
+
+/*
+ * The NIC type definition:
+ * For backward compatibility, lower 16 bits used as they were.
+ * Lower 16 bit: NIC_TYPE values
+ * Uppoer 16 bit: NIC_TYPE Flags
+ */
+#define NIC_TYPE_NIC0		0x00000010
+#define NIC_TYPE_NIC1		0x00000011
+#define NIC_TYPE_NIC2		0x00000012
+#define NIC_TYPE_NIC3		0x00000013
+#define NIC_TYPE_ARP		0x00000100
+#define NIC_TYPE_ICMPV6		0x00000200
+#define NIC_TYPE_MASK		0x0000FFFF
+#define NIC_TYPE_F_IPV4		0x00010000
+#define NIC_TYPE_F_IPV6		0x00020000
+#define NIC_TYPE_F_DHCP		0x00040000
+#define NIC_TYPE_F_NDP		0x00080000
+#define NIC_TYPE_F_VLAN		0x00100000
+
+struct hci_packet {
+	u16 cmd_evt;
+	u16 len;
+	u8 data[0];
+} __packed;
+
+struct tlv {
+	u8 type;
+	u8 len;
+	u8 *data[1];
+} __packed;
+
+struct sdu_header {
+	u16 cmd_evt;
+	u16 len;
+	u32 dftEpsId;
+	u32 bearer_ID;
+	u32 nic_type;
+} __packed;
+
+struct sdu {
+	u16 cmd_evt;
+	u16 len;
+	u32 dftEpsId;
+	u32 bearer_ID;
+	u32 nic_type;
+	u8 data[0];
+} __packed;
+
+struct multi_sdu {
+	u16 cmd_evt;
+	u16 len;
+	u16 num_packet;
+	u16 reserved;
+	u8 data[0];
+} __packed;
+
+struct hci_pdn_table_ind {
+	u16 cmd_evt;
+	u16 len;
+	u8 activate;
+	u32 dft_eps_id;
+	u32 nic_type;
+	u8 pdn_type;
+	u8 ipv4_addr[4];
+	u8 ipv6_intf_id[8];
+} __packed;
+
+struct hci_connect_ind {
+	u16 cmd_evt;
+	u16 len;
+	u32 connect;
+} __packed;
+
+
+#endif /* _HCI_PACKET_H_ */
diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c
new file mode 100644
index 0000000..90004a7
--- /dev/null
+++ b/drivers/staging/gdm724x/netlink_k.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/version.h>
+#include <linux/export.h>
+#include <linux/etherdevice.h>
+#include <linux/netlink.h>
+#include <asm/byteorder.h>
+#include <net/sock.h>
+
+#include "netlink_k.h"
+
+#if defined(DEFINE_MUTEX)
+static DEFINE_MUTEX(netlink_mutex);
+#else
+static struct semaphore netlink_mutex;
+#define mutex_lock(x)		down(x)
+#define mutex_unlock(x)		up(x)
+#endif
+
+#define ND_MAX_GROUP		30
+#define ND_IFINDEX_LEN		sizeof(int)
+#define ND_NLMSG_SPACE(len)	(NLMSG_SPACE(len) + ND_IFINDEX_LEN)
+#define ND_NLMSG_DATA(nlh)	((void *)((char *)NLMSG_DATA(nlh) + ND_IFINDEX_LEN))
+#define ND_NLMSG_S_LEN(len)	(len+ND_IFINDEX_LEN)
+#define ND_NLMSG_R_LEN(nlh)	(nlh->nlmsg_len-ND_IFINDEX_LEN)
+#define ND_NLMSG_IFIDX(nlh)	NLMSG_DATA(nlh)
+#define ND_MAX_MSG_LEN		(1024 * 32)
+
+static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len);
+
+static void netlink_rcv_cb(struct sk_buff *skb)
+{
+	struct nlmsghdr	*nlh;
+	struct net_device *dev;
+	u32 mlen;
+	void *msg;
+	int ifindex;
+
+	if (!rcv_cb) {
+		pr_err("nl cb - unregistered\n");
+		return;
+	}
+
+	if (skb->len < NLMSG_SPACE(0)) {
+		pr_err("nl cb - invalid skb length\n");
+		return;
+	}
+
+	nlh = (struct nlmsghdr *)skb->data;
+
+	if (skb->len < nlh->nlmsg_len || nlh->nlmsg_len > ND_MAX_MSG_LEN) {
+		pr_err("nl cb - invalid length (%d,%d)\n",
+		       skb->len, nlh->nlmsg_len);
+		return;
+	}
+
+	memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN);
+	msg = ND_NLMSG_DATA(nlh);
+	mlen = ND_NLMSG_R_LEN(nlh);
+
+	dev = dev_get_by_index(&init_net, ifindex);
+	if (dev) {
+		rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
+		dev_put(dev);
+	} else {
+		pr_err("nl cb - dev (%d) not found\n", ifindex);
+	}
+}
+
+static void netlink_rcv(struct sk_buff *skb)
+{
+	mutex_lock(&netlink_mutex);
+	netlink_rcv_cb(skb);
+	mutex_unlock(&netlink_mutex);
+}
+
+struct sock *netlink_init(int unit,
+	void (*cb)(struct net_device *dev, u16 type, void *msg, int len))
+{
+	struct sock *sock;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct netlink_kernel_cfg cfg = {
+		.input  = netlink_rcv,
+	};
+#endif
+
+#if !defined(DEFINE_MUTEX)
+	init_MUTEX(&netlink_mutex);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+	sock = netlink_kernel_create(&init_net, unit, 0, netlink_rcv, NULL,
+		THIS_MODULE);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
+	sock = netlink_kernel_create(&init_net, unit, THIS_MODULE, &cfg);
+#else
+	sock = netlink_kernel_create(&init_net, unit, &cfg);
+#endif
+
+	if (sock)
+		rcv_cb = cb;
+
+	return sock;
+}
+
+void netlink_exit(struct sock *sock)
+{
+	sock_release(sock->sk_socket);
+}
+
+int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
+{
+	static u32 seq;
+	struct sk_buff *skb = NULL;
+	struct nlmsghdr *nlh;
+	int ret = 0;
+
+	if (group > ND_MAX_GROUP)
+		return -EINVAL;
+
+	if (!netlink_has_listeners(sock, group+1))
+		return -ESRCH;
+
+	skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	seq++;
+
+	nlh = nlmsg_put(skb, 0, seq, type, len, 0);
+	memcpy(NLMSG_DATA(nlh), msg, len);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
+	NETLINK_CB(skb).pid = 0;
+#else
+	NETLINK_CB(skb).portid = 0;
+#endif
+	NETLINK_CB(skb).dst_group = 0;
+
+	ret = netlink_broadcast(sock, skb, 0, group+1, GFP_ATOMIC);
+	if (!ret)
+		return len;
+
+	if (ret != -ESRCH)
+		pr_err("nl broadcast g=%d, t=%d, l=%d, r=%d\n",
+		       group, type, len, ret);
+	else if (netlink_has_listeners(sock, group+1))
+		return -EAGAIN;
+
+	return ret;
+}
diff --git a/drivers/staging/gdm724x/netlink_k.h b/drivers/staging/gdm724x/netlink_k.h
new file mode 100644
index 0000000..589486d
--- /dev/null
+++ b/drivers/staging/gdm724x/netlink_k.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _NETLINK_K_H
+#define _NETLINK_K_H
+
+#include <linux/netdevice.h>
+#include <net/sock.h>
+
+struct sock *netlink_init(int unit,
+	void (*cb)(struct net_device *dev, u16 type, void *msg, int len));
+void netlink_exit(struct sock *sock);
+int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len);
+
+#endif /* _NETLINK_K_H_ */
diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt
index ea08d62..8be32e5 100644
--- a/drivers/staging/iio/Documentation/device.txt
+++ b/drivers/staging/iio/Documentation/device.txt
@@ -56,7 +56,7 @@ Then fill in the following:
 
 - indio_dev->modes:
 	Specify whether direct access and / or ring buffer access is supported.
-- indio_dev->ring:
+- indio_dev->buffer:
 	An optional associated buffer.
 - indio_dev->pollfunc:
 	Poll function related elements. This controls what occurs when a trigger
@@ -67,7 +67,7 @@ Then fill in the following:
 - indio_dev->num_channels:
 	How many channels are there?
 
-Once these are set up, a call to iio_device_register(indio_dev),
+Once these are set up, a call to iio_device_register(indio_dev)
 will register the device with the iio core.
 
 Worth noting here is that, if a ring buffer is to be used, it can be
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 9f52a28..863f086 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -841,14 +841,16 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
 	MXS_ADC_CHAN(15, IIO_VOLTAGE),	/* VDD5V */
 };
 
-static void mxs_lradc_hw_init(struct mxs_lradc *lradc)
+static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
 {
 	/* The ADC always uses DELAY CHANNEL 0. */
 	const uint32_t adc_cfg =
 		(1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) |
 		(LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET);
 
-	stmp_reset_block(lradc->base);
+	int ret = stmp_reset_block(lradc->base);
+	if (ret)
+		return ret;
 
 	/* Configure DELAY CHANNEL 0 for generic ADC sampling. */
 	writel(adc_cfg, lradc->base + LRADC_DELAY(0));
@@ -869,6 +871,8 @@ static void mxs_lradc_hw_init(struct mxs_lradc *lradc)
 
 	/* Start internal temperature sensing. */
 	writel(0, lradc->base + LRADC_CTRL2);
+
+	return 0;
 }
 
 static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
@@ -905,7 +909,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	int i;
 
 	/* Allocate the IIO device. */
-	iio = iio_device_alloc(sizeof(*lradc));
+	iio = devm_iio_device_alloc(dev, sizeof(*lradc));
 	if (!iio) {
 		dev_err(dev, "Failed to allocate IIO device\n");
 		return -ENOMEM;
@@ -917,10 +921,8 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	lradc->dev = &pdev->dev;
 	lradc->base = devm_ioremap_resource(dev, iores);
-	if (IS_ERR(lradc->base)) {
-		ret = PTR_ERR(lradc->base);
-		goto err_addr;
-	}
+	if (IS_ERR(lradc->base))
+		return PTR_ERR(lradc->base);
 
 	INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work);
 
@@ -940,16 +942,14 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	/* Grab all IRQ sources */
 	for (i = 0; i < of_cfg->irq_count; i++) {
 		lradc->irq[i] = platform_get_irq(pdev, i);
-		if (lradc->irq[i] < 0) {
-			ret = -EINVAL;
-			goto err_addr;
-		}
+		if (lradc->irq[i] < 0)
+			return -EINVAL;
 
 		ret = devm_request_irq(dev, lradc->irq[i],
 					mxs_lradc_handle_irq, 0,
 					of_cfg->irq_name[i], iio);
 		if (ret)
-			goto err_addr;
+			return ret;
 	}
 
 	platform_set_drvdata(pdev, iio);
@@ -969,14 +969,16 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 				&mxs_lradc_trigger_handler,
 				&mxs_lradc_buffer_ops);
 	if (ret)
-		goto err_addr;
+		return ret;
 
 	ret = mxs_lradc_trigger_init(iio);
 	if (ret)
 		goto err_trig;
 
 	/* Configure the hardware. */
-	mxs_lradc_hw_init(lradc);
+	ret = mxs_lradc_hw_init(lradc);
+	if (ret)
+		goto err_dev;
 
 	/* Register the touchscreen input device. */
 	ret = mxs_lradc_ts_register(lradc);
@@ -998,8 +1000,6 @@ err_dev:
 	mxs_lradc_trigger_remove(iio);
 err_trig:
 	iio_triggered_buffer_cleanup(iio);
-err_addr:
-	iio_device_free(iio);
 	return ret;
 }
 
@@ -1015,7 +1015,6 @@ static int mxs_lradc_remove(struct platform_device *pdev)
 	iio_device_unregister(iio);
 	iio_triggered_buffer_cleanup(iio);
 	mxs_lradc_trigger_remove(iio);
-	iio_device_free(iio);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 736219c..20f2d55 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -300,11 +300,10 @@ static int spear_adc_probe(struct platform_device *pdev)
 	int ret = -ENODEV;
 	int irq;
 
-	iodev = iio_device_alloc(sizeof(struct spear_adc_info));
+	iodev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_info));
 	if (!iodev) {
 		dev_err(dev, "failed allocating iio device\n");
-		ret = -ENOMEM;
-		goto errout1;
+		return -ENOMEM;
 	}
 
 	info = iio_priv(iodev);
@@ -318,8 +317,7 @@ static int spear_adc_probe(struct platform_device *pdev)
 	info->adc_base_spear6xx = of_iomap(np, 0);
 	if (!info->adc_base_spear6xx) {
 		dev_err(dev, "failed mapping memory\n");
-		ret = -ENOMEM;
-		goto errout2;
+		return -ENOMEM;
 	}
 	info->adc_base_spear3xx =
 		(struct adc_regs_spear3xx *)info->adc_base_spear6xx;
@@ -327,33 +325,33 @@ static int spear_adc_probe(struct platform_device *pdev)
 	info->clk = clk_get(dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(dev, "failed getting clock\n");
-		goto errout3;
+		goto errout1;
 	}
 
 	ret = clk_prepare_enable(info->clk);
 	if (ret) {
 		dev_err(dev, "failed enabling clock\n");
-		goto errout4;
+		goto errout2;
 	}
 
 	irq = platform_get_irq(pdev, 0);
 	if ((irq < 0) || (irq >= NR_IRQS)) {
 		dev_err(dev, "failed getting interrupt resource\n");
 		ret = -EINVAL;
-		goto errout5;
+		goto errout3;
 	}
 
 	ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info);
 	if (ret < 0) {
 		dev_err(dev, "failed requesting interrupt\n");
-		goto errout5;
+		goto errout3;
 	}
 
 	if (of_property_read_u32(np, "sampling-frequency",
 				 &info->sampling_freq)) {
 		dev_err(dev, "sampling-frequency missing in DT\n");
 		ret = -EINVAL;
-		goto errout5;
+		goto errout3;
 	}
 
 	/*
@@ -383,21 +381,18 @@ static int spear_adc_probe(struct platform_device *pdev)
 
 	ret = iio_device_register(iodev);
 	if (ret)
-		goto errout5;
+		goto errout3;
 
 	dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
 
 	return 0;
 
-errout5:
-	clk_disable_unprepare(info->clk);
-errout4:
-	clk_put(info->clk);
 errout3:
-	iounmap(info->adc_base_spear6xx);
+	clk_disable_unprepare(info->clk);
 errout2:
-	iio_device_free(iodev);
+	clk_put(info->clk);
 errout1:
+	iounmap(info->adc_base_spear6xx);
 	return ret;
 }
 
@@ -410,7 +405,6 @@ static int spear_adc_remove(struct platform_device *pdev)
 	clk_disable_unprepare(info->clk);
 	clk_put(info->clk);
 	iounmap(info->adc_base_spear6xx);
-	iio_device_free(iodev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 506b5a7..1e13568 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -551,31 +551,6 @@ static IIO_DEVICE_ATTR(enable_smbus_timeout, S_IRUGO | S_IWUSR,
 		adt7316_store_enable_smbus_timeout,
 		0);
 
-
-static ssize_t adt7316_store_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7316_chip_info *chip = iio_priv(dev_info);
-	u8 config2;
-	int ret;
-
-	config2 = chip->config2 | ADT7316_RESET;
-
-	ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
-	if (ret)
-		return -EIO;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(reset, S_IWUSR,
-		NULL,
-		adt7316_store_reset,
-		0);
-
 static ssize_t adt7316_show_powerdown(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
@@ -1675,7 +1650,6 @@ static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0);
 static struct attribute *adt7316_attributes[] = {
 	&iio_dev_attr_all_modes.dev_attr.attr,
 	&iio_dev_attr_mode.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_enabled.dev_attr.attr,
 	&iio_dev_attr_ad_channel.dev_attr.attr,
 	&iio_dev_attr_all_ad_channels.dev_attr.attr,
@@ -1719,7 +1693,6 @@ static struct attribute *adt7516_attributes[] = {
 	&iio_dev_attr_all_modes.dev_attr.attr,
 	&iio_dev_attr_mode.dev_attr.attr,
 	&iio_dev_attr_select_ex_temp.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_enabled.dev_attr.attr,
 	&iio_dev_attr_ad_channel.dev_attr.attr,
 	&iio_dev_attr_all_ad_channels.dev_attr.attr,
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig
index b433371..88b199b 100644
--- a/drivers/staging/iio/gyro/Kconfig
+++ b/drivers/staging/iio/gyro/Kconfig
@@ -10,16 +10,4 @@ config ADIS16060
 	  Say yes here to build support for Analog Devices adis16060 wide bandwidth
 	  yaw rate gyroscope with SPI.
 
-config ADIS16260
-	tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
-	depends on SPI
-	select IIO_ADIS_LIB
-	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
-	help
-	  Say yes here to build support for Analog Devices ADIS16260 ADIS16265
-	  ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called adis16260.
-
 endmenu
diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile
index 975f95b..cf22d6d 100644
--- a/drivers/staging/iio/gyro/Makefile
+++ b/drivers/staging/iio/gyro/Makefile
@@ -4,6 +4,3 @@
 
 adis16060-y             := adis16060_core.o
 obj-$(CONFIG_ADIS16060) += adis16060.o
-
-adis16260-y             := adis16260_core.o
-obj-$(CONFIG_ADIS16260) += adis16260.o
diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
deleted file mode 100644
index df3c0b7..0000000
--- a/drivers/staging/iio/gyro/adis16260.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef SPI_ADIS16260_H_
-#define SPI_ADIS16260_H_
-
-#include "adis16260_platform_data.h"
-#include <linux/iio/imu/adis.h>
-
-#define ADIS16260_STARTUP_DELAY	220 /* ms */
-
-#define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
-#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
-#define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
-#define ADIS16260_AUX_ADC    0x0A /* analog input channel measurement */
-#define ADIS16260_TEMP_OUT   0x0C /* internal temperature measurement */
-#define ADIS16260_ANGL_OUT   0x0E /* angle displacement */
-#define ADIS16260_GYRO_OFF   0x14 /* Calibration, offset/bias adjustment */
-#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
-#define ADIS16260_ALM_MAG1   0x20 /* Alarm 1 magnitude/polarity setting */
-#define ADIS16260_ALM_MAG2   0x22 /* Alarm 2 magnitude/polarity setting */
-#define ADIS16260_ALM_SMPL1  0x24 /* Alarm 1 dynamic rate of change setting */
-#define ADIS16260_ALM_SMPL2  0x26 /* Alarm 2 dynamic rate of change setting */
-#define ADIS16260_ALM_CTRL   0x28 /* Alarm control */
-#define ADIS16260_AUX_DAC    0x30 /* Auxiliary DAC data */
-#define ADIS16260_GPIO_CTRL  0x32 /* Control, digital I/O line */
-#define ADIS16260_MSC_CTRL   0x34 /* Control, data ready, self-test settings */
-#define ADIS16260_SMPL_PRD   0x36 /* Control, internal sample rate */
-#define ADIS16260_SENS_AVG   0x38 /* Control, dynamic range, filtering */
-#define ADIS16260_SLP_CNT    0x3A /* Control, sleep mode initiation */
-#define ADIS16260_DIAG_STAT  0x3C /* Diagnostic, error flags */
-#define ADIS16260_GLOB_CMD   0x3E /* Control, global commands */
-#define ADIS16260_LOT_ID1    0x52 /* Lot Identification Code 1 */
-#define ADIS16260_LOT_ID2    0x54 /* Lot Identification Code 2 */
-#define ADIS16260_PROD_ID    0x56 /* Product identifier;
-				   * convert to decimal = 16,265/16,260 */
-#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
-
-#define ADIS16260_ERROR_ACTIVE			(1<<14)
-#define ADIS16260_NEW_DATA			(1<<15)
-
-/* MSC_CTRL */
-#define ADIS16260_MSC_CTRL_MEM_TEST		(1<<11)
-/* Internal self-test enable */
-#define ADIS16260_MSC_CTRL_INT_SELF_TEST	(1<<10)
-#define ADIS16260_MSC_CTRL_NEG_SELF_TEST	(1<<9)
-#define ADIS16260_MSC_CTRL_POS_SELF_TEST	(1<<8)
-#define ADIS16260_MSC_CTRL_DATA_RDY_EN		(1<<2)
-#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
-#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
-
-/* SMPL_PRD */
-/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
-#define ADIS16260_SMPL_PRD_TIME_BASE	(1<<7)
-#define ADIS16260_SMPL_PRD_DIV_MASK	0x7F
-
-/* SLP_CNT */
-#define ADIS16260_SLP_CNT_POWER_OFF     0x80
-
-/* DIAG_STAT */
-#define ADIS16260_DIAG_STAT_ALARM2	(1<<9)
-#define ADIS16260_DIAG_STAT_ALARM1	(1<<8)
-#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT	6
-#define ADIS16260_DIAG_STAT_SELF_TEST_BIT	5
-#define ADIS16260_DIAG_STAT_OVERFLOW_BIT	4
-#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT	3
-#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT	2
-#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT	1
-#define ADIS16260_DIAG_STAT_POWER_LOW_BIT	0
-
-/* GLOB_CMD */
-#define ADIS16260_GLOB_CMD_SW_RESET	(1<<7)
-#define ADIS16260_GLOB_CMD_FLASH_UPD	(1<<3)
-#define ADIS16260_GLOB_CMD_DAC_LATCH	(1<<2)
-#define ADIS16260_GLOB_CMD_FAC_CALIB	(1<<1)
-#define ADIS16260_GLOB_CMD_AUTO_NULL	(1<<0)
-
-#define ADIS16260_SPI_SLOW	(u32)(300 * 1000)
-#define ADIS16260_SPI_BURST	(u32)(1000 * 1000)
-#define ADIS16260_SPI_FAST	(u32)(2000 * 1000)
-
-/**
- * struct adis16260_state - device instance specific data
- * @negate:		negate the scale parameter
- **/
-struct adis16260_state {
-	unsigned	negate:1;
-	struct adis	adis;
-};
-
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-#define ADIS16260_SCAN_GYRO	0
-#define ADIS16260_SCAN_SUPPLY	1
-#define ADIS16260_SCAN_AUX_ADC	2
-#define ADIS16260_SCAN_TEMP	3
-#define ADIS16260_SCAN_ANGL	4
-
-#endif /* SPI_ADIS16260_H_ */
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
deleted file mode 100644
index 620d63f..0000000
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-
-#include "adis16260.h"
-
-static ssize_t adis16260_read_frequency_available(struct device *dev,
-						  struct device_attribute *attr,
-						  char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16260_state *st = iio_priv(indio_dev);
-	if (spi_get_device_id(st->adis.spi)->driver_data)
-		return sprintf(buf, "%s\n", "0.129 ~ 256");
-	else
-		return sprintf(buf, "%s\n", "256 2048");
-}
-
-static ssize_t adis16260_read_frequency(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int ret, len = 0;
-	u16 t;
-	int sps;
-	ret = adis_read_reg_16(&st->adis, ADIS16260_SMPL_PRD, &t);
-	if (ret)
-		return ret;
-
-	if (spi_get_device_id(st->adis.spi)->driver_data) /* If an adis16251 */
-		sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
-	else
-		sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
-	sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
-	len = sprintf(buf, "%d SPS\n", sps);
-	return len;
-}
-
-static ssize_t adis16260_write_frequency(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16260_state *st = iio_priv(indio_dev);
-	long val;
-	int ret;
-	u8 t;
-
-	ret = strict_strtol(buf, 10, &val);
-	if (ret)
-		return ret;
-	if (val == 0)
-		return -EINVAL;
-
-	mutex_lock(&indio_dev->mlock);
-	if (spi_get_device_id(st->adis.spi)->driver_data) {
-		t = (256 / val);
-		if (t > 0)
-			t--;
-		t &= ADIS16260_SMPL_PRD_DIV_MASK;
-	} else {
-		t = (2048 / val);
-		if (t > 0)
-			t--;
-		t &= ADIS16260_SMPL_PRD_DIV_MASK;
-	}
-	if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A)
-		st->adis.spi->max_speed_hz = ADIS16260_SPI_SLOW;
-	else
-		st->adis.spi->max_speed_hz = ADIS16260_SPI_FAST;
-	ret = adis_write_reg_8(&st->adis,
-			ADIS16260_SMPL_PRD,
-			t);
-
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret ? ret : len;
-}
-
-/* Power down the device */
-static int adis16260_stop_device(struct iio_dev *indio_dev)
-{
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int ret;
-	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
-
-	ret = adis_write_reg_16(&st->adis, ADIS16260_SLP_CNT, val);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
-
-	return ret;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-		adis16260_read_frequency,
-		adis16260_write_frequency);
-
-static IIO_DEVICE_ATTR(sampling_frequency_available,
-		       S_IRUGO, adis16260_read_frequency_available, NULL, 0);
-
-#define ADIS16260_GYRO_CHANNEL_SET(axis, mod)				\
-struct iio_chan_spec adis16260_channels_##axis[] = {		\
-	ADIS_GYRO_CHAN(mod, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO, \
-		BIT(IIO_CHAN_INFO_CALIBBIAS) | \
-		BIT(IIO_CHAN_INFO_CALIBSCALE), 14), \
-	ADIS_INCLI_CHAN(mod, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14), \
-	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12), \
-	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12), \
-	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12), \
-	IIO_CHAN_SOFT_TIMESTAMP(5),				\
-}
-
-static const ADIS16260_GYRO_CHANNEL_SET(x, X);
-static const ADIS16260_GYRO_CHANNEL_SET(y, Y);
-static const ADIS16260_GYRO_CHANNEL_SET(z, Z);
-
-static const u8 adis16260_addresses[][2] = {
-	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
-};
-
-static int adis16260_read_raw(struct iio_dev *indio_dev,
-			      struct iio_chan_spec const *chan,
-			      int *val, int *val2,
-			      long mask)
-{
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int ret;
-	int bits;
-	u8 addr;
-	s16 val16;
-
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		return adis_single_conversion(indio_dev, chan,
-				ADIS16260_ERROR_ACTIVE, val);
-	case IIO_CHAN_INFO_SCALE:
-		switch (chan->type) {
-		case IIO_ANGL_VEL:
-			*val = 0;
-			if (spi_get_device_id(st->adis.spi)->driver_data) {
-				/* 0.01832 degree / sec */
-				*val2 = IIO_DEGREE_TO_RAD(18320);
-			} else {
-				/* 0.07326 degree / sec */
-				*val2 = IIO_DEGREE_TO_RAD(73260);
-			}
-			return IIO_VAL_INT_PLUS_MICRO;
-		case IIO_VOLTAGE:
-			if (chan->channel == 0) {
-				*val = 1;
-				*val2 = 831500; /* 1.8315 mV */
-			} else {
-				*val = 0;
-				*val2 = 610500; /* 610.5 uV */
-			}
-			return IIO_VAL_INT_PLUS_MICRO;
-		case IIO_TEMP:
-			*val = 145;
-			*val2 = 300000; /* 0.1453 C */
-			return IIO_VAL_INT_PLUS_MICRO;
-		default:
-			return -EINVAL;
-		}
-		break;
-	case IIO_CHAN_INFO_OFFSET:
-		*val = 250000 / 1453; /* 25 C = 0x00 */
-		return IIO_VAL_INT;
-	case IIO_CHAN_INFO_CALIBBIAS:
-		switch (chan->type) {
-		case IIO_ANGL_VEL:
-			bits = 12;
-			break;
-		default:
-			return -EINVAL;
-		}
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16260_addresses[chan->scan_index][0];
-		ret = adis_read_reg_16(&st->adis, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-		val16 &= (1 << bits) - 1;
-		val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
-	case IIO_CHAN_INFO_CALIBSCALE:
-		switch (chan->type) {
-		case IIO_ANGL_VEL:
-			bits = 12;
-			break;
-		default:
-			return -EINVAL;
-		}
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16260_addresses[chan->scan_index][1];
-		ret = adis_read_reg_16(&st->adis, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-		*val = (1 << bits) - 1;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
-	}
-	return -EINVAL;
-}
-
-static int adis16260_write_raw(struct iio_dev *indio_dev,
-			       struct iio_chan_spec const *chan,
-			       int val,
-			       int val2,
-			       long mask)
-{
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int bits = 12;
-	s16 val16;
-	u8 addr;
-	switch (mask) {
-	case IIO_CHAN_INFO_CALIBBIAS:
-		val16 = val & ((1 << bits) - 1);
-		addr = adis16260_addresses[chan->scan_index][0];
-		return adis_write_reg_16(&st->adis, addr, val16);
-	case IIO_CHAN_INFO_CALIBSCALE:
-		val16 = val & ((1 << bits) - 1);
-		addr = adis16260_addresses[chan->scan_index][1];
-		return adis_write_reg_16(&st->adis, addr, val16);
-	}
-	return -EINVAL;
-}
-
-static struct attribute *adis16260_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group adis16260_attribute_group = {
-	.attrs = adis16260_attributes,
-};
-
-static const struct iio_info adis16260_info = {
-	.attrs = &adis16260_attribute_group,
-	.read_raw = &adis16260_read_raw,
-	.write_raw = &adis16260_write_raw,
-	.update_scan_mode = adis_update_scan_mode,
-	.driver_module = THIS_MODULE,
-};
-
-static const char * const adis1620_status_error_msgs[] = {
-	[ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
-	[ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
-	[ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
-	[ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
-	[ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
-	[ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
-	[ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
-};
-
-static const struct adis_data adis16260_data = {
-	.write_delay = 30,
-	.read_delay = 30,
-	.msc_ctrl_reg = ADIS16260_MSC_CTRL,
-	.glob_cmd_reg = ADIS16260_GLOB_CMD,
-	.diag_stat_reg = ADIS16260_DIAG_STAT,
-
-	.self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
-	.startup_delay = ADIS16260_STARTUP_DELAY,
-
-	.status_error_msgs = adis1620_status_error_msgs,
-	.status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
-		BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
-		BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
-		BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
-		BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
-		BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
-		BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
-};
-
-static int adis16260_probe(struct spi_device *spi)
-{
-	int ret;
-	struct adis16260_platform_data *pd = spi->dev.platform_data;
-	struct adis16260_state *st;
-	struct iio_dev *indio_dev;
-
-	/* setup the industrialio driver allocated elements */
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	st = iio_priv(indio_dev);
-	if (pd)
-		st->negate = pd->negate;
-	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, indio_dev);
-
-	indio_dev->name = spi_get_device_id(spi)->name;
-	indio_dev->dev.parent = &spi->dev;
-	indio_dev->info = &adis16260_info;
-	indio_dev->num_channels
-		= ARRAY_SIZE(adis16260_channels_x);
-	if (pd && pd->direction)
-		switch (pd->direction) {
-		case 'x':
-			indio_dev->channels = adis16260_channels_x;
-			break;
-		case 'y':
-			indio_dev->channels = adis16260_channels_y;
-			break;
-		case 'z':
-			indio_dev->channels = adis16260_channels_z;
-			break;
-		default:
-			return -EINVAL;
-		}
-	else
-		indio_dev->channels = adis16260_channels_x;
-	indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x);
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	ret = adis_init(&st->adis, indio_dev, spi, &adis16260_data);
-	if (ret)
-		goto error_free_dev;
-
-	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
-	if (ret)
-		goto error_free_dev;
-
-	if (indio_dev->buffer) {
-		/* Set default scan mode */
-		iio_scan_mask_set(indio_dev, indio_dev->buffer,
-				  ADIS16260_SCAN_SUPPLY);
-		iio_scan_mask_set(indio_dev, indio_dev->buffer,
-				  ADIS16260_SCAN_GYRO);
-		iio_scan_mask_set(indio_dev, indio_dev->buffer,
-				  ADIS16260_SCAN_AUX_ADC);
-		iio_scan_mask_set(indio_dev, indio_dev->buffer,
-				  ADIS16260_SCAN_TEMP);
-		iio_scan_mask_set(indio_dev, indio_dev->buffer,
-				  ADIS16260_SCAN_ANGL);
-	}
-
-	/* Get the device into a sane initial state */
-	ret = adis_initial_startup(&st->adis);
-	if (ret)
-		goto error_cleanup_buffer_trigger;
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		goto error_cleanup_buffer_trigger;
-
-	return 0;
-
-error_cleanup_buffer_trigger:
-	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
-}
-
-static int adis16260_remove(struct spi_device *spi)
-{
-	struct iio_dev *indio_dev = spi_get_drvdata(spi);
-	struct adis16260_state *st = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-	adis16260_stop_device(indio_dev);
-	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-/*
- * These parts do not need to be differentiated until someone adds
- * support for the on chip filtering.
- */
-static const struct spi_device_id adis16260_id[] = {
-	{"adis16260", 0},
-	{"adis16265", 0},
-	{"adis16250", 0},
-	{"adis16255", 0},
-	{"adis16251", 1},
-	{}
-};
-MODULE_DEVICE_TABLE(spi, adis16260_id);
-
-static struct spi_driver adis16260_driver = {
-	.driver = {
-		.name = "adis16260",
-		.owner = THIS_MODULE,
-	},
-	.probe = adis16260_probe,
-	.remove = adis16260_remove,
-	.id_table = adis16260_id,
-};
-module_spi_driver(adis16260_driver);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/gyro/adis16260_platform_data.h b/drivers/staging/iio/gyro/adis16260_platform_data.h
deleted file mode 100644
index 12802e9..0000000
--- a/drivers/staging/iio/gyro/adis16260_platform_data.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * ADIS16260 Programmable Digital Gyroscope Sensor Driver Platform Data
- *
- * Based on adis16255.h Matthia Brugger <m_brugger&web.de>
- *
- * Copyright (C) 2010 Fraunhofer Institute for Integrated Circuits
-  *
- * Licensed under the GPL-2 or later.
- */
-
-/**
- * struct adis16260_platform_data - instance specific data
- * @direction: x y or z
- * @negate: flag to indicate value should be inverted.
- **/
-struct adis16260_platform_data {
-	char direction;
-	unsigned negate:1;
-};
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 82478a5..351936c 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -550,11 +550,10 @@ static int isl29018_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	int err;
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
 	if (indio_dev == NULL) {
 		dev_err(&client->dev, "iio allocation fails\n");
-		err = -ENOMEM;
-		goto exit;
+		return -ENOMEM;
 	}
 	chip = iio_priv(indio_dev);
 
@@ -572,12 +571,12 @@ static int isl29018_probe(struct i2c_client *client,
 	if (IS_ERR(chip->regmap)) {
 		err = PTR_ERR(chip->regmap);
 		dev_err(chip->dev, "regmap initialization failed: %d\n", err);
-		goto exit;
+		return err;
 	}
 
 	err = isl29018_chip_init(chip);
 	if (err)
-		goto exit_iio_free;
+		return err;
 
 	indio_dev->info = &isl29108_info;
 	indio_dev->channels = isl29018_channels;
@@ -588,14 +587,10 @@ static int isl29018_probe(struct i2c_client *client,
 	err = iio_device_register(indio_dev);
 	if (err) {
 		dev_err(&client->dev, "iio registration fails\n");
-		goto exit_iio_free;
+		return err;
 	}
 
 	return 0;
-exit_iio_free:
-	iio_device_free(indio_dev);
-exit:
-	return err;
 }
 
 static int isl29018_remove(struct i2c_client *client)
@@ -604,7 +599,6 @@ static int isl29018_remove(struct i2c_client *client)
 
 	dev_dbg(&client->dev, "%s()\n", __func__);
 	iio_device_unregister(indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
index 8bb0d03..6014625 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/staging/iio/light/isl29028.c
@@ -482,7 +482,7 @@ static int isl29028_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
 	if (!indio_dev) {
 		dev_err(&client->dev, "iio allocation fails\n");
 		return -ENOMEM;
@@ -498,13 +498,13 @@ static int isl29028_probe(struct i2c_client *client,
 	if (IS_ERR(chip->regmap)) {
 		ret = PTR_ERR(chip->regmap);
 		dev_err(chip->dev, "regmap initialization failed: %d\n", ret);
-		goto exit_iio_free;
+		return ret;
 	}
 
 	ret = isl29028_chip_init(chip);
 	if (ret < 0) {
 		dev_err(chip->dev, "chip initialization failed: %d\n", ret);
-		goto exit_iio_free;
+		return ret;
 	}
 
 	indio_dev->info = &isl29028_info;
@@ -517,13 +517,9 @@ static int isl29028_probe(struct i2c_client *client,
 	if (ret < 0) {
 		dev_err(chip->dev, "iio registration fails with error %d\n",
 			ret);
-		goto exit_iio_free;
+		return ret;
 	}
 	return 0;
-
-exit_iio_free:
-	iio_device_free(indio_dev);
-	return ret;
 }
 
 static int isl29028_remove(struct i2c_client *client)
@@ -531,7 +527,6 @@ static int isl29028_remove(struct i2c_client *client)
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	iio_device_unregister(indio_dev);
-	iio_device_free(indio_dev);
 	return 0;
 }
 
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 86c6bf9..d2748c3 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -20,12 +20,10 @@
 */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/types.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/delay.h>
 
 #define HMC5843_CONFIG_REG_A			0x00
 #define HMC5843_CONFIG_REG_B			0x01
@@ -42,9 +40,6 @@
 #define HMC5883_DATA_OUT_Y_MSB_REG		0x07
 #define HMC5883_DATA_OUT_Y_LSB_REG		0x08
 #define HMC5843_STATUS_REG			0x09
-#define HMC5843_ID_REG_A			0x0A
-#define HMC5843_ID_REG_B			0x0B
-#define HMC5843_ID_REG_C			0x0C
 
 enum hmc5843_ids {
 	HMC5843_ID,
@@ -53,14 +48,6 @@ enum hmc5843_ids {
 };
 
 /*
- * Beware: identification of the HMC5883 is still "H43";
- * I2C address is also unchanged
- */
-#define HMC5843_ID_REG_LENGTH			0x03
-#define HMC5843_ID_STRING			"H43"
-#define HMC5843_I2C_ADDRESS			0x1E
-
-/*
  * Range gain settings in (+-)Ga
  * Beware: HMC5843 and HMC5883 have different recommended sensor field
  * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively
@@ -185,14 +172,9 @@ static const char * const hmc5883_regval_to_sample_freq[] = {
 	"0.75", "1.5", "3", "7.5", "15", "30", "75",
 };
 
-/* Addresses to scan: 0x1E */
-static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS,
-					     I2C_CLIENT_END };
-
 /* Describe chip variants */
 struct hmc5843_chip_info {
 	const struct iio_chan_spec *channels;
-	int num_channels;
 	const char * const *regval_to_sample_freq;
 	const int *regval_to_input_field_mga;
 	const int *regval_to_nanoscale;
@@ -225,18 +207,29 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev,
 	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
 	struct hmc5843_data *data = iio_priv(indio_dev);
 	s32 result;
+	int tries = 150;
 
 	mutex_lock(&data->lock);
-	result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
-	while (!(result & HMC5843_DATA_READY))
-		result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
+	while (tries-- > 0) {
+		result = i2c_smbus_read_byte_data(client,
+			HMC5843_STATUS_REG);
+		if (result & HMC5843_DATA_READY)
+			break;
+		msleep(20);
+	}
+
+	if (tries < 0) {
+		dev_err(&client->dev, "data not ready\n");
+		mutex_unlock(&data->lock);
+		return -EIO;
+	}
 
-	result = i2c_smbus_read_word_data(client, address);
+	result = i2c_smbus_read_word_swapped(client, address);
 	mutex_unlock(&data->lock);
 	if (result < 0)
 		return -EINVAL;
 
-	*val = (s16)swab16((u16)result);
+	*val = result;
 	return IIO_VAL_INT;
 }
 
@@ -559,14 +552,14 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
 	return -EINVAL;
 }
 
-#define HMC5843_CHANNEL(axis, add)					\
+#define HMC5843_CHANNEL(axis, addr)					\
 	{								\
 		.type = IIO_MAGN,					\
 		.modified = 1,						\
 		.channel2 = IIO_MOD_##axis,				\
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
-		.address = add						\
+		.address = addr						\
 	}
 
 static const struct iio_chan_spec hmc5843_channels[] = {
@@ -597,7 +590,6 @@ static const struct attribute_group hmc5843_group = {
 static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 	[HMC5843_ID] = {
 		.channels = hmc5843_channels,
-		.num_channels = ARRAY_SIZE(hmc5843_channels),
 		.regval_to_sample_freq = hmc5843_regval_to_sample_freq,
 		.regval_to_input_field_mga =
 			hmc5843_regval_to_input_field_mga,
@@ -605,7 +597,6 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 	},
 	[HMC5883_ID] = {
 		.channels = hmc5883_channels,
-		.num_channels = ARRAY_SIZE(hmc5883_channels),
 		.regval_to_sample_freq = hmc5883_regval_to_sample_freq,
 		.regval_to_input_field_mga =
 			hmc5883_regval_to_input_field_mga,
@@ -613,7 +604,6 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 	},
 	[HMC5883L_ID] = {
 		.channels = hmc5883_channels,
-		.num_channels = ARRAY_SIZE(hmc5883_channels),
 		.regval_to_sample_freq = hmc5883_regval_to_sample_freq,
 		.regval_to_input_field_mga =
 			hmc5883l_regval_to_input_field_mga,
@@ -621,25 +611,6 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 	},
 };
 
-static int hmc5843_detect(struct i2c_client *client,
-			  struct i2c_board_info *info)
-{
-	unsigned char id_str[HMC5843_ID_REG_LENGTH];
-
-	if (client->addr != HMC5843_I2C_ADDRESS)
-		return -ENODEV;
-
-	if (i2c_smbus_read_i2c_block_data(client, HMC5843_ID_REG_A,
-				HMC5843_ID_REG_LENGTH, id_str)
-			!= HMC5843_ID_REG_LENGTH)
-		return -ENODEV;
-
-	if (0 != strncmp(id_str, HMC5843_ID_STRING, HMC5843_ID_REG_LENGTH))
-		return -ENODEV;
-
-	return 0;
-}
-
 /* Called when we have found a new HMC58X3 */
 static void hmc5843_init_client(struct i2c_client *client,
 				const struct i2c_device_id *id)
@@ -649,7 +620,7 @@ static void hmc5843_init_client(struct i2c_client *client,
 
 	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
 	indio_dev->channels = data->variant->channels;
-	indio_dev->num_channels = data->variant->num_channels;
+	indio_dev->num_channels = 3;
 	hmc5843_set_meas_conf(client, data->meas_conf);
 	hmc5843_set_rate(client, data->rate);
 	hmc5843_configure(client, data->operating_mode);
@@ -756,8 +727,6 @@ static struct i2c_driver hmc5843_driver = {
 	.id_table	= hmc5843_id,
 	.probe		= hmc5843_probe,
 	.remove		= hmc5843_remove,
-	.detect		= hmc5843_detect,
-	.address_list	= normal_i2c,
 };
 module_i2c_driver(hmc5843_driver);
 
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index e5943e2..74025fb 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -225,21 +225,6 @@ static int ade7753_reset(struct device *dev)
 	return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val);
 }
 
-static ssize_t ade7753_write_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	if (len < 1)
-		return -1;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return ade7753_reset(dev);
-	}
-	return -1;
-}
-
 static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY);
 static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY);
 static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY);
@@ -458,8 +443,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 		ade7753_read_frequency,
 		ade7753_write_frequency);
 
-static IIO_DEV_ATTR_RESET(ade7753_write_reset);
-
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
 
 static struct attribute *ade7753_attributes[] = {
@@ -468,7 +451,6 @@ static struct attribute *ade7753_attributes[] = {
 	&iio_const_attr_in_temp_scale.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_phcal.dev_attr.attr,
 	&iio_dev_attr_cfden.dev_attr.attr,
 	&iio_dev_attr_aenergy.dev_attr.attr,
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 7b6503b..f649ebe 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -224,22 +224,6 @@ static int ade7754_reset(struct device *dev)
 	return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
 }
 
-
-static ssize_t ade7754_write_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	if (len < 1)
-		return -1;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return ade7754_reset(dev);
-	}
-	return -1;
-}
-
 static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY);
 static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY);
 static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY);
@@ -478,8 +462,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 		ade7754_read_frequency,
 		ade7754_write_frequency);
 
-static IIO_DEV_ATTR_RESET(ade7754_write_reset);
-
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000");
 
 static struct attribute *ade7754_attributes[] = {
@@ -488,7 +470,6 @@ static struct attribute *ade7754_attributes[] = {
 	&iio_const_attr_in_temp_scale.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_aenergy.dev_attr.attr,
 	&iio_dev_attr_laenergy.dev_attr.attr,
 	&iio_dev_attr_vaenergy.dev_attr.attr,
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 8f5bcfa..6005d4a 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -313,21 +313,6 @@ static int ade7758_reset(struct device *dev)
 	return ret;
 }
 
-static ssize_t ade7758_write_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	if (len < 1)
-		return -1;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return ade7758_reset(dev);
-	}
-	return len;
-}
-
 static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
 		ade7758_read_8bit,
 		ade7758_write_8bit,
@@ -591,8 +576,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 		ade7758_read_frequency,
 		ade7758_write_frequency);
 
-static IIO_DEV_ATTR_RESET(ade7758_write_reset);
-
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255");
 
 static struct attribute *ade7758_attributes[] = {
@@ -601,7 +584,6 @@ static struct attribute *ade7758_attributes[] = {
 	&iio_const_attr_in_temp_scale.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_awatthr.dev_attr.attr,
 	&iio_dev_attr_bwatthr.dev_attr.attr,
 	&iio_dev_attr_cwatthr.dev_attr.attr,
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index b29e2d5..7d5db71 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -54,7 +54,7 @@ out:
 	return ret;
 }
 
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
+/* Whilst this makes a lot of calls to iio_sw_ring functions - it is too device
  * specific to be rolled into the core.
  */
 static irqreturn_t ade7758_trigger_handler(int irq, void *p)
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index 17dc373..d214ac4 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -229,21 +229,6 @@ static int ade7759_reset(struct device *dev)
 	return ret;
 }
 
-static ssize_t ade7759_write_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	if (len < 1)
-		return -1;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return ade7759_reset(dev);
-	}
-	return -1;
-}
-
 static IIO_DEV_ATTR_AENERGY(ade7759_read_40bit, ADE7759_AENERGY);
 static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO,
 		ade7759_read_16bit,
@@ -418,8 +403,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 		ade7759_read_frequency,
 		ade7759_write_frequency);
 
-static IIO_DEV_ATTR_RESET(ade7759_write_reset);
-
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
 
 static struct attribute *ade7759_attributes[] = {
@@ -428,7 +411,6 @@ static struct attribute *ade7759_attributes[] = {
 	&iio_const_attr_in_temp_scale.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_phcal.dev_attr.attr,
 	&iio_dev_attr_cfden.dev_attr.attr,
 	&iio_dev_attr_aenergy.dev_attr.attr,
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index c642da8..e8379c0 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -186,22 +186,6 @@ static int ade7854_reset(struct device *dev)
 	return st->write_reg_16(dev, ADE7854_CONFIG, val);
 }
 
-
-static ssize_t ade7854_write_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	if (len < 1)
-		return -1;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return ade7854_reset(dev);
-	}
-	return -1;
-}
-
 static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO,
 		ade7854_read_24bit,
 		ade7854_write_24bit,
@@ -468,8 +452,6 @@ err_ret:
 	return ret;
 }
 
-static IIO_DEV_ATTR_RESET(ade7854_write_reset);
-
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000");
 
 static IIO_CONST_ATTR(name, "ade7854");
@@ -515,7 +497,6 @@ static struct attribute *ade7854_attributes[] = {
 	&iio_dev_attr_bvahr.dev_attr.attr,
 	&iio_dev_attr_cvahr.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_const_attr_name.dev_attr.attr,
 	&iio_dev_attr_vpeak.dev_attr.attr,
 	&iio_dev_attr_ipeak.dev_attr.attr,
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 0d3356d..dcdadbb 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -192,21 +192,6 @@ static inline int ad2s1210_soft_reset(struct ad2s1210_state *st)
 	return ad2s1210_config_write(st, 0x0);
 }
 
-static ssize_t ad2s1210_store_softreset(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf,
-					size_t len)
-{
-	struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
-	int ret;
-
-	mutex_lock(&st->lock);
-	ret = ad2s1210_soft_reset(st);
-	mutex_unlock(&st->lock);
-
-	return ret < 0 ? ret : len;
-}
-
 static ssize_t ad2s1210_show_fclkin(struct device *dev,
 				    struct device_attribute *attr,
 				    char *buf)
@@ -536,8 +521,6 @@ error_ret:
 	return ret;
 }
 
-static IIO_DEVICE_ATTR(reset, S_IWUSR,
-		       NULL, ad2s1210_store_softreset, 0);
 static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR,
 		       ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0);
 static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUSR,
@@ -587,7 +570,6 @@ static const struct iio_chan_spec ad2s1210_channels[] = {
 };
 
 static struct attribute *ad2s1210_attributes[] = {
-	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_fclkin.dev_attr.attr,
 	&iio_dev_attr_fexcit.dev_attr.attr,
 	&iio_dev_attr_control.dev_attr.attr,
diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig
index bd0f2fd..394254f 100644
--- a/drivers/staging/imx-drm/Kconfig
+++ b/drivers/staging/imx-drm/Kconfig
@@ -15,7 +15,7 @@ config DRM_IMX_FB_HELPER
 	help
 	  The DRM framework can provide a legacy /dev/fb0 framebuffer
 	  for your device. This is necessary to get a framebuffer console
-	  and also for appplications using the legacy framebuffer API
+	  and also for applications using the legacy framebuffer API
 
 config DRM_IMX_PARALLEL_DISPLAY
 	tristate "Support for parallel displays"
@@ -32,7 +32,7 @@ config DRM_IMX_TVE
 
 config DRM_IMX_LDB
 	tristate "Support for LVDS displays"
-	depends on DRM_IMX
+	depends on DRM_IMX && MFD_SYSCON
 	help
 	  Choose this to enable the internal LVDS Display Bridge (LDB)
 	  found on i.MX53 and i.MX6 processors.
diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO
index f806415..9cfa2a7 100644
--- a/drivers/staging/imx-drm/TODO
+++ b/drivers/staging/imx-drm/TODO
@@ -10,7 +10,6 @@ TODO:
 Missing features (not necessarily for moving out of staging):
 
 - Add KMS plane support for CRTC driver
-- Add LDB (LVDS Display Bridge) support
 - Add i.MX6 HDMI support
 - Add support for IC (Image converter)
 - Add support for CSI (CMOS Sensor interface)
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 9854a1d..9142f50 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -69,28 +69,20 @@ struct imx_drm_connector {
 	struct module				*owner;
 };
 
-static int imx_drm_driver_firstopen(struct drm_device *drm)
-{
-	if (!imx_drm_device_get())
-		return -EINVAL;
-
-	return 0;
-}
-
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
 
 	if (imxdrm->fbhelper)
 		drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
-
-	imx_drm_device_put();
 }
 
 static int imx_drm_driver_unload(struct drm_device *drm)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
 
+	imx_drm_device_put();
+
 	drm_mode_config_cleanup(imxdrm->drm);
 	drm_kms_helper_poll_fini(imxdrm->drm);
 
@@ -226,8 +218,6 @@ struct drm_device *imx_drm_device_get(void)
 	struct imx_drm_connector *con;
 	struct imx_drm_crtc *crtc;
 
-	mutex_lock(&imxdrm->mutex);
-
 	list_for_each_entry(enc, &imxdrm->encoder_list, list) {
 		if (!try_module_get(enc->owner)) {
 			dev_err(imxdrm->dev, "could not get module %s\n",
@@ -254,8 +244,6 @@ struct drm_device *imx_drm_device_get(void)
 
 	imxdrm->references++;
 
-	mutex_unlock(&imxdrm->mutex);
-
 	return imxdrm->drm;
 
 unwind_crtc:
@@ -447,6 +435,9 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 	 */
 	imxdrm->drm->vblank_disable_allowed = 1;
 
+	if (!imx_drm_device_get())
+		ret = -EINVAL;
+
 	ret = 0;
 
 err_init:
@@ -678,6 +669,7 @@ found:
 
 	return i;
 }
+EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
 
 /*
  * imx_drm_remove_encoder - remove an encoder
@@ -783,7 +775,7 @@ int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
 }
 EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
 
-static struct drm_ioctl_desc imx_drm_ioctls[] = {
+static const struct drm_ioctl_desc imx_drm_ioctls[] = {
 	/* none so far */
 };
 
@@ -791,13 +783,12 @@ static struct drm_driver imx_drm_driver = {
 	.driver_features	= DRIVER_MODESET | DRIVER_GEM,
 	.load			= imx_drm_driver_load,
 	.unload			= imx_drm_driver_unload,
-	.firstopen		= imx_drm_driver_firstopen,
 	.lastclose		= imx_drm_driver_lastclose,
 	.gem_free_object	= drm_gem_cma_free_object,
 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
 	.dumb_create		= drm_gem_cma_dumb_create,
 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
-	.dumb_destroy		= drm_gem_cma_dumb_destroy,
+	.dumb_destroy		= drm_gem_dumb_destroy,
 
 	.get_vblank_counter	= drm_vblank_count,
 	.enable_vblank		= imx_drm_enable_vblank,
diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
index 8af7f3b..bb7da0e 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -497,7 +497,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
 		imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
 
 	/*
-	 * There are three diferent possible clock mux configurations:
+	 * There are three different possible clock mux configurations:
 	 * i.MX53:  ipu1_di0_sel, ipu1_di1_sel
 	 * i.MX6q:  ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel
 	 * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index a56797d..12a3940d 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -131,12 +131,14 @@ struct imx_tve {
 };
 
 static void tve_lock(void *__tve)
+__acquires(&tve->lock)
 {
 	struct imx_tve *tve = __tve;
 	spin_lock(&tve->lock);
 }
 
 static void tve_unlock(void *__tve)
+__releases(&tve->lock)
 {
 	struct imx_tve *tve = __tve;
 	spin_unlock(&tve->lock);
@@ -623,11 +625,6 @@ static int imx_tve_probe(struct platform_device *pdev)
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get memory region\n");
-		return -ENOENT;
-	}
-
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index e35d0bf..ba464e5 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -1075,21 +1075,23 @@ static int ipu_probe(struct platform_device *pdev)
 	ipu->cpmem_base = devm_ioremap(&pdev->dev,
 			ipu_base + devtype->cpmem_ofs, PAGE_SIZE);
 
-	if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) {
-		ret = -ENOMEM;
-		goto failed_ioremap;
-	}
+	if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base)
+		return -ENOMEM;
 
 	ipu->clk = devm_clk_get(&pdev->dev, "bus");
 	if (IS_ERR(ipu->clk)) {
 		ret = PTR_ERR(ipu->clk);
 		dev_err(&pdev->dev, "clk_get failed with %d", ret);
-		goto failed_clk_get;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, ipu);
 
-	clk_prepare_enable(ipu->clk);
+	ret = clk_prepare_enable(ipu->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
+		return ret;
+	}
 
 	ipu->dev = &pdev->dev;
 	ipu->irq_sync = irq_sync;
@@ -1134,8 +1136,6 @@ out_failed_reset:
 	ipu_irq_exit(ipu);
 out_failed_irq:
 	clk_disable_unprepare(ipu->clk);
-failed_clk_get:
-failed_ioremap:
 	return ret;
 }
 
@@ -1163,6 +1163,7 @@ static struct platform_driver imx_ipu_driver = {
 
 module_platform_driver(imx_ipu_driver);
 
+MODULE_ALIAS("platform:imx-ipuv3");
 MODULE_DESCRIPTION("i.MX IPU v3 driver");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
index 113b046..231afd6 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
@@ -46,6 +46,8 @@
 #define DP_COM_CONF_CSC_DEF_BG		(2 << 8)
 #define DP_COM_CONF_CSC_DEF_BOTH	(1 << 8)
 
+#define IPUV3_NUM_FLOWS		3
+
 struct ipu_dp_priv;
 
 struct ipu_dp {
@@ -67,7 +69,7 @@ struct ipu_dp_priv {
 	struct ipu_soc *ipu;
 	struct device *dev;
 	void __iomem *base;
-	struct ipu_flow flow[3];
+	struct ipu_flow flow[IPUV3_NUM_FLOWS];
 	struct mutex mutex;
 	int use_count;
 };
@@ -280,7 +282,7 @@ struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
 	struct ipu_dp_priv *priv = ipu->dp_priv;
 	struct ipu_dp *dp;
 
-	if (flow > 5)
+	if ((flow >> 1) >= IPUV3_NUM_FLOWS)
 		return ERR_PTR(-EINVAL);
 
 	if (flow & 1)
@@ -309,19 +311,20 @@ int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
 	int i;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 	priv->dev = dev;
 	priv->ipu = ipu;
 
 	ipu->dp_priv = priv;
 
 	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-	if (!priv->base) {
+	if (!priv->base)
 		return -ENOMEM;
-	}
 
 	mutex_init(&priv->mutex);
 
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
 		priv->flow[i].foreground.foreground = 1;
 		priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
 		priv->flow[i].priv = priv;
diff --git a/drivers/staging/lustre/Makefile b/drivers/staging/lustre/Makefile
index 2616289..fb0e0fa 100644
--- a/drivers/staging/lustre/Makefile
+++ b/drivers/staging/lustre/Makefile
@@ -1,4 +1,4 @@
 subdir-ccflags-y := -I$(src)/include/
 
-obj-$(CONFIG_LUSTRE_FS)		+= lustre/
 obj-$(CONFIG_LNET)		+= lnet/
+obj-$(CONFIG_LUSTRE_FS)		+= lustre/
diff --git a/drivers/staging/lustre/include/linux/libcfs/bitmap.h b/drivers/staging/lustre/include/linux/libcfs/bitmap.h
index 3f1c37b..f3d4a89 100644
--- a/drivers/staging/lustre/include/linux/libcfs/bitmap.h
+++ b/drivers/staging/lustre/include/linux/libcfs/bitmap.h
@@ -52,11 +52,11 @@ cfs_bitmap_t *CFS_ALLOCATE_BITMAP(int size)
 
 	OBD_ALLOC(ptr, CFS_BITMAP_SIZE(size));
 	if (ptr == NULL)
-		RETURN(ptr);
+		return ptr;
 
 	ptr->size = size;
 
-	RETURN (ptr);
+	return ptr;
 }
 
 #define CFS_FREE_BITMAP(ptr)	OBD_FREE(ptr, CFS_BITMAP_SIZE(ptr->size))
diff --git a/drivers/staging/lustre/include/linux/libcfs/curproc.h b/drivers/staging/lustre/include/linux/libcfs/curproc.h
index 90d7ce6..de8e35b 100644
--- a/drivers/staging/lustre/include/linux/libcfs/curproc.h
+++ b/drivers/staging/lustre/include/linux/libcfs/curproc.h
@@ -49,8 +49,6 @@
  * Implemented in portals/include/libcfs/<os>/
  */
 int    cfs_curproc_groups_nr(void);
-int    current_is_in_group(gid_t group);
-void   cfs_curproc_groups_dump(gid_t *array, int size);
 
 /*
  * Plus, platform-specific constant
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h
index 1ab1f2b..687dbab 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h
@@ -80,26 +80,10 @@ static inline int __is_po2(unsigned long long val)
 #define LERRCHKSUM(hexnum) (((hexnum) & 0xf) ^ ((hexnum) >> 4 & 0xf) ^ \
 			   ((hexnum) >> 8 & 0xf))
 
-
-/*
- * Some (nomina odiosa sunt) platforms define NULL as naked 0. This confuses
- * Lustre RETURN(NULL) macro.
- */
-#if defined(NULL)
-#undef NULL
-#endif
-
-#define NULL ((void *)0)
-
 #define LUSTRE_SRV_LNET_PID      LUSTRE_LNET_PID
 
-
 #include <linux/list.h>
 
-#ifndef cfs_for_each_possible_cpu
-#  error cfs_for_each_possible_cpu is not supported by kernel!
-#endif
-
 /* libcfs tcpip */
 int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask);
 int libcfs_ipif_enumerate(char ***names);
@@ -117,31 +101,6 @@ int libcfs_sock_write(socket_t *sock, void *buffer, int nob, int timeout);
 int libcfs_sock_read(socket_t *sock, void *buffer, int nob, int timeout);
 void libcfs_sock_release(socket_t *sock);
 
-/* libcfs watchdogs */
-struct lc_watchdog;
-
-/* Add a watchdog which fires after "time" milliseconds of delay.  You have to
- * touch it once to enable it. */
-struct lc_watchdog *lc_watchdog_add(int time,
-				    void (*cb)(pid_t pid, void *),
-				    void *data);
-
-/* Enables a watchdog and resets its timer. */
-void lc_watchdog_touch(struct lc_watchdog *lcw, int timeout);
-#define CFS_GET_TIMEOUT(svc) (max_t(int, obd_timeout,		   \
-			  AT_OFF ? 0 : at_get(&svc->srv_at_estimate)) * \
-			  svc->srv_watchdog_factor)
-
-/* Disable a watchdog; touch it to restart it. */
-void lc_watchdog_disable(struct lc_watchdog *lcw);
-
-/* Clean up the watchdog */
-void lc_watchdog_delete(struct lc_watchdog *lcw);
-
-/* Dump a debug log */
-void lc_watchdog_dumplog(pid_t pid, void *data);
-
-
 /* need both kernel and user-land acceptor */
 #define LNET_ACCEPTOR_MIN_RESERVED_PORT    512
 #define LNET_ACCEPTOR_MAX_RESERVED_PORT    1023
@@ -149,11 +108,6 @@ void lc_watchdog_dumplog(pid_t pid, void *data);
 /*
  * libcfs pseudo device operations
  *
- * struct psdev_t and
- * misc_register() and
- * misc_deregister() are declared in
- * libcfs/<os>/<os>-prim.h
- *
  * It's just draft now.
  */
 
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h
index 6ae7415..c87efb4 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h
@@ -75,11 +75,19 @@
 #ifndef __LIBCFS_CPU_H__
 #define __LIBCFS_CPU_H__
 
-#ifndef HAVE_LIBCFS_CPT
-
-typedef unsigned long		cpumask_t;
-typedef unsigned long		nodemask_t;
+/* any CPU partition */
+#define CFS_CPT_ANY		(-1)
 
+#ifdef CONFIG_SMP
+/**
+ * return cpumask of CPU partition \a cpt
+ */
+cpumask_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt);
+/**
+ * print string information of cpt-table
+ */
+int cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len);
+#else /* !CONFIG_SMP */
 struct cfs_cpt_table {
 	/* # of CPU partitions */
 	int			ctb_nparts;
@@ -91,10 +99,18 @@ struct cfs_cpt_table {
 	__u64			ctb_version;
 };
 
-#endif /* !HAVE_LIBCFS_CPT */
+static inline cpumask_t *
+cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt)
+{
+       return NULL;
+}
 
-/* any CPU partition */
-#define CFS_CPT_ANY		(-1)
+static inline int
+cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len)
+{
+       return 0;
+}
+#endif /* CONFIG_SMP */
 
 extern struct cfs_cpt_table	*cfs_cpt_table;
 
@@ -107,10 +123,6 @@ void cfs_cpt_table_free(struct cfs_cpt_table *cptab);
  */
 struct cfs_cpt_table *cfs_cpt_table_alloc(unsigned int ncpt);
 /**
- * print string information of cpt-table
- */
-int cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len);
-/**
  * return total number of CPU partitions in \a cptab
  */
 int
@@ -124,10 +136,6 @@ int cfs_cpt_weight(struct cfs_cpt_table *cptab, int cpt);
  */
 int cfs_cpt_online(struct cfs_cpt_table *cptab, int cpt);
 /**
- * return cpumask of CPU partition \a cpt
- */
-cpumask_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt);
-/**
  * return nodemask of CPU partition \a cpt
  */
 nodemask_t *cfs_cpt_nodemask(struct cfs_cpt_table *cptab, int cpt);
@@ -200,14 +208,6 @@ int cfs_cpt_spread_node(struct cfs_cpt_table *cptab, int cpt);
 #define cfs_cpt_for_each(i, cptab)	\
 	for (i = 0; i < cfs_cpt_number(cptab); i++)
 
-#ifndef __read_mostly
-# define __read_mostly
-#endif
-
-#ifndef ____cacheline_aligned
-#define ____cacheline_aligned
-#endif
-
 int  cfs_cpu_init(void);
 void cfs_cpu_fini(void);
 
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
index dd8ac2f..e6439d1 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
@@ -262,74 +262,6 @@ do {								    \
 } while (0)
 
 
-/*
- * if rc == NULL, we need to code as RETURN((void *)NULL), otherwise
- * there will be a warning in osx.
- */
-#if defined(__GNUC__)
-
-long libcfs_log_return(struct libcfs_debug_msg_data *, long rc);
-#if BITS_PER_LONG > 32
-#define RETURN(rc)							\
-do {									\
-	EXIT_NESTING;							\
-	if (cfs_cdebug_show(D_TRACE, DEBUG_SUBSYSTEM)) {		\
-		LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_TRACE, NULL);	\
-		return (typeof(rc))libcfs_log_return(&msgdata,		\
-						     (long)(rc));	\
-	}								\
-									\
-	return (rc);							\
-} while (0)
-#else /* BITS_PER_LONG == 32 */
-/* We need an on-stack variable, because we cannot case a 32-bit pointer
- * directly to (long long) without generating a complier warning/error, yet
- * casting directly to (long) will truncate 64-bit return values. The log
- * values will print as 32-bit values, but they always have been. LU-1436
- */
-#define RETURN(rc)							\
-do {									\
-	EXIT_NESTING;							\
-	if (cfs_cdebug_show(D_TRACE, DEBUG_SUBSYSTEM)) {		\
-		typeof(rc) __rc = (rc);					\
-		LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_TRACE, NULL);	\
-		libcfs_log_return(&msgdata, (long_ptr_t)__rc);		\
-		return __rc;						\
-	}								\
-									\
-	return (rc);							\
-} while (0)
-#endif /* BITS_PER_LONG > 32 */
-
-#elif defined(_MSC_VER)
-#define RETURN(rc)						      \
-do {								    \
-	CDEBUG(D_TRACE, "Process leaving.\n");			  \
-	EXIT_NESTING;						   \
-	return (rc);						    \
-} while (0)
-#else
-# error "Unkown compiler"
-#endif /* __GNUC__ */
-
-#define ENTRY							   \
-ENTRY_NESTING;							  \
-do {								    \
-	CDEBUG(D_TRACE, "Process entered\n");			   \
-} while (0)
-
-#define EXIT							    \
-do {								    \
-	CDEBUG(D_TRACE, "Process leaving\n");			   \
-	EXIT_NESTING;						   \
-} while(0)
-
-#define RETURN_EXIT							\
-do {									\
-	EXIT;								\
-	return;								\
-} while (0)
-
 extern int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata,
 			    const char *format1, ...)
 	__attribute__ ((format (printf, 2, 3)));
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h
index 9c40ed9..e6e417a 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h
@@ -40,10 +40,6 @@
 #ifndef __LIBCFS_PRIM_H__
 #define __LIBCFS_PRIM_H__
 
-#ifndef EXPORT_SYMBOL
-# define EXPORT_SYMBOL(s)
-#endif
-
 /*
  * Schedule
  */
@@ -53,20 +49,20 @@ void cfs_pause(cfs_duration_t ticks);
  * Timer
  */
 typedef  void (cfs_timer_func_t)(ulong_ptr_t);
-void schedule_timeout_and_set_state(cfs_task_state_t, int64_t);
+void schedule_timeout_and_set_state(long, int64_t);
 
 void init_waitqueue_entry_current(wait_queue_t *link);
-int64_t waitq_timedwait(wait_queue_t *, cfs_task_state_t, int64_t);
-void waitq_wait(wait_queue_t *, cfs_task_state_t);
+int64_t waitq_timedwait(wait_queue_t *, long, int64_t);
+void waitq_wait(wait_queue_t *, long);
 void add_wait_queue_exclusive_head(wait_queue_head_t *, wait_queue_t *);
 
-void cfs_init_timer(timer_list_t *t);
-void cfs_timer_init(timer_list_t *t, cfs_timer_func_t *func, void *arg);
-void cfs_timer_done(timer_list_t *t);
-void cfs_timer_arm(timer_list_t *t, cfs_time_t deadline);
-void cfs_timer_disarm(timer_list_t *t);
-int  cfs_timer_is_armed(timer_list_t *t);
-cfs_time_t cfs_timer_deadline(timer_list_t *t);
+void cfs_init_timer(struct timer_list *t);
+void cfs_timer_init(struct timer_list *t, cfs_timer_func_t *func, void *arg);
+void cfs_timer_done(struct timer_list *t);
+void cfs_timer_arm(struct timer_list *t, cfs_time_t deadline);
+void cfs_timer_disarm(struct timer_list *t);
+int  cfs_timer_is_armed(struct timer_list *t);
+cfs_time_t cfs_timer_deadline(struct timer_list *t);
 
 /*
  * Memory
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
index 056caa4..b033aa4 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
@@ -210,7 +210,6 @@ do {								    \
 #define ntohs(x) ___ntohs(x)
 #endif
 
-void libcfs_debug_dumpstack(task_t *tsk);
 void libcfs_run_upcall(char **argv);
 void libcfs_run_lbug_upcall(struct libcfs_debug_msg_data *);
 void libcfs_debug_dumplog(void);
@@ -456,10 +455,6 @@ int	 cfs_match_nid(lnet_nid_t nid, struct list_head *list);
 /* logical equivalence */
 #define equi(a, b) (!!(a) == !!(b))
 
-#ifndef CFS_CURRENT_TIME
-# define CFS_CURRENT_TIME time(0)
-#endif
-
 /* --------------------------------------------------------------------
  * Light-weight trace
  * Support for temporary event tracing with minimal Heisenberg effect.
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h
index 4b7ae1c..073f4d1 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h
@@ -55,7 +55,6 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/rwsem.h>
@@ -74,34 +73,6 @@
 #include <linux/libcfs/linux/portals_compat25.h>
 
 
-#define prepare_work(wq,cb,cbdata)					    \
-do {									  \
-	INIT_WORK((wq), (void *)(cb));					\
-} while (0)
-
-#define cfs_get_work_data(type,field,data) container_of(data,type,field)
-
-
-#define our_recalc_sigpending(current) recalc_sigpending()
-#define strtok(a,b) strpbrk(a, b)
-#define work_struct_t      struct work_struct
-
-#ifdef CONFIG_SMP
-#else
-#endif
-
-
-#define SEM_COUNT(sem)	  ((sem)->count)
-
-
-/* ------------------------------------------------------------------- */
-
-#define PORTAL_SYMBOL_REGISTER(x)
-#define PORTAL_SYMBOL_UNREGISTER(x)
-
-
-
-
 /******************************************************************************/
 /* Module parameter support */
 #define CFS_MODULE_PARM(name, t, type, perm, desc) \
@@ -111,26 +82,6 @@ do {									  \
 #define CFS_SYSFS_MODULE_PARM  1 /* module parameters accessible via sysfs */
 
 /******************************************************************************/
-
-#if (__GNUC__)
-/* Use the special GNU C __attribute__ hack to have the compiler check the
- * printf style argument string against the actual argument count and
- * types.
- */
-#ifdef printf
-# warning printf has been defined as a macro...
-# undef printf
-#endif
-
-#endif /* __GNUC__ */
-
-# define fprintf(a, format, b...) CDEBUG(D_OTHER, format , ## b)
-# define printf(format, b...) CDEBUG(D_OTHER, format , ## b)
-# define time(a) CURRENT_TIME
-
-# define cfs_num_present_cpus()  num_present_cpus()
-
-/******************************************************************************/
 /* Light-weight trace
  * Support for temporary event tracing with minimal Heisenberg effect. */
 #define LWT_SUPPORT  0
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h
index 292a3ba..60ecaf6 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h
@@ -97,9 +97,6 @@ do {								    \
 /* initial pid  */
 #define LUSTRE_LNET_PID	  12345
 
-#define ENTRY_NESTING_SUPPORT (1)
-#define ENTRY_NESTING   do {;} while (0)
-#define EXIT_NESTING   do {;} while (0)
 #define __current_nesting_level() (0)
 
 /**
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h
index 224371c..8dd354d 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h
@@ -46,8 +46,6 @@
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
 #include <linux/topology.h>
-#include <linux/version.h>
-
 
 #ifdef CONFIG_SMP
 
@@ -81,15 +79,8 @@ struct cfs_cpt_table {
 	nodemask_t			*ctb_nodemask;
 };
 
-void cfs_cpu_core_siblings(int cpu, cpumask_t *mask);
-void cfs_cpu_ht_siblings(int cpu, cpumask_t *mask);
-void cfs_node_to_cpumask(int node, cpumask_t *mask);
-int cfs_cpu_core_nsiblings(int cpu);
-int cfs_cpu_ht_nsiblings(int cpu);
-
 /**
  * comment out definitions for compatible layer
- * #define CFS_CPU_NR			  NR_CPUS
  *
  * typedef cpumask_t			   cfs_cpumask_t;
  *
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h
index 042a2bc..2af15d4 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h
@@ -63,9 +63,9 @@
 #if BITS_PER_LONG == 32
 /* limit to lowmem on 32-bit systems */
 #define NUM_CACHEPAGES \
-	min(num_physpages, 1UL << (30 - PAGE_CACHE_SHIFT) * 3 / 4)
+	min(totalram_pages, 1UL << (30 - PAGE_CACHE_SHIFT) * 3 / 4)
 #else
-#define NUM_CACHEPAGES num_physpages
+#define NUM_CACHEPAGES totalram_pages
 #endif
 
 /*
@@ -79,42 +79,4 @@
 	do { __oldfs = get_fs(); set_fs(get_ds());} while(0)
 #define MMSPACE_CLOSE	       set_fs(__oldfs)
 
-/*
- * Shrinker
- */
-
-# define SHRINKER_ARGS(sc, nr_to_scan, gfp_mask)  \
-		       struct shrinker *shrinker, \
-		       struct shrink_control *sc
-# define shrink_param(sc, var) ((sc)->var)
-
-typedef int (*shrinker_t)(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask));
-
-static inline
-struct shrinker *set_shrinker(int seek, shrinker_t func)
-{
-	struct shrinker *s;
-
-	s = kmalloc(sizeof(*s), GFP_KERNEL);
-	if (s == NULL)
-		return (NULL);
-
-	s->shrink = func;
-	s->seeks = seek;
-
-	register_shrinker(s);
-
-	return s;
-}
-
-static inline
-void remove_shrinker(struct shrinker *shrinker)
-{
-	if (shrinker == NULL)
-		return;
-
-	unregister_shrinker(shrinker);
-	kfree(shrinker);
-}
-
 #endif /* __LINUX_CFS_MEM_H__ */
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h
index a4963a8..1ec4ca1 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h
@@ -49,7 +49,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
@@ -64,43 +63,12 @@
 
 #include <linux/libcfs/linux/linux-time.h>
 
-
-/*
- * CPU
- */
-#ifdef for_each_possible_cpu
-#define cfs_for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
-#elif defined(for_each_cpu)
-#define cfs_for_each_possible_cpu(cpu) for_each_cpu(cpu)
-#endif
-
-#ifdef NR_CPUS
-#else
-#define NR_CPUS     1
-#endif
-
-/*
- * cache
- */
-
-/*
- * IRQs
- */
-
-
-/*
- * Pseudo device register
- */
-typedef struct miscdevice		psdev_t;
-
 /*
  * Sysctl register
  */
 typedef struct ctl_table		ctl_table_t;
 typedef struct ctl_table_header		ctl_table_header_t;
 
-#define cfs_register_sysctl_table(t, a) register_sysctl_table(t)
-
 #define DECLARE_PROC_HANDLER(name)		      \
 static int					      \
 LL_PROC_PROTO(name)				     \
@@ -112,130 +80,4 @@ LL_PROC_PROTO(name)				     \
 				 __##name);	     \
 }
 
-/*
- * Symbol register
- */
-#define cfs_symbol_register(s, p)       do {} while(0)
-#define cfs_symbol_unregister(s)	do {} while(0)
-#define cfs_symbol_get(s)	       symbol_get(s)
-#define cfs_symbol_put(s)	       symbol_put(s)
-
-typedef struct module module_t;
-
-/*
- * Proc file system APIs
- */
-typedef struct proc_dir_entry	   proc_dir_entry_t;
-
-/*
- * Wait Queue
- */
-
-
-typedef long			    cfs_task_state_t;
-
-#define CFS_DECL_WAITQ(wq)		DECLARE_WAIT_QUEUE_HEAD(wq)
-
-/*
- * Task struct
- */
-typedef struct task_struct	      task_t;
-#define DECL_JOURNAL_DATA	   void *journal_info
-#define PUSH_JOURNAL		do {    \
-	journal_info = current->journal_info;   \
-	current->journal_info = NULL;	   \
-	} while(0)
-#define POP_JOURNAL		 do {    \
-	current->journal_info = journal_info;   \
-	} while(0)
-
-/* Module interfaces */
-#define cfs_module(name, version, init, fini) \
-	module_init(init);		    \
-	module_exit(fini)
-
-/*
- * Signal
- */
-
-/*
- * Timer
- */
-typedef struct timer_list timer_list_t;
-
-
-#ifndef wait_event_timeout /* Only for RHEL3 2.4.21 kernel */
-#define __wait_event_timeout(wq, condition, timeout, ret)	\
-do {							     \
-	int __ret = 0;					   \
-	if (!(condition)) {				      \
-		wait_queue_t __wait;			     \
-		unsigned long expire;			    \
-								 \
-		init_waitqueue_entry(&__wait, current);	  \
-		expire = timeout + jiffies;		      \
-		add_wait_queue(&wq, &__wait);		    \
-		for (;;) {				       \
-			set_current_state(TASK_UNINTERRUPTIBLE); \
-			if (condition)			   \
-				break;			   \
-			if (jiffies > expire) {		  \
-				ret = jiffies - expire;	  \
-				break;			   \
-			}					\
-			schedule_timeout(timeout);	       \
-		}						\
-		current->state = TASK_RUNNING;		   \
-		remove_wait_queue(&wq, &__wait);		 \
-	}							\
-} while (0)
-/*
-   retval == 0; condition met; we're good.
-   retval > 0; timed out.
-*/
-#define cfs_waitq_wait_event_timeout(wq, condition, timeout, ret)    \
-do {								 \
-	ret = 0;						     \
-	if (!(condition))					    \
-		__wait_event_timeout(wq, condition, timeout, ret);   \
-} while (0)
-#else
-#define cfs_waitq_wait_event_timeout(wq, condition, timeout, ret)    \
-	ret = wait_event_timeout(wq, condition, timeout)
-#endif
-
-#define cfs_waitq_wait_event_interruptible_timeout(wq, c, timeout, ret) \
-	ret = wait_event_interruptible_timeout(wq, c, timeout)
-
-/*
- * atomic
- */
-
-
-#define cfs_atomic_add_unless(atom, a, u)    atomic_add_unless(atom, a, u)
-#define cfs_atomic_cmpxchg(atom, old, nv)    atomic_cmpxchg(atom, old, nv)
-
-/*
- * membar
- */
-
-
-/*
- * interrupt
- */
-
-
-/*
- * might_sleep
- */
-
-/*
- * group_info
- */
-typedef struct group_info group_info_t;
-
-
-/*
- * Random bytes
- */
 #endif
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h
index 687f33f..7a8d006 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h
@@ -48,21 +48,6 @@
 
 #include <net/sock.h>
 
-#ifndef HIPQUAD
-// XXX Should just kill all users
-#if defined(__LITTLE_ENDIAN)
-#define HIPQUAD(addr) \
-	((unsigned char *)&addr)[3], \
-	((unsigned char *)&addr)[2], \
-	((unsigned char *)&addr)[1], \
-	((unsigned char *)&addr)[0]
-#elif defined(__BIG_ENDIAN)
-#define HIPQUAD NIPQUAD
-#else
-#error "Please fix asm/byteorder.h"
-#endif /* __LITTLE_ENDIAN */
-#endif
-
 typedef struct socket   socket_t;
 
 #define SOCK_SNDBUF(so)	 ((so)->sk->sk_sndbuf)
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h
index 4a48b91..a386d1b 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h
@@ -91,7 +91,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/time.h>
 #include <asm/div64.h>
 
diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h b/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h
index 132a4be..fe4c63f 100644
--- a/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h
+++ b/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h
@@ -95,20 +95,5 @@ int proc_call_handler(void *data, int write,
 		      loff_t *ppos, void *buffer, size_t *lenp,
 		      int (*handler)(void *data, int write,
 				     loff_t pos, void *buffer, int len));
-/*
- * CPU
- */
-#ifdef for_each_possible_cpu
-#define cfs_for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
-#elif defined(for_each_cpu)
-#define cfs_for_each_possible_cpu(cpu) for_each_cpu(cpu)
-#endif
-
-#ifdef NR_CPUS
-#else
-#define NR_CPUS     1
-#endif
-
-#define cfs_register_sysctl_table(t, a) register_sysctl_table(t)
 
 #endif /* _PORTALS_COMPAT_H */
diff --git a/drivers/staging/lustre/include/linux/libcfs/lucache.h b/drivers/staging/lustre/include/linux/libcfs/lucache.h
index 7ae36fc..9668b39 100644
--- a/drivers/staging/lustre/include/linux/libcfs/lucache.h
+++ b/drivers/staging/lustre/include/linux/libcfs/lucache.h
@@ -77,7 +77,7 @@ struct md_identity {
 	struct upcall_cache_entry *mi_uc_entry;
 	uid_t		      mi_uid;
 	gid_t		      mi_gid;
-	group_info_t	  *mi_ginfo;
+	struct group_info	*mi_ginfo;
 	int			mi_nperms;
 	struct md_perm	    *mi_perms;
 };
diff --git a/drivers/staging/lustre/include/linux/libcfs/params_tree.h b/drivers/staging/lustre/include/linux/libcfs/params_tree.h
index 3f18a44..78a2c4e 100644
--- a/drivers/staging/lustre/include/linux/libcfs/params_tree.h
+++ b/drivers/staging/lustre/include/linux/libcfs/params_tree.h
@@ -54,7 +54,6 @@ typedef struct proc_inode		       cfs_proc_inode_t;
 typedef struct seq_file			 cfs_seq_file_t;
 typedef struct seq_operations		   cfs_seq_ops_t;
 typedef struct file_operations		  cfs_param_file_ops_t;
-typedef module_t			   *cfs_param_module_t;
 typedef struct proc_dir_entry		   cfs_param_dentry_t;
 typedef struct poll_table_struct		cfs_poll_table_t;
 #define CFS_PARAM_MODULE			THIS_MODULE
@@ -115,11 +114,10 @@ typedef struct cfs_seq_operations {
 	int   (*show) (cfs_seq_file_t *m, void *v);
 } cfs_seq_ops_t;
 
-typedef void *cfs_param_module_t;
 typedef void *cfs_poll_table_t;
 
 typedef struct cfs_param_file_ops {
-	cfs_param_module_t owner;
+	struct module *owner;
 	int (*open) (cfs_inode_t *, struct file *);
 	loff_t (*llseek)(struct file *, loff_t, int);
 	int (*release) (cfs_inode_t *, cfs_param_file_t *);
diff --git a/drivers/staging/lustre/lnet/Makefile b/drivers/staging/lustre/lnet/Makefile
index 374212b..f6f03e3 100644
--- a/drivers/staging/lustre/lnet/Makefile
+++ b/drivers/staging/lustre/lnet/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_LNET) := klnds/ lnet/ selftest/
+obj-$(CONFIG_LNET) += lnet/ klnds/ selftest/
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
index 29a9794..86397f9 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
@@ -702,6 +702,8 @@ kiblnd_get_completion_vector(kib_conn_t *conn, int cpt)
 		return 0;
 
 	mask = cfs_cpt_cpumask(lnet_cpt_table(), cpt);
+	if (mask == NULL)
+		return 0;
 
 	/* hash NID to CPU id in this partition... */
 	off = do_div(nid, cpus_weight(*mask));
@@ -2574,8 +2576,8 @@ kiblnd_dev_need_failover(kib_dev_t *dev)
 	rc = rdma_resolve_addr(cmid, (struct sockaddr *)&srcaddr,
 			       (struct sockaddr *)&dstaddr, 1);
 	if (rc != 0 || cmid->device == NULL) {
-		CERROR("Failed to bind %s:%u.%u.%u.%u to device(%p): %d\n",
-		       dev->ibd_ifname, HIPQUAD(dev->ibd_ifip),
+		CERROR("Failed to bind %s:%pI4h to device(%p): %d\n",
+		       dev->ibd_ifname, &dev->ibd_ifip,
 		       cmid->device, rc);
 		rdma_destroy_id(cmid);
 		return rc;
@@ -2647,8 +2649,8 @@ kiblnd_dev_failover(kib_dev_t *dev)
 	/* Bind to failover device or port */
 	rc = rdma_bind_addr(cmid, (struct sockaddr *)&addr);
 	if (rc != 0 || cmid->device == NULL) {
-		CERROR("Failed to bind %s:%u.%u.%u.%u to device(%p): %d\n",
-		       dev->ibd_ifname, HIPQUAD(dev->ibd_ifip),
+		CERROR("Failed to bind %s:%pI4h to device(%p): %d\n",
+		       dev->ibd_ifname, &dev->ibd_ifip,
 		       cmid->device, rc);
 		rdma_destroy_id(cmid);
 		goto out;
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
index e4626bf..938df0c 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
@@ -53,7 +53,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/file.h>
-#include <linux/stat.h>
 #include <linux/list.h>
 #include <linux/kmod.h>
 #include <linux/sysctl.h>
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
index cc62321..086ca3d 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
@@ -1319,9 +1319,9 @@ kiblnd_connect_peer (kib_peer_t *peer)
 	}
 
 	LASSERT (cmid->device != NULL);
-	CDEBUG(D_NET, "%s: connection bound to %s:%u.%u.%u.%u:%s\n",
+	CDEBUG(D_NET, "%s: connection bound to %s:%pI4h:%s\n",
 	       libcfs_nid2str(peer->ibp_nid), dev->ibd_ifname,
-	       HIPQUAD(dev->ibd_ifip), cmid->device->name);
+	       &dev->ibd_ifip, cmid->device->name);
 
 	return;
 
@@ -1802,7 +1802,7 @@ kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
 int
 kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name)
 {
-	task_t *task = kthread_run(fn, arg, name);
+	struct task_struct *task = kthread_run(fn, arg, name);
 
 	if (IS_ERR(task))
 		return PTR_ERR(task);
@@ -2209,8 +2209,8 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
 	if (*kiblnd_tunables.kib_require_priv_port &&
 	    ntohs(peer_addr->sin_port) >= PROT_SOCK) {
 		__u32 ip = ntohl(peer_addr->sin_addr.s_addr);
-		CERROR("Peer's port (%u.%u.%u.%u:%hu) is not privileged\n",
-		       HIPQUAD(ip), ntohs(peer_addr->sin_port));
+		CERROR("Peer's port (%pI4h:%hu) is not privileged\n",
+		       &ip, ntohs(peer_addr->sin_port));
 		goto failed;
 	}
 
@@ -2254,11 +2254,11 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
 	if (ni == NULL ||			 /* no matching net */
 	    ni->ni_nid != reqmsg->ibm_dstnid ||   /* right NET, wrong NID! */
 	    net->ibn_dev != ibdev) {	      /* wrong device */
-		CERROR("Can't accept %s on %s (%s:%d:%u.%u.%u.%u): "
+		CERROR("Can't accept %s on %s (%s:%d:%pI4h): "
 		       "bad dst nid %s\n", libcfs_nid2str(nid),
 		       ni == NULL ? "NA" : libcfs_nid2str(ni->ni_nid),
 		       ibdev->ibd_ifname, ibdev->ibd_nnets,
-		       HIPQUAD(ibdev->ibd_ifip),
+		       &ibdev->ibd_ifip,
 		       libcfs_nid2str(reqmsg->ibm_dstnid));
 
 		goto failed;
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
index e21028b..92dc567 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
@@ -404,7 +404,7 @@ kiblnd_sysctl_init (void)
 			      sizeof(ipif_basename_space));
 
 	kiblnd_tunables.kib_sysctl =
-		cfs_register_sysctl_table(kiblnd_top_ctl_table, 0);
+		register_sysctl_table(kiblnd_top_ctl_table);
 
 	if (kiblnd_tunables.kib_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
index c826bf9..1f36763 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
@@ -334,17 +334,17 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn)
 	if (route->ksnr_myipaddr != conn->ksnc_myipaddr) {
 		if (route->ksnr_myipaddr == 0) {
 			/* route wasn't bound locally yet (the initial route) */
-			CDEBUG(D_NET, "Binding %s %u.%u.%u.%u to %u.%u.%u.%u\n",
+			CDEBUG(D_NET, "Binding %s %pI4h to %pI4h\n",
 			       libcfs_id2str(peer->ksnp_id),
-			       HIPQUAD(route->ksnr_ipaddr),
-			       HIPQUAD(conn->ksnc_myipaddr));
+			       &route->ksnr_ipaddr,
+			       &conn->ksnc_myipaddr);
 		} else {
-			CDEBUG(D_NET, "Rebinding %s %u.%u.%u.%u from "
-			       "%u.%u.%u.%u to %u.%u.%u.%u\n",
+			CDEBUG(D_NET, "Rebinding %s %pI4h from "
+			       "%pI4h to %pI4h\n",
 			       libcfs_id2str(peer->ksnp_id),
-			       HIPQUAD(route->ksnr_ipaddr),
-			       HIPQUAD(route->ksnr_myipaddr),
-			       HIPQUAD(conn->ksnc_myipaddr));
+			       &route->ksnr_ipaddr,
+			       &route->ksnr_myipaddr,
+			       &conn->ksnc_myipaddr);
 
 			iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni,
 						  route->ksnr_myipaddr);
@@ -384,9 +384,9 @@ ksocknal_add_route_locked (ksock_peer_t *peer, ksock_route_t *route)
 		route2 = list_entry(tmp, ksock_route_t, ksnr_list);
 
 		if (route2->ksnr_ipaddr == route->ksnr_ipaddr) {
-			CERROR ("Duplicate route %s %u.%u.%u.%u\n",
+			CERROR("Duplicate route %s %pI4h\n",
 				libcfs_id2str(peer->ksnp_id),
-				HIPQUAD(route->ksnr_ipaddr));
+				&route->ksnr_ipaddr);
 			LBUG();
 		}
 	}
@@ -982,8 +982,8 @@ ksocknal_accept (lnet_ni_t *ni, socket_t *sock)
 	LIBCFS_ALLOC(cr, sizeof(*cr));
 	if (cr == NULL) {
 		LCONSOLE_ERROR_MSG(0x12f, "Dropping connection request from "
-				   "%u.%u.%u.%u: memory exhausted\n",
-				   HIPQUAD(peer_ip));
+				   "%pI4h: memory exhausted\n",
+				   &peer_ip);
 		return -ENOMEM;
 	}
 
@@ -1236,10 +1236,10 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 	 * code below probably isn't going to work. */
 	if (active &&
 	    route->ksnr_ipaddr != conn->ksnc_ipaddr) {
-		CERROR("Route %s %u.%u.%u.%u connected to %u.%u.%u.%u\n",
+		CERROR("Route %s %pI4h connected to %pI4h\n",
 		       libcfs_id2str(peer->ksnp_id),
-		       HIPQUAD(route->ksnr_ipaddr),
-		       HIPQUAD(conn->ksnc_ipaddr));
+		       &route->ksnr_ipaddr,
+		       &conn->ksnc_ipaddr);
 	}
 
 	/* Search for a route corresponding to the new connection and
@@ -1297,10 +1297,10 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 	 *	socket callbacks.
 	 */
 
-	CDEBUG(D_NET, "New conn %s p %d.x %u.%u.%u.%u -> %u.%u.%u.%u/%d"
+	CDEBUG(D_NET, "New conn %s p %d.x %pI4h -> %pI4h/%d"
 	       " incarnation:"LPD64" sched[%d:%d]\n",
 	       libcfs_id2str(peerid), conn->ksnc_proto->pro_version,
-	       HIPQUAD(conn->ksnc_myipaddr), HIPQUAD(conn->ksnc_ipaddr),
+	       &conn->ksnc_myipaddr, &conn->ksnc_ipaddr,
 	       conn->ksnc_port, incarnation, cpt,
 	       (int)(sched - &sched->kss_info->ksi_scheds[0]));
 
@@ -1648,10 +1648,10 @@ ksocknal_destroy_conn (ksock_conn_t *conn)
 		last_rcv = conn->ksnc_rx_deadline -
 			   cfs_time_seconds(*ksocknal_tunables.ksnd_timeout);
 		CERROR("Completing partial receive from %s[%d]"
-		       ", ip %d.%d.%d.%d:%d, with error, wanted: %d, left: %d, "
+		       ", ip %pI4h:%d, with error, wanted: %d, left: %d, "
 		       "last alive is %ld secs ago\n",
 		       libcfs_id2str(conn->ksnc_peer->ksnp_id), conn->ksnc_type,
-		       HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port,
+		       &conn->ksnc_ipaddr, conn->ksnc_port,
 		       conn->ksnc_rx_nob_wanted, conn->ksnc_rx_nob_left,
 		       cfs_duration_sec(cfs_time_sub(cfs_time_current(),
 					last_rcv)));
@@ -1661,25 +1661,25 @@ ksocknal_destroy_conn (ksock_conn_t *conn)
 	case SOCKNAL_RX_LNET_HEADER:
 		if (conn->ksnc_rx_started)
 			CERROR("Incomplete receive of lnet header from %s"
-			       ", ip %d.%d.%d.%d:%d, with error, protocol: %d.x.\n",
+			       ", ip %pI4h:%d, with error, protocol: %d.x.\n",
 			       libcfs_id2str(conn->ksnc_peer->ksnp_id),
-			       HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port,
+			       &conn->ksnc_ipaddr, conn->ksnc_port,
 			       conn->ksnc_proto->pro_version);
 		break;
 	case SOCKNAL_RX_KSM_HEADER:
 		if (conn->ksnc_rx_started)
 			CERROR("Incomplete receive of ksock message from %s"
-			       ", ip %d.%d.%d.%d:%d, with error, protocol: %d.x.\n",
+			       ", ip %pI4h:%d, with error, protocol: %d.x.\n",
 			       libcfs_id2str(conn->ksnc_peer->ksnp_id),
-			       HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port,
+			       &conn->ksnc_ipaddr, conn->ksnc_port,
 			       conn->ksnc_proto->pro_version);
 		break;
 	case SOCKNAL_RX_SLOP:
 		if (conn->ksnc_rx_started)
 			CERROR("Incomplete receive of slops from %s"
-			       ", ip %d.%d.%d.%d:%d, with error\n",
+			       ", ip %pI4h:%d, with error\n",
 			       libcfs_id2str(conn->ksnc_peer->ksnp_id),
-			       HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
+			       &conn->ksnc_ipaddr, conn->ksnc_port);
 	       break;
 	default:
 		LBUG ();
@@ -2898,5 +2898,7 @@ ksocknal_module_init (void)
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Kernel TCP Socket LND v3.0.0");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("3.0.0");
 
-cfs_module(ksocknal, "3.0.0", ksocknal_module_init, ksocknal_module_fini);
+module_init(ksocknal_module_init);
+module_exit(ksocknal_module_fini);
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
index ad5e241..727f352 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
@@ -343,7 +343,6 @@ ksocknal_receive (ksock_conn_t *conn)
 	 * Caller checks ksnc_rx_nob_wanted to determine
 	 * progress/completion. */
 	int     rc;
-	ENTRY;
 
 	if (ksocknal_data.ksnd_stall_rx != 0) {
 		cfs_pause(cfs_time_seconds (ksocknal_data.ksnd_stall_rx));
@@ -381,7 +380,7 @@ ksocknal_receive (ksock_conn_t *conn)
 	}
 
 	ksocknal_connsock_decref(conn);
-	RETURN (rc);
+	return rc;
 }
 
 void
@@ -389,7 +388,6 @@ ksocknal_tx_done (lnet_ni_t *ni, ksock_tx_t *tx)
 {
 	lnet_msg_t  *lnetmsg = tx->tx_lnetmsg;
 	int	  rc = (tx->tx_resid == 0 && !tx->tx_zc_aborted) ? 0 : -EIO;
-	ENTRY;
 
 	LASSERT(ni != NULL || tx->tx_conn != NULL);
 
@@ -402,8 +400,6 @@ ksocknal_tx_done (lnet_ni_t *ni, ksock_tx_t *tx)
 	ksocknal_free_tx (tx);
 	if (lnetmsg != NULL) /* KSOCK_MSG_NOOP go without lnetmsg */
 		lnet_finalize (ni, lnetmsg, rc);
-
-	EXIT;
 }
 
 void
@@ -553,21 +549,21 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx)
 	if (!conn->ksnc_closing) {
 		switch (rc) {
 		case -ECONNRESET:
-			LCONSOLE_WARN("Host %u.%u.%u.%u reset our connection "
+			LCONSOLE_WARN("Host %pI4h reset our connection "
 				      "while we were sending data; it may have "
 				      "rebooted.\n",
-				      HIPQUAD(conn->ksnc_ipaddr));
+				      &conn->ksnc_ipaddr);
 			break;
 		default:
 			LCONSOLE_WARN("There was an unexpected network error "
-				      "while writing to %u.%u.%u.%u: %d.\n",
-				      HIPQUAD(conn->ksnc_ipaddr), rc);
+				      "while writing to %pI4h: %d.\n",
+				      &conn->ksnc_ipaddr, rc);
 			break;
 		}
 		CDEBUG(D_NET, "[%p] Error %d on write to %s"
-		       " ip %d.%d.%d.%d:%d\n", conn, rc,
+		       " ip %pI4h:%d\n", conn, rc,
 		       libcfs_id2str(conn->ksnc_peer->ksnp_id),
-		       HIPQUAD(conn->ksnc_ipaddr),
+		       &conn->ksnc_ipaddr,
 		       conn->ksnc_port);
 	}
 
@@ -700,9 +696,9 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn)
 	 * ksnc_sock... */
 	LASSERT(!conn->ksnc_closing);
 
-	CDEBUG (D_NET, "Sending to %s ip %d.%d.%d.%d:%d\n",
+	CDEBUG(D_NET, "Sending to %s ip %pI4h:%d\n",
 		libcfs_id2str(conn->ksnc_peer->ksnp_id),
-		HIPQUAD(conn->ksnc_ipaddr),
+		&conn->ksnc_ipaddr,
 		conn->ksnc_port);
 
 	ksocknal_tx_prep(conn, tx);
@@ -801,9 +797,9 @@ ksocknal_find_connectable_route_locked (ksock_peer_t *peer)
 		if (!(route->ksnr_retry_interval == 0 || /* first attempt */
 		      cfs_time_aftereq(now, route->ksnr_timeout))) {
 			CDEBUG(D_NET,
-			       "Too soon to retry route %u.%u.%u.%u "
+			       "Too soon to retry route %pI4h "
 			       "(cnted %d, interval %ld, %ld secs later)\n",
-			       HIPQUAD(route->ksnr_ipaddr),
+			       &route->ksnr_ipaddr,
 			       route->ksnr_connected,
 			       route->ksnr_retry_interval,
 			       cfs_duration_sec(route->ksnr_timeout - now));
@@ -1009,7 +1005,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 int
 ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name)
 {
-	task_t *task = kthread_run(fn, arg, name);
+	struct task_struct *task = kthread_run(fn, arg, name);
 
 	if (IS_ERR(task))
 		return PTR_ERR(task);
@@ -1133,17 +1129,17 @@ ksocknal_process_receive (ksock_conn_t *conn)
 			LASSERT (rc != -EAGAIN);
 
 			if (rc == 0)
-				CDEBUG (D_NET, "[%p] EOF from %s"
-					" ip %d.%d.%d.%d:%d\n", conn,
+				CDEBUG(D_NET, "[%p] EOF from %s"
+					" ip %pI4h:%d\n", conn,
 					libcfs_id2str(conn->ksnc_peer->ksnp_id),
-					HIPQUAD(conn->ksnc_ipaddr),
+					&conn->ksnc_ipaddr,
 					conn->ksnc_port);
 			else if (!conn->ksnc_closing)
-				CERROR ("[%p] Error %d on read from %s"
-					" ip %d.%d.%d.%d:%d\n",
+				CERROR("[%p] Error %d on read from %s"
+					" ip %pI4h:%d\n",
 					conn, rc,
 					libcfs_id2str(conn->ksnc_peer->ksnp_id),
-					HIPQUAD(conn->ksnc_ipaddr),
+					&conn->ksnc_ipaddr,
 					conn->ksnc_port);
 
 			/* it's not an error if conn is being closed */
@@ -1562,7 +1558,6 @@ int ksocknal_scheduler(void *arg)
 void ksocknal_read_callback (ksock_conn_t *conn)
 {
 	ksock_sched_t *sched;
-	ENTRY;
 
 	sched = conn->ksnc_scheduler;
 
@@ -1580,8 +1575,6 @@ void ksocknal_read_callback (ksock_conn_t *conn)
 		wake_up (&sched->kss_waitq);
 	}
 	spin_unlock_bh(&sched->kss_lock);
-
-	EXIT;
 }
 
 /*
@@ -1591,7 +1584,6 @@ void ksocknal_read_callback (ksock_conn_t *conn)
 void ksocknal_write_callback (ksock_conn_t *conn)
 {
 	ksock_sched_t *sched;
-	ENTRY;
 
 	sched = conn->ksnc_scheduler;
 
@@ -1611,8 +1603,6 @@ void ksocknal_write_callback (ksock_conn_t *conn)
 	}
 
 	spin_unlock_bh(&sched->kss_lock);
-
-	EXIT;
 }
 
 ksock_proto_t *
@@ -1722,8 +1712,8 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 
 	rc = libcfs_sock_read(sock, &hello->kshm_magic, sizeof (hello->kshm_magic), timeout);
 	if (rc != 0) {
-		CERROR ("Error %d reading HELLO from %u.%u.%u.%u\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr));
+		CERROR("Error %d reading HELLO from %pI4h\n",
+			rc, &conn->ksnc_ipaddr);
 		LASSERT (rc < 0);
 		return rc;
 	}
@@ -1732,18 +1722,18 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 	    hello->kshm_magic != __swab32(LNET_PROTO_MAGIC) &&
 	    hello->kshm_magic != le32_to_cpu (LNET_PROTO_TCP_MAGIC)) {
 		/* Unexpected magic! */
-		CERROR ("Bad magic(1) %#08x (%#08x expected) from "
-			"%u.%u.%u.%u\n", __cpu_to_le32 (hello->kshm_magic),
+		CERROR("Bad magic(1) %#08x (%#08x expected) from "
+			"%pI4h\n", __cpu_to_le32 (hello->kshm_magic),
 			LNET_PROTO_TCP_MAGIC,
-			HIPQUAD(conn->ksnc_ipaddr));
+			&conn->ksnc_ipaddr);
 		return -EPROTO;
 	}
 
 	rc = libcfs_sock_read(sock, &hello->kshm_version,
 			      sizeof(hello->kshm_version), timeout);
 	if (rc != 0) {
-		CERROR ("Error %d reading HELLO from %u.%u.%u.%u\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr));
+		CERROR("Error %d reading HELLO from %pI4h\n",
+			rc, &conn->ksnc_ipaddr);
 		LASSERT (rc < 0);
 		return rc;
 	}
@@ -1763,10 +1753,10 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 			ksocknal_send_hello(ni, conn, ni->ni_nid, hello);
 		}
 
-		CERROR ("Unknown protocol version (%d.x expected)"
-			" from %u.%u.%u.%u\n",
+		CERROR("Unknown protocol version (%d.x expected)"
+			" from %pI4h\n",
 			conn->ksnc_proto->pro_version,
-			HIPQUAD(conn->ksnc_ipaddr));
+			&conn->ksnc_ipaddr);
 
 		return -EPROTO;
 	}
@@ -1777,8 +1767,8 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 	/* receive the rest of hello message anyway */
 	rc = conn->ksnc_proto->pro_recv_hello(conn, hello, timeout);
 	if (rc != 0) {
-		CERROR("Error %d reading or checking hello from from %u.%u.%u.%u\n",
-		       rc, HIPQUAD(conn->ksnc_ipaddr));
+		CERROR("Error %d reading or checking hello from from %pI4h\n",
+		       rc, &conn->ksnc_ipaddr);
 		LASSERT (rc < 0);
 		return rc;
 	}
@@ -1787,7 +1777,7 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 
 	if (hello->kshm_src_nid == LNET_NID_ANY) {
 		CERROR("Expecting a HELLO hdr with a NID, but got LNET_NID_ANY"
-		       "from %u.%u.%u.%u\n", HIPQUAD(conn->ksnc_ipaddr));
+		       "from %pI4h\n", &conn->ksnc_ipaddr);
 		return -EPROTO;
 	}
 
@@ -1807,9 +1797,9 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 		/* peer determines type */
 		conn->ksnc_type = ksocknal_invert_type(hello->kshm_ctype);
 		if (conn->ksnc_type == SOCKLND_CONN_NONE) {
-			CERROR ("Unexpected type %d from %s ip %u.%u.%u.%u\n",
+			CERROR("Unexpected type %d from %s ip %pI4h\n",
 				hello->kshm_ctype, libcfs_id2str(*peerid),
-				HIPQUAD(conn->ksnc_ipaddr));
+				&conn->ksnc_ipaddr);
 			return -EPROTO;
 		}
 
@@ -1819,11 +1809,11 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 	if (peerid->pid != recv_id.pid ||
 	    peerid->nid != recv_id.nid) {
 		LCONSOLE_ERROR_MSG(0x130, "Connected successfully to %s on host"
-				   " %u.%u.%u.%u, but they claimed they were "
+				   " %pI4h, but they claimed they were "
 				   "%s; please check your Lustre "
 				   "configuration.\n",
 				   libcfs_id2str(*peerid),
-				   HIPQUAD(conn->ksnc_ipaddr),
+				   &conn->ksnc_ipaddr,
 				   libcfs_id2str(recv_id));
 		return -EPROTO;
 	}
@@ -1834,9 +1824,9 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn,
 	}
 
 	if (ksocknal_invert_type(hello->kshm_ctype) != conn->ksnc_type) {
-		CERROR ("Mismatched types: me %d, %s ip %u.%u.%u.%u %d\n",
+		CERROR("Mismatched types: me %d, %s ip %pI4h %d\n",
 			conn->ksnc_type, libcfs_id2str(*peerid),
-			HIPQUAD(conn->ksnc_ipaddr),
+			&conn->ksnc_ipaddr,
 			hello->kshm_ctype);
 		return -EPROTO;
 	}
@@ -2208,8 +2198,8 @@ ksocknal_connd (void *arg)
 				/* consecutive retry */
 				if (cons_retry++ > SOCKNAL_INSANITY_RECONN) {
 					CWARN("massive consecutive "
-					      "re-connecting to %u.%u.%u.%u\n",
-					      HIPQUAD(route->ksnr_ipaddr));
+					      "re-connecting to %pI4h\n",
+					      &route->ksnr_ipaddr);
 					cons_retry = 0;
 				}
 			} else {
@@ -2274,26 +2264,26 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer)
 			switch (error) {
 			case ECONNRESET:
 				CNETERR("A connection with %s "
-					"(%u.%u.%u.%u:%d) was reset; "
+					"(%pI4h:%d) was reset; "
 					"it may have rebooted.\n",
 					libcfs_id2str(peer->ksnp_id),
-					HIPQUAD(conn->ksnc_ipaddr),
+					&conn->ksnc_ipaddr,
 					conn->ksnc_port);
 				break;
 			case ETIMEDOUT:
 				CNETERR("A connection with %s "
-					"(%u.%u.%u.%u:%d) timed out; the "
+					"(%pI4h:%d) timed out; the "
 					"network or node may be down.\n",
 					libcfs_id2str(peer->ksnp_id),
-					HIPQUAD(conn->ksnc_ipaddr),
+					&conn->ksnc_ipaddr,
 					conn->ksnc_port);
 				break;
 			default:
 				CNETERR("An unexpected network error %d "
 					"occurred with %s "
-					"(%u.%u.%u.%u:%d\n", error,
+					"(%pI4h:%d\n", error,
 					libcfs_id2str(peer->ksnp_id),
-					HIPQUAD(conn->ksnc_ipaddr),
+					&conn->ksnc_ipaddr,
 					conn->ksnc_port);
 				break;
 			}
@@ -2306,10 +2296,10 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer)
 				     conn->ksnc_rx_deadline)) {
 			/* Timed out incomplete incoming message */
 			ksocknal_conn_addref(conn);
-			CNETERR("Timeout receiving from %s (%u.%u.%u.%u:%d), "
+			CNETERR("Timeout receiving from %s (%pI4h:%d), "
 				"state %d wanted %d left %d\n",
 				libcfs_id2str(peer->ksnp_id),
-				HIPQUAD(conn->ksnc_ipaddr),
+				&conn->ksnc_ipaddr,
 				conn->ksnc_port,
 				conn->ksnc_rx_state,
 				conn->ksnc_rx_nob_wanted,
@@ -2324,10 +2314,10 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer)
 			/* Timed out messages queued for sending or
 			 * buffered in the socket's send buffer */
 			ksocknal_conn_addref(conn);
-			CNETERR("Timeout sending data to %s (%u.%u.%u.%u:%d) "
+			CNETERR("Timeout sending data to %s (%pI4h:%d) "
 				"the network or that node may be down.\n",
 				libcfs_id2str(peer->ksnp_id),
-				HIPQUAD(conn->ksnc_ipaddr),
+				&conn->ksnc_ipaddr,
 				conn->ksnc_port);
 			return (conn);
 		}
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c
index 3e08fe2..a1c6a51 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c
@@ -316,7 +316,7 @@ ksocknal_lib_tunables_init ()
 		*ksocknal_tunables.ksnd_zc_recv_min_nfrags = LNET_MAX_IOV;
 
 	ksocknal_tunables.ksnd_sysctl =
-		cfs_register_sysctl_table(ksocknal_top_ctl_table, 0);
+		register_sysctl_table(ksocknal_top_ctl_table);
 
 	if (ksocknal_tunables.ksnd_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -325,20 +325,20 @@ ksocknal_lib_tunables_init ()
 }
 
 void
-ksocknal_lib_tunables_fini ()
+ksocknal_lib_tunables_fini(void)
 {
 	if (ksocknal_tunables.ksnd_sysctl != NULL)
 		unregister_sysctl_table(ksocknal_tunables.ksnd_sysctl);
 }
 #else
 int
-ksocknal_lib_tunables_init ()
+ksocknal_lib_tunables_init(void)
 {
 	return 0;
 }
 
 void
-ksocknal_lib_tunables_fini ()
+ksocknal_lib_tunables_fini(void)
 {
 }
 #endif /* # if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM */
@@ -964,7 +964,6 @@ static void
 ksocknal_data_ready (struct sock *sk, int n)
 {
 	ksock_conn_t  *conn;
-	ENTRY;
 
 	/* interleave correctly with closing sockets... */
 	LASSERT(!in_irq());
@@ -978,8 +977,6 @@ ksocknal_data_ready (struct sock *sk, int n)
 		ksocknal_read_callback(conn);
 
 	read_unlock(&ksocknal_data.ksnd_global_lock);
-
-	EXIT;
 }
 
 static void
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h
index 3c13578..1cfc1b1 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h
@@ -41,7 +41,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
@@ -58,11 +57,9 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/file.h>
-#include <linux/stat.h>
 #include <linux/list.h>
 #include <linux/kmod.h>
 #include <linux/sysctl.h>
-#include <asm/uaccess.h>
 #include <asm/div64.h>
 #include <linux/syscalls.h>
 
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c
index ec57179..6f7147d 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c
@@ -496,8 +496,8 @@ ksocknal_send_hello_v1 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
 	rc = libcfs_sock_write(sock, hdr, sizeof(*hdr),lnet_acceptor_timeout());
 
 	if (rc != 0) {
-		CNETERR("Error %d sending HELLO hdr to %u.%u.%u.%u/%d\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
+		CNETERR("Error %d sending HELLO hdr to %pI4h/%d\n",
+			rc, &conn->ksnc_ipaddr, conn->ksnc_port);
 		goto out;
 	}
 
@@ -513,8 +513,8 @@ ksocknal_send_hello_v1 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
 			       lnet_acceptor_timeout());
 	if (rc != 0) {
 		CNETERR("Error %d sending HELLO payload (%d)"
-			" to %u.%u.%u.%u/%d\n", rc, hello->kshm_nips,
-			HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
+			" to %pI4h/%d\n", rc, hello->kshm_nips,
+			&conn->ksnc_ipaddr, conn->ksnc_port);
 	}
 out:
 	LIBCFS_FREE(hdr, sizeof(*hdr));
@@ -545,8 +545,8 @@ ksocknal_send_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
 			       lnet_acceptor_timeout());
 
 	if (rc != 0) {
-		CNETERR("Error %d sending HELLO hdr to %u.%u.%u.%u/%d\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
+		CNETERR("Error %d sending HELLO hdr to %pI4h/%d\n",
+			rc, &conn->ksnc_ipaddr, conn->ksnc_port);
 		return rc;
 	}
 
@@ -558,8 +558,8 @@ ksocknal_send_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
 			       lnet_acceptor_timeout());
 	if (rc != 0) {
 		CNETERR("Error %d sending HELLO payload (%d)"
-			" to %u.%u.%u.%u/%d\n", rc, hello->kshm_nips,
-			HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
+			" to %pI4h/%d\n", rc, hello->kshm_nips,
+			&conn->ksnc_ipaddr, conn->ksnc_port);
 	}
 
 	return rc;
@@ -583,18 +583,18 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout)
 			      sizeof (*hdr) - offsetof (lnet_hdr_t, src_nid),
 			      timeout);
 	if (rc != 0) {
-		CERROR ("Error %d reading rest of HELLO hdr from %u.%u.%u.%u\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr));
+		CERROR("Error %d reading rest of HELLO hdr from %pI4h\n",
+			rc, &conn->ksnc_ipaddr);
 		LASSERT (rc < 0 && rc != -EALREADY);
 		goto out;
 	}
 
 	/* ...and check we got what we expected */
 	if (hdr->type != cpu_to_le32 (LNET_MSG_HELLO)) {
-		CERROR ("Expecting a HELLO hdr,"
-			" but got type %d from %u.%u.%u.%u\n",
+		CERROR("Expecting a HELLO hdr,"
+			" but got type %d from %pI4h\n",
 			le32_to_cpu (hdr->type),
-			HIPQUAD(conn->ksnc_ipaddr));
+			&conn->ksnc_ipaddr);
 		rc = -EPROTO;
 		goto out;
 	}
@@ -607,8 +607,8 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout)
 					 sizeof (__u32);
 
 	if (hello->kshm_nips > LNET_MAX_INTERFACES) {
-		CERROR("Bad nips %d from ip %u.%u.%u.%u\n",
-		       hello->kshm_nips, HIPQUAD(conn->ksnc_ipaddr));
+		CERROR("Bad nips %d from ip %pI4h\n",
+		       hello->kshm_nips, &conn->ksnc_ipaddr);
 		rc = -EPROTO;
 		goto out;
 	}
@@ -619,9 +619,9 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout)
 	rc = libcfs_sock_read(sock, hello->kshm_ips,
 			      hello->kshm_nips * sizeof(__u32), timeout);
 	if (rc != 0) {
-		CERROR ("Error %d reading IPs from ip %u.%u.%u.%u\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr));
-		LASSERT (rc < 0 && rc != -EALREADY);
+		CERROR("Error %d reading IPs from ip %pI4h\n",
+			rc, &conn->ksnc_ipaddr);
+		LASSERT(rc < 0 && rc != -EALREADY);
 		goto out;
 	}
 
@@ -629,8 +629,8 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout)
 		hello->kshm_ips[i] = __le32_to_cpu(hello->kshm_ips[i]);
 
 		if (hello->kshm_ips[i] == 0) {
-			CERROR("Zero IP[%d] from ip %u.%u.%u.%u\n",
-			       i, HIPQUAD(conn->ksnc_ipaddr));
+			CERROR("Zero IP[%d] from ip %pI4h\n",
+			       i, &conn->ksnc_ipaddr);
 			rc = -EPROTO;
 			break;
 		}
@@ -658,9 +658,9 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou
 				       offsetof(ksock_hello_msg_t, kshm_src_nid),
 			      timeout);
 	if (rc != 0) {
-		CERROR ("Error %d reading HELLO from %u.%u.%u.%u\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr));
-		LASSERT (rc < 0 && rc != -EALREADY);
+		CERROR("Error %d reading HELLO from %pI4h\n",
+			rc, &conn->ksnc_ipaddr);
+		LASSERT(rc < 0 && rc != -EALREADY);
 		return rc;
 	}
 
@@ -676,8 +676,8 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou
 	}
 
 	if (hello->kshm_nips > LNET_MAX_INTERFACES) {
-		CERROR("Bad nips %d from ip %u.%u.%u.%u\n",
-		       hello->kshm_nips, HIPQUAD(conn->ksnc_ipaddr));
+		CERROR("Bad nips %d from ip %pI4h\n",
+		       hello->kshm_nips, &conn->ksnc_ipaddr);
 		return -EPROTO;
 	}
 
@@ -687,9 +687,9 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou
 	rc = libcfs_sock_read(sock, hello->kshm_ips,
 			      hello->kshm_nips * sizeof(__u32), timeout);
 	if (rc != 0) {
-		CERROR ("Error %d reading IPs from ip %u.%u.%u.%u\n",
-			rc, HIPQUAD(conn->ksnc_ipaddr));
-		LASSERT (rc < 0 && rc != -EALREADY);
+		CERROR("Error %d reading IPs from ip %pI4h\n",
+			rc, &conn->ksnc_ipaddr);
+		LASSERT(rc < 0 && rc != -EALREADY);
 		return rc;
 	}
 
@@ -698,8 +698,8 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou
 			__swab32s(&hello->kshm_ips[i]);
 
 		if (hello->kshm_ips[i] == 0) {
-			CERROR("Zero IP[%d] from ip %u.%u.%u.%u\n",
-			       i, HIPQUAD(conn->ksnc_ipaddr));
+			CERROR("Zero IP[%d] from ip %pI4h\n",
+			       i, &conn->ksnc_ipaddr);
 			return -EPROTO;
 		}
 	}
diff --git a/drivers/staging/lustre/lnet/lnet/Makefile b/drivers/staging/lustre/lnet/lnet/Makefile
index 1bd9ef7..b815fe1 100644
--- a/drivers/staging/lustre/lnet/lnet/Makefile
+++ b/drivers/staging/lustre/lnet/lnet/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_LNET) += lnet.o
 
-lnet-y := api-errno.o api-ni.o config.o lib-me.o lib-msg.o lib-eq.o	\
+lnet-y := api-ni.o config.o lib-me.o lib-msg.o lib-eq.o	\
 	  lib-md.o lib-ptl.o lib-move.o module.o lo.o router.o		\
 	  router_proc.o acceptor.o peer.o
 
diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c
index 81ef28b..bb15bde 100644
--- a/drivers/staging/lustre/lnet/lnet/acceptor.c
+++ b/drivers/staging/lustre/lnet/lnet/acceptor.c
@@ -101,52 +101,52 @@ lnet_connect_console_error (int rc, lnet_nid_t peer_nid,
 	switch (rc) {
 	/* "normal" errors */
 	case -ECONNREFUSED:
-		CNETERR("Connection to %s at host %u.%u.%u.%u on port %d was "
+		CNETERR("Connection to %s at host %pI4h on port %d was "
 			"refused: check that Lustre is running on that node.\n",
 			libcfs_nid2str(peer_nid),
-			HIPQUAD(peer_ip), peer_port);
+			&peer_ip, peer_port);
 		break;
 	case -EHOSTUNREACH:
 	case -ENETUNREACH:
-		CNETERR("Connection to %s at host %u.%u.%u.%u "
+		CNETERR("Connection to %s at host %pI4h "
 			"was unreachable: the network or that node may "
 			"be down, or Lustre may be misconfigured.\n",
-			libcfs_nid2str(peer_nid), HIPQUAD(peer_ip));
+			libcfs_nid2str(peer_nid), &peer_ip);
 		break;
 	case -ETIMEDOUT:
-		CNETERR("Connection to %s at host %u.%u.%u.%u on "
+		CNETERR("Connection to %s at host %pI4h on "
 			"port %d took too long: that node may be hung "
 			"or experiencing high load.\n",
 			libcfs_nid2str(peer_nid),
-			HIPQUAD(peer_ip), peer_port);
+			&peer_ip, peer_port);
 		break;
 	case -ECONNRESET:
-		LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %u.%u.%u.%u"
+		LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %pI4h"
 				   " on port %d was reset: "
 				   "is it running a compatible version of "
 				   "Lustre and is %s one of its NIDs?\n",
 				   libcfs_nid2str(peer_nid),
-				   HIPQUAD(peer_ip), peer_port,
+				   &peer_ip, peer_port,
 				   libcfs_nid2str(peer_nid));
 		break;
 	case -EPROTO:
 		LCONSOLE_ERROR_MSG(0x11c, "Protocol error connecting to %s at "
-				   "host %u.%u.%u.%u on port %d: is it running "
+				   "host %pI4h on port %d: is it running "
 				   "a compatible version of Lustre?\n",
 				   libcfs_nid2str(peer_nid),
-				   HIPQUAD(peer_ip), peer_port);
+				   &peer_ip, peer_port);
 		break;
 	case -EADDRINUSE:
 		LCONSOLE_ERROR_MSG(0x11d, "No privileged ports available to "
-				   "connect to %s at host %u.%u.%u.%u on port "
+				   "connect to %s at host %pI4h on port "
 				   "%d\n", libcfs_nid2str(peer_nid),
-				   HIPQUAD(peer_ip), peer_port);
+				   &peer_ip, peer_port);
 		break;
 	default:
 		LCONSOLE_ERROR_MSG(0x11e, "Unexpected error %d connecting to %s"
-				   " at host %u.%u.%u.%u on port %d\n", rc,
+				   " at host %pI4h on port %d\n", rc,
 				   libcfs_nid2str(peer_nid),
-				   HIPQUAD(peer_ip), peer_port);
+				   &peer_ip, peer_port);
 		break;
 	}
 }
@@ -253,8 +253,8 @@ lnet_accept(socket_t *sock, __u32 magic)
 
 			if (rc != 0)
 				CERROR("Error sending magic+version in response"
-				       "to LNET magic from %u.%u.%u.%u: %d\n",
-				       HIPQUAD(peer_ip), rc);
+				       "to LNET magic from %pI4h: %d\n",
+				       &peer_ip, rc);
 			return -EPROTO;
 		}
 
@@ -265,9 +265,9 @@ lnet_accept(socket_t *sock, __u32 magic)
 		else
 			str = "unrecognised";
 
-		LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %u.%u.%u.%u"
+		LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %pI4h"
 				   " magic %08x: %s acceptor protocol\n",
-				   HIPQUAD(peer_ip), magic, str);
+				   &peer_ip, magic, str);
 		return -EPROTO;
 	}
 
@@ -278,7 +278,7 @@ lnet_accept(socket_t *sock, __u32 magic)
 			      accept_timeout);
 	if (rc != 0) {
 		CERROR("Error %d reading connection request version from "
-		       "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
+		       "%pI4h\n", rc, &peer_ip);
 		return -EIO;
 	}
 
@@ -301,8 +301,8 @@ lnet_accept(socket_t *sock, __u32 magic)
 
 		if (rc != 0)
 			CERROR("Error sending magic+version in response"
-			       "to version %d from %u.%u.%u.%u: %d\n",
-			       peer_version, HIPQUAD(peer_ip), rc);
+			       "to version %d from %pI4h: %d\n",
+			       peer_version, &peer_ip, rc);
 		return -EPROTO;
 	}
 
@@ -312,7 +312,7 @@ lnet_accept(socket_t *sock, __u32 magic)
 			      accept_timeout);
 	if (rc != 0) {
 		CERROR("Error %d reading connection request from "
-		       "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
+		       "%pI4h\n", rc, &peer_ip);
 		return -EIO;
 	}
 
@@ -324,23 +324,23 @@ lnet_accept(socket_t *sock, __u32 magic)
 	    ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */
 		if (ni != NULL)
 			lnet_ni_decref(ni);
-		LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %u.%u.%u.%u"
+		LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h"
 				   " for %s: No matching NI\n",
-				   HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid));
+				   &peer_ip, libcfs_nid2str(cr.acr_nid));
 		return -EPERM;
 	}
 
 	if (ni->ni_lnd->lnd_accept == NULL) {
 		/* This catches a request for the loopback LND */
 		lnet_ni_decref(ni);
-		LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %u.%u.%u.%u"
+		LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h"
 				  " for %s: NI doesn not accept IP connections\n",
-				  HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid));
+				  &peer_ip, libcfs_nid2str(cr.acr_nid));
 		return -EPERM;
 	}
 
-	CDEBUG(D_NET, "Accept %s from %u.%u.%u.%u\n",
-	       libcfs_nid2str(cr.acr_nid), HIPQUAD(peer_ip));
+	CDEBUG(D_NET, "Accept %s from %pI4h\n",
+	       libcfs_nid2str(cr.acr_nid), &peer_ip);
 
 	rc = ni->ni_lnd->lnd_accept(ni, sock);
 
@@ -410,9 +410,9 @@ lnet_acceptor(void *arg)
 		}
 
 		if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) {
-			CERROR("Refusing connection from %u.%u.%u.%u: "
+			CERROR("Refusing connection from %pI4h: "
 			       "insecure port %d\n",
-			       HIPQUAD(peer_ip), peer_port);
+			       &peer_ip, peer_port);
 			goto failed;
 		}
 
@@ -420,7 +420,7 @@ lnet_acceptor(void *arg)
 				      accept_timeout);
 		if (rc != 0) {
 			CERROR("Error %d reading connection request from "
-			       "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
+			       "%pI4h\n", rc, &peer_ip);
 			goto failed;
 		}
 
diff --git a/drivers/staging/lustre/lnet/lnet/api-errno.c b/drivers/staging/lustre/lnet/lnet/api-errno.c
deleted file mode 100644
index 695b272..0000000
--- a/drivers/staging/lustre/lnet/lnet/api-errno.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/lnet/api-errno.c
- *
- * Instantiate the string table of errors
- */
-
-/* If you change these, you must update the number table in portals/errno.h */
diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c
index e88bee3..160a429 100644
--- a/drivers/staging/lustre/lnet/lnet/api-ni.c
+++ b/drivers/staging/lustre/lnet/lnet/api-ni.c
@@ -1371,7 +1371,7 @@ EXPORT_SYMBOL(LNetNIInit);
  * \return always 0 for current implementation.
  */
 int
-LNetNIFini()
+LNetNIFini(void)
 {
 	LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex);
 
@@ -1541,7 +1541,10 @@ LNetGetId(unsigned int index, lnet_process_id_t *id)
 	int		rc = -ENOENT;
 
 	LASSERT(the_lnet.ln_init);
-	LASSERT(the_lnet.ln_refcount > 0);
+
+	/* LNetNI initilization failed? */
+	if (the_lnet.ln_refcount == 0)
+		return rc;
 
 	cpt = lnet_net_lock_current();
 
diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c
index 78297a7..4ce68d3 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-eq.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c
@@ -244,11 +244,10 @@ lnet_eq_dequeue_event(lnet_eq_t *eq, lnet_event_t *ev)
 	int		new_index = eq->eq_deq_seq & (eq->eq_size - 1);
 	lnet_event_t	*new_event = &eq->eq_events[new_index];
 	int		rc;
-	ENTRY;
 
 	/* must called with lnet_eq_wait_lock hold */
 	if (LNET_SEQ_GT(eq->eq_deq_seq, new_event->sequence))
-		RETURN(0);
+		return 0;
 
 	/* We've got a new event... */
 	*ev = *new_event;
@@ -268,7 +267,7 @@ lnet_eq_dequeue_event(lnet_eq_t *eq, lnet_event_t *ev)
 	}
 
 	eq->eq_deq_seq = new_event->sequence + 1;
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -400,13 +399,12 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms,
 	int	wait = 1;
 	int	rc;
 	int	i;
-	ENTRY;
 
 	LASSERT (the_lnet.ln_init);
 	LASSERT (the_lnet.ln_refcount > 0);
 
 	if (neq < 1)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	lnet_eq_wait_lock();
 
@@ -416,14 +414,14 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms,
 
 			if (eq == NULL) {
 				lnet_eq_wait_unlock();
-				RETURN(-ENOENT);
+				return -ENOENT;
 			}
 
 			rc = lnet_eq_dequeue_event(eq, event);
 			if (rc != 0) {
 				lnet_eq_wait_unlock();
 				*which = i;
-				RETURN(rc);
+				return rc;
 			}
 		}
 
@@ -443,5 +441,5 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms,
 	}
 
 	lnet_eq_wait_unlock();
-	RETURN(0);
+	return 0;
 }
diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c
index 8f3a50b..fc7ba42 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-msg.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c
@@ -45,8 +45,6 @@
 void
 lnet_build_unlink_event (lnet_libmd_t *md, lnet_event_t *ev)
 {
-	ENTRY;
-
 	memset(ev, 0, sizeof(*ev));
 
 	ev->status   = 0;
@@ -54,7 +52,6 @@ lnet_build_unlink_event (lnet_libmd_t *md, lnet_event_t *ev)
 	ev->type     = LNET_EVENT_UNLINK;
 	lnet_md_deconstruct(md, &ev->md);
 	lnet_md2handle(&ev->md_handle, md);
-	EXIT;
 }
 
 /*
diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c
index c832385..afb8175 100644
--- a/drivers/staging/lustre/lnet/lnet/module.c
+++ b/drivers/staging/lustre/lnet/lnet/module.c
@@ -114,14 +114,13 @@ int
 init_lnet(void)
 {
 	int		  rc;
-	ENTRY;
 
 	mutex_init(&lnet_config_mutex);
 
 	rc = LNetInit();
 	if (rc != 0) {
 		CERROR("LNetInit: error %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = libcfs_register_ioctl(&lnet_ioctl_handler);
@@ -133,7 +132,7 @@ init_lnet(void)
 		(void) kthread_run(lnet_configure, NULL, "lnet_initd");
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 void
@@ -150,5 +149,7 @@ fini_lnet(void)
 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
 MODULE_DESCRIPTION("Portals v3.1");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
 
-cfs_module(lnet, "1.0.0", init_lnet, fini_lnet);
+module_init(init_lnet);
+module_exit(fini_lnet);
diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c
index 3084b0c..931f6ca2 100644
--- a/drivers/staging/lustre/lnet/lnet/router_proc.c
+++ b/drivers/staging/lustre/lnet/lnet/router_proc.c
@@ -920,7 +920,7 @@ lnet_proc_init(void)
 {
 #ifdef CONFIG_SYSCTL
 	if (lnet_table_header == NULL)
-		lnet_table_header = cfs_register_sysctl_table(top_table, 0);
+		lnet_table_header = register_sysctl_table(top_table);
 #endif
 }
 
diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c
index 78e8d04..09e4700 100644
--- a/drivers/staging/lustre/lnet/selftest/console.c
+++ b/drivers/staging/lustre/lnet/selftest/console.c
@@ -1773,7 +1773,7 @@ lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp,
 }
 
 int
-lstcon_session_end()
+lstcon_session_end(void)
 {
 	lstcon_rpc_trans_t *trans;
 	lstcon_group_t     *grp;
diff --git a/drivers/staging/lustre/lnet/selftest/module.c b/drivers/staging/lustre/lnet/selftest/module.c
index 5257e56..6dd4309 100644
--- a/drivers/staging/lustre/lnet/selftest/module.c
+++ b/drivers/staging/lustre/lnet/selftest/module.c
@@ -165,5 +165,7 @@ error:
 
 MODULE_DESCRIPTION("LNet Selftest");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("0.9.0");
 
-cfs_module(lnet, "0.9.0", lnet_selftest_init, lnet_selftest_fini);
+module_init(lnet_selftest_init);
+module_exit(lnet_selftest_fini);
diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c
index bc1f38b..0dfc76e 100644
--- a/drivers/staging/lustre/lnet/selftest/rpc.c
+++ b/drivers/staging/lustre/lnet/selftest/rpc.c
@@ -661,8 +661,10 @@ srpc_finish_service(struct srpc_service *sv)
 
 	cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
 		spin_lock(&scd->scd_lock);
-		if (!swi_deschedule_workitem(&scd->scd_buf_wi))
+		if (!swi_deschedule_workitem(&scd->scd_buf_wi)) {
+			spin_unlock(&scd->scd_lock);
 			return 0;
+		}
 
 		if (scd->scd_buf_nposted > 0) {
 			CDEBUG(D_NET, "waiting for %d posted buffers to unlink",
diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c
index 2c07855..3bf4afb 100644
--- a/drivers/staging/lustre/lnet/selftest/timer.c
+++ b/drivers/staging/lustre/lnet/selftest/timer.c
@@ -195,7 +195,7 @@ stt_timer_main (void *arg)
 int
 stt_start_timer_thread (void)
 {
-	task_t *task;
+	struct task_struct *task;
 
 	LASSERT(!stt_data.stt_shuttingdown);
 
diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig
index e0eb830..4e898e4 100644
--- a/drivers/staging/lustre/lustre/Kconfig
+++ b/drivers/staging/lustre/lustre/Kconfig
@@ -1,6 +1,6 @@
 config LUSTRE_FS
 	tristate "Lustre file system client support"
-	depends on STAGING && INET && BROKEN
+	depends on INET && m
 	select LNET
 	select CRYPTO
 	select CRYPTO_CRC32
@@ -43,9 +43,18 @@ config LUSTRE_OBD_MAX_IOCTL_BUFFER
 config LUSTRE_DEBUG_EXPENSIVE_CHECK
 	bool "Enable Lustre DEBUG checks"
 	depends on LUSTRE_FS
-	default false
 	help
 	  This option is mainly for debug purpose. It enables Lustre code to do
 	  expensive checks that may have a performance impact.
 
 	  Use with caution. If unsure, say N.
+
+config LUSTRE_TRANSLATE_ERRNOS
+	bool
+	depends on LUSTRE_FS && !X86
+	default true
+
+config LUSTRE_LLITE_LLOOP
+	bool "Lustre virtual block device"
+	depends on LUSTRE_FS && BLOCK
+	default m
diff --git a/drivers/staging/lustre/lustre/Makefile b/drivers/staging/lustre/lustre/Makefile
index 3fb94fc..d1eb0bd 100644
--- a/drivers/staging/lustre/lustre/Makefile
+++ b/drivers/staging/lustre/lustre/Makefile
@@ -1,2 +1,2 @@
-obj-$(CONFIG_LUSTRE_FS) := fid/ lvfs/ obdclass/ ptlrpc/ obdecho/ mgc/ lov/ \
-			   osc/ mdc/ lmv/ llite/ fld/ libcfs/
+obj-$(CONFIG_LUSTRE_FS) += libcfs/ lvfs/ obdclass/ ptlrpc/ fld/ osc/ mgc/ \
+			   fid/ lov/ mdc/ lmv/ llite/ obdecho/
diff --git a/drivers/staging/lustre/lustre/fid/Makefile b/drivers/staging/lustre/lustre/fid/Makefile
index b8d6d21..ed21bea 100644
--- a/drivers/staging/lustre/lustre/fid/Makefile
+++ b/drivers/staging/lustre/lustre/fid/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_LUSTRE_FS) += fid.o
-fid-y := fid_handler.o fid_store.o fid_request.o lproc_fid.o fid_lib.o
+fid-y := fid_request.o lproc_fid.o fid_lib.o
 
 
 ccflags-y := -I$(src)/../include
diff --git a/drivers/staging/lustre/lustre/fid/fid_handler.c b/drivers/staging/lustre/lustre/fid/fid_handler.c
deleted file mode 100644
index bbbb3cf..0000000
--- a/drivers/staging/lustre/lustre/fid/fid_handler.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/fid/fid_handler.c
- *
- * Lustre Sequence Manager
- *
- * Author: Yury Umanets <umka@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_FID
-
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <dt_object.h>
-#include <md_object.h>
-#include <obd_support.h>
-#include <lustre_req_layout.h>
-#include <lustre_fid.h>
-#include "fid_internal.h"
-
-int client_fid_init(struct obd_device *obd,
-		    struct obd_export *exp, enum lu_cli_type type)
-{
-	struct client_obd *cli = &obd->u.cli;
-	char *prefix;
-	int rc;
-	ENTRY;
-
-	OBD_ALLOC_PTR(cli->cl_seq);
-	if (cli->cl_seq == NULL)
-		RETURN(-ENOMEM);
-
-	OBD_ALLOC(prefix, MAX_OBD_NAME + 5);
-	if (prefix == NULL)
-		GOTO(out_free_seq, rc = -ENOMEM);
-
-	snprintf(prefix, MAX_OBD_NAME + 5, "cli-%s", obd->obd_name);
-
-	/* Init client side sequence-manager */
-	rc = seq_client_init(cli->cl_seq, exp, type, prefix, NULL);
-	OBD_FREE(prefix, MAX_OBD_NAME + 5);
-	if (rc)
-		GOTO(out_free_seq, rc);
-
-	RETURN(rc);
-out_free_seq:
-	OBD_FREE_PTR(cli->cl_seq);
-	cli->cl_seq = NULL;
-	return rc;
-}
-EXPORT_SYMBOL(client_fid_init);
-
-int client_fid_fini(struct obd_device *obd)
-{
-	struct client_obd *cli = &obd->u.cli;
-	ENTRY;
-
-	if (cli->cl_seq != NULL) {
-		seq_client_fini(cli->cl_seq);
-		OBD_FREE_PTR(cli->cl_seq);
-		cli->cl_seq = NULL;
-	}
-
-	RETURN(0);
-}
-EXPORT_SYMBOL(client_fid_fini);
-
-static void seq_server_proc_fini(struct lu_server_seq *seq);
-
-/* Assigns client to sequence controller node. */
-int seq_server_set_cli(struct lu_server_seq *seq,
-		       struct lu_client_seq *cli,
-		       const struct lu_env *env)
-{
-	int rc = 0;
-	ENTRY;
-
-	/*
-	 * Ask client for new range, assign that range to ->seq_space and write
-	 * seq state to backing store should be atomic.
-	 */
-	mutex_lock(&seq->lss_mutex);
-
-	if (cli == NULL) {
-		CDEBUG(D_INFO, "%s: Detached sequence client %s\n",
-		       seq->lss_name, cli->lcs_name);
-		seq->lss_cli = cli;
-		GOTO(out_up, rc = 0);
-	}
-
-	if (seq->lss_cli != NULL) {
-		CDEBUG(D_HA, "%s: Sequence controller is already "
-		       "assigned\n", seq->lss_name);
-		GOTO(out_up, rc = -EEXIST);
-	}
-
-	CDEBUG(D_INFO, "%s: Attached sequence controller %s\n",
-	       seq->lss_name, cli->lcs_name);
-
-	seq->lss_cli = cli;
-	cli->lcs_space.lsr_index = seq->lss_site->ss_node_id;
-	EXIT;
-out_up:
-	mutex_unlock(&seq->lss_mutex);
-	return rc;
-}
-EXPORT_SYMBOL(seq_server_set_cli);
-/*
- * allocate \a w units of sequence from range \a from.
- */
-static inline void range_alloc(struct lu_seq_range *to,
-			       struct lu_seq_range *from,
-			       __u64 width)
-{
-	width = min(range_space(from), width);
-	to->lsr_start = from->lsr_start;
-	to->lsr_end = from->lsr_start + width;
-	from->lsr_start += width;
-}
-
-/**
- * On controller node, allocate new super sequence for regular sequence server.
- * As this super sequence controller, this node suppose to maintain fld
- * and update index.
- * \a out range always has currect mds node number of requester.
- */
-
-static int __seq_server_alloc_super(struct lu_server_seq *seq,
-				    struct lu_seq_range *out,
-				    const struct lu_env *env)
-{
-	struct lu_seq_range *space = &seq->lss_space;
-	int rc;
-	ENTRY;
-
-	LASSERT(range_is_sane(space));
-
-	if (range_is_exhausted(space)) {
-		CERROR("%s: Sequences space is exhausted\n",
-		       seq->lss_name);
-		RETURN(-ENOSPC);
-	} else {
-		range_alloc(out, space, seq->lss_width);
-	}
-
-	rc = seq_store_update(env, seq, out, 1 /* sync */);
-
-	LCONSOLE_INFO("%s: super-sequence allocation rc = %d " DRANGE"\n",
-		      seq->lss_name, rc, PRANGE(out));
-
-	RETURN(rc);
-}
-
-int seq_server_alloc_super(struct lu_server_seq *seq,
-			   struct lu_seq_range *out,
-			   const struct lu_env *env)
-{
-	int rc;
-	ENTRY;
-
-	mutex_lock(&seq->lss_mutex);
-	rc = __seq_server_alloc_super(seq, out, env);
-	mutex_unlock(&seq->lss_mutex);
-
-	RETURN(rc);
-}
-
-static int __seq_set_init(const struct lu_env *env,
-			    struct lu_server_seq *seq)
-{
-	struct lu_seq_range *space = &seq->lss_space;
-	int rc;
-
-	range_alloc(&seq->lss_lowater_set, space, seq->lss_set_width);
-	range_alloc(&seq->lss_hiwater_set, space, seq->lss_set_width);
-
-	rc = seq_store_update(env, seq, NULL, 1);
-
-	return rc;
-}
-
-/*
- * This function implements new seq allocation algorithm using async
- * updates to seq file on disk. ref bug 18857 for details.
- * there are four variable to keep track of this process
- *
- * lss_space; - available lss_space
- * lss_lowater_set; - lu_seq_range for all seqs before barrier, i.e. safe to use
- * lss_hiwater_set; - lu_seq_range after barrier, i.e. allocated but may be
- *		    not yet committed
- *
- * when lss_lowater_set reaches the end it is replaced with hiwater one and
- * a write operation is initiated to allocate new hiwater range.
- * if last seq write opearion is still not commited, current operation is
- * flaged as sync write op.
- */
-static int range_alloc_set(const struct lu_env *env,
-			    struct lu_seq_range *out,
-			    struct lu_server_seq *seq)
-{
-	struct lu_seq_range *space = &seq->lss_space;
-	struct lu_seq_range *loset = &seq->lss_lowater_set;
-	struct lu_seq_range *hiset = &seq->lss_hiwater_set;
-	int rc = 0;
-
-	if (range_is_zero(loset))
-		__seq_set_init(env, seq);
-
-	if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_ALLOC)) /* exhaust set */
-		loset->lsr_start = loset->lsr_end;
-
-	if (range_is_exhausted(loset)) {
-		/* reached high water mark. */
-		struct lu_device *dev = seq->lss_site->ss_lu->ls_top_dev;
-		int obd_num_clients = dev->ld_obd->obd_num_exports;
-		__u64 set_sz;
-
-		/* calculate new seq width based on number of clients */
-		set_sz = max(seq->lss_set_width,
-			     obd_num_clients * seq->lss_width);
-		set_sz = min(range_space(space), set_sz);
-
-		/* Switch to hiwater range now */
-		*loset = *hiset;
-		/* allocate new hiwater range */
-		range_alloc(hiset, space, set_sz);
-
-		/* update ondisk seq with new *space */
-		rc = seq_store_update(env, seq, NULL, seq->lss_need_sync);
-	}
-
-	LASSERTF(!range_is_exhausted(loset) || range_is_sane(loset),
-		 DRANGE"\n", PRANGE(loset));
-
-	if (rc == 0)
-		range_alloc(out, loset, seq->lss_width);
-
-	RETURN(rc);
-}
-
-static int __seq_server_alloc_meta(struct lu_server_seq *seq,
-				   struct lu_seq_range *out,
-				   const struct lu_env *env)
-{
-	struct lu_seq_range *space = &seq->lss_space;
-	int rc = 0;
-
-	ENTRY;
-
-	LASSERT(range_is_sane(space));
-
-	/* Check if available space ends and allocate new super seq */
-	if (range_is_exhausted(space)) {
-		if (!seq->lss_cli) {
-			CERROR("%s: No sequence controller is attached.\n",
-			       seq->lss_name);
-			RETURN(-ENODEV);
-		}
-
-		rc = seq_client_alloc_super(seq->lss_cli, env);
-		if (rc) {
-			CERROR("%s: Can't allocate super-sequence, rc %d\n",
-			       seq->lss_name, rc);
-			RETURN(rc);
-		}
-
-		/* Saving new range to allocation space. */
-		*space = seq->lss_cli->lcs_space;
-		LASSERT(range_is_sane(space));
-	}
-
-	rc = range_alloc_set(env, out, seq);
-	if (rc != 0) {
-		CERROR("%s: Allocated meta-sequence failed: rc = %d\n",
-			seq->lss_name, rc);
-		RETURN(rc);
-	}
-
-	CDEBUG(D_INFO, "%s: Allocated meta-sequence " DRANGE"\n",
-		seq->lss_name, PRANGE(out));
-
-	RETURN(rc);
-}
-
-int seq_server_alloc_meta(struct lu_server_seq *seq,
-			  struct lu_seq_range *out,
-			  const struct lu_env *env)
-{
-	int rc;
-	ENTRY;
-
-	mutex_lock(&seq->lss_mutex);
-	rc = __seq_server_alloc_meta(seq, out, env);
-	mutex_unlock(&seq->lss_mutex);
-
-	RETURN(rc);
-}
-EXPORT_SYMBOL(seq_server_alloc_meta);
-
-static int seq_server_handle(struct lu_site *site,
-			     const struct lu_env *env,
-			     __u32 opc, struct lu_seq_range *out)
-{
-	int rc;
-	struct seq_server_site *ss_site;
-	ENTRY;
-
-	ss_site = lu_site2seq(site);
-
-	switch (opc) {
-	case SEQ_ALLOC_META:
-		if (!ss_site->ss_server_seq) {
-			CERROR("Sequence server is not "
-			       "initialized\n");
-			RETURN(-EINVAL);
-		}
-		rc = seq_server_alloc_meta(ss_site->ss_server_seq, out, env);
-		break;
-	case SEQ_ALLOC_SUPER:
-		if (!ss_site->ss_control_seq) {
-			CERROR("Sequence controller is not "
-			       "initialized\n");
-			RETURN(-EINVAL);
-		}
-		rc = seq_server_alloc_super(ss_site->ss_control_seq, out, env);
-		break;
-	default:
-		rc = -EINVAL;
-		break;
-	}
-
-	RETURN(rc);
-}
-
-static int seq_req_handle(struct ptlrpc_request *req,
-			  const struct lu_env *env,
-			  struct seq_thread_info *info)
-{
-	struct lu_seq_range *out, *tmp;
-	struct lu_site *site;
-	int rc = -EPROTO;
-	__u32 *opc;
-	ENTRY;
-
-	LASSERT(!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY));
-	site = req->rq_export->exp_obd->obd_lu_dev->ld_site;
-	LASSERT(site != NULL);
-
-	rc = req_capsule_server_pack(info->sti_pill);
-	if (rc)
-		RETURN(err_serious(rc));
-
-	opc = req_capsule_client_get(info->sti_pill, &RMF_SEQ_OPC);
-	if (opc != NULL) {
-		out = req_capsule_server_get(info->sti_pill, &RMF_SEQ_RANGE);
-		if (out == NULL)
-			RETURN(err_serious(-EPROTO));
-
-		tmp = req_capsule_client_get(info->sti_pill, &RMF_SEQ_RANGE);
-
-		/* seq client passed mdt id, we need to pass that using out
-		 * range parameter */
-
-		out->lsr_index = tmp->lsr_index;
-		out->lsr_flags = tmp->lsr_flags;
-		rc = seq_server_handle(site, env, *opc, out);
-	} else
-		rc = err_serious(-EPROTO);
-
-	RETURN(rc);
-}
-
-/* context key constructor/destructor: seq_key_init, seq_key_fini */
-LU_KEY_INIT_FINI(seq, struct seq_thread_info);
-
-/* context key: seq_thread_key */
-LU_CONTEXT_KEY_DEFINE(seq, LCT_MD_THREAD | LCT_DT_THREAD);
-
-static void seq_thread_info_init(struct ptlrpc_request *req,
-				 struct seq_thread_info *info)
-{
-	info->sti_pill = &req->rq_pill;
-	/* Init request capsule */
-	req_capsule_init(info->sti_pill, req, RCL_SERVER);
-	req_capsule_set(info->sti_pill, &RQF_SEQ_QUERY);
-}
-
-static void seq_thread_info_fini(struct seq_thread_info *info)
-{
-	req_capsule_fini(info->sti_pill);
-}
-
-int seq_handle(struct ptlrpc_request *req)
-{
-	const struct lu_env *env;
-	struct seq_thread_info *info;
-	int rc;
-
-	env = req->rq_svc_thread->t_env;
-	LASSERT(env != NULL);
-
-	info = lu_context_key_get(&env->le_ctx, &seq_thread_key);
-	LASSERT(info != NULL);
-
-	seq_thread_info_init(req, info);
-	rc = seq_req_handle(req, env, info);
-	/* XXX: we don't need replay but MDT assign transno in any case,
-	 * remove it manually before reply*/
-	lustre_msg_set_transno(req->rq_repmsg, 0);
-	seq_thread_info_fini(info);
-
-	return rc;
-}
-EXPORT_SYMBOL(seq_handle);
-
-/*
- * Entry point for handling FLD RPCs called from MDT.
- */
-int seq_query(struct com_thread_info *info)
-{
-	return seq_handle(info->cti_pill->rc_req);
-}
-EXPORT_SYMBOL(seq_query);
-
-
-#ifdef LPROCFS
-static int seq_server_proc_init(struct lu_server_seq *seq)
-{
-	int rc;
-	ENTRY;
-
-	seq->lss_proc_dir = lprocfs_register(seq->lss_name,
-					     seq_type_proc_dir,
-					     NULL, NULL);
-	if (IS_ERR(seq->lss_proc_dir)) {
-		rc = PTR_ERR(seq->lss_proc_dir);
-		RETURN(rc);
-	}
-
-	rc = lprocfs_add_vars(seq->lss_proc_dir,
-			      seq_server_proc_list, seq);
-	if (rc) {
-		CERROR("%s: Can't init sequence manager "
-		       "proc, rc %d\n", seq->lss_name, rc);
-		GOTO(out_cleanup, rc);
-	}
-
-	RETURN(0);
-
-out_cleanup:
-	seq_server_proc_fini(seq);
-	return rc;
-}
-
-static void seq_server_proc_fini(struct lu_server_seq *seq)
-{
-	ENTRY;
-	if (seq->lss_proc_dir != NULL) {
-		if (!IS_ERR(seq->lss_proc_dir))
-			lprocfs_remove(&seq->lss_proc_dir);
-		seq->lss_proc_dir = NULL;
-	}
-	EXIT;
-}
-#else
-static int seq_server_proc_init(struct lu_server_seq *seq)
-{
-	return 0;
-}
-
-static void seq_server_proc_fini(struct lu_server_seq *seq)
-{
-	return;
-}
-#endif
-
-
-int seq_server_init(struct lu_server_seq *seq,
-		    struct dt_device *dev,
-		    const char *prefix,
-		    enum lu_mgr_type type,
-		    struct seq_server_site *ss,
-		    const struct lu_env *env)
-{
-	int rc, is_srv = (type == LUSTRE_SEQ_SERVER);
-	ENTRY;
-
-	LASSERT(dev != NULL);
-	LASSERT(prefix != NULL);
-	LASSERT(ss != NULL);
-	LASSERT(ss->ss_lu != NULL);
-
-	seq->lss_cli = NULL;
-	seq->lss_type = type;
-	seq->lss_site = ss;
-	range_init(&seq->lss_space);
-
-	range_init(&seq->lss_lowater_set);
-	range_init(&seq->lss_hiwater_set);
-	seq->lss_set_width = LUSTRE_SEQ_BATCH_WIDTH;
-
-	mutex_init(&seq->lss_mutex);
-
-	seq->lss_width = is_srv ?
-		LUSTRE_SEQ_META_WIDTH : LUSTRE_SEQ_SUPER_WIDTH;
-
-	snprintf(seq->lss_name, sizeof(seq->lss_name),
-		 "%s-%s", (is_srv ? "srv" : "ctl"), prefix);
-
-	rc = seq_store_init(seq, env, dev);
-	if (rc)
-		GOTO(out, rc);
-	/* Request backing store for saved sequence info. */
-	rc = seq_store_read(seq, env);
-	if (rc == -ENODATA) {
-
-		/* Nothing is read, init by default value. */
-		seq->lss_space = is_srv ?
-			LUSTRE_SEQ_ZERO_RANGE:
-			LUSTRE_SEQ_SPACE_RANGE;
-
-		LASSERT(ss != NULL);
-		seq->lss_space.lsr_index = ss->ss_node_id;
-		LCONSOLE_INFO("%s: No data found "
-			      "on store. Initialize space\n",
-			      seq->lss_name);
-
-		rc = seq_store_update(env, seq, NULL, 0);
-		if (rc) {
-			CERROR("%s: Can't write space data, "
-			       "rc %d\n", seq->lss_name, rc);
-		}
-	} else if (rc) {
-		CERROR("%s: Can't read space data, rc %d\n",
-		       seq->lss_name, rc);
-		GOTO(out, rc);
-	}
-
-	if (is_srv) {
-		LASSERT(range_is_sane(&seq->lss_space));
-	} else {
-		LASSERT(!range_is_zero(&seq->lss_space) &&
-			range_is_sane(&seq->lss_space));
-	}
-
-	rc  = seq_server_proc_init(seq);
-	if (rc)
-		GOTO(out, rc);
-
-	EXIT;
-out:
-	if (rc)
-		seq_server_fini(seq, env);
-	return rc;
-}
-EXPORT_SYMBOL(seq_server_init);
-
-void seq_server_fini(struct lu_server_seq *seq,
-		     const struct lu_env *env)
-{
-	ENTRY;
-
-	seq_server_proc_fini(seq);
-	seq_store_fini(seq, env);
-
-	EXIT;
-}
-EXPORT_SYMBOL(seq_server_fini);
-
-int seq_site_fini(const struct lu_env *env, struct seq_server_site *ss)
-{
-	if (ss == NULL)
-		RETURN(0);
-
-	if (ss->ss_server_seq) {
-		seq_server_fini(ss->ss_server_seq, env);
-		OBD_FREE_PTR(ss->ss_server_seq);
-		ss->ss_server_seq = NULL;
-	}
-
-	if (ss->ss_control_seq) {
-		seq_server_fini(ss->ss_control_seq, env);
-		OBD_FREE_PTR(ss->ss_control_seq);
-		ss->ss_control_seq = NULL;
-	}
-
-	if (ss->ss_client_seq) {
-		seq_client_fini(ss->ss_client_seq);
-		OBD_FREE_PTR(ss->ss_client_seq);
-		ss->ss_client_seq = NULL;
-	}
-
-	RETURN(0);
-}
-EXPORT_SYMBOL(seq_site_fini);
-
-proc_dir_entry_t *seq_type_proc_dir = NULL;
-
-static int __init fid_mod_init(void)
-{
-	seq_type_proc_dir = lprocfs_register(LUSTRE_SEQ_NAME,
-					     proc_lustre_root,
-					     NULL, NULL);
-	if (IS_ERR(seq_type_proc_dir))
-		return PTR_ERR(seq_type_proc_dir);
-
-	LU_CONTEXT_KEY_INIT(&seq_thread_key);
-	lu_context_key_register(&seq_thread_key);
-	return 0;
-}
-
-static void __exit fid_mod_exit(void)
-{
-	lu_context_key_degister(&seq_thread_key);
-	if (seq_type_proc_dir != NULL && !IS_ERR(seq_type_proc_dir)) {
-		lprocfs_remove(&seq_type_proc_dir);
-		seq_type_proc_dir = NULL;
-	}
-}
-
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("Lustre FID Module");
-MODULE_LICENSE("GPL");
-
-cfs_module(fid, "0.1.0", fid_mod_init, fid_mod_exit);
diff --git a/drivers/staging/lustre/lustre/fid/fid_internal.h b/drivers/staging/lustre/lustre/fid/fid_internal.h
index 407a743..1dbe46b 100644
--- a/drivers/staging/lustre/lustre/fid/fid_internal.h
+++ b/drivers/staging/lustre/lustre/fid/fid_internal.h
@@ -41,44 +41,16 @@
 #define __FID_INTERNAL_H
 
 #include <lustre/lustre_idl.h>
-#include <dt_object.h>
-
 #include <linux/libcfs/libcfs.h>
 
-struct seq_thread_info {
-	struct req_capsule     *sti_pill;
-	struct lu_seq_range     sti_space;
-	struct lu_buf	   sti_buf;
-};
-
-enum {
-	SEQ_TXN_STORE_CREDITS = 20
-};
-
-extern struct lu_context_key seq_thread_key;
-
+/* Functions used internally in module. */
 int seq_client_alloc_super(struct lu_client_seq *seq,
 			   const struct lu_env *env);
-/* Store API functions. */
-int seq_store_init(struct lu_server_seq *seq,
-		   const struct lu_env *env,
-		   struct dt_device *dt);
 
-void seq_store_fini(struct lu_server_seq *seq,
-		    const struct lu_env *env);
-
-int seq_store_read(struct lu_server_seq *seq,
-		   const struct lu_env *env);
-
-int seq_store_update(const struct lu_env *env, struct lu_server_seq *seq,
-		     struct lu_seq_range *out, int sync);
-
-#ifdef LPROCFS
-extern struct lprocfs_vars seq_server_proc_list[];
+# ifdef LPROCFS
 extern struct lprocfs_vars seq_client_proc_list[];
-#endif
-
+# endif
 
-extern proc_dir_entry_t *seq_type_proc_dir;
+extern struct proc_dir_entry *seq_type_proc_dir;
 
 #endif /* __FID_INTERNAL_H */
diff --git a/drivers/staging/lustre/lustre/fid/fid_lib.c b/drivers/staging/lustre/lustre/fid/fid_lib.c
index eaff51a..f03afde 100644
--- a/drivers/staging/lustre/lustre/fid/fid_lib.c
+++ b/drivers/staging/lustre/lustre/fid/fid_lib.c
@@ -43,11 +43,9 @@
 
 #define DEBUG_SUBSYSTEM S_FID
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-
-#include <obd.h>
-#include <lu_object.h>
+#include <linux/libcfs/libcfs.h>
+#include <linux/module.h>
+#include <lustre/lustre_idl.h>
 #include <lustre_fid.h>
 
 /**
@@ -56,9 +54,9 @@
  *
  * Fid namespace:
  * <pre>
- * Normal FID:	seq:64 [2^33,2^64-1]      oid:32	  ver:32
- * IGIF      :	0:32, ino:32	      gen:32	  0:32
- * IDIF      :	0:31, 1:1, ost-index:16,  objd:48	 0:32
+ * Normal FID:        seq:64 [2^33,2^64-1]      oid:32          ver:32
+ * IGIF      :        0:32, ino:32              gen:32          0:32
+ * IDIF      :        0:31, 1:1, ost-index:16,  objd:48         0:32
  * </pre>
  *
  * The first 0x400 sequences of normal FID are reserved for special purpose.
diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c
index fcaaca7..66007b5 100644
--- a/drivers/staging/lustre/lustre/fid/fid_request.c
+++ b/drivers/staging/lustre/lustre/fid/fid_request.c
@@ -27,7 +27,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2012, Intel Corporation.
+ * Copyright (c) 2011, 2013, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -42,15 +42,12 @@
 
 #define DEBUG_SUBSYSTEM S_FID
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
+#include <linux/libcfs/libcfs.h>
+#include <linux/module.h>
 
 #include <obd.h>
 #include <obd_class.h>
-#include <dt_object.h>
-#include <md_object.h>
 #include <obd_support.h>
-#include <lustre_req_layout.h>
 #include <lustre_fid.h>
 /* mdc RPC locks */
 #include <lustre_mdc.h>
@@ -63,15 +60,14 @@ static int seq_client_rpc(struct lu_client_seq *seq,
 	struct obd_export     *exp = seq->lcs_exp;
 	struct ptlrpc_request *req;
 	struct lu_seq_range   *out, *in;
-	__u32		 *op;
-	unsigned int	   debug_mask;
-	int		    rc;
-	ENTRY;
+	__u32                 *op;
+	unsigned int           debug_mask;
+	int                    rc;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_SEQ_QUERY,
 					LUSTRE_MDS_VERSION, SEQ_QUERY);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* Init operation code */
 	op = req_capsule_client_get(&req->rq_pill, &RMF_SEQ_OPC);
@@ -137,7 +133,6 @@ static int seq_client_rpc(struct lu_client_seq *seq,
 	CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence "DRANGE"]\n",
 		     seq->lcs_name, opcname, PRANGE(output));
 
-	EXIT;
 out_req:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -148,27 +143,24 @@ int seq_client_alloc_super(struct lu_client_seq *seq,
 			   const struct lu_env *env)
 {
 	int rc;
-	ENTRY;
 
 	mutex_lock(&seq->lcs_mutex);
 
 	if (seq->lcs_srv) {
-		LASSERT(env != NULL);
-		rc = seq_server_alloc_super(seq->lcs_srv, &seq->lcs_space,
-					    env);
+		rc = 0;
 	} else {
 		/* Check whether the connection to seq controller has been
 		 * setup (lcs_exp != NULL) */
 		if (seq->lcs_exp == NULL) {
 			mutex_unlock(&seq->lcs_mutex);
-			RETURN(-EINPROGRESS);
+			return -EINPROGRESS;
 		}
 
 		rc = seq_client_rpc(seq, &seq->lcs_space,
 				    SEQ_ALLOC_SUPER, "super");
 	}
 	mutex_unlock(&seq->lcs_mutex);
-	RETURN(rc);
+	return rc;
 }
 
 /* Request sequence-controller node to allocate new meta-sequence. */
@@ -176,11 +168,9 @@ static int seq_client_alloc_meta(const struct lu_env *env,
 				 struct lu_client_seq *seq)
 {
 	int rc;
-	ENTRY;
 
 	if (seq->lcs_srv) {
-		LASSERT(env != NULL);
-		rc = seq_server_alloc_meta(seq->lcs_srv, &seq->lcs_space, env);
+		rc = 0;
 	} else {
 		do {
 			/* If meta server return -EINPROGRESS or EAGAIN,
@@ -191,7 +181,8 @@ static int seq_client_alloc_meta(const struct lu_env *env,
 					    SEQ_ALLOC_META, "meta");
 		} while (rc == -EINPROGRESS || rc == -EAGAIN);
 	}
-	RETURN(rc);
+
+	return rc;
 }
 
 /* Allocate new sequence for client. */
@@ -199,7 +190,6 @@ static int seq_client_alloc_seq(const struct lu_env *env,
 				struct lu_client_seq *seq, seqno_t *seqnr)
 {
 	int rc;
-	ENTRY;
 
 	LASSERT(range_is_sane(&seq->lcs_space));
 
@@ -208,7 +198,7 @@ static int seq_client_alloc_seq(const struct lu_env *env,
 		if (rc) {
 			CERROR("%s: Can't allocate new meta-sequence,"
 			       "rc %d\n", seq->lcs_name, rc);
-			RETURN(rc);
+			return rc;
 		} else {
 			CDEBUG(D_INFO, "%s: New range - "DRANGE"\n",
 			       seq->lcs_name, PRANGE(&seq->lcs_space));
@@ -224,7 +214,7 @@ static int seq_client_alloc_seq(const struct lu_env *env,
 	CDEBUG(D_INFO, "%s: Allocated sequence ["LPX64"]\n", seq->lcs_name,
 	       *seqnr);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int seq_fid_alloc_prep(struct lu_client_seq *seq,
@@ -312,7 +302,6 @@ int seq_client_alloc_fid(const struct lu_env *env,
 {
 	wait_queue_t link;
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 	LASSERT(fid != NULL);
@@ -344,7 +333,7 @@ int seq_client_alloc_fid(const struct lu_env *env,
 			       "rc %d\n", seq->lcs_name, rc);
 			seq_fid_alloc_fini(seq);
 			mutex_unlock(&seq->lcs_mutex);
-			RETURN(rc);
+			return rc;
 		}
 
 		CDEBUG(D_INFO, "%s: Switch to sequence "
@@ -368,7 +357,7 @@ int seq_client_alloc_fid(const struct lu_env *env,
 	mutex_unlock(&seq->lcs_mutex);
 
 	CDEBUG(D_INFO, "%s: Allocated FID "DFID"\n", seq->lcs_name,  PFID(fid));
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(seq_client_alloc_fid);
 
@@ -409,13 +398,21 @@ void seq_client_flush(struct lu_client_seq *seq)
 }
 EXPORT_SYMBOL(seq_client_flush);
 
-static void seq_client_proc_fini(struct lu_client_seq *seq);
-
+static void seq_client_proc_fini(struct lu_client_seq *seq)
+{
 #ifdef LPROCFS
+	if (seq->lcs_proc_dir) {
+		if (!IS_ERR(seq->lcs_proc_dir))
+			lprocfs_remove(&seq->lcs_proc_dir);
+		seq->lcs_proc_dir = NULL;
+	}
+#endif /* LPROCFS */
+}
+
 static int seq_client_proc_init(struct lu_client_seq *seq)
 {
+#ifdef LPROCFS
 	int rc;
-	ENTRY;
 
 	seq->lcs_proc_dir = lprocfs_register(seq->lcs_name,
 					     seq_type_proc_dir,
@@ -425,7 +422,7 @@ static int seq_client_proc_init(struct lu_client_seq *seq)
 		CERROR("%s: LProcFS failed in seq-init\n",
 		       seq->lcs_name);
 		rc = PTR_ERR(seq->lcs_proc_dir);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = lprocfs_add_vars(seq->lcs_proc_dir,
@@ -436,34 +433,16 @@ static int seq_client_proc_init(struct lu_client_seq *seq)
 		GOTO(out_cleanup, rc);
 	}
 
-	RETURN(0);
+	return 0;
 
 out_cleanup:
 	seq_client_proc_fini(seq);
 	return rc;
-}
 
-static void seq_client_proc_fini(struct lu_client_seq *seq)
-{
-	ENTRY;
-	if (seq->lcs_proc_dir) {
-		if (!IS_ERR(seq->lcs_proc_dir))
-			lprocfs_remove(&seq->lcs_proc_dir);
-		seq->lcs_proc_dir = NULL;
-	}
-	EXIT;
-}
-#else
-static int seq_client_proc_init(struct lu_client_seq *seq)
-{
+#else /* LPROCFS */
 	return 0;
-}
-
-static void seq_client_proc_fini(struct lu_client_seq *seq)
-{
-	return;
-}
 #endif
+}
 
 int seq_client_init(struct lu_client_seq *seq,
 		    struct obd_export *exp,
@@ -472,7 +451,6 @@ int seq_client_init(struct lu_client_seq *seq,
 		    struct lu_server_seq *srv)
 {
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 	LASSERT(prefix != NULL);
@@ -501,14 +479,12 @@ int seq_client_init(struct lu_client_seq *seq,
 	rc = seq_client_proc_init(seq);
 	if (rc)
 		seq_client_fini(seq);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(seq_client_init);
 
 void seq_client_fini(struct lu_client_seq *seq)
 {
-	ENTRY;
-
 	seq_client_proc_fini(seq);
 
 	if (seq->lcs_exp != NULL) {
@@ -517,6 +493,78 @@ void seq_client_fini(struct lu_client_seq *seq)
 	}
 
 	seq->lcs_srv = NULL;
-	EXIT;
 }
 EXPORT_SYMBOL(seq_client_fini);
+
+int client_fid_init(struct obd_device *obd,
+		    struct obd_export *exp, enum lu_cli_type type)
+{
+	struct client_obd *cli = &obd->u.cli;
+	char *prefix;
+	int rc;
+
+	OBD_ALLOC_PTR(cli->cl_seq);
+	if (cli->cl_seq == NULL)
+		return -ENOMEM;
+
+	OBD_ALLOC(prefix, MAX_OBD_NAME + 5);
+	if (prefix == NULL)
+		GOTO(out_free_seq, rc = -ENOMEM);
+
+	snprintf(prefix, MAX_OBD_NAME + 5, "cli-%s", obd->obd_name);
+
+	/* Init client side sequence-manager */
+	rc = seq_client_init(cli->cl_seq, exp, type, prefix, NULL);
+	OBD_FREE(prefix, MAX_OBD_NAME + 5);
+	if (rc)
+		GOTO(out_free_seq, rc);
+
+	return rc;
+out_free_seq:
+	OBD_FREE_PTR(cli->cl_seq);
+	cli->cl_seq = NULL;
+	return rc;
+}
+EXPORT_SYMBOL(client_fid_init);
+
+int client_fid_fini(struct obd_device *obd)
+{
+	struct client_obd *cli = &obd->u.cli;
+
+	if (cli->cl_seq != NULL) {
+		seq_client_fini(cli->cl_seq);
+		OBD_FREE_PTR(cli->cl_seq);
+		cli->cl_seq = NULL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(client_fid_fini);
+
+struct proc_dir_entry *seq_type_proc_dir;
+
+static int __init fid_mod_init(void)
+{
+	seq_type_proc_dir = lprocfs_register(LUSTRE_SEQ_NAME,
+					     proc_lustre_root,
+					     NULL, NULL);
+	if (IS_ERR(seq_type_proc_dir))
+		return PTR_ERR(seq_type_proc_dir);
+	return 0;
+}
+
+static void __exit fid_mod_exit(void)
+{
+	if (seq_type_proc_dir != NULL && !IS_ERR(seq_type_proc_dir)) {
+		lprocfs_remove(&seq_type_proc_dir);
+		seq_type_proc_dir = NULL;
+	}
+}
+
+MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_DESCRIPTION("Lustre FID Module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1.0");
+
+module_init(fid_mod_init);
+module_exit(fid_mod_exit);
diff --git a/drivers/staging/lustre/lustre/fid/fid_store.c b/drivers/staging/lustre/lustre/fid/fid_store.c
deleted file mode 100644
index a90e6e3..0000000
--- a/drivers/staging/lustre/lustre/fid/fid_store.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2013, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/fid/fid_store.c
- *
- * Lustre Sequence Manager
- *
- * Author: Yury Umanets <umka@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_FID
-
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <dt_object.h>
-#include <md_object.h>
-#include <obd_support.h>
-#include <lustre_req_layout.h>
-#include <lustre_fid.h>
-#include "fid_internal.h"
-
-
-static struct lu_buf *seq_store_buf(struct seq_thread_info *info)
-{
-	struct lu_buf *buf;
-
-	buf = &info->sti_buf;
-	buf->lb_buf = &info->sti_space;
-	buf->lb_len = sizeof(info->sti_space);
-	return buf;
-}
-
-struct seq_update_callback {
-	struct dt_txn_commit_cb suc_cb;
-	struct lu_server_seq   *suc_seq;
-};
-
-void seq_update_cb(struct lu_env *env, struct thandle *th,
-		   struct dt_txn_commit_cb *cb, int err)
-{
-	struct seq_update_callback *ccb;
-
-	ccb = container_of0(cb, struct seq_update_callback, suc_cb);
-
-	LASSERT(ccb->suc_seq != NULL);
-
-	ccb->suc_seq->lss_need_sync = 0;
-	OBD_FREE_PTR(ccb);
-}
-
-int seq_update_cb_add(struct thandle *th, struct lu_server_seq *seq)
-{
-	struct seq_update_callback *ccb;
-	struct dt_txn_commit_cb	   *dcb;
-	int			   rc;
-
-	OBD_ALLOC_PTR(ccb);
-	if (ccb == NULL)
-		return -ENOMEM;
-
-	ccb->suc_seq	   = seq;
-	seq->lss_need_sync = 1;
-
-	dcb	       = &ccb->suc_cb;
-	dcb->dcb_func  = seq_update_cb;
-	INIT_LIST_HEAD(&dcb->dcb_linkage);
-	strncpy(dcb->dcb_name, "seq_update_cb", MAX_COMMIT_CB_STR_LEN);
-	dcb->dcb_name[MAX_COMMIT_CB_STR_LEN - 1] = '\0';
-
-	rc = dt_trans_cb_add(th, dcb);
-	if (rc)
-		OBD_FREE_PTR(ccb);
-	return rc;
-}
-
-/* This function implies that caller takes care about locking. */
-int seq_store_update(const struct lu_env *env, struct lu_server_seq *seq,
-		     struct lu_seq_range *out, int sync)
-{
-	struct dt_device *dt_dev = lu2dt_dev(seq->lss_obj->do_lu.lo_dev);
-	struct seq_thread_info *info;
-	struct thandle *th;
-	loff_t pos = 0;
-	int rc;
-
-	info = lu_context_key_get(&env->le_ctx, &seq_thread_key);
-	LASSERT(info != NULL);
-
-	th = dt_trans_create(env, dt_dev);
-	if (IS_ERR(th))
-		RETURN(PTR_ERR(th));
-
-	rc = dt_declare_record_write(env, seq->lss_obj,
-				     sizeof(struct lu_seq_range), 0, th);
-	if (rc)
-		GOTO(exit, rc);
-
-	if (out != NULL) {
-		rc = fld_declare_server_create(env,
-					       seq->lss_site->ss_server_fld,
-					       out, th);
-		if (rc)
-			GOTO(exit, rc);
-	}
-
-	rc = dt_trans_start_local(env, dt_dev, th);
-	if (rc)
-		GOTO(exit, rc);
-
-	/* Store ranges in le format. */
-	range_cpu_to_le(&info->sti_space, &seq->lss_space);
-
-	rc = dt_record_write(env, seq->lss_obj, seq_store_buf(info), &pos, th);
-	if (rc) {
-		CERROR("%s: Can't write space data, rc %d\n",
-		       seq->lss_name, rc);
-		GOTO(exit, rc);
-	} else if (out != NULL) {
-		rc = fld_server_create(env, seq->lss_site->ss_server_fld, out,
-				       th);
-		if (rc) {
-			CERROR("%s: Can't Update fld database, rc %d\n",
-				seq->lss_name, rc);
-			GOTO(exit, rc);
-		}
-	}
-	/* next sequence update will need sync until this update is committed
-	 * in case of sync operation this is not needed obviously */
-	if (!sync)
-		/* if callback can't be added then sync always */
-		sync = !!seq_update_cb_add(th, seq);
-
-	th->th_sync |= sync;
-exit:
-	dt_trans_stop(env, dt_dev, th);
-	return rc;
-}
-
-/*
- * This function implies that caller takes care about locking or locking is not
- * needed (init time).
- */
-int seq_store_read(struct lu_server_seq *seq,
-		   const struct lu_env *env)
-{
-	struct seq_thread_info *info;
-	loff_t pos = 0;
-	int rc;
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &seq_thread_key);
-	LASSERT(info != NULL);
-
-	rc = seq->lss_obj->do_body_ops->dbo_read(env, seq->lss_obj,
-						 seq_store_buf(info),
-						 &pos, BYPASS_CAPA);
-
-	if (rc == sizeof(info->sti_space)) {
-		range_le_to_cpu(&seq->lss_space, &info->sti_space);
-		CDEBUG(D_INFO, "%s: Space - "DRANGE"\n",
-		       seq->lss_name, PRANGE(&seq->lss_space));
-		rc = 0;
-	} else if (rc == 0) {
-		rc = -ENODATA;
-	} else if (rc > 0) {
-		CERROR("%s: Read only %d bytes of %d\n", seq->lss_name,
-		       rc, (int)sizeof(info->sti_space));
-		rc = -EIO;
-	}
-
-	RETURN(rc);
-}
-
-int seq_store_init(struct lu_server_seq *seq,
-		   const struct lu_env *env,
-		   struct dt_device *dt)
-{
-	struct dt_object *dt_obj;
-	struct lu_fid fid;
-	struct lu_attr attr;
-	struct dt_object_format dof;
-	const char *name;
-	int rc;
-	ENTRY;
-
-	name = seq->lss_type == LUSTRE_SEQ_SERVER ?
-		LUSTRE_SEQ_SRV_NAME : LUSTRE_SEQ_CTL_NAME;
-
-	if (seq->lss_type == LUSTRE_SEQ_SERVER)
-		lu_local_obj_fid(&fid, FID_SEQ_SRV_OID);
-	else
-		lu_local_obj_fid(&fid, FID_SEQ_CTL_OID);
-
-	memset(&attr, 0, sizeof(attr));
-	attr.la_valid = LA_MODE;
-	attr.la_mode = S_IFREG | 0666;
-	dof.dof_type = DFT_REGULAR;
-
-	dt_obj = dt_find_or_create(env, dt, &fid, &dof, &attr);
-	if (!IS_ERR(dt_obj)) {
-		seq->lss_obj = dt_obj;
-		rc = 0;
-	} else {
-		CERROR("%s: Can't find \"%s\" obj %d\n",
-		       seq->lss_name, name, (int)PTR_ERR(dt_obj));
-		rc = PTR_ERR(dt_obj);
-	}
-
-	RETURN(rc);
-}
-
-void seq_store_fini(struct lu_server_seq *seq,
-		    const struct lu_env *env)
-{
-	ENTRY;
-
-	if (seq->lss_obj != NULL) {
-		if (!IS_ERR(seq->lss_obj))
-			lu_object_put(env, &seq->lss_obj->do_lu);
-		seq->lss_obj = NULL;
-	}
-
-	EXIT;
-}
diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c
index af817a8..294070d 100644
--- a/drivers/staging/lustre/lustre/fid/lproc_fid.c
+++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c
@@ -65,7 +65,6 @@ lprocfs_fid_write_common(const char *buffer, unsigned long count,
 {
 	struct lu_seq_range tmp;
 	int rc;
-	ENTRY;
 
 	LASSERT(range != NULL);
 
@@ -73,9 +72,9 @@ lprocfs_fid_write_common(const char *buffer, unsigned long count,
 		    (long long unsigned *)&tmp.lsr_start,
 		    (long long unsigned *)&tmp.lsr_end);
 	if (rc != 2 || !range_is_sane(&tmp) || range_is_zero(&tmp))
-		RETURN(-EINVAL);
+		return -EINVAL;
 	*range = tmp;
-	RETURN(0);
+	return 0;
 }
 
 /* Client side procfs stuff */
@@ -85,7 +84,6 @@ lprocfs_fid_space_seq_write(struct file *file, const char *buffer,
 {
 	struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 
@@ -99,7 +97,7 @@ lprocfs_fid_space_seq_write(struct file *file, const char *buffer,
 
 	mutex_unlock(&seq->lcs_mutex);
 
-	RETURN(count);
+	return count;
 }
 
 static int
@@ -107,7 +105,6 @@ lprocfs_fid_space_seq_show(struct seq_file *m, void *unused)
 {
 	struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 
@@ -115,7 +112,7 @@ lprocfs_fid_space_seq_show(struct seq_file *m, void *unused)
 	rc = seq_printf(m, "["LPX64" - "LPX64"]:%x:%s\n", PRANGE(&seq->lcs_space));
 	mutex_unlock(&seq->lcs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 
 static ssize_t
@@ -125,13 +122,12 @@ lprocfs_fid_width_seq_write(struct file *file, const char *buffer,
 	struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
 	__u64  max;
 	int rc, val;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 
 	rc = lprocfs_write_helper(buffer, count, &val);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	mutex_lock(&seq->lcs_mutex);
 	if (seq->lcs_type == LUSTRE_SEQ_DATA)
@@ -150,7 +146,7 @@ lprocfs_fid_width_seq_write(struct file *file, const char *buffer,
 
 	mutex_unlock(&seq->lcs_mutex);
 
-	RETURN(count);
+	return count;
 }
 
 static int
@@ -158,7 +154,6 @@ lprocfs_fid_width_seq_show(struct seq_file *m, void *unused)
 {
 	struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 
@@ -166,7 +161,7 @@ lprocfs_fid_width_seq_show(struct seq_file *m, void *unused)
 	rc = seq_printf(m, LPU64"\n", seq->lcs_width);
 	mutex_unlock(&seq->lcs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -174,7 +169,6 @@ lprocfs_fid_fid_seq_show(struct seq_file *m, void *unused)
 {
 	struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 
@@ -182,7 +176,7 @@ lprocfs_fid_fid_seq_show(struct seq_file *m, void *unused)
 	rc = seq_printf(m, DFID"\n", PFID(&seq->lcs_fid));
 	mutex_unlock(&seq->lcs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -191,7 +185,6 @@ lprocfs_fid_server_seq_show(struct seq_file *m, void *unused)
 	struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
 	struct client_obd *cli;
 	int rc;
-	ENTRY;
 
 	LASSERT(seq != NULL);
 
@@ -201,12 +194,9 @@ lprocfs_fid_server_seq_show(struct seq_file *m, void *unused)
 	} else {
 		rc = seq_printf(m, "%s\n", seq->lcs_srv->lss_name);
 	}
-	RETURN(rc);
+	return rc;
 }
 
-struct lprocfs_vars seq_server_proc_list[] = {
-};
-
 LPROC_SEQ_FOPS(lprocfs_fid_space);
 LPROC_SEQ_FOPS(lprocfs_fid_width);
 LPROC_SEQ_FOPS_RO(lprocfs_fid_server);
diff --git a/drivers/staging/lustre/lustre/fld/Makefile b/drivers/staging/lustre/lustre/fld/Makefile
index e7f2881..90d46d8 100644
--- a/drivers/staging/lustre/lustre/fld/Makefile
+++ b/drivers/staging/lustre/lustre/fld/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_LUSTRE_FS) += fld.o
-fld-y := fld_handler.o fld_request.o fld_cache.o fld_index.o lproc_fld.o
+fld-y := fld_request.o fld_cache.o lproc_fld.o
 
 
 ccflags-y := -I$(src)/../include
diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c
index 347f2ae..25099cb 100644
--- a/drivers/staging/lustre/lustre/fld/fld_cache.c
+++ b/drivers/staging/lustre/lustre/fld/fld_cache.c
@@ -45,7 +45,6 @@
 
 # include <linux/libcfs/libcfs.h>
 # include <linux/module.h>
-# include <linux/jbd.h>
 # include <asm/div64.h>
 
 #include <obd.h>
@@ -67,14 +66,13 @@ struct fld_cache *fld_cache_init(const char *name,
 				 int cache_size, int cache_threshold)
 {
 	struct fld_cache *cache;
-	ENTRY;
 
 	LASSERT(name != NULL);
 	LASSERT(cache_threshold < cache_size);
 
 	OBD_ALLOC_PTR(cache);
 	if (cache == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&cache->fci_entries_head);
 	INIT_LIST_HEAD(&cache->fci_lru);
@@ -94,7 +92,7 @@ struct fld_cache *fld_cache_init(const char *name,
 	CDEBUG(D_INFO, "%s: FLD cache - Size: %d, Threshold: %d\n",
 	       cache->fci_name, cache_size, cache_threshold);
 
-	RETURN(cache);
+	return cache;
 }
 
 /**
@@ -103,7 +101,6 @@ struct fld_cache *fld_cache_init(const char *name,
 void fld_cache_fini(struct fld_cache *cache)
 {
 	__u64 pct;
-	ENTRY;
 
 	LASSERT(cache != NULL);
 	fld_cache_flush(cache);
@@ -121,8 +118,6 @@ void fld_cache_fini(struct fld_cache *cache)
 	CDEBUG(D_INFO, "  Cache hits: "LPU64"%%\n", pct);
 
 	OBD_FREE_PTR(cache);
-
-	EXIT;
 }
 
 /**
@@ -147,7 +142,6 @@ static void fld_fix_new_list(struct fld_cache *cache)
 	struct lu_seq_range *c_range;
 	struct lu_seq_range *n_range;
 	struct list_head *head = &cache->fci_entries_head;
-	ENTRY;
 
 restart_fixup:
 
@@ -200,8 +194,6 @@ restart_fixup:
 		    c_range->lsr_end == n_range->lsr_end)
 			fld_cache_entry_delete(cache, f_curr);
 	}
-
-	EXIT;
 }
 
 /**
@@ -227,12 +219,11 @@ static int fld_cache_shrink(struct fld_cache *cache)
 	struct fld_cache_entry *flde;
 	struct list_head *curr;
 	int num = 0;
-	ENTRY;
 
 	LASSERT(cache != NULL);
 
 	if (cache->fci_cache_count < cache->fci_cache_size)
-		RETURN(0);
+		return 0;
 
 	curr = cache->fci_lru.prev;
 
@@ -248,7 +239,7 @@ static int fld_cache_shrink(struct fld_cache *cache)
 	CDEBUG(D_INFO, "%s: FLD cache - Shrunk by "
 	       "%d entries\n", cache->fci_name, num);
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -256,14 +247,10 @@ static int fld_cache_shrink(struct fld_cache *cache)
  */
 void fld_cache_flush(struct fld_cache *cache)
 {
-	ENTRY;
-
 	write_lock(&cache->fci_lock);
 	cache->fci_cache_size = 0;
 	fld_cache_shrink(cache);
 	write_unlock(&cache->fci_lock);
-
-	EXIT;
 }
 
 /**
@@ -280,11 +267,9 @@ void fld_cache_punch_hole(struct fld_cache *cache,
 	const seqno_t new_end  = range->lsr_end;
 	struct fld_cache_entry *fldt;
 
-	ENTRY;
 	OBD_ALLOC_GFP(fldt, sizeof *fldt, GFP_ATOMIC);
 	if (!fldt) {
 		OBD_FREE_PTR(f_new);
-		EXIT;
 		/* overlap is not allowed, so dont mess up list. */
 		return;
 	}
@@ -307,7 +292,6 @@ void fld_cache_punch_hole(struct fld_cache *cache,
 	fld_cache_entry_add(cache, fldt, &f_new->fce_list);
 
 	/* no need to fixup */
-	EXIT;
 }
 
 /**
@@ -383,10 +367,10 @@ struct fld_cache_entry
 
 	OBD_ALLOC_PTR(f_new);
 	if (!f_new)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	f_new->fce_range = *range;
-	RETURN(f_new);
+	return f_new;
 }
 
 /**
@@ -405,7 +389,6 @@ int fld_cache_insert_nolock(struct fld_cache *cache,
 	const seqno_t new_start  = f_new->fce_range.lsr_start;
 	const seqno_t new_end  = f_new->fce_range.lsr_end;
 	__u32 new_flags  = f_new->fce_range.lsr_flags;
-	ENTRY;
 
 	/*
 	 * Duplicate entries are eliminated in insert op.
@@ -441,7 +424,7 @@ int fld_cache_insert_nolock(struct fld_cache *cache,
 	/* Add new entry to cache and lru list. */
 	fld_cache_entry_add(cache, f_new, prev);
 out:
-	RETURN(0);
+	return 0;
 }
 
 int fld_cache_insert(struct fld_cache *cache,
@@ -452,7 +435,7 @@ int fld_cache_insert(struct fld_cache *cache,
 
 	flde = fld_cache_entry_create(range);
 	if (IS_ERR(flde))
-		RETURN(PTR_ERR(flde));
+		return PTR_ERR(flde);
 
 	write_lock(&cache->fci_lock);
 	rc = fld_cache_insert_nolock(cache, flde);
@@ -460,7 +443,7 @@ int fld_cache_insert(struct fld_cache *cache,
 	if (rc)
 		OBD_FREE_PTR(flde);
 
-	RETURN(rc);
+	return rc;
 }
 
 void fld_cache_delete_nolock(struct fld_cache *cache,
@@ -512,7 +495,7 @@ struct fld_cache_entry
 		}
 	}
 
-	RETURN(got);
+	return got;
 }
 
 /**
@@ -522,12 +505,11 @@ struct fld_cache_entry
 *fld_cache_entry_lookup(struct fld_cache *cache, struct lu_seq_range *range)
 {
 	struct fld_cache_entry *got = NULL;
-	ENTRY;
 
 	read_lock(&cache->fci_lock);
 	got = fld_cache_entry_lookup_nolock(cache, range);
 	read_unlock(&cache->fci_lock);
-	RETURN(got);
+	return got;
 }
 
 /**
@@ -539,7 +521,6 @@ int fld_cache_lookup(struct fld_cache *cache,
 	struct fld_cache_entry *flde;
 	struct fld_cache_entry *prev = NULL;
 	struct list_head *head;
-	ENTRY;
 
 	read_lock(&cache->fci_lock);
 	head = &cache->fci_entries_head;
@@ -558,9 +539,9 @@ int fld_cache_lookup(struct fld_cache *cache,
 
 			cache->fci_stat.fst_cache++;
 			read_unlock(&cache->fci_lock);
-			RETURN(0);
+			return 0;
 		}
 	}
 	read_unlock(&cache->fci_lock);
-	RETURN(-ENOENT);
+	return -ENOENT;
 }
diff --git a/drivers/staging/lustre/lustre/fld/fld_handler.c b/drivers/staging/lustre/lustre/fld/fld_handler.c
deleted file mode 100644
index d2707ae..0000000
--- a/drivers/staging/lustre/lustre/fld/fld_handler.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2013, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/fld/fld_handler.c
- *
- * FLD (Fids Location Database)
- *
- * Author: Yury Umanets <umka@clusterfs.com>
- * Author: WangDi <wangdi@clusterfs.com>
- * Author: Pravin Shelar <pravin.shelar@sun.com>
- */
-
-#define DEBUG_SUBSYSTEM S_FLD
-
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-# include <linux/jbd.h>
-# include <asm/div64.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_ver.h>
-#include <obd_support.h>
-#include <lprocfs_status.h>
-
-#include <md_object.h>
-#include <lustre_fid.h>
-#include <lustre_req_layout.h>
-#include "fld_internal.h"
-#include <lustre_fid.h>
-
-
-/* context key constructor/destructor: fld_key_init, fld_key_fini */
-LU_KEY_INIT_FINI(fld, struct fld_thread_info);
-
-/* context key: fld_thread_key */
-LU_CONTEXT_KEY_DEFINE(fld, LCT_MD_THREAD | LCT_DT_THREAD | LCT_MG_THREAD);
-
-proc_dir_entry_t *fld_type_proc_dir = NULL;
-
-static int __init fld_mod_init(void)
-{
-	fld_type_proc_dir = lprocfs_register(LUSTRE_FLD_NAME,
-					     proc_lustre_root,
-					     NULL, NULL);
-	if (IS_ERR(fld_type_proc_dir))
-		return PTR_ERR(fld_type_proc_dir);
-
-	LU_CONTEXT_KEY_INIT(&fld_thread_key);
-	lu_context_key_register(&fld_thread_key);
-	return 0;
-}
-
-static void __exit fld_mod_exit(void)
-{
-	lu_context_key_degister(&fld_thread_key);
-	if (fld_type_proc_dir != NULL && !IS_ERR(fld_type_proc_dir)) {
-		lprocfs_remove(&fld_type_proc_dir);
-		fld_type_proc_dir = NULL;
-	}
-}
-
-int fld_declare_server_create(const struct lu_env *env,
-			      struct lu_server_fld *fld,
-			      struct lu_seq_range *range,
-			      struct thandle *th)
-{
-	int rc;
-
-	rc = fld_declare_index_create(env, fld, range, th);
-	RETURN(rc);
-}
-EXPORT_SYMBOL(fld_declare_server_create);
-
-/**
- * Insert FLD index entry and update FLD cache.
- *
- * This function is called from the sequence allocator when a super-sequence
- * is granted to a server.
- */
-int fld_server_create(const struct lu_env *env, struct lu_server_fld *fld,
-		      struct lu_seq_range *range, struct thandle *th)
-{
-	int rc;
-
-	mutex_lock(&fld->lsf_lock);
-	rc = fld_index_create(env, fld, range, th);
-	mutex_unlock(&fld->lsf_lock);
-
-	RETURN(rc);
-}
-EXPORT_SYMBOL(fld_server_create);
-
-/**
- *  Lookup mds by seq, returns a range for given seq.
- *
- *  If that entry is not cached in fld cache, request is sent to super
- *  sequence controller node (MDT0). All other MDT[1...N] and client
- *  cache fld entries, but this cache is not persistent.
- */
-int fld_server_lookup(const struct lu_env *env, struct lu_server_fld *fld,
-		      seqno_t seq, struct lu_seq_range *range)
-{
-	struct lu_seq_range *erange;
-	struct fld_thread_info *info;
-	int rc;
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-	LASSERT(info != NULL);
-	erange = &info->fti_lrange;
-
-	/* Lookup it in the cache. */
-	rc = fld_cache_lookup(fld->lsf_cache, seq, erange);
-	if (rc == 0) {
-		if (unlikely(fld_range_type(erange) != fld_range_type(range) &&
-			     !fld_range_is_any(range))) {
-			CERROR("%s: FLD cache range "DRANGE" does not match"
-			       "requested flag %x: rc = %d\n", fld->lsf_name,
-			       PRANGE(erange), range->lsr_flags, -EIO);
-			RETURN(-EIO);
-		}
-		*range = *erange;
-		RETURN(0);
-	}
-
-	if (fld->lsf_obj) {
-		/* On server side, all entries should be in cache.
-		 * If we can not find it in cache, just return error */
-		CERROR("%s: Cannot find sequence "LPX64": rc = %d\n",
-			fld->lsf_name, seq, -EIO);
-		RETURN(-EIO);
-	} else {
-		LASSERT(fld->lsf_control_exp);
-		/* send request to mdt0 i.e. super seq. controller.
-		 * This is temporary solution, long term solution is fld
-		 * replication on all mdt servers.
-		 */
-		range->lsr_start = seq;
-		rc = fld_client_rpc(fld->lsf_control_exp,
-				    range, FLD_LOOKUP);
-		if (rc == 0)
-			fld_cache_insert(fld->lsf_cache, range);
-	}
-	RETURN(rc);
-}
-EXPORT_SYMBOL(fld_server_lookup);
-
-/**
- * All MDT server handle fld lookup operation. But only MDT0 has fld index.
- * if entry is not found in cache we need to forward lookup request to MDT0
- */
-
-static int fld_server_handle(struct lu_server_fld *fld,
-			     const struct lu_env *env,
-			     __u32 opc, struct lu_seq_range *range,
-			     struct fld_thread_info *info)
-{
-	int rc;
-	ENTRY;
-
-	switch (opc) {
-	case FLD_LOOKUP:
-		rc = fld_server_lookup(env, fld, range->lsr_start, range);
-		break;
-	default:
-		rc = -EINVAL;
-		break;
-	}
-
-	CDEBUG(D_INFO, "%s: FLD req handle: error %d (opc: %d, range: "
-	       DRANGE"\n", fld->lsf_name, rc, opc, PRANGE(range));
-
-	RETURN(rc);
-
-}
-
-static int fld_req_handle(struct ptlrpc_request *req,
-			  struct fld_thread_info *info)
-{
-	struct obd_export *exp = req->rq_export;
-	struct lu_site *site = exp->exp_obd->obd_lu_dev->ld_site;
-	struct lu_seq_range *in;
-	struct lu_seq_range *out;
-	int rc;
-	__u32 *opc;
-	ENTRY;
-
-	rc = req_capsule_server_pack(info->fti_pill);
-	if (rc)
-		RETURN(err_serious(rc));
-
-	opc = req_capsule_client_get(info->fti_pill, &RMF_FLD_OPC);
-	if (opc != NULL) {
-		in = req_capsule_client_get(info->fti_pill, &RMF_FLD_MDFLD);
-		if (in == NULL)
-			RETURN(err_serious(-EPROTO));
-		out = req_capsule_server_get(info->fti_pill, &RMF_FLD_MDFLD);
-		if (out == NULL)
-			RETURN(err_serious(-EPROTO));
-		*out = *in;
-
-		/* For old 2.0 client, the 'lsr_flags' is uninitialized.
-		 * Set it as 'LU_SEQ_RANGE_MDT' by default. */
-		if (!(exp_connect_flags(exp) & OBD_CONNECT_64BITHASH) &&
-		    !(exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS) &&
-		    !(exp_connect_flags(exp) & OBD_CONNECT_LIGHTWEIGHT) &&
-		    !exp->exp_libclient)
-			fld_range_set_mdt(out);
-
-		rc = fld_server_handle(lu_site2seq(site)->ss_server_fld,
-				       req->rq_svc_thread->t_env,
-				       *opc, out, info);
-	} else {
-		rc = err_serious(-EPROTO);
-	}
-
-	RETURN(rc);
-}
-
-static void fld_thread_info_init(struct ptlrpc_request *req,
-				 struct fld_thread_info *info)
-{
-	info->fti_pill = &req->rq_pill;
-	/* Init request capsule. */
-	req_capsule_init(info->fti_pill, req, RCL_SERVER);
-	req_capsule_set(info->fti_pill, &RQF_FLD_QUERY);
-}
-
-static void fld_thread_info_fini(struct fld_thread_info *info)
-{
-	req_capsule_fini(info->fti_pill);
-}
-
-static int fld_handle(struct ptlrpc_request *req)
-{
-	struct fld_thread_info *info;
-	const struct lu_env *env;
-	int rc;
-
-	env = req->rq_svc_thread->t_env;
-	LASSERT(env != NULL);
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-	LASSERT(info != NULL);
-
-	fld_thread_info_init(req, info);
-	rc = fld_req_handle(req, info);
-	fld_thread_info_fini(info);
-
-	return rc;
-}
-
-/*
- * Entry point for handling FLD RPCs called from MDT.
- */
-int fld_query(struct com_thread_info *info)
-{
-	return fld_handle(info->cti_pill->rc_req);
-}
-EXPORT_SYMBOL(fld_query);
-
-/*
- * Returns true, if fid is local to this server node.
- *
- * WARNING: this function is *not* guaranteed to return false if fid is
- * remote: it makes an educated conservative guess only.
- *
- * fid_is_local() is supposed to be used in assertion checks only.
- */
-int fid_is_local(const struct lu_env *env,
-		 struct lu_site *site, const struct lu_fid *fid)
-{
-	int result;
-	struct seq_server_site *ss_site;
-	struct lu_seq_range *range;
-	struct fld_thread_info *info;
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-	range = &info->fti_lrange;
-
-	result = 1; /* conservatively assume fid is local */
-	ss_site = lu_site2seq(site);
-	if (ss_site->ss_client_fld != NULL) {
-		int rc;
-
-		rc = fld_cache_lookup(ss_site->ss_client_fld->lcf_cache,
-				      fid_seq(fid), range);
-		if (rc == 0)
-			result = (range->lsr_index == ss_site->ss_node_id);
-	}
-	return result;
-}
-EXPORT_SYMBOL(fid_is_local);
-
-static void fld_server_proc_fini(struct lu_server_fld *fld);
-
-#ifdef LPROCFS
-static int fld_server_proc_init(struct lu_server_fld *fld)
-{
-	int rc = 0;
-	ENTRY;
-
-	fld->lsf_proc_dir = lprocfs_register(fld->lsf_name,
-					     fld_type_proc_dir,
-					     fld_server_proc_list, fld);
-	if (IS_ERR(fld->lsf_proc_dir)) {
-		rc = PTR_ERR(fld->lsf_proc_dir);
-		RETURN(rc);
-	}
-
-	rc = lprocfs_seq_create(fld->lsf_proc_dir, "fldb", 0444,
-				&fld_proc_seq_fops, fld);
-	if (rc) {
-		lprocfs_remove(&fld->lsf_proc_dir);
-		fld->lsf_proc_dir = NULL;
-	}
-
-	RETURN(rc);
-}
-
-static void fld_server_proc_fini(struct lu_server_fld *fld)
-{
-	ENTRY;
-	if (fld->lsf_proc_dir != NULL) {
-		if (!IS_ERR(fld->lsf_proc_dir))
-			lprocfs_remove(&fld->lsf_proc_dir);
-		fld->lsf_proc_dir = NULL;
-	}
-	EXIT;
-}
-#else
-static int fld_server_proc_init(struct lu_server_fld *fld)
-{
-	return 0;
-}
-
-static void fld_server_proc_fini(struct lu_server_fld *fld)
-{
-	return;
-}
-#endif
-
-int fld_server_init(const struct lu_env *env, struct lu_server_fld *fld,
-		    struct dt_device *dt, const char *prefix, int mds_node_id,
-		    int type)
-{
-	int cache_size, cache_threshold;
-	int rc;
-	ENTRY;
-
-	snprintf(fld->lsf_name, sizeof(fld->lsf_name),
-		 "srv-%s", prefix);
-
-	cache_size = FLD_SERVER_CACHE_SIZE /
-		sizeof(struct fld_cache_entry);
-
-	cache_threshold = cache_size *
-		FLD_SERVER_CACHE_THRESHOLD / 100;
-
-	mutex_init(&fld->lsf_lock);
-	fld->lsf_cache = fld_cache_init(fld->lsf_name,
-					cache_size, cache_threshold);
-	if (IS_ERR(fld->lsf_cache)) {
-		rc = PTR_ERR(fld->lsf_cache);
-		fld->lsf_cache = NULL;
-		GOTO(out, rc);
-	}
-
-	if (!mds_node_id && type == LU_SEQ_RANGE_MDT) {
-		rc = fld_index_init(env, fld, dt);
-		if (rc)
-			GOTO(out, rc);
-	} else {
-		fld->lsf_obj = NULL;
-	}
-
-	rc = fld_server_proc_init(fld);
-	if (rc)
-		GOTO(out, rc);
-
-	fld->lsf_control_exp = NULL;
-
-	GOTO(out, rc);
-
-out:
-	if (rc)
-		fld_server_fini(env, fld);
-	return rc;
-}
-EXPORT_SYMBOL(fld_server_init);
-
-void fld_server_fini(const struct lu_env *env, struct lu_server_fld *fld)
-{
-	ENTRY;
-
-	fld_server_proc_fini(fld);
-	fld_index_fini(env, fld);
-
-	if (fld->lsf_cache != NULL) {
-		if (!IS_ERR(fld->lsf_cache))
-			fld_cache_fini(fld->lsf_cache);
-		fld->lsf_cache = NULL;
-	}
-
-	EXIT;
-}
-EXPORT_SYMBOL(fld_server_fini);
-
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("Lustre FLD");
-MODULE_LICENSE("GPL");
-
-cfs_module(mdd, "0.1.0", fld_mod_init, fld_mod_exit);
diff --git a/drivers/staging/lustre/lustre/fld/fld_index.c b/drivers/staging/lustre/lustre/fld/fld_index.c
deleted file mode 100644
index ec68a54..0000000
--- a/drivers/staging/lustre/lustre/fld/fld_index.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2013, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/fld/fld_index.c
- *
- * Author: WangDi <wangdi@clusterfs.com>
- * Author: Yury Umanets <umka@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_FLD
-
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-# include <linux/jbd.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_ver.h>
-#include <obd_support.h>
-#include <lprocfs_status.h>
-
-#include <dt_object.h>
-#include <md_object.h>
-#include <lustre_mdc.h>
-#include <lustre_fid.h>
-#include <lustre_fld.h>
-#include "fld_internal.h"
-
-const char fld_index_name[] = "fld";
-
-static const struct lu_seq_range IGIF_FLD_RANGE = {
-	.lsr_start = FID_SEQ_IGIF,
-	.lsr_end   = FID_SEQ_IGIF_MAX + 1,
-	.lsr_index = 0,
-	.lsr_flags = LU_SEQ_RANGE_MDT
-};
-
-static const struct lu_seq_range DOT_LUSTRE_FLD_RANGE = {
-	.lsr_start = FID_SEQ_DOT_LUSTRE,
-	.lsr_end   = FID_SEQ_DOT_LUSTRE + 1,
-	.lsr_index = 0,
-	.lsr_flags = LU_SEQ_RANGE_MDT
-};
-
-static const struct lu_seq_range ROOT_FLD_RANGE = {
-	.lsr_start = FID_SEQ_ROOT,
-	.lsr_end   = FID_SEQ_ROOT + 1,
-	.lsr_index = 0,
-	.lsr_flags = LU_SEQ_RANGE_MDT
-};
-
-const struct dt_index_features fld_index_features = {
-	.dif_flags       = DT_IND_UPDATE,
-	.dif_keysize_min = sizeof(seqno_t),
-	.dif_keysize_max = sizeof(seqno_t),
-	.dif_recsize_min = sizeof(struct lu_seq_range),
-	.dif_recsize_max = sizeof(struct lu_seq_range),
-	.dif_ptrsize     = 4
-};
-
-extern struct lu_context_key fld_thread_key;
-
-int fld_declare_index_create(const struct lu_env *env,
-			     struct lu_server_fld *fld,
-			     const struct lu_seq_range *new_range,
-			     struct thandle *th)
-{
-	struct lu_seq_range	*tmp;
-	struct lu_seq_range	*range;
-	struct fld_thread_info	*info;
-	int			rc = 0;
-
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-	range = &info->fti_lrange;
-	tmp = &info->fti_irange;
-	memset(range, 0, sizeof(*range));
-
-	rc = fld_index_lookup(env, fld, new_range->lsr_start, range);
-	if (rc == 0) {
-		/* In case of duplicate entry, the location must be same */
-		LASSERT((range_compare_loc(new_range, range) == 0));
-		GOTO(out, rc = -EEXIST);
-	}
-
-	if (rc != -ENOENT) {
-		CERROR("%s: lookup range "DRANGE" error: rc = %d\n",
-			fld->lsf_name, PRANGE(range), rc);
-		GOTO(out, rc);
-	}
-
-	/* Check for merge case, since the fld entry can only be increamental,
-	 * so we will only check whether it can be merged from the left. */
-	if (new_range->lsr_start == range->lsr_end && range->lsr_end != 0 &&
-	    range_compare_loc(new_range, range) == 0) {
-		range_cpu_to_be(tmp, range);
-		rc = dt_declare_delete(env, fld->lsf_obj,
-				       (struct dt_key *)&tmp->lsr_start, th);
-		if (rc) {
-			CERROR("%s: declare record "DRANGE" failed: rc = %d\n",
-			       fld->lsf_name, PRANGE(range), rc);
-			GOTO(out, rc);
-		}
-		memcpy(tmp, new_range, sizeof(*new_range));
-		tmp->lsr_start = range->lsr_start;
-	} else {
-		memcpy(tmp, new_range, sizeof(*new_range));
-	}
-
-	range_cpu_to_be(tmp, tmp);
-	rc = dt_declare_insert(env, fld->lsf_obj, (struct dt_rec *)tmp,
-			       (struct dt_key *)&tmp->lsr_start, th);
-out:
-	RETURN(rc);
-}
-
-/**
- * insert range in fld store.
- *
- *      \param  range  range to be inserted
- *      \param  th     transaction for this operation as it could compound
- *		     transaction.
- *
- *      \retval  0  success
- *      \retval  -ve error
- *
- * The whole fld index insertion is protected by seq->lss_mutex (see
- * seq_server_alloc_super), i.e. only one thread will access fldb each
- * time, so we do not need worry the fld file and cache will being
- * changed between declare and create.
- * Because the fld entry can only be increamental, so we will only check
- * whether it can be merged from the left.
- **/
-int fld_index_create(const struct lu_env *env, struct lu_server_fld *fld,
-		     const struct lu_seq_range *new_range, struct thandle *th)
-{
-	struct lu_seq_range	*range;
-	struct lu_seq_range	*tmp;
-	struct fld_thread_info	*info;
-	int			rc = 0;
-	int			deleted = 0;
-	struct fld_cache_entry	*flde;
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-
-	LASSERT(mutex_is_locked(&fld->lsf_lock));
-
-	range = &info->fti_lrange;
-	memset(range, 0, sizeof(*range));
-	tmp = &info->fti_irange;
-	rc = fld_index_lookup(env, fld, new_range->lsr_start, range);
-	if (rc != -ENOENT) {
-		rc = rc == 0 ? -EEXIST : rc;
-		GOTO(out, rc);
-	}
-
-	if (new_range->lsr_start == range->lsr_end && range->lsr_end != 0 &&
-	    range_compare_loc(new_range, range) == 0) {
-		range_cpu_to_be(tmp, range);
-		rc = dt_delete(env, fld->lsf_obj,
-			       (struct dt_key *)&tmp->lsr_start, th,
-				BYPASS_CAPA);
-		if (rc != 0)
-			GOTO(out, rc);
-		memcpy(tmp, new_range, sizeof(*new_range));
-		tmp->lsr_start = range->lsr_start;
-		deleted = 1;
-	} else {
-		memcpy(tmp, new_range, sizeof(*new_range));
-	}
-
-	range_cpu_to_be(tmp, tmp);
-	rc = dt_insert(env, fld->lsf_obj, (struct dt_rec *)tmp,
-		       (struct dt_key *)&tmp->lsr_start, th, BYPASS_CAPA, 1);
-	if (rc != 0) {
-		CERROR("%s: insert range "DRANGE" failed: rc = %d\n",
-		       fld->lsf_name, PRANGE(new_range), rc);
-		GOTO(out, rc);
-	}
-
-	flde = fld_cache_entry_create(new_range);
-	if (IS_ERR(flde))
-		GOTO(out, rc = PTR_ERR(flde));
-
-	write_lock(&fld->lsf_cache->fci_lock);
-	if (deleted)
-		fld_cache_delete_nolock(fld->lsf_cache, new_range);
-	rc = fld_cache_insert_nolock(fld->lsf_cache, flde);
-	write_unlock(&fld->lsf_cache->fci_lock);
-	if (rc)
-		OBD_FREE_PTR(flde);
-out:
-	RETURN(rc);
-}
-
-/**
- * lookup range for a seq passed. note here we only care about the start/end,
- * caller should handle the attached location data (flags, index).
- *
- * \param  seq     seq for lookup.
- * \param  range   result of lookup.
- *
- * \retval  0	   found, \a range is the matched range;
- * \retval -ENOENT      not found, \a range is the left-side range;
- * \retval  -ve	 other error;
- */
-int fld_index_lookup(const struct lu_env *env, struct lu_server_fld *fld,
-		     seqno_t seq, struct lu_seq_range *range)
-{
-	struct lu_seq_range     *fld_rec;
-	struct fld_thread_info  *info;
-	int rc;
-
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-	fld_rec = &info->fti_rec;
-
-	rc = fld_cache_lookup(fld->lsf_cache, seq, fld_rec);
-	if (rc == 0) {
-		*range = *fld_rec;
-		if (range_within(range, seq))
-			rc = 0;
-		else
-			rc = -ENOENT;
-	}
-
-	CDEBUG(D_INFO, "%s: lookup seq = "LPX64" range : "DRANGE" rc = %d\n",
-	       fld->lsf_name, seq, PRANGE(range), rc);
-
-	RETURN(rc);
-}
-
-int fld_insert_entry(const struct lu_env *env,
-		     struct lu_server_fld *fld,
-		     const struct lu_seq_range *range)
-{
-	struct thandle *th;
-	int rc;
-	ENTRY;
-
-	th = dt_trans_create(env, lu2dt_dev(fld->lsf_obj->do_lu.lo_dev));
-	if (IS_ERR(th))
-		RETURN(PTR_ERR(th));
-
-	rc = fld_declare_index_create(env, fld, range, th);
-	if (rc != 0) {
-		if (rc == -EEXIST)
-			rc = 0;
-		GOTO(out, rc);
-	}
-
-	rc = dt_trans_start_local(env, lu2dt_dev(fld->lsf_obj->do_lu.lo_dev),
-				  th);
-	if (rc)
-		GOTO(out, rc);
-
-	rc = fld_index_create(env, fld, range, th);
-	if (rc == -EEXIST)
-		rc = 0;
-out:
-	dt_trans_stop(env, lu2dt_dev(fld->lsf_obj->do_lu.lo_dev), th);
-	RETURN(rc);
-}
-EXPORT_SYMBOL(fld_insert_entry);
-
-static int fld_insert_special_entries(const struct lu_env *env,
-				      struct lu_server_fld *fld)
-{
-	int rc;
-
-	rc = fld_insert_entry(env, fld, &IGIF_FLD_RANGE);
-	if (rc != 0)
-		RETURN(rc);
-
-	rc = fld_insert_entry(env, fld, &DOT_LUSTRE_FLD_RANGE);
-	if (rc != 0)
-		RETURN(rc);
-
-	rc = fld_insert_entry(env, fld, &ROOT_FLD_RANGE);
-
-	RETURN(rc);
-}
-
-int fld_index_init(const struct lu_env *env, struct lu_server_fld *fld,
-		   struct dt_device *dt)
-{
-	struct dt_object	*dt_obj = NULL;
-	struct lu_fid		fid;
-	struct lu_attr		*attr = NULL;
-	struct lu_seq_range	*range = NULL;
-	struct fld_thread_info	*info;
-	struct dt_object_format	dof;
-	struct dt_it		*it;
-	const struct dt_it_ops	*iops;
-	int			rc;
-	ENTRY;
-
-	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
-	LASSERT(info != NULL);
-
-	lu_local_obj_fid(&fid, FLD_INDEX_OID);
-	OBD_ALLOC_PTR(attr);
-	if (attr == NULL)
-		RETURN(-ENOMEM);
-
-	memset(attr, 0, sizeof(*attr));
-	attr->la_valid = LA_MODE;
-	attr->la_mode = S_IFREG | 0666;
-	dof.dof_type = DFT_INDEX;
-	dof.u.dof_idx.di_feat = &fld_index_features;
-
-	dt_obj = dt_find_or_create(env, dt, &fid, &dof, attr);
-	if (IS_ERR(dt_obj)) {
-		rc = PTR_ERR(dt_obj);
-		CERROR("%s: Can't find \"%s\" obj %d\n", fld->lsf_name,
-			fld_index_name, rc);
-		dt_obj = NULL;
-		GOTO(out, rc);
-	}
-
-	fld->lsf_obj = dt_obj;
-	rc = dt_obj->do_ops->do_index_try(env, dt_obj, &fld_index_features);
-	if (rc != 0) {
-		CERROR("%s: File \"%s\" is not an index: rc = %d!\n",
-		       fld->lsf_name, fld_index_name, rc);
-		GOTO(out, rc);
-	}
-
-	range = &info->fti_rec;
-	/* Load fld entry to cache */
-	iops = &dt_obj->do_index_ops->dio_it;
-	it = iops->init(env, dt_obj, 0, NULL);
-	if (IS_ERR(it))
-		GOTO(out, rc = PTR_ERR(it));
-
-	rc = iops->load(env, it, 0);
-	if (rc < 0)
-		GOTO(out_it_fini, rc);
-
-	if (rc > 0) {
-		/* Load FLD entry into server cache */
-		do {
-			rc = iops->rec(env, it, (struct dt_rec *)range, 0);
-			if (rc != 0)
-				GOTO(out_it_put, rc);
-			LASSERT(range != NULL);
-			range_be_to_cpu(range, range);
-			rc = fld_cache_insert(fld->lsf_cache, range);
-			if (rc != 0)
-				GOTO(out_it_put, rc);
-			rc = iops->next(env, it);
-		} while (rc == 0);
-	}
-
-	/* Note: fld_insert_entry will detect whether these
-	 * special entries already exist inside FLDB */
-	mutex_lock(&fld->lsf_lock);
-	rc = fld_insert_special_entries(env, fld);
-	mutex_unlock(&fld->lsf_lock);
-	if (rc != 0) {
-		CERROR("%s: insert special entries failed!: rc = %d\n",
-		       fld->lsf_name, rc);
-		GOTO(out_it_put, rc);
-	}
-
-out_it_put:
-	iops->put(env, it);
-out_it_fini:
-	iops->fini(env, it);
-out:
-	if (attr != NULL)
-		OBD_FREE_PTR(attr);
-
-	if (rc != 0) {
-		if (dt_obj != NULL)
-			lu_object_put(env, &dt_obj->do_lu);
-		fld->lsf_obj = NULL;
-	}
-	RETURN(rc);
-}
-
-void fld_index_fini(const struct lu_env *env, struct lu_server_fld *fld)
-{
-	ENTRY;
-	if (fld->lsf_obj != NULL) {
-		if (!IS_ERR(fld->lsf_obj))
-			lu_object_put(env, &fld->lsf_obj->do_lu);
-		fld->lsf_obj = NULL;
-	}
-	EXIT;
-}
diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h
index 9fa9e01..56686b1 100644
--- a/drivers/staging/lustre/lustre/fld/fld_internal.h
+++ b/drivers/staging/lustre/lustre/fld/fld_internal.h
@@ -139,38 +139,10 @@ enum {
 
 extern struct lu_fld_hash fld_hash[];
 
-
-struct fld_thread_info {
-	struct req_capsule *fti_pill;
-	__u64	       fti_key;
-	struct lu_seq_range fti_rec;
-	struct lu_seq_range fti_lrange;
-	struct lu_seq_range fti_irange;
-};
-
-extern struct lu_context_key fld_thread_key;
-
-int fld_index_init(const struct lu_env *env, struct lu_server_fld *fld,
-		   struct dt_device *dt);
-
-void fld_index_fini(const struct lu_env *env, struct lu_server_fld *fld);
-
-int fld_declare_index_create(const struct lu_env *env,
-			     struct lu_server_fld *fld,
-			     const struct lu_seq_range *new,
-			     struct thandle *th);
-
-int fld_index_create(const struct lu_env *env, struct lu_server_fld *fld,
-		     const struct lu_seq_range *new, struct thandle *th);
-
-int fld_index_lookup(const struct lu_env *env, struct lu_server_fld *fld,
-		     seqno_t seq, struct lu_seq_range *range);
-
 int fld_client_rpc(struct obd_export *exp,
 		   struct lu_seq_range *range, __u32 fld_op);
 
 #ifdef LPROCFS
-extern struct lprocfs_vars fld_server_proc_list[];
 extern struct lprocfs_vars fld_client_proc_list[];
 #endif
 
@@ -218,6 +190,5 @@ fld_target_name(struct lu_fld_target *tar)
 	return (const char *)tar->ft_exp->exp_obd->obd_name;
 }
 
-extern proc_dir_entry_t *fld_type_proc_dir;
-extern struct file_operations fld_proc_seq_fops;
+extern struct proc_dir_entry *fld_type_proc_dir;
 #endif /* __FLD_INTERNAL_H */
diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c
index e9f0739..078e98b 100644
--- a/drivers/staging/lustre/lustre/fld/fld_request.c
+++ b/drivers/staging/lustre/lustre/fld/fld_request.c
@@ -44,7 +44,6 @@
 
 # include <linux/libcfs/libcfs.h>
 # include <linux/module.h>
-# include <linux/jbd.h>
 # include <asm/div64.h>
 
 #include <obd.h>
@@ -60,16 +59,18 @@
 #include <lustre_mdc.h>
 #include "fld_internal.h"
 
+struct lu_context_key fld_thread_key;
+
 /* TODO: these 3 functions are copies of flow-control code from mdc_lib.c
  * It should be common thing. The same about mdc RPC lock */
 static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw)
 {
 	int rc;
-	ENTRY;
+
 	client_obd_list_lock(&cli->cl_loi_list_lock);
 	rc = list_empty(&mcw->mcw_entry);
 	client_obd_list_unlock(&cli->cl_loi_list_lock);
-	RETURN(rc);
+	return rc;
 };
 
 static void fld_enter_request(struct client_obd *cli)
@@ -123,7 +124,6 @@ fld_rrb_scan(struct lu_client_fld *fld, seqno_t seq)
 {
 	struct lu_fld_target *target;
 	int hash;
-	ENTRY;
 
 	/* Because almost all of special sequence located in MDT0,
 	 * it should go to index 0 directly, instead of calculating
@@ -137,7 +137,7 @@ fld_rrb_scan(struct lu_client_fld *fld, seqno_t seq)
 
 	list_for_each_entry(target, &fld->lcf_targets, ft_chain) {
 		if (target->ft_idx == hash)
-			RETURN(target);
+			return target;
 	}
 
 	CERROR("%s: Can't find target by hash %d (seq "LPX64"). "
@@ -161,7 +161,7 @@ fld_rrb_scan(struct lu_client_fld *fld, seqno_t seq)
 	 * LBUG() to catch this situation.
 	 */
 	LBUG();
-	RETURN(NULL);
+	return NULL;
 }
 
 struct lu_fld_hash fld_hash[] = {
@@ -179,7 +179,6 @@ static struct lu_fld_target *
 fld_client_get_target(struct lu_client_fld *fld, seqno_t seq)
 {
 	struct lu_fld_target *target;
-	ENTRY;
 
 	LASSERT(fld->lcf_hash != NULL);
 
@@ -193,7 +192,7 @@ fld_client_get_target(struct lu_client_fld *fld, seqno_t seq)
 		       target->ft_idx, seq);
 	}
 
-	RETURN(target);
+	return target;
 }
 
 /*
@@ -205,7 +204,6 @@ int fld_client_add_target(struct lu_client_fld *fld,
 {
 	const char *name;
 	struct lu_fld_target *target, *tmp;
-	ENTRY;
 
 	LASSERT(tar != NULL);
 	name = fld_target_name(tar);
@@ -216,7 +214,7 @@ int fld_client_add_target(struct lu_client_fld *fld,
 		CERROR("%s: Attempt to add target %s (idx "LPU64") "
 		       "on fly - skip it\n", fld->lcf_name, name,
 		       tar->ft_idx);
-		RETURN(0);
+		return 0;
 	} else {
 		CDEBUG(D_INFO, "%s: Adding target %s (idx "
 		       LPU64")\n", fld->lcf_name, name, tar->ft_idx);
@@ -224,7 +222,7 @@ int fld_client_add_target(struct lu_client_fld *fld,
 
 	OBD_ALLOC_PTR(target);
 	if (target == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock(&fld->lcf_lock);
 	list_for_each_entry(tmp, &fld->lcf_targets, ft_chain) {
@@ -233,7 +231,7 @@ int fld_client_add_target(struct lu_client_fld *fld,
 			OBD_FREE_PTR(target);
 			CERROR("Target %s exists in FLD and known as %s:#"LPU64"\n",
 			       name, fld_target_name(tmp), tmp->ft_idx);
-			RETURN(-EEXIST);
+			return -EEXIST;
 		}
 	}
 
@@ -249,7 +247,7 @@ int fld_client_add_target(struct lu_client_fld *fld,
 	fld->lcf_count++;
 	spin_unlock(&fld->lcf_lock);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(fld_client_add_target);
 
@@ -257,7 +255,6 @@ EXPORT_SYMBOL(fld_client_add_target);
 int fld_client_del_target(struct lu_client_fld *fld, __u64 idx)
 {
 	struct lu_fld_target *target, *tmp;
-	ENTRY;
 
 	spin_lock(&fld->lcf_lock);
 	list_for_each_entry_safe(target, tmp,
@@ -271,19 +268,20 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx)
 				class_export_put(target->ft_exp);
 
 			OBD_FREE_PTR(target);
-			RETURN(0);
+			return 0;
 		}
 	}
 	spin_unlock(&fld->lcf_lock);
-	RETURN(-ENOENT);
+	return -ENOENT;
 }
 EXPORT_SYMBOL(fld_client_del_target);
 
 #ifdef LPROCFS
+struct proc_dir_entry *fld_type_proc_dir = NULL;
+
 static int fld_client_proc_init(struct lu_client_fld *fld)
 {
 	int rc;
-	ENTRY;
 
 	fld->lcf_proc_dir = lprocfs_register(fld->lcf_name,
 					     fld_type_proc_dir,
@@ -293,7 +291,7 @@ static int fld_client_proc_init(struct lu_client_fld *fld)
 		CERROR("%s: LProcFS failed in fld-init\n",
 		       fld->lcf_name);
 		rc = PTR_ERR(fld->lcf_proc_dir);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = lprocfs_add_vars(fld->lcf_proc_dir,
@@ -304,7 +302,7 @@ static int fld_client_proc_init(struct lu_client_fld *fld)
 		GOTO(out_cleanup, rc);
 	}
 
-	RETURN(0);
+	return 0;
 
 out_cleanup:
 	fld_client_proc_fini(fld);
@@ -313,13 +311,11 @@ out_cleanup:
 
 void fld_client_proc_fini(struct lu_client_fld *fld)
 {
-	ENTRY;
 	if (fld->lcf_proc_dir) {
 		if (!IS_ERR(fld->lcf_proc_dir))
 			lprocfs_remove(&fld->lcf_proc_dir);
 		fld->lcf_proc_dir = NULL;
 	}
-	EXIT;
 }
 #else
 static int fld_client_proc_init(struct lu_client_fld *fld)
@@ -345,7 +341,6 @@ int fld_client_init(struct lu_client_fld *fld,
 {
 	int cache_size, cache_threshold;
 	int rc;
-	ENTRY;
 
 	LASSERT(fld != NULL);
 
@@ -355,7 +350,7 @@ int fld_client_init(struct lu_client_fld *fld,
 	if (!hash_is_sane(hash)) {
 		CERROR("%s: Wrong hash function %#x\n",
 		       fld->lcf_name, hash);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	fld->lcf_count = 0;
@@ -381,7 +376,6 @@ int fld_client_init(struct lu_client_fld *fld,
 	rc = fld_client_proc_init(fld);
 	if (rc)
 		GOTO(out, rc);
-	EXIT;
 out:
 	if (rc)
 		fld_client_fini(fld);
@@ -395,7 +389,6 @@ EXPORT_SYMBOL(fld_client_init);
 void fld_client_fini(struct lu_client_fld *fld)
 {
 	struct lu_fld_target *target, *tmp;
-	ENTRY;
 
 	spin_lock(&fld->lcf_lock);
 	list_for_each_entry_safe(target, tmp,
@@ -413,8 +406,6 @@ void fld_client_fini(struct lu_client_fld *fld)
 			fld_cache_fini(fld->lcf_cache);
 		fld->lcf_cache = NULL;
 	}
-
-	EXIT;
 }
 EXPORT_SYMBOL(fld_client_fini);
 
@@ -426,7 +417,6 @@ int fld_client_rpc(struct obd_export *exp,
 	__u32		 *op;
 	int		    rc;
 	struct obd_import     *imp;
-	ENTRY;
 
 	LASSERT(exp != NULL);
 
@@ -434,7 +424,7 @@ int fld_client_rpc(struct obd_export *exp,
 	req = ptlrpc_request_alloc_pack(imp, &RQF_FLD_QUERY, LUSTRE_MDS_VERSION,
 					FLD_QUERY);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	op = req_capsule_client_get(&req->rq_pill, &RMF_FLD_OPC);
 	*op = fld_op;
@@ -464,7 +454,6 @@ int fld_client_rpc(struct obd_export *exp,
 	if (prange == NULL)
 		GOTO(out_req, rc = -EFAULT);
 	*range = *prange;
-	EXIT;
 out_req:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -476,14 +465,13 @@ int fld_client_lookup(struct lu_client_fld *fld, seqno_t seq, mdsno_t *mds,
 	struct lu_seq_range res = { 0 };
 	struct lu_fld_target *target;
 	int rc;
-	ENTRY;
 
 	fld->lcf_flags |= LUSTRE_FLD_RUN;
 
 	rc = fld_cache_lookup(fld->lcf_cache, seq, &res);
 	if (rc == 0) {
 		*mds = res.lsr_index;
-		RETURN(0);
+		return 0;
 	}
 
 	/* Can not find it in the cache */
@@ -496,19 +484,14 @@ int fld_client_lookup(struct lu_client_fld *fld, seqno_t seq, mdsno_t *mds,
 
 	res.lsr_start = seq;
 	fld_range_set_type(&res, flags);
-	if (target->ft_srv != NULL) {
-		LASSERT(env != NULL);
-		rc = fld_server_lookup(env, target->ft_srv, seq, &res);
-	} else {
-		rc = fld_client_rpc(target->ft_exp, &res, FLD_LOOKUP);
-	}
+	rc = fld_client_rpc(target->ft_exp, &res, FLD_LOOKUP);
 
 	if (rc == 0) {
 		*mds = res.lsr_index;
 
 		fld_cache_insert(fld->lcf_cache, &res);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(fld_client_lookup);
 
@@ -517,3 +500,32 @@ void fld_client_flush(struct lu_client_fld *fld)
 	fld_cache_flush(fld->lcf_cache);
 }
 EXPORT_SYMBOL(fld_client_flush);
+
+static int __init fld_mod_init(void)
+{
+	fld_type_proc_dir = lprocfs_register(LUSTRE_FLD_NAME,
+					     proc_lustre_root,
+					     NULL, NULL);
+	if (IS_ERR(fld_type_proc_dir))
+		return PTR_ERR(fld_type_proc_dir);
+
+	LU_CONTEXT_KEY_INIT(&fld_thread_key);
+	lu_context_key_register(&fld_thread_key);
+	return 0;
+}
+
+static void __exit fld_mod_exit(void)
+{
+	lu_context_key_degister(&fld_thread_key);
+	if (fld_type_proc_dir != NULL && !IS_ERR(fld_type_proc_dir)) {
+		lprocfs_remove(&fld_type_proc_dir);
+		fld_type_proc_dir = NULL;
+	}
+}
+
+MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_DESCRIPTION("Lustre FLD");
+MODULE_LICENSE("GPL");
+
+module_init(fld_mod_init)
+module_exit(fld_mod_exit)
diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c
index c1bd803..052f7d5 100644
--- a/drivers/staging/lustre/lustre/fld/lproc_fld.c
+++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c
@@ -62,7 +62,6 @@ fld_proc_targets_seq_show(struct seq_file *m, void *unused)
 {
 	struct lu_client_fld *fld = (struct lu_client_fld *)m->private;
 	struct lu_fld_target *target;
-	ENTRY;
 
 	LASSERT(fld != NULL);
 
@@ -72,14 +71,13 @@ fld_proc_targets_seq_show(struct seq_file *m, void *unused)
 		seq_printf(m, "%s\n", fld_target_name(target));
 	spin_unlock(&fld->lcf_lock);
 
-	RETURN(0);
+	return 0;
 }
 
 static int
 fld_proc_hash_seq_show(struct seq_file *m, void *unused)
 {
 	struct lu_client_fld *fld = (struct lu_client_fld *)m->private;
-	ENTRY;
 
 	LASSERT(fld != NULL);
 
@@ -87,7 +85,7 @@ fld_proc_hash_seq_show(struct seq_file *m, void *unused)
 	seq_printf(m, "%s\n", fld->lcf_hash->fh_name);
 	spin_unlock(&fld->lcf_lock);
 
-	RETURN(0);
+	return 0;
 }
 
 static ssize_t
@@ -97,7 +95,6 @@ fld_proc_hash_seq_write(struct file *file, const char *buffer,
 	struct lu_client_fld *fld = ((struct seq_file *)file->private_data)->private;
 	struct lu_fld_hash *hash = NULL;
 	int i;
-	ENTRY;
 
 	LASSERT(fld != NULL);
 
@@ -120,7 +117,7 @@ fld_proc_hash_seq_write(struct file *file, const char *buffer,
 		       fld->lcf_name, hash->fh_name);
 	}
 
-	RETURN(count);
+	return count;
 }
 
 static ssize_t
@@ -128,7 +125,6 @@ fld_proc_cache_flush_write(struct file *file, const char __user *buffer,
 			       size_t count, loff_t *pos)
 {
 	struct lu_client_fld *fld = file->private_data;
-	ENTRY;
 
 	LASSERT(fld != NULL);
 
@@ -136,7 +132,7 @@ fld_proc_cache_flush_write(struct file *file, const char __user *buffer,
 
 	CDEBUG(D_INFO, "%s: Lookup cache is flushed\n", fld->lcf_name);
 
-	RETURN(count);
+	return count;
 }
 
 static int fld_proc_cache_flush_open(struct inode *inode, struct file *file)
@@ -158,202 +154,6 @@ struct file_operations fld_proc_cache_flush_fops = {
 	.release	= fld_proc_cache_flush_release,
 };
 
-struct fld_seq_param {
-	struct lu_env		fsp_env;
-	struct dt_it		*fsp_it;
-	struct lu_server_fld	*fsp_fld;
-	unsigned int		fsp_stop:1;
-};
-
-static void *fldb_seq_start(struct seq_file *p, loff_t *pos)
-{
-	struct fld_seq_param    *param = p->private;
-	struct lu_server_fld    *fld;
-	struct dt_object	*obj;
-	const struct dt_it_ops  *iops;
-
-	if (param == NULL || param->fsp_stop)
-		return NULL;
-
-	fld = param->fsp_fld;
-	obj = fld->lsf_obj;
-	LASSERT(obj != NULL);
-	iops = &obj->do_index_ops->dio_it;
-
-	iops->load(&param->fsp_env, param->fsp_it, *pos);
-
-	*pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
-	return param;
-}
-
-static void fldb_seq_stop(struct seq_file *p, void *v)
-{
-	struct fld_seq_param    *param = p->private;
-	const struct dt_it_ops	*iops;
-	struct lu_server_fld	*fld;
-	struct dt_object	*obj;
-
-	if (param == NULL)
-		return;
-
-	fld = param->fsp_fld;
-	obj = fld->lsf_obj;
-	LASSERT(obj != NULL);
-	iops = &obj->do_index_ops->dio_it;
-
-	iops->put(&param->fsp_env, param->fsp_it);
-}
-
-static void *fldb_seq_next(struct seq_file *p, void *v, loff_t *pos)
-{
-	struct fld_seq_param    *param = p->private;
-	struct lu_server_fld	*fld;
-	struct dt_object	*obj;
-	const struct dt_it_ops	*iops;
-	int			rc;
-
-	if (param == NULL || param->fsp_stop)
-		return NULL;
-
-	fld = param->fsp_fld;
-	obj = fld->lsf_obj;
-	LASSERT(obj != NULL);
-	iops = &obj->do_index_ops->dio_it;
-
-	rc = iops->next(&param->fsp_env, param->fsp_it);
-	if (rc > 0) {
-		param->fsp_stop = 1;
-		return NULL;
-	}
-
-	*pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
-	return param;
-}
-
-static int fldb_seq_show(struct seq_file *p, void *v)
-{
-	struct fld_seq_param    *param = p->private;
-	struct lu_server_fld	*fld;
-	struct dt_object	*obj;
-	const struct dt_it_ops	*iops;
-	struct fld_thread_info	*info;
-	struct lu_seq_range	*fld_rec;
-	int			rc;
-
-	if (param == NULL || param->fsp_stop)
-		return 0;
-
-	fld = param->fsp_fld;
-	obj = fld->lsf_obj;
-	LASSERT(obj != NULL);
-	iops = &obj->do_index_ops->dio_it;
-
-	info = lu_context_key_get(&param->fsp_env.le_ctx,
-				  &fld_thread_key);
-	fld_rec = &info->fti_rec;
-	rc = iops->rec(&param->fsp_env, param->fsp_it,
-		       (struct dt_rec *)fld_rec, 0);
-	if (rc != 0) {
-		CERROR("%s:read record error: rc %d\n",
-		       fld->lsf_name, rc);
-	} else if (fld_rec->lsr_start != 0) {
-		range_be_to_cpu(fld_rec, fld_rec);
-		rc = seq_printf(p, DRANGE"\n", PRANGE(fld_rec));
-	}
-
-	return rc;
-}
-
-struct seq_operations fldb_sops = {
-	.start = fldb_seq_start,
-	.stop = fldb_seq_stop,
-	.next = fldb_seq_next,
-	.show = fldb_seq_show,
-};
-
-static int fldb_seq_open(struct inode *inode, struct file *file)
-{
-	struct seq_file		*seq;
-	struct lu_server_fld    *fld = (struct lu_server_fld *)PDE_DATA(inode);
-	struct dt_object	*obj;
-	const struct dt_it_ops  *iops;
-	struct fld_seq_param    *param = NULL;
-	int			env_init = 0;
-	int			rc;
-
-	rc = seq_open(file, &fldb_sops);
-	if (rc)
-		GOTO(out, rc);
-
-	obj = fld->lsf_obj;
-	if (obj == NULL) {
-		seq = file->private_data;
-		seq->private = NULL;
-		return 0;
-	}
-
-	OBD_ALLOC_PTR(param);
-	if (param == NULL)
-		GOTO(out, rc = -ENOMEM);
-
-	rc = lu_env_init(&param->fsp_env, LCT_MD_THREAD);
-	if (rc != 0)
-		GOTO(out, rc);
-
-	env_init = 1;
-	iops = &obj->do_index_ops->dio_it;
-	param->fsp_it = iops->init(&param->fsp_env, obj, 0, NULL);
-	if (IS_ERR(param->fsp_it))
-		GOTO(out, rc = PTR_ERR(param->fsp_it));
-
-	param->fsp_fld = fld;
-	param->fsp_stop = 0;
-
-	seq = file->private_data;
-	seq->private = param;
-out:
-	if (rc != 0) {
-		if (env_init == 1)
-			lu_env_fini(&param->fsp_env);
-		if (param != NULL)
-			OBD_FREE_PTR(param);
-	}
-	return rc;
-}
-
-static int fldb_seq_release(struct inode *inode, struct file *file)
-{
-	struct seq_file		*seq = file->private_data;
-	struct fld_seq_param	*param;
-	struct lu_server_fld	*fld;
-	struct dt_object	*obj;
-	const struct dt_it_ops	*iops;
-
-	param = seq->private;
-	if (param == NULL) {
-		lprocfs_seq_release(inode, file);
-		return 0;
-	}
-
-	fld = param->fsp_fld;
-	obj = fld->lsf_obj;
-	LASSERT(obj != NULL);
-	iops = &obj->do_index_ops->dio_it;
-
-	LASSERT(iops != NULL);
-	LASSERT(obj != NULL);
-	LASSERT(param->fsp_it != NULL);
-	iops->fini(&param->fsp_env, param->fsp_it);
-	lu_env_fini(&param->fsp_env);
-	OBD_FREE_PTR(param);
-	lprocfs_seq_release(inode, file);
-
-	return 0;
-}
-
-struct lprocfs_vars fld_server_proc_list[] = {
-	{ NULL }};
-
 LPROC_SEQ_FOPS_RO(fld_proc_targets);
 LPROC_SEQ_FOPS(fld_proc_hash);
 
@@ -363,11 +163,4 @@ struct lprocfs_vars fld_client_proc_list[] = {
 	{ "cache_flush", &fld_proc_cache_flush_fops },
 	{ NULL }};
 
-struct file_operations fld_proc_seq_fops = {
-	.owner   = THIS_MODULE,
-	.open    = fldb_seq_open,
-	.read    = seq_read,
-	.release = fldb_seq_release,
-};
-
-#endif
+#endif /* LPROCFS */
diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index 4bb6880..edb40af 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -758,7 +758,7 @@ struct cl_page {
 	/**
 	 * Debug information, the task is owning the page.
 	 */
-	task_t	      *cp_task;
+	struct task_struct	*cp_task;
 	/**
 	 * Owning IO request in cl_page_state::CPS_PAGEOUT and
 	 * cl_page_state::CPS_PAGEIN states. This field is maintained only in
@@ -768,11 +768,11 @@ struct cl_page {
 	/** List of references to this page, for debugging. */
 	struct lu_ref	    cp_reference;
 	/** Link to an object, for debugging. */
-	struct lu_ref_link      *cp_obj_ref;
+	struct lu_ref_link       cp_obj_ref;
 	/** Link to a queue, for debugging. */
-	struct lu_ref_link      *cp_queue_ref;
+	struct lu_ref_link       cp_queue_ref;
 	/** Per-page flags from enum cl_page_flags. Protected by a VM lock. */
-	unsigned		 cp_flags;
+	unsigned                 cp_flags;
 	/** Assigned if doing a sync_io */
 	struct cl_sync_io       *cp_sync_io;
 };
@@ -1576,13 +1576,13 @@ struct cl_lock {
 	 * \see osc_lock_enqueue_wait(), lov_lock_cancel(), lov_sublock_wait().
 	 */
 	struct mutex		cll_guard;
-	task_t	   *cll_guarder;
+	struct task_struct	*cll_guarder;
 	int		   cll_depth;
 
 	/**
 	 * the owner for INTRANSIT state
 	 */
-	task_t	   *cll_intransit_owner;
+	struct task_struct	*cll_intransit_owner;
 	int		   cll_error;
 	/**
 	 * Number of holds on a lock. A hold prevents a lock from being
@@ -1625,7 +1625,7 @@ struct cl_lock {
 	/**
 	 * A reference for cl_lock::cll_descr::cld_obj. For debugging.
 	 */
-	struct lu_ref_link   *cll_obj_ref;
+	struct lu_ref_link    cll_obj_ref;
 #ifdef CONFIG_LOCKDEP
 	/* "dep_map" name is assumed by lockdep.h macros. */
 	struct lockdep_map    dep_map;
@@ -1869,7 +1869,7 @@ do {								    \
 struct cl_page_list {
 	unsigned	     pl_nr;
 	struct list_head	   pl_pages;
-	task_t	  *pl_owner;
+	struct task_struct	*pl_owner;
 };
 
 /**
@@ -2517,7 +2517,7 @@ struct cl_req_obj {
 	/** object itself */
 	struct cl_object   *ro_obj;
 	/** reference to cl_req_obj::ro_obj. For debugging. */
-	struct lu_ref_link *ro_obj_ref;
+	struct lu_ref_link  ro_obj_ref;
 	/* something else? Number of pages for a given object? */
 };
 
diff --git a/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h b/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h
index 5866922..4bcc4dc 100644
--- a/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h
+++ b/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h
@@ -48,7 +48,6 @@
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/version.h>
 #include <linux/smp.h>
 #include <linux/rwsem.h>
 #include <linux/libcfs/libcfs.h>
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
index dff0468..9243dfa 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
@@ -87,22 +87,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
 
 #define LTIME_S(time)		   (time.tv_sec)
 
-#define ll_permission(inode,mask,nd)    inode_permission(inode,mask)
-
-# define ll_generic_permission(inode, mask, flags, check_acl) \
-	 generic_permission(inode, mask)
-
-#define ll_blkdev_put(a, b) blkdev_put(a, b)
-
-#define ll_dentry_open(a,b,c)	dentry_open(a,b,c)
-
-#define ll_vfs_symlink(dir, dentry, mnt, path, mode) \
-		       vfs_symlink(dir, dentry, path)
-
-
-#define ll_generic_file_llseek_size(file, offset, origin, maxbytes, eof) \
-		generic_file_llseek_size(file, offset, origin, maxbytes, eof);
-
 /* inode_dio_wait(i) use as-is for write lock */
 # define inode_dio_write_done(i)	do {} while (0) /* for write unlock */
 # define inode_dio_read(i)		atomic_inc(&(i)->i_dio_count)
@@ -111,88 +95,10 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
 #define TREE_READ_LOCK_IRQ(mapping)	spin_lock_irq(&(mapping)->tree_lock)
 #define TREE_READ_UNLOCK_IRQ(mapping)	spin_unlock_irq(&(mapping)->tree_lock)
 
-static inline
-int ll_unregister_blkdev(unsigned int dev, const char *name)
-{
-	unregister_blkdev(dev, name);
-	return 0;
-}
-
-#define ll_invalidate_bdev(a,b)	 invalidate_bdev((a))
-
 #ifndef FS_HAS_FIEMAP
 #define FS_HAS_FIEMAP			(0)
 #endif
 
-
-
-/* add a lustre compatible layer for crypto API */
-#include <linux/crypto.h>
-#define ll_crypto_hash	  crypto_hash
-#define ll_crypto_cipher	crypto_blkcipher
-#define ll_crypto_alloc_hash(name, type, mask)  crypto_alloc_hash(name, type, mask)
-#define ll_crypto_hash_setkey(tfm, key, keylen) crypto_hash_setkey(tfm, key, keylen)
-#define ll_crypto_hash_init(desc)	       crypto_hash_init(desc)
-#define ll_crypto_hash_update(desc, sl, bytes)  crypto_hash_update(desc, sl, bytes)
-#define ll_crypto_hash_final(desc, out)	 crypto_hash_final(desc, out)
-#define ll_crypto_blkcipher_setkey(tfm, key, keylen) \
-		crypto_blkcipher_setkey(tfm, key, keylen)
-#define ll_crypto_blkcipher_set_iv(tfm, src, len) \
-		crypto_blkcipher_set_iv(tfm, src, len)
-#define ll_crypto_blkcipher_get_iv(tfm, dst, len) \
-		crypto_blkcipher_get_iv(tfm, dst, len)
-#define ll_crypto_blkcipher_encrypt(desc, dst, src, bytes) \
-		crypto_blkcipher_encrypt(desc, dst, src, bytes)
-#define ll_crypto_blkcipher_decrypt(desc, dst, src, bytes) \
-		crypto_blkcipher_decrypt(desc, dst, src, bytes)
-#define ll_crypto_blkcipher_encrypt_iv(desc, dst, src, bytes) \
-		crypto_blkcipher_encrypt_iv(desc, dst, src, bytes)
-#define ll_crypto_blkcipher_decrypt_iv(desc, dst, src, bytes) \
-		crypto_blkcipher_decrypt_iv(desc, dst, src, bytes)
-
-static inline
-struct ll_crypto_cipher *ll_crypto_alloc_blkcipher(const char *name,
-						   u32 type, u32 mask)
-{
-	struct ll_crypto_cipher *rtn = crypto_alloc_blkcipher(name, type, mask);
-
-	return (rtn == NULL ? ERR_PTR(-ENOMEM) : rtn);
-}
-
-static inline int ll_crypto_hmac(struct ll_crypto_hash *tfm,
-				 u8 *key, unsigned int *keylen,
-				 struct scatterlist *sg,
-				 unsigned int size, u8 *result)
-{
-	struct hash_desc desc;
-	int	      rv;
-	desc.tfm   = tfm;
-	desc.flags = 0;
-	rv = crypto_hash_setkey(desc.tfm, key, *keylen);
-	if (rv) {
-		CERROR("failed to hash setkey: %d\n", rv);
-		return rv;
-	}
-	return crypto_hash_digest(&desc, sg, size, result);
-}
-static inline
-unsigned int ll_crypto_tfm_alg_max_keysize(struct crypto_blkcipher *tfm)
-{
-	return crypto_blkcipher_tfm(tfm)->__crt_alg->cra_blkcipher.max_keysize;
-}
-static inline
-unsigned int ll_crypto_tfm_alg_min_keysize(struct crypto_blkcipher *tfm)
-{
-	return crypto_blkcipher_tfm(tfm)->__crt_alg->cra_blkcipher.min_keysize;
-}
-
-#define ll_crypto_hash_blocksize(tfm)       crypto_hash_blocksize(tfm)
-#define ll_crypto_hash_digestsize(tfm)      crypto_hash_digestsize(tfm)
-#define ll_crypto_blkcipher_ivsize(tfm)     crypto_blkcipher_ivsize(tfm)
-#define ll_crypto_blkcipher_blocksize(tfm)  crypto_blkcipher_blocksize(tfm)
-#define ll_crypto_free_hash(tfm)	    crypto_free_hash(tfm)
-#define ll_crypto_free_blkcipher(tfm)       crypto_free_blkcipher(tfm)
-
 #define ll_vfs_rmdir(dir,entry,mnt)	     vfs_rmdir(dir,entry)
 #define ll_vfs_mkdir(inode,dir,mnt,mode)	vfs_mkdir(inode,dir,mode)
 #define ll_vfs_link(old,mnt,dir,new,mnt1)       vfs_link(old,dir,new)
@@ -202,12 +108,6 @@ unsigned int ll_crypto_tfm_alg_min_keysize(struct crypto_blkcipher *tfm)
 #define ll_vfs_rename(old,old_dir,mnt,new,new_dir,mnt1) \
 		vfs_rename(old,old_dir,new,new_dir)
 
-#ifdef for_each_possible_cpu
-#define cfs_for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
-#elif defined(for_each_cpu)
-#define cfs_for_each_possible_cpu(cpu) for_each_cpu(cpu)
-#endif
-
 #define cfs_bio_io_error(a,b)   bio_io_error((a))
 #define cfs_bio_endio(a,b,c)    bio_endio((a),(c))
 
@@ -266,9 +166,6 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount)
 #define queue_max_phys_segments(rq)       queue_max_segments(rq)
 #define queue_max_hw_segments(rq)	 queue_max_segments(rq)
 
-#define ll_kmap_atomic(a, b)	kmap_atomic(a)
-#define ll_kunmap_atomic(a, b)	kunmap_atomic(a)
-
 
 #define ll_d_hlist_node hlist_node
 #define ll_d_hlist_empty(list) hlist_empty(list)
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h b/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h
index 6c72609..4da6e372 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h
@@ -54,7 +54,7 @@ typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd,
 
 struct fsfilt_operations {
 	struct list_head fs_list;
-	module_t *fs_owner;
+	struct module *fs_owner;
 	char   *fs_type;
 	char   *(* fs_getlabel)(struct super_block *sb);
 	void   *(* fs_start)(struct inode *inode, int op, void *desc_private,
@@ -145,16 +145,6 @@ static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode,
 	return rc;
 }
 
-static inline int fsfilt_map_inode_pages(struct obd_device *obd,
-					 struct inode *inode,
-					 struct page **page, int pages,
-					 unsigned long *blocks,
-					 int create, struct mutex *mutex)
-{
-	return obd->obd_fsops->fs_map_inode_pages(inode, page, pages, blocks,
-						  create, mutex);
-}
-
 static inline int fsfilt_read_record(struct obd_device *obd, struct file *file,
 				     void *buf, loff_t size, loff_t *offs)
 {
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_handles.h b/drivers/staging/lustre/lustre/include/linux/lustre_handles.h
index ecf1840..459b238 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_handles.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_handles.h
@@ -42,7 +42,6 @@
 #include <asm/types.h>
 #include <asm/atomic.h>
 #include <linux/list.h>
-#include <linux/version.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h
index c95dff9..9e5df8d 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h
@@ -40,8 +40,6 @@
 #endif
 
 
-#include <linux/version.h>
-
 #include <asm/statfs.h>
 
 #include <linux/fs.h>
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_net.h b/drivers/staging/lustre/lustre/include/linux/lustre_net.h
index 2d7c425..05de4d8 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_net.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_net.h
@@ -39,7 +39,6 @@
 #error Do not #include this file directly. #include <lustre_net.h> instead
 #endif
 
-#include <linux/version.h>
 #include <linux/workqueue.h>
 
 /* XXX Liang: should be moved to other header instead of here */
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
index a8e9c0c..a260e99 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
@@ -53,7 +53,7 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
 		return;
 
 	if (PagePrivate(page))
-		page->mapping->a_ops->invalidatepage(page, 0);
+		page->mapping->a_ops->invalidatepage(page, 0, PAGE_CACHE_SIZE);
 
 	cancel_dirty_page(page, PAGE_SIZE);
 	ClearPageMappedToDisk(page);
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_quota.h b/drivers/staging/lustre/lustre/include/linux/lustre_quota.h
index 421866b..a395050 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_quota.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_quota.h
@@ -39,7 +39,6 @@
 #error Do not #include this file directly. #include <lustre_quota.h> instead
 #endif
 
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/quota.h>
 #include <linux/quotaops.h>
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_user.h b/drivers/staging/lustre/lustre/include/linux/lustre_user.h
index ebaf929..9cc2849 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_user.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_user.h
@@ -41,7 +41,6 @@
 #ifndef _LINUX_LUSTRE_USER_H
 #define _LINUX_LUSTRE_USER_H
 
-# include <linux/version.h>
 # include <linux/quota.h>
 
 /*
@@ -53,15 +52,19 @@
 
 #include <linux/string.h>
 
-#if defined(__x86_64__) || defined(__ia64__) || defined(__ppc64__) || \
-    defined(__craynv) || defined (__mips64__) || defined(__powerpc64__)
-typedef struct stat     lstat_t;
-#define lstat_f	 lstat
-#define HAVE_LOV_USER_MDS_DATA
-#else
+/*
+ * We need to always use 64bit version because the structure
+ * is shared across entire cluster where 32bit and 64bit machines
+ * are co-existing.
+ */
+#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64)
 typedef struct stat64   lstat_t;
 #define lstat_f	 lstat64
-#define HAVE_LOV_USER_MDS_DATA
+#else
+typedef struct stat     lstat_t;
+#define lstat_f	 lstat
 #endif
 
+#define HAVE_LOV_USER_MDS_DATA
+
 #endif /* _LUSTRE_USER_H */
diff --git a/drivers/staging/lustre/lustre/include/linux/lvfs.h b/drivers/staging/lustre/lustre/include/linux/lvfs.h
index eb59ac7..e61f1b8 100644
--- a/drivers/staging/lustre/lustre/include/linux/lvfs.h
+++ b/drivers/staging/lustre/lustre/include/linux/lvfs.h
@@ -54,10 +54,10 @@
 /* simple.c */
 
 struct lvfs_ucred {
-	__u32		   luc_uid;
-	__u32		   luc_gid;
-	__u32		   luc_fsuid;
-	__u32		   luc_fsgid;
+	kuid_t		luc_uid;
+	kgid_t		luc_gid;
+	kuid_t		luc_fsuid;
+	kgid_t		luc_fsgid;
 	kernel_cap_t	luc_cap;
 	__u32		   luc_umask;
 	struct group_info      *luc_ginfo;
diff --git a/drivers/staging/lustre/lustre/include/linux/obd.h b/drivers/staging/lustre/lustre/include/linux/obd.h
index 2c36c0d..01a5026 100644
--- a/drivers/staging/lustre/lustre/include/linux/obd.h
+++ b/drivers/staging/lustre/lustre/include/linux/obd.h
@@ -93,11 +93,8 @@ static inline void __client_obd_list_lock(client_obd_lock_t *lock,
 				      lock, task->comm, task->pid,
 				      lock->func, lock->line,
 				      (jiffies - lock->time) / HZ);
-			LCONSOLE_WARN("====== for process holding the "
-				      "lock =====\n");
-			libcfs_debug_dumpstack(task);
 			LCONSOLE_WARN("====== for current process =====\n");
-			libcfs_debug_dumpstack(NULL);
+			dump_stack();
 			LCONSOLE_WARN("====== end =======\n");
 			cfs_pause(1000 * HZ);
 		}
diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h
index 55f1822..56b0572 100644
--- a/drivers/staging/lustre/lustre/include/lprocfs_status.h
+++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h
@@ -345,7 +345,7 @@ enum {
 
 #define EXTRA_FIRST_OPC LDLM_GLIMPSE_ENQUEUE
 /* class_obd.c */
-extern proc_dir_entry_t *proc_lustre_root;
+extern struct proc_dir_entry *proc_lustre_root;
 
 struct obd_device;
 struct obd_histogram;
@@ -370,18 +370,6 @@ static inline void s2dhms(struct dhms *ts, time_t secs)
 #define JOBSTATS_DISABLE		"disable"
 #define JOBSTATS_PROCNAME_UID		"procname_uid"
 
-typedef void (*cntr_init_callback)(struct lprocfs_stats *stats);
-
-struct obd_job_stats {
-	cfs_hash_t	*ojs_hash;
-	struct list_head	 ojs_list;
-	rwlock_t       ojs_lock; /* protect the obj_list */
-	cntr_init_callback ojs_cntr_init_fn;
-	int		ojs_cntr_num;
-	int		ojs_cleanup_interval;
-	time_t		   ojs_last_cleanup;
-};
-
 #ifdef LPROCFS
 
 extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats,
@@ -562,11 +550,11 @@ extern void lprocfs_free_md_stats(struct obd_device *obddev);
 struct obd_export;
 struct nid_stat;
 extern int lprocfs_add_clear_entry(struct obd_device * obd,
-				   proc_dir_entry_t *entry);
+				   struct proc_dir_entry *entry);
 extern int lprocfs_exp_setup(struct obd_export *exp,
 			     lnet_nid_t *peer_nid, int *newnid);
 extern int lprocfs_exp_cleanup(struct obd_export *exp);
-extern proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
+extern struct proc_dir_entry *lprocfs_add_simple(struct proc_dir_entry *root,
 						char *name,
 						void *data,
 						struct file_operations *fops);
@@ -579,27 +567,27 @@ lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
 			      unsigned long count, void *data);
 extern int lprocfs_nid_stats_clear_read(struct seq_file *m, void *data);
 
-extern int lprocfs_register_stats(proc_dir_entry_t *root, const char *name,
+extern int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
 				  struct lprocfs_stats *stats);
 
 /* lprocfs_status.c */
-extern int lprocfs_add_vars(proc_dir_entry_t *root,
+extern int lprocfs_add_vars(struct proc_dir_entry *root,
 			    struct lprocfs_vars *var,
 			    void *data);
 
-extern proc_dir_entry_t *lprocfs_register(const char *name,
-					      proc_dir_entry_t *parent,
+extern struct proc_dir_entry *lprocfs_register(const char *name,
+					      struct proc_dir_entry *parent,
 					      struct lprocfs_vars *list,
 					      void *data);
 
-extern void lprocfs_remove(proc_dir_entry_t **root);
+extern void lprocfs_remove(struct proc_dir_entry **root);
 extern void lprocfs_remove_proc_entry(const char *name,
 				      struct proc_dir_entry *parent);
 
 extern int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list);
 extern int lprocfs_obd_cleanup(struct obd_device *obd);
 
-extern int lprocfs_seq_create(proc_dir_entry_t *parent, const char *name,
+extern int lprocfs_seq_create(struct proc_dir_entry *parent, const char *name,
 			      umode_t mode,
 			      const struct file_operations *seq_fops,
 			      void *data);
@@ -663,8 +651,8 @@ extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count,
 extern int lprocfs_write_frac_u64_helper(const char *buffer,
 					 unsigned long count,
 					 __u64 *val, int mult);
-char *lprocfs_find_named_value(const char *buffer, const char *name,
-				unsigned long *count);
+extern char *lprocfs_find_named_value(const char *buffer, const char *name,
+				      size_t *count);
 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value);
 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value);
 void lprocfs_oh_clear(struct obd_histogram *oh);
@@ -748,16 +736,6 @@ struct file_operations name##_fops = {				     \
 		.release = lprocfs_single_release,			\
 	};
 
-/* lprocfs_jobstats.c */
-int lprocfs_job_stats_log(struct obd_device *obd, char *jobid,
-			  int event, long amount);
-void lprocfs_job_stats_fini(struct obd_device *obd);
-int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num,
-			   cntr_init_callback fn);
-int lprocfs_rd_job_interval(struct seq_file *m, void *data);
-int lprocfs_wr_job_interval(struct file *file, const char *buffer,
-			    unsigned long count, void *data);
-
 /* lproc_ptlrpc.c */
 struct ptlrpc_request;
 extern void target_print_req(void *seq_file, struct ptlrpc_request *req);
@@ -826,9 +804,6 @@ extern int lprocfs_quota_rd_qs_factor(char *page, char **start, loff_t off,
 extern int lprocfs_quota_wr_qs_factor(struct file *file,
 				      const char *buffer,
 				      unsigned long count, void *data);
-
-
-
 #else
 /* LPROCFS is not defined */
 
@@ -863,7 +838,7 @@ static inline void lprocfs_clear_stats(struct lprocfs_stats *stats)
 { return; }
 static inline void lprocfs_free_stats(struct lprocfs_stats **stats)
 { return; }
-static inline int lprocfs_register_stats(proc_dir_entry_t *root,
+static inline int lprocfs_register_stats(struct proc_dir_entry *root,
 					 const char *name,
 					 struct lprocfs_stats *stats)
 { return 0; }
@@ -894,7 +869,7 @@ static inline int lprocfs_exp_setup(struct obd_export *exp,lnet_nid_t *peer_nid,
 { return 0; }
 static inline int lprocfs_exp_cleanup(struct obd_export *exp)
 { return 0; }
-static inline proc_dir_entry_t *
+static inline struct proc_dir_entry *
 lprocfs_add_simple(struct proc_dir_entry *root, char *name,
 		   void *data, struct file_operations *fops)
 {return 0; }
@@ -912,15 +887,15 @@ static inline
 int lprocfs_nid_stats_clear_read(struct seq_file *m, void *data)
 { return 0; }
 
-static inline proc_dir_entry_t *
-lprocfs_register(const char *name, proc_dir_entry_t *parent,
+static inline struct proc_dir_entry *
+lprocfs_register(const char *name, struct proc_dir_entry *parent,
 		 struct lprocfs_vars *list, void *data)
 { return NULL; }
-static inline int lprocfs_add_vars(proc_dir_entry_t *root,
+static inline int lprocfs_add_vars(struct proc_dir_entry *root,
 				   struct lprocfs_vars *var,
 				   void *data)
 { return 0; }
-static inline void lprocfs_remove(proc_dir_entry_t **root)
+static inline void lprocfs_remove(struct proc_dir_entry **root)
 { return; }
 static inline void lprocfs_remove_proc_entry(const char *name,
 					     struct proc_dir_entry *parent)
@@ -1021,20 +996,6 @@ __u64 lprocfs_stats_collector(struct lprocfs_stats *stats, int idx,
 #define LPROC_SEQ_FOPS_RW_TYPE(name, type)
 #define LPROC_SEQ_FOPS_WR_ONLY(name, type)
 
-/* lprocfs_jobstats.c */
-static inline
-int lprocfs_job_stats_log(struct obd_device *obd, char *jobid, int event,
-			  long amount)
-{ return 0; }
-static inline
-void lprocfs_job_stats_fini(struct obd_device *obd)
-{ return; }
-static inline
-int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num,
-			   cntr_init_callback fn)
-{ return 0; }
-
-
 /* lproc_ptlrpc.c */
 #define target_print_req NULL
 
diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h
index d40ad81..fa31be8 100644
--- a/drivers/staging/lustre/lustre/include/lu_object.h
+++ b/drivers/staging/lustre/lustre/include/lu_object.h
@@ -496,7 +496,7 @@ struct lu_object {
 	/**
 	 * Link to the device, for debugging.
 	 */
-	struct lu_ref_link		*lo_dev_ref;
+	struct lu_ref_link                 lo_dev_ref;
 };
 
 enum lu_object_header_flags {
@@ -665,6 +665,11 @@ lu_site_bkt_from_fid(struct lu_site *site, struct lu_fid *fid)
 	return cfs_hash_bd_extra_get(site->ls_obj_hash, &bd);
 }
 
+static inline struct seq_server_site *lu_site2seq(const struct lu_site *s)
+{
+	return s->ld_seq_site;
+}
+
 /** \name ctors
  * Constructors/destructors.
  * @{
@@ -868,11 +873,19 @@ static inline __u32 lu_object_attr(const struct lu_object *o)
 	return o->lo_header->loh_attr;
 }
 
-static inline struct lu_ref_link *lu_object_ref_add(struct lu_object *o,
-						    const char *scope,
-						    const void *source)
+static inline void lu_object_ref_add(struct lu_object *o,
+				     const char *scope,
+				     const void *source)
+{
+	lu_ref_add(&o->lo_header->loh_reference, scope, source);
+}
+
+static inline void lu_object_ref_add_at(struct lu_object *o,
+					struct lu_ref_link *link,
+					const char *scope,
+					const void *source)
 {
-	return lu_ref_add(&o->lo_header->loh_reference, scope, source);
+	lu_ref_add_at(&o->lo_header->loh_reference, link, scope, source);
 }
 
 static inline void lu_object_ref_del(struct lu_object *o,
@@ -1118,7 +1131,7 @@ struct lu_context_key {
 	/**
 	 * Internal implementation detail: module for this key.
 	 */
-	module_t *lct_owner;
+	struct module *lct_owner;
 	/**
 	 * References to this key. For debugging.
 	 */
diff --git a/drivers/staging/lustre/lustre/include/lu_ref.h b/drivers/staging/lustre/lustre/include/lu_ref.h
index 624c19b..50a2a7f 100644
--- a/drivers/staging/lustre/lustre/include/lu_ref.h
+++ b/drivers/staging/lustre/lustre/include/lu_ref.h
@@ -108,7 +108,12 @@
  */
 
 
-struct lu_ref  {};
+/*
+ * dummy data structures/functions to pass compile for now.
+ * We need to reimplement them with kref.
+ */
+struct lu_ref {};
+struct lu_ref_link {};
 
 static inline void lu_ref_init(struct lu_ref *ref)
 {
@@ -132,6 +137,13 @@ static inline struct lu_ref_link *lu_ref_add_atomic(struct lu_ref *ref,
 	return NULL;
 }
 
+static inline void lu_ref_add_at(struct lu_ref *ref,
+				 struct lu_ref_link *link,
+				 const char *scope,
+				 const void *source)
+{
+}
+
 static inline void lu_ref_del(struct lu_ref *ref, const char *scope,
 			      const void *source)
 {
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_errno.h b/drivers/staging/lustre/lustre/include/lustre/lustre_errno.h
new file mode 100644
index 0000000..2870487
--- /dev/null
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_errno.h
@@ -0,0 +1,215 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (C) 2011 FUJITSU LIMITED.  All rights reserved.
+ *
+ * Copyright (c) 2013, Intel Corporation.
+ */
+
+#ifndef LUSTRE_ERRNO_H
+#define LUSTRE_ERRNO_H
+
+/*
+ * Only "network" errnos, which are defined below, are allowed on wire (or on
+ * disk).  Generic routines exist to help translate between these and a subset
+ * of the "host" errnos.  Some host errnos (e.g., EDEADLOCK) are intentionally
+ * left out.  See also the comment on lustre_errno_hton_mapping[].
+ *
+ * To maintain compatibility with existing x86 clients and servers, each of
+ * these network errnos has the same numerical value as its corresponding host
+ * errno on x86.
+ */
+#define LUSTRE_EPERM		1	/* Operation not permitted */
+#define LUSTRE_ENOENT		2	/* No such file or directory */
+#define LUSTRE_ESRCH		3	/* No such process */
+#define LUSTRE_EINTR		4	/* Interrupted system call */
+#define LUSTRE_EIO		5	/* I/O error */
+#define LUSTRE_ENXIO		6	/* No such device or address */
+#define LUSTRE_E2BIG		7	/* Argument list too long */
+#define LUSTRE_ENOEXEC		8	/* Exec format error */
+#define LUSTRE_EBADF		9	/* Bad file number */
+#define LUSTRE_ECHILD		10	/* No child processes */
+#define LUSTRE_EAGAIN		11	/* Try again */
+#define LUSTRE_ENOMEM		12	/* Out of memory */
+#define LUSTRE_EACCES		13	/* Permission denied */
+#define LUSTRE_EFAULT		14	/* Bad address */
+#define LUSTRE_ENOTBLK		15	/* Block device required */
+#define LUSTRE_EBUSY		16	/* Device or resource busy */
+#define LUSTRE_EEXIST		17	/* File exists */
+#define LUSTRE_EXDEV		18	/* Cross-device link */
+#define LUSTRE_ENODEV		19	/* No such device */
+#define LUSTRE_ENOTDIR		20	/* Not a directory */
+#define LUSTRE_EISDIR		21	/* Is a directory */
+#define LUSTRE_EINVAL		22	/* Invalid argument */
+#define LUSTRE_ENFILE		23	/* File table overflow */
+#define LUSTRE_EMFILE		24	/* Too many open files */
+#define LUSTRE_ENOTTY		25	/* Not a typewriter */
+#define LUSTRE_ETXTBSY		26	/* Text file busy */
+#define LUSTRE_EFBIG		27	/* File too large */
+#define LUSTRE_ENOSPC		28	/* No space left on device */
+#define LUSTRE_ESPIPE		29	/* Illegal seek */
+#define LUSTRE_EROFS		30	/* Read-only file system */
+#define LUSTRE_EMLINK		31	/* Too many links */
+#define LUSTRE_EPIPE		32	/* Broken pipe */
+#define LUSTRE_EDOM		33	/* Math argument out of domain of
+					   func */
+#define LUSTRE_ERANGE		34	/* Math result not representable */
+#define LUSTRE_EDEADLK		35	/* Resource deadlock would occur */
+#define LUSTRE_ENAMETOOLONG	36	/* File name too long */
+#define LUSTRE_ENOLCK		37	/* No record locks available */
+#define LUSTRE_ENOSYS		38	/* Function not implemented */
+#define LUSTRE_ENOTEMPTY	39	/* Directory not empty */
+#define LUSTRE_ELOOP		40	/* Too many symbolic links
+					   encountered */
+#define LUSTRE_ENOMSG		42	/* No message of desired type */
+#define LUSTRE_EIDRM		43	/* Identifier removed */
+#define LUSTRE_ECHRNG		44	/* Channel number out of range */
+#define LUSTRE_EL2NSYNC		45	/* Level 2 not synchronized */
+#define LUSTRE_EL3HLT		46	/* Level 3 halted */
+#define LUSTRE_EL3RST		47	/* Level 3 reset */
+#define LUSTRE_ELNRNG		48	/* Link number out of range */
+#define LUSTRE_EUNATCH		49	/* Protocol driver not attached */
+#define LUSTRE_ENOCSI		50	/* No CSI structure available */
+#define LUSTRE_EL2HLT		51	/* Level 2 halted */
+#define LUSTRE_EBADE		52	/* Invalid exchange */
+#define LUSTRE_EBADR		53	/* Invalid request descriptor */
+#define LUSTRE_EXFULL		54	/* Exchange full */
+#define LUSTRE_ENOANO		55	/* No anode */
+#define LUSTRE_EBADRQC		56	/* Invalid request code */
+#define LUSTRE_EBADSLT		57	/* Invalid slot */
+#define LUSTRE_EBFONT		59	/* Bad font file format */
+#define LUSTRE_ENOSTR		60	/* Device not a stream */
+#define LUSTRE_ENODATA		61	/* No data available */
+#define LUSTRE_ETIME		62	/* Timer expired */
+#define LUSTRE_ENOSR		63	/* Out of streams resources */
+#define LUSTRE_ENONET		64	/* Machine is not on the network */
+#define LUSTRE_ENOPKG		65	/* Package not installed */
+#define LUSTRE_EREMOTE		66	/* Object is remote */
+#define LUSTRE_ENOLINK		67	/* Link has been severed */
+#define LUSTRE_EADV		68	/* Advertise error */
+#define LUSTRE_ESRMNT		69	/* Srmount error */
+#define LUSTRE_ECOMM		70	/* Communication error on send */
+#define LUSTRE_EPROTO		71	/* Protocol error */
+#define LUSTRE_EMULTIHOP	72	/* Multihop attempted */
+#define LUSTRE_EDOTDOT		73	/* RFS specific error */
+#define LUSTRE_EBADMSG		74	/* Not a data message */
+#define LUSTRE_EOVERFLOW	75	/* Value too large for defined data
+					   type */
+#define LUSTRE_ENOTUNIQ		76	/* Name not unique on network */
+#define LUSTRE_EBADFD		77	/* File descriptor in bad state */
+#define LUSTRE_EREMCHG		78	/* Remote address changed */
+#define LUSTRE_ELIBACC		79	/* Can not access a needed shared
+					   library */
+#define LUSTRE_ELIBBAD		80	/* Accessing a corrupted shared
+					   library */
+#define LUSTRE_ELIBSCN		81	/* .lib section in a.out corrupted */
+#define LUSTRE_ELIBMAX		82	/* Attempting to link in too many shared
+					   libraries */
+#define LUSTRE_ELIBEXEC		83	/* Cannot exec a shared library
+					   directly */
+#define LUSTRE_EILSEQ		84	/* Illegal byte sequence */
+#define LUSTRE_ERESTART		85	/* Interrupted system call should be
+					   restarted */
+#define LUSTRE_ESTRPIPE		86	/* Streams pipe error */
+#define LUSTRE_EUSERS		87	/* Too many users */
+#define LUSTRE_ENOTSOCK		88	/* Socket operation on non-socket */
+#define LUSTRE_EDESTADDRREQ	89	/* Destination address required */
+#define LUSTRE_EMSGSIZE		90	/* Message too long */
+#define LUSTRE_EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define LUSTRE_ENOPROTOOPT	92	/* Protocol not available */
+#define LUSTRE_EPROTONOSUPPORT	93	/* Protocol not supported */
+#define LUSTRE_ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define LUSTRE_EOPNOTSUPP	95	/* Operation not supported on transport
+					   endpoint */
+#define LUSTRE_EPFNOSUPPORT	96	/* Protocol family not supported */
+#define LUSTRE_EAFNOSUPPORT	97	/* Address family not supported by
+					   protocol */
+#define LUSTRE_EADDRINUSE	98	/* Address already in use */
+#define LUSTRE_EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define LUSTRE_ENETDOWN		100	/* Network is down */
+#define LUSTRE_ENETUNREACH	101	/* Network is unreachable */
+#define LUSTRE_ENETRESET	102	/* Network dropped connection because of
+					   reset */
+#define LUSTRE_ECONNABORTED	103	/* Software caused connection abort */
+#define LUSTRE_ECONNRESET	104	/* Connection reset by peer */
+#define LUSTRE_ENOBUFS		105	/* No buffer space available */
+#define LUSTRE_EISCONN		106	/* Transport endpoint is already
+					   connected */
+#define LUSTRE_ENOTCONN		107	/* Transport endpoint is not
+					   connected */
+#define LUSTRE_ESHUTDOWN	108	/* Cannot send after transport endpoint
+					   shutdown */
+#define LUSTRE_ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define LUSTRE_ETIMEDOUT	110	/* Connection timed out */
+#define LUSTRE_ECONNREFUSED	111	/* Connection refused */
+#define LUSTRE_EHOSTDOWN	112	/* Host is down */
+#define LUSTRE_EHOSTUNREACH	113	/* No route to host */
+#define LUSTRE_EALREADY		114	/* Operation already in progress */
+#define LUSTRE_EINPROGRESS	115	/* Operation now in progress */
+#define LUSTRE_ESTALE		116	/* Stale NFS file handle */
+#define LUSTRE_EUCLEAN		117	/* Structure needs cleaning */
+#define LUSTRE_ENOTNAM		118	/* Not a XENIX named type file */
+#define LUSTRE_ENAVAIL		119	/* No XENIX semaphores available */
+#define LUSTRE_EISNAM		120	/* Is a named type file */
+#define LUSTRE_EREMOTEIO	121	/* Remote I/O error */
+#define LUSTRE_EDQUOT		122	/* Quota exceeded */
+#define LUSTRE_ENOMEDIUM	123	/* No medium found */
+#define LUSTRE_EMEDIUMTYPE	124	/* Wrong medium type */
+#define LUSTRE_ECANCELED	125	/* Operation Canceled */
+#define LUSTRE_ENOKEY		126	/* Required key not available */
+#define LUSTRE_EKEYEXPIRED	127	/* Key has expired */
+#define LUSTRE_EKEYREVOKED	128	/* Key has been revoked */
+#define LUSTRE_EKEYREJECTED	129	/* Key was rejected by service */
+#define LUSTRE_EOWNERDEAD	130	/* Owner died */
+#define LUSTRE_ENOTRECOVERABLE	131	/* State not recoverable */
+#define LUSTRE_ERESTARTSYS	512
+#define LUSTRE_ERESTARTNOINTR	513
+#define LUSTRE_ERESTARTNOHAND	514	/* restart if no handler.. */
+#define LUSTRE_ENOIOCTLCMD	515	/* No ioctl command */
+#define LUSTRE_ERESTART_RESTARTBLOCK 516 /* restart by calling
+					    sys_restart_syscall */
+#define LUSTRE_EBADHANDLE	521	/* Illegal NFS file handle */
+#define LUSTRE_ENOTSYNC		522	/* Update synchronization mismatch */
+#define LUSTRE_EBADCOOKIE	523	/* Cookie is stale */
+#define LUSTRE_ENOTSUPP		524	/* Operation is not supported */
+#define LUSTRE_ETOOSMALL	525	/* Buffer or request is too small */
+#define LUSTRE_ESERVERFAULT	526	/* An untranslatable error occurred */
+#define LUSTRE_EBADTYPE		527	/* Type not supported by server */
+#define LUSTRE_EJUKEBOX		528	/* Request initiated, but will not
+					   complete before timeout */
+#define LUSTRE_EIOCBQUEUED	529	/* iocb queued, will get completion
+					   event */
+#define LUSTRE_EIOCBRETRY	530	/* iocb queued, will trigger a retry */
+
+/*
+ * Translations are optimized away on x86.  Host errnos that shouldn't be put
+ * on wire could leak through as a result.  Do not count on this side effect.
+ */
+#ifdef CONFIG_LUSTRE_TRANSLATE_ERRNOS
+unsigned int lustre_errno_hton(unsigned int h);
+unsigned int lustre_errno_ntoh(unsigned int n);
+#else
+#define lustre_errno_hton(h) (h)
+#define lustre_errno_ntoh(n) (n)
+#endif
+
+#endif /* LUSTRE_ERRNO_H */
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
index 8825460..984235c 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
@@ -98,6 +98,8 @@
 /* Defn's shared with user-space. */
 #include <lustre/lustre_user.h>
 
+#include <lustre/lustre_errno.h>
+
 /*
  *  GENERAL STUFF
  */
@@ -911,7 +913,7 @@ static inline int lu_fid_cmp(const struct lu_fid *f0,
 		__diff_normalize(fid_ver(f0), fid_ver(f1));
 }
 
-static inline void ostid_cpu_to_le(struct ost_id *src_oi,
+static inline void ostid_cpu_to_le(const struct ost_id *src_oi,
 				   struct ost_id *dst_oi)
 {
 	if (fid_seq_is_mdt0(ostid_seq(src_oi))) {
@@ -922,7 +924,7 @@ static inline void ostid_cpu_to_le(struct ost_id *src_oi,
 	}
 }
 
-static inline void ostid_le_to_cpu(struct ost_id *src_oi,
+static inline void ostid_le_to_cpu(const struct ost_id *src_oi,
 				   struct ost_id *dst_oi)
 {
 	if (fid_seq_is_mdt0(ostid_seq(src_oi))) {
@@ -1544,10 +1546,16 @@ enum obdo_flags {
 #define LOV_MAGIC_V1_DEF  0x0CD10BD0
 #define LOV_MAGIC_V3_DEF  0x0CD30BD0
 
-#define LOV_PATTERN_RAID0 0x001   /* stripes are used round-robin */
-#define LOV_PATTERN_RAID1 0x002   /* stripes are mirrors of each other */
-#define LOV_PATTERN_FIRST 0x100   /* first stripe is not in round-robin */
-#define LOV_PATTERN_CMOBD 0x200
+#define LOV_PATTERN_RAID0	0x001   /* stripes are used round-robin */
+#define LOV_PATTERN_RAID1	0x002   /* stripes are mirrors of each other */
+#define LOV_PATTERN_FIRST	0x100   /* first stripe is not in round-robin */
+#define LOV_PATTERN_CMOBD	0x200
+
+#define LOV_PATTERN_F_MASK	0xffff0000
+#define LOV_PATTERN_F_RELEASED	0x80000000 /* HSM released file */
+
+#define lov_pattern(pattern)		(pattern & ~LOV_PATTERN_F_MASK)
+#define lov_pattern_flags(pattern)	(pattern & LOV_PATTERN_F_MASK)
 
 #define lov_ost_data lov_ost_data_v1
 struct lov_ost_data_v1 {	  /* per-stripe data structure (little-endian)*/
@@ -1662,6 +1670,17 @@ struct lov_mds_md_v3 {	    /* LOV EA mds/wire data (little-endian) */
 	struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 };
 
+static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic)
+{
+	if (lmm_magic == LOV_MAGIC_V3)
+		return sizeof(struct lov_mds_md_v3) +
+				stripes * sizeof(struct lov_ost_data_v1);
+	else
+		return sizeof(struct lov_mds_md_v1) +
+				stripes * sizeof(struct lov_ost_data_v1);
+}
+
+
 #define OBD_MD_FLID	(0x00000001ULL) /* object ID */
 #define OBD_MD_FLATIME     (0x00000002ULL) /* access time */
 #define OBD_MD_FLMTIME     (0x00000004ULL) /* data modification time */
@@ -2671,6 +2690,10 @@ struct ldlm_res_id {
 	__u64 name[RES_NAME_SIZE];
 };
 
+#define DLDLMRES	"["LPX64":"LPX64":"LPX64"]."LPX64i
+#define PLDLMRES(res)	(res)->lr_name.name[0], (res)->lr_name.name[1], \
+			(res)->lr_name.name[2], (res)->lr_name.name[3]
+
 extern void lustre_swab_ldlm_res_id (struct ldlm_res_id *id);
 
 static inline int ldlm_res_eq(const struct ldlm_res_id *res0,
@@ -2963,6 +2986,7 @@ typedef enum {
 	/* LLOG_JOIN_REC	= LLOG_OP_MAGIC | 0x50000, obsolete  1.8.0 */
 	CHANGELOG_REC		= LLOG_OP_MAGIC | 0x60000,
 	CHANGELOG_USER_REC	= LLOG_OP_MAGIC | 0x70000,
+	HSM_AGENT_REC		= LLOG_OP_MAGIC | 0x80000,
 	LLOG_HDR_MAGIC		= LLOG_OP_MAGIC | 0x45539,
 	LLOG_LOGID_MAGIC	= LLOG_OP_MAGIC | 0x4553b,
 } llog_op_type;
@@ -3082,6 +3106,52 @@ struct llog_changelog_user_rec {
 	struct llog_rec_tail  cur_tail;
 } __attribute__((packed));
 
+enum agent_req_status {
+	ARS_WAITING,
+	ARS_STARTED,
+	ARS_FAILED,
+	ARS_CANCELED,
+	ARS_SUCCEED,
+};
+
+static inline char *agent_req_status2name(enum agent_req_status ars)
+{
+	switch (ars) {
+	case ARS_WAITING:
+		return "WAITING";
+	case ARS_STARTED:
+		return "STARTED";
+	case ARS_FAILED:
+		return "FAILED";
+	case ARS_CANCELED:
+		return "CANCELED";
+	case ARS_SUCCEED:
+		return "SUCCEED";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static inline bool agent_req_in_final_state(enum agent_req_status ars)
+{
+	return ((ars == ARS_SUCCEED) || (ars == ARS_FAILED) ||
+		(ars == ARS_CANCELED));
+}
+
+struct llog_agent_req_rec {
+	struct llog_rec_hdr	arr_hdr;	/**< record header */
+	__u32			arr_status;	/**< status of the request */
+						/* must match enum
+						 * agent_req_status */
+	__u32			arr_archive_id;	/**< backend archive number */
+	__u64			arr_flags;	/**< req flags */
+	__u64			arr_compound_id;	/**< compound cookie */
+	__u64			arr_req_create;	/**< req. creation time */
+	__u64			arr_req_change;	/**< req. status change time */
+	struct hsm_action_item	arr_hai;	/**< req. to the agent */
+	struct llog_rec_tail	arr_tail; /**< record tail for_sizezof_only */
+} __attribute__((packed));
+
 /* Old llog gen for compatibility */
 struct llog_gen {
 	__u64 mnt_cnt;
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
index 7e9f575..c7bd447 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
@@ -347,6 +347,16 @@ struct lov_user_md_v3 {	   /* LOV EA user data (host-endian) */
 	struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 } __attribute__((packed));
 
+static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic)
+{
+	if (lmm_magic == LOV_USER_MAGIC_V3)
+		return sizeof(struct lov_user_md_v3) +
+				stripes * sizeof(struct lov_user_ost_data_v1);
+	else
+		return sizeof(struct lov_user_md_v1) +
+				stripes * sizeof(struct lov_user_ost_data_v1);
+}
+
 /* Compile with -D_LARGEFILE64_SOURCE or -D_GNU_SOURCE (or #define) to
  * use this.  It is unsafe to #define those values in this header as it
  * is possible the application has already #included <sys/stat.h>. */
@@ -462,6 +472,8 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen)
 
 /* printf display format
    e.g. printf("file FID is "DFID"\n", PFID(fid)); */
+#define FID_NOBRACE_LEN 40
+#define FID_LEN (FID_NOBRACE_LEN + 2)
 #define DFID_NOBRACE LPX64":0x%x:0x%x"
 #define DFID "["DFID_NOBRACE"]"
 #define PFID(fid)     \
diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h
index f12429f..e14a5f6 100644
--- a/drivers/staging/lustre/lustre/include/lustre_cfg.h
+++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h
@@ -211,13 +211,12 @@ static inline int lustre_cfg_len(__u32 bufcount, __u32 *buflens)
 {
 	int i;
 	int len;
-	ENTRY;
 
 	len = LCFG_HDR_SIZE(bufcount);
 	for (i = 0; i < bufcount; i++)
 		len += cfs_size_round(buflens[i]);
 
-	RETURN(cfs_size_round(len));
+	return cfs_size_round(len);
 }
 
 
@@ -230,12 +229,10 @@ static inline struct lustre_cfg *lustre_cfg_new(int cmd,
 	char *ptr;
 	int i;
 
-	ENTRY;
-
 	OBD_ALLOC(lcfg, lustre_cfg_len(bufs->lcfg_bufcount,
 				       bufs->lcfg_buflen));
 	if (!lcfg)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	lcfg->lcfg_version = LUSTRE_CFG_VERSION;
 	lcfg->lcfg_command = cmd;
@@ -246,7 +243,7 @@ static inline struct lustre_cfg *lustre_cfg_new(int cmd,
 		lcfg->lcfg_buflens[i] = bufs->lcfg_buflen[i];
 		LOGL((char *)bufs->lcfg_buf[i], bufs->lcfg_buflen[i], ptr);
 	}
-	RETURN(lcfg);
+	return lcfg;
 }
 
 static inline void lustre_cfg_free(struct lustre_cfg *lcfg)
@@ -256,44 +253,39 @@ static inline void lustre_cfg_free(struct lustre_cfg *lcfg)
 	len = lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens);
 
 	OBD_FREE(lcfg, len);
-	EXIT;
 	return;
 }
 
 static inline int lustre_cfg_sanity_check(void *buf, int len)
 {
 	struct lustre_cfg *lcfg = (struct lustre_cfg *)buf;
-	ENTRY;
+
 	if (!lcfg)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* check that the first bits of the struct are valid */
 	if (len < LCFG_HDR_SIZE(0))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if (lcfg->lcfg_version != LUSTRE_CFG_VERSION)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if (lcfg->lcfg_bufcount >= LUSTRE_CFG_MAX_BUFCOUNT)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* check that the buflens are valid */
 	if (len < LCFG_HDR_SIZE(lcfg->lcfg_bufcount))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* make sure all the pointers point inside the data */
 	if (len < lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
-	RETURN(0);
+	return 0;
 }
 
 #include <lustre/lustre_user.h>
 
-#ifndef INVALID_UID
-#define INVALID_UID     (-1)
-#endif
-
 /** @} cfg */
 
 #endif // _LUSTRE_CFG_H
diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h
index 8db6086..9228b16 100644
--- a/drivers/staging/lustre/lustre/include/lustre_disk.h
+++ b/drivers/staging/lustre/lustre/include/lustre_disk.h
@@ -53,20 +53,21 @@
 
 /****************** on-disk files *********************/
 
-#define MDT_LOGS_DIR      "LOGS"  /* COMPAT_146 */
-#define MOUNT_CONFIGS_DIR "CONFIGS"
-#define CONFIGS_FILE      "mountdata"
+#define MDT_LOGS_DIR		"LOGS"  /* COMPAT_146 */
+#define MOUNT_CONFIGS_DIR	"CONFIGS"
+#define CONFIGS_FILE		"mountdata"
 /** Persistent mount data are stored on the disk in this file. */
-#define MOUNT_DATA_FILE    MOUNT_CONFIGS_DIR"/"CONFIGS_FILE
-#define LAST_RCVD	 "last_rcvd"
-#define LOV_OBJID	 "lov_objid"
+#define MOUNT_DATA_FILE		MOUNT_CONFIGS_DIR"/"CONFIGS_FILE
+#define LAST_RCVD		"last_rcvd"
+#define LOV_OBJID		"lov_objid"
 #define LOV_OBJSEQ		"lov_objseq"
-#define HEALTH_CHECK      "health_check"
-#define CAPA_KEYS	 "capa_keys"
-#define CHANGELOG_USERS   "changelog_users"
-#define MGS_NIDTBL_DIR    "NIDTBL_VERSIONS"
-#define QMT_DIR	   "quota_master"
-#define QSD_DIR	   "quota_slave"
+#define HEALTH_CHECK		"health_check"
+#define CAPA_KEYS		"capa_keys"
+#define CHANGELOG_USERS		"changelog_users"
+#define MGS_NIDTBL_DIR		"NIDTBL_VERSIONS"
+#define QMT_DIR			"quota_master"
+#define QSD_DIR			"quota_slave"
+#define HSM_ACTIONS		"hsm_actions"
 
 /****************** persistent mount data *********************/
 
@@ -226,21 +227,22 @@ struct lustre_mount_data {
 	char	*lmd_osd_type;      /* OSD type */
 };
 
-#define LMD_FLG_SERVER       0x0001  /* Mounting a server */
-#define LMD_FLG_CLIENT       0x0002  /* Mounting a client */
-#define LMD_FLG_ABORT_RECOV  0x0008  /* Abort recovery */
-#define LMD_FLG_NOSVC	0x0010  /* Only start MGS/MGC for servers,
-					no other services */
-#define LMD_FLG_NOMGS	0x0020  /* Only start target for servers, reusing
-					existing MGS services */
-#define LMD_FLG_WRITECONF    0x0040  /* Rewrite config log */
-#define LMD_FLG_NOIR	 0x0080  /* NO imperative recovery */
-#define LMD_FLG_NOSCRUB	     0x0100  /* Do not trigger scrub automatically */
-#define LMD_FLG_MGS	     0x0200  /* Also start MGS along with server */
-#define LMD_FLG_IAM	     0x0400  /* IAM dir */
-#define LMD_FLG_NO_PRIMNODE  0x0800  /* all nodes are service nodes */
-#define LMD_FLG_VIRGIN	     0x1000  /* the service registers first time */
-#define LMD_FLG_UPDATE	     0x2000  /* update parameters */
+#define LMD_FLG_SERVER		0x0001	/* Mounting a server */
+#define LMD_FLG_CLIENT		0x0002	/* Mounting a client */
+#define LMD_FLG_ABORT_RECOV	0x0008	/* Abort recovery */
+#define LMD_FLG_NOSVC		0x0010	/* Only start MGS/MGC for servers,
+					   no other services */
+#define LMD_FLG_NOMGS		0x0020	/* Only start target for servers, reusing
+					   existing MGS services */
+#define LMD_FLG_WRITECONF	0x0040	/* Rewrite config log */
+#define LMD_FLG_NOIR		0x0080	/* NO imperative recovery */
+#define LMD_FLG_NOSCRUB		0x0100	/* Do not trigger scrub automatically */
+#define LMD_FLG_MGS		0x0200	/* Also start MGS along with server */
+#define LMD_FLG_IAM		0x0400	/* IAM dir */
+#define LMD_FLG_NO_PRIMNODE	0x0800	/* all nodes are service nodes */
+#define LMD_FLG_VIRGIN		0x1000	/* the service registers first time */
+#define LMD_FLG_UPDATE		0x2000	/* update parameters */
+#define LMD_FLG_HSM		0x4000	/* Start coordinator */
 
 #define lmd_is_client(x) ((x)->lmd_flags & LMD_FLG_CLIENT)
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h
index 317f928..7020d9c 100644
--- a/drivers/staging/lustre/lustre/include/lustre_dlm.h
+++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h
@@ -57,6 +57,8 @@
 #include <interval_tree.h> /* for interval_node{}, ldlm_extent */
 #include <lu_ref.h>
 
+#include "lustre_dlm_flags.h"
+
 struct obd_ops;
 struct obd_device;
 
@@ -96,161 +98,6 @@ typedef enum {
 } ldlm_side_t;
 
 /**
- * Declaration of flags sent through the wire.
- **/
-#define LDLM_FL_LOCK_CHANGED   0x000001 /* extent, mode, or resource changed */
-
-/**
- * If the server returns one of these flags, then the lock was put on that list.
- * If the client sends one of these flags (during recovery ONLY!), it wants the
- * lock added to the specified list, no questions asked.
- */
-#define LDLM_FL_BLOCK_GRANTED  0x000002
-#define LDLM_FL_BLOCK_CONV     0x000004
-#define LDLM_FL_BLOCK_WAIT     0x000008
-
-/* Used to be LDLM_FL_CBPENDING 0x000010 moved to non-wire flags */
-
-#define LDLM_FL_AST_SENT       0x000020 /* blocking or cancel packet was
-					 * queued for sending. */
-/* Used to be LDLM_FL_WAIT_NOREPROC 0x000040   moved to non-wire flags */
-/* Used to be LDLM_FL_CANCEL	0x000080   moved to non-wire flags */
-
-/**
- * Lock is being replayed.  This could probably be implied by the fact that one
- * of BLOCK_{GRANTED,CONV,WAIT} is set, but that is pretty dangerous.
- */
-#define LDLM_FL_REPLAY	 0x000100
-
-#define LDLM_FL_INTENT_ONLY    0x000200 /* Don't grant lock, just do intent. */
-
-/* Used to be LDLM_FL_LOCAL_ONLY 0x000400  moved to non-wire flags */
-/* Used to be LDLM_FL_FAILED     0x000800  moved to non-wire flags */
-
-#define LDLM_FL_HAS_INTENT     0x001000 /* lock request has intent */
-
-/* Used to be LDLM_FL_CANCELING  0x002000  moved to non-wire flags */
-/* Used to be LDLM_FL_LOCAL      0x004000  moved to non-wire flags */
-
-#define LDLM_FL_DISCARD_DATA   0x010000 /* discard (no writeback) on cancel */
-
-#define LDLM_FL_NO_TIMEOUT     0x020000 /* Blocked by group lock - wait
-					 * indefinitely */
-
-/** file & record locking */
-#define LDLM_FL_BLOCK_NOWAIT   0x040000 /* Server told not to wait if blocked.
-					 * For AGL, OST will not send glimpse
-					 * callback. */
-#define LDLM_FL_TEST_LOCK      0x080000 // return blocking lock
-
-/* Used to be LDLM_FL_LVB_READY  0x100000 moved to non-wire flags */
-/* Used to be LDLM_FL_KMS_IGNORE 0x200000 moved to non-wire flags */
-/* Used to be LDLM_FL_NO_LRU     0x400000 moved to non-wire flags */
-
-/* Immediatelly cancel such locks when they block some other locks. Send
- * cancel notification to original lock holder, but expect no reply. This is
- * for clients (like liblustre) that cannot be expected to reliably response
- * to blocking AST. */
-#define LDLM_FL_CANCEL_ON_BLOCK 0x800000
-
-/* Flags flags inherited from parent lock when doing intents. */
-#define LDLM_INHERIT_FLAGS     (LDLM_FL_CANCEL_ON_BLOCK)
-
-/* Used to be LDLM_FL_CP_REQD	0x1000000 moved to non-wire flags */
-/* Used to be LDLM_FL_CLEANED	0x2000000 moved to non-wire flags */
-/* Used to be LDLM_FL_ATOMIC_CB      0x4000000 moved to non-wire flags */
-/* Used to be LDLM_FL_BL_AST	 0x10000000 moved to non-wire flags */
-/* Used to be LDLM_FL_BL_DONE	0x20000000 moved to non-wire flags */
-
-/* measure lock contention and return -EUSERS if locking contention is high */
-#define LDLM_FL_DENY_ON_CONTENTION 0x40000000
-
-/* These are flags that are mapped into the flags and ASTs of blocking locks */
-#define LDLM_AST_DISCARD_DATA  0x80000000 /* Add FL_DISCARD to blocking ASTs */
-
-/* Flags sent in AST lock_flags to be mapped into the receiving lock. */
-#define LDLM_AST_FLAGS	 (LDLM_FL_DISCARD_DATA)
-
-/*
- * --------------------------------------------------------------------------
- * NOTE! Starting from this point, that is, LDLM_FL_* flags with values above
- * 0x80000000 will not be sent over the wire.
- * --------------------------------------------------------------------------
- */
-
-/**
- * Declaration of flags not sent through the wire.
- **/
-
-/**
- * Used for marking lock as a target for -EINTR while cp_ast sleep
- * emulation + race with upcoming bl_ast.
- */
-#define LDLM_FL_FAIL_LOC       0x100000000ULL
-
-/**
- * Used while processing the unused list to know that we have already
- * handled this lock and decided to skip it.
- */
-#define LDLM_FL_SKIPPED	0x200000000ULL
-/* this lock is being destroyed */
-#define LDLM_FL_CBPENDING      0x400000000ULL
-/* not a real flag, not saved in lock */
-#define LDLM_FL_WAIT_NOREPROC  0x800000000ULL
-/* cancellation callback already run */
-#define LDLM_FL_CANCEL	 0x1000000000ULL
-#define LDLM_FL_LOCAL_ONLY     0x2000000000ULL
-/* don't run the cancel callback under ldlm_cli_cancel_unused */
-#define LDLM_FL_FAILED	 0x4000000000ULL
-/* lock cancel has already been sent */
-#define LDLM_FL_CANCELING      0x8000000000ULL
-/* local lock (ie, no srv/cli split) */
-#define LDLM_FL_LOCAL	  0x10000000000ULL
-/* XXX FIXME: This is being added to b_size as a low-risk fix to the fact that
- * the LVB filling happens _after_ the lock has been granted, so another thread
- * can match it before the LVB has been updated.  As a dirty hack, we set
- * LDLM_FL_LVB_READY only after we've done the LVB poop.
- * this is only needed on LOV/OSC now, where LVB is actually used and callers
- * must set it in input flags.
- *
- * The proper fix is to do the granting inside of the completion AST, which can
- * be replaced with a LVB-aware wrapping function for OSC locks.  That change is
- * pretty high-risk, though, and would need a lot more testing. */
-#define LDLM_FL_LVB_READY      0x20000000000ULL
-/* A lock contributes to the known minimum size (KMS) calculation until it has
- * finished the part of its cancelation that performs write back on its dirty
- * pages.  It can remain on the granted list during this whole time.  Threads
- * racing to update the KMS after performing their writeback need to know to
- * exclude each other's locks from the calculation as they walk the granted
- * list. */
-#define LDLM_FL_KMS_IGNORE     0x40000000000ULL
-/* completion AST to be executed */
-#define LDLM_FL_CP_REQD	0x80000000000ULL
-/* cleanup_resource has already handled the lock */
-#define LDLM_FL_CLEANED	0x100000000000ULL
-/* optimization hint: LDLM can run blocking callback from current context
- * w/o involving separate thread. in order to decrease cs rate */
-#define LDLM_FL_ATOMIC_CB      0x200000000000ULL
-
-/* It may happen that a client initiates two operations, e.g. unlink and
- * mkdir, such that the server sends a blocking AST for conflicting
- * locks to this client for the first operation, whereas the second
- * operation has canceled this lock and is waiting for rpc_lock which is
- * taken by the first operation. LDLM_FL_BL_AST is set by
- * ldlm_callback_handler() in the lock to prevent the Early Lock Cancel
- * (ELC) code from cancelling it.
- *
- * LDLM_FL_BL_DONE is to be set by ldlm_cancel_callback() when lock
- * cache is dropped to let ldlm_callback_handler() return EINVAL to the
- * server. It is used when ELC RPC is already prepared and is waiting
- * for rpc_lock, too late to send a separate CANCEL RPC. */
-#define LDLM_FL_BL_AST	  0x400000000000ULL
-#define LDLM_FL_BL_DONE	 0x800000000000ULL
-/* Don't put lock into the LRU list, so that it is not canceled due to aging.
- * Used by MGC locks, they are cancelled only at unmount or by callback. */
-#define LDLM_FL_NO_LRU		0x1000000000000ULL
-
-/**
  * The blocking callback is overloaded to perform two functions.  These flags
  * indicate which operation should be performed.
  */
@@ -388,7 +235,7 @@ struct ldlm_pool_ops {
  */
 struct ldlm_pool {
 	/** Pool proc directory. */
-	proc_dir_entry_t	*pl_proc_dir;
+	struct proc_dir_entry	*pl_proc_dir;
 	/** Pool name, must be long enough to hold compound proc entry name. */
 	char			pl_name[100];
 	/** Lock for protecting SLV/CLV updates. */
@@ -720,8 +567,6 @@ typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, __u64 flags,
 					void *data);
 /** Type for glimpse callback function of a lock. */
 typedef int (*ldlm_glimpse_callback)(struct ldlm_lock *lock, void *data);
-/** Type for weight callback function of a lock. */
-typedef unsigned long (*ldlm_weigh_callback)(struct ldlm_lock *lock);
 
 /** Work list for sending GL ASTs to multiple locks. */
 struct ldlm_glimpse_work {
@@ -890,9 +735,6 @@ struct ldlm_lock {
 	 */
 	ldlm_glimpse_callback	l_glimpse_ast;
 
-	/** XXX apparently unused "weight" handler. To be removed? */
-	ldlm_weigh_callback	l_weigh_ast;
-
 	/**
 	 * Lock export.
 	 * This is a pointer to actual client export for locks that were granted
@@ -919,11 +761,11 @@ struct ldlm_lock {
 	ldlm_policy_data_t	l_policy_data;
 
 	/**
-	 * Lock state flags.
-	 * Like whenever we receive any blocking requests for this lock, etc.
-	 * Protected by lr_lock.
+	 * Lock state flags. Protected by lr_lock.
+	 * \see lustre_dlm_flags.h where the bits are defined.
 	 */
 	__u64			l_flags;
+
 	/**
 	 * Lock r/w usage counters.
 	 * Protected by lr_lock.
@@ -952,34 +794,6 @@ struct ldlm_lock {
 	/** Originally requested extent for the extent lock. */
 	struct ldlm_extent	l_req_extent;
 
-	unsigned int		l_failed:1,
-	/**
-	 * Set for locks that were removed from class hash table and will be
-	 * destroyed when last reference to them is released. Set by
-	 * ldlm_lock_destroy_internal().
-	 *
-	 * Protected by lock and resource locks.
-	 */
-				l_destroyed:1,
-	/*
-	 * it's set in lock_res_and_lock() and unset in unlock_res_and_lock().
-	 *
-	 * NB: compared with check_res_locked(), checking this bit is cheaper.
-	 * Also, spin_is_locked() is deprecated for kernel code; one reason is
-	 * because it works only for SMP so user needs to add extra macros like
-	 * LASSERT_SPIN_LOCKED for uniprocessor kernels.
-	 */
-				l_res_locked:1,
-	/*
-	 * It's set once we call ldlm_add_waiting_lock_res_locked()
-	 * to start the lock-timeout timer and it will never be reset.
-	 *
-	 * Protected by lock_res_and_lock().
-	 */
-				l_waited:1,
-	/** Flag whether this is a server namespace lock. */
-				l_ns_srv:1;
-
 	/*
 	 * Client-side-only members.
 	 */
@@ -1230,7 +1044,6 @@ struct ldlm_enqueue_info {
 	void *ei_cb_bl;  /** blocking lock callback */
 	void *ei_cb_cp;  /** lock completion callback */
 	void *ei_cb_gl;  /** lock glimpse callback */
-	void *ei_cb_wg;  /** lock weigh callback */
 	void *ei_cbdata; /** Data to be passed into callbacks. */
 };
 
@@ -1328,7 +1141,6 @@ struct ldlm_callback_suite {
 	ldlm_completion_callback lcs_completion;
 	ldlm_blocking_callback   lcs_blocking;
 	ldlm_glimpse_callback    lcs_glimpse;
-	ldlm_weigh_callback      lcs_weigh;
 };
 
 /* ldlm_lockd.c */
@@ -1471,8 +1283,6 @@ void ldlm_namespace_free(struct ldlm_namespace *ns,
 			 struct obd_import *imp, int force);
 void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client);
 void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client);
-void ldlm_namespace_move_locked(struct ldlm_namespace *ns, ldlm_side_t client);
-struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t client);
 void ldlm_namespace_get(struct ldlm_namespace *ns);
 void ldlm_namespace_put(struct ldlm_namespace *ns);
 int ldlm_proc_setup(void);
@@ -1645,7 +1455,7 @@ void unlock_res_and_lock(struct ldlm_lock *lock);
  * There are not used outside of ldlm.
  * @{
  */
-void ldlm_pools_recalc(ldlm_side_t client);
+int ldlm_pools_recalc(ldlm_side_t client);
 int ldlm_pools_init(void);
 void ldlm_pools_fini(void);
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
new file mode 100644
index 0000000..8c34d9d
--- /dev/null
+++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
@@ -0,0 +1,460 @@
+/*  -*- buffer-read-only: t -*- vi: set ro:
+ *
+ * DO NOT EDIT THIS FILE   (lustre_dlm_flags.h)
+ *
+ * It has been AutoGen-ed
+ * From the definitions    lustre_dlm_flags.def
+ * and the template file   lustre_dlm_flags.tpl
+ *
+ * lustre is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * lustre is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU 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/>.
+ */
+/**
+ * \file lustre_dlm_flags.h
+ * The flags and collections of flags (masks) for \see struct ldlm_lock.
+ * This file is derived from flag definitions in lustre_dlm_flags.def.
+ * The format is defined in the lustre_dlm_flags.tpl template file.
+ *
+ * \addtogroup LDLM Lustre Distributed Lock Manager
+ * @{
+ *
+ * \name flags
+ * The flags and collections of flags (masks) for \see struct ldlm_lock.
+ * @{
+ */
+#ifndef LDLM_ALL_FLAGS_MASK
+
+/** l_flags bits marked as "all_flags" bits */
+#define LDLM_FL_ALL_FLAGS_MASK          0x007FFFFFC08F132FULL
+
+/** l_flags bits marked as "ast" bits */
+#define LDLM_FL_AST_MASK                0x0000000080000000ULL
+
+/** l_flags bits marked as "blocked" bits */
+#define LDLM_FL_BLOCKED_MASK            0x000000000000000EULL
+
+/** l_flags bits marked as "gone" bits */
+#define LDLM_FL_GONE_MASK               0x0006004000000000ULL
+
+/** l_flags bits marked as "hide_lock" bits */
+#define LDLM_FL_HIDE_LOCK_MASK          0x0000206400000000ULL
+
+/** l_flags bits marked as "inherit" bits */
+#define LDLM_FL_INHERIT_MASK            0x0000000000800000ULL
+
+/** l_flags bits marked as "local_only" bits */
+#define LDLM_FL_LOCAL_ONLY_MASK         0x007FFFFF00000000ULL
+
+/** l_flags bits marked as "on_wire" bits */
+#define LDLM_FL_ON_WIRE_MASK            0x00000000C08F132FULL
+
+/** extent, mode, or resource changed */
+#define LDLM_FL_LOCK_CHANGED            0x0000000000000001ULL // bit   0
+#define ldlm_is_lock_changed(_l)        LDLM_TEST_FLAG(( _l), 1ULL <<  0)
+#define ldlm_set_lock_changed(_l)       LDLM_SET_FLAG((  _l), 1ULL <<  0)
+#define ldlm_clear_lock_changed(_l)     LDLM_CLEAR_FLAG((_l), 1ULL <<  0)
+
+/**
+ * Server placed lock on granted list, or a recovering client wants the
+ * lock added to the granted list, no questions asked. */
+#define LDLM_FL_BLOCK_GRANTED           0x0000000000000002ULL // bit   1
+#define ldlm_is_block_granted(_l)       LDLM_TEST_FLAG(( _l), 1ULL <<  1)
+#define ldlm_set_block_granted(_l)      LDLM_SET_FLAG((  _l), 1ULL <<  1)
+#define ldlm_clear_block_granted(_l)    LDLM_CLEAR_FLAG((_l), 1ULL <<  1)
+
+/**
+ * Server placed lock on conv list, or a recovering client wants the lock
+ * added to the conv list, no questions asked. */
+#define LDLM_FL_BLOCK_CONV              0x0000000000000004ULL // bit   2
+#define ldlm_is_block_conv(_l)          LDLM_TEST_FLAG(( _l), 1ULL <<  2)
+#define ldlm_set_block_conv(_l)         LDLM_SET_FLAG((  _l), 1ULL <<  2)
+#define ldlm_clear_block_conv(_l)       LDLM_CLEAR_FLAG((_l), 1ULL <<  2)
+
+/**
+ * Server placed lock on wait list, or a recovering client wants the lock
+ * added to the wait list, no questions asked. */
+#define LDLM_FL_BLOCK_WAIT              0x0000000000000008ULL // bit   3
+#define ldlm_is_block_wait(_l)          LDLM_TEST_FLAG(( _l), 1ULL <<  3)
+#define ldlm_set_block_wait(_l)         LDLM_SET_FLAG((  _l), 1ULL <<  3)
+#define ldlm_clear_block_wait(_l)       LDLM_CLEAR_FLAG((_l), 1ULL <<  3)
+
+/** blocking or cancel packet was queued for sending. */
+#define LDLM_FL_AST_SENT                0x0000000000000020ULL // bit   5
+#define ldlm_is_ast_sent(_l)            LDLM_TEST_FLAG(( _l), 1ULL <<  5)
+#define ldlm_set_ast_sent(_l)           LDLM_SET_FLAG((  _l), 1ULL <<  5)
+#define ldlm_clear_ast_sent(_l)         LDLM_CLEAR_FLAG((_l), 1ULL <<  5)
+
+/**
+ * Lock is being replayed.  This could probably be implied by the fact that
+ * one of BLOCK_{GRANTED,CONV,WAIT} is set, but that is pretty dangerous. */
+#define LDLM_FL_REPLAY                  0x0000000000000100ULL // bit   8
+#define ldlm_is_replay(_l)              LDLM_TEST_FLAG(( _l), 1ULL <<  8)
+#define ldlm_set_replay(_l)             LDLM_SET_FLAG((  _l), 1ULL <<  8)
+#define ldlm_clear_replay(_l)           LDLM_CLEAR_FLAG((_l), 1ULL <<  8)
+
+/** Don't grant lock, just do intent. */
+#define LDLM_FL_INTENT_ONLY             0x0000000000000200ULL // bit   9
+#define ldlm_is_intent_only(_l)         LDLM_TEST_FLAG(( _l), 1ULL <<  9)
+#define ldlm_set_intent_only(_l)        LDLM_SET_FLAG((  _l), 1ULL <<  9)
+#define ldlm_clear_intent_only(_l)      LDLM_CLEAR_FLAG((_l), 1ULL <<  9)
+
+/** lock request has intent */
+#define LDLM_FL_HAS_INTENT              0x0000000000001000ULL // bit  12
+#define ldlm_is_has_intent(_l)          LDLM_TEST_FLAG(( _l), 1ULL << 12)
+#define ldlm_set_has_intent(_l)         LDLM_SET_FLAG((  _l), 1ULL << 12)
+#define ldlm_clear_has_intent(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 12)
+
+/** discard (no writeback) on cancel */
+#define LDLM_FL_DISCARD_DATA            0x0000000000010000ULL // bit  16
+#define ldlm_is_discard_data(_l)        LDLM_TEST_FLAG(( _l), 1ULL << 16)
+#define ldlm_set_discard_data(_l)       LDLM_SET_FLAG((  _l), 1ULL << 16)
+#define ldlm_clear_discard_data(_l)     LDLM_CLEAR_FLAG((_l), 1ULL << 16)
+
+/** Blocked by group lock - wait indefinitely */
+#define LDLM_FL_NO_TIMEOUT              0x0000000000020000ULL // bit  17
+#define ldlm_is_no_timeout(_l)          LDLM_TEST_FLAG(( _l), 1ULL << 17)
+#define ldlm_set_no_timeout(_l)         LDLM_SET_FLAG((  _l), 1ULL << 17)
+#define ldlm_clear_no_timeout(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 17)
+
+/**
+ * Server told not to wait if blocked. For AGL, OST will not send glimpse
+ * callback. */
+#define LDLM_FL_BLOCK_NOWAIT            0x0000000000040000ULL // bit  18
+#define ldlm_is_block_nowait(_l)        LDLM_TEST_FLAG(( _l), 1ULL << 18)
+#define ldlm_set_block_nowait(_l)       LDLM_SET_FLAG((  _l), 1ULL << 18)
+#define ldlm_clear_block_nowait(_l)     LDLM_CLEAR_FLAG((_l), 1ULL << 18)
+
+/** return blocking lock */
+#define LDLM_FL_TEST_LOCK               0x0000000000080000ULL // bit  19
+#define ldlm_is_test_lock(_l)           LDLM_TEST_FLAG(( _l), 1ULL << 19)
+#define ldlm_set_test_lock(_l)          LDLM_SET_FLAG((  _l), 1ULL << 19)
+#define ldlm_clear_test_lock(_l)        LDLM_CLEAR_FLAG((_l), 1ULL << 19)
+
+/**
+ * Immediatelly cancel such locks when they block some other locks. Send
+ * cancel notification to original lock holder, but expect no reply. This
+ * is for clients (like liblustre) that cannot be expected to reliably
+ * response to blocking AST. */
+#define LDLM_FL_CANCEL_ON_BLOCK         0x0000000000800000ULL // bit  23
+#define ldlm_is_cancel_on_block(_l)     LDLM_TEST_FLAG(( _l), 1ULL << 23)
+#define ldlm_set_cancel_on_block(_l)    LDLM_SET_FLAG((  _l), 1ULL << 23)
+#define ldlm_clear_cancel_on_block(_l)  LDLM_CLEAR_FLAG((_l), 1ULL << 23)
+
+/**
+ * measure lock contention and return -EUSERS if locking contention is high */
+#define LDLM_FL_DENY_ON_CONTENTION        0x0000000040000000ULL // bit  30
+#define ldlm_is_deny_on_contention(_l)    LDLM_TEST_FLAG(( _l), 1ULL << 30)
+#define ldlm_set_deny_on_contention(_l)   LDLM_SET_FLAG((  _l), 1ULL << 30)
+#define ldlm_clear_deny_on_contention(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 30)
+
+/**
+ * These are flags that are mapped into the flags and ASTs of blocking
+ * locks Add FL_DISCARD to blocking ASTs */
+#define LDLM_FL_AST_DISCARD_DATA        0x0000000080000000ULL // bit  31
+#define ldlm_is_ast_discard_data(_l)    LDLM_TEST_FLAG(( _l), 1ULL << 31)
+#define ldlm_set_ast_discard_data(_l)   LDLM_SET_FLAG((  _l), 1ULL << 31)
+#define ldlm_clear_ast_discard_data(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 31)
+
+/**
+ * Used for marking lock as a target for -EINTR while cp_ast sleep emulation
+ * + race with upcoming bl_ast. */
+#define LDLM_FL_FAIL_LOC                0x0000000100000000ULL // bit  32
+#define ldlm_is_fail_loc(_l)            LDLM_TEST_FLAG(( _l), 1ULL << 32)
+#define ldlm_set_fail_loc(_l)           LDLM_SET_FLAG((  _l), 1ULL << 32)
+#define ldlm_clear_fail_loc(_l)         LDLM_CLEAR_FLAG((_l), 1ULL << 32)
+
+/**
+ * Used while processing the unused list to know that we have already
+ * handled this lock and decided to skip it. */
+#define LDLM_FL_SKIPPED                 0x0000000200000000ULL // bit  33
+#define ldlm_is_skipped(_l)             LDLM_TEST_FLAG(( _l), 1ULL << 33)
+#define ldlm_set_skipped(_l)            LDLM_SET_FLAG((  _l), 1ULL << 33)
+#define ldlm_clear_skipped(_l)          LDLM_CLEAR_FLAG((_l), 1ULL << 33)
+
+/** this lock is being destroyed */
+#define LDLM_FL_CBPENDING               0x0000000400000000ULL // bit  34
+#define ldlm_is_cbpending(_l)           LDLM_TEST_FLAG(( _l), 1ULL << 34)
+#define ldlm_set_cbpending(_l)          LDLM_SET_FLAG((  _l), 1ULL << 34)
+#define ldlm_clear_cbpending(_l)        LDLM_CLEAR_FLAG((_l), 1ULL << 34)
+
+/** not a real flag, not saved in lock */
+#define LDLM_FL_WAIT_NOREPROC           0x0000000800000000ULL // bit  35
+#define ldlm_is_wait_noreproc(_l)       LDLM_TEST_FLAG(( _l), 1ULL << 35)
+#define ldlm_set_wait_noreproc(_l)      LDLM_SET_FLAG((  _l), 1ULL << 35)
+#define ldlm_clear_wait_noreproc(_l)    LDLM_CLEAR_FLAG((_l), 1ULL << 35)
+
+/** cancellation callback already run */
+#define LDLM_FL_CANCEL                  0x0000001000000000ULL // bit  36
+#define ldlm_is_cancel(_l)              LDLM_TEST_FLAG(( _l), 1ULL << 36)
+#define ldlm_set_cancel(_l)             LDLM_SET_FLAG((  _l), 1ULL << 36)
+#define ldlm_clear_cancel(_l)           LDLM_CLEAR_FLAG((_l), 1ULL << 36)
+
+/** whatever it might mean */
+#define LDLM_FL_LOCAL_ONLY              0x0000002000000000ULL // bit  37
+#define ldlm_is_local_only(_l)          LDLM_TEST_FLAG(( _l), 1ULL << 37)
+#define ldlm_set_local_only(_l)         LDLM_SET_FLAG((  _l), 1ULL << 37)
+#define ldlm_clear_local_only(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 37)
+
+/** don't run the cancel callback under ldlm_cli_cancel_unused */
+#define LDLM_FL_FAILED                  0x0000004000000000ULL // bit  38
+#define ldlm_is_failed(_l)              LDLM_TEST_FLAG(( _l), 1ULL << 38)
+#define ldlm_set_failed(_l)             LDLM_SET_FLAG((  _l), 1ULL << 38)
+#define ldlm_clear_failed(_l)           LDLM_CLEAR_FLAG((_l), 1ULL << 38)
+
+/** lock cancel has already been sent */
+#define LDLM_FL_CANCELING               0x0000008000000000ULL // bit  39
+#define ldlm_is_canceling(_l)           LDLM_TEST_FLAG(( _l), 1ULL << 39)
+#define ldlm_set_canceling(_l)          LDLM_SET_FLAG((  _l), 1ULL << 39)
+#define ldlm_clear_canceling(_l)        LDLM_CLEAR_FLAG((_l), 1ULL << 39)
+
+/** local lock (ie, no srv/cli split) */
+#define LDLM_FL_LOCAL                   0x0000010000000000ULL // bit  40
+#define ldlm_is_local(_l)               LDLM_TEST_FLAG(( _l), 1ULL << 40)
+#define ldlm_set_local(_l)              LDLM_SET_FLAG((  _l), 1ULL << 40)
+#define ldlm_clear_local(_l)            LDLM_CLEAR_FLAG((_l), 1ULL << 40)
+
+/**
+ * XXX FIXME: This is being added to b_size as a low-risk fix to the
+ * fact that the LVB filling happens _after_ the lock has been granted,
+ * so another thread can match it before the LVB has been updated.  As a
+ * dirty hack, we set LDLM_FL_LVB_READY only after we've done the LVB poop.
+ * this is only needed on LOV/OSC now, where LVB is actually used and
+ * callers must set it in input flags.
+ *
+ * The proper fix is to do the granting inside of the completion AST,
+ * which can be replaced with a LVB-aware wrapping function for OSC locks.
+ * That change is pretty high-risk, though, and would need a lot more
+ * testing. */
+#define LDLM_FL_LVB_READY               0x0000020000000000ULL // bit  41
+#define ldlm_is_lvb_ready(_l)           LDLM_TEST_FLAG(( _l), 1ULL << 41)
+#define ldlm_set_lvb_ready(_l)          LDLM_SET_FLAG((  _l), 1ULL << 41)
+#define ldlm_clear_lvb_ready(_l)        LDLM_CLEAR_FLAG((_l), 1ULL << 41)
+
+/**
+ * A lock contributes to the known minimum size (KMS) calculation until it
+ * has finished the part of its cancelation that performs write back on its
+ * dirty pages.  It can remain on the granted list during this whole time.
+ * Threads racing to update the KMS after performing their writeback need
+ * to know to exclude each other's locks from the calculation as they walk
+ * the granted list. */
+#define LDLM_FL_KMS_IGNORE              0x0000040000000000ULL // bit  42
+#define ldlm_is_kms_ignore(_l)          LDLM_TEST_FLAG(( _l), 1ULL << 42)
+#define ldlm_set_kms_ignore(_l)         LDLM_SET_FLAG((  _l), 1ULL << 42)
+#define ldlm_clear_kms_ignore(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 42)
+
+/** completion AST to be executed */
+#define LDLM_FL_CP_REQD                 0x0000080000000000ULL // bit  43
+#define ldlm_is_cp_reqd(_l)             LDLM_TEST_FLAG(( _l), 1ULL << 43)
+#define ldlm_set_cp_reqd(_l)            LDLM_SET_FLAG((  _l), 1ULL << 43)
+#define ldlm_clear_cp_reqd(_l)          LDLM_CLEAR_FLAG((_l), 1ULL << 43)
+
+/** cleanup_resource has already handled the lock */
+#define LDLM_FL_CLEANED                 0x0000100000000000ULL // bit  44
+#define ldlm_is_cleaned(_l)             LDLM_TEST_FLAG(( _l), 1ULL << 44)
+#define ldlm_set_cleaned(_l)            LDLM_SET_FLAG((  _l), 1ULL << 44)
+#define ldlm_clear_cleaned(_l)          LDLM_CLEAR_FLAG((_l), 1ULL << 44)
+
+/**
+ * optimization hint: LDLM can run blocking callback from current context
+ * w/o involving separate thread. in order to decrease cs rate */
+#define LDLM_FL_ATOMIC_CB               0x0000200000000000ULL // bit  45
+#define ldlm_is_atomic_cb(_l)           LDLM_TEST_FLAG(( _l), 1ULL << 45)
+#define ldlm_set_atomic_cb(_l)          LDLM_SET_FLAG((  _l), 1ULL << 45)
+#define ldlm_clear_atomic_cb(_l)        LDLM_CLEAR_FLAG((_l), 1ULL << 45)
+
+/**
+ * It may happen that a client initiates two operations, e.g. unlink and
+ * mkdir, such that the server sends a blocking AST for conflicting locks
+ * to this client for the first operation, whereas the second operation
+ * has canceled this lock and is waiting for rpc_lock which is taken by
+ * the first operation. LDLM_FL_BL_AST is set by ldlm_callback_handler() in
+ * the lock to prevent the Early Lock Cancel (ELC) code from cancelling it.
+ *
+ * LDLM_FL_BL_DONE is to be set by ldlm_cancel_callback() when lock cache is
+ * dropped to let ldlm_callback_handler() return EINVAL to the server. It
+ * is used when ELC RPC is already prepared and is waiting for rpc_lock,
+ * too late to send a separate CANCEL RPC. */
+#define LDLM_FL_BL_AST                  0x0000400000000000ULL // bit  46
+#define ldlm_is_bl_ast(_l)              LDLM_TEST_FLAG(( _l), 1ULL << 46)
+#define ldlm_set_bl_ast(_l)             LDLM_SET_FLAG((  _l), 1ULL << 46)
+#define ldlm_clear_bl_ast(_l)           LDLM_CLEAR_FLAG((_l), 1ULL << 46)
+
+/** whatever it might mean */
+#define LDLM_FL_BL_DONE                 0x0000800000000000ULL // bit  47
+#define ldlm_is_bl_done(_l)             LDLM_TEST_FLAG(( _l), 1ULL << 47)
+#define ldlm_set_bl_done(_l)            LDLM_SET_FLAG((  _l), 1ULL << 47)
+#define ldlm_clear_bl_done(_l)          LDLM_CLEAR_FLAG((_l), 1ULL << 47)
+
+/**
+ * Don't put lock into the LRU list, so that it is not canceled due
+ * to aging.  Used by MGC locks, they are cancelled only at unmount or
+ * by callback. */
+#define LDLM_FL_NO_LRU                  0x0001000000000000ULL // bit  48
+#define ldlm_is_no_lru(_l)              LDLM_TEST_FLAG(( _l), 1ULL << 48)
+#define ldlm_set_no_lru(_l)             LDLM_SET_FLAG((  _l), 1ULL << 48)
+#define ldlm_clear_no_lru(_l)           LDLM_CLEAR_FLAG((_l), 1ULL << 48)
+
+/**
+ * Set for locks that failed and where the server has been notified.
+ *
+ * Protected by lock and resource locks. */
+#define LDLM_FL_FAIL_NOTIFIED           0x0002000000000000ULL // bit  49
+#define ldlm_is_fail_notified(_l)       LDLM_TEST_FLAG(( _l), 1ULL << 49)
+#define ldlm_set_fail_notified(_l)      LDLM_SET_FLAG((  _l), 1ULL << 49)
+#define ldlm_clear_fail_notified(_l)    LDLM_CLEAR_FLAG((_l), 1ULL << 49)
+
+/**
+ * Set for locks that were removed from class hash table and will
+ * be destroyed when last reference to them is released. Set by
+ * ldlm_lock_destroy_internal().
+ *
+ * Protected by lock and resource locks. */
+#define LDLM_FL_DESTROYED               0x0004000000000000ULL // bit  50
+#define ldlm_is_destroyed(_l)           LDLM_TEST_FLAG(( _l), 1ULL << 50)
+#define ldlm_set_destroyed(_l)          LDLM_SET_FLAG((  _l), 1ULL << 50)
+#define ldlm_clear_destroyed(_l)        LDLM_CLEAR_FLAG((_l), 1ULL << 50)
+
+/** flag whether this is a server namespace lock */
+#define LDLM_FL_SERVER_LOCK             0x0008000000000000ULL // bit  51
+#define ldlm_is_server_lock(_l)         LDLM_TEST_FLAG(( _l), 1ULL << 51)
+#define ldlm_set_server_lock(_l)        LDLM_SET_FLAG((  _l), 1ULL << 51)
+#define ldlm_clear_server_lock(_l)      LDLM_CLEAR_FLAG((_l), 1ULL << 51)
+
+/**
+ * It's set in lock_res_and_lock() and unset in unlock_res_and_lock().
+ *
+ * NB: compared with check_res_locked(), checking this bit is cheaper.
+ * Also, spin_is_locked() is deprecated for kernel code; one reason is
+ * because it works only for SMP so user needs to add extra macros like
+ * LASSERT_SPIN_LOCKED for uniprocessor kernels. */
+#define LDLM_FL_RES_LOCKED              0x0010000000000000ULL // bit  52
+#define ldlm_is_res_locked(_l)          LDLM_TEST_FLAG(( _l), 1ULL << 52)
+#define ldlm_set_res_locked(_l)         LDLM_SET_FLAG((  _l), 1ULL << 52)
+#define ldlm_clear_res_locked(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 52)
+
+/**
+ * It's set once we call ldlm_add_waiting_lock_res_locked() to start the
+ * lock-timeout timer and it will never be reset.
+ *
+ * Protected by lock and resource locks. */
+#define LDLM_FL_WAITED                  0x0020000000000000ULL // bit  53
+#define ldlm_is_waited(_l)              LDLM_TEST_FLAG(( _l), 1ULL << 53)
+#define ldlm_set_waited(_l)             LDLM_SET_FLAG((  _l), 1ULL << 53)
+#define ldlm_clear_waited(_l)           LDLM_CLEAR_FLAG((_l), 1ULL << 53)
+
+/** Flag whether this is a server namespace lock. */
+#define LDLM_FL_NS_SRV                  0x0040000000000000ULL // bit  54
+#define ldlm_is_ns_srv(_l)              LDLM_TEST_FLAG(( _l), 1ULL << 54)
+#define ldlm_set_ns_srv(_l)             LDLM_SET_FLAG((  _l), 1ULL << 54)
+#define ldlm_clear_ns_srv(_l)           LDLM_CLEAR_FLAG((_l), 1ULL << 54)
+
+/** test for ldlm_lock flag bit set */
+#define LDLM_TEST_FLAG(_l, _b)        (((_l)->l_flags & (_b)) != 0)
+
+/** set a ldlm_lock flag bit */
+#define LDLM_SET_FLAG(_l, _b)         (((_l)->l_flags |= (_b))
+
+/** clear a ldlm_lock flag bit */
+#define LDLM_CLEAR_FLAG(_l, _b)       (((_l)->l_flags &= ~(_b))
+
+/** Mask of flags inherited from parent lock when doing intents. */
+#define LDLM_INHERIT_FLAGS            LDLM_FL_INHERIT_MASK
+
+/** Mask of Flags sent in AST lock_flags to map into the receiving lock. */
+#define LDLM_AST_FLAGS                LDLM_FL_AST_MASK
+
+/** @} subgroup */
+/** @} group */
+#ifdef WIRESHARK_COMPILE
+static int hf_lustre_ldlm_fl_lock_changed        = -1;
+static int hf_lustre_ldlm_fl_block_granted       = -1;
+static int hf_lustre_ldlm_fl_block_conv          = -1;
+static int hf_lustre_ldlm_fl_block_wait          = -1;
+static int hf_lustre_ldlm_fl_ast_sent            = -1;
+static int hf_lustre_ldlm_fl_replay              = -1;
+static int hf_lustre_ldlm_fl_intent_only         = -1;
+static int hf_lustre_ldlm_fl_has_intent          = -1;
+static int hf_lustre_ldlm_fl_discard_data        = -1;
+static int hf_lustre_ldlm_fl_no_timeout          = -1;
+static int hf_lustre_ldlm_fl_block_nowait        = -1;
+static int hf_lustre_ldlm_fl_test_lock           = -1;
+static int hf_lustre_ldlm_fl_cancel_on_block     = -1;
+static int hf_lustre_ldlm_fl_deny_on_contention  = -1;
+static int hf_lustre_ldlm_fl_ast_discard_data    = -1;
+static int hf_lustre_ldlm_fl_fail_loc            = -1;
+static int hf_lustre_ldlm_fl_skipped             = -1;
+static int hf_lustre_ldlm_fl_cbpending           = -1;
+static int hf_lustre_ldlm_fl_wait_noreproc       = -1;
+static int hf_lustre_ldlm_fl_cancel              = -1;
+static int hf_lustre_ldlm_fl_local_only          = -1;
+static int hf_lustre_ldlm_fl_failed              = -1;
+static int hf_lustre_ldlm_fl_canceling           = -1;
+static int hf_lustre_ldlm_fl_local               = -1;
+static int hf_lustre_ldlm_fl_lvb_ready           = -1;
+static int hf_lustre_ldlm_fl_kms_ignore          = -1;
+static int hf_lustre_ldlm_fl_cp_reqd             = -1;
+static int hf_lustre_ldlm_fl_cleaned             = -1;
+static int hf_lustre_ldlm_fl_atomic_cb           = -1;
+static int hf_lustre_ldlm_fl_bl_ast              = -1;
+static int hf_lustre_ldlm_fl_bl_done             = -1;
+static int hf_lustre_ldlm_fl_no_lru              = -1;
+static int hf_lustre_ldlm_fl_fail_notified       = -1;
+static int hf_lustre_ldlm_fl_destroyed           = -1;
+static int hf_lustre_ldlm_fl_server_lock         = -1;
+static int hf_lustre_ldlm_fl_res_locked          = -1;
+static int hf_lustre_ldlm_fl_waited              = -1;
+static int hf_lustre_ldlm_fl_ns_srv              = -1;
+
+const value_string lustre_ldlm_flags_vals[] = {
+  {LDLM_FL_LOCK_CHANGED,        "LDLM_FL_LOCK_CHANGED"},
+  {LDLM_FL_BLOCK_GRANTED,       "LDLM_FL_BLOCK_GRANTED"},
+  {LDLM_FL_BLOCK_CONV,          "LDLM_FL_BLOCK_CONV"},
+  {LDLM_FL_BLOCK_WAIT,          "LDLM_FL_BLOCK_WAIT"},
+  {LDLM_FL_AST_SENT,            "LDLM_FL_AST_SENT"},
+  {LDLM_FL_REPLAY,              "LDLM_FL_REPLAY"},
+  {LDLM_FL_INTENT_ONLY,         "LDLM_FL_INTENT_ONLY"},
+  {LDLM_FL_HAS_INTENT,          "LDLM_FL_HAS_INTENT"},
+  {LDLM_FL_DISCARD_DATA,        "LDLM_FL_DISCARD_DATA"},
+  {LDLM_FL_NO_TIMEOUT,          "LDLM_FL_NO_TIMEOUT"},
+  {LDLM_FL_BLOCK_NOWAIT,        "LDLM_FL_BLOCK_NOWAIT"},
+  {LDLM_FL_TEST_LOCK,           "LDLM_FL_TEST_LOCK"},
+  {LDLM_FL_CANCEL_ON_BLOCK,     "LDLM_FL_CANCEL_ON_BLOCK"},
+  {LDLM_FL_DENY_ON_CONTENTION,  "LDLM_FL_DENY_ON_CONTENTION"},
+  {LDLM_FL_AST_DISCARD_DATA,    "LDLM_FL_AST_DISCARD_DATA"},
+  {LDLM_FL_FAIL_LOC,            "LDLM_FL_FAIL_LOC"},
+  {LDLM_FL_SKIPPED,             "LDLM_FL_SKIPPED"},
+  {LDLM_FL_CBPENDING,           "LDLM_FL_CBPENDING"},
+  {LDLM_FL_WAIT_NOREPROC,       "LDLM_FL_WAIT_NOREPROC"},
+  {LDLM_FL_CANCEL,              "LDLM_FL_CANCEL"},
+  {LDLM_FL_LOCAL_ONLY,          "LDLM_FL_LOCAL_ONLY"},
+  {LDLM_FL_FAILED,              "LDLM_FL_FAILED"},
+  {LDLM_FL_CANCELING,           "LDLM_FL_CANCELING"},
+  {LDLM_FL_LOCAL,               "LDLM_FL_LOCAL"},
+  {LDLM_FL_LVB_READY,           "LDLM_FL_LVB_READY"},
+  {LDLM_FL_KMS_IGNORE,          "LDLM_FL_KMS_IGNORE"},
+  {LDLM_FL_CP_REQD,             "LDLM_FL_CP_REQD"},
+  {LDLM_FL_CLEANED,             "LDLM_FL_CLEANED"},
+  {LDLM_FL_ATOMIC_CB,           "LDLM_FL_ATOMIC_CB"},
+  {LDLM_FL_BL_AST,              "LDLM_FL_BL_AST"},
+  {LDLM_FL_BL_DONE,             "LDLM_FL_BL_DONE"},
+  {LDLM_FL_NO_LRU,              "LDLM_FL_NO_LRU"},
+  {LDLM_FL_FAIL_NOTIFIED,       "LDLM_FL_FAIL_NOTIFIED"},
+  {LDLM_FL_DESTROYED,           "LDLM_FL_DESTROYED"},
+  {LDLM_FL_SERVER_LOCK,         "LDLM_FL_SERVER_LOCK"},
+  {LDLM_FL_RES_LOCKED,          "LDLM_FL_RES_LOCKED"},
+  {LDLM_FL_WAITED,              "LDLM_FL_WAITED"},
+  {LDLM_FL_NS_SRV,              "LDLM_FL_NS_SRV"},
+  { 0, NULL }
+};
+#endif /*  WIRESHARK_COMPILE */
+#endif /* LDLM_ALL_FLAGS_MASK */
diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h
index 7d20cba..d9d5814 100644
--- a/drivers/staging/lustre/lustre/include/lustre_fid.h
+++ b/drivers/staging/lustre/lustre/include/lustre_fid.h
@@ -38,8 +38,8 @@
  * Author: Yury Umanets <umka@clusterfs.com>
  */
 
-#ifndef __LINUX_FID_H
-#define __LINUX_FID_H
+#ifndef __LUSTRE_FID_H
+#define __LUSTRE_FID_H
 
 /** \defgroup fid fid
  *
@@ -154,13 +154,12 @@
 
 #include <linux/libcfs/libcfs.h>
 #include <lustre/lustre_idl.h>
-#include <lustre_req_layout.h>
-#include <lustre_mdt.h>
-#include <obd.h>
-
 
+struct lu_env;
 struct lu_site;
 struct lu_context;
+struct obd_device;
+struct obd_export;
 
 /* Whole sequences space range and zero range definitions */
 extern const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE;
@@ -320,6 +319,12 @@ static inline void lu_last_id_fid(struct lu_fid *fid, __u64 seq)
 	fid->f_ver = 0;
 }
 
+/* seq client type */
+enum lu_cli_type {
+	LUSTRE_SEQ_METADATA = 1,
+	LUSTRE_SEQ_DATA
+};
+
 enum lu_mgr_type {
 	LUSTRE_SEQ_SERVER,
 	LUSTRE_SEQ_CONTROLLER
@@ -341,7 +346,7 @@ struct lu_client_seq {
 	struct lu_seq_range	 lcs_space;
 
 	/* Seq related proc */
-	proc_dir_entry_t   *lcs_proc_dir;
+	struct proc_dir_entry   *lcs_proc_dir;
 
 	/* This holds last allocated fid in last obtained seq */
 	struct lu_fid	   lcs_fid;
@@ -388,7 +393,7 @@ struct lu_server_seq {
 	struct dt_object       *lss_obj;
 
 	/* Seq related proc */
-	proc_dir_entry_t   *lss_proc_dir;
+	struct proc_dir_entry   *lss_proc_dir;
 
 	/* LUSTRE_SEQ_SERVER or LUSTRE_SEQ_CONTROLLER */
 	enum lu_mgr_type       lss_type;
@@ -426,10 +431,14 @@ struct lu_server_seq {
 	struct seq_server_site  *lss_site;
 };
 
+struct com_thread_info;
 int seq_query(struct com_thread_info *info);
+
+struct ptlrpc_request;
 int seq_handle(struct ptlrpc_request *req);
 
 /* Server methods */
+
 int seq_server_init(struct lu_server_seq *seq,
 		    struct dt_device *dev,
 		    const char *prefix,
@@ -472,6 +481,7 @@ int seq_site_fini(const struct lu_env *env, struct seq_server_site *ss);
 int fid_is_local(const struct lu_env *env,
 		 struct lu_site *site, const struct lu_fid *fid);
 
+enum lu_cli_type;
 int client_fid_init(struct obd_device *obd, struct obd_export *exp,
 		    enum lu_cli_type type);
 int client_fid_fini(struct obd_device *obd);
@@ -488,74 +498,75 @@ struct ldlm_namespace;
  * renaming name[2,3] fields that need to be used for the quota identifier.
  */
 static inline struct ldlm_res_id *
-fid_build_reg_res_name(const struct lu_fid *f,
-		       struct ldlm_res_id *name)
+fid_build_reg_res_name(const struct lu_fid *fid, struct ldlm_res_id *res)
 {
-	memset(name, 0, sizeof *name);
-	name->name[LUSTRE_RES_ID_SEQ_OFF] = fid_seq(f);
-	name->name[LUSTRE_RES_ID_VER_OID_OFF] = fid_ver_oid(f);
-	return name;
+	memset(res, 0, sizeof(*res));
+	res->name[LUSTRE_RES_ID_SEQ_OFF] = fid_seq(fid);
+	res->name[LUSTRE_RES_ID_VER_OID_OFF] = fid_ver_oid(fid);
+
+	return res;
+}
+
+/*
+ * Return true if resource is for object identified by FID.
+ */
+static inline int fid_res_name_eq(const struct lu_fid *fid,
+				  const struct ldlm_res_id *res)
+{
+	return res->name[LUSTRE_RES_ID_SEQ_OFF] == fid_seq(fid) &&
+	       res->name[LUSTRE_RES_ID_VER_OID_OFF] == fid_ver_oid(fid);
+}
+
+/*
+ * Extract FID from LDLM resource. Reverse of fid_build_reg_res_name().
+ */
+static inline struct lu_fid *
+fid_extract_from_res_name(struct lu_fid *fid, const struct ldlm_res_id *res)
+{
+	fid->f_seq = res->name[LUSTRE_RES_ID_SEQ_OFF];
+	fid->f_oid = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF]);
+	fid->f_ver = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32);
+	LASSERT(fid_res_name_eq(fid, res));
+
+	return fid;
 }
 
 /*
  * Build (DLM) resource identifier from global quota FID and quota ID.
  */
 static inline struct ldlm_res_id *
-fid_build_quota_resid(const struct lu_fid *glb_fid, union lquota_id *qid,
+fid_build_quota_res_name(const struct lu_fid *glb_fid, union lquota_id *qid,
 		      struct ldlm_res_id *res)
 {
 	fid_build_reg_res_name(glb_fid, res);
 	res->name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] = fid_seq(&qid->qid_fid);
 	res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] = fid_ver_oid(&qid->qid_fid);
+
 	return res;
 }
 
 /*
  * Extract global FID and quota ID from resource name
  */
-static inline void fid_extract_quota_resid(struct ldlm_res_id *res,
-					   struct lu_fid *glb_fid,
-					   union lquota_id *qid)
+static inline void fid_extract_from_quota_res(struct lu_fid *glb_fid,
+					      union lquota_id *qid,
+					      const struct ldlm_res_id *res)
 {
-	glb_fid->f_seq = res->name[LUSTRE_RES_ID_SEQ_OFF];
-	glb_fid->f_oid = (__u32)res->name[LUSTRE_RES_ID_VER_OID_OFF];
-	glb_fid->f_ver = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32);
-
+	fid_extract_from_res_name(glb_fid, res);
 	qid->qid_fid.f_seq = res->name[LUSTRE_RES_ID_QUOTA_SEQ_OFF];
 	qid->qid_fid.f_oid = (__u32)res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF];
 	qid->qid_fid.f_ver =
 		(__u32)(res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] >> 32);
 }
 
-/*
- * Return true if resource is for object identified by fid.
- */
-static inline int fid_res_name_eq(const struct lu_fid *f,
-				  const struct ldlm_res_id *name)
-{
-	return name->name[LUSTRE_RES_ID_SEQ_OFF] == fid_seq(f) &&
-	       name->name[LUSTRE_RES_ID_VER_OID_OFF] == fid_ver_oid(f);
-}
-
-/* reverse function of fid_build_reg_res_name() */
-static inline void fid_build_from_res_name(struct lu_fid *f,
-					   const struct ldlm_res_id *name)
-{
-	fid_zero(f);
-	f->f_seq = name->name[LUSTRE_RES_ID_SEQ_OFF];
-	f->f_oid = name->name[LUSTRE_RES_ID_VER_OID_OFF] & 0xffffffff;
-	f->f_ver = name->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32;
-	LASSERT(fid_res_name_eq(f, name));
-}
-
 static inline struct ldlm_res_id *
-fid_build_pdo_res_name(const struct lu_fid *f,
-		       unsigned int hash,
-		       struct ldlm_res_id *name)
+fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash,
+		       struct ldlm_res_id *res)
 {
-	fid_build_reg_res_name(f, name);
-	name->name[LUSTRE_RES_ID_HSH_OFF] = hash;
-	return name;
+	fid_build_reg_res_name(fid, res);
+	res->name[LUSTRE_RES_ID_HSH_OFF] = hash;
+
+	return res;
 }
 
 /**
@@ -584,7 +595,7 @@ static inline void ostid_build_res_name(struct ost_id *oi,
 		name->name[LUSTRE_RES_ID_SEQ_OFF] = ostid_id(oi);
 		name->name[LUSTRE_RES_ID_VER_OID_OFF] = ostid_seq(oi);
 	} else {
-		fid_build_reg_res_name((struct lu_fid *)oi, name);
+		fid_build_reg_res_name(&oi->oi_fid, name);
 	}
 }
 
@@ -597,7 +608,7 @@ static inline void ostid_res_name_to_id(struct ost_id *oi,
 		ostid_set_id(oi, name->name[LUSTRE_RES_ID_SEQ_OFF]);
 	} else {
 		/* new resid */
-		fid_build_from_res_name((struct lu_fid *)oi, name);
+		fid_extract_from_res_name(&oi->oi_fid, name);
 	}
 }
 
@@ -644,7 +655,7 @@ static inline void ost_fid_from_resid(struct lu_fid *fid,
 		ostid_to_fid(fid, &oi, 0);
 	} else {
 		/* new resid */
-		fid_build_from_res_name(fid, name);
+		fid_extract_from_res_name(fid, name);
 	}
 }
 
@@ -666,14 +677,14 @@ static inline __u64 fid_flatten(const struct lu_fid *fid)
 
 	if (fid_is_igif(fid)) {
 		ino = lu_igif_ino(fid);
-		RETURN(ino);
+		return ino;
 	}
 
 	seq = fid_seq(fid);
 
 	ino = (seq << 24) + ((seq >> 24) & 0xffffff0000ULL) + fid_oid(fid);
 
-	RETURN(ino ? ino : fid_oid(fid));
+	return ino ? ino : fid_oid(fid);
 }
 
 static inline __u32 fid_hash(const struct lu_fid *f, int bits)
@@ -692,7 +703,7 @@ static inline __u32 fid_flatten32(const struct lu_fid *fid)
 
 	if (fid_is_igif(fid)) {
 		ino = lu_igif_ino(fid);
-		RETURN(ino);
+		return ino;
 	}
 
 	seq = fid_seq(fid) - FID_SEQ_START;
@@ -706,7 +717,7 @@ static inline __u32 fid_flatten32(const struct lu_fid *fid)
 	       (seq >> (64 - (40-8)) & 0xffffff00) +
 	       (fid_oid(fid) & 0xff000fff) + ((fid_oid(fid) & 0x00fff000) << 8);
 
-	RETURN(ino ? ino : fid_oid(fid));
+	return ino ? ino : fid_oid(fid);
 }
 
 static inline int lu_fid_diff(struct lu_fid *fid1, struct lu_fid *fid2)
@@ -759,4 +770,4 @@ static inline void range_be_to_cpu(struct lu_seq_range *dst, const struct lu_seq
 
 /** @} fid */
 
-#endif /* __LINUX_FID_H */
+#endif /* __LUSTRE_FID_H */
diff --git a/drivers/staging/lustre/lustre/include/lustre_fld.h b/drivers/staging/lustre/lustre/include/lustre_fld.h
index 11e034a..550fff5 100644
--- a/drivers/staging/lustre/lustre/include/lustre_fld.h
+++ b/drivers/staging/lustre/lustre/include/lustre_fld.h
@@ -43,9 +43,6 @@
  */
 
 #include <lustre/lustre_idl.h>
-#include <lustre_mdt.h>
-#include <dt_object.h>
-
 #include <linux/libcfs/libcfs.h>
 
 struct lu_client_fld;
@@ -75,7 +72,7 @@ struct lu_fld_target {
 struct lu_server_fld {
 	/**
 	 * Fld dir proc entry. */
-	proc_dir_entry_t    *lsf_proc_dir;
+	struct proc_dir_entry    *lsf_proc_dir;
 
 	/**
 	 * /fld file object device */
@@ -103,7 +100,7 @@ struct lu_server_fld {
 struct lu_client_fld {
 	/**
 	 * Client side proc entry. */
-	proc_dir_entry_t    *lcf_proc_dir;
+	struct proc_dir_entry    *lcf_proc_dir;
 
 	/**
 	 * List of exports client FLD knows about. */
@@ -129,47 +126,9 @@ struct lu_client_fld {
 	 * Client fld proc entry name. */
 	char		     lcf_name[80];
 
-	const struct lu_context *lcf_ctx;
-
 	int		      lcf_flags;
 };
 
-/**
- * number of blocks to reserve for particular operations. Should be function of
- * ... something. Stub for now.
- */
-enum {
-	/* one insert operation can involve two delete and one insert */
-	FLD_TXN_INDEX_INSERT_CREDITS  = 60,
-	FLD_TXN_INDEX_DELETE_CREDITS  = 20,
-};
-
-int fld_query(struct com_thread_info *info);
-
-/* Server methods */
-int fld_server_init(const struct lu_env *env, struct lu_server_fld *fld,
-		    struct dt_device *dt, const char *prefix, int mds_node_id,
-		    int type);
-
-void fld_server_fini(const struct lu_env *env, struct lu_server_fld *fld);
-
-int fld_declare_server_create(const struct lu_env *env,
-			      struct lu_server_fld *fld,
-			      struct lu_seq_range *new,
-			      struct thandle *th);
-
-int fld_server_create(const struct lu_env *env,
-		      struct lu_server_fld *fld,
-		      struct lu_seq_range *add_range,
-		      struct thandle *th);
-
-int fld_insert_entry(const struct lu_env *env,
-		     struct lu_server_fld *fld,
-		     const struct lu_seq_range *range);
-
-int fld_server_lookup(const struct lu_env *env, struct lu_server_fld *fld,
-		      seqno_t seq, struct lu_seq_range *range);
-
 /* Client methods */
 int fld_client_init(struct lu_client_fld *fld,
 		    const char *prefix, int hash);
diff --git a/drivers/staging/lustre/lustre/include/lustre_idmap.h b/drivers/staging/lustre/lustre/include/lustre_idmap.h
index 084bdd6..2da8596 100644
--- a/drivers/staging/lustre/lustre/include/lustre_idmap.h
+++ b/drivers/staging/lustre/lustre/include/lustre_idmap.h
@@ -80,8 +80,8 @@ struct lustre_idmap_table {
 
 struct lu_ucred;
 
-extern void lustre_groups_from_list(group_info_t *ginfo, gid_t *glist);
-extern void lustre_groups_sort(group_info_t *group_info);
+extern void lustre_groups_from_list(struct group_info *ginfo, gid_t *glist);
+extern void lustre_groups_sort(struct group_info *group_info);
 extern int lustre_in_group_p(struct lu_ucred *mu, gid_t grp);
 
 extern int lustre_idmap_add(struct lustre_idmap_table *t,
diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h
index 3a5dd6a..67259eb 100644
--- a/drivers/staging/lustre/lustre/include/lustre_import.h
+++ b/drivers/staging/lustre/lustre/include/lustre_import.h
@@ -336,9 +336,11 @@ static inline unsigned int at_timeout2est(unsigned int val)
 }
 
 static inline void at_reset(struct adaptive_timeout *at, int val) {
+	spin_lock(&at->at_lock);
 	at->at_current = val;
 	at->at_worst_ever = val;
 	at->at_worst_time = cfs_time_current_sec();
+	spin_unlock(&at->at_lock);
 }
 static inline void at_init(struct adaptive_timeout *at, int val, int flags) {
 	memset(at, 0, sizeof(*at));
diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h
index bdfc539..5e11107 100644
--- a/drivers/staging/lustre/lustre/include/lustre_lib.h
+++ b/drivers/staging/lustre/lustre/include/lustre_lib.h
@@ -96,7 +96,7 @@ void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs);
 /* l_lock.c */
 struct lustre_lock {
 	int			l_depth;
-	task_t		*l_owner;
+	struct task_struct	*l_owner;
 	struct semaphore	l_sem;
 	spinlock_t		l_spin;
 };
@@ -260,10 +260,7 @@ int obd_ioctl_popdata(void *arg, void *data, int len);
 
 static inline void obd_ioctl_freedata(char *buf, int len)
 {
-	ENTRY;
-
 	OBD_FREE_LARGE(buf, len);
-	EXIT;
 	return;
 }
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h
index 714ab37..721aa05 100644
--- a/drivers/staging/lustre/lustre/include/lustre_log.h
+++ b/drivers/staging/lustre/lustre/include/lustre_log.h
@@ -469,16 +469,14 @@ static inline int llog_destroy(const struct lu_env *env,
 	struct llog_operations *lop;
 	int rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(handle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_destroy == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	rc = lop->lop_destroy(env, handle);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int llog_next_block(const struct lu_env *env,
@@ -489,17 +487,15 @@ static inline int llog_next_block(const struct lu_env *env,
 	struct llog_operations *lop;
 	int rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(loghandle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_next_block == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	rc = lop->lop_next_block(env, loghandle, cur_idx, next_idx,
 				 cur_offset, buf, len);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int llog_prev_block(const struct lu_env *env,
@@ -509,16 +505,14 @@ static inline int llog_prev_block(const struct lu_env *env,
 	struct llog_operations *lop;
 	int rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(loghandle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_prev_block == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	rc = lop->lop_prev_block(env, loghandle, prev_idx, buf, len);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int llog_connect(struct llog_ctxt *ctxt,
@@ -528,16 +522,14 @@ static inline int llog_connect(struct llog_ctxt *ctxt,
 	struct llog_operations	*lop;
 	int			 rc;
 
-	ENTRY;
-
 	rc = llog_obd2ops(ctxt, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_connect == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	rc = lop->lop_connect(ctxt, logid, gen, uuid);
-	RETURN(rc);
+	return rc;
 }
 
 /* llog.c */
diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h
index fb1561a..1900025 100644
--- a/drivers/staging/lustre/lustre/include/lustre_mdc.h
+++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h
@@ -84,9 +84,8 @@ static inline void mdc_init_rpc_lock(struct mdc_rpc_lock *lck)
 static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck,
 				    struct lookup_intent *it)
 {
-	ENTRY;
-
-	if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP))
+	if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP ||
+			   it->it_op == IT_LAYOUT))
 		return;
 
 	/* This would normally block until the existing request finishes.
@@ -123,8 +122,9 @@ static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck,
 static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck,
 				    struct lookup_intent *it)
 {
-	if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP))
-		goto out;
+	if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP ||
+			   it->it_op == IT_LAYOUT))
+		return;
 
 	if (lck->rpcl_it == MDC_FAKE_RPCL_IT) { /* OBD_FAIL_MDC_RPCS_SEM */
 		mutex_lock(&lck->rpcl_mutex);
@@ -141,8 +141,6 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck,
 	}
 
 	mutex_unlock(&lck->rpcl_mutex);
- out:
-	EXIT;
 }
 
 static inline void mdc_update_max_ea_from_body(struct obd_export *exp,
diff --git a/drivers/staging/lustre/lustre/include/lustre_mdt.h b/drivers/staging/lustre/lustre/include/lustre_mdt.h
deleted file mode 100644
index dba26a6..0000000
--- a/drivers/staging/lustre/lustre/include/lustre_mdt.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#ifndef __LINUX_MDT_H
-#define __LINUX_MDT_H
-
-/** \defgroup mdt mdt
- *
- * @{
- */
-
-#include <lustre/lustre_idl.h>
-#include <lustre_req_layout.h>
-#include <md_object.h>
-#include <dt_object.h>
-#include <linux/libcfs/libcfs.h>
-
-/*
- * Common thread info for mdt, seq and fld
- */
-struct com_thread_info {
-	/*
-	 * for req-layout interface.
-	 */
-	struct req_capsule *cti_pill;
-};
-
-enum {
-	ESERIOUS = 0x0001000
-};
-
-static inline int err_serious(int rc)
-{
-	LASSERT(rc < 0);
-	LASSERT(-rc < ESERIOUS);
-	return -(-rc | ESERIOUS);
-}
-
-static inline int clear_serious(int rc)
-{
-	if (rc < 0)
-		rc = -(-rc & ~ESERIOUS);
-	return rc;
-}
-
-static inline int is_serious(int rc)
-{
-	return (rc < 0 && -rc & ESERIOUS);
-}
-
-/** @} mdt */
-
-#endif
diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h
index 293dd90..e947002 100644
--- a/drivers/staging/lustre/lustre/include/lustre_net.h
+++ b/drivers/staging/lustre/lustre/include/lustre_net.h
@@ -1136,7 +1136,7 @@ struct ptlrpc_nrs_pol_conf {
 	 * different module to the one the NRS framework is held within
 	 * (currently ptlrpc), should set this field to THIS_MODULE.
 	 */
-	module_t			  *nc_owner;
+	struct module			  *nc_owner;
 	/**
 	 * Policy registration flags; a bitmast of \e nrs_policy_flags
 	 */
@@ -1211,7 +1211,7 @@ struct ptlrpc_nrs_pol_desc {
 	 *   then unregistration and lprocfs operations will be properly
 	 *   serialized.
 	 */
-	module_t			       *pd_owner;
+	struct module			       *pd_owner;
 	/**
 	 * Bitmask of \e nrs_policy_flags
 	 */
@@ -2322,8 +2322,13 @@ struct ptlrpc_thread {
 	pid_t t_pid;
 	/**
 	 * put watchdog in the structure per thread b=14840
+	 *
+	 * Lustre watchdog is removed for client in the hope
+	 * of a generic watchdog can be merged in kernel.
+	 * When that happens, we should add below back.
+	 *
+	 * struct lc_watchdog *t_watchdog;
 	 */
-	struct lc_watchdog *t_watchdog;
 	/**
 	 * the svc this thread belonged to b=18582
 	 */
@@ -2484,7 +2489,7 @@ struct ptlrpc_service {
 	/** limit of threads number for each partition */
 	int				srv_nthrs_cpt_limit;
 	/** Root of /proc dir tree for this service */
-	proc_dir_entry_t	   *srv_procroot;
+	struct proc_dir_entry	   *srv_procroot;
 	/** Pointer to statistic data for this service */
 	struct lprocfs_stats	   *srv_stats;
 	/** # hp per lp reqs to handle */
@@ -2631,7 +2636,7 @@ struct ptlrpc_service_part {
 	/** reqs waiting for replies */
 	struct ptlrpc_at_array		scp_at_array;
 	/** early reply timer */
-	timer_list_t			scp_at_timer;
+	struct timer_list		scp_at_timer;
 	/** debug */
 	cfs_time_t			scp_at_checktime;
 	/** check early replies */
@@ -3161,6 +3166,38 @@ lustre_shrink_reply(struct ptlrpc_request *req, int segment,
 	req->rq_replen = lustre_shrink_msg(req->rq_repmsg, segment,
 					   newlen, move_data);
 }
+
+#ifdef CONFIG_LUSTRE_TRANSLATE_ERRNOS
+
+static inline int ptlrpc_status_hton(int h)
+{
+	/*
+	 * Positive errnos must be network errnos, such as LUSTRE_EDEADLK,
+	 * ELDLM_LOCK_ABORTED, etc.
+	 */
+	if (h < 0)
+		return -lustre_errno_hton(-h);
+	else
+		return h;
+}
+
+static inline int ptlrpc_status_ntoh(int n)
+{
+	/*
+	 * See the comment in ptlrpc_status_hton().
+	 */
+	if (n < 0)
+		return -lustre_errno_ntoh(-n);
+	else
+		return n;
+}
+
+#else
+
+#define ptlrpc_status_hton(h) (h)
+#define ptlrpc_status_ntoh(n) (n)
+
+#endif
 /** @} */
 
 /** Change request phase of \a req to \a new_phase */
diff --git a/drivers/staging/lustre/lustre/include/lustre_quota.h b/drivers/staging/lustre/lustre/include/lustre_quota.h
index 1c3041f..71b5d97 100644
--- a/drivers/staging/lustre/lustre/include/lustre_quota.h
+++ b/drivers/staging/lustre/lustre/include/lustre_quota.h
@@ -168,7 +168,7 @@ struct qsd_instance;
  * enforcement. Arguments are documented where each function is defined.  */
 
 struct qsd_instance *qsd_init(const struct lu_env *, char *, struct dt_device *,
-			      proc_dir_entry_t *);
+			      struct proc_dir_entry *);
 int qsd_prepare(const struct lu_env *, struct qsd_instance *);
 int qsd_start(const struct lu_env *, struct qsd_instance *);
 void qsd_fini(const struct lu_env *, struct qsd_instance *);
diff --git a/drivers/staging/lustre/lustre/include/lustre_sec.h b/drivers/staging/lustre/lustre/include/lustre_sec.h
index 9e0908e..70b8b13 100644
--- a/drivers/staging/lustre/lustre/include/lustre_sec.h
+++ b/drivers/staging/lustre/lustre/include/lustre_sec.h
@@ -796,7 +796,7 @@ struct ptlrpc_sec_sops {
 };
 
 struct ptlrpc_sec_policy {
-	module_t		   *sp_owner;
+	struct module		   *sp_owner;
 	char			   *sp_name;
 	__u16			   sp_policy; /* policy number */
 	struct ptlrpc_sec_cops	 *sp_cops;   /* client ops */
diff --git a/drivers/staging/lustre/lustre/include/md_object.h b/drivers/staging/lustre/lustre/include/md_object.h
index 92d6420..daf93af 100644
--- a/drivers/staging/lustre/lustre/include/md_object.h
+++ b/drivers/staging/lustre/lustre/include/md_object.h
@@ -503,11 +503,6 @@ static inline struct md_device *md_obj2dev(const struct md_object *o)
 	return container_of0(o->mo_lu.lo_dev, struct md_device, md_lu_dev);
 }
 
-static inline struct seq_server_site *lu_site2seq(const struct lu_site *s)
-{
-	return s->ld_seq_site;
-}
-
 static inline int md_device_init(struct md_device *md, struct lu_device_type *t)
 {
 	return lu_device_init(&md->md_lu_dev, t);
@@ -876,7 +871,7 @@ struct lu_ucred {
 	__u32	       uc_suppgids[2];
 	cfs_cap_t	   uc_cap;
 	__u32	       uc_umask;
-	group_info_t   *uc_ginfo;
+	struct group_info *uc_ginfo;
 	struct md_identity *uc_identity;
 };
 
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index 0a251fd..a612255 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -49,15 +49,14 @@
 #define IOC_MDC_MAX_NR       50
 
 #include <lustre/lustre_idl.h>
-#include <lu_ref.h>
 #include <lustre_lib.h>
+#include <linux/libcfs/bitmap.h>
+#include <lu_ref.h>
 #include <lustre_export.h>
+#include <lustre_fid.h>
 #include <lustre_fld.h>
 #include <lustre_capa.h>
 
-#include <linux/libcfs/bitmap.h>
-
-
 #define MAX_OBD_DEVICES 8192
 
 struct osc_async_rc {
@@ -119,6 +118,20 @@ struct lov_stripe_md {
 #define lsm_stripe_count lsm_wire.lw_stripe_count
 #define lsm_pool_name    lsm_wire.lw_pool_name
 
+static inline bool lsm_is_released(struct lov_stripe_md *lsm)
+{
+	return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED);
+}
+
+static inline bool lsm_has_objects(struct lov_stripe_md *lsm)
+{
+	if (lsm == NULL)
+		return false;
+	if (lsm_is_released(lsm))
+		return false;
+	return true;
+}
+
 struct obd_info;
 
 typedef int (*obd_enqueue_update_f)(void *cookie, int rc);
@@ -225,7 +238,7 @@ struct obd_type {
 	struct list_head typ_chain;
 	struct obd_ops *typ_dt_ops;
 	struct md_ops *typ_md_ops;
-	proc_dir_entry_t *typ_procroot;
+	struct proc_dir_entry *typ_procroot;
 	char *typ_name;
 	int  typ_refcnt;
 	struct lu_device_type *typ_lu;
@@ -239,30 +252,6 @@ struct brw_page {
 	obd_flag flag;
 };
 
-/* Individual type definitions */
-
-struct ost_server_data;
-
-struct osd_properties {
-	size_t osd_max_ea_size;
-};
-
-#define OBT_MAGIC       0xBDDECEAE
-/* hold common fields for "target" device */
-struct obd_device_target {
-	__u32		     obt_magic;
-	__u32		     obt_instance;
-	struct super_block       *obt_sb;
-	/** last_rcvd file */
-	struct file	      *obt_rcvd_filp;
-	__u64		     obt_mount_count;
-	struct rw_semaphore	  obt_rwsem;
-	struct vfsmount	  *obt_vfsmnt;
-	struct file	      *obt_health_check_filp;
-	struct osd_properties     obt_osd_properties;
-	struct obd_job_stats      obt_jobstats;
-};
-
 /* llog contexts */
 enum llog_ctxt_id {
 	LLOG_CONFIG_ORIG_CTXT  =  0,
@@ -277,100 +266,13 @@ enum llog_ctxt_id {
 	LLOG_TEST_REPL_CTXT,
 	LLOG_LOVEA_ORIG_CTXT,
 	LLOG_LOVEA_REPL_CTXT,
-	LLOG_CHANGELOG_ORIG_CTXT,      /**< changelog generation on mdd */
-	LLOG_CHANGELOG_REPL_CTXT,      /**< changelog access on clients */
-	LLOG_CHANGELOG_USER_ORIG_CTXT, /**< for multiple changelog consumers */
+	LLOG_CHANGELOG_ORIG_CTXT,	/**< changelog generation on mdd */
+	LLOG_CHANGELOG_REPL_CTXT,	/**< changelog access on clients */
+	LLOG_CHANGELOG_USER_ORIG_CTXT,	/**< for multiple changelog consumers */
+	LLOG_AGENT_ORIG_CTXT,		/**< agent requests generation on cdt */
 	LLOG_MAX_CTXTS
 };
 
-#define FILTER_SUBDIR_COUNT      32	    /* set to zero for no subdirs */
-
-struct filter_subdirs {
-	struct dentry *dentry[FILTER_SUBDIR_COUNT];
-};
-
-
-struct filter_ext {
-	__u64		fe_start;
-	__u64		fe_end;
-};
-
-struct filter_obd {
-	/* NB this field MUST be first */
-	struct obd_device_target fo_obt;
-	const char		*fo_fstype;
-
-	int			fo_group_count;
-	struct dentry		*fo_dentry_O;
-	struct dentry		**fo_dentry_O_groups;
-	struct filter_subdirs	*fo_dentry_O_sub;
-	struct mutex		fo_init_lock;	/* group initialization lock*/
-	int			fo_committed_group;
-
-	spinlock_t		fo_objidlock;	/* protect fo_lastobjid */
-
-	unsigned long		fo_destroys_in_progress;
-	struct mutex		fo_create_locks[FILTER_SUBDIR_COUNT];
-
-	struct list_head fo_export_list;
-	int		  fo_subdir_count;
-
-	obd_size	     fo_tot_dirty;      /* protected by obd_osfs_lock */
-	obd_size	     fo_tot_granted;    /* all values in bytes */
-	obd_size	     fo_tot_pending;
-	int		  fo_tot_granted_clients;
-
-	obd_size	     fo_readcache_max_filesize;
-	spinlock_t		fo_flags_lock;
-	unsigned int	 fo_read_cache:1,   /**< enable read-only cache */
-			     fo_writethrough_cache:1,/**< read cache writes */
-			     fo_mds_ost_sync:1, /**< MDS-OST orphan recovery*/
-			     fo_raid_degraded:1;/**< RAID device degraded */
-
-	struct obd_import   *fo_mdc_imp;
-	struct obd_uuid      fo_mdc_uuid;
-	struct lustre_handle fo_mdc_conn;
-	struct file	**fo_last_objid_files;
-	__u64	       *fo_last_objids; /* last created objid for groups,
-					      * protected by fo_objidlock */
-
-	struct mutex		fo_alloc_lock;
-
-	atomic_t	 fo_r_in_flight;
-	atomic_t	 fo_w_in_flight;
-
-	/*
-	 * per-filter pool of kiobuf's allocated by filter_common_setup() and
-	 * torn down by filter_cleanup().
-	 *
-	 * This pool contains kiobuf used by
-	 * filter_{prep,commit}rw_{read,write}() and is shared by all OST
-	 * threads.
-	 *
-	 * Locking: protected by internal lock of cfs_hash, pool can be
-	 * found from this hash table by t_id of ptlrpc_thread.
-	 */
-	struct cfs_hash		*fo_iobuf_hash;
-
-	struct brw_stats	 fo_filter_stats;
-
-	int		      fo_fmd_max_num; /* per exp filter_mod_data */
-	int		      fo_fmd_max_age; /* jiffies to fmd expiry */
-	unsigned long	    fo_syncjournal:1, /* sync journal on writes */
-				 fo_sync_lock_cancel:2;/* sync on lock cancel */
-
-
-	/* sptlrpc stuff */
-	rwlock_t		fo_sptlrpc_lock;
-	struct sptlrpc_rule_set  fo_sptlrpc_rset;
-
-	/* capability related */
-	unsigned int	     fo_fl_oss_capa;
-	struct list_head	       fo_capa_keys;
-	struct hlist_head	*fo_capa_hash;
-	int		      fo_sec_level;
-};
-
 struct timeout_item {
 	enum timeout_event ti_event;
 	cfs_time_t	 ti_timeout;
@@ -536,25 +438,6 @@ struct obd_id_info {
 	obd_id  *data;
 };
 
-/* */
-
-struct echo_obd {
-	struct obd_device_target eo_obt;
-	struct obdo		eo_oa;
-	spinlock_t		 eo_lock;
-	__u64			 eo_lastino;
-	struct lustre_handle	eo_nl_lock;
-	atomic_t		eo_prep;
-};
-
-struct ost_obd {
-	struct ptlrpc_service	*ost_service;
-	struct ptlrpc_service	*ost_create_service;
-	struct ptlrpc_service	*ost_io_service;
-	struct ptlrpc_service	*ost_seq_service;
-	struct mutex		ost_health_mutex;
-};
-
 struct echo_client_obd {
 	struct obd_export	*ec_exp;   /* the local connection to osc/lov */
 	spinlock_t		ec_lock;
@@ -654,7 +537,7 @@ struct pool_desc {
 	struct lov_qos_rr     pool_rr;		/* round robin qos */
 	struct hlist_node      pool_hash;	      /* access by poolname */
 	struct list_head	    pool_list;	      /* serial access */
-	proc_dir_entry_t *pool_proc_entry;	/* file in /proc */
+	struct proc_dir_entry *pool_proc_entry;	/* file in /proc */
 	struct obd_device    *pool_lobd;	      /* obd of the lov/lod to which
 						       * this pool belongs */
 };
@@ -675,7 +558,7 @@ struct lov_obd {
 	int		     lov_pool_count;
 	cfs_hash_t	     *lov_pools_hash_body; /* used for key access */
 	struct list_head	      lov_pool_list; /* used for sequential access */
-	proc_dir_entry_t   *lov_pool_proc_entry;
+	struct proc_dir_entry   *lov_pool_proc_entry;
 	enum lustre_sec_part    lov_sp_me;
 
 	/* Cached LRU pages from upper layer */
@@ -1017,7 +900,7 @@ struct obd_device {
 	int			      obd_requests_queued_for_recovery;
 	wait_queue_head_t		      obd_next_transno_waitq;
 	/* protected by obd_recovery_task_lock */
-	timer_list_t		      obd_recovery_timer;
+	struct timer_list	      obd_recovery_timer;
 	time_t			   obd_recovery_start; /* seconds */
 	time_t			   obd_recovery_end; /* seconds, for lprocfs_status */
 	int			      obd_recovery_time_hard;
@@ -1036,12 +919,8 @@ struct obd_device {
 	int			      obd_recovery_stage;
 
 	union {
-		struct obd_device_target obt;
-		struct filter_obd filter;
 		struct client_obd cli;
-		struct ost_obd ost;
 		struct echo_client_obd echo_client;
-		struct echo_obd echo;
 		struct lov_obd lov;
 		struct lmv_obd lmv;
 	} u;
@@ -1052,10 +931,10 @@ struct obd_device {
 	unsigned int	   md_cntr_base;
 	struct lprocfs_stats  *md_stats;
 
-	proc_dir_entry_t  *obd_proc_entry;
+	struct proc_dir_entry  *obd_proc_entry;
 	void		  *obd_proc_private; /* type private PDEs */
-	proc_dir_entry_t  *obd_proc_exports_entry;
-	proc_dir_entry_t  *obd_svc_procroot;
+	struct proc_dir_entry  *obd_proc_exports_entry;
+	struct proc_dir_entry  *obd_svc_procroot;
 	struct lprocfs_stats  *obd_svc_stats;
 	atomic_t	   obd_evict_inprogress;
 	wait_queue_head_t	    obd_evict_inprogress_waitq;
@@ -1218,12 +1097,6 @@ typedef int (* md_enqueue_cb_t)(struct ptlrpc_request *req,
 				struct md_enqueue_info *minfo,
 				int rc);
 
-/* seq client type */
-enum lu_cli_type {
-	LUSTRE_SEQ_METADATA = 1,
-	LUSTRE_SEQ_DATA
-};
-
 struct md_enqueue_info {
 	struct md_op_data       mi_data;
 	struct lookup_intent    mi_it;
@@ -1235,7 +1108,7 @@ struct md_enqueue_info {
 };
 
 struct obd_ops {
-	module_t *o_owner;
+	struct module *o_owner;
 	int (*o_iocontrol)(unsigned int cmd, struct obd_export *exp, int len,
 			   void *karg, void *uarg);
 	int (*o_get_info)(const struct lu_env *env, struct obd_export *,
diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h
index de5c585..983718f 100644
--- a/drivers/staging/lustre/lustre/include/obd_class.h
+++ b/drivers/staging/lustre/lustre/include/obd_class.h
@@ -326,7 +326,7 @@ void obdo_le_to_cpu(struct obdo *dobdo, struct obdo *sobdo);
 do {							    \
 	if (!(obd)) {					   \
 		CERROR("NULL device\n");			\
-		RETURN(-ENODEV);				\
+		return -ENODEV;				\
 	}						       \
 } while (0)
 
@@ -337,7 +337,7 @@ do {							    \
 	if (!(obd)->obd_set_up || (obd)->obd_stopping) {	\
 		CERROR("Device %d not setup\n",		 \
 		       (obd)->obd_minor);		       \
-		RETURN(-ENODEV);				\
+		return -ENODEV;				\
 	}						       \
 } while (0)
 
@@ -424,7 +424,7 @@ do {							    \
 		if (err)					\
 			CERROR("md_" #op ": dev %s/%d no operation\n", \
 			       obd->obd_name, obd->obd_minor);  \
-		RETURN(err);				    \
+		return err;				    \
 	}						       \
 } while (0)
 
@@ -432,17 +432,17 @@ do {							    \
 do {							    \
 	if ((exp) == NULL) {				    \
 		CERROR("obd_" #op ": NULL export\n");	   \
-		RETURN(-ENODEV);				\
+		return -ENODEV;				\
 	}						       \
 	if ((exp)->exp_obd == NULL || !OBT((exp)->exp_obd)) {   \
 		CERROR("obd_" #op ": cleaned up obd\n");	\
-		RETURN(-EOPNOTSUPP);			    \
+		return -EOPNOTSUPP;			    \
 	}						       \
 	if (!OBT((exp)->exp_obd) || !MDP((exp)->exp_obd, op)) { \
 		CERROR("obd_" #op ": dev %s/%d no operation\n", \
 		       (exp)->exp_obd->obd_name,		\
 		       (exp)->exp_obd->obd_minor);	      \
-		RETURN(-EOPNOTSUPP);			    \
+		return -EOPNOTSUPP;			    \
 	}						       \
 } while (0)
 
@@ -453,7 +453,7 @@ do {							    \
 		if (err)					\
 			CERROR("obd_" #op ": dev %d no operation\n",    \
 			       obd->obd_minor);		 \
-		RETURN(err);				    \
+		return err;				    \
 	}						       \
 } while (0)
 
@@ -461,16 +461,16 @@ do {							    \
 do {							    \
 	if ((exp) == NULL) {				    \
 		CERROR("obd_" #op ": NULL export\n");	   \
-		RETURN(-ENODEV);				\
+		return -ENODEV;				\
 	}						       \
 	if ((exp)->exp_obd == NULL || !OBT((exp)->exp_obd)) {   \
 		CERROR("obd_" #op ": cleaned up obd\n");	\
-		RETURN(-EOPNOTSUPP);			    \
+		return -EOPNOTSUPP;			    \
 	}						       \
 	if (!OBT((exp)->exp_obd) || !OBP((exp)->exp_obd, op)) { \
 		CERROR("obd_" #op ": dev %d no operation\n",    \
 		       (exp)->exp_obd->obd_minor);	      \
-		RETURN(-EOPNOTSUPP);			    \
+		return -EOPNOTSUPP;			    \
 	}						       \
 } while (0)
 
@@ -480,7 +480,7 @@ do {								 \
 		if (err)					     \
 			CERROR("lop_" #op ": dev %d no operation\n", \
 			       ctxt->loc_obd->obd_minor);	    \
-		RETURN(err);					 \
+		return err;					 \
 	}							    \
 } while (0)
 
@@ -495,14 +495,13 @@ static inline int obd_get_info(const struct lu_env *env,
 			       struct lov_stripe_md *lsm)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, get_info);
 	EXP_COUNTER_INCREMENT(exp, get_info);
 
 	rc = OBP(exp->exp_obd, get_info)(env, exp, keylen, key, vallen, val,
 					 lsm);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_set_info_async(const struct lu_env *env,
@@ -511,14 +510,13 @@ static inline int obd_set_info_async(const struct lu_env *env,
 				     struct ptlrpc_request_set *set)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, set_info_async);
 	EXP_COUNTER_INCREMENT(exp, set_info_async);
 
 	rc = OBP(exp->exp_obd, set_info_async)(env, exp, keylen, key, vallen,
 					       val, set);
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -547,7 +545,6 @@ static inline int obd_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 {
 	int rc;
 	DECLARE_LU_VARS(ldt, d);
-	ENTRY;
 
 	ldt = obd->obd_type->typ_lu;
 	if (ldt != NULL) {
@@ -577,7 +574,7 @@ static inline int obd_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 		OBD_COUNTER_INCREMENT(obd, setup);
 		rc = OBP(obd, setup)(obd, cfg);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_precleanup(struct obd_device *obd,
@@ -585,7 +582,6 @@ static inline int obd_precleanup(struct obd_device *obd,
 {
 	int rc;
 	DECLARE_LU_VARS(ldt, d);
-	ENTRY;
 
 	OBD_CHECK_DEV(obd);
 	ldt = obd->obd_type->typ_lu;
@@ -605,14 +601,13 @@ static inline int obd_precleanup(struct obd_device *obd,
 	OBD_COUNTER_INCREMENT(obd, precleanup);
 
 	rc = OBP(obd, precleanup)(obd, cleanup_stage);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_cleanup(struct obd_device *obd)
 {
 	int rc;
 	DECLARE_LU_VARS(ldt, d);
-	ENTRY;
 
 	OBD_CHECK_DEV(obd);
 
@@ -632,13 +627,11 @@ static inline int obd_cleanup(struct obd_device *obd)
 	OBD_COUNTER_INCREMENT(obd, cleanup);
 
 	rc = OBP(obd, cleanup)(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static inline void obd_cleanup_client_import(struct obd_device *obd)
 {
-	ENTRY;
-
 	/* If we set up but never connected, the
 	   client import will not have been cleaned. */
 	down_write(&obd->u.cli.cl_sem);
@@ -656,8 +649,6 @@ static inline void obd_cleanup_client_import(struct obd_device *obd)
 		obd->u.cli.cl_import = NULL;
 	}
 	up_write(&obd->u.cli.cl_sem);
-
-	EXIT;
 }
 
 static inline int
@@ -665,7 +656,6 @@ obd_process_config(struct obd_device *obd, int datalen, void *data)
 {
 	int rc;
 	DECLARE_LU_VARS(ldt, d);
-	ENTRY;
 
 	OBD_CHECK_DEV(obd);
 
@@ -687,7 +677,7 @@ obd_process_config(struct obd_device *obd, int datalen, void *data)
 	OBD_COUNTER_INCREMENT(obd, process_config);
 	obd->obd_process_conf = 0;
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Pack an in-memory MD struct for storage on disk.
@@ -702,13 +692,12 @@ static inline int obd_packmd(struct obd_export *exp,
 			     struct lov_stripe_md *mem_src)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, packmd);
 	EXP_COUNTER_INCREMENT(exp, packmd);
 
 	rc = OBP(exp->exp_obd, packmd)(exp, disk_tgt, mem_src);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_size_diskmd(struct obd_export *exp,
@@ -757,13 +746,12 @@ static inline int obd_unpackmd(struct obd_export *exp,
 			       int disk_len)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, unpackmd);
 	EXP_COUNTER_INCREMENT(exp, unpackmd);
 
 	rc = OBP(exp->exp_obd, unpackmd)(exp, mem_tgt, disk_src, disk_len);
-	RETURN(rc);
+	return rc;
 }
 
 /* helper functions */
@@ -790,13 +778,12 @@ static inline int obd_free_memmd(struct obd_export *exp,
 static inline int obd_precreate(struct obd_export *exp)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, precreate);
 	OBD_COUNTER_INCREMENT(exp->exp_obd, precreate);
 
 	rc = OBP(exp->exp_obd, precreate)(exp);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_create_async(struct obd_export *exp,
@@ -805,13 +792,12 @@ static inline int obd_create_async(struct obd_export *exp,
 				   struct obd_trans_info *oti)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, create_async);
 	EXP_COUNTER_INCREMENT(exp, create_async);
 
 	rc = OBP(exp->exp_obd, create_async)(exp, oinfo, ea, oti);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_create(const struct lu_env *env, struct obd_export *exp,
@@ -819,13 +805,12 @@ static inline int obd_create(const struct lu_env *env, struct obd_export *exp,
 			     struct obd_trans_info *oti)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, create);
 	EXP_COUNTER_INCREMENT(exp, create);
 
 	rc = OBP(exp->exp_obd, create)(env, exp, obdo, ea, oti);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp,
@@ -834,26 +819,24 @@ static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp,
 			      struct obd_export *md_exp, void *capa)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, destroy);
 	EXP_COUNTER_INCREMENT(exp, destroy);
 
 	rc = OBP(exp->exp_obd, destroy)(env, exp, obdo, ea, oti, md_exp, capa);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_getattr(const struct lu_env *env, struct obd_export *exp,
 			      struct obd_info *oinfo)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, getattr);
 	EXP_COUNTER_INCREMENT(exp, getattr);
 
 	rc = OBP(exp->exp_obd, getattr)(env, exp, oinfo);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_getattr_async(struct obd_export *exp,
@@ -861,13 +844,12 @@ static inline int obd_getattr_async(struct obd_export *exp,
 				    struct ptlrpc_request_set *set)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, getattr_async);
 	EXP_COUNTER_INCREMENT(exp, getattr_async);
 
 	rc = OBP(exp->exp_obd, getattr_async)(exp, oinfo, set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp,
@@ -875,13 +857,12 @@ static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp,
 			      struct obd_trans_info *oti)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, setattr);
 	EXP_COUNTER_INCREMENT(exp, setattr);
 
 	rc = OBP(exp->exp_obd, setattr)(env, exp, oinfo, oti);
-	RETURN(rc);
+	return rc;
 }
 
 /* This performs all the requests set init/wait/destroy actions. */
@@ -891,20 +872,19 @@ static inline int obd_setattr_rqset(struct obd_export *exp,
 {
 	struct ptlrpc_request_set *set = NULL;
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, setattr_async);
 	EXP_COUNTER_INCREMENT(exp, setattr_async);
 
 	set =  ptlrpc_prep_set();
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = OBP(exp->exp_obd, setattr_async)(exp, oinfo, oti, set);
 	if (rc == 0)
 		rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
-	RETURN(rc);
+	return rc;
 }
 
 /* This adds all the requests into @set if @set != NULL, otherwise
@@ -915,13 +895,12 @@ static inline int obd_setattr_async(struct obd_export *exp,
 				    struct ptlrpc_request_set *set)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, setattr_async);
 	EXP_COUNTER_INCREMENT(exp, setattr_async);
 
 	rc = OBP(exp->exp_obd, setattr_async)(exp, oinfo, oti, set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
@@ -929,40 +908,37 @@ static inline int obd_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
 {
 	struct obd_device *obd = imp->imp_obd;
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DEV_ACTIVE(obd);
 	OBD_CHECK_DT_OP(obd, add_conn, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, add_conn);
 
 	rc = OBP(obd, add_conn)(imp, uuid, priority);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
 {
 	struct obd_device *obd = imp->imp_obd;
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DEV_ACTIVE(obd);
 	OBD_CHECK_DT_OP(obd, del_conn, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, del_conn);
 
 	rc = OBP(obd, del_conn)(imp, uuid);
-	RETURN(rc);
+	return rc;
 }
 
 static inline struct obd_uuid *obd_get_uuid(struct obd_export *exp)
 {
 	struct obd_uuid *uuid;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, get_uuid, NULL);
 	EXP_COUNTER_INCREMENT(exp, get_uuid);
 
 	uuid = OBP(exp->exp_obd, get_uuid)(exp);
-	RETURN(uuid);
+	return uuid;
 }
 
 /** Create a new /a exp on device /a obd for the uuid /a cluuid
@@ -979,7 +955,6 @@ static inline int obd_connect(const struct lu_env *env,
 	int rc;
 	__u64 ocf = data ? data->ocd_connect_flags : 0; /* for post-condition
 						   * check */
-	ENTRY;
 
 	OBD_CHECK_DEV_ACTIVE(obd);
 	OBD_CHECK_DT_OP(obd, connect, -EOPNOTSUPP);
@@ -989,7 +964,7 @@ static inline int obd_connect(const struct lu_env *env,
 	/* check that only subset is granted */
 	LASSERT(ergo(data != NULL, (data->ocd_connect_flags & ocf) ==
 				    data->ocd_connect_flags));
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_reconnect(const struct lu_env *env,
@@ -1003,8 +978,6 @@ static inline int obd_reconnect(const struct lu_env *env,
 	__u64 ocf = d ? d->ocd_connect_flags : 0; /* for post-condition
 						   * check */
 
-	ENTRY;
-
 	OBD_CHECK_DEV_ACTIVE(obd);
 	OBD_CHECK_DT_OP(obd, reconnect, 0);
 	OBD_COUNTER_INCREMENT(obd, reconnect);
@@ -1013,44 +986,41 @@ static inline int obd_reconnect(const struct lu_env *env,
 	/* check that only subset is granted */
 	LASSERT(ergo(d != NULL,
 		     (d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_disconnect(struct obd_export *exp)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, disconnect);
 	EXP_COUNTER_INCREMENT(exp, disconnect);
 
 	rc = OBP(exp->exp_obd, disconnect)(exp);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_fid_init(struct obd_device *obd, struct obd_export *exp,
 			       enum lu_cli_type type)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(obd, fid_init, 0);
 	OBD_COUNTER_INCREMENT(obd, fid_init);
 
 	rc = OBP(obd, fid_init)(obd, exp, type);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_fid_fini(struct obd_device *obd)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(obd, fid_fini, 0);
 	OBD_COUNTER_INCREMENT(obd, fid_fini);
 
 	rc = OBP(obd, fid_fini)(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_fid_alloc(struct obd_export *exp,
@@ -1058,113 +1028,101 @@ static inline int obd_fid_alloc(struct obd_export *exp,
 				struct md_op_data *op_data)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, fid_alloc);
 	EXP_COUNTER_INCREMENT(exp, fid_alloc);
 
 	rc = OBP(exp->exp_obd, fid_alloc)(exp, fid, op_data);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_ping(const struct lu_env *env, struct obd_export *exp)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, ping, 0);
 	EXP_COUNTER_INCREMENT(exp, ping);
 
 	rc = OBP(exp->exp_obd, ping)(env, exp);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_pool_new(struct obd_device *obd, char *poolname)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(obd, pool_new, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, pool_new);
 
 	rc = OBP(obd, pool_new)(obd, poolname);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_pool_del(struct obd_device *obd, char *poolname)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(obd, pool_del, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, pool_del);
 
 	rc = OBP(obd, pool_del)(obd, poolname);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_pool_add(struct obd_device *obd, char *poolname, char *ostname)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(obd, pool_add, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, pool_add);
 
 	rc = OBP(obd, pool_add)(obd, poolname, ostname);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_pool_rem(struct obd_device *obd, char *poolname, char *ostname)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(obd, pool_rem, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, pool_rem);
 
 	rc = OBP(obd, pool_rem)(obd, poolname, ostname);
-	RETURN(rc);
+	return rc;
 }
 
 static inline void obd_getref(struct obd_device *obd)
 {
-	ENTRY;
 	if (OBT(obd) && OBP(obd, getref)) {
 		OBD_COUNTER_INCREMENT(obd, getref);
 		OBP(obd, getref)(obd);
 	}
-	EXIT;
 }
 
 static inline void obd_putref(struct obd_device *obd)
 {
-	ENTRY;
 	if (OBT(obd) && OBP(obd, putref)) {
 		OBD_COUNTER_INCREMENT(obd, putref);
 		OBP(obd, putref)(obd);
 	}
-	EXIT;
 }
 
 static inline int obd_init_export(struct obd_export *exp)
 {
 	int rc = 0;
 
-	ENTRY;
 	if ((exp)->exp_obd != NULL && OBT((exp)->exp_obd) &&
 	    OBP((exp)->exp_obd, init_export))
 		rc = OBP(exp->exp_obd, init_export)(exp);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_destroy_export(struct obd_export *exp)
 {
-	ENTRY;
 	if ((exp)->exp_obd != NULL && OBT((exp)->exp_obd) &&
 	    OBP((exp)->exp_obd, destroy_export))
 		OBP(exp->exp_obd, destroy_export)(exp);
-	RETURN(0);
+	return 0;
 }
 
 static inline int obd_extent_calc(struct obd_export *exp,
@@ -1172,10 +1130,10 @@ static inline int obd_extent_calc(struct obd_export *exp,
 				  int cmd, obd_off *offset)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_DT_OP(exp, extent_calc);
 	rc = OBP(exp->exp_obd, extent_calc)(exp, md, cmd, offset);
-	RETURN(rc);
+	return rc;
 }
 
 static inline struct dentry *
@@ -1198,10 +1156,9 @@ static inline int obd_statfs_async(struct obd_export *exp,
 {
 	int rc = 0;
 	struct obd_device *obd;
-	ENTRY;
 
 	if (exp == NULL || exp->exp_obd == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	obd = exp->exp_obd;
 	OBD_CHECK_DT_OP(obd, statfs, -EOPNOTSUPP);
@@ -1224,7 +1181,7 @@ static inline int obd_statfs_async(struct obd_export *exp,
 		if (oinfo->oi_cb_up)
 			oinfo->oi_cb_up(oinfo, 0);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_statfs_rqset(struct obd_export *exp,
@@ -1234,11 +1191,10 @@ static inline int obd_statfs_rqset(struct obd_export *exp,
 	struct ptlrpc_request_set *set = NULL;
 	struct obd_info oinfo = { { { 0 } } };
 	int rc = 0;
-	ENTRY;
 
 	set =  ptlrpc_prep_set();
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	oinfo.oi_osfs = osfs;
 	oinfo.oi_flags = flags;
@@ -1246,7 +1202,7 @@ static inline int obd_statfs_rqset(struct obd_export *exp,
 	if (rc == 0)
 		rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
-	RETURN(rc);
+	return rc;
 }
 
 /* @max_age is the oldest time in jiffies that we accept using a cached data.
@@ -1258,10 +1214,9 @@ static inline int obd_statfs(const struct lu_env *env, struct obd_export *exp,
 {
 	int rc = 0;
 	struct obd_device *obd = exp->exp_obd;
-	ENTRY;
 
 	if (obd == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	OBD_CHECK_DT_OP(obd, statfs, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, statfs);
@@ -1286,7 +1241,7 @@ static inline int obd_statfs(const struct lu_env *env, struct obd_export *exp,
 		memcpy(osfs, &obd->obd_osfs, sizeof(*osfs));
 		spin_unlock(&obd->obd_osfs_lock);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_sync_rqset(struct obd_export *exp, struct obd_info *oinfo,
@@ -1294,20 +1249,19 @@ static inline int obd_sync_rqset(struct obd_export *exp, struct obd_info *oinfo,
 {
 	struct ptlrpc_request_set *set = NULL;
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, sync, -EOPNOTSUPP);
 	EXP_COUNTER_INCREMENT(exp, sync);
 
 	set =  ptlrpc_prep_set();
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = OBP(exp->exp_obd, sync)(NULL, exp, oinfo, start, end, set);
 	if (rc == 0)
 		rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_sync(const struct lu_env *env, struct obd_export *exp,
@@ -1315,13 +1269,12 @@ static inline int obd_sync(const struct lu_env *env, struct obd_export *exp,
 			   struct ptlrpc_request_set *set)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, sync, -EOPNOTSUPP);
 	EXP_COUNTER_INCREMENT(exp, sync);
 
 	rc = OBP(exp->exp_obd, sync)(env, exp, oinfo, start, end, set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_punch_rqset(struct obd_export *exp,
@@ -1330,20 +1283,19 @@ static inline int obd_punch_rqset(struct obd_export *exp,
 {
 	struct ptlrpc_request_set *set = NULL;
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, punch);
 	EXP_COUNTER_INCREMENT(exp, punch);
 
 	set =  ptlrpc_prep_set();
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = OBP(exp->exp_obd, punch)(NULL, exp, oinfo, oti, set);
 	if (rc == 0)
 		rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_punch(const struct lu_env *env, struct obd_export *exp,
@@ -1351,13 +1303,12 @@ static inline int obd_punch(const struct lu_env *env, struct obd_export *exp,
 			    struct ptlrpc_request_set *rqset)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, punch);
 	EXP_COUNTER_INCREMENT(exp, punch);
 
 	rc = OBP(exp->exp_obd, punch)(env, exp, oinfo, oti, rqset);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_brw(int cmd, struct obd_export *exp,
@@ -1365,7 +1316,6 @@ static inline int obd_brw(int cmd, struct obd_export *exp,
 			  struct brw_page *pg, struct obd_trans_info *oti)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, brw);
 	EXP_COUNTER_INCREMENT(exp, brw);
@@ -1377,7 +1327,7 @@ static inline int obd_brw(int cmd, struct obd_export *exp,
 	}
 
 	rc = OBP(exp->exp_obd, brw)(cmd, exp, oinfo, oa_bufs, pg, oti);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_preprw(const struct lu_env *env, int cmd,
@@ -1389,14 +1339,13 @@ static inline int obd_preprw(const struct lu_env *env, int cmd,
 			     struct lustre_capa *capa)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, preprw);
 	EXP_COUNTER_INCREMENT(exp, preprw);
 
 	rc = OBP(exp->exp_obd, preprw)(env, cmd, exp, oa, objcount, obj, remote,
 				       pages, local, oti, capa);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_commitrw(const struct lu_env *env, int cmd,
@@ -1406,14 +1355,12 @@ static inline int obd_commitrw(const struct lu_env *env, int cmd,
 			       struct niobuf_local *local,
 			       struct obd_trans_info *oti, int rc)
 {
-	ENTRY;
-
 	EXP_CHECK_DT_OP(exp, commitrw);
 	EXP_COUNTER_INCREMENT(exp, commitrw);
 
 	rc = OBP(exp->exp_obd, commitrw)(env, cmd, exp, oa, objcount, obj,
 					 rnb, pages, local, oti, rc);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_merge_lvb(struct obd_export *exp,
@@ -1421,13 +1368,12 @@ static inline int obd_merge_lvb(struct obd_export *exp,
 				struct ost_lvb *lvb, int kms_only)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, merge_lvb);
 	EXP_COUNTER_INCREMENT(exp, merge_lvb);
 
 	rc = OBP(exp->exp_obd, merge_lvb)(exp, lsm, lvb, kms_only);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_adjust_kms(struct obd_export *exp,
@@ -1435,26 +1381,24 @@ static inline int obd_adjust_kms(struct obd_export *exp,
 				 int shrink)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, adjust_kms);
 	EXP_COUNTER_INCREMENT(exp, adjust_kms);
 
 	rc = OBP(exp->exp_obd, adjust_kms)(exp, lsm, size, shrink);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp,
 				int len, void *karg, void *uarg)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, iocontrol);
 	EXP_COUNTER_INCREMENT(exp, iocontrol);
 
 	rc = OBP(exp->exp_obd, iocontrol)(cmd, exp, len, karg, uarg);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_enqueue_rqset(struct obd_export *exp,
@@ -1463,20 +1407,19 @@ static inline int obd_enqueue_rqset(struct obd_export *exp,
 {
 	struct ptlrpc_request_set *set = NULL;
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, enqueue);
 	EXP_COUNTER_INCREMENT(exp, enqueue);
 
 	set =  ptlrpc_prep_set();
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = OBP(exp->exp_obd, enqueue)(exp, oinfo, einfo, set);
 	if (rc == 0)
 		rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_enqueue(struct obd_export *exp,
@@ -1485,13 +1428,12 @@ static inline int obd_enqueue(struct obd_export *exp,
 			      struct ptlrpc_request_set *set)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, enqueue);
 	EXP_COUNTER_INCREMENT(exp, enqueue);
 
 	rc = OBP(exp->exp_obd, enqueue)(exp, oinfo, einfo, set);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_change_cbdata(struct obd_export *exp,
@@ -1499,13 +1441,12 @@ static inline int obd_change_cbdata(struct obd_export *exp,
 				    ldlm_iterator_t it, void *data)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, change_cbdata);
 	EXP_COUNTER_INCREMENT(exp, change_cbdata);
 
 	rc = OBP(exp->exp_obd, change_cbdata)(exp, lsm, it, data);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_find_cbdata(struct obd_export *exp,
@@ -1513,13 +1454,12 @@ static inline int obd_find_cbdata(struct obd_export *exp,
 				  ldlm_iterator_t it, void *data)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, find_cbdata);
 	EXP_COUNTER_INCREMENT(exp, find_cbdata);
 
 	rc = OBP(exp->exp_obd, find_cbdata)(exp, lsm, it, data);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_cancel(struct obd_export *exp,
@@ -1527,13 +1467,12 @@ static inline int obd_cancel(struct obd_export *exp,
 			     struct lustre_handle *lockh)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, cancel);
 	EXP_COUNTER_INCREMENT(exp, cancel);
 
 	rc = OBP(exp->exp_obd, cancel)(exp, ea, mode, lockh);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_cancel_unused(struct obd_export *exp,
@@ -1542,13 +1481,12 @@ static inline int obd_cancel_unused(struct obd_export *exp,
 				    void *opaque)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, cancel_unused);
 	EXP_COUNTER_INCREMENT(exp, cancel_unused);
 
 	rc = OBP(exp->exp_obd, cancel_unused)(exp, ea, flags, opaque);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_pin(struct obd_export *exp, const struct lu_fid *fid,
@@ -1556,26 +1494,24 @@ static inline int obd_pin(struct obd_export *exp, const struct lu_fid *fid,
 			  int flag)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, pin);
 	EXP_COUNTER_INCREMENT(exp, pin);
 
 	rc = OBP(exp->exp_obd, pin)(exp, fid, oc, handle, flag);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_unpin(struct obd_export *exp,
 			    struct obd_client_handle *handle, int flag)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, unpin);
 	EXP_COUNTER_INCREMENT(exp, unpin);
 
 	rc = OBP(exp->exp_obd, unpin)(exp, handle, flag);
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1583,30 +1519,26 @@ static inline void obd_import_event(struct obd_device *obd,
 				    struct obd_import *imp,
 				    enum obd_import_event event)
 {
-	ENTRY;
 	if (!obd) {
 		CERROR("NULL device\n");
-		EXIT;
 		return;
 	}
 	if (obd->obd_set_up && OBP(obd, import_event)) {
 		OBD_COUNTER_INCREMENT(obd, import_event);
 		OBP(obd, import_event)(obd, imp, event);
 	}
-	EXIT;
 }
 
 static inline int obd_llog_connect(struct obd_export *exp,
 				   struct llogd_conn_body *body)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, llog_connect, 0);
 	EXP_COUNTER_INCREMENT(exp, llog_connect);
 
 	rc = OBP(exp->exp_obd, llog_connect)(exp, body);
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1616,7 +1548,7 @@ static inline int obd_notify(struct obd_device *obd,
 			     void *data)
 {
 	int rc;
-	ENTRY;
+
 	OBD_CHECK_DEV(obd);
 
 	/* the check for async_recov is a complete hack - I'm hereby
@@ -1625,17 +1557,17 @@ static inline int obd_notify(struct obd_device *obd,
 	   by this point, and it needs to get them to execute mds_postrecov. */
 	if (!obd->obd_set_up && !obd->obd_async_recov) {
 		CDEBUG(D_HA, "obd %s not set up\n", obd->obd_name);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (!OBP(obd, notify)) {
 		CDEBUG(D_HA, "obd %s has no notify handler\n", obd->obd_name);
-		RETURN(-ENOSYS);
+		return -ENOSYS;
 	}
 
 	OBD_COUNTER_INCREMENT(obd, notify);
 	rc = OBP(obd, notify)(obd, watched, ev, data);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_notify_observer(struct obd_device *observer,
@@ -1669,26 +1601,24 @@ static inline int obd_quotacheck(struct obd_export *exp,
 				 struct obd_quotactl *oqctl)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, quotacheck);
 	EXP_COUNTER_INCREMENT(exp, quotacheck);
 
 	rc = OBP(exp->exp_obd, quotacheck)(exp->exp_obd, exp, oqctl);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_quotactl(struct obd_export *exp,
 			       struct obd_quotactl *oqctl)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_DT_OP(exp, quotactl);
 	EXP_COUNTER_INCREMENT(exp, quotactl);
 
 	rc = OBP(exp->exp_obd, quotactl)(exp->exp_obd, exp, oqctl);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_health_check(const struct lu_env *env,
@@ -1702,56 +1632,52 @@ static inline int obd_health_check(const struct lu_env *env,
 	 *	 <0 on error
 	 */
 	int rc;
-	ENTRY;
 
 	/* don't use EXP_CHECK_DT_OP, because NULL method is normal here */
 	if (obd == NULL || !OBT(obd)) {
 		CERROR("cleaned up obd\n");
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 	if (!obd->obd_set_up || obd->obd_stopping)
-		RETURN(0);
+		return 0;
 	if (!OBP(obd, health_check))
-		RETURN(0);
+		return 0;
 
 	rc = OBP(obd, health_check)(env, obd);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_register_observer(struct obd_device *obd,
 					struct obd_device *observer)
 {
-	ENTRY;
 	OBD_CHECK_DEV(obd);
 	down_write(&obd->obd_observer_link_sem);
 	if (obd->obd_observer && observer) {
 		up_write(&obd->obd_observer_link_sem);
-		RETURN(-EALREADY);
+		return -EALREADY;
 	}
 	obd->obd_observer = observer;
 	up_write(&obd->obd_observer_link_sem);
-	RETURN(0);
+	return 0;
 }
 
 static inline int obd_pin_observer(struct obd_device *obd,
 				   struct obd_device **observer)
 {
-	ENTRY;
 	down_read(&obd->obd_observer_link_sem);
 	if (!obd->obd_observer) {
 		*observer = NULL;
 		up_read(&obd->obd_observer_link_sem);
-		RETURN(-ENOENT);
+		return -ENOENT;
 	}
 	*observer = obd->obd_observer;
-	RETURN(0);
+	return 0;
 }
 
 static inline int obd_unpin_observer(struct obd_device *obd)
 {
-	ENTRY;
 	up_read(&obd->obd_observer_link_sem);
-	RETURN(0);
+	return 0;
 }
 
 #if 0
@@ -1760,52 +1686,48 @@ static inline int obd_register_page_removal_cb(struct obd_export *exp,
 					       obd_pin_extent_cb pin_cb)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, register_page_removal_cb, 0);
 	OBD_COUNTER_INCREMENT(exp->exp_obd, register_page_removal_cb);
 
 	rc = OBP(exp->exp_obd, register_page_removal_cb)(exp, cb, pin_cb);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_unregister_page_removal_cb(struct obd_export *exp,
 						 obd_page_removal_cb_t cb)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, unregister_page_removal_cb, 0);
 	OBD_COUNTER_INCREMENT(exp->exp_obd, unregister_page_removal_cb);
 
 	rc = OBP(exp->exp_obd, unregister_page_removal_cb)(exp, cb);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_register_lock_cancel_cb(struct obd_export *exp,
 					      obd_lock_cancel_cb cb)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, register_lock_cancel_cb, 0);
 	OBD_COUNTER_INCREMENT(exp->exp_obd, register_lock_cancel_cb);
 
 	rc = OBP(exp->exp_obd, register_lock_cancel_cb)(exp, cb);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int obd_unregister_lock_cancel_cb(struct obd_export *exp,
 						 obd_lock_cancel_cb cb)
 {
 	int rc;
-	ENTRY;
 
 	OBD_CHECK_DT_OP(exp->exp_obd, unregister_lock_cancel_cb, 0);
 	OBD_COUNTER_INCREMENT(exp->exp_obd, unregister_lock_cancel_cb);
 
 	rc = OBP(exp->exp_obd, unregister_lock_cancel_cb)(exp, cb);
-	RETURN(rc);
+	return rc;
 }
 #endif
 
@@ -1814,34 +1736,33 @@ static inline int md_getstatus(struct obd_export *exp,
 			       struct lu_fid *fid, struct obd_capa **pc)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_MD_OP(exp, getstatus);
 	EXP_MD_COUNTER_INCREMENT(exp, getstatus);
 	rc = MDP(exp->exp_obd, getstatus)(exp, fid, pc);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_getattr(struct obd_export *exp, struct md_op_data *op_data,
 			     struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, getattr);
 	EXP_MD_COUNTER_INCREMENT(exp, getattr);
 	rc = MDP(exp->exp_obd, getattr)(exp, op_data, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_null_inode(struct obd_export *exp,
 				   const struct lu_fid *fid)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, null_inode);
 	EXP_MD_COUNTER_INCREMENT(exp, null_inode);
 	rc = MDP(exp->exp_obd, null_inode)(exp, fid);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_find_cbdata(struct obd_export *exp,
@@ -1849,11 +1770,11 @@ static inline int md_find_cbdata(struct obd_export *exp,
 				 ldlm_iterator_t it, void *data)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, find_cbdata);
 	EXP_MD_COUNTER_INCREMENT(exp, find_cbdata);
 	rc = MDP(exp->exp_obd, find_cbdata)(exp, fid, it, data);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_close(struct obd_export *exp, struct md_op_data *op_data,
@@ -1861,11 +1782,11 @@ static inline int md_close(struct obd_export *exp, struct md_op_data *op_data,
 			   struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, close);
 	EXP_MD_COUNTER_INCREMENT(exp, close);
 	rc = MDP(exp->exp_obd, close)(exp, op_data, mod, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_create(struct obd_export *exp, struct md_op_data *op_data,
@@ -1874,12 +1795,12 @@ static inline int md_create(struct obd_export *exp, struct md_op_data *op_data,
 			    struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, create);
 	EXP_MD_COUNTER_INCREMENT(exp, create);
 	rc = MDP(exp->exp_obd, create)(exp, op_data, data, datalen, mode,
 				       uid, gid, cap_effective, rdev, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_done_writing(struct obd_export *exp,
@@ -1887,11 +1808,11 @@ static inline int md_done_writing(struct obd_export *exp,
 				  struct md_open_data *mod)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, done_writing);
 	EXP_MD_COUNTER_INCREMENT(exp, done_writing);
 	rc = MDP(exp->exp_obd, done_writing)(exp, op_data, mod);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_enqueue(struct obd_export *exp,
@@ -1904,12 +1825,12 @@ static inline int md_enqueue(struct obd_export *exp,
 			     int extra_lock_flags)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, enqueue);
 	EXP_MD_COUNTER_INCREMENT(exp, enqueue);
 	rc = MDP(exp->exp_obd, enqueue)(exp, einfo, it, op_data, lockh,
 					lmm, lmmsize, req, extra_lock_flags);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_getattr_name(struct obd_export *exp,
@@ -1917,11 +1838,11 @@ static inline int md_getattr_name(struct obd_export *exp,
 				  struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, getattr_name);
 	EXP_MD_COUNTER_INCREMENT(exp, getattr_name);
 	rc = MDP(exp->exp_obd, getattr_name)(exp, op_data, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_intent_lock(struct obd_export *exp,
@@ -1932,24 +1853,24 @@ static inline int md_intent_lock(struct obd_export *exp,
 				 __u64 extra_lock_flags)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, intent_lock);
 	EXP_MD_COUNTER_INCREMENT(exp, intent_lock);
 	rc = MDP(exp->exp_obd, intent_lock)(exp, op_data, lmm, lmmsize,
 					    it, lookup_flags, reqp, cb_blocking,
 					    extra_lock_flags);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_link(struct obd_export *exp, struct md_op_data *op_data,
 			  struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, link);
 	EXP_MD_COUNTER_INCREMENT(exp, link);
 	rc = MDP(exp->exp_obd, link)(exp, op_data, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data,
@@ -1957,12 +1878,12 @@ static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data,
 			    int newlen, struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, rename);
 	EXP_MD_COUNTER_INCREMENT(exp, rename);
 	rc = MDP(exp->exp_obd, rename)(exp, op_data, old, oldlen, new,
 				       newlen, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_is_subdir(struct obd_export *exp,
@@ -1971,11 +1892,11 @@ static inline int md_is_subdir(struct obd_export *exp,
 			       struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, is_subdir);
 	EXP_MD_COUNTER_INCREMENT(exp, is_subdir);
 	rc = MDP(exp->exp_obd, is_subdir)(exp, pfid, cfid, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data,
@@ -1984,23 +1905,23 @@ static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data,
 			     struct md_open_data **mod)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, setattr);
 	EXP_MD_COUNTER_INCREMENT(exp, setattr);
 	rc = MDP(exp->exp_obd, setattr)(exp, op_data, ea, ealen,
 					ea2, ea2len, request, mod);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_sync(struct obd_export *exp, const struct lu_fid *fid,
 			  struct obd_capa *oc, struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, sync);
 	EXP_MD_COUNTER_INCREMENT(exp, sync);
 	rc = MDP(exp->exp_obd, sync)(exp, fid, oc, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_readpage(struct obd_export *exp, struct md_op_data *opdata,
@@ -2008,22 +1929,22 @@ static inline int md_readpage(struct obd_export *exp, struct md_op_data *opdata,
 			      struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, readpage);
 	EXP_MD_COUNTER_INCREMENT(exp, readpage);
 	rc = MDP(exp->exp_obd, readpage)(exp, opdata, pages, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_unlink(struct obd_export *exp, struct md_op_data *op_data,
 			    struct ptlrpc_request **request)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, unlink);
 	EXP_MD_COUNTER_INCREMENT(exp, unlink);
 	rc = MDP(exp->exp_obd, unlink)(exp, op_data, request);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_get_lustre_md(struct obd_export *exp,
@@ -2032,19 +1953,17 @@ static inline int md_get_lustre_md(struct obd_export *exp,
 				   struct obd_export *md_exp,
 				   struct lustre_md *md)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, get_lustre_md);
 	EXP_MD_COUNTER_INCREMENT(exp, get_lustre_md);
-	RETURN(MDP(exp->exp_obd, get_lustre_md)(exp, req, dt_exp, md_exp, md));
+	return MDP(exp->exp_obd, get_lustre_md)(exp, req, dt_exp, md_exp, md);
 }
 
 static inline int md_free_lustre_md(struct obd_export *exp,
 				    struct lustre_md *md)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, free_lustre_md);
 	EXP_MD_COUNTER_INCREMENT(exp, free_lustre_md);
-	RETURN(MDP(exp->exp_obd, free_lustre_md)(exp, md));
+	return MDP(exp->exp_obd, free_lustre_md)(exp, md);
 }
 
 static inline int md_setxattr(struct obd_export *exp,
@@ -2054,12 +1973,11 @@ static inline int md_setxattr(struct obd_export *exp,
 			      int output_size, int flags, __u32 suppgid,
 			      struct ptlrpc_request **request)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, setxattr);
 	EXP_MD_COUNTER_INCREMENT(exp, setxattr);
-	RETURN(MDP(exp->exp_obd, setxattr)(exp, fid, oc, valid, name, input,
+	return MDP(exp->exp_obd, setxattr)(exp, fid, oc, valid, name, input,
 					   input_size, output_size, flags,
-					   suppgid, request));
+					   suppgid, request);
 }
 
 static inline int md_getxattr(struct obd_export *exp,
@@ -2069,40 +1987,36 @@ static inline int md_getxattr(struct obd_export *exp,
 			      int output_size, int flags,
 			      struct ptlrpc_request **request)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, getxattr);
 	EXP_MD_COUNTER_INCREMENT(exp, getxattr);
-	RETURN(MDP(exp->exp_obd, getxattr)(exp, fid, oc, valid, name, input,
+	return MDP(exp->exp_obd, getxattr)(exp, fid, oc, valid, name, input,
 					   input_size, output_size, flags,
-					   request));
+					   request);
 }
 
 static inline int md_set_open_replay_data(struct obd_export *exp,
 					  struct obd_client_handle *och,
 					  struct ptlrpc_request *open_req)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, set_open_replay_data);
 	EXP_MD_COUNTER_INCREMENT(exp, set_open_replay_data);
-	RETURN(MDP(exp->exp_obd, set_open_replay_data)(exp, och, open_req));
+	return MDP(exp->exp_obd, set_open_replay_data)(exp, och, open_req);
 }
 
 static inline int md_clear_open_replay_data(struct obd_export *exp,
 					    struct obd_client_handle *och)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, clear_open_replay_data);
 	EXP_MD_COUNTER_INCREMENT(exp, clear_open_replay_data);
-	RETURN(MDP(exp->exp_obd, clear_open_replay_data)(exp, och));
+	return MDP(exp->exp_obd, clear_open_replay_data)(exp, och);
 }
 
 static inline int md_set_lock_data(struct obd_export *exp,
 				   __u64 *lockh, void *data, __u64 *bits)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, set_lock_data);
 	EXP_MD_COUNTER_INCREMENT(exp, set_lock_data);
-	RETURN(MDP(exp->exp_obd, set_lock_data)(exp, lockh, data, bits));
+	return MDP(exp->exp_obd, set_lock_data)(exp, lockh, data, bits);
 }
 
 static inline int md_cancel_unused(struct obd_export *exp,
@@ -2113,14 +2027,13 @@ static inline int md_cancel_unused(struct obd_export *exp,
 				   void *opaque)
 {
 	int rc;
-	ENTRY;
 
 	EXP_CHECK_MD_OP(exp, cancel_unused);
 	EXP_MD_COUNTER_INCREMENT(exp, cancel_unused);
 
 	rc = MDP(exp->exp_obd, cancel_unused)(exp, fid, policy, mode,
 					      flags, opaque);
-	RETURN(rc);
+	return rc;
 }
 
 static inline ldlm_mode_t md_lock_match(struct obd_export *exp, __u64 flags,
@@ -2130,21 +2043,19 @@ static inline ldlm_mode_t md_lock_match(struct obd_export *exp, __u64 flags,
 					ldlm_mode_t mode,
 					struct lustre_handle *lockh)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, lock_match);
 	EXP_MD_COUNTER_INCREMENT(exp, lock_match);
-	RETURN(MDP(exp->exp_obd, lock_match)(exp, flags, fid, type,
-					     policy, mode, lockh));
+	return MDP(exp->exp_obd, lock_match)(exp, flags, fid, type,
+					     policy, mode, lockh);
 }
 
 static inline int md_init_ea_size(struct obd_export *exp, int easize,
 				  int def_asize, int cookiesize)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, init_ea_size);
 	EXP_MD_COUNTER_INCREMENT(exp, init_ea_size);
-	RETURN(MDP(exp->exp_obd, init_ea_size)(exp, easize, def_asize,
-					       cookiesize));
+	return MDP(exp->exp_obd, init_ea_size)(exp, easize, def_asize,
+					       cookiesize);
 }
 
 static inline int md_get_remote_perm(struct obd_export *exp,
@@ -2152,22 +2063,21 @@ static inline int md_get_remote_perm(struct obd_export *exp,
 				     struct obd_capa *oc, __u32 suppgid,
 				     struct ptlrpc_request **request)
 {
-	ENTRY;
 	EXP_CHECK_MD_OP(exp, get_remote_perm);
 	EXP_MD_COUNTER_INCREMENT(exp, get_remote_perm);
-	RETURN(MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, suppgid,
-						  request));
+	return MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, suppgid,
+						  request);
 }
 
 static inline int md_renew_capa(struct obd_export *exp, struct obd_capa *ocapa,
 				renew_capa_cb_t cb)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, renew_capa);
 	EXP_MD_COUNTER_INCREMENT(exp, renew_capa);
 	rc = MDP(exp->exp_obd, renew_capa)(exp, ocapa, cb);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_unpack_capa(struct obd_export *exp,
@@ -2176,11 +2086,11 @@ static inline int md_unpack_capa(struct obd_export *exp,
 				 struct obd_capa **oc)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, unpack_capa);
 	EXP_MD_COUNTER_INCREMENT(exp, unpack_capa);
 	rc = MDP(exp->exp_obd, unpack_capa)(exp, req, field, oc);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_intent_getattr_async(struct obd_export *exp,
@@ -2188,11 +2098,11 @@ static inline int md_intent_getattr_async(struct obd_export *exp,
 					  struct ldlm_enqueue_info *einfo)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, intent_getattr_async);
 	EXP_MD_COUNTER_INCREMENT(exp, intent_getattr_async);
 	rc = MDP(exp->exp_obd, intent_getattr_async)(exp, minfo, einfo);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int md_revalidate_lock(struct obd_export *exp,
@@ -2200,11 +2110,11 @@ static inline int md_revalidate_lock(struct obd_export *exp,
 				     struct lu_fid *fid, __u64 *bits)
 {
 	int rc;
-	ENTRY;
+
 	EXP_CHECK_MD_OP(exp, revalidate_lock);
 	EXP_MD_COUNTER_INCREMENT(exp, revalidate_lock);
 	rc = MDP(exp->exp_obd, revalidate_lock)(exp, it, fid, bits);
-	RETURN(rc);
+	return rc;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/include/obd_lov.h b/drivers/staging/lustre/lustre/include/obd_lov.h
index d82f334..235718b 100644
--- a/drivers/staging/lustre/lustre/include/obd_lov.h
+++ b/drivers/staging/lustre/lustre/include/obd_lov.h
@@ -44,16 +44,6 @@ static inline int lov_stripe_md_size(__u16 stripes)
 	return sizeof(struct lov_stripe_md) + stripes*sizeof(struct lov_oinfo*);
 }
 
-static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic)
-{
-	if (lmm_magic == LOV_MAGIC_V3)
-		return sizeof(struct lov_mds_md_v3) +
-			stripes * sizeof(struct lov_ost_data_v1);
-	else
-		return sizeof(struct lov_mds_md_v1) +
-			stripes * sizeof(struct lov_ost_data_v1);
-}
-
 struct lov_version_size {
 	__u32   lvs_magic;
 	size_t  lvs_lmm_size;
diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h
index b5d40af..03e6133 100644
--- a/drivers/staging/lustre/lustre/include/obd_support.h
+++ b/drivers/staging/lustre/lustre/include/obd_support.h
@@ -470,6 +470,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type,
 #define OBD_FAIL_LFSCK_DELAY3		0x1602
 #define OBD_FAIL_LFSCK_LINKEA_CRASH	0x1603
 #define OBD_FAIL_LFSCK_LINKEA_MORE	0x1604
+#define OBD_FAIL_LFSCK_LINKEA_MORE2	0x1605
 #define OBD_FAIL_LFSCK_FATAL1		0x1608
 #define OBD_FAIL_LFSCK_FATAL2		0x1609
 #define OBD_FAIL_LFSCK_CRASH		0x160a
diff --git a/drivers/staging/lustre/lustre/lclient/glimpse.c b/drivers/staging/lustre/lustre/lclient/glimpse.c
index 7f3974b..7bbca4b 100644
--- a/drivers/staging/lustre/lustre/lclient/glimpse.c
+++ b/drivers/staging/lustre/lustre/lclient/glimpse.c
@@ -93,7 +93,6 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
 	struct cl_lock       *lock;
 	int result;
 
-	ENTRY;
 	result = 0;
 	if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) {
 		CDEBUG(D_DLMTRACE, "Glimpsing inode "DFID"\n", PFID(fid));
@@ -131,10 +130,10 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
 			cio->cui_glimpse = 0;
 
 			if (lock == NULL)
-				RETURN(0);
+				return 0;
 
 			if (IS_ERR(lock))
-				RETURN(PTR_ERR(lock));
+				return PTR_ERR(lock);
 
 			LASSERT(agl == 0);
 			result = cl_wait(env, lock);
@@ -159,7 +158,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
 		}
 	}
 
-	RETURN(result);
+	return result;
 }
 
 static int cl_io_get(struct inode *inode, struct lu_env **envout,
@@ -203,8 +202,6 @@ int cl_glimpse_size0(struct inode *inode, int agl)
 	int		     result;
 	int		     refcheck;
 
-	ENTRY;
-
 	result = cl_io_get(inode, &env, &io, &refcheck);
 	if (result > 0) {
 	again:
@@ -226,7 +223,7 @@ int cl_glimpse_size0(struct inode *inode, int agl)
 			goto again;
 		cl_env_put(env, &refcheck);
 	}
-	RETURN(result);
+	return result;
 }
 
 int cl_local_size(struct inode *inode)
@@ -240,14 +237,12 @@ int cl_local_size(struct inode *inode)
 	int		      result;
 	int		      refcheck;
 
-	ENTRY;
-
 	if (!cl_i2info(inode)->lli_has_smd)
-		RETURN(0);
+		return 0;
 
 	result = cl_io_get(inode, &env, &io, &refcheck);
 	if (result <= 0)
-		RETURN(result);
+		return result;
 
 	clob = io->ci_obj;
 	result = cl_io_init(env, io, CIT_MISC, clob);
@@ -270,5 +265,5 @@ int cl_local_size(struct inode *inode)
 	}
 	cl_io_fini(env, io);
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
index 4a01666..8ff38c6 100644
--- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
+++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
@@ -169,7 +169,6 @@ int ccc_device_init(const struct lu_env *env, struct lu_device *d,
 {
 	struct ccc_device  *vdv;
 	int rc;
-	ENTRY;
 
 	vdv = lu2ccc_dev(d);
 	vdv->cdv_next = lu2cl_dev(next);
@@ -182,7 +181,7 @@ int ccc_device_init(const struct lu_env *env, struct lu_device *d,
 		lu_device_get(next);
 		lu_ref_add(&next->ld_reference, "lu-stack", &lu_site_init);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 struct lu_device *ccc_device_fini(const struct lu_env *env,
@@ -201,11 +200,10 @@ struct lu_device *ccc_device_alloc(const struct lu_env *env,
 	struct lu_device  *lud;
 	struct cl_site    *site;
 	int rc;
-	ENTRY;
 
 	OBD_ALLOC_PTR(vdv);
 	if (vdv == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	lud = &vdv->cdv_cl.cd_lu_dev;
 	cl_device_init(&vdv->cdv_cl, t);
@@ -228,7 +226,7 @@ struct lu_device *ccc_device_alloc(const struct lu_env *env,
 		ccc_device_free(env, lud);
 		lud = ERR_PTR(rc);
 	}
-	RETURN(lud);
+	return lud;
 }
 
 struct lu_device *ccc_device_free(const struct lu_env *env,
@@ -418,7 +416,6 @@ int ccc_object_glimpse(const struct lu_env *env,
 {
 	struct inode *inode = ccc_object_inode(obj);
 
-	ENTRY;
 	lvb->lvb_mtime = cl_inode_mtime(inode);
 	lvb->lvb_atime = cl_inode_atime(inode);
 	lvb->lvb_ctime = cl_inode_ctime(inode);
@@ -429,7 +426,7 @@ int ccc_object_glimpse(const struct lu_env *env,
 	 */
 	if (lvb->lvb_size > 0 && lvb->lvb_blocks == 0)
 		lvb->lvb_blocks = dirty_cnt(inode);
-	RETURN(0);
+	return 0;
 }
 
 
@@ -479,8 +476,6 @@ int ccc_page_is_under_lock(const struct lu_env *env,
 
 	int result;
 
-	ENTRY;
-
 	if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE ||
 	    io->ci_type == CIT_FAULT) {
 		if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)
@@ -495,7 +490,7 @@ int ccc_page_is_under_lock(const struct lu_env *env,
 		}
 	} else
 		result = 0;
-	RETURN(result);
+	return result;
 }
 
 int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice)
@@ -559,9 +554,8 @@ int ccc_transient_page_prep(const struct lu_env *env,
 				   const struct cl_page_slice *slice,
 				   struct cl_io *unused)
 {
-	ENTRY;
 	/* transient page should always be sent. */
-	RETURN(0);
+	return 0;
 }
 
 /*****************************************************************************
@@ -623,7 +617,6 @@ int ccc_lock_fits_into(const struct lu_env *env,
 	const struct ccc_io	*cio   = ccc_env_io(env);
 	int			 result;
 
-	ENTRY;
 	/*
 	 * Work around DLM peculiarity: it assumes that glimpse
 	 * (LDLM_FL_HAS_INTENT) lock is always LCK_PR, and returns reads lock
@@ -642,7 +635,7 @@ int ccc_lock_fits_into(const struct lu_env *env,
 		result = lock->cll_state >= CLS_ENQUEUED;
 	else
 		result = 1;
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -655,7 +648,6 @@ void ccc_lock_state(const struct lu_env *env,
 		    enum cl_lock_state state)
 {
 	struct cl_lock *lock = slice->cls_lock;
-	ENTRY;
 
 	/*
 	 * Refresh inode attributes when the lock is moving into CLS_HELD
@@ -682,7 +674,6 @@ void ccc_lock_state(const struct lu_env *env,
 		    lock->cll_descr.cld_end == CL_PAGE_EOF)
 			cl_merge_lvb(env, inode);
 	}
-	EXIT;
 }
 
 /*****************************************************************************
@@ -707,7 +698,6 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io,
 	struct cl_object       *obj   = io->ci_obj;
 
 	CLOBINVRNT(env, obj, ccc_object_invariant(obj));
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end);
 
@@ -725,7 +715,7 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io,
 	descr->cld_enq_flags = enqflags;
 
 	cl_io_lock_add(env, io, &cio->cui_link);
-	RETURN(0);
+	return 0;
 }
 
 void ccc_io_update_iov(const struct lu_env *env,
@@ -986,11 +976,9 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr,
 	int	    result;
 	int	    refcheck;
 
-	ENTRY;
-
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	io = ccc_env_thread_io(env);
 	io->ci_obj = cl_i2info(inode)->lli_clob;
@@ -1019,7 +1007,7 @@ again:
 	if (unlikely(io->ci_need_restart))
 		goto again;
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
 
 /*****************************************************************************
@@ -1166,7 +1154,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md)
 			 * locked by I_NEW bit.
 			 */
 			lli->lli_clob = clob;
-			lli->lli_has_smd = md->lsm != NULL;
+			lli->lli_has_smd = lsm_has_objects(md->lsm);
 			lu_object_ref_add(&clob->co_lu, "inode", inode);
 		} else
 			result = PTR_ERR(clob);
@@ -1284,9 +1272,9 @@ __u16 ll_dirent_type_get(struct lu_dirent *ent)
 __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32)
 {
 	if (BITS_PER_LONG == 32 || api32)
-		RETURN(fid_flatten32(fid));
+		return fid_flatten32(fid);
 	else
-		RETURN(fid_flatten(fid));
+		return fid_flatten(fid);
 }
 
 /**
@@ -1295,15 +1283,14 @@ __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32)
 __u32 cl_fid_build_gen(const struct lu_fid *fid)
 {
 	__u32 gen;
-	ENTRY;
 
 	if (fid_is_igif(fid)) {
 		gen = lu_igif_gen(fid);
-		RETURN(gen);
+		return gen;
 	}
 
 	gen = (fid_flatten(fid) >> 32);
-	RETURN(gen);
+	return gen;
 }
 
 /* lsm is unreliable after hsm implementation as layout can be changed at
diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c b/drivers/staging/lustre/lustre/lclient/lcommon_misc.c
index 8ecbef9..2b4dbee 100644
--- a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c
+++ b/drivers/staging/lustre/lustre/lclient/lcommon_misc.c
@@ -57,12 +57,11 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp)
 	int rc, easize, def_easize, cookiesize;
 	struct lov_desc desc;
 	__u16 stripes;
-	ENTRY;
 
 	rc = obd_get_info(NULL, dt_exp, sizeof(KEY_LOVDESC), KEY_LOVDESC,
 			  &valsize, &desc, NULL);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	stripes = min(desc.ld_tgt_count, (__u32)LOV_MAX_STRIPE_COUNT);
 	lsm.lsm_stripe_count = stripes;
@@ -77,7 +76,7 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp)
 	       easize, cookiesize);
 
 	rc = md_init_ea_size(md_exp, easize, def_easize, cookiesize);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -95,7 +94,6 @@ int cl_ocd_update(struct obd_device *host,
 	__u64 flags;
 	int   result;
 
-	ENTRY;
 	if (!strcmp(watched->obd_type->typ_name, LUSTRE_OSC_NAME)) {
 		cli = &watched->u.cli;
 		lco = owner;
@@ -116,7 +114,7 @@ int cl_ocd_update(struct obd_device *host,
 		       watched->obd_name);
 		result = -EINVAL;
 	}
-	RETURN(result);
+	return result;
 }
 
 #define GROUPLOCK_SCOPE "grouplock"
diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c
index ce90c7e..c65b13c 100644
--- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c
+++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c
@@ -133,53 +133,45 @@ for (node = interval_last(root); node != NULL;	  \
 
 static struct interval_node *interval_first(struct interval_node *node)
 {
-	ENTRY;
-
 	if (!node)
-		RETURN(NULL);
+		return NULL;
 	while (node->in_left)
 		node = node->in_left;
-	RETURN(node);
+	return node;
 }
 
 static struct interval_node *interval_last(struct interval_node *node)
 {
-	ENTRY;
-
 	if (!node)
-		RETURN(NULL);
+		return NULL;
 	while (node->in_right)
 		node = node->in_right;
-	RETURN(node);
+	return node;
 }
 
 static struct interval_node *interval_next(struct interval_node *node)
 {
-	ENTRY;
-
 	if (!node)
-		RETURN(NULL);
+		return NULL;
 	if (node->in_right)
-		RETURN(interval_first(node->in_right));
+		return interval_first(node->in_right);
 	while (node->in_parent && node_is_right_child(node))
 		node = node->in_parent;
-	RETURN(node->in_parent);
+	return node->in_parent;
 }
 
 static struct interval_node *interval_prev(struct interval_node *node)
 {
-	ENTRY;
-
 	if (!node)
-		RETURN(NULL);
+		return NULL;
 
 	if (node->in_left)
-		RETURN(interval_last(node->in_left));
+		return interval_last(node->in_left);
 
 	while (node->in_parent && node_is_left_child(node))
 		node = node->in_parent;
 
-	RETURN(node->in_parent);
+	return node->in_parent;
 }
 
 enum interval_iter interval_iterate(struct interval_node *root,
@@ -188,7 +180,6 @@ enum interval_iter interval_iterate(struct interval_node *root,
 {
 	struct interval_node *node;
 	enum interval_iter rc = INTERVAL_ITER_CONT;
-	ENTRY;
 
 	interval_for_each(node, root) {
 		rc = func(node, data);
@@ -196,7 +187,7 @@ enum interval_iter interval_iterate(struct interval_node *root,
 			break;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(interval_iterate);
 
@@ -206,7 +197,6 @@ enum interval_iter interval_iterate_reverse(struct interval_node *root,
 {
 	struct interval_node *node;
 	enum interval_iter rc = INTERVAL_ITER_CONT;
-	ENTRY;
 
 	interval_for_each_reverse(node, root) {
 		rc = func(node, data);
@@ -214,7 +204,7 @@ enum interval_iter interval_iterate_reverse(struct interval_node *root,
 			break;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(interval_iterate_reverse);
 
@@ -225,7 +215,6 @@ struct interval_node *interval_find(struct interval_node *root,
 {
 	struct interval_node *walk = root;
 	int rc;
-	ENTRY;
 
 	while (walk) {
 		rc = extent_compare(ex, &walk->in_extent);
@@ -237,7 +226,7 @@ struct interval_node *interval_find(struct interval_node *root,
 			walk = walk->in_right;
 	}
 
-	RETURN(walk);
+	return walk;
 }
 EXPORT_SYMBOL(interval_find);
 
@@ -326,7 +315,6 @@ static void interval_insert_color(struct interval_node *node,
 				  struct interval_node **root)
 {
 	struct interval_node *parent, *gparent;
-	ENTRY;
 
 	while ((parent = node->in_parent) && node_is_red(parent)) {
 		gparent = parent->in_parent;
@@ -373,7 +361,6 @@ static void interval_insert_color(struct interval_node *node,
 	}
 
 	(*root)->in_color = INTERVAL_BLACK;
-	EXIT;
 }
 
 struct interval_node *interval_insert(struct interval_node *node,
@@ -381,14 +368,13 @@ struct interval_node *interval_insert(struct interval_node *node,
 
 {
 	struct interval_node **p, *parent = NULL;
-	ENTRY;
 
 	LASSERT(!interval_is_intree(node));
 	p = root;
 	while (*p) {
 		parent = *p;
 		if (node_equal(parent, node))
-			RETURN(parent);
+			return parent;
 
 		/* max_high field must be updated after each iteration */
 		if (parent->in_max_high < interval_high(node))
@@ -409,7 +395,7 @@ struct interval_node *interval_insert(struct interval_node *node,
 	interval_insert_color(node, root);
 	node->in_intree = 1;
 
-	RETURN(NULL);
+	return NULL;
 }
 EXPORT_SYMBOL(interval_insert);
 
@@ -423,7 +409,6 @@ static void interval_erase_color(struct interval_node *node,
 				 struct interval_node **root)
 {
 	struct interval_node *tmp;
-	ENTRY;
 
 	while (node_is_black_or_0(node) && node != *root) {
 		if (parent->in_left == node) {
@@ -490,7 +475,6 @@ static void interval_erase_color(struct interval_node *node,
 	}
 	if (node)
 		node->in_color = INTERVAL_BLACK;
-	EXIT;
 }
 
 /*
@@ -501,7 +485,6 @@ static void update_maxhigh(struct interval_node *node,
 			   __u64  old_maxhigh)
 {
 	__u64 left_max, right_max;
-	ENTRY;
 
 	while (node) {
 		left_max = node->in_left ? node->in_left->in_max_high : 0;
@@ -513,7 +496,6 @@ static void update_maxhigh(struct interval_node *node,
 			break;
 		node = node->in_parent;
 	}
-	EXIT;
 }
 
 void interval_erase(struct interval_node *node,
@@ -521,7 +503,6 @@ void interval_erase(struct interval_node *node,
 {
 	struct interval_node *child, *parent;
 	int color;
-	ENTRY;
 
 	LASSERT(interval_is_intree(node));
 	node->in_intree = 0;
@@ -586,7 +567,6 @@ void interval_erase(struct interval_node *node,
 color:
 	if (color == INTERVAL_BLACK)
 		interval_erase_color(child, parent, root);
-	EXIT;
 }
 EXPORT_SYMBOL(interval_erase);
 
diff --git a/drivers/staging/lustre/lustre/ldlm/l_lock.c b/drivers/staging/lustre/lustre/ldlm/l_lock.c
index 853409a..32f4d52 100644
--- a/drivers/staging/lustre/lustre/ldlm/l_lock.c
+++ b/drivers/staging/lustre/lustre/ldlm/l_lock.c
@@ -51,12 +51,12 @@
 struct ldlm_resource *lock_res_and_lock(struct ldlm_lock *lock)
 {
 	/* on server-side resource of lock doesn't change */
-	if (!lock->l_ns_srv)
+	if ((lock->l_flags & LDLM_FL_NS_SRV) == 0)
 		spin_lock(&lock->l_lock);
 
 	lock_res(lock->l_resource);
 
-	lock->l_res_locked = 1;
+	lock->l_flags |= LDLM_FL_RES_LOCKED;
 	return lock->l_resource;
 }
 EXPORT_SYMBOL(lock_res_and_lock);
@@ -67,10 +67,10 @@ EXPORT_SYMBOL(lock_res_and_lock);
 void unlock_res_and_lock(struct ldlm_lock *lock)
 {
 	/* on server-side resource of lock doesn't change */
-	lock->l_res_locked = 0;
+	lock->l_flags &= ~LDLM_FL_RES_LOCKED;
 
 	unlock_res(lock->l_resource);
-	if (!lock->l_ns_srv)
+	if ((lock->l_flags & LDLM_FL_NS_SRV) == 0)
 		spin_unlock(&lock->l_lock);
 }
 EXPORT_SYMBOL(unlock_res_and_lock);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
index f7432f7..7e31663 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
@@ -72,7 +72,6 @@ __u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms)
 	struct list_head *tmp;
 	struct ldlm_lock *lck;
 	__u64 kms = 0;
-	ENTRY;
 
 	/* don't let another thread in ldlm_extent_shift_kms race in
 	 * just after we finish and take our lock into account in its
@@ -86,7 +85,7 @@ __u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms)
 			continue;
 
 		if (lck->l_policy_data.l_extent.end >= old_kms)
-			RETURN(old_kms);
+			return old_kms;
 
 		/* This extent _has_ to be smaller than old_kms (checked above)
 		 * so kms can only ever be smaller or the same as old_kms. */
@@ -95,7 +94,7 @@ __u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms)
 	}
 	LASSERTF(kms <= old_kms, "kms "LPU64" old_kms "LPU64"\n", kms, old_kms);
 
-	RETURN(kms);
+	return kms;
 }
 EXPORT_SYMBOL(ldlm_extent_shift_kms);
 
@@ -103,16 +102,15 @@ struct kmem_cache *ldlm_interval_slab;
 struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock)
 {
 	struct ldlm_interval *node;
-	ENTRY;
 
 	LASSERT(lock->l_resource->lr_type == LDLM_EXTENT);
 	OBD_SLAB_ALLOC_PTR_GFP(node, ldlm_interval_slab, __GFP_IO);
 	if (node == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	INIT_LIST_HEAD(&node->li_group);
 	ldlm_interval_attach(node, lock);
-	RETURN(node);
+	return node;
 }
 
 void ldlm_interval_free(struct ldlm_interval *node)
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
index f100a84..c68ed27 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
@@ -142,8 +142,6 @@ static inline void ldlm_flock_blocking_unlink(struct ldlm_lock *req)
 static inline void
 ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, __u64 flags)
 {
-	ENTRY;
-
 	LDLM_DEBUG(lock, "ldlm_flock_destroy(mode: %d, flags: 0x%llx)",
 		   mode, flags);
 
@@ -162,7 +160,6 @@ ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, __u64 flags)
 	}
 
 	ldlm_lock_destroy_nolock(lock);
-	EXIT;
 }
 
 /**
@@ -198,6 +195,7 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock)
 		if (lock == NULL)
 			break;
 
+		LASSERT(req != lock);
 		flock = &lock->l_policy_data.l_flock;
 		LASSERT(flock->owner == bl_owner);
 		bl_owner = flock->blocking_owner;
@@ -253,7 +251,6 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq,
 	int splitted = 0;
 	const struct ldlm_callback_suite null_cbs = { NULL };
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_DLMTRACE, "flags %#llx owner "LPU64" pid %u mode %u start "
 	       LPU64" end "LPU64"\n", *flags,
@@ -308,12 +305,12 @@ reprocess:
 				continue;
 
 			if (!first_enq)
-				RETURN(LDLM_ITER_CONTINUE);
+				return LDLM_ITER_CONTINUE;
 
 			if (*flags & LDLM_FL_BLOCK_NOWAIT) {
 				ldlm_flock_destroy(req, mode, *flags);
 				*err = -EAGAIN;
-				RETURN(LDLM_ITER_STOP);
+				return LDLM_ITER_STOP;
 			}
 
 			if (*flags & LDLM_FL_TEST_LOCK) {
@@ -326,24 +323,27 @@ reprocess:
 				req->l_policy_data.l_flock.end =
 					lock->l_policy_data.l_flock.end;
 				*flags |= LDLM_FL_LOCK_CHANGED;
-				RETURN(LDLM_ITER_STOP);
-			}
-
-			if (ldlm_flock_deadlock(req, lock)) {
-				ldlm_flock_destroy(req, mode, *flags);
-				*err = -EDEADLK;
-				RETURN(LDLM_ITER_STOP);
+				return LDLM_ITER_STOP;
 			}
 
+			/* add lock to blocking list before deadlock
+			 * check to prevent race */
 			rc = ldlm_flock_blocking_link(req, lock);
 			if (rc) {
 				ldlm_flock_destroy(req, mode, *flags);
 				*err = rc;
-				RETURN(LDLM_ITER_STOP);
+				return LDLM_ITER_STOP;
+			}
+			if (ldlm_flock_deadlock(req, lock)) {
+				ldlm_flock_blocking_unlink(req);
+				ldlm_flock_destroy(req, mode, *flags);
+				*err = -EDEADLK;
+				return LDLM_ITER_STOP;
 			}
+
 			ldlm_resource_add_lock(res, &res->lr_waiting, req);
 			*flags |= LDLM_FL_BLOCK_GRANTED;
-			RETURN(LDLM_ITER_STOP);
+			return LDLM_ITER_STOP;
 		}
 	}
 
@@ -351,7 +351,7 @@ reprocess:
 		ldlm_flock_destroy(req, mode, *flags);
 		req->l_req_mode = LCK_NL;
 		*flags |= LDLM_FL_LOCK_CHANGED;
-		RETURN(LDLM_ITER_STOP);
+		return LDLM_ITER_STOP;
 	}
 
 	/* In case we had slept on this lock request take it off of the
@@ -463,7 +463,7 @@ reprocess:
 				ldlm_flock_destroy(req, lock->l_granted_mode,
 						   *flags);
 				*err = -ENOLCK;
-				RETURN(LDLM_ITER_STOP);
+				return LDLM_ITER_STOP;
 			}
 			goto reprocess;
 		}
@@ -530,7 +530,7 @@ reprocess:
 		ldlm_flock_destroy(req, mode, *flags);
 
 	ldlm_resource_dump(D_INFO, res);
-	RETURN(LDLM_ITER_CONTINUE);
+	return LDLM_ITER_CONTINUE;
 }
 
 struct ldlm_flock_wait_data {
@@ -542,7 +542,6 @@ static void
 ldlm_flock_interrupted_wait(void *data)
 {
 	struct ldlm_lock *lock;
-	ENTRY;
 
 	lock = ((struct ldlm_flock_wait_data *)data)->fwd_lock;
 
@@ -553,8 +552,6 @@ ldlm_flock_interrupted_wait(void *data)
 	/* client side - set flag to prevent lock from being put on LRU list */
 	lock->l_flags |= LDLM_FL_CBPENDING;
 	unlock_res_and_lock(lock);
-
-	EXIT;
 }
 
 /**
@@ -577,7 +574,6 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
 	struct l_wait_info	      lwi;
 	ldlm_error_t		    err;
 	int			     rc = 0;
-	ENTRY;
 
 	CDEBUG(D_DLMTRACE, "flags: 0x%llx data: %p getlk: %p\n",
 	       flags, data, getlk);
@@ -595,7 +591,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
 
 		/* Need to wake up the waiter if we were evicted */
 		wake_up(&lock->l_waitq);
-		RETURN(0);
+		return 0;
 	}
 
 	LASSERT(flags != LDLM_FL_WAIT_NOREPROC);
@@ -607,7 +603,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
 			goto granted;
 		/* CP AST RPC: lock get granted, wake it up */
 		wake_up(&lock->l_waitq);
-		RETURN(0);
+		return 0;
 	}
 
 	LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, "
@@ -633,26 +629,26 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
 	if (rc) {
 		LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)",
 			   rc);
-		RETURN(rc);
+		return rc;
 	}
 
 granted:
 	OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT, 10);
 
-	if (lock->l_destroyed) {
+	if (lock->l_flags & LDLM_FL_DESTROYED) {
 		LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed");
-		RETURN(0);
+		return 0;
 	}
 
 	if (lock->l_flags & LDLM_FL_FAILED) {
 		LDLM_DEBUG(lock, "client-side enqueue waking up: failed");
-		RETURN(-EIO);
+		return -EIO;
 	}
 
 	if (rc) {
 		LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)",
 			   rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	LDLM_DEBUG(lock, "client-side enqueue granted");
@@ -694,15 +690,13 @@ granted:
 		ldlm_process_flock_lock(lock, &noreproc, 1, &err, NULL);
 	}
 	unlock_res_and_lock(lock);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_flock_completion_ast);
 
 int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 			    void *data, int flag)
 {
-	ENTRY;
-
 	LASSERT(lock);
 	LASSERT(flag == LDLM_CB_CANCELING);
 
@@ -710,7 +704,7 @@ int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 	lock_res_and_lock(lock);
 	ldlm_flock_blocking_unlink(lock);
 	unlock_res_and_lock(lock);
-	RETURN(0);
+	return 0;
 }
 
 void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy,
@@ -831,19 +825,17 @@ int ldlm_init_flock_export(struct obd_export *exp)
 				&ldlm_export_flock_ops,
 				CFS_HASH_DEFAULT | CFS_HASH_NBLK_CHANGE);
 	if (!exp->exp_flock_hash)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_init_flock_export);
 
 void ldlm_destroy_flock_export(struct obd_export *exp)
 {
-	ENTRY;
 	if (exp->exp_flock_hash) {
 		cfs_hash_putref(exp->exp_flock_hash);
 		exp->exp_flock_hash = NULL;
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_destroy_flock_export);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
index 141a957..8cd7963 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
@@ -36,23 +36,46 @@
 
 #define MAX_STRING_SIZE 128
 
-extern atomic_t ldlm_srv_namespace_nr;
-extern atomic_t ldlm_cli_namespace_nr;
+extern int ldlm_srv_namespace_nr;
+extern int ldlm_cli_namespace_nr;
 extern struct mutex ldlm_srv_namespace_lock;
 extern struct list_head ldlm_srv_namespace_list;
 extern struct mutex ldlm_cli_namespace_lock;
-extern struct list_head ldlm_cli_namespace_list;
+extern struct list_head ldlm_cli_active_namespace_list;
+extern struct list_head ldlm_cli_inactive_namespace_list;
 
-static inline atomic_t *ldlm_namespace_nr(ldlm_side_t client)
+static inline int ldlm_namespace_nr_read(ldlm_side_t client)
 {
 	return client == LDLM_NAMESPACE_SERVER ?
-		&ldlm_srv_namespace_nr : &ldlm_cli_namespace_nr;
+		ldlm_srv_namespace_nr : ldlm_cli_namespace_nr;
+}
+
+static inline void ldlm_namespace_nr_inc(ldlm_side_t client)
+{
+	if (client == LDLM_NAMESPACE_SERVER)
+		ldlm_srv_namespace_nr++;
+	else
+		ldlm_cli_namespace_nr++;
+}
+
+static inline void ldlm_namespace_nr_dec(ldlm_side_t client)
+{
+	if (client == LDLM_NAMESPACE_SERVER)
+		ldlm_srv_namespace_nr--;
+	else
+		ldlm_cli_namespace_nr--;
 }
 
 static inline struct list_head *ldlm_namespace_list(ldlm_side_t client)
 {
 	return client == LDLM_NAMESPACE_SERVER ?
-		&ldlm_srv_namespace_list : &ldlm_cli_namespace_list;
+		&ldlm_srv_namespace_list : &ldlm_cli_active_namespace_list;
+}
+
+static inline struct list_head *ldlm_namespace_inactive_list(ldlm_side_t client)
+{
+	return client == LDLM_NAMESPACE_SERVER ?
+		&ldlm_srv_namespace_list : &ldlm_cli_inactive_namespace_list;
 }
 
 static inline struct mutex *ldlm_namespace_lock(ldlm_side_t client)
@@ -61,6 +84,16 @@ static inline struct mutex *ldlm_namespace_lock(ldlm_side_t client)
 		&ldlm_srv_namespace_lock : &ldlm_cli_namespace_lock;
 }
 
+/* ns_bref is the number of resources in this namespace */
+static inline int ldlm_ns_empty(struct ldlm_namespace *ns)
+{
+	return atomic_read(&ns->ns_bref) == 0;
+}
+
+void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *, ldlm_side_t);
+void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *, ldlm_side_t);
+struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t);
+
 /* ldlm_request.c */
 /* Cancel lru flag, it indicates we cancel aged locks. */
 enum {
@@ -159,8 +192,8 @@ void ldlm_destroy_flock_export(struct obd_export *exp);
 void l_check_ns_lock(struct ldlm_namespace *ns);
 void l_check_no_ns_lock(struct ldlm_namespace *ns);
 
-extern proc_dir_entry_t *ldlm_svc_proc_dir;
-extern proc_dir_entry_t *ldlm_type_proc_dir;
+extern struct proc_dir_entry *ldlm_svc_proc_dir;
+extern struct proc_dir_entry *ldlm_type_proc_dir;
 
 struct ldlm_state {
 	struct ptlrpc_service *ldlm_cb_service;
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
index 42df530..1a8c0d7 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
@@ -60,17 +60,16 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid,
 	struct ptlrpc_connection *ptlrpc_conn;
 	struct obd_import_conn *imp_conn = NULL, *item;
 	int rc = 0;
-	ENTRY;
 
 	if (!create && !priority) {
 		CDEBUG(D_HA, "Nothing to do\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	ptlrpc_conn = ptlrpc_uuid_to_connection(uuid);
 	if (!ptlrpc_conn) {
 		CDEBUG(D_HA, "can't find connection %s\n", uuid->uuid);
-		RETURN (-ENOENT);
+		return -ENOENT;
 	}
 
 	if (create) {
@@ -115,13 +114,13 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid,
 	}
 
 	spin_unlock(&imp->imp_lock);
-	RETURN(0);
+	return 0;
 out_free:
 	if (imp_conn)
 		OBD_FREE(imp_conn, sizeof(*imp_conn));
 out_put:
 	ptlrpc_connection_put(ptlrpc_conn);
-	RETURN(rc);
+	return rc;
 }
 
 int import_set_conn_priority(struct obd_import *imp, struct obd_uuid *uuid)
@@ -141,7 +140,6 @@ int client_import_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
 	struct obd_import_conn *imp_conn;
 	struct obd_export *dlmexp;
 	int rc = -ENOENT;
-	ENTRY;
 
 	spin_lock(&imp->imp_lock);
 	if (list_empty(&imp->imp_conn_list)) {
@@ -187,7 +185,7 @@ out:
 	spin_unlock(&imp->imp_lock);
 	if (rc == -ENOENT)
 		CERROR("connection %s not found\n", uuid->uuid);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(client_import_del_conn);
 
@@ -200,7 +198,6 @@ int client_import_find_conn(struct obd_import *imp, lnet_nid_t peer,
 {
 	struct obd_import_conn *conn;
 	int rc = -ENOENT;
-	ENTRY;
 
 	spin_lock(&imp->imp_lock);
 	list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
@@ -212,7 +209,7 @@ int client_import_find_conn(struct obd_import *imp, lnet_nid_t peer,
 		}
 	}
 	spin_unlock(&imp->imp_lock);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(client_import_find_conn);
 
@@ -267,7 +264,6 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 	ldlm_ns_type_t ns_type = LDLM_NS_TYPE_UNKNOWN;
 	int rc;
 	char	*cli_name = lustre_cfg_buf(lcfg, 0);
-	ENTRY;
 
 	/* In a more perfect world, we would hang a ptlrpc_client off of
 	 * obd_type and just use the values from there. */
@@ -305,27 +301,27 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 	} else {
 		CERROR("unknown client OBD type \"%s\", can't setup\n",
 		       name);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
 		CERROR("requires a TARGET UUID\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 1) > 37) {
 		CERROR("client UUID must be less than 38 characters\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 2) < 1) {
 		CERROR("setup requires a SERVER UUID\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 2) > 37) {
 		CERROR("target UUID must be less than 38 characters\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	init_rwsem(&cli->cl_sem);
@@ -339,8 +335,8 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 	cli->cl_avail_grant = 0;
 	/* FIXME: Should limit this for the sum of all cl_dirty_max. */
 	cli->cl_dirty_max = OSC_MAX_DIRTY_DEFAULT * 1024 * 1024;
-	if (cli->cl_dirty_max >> PAGE_CACHE_SHIFT > num_physpages / 8)
-		cli->cl_dirty_max = num_physpages << (PAGE_CACHE_SHIFT - 3);
+	if (cli->cl_dirty_max >> PAGE_CACHE_SHIFT > totalram_pages / 8)
+		cli->cl_dirty_max = totalram_pages << (PAGE_CACHE_SHIFT - 3);
 	INIT_LIST_HEAD(&cli->cl_cache_waiters);
 	INIT_LIST_HEAD(&cli->cl_loi_ready_list);
 	INIT_LIST_HEAD(&cli->cl_loi_hp_ready_list);
@@ -388,11 +384,11 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 
 	if (!strcmp(name, LUSTRE_MDC_NAME)) {
 		cli->cl_max_rpcs_in_flight = MDC_MAX_RIF_DEFAULT;
-	} else if (num_physpages >> (20 - PAGE_CACHE_SHIFT) <= 128 /* MB */) {
+	} else if (totalram_pages >> (20 - PAGE_CACHE_SHIFT) <= 128 /* MB */) {
 		cli->cl_max_rpcs_in_flight = 2;
-	} else if (num_physpages >> (20 - PAGE_CACHE_SHIFT) <= 256 /* MB */) {
+	} else if (totalram_pages >> (20 - PAGE_CACHE_SHIFT) <= 256 /* MB */) {
 		cli->cl_max_rpcs_in_flight = 3;
-	} else if (num_physpages >> (20 - PAGE_CACHE_SHIFT) <= 512 /* MB */) {
+	} else if (totalram_pages >> (20 - PAGE_CACHE_SHIFT) <= 512 /* MB */) {
 		cli->cl_max_rpcs_in_flight = 4;
 	} else {
 		if (osc_on_mdt(obddev->obd_name))
@@ -452,29 +448,27 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 
 	cli->cl_qchk_stat = CL_NOT_QUOTACHECKED;
 
-	RETURN(rc);
+	return rc;
 
 err_import:
 	class_destroy_import(imp);
 err_ldlm:
 	ldlm_put_ref();
 err:
-	RETURN(rc);
+	return rc;
 
 }
 EXPORT_SYMBOL(client_obd_setup);
 
 int client_obd_cleanup(struct obd_device *obddev)
 {
-	ENTRY;
-
 	ldlm_namespace_free_post(obddev->obd_namespace);
 	obddev->obd_namespace = NULL;
 
 	LASSERT(obddev->u.cli.cl_import == NULL);
 
 	ldlm_put_ref();
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(client_obd_cleanup);
 
@@ -489,7 +483,6 @@ int client_connect_import(const struct lu_env *env,
 	struct obd_connect_data *ocd;
 	struct lustre_handle    conn    = { 0 };
 	int		     rc;
-	ENTRY;
 
 	*exp = NULL;
 	down_write(&cli->cl_sem);
@@ -532,8 +525,6 @@ int client_connect_import(const struct lu_env *env,
 
 	ptlrpc_pinger_add_import(imp);
 
-	EXIT;
-
 	if (rc) {
 out_ldlm:
 		cli->cl_conn_count--;
@@ -553,12 +544,11 @@ int client_disconnect_export(struct obd_export *exp)
 	struct client_obd *cli;
 	struct obd_import *imp;
 	int rc = 0, err;
-	ENTRY;
 
 	if (!obd) {
 		CERROR("invalid export for disconnect: exp %p cookie "LPX64"\n",
 		       exp, exp ? exp->exp_handle.h_cookie : -1);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	cli = &obd->u.cli;
@@ -605,8 +595,6 @@ int client_disconnect_export(struct obd_export *exp)
 
 	ptlrpc_invalidate_import(imp);
 
-	EXIT;
-
 out_disconnect:
 	/* Use server style - class_disconnect should be always called for
 	 * o_disconnect. */
@@ -616,7 +604,7 @@ out_disconnect:
 
 	up_write(&cli->cl_sem);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(client_disconnect_export);
 
@@ -627,7 +615,6 @@ EXPORT_SYMBOL(client_disconnect_export);
 int target_pack_pool_reply(struct ptlrpc_request *req)
 {
 	struct obd_device *obd;
-	ENTRY;
 
 	/* Check that we still have all structures alive as this may
 	 * be some late RPC at shutdown time. */
@@ -635,7 +622,7 @@ int target_pack_pool_reply(struct ptlrpc_request *req)
 		     !exp_connect_lru_resize(req->rq_export))) {
 		lustre_msg_set_slv(req->rq_repmsg, 0);
 		lustre_msg_set_limit(req->rq_repmsg, 0);
-		RETURN(0);
+		return 0;
 	}
 
 	/* OBD is alive here as export is alive, which we checked above. */
@@ -646,7 +633,7 @@ int target_pack_pool_reply(struct ptlrpc_request *req)
 	lustre_msg_set_limit(req->rq_repmsg, obd->obd_pool_limit);
 	read_unlock(&obd->obd_pool_lock);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(target_pack_pool_reply);
 
@@ -674,10 +661,8 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
 	int			netrc;
 	struct ptlrpc_reply_state *rs;
 	struct obd_export	 *exp;
-	ENTRY;
 
 	if (req->rq_no_reply) {
-		EXIT;
 		return;
 	}
 
@@ -686,7 +671,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
 	if (rs == NULL || !rs->rs_difficult) {
 		/* no notifiers */
 		target_send_reply_msg (req, rc, fail_id);
-		EXIT;
 		return;
 	}
 
@@ -757,19 +741,18 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id)
 	}
 	spin_unlock(&rs->rs_lock);
 	spin_unlock(&svcpt->scp_rep_lock);
-	EXIT;
 }
 EXPORT_SYMBOL(target_send_reply);
 
 ldlm_mode_t lck_compat_array[] = {
-	[LCK_EX] LCK_COMPAT_EX,
-	[LCK_PW] LCK_COMPAT_PW,
-	[LCK_PR] LCK_COMPAT_PR,
-	[LCK_CW] LCK_COMPAT_CW,
-	[LCK_CR] LCK_COMPAT_CR,
-	[LCK_NL] LCK_COMPAT_NL,
-	[LCK_GROUP] LCK_COMPAT_GROUP,
-	[LCK_COS] LCK_COMPAT_COS,
+	[LCK_EX]	= LCK_COMPAT_EX,
+	[LCK_PW]	= LCK_COMPAT_PW,
+	[LCK_PR]	= LCK_COMPAT_PR,
+	[LCK_CW]	= LCK_COMPAT_CW,
+	[LCK_CR]	= LCK_COMPAT_CR,
+	[LCK_NL]	= LCK_COMPAT_NL,
+	[LCK_GROUP]	= LCK_COMPAT_GROUP,
+	[LCK_COS]	= LCK_COMPAT_COS,
 };
 
 /**
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
index 33b76a1..6133b3f 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
@@ -49,45 +49,45 @@
 
 /* lock types */
 char *ldlm_lockname[] = {
-	[0] "--",
-	[LCK_EX] "EX",
-	[LCK_PW] "PW",
-	[LCK_PR] "PR",
-	[LCK_CW] "CW",
-	[LCK_CR] "CR",
-	[LCK_NL] "NL",
-	[LCK_GROUP] "GROUP",
-	[LCK_COS] "COS"
+	[0]		= "--",
+	[LCK_EX]	= "EX",
+	[LCK_PW]	= "PW",
+	[LCK_PR]	= "PR",
+	[LCK_CW]	= "CW",
+	[LCK_CR]	= "CR",
+	[LCK_NL]	= "NL",
+	[LCK_GROUP]	= "GROUP",
+	[LCK_COS]	= "COS",
 };
 EXPORT_SYMBOL(ldlm_lockname);
 
 char *ldlm_typename[] = {
-	[LDLM_PLAIN] "PLN",
-	[LDLM_EXTENT] "EXT",
-	[LDLM_FLOCK] "FLK",
-	[LDLM_IBITS] "IBT",
+	[LDLM_PLAIN]	= "PLN",
+	[LDLM_EXTENT]	= "EXT",
+	[LDLM_FLOCK]	= "FLK",
+	[LDLM_IBITS]	= "IBT",
 };
 EXPORT_SYMBOL(ldlm_typename);
 
 static ldlm_policy_wire_to_local_t ldlm_policy_wire18_to_local[] = {
-	[LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_wire_to_local,
-	[LDLM_EXTENT - LDLM_MIN_TYPE] ldlm_extent_policy_wire_to_local,
-	[LDLM_FLOCK - LDLM_MIN_TYPE] ldlm_flock_policy_wire18_to_local,
-	[LDLM_IBITS - LDLM_MIN_TYPE] ldlm_ibits_policy_wire_to_local,
+	[LDLM_PLAIN - LDLM_MIN_TYPE]	= ldlm_plain_policy_wire_to_local,
+	[LDLM_EXTENT - LDLM_MIN_TYPE]	= ldlm_extent_policy_wire_to_local,
+	[LDLM_FLOCK - LDLM_MIN_TYPE]	= ldlm_flock_policy_wire18_to_local,
+	[LDLM_IBITS - LDLM_MIN_TYPE]	= ldlm_ibits_policy_wire_to_local,
 };
 
 static ldlm_policy_wire_to_local_t ldlm_policy_wire21_to_local[] = {
-	[LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_wire_to_local,
-	[LDLM_EXTENT - LDLM_MIN_TYPE] ldlm_extent_policy_wire_to_local,
-	[LDLM_FLOCK - LDLM_MIN_TYPE] ldlm_flock_policy_wire21_to_local,
-	[LDLM_IBITS - LDLM_MIN_TYPE] ldlm_ibits_policy_wire_to_local,
+	[LDLM_PLAIN - LDLM_MIN_TYPE]	= ldlm_plain_policy_wire_to_local,
+	[LDLM_EXTENT - LDLM_MIN_TYPE]	= ldlm_extent_policy_wire_to_local,
+	[LDLM_FLOCK - LDLM_MIN_TYPE]	= ldlm_flock_policy_wire21_to_local,
+	[LDLM_IBITS - LDLM_MIN_TYPE]	= ldlm_ibits_policy_wire_to_local,
 };
 
 static ldlm_policy_local_to_wire_t ldlm_policy_local_to_wire[] = {
-	[LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_local_to_wire,
-	[LDLM_EXTENT - LDLM_MIN_TYPE] ldlm_extent_policy_local_to_wire,
-	[LDLM_FLOCK - LDLM_MIN_TYPE] ldlm_flock_policy_local_to_wire,
-	[LDLM_IBITS - LDLM_MIN_TYPE] ldlm_ibits_policy_local_to_wire,
+	[LDLM_PLAIN - LDLM_MIN_TYPE]	= ldlm_plain_policy_local_to_wire,
+	[LDLM_EXTENT - LDLM_MIN_TYPE]	= ldlm_extent_policy_local_to_wire,
+	[LDLM_FLOCK - LDLM_MIN_TYPE]	= ldlm_flock_policy_local_to_wire,
+	[LDLM_IBITS - LDLM_MIN_TYPE]	= ldlm_ibits_policy_local_to_wire,
 };
 
 /**
@@ -188,8 +188,6 @@ EXPORT_SYMBOL(ldlm_lock_get);
  */
 void ldlm_lock_put(struct ldlm_lock *lock)
 {
-	ENTRY;
-
 	LASSERT(lock->l_resource != LP_POISON);
 	LASSERT(atomic_read(&lock->l_refc) > 0);
 	if (atomic_dec_and_test(&lock->l_refc)) {
@@ -199,7 +197,7 @@ void ldlm_lock_put(struct ldlm_lock *lock)
 			   "final lock_put on destroyed lock, freeing it.");
 
 		res = lock->l_resource;
-		LASSERT(lock->l_destroyed);
+		LASSERT(lock->l_flags & LDLM_FL_DESTROYED);
 		LASSERT(list_empty(&lock->l_res_link));
 		LASSERT(list_empty(&lock->l_pending_chain));
 
@@ -220,8 +218,6 @@ void ldlm_lock_put(struct ldlm_lock *lock)
 		lu_ref_fini(&lock->l_reference);
 		OBD_FREE_RCU(lock, sizeof(*lock), &lock->l_handle);
 	}
-
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_lock_put);
 
@@ -253,16 +249,14 @@ int ldlm_lock_remove_from_lru(struct ldlm_lock *lock)
 	struct ldlm_namespace *ns = ldlm_lock_to_ns(lock);
 	int rc;
 
-	ENTRY;
-	if (lock->l_ns_srv) {
+	if (lock->l_flags & LDLM_FL_NS_SRV) {
 		LASSERT(list_empty(&lock->l_lru));
-		RETURN(0);
+		return 0;
 	}
 
 	spin_lock(&ns->ns_lock);
 	rc = ldlm_lock_remove_from_lru_nolock(lock);
 	spin_unlock(&ns->ns_lock);
-	EXIT;
 	return rc;
 }
 
@@ -289,11 +283,9 @@ void ldlm_lock_add_to_lru(struct ldlm_lock *lock)
 {
 	struct ldlm_namespace *ns = ldlm_lock_to_ns(lock);
 
-	ENTRY;
 	spin_lock(&ns->ns_lock);
 	ldlm_lock_add_to_lru_nolock(lock);
 	spin_unlock(&ns->ns_lock);
-	EXIT;
 }
 
 /**
@@ -304,10 +296,8 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock)
 {
 	struct ldlm_namespace *ns = ldlm_lock_to_ns(lock);
 
-	ENTRY;
-	if (lock->l_ns_srv) {
+	if (lock->l_flags & LDLM_FL_NS_SRV) {
 		LASSERT(list_empty(&lock->l_lru));
-		EXIT;
 		return;
 	}
 
@@ -317,7 +307,6 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock)
 		ldlm_lock_add_to_lru_nolock(lock);
 	}
 	spin_unlock(&ns->ns_lock);
-	EXIT;
 }
 
 /**
@@ -341,8 +330,6 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock)
  */
 int ldlm_lock_destroy_internal(struct ldlm_lock *lock)
 {
-	ENTRY;
-
 	if (lock->l_readers || lock->l_writers) {
 		LDLM_ERROR(lock, "lock still has references");
 		LBUG();
@@ -353,12 +340,11 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock)
 		LBUG();
 	}
 
-	if (lock->l_destroyed) {
+	if (lock->l_flags & LDLM_FL_DESTROYED) {
 		LASSERT(list_empty(&lock->l_lru));
-		EXIT;
 		return 0;
 	}
-	lock->l_destroyed = 1;
+	lock->l_flags |= LDLM_FL_DESTROYED;
 
 	if (lock->l_export && lock->l_export->exp_lock_hash) {
 		/* NB: it's safe to call cfs_hash_del() even lock isn't
@@ -383,7 +369,6 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock)
 	if (lock->l_export && lock->l_completion_ast)
 		lock->l_completion_ast(lock, 0);
 #endif
-	EXIT;
 	return 1;
 }
 
@@ -393,7 +378,7 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock)
 void ldlm_lock_destroy(struct ldlm_lock *lock)
 {
 	int first;
-	ENTRY;
+
 	lock_res_and_lock(lock);
 	first = ldlm_lock_destroy_internal(lock);
 	unlock_res_and_lock(lock);
@@ -403,7 +388,6 @@ void ldlm_lock_destroy(struct ldlm_lock *lock)
 		lu_ref_del(&lock->l_reference, "hash", lock);
 		LDLM_LOCK_RELEASE(lock);
 	}
-	EXIT;
 }
 
 /**
@@ -412,14 +396,13 @@ void ldlm_lock_destroy(struct ldlm_lock *lock)
 void ldlm_lock_destroy_nolock(struct ldlm_lock *lock)
 {
 	int first;
-	ENTRY;
+
 	first = ldlm_lock_destroy_internal(lock);
 	/* drop reference from hashtable only for first destroy */
 	if (first) {
 		lu_ref_del(&lock->l_reference, "hash", lock);
 		LDLM_LOCK_RELEASE(lock);
 	}
-	EXIT;
 }
 
 /* this is called by portals_handle2object with the handle lock taken */
@@ -450,14 +433,13 @@ struct portals_handle_ops lock_handle_ops = {
 static struct ldlm_lock *ldlm_lock_new(struct ldlm_resource *resource)
 {
 	struct ldlm_lock *lock;
-	ENTRY;
 
 	if (resource == NULL)
 		LBUG();
 
 	OBD_SLAB_ALLOC_PTR_GFP(lock, ldlm_lock_slab, __GFP_IO);
 	if (lock == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	spin_lock_init(&lock->l_lock);
 	lock->l_resource = resource;
@@ -493,7 +475,7 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_resource *resource)
 #endif
 	INIT_LIST_HEAD(&lock->l_exp_list);
 
-	RETURN(lock);
+	return lock;
 }
 
 /**
@@ -507,7 +489,6 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock,
 	struct ldlm_resource *oldres = lock->l_resource;
 	struct ldlm_resource *newres;
 	int type;
-	ENTRY;
 
 	LASSERT(ns_is_client(ns));
 
@@ -516,7 +497,7 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock,
 		   sizeof(lock->l_resource->lr_name)) == 0) {
 		/* Nothing to do */
 		unlock_res_and_lock(lock);
-		RETURN(0);
+		return 0;
 	}
 
 	LASSERT(new_resid->name[0] != 0);
@@ -529,7 +510,7 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock,
 
 	newres = ldlm_resource_get(ns, NULL, new_resid, type, 1);
 	if (newres == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	lu_ref_add(&newres->lr_reference, "lock", lock);
 	/*
@@ -557,7 +538,7 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock,
 	lu_ref_del(&oldres->lr_reference, "lock", lock);
 	ldlm_resource_putref(oldres);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_lock_change_resource);
 
@@ -586,19 +567,18 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle,
 				     __u64 flags)
 {
 	struct ldlm_lock *lock;
-	ENTRY;
 
 	LASSERT(handle);
 
 	lock = class_handle2object(handle->cookie);
 	if (lock == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	/* It's unlikely but possible that someone marked the lock as
 	 * destroyed after we did handle2object on it */
-	if (flags == 0 && !lock->l_destroyed) {
+	if (flags == 0 && ((lock->l_flags & LDLM_FL_DESTROYED)== 0)) {
 		lu_ref_add(&lock->l_reference, "handle", current);
-		RETURN(lock);
+		return lock;
 	}
 
 	lock_res_and_lock(lock);
@@ -606,24 +586,24 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle,
 	LASSERT(lock->l_resource != NULL);
 
 	lu_ref_add_atomic(&lock->l_reference, "handle", current);
-	if (unlikely(lock->l_destroyed)) {
+	if (unlikely(lock->l_flags & LDLM_FL_DESTROYED)) {
 		unlock_res_and_lock(lock);
 		CDEBUG(D_INFO, "lock already destroyed: lock %p\n", lock);
 		LDLM_LOCK_PUT(lock);
-		RETURN(NULL);
+		return NULL;
 	}
 
 	if (flags && (lock->l_flags & flags)) {
 		unlock_res_and_lock(lock);
 		LDLM_LOCK_PUT(lock);
-		RETURN(NULL);
+		return NULL;
 	}
 
 	if (flags)
 		lock->l_flags |= flags;
 
 	unlock_res_and_lock(lock);
-	RETURN(lock);
+	return lock;
 }
 EXPORT_SYMBOL(__ldlm_handle2lock);
 /** @} ldlm_handles */
@@ -695,7 +675,7 @@ void ldlm_add_bl_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
 		lock->l_flags |= LDLM_FL_AST_SENT;
 		/* If the enqueuing client said so, tell the AST recipient to
 		 * discard dirty data, rather than writing back. */
-		if (new->l_flags & LDLM_AST_DISCARD_DATA)
+		if (new->l_flags & LDLM_FL_AST_DISCARD_DATA)
 			lock->l_flags |= LDLM_FL_DISCARD_DATA;
 		LASSERT(list_empty(&lock->l_bl_ast));
 		list_add(&lock->l_bl_ast, work_list);
@@ -728,13 +708,11 @@ void ldlm_add_cp_work_item(struct ldlm_lock *lock, struct list_head *work_list)
 void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
 			    struct list_head *work_list)
 {
-	ENTRY;
 	check_res_locked(lock->l_resource);
 	if (new)
 		ldlm_add_bl_work_item(lock, new, work_list);
 	else
 		ldlm_add_cp_work_item(lock, work_list);
-	EXIT;
 }
 
 /**
@@ -853,7 +831,6 @@ void ldlm_lock_decref_internal_nolock(struct ldlm_lock *lock, __u32 mode)
 void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
 {
 	struct ldlm_namespace *ns;
-	ENTRY;
 
 	lock_res_and_lock(lock);
 
@@ -873,7 +850,7 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
 	    (lock->l_flags & LDLM_FL_CBPENDING)) {
 		/* If we received a blocked AST and this was the last reference,
 		 * run the callback. */
-		if (lock->l_ns_srv && lock->l_export)
+		if ((lock->l_flags & LDLM_FL_NS_SRV) && lock->l_export)
 			CERROR("FL_CBPENDING set on non-local lock--just a "
 			       "warning\n");
 
@@ -914,8 +891,6 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode)
 		LDLM_DEBUG(lock, "do not add lock into lru list");
 		unlock_res_and_lock(lock);
 	}
-
-	EXIT;
 }
 
 /**
@@ -940,7 +915,6 @@ EXPORT_SYMBOL(ldlm_lock_decref);
 void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode)
 {
 	struct ldlm_lock *lock = __ldlm_handle2lock(lockh, 0);
-	ENTRY;
 
 	LASSERT(lock != NULL);
 
@@ -979,7 +953,6 @@ static void search_granted_lock(struct list_head *queue,
 {
 	struct list_head *tmp;
 	struct ldlm_lock *lock, *mode_end, *policy_end;
-	ENTRY;
 
 	list_for_each(tmp, queue) {
 		lock = list_entry(tmp, struct ldlm_lock, l_res_link);
@@ -999,7 +972,6 @@ static void search_granted_lock(struct list_head *queue,
 			prev->res_link = &mode_end->l_res_link;
 			prev->mode_link = &mode_end->l_sl_mode;
 			prev->policy_link = &req->l_sl_policy;
-			EXIT;
 			return;
 		} else if (lock->l_resource->lr_type == LDLM_IBITS) {
 			for (;;) {
@@ -1018,7 +990,6 @@ static void search_granted_lock(struct list_head *queue,
 						&policy_end->l_sl_mode;
 					prev->policy_link =
 						&policy_end->l_sl_policy;
-					EXIT;
 					return;
 				}
 
@@ -1037,7 +1008,6 @@ static void search_granted_lock(struct list_head *queue,
 			prev->res_link = &mode_end->l_res_link;
 			prev->mode_link = &mode_end->l_sl_mode;
 			prev->policy_link = &req->l_sl_policy;
-			EXIT;
 			return;
 		} else {
 			LDLM_ERROR(lock,"is not LDLM_PLAIN or LDLM_IBITS lock");
@@ -1050,7 +1020,6 @@ static void search_granted_lock(struct list_head *queue,
 	prev->res_link = queue->prev;
 	prev->mode_link = &req->l_sl_mode;
 	prev->policy_link = &req->l_sl_policy;
-	EXIT;
 	return;
 }
 
@@ -1062,14 +1031,13 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock,
 				       struct sl_insert_point *prev)
 {
 	struct ldlm_resource *res = lock->l_resource;
-	ENTRY;
 
 	check_res_locked(res);
 
 	ldlm_resource_dump(D_INFO, res);
 	LDLM_DEBUG(lock, "About to add lock:");
 
-	if (lock->l_destroyed) {
+	if (lock->l_flags & LDLM_FL_DESTROYED) {
 		CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
 		return;
 	}
@@ -1088,8 +1056,6 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock,
 		list_add(&lock->l_sl_mode, prev->mode_link);
 	if (&lock->l_sl_policy != prev->policy_link)
 		list_add(&lock->l_sl_policy, prev->policy_link);
-
-	EXIT;
 }
 
 /**
@@ -1099,13 +1065,11 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock,
 static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock)
 {
 	struct sl_insert_point prev;
-	ENTRY;
 
 	LASSERT(lock->l_req_mode == lock->l_granted_mode);
 
 	search_granted_lock(&lock->l_resource->lr_granted, lock, &prev);
 	ldlm_granted_list_add_lock(lock, &prev);
-	EXIT;
 }
 
 /**
@@ -1122,7 +1086,6 @@ static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock)
 void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list)
 {
 	struct ldlm_resource *res = lock->l_resource;
-	ENTRY;
 
 	check_res_locked(res);
 
@@ -1141,7 +1104,6 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list)
 		ldlm_add_ast_work_item(lock, NULL, work_list);
 
 	ldlm_pool_add(&ldlm_res_to_ns(res)->ns_pool, lock);
-	EXIT;
 }
 
 /**
@@ -1203,9 +1165,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue,
 		      policy->l_inodebits.bits))
 			continue;
 
-		if (!unref &&
-		    (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED ||
-		     lock->l_failed))
+		if (!unref && (lock->l_flags & LDLM_FL_GONE_MASK))
 			continue;
 
 		if ((flags & LDLM_FL_LOCAL_ONLY) &&
@@ -1227,8 +1187,8 @@ static struct ldlm_lock *search_queue(struct list_head *queue,
 
 void ldlm_lock_fail_match_locked(struct ldlm_lock *lock)
 {
-	if (!lock->l_failed) {
-		lock->l_failed = 1;
+	if ((lock->l_flags & LDLM_FL_FAIL_NOTIFIED) == 0) {
+		lock->l_flags |= LDLM_FL_FAIL_NOTIFIED;
 		wake_up_all(&lock->l_waitq);
 	}
 }
@@ -1306,7 +1266,6 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags,
 	struct ldlm_resource *res;
 	struct ldlm_lock *lock, *old_lock = NULL;
 	int rc = 0;
-	ENTRY;
 
 	if (ns == NULL) {
 		old_lock = ldlm_handle2lock(lockh);
@@ -1321,7 +1280,7 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags,
 	res = ldlm_resource_get(ns, NULL, res_id, type, 0);
 	if (res == NULL) {
 		LASSERT(old_lock == NULL);
-		RETURN(0);
+		return 0;
 	}
 
 	LDLM_RESOURCE_ADDREF(res);
@@ -1342,7 +1301,6 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags,
 	if (lock != NULL)
 		GOTO(out, rc = 1);
 
-	EXIT;
  out:
 	unlock_res(res);
 	LDLM_RESOURCE_DELREF(res);
@@ -1352,6 +1310,8 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags,
 		ldlm_lock2handle(lock, lockh);
 		if ((flags & LDLM_FL_LVB_READY) &&
 		    (!(lock->l_flags & LDLM_FL_LVB_READY))) {
+			__u64 wait_flags = LDLM_FL_LVB_READY |
+				LDLM_FL_DESTROYED | LDLM_FL_FAIL_NOTIFIED;
 			struct l_wait_info lwi;
 			if (lock->l_completion_ast) {
 				int err = lock->l_completion_ast(lock,
@@ -1373,8 +1333,7 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags,
 
 			/* XXX FIXME see comment on CAN_MATCH in lustre_dlm.h */
 			l_wait_event(lock->l_waitq,
-				     lock->l_flags & LDLM_FL_LVB_READY ||
-				     lock->l_destroyed || lock->l_failed,
+				     lock->l_flags & wait_flags,
 				     &lwi);
 			if (!(lock->l_flags & LDLM_FL_LVB_READY)) {
 				if (flags & LDLM_FL_TEST_LOCK)
@@ -1426,13 +1385,11 @@ ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh,
 {
 	struct ldlm_lock *lock;
 	ldlm_mode_t mode = 0;
-	ENTRY;
 
 	lock = ldlm_handle2lock(lockh);
 	if (lock != NULL) {
 		lock_res_and_lock(lock);
-		if (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED ||
-		    lock->l_failed)
+		if (lock->l_flags & LDLM_FL_GONE_MASK)
 			GOTO(out, mode);
 
 		if (lock->l_flags & LDLM_FL_CBPENDING &&
@@ -1445,8 +1402,6 @@ ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh,
 		ldlm_lock_addref_internal_nolock(lock, mode);
 	}
 
-	EXIT;
-
 out:
 	if (lock != NULL) {
 		unlock_res_and_lock(lock);
@@ -1461,7 +1416,6 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
 		  enum req_location loc, void *data, int size)
 {
 	void *lvb;
-	ENTRY;
 
 	LASSERT(data != NULL);
 	LASSERT(size >= 0);
@@ -1479,7 +1433,7 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
 						lustre_swab_ost_lvb);
 			if (unlikely(lvb == NULL)) {
 				LDLM_ERROR(lock, "no LVB");
-				RETURN(-EPROTO);
+				return -EPROTO;
 			}
 
 			memcpy(data, lvb, size);
@@ -1496,7 +1450,7 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
 						lustre_swab_ost_lvb_v1);
 			if (unlikely(lvb == NULL)) {
 				LDLM_ERROR(lock, "no LVB");
-				RETURN(-EPROTO);
+				return -EPROTO;
 			}
 
 			memcpy(data, lvb, size);
@@ -1506,7 +1460,7 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
 		} else {
 			LDLM_ERROR(lock, "Replied unexpected ost LVB size %d",
 				   size);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		break;
 	case LVB_T_LQUOTA:
@@ -1521,14 +1475,14 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
 						lustre_swab_lquota_lvb);
 			if (unlikely(lvb == NULL)) {
 				LDLM_ERROR(lock, "no LVB");
-				RETURN(-EPROTO);
+				return -EPROTO;
 			}
 
 			memcpy(data, lvb, size);
 		} else {
 			LDLM_ERROR(lock, "Replied unexpected lquota LVB size %d",
 				   size);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		break;
 	case LVB_T_LAYOUT:
@@ -1541,18 +1495,18 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
 			lvb = req_capsule_server_get(pill, &RMF_DLM_LVB);
 		if (unlikely(lvb == NULL)) {
 			LDLM_ERROR(lock, "no LVB");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		memcpy(data, lvb, size);
 		break;
 	default:
 		LDLM_ERROR(lock, "Unknown LVB type: %d\n", lock->l_lvb_type);
-		libcfs_debug_dumpstack(NULL);
-		RETURN(-EINVAL);
+		dump_stack();
+		return -EINVAL;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1569,26 +1523,25 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns,
 {
 	struct ldlm_lock *lock;
 	struct ldlm_resource *res;
-	ENTRY;
 
 	res = ldlm_resource_get(ns, NULL, res_id, type, 1);
 	if (res == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	lock = ldlm_lock_new(res);
 
 	if (lock == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	lock->l_req_mode = mode;
 	lock->l_ast_data = data;
 	lock->l_pid = current_pid();
-	lock->l_ns_srv = !!ns_is_server(ns);
+	if (ns_is_server(ns))
+		lock->l_flags |= LDLM_FL_NS_SRV;
 	if (cbs) {
 		lock->l_blocking_ast = cbs->lcs_blocking;
 		lock->l_completion_ast = cbs->lcs_completion;
 		lock->l_glimpse_ast = cbs->lcs_glimpse;
-		lock->l_weigh_ast = cbs->lcs_weigh;
 	}
 
 	lock->l_tree_node = NULL;
@@ -1609,7 +1562,7 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns,
 	if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_NEW_LOCK))
 		GOTO(out, 0);
 
-	RETURN(lock);
+	return lock;
 
 out:
 	ldlm_lock_destroy(lock);
@@ -1636,7 +1589,6 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns,
 	int local = ns_is_client(ldlm_res_to_ns(res));
 	ldlm_error_t rc = ELDLM_OK;
 	struct ldlm_interval *node = NULL;
-	ENTRY;
 
 	lock->l_last_activity = cfs_time_current_sec();
 	/* policies are not executed on the client or during replay */
@@ -1654,11 +1606,11 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns,
 				LDLM_LOCK_RELEASE(lock);
 			}
 			*flags |= LDLM_FL_LOCK_CHANGED;
-			RETURN(0);
+			return 0;
 		} else if (rc != ELDLM_OK ||
 			   (rc == ELDLM_OK && (*flags & LDLM_FL_INTENT_ONLY))) {
 			ldlm_lock_destroy(lock);
-			RETURN(rc);
+			return rc;
 		}
 	}
 
@@ -1693,7 +1645,7 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns,
 
 	/* Some flags from the enqueue want to make it into the AST, via the
 	 * lock's l_flags. */
-	lock->l_flags |= *flags & LDLM_AST_DISCARD_DATA;
+	lock->l_flags |= *flags & LDLM_FL_AST_DISCARD_DATA;
 
 	/* This distinction between local lock trees is very important; a client
 	 * namespace only has information about locks taken by that client, and
@@ -1738,10 +1690,9 @@ ldlm_work_bl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	struct ldlm_lock_desc   d;
 	int		     rc;
 	struct ldlm_lock       *lock;
-	ENTRY;
 
 	if (list_empty(arg->list))
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	lock = list_entry(arg->list->next, struct ldlm_lock, l_bl_ast);
 
@@ -1762,7 +1713,7 @@ ldlm_work_bl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	lock->l_blocking_lock = NULL;
 	LDLM_LOCK_RELEASE(lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1775,10 +1726,9 @@ ldlm_work_cp_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	int		      rc = 0;
 	struct ldlm_lock	*lock;
 	ldlm_completion_callback completion_callback;
-	ENTRY;
 
 	if (list_empty(arg->list))
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	lock = list_entry(arg->list->next, struct ldlm_lock, l_cp_ast);
 
@@ -1807,7 +1757,7 @@ ldlm_work_cp_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 		rc = completion_callback(lock, 0, (void *)arg);
 	LDLM_LOCK_RELEASE(lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1820,10 +1770,9 @@ ldlm_work_revoke_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	struct ldlm_lock_desc   desc;
 	int		     rc;
 	struct ldlm_lock       *lock;
-	ENTRY;
 
 	if (list_empty(arg->list))
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	lock = list_entry(arg->list->next, struct ldlm_lock, l_rk_ast);
 	list_del_init(&lock->l_rk_ast);
@@ -1836,7 +1785,7 @@ ldlm_work_revoke_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	rc = lock->l_blocking_ast(lock, &desc, (void*)arg, LDLM_CB_BLOCKING);
 	LDLM_LOCK_RELEASE(lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1848,10 +1797,9 @@ int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	struct ldlm_glimpse_work	*gl_work;
 	struct ldlm_lock		*lock;
 	int				 rc = 0;
-	ENTRY;
 
 	if (list_empty(arg->list))
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	gl_work = list_entry(arg->list->next, struct ldlm_glimpse_work,
 				 gl_list);
@@ -1871,7 +1819,7 @@ int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
 	if ((gl_work->gl_flags & LDLM_GL_WORK_NOFREE) == 0)
 		OBD_FREE_PTR(gl_work);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1888,11 +1836,11 @@ int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
 	int		     rc;
 
 	if (list_empty(rpc_list))
-		RETURN(0);
+		return 0;
 
 	OBD_ALLOC_PTR(arg);
 	if (arg == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	atomic_set(&arg->restart, 0);
 	arg->list = rpc_list;
@@ -1960,13 +1908,10 @@ static int ldlm_reprocess_res(cfs_hash_t *hs, cfs_hash_bd_t *bd,
  */
 void ldlm_reprocess_all_ns(struct ldlm_namespace *ns)
 {
-	ENTRY;
-
 	if (ns != NULL) {
 		cfs_hash_for_each_nolock(ns->ns_rs_hash,
 					 ldlm_reprocess_res, NULL);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_reprocess_all_ns);
 
@@ -1982,13 +1927,11 @@ void ldlm_reprocess_all(struct ldlm_resource *res)
 {
 	LIST_HEAD(rpc_list);
 
-	ENTRY;
 	if (!ns_is_client(ldlm_res_to_ns(res))) {
 		CERROR("This is client-side-only module, cannot handle "
 		       "LDLM_NAMESPACE_SERVER resource type lock.\n");
 		LBUG();
 	}
-	EXIT;
 }
 
 /**
@@ -2032,7 +1975,6 @@ void ldlm_lock_cancel(struct ldlm_lock *lock)
 {
 	struct ldlm_resource *res;
 	struct ldlm_namespace *ns;
-	ENTRY;
 
 	lock_res_and_lock(lock);
 
@@ -2046,15 +1988,15 @@ void ldlm_lock_cancel(struct ldlm_lock *lock)
 		LBUG();
 	}
 
-	if (lock->l_waited)
+	if (lock->l_flags & LDLM_FL_WAITED)
 		ldlm_del_waiting_lock(lock);
 
 	/* Releases cancel callback. */
 	ldlm_cancel_callback(lock);
 
 	/* Yes, second time, just in case it was added again while we were
-	   running with no res lock in ldlm_cancel_callback */
-	if (lock->l_waited)
+	 * running with no res lock in ldlm_cancel_callback */
+	if (lock->l_flags & LDLM_FL_WAITED)
 		ldlm_del_waiting_lock(lock);
 
 	ldlm_resource_unlink_lock(lock);
@@ -2067,8 +2009,6 @@ void ldlm_lock_cancel(struct ldlm_lock *lock)
 	 * if not to zero out lock->l_granted_mode */
 	lock->l_granted_mode = LCK_MINMODE;
 	unlock_res_and_lock(lock);
-
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_lock_cancel);
 
@@ -2079,7 +2019,6 @@ int ldlm_lock_set_data(struct lustre_handle *lockh, void *data)
 {
 	struct ldlm_lock *lock = ldlm_handle2lock(lockh);
 	int rc = -EINVAL;
-	ENTRY;
 
 	if (lock) {
 		if (lock->l_ast_data == NULL)
@@ -2088,7 +2027,7 @@ int ldlm_lock_set_data(struct lustre_handle *lockh, void *data)
 			rc = 0;
 		LDLM_LOCK_PUT(lock);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_lock_set_data);
 
@@ -2160,8 +2099,6 @@ void ldlm_cancel_locks_for_export(struct obd_export *exp)
  */
 void ldlm_lock_downgrade(struct ldlm_lock *lock, int new_mode)
 {
-	ENTRY;
-
 	LASSERT(lock->l_granted_mode & (LCK_PW | LCK_EX));
 	LASSERT(new_mode == LCK_COS);
 
@@ -2177,8 +2114,6 @@ void ldlm_lock_downgrade(struct ldlm_lock *lock, int new_mode)
 	ldlm_grant_lock(lock, NULL);
 	unlock_res_and_lock(lock);
 	ldlm_reprocess_all(lock->l_resource);
-
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_lock_downgrade);
 
@@ -2197,19 +2132,19 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
 	struct ldlm_namespace *ns;
 	int granted = 0;
 	struct ldlm_interval *node;
-	ENTRY;
 
 	/* Just return if mode is unchanged. */
 	if (new_mode == lock->l_granted_mode) {
 		*flags |= LDLM_FL_BLOCK_GRANTED;
-		RETURN(lock->l_resource);
+		return lock->l_resource;
 	}
 
 	/* I can't check the type of lock here because the bitlock of lock
 	 * is not held here, so do the allocation blindly. -jay */
 	OBD_SLAB_ALLOC_PTR_GFP(node, ldlm_interval_slab, __GFP_IO);
-	if (node == NULL)  /* Actually, this causes EDEADLOCK to be returned */
-		RETURN(NULL);
+	if (node == NULL)
+		/* Actually, this causes EDEADLOCK to be returned */
+		return NULL;
 
 	LASSERTF((new_mode == LCK_PW && lock->l_granted_mode == LCK_PR),
 		 "new_mode %u, granted %u\n", new_mode, lock->l_granted_mode);
@@ -2268,7 +2203,7 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
 		ldlm_run_ast_work(ns, &rpc_list, LDLM_WORK_CP_AST);
 	if (node)
 		OBD_SLAB_FREE(node, ldlm_interval_slab, sizeof(*node));
-	RETURN(res);
+	return res;
 }
 EXPORT_SYMBOL(ldlm_lock_convert);
 
@@ -2337,91 +2272,90 @@ void _ldlm_lock_debug(struct ldlm_lock *lock,
 	switch (resource->lr_type) {
 	case LDLM_EXTENT:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-		       " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-		       "res: "LPU64"/"LPU64" rrc: %d type: %s ["LPU64"->"LPU64
-		       "] (req "LPU64"->"LPU64") flags: "LPX64" nid: %s remote:"
-		       " "LPX64" expref: %d pid: %u timeout: %lu lvb_type: %d\n",
-		       ldlm_lock_to_ns_name(lock), lock,
-		       lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
-		       lock->l_readers, lock->l_writers,
-		       ldlm_lockname[lock->l_granted_mode],
-		       ldlm_lockname[lock->l_req_mode],
-		       resource->lr_name.name[0],
-		       resource->lr_name.name[1],
-		       atomic_read(&resource->lr_refcount),
-		       ldlm_typename[resource->lr_type],
-		       lock->l_policy_data.l_extent.start,
-		       lock->l_policy_data.l_extent.end,
-		       lock->l_req_extent.start, lock->l_req_extent.end,
-		       lock->l_flags, nid, lock->l_remote_handle.cookie,
-		       exp ? atomic_read(&exp->exp_refcount) : -99,
-		       lock->l_pid, lock->l_callback_timeout, lock->l_lvb_type);
+			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" rrc: %d type: %s ["LPU64"->"LPU64"] "
+			"(req "LPU64"->"LPU64") flags: "LPX64" nid: %s remote: "
+			LPX64" expref: %d pid: %u timeout: %lu lvb_type: %d\n",
+			ldlm_lock_to_ns_name(lock), lock,
+			lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
+			lock->l_readers, lock->l_writers,
+			ldlm_lockname[lock->l_granted_mode],
+			ldlm_lockname[lock->l_req_mode],
+			PLDLMRES(resource),
+			atomic_read(&resource->lr_refcount),
+			ldlm_typename[resource->lr_type],
+			lock->l_policy_data.l_extent.start,
+			lock->l_policy_data.l_extent.end,
+			lock->l_req_extent.start, lock->l_req_extent.end,
+			lock->l_flags, nid, lock->l_remote_handle.cookie,
+			exp ? atomic_read(&exp->exp_refcount) : -99,
+			lock->l_pid, lock->l_callback_timeout,
+			lock->l_lvb_type);
 		break;
 
 	case LDLM_FLOCK:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-		       " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-		       "res: "LPU64"/"LPU64" rrc: %d type: %s pid: %d "
-		       "["LPU64"->"LPU64"] flags: "LPX64" nid: %s remote: "LPX64
-		       " expref: %d pid: %u timeout: %lu\n",
-		       ldlm_lock_to_ns_name(lock), lock,
-		       lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
-		       lock->l_readers, lock->l_writers,
-		       ldlm_lockname[lock->l_granted_mode],
-		       ldlm_lockname[lock->l_req_mode],
-		       resource->lr_name.name[0],
-		       resource->lr_name.name[1],
-		       atomic_read(&resource->lr_refcount),
-		       ldlm_typename[resource->lr_type],
-		       lock->l_policy_data.l_flock.pid,
-		       lock->l_policy_data.l_flock.start,
-		       lock->l_policy_data.l_flock.end,
-		       lock->l_flags, nid, lock->l_remote_handle.cookie,
-		       exp ? atomic_read(&exp->exp_refcount) : -99,
-		       lock->l_pid, lock->l_callback_timeout);
+			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" rrc: %d type: %s pid: %d "
+			"["LPU64"->"LPU64"] flags: "LPX64" nid: %s "
+			"remote: "LPX64" expref: %d pid: %u timeout: %lu\n",
+			ldlm_lock_to_ns_name(lock), lock,
+			lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
+			lock->l_readers, lock->l_writers,
+			ldlm_lockname[lock->l_granted_mode],
+			ldlm_lockname[lock->l_req_mode],
+			PLDLMRES(resource),
+			atomic_read(&resource->lr_refcount),
+			ldlm_typename[resource->lr_type],
+			lock->l_policy_data.l_flock.pid,
+			lock->l_policy_data.l_flock.start,
+			lock->l_policy_data.l_flock.end,
+			lock->l_flags, nid, lock->l_remote_handle.cookie,
+			exp ? atomic_read(&exp->exp_refcount) : -99,
+			lock->l_pid, lock->l_callback_timeout);
 		break;
 
 	case LDLM_IBITS:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-		       " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-		       "res: "LPU64"/"LPU64" bits "LPX64" rrc: %d type: %s "
-		       "flags: "LPX64" nid: %s remote: "LPX64" expref: %d "
-		       "pid: %u timeout: %lu lvb_type: %d\n",
-		       ldlm_lock_to_ns_name(lock),
-		       lock, lock->l_handle.h_cookie,
-		       atomic_read (&lock->l_refc),
-		       lock->l_readers, lock->l_writers,
-		       ldlm_lockname[lock->l_granted_mode],
-		       ldlm_lockname[lock->l_req_mode],
-		       resource->lr_name.name[0],
-		       resource->lr_name.name[1],
-		       lock->l_policy_data.l_inodebits.bits,
-		       atomic_read(&resource->lr_refcount),
-		       ldlm_typename[resource->lr_type],
-		       lock->l_flags, nid, lock->l_remote_handle.cookie,
-		       exp ? atomic_read(&exp->exp_refcount) : -99,
-		       lock->l_pid, lock->l_callback_timeout, lock->l_lvb_type);
+			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" bits "LPX64" rrc: %d type: %s "
+			"flags: "LPX64" nid: %s remote: "LPX64" expref: %d "
+			"pid: %u timeout: %lu lvb_type: %d\n",
+			ldlm_lock_to_ns_name(lock),
+			lock, lock->l_handle.h_cookie,
+			atomic_read(&lock->l_refc),
+			lock->l_readers, lock->l_writers,
+			ldlm_lockname[lock->l_granted_mode],
+			ldlm_lockname[lock->l_req_mode],
+			PLDLMRES(resource),
+			lock->l_policy_data.l_inodebits.bits,
+			atomic_read(&resource->lr_refcount),
+			ldlm_typename[resource->lr_type],
+			lock->l_flags, nid, lock->l_remote_handle.cookie,
+			exp ? atomic_read(&exp->exp_refcount) : -99,
+			lock->l_pid, lock->l_callback_timeout,
+			lock->l_lvb_type);
 		break;
 
 	default:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-		       " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-		       "res: "LPU64"/"LPU64" rrc: %d type: %s flags: "LPX64" "
-		       "nid: %s remote: "LPX64" expref: %d pid: %u timeout: %lu"
-		       "lvb_type: %d\n",
-		       ldlm_lock_to_ns_name(lock),
-		       lock, lock->l_handle.h_cookie,
-		       atomic_read (&lock->l_refc),
-		       lock->l_readers, lock->l_writers,
-		       ldlm_lockname[lock->l_granted_mode],
-		       ldlm_lockname[lock->l_req_mode],
-		       resource->lr_name.name[0],
-		       resource->lr_name.name[1],
-		       atomic_read(&resource->lr_refcount),
-		       ldlm_typename[resource->lr_type],
-		       lock->l_flags, nid, lock->l_remote_handle.cookie,
-		       exp ? atomic_read(&exp->exp_refcount) : -99,
-		       lock->l_pid, lock->l_callback_timeout, lock->l_lvb_type);
+			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" rrc: %d type: %s flags: "LPX64" "
+			"nid: %s remote: "LPX64" expref: %d pid: %u "
+			"timeout: %lu lvb_type: %d\n",
+			ldlm_lock_to_ns_name(lock),
+			lock, lock->l_handle.h_cookie,
+			atomic_read(&lock->l_refc),
+			lock->l_readers, lock->l_writers,
+			ldlm_lockname[lock->l_granted_mode],
+			ldlm_lockname[lock->l_req_mode],
+			PLDLMRES(resource),
+			atomic_read(&resource->lr_refcount),
+			ldlm_typename[resource->lr_type],
+			lock->l_flags, nid, lock->l_remote_handle.cookie,
+			exp ? atomic_read(&exp->exp_refcount) : -99,
+			lock->l_pid, lock->l_callback_timeout,
+			lock->l_lvb_type);
 		break;
 	}
 	va_end(args);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
index 324d5e4..3916bda 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
@@ -127,12 +127,12 @@ struct ldlm_bl_work_item {
 
 int ldlm_del_waiting_lock(struct ldlm_lock *lock)
 {
-	RETURN(0);
+	return 0;
 }
 
 int ldlm_refresh_waiting_lock(struct ldlm_lock *lock, int timeout)
 {
-	RETURN(0);
+	return 0;
 }
 
 
@@ -146,7 +146,6 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
 			     struct ldlm_lock_desc *ld, struct ldlm_lock *lock)
 {
 	int do_ast;
-	ENTRY;
 
 	LDLM_DEBUG(lock, "client blocking AST callback handler");
 
@@ -172,7 +171,6 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
 
 	LDLM_DEBUG(lock, "client blocking callback handler END");
 	LDLM_LOCK_RELEASE(lock);
-	EXIT;
 }
 
 /**
@@ -188,7 +186,6 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
 	int lvb_len;
 	LIST_HEAD(ast_list);
 	int rc = 0;
-	ENTRY;
 
 	LDLM_DEBUG(lock, "client completion callback handler START");
 
@@ -198,7 +195,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
 			schedule_timeout_and_set_state(
 				TASK_INTERRUPTIBLE, to);
 			if (lock->l_granted_mode == lock->l_req_mode ||
-			    lock->l_destroyed)
+			    lock->l_flags & LDLM_FL_DESTROYED)
 				break;
 		}
 	}
@@ -238,7 +235,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
 	}
 
 	lock_res_and_lock(lock);
-	if (lock->l_destroyed ||
+	if ((lock->l_flags & LDLM_FL_DESTROYED) ||
 	    lock->l_granted_mode == lock->l_req_mode) {
 		/* bug 11300: the lock has already been granted */
 		unlock_res_and_lock(lock);
@@ -332,7 +329,6 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req,
 				    struct ldlm_lock *lock)
 {
 	int rc = -ENOSYS;
-	ENTRY;
 
 	LDLM_DEBUG(lock, "client glimpse AST callback handler");
 
@@ -356,12 +352,10 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req,
 		if (ldlm_bl_to_thread_lock(ns, NULL, lock))
 			ldlm_handle_bl_callback(ns, NULL, lock);
 
-		EXIT;
 		return;
 	}
 	unlock_res_and_lock(lock);
 	LDLM_LOCK_RELEASE(lock);
-	EXIT;
 }
 
 static int ldlm_callback_reply(struct ptlrpc_request *req, int rc)
@@ -382,7 +376,6 @@ static int __ldlm_bl_to_thread(struct ldlm_bl_work_item *blwi,
 			       ldlm_cancel_flags_t cancel_flags)
 {
 	struct ldlm_bl_pool *blp = ldlm_state->ldlm_bl_pool;
-	ENTRY;
 
 	spin_lock(&blp->blp_lock);
 	if (blwi->blwi_lock &&
@@ -402,7 +395,7 @@ static int __ldlm_bl_to_thread(struct ldlm_bl_work_item *blwi,
 	if (!(cancel_flags & LCF_ASYNC))
 		wait_for_completion(&blwi->blwi_comp);
 
-	RETURN(0);
+	return 0;
 }
 
 static inline void init_blwi(struct ldlm_bl_work_item *blwi,
@@ -446,20 +439,18 @@ static int ldlm_bl_to_thread(struct ldlm_namespace *ns,
 			     struct list_head *cancels, int count,
 			     ldlm_cancel_flags_t cancel_flags)
 {
-	ENTRY;
-
 	if (cancels && count == 0)
-		RETURN(0);
+		return 0;
 
 	if (cancel_flags & LCF_ASYNC) {
 		struct ldlm_bl_work_item *blwi;
 
 		OBD_ALLOC(blwi, sizeof(*blwi));
 		if (blwi == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		init_blwi(blwi, ns, ld, cancels, count, lock, cancel_flags);
 
-		RETURN(__ldlm_bl_to_thread(blwi, cancel_flags));
+		return __ldlm_bl_to_thread(blwi, cancel_flags);
 	} else {
 		/* if it is synchronous call do minimum mem alloc, as it could
 		 * be triggered from kernel shrinker
@@ -468,7 +459,7 @@ static int ldlm_bl_to_thread(struct ldlm_namespace *ns,
 
 		memset(&blwi, 0, sizeof(blwi));
 		init_blwi(&blwi, ns, ld, cancels, count, lock, cancel_flags);
-		RETURN(__ldlm_bl_to_thread(&blwi, cancel_flags));
+		return __ldlm_bl_to_thread(&blwi, cancel_flags);
 	}
 }
 
@@ -494,7 +485,6 @@ static int ldlm_handle_setinfo(struct ptlrpc_request *req)
 	void *val;
 	int keylen, vallen;
 	int rc = -ENOSYS;
-	ENTRY;
 
 	DEBUG_REQ(D_HSM, req, "%s: handle setinfo\n", obd->obd_name);
 
@@ -503,14 +493,14 @@ static int ldlm_handle_setinfo(struct ptlrpc_request *req)
 	key = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY);
 	if (key == NULL) {
 		DEBUG_REQ(D_IOCTL, req, "no set_info key");
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 	keylen = req_capsule_get_size(&req->rq_pill, &RMF_SETINFO_KEY,
 				      RCL_CLIENT);
 	val = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_VAL);
 	if (val == NULL) {
 		DEBUG_REQ(D_IOCTL, req, "no set_info val");
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 	vallen = req_capsule_get_size(&req->rq_pill, &RMF_SETINFO_VAL,
 				      RCL_CLIENT);
@@ -552,9 +542,11 @@ static int ldlm_handle_qc_callback(struct ptlrpc_request *req)
 	oqctl = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
 	if (oqctl == NULL) {
 		CERROR("Can't unpack obd_quotactl\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
+	oqctl->qc_stat = ptlrpc_status_ntoh(oqctl->qc_stat);
+
 	cli->cl_qchk_stat = oqctl->qc_stat;
 	return 0;
 }
@@ -566,7 +558,6 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 	struct ldlm_request *dlm_req;
 	struct ldlm_lock *lock;
 	int rc;
-	ENTRY;
 
 	/* Requests arrive in sender's byte order.  The ptlrpc service
 	 * handler has already checked and, if necessary, byte-swapped the
@@ -575,7 +566,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 
 	/* do nothing for sec context finalize */
 	if (lustre_msg_get_opc(req->rq_reqmsg) == SEC_CTX_FINI)
-		RETURN(0);
+		return 0;
 
 	req_capsule_init(&req->rq_pill, req, RCL_SERVER);
 
@@ -583,7 +574,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 		rc = ldlm_callback_reply(req, -ENOTCONN);
 		ldlm_callback_errmsg(req, "Operate on unconnected server",
 				     rc, NULL);
-		RETURN(0);
+		return 0;
 	}
 
 	LASSERT(req->rq_export != NULL);
@@ -592,71 +583,71 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 	switch (lustre_msg_get_opc(req->rq_reqmsg)) {
 	case LDLM_BL_CALLBACK:
 		if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET))
-			RETURN(0);
+			return 0;
 		break;
 	case LDLM_CP_CALLBACK:
 		if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CP_CALLBACK_NET))
-			RETURN(0);
+			return 0;
 		break;
 	case LDLM_GL_CALLBACK:
 		if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_GL_CALLBACK_NET))
-			RETURN(0);
+			return 0;
 		break;
 	case LDLM_SET_INFO:
 		rc = ldlm_handle_setinfo(req);
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	case OBD_LOG_CANCEL: /* remove this eventually - for 1.4.0 compat */
 		CERROR("shouldn't be handling OBD_LOG_CANCEL on DLM thread\n");
 		req_capsule_set(&req->rq_pill, &RQF_LOG_CANCEL);
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOG_CANCEL_NET))
-			RETURN(0);
+			return 0;
 		rc = llog_origin_handle_cancel(req);
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOG_CANCEL_REP))
-			RETURN(0);
+			return 0;
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	case LLOG_ORIGIN_HANDLE_CREATE:
 		req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
-			RETURN(0);
+			return 0;
 		rc = llog_origin_handle_open(req);
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
 		req_capsule_set(&req->rq_pill,
 				&RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
-			RETURN(0);
+			return 0;
 		rc = llog_origin_handle_next_block(req);
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	case LLOG_ORIGIN_HANDLE_READ_HEADER:
 		req_capsule_set(&req->rq_pill,
 				&RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
-			RETURN(0);
+			return 0;
 		rc = llog_origin_handle_read_header(req);
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	case LLOG_ORIGIN_HANDLE_CLOSE:
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
-			RETURN(0);
+			return 0;
 		rc = llog_origin_handle_close(req);
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	case OBD_QC_CALLBACK:
 		req_capsule_set(&req->rq_pill, &RQF_QC_CALLBACK);
 		if (OBD_FAIL_CHECK(OBD_FAIL_OBD_QC_CALLBACK_NET))
-			RETURN(0);
+			return 0;
 		rc = ldlm_handle_qc_callback(req);
 		ldlm_callback_reply(req, rc);
-		RETURN(0);
+		return 0;
 	default:
 		CERROR("unknown opcode %u\n",
 		       lustre_msg_get_opc(req->rq_reqmsg));
 		ldlm_callback_reply(req, -EPROTO);
-		RETURN(0);
+		return 0;
 	}
 
 	ns = req->rq_export->exp_obd->obd_namespace;
@@ -669,7 +660,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 		rc = ldlm_callback_reply(req, -EPROTO);
 		ldlm_callback_errmsg(req, "Operate without parameter", rc,
 				     NULL);
-		RETURN(0);
+		return 0;
 	}
 
 	/* Force a known safe race, send a cancel to the server for a lock
@@ -688,7 +679,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 		rc = ldlm_callback_reply(req, -EINVAL);
 		ldlm_callback_errmsg(req, "Operate with invalid parameter", rc,
 				     &dlm_req->lock_handle[0]);
-		RETURN(0);
+		return 0;
 	}
 
 	if ((lock->l_flags & LDLM_FL_FAIL_LOC) &&
@@ -715,7 +706,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 			rc = ldlm_callback_reply(req, -EINVAL);
 			ldlm_callback_errmsg(req, "Operate on stale lock", rc,
 					     &dlm_req->lock_handle[0]);
-			RETURN(0);
+			return 0;
 		}
 		/* BL_AST locks are not needed in LRU.
 		 * Let ldlm_cancel_lru() be fast. */
@@ -761,7 +752,7 @@ static int ldlm_callback_handler(struct ptlrpc_request *req)
 		LBUG();			 /* checked above */
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 
@@ -805,7 +796,7 @@ static int ldlm_bl_thread_main(void *arg);
 static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp)
 {
 	struct ldlm_bl_thread_data bltd = { .bltd_blp = blp };
-	task_t *task;
+	struct task_struct *task;
 
 	init_completion(&bltd.bltd_comp);
 	bltd.bltd_num = atomic_read(&blp->blp_num_threads);
@@ -832,7 +823,6 @@ static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp)
 static int ldlm_bl_thread_main(void *arg)
 {
 	struct ldlm_bl_pool *blp;
-	ENTRY;
 
 	{
 		struct ldlm_bl_thread_data *bltd = arg;
@@ -904,7 +894,7 @@ static int ldlm_bl_thread_main(void *arg)
 	atomic_dec(&blp->blp_busy_threads);
 	atomic_dec(&blp->blp_num_threads);
 	complete(&blp->blp_comp);
-	RETURN(0);
+	return 0;
 }
 
 
@@ -914,7 +904,7 @@ static int ldlm_cleanup(void);
 int ldlm_get_ref(void)
 {
 	int rc = 0;
-	ENTRY;
+
 	mutex_lock(&ldlm_ref_mutex);
 	if (++ldlm_refcount == 1) {
 		rc = ldlm_setup();
@@ -923,13 +913,12 @@ int ldlm_get_ref(void)
 	}
 	mutex_unlock(&ldlm_ref_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_get_ref);
 
 void ldlm_put_ref(void)
 {
-	ENTRY;
 	mutex_lock(&ldlm_ref_mutex);
 	if (ldlm_refcount == 1) {
 		int rc = ldlm_cleanup();
@@ -941,8 +930,6 @@ void ldlm_put_ref(void)
 		ldlm_refcount--;
 	}
 	mutex_unlock(&ldlm_ref_mutex);
-
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_put_ref);
 
@@ -1016,8 +1003,6 @@ static cfs_hash_ops_t ldlm_export_lock_ops = {
 
 int ldlm_init_export(struct obd_export *exp)
 {
-	ENTRY;
-
 	exp->exp_lock_hash =
 		cfs_hash_create(obd_uuid2str(&exp->exp_client_uuid),
 				HASH_EXP_LOCK_CUR_BITS,
@@ -1029,20 +1014,18 @@ int ldlm_init_export(struct obd_export *exp)
 				CFS_HASH_NBLK_CHANGE);
 
 	if (!exp->exp_lock_hash)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_init_export);
 
 void ldlm_destroy_export(struct obd_export *exp)
 {
-	ENTRY;
 	cfs_hash_putref(exp->exp_lock_hash);
 	exp->exp_lock_hash = NULL;
 
 	ldlm_destroy_flock_export(exp);
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_destroy_export);
 
@@ -1052,14 +1035,13 @@ static int ldlm_setup(void)
 	struct ldlm_bl_pool			*blp = NULL;
 	int rc = 0;
 	int i;
-	ENTRY;
 
 	if (ldlm_state != NULL)
-		RETURN(-EALREADY);
+		return -EALREADY;
 
 	OBD_ALLOC(ldlm_state, sizeof(*ldlm_state));
 	if (ldlm_state == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 #ifdef LPROCFS
 	rc = ldlm_proc_setup();
@@ -1139,23 +1121,21 @@ static int ldlm_setup(void)
 		CERROR("Failed to initialize LDLM pools: %d\n", rc);
 		GOTO(out, rc);
 	}
-	RETURN(0);
+	return 0;
 
  out:
 	ldlm_cleanup();
-	RETURN(rc);
+	return rc;
 }
 
 static int ldlm_cleanup(void)
 {
-	ENTRY;
-
 	if (!list_empty(ldlm_namespace_list(LDLM_NAMESPACE_SERVER)) ||
 	    !list_empty(ldlm_namespace_list(LDLM_NAMESPACE_CLIENT))) {
 		CERROR("ldlm still has namespaces; clean these up first.\n");
 		ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE);
 		ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE);
-		RETURN(-EBUSY);
+		return -EBUSY;
 	}
 
 	ldlm_pools_fini();
@@ -1188,7 +1168,7 @@ static int ldlm_cleanup(void)
 	OBD_FREE(ldlm_state, sizeof(*ldlm_state));
 	ldlm_state = NULL;
 
-	RETURN(0);
+	return 0;
 }
 
 int ldlm_init(void)
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
index b3b6028..0025ee6 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
@@ -142,7 +142,7 @@
  */
 #define LDLM_POOL_SLV_SHIFT (10)
 
-extern proc_dir_entry_t *ldlm_ns_proc_dir;
+extern struct proc_dir_entry *ldlm_ns_proc_dir;
 
 static inline __u64 dru(__u64 val, __u32 shift, int round_up)
 {
@@ -335,17 +335,16 @@ static void ldlm_srv_pool_push_slv(struct ldlm_pool *pl)
 static int ldlm_srv_pool_recalc(struct ldlm_pool *pl)
 {
 	time_t recalc_interval_sec;
-	ENTRY;
 
 	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period)
-		RETURN(0);
+		return 0;
 
 	spin_lock(&pl->pl_lock);
 	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period) {
 		spin_unlock(&pl->pl_lock);
-		RETURN(0);
+		return 0;
 	}
 	/*
 	 * Recalc SLV after last period. This should be done
@@ -367,7 +366,7 @@ static int ldlm_srv_pool_recalc(struct ldlm_pool *pl)
 	lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT,
 			    recalc_interval_sec);
 	spin_unlock(&pl->pl_lock);
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -394,7 +393,7 @@ static int ldlm_srv_pool_shrink(struct ldlm_pool *pl,
 	 * and can't cancel anything. Let's catch this race.
 	 */
 	if (atomic_read(&pl->pl_granted) == 0)
-		RETURN(0);
+		return 0;
 
 	spin_lock(&pl->pl_lock);
 
@@ -473,11 +472,10 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl)
 static int ldlm_cli_pool_recalc(struct ldlm_pool *pl)
 {
 	time_t recalc_interval_sec;
-	ENTRY;
 
 	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period)
-		RETURN(0);
+		return 0;
 
 	spin_lock(&pl->pl_lock);
 	/*
@@ -486,7 +484,7 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl)
 	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period) {
 		spin_unlock(&pl->pl_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	/*
@@ -503,7 +501,7 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl)
 	 * Do not cancel locks in case lru resize is disabled for this ns.
 	 */
 	if (!ns_connect_lru_resize(ldlm_pl2ns(pl)))
-		RETURN(0);
+		return 0;
 
 	/*
 	 * In the time of canceling locks on client we do not need to maintain
@@ -511,8 +509,7 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl)
 	 * It may be called when SLV has changed much, this is why we do not
 	 * take into account pl->pl_recalc_time here.
 	 */
-	RETURN(ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC,
-			       LDLM_CANCEL_LRUR));
+	return ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR);
 }
 
 /**
@@ -524,7 +521,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
 				int nr, unsigned int gfp_mask)
 {
 	struct ldlm_namespace *ns;
-	int canceled = 0, unused;
+	int unused;
 
 	ns = ldlm_pl2ns(pl);
 
@@ -532,7 +529,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
 	 * Do not cancel locks in case lru resize is disabled for this ns.
 	 */
 	if (!ns_connect_lru_resize(ns))
-		RETURN(0);
+		return 0;
 
 	/*
 	 * Make sure that pool knows last SLV and Limit from obd.
@@ -543,14 +540,10 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
 	unused = ns->ns_nr_unused;
 	spin_unlock(&ns->ns_lock);
 
-	if (nr) {
-		canceled = ldlm_cancel_lru(ns, nr, LCF_ASYNC,
-					   LDLM_CANCEL_SHRINK);
-	}
-	/*
-	 * Return the number of potentially reclaimable locks.
-	 */
-	return ((unused - canceled) / 100) * sysctl_vfs_cache_pressure;
+	if (nr == 0)
+		return (unused / 100) * sysctl_vfs_cache_pressure;
+	else
+		return ldlm_cancel_lru(ns, nr, LCF_ASYNC, LDLM_CANCEL_SHRINK);
 }
 
 struct ldlm_pool_ops ldlm_srv_pool_ops = {
@@ -578,7 +571,6 @@ int ldlm_pool_recalc(struct ldlm_pool *pl)
 		goto recalc;
 
 	spin_lock(&pl->pl_lock);
-	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
 	if (recalc_interval_sec > 0) {
 		/*
 		 * Update pool statistics every 1s.
@@ -598,16 +590,17 @@ int ldlm_pool_recalc(struct ldlm_pool *pl)
 		count = pl->pl_ops->po_recalc(pl);
 		lprocfs_counter_add(pl->pl_stats, LDLM_POOL_RECALC_STAT,
 				    count);
-		return count;
 	}
+	recalc_interval_sec = pl->pl_recalc_time - cfs_time_current_sec() +
+			      pl->pl_recalc_period;
 
-	return 0;
+	return recalc_interval_sec;
 }
-EXPORT_SYMBOL(ldlm_pool_recalc);
 
-/**
+/*
  * Pool shrink wrapper. Will call either client or server pool recalc callback
- * depending what pool \a pl is used.
+ * depending what pool pl is used. When nr == 0, just return the number of
+ * freeable locks. Otherwise, return the number of canceled locks.
  */
 int ldlm_pool_shrink(struct ldlm_pool *pl, int nr,
 		     unsigned int gfp_mask)
@@ -734,11 +727,10 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl)
 	struct lprocfs_vars pool_vars[2];
 	char *var_name = NULL;
 	int rc = 0;
-	ENTRY;
 
 	OBD_ALLOC(var_name, MAX_STRING_SIZE + 1);
 	if (!var_name)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	parent_ns_proc = ns->ns_proc_dir_entry;
 	if (parent_ns_proc == NULL) {
@@ -751,6 +743,7 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl)
 	if (IS_ERR(pl->pl_proc_dir)) {
 		CERROR("LProcFS failed in ldlm-pool-init\n");
 		rc = PTR_ERR(pl->pl_proc_dir);
+		pl->pl_proc_dir = NULL;
 		GOTO(out_free_name, rc);
 	}
 
@@ -813,7 +806,6 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl)
 			     "recalc_timing", "sec");
 	rc = lprocfs_register_stats(pl->pl_proc_dir, "stats", pl->pl_stats);
 
-	EXIT;
 out_free_name:
 	OBD_FREE(var_name, MAX_STRING_SIZE + 1);
 	return rc;
@@ -835,7 +827,6 @@ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns,
 		   int idx, ldlm_side_t client)
 {
 	int rc;
-	ENTRY;
 
 	spin_lock_init(&pl->pl_lock);
 	atomic_set(&pl->pl_granted, 0);
@@ -863,17 +854,16 @@ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns,
 	pl->pl_client_lock_volume = 0;
 	rc = ldlm_pool_proc_init(pl);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_DLMTRACE, "Lock pool %s is initialized\n", pl->pl_name);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_pool_init);
 
 void ldlm_pool_fini(struct ldlm_pool *pl)
 {
-	ENTRY;
 	ldlm_pool_proc_fini(pl);
 
 	/*
@@ -882,7 +872,6 @@ void ldlm_pool_fini(struct ldlm_pool *pl)
 	 * any abnormal using cases.
 	 */
 	POISON(pl, 0x5a, sizeof(*pl));
-	EXIT;
 }
 EXPORT_SYMBOL(ldlm_pool_fini);
 
@@ -1025,37 +1014,32 @@ static int ldlm_pool_granted(struct ldlm_pool *pl)
 }
 
 static struct ptlrpc_thread *ldlm_pools_thread;
-static struct shrinker *ldlm_pools_srv_shrinker;
-static struct shrinker *ldlm_pools_cli_shrinker;
 static struct completion ldlm_pools_comp;
 
 /*
- * Cancel \a nr locks from all namespaces (if possible). Returns number of
- * cached locks after shrink is finished. All namespaces are asked to
- * cancel approximately equal amount of locks to keep balancing.
+ * count locks from all namespaces (if possible). Returns number of
+ * cached locks.
  */
-static int ldlm_pools_shrink(ldlm_side_t client, int nr,
-			     unsigned int gfp_mask)
+static unsigned long ldlm_pools_count(ldlm_side_t client, unsigned int gfp_mask)
 {
-	int total = 0, cached = 0, nr_ns;
+	int total = 0, nr_ns;
 	struct ldlm_namespace *ns;
+	struct ldlm_namespace *ns_old = NULL; /* loop detection */
 	void *cookie;
 
-	if (client == LDLM_NAMESPACE_CLIENT && nr != 0 &&
-	    !(gfp_mask & __GFP_FS))
-		return -1;
+	if (client == LDLM_NAMESPACE_CLIENT && !(gfp_mask & __GFP_FS))
+		return 0;
 
-	CDEBUG(D_DLMTRACE, "Request to shrink %d %s locks from all pools\n",
-	       nr, client == LDLM_NAMESPACE_CLIENT ? "client" : "server");
+	CDEBUG(D_DLMTRACE, "Request to count %s locks from all pools\n",
+	       client == LDLM_NAMESPACE_CLIENT ? "client" : "server");
 
 	cookie = cl_env_reenter();
 
 	/*
 	 * Find out how many resources we may release.
 	 */
-	for (nr_ns = atomic_read(ldlm_namespace_nr(client));
-	     nr_ns > 0; nr_ns--)
-	{
+	for (nr_ns = ldlm_namespace_nr_read(client);
+	     nr_ns > 0; nr_ns--) {
 		mutex_lock(ldlm_namespace_lock(client));
 		if (list_empty(ldlm_namespace_list(client))) {
 			mutex_unlock(ldlm_namespace_lock(client));
@@ -1063,24 +1047,49 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr,
 			return 0;
 		}
 		ns = ldlm_namespace_first_locked(client);
+
+		if (ns == ns_old) {
+			mutex_unlock(ldlm_namespace_lock(client));
+			break;
+		}
+
+		if (ldlm_ns_empty(ns)) {
+			ldlm_namespace_move_to_inactive_locked(ns, client);
+			mutex_unlock(ldlm_namespace_lock(client));
+			continue;
+		}
+
+		if (ns_old == NULL)
+			ns_old = ns;
+
 		ldlm_namespace_get(ns);
-		ldlm_namespace_move_locked(ns, client);
+		ldlm_namespace_move_to_active_locked(ns, client);
 		mutex_unlock(ldlm_namespace_lock(client));
 		total += ldlm_pool_shrink(&ns->ns_pool, 0, gfp_mask);
 		ldlm_namespace_put(ns);
 	}
 
-	if (nr == 0 || total == 0) {
-		cl_env_reexit(cookie);
-		return total;
-	}
+	cl_env_reexit(cookie);
+	return total;
+}
+
+static unsigned long ldlm_pools_scan(ldlm_side_t client, int nr, unsigned int gfp_mask)
+{
+	unsigned long freed = 0;
+	int tmp, nr_ns;
+	struct ldlm_namespace *ns;
+	void *cookie;
+
+	if (client == LDLM_NAMESPACE_CLIENT && !(gfp_mask & __GFP_FS))
+		return -1;
+
+	cookie = cl_env_reenter();
 
 	/*
-	 * Shrink at least ldlm_namespace_nr(client) namespaces.
+	 * Shrink at least ldlm_namespace_nr_read(client) namespaces.
 	 */
-	for (nr_ns = atomic_read(ldlm_namespace_nr(client));
-	     nr_ns > 0; nr_ns--)
-	{
+	for (tmp = nr_ns = ldlm_namespace_nr_read(client);
+	     tmp > 0; tmp--) {
 		int cancel, nr_locks;
 
 		/*
@@ -1089,50 +1098,59 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr,
 		mutex_lock(ldlm_namespace_lock(client));
 		if (list_empty(ldlm_namespace_list(client))) {
 			mutex_unlock(ldlm_namespace_lock(client));
-			/*
-			 * If list is empty, we can't return any @cached > 0,
-			 * that probably would cause needless shrinker
-			 * call.
-			 */
-			cached = 0;
 			break;
 		}
 		ns = ldlm_namespace_first_locked(client);
 		ldlm_namespace_get(ns);
-		ldlm_namespace_move_locked(ns, client);
+		ldlm_namespace_move_to_active_locked(ns, client);
 		mutex_unlock(ldlm_namespace_lock(client));
 
 		nr_locks = ldlm_pool_granted(&ns->ns_pool);
-		cancel = 1 + nr_locks * nr / total;
-		ldlm_pool_shrink(&ns->ns_pool, cancel, gfp_mask);
-		cached += ldlm_pool_granted(&ns->ns_pool);
+		/*
+		 * We use to shrink propotionally but with new shrinker API,
+		 * we lost the total number of freeable locks.
+		 */
+		cancel = 1 + min_t(int, nr_locks, nr / nr_ns);
+		freed += ldlm_pool_shrink(&ns->ns_pool, cancel, gfp_mask);
 		ldlm_namespace_put(ns);
 	}
 	cl_env_reexit(cookie);
-	/* we only decrease the SLV in server pools shrinker, return -1 to
-	 * kernel to avoid needless loop. LU-1128 */
-	return (client == LDLM_NAMESPACE_SERVER) ? -1 : cached;
+	/*
+	 * we only decrease the SLV in server pools shrinker, return
+	 * SHRINK_STOP to kernel to avoid needless loop. LU-1128
+	 */
+	return (client == LDLM_NAMESPACE_SERVER) ? SHRINK_STOP : freed;
+}
+
+static unsigned long ldlm_pools_srv_count(struct shrinker *s, struct shrink_control *sc)
+{
+	return ldlm_pools_count(LDLM_NAMESPACE_SERVER, sc->gfp_mask);
+}
+
+static unsigned long ldlm_pools_srv_scan(struct shrinker *s, struct shrink_control *sc)
+{
+	return ldlm_pools_scan(LDLM_NAMESPACE_SERVER, sc->nr_to_scan,
+			       sc->gfp_mask);
 }
 
-static int ldlm_pools_srv_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
+static unsigned long ldlm_pools_cli_count(struct shrinker *s, struct shrink_control *sc)
 {
-	return ldlm_pools_shrink(LDLM_NAMESPACE_SERVER,
-				 shrink_param(sc, nr_to_scan),
-				 shrink_param(sc, gfp_mask));
+	return ldlm_pools_count(LDLM_NAMESPACE_CLIENT, sc->gfp_mask);
 }
 
-static int ldlm_pools_cli_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
+static unsigned long ldlm_pools_cli_scan(struct shrinker *s, struct shrink_control *sc)
 {
-	return ldlm_pools_shrink(LDLM_NAMESPACE_CLIENT,
-				 shrink_param(sc, nr_to_scan),
-				 shrink_param(sc, gfp_mask));
+	return ldlm_pools_scan(LDLM_NAMESPACE_CLIENT, sc->nr_to_scan,
+			       sc->gfp_mask);
 }
 
-void ldlm_pools_recalc(ldlm_side_t client)
+int ldlm_pools_recalc(ldlm_side_t client)
 {
 	__u32 nr_l = 0, nr_p = 0, l;
 	struct ldlm_namespace *ns;
+	struct ldlm_namespace *ns_old = NULL;
 	int nr, equal = 0;
+	int time = 50; /* seconds of sleep if no active namespaces */
 
 	/*
 	 * No need to setup pool limit for client pools.
@@ -1190,16 +1208,14 @@ void ldlm_pools_recalc(ldlm_side_t client)
 				 * for _all_ pools.
 				 */
 				l = LDLM_POOL_HOST_L /
-					atomic_read(
-						ldlm_namespace_nr(client));
+					ldlm_namespace_nr_read(client);
 			} else {
 				/*
 				 * All the rest of greedy pools will have
 				 * all locks in equal parts.
 				 */
 				l = (LDLM_POOL_HOST_L - nr_l) /
-					(atomic_read(
-						ldlm_namespace_nr(client)) -
+					(ldlm_namespace_nr_read(client) -
 					 nr_p);
 			}
 			ldlm_pool_setup(&ns->ns_pool, l);
@@ -1208,9 +1224,9 @@ void ldlm_pools_recalc(ldlm_side_t client)
 	}
 
 	/*
-	 * Recalc at least ldlm_namespace_nr(client) namespaces.
+	 * Recalc at least ldlm_namespace_nr_read(client) namespaces.
 	 */
-	for (nr = atomic_read(ldlm_namespace_nr(client)); nr > 0; nr--) {
+	for (nr = ldlm_namespace_nr_read(client); nr > 0; nr--) {
 		int     skip;
 		/*
 		 * Lock the list, get first @ns in the list, getref, move it
@@ -1226,6 +1242,30 @@ void ldlm_pools_recalc(ldlm_side_t client)
 		}
 		ns = ldlm_namespace_first_locked(client);
 
+		if (ns_old == ns) { /* Full pass complete */
+			mutex_unlock(ldlm_namespace_lock(client));
+			break;
+		}
+
+		/* We got an empty namespace, need to move it back to inactive
+		 * list.
+		 * The race with parallel resource creation is fine:
+		 * - If they do namespace_get before our check, we fail the
+		 *   check and they move this item to the end of the list anyway
+		 * - If we do the check and then they do namespace_get, then
+		 *   we move the namespace to inactive and they will move
+		 *   it back to active (synchronised by the lock, so no clash
+		 *   there).
+		 */
+		if (ldlm_ns_empty(ns)) {
+			ldlm_namespace_move_to_inactive_locked(ns, client);
+			mutex_unlock(ldlm_namespace_lock(client));
+			continue;
+		}
+
+		if (ns_old == NULL)
+			ns_old = ns;
+
 		spin_lock(&ns->ns_lock);
 		/*
 		 * skip ns which is being freed, and we don't want to increase
@@ -1239,24 +1279,29 @@ void ldlm_pools_recalc(ldlm_side_t client)
 		}
 		spin_unlock(&ns->ns_lock);
 
-		ldlm_namespace_move_locked(ns, client);
+		ldlm_namespace_move_to_active_locked(ns, client);
 		mutex_unlock(ldlm_namespace_lock(client));
 
 		/*
 		 * After setup is done - recalc the pool.
 		 */
 		if (!skip) {
-			ldlm_pool_recalc(&ns->ns_pool);
+			int ttime = ldlm_pool_recalc(&ns->ns_pool);
+
+			if (ttime < time)
+				time = ttime;
+
 			ldlm_namespace_put(ns);
 		}
 	}
+	return time;
 }
 EXPORT_SYMBOL(ldlm_pools_recalc);
 
 static int ldlm_pools_thread_main(void *arg)
 {
 	struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg;
-	ENTRY;
+	int s_time, c_time;
 
 	thread_set_flags(thread, SVC_RUNNING);
 	wake_up(&thread->t_ctl_waitq);
@@ -1270,14 +1315,14 @@ static int ldlm_pools_thread_main(void *arg)
 		/*
 		 * Recal all pools on this tick.
 		 */
-		ldlm_pools_recalc(LDLM_NAMESPACE_SERVER);
-		ldlm_pools_recalc(LDLM_NAMESPACE_CLIENT);
+		s_time = ldlm_pools_recalc(LDLM_NAMESPACE_SERVER);
+		c_time = ldlm_pools_recalc(LDLM_NAMESPACE_CLIENT);
 
 		/*
 		 * Wait until the next check time, or until we're
 		 * stopped.
 		 */
-		lwi = LWI_TIMEOUT(cfs_time_seconds(LDLM_POOLS_THREAD_PERIOD),
+		lwi = LWI_TIMEOUT(cfs_time_seconds(min(s_time, c_time)),
 				  NULL, NULL);
 		l_wait_event(thread->t_ctl_waitq,
 			     thread_is_stopping(thread) ||
@@ -1302,15 +1347,14 @@ static int ldlm_pools_thread_main(void *arg)
 static int ldlm_pools_thread_start(void)
 {
 	struct l_wait_info lwi = { 0 };
-	task_t *task;
-	ENTRY;
+	struct task_struct *task;
 
 	if (ldlm_pools_thread != NULL)
-		RETURN(-EALREADY);
+		return -EALREADY;
 
 	OBD_ALLOC_PTR(ldlm_pools_thread);
 	if (ldlm_pools_thread == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	init_completion(&ldlm_pools_comp);
 	init_waitqueue_head(&ldlm_pools_thread->t_ctl_waitq);
@@ -1321,19 +1365,16 @@ static int ldlm_pools_thread_start(void)
 		CERROR("Can't start pool thread, error %ld\n", PTR_ERR(task));
 		OBD_FREE(ldlm_pools_thread, sizeof(*ldlm_pools_thread));
 		ldlm_pools_thread = NULL;
-		RETURN(PTR_ERR(task));
+		return PTR_ERR(task);
 	}
 	l_wait_event(ldlm_pools_thread->t_ctl_waitq,
 		     thread_is_running(ldlm_pools_thread), &lwi);
-	RETURN(0);
+	return 0;
 }
 
 static void ldlm_pools_thread_stop(void)
 {
-	ENTRY;
-
 	if (ldlm_pools_thread == NULL) {
-		EXIT;
 		return;
 	}
 
@@ -1348,37 +1389,37 @@ static void ldlm_pools_thread_stop(void)
 	wait_for_completion(&ldlm_pools_comp);
 	OBD_FREE_PTR(ldlm_pools_thread);
 	ldlm_pools_thread = NULL;
-	EXIT;
 }
 
+static struct shrinker ldlm_pools_srv_shrinker = {
+	.count_objects	= ldlm_pools_srv_count,
+	.scan_objects	= ldlm_pools_srv_scan,
+	.seeks		= DEFAULT_SEEKS,
+};
+
+static struct shrinker ldlm_pools_cli_shrinker = {
+	.count_objects	= ldlm_pools_cli_count,
+	.scan_objects	= ldlm_pools_cli_scan,
+	.seeks		= DEFAULT_SEEKS,
+};
+
 int ldlm_pools_init(void)
 {
 	int rc;
-	ENTRY;
 
 	rc = ldlm_pools_thread_start();
 	if (rc == 0) {
-		ldlm_pools_srv_shrinker =
-			set_shrinker(DEFAULT_SEEKS,
-					 ldlm_pools_srv_shrink);
-		ldlm_pools_cli_shrinker =
-			set_shrinker(DEFAULT_SEEKS,
-					 ldlm_pools_cli_shrink);
+		register_shrinker(&ldlm_pools_srv_shrinker);
+		register_shrinker(&ldlm_pools_cli_shrinker);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_pools_init);
 
 void ldlm_pools_fini(void)
 {
-	if (ldlm_pools_srv_shrinker != NULL) {
-		remove_shrinker(ldlm_pools_srv_shrinker);
-		ldlm_pools_srv_shrinker = NULL;
-	}
-	if (ldlm_pools_cli_shrinker != NULL) {
-		remove_shrinker(ldlm_pools_cli_shrinker);
-		ldlm_pools_cli_shrinker = NULL;
-	}
+	unregister_shrinker(&ldlm_pools_srv_shrinker);
+	unregister_shrinker(&ldlm_pools_cli_shrinker);
 	ldlm_pools_thread_stop();
 }
 EXPORT_SYMBOL(ldlm_pools_fini);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
index 1a690ed..21cb523 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
@@ -94,12 +94,11 @@ int ldlm_expired_completion_wait(void *data)
 	struct obd_import *imp;
 	struct obd_device *obd;
 
-	ENTRY;
 	if (lock->l_conn_export == NULL) {
 		static cfs_time_t next_dump = 0, last_dump = 0;
 
 		if (ptlrpc_check_suspend())
-			RETURN(0);
+			return 0;
 
 		LCONSOLE_WARN("lock timed out (enqueued at "CFS_TIME_T", "
 			      CFS_DURATION_T"s ago)\n",
@@ -120,7 +119,7 @@ int ldlm_expired_completion_wait(void *data)
 			if (last_dump == 0)
 				libcfs_debug_dumplog();
 		}
-		RETURN(0);
+		return 0;
 	}
 
 	obd = lock->l_conn_export->exp_obd;
@@ -132,7 +131,7 @@ int ldlm_expired_completion_wait(void *data)
 		  cfs_time_sub(cfs_time_current_sec(), lock->l_last_activity),
 		  obd2cli_tgt(obd), imp->imp_connection->c_remote_uuid.uuid);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_expired_completion_wait);
 
@@ -160,7 +159,7 @@ static int ldlm_completion_tail(struct ldlm_lock *lock)
 	long delay;
 	int  result;
 
-	if (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED) {
+	if (lock->l_flags & (LDLM_FL_DESTROYED | LDLM_FL_FAILED)) {
 		LDLM_DEBUG(lock, "client-side enqueue: destroyed");
 		result = -EIO;
 	} else {
@@ -184,23 +183,21 @@ static int ldlm_completion_tail(struct ldlm_lock *lock)
  */
 int ldlm_completion_ast_async(struct ldlm_lock *lock, __u64 flags, void *data)
 {
-	ENTRY;
-
 	if (flags == LDLM_FL_WAIT_NOREPROC) {
 		LDLM_DEBUG(lock, "client-side enqueue waiting on pending lock");
-		RETURN(0);
+		return 0;
 	}
 
 	if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
 		       LDLM_FL_BLOCK_CONV))) {
 		wake_up(&lock->l_waitq);
-		RETURN(ldlm_completion_tail(lock));
+		return ldlm_completion_tail(lock);
 	}
 
 	LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, "
 		   "going forward");
 	ldlm_reprocess_all(lock->l_resource);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_completion_ast_async);
 
@@ -234,7 +231,6 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
 	struct l_wait_info lwi;
 	__u32 timeout;
 	int rc = 0;
-	ENTRY;
 
 	if (flags == LDLM_FL_WAIT_NOREPROC) {
 		LDLM_DEBUG(lock, "client-side enqueue waiting on pending lock");
@@ -244,7 +240,7 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
 	if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
 		       LDLM_FL_BLOCK_CONV))) {
 		wake_up(&lock->l_waitq);
-		RETURN(0);
+		return 0;
 	}
 
 	LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, "
@@ -295,10 +291,10 @@ noreproc:
 	if (rc) {
 		LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)",
 			   rc);
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(ldlm_completion_tail(lock));
+	return ldlm_completion_tail(lock);
 }
 EXPORT_SYMBOL(ldlm_completion_ast);
 
@@ -316,7 +312,6 @@ EXPORT_SYMBOL(ldlm_completion_ast);
 int ldlm_blocking_ast_nocheck(struct ldlm_lock *lock)
 {
 	int do_ast;
-	ENTRY;
 
 	lock->l_flags |= LDLM_FL_CBPENDING;
 	do_ast = (!lock->l_readers && !lock->l_writers);
@@ -335,7 +330,7 @@ int ldlm_blocking_ast_nocheck(struct ldlm_lock *lock)
 		LDLM_DEBUG(lock, "Lock still has references, will be "
 			   "cancelled later");
 	}
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_blocking_ast_nocheck);
 
@@ -355,11 +350,9 @@ EXPORT_SYMBOL(ldlm_blocking_ast_nocheck);
 int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 		      void *data, int flag)
 {
-	ENTRY;
-
 	if (flag == LDLM_CB_CANCELING) {
 		/* Don't need to do anything here. */
-		RETURN(0);
+		return 0;
 	}
 
 	lock_res_and_lock(lock);
@@ -370,9 +363,9 @@ int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 	 * early, if so. */
 	if (lock->l_blocking_ast != ldlm_blocking_ast) {
 		unlock_res_and_lock(lock);
-		RETURN(0);
+		return 0;
 	}
-	RETURN(ldlm_blocking_ast_nocheck(lock));
+	return ldlm_blocking_ast_nocheck(lock);
 }
 EXPORT_SYMBOL(ldlm_blocking_ast);
 
@@ -424,7 +417,6 @@ int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
 						 .lcs_blocking   = blocking,
 						 .lcs_glimpse    = glimpse,
 	};
-	ENTRY;
 
 	LASSERT(!(*flags & LDLM_FL_REPLAY));
 	if (unlikely(ns_is_client(ns))) {
@@ -464,7 +456,6 @@ int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
 		lock->l_completion_ast(lock, *flags, NULL);
 
 	LDLM_DEBUG(lock, "client-side local enqueue handler, new lock created");
-	EXIT;
  out:
 	LDLM_LOCK_RELEASE(lock);
  out_nolock:
@@ -530,13 +521,12 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
 	struct ldlm_reply *reply;
 	int cleanup_phase = 1;
 	int size = 0;
-	ENTRY;
 
 	lock = ldlm_handle2lock(lockh);
 	/* ldlm_cli_enqueue is holding a reference on this lock. */
 	if (!lock) {
 		LASSERT(type == LDLM_FLOCK);
-		RETURN(-ENOLCK);
+		return -ENOLCK;
 	}
 
 	LASSERTF(ergo(lvb_len != 0, lvb_len == lock->l_lvb_len),
@@ -698,7 +688,6 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
 	}
 
 	LDLM_DEBUG(lock, "client-side enqueue END");
-	EXIT;
 cleanup:
 	if (cleanup_phase == 1 && rc)
 		failed_lock_cleanup(ns, lock, mode);
@@ -763,7 +752,6 @@ int ldlm_prep_elc_req(struct obd_export *exp, struct ptlrpc_request *req,
 	int flags, avail, to_free, pack = 0;
 	LIST_HEAD(head);
 	int rc;
-	ENTRY;
 
 	if (cancels == NULL)
 		cancels = &head;
@@ -794,7 +782,7 @@ int ldlm_prep_elc_req(struct obd_export *exp, struct ptlrpc_request *req,
 	rc = ptlrpc_request_pack(req, version, opc);
 	if (rc) {
 		ldlm_lock_list_put(cancels, l_bl_ast, count);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (ns_connect_cancelset(ns)) {
@@ -814,7 +802,7 @@ int ldlm_prep_elc_req(struct obd_export *exp, struct ptlrpc_request *req,
 	} else {
 		ldlm_lock_list_put(cancels, l_bl_ast, count);
 	}
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_prep_elc_req);
 
@@ -830,21 +818,20 @@ struct ptlrpc_request *ldlm_enqueue_pack(struct obd_export *exp, int lvb_len)
 {
 	struct ptlrpc_request *req;
 	int rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_ENQUEUE);
 	if (req == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER, lvb_len);
 	ptlrpc_request_set_replen(req);
-	RETURN(req);
+	return req;
 }
 EXPORT_SYMBOL(ldlm_enqueue_pack);
 
@@ -872,7 +859,6 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
 	int		    req_passed_in = 1;
 	int		    rc, err;
 	struct ptlrpc_request *req;
-	ENTRY;
 
 	LASSERT(exp != NULL);
 
@@ -888,15 +874,14 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
 	} else {
 		const struct ldlm_callback_suite cbs = {
 			.lcs_completion = einfo->ei_cb_cp,
-			.lcs_blocking   = einfo->ei_cb_bl,
-			.lcs_glimpse    = einfo->ei_cb_gl,
-			.lcs_weigh      = einfo->ei_cb_wg
+			.lcs_blocking	= einfo->ei_cb_bl,
+			.lcs_glimpse	= einfo->ei_cb_gl
 		};
 		lock = ldlm_lock_create(ns, res_id, einfo->ei_type,
 					einfo->ei_mode, &cbs, einfo->ei_cbdata,
 					lvb_len, lvb_type);
 		if (lock == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		/* for the local lock, add the reference */
 		ldlm_lock_addref_internal(lock, einfo->ei_mode);
 		ldlm_lock2handle(lock, lockh);
@@ -937,7 +922,7 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
 		if (req == NULL) {
 			failed_lock_cleanup(ns, lock, einfo->ei_mode);
 			LDLM_LOCK_RELEASE(lock);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		req_passed_in = 0;
 		if (reqp)
@@ -978,7 +963,7 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
 
 	if (async) {
 		LASSERT(reqp != NULL);
-		RETURN(0);
+		return 0;
 	}
 
 	LDLM_DEBUG(lock, "sending request");
@@ -1002,7 +987,7 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
 			*reqp = NULL;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_cli_enqueue);
 
@@ -1011,7 +996,7 @@ static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode,
 {
 	struct ldlm_resource *res;
 	int rc;
-	ENTRY;
+
 	if (ns_is_client(ldlm_lock_to_ns(lock))) {
 		CERROR("Trying to cancel local lock\n");
 		LBUG();
@@ -1023,11 +1008,11 @@ static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode,
 		ldlm_reprocess_all(res);
 		rc = 0;
 	} else {
-		rc = EDEADLOCK;
+		rc = LUSTRE_EDEADLK;
 	}
 	LDLM_DEBUG(lock, "client-side local convert handler END");
 	LDLM_LOCK_PUT(lock);
-	RETURN(rc);
+	return rc;
 }
 
 /* FIXME: one of ldlm_cli_convert or the server side should reject attempted
@@ -1042,17 +1027,16 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, __u32 *flags)
 	struct ldlm_resource  *res;
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	lock = ldlm_handle2lock(lockh);
 	if (!lock) {
 		LBUG();
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	*flags = 0;
 
 	if (lock->l_conn_export == NULL)
-		RETURN(ldlm_cli_convert_local(lock, new_mode, flags));
+		return ldlm_cli_convert_local(lock, new_mode, flags);
 
 	LDLM_DEBUG(lock, "client-side convert");
 
@@ -1061,7 +1045,7 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, __u32 *flags)
 					LDLM_CONVERT);
 	if (req == NULL) {
 		LDLM_LOCK_PUT(lock);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	body = req_capsule_client_get(&req->rq_pill, &RMF_DLM_REQ);
@@ -1095,9 +1079,8 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, __u32 *flags)
 				GOTO(out, rc);
 		}
 	} else {
-		rc = EDEADLOCK;
+		rc = LUSTRE_EDEADLK;
 	}
-	EXIT;
  out:
 	LDLM_LOCK_PUT(lock);
 	ptlrpc_req_finished(req);
@@ -1115,7 +1098,6 @@ EXPORT_SYMBOL(ldlm_cli_convert);
 static __u64 ldlm_cli_cancel_local(struct ldlm_lock *lock)
 {
 	__u64 rc = LDLM_FL_LOCAL_ONLY;
-	ENTRY;
 
 	if (lock->l_conn_export) {
 		bool local_only;
@@ -1147,7 +1129,7 @@ static __u64 ldlm_cli_cancel_local(struct ldlm_lock *lock)
 		ldlm_reprocess_all(lock->l_resource);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1159,7 +1141,6 @@ static void ldlm_cancel_pack(struct ptlrpc_request *req,
 	struct ldlm_request *dlm;
 	struct ldlm_lock *lock;
 	int max, packed = 0;
-	ENTRY;
 
 	dlm = req_capsule_client_get(&req->rq_pill, &RMF_DLM_REQ);
 	LASSERT(dlm != NULL);
@@ -1184,7 +1165,6 @@ static void ldlm_cancel_pack(struct ptlrpc_request *req,
 		packed++;
 	}
 	CDEBUG(D_DLMTRACE, "%d locks packed\n", packed);
-	EXIT;
 }
 
 /**
@@ -1197,7 +1177,6 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels,
 	struct obd_import *imp;
 	int free, sent = 0;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(exp != NULL);
 	LASSERT(count > 0);
@@ -1205,7 +1184,7 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels,
 	CFS_FAIL_TIMEOUT(OBD_FAIL_LDLM_PAUSE_CANCEL, cfs_fail_val);
 
 	if (CFS_FAIL_CHECK(OBD_FAIL_LDLM_CANCEL_RACE))
-		RETURN(count);
+		return count;
 
 	free = ldlm_format_handles_avail(class_exp2cliimp(exp),
 					 &RQF_LDLM_CANCEL, RCL_CLIENT, 0);
@@ -1217,7 +1196,7 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels,
 		if (imp == NULL || imp->imp_invalid) {
 			CDEBUG(D_DLMTRACE,
 			       "skipping cancel on invalid import %p\n", imp);
-			RETURN(count);
+			return count;
 		}
 
 		req = ptlrpc_request_alloc(imp, &RQF_LDLM_CANCEL);
@@ -1248,7 +1227,7 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels,
 		} else {
 			rc = ptlrpc_queue_wait(req);
 		}
-		if (rc == ESTALE) {
+		if (rc == LUSTRE_ESTALE) {
 			CDEBUG(D_DLMTRACE, "client/server (nid %s) "
 			       "out of sync -- not fatal\n",
 			       libcfs_nid2str(req->rq_import->
@@ -1270,7 +1249,6 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels,
 	}
 
 	ptlrpc_req_finished(req);
-	EXIT;
 out:
 	return sent ? sent : rc;
 }
@@ -1290,14 +1268,14 @@ int ldlm_cli_update_pool(struct ptlrpc_request *req)
 	struct obd_device *obd;
 	__u64 new_slv;
 	__u32 new_limit;
-	ENTRY;
+
 	if (unlikely(!req->rq_import || !req->rq_import->imp_obd ||
 		     !imp_connect_lru_resize(req->rq_import)))
 	{
 		/*
 		 * Do nothing for corner cases.
 		 */
-		RETURN(0);
+		return 0;
 	}
 
 	/* In some cases RPC may contain SLV and limit zeroed out. This
@@ -1311,7 +1289,7 @@ int ldlm_cli_update_pool(struct ptlrpc_request *req)
 			  "(SLV: "LPU64", Limit: %u)",
 			  lustre_msg_get_slv(req->rq_repmsg),
 			  lustre_msg_get_limit(req->rq_repmsg));
-		RETURN(0);
+		return 0;
 	}
 
 	new_limit = lustre_msg_get_limit(req->rq_repmsg);
@@ -1328,7 +1306,7 @@ int ldlm_cli_update_pool(struct ptlrpc_request *req)
 	obd->obd_pool_limit = new_limit;
 	write_unlock(&obd->obd_pool_lock);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_cli_update_pool);
 
@@ -1346,19 +1324,18 @@ int ldlm_cli_cancel(struct lustre_handle *lockh,
 	struct ldlm_namespace *ns;
 	struct ldlm_lock *lock;
 	LIST_HEAD(cancels);
-	ENTRY;
 
 	/* concurrent cancels on the same handle can happen */
 	lock = ldlm_handle2lock_long(lockh, LDLM_FL_CANCELING);
 	if (lock == NULL) {
 		LDLM_DEBUG_NOLOCK("lock is already being destroyed\n");
-		RETURN(0);
+		return 0;
 	}
 
 	rc = ldlm_cli_cancel_local(lock);
 	if (rc == LDLM_FL_LOCAL_ONLY) {
 		LDLM_LOCK_RELEASE(lock);
-		RETURN(0);
+		return 0;
 	}
 	/* Even if the lock is marked as LDLM_FL_BL_AST, this is a LDLM_CANCEL
 	 * RPC which goes to canceld portal, so we can cancel other LRU locks
@@ -1380,7 +1357,7 @@ int ldlm_cli_cancel(struct lustre_handle *lockh,
 					       LCF_BL_AST, flags);
 	}
 	ldlm_cli_cancel_list(&cancels, count, NULL, cancel_flags);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_cli_cancel);
 
@@ -1430,7 +1407,7 @@ int ldlm_cli_cancel_list_local(struct list_head *cancels, int count,
 		ldlm_cli_cancel_list(&head, bl_ast, NULL, 0);
 	}
 
-	RETURN(count);
+	return count;
 }
 EXPORT_SYMBOL(ldlm_cli_cancel_list_local);
 
@@ -1462,7 +1439,7 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns,
 	}
 
 	unlock_res_and_lock(lock);
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -1631,7 +1608,6 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, struct list_head *ca
 	ldlm_cancel_lru_policy_t pf;
 	struct ldlm_lock *lock, *next;
 	int added = 0, unused, remained;
-	ENTRY;
 
 	spin_lock(&ns->ns_lock);
 	unused = ns->ns_nr_unused;
@@ -1754,7 +1730,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, struct list_head *ca
 		unused--;
 	}
 	spin_unlock(&ns->ns_lock);
-	RETURN(added);
+	return added;
 }
 
 int ldlm_cancel_lru_local(struct ldlm_namespace *ns, struct list_head *cancels,
@@ -1782,16 +1758,15 @@ int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr,
 {
 	LIST_HEAD(cancels);
 	int count, rc;
-	ENTRY;
 
 	/* Just prepare the list of locks, do not actually cancel them yet.
 	 * Locks are cancelled later in a separate thread. */
 	count = ldlm_prepare_lru_list(ns, &cancels, nr, 0, flags);
 	rc = ldlm_bl_to_thread_list(ns, NULL, &cancels, count, cancel_flags);
 	if (rc == 0)
-		RETURN(count);
+		return count;
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1807,7 +1782,6 @@ int ldlm_cancel_resource_local(struct ldlm_resource *res,
 {
 	struct ldlm_lock *lock;
 	int count = 0;
-	ENTRY;
 
 	lock_res(res);
 	list_for_each_entry(lock, &res->lr_granted, l_res_link) {
@@ -1848,7 +1822,7 @@ int ldlm_cancel_resource_local(struct ldlm_resource *res,
 	}
 	unlock_res(res);
 
-	RETURN(ldlm_cli_cancel_list_local(cancels, count, cancel_flags));
+	return ldlm_cli_cancel_list_local(cancels, count, cancel_flags);
 }
 EXPORT_SYMBOL(ldlm_cancel_resource_local);
 
@@ -1867,10 +1841,9 @@ int ldlm_cli_cancel_list(struct list_head *cancels, int count,
 {
 	struct ldlm_lock *lock;
 	int res = 0;
-	ENTRY;
 
 	if (list_empty(cancels) || count == 0)
-		RETURN(0);
+		return 0;
 
 	/* XXX: requests (both batched and not) could be sent in parallel.
 	 * Usually it is enough to have just 1 RPC, but it is possible that
@@ -1906,7 +1879,7 @@ int ldlm_cli_cancel_list(struct list_head *cancels, int count,
 		ldlm_lock_list_put(cancels, l_bl_ast, res);
 	}
 	LASSERT(count == 0);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_cli_cancel_list);
 
@@ -1926,13 +1899,12 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
 	LIST_HEAD(cancels);
 	int count;
 	int rc;
-	ENTRY;
 
 	res = ldlm_resource_get(ns, NULL, res_id, 0, 0);
 	if (res == NULL) {
 		/* This is not a problem. */
 		CDEBUG(D_INFO, "No resource "LPU64"\n", res_id->name[0]);
-		RETURN(0);
+		return 0;
 	}
 
 	LDLM_RESOURCE_ADDREF(res);
@@ -1944,7 +1916,7 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
 
 	LDLM_RESOURCE_DELREF(res);
 	ldlm_resource_putref(res);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ldlm_cli_cancel_unused_resource);
 
@@ -1986,19 +1958,17 @@ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns,
 		.lc_opaque      = opaque,
 	};
 
-	ENTRY;
-
 	if (ns == NULL)
-		RETURN(ELDLM_OK);
+		return ELDLM_OK;
 
 	if (res_id != NULL) {
-		RETURN(ldlm_cli_cancel_unused_resource(ns, res_id, NULL,
+		return ldlm_cli_cancel_unused_resource(ns, res_id, NULL,
 						       LCK_MINMODE, flags,
-						       opaque));
+						       opaque);
 	} else {
 		cfs_hash_for_each_nolock(ns->ns_rs_hash,
 					 ldlm_cli_hash_cancel_unused, &arg);
-		RETURN(ELDLM_OK);
+		return ELDLM_OK;
 	}
 }
 EXPORT_SYMBOL(ldlm_cli_cancel_unused);
@@ -2012,10 +1982,8 @@ int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
 	struct ldlm_lock *lock;
 	int rc = LDLM_ITER_CONTINUE;
 
-	ENTRY;
-
 	if (!res)
-		RETURN(LDLM_ITER_CONTINUE);
+		return LDLM_ITER_CONTINUE;
 
 	lock_res(res);
 	list_for_each_safe(tmp, next, &res->lr_granted) {
@@ -2040,7 +2008,7 @@ int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
 	}
  out:
 	unlock_res(res);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_resource_foreach);
 
@@ -2069,7 +2037,10 @@ void ldlm_namespace_foreach(struct ldlm_namespace *ns,
 			    ldlm_iterator_t iter, void *closure)
 
 {
-	struct iter_helper_data helper = { iter: iter, closure: closure };
+	struct iter_helper_data helper = {
+		.iter		= iter,
+		.closure	= closure,
+	};
 
 	cfs_hash_for_each_nolock(ns->ns_rs_hash,
 				 ldlm_res_iter_helper, &helper);
@@ -2088,7 +2059,6 @@ int ldlm_resource_iterate(struct ldlm_namespace *ns,
 {
 	struct ldlm_resource *res;
 	int rc;
-	ENTRY;
 
 	if (ns == NULL) {
 		CERROR("must pass in namespace\n");
@@ -2097,13 +2067,13 @@ int ldlm_resource_iterate(struct ldlm_namespace *ns,
 
 	res = ldlm_resource_get(ns, NULL, res_id, 0, 0);
 	if (res == NULL)
-		RETURN(0);
+		return 0;
 
 	LDLM_RESOURCE_ADDREF(res);
 	rc = ldlm_resource_foreach(res, iter, data);
 	LDLM_RESOURCE_DELREF(res);
 	ldlm_resource_putref(res);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_resource_iterate);
 
@@ -2137,7 +2107,6 @@ static int replay_lock_interpret(const struct lu_env *env,
 	struct ldlm_reply    *reply;
 	struct obd_export    *exp;
 
-	ENTRY;
 	atomic_dec(&req->rq_import->imp_replay_inflight);
 	if (rc != ELDLM_OK)
 		GOTO(out, rc);
@@ -2178,7 +2147,7 @@ out:
 	if (rc != ELDLM_OK)
 		ptlrpc_connect_import(req->rq_import);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
@@ -2187,13 +2156,11 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
 	struct ldlm_async_args *aa;
 	struct ldlm_request   *body;
 	int flags;
-	ENTRY;
-
 
 	/* Bug 11974: Do not replay a lock which is actively being canceled */
 	if (lock->l_flags & LDLM_FL_CANCELING) {
 		LDLM_DEBUG(lock, "Not replaying canceled lock:");
-		RETURN(0);
+		return 0;
 	}
 
 	/* If this is reply-less callback lock, we cannot replay it, since
@@ -2202,7 +2169,7 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
 	if (lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK) {
 		LDLM_DEBUG(lock, "Not replaying reply-less lock:");
 		ldlm_lock_cancel(lock);
-		RETURN(0);
+		return 0;
 	}
 
 	/*
@@ -2231,7 +2198,7 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
 	req = ptlrpc_request_alloc_pack(imp, &RQF_LDLM_ENQUEUE,
 					LUSTRE_DLM_VERSION, LDLM_ENQUEUE);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* We're part of recovery, so don't wait for it. */
 	req->rq_send_state = LUSTRE_IMP_REPLAY_LOCKS;
@@ -2261,7 +2228,7 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock)
 	req->rq_interpret_reply = (ptlrpc_interpterer_t)replay_lock_interpret;
 	ptlrpcd_add_req(req, PDL_POLICY_LOCAL, -1);
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -2300,13 +2267,11 @@ int ldlm_replay_locks(struct obd_import *imp)
 	struct ldlm_lock *lock, *next;
 	int rc = 0;
 
-	ENTRY;
-
 	LASSERT(atomic_read(&imp->imp_replay_inflight) == 0);
 
 	/* don't replay locks if import failed recovery */
 	if (imp->imp_vbr_failed)
-		RETURN(0);
+		return 0;
 
 	/* ensure this doesn't fall to 0 before all have been queued */
 	atomic_inc(&imp->imp_replay_inflight);
@@ -2328,6 +2293,6 @@ int ldlm_replay_locks(struct obd_import *imp)
 
 	atomic_dec(&imp->imp_replay_inflight);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ldlm_replay_locks);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index 9052dc5..208751a 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -48,18 +48,23 @@
 
 struct kmem_cache *ldlm_resource_slab, *ldlm_lock_slab;
 
-atomic_t ldlm_srv_namespace_nr = ATOMIC_INIT(0);
-atomic_t ldlm_cli_namespace_nr = ATOMIC_INIT(0);
+int ldlm_srv_namespace_nr = 0;
+int ldlm_cli_namespace_nr = 0;
 
 struct mutex ldlm_srv_namespace_lock;
 LIST_HEAD(ldlm_srv_namespace_list);
 
 struct mutex ldlm_cli_namespace_lock;
-LIST_HEAD(ldlm_cli_namespace_list);
+/* Client Namespaces that have active resources in them.
+ * Once all resources go away, ldlm_poold moves such namespaces to the
+ * inactive list */
+LIST_HEAD(ldlm_cli_active_namespace_list);
+/* Client namespaces that don't have any locks in them */
+LIST_HEAD(ldlm_cli_inactive_namespace_list);
 
-proc_dir_entry_t *ldlm_type_proc_dir = NULL;
-proc_dir_entry_t *ldlm_ns_proc_dir = NULL;
-proc_dir_entry_t *ldlm_svc_proc_dir = NULL;
+struct proc_dir_entry *ldlm_type_proc_dir = NULL;
+struct proc_dir_entry *ldlm_ns_proc_dir = NULL;
+struct proc_dir_entry *ldlm_svc_proc_dir = NULL;
 
 extern unsigned int ldlm_cancel_unused_locks_before_replay;
 
@@ -73,7 +78,7 @@ static ssize_t lprocfs_wr_dump_ns(struct file *file, const char *buffer,
 {
 	ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE);
 	ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE);
-	RETURN(count);
+	return count;
 }
 LPROC_SEQ_FOPS_WR_ONLY(ldlm, dump_ns);
 
@@ -90,7 +95,6 @@ int ldlm_proc_setup(void)
 		{ "cancel_unused_locks_before_replay", &ldlm_rw_uint_fops,
 		  &ldlm_cancel_unused_locks_before_replay },
 		{ NULL }};
-	ENTRY;
 	LASSERT(ldlm_ns_proc_dir == NULL);
 
 	ldlm_type_proc_dir = lprocfs_register(OBD_LDLM_DEVICENAME,
@@ -122,7 +126,7 @@ int ldlm_proc_setup(void)
 
 	rc = lprocfs_add_vars(ldlm_type_proc_dir, list, NULL);
 
-	RETURN(0);
+	return 0;
 
 err_ns:
 	lprocfs_remove(&ldlm_ns_proc_dir);
@@ -132,7 +136,7 @@ err:
 	ldlm_svc_proc_dir = NULL;
 	ldlm_type_proc_dir = NULL;
 	ldlm_ns_proc_dir = NULL;
-	RETURN(rc);
+	return rc;
 }
 
 void ldlm_proc_cleanup(void)
@@ -325,7 +329,7 @@ int ldlm_namespace_proc_register(struct ldlm_namespace *ns)
 {
 	struct lprocfs_vars lock_vars[2];
 	char lock_name[MAX_STRING_SIZE + 1];
-	proc_dir_entry_t *ns_pde;
+	struct proc_dir_entry *ns_pde;
 
 	LASSERT(ns != NULL);
 	LASSERT(ns->ns_rs_hash != NULL);
@@ -563,14 +567,13 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
 	cfs_hash_bd_t	  bd;
 	int		    idx;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(obd != NULL);
 
 	rc = ldlm_get_ref();
 	if (rc) {
 		CERROR("ldlm_get_ref failed: %d\n", rc);
-		RETURN(NULL);
+		return NULL;
 	}
 
 	for (idx = 0;;idx++) {
@@ -636,7 +639,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
 		GOTO(out_hash, rc);
 	}
 
-	idx = atomic_read(ldlm_namespace_nr(client));
+	idx = ldlm_namespace_nr_read(client);
 	rc = ldlm_pool_init(&ns->ns_pool, ns, idx, client);
 	if (rc) {
 		CERROR("Can't initialize lock pool, rc %d\n", rc);
@@ -644,7 +647,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
 	}
 
 	ldlm_namespace_register(ns, client);
-	RETURN(ns);
+	return ns;
 out_proc:
 	ldlm_namespace_proc_unregister(ns);
 	ldlm_namespace_cleanup(ns, 0);
@@ -654,7 +657,7 @@ out_ns:
 	OBD_FREE_PTR(ns);
 out_ref:
 	ldlm_put_ref();
-	RETURN(NULL);
+	return NULL;
 }
 EXPORT_SYMBOL(ldlm_namespace_new);
 
@@ -803,8 +806,6 @@ EXPORT_SYMBOL(ldlm_namespace_cleanup);
  */
 static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force)
 {
-	ENTRY;
-
 	/* At shutdown time, don't call the cancellation callback */
 	ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0);
 
@@ -836,13 +837,13 @@ force_wait:
 				       "with %d resources in use, (rc=%d)\n",
 				       ldlm_ns_name(ns),
 				       atomic_read(&ns->ns_bref), rc);
-			RETURN(ELDLM_NAMESPACE_EXISTS);
+			return ELDLM_NAMESPACE_EXISTS;
 		}
 		CDEBUG(D_DLMTRACE, "dlm namespace %s free done waiting\n",
 		       ldlm_ns_name(ns));
 	}
 
-	RETURN(ELDLM_OK);
+	return ELDLM_OK;
 }
 
 /**
@@ -859,9 +860,8 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns,
 			       int force)
 {
 	int rc;
-	ENTRY;
+
 	if (!ns) {
-		EXIT;
 		return;
 	}
 
@@ -886,7 +886,6 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns,
 		rc = __ldlm_namespace_free(ns, 1);
 		LASSERT(rc == 0);
 	}
-	EXIT;
 }
 
 /**
@@ -896,9 +895,7 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns,
  */
 void ldlm_namespace_free_post(struct ldlm_namespace *ns)
 {
-	ENTRY;
 	if (!ns) {
-		EXIT;
 		return;
 	}
 
@@ -917,7 +914,6 @@ void ldlm_namespace_free_post(struct ldlm_namespace *ns)
 	LASSERT(list_empty(&ns->ns_list_chain));
 	OBD_FREE_PTR(ns);
 	ldlm_put_ref();
-	EXIT;
 }
 
 /**
@@ -953,6 +949,12 @@ void ldlm_namespace_get(struct ldlm_namespace *ns)
 }
 EXPORT_SYMBOL(ldlm_namespace_get);
 
+/* This is only for callers that care about refcount */
+int ldlm_namespace_get_return(struct ldlm_namespace *ns)
+{
+	return atomic_inc_return(&ns->ns_bref);
+}
+
 void ldlm_namespace_put(struct ldlm_namespace *ns)
 {
 	if (atomic_dec_and_lock(&ns->ns_bref, &ns->ns_lock)) {
@@ -967,8 +969,8 @@ void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client)
 {
 	mutex_lock(ldlm_namespace_lock(client));
 	LASSERT(list_empty(&ns->ns_list_chain));
-	list_add(&ns->ns_list_chain, ldlm_namespace_list(client));
-	atomic_inc(ldlm_namespace_nr(client));
+	list_add(&ns->ns_list_chain, ldlm_namespace_inactive_list(client));
+	ldlm_namespace_nr_inc(client);
 	mutex_unlock(ldlm_namespace_lock(client));
 }
 
@@ -981,12 +983,13 @@ void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client)
 	 * using list_empty(&ns->ns_list_chain). This is why it is
 	 * important to use list_del_init() here. */
 	list_del_init(&ns->ns_list_chain);
-	atomic_dec(ldlm_namespace_nr(client));
+	ldlm_namespace_nr_dec(client);
 	mutex_unlock(ldlm_namespace_lock(client));
 }
 
 /** Should be called with ldlm_namespace_lock(client) taken. */
-void ldlm_namespace_move_locked(struct ldlm_namespace *ns, ldlm_side_t client)
+void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns,
+					  ldlm_side_t client)
 {
 	LASSERT(!list_empty(&ns->ns_list_chain));
 	LASSERT(mutex_is_locked(ldlm_namespace_lock(client)));
@@ -994,6 +997,16 @@ void ldlm_namespace_move_locked(struct ldlm_namespace *ns, ldlm_side_t client)
 }
 
 /** Should be called with ldlm_namespace_lock(client) taken. */
+void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *ns,
+					    ldlm_side_t client)
+{
+	LASSERT(!list_empty(&ns->ns_list_chain));
+	LASSERT(mutex_is_locked(ldlm_namespace_lock(client)));
+	list_move_tail(&ns->ns_list_chain,
+		       ldlm_namespace_inactive_list(client));
+}
+
+/** Should be called with ldlm_namespace_lock(client) taken. */
 struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t client)
 {
 	LASSERT(mutex_is_locked(ldlm_namespace_lock(client)));
@@ -1049,6 +1062,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
 	struct ldlm_resource *res;
 	cfs_hash_bd_t	 bd;
 	__u64		 version;
+	int		      ns_refcount = 0;
 
 	LASSERT(ns != NULL);
 	LASSERT(parent == NULL);
@@ -1119,7 +1133,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
 	/* We won! Let's add the resource. */
 	cfs_hash_bd_add_locked(ns->ns_rs_hash, &bd, &res->lr_hash);
 	if (cfs_hash_bd_count_get(&bd) == 1)
-		ldlm_namespace_get(ns);
+		ns_refcount = ldlm_namespace_get_return(ns);
 
 	cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
 	if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
@@ -1128,8 +1142,9 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
 		OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2);
 		rc = ns->ns_lvbo->lvbo_init(res);
 		if (rc < 0) {
-			CERROR("lvbo_init failed for resource "
-			       LPU64": rc %d\n", name->name[0], rc);
+			CERROR("%s: lvbo_init failed for resource "LPX64":"
+			       LPX64": rc = %d\n", ns->ns_obd->obd_name,
+			       name->name[0], name->name[1], rc);
 			if (res->lr_lvb_data) {
 				OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);
 				res->lr_lvb_data = NULL;
@@ -1144,6 +1159,16 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
 	/* We create resource with locked lr_lvb_mutex. */
 	mutex_unlock(&res->lr_lvb_mutex);
 
+	/* Let's see if we happened to be the very first resource in this
+	 * namespace. If so, and this is a client namespace, we need to move
+	 * the namespace into the active namespaces list to be patrolled by
+	 * the ldlm_poold. */
+	if (ns_is_client(ns) && ns_refcount == 1) {
+		mutex_lock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
+		ldlm_namespace_move_to_active_locked(ns, LDLM_NAMESPACE_CLIENT);
+		mutex_unlock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
+	}
+
 	return res;
 }
 EXPORT_SYMBOL(ldlm_resource_get);
@@ -1249,7 +1274,7 @@ void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
 
 	LDLM_DEBUG(lock, "About to add this lock:\n");
 
-	if (lock->l_destroyed) {
+	if (lock->l_flags & LDLM_FL_DESTROYED) {
 		CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
 		return;
 	}
@@ -1274,7 +1299,7 @@ void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
 	ldlm_resource_dump(D_INFO, res);
 	LDLM_DEBUG(new, "About to insert this lock after %p:\n", original);
 
-	if (new->l_destroyed) {
+	if (new->l_flags & LDLM_FL_DESTROYED) {
 		CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
 		goto out;
 	}
diff --git a/drivers/staging/lustre/lustre/libcfs/Makefile b/drivers/staging/lustre/lustre/libcfs/Makefile
index bf5c563..6e489d7 100644
--- a/drivers/staging/lustre/lustre/libcfs/Makefile
+++ b/drivers/staging/lustre/lustre/libcfs/Makefile
@@ -11,7 +11,7 @@ libcfs-linux-objs += linux-crypto-adler.o
 libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs))
 
 libcfs-all-objs := debug.o fail.o nidstrings.o module.o tracefile.o \
-		   watchdog.o libcfs_string.o hash.o kernel_user_comm.o \
+		   libcfs_string.o hash.o kernel_user_comm.o \
 		   prng.o workitem.o upcall_cache.o libcfs_cpu.o \
 		   libcfs_mem.o libcfs_lock.o
 
diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c
index 5a87b08..9b9c451 100644
--- a/drivers/staging/lustre/lustre/libcfs/debug.c
+++ b/drivers/staging/lustre/lustre/libcfs/debug.c
@@ -335,9 +335,10 @@ libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
  */
 void libcfs_debug_dumplog_internal(void *arg)
 {
-	DECL_JOURNAL_DATA;
+	void *journal_info;
 
-	PUSH_JOURNAL;
+	journal_info = current->journal_info;
+	current->journal_info = NULL;
 
 	if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) != 0) {
 		snprintf(debug_file_name, sizeof(debug_file_name) - 1,
@@ -348,7 +349,8 @@ void libcfs_debug_dumplog_internal(void *arg)
 		cfs_tracefile_dump_all_pages(debug_file_name);
 		libcfs_run_debug_log_upcall(debug_file_name);
 	}
-	POP_JOURNAL;
+
+	current->journal_info = journal_info;
 }
 
 int libcfs_debug_dumplog_thread(void *arg)
@@ -361,8 +363,7 @@ int libcfs_debug_dumplog_thread(void *arg)
 void libcfs_debug_dumplog(void)
 {
 	wait_queue_t wait;
-	task_t    *dumper;
-	ENTRY;
+	struct task_struct *dumper;
 
 	/* we're being careful to ensure that the kernel thread is
 	 * able to set our state to running as it exits before we
@@ -459,14 +460,6 @@ void libcfs_debug_set_level(unsigned int debug_level)
 
 EXPORT_SYMBOL(libcfs_debug_set_level);
 
-long libcfs_log_return(struct libcfs_debug_msg_data *msgdata, long rc)
-{
-	libcfs_debug_msg(msgdata, "Process leaving (rc=%lu : %ld : %lx)\n",
-			 rc, rc, rc);
-	return rc;
-}
-EXPORT_SYMBOL(libcfs_log_return);
-
 void libcfs_log_goto(struct libcfs_debug_msg_data *msgdata, const char *label,
 		     long_ptr_t rc)
 {
diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c
index 98c76df..0dd12c8 100644
--- a/drivers/staging/lustre/lustre/libcfs/hash.c
+++ b/drivers/staging/lustre/lustre/libcfs/hash.c
@@ -1026,8 +1026,6 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
 	cfs_hash_t *hs;
 	int	 len;
 
-	ENTRY;
-
 	CLASSERT(CFS_HASH_THETA_BITS < 15);
 
 	LASSERT(name != NULL);
@@ -1055,7 +1053,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
 	      CFS_HASH_NAME_LEN : CFS_HASH_BIGNAME_LEN;
 	LIBCFS_ALLOC(hs, offsetof(cfs_hash_t, hs_name[len]));
 	if (hs == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	strncpy(hs->hs_name, name, len);
 	hs->hs_name[len - 1] = '\0';
@@ -1087,7 +1085,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
 		return hs;
 
 	LIBCFS_FREE(hs, offsetof(cfs_hash_t, hs_name[len]));
-	RETURN(NULL);
+	return NULL;
 }
 EXPORT_SYMBOL(cfs_hash_create);
 
@@ -1101,7 +1099,6 @@ cfs_hash_destroy(cfs_hash_t *hs)
 	struct hlist_node     *pos;
 	cfs_hash_bd_t	 bd;
 	int		   i;
-	ENTRY;
 
 	LASSERT(hs != NULL);
 	LASSERT(!cfs_hash_is_exiting(hs) &&
@@ -1152,8 +1149,6 @@ cfs_hash_destroy(cfs_hash_t *hs)
 	i = cfs_hash_with_bigname(hs) ?
 	    CFS_HASH_BIGNAME_LEN : CFS_HASH_NAME_LEN;
 	LIBCFS_FREE(hs, offsetof(cfs_hash_t, hs_name[i]));
-
-	EXIT;
 }
 
 cfs_hash_t *cfs_hash_getref(cfs_hash_t *hs)
@@ -1449,7 +1444,6 @@ cfs_hash_for_each_tight(cfs_hash_t *hs, cfs_hash_for_each_cb_t func,
 	int		   excl  = !!remove_safe;
 	int		   loop  = 0;
 	int		   i;
-	ENTRY;
 
 	cfs_hash_for_each_enter(hs);
 
@@ -1489,7 +1483,7 @@ cfs_hash_for_each_tight(cfs_hash_t *hs, cfs_hash_for_each_cb_t func,
 	cfs_hash_unlock(hs, 0);
 
 	cfs_hash_for_each_exit(hs);
-	RETURN(count);
+	return count;
 }
 
 typedef struct {
@@ -1594,7 +1588,6 @@ cfs_hash_for_each_relax(cfs_hash_t *hs, cfs_hash_for_each_cb_t func, void *data)
 	int	       stop_on_change;
 	int	       rc;
 	int	       i;
-	ENTRY;
 
 	stop_on_change = cfs_hash_with_rehash_key(hs) ||
 			 !cfs_hash_with_no_itemref(hs) ||
@@ -1649,23 +1642,21 @@ int
 cfs_hash_for_each_nolock(cfs_hash_t *hs,
 			 cfs_hash_for_each_cb_t func, void *data)
 {
-	ENTRY;
-
 	if (cfs_hash_with_no_lock(hs) ||
 	    cfs_hash_with_rehash_key(hs) ||
 	    !cfs_hash_with_no_itemref(hs))
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	if (CFS_HOP(hs, get) == NULL ||
 	    (CFS_HOP(hs, put) == NULL &&
 	     CFS_HOP(hs, put_locked) == NULL))
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	cfs_hash_for_each_enter(hs);
 	cfs_hash_for_each_relax(hs, func, data);
 	cfs_hash_for_each_exit(hs);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(cfs_hash_for_each_nolock);
 
@@ -1685,7 +1676,6 @@ cfs_hash_for_each_empty(cfs_hash_t *hs,
 			cfs_hash_for_each_cb_t func, void *data)
 {
 	unsigned  i = 0;
-	ENTRY;
 
 	if (cfs_hash_with_no_lock(hs))
 		return -EOPNOTSUPP;
@@ -1701,7 +1691,7 @@ cfs_hash_for_each_empty(cfs_hash_t *hs,
 		       hs->hs_name, i++);
 	}
 	cfs_hash_for_each_exit(hs);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(cfs_hash_for_each_empty);
 
diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
index d6d3b2e..74a0db5 100644
--- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
+++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
@@ -246,10 +246,9 @@ EXPORT_SYMBOL(libcfs_kkuc_group_add);
 int libcfs_kkuc_group_rem(int uid, int group)
 {
 	struct kkuc_reg *reg, *next;
-	ENTRY;
 
 	if (kkuc_groups[group].next == NULL)
-		RETURN(0);
+		return 0;
 
 	if (uid == 0) {
 		/* Broadcast a shutdown message */
@@ -275,7 +274,7 @@ int libcfs_kkuc_group_rem(int uid, int group)
 	}
 	up_write(&kg_sem);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(libcfs_kkuc_group_rem);
 
@@ -284,7 +283,6 @@ int libcfs_kkuc_group_put(int group, void *payload)
 	struct kkuc_reg	*reg;
 	int		 rc = 0;
 	int one_success = 0;
-	ENTRY;
 
 	down_read(&kg_sem);
 	list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
@@ -305,7 +303,7 @@ int libcfs_kkuc_group_put(int group, void *payload)
 	if (one_success)
 		rc = 0;
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(libcfs_kkuc_group_put);
 
@@ -320,16 +318,15 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
 {
 	struct kkuc_reg *reg;
 	int rc = 0;
-	ENTRY;
 
 	if (group > KUC_GRP_MAX) {
 		CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* no link for this group */
 	if (kkuc_groups[group].next == NULL)
-		RETURN(0);
+		return 0;
 
 	down_read(&kg_sem);
 	list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
@@ -339,7 +336,7 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
 	}
 	up_read(&kg_sem);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(libcfs_kkuc_group_foreach);
 
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
index 8e88eb5..1fb3700 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
@@ -33,9 +33,6 @@
  * Author: liang@whamcloud.com
  */
 
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
 #define DEBUG_SUBSYSTEM S_LNET
 
 #include <linux/libcfs/libcfs.h>
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c
index 8d6c4ad..a2ce4c0 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c
@@ -30,9 +30,6 @@
  * Author: liang@whamcloud.com
  */
 
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
 #define DEBUG_SUBSYSTEM S_LNET
 
 #include <linux/libcfs/libcfs.h>
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c b/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
index 8791373..feab537 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
@@ -31,9 +31,6 @@
  * Author: liang@whamcloud.com
  */
 
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
 #define DEBUG_SUBSYSTEM S_LNET
 
 #include <linux/libcfs/libcfs.h>
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
index 9edccc9..922debd 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
@@ -69,7 +69,6 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
 	const char *debugstr;
 	char op = 0;
 	int newmask = minmask, i, len, found = 0;
-	ENTRY;
 
 	/* <str> must be a list of tokens separated by whitespace
 	 * and optionally an operator ('+' or '-').  If an operator
@@ -132,54 +131,6 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
 }
 EXPORT_SYMBOL(cfs_str2mask);
 
-/* Duplicate a string in a platform-independent way */
-char *cfs_strdup(const char *str, u_int32_t flags)
-{
-	size_t lenz; /* length of str + zero byte */
-	char *dup_str;
-
-	lenz = strlen(str) + 1;
-
-	dup_str = kmalloc(lenz, flags);
-	if (dup_str == NULL)
-		return NULL;
-
-	memcpy(dup_str, str, lenz);
-
-	return dup_str;
-}
-EXPORT_SYMBOL(cfs_strdup);
-
-/**
- * cfs_{v}snprintf() return the actual size that is printed rather than
- * the size that would be printed in standard functions.
- */
-/* safe vsnprintf */
-int cfs_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
-{
-	int i;
-
-	LASSERT(size > 0);
-	i = vsnprintf(buf, size, fmt, args);
-
-	return  (i >= size ? size - 1 : i);
-}
-EXPORT_SYMBOL(cfs_vsnprintf);
-
-/* safe snprintf */
-int cfs_snprintf(char *buf, size_t size, const char *fmt, ...)
-{
-	va_list args;
-	int i;
-
-	va_start(args, fmt);
-	i = cfs_vsnprintf(buf, size, fmt, args);
-	va_end(args);
-
-	return  i;
-}
-EXPORT_SYMBOL(cfs_snprintf);
-
 /* get the first string out of @str */
 char *cfs_firststr(char *str, size_t size)
 {
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
index 95142d1..00ab8fd 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
@@ -76,62 +76,22 @@ struct cfs_cpt_data {
 
 static struct cfs_cpt_data	cpt_data;
 
-void
-cfs_cpu_core_siblings(int cpu, cpumask_t *mask)
+static void cfs_cpu_core_siblings(int cpu, cpumask_t *mask)
 {
 	/* return cpumask of cores in the same socket */
 	cpumask_copy(mask, topology_core_cpumask(cpu));
 }
-EXPORT_SYMBOL(cfs_cpu_core_siblings);
-
-/* return number of cores in the same socket of \a cpu */
-int
-cfs_cpu_core_nsiblings(int cpu)
-{
-	int	num;
-
-	down(&cpt_data.cpt_mutex);
-
-	cfs_cpu_core_siblings(cpu, cpt_data.cpt_cpumask);
-	num = cpus_weight(*cpt_data.cpt_cpumask);
-
-	up(&cpt_data.cpt_mutex);
-
-	return num;
-}
-EXPORT_SYMBOL(cfs_cpu_core_nsiblings);
 
 /* return cpumask of HTs in the same core */
-void
-cfs_cpu_ht_siblings(int cpu, cpumask_t *mask)
+static void cfs_cpu_ht_siblings(int cpu, cpumask_t *mask)
 {
 	cpumask_copy(mask, topology_thread_cpumask(cpu));
 }
-EXPORT_SYMBOL(cfs_cpu_ht_siblings);
 
-/* return number of HTs in the same core of \a cpu */
-int
-cfs_cpu_ht_nsiblings(int cpu)
-{
-	int	num;
-
-	down(&cpt_data.cpt_mutex);
-
-	cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask);
-	num = cpus_weight(*cpt_data.cpt_cpumask);
-
-	up(&cpt_data.cpt_mutex);
-
-	return num;
-}
-EXPORT_SYMBOL(cfs_cpu_ht_nsiblings);
-
-void
-cfs_node_to_cpumask(int node, cpumask_t *mask)
+static void cfs_node_to_cpumask(int node, cpumask_t *mask)
 {
 	cpumask_copy(mask, cpumask_of_node(node));
 }
-EXPORT_SYMBOL(cfs_node_to_cpumask);
 
 void
 cfs_cpt_table_free(struct cfs_cpt_table *cptab)
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
index 8e35777..b6c79bc 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
@@ -274,6 +274,8 @@ static int adler32;
 
 int cfs_crypto_register(void)
 {
+	request_module("crc32c");
+
 	adler32 = cfs_crypto_adler32_register();
 
 	/* check all algorithms and do performance test */
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
index f236510..ea9e949 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
@@ -65,20 +65,6 @@ int    cfs_curproc_groups_nr(void)
 	return nr;
 }
 
-void   cfs_curproc_groups_dump(gid_t *array, int size)
-{
-	task_lock(current);
-	size = min_t(int, size, current_cred()->group_info->ngroups);
-	memcpy(array, current_cred()->group_info->blocks[0], size * sizeof(__u32));
-	task_unlock(current);
-}
-
-
-int    current_is_in_group(gid_t gid)
-{
-	return in_group_p(gid);
-}
-
 /* Currently all the CFS_CAP_* defines match CAP_* ones. */
 #define cfs_cap_pack(cap) (cap)
 #define cfs_cap_unpack(cap) (cap)
@@ -226,16 +212,15 @@ int cfs_get_environ(const char *key, char *value, int *val_len)
 	int key_len = strlen(key);
 	unsigned long addr;
 	int rc;
-	ENTRY;
 
 	buffer = kmalloc(buf_len, GFP_USER);
 	if (!buffer)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mm = get_task_mm(current);
 	if (!mm) {
 		kfree(buffer);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* Avoid deadlocks on mmap_sem if called from sys_mmap_pgoff(),
@@ -318,8 +303,6 @@ out:
 EXPORT_SYMBOL(cfs_get_environ);
 
 EXPORT_SYMBOL(cfs_curproc_groups_nr);
-EXPORT_SYMBOL(cfs_curproc_groups_dump);
-EXPORT_SYMBOL(current_is_in_group);
 EXPORT_SYMBOL(cfs_cap_raise);
 EXPORT_SYMBOL(cfs_cap_lower);
 EXPORT_SYMBOL(cfs_cap_raised);
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
index e2c195b..ab1e731 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
@@ -48,14 +48,10 @@
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #include <linux/interrupt.h>
-#include <asm/uaccess.h>
 #include <linux/completion.h>
-
 #include <linux/fs.h>
-#include <linux/stat.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/version.h>
 
 # define DEBUG_SUBSYSTEM S_LNET
 
@@ -82,7 +78,6 @@ void libcfs_run_debug_log_upcall(char *file)
 		"HOME=/",
 		"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
 		NULL};
-	ENTRY;
 
 	argv[0] = lnet_debug_log_upcall;
 
@@ -100,8 +95,6 @@ void libcfs_run_debug_log_upcall(char *file)
 		CDEBUG(D_HA, "Invoked LNET debug log upcall %s %s\n",
 		       argv[0], argv[1]);
 	}
-
-	EXIT;
 }
 
 void libcfs_run_upcall(char **argv)
@@ -112,7 +105,6 @@ void libcfs_run_upcall(char **argv)
 		"HOME=/",
 		"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
 		NULL};
-	ENTRY;
 
 	argv[0] = lnet_upcall;
 	argc = 1;
@@ -145,7 +137,6 @@ void libcfs_run_lbug_upcall(struct libcfs_debug_msg_data *msgdata)
 	char *argv[6];
 	char buf[32];
 
-	ENTRY;
 	snprintf (buf, sizeof buf, "%d", msgdata->msg_line);
 
 	argv[1] = "LBUG";
@@ -168,7 +159,7 @@ void lbug_with_loc(struct libcfs_debug_msg_data *msgdata)
 		/* not reached */
 	}
 
-	libcfs_debug_dumpstack(NULL);
+	dump_stack();
 	if (!libcfs_panic_on_lbug)
 		libcfs_debug_dumplog();
 	libcfs_run_lbug_upcall(msgdata);
@@ -179,54 +170,6 @@ void lbug_with_loc(struct libcfs_debug_msg_data *msgdata)
 		schedule();
 }
 
-
-#include <linux/nmi.h>
-#include <asm/stacktrace.h>
-
-
-static int print_trace_stack(void *data, char *name)
-{
-	printk(" <%s> ", name);
-	return 0;
-}
-
-# define RELIABLE reliable
-# define DUMP_TRACE_CONST const
-static void print_trace_address(void *data, unsigned long addr, int reliable)
-{
-	char fmt[32];
-	touch_nmi_watchdog();
-	sprintf(fmt, " [<%016lx>] %s%%s\n", addr, RELIABLE ? "": "? ");
-	__print_symbol(fmt, addr);
-}
-
-static DUMP_TRACE_CONST struct stacktrace_ops print_trace_ops = {
-	.stack = print_trace_stack,
-	.address = print_trace_address,
-	.walk_stack = print_context_stack,
-};
-
-void libcfs_debug_dumpstack(struct task_struct *tsk)
-{
-	/* dump_stack() */
-	/* show_trace() */
-	if (tsk == NULL)
-		tsk = current;
-	printk("Pid: %d, comm: %.20s\n", tsk->pid, tsk->comm);
-	/* show_trace_log_lvl() */
-	printk("\nCall Trace:\n");
-	dump_trace(tsk, NULL, NULL,
-		   0,
-		   &print_trace_ops, NULL);
-	printk("\n");
-}
-
-task_t *libcfs_current(void)
-{
-	CWARN("current task struct is %p\n", current);
-	return current;
-}
-
 static int panic_notifier(struct notifier_block *self, unsigned long unused1,
 			 void *unused2)
 {
@@ -240,9 +183,9 @@ static int panic_notifier(struct notifier_block *self, unsigned long unused1,
 }
 
 static struct notifier_block libcfs_panic_notifier = {
-	notifier_call :     panic_notifier,
-	next :	      NULL,
-	priority :	  10000
+	.notifier_call	= panic_notifier,
+	.next		= NULL,
+	.priority	= 10000,
 };
 
 void libcfs_register_panic_notifier(void)
@@ -255,10 +198,6 @@ void libcfs_unregister_panic_notifier(void)
 	atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier);
 }
 
-EXPORT_SYMBOL(libcfs_debug_dumpstack);
-EXPORT_SYMBOL(libcfs_current);
-
-
 EXPORT_SYMBOL(libcfs_run_upcall);
 EXPORT_SYMBOL(libcfs_run_lbug_upcall);
 EXPORT_SYMBOL(lbug_with_loc);
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
index 2c7d4a3..55296a3 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
@@ -45,38 +45,37 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
 	struct libcfs_ioctl_hdr   *hdr;
 	struct libcfs_ioctl_data  *data;
 	int err;
-	ENTRY;
 
 	hdr = (struct libcfs_ioctl_hdr *)buf;
 	data = (struct libcfs_ioctl_data *)buf;
 
 	err = copy_from_user(buf, (void *)arg, sizeof(*hdr));
 	if (err)
-		RETURN(err);
+		return err;
 
 	if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) {
 		CERROR("PORTALS: version mismatch kernel vs application\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (hdr->ioc_len + buf >= end) {
 		CERROR("PORTALS: user buffer exceeds kernel buffer\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 
 	if (hdr->ioc_len < sizeof(struct libcfs_ioctl_data)) {
 		CERROR("PORTALS: user buffer too small for ioctl\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	err = copy_from_user(buf, (void *)arg, hdr->ioc_len);
 	if (err)
-		RETURN(err);
+		return err;
 
 	if (libcfs_ioctl_is_invalid(data)) {
 		CERROR("PORTALS: ioctl not correctly formatted\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (data->ioc_inllen1)
@@ -86,7 +85,7 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
 		data->ioc_inlbuf2 = &data->ioc_bulk[0] +
 			cfs_size_round(data->ioc_inllen1);
 
-	RETURN(0);
+	return 0;
 }
 
 int libcfs_ioctl_popdata(void *arg, void *data, int size)
@@ -137,7 +136,7 @@ static long libcfs_ioctl(struct file *file,
 	struct cfs_psdev_file	 pfile;
 	int    rc = 0;
 
-	if (current_fsuid() != 0)
+	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
 	if ( _IOC_TYPE(cmd) != IOC_LIBCFS_TYPE ||
@@ -171,13 +170,13 @@ static long libcfs_ioctl(struct file *file,
 }
 
 static struct file_operations libcfs_fops = {
-	unlocked_ioctl: libcfs_ioctl,
-	open :	  libcfs_psdev_open,
-	release :       libcfs_psdev_release
+	.unlocked_ioctl	= libcfs_ioctl,
+	.open		= libcfs_psdev_open,
+	.release	= libcfs_psdev_release,
 };
 
-psdev_t libcfs_dev = {
-	LNET_MINOR,
-	"lnet",
-	&libcfs_fops
+struct miscdevice libcfs_dev = {
+	.minor = LNET_MINOR,
+	.name = "lnet",
+	.fops = &libcfs_fops,
 };
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c
index b652a79..cc9829f 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c
@@ -81,22 +81,21 @@ add_wait_queue_exclusive_head(wait_queue_head_t *waitq, wait_queue_t *link)
 EXPORT_SYMBOL(add_wait_queue_exclusive_head);
 
 void
-waitq_wait(wait_queue_t *link, cfs_task_state_t state)
+waitq_wait(wait_queue_t *link, long state)
 {
 	schedule();
 }
 EXPORT_SYMBOL(waitq_wait);
 
 int64_t
-waitq_timedwait(wait_queue_t *link, cfs_task_state_t state,
-		    int64_t timeout)
+waitq_timedwait(wait_queue_t *link, long state, int64_t timeout)
 {
 	return schedule_timeout(timeout);
 }
 EXPORT_SYMBOL(waitq_timedwait);
 
 void
-schedule_timeout_and_set_state(cfs_task_state_t state, int64_t timeout)
+schedule_timeout_and_set_state(long state, int64_t timeout)
 {
 	set_current_state(state);
 	schedule_timeout(timeout);
@@ -112,13 +111,13 @@ cfs_pause(cfs_duration_t ticks)
 }
 EXPORT_SYMBOL(cfs_pause);
 
-void cfs_init_timer(timer_list_t *t)
+void cfs_init_timer(struct timer_list *t)
 {
 	init_timer(t);
 }
 EXPORT_SYMBOL(cfs_init_timer);
 
-void cfs_timer_init(timer_list_t *t, cfs_timer_func_t *func, void *arg)
+void cfs_timer_init(struct timer_list *t, cfs_timer_func_t *func, void *arg)
 {
 	init_timer(t);
 	t->function = func;
@@ -126,31 +125,31 @@ void cfs_timer_init(timer_list_t *t, cfs_timer_func_t *func, void *arg)
 }
 EXPORT_SYMBOL(cfs_timer_init);
 
-void cfs_timer_done(timer_list_t *t)
+void cfs_timer_done(struct timer_list *t)
 {
 	return;
 }
 EXPORT_SYMBOL(cfs_timer_done);
 
-void cfs_timer_arm(timer_list_t *t, cfs_time_t deadline)
+void cfs_timer_arm(struct timer_list *t, cfs_time_t deadline)
 {
 	mod_timer(t, deadline);
 }
 EXPORT_SYMBOL(cfs_timer_arm);
 
-void cfs_timer_disarm(timer_list_t *t)
+void cfs_timer_disarm(struct timer_list *t)
 {
 	del_timer(t);
 }
 EXPORT_SYMBOL(cfs_timer_disarm);
 
-int  cfs_timer_is_armed(timer_list_t *t)
+int  cfs_timer_is_armed(struct timer_list *t)
 {
 	return timer_pending(t);
 }
 EXPORT_SYMBOL(cfs_timer_is_armed);
 
-cfs_time_t cfs_timer_deadline(timer_list_t *t)
+cfs_time_t cfs_timer_deadline(struct timer_list *t)
 {
 	return t->expires;
 }
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c
index 522b28e..fc6c977 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c
@@ -54,9 +54,7 @@
 
 #include <linux/fs.h>
 #include <linux/file.h>
-#include <linux/stat.h>
 #include <linux/list.h>
-#include <asm/uaccess.h>
 
 #include <linux/proc_fs.h>
 #include <linux/sysctl.h>
@@ -564,7 +562,7 @@ int insert_proc(void)
 {
 #ifdef CONFIG_SYSCTL
 	if (lnet_table_header == NULL)
-		lnet_table_header = cfs_register_sysctl_table(top_table, 0);
+		lnet_table_header = register_sysctl_table(top_table);
 #endif
 	return 0;
 }
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c
index 855c7e8..e6069d7 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c
@@ -36,7 +36,6 @@
 #define DEBUG_SUBSYSTEM S_LNET
 
 #include <linux/libcfs/libcfs.h>
-#include <linux/libcfs/libcfs.h>
 
 #include <linux/if.h>
 #include <linux/in.h>
@@ -641,8 +640,8 @@ libcfs_sock_connect (struct socket **sockp, int *fatal,
 	*fatal = !(rc == -EADDRNOTAVAIL);
 
 	CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
-	       "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,
-	       HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port);
+	       "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
+	       &local_ip, local_port, &peer_ip, peer_port);
 
 	sock_release(*sockp);
 	return rc;
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c
index 6f56343..162beee 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c
@@ -51,7 +51,7 @@ char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX];
 
 struct rw_semaphore cfs_tracefile_sem;
 
-int cfs_tracefile_init_arch()
+int cfs_tracefile_init_arch(void)
 {
 	int    i;
 	int    j;
@@ -96,7 +96,7 @@ out:
 	return -ENOMEM;
 }
 
-void cfs_tracefile_fini_arch()
+void cfs_tracefile_fini_arch(void)
 {
 	int    i;
 	int    j;
@@ -116,27 +116,27 @@ void cfs_tracefile_fini_arch()
 	fini_rwsem(&cfs_tracefile_sem);
 }
 
-void cfs_tracefile_read_lock()
+void cfs_tracefile_read_lock(void)
 {
 	down_read(&cfs_tracefile_sem);
 }
 
-void cfs_tracefile_read_unlock()
+void cfs_tracefile_read_unlock(void)
 {
 	up_read(&cfs_tracefile_sem);
 }
 
-void cfs_tracefile_write_lock()
+void cfs_tracefile_write_lock(void)
 {
 	down_write(&cfs_tracefile_sem);
 }
 
-void cfs_tracefile_write_unlock()
+void cfs_tracefile_write_unlock(void)
 {
 	up_write(&cfs_tracefile_sem);
 }
 
-cfs_trace_buf_type_t cfs_trace_buf_idx_get()
+cfs_trace_buf_type_t cfs_trace_buf_idx_get(void)
 {
 	if (in_irq())
 		return CFS_TCD_TYPE_IRQ;
@@ -269,7 +269,7 @@ void cfs_print_to_console(struct ptldebug_header *hdr, int mask,
 
 int cfs_trace_max_debug_mb(void)
 {
-	int  total_mb = (num_physpages >> (20 - PAGE_SHIFT));
+	int  total_mb = (totalram_pages >> (20 - PAGE_SHIFT));
 
 	return MAX(512, (total_mb * 80)/100);
 }
diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c
index 3372537..f3108c7 100644
--- a/drivers/staging/lustre/lustre/libcfs/module.c
+++ b/drivers/staging/lustre/lustre/libcfs/module.c
@@ -155,7 +155,6 @@ kportal_memhog_alloc (struct libcfs_device_userstate *ldu, int npages, int flags
 static int libcfs_psdev_open(unsigned long flags, void *args)
 {
 	struct libcfs_device_userstate *ldu;
-	ENTRY;
 
 	try_module_get(THIS_MODULE);
 
@@ -166,14 +165,13 @@ static int libcfs_psdev_open(unsigned long flags, void *args)
 	}
 	*(struct libcfs_device_userstate **)args = ldu;
 
-	RETURN(0);
+	return 0;
 }
 
 /* called when closing /dev/device */
 static int libcfs_psdev_release(unsigned long flags, void *args)
 {
 	struct libcfs_device_userstate *ldu;
-	ENTRY;
 
 	ldu = (struct libcfs_device_userstate *)args;
 	if (ldu != NULL) {
@@ -182,7 +180,7 @@ static int libcfs_psdev_release(unsigned long flags, void *args)
 	}
 
 	module_put(THIS_MODULE);
-	RETURN(0);
+	return 0;
 }
 
 static struct rw_semaphore ioctl_list_sem;
@@ -222,12 +220,11 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile,unsigned long cmd,
 			    void *arg, struct libcfs_ioctl_data *data)
 {
 	int err = -EINVAL;
-	ENTRY;
 
 	switch (cmd) {
 	case IOC_LIBCFS_CLEAR_DEBUG:
 		libcfs_debug_clear_buffer();
-		RETURN(0);
+		return 0;
 	/*
 	 * case IOC_LIBCFS_PANIC:
 	 * Handled in arch/cfs_module.c
@@ -235,9 +232,9 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile,unsigned long cmd,
 	case IOC_LIBCFS_MARK_DEBUG:
 		if (data->ioc_inlbuf1 == NULL ||
 		    data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
-			RETURN(-EINVAL);
+			return -EINVAL;
 		libcfs_debug_mark_buffer(data->ioc_inlbuf1);
-		RETURN(0);
+		return 0;
 #if LWT_SUPPORT
 	case IOC_LIBCFS_LWT_CONTROL:
 		err = lwt_control ((data->ioc_flags & 1) != 0,
@@ -301,7 +298,7 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile,unsigned long cmd,
 			ping(data);
 			symbol_put(kping_client);
 		}
-		RETURN(0);
+		return 0;
 	}
 
 	default: {
@@ -322,7 +319,7 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile,unsigned long cmd,
 	}
 	}
 
-	RETURN(err);
+	return err;
 }
 
 static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg)
@@ -330,11 +327,10 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *a
 	char    *buf;
 	struct libcfs_ioctl_data *data;
 	int err = 0;
-	ENTRY;
 
 	LIBCFS_ALLOC_GFP(buf, 1024, GFP_IOFS);
 	if (buf == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* 'cmd' and permissions get checked in our arch-specific caller */
 	if (libcfs_ioctl_getdata(buf, buf + 800, (void *)arg)) {
@@ -347,7 +343,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *a
 
 out:
 	LIBCFS_FREE(buf, 1024);
-	RETURN(err);
+	return err;
 }
 
 
@@ -365,7 +361,7 @@ MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
 MODULE_DESCRIPTION("Portals v3.1");
 MODULE_LICENSE("GPL");
 
-extern psdev_t libcfs_dev;
+extern struct miscdevice libcfs_dev;
 extern struct rw_semaphore cfs_tracefile_sem;
 extern struct mutex cfs_trace_thread_mutex;
 extern struct cfs_wi_sched *cfs_sched_rehash;
@@ -495,4 +491,6 @@ static void exit_libcfs_module(void)
 	libcfs_arch_cleanup();
 }
 
-cfs_module(libcfs, "1.0.0", init_libcfs_module, exit_libcfs_module);
+MODULE_VERSION("1.0.0");
+module_init(init_libcfs_module);
+module_exit(exit_libcfs_module);
diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c
index ccfd107..99c9e9d 100644
--- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c
+++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c
@@ -785,7 +785,6 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
 	struct cfs_lstr src;
 	struct cfs_lstr res;
 	int rc;
-	ENTRY;
 
 	src.ls_str = str;
 	src.ls_len = len;
@@ -794,15 +793,15 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
 		rc = cfs_gettok(&src, ' ', &res);
 		if (rc == 0) {
 			cfs_free_nidlist(nidlist);
-			RETURN(0);
+			return 0;
 		}
 		rc = parse_nidrange(&res, nidlist);
 		if (rc == 0) {
 			cfs_free_nidlist(nidlist);
-			RETURN(0);
+			return 0;
 		}
 	}
-	RETURN(1);
+	return 1;
 }
 
 /*
@@ -834,7 +833,6 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
 {
 	struct nidrange *nr;
 	struct addrrange *ar;
-	ENTRY;
 
 	list_for_each_entry(nr, nidlist, nr_link) {
 		if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid)))
@@ -842,13 +840,13 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
 		if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid)))
 			continue;
 		if (nr->nr_all)
-			RETURN(1);
+			return 1;
 		list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
 			if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid),
 						       &ar->ar_numaddr_ranges))
-				RETURN(1);
+				return 1;
 	}
-	RETURN(0);
+	return 0;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c
index 439e71d..68c77d3 100644
--- a/drivers/staging/lustre/lustre/libcfs/tracefile.c
+++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c
@@ -529,7 +529,7 @@ static void collect_pages_on_all_cpus(struct page_collection *pc)
 	int i, cpu;
 
 	spin_lock(&pc->pc_lock);
-	cfs_for_each_possible_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		cfs_tcd_for_each_type_lock(tcd, i, cpu) {
 			list_splice_init(&tcd->tcd_pages, &pc->pc_pages);
 			tcd->tcd_cur_pages = 0;
@@ -562,7 +562,7 @@ static void put_pages_back_on_all_cpus(struct page_collection *pc)
 	int i, cpu;
 
 	spin_lock(&pc->pc_lock);
-	cfs_for_each_possible_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		cfs_tcd_for_each_type_lock(tcd, i, cpu) {
 			cur_head = tcd->tcd_pages.next;
 
@@ -630,7 +630,7 @@ static void put_pages_on_daemon_list(struct page_collection *pc)
 	struct cfs_trace_cpu_data *tcd;
 	int i, cpu;
 
-	cfs_for_each_possible_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		cfs_tcd_for_each_type_lock(tcd, i, cpu)
 			put_pages_on_tcd_daemon_list(pc, tcd);
 	}
@@ -1159,7 +1159,7 @@ static void trace_cleanup_on_all_cpus(void)
 	struct cfs_trace_page *tmp;
 	int i, cpu;
 
-	cfs_for_each_possible_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		cfs_tcd_for_each_type_lock(tcd, i, cpu) {
 			tcd->tcd_shutting_down = 1;
 
diff --git a/drivers/staging/lustre/lustre/libcfs/upcall_cache.c b/drivers/staging/lustre/lustre/libcfs/upcall_cache.c
index 18c68c3..245b46f 100644
--- a/drivers/staging/lustre/lustre/libcfs/upcall_cache.c
+++ b/drivers/staging/lustre/lustre/libcfs/upcall_cache.c
@@ -152,7 +152,6 @@ struct upcall_cache_entry *upcall_cache_get_entry(struct upcall_cache *cache,
 	struct list_head *head;
 	wait_queue_t wait;
 	int rc, found;
-	ENTRY;
 
 	LASSERT(cache);
 
@@ -176,7 +175,7 @@ find_again:
 			new = alloc_entry(cache, key, args);
 			if (!new) {
 				CERROR("fail to alloc entry\n");
-				RETURN(ERR_PTR(-ENOMEM));
+				return ERR_PTR(-ENOMEM);
 			}
 			goto find_again;
 		} else {
@@ -266,17 +265,14 @@ find_again:
 	/* Now we know it's good */
 out:
 	spin_unlock(&cache->uc_lock);
-	RETURN(entry);
+	return entry;
 }
 EXPORT_SYMBOL(upcall_cache_get_entry);
 
 void upcall_cache_put_entry(struct upcall_cache *cache,
 			    struct upcall_cache_entry *entry)
 {
-	ENTRY;
-
 	if (!entry) {
-		EXIT;
 		return;
 	}
 
@@ -284,7 +280,6 @@ void upcall_cache_put_entry(struct upcall_cache *cache,
 	spin_lock(&cache->uc_lock);
 	put_entry(cache, entry);
 	spin_unlock(&cache->uc_lock);
-	EXIT;
 }
 EXPORT_SYMBOL(upcall_cache_put_entry);
 
@@ -294,7 +289,6 @@ int upcall_cache_downcall(struct upcall_cache *cache, __u32 err, __u64 key,
 	struct upcall_cache_entry *entry = NULL;
 	struct list_head *head;
 	int found = 0, rc = 0;
-	ENTRY;
 
 	LASSERT(cache);
 
@@ -314,7 +308,7 @@ int upcall_cache_downcall(struct upcall_cache *cache, __u32 err, __u64 key,
 		       cache->uc_name, key);
 		/* haven't found, it's possible */
 		spin_unlock(&cache->uc_lock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (err) {
@@ -356,7 +350,7 @@ out:
 	wake_up_all(&entry->ue_waitq);
 	put_entry(cache, entry);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(upcall_cache_downcall);
 
@@ -364,7 +358,6 @@ static void cache_flush(struct upcall_cache *cache, int force)
 {
 	struct upcall_cache_entry *entry, *next;
 	int i;
-	ENTRY;
 
 	spin_lock(&cache->uc_lock);
 	for (i = 0; i < UC_CACHE_HASH_SIZE; i++) {
@@ -379,7 +372,6 @@ static void cache_flush(struct upcall_cache *cache, int force)
 		}
 	}
 	spin_unlock(&cache->uc_lock);
-	EXIT;
 }
 
 void upcall_cache_flush_idle(struct upcall_cache *cache)
@@ -399,7 +391,6 @@ void upcall_cache_flush_one(struct upcall_cache *cache, __u64 key, void *args)
 	struct list_head *head;
 	struct upcall_cache_entry *entry;
 	int found = 0;
-	ENTRY;
 
 	head = &cache->uc_hashtable[UC_CACHE_HASH_INDEX(key)];
 
@@ -431,11 +422,10 @@ struct upcall_cache *upcall_cache_init(const char *name, const char *upcall,
 {
 	struct upcall_cache *cache;
 	int i;
-	ENTRY;
 
 	LIBCFS_ALLOC(cache, sizeof(*cache));
 	if (!cache)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	spin_lock_init(&cache->uc_lock);
 	rwlock_init(&cache->uc_upcall_rwlock);
@@ -448,7 +438,7 @@ struct upcall_cache *upcall_cache_init(const char *name, const char *upcall,
 	cache->uc_acquire_expire = 30;
 	cache->uc_ops = ops;
 
-	RETURN(cache);
+	return cache;
 }
 EXPORT_SYMBOL(upcall_cache_init);
 
diff --git a/drivers/staging/lustre/lustre/libcfs/watchdog.c b/drivers/staging/lustre/lustre/libcfs/watchdog.c
deleted file mode 100644
index 7c385ad..0000000
--- a/drivers/staging/lustre/lustre/libcfs/watchdog.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/libcfs/watchdog.c
- *
- * Author: Jacob Berkman <jacob@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include <linux/libcfs/libcfs.h>
-#include "tracefile.h"
-
-struct lc_watchdog {
-	spinlock_t  lcw_lock;     /* check or change lcw_list */
-	int	     lcw_refcount; /* must hold lcw_pending_timers_lock */
-	timer_list_t     lcw_timer;    /* kernel timer */
-	struct list_head      lcw_list;     /* chain on pending list */
-	cfs_time_t      lcw_last_touched; /* last touched stamp */
-	task_t     *lcw_task;     /* owner task */
-	void	  (*lcw_callback)(pid_t, void *);
-	void	   *lcw_data;
-
-	pid_t	   lcw_pid;
-
-	enum {
-		LC_WATCHDOG_DISABLED,
-		LC_WATCHDOG_ENABLED,
-		LC_WATCHDOG_EXPIRED
-	} lcw_state;
-};
-
-#ifdef WITH_WATCHDOG
-/*
- * The dispatcher will complete lcw_start_completion when it starts,
- * and lcw_stop_completion when it exits.
- * Wake lcw_event_waitq to signal timer callback dispatches.
- */
-static struct completion lcw_start_completion;
-static struct completion  lcw_stop_completion;
-static wait_queue_head_t lcw_event_waitq;
-
-/*
- * Set this and wake lcw_event_waitq to stop the dispatcher.
- */
-enum {
-	LCW_FLAG_STOP = 0
-};
-static unsigned long lcw_flags = 0;
-
-/*
- * Number of outstanding watchdogs.
- * When it hits 1, we start the dispatcher.
- * When it hits 0, we stop the dispatcher.
- */
-static __u32	 lcw_refcount = 0;
-static DEFINE_MUTEX(lcw_refcount_mutex);
-
-/*
- * List of timers that have fired that need their callbacks run by the
- * dispatcher.
- */
-/* BH lock! */
-static DEFINE_SPINLOCK(lcw_pending_timers_lock);
-static struct list_head lcw_pending_timers = LIST_HEAD_INIT(lcw_pending_timers);
-
-/* Last time a watchdog expired */
-static cfs_time_t lcw_last_watchdog_time;
-static int lcw_recent_watchdog_count;
-
-static void
-lcw_dump(struct lc_watchdog *lcw)
-{
-	ENTRY;
-	rcu_read_lock();
-       if (lcw->lcw_task == NULL) {
-		LCONSOLE_WARN("Process " LPPID " was not found in the task "
-			      "list; watchdog callback may be incomplete\n",
-			      (int)lcw->lcw_pid);
-	} else {
-		libcfs_debug_dumpstack(lcw->lcw_task);
-	}
-
-	rcu_read_unlock();
-	EXIT;
-}
-
-static void lcw_cb(ulong_ptr_t data)
-{
-	struct lc_watchdog *lcw = (struct lc_watchdog *)data;
-	ENTRY;
-
-	if (lcw->lcw_state != LC_WATCHDOG_ENABLED) {
-		EXIT;
-		return;
-	}
-
-	lcw->lcw_state = LC_WATCHDOG_EXPIRED;
-
-	spin_lock_bh(&lcw->lcw_lock);
-	LASSERT(list_empty(&lcw->lcw_list));
-
-	spin_lock_bh(&lcw_pending_timers_lock);
-	lcw->lcw_refcount++; /* +1 for pending list */
-	list_add(&lcw->lcw_list, &lcw_pending_timers);
-	wake_up(&lcw_event_waitq);
-
-	spin_unlock_bh(&lcw_pending_timers_lock);
-	spin_unlock_bh(&lcw->lcw_lock);
-	EXIT;
-}
-
-static int is_watchdog_fired(void)
-{
-	int rc;
-
-	if (test_bit(LCW_FLAG_STOP, &lcw_flags))
-		return 1;
-
-	spin_lock_bh(&lcw_pending_timers_lock);
-	rc = !list_empty(&lcw_pending_timers);
-	spin_unlock_bh(&lcw_pending_timers_lock);
-	return rc;
-}
-
-static void lcw_dump_stack(struct lc_watchdog *lcw)
-{
-	cfs_time_t      current_time;
-	cfs_duration_t  delta_time;
-	struct timeval  timediff;
-
-	current_time = cfs_time_current();
-	delta_time = cfs_time_sub(current_time, lcw->lcw_last_touched);
-	cfs_duration_usec(delta_time, &timediff);
-
-	/*
-	 * Check to see if we should throttle the watchdog timer to avoid
-	 * too many dumps going to the console thus triggering an NMI.
-	 */
-	delta_time = cfs_duration_sec(cfs_time_sub(current_time,
-						   lcw_last_watchdog_time));
-
-	if (delta_time < libcfs_watchdog_ratelimit &&
-	    lcw_recent_watchdog_count > 3) {
-		LCONSOLE_WARN("Service thread pid %u was inactive for "
-			      "%lu.%.02lus. Watchdog stack traces are limited "
-			      "to 3 per %d seconds, skipping this one.\n",
-			      (int)lcw->lcw_pid,
-			      timediff.tv_sec,
-			      timediff.tv_usec / 10000,
-			      libcfs_watchdog_ratelimit);
-	} else {
-		if (delta_time < libcfs_watchdog_ratelimit) {
-			lcw_recent_watchdog_count++;
-		} else {
-			memcpy(&lcw_last_watchdog_time, &current_time,
-			       sizeof(current_time));
-			lcw_recent_watchdog_count = 0;
-		}
-
-		LCONSOLE_WARN("Service thread pid %u was inactive for "
-			      "%lu.%.02lus. The thread might be hung, or it "
-			      "might only be slow and will resume later. "
-			      "Dumping the stack trace for debugging purposes:"
-			      "\n",
-			      (int)lcw->lcw_pid,
-			      timediff.tv_sec,
-			      timediff.tv_usec / 10000);
-		lcw_dump(lcw);
-	}
-}
-
-static int lcw_dispatch_main(void *data)
-{
-	int		 rc = 0;
-	struct lc_watchdog *lcw;
-	LIST_HEAD      (zombies);
-
-	ENTRY;
-
-	complete(&lcw_start_completion);
-
-	while (1) {
-		int dumplog = 1;
-
-		cfs_wait_event_interruptible(lcw_event_waitq,
-					     is_watchdog_fired(), rc);
-		CDEBUG(D_INFO, "Watchdog got woken up...\n");
-		if (test_bit(LCW_FLAG_STOP, &lcw_flags)) {
-			CDEBUG(D_INFO, "LCW_FLAG_STOP set, shutting down...\n");
-
-			spin_lock_bh(&lcw_pending_timers_lock);
-			rc = !list_empty(&lcw_pending_timers);
-			spin_unlock_bh(&lcw_pending_timers_lock);
-			if (rc) {
-				CERROR("pending timers list was not empty at "
-				       "time of watchdog dispatch shutdown\n");
-			}
-			break;
-		}
-
-		spin_lock_bh(&lcw_pending_timers_lock);
-		while (!list_empty(&lcw_pending_timers)) {
-			int is_dumplog;
-
-			lcw = list_entry(lcw_pending_timers.next,
-					     struct lc_watchdog, lcw_list);
-			/* +1 ref for callback to make sure lwc wouldn't be
-			 * deleted after releasing lcw_pending_timers_lock */
-			lcw->lcw_refcount++;
-			spin_unlock_bh(&lcw_pending_timers_lock);
-
-			/* lock ordering */
-			spin_lock_bh(&lcw->lcw_lock);
-			spin_lock_bh(&lcw_pending_timers_lock);
-
-			if (list_empty(&lcw->lcw_list)) {
-				/* already removed from pending list */
-				lcw->lcw_refcount--; /* -1 ref for callback */
-				if (lcw->lcw_refcount == 0)
-					list_add(&lcw->lcw_list, &zombies);
-				spin_unlock_bh(&lcw->lcw_lock);
-				/* still hold lcw_pending_timers_lock */
-				continue;
-			}
-
-			list_del_init(&lcw->lcw_list);
-			lcw->lcw_refcount--; /* -1 ref for pending list */
-
-			spin_unlock_bh(&lcw_pending_timers_lock);
-			spin_unlock_bh(&lcw->lcw_lock);
-
-			CDEBUG(D_INFO, "found lcw for pid " LPPID "\n",
-			       lcw->lcw_pid);
-			lcw_dump_stack(lcw);
-
-			is_dumplog = lcw->lcw_callback == lc_watchdog_dumplog;
-			if (lcw->lcw_state != LC_WATCHDOG_DISABLED &&
-			    (dumplog || !is_dumplog)) {
-				lcw->lcw_callback(lcw->lcw_pid, lcw->lcw_data);
-				if (dumplog && is_dumplog)
-					dumplog = 0;
-			}
-
-			spin_lock_bh(&lcw_pending_timers_lock);
-			lcw->lcw_refcount--; /* -1 ref for callback */
-			if (lcw->lcw_refcount == 0)
-				list_add(&lcw->lcw_list, &zombies);
-		}
-		spin_unlock_bh(&lcw_pending_timers_lock);
-
-		while (!list_empty(&zombies)) {
-			lcw = list_entry(lcw_pending_timers.next,
-					 struct lc_watchdog, lcw_list);
-			list_del(&lcw->lcw_list);
-			LIBCFS_FREE(lcw, sizeof(*lcw));
-		}
-	}
-
-	complete(&lcw_stop_completion);
-
-	RETURN(rc);
-}
-
-static void lcw_dispatch_start(void)
-{
-	task_t *task;
-
-	ENTRY;
-	LASSERT(lcw_refcount == 1);
-
-	init_completion(&lcw_stop_completion);
-	init_completion(&lcw_start_completion);
-	init_waitqueue_head(&lcw_event_waitq);
-
-	CDEBUG(D_INFO, "starting dispatch thread\n");
-	task = kthread_run(lcw_dispatch_main, NULL, "lc_watchdogd");
-	if (IS_ERR(task)) {
-		CERROR("error spawning watchdog dispatch thread: %ld\n",
-			PTR_ERR(task));
-		EXIT;
-		return;
-	}
-	wait_for_completion(&lcw_start_completion);
-	CDEBUG(D_INFO, "watchdog dispatcher initialization complete.\n");
-
-	EXIT;
-}
-
-static void lcw_dispatch_stop(void)
-{
-	ENTRY;
-	LASSERT(lcw_refcount == 0);
-
-	CDEBUG(D_INFO, "trying to stop watchdog dispatcher.\n");
-
-	set_bit(LCW_FLAG_STOP, &lcw_flags);
-	wake_up(&lcw_event_waitq);
-
-	wait_for_completion(&lcw_stop_completion);
-
-	CDEBUG(D_INFO, "watchdog dispatcher has shut down.\n");
-
-	EXIT;
-}
-
-struct lc_watchdog *lc_watchdog_add(int timeout,
-				    void (*callback)(pid_t, void *),
-				    void *data)
-{
-	struct lc_watchdog *lcw = NULL;
-	ENTRY;
-
-	LIBCFS_ALLOC(lcw, sizeof(*lcw));
-	if (lcw == NULL) {
-		CDEBUG(D_INFO, "Could not allocate new lc_watchdog\n");
-		RETURN(ERR_PTR(-ENOMEM));
-	}
-
-	spin_lock_init(&lcw->lcw_lock);
-	lcw->lcw_refcount = 1; /* refcount for owner */
-	lcw->lcw_task     = current;
-	lcw->lcw_pid      = current_pid();
-	lcw->lcw_callback = (callback != NULL) ? callback : lc_watchdog_dumplog;
-	lcw->lcw_data     = data;
-	lcw->lcw_state    = LC_WATCHDOG_DISABLED;
-
-	INIT_LIST_HEAD(&lcw->lcw_list);
-	cfs_timer_init(&lcw->lcw_timer, lcw_cb, lcw);
-
-	mutex_lock(&lcw_refcount_mutex);
-	if (++lcw_refcount == 1)
-		lcw_dispatch_start();
-	mutex_unlock(&lcw_refcount_mutex);
-
-	/* Keep this working in case we enable them by default */
-	if (lcw->lcw_state == LC_WATCHDOG_ENABLED) {
-		lcw->lcw_last_touched = cfs_time_current();
-		cfs_timer_arm(&lcw->lcw_timer, cfs_time_seconds(timeout) +
-			      cfs_time_current());
-	}
-
-	RETURN(lcw);
-}
-EXPORT_SYMBOL(lc_watchdog_add);
-
-static void lcw_update_time(struct lc_watchdog *lcw, const char *message)
-{
-	cfs_time_t newtime = cfs_time_current();;
-
-	if (lcw->lcw_state == LC_WATCHDOG_EXPIRED) {
-		struct timeval timediff;
-		cfs_time_t delta_time = cfs_time_sub(newtime,
-						     lcw->lcw_last_touched);
-		cfs_duration_usec(delta_time, &timediff);
-
-		LCONSOLE_WARN("Service thread pid %u %s after %lu.%.02lus. "
-			      "This indicates the system was overloaded (too "
-			      "many service threads, or there were not enough "
-			      "hardware resources).\n",
-			      lcw->lcw_pid,
-			      message,
-			      timediff.tv_sec,
-			      timediff.tv_usec / 10000);
-	}
-	lcw->lcw_last_touched = newtime;
-}
-
-static void lc_watchdog_del_pending(struct lc_watchdog *lcw)
-{
-	spin_lock_bh(&lcw->lcw_lock);
-	if (unlikely(!list_empty(&lcw->lcw_list))) {
-		spin_lock_bh(&lcw_pending_timers_lock);
-		list_del_init(&lcw->lcw_list);
-		lcw->lcw_refcount--; /* -1 ref for pending list */
-		spin_unlock_bh(&lcw_pending_timers_lock);
-	}
-
-	spin_unlock_bh(&lcw->lcw_lock);
-}
-
-void lc_watchdog_touch(struct lc_watchdog *lcw, int timeout)
-{
-	ENTRY;
-	LASSERT(lcw != NULL);
-
-	lc_watchdog_del_pending(lcw);
-
-	lcw_update_time(lcw, "resumed");
-	lcw->lcw_state = LC_WATCHDOG_ENABLED;
-
-	cfs_timer_arm(&lcw->lcw_timer, cfs_time_current() +
-		      cfs_time_seconds(timeout));
-
-	EXIT;
-}
-EXPORT_SYMBOL(lc_watchdog_touch);
-
-void lc_watchdog_disable(struct lc_watchdog *lcw)
-{
-	ENTRY;
-	LASSERT(lcw != NULL);
-
-	lc_watchdog_del_pending(lcw);
-
-	lcw_update_time(lcw, "completed");
-	lcw->lcw_state = LC_WATCHDOG_DISABLED;
-
-	EXIT;
-}
-EXPORT_SYMBOL(lc_watchdog_disable);
-
-void lc_watchdog_delete(struct lc_watchdog *lcw)
-{
-	int dead;
-
-	ENTRY;
-	LASSERT(lcw != NULL);
-
-	cfs_timer_disarm(&lcw->lcw_timer);
-
-	lcw_update_time(lcw, "stopped");
-
-	spin_lock_bh(&lcw->lcw_lock);
-	spin_lock_bh(&lcw_pending_timers_lock);
-	if (unlikely(!list_empty(&lcw->lcw_list))) {
-		list_del_init(&lcw->lcw_list);
-		lcw->lcw_refcount--; /* -1 ref for pending list */
-	}
-
-	lcw->lcw_refcount--; /* -1 ref for owner */
-	dead = lcw->lcw_refcount == 0;
-	spin_unlock_bh(&lcw_pending_timers_lock);
-	spin_unlock_bh(&lcw->lcw_lock);
-
-	if (dead)
-		LIBCFS_FREE(lcw, sizeof(*lcw));
-
-	mutex_lock(&lcw_refcount_mutex);
-	if (--lcw_refcount == 0)
-		lcw_dispatch_stop();
-	mutex_unlock(&lcw_refcount_mutex);
-
-	EXIT;
-}
-EXPORT_SYMBOL(lc_watchdog_delete);
-
-/*
- * Provided watchdog handlers
- */
-
-void lc_watchdog_dumplog(pid_t pid, void *data)
-{
-	libcfs_debug_dumplog_internal((void *)((long_ptr_t)pid));
-}
-EXPORT_SYMBOL(lc_watchdog_dumplog);
-
-#else   /* !defined(WITH_WATCHDOG) */
-
-struct lc_watchdog *lc_watchdog_add(int timeout,
-				    void (*callback)(pid_t pid, void *),
-				    void *data)
-{
-	static struct lc_watchdog      watchdog;
-	return &watchdog;
-}
-EXPORT_SYMBOL(lc_watchdog_add);
-
-void lc_watchdog_touch(struct lc_watchdog *lcw, int timeout)
-{
-}
-EXPORT_SYMBOL(lc_watchdog_touch);
-
-void lc_watchdog_disable(struct lc_watchdog *lcw)
-{
-}
-EXPORT_SYMBOL(lc_watchdog_disable);
-
-void lc_watchdog_delete(struct lc_watchdog *lcw)
-{
-}
-EXPORT_SYMBOL(lc_watchdog_delete);
-
-#endif
diff --git a/drivers/staging/lustre/lustre/libcfs/workitem.c b/drivers/staging/lustre/lustre/libcfs/workitem.c
index b533666..462172d 100644
--- a/drivers/staging/lustre/lustre/libcfs/workitem.c
+++ b/drivers/staging/lustre/lustre/libcfs/workitem.c
@@ -376,7 +376,8 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
 	rc = 0;
 	while (nthrs > 0)  {
 		char	name[16];
-		task_t	*task;
+		struct task_struct *task;
+
 		spin_lock(&cfs_wi_data.wi_glock);
 		while (sched->ws_starting > 0) {
 			spin_unlock(&cfs_wi_data.wi_glock);
diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile
index dff0c04..f493e07 100644
--- a/drivers/staging/lustre/lustre/llite/Makefile
+++ b/drivers/staging/lustre/lustre/llite/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_LUSTRE_FS) += lustre.o
-obj-$(CONFIG_LUSTRE_FS) += llite_lloop.o
+obj-$(CONFIG_LUSTRE_LLITE_LLOOP) += llite_lloop.o
 lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \
 	    rw.o lproc_llite.o namei.o symlink.o llite_mmap.o \
 	    xattr.o remote_perm.o llite_rmtacl.o llite_capa.o \
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c
index ff0d085..e7629be 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -59,11 +59,11 @@ static void free_dentry_data(struct rcu_head *head)
 static void ll_release(struct dentry *de)
 {
 	struct ll_dentry_data *lld;
-	ENTRY;
+
 	LASSERT(de != NULL);
 	lld = ll_d2d(de);
 	if (lld == NULL) /* NFS copies the de->d_op methods (bug 4655) */
-		RETURN_EXIT;
+		return;
 
 	if (lld->lld_it) {
 		ll_intent_release(lld->lld_it);
@@ -73,8 +73,6 @@ static void ll_release(struct dentry *de)
 	LASSERT(lld->lld_mnt_count == 0);
 	de->d_fsdata = NULL;
 	call_rcu(&lld->lld_rcu_head, free_dentry_data);
-
-	EXIT;
 }
 
 /* Compare if two dentries are the same.  Don't match if the existing dentry
@@ -84,17 +82,14 @@ static void ll_release(struct dentry *de)
  * an AST before calling d_revalidate_it().  The dentry still exists (marked
  * INVALID) so d_lookup() matches it, but we have no lock on it (so
  * lock_match() fails) and we spin around real_lookup(). */
-int ll_dcompare(const struct dentry *parent, const struct inode *pinode,
-		const struct dentry *dentry, const struct inode *inode,
+int ll_dcompare(const struct dentry *parent, const struct dentry *dentry,
 		unsigned int len, const char *str, const struct qstr *name)
 {
-	ENTRY;
-
 	if (len != name->len)
-		RETURN(1);
+		return 1;
 
 	if (memcmp(str, name->name, len))
-		RETURN(1);
+		return 1;
 
 	CDEBUG(D_DENTRY, "found name %.*s(%p) flags %#x refc %d\n",
 	       name->len, name->name, dentry, dentry->d_flags,
@@ -102,12 +97,12 @@ int ll_dcompare(const struct dentry *parent, const struct inode *pinode,
 
 	/* mountpoint is always valid */
 	if (d_mountpoint((struct dentry *)dentry))
-		RETURN(0);
+		return 0;
 
 	if (d_lustre_invalid(dentry))
-		RETURN(1);
+		return 1;
 
-	RETURN(0);
+	return 0;
 }
 
 static inline int return_if_equal(struct ldlm_lock *lock, void *data)
@@ -128,22 +123,21 @@ static int find_cbdata(struct inode *inode)
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct lov_stripe_md *lsm;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(inode);
 	rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode),
 			    return_if_equal, NULL);
 	if (rc != 0)
-		 RETURN(rc);
+		 return rc;
 
 	lsm = ccc_inode_lsm_get(inode);
 	if (lsm == NULL)
-		RETURN(rc);
+		return rc;
 
 	rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL);
 	ccc_inode_lsm_put(inode, lsm);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -155,7 +149,6 @@ static int find_cbdata(struct inode *inode)
  */
 static int ll_ddelete(const struct dentry *de)
 {
-	ENTRY;
 	LASSERT(de);
 
 	CDEBUG(D_DENTRY, "%s dentry %.*s (%p, parent %p, inode %p) %s%s\n",
@@ -179,13 +172,12 @@ static int ll_ddelete(const struct dentry *de)
 #endif
 
 	if (d_lustre_invalid((struct dentry *)de))
-		RETURN(1);
-	RETURN(0);
+		return 1;
+	return 0;
 }
 
 static int ll_set_dd(struct dentry *de)
 {
-	ENTRY;
 	LASSERT(de != NULL);
 
 	CDEBUG(D_DENTRY, "ldd on dentry %.*s (%p) parent %p inode %p refc %d\n",
@@ -204,11 +196,11 @@ static int ll_set_dd(struct dentry *de)
 				OBD_FREE_PTR(lld);
 			spin_unlock(&de->d_lock);
 		} else {
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int ll_dops_init(struct dentry *de, int block, int init_sa)
@@ -260,8 +252,6 @@ void ll_intent_drop_lock(struct lookup_intent *it)
 
 void ll_intent_release(struct lookup_intent *it)
 {
-	ENTRY;
-
 	CDEBUG(D_INFO, "intent %p released\n", it);
 	ll_intent_drop_lock(it);
 	/* We are still holding extra reference on a request, need to free it */
@@ -275,14 +265,12 @@ void ll_intent_release(struct lookup_intent *it)
 
 	it->d.lustre.it_disposition = 0;
 	it->d.lustre.it_data = NULL;
-	EXIT;
 }
 
 void ll_invalidate_aliases(struct inode *inode)
 {
 	struct dentry *dentry;
 	struct ll_d_hlist_node *p;
-	ENTRY;
 
 	LASSERT(inode != NULL);
 
@@ -296,18 +284,17 @@ void ll_invalidate_aliases(struct inode *inode)
 		       dentry->d_name.name, dentry, dentry->d_parent,
 		       dentry->d_inode, dentry->d_flags);
 
-		if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') {
-			CERROR("called on root (?) dentry=%p, inode=%p "
-			       "ino=%lu\n", dentry, inode, inode->i_ino);
+		if (unlikely(dentry == dentry->d_sb->s_root)) {
+			CERROR("%s: called on root dentry=%p, fid="DFID"\n",
+			       ll_get_fsname(dentry->d_sb, NULL, 0),
+			       dentry, PFID(ll_inode2fid(inode)));
 			lustre_dump_dentry(dentry, 1);
-			libcfs_debug_dumpstack(NULL);
+			dump_stack();
 		}
 
 		d_lustre_invalidate(dentry, 0);
 	}
 	ll_unlock_dcache(inode);
-
-	EXIT;
 }
 
 int ll_revalidate_it_finish(struct ptlrpc_request *request,
@@ -315,17 +302,16 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
 			    struct dentry *de)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (!request)
-		RETURN(0);
+		return 0;
 
 	if (it_disposition(it, DISP_LOOKUP_NEG))
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	rc = ll_prep_inode(&de->d_inode, request, NULL, it);
 
-	RETURN(rc);
+	return rc;
 }
 
 void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry)
@@ -370,7 +356,6 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
 	struct inode *parent = de->d_parent->d_inode;
 	int rc;
 
-	ENTRY;
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
 	       LL_IT2STR(it));
 
@@ -383,10 +368,10 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
 		   away this negative dentry and actually do the request to
 		   kernel to create whatever needs to be created (if possible)*/
 		if (it && (it->it_op & IT_CREAT))
-			RETURN(0);
+			return 0;
 
 		if (d_lustre_invalid(de))
-			RETURN(0);
+			return 0;
 
 		ibits = MDS_INODELOCK_UPDATE;
 		rc = ll_have_md_lock(parent, &ibits, LCK_MINMODE);
@@ -413,7 +398,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
 	LASSERT(it);
 
 	if (it->it_op == IT_LOOKUP && !d_lustre_invalid(de))
-		RETURN(1);
+		return 1;
 
 	if (it->it_op == IT_OPEN) {
 		struct inode *inode = de->d_inode;
@@ -460,7 +445,7 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags,
 			   if it would be, we'll reopen the open request to
 			   MDS later during file open path */
 			mutex_unlock(&lli->lli_och_mutex);
-			RETURN(1);
+			return 1;
 		} else {
 			mutex_unlock(&lli->lli_och_mutex);
 		}
@@ -479,7 +464,7 @@ do_lock:
 				     de->d_name.name, de->d_name.len,
 				     0, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	if (!IS_POSIXACL(parent) || !exp_connect_umask(exp))
 		it->it_create_mode &= ~current_umask();
@@ -566,7 +551,7 @@ out:
 mark:
 	if (it != NULL && it->it_op == IT_GETATTR && rc > 0)
 		ll_statahead_mark(parent, de);
-	RETURN(rc);
+	return rc;
 
 	/*
 	 * This part is here to combat evil-evil race in real_lookup on 2.6
@@ -598,7 +583,7 @@ do_lookup:
 							 LUSTRE_OPC_CREATE :
 							 LUSTRE_OPC_ANY), NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	rc = md_intent_lock(exp, op_data, NULL, 0,  it, 0, &req,
 			    ll_md_blocking_ast, 0);
@@ -639,14 +624,13 @@ int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
 	struct inode *parent = dentry->d_parent->d_inode;
 	int unplug = 0;
 
-	ENTRY;
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%s,flags=%u\n",
 	       dentry->d_name.name, flags);
 
 	if (!(flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) &&
 	    ll_need_statahead(parent, dentry) > 0) {
 		if (flags & LOOKUP_RCU)
-			RETURN(-ECHILD);
+			return -ECHILD;
 
 		if (dentry->d_inode == NULL)
 			unplug = 1;
@@ -654,7 +638,7 @@ int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
 		ll_statahead_mark(parent, dentry);
 	}
 
-	RETURN(1);
+	return 1;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 23c61fe..09844be 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -41,14 +41,13 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/mm.h>
-#include <linux/version.h>
 #include <asm/uaccess.h>
 #include <linux/buffer_head.h>   // for wait_on_buffer
 #include <linux/pagevec.h>
+#include <linux/prefetch.h>
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre/lustre_idl.h>
 #include <obd_support.h>
 #include <obd_class.h>
 #include <lustre_lib.h>
@@ -158,7 +157,6 @@ static int ll_dir_filler(void *_hash, struct page *page0)
 	int npages;
 	int i;
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) hash "LPU64"\n",
 	       inode->i_ino, inode->i_generation, inode, hash);
@@ -239,7 +237,6 @@ static int ll_dir_filler(void *_hash, struct page *page0)
 
 	if (page_pool != &page0)
 		OBD_FREE(page_pool, sizeof(struct page *) * max_pages);
-	EXIT;
 	return rc;
 }
 
@@ -355,15 +352,12 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash,
 	rc = md_lock_match(ll_i2sbi(dir)->ll_md_exp, LDLM_FL_BLOCK_GRANTED,
 			   ll_inode2fid(dir), LDLM_IBITS, &policy, mode, &lockh);
 	if (!rc) {
-		struct ldlm_enqueue_info einfo = {.ei_type = LDLM_IBITS,
-						  .ei_mode = mode,
-						  .ei_cb_bl =
-						  ll_md_blocking_ast,
-						  .ei_cb_cp =
-						  ldlm_completion_ast,
-						  .ei_cb_gl = NULL,
-						  .ei_cb_wg = NULL,
-						  .ei_cbdata = NULL};
+		struct ldlm_enqueue_info einfo = {
+			.ei_type = LDLM_IBITS,
+			.ei_mode = mode,
+			.ei_cb_bl = ll_md_blocking_ast,
+			.ei_cb_cp = ldlm_completion_ast,
+		};
 		struct lookup_intent it = { .it_op = IT_READDIR };
 		struct ptlrpc_request *request;
 		struct md_op_data *op_data;
@@ -482,19 +476,17 @@ fail:
 	goto out_unlock;
 }
 
-int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie,
-		filldir_t filldir)
+int ll_dir_read(struct inode *inode, struct dir_context *ctx)
 {
 	struct ll_inode_info *info       = ll_i2info(inode);
 	struct ll_sb_info    *sbi	= ll_i2sbi(inode);
-	__u64		 pos	= *_pos;
+	__u64		   pos		= ctx->pos;
 	int		   api32      = ll_need_32bit_api(sbi);
 	int		   hash64     = sbi->ll_flags & LL_SBI_64BIT_HASH;
 	struct page	  *page;
 	struct ll_dir_chain   chain;
 	int		   done = 0;
 	int		   rc = 0;
-	ENTRY;
 
 	ll_dir_chain_init(&chain);
 
@@ -547,12 +539,14 @@ int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie,
 				fid_le_to_cpu(&fid, &ent->lde_fid);
 				ino = cl_fid_build_ino(&fid, api32);
 				type = ll_dirent_type_get(ent);
+				ctx->pos = lhash;
 				/* For 'll_nfs_get_name_filldir()', it will try
 				 * to access the 'ent' through its 'lde_name',
-				 * so the parameter 'name' for 'filldir()' must
-				 * be part of the 'ent'. */
-				done = filldir(cookie, ent->lde_name, namelen,
-					       lhash, ino, type);
+				 * so the parameter 'name' for 'ctx->actor()'
+				 * must be part of the 'ent'.
+				 */
+				done = !dir_emit(ctx, ent->lde_name,
+						 namelen, ino, type);
 			}
 			next = le64_to_cpu(dp->ldp_hash_end);
 			if (!done) {
@@ -593,56 +587,49 @@ int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie,
 		}
 	}
 
-	*_pos = pos;
+	ctx->pos = pos;
 	ll_dir_chain_fini(&chain);
-	RETURN(rc);
+	return rc;
 }
 
-static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir)
+static int ll_readdir(struct file *filp, struct dir_context *ctx)
 {
 	struct inode		*inode	= filp->f_dentry->d_inode;
 	struct ll_file_data	*lfd	= LUSTRE_FPRIVATE(filp);
 	struct ll_sb_info	*sbi	= ll_i2sbi(inode);
-	__u64			pos	= lfd->lfd_pos;
 	int			hash64	= sbi->ll_flags & LL_SBI_64BIT_HASH;
 	int			api32	= ll_need_32bit_api(sbi);
 	int			rc;
-	struct path		path;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %lu/%llu "
 	       " 32bit_api %d\n", inode->i_ino, inode->i_generation,
-	       inode, (unsigned long)pos, i_size_read(inode), api32);
+	       inode, (unsigned long)lfd->lfd_pos, i_size_read(inode), api32);
 
-	if (pos == MDS_DIR_END_OFF)
+	if (lfd->lfd_pos == MDS_DIR_END_OFF)
 		/*
 		 * end-of-file.
 		 */
 		GOTO(out, rc = 0);
 
-	rc = ll_dir_read(inode, &pos, cookie, filldir);
-	lfd->lfd_pos = pos;
-	if (pos == MDS_DIR_END_OFF) {
+	ctx->pos = lfd->lfd_pos;
+	rc = ll_dir_read(inode, ctx);
+	lfd->lfd_pos = ctx->pos;
+	if (ctx->pos == MDS_DIR_END_OFF) {
 		if (api32)
-			filp->f_pos = LL_DIR_END_OFF_32BIT;
+			ctx->pos = LL_DIR_END_OFF_32BIT;
 		else
-			filp->f_pos = LL_DIR_END_OFF;
+			ctx->pos = LL_DIR_END_OFF;
 	} else {
 		if (api32 && hash64)
-			filp->f_pos = pos >> 32;
-		else
-			filp->f_pos = pos;
+			ctx->pos >>= 32;
 	}
 	filp->f_version = inode->i_version;
-	path.mnt = filp->f_path.mnt;
-	path.dentry = filp->f_dentry;
-	touch_atime(&path);
 
 out:
 	if (!rc)
 		ll_stats_ops_tally(sbi, LPROC_LL_READDIR, 1);
 
-	RETURN(rc);
+	return rc;
 }
 
 int ll_send_mgc_param(struct obd_export *mgc, char *string)
@@ -673,8 +660,6 @@ int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump,
 	int mode;
 	int err;
 
-	ENTRY;
-
 	mode = (0755 & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask) | S_IFDIR;
 	op_data = ll_prep_md_op_data(NULL, dir, NULL, filename,
 				     strlen(filename), mode, LUSTRE_OPC_MKDIR,
@@ -684,7 +669,8 @@ int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump,
 
 	op_data->op_cli_flags |= CLI_SET_MEA;
 	err = md_create(sbi->ll_md_exp, op_data, lump, sizeof(*lump), mode,
-			current_fsuid(), current_fsgid(),
+			from_kuid(&init_user_ns, current_fsuid()),
+			from_kgid(&init_user_ns, current_fsgid()),
 			cfs_curproc_cap_pack(), 0, &request);
 	ll_finish_md_op_data(op_data);
 	if (err)
@@ -704,7 +690,6 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
 	struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
 	struct obd_device *mgc = lsi->lsi_mgc;
 	int lum_size;
-	ENTRY;
 
 	if (lump != NULL) {
 		/*
@@ -731,7 +716,7 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
 					" %#08x != %#08x nor %#08x\n",
 					lump->lmm_magic, LOV_USER_MAGIC_V1,
 					LOV_USER_MAGIC_V3);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		}
 	} else {
@@ -741,7 +726,7 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	if (lump != NULL && lump->lmm_magic == cpu_to_le32(LMV_USER_MAGIC))
 		op_data->op_cli_flags |= CLI_SET_MEA;
@@ -797,7 +782,7 @@ end:
 		if (param != NULL)
 			OBD_FREE(param, MGS_PARAM_MAXLEN);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp,
@@ -812,13 +797,13 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp,
 
 	rc = ll_get_max_mdsize(sbi, &lmmsize);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL,
 				     0, lmmsize, LUSTRE_OPC_ANY,
 				     NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
 	rc = md_getattr(sbi->ll_md_exp, op_data, &req);
@@ -878,12 +863,11 @@ int ll_get_mdt_idx(struct inode *inode)
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct md_op_data *op_data;
 	int rc, mdtidx;
-	ENTRY;
 
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0,
 				     0, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	op_data->op_flags |= MF_GET_MDT_IDX;
 	rc = md_getattr(sbi->ll_md_exp, op_data, NULL);
@@ -891,7 +875,7 @@ int ll_get_mdt_idx(struct inode *inode)
 	ll_finish_md_op_data(op_data);
 	if (rc < 0) {
 		CDEBUG(D_INFO, "md_getattr_name: %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 	return mdtidx;
 }
@@ -912,7 +896,6 @@ static int ll_ioc_copy_start(struct super_block *sb, struct hsm_copy *copy)
 	struct ll_sb_info		*sbi = ll_s2sbi(sb);
 	struct hsm_progress_kernel	 hpk;
 	int				 rc;
-	ENTRY;
 
 	/* Forge a hsm_progress based on data from copy. */
 	hpk.hpk_fid = copy->hc_hai.hai_fid;
@@ -962,7 +945,7 @@ progress:
 	rc = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk),
 			   &hpk, NULL);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -985,7 +968,6 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy)
 	struct ll_sb_info		*sbi = ll_s2sbi(sb);
 	struct hsm_progress_kernel	 hpk;
 	int				 rc;
-	ENTRY;
 
 	/* If you modify the logic here, also check llapi_hsm_copy_end(). */
 	/* Take care: copy->hc_hai.hai_action, len, gid and data are not
@@ -1062,7 +1044,7 @@ progress:
 	rc = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk),
 			   &hpk, NULL);
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1090,7 +1072,6 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 	int id = qctl->qc_id;
 	int valid = qctl->qc_valid;
 	int rc = 0;
-	ENTRY;
 
 	switch (cmd) {
 	case LUSTRE_Q_INVALIDATE:
@@ -1101,32 +1082,34 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 	case Q_SETINFO:
 		if (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
 		    sbi->ll_flags & LL_SBI_RMT_CLIENT)
-			RETURN(-EPERM);
+			return -EPERM;
 		break;
 	case Q_GETQUOTA:
-		if (((type == USRQUOTA && current_euid() != id) ||
-		     (type == GRPQUOTA && !in_egroup_p(id))) &&
+		if (((type == USRQUOTA &&
+		      uid_eq(current_euid(), make_kuid(&init_user_ns, id))) ||
+		     (type == GRPQUOTA &&
+		      !in_egroup_p(make_kgid(&init_user_ns, id)))) &&
 		    (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
 		     sbi->ll_flags & LL_SBI_RMT_CLIENT))
-			RETURN(-EPERM);
+			return -EPERM;
 		break;
 	case Q_GETINFO:
 		break;
 	default:
 		CERROR("unsupported quotactl op: %#x\n", cmd);
-		RETURN(-ENOTTY);
+		return -ENOTTY;
 	}
 
 	if (valid != QC_GENERAL) {
 		if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
-			RETURN(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 
 		if (cmd == Q_GETINFO)
 			qctl->qc_cmd = Q_GETOINFO;
 		else if (cmd == Q_GETQUOTA)
 			qctl->qc_cmd = Q_GETOQUOTA;
 		else
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		switch (valid) {
 		case QC_MDTIDX:
@@ -1151,7 +1134,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 		}
 
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		qctl->qc_cmd = cmd;
 	} else {
@@ -1159,7 +1142,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 
 		OBD_ALLOC_PTR(oqctl);
 		if (oqctl == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		QCTL_COPY(oqctl, qctl);
 		rc = obd_quotactl(sbi->ll_md_exp, oqctl);
@@ -1169,7 +1152,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
 				obd_quotactl(sbi->ll_md_exp, oqctl);
 			}
 			OBD_FREE_PTR(oqctl);
-			RETURN(rc);
+			return rc;
 		}
 		/* If QIF_SPACE is not set, client should collect the
 		 * space usage from OSSs by itself */
@@ -1216,7 +1199,7 @@ out:
 		OBD_FREE_PTR(oqctl);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static char *
@@ -1249,7 +1232,6 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct obd_ioctl_data *data;
 	int rc = 0;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), cmd=%#x\n",
 	       inode->i_ino, inode->i_generation, inode, cmd);
@@ -1262,10 +1244,10 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	switch(cmd) {
 	case FSFILT_IOC_GETFLAGS:
 	case FSFILT_IOC_SETFLAGS:
-		RETURN(ll_iocontrol(inode, file, cmd, arg));
+		return ll_iocontrol(inode, file, cmd, arg);
 	case FSFILT_IOC_GETVERSION_OLD:
 	case FSFILT_IOC_GETVERSION:
-		RETURN(put_user(inode->i_generation, (int *)arg));
+		return put_user(inode->i_generation, (int *)arg);
 	/* We need to special case any other ioctls we want to handle,
 	 * to send them to the MDS/OST as appropriate and to properly
 	 * network encode the arg field.
@@ -1277,10 +1259,10 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		mdtidx = ll_get_mdt_idx(inode);
 		if (mdtidx < 0)
-			RETURN(mdtidx);
+			return mdtidx;
 
 		if (put_user((int)mdtidx, (int*)arg))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		return 0;
 	}
@@ -1293,7 +1275,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		rc = obd_ioctl_getdata(&buf, &len, (void *)arg);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		data = (void *)buf;
 
 		filename = data->ioc_inlbuf1;
@@ -1317,7 +1299,6 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			GOTO(out_free, rc);
 		}
 		ptlrpc_req_finished(request);
-		EXIT;
 out_free:
 		obd_ioctl_freedata(buf, len);
 		return rc;
@@ -1333,7 +1314,7 @@ out_free:
 
 		rc = obd_ioctl_getdata(&buf, &len, (void *)arg);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		data = (void *)buf;
 		if (data->ioc_inlbuf1 == NULL || data->ioc_inlbuf2 == NULL ||
@@ -1364,7 +1345,7 @@ out_free:
 		rc = ll_dir_setdirstripe(inode, lum, filename);
 lmv_out_free:
 		obd_ioctl_freedata(buf, len);
-		RETURN(rc);
+		return rc;
 
 	}
 	case LL_IOC_LOV_SETSTRIPE: {
@@ -1380,11 +1361,11 @@ lmv_out_free:
 			sizeof(lumv3p->lmm_objects[0]));
 		/* first try with v1 which is smaller than v3 */
 		if (copy_from_user(lumv1, lumv1p, sizeof(*lumv1)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		if ((lumv1->lmm_magic == LOV_USER_MAGIC_V3) ) {
 			if (copy_from_user(&lumv3, lumv3p, sizeof(lumv3)))
-				RETURN(-EFAULT);
+				return -EFAULT;
 		}
 
 		if (inode->i_sb->s_root == file->f_dentry)
@@ -1393,7 +1374,7 @@ lmv_out_free:
 		/* in v1 and v3 cases lumv1 points to data */
 		rc = ll_dir_setstripe(inode, lumv1, set_default);
 
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_LMV_GETSTRIPE: {
 		struct lmv_user_md *lump = (struct lmv_user_md *)arg;
@@ -1404,10 +1385,10 @@ lmv_out_free:
 		int mdtindex;
 
 		if (copy_from_user(&lum, lump, sizeof(struct lmv_user_md)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		if (lum.lum_magic != LMV_MAGIC_V1)
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		lum_size = lmv_user_md_size(1, LMV_MAGIC_V1);
 		OBD_ALLOC(tmp, lum_size);
@@ -1430,7 +1411,7 @@ lmv_out_free:
 free_lmv:
 		if (tmp)
 			OBD_FREE(tmp, lum_size);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_REMOVE_ENTRY: {
 		char		*filename = NULL;
@@ -1447,7 +1428,7 @@ free_lmv:
 
 		filename = ll_getname((const char *)arg);
 		if (IS_ERR(filename))
-			RETURN(PTR_ERR(filename));
+			return PTR_ERR(filename);
 
 		namelen = strlen(filename);
 		if (namelen < 1)
@@ -1457,12 +1438,12 @@ free_lmv:
 out_rmdir:
 		if (filename)
 			ll_putname(filename);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_LOV_SWAP_LAYOUTS:
-		RETURN(-EPERM);
+		return -EPERM;
 	case LL_IOC_OBD_STATFS:
-		RETURN(ll_obd_statfs(inode, (void *)arg));
+		return ll_obd_statfs(inode, (void *)arg);
 	case LL_IOC_LOV_GETSTRIPE:
 	case LL_IOC_MDC_GETINFO:
 	case IOC_MDC_GETFILEINFO:
@@ -1478,7 +1459,7 @@ out_rmdir:
 		    cmd == IOC_MDC_GETFILESTRIPE) {
 			filename = ll_getname((const char *)arg);
 			if (IS_ERR(filename))
-				RETURN(PTR_ERR(filename));
+				return PTR_ERR(filename);
 
 			rc = ll_lov_getstripe_ea_info(inode, filename, &lmm,
 						      &lmmsize, &request);
@@ -1539,7 +1520,6 @@ out_rmdir:
 				GOTO(out_req, rc = -EFAULT);
 		}
 
-		EXIT;
 	out_req:
 		ptlrpc_req_finished(request);
 		if (filename)
@@ -1559,9 +1539,11 @@ out_rmdir:
 
 		rc = ll_get_max_mdsize(sbi, &lmmsize);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		OBD_ALLOC_LARGE(lmm, lmmsize);
+		if (lmm == NULL)
+			return -ENOMEM;
 		if (copy_from_user(lmm, lum, lmmsize))
 			GOTO(free_lmm, rc = -EFAULT);
 
@@ -1602,7 +1584,6 @@ out_rmdir:
 		if (copy_to_user(&lumd->lmd_st, &st, sizeof(st)))
 			GOTO(free_lsm, rc = -EFAULT);
 
-		EXIT;
 	free_lsm:
 		obd_free_memmd(sbi->ll_dt_exp, &lsm);
 	free_lmm:
@@ -1610,7 +1591,7 @@ out_rmdir:
 		return rc;
 	}
 	case OBD_IOC_LLOG_CATINFO: {
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 	case OBD_IOC_QUOTACHECK: {
 		struct obd_quotactl *oqctl;
@@ -1618,11 +1599,11 @@ out_rmdir:
 
 		if (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
 		    sbi->ll_flags & LL_SBI_RMT_CLIENT)
-			RETURN(-EPERM);
+			return -EPERM;
 
 		OBD_ALLOC_PTR(oqctl);
 		if (!oqctl)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		oqctl->qc_type = arg;
 		rc = obd_quotacheck(sbi->ll_md_exp, oqctl);
 		if (rc < 0) {
@@ -1642,11 +1623,11 @@ out_rmdir:
 
 		if (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
 		    sbi->ll_flags & LL_SBI_RMT_CLIENT)
-			RETURN(-EPERM);
+			return -EPERM;
 
 		OBD_ALLOC_PTR(check);
 		if (!check)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		rc = obd_iocontrol(cmd, sbi->ll_md_exp, 0, (void *)check,
 				   NULL);
@@ -1669,7 +1650,7 @@ out_rmdir:
 		}
 	out_poll:
 		OBD_FREE_PTR(check);
-		RETURN(rc);
+		return rc;
 	}
 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 50, 0)
 	case LL_IOC_QUOTACTL_18: {
@@ -1680,7 +1661,7 @@ out_rmdir:
 
 		OBD_ALLOC_PTR(qctl_18);
 		if (!qctl_18)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		OBD_ALLOC_PTR(qctl_20);
 		if (!qctl_20)
@@ -1720,7 +1701,7 @@ out_rmdir:
 		OBD_FREE_PTR(qctl_20);
 	out_quotactl_18:
 		OBD_FREE_PTR(qctl_18);
-		RETURN(rc);
+		return rc;
 	}
 #else
 #warning "remove old LL_IOC_QUOTACTL_18 compatibility code"
@@ -1730,7 +1711,7 @@ out_rmdir:
 
 		OBD_ALLOC_PTR(qctl);
 		if (!qctl)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		if (copy_from_user(qctl, (void *)arg, sizeof(*qctl)))
 			GOTO(out_quotactl, rc = -EFAULT);
@@ -1742,13 +1723,13 @@ out_rmdir:
 
 	out_quotactl:
 		OBD_FREE_PTR(qctl);
-		RETURN(rc);
+		return rc;
 	}
 	case OBD_IOC_GETDTNAME:
 	case OBD_IOC_GETMDNAME:
-		RETURN(ll_get_obd_name(inode, cmd, arg));
+		return ll_get_obd_name(inode, cmd, arg);
 	case LL_IOC_FLUSHCTX:
-		RETURN(ll_flush_ctx(inode));
+		return ll_flush_ctx(inode);
 #ifdef CONFIG_FS_POSIX_ACL
 	case LL_IOC_RMTACL: {
 	    if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
@@ -1759,9 +1740,9 @@ out_rmdir:
 		rc = rct_add(&sbi->ll_rct, current_pid(), arg);
 		if (!rc)
 			fd->fd_flags |= LL_FILE_RMTACL;
-		RETURN(rc);
+		return rc;
 	    } else
-		RETURN(0);
+		return 0;
 	}
 #endif
 	case LL_IOC_GETOBDCOUNT: {
@@ -1769,7 +1750,7 @@ out_rmdir:
 		struct obd_export *exp;
 
 		if (copy_from_user(&count, (int *)arg, sizeof(int)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		/* get ost count when count is zero, get mdt count otherwise */
 		exp = count ? sbi->ll_md_exp : sbi->ll_dt_exp;
@@ -1778,41 +1759,41 @@ out_rmdir:
 				  KEY_TGT_COUNT, &vallen, &count, NULL);
 		if (rc) {
 			CERROR("get target count failed: %d\n", rc);
-			RETURN(rc);
+			return rc;
 		}
 
 		if (copy_to_user((int *)arg, &count, sizeof(int)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
-		RETURN(0);
+		return 0;
 	}
 	case LL_IOC_PATH2FID:
 		if (copy_to_user((void *)arg, ll_inode2fid(inode),
 				     sizeof(struct lu_fid)))
-			RETURN(-EFAULT);
-		RETURN(0);
+			return -EFAULT;
+		return 0;
 	case LL_IOC_GET_CONNECT_FLAGS: {
-		RETURN(obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void*)arg));
+		return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void*)arg);
 	}
 	case OBD_IOC_CHANGELOG_SEND:
 	case OBD_IOC_CHANGELOG_CLEAR:
 		rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg,
 				    sizeof(struct ioc_changelog));
-		RETURN(rc);
+		return rc;
 	case OBD_IOC_FID2PATH:
-		RETURN(ll_fid2path(inode, (void *)arg));
+		return ll_fid2path(inode, (void *)arg);
 	case LL_IOC_HSM_REQUEST: {
 		struct hsm_user_request	*hur;
 		int			 totalsize;
 
 		OBD_ALLOC_PTR(hur);
 		if (hur == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		/* We don't know the true size yet; copy the fixed-size part */
 		if (copy_from_user(hur, (void *)arg, sizeof(*hur))) {
 			OBD_FREE_PTR(hur);
-			RETURN(-EFAULT);
+			return -EFAULT;
 		}
 
 		/* Compute the whole struct size */
@@ -1820,12 +1801,12 @@ out_rmdir:
 		OBD_FREE_PTR(hur);
 		OBD_ALLOC_LARGE(hur, totalsize);
 		if (hur == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		/* Copy the whole struct */
 		if (copy_from_user(hur, (void *)arg, totalsize)) {
 			OBD_FREE_LARGE(hur, totalsize);
-			RETURN(-EFAULT);
+			return -EFAULT;
 		}
 
 		rc = obd_iocontrol(cmd, ll_i2mdexp(inode), totalsize,
@@ -1833,14 +1814,14 @@ out_rmdir:
 
 		OBD_FREE_LARGE(hur, totalsize);
 
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_HSM_PROGRESS: {
 		struct hsm_progress_kernel	hpk;
 		struct hsm_progress		hp;
 
 		if (copy_from_user(&hp, (void *)arg, sizeof(hp)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		hpk.hpk_fid = hp.hp_fid;
 		hpk.hpk_cookie = hp.hp_cookie;
@@ -1853,12 +1834,12 @@ out_rmdir:
 		 * reported to Lustre root */
 		rc = obd_iocontrol(cmd, sbi->ll_md_exp, sizeof(hpk), &hpk,
 				   NULL);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_HSM_CT_START:
 		rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg,
 				    sizeof(struct lustre_kernelcomm));
-		RETURN(rc);
+		return rc;
 
 	case LL_IOC_HSM_COPY_START: {
 		struct hsm_copy	*copy;
@@ -1866,10 +1847,10 @@ out_rmdir:
 
 		OBD_ALLOC_PTR(copy);
 		if (copy == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		if (copy_from_user(copy, (char *)arg, sizeof(*copy))) {
 			OBD_FREE_PTR(copy);
-			RETURN(-EFAULT);
+			return -EFAULT;
 		}
 
 		rc = ll_ioc_copy_start(inode->i_sb, copy);
@@ -1877,7 +1858,7 @@ out_rmdir:
 			rc = -EFAULT;
 
 		OBD_FREE_PTR(copy);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_HSM_COPY_END: {
 		struct hsm_copy	*copy;
@@ -1885,10 +1866,10 @@ out_rmdir:
 
 		OBD_ALLOC_PTR(copy);
 		if (copy == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		if (copy_from_user(copy, (char *)arg, sizeof(*copy))) {
 			OBD_FREE_PTR(copy);
-			RETURN(-EFAULT);
+			return -EFAULT;
 		}
 
 		rc = ll_ioc_copy_end(inode->i_sb, copy);
@@ -1896,11 +1877,10 @@ out_rmdir:
 			rc = -EFAULT;
 
 		OBD_FREE_PTR(copy);
-		RETURN(rc);
+		return rc;
 	}
 	default:
-		RETURN(obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL,
-				     (void *)arg));
+		return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void *)arg);
 	}
 }
 
@@ -1911,7 +1891,6 @@ static loff_t ll_dir_seek(struct file *file, loff_t offset, int origin)
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	int api32 = ll_need_32bit_api(sbi);
 	loff_t ret = -EINVAL;
-	ENTRY;
 
 	mutex_lock(&inode->i_mutex);
 	switch (origin) {
@@ -1957,14 +1936,12 @@ out:
 
 int ll_dir_open(struct inode *inode, struct file *file)
 {
-	ENTRY;
-	RETURN(ll_file_open(inode, file));
+	return ll_file_open(inode, file);
 }
 
 int ll_dir_release(struct inode *inode, struct file *file)
 {
-	ENTRY;
-	RETURN(ll_file_release(inode, file));
+	return ll_file_release(inode, file);
 }
 
 struct file_operations ll_dir_operations = {
@@ -1972,7 +1949,7 @@ struct file_operations ll_dir_operations = {
 	.open     = ll_dir_open,
 	.release  = ll_dir_release,
 	.read     = generic_read_dir,
-	.readdir  = ll_readdir,
+	.iterate  = ll_readdir,
 	.unlocked_ioctl   = ll_dir_ioctl,
 	.fsync    = ll_fsync,
 };
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index ed1e3f7..bc534db 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -55,6 +55,8 @@ struct ll_file_data *ll_file_data_get(void)
 	struct ll_file_data *fd;
 
 	OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, __GFP_IO);
+	if (fd == NULL)
+		return NULL;
 	fd->fd_write_failed = false;
 	return fd;
 }
@@ -93,8 +95,6 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data,
 static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
 			     struct obd_client_handle *och)
 {
-	ENTRY;
-
 	op_data->op_attr.ia_valid = ATTR_MODE | ATTR_ATIME | ATTR_ATIME_SET |
 					ATTR_MTIME | ATTR_MTIME_SET |
 					ATTR_CTIME | ATTR_CTIME_SET;
@@ -111,7 +111,6 @@ out:
 	ll_pack_inode2opdata(inode, op_data, &och->och_fh);
 	ll_prep_md_op_data(op_data, inode, NULL, NULL,
 			   0, 0, LUSTRE_OPC_ANY, NULL);
-	EXIT;
 }
 
 static int ll_close_inode_openhandle(struct obd_export *md_exp,
@@ -124,7 +123,6 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
 	struct obd_device *obd = class_exp2obd(exp);
 	int epoch_close = 1;
 	int rc;
-	ENTRY;
 
 	if (obd == NULL) {
 		/*
@@ -178,9 +176,7 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
 			       inode->i_ino, rc);
 	}
 
-	EXIT;
 out:
-
 	if (exp_connect_som(exp) && !epoch_close &&
 	    S_ISREG(inode->i_mode) && (och->och_flags & FMODE_WRITE)) {
 		ll_queue_done_writing(inode, LLIF_DONE_WRITING);
@@ -202,7 +198,6 @@ int ll_md_real_close(struct inode *inode, int flags)
 	struct obd_client_handle *och;
 	__u64 *och_usecount;
 	int rc = 0;
-	ENTRY;
 
 	if (flags & FMODE_WRITE) {
 		och_p = &lli->lli_mds_write_och;
@@ -220,7 +215,7 @@ int ll_md_real_close(struct inode *inode, int flags)
 	if (*och_usecount) { /* There are still users of this handle, so
 				skip freeing it. */
 		mutex_unlock(&lli->lli_och_mutex);
-		RETURN(0);
+		return 0;
 	}
 	och=*och_p;
 	*och_p = NULL;
@@ -232,7 +227,7 @@ int ll_md_real_close(struct inode *inode, int flags)
 					       inode, och);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 int ll_md_close(struct obd_export *md_exp, struct inode *inode,
@@ -241,7 +236,6 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode,
 	struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
 	struct ll_inode_info *lli = ll_i2info(inode);
 	int rc = 0;
-	ENTRY;
 
 	/* clear group lock, if present */
 	if (unlikely(fd->fd_flags & LL_FILE_GROUP_LOCKED))
@@ -287,7 +281,7 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode,
 	ll_file_data_put(fd);
 	ll_capa_close(inode);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* While this returns an error code, fput() the caller does not, so we need
@@ -301,7 +295,6 @@ int ll_file_release(struct inode *inode, struct file *file)
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct ll_inode_info *lli = ll_i2info(inode);
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino,
 	       inode->i_generation, inode);
@@ -335,7 +328,7 @@ int ll_file_release(struct inode *inode, struct file *file)
 	if (inode->i_sb->s_root == file->f_dentry) {
 		LUSTRE_FPRIVATE(file) = NULL;
 		ll_file_data_put(fd);
-		RETURN(0);
+		return 0;
 	}
 
 	if (!S_ISDIR(inode->i_mode)) {
@@ -348,7 +341,7 @@ int ll_file_release(struct inode *inode, struct file *file)
 	if (CFS_FAIL_TIMEOUT_MS(OBD_FAIL_PTLRPC_DUMP_LOG, cfs_fail_val))
 		libcfs_debug_dumplog();
 
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_intent_file_open(struct file *file, void *lmm,
@@ -362,10 +355,9 @@ static int ll_intent_file_open(struct file *file, void *lmm,
 	struct ptlrpc_request *req;
 	__u32 opc = LUSTRE_OPC_ANY;
 	int rc;
-	ENTRY;
 
 	if (!parent)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	/* Usually we come here only for NFSD, and we want open lock.
 	   But we can also get here with pre 2.6.15 patchless kernels, and in
@@ -386,7 +378,7 @@ static int ll_intent_file_open(struct file *file, void *lmm,
 				      file->f_dentry->d_inode, name, len,
 				      O_RDWR, opc, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	itp->it_flags |= MDS_OPEN_BY_FID;
 	rc = md_intent_lock(sbi->ll_md_exp, op_data, lmm, lmmsize, itp,
@@ -422,7 +414,7 @@ out:
 	it_clear_disposition(itp, DISP_ENQ_COMPLETE);
 	ll_intent_drop_lock(itp);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -464,7 +456,6 @@ int ll_local_open(struct file *file, struct lookup_intent *it,
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ll_inode_info *lli = ll_i2info(inode);
-	ENTRY;
 
 	LASSERT(!LUSTRE_FPRIVATE(file));
 
@@ -477,7 +468,7 @@ int ll_local_open(struct file *file, struct lookup_intent *it,
 
 		rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, lli, it, och);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 		if ((it->it_flags & FMODE_WRITE) &&
@@ -489,7 +480,7 @@ int ll_local_open(struct file *file, struct lookup_intent *it,
 	LUSTRE_FPRIVATE(file) = fd;
 	ll_readahead_init(inode, &fd->fd_ras);
 	fd->fd_omode = it->it_flags;
-	RETURN(0);
+	return 0;
 }
 
 /* Open a file, and (for the very first open) create objects on the OSTs at
@@ -514,7 +505,6 @@ int ll_file_open(struct inode *inode, struct file *file)
 	__u64 *och_usecount = NULL;
 	struct ll_file_data *fd;
 	int rc = 0, opendir_set = 0;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino,
 	       inode->i_generation, inode, file->f_flags);
@@ -524,7 +514,7 @@ int ll_file_open(struct inode *inode, struct file *file)
 
 	fd = ll_file_data_get();
 	if (fd == NULL)
-		GOTO(out_och_free, rc = -ENOMEM);
+		GOTO(out_openerr, rc = -ENOMEM);
 
 	fd->fd_file = file;
 	if (S_ISDIR(inode->i_mode)) {
@@ -540,7 +530,7 @@ int ll_file_open(struct inode *inode, struct file *file)
 
 	if (inode->i_sb->s_root == file->f_dentry) {
 		LUSTRE_FPRIVATE(file) = fd;
-		RETURN(0);
+		return 0;
 	}
 
 	if (!it || !it->d.lustre.it_disposition) {
@@ -700,8 +690,6 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp,
 	struct obd_info	    oinfo = { { { 0 } } };
 	int			rc;
 
-	ENTRY;
-
 	LASSERT(lsm != NULL);
 
 	oinfo.oi_md = lsm;
@@ -736,7 +724,7 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp,
 					 OBD_MD_FLATIME | OBD_MD_FLMTIME |
 					 OBD_MD_FLCTIME | OBD_MD_FLSIZE |
 					 OBD_MD_FLDATAVERSION);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -749,7 +737,6 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo,
 	struct obd_capa      *capa = ll_mdscapa_get(inode);
 	struct lov_stripe_md *lsm;
 	int rc;
-	ENTRY;
 
 	lsm = ccc_inode_lsm_get(inode);
 	rc = ll_lsm_getattr(lsm, ll_i2dtexp(inode),
@@ -765,7 +752,7 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo,
 		       (unsigned long)ll_inode_blksize(inode));
 	}
 	ccc_inode_lsm_put(inode, lsm);
-	RETURN(rc);
+	return rc;
 }
 
 int ll_merge_lvb(const struct lu_env *env, struct inode *inode)
@@ -776,8 +763,6 @@ int ll_merge_lvb(const struct lu_env *env, struct inode *inode)
 	struct ost_lvb lvb;
 	int rc = 0;
 
-	ENTRY;
-
 	ll_inode_size_lock(inode);
 	/* merge timestamps the most recently obtained from mds with
 	   timestamps obtained from osts */
@@ -810,7 +795,7 @@ int ll_merge_lvb(const struct lu_env *env, struct inode *inode)
 	}
 	ll_inode_size_unlock(inode);
 
-	RETURN(rc);
+	return rc;
 }
 
 int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm,
@@ -860,7 +845,6 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
 	struct ll_file_data  *fd  = LUSTRE_FPRIVATE(file);
 	struct cl_io	 *io;
 	ssize_t	       result;
-	ENTRY;
 
 restart:
 	io = ccc_env_thread_io(env);
@@ -986,15 +970,14 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 	size_t	      count;
 	ssize_t	     result;
 	int		 refcheck;
-	ENTRY;
 
 	result = ll_file_get_iov_count(iov, &nr_segs, &count);
 	if (result)
-		RETURN(result);
+		return result;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	args = vvp_env_args(env, IO_NORMAL);
 	args->u.normal.via_iov = (struct iovec *)iov;
@@ -1004,7 +987,7 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 	result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
 				    &iocb->ki_pos, count);
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
 
 static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
@@ -1015,11 +998,10 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
 	struct kiocb  *kiocb;
 	ssize_t	result;
 	int	    refcheck;
-	ENTRY;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	local_iov = &vvp_env_info(env)->vti_local_iov;
 	kiocb = &vvp_env_info(env)->vti_kiocb;
@@ -1027,13 +1009,13 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
 	local_iov->iov_len = count;
 	init_sync_kiocb(kiocb, file);
 	kiocb->ki_pos = *ppos;
-	kiocb->ki_left = count;
+	kiocb->ki_nbytes = count;
 
 	result = ll_file_aio_read(kiocb, local_iov, 1, kiocb->ki_pos);
 	*ppos = kiocb->ki_pos;
 
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
 
 /*
@@ -1047,15 +1029,14 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	size_t	      count;
 	ssize_t	     result;
 	int		 refcheck;
-	ENTRY;
 
 	result = ll_file_get_iov_count(iov, &nr_segs, &count);
 	if (result)
-		RETURN(result);
+		return result;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	args = vvp_env_args(env, IO_NORMAL);
 	args->u.normal.via_iov = (struct iovec *)iov;
@@ -1065,7 +1046,7 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE,
 				  &iocb->ki_pos, count);
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
 
 static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
@@ -1076,11 +1057,10 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
 	struct kiocb  *kiocb;
 	ssize_t	result;
 	int	    refcheck;
-	ENTRY;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	local_iov = &vvp_env_info(env)->vti_local_iov;
 	kiocb = &vvp_env_info(env)->vti_kiocb;
@@ -1088,13 +1068,13 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
 	local_iov->iov_len = count;
 	init_sync_kiocb(kiocb, file);
 	kiocb->ki_pos = *ppos;
-	kiocb->ki_left = count;
+	kiocb->ki_nbytes = count;
 
 	result = ll_file_aio_write(kiocb, local_iov, 1, kiocb->ki_pos);
 	*ppos = kiocb->ki_pos;
 
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
 
 
@@ -1110,11 +1090,10 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
 	struct vvp_io_args *args;
 	ssize_t	     result;
 	int		 refcheck;
-	ENTRY;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	args = vvp_env_args(env, IO_SPLICE);
 	args->u.splice.via_pipe = pipe;
@@ -1122,7 +1101,7 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
 
 	result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
 	cl_env_put(env, &refcheck);
-	RETURN(result);
+	return result;
 }
 
 static int ll_lov_recreate(struct inode *inode, struct ost_id *oi,
@@ -1134,14 +1113,13 @@ static int ll_lov_recreate(struct inode *inode, struct ost_id *oi,
 	int lsm_size;
 	int rc = 0;
 	struct lov_stripe_md *lsm = NULL, *lsm2;
-	ENTRY;
 
 	OBDO_ALLOC(oa);
 	if (oa == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	lsm = ccc_inode_lsm_get(inode);
-	if (lsm == NULL)
+	if (!lsm_has_objects(lsm))
 		GOTO(out, rc = -ENOENT);
 
 	lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) *
@@ -1175,18 +1153,17 @@ static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg)
 {
 	struct ll_recreate_obj ucreat;
 	struct ost_id		oi;
-	ENTRY;
 
 	if (!cfs_capable(CFS_CAP_SYS_ADMIN))
-		RETURN(-EPERM);
+		return -EPERM;
 
 	if (copy_from_user(&ucreat, (struct ll_recreate_obj *)arg,
 			   sizeof(ucreat)))
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	ostid_set_seq_mdt0(&oi);
 	ostid_set_id(&oi, ucreat.lrc_id);
-	RETURN(ll_lov_recreate(inode, &oi, ucreat.lrc_ost_idx));
+	return ll_lov_recreate(inode, &oi, ucreat.lrc_ost_idx);
 }
 
 static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg)
@@ -1194,17 +1171,16 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg)
 	struct lu_fid	fid;
 	struct ost_id	oi;
 	obd_count	ost_idx;
-	ENTRY;
 
 	if (!cfs_capable(CFS_CAP_SYS_ADMIN))
-		RETURN(-EPERM);
+		return -EPERM;
 
 	if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid)))
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	fid_to_ostid(&fid, &oi);
 	ost_idx = (fid_seq(&fid) >> 16) & 0xffff;
-	RETURN(ll_lov_recreate(inode, &oi, ost_idx));
+	return ll_lov_recreate(inode, &oi, ost_idx);
 }
 
 int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
@@ -1213,14 +1189,13 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
 	struct lov_stripe_md *lsm = NULL;
 	struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags};
 	int rc = 0;
-	ENTRY;
 
 	lsm = ccc_inode_lsm_get(inode);
 	if (lsm != NULL) {
 		ccc_inode_lsm_put(inode, lsm);
 		CDEBUG(D_IOCTL, "stripe already exists for ino %lu\n",
 		       inode->i_ino);
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 
 	ll_inode_size_lock(inode);
@@ -1237,7 +1212,7 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
 	ll_inode_size_unlock(inode);
 	ll_intent_release(&oit);
 	ccc_inode_lsm_put(inode, lsm);
-	RETURN(rc);
+	return rc;
 out_req_free:
 	ptlrpc_req_finished((struct ptlrpc_request *) oit.d.lustre.it_data);
 	goto out;
@@ -1256,13 +1231,13 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
 
 	rc = ll_get_max_mdsize(sbi, &lmmsize);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, filename,
 				     strlen(filename), lmmsize,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
 	rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
@@ -1297,6 +1272,12 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
 	 * passing it to userspace.
 	 */
 	if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) {
+		int stripe_count;
+
+		stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
+		if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
+			stripe_count = 0;
+
 		/* if function called for directory - we should
 		 * avoid swab not existent lsm objects */
 		if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) {
@@ -1304,13 +1285,13 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
 			if (S_ISREG(body->mode))
 				lustre_swab_lov_user_md_objects(
 				 ((struct lov_user_md_v1 *)lmm)->lmm_objects,
-				 ((struct lov_user_md_v1 *)lmm)->lmm_stripe_count);
+				 stripe_count);
 		} else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) {
 			lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
 			if (S_ISREG(body->mode))
 				lustre_swab_lov_user_md_objects(
 				 ((struct lov_user_md_v3 *)lmm)->lmm_objects,
-				 ((struct lov_user_md_v3 *)lmm)->lmm_stripe_count);
+				 stripe_count);
 		}
 	}
 
@@ -1329,24 +1310,23 @@ static int ll_lov_setea(struct inode *inode, struct file *file,
 	int			 lum_size = sizeof(struct lov_user_md) +
 					    sizeof(struct lov_user_ost_data);
 	int			 rc;
-	ENTRY;
 
 	if (!cfs_capable(CFS_CAP_SYS_ADMIN))
-		RETURN(-EPERM);
+		return -EPERM;
 
 	OBD_ALLOC_LARGE(lump, lum_size);
 	if (lump == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (copy_from_user(lump, (struct lov_user_md  *)arg, lum_size)) {
 		OBD_FREE_LARGE(lump, lum_size);
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 
 	rc = ll_lov_setstripe_ea_info(inode, file, flags, lump, lum_size);
 
 	OBD_FREE_LARGE(lump, lum_size);
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_lov_setstripe(struct inode *inode, struct file *file,
@@ -1358,17 +1338,16 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file,
 	struct lov_user_md_v3	*lumv3p = (struct lov_user_md_v3 *)arg;
 	int			 lum_size, rc;
 	int			 flags = FMODE_WRITE;
-	ENTRY;
 
 	/* first try with v1 which is smaller than v3 */
 	lum_size = sizeof(struct lov_user_md_v1);
 	if (copy_from_user(lumv1, lumv1p, lum_size))
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) {
 		lum_size = sizeof(struct lov_user_md_v3);
 		if (copy_from_user(&lumv3, lumv3p, lum_size))
-			RETURN(-EFAULT);
+			return -EFAULT;
 	}
 
 	rc = ll_lov_setstripe_ea_info(inode, file, flags, lumv1, lum_size);
@@ -1384,21 +1363,20 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file,
 				   0, lsm, (void *)arg);
 		ccc_inode_lsm_put(inode, lsm);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_lov_getstripe(struct inode *inode, unsigned long arg)
 {
 	struct lov_stripe_md *lsm;
 	int rc = -ENODATA;
-	ENTRY;
 
 	lsm = ccc_inode_lsm_get(inode);
 	if (lsm != NULL)
 		rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0,
 				   lsm, (void *)arg);
 	ccc_inode_lsm_put(inode, lsm);
-	RETURN(rc);
+	return rc;
 }
 
 int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg)
@@ -1407,17 +1385,16 @@ int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 	struct ll_file_data    *fd = LUSTRE_FPRIVATE(file);
 	struct ccc_grouplock    grouplock;
 	int		     rc;
-	ENTRY;
 
 	if (ll_file_nolock(file))
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	spin_lock(&lli->lli_lock);
 	if (fd->fd_flags & LL_FILE_GROUP_LOCKED) {
 		CWARN("group lock already existed with gid %lu\n",
 		      fd->fd_grouplock.cg_gid);
 		spin_unlock(&lli->lli_lock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	LASSERT(fd->fd_grouplock.cg_lock == NULL);
 	spin_unlock(&lli->lli_lock);
@@ -1425,14 +1402,14 @@ int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 	rc = cl_get_grouplock(cl_i2info(inode)->lli_clob,
 			      arg, (file->f_flags & O_NONBLOCK), &grouplock);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	spin_lock(&lli->lli_lock);
 	if (fd->fd_flags & LL_FILE_GROUP_LOCKED) {
 		spin_unlock(&lli->lli_lock);
 		CERROR("another thread just won the race\n");
 		cl_put_grouplock(&grouplock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	fd->fd_flags |= LL_FILE_GROUP_LOCKED;
@@ -1440,7 +1417,7 @@ int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 	spin_unlock(&lli->lli_lock);
 
 	CDEBUG(D_INFO, "group lock %lu obtained\n", arg);
-	RETURN(0);
+	return 0;
 }
 
 int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg)
@@ -1448,13 +1425,12 @@ int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 	struct ll_inode_info   *lli = ll_i2info(inode);
 	struct ll_file_data    *fd = LUSTRE_FPRIVATE(file);
 	struct ccc_grouplock    grouplock;
-	ENTRY;
 
 	spin_lock(&lli->lli_lock);
 	if (!(fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
 		spin_unlock(&lli->lli_lock);
 		CWARN("no group lock held\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	LASSERT(fd->fd_grouplock.cg_lock != NULL);
 
@@ -1462,7 +1438,7 @@ int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 		CWARN("group lock %lu doesn't match current id %lu\n",
 		       arg, fd->fd_grouplock.cg_gid);
 		spin_unlock(&lli->lli_lock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	grouplock = fd->fd_grouplock;
@@ -1472,7 +1448,7 @@ int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 
 	cl_put_grouplock(&grouplock);
 	CDEBUG(D_INFO, "group lock %lu released\n", arg);
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1489,17 +1465,16 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it)
 	struct inode *inode = dentry->d_inode;
 	struct obd_client_handle *och;
 	int rc;
-	ENTRY;
 
 	LASSERT(inode);
 
 	/* Root ? Do nothing. */
 	if (dentry->d_inode->i_sb->s_root == dentry)
-		RETURN(0);
+		return 0;
 
 	/* No open handle to close? Move away */
 	if (!it_disposition(it, DISP_OPEN_OPEN))
-		RETURN(0);
+		return 0;
 
 	LASSERT(it_open_error(DISP_OPEN_OPEN, it) == 0);
 
@@ -1518,7 +1493,7 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it)
 		ptlrpc_req_finished(it->d.lustre.it_data);
 		it_clear_disposition(it, DISP_ENQ_OPEN_REF);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1533,7 +1508,6 @@ int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
 	struct ll_fiemap_info_key fm_key = { .name = KEY_FIEMAP, };
 	int vallen = num_bytes;
 	int rc;
-	ENTRY;
 
 	/* Checks for fiemap flags */
 	if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) {
@@ -1579,7 +1553,7 @@ int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
 
 out:
 	ccc_inode_lsm_put(inode, lsm);
-	RETURN(rc);
+	return rc;
 }
 
 int ll_fid2path(struct inode *inode, void *arg)
@@ -1587,26 +1561,25 @@ int ll_fid2path(struct inode *inode, void *arg)
 	struct obd_export	*exp = ll_i2mdexp(inode);
 	struct getinfo_fid2path	*gfout, *gfin;
 	int			 outsize, rc;
-	ENTRY;
 
 	if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) &&
 	    !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
-		RETURN(-EPERM);
+		return -EPERM;
 
 	/* Need to get the buflen */
 	OBD_ALLOC_PTR(gfin);
 	if (gfin == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	if (copy_from_user(gfin, arg, sizeof(*gfin))) {
 		OBD_FREE_PTR(gfin);
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 
 	outsize = sizeof(*gfout) + gfin->gf_pathlen;
 	OBD_ALLOC(gfout, outsize);
 	if (gfout == NULL) {
 		OBD_FREE_PTR(gfin);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 	memcpy(gfout, gfin, sizeof(*gfout));
 	OBD_FREE_PTR(gfin);
@@ -1621,7 +1594,7 @@ int ll_fid2path(struct inode *inode, void *arg)
 
 gf_free:
 	OBD_FREE(gfout, outsize);
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg)
@@ -1635,13 +1608,13 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg)
 	 * required fiemap buffer */
 	if (get_user(extent_count,
 	    &((struct ll_user_fiemap __user *)arg)->fm_extent_count))
-		RETURN(-EFAULT);
+		return -EFAULT;
 	num_bytes = sizeof(*fiemap_s) + (extent_count *
 					 sizeof(struct ll_fiemap_extent));
 
 	OBD_ALLOC_LARGE(fiemap_s, num_bytes);
 	if (fiemap_s == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* get the fiemap value */
 	if (copy_from_user(fiemap_s, (struct ll_user_fiemap __user *)arg,
@@ -1673,7 +1646,7 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg)
 
 error:
 	OBD_FREE_LARGE(fiemap_s, num_bytes);
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -1692,24 +1665,21 @@ int ll_data_version(struct inode *inode, __u64 *data_version,
 	struct ll_sb_info	*sbi = ll_i2sbi(inode);
 	struct obdo		*obdo = NULL;
 	int			 rc;
-	ENTRY;
 
 	/* If no stripe, we consider version is 0. */
 	lsm = ccc_inode_lsm_get(inode);
-	if (lsm == NULL) {
+	if (!lsm_has_objects(lsm)) {
 		*data_version = 0;
 		CDEBUG(D_INODE, "No object for inode\n");
-		RETURN(0);
+		GOTO(out, rc = 0);
 	}
 
 	OBD_ALLOC_PTR(obdo);
-	if (obdo == NULL) {
-		ccc_inode_lsm_put(inode, lsm);
-		RETURN(-ENOMEM);
-	}
+	if (obdo == NULL)
+		GOTO(out, rc = -ENOMEM);
 
 	rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, NULL, obdo, 0, extent_lock);
-	if (!rc) {
+	if (rc == 0) {
 		if (!(obdo->o_valid & OBD_MD_FLDATAVERSION))
 			rc = -EOPNOTSUPP;
 		else
@@ -1717,9 +1687,9 @@ int ll_data_version(struct inode *inode, __u64 *data_version,
 	}
 
 	OBD_FREE_PTR(obdo);
+out:
 	ccc_inode_lsm_put(inode, lsm);
-
-	RETURN(rc);
+	return rc;
 }
 
 struct ll_swap_stack {
@@ -1741,7 +1711,7 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
 
 	OBD_ALLOC_PTR(llss);
 	if (llss == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	llss->inode1 = file1->f_dentry->d_inode;
 	llss->inode2 = file2->f_dentry->d_inode;
@@ -1749,8 +1719,8 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
 	if (!S_ISREG(llss->inode2->i_mode))
 		GOTO(free, rc = -EINVAL);
 
-	if (ll_permission(llss->inode1, MAY_WRITE, NULL) ||
-	    ll_permission(llss->inode2, MAY_WRITE, NULL))
+	if (inode_permission(llss->inode1, MAY_WRITE) ||
+	    inode_permission(llss->inode2, MAY_WRITE))
 		GOTO(free, rc = -EPERM);
 
 	if (llss->inode2->i_sb != llss->inode1->i_sb)
@@ -1830,12 +1800,12 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
 	rc = -ENOMEM;
 	op_data = ll_prep_md_op_data(NULL, llss->inode1, llss->inode2, NULL, 0,
 				     0, LUSTRE_OPC_ANY, &msl);
-	if (op_data != NULL) {
-		rc = obd_iocontrol(LL_IOC_LOV_SWAP_LAYOUTS,
-				   ll_i2mdexp(llss->inode1),
-				   sizeof(*op_data), op_data, NULL);
-		ll_finish_md_op_data(op_data);
-	}
+	if (IS_ERR(op_data))
+		GOTO(free, rc = PTR_ERR(op_data));
+
+	rc = obd_iocontrol(LL_IOC_LOV_SWAP_LAYOUTS, ll_i2mdexp(llss->inode1),
+			   sizeof(*op_data), op_data, NULL);
+	ll_finish_md_op_data(op_data);
 
 putgl:
 	if (gid != 0) {
@@ -1880,7 +1850,7 @@ free:
 	if (llss != NULL)
 		OBD_FREE_PTR(llss);
 
-	RETURN(rc);
+	return rc;
 }
 
 long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1888,7 +1858,6 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	struct inode		*inode = file->f_dentry->d_inode;
 	struct ll_file_data	*fd = LUSTRE_FPRIVATE(file);
 	int			 flags, rc;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p),cmd=%x\n", inode->i_ino,
 	       inode->i_generation, inode, cmd);
@@ -1896,7 +1865,7 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	/* asm-ppc{,64} declares TCGETS, et. al. as type 't' not 'T' */
 	if (_IOC_TYPE(cmd) == 'T' || _IOC_TYPE(cmd) == 't') /* tty ioctls */
-		RETURN(-ENOTTY);
+		return -ENOTTY;
 
 	switch(cmd) {
 	case LL_IOC_GETFLAGS:
@@ -1909,66 +1878,66 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		 *     not abused, and to handle any flag side effects.
 		 */
 		if (get_user(flags, (int *) arg))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		if (cmd == LL_IOC_SETFLAGS) {
 			if ((flags & LL_FILE_IGNORE_LOCK) &&
 			    !(file->f_flags & O_DIRECT)) {
 				CERROR("%s: unable to disable locking on "
 				       "non-O_DIRECT file\n", current->comm);
-				RETURN(-EINVAL);
+				return -EINVAL;
 			}
 
 			fd->fd_flags |= flags;
 		} else {
 			fd->fd_flags &= ~flags;
 		}
-		RETURN(0);
+		return 0;
 	case LL_IOC_LOV_SETSTRIPE:
-		RETURN(ll_lov_setstripe(inode, file, arg));
+		return ll_lov_setstripe(inode, file, arg);
 	case LL_IOC_LOV_SETEA:
-		RETURN(ll_lov_setea(inode, file, arg));
+		return ll_lov_setea(inode, file, arg);
 	case LL_IOC_LOV_SWAP_LAYOUTS: {
 		struct file *file2;
 		struct lustre_swap_layouts lsl;
 
 		if (copy_from_user(&lsl, (char *)arg,
 				       sizeof(struct lustre_swap_layouts)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */
-			RETURN(-EPERM);
+			return -EPERM;
 
 		file2 = fget(lsl.sl_fd);
 		if (file2 == NULL)
-			RETURN(-EBADF);
+			return -EBADF;
 
 		rc = -EPERM;
 		if ((file2->f_flags & O_ACCMODE) != 0) /* O_WRONLY or O_RDWR */
 			rc = ll_swap_layouts(file, file2, &lsl);
 		fput(file2);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_LOV_GETSTRIPE:
-		RETURN(ll_lov_getstripe(inode, arg));
+		return ll_lov_getstripe(inode, arg);
 	case LL_IOC_RECREATE_OBJ:
-		RETURN(ll_lov_recreate_obj(inode, arg));
+		return ll_lov_recreate_obj(inode, arg);
 	case LL_IOC_RECREATE_FID:
-		RETURN(ll_lov_recreate_fid(inode, arg));
+		return ll_lov_recreate_fid(inode, arg);
 	case FSFILT_IOC_FIEMAP:
-		RETURN(ll_ioctl_fiemap(inode, arg));
+		return ll_ioctl_fiemap(inode, arg);
 	case FSFILT_IOC_GETFLAGS:
 	case FSFILT_IOC_SETFLAGS:
-		RETURN(ll_iocontrol(inode, file, cmd, arg));
+		return ll_iocontrol(inode, file, cmd, arg);
 	case FSFILT_IOC_GETVERSION_OLD:
 	case FSFILT_IOC_GETVERSION:
-		RETURN(put_user(inode->i_generation, (int *)arg));
+		return put_user(inode->i_generation, (int *)arg);
 	case LL_IOC_GROUP_LOCK:
-		RETURN(ll_get_grouplock(inode, file, arg));
+		return ll_get_grouplock(inode, file, arg);
 	case LL_IOC_GROUP_UNLOCK:
-		RETURN(ll_put_grouplock(inode, file, arg));
+		return ll_put_grouplock(inode, file, arg);
 	case IOC_OBD_STATFS:
-		RETURN(ll_obd_statfs(inode, (void *)arg));
+		return ll_obd_statfs(inode, (void *)arg);
 
 	/* We need to special case any other ioctls we want to handle,
 	 * to send them to the MDS/OST as appropriate and to properly
@@ -1977,30 +1946,30 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case FSFILT_IOC_SETVERSION:
 	*/
 	case LL_IOC_FLUSHCTX:
-		RETURN(ll_flush_ctx(inode));
+		return ll_flush_ctx(inode);
 	case LL_IOC_PATH2FID: {
 		if (copy_to_user((void *)arg, ll_inode2fid(inode),
 				 sizeof(struct lu_fid)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
-		RETURN(0);
+		return 0;
 	}
 	case OBD_IOC_FID2PATH:
-		RETURN(ll_fid2path(inode, (void *)arg));
+		return ll_fid2path(inode, (void *)arg);
 	case LL_IOC_DATA_VERSION: {
 		struct ioc_data_version	idv;
 		int			rc;
 
 		if (copy_from_user(&idv, (char *)arg, sizeof(idv)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		rc = ll_data_version(inode, &idv.idv_version,
 				!(idv.idv_flags & LL_DV_NOFLUSH));
 
 		if (rc == 0 && copy_to_user((char *) arg, &idv, sizeof(idv)))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
-		RETURN(rc);
+		return rc;
 	}
 
 	case LL_IOC_GET_MDTIDX: {
@@ -2008,16 +1977,16 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		mdtidx = ll_get_mdt_idx(inode);
 		if (mdtidx < 0)
-			RETURN(mdtidx);
+			return mdtidx;
 
 		if (put_user((int)mdtidx, (int*)arg))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
-		RETURN(0);
+		return 0;
 	}
 	case OBD_IOC_GETDTNAME:
 	case OBD_IOC_GETMDNAME:
-		RETURN(ll_get_obd_name(inode, cmd, arg));
+		return ll_get_obd_name(inode, cmd, arg);
 	case LL_IOC_HSM_STATE_GET: {
 		struct md_op_data	*op_data;
 		struct hsm_user_state	*hus;
@@ -2025,13 +1994,13 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		OBD_ALLOC_PTR(hus);
 		if (hus == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, hus);
-		if (op_data == NULL) {
+		if (IS_ERR(op_data)) {
 			OBD_FREE_PTR(hus);
-			RETURN(-ENOMEM);
+			return PTR_ERR(op_data);
 		}
 
 		rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data),
@@ -2042,7 +2011,7 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		ll_finish_md_op_data(op_data);
 		OBD_FREE_PTR(hus);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_HSM_STATE_SET: {
 		struct md_op_data	*op_data;
@@ -2051,10 +2020,10 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		OBD_ALLOC_PTR(hss);
 		if (hss == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		if (copy_from_user(hss, (char *)arg, sizeof(*hss))) {
 			OBD_FREE_PTR(hss);
-			RETURN(-EFAULT);
+			return -EFAULT;
 		}
 
 		/* Non-root users are forbidden to set or clear flags which are
@@ -2062,14 +2031,14 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK)
 		    && !cfs_capable(CFS_CAP_SYS_ADMIN)) {
 			OBD_FREE_PTR(hss);
-			RETURN(-EPERM);
+			return -EPERM;
 		}
 
 		op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, hss);
-		if (op_data == NULL) {
+		if (IS_ERR(op_data)) {
 			OBD_FREE_PTR(hss);
-			RETURN(-ENOMEM);
+			return PTR_ERR(op_data);
 		}
 
 		rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data),
@@ -2078,7 +2047,7 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		ll_finish_md_op_data(op_data);
 
 		OBD_FREE_PTR(hss);
-		RETURN(rc);
+		return rc;
 	}
 	case LL_IOC_HSM_ACTION: {
 		struct md_op_data		*op_data;
@@ -2087,13 +2056,13 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		OBD_ALLOC_PTR(hca);
 		if (hca == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, hca);
-		if (op_data == NULL) {
+		if (IS_ERR(op_data)) {
 			OBD_FREE_PTR(hca);
-			RETURN(-ENOMEM);
+			return PTR_ERR(op_data);
 		}
 
 		rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data),
@@ -2104,17 +2073,17 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		ll_finish_md_op_data(op_data);
 		OBD_FREE_PTR(hca);
-		RETURN(rc);
+		return rc;
 	}
 	default: {
 		int err;
 
 		if (LLIOC_STOP ==
 		     ll_iocontrol_call(inode, file, cmd, arg, &err))
-			RETURN(err);
+			return err;
 
-		RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
-				     (void *)arg));
+		return obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
+				     (void *)arg);
 	}
 	}
 }
@@ -2125,7 +2094,6 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 	struct inode *inode = file->f_dentry->d_inode;
 	loff_t retval, eof = 0;
 
-	ENTRY;
 	retval = offset + ((origin == SEEK_END) ? i_size_read(inode) :
 			   (origin == SEEK_CUR) ? file->f_pos : 0);
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), to=%llu=%#llx(%d)\n",
@@ -2136,13 +2104,13 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 	if (origin == SEEK_END || origin == SEEK_HOLE || origin == SEEK_DATA) {
 		retval = ll_glimpse_size(inode);
 		if (retval != 0)
-			RETURN(retval);
+			return retval;
 		eof = i_size_read(inode);
 	}
 
-	retval = ll_generic_file_llseek_size(file, offset, origin,
+	retval = generic_file_llseek_size(file, offset, origin,
 					  ll_file_maxbytes(inode), eof);
-	RETURN(retval);
+	return retval;
 }
 
 int ll_flush(struct file *file, fl_owner_t id)
@@ -2184,15 +2152,14 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end,
 	struct obd_capa *capa = NULL;
 	struct cl_fsync_io *fio;
 	int result;
-	ENTRY;
 
 	if (mode != CL_FSYNC_NONE && mode != CL_FSYNC_LOCAL &&
 	    mode != CL_FSYNC_DISCARD && mode != CL_FSYNC_ALL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	env = cl_env_nested_get(&nest);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	capa = ll_osscapa_get(inode, CAPA_OPC_OSS_WRITE);
 
@@ -2220,7 +2187,7 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end,
 
 	capa_put(capa);
 
-	RETURN(result);
+	return result;
 }
 
 /*
@@ -2237,7 +2204,6 @@ int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 	struct ptlrpc_request *req;
 	struct obd_capa *oc;
 	int rc, err;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino,
 	       inode->i_generation, inode);
@@ -2281,23 +2247,24 @@ int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 	}
 
 	mutex_unlock(&inode->i_mutex);
-	RETURN(rc);
+	return rc;
 }
 
 int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
-	struct ldlm_enqueue_info einfo = { .ei_type = LDLM_FLOCK,
-					   .ei_cb_cp =ldlm_flock_completion_ast,
-					   .ei_cbdata = file_lock };
+	struct ldlm_enqueue_info einfo = {
+		.ei_type	= LDLM_FLOCK,
+		.ei_cb_cp	= ldlm_flock_completion_ast,
+		.ei_cbdata	= file_lock,
+	};
 	struct md_op_data *op_data;
 	struct lustre_handle lockh = {0};
 	ldlm_policy_data_t flock = {{0}};
 	int flags = 0;
 	int rc;
 	int rc2 = 0;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu file_lock=%p\n",
 	       inode->i_ino, file_lock);
@@ -2315,7 +2282,7 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 		flock.l_flock.start = file_lock->fl_start;
 		flock.l_flock.end = file_lock->fl_end;
 	} else {
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	flock.l_flock.pid = file_lock->fl_pid;
 
@@ -2350,7 +2317,7 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 	default:
 		CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n",
 			file_lock->fl_type);
-		RETURN (-ENOTSUPP);
+		return -ENOTSUPP;
 	}
 
 	switch (cmd) {
@@ -2377,13 +2344,13 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 		break;
 	default:
 		CERROR("unknown fcntl lock command: %d\n", cmd);
-		RETURN (-EINVAL);
+		return -EINVAL;
 	}
 
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	CDEBUG(D_DLMTRACE, "inode=%lu, pid=%u, flags=%#x, mode=%u, "
 	       "start="LPU64", end="LPU64"\n", inode->i_ino, flock.l_flock.pid,
@@ -2409,14 +2376,12 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 
 	ll_finish_md_op_data(op_data);
 
-	RETURN(rc);
+	return rc;
 }
 
 int ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock)
 {
-	ENTRY;
-
-	RETURN(-ENOSYS);
+	return -ENOSYS;
 }
 
 /**
@@ -2438,17 +2403,16 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits,  ldlm_mode_t l_req_mode)
 	struct lu_fid *fid;
 	__u64 flags;
 	int i;
-	ENTRY;
 
 	if (!inode)
-	       RETURN(0);
+	       return 0;
 
 	fid = &ll_i2info(inode)->lli_fid;
 	CDEBUG(D_INFO, "trying to match res "DFID" mode %s\n", PFID(fid),
 	       ldlm_lockname[mode]);
 
 	flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
-	for (i = 0; i < MDS_INODELOCK_MAXSHIFT && *bits != 0; i++) {
+	for (i = 0; i <= MDS_INODELOCK_MAXSHIFT && *bits != 0; i++) {
 		policy.l_inodebits.bits = *bits & (1 << i);
 		if (policy.l_inodebits.bits == 0)
 			continue;
@@ -2467,7 +2431,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits,  ldlm_mode_t l_req_mode)
 			}
 		}
 	}
-	RETURN(*bits == 0);
+	return *bits == 0;
 }
 
 ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
@@ -2476,7 +2440,6 @@ ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
 	ldlm_policy_data_t policy = { .l_inodebits = {bits}};
 	struct lu_fid *fid;
 	ldlm_mode_t rc;
-	ENTRY;
 
 	fid = &ll_i2info(inode)->lli_fid;
 	CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
@@ -2484,7 +2447,7 @@ ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
 	rc = md_lock_match(ll_i2mdexp(inode), LDLM_FL_BLOCK_GRANTED|flags,
 			   fid, LDLM_IBITS, &policy,
 			   LCK_CR|LCK_CW|LCK_PR|LCK_PW, lockh);
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_inode_revalidate_fini(struct inode *inode, int rc)
@@ -2513,7 +2476,6 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 	struct ptlrpc_request *req = NULL;
 	struct obd_export *exp;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(inode != NULL);
 
@@ -2537,7 +2499,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 					     dentry->d_inode, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, NULL);
 		if (IS_ERR(op_data))
-			RETURN(PTR_ERR(op_data));
+			return PTR_ERR(op_data);
 
 		oit.it_create_mode |= M_CHECK_STALE;
 		rc = md_intent_lock(exp, op_data, NULL, 0,
@@ -2575,7 +2537,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 		if (S_ISREG(inode->i_mode)) {
 			rc = ll_get_max_mdsize(sbi, &ealen);
 			if (rc)
-				RETURN(rc);
+				return rc;
 			valid |= OBD_MD_FLEASIZE | OBD_MD_FLMODEASIZE;
 		}
 
@@ -2583,7 +2545,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 					     0, ealen, LUSTRE_OPC_ANY,
 					     NULL);
 		if (IS_ERR(op_data))
-			RETURN(PTR_ERR(op_data));
+			return PTR_ERR(op_data);
 
 		op_data->op_valid = valid;
 		/* Once OBD_CONNECT_ATTRFID is not supported, we can't find one
@@ -2593,7 +2555,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 		ll_finish_md_op_data(op_data);
 		if (rc) {
 			rc = ll_inode_revalidate_fini(inode, rc);
-			RETURN(rc);
+			return rc;
 		}
 
 		rc = ll_prep_inode(&inode, req, NULL, NULL);
@@ -2608,11 +2570,10 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 {
 	struct inode *inode = dentry->d_inode;
 	int rc;
-	ENTRY;
 
 	rc = __ll_inode_revalidate_it(dentry, it, ibits);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	/* if object isn't regular file, don't validate size */
 	if (!S_ISREG(inode->i_mode)) {
@@ -2622,7 +2583,7 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 	} else {
 		rc = ll_glimpse_size(inode);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int ll_getattr_it(struct vfsmount *mnt, struct dentry *de,
@@ -2672,21 +2633,19 @@ struct posix_acl * ll_get_acl(struct inode *inode, int type)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct posix_acl *acl = NULL;
-	ENTRY;
 
 	spin_lock(&lli->lli_lock);
 	/* VFS' acl_permission_check->check_acl will release the refcount */
 	acl = posix_acl_dup(lli->lli_posix_acl);
 	spin_unlock(&lli->lli_lock);
 
-	RETURN(acl);
+	return acl;
 }
 
 
 int ll_inode_permission(struct inode *inode, int mask)
 {
 	int rc = 0;
-	ENTRY;
 
 #ifdef MAY_NOT_BLOCK
 	if (mask & MAY_NOT_BLOCK)
@@ -2702,7 +2661,7 @@ int ll_inode_permission(struct inode *inode, int mask)
 		rc = __ll_inode_revalidate_it(inode->i_sb->s_root, &it,
 					      MDS_INODELOCK_LOOKUP);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), inode mode %x mask %o\n",
@@ -2712,9 +2671,9 @@ int ll_inode_permission(struct inode *inode, int mask)
 		return lustre_check_remote_perm(inode, mask);
 
 	ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1);
-	rc = ll_generic_permission(inode, mask, flags, ll_check_acl);
+	rc = generic_permission(inode, mask);
 
-	RETURN(rc);
+	return rc;
 }
 
 #define READ_METHOD aio_read
@@ -2806,16 +2765,15 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd)
 {
 	unsigned int size;
 	struct llioc_data *in_data = NULL;
-	ENTRY;
 
 	if (cb == NULL || cmd == NULL ||
 	    count > LLIOC_MAX_CMD || count < 0)
-		RETURN(NULL);
+		return NULL;
 
 	size = sizeof(*in_data) + count * sizeof(unsigned int);
 	OBD_ALLOC(in_data, size);
 	if (in_data == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	memset(in_data, 0, sizeof(*in_data));
 	in_data->iocd_size = size;
@@ -2827,7 +2785,7 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd)
 	list_add_tail(&in_data->iocd_list, &llioc.ioc_head);
 	up_write(&llioc.ioc_sem);
 
-	RETURN(in_data);
+	return in_data;
 }
 
 void ll_iocontrol_unregister(void *magic)
@@ -2890,14 +2848,13 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf)
 	struct cl_env_nest nest;
 	struct lu_env *env;
 	int result;
-	ENTRY;
 
 	if (lli->lli_clob == NULL)
-		RETURN(0);
+		return 0;
 
 	env = cl_env_nested_get(&nest);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	result = cl_conf_set(env, lli->lli_clob, conf);
 	cl_env_nested_put(&nest, env);
@@ -2915,7 +2872,7 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf)
 			ldlm_lock_allow_match(lock);
 		}
 	}
-	RETURN(result);
+	return result;
 }
 
 /* Fetch layout from MDT with getxattr request, if it's not ready yet */
@@ -2930,10 +2887,13 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
 	void *lmm;
 	int lmmsize;
 	int rc;
-	ENTRY;
 
-	if (lock->l_lvb_data != NULL)
-		RETURN(0);
+	CDEBUG(D_INODE, DFID" LVB_READY=%d l_lvb_data=%p l_lvb_len=%d\n",
+	       PFID(ll_inode2fid(inode)), !!(lock->l_flags & LDLM_FL_LVB_READY),
+	       lock->l_lvb_data, lock->l_lvb_len);
+
+	if ((lock->l_lvb_data != NULL) && (lock->l_flags & LDLM_FL_LVB_READY))
+		return 0;
 
 	/* if layout lock was granted right away, the layout is returned
 	 * within DLM_LVB of dlm reply; otherwise if the lock was ever
@@ -2948,7 +2908,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
 				lmmsize, 0, &req);
 	capa_put(oc);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 	if (body == NULL || body->eadatasize > lmmsize)
@@ -2968,16 +2928,12 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
 
 	memcpy(lvbdata, lmm, lmmsize);
 	lock_res_and_lock(lock);
-	if (lock->l_lvb_data == NULL) {
-		lock->l_lvb_data = lvbdata;
-		lock->l_lvb_len = lmmsize;
-		lvbdata = NULL;
-	}
-	unlock_res_and_lock(lock);
+	if (lock->l_lvb_data != NULL)
+		OBD_FREE_LARGE(lock->l_lvb_data, lock->l_lvb_len);
 
-	if (lvbdata != NULL)
-		OBD_FREE_LARGE(lvbdata, lmmsize);
-	EXIT;
+	lock->l_lvb_data = lvbdata;
+	lock->l_lvb_len = lmmsize;
+	unlock_res_and_lock(lock);
 
 out:
 	ptlrpc_req_finished(req);
@@ -2999,7 +2955,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
 	int rc = 0;
 	bool lvb_ready;
 	bool wait_layout = false;
-	ENTRY;
 
 	LASSERT(lustre_handle_is_used(lockh));
 
@@ -3008,7 +2963,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
 	LASSERT(ldlm_has_layout(lock));
 
 	LDLM_DEBUG(lock, "File %p/"DFID" being reconfigured: %d.\n",
-		inode, PFID(&lli->lli_fid), reconf);
+		   inode, PFID(&lli->lli_fid), reconf);
 
 	/* in case this is a caching lock and reinstate with new inode */
 	md_set_lock_data(sbi->ll_md_exp, &lockh->cookie, inode, NULL);
@@ -3068,7 +3023,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
 
 	/* refresh layout failed, need to wait */
 	wait_layout = rc == -EBUSY;
-	EXIT;
 
 out:
 	LDLM_LOCK_PUT(lock);
@@ -3090,7 +3044,7 @@ out:
 		CDEBUG(D_INODE, "file: "DFID" waiting layout return: %d.\n",
 			PFID(&lli->lli_fid), rc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -3114,17 +3068,17 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen)
 	struct lookup_intent   it;
 	struct lustre_handle   lockh;
 	ldlm_mode_t	       mode;
-	struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS,
-					   .ei_mode = LCK_CR,
-					   .ei_cb_bl = ll_md_blocking_ast,
-					   .ei_cb_cp = ldlm_completion_ast,
-					   .ei_cbdata = NULL };
+	struct ldlm_enqueue_info einfo = {
+		.ei_type = LDLM_IBITS,
+		.ei_mode = LCK_CR,
+		.ei_cb_bl = ll_md_blocking_ast,
+		.ei_cb_cp = ldlm_completion_ast,
+	};
 	int rc;
-	ENTRY;
 
 	*gen = lli->lli_layout_gen;
 	if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK))
-		RETURN(0);
+		return 0;
 
 	/* sanity checks */
 	LASSERT(fid_is_sane(ll_inode2fid(inode)));
@@ -3136,7 +3090,7 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen)
 	if (mode != 0) { /* hit cached lock */
 		rc = ll_layout_lock_set(&lockh, mode, inode, gen, false);
 		if (rc == 0)
-			RETURN(0);
+			return 0;
 
 		/* better hold lli_layout_mutex to try again otherwise
 		 * it will have starvation problem. */
@@ -3154,14 +3108,14 @@ again:
 			goto again;
 
 		mutex_unlock(&lli->lli_layout_mutex);
-		RETURN(rc);
+		return rc;
 	}
 
 	op_data = ll_prep_md_op_data(NULL, inode, inode, NULL,
 			0, 0, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data)) {
 		mutex_unlock(&lli->lli_layout_mutex);
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 	}
 
 	/* have to enqueue one */
@@ -3194,5 +3148,5 @@ again:
 	}
 	mutex_unlock(&lli->lli_layout_mutex);
 
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/llite/llite_capa.c b/drivers/staging/lustre/lustre/llite/llite_capa.c
index b6fd959..edd512b2 100644
--- a/drivers/staging/lustre/lustre/llite/llite_capa.c
+++ b/drivers/staging/lustre/lustre/llite/llite_capa.c
@@ -41,7 +41,6 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 #include <linux/fs.h>
-#include <linux/version.h>
 #include <asm/uaccess.h>
 #include <linux/file.h>
 #include <linux/kmod.h>
@@ -171,7 +170,6 @@ static int capa_thread_main(void *unused)
 	struct inode *inode = NULL;
 	struct l_wait_info lwi = { 0 };
 	int rc;
-	ENTRY;
 
 	thread_set_flags(&ll_capa_thread, SVC_RUNNING);
 	wake_up(&ll_capa_thread.t_ctl_waitq);
@@ -281,7 +279,7 @@ static int capa_thread_main(void *unused)
 
 	thread_set_flags(&ll_capa_thread, SVC_STOPPED);
 	wake_up(&ll_capa_thread.t_ctl_waitq);
-	RETURN(0);
+	return 0;
 }
 
 void ll_capa_timer_callback(unsigned long unused)
@@ -291,8 +289,7 @@ void ll_capa_timer_callback(unsigned long unused)
 
 int ll_capa_thread_start(void)
 {
-	task_t *task;
-	ENTRY;
+	struct task_struct *task;
 
 	init_waitqueue_head(&ll_capa_thread.t_ctl_waitq);
 
@@ -300,12 +297,12 @@ int ll_capa_thread_start(void)
 	if (IS_ERR(task)) {
 		CERROR("cannot start expired capa thread: rc %ld\n",
 			PTR_ERR(task));
-		RETURN(PTR_ERR(task));
+		return PTR_ERR(task);
 	}
 	wait_event(ll_capa_thread.t_ctl_waitq,
 		       thread_is_running(&ll_capa_thread));
 
-	RETURN(0);
+	return 0;
 }
 
 void ll_capa_thread_stop(void)
@@ -322,10 +319,8 @@ struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc)
 	struct obd_capa *ocapa;
 	int found = 0;
 
-	ENTRY;
-
 	if ((ll_i2sbi(inode)->ll_flags & LL_SBI_OSS_CAPA) == 0)
-		RETURN(NULL);
+		return NULL;
 
 	LASSERT(opc == CAPA_OPC_OSS_WRITE || opc == CAPA_OPC_OSS_RW ||
 		opc == CAPA_OPC_OSS_TRUNC);
@@ -369,7 +364,7 @@ struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc)
 	}
 	spin_unlock(&capa_lock);
 
-	RETURN(ocapa);
+	return ocapa;
 }
 EXPORT_SYMBOL(ll_osscapa_get);
 
@@ -377,12 +372,11 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct obd_capa *ocapa;
-	ENTRY;
 
 	LASSERT(inode != NULL);
 
 	if ((ll_i2sbi(inode)->ll_flags & LL_SBI_MDS_CAPA) == 0)
-		RETURN(NULL);
+		return NULL;
 
 	spin_lock(&capa_lock);
 	ocapa = capa_get(lli->lli_mds_capa);
@@ -392,7 +386,7 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode)
 		atomic_set(&ll_capa_debug, 0);
 	}
 
-	RETURN(ocapa);
+	return ocapa;
 }
 
 static struct obd_capa *do_add_mds_capa(struct inode *inode,
@@ -525,7 +519,6 @@ int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
 {
 	struct inode *inode = ocapa->u.cli.inode;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(ocapa);
 
@@ -561,7 +554,7 @@ int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
 
 		capa_put(ocapa);
 		iput(inode);
-		RETURN(rc);
+		return rc;
 	}
 
 	spin_lock(&ocapa->c_lock);
@@ -575,7 +568,6 @@ int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
 	if (capa_for_oss(capa))
 		inode_add_oss_capa(inode, ocapa);
 	DEBUG_CAPA(D_SEC, capa, "renew");
-	EXIT;
 retry:
 	list_del_init(&ocapa->c_list);
 	sort_add_capa(ocapa, ll_capa_list);
diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c
index 00b2b38..1f5825c 100644
--- a/drivers/staging/lustre/lustre/llite/llite_close.c
+++ b/drivers/staging/lustre/lustre/llite/llite_close.c
@@ -50,14 +50,12 @@ void vvp_write_pending(struct ccc_object *club, struct ccc_page *page)
 {
 	struct ll_inode_info *lli = ll_i2info(club->cob_inode);
 
-	ENTRY;
 	spin_lock(&lli->lli_lock);
 	lli->lli_flags |= LLIF_SOM_DIRTY;
 	if (page != NULL && list_empty(&page->cpg_pending_linkage))
 		list_add(&page->cpg_pending_linkage,
 			     &club->cob_pending_list);
 	spin_unlock(&lli->lli_lock);
-	EXIT;
 }
 
 /** records that a write has completed */
@@ -66,7 +64,6 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page)
 	struct ll_inode_info *lli = ll_i2info(club->cob_inode);
 	int rc = 0;
 
-	ENTRY;
 	spin_lock(&lli->lli_lock);
 	if (page != NULL && !list_empty(&page->cpg_pending_linkage)) {
 		list_del_init(&page->cpg_pending_linkage);
@@ -75,7 +72,6 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page)
 	spin_unlock(&lli->lli_lock);
 	if (rc)
 		ll_queue_done_writing(club->cob_inode, 0);
-	EXIT;
 }
 
 /** Queues DONE_WRITING if
@@ -85,7 +81,6 @@ void ll_queue_done_writing(struct inode *inode, unsigned long flags)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct ccc_object *club = cl2ccc(ll_i2info(inode)->lli_clob);
-	ENTRY;
 
 	spin_lock(&lli->lli_lock);
 	lli->lli_flags |= flags;
@@ -119,14 +114,12 @@ void ll_queue_done_writing(struct inode *inode, unsigned long flags)
 		spin_unlock(&lcq->lcq_lock);
 	}
 	spin_unlock(&lli->lli_lock);
-	EXIT;
 }
 
 /** Pack SOM attributes info @opdata for CLOSE, DONE_WRITING rpc. */
 void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
-	ENTRY;
 
 	op_data->op_flags |= MF_SOM_CHANGE;
 	/* Check if Size-on-MDS attributes are valid. */
@@ -140,7 +133,6 @@ void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data)
 		op_data->op_attr.ia_valid |= ATTR_MTIME_SET | ATTR_CTIME_SET |
 				ATTR_ATIME_SET | ATTR_SIZE | ATTR_BLOCKS;
 	}
-	EXIT;
 }
 
 /** Closes ioepoch and packs Size-on-MDS attribute if needed into @op_data. */
@@ -149,7 +141,6 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data,
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct ccc_object *club = cl2ccc(ll_i2info(inode)->lli_clob);
-	ENTRY;
 
 	spin_lock(&lli->lli_lock);
 	if (!(list_empty(&club->cob_pending_list))) {
@@ -209,7 +200,6 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data,
 	spin_unlock(&lli->lli_lock);
 	ll_done_writing_attr(inode, op_data);
 
-	EXIT;
 out:
 	return;
 }
@@ -225,7 +215,6 @@ int ll_som_update(struct inode *inode, struct md_op_data *op_data)
 	__u32 old_flags;
 	struct obdo *oa;
 	int rc;
-	ENTRY;
 
 	LASSERT(op_data != NULL);
 	if (lli->lli_flags & LLIF_MDS_SIZE_LOCK)
@@ -236,7 +225,7 @@ int ll_som_update(struct inode *inode, struct md_op_data *op_data)
 	OBDO_ALLOC(oa);
 	if (!oa) {
 		CERROR("can't allocate memory for Size-on-MDS update.\n");
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	old_flags = op_data->op_flags;
@@ -266,7 +255,7 @@ int ll_som_update(struct inode *inode, struct md_op_data *op_data)
 	ptlrpc_req_finished(request);
 
 	OBDO_FREE(oa);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -293,14 +282,12 @@ static void ll_done_writing(struct inode *inode)
 	struct obd_client_handle *och = NULL;
 	struct md_op_data *op_data;
 	int rc;
-	ENTRY;
 
 	LASSERT(exp_connect_som(ll_i2mdexp(inode)));
 
 	OBD_ALLOC_PTR(op_data);
 	if (op_data == NULL) {
 		CERROR("can't allocate op_data\n");
-		EXIT;
 		return;
 	}
 
@@ -324,7 +311,6 @@ out:
 		md_clear_open_replay_data(ll_i2sbi(inode)->ll_md_exp, och);
 		OBD_FREE_PTR(och);
 	}
-	EXIT;
 }
 
 static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq)
@@ -347,7 +333,6 @@ static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq)
 static int ll_close_thread(void *arg)
 {
 	struct ll_close_queue *lcq = arg;
-	ENTRY;
 
 	complete(&lcq->lcq_comp);
 
@@ -371,13 +356,13 @@ static int ll_close_thread(void *arg)
 
 	CDEBUG(D_INFO, "ll_close exiting\n");
 	complete(&lcq->lcq_comp);
-	RETURN(0);
+	return 0;
 }
 
 int ll_close_thread_start(struct ll_close_queue **lcq_ret)
 {
 	struct ll_close_queue *lcq;
-	task_t *task;
+	struct task_struct *task;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CLOSE_THREAD))
 		return -EINTR;
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index 5227c5c..47e443d 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -90,6 +90,7 @@ extern struct file_operations ll_pgcache_seq_fops;
 #define REMOTE_PERM_HASHSIZE 16
 
 struct ll_getname_data {
+	struct dir_context ctx;
 	char	    *lgd_name;      /* points to a buffer with NAME_MAX+1 size */
 	struct lu_fid    lgd_fid;       /* target fid we are looking for */
 	int	      lgd_found;     /* inode matched? */
@@ -438,14 +439,6 @@ struct rmtacl_ctl_table {
 
 #define EE_HASHES       32
 
-struct eacl_entry {
-	struct list_head	    ee_list;
-	pid_t		 ee_key; /* hash key */
-	struct lu_fid	 ee_fid;
-	int		   ee_type; /* ACL type for ACCESS or DEFAULT */
-	ext_acl_xattr_header *ee_acl;
-};
-
 struct eacl_table {
 	spinlock_t	et_lock;
 	struct list_head	et_entries[EE_HASHES];
@@ -512,6 +505,7 @@ struct ll_sb_info {
 						 * clustred nfs */
 	struct rmtacl_ctl_table   ll_rct;
 	struct eacl_table	 ll_et;
+	__kernel_fsid_t		  ll_fsid;
 };
 
 #define LL_DEFAULT_MAX_RW_CHUNK      (32 * 1024 * 1024)
@@ -687,8 +681,7 @@ extern struct file_operations ll_dir_operations;
 extern struct inode_operations ll_dir_inode_operations;
 struct page *ll_get_dir_page(struct inode *dir, __u64 hash,
 			     struct ll_dir_chain *chain);
-int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie,
-		filldir_t filldir);
+int ll_dir_read(struct inode *inode, struct dir_context *ctx);
 
 int ll_get_mdt_idx(struct inode *inode);
 /* llite/namei.c */
@@ -792,8 +785,7 @@ void ll_intent_release(struct lookup_intent *);
 void ll_invalidate_aliases(struct inode *);
 void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft);
 void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry);
-int ll_dcompare(const struct dentry *parent, const struct inode *pinode,
-		const struct dentry *dentry, const struct inode *inode,
+int ll_dcompare(const struct dentry *parent, const struct dentry *dentry,
 		unsigned int len, const char *str, const struct qstr *d_name);
 int ll_revalidate_it_finish(struct ptlrpc_request *request,
 			    struct lookup_intent *it, struct dentry *de);
@@ -842,6 +834,7 @@ char *ll_get_fsname(struct super_block *sb, char *buf, int buflen);
 /* llite/llite_nfs.c */
 extern struct export_operations lustre_export_operations;
 __u32 get_uuid2int(const char *name, int len);
+void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid);
 struct inode *search_inode_for_lustre(struct super_block *sb,
 				      const struct lu_fid *fid);
 
@@ -1129,7 +1122,7 @@ int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm);
 int lustre_check_remote_perm(struct inode *inode, int mask);
 
 /* llite/llite_capa.c */
-extern timer_list_t ll_capa_timer;
+extern struct timer_list ll_capa_timer;
 
 int ll_capa_thread_start(void);
 void ll_capa_thread_stop(void);
@@ -1168,6 +1161,14 @@ void ll_ra_stats_inc(struct address_space *mapping, enum ra_stat which);
 
 /* llite/llite_rmtacl.c */
 #ifdef CONFIG_FS_POSIX_ACL
+struct eacl_entry {
+	struct list_head	    ee_list;
+	pid_t		 ee_key; /* hash key */
+	struct lu_fid	 ee_fid;
+	int		   ee_type; /* ACL type for ACCESS or DEFAULT */
+	ext_acl_xattr_header *ee_acl;
+};
+
 obd_valid rce_ops2valid(int ops);
 struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key);
 int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops);
@@ -1183,6 +1184,11 @@ struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
 void et_search_free(struct eacl_table *et, pid_t key);
 void et_init(struct eacl_table *et);
 void et_fini(struct eacl_table *et);
+#else
+static inline obd_valid rce_ops2valid(int ops)
+{
+	return 0;
+}
 #endif
 
 /* statahead.c */
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index afae801..b868c2b 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -42,7 +42,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 
 #include <lustre_lite.h>
@@ -79,11 +78,10 @@ static struct ll_sb_info *ll_init_sbi(void)
 	struct sysinfo si;
 	class_uuid_t uuid;
 	int i;
-	ENTRY;
 
 	OBD_ALLOC(sbi, sizeof(*sbi));
 	if (!sbi)
-		RETURN(NULL);
+		return NULL;
 
 	spin_lock_init(&sbi->ll_lock);
 	mutex_init(&sbi->ll_lco.lco_lock);
@@ -141,13 +139,12 @@ static struct ll_sb_info *ll_init_sbi(void)
 	atomic_set(&sbi->ll_agl_total, 0);
 	sbi->ll_flags |= LL_SBI_AGL_ENABLED;
 
-	RETURN(sbi);
+	return sbi;
 }
 
 void ll_free_sbi(struct super_block *sb)
 {
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
-	ENTRY;
 
 	if (sbi != NULL) {
 		spin_lock(&ll_sb_lock);
@@ -155,7 +152,6 @@ void ll_free_sbi(struct super_block *sb)
 		spin_unlock(&ll_sb_lock);
 		OBD_FREE(sbi, sizeof(*sbi));
 	}
-	EXIT;
 }
 
 static struct dentry_operations ll_d_root_ops = {
@@ -178,22 +174,21 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 	struct lustre_md lmd;
 	obd_valid valid;
 	int size, err, checksum;
-	ENTRY;
 
 	obd = class_name2obd(md);
 	if (!obd) {
 		CERROR("MD %s: not setup or attached\n", md);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	OBD_ALLOC_PTR(data);
 	if (data == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	OBD_ALLOC_PTR(osfs);
 	if (osfs == NULL) {
 		OBD_FREE_PTR(data);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	if (proc_lustre_fs_root) {
@@ -583,15 +578,17 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 	/* s_dev is also used in lt_compare() to compare two fs, but that is
 	 * only a node-local comparison. */
 	uuid = obd_get_uuid(sbi->ll_md_exp);
-	if (uuid != NULL)
+	if (uuid != NULL) {
 		sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid));
+		get_uuid2fsid(uuid->uuid, strlen(uuid->uuid), &sbi->ll_fsid);
+	}
 
 	if (data != NULL)
 		OBD_FREE_PTR(data);
 	if (osfs != NULL)
 		OBD_FREE_PTR(osfs);
 
-	RETURN(err);
+	return err;
 out_root:
 	if (root)
 		iput(root);
@@ -627,7 +624,7 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize)
 	if (rc)
 		CERROR("Get max mdsize error rc %d \n", rc);
 
-	RETURN(rc);
+	return rc;
 }
 
 void ll_dump_inode(struct inode *inode)
@@ -676,7 +673,6 @@ void lustre_dump_dentry(struct dentry *dentry, int recur)
 void client_common_put_super(struct super_block *sb)
 {
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
-	ENTRY;
 
 #ifdef CONFIG_FS_POSIX_ACL
 	if (sbi->ll_flags & LL_SBI_RMT_CLIENT) {
@@ -703,16 +699,12 @@ void client_common_put_super(struct super_block *sb)
 	obd_fid_fini(sbi->ll_md_exp->exp_obd);
 	obd_disconnect(sbi->ll_md_exp);
 	sbi->ll_md_exp = NULL;
-
-	EXIT;
 }
 
 void ll_kill_super(struct super_block *sb)
 {
 	struct ll_sb_info *sbi;
 
-	ENTRY;
-
 	/* not init sb ?*/
 	if (!(sb->s_flags & MS_ACTIVE))
 		return;
@@ -725,31 +717,29 @@ void ll_kill_super(struct super_block *sb)
 		sb->s_dev = sbi->ll_sdev_orig;
 		sbi->ll_umounting = 1;
 	}
-	EXIT;
 }
 
 char *ll_read_opt(const char *opt, char *data)
 {
 	char *value;
 	char *retval;
-	ENTRY;
 
 	CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
 	if (strncmp(opt, data, strlen(opt)))
-		RETURN(NULL);
+		return NULL;
 	if ((value = strchr(data, '=')) == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	value++;
 	OBD_ALLOC(retval, strlen(value) + 1);
 	if (!retval) {
 		CERROR("out of memory!\n");
-		RETURN(NULL);
+		return NULL;
 	}
 
 	memcpy(retval, value, strlen(value)+1);
 	CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);
-	RETURN(retval);
+	return retval;
 }
 
 static inline int ll_set_opt(const char *opt, char *data, int fl)
@@ -765,10 +755,9 @@ static int ll_options(char *options, int *flags)
 {
 	int tmp;
 	char *s1 = options, *s2;
-	ENTRY;
 
 	if (!options)
-		RETURN(0);
+		return 0;
 
 	CDEBUG(D_CONFIG, "Parsing opts %s\n", options);
 
@@ -891,7 +880,7 @@ static int ll_options(char *options, int *flags)
 		}
 		LCONSOLE_ERROR_MSG(0x152, "Unknown option '%s', won't mount.\n",
 				   s1);
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 next:
 		/* Find next opt */
@@ -900,7 +889,7 @@ next:
 			break;
 		s1 = s2 + 1;
 	}
-	RETURN(0);
+	return 0;
 }
 
 void ll_lli_init(struct ll_inode_info *lli)
@@ -977,13 +966,12 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
 	/* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */
 	const int instlen = sizeof(cfg->cfg_instance) * 2 + 2;
 	int    err;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb);
 
 	OBD_ALLOC_PTR(cfg);
 	if (cfg == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	try_module_get(THIS_MODULE);
 
@@ -992,7 +980,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
 	if (!sbi) {
 		module_put(THIS_MODULE);
 		OBD_FREE_PTR(cfg);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags);
@@ -1058,7 +1046,7 @@ out_free:
 		LCONSOLE_WARN("Mounted %s\n", profilenm);
 
 	OBD_FREE_PTR(cfg);
-	RETURN(err);
+	return err;
 } /* ll_fill_super */
 
 void ll_put_super(struct super_block *sb)
@@ -1069,7 +1057,6 @@ void ll_put_super(struct super_block *sb)
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	char *profilenm = get_profile_name(sb);
 	int next, force = 1;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm);
 
@@ -1121,8 +1108,6 @@ void ll_put_super(struct super_block *sb)
 	lustre_common_put_super(sb);
 
 	module_put(THIS_MODULE);
-
-	EXIT;
 } /* client_put_super */
 
 struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock)
@@ -1176,7 +1161,6 @@ void ll_clear_inode(struct inode *inode)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino,
 	       inode->i_generation, inode);
@@ -1188,7 +1172,9 @@ void ll_clear_inode(struct inode *inode)
 		LASSERT(lli->lli_opendir_pid == 0);
 	}
 
+	spin_lock(&lli->lli_lock);
 	ll_i2info(inode)->lli_flags &= ~LLIF_MDS_SIZE_LOCK;
+	spin_unlock(&lli->lli_lock);
 	md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode));
 
 	LASSERT(!lli->lli_open_fd_write_count);
@@ -1235,8 +1221,6 @@ void ll_clear_inode(struct inode *inode)
 	 */
 	cl_inode_fini(inode);
 	lli->lli_has_smd = false;
-
-	EXIT;
 }
 
 int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
@@ -1247,12 +1231,11 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct ptlrpc_request *request = NULL;
 	int rc, ia_valid;
-	ENTRY;
 
 	op_data = ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, NULL, 0,
 			&request, mod);
@@ -1272,14 +1255,14 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
 		} else if (rc != -EPERM && rc != -EACCES && rc != -ETXTBSY) {
 			CERROR("md_setattr fails: rc = %d\n", rc);
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
 			      sbi->ll_md_exp, &md);
 	if (rc) {
 		ptlrpc_req_finished(request);
-		RETURN(rc);
+		return rc;
 	}
 
 	ia_valid = op_data->op_attr.ia_valid;
@@ -1296,7 +1279,7 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
 	ll_update_inode(inode, &md);
 	ptlrpc_req_finished(request);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Close IO epoch and send Size-on-MDS attribute update. */
@@ -1306,11 +1289,10 @@ static int ll_setattr_done_writing(struct inode *inode,
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(op_data != NULL);
 	if (!S_ISREG(inode->i_mode))
-		RETURN(0);
+		return 0;
 
 	CDEBUG(D_INODE, "Epoch "LPU64" closed on "DFID" for truncate\n",
 	       op_data->op_ioepoch, PFID(&lli->lli_fid));
@@ -1328,7 +1310,7 @@ static int ll_setattr_done_writing(struct inode *inode,
 		CERROR("inode %lu mdc truncate failed: rc = %d\n",
 		       inode->i_ino, rc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_setattr_ost(struct inode *inode, struct iattr *attr)
@@ -1372,7 +1354,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 	struct md_op_data *op_data = NULL;
 	struct md_open_data *mod = NULL;
 	int rc = 0, rc1 = 0;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, "
 		"valid %x\n", ll_get_fsname(inode->i_sb, NULL, 0), inode,
@@ -1383,7 +1364,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 		/* Check new size against VFS/VM file size limit and rlimit */
 		rc = inode_newsize_ok(inode, attr->ia_size);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		/* The maximum Lustre file size is variable, based on the
 		 * OST maximum object size and number of stripes.  This
@@ -1392,7 +1373,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 			CDEBUG(D_INODE,"file "DFID" too large %llu > "LPU64"\n",
 			       PFID(&lli->lli_fid), attr->ia_size,
 			       ll_file_maxbytes(inode));
-			RETURN(-EFBIG);
+			return -EFBIG;
 		}
 
 		attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
@@ -1400,24 +1381,24 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 
 	/* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
 	if (attr->ia_valid & TIMES_SET_FLAGS) {
-		if (current_fsuid() != inode->i_uid &&
+		if ((!uid_eq(current_fsuid(), inode->i_uid)) &&
 		    !cfs_capable(CFS_CAP_FOWNER))
-			RETURN(-EPERM);
+			return -EPERM;
 	}
 
 	/* We mark all of the fields "set" so MDS/OST does not re-set them */
 	if (attr->ia_valid & ATTR_CTIME) {
-		attr->ia_ctime = CFS_CURRENT_TIME;
+		attr->ia_ctime = CURRENT_TIME;
 		attr->ia_valid |= ATTR_CTIME_SET;
 	}
 	if (!(attr->ia_valid & ATTR_ATIME_SET) &&
 	    (attr->ia_valid & ATTR_ATIME)) {
-		attr->ia_atime = CFS_CURRENT_TIME;
+		attr->ia_atime = CURRENT_TIME;
 		attr->ia_valid |= ATTR_ATIME_SET;
 	}
 	if (!(attr->ia_valid & ATTR_MTIME_SET) &&
 	    (attr->ia_valid & ATTR_MTIME)) {
-		attr->ia_mtime = CFS_CURRENT_TIME;
+		attr->ia_mtime = CURRENT_TIME;
 		attr->ia_valid |= ATTR_MTIME_SET;
 	}
 
@@ -1439,7 +1420,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 
 	OBD_ALLOC_PTR(op_data);
 	if (op_data == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (!S_ISDIR(inode->i_mode)) {
 		if (attr->ia_valid & ATTR_SIZE)
@@ -1480,7 +1461,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 		 * setting times to past, but it is necessary due to possible
 		 * time de-synchronization between MDT inode and OST objects */
 		rc = ll_setattr_ost(inode, attr);
-	EXIT;
 out:
 	if (op_data) {
 		if (op_data->op_ioepoch) {
@@ -1537,12 +1517,11 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	struct obd_statfs obd_osfs;
 	int rc;
-	ENTRY;
 
 	rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags);
 	if (rc) {
 		CERROR("md_statfs fails: rc = %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	osfs->os_type = sb->s_magic;
@@ -1556,7 +1535,7 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
 	rc = obd_statfs_rqset(sbi->ll_dt_exp, &obd_osfs, max_age, flags);
 	if (rc) {
 		CERROR("obd_statfs fails: rc = %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	CDEBUG(D_SUPER, "OSC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
@@ -1578,7 +1557,7 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
 		osfs->os_ffree = obd_osfs.os_ffree;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 int ll_statfs(struct dentry *de, struct kstatfs *sfs)
 {
@@ -1615,7 +1594,7 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs)
 	sfs->f_blocks = osfs.os_blocks;
 	sfs->f_bfree = osfs.os_bfree;
 	sfs->f_bavail = osfs.os_bavail;
-
+	sfs->f_fsid = ll_s2sbi(sb)->ll_fsid;
 	return 0;
 }
 
@@ -1707,9 +1686,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
 		inode->i_blkbits = inode->i_sb->s_blocksize_bits;
 	}
 	if (body->valid & OBD_MD_FLUID)
-		inode->i_uid = body->uid;
+		inode->i_uid = make_kuid(&init_user_ns, body->uid);
 	if (body->valid & OBD_MD_FLGID)
-		inode->i_gid = body->gid;
+		inode->i_gid = make_kgid(&init_user_ns, body->gid);
 	if (body->valid & OBD_MD_FLFLAGS)
 		inode->i_flags = ll_ext_to_inode_flags(body->flags);
 	if (body->valid & OBD_MD_FLNLINK)
@@ -1755,7 +1734,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
 					/* Use old size assignment to avoid
 					 * deadlock bz14138 & bz14326 */
 					i_size_write(inode, body->size);
+					spin_lock(&lli->lli_lock);
 					lli->lli_flags |= LLIF_MDS_SIZE_LOCK;
+					spin_unlock(&lli->lli_lock);
 				}
 				ldlm_lock_decref(&lockh, mode);
 			}
@@ -1786,7 +1767,6 @@ void ll_read_inode2(struct inode *inode, void *opaque)
 {
 	struct lustre_md *md = opaque;
 	struct ll_inode_info *lli = ll_i2info(inode);
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
 	       PFID(&lli->lli_fid), inode);
@@ -1814,28 +1794,22 @@ void ll_read_inode2(struct inode *inode, void *opaque)
 		inode->i_op = &ll_file_inode_operations;
 		inode->i_fop = sbi->ll_fop;
 		inode->i_mapping->a_ops = (struct address_space_operations *)&ll_aops;
-		EXIT;
 	} else if (S_ISDIR(inode->i_mode)) {
 		inode->i_op = &ll_dir_inode_operations;
 		inode->i_fop = &ll_dir_operations;
-		EXIT;
 	} else if (S_ISLNK(inode->i_mode)) {
 		inode->i_op = &ll_fast_symlink_inode_operations;
-		EXIT;
 	} else {
 		inode->i_op = &ll_special_inode_operations;
 
 		init_special_inode(inode, inode->i_mode,
 				   inode->i_rdev);
-
-		EXIT;
 	}
 }
 
 void ll_delete_inode(struct inode *inode)
 {
 	struct cl_inode_info *lli = cl_i2info(inode);
-	ENTRY;
 
 	if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL)
 		/* discard all dirty pages before truncating them, required by
@@ -1859,8 +1833,6 @@ void ll_delete_inode(struct inode *inode)
 
 	ll_clear_inode(inode);
 	clear_inode(inode);
-
-	EXIT;
 }
 
 int ll_iocontrol(struct inode *inode, struct file *file,
@@ -1869,7 +1841,6 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct ptlrpc_request *req = NULL;
 	int rc, flags = 0;
-	ENTRY;
 
 	switch(cmd) {
 	case FSFILT_IOC_GETFLAGS: {
@@ -1880,14 +1851,14 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 					     0, 0, LUSTRE_OPC_ANY,
 					     NULL);
 		if (IS_ERR(op_data))
-			RETURN(PTR_ERR(op_data));
+			return PTR_ERR(op_data);
 
 		op_data->op_valid = OBD_MD_FLFLAGS;
 		rc = md_getattr(sbi->ll_md_exp, op_data, &req);
 		ll_finish_md_op_data(op_data);
 		if (rc) {
 			CERROR("failure %d inode %lu\n", rc, inode->i_ino);
-			RETURN(-abs(rc));
+			return -abs(rc);
 		}
 
 		body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
@@ -1896,7 +1867,7 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 
 		ptlrpc_req_finished(req);
 
-		RETURN(put_user(flags, (int *)arg));
+		return put_user(flags, (int *)arg);
 	}
 	case FSFILT_IOC_SETFLAGS: {
 		struct lov_stripe_md *lsm;
@@ -1904,12 +1875,12 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 		struct md_op_data *op_data;
 
 		if (get_user(flags, (int *)arg))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, NULL);
 		if (IS_ERR(op_data))
-			RETURN(PTR_ERR(op_data));
+			return PTR_ERR(op_data);
 
 		((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags = flags;
 		op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG;
@@ -1918,18 +1889,20 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 		ll_finish_md_op_data(op_data);
 		ptlrpc_req_finished(req);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		inode->i_flags = ll_ext_to_inode_flags(flags);
 
 		lsm = ccc_inode_lsm_get(inode);
-		if (lsm == NULL)
-			RETURN(0);
+		if (!lsm_has_objects(lsm)) {
+			ccc_inode_lsm_put(inode, lsm);
+			return 0;
+		}
 
 		OBDO_ALLOC(oinfo.oi_oa);
 		if (!oinfo.oi_oa) {
 			ccc_inode_lsm_put(inode, lsm);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		oinfo.oi_md = lsm;
 		oinfo.oi_oa->o_oi = lsm->lsm_oi;
@@ -1946,20 +1919,21 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 		if (rc && rc != -EPERM && rc != -EACCES)
 			CERROR("osc_setattr_async fails: rc = %d\n", rc);
 
-		RETURN(rc);
+		return rc;
 	}
 	default:
-		RETURN(-ENOSYS);
+		return -ENOSYS;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int ll_flush_ctx(struct inode *inode)
 {
 	struct ll_sb_info  *sbi = ll_i2sbi(inode);
 
-	CDEBUG(D_SEC, "flush context for user %d\n", current_uid());
+	CDEBUG(D_SEC, "flush context for user %d\n",
+		      from_kuid(&init_user_ns, current_uid()));
 
 	obd_set_info_async(NULL, sbi->ll_md_exp,
 			   sizeof(KEY_FLUSH_CTX), KEY_FLUSH_CTX,
@@ -1976,8 +1950,6 @@ void ll_umount_begin(struct super_block *sb)
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	struct obd_device *obd;
 	struct obd_ioctl_data *ioc_data;
-	ENTRY;
-
 
 	CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb,
 	       sb->s_count, atomic_read(&sb->s_active));
@@ -1986,7 +1958,6 @@ void ll_umount_begin(struct super_block *sb)
 	if (obd == NULL) {
 		CERROR("Invalid MDC connection handle "LPX64"\n",
 		       sbi->ll_md_exp->exp_handle.h_cookie);
-		EXIT;
 		return;
 	}
 	obd->obd_force = 1;
@@ -1995,7 +1966,6 @@ void ll_umount_begin(struct super_block *sb)
 	if (obd == NULL) {
 		CERROR("Invalid LOV connection handle "LPX64"\n",
 		       sbi->ll_dt_exp->exp_handle.h_cookie);
-		EXIT;
 		return;
 	}
 	obd->obd_force = 1;
@@ -2016,8 +1986,6 @@ void ll_umount_begin(struct super_block *sb)
 	 * schedule() and sleep one second if needed, and hope.
 	 */
 	schedule();
-
-	EXIT;
 }
 
 int ll_remount_fs(struct super_block *sb, int *flags, char *data)
@@ -2058,14 +2026,13 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
 	struct ll_sb_info *sbi = NULL;
 	struct lustre_md md;
 	int rc;
-	ENTRY;
 
 	LASSERT(*inode || sb);
 	sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode);
 	rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp,
 			      sbi->ll_md_exp, &md);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (*inode) {
 		ll_update_inode(*inode, &md);
@@ -2127,7 +2094,7 @@ out:
 	if (md.lsm != NULL)
 		obd_free_memmd(sbi->ll_dt_exp, &md.lsm);
 	md_free_lustre_md(sbi->ll_md_exp, &md);
-	RETURN(rc);
+	return rc;
 }
 
 int ll_obd_statfs(struct inode *inode, void *arg)
@@ -2238,8 +2205,8 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data,
 	op_data->op_namelen = namelen;
 	op_data->op_mode = mode;
 	op_data->op_mod_time = cfs_time_current_sec();
-	op_data->op_fsuid = current_fsuid();
-	op_data->op_fsgid = current_fsgid();
+	op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
+	op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
 	op_data->op_cap = cfs_curproc_cap_pack();
 	op_data->op_bias = 0;
 	op_data->op_cli_flags = 0;
@@ -2303,7 +2270,7 @@ int ll_show_options(struct seq_file *seq, struct dentry *dentry)
 	if (sbi->ll_flags & LL_SBI_USER_FID2PATH)
 		seq_puts(seq, ",user_fid2path");
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -2313,23 +2280,22 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg)
 {
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	struct obd_device *obd;
-	ENTRY;
 
 	if (cmd == OBD_IOC_GETDTNAME)
 		obd = class_exp2obd(sbi->ll_dt_exp);
 	else if (cmd == OBD_IOC_GETMDNAME)
 		obd = class_exp2obd(sbi->ll_md_exp);
 	else
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if (!obd)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	if (copy_to_user((void *)arg, obd->obd_name,
 			     strlen(obd->obd_name) + 1))
-		RETURN(-EFAULT);
+		return -EFAULT;
 
-	RETURN(0);
+	return 0;
 }
 
 /**
diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c
index d9590d8..caed642 100644
--- a/drivers/staging/lustre/lustre/llite/llite_mmap.c
+++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c
@@ -40,13 +40,9 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
-#include <linux/version.h>
 #include <asm/uaccess.h>
 
 #include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
 #include <linux/pagemap.h>
 
 #define DEBUG_SUBSYSTEM S_LLITE
@@ -74,7 +70,6 @@ struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr,
 			       size_t count)
 {
 	struct vm_area_struct *vma, *ret = NULL;
-	ENTRY;
 
 	/* mmap_sem must have been held by caller. */
 	LASSERT(!down_write_trylock(&mm->mmap_sem));
@@ -87,7 +82,7 @@ struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr,
 			break;
 		}
 	}
-	RETURN(ret);
+	return ret;
 }
 
 /**
@@ -107,16 +102,16 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma,
 			       struct cl_env_nest *nest,
 			       pgoff_t index, unsigned long *ra_flags)
 {
-	struct file       *file  = vma->vm_file;
-	struct inode      *inode = file->f_dentry->d_inode;
-	struct cl_io      *io;
-	struct cl_fault_io *fio;
-	struct lu_env     *env;
-	ENTRY;
+	struct file	       *file = vma->vm_file;
+	struct inode	       *inode = file->f_dentry->d_inode;
+	struct cl_io	       *io;
+	struct cl_fault_io     *fio;
+	struct lu_env	       *env;
+	int			rc;
 
 	*env_ret = NULL;
 	if (ll_file_nolock(file))
-		RETURN(ERR_PTR(-EOPNOTSUPP));
+		return ERR_PTR(-EOPNOTSUPP);
 
 	/*
 	 * page fault can be called when lustre IO is
@@ -127,7 +122,7 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma,
 	 */
 	env = cl_env_nested_get(nest);
 	if (IS_ERR(env))
-		 RETURN(ERR_PTR(-EINVAL));
+		 return ERR_PTR(-EINVAL);
 
 	*env_ret = env;
 
@@ -152,17 +147,22 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma,
 	CDEBUG(D_MMAP, "vm_flags: %lx (%lu %d)\n", vma->vm_flags,
 	       fio->ft_index, fio->ft_executable);
 
-	if (cl_io_init(env, io, CIT_FAULT, io->ci_obj) == 0) {
+	rc = cl_io_init(env, io, CIT_FAULT, io->ci_obj);
+	if (rc == 0) {
 		struct ccc_io *cio = ccc_env_io(env);
 		struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
 
 		LASSERT(cio->cui_cl.cis_io == io);
 
-		/* mmap lock must be MANDATORY
-		 * it has to cache pages. */
+		/* mmap lock must be MANDATORY it has to cache
+		 * pages. */
 		io->ci_lockreq = CILR_MANDATORY;
-
-		cio->cui_fd  = fd;
+		cio->cui_fd = fd;
+	} else {
+		LASSERT(rc < 0);
+		cl_io_fini(env, io);
+		cl_env_nested_put(nest, env);
+		io = ERR_PTR(rc);
 	}
 
 	return io;
@@ -180,7 +180,6 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
 	sigset_t	     set;
 	struct inode	     *inode;
 	struct ll_inode_info     *lli;
-	ENTRY;
 
 	LASSERT(vmpage != NULL);
 
@@ -190,7 +189,7 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
 
 	result = io->ci_result;
 	if (result < 0)
-		GOTO(out, result);
+		GOTO(out_io, result);
 
 	io->u.ci_fault.ft_mkwrite = 1;
 	io->u.ci_fault.ft_writable = 1;
@@ -250,16 +249,15 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
 			spin_unlock(&lli->lli_lock);
 		}
 	}
-	EXIT;
 
-out:
+out_io:
 	cl_io_fini(env, io);
 	cl_env_nested_put(&nest, env);
-
+out:
 	CDEBUG(D_MMAP, "%s mkwrite with %d\n", current->comm, result);
-
 	LASSERT(ergo(result == 0, PageLocked(vmpage)));
-	return(result);
+
+	return result;
 }
 
 
@@ -304,11 +302,10 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct cl_env_nest       nest;
 	int		      result;
 	int		      fault_ret = 0;
-	ENTRY;
 
 	io = ll_fault_io_init(vma, &env,  &nest, vmf->pgoff, &ra_flags);
 	if (IS_ERR(io))
-		RETURN(to_fault_error(PTR_ERR(io)));
+		return to_fault_error(PTR_ERR(io));
 
 	result = io->ci_result;
 	if (result == 0) {
@@ -335,7 +332,7 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 	CDEBUG(D_MMAP, "%s fault %d/%d\n",
 	       current->comm, fault_ret, result);
-	RETURN(fault_ret);
+	return fault_ret;
 }
 
 static int ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -431,11 +428,9 @@ static void ll_vm_open(struct vm_area_struct * vma)
 	struct inode *inode    = vma->vm_file->f_dentry->d_inode;
 	struct ccc_object *vob = cl_inode2ccc(inode);
 
-	ENTRY;
 	LASSERT(vma->vm_file);
 	LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0);
 	atomic_inc(&vob->cob_mmap_cnt);
-	EXIT;
 }
 
 /**
@@ -446,11 +441,9 @@ static void ll_vm_close(struct vm_area_struct *vma)
 	struct inode      *inode = vma->vm_file->f_dentry->d_inode;
 	struct ccc_object *vob   = cl_inode2ccc(inode);
 
-	ENTRY;
 	LASSERT(vma->vm_file);
 	atomic_dec(&vob->cob_mmap_cnt);
 	LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0);
-	EXIT;
 }
 
 
@@ -466,7 +459,6 @@ static inline unsigned long file_to_user(struct vm_area_struct *vma, __u64 byte)
 int ll_teardown_mmaps(struct address_space *mapping, __u64 first, __u64 last)
 {
 	int rc = -ENOENT;
-	ENTRY;
 
 	LASSERTF(last > first, "last "LPU64" first "LPU64"\n", last, first);
 	if (mapping_mapped(mapping)) {
@@ -475,7 +467,7 @@ int ll_teardown_mmaps(struct address_space *mapping, __u64 first, __u64 last)
 				    last - first + 1, 0);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static struct vm_operations_struct ll_file_vm_ops = {
@@ -489,10 +481,9 @@ int ll_file_mmap(struct file *file, struct vm_area_struct * vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	int rc;
-	ENTRY;
 
 	if (ll_file_nolock(file))
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_MAP, 1);
 	rc = generic_file_mmap(file, vma);
@@ -503,5 +494,5 @@ int ll_file_mmap(struct file *file, struct vm_area_struct * vma)
 		rc = ll_glimpse_size(inode);
 	}
 
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c
index 28cc41e..1767c74 100644
--- a/drivers/staging/lustre/lustre/llite/llite_nfs.c
+++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c
@@ -58,6 +58,22 @@ __u32 get_uuid2int(const char *name, int len)
 	return (key0 << 1);
 }
 
+void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid)
+{
+	__u64 key = 0, key0 = 0x12a3fe2d, key1 = 0x37abe8f9;
+
+	while (len--) {
+		key = key1 + (key0 ^ (*name++ * 7152373));
+		if (key & 0x8000000000000000ULL)
+			key -= 0x7fffffffffffffffULL;
+		key1 = key0;
+		key0 = key;
+	}
+
+	fsid->val[0] = key;
+	fsid->val[1] = key >> 32;
+}
+
 static int ll_nfs_test_inode(struct inode *inode, void *opaque)
 {
 	return lu_fid_eq(&ll_i2info(inode)->lli_fid,
@@ -75,17 +91,16 @@ struct inode *search_inode_for_lustre(struct super_block *sb,
 						      ll_need_32bit_api(sbi));
 	struct  md_op_data    *op_data;
 	int		   rc;
-	ENTRY;
 
 	CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid));
 
 	inode = ilookup5(sb, hash, ll_nfs_test_inode, (void *)fid);
 	if (inode)
-		RETURN(inode);
+		return inode;
 
 	rc = ll_get_max_mdsize(sbi, &eadatalen);
 	if (rc)
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 
 	/* Because inode is NULL, ll_prep_md_op_data can not
 	 * be used here. So we allocate op_data ourselves */
@@ -103,14 +118,14 @@ struct inode *search_inode_for_lustre(struct super_block *sb,
 	if (rc) {
 		CERROR("can't get object attrs, fid "DFID", rc %d\n",
 		       PFID(fid), rc);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 	rc = ll_prep_inode(&inode, req, sb, NULL);
 	ptlrpc_req_finished(req);
 	if (rc)
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 
-	RETURN(inode);
+	return inode;
 }
 
 struct lustre_nfs_fid {
@@ -123,20 +138,19 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
 {
 	struct inode  *inode;
 	struct dentry *result;
-	ENTRY;
 
 	CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid));
 	if (!fid_is_sane(fid))
-		RETURN(ERR_PTR(-ESTALE));
+		return ERR_PTR(-ESTALE);
 
 	inode = search_inode_for_lustre(sb, fid);
 	if (IS_ERR(inode))
-		RETURN(ERR_PTR(PTR_ERR(inode)));
+		return ERR_CAST(inode);
 
 	if (is_bad_inode(inode)) {
 		/* we didn't find the right inode.. */
 		iput(inode);
-		RETURN(ERR_PTR(-ESTALE));
+		return ERR_PTR(-ESTALE);
 	}
 
 	/**
@@ -154,11 +168,11 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
 
 	result = d_obtain_alias(inode);
 	if (IS_ERR(result))
-		RETURN(result);
+		return result;
 
 	ll_dops_init(result, 1, 0);
 
-	RETURN(result);
+	return result;
 }
 
 #define LUSTRE_NFS_FID	  0x97
@@ -176,20 +190,19 @@ static int ll_encode_fh(struct inode *inode, __u32 *fh, int *plen,
 			struct inode *parent)
 {
 	struct lustre_nfs_fid *nfs_fid = (void *)fh;
-	ENTRY;
 
 	CDEBUG(D_INFO, "encoding for (%lu,"DFID") maxlen=%d minlen=%d\n",
 	      inode->i_ino, PFID(ll_inode2fid(inode)), *plen,
 	      (int)sizeof(struct lustre_nfs_fid));
 
 	if (*plen < sizeof(struct lustre_nfs_fid) / 4)
-		RETURN(255);
+		return 255;
 
 	nfs_fid->lnf_child = *ll_inode2fid(inode);
 	nfs_fid->lnf_parent = *ll_inode2fid(parent);
 	*plen = sizeof(struct lustre_nfs_fid) / 4;
 
-	RETURN(LUSTRE_NFS_FID);
+	return LUSTRE_NFS_FID;
 }
 
 static int ll_nfs_get_name_filldir(void *cookie, const char *name, int namelen,
@@ -214,10 +227,12 @@ static int ll_get_name(struct dentry *dentry, char *name,
 		       struct dentry *child)
 {
 	struct inode *dir = dentry->d_inode;
-	struct ll_getname_data lgd;
-	__u64 offset = 0;
 	int rc;
-	ENTRY;
+	struct ll_getname_data lgd = {
+		.lgd_name = name,
+		.lgd_fid = ll_i2info(child->d_inode)->lli_fid,
+		.ctx.actor = ll_nfs_get_name_filldir,
+	};
 
 	if (!dir || !S_ISDIR(dir->i_mode))
 		GOTO(out, rc = -ENOTDIR);
@@ -225,17 +240,11 @@ static int ll_get_name(struct dentry *dentry, char *name,
 	if (!dir->i_fop)
 		GOTO(out, rc = -EINVAL);
 
-	lgd.lgd_name = name;
-	lgd.lgd_fid = ll_i2info(child->d_inode)->lli_fid;
-	lgd.lgd_found = 0;
-
 	mutex_lock(&dir->i_mutex);
-	rc = ll_dir_read(dir, &offset, &lgd, ll_nfs_get_name_filldir);
+	rc = ll_dir_read(dir, &lgd.ctx);
 	mutex_unlock(&dir->i_mutex);
 	if (!rc && !lgd.lgd_found)
 		rc = -ENOENT;
-	EXIT;
-
 out:
 	return rc;
 }
@@ -246,9 +255,9 @@ static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid,
 	struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
 
 	if (fh_type != LUSTRE_NFS_FID)
-		RETURN(ERR_PTR(-EPROTO));
+		return ERR_PTR(-EPROTO);
 
-	RETURN(ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent));
+	return ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent);
 }
 
 static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
@@ -257,9 +266,9 @@ static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
 	struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
 
 	if (fh_type != LUSTRE_NFS_FID)
-		RETURN(ERR_PTR(-EPROTO));
+		return ERR_PTR(-EPROTO);
 
-	RETURN(ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL));
+	return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL);
 }
 
 static struct dentry *ll_get_parent(struct dentry *dchild)
@@ -273,7 +282,6 @@ static struct dentry *ll_get_parent(struct dentry *dchild)
 	struct md_op_data     *op_data;
 	int		   rc;
 	int		      lmmsize;
-	ENTRY;
 
 	LASSERT(dir && S_ISDIR(dir->i_mode));
 
@@ -284,19 +292,19 @@ static struct dentry *ll_get_parent(struct dentry *dchild)
 
 	rc = ll_get_max_mdsize(sbi, &lmmsize);
 	if (rc != 0)
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 
 	op_data = ll_prep_md_op_data(NULL, dir, NULL, dotdot,
 				     strlen(dotdot), lmmsize,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN((void *)op_data);
+		return (void *)op_data;
 
 	rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
 	ll_finish_md_op_data(op_data);
 	if (rc) {
 		CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 	body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 	LASSERT(body->valid & OBD_MD_FLID);
@@ -307,7 +315,7 @@ static struct dentry *ll_get_parent(struct dentry *dchild)
 	result = ll_iget_for_nfs(dir->i_sb, &body->fid1, NULL);
 
 	ptlrpc_req_finished(req);
-	RETURN(result);
+	return result;
 }
 
 struct export_operations lustre_export_operations = {
diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c
index 9d4c17e..2340458 100644
--- a/drivers/staging/lustre/lustre/llite/lloop.c
+++ b/drivers/staging/lustre/lustre/llite/lloop.c
@@ -99,7 +99,6 @@
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
-#include <linux/swap.h>
 #include <linux/pagevec.h>
 
 #include <asm/uaccess.h>
@@ -574,7 +573,7 @@ static int loop_clr_fd(struct lloop_device *lo, struct block_device *bdev,
 	lo->lo_offset = 0;
 	lo->lo_sizelimit = 0;
 	lo->lo_flags = 0;
-	ll_invalidate_bdev(bdev, 0);
+	invalidate_bdev(bdev);
 	set_capacity(disks[lo->lo_number], 0);
 	bd_set_size(bdev, 0);
 	mapping_set_gfp_mask(filp->f_mapping, gfp);
@@ -618,7 +617,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
 	case LL_IOC_LLOOP_DETACH: {
 		err = loop_clr_fd(lo, bdev, 2);
 		if (err == 0)
-			ll_blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */
+			blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */
 		break;
 	}
 
@@ -713,7 +712,7 @@ static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file,
 		err = loop_set_fd(lo, NULL, bdev, file);
 		if (err) {
 			fput(file);
-			ll_blkdev_put(bdev, 0);
+			blkdev_put(bdev, 0);
 		}
 
 		break;
@@ -737,7 +736,7 @@ static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file,
 		bdev = lo->lo_device;
 		err = loop_clr_fd(lo, bdev, 1);
 		if (err == 0)
-			ll_blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */
+			blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */
 
 		break;
 	}
@@ -849,10 +848,8 @@ static void lloop_exit(void)
 		blk_cleanup_queue(loop_dev[i].lo_queue);
 		put_disk(disks[i]);
 	}
-	if (ll_unregister_blkdev(lloop_major, "lloop"))
-		CWARN("lloop: cannot unregister blkdev\n");
-	else
-		CDEBUG(D_CONFIG, "unregistered lloop major %d\n", lloop_major);
+
+	unregister_blkdev(lloop_major, "lloop");
 
 	OBD_FREE(disks, max_loop * sizeof(*disks));
 	OBD_FREE(loop_dev, max_loop * sizeof(*loop_dev));
diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c
index 6a82505..d4d3c17 100644
--- a/drivers/staging/lustre/lustre/llite/lproc_llite.c
+++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c
@@ -35,7 +35,6 @@
  */
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <linux/version.h>
 #include <lustre_lite.h>
 #include <lprocfs_status.h>
 #include <linux/seq_file.h>
@@ -243,9 +242,9 @@ static ssize_t ll_max_readahead_mb_seq_write(struct file *file, const char *buff
 	if (rc)
 		return rc;
 
-	if (pages_number < 0 || pages_number > num_physpages / 2) {
+	if (pages_number < 0 || pages_number > totalram_pages / 2) {
 		CERROR("can't set file readahead more than %lu MB\n",
-		       num_physpages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/
+		       totalram_pages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/
 		return -ERANGE;
 	}
 
@@ -380,23 +379,22 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, const char *buffer,
 	int mult, rc, pages_number;
 	int diff = 0;
 	int nrpages = 0;
-	ENTRY;
 
 	mult = 1 << (20 - PAGE_CACHE_SHIFT);
 	buffer = lprocfs_find_named_value(buffer, "max_cached_mb:", &count);
 	rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
-	if (pages_number < 0 || pages_number > num_physpages) {
+	if (pages_number < 0 || pages_number > totalram_pages) {
 		CERROR("%s: can't set max cache more than %lu MB\n",
 		       ll_get_fsname(sb, NULL, 0),
-		       num_physpages >> (20 - PAGE_CACHE_SHIFT));
-		RETURN(-ERANGE);
+		       totalram_pages >> (20 - PAGE_CACHE_SHIFT));
+		return -ERANGE;
 	}
 
 	if (sbi->ll_dt_exp == NULL)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	spin_lock(&sbi->ll_lock);
 	diff = pages_number - cache->ccc_lru_max;
@@ -421,7 +419,7 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, const char *buffer,
 				break;
 
 			nv = ov > diff ? ov - diff : 0;
-			rc = cfs_atomic_cmpxchg(&cache->ccc_lru_left, ov, nv);
+			rc = atomic_cmpxchg(&cache->ccc_lru_left, ov, nv);
 			if (likely(ov == rc)) {
 				diff -= ov - nv;
 				nrpages += ov - nv;
@@ -822,7 +820,8 @@ void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count)
 		 sbi->ll_stats_track_id == current->parent->pid)
 		lprocfs_counter_add(sbi->ll_stats, op, count);
 	else if (sbi->ll_stats_track_type == STATS_TRACK_GID &&
-		 sbi->ll_stats_track_id == current_gid())
+		 sbi->ll_stats_track_id ==
+			from_kgid(&init_user_ns, current_gid()))
 		lprocfs_counter_add(sbi->ll_stats, op, count);
 }
 EXPORT_SYMBOL(ll_stats_ops_tally);
@@ -852,10 +851,9 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
 	struct lustre_sb_info *lsi = s2lsi(sb);
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	struct obd_device *obd;
-	proc_dir_entry_t *dir;
+	struct proc_dir_entry *dir;
 	char name[MAX_STRING_SIZE + 1], *ptr;
 	int err, id, len, rc;
-	ENTRY;
 
 	memset(lvars, 0, sizeof(lvars));
 
@@ -880,7 +878,7 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
 	if (IS_ERR(sbi->ll_proc_root)) {
 		err = PTR_ERR(sbi->ll_proc_root);
 		sbi->ll_proc_root = NULL;
-		RETURN(err);
+		return err;
 	}
 
 	rc = lprocfs_seq_create(sbi->ll_proc_root, "dump_page_cache", 0444,
@@ -994,7 +992,7 @@ out:
 		lprocfs_free_stats(&sbi->ll_ra_stats);
 		lprocfs_free_stats(&sbi->ll_stats);
 	}
-	RETURN(err);
+	return err;
 }
 
 void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi)
@@ -1302,8 +1300,9 @@ static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
 	/* We stored the discontiguous offsets here; print them first */
 	for(i = 0; i < LL_OFFSET_HIST_MAX; i++) {
 		if (offset[i].rw_pid != 0)
-			seq_printf(seq,"%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
-				   offset[i].rw_op ? 'W' : 'R',
+			seq_printf(seq,
+				   "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
+				   offset[i].rw_op == READ ? 'R' : 'W',
 				   offset[i].rw_pid,
 				   offset[i].rw_range_start,
 				   offset[i].rw_range_end,
@@ -1314,8 +1313,9 @@ static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
 	/* Then print the current offsets for each process */
 	for(i = 0; i < LL_PROCESS_HIST_MAX; i++) {
 		if (process[i].rw_pid != 0)
-			seq_printf(seq,"%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
-				   process[i].rw_op ? 'W' : 'R',
+			seq_printf(seq,
+				   "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
+				   process[i].rw_op == READ ? 'R' : 'W',
 				   process[i].rw_pid,
 				   process[i].rw_range_start,
 				   process[i].rw_last_file_pos,
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index ff8f63d..34815b5 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -77,11 +77,9 @@ static int ll_d_mountpoint(struct dentry *dparent, struct dentry *dchild,
 
 int ll_unlock(__u32 mode, struct lustre_handle *lockh)
 {
-	ENTRY;
-
 	ldlm_lock_decref(lockh, mode);
 
-	RETURN(0);
+	return 0;
 }
 
 
@@ -139,7 +137,6 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash,
 		      struct lustre_md *md)
 {
 	struct inode	 *inode;
-	ENTRY;
 
 	LASSERT(hash != 0);
 	inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md);
@@ -169,7 +166,7 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash,
 		CDEBUG(D_VFSTRACE, "got inode: %p for "DFID"\n",
 		       inode, PFID(&md->body->fid1));
 	}
-	RETURN(inode);
+	return inode;
 }
 
 static void ll_invalidate_negative_children(struct inode *dir)
@@ -200,7 +197,6 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 {
 	int rc;
 	struct lustre_handle lockh;
-	ENTRY;
 
 	switch (flag) {
 	case LDLM_CB_BLOCKING:
@@ -208,7 +204,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 		rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
 		if (rc < 0) {
 			CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
-			RETURN(rc);
+			return rc;
 		}
 		break;
 	case LDLM_CB_CANCELING: {
@@ -275,8 +271,11 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 				CDEBUG(D_INODE, "invaliding layout %d.\n", rc);
 		}
 
-		if (bits & MDS_INODELOCK_UPDATE)
+		if (bits & MDS_INODELOCK_UPDATE) {
+			spin_lock(&lli->lli_lock);
 			lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK;
+			spin_unlock(&lli->lli_lock);
+		}
 
 		if (S_ISDIR(inode->i_mode) &&
 		     (bits & MDS_INODELOCK_UPDATE)) {
@@ -297,13 +296,13 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 		LBUG();
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 __u32 ll_i2suppgid(struct inode *i)
 {
-	if (current_is_in_group(i->i_gid))
-		return (__u32)i->i_gid;
+	if (in_group_p(i->i_gid))
+		return (__u32)from_kgid(&init_user_ns, i->i_gid);
 	else
 		return (__u32)(-1);
 }
@@ -430,7 +429,6 @@ int ll_lookup_it_finish(struct ptlrpc_request *request,
 	struct inode *inode = NULL;
 	__u64 bits = 0;
 	int rc;
-	ENTRY;
 
 	/* NB 1 request reference will be taken away by ll_intent_lock()
 	 * when I return */
@@ -439,7 +437,7 @@ int ll_lookup_it_finish(struct ptlrpc_request *request,
 	if (!it_disposition(it, DISP_LOOKUP_NEG)) {
 		rc = ll_prep_inode(&inode, request, (*de)->d_sb, it);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		ll_set_lock_data(ll_i2sbi(parent)->ll_md_exp, inode, it, &bits);
 
@@ -480,7 +478,7 @@ int ll_lookup_it_finish(struct ptlrpc_request *request,
 		}
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
@@ -493,10 +491,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 	struct it_cb_data icbd;
 	__u32 opc;
 	int rc;
-	ENTRY;
 
 	if (dentry->d_name.len > ll_i2sbi(parent)->ll_namelen)
-		RETURN(ERR_PTR(-ENAMETOOLONG));
+		return ERR_PTR(-ENAMETOOLONG);
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
 	       dentry->d_name.len, dentry->d_name.name, parent->i_ino,
@@ -514,7 +511,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 		rc = ll_inode_revalidate_it(parent->i_sb->s_root, it,
 					    MDS_INODELOCK_LOOKUP);
 		if (rc)
-			RETURN(ERR_PTR(rc));
+			return ERR_PTR(rc);
 	}
 
 	if (it->it_op == IT_GETATTR) {
@@ -539,7 +536,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 				     dentry->d_name.len, lookup_flags, opc,
 				     NULL);
 	if (IS_ERR(op_data))
-		RETURN((void *)op_data);
+		return (void *)op_data;
 
 	/* enforce umask if acl disabled or MDS doesn't support umask */
 	if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent)))
@@ -618,7 +615,6 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
 	struct dentry *de;
 	long long lookup_flags = LOOKUP_OPEN;
 	int rc = 0;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),file %p,"
 			   "open_flags %x,mode %x opened %d\n",
@@ -627,7 +623,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
 
 	OBD_ALLOC(it, sizeof(*it));
 	if (!it)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	it->it_op = IT_OPEN;
 	if (mode) {
@@ -686,7 +682,7 @@ out_release:
 	ll_intent_release(it);
 	OBD_FREE(it, sizeof(*it));
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -700,7 +696,6 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
 	struct ptlrpc_request *request = NULL;
 	struct ll_sb_info *sbi = ll_i2sbi(dir);
 	int rc;
-	ENTRY;
 
 	LASSERT(it && it->d.lustre.it_disposition);
 
@@ -719,7 +714,6 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
 	CDEBUG(D_DLMTRACE, "setting l_ast_data to inode %p (%lu/%u)\n",
 	       inode, inode->i_ino, inode->i_generation);
 	ll_set_lock_data(sbi->ll_md_exp, inode, it, NULL);
-	EXIT;
  out:
 	ptlrpc_req_finished(request);
 	return inode;
@@ -744,7 +738,6 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
 {
 	struct inode *inode;
 	int rc = 0;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
 	       dentry->d_name.len, dentry->d_name.name, dir->i_ino,
@@ -752,18 +745,18 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
 
 	rc = it_open_error(DISP_OPEN_CREATE, it);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
 			       NULL, 0, mode, 0, it);
 	if (IS_ERR(inode))
-		RETURN(PTR_ERR(inode));
+		return PTR_ERR(inode);
 
 	if (filename_is_volatile(dentry->d_name.name, dentry->d_name.len, NULL))
 		ll_i2info(inode)->lli_volatile = true;
 
 	d_instantiate(dentry, inode);
-	RETURN(0);
+	return 0;
 }
 
 static void ll_update_times(struct ptlrpc_request *request,
@@ -795,7 +788,6 @@ static int ll_new_node(struct inode *dir, struct qstr *name,
 	int tgt_len = 0;
 	int err;
 
-	ENTRY;
 	if (unlikely(tgt != NULL))
 		tgt_len = strlen(tgt) + 1;
 
@@ -805,7 +797,8 @@ static int ll_new_node(struct inode *dir, struct qstr *name,
 		GOTO(err_exit, err = PTR_ERR(op_data));
 
 	err = md_create(sbi->ll_md_exp, op_data, tgt, tgt_len, mode,
-			current_fsuid(), current_fsgid(),
+			from_kuid(&init_user_ns, current_fsuid()),
+			from_kgid(&init_user_ns, current_fsgid()),
 			cfs_curproc_cap_pack(), rdev, &request);
 	ll_finish_md_op_data(op_data);
 	if (err)
@@ -820,7 +813,6 @@ static int ll_new_node(struct inode *dir, struct qstr *name,
 
 		d_instantiate(dchild, inode);
 	}
-	EXIT;
 err_exit:
 	ptlrpc_req_finished(request);
 
@@ -831,7 +823,6 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode,
 			    unsigned rdev, struct dentry *dchild)
 {
 	int err;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p) mode %o dev %x\n",
 	       name->len, name->name, dir->i_ino, dir->i_generation, dir,
@@ -861,7 +852,7 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode,
 	if (!err)
 		ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKNOD, 1);
 
-	RETURN(err);
+	return err;
 }
 
 /*
@@ -891,7 +882,6 @@ static int ll_symlink_generic(struct inode *dir, struct qstr *name,
 			      const char *tgt, struct dentry *dchild)
 {
 	int err;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),target=%.*s\n",
 	       name->len, name->name, dir->i_ino, dir->i_generation,
@@ -903,7 +893,7 @@ static int ll_symlink_generic(struct inode *dir, struct qstr *name,
 	if (!err)
 		ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_SYMLINK, 1);
 
-	RETURN(err);
+	return err;
 }
 
 static int ll_link_generic(struct inode *src,  struct inode *dir,
@@ -914,7 +904,6 @@ static int ll_link_generic(struct inode *src,  struct inode *dir,
 	struct md_op_data *op_data;
 	int err;
 
-	ENTRY;
 	CDEBUG(D_VFSTRACE,
 	       "VFS Op: inode=%lu/%u(%p), dir=%lu/%u(%p), target=%.*s\n",
 	       src->i_ino, src->i_generation, src, dir->i_ino,
@@ -923,7 +912,7 @@ static int ll_link_generic(struct inode *src,  struct inode *dir,
 	op_data = ll_prep_md_op_data(NULL, src, dir, name->name, name->len,
 				     0, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	err = md_link(sbi->ll_md_exp, op_data, &request);
 	ll_finish_md_op_data(op_data);
@@ -932,10 +921,9 @@ static int ll_link_generic(struct inode *src,  struct inode *dir,
 
 	ll_update_times(request, dir);
 	ll_stats_ops_tally(sbi, LPROC_LL_LINK, 1);
-	EXIT;
 out:
 	ptlrpc_req_finished(request);
-	RETURN(err);
+	return err;
 }
 
 static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
@@ -943,7 +931,6 @@ static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
 
 {
 	int err;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
 	       name->len, name->name, dir->i_ino, dir->i_generation, dir);
@@ -956,7 +943,7 @@ static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
 	if (!err)
 		ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1);
 
-	RETURN(err);
+	return err;
 }
 
 /* Try to find the child dentry by its name.
@@ -981,18 +968,17 @@ static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent,
 	struct ptlrpc_request *request = NULL;
 	struct md_op_data *op_data;
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
 	       name->len, name->name, dir->i_ino, dir->i_generation, dir);
 
 	if (unlikely(ll_d_mountpoint(dparent, dchild, name)))
-		RETURN(-EBUSY);
+		return -EBUSY;
 
 	op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name, name->len,
 				     S_IFDIR, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	ll_get_child_fid(dir, name, &op_data->op_fid3);
 	op_data->op_fid2 = op_data->op_fid3;
@@ -1004,7 +990,7 @@ static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent,
 	}
 
 	ptlrpc_req_finished(request);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1015,7 +1001,6 @@ int ll_rmdir_entry(struct inode *dir, char *name, int namelen)
 	struct ptlrpc_request *request = NULL;
 	struct md_op_data *op_data;
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
 	       namelen, name, dir->i_ino, dir->i_generation, dir);
@@ -1023,7 +1008,7 @@ int ll_rmdir_entry(struct inode *dir, char *name, int namelen)
 	op_data = ll_prep_md_op_data(NULL, dir, NULL, name, strlen(name),
 				     S_IFDIR, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 	op_data->op_cli_flags |= CLI_RM_ENTRY;
 	rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request);
 	ll_finish_md_op_data(op_data);
@@ -1033,7 +1018,7 @@ int ll_rmdir_entry(struct inode *dir, char *name, int namelen)
 	}
 
 	ptlrpc_req_finished(request);
-	RETURN(rc);
+	return rc;
 }
 
 int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
@@ -1045,12 +1030,11 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
 	struct obdo *oa;
 	struct obd_capa *oc = NULL;
 	int rc;
-	ENTRY;
 
 	/* req is swabbed so this is safe */
 	body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
 	if (!(body->valid & OBD_MD_FLEASIZE))
-		RETURN(0);
+		return 0;
 
 	if (body->eadatasize == 0) {
 		CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n");
@@ -1122,7 +1106,6 @@ static int ll_unlink_generic(struct inode *dir, struct dentry *dparent,
 	struct ptlrpc_request *request = NULL;
 	struct md_op_data *op_data;
 	int rc;
-	ENTRY;
 	CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
 	       name->len, name->name, dir->i_ino, dir->i_generation, dir);
 
@@ -1131,12 +1114,12 @@ static int ll_unlink_generic(struct inode *dir, struct dentry *dparent,
 	 * just check it as vfs_unlink does.
 	 */
 	if (unlikely(ll_d_mountpoint(dparent, dchild, name)))
-		RETURN(-EBUSY);
+		return -EBUSY;
 
 	op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name,
 				     name->len, 0, LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	ll_get_child_fid(dir, name, &op_data->op_fid3);
 	op_data->op_fid2 = op_data->op_fid3;
@@ -1151,7 +1134,7 @@ static int ll_unlink_generic(struct inode *dir, struct dentry *dparent,
 	rc = ll_objects_destroy(request, dir);
  out:
 	ptlrpc_req_finished(request);
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_rename_generic(struct inode *src, struct dentry *src_dparent,
@@ -1163,7 +1146,7 @@ static int ll_rename_generic(struct inode *src, struct dentry *src_dparent,
 	struct ll_sb_info *sbi = ll_i2sbi(src);
 	struct md_op_data *op_data;
 	int err;
-	ENTRY;
+
 	CDEBUG(D_VFSTRACE,"VFS Op:oldname=%.*s,src_dir=%lu/%u(%p),newname=%.*s,"
 	       "tgt_dir=%lu/%u(%p)\n", src_name->len, src_name->name,
 	       src->i_ino, src->i_generation, src, tgt_name->len,
@@ -1171,12 +1154,12 @@ static int ll_rename_generic(struct inode *src, struct dentry *src_dparent,
 
 	if (unlikely(ll_d_mountpoint(src_dparent, src_dchild, src_name) ||
 	    ll_d_mountpoint(tgt_dparent, tgt_dchild, tgt_name)))
-		RETURN(-EBUSY);
+		return -EBUSY;
 
 	op_data = ll_prep_md_op_data(NULL, src, tgt, NULL, 0, 0,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	ll_get_child_fid(src, src_name, &op_data->op_fid3);
 	ll_get_child_fid(tgt, tgt_name, &op_data->op_fid4);
@@ -1193,7 +1176,7 @@ static int ll_rename_generic(struct inode *src, struct dentry *src_dparent,
 
 	ptlrpc_req_finished(request);
 
-	RETURN(err);
+	return err;
 }
 
 static int ll_mknod(struct inode *dir, struct dentry *dchild, ll_umode_t mode,
diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c
index 68b2dc4..dedd56a 100644
--- a/drivers/staging/lustre/lustre/llite/remote_perm.c
+++ b/drivers/staging/lustre/lustre/llite/remote_perm.c
@@ -45,7 +45,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/version.h>
 
 #include <lustre_lite.h>
 #include <lustre_ha.h>
@@ -124,22 +123,22 @@ static int do_check_remote_perm(struct ll_inode_info *lli, int mask)
 	struct hlist_head *head;
 	struct ll_remote_perm *lrp;
 	int found = 0, rc;
-	ENTRY;
 
 	if (!lli->lli_remote_perms)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
-	head = lli->lli_remote_perms + remote_perm_hashfunc(current_uid());
+	head = lli->lli_remote_perms +
+		remote_perm_hashfunc(from_kuid(&init_user_ns, current_uid()));
 
 	spin_lock(&lli->lli_lock);
 	hlist_for_each_entry(lrp, head, lrp_list) {
-		if (lrp->lrp_uid != current_uid())
+		if (lrp->lrp_uid != from_kuid(&init_user_ns, current_uid()))
 			continue;
-		if (lrp->lrp_gid != current_gid())
+		if (lrp->lrp_gid != from_kgid(&init_user_ns, current_gid()))
 			continue;
-		if (lrp->lrp_fsuid != current_fsuid())
+		if (lrp->lrp_fsuid != from_kuid(&init_user_ns, current_fsuid()))
 			continue;
-		if (lrp->lrp_fsgid != current_fsgid())
+		if (lrp->lrp_fsgid != from_kgid(&init_user_ns, current_fsgid()))
 			continue;
 		found = 1;
 		break;
@@ -163,7 +162,6 @@ int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm)
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct ll_remote_perm *lrp = NULL, *tmp = NULL;
 	struct hlist_head *head, *perm_hash = NULL;
-	ENTRY;
 
 	LASSERT(ll_i2sbi(inode)->ll_flags & LL_SBI_RMT_CLIENT);
 
@@ -178,7 +176,7 @@ int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm)
 		       perm->rp_uid, perm->rp_gid, perm->rp_fsuid,
 		       perm->rp_fsgid, current->uid, current->gid,
 		       current->fsuid, current->fsgid);
-		RETURN(-EAGAIN);
+		return -EAGAIN;
 	}
 #endif
 
@@ -186,7 +184,7 @@ int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm)
 		perm_hash = alloc_rmtperm_hash();
 		if (perm_hash == NULL) {
 			CERROR("alloc lli_remote_perms failed!\n");
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 	}
 
@@ -220,7 +218,7 @@ again:
 		lrp = alloc_ll_remote_perm();
 		if (!lrp) {
 			CERROR("alloc memory for ll_remote_perm failed!\n");
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		spin_lock(&lli->lli_lock);
 		goto again;
@@ -241,7 +239,7 @@ again:
 	       lrp, lrp->lrp_uid, lrp->lrp_gid, lrp->lrp_fsuid, lrp->lrp_fsgid,
 	       lrp->lrp_access_perm);
 
-	RETURN(0);
+	return 0;
 }
 
 int lustre_check_remote_perm(struct inode *inode, int mask)
@@ -253,7 +251,6 @@ int lustre_check_remote_perm(struct inode *inode, int mask)
 	struct obd_capa *oc;
 	cfs_time_t save;
 	int i = 0, rc;
-	ENTRY;
 
 	do {
 		save = lli->lli_rmtperm_time;
@@ -304,7 +301,7 @@ int lustre_check_remote_perm(struct inode *inode, int mask)
 		req = NULL;
 	} while (1);
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 #if 0  /* NB: remote perms can't be freed in ll_mdc_blocking_ast of UPDATE lock,
diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c
index fac1178..ae0dc44 100644
--- a/drivers/staging/lustre/lustre/llite/rw.c
+++ b/drivers/staging/lustre/lustre/llite/rw.c
@@ -48,9 +48,6 @@
 #include <asm/uaccess.h>
 
 #include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
 #include <linux/pagemap.h>
 /* current_is_kswapd() */
 #include <linux/swap.h>
@@ -110,7 +107,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file,
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		return ERR_PTR(PTR_ERR(env));
+		return ERR_CAST(env);
 
 	lcc = &vvp_env_info(env)->vti_io_ctx;
 	memset(lcc, 0, sizeof(*lcc));
@@ -132,7 +129,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file,
 			 * add dirty pages into cache during truncate */
 			CERROR("Proc %s is dirting page w/o inode lock, this"
 			       "will break truncate.\n", current->comm);
-			libcfs_debug_dumpstack(NULL);
+			dump_stack();
 			LBUG();
 			return ERR_PTR(-EIO);
 		}
@@ -228,7 +225,6 @@ int ll_prepare_write(struct file *file, struct page *vmpage, unsigned from,
 {
 	struct ll_cl_context *lcc;
 	int result;
-	ENTRY;
 
 	lcc = ll_cl_init(file, vmpage, 1);
 	if (!IS_ERR(lcc)) {
@@ -256,7 +252,7 @@ int ll_prepare_write(struct file *file, struct page *vmpage, unsigned from,
 	} else {
 		result = PTR_ERR(lcc);
 	}
-	RETURN(result);
+	return result;
 }
 
 int ll_commit_write(struct file *file, struct page *vmpage, unsigned from,
@@ -267,7 +263,6 @@ int ll_commit_write(struct file *file, struct page *vmpage, unsigned from,
 	struct cl_io     *io;
 	struct cl_page   *page;
 	int result = 0;
-	ENTRY;
 
 	lcc  = ll_cl_get();
 	env  = lcc->lcc_env;
@@ -287,7 +282,7 @@ int ll_commit_write(struct file *file, struct page *vmpage, unsigned from,
 	lu_ref_del(&page->cp_reference, "prepare_write", current);
 	cl_page_put(env, page);
 	ll_cl_fini(lcc);
-	RETURN(result);
+	return result;
 }
 
 struct obd_capa *cl_capa_lookup(struct inode *inode, enum cl_req_type crt)
@@ -325,7 +320,6 @@ static unsigned long ll_ra_count_get(struct ll_sb_info *sbi,
 {
 	struct ll_ra_info *ra = &sbi->ll_ra_info;
 	long ret;
-	ENTRY;
 
 	/* If read-ahead pages left are less than 1M, do not do read-ahead,
 	 * otherwise it will form small read RPC(< 1M), which hurt server
@@ -357,7 +351,7 @@ static unsigned long ll_ra_count_get(struct ll_sb_info *sbi,
 	}
 
 out:
-	RETURN(ret);
+	return ret;
 }
 
 void ll_ra_count_put(struct ll_sb_info *sbi, unsigned long len)
@@ -468,8 +462,6 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io,
 	struct ccc_page *cp;
 	int	      rc;
 
-	ENTRY;
-
 	rc = 0;
 	cl_page_assume(env, io, page);
 	lu_ref_add(&page->cp_reference, "ra", current);
@@ -491,7 +483,7 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io,
 	}
 	lu_ref_del(&page->cp_reference, "ra", current);
 	cl_page_put(env, page);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -516,8 +508,6 @@ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io,
 	int	       rc    = 0;
 	const char       *msg   = NULL;
 
-	ENTRY;
-
 	gfp_mask = GFP_HIGHUSER & ~__GFP_WAIT;
 #ifdef __GFP_NOWARN
 	gfp_mask |= __GFP_NOWARN;
@@ -554,7 +544,7 @@ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io,
 		ll_ra_stats_inc(mapping, which);
 		CDEBUG(D_READA, "%s\n", msg);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 #define RIA_DEBUG(ria)						       \
@@ -722,7 +712,6 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io,
 	struct cl_object *clob;
 	int ret = 0;
 	__u64 kms;
-	ENTRY;
 
 	inode = mapping->host;
 	lli = ll_i2info(inode);
@@ -735,11 +724,11 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io,
 	cl_object_attr_unlock(clob);
 
 	if (ret != 0)
-		RETURN(ret);
+		return ret;
 	kms = attr->cat_kms;
 	if (kms == 0) {
 		ll_ra_stats_inc(mapping, RA_STAT_ZERO_LEN);
-		RETURN(0);
+		return 0;
 	}
 
 	spin_lock(&ras->ras_lock);
@@ -797,11 +786,11 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io,
 
 	if (end == 0) {
 		ll_ra_stats_inc(mapping, RA_STAT_ZERO_WINDOW);
-		RETURN(0);
+		return 0;
 	}
 	len = ria_page_count(ria);
 	if (len == 0)
-		RETURN(0);
+		return 0;
 
 	reserved = ll_ra_count_get(ll_i2sbi(inode), ria, len);
 	if (reserved < len)
@@ -840,7 +829,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io,
 		spin_unlock(&ras->ras_lock);
 	}
 
-	RETURN(ret);
+	return ret;
 }
 
 static void ras_set_start(struct inode *inode, struct ll_readahead_state *ras,
@@ -999,7 +988,6 @@ void ras_update(struct ll_sb_info *sbi, struct inode *inode,
 {
 	struct ll_ra_info *ra = &sbi->ll_ra_info;
 	int zero = 0, stride_detect = 0, ra_miss = 0;
-	ENTRY;
 
 	spin_lock(&ras->ras_lock);
 
@@ -1135,7 +1123,6 @@ void ras_update(struct ll_sb_info *sbi, struct inode *inode,
 	if ((ras->ras_consecutive_requests > 1 || stride_detect) &&
 	    !ras->ras_request_index)
 		ras_increase_window(inode, ras, ra);
-	EXIT;
 out_unlock:
 	RAS_CDEBUG(ras);
 	ras->ras_request_index++;
@@ -1155,7 +1142,6 @@ int ll_writepage(struct page *vmpage, struct writeback_control *wbc)
 	bool redirtied = false;
 	bool unlocked = false;
 	int result;
-	ENTRY;
 
 	LASSERT(PageLocked(vmpage));
 	LASSERT(!PageWriteback(vmpage));
@@ -1247,7 +1233,6 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc)
 	int range_whole = 0;
 	int result;
 	int ignore_layout = 0;
-	ENTRY;
 
 	if (wbc->range_cyclic) {
 		start = mapping->writeback_index << PAGE_CACHE_SHIFT;
@@ -1281,14 +1266,13 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc)
 			end = i_size_read(inode);
 		mapping->writeback_index = (end >> PAGE_CACHE_SHIFT) + 1;
 	}
-	RETURN(result);
+	return result;
 }
 
 int ll_readpage(struct file *file, struct page *vmpage)
 {
 	struct ll_cl_context *lcc;
 	int result;
-	ENTRY;
 
 	lcc = ll_cl_init(file, vmpage, 0);
 	if (!IS_ERR(lcc)) {
@@ -1310,5 +1294,5 @@ int ll_readpage(struct file *file, struct page *vmpage)
 		unlock_page(vmpage);
 		result = PTR_ERR(lcc);
 	}
-	RETURN(result);
+	return result;
 }
diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c
index 27e4e64..96c29ad 100644
--- a/drivers/staging/lustre/lustre/llite/rw26.c
+++ b/drivers/staging/lustre/lustre/llite/rw26.c
@@ -51,9 +51,6 @@
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
 #include <linux/writeback.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
 #include <linux/pagemap.h>
 
 #define DEBUG_SUBSYSTEM S_LLITE
@@ -72,7 +69,8 @@
  * aligned truncate). Lustre leaves partially truncated page in the cache,
  * relying on struct inode::i_size to limit further accesses.
  */
-static void ll_invalidatepage(struct page *vmpage, unsigned long offset)
+static void ll_invalidatepage(struct page *vmpage, unsigned int offset,
+			      unsigned int length)
 {
 	struct inode     *inode;
 	struct lu_env    *env;
@@ -89,7 +87,7 @@ static void ll_invalidatepage(struct page *vmpage, unsigned long offset)
 	 * below because they are run with page locked and all our io is
 	 * happening with locked page too
 	 */
-	if (offset == 0) {
+	if (offset == 0 && length == PAGE_CACHE_SIZE) {
 		env = cl_env_get(&refcheck);
 		if (!IS_ERR(env)) {
 			inode = vmpage->mapping->host;
@@ -182,7 +180,7 @@ static int ll_set_page_dirty(struct page *vmpage)
 	 */
 	vvp_write_pending(obj, cpg);
 #endif
-	RETURN(__set_page_dirty_nobuffers(vmpage));
+	return __set_page_dirty_nobuffers(vmpage);
 }
 
 #define MAX_DIRECTIO_SIZE 2*1024*1024*1024UL
@@ -249,7 +247,6 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
 	long page_size      = cl_page_size(obj);
 	bool do_io;
 	int  io_pages       = 0;
-	ENTRY;
 
 	queue = &io->ci_queue;
 	cl_2queue_init(queue);
@@ -286,11 +283,11 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
 			src_page = (rw == WRITE) ? pages[i] : vmpage;
 			dst_page = (rw == WRITE) ? vmpage : pages[i];
 
-			src = ll_kmap_atomic(src_page, KM_USER0);
-			dst = ll_kmap_atomic(dst_page, KM_USER1);
+			src = kmap_atomic(src_page);
+			dst = kmap_atomic(dst_page);
 			memcpy(dst, src, min(page_size, size));
-			ll_kunmap_atomic(dst, KM_USER1);
-			ll_kunmap_atomic(src, KM_USER0);
+			kunmap_atomic(dst);
+			kunmap_atomic(src);
 
 			/* make sure page will be added to the transfer by
 			 * cl_io_submit()->...->vvp_page_prep_write(). */
@@ -335,7 +332,7 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
 	cl_2queue_discard(env, io, queue);
 	cl_2queue_disown(env, io, queue);
 	cl_2queue_fini(env, queue);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ll_direct_rw_pages);
 
@@ -383,14 +380,13 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
 	unsigned long seg = 0;
 	long size = MAX_DIO_SIZE;
 	int refcheck;
-	ENTRY;
 
 	if (!lli->lli_has_smd)
-		RETURN(-EBADF);
+		return -EBADF;
 
 	/* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */
 	if ((file_offset & ~CFS_PAGE_MASK) || (count & ~CFS_PAGE_MASK))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), size=%lu (max %lu), "
 	       "offset=%lld=%llx, pages %lu (max %lu)\n",
@@ -402,7 +398,7 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
 	for (seg = 0; seg < nr_segs; seg++) {
 		if (((unsigned long)iov[seg].iov_base & ~CFS_PAGE_MASK) ||
 		    (iov[seg].iov_len & ~CFS_PAGE_MASK))
-			RETURN(-EINVAL);
+			return -EINVAL;
 	}
 
 	env = cl_env_get(&refcheck);
@@ -495,7 +491,7 @@ out:
 	}
 
 	cl_env_put(env, &refcheck);
-	RETURN(tot_bytes ? : result);
+	return tot_bytes ? : result;
 }
 
 static int ll_write_begin(struct file *file, struct address_space *mapping,
@@ -506,11 +502,10 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
 	struct page *page;
 	int rc;
 	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-	ENTRY;
 
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (!page)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	*pagep = page;
 
@@ -519,7 +514,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
 		unlock_page(page);
 		page_cache_release(page);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int ll_write_end(struct file *file, struct address_space *mapping,
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index 7747f8f..8eaa38e9 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -200,12 +200,11 @@ ll_sa_entry_alloc(struct ll_statahead_info *sai, __u64 index,
 	struct ll_sa_entry   *entry;
 	int		   entry_size;
 	char		 *dname;
-	ENTRY;
 
 	entry_size = sizeof(struct ll_sa_entry) + (len & ~3) + 4;
 	OBD_ALLOC(entry, entry_size);
 	if (unlikely(entry == NULL))
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	CDEBUG(D_READA, "alloc sa entry %.*s(%p) index "LPU64"\n",
 	       len, name, entry, index);
@@ -254,7 +253,7 @@ ll_sa_entry_alloc(struct ll_statahead_info *sai, __u64 index,
 
 	atomic_inc(&sai->sai_cache_count);
 
-	RETURN(entry);
+	return entry;
 }
 
 /*
@@ -465,11 +464,10 @@ static struct ll_statahead_info *ll_sai_alloc(void)
 {
 	struct ll_statahead_info *sai;
 	int		       i;
-	ENTRY;
 
 	OBD_ALLOC_PTR(sai);
 	if (!sai)
-		RETURN(NULL);
+		return NULL;
 
 	atomic_set(&sai->sai_refcount, 1);
 
@@ -496,7 +494,7 @@ static struct ll_statahead_info *ll_sai_alloc(void)
 	}
 	atomic_set(&sai->sai_cache_count, 0);
 
-	RETURN(sai);
+	return sai;
 }
 
 static inline struct ll_statahead_info *
@@ -510,7 +508,6 @@ static void ll_sai_put(struct ll_statahead_info *sai)
 {
 	struct inode	 *inode = sai->sai_inode;
 	struct ll_inode_info *lli   = ll_i2info(inode);
-	ENTRY;
 
 	if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_sa_lock)) {
 		struct ll_sa_entry *entry, *next;
@@ -519,7 +516,7 @@ static void ll_sai_put(struct ll_statahead_info *sai)
 			/* It is race case, the interpret callback just hold
 			 * a reference count */
 			spin_unlock(&lli->lli_sa_lock);
-			RETURN_EXIT;
+			return;
 		}
 
 		LASSERT(lli->lli_opendir_key == NULL);
@@ -550,8 +547,6 @@ static void ll_sai_put(struct ll_statahead_info *sai)
 		iput(inode);
 		OBD_FREE_PTR(sai);
 	}
-
-	EXIT;
 }
 
 /* Do NOT forget to drop inode refcount when into sai_entries_agl. */
@@ -560,7 +555,6 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
 	struct ll_inode_info *lli   = ll_i2info(inode);
 	__u64		 index = lli->lli_agl_index;
 	int		   rc;
-	ENTRY;
 
 	LASSERT(list_empty(&lli->lli_agl_list));
 
@@ -568,7 +562,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
 	if (is_omitted_entry(sai, index + 1)) {
 		lli->lli_agl_index = 0;
 		iput(inode);
-		RETURN_EXIT;
+		return;
 	}
 
 	/* Someone is in glimpse (sync or async), do nothing. */
@@ -576,7 +570,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
 	if (rc == 0) {
 		lli->lli_agl_index = 0;
 		iput(inode);
-		RETURN_EXIT;
+		return;
 	}
 
 	/*
@@ -597,7 +591,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
 		up_write(&lli->lli_glimpse_sem);
 		lli->lli_agl_index = 0;
 		iput(inode);
-		RETURN_EXIT;
+		return;
 	}
 
 	CDEBUG(D_READA, "Handling (init) async glimpse: inode = "
@@ -613,8 +607,6 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
 	       PFID(&lli->lli_fid), index, rc);
 
 	iput(inode);
-
-	EXIT;
 }
 
 static void ll_post_statahead(struct ll_statahead_info *sai)
@@ -628,12 +620,11 @@ static void ll_post_statahead(struct ll_statahead_info *sai)
 	struct ptlrpc_request  *req;
 	struct mdt_body	*body;
 	int		     rc    = 0;
-	ENTRY;
 
 	spin_lock(&lli->lli_sa_lock);
 	if (unlikely(sa_received_empty(sai))) {
 		spin_unlock(&lli->lli_sa_lock);
-		RETURN_EXIT;
+		return;
 	}
 	entry = sa_first_received_entry(sai);
 	atomic_inc(&entry->se_refcount);
@@ -690,8 +681,6 @@ static void ll_post_statahead(struct ll_statahead_info *sai)
 	if (agl_should_run(sai, child))
 		ll_agl_add(sai, child, entry->se_index);
 
-	EXIT;
-
 out:
 	/* The "ll_sa_entry_to_stated()" will drop related ldlm ibits lock
 	 * reference count by calling "ll_intent_drop_lock()" in spite of the
@@ -713,7 +702,6 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
 	struct ll_statahead_info *sai = NULL;
 	struct ll_sa_entry       *entry;
 	int		       wakeup;
-	ENTRY;
 
 	if (it_disposition(it, DISP_LOOKUP_NEG))
 		rc = -ENOENT;
@@ -763,8 +751,6 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
 			wake_up(&sai->sai_thread.t_ctl_waitq);
 	}
 
-	EXIT;
-
 out:
 	if (rc != 0) {
 		ll_intent_release(it);
@@ -852,11 +838,10 @@ static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry)
 	struct ldlm_enqueue_info *einfo;
 	struct obd_capa	  *capas[2];
 	int		       rc;
-	ENTRY;
 
 	rc = sa_args_init(dir, NULL, entry, &minfo, &einfo, capas);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo);
 	if (!rc) {
@@ -866,7 +851,7 @@ static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry)
 		sa_args_fini(minfo, einfo);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -885,30 +870,29 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry,
 	struct ldlm_enqueue_info *einfo;
 	struct obd_capa	  *capas[2];
 	int rc;
-	ENTRY;
 
 	if (unlikely(inode == NULL))
-		RETURN(1);
+		return 1;
 
 	if (d_mountpoint(dentry))
-		RETURN(1);
+		return 1;
 
 	if (unlikely(dentry == dentry->d_sb->s_root))
-		RETURN(1);
+		return 1;
 
 	entry->se_inode = igrab(inode);
 	rc = md_revalidate_lock(ll_i2mdexp(dir), &it, ll_inode2fid(inode),NULL);
 	if (rc == 1) {
 		entry->se_handle = it.d.lustre.it_lock_handle;
 		ll_intent_release(&it);
-		RETURN(1);
+		return 1;
 	}
 
 	rc = sa_args_init(dir, inode, entry, &minfo, &einfo, capas);
 	if (rc) {
 		entry->se_inode = NULL;
 		iput(inode);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo);
@@ -921,7 +905,7 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry,
 		sa_args_fini(minfo, einfo);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static void ll_statahead_one(struct dentry *parent, const char* entry_name,
@@ -934,12 +918,11 @@ static void ll_statahead_one(struct dentry *parent, const char* entry_name,
 	struct ll_sa_entry       *entry;
 	int		       rc;
 	int		       rc1;
-	ENTRY;
 
 	entry = ll_sa_entry_alloc(sai, sai->sai_index, entry_name,
 				  entry_name_len);
 	if (IS_ERR(entry))
-		RETURN_EXIT;
+		return;
 
 	dentry = d_lookup(parent, &entry->se_qstr);
 	if (!dentry) {
@@ -965,8 +948,6 @@ static void ll_statahead_one(struct dentry *parent, const char* entry_name,
 	sai->sai_index++;
 	/* drop one refcount on entry by ll_sa_entry_alloc */
 	ll_sa_entry_put(sai, entry);
-
-	EXIT;
 }
 
 static int ll_agl_thread(void *arg)
@@ -979,7 +960,6 @@ static int ll_agl_thread(void *arg)
 	struct ll_statahead_info *sai    = ll_sai_get(plli->lli_sai);
 	struct ptlrpc_thread     *thread = &sai->sai_agl_thread;
 	struct l_wait_info	lwi    = { 0 };
-	ENTRY;
 
 	CDEBUG(D_READA, "agl thread started: [pid %d] [parent %.*s]\n",
 	       current_pid(), parent->d_name.len, parent->d_name.name);
@@ -1029,7 +1009,7 @@ static int ll_agl_thread(void *arg)
 	ll_sai_put(sai);
 	CDEBUG(D_READA, "agl thread stopped: [pid %d] [parent %.*s]\n",
 	       current_pid(), parent->d_name.len, parent->d_name.name);
-	RETURN(0);
+	return 0;
 }
 
 static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
@@ -1037,8 +1017,7 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
 	struct ptlrpc_thread *thread = &sai->sai_agl_thread;
 	struct l_wait_info    lwi    = { 0 };
 	struct ll_inode_info  *plli;
-	task_t	      *task;
-	ENTRY;
+	struct task_struct *task;
 
 	CDEBUG(D_READA, "start agl thread: [pid %d] [parent %.*s]\n",
 	       current_pid(), parent->d_name.len, parent->d_name.name);
@@ -1049,13 +1028,12 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
 	if (IS_ERR(task)) {
 		CERROR("can't start ll_agl thread, rc: %ld\n", PTR_ERR(task));
 		thread_set_flags(thread, SVC_STOPPED);
-		RETURN_EXIT;
+		return;
 	}
 
 	l_wait_event(thread->t_ctl_waitq,
 		     thread_is_running(thread) || thread_is_stopped(thread),
 		     &lwi);
-	EXIT;
 }
 
 static int ll_statahead_thread(void *arg)
@@ -1074,7 +1052,6 @@ static int ll_statahead_thread(void *arg)
 	int		       rc     = 0;
 	struct ll_dir_chain       chain;
 	struct l_wait_info	lwi    = { 0 };
-	ENTRY;
 
 	CDEBUG(D_READA, "statahead thread started: [pid %d] [parent %.*s]\n",
 	       current_pid(), parent->d_name.len, parent->d_name.name);
@@ -1257,7 +1234,6 @@ do_it:
 			 */
 		}
 	}
-	EXIT;
 
 out:
 	if (sai->sai_agl_valid) {
@@ -1369,7 +1345,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
 	__u64		 pos    = 0;
 	int		   dot_de;
 	int		   rc     = LS_NONE_FIRST_DE;
-	ENTRY;
 
 	ll_dir_chain_init(&chain);
 	page = ll_get_dir_page(dir, pos, &chain);
@@ -1468,7 +1443,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
 			ll_release_page(page, 1);
 		}
 	}
-	EXIT;
 
 out:
 	ll_dir_chain_fini(&chain);
@@ -1481,7 +1455,6 @@ ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry)
 	struct ptlrpc_thread *thread = &sai->sai_thread;
 	struct ll_sb_info    *sbi    = ll_i2sbi(sai->sai_inode);
 	int		   hit;
-	ENTRY;
 
 	if (entry != NULL && entry->se_stat == SA_ENTRY_SUCC)
 		hit = 1;
@@ -1516,8 +1489,6 @@ ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry)
 
 	if (!thread_is_stopped(thread))
 		wake_up(&thread->t_ctl_waitq);
-
-	EXIT;
 }
 
 /**
@@ -1540,7 +1511,6 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 	struct l_wait_info	lwi   = { 0 };
 	int		       rc    = 0;
 	struct ll_inode_info     *plli;
-	ENTRY;
 
 	LASSERT(lli->lli_opendir_pid == current_pid());
 
@@ -1550,7 +1520,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 			     list_empty(&sai->sai_entries_stated))) {
 			/* to release resource */
 			ll_stop_statahead(dir, lli->lli_opendir_key);
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 		}
 
 		if ((*dentryp)->d_name.name[0] == '.') {
@@ -1576,14 +1546,14 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 				 * "sai_ls_all" enabled as above.
 				 */
 				sai->sai_miss_hidden++;
-				RETURN(-EAGAIN);
+				return -EAGAIN;
 			}
 		}
 
 		entry = ll_sa_entry_get_byname(sai, &(*dentryp)->d_name);
 		if (entry == NULL || only_unplug) {
 			ll_sai_unplug(sai, entry);
-			RETURN(entry ? 1 : -EAGAIN);
+			return entry ? 1 : -EAGAIN;
 		}
 
 		/* if statahead is busy in readdir, help it do post-work */
@@ -1602,7 +1572,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 					  &lwi);
 			if (rc < 0) {
 				ll_sai_unplug(sai, entry);
-				RETURN(-EAGAIN);
+				return -EAGAIN;
 			}
 		}
 
@@ -1632,7 +1602,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 					      inode->i_ino,
 					      inode->i_generation);
 					ll_sai_unplug(sai, entry);
-					RETURN(-ESTALE);
+					return -ESTALE;
 				} else {
 					iput(inode);
 				}
@@ -1646,7 +1616,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 		}
 
 		ll_sai_unplug(sai, entry);
-		RETURN(rc);
+		return rc;
 	}
 
 	/* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */
@@ -1698,7 +1668,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 		thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED);
 		ll_sai_put(sai);
 		LASSERT(lli->lli_sai == NULL);
-		RETURN(-EAGAIN);
+		return -EAGAIN;
 	}
 
 	l_wait_event(thread->t_ctl_waitq,
@@ -1709,7 +1679,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 	 * We don't stat-ahead for the first dirent since we are already in
 	 * lookup.
 	 */
-	RETURN(-EAGAIN);
+	return -EAGAIN;
 
 out:
 	if (sai != NULL)
diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c
index 82c14a9..0beaf4e 100644
--- a/drivers/staging/lustre/lustre/llite/super25.c
+++ b/drivers/staging/lustre/lustre/llite/super25.c
@@ -38,7 +38,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <lustre_lite.h>
 #include <lustre_ha.h>
 #include <lustre_dlm.h>
@@ -214,7 +213,7 @@ static void __exit exit_lustre_lite(void)
 	ll_remote_perm_cachep = NULL;
 
 	kmem_cache_destroy(ll_file_data_slab);
-	if (proc_lustre_fs_root)
+	if (proc_lustre_fs_root && !IS_ERR(proc_lustre_fs_root))
 		lprocfs_remove(&proc_lustre_fs_root);
 }
 
diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c
index 5260e98..ab06891 100644
--- a/drivers/staging/lustre/lustre/llite/symlink.c
+++ b/drivers/staging/lustre/lustre/llite/symlink.c
@@ -37,7 +37,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/stat.h>
-#include <linux/version.h>
 #define DEBUG_SUBSYSTEM S_LLITE
 
 #include <lustre_lite.h>
@@ -51,7 +50,6 @@ static int ll_readlink_internal(struct inode *inode,
 	int rc, symlen = i_size_read(inode) + 1;
 	struct mdt_body *body;
 	struct md_op_data *op_data;
-	ENTRY;
 
 	*request = NULL;
 
@@ -65,13 +63,13 @@ static int ll_readlink_internal(struct inode *inode,
 		CDEBUG(D_INODE, "using cached symlink %s%.*s, len = %d\n",
 		       print_limit < symlen ? "..." : "", print_limit,
 		       (*symname) + symlen - print_limit, symlen);
-		RETURN(0);
+		return 0;
 	}
 
 	op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, symlen,
 				     LUSTRE_OPC_ANY, NULL);
 	if (IS_ERR(op_data))
-		RETURN(PTR_ERR(op_data));
+		return PTR_ERR(op_data);
 
 	op_data->op_valid = OBD_MD_LINKNAME;
 	rc = md_getattr(sbi->ll_md_exp, op_data, request);
@@ -111,10 +109,10 @@ static int ll_readlink_internal(struct inode *inode,
 		memcpy(lli->lli_symlink_name, *symname, symlen);
 		*symname = lli->lli_symlink_name;
 	}
-	RETURN(0);
+	return 0;
 
 failed:
-	RETURN (rc);
+	return rc;
 }
 
 static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
@@ -123,7 +121,6 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
 	struct ptlrpc_request *request;
 	char *symname;
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op\n");
 
@@ -136,7 +133,7 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
  out:
 	ptlrpc_req_finished(request);
 	ll_inode_size_unlock(inode);
-	RETURN(rc);
+	return rc;
 }
 
 static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -145,7 +142,6 @@ static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
 	struct ptlrpc_request *request = NULL;
 	int rc;
 	char *symname;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op\n");
 	/* Limit the recursive symlink depth to 5 instead of default
@@ -170,7 +166,7 @@ static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
 	/* symname may contain a pointer to the request message buffer,
 	 * we delay request releasing until ll_put_link then.
 	 */
-	RETURN(request);
+	return request;
 }
 
 static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c
index 9254b99..be125b9 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_dev.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c
@@ -213,7 +213,7 @@ int cl_sb_init(struct super_block *sb)
 		cl_env_put(env, &refcheck);
 	} else
 		rc = PTR_ERR(env);
-	RETURN(rc);
+	return rc;
 }
 
 int cl_sb_fini(struct super_block *sb)
@@ -224,7 +224,6 @@ int cl_sb_fini(struct super_block *sb)
 	int		refcheck;
 	int		result;
 
-	ENTRY;
 	sbi = ll_s2sbi(sb);
 	env = cl_env_get(&refcheck);
 	if (!IS_ERR(env)) {
@@ -247,7 +246,7 @@ int cl_sb_fini(struct super_block *sb)
 	 * automatically when last device is destroyed).
 	 */
 	lu_types_stop();
-	RETURN(result);
+	return result;
 }
 
 /****************************************************************************
diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c
index eb964ac..3ff664c 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -176,19 +176,18 @@ static int vvp_mmap_locks(const struct lu_env *env,
 	unsigned long	   seg;
 	ssize_t		 count;
 	int		     result;
-	ENTRY;
 
 	LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
 
 	if (!cl_is_normalio(env, io))
-		RETURN(0);
+		return 0;
 
 	if (vio->cui_iov == NULL) /* nfs or loop back device write */
-		RETURN(0);
+		return 0;
 
 	/* No MM (e.g. NFS)? No vmas too. */
 	if (mm == NULL)
-		RETURN(0);
+		return 0;
 
 	for (seg = 0; seg < vio->cui_nrsegs; seg++) {
 		const struct iovec *iv = &vio->cui_iov[seg];
@@ -234,7 +233,7 @@ static int vvp_mmap_locks(const struct lu_env *env,
 			       descr->cld_end);
 
 			if (result < 0)
-				RETURN(result);
+				return result;
 
 			if (vma->vm_end - addr >= count)
 				break;
@@ -244,7 +243,7 @@ static int vvp_mmap_locks(const struct lu_env *env,
 		}
 		up_read(&mm->mmap_sem);
 	}
-	RETURN(0);
+	return 0;
 }
 
 static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io,
@@ -255,7 +254,6 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io,
 	int ast_flags = 0;
 
 	LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
-	ENTRY;
 
 	ccc_io_update_iov(env, cio, io);
 
@@ -264,7 +262,7 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io,
 	result = vvp_mmap_locks(env, cio, io);
 	if (result == 0)
 		result = ccc_io_one_lock(env, io, ast_flags, mode, start, end);
-	RETURN(result);
+	return result;
 }
 
 static int vvp_io_read_lock(const struct lu_env *env,
@@ -274,7 +272,6 @@ static int vvp_io_read_lock(const struct lu_env *env,
 	struct ll_inode_info *lli = ll_i2info(ccc_object_inode(io->ci_obj));
 	int result;
 
-	ENTRY;
 	/* XXX: Layer violation, we shouldn't see lsm at llite level. */
 	if (lli->lli_has_smd) /* lsm-less file doesn't need to lock */
 		result = vvp_io_rw_lock(env, io, CLM_READ,
@@ -283,7 +280,7 @@ static int vvp_io_read_lock(const struct lu_env *env,
 					io->u.ci_rd.rd.crw_count - 1);
 	else
 		result = 0;
-	RETURN(result);
+	return result;
 }
 
 static int vvp_io_fault_lock(const struct lu_env *env,
@@ -407,13 +404,15 @@ static int vvp_io_setattr_start(const struct lu_env *env,
 {
 	struct cl_io	*io    = ios->cis_io;
 	struct inode	*inode = ccc_object_inode(io->ci_obj);
+	int result = 0;
 
 	mutex_lock(&inode->i_mutex);
 	if (cl_io_is_trunc(io))
-		return vvp_io_setattr_trunc(env, ios, inode,
-					    io->u.ci_setattr.sa_attr.lvb_size);
-	else
-		return vvp_io_setattr_time(env, ios);
+		result = vvp_io_setattr_trunc(env, ios, inode,
+					io->u.ci_setattr.sa_attr.lvb_size);
+	if (result == 0)
+		result = vvp_io_setattr_time(env, ios);
+	return result;
 }
 
 static void vvp_io_setattr_end(const struct lu_env *env,
@@ -525,7 +524,7 @@ out:
 			io->ci_continue = 0;
 		io->ci_nob += result;
 		ll_rw_stats_tally(ll_i2sbi(inode), current->pid,
-				  cio->cui_fd, pos, result, 0);
+				  cio->cui_fd, pos, result, READ);
 		result = 0;
 	}
 	return result;
@@ -554,8 +553,6 @@ static int vvp_io_write_start(const struct lu_env *env,
 	loff_t pos = io->u.ci_wr.wr.crw_pos;
 	size_t cnt = io->u.ci_wr.wr.crw_count;
 
-	ENTRY;
-
 	if (!can_populate_pages(env, io, inode))
 		return 0;
 
@@ -580,10 +577,10 @@ static int vvp_io_write_start(const struct lu_env *env,
 			io->ci_continue = 0;
 		io->ci_nob += result;
 		ll_rw_stats_tally(ll_i2sbi(inode), current->pid,
-				  cio->cui_fd, pos, result, 0);
+				  cio->cui_fd, pos, result, WRITE);
 		result = 0;
 	}
-	RETURN(result);
+	return result;
 }
 
 static int vvp_io_kernel_fault(struct vvp_fault_io *cfio)
@@ -767,7 +764,6 @@ static int vvp_io_fault_start(const struct lu_env *env,
 
 	lu_ref_add(&page->cp_reference, "fault", io);
 	fio->ft_page = page;
-	EXIT;
 
 out:
 	/* return unlocked vmpage to avoid deadlocking */
@@ -805,8 +801,6 @@ static int vvp_io_read_page(const struct lu_env *env,
 	CLOBINVRNT(env, obj, ccc_object_invariant(obj));
 	LASSERT(slice->cpl_obj == obj);
 
-	ENTRY;
-
 	if (sbi->ll_ra_info.ra_max_pages_per_file &&
 	    sbi->ll_ra_info.ra_max_pages)
 		ras_update(sbi, inode, ras, page->cp_index,
@@ -819,7 +813,7 @@ static int vvp_io_read_page(const struct lu_env *env,
 			       rc == -ENODATA ? "without a lock" :
 			       "match failed", rc);
 		if (rc != -ENODATA)
-			RETURN(rc);
+			return rc;
 	}
 
 	if (cp->cpg_defer_uptodate) {
@@ -836,7 +830,7 @@ static int vvp_io_read_page(const struct lu_env *env,
 		ll_readahead(env, io, ras,
 			     vmpage->mapping, &queue->c2_qin, fd->fd_flags);
 
-	RETURN(0);
+	return 0;
 }
 
 static int vvp_page_sync_io(const struct lu_env *env, struct cl_io *io,
@@ -887,10 +881,10 @@ static int vvp_io_prepare_partial(const struct lu_env *env, struct cl_io *io,
 		 * purposes here we can treat it like i_size.
 		 */
 		if (attr->cat_kms <= offset) {
-			char *kaddr = ll_kmap_atomic(cp->cpg_page, KM_USER0);
+			char *kaddr = kmap_atomic(cp->cpg_page);
 
 			memset(kaddr, 0, cl_page_size(obj));
-			ll_kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 		} else if (cp->cpg_defer_uptodate)
 			cp->cpg_ra_used = 1;
 		else
@@ -921,8 +915,6 @@ static int vvp_io_prepare_write(const struct lu_env *env,
 
 	int result;
 
-	ENTRY;
-
 	LINVRNT(cl_page_is_vmlocked(env, pg));
 	LASSERT(vmpage->mapping->host == ccc_object_inode(obj));
 
@@ -942,7 +934,7 @@ static int vvp_io_prepare_write(const struct lu_env *env,
 							pg, cp, from, to);
 	} else
 		CL_PAGE_HEADER(D_PAGE, env, pg, "uptodate\n");
-	RETURN(result);
+	return result;
 }
 
 static int vvp_io_commit_write(const struct lu_env *env,
@@ -963,12 +955,10 @@ static int vvp_io_commit_write(const struct lu_env *env,
 	int    tallyop;
 	loff_t size;
 
-	ENTRY;
-
 	LINVRNT(cl_page_is_vmlocked(env, pg));
 	LASSERT(vmpage->mapping->host == inode);
 
-	LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu, "commiting page write\n");
+	LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu, "committing page write\n");
 	CL_PAGE_HEADER(D_PAGE, env, pg, "committing: [%d, %d]\n", from, to);
 
 	/*
@@ -1067,7 +1057,7 @@ static int vvp_io_commit_write(const struct lu_env *env,
 			cl_page_discard(env, io, pg);
 	}
 	ll_inode_size_unlock(inode);
-	RETURN(result);
+	return result;
 }
 
 static const struct cl_io_operations vvp_io_ops = {
@@ -1120,7 +1110,6 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
 	int		 result;
 
 	CLOBINVRNT(env, obj, ccc_object_invariant(obj));
-	ENTRY;
 
 	CL_IO_SLICE_CLEAN(cio, cui_cl);
 	cl_io_slice_add(io, &cio->cui_cl, obj, &vvp_io_ops);
@@ -1174,7 +1163,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
 				PFID(lu_object_fid(&obj->co_lu)), result);
 	}
 
-	RETURN(result);
+	return result;
 }
 
 static struct vvp_io *cl2vvp_io(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c
index 9b8712b..e16b31e 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_lock.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c
@@ -63,8 +63,7 @@ static unsigned long vvp_lock_weigh(const struct lu_env *env,
 {
 	struct ccc_object *cob = cl2ccc(slice->cls_obj);
 
-	ENTRY;
-	RETURN(atomic_read(&cob->cob_mmap_cnt) > 0 ? ~0UL >> 2 : 0);
+	return atomic_read(&cob->cob_mmap_cnt) > 0 ? ~0UL >> 2 : 0;
 }
 
 static const struct cl_lock_operations vvp_lock_ops = {
diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c
index 01edc5b..33173fc 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_object.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_object.c
@@ -91,8 +91,8 @@ static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj,
 	attr->cat_atime = LTIME_S(inode->i_atime);
 	attr->cat_ctime = LTIME_S(inode->i_ctime);
 	attr->cat_blocks = inode->i_blocks;
-	attr->cat_uid = inode->i_uid;
-	attr->cat_gid = inode->i_gid;
+	attr->cat_uid = from_kuid(&init_user_ns, inode->i_uid);
+	attr->cat_gid = from_kgid(&init_user_ns, inode->i_gid);
 	/* KMS is not known by this layer */
 	return 0; /* layers below have to fill in the rest */
 }
@@ -103,9 +103,9 @@ static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj,
 	struct inode *inode = ccc_object_inode(obj);
 
 	if (valid & CAT_UID)
-		inode->i_uid = attr->cat_uid;
+		inode->i_uid = make_kuid(&init_user_ns, attr->cat_uid);
 	if (valid & CAT_GID)
-		inode->i_gid = attr->cat_gid;
+		inode->i_gid = make_kgid(&init_user_ns, attr->cat_gid);
 	if (valid & CAT_ATIME)
 		LTIME_S(inode->i_atime) = attr->cat_atime;
 	if (valid & CAT_MTIME)
diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c
index 4568e69..1c02c12 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_page.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_page.c
@@ -218,9 +218,8 @@ static int vvp_page_prep_read(const struct lu_env *env,
 			      const struct cl_page_slice *slice,
 			      struct cl_io *unused)
 {
-	ENTRY;
 	/* Skip the page already marked as PG_uptodate. */
-	RETURN(PageUptodate(cl2vm_page(slice)) ? -EALREADY : 0);
+	return PageUptodate(cl2vm_page(slice)) ? -EALREADY : 0;
 }
 
 static int vvp_page_prep_write(const struct lu_env *env,
@@ -274,7 +273,6 @@ static void vvp_page_completion_read(const struct lu_env *env,
 	struct page      *vmpage = cp->cpg_page;
 	struct cl_page  *page   = cl_page_top(slice->cpl_page);
 	struct inode    *inode  = ccc_object_inode(page->cp_obj);
-	ENTRY;
 
 	LASSERT(PageLocked(vmpage));
 	CL_PAGE_HEADER(D_PAGE, env, page, "completing READ with %d\n", ioret);
@@ -290,8 +288,6 @@ static void vvp_page_completion_read(const struct lu_env *env,
 
 	if (page->cp_sync_io == NULL)
 		unlock_page(vmpage);
-
-	EXIT;
 }
 
 static void vvp_page_completion_write(const struct lu_env *env,
@@ -301,7 +297,6 @@ static void vvp_page_completion_write(const struct lu_env *env,
 	struct ccc_page *cp     = cl2ccc_page(slice);
 	struct cl_page  *pg     = slice->cpl_page;
 	struct page      *vmpage = cp->cpg_page;
-	ENTRY;
 
 	LASSERT(ergo(pg->cp_sync_io != NULL, PageLocked(vmpage)));
 	LASSERT(PageWriteback(vmpage));
@@ -329,7 +324,6 @@ static void vvp_page_completion_write(const struct lu_env *env,
 		vvp_vmpage_error(ccc_object_inode(pg->cp_obj), vmpage, ioret);
 
 	end_page_writeback(vmpage);
-	EXIT;
 }
 
 /**
@@ -372,7 +366,7 @@ static int vvp_page_make_ready(const struct lu_env *env,
 		LBUG();
 	}
 	unlock_page(vmpage);
-	RETURN(result);
+	return result;
 }
 
 static int vvp_page_print(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c
index 4176264..bcf86ba 100644
--- a/drivers/staging/lustre/lustre/llite/xattr.c
+++ b/drivers/staging/lustre/lustre/llite/xattr.c
@@ -112,31 +112,32 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 	struct ptlrpc_request *req;
 	int xattr_type, rc;
 	struct obd_capa *oc;
+#ifdef CONFIG_FS_POSIX_ACL
 	posix_acl_xattr_header *new_value = NULL;
 	struct rmtacl_ctl_entry *rce = NULL;
 	ext_acl_xattr_header *acl = NULL;
+#endif
 	const char *pv = value;
-	ENTRY;
 
 	xattr_type = get_xattr_type(name);
 	rc = xattr_type_filter(sbi, xattr_type);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	/* b10667: ignore lustre special xattr for now */
 	if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
 	    (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
-		RETURN(0);
+		return 0;
 
 	/* b15587: ignore security.capability xattr for now */
 	if ((xattr_type == XATTR_SECURITY_T &&
 	    strcmp(name, "security.capability") == 0))
-		RETURN(0);
+		return 0;
 
 	/* LU-549:  Disable security.selinux when selinux is disabled */
 	if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() &&
 	    strcmp(name, "security.selinux") == 0)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 #ifdef CONFIG_FS_POSIX_ACL
 	if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
@@ -146,7 +147,7 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 		if (rce == NULL ||
 		    (rce->rce_ops != RMT_LSETFACL &&
 		    rce->rce_ops != RMT_RSETFACL))
-			RETURN(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 
 		if (rce->rce_ops == RMT_LSETFACL) {
 			struct eacl_entry *ee;
@@ -160,7 +161,7 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 						size, ee->ee_acl);
 				if (IS_ERR(acl)) {
 					ee_free(ee);
-					RETURN(PTR_ERR(acl));
+					return PTR_ERR(acl);
 				}
 				size =  CFS_ACL_XATTR_SIZE(\
 						le32_to_cpu(acl->a_count), \
@@ -173,11 +174,11 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 						(posix_acl_xattr_header *)value,
 						size, &new_value);
 			if (unlikely(size < 0))
-				RETURN(size);
+				return size;
 
 			pv = (const char *)new_value;
 		} else
-			RETURN(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 
 		valid |= rce_ops2valid(rce->rce_ops);
 	}
@@ -199,11 +200,11 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 				      "it is not supported on the server\n");
 			sbi->ll_flags &= ~LL_SBI_USER_XATTR;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	ptlrpc_req_finished(req);
-	RETURN(0);
+	return 0;
 }
 
 int ll_setxattr(struct dentry *dentry, const char *name,
@@ -285,7 +286,6 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 	void *xdata;
 	struct obd_capa *oc;
 	struct rmtacl_ctl_entry *rce = NULL;
-	ENTRY;
 
 	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
 	       inode->i_ino, inode->i_generation, inode);
@@ -302,17 +302,17 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 	xattr_type = get_xattr_type(name);
 	rc = xattr_type_filter(sbi, xattr_type);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	/* b15587: ignore security.capability xattr for now */
 	if ((xattr_type == XATTR_SECURITY_T &&
 	    strcmp(name, "security.capability") == 0))
-		RETURN(-ENODATA);
+		return -ENODATA;
 
 	/* LU-549:  Disable security.selinux when selinux is disabled */
 	if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() &&
 	    strcmp(name, "security.selinux") == 0)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 #ifdef CONFIG_FS_POSIX_ACL
 	if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
@@ -324,7 +324,7 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 		    rce->rce_ops != RMT_LGETFACL &&
 		    rce->rce_ops != RMT_RSETFACL &&
 		    rce->rce_ops != RMT_RGETFACL))
-			RETURN(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 	}
 
 	/* posix acl is under protection of LOOKUP lock. when calling to this,
@@ -341,14 +341,14 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 		spin_unlock(&lli->lli_lock);
 
 		if (!acl)
-			RETURN(-ENODATA);
+			return -ENODATA;
 
 		rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
 		posix_acl_release(acl);
-		RETURN(rc);
+		return rc;
 	}
 	if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode))
-		RETURN(-ENODATA);
+		return -ENODATA;
 #endif
 
 do_getxattr:
@@ -363,7 +363,7 @@ do_getxattr:
 				      "it is not supported on the server\n");
 			sbi->ll_flags &= ~LL_SBI_USER_XATTR;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
@@ -413,7 +413,6 @@ do_getxattr:
 		memcpy(buffer, xdata, body->eadatasize);
 		rc = body->eadatasize;
 	}
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -562,7 +561,12 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
 		const size_t name_len   = sizeof("lov") - 1;
 		const size_t total_len  = prefix_len + name_len + 1;
 
-		if (buffer && (rc + total_len) <= size) {
+		if (((rc + total_len) > size) && (buffer != NULL)) {
+			ptlrpc_req_finished(request);
+			return -ERANGE;
+		}
+
+		if (buffer != NULL) {
 			buffer += rc;
 			memcpy(buffer, XATTR_LUSTRE_PREFIX, prefix_len);
 			memcpy(buffer + prefix_len, "lov", name_len);
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_fld.c b/drivers/staging/lustre/lustre/lmv/lmv_fld.c
index a4805ae..0b2d38d 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_fld.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_fld.c
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <asm/div64.h>
 #include <linux/seq_file.h>
@@ -58,8 +57,6 @@ int lmv_fld_lookup(struct lmv_obd *lmv,
 		   mdsno_t *mds)
 {
 	int rc;
-	ENTRY;
-
 
 	/* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and
 	 * this fid_is_local check should be removed once LU-2240 is fixed */
@@ -72,7 +69,7 @@ int lmv_fld_lookup(struct lmv_obd *lmv,
 	if (rc) {
 		CERROR("Error while looking for mds number. Seq "LPX64
 		       ", err = %d\n", fid_seq(fid), rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
@@ -84,5 +81,5 @@ int lmv_fld_lookup(struct lmv_obd *lmv,
 		       PFID(fid));
 		rc = -EINVAL;
 	}
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
index 7eefab5..511b3b4 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <asm/div64.h>
 #include <linux/seq_file.h>
@@ -70,11 +69,10 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm,
 	struct mdt_body		*body;
 	int			pmode;
 	int			rc = 0;
-	ENTRY;
 
 	body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
 	if (body == NULL)
-		RETURN(-EPROTO);
+		return -EPROTO;
 
 	LASSERT((body->valid & OBD_MD_MDS));
 
@@ -142,7 +140,6 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm,
 	it->d.lustre.it_lock_handle = plock.cookie;
 	it->d.lustre.it_lock_mode = pmode;
 
-	EXIT;
 out_free_op_data:
 	OBD_FREE_PTR(op_data);
 out:
@@ -169,11 +166,10 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_tgt_desc	*tgt;
 	struct mdt_body		*body;
 	int			rc;
-	ENTRY;
 
 	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	/* If it is ready to open the file by FID, do not need
 	 * allocate FID at all, otherwise it will confuse MDT */
@@ -186,7 +182,7 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
 		op_data->op_fid3 = op_data->op_fid2;
 		rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data);
 		if (rc != 0)
-			RETURN(rc);
+			return rc;
 	}
 
 	CDEBUG(D_INODE, "OPEN_INTENT with fid1="DFID", fid2="DFID","
@@ -196,7 +192,7 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
 	rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags,
 			    reqp, cb_blocking, extra_lock_flags);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 	/*
 	 * Nothing is found, do not access body->fid1 as it is zero and thus
 	 * pointless.
@@ -204,16 +200,16 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
 	if ((it->d.lustre.it_disposition & DISP_LOOKUP_NEG) &&
 	    !(it->d.lustre.it_disposition & DISP_OPEN_CREATE) &&
 	    !(it->d.lustre.it_disposition & DISP_OPEN_OPEN))
-		RETURN(rc);
+		return rc;
 
 	body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
 	if (body == NULL)
-		RETURN(-EPROTO);
+		return -EPROTO;
 	/*
 	 * Not cross-ref case, just get out of here.
 	 */
 	if (likely(!(body->valid & OBD_MD_MDS)))
-		RETURN(0);
+		return 0;
 
 	/*
 	 * Okay, MDS has returned success. Probably name has been resolved in
@@ -233,10 +229,10 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
 		       "%*s: %d\n", LL_IT2STR(it), PFID(&op_data->op_fid2),
 		       PFID(&op_data->op_fid1), op_data->op_namelen,
 		       op_data->op_name, rc);
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -253,11 +249,10 @@ int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_tgt_desc    *tgt = NULL;
 	struct mdt_body	*body;
 	int		     rc = 0;
-	ENTRY;
 
 	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	if (!fid_is_sane(&op_data->op_fid2))
 		fid_zero(&op_data->op_fid2);
@@ -274,7 +269,7 @@ int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
 			     flags, reqp, cb_blocking, extra_lock_flags);
 
 	if (rc < 0 || *reqp == NULL)
-		RETURN(rc);
+		return rc;
 
 	/*
 	 * MDS has returned success. Probably name has been resolved in
@@ -282,15 +277,15 @@ int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
 	 */
 	body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
 	if (body == NULL)
-		RETURN(-EPROTO);
+		return -EPROTO;
 	/* Not cross-ref case, just get out of here. */
 	if (likely(!(body->valid & OBD_MD_MDS)))
-		RETURN(0);
+		return 0;
 
 	rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, reqp,
 			       cb_blocking, extra_lock_flags);
 
-	RETURN(rc);
+	return rc;
 }
 
 int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
@@ -301,7 +296,6 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 {
 	struct obd_device *obd = exp->exp_obd;
 	int		rc;
-	ENTRY;
 
 	LASSERT(it != NULL);
 	LASSERT(fid_is_sane(&op_data->op_fid1));
@@ -312,7 +306,7 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT))
 		rc = lmv_intent_lookup(exp, op_data, lmm, lmmsize, it,
@@ -324,5 +318,5 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 				     extra_lock_flags);
 	else
 		LBUG();
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index 1eebfbf..c286604 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -38,12 +38,12 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/mm.h>
 #include <asm/div64.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
+#include <asm/uaccess.h>
 
 #include <lustre/lustre_idl.h>
 #include <obd_support.h>
@@ -80,7 +80,6 @@ static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid,
 	struct obd_device      *obd;
 	int		     i;
 	int		     rc = 0;
-	ENTRY;
 
 	CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n",
 	       lmv, uuid->uuid, activate);
@@ -119,7 +118,6 @@ static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid,
 	CDEBUG(D_INFO, "Marking OBD %p %sactive\n", obd,
 	       activate ? "" : "in");
 	lmv_activate_target(lmv, tgt, activate);
-	EXIT;
 
  out_lmv_lock:
 	spin_unlock(&lmv->lmv_lock);
@@ -140,13 +138,12 @@ static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct obd_uuid	 *uuid;
 	int		      rc = 0;
-	ENTRY;
 
 	if (strcmp(watched->obd_type->typ_name, LUSTRE_MDC_NAME)) {
 		CERROR("unexpected notification of %s %s!\n",
 		       watched->obd_type->typ_name,
 		       watched->obd_name);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	uuid = &watched->u.cli.cl_target_uuid;
@@ -161,7 +158,7 @@ static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
 			CERROR("%sactivation of %s failed: %d\n",
 			       ev == OBD_NOTIFY_ACTIVE ? "" : "de",
 			       uuid->uuid, rc);
-			RETURN(rc);
+			return rc;
 		}
 	} else if (ev == OBD_NOTIFY_OCD) {
 		conn_data = &watched->u.cli.cl_import->imp_connect_data;
@@ -186,7 +183,7 @@ static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
 	if (obd->obd_observer)
 		rc = obd_notify(obd->obd_observer, watched, ev, data);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -202,7 +199,6 @@ static int lmv_connect(const struct lu_env *env,
 	struct lmv_obd	*lmv = &obd->u.lmv;
 	struct lustre_handle  conn = { 0 };
 	int		    rc = 0;
-	ENTRY;
 
 	/*
 	 * We don't want to actually do the underlying connections more than
@@ -211,13 +207,13 @@ static int lmv_connect(const struct lu_env *env,
 	lmv->refcount++;
 	if (lmv->refcount > 1) {
 		*exp = NULL;
-		RETURN(0);
+		return 0;
 	}
 
 	rc = class_connect(&conn, obd, cluuid);
 	if (rc) {
 		CERROR("class_connection() returned %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	*exp = class_conn2export(&conn);
@@ -257,7 +253,7 @@ static int lmv_connect(const struct lu_env *env,
 		obd->obd_proc_private = NULL;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static void lmv_set_timeouts(struct obd_device *obd)
@@ -291,7 +287,6 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize,
 	int		  i;
 	int		  rc = 0;
 	int		  change = 0;
-	ENTRY;
 
 	if (lmv->max_easize < easize) {
 		lmv->max_easize = easize;
@@ -306,10 +301,10 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize,
 		change = 1;
 	}
 	if (change == 0)
-		RETURN(0);
+		return 0;
 
 	if (lmv->connected == 0)
-		RETURN(0);
+		return 0;
 
 	for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
 		if (lmv->tgts[i] == NULL ||
@@ -327,7 +322,7 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize,
 			break;
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 
 #define MAX_STRING_SIZE 128
@@ -342,13 +337,12 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 	struct obd_export       *mdc_exp;
 	struct lu_fld_target     target;
 	int		      rc;
-	ENTRY;
 
 	mdc_obd = class_find_client_obd(&tgt->ltd_uuid, LUSTRE_MDC_NAME,
 					&obd->obd_uuid);
 	if (!mdc_obd) {
 		CERROR("target %s not attached\n", tgt->ltd_uuid.uuid);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	CDEBUG(D_CONFIG, "connect to %s(%s) - %s, %s FOR %s\n",
@@ -358,14 +352,14 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 
 	if (!mdc_obd->obd_set_up) {
 		CERROR("target %s is not set up\n", tgt->ltd_uuid.uuid);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = obd_connect(NULL, &mdc_exp, mdc_obd, &lmv_mdc_uuid,
 			 &lmv->conn_data, NULL);
 	if (rc) {
 		CERROR("target %s connect error %d\n", tgt->ltd_uuid.uuid, rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	/*
@@ -373,7 +367,7 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 	 */
 	rc = obd_fid_init(mdc_obd, mdc_exp, LUSTRE_SEQ_METADATA);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	target.ft_srv = NULL;
 	target.ft_exp = mdc_exp;
@@ -386,7 +380,7 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 		obd_disconnect(mdc_exp);
 		CERROR("target %s register_observer error %d\n",
 		       tgt->ltd_uuid.uuid, rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (obd->obd_observer) {
@@ -398,7 +392,7 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 				(void *)(tgt - lmv->tgts[0]));
 		if (rc) {
 			obd_disconnect(mdc_exp);
-			RETURN(rc);
+			return rc;
 		}
 	}
 
@@ -433,7 +427,7 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 			obd->obd_proc_private = NULL;
 		}
 	}
-	RETURN(0);
+	return 0;
 }
 
 static void lmv_del_target(struct lmv_obd *lmv, int index)
@@ -452,7 +446,6 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 	struct lmv_obd      *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc *tgt;
 	int		  rc = 0;
-	ENTRY;
 
 	CDEBUG(D_CONFIG, "Target uuid: %s. index %d\n", uuidp->uuid, index);
 
@@ -467,7 +460,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 			lmv_init_unlock(lmv);
 			CERROR("%s: Target %s not attached: rc = %d\n",
 			       obd->obd_name, uuidp->uuid, -EINVAL);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
@@ -477,7 +470,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 		       " rc = %d\n", obd->obd_name,
 		       obd_uuid2str(&tgt->ltd_uuid), index, -EEXIST);
 		lmv_init_unlock(lmv);
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 
 	if (index >= lmv->tgts_size) {
@@ -491,7 +484,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 		OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize);
 		if (newtgts == NULL) {
 			lmv_init_unlock(lmv);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 
 		if (lmv->tgts_size) {
@@ -514,7 +507,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 	OBD_ALLOC_PTR(tgt);
 	if (!tgt) {
 		lmv_init_unlock(lmv);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	mutex_init(&tgt->ltd_fid_mutex);
@@ -541,7 +534,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 	}
 
 	lmv_init_unlock(lmv);
-	RETURN(rc);
+	return rc;
 }
 
 int lmv_check_connect(struct obd_device *obd)
@@ -551,21 +544,20 @@ int lmv_check_connect(struct obd_device *obd)
 	int		   i;
 	int		   rc;
 	int		   easize;
-	ENTRY;
 
 	if (lmv->connected)
-		RETURN(0);
+		return 0;
 
 	lmv_init_lock(lmv);
 	if (lmv->connected) {
 		lmv_init_unlock(lmv);
-		RETURN(0);
+		return 0;
 	}
 
 	if (lmv->desc.ld_tgt_count == 0) {
 		lmv_init_unlock(lmv);
 		CERROR("%s: no targets configured.\n", obd->obd_name);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	CDEBUG(D_CONFIG, "Time to connect %s to %s\n",
@@ -588,7 +580,7 @@ int lmv_check_connect(struct obd_device *obd)
 	easize = lmv_get_easize(lmv);
 	lmv_init_ea_size(obd->obd_self_export, easize, 0, 0);
 	lmv_init_unlock(lmv);
-	RETURN(0);
+	return 0;
 
  out_disc:
 	while (i-- > 0) {
@@ -609,7 +601,7 @@ int lmv_check_connect(struct obd_device *obd)
 	}
 	class_disconnect(lmv->exp);
 	lmv_init_unlock(lmv);
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
@@ -618,7 +610,6 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 	struct lmv_obd	 *lmv = &obd->u.lmv;
 	struct obd_device      *mdc_obd;
 	int		     rc;
-	ENTRY;
 
 	LASSERT(tgt != NULL);
 	LASSERT(obd != NULL);
@@ -654,7 +645,7 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
 
 	lmv_activate_target(lmv, tgt, 0);
 	tgt->ltd_exp = NULL;
-	RETURN(0);
+	return 0;
 }
 
 static int lmv_disconnect(struct obd_export *exp)
@@ -663,7 +654,6 @@ static int lmv_disconnect(struct obd_export *exp)
 	struct lmv_obd	*lmv = &obd->u.lmv;
 	int		    rc;
 	int		    i;
-	ENTRY;
 
 	if (!lmv->tgts)
 		goto out_local;
@@ -683,7 +673,7 @@ static int lmv_disconnect(struct obd_export *exp)
 	}
 
 	if (obd->obd_proc_private)
-		lprocfs_remove((proc_dir_entry_t **)&obd->obd_proc_private);
+		lprocfs_remove((struct proc_dir_entry **)&obd->obd_proc_private);
 	else
 		CERROR("/proc/fs/lustre/%s/%s/target_obds missing\n",
 		       obd->obd_type->typ_name, obd->obd_name);
@@ -698,7 +688,7 @@ out_local:
 	rc = class_disconnect(exp);
 	if (lmv->refcount == 0)
 		lmv->connected = 0;
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_fid2path(struct obd_export *exp, int len, void *karg, void *uarg)
@@ -714,7 +704,7 @@ static int lmv_fid2path(struct obd_export *exp, int len, void *karg, void *uarg)
 	gf = (struct getinfo_fid2path *)karg;
 	tgt = lmv_find_target(lmv, &gf->gf_fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 repeat_fid2path:
 	rc = obd_iocontrol(OBD_IOC_FID2PATH, tgt->ltd_exp, len, gf, uarg);
@@ -780,9 +770,126 @@ repeat_fid2path:
 out_fid2path:
 	if (remote_gf != NULL)
 		OBD_FREE(remote_gf, remote_gf_size);
-	RETURN(rc);
+	return rc;
+}
+
+static int lmv_hsm_req_count(struct lmv_obd *lmv,
+			     const struct hsm_user_request *hur,
+			     const struct lmv_tgt_desc *tgt_mds)
+{
+	int			i, nr = 0;
+	struct lmv_tgt_desc    *curr_tgt;
+
+	/* count how many requests must be sent to the given target */
+	for (i = 0; i < hur->hur_request.hr_itemcount; i++) {
+		curr_tgt = lmv_find_target(lmv, &hur->hur_user_item[i].hui_fid);
+		if (obd_uuid_equals(&curr_tgt->ltd_uuid, &tgt_mds->ltd_uuid))
+			nr++;
+	}
+	return nr;
+}
+
+static void lmv_hsm_req_build(struct lmv_obd *lmv,
+			      struct hsm_user_request *hur_in,
+			      const struct lmv_tgt_desc *tgt_mds,
+			      struct hsm_user_request *hur_out)
+{
+	int			i, nr_out;
+	struct lmv_tgt_desc    *curr_tgt;
+
+	/* build the hsm_user_request for the given target */
+	hur_out->hur_request = hur_in->hur_request;
+	nr_out = 0;
+	for (i = 0; i < hur_in->hur_request.hr_itemcount; i++) {
+		curr_tgt = lmv_find_target(lmv,
+					&hur_in->hur_user_item[i].hui_fid);
+		if (obd_uuid_equals(&curr_tgt->ltd_uuid, &tgt_mds->ltd_uuid)) {
+			hur_out->hur_user_item[nr_out] =
+				hur_in->hur_user_item[i];
+			nr_out++;
+		}
+	}
+	hur_out->hur_request.hr_itemcount = nr_out;
+	memcpy(hur_data(hur_out), hur_data(hur_in),
+	       hur_in->hur_request.hr_data_len);
+}
+
+static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len,
+				 struct lustre_kernelcomm *lk, void *uarg)
+{
+	int	i, rc = 0;
+
+	/* unregister request (call from llapi_hsm_copytool_fini) */
+	for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
+		/* best effort: try to clean as much as possible
+		 * (continue on error) */
+		obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, len, lk, uarg);
+	}
+
+	/* Whatever the result, remove copytool from kuc groups.
+	 * Unreached coordinators will get EPIPE on next requests
+	 * and will unregister automatically.
+	 */
+	rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group);
+	return rc;
 }
 
+static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len,
+			       struct lustre_kernelcomm *lk, void *uarg)
+{
+	struct file	*filp;
+	int		 i, j, err;
+	int		 rc = 0;
+	bool		 any_set = false;
+
+	/* All or nothing: try to register to all MDS.
+	 * In case of failure, unregister from previous MDS,
+	 * except if it because of inactive target. */
+	for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
+		err = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp,
+				   len, lk, uarg);
+		if (err) {
+			if (lmv->tgts[i]->ltd_active) {
+				/* permanent error */
+				CERROR("error: iocontrol MDC %s on MDT"
+				       "idx %d cmd %x: err = %d\n",
+					lmv->tgts[i]->ltd_uuid.uuid,
+					i, cmd, err);
+				rc = err;
+				lk->lk_flags |= LK_FLG_STOP;
+				/* unregister from previous MDS */
+				for (j = 0; j < i; j++)
+					obd_iocontrol(cmd,
+						  lmv->tgts[j]->ltd_exp,
+						  len, lk, uarg);
+				return rc;
+			}
+			/* else: transient error.
+			 * kuc will register to the missing MDT
+			 * when it is back */
+		} else {
+			any_set = true;
+		}
+	}
+
+	if (!any_set)
+		/* no registration done: return error */
+		return -ENOTCONN;
+
+	/* at least one registration done, with no failure */
+	filp = fget(lk->lk_wfd);
+	if (filp == NULL) {
+		return -EBADF;
+	}
+	rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, lk->lk_data);
+	if (rc != 0 && filp != NULL)
+		fput(filp);
+	return rc;
+}
+
+
+
+
 static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 			 int len, void *karg, void *uarg)
 {
@@ -792,10 +899,9 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 	int		   rc = 0;
 	int		   set = 0;
 	int		   count = lmv->desc.ld_tgt_count;
-	ENTRY;
 
 	if (count == 0)
-		RETURN(-ENOTTY);
+		return -ENOTTY;
 
 	switch (cmd) {
 	case IOC_OBD_STATFS: {
@@ -806,31 +912,31 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 
 		memcpy(&index, data->ioc_inlbuf2, sizeof(__u32));
 		if ((index >= count))
-			RETURN(-ENODEV);
+			return -ENODEV;
 
 		if (lmv->tgts[index] == NULL ||
 		    lmv->tgts[index]->ltd_active == 0)
-			RETURN(-ENODATA);
+			return -ENODATA;
 
 		mdc_obd = class_exp2obd(lmv->tgts[index]->ltd_exp);
 		if (!mdc_obd)
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		/* copy UUID */
 		if (copy_to_user(data->ioc_pbuf2, obd2cli_tgt(mdc_obd),
 				     min((int) data->ioc_plen2,
 					 (int) sizeof(struct obd_uuid))))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		rc = obd_statfs(NULL, lmv->tgts[index]->ltd_exp, &stat_buf,
 				cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 				0);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		if (copy_to_user(data->ioc_pbuf1, &stat_buf,
 				     min((int) data->ioc_plen1,
 					 (int) sizeof(stat_buf))))
-			RETURN(-EFAULT);
+			return -EFAULT;
 		break;
 	}
 	case OBD_IOC_QUOTACTL: {
@@ -840,11 +946,11 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 
 		if (qctl->qc_valid == QC_MDTIDX) {
 			if (qctl->qc_idx < 0 || count <= qctl->qc_idx)
-				RETURN(-EINVAL);
+				return -EINVAL;
 
 			tgt = lmv->tgts[qctl->qc_idx];
 			if (tgt == NULL || tgt->ltd_exp == NULL)
-				RETURN(-EINVAL);
+				return -EINVAL;
 		} else if (qctl->qc_valid == QC_UUID) {
 			for (i = 0; i < count; i++) {
 				tgt = lmv->tgts[i];
@@ -855,21 +961,21 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 					continue;
 
 				if (tgt->ltd_exp == NULL)
-					RETURN(-EINVAL);
+					return -EINVAL;
 
 				break;
 			}
 		} else {
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (i >= count)
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 
 		LASSERT(tgt && tgt->ltd_exp);
 		OBD_ALLOC_PTR(oqctl);
 		if (!oqctl)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		QCTL_COPY(oqctl, qctl);
 		rc = obd_quotactl(tgt->ltd_exp, oqctl);
@@ -886,19 +992,19 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 		struct ioc_changelog *icc = karg;
 
 		if (icc->icc_mdtindex >= count)
-			RETURN(-ENODEV);
+			return -ENODEV;
 
 		if (lmv->tgts[icc->icc_mdtindex] == NULL ||
 		    lmv->tgts[icc->icc_mdtindex]->ltd_exp == NULL ||
 		    lmv->tgts[icc->icc_mdtindex]->ltd_active == 0)
-			RETURN(-ENODEV);
+			return -ENODEV;
 		rc = obd_iocontrol(cmd, lmv->tgts[icc->icc_mdtindex]->ltd_exp,
 				   sizeof(*icc), icc, NULL);
 		break;
 	}
 	case LL_IOC_GET_CONNECT_FLAGS: {
 		if (lmv->tgts[0] == NULL)
-			RETURN(-ENODATA);
+			return -ENODATA;
 		rc = obd_iocontrol(cmd, lmv->tgts[0]->ltd_exp, len, karg, uarg);
 		break;
 	}
@@ -908,29 +1014,107 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 	}
 	case LL_IOC_HSM_STATE_GET:
 	case LL_IOC_HSM_STATE_SET:
-	case LL_IOC_HSM_ACTION:
+	case LL_IOC_HSM_ACTION: {
+		struct md_op_data	*op_data = karg;
+		struct lmv_tgt_desc	*tgt;
+
+		tgt = lmv_find_target(lmv, &op_data->op_fid1);
+		if (IS_ERR(tgt))
+				return PTR_ERR(tgt);
+
+		if (tgt->ltd_exp == NULL)
+				return -EINVAL;
+
+		rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
+		break;
+	}
+	case LL_IOC_HSM_PROGRESS: {
+		const struct hsm_progress_kernel *hpk = karg;
+		struct lmv_tgt_desc	*tgt;
+
+		tgt = lmv_find_target(lmv, &hpk->hpk_fid);
+		if (IS_ERR(tgt))
+			return PTR_ERR(tgt);
+		rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
+		break;
+	}
+	case LL_IOC_HSM_REQUEST: {
+		struct hsm_user_request *hur = karg;
+		struct lmv_tgt_desc	*tgt;
+		unsigned int reqcount = hur->hur_request.hr_itemcount;
+
+		if (reqcount == 0)
+			return 0;
+
+		/* if the request is about a single fid
+		 * or if there is a single MDS, no need to split
+		 * the request. */
+		if (reqcount == 1 || count == 1) {
+			tgt = lmv_find_target(lmv,
+					      &hur->hur_user_item[0].hui_fid);
+			if (IS_ERR(tgt))
+				return PTR_ERR(tgt);
+			rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
+		} else {
+			/* split fid list to their respective MDS */
+			for (i = 0; i < count; i++) {
+				unsigned int		nr, reqlen;
+				int			rc1;
+				struct hsm_user_request *req;
+
+				nr = lmv_hsm_req_count(lmv, hur, lmv->tgts[i]);
+				if (nr == 0) /* nothing for this MDS */
+					continue;
+
+				/* build a request with fids for this MDS */
+				reqlen = offsetof(typeof(*hur),
+						  hur_user_item[nr])
+					 + hur->hur_request.hr_data_len;
+				OBD_ALLOC_LARGE(req, reqlen);
+				if (req == NULL)
+					return -ENOMEM;
+
+				lmv_hsm_req_build(lmv, hur, lmv->tgts[i], req);
+
+				rc1 = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp,
+						    reqlen, req, uarg);
+				if (rc1 != 0 && rc == 0)
+					rc = rc1;
+				OBD_FREE_LARGE(req, reqlen);
+			}
+		}
+		break;
+	}
 	case LL_IOC_LOV_SWAP_LAYOUTS: {
 		struct md_op_data	*op_data = karg;
 		struct lmv_tgt_desc	*tgt1, *tgt2;
 
 		tgt1 = lmv_find_target(lmv, &op_data->op_fid1);
 		if (IS_ERR(tgt1))
-			RETURN(PTR_ERR(tgt1));
+			return PTR_ERR(tgt1);
 
 		tgt2 = lmv_find_target(lmv, &op_data->op_fid2);
 		if (IS_ERR(tgt2))
-			RETURN(PTR_ERR(tgt2));
+			return PTR_ERR(tgt2);
 
 		if ((tgt1->ltd_exp == NULL) || (tgt2->ltd_exp == NULL))
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		/* only files on same MDT can have their layouts swapped */
 		if (tgt1->ltd_idx != tgt2->ltd_idx)
-			RETURN(-EPERM);
+			return -EPERM;
 
 		rc = obd_iocontrol(cmd, tgt1->ltd_exp, len, karg, uarg);
 		break;
 	}
+	case LL_IOC_HSM_CT_START: {
+		struct lustre_kernelcomm *lk = karg;
+		if (lk->lk_flags & LK_FLG_STOP)
+			rc = lmv_hsm_ct_unregister(lmv, cmd, len, lk, uarg);
+		else
+			rc = lmv_hsm_ct_register(lmv, cmd, len, lk, uarg);
+		break;
+	}
 	default:
 		for (i = 0; i < count; i++) {
 			struct obd_device *mdc_obd;
@@ -946,7 +1130,7 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 			err = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, len,
 					    karg, uarg);
 			if (err == -ENODATA && cmd == OBD_IOC_POLL_QUOTACHECK) {
-				RETURN(err);
+				return err;
 			} else if (err) {
 				if (lmv->tgts[i]->ltd_active) {
 					CERROR("error: iocontrol MDC %s on MDT"
@@ -962,7 +1146,7 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
 		if (!set && !rc)
 			rc = -EIO;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 #if 0
@@ -1018,13 +1202,12 @@ static int lmv_placement_policy(struct obd_device *obd,
 				mdsno_t *mds)
 {
 	struct lmv_obd	  *lmv = &obd->u.lmv;
-	ENTRY;
 
 	LASSERT(mds != NULL);
 
 	if (lmv->desc.ld_tgt_count == 1) {
 		*mds = 0;
-		RETURN(0);
+		return 0;
 	}
 
 	/**
@@ -1042,17 +1225,17 @@ static int lmv_placement_policy(struct obd_device *obd,
 				       " rc = %d\n", obd->obd_name,
 				       lum->lum_stripe_offset,
 				       lmv->desc.ld_tgt_count, -ERANGE);
-				RETURN(-ERANGE);
+				return -ERANGE;
 			}
 			*mds = lum->lum_stripe_offset;
-			RETURN(0);
+			return 0;
 		}
 	}
 
 	/* Allocate new fid on target according to operation type and parent
 	 * home mds. */
 	*mds = op_data->op_mds;
-	RETURN(0);
+	return 0;
 }
 
 int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid,
@@ -1060,11 +1243,10 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid,
 {
 	struct lmv_tgt_desc	*tgt;
 	int			 rc;
-	ENTRY;
 
 	tgt = lmv_get_target(lmv, mds);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	/*
 	 * New seq alloc and FLD setup should be atomic. Otherwise we may find
@@ -1084,7 +1266,6 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid,
 		rc = 0;
 	}
 
-	EXIT;
 out:
 	mutex_unlock(&tgt->ltd_fid_mutex);
 	return rc;
@@ -1097,7 +1278,6 @@ int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
 	struct lmv_obd	*lmv = &obd->u.lmv;
 	mdsno_t		mds = 0;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(op_data != NULL);
 	LASSERT(fid != NULL);
@@ -1106,16 +1286,16 @@ int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
 	if (rc) {
 		CERROR("Can't get target for allocating fid, "
 		       "rc %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = __lmv_fid_alloc(lmv, fid, mds);
 	if (rc) {
 		CERROR("Can't alloc new fid, rc %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
@@ -1124,23 +1304,22 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	struct lprocfs_static_vars  lvars;
 	struct lmv_desc	    *desc;
 	int			 rc;
-	ENTRY;
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
 		CERROR("LMV setup requires a descriptor\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	desc = (struct lmv_desc *)lustre_cfg_buf(lcfg, 1);
 	if (sizeof(*desc) > LUSTRE_CFG_BUFLEN(lcfg, 1)) {
 		CERROR("Lmv descriptor size wrong: %d > %d\n",
 		       (int)sizeof(*desc), LUSTRE_CFG_BUFLEN(lcfg, 1));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	OBD_ALLOC(lmv->tgts, sizeof(*lmv->tgts) * 32);
 	if (lmv->tgts == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lmv->tgts_size = 32;
 
 	obd_str2uuid(&lmv->desc.ld_uuid, desc->ld_uuid.uuid);
@@ -1173,7 +1352,7 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 		GOTO(out, rc);
 	}
 
-	RETURN(0);
+	return 0;
 
 out:
 	return rc;
@@ -1182,7 +1361,6 @@ out:
 static int lmv_cleanup(struct obd_device *obd)
 {
 	struct lmv_obd   *lmv = &obd->u.lmv;
-	ENTRY;
 
 	fld_client_fini(&lmv->lmv_fld);
 	if (lmv->tgts != NULL) {
@@ -1195,7 +1373,7 @@ static int lmv_cleanup(struct obd_device *obd)
 		OBD_FREE(lmv->tgts, sizeof(*lmv->tgts) * lmv->tgts_size);
 		lmv->tgts_size = 0;
 	}
-	RETURN(0);
+	return 0;
 }
 
 static int lmv_process_config(struct obd_device *obd, obd_count len, void *buf)
@@ -1205,7 +1383,6 @@ static int lmv_process_config(struct obd_device *obd, obd_count len, void *buf)
 	int			gen;
 	__u32			index;
 	int			rc;
-	ENTRY;
 
 	switch (lcfg->lcfg_command) {
 	case LCFG_ADD_MDC:
@@ -1227,7 +1404,7 @@ static int lmv_process_config(struct obd_device *obd, obd_count len, void *buf)
 		GOTO(out, rc = -EINVAL);
 	}
 out:
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_statfs(const struct lu_env *env, struct obd_export *exp,
@@ -1238,15 +1415,14 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp,
 	struct obd_statfs     *temp;
 	int		    rc = 0;
 	int		    i;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	OBD_ALLOC(temp, sizeof(*temp));
 	if (temp == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
 		if (lmv->tgts[i] == NULL || lmv->tgts[i]->ltd_exp == NULL)
@@ -1279,7 +1455,6 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp,
 		}
 	}
 
-	EXIT;
 out_free_temp:
 	OBD_FREE(temp, sizeof(*temp));
 	return rc;
@@ -1292,14 +1467,13 @@ static int lmv_getstatus(struct obd_export *exp,
 	struct obd_device    *obd = exp->exp_obd;
 	struct lmv_obd       *lmv = &obd->u.lmv;
 	int		   rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = md_getstatus(lmv->tgts[0]->ltd_exp, fid, pc);
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_getxattr(struct obd_export *exp, const struct lu_fid *fid,
@@ -1311,20 +1485,19 @@ static int lmv_getxattr(struct obd_export *exp, const struct lu_fid *fid,
 	struct lmv_obd	 *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc    *tgt;
 	int		     rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_getxattr(tgt->ltd_exp, fid, oc, valid, name, input,
 			 input_size, output_size, flags, request);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
@@ -1337,21 +1510,20 @@ static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
 	struct lmv_obd	 *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc    *tgt;
 	int		     rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_setxattr(tgt->ltd_exp, fid, oc, valid, name, input,
 			 input_size, output_size, flags, suppgid,
 			 request);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_getattr(struct obd_export *exp, struct md_op_data *op_data,
@@ -1361,24 +1533,23 @@ static int lmv_getattr(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	if (op_data->op_flags & MF_GET_MDT_IDX) {
 		op_data->op_mds = tgt->ltd_idx;
-		RETURN(0);
+		return 0;
 	}
 
 	rc = md_getattr(tgt->ltd_exp, op_data, request);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid)
@@ -1387,11 +1558,10 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid)
 	struct lmv_obd      *lmv = &obd->u.lmv;
 	int		  i;
 	int		  rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid));
 
@@ -1406,7 +1576,7 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid)
 		md_null_inode(lmv->tgts[i]->ltd_exp, fid);
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid,
@@ -1416,11 +1586,10 @@ static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid,
 	struct lmv_obd      *lmv = &obd->u.lmv;
 	int		  i;
 	int		  rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid));
 
@@ -1434,10 +1603,10 @@ static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid,
 			continue;
 		rc = md_find_cbdata(lmv->tgts[i]->ltd_exp, fid, it, data);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1448,19 +1617,18 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_obd	*lmv = &obd->u.lmv;
 	struct lmv_tgt_desc   *tgt;
 	int		    rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	CDEBUG(D_INODE, "CLOSE "DFID"\n", PFID(&op_data->op_fid1));
 	rc = md_close(tgt->ltd_exp, op_data, mod, request);
-	RETURN(rc);
+	return rc;
 }
 
 struct lmv_tgt_desc
@@ -1487,22 +1655,21 @@ int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (!lmv->desc.ld_active_tgt_count)
-		RETURN(-EIO);
+		return -EIO;
 
 	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "CREATE '%*s' on "DFID" -> mds #%x\n",
 	       op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1),
@@ -1514,10 +1681,10 @@ int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
 
 	if (rc == 0) {
 		if (*request == NULL)
-			RETURN(rc);
+			return rc;
 		CDEBUG(D_INODE, "Created - "DFID"\n", PFID(&op_data->op_fid2));
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_done_writing(struct obd_export *exp,
@@ -1528,18 +1695,17 @@ static int lmv_done_writing(struct obd_export *exp,
 	struct lmv_obd	*lmv = &obd->u.lmv;
 	struct lmv_tgt_desc   *tgt;
 	int		    rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_done_writing(tgt->ltd_exp, op_data, mod);
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -1558,13 +1724,12 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 	struct mdt_body	    *body;
 	int			 rc = 0;
 	int			 pmode;
-	ENTRY;
 
 	body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 	LASSERT(body != NULL);
 
 	if (!(body->valid & OBD_MD_MDS))
-		RETURN(0);
+		return 0;
 
 	CDEBUG(D_INODE, "REMOTE_ENQUEUE '%s' on "DFID" -> "DFID"\n",
 	       LL_IT2STR(it), PFID(&op_data->op_fid1), PFID(&body->fid1));
@@ -1596,7 +1761,6 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 	rc = md_enqueue(tgt->ltd_exp, einfo, it, rdata, lockh,
 			lmm, lmmsize, NULL, extra_lock_flags);
 	OBD_FREE_PTR(rdata);
-	EXIT;
 out:
 	ldlm_lock_decref(&plock, pmode);
 	return rc;
@@ -1612,18 +1776,17 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 	struct lmv_obd	   *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc      *tgt;
 	int		       rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID"\n",
 	       LL_IT2STR(it), PFID(&op_data->op_fid1));
 
 	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID" -> mds #%d\n",
 	       LL_IT2STR(it), PFID(&op_data->op_fid1), tgt->ltd_idx);
@@ -1635,7 +1798,7 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 		rc = lmv_enqueue_remote(exp, einfo, it, op_data, lockh,
 					lmm, lmmsize, extra_lock_flags);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -1648,15 +1811,14 @@ lmv_getattr_name(struct obd_export *exp,struct md_op_data *op_data,
 	struct lmv_tgt_desc     *tgt;
 	struct mdt_body	 *body;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	CDEBUG(D_INODE, "GETATTR_NAME for %*s on "DFID" -> mds #%d\n",
 	       op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1),
@@ -1664,7 +1826,7 @@ lmv_getattr_name(struct obd_export *exp,struct md_op_data *op_data,
 
 	rc = md_getattr_name(tgt->ltd_exp, op_data, request);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	body = req_capsule_server_get(&(*request)->rq_pill,
 				      &RMF_MDT_BODY);
@@ -1678,7 +1840,7 @@ lmv_getattr_name(struct obd_export *exp,struct md_op_data *op_data,
 		tgt = lmv_find_target(lmv, &rid);
 		if (IS_ERR(tgt)) {
 			ptlrpc_req_finished(*request);
-			RETURN(PTR_ERR(tgt));
+			return PTR_ERR(tgt);
 		}
 
 		op_data->op_fid1 = rid;
@@ -1690,7 +1852,7 @@ lmv_getattr_name(struct obd_export *exp,struct md_op_data *op_data,
 		*request = req;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 #define md_op_data_fid(op_data, fl)		     \
@@ -1709,14 +1871,13 @@ static int lmv_early_cancel(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_tgt_desc    *tgt;
 	ldlm_policy_data_t      policy = {{0}};
 	int		     rc = 0;
-	ENTRY;
 
 	if (!fid_is_sane(fid))
-		RETURN(0);
+		return 0;
 
 	tgt = lmv_find_target(lmv, fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	if (tgt->ltd_idx != op_tgt) {
 		CDEBUG(D_INODE, "EARLY_CANCEL on "DFID"\n", PFID(fid));
@@ -1731,7 +1892,7 @@ static int lmv_early_cancel(struct obd_export *exp, struct md_op_data *op_data,
 		rc = 0;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -1745,11 +1906,10 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	LASSERT(op_data->op_namelen != 0);
 
@@ -1757,12 +1917,12 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data,
 	       PFID(&op_data->op_fid2), op_data->op_namelen,
 	       op_data->op_name, PFID(&op_data->op_fid1));
 
-	op_data->op_fsuid = current_fsuid();
-	op_data->op_fsgid = current_fsgid();
+	op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
+	op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
 	op_data->op_cap = cfs_curproc_cap_pack();
 	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	/*
 	 * Cancel UPDATE lock on child (fid1).
@@ -1771,11 +1931,11 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data,
 	rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX,
 			      MDS_INODELOCK_UPDATE, MF_MDC_CANCEL_FID1);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	rc = md_link(tgt->ltd_exp, op_data, request);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
@@ -1787,7 +1947,6 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_tgt_desc     *src_tgt;
 	struct lmv_tgt_desc     *tgt_tgt;
 	int			rc;
-	ENTRY;
 
 	LASSERT(oldlen != 0);
 
@@ -1797,18 +1956,18 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
-	op_data->op_fsuid = current_fsuid();
-	op_data->op_fsgid = current_fsgid();
+	op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
+	op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
 	op_data->op_cap = cfs_curproc_cap_pack();
 	src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(src_tgt))
-		RETURN(PTR_ERR(src_tgt));
+		return PTR_ERR(src_tgt);
 
 	tgt_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2);
 	if (IS_ERR(tgt_tgt))
-		RETURN(PTR_ERR(tgt_tgt));
+		return PTR_ERR(tgt_tgt);
 	/*
 	 * LOOKUP lock on src child (fid3) should also be cancelled for
 	 * src_tgt in mdc_rename.
@@ -1843,7 +2002,7 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
 	if (rc == 0)
 		rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen,
 			       new, newlen, request);
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
@@ -1855,11 +2014,10 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc = 0;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "SETATTR for "DFID", valid 0x%x\n",
 	       PFID(&op_data->op_fid1), op_data->op_attr.ia_valid);
@@ -1867,12 +2025,12 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
 	op_data->op_flags |= MF_MDC_CANCEL_FID1;
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_setattr(tgt->ltd_exp, op_data, ea, ealen, ea2,
 			ea2len, request, mod);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid,
@@ -1882,18 +2040,17 @@ static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid,
 	struct lmv_obd	    *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc       *tgt;
 	int			rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_sync(tgt->ltd_exp, fid, oc, request);
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -1959,7 +2116,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs)
 		__u64			hash_end = dp->ldp_hash_end;
 		__u32			flags = dp->ldp_flags;
 
-		for (; nlupgs > 1; nlupgs--) {
+		while (--nlupgs > 0) {
 			ent = lu_dirent_start(dp);
 			for (end_dirent = ent; ent != NULL;
 			     end_dirent = ent, ent = lu_dirent_next(ent));
@@ -1993,6 +2150,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs)
 
 		kunmap(pages[i]);
 	}
+	LASSERTF(nlupgs == 0, "left = %d", nlupgs);
 }
 #else
 #define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0)
@@ -2008,22 +2166,21 @@ static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data,
 	int			ncfspgs; /* pages read in PAGE_CACHE_SIZE */
 	int			nlupgs; /* pages read in LU_PAGE_SIZE */
 	struct lmv_tgt_desc	*tgt;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "READPAGE at "LPX64" from "DFID"\n",
 	       offset, PFID(&op_data->op_fid1));
 
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_readpage(tgt->ltd_exp, op_data, pages, request);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	ncfspgs = ((*request)->rq_bulk->bd_nob_transferred + PAGE_CACHE_SIZE - 1)
 		 >> PAGE_CACHE_SHIFT;
@@ -2036,7 +2193,7 @@ static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data,
 
 	lmv_adjust_dirpages(pages, ncfspgs, nlupgs);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data,
@@ -2047,11 +2204,10 @@ static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data,
 	struct lmv_tgt_desc     *tgt = NULL;
 	struct mdt_body		*body;
 	int		     rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 retry:
 	/* Send unlink requests to the MDT where the child is located */
 	if (likely(!fid_is_zero(&op_data->op_fid2)))
@@ -2059,10 +2215,10 @@ retry:
 	else
 		tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
-	op_data->op_fsuid = current_fsuid();
-	op_data->op_fsgid = current_fsgid();
+	op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
+	op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
 	op_data->op_cap = cfs_curproc_cap_pack();
 
 	/*
@@ -2081,22 +2237,22 @@ retry:
 			      MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID3);
 
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INODE, "unlink with fid="DFID"/"DFID" -> mds #%d\n",
 	       PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), tgt->ltd_idx);
 
 	rc = md_unlink(tgt->ltd_exp, op_data, request);
 	if (rc != 0 && rc != -EREMOTE)
-		RETURN(rc);
+		return rc;
 
 	body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY);
 	if (body == NULL)
-		RETURN(-EPROTO);
+		return -EPROTO;
 
 	/* Not cross-ref case, just get out of here. */
 	if (likely(!(body->valid & OBD_MD_MDS)))
-		RETURN(0);
+		return 0;
 
 	CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n",
 	       exp->exp_obd->obd_name, PFID(&body->fid1));
@@ -2144,7 +2300,7 @@ static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 	default:
 		break;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
@@ -2154,13 +2310,12 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
 	struct obd_device       *obd;
 	struct lmv_obd	  *lmv;
 	int		      rc = 0;
-	ENTRY;
 
 	obd = class_exp2obd(exp);
 	if (obd == NULL) {
 		CDEBUG(D_IOCTL, "Invalid client cookie "LPX64"\n",
 		       exp->exp_handle.h_cookie);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	lmv = &obd->u.lmv;
@@ -2170,7 +2325,7 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
 
 		rc = lmv_check_connect(obd);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		LASSERT(*vallen == sizeof(__u32));
 		for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
@@ -2183,13 +2338,13 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
 
 			if (!obd_get_info(env, tgt->ltd_exp, keylen, key,
 					  vallen, val, NULL))
-				RETURN(0);
+				return 0;
 		}
-		RETURN(-EINVAL);
+		return -EINVAL;
 	} else if (KEY_IS(KEY_MAX_EASIZE) || KEY_IS(KEY_CONN_DATA)) {
 		rc = lmv_check_connect(obd);
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		/*
 		 * Forwarding this request to first MDS, it should know LOV
@@ -2199,14 +2354,14 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
 				  vallen, val, NULL);
 		if (!rc && KEY_IS(KEY_CONN_DATA))
 			exp->exp_connect_data = *(struct obd_connect_data *)val;
-		RETURN(rc);
+		return rc;
 	} else if (KEY_IS(KEY_TGT_COUNT)) {
 		*((int *)val) = lmv->desc.ld_tgt_count;
-		RETURN(0);
+		return 0;
 	}
 
 	CDEBUG(D_IOCTL, "Invalid key\n");
-	RETURN(-EINVAL);
+	return -EINVAL;
 }
 
 int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp,
@@ -2217,13 +2372,12 @@ int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp,
 	struct obd_device      *obd;
 	struct lmv_obd	 *lmv;
 	int rc = 0;
-	ENTRY;
 
 	obd = class_exp2obd(exp);
 	if (obd == NULL) {
 		CDEBUG(D_IOCTL, "Invalid client cookie "LPX64"\n",
 		       exp->exp_handle.h_cookie);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	lmv = &obd->u.lmv;
 
@@ -2242,10 +2396,10 @@ int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp,
 				rc = err;
 		}
 
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(-EINVAL);
+	return -EINVAL;
 }
 
 int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
@@ -2257,33 +2411,32 @@ int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 	struct lmv_stripe_md      *lsmp;
 	int			mea_size;
 	int			i;
-	ENTRY;
 
 	mea_size = lmv_get_easize(lmv);
 	if (!lmmp)
-		RETURN(mea_size);
+		return mea_size;
 
 	if (*lmmp && !lsm) {
 		OBD_FREE_LARGE(*lmmp, mea_size);
 		*lmmp = NULL;
-		RETURN(0);
+		return 0;
 	}
 
 	if (*lmmp == NULL) {
 		OBD_ALLOC_LARGE(*lmmp, mea_size);
 		if (*lmmp == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 	}
 
 	if (!lsm)
-		RETURN(mea_size);
+		return mea_size;
 
 	lsmp = (struct lmv_stripe_md *)lsm;
 	meap = (struct lmv_stripe_md *)*lmmp;
 
 	if (lsmp->mea_magic != MEA_MAGIC_LAST_CHAR &&
 	    lsmp->mea_magic != MEA_MAGIC_ALL_CHARS)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	meap->mea_magic = cpu_to_le32(lsmp->mea_magic);
 	meap->mea_count = cpu_to_le32(lsmp->mea_count);
@@ -2294,7 +2447,7 @@ int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 		fid_cpu_to_le(&meap->mea_ids[i], &lsmp->mea_ids[i]);
 	}
 
-	RETURN(mea_size);
+	return mea_size;
 }
 
 int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
@@ -2307,7 +2460,6 @@ int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 	int			 mea_size;
 	int			 i;
 	__u32		       magic;
-	ENTRY;
 
 	mea_size = lmv_get_easize(lmv);
 	if (lsmp == NULL)
@@ -2316,17 +2468,17 @@ int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 	if (*lsmp != NULL && lmm == NULL) {
 		OBD_FREE_LARGE(*tmea, mea_size);
 		*lsmp = NULL;
-		RETURN(0);
+		return 0;
 	}
 
 	LASSERT(mea_size == lmm_size);
 
 	OBD_ALLOC_LARGE(*tmea, mea_size);
 	if (*tmea == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (!lmm)
-		RETURN(mea_size);
+		return mea_size;
 
 	if (mea->mea_magic == MEA_MAGIC_LAST_CHAR ||
 	    mea->mea_magic == MEA_MAGIC_ALL_CHARS ||
@@ -2349,7 +2501,7 @@ int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 		(*tmea)->mea_ids[i] = mea->mea_ids[i];
 		fid_le_to_cpu(&(*tmea)->mea_ids[i], &(*tmea)->mea_ids[i]);
 	}
-	RETURN(mea_size);
+	return mea_size;
 }
 
 static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid,
@@ -2361,7 +2513,6 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid,
 	int		      rc = 0;
 	int		      err;
 	int		      i;
-	ENTRY;
 
 	LASSERT(fid != NULL);
 
@@ -2375,7 +2526,7 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid,
 		if (!rc)
 			rc = err;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
@@ -2383,10 +2534,9 @@ int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
 {
 	struct lmv_obd	  *lmv = &exp->exp_obd->u.lmv;
 	int		      rc;
-	ENTRY;
 
 	rc =  md_set_lock_data(lmv->tgts[0]->ltd_exp, lockh, data, bits);
-	RETURN(rc);
+	return rc;
 }
 
 ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags,
@@ -2398,7 +2548,6 @@ ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	ldlm_mode_t	      rc;
 	int		      i;
-	ENTRY;
 
 	CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid));
 
@@ -2417,10 +2566,10 @@ ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags,
 		rc = md_lock_match(lmv->tgts[i]->ltd_exp, flags, fid,
 				   type, policy, mode, lockh);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int lmv_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
@@ -2436,11 +2585,10 @@ int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
 {
 	struct obd_device       *obd = exp->exp_obd;
 	struct lmv_obd	  *lmv = &obd->u.lmv;
-	ENTRY;
 
 	if (md->mea)
 		obd_free_memmd(exp, (void *)&md->mea);
-	RETURN(md_free_lustre_md(lmv->tgts[0]->ltd_exp, md));
+	return md_free_lustre_md(lmv->tgts[0]->ltd_exp, md);
 }
 
 int lmv_set_open_replay_data(struct obd_export *exp,
@@ -2450,13 +2598,12 @@ int lmv_set_open_replay_data(struct obd_export *exp,
 	struct obd_device       *obd = exp->exp_obd;
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
-	ENTRY;
 
 	tgt = lmv_find_target(lmv, &och->och_fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
-	RETURN(md_set_open_replay_data(tgt->ltd_exp, och, open_req));
+	return md_set_open_replay_data(tgt->ltd_exp, och, open_req);
 }
 
 int lmv_clear_open_replay_data(struct obd_export *exp,
@@ -2465,13 +2612,12 @@ int lmv_clear_open_replay_data(struct obd_export *exp,
 	struct obd_device       *obd = exp->exp_obd;
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
-	ENTRY;
 
 	tgt = lmv_find_target(lmv, &och->och_fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
-	RETURN(md_clear_open_replay_data(tgt->ltd_exp, och));
+	return md_clear_open_replay_data(tgt->ltd_exp, och);
 }
 
 static int lmv_get_remote_perm(struct obd_export *exp,
@@ -2483,18 +2629,17 @@ static int lmv_get_remote_perm(struct obd_export *exp,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_get_remote_perm(tgt->ltd_exp, fid, oc, suppgid, request);
-	RETURN(rc);
+	return rc;
 }
 
 static int lmv_renew_capa(struct obd_export *exp, struct obd_capa *oc,
@@ -2504,18 +2649,17 @@ static int lmv_renew_capa(struct obd_export *exp, struct obd_capa *oc,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, &oc->c_capa.lc_fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_renew_capa(tgt->ltd_exp, oc, cb);
-	RETURN(rc);
+	return rc;
 }
 
 int lmv_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req,
@@ -2535,18 +2679,17 @@ int lmv_intent_getattr_async(struct obd_export *exp,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt = NULL;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_intent_getattr_async(tgt->ltd_exp, minfo, einfo);
-	RETURN(rc);
+	return rc;
 }
 
 int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
@@ -2556,18 +2699,17 @@ int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
 	struct lmv_obd	  *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc     *tgt;
 	int		      rc;
-	ENTRY;
 
 	rc = lmv_check_connect(obd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = lmv_find_target(lmv, fid);
 	if (IS_ERR(tgt))
-		RETURN(PTR_ERR(tgt));
+		return PTR_ERR(tgt);
 
 	rc = md_revalidate_lock(tgt->ltd_exp, it, fid, bits);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2583,16 +2725,15 @@ int lmv_quotactl(struct obd_device *unused, struct obd_export *exp,
 	struct lmv_tgt_desc *tgt = lmv->tgts[0];
 	int		  rc = 0, i;
 	__u64		curspace, curinodes;
-	ENTRY;
 
 	if (!lmv->desc.ld_tgt_count || !tgt->ltd_active) {
 		CERROR("master lmv inactive\n");
-		RETURN(-EIO);
+		return -EIO;
 	}
 
 	if (oqctl->qc_cmd != Q_GETOQUOTA) {
 		rc = obd_quotactl(tgt->ltd_exp, oqctl);
-		RETURN(rc);
+		return rc;
 	}
 
 	curspace = curinodes = 0;
@@ -2620,7 +2761,7 @@ int lmv_quotactl(struct obd_device *unused, struct obd_export *exp,
 	oqctl->qc_dqblk.dqb_curspace = curspace;
 	oqctl->qc_dqblk.dqb_curinodes = curinodes;
 
-	RETURN(rc);
+	return rc;
 }
 
 int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp,
@@ -2630,14 +2771,13 @@ int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp,
 	struct lmv_obd      *lmv = &obd->u.lmv;
 	struct lmv_tgt_desc *tgt;
 	int		  i, rc = 0;
-	ENTRY;
 
 	for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
 		int err;
 		tgt = lmv->tgts[i];
 		if (tgt == NULL || tgt->ltd_exp == NULL || !tgt->ltd_active) {
 			CERROR("lmv idx %d inactive\n", i);
-			RETURN(-EIO);
+			return -EIO;
 		}
 
 		err = obd_quotacheck(tgt->ltd_exp, oqctl);
@@ -2645,7 +2785,7 @@ int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp,
 			rc = err;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 struct obd_ops lmv_obd_ops = {
diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c
index d1c45b5..edb5a3a 100644
--- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c
+++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c
@@ -36,7 +36,6 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/version.h>
 #include <linux/seq_file.h>
 #include <asm/statfs.h>
 #include <lprocfs_status.h>
diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
index 28801b8..33d9ce6 100644
--- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
+++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
@@ -162,10 +162,9 @@ struct lov_device {
  * Layout type.
  */
 enum lov_layout_type {
-	/** empty file without body */
-	LLT_EMPTY,
-	/** striped file */
-	LLT_RAID0,
+	LLT_EMPTY,	/** empty file without body (mknod + truncate) */
+	LLT_RAID0,	/** striped file */
+	LLT_RELEASED,	/** file with no objects (data in HSM) */
 	LLT_NR
 };
 
@@ -255,12 +254,14 @@ struct lov_object {
 		} raid0;
 		struct lov_layout_state_empty {
 		} empty;
+		struct lov_layout_state_released {
+		} released;
 	} u;
 	/**
 	 * Thread that acquired lov_object::lo_type_guard in an exclusive
 	 * mode.
 	 */
-	task_t	    *lo_owner;
+	struct task_struct	*lo_owner;
 };
 
 /**
@@ -582,6 +583,8 @@ int   lov_io_init_raid0   (const struct lu_env *env, struct cl_object *obj,
 			   struct cl_io *io);
 int   lov_io_init_empty   (const struct lu_env *env, struct cl_object *obj,
 			   struct cl_io *io);
+int   lov_io_init_released(const struct lu_env *env, struct cl_object *obj,
+			   struct cl_io *io);
 void  lov_lock_unlink     (const struct lu_env *env, struct lov_lock_link *link,
 			   struct lovsub_lock *sub);
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c
index f94f8d9..a4006ef 100644
--- a/drivers/staging/lustre/lustre/lov/lov_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lov_dev.c
@@ -122,10 +122,8 @@ static void lov_req_completion(const struct lu_env *env,
 {
 	struct lov_req *lr;
 
-	ENTRY;
 	lr = cl2lov_req(slice);
 	OBD_SLAB_FREE_PTR(lr, lov_req_kmem);
-	EXIT;
 }
 
 static const struct cl_req_operations lov_req_ops = {
@@ -200,7 +198,7 @@ static struct lu_device *lov_device_fini(const struct lu_env *env,
 
 	LASSERT(ld->ld_lov != NULL);
 	if (ld->ld_target == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	lov_foreach_target(ld, i) {
 		struct lovsub_device *lsd;
@@ -211,7 +209,7 @@ static struct lu_device *lov_device_fini(const struct lu_env *env,
 			ld->ld_target[i] = NULL;
 		}
 	}
-	RETURN(NULL);
+	return NULL;
 }
 
 static int lov_device_init(const struct lu_env *env, struct lu_device *d,
@@ -223,7 +221,7 @@ static int lov_device_init(const struct lu_env *env, struct lu_device *d,
 
 	LASSERT(d->ld_site != NULL);
 	if (ld->ld_target == NULL)
-		RETURN(rc);
+		return rc;
 
 	lov_foreach_target(ld, i) {
 		struct lovsub_device *lsd;
@@ -251,7 +249,7 @@ static int lov_device_init(const struct lu_env *env, struct lu_device *d,
 	else
 		ld->ld_flags |= LOV_DEV_INITIALIZED;
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_req_init(const struct lu_env *env, struct cl_device *dev,
@@ -260,14 +258,13 @@ static int lov_req_init(const struct lu_env *env, struct cl_device *dev,
 	struct lov_req *lr;
 	int result;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(lr, lov_req_kmem, __GFP_IO);
 	if (lr != NULL) {
 		cl_req_slice_add(req, &lr->lr_cl, dev, &lov_req_ops);
 		result = 0;
 	} else
 		result = -ENOMEM;
-	RETURN(result);
+	return result;
 }
 
 static const struct cl_device_operations lov_cl_ops = {
@@ -311,13 +308,11 @@ static void lov_cl_del_target(const struct lu_env *env, struct lu_device *dev,
 			      __u32 index)
 {
 	struct lov_device *ld = lu2lov_dev(dev);
-	ENTRY;
 
 	if (ld->ld_target[index] != NULL) {
 		cl_stack_fini(env, lovsub2cl_dev(ld->ld_target[index]));
 		ld->ld_target[index] = NULL;
 	}
-	EXIT;
 }
 
 static struct lov_device_emerg **lov_emerg_alloc(int nr)
@@ -360,7 +355,6 @@ static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev)
 	__u32 tgt_size;
 	__u32 sub_size;
 
-	ENTRY;
 	result = 0;
 	tgt_size = dev->ld_lov->lov_tgt_size;
 	sub_size = dev->ld_target_nr;
@@ -371,7 +365,7 @@ static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev)
 
 		emerg = lov_emerg_alloc(tgt_size);
 		if (IS_ERR(emerg))
-			RETURN(PTR_ERR(emerg));
+			return PTR_ERR(emerg);
 
 		OBD_ALLOC(newd, tgt_size * sz);
 		if (newd != NULL) {
@@ -392,7 +386,7 @@ static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev)
 			result = -ENOMEM;
 		}
 	}
-	RETURN(result);
+	return result;
 }
 
 static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
@@ -404,7 +398,6 @@ static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
 	struct lovsub_device *lsd;
 	struct cl_device     *cl;
 	int rc;
-	ENTRY;
 
 	obd_getref(obd);
 
@@ -414,7 +407,7 @@ static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
 
 	if (!tgt->ltd_obd->obd_set_up) {
 		CERROR("Target %s not set up\n", obd_uuid2str(&tgt->ltd_uuid));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = lov_expand_targets(env, ld);
@@ -436,7 +429,7 @@ static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
 		}
 	}
 	obd_putref(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_process_config(const struct lu_env *env,
@@ -466,7 +459,7 @@ static int lov_process_config(const struct lu_env *env,
 		}
 	}
 	obd_putref(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static const struct lu_device_operations lov_lu_ops = {
@@ -485,7 +478,7 @@ static struct lu_device *lov_device_alloc(const struct lu_env *env,
 
 	OBD_ALLOC_PTR(ld);
 	if (ld == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	cl_device_init(&ld->ld_cl, t);
 	d = lov2lu_dev(ld);
@@ -501,11 +494,11 @@ static struct lu_device *lov_device_alloc(const struct lu_env *env,
 	rc = lov_setup(obd, cfg);
 	if (rc) {
 		lov_device_free(env, d);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	ld->ld_lov = &obd->u.lov;
-	RETURN(d);
+	return d;
 }
 
 static const struct lu_device_type_operations lov_device_type_ops = {
diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c
index 340dbcf..e6c6015 100644
--- a/drivers/staging/lustre/lustre/lov/lov_ea.c
+++ b/drivers/staging/lustre/lustre/lov/lov_ea.c
@@ -57,7 +57,7 @@ struct lovea_unpack_args {
 static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes,
 				 __u16 stripe_count)
 {
-	if (stripe_count == 0 || stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
+	if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
 		CERROR("bad stripe count %d\n", stripe_count);
 		lov_dump_lmm_common(D_WARNING, lmm);
 		return -EINVAL;
@@ -69,7 +69,7 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes,
 		return -EINVAL;
 	}
 
-	if (lmm->lmm_pattern != cpu_to_le32(LOV_PATTERN_RAID0)) {
+	if (lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_RAID0) {
 		CERROR("bad striping pattern\n");
 		lov_dump_lmm_common(D_WARNING, lmm);
 		return -EINVAL;
@@ -197,6 +197,8 @@ static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes,
 	}
 
 	*stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
+	if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
+		*stripe_count = 0;
 
 	if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)) {
 		CERROR("LOV EA V1 too small: %d, need %d\n",
@@ -213,11 +215,14 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
 {
 	struct lov_oinfo *loi;
 	int i;
+	int stripe_count;
 	__u64 stripe_maxbytes = OBD_OBJECT_EOF;
 
 	lsm_unpackmd_common(lsm, lmm);
 
-	for (i = 0; i < lsm->lsm_stripe_count; i++) {
+	stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count;
+
+	for (i = 0; i < stripe_count; i++) {
 		/* XXX LOV STACKING call down to osc_unpackmd() */
 		loi = lsm->lsm_oinfo[i];
 		ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
@@ -240,6 +245,8 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
 	}
 
 	lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count;
+	if (lsm->lsm_stripe_count == 0)
+		lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count;
 
 	return 0;
 }
@@ -267,6 +274,8 @@ static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes,
 	}
 
 	*stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
+	if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
+		*stripe_count = 0;
 
 	if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)) {
 		CERROR("LOV EA V3 too small: %d, need %d\n",
@@ -285,18 +294,22 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
 	struct lov_mds_md_v3 *lmm;
 	struct lov_oinfo *loi;
 	int i;
+	int stripe_count;
 	__u64 stripe_maxbytes = OBD_OBJECT_EOF;
 	int cplen = 0;
 
 	lmm = (struct lov_mds_md_v3 *)lmmv1;
 
 	lsm_unpackmd_common(lsm, (struct lov_mds_md_v1 *)lmm);
+
+	stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count;
+
 	cplen = strlcpy(lsm->lsm_pool_name, lmm->lmm_pool_name,
 			sizeof(lsm->lsm_pool_name));
 	if (cplen >= sizeof(lsm->lsm_pool_name))
 		return -E2BIG;
 
-	for (i = 0; i < lsm->lsm_stripe_count; i++) {
+	for (i = 0; i < stripe_count; i++) {
 		/* XXX LOV STACKING call down to osc_unpackmd() */
 		loi = lsm->lsm_oinfo[i];
 		ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
@@ -319,6 +332,8 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
 	}
 
 	lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count;
+	if (lsm->lsm_stripe_count == 0)
+		lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count;
 
 	return 0;
 }
diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c
index 1a87abd..b611aa4 100644
--- a/drivers/staging/lustre/lustre/lov/lov_io.c
+++ b/drivers/staging/lustre/lustre/lov/lov_io.c
@@ -59,7 +59,6 @@ static inline void lov_sub_exit(struct lov_io_sub *sub)
 static void lov_io_sub_fini(const struct lu_env *env, struct lov_io *lio,
 			    struct lov_io_sub *sub)
 {
-	ENTRY;
 	if (sub->sub_io != NULL) {
 		if (sub->sub_io_initialized) {
 			lov_sub_enter(sub);
@@ -79,7 +78,6 @@ static void lov_io_sub_fini(const struct lu_env *env, struct lov_io *lio,
 			cl_env_put(sub->sub_env, &sub->sub_refcheck);
 		sub->sub_env = NULL;
 	}
-	EXIT;
 }
 
 static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio,
@@ -149,7 +147,6 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
 	LASSERT(sub->sub_io == NULL);
 	LASSERT(sub->sub_env == NULL);
 	LASSERT(sub->sub_stripe < lio->lis_stripe_count);
-	ENTRY;
 
 	result = 0;
 	sub->sub_io_initialized = 0;
@@ -210,7 +207,7 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
 	}
 	if (result != 0)
 		lov_io_sub_fini(env, lio, sub);
-	RETURN(result);
+	return result;
 }
 
 struct lov_io_sub *lov_sub_get(const struct lu_env *env,
@@ -220,7 +217,6 @@ struct lov_io_sub *lov_sub_get(const struct lu_env *env,
 	struct lov_io_sub *sub = &lio->lis_subs[stripe];
 
 	LASSERT(stripe < lio->lis_stripe_count);
-	ENTRY;
 
 	if (!sub->sub_io_initialized) {
 		sub->sub_stripe = stripe;
@@ -231,7 +227,7 @@ struct lov_io_sub *lov_sub_get(const struct lu_env *env,
 		lov_sub_enter(sub);
 	else
 		sub = ERR_PTR(rc);
-	RETURN(sub);
+	return sub;
 }
 
 void lov_sub_put(struct lov_io_sub *sub)
@@ -249,12 +245,11 @@ static int lov_page_stripe(const struct cl_page *page)
 {
 	struct lovsub_object *subobj;
 
-	ENTRY;
 	subobj = lu2lovsub(
 		lu_object_locate(page->cp_child->cp_obj->co_lu.lo_header,
 				 &lovsub_device_type));
 	LASSERT(subobj != NULL);
-	RETURN(subobj->lso_index);
+	return subobj->lso_index;
 }
 
 struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio,
@@ -268,10 +263,9 @@ struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio,
 	LASSERT(cl2lov(slice->cpl_obj) == lio->lis_object);
 	LASSERT(lsm != NULL);
 	LASSERT(lio->lis_nr_subios > 0);
-	ENTRY;
 
 	stripe = lov_page_stripe(page);
-	RETURN(lov_sub_get(env, lio, stripe));
+	return lov_sub_get(env, lio, stripe);
 }
 
 
@@ -282,7 +276,6 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio,
 	int result;
 
 	LASSERT(lio->lis_object != NULL);
-	ENTRY;
 
 	/*
 	 * Need to be optimized, we can't afford to allocate a piece of memory
@@ -297,14 +290,12 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio,
 		result = 0;
 	} else
 		result = -ENOMEM;
-	RETURN(result);
+	return result;
 }
 
 static void lov_io_slice_init(struct lov_io *lio,
 			      struct lov_object *obj, struct cl_io *io)
 {
-	ENTRY;
-
 	io->ci_result = 0;
 	lio->lis_object = obj;
 
@@ -353,8 +344,6 @@ static void lov_io_slice_init(struct lov_io *lio,
 	default:
 		LBUG();
 	}
-
-	EXIT;
 }
 
 static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios)
@@ -363,7 +352,6 @@ static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios)
 	struct lov_object *lov = cl2lov(ios->cis_obj);
 	int i;
 
-	ENTRY;
 	if (lio->lis_subs != NULL) {
 		for (i = 0; i < lio->lis_nr_subios; i++)
 			lov_io_sub_fini(env, lio, &lio->lis_subs[i]);
@@ -375,7 +363,6 @@ static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios)
 	LASSERT(atomic_read(&lov->lo_active_ios) > 0);
 	if (atomic_dec_and_test(&lov->lo_active_ios))
 		wake_up_all(&lov->lo_waitq);
-	EXIT;
 }
 
 static obd_off lov_offset_mod(obd_off val, int delta)
@@ -397,7 +384,6 @@ static int lov_io_iter_init(const struct lu_env *env,
 	int stripe;
 	int rc = 0;
 
-	ENTRY;
 	endpos = lov_offset_mod(lio->lis_endpos, -1);
 	for (stripe = 0; stripe < lio->lis_stripe_count; stripe++) {
 		if (!lov_stripe_intersects(lsm, stripe, lio->lis_pos,
@@ -421,7 +407,7 @@ static int lov_io_iter_init(const struct lu_env *env,
 		else
 			break;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_io_rw_iter_init(const struct lu_env *env,
@@ -430,12 +416,11 @@ static int lov_io_rw_iter_init(const struct lu_env *env,
 	struct lov_io	*lio = cl2lov_io(env, ios);
 	struct cl_io	 *io  = ios->cis_io;
 	struct lov_stripe_md *lsm = lio->lis_object->lo_lsm;
-	loff_t start = io->u.ci_rw.crw_pos;
+	__u64 start = io->u.ci_rw.crw_pos;
 	loff_t next;
 	unsigned long ssize = lsm->lsm_stripe_size;
 
 	LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
-	ENTRY;
 
 	/* fast path for common case. */
 	if (lio->lis_nr_subios != 1 && !cl_io_is_append(io)) {
@@ -458,7 +443,7 @@ static int lov_io_rw_iter_init(const struct lu_env *env,
 	 * XXX The following call should be optimized: we know, that
 	 * [lio->lis_pos, lio->lis_endpos) intersects with exactly one stripe.
 	 */
-	RETURN(lov_io_iter_init(env, ios));
+	return lov_io_iter_init(env, ios);
 }
 
 static int lov_io_call(const struct lu_env *env, struct lov_io *lio,
@@ -468,7 +453,6 @@ static int lov_io_call(const struct lu_env *env, struct lov_io *lio,
 	struct lov_io_sub *sub;
 	int rc = 0;
 
-	ENTRY;
 	list_for_each_entry(sub, &lio->lis_active, sub_linkage) {
 		lov_sub_enter(sub);
 		rc = iofunc(sub->sub_env, sub->sub_io);
@@ -479,24 +463,21 @@ static int lov_io_call(const struct lu_env *env, struct lov_io *lio,
 		if (parent->ci_result == 0)
 			parent->ci_result = sub->sub_io->ci_result;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_io_lock(const struct lu_env *env, const struct cl_io_slice *ios)
 {
-	ENTRY;
-	RETURN(lov_io_call(env, cl2lov_io(env, ios), cl_io_lock));
+	return lov_io_call(env, cl2lov_io(env, ios), cl_io_lock);
 }
 
 static int lov_io_start(const struct lu_env *env, const struct cl_io_slice *ios)
 {
-	ENTRY;
-	RETURN(lov_io_call(env, cl2lov_io(env, ios), cl_io_start));
+	return lov_io_call(env, cl2lov_io(env, ios), cl_io_start);
 }
 
 static int lov_io_end_wrapper(const struct lu_env *env, struct cl_io *io)
 {
-	ENTRY;
 	/*
 	 * It's possible that lov_io_start() wasn't called against this
 	 * sub-io, either because previous sub-io failed, or upper layer
@@ -506,19 +487,19 @@ static int lov_io_end_wrapper(const struct lu_env *env, struct cl_io *io)
 		cl_io_end(env, io);
 	else
 		io->ci_state = CIS_IO_FINISHED;
-	RETURN(0);
+	return 0;
 }
 
 static int lov_io_iter_fini_wrapper(const struct lu_env *env, struct cl_io *io)
 {
 	cl_io_iter_fini(env, io);
-	RETURN(0);
+	return 0;
 }
 
 static int lov_io_unlock_wrapper(const struct lu_env *env, struct cl_io *io)
 {
 	cl_io_unlock(env, io);
-	RETURN(0);
+	return 0;
 }
 
 static void lov_io_end(const struct lu_env *env, const struct cl_io_slice *ios)
@@ -535,12 +516,10 @@ static void lov_io_iter_fini(const struct lu_env *env,
 	struct lov_io *lio = cl2lov_io(env, ios);
 	int rc;
 
-	ENTRY;
 	rc = lov_io_call(env, lio, lov_io_iter_fini_wrapper);
 	LASSERT(rc == 0);
 	while (!list_empty(&lio->lis_active))
 		list_del_init(lio->lis_active.next);
-	EXIT;
 }
 
 static void lov_io_unlock(const struct lu_env *env,
@@ -548,10 +527,8 @@ static void lov_io_unlock(const struct lu_env *env,
 {
 	int rc;
 
-	ENTRY;
 	rc = lov_io_call(env, cl2lov_io(env, ios), lov_io_unlock_wrapper);
 	LASSERT(rc == 0);
-	EXIT;
 }
 
 
@@ -596,7 +573,7 @@ static int lov_io_submit(const struct lu_env *env,
 	int rc = 0;
 	int alloc =
 		!(current->flags & PF_MEMALLOC);
-	ENTRY;
+
 	if (lio->lis_active_subios == 1) {
 		int idx = lio->lis_single_subio_index;
 		struct lov_io_sub *sub;
@@ -608,7 +585,7 @@ static int lov_io_submit(const struct lu_env *env,
 		rc = cl_io_submit_rw(sub->sub_env, sub->sub_io,
 				     crt, queue);
 		lov_sub_put(sub);
-		RETURN(rc);
+		return rc;
 	}
 
 	LASSERT(lio->lis_subs != NULL);
@@ -616,7 +593,7 @@ static int lov_io_submit(const struct lu_env *env,
 		OBD_ALLOC_LARGE(stripes_qin,
 				sizeof(*stripes_qin) * lio->lis_nr_subios);
 		if (stripes_qin == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		for (stripe = 0; stripe < lio->lis_nr_subios; stripe++)
 			cl_page_list_init(&stripes_qin[stripe]);
@@ -682,7 +659,7 @@ static int lov_io_submit(const struct lu_env *env,
 		mutex_unlock(&ld->ld_mutex);
 	}
 
-	RETURN(rc);
+	return rc;
 #undef QIN
 }
 
@@ -696,7 +673,6 @@ static int lov_io_prepare_write(const struct lu_env *env,
 	struct lov_io_sub *sub;
 	int result;
 
-	ENTRY;
 	sub = lov_page_subio(env, lio, slice);
 	if (!IS_ERR(sub)) {
 		result = cl_io_prepare_write(sub->sub_env, sub->sub_io,
@@ -704,7 +680,7 @@ static int lov_io_prepare_write(const struct lu_env *env,
 		lov_sub_put(sub);
 	} else
 		result = PTR_ERR(sub);
-	RETURN(result);
+	return result;
 }
 
 static int lov_io_commit_write(const struct lu_env *env,
@@ -717,7 +693,6 @@ static int lov_io_commit_write(const struct lu_env *env,
 	struct lov_io_sub *sub;
 	int result;
 
-	ENTRY;
 	sub = lov_page_subio(env, lio, slice);
 	if (!IS_ERR(sub)) {
 		result = cl_io_commit_write(sub->sub_env, sub->sub_io,
@@ -725,7 +700,7 @@ static int lov_io_commit_write(const struct lu_env *env,
 		lov_sub_put(sub);
 	} else
 		result = PTR_ERR(sub);
-	RETURN(result);
+	return result;
 }
 
 static int lov_io_fault_start(const struct lu_env *env,
@@ -735,13 +710,12 @@ static int lov_io_fault_start(const struct lu_env *env,
 	struct lov_io      *lio;
 	struct lov_io_sub  *sub;
 
-	ENTRY;
 	fio = &ios->cis_io->u.ci_fault;
 	lio = cl2lov_io(env, ios);
 	sub = lov_sub_get(env, lio, lov_page_stripe(fio->ft_page));
 	sub->sub_io->u.ci_fault.ft_nob = fio->ft_nob;
 	lov_sub_put(sub);
-	RETURN(lov_io_start(env, ios));
+	return lov_io_start(env, ios);
 }
 
 static void lov_io_fsync_end(const struct lu_env *env,
@@ -750,7 +724,6 @@ static void lov_io_fsync_end(const struct lu_env *env,
 	struct lov_io *lio = cl2lov_io(env, ios);
 	struct lov_io_sub *sub;
 	unsigned int *written = &ios->cis_io->u.ci_fsync.fi_nr_written;
-	ENTRY;
 
 	*written = 0;
 	list_for_each_entry(sub, &lio->lis_active, sub_linkage) {
@@ -763,7 +736,6 @@ static void lov_io_fsync_end(const struct lu_env *env,
 		if (subio->ci_result == 0)
 			*written += subio->u.ci_fsync.fi_nr_written;
 	}
-	RETURN_EXIT;
 }
 
 static const struct cl_io_operations lov_io_ops = {
@@ -839,11 +811,9 @@ static void lov_empty_io_fini(const struct lu_env *env,
 			      const struct cl_io_slice *ios)
 {
 	struct lov_object *lov = cl2lov(ios->cis_obj);
-	ENTRY;
 
 	if (atomic_dec_and_test(&lov->lo_active_ios))
 		wake_up_all(&lov->lo_waitq);
-	EXIT;
 }
 
 static void lov_empty_impossible(const struct lu_env *env,
@@ -913,7 +883,6 @@ int lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj,
 	struct lov_io       *lio = lov_env_io(env);
 	struct lov_object   *lov = cl2lov(obj);
 
-	ENTRY;
 	INIT_LIST_HEAD(&lio->lis_active);
 	lov_io_slice_init(lio, lov, io);
 	if (io->ci_result == 0) {
@@ -923,7 +892,7 @@ int lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj,
 			atomic_inc(&lov->lo_active_ios);
 		}
 	}
-	RETURN(io->ci_result);
+	return io->ci_result;
 }
 
 int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
@@ -932,7 +901,6 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
 	struct lov_object *lov = cl2lov(obj);
 	struct lov_io *lio = lov_env_io(env);
 	int result;
-	ENTRY;
 
 	lio->lis_object = lov;
 	switch (io->ci_type) {
@@ -961,7 +929,40 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
 	}
 
 	io->ci_result = result < 0 ? result : 0;
-	RETURN(result != 0);
+	return result != 0;
 }
 
+int lov_io_init_released(const struct lu_env *env, struct cl_object *obj,
+			struct cl_io *io)
+{
+	struct lov_object *lov = cl2lov(obj);
+	struct lov_io *lio = lov_env_io(env);
+	int result;
+
+	LASSERT(lov->lo_lsm != NULL);
+	lio->lis_object = lov;
+
+	switch (io->ci_type) {
+	default:
+		LASSERTF(0, "invalid type %d\n", io->ci_type);
+	case CIT_MISC:
+	case CIT_FSYNC:
+		result = +1;
+		break;
+	case CIT_SETATTR:
+	case CIT_READ:
+	case CIT_WRITE:
+	case CIT_FAULT:
+		/* TODO: need to restore the file. */
+		result = -EBADF;
+		break;
+	}
+	if (result == 0) {
+		cl_io_slice_add(io, &lio->lis_cl, obj, &lov_empty_io_ops);
+		atomic_inc(&lov->lo_active_ios);
+	}
+
+	io->ci_result = result < 0 ? result : 0;
+	return result != 0;
+}
 /** @} lov */
diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c
index bdf3334..ec297e8 100644
--- a/drivers/staging/lustre/lustre/lov/lov_lock.c
+++ b/drivers/staging/lustre/lustre/lov/lov_lock.c
@@ -110,7 +110,6 @@ static void lov_sublock_adopt(const struct lu_env *env, struct lov_lock *lck,
 
 	LASSERT(cl_lock_is_mutexed(parent));
 	LASSERT(cl_lock_is_mutexed(sublock));
-	ENTRY;
 
 	lsl = cl2sub_lock(sublock);
 	/*
@@ -132,7 +131,6 @@ static void lov_sublock_adopt(const struct lu_env *env, struct lov_lock *lck,
 
 	rc = lov_sublock_modify(env, lck, lsl, &sublock->cll_descr, idx);
 	LASSERT(rc == 0); /* there is no way this can fail, currently */
-	EXIT;
 }
 
 static struct cl_lock *lov_sublock_alloc(const struct lu_env *env,
@@ -145,7 +143,6 @@ static struct cl_lock *lov_sublock_alloc(const struct lu_env *env,
 	struct lov_lock_link *link;
 
 	LASSERT(idx < lck->lls_nr);
-	ENTRY;
 
 	OBD_SLAB_ALLOC_PTR_GFP(link, lov_lock_link_kmem, __GFP_IO);
 	if (link != NULL) {
@@ -179,7 +176,7 @@ static struct cl_lock *lov_sublock_alloc(const struct lu_env *env,
 			OBD_SLAB_FREE_PTR(link, lov_lock_link_kmem);
 	} else
 		sublock = ERR_PTR(-ENOMEM);
-	RETURN(sublock);
+	return sublock;
 }
 
 static void lov_sublock_unlock(const struct lu_env *env,
@@ -187,11 +184,9 @@ static void lov_sublock_unlock(const struct lu_env *env,
 			       struct cl_lock_closure *closure,
 			       struct lov_sublock_env *subenv)
 {
-	ENTRY;
 	lov_sublock_env_put(subenv);
 	lsl->lss_active = NULL;
 	cl_lock_disclosure(env, closure);
-	EXIT;
 }
 
 static int lov_sublock_lock(const struct lu_env *env,
@@ -203,7 +198,6 @@ static int lov_sublock_lock(const struct lu_env *env,
 	struct lovsub_lock *sublock;
 	struct cl_lock     *child;
 	int		 result = 0;
-	ENTRY;
 
 	LASSERT(list_empty(&closure->clc_list));
 
@@ -243,7 +237,7 @@ static int lov_sublock_lock(const struct lu_env *env,
 			}
 		}
 	}
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -267,8 +261,6 @@ static int lov_subresult(int result, int rc)
 	int result_rank;
 	int rc_rank;
 
-	ENTRY;
-
 	LASSERTF(result <= 0 || result == CLO_REPEAT || result == CLO_WAIT,
 		 "result = %d", result);
 	LASSERTF(rc <= 0 || rc == CLO_REPEAT || rc == CLO_WAIT,
@@ -281,7 +273,7 @@ static int lov_subresult(int result, int rc)
 
 	if (result_rank < rc_rank)
 		result = rc;
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -307,8 +299,6 @@ static int lov_lock_sub_init(const struct lu_env *env,
 	struct lov_layout_raid0 *r0     = lov_r0(loo);
 	struct cl_lock	  *parent = lck->lls_cl.cls_lock;
 
-	ENTRY;
-
 	lck->lls_orig = parent->cll_descr;
 	file_start = cl_offset(lov2cl(loo), parent->cll_descr.cld_start);
 	file_end   = cl_offset(lov2cl(loo), parent->cll_descr.cld_end + 1) - 1;
@@ -325,7 +315,7 @@ static int lov_lock_sub_init(const struct lu_env *env,
 	LASSERT(nr > 0);
 	OBD_ALLOC_LARGE(lck->lls_sub, nr * sizeof lck->lls_sub[0]);
 	if (lck->lls_sub == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	lck->lls_nr = nr;
 	/*
@@ -396,7 +386,7 @@ static int lov_lock_sub_init(const struct lu_env *env,
 	 * because enqueue will create them anyway. Main duty of this function
 	 * is to fill in sub-lock descriptions in a race free manner.
 	 */
-	RETURN(result);
+	return result;
 }
 
 static int lov_sublock_release(const struct lu_env *env, struct lov_lock *lck,
@@ -405,7 +395,6 @@ static int lov_sublock_release(const struct lu_env *env, struct lov_lock *lck,
 	struct cl_lock *parent = lck->lls_cl.cls_lock;
 
 	LASSERT(cl_lock_is_mutexed(parent));
-	ENTRY;
 
 	if (lck->lls_sub[i].sub_flags & LSF_HELD) {
 		struct cl_lock    *sublock;
@@ -442,7 +431,7 @@ static int lov_sublock_release(const struct lu_env *env, struct lov_lock *lck,
 		 * sub-lock is destroyed.
 		 */
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static void lov_sublock_hold(const struct lu_env *env, struct lov_lock *lck,
@@ -451,7 +440,6 @@ static void lov_sublock_hold(const struct lu_env *env, struct lov_lock *lck,
 	struct cl_lock *parent = lck->lls_cl.cls_lock;
 
 	LASSERT(cl_lock_is_mutexed(parent));
-	ENTRY;
 
 	if (!(lck->lls_sub[i].sub_flags & LSF_HELD)) {
 		struct cl_lock *sublock;
@@ -468,7 +456,6 @@ static void lov_sublock_hold(const struct lu_env *env, struct lov_lock *lck,
 		cl_lock_user_add(env, sublock);
 		cl_lock_put(env, sublock);
 	}
-	EXIT;
 }
 
 static void lov_lock_fini(const struct lu_env *env,
@@ -477,7 +464,6 @@ static void lov_lock_fini(const struct lu_env *env,
 	struct lov_lock *lck;
 	int i;
 
-	ENTRY;
 	lck = cl2lov_lock(slice);
 	LASSERT(lck->lls_nr_filled == 0);
 	if (lck->lls_sub != NULL) {
@@ -491,7 +477,6 @@ static void lov_lock_fini(const struct lu_env *env,
 			       lck->lls_nr * sizeof lck->lls_sub[0]);
 	}
 	OBD_SLAB_FREE_PTR(lck, lov_lock_kmem);
-	EXIT;
 }
 
 static int lov_lock_enqueue_wait(const struct lu_env *env,
@@ -500,14 +485,13 @@ static int lov_lock_enqueue_wait(const struct lu_env *env,
 {
 	struct cl_lock *lock = lck->lls_cl.cls_lock;
 	int	     result;
-	ENTRY;
 
 	LASSERT(cl_lock_is_mutexed(lock));
 
 	cl_lock_mutex_put(env, lock);
 	result = cl_lock_enqueue_wait(env, sublock, 0);
 	cl_lock_mutex_get(env, lock);
-	RETURN(result ?: CLO_REPEAT);
+	return result ?: CLO_REPEAT;
 }
 
 /**
@@ -522,7 +506,6 @@ static int lov_lock_enqueue_one(const struct lu_env *env, struct lov_lock *lck,
 				struct cl_io *io, __u32 enqflags, int last)
 {
 	int result;
-	ENTRY;
 
 	/* first, try to enqueue a sub-lock ... */
 	result = cl_enqueue_try(env, sublock, io, enqflags);
@@ -541,7 +524,7 @@ static int lov_lock_enqueue_one(const struct lu_env *env, struct lov_lock *lck,
 	if ((result == CLO_WAIT) && (sublock->cll_state <= CLS_HELD) &&
 	    (enqflags & CEF_ASYNC) && (!last || (enqflags & CEF_AGL)))
 		result = 0;
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -600,8 +583,6 @@ static int lov_lock_enqueue(const struct lu_env *env,
 	int result;
 	enum cl_lock_state minstate;
 
-	ENTRY;
-
 	for (result = 0, minstate = CLS_FREEING, i = 0; i < lck->lls_nr; ++i) {
 		int rc;
 		struct lovsub_lock     *sub;
@@ -680,7 +661,7 @@ static int lov_lock_enqueue(const struct lu_env *env,
 			break;
 	}
 	cl_lock_closure_fini(closure);
-	RETURN(result ?: minstate >= CLS_ENQUEUED ? 0 : CLO_WAIT);
+	return result ?: minstate >= CLS_ENQUEUED ? 0 : CLO_WAIT;
 }
 
 static int lov_lock_unuse(const struct lu_env *env,
@@ -691,8 +672,6 @@ static int lov_lock_unuse(const struct lu_env *env,
 	int i;
 	int result;
 
-	ENTRY;
-
 	for (result = 0, i = 0; i < lck->lls_nr; ++i) {
 		int rc;
 		struct lovsub_lock     *sub;
@@ -728,7 +707,7 @@ static int lov_lock_unuse(const struct lu_env *env,
 		result = -ESTALE;
 	}
 	cl_lock_closure_fini(closure);
-	RETURN(result);
+	return result;
 }
 
 
@@ -740,8 +719,6 @@ static void lov_lock_cancel(const struct lu_env *env,
 	int i;
 	int result;
 
-	ENTRY;
-
 	for (result = 0, i = 0; i < lck->lls_nr; ++i) {
 		int rc;
 		struct lovsub_lock     *sub;
@@ -802,8 +779,6 @@ static int lov_lock_wait(const struct lu_env *env,
 	int		     result;
 	int		     i;
 
-	ENTRY;
-
 again:
 	for (result = 0, minstate = CLS_FREEING, i = 0, reenqueued = 0;
 	     i < lck->lls_nr; ++i) {
@@ -839,7 +814,7 @@ again:
 	if (result == 0 && reenqueued != 0)
 		goto again;
 	cl_lock_closure_fini(closure);
-	RETURN(result ?: minstate >= CLS_HELD ? 0 : CLO_WAIT);
+	return result ?: minstate >= CLS_HELD ? 0 : CLO_WAIT;
 }
 
 static int lov_lock_use(const struct lu_env *env,
@@ -851,7 +826,6 @@ static int lov_lock_use(const struct lu_env *env,
 	int		     i;
 
 	LASSERT(slice->cls_lock->cll_state == CLS_INTRANSIT);
-	ENTRY;
 
 	for (result = 0, i = 0; i < lck->lls_nr; ++i) {
 		int rc;
@@ -908,7 +882,7 @@ static int lov_lock_use(const struct lu_env *env,
 		result = -ESTALE;
 	}
 	cl_lock_closure_fini(closure);
-	RETURN(result);
+	return result;
 }
 
 #if 0
@@ -1016,8 +990,6 @@ static int lov_lock_fits_into(const struct lu_env *env,
 	LASSERT(cl_object_same(need->cld_obj, slice->cls_obj));
 	LASSERT(lov->lls_nr > 0);
 
-	ENTRY;
-
 	/* for top lock, it's necessary to match enq flags otherwise it will
 	 * run into problem if a sublock is missing and reenqueue. */
 	if (need->cld_enq_flags != lov->lls_orig.cld_enq_flags)
@@ -1055,7 +1027,7 @@ static int lov_lock_fits_into(const struct lu_env *env,
 	       PDESCR(&lov->lls_orig), PDESCR(&lov->lls_sub[0].sub_got),
 	       lov->lls_sub[0].sub_stripe, lov->lls_nr, lov_r0(obj)->lo_nr,
 	       result);
-	RETURN(result);
+	return result;
 }
 
 void lov_lock_unlink(const struct lu_env *env,
@@ -1066,7 +1038,6 @@ void lov_lock_unlink(const struct lu_env *env,
 
 	LASSERT(cl_lock_is_mutexed(parent));
 	LASSERT(cl_lock_is_mutexed(sub->lss_cl.cls_lock));
-	ENTRY;
 
 	list_del_init(&link->lll_list);
 	LASSERT(lck->lls_sub[link->lll_idx].sub_lock == sub);
@@ -1077,7 +1048,6 @@ void lov_lock_unlink(const struct lu_env *env,
 	lu_ref_del(&parent->cll_reference, "lov-child", sub->lss_cl.cls_lock);
 	cl_lock_put(env, parent);
 	OBD_SLAB_FREE_PTR(link, lov_lock_link_kmem);
-	EXIT;
 }
 
 struct lov_lock_link *lov_lock_link_find(const struct lu_env *env,
@@ -1087,13 +1057,12 @@ struct lov_lock_link *lov_lock_link_find(const struct lu_env *env,
 	struct lov_lock_link *scan;
 
 	LASSERT(cl_lock_is_mutexed(sub->lss_cl.cls_lock));
-	ENTRY;
 
 	list_for_each_entry(scan, &sub->lss_parents, lll_list) {
 		if (scan->lll_super == lck)
-			RETURN(scan);
+			return scan;
 	}
-	RETURN(NULL);
+	return NULL;
 }
 
 /**
@@ -1120,7 +1089,6 @@ static void lov_lock_delete(const struct lu_env *env,
 	int		     i;
 
 	LASSERT(slice->cls_lock->cll_state == CLS_FREEING);
-	ENTRY;
 
 	for (i = 0; i < lck->lls_nr; ++i) {
 		struct lov_lock_sub *lls = &lck->lls_sub[i];
@@ -1150,7 +1118,6 @@ static void lov_lock_delete(const struct lu_env *env,
 	}
 
 	cl_lock_closure_fini(closure);
-	EXIT;
 }
 
 static int lov_lock_print(const struct lu_env *env, void *cookie,
@@ -1192,14 +1159,13 @@ int lov_lock_init_raid0(const struct lu_env *env, struct cl_object *obj,
 	struct lov_lock *lck;
 	int result;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(lck, lov_lock_kmem, __GFP_IO);
 	if (lck != NULL) {
 		cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_lock_ops);
 		result = lov_lock_sub_init(env, lck, io);
 	} else
 		result = -ENOMEM;
-	RETURN(result);
+	return result;
 }
 
 static void lov_empty_lock_fini(const struct lu_env *env,
@@ -1228,14 +1194,13 @@ int lov_lock_init_empty(const struct lu_env *env, struct cl_object *obj,
 	struct lov_lock *lck;
 	int result = -ENOMEM;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(lck, lov_lock_kmem, __GFP_IO);
 	if (lck != NULL) {
 		cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_empty_lock_ops);
 		lck->lls_orig = lock->cll_descr;
 		result = 0;
 	}
-	RETURN(result);
+	return result;
 }
 
 static struct cl_lock_closure *lov_closure_get(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/lov/lov_log.c b/drivers/staging/lustre/lustre/lov/lov_log.c
index 63b7f8d..3eedd93 100644
--- a/drivers/staging/lustre/lustre/lov/lov_log.c
+++ b/drivers/staging/lustre/lustre/lov/lov_log.c
@@ -71,7 +71,6 @@ static int lov_llog_origin_add(const struct lu_env *env,
 	struct obd_device *obd = ctxt->loc_obd;
 	struct lov_obd *lov = &obd->u.lov;
 	int i, rc = 0, cookies = 0;
-	ENTRY;
 
 	LASSERTF(logcookies && numcookies >= lsm->lsm_stripe_count,
 		 "logcookies %p, numcookies %d lsm->lsm_stripe_count %d \n",
@@ -118,7 +117,7 @@ static int lov_llog_origin_add(const struct lu_env *env,
 		/* Note that rc is always 1 if llog_obd_add was successful */
 		cookies += rc;
 	}
-	RETURN(cookies);
+	return cookies;
 }
 
 static int lov_llog_origin_connect(struct llog_ctxt *ctxt,
@@ -129,7 +128,6 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt,
 	struct obd_device *obd = ctxt->loc_obd;
 	struct lov_obd *lov = &obd->u.lov;
 	int i, rc = 0, err = 0;
-	ENTRY;
 
 	obd_getref(obd);
 	for (i = 0; i < lov->desc.ld_tgt_count; i++) {
@@ -154,7 +152,7 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt,
 	}
 	obd_putref(obd);
 
-	RETURN(err);
+	return err;
 }
 
 /* the replicators commit callback */
@@ -167,7 +165,6 @@ static int lov_llog_repl_cancel(const struct lu_env *env,
 	struct lov_obd *lov;
 	struct obd_device *obd = ctxt->loc_obd;
 	int rc = 0, i;
-	ENTRY;
 
 	LASSERT(lsm != NULL);
 	LASSERT(count == lsm->lsm_stripe_count);
@@ -194,7 +191,7 @@ static int lov_llog_repl_cancel(const struct lu_env *env,
 		}
 	}
 	obd_putref(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static struct llog_operations lov_mds_ost_orig_logops = {
@@ -212,13 +209,12 @@ int lov_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
 	struct lov_obd *lov = &obd->u.lov;
 	struct obd_device *child;
 	int i, rc = 0;
-	ENTRY;
 
 	LASSERT(olg == &obd->obd_olg);
 	rc = llog_setup(NULL, obd, olg, LLOG_MDS_OST_ORIG_CTXT, disk_obd,
 			&lov_mds_ost_orig_logops);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = llog_setup(NULL, obd, olg, LLOG_SIZE_REPL_CTXT, disk_obd,
 			&lov_size_repl_logops);
@@ -261,8 +257,6 @@ int lov_llog_finish(struct obd_device *obd, int count)
 {
 	struct llog_ctxt *ctxt;
 
-	ENTRY;
-
 	/* cleanup our llogs only if the ctxts have been setup
 	 * (client lov doesn't setup, mds lov does). */
 	ctxt = llog_get_context(obd, LLOG_MDS_OST_ORIG_CTXT);
@@ -274,5 +268,5 @@ int lov_llog_finish(struct obd_device *obd, int count)
 		llog_cleanup(NULL, ctxt);
 
 	/* lov->tgt llogs are cleaned during osc_cleanup. */
-	RETURN(0);
+	return 0;
 }
diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c
index ddbac12..d204fed 100644
--- a/drivers/staging/lustre/lustre/lov/lov_merge.c
+++ b/drivers/staging/lustre/lustre/lov/lov_merge.c
@@ -109,7 +109,7 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm,
 	lvb->lvb_mtime = current_mtime;
 	lvb->lvb_atime = current_atime;
 	lvb->lvb_ctime = current_ctime;
-	RETURN(rc);
+	return rc;
 }
 
 /** Merge the lock value block(&lvb) attributes from each of the stripes in a
@@ -127,7 +127,6 @@ int lov_merge_lvb(struct obd_export *exp,
 	int   rc;
 	__u64 kms;
 
-	ENTRY;
 	lov_stripe_lock(lsm);
 	rc = lov_merge_lvb_kms(lsm, lvb, &kms);
 	lov_stripe_unlock(lsm);
@@ -137,7 +136,7 @@ int lov_merge_lvb(struct obd_export *exp,
 	CDEBUG(D_INODE, "merged for ID "DOSTID" s="LPU64" m="LPU64" a="LPU64
 	       " c="LPU64" b="LPU64"\n", POSTID(&lsm->lsm_oi), lvb->lvb_size,
 	       lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
-	RETURN(rc);
+	return rc;
 }
 
 /* Must be called under the lov_stripe_lock() */
@@ -147,7 +146,6 @@ int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm,
 	struct lov_oinfo *loi;
 	int stripe = 0;
 	__u64 kms;
-	ENTRY;
 
 	LASSERT(spin_is_locked(&lsm->lsm_lock));
 	LASSERT(lsm->lsm_lock_owner == current_pid());
@@ -162,7 +160,7 @@ int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm,
 			       loi->loi_kms, kms);
 			loi_kms_set(loi, loi->loi_lvb.lvb_size = kms);
 		}
-		RETURN(0);
+		return 0;
 	}
 
 	if (size > 0)
@@ -175,7 +173,7 @@ int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm,
 	if (kms > loi->loi_kms)
 		loi_kms_set(loi, kms);
 
-	RETURN(0);
+	return 0;
 }
 
 void lov_merge_attrs(struct obdo *tgt, struct obdo *src, obd_valid valid,
diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c
index ef7ff09..0b47aba 100644
--- a/drivers/staging/lustre/lustre/lov/lov_obd.c
+++ b/drivers/staging/lustre/lustre/lov/lov_obd.c
@@ -131,19 +131,18 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 	struct obd_device *tgt_obd;
 	static struct obd_uuid lov_osc_uuid = { "LOV_OSC_UUID" };
 	struct obd_import *imp;
-	proc_dir_entry_t *lov_proc_dir;
+	struct proc_dir_entry *lov_proc_dir;
 	int rc;
-	ENTRY;
 
 	if (!lov->lov_tgts[index])
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	tgt_uuid = &lov->lov_tgts[index]->ltd_uuid;
 	tgt_obd = lov->lov_tgts[index]->ltd_obd;
 
 	if (!tgt_obd->obd_set_up) {
 		CERROR("Target %s not set up\n", obd_uuid2str(tgt_uuid));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* override the sp_me from lov */
@@ -168,14 +167,14 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 	if (rc) {
 		CERROR("Target %s register_observer error %d\n",
 		       obd_uuid2str(tgt_uuid), rc);
-		RETURN(rc);
+		return rc;
 	}
 
 
 	if (imp->imp_invalid) {
 		CDEBUG(D_CONFIG, "not connecting OSC %s; administratively "
 		       "disabled\n", obd_uuid2str(tgt_uuid));
-		RETURN(0);
+		return 0;
 	}
 
 	rc = obd_connect(NULL, &lov->lov_tgts[index]->ltd_exp, tgt_obd,
@@ -183,7 +182,7 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 	if (rc || !lov->lov_tgts[index]->ltd_exp) {
 		CERROR("Target %s connect error %d\n",
 		       obd_uuid2str(tgt_uuid), rc);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	lov->lov_tgts[index]->ltd_reap = 0;
@@ -194,7 +193,7 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 	lov_proc_dir = obd->obd_proc_private;
 	if (lov_proc_dir) {
 		struct obd_device *osc_obd = lov->lov_tgts[index]->ltd_exp->exp_obd;
-		proc_dir_entry_t *osc_symlink;
+		struct proc_dir_entry *osc_symlink;
 
 		LASSERT(osc_obd != NULL);
 		LASSERT(osc_obd->obd_magic == OBD_DEVICE_MAGIC);
@@ -215,7 +214,7 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 		}
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static int lov_connect(const struct lu_env *env,
@@ -227,13 +226,12 @@ static int lov_connect(const struct lu_env *env,
 	struct lov_tgt_desc *tgt;
 	struct lustre_handle conn;
 	int i, rc;
-	ENTRY;
 
 	CDEBUG(D_CONFIG, "connect #%d\n", lov->lov_connects);
 
 	rc = class_connect(&conn, obd, cluuid);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	*exp = class_conn2export(&conn);
 
@@ -270,16 +268,15 @@ static int lov_connect(const struct lu_env *env,
 	}
 	obd_putref(obd);
 
-	RETURN(0);
+	return 0;
 }
 
 static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt)
 {
-	proc_dir_entry_t *lov_proc_dir;
+	struct proc_dir_entry *lov_proc_dir;
 	struct lov_obd *lov = &obd->u.lov;
 	struct obd_device *osc_obd;
 	int rc;
-	ENTRY;
 
 	osc_obd = class_exp2obd(tgt->ltd_exp);
 	CDEBUG(D_CONFIG, "%s: disconnecting target %s\n",
@@ -315,7 +312,7 @@ static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt)
 	}
 
 	tgt->ltd_exp = NULL;
-	RETURN(0);
+	return 0;
 }
 
 static int lov_disconnect(struct obd_export *exp)
@@ -323,7 +320,6 @@ static int lov_disconnect(struct obd_export *exp)
 	struct obd_device *obd = class_exp2obd(exp);
 	struct lov_obd *lov = &obd->u.lov;
 	int i, rc;
-	ENTRY;
 
 	if (!lov->lov_tgts)
 		goto out;
@@ -350,7 +346,7 @@ static int lov_disconnect(struct obd_export *exp)
 
 out:
 	rc = class_disconnect(exp); /* bz 9811 */
-	RETURN(rc);
+	return rc;
 }
 
 /* Error codes:
@@ -366,7 +362,6 @@ static int lov_set_osc_active(struct obd_device *obd, struct obd_uuid *uuid,
 	struct lov_obd *lov = &obd->u.lov;
 	struct lov_tgt_desc *tgt;
 	int index, activate, active;
-	ENTRY;
 
 	CDEBUG(D_INFO, "Searching in lov %p for uuid %s event(%d)\n",
 	       lov, uuid->uuid, ev);
@@ -438,7 +433,7 @@ static int lov_set_osc_active(struct obd_device *obd, struct obd_uuid *uuid,
 
  out:
 	obd_putref(obd);
-	RETURN(index);
+	return index;
 }
 
 static int lov_notify(struct obd_device *obd, struct obd_device *watched,
@@ -446,12 +441,11 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
 {
 	int rc = 0;
 	struct lov_obd *lov = &obd->u.lov;
-	ENTRY;
 
 	down_read(&lov->lov_notify_lock);
 	if (!lov->lov_connects) {
 		up_read(&lov->lov_notify_lock);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (ev == OBD_NOTIFY_ACTIVE || ev == OBD_NOTIFY_INACTIVE ||
@@ -465,7 +459,7 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
 			CERROR("unexpected notification of %s %s!\n",
 			       watched->obd_type->typ_name,
 			       watched->obd_name);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		uuid = &watched->u.cli.cl_target_uuid;
 
@@ -477,7 +471,7 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
 			up_read(&lov->lov_notify_lock);
 			CERROR("event(%d) of %s failed: %d\n", ev,
 			       obd_uuid2str(uuid), rc);
-			RETURN(rc);
+			return rc;
 		}
 		/* active event should be pass lov target index as data */
 		data = &rc;
@@ -520,7 +514,7 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched,
 	}
 
 	up_read(&lov->lov_notify_lock);
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
@@ -530,7 +524,6 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 	struct lov_tgt_desc *tgt;
 	struct obd_device *tgt_obd;
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_CONFIG, "uuid:%s idx:%d gen:%d active:%d\n",
 	       uuidp->uuid, index, gen, active);
@@ -538,13 +531,13 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 	if (gen <= 0) {
 		CERROR("request to add OBD %s with invalid generation: %d\n",
 		       uuidp->uuid, gen);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	tgt_obd = class_find_client_obd(uuidp, LUSTRE_OSC_NAME,
 					&obd->obd_uuid);
 	if (tgt_obd == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	mutex_lock(&lov->lov_lock);
 
@@ -553,7 +546,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 		CERROR("UUID %s already assigned at LOV target index %d\n",
 		       obd_uuid2str(&tgt->ltd_uuid), index);
 		mutex_unlock(&lov->lov_lock);
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 
 	if (index >= lov->lov_tgt_size) {
@@ -567,7 +560,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 		OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize);
 		if (newtgts == NULL) {
 			mutex_unlock(&lov->lov_lock);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 
 		if (lov->lov_tgt_size) {
@@ -590,14 +583,14 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 	OBD_ALLOC_PTR(tgt);
 	if (!tgt) {
 		mutex_unlock(&lov->lov_lock);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	rc = lov_ost_pool_add(&lov->lov_packed, index, lov->lov_tgt_size);
 	if (rc) {
 		mutex_unlock(&lov->lov_lock);
 		OBD_FREE_PTR(tgt);
-		RETURN(rc);
+		return rc;
 	}
 
 	tgt->ltd_uuid = *uuidp;
@@ -621,7 +614,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 		/* lov_connect hasn't been called yet. We'll do the
 		   lov_connect_obd on this target when that fn first runs,
 		   because we don't know the connect flags yet. */
-		RETURN(0);
+		return 0;
 	}
 
 	obd_getref(obd);
@@ -654,7 +647,7 @@ out:
 		lov_del_target(obd, index, 0, 0);
 	}
 	obd_putref(obd);
-	RETURN(rc);
+	return rc;
 }
 
 /* Schedule a target for deletion */
@@ -664,12 +657,11 @@ int lov_del_target(struct obd_device *obd, __u32 index,
 	struct lov_obd *lov = &obd->u.lov;
 	int count = lov->desc.ld_tgt_count;
 	int rc = 0;
-	ENTRY;
 
 	if (index >= count) {
 		CERROR("LOV target index %d >= number of LOV OBDs %d.\n",
 		       index, count);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* to make sure there's no ongoing lov_notify() now */
@@ -700,7 +692,7 @@ out:
 	obd_putref(obd);
 	up_write(&lov->lov_notify_lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 static void __lov_del_obd(struct obd_device *obd, struct lov_tgt_desc *tgt)
@@ -780,11 +772,10 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	struct lov_desc *desc;
 	struct lov_obd *lov = &obd->u.lov;
 	int rc;
-	ENTRY;
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
 		CERROR("LOV setup requires a descriptor\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	desc = (struct lov_desc *)lustre_cfg_buf(lcfg, 1);
@@ -792,7 +783,7 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	if (sizeof(*desc) > LUSTRE_CFG_BUFLEN(lcfg, 1)) {
 		CERROR("descriptor size wrong: %d > %d\n",
 		       (int)sizeof(*desc), LUSTRE_CFG_BUFLEN(lcfg, 1));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (desc->ld_magic != LOV_DESC_MAGIC) {
@@ -803,7 +794,7 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 		} else {
 			CERROR("%s: Bad lov desc magic: %#x\n",
 			       obd->obd_name, desc->ld_magic);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
@@ -836,11 +827,11 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	lprocfs_obd_setup(obd, lvars.obd_vars);
 #ifdef LPROCFS
 	{
-		int rc;
+		int rc1;
 
-		rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
+		rc1 = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
 					0444, &lov_proc_target_fops, obd);
-		if (rc)
+		if (rc1)
 			CWARN("Error adding the target_obd file\n");
 	}
 #endif
@@ -848,7 +839,7 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 						    obd->obd_proc_entry,
 						    NULL, NULL);
 
-	RETURN(0);
+	return 0;
 
 out:
 	return rc;
@@ -859,8 +850,6 @@ static int lov_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 	int rc = 0;
 	struct lov_obd *lov = &obd->u.lov;
 
-	ENTRY;
-
 	switch (stage) {
 	case OBD_CLEANUP_EARLY: {
 		int i;
@@ -878,7 +867,7 @@ static int lov_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 			CERROR("failed to cleanup llogging subsystems\n");
 		break;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_cleanup(struct obd_device *obd)
@@ -886,7 +875,6 @@ static int lov_cleanup(struct obd_device *obd)
 	struct lov_obd *lov = &obd->u.lov;
 	struct list_head *pos, *tmp;
 	struct pool_desc *pool;
-	ENTRY;
 
 	list_for_each_safe(pos, tmp, &lov->lov_pool_list) {
 		pool = list_entry(pos, struct pool_desc, pool_list);
@@ -925,7 +913,7 @@ static int lov_cleanup(struct obd_device *obd)
 			 lov->lov_tgt_size);
 		lov->lov_tgt_size = 0;
 	}
-	RETURN(0);
+	return 0;
 }
 
 int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg,
@@ -934,7 +922,6 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg,
 	struct obd_uuid obd_uuid;
 	int cmd;
 	int rc = 0;
-	ENTRY;
 
 	switch(cmd = lcfg->lcfg_command) {
 	case LCFG_LOV_ADD_OBD:
@@ -990,7 +977,7 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg,
 	}
 	}
 out:
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
@@ -1000,14 +987,13 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	unsigned ost_idx;
 	int rc, i;
-	ENTRY;
 
 	LASSERT(src_oa->o_valid & OBD_MD_FLFLAGS &&
 		src_oa->o_flags & OBD_FL_RECREATE_OBJS);
 
 	OBD_ALLOC(obj_mdp, sizeof(*obj_mdp));
 	if (obj_mdp == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	ost_idx = src_oa->o_nlink;
 	lsm = *ea;
@@ -1032,7 +1018,7 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
 			src_oa, &obj_mdp, oti);
 out:
 	OBD_FREE(obj_mdp, sizeof(*obj_mdp));
-	RETURN(rc);
+	return rc;
 }
 
 /* the LOV expects oa->o_id to be set to the LOV object id */
@@ -1042,11 +1028,10 @@ static int lov_create(const struct lu_env *env, struct obd_export *exp,
 {
 	struct lov_obd *lov;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(ea != NULL);
 	if (exp == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if ((src_oa->o_valid & OBD_MD_FLFLAGS) &&
 	    src_oa->o_flags == OBD_FL_DELORPHAN) {
@@ -1056,7 +1041,7 @@ static int lov_create(const struct lu_env *env, struct obd_export *exp,
 
 	lov = &exp->exp_obd->u.lov;
 	if (!lov->desc.ld_active_tgt_count)
-		RETURN(-EIO);
+		return -EIO;
 
 	obd_getref(exp->exp_obd);
 	/* Recreate a specific object id at the given OST index */
@@ -1066,7 +1051,7 @@ static int lov_create(const struct lu_env *env, struct obd_export *exp,
 	}
 
 	obd_putref(exp->exp_obd);
-	RETURN(rc);
+	return rc;
 }
 
 #define ASSERT_LSM_MAGIC(lsmp)						  \
@@ -1088,12 +1073,11 @@ static int lov_destroy(const struct lu_env *env, struct obd_export *exp,
 	struct list_head *pos;
 	struct lov_obd *lov;
 	int rc = 0, err = 0;
-	ENTRY;
 
 	ASSERT_LSM_MAGIC(lsm);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	if (oa->o_valid & OBD_MD_FLCOOKIE) {
 		LASSERT(oti);
@@ -1133,7 +1117,7 @@ static int lov_destroy(const struct lu_env *env, struct obd_export *exp,
 	err = lov_fini_destroy_set(set);
 out:
 	obd_putref(exp->exp_obd);
-	RETURN(rc ? rc : err);
+	return rc ? rc : err;
 }
 
 static int lov_getattr(const struct lu_env *env, struct obd_export *exp,
@@ -1144,19 +1128,18 @@ static int lov_getattr(const struct lu_env *env, struct obd_export *exp,
 	struct list_head *pos;
 	struct lov_obd *lov;
 	int err = 0, rc = 0;
-	ENTRY;
 
 	LASSERT(oinfo);
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 
 	rc = lov_prep_getattr_set(exp, oinfo, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each (pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1182,7 +1165,7 @@ static int lov_getattr(const struct lu_env *env, struct obd_export *exp,
 	rc = lov_fini_getattr_set(set);
 	if (err)
 		rc = err;
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_getattr_interpret(struct ptlrpc_request_set *rqset,
@@ -1190,13 +1173,12 @@ static int lov_getattr_interpret(struct ptlrpc_request_set *rqset,
 {
 	struct lov_request_set *lovset = (struct lov_request_set *)data;
 	int err;
-	ENTRY;
 
 	/* don't do attribute merge if this aysnc op failed */
 	if (rc)
 		atomic_set(&lovset->set_completes, 0);
 	err = lov_fini_getattr_set(lovset);
-	RETURN(rc ? rc : err);
+	return rc ? rc : err;
 }
 
 static int lov_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
@@ -1207,19 +1189,18 @@ static int lov_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
 	struct list_head *pos;
 	struct lov_request *req;
 	int rc = 0, err;
-	ENTRY;
 
 	LASSERT(oinfo);
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 
 	rc = lov_prep_getattr_set(exp, oinfo, &lovset);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INFO, "objid "DOSTID": %ux%u byte stripes\n",
 	       POSTID(&oinfo->oi_md->lsm_oi), oinfo->oi_md->lsm_stripe_count,
@@ -1249,13 +1230,13 @@ static int lov_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
 		LASSERT (rqset->set_interpret == NULL);
 		rqset->set_interpret = lov_getattr_interpret;
 		rqset->set_arg = (void *)lovset;
-		RETURN(rc);
+		return rc;
 	}
 out:
 	if (rc)
 		atomic_set(&lovset->set_completes, 0);
 	err = lov_fini_getattr_set(lovset);
-	RETURN(rc ? rc : err);
+	return rc ? rc : err;
 }
 
 static int lov_setattr(const struct lu_env *env, struct obd_export *exp,
@@ -1266,13 +1247,12 @@ static int lov_setattr(const struct lu_env *env, struct obd_export *exp,
 	struct list_head *pos;
 	struct lov_request *req;
 	int err = 0, rc = 0;
-	ENTRY;
 
 	LASSERT(oinfo);
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	/* for now, we only expect the following updates here */
 	LASSERT(!(oinfo->oi_oa->o_valid & ~(OBD_MD_FLID | OBD_MD_FLTYPE |
@@ -1285,7 +1265,7 @@ static int lov_setattr(const struct lu_env *env, struct obd_export *exp,
 	lov = &exp->exp_obd->u.lov;
 	rc = lov_prep_setattr_set(exp, oinfo, oti, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each (pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1307,7 +1287,7 @@ static int lov_setattr(const struct lu_env *env, struct obd_export *exp,
 	err = lov_fini_setattr_set(set);
 	if (!rc)
 		rc = err;
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_setattr_interpret(struct ptlrpc_request_set *rqset,
@@ -1315,12 +1295,11 @@ static int lov_setattr_interpret(struct ptlrpc_request_set *rqset,
 {
 	struct lov_request_set *lovset = (struct lov_request_set *)data;
 	int err;
-	ENTRY;
 
 	if (rc)
 		atomic_set(&lovset->set_completes, 0);
 	err = lov_fini_setattr_set(lovset);
-	RETURN(rc ? rc : err);
+	return rc ? rc : err;
 }
 
 /* If @oti is given, the request goes from MDS and responses from OSTs are not
@@ -1334,7 +1313,6 @@ static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
 	struct list_head *pos;
 	struct lov_obd *lov;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(oinfo);
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
@@ -1344,12 +1322,12 @@ static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
 	}
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	rc = lov_prep_setattr_set(exp, oinfo, oti, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INFO, "objid "DOSTID": %ux%u byte stripes\n",
 	       POSTID(&oinfo->oi_md->lsm_oi),
@@ -1384,14 +1362,14 @@ static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
 		if (rc)
 			atomic_set(&set->set_completes, 0);
 		err = lov_fini_setattr_set(set);
-		RETURN(rc ? rc : err);
+		return rc ? rc : err;
 	}
 
 	LASSERT(rqset->set_interpret == NULL);
 	rqset->set_interpret = lov_setattr_interpret;
 	rqset->set_arg = (void *)set;
 
-	RETURN(0);
+	return 0;
 }
 
 static int lov_punch_interpret(struct ptlrpc_request_set *rqset,
@@ -1399,12 +1377,11 @@ static int lov_punch_interpret(struct ptlrpc_request_set *rqset,
 {
 	struct lov_request_set *lovset = (struct lov_request_set *)data;
 	int err;
-	ENTRY;
 
 	if (rc)
 		atomic_set(&lovset->set_completes, 0);
 	err = lov_fini_punch_set(lovset);
-	RETURN(rc ? rc : err);
+	return rc ? rc : err;
 }
 
 /* FIXME: maybe we'll just make one node the authoritative attribute node, then
@@ -1419,18 +1396,17 @@ static int lov_punch(const struct lu_env *env, struct obd_export *exp,
 	struct list_head *pos;
 	struct lov_request *req;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(oinfo);
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	rc = lov_prep_punch_set(exp, oinfo, oti, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each (pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1450,14 +1426,14 @@ static int lov_punch(const struct lu_env *env, struct obd_export *exp,
 	if (rc || list_empty(&rqset->set_requests)) {
 		int err;
 		err = lov_fini_punch_set(set);
-		RETURN(rc ? rc : err);
+		return rc ? rc : err;
 	}
 
 	LASSERT(rqset->set_interpret == NULL);
 	rqset->set_interpret = lov_punch_interpret;
 	rqset->set_arg = (void *)set;
 
-	RETURN(0);
+	return 0;
 }
 
 static int lov_sync_interpret(struct ptlrpc_request_set *rqset,
@@ -1465,12 +1441,11 @@ static int lov_sync_interpret(struct ptlrpc_request_set *rqset,
 {
 	struct lov_request_set *lovset = data;
 	int err;
-	ENTRY;
 
 	if (rc)
 		atomic_set(&lovset->set_completes, 0);
 	err = lov_fini_sync_set(lovset);
-	RETURN(rc ?: err);
+	return rc ?: err;
 }
 
 static int lov_sync(const struct lu_env *env, struct obd_export *exp,
@@ -1482,18 +1457,17 @@ static int lov_sync(const struct lu_env *env, struct obd_export *exp,
 	struct list_head *pos;
 	struct lov_request *req;
 	int rc = 0;
-	ENTRY;
 
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
 	LASSERT(rqset != NULL);
 
 	if (!exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	rc = lov_prep_sync_set(exp, oinfo, start, end, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_INFO, "fsync objid "DOSTID" ["LPX64", "LPX64"]\n",
 	       POSTID(&set->set_oi->oi_oa->o_oi), start, end);
@@ -1519,14 +1493,14 @@ static int lov_sync(const struct lu_env *env, struct obd_export *exp,
 	if (rc || list_empty(&rqset->set_requests)) {
 		int err = lov_fini_sync_set(set);
 
-		RETURN(rc ?: err);
+		return rc ?: err;
 	}
 
 	LASSERT(rqset->set_interpret == NULL);
 	rqset->set_interpret = lov_sync_interpret;
 	rqset->set_arg = (void *)set;
 
-	RETURN(0);
+	return 0;
 }
 
 static int lov_brw_check(struct lov_obd *lov, struct obd_info *lov_oinfo,
@@ -1571,18 +1545,17 @@ static int lov_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
 	struct list_head *pos;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int err, rc = 0;
-	ENTRY;
 
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
 
 	if (cmd == OBD_BRW_CHECK) {
 		rc = lov_brw_check(lov, oinfo, oa_bufs, pga);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = lov_prep_brw_set(exp, oinfo, oa_bufs, pga, oti, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each (pos, &set->set_list) {
 		struct obd_export *sub_exp;
@@ -1601,16 +1574,16 @@ static int lov_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
 	err = lov_fini_brw_set(set);
 	if (!rc)
 		rc = err;
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_enqueue_interpret(struct ptlrpc_request_set *rqset,
 				 void *data, int rc)
 {
 	struct lov_request_set *lovset = (struct lov_request_set *)data;
-	ENTRY;
+
 	rc = lov_fini_enqueue_set(lovset, lovset->set_ei->ei_mode, rc, rqset);
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_enqueue(struct obd_export *exp, struct obd_info *oinfo,
@@ -1623,7 +1596,6 @@ static int lov_enqueue(struct obd_export *exp, struct obd_info *oinfo,
 	struct list_head *pos;
 	struct lov_obd *lov;
 	ldlm_error_t rc;
-	ENTRY;
 
 	LASSERT(oinfo);
 	ASSERT_LSM_MAGIC(oinfo->oi_md);
@@ -1633,12 +1605,12 @@ static int lov_enqueue(struct obd_export *exp, struct obd_info *oinfo,
 	LASSERT((oinfo->oi_flags & LDLM_FL_REPLAY) == 0);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	rc = lov_prep_enqueue_set(exp, oinfo, einfo, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each (pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1654,11 +1626,11 @@ static int lov_enqueue(struct obd_export *exp, struct obd_info *oinfo,
 		LASSERT(rqset->set_interpret == NULL);
 		rqset->set_interpret = lov_enqueue_interpret;
 		rqset->set_arg = (void *)set;
-		RETURN(rc);
+		return rc;
 	}
 out:
 	rc = lov_fini_enqueue_set(set, mode, rc, rqset);
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_change_cbdata(struct obd_export *exp,
@@ -1667,12 +1639,11 @@ static int lov_change_cbdata(struct obd_export *exp,
 {
 	struct lov_obd *lov;
 	int rc = 0, i;
-	ENTRY;
 
 	ASSERT_LSM_MAGIC(lsm);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	for (i = 0; i < lsm->lsm_stripe_count; i++) {
@@ -1689,7 +1660,7 @@ static int lov_change_cbdata(struct obd_export *exp,
 		rc = obd_change_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
 				       &submd, it, data);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /* find any ldlm lock of the inode in lov
@@ -1702,12 +1673,11 @@ static int lov_find_cbdata(struct obd_export *exp,
 {
 	struct lov_obd *lov;
 	int rc = 0, i;
-	ENTRY;
 
 	ASSERT_LSM_MAGIC(lsm);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	for (i = 0; i < lsm->lsm_stripe_count; i++) {
@@ -1723,9 +1693,9 @@ static int lov_find_cbdata(struct obd_export *exp,
 		rc = obd_find_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
 				     &submd, it, data);
 		if (rc != 0)
-			RETURN(rc);
+			return rc;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm,
@@ -1738,18 +1708,17 @@ static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm,
 	struct lov_obd *lov;
 	struct lustre_handle *lov_lockhp;
 	int err = 0, rc = 0;
-	ENTRY;
 
 	ASSERT_LSM_MAGIC(lsm);
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	LASSERT(lockh);
 	lov = &exp->exp_obd->u.lov;
 	rc = lov_prep_cancel_set(exp, &oinfo, lsm, mode, lockh, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1769,7 +1738,7 @@ static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm,
 
 	}
 	lov_fini_cancel_set(set);
-	RETURN(err);
+	return err;
 }
 
 static int lov_cancel_unused(struct obd_export *exp,
@@ -1778,10 +1747,9 @@ static int lov_cancel_unused(struct obd_export *exp,
 {
 	struct lov_obd *lov;
 	int rc = 0, i;
-	ENTRY;
 
 	if (!exp || !exp->exp_obd)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	lov = &exp->exp_obd->u.lov;
 	if (lsm == NULL) {
@@ -1795,7 +1763,7 @@ static int lov_cancel_unused(struct obd_export *exp,
 			if (!rc)
 				rc = err;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	ASSERT_LSM_MAGIC(lsm);
@@ -1827,20 +1795,19 @@ static int lov_cancel_unused(struct obd_export *exp,
 				rc = err;
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc)
 {
 	struct lov_request_set *lovset = (struct lov_request_set *)data;
 	int err;
-	ENTRY;
 
 	if (rc)
 		atomic_set(&lovset->set_completes, 0);
 
 	err = lov_fini_statfs_set(lovset);
-	RETURN(rc ? rc : err);
+	return rc ? rc : err;
 }
 
 static int lov_statfs_async(struct obd_export *exp, struct obd_info *oinfo,
@@ -1852,7 +1819,6 @@ static int lov_statfs_async(struct obd_export *exp, struct obd_info *oinfo,
 	struct list_head *pos;
 	struct lov_obd *lov;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(oinfo != NULL);
 	LASSERT(oinfo->oi_osfs != NULL);
@@ -1860,7 +1826,7 @@ static int lov_statfs_async(struct obd_export *exp, struct obd_info *oinfo,
 	lov = &obd->u.lov;
 	rc = lov_prep_statfs_set(obd, oinfo, &set);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each (pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1875,13 +1841,13 @@ static int lov_statfs_async(struct obd_export *exp, struct obd_info *oinfo,
 		if (rc)
 			atomic_set(&set->set_completes, 0);
 		err = lov_fini_statfs_set(set);
-		RETURN(rc ? rc : err);
+		return rc ? rc : err;
 	}
 
 	LASSERT(rqset->set_interpret == NULL);
 	rqset->set_interpret = lov_statfs_interpret;
 	rqset->set_arg = (void *)set;
-	RETURN(0);
+	return 0;
 }
 
 static int lov_statfs(const struct lu_env *env, struct obd_export *exp,
@@ -1890,14 +1856,12 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp,
 	struct ptlrpc_request_set *set = NULL;
 	struct obd_info oinfo = { { { 0 } } };
 	int rc = 0;
-	ENTRY;
-
 
 	/* for obdclass we forbid using obd_statfs_rqset, but prefer using async
 	 * statfs requests */
 	set = ptlrpc_prep_set();
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	oinfo.oi_osfs = osfs;
 	oinfo.oi_flags = flags;
@@ -1906,7 +1870,7 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp,
 		rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
@@ -1916,7 +1880,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 	struct lov_obd *lov = &obddev->u.lov;
 	int i = 0, rc = 0, count = lov->desc.ld_tgt_count;
 	struct obd_uuid *uuidp;
-	ENTRY;
 
 	switch (cmd) {
 	case IOC_OBD_STATFS: {
@@ -1928,23 +1891,23 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
 		memcpy(&index, data->ioc_inlbuf2, sizeof(__u32));
 		if ((index >= count))
-			RETURN(-ENODEV);
+			return -ENODEV;
 
 		if (!lov->lov_tgts[index])
 			/* Try again with the next index */
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 		if (!lov->lov_tgts[index]->ltd_active)
-			RETURN(-ENODATA);
+			return -ENODATA;
 
 		osc_obd = class_exp2obd(lov->lov_tgts[index]->ltd_exp);
 		if (!osc_obd)
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		/* copy UUID */
 		if (copy_to_user(data->ioc_pbuf2, obd2cli_tgt(osc_obd),
 				     min((int) data->ioc_plen2,
 					 (int) sizeof(struct obd_uuid))))
-			RETURN(-EFAULT);
+			return -EFAULT;
 
 		flags = uarg ? *(__u32*)uarg : 0;
 		/* got statfs data */
@@ -1952,11 +1915,11 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 				cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 				flags);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		if (copy_to_user(data->ioc_pbuf1, &stat_buf,
 				     min((int) data->ioc_plen1,
 					 (int) sizeof(stat_buf))))
-			RETURN(-EFAULT);
+			return -EFAULT;
 		break;
 	}
 	case OBD_IOC_LOV_GET_CONFIG: {
@@ -1967,23 +1930,23 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
 		len = 0;
 		if (obd_ioctl_getdata(&buf, &len, (void *)uarg))
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		data = (struct obd_ioctl_data *)buf;
 
 		if (sizeof(*desc) > data->ioc_inllen1) {
 			obd_ioctl_freedata(buf, len);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (sizeof(uuidp->uuid) * count > data->ioc_inllen2) {
 			obd_ioctl_freedata(buf, len);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (sizeof(__u32) * count > data->ioc_inllen3) {
 			obd_ioctl_freedata(buf, len);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		desc = (struct lov_desc *)data->ioc_inlbuf1;
@@ -2020,11 +1983,11 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
 		if (qctl->qc_valid == QC_OSTIDX) {
 			if (qctl->qc_idx < 0 || count <= qctl->qc_idx)
-				RETURN(-EINVAL);
+				return -EINVAL;
 
 			tgt = lov->lov_tgts[qctl->qc_idx];
 			if (!tgt || !tgt->ltd_exp)
-				RETURN(-EINVAL);
+				return -EINVAL;
 		} else if (qctl->qc_valid == QC_UUID) {
 			for (i = 0; i < count; i++) {
 				tgt = lov->lov_tgts[i];
@@ -2034,21 +1997,21 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 					continue;
 
 				if (tgt->ltd_exp == NULL)
-					RETURN(-EINVAL);
+					return -EINVAL;
 
 				break;
 			}
 		} else {
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (i >= count)
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 
 		LASSERT(tgt && tgt->ltd_exp);
 		OBD_ALLOC_PTR(oqctl);
 		if (!oqctl)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		QCTL_COPY(oqctl, qctl);
 		rc = obd_quotactl(tgt->ltd_exp, oqctl);
@@ -2064,7 +2027,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		int set = 0;
 
 		if (count == 0)
-			RETURN(-ENOTTY);
+			return -ENOTTY;
 
 		for (i = 0; i < count; i++) {
 			int err;
@@ -2081,7 +2044,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 			err = obd_iocontrol(cmd, lov->lov_tgts[i]->ltd_exp,
 					    len, karg, uarg);
 			if (err == -ENODATA && cmd == OBD_IOC_POLL_QUOTACHECK) {
-				RETURN(err);
+				return err;
 			} else if (err) {
 				if (lov->lov_tgts[i]->ltd_active) {
 					CDEBUG(err == -ENOTTY ?
@@ -2102,7 +2065,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 	}
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 #define FIEMAP_BUFFER_SIZE 4096
@@ -2259,7 +2222,7 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key,
 	int cur_stripe = 0, cur_stripe_wrap = 0, stripe_count;
 	unsigned int buffer_size = FIEMAP_BUFFER_SIZE;
 
-	if (lsm == NULL)
+	if (!lsm_has_objects(lsm))
 		GOTO(out, rc = 0);
 
 	if (fiemap_count_to_size(fm_key->fiemap.fm_extent_count) < buffer_size)
@@ -2469,10 +2432,9 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp,
 	struct obd_device *obddev = class_exp2obd(exp);
 	struct lov_obd *lov = &obddev->u.lov;
 	int i, rc;
-	ENTRY;
 
 	if (!vallen || !val)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	obd_getref(obddev);
 
@@ -2553,7 +2515,7 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp,
 
 out:
 	obd_putref(obddev);
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp,
@@ -2568,14 +2530,13 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp,
 	unsigned incr, check_uuid,
 		 do_inactive, no_set;
 	unsigned next_id = 0,  mds_con = 0, capa = 0;
-	ENTRY;
 
 	incr = check_uuid = do_inactive = no_set = 0;
 	if (set == NULL) {
 		no_set = 1;
 		set = ptlrpc_prep_set();
 		if (!set)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 	}
 
 	obd_getref(obddev);
@@ -2667,7 +2628,7 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp,
 			rc = err;
 		ptlrpc_set_destroy(set);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_extent_calc(struct obd_export *exp, struct lov_stripe_md *lsm,
@@ -2691,7 +2652,7 @@ static int lov_extent_calc(struct obd_export *exp, struct lov_stripe_md *lsm,
 		LBUG();
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 void lov_stripe_lock(struct lov_stripe_md *md)
@@ -2719,7 +2680,6 @@ static int lov_quotactl(struct obd_device *obd, struct obd_export *exp,
 	__u64		curspace = 0;
 	__u64		bhardlimit = 0;
 	int		  i, rc = 0;
-	ENTRY;
 
 	if (oqctl->qc_cmd != LUSTRE_Q_QUOTAON &&
 	    oqctl->qc_cmd != LUSTRE_Q_QUOTAOFF &&
@@ -2728,7 +2688,7 @@ static int lov_quotactl(struct obd_device *obd, struct obd_export *exp,
 	    oqctl->qc_cmd != LUSTRE_Q_SETQUOTA &&
 	    oqctl->qc_cmd != Q_FINVALIDATE) {
 		CERROR("bad quota opc %x for lov obd", oqctl->qc_cmd);
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 
 	/* for lov tgt */
@@ -2770,7 +2730,7 @@ static int lov_quotactl(struct obd_device *obd, struct obd_export *exp,
 		oqctl->qc_dqblk.dqb_curspace = curspace;
 		oqctl->qc_dqblk.dqb_bhardlimit = bhardlimit;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_quotacheck(struct obd_device *obd, struct obd_export *exp,
@@ -2778,7 +2738,6 @@ static int lov_quotacheck(struct obd_device *obd, struct obd_export *exp,
 {
 	struct lov_obd *lov = &obd->u.lov;
 	int	     i, rc = 0;
-	ENTRY;
 
 	obd_getref(obd);
 
@@ -2814,7 +2773,7 @@ static int lov_quotacheck(struct obd_device *obd, struct obd_export *exp,
 out:
 	obd_putref(obd);
 
-	RETURN(rc);
+	return rc;
 }
 
 struct obd_ops lov_obd_ops = {
@@ -2870,7 +2829,6 @@ int __init lov_init(void)
 {
 	struct lprocfs_static_vars lvars = { 0 };
 	int rc;
-	ENTRY;
 
 	/* print an address of _any_ initialized kernel symbol from this
 	 * module, to allow debugging with gdb that doesn't support data
@@ -2898,7 +2856,7 @@ int __init lov_init(void)
 		lu_kmem_fini(lov_caches);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static void /*__exit*/ lov_exit(void)
@@ -2912,5 +2870,7 @@ static void /*__exit*/ lov_exit(void)
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(LUSTRE_VERSION_STRING);
 
-cfs_module(lov, LUSTRE_VERSION_STRING, lov_init, lov_exit);
+module_init(lov_init);
+module_exit(lov_exit);
diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c
index aa8ae80..84e55ce 100644
--- a/drivers/staging/lustre/lustre/lov/lov_object.c
+++ b/drivers/staging/lustre/lustre/lov/lov_object.c
@@ -116,10 +116,9 @@ static struct cl_object *lov_sub_find(const struct lu_env *env,
 {
 	struct lu_object *o;
 
-	ENTRY;
 	o = lu_object_find_at(env, cl2lu_dev(dev), fid, &conf->coc_lu);
 	LASSERT(ergo(!IS_ERR(o), o->lo_dev->ld_type == &lovsub_device_type));
-	RETURN(lu2cl(o));
+	return lu2cl(o);
 }
 
 static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
@@ -204,8 +203,6 @@ static int lov_init_raid0(const struct lu_env *env,
 	struct lu_fid	   *ofid    = &lti->lti_fid;
 	struct lov_layout_raid0 *r0      = &state->raid0;
 
-	ENTRY;
-
 	if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) {
 		dump_lsm(D_ERROR, lsm);
 		LASSERTF(0, "magic mismatch, expected %d/%d, actual %d.\n",
@@ -255,13 +252,28 @@ static int lov_init_raid0(const struct lu_env *env,
 	} else
 		result = -ENOMEM;
 out:
-	RETURN(result);
+	return result;
+}
+
+static int lov_init_released(const struct lu_env *env,
+			struct lov_device *dev, struct lov_object *lov,
+			const struct cl_object_conf *conf,
+			union  lov_layout_state *state)
+{
+	struct lov_stripe_md *lsm = conf->u.coc_md->lsm;
+
+	LASSERT(lsm != NULL);
+	LASSERT(lsm_is_released(lsm));
+	LASSERT(lov->lo_lsm == NULL);
+
+	lov->lo_lsm = lsm_addref(lsm);
+	return 0;
 }
 
 static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov,
 			    union lov_layout_state *state)
 {
-	LASSERT(lov->lo_type == LLT_EMPTY);
+	LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED);
 
 	lov_layout_wait(env, lov);
 
@@ -323,8 +335,6 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov,
 	struct lov_stripe_md    *lsm = lov->lo_lsm;
 	int i;
 
-	ENTRY;
-
 	dump_lsm(D_INODE, lsm);
 
 	lov_layout_wait(env, lov);
@@ -343,20 +353,19 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov,
 		}
 	}
 	cl_object_prune(env, &lov->lo_cl);
-	RETURN(0);
+	return 0;
 }
 
 static void lov_fini_empty(const struct lu_env *env, struct lov_object *lov,
 			   union lov_layout_state *state)
 {
-	LASSERT(lov->lo_type == LLT_EMPTY);
+	LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED);
 }
 
 static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov,
 			   union lov_layout_state *state)
 {
 	struct lov_layout_raid0 *r0 = &state->raid0;
-	ENTRY;
 
 	if (r0->lo_sub != NULL) {
 		OBD_FREE_LARGE(r0->lo_sub, r0->lo_nr * sizeof r0->lo_sub[0]);
@@ -365,8 +374,13 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov,
 
 	dump_lsm(D_INODE, lov->lo_lsm);
 	lov_free_memmd(&lov->lo_lsm);
+}
 
-	EXIT;
+static void lov_fini_released(const struct lu_env *env, struct lov_object *lov,
+				union lov_layout_state *state)
+{
+	dump_lsm(D_INODE, lov->lo_lsm);
+	lov_free_memmd(&lov->lo_lsm);
 }
 
 static int lov_print_empty(const struct lu_env *env, void *cookie,
@@ -400,6 +414,13 @@ static int lov_print_raid0(const struct lu_env *env, void *cookie,
 	return 0;
 }
 
+static int lov_print_released(const struct lu_env *env, void *cookie,
+				lu_printer_t p, const struct lu_object *o)
+{
+	(*p)(env, cookie, "released\n");
+	return 0;
+}
+
 /**
  * Implements cl_object_operations::coo_attr_get() method for an object
  * without stripes (LLT_EMPTY layout type).
@@ -422,8 +443,6 @@ static int lov_attr_get_raid0(const struct lu_env *env, struct cl_object *obj,
 	struct cl_attr		*lov_attr = &r0->lo_attr;
 	int			 result = 0;
 
-	ENTRY;
-
 	/* this is called w/o holding type guard mutex, so it must be inside
 	 * an on going IO otherwise lsm may be replaced.
 	 * LU-2117: it turns out there exists one exception. For mmaped files,
@@ -478,7 +497,7 @@ static int lov_attr_get_raid0(const struct lu_env *env, struct cl_object *obj,
 		if (attr->cat_mtime < lov_attr->cat_mtime)
 			attr->cat_mtime = lov_attr->cat_mtime;
 	}
-	RETURN(result);
+	return result;
 }
 
 const static struct lov_layout_operations lov_dispatch[] = {
@@ -503,10 +522,20 @@ const static struct lov_layout_operations lov_dispatch[] = {
 		.llo_lock_init = lov_lock_init_raid0,
 		.llo_io_init   = lov_io_init_raid0,
 		.llo_getattr   = lov_attr_get_raid0
+	},
+	[LLT_RELEASED] = {
+		.llo_init      = lov_init_released,
+		.llo_delete    = lov_delete_empty,
+		.llo_fini      = lov_fini_released,
+		.llo_install   = lov_install_empty,
+		.llo_print     = lov_print_released,
+		.llo_page_init = lov_page_init_empty,
+		.llo_lock_init = lov_lock_init_empty,
+		.llo_io_init   = lov_io_init_released,
+		.llo_getattr   = lov_attr_get_empty
 	}
 };
 
-
 /**
  * Performs a double-dispatch based on the layout type of an object.
  */
@@ -520,6 +549,18 @@ const static struct lov_layout_operations lov_dispatch[] = {
 	lov_dispatch[__llt].op(__VA_ARGS__);			    \
 })
 
+/**
+ * Return lov_layout_type associated with a given lsm
+ */
+enum lov_layout_type lov_type(struct lov_stripe_md *lsm)
+{
+	if (lsm == NULL)
+		return LLT_EMPTY;
+	if (lsm_is_released(lsm))
+		return LLT_RELEASED;
+	return LLT_RAID0;
+}
+
 static inline void lov_conf_freeze(struct lov_object *lov)
 {
 	if (lov->lo_owner != current)
@@ -581,7 +622,6 @@ static void lov_conf_unlock(struct lov_object *lov)
 static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov)
 {
 	struct l_wait_info lwi = { 0 };
-	ENTRY;
 
 	while (atomic_read(&lov->lo_active_ios) > 0) {
 		CDEBUG(D_INODE, "file:"DFID" wait for active IO, now: %d.\n",
@@ -591,7 +631,7 @@ static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov)
 		l_wait_event(lov->lo_waitq,
 			     atomic_read(&lov->lo_active_ios) == 0, &lwi);
 	}
-	RETURN(0);
+	return 0;
 }
 
 static int lov_layout_change(const struct lu_env *unused,
@@ -608,19 +648,18 @@ static int lov_layout_change(const struct lu_env *unused,
 	void *cookie;
 	struct lu_env *env;
 	int refcheck;
-	ENTRY;
 
 	LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch));
 
-	if (conf->u.coc_md != NULL && conf->u.coc_md->lsm != NULL)
-		llt = LLT_RAID0; /* only raid0 is supported. */
+	if (conf->u.coc_md != NULL)
+		llt = lov_type(conf->u.coc_md->lsm);
 	LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch));
 
 	cookie = cl_env_reenter();
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env)) {
 		cl_env_reexit(cookie);
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 	}
 
 	old_ops = &lov_dispatch[lov->lo_type];
@@ -650,7 +689,7 @@ static int lov_layout_change(const struct lu_env *unused,
 
 	cl_env_put(env, &refcheck);
 	cl_env_reexit(cookie);
-	RETURN(result);
+	return result;
 }
 
 /*****************************************************************************
@@ -658,7 +697,6 @@ static int lov_layout_change(const struct lu_env *unused,
  * Lov object operations.
  *
  */
-
 int lov_object_init(const struct lu_env *env, struct lu_object *obj,
 		    const struct lu_object_conf *conf)
 {
@@ -669,7 +707,6 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj,
 	const struct lov_layout_operations *ops;
 	int result;
 
-	ENTRY;
 	init_rwsem(&lov->lo_type_guard);
 	atomic_set(&lov->lo_active_ios, 0);
 	init_waitqueue_head(&lov->lo_waitq);
@@ -677,21 +714,20 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj,
 	cl_object_page_init(lu2cl(obj), sizeof(struct lov_page));
 
 	/* no locking is necessary, as object is being created */
-	lov->lo_type = cconf->u.coc_md->lsm != NULL ? LLT_RAID0 : LLT_EMPTY;
+	lov->lo_type = lov_type(cconf->u.coc_md->lsm);
 	ops = &lov_dispatch[lov->lo_type];
 	result = ops->llo_init(env, dev, lov, cconf, set);
 	if (result == 0)
 		ops->llo_install(env, lov, set);
-	RETURN(result);
+	return result;
 }
 
 static int lov_conf_set(const struct lu_env *env, struct cl_object *obj,
 			const struct cl_object_conf *conf)
 {
-	struct lov_stripe_md *lsm = NULL;
-	struct lov_object *lov = cl2lov(obj);
-	int result = 0;
-	ENTRY;
+	struct lov_stripe_md	*lsm = NULL;
+	struct lov_object	*lov = cl2lov(obj);
+	int			 result = 0;
 
 	lov_conf_lock(lov);
 	if (conf->coc_opc == OBJECT_CONF_INVALIDATE) {
@@ -728,31 +764,26 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj,
 	}
 
 	lov->lo_layout_invalid = lov_layout_change(env, lov, conf);
-	EXIT;
 
 out:
 	lov_conf_unlock(lov);
-	RETURN(result);
+	return result;
 }
 
 static void lov_object_delete(const struct lu_env *env, struct lu_object *obj)
 {
 	struct lov_object *lov = lu2lov(obj);
 
-	ENTRY;
 	LOV_2DISPATCH_VOID(lov, llo_delete, env, lov, &lov->u);
-	EXIT;
 }
 
 static void lov_object_free(const struct lu_env *env, struct lu_object *obj)
 {
 	struct lov_object *lov = lu2lov(obj);
 
-	ENTRY;
 	LOV_2DISPATCH_VOID(lov, llo_fini, env, lov, &lov->u);
 	lu_object_fini(obj);
 	OBD_SLAB_FREE_PTR(lov, lov_object_kmem);
-	EXIT;
 }
 
 static int lov_object_print(const struct lu_env *env, void *cookie,
@@ -835,7 +866,6 @@ struct lu_object *lov_object_alloc(const struct lu_env *env,
 	struct lov_object *lov;
 	struct lu_object  *obj;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(lov, lov_object_kmem, __GFP_IO);
 	if (lov != NULL) {
 		obj = lov2lu(lov);
@@ -850,7 +880,7 @@ struct lu_object *lov_object_alloc(const struct lu_env *env,
 		obj->lo_ops = &lov_lu_obj_ops;
 	} else
 		obj = NULL;
-	RETURN(obj);
+	return obj;
 }
 
 struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov)
@@ -906,7 +936,6 @@ int lov_read_and_clear_async_rc(struct cl_object *clob)
 {
 	struct lu_object *luobj;
 	int rc = 0;
-	ENTRY;
 
 	luobj = lu_object_locate(&cl_object_header(clob)->coh_lu,
 				 &lov_device_type);
@@ -928,6 +957,7 @@ int lov_read_and_clear_async_rc(struct cl_object *clob)
 				loi->loi_ar.ar_rc = 0;
 			}
 		}
+		case LLT_RELEASED:
 		case LLT_EMPTY:
 			break;
 		default:
@@ -935,7 +965,7 @@ int lov_read_and_clear_async_rc(struct cl_object *clob)
 		}
 		lov_conf_thaw(lov);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(lov_read_and_clear_async_rc);
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_offset.c b/drivers/staging/lustre/lustre/lov/lov_offset.c
index f62b7e5..04863a7 100644
--- a/drivers/staging/lustre/lustre/lov/lov_offset.c
+++ b/drivers/staging/lustre/lustre/lov/lov_offset.c
@@ -52,10 +52,9 @@ obd_size lov_stripe_size(struct lov_stripe_md *lsm, obd_size ost_size,
 	obd_off swidth;
 	obd_size lov_size;
 	int magic = lsm->lsm_magic;
-	ENTRY;
 
 	if (ost_size == 0)
-		RETURN(0);
+		return 0;
 
 	LASSERT(lsm_op_find(magic) != NULL);
 	lsm_op_find(magic)->lsm_stripe_by_index(lsm, &stripeno, NULL, &swidth);
@@ -67,7 +66,7 @@ obd_size lov_stripe_size(struct lov_stripe_md *lsm, obd_size ost_size,
 	else
 		lov_size = (ost_size - 1) * swidth + (stripeno + 1) * ssize;
 
-	RETURN(lov_size);
+	return lov_size;
 }
 
 /* we have an offset in file backed by an lov and want to find out where
diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c
index 492948a..55ec267 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pack.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pack.c
@@ -143,7 +143,6 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 	int lmm_size, lmm_magic;
 	int i;
 	int cplen = 0;
-	ENTRY;
 
 	if (lsm) {
 		lmm_magic = lsm->lsm_magic;
@@ -159,7 +158,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 	    (lmm_magic != LOV_MAGIC_V3)) {
 		CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n",
 			lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3);
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	}
 
@@ -168,10 +167,12 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 		 * to the actual number of OSTs in this filesystem. */
 		if (!lmmp) {
 			stripe_count = lov_get_stripecnt(lov, lmm_magic,
-							 lsm->lsm_stripe_count);
+							lsm->lsm_stripe_count);
 			lsm->lsm_stripe_count = stripe_count;
-		} else {
+		} else if (!lsm_is_released(lsm)) {
 			stripe_count = lsm->lsm_stripe_count;
+		} else {
+			stripe_count = 0;
 		}
 	} else {
 		/* No need to allocate more than maximum supported stripes.
@@ -188,20 +189,20 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 	lmm_size = lov_mds_md_size(stripe_count, lmm_magic);
 
 	if (!lmmp)
-		RETURN(lmm_size);
+		return lmm_size;
 
 	if (*lmmp && !lsm) {
 		stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count);
 		lmm_size = lov_mds_md_size(stripe_count, lmm_magic);
 		OBD_FREE_LARGE(*lmmp, lmm_size);
 		*lmmp = NULL;
-		RETURN(0);
+		return 0;
 	}
 
 	if (!*lmmp) {
 		OBD_ALLOC_LARGE(*lmmp, lmm_size);
 		if (!*lmmp)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 	}
 
 	CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d \n",
@@ -215,7 +216,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 		lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1);
 
 	if (!lsm)
-		RETURN(lmm_size);
+		return lmm_size;
 
 	/* lmmv1 and lmmv3 point to the same struct and have the
 	 * same first fields
@@ -229,7 +230,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 		cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name,
 				sizeof(lmmv3->lmm_pool_name));
 		if (cplen >= sizeof(lmmv3->lmm_pool_name))
-			RETURN(-E2BIG);
+			return -E2BIG;
 		lmm_objects = lmmv3->lmm_objects;
 	} else {
 		lmm_objects = lmmv1->lmm_objects;
@@ -246,7 +247,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 		lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx);
 	}
 
-	RETURN(lmm_size);
+	return lmm_size;
 }
 
 /* Find the max stripecount we should use */
@@ -307,14 +308,13 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count,
 		    int pattern, int magic)
 {
 	int i, lsm_size;
-	ENTRY;
 
 	CDEBUG(D_INFO, "alloc lsm, stripe_count %d\n", stripe_count);
 
 	*lsmp = lsm_alloc_plain(stripe_count, &lsm_size);
 	if (!*lsmp) {
 		CERROR("can't allocate lsmp stripe_count %d\n", stripe_count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	atomic_set(&(*lsmp)->lsm_refc, 1);
@@ -325,12 +325,13 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count,
 	(*lsmp)->lsm_pattern = pattern;
 	(*lsmp)->lsm_pool_name[0] = '\0';
 	(*lsmp)->lsm_layout_gen = 0;
-	(*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0;
+	if (stripe_count > 0)
+		(*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0;
 
 	for (i = 0; i < stripe_count; i++)
 		loi_init((*lsmp)->lsm_oinfo[i]);
 
-	RETURN(lsm_size);
+	return lsm_size;
 }
 
 int lov_free_memmd(struct lov_stripe_md **lsmp)
@@ -359,13 +360,13 @@ int lov_unpackmd(struct obd_export *exp,  struct lov_stripe_md **lsmp,
 	int rc = 0, lsm_size;
 	__u16 stripe_count;
 	__u32 magic;
-	ENTRY;
+	__u32 pattern;
 
 	/* If passed an MDS struct use values from there, otherwise defaults */
 	if (lmm) {
 		rc = lov_verify_lmm(lmm, lmm_bytes, &stripe_count);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		magic = le32_to_cpu(lmm->lmm_magic);
 	} else {
 		magic = LOV_MAGIC;
@@ -376,31 +377,31 @@ int lov_unpackmd(struct obd_export *exp,  struct lov_stripe_md **lsmp,
 	if (!lsmp) {
 		/* XXX LOV STACKING call into osc for sizes */
 		LBUG();
-		RETURN(lov_stripe_md_size(stripe_count));
+		return lov_stripe_md_size(stripe_count);
 	}
 	/* If we are passed an allocated struct but nothing to unpack, free */
 	if (*lsmp && !lmm) {
 		lov_free_memmd(lsmp);
-		RETURN(0);
+		return 0;
 	}
 
-	lsm_size = lov_alloc_memmd(lsmp, stripe_count, LOV_PATTERN_RAID0,
-				   magic);
+	pattern = le32_to_cpu(lmm->lmm_pattern);
+	lsm_size = lov_alloc_memmd(lsmp, stripe_count, pattern, magic);
 	if (lsm_size < 0)
-		RETURN(lsm_size);
+		return lsm_size;
 
 	/* If we are passed a pointer but nothing to unpack, we only alloc */
 	if (!lmm)
-		RETURN(lsm_size);
+		return lsm_size;
 
 	LASSERT(lsm_op_find(magic) != NULL);
 	rc = lsm_op_find(magic)->lsm_unpackmd(lov, *lsmp, lmm);
 	if (rc) {
 		lov_free_memmd(lsmp);
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(lsm_size);
+	return lsm_size;
 }
 
 static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
@@ -416,11 +417,10 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
 	__u16 stripe_count;
 	int rc;
 	int cplen = 0;
-	ENTRY;
 
 	rc = lov_lum_swab_if_needed(lumv3, &lmm_magic, lump);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	/* in the rest of the tests, as *lumv1 and lumv3 have the same
 	 * fields, we use lumv1 to avoid code duplication */
@@ -430,10 +430,10 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
 			lov->desc.ld_pattern : LOV_PATTERN_RAID0;
 	}
 
-	if (lumv1->lmm_pattern != LOV_PATTERN_RAID0) {
+	if (lov_pattern(lumv1->lmm_pattern) != LOV_PATTERN_RAID0) {
 		CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n",
 		       lumv1->lmm_pattern);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* 64kB is the largest common page size we see (ia64), and matches the
@@ -449,7 +449,7 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
 	     (typeof(lumv1->lmm_stripe_offset))(-1))) {
 		CDEBUG(D_IOCTL, "stripe offset %u > number of OSTs %u\n",
 		       lumv1->lmm_stripe_offset, lov->desc.ld_tgt_count);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	stripe_count = lov_get_stripecnt(lov, lmm_magic,
 					 lumv1->lmm_stripe_count);
@@ -479,7 +479,7 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
 					lumv3->lmm_stripe_offset, pool);
 				if (rc < 0) {
 					lov_pool_putref(pool);
-					RETURN(-EINVAL);
+					return -EINVAL;
 				}
 			}
 
@@ -490,6 +490,9 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
 		}
 	}
 
+	if (lumv1->lmm_pattern & LOV_PATTERN_F_RELEASED)
+		stripe_count = 0;
+
 	rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic);
 
 	if (rc >= 0) {
@@ -505,7 +508,7 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
 		rc = 0;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Configure object striping information on a new file.
@@ -526,7 +529,7 @@ int lov_setstripe(struct obd_export *exp, int max_lmm_size,
 
 	rc = __lov_setstripe(exp, max_lmm_size, lsmp, lump);
 	set_fs(seg);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
@@ -539,8 +542,6 @@ int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
 	obd_id last_id = 0;
 	struct lov_user_ost_data_v1 *lmm_objects;
 
-	ENTRY;
-
 	if (lump->lmm_magic == LOV_USER_MAGIC_V3)
 		lmm_objects = ((struct lov_user_md_v3 *)lump)->lmm_objects;
 	else
@@ -552,26 +553,26 @@ int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
 		rc = obd_get_info(NULL, oexp, sizeof(KEY_LAST_ID), KEY_LAST_ID,
 				  &len, &last_id, NULL);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		if (ostid_id(&lmm_objects[i].l_ost_oi) > last_id) {
 			CERROR("Setting EA for object > than last id on"
 			       " ost idx %d "DOSTID" > "LPD64" \n",
 			       lmm_objects[i].l_ost_idx,
 			       POSTID(&lmm_objects[i].l_ost_oi), last_id);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
 	rc = lov_setstripe(exp, 0, lsmp, lump);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	for (i = 0; i < lump->lmm_stripe_count; i++) {
 		(*lsmp)->lsm_oinfo[i]->loi_ost_idx =
 			lmm_objects[i].l_ost_idx;
 		(*lsmp)->lsm_oinfo[i]->loi_oi = lmm_objects[i].l_ost_oi;
 	}
-	RETURN(0);
+	return 0;
 }
 
 
@@ -593,10 +594,9 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm,
 	int rc, lmm_size;
 	int lum_size;
 	mm_segment_t seg;
-	ENTRY;
 
 	if (!lsm)
-		RETURN(-ENODATA);
+		return -ENODATA;
 
 	/*
 	 * "Switch to kernel segment" to allow copying from kernel space by
@@ -674,5 +674,5 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm,
 	obd_free_diskmd(exp, &lmmk);
 out_set:
 	set_fs(seg);
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c
index 65790d68..674e617 100644
--- a/drivers/staging/lustre/lustre/lov/lov_page.c
+++ b/drivers/staging/lustre/lustre/lov/lov_page.c
@@ -69,7 +69,6 @@ static void lov_page_fini(const struct lu_env *env,
 	struct cl_page  *sub = lov_sub_page(slice);
 
 	LINVRNT(lov_page_invariant(slice));
-	ENTRY;
 
 	if (sub != NULL) {
 		LASSERT(sub->cp_state == CPS_FREEING);
@@ -78,7 +77,6 @@ static void lov_page_fini(const struct lu_env *env,
 		slice->cpl_page->cp_child = NULL;
 		cl_page_put(env, sub);
 	}
-	EXIT;
 }
 
 static int lov_page_own(const struct lu_env *env,
@@ -90,7 +88,6 @@ static int lov_page_own(const struct lu_env *env,
 
 	LINVRNT(lov_page_invariant(slice));
 	LINVRNT(!cl2lov_page(slice)->lps_invalid);
-	ENTRY;
 
 	sub = lov_page_subio(env, lio, slice);
 	if (!IS_ERR(sub)) {
@@ -98,7 +95,7 @@ static int lov_page_own(const struct lu_env *env,
 		lov_sub_put(sub);
 	} else
 		LBUG(); /* Arrgh */
-	RETURN(0);
+	return 0;
 }
 
 static void lov_page_assume(const struct lu_env *env,
@@ -117,7 +114,6 @@ static int lov_page_cache_add(const struct lu_env *env,
 
 	LINVRNT(lov_page_invariant(slice));
 	LINVRNT(!cl2lov_page(slice)->lps_invalid);
-	ENTRY;
 
 	sub = lov_page_subio(env, lio, slice);
 	if (!IS_ERR(sub)) {
@@ -128,7 +124,7 @@ static int lov_page_cache_add(const struct lu_env *env,
 		rc = PTR_ERR(sub);
 		CL_PAGE_DEBUG(D_ERROR, env, slice->cpl_page, "rc = %d\n", rc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int lov_page_print(const struct lu_env *env,
@@ -172,7 +168,6 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj,
 	obd_off	    suboff;
 	int		stripe;
 	int		rc;
-	ENTRY;
 
 	offset = cl_offset(obj, page->cp_index);
 	stripe = lov_stripe_number(loo->lo_lsm, offset);
@@ -205,7 +200,6 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj,
 		LASSERT(0);
 	}
 
-	EXIT;
 out:
 	return rc;
 }
@@ -221,14 +215,13 @@ int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj,
 {
 	struct lov_page *lpg = cl_object_page_slice(obj, page);
 	void *addr;
-	ENTRY;
 
 	cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_empty_page_ops);
 	addr = kmap(vmpage);
 	memset(addr, 0, cl_page_size(obj));
 	kunmap(vmpage);
 	cl_page_export(env, page, 1);
-	RETURN(0);
+	return 0;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c
index a96f908..dd3c07d 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pool.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pool.c
@@ -68,7 +68,6 @@ void lov_pool_putref(struct pool_desc *pool)
 		lov_ost_pool_free(&(pool->pool_rr.lqr_pool));
 		lov_ost_pool_free(&(pool->pool_obds));
 		OBD_FREE_PTR(pool);
-		EXIT;
 	}
 }
 
@@ -322,8 +321,6 @@ void lov_dump_pool(int level, struct pool_desc *pool)
 #define LOV_POOL_INIT_COUNT 2
 int lov_ost_pool_init(struct ost_pool *op, unsigned int count)
 {
-	ENTRY;
-
 	if (count == 0)
 		count = LOV_POOL_INIT_COUNT;
 	op->op_array = NULL;
@@ -333,9 +330,8 @@ int lov_ost_pool_init(struct ost_pool *op, unsigned int count)
 	OBD_ALLOC(op->op_array, op->op_size * sizeof(op->op_array[0]));
 	if (op->op_array == NULL) {
 		op->op_size = 0;
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
-	EXIT;
 	return 0;
 }
 
@@ -366,7 +362,6 @@ int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count)
 int lov_ost_pool_add(struct ost_pool *op, __u32 idx, unsigned int min_count)
 {
 	int rc = 0, i;
-	ENTRY;
 
 	down_write(&op->op_rw_sem);
 
@@ -382,7 +377,6 @@ int lov_ost_pool_add(struct ost_pool *op, __u32 idx, unsigned int min_count)
 	/* ost not found we add it */
 	op->op_array[op->op_count] = idx;
 	op->op_count++;
-	EXIT;
 out:
 	up_write(&op->op_rw_sem);
 	return rc;
@@ -391,7 +385,6 @@ out:
 int lov_ost_pool_remove(struct ost_pool *op, __u32 idx)
 {
 	int i;
-	ENTRY;
 
 	down_write(&op->op_rw_sem);
 
@@ -401,21 +394,18 @@ int lov_ost_pool_remove(struct ost_pool *op, __u32 idx)
 				(op->op_count - i - 1) * sizeof(op->op_array[0]));
 			op->op_count--;
 			up_write(&op->op_rw_sem);
-			EXIT;
 			return 0;
 		}
 	}
 
 	up_write(&op->op_rw_sem);
-	RETURN(-EINVAL);
+	return -EINVAL;
 }
 
 int lov_ost_pool_free(struct ost_pool *op)
 {
-	ENTRY;
-
 	if (op->op_size == 0)
-		RETURN(0);
+		return 0;
 
 	down_write(&op->op_rw_sem);
 
@@ -425,7 +415,7 @@ int lov_ost_pool_free(struct ost_pool *op)
 	op->op_size = 0;
 
 	up_write(&op->op_rw_sem);
-	RETURN(0);
+	return 0;
 }
 
 
@@ -434,16 +424,15 @@ int lov_pool_new(struct obd_device *obd, char *poolname)
 	struct lov_obd *lov;
 	struct pool_desc *new_pool;
 	int rc;
-	ENTRY;
 
 	lov = &(obd->u.lov);
 
 	if (strlen(poolname) > LOV_MAXPOOLNAME)
-		RETURN(-ENAMETOOLONG);
+		return -ENAMETOOLONG;
 
 	OBD_ALLOC_PTR(new_pool);
 	if (new_pool == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME);
 	new_pool->pool_name[LOV_MAXPOOLNAME] = '\0';
@@ -492,7 +481,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname)
 	CDEBUG(D_CONFIG, LOV_POOLNAMEF" is pool #%d\n",
 	       poolname, lov->lov_pool_count);
 
-	RETURN(0);
+	return 0;
 
 out_err:
 	spin_lock(&obd->obd_dev_lock);
@@ -513,14 +502,13 @@ int lov_pool_del(struct obd_device *obd, char *poolname)
 {
 	struct lov_obd *lov;
 	struct pool_desc *pool;
-	ENTRY;
 
 	lov = &(obd->u.lov);
 
 	/* lookup and kill hash reference */
 	pool = cfs_hash_del_key(lov->lov_pools_hash_body, poolname);
 	if (pool == NULL)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	if (pool->pool_proc_entry != NULL) {
 		CDEBUG(D_INFO, "proc entry %p\n", pool->pool_proc_entry);
@@ -536,7 +524,7 @@ int lov_pool_del(struct obd_device *obd, char *poolname)
 	/* release last reference */
 	lov_pool_putref(pool);
 
-	RETURN(0);
+	return 0;
 }
 
 
@@ -547,13 +535,12 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname)
 	struct pool_desc *pool;
 	unsigned int lov_idx;
 	int rc;
-	ENTRY;
 
 	lov = &(obd->u.lov);
 
 	pool = cfs_hash_lookup(lov->lov_pools_hash_body, poolname);
 	if (pool == NULL)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	obd_str2uuid(&ost_uuid, ostname);
 
@@ -580,7 +567,6 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname)
 	CDEBUG(D_CONFIG, "Added %s to "LOV_POOLNAMEF" as member %d\n",
 	       ostname, poolname,  pool_tgt_count(pool));
 
-	EXIT;
 out:
 	obd_putref(obd);
 	lov_pool_putref(pool);
@@ -594,13 +580,12 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname)
 	struct pool_desc *pool;
 	unsigned int lov_idx;
 	int rc = 0;
-	ENTRY;
 
 	lov = &(obd->u.lov);
 
 	pool = cfs_hash_lookup(lov->lov_pools_hash_body, poolname);
 	if (pool == NULL)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	obd_str2uuid(&ost_uuid, ostname);
 
@@ -626,7 +611,6 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname)
 	CDEBUG(D_CONFIG, "%s removed from "LOV_POOLNAMEF"\n", ostname,
 	       poolname);
 
-	EXIT;
 out:
 	obd_putref(obd);
 	lov_pool_putref(pool);
@@ -636,7 +620,6 @@ out:
 int lov_check_index_in_pool(__u32 idx, struct pool_desc *pool)
 {
 	int i, rc;
-	ENTRY;
 
 	/* caller may no have a ref on pool if it got the pool
 	 * without calling lov_find_pool() (e.g. go through the lov pool
@@ -651,7 +634,6 @@ int lov_check_index_in_pool(__u32 idx, struct pool_desc *pool)
 			GOTO(out, rc = 0);
 	}
 	rc = -ENOENT;
-	EXIT;
 out:
 	up_read(&pool_tgt_rw_sem(pool));
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c
index 13f1637..61e6d0b 100644
--- a/drivers/staging/lustre/lustre/lov/lov_request.c
+++ b/drivers/staging/lustre/lustre/lov/lov_request.c
@@ -60,7 +60,6 @@ static void lov_init_set(struct lov_request_set *set)
 void lov_finish_set(struct lov_request_set *set)
 {
 	struct list_head *pos, *n;
-	ENTRY;
 
 	LASSERT(set);
 	list_for_each_safe(pos, n, &set->set_list) {
@@ -87,7 +86,6 @@ void lov_finish_set(struct lov_request_set *set)
 		lov_llh_put(set->set_lockh);
 
 	OBD_FREE(set, sizeof(*set));
-	EXIT;
 }
 
 int lov_set_finished(struct lov_request_set *set, int idempotent)
@@ -122,7 +120,6 @@ int lov_update_common_set(struct lov_request_set *set,
 			  struct lov_request *req, int rc)
 {
 	struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
-	ENTRY;
 
 	lov_update_set(set, req, rc);
 
@@ -132,7 +129,7 @@ int lov_update_common_set(struct lov_request_set *set,
 		rc = 0;
 
 	/* FIXME in raid1 regime, should return 0 */
-	RETURN(rc);
+	return rc;
 }
 
 void lov_set_add_req(struct lov_request *req, struct lov_request_set *set)
@@ -232,7 +229,6 @@ int lov_update_enqueue_set(struct lov_request *req, __u32 mode, int rc)
 	struct lustre_handle *lov_lockhp;
 	struct obd_info *oi = set->set_oi;
 	struct lov_oinfo *loi;
-	ENTRY;
 
 	LASSERT(oi != NULL);
 
@@ -254,7 +250,7 @@ int lov_update_enqueue_set(struct lov_request *req, __u32 mode, int rc)
 				    req->rq_idx, &oi->oi_md->lsm_oi, rc);
 	lov_stripe_unlock(oi->oi_md);
 	lov_update_set(set, req, rc);
-	RETURN(rc);
+	return rc;
 }
 
 /* The callback for osc_enqueue that updates lov info for every OSC request. */
@@ -275,11 +271,10 @@ static int enqueue_done(struct lov_request_set *set, __u32 mode)
 	struct lov_obd *lov = &set->set_exp->exp_obd->u.lov;
 	int completes = atomic_read(&set->set_completes);
 	int rc = 0;
-	ENTRY;
 
 	/* enqueue/match success, just return */
 	if (completes && completes == atomic_read(&set->set_success))
-		RETURN(0);
+		return 0;
 
 	/* cancel enqueued/matched locks */
 	list_for_each_entry(req, &set->set_list, rq_link) {
@@ -305,17 +300,16 @@ static int enqueue_done(struct lov_request_set *set, __u32 mode)
 	}
 	if (set->set_lockh)
 		lov_llh_put(set->set_lockh);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode, int rc,
 			 struct ptlrpc_request_set *rqset)
 {
 	int ret = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	/* Do enqueue_done only for sync requests and if any request
 	 * succeeded. */
@@ -328,7 +322,7 @@ int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode, int rc,
 
 	lov_put_reqset(set);
 
-	RETURN(rc ? rc : ret);
+	return rc ? rc : ret;
 }
 
 static void lov_llh_addref(void *llhp)
@@ -369,11 +363,10 @@ int lov_prep_enqueue_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	struct lov_request_set *set;
 	int i, rc = 0;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -445,19 +438,18 @@ int lov_prep_enqueue_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(0);
+	return 0;
 out_set:
 	lov_fini_enqueue_set(set, einfo->ei_mode, rc, NULL);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	rc = enqueue_done(set, mode);
 	if ((set->set_count == atomic_read(&set->set_success)) &&
@@ -466,7 +458,7 @@ int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags)
 
 	lov_put_reqset(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 int lov_prep_match_set(struct obd_export *exp, struct obd_info *oinfo,
@@ -477,11 +469,10 @@ int lov_prep_match_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	struct lov_request_set *set;
 	int i, rc = 0;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -535,19 +526,18 @@ int lov_prep_match_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_match_set(set, mode, 0);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_cancel_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 
 	LASSERT(set->set_exp);
 	if (set->set_lockh)
@@ -555,7 +545,7 @@ int lov_fini_cancel_set(struct lov_request_set *set)
 
 	lov_put_reqset(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo,
@@ -565,11 +555,10 @@ int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo,
 {
 	struct lov_request_set *set;
 	int i, rc = 0;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -617,10 +606,10 @@ int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_cancel_set(set);
-	RETURN(rc);
+	return rc;
 }
 static int common_attr_done(struct lov_request_set *set)
 {
@@ -628,15 +617,14 @@ static int common_attr_done(struct lov_request_set *set)
 	struct lov_request *req;
 	struct obdo *tmp_oa;
 	int rc = 0, attrset = 0;
-	ENTRY;
 
 	LASSERT(set->set_oi != NULL);
 
 	if (set->set_oi->oi_oa == NULL)
-		RETURN(0);
+		return 0;
 
 	if (!atomic_read(&set->set_success))
-		RETURN(-EIO);
+		return -EIO;
 
 	OBDO_ALLOC(tmp_oa);
 	if (tmp_oa == NULL)
@@ -670,7 +658,7 @@ static int common_attr_done(struct lov_request_set *set)
 out:
 	if (tmp_oa)
 		OBDO_FREE(tmp_oa);
-	RETURN(rc);
+	return rc;
 
 }
 
@@ -680,7 +668,6 @@ static int brw_done(struct lov_request_set *set)
 	struct lov_oinfo     *loi = NULL;
 	struct list_head *pos;
 	struct lov_request *req;
-	ENTRY;
 
 	list_for_each (pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -694,16 +681,15 @@ static int brw_done(struct lov_request_set *set)
 			loi->loi_lvb.lvb_blocks = req->rq_oi.oi_oa->o_blocks;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int lov_fini_brw_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	if (atomic_read(&set->set_completes)) {
 		rc = brw_done(set);
@@ -711,7 +697,7 @@ int lov_fini_brw_set(struct lov_request_set *set)
 	}
 	lov_put_reqset(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 int lov_prep_brw_set(struct obd_export *exp, struct obd_info *oinfo,
@@ -727,11 +713,10 @@ int lov_prep_brw_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int rc = 0, i, shift;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -832,23 +817,22 @@ out:
 	else
 		lov_fini_brw_set(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_getattr_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	if (atomic_read(&set->set_completes))
 		rc = common_attr_done(set);
 
 	lov_put_reqset(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* The callback for osc_getattr_async that finilizes a request info when a
@@ -867,11 +851,10 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int rc = 0, i;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -913,18 +896,16 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_getattr_set(set);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_destroy_set(struct lov_request_set *set)
 {
-	ENTRY;
-
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	if (atomic_read(&set->set_completes)) {
 		/* FIXME update qos data here */
@@ -932,7 +913,7 @@ int lov_fini_destroy_set(struct lov_request_set *set)
 
 	lov_put_reqset(set);
 
-	RETURN(0);
+	return 0;
 }
 
 int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
@@ -943,11 +924,10 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int rc = 0, i;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -987,19 +967,18 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_destroy_set(set);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_setattr_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	if (atomic_read(&set->set_completes)) {
 		rc = common_attr_done(set);
@@ -1007,7 +986,7 @@ int lov_fini_setattr_set(struct lov_request_set *set)
 	}
 
 	lov_put_reqset(set);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_update_setattr_set(struct lov_request_set *set,
@@ -1015,7 +994,6 @@ int lov_update_setattr_set(struct lov_request_set *set,
 {
 	struct lov_obd *lov = &req->rq_rqset->set_exp->exp_obd->u.lov;
 	struct lov_stripe_md *lsm = req->rq_rqset->set_oi->oi_md;
-	ENTRY;
 
 	lov_update_set(set, req, rc);
 
@@ -1036,7 +1014,7 @@ int lov_update_setattr_set(struct lov_request_set *set,
 				req->rq_oi.oi_oa->o_atime;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /* The callback for osc_setattr_async that finilizes a request info when a
@@ -1056,11 +1034,10 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int rc = 0, i;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -1113,19 +1090,18 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_setattr_set(set);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_punch_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	if (atomic_read(&set->set_completes)) {
 		rc = -EIO;
@@ -1136,7 +1112,7 @@ int lov_fini_punch_set(struct lov_request_set *set)
 
 	lov_put_reqset(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 int lov_update_punch_set(struct lov_request_set *set,
@@ -1144,7 +1120,6 @@ int lov_update_punch_set(struct lov_request_set *set,
 {
 	struct lov_obd *lov = &req->rq_rqset->set_exp->exp_obd->u.lov;
 	struct lov_stripe_md *lsm = req->rq_rqset->set_oi->oi_md;
-	ENTRY;
 
 	lov_update_set(set, req, rc);
 
@@ -1162,7 +1137,7 @@ int lov_update_punch_set(struct lov_request_set *set,
 		lov_stripe_unlock(lsm);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /* The callback for osc_punch that finilizes a request info when a response
@@ -1182,11 +1157,10 @@ int lov_prep_punch_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int rc = 0, i;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_oi = oinfo;
@@ -1238,19 +1212,18 @@ int lov_prep_punch_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_punch_set(set);
-	RETURN(rc);
+	return rc;
 }
 
 int lov_fini_sync_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 	LASSERT(set->set_exp);
 	if (atomic_read(&set->set_completes)) {
 		if (!atomic_read(&set->set_success))
@@ -1260,7 +1233,7 @@ int lov_fini_sync_set(struct lov_request_set *set)
 
 	lov_put_reqset(set);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* The callback for osc_sync that finilizes a request info when a
@@ -1281,11 +1254,10 @@ int lov_prep_sync_set(struct obd_export *exp, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
 	int rc = 0, i;
-	ENTRY;
 
 	OBD_ALLOC_PTR(set);
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_exp = exp;
@@ -1330,10 +1302,10 @@ int lov_prep_sync_set(struct obd_export *exp, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_sync_set(set);
-	RETURN(rc);
+	return rc;
 }
 
 #define LOV_U64_MAX ((__u64)~0ULL)
@@ -1347,8 +1319,6 @@ out_set:
 
 int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,int success)
 {
-	ENTRY;
-
 	if (success) {
 		__u32 expected_stripes = lov_get_stripecnt(&obd->u.lov,
 							   LOV_MAGIC, 0);
@@ -1361,26 +1331,25 @@ int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,int success)
 		memcpy(&obd->obd_osfs, osfs, sizeof(*osfs));
 		obd->obd_osfs_age = cfs_time_current_64();
 		spin_unlock(&obd->obd_osfs_lock);
-		RETURN(0);
+		return 0;
 	}
 
-	RETURN(-EIO);
+	return -EIO;
 }
 
 int lov_fini_statfs_set(struct lov_request_set *set)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (set == NULL)
-		RETURN(0);
+		return 0;
 
 	if (atomic_read(&set->set_completes)) {
 		rc = lov_fini_statfs(set->set_obd, set->set_oi->oi_osfs,
 				     atomic_read(&set->set_success));
 	}
 	lov_put_reqset(set);
-	RETURN(rc);
+	return rc;
 }
 
 void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs,
@@ -1450,7 +1419,6 @@ static int cb_statfs_update(void *cookie, int rc)
 	struct lov_tgt_desc *tgt;
 	struct obd_device *lovobd, *tgtobd;
 	int success;
-	ENTRY;
 
 	lovreq = container_of(oinfo, struct lov_request, rq_oi);
 	set = lovreq->rq_rqset;
@@ -1488,7 +1456,7 @@ out:
 				     atomic_read(&set->set_success));
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
@@ -1497,11 +1465,10 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
 	struct lov_request_set *set;
 	struct lov_obd *lov = &obd->u.lov;
 	int rc = 0, i;
-	ENTRY;
 
 	OBD_ALLOC(set, sizeof(*set));
 	if (set == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lov_init_set(set);
 
 	set->set_obd = obd;
@@ -1544,8 +1511,8 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
 	if (!set->set_count)
 		GOTO(out_set, rc = -EIO);
 	*reqset = set;
-	RETURN(rc);
+	return rc;
 out_set:
 	lov_fini_statfs_set(set);
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c
index 204ecd0..998ea1c 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c
@@ -55,10 +55,8 @@ static void lovsub_req_completion(const struct lu_env *env,
 {
 	struct lovsub_req *lsr;
 
-	ENTRY;
 	lsr = cl2lovsub_req(slice);
 	OBD_SLAB_FREE_PTR(lsr, lovsub_req_kmem);
-	EXIT;
 }
 
 /**
@@ -73,14 +71,12 @@ static void lovsub_req_attr_set(const struct lu_env *env,
 {
 	struct lovsub_object *subobj;
 
-	ENTRY;
 	subobj = cl2lovsub(obj);
 	/*
 	 * There is no OBD_MD_* flag for obdo::o_stripe_idx, so set it
 	 * unconditionally. It never changes anyway.
 	 */
 	attr->cra_oa->o_stripe_idx = subobj->lso_index;
-	EXIT;
 }
 
 static const struct cl_req_operations lovsub_req_ops = {
@@ -101,20 +97,19 @@ static int lovsub_device_init(const struct lu_env *env, struct lu_device *d,
 	struct lu_device_type *ldt;
 	int rc;
 
-	ENTRY;
 	next->ld_site = d->ld_site;
 	ldt = next->ld_type;
 	LASSERT(ldt != NULL);
 	rc = ldt->ldt_ops->ldto_device_init(env, next, ldt->ldt_name, NULL);
 	if (rc) {
 		next->ld_site = NULL;
-		RETURN(rc);
+		return rc;
 	}
 
 	lu_device_get(next);
 	lu_ref_add(&next->ld_reference, "lu-stack", &lu_site_init);
 	lsd->acid_next = lu2cl_dev(next);
-	RETURN(rc);
+	return rc;
 }
 
 static struct lu_device *lovsub_device_fini(const struct lu_env *env,
@@ -123,12 +118,11 @@ static struct lu_device *lovsub_device_fini(const struct lu_env *env,
 	struct lu_device *next;
 	struct lovsub_device *lsd;
 
-	ENTRY;
 	lsd = lu2lovsub_dev(d);
 	next = cl2lu_dev(lsd->acid_next);
 	lsd->acid_super = NULL;
 	lsd->acid_next = NULL;
-	RETURN(next);
+	return next;
 }
 
 static struct lu_device *lovsub_device_free(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_lock.c b/drivers/staging/lustre/lustre/lov/lovsub_lock.c
index 03bab17..80305aa 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_lock.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_lock.c
@@ -57,35 +57,29 @@ static void lovsub_lock_fini(const struct lu_env *env,
 {
 	struct lovsub_lock   *lsl;
 
-	ENTRY;
 	lsl = cl2lovsub_lock(slice);
 	LASSERT(list_empty(&lsl->lss_parents));
 	OBD_SLAB_FREE_PTR(lsl, lovsub_lock_kmem);
-	EXIT;
 }
 
 static void lovsub_parent_lock(const struct lu_env *env, struct lov_lock *lov)
 {
 	struct cl_lock *parent;
 
-	ENTRY;
 	parent = lov->lls_cl.cls_lock;
 	cl_lock_get(parent);
 	lu_ref_add(&parent->cll_reference, "lovsub-parent", current);
 	cl_lock_mutex_get(env, parent);
-	EXIT;
 }
 
 static void lovsub_parent_unlock(const struct lu_env *env, struct lov_lock *lov)
 {
 	struct cl_lock *parent;
 
-	ENTRY;
 	parent = lov->lls_cl.cls_lock;
 	cl_lock_mutex_put(env, lov->lls_cl.cls_lock);
 	lu_ref_del(&parent->cll_reference, "lovsub-parent", current);
 	cl_lock_put(env, parent);
-	EXIT;
 }
 
 /**
@@ -101,7 +95,6 @@ static void lovsub_lock_state(const struct lu_env *env,
 	struct lov_lock_link *scan;
 
 	LASSERT(cl_lock_is_mutexed(slice->cls_lock));
-	ENTRY;
 
 	list_for_each_entry(scan, &sub->lss_parents, lll_list) {
 		struct lov_lock *lov    = scan->lll_super;
@@ -113,7 +106,6 @@ static void lovsub_lock_state(const struct lu_env *env,
 			lovsub_parent_unlock(env, lov);
 		}
 	}
-	EXIT;
 }
 
 /**
@@ -127,8 +119,6 @@ static unsigned long lovsub_lock_weigh(const struct lu_env *env,
 	struct lov_lock    *lov;
 	unsigned long       dumbbell;
 
-	ENTRY;
-
 	LASSERT(cl_lock_is_mutexed(slice->cls_lock));
 
 	if (!list_empty(&lock->lss_parents)) {
@@ -146,7 +136,7 @@ static unsigned long lovsub_lock_weigh(const struct lu_env *env,
 	} else
 		dumbbell = 0;
 
-	RETURN(dumbbell);
+	return dumbbell;
 }
 
 /**
@@ -162,7 +152,6 @@ static void lovsub_lock_descr_map(const struct cl_lock_descr *in,
 	pgoff_t start;
 	pgoff_t end;
 
-	ENTRY;
 	start = in->cld_start;
 	end   = in->cld_end;
 
@@ -184,7 +173,6 @@ static void lovsub_lock_descr_map(const struct cl_lock_descr *in,
 	}
 	out->cld_start = start;
 	out->cld_end   = end;
-	EXIT;
 }
 
 /**
@@ -241,8 +229,6 @@ static int lovsub_lock_modify(const struct lu_env *env,
 	struct lov_lock      *lov;
 	int result		   = 0;
 
-	ENTRY;
-
 	LASSERT(cl_lock_mode_match(d->cld_mode,
 				   s->cls_lock->cll_descr.cld_mode));
 	list_for_each_entry(scan, &lock->lss_parents, lll_list) {
@@ -254,7 +240,7 @@ static int lovsub_lock_modify(const struct lu_env *env,
 		lovsub_parent_unlock(env, lov);
 		result = result ?: rc;
 	}
-	RETURN(result);
+	return result;
 }
 
 static int lovsub_lock_closure(const struct lu_env *env,
@@ -267,7 +253,6 @@ static int lovsub_lock_closure(const struct lu_env *env,
 	int		   result;
 
 	LASSERT(cl_lock_is_mutexed(slice->cls_lock));
-	ENTRY;
 
 	sub    = cl2lovsub_lock(slice);
 	result = 0;
@@ -278,7 +263,7 @@ static int lovsub_lock_closure(const struct lu_env *env,
 		if (result != 0)
 			break;
 	}
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -290,11 +275,10 @@ static int lovsub_lock_delete_one(const struct lu_env *env,
 {
 	struct cl_lock *parent;
 	int	     result;
-	ENTRY;
 
 	parent = lov->lls_cl.cls_lock;
 	if (parent->cll_error)
-		RETURN(0);
+		return 0;
 
 	result = 0;
 	switch (parent->cll_state) {
@@ -386,7 +370,7 @@ static int lovsub_lock_delete_one(const struct lu_env *env,
 		break;
 	}
 
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -403,7 +387,6 @@ static void lovsub_lock_delete(const struct lu_env *env,
 
 	LASSERT(cl_lock_is_mutexed(child));
 
-	ENTRY;
 	/*
 	 * Destruction of a sub-lock might take multiple iterations, because
 	 * when the last sub-lock of a given top-lock is deleted, top-lock is
@@ -434,7 +417,6 @@ static void lovsub_lock_delete(const struct lu_env *env,
 			}
 	       }
 	} while (restart);
-	EXIT;
 }
 
 static int lovsub_lock_print(const struct lu_env *env, void *cookie,
@@ -471,7 +453,6 @@ int lovsub_lock_init(const struct lu_env *env, struct cl_object *obj,
 	struct lovsub_lock *lsk;
 	int result;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(lsk, lovsub_lock_kmem, __GFP_IO);
 	if (lsk != NULL) {
 		INIT_LIST_HEAD(&lsk->lss_parents);
@@ -479,7 +460,7 @@ int lovsub_lock_init(const struct lu_env *env, struct cl_object *obj,
 		result = 0;
 	} else
 		result = -ENOMEM;
-	RETURN(result);
+	return result;
 }
 
 /** @} lov */
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c
index 1b83d90..89760b3 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_object.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c
@@ -61,7 +61,6 @@ int lovsub_object_init(const struct lu_env *env, struct lu_object *obj,
 
 	int result;
 
-	ENTRY;
 	under = &dev->acid_next->cd_lu_dev;
 	below = under->ld_ops->ldo_object_alloc(env, obj->lo_header, under);
 	if (below != NULL) {
@@ -70,7 +69,7 @@ int lovsub_object_init(const struct lu_env *env, struct lu_object *obj,
 		result = 0;
 	} else
 		result = -ENOMEM;
-	RETURN(result);
+	return result;
 
 }
 
@@ -78,7 +77,6 @@ static void lovsub_object_free(const struct lu_env *env, struct lu_object *obj)
 {
 	struct lovsub_object *los = lu2lovsub(obj);
 	struct lov_object    *lov = los->lso_super;
-	ENTRY;
 
 	/* We can't assume lov was assigned here, because of the shadow
 	 * object handling in lu_object_find.
@@ -94,7 +92,6 @@ static void lovsub_object_free(const struct lu_env *env, struct lu_object *obj)
 	lu_object_fini(obj);
 	lu_object_header_fini(&los->lso_header.coh_lu);
 	OBD_SLAB_FREE_PTR(los, lovsub_object_kmem);
-	EXIT;
 }
 
 static int lovsub_object_print(const struct lu_env *env, void *cookie,
@@ -110,9 +107,8 @@ static int lovsub_attr_set(const struct lu_env *env, struct cl_object *obj,
 {
 	struct lov_object *lov = cl2lovsub(obj)->lso_super;
 
-	ENTRY;
 	lov_r0(lov)->lo_attr_valid = 0;
-	RETURN(0);
+	return 0;
 }
 
 static int lovsub_object_glimpse(const struct lu_env *env,
@@ -121,8 +117,7 @@ static int lovsub_object_glimpse(const struct lu_env *env,
 {
 	struct lovsub_object *los = cl2lovsub(obj);
 
-	ENTRY;
-	RETURN(cl_object_glimpse(env, &los->lso_super->lo_cl, lvb));
+	return cl_object_glimpse(env, &los->lso_super->lo_cl, lvb);
 }
 
 
@@ -150,7 +145,6 @@ struct lu_object *lovsub_object_alloc(const struct lu_env *env,
 	struct lovsub_object *los;
 	struct lu_object     *obj;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(los, lovsub_object_kmem, __GFP_IO);
 	if (los != NULL) {
 		struct cl_object_header *hdr;
@@ -164,7 +158,7 @@ struct lu_object *lovsub_object_alloc(const struct lu_env *env,
 		obj->lo_ops = &lovsub_lu_obj_ops;
 	} else
 		obj = NULL;
-	RETURN(obj);
+	return obj;
 }
 
 /** @} lov */
diff --git a/drivers/staging/lustre/lustre/lov/lovsub_page.c b/drivers/staging/lustre/lustre/lov/lovsub_page.c
index bc9e683..3f00ce9 100644
--- a/drivers/staging/lustre/lustre/lov/lovsub_page.c
+++ b/drivers/staging/lustre/lustre/lov/lovsub_page.c
@@ -63,10 +63,9 @@ int lovsub_page_init(const struct lu_env *env, struct cl_object *obj,
 			struct cl_page *page, struct page *unused)
 {
 	struct lovsub_page *lsb = cl_object_page_slice(obj, page);
-	ENTRY;
 
 	cl_page_slice_add(page, &lsb->lsb_cl, obj, &lovsub_page_ops);
-	RETURN(0);
+	return 0;
 }
 
 /** @} lov */
diff --git a/drivers/staging/lustre/lustre/lov/lproc_lov.c b/drivers/staging/lustre/lustre/lov/lproc_lov.c
index 5b2c0d8..15744e1 100644
--- a/drivers/staging/lustre/lustre/lov/lproc_lov.c
+++ b/drivers/staging/lustre/lustre/lov/lproc_lov.c
@@ -35,7 +35,6 @@
  */
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/version.h>
 #include <asm/statfs.h>
 #include <lprocfs_status.h>
 #include <obd_class.h>
diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt.c b/drivers/staging/lustre/lustre/lvfs/fsfilt.c
index 064445c..e86df73 100644
--- a/drivers/staging/lustre/lustre/lvfs/fsfilt.c
+++ b/drivers/staging/lustre/lustre/lvfs/fsfilt.c
@@ -35,7 +35,6 @@
 #define DEBUG_SUBSYSTEM S_FILTER
 
 #include <linux/fs.h>
-#include <linux/jbd.h>
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
@@ -68,7 +67,7 @@ int fsfilt_register_ops(struct fsfilt_operations *fs_ops)
 			CERROR("different operations for type %s\n",
 			       fs_ops->fs_type);
 			/* unlock fsfilt_types list */
-			RETURN(-EEXIST);
+			return -EEXIST;
 		}
 	} else {
 		try_module_get(THIS_MODULE);
@@ -120,7 +119,7 @@ struct fsfilt_operations *fsfilt_get_ops(const char *type)
 
 		if (rc) {
 			CERROR("Can't find %s interface\n", name);
-			RETURN(ERR_PTR(rc < 0 ? rc : -rc));
+			return ERR_PTR(rc < 0 ? rc : -rc);
 			/* unlock fsfilt_types list */
 		}
 	}
diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c b/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c
index c1e99b3..ee75994 100644
--- a/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c
+++ b/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c
@@ -48,7 +48,6 @@
 #include <ldiskfs/ldiskfs_config.h>
 #include <ext4/ext4.h>
 #include <ext4/ext4_jbd2.h>
-#include <linux/version.h>
 #include <linux/bitops.h>
 #include <linux/quota.h>
 
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
index e70d8fe..18e1b47 100644
--- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
+++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
@@ -40,16 +40,12 @@
 
 #define DEBUG_SUBSYSTEM S_FILTER
 
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <asm/unistd.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
-#include <linux/version.h>
 #include <linux/libcfs/libcfs.h>
-#include <lustre_fsfilt.h>
-#include <obd.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/lustre_compat25.h>
@@ -207,7 +203,6 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt,
 {
 	struct dentry *dchild_old, *dchild_new;
 	int err = 0;
-	ENTRY;
 
 	ASSERT_KERNEL_CTXT("kernel doing rename outside kernel context\n");
 	CDEBUG(D_INODE, "renaming file %.*s to %.*s\n",
@@ -215,7 +210,7 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt,
 
 	dchild_old = ll_lookup_one_len(oldname, dir, strlen(oldname));
 	if (IS_ERR(dchild_old))
-		RETURN(PTR_ERR(dchild_old));
+		return PTR_ERR(dchild_old);
 
 	if (!dchild_old->d_inode)
 		GOTO(put_old, err = -ENOENT);
@@ -230,7 +225,7 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt,
 	dput(dchild_new);
 put_old:
 	dput(dchild_old);
-	RETURN(err);
+	return err;
 }
 EXPORT_SYMBOL(lustre_rename);
 
@@ -242,7 +237,7 @@ struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de,
 		.dentry = de,
 		.mnt = ctxt->pwdmnt,
 	};
-	return ll_dentry_open(&path, flags, current_cred());
+	return dentry_open(&path, flags, current_cred());
 }
 EXPORT_SYMBOL(l_dentry_open);
 
@@ -255,7 +250,7 @@ __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
 	__s64 ret = 0;
 
 	if (lc == NULL || header == NULL)
-		RETURN(0);
+		return 0;
 
 	switch (field) {
 		case LPROCFS_FIELDS_FLAGS_CONFIG:
@@ -285,7 +280,7 @@ __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
 			break;
 	};
 
-	RETURN(ret);
+	return ret;
 }
 EXPORT_SYMBOL(lprocfs_read_helper);
 #endif /* LPROCFS */
diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c
index 6592478..e0b8f18 100644
--- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c
+++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c
@@ -35,7 +35,6 @@
  */
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/version.h>
 #include <linux/vfs.h>
 #include <obd_class.h>
 #include <lprocfs_status.h>
@@ -93,14 +92,13 @@ static ssize_t mdc_kuc_write(struct file *file, const char *buffer,
 	struct hsm_action_item	*hai;
 	int			 len;
 	int			 fd, rc;
-	ENTRY;
 
 	rc = lprocfs_write_helper(buffer, count, &fd);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (fd < 0)
-		RETURN(-ERANGE);
+		return -ERANGE;
 	CWARN("message to fd %d\n", fd);
 
 	len = sizeof(*lh) + sizeof(*hal) + MTI_NAME_MAXLEN +
@@ -141,8 +139,8 @@ static ssize_t mdc_kuc_write(struct file *file, const char *buffer,
 	}
 	OBD_FREE(lh, len);
 	if (rc < 0)
-		RETURN(rc);
-	RETURN(count);
+		return rc;
+	return count;
 }
 
 struct file_operations mdc_kuc_fops = {
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c
index e789aed..b2de478 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c
@@ -45,10 +45,10 @@ static void __mdc_pack_body(struct mdt_body *b, __u32 suppgid)
 	LASSERT (b != NULL);
 
 	b->suppgid = suppgid;
-	b->uid = current_uid();
-	b->gid = current_gid();
-	b->fsuid = current_fsuid();
-	b->fsgid = current_fsgid();
+	b->uid = from_kuid(&init_user_ns, current_uid());
+	b->gid = from_kgid(&init_user_ns, current_gid());
+	b->fsuid = from_kuid(&init_user_ns, current_fsuid());
+	b->fsgid = from_kgid(&init_user_ns, current_fsgid());
 	b->capability = cfs_curproc_cap_pack();
 }
 
@@ -219,8 +219,8 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
 
 	/* XXX do something about time, uid, gid */
 	rec->cr_opcode   = REINT_OPEN;
-	rec->cr_fsuid   = current_fsuid();
-	rec->cr_fsgid   = current_fsgid();
+	rec->cr_fsuid    = from_kuid(&init_user_ns, current_fsuid());
+	rec->cr_fsgid    = from_kgid(&init_user_ns, current_fsgid());
 	rec->cr_cap      = cfs_curproc_cap_pack();
 	if (op_data != NULL) {
 		rec->cr_fid1 = op_data->op_fid1;
@@ -299,16 +299,16 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec,
 				 struct md_op_data *op_data)
 {
 	rec->sa_opcode  = REINT_SETATTR;
-	rec->sa_fsuid   = current_fsuid();
-	rec->sa_fsgid   = current_fsgid();
+	rec->sa_fsuid   = from_kuid(&init_user_ns, current_fsuid());
+	rec->sa_fsgid   = from_kgid(&init_user_ns, current_fsgid());
 	rec->sa_cap     = cfs_curproc_cap_pack();
 	rec->sa_suppgid = -1;
 
 	rec->sa_fid    = op_data->op_fid1;
 	rec->sa_valid  = attr_pack(op_data->op_attr.ia_valid);
 	rec->sa_mode   = op_data->op_attr.ia_mode;
-	rec->sa_uid    = op_data->op_attr.ia_uid;
-	rec->sa_gid    = op_data->op_attr.ia_gid;
+	rec->sa_uid    = from_kuid(&init_user_ns, op_data->op_attr.ia_uid);
+	rec->sa_gid    = from_kgid(&init_user_ns, op_data->op_attr.ia_gid);
 	rec->sa_size   = op_data->op_attr.ia_size;
 	rec->sa_blocks = op_data->op_attr_blocks;
 	rec->sa_atime  = LTIME_S(op_data->op_attr.ia_atime);
@@ -316,8 +316,9 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec,
 	rec->sa_ctime  = LTIME_S(op_data->op_attr.ia_ctime);
 	rec->sa_attr_flags = ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags;
 	if ((op_data->op_attr.ia_valid & ATTR_GID) &&
-	    current_is_in_group(op_data->op_attr.ia_gid))
-		rec->sa_suppgid = op_data->op_attr.ia_gid;
+	    in_group_p(op_data->op_attr.ia_gid))
+		rec->sa_suppgid =
+			from_kgid(&init_user_ns, op_data->op_attr.ia_gid);
 	else
 		rec->sa_suppgid = op_data->op_suppgids[0];
 
@@ -504,11 +505,11 @@ void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data)
 static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw)
 {
 	int rc;
-	ENTRY;
+
 	client_obd_list_lock(&cli->cl_loi_list_lock);
 	rc = list_empty(&mcw->mcw_entry);
 	client_obd_list_unlock(&cli->cl_loi_list_lock);
-	RETURN(rc);
+	return rc;
 };
 
 /* We record requests in flight in cli->cl_r_in_flight here.
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
index 1cc90b6..fb5a995 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
@@ -115,13 +115,12 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
 {
 	struct ldlm_lock *lock;
 	struct inode *new_inode = data;
-	ENTRY;
 
 	if(bits)
 		*bits = 0;
 
 	if (!*lockh)
-		RETURN(0);
+		return 0;
 
 	lock = ldlm_handle2lock((struct lustre_handle *)lockh);
 
@@ -144,7 +143,7 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
 	unlock_res_and_lock(lock);
 	LDLM_LOCK_PUT(lock);
 
-	RETURN(0);
+	return 0;
 }
 
 ldlm_mode_t mdc_lock_match(struct obd_export *exp, __u64 flags,
@@ -154,12 +153,11 @@ ldlm_mode_t mdc_lock_match(struct obd_export *exp, __u64 flags,
 {
 	struct ldlm_res_id res_id;
 	ldlm_mode_t rc;
-	ENTRY;
 
 	fid_build_reg_res_name(fid, &res_id);
 	rc = ldlm_lock_match(class_exp2obd(exp)->obd_namespace, flags,
 			     &res_id, type, policy, mode, lockh, 0);
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_cancel_unused(struct obd_export *exp,
@@ -173,12 +171,10 @@ int mdc_cancel_unused(struct obd_export *exp,
 	struct obd_device *obd = class_exp2obd(exp);
 	int rc;
 
-	ENTRY;
-
 	fid_build_reg_res_name(fid, &res_id);
 	rc = ldlm_cli_cancel_unused_resource(obd->obd_namespace, &res_id,
 					     policy, mode, flags, opaque);
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_null_inode(struct obd_export *exp,
@@ -187,7 +183,6 @@ int mdc_null_inode(struct obd_export *exp,
 	struct ldlm_res_id res_id;
 	struct ldlm_resource *res;
 	struct ldlm_namespace *ns = class_exp2obd(exp)->obd_namespace;
-	ENTRY;
 
 	LASSERTF(ns != NULL, "no namespace passed\n");
 
@@ -195,14 +190,14 @@ int mdc_null_inode(struct obd_export *exp,
 
 	res = ldlm_resource_get(ns, NULL, &res_id, 0, 0);
 	if(res == NULL)
-		RETURN(0);
+		return 0;
 
 	lock_res(res);
 	res->lr_lvb_inode = NULL;
 	unlock_res(res);
 
 	ldlm_resource_putref(res);
-	RETURN(0);
+	return 0;
 }
 
 /* find any ldlm lock of the inode in mdc
@@ -215,16 +210,15 @@ int mdc_find_cbdata(struct obd_export *exp,
 {
 	struct ldlm_res_id res_id;
 	int rc = 0;
-	ENTRY;
 
 	fid_build_reg_res_name((struct lu_fid*)fid, &res_id);
 	rc = ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace, &res_id,
 				   it, data);
 	if (rc == LDLM_ITER_STOP)
-		RETURN(1);
+		return 1;
 	else if (rc == LDLM_ITER_CONTINUE)
-		RETURN(0);
-	RETURN(rc);
+		return 0;
+	return rc;
 }
 
 static inline void mdc_clear_replay_flag(struct ptlrpc_request *req, int rc)
@@ -281,7 +275,6 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp,
 	int		    count = 0;
 	int		    mode;
 	int		    rc;
-	ENTRY;
 
 	it->it_create_mode = (it->it_create_mode & ~S_IFMT) | S_IFREG;
 
@@ -314,7 +307,7 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp,
 				   &RQF_LDLM_INTENT_OPEN);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 	}
 
 	/* parent capability */
@@ -362,12 +355,11 @@ static struct ptlrpc_request *mdc_intent_unlink_pack(struct obd_export *exp,
 	struct obd_device     *obddev = class_exp2obd(exp);
 	struct ldlm_intent    *lit;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_LDLM_INTENT_UNLINK);
 	if (req == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
@@ -376,7 +368,7 @@ static struct ptlrpc_request *mdc_intent_unlink_pack(struct obd_export *exp,
 	rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	/* pack the intent */
@@ -391,7 +383,7 @@ static struct ptlrpc_request *mdc_intent_unlink_pack(struct obd_export *exp,
 	req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER,
 			     obddev->u.cli.cl_max_mds_cookiesize);
 	ptlrpc_request_set_replen(req);
-	RETURN(req);
+	return req;
 }
 
 static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp,
@@ -407,12 +399,11 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp,
 					       OBD_MD_FLRMTPERM : OBD_MD_FLACL);
 	struct ldlm_intent    *lit;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_LDLM_INTENT_GETATTR);
 	if (req == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
@@ -421,7 +412,7 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp,
 	rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	/* pack the intent */
@@ -438,7 +429,7 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp,
 		req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER,
 				     sizeof(struct mdt_remote_perm));
 	ptlrpc_request_set_replen(req);
-	RETURN(req);
+	return req;
 }
 
 static struct ptlrpc_request *mdc_intent_layout_pack(struct obd_export *exp,
@@ -450,18 +441,17 @@ static struct ptlrpc_request *mdc_intent_layout_pack(struct obd_export *exp,
 	struct ldlm_intent    *lit;
 	struct layout_intent  *layout;
 	int rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				&RQF_LDLM_INTENT_LAYOUT);
 	if (req == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, 0);
 	rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	/* pack the intent */
@@ -477,7 +467,7 @@ static struct ptlrpc_request *mdc_intent_layout_pack(struct obd_export *exp,
 	req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER,
 			obd->u.cli.cl_max_mds_easize);
 	ptlrpc_request_set_replen(req);
-	RETURN(req);
+	return req;
 }
 
 static struct ptlrpc_request *
@@ -485,21 +475,20 @@ mdc_enqueue_pack(struct obd_export *exp, int lvb_len)
 {
 	struct ptlrpc_request *req;
 	int rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_ENQUEUE);
 	if (req == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER, lvb_len);
 	ptlrpc_request_set_replen(req);
-	RETURN(req);
+	return req;
 }
 
 static int mdc_finish_enqueue(struct obd_export *exp,
@@ -516,7 +505,6 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 	struct ldlm_lock    *lock;
 	void		*lvb_data = NULL;
 	int		  lvb_len = 0;
-	ENTRY;
 
 	LASSERT(rc >= 0);
 	/* Similarly, if we're going to replay this request, we don't want to
@@ -579,7 +567,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 		body = req_capsule_server_get(pill, &RMF_MDT_BODY);
 		if (body == NULL) {
 			CERROR ("Can't swab mdt_body\n");
-			RETURN (-EPROTO);
+			return -EPROTO;
 		}
 
 		if (it_disposition(it, DISP_OPEN_OPEN) &&
@@ -605,7 +593,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 			eadata = req_capsule_server_sized_get(pill, &RMF_MDT_MD,
 							      body->eadatasize);
 			if (eadata == NULL)
-				RETURN(-EPROTO);
+				return -EPROTO;
 
 			/* save lvb data and length in case this is for layout
 			 * lock */
@@ -649,14 +637,14 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 			perm = req_capsule_server_swab_get(pill, &RMF_ACL,
 						lustre_swab_mdt_remote_perm);
 			if (perm == NULL)
-				RETURN(-EPROTO);
+				return -EPROTO;
 		}
 		if (body->valid & OBD_MD_FLMDSCAPA) {
 			struct lustre_capa *capa, *p;
 
 			capa = req_capsule_server_get(pill, &RMF_CAPA1);
 			if (capa == NULL)
-				RETURN(-EPROTO);
+				return -EPROTO;
 
 			if (it->it_op & IT_OPEN) {
 				/* client fid capa will be checked in replay */
@@ -670,7 +658,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 
 			capa = req_capsule_server_get(pill, &RMF_CAPA2);
 			if (capa == NULL)
-				RETURN(-EPROTO);
+				return -EPROTO;
 		}
 	} else if (it->it_op & IT_LAYOUT) {
 		/* maybe the lock was granted right away and layout
@@ -680,7 +668,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 			lvb_data = req_capsule_server_sized_get(pill,
 							&RMF_DLM_LVB, lvb_len);
 			if (lvb_data == NULL)
-				RETURN(-EPROTO);
+				return -EPROTO;
 		}
 	}
 
@@ -695,7 +683,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 		OBD_ALLOC_LARGE(lmm, lvb_len);
 		if (lmm == NULL) {
 			LDLM_LOCK_PUT(lock);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		memcpy(lmm, lvb_data, lvb_len);
 
@@ -713,7 +701,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 	if (lock != NULL)
 		LDLM_LOCK_PUT(lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* We always reserve enough space in the reply packet for a stripe MD, because
@@ -738,7 +726,6 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 	int		    generation, resends = 0;
 	struct ldlm_reply     *lockrep;
 	enum lvb_type	       lvb_type = 0;
-	ENTRY;
 
 	LASSERTF(!it || einfo->ei_type == LDLM_IBITS, "lock type %d\n",
 		 einfo->ei_type);
@@ -780,17 +767,17 @@ resend:
 		req = mdc_enqueue_pack(exp, 0);
 	} else if (it->it_op & IT_LAYOUT) {
 		if (!imp_connect_lvb_type(class_exp2cliimp(exp)))
-			RETURN(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 
 		req = mdc_intent_layout_pack(exp, it, op_data);
 		lvb_type = LVB_T_LAYOUT;
 	} else {
 		LBUG();
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (IS_ERR(req))
-		RETURN(PTR_ERR(req));
+		return PTR_ERR(req);
 
 	if (req != NULL && it && it->it_op & IT_CREAT)
 		/* ask ptlrpc not to resend on EINPROGRESS since we have our own
@@ -813,7 +800,7 @@ resend:
 			mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
 			mdc_clear_replay_flag(req, 0);
 			ptlrpc_req_finished(req);
-			RETURN(rc);
+			return rc;
 		}
 	}
 
@@ -823,8 +810,14 @@ resend:
 		/* For flock requests we immediatelly return without further
 		   delay and let caller deal with the rest, since rest of
 		   this function metadata processing makes no sense for flock
-		   requests anyway */
-		RETURN(rc);
+		   requests anyway. But in case of problem during comms with
+		   Server (ETIMEDOUT) or any signal/kill attempt (EINTR), we
+		   can not rely on caller and this mainly for F_UNLCKs
+		   (explicits or automatically generated by Kernel to clean
+		   current FLocks upon exit) that can't be trashed */
+		if ((rc == -EINTR) || (rc == -ETIMEDOUT))
+			goto resend;
+		return rc;
 	}
 
 	mdc_exit_request(&obddev->u.cli);
@@ -834,12 +827,15 @@ resend:
 		CERROR("ldlm_cli_enqueue: %d\n", rc);
 		mdc_clear_replay_flag(req, rc);
 		ptlrpc_req_finished(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP);
 	LASSERT(lockrep != NULL);
 
+	lockrep->lock_policy_res2 =
+		ptlrpc_status_ntoh(lockrep->lock_policy_res2);
+
 	/* Retry the create infinitely when we get -EINPROGRESS from
 	 * server. This is required by the new quota design. */
 	if (it && it->it_op & IT_CREAT &&
@@ -856,7 +852,7 @@ resend:
 			goto resend;
 		} else {
 			CDEBUG(D_HA, "resend cross eviction\n");
-			RETURN(-EIO);
+			return -EIO;
 		}
 	}
 
@@ -868,7 +864,7 @@ resend:
 		}
 		ptlrpc_req_finished(req);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_finish_intent_lock(struct obd_export *exp,
@@ -882,7 +878,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
 	struct ldlm_lock *lock;
 	int rc;
 
-
 	LASSERT(request != NULL);
 	LASSERT(request != LP_POISON);
 	LASSERT(request->rq_repmsg != LP_POISON);
@@ -891,11 +886,11 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
 		/* The server failed before it even started executing the
 		 * intent, i.e. because it couldn't unpack the request. */
 		LASSERT(it->d.lustre.it_status != 0);
-		RETURN(it->d.lustre.it_status);
+		return it->d.lustre.it_status;
 	}
 	rc = it_open_error(DISP_IT_EXECD, it);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	mdt_body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
 	LASSERT(mdt_body != NULL);      /* mdc_enqueue checked */
@@ -917,13 +912,13 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
 			CDEBUG(D_DENTRY, "Found stale data "DFID"("DFID")/"DFID
 			       "\n", PFID(&op_data->op_fid2),
 			       PFID(&op_data->op_fid2), PFID(&mdt_body->fid1));
-			RETURN(-ESTALE);
+			return -ESTALE;
 		}
 	}
 
 	rc = it_open_error(DISP_LOOKUP_EXECD, it);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	/* keep requests around for the multiple phases of the call
 	 * this shows the DISP_XX must guarantee we make it into the call
@@ -984,7 +979,7 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
 	CDEBUG(D_DENTRY,"D_IT dentry %.*s intent: %s status %d disp %x rc %d\n",
 	       op_data->op_namelen, op_data->op_name, ldlm_it2str(it->it_op),
 	       it->d.lustre.it_status, it->d.lustre.it_disposition, rc);
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
@@ -997,7 +992,6 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
 	struct lustre_handle lockh;
 	ldlm_policy_data_t policy;
 	ldlm_mode_t mode;
-	ENTRY;
 
 	if (it->d.lustre.it_lock_handle) {
 		lockh.cookie = it->d.lustre.it_lock_handle;
@@ -1029,7 +1023,7 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
 		it->d.lustre.it_lock_mode = 0;
 	}
 
-	RETURN(!!mode);
+	return !!mode;
 }
 
 /*
@@ -1067,7 +1061,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 {
 	struct lustre_handle lockh;
 	int rc = 0;
-	ENTRY;
+
 	LASSERT(it);
 
 	CDEBUG(D_DLMTRACE, "(name: %.*s,"DFID") in obj "DFID
@@ -1087,7 +1081,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 		/* Only return failure if it was not GETATTR by cfid
 		   (from inode_revalidate) */
 		if (rc || op_data->op_namelen != 0)
-			RETURN(rc);
+			return rc;
 	}
 
 	/* lookup_it may be called only after revalidate_it has run, because
@@ -1099,22 +1093,25 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 	 * this and use the request from revalidate.  In this case, revalidate
 	 * never dropped its reference, so the refcounts are all OK */
 	if (!it_disposition(it, DISP_ENQ_COMPLETE)) {
-		struct ldlm_enqueue_info einfo =
-			{ LDLM_IBITS, it_to_lock_mode(it), cb_blocking,
-			  ldlm_completion_ast, NULL, NULL, NULL };
+		struct ldlm_enqueue_info einfo = {
+			.ei_type	= LDLM_IBITS,
+			.ei_mode	= it_to_lock_mode(it),
+			.ei_cb_bl	= cb_blocking,
+			.ei_cb_cp	= ldlm_completion_ast,
+		};
 
 		/* For case if upper layer did not alloc fid, do it now. */
 		if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
 			rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
 			if (rc < 0) {
 				CERROR("Can't alloc new fid, rc %d\n", rc);
-				RETURN(rc);
+				return rc;
 			}
 		}
 		rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh,
 				 lmm, lmmsize, NULL, extra_lock_flags);
 		if (rc < 0)
-			RETURN(rc);
+			return rc;
 	} else if (!fid_is_sane(&op_data->op_fid2) ||
 		   !(it->it_create_mode & M_CHECK_STALE)) {
 		/* DISP_ENQ_COMPLETE set means there is extra reference on
@@ -1125,7 +1122,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
 	}
 	*reqp = it->d.lustre.it_data;
 	rc = mdc_finish_intent_lock(exp, *reqp, op_data, it, &lockh);
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_intent_getattr_async_interpret(const struct lu_env *env,
@@ -1139,8 +1136,8 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env,
 	struct lookup_intent     *it;
 	struct lustre_handle     *lockh;
 	struct obd_device	*obddev;
+	struct ldlm_reply	 *lockrep;
 	__u64		     flags = LDLM_FL_HAS_INTENT;
-	ENTRY;
 
 	it    = &minfo->mi_it;
 	lockh = &minfo->mi_lockh;
@@ -1159,12 +1156,17 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env,
 		GOTO(out, rc);
 	}
 
+	lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP);
+	LASSERT(lockrep != NULL);
+
+	lockrep->lock_policy_res2 =
+		ptlrpc_status_ntoh(lockrep->lock_policy_res2);
+
 	rc = mdc_finish_enqueue(exp, req, einfo, it, lockh, rc);
 	if (rc)
 		GOTO(out, rc);
 
 	rc = mdc_finish_intent_lock(exp, req, &minfo->mi_data, it, lockh);
-	EXIT;
 
 out:
 	OBD_FREE_PTR(einfo);
@@ -1191,7 +1193,6 @@ int mdc_intent_getattr_async(struct obd_export *exp,
 				 };
 	int		      rc = 0;
 	__u64		    flags = LDLM_FL_HAS_INTENT;
-	ENTRY;
 
 	CDEBUG(D_DLMTRACE,"name: %.*s in inode "DFID", intent: %s flags %#o\n",
 	       op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1),
@@ -1200,12 +1201,12 @@ int mdc_intent_getattr_async(struct obd_export *exp,
 	fid_build_reg_res_name(&op_data->op_fid1, &res_id);
 	req = mdc_intent_getattr_pack(exp, it, op_data);
 	if (!req)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = mdc_enter_request(&obddev->u.cli);
 	if (rc != 0) {
 		ptlrpc_req_finished(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = ldlm_cli_enqueue(exp, &req, einfo, &res_id, &policy, &flags, NULL,
@@ -1213,7 +1214,7 @@ int mdc_intent_getattr_async(struct obd_export *exp,
 	if (rc < 0) {
 		mdc_exit_request(&obddev->u.cli);
 		ptlrpc_req_finished(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	CLASSERT(sizeof(*ga) <= sizeof(req->rq_async_args));
@@ -1225,5 +1226,5 @@ int mdc_intent_getattr_async(struct obd_export *exp,
 	req->rq_interpret_reply = mdc_intent_getattr_async_interpret;
 	ptlrpcd_add_req(req, PDL_POLICY_LOCAL, -1);
 
-	RETURN(0);
+	return 0;
 }
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
index 5e25a07..9f3a345 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
@@ -75,7 +75,6 @@ int mdc_resource_get_unused(struct obd_export *exp, struct lu_fid *fid,
 	struct ldlm_res_id res_id;
 	struct ldlm_resource *res;
 	int count;
-	ENTRY;
 
 	/* Return, i.e. cancel nothing, only if ELC is supported (flag in
 	 * export) but disabled through procfs (flag in NS).
@@ -84,13 +83,13 @@ int mdc_resource_get_unused(struct obd_export *exp, struct lu_fid *fid,
 	 * when we still want to cancel locks in advance and just cancel them
 	 * locally, without sending any RPC. */
 	if (exp_connect_cancelset(exp) && !ns_connect_cancelset(ns))
-		RETURN(0);
+		return 0;
 
 	fid_build_reg_res_name(fid, &res_id);
 	res = ldlm_resource_get(exp->exp_obd->obd_namespace,
 				NULL, &res_id, 0, 0);
 	if (res == NULL)
-		RETURN(0);
+		return 0;
 	LDLM_RESOURCE_ADDREF(res);
 	/* Initialize ibits lock policy. */
 	policy.l_inodebits.bits = bits;
@@ -98,7 +97,7 @@ int mdc_resource_get_unused(struct obd_export *exp, struct lu_fid *fid,
 					   mode, 0, 0, NULL);
 	LDLM_RESOURCE_DELREF(res);
 	ldlm_resource_putref(res);
-	RETURN(count);
+	return count;
 }
 
 int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
@@ -111,7 +110,6 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_device *obd = exp->exp_obd;
 	int count = 0, rc;
 	__u64 bits;
-	ENTRY;
 
 	LASSERT(op_data != NULL);
 
@@ -127,7 +125,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
 				   &RQF_MDS_REINT_SETATTR);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	if ((op_data->op_flags & (MF_SOM_CHANGE | MF_EPOCH_OPEN)) == 0)
@@ -140,7 +138,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
 	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	rpc_lock = obd->u.cli.cl_rpc_lock;
@@ -203,7 +201,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
 		obd_mod_put(*mod);
 		req->rq_commit_cb(req);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
@@ -217,7 +215,6 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_import *import = exp->exp_obd->u.cli.cl_import;
 	int generation = import->imp_generation;
 	LIST_HEAD(cancels);
-	ENTRY;
 
 	/* For case if upper layer did not alloc fid, do it now. */
 	if (!fid_is_sane(&op_data->op_fid2)) {
@@ -228,7 +225,7 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
 		rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
 		if (rc < 0) {
 			CERROR("Can't alloc new fid, rc %d\n", rc);
-			RETURN(rc);
+			return rc;
 		}
 	}
 
@@ -244,7 +241,7 @@ rebuild:
 				   &RQF_MDS_REINT_CREATE_RMT_ACL);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
@@ -255,7 +252,7 @@ rebuild:
 	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	/*
@@ -298,7 +295,7 @@ rebuild:
 			goto rebuild;
 		} else {
 			CDEBUG(D_HA, "resend cross eviction\n");
-			RETURN(-EIO);
+			return -EIO;
 		}
 	} else if (rc == 0) {
 		struct mdt_body *body;
@@ -315,7 +312,7 @@ rebuild:
 	}
 
 	*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
@@ -325,7 +322,6 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_device *obd = class_exp2obd(exp);
 	struct ptlrpc_request *req = *request;
 	int count = 0, rc;
-	ENTRY;
 
 	LASSERT(req == NULL);
 
@@ -345,7 +341,7 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
 				   &RQF_MDS_REINT_UNLINK);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
@@ -354,7 +350,7 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
 	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_unlink_pack(req, op_data);
@@ -370,7 +366,7 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
 	rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL);
 	if (rc == -ERESTARTSYS)
 		rc = 0;
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
@@ -380,7 +376,6 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_device *obd = exp->exp_obd;
 	struct ptlrpc_request *req;
 	int count = 0, rc;
-	ENTRY;
 
 	if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
 	    (fid_is_sane(&op_data->op_fid2)))
@@ -396,7 +391,7 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	mdc_set_capa_size(req, &RMF_CAPA2, op_data->op_capa2);
@@ -406,7 +401,7 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
 	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_link_pack(req, op_data);
@@ -417,7 +412,7 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
 	if (rc == -ERESTARTSYS)
 		rc = 0;
 
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
@@ -428,7 +423,6 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_device *obd = exp->exp_obd;
 	struct ptlrpc_request *req;
 	int count = 0, rc;
-	ENTRY;
 
 	if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
 	    (fid_is_sane(&op_data->op_fid1)))
@@ -455,7 +449,7 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
 				   &RQF_MDS_REINT_RENAME);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
@@ -466,7 +460,7 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
 	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (exp_connect_cancelset(exp) && req)
@@ -485,5 +479,5 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
 	if (rc == -ERESTARTSYS)
 		rc = 0;
 
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 3cf9d8d..ed3a7a0 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -65,21 +65,20 @@ int mdc_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req,
 {
 	struct lustre_capa *capa;
 	struct obd_capa *c;
-	ENTRY;
 
 	/* swabbed already in mdc_enqueue */
 	capa = req_capsule_server_get(&req->rq_pill, field);
 	if (capa == NULL)
-		RETURN(-EPROTO);
+		return -EPROTO;
 
 	c = alloc_capa(CAPA_SITE_CLIENT);
 	if (IS_ERR(c)) {
 		CDEBUG(D_INFO, "alloc capa failed!\n");
-		RETURN(PTR_ERR(c));
+		return PTR_ERR(c);
 	} else {
 		c->c_capa = *capa;
 		*oc = c;
-		RETURN(0);
+		return 0;
 	}
 }
 
@@ -109,12 +108,11 @@ static int send_getstatus(struct obd_import *imp, struct lu_fid *rootfid,
 	struct ptlrpc_request *req;
 	struct mdt_body       *body;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_GETSTATUS,
 					LUSTRE_MDS_VERSION, MDS_GETSTATUS);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_pack_body(req, NULL, NULL, 0, 0, -1, 0);
 	lustre_msg_add_flags(req->rq_reqmsg, msg_flags);
@@ -141,7 +139,6 @@ static int send_getstatus(struct obd_import *imp, struct lu_fid *rootfid,
 	       "root fid="DFID", last_committed="LPU64"\n",
 	       PFID(rootfid),
 	       lustre_msg_get_last_committed(req->rq_repmsg));
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -172,17 +169,16 @@ static int mdc_getattr_common(struct obd_export *exp,
 	struct mdt_body    *body;
 	void	       *eadata;
 	int		 rc;
-	ENTRY;
 
 	/* Request message already built. */
 	rc = ptlrpc_queue_wait(req);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	/* sanity check for the reply */
 	body = req_capsule_server_get(pill, &RMF_MDT_BODY);
 	if (body == NULL)
-		RETURN(-EPROTO);
+		return -EPROTO;
 
 	CDEBUG(D_NET, "mode: %o\n", body->mode);
 
@@ -192,7 +188,7 @@ static int mdc_getattr_common(struct obd_export *exp,
 		eadata = req_capsule_server_sized_get(pill, &RMF_MDT_MD,
 						      body->eadatasize);
 		if (eadata == NULL)
-			RETURN(-EPROTO);
+			return -EPROTO;
 	}
 
 	if (body->valid & OBD_MD_FLRMTPERM) {
@@ -202,17 +198,17 @@ static int mdc_getattr_common(struct obd_export *exp,
 		perm = req_capsule_server_swab_get(pill, &RMF_ACL,
 						lustre_swab_mdt_remote_perm);
 		if (perm == NULL)
-			RETURN(-EPROTO);
+			return -EPROTO;
 	}
 
 	if (body->valid & OBD_MD_FLMDSCAPA) {
 		struct lustre_capa *capa;
 		capa = req_capsule_server_get(pill, &RMF_CAPA1);
 		if (capa == NULL)
-			RETURN(-EPROTO);
+			return -EPROTO;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int mdc_getattr(struct obd_export *exp, struct md_op_data *op_data,
@@ -220,24 +216,23 @@ int mdc_getattr(struct obd_export *exp, struct md_op_data *op_data,
 {
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	/* Single MDS without an LMV case */
 	if (op_data->op_flags & MF_GET_MDT_IDX) {
 		op_data->op_mds = 0;
-		RETURN(0);
+		return 0;
 	}
 	*request = NULL;
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_GETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_GETATTR);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, &op_data->op_fid1, op_data->op_capa1,
@@ -257,7 +252,7 @@ int mdc_getattr(struct obd_export *exp, struct md_op_data *op_data,
 		ptlrpc_req_finished(req);
 	else
 		*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data,
@@ -265,13 +260,12 @@ int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data,
 {
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	*request = NULL;
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_MDS_GETATTR_NAME);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
@@ -280,7 +274,7 @@ int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data,
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_GETATTR_NAME);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, &op_data->op_fid1, op_data->op_capa1,
@@ -303,7 +297,7 @@ int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data,
 		ptlrpc_req_finished(req);
 	else
 		*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_is_subdir(struct obd_export *exp,
@@ -314,14 +308,12 @@ static int mdc_is_subdir(struct obd_export *exp,
 	struct ptlrpc_request  *req;
 	int		     rc;
 
-	ENTRY;
-
 	*request = NULL;
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_MDS_IS_SUBDIR, LUSTRE_MDS_VERSION,
 					MDS_IS_SUBDIR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_is_subdir_pack(req, pfid, cfid, 0);
 	ptlrpc_request_set_replen(req);
@@ -331,7 +323,7 @@ static int mdc_is_subdir(struct obd_export *exp,
 		ptlrpc_req_finished(req);
 	else
 		*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
@@ -345,12 +337,11 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
 	int   xattr_namelen = 0;
 	char *tmp;
 	int   rc;
-	ENTRY;
 
 	*request = NULL;
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), fmt);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, oc);
 	if (xattr_name) {
@@ -367,7 +358,7 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, opcode);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (opcode == MDS_REINT) {
@@ -377,12 +368,8 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
 			 sizeof(struct mdt_rec_reint));
 		rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
 		rec->sx_opcode = REINT_SETXATTR;
-		/* TODO:
-		 *  cfs_curproc_fs{u,g}id() should replace
-		 *  current->fs{u,g}id for portability.
-		 */
-		rec->sx_fsuid  = current_fsuid();
-		rec->sx_fsgid  = current_fsgid();
+		rec->sx_fsuid  = from_kuid(&init_user_ns, current_fsuid());
+		rec->sx_fsgid  = from_kgid(&init_user_ns, current_fsgid());
 		rec->sx_cap    = cfs_curproc_cap_pack();
 		rec->sx_suppgid1 = suppgid;
 		rec->sx_suppgid2 = -1;
@@ -424,7 +411,7 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
 		ptlrpc_req_finished(req);
 	else
 		*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_setxattr(struct obd_export *exp, const struct lu_fid *fid,
@@ -457,32 +444,31 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md)
 	struct posix_acl       *acl;
 	void		   *buf;
 	int		     rc;
-	ENTRY;
 
 	if (!body->aclsize)
-		RETURN(0);
+		return 0;
 
 	buf = req_capsule_server_sized_get(pill, &RMF_ACL, body->aclsize);
 
 	if (!buf)
-		RETURN(-EPROTO);
+		return -EPROTO;
 
 	acl = posix_acl_from_xattr(&init_user_ns, buf, body->aclsize);
 	if (IS_ERR(acl)) {
 		rc = PTR_ERR(acl);
 		CERROR("convert xattr to acl: %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = posix_acl_valid(acl);
 	if (rc) {
 		CERROR("validate acl: %d\n", rc);
 		posix_acl_release(acl);
-		RETURN(rc);
+		return rc;
 	}
 
 	md->posix_acl = acl;
-	RETURN(0);
+	return 0;
 }
 #else
 #define mdc_unpack_acl(req, md) 0
@@ -494,7 +480,6 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
 {
 	struct req_capsule *pill = &req->rq_pill;
 	int rc;
-	ENTRY;
 
 	LASSERT(md);
 	memset(md, 0, sizeof(*md));
@@ -546,7 +531,7 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
 		if (md->body->eadatasize == 0) {
 			CDEBUG(D_INFO, "OBD_MD_FLDIREA is set, "
 			       "but eadatasize 0\n");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 		if (md->body->valid & OBD_MD_MEA) {
 			lmvsize = md->body->eadatasize;
@@ -611,7 +596,6 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req,
 		md->oss_capa = oc;
 	}
 
-	EXIT;
 out:
 	if (rc) {
 		if (md->oss_capa) {
@@ -633,8 +617,7 @@ out:
 
 int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
 {
-	ENTRY;
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -648,12 +631,10 @@ void mdc_replay_open(struct ptlrpc_request *req)
 	struct obd_client_handle *och;
 	struct lustre_handle old;
 	struct mdt_body *body;
-	ENTRY;
 
 	if (mod == NULL) {
 		DEBUG_REQ(D_ERROR, req,
 			  "Can't properly replay without open data.");
-		EXIT;
 		return;
 	}
 
@@ -687,7 +668,6 @@ void mdc_replay_open(struct ptlrpc_request *req)
 		DEBUG_REQ(D_HA, close_req, "updating close body with new fh");
 		epoch->handle = body->handle;
 	}
-	EXIT;
 }
 
 void mdc_commit_open(struct ptlrpc_request *req)
@@ -726,10 +706,9 @@ int mdc_set_open_replay_data(struct obd_export *exp,
 	struct mdt_rec_create *rec;
 	struct mdt_body       *body;
 	struct obd_import     *imp = open_req->rq_import;
-	ENTRY;
 
 	if (!open_req->rq_replay)
-		RETURN(0);
+		return 0;
 
 	rec = req_capsule_client_get(&open_req->rq_pill, &RMF_REC_REINT);
 	body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY);
@@ -744,7 +723,7 @@ int mdc_set_open_replay_data(struct obd_export *exp,
 		if (mod == NULL) {
 			DEBUG_REQ(D_ERROR, open_req,
 				  "Can't allocate md_open_data");
-			RETURN(0);
+			return 0;
 		}
 
 		/**
@@ -776,21 +755,20 @@ int mdc_set_open_replay_data(struct obd_export *exp,
 	}
 
 	DEBUG_REQ(D_RPCTRACE, open_req, "Set up open replay data");
-	RETURN(0);
+	return 0;
 }
 
 int mdc_clear_open_replay_data(struct obd_export *exp,
 			       struct obd_client_handle *och)
 {
 	struct md_open_data *mod = och->och_mod;
-	ENTRY;
 
 	/**
 	 * It is possible to not have \var mod in a case of eviction between
 	 * lookup and ll_file_open().
 	 **/
 	if (mod == NULL)
-		RETURN(0);
+		return 0;
 
 	LASSERT(mod != LP_POISON);
 
@@ -798,7 +776,7 @@ int mdc_clear_open_replay_data(struct obd_export *exp,
 	och->och_mod = NULL;
 	obd_mod_put(mod);
 
-	RETURN(0);
+	return 0;
 }
 
 /* Prepares the request for the replay by the given reply */
@@ -823,19 +801,18 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_device     *obd = class_exp2obd(exp);
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	*request = NULL;
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_CLOSE);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_CLOSE);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	/* To avoid a livelock (bug 7034), we need to send CLOSE RPCs to a
@@ -916,7 +893,7 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
 	}
 	*request = req;
 	mdc_close_handle_reply(req, op_data, rc);
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data,
@@ -925,18 +902,17 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data,
 	struct obd_device     *obd = class_exp2obd(exp);
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_MDS_DONE_WRITING);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_DONE_WRITING);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (mod != NULL) {
@@ -983,7 +959,7 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data,
 
 	mdc_close_handle_reply(req, op_data, rc);
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -997,7 +973,6 @@ int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data,
 	int		      resends = 0;
 	struct l_wait_info       lwi;
 	int		      rc;
-	ENTRY;
 
 	*request = NULL;
 	init_waitqueue_head(&waitq);
@@ -1005,14 +980,14 @@ int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data,
 restart_bulk:
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_READPAGE);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_READPAGE);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	req->rq_request_portal = MDS_READPAGE_PORTAL;
@@ -1022,7 +997,7 @@ restart_bulk:
 				    MDS_BULK_PORTAL);
 	if (desc == NULL) {
 		ptlrpc_request_free(req);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* NB req now owns desc and will free it when it gets freed */
@@ -1038,12 +1013,12 @@ restart_bulk:
 	if (rc) {
 		ptlrpc_req_finished(req);
 		if (rc != -ETIMEDOUT)
-			RETURN(rc);
+			return rc;
 
 		resends++;
 		if (!client_should_resend(resends, &exp->exp_obd->u.cli)) {
 			CERROR("too many resend retries, returning error\n");
-			RETURN(-EIO);
+			return -EIO;
 		}
 		lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(resends), NULL, NULL, NULL);
 		l_wait_event(waitq, 0, &lwi);
@@ -1055,7 +1030,7 @@ restart_bulk:
 					  req->rq_bulk->bd_nob_transferred);
 	if (rc < 0) {
 		ptlrpc_req_finished(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK) {
@@ -1063,11 +1038,11 @@ restart_bulk:
 			req->rq_bulk->bd_nob_transferred,
 			PAGE_CACHE_SIZE * op_data->op_npages);
 		ptlrpc_req_finished(req);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	*request = req;
-	RETURN(0);
+	return 0;
 }
 
 static int mdc_statfs(const struct lu_env *env,
@@ -1079,7 +1054,6 @@ static int mdc_statfs(const struct lu_env *env,
 	struct obd_statfs     *msfs;
 	struct obd_import     *imp = NULL;
 	int		    rc;
-	ENTRY;
 
 	/*
 	 * Since the request might also come from lprocfs, so we need
@@ -1090,7 +1064,7 @@ static int mdc_statfs(const struct lu_env *env,
 		imp = class_import_get(obd->u.cli.cl_import);
 	up_read(&obd->u.cli.cl_sem);
 	if (!imp)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_STATFS,
 					LUSTRE_MDS_VERSION, MDS_STATFS);
@@ -1118,7 +1092,6 @@ static int mdc_statfs(const struct lu_env *env,
 		GOTO(out, rc = -EPROTO);
 
 	*osfs = *msfs;
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 output:
@@ -1133,15 +1106,15 @@ static int mdc_ioc_fid2path(struct obd_export *exp, struct getinfo_fid2path *gf)
 	int rc;
 
 	if (gf->gf_pathlen > PATH_MAX)
-		RETURN(-ENAMETOOLONG);
+		return -ENAMETOOLONG;
 	if (gf->gf_pathlen < 2)
-		RETURN(-EOVERFLOW);
+		return -EOVERFLOW;
 
 	/* Key is KEY_FID2PATH + getinfo_fid2path description */
 	keylen = cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*gf);
 	OBD_ALLOC(key, keylen);
 	if (key == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
 	memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
 
@@ -1178,7 +1151,6 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp,
 	struct hsm_progress_kernel	*req_hpk;
 	struct ptlrpc_request		*req;
 	int				 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_PROGRESS,
 					LUSTRE_MDS_VERSION, MDS_HSM_PROGRESS);
@@ -1193,6 +1165,7 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp,
 		GOTO(out, rc = -EPROTO);
 
 	*req_hpk = *hpk;
+	req_hpk->hpk_errval = lustre_errno_hton(hpk->hpk_errval);
 
 	ptlrpc_request_set_replen(req);
 
@@ -1208,7 +1181,6 @@ static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archives)
 	__u32			*archive_mask;
 	struct ptlrpc_request	*req;
 	int			 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_CT_REGISTER,
 					LUSTRE_MDS_VERSION,
@@ -1242,19 +1214,18 @@ static int mdc_ioc_hsm_current_action(struct obd_export *exp,
 	struct hsm_current_action	*req_hca;
 	struct ptlrpc_request		*req;
 	int				 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_MDS_HSM_ACTION);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_HSM_ACTION);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, &op_data->op_fid1, op_data->op_capa1,
@@ -1273,7 +1244,6 @@ static int mdc_ioc_hsm_current_action(struct obd_export *exp,
 
 	*hca = *req_hca;
 
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -1283,7 +1253,6 @@ static int mdc_ioc_hsm_ct_unregister(struct obd_import *imp)
 {
 	struct ptlrpc_request	*req;
 	int			 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_CT_UNREGISTER,
 					LUSTRE_MDS_VERSION,
@@ -1309,19 +1278,18 @@ static int mdc_ioc_hsm_state_get(struct obd_export *exp,
 	struct hsm_user_state	*req_hus;
 	struct ptlrpc_request	*req;
 	int			 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_MDS_HSM_STATE_GET);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_HSM_STATE_GET);
 	if (rc != 0) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, &op_data->op_fid1, op_data->op_capa1,
@@ -1339,7 +1307,6 @@ static int mdc_ioc_hsm_state_get(struct obd_export *exp,
 
 	*hus = *req_hus;
 
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -1352,19 +1319,18 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp,
 	struct hsm_state_set	*req_hss;
 	struct ptlrpc_request	*req;
 	int			 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 				   &RQF_MDS_HSM_STATE_SET);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_HSM_STATE_SET);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, &op_data->op_fid1, op_data->op_capa1,
@@ -1381,7 +1347,6 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp,
 	rc = mdc_queue_wait(req);
 	GOTO(out, rc);
 
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -1396,7 +1361,6 @@ static int mdc_ioc_hsm_request(struct obd_export *exp,
 	struct hsm_user_item	*req_hui;
 	char			*req_opaque;
 	int			 rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(imp, &RQF_MDS_HSM_REQUEST);
 	if (req == NULL)
@@ -1411,7 +1375,7 @@ static int mdc_ioc_hsm_request(struct obd_export *exp,
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_HSM_REQUEST);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, NULL, NULL, OBD_MD_FLRMTPERM, 0, 0, 0);
@@ -1476,21 +1440,20 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh,
 	struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr;
 	struct kuc_hdr *lh;
 	int len, rc;
-	ENTRY;
 
 	if (rec->cr_hdr.lrh_type != CHANGELOG_REC) {
 		rc = -EINVAL;
 		CERROR("%s: not a changelog rec %x/%d: rc = %d\n",
 		       cs->cs_obd->obd_name, rec->cr_hdr.lrh_type,
 		       rec->cr.cr_type, rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (rec->cr.cr_index < cs->cs_startrec) {
 		/* Skip entries earlier than what we are interested in */
 		CDEBUG(D_CHANGELOG, "rec="LPU64" start="LPU64"\n",
 		       rec->cr.cr_index, cs->cs_startrec);
-		RETURN(0);
+		return 0;
 	}
 
 	CDEBUG(D_CHANGELOG, LPU64" %02d%-5s "LPU64" 0x%x t="DFID" p="DFID
@@ -1509,7 +1472,7 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh,
 	rc = libcfs_kkuc_msg_put(cs->cs_fp, lh);
 	CDEBUG(D_CHANGELOG, "kucmsg fp %p len %d rc %d\n", cs->cs_fp, len,rc);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_changelog_send_thread(void *csdata)
@@ -1608,13 +1571,12 @@ static int mdc_quotacheck(struct obd_device *unused, struct obd_export *exp,
 	struct ptlrpc_request   *req;
 	struct obd_quotactl     *body;
 	int		      rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_MDS_QUOTACHECK, LUSTRE_MDS_VERSION,
 					MDS_QUOTACHECK);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
 	*body = *oqctl;
@@ -1628,7 +1590,7 @@ static int mdc_quotacheck(struct obd_device *unused, struct obd_export *exp,
 	if (rc)
 		cli->cl_qchk_stat = rc;
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_quota_poll_check(struct obd_export *exp,
@@ -1636,7 +1598,6 @@ static int mdc_quota_poll_check(struct obd_export *exp,
 {
 	struct client_obd *cli = &exp->exp_obd->u.cli;
 	int rc;
-	ENTRY;
 
 	qchk->obd_uuid = cli->cl_target_uuid;
 	memcpy(qchk->obd_type, LUSTRE_MDS_NAME, strlen(LUSTRE_MDS_NAME));
@@ -1645,7 +1606,7 @@ static int mdc_quota_poll_check(struct obd_export *exp,
 	/* the client is not the previous one */
 	if (rc == CL_NOT_QUOTACHECKED)
 		rc = -EINTR;
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
@@ -1654,13 +1615,12 @@ static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
 	struct ptlrpc_request   *req;
 	struct obd_quotactl     *oqc;
 	int		      rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_MDS_QUOTACTL, LUSTRE_MDS_VERSION,
 					MDS_QUOTACTL);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
 	*oqc = *oqctl;
@@ -1682,7 +1642,7 @@ static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
 	}
 	ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_ioc_swap_layouts(struct obd_export *exp,
@@ -1692,7 +1652,6 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp,
 	struct ptlrpc_request	*req;
 	int			 rc, count;
 	struct mdc_swap_layouts *msl, *payload;
-	ENTRY;
 
 	msl = op_data->op_data;
 
@@ -1711,7 +1670,7 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp,
 				   &RQF_MDS_SWAP_LAYOUTS);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
@@ -1720,7 +1679,7 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp,
 	rc = mdc_prep_elc_req(exp, req, MDS_SWAP_LAYOUTS, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_swap_layouts_pack(req, op_data);
@@ -1735,7 +1694,6 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp,
 	rc = ptlrpc_queue_wait(req);
 	if (rc)
 		GOTO(out, rc);
-	EXIT;
 
 out:
 	ptlrpc_req_finished(req);
@@ -1750,7 +1708,6 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 	struct obd_import *imp = obd->u.cli.cl_import;
 	struct llog_ctxt *ctxt;
 	int rc;
-	ENTRY;
 
 	if (!try_module_get(THIS_MODULE)) {
 		CERROR("Can't get module. Is it alive?");
@@ -1774,6 +1731,9 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO(out, rc);
 	case LL_IOC_HSM_CT_START:
 		rc = mdc_ioc_hsm_ct_start(exp, karg);
+		/* ignore if it was already registered on this MDS. */
+		if (rc == -EEXIST)
+			rc = 0;
 		GOTO(out, rc);
 	case LL_IOC_HSM_PROGRESS:
 		rc = mdc_ioc_hsm_progress(exp, karg);
@@ -1855,7 +1815,7 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
 		OBD_ALLOC_PTR(oqctl);
 		if (!oqctl)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		QCTL_COPY(oqctl, qctl);
 		rc = obd_quotactl(exp, oqctl);
@@ -1897,11 +1857,10 @@ int mdc_get_info_rpc(struct obd_export *exp,
 	struct ptlrpc_request  *req;
 	char		   *tmp;
 	int		     rc = -EINVAL;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(imp, &RQF_MDS_GET_INFO);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req_capsule_set_size(&req->rq_pill, &RMF_GETINFO_KEY,
 			     RCL_CLIENT, keylen);
@@ -1911,7 +1870,7 @@ int mdc_get_info_rpc(struct obd_export *exp,
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_GET_INFO);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	tmp = req_capsule_client_get(&req->rq_pill, &RMF_GETINFO_KEY);
@@ -1936,7 +1895,7 @@ int mdc_get_info_rpc(struct obd_export *exp,
 	}
 	ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 static void lustre_swab_hai(struct hsm_action_item *h)
@@ -1991,19 +1950,10 @@ static int mdc_ioc_hsm_ct_start(struct obd_export *exp,
 	       lk->lk_uid, lk->lk_group, lk->lk_flags);
 
 	if (lk->lk_flags & LK_FLG_STOP) {
-		rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group);
 		/* Unregister with the coordinator */
-		if (rc == 0)
-			rc = mdc_ioc_hsm_ct_unregister(imp);
+		rc = mdc_ioc_hsm_ct_unregister(imp);
 	} else {
-		struct file *fp = fget(lk->lk_wfd);
-
-		rc = libcfs_kkuc_group_add(fp, lk->lk_uid, lk->lk_group,
-					   lk->lk_data);
-		if (rc && fp)
-			fput(fp);
-		if (rc == 0)
-			rc = mdc_ioc_hsm_ct_register(imp, archive);
+		rc = mdc_ioc_hsm_ct_register(imp, archive);
 	}
 
 	return rc;
@@ -2019,19 +1969,18 @@ static int mdc_hsm_copytool_send(int len, void *val)
 	struct kuc_hdr		*lh = (struct kuc_hdr *)val;
 	struct hsm_action_list	*hal = (struct hsm_action_list *)(lh + 1);
 	int			 rc;
-	ENTRY;
 
 	if (len < sizeof(*lh) + sizeof(*hal)) {
 		CERROR("Short HSM message %d < %d\n", len,
 		       (int) (sizeof(*lh) + sizeof(*hal)));
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 	if (lh->kuc_magic == __swab16(KUC_MAGIC)) {
 		lustre_swab_kuch(lh);
 		lustre_swab_hal(hal);
 	} else if (lh->kuc_magic != KUC_MAGIC) {
 		CERROR("Bad magic %x!=%x\n", lh->kuc_magic, KUC_MAGIC);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	CDEBUG(D_HSM, " Received message mg=%x t=%d m=%d l=%d actions=%d "
@@ -2042,7 +1991,7 @@ static int mdc_hsm_copytool_send(int len, void *val)
 	/* Broadcast to HSM listeners */
 	rc = libcfs_kkuc_group_put(KUC_GRP_HSM, lh);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2084,11 +2033,10 @@ int mdc_set_info_async(const struct lu_env *env,
 {
 	struct obd_import	*imp = class_exp2cliimp(exp);
 	int			 rc;
-	ENTRY;
 
 	if (KEY_IS(KEY_READ_ONLY)) {
 		if (vallen != sizeof(int))
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		spin_lock(&imp->imp_lock);
 		if (*((int *)val)) {
@@ -2104,15 +2052,15 @@ int mdc_set_info_async(const struct lu_env *env,
 
 		rc = do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION,
 				       keylen, key, vallen, val, set);
-		RETURN(rc);
+		return rc;
 	}
 	if (KEY_IS(KEY_SPTLRPC_CONF)) {
 		sptlrpc_conf_client_adapt(exp->exp_obd);
-		RETURN(0);
+		return 0;
 	}
 	if (KEY_IS(KEY_FLUSH_CTX)) {
 		sptlrpc_import_flush_my_ctx(imp);
-		RETURN(0);
+		return 0;
 	}
 	if (KEY_IS(KEY_MDS_CONN)) {
 		/* mds-mds import */
@@ -2121,20 +2069,20 @@ int mdc_set_info_async(const struct lu_env *env,
 		spin_unlock(&imp->imp_lock);
 		imp->imp_client->cli_request_portal = MDS_MDS_PORTAL;
 		CDEBUG(D_OTHER, "%s: timeout / 2\n", exp->exp_obd->obd_name);
-		RETURN(0);
+		return 0;
 	}
 	if (KEY_IS(KEY_CHANGELOG_CLEAR)) {
 		rc = do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION,
 				       keylen, key, vallen, val, set);
-		RETURN(rc);
+		return rc;
 	}
 	if (KEY_IS(KEY_HSM_COPYTOOL_SEND)) {
 		rc = mdc_hsm_copytool_send(vallen, val);
-		RETURN(rc);
+		return rc;
 	}
 
 	CERROR("Unknown key %s\n", (char *)key);
-	RETURN(-EINVAL);
+	return -EINVAL;
 }
 
 int mdc_get_info(const struct lu_env *env, struct obd_export *exp,
@@ -2147,30 +2095,30 @@ int mdc_get_info(const struct lu_env *env, struct obd_export *exp,
 		int mdsize, *max_easize;
 
 		if (*vallen != sizeof(int))
-			RETURN(-EINVAL);
+			return -EINVAL;
 		mdsize = *(int*)val;
 		if (mdsize > exp->exp_obd->u.cli.cl_max_mds_easize)
 			exp->exp_obd->u.cli.cl_max_mds_easize = mdsize;
 		max_easize = val;
 		*max_easize = exp->exp_obd->u.cli.cl_max_mds_easize;
-		RETURN(0);
+		return 0;
 	} else if (KEY_IS(KEY_CONN_DATA)) {
 		struct obd_import *imp = class_exp2cliimp(exp);
 		struct obd_connect_data *data = val;
 
 		if (*vallen != sizeof(*data))
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		*data = imp->imp_connect_data;
-		RETURN(0);
+		return 0;
 	} else if (KEY_IS(KEY_TGT_COUNT)) {
 		*((int *)val) = 1;
-		RETURN(0);
+		return 0;
 	}
 
 	rc = mdc_get_info_rpc(exp, keylen, key, *vallen, val);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_pin(struct obd_export *exp, const struct lu_fid *fid,
@@ -2180,18 +2128,17 @@ static int mdc_pin(struct obd_export *exp, const struct lu_fid *fid,
 	struct ptlrpc_request *req;
 	struct mdt_body       *body;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_PIN);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, oc);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_PIN);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, fid, oc, 0, 0, -1, flags);
@@ -2220,11 +2167,11 @@ static int mdc_pin(struct obd_export *exp, const struct lu_fid *fid,
 	}
 	handle->och_mod->mod_open_req = req; /* will be dropped by unpin */
 
-	RETURN(0);
+	return 0;
 
 err_out:
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_unpin(struct obd_export *exp, struct obd_client_handle *handle,
@@ -2233,12 +2180,11 @@ static int mdc_unpin(struct obd_export *exp, struct obd_client_handle *handle,
 	struct ptlrpc_request *req;
 	struct mdt_body       *body;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_UNPIN,
 					LUSTRE_MDS_VERSION, MDS_UNPIN);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	body = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY);
 	body->handle = handle->och_fh;
@@ -2257,7 +2203,7 @@ static int mdc_unpin(struct obd_export *exp, struct obd_client_handle *handle,
 	ptlrpc_req_finished(handle->och_mod->mod_open_req);
 
 	obd_mod_put(handle->och_mod);
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_sync(struct obd_export *exp, const struct lu_fid *fid,
@@ -2265,19 +2211,18 @@ int mdc_sync(struct obd_export *exp, const struct lu_fid *fid,
 {
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	*request = NULL;
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_SYNC);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, oc);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_SYNC);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, fid, oc, 0, 0, -1, 0);
@@ -2289,7 +2234,7 @@ int mdc_sync(struct obd_export *exp, const struct lu_fid *fid,
 		ptlrpc_req_finished(req);
 	else
 		*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
@@ -2328,7 +2273,7 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
 	}
 	case IMP_EVENT_ACTIVE:
 		rc = obd_notify_observer(obd, obd, OBD_NOTIFY_ACTIVE, NULL);
-		/* restore re-establish kuc registration after reconnecting */
+		/* redo the kuc registration after reconnecting */
 		if (rc == 0)
 			rc = mdc_kuc_reregister(imp);
 		break;
@@ -2342,7 +2287,7 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
 		CERROR("Unknown import event %x\n", event);
 		LBUG();
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
@@ -2350,8 +2295,8 @@ int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid,
 {
 	struct client_obd *cli = &exp->exp_obd->u.cli;
 	struct lu_client_seq *seq = cli->cl_seq;
-	ENTRY;
-	RETURN(seq_client_alloc_fid(NULL, seq, fid));
+
+	return seq_client_alloc_fid(NULL, seq, fid);
 }
 
 struct obd_uuid *mdc_get_uuid(struct obd_export *exp) {
@@ -2367,15 +2312,15 @@ struct obd_uuid *mdc_get_uuid(struct obd_export *exp) {
 static int mdc_cancel_for_recovery(struct ldlm_lock *lock)
 {
 	if (lock->l_resource->lr_type != LDLM_IBITS)
-		RETURN(0);
+		return 0;
 
 	/* FIXME: if we ever get into a situation where there are too many
 	 * opened files with open locks on a single node, then we really
 	 * should replay these open locks to reget it */
 	if (lock->l_policy_data.l_inodebits.bits & MDS_INODELOCK_OPEN)
-		RETURN(0);
+		return 0;
 
-	RETURN(1);
+	return 1;
 }
 
 static int mdc_resource_inode_free(struct ldlm_resource *res)
@@ -2387,7 +2332,7 @@ static int mdc_resource_inode_free(struct ldlm_resource *res)
 }
 
 struct ldlm_valblock_ops inode_lvbo = {
-	lvbo_free: mdc_resource_inode_free
+	.lvbo_free = mdc_resource_inode_free,
 };
 
 static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
@@ -2395,11 +2340,10 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 	struct client_obd *cli = &obd->u.cli;
 	struct lprocfs_static_vars lvars = { 0 };
 	int rc;
-	ENTRY;
 
 	OBD_ALLOC(cli->cl_rpc_lock, sizeof (*cli->cl_rpc_lock));
 	if (!cli->cl_rpc_lock)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	mdc_init_rpc_lock(cli->cl_rpc_lock);
 
 	ptlrpcd_addref();
@@ -2427,14 +2371,14 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 		CERROR("failed to setup llogging subsystems\n");
 	}
 
-	RETURN(rc);
+	return rc;
 
 err_close_lock:
 	OBD_FREE(cli->cl_close_lock, sizeof (*cli->cl_close_lock));
 err_rpc_lock:
 	OBD_FREE(cli->cl_rpc_lock, sizeof (*cli->cl_rpc_lock));
 	ptlrpcd_decref();
-	RETURN(rc);
+	return rc;
 }
 
 /* Initialize the default and maximum LOV EA and cookie sizes.  This allows
@@ -2446,7 +2390,6 @@ static int mdc_init_ea_size(struct obd_export *exp, int easize,
 {
 	struct obd_device *obd = exp->exp_obd;
 	struct client_obd *cli = &obd->u.cli;
-	ENTRY;
 
 	if (cli->cl_max_mds_easize < easize)
 		cli->cl_max_mds_easize = easize;
@@ -2457,13 +2400,12 @@ static int mdc_init_ea_size(struct obd_export *exp, int easize,
 	if (cli->cl_max_mds_cookiesize < cookiesize)
 		cli->cl_max_mds_cookiesize = cookiesize;
 
-	RETURN(0);
+	return 0;
 }
 
 static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 {
 	int rc = 0;
-	ENTRY;
 
 	switch (stage) {
 	case OBD_CLEANUP_EARLY:
@@ -2482,7 +2424,7 @@ static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 			CERROR("failed to cleanup llogging subsystems\n");
 		break;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_cleanup(struct obd_device *obd)
@@ -2504,33 +2446,29 @@ static int mdc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
 	struct llog_ctxt	*ctxt;
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(olg == &obd->obd_olg);
 
 	rc = llog_setup(NULL, obd, olg, LLOG_CHANGELOG_REPL_CTXT, tgt,
 			&llog_client_ops);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	ctxt = llog_group_get_ctxt(olg, LLOG_CHANGELOG_REPL_CTXT);
 	llog_initiator_connect(ctxt);
 	llog_ctxt_put(ctxt);
 
-	RETURN(0);
+	return 0;
 }
 
 static int mdc_llog_finish(struct obd_device *obd, int count)
 {
 	struct llog_ctxt *ctxt;
 
-	ENTRY;
-
 	ctxt = llog_get_context(obd, LLOG_CHANGELOG_REPL_CTXT);
 	if (ctxt)
 		llog_cleanup(NULL, ctxt);
 
-	RETURN(0);
+	return 0;
 }
 
 static int mdc_process_config(struct obd_device *obd, obd_count len, void *buf)
@@ -2559,21 +2497,20 @@ int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
 {
 	struct ptlrpc_request  *req;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(client_is_remote(exp));
 
 	*request = NULL;
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_GETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	mdc_set_capa_size(req, &RMF_CAPA1, oc);
 
 	rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_GETATTR);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	mdc_pack_body(req, fid, oc, OBD_MD_FLRMTPERM, 0, suppgid, 0);
@@ -2588,7 +2525,7 @@ int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
 		ptlrpc_req_finished(req);
 	else
 		*request = req;
-	RETURN(rc);
+	return rc;
 }
 
 static int mdc_interpret_renew_capa(const struct lu_env *env,
@@ -2598,7 +2535,6 @@ static int mdc_interpret_renew_capa(const struct lu_env *env,
 	struct mdc_renew_capa_args *ra = args;
 	struct mdt_body *body = NULL;
 	struct lustre_capa *capa;
-	ENTRY;
 
 	if (status)
 		GOTO(out, capa = ERR_PTR(status));
@@ -2613,7 +2549,6 @@ static int mdc_interpret_renew_capa(const struct lu_env *env,
 	capa = req_capsule_server_get(&req->rq_pill, &RMF_CAPA2);
 	if (!capa)
 		GOTO(out, capa = ERR_PTR(-EFAULT));
-	EXIT;
 out:
 	ra->ra_cb(ra->ra_oc, capa);
 	return 0;
@@ -2624,12 +2559,11 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc,
 {
 	struct ptlrpc_request *req;
 	struct mdc_renew_capa_args *ra;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_GETATTR,
 					LUSTRE_MDS_VERSION, MDS_GETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* NB, OBD_MD_FLOSSCAPA is set here, but it doesn't necessarily mean the
 	 * capa to renew is oss capa.
@@ -2643,7 +2577,7 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc,
 	ra->ra_cb = cb;
 	req->rq_interpret_reply = mdc_interpret_renew_capa;
 	ptlrpcd_add_req(req, PDL_POLICY_LOCAL, -1);
-	RETURN(0);
+	return 0;
 }
 
 static int mdc_connect(const struct lu_env *env,
@@ -2737,7 +2671,7 @@ int __init mdc_init(void)
 
 	rc = class_register_type(&mdc_obd_ops, &mdc_md_ops, lvars.module_vars,
 				 LUSTRE_MDC_NAME, NULL);
-	RETURN(rc);
+	return rc;
 }
 
 static void /*__exit*/ mdc_exit(void)
diff --git a/drivers/staging/lustre/lustre/mgc/libmgc.c b/drivers/staging/lustre/lustre/mgc/libmgc.c
index 442146c..7b4947c 100644
--- a/drivers/staging/lustre/lustre/mgc/libmgc.c
+++ b/drivers/staging/lustre/lustre/mgc/libmgc.c
@@ -56,7 +56,6 @@
 static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
 	int rc;
-	ENTRY;
 
 	ptlrpcd_addref();
 
@@ -73,19 +72,18 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 		GOTO(err_cleanup, rc);
 	}
 
-	RETURN(rc);
+	return rc;
 
 err_cleanup:
 	client_obd_cleanup(obd);
 err_decref:
 	ptlrpcd_decref();
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 {
 	int rc = 0;
-	ENTRY;
 
 	switch (stage) {
 	case OBD_CLEANUP_EARLY:
@@ -96,21 +94,20 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 			CERROR("failed to cleanup llogging subsystems\n");
 		break;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_cleanup(struct obd_device *obd)
 {
 	struct client_obd *cli = &obd->u.cli;
 	int rc;
-	ENTRY;
 
 	LASSERT(cli->cl_mgc_vfsmnt == NULL);
 
 	ptlrpcd_decref();
 
 	rc = client_obd_cleanup(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
@@ -118,32 +115,30 @@ static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
 {
 	struct llog_ctxt *ctxt;
 	int rc;
-	ENTRY;
 
 	LASSERT(olg == &obd->obd_olg);
 	rc = llog_setup(NULL, obd, olg, LLOG_CONFIG_REPL_CTXT, tgt,
 			&llog_client_ops);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	ctxt = llog_group_get_ctxt(olg, LLOG_CONFIG_REPL_CTXT);
 	llog_initiator_connect(ctxt);
 	llog_ctxt_put(ctxt);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_llog_finish(struct obd_device *obd, int count)
 {
 	struct llog_ctxt *ctxt;
 
-	ENTRY;
 
 	ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
 	if (ctxt)
 		llog_cleanup(NULL, ctxt);
 
-	RETURN(0);
+	return 0;
 }
 
 struct obd_ops mgc_obd_ops = {
diff --git a/drivers/staging/lustre/lustre/mgc/lproc_mgc.c b/drivers/staging/lustre/lustre/mgc/lproc_mgc.c
index 1105eaa..ebecec2 100644
--- a/drivers/staging/lustre/lustre/mgc/lproc_mgc.c
+++ b/drivers/staging/lustre/lustre/mgc/lproc_mgc.c
@@ -35,7 +35,6 @@
  */
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/version.h>
 #include <linux/vfs.h>
 #include <obd_class.h>
 #include <lprocfs_status.h>
diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c
index c6c84d9..12a9ede 100644
--- a/drivers/staging/lustre/lustre/mgc/mgc_request.c
+++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c
@@ -118,19 +118,16 @@ static DEFINE_SPINLOCK(config_list_lock);
 /* Take a reference to a config log */
 static int config_log_get(struct config_llog_data *cld)
 {
-	ENTRY;
 	atomic_inc(&cld->cld_refcount);
 	CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname,
 	       atomic_read(&cld->cld_refcount));
-	RETURN(0);
+	return 0;
 }
 
 /* Drop a reference to a config log.  When no longer referenced,
    we can free the config log data */
 static void config_log_put(struct config_llog_data *cld)
 {
-	ENTRY;
-
 	CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname,
 	       atomic_read(&cld->cld_refcount));
 	LASSERT(atomic_read(&cld->cld_refcount) > 0);
@@ -152,8 +149,6 @@ static void config_log_put(struct config_llog_data *cld)
 		class_export_put(cld->cld_mgcexp);
 		OBD_FREE(cld, sizeof(*cld) + strlen(cld->cld_logname) + 1);
 	}
-
-	EXIT;
 }
 
 /* Find a config log by name */
@@ -164,7 +159,6 @@ struct config_llog_data *config_log_find(char *logname,
 	struct config_llog_data *cld;
 	struct config_llog_data *found = NULL;
 	void *		   instance;
-	ENTRY;
 
 	LASSERT(logname != NULL);
 
@@ -186,7 +180,7 @@ struct config_llog_data *config_log_find(char *logname,
 		LASSERT(found->cld_stopping == 0 || cld_is_sptlrpc(found) == 0);
 	}
 	spin_unlock(&config_list_lock);
-	RETURN(found);
+	return found;
 }
 
 static
@@ -198,14 +192,13 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd,
 {
 	struct config_llog_data *cld;
 	int		      rc;
-	ENTRY;
 
 	CDEBUG(D_MGC, "do adding config log %s:%p\n", logname,
 	       cfg ? cfg->cfg_instance : 0);
 
 	OBD_ALLOC(cld, sizeof(*cld) + strlen(logname) + 1);
 	if (!cld)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	strcpy(cld->cld_logname, logname);
 	if (cfg)
@@ -235,7 +228,7 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd,
 
 	if (rc) {
 		config_log_put(cld);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	if (cld_is_sptlrpc(cld)) {
@@ -244,7 +237,7 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd,
 			CERROR("failed processing sptlrpc log: %d\n", rc);
 	}
 
-	RETURN(cld);
+	return cld;
 }
 
 static struct config_llog_data *config_recover_log_add(struct obd_device *obd,
@@ -296,7 +289,6 @@ static int config_log_add(struct obd_device *obd, char *logname,
 	struct config_llog_data *sptlrpc_cld;
 	char		     seclogname[32];
 	char		    *ptr;
-	ENTRY;
 
 	CDEBUG(D_MGC, "adding config log %s:%p\n", logname, cfg->cfg_instance);
 
@@ -307,7 +299,7 @@ static int config_log_add(struct obd_device *obd, char *logname,
 	ptr = strrchr(logname, '-');
 	if (ptr == NULL || ptr - logname > 8) {
 		CERROR("logname %s is too long\n", logname);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	memcpy(seclogname, logname, ptr - logname);
@@ -319,7 +311,7 @@ static int config_log_add(struct obd_device *obd, char *logname,
 						CONFIG_T_SPTLRPC, NULL, NULL);
 		if (IS_ERR(sptlrpc_cld)) {
 			CERROR("can't create sptlrpc log: %s\n", seclogname);
-			RETURN(PTR_ERR(sptlrpc_cld));
+			return PTR_ERR(sptlrpc_cld);
 		}
 	}
 
@@ -327,7 +319,7 @@ static int config_log_add(struct obd_device *obd, char *logname,
 	if (IS_ERR(cld)) {
 		CERROR("can't create log: %s\n", logname);
 		config_log_put(sptlrpc_cld);
-		RETURN(PTR_ERR(cld));
+		return PTR_ERR(cld);
 	}
 
 	cld->cld_sptlrpc = sptlrpc_cld;
@@ -339,12 +331,12 @@ static int config_log_add(struct obd_device *obd, char *logname,
 		recover_cld = config_recover_log_add(obd, seclogname, cfg, sb);
 		if (IS_ERR(recover_cld)) {
 			config_log_put(cld);
-			RETURN(PTR_ERR(recover_cld));
+			return PTR_ERR(recover_cld);
 		}
 		cld->cld_recover = recover_cld;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 DEFINE_MUTEX(llog_process_lock);
@@ -357,11 +349,10 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
 	struct config_llog_data *cld_sptlrpc = NULL;
 	struct config_llog_data *cld_recover = NULL;
 	int rc = 0;
-	ENTRY;
 
 	cld = config_log_find(logname, cfg);
 	if (cld == NULL)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	mutex_lock(&cld->cld_lock);
 	/*
@@ -375,7 +366,7 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
 		mutex_unlock(&cld->cld_lock);
 		/* drop the ref from the find */
 		config_log_put(cld);
-		RETURN(rc);
+		return rc;
 	}
 
 	cld->cld_stopping = 1;
@@ -406,7 +397,7 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
 
 	CDEBUG(D_MGC, "end config log %s (%d)\n", logname ? logname : "client",
 	       rc);
-	RETURN(rc);
+	return rc;
 }
 
 int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
@@ -415,7 +406,6 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 	struct obd_import       *imp = obd->u.cli.cl_import;
 	struct obd_connect_data *ocd = &imp->imp_connect_data;
 	struct config_llog_data *cld;
-	ENTRY;
 
 	seq_printf(m, "imperative_recovery: %s\n",
 		      OCD_HAS_FLAG(ocd, IMP_RECOV) ? "ENABLED" : "DISABLED");
@@ -431,7 +421,7 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 	}
 	spin_unlock(&config_list_lock);
 
-	RETURN(0);
+	return 0;
 }
 
 /* reenqueue any lost locks */
@@ -445,7 +435,6 @@ static DECLARE_COMPLETION(rq_exit);
 
 static void do_requeue(struct config_llog_data *cld)
 {
-	ENTRY;
 	LASSERT(atomic_read(&cld->cld_refcount) > 0);
 
 	/* Do not run mgc_process_log on a disconnected export or an
@@ -460,8 +449,6 @@ static void do_requeue(struct config_llog_data *cld)
 		       cld->cld_logname);
 	}
 	up_read(&cld->cld_mgcexp->exp_obd->u.cli.cl_sem);
-
-	EXIT;
 }
 
 /* this timeout represents how many seconds MGC should wait before
@@ -474,7 +461,6 @@ static void do_requeue(struct config_llog_data *cld)
 static int mgc_requeue_thread(void *data)
 {
 	int rc = 0;
-	ENTRY;
 
 	CDEBUG(D_MGC, "Starting requeue thread\n");
 
@@ -556,15 +542,13 @@ static int mgc_requeue_thread(void *data)
 	complete(&rq_exit);
 
 	CDEBUG(D_MGC, "Ending requeue thread\n");
-	RETURN(rc);
+	return rc;
 }
 
 /* Add a cld to the list to requeue.  Start the requeue thread if needed.
    We are responsible for dropping the config log reference from here on out. */
 static void mgc_requeue_add(struct config_llog_data *cld)
 {
-	ENTRY;
-
 	CDEBUG(D_INFO, "log %s: requeue (r=%d sp=%d st=%x)\n",
 	       cld->cld_logname, atomic_read(&cld->cld_refcount),
 	       cld->cld_stopping, rq_state);
@@ -573,7 +557,7 @@ static void mgc_requeue_add(struct config_llog_data *cld)
 	mutex_lock(&cld->cld_lock);
 	if (cld->cld_stopping || cld->cld_lostlock) {
 		mutex_unlock(&cld->cld_lock);
-		RETURN_EXIT;
+		return;
 	}
 	/* this refcount will be released in mgc_requeue_thread. */
 	config_log_get(cld);
@@ -591,7 +575,6 @@ static void mgc_requeue_add(struct config_llog_data *cld)
 		spin_unlock(&config_list_lock);
 		wake_up(&rq_waitq);
 	}
-	EXIT;
 }
 
 /********************** class fns **********************/
@@ -605,7 +588,6 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb,
 	struct dentry *dentry;
 	char *label;
 	int err = 0;
-	ENTRY;
 
 	LASSERT(lsi);
 	LASSERT(lsi->lsi_srv_mnt == mnt);
@@ -620,7 +602,7 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb,
 		up(&cli->cl_mgc_sem);
 		CERROR("%s: No fstype %s: rc = %ld\n", lsi->lsi_fstype,
 		       obd->obd_name, PTR_ERR(obd->obd_fsops));
-		RETURN(PTR_ERR(obd->obd_fsops));
+		return PTR_ERR(obd->obd_fsops);
 	}
 
 	cli->cl_mgc_vfsmnt = mnt;
@@ -654,21 +636,20 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb,
 		CDEBUG(D_MGC, "MGC using disk labelled=%s\n", label);
 
 	/* We keep the cl_mgc_sem until mgc_fs_cleanup */
-	RETURN(0);
+	return 0;
 
 err_ops:
 	fsfilt_put_ops(obd->obd_fsops);
 	obd->obd_fsops = NULL;
 	cli->cl_mgc_vfsmnt = NULL;
 	up(&cli->cl_mgc_sem);
-	RETURN(err);
+	return err;
 }
 
 static int mgc_fs_cleanup(struct obd_device *obd)
 {
 	struct client_obd *cli = &obd->u.cli;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(cli->cl_mgc_vfsmnt != NULL);
 
@@ -687,14 +668,13 @@ static int mgc_fs_cleanup(struct obd_device *obd)
 
 	up(&cli->cl_mgc_sem);
 
-	RETURN(rc);
+	return rc;
 }
 
 static atomic_t mgc_count = ATOMIC_INIT(0);
 static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 {
 	int rc = 0;
-	ENTRY;
 
 	switch (stage) {
 	case OBD_CLEANUP_EARLY:
@@ -719,14 +699,13 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 			CERROR("failed to cleanup llogging subsystems\n");
 		break;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_cleanup(struct obd_device *obd)
 {
 	struct client_obd *cli = &obd->u.cli;
 	int rc;
-	ENTRY;
 
 	LASSERT(cli->cl_mgc_vfsmnt == NULL);
 
@@ -740,14 +719,13 @@ static int mgc_cleanup(struct obd_device *obd)
 	ptlrpcd_decref();
 
 	rc = client_obd_cleanup(obd);
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
 	struct lprocfs_static_vars lvars;
 	int rc;
-	ENTRY;
 
 	ptlrpcd_addref();
 
@@ -782,13 +760,13 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 		rc = 0;
 	}
 
-	RETURN(rc);
+	return rc;
 
 err_cleanup:
 	client_obd_cleanup(obd);
 err_decref:
 	ptlrpcd_decref();
-	RETURN(rc);
+	return rc;
 }
 
 /* based on ll_mdc_blocking_ast */
@@ -798,7 +776,6 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 	struct lustre_handle lockh;
 	struct config_llog_data *cld = (struct config_llog_data *)data;
 	int rc = 0;
-	ENTRY;
 
 	switch (flag) {
 	case LDLM_CB_BLOCKING:
@@ -847,7 +824,7 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 		LBUG();
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Not sure where this should go... */
@@ -862,18 +839,17 @@ static int mgc_set_mgs_param(struct obd_export *exp,
 	struct ptlrpc_request *req;
 	struct mgs_send_param *req_msp, *rep_msp;
 	int rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_MGS_SET_INFO, LUSTRE_MGS_VERSION,
 					MGS_SET_INFO);
 	if (!req)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req_msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
 	if (!req_msp) {
 		ptlrpc_req_finished(req);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	memcpy(req_msp, msp, sizeof(*req_msp));
@@ -889,7 +865,7 @@ static int mgc_set_mgs_param(struct obd_export *exp,
 
 	ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Take a config lock so we can get cancel notifications */
@@ -900,12 +876,15 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
 		       struct lustre_handle *lockh)
 {
 	struct config_llog_data *cld = (struct config_llog_data *)data;
-	struct ldlm_enqueue_info einfo = { type, mode, mgc_blocking_ast,
-			 ldlm_completion_ast, NULL, NULL, NULL };
+	struct ldlm_enqueue_info einfo = {
+		.ei_type	= type,
+		.ei_mode	= mode,
+		.ei_cb_bl	= mgc_blocking_ast,
+		.ei_cb_cp	= ldlm_completion_ast,
+	};
 	struct ptlrpc_request *req;
 	int short_limit = cld_is_sptlrpc(cld);
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_MGC, "Enqueue for %s (res "LPX64")\n", cld->cld_logname,
 	       cld->cld_resid.name[0]);
@@ -916,7 +895,7 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
 					&RQF_LDLM_ENQUEUE, LUSTRE_DLM_VERSION,
 					LDLM_ENQUEUE);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER, 0);
 	ptlrpc_request_set_replen(req);
@@ -934,17 +913,15 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
 	/* A failed enqueue should still call the mgc_blocking_ast,
 	   where it will be requeued if needed ("grant failed"). */
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_cancel(struct obd_export *exp, struct lov_stripe_md *md,
 		      __u32 mode, struct lustre_handle *lockh)
 {
-	ENTRY;
-
 	ldlm_lock_decref(lockh, mode);
 
-	RETURN(0);
+	return 0;
 }
 
 static void mgc_notify_active(struct obd_device *unused)
@@ -965,18 +942,17 @@ static int mgc_target_register(struct obd_export *exp,
 	struct ptlrpc_request  *req;
 	struct mgs_target_info *req_mti, *rep_mti;
 	int		     rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_MGS_TARGET_REG, LUSTRE_MGS_VERSION,
 					MGS_TARGET_REG);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req_mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
 	if (!req_mti) {
 		ptlrpc_req_finished(req);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	memcpy(req_mti, mti, sizeof(*req_mti));
@@ -995,7 +971,7 @@ static int mgc_target_register(struct obd_export *exp,
 	}
 	ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
@@ -1003,14 +979,13 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 		       void *val, struct ptlrpc_request_set *set)
 {
 	int rc = -EINVAL;
-	ENTRY;
 
 	/* Turn off initial_recov after we try all backup servers once */
 	if (KEY_IS(KEY_INIT_RECOV_BACKUP)) {
 		struct obd_import *imp = class_exp2cliimp(exp);
 		int value;
 		if (vallen != sizeof(int))
-			RETURN(-EINVAL);
+			return -EINVAL;
 		value = *(int *)val;
 		CDEBUG(D_MGC, "InitRecov %s %d/d%d:i%d:r%d:or%d:%s\n",
 		       imp->imp_obd->obd_name, value,
@@ -1021,46 +996,46 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 		if ((imp->imp_state != LUSTRE_IMP_FULL &&
 		     imp->imp_state != LUSTRE_IMP_NEW) || value > 1)
 			ptlrpc_reconnect_import(imp);
-		RETURN(0);
+		return 0;
 	}
 	/* FIXME move this to mgc_process_config */
 	if (KEY_IS(KEY_REGISTER_TARGET)) {
 		struct mgs_target_info *mti;
 		if (vallen != sizeof(struct mgs_target_info))
-			RETURN(-EINVAL);
+			return -EINVAL;
 		mti = (struct mgs_target_info *)val;
 		CDEBUG(D_MGC, "register_target %s %#x\n",
 		       mti->mti_svname, mti->mti_flags);
 		rc =  mgc_target_register(exp, mti);
-		RETURN(rc);
+		return rc;
 	}
 	if (KEY_IS(KEY_SET_FS)) {
 		struct super_block *sb = (struct super_block *)val;
 		struct lustre_sb_info *lsi;
 		if (vallen != sizeof(struct super_block))
-			RETURN(-EINVAL);
+			return -EINVAL;
 		lsi = s2lsi(sb);
 		rc = mgc_fs_setup(exp->exp_obd, sb, lsi->lsi_srv_mnt);
 		if (rc) {
 			CERROR("set_fs got %d\n", rc);
 		}
-		RETURN(rc);
+		return rc;
 	}
 	if (KEY_IS(KEY_CLEAR_FS)) {
 		if (vallen != 0)
-			RETURN(-EINVAL);
+			return -EINVAL;
 		rc = mgc_fs_cleanup(exp->exp_obd);
 		if (rc) {
 			CERROR("clear_fs got %d\n", rc);
 		}
-		RETURN(rc);
+		return rc;
 	}
 	if (KEY_IS(KEY_SET_INFO)) {
 		struct mgs_send_param *msp;
 
 		msp = (struct mgs_send_param *)val;
 		rc =  mgc_set_mgs_param(exp, msp);
-		RETURN(rc);
+		return rc;
 	}
 	if (KEY_IS(KEY_MGSSEC)) {
 		struct client_obd     *cli = &exp->exp_obd->u.cli;
@@ -1075,7 +1050,7 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 		 */
 		if (vallen == 0) {
 			if (cli->cl_flvr_mgc.sf_rpc != SPTLRPC_FLVR_INVALID)
-				RETURN(0);
+				return 0;
 			val = "null";
 			vallen = 4;
 		}
@@ -1084,7 +1059,7 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 		if (rc) {
 			CERROR("invalid sptlrpc flavor %s to MGS\n",
 			       (char *) val);
-			RETURN(rc);
+			return rc;
 		}
 
 		/*
@@ -1103,10 +1078,10 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 				       (char *) val, str);
 			rc = -EPERM;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_get_info(const struct lu_env *env, struct obd_export *exp,
@@ -1167,7 +1142,7 @@ static int mgc_import_event(struct obd_device *obd,
 		CERROR("Unknown import event %#x\n", event);
 		LBUG();
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
@@ -1175,7 +1150,6 @@ static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
 {
 	struct llog_ctxt *ctxt;
 	int rc;
-	ENTRY;
 
 	LASSERT(olg == &obd->obd_olg);
 
@@ -1192,20 +1166,18 @@ static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
 	llog_initiator_connect(ctxt);
 	llog_ctxt_put(ctxt);
 
-	RETURN(0);
+	return 0;
 out:
 	ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
 	if (ctxt)
 		llog_cleanup(NULL, ctxt);
-	RETURN(rc);
+	return rc;
 }
 
 static int mgc_llog_finish(struct obd_device *obd, int count)
 {
 	struct llog_ctxt *ctxt;
 
-	ENTRY;
-
 	ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
 	if (ctxt)
 		llog_cleanup(NULL, ctxt);
@@ -1213,7 +1185,7 @@ static int mgc_llog_finish(struct obd_device *obd, int count)
 	ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
 	if (ctxt)
 		llog_cleanup(NULL, ctxt);
-	RETURN(0);
+	return 0;
 }
 
 enum {
@@ -1238,14 +1210,13 @@ static int mgc_apply_recover_logs(struct obd_device *mgc,
 	int   pos;
 	int   rc  = 0;
 	int   off = 0;
-	ENTRY;
 
 	LASSERT(cfg->cfg_instance != NULL);
 	LASSERT(cfg->cfg_sb == cfg->cfg_instance);
 
 	OBD_ALLOC(inst, PAGE_CACHE_SIZE);
 	if (inst == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (!IS_SERVER(lsi)) {
 		pos = snprintf(inst, PAGE_CACHE_SIZE, "%p", cfg->cfg_instance);
@@ -1259,7 +1230,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc,
 					PAGE_CACHE_SIZE);
 		if (rc) {
 			OBD_FREE(inst, PAGE_CACHE_SIZE);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		pos = strlen(inst);
 	}
@@ -1417,7 +1388,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc,
 	}
 
 	OBD_FREE(inst, PAGE_CACHE_SIZE);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1439,7 +1410,6 @@ static int mgc_process_recover_log(struct obd_device *obd,
 	int i;
 	int ealen;
 	int rc;
-	ENTRY;
 
 	/* allocate buffer for bulk transfer.
 	 * if this is the first time for this mgs to read logs,
@@ -1582,8 +1552,6 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
 	int rc = 0, must_pop = 0;
 	bool sptlrpc_started = false;
 
-	ENTRY;
-
 	LASSERT(cld);
 	LASSERT(mutex_is_locked(&cld->cld_lock));
 
@@ -1592,7 +1560,7 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
 	 * read it up here.
 	 */
 	if (cld_is_sptlrpc(cld) && local_only)
-		RETURN(0);
+		return 0;
 
 	if (cld->cld_cfg.cfg_sb)
 		lsi = s2lsi(cld->cld_cfg.cfg_sb);
@@ -1600,12 +1568,12 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
 	ctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT);
 	if (!ctxt) {
 		CERROR("missing llog context\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	OBD_ALLOC_PTR(saved_ctxt);
 	if (saved_ctxt == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	lctxt = llog_get_context(mgc, LLOG_CONFIG_ORIG_CTXT);
 
@@ -1623,7 +1591,6 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
 	   be updated here. */
 	rc = class_config_parse_llog(NULL, ctxt, cld->cld_logname,
 				     &cld->cld_cfg);
-	EXIT;
 
 out_pop:
 	llog_ctxt_put(ctxt);
@@ -1647,7 +1614,7 @@ out_pop:
 					  strlen("-sptlrpc"));
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /** Get a config log from the MGS and process it.
@@ -1659,7 +1626,6 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld)
 	struct lustre_handle lockh = { 0 };
 	__u64 flags = LDLM_FL_NO_LRU;
 	int rc = 0, rcl;
-	ENTRY;
 
 	LASSERT(cld);
 
@@ -1670,7 +1636,7 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld)
 	mutex_lock(&cld->cld_lock);
 	if (cld->cld_stopping) {
 		mutex_unlock(&cld->cld_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	OBD_FAIL_TIMEOUT(OBD_FAIL_MGC_PAUSE_PROCESS_LOG, 20);
@@ -1719,7 +1685,7 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld)
 			CERROR("Can't drop cfg lock: %d\n", rcl);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1733,7 +1699,6 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
 	struct config_llog_instance *cfg = NULL;
 	char *logname;
 	int rc = 0;
-	ENTRY;
 
 	switch(lcfg->lcfg_command) {
 	case LCFG_LOV_ADD_OBD: {
@@ -1818,7 +1783,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
 	}
 	}
 out:
-	RETURN(rc);
+	return rc;
 }
 
 struct obd_ops mgc_obd_ops = {
diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile
index b80c13c..8a0e08c 100644
--- a/drivers/staging/lustre/lustre/obdclass/Makefile
+++ b/drivers/staging/lustre/lustre/obdclass/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o llog_test.o
 obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \
 	      llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \
 	      genops.o uuid.o llog_ioctl.o lprocfs_status.o		   \
-	      lprocfs_jobstats.o lustre_handles.o lustre_peer.o llog_osd.o \
+	      lustre_handles.o lustre_peer.o llog_osd.o \
 	      local_storage.o statfs_pack.o obdo.o obd_config.o obd_mount.o\
 	      mea.o lu_object.o dt_object.o capa.o cl_object.o   \
 	      cl_page.o cl_lock.o cl_io.o lu_ref.o acl.o idmap.o	   \
diff --git a/drivers/staging/lustre/lustre/obdclass/acl.c b/drivers/staging/lustre/lustre/obdclass/acl.c
index c2a6702..f0bb632 100644
--- a/drivers/staging/lustre/lustre/obdclass/acl.c
+++ b/drivers/staging/lustre/lustre/obdclass/acl.c
@@ -144,10 +144,9 @@ lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size)
 {
 	int count, i, esize;
 	ext_acl_xattr_header *new;
-	ENTRY;
 
 	if (unlikely(size < 0))
-		RETURN(ERR_PTR(-EINVAL));
+		return ERR_PTR(-EINVAL);
 	else if (!size)
 		count = 0;
 	else
@@ -155,7 +154,7 @@ lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size)
 	esize = CFS_ACL_XATTR_SIZE(count, ext_acl_xattr);
 	OBD_ALLOC(new, esize);
 	if (unlikely(new == NULL))
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	new->a_count = cpu_to_le32(count);
 	for (i = 0; i < count; i++) {
@@ -165,7 +164,7 @@ lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size)
 		new->a_entries[i].e_stat = cpu_to_le32(ES_UNK);
 	}
 
-	RETURN(new);
+	return new;
 }
 EXPORT_SYMBOL(lustre_posix_acl_xattr_2ext);
 
@@ -178,16 +177,15 @@ int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size,
 	int count, i, j, rc = 0;
 	__u32 id;
 	posix_acl_xattr_header *new;
-	ENTRY;
 
 	if (unlikely(size < 0))
-		RETURN(-EINVAL);
+		return -EINVAL;
 	else if (!size)
-		RETURN(0);
+		return 0;
 
 	OBD_ALLOC(new, size);
 	if (unlikely(new == NULL))
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
 	count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
@@ -228,7 +226,6 @@ int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size,
 		*out = new;
 		rc = 0;
 	}
-	EXIT;
 
 _out:
 	if (rc) {
@@ -302,7 +299,6 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
 	posix_acl_xattr_entry pe = {ACL_MASK, 0, ACL_UNDEFINED_ID};
 	posix_acl_xattr_header *new;
 	ext_acl_xattr_entry *ee, ae;
-	ENTRY;
 
 	lustre_posix_acl_cpu_to_le(&pe, &pe);
 	ee = lustre_ext_acl_xattr_search(ext_header, &pe, &pos);
@@ -312,7 +308,7 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
 		posix_size = CFS_ACL_XATTR_SIZE(posix_count, posix_acl_xattr);
 		OBD_ALLOC(new, posix_size);
 		if (unlikely(new == NULL))
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
 		for (i = 0, j = 0; i < ext_count; i++) {
@@ -349,7 +345,7 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
 		int ori_posix_count;
 
 		if (unlikely(size < 0))
-			RETURN(-EINVAL);
+			return -EINVAL;
 		else if (!size)
 			ori_posix_count = 0;
 		else
@@ -360,7 +356,7 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
 			CFS_ACL_XATTR_SIZE(posix_count, posix_acl_xattr);
 		OBD_ALLOC(new, posix_size);
 		if (unlikely(new == NULL))
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
 		/* 1. process the unchanged ACL entries
@@ -397,7 +393,6 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
 		*out = new;
 		rc = 0;
 	}
-	EXIT;
 
 _out:
 	if (rc) {
@@ -420,10 +415,9 @@ lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
 	posix_acl_xattr_entry pae;
 	ext_acl_xattr_header *new;
 	ext_acl_xattr_entry *ee, eae;
-	ENTRY;
 
 	if (unlikely(size < 0))
-		RETURN(ERR_PTR(-EINVAL));
+		return ERR_PTR(-EINVAL);
 	else if (!size)
 		posix_count = 0;
 	else
@@ -434,7 +428,7 @@ lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
 
 	OBD_ALLOC(new, ext_size);
 	if (unlikely(new == NULL))
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	for (i = 0, j = 0; i < posix_count; i++) {
 		lustre_posix_acl_le_to_cpu(&pae, &posix_header->a_entries[i]);
@@ -532,7 +526,6 @@ lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
 	new->a_count = cpu_to_le32(j);
 	/* free unused space. */
 	rc = lustre_ext_acl_xattr_reduce_space(&new, ext_count);
-	EXIT;
 
 out:
 	if (rc) {
diff --git a/drivers/staging/lustre/lustre/obdclass/capa.c b/drivers/staging/lustre/lustre/obdclass/capa.c
index 3e532f5..68d797b 100644
--- a/drivers/staging/lustre/lustre/obdclass/capa.c
+++ b/drivers/staging/lustre/lustre/obdclass/capa.c
@@ -42,12 +42,12 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <asm/unistd.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/crypto.h>
 
 #include <obd_class.h>
 #include <lustre_debug.h>
@@ -77,6 +77,12 @@ EXPORT_SYMBOL(capa_list);
 EXPORT_SYMBOL(capa_lock);
 EXPORT_SYMBOL(capa_count);
 
+static inline
+unsigned int ll_crypto_tfm_alg_min_keysize(struct crypto_blkcipher *tfm)
+{
+	return crypto_blkcipher_tfm(tfm)->__crt_alg->cra_blkcipher.min_keysize;
+}
+
 struct hlist_head *init_capa_hash(void)
 {
 	struct hlist_head *hash;
@@ -235,9 +241,26 @@ struct obd_capa *capa_lookup(struct hlist_head *hash, struct lustre_capa *capa,
 }
 EXPORT_SYMBOL(capa_lookup);
 
+static inline int ll_crypto_hmac(struct crypto_hash *tfm,
+				 u8 *key, unsigned int *keylen,
+				 struct scatterlist *sg,
+				 unsigned int size, u8 *result)
+{
+	struct hash_desc desc;
+	int	      rv;
+	desc.tfm   = tfm;
+	desc.flags = 0;
+	rv = crypto_hash_setkey(desc.tfm, key, *keylen);
+	if (rv) {
+		CERROR("failed to hash setkey: %d\n", rv);
+		return rv;
+	}
+	return crypto_hash_digest(&desc, sg, size, result);
+}
+
 int capa_hmac(__u8 *hmac, struct lustre_capa *capa, __u8 *key)
 {
-	struct ll_crypto_hash *tfm;
+	struct crypto_hash *tfm;
 	struct capa_hmac_alg  *alg;
 	int keylen;
 	struct scatterlist sl;
@@ -249,7 +272,7 @@ int capa_hmac(__u8 *hmac, struct lustre_capa *capa, __u8 *key)
 
 	alg = &capa_hmac_algs[capa_alg(capa)];
 
-	tfm = ll_crypto_alloc_hash(alg->ha_name, 0, 0);
+	tfm = crypto_alloc_hash(alg->ha_name, 0, 0);
 	if (!tfm) {
 		CERROR("crypto_alloc_tfm failed, check whether your kernel"
 		       "has crypto support!\n");
@@ -262,7 +285,7 @@ int capa_hmac(__u8 *hmac, struct lustre_capa *capa, __u8 *key)
 		    (unsigned long)(capa) % PAGE_CACHE_SIZE);
 
 	ll_crypto_hmac(tfm, key, &keylen, &sl, sl.length, hmac);
-	ll_crypto_free_hash(tfm);
+	crypto_free_hash(tfm);
 
 	return 0;
 }
@@ -270,21 +293,20 @@ EXPORT_SYMBOL(capa_hmac);
 
 int capa_encrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen)
 {
-	struct ll_crypto_cipher *tfm;
+	struct crypto_blkcipher *tfm;
 	struct scatterlist sd;
 	struct scatterlist ss;
 	struct blkcipher_desc desc;
 	unsigned int min;
 	int rc;
 	char alg[CRYPTO_MAX_ALG_NAME+1] = "aes";
-	ENTRY;
 
 	/* passing "aes" in a variable instead of a constant string keeps gcc
 	 * 4.3.2 happy */
-	tfm = ll_crypto_alloc_blkcipher(alg, 0, 0 );
+	tfm = crypto_alloc_blkcipher(alg, 0, 0 );
 	if (IS_ERR(tfm)) {
 		CERROR("failed to load transform for aes\n");
-		RETURN(PTR_ERR(tfm));
+		return PTR_ERR(tfm);
 	}
 
 	min = ll_crypto_tfm_alg_min_keysize(tfm);
@@ -293,7 +315,7 @@ int capa_encrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen)
 		GOTO(out, rc = -EINVAL);
 	}
 
-	rc = ll_crypto_blkcipher_setkey(tfm, key, min);
+	rc = crypto_blkcipher_setkey(tfm, key, min);
 	if (rc) {
 		CERROR("failed to setting key for aes\n");
 		GOTO(out, rc);
@@ -307,37 +329,34 @@ int capa_encrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen)
 	desc.tfm   = tfm;
 	desc.info  = NULL;
 	desc.flags = 0;
-	rc = ll_crypto_blkcipher_encrypt(&desc, &sd, &ss, 16);
+	rc = crypto_blkcipher_encrypt(&desc, &sd, &ss, 16);
 	if (rc) {
 		CERROR("failed to encrypt for aes\n");
 		GOTO(out, rc);
 	}
 
-	EXIT;
-
 out:
-	ll_crypto_free_blkcipher(tfm);
+	crypto_free_blkcipher(tfm);
 	return rc;
 }
 EXPORT_SYMBOL(capa_encrypt_id);
 
 int capa_decrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen)
 {
-	struct ll_crypto_cipher *tfm;
+	struct crypto_blkcipher *tfm;
 	struct scatterlist sd;
 	struct scatterlist ss;
 	struct blkcipher_desc desc;
 	unsigned int min;
 	int rc;
 	char alg[CRYPTO_MAX_ALG_NAME+1] = "aes";
-	ENTRY;
 
 	/* passing "aes" in a variable instead of a constant string keeps gcc
 	 * 4.3.2 happy */
-	tfm = ll_crypto_alloc_blkcipher(alg, 0, 0 );
+	tfm = crypto_alloc_blkcipher(alg, 0, 0 );
 	if (IS_ERR(tfm)) {
 		CERROR("failed to load transform for aes\n");
-		RETURN(PTR_ERR(tfm));
+		return PTR_ERR(tfm);
 	}
 
 	min = ll_crypto_tfm_alg_min_keysize(tfm);
@@ -346,7 +365,7 @@ int capa_decrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen)
 		GOTO(out, rc = -EINVAL);
 	}
 
-	rc = ll_crypto_blkcipher_setkey(tfm, key, min);
+	rc = crypto_blkcipher_setkey(tfm, key, min);
 	if (rc) {
 		CERROR("failed to setting key for aes\n");
 		GOTO(out, rc);
@@ -361,16 +380,14 @@ int capa_decrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen)
 	desc.tfm   = tfm;
 	desc.info  = NULL;
 	desc.flags = 0;
-	rc = ll_crypto_blkcipher_decrypt(&desc, &sd, &ss, 16);
+	rc = crypto_blkcipher_decrypt(&desc, &sd, &ss, 16);
 	if (rc) {
 		CERROR("failed to decrypt for aes\n");
 		GOTO(out, rc);
 	}
 
-	EXIT;
-
 out:
-	ll_crypto_free_blkcipher(tfm);
+	crypto_free_blkcipher(tfm);
 	return rc;
 }
 EXPORT_SYMBOL(capa_decrypt_id);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c
index 75c9be8..4269793 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_io.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c
@@ -106,7 +106,6 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io)
 
 	LINVRNT(cl_io_type_is_valid(io->ci_type));
 	LINVRNT(cl_io_invariant(io));
-	ENTRY;
 
 	while (!list_empty(&io->ci_layers)) {
 		slice = container_of(io->ci_layers.prev, struct cl_io_slice,
@@ -144,7 +143,6 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io)
 	default:
 		LBUG();
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_io_fini);
 
@@ -157,7 +155,6 @@ static int cl_io_init0(const struct lu_env *env, struct cl_io *io,
 	LINVRNT(io->ci_state == CIS_ZERO || io->ci_state == CIS_FINI);
 	LINVRNT(cl_io_type_is_valid(iot));
 	LINVRNT(cl_io_invariant(io));
-	ENTRY;
 
 	io->ci_type = iot;
 	INIT_LIST_HEAD(&io->ci_lockset.cls_todo);
@@ -175,7 +172,7 @@ static int cl_io_init0(const struct lu_env *env, struct cl_io *io,
 	}
 	if (result == 0)
 		io->ci_state = CIS_INIT;
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -228,7 +225,6 @@ int cl_io_rw_init(const struct lu_env *env, struct cl_io *io,
 {
 	LINVRNT(iot == CIT_READ || iot == CIT_WRITE);
 	LINVRNT(io->ci_obj != NULL);
-	ENTRY;
 
 	LU_OBJECT_HEADER(D_VFSTRACE, env, &io->ci_obj->co_lu,
 			 "io range: %u ["LPU64", "LPU64") %u %u\n",
@@ -236,7 +232,7 @@ int cl_io_rw_init(const struct lu_env *env, struct cl_io *io,
 			 io->u.ci_rw.crw_nonblock, io->u.ci_wr.wr_append);
 	io->u.ci_rw.crw_pos    = pos;
 	io->u.ci_rw.crw_count  = count;
-	RETURN(cl_io_init(env, io, iot, io->ci_obj));
+	return cl_io_init(env, io, iot, io->ci_obj);
 }
 EXPORT_SYMBOL(cl_io_rw_init);
 
@@ -288,7 +284,6 @@ static void cl_io_locks_sort(struct cl_io *io)
 {
 	int done = 0;
 
-	ENTRY;
 	/* hidden treasure: bubble sort for now. */
 	do {
 		struct cl_io_lock_link *curr;
@@ -325,7 +320,6 @@ static void cl_io_locks_sort(struct cl_io *io)
 			prev = curr;
 		}
 	} while (!done);
-	EXIT;
 }
 
 /**
@@ -339,12 +333,11 @@ int cl_queue_match(const struct list_head *queue,
 {
        struct cl_io_lock_link *scan;
 
-       ENTRY;
        list_for_each_entry(scan, queue, cill_linkage) {
 	       if (cl_lock_descr_match(&scan->cill_descr, need))
-		       RETURN(+1);
+		       return +1;
        }
-       RETURN(0);
+       return 0;
 }
 EXPORT_SYMBOL(cl_queue_match);
 
@@ -353,7 +346,6 @@ static int cl_queue_merge(const struct list_head *queue,
 {
        struct cl_io_lock_link *scan;
 
-       ENTRY;
        list_for_each_entry(scan, queue, cill_linkage) {
 	       if (cl_lock_descr_cmp(&scan->cill_descr, need))
 		       continue;
@@ -361,9 +353,9 @@ static int cl_queue_merge(const struct list_head *queue,
 	       CDEBUG(D_VFSTRACE, "lock: %d: [%lu, %lu]\n",
 		      scan->cill_descr.cld_mode, scan->cill_descr.cld_start,
 		      scan->cill_descr.cld_end);
-	       RETURN(+1);
+	       return +1;
        }
-       RETURN(0);
+       return 0;
 
 }
 
@@ -388,8 +380,6 @@ static int cl_lockset_lock_one(const struct lu_env *env,
 	struct cl_lock *lock;
 	int	     result;
 
-	ENTRY;
-
 	lock = cl_lock_request(env, io, &link->cill_descr, "io", io);
 
 	if (!IS_ERR(lock)) {
@@ -404,7 +394,7 @@ static int cl_lockset_lock_one(const struct lu_env *env,
 			result = 0;
 	} else
 		result = PTR_ERR(lock);
-	RETURN(result);
+	return result;
 }
 
 static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io,
@@ -412,7 +402,6 @@ static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io,
 {
 	struct cl_lock *lock = link->cill_lock;
 
-	ENTRY;
 	list_del_init(&link->cill_linkage);
 	if (lock != NULL) {
 		cl_lock_release(env, lock, "io", io);
@@ -420,7 +409,6 @@ static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io,
 	}
 	if (link->cill_fini != NULL)
 		link->cill_fini(env, link);
-	EXIT;
 }
 
 static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io,
@@ -431,7 +419,6 @@ static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io,
 	struct cl_lock	 *lock;
 	int result;
 
-	ENTRY;
 	result = 0;
 	list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) {
 		if (!cl_lockset_match(set, &link->cill_descr)) {
@@ -455,7 +442,7 @@ static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io,
 				break;
 		}
 	}
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -474,7 +461,6 @@ int cl_io_lock(const struct lu_env *env, struct cl_io *io)
 	LINVRNT(io->ci_state == CIS_IT_STARTED);
 	LINVRNT(cl_io_invariant(io));
 
-	ENTRY;
 	cl_io_for_each(scan, io) {
 		if (scan->cis_iop->op[io->ci_type].cio_lock == NULL)
 			continue;
@@ -490,7 +476,7 @@ int cl_io_lock(const struct lu_env *env, struct cl_io *io)
 		cl_io_unlock(env, io);
 	else
 		io->ci_state = CIS_LOCKED;
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_lock);
 
@@ -508,7 +494,6 @@ void cl_io_unlock(const struct lu_env *env, struct cl_io *io)
 	LASSERT(CIS_IT_STARTED <= io->ci_state && io->ci_state < CIS_UNLOCKED);
 	LINVRNT(cl_io_invariant(io));
 
-	ENTRY;
 	set = &io->ci_lockset;
 
 	list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage)
@@ -527,7 +512,6 @@ void cl_io_unlock(const struct lu_env *env, struct cl_io *io)
 	}
 	io->ci_state = CIS_UNLOCKED;
 	LASSERT(!cl_env_info(env)->clt_counters[CNL_TOP].ctc_nr_locks_acquired);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_io_unlock);
 
@@ -547,7 +531,6 @@ int cl_io_iter_init(const struct lu_env *env, struct cl_io *io)
 	LINVRNT(io->ci_state == CIS_INIT || io->ci_state == CIS_IT_ENDED);
 	LINVRNT(cl_io_invariant(io));
 
-	ENTRY;
 	result = 0;
 	cl_io_for_each(scan, io) {
 		if (scan->cis_iop->op[io->ci_type].cio_iter_init == NULL)
@@ -559,7 +542,7 @@ int cl_io_iter_init(const struct lu_env *env, struct cl_io *io)
 	}
 	if (result == 0)
 		io->ci_state = CIS_IT_STARTED;
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_iter_init);
 
@@ -576,13 +559,11 @@ void cl_io_iter_fini(const struct lu_env *env, struct cl_io *io)
 	LINVRNT(io->ci_state == CIS_UNLOCKED);
 	LINVRNT(cl_io_invariant(io));
 
-	ENTRY;
 	cl_io_for_each_reverse(scan, io) {
 		if (scan->cis_iop->op[io->ci_type].cio_iter_fini != NULL)
 			scan->cis_iop->op[io->ci_type].cio_iter_fini(env, scan);
 	}
 	io->ci_state = CIS_IT_ENDED;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_io_iter_fini);
 
@@ -598,8 +579,6 @@ void cl_io_rw_advance(const struct lu_env *env, struct cl_io *io, size_t nob)
 	LINVRNT(cl_io_is_loopable(io));
 	LINVRNT(cl_io_invariant(io));
 
-	ENTRY;
-
 	io->u.ci_rw.crw_pos   += nob;
 	io->u.ci_rw.crw_count -= nob;
 
@@ -609,7 +588,6 @@ void cl_io_rw_advance(const struct lu_env *env, struct cl_io *io, size_t nob)
 			scan->cis_iop->op[io->ci_type].cio_advance(env, scan,
 								   nob);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_io_rw_advance);
 
@@ -621,14 +599,13 @@ int cl_io_lock_add(const struct lu_env *env, struct cl_io *io,
 {
 	int result;
 
-	ENTRY;
 	if (cl_lockset_merge(&io->ci_lockset, &link->cill_descr))
 		result = +1;
 	else {
 		list_add(&link->cill_linkage, &io->ci_lockset.cls_todo);
 		result = 0;
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_lock_add);
 
@@ -647,7 +624,6 @@ int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io,
 	struct cl_io_lock_link *link;
 	int result;
 
-	ENTRY;
 	OBD_ALLOC_PTR(link);
 	if (link != NULL) {
 		link->cill_descr     = *descr;
@@ -658,7 +634,7 @@ int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io,
 	} else
 		result = -ENOMEM;
 
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_lock_alloc_add);
 
@@ -673,7 +649,6 @@ int cl_io_start(const struct lu_env *env, struct cl_io *io)
 	LINVRNT(cl_io_is_loopable(io));
 	LINVRNT(io->ci_state == CIS_LOCKED);
 	LINVRNT(cl_io_invariant(io));
-	ENTRY;
 
 	io->ci_state = CIS_IO_GOING;
 	cl_io_for_each(scan, io) {
@@ -685,7 +660,7 @@ int cl_io_start(const struct lu_env *env, struct cl_io *io)
 	}
 	if (result >= 0)
 		result = 0;
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_start);
 
@@ -700,7 +675,6 @@ void cl_io_end(const struct lu_env *env, struct cl_io *io)
 	LINVRNT(cl_io_is_loopable(io));
 	LINVRNT(io->ci_state == CIS_IO_GOING);
 	LINVRNT(cl_io_invariant(io));
-	ENTRY;
 
 	cl_io_for_each_reverse(scan, io) {
 		if (scan->cis_iop->op[io->ci_type].cio_end != NULL)
@@ -708,7 +682,6 @@ void cl_io_end(const struct lu_env *env, struct cl_io *io)
 		/* TODO: error handling. */
 	}
 	io->ci_state = CIS_IO_FINISHED;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_io_end);
 
@@ -774,7 +747,6 @@ int cl_io_read_page(const struct lu_env *env, struct cl_io *io,
 	LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED);
 	LINVRNT(cl_page_in_io(page, io));
 	LINVRNT(cl_io_invariant(io));
-	ENTRY;
 
 	queue = &io->ci_queue;
 
@@ -807,7 +779,7 @@ int cl_io_read_page(const struct lu_env *env, struct cl_io *io,
 	 */
 	cl_page_list_disown(env, io, &queue->c2_qin);
 	cl_2queue_fini(env, queue);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_read_page);
 
@@ -827,7 +799,6 @@ int cl_io_prepare_write(const struct lu_env *env, struct cl_io *io,
 	LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED);
 	LINVRNT(cl_io_invariant(io));
 	LASSERT(cl_page_in_io(page, io));
-	ENTRY;
 
 	cl_io_for_each_reverse(scan, io) {
 		if (scan->cis_iop->cio_prepare_write != NULL) {
@@ -841,7 +812,7 @@ int cl_io_prepare_write(const struct lu_env *env, struct cl_io *io,
 				break;
 		}
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_prepare_write);
 
@@ -867,7 +838,6 @@ int cl_io_commit_write(const struct lu_env *env, struct cl_io *io,
 	 */
 	LASSERT(cl_page_is_owned(page, io) || page->cp_parent != NULL);
 	LASSERT(cl_page_in_io(page, io));
-	ENTRY;
 
 	cl_io_for_each(scan, io) {
 		if (scan->cis_iop->cio_commit_write != NULL) {
@@ -882,7 +852,7 @@ int cl_io_commit_write(const struct lu_env *env, struct cl_io *io,
 		}
 	}
 	LINVRNT(result <= 0);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_commit_write);
 
@@ -903,7 +873,6 @@ int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io,
 	int result = 0;
 
 	LINVRNT(crt < ARRAY_SIZE(scan->cis_iop->req_op));
-	ENTRY;
 
 	cl_io_for_each(scan, io) {
 		if (scan->cis_iop->req_op[crt].cio_submit == NULL)
@@ -917,7 +886,7 @@ int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io,
 	 * If ->cio_submit() failed, no pages were sent.
 	 */
 	LASSERT(ergo(result != 0, list_empty(&queue->c2_qout.pl_pages)));
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_io_submit_rw);
 
@@ -1009,7 +978,6 @@ int cl_io_loop(const struct lu_env *env, struct cl_io *io)
 	int result   = 0;
 
 	LINVRNT(cl_io_is_loopable(io));
-	ENTRY;
 
 	do {
 		size_t nob;
@@ -1043,7 +1011,7 @@ int cl_io_loop(const struct lu_env *env, struct cl_io *io)
 	} while (result == 0 && io->ci_continue);
 	if (result == 0)
 		result = io->ci_result;
-	RETURN(result < 0 ? result : 0);
+	return result < 0 ? result : 0;
 }
 EXPORT_SYMBOL(cl_io_loop);
 
@@ -1064,13 +1032,11 @@ void cl_io_slice_add(struct cl_io *io, struct cl_io_slice *slice,
 
 	LASSERT((linkage->prev == NULL && linkage->next == NULL) ||
 		list_empty(linkage));
-	ENTRY;
 
 	list_add_tail(linkage, &io->ci_layers);
 	slice->cis_io  = io;
 	slice->cis_obj = obj;
 	slice->cis_iop = ops;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_io_slice_add);
 
@@ -1080,11 +1046,9 @@ EXPORT_SYMBOL(cl_io_slice_add);
  */
 void cl_page_list_init(struct cl_page_list *plist)
 {
-	ENTRY;
 	plist->pl_nr = 0;
 	INIT_LIST_HEAD(&plist->pl_pages);
 	plist->pl_owner = current;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_init);
 
@@ -1093,7 +1057,6 @@ EXPORT_SYMBOL(cl_page_list_init);
  */
 void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page)
 {
-	ENTRY;
 	/* it would be better to check that page is owned by "current" io, but
 	 * it is not passed here. */
 	LASSERT(page->cp_owner != NULL);
@@ -1105,9 +1068,8 @@ void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page)
 	LASSERT(list_empty(&page->cp_batch));
 	list_add_tail(&page->cp_batch, &plist->pl_pages);
 	++plist->pl_nr;
-	page->cp_queue_ref = lu_ref_add(&page->cp_reference, "queue", plist);
+	lu_ref_add_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
 	cl_page_get(page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_add);
 
@@ -1120,15 +1082,13 @@ void cl_page_list_del(const struct lu_env *env,
 	LASSERT(plist->pl_nr > 0);
 	LINVRNT(plist->pl_owner == current);
 
-	ENTRY;
 	list_del_init(&page->cp_batch);
 	lockdep_off();
 	mutex_unlock(&page->cp_mutex);
 	lockdep_on();
 	--plist->pl_nr;
-	lu_ref_del_at(&page->cp_reference, page->cp_queue_ref, "queue", plist);
+	lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
 	cl_page_put(env, page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_del);
 
@@ -1142,13 +1102,11 @@ void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src,
 	LINVRNT(dst->pl_owner == current);
 	LINVRNT(src->pl_owner == current);
 
-	ENTRY;
 	list_move_tail(&page->cp_batch, &dst->pl_pages);
 	--src->pl_nr;
 	++dst->pl_nr;
-	lu_ref_set_at(&page->cp_reference,
-		      page->cp_queue_ref, "queue", src, dst);
-	EXIT;
+	lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue",
+		      src, dst);
 }
 EXPORT_SYMBOL(cl_page_list_move);
 
@@ -1163,10 +1121,8 @@ void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head)
 	LINVRNT(list->pl_owner == current);
 	LINVRNT(head->pl_owner == current);
 
-	ENTRY;
 	cl_page_list_for_each_safe(page, tmp, list)
 		cl_page_list_move(head, list, page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_splice);
 
@@ -1184,7 +1140,6 @@ void cl_page_list_disown(const struct lu_env *env,
 
 	LINVRNT(plist->pl_owner == current);
 
-	ENTRY;
 	cl_page_list_for_each_safe(page, temp, plist) {
 		LASSERT(plist->pl_nr > 0);
 
@@ -1202,10 +1157,10 @@ void cl_page_list_disown(const struct lu_env *env,
 		 * XXX cl_page_disown0() will fail if page is not locked.
 		 */
 		cl_page_disown0(env, io, page);
-		lu_ref_del(&page->cp_reference, "queue", plist);
+		lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue",
+			      plist);
 		cl_page_put(env, page);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_disown);
 
@@ -1219,11 +1174,9 @@ void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist)
 
 	LINVRNT(plist->pl_owner == current);
 
-	ENTRY;
 	cl_page_list_for_each_safe(page, temp, plist)
 		cl_page_list_del(env, plist, page);
 	LASSERT(plist->pl_nr == 0);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_fini);
 
@@ -1240,7 +1193,6 @@ int cl_page_list_own(const struct lu_env *env,
 
 	LINVRNT(plist->pl_owner == current);
 
-	ENTRY;
 	result = 0;
 	cl_page_list_for_each_safe(page, temp, plist) {
 		LASSERT(index <= page->cp_index);
@@ -1250,7 +1202,7 @@ int cl_page_list_own(const struct lu_env *env,
 		else
 			cl_page_list_del(env, plist, page);
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_page_list_own);
 
@@ -1278,10 +1230,8 @@ void cl_page_list_discard(const struct lu_env *env, struct cl_io *io,
 	struct cl_page *page;
 
 	LINVRNT(plist->pl_owner == current);
-	ENTRY;
 	cl_page_list_for_each(page, plist)
 		cl_page_discard(env, io, page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_list_discard);
 
@@ -1295,14 +1245,13 @@ int cl_page_list_unmap(const struct lu_env *env, struct cl_io *io,
 	int result;
 
 	LINVRNT(plist->pl_owner == current);
-	ENTRY;
 	result = 0;
 	cl_page_list_for_each(page, plist) {
 		result = cl_page_unmap(env, io, page);
 		if (result != 0)
 			break;
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_page_list_unmap);
 
@@ -1311,10 +1260,8 @@ EXPORT_SYMBOL(cl_page_list_unmap);
  */
 void cl_2queue_init(struct cl_2queue *queue)
 {
-	ENTRY;
 	cl_page_list_init(&queue->c2_qin);
 	cl_page_list_init(&queue->c2_qout);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_2queue_init);
 
@@ -1323,9 +1270,7 @@ EXPORT_SYMBOL(cl_2queue_init);
  */
 void cl_2queue_add(struct cl_2queue *queue, struct cl_page *page)
 {
-	ENTRY;
 	cl_page_list_add(&queue->c2_qin, page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_2queue_add);
 
@@ -1335,10 +1280,8 @@ EXPORT_SYMBOL(cl_2queue_add);
 void cl_2queue_disown(const struct lu_env *env,
 		      struct cl_io *io, struct cl_2queue *queue)
 {
-	ENTRY;
 	cl_page_list_disown(env, io, &queue->c2_qin);
 	cl_page_list_disown(env, io, &queue->c2_qout);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_2queue_disown);
 
@@ -1348,10 +1291,8 @@ EXPORT_SYMBOL(cl_2queue_disown);
 void cl_2queue_discard(const struct lu_env *env,
 		       struct cl_io *io, struct cl_2queue *queue)
 {
-	ENTRY;
 	cl_page_list_discard(env, io, &queue->c2_qin);
 	cl_page_list_discard(env, io, &queue->c2_qout);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_2queue_discard);
 
@@ -1371,10 +1312,8 @@ EXPORT_SYMBOL(cl_2queue_assume);
  */
 void cl_2queue_fini(const struct lu_env *env, struct cl_2queue *queue)
 {
-	ENTRY;
 	cl_page_list_fini(env, &queue->c2_qout);
 	cl_page_list_fini(env, &queue->c2_qin);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_2queue_fini);
 
@@ -1383,10 +1322,8 @@ EXPORT_SYMBOL(cl_2queue_fini);
  */
 void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page)
 {
-	ENTRY;
 	cl_2queue_init(queue);
 	cl_2queue_add(queue, page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_2queue_init_page);
 
@@ -1397,10 +1334,9 @@ EXPORT_SYMBOL(cl_2queue_init_page);
  */
 struct cl_io *cl_io_top(struct cl_io *io)
 {
-	ENTRY;
 	while (io->ci_parent != NULL)
 		io = io->ci_parent;
-	RETURN(io);
+	return io;
 }
 EXPORT_SYMBOL(cl_io_top);
 
@@ -1425,12 +1361,10 @@ void cl_req_slice_add(struct cl_req *req, struct cl_req_slice *slice,
 		      struct cl_device *dev,
 		      const struct cl_req_operations *ops)
 {
-	ENTRY;
 	list_add_tail(&slice->crs_linkage, &req->crq_layers);
 	slice->crs_dev = dev;
 	slice->crs_ops = ops;
 	slice->crs_req = req;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_req_slice_add);
 
@@ -1442,14 +1376,13 @@ static void cl_req_free(const struct lu_env *env, struct cl_req *req)
 	LASSERT(req->crq_nrpages == 0);
 	LINVRNT(list_empty(&req->crq_layers));
 	LINVRNT(equi(req->crq_nrobjs > 0, req->crq_o != NULL));
-	ENTRY;
 
 	if (req->crq_o != NULL) {
 		for (i = 0; i < req->crq_nrobjs; ++i) {
 			struct cl_object *obj = req->crq_o[i].ro_obj;
 			if (obj != NULL) {
 				lu_object_ref_del_at(&obj->co_lu,
-						     req->crq_o[i].ro_obj_ref,
+						     &req->crq_o[i].ro_obj_ref,
 						     "cl_req", req);
 				cl_object_put(env, obj);
 			}
@@ -1457,7 +1390,6 @@ static void cl_req_free(const struct lu_env *env, struct cl_req *req)
 		OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof req->crq_o[0]);
 	}
 	OBD_FREE_PTR(req);
-	EXIT;
 }
 
 static int cl_req_init(const struct lu_env *env, struct cl_req *req,
@@ -1467,7 +1399,6 @@ static int cl_req_init(const struct lu_env *env, struct cl_req *req,
 	struct cl_page_slice *slice;
 	int result;
 
-	ENTRY;
 	result = 0;
 	page = cl_page_top(page);
 	do {
@@ -1482,7 +1413,7 @@ static int cl_req_init(const struct lu_env *env, struct cl_req *req,
 		}
 		page = page->cp_child;
 	} while (page != NULL && result == 0);
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -1493,7 +1424,6 @@ void cl_req_completion(const struct lu_env *env, struct cl_req *req, int rc)
 {
 	struct cl_req_slice *slice;
 
-	ENTRY;
 	/*
 	 * for the lack of list_for_each_entry_reverse_safe()...
 	 */
@@ -1505,7 +1435,6 @@ void cl_req_completion(const struct lu_env *env, struct cl_req *req, int rc)
 			slice->crs_ops->cro_completion(env, slice, rc);
 	}
 	cl_req_free(env, req);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_req_completion);
 
@@ -1518,7 +1447,6 @@ struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page,
 	struct cl_req *req;
 
 	LINVRNT(nr_objects > 0);
-	ENTRY;
 
 	OBD_ALLOC_PTR(req);
 	if (req != NULL) {
@@ -1539,7 +1467,7 @@ struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page,
 		}
 	} else
 		req = ERR_PTR(-ENOMEM);
-	RETURN(req);
+	return req;
 }
 EXPORT_SYMBOL(cl_req_alloc);
 
@@ -1553,7 +1481,6 @@ void cl_req_page_add(const struct lu_env *env,
 	struct cl_req_obj *rqo;
 	int i;
 
-	ENTRY;
 	page = cl_page_top(page);
 
 	LASSERT(list_empty(&page->cp_flight));
@@ -1570,13 +1497,12 @@ void cl_req_page_add(const struct lu_env *env,
 		if (rqo->ro_obj == NULL) {
 			rqo->ro_obj = obj;
 			cl_object_get(obj);
-			rqo->ro_obj_ref = lu_object_ref_add(&obj->co_lu,
-							    "cl_req", req);
+			lu_object_ref_add_at(&obj->co_lu, &rqo->ro_obj_ref,
+					     "cl_req", req);
 			break;
 		}
 	}
 	LASSERT(i < req->crq_nrobjs);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_req_page_add);
 
@@ -1587,7 +1513,6 @@ void cl_req_page_done(const struct lu_env *env, struct cl_page *page)
 {
 	struct cl_req *req = page->cp_req;
 
-	ENTRY;
 	page = cl_page_top(page);
 
 	LASSERT(!list_empty(&page->cp_flight));
@@ -1596,7 +1521,6 @@ void cl_req_page_done(const struct lu_env *env, struct cl_page *page)
 	list_del_init(&page->cp_flight);
 	--req->crq_nrpages;
 	page->cp_req = NULL;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_req_page_done);
 
@@ -1610,7 +1534,6 @@ int cl_req_prep(const struct lu_env *env, struct cl_req *req)
 	int result;
 	const struct cl_req_slice *slice;
 
-	ENTRY;
 	/*
 	 * Check that the caller of cl_req_alloc() didn't lie about the number
 	 * of objects.
@@ -1626,7 +1549,7 @@ int cl_req_prep(const struct lu_env *env, struct cl_req *req)
 				break;
 		}
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_req_prep);
 
@@ -1643,7 +1566,6 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req,
 	int i;
 
 	LASSERT(!list_empty(&req->crq_pages));
-	ENTRY;
 
 	/* Take any page to use as a model. */
 	page = list_entry(req->crq_pages.next, struct cl_page, cp_flight);
@@ -1662,7 +1584,6 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req,
 							     attr + i, flags);
 		}
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_req_attr_set);
 
@@ -1675,12 +1596,10 @@ EXPORT_SYMBOL(cl_req_attr_set);
  */
 void cl_sync_io_init(struct cl_sync_io *anchor, int nrpages)
 {
-	ENTRY;
 	init_waitqueue_head(&anchor->csi_waitq);
 	atomic_set(&anchor->csi_sync_nr, nrpages);
 	atomic_set(&anchor->csi_barrier, nrpages > 0);
 	anchor->csi_sync_rc = 0;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_sync_io_init);
 
@@ -1695,7 +1614,6 @@ int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io,
 	struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(timeout),
 						  NULL, NULL, NULL);
 	int rc;
-	ENTRY;
 
 	LASSERT(timeout >= 0);
 
@@ -1725,7 +1643,7 @@ int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io,
 	}
 
 	POISON(anchor, 0x5a, sizeof *anchor);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(cl_sync_io_wait);
 
@@ -1734,7 +1652,6 @@ EXPORT_SYMBOL(cl_sync_io_wait);
  */
 void cl_sync_io_note(struct cl_sync_io *anchor, int ioret)
 {
-	ENTRY;
 	if (anchor->csi_sync_rc == 0 && ioret < 0)
 		anchor->csi_sync_rc = ioret;
 	/*
@@ -1748,6 +1665,5 @@ void cl_sync_io_note(struct cl_sync_io *anchor, int ioret)
 		/* it's safe to nuke or reuse anchor now */
 		atomic_set(&anchor->csi_barrier, 0);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_sync_io_note);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
index d34e044..749eb08 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
@@ -191,12 +191,10 @@ void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice,
 		       struct cl_object *obj,
 		       const struct cl_lock_operations *ops)
 {
-	ENTRY;
 	slice->cls_lock = lock;
 	list_add_tail(&slice->cls_linkage, &lock->cll_layers);
 	slice->cls_obj = obj;
 	slice->cls_ops = ops;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_slice_add);
 
@@ -254,7 +252,6 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock)
 
 	LINVRNT(!cl_lock_is_mutexed(lock));
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "free lock", lock);
 	might_sleep();
 	while (!list_empty(&lock->cll_layers)) {
@@ -267,13 +264,12 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock)
 	}
 	CS_LOCK_DEC(obj, total);
 	CS_LOCKSTATE_DEC(obj, lock->cll_state);
-	lu_object_ref_del_at(&obj->co_lu, lock->cll_obj_ref, "cl_lock", lock);
+	lu_object_ref_del_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock", lock);
 	cl_object_put(env, obj);
 	lu_ref_fini(&lock->cll_reference);
 	lu_ref_fini(&lock->cll_holders);
 	mutex_destroy(&lock->cll_guard);
 	OBD_SLAB_FREE_PTR(lock, cl_lock_kmem);
-	EXIT;
 }
 
 /**
@@ -290,7 +286,6 @@ void cl_lock_put(const struct lu_env *env, struct cl_lock *lock)
 	struct cl_object	*obj;
 
 	LINVRNT(cl_lock_invariant(env, lock));
-	ENTRY;
 	obj = lock->cll_descr.cld_obj;
 	LINVRNT(obj != NULL);
 
@@ -304,7 +299,6 @@ void cl_lock_put(const struct lu_env *env, struct cl_lock *lock)
 		}
 		CS_LOCK_DEC(obj, busy);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_put);
 
@@ -366,15 +360,14 @@ static struct cl_lock *cl_lock_alloc(const struct lu_env *env,
 	struct cl_lock	  *lock;
 	struct lu_object_header *head;
 
-	ENTRY;
 	OBD_SLAB_ALLOC_PTR_GFP(lock, cl_lock_kmem, __GFP_IO);
 	if (lock != NULL) {
 		atomic_set(&lock->cll_ref, 1);
 		lock->cll_descr = *descr;
 		lock->cll_state = CLS_NEW;
 		cl_object_get(obj);
-		lock->cll_obj_ref = lu_object_ref_add(&obj->co_lu,
-						      "cl_lock", lock);
+		lu_object_ref_add_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock",
+				     lock);
 		INIT_LIST_HEAD(&lock->cll_layers);
 		INIT_LIST_HEAD(&lock->cll_linkage);
 		INIT_LIST_HEAD(&lock->cll_inclosure);
@@ -401,7 +394,7 @@ static struct cl_lock *cl_lock_alloc(const struct lu_env *env,
 		}
 	} else
 		lock = ERR_PTR(-ENOMEM);
-	RETURN(lock);
+	return lock;
 }
 
 /**
@@ -468,13 +461,12 @@ static int cl_lock_fits_into(const struct lu_env *env,
 	const struct cl_lock_slice *slice;
 
 	LINVRNT(cl_lock_invariant_trusted(env, lock));
-	ENTRY;
 	list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
 		if (slice->cls_ops->clo_fits_into != NULL &&
 		    !slice->cls_ops->clo_fits_into(env, slice, need, io))
-			RETURN(0);
+			return 0;
 	}
-	RETURN(1);
+	return 1;
 }
 
 static struct cl_lock *cl_lock_lookup(const struct lu_env *env,
@@ -485,8 +477,6 @@ static struct cl_lock *cl_lock_lookup(const struct lu_env *env,
 	struct cl_lock	  *lock;
 	struct cl_object_header *head;
 
-	ENTRY;
-
 	head = cl_object_header(obj);
 	LINVRNT(spin_is_locked(&head->coh_lock_guard));
 	CS_LOCK_INC(obj, lookup);
@@ -504,10 +494,10 @@ static struct cl_lock *cl_lock_lookup(const struct lu_env *env,
 		if (matched) {
 			cl_lock_get_trust(lock);
 			CS_LOCK_INC(obj, hit);
-			RETURN(lock);
+			return lock;
 		}
 	}
-	RETURN(NULL);
+	return NULL;
 }
 
 /**
@@ -528,8 +518,6 @@ static struct cl_lock *cl_lock_find(const struct lu_env *env,
 	struct cl_object	*obj;
 	struct cl_lock	  *lock;
 
-	ENTRY;
-
 	obj  = need->cld_obj;
 	head = cl_object_header(obj);
 
@@ -561,7 +549,7 @@ static struct cl_lock *cl_lock_find(const struct lu_env *env,
 			}
 		}
 	}
-	RETURN(lock);
+	return lock;
 }
 
 /**
@@ -630,13 +618,12 @@ const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock,
 	const struct cl_lock_slice *slice;
 
 	LINVRNT(cl_lock_invariant_trusted(NULL, lock));
-	ENTRY;
 
 	list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
 		if (slice->cls_obj->co_lu.lo_dev->ld_type == dtype)
-			RETURN(slice);
+			return slice;
 	}
-	RETURN(NULL);
+	return NULL;
 }
 EXPORT_SYMBOL(cl_lock_at);
 
@@ -705,7 +692,6 @@ int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock)
 	int result;
 
 	LINVRNT(cl_lock_invariant_trusted(env, lock));
-	ENTRY;
 
 	result = 0;
 	if (lock->cll_guarder == current) {
@@ -717,7 +703,7 @@ int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock)
 		cl_lock_mutex_tail(env, lock);
 	} else
 		result = -EBUSY;
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_lock_mutex_try);
 
@@ -784,7 +770,6 @@ static void cl_lock_cancel0(const struct lu_env *env, struct cl_lock *lock)
 {
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
-	ENTRY;
 	if (!(lock->cll_flags & CLF_CANCELLED)) {
 		const struct cl_lock_slice *slice;
 
@@ -795,7 +780,6 @@ static void cl_lock_cancel0(const struct lu_env *env, struct cl_lock *lock)
 				slice->cls_ops->clo_cancel(env, slice);
 		}
 	}
-	EXIT;
 }
 
 static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock)
@@ -806,7 +790,6 @@ static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock)
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 
-	ENTRY;
 	if (lock->cll_state < CLS_FREEING) {
 		LASSERT(lock->cll_state != CLS_INTRANSIT);
 		cl_lock_state_set(env, lock, CLS_FREEING);
@@ -836,7 +819,6 @@ static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock)
 		 * existing references goes away.
 		 */
 	}
-	EXIT;
 }
 
 /**
@@ -886,7 +868,6 @@ void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock,
 	LINVRNT(cl_lock_invariant(env, lock));
 	LASSERT(lock->cll_holds > 0);
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "hold release lock", lock);
 	lu_ref_del(&lock->cll_holders, scope, source);
 	cl_lock_hold_mod(env, lock, -1);
@@ -910,7 +891,6 @@ void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock,
 			cl_lock_delete0(env, lock);
 		}
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_hold_release);
 
@@ -939,7 +919,6 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
 	sigset_t blocked;
 	int result;
 
-	ENTRY;
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 	LASSERT(lock->cll_depth == 1);
@@ -976,7 +955,7 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
 		/* Restore old blocked signals */
 		cfs_restore_sigs(blocked);
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_lock_state_wait);
 
@@ -985,7 +964,6 @@ static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock,
 {
 	const struct cl_lock_slice *slice;
 
-	ENTRY;
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 
@@ -993,7 +971,6 @@ static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock,
 		if (slice->cls_ops->clo_state != NULL)
 			slice->cls_ops->clo_state(env, slice, state);
 	wake_up_all(&lock->cll_wq);
-	EXIT;
 }
 
 /**
@@ -1005,10 +982,8 @@ static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock,
  */
 void cl_lock_signal(const struct lu_env *env, struct cl_lock *lock)
 {
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "state signal lock", lock);
 	cl_lock_state_signal(env, lock, lock->cll_state);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_signal);
 
@@ -1025,7 +1000,6 @@ EXPORT_SYMBOL(cl_lock_signal);
 void cl_lock_state_set(const struct lu_env *env, struct cl_lock *lock,
 		       enum cl_lock_state state)
 {
-	ENTRY;
 	LASSERT(lock->cll_state <= state ||
 		(lock->cll_state == CLS_CACHED &&
 		 (state == CLS_HELD || /* lock found in cache */
@@ -1041,7 +1015,6 @@ void cl_lock_state_set(const struct lu_env *env, struct cl_lock *lock,
 		cl_lock_state_signal(env, lock, state);
 		lock->cll_state = state;
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_state_set);
 
@@ -1084,12 +1057,11 @@ int cl_use_try(const struct lu_env *env, struct cl_lock *lock, int atomic)
 	int result;
 	enum cl_lock_state state;
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "use lock", lock);
 
 	LASSERT(lock->cll_state == CLS_CACHED);
 	if (lock->cll_error)
-		RETURN(lock->cll_error);
+		return lock->cll_error;
 
 	result = -ENOSYS;
 	state = cl_lock_intransit(env, lock);
@@ -1129,7 +1101,7 @@ int cl_use_try(const struct lu_env *env, struct cl_lock *lock, int atomic)
 
 	}
 	cl_lock_extransit(env, lock, state);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_use_try);
 
@@ -1144,7 +1116,6 @@ static int cl_enqueue_kick(const struct lu_env *env,
 	int result;
 	const struct cl_lock_slice *slice;
 
-	ENTRY;
 	result = -ENOSYS;
 	list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
 		if (slice->cls_ops->clo_enqueue != NULL) {
@@ -1155,7 +1126,7 @@ static int cl_enqueue_kick(const struct lu_env *env,
 		}
 	}
 	LASSERT(result != -ENOSYS);
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -1176,7 +1147,6 @@ int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock,
 {
 	int result;
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "enqueue lock", lock);
 	do {
 		LINVRNT(cl_lock_is_mutexed(lock));
@@ -1219,7 +1189,7 @@ int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock,
 			LBUG();
 		}
 	} while (result == CLO_REPEAT);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_enqueue_try);
 
@@ -1235,7 +1205,6 @@ int cl_lock_enqueue_wait(const struct lu_env *env,
 {
 	struct cl_lock  *conflict;
 	int	      rc = 0;
-	ENTRY;
 
 	LASSERT(cl_lock_is_mutexed(lock));
 	LASSERT(lock->cll_state == CLS_QUEUING);
@@ -1265,7 +1234,7 @@ int cl_lock_enqueue_wait(const struct lu_env *env,
 		cl_lock_mutex_get(env, lock);
 
 	LASSERT(rc <= 0);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(cl_lock_enqueue_wait);
 
@@ -1274,8 +1243,6 @@ static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock,
 {
 	int result;
 
-	ENTRY;
-
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 	LASSERT(lock->cll_holds > 0);
@@ -1298,7 +1265,7 @@ static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock,
 	LASSERT(ergo(result == 0 && !(enqflags & CEF_AGL),
 		     lock->cll_state == CLS_ENQUEUED ||
 		     lock->cll_state == CLS_HELD));
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -1315,8 +1282,6 @@ int cl_enqueue(const struct lu_env *env, struct cl_lock *lock,
 {
 	int result;
 
-	ENTRY;
-
 	cl_lock_lockdep_acquire(env, lock, enqflags);
 	cl_lock_mutex_get(env, lock);
 	result = cl_enqueue_locked(env, lock, io, enqflags);
@@ -1325,7 +1290,7 @@ int cl_enqueue(const struct lu_env *env, struct cl_lock *lock,
 		cl_lock_lockdep_release(env, lock);
 	LASSERT(ergo(result == 0, lock->cll_state == CLS_ENQUEUED ||
 		     lock->cll_state == CLS_HELD));
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_enqueue);
 
@@ -1346,19 +1311,18 @@ int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock)
 	int			 result;
 	enum cl_lock_state	  state = CLS_NEW;
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "unuse lock", lock);
 
 	if (lock->cll_users > 1) {
 		cl_lock_user_del(env, lock);
-		RETURN(0);
+		return 0;
 	}
 
 	/* Only if the lock is in CLS_HELD or CLS_ENQUEUED state, it can hold
 	 * underlying resources. */
 	if (!(lock->cll_state == CLS_HELD || lock->cll_state == CLS_ENQUEUED)) {
 		cl_lock_user_del(env, lock);
-		RETURN(0);
+		return 0;
 	}
 
 	/*
@@ -1404,20 +1368,17 @@ int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock)
 		state = CLS_NEW;
 		cl_lock_extransit(env, lock, state);
 	}
-	RETURN(result ?: lock->cll_error);
+	return result ?: lock->cll_error;
 }
 EXPORT_SYMBOL(cl_unuse_try);
 
 static void cl_unuse_locked(const struct lu_env *env, struct cl_lock *lock)
 {
 	int result;
-	ENTRY;
 
 	result = cl_unuse_try(env, lock);
 	if (result)
 		CL_LOCK_DEBUG(D_ERROR, env, lock, "unuse return %d\n", result);
-
-	EXIT;
 }
 
 /**
@@ -1425,12 +1386,10 @@ static void cl_unuse_locked(const struct lu_env *env, struct cl_lock *lock)
  */
 void cl_unuse(const struct lu_env *env, struct cl_lock *lock)
 {
-	ENTRY;
 	cl_lock_mutex_get(env, lock);
 	cl_unuse_locked(env, lock);
 	cl_lock_mutex_put(env, lock);
 	cl_lock_lockdep_release(env, lock);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_unuse);
 
@@ -1449,7 +1408,6 @@ int cl_wait_try(const struct lu_env *env, struct cl_lock *lock)
 	const struct cl_lock_slice *slice;
 	int			 result;
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "wait lock try", lock);
 	do {
 		LINVRNT(cl_lock_is_mutexed(lock));
@@ -1489,7 +1447,7 @@ int cl_wait_try(const struct lu_env *env, struct cl_lock *lock)
 			cl_lock_state_set(env, lock, CLS_HELD);
 		}
 	} while (result == CLO_REPEAT);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_wait_try);
 
@@ -1506,7 +1464,6 @@ int cl_wait(const struct lu_env *env, struct cl_lock *lock)
 {
 	int result;
 
-	ENTRY;
 	cl_lock_mutex_get(env, lock);
 
 	LINVRNT(cl_lock_invariant(env, lock));
@@ -1530,7 +1487,7 @@ int cl_wait(const struct lu_env *env, struct cl_lock *lock)
 	cl_lock_trace(D_DLMTRACE, env, "wait lock", lock);
 	cl_lock_mutex_put(env, lock);
 	LASSERT(ergo(result == 0, lock->cll_state == CLS_HELD));
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_wait);
 
@@ -1544,7 +1501,6 @@ unsigned long cl_lock_weigh(const struct lu_env *env, struct cl_lock *lock)
 	unsigned long pound;
 	unsigned long ounce;
 
-	ENTRY;
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 
@@ -1557,7 +1513,7 @@ unsigned long cl_lock_weigh(const struct lu_env *env, struct cl_lock *lock)
 				pound = ~0UL;
 		}
 	}
-	RETURN(pound);
+	return pound;
 }
 EXPORT_SYMBOL(cl_lock_weigh);
 
@@ -1579,7 +1535,6 @@ int cl_lock_modify(const struct lu_env *env, struct cl_lock *lock,
 	struct cl_object_header    *hdr = cl_object_header(obj);
 	int result;
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "modify lock", lock);
 	/* don't allow object to change */
 	LASSERT(obj == desc->cld_obj);
@@ -1590,7 +1545,7 @@ int cl_lock_modify(const struct lu_env *env, struct cl_lock *lock,
 		if (slice->cls_ops->clo_modify != NULL) {
 			result = slice->cls_ops->clo_modify(env, slice, desc);
 			if (result != 0)
-				RETURN(result);
+				return result;
 		}
 	}
 	CL_LOCK_DEBUG(D_DLMTRACE, env, lock, " -> "DDESCR"@"DFID"\n",
@@ -1603,7 +1558,7 @@ int cl_lock_modify(const struct lu_env *env, struct cl_lock *lock,
 	spin_lock(&hdr->coh_lock_guard);
 	lock->cll_descr = *desc;
 	spin_unlock(&hdr->coh_lock_guard);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(cl_lock_modify);
 
@@ -1642,7 +1597,6 @@ int cl_lock_closure_build(const struct lu_env *env, struct cl_lock *lock,
 	const struct cl_lock_slice *slice;
 	int result;
 
-	ENTRY;
 	LINVRNT(cl_lock_is_mutexed(closure->clc_origin));
 	LINVRNT(cl_lock_invariant(env, closure->clc_origin));
 
@@ -1659,7 +1613,7 @@ int cl_lock_closure_build(const struct lu_env *env, struct cl_lock *lock,
 	}
 	if (result != 0)
 		cl_lock_disclosure(env, closure);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_lock_closure_build);
 
@@ -1674,7 +1628,7 @@ int cl_lock_enclosure(const struct lu_env *env, struct cl_lock *lock,
 		      struct cl_lock_closure *closure)
 {
 	int result = 0;
-	ENTRY;
+
 	cl_lock_trace(D_DLMTRACE, env, "enclosure lock", lock);
 	if (!cl_lock_mutex_try(env, lock)) {
 		/*
@@ -1706,7 +1660,7 @@ int cl_lock_enclosure(const struct lu_env *env, struct cl_lock *lock,
 		}
 		result = CLO_REPEAT;
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_lock_enclosure);
 
@@ -1766,13 +1720,11 @@ void cl_lock_delete(const struct lu_env *env, struct cl_lock *lock)
 	LASSERT(ergo(cl_lock_nesting(lock) == CNL_TOP,
 		     cl_lock_nr_mutexed(env) == 1));
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "delete lock", lock);
 	if (lock->cll_holds == 0)
 		cl_lock_delete0(env, lock);
 	else
 		lock->cll_flags |= CLF_DOOMED;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_delete);
 
@@ -1791,7 +1743,6 @@ void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error)
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 
-	ENTRY;
 	if (lock->cll_error == 0 && error != 0) {
 		cl_lock_trace(D_DLMTRACE, env, "set lock error", lock);
 		lock->cll_error = error;
@@ -1799,7 +1750,6 @@ void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error)
 		cl_lock_cancel(env, lock);
 		cl_lock_delete(env, lock);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_error);
 
@@ -1819,13 +1769,11 @@ void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock)
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "cancel lock", lock);
 	if (lock->cll_holds == 0)
 		cl_lock_cancel0(env, lock);
 	else
 		lock->cll_flags |= CLF_CANCELPEND;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_cancel);
 
@@ -1843,8 +1791,6 @@ struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env,
 	struct cl_lock	  *lock;
 	struct cl_lock_descr    *need;
 
-	ENTRY;
-
 	head = cl_object_header(obj);
 	need = &cl_env_info(env)->clt_descr;
 	lock = NULL;
@@ -1878,7 +1824,7 @@ struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env,
 		}
 	}
 	spin_unlock(&head->coh_lock_guard);
-	RETURN(lock);
+	return lock;
 }
 EXPORT_SYMBOL(cl_lock_at_pgoff);
 
@@ -1979,7 +1925,6 @@ int cl_lock_discard_pages(const struct lu_env *env, struct cl_lock *lock)
 	int result;
 
 	LINVRNT(cl_lock_invariant(env, lock));
-	ENTRY;
 
 	io->ci_obj = cl_object_top(descr->cld_obj);
 	io->ci_ignore_layout = 1;
@@ -2001,7 +1946,7 @@ int cl_lock_discard_pages(const struct lu_env *env, struct cl_lock *lock)
 	} while (res != CLP_GANG_OKAY);
 out:
 	cl_io_fini(env, io);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_lock_discard_pages);
 
@@ -2018,7 +1963,6 @@ void cl_locks_prune(const struct lu_env *env, struct cl_object *obj, int cancel)
 	struct cl_object_header *head;
 	struct cl_lock	  *lock;
 
-	ENTRY;
 	head = cl_object_header(obj);
 	/*
 	 * If locks are destroyed without cancellation, all pages must be
@@ -2059,7 +2003,6 @@ again:
 		spin_lock(&head->coh_lock_guard);
 	}
 	spin_unlock(&head->coh_lock_guard);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_locks_prune);
 
@@ -2070,8 +2013,6 @@ static struct cl_lock *cl_lock_hold_mutex(const struct lu_env *env,
 {
 	struct cl_lock *lock;
 
-	ENTRY;
-
 	while (1) {
 		lock = cl_lock_find(env, io, need);
 		if (IS_ERR(lock))
@@ -2087,7 +2028,7 @@ static struct cl_lock *cl_lock_hold_mutex(const struct lu_env *env,
 		cl_lock_mutex_put(env, lock);
 		cl_lock_put(env, lock);
 	}
-	RETURN(lock);
+	return lock;
 }
 
 /**
@@ -2103,12 +2044,10 @@ struct cl_lock *cl_lock_hold(const struct lu_env *env, const struct cl_io *io,
 {
 	struct cl_lock *lock;
 
-	ENTRY;
-
 	lock = cl_lock_hold_mutex(env, io, need, scope, source);
 	if (!IS_ERR(lock))
 		cl_lock_mutex_put(env, lock);
-	RETURN(lock);
+	return lock;
 }
 EXPORT_SYMBOL(cl_lock_hold);
 
@@ -2124,7 +2063,6 @@ struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io,
 	int		   rc;
 	__u32		 enqflags = need->cld_enq_flags;
 
-	ENTRY;
 	do {
 		lock = cl_lock_hold_mutex(env, io, need, scope, source);
 		if (IS_ERR(lock))
@@ -2156,7 +2094,7 @@ struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io,
 			lock = ERR_PTR(rc);
 		}
 	} while (rc == 0);
-	RETURN(lock);
+	return lock;
 }
 EXPORT_SYMBOL(cl_lock_request);
 
@@ -2170,12 +2108,10 @@ void cl_lock_hold_add(const struct lu_env *env, struct cl_lock *lock,
 	LINVRNT(cl_lock_invariant(env, lock));
 	LASSERT(lock->cll_state != CLS_FREEING);
 
-	ENTRY;
 	cl_lock_hold_mod(env, lock, +1);
 	cl_lock_get(lock);
 	lu_ref_add(&lock->cll_holders, scope, source);
 	lu_ref_add(&lock->cll_reference, scope, source);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_hold_add);
 
@@ -2187,11 +2123,9 @@ void cl_lock_unhold(const struct lu_env *env, struct cl_lock *lock,
 		    const char *scope, const void *source)
 {
 	LINVRNT(cl_lock_invariant(env, lock));
-	ENTRY;
 	cl_lock_hold_release(env, lock, scope, source);
 	lu_ref_del(&lock->cll_reference, scope, source);
 	cl_lock_put(env, lock);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_unhold);
 
@@ -2202,14 +2136,12 @@ void cl_lock_release(const struct lu_env *env, struct cl_lock *lock,
 		     const char *scope, const void *source)
 {
 	LINVRNT(cl_lock_invariant(env, lock));
-	ENTRY;
 	cl_lock_trace(D_DLMTRACE, env, "release lock", lock);
 	cl_lock_mutex_get(env, lock);
 	cl_lock_hold_release(env, lock, scope, source);
 	cl_lock_mutex_put(env, lock);
 	lu_ref_del(&lock->cll_reference, scope, source);
 	cl_lock_put(env, lock);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_release);
 
@@ -2218,9 +2150,7 @@ void cl_lock_user_add(const struct lu_env *env, struct cl_lock *lock)
 	LINVRNT(cl_lock_is_mutexed(lock));
 	LINVRNT(cl_lock_invariant(env, lock));
 
-	ENTRY;
 	cl_lock_used_mod(env, lock, +1);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_user_add);
 
@@ -2230,11 +2160,9 @@ void cl_lock_user_del(const struct lu_env *env, struct cl_lock *lock)
 	LINVRNT(cl_lock_invariant(env, lock));
 	LASSERT(lock->cll_users > 0);
 
-	ENTRY;
 	cl_lock_used_mod(env, lock, -1);
 	if (lock->cll_users == 0)
 		wake_up_all(&lock->cll_wq);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lock_user_del);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c
index cdb5fba..7b0e9d2 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c
@@ -79,7 +79,6 @@ int cl_object_header_init(struct cl_object_header *h)
 {
 	int result;
 
-	ENTRY;
 	result = lu_object_header_init(&h->coh_lu);
 	if (result == 0) {
 		spin_lock_init(&h->coh_page_guard);
@@ -94,7 +93,7 @@ int cl_object_header_init(struct cl_object_header *h)
 		INIT_LIST_HEAD(&h->coh_locks);
 		h->coh_page_bufsize = ALIGN(sizeof(struct cl_page), 8);
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_object_header_init);
 
@@ -222,7 +221,6 @@ int cl_object_attr_get(const struct lu_env *env, struct cl_object *obj,
 	int result;
 
 	LASSERT(spin_is_locked(cl_object_attr_guard(obj)));
-	ENTRY;
 
 	top = obj->co_lu.lo_header;
 	result = 0;
@@ -236,7 +234,7 @@ int cl_object_attr_get(const struct lu_env *env, struct cl_object *obj,
 			}
 		}
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_object_attr_get);
 
@@ -254,7 +252,6 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj,
 	int result;
 
 	LASSERT(spin_is_locked(cl_object_attr_guard(obj)));
-	ENTRY;
 
 	top = obj->co_lu.lo_header;
 	result = 0;
@@ -269,7 +266,7 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj,
 			}
 		}
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_object_attr_set);
 
@@ -287,7 +284,6 @@ int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj,
 	struct lu_object_header *top;
 	int result;
 
-	ENTRY;
 	top = obj->co_lu.lo_header;
 	result = 0;
 	list_for_each_entry_reverse(obj, &top->loh_layers,
@@ -303,7 +299,7 @@ int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj,
 			 "ctime: "LPU64" blocks: "LPU64"\n",
 			 lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime,
 			 lvb->lvb_ctime, lvb->lvb_blocks);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_object_glimpse);
 
@@ -316,7 +312,6 @@ int cl_conf_set(const struct lu_env *env, struct cl_object *obj,
 	struct lu_object_header *top;
 	int result;
 
-	ENTRY;
 	top = obj->co_lu.lo_header;
 	result = 0;
 	list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
@@ -326,7 +321,7 @@ int cl_conf_set(const struct lu_env *env, struct cl_object *obj,
 				break;
 		}
 	}
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_conf_set);
 
@@ -362,10 +357,8 @@ EXPORT_SYMBOL(cl_object_kill);
  */
 void cl_object_prune(const struct lu_env *env, struct cl_object *obj)
 {
-	ENTRY;
 	cl_pages_prune(env, obj);
 	cl_locks_prune(env, obj, 1);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_object_prune);
 
@@ -941,13 +934,11 @@ EXPORT_SYMBOL(cl_env_nested_put);
  */
 void cl_attr2lvb(struct ost_lvb *lvb, const struct cl_attr *attr)
 {
-	ENTRY;
 	lvb->lvb_size   = attr->cat_size;
 	lvb->lvb_mtime  = attr->cat_mtime;
 	lvb->lvb_atime  = attr->cat_atime;
 	lvb->lvb_ctime  = attr->cat_ctime;
 	lvb->lvb_blocks = attr->cat_blocks;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_attr2lvb);
 
@@ -958,13 +949,11 @@ EXPORT_SYMBOL(cl_attr2lvb);
  */
 void cl_lvb2attr(struct cl_attr *attr, const struct ost_lvb *lvb)
 {
-	ENTRY;
 	attr->cat_size   = lvb->lvb_size;
 	attr->cat_mtime  = lvb->lvb_mtime;
 	attr->cat_atime  = lvb->lvb_atime;
 	attr->cat_ctime  = lvb->lvb_ctime;
 	attr->cat_blocks = lvb->lvb_blocks;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_lvb2attr);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c
index bb93359..2a5ce37 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_page.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c
@@ -108,17 +108,16 @@ cl_page_at_trusted(const struct cl_page *page,
 		   const struct lu_device_type *dtype)
 {
 	const struct cl_page_slice *slice;
-	ENTRY;
 
 	page = cl_page_top_trusted((struct cl_page *)page);
 	do {
 		list_for_each_entry(slice, &page->cp_layers, cpl_linkage) {
 			if (slice->cpl_obj->co_lu.lo_dev->ld_type == dtype)
-				RETURN(slice);
+				return slice;
 		}
 		page = page->cp_child;
 	} while (page != NULL);
-	RETURN(NULL);
+	return NULL;
 }
 
 /**
@@ -167,7 +166,6 @@ int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj,
 	unsigned int	     j;
 	int		      res = CLP_GANG_OKAY;
 	int		      tree_lock = 1;
-	ENTRY;
 
 	idx = start;
 	hdr = cl_object_header(obj);
@@ -243,7 +241,7 @@ int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj,
 	}
 	if (tree_lock)
 		spin_unlock(&hdr->coh_page_guard);
-	RETURN(res);
+	return res;
 }
 EXPORT_SYMBOL(cl_page_gang_lookup);
 
@@ -258,7 +256,6 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page)
 	PASSERT(env, page, page->cp_parent == NULL);
 	PASSERT(env, page, page->cp_state == CPS_FREEING);
 
-	ENTRY;
 	might_sleep();
 	while (!list_empty(&page->cp_layers)) {
 		struct cl_page_slice *slice;
@@ -270,11 +267,10 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page)
 	}
 	CS_PAGE_DEC(obj, total);
 	CS_PAGESTATE_DEC(obj, page->cp_state);
-	lu_object_ref_del_at(&obj->co_lu, page->cp_obj_ref, "cl_page", page);
+	lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page);
 	cl_object_put(env, obj);
 	lu_ref_fini(&page->cp_reference);
 	OBD_FREE(page, pagesize);
-	EXIT;
 }
 
 /**
@@ -295,7 +291,6 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env,
 	struct cl_page	  *page;
 	struct lu_object_header *head;
 
-	ENTRY;
 	OBD_ALLOC_GFP(page, cl_object_header(o)->coh_page_bufsize,
 			__GFP_IO);
 	if (page != NULL) {
@@ -305,7 +300,8 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env,
 			atomic_inc(&page->cp_ref);
 		page->cp_obj = o;
 		cl_object_get(o);
-		page->cp_obj_ref = lu_object_ref_add(&o->co_lu, "cl_page",page);
+		lu_object_ref_add_at(&o->co_lu, &page->cp_obj_ref, "cl_page",
+				     page);
 		page->cp_index = ind;
 		cl_page_state_set_trust(page, CPS_CACHED);
 		page->cp_type = type;
@@ -336,7 +332,7 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env,
 	} else {
 		page = ERR_PTR(-ENOMEM);
 	}
-	RETURN(page);
+	return page;
 }
 
 /**
@@ -364,8 +360,6 @@ static struct cl_page *cl_page_find0(const struct lu_env *env,
 	LASSERT(type == CPT_CACHEABLE || type == CPT_TRANSIENT);
 	might_sleep();
 
-	ENTRY;
-
 	hdr = cl_object_header(o);
 	CS_PAGE_INC(o, lookup);
 
@@ -395,13 +389,13 @@ static struct cl_page *cl_page_find0(const struct lu_env *env,
 
 	if (page != NULL) {
 		CS_PAGE_INC(o, hit);
-		RETURN(page);
+		return page;
 	}
 
 	/* allocate and initialize cl_page */
 	page = cl_page_alloc(env, o, idx, vmpage, type);
 	if (IS_ERR(page))
-		RETURN(page);
+		return page;
 
 	if (type == CPT_TRANSIENT) {
 		if (parent) {
@@ -409,7 +403,7 @@ static struct cl_page *cl_page_find0(const struct lu_env *env,
 			page->cp_parent = parent;
 			parent->cp_child = page;
 		}
-		RETURN(page);
+		return page;
 	}
 
 	/*
@@ -450,7 +444,7 @@ static struct cl_page *cl_page_find0(const struct lu_env *env,
 		cl_page_delete0(env, ghost, 0);
 		cl_page_free(env, ghost);
 	}
-	RETURN(page);
+	return page;
 }
 
 struct cl_page *cl_page_find(const struct lu_env *env, struct cl_object *o,
@@ -553,7 +547,6 @@ static void cl_page_state_set0(const struct lu_env *env,
 		}
 	};
 
-	ENTRY;
 	old = page->cp_state;
 	PASSERT(env, page, allowed_transitions[old][state]);
 	CL_PAGE_HEADER(D_TRACE, env, page, "%d -> %d\n", old, state);
@@ -566,7 +559,6 @@ static void cl_page_state_set0(const struct lu_env *env,
 		CS_PAGESTATE_INC(page->cp_obj, state);
 		cl_page_state_set_trust(page, state);
 	}
-	EXIT;
 }
 
 static void cl_page_state_set(const struct lu_env *env,
@@ -585,9 +577,7 @@ static void cl_page_state_set(const struct lu_env *env,
  */
 void cl_page_get(struct cl_page *page)
 {
-	ENTRY;
 	cl_page_get_trust(page);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_get);
 
@@ -604,7 +594,6 @@ void cl_page_put(const struct lu_env *env, struct cl_page *page)
 {
 	PASSERT(env, page, atomic_read(&page->cp_ref) > !!page->cp_parent);
 
-	ENTRY;
 	CL_PAGE_HEADER(D_TRACE, env, page, "%d\n",
 		       atomic_read(&page->cp_ref));
 
@@ -620,8 +609,6 @@ void cl_page_put(const struct lu_env *env, struct cl_page *page)
 		 */
 		cl_page_free(env, page);
 	}
-
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_put);
 
@@ -640,7 +627,7 @@ struct page *cl_page_vmpage(const struct lu_env *env, struct cl_page *page)
 	do {
 		list_for_each_entry(slice, &page->cp_layers, cpl_linkage) {
 			if (slice->cpl_ops->cpo_vmpage != NULL)
-				RETURN(slice->cpl_ops->cpo_vmpage(env, slice));
+				return slice->cpl_ops->cpo_vmpage(env, slice);
 		}
 		page = page->cp_child;
 	} while (page != NULL);
@@ -656,7 +643,6 @@ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj)
 	struct cl_page *top;
 	struct cl_page *page;
 
-	ENTRY;
 	KLASSERT(PageLocked(vmpage));
 
 	/*
@@ -671,7 +657,7 @@ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj)
 	 */
 	top = (struct cl_page *)vmpage->private;
 	if (top == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	for (page = top; page != NULL; page = page->cp_child) {
 		if (cl_object_same(page->cp_obj, obj)) {
@@ -680,7 +666,7 @@ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj)
 		}
 	}
 	LASSERT(ergo(page, page->cp_type == CPT_CACHEABLE));
-	RETURN(page);
+	return page;
 }
 EXPORT_SYMBOL(cl_vmpage_page);
 
@@ -785,11 +771,10 @@ static int cl_page_invoke(const struct lu_env *env,
 
 {
 	PINVRNT(env, page, cl_object_same(page->cp_obj, io->ci_obj));
-	ENTRY;
-	RETURN(CL_PAGE_INVOKE(env, page, op,
+	return CL_PAGE_INVOKE(env, page, op,
 			      (const struct lu_env *,
 			       const struct cl_page_slice *, struct cl_io *),
-			      io));
+			      io);
 }
 
 static void cl_page_invoid(const struct lu_env *env,
@@ -797,16 +782,13 @@ static void cl_page_invoid(const struct lu_env *env,
 
 {
 	PINVRNT(env, page, cl_object_same(page->cp_obj, io->ci_obj));
-	ENTRY;
 	CL_PAGE_INVOID(env, page, op,
 		       (const struct lu_env *,
 			const struct cl_page_slice *, struct cl_io *), io);
-	EXIT;
 }
 
 static void cl_page_owner_clear(struct cl_page *page)
 {
-	ENTRY;
 	for (page = cl_page_top(page); page != NULL; page = page->cp_child) {
 		if (page->cp_owner != NULL) {
 			LASSERT(page->cp_owner->ci_owned_nr > 0);
@@ -815,17 +797,14 @@ static void cl_page_owner_clear(struct cl_page *page)
 			page->cp_task = NULL;
 		}
 	}
-	EXIT;
 }
 
 static void cl_page_owner_set(struct cl_page *page)
 {
-	ENTRY;
 	for (page = cl_page_top(page); page != NULL; page = page->cp_child) {
 		LASSERT(page->cp_owner != NULL);
 		page->cp_owner->ci_owned_nr++;
 	}
-	EXIT;
 }
 
 void cl_page_disown0(const struct lu_env *env,
@@ -833,7 +812,6 @@ void cl_page_disown0(const struct lu_env *env,
 {
 	enum cl_page_state state;
 
-	ENTRY;
 	state = pg->cp_state;
 	PINVRNT(env, pg, state == CPS_OWNED || state == CPS_FREEING);
 	PINVRNT(env, pg, cl_page_invariant(pg));
@@ -850,7 +828,6 @@ void cl_page_disown0(const struct lu_env *env,
 			       (const struct lu_env *,
 				const struct cl_page_slice *, struct cl_io *),
 			       io);
-	EXIT;
 }
 
 /**
@@ -859,8 +836,7 @@ void cl_page_disown0(const struct lu_env *env,
 int cl_page_is_owned(const struct cl_page *pg, const struct cl_io *io)
 {
 	LINVRNT(cl_object_same(pg->cp_obj, io->ci_obj));
-	ENTRY;
-	RETURN(pg->cp_state == CPS_OWNED && pg->cp_owner == io);
+	return pg->cp_state == CPS_OWNED && pg->cp_owner == io;
 }
 EXPORT_SYMBOL(cl_page_is_owned);
 
@@ -891,7 +867,6 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io,
 
 	PINVRNT(env, pg, !cl_page_is_owned(pg, io));
 
-	ENTRY;
 	pg = cl_page_top(pg);
 	io = cl_io_top(io);
 
@@ -918,7 +893,7 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io,
 		}
 	}
 	PINVRNT(env, pg, ergo(result == 0, cl_page_invariant(pg)));
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -960,7 +935,6 @@ void cl_page_assume(const struct lu_env *env,
 {
 	PINVRNT(env, pg, cl_object_same(pg->cp_obj, io->ci_obj));
 
-	ENTRY;
 	pg = cl_page_top(pg);
 	io = cl_io_top(io);
 
@@ -970,7 +944,6 @@ void cl_page_assume(const struct lu_env *env,
 	pg->cp_task = current;
 	cl_page_owner_set(pg);
 	cl_page_state_set(env, pg, CPS_OWNED);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_assume);
 
@@ -991,7 +964,6 @@ void cl_page_unassume(const struct lu_env *env,
 	PINVRNT(env, pg, cl_page_is_owned(pg, io));
 	PINVRNT(env, pg, cl_page_invariant(pg));
 
-	ENTRY;
 	pg = cl_page_top(pg);
 	io = cl_io_top(io);
 	cl_page_owner_clear(pg);
@@ -1000,7 +972,6 @@ void cl_page_unassume(const struct lu_env *env,
 			       (const struct lu_env *,
 				const struct cl_page_slice *, struct cl_io *),
 			       io);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_unassume);
 
@@ -1020,11 +991,9 @@ void cl_page_disown(const struct lu_env *env,
 {
 	PINVRNT(env, pg, cl_page_is_owned(pg, io));
 
-	ENTRY;
 	pg = cl_page_top(pg);
 	io = cl_io_top(io);
 	cl_page_disown0(env, io, pg);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_disown);
 
@@ -1057,7 +1026,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg,
 			    int radix)
 {
 	struct cl_page *tmp = pg;
-	ENTRY;
 
 	PASSERT(env, pg, pg == cl_page_top(pg));
 	PASSERT(env, pg, pg->cp_state != CPS_FREEING);
@@ -1102,8 +1070,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg,
 			cl_page_put(env, tmp);
 		}
 	}
-
-	EXIT;
 }
 
 /**
@@ -1134,9 +1100,7 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg,
 void cl_page_delete(const struct lu_env *env, struct cl_page *pg)
 {
 	PINVRNT(env, pg, cl_page_invariant(pg));
-	ENTRY;
 	cl_page_delete0(env, pg, 1);
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_delete);
 
@@ -1186,7 +1150,6 @@ int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg)
 	int result;
 	const struct cl_page_slice *slice;
 
-	ENTRY;
 	pg = cl_page_top_trusted((struct cl_page *)pg);
 	slice = container_of(pg->cp_layers.next,
 			     const struct cl_page_slice, cpl_linkage);
@@ -1198,14 +1161,13 @@ int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg)
 	 */
 	result = slice->cpl_ops->cpo_is_vmlocked(env, slice);
 	PASSERT(env, pg, result == -EBUSY || result == -ENODATA);
-	RETURN(result == -EBUSY);
+	return result == -EBUSY;
 }
 EXPORT_SYMBOL(cl_page_is_vmlocked);
 
 static enum cl_page_state cl_req_type_state(enum cl_req_type crt)
 {
-	ENTRY;
-	RETURN(crt == CRT_WRITE ? CPS_PAGEOUT : CPS_PAGEIN);
+	return crt == CRT_WRITE ? CPS_PAGEOUT : CPS_PAGEIN;
 }
 
 static void cl_page_io_start(const struct lu_env *env,
@@ -1214,10 +1176,8 @@ static void cl_page_io_start(const struct lu_env *env,
 	/*
 	 * Page is queued for IO, change its state.
 	 */
-	ENTRY;
 	cl_page_owner_clear(pg);
 	cl_page_state_set(env, pg, cl_req_type_state(crt));
-	EXIT;
 }
 
 /**
@@ -1280,7 +1240,6 @@ void cl_page_completion(const struct lu_env *env,
 	PASSERT(env, pg, pg->cp_req == NULL);
 	PASSERT(env, pg, pg->cp_state == cl_req_type_state(crt));
 
-	ENTRY;
 	CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, ioret);
 	if (crt == CRT_READ && ioret == 0) {
 		PASSERT(env, pg, !(pg->cp_flags & CPF_READ_COMPLETED));
@@ -1307,8 +1266,6 @@ void cl_page_completion(const struct lu_env *env,
 
 	if (anchor)
 		cl_sync_io_note(anchor, ioret);
-
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_completion);
 
@@ -1328,9 +1285,8 @@ int cl_page_make_ready(const struct lu_env *env, struct cl_page *pg,
 
 	PINVRNT(env, pg, crt < CRT_NR);
 
-	ENTRY;
 	if (crt >= CRT_NR)
-		RETURN(-EINVAL);
+		return -EINVAL;
 	result = CL_PAGE_INVOKE(env, pg, CL_PAGE_OP(io[crt].cpo_make_ready),
 				(const struct lu_env *,
 				 const struct cl_page_slice *));
@@ -1339,7 +1295,7 @@ int cl_page_make_ready(const struct lu_env *env, struct cl_page *pg,
 		cl_page_io_start(env, pg, crt);
 	}
 	CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_page_make_ready);
 
@@ -1365,10 +1321,8 @@ int cl_page_cache_add(const struct lu_env *env, struct cl_io *io,
 	PINVRNT(env, pg, cl_page_is_owned(pg, io));
 	PINVRNT(env, pg, cl_page_invariant(pg));
 
-	ENTRY;
-
 	if (crt >= CRT_NR)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	list_for_each_entry(scan, &pg->cp_layers, cpl_linkage) {
 		if (scan->cpl_ops->io[crt].cpo_cache_add == NULL)
@@ -1379,7 +1333,7 @@ int cl_page_cache_add(const struct lu_env *env, struct cl_io *io,
 			break;
 	}
 	CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_page_cache_add);
 
@@ -1399,12 +1353,10 @@ int cl_page_flush(const struct lu_env *env, struct cl_io *io,
 	PINVRNT(env, pg, cl_page_is_owned(pg, io));
 	PINVRNT(env, pg, cl_page_invariant(pg));
 
-	ENTRY;
-
 	result = cl_page_invoke(env, io, pg, CL_PAGE_OP(cpo_flush));
 
 	CL_PAGE_HEADER(D_TRACE, env, pg, "%d\n", result);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_page_flush);
 
@@ -1422,13 +1374,12 @@ int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io,
 
 	PINVRNT(env, page, cl_page_invariant(page));
 
-	ENTRY;
 	rc = CL_PAGE_INVOKE(env, page, CL_PAGE_OP(cpo_is_under_lock),
 			    (const struct lu_env *,
 			     const struct cl_page_slice *, struct cl_io *),
 			    io);
 	PASSERT(env, page, rc != 0);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(cl_page_is_under_lock);
 
@@ -1452,7 +1403,6 @@ int cl_pages_prune(const struct lu_env *env, struct cl_object *clobj)
 	struct cl_io	    *io;
 	int		      result;
 
-	ENTRY;
 	info  = cl_env_info(env);
 	io    = &info->clt_io;
 
@@ -1465,7 +1415,7 @@ int cl_pages_prune(const struct lu_env *env, struct cl_object *clobj)
 	result = cl_io_init(env, io, CIT_MISC, obj);
 	if (result != 0) {
 		cl_io_fini(env, io);
-		RETURN(io->ci_result);
+		return io->ci_result;
 	}
 
 	do {
@@ -1476,7 +1426,7 @@ int cl_pages_prune(const struct lu_env *env, struct cl_object *clobj)
 	} while (result != CLP_GANG_OKAY);
 
 	cl_io_fini(env, io);
-	RETURN(result);
+	return result;
 }
 EXPORT_SYMBOL(cl_pages_prune);
 
@@ -1586,12 +1536,10 @@ void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice,
 		       struct cl_object *obj,
 		       const struct cl_page_operations *ops)
 {
-	ENTRY;
 	list_add_tail(&slice->cpl_linkage, &page->cp_layers);
 	slice->cpl_obj  = obj;
 	slice->cpl_ops  = ops;
 	slice->cpl_page = page;
-	EXIT;
 }
 EXPORT_SYMBOL(cl_page_slice_add);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c
index af1c2d0..b1024a6 100644
--- a/drivers/staging/lustre/lustre/obdclass/class_obd.c
+++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c
@@ -112,18 +112,18 @@ int lustre_get_jobid(char *jobid)
 {
 	int jobid_len = JOBSTATS_JOBID_SIZE;
 	int rc = 0;
-	ENTRY;
 
 	memset(jobid, 0, JOBSTATS_JOBID_SIZE);
 	/* Jobstats isn't enabled */
 	if (strcmp(obd_jobid_var, JOBSTATS_DISABLE) == 0)
-		RETURN(0);
+		return 0;
 
 	/* Use process name + fsuid as jobid */
 	if (strcmp(obd_jobid_var, JOBSTATS_PROCNAME_UID) == 0) {
 		snprintf(jobid, JOBSTATS_JOBID_SIZE, "%s.%u",
-			 current_comm(), current_fsuid());
-		RETURN(0);
+			 current_comm(),
+			 from_kuid(&init_user_ns, current_fsuid()));
+		return 0;
 	}
 
 	rc = cfs_get_environ(obd_jobid_var, jobid, &jobid_len);
@@ -150,7 +150,7 @@ int lustre_get_jobid(char *jobid)
 			       obd_jobid_var, rc);
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(lustre_get_jobid);
 
@@ -193,7 +193,6 @@ int class_resolve_dev_name(__u32 len, const char *name)
 	int rc;
 	int dev;
 
-	ENTRY;
 	if (!len || !name) {
 		CERROR("No name passed,!\n");
 		GOTO(out, rc = -EINVAL);
@@ -214,7 +213,7 @@ int class_resolve_dev_name(__u32 len, const char *name)
 	rc = dev;
 
 out:
-	RETURN(rc);
+	return rc;
 }
 
 int class_handle_ioctl(unsigned int cmd, unsigned long arg)
@@ -224,7 +223,6 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
 	struct libcfs_debug_ioctl_data *debug_data;
 	struct obd_device *obd = NULL;
 	int err = 0, len = 0;
-	ENTRY;
 
 	/* only for debugging */
 	if (cmd == LIBCFS_IOC_DEBUG_MASK) {
@@ -237,7 +235,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
 	CDEBUG(D_IOCTL, "cmd = %x\n", cmd);
 	if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
 		CERROR("OBD ioctl: data error\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	data = (struct obd_ioctl_data *)buf;
 
@@ -428,10 +426,10 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
  out:
 	if (buf)
 		obd_ioctl_freedata(buf, len);
-	RETURN(err);
+	return err;
 } /* class_handle_ioctl */
 
-extern psdev_t obd_psdev;
+extern struct miscdevice obd_psdev;
 
 #define OBD_INIT_CHECK
 int obd_init_checks(void)
@@ -524,7 +522,7 @@ static int __init init_obdclass(void)
 					 LPROCFS_STATS_FLAG_IRQ_SAFE);
 	if (obd_memory == NULL) {
 		CERROR("kmalloc of 'obd_memory' failed\n");
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	lprocfs_counter_init(obd_memory, OBD_MEMORY_STAT,
@@ -558,10 +556,10 @@ static int __init init_obdclass(void)
 	/* Default the dirty page cache cap to 1/2 of system memory.
 	 * For clients with less memory, a larger fraction is needed
 	 * for other purposes (mostly for BGL). */
-	if (num_physpages <= 512 << (20 - PAGE_CACHE_SHIFT))
-		obd_max_dirty_pages = num_physpages / 4;
+	if (totalram_pages <= 512 << (20 - PAGE_CACHE_SHIFT))
+		obd_max_dirty_pages = totalram_pages / 4;
 	else
-		obd_max_dirty_pages = num_physpages / 2;
+		obd_max_dirty_pages = totalram_pages / 2;
 
 	err = obd_init_caches();
 	if (err)
@@ -638,7 +636,6 @@ static void cleanup_obdclass(void)
 	int lustre_unregister_fs(void);
 	__u64 memory_leaked, pages_leaked;
 	__u64 memory_max, pages_max;
-	ENTRY;
 
 	lustre_unregister_fs();
 
@@ -678,12 +675,12 @@ static void cleanup_obdclass(void)
 	CDEBUG((pages_leaked) ? D_ERROR : D_INFO,
 	       "obd_memory_pages max: "LPU64", leaked: "LPU64"\n",
 	       pages_max, pages_leaked);
-
-	EXIT;
 }
 
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(LUSTRE_VERSION_STRING);
 
-cfs_module(obdclass, LUSTRE_VERSION_STRING, init_obdclass, cleanup_obdclass);
+module_init(init_obdclass);
+module_exit(cleanup_obdclass);
diff --git a/drivers/staging/lustre/lustre/obdclass/dt_object.c b/drivers/staging/lustre/lustre/obdclass/dt_object.c
index 1c962dd..1b164c7 100644
--- a/drivers/staging/lustre/lustre/obdclass/dt_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/dt_object.c
@@ -219,7 +219,6 @@ struct dt_object *dt_locate_at(const struct lu_env *env,
 			       struct lu_device *top_dev)
 {
 	struct lu_object *lo, *n;
-	ENTRY;
 
 	lo = lu_object_find_at(env, top_dev, fid, NULL);
 	if (IS_ERR(lo))
@@ -376,15 +375,13 @@ struct dt_object *dt_find_or_create(const struct lu_env *env,
 	struct thandle *th;
 	int rc;
 
-	ENTRY;
-
 	dto = dt_locate(env, dt, fid);
 	if (IS_ERR(dto))
-		RETURN(dto);
+		return dto;
 
 	LASSERT(dto != NULL);
 	if (dt_object_exists(dto))
-		RETURN(dto);
+		return dto;
 
 	th = dt_trans_create(env, dt);
 	if (IS_ERR(th))
@@ -415,9 +412,9 @@ trans_stop:
 out:
 	if (rc) {
 		lu_object_put(env, &dto->do_lu);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
-	RETURN(dto);
+	return dto;
 }
 EXPORT_SYMBOL(dt_find_or_create);
 
@@ -659,7 +656,6 @@ static int dt_index_page_build(const struct lu_env *env, union lu_page *lp,
 	struct lu_idxpage	*lip = &lp->lp_idx;
 	char			*entry;
 	int			 rc, size;
-	ENTRY;
 
 	/* no support for variable key & record size for now */
 	LASSERT((ii->ii_flags & II_FL_VARKEY) == 0);
@@ -763,21 +759,20 @@ int dt_index_walk(const struct lu_env *env, struct dt_object *obj,
 	const struct dt_it_ops	*iops;
 	unsigned int		 pageidx, nob, nlupgs = 0;
 	int			 rc;
-	ENTRY;
 
 	LASSERT(rdpg->rp_pages != NULL);
 	LASSERT(obj->do_index_ops != NULL);
 
 	nob = rdpg->rp_count;
 	if (nob <= 0)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	/* Iterate through index and fill containers from @rdpg */
 	iops = &obj->do_index_ops->dio_it;
 	LASSERT(iops != NULL);
 	it = iops->init(env, obj, rdpg->rp_attrs, BYPASS_CAPA);
 	if (IS_ERR(it))
-		RETURN(PTR_ERR(it));
+		return PTR_ERR(it);
 
 	rc = iops->load(env, it, rdpg->rp_hash);
 	if (rc == 0) {
@@ -831,7 +826,7 @@ int dt_index_walk(const struct lu_env *env, struct dt_object *obj,
 	if (rc >= 0)
 		rc = min_t(unsigned int, nlupgs * LU_PAGE_SIZE, rdpg->rp_count);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(dt_index_walk);
 
@@ -855,26 +850,25 @@ int dt_index_read(const struct lu_env *env, struct dt_device *dev,
 	const struct dt_index_features	*feat;
 	struct dt_object		*obj;
 	int				 rc;
-	ENTRY;
 
 	/* rp_count shouldn't be null and should be a multiple of the container
 	 * size */
 	if (rdpg->rp_count <= 0 && (rdpg->rp_count & (LU_PAGE_SIZE - 1)) != 0)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	if (fid_seq(&ii->ii_fid) >= FID_SEQ_NORMAL)
 		/* we don't support directory transfer via OBD_IDX_READ for the
 		 * time being */
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	if (!fid_is_quota(&ii->ii_fid))
 		/* block access to all local files except quota files */
-		RETURN(-EPERM);
+		return -EPERM;
 
 	/* lookup index object subject to the transfer */
 	obj = dt_locate(env, dev, &ii->ii_fid);
 	if (IS_ERR(obj))
-		RETURN(PTR_ERR(obj));
+		return PTR_ERR(obj);
 	if (dt_object_exists(obj) == 0)
 		GOTO(out, rc = -ENOENT);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index d96876e..68fe71c 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -163,20 +163,19 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
 {
 	struct obd_type *type;
 	int rc = 0;
-	ENTRY;
 
 	/* sanity check */
 	LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME);
 
 	if (class_search_type(name)) {
 		CDEBUG(D_IOCTL, "Type %s already registered\n", name);
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 
 	rc = -ENOMEM;
 	OBD_ALLOC(type, sizeof(*type));
 	if (type == NULL)
-		RETURN(rc);
+		return rc;
 
 	OBD_ALLOC_PTR(type->typ_dt_ops);
 	OBD_ALLOC_PTR(type->typ_md_ops);
@@ -214,7 +213,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
 	list_add(&type->typ_chain, &obd_types);
 	spin_unlock(&obd_types_lock);
 
-	RETURN (0);
+	return 0;
 
  failed:
 	if (type->typ_name != NULL)
@@ -224,18 +223,17 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
 	if (type->typ_dt_ops != NULL)
 		OBD_FREE_PTR(type->typ_dt_ops);
 	OBD_FREE(type, sizeof(*type));
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_register_type);
 
 int class_unregister_type(const char *name)
 {
 	struct obd_type *type = class_search_type(name);
-	ENTRY;
 
 	if (!type) {
 		CERROR("unknown obd type\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (type->typ_refcnt) {
@@ -244,7 +242,7 @@ int class_unregister_type(const char *name)
 		/* Remove ops, but leave the name for debugging */
 		OBD_FREE_PTR(type->typ_dt_ops);
 		OBD_FREE_PTR(type->typ_md_ops);
-		RETURN(-EBUSY);
+		return -EBUSY;
 	}
 
 	if (type->typ_procroot) {
@@ -263,7 +261,7 @@ int class_unregister_type(const char *name)
 	if (type->typ_md_ops != NULL)
 		OBD_FREE_PTR(type->typ_md_ops);
 	OBD_FREE(type, sizeof(*type));
-	RETURN(0);
+	return 0;
 } /* class_unregister_type */
 EXPORT_SYMBOL(class_unregister_type);
 
@@ -285,17 +283,16 @@ struct obd_device *class_newdev(const char *type_name, const char *name)
 	struct obd_type *type = NULL;
 	int i;
 	int new_obd_minor = 0;
-	ENTRY;
 
 	if (strlen(name) >= MAX_OBD_NAME) {
 		CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME);
-		RETURN(ERR_PTR(-EINVAL));
+		return ERR_PTR(-EINVAL);
 	}
 
 	type = class_get_type(type_name);
 	if (type == NULL){
 		CERROR("OBD: unknown type: %s\n", type_name);
-		RETURN(ERR_PTR(-ENODEV));
+		return ERR_PTR(-ENODEV);
 	}
 
 	newdev = obd_device_alloc();
@@ -349,7 +346,7 @@ struct obd_device *class_newdev(const char *type_name, const char *name)
 	CDEBUG(D_IOCTL, "Adding new device %s (%p)\n",
 	       result->obd_name, result);
 
-	RETURN(result);
+	return result;
 out:
 	obd_device_free(newdev);
 out_type:
@@ -635,7 +632,6 @@ EXPORT_SYMBOL(class_notify_sptlrpc_conf);
 
 void obd_cleanup_caches(void)
 {
-	ENTRY;
 	if (obd_device_cachep) {
 		kmem_cache_destroy(obd_device_cachep);
 		obd_device_cachep = NULL;
@@ -652,13 +648,10 @@ void obd_cleanup_caches(void)
 		kmem_cache_destroy(capa_cachep);
 		capa_cachep = NULL;
 	}
-	EXIT;
 }
 
 int obd_init_caches(void)
 {
-	ENTRY;
-
 	LASSERT(obd_device_cachep == NULL);
 	obd_device_cachep = kmem_cache_create("ll_obd_dev_cache",
 						 sizeof(struct obd_device),
@@ -685,10 +678,10 @@ int obd_init_caches(void)
 	if (!capa_cachep)
 		GOTO(out, -ENOMEM);
 
-	RETURN(0);
+	return 0;
  out:
 	obd_cleanup_caches();
-	RETURN(-ENOMEM);
+	return -ENOMEM;
 
 }
 
@@ -696,21 +689,20 @@ int obd_init_caches(void)
 struct obd_export *class_conn2export(struct lustre_handle *conn)
 {
 	struct obd_export *export;
-	ENTRY;
 
 	if (!conn) {
 		CDEBUG(D_CACHE, "looking for null handle\n");
-		RETURN(NULL);
+		return NULL;
 	}
 
 	if (conn->cookie == -1) {  /* this means assign a new connection */
 		CDEBUG(D_CACHE, "want a new connection\n");
-		RETURN(NULL);
+		return NULL;
 	}
 
 	CDEBUG(D_INFO, "looking for export cookie "LPX64"\n", conn->cookie);
 	export = class_handle2object(conn->cookie);
-	RETURN(export);
+	return export;
 }
 EXPORT_SYMBOL(class_conn2export);
 
@@ -757,7 +749,6 @@ EXPORT_SYMBOL(class_conn2cliimp);
 static void class_export_destroy(struct obd_export *exp)
 {
 	struct obd_device *obd = exp->exp_obd;
-	ENTRY;
 
 	LASSERT_ATOMIC_ZERO(&exp->exp_refcount);
 	LASSERT(obd != NULL);
@@ -777,7 +768,6 @@ static void class_export_destroy(struct obd_export *exp)
 	class_decref(obd, "export", exp);
 
 	OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle);
-	EXIT;
 }
 
 static void export_handle_addref(void *export)
@@ -828,7 +818,6 @@ struct obd_export *class_new_export(struct obd_device *obd,
 	struct obd_export *export;
 	cfs_hash_t *hash = NULL;
 	int rc = 0;
-	ENTRY;
 
 	OBD_ALLOC_PTR(export);
 	if (!export)
@@ -899,7 +888,7 @@ struct obd_export *class_new_export(struct obd_device *obd,
 	export->exp_obd->obd_num_exports++;
 	spin_unlock(&obd->obd_dev_lock);
 	cfs_hash_putref(hash);
-	RETURN(export);
+	return export;
 
 exit_unlock:
 	spin_unlock(&obd->obd_dev_lock);
@@ -936,8 +925,6 @@ EXPORT_SYMBOL(class_unlink_export);
 /* Import management functions */
 void class_import_destroy(struct obd_import *imp)
 {
-	ENTRY;
-
 	CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
 		imp->imp_obd->obd_name);
 
@@ -958,7 +945,6 @@ void class_import_destroy(struct obd_import *imp)
 	LASSERT(imp->imp_sec == NULL);
 	class_decref(imp->imp_obd, "import", imp);
 	OBD_FREE_RCU(imp, sizeof(*imp), &imp->imp_handle);
-	EXIT;
 }
 
 static void import_handle_addref(void *import)
@@ -983,8 +969,6 @@ EXPORT_SYMBOL(class_import_get);
 
 void class_import_put(struct obd_import *imp)
 {
-	ENTRY;
-
 	LASSERT(list_empty(&imp->imp_zombie_chain));
 	LASSERT_ATOMIC_GT_LT(&imp->imp_refcount, 0, LI_POISON);
 
@@ -999,7 +983,6 @@ void class_import_put(struct obd_import *imp)
 
 	/* catch possible import put race */
 	LASSERT_ATOMIC_GE_LT(&imp->imp_refcount, 0, LI_POISON);
-	EXIT;
 }
 EXPORT_SYMBOL(class_import_put);
 
@@ -1121,18 +1104,17 @@ int class_connect(struct lustre_handle *conn, struct obd_device *obd,
 	LASSERT(conn != NULL);
 	LASSERT(obd != NULL);
 	LASSERT(cluuid != NULL);
-	ENTRY;
 
 	export = class_new_export(obd, cluuid);
 	if (IS_ERR(export))
-		RETURN(PTR_ERR(export));
+		return PTR_ERR(export);
 
 	conn->cookie = export->exp_handle.h_cookie;
 	class_export_put(export);
 
 	CDEBUG(D_IOCTL, "connect: client %s, cookie "LPX64"\n",
 	       cluuid->uuid, conn->cookie);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(class_connect);
 
@@ -1188,11 +1170,10 @@ void class_export_recovery_cleanup(struct obd_export *exp)
 int class_disconnect(struct obd_export *export)
 {
 	int already_disconnected;
-	ENTRY;
 
 	if (export == NULL) {
 		CWARN("attempting to free NULL export %p\n", export);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	spin_lock(&export->exp_lock);
@@ -1220,7 +1201,7 @@ int class_disconnect(struct obd_export *export)
 	class_unlink_export(export);
 no_disconn:
 	class_export_put(export);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(class_disconnect);
 
@@ -1243,7 +1224,6 @@ static void class_disconnect_export_list(struct list_head *list,
 {
 	int rc;
 	struct obd_export *exp;
-	ENTRY;
 
 	/* It's possible that an export may disconnect itself, but
 	 * nothing else will be added to this list. */
@@ -1281,13 +1261,11 @@ static void class_disconnect_export_list(struct list_head *list,
 		       obd_export_nid2str(exp), exp, rc);
 		class_export_put(exp);
 	}
-	EXIT;
 }
 
 void class_disconnect_exports(struct obd_device *obd)
 {
 	struct list_head work_list;
-	ENTRY;
 
 	/* Move all of the exports from obd_exports to a work list, en masse. */
 	INIT_LIST_HEAD(&work_list);
@@ -1304,7 +1282,6 @@ void class_disconnect_exports(struct obd_device *obd)
 	} else
 		CDEBUG(D_HA, "OBD device %d (%p) has no exports\n",
 		       obd->obd_minor, obd);
-	EXIT;
 }
 EXPORT_SYMBOL(class_disconnect_exports);
 
@@ -1316,7 +1293,6 @@ void class_disconnect_stale_exports(struct obd_device *obd,
 	struct list_head work_list;
 	struct obd_export *exp, *n;
 	int evicted = 0;
-	ENTRY;
 
 	INIT_LIST_HEAD(&work_list);
 	spin_lock(&obd->obd_dev_lock);
@@ -1356,7 +1332,6 @@ void class_disconnect_stale_exports(struct obd_device *obd,
 
 	class_disconnect_export_list(&work_list, exp_flags_from_obd(obd) |
 						 OBD_OPT_ABORT_RECOV);
-	EXIT;
 }
 EXPORT_SYMBOL(class_disconnect_stale_exports);
 
@@ -1484,7 +1459,7 @@ int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid)
 		CERROR("%s: can't disconnect %s: no exports found\n",
 		       obd->obd_name, uuid);
 	} else {
-		CWARN("%s: evicting %s at adminstrative request\n",
+		CWARN("%s: evicting %s at administrative request\n",
 		       obd->obd_name, doomed_exp->exp_client_uuid.uuid);
 		class_fail_export(doomed_exp);
 		class_export_put(doomed_exp);
@@ -1585,7 +1560,6 @@ void obd_zombie_impexp_cull(void)
 {
 	struct obd_import *import;
 	struct obd_export *export;
-	ENTRY;
 
 	do {
 		spin_lock(&obd_zombie_impexp_lock);
@@ -1624,7 +1598,6 @@ void obd_zombie_impexp_cull(void)
 
 		cond_resched();
 	} while (import != NULL || export != NULL);
-	EXIT;
 }
 
 static struct completion	obd_zombie_start;
@@ -1649,7 +1622,7 @@ static int obd_zombie_impexp_check(void *arg)
 	     !test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags);
 	spin_unlock(&obd_zombie_impexp_lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1751,7 +1724,7 @@ static int obd_zombie_impexp_thread(void *unused)
 
 	complete(&obd_zombie_stop);
 
-	RETURN(0);
+	return 0;
 }
 
 
@@ -1760,7 +1733,7 @@ static int obd_zombie_impexp_thread(void *unused)
  */
 int obd_zombie_impexp_init(void)
 {
-	task_t *task;
+	struct task_struct *task;
 
 	INIT_LIST_HEAD(&obd_zombie_imports);
 	INIT_LIST_HEAD(&obd_zombie_exports);
@@ -1772,10 +1745,10 @@ int obd_zombie_impexp_init(void)
 
 	task = kthread_run(obd_zombie_impexp_thread, NULL, "obd_zombid");
 	if (IS_ERR(task))
-		RETURN(PTR_ERR(task));
+		return PTR_ERR(task);
 
 	wait_for_completion(&obd_zombie_start);
-	RETURN(0);
+	return 0;
 }
 /**
  * stop destroy zombie import/export thread
diff --git a/drivers/staging/lustre/lustre/obdclass/idmap.c b/drivers/staging/lustre/lustre/obdclass/idmap.c
index 622f8d1..ec2590f 100644
--- a/drivers/staging/lustre/lustre/obdclass/idmap.c
+++ b/drivers/staging/lustre/lustre/obdclass/idmap.c
@@ -59,8 +59,7 @@
  * groups_search() is copied from linux kernel!
  * A simple bsearch.
  */
-static int lustre_groups_search(group_info_t *group_info,
-				gid_t grp)
+static int lustre_groups_search(const struct group_info *group_info, gid_t grp)
 {
 	int left, right;
 
@@ -71,7 +70,8 @@ static int lustre_groups_search(group_info_t *group_info,
 	right = group_info->ngroups;
 	while (left < right) {
 		int mid = (left + right) / 2;
-		int cmp = grp - CFS_GROUP_AT(group_info, mid);
+		int cmp = grp -
+			from_kgid(&init_user_ns, CFS_GROUP_AT(group_info, mid));
 
 		if (cmp > 0)
 			left = mid + 1;
@@ -83,7 +83,7 @@ static int lustre_groups_search(group_info_t *group_info,
 	return 0;
 }
 
-void lustre_groups_from_list(group_info_t *ginfo, gid_t *glist)
+void lustre_groups_from_list(struct group_info *ginfo, gid_t *glist)
 {
 	int i;
 	int count = ginfo->ngroups;
@@ -102,7 +102,7 @@ EXPORT_SYMBOL(lustre_groups_from_list);
 
 /* groups_sort() is copied from linux kernel! */
 /* a simple shell-metzner sort */
-void lustre_groups_sort(group_info_t *group_info)
+void lustre_groups_sort(struct group_info *group_info)
 {
 	int base, max, stride;
 	int gidsetsize = group_info->ngroups;
@@ -116,16 +116,19 @@ void lustre_groups_sort(group_info_t *group_info)
 		for (base = 0; base < max; base++) {
 			int left = base;
 			int right = left + stride;
-			gid_t tmp = CFS_GROUP_AT(group_info, right);
+			gid_t tmp = from_kgid(&init_user_ns,
+					      CFS_GROUP_AT(group_info, right));
 
 			while (left >= 0 &&
-			       CFS_GROUP_AT(group_info, left) > tmp) {
+			       tmp < from_kgid(&init_user_ns,
+					       CFS_GROUP_AT(group_info, left))) {
 				CFS_GROUP_AT(group_info, right) =
 				    CFS_GROUP_AT(group_info, left);
 				right = left;
 				left -= stride;
 			}
-			CFS_GROUP_AT(group_info, right) = tmp;
+			CFS_GROUP_AT(group_info, right) =
+						make_kgid(&init_user_ns, tmp);
 		}
 		stride /= 3;
 	}
@@ -137,7 +140,7 @@ int lustre_in_group_p(struct lu_ucred *mu, gid_t grp)
 	int rc = 1;
 
 	if (grp != mu->uc_fsgid) {
-		group_info_t *group_info = NULL;
+		struct group_info *group_info = NULL;
 
 		if (mu->uc_ginfo || !mu->uc_identity ||
 		    mu->uc_valid == UCRED_OLD)
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
index d2c3072..d1a57eb 100644
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
+++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
@@ -83,27 +83,26 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg)
 	struct obd_ioctl_data *data;
 	int err;
 	int offset = 0;
-	ENTRY;
 
 	err = copy_from_user(&hdr, (void *)arg, sizeof(hdr));
 	if ( err )
-		RETURN(err);
+		return err;
 
 	if (hdr.ioc_version != OBD_IOCTL_VERSION) {
 		CERROR("Version mismatch kernel (%x) vs application (%x)\n",
 		       OBD_IOCTL_VERSION, hdr.ioc_version);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (hdr.ioc_len > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("User buffer len %d exceeds %d max buffer\n",
 		       hdr.ioc_len, OBD_MAX_IOCTL_BUFFER);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (hdr.ioc_len < sizeof(struct obd_ioctl_data)) {
 		CERROR("User buffer too small for ioctl (%d)\n", hdr.ioc_len);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* When there are lots of processes calling vmalloc on multi-core
@@ -114,7 +113,7 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg)
 	if (*buf == NULL) {
 		CERROR("Cannot allocate control buffer of len %d\n",
 		       hdr.ioc_len);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	*len = hdr.ioc_len;
 	data = (struct obd_ioctl_data *)*buf;
@@ -122,13 +121,13 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg)
 	err = copy_from_user(*buf, (void *)arg, hdr.ioc_len);
 	if ( err ) {
 		OBD_FREE_LARGE(*buf, hdr.ioc_len);
-		RETURN(err);
+		return err;
 	}
 
 	if (obd_ioctl_is_invalid(data)) {
 		CERROR("ioctl not correctly formatted\n");
 		OBD_FREE_LARGE(*buf, hdr.ioc_len);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (data->ioc_inllen1) {
@@ -150,7 +149,6 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg)
 		data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
 	}
 
-	EXIT;
 	return 0;
 }
 EXPORT_SYMBOL(obd_ioctl_getdata);
@@ -169,19 +167,15 @@ EXPORT_SYMBOL(obd_ioctl_popdata);
 /*  opening /dev/obd */
 static int obd_class_open(struct inode * inode, struct file * file)
 {
-	ENTRY;
-
 	try_module_get(THIS_MODULE);
-	RETURN(0);
+	return 0;
 }
 
 /*  closing /dev/obd */
 static int obd_class_release(struct inode * inode, struct file * file)
 {
-	ENTRY;
-
 	module_put(THIS_MODULE);
-	RETURN(0);
+	return 0;
 }
 
 /* to control /dev/obd */
@@ -189,17 +183,16 @@ static long obd_class_ioctl(struct file *filp, unsigned int cmd,
 			    unsigned long arg)
 {
 	int err = 0;
-	ENTRY;
 
 	/* Allow non-root access for OBD_IOC_PING_TARGET - used by lfs check */
 	if (!cfs_capable(CFS_CAP_SYS_ADMIN) && (cmd != OBD_IOC_PING_TARGET))
-		RETURN(err = -EACCES);
+		return err = -EACCES;
 	if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
-		RETURN(err = -ENOTTY);
+		return err = -ENOTTY;
 
 	err = class_handle_ioctl(cmd, (unsigned long)arg);
 
-	RETURN(err);
+	return err;
 }
 
 /* declare character device */
@@ -211,7 +204,7 @@ static struct file_operations obd_psdev_fops = {
 };
 
 /* modules setup */
-psdev_t obd_psdev = {
+struct miscdevice obd_psdev = {
 	.minor = OBD_DEV_MINOR,
 	.name  = OBD_DEV_NAME,
 	.fops  = &obd_psdev_fops,
@@ -385,24 +378,29 @@ struct file_operations obd_device_list_fops = {
 
 int class_procfs_init(void)
 {
-	int rc;
-	ENTRY;
+	int rc = 0;
 
 	obd_sysctl_init();
 	proc_lustre_root = lprocfs_register("fs/lustre", NULL,
 					    lprocfs_base, NULL);
+	if (IS_ERR(proc_lustre_root)) {
+		rc = PTR_ERR(proc_lustre_root);
+		proc_lustre_root = NULL;
+		goto out;
+	}
+
 	rc = lprocfs_seq_create(proc_lustre_root, "devices", 0444,
 				&obd_device_list_fops, NULL);
+out:
 	if (rc)
 		CERROR("error adding /proc/fs/lustre/devices file\n");
-	RETURN(0);
+	return 0;
 }
 
 int class_procfs_clean(void)
 {
-	ENTRY;
 	if (proc_lustre_root) {
 		lprocfs_remove(&proc_lustre_root);
 	}
-	RETURN(0);
+	return 0;
 }
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c
index 6ee3471..d3bb5ff 100644
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c
+++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c
@@ -213,9 +213,9 @@ void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid)
 	if (valid & OBD_MD_FLMODE)
 		dst->i_mode = (dst->i_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
 	if (valid & OBD_MD_FLUID)
-		dst->i_uid = src->o_uid;
+		dst->i_uid = make_kuid(&init_user_ns, src->o_uid);
 	if (valid & OBD_MD_FLGID)
-		dst->i_gid = src->o_gid;
+		dst->i_gid = make_kgid(&init_user_ns, src->o_gid);
 	if (valid & OBD_MD_FLFLAGS)
 		dst->i_flags = src->o_flags;
 }
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
index 46aad68..acd2619 100644
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
+++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
@@ -38,8 +38,6 @@
 #include <linux/sysctl.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/version.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
@@ -202,12 +200,12 @@ int LL_PROC_PROTO(proc_max_dirty_pages_in_mb)
 					       1 << (20 - PAGE_CACHE_SHIFT));
 		/* Don't allow them to let dirty pages exceed 90% of system
 		 * memory and set a hard minimum of 4MB. */
-		if (obd_max_dirty_pages > ((num_physpages / 10) * 9)) {
+		if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
 			CERROR("Refusing to set max dirty pages to %u, which "
 			       "is more than 90%% of available RAM; setting "
 			       "to %lu\n", obd_max_dirty_pages,
-			       ((num_physpages / 10) * 9));
-			obd_max_dirty_pages = ((num_physpages / 10) * 9);
+			       ((totalram_pages / 10) * 9));
+			obd_max_dirty_pages = ((totalram_pages / 10) * 9);
 		} else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
 			obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
 		}
@@ -431,7 +429,7 @@ void obd_sysctl_init (void)
 {
 #ifdef CONFIG_SYSCTL
 	if ( !obd_table_header )
-		obd_table_header = cfs_register_sysctl_table(parent_table, 0);
+		obd_table_header = register_sysctl_table(parent_table);
 #endif
 }
 
diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c
index b1d215e..0cb4428 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog.c
@@ -111,21 +111,20 @@ int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle,
 {
 	struct llog_log_hdr *llh = loghandle->lgh_hdr;
 	int rc = 0;
-	ENTRY;
 
 	CDEBUG(D_RPCTRACE, "Canceling %d in log "DOSTID"\n",
 	       index, POSTID(&loghandle->lgh_id.lgl_oi));
 
 	if (index == 0) {
 		CERROR("Can't cancel index 0 which is header\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	spin_lock(&loghandle->lgh_hdr_lock);
 	if (!ext2_clear_bit(index, llh->llh_bitmap)) {
 		spin_unlock(&loghandle->lgh_hdr_lock);
 		CDEBUG(D_RPCTRACE, "Catalog index %u already clear?\n", index);
-		RETURN(-ENOENT);
+		return -ENOENT;
 	}
 
 	llh->llh_count--;
@@ -143,7 +142,7 @@ int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle,
 			       loghandle->lgh_id.lgl_ogen, rc);
 			GOTO(out_err, rc);
 		}
-		RETURN(1);
+		return 1;
 	}
 	spin_unlock(&loghandle->lgh_hdr_lock);
 
@@ -156,7 +155,7 @@ int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle,
 		       loghandle->lgh_id.lgl_ogen, rc);
 		GOTO(out_err, rc);
 	}
-	RETURN(0);
+	return 0;
 out_err:
 	spin_lock(&loghandle->lgh_hdr_lock);
 	ext2_set_bit(index, llh->llh_bitmap);
@@ -175,10 +174,10 @@ static int llog_read_header(const struct lu_env *env,
 
 	rc = llog_handle2ops(handle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (lop->lop_read_header == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	rc = lop->lop_read_header(env, handle);
 	if (rc == LLOG_EEMPTY) {
@@ -206,12 +205,11 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle,
 	struct llog_log_hdr	*llh;
 	int			 rc;
 
-	ENTRY;
 	LASSERT(handle->lgh_hdr == NULL);
 
 	OBD_ALLOC_PTR(llh);
 	if (llh == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	handle->lgh_hdr = llh;
 	/* first assign flags to use llog_client_ops */
 	llh->llh_flags = flags;
@@ -263,7 +261,7 @@ out:
 		OBD_FREE_PTR(llh);
 		handle->lgh_hdr = NULL;
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_init_handle);
 
@@ -277,7 +275,6 @@ int llog_copy_handler(const struct lu_env *env,
 	char *cfg_buf = (char*) (rec + 1);
 	struct lustre_cfg *lcfg;
 	int rc = 0;
-	ENTRY;
 
 	/* Append all records */
 	local_rec.lrh_len -= sizeof(*rec) + sizeof(struct llog_rec_tail);
@@ -289,7 +286,7 @@ int llog_copy_handler(const struct lu_env *env,
 	       rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
 	       lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_copy_handler);
 
@@ -306,14 +303,12 @@ static int llog_process_thread(void *arg)
 	int				 saved_index = 0;
 	int				 last_called_index = 0;
 
-	ENTRY;
-
 	LASSERT(llh);
 
 	OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
 	if (!buf) {
 		lpi->lpi_rc = -ENOMEM;
-		RETURN(0);
+		return 0;
 	}
 
 	if (cd != NULL) {
@@ -457,12 +452,10 @@ int llog_process_or_fork(const struct lu_env *env,
 	struct llog_process_info *lpi;
 	int		      rc;
 
-	ENTRY;
-
 	OBD_ALLOC_PTR(lpi);
 	if (lpi == NULL) {
 		CERROR("cannot alloc pointer\n");
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 	lpi->lpi_loghandle = loghandle;
 	lpi->lpi_cb	= cb;
@@ -480,7 +473,7 @@ int llog_process_or_fork(const struct lu_env *env,
 			CERROR("%s: cannot start thread: rc = %d\n",
 			       loghandle->lgh_ctxt->loc_obd->obd_name, rc);
 			OBD_FREE_PTR(lpi);
-			RETURN(rc);
+			return rc;
 		}
 		wait_for_completion(&lpi->lpi_completion);
 	} else {
@@ -489,7 +482,7 @@ int llog_process_or_fork(const struct lu_env *env,
 	}
 	rc = lpi->lpi_rc;
 	OBD_FREE_PTR(lpi);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_process_or_fork);
 
@@ -516,11 +509,10 @@ int llog_reverse_process(const struct lu_env *env,
 	struct llog_process_cat_data *cd = catdata;
 	void *buf;
 	int rc = 0, first_index = 1, index, idx;
-	ENTRY;
 
 	OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
 	if (!buf)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (cd != NULL)
 		first_index = cd->lpcd_first_idx + 1;
@@ -594,7 +586,7 @@ int llog_reverse_process(const struct lu_env *env,
 out:
 	if (buf)
 		OBD_FREE(buf, LLOG_CHUNK_SIZE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_reverse_process);
 
@@ -617,16 +609,14 @@ int llog_exist(struct llog_handle *loghandle)
 	struct llog_operations	*lop;
 	int			 rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(loghandle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_exist == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	rc = lop->lop_exist(loghandle);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_exist);
 
@@ -636,13 +626,11 @@ int llog_declare_create(const struct lu_env *env,
 	struct llog_operations	*lop;
 	int			 raised, rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(loghandle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_declare_create == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
 	if (!raised)
@@ -650,7 +638,7 @@ int llog_declare_create(const struct lu_env *env,
 	rc = lop->lop_declare_create(env, loghandle, th);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_declare_create);
 
@@ -660,13 +648,11 @@ int llog_create(const struct lu_env *env, struct llog_handle *handle,
 	struct llog_operations	*lop;
 	int			 raised, rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(handle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	if (lop->lop_create == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
 	if (!raised)
@@ -674,7 +660,7 @@ int llog_create(const struct lu_env *env, struct llog_handle *handle,
 	rc = lop->lop_create(env, handle, th);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_create);
 
@@ -686,14 +672,12 @@ int llog_declare_write_rec(const struct lu_env *env,
 	struct llog_operations	*lop;
 	int			 raised, rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(handle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 	LASSERT(lop);
 	if (lop->lop_declare_write_rec == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
 	if (!raised)
@@ -701,7 +685,7 @@ int llog_declare_write_rec(const struct lu_env *env,
 	rc = lop->lop_declare_write_rec(env, handle, rec, idx, th);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_declare_write_rec);
 
@@ -712,15 +696,13 @@ int llog_write_rec(const struct lu_env *env, struct llog_handle *handle,
 	struct llog_operations	*lop;
 	int			 raised, rc, buflen;
 
-	ENTRY;
-
 	rc = llog_handle2ops(handle, &lop);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	LASSERT(lop);
 	if (lop->lop_write_rec == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	if (buf)
 		buflen = rec->lrh_len + sizeof(struct llog_rec_hdr) +
@@ -736,7 +718,7 @@ int llog_write_rec(const struct lu_env *env, struct llog_handle *handle,
 				buf, idx, th);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_write_rec);
 
@@ -746,10 +728,8 @@ int llog_add(const struct lu_env *env, struct llog_handle *lgh,
 {
 	int raised, rc;
 
-	ENTRY;
-
 	if (lgh->lgh_logops->lop_add == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
 	if (!raised)
@@ -757,7 +737,7 @@ int llog_add(const struct lu_env *env, struct llog_handle *lgh,
 	rc = lgh->lgh_logops->lop_add(env, lgh, rec, logcookies, buf, th);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_add);
 
@@ -766,10 +746,8 @@ int llog_declare_add(const struct lu_env *env, struct llog_handle *lgh,
 {
 	int raised, rc;
 
-	ENTRY;
-
 	if (lgh->lgh_logops->lop_declare_add == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
 	if (!raised)
@@ -777,7 +755,7 @@ int llog_declare_add(const struct lu_env *env, struct llog_handle *lgh,
 	rc = lgh->lgh_logops->lop_declare_add(env, lgh, rec, th);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_declare_add);
 
@@ -792,14 +770,12 @@ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt,
 	struct thandle	*th;
 	int		 rc;
 
-	ENTRY;
-
 	rc = llog_open(env, ctxt, res, logid, name, LLOG_OPEN_NEW);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (llog_exist(*res))
-		RETURN(0);
+		return 0;
 
 	if ((*res)->lgh_obj != NULL) {
 		struct dt_device *d;
@@ -825,7 +801,7 @@ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt,
 out:
 	if (rc)
 		llog_close(env, *res);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_open_create);
 
@@ -838,15 +814,13 @@ int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt,
 	struct llog_handle	*handle;
 	int			 rc = 0, rc2;
 
-	ENTRY;
-
 	/* nothing to erase */
 	if (name == NULL && logid == NULL)
-		RETURN(0);
+		return 0;
 
 	rc = llog_open(env, ctxt, &handle, logid, name, LLOG_OPEN_EXISTS);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	rc = llog_init_handle(env, handle, LLOG_F_IS_PLAIN, NULL);
 	if (rc == 0)
@@ -855,7 +829,7 @@ int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt,
 	rc2 = llog_close(env, handle);
 	if (rc == 0)
 		rc = rc2;
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_erase);
 
@@ -870,8 +844,6 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle,
 {
 	int rc;
 
-	ENTRY;
-
 	LASSERT(loghandle);
 	LASSERT(loghandle->lgh_ctxt);
 
@@ -883,7 +855,7 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle,
 
 		th = dt_trans_create(env, dt);
 		if (IS_ERR(th))
-			RETURN(PTR_ERR(th));
+			return PTR_ERR(th);
 
 		rc = llog_declare_write_rec(env, loghandle, rec, idx, th);
 		if (rc)
@@ -905,7 +877,7 @@ out_trans:
 				    cookiecount, buf, idx, NULL);
 		up_write(&loghandle->lgh_lock);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_write);
 
@@ -916,19 +888,17 @@ int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt,
 	int	 raised;
 	int	 rc;
 
-	ENTRY;
-
 	LASSERT(ctxt);
 	LASSERT(ctxt->loc_logops);
 
 	if (ctxt->loc_logops->lop_open == NULL) {
 		*lgh = NULL;
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 
 	*lgh = llog_alloc_handle();
 	if (*lgh == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	(*lgh)->lgh_ctxt = ctxt;
 	(*lgh)->lgh_logops = ctxt->loc_logops;
 
@@ -942,7 +912,7 @@ int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt,
 		llog_free_handle(*lgh);
 		*lgh = NULL;
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_open);
 
@@ -951,8 +921,6 @@ int llog_close(const struct lu_env *env, struct llog_handle *loghandle)
 	struct llog_operations	*lop;
 	int			 rc;
 
-	ENTRY;
-
 	rc = llog_handle2ops(loghandle, &lop);
 	if (rc)
 		GOTO(out, rc);
@@ -961,6 +929,6 @@ int llog_close(const struct lu_env *env, struct llog_handle *loghandle)
 	rc = lop->lop_close(env, loghandle);
 out:
 	llog_handle_put(loghandle);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_close);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
index cf00b2f..c0f3af7 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
@@ -67,7 +67,6 @@ static int llog_cat_new_log(const struct lu_env *env,
 	struct llog_log_hdr *llh;
 	struct llog_logid_rec rec = { { 0 }, };
 	int rc, index, bitmap_size;
-	ENTRY;
 
 	llh = cathandle->lgh_hdr;
 	bitmap_size = LLOG_BITMAP_SIZE(llh);
@@ -77,20 +76,20 @@ static int llog_cat_new_log(const struct lu_env *env,
 	/* maximum number of available slots in catlog is bitmap_size - 2 */
 	if (llh->llh_cat_idx == index) {
 		CERROR("no free catalog slots for log...\n");
-		RETURN(-ENOSPC);
+		return -ENOSPC;
 	}
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_MDS_LLOG_CREATE_FAILED))
-		RETURN(-ENOSPC);
+		return -ENOSPC;
 
 	rc = llog_create(env, loghandle, th);
 	/* if llog is already created, no need to initialize it */
 	if (rc == -EEXIST) {
-		RETURN(0);
+		return 0;
 	} else if (rc != 0) {
 		CERROR("%s: can't create new plain llog in catalog: rc = %d\n",
 		       loghandle->lgh_ctxt->loc_obd->obd_name, rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = llog_init_handle(env, loghandle,
@@ -134,10 +133,10 @@ static int llog_cat_new_log(const struct lu_env *env,
 		GOTO(out_destroy, rc);
 
 	loghandle->lgh_hdr->llh_cat_idx = index;
-	RETURN(0);
+	return 0;
 out_destroy:
 	llog_destroy(env, loghandle);
-	RETURN(rc);
+	return rc;
 }
 
 /* Open an existent log handle and add it to the open list.
@@ -155,10 +154,8 @@ int llog_cat_id2handle(const struct lu_env *env, struct llog_handle *cathandle,
 	struct llog_handle	*loghandle;
 	int			 rc = 0;
 
-	ENTRY;
-
 	if (cathandle == NULL)
-		RETURN(-EBADF);
+		return -EBADF;
 
 	down_write(&cathandle->lgh_lock);
 	list_for_each_entry(loghandle, &cathandle->u.chd.chd_head,
@@ -187,14 +184,14 @@ int llog_cat_id2handle(const struct lu_env *env, struct llog_handle *cathandle,
 		CERROR("%s: error opening log id "DOSTID":%x: rc = %d\n",
 		       cathandle->lgh_ctxt->loc_obd->obd_name,
 		       POSTID(&logid->lgl_oi), logid->lgl_ogen, rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
 	if (rc < 0) {
 		llog_close(env, loghandle);
 		loghandle = NULL;
-		RETURN(rc);
+		return rc;
 	}
 
 	down_write(&cathandle->lgh_lock);
@@ -205,7 +202,6 @@ int llog_cat_id2handle(const struct lu_env *env, struct llog_handle *cathandle,
 	loghandle->u.phd.phd_cookie.lgc_lgl = cathandle->lgh_id;
 	loghandle->u.phd.phd_cookie.lgc_index =
 				loghandle->lgh_hdr->llh_cat_idx;
-	EXIT;
 out:
 	llog_handle_get(loghandle);
 	*res = loghandle;
@@ -217,8 +213,6 @@ int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle)
 	struct llog_handle	*loghandle, *n;
 	int			 rc;
 
-	ENTRY;
-
 	list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head,
 				     u.phd.phd_entry) {
 		struct llog_log_hdr	*llh = loghandle->lgh_hdr;
@@ -246,7 +240,7 @@ int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle)
 	if (cathandle->lgh_ctxt->loc_handle == cathandle)
 		cathandle->lgh_ctxt->loc_handle = NULL;
 	rc = llog_close(env, cathandle);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_close);
 
@@ -272,7 +266,6 @@ static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
 						struct thandle *th)
 {
 	struct llog_handle *loghandle = NULL;
-	ENTRY;
 
 	down_read_nested(&cathandle->lgh_lock, LLOGH_CAT);
 	loghandle = cathandle->u.chd.chd_current_log;
@@ -284,7 +277,7 @@ static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
 		if (llh == NULL ||
 		    loghandle->lgh_last_idx < LLOG_BITMAP_SIZE(llh) - 1) {
 			up_read(&cathandle->lgh_lock);
-			RETURN(loghandle);
+			return loghandle;
 		} else {
 			up_write(&loghandle->lgh_lock);
 		}
@@ -304,7 +297,7 @@ static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
 		LASSERT(llh);
 		if (loghandle->lgh_last_idx < LLOG_BITMAP_SIZE(llh) - 1) {
 			up_write(&cathandle->lgh_lock);
-			RETURN(loghandle);
+			return loghandle;
 		} else {
 			up_write(&loghandle->lgh_lock);
 		}
@@ -318,7 +311,7 @@ static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
 	down_write_nested(&loghandle->lgh_lock, LLOGH_LOG);
 	up_write(&cathandle->lgh_lock);
 	LASSERT(loghandle);
-	RETURN(loghandle);
+	return loghandle;
 }
 
 /* Add a single record to the recovery log(s) using a catalog
@@ -332,7 +325,6 @@ int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle,
 {
 	struct llog_handle *loghandle;
 	int rc;
-	ENTRY;
 
 	LASSERT(rec->lrh_len <= LLOG_CHUNK_SIZE);
 	loghandle = llog_cat_current_log(cathandle, th);
@@ -343,7 +335,7 @@ int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle,
 		rc = llog_cat_new_log(env, cathandle, loghandle, th);
 		if (rc < 0) {
 			up_write(&loghandle->lgh_lock);
-			RETURN(rc);
+			return rc;
 		}
 	}
 	/* now let's try to add the record */
@@ -361,7 +353,7 @@ int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle,
 			rc = llog_cat_new_log(env, cathandle, loghandle, th);
 			if (rc < 0) {
 				up_write(&loghandle->lgh_lock);
-				RETURN(rc);
+				return rc;
 			}
 		}
 		/* now let's try to add the record */
@@ -372,7 +364,7 @@ int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle,
 		up_write(&loghandle->lgh_lock);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_add_rec);
 
@@ -383,8 +375,6 @@ int llog_cat_declare_add_rec(const struct lu_env *env,
 	struct llog_handle	*loghandle, *next;
 	int			 rc = 0;
 
-	ENTRY;
-
 	if (cathandle->u.chd.chd_current_log == NULL) {
 		/* declare new plain llog */
 		down_write(&cathandle->lgh_lock);
@@ -437,7 +427,7 @@ int llog_cat_declare_add_rec(const struct lu_env *env,
 		llog_declare_write_rec(env, next, rec, -1, th);
 	}
 out:
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_declare_add_rec);
 
@@ -460,7 +450,7 @@ int llog_cat_add(const struct lu_env *env, struct llog_handle *cathandle,
 
 		th = dt_trans_create(env, dt);
 		if (IS_ERR(th))
-			RETURN(PTR_ERR(th));
+			return PTR_ERR(th);
 
 		rc = llog_cat_declare_add_rec(env, cathandle, rec, th);
 		if (rc)
@@ -479,7 +469,7 @@ out_trans:
 			rc = llog_cat_add_rec(env, cathandle, rec, reccookie,
 					      buf, th);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_add);
 
@@ -498,8 +488,6 @@ int llog_cat_cancel_records(const struct lu_env *env,
 {
 	int i, index, rc = 0, failed = 0;
 
-	ENTRY;
-
 	for (i = 0; i < count; i++, cookies++) {
 		struct llog_handle	*loghandle;
 		struct llog_logid	*lgl = &cookies->lgc_lgl;
@@ -533,7 +521,7 @@ int llog_cat_cancel_records(const struct lu_env *env,
 		       cathandle->lgh_ctxt->loc_obd->obd_name, failed, count,
 		       rc);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_cancel_records);
 
@@ -545,10 +533,9 @@ int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh,
 	struct llog_handle *llh;
 	int rc;
 
-	ENTRY;
 	if (rec->lrh_type != LLOG_LOGID_MAGIC) {
 		CERROR("invalid record in catalog\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	CDEBUG(D_HA, "processing log "DOSTID":%x at index %u of catalog "
 	       DOSTID"\n", POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen,
@@ -559,12 +546,12 @@ int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh,
 		CERROR("%s: cannot find handle for llog "DOSTID": %d\n",
 		       cat_llh->lgh_ctxt->loc_obd->obd_name,
 		       POSTID(&lir->lid_id.lgl_oi), rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (rec->lrh_index < d->lpd_startcat)
 		/* Skip processing of the logs until startcat */
-		RETURN(0);
+		return 0;
 
 	if (d->lpd_startidx > 0) {
 		struct llog_process_cat_data cd;
@@ -581,7 +568,7 @@ int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh,
 	}
 	llog_handle_put(llh);
 
-	RETURN(rc);
+	return rc;
 }
 
 int llog_cat_process_or_fork(const struct lu_env *env,
@@ -592,7 +579,6 @@ int llog_cat_process_or_fork(const struct lu_env *env,
 	struct llog_process_data d;
 	struct llog_log_hdr *llh = cat_llh->lgh_hdr;
 	int rc;
-	ENTRY;
 
 	LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
 	d.lpd_data = data;
@@ -611,7 +597,7 @@ int llog_cat_process_or_fork(const struct lu_env *env,
 		rc = llog_process_or_fork(env, cat_llh, llog_cat_process_cb,
 					  &d, &cd, fork);
 		if (rc != 0)
-			RETURN(rc);
+			return rc;
 
 		cd.lpcd_first_idx = 0;
 		cd.lpcd_last_idx = cat_llh->lgh_last_idx;
@@ -622,7 +608,7 @@ int llog_cat_process_or_fork(const struct lu_env *env,
 					  &d, NULL, fork);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_process_or_fork);
 
@@ -645,7 +631,7 @@ static int llog_cat_reverse_process_cb(const struct lu_env *env,
 
 	if (le32_to_cpu(rec->lrh_type) != LLOG_LOGID_MAGIC) {
 		CERROR("invalid record in catalog\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	CDEBUG(D_HA, "processing log "DOSTID":%x at index %u of catalog "
 	       DOSTID"\n", POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen,
@@ -656,12 +642,12 @@ static int llog_cat_reverse_process_cb(const struct lu_env *env,
 		CERROR("%s: cannot find handle for llog "DOSTID": %d\n",
 		       cat_llh->lgh_ctxt->loc_obd->obd_name,
 		       POSTID(&lir->lid_id.lgl_oi), rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = llog_reverse_process(env, llh, d->lpd_cb, d->lpd_data, NULL);
 	llog_handle_put(llh);
-	RETURN(rc);
+	return rc;
 }
 
 int llog_cat_reverse_process(const struct lu_env *env,
@@ -672,7 +658,6 @@ int llog_cat_reverse_process(const struct lu_env *env,
 	struct llog_process_cat_data cd;
 	struct llog_log_hdr *llh = cat_llh->lgh_hdr;
 	int rc;
-	ENTRY;
 
 	LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
 	d.lpd_data = data;
@@ -688,7 +673,7 @@ int llog_cat_reverse_process(const struct lu_env *env,
 					  llog_cat_reverse_process_cb,
 					  &d, &cd);
 		if (rc != 0)
-			RETURN(rc);
+			return rc;
 
 		cd.lpcd_first_idx = le32_to_cpu(llh->llh_cat_idx);
 		cd.lpcd_last_idx = 0;
@@ -701,7 +686,7 @@ int llog_cat_reverse_process(const struct lu_env *env,
 					  &d, NULL);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cat_reverse_process);
 
@@ -709,7 +694,6 @@ int llog_cat_set_first_idx(struct llog_handle *cathandle, int index)
 {
 	struct llog_log_hdr *llh = cathandle->lgh_hdr;
 	int i, bitmap_size, idx;
-	ENTRY;
 
 	bitmap_size = LLOG_BITMAP_SIZE(llh);
 	if (llh->llh_cat_idx == (index - 1)) {
@@ -734,7 +718,7 @@ out:
 		       POSTID(&cathandle->lgh_id.lgl_oi), llh->llh_cat_idx);
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 /* Cleanup deleted plain llog traces from catalog */
@@ -774,11 +758,9 @@ int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle,
 	struct llog_log_hdr	*llh;
 	int			 rc;
 
-	ENTRY;
-
 	if (rec->lrh_type != LLOG_LOGID_MAGIC) {
 		CERROR("invalid record in catalog\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	CDEBUG(D_HA, "processing log "DOSTID":%x at index %u of catalog "
@@ -794,7 +776,7 @@ int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle,
 			/* remove index from catalog */
 			llog_cat_cleanup(env, cathandle, NULL, rec->lrh_index);
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	llh = loghandle->lgh_hdr;
@@ -810,7 +792,7 @@ int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle,
 	}
 	llog_handle_put(loghandle);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(cat_cancel_cb);
 
@@ -822,12 +804,12 @@ int llog_cat_init_and_process(const struct lu_env *env,
 
 	rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, NULL);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = llog_process_or_fork(env, llh, cat_cancel_cb, NULL, NULL, false);
 	if (rc)
 		CERROR("%s: llog_process() with cat_cancel_cb failed: rc = "
 		       "%d\n", llh->lgh_ctxt->loc_obd->obd_name, rc);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(llog_cat_init_and_process);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c b/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c
index 0732874..da558a5 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c
@@ -45,46 +45,45 @@ static int str2logid(struct llog_logid *logid, char *str, int len)
 	char *start, *end, *endp;
 	__u64 id, seq;
 
-	ENTRY;
 	start = str;
 	if (*start != '#')
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	start++;
 	if (start - str >= len - 1)
-		RETURN(-EINVAL);
+		return -EINVAL;
 	end = strchr(start, '#');
 	if (end == NULL || end == start)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	*end = '\0';
 	id = simple_strtoull(start, &endp, 0);
 	if (endp != end)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	start = ++end;
 	if (start - str >= len - 1)
-		RETURN(-EINVAL);
+		return -EINVAL;
 	end = strchr(start, '#');
 	if (end == NULL || end == start)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	*end = '\0';
 	seq = simple_strtoull(start, &endp, 0);
 	if (endp != end)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	ostid_set_seq(&logid->lgl_oi, seq);
 	ostid_set_id(&logid->lgl_oi, id);
 
 	start = ++end;
 	if (start - str >= len - 1)
-		RETURN(-EINVAL);
+		return -EINVAL;
 	logid->lgl_ogen = simple_strtoul(start, &endp, 16);
 	if (*endp != '\0')
-		RETURN(-EINVAL);
+		return -EINVAL;
 
-	RETURN(0);
+	return 0;
 }
 
 static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
@@ -96,8 +95,6 @@ static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
 	char *endp;
 	int cur_index, rc = 0;
 
-	ENTRY;
-
 	if (ioc_data && ioc_data->ioc_inllen1 > 0) {
 		l = 0;
 		remains = ioc_data->ioc_inllen4 +
@@ -106,19 +103,19 @@ static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
 			cfs_size_round(ioc_data->ioc_inllen3);
 		from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
 		if (*endp != '\0')
-			RETURN(-EINVAL);
+			return -EINVAL;
 		to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
 		if (*endp != '\0')
-			RETURN(-EINVAL);
+			return -EINVAL;
 		ioc_data->ioc_inllen1 = 0;
 		out = ioc_data->ioc_bulk;
 	}
 
 	cur_index = rec->lrh_index;
 	if (cur_index < from)
-		RETURN(0);
+		return 0;
 	if (to > 0 && cur_index > to)
-		RETURN(-LLOG_EEMPTY);
+		return -LLOG_EEMPTY;
 
 	if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) {
 		struct llog_logid_rec	*lir = (struct llog_logid_rec *)rec;
@@ -131,13 +128,13 @@ static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
 				     rec->lrh_len);
 		}
 		if (handle->lgh_ctxt == NULL)
-			RETURN(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 		rc = llog_cat_id2handle(env, handle, &loghandle, &lir->lid_id);
 		if (rc) {
 			CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n",
 			       POSTID(&lir->lid_id.lgl_oi),
 			       lir->lid_id.lgl_ogen);
-			RETURN(rc);
+			return rc;
 		}
 		rc = llog_process(env, loghandle, llog_check_cb, NULL, NULL);
 		llog_handle_put(loghandle);
@@ -167,10 +164,10 @@ static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
 		if (remains <= 0) {
 			CERROR("%s: no space to print log records\n",
 			       handle->lgh_ctxt->loc_obd->obd_name);
-			RETURN(-LLOG_EEMPTY);
+			return -LLOG_EEMPTY;
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
@@ -182,7 +179,6 @@ static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
 	char *endp;
 	int cur_index;
 
-	ENTRY;
 	if (ioc_data != NULL && ioc_data->ioc_inllen1 > 0) {
 		l = 0;
 		remains = ioc_data->ioc_inllen4 +
@@ -191,26 +187,26 @@ static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
 			cfs_size_round(ioc_data->ioc_inllen3);
 		from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
 		if (*endp != '\0')
-			RETURN(-EINVAL);
+			return -EINVAL;
 		to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
 		if (*endp != '\0')
-			RETURN(-EINVAL);
+			return -EINVAL;
 		out = ioc_data->ioc_bulk;
 		ioc_data->ioc_inllen1 = 0;
 	}
 
 	cur_index = rec->lrh_index;
 	if (cur_index < from)
-		RETURN(0);
+		return 0;
 	if (to > 0 && cur_index > to)
-		RETURN(-LLOG_EEMPTY);
+		return -LLOG_EEMPTY;
 
 	if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) {
 		struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
 
 		if (rec->lrh_type != LLOG_LOGID_MAGIC) {
 			CERROR("invalid record in catalog\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		l = snprintf(out, remains,
@@ -222,7 +218,7 @@ static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
 
 		rc = class_config_parse_rec(rec, out, remains);
 		if (rc < 0)
-			RETURN(rc);
+			return rc;
 		l = rc;
 	} else {
 		l = snprintf(out, remains,
@@ -233,10 +229,10 @@ static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
 	remains -= l;
 	if (remains <= 0) {
 		CERROR("not enough space for print log records\n");
-		RETURN(-LLOG_EEMPTY);
+		return -LLOG_EEMPTY;
 	}
 
-	RETURN(0);
+	return 0;
 }
 static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat,
 			   struct llog_logid *logid)
@@ -244,13 +240,11 @@ static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat,
 	struct llog_handle	*log;
 	int			 rc;
 
-	ENTRY;
-
 	rc = llog_cat_id2handle(env, cat, &log, logid);
 	if (rc) {
 		CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n",
 		       POSTID(&logid->lgl_oi), logid->lgl_ogen);
-		RETURN(-ENOENT);
+		return -ENOENT;
 	}
 
 	rc = llog_destroy(env, log);
@@ -261,7 +255,7 @@ static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat,
 	llog_cat_cleanup(env, cat, log, log->u.phd.phd_cookie.lgc_index);
 out:
 	llog_handle_put(log);
-	RETURN(rc);
+	return rc;
 
 }
 
@@ -271,12 +265,11 @@ static int llog_delete_cb(const struct lu_env *env, struct llog_handle *handle,
 	struct llog_logid_rec	*lir = (struct llog_logid_rec *)rec;
 	int			 rc;
 
-	ENTRY;
 	if (rec->lrh_type != LLOG_LOGID_MAGIC)
-		RETURN(-EINVAL);
+		return -EINVAL;
 	rc = llog_remove_log(env, handle, &lir->lid_id);
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -287,25 +280,23 @@ int llog_ioctl(const struct lu_env *env, struct llog_ctxt *ctxt, int cmd,
 	int			 rc = 0;
 	struct llog_handle	*handle = NULL;
 
-	ENTRY;
-
 	if (*data->ioc_inlbuf1 == '#') {
 		rc = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		rc = llog_open(env, ctxt, &handle, &logid, NULL,
 			       LLOG_OPEN_EXISTS);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	} else if (*data->ioc_inlbuf1 == '$') {
 		char *name = data->ioc_inlbuf1 + 1;
 
 		rc = llog_open(env, ctxt, &handle, NULL, name,
 			       LLOG_OPEN_EXISTS);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	} else {
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = llog_init_handle(env, handle, 0, NULL);
@@ -422,6 +413,6 @@ out_close:
 		llog_cat_close(env, handle);
 	else
 		llog_close(env, handle);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_ioctl);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c b/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
index 7e12dc6..5385d8e 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
@@ -64,7 +64,6 @@ static int llog_lvfs_pad(struct obd_device *obd, struct l_file *file,
 	struct llog_rec_hdr rec = { 0 };
 	struct llog_rec_tail tail;
 	int rc;
-	ENTRY;
 
 	LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0);
 
@@ -86,7 +85,7 @@ static int llog_lvfs_pad(struct obd_device *obd, struct l_file *file,
 	}
 
  out:
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file,
@@ -97,8 +96,6 @@ static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file,
 	loff_t saved_off = file->f_pos;
 	int buflen = rec->lrh_len;
 
-	ENTRY;
-
 	file->f_pos = off;
 
 	if (buflen == 0)
@@ -140,7 +137,7 @@ static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file,
 	if (saved_off > file->f_pos)
 		file->f_pos = saved_off;
 	LASSERT(rc <= 0);
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_lvfs_read_blob(struct obd_device *obd, struct l_file *file,
@@ -148,14 +145,13 @@ static int llog_lvfs_read_blob(struct obd_device *obd, struct l_file *file,
 {
 	loff_t offset = off;
 	int rc;
-	ENTRY;
 
 	rc = fsfilt_read_record(obd, file, buf, size, &offset);
 	if (rc) {
 		CERROR("error reading log record: rc %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
-	RETURN(0);
+	return 0;
 }
 
 static int llog_lvfs_read_header(const struct lu_env *env,
@@ -163,7 +159,6 @@ static int llog_lvfs_read_header(const struct lu_env *env,
 {
 	struct obd_device *obd;
 	int rc;
-	ENTRY;
 
 	LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE);
 
@@ -171,7 +166,7 @@ static int llog_lvfs_read_header(const struct lu_env *env,
 
 	if (i_size_read(handle->lgh_file->f_dentry->d_inode) == 0) {
 		CDEBUG(D_HA, "not reading header from 0-byte log\n");
-		RETURN(LLOG_EEMPTY);
+		return LLOG_EEMPTY;
 	}
 
 	rc = llog_lvfs_read_blob(obd, handle->lgh_file, handle->lgh_hdr,
@@ -206,7 +201,7 @@ static int llog_lvfs_read_header(const struct lu_env *env,
 	handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index;
 	handle->lgh_file->f_pos = i_size_read(handle->lgh_file->f_dentry->d_inode);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* returns negative in on error; 0 if success && reccookie == 0; 1 otherwise */
@@ -223,7 +218,6 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 	struct obd_device *obd;
 	struct file *file;
 	size_t left;
-	ENTRY;
 
 	llh = loghandle->lgh_hdr;
 	file = loghandle->lgh_file;
@@ -236,7 +230,7 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 	else
 		rc = (reclen > LLOG_CHUNK_SIZE) ? -E2BIG : 0;
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (buf)
 		/* write_blob adds header and tail to lrh_len. */
@@ -253,7 +247,7 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 		}
 
 		if (idx && llh->llh_size && llh->llh_size != rec->lrh_len)
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		if (!ext2_test_bit(idx, llh->llh_bitmap))
 			CERROR("Modify unset record %u\n", idx);
@@ -263,7 +257,7 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 		rc = llog_lvfs_write_blob(obd, file, &llh->llh_hdr, NULL, 0);
 		/* we are done if we only write the header or on error */
 		if (rc || idx == 0)
-			RETURN(rc);
+			return rc;
 
 		if (buf) {
 			/* We assume that caller has set lgh_cur_* */
@@ -277,7 +271,7 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 			if (rec->lrh_index != loghandle->lgh_cur_idx) {
 				CERROR("modify idx mismatch %u/%d\n",
 				       idx, loghandle->lgh_cur_idx);
-				RETURN(-EFAULT);
+				return -EFAULT;
 			}
 		} else {
 			/* Assumes constant lrh_len */
@@ -290,7 +284,7 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 			reccookie->lgc_index = idx;
 			rc = 1;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	/* Make sure that records don't cross a chunk boundary, so we can
@@ -308,12 +302,12 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 		 index = loghandle->lgh_last_idx + 1;
 		 rc = llog_lvfs_pad(obd, file, left, index);
 		 if (rc)
-			 RETURN(rc);
+			 return rc;
 		 loghandle->lgh_last_idx++; /*for pad rec*/
 	 }
 	 /* if it's the last idx in log file, then return -ENOSPC */
 	 if (loghandle->lgh_last_idx >= LLOG_BITMAP_SIZE(llh) - 1)
-		 RETURN(-ENOSPC);
+		 return -ENOSPC;
 	loghandle->lgh_last_idx++;
 	index = loghandle->lgh_last_idx;
 	LASSERT(index < LLOG_BITMAP_SIZE(llh));
@@ -339,11 +333,11 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 
 	rc = llog_lvfs_write_blob(obd, file, &llh->llh_hdr, NULL, 0);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = llog_lvfs_write_blob(obd, file, rec, buf, file->f_pos);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CDEBUG(D_RPCTRACE, "added record "DOSTID": idx: %u, %u \n",
 	       POSTID(&loghandle->lgh_id.lgl_oi), index, rec->lrh_len);
@@ -362,7 +356,7 @@ static int llog_lvfs_write_rec(const struct lu_env *env,
 	if (rc == 0 && rec->lrh_type == LLOG_GEN_REC)
 		rc = 1;
 
-	RETURN(rc);
+	return rc;
 }
 
 /* We can skip reading at least as many log blocks as the number of
@@ -391,10 +385,9 @@ static int llog_lvfs_next_block(const struct lu_env *env,
 				int len)
 {
 	int rc;
-	ENTRY;
 
 	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off "LPU64")\n",
 	       next_idx, *cur_idx, *cur_offset);
@@ -419,7 +412,7 @@ static int llog_lvfs_next_block(const struct lu_env *env,
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen,
 			       *cur_offset);
-			RETURN(rc);
+			return rc;
 		}
 
 		/* put number of bytes read into rc to make code simpler */
@@ -430,13 +423,13 @@ static int llog_lvfs_next_block(const struct lu_env *env,
 		}
 
 		if (rc == 0) /* end of file, nothing to do */
-			RETURN(0);
+			return 0;
 
 		if (rc < sizeof(*tail)) {
 			CERROR("Invalid llog block at log id "DOSTID"/%u offset"
 			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, *cur_offset);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		rec = buf;
@@ -461,7 +454,7 @@ static int llog_lvfs_next_block(const struct lu_env *env,
 			CERROR("Invalid llog tail at log id "DOSTID"/%u offset "
 			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, *cur_offset);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		if (tail->lrt_index < next_idx)
 			continue;
@@ -471,11 +464,11 @@ static int llog_lvfs_next_block(const struct lu_env *env,
 		if (rec->lrh_index > next_idx) {
 			CERROR("missed desired record? %u > %u\n",
 			       rec->lrh_index, next_idx);
-			RETURN(-ENOENT);
+			return -ENOENT;
 		}
-		RETURN(0);
+		return 0;
 	}
-	RETURN(-EIO);
+	return -EIO;
 }
 
 static int llog_lvfs_prev_block(const struct lu_env *env,
@@ -484,10 +477,9 @@ static int llog_lvfs_prev_block(const struct lu_env *env,
 {
 	__u64 cur_offset;
 	int rc;
-	ENTRY;
 
 	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	CDEBUG(D_OTHER, "looking for log index %u\n", prev_idx);
 
@@ -508,20 +500,20 @@ static int llog_lvfs_prev_block(const struct lu_env *env,
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen,
 			       cur_offset);
-			RETURN(rc);
+			return rc;
 		}
 
 		/* put number of bytes read into rc to make code simpler */
 		rc = cur_offset - ppos;
 
 		if (rc == 0) /* end of file, nothing to do */
-			RETURN(0);
+			return 0;
 
 		if (rc < sizeof(*tail)) {
 			CERROR("Invalid llog block at log id "DOSTID"/%u offset"
 			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, cur_offset);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		rec = buf;
@@ -544,7 +536,7 @@ static int llog_lvfs_prev_block(const struct lu_env *env,
 			CERROR("Invalid llog tail at log id "DOSTID"/%u offset"
 			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, cur_offset);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		if (tail->lrt_index < prev_idx)
 			continue;
@@ -554,11 +546,11 @@ static int llog_lvfs_prev_block(const struct lu_env *env,
 		if (rec->lrh_index > prev_idx) {
 			CERROR("missed desired record? %u > %u\n",
 			       rec->lrh_index, prev_idx);
-			RETURN(-ENOENT);
+			return -ENOENT;
 		}
-		RETURN(0);
+		return 0;
 	}
-	RETURN(-EIO);
+	return -EIO;
 }
 
 static struct file *llog_filp_open(char *dir, char *name, int flags, int mode)
@@ -593,8 +585,6 @@ static int llog_lvfs_open(const struct lu_env *env,  struct llog_handle *handle,
 	struct obd_device	*obd;
 	int			 rc = 0;
 
-	ENTRY;
-
 	LASSERT(ctxt);
 	LASSERT(ctxt->loc_exp);
 	LASSERT(ctxt->loc_exp->exp_obd);
@@ -661,12 +651,12 @@ static int llog_lvfs_open(const struct lu_env *env,  struct llog_handle *handle,
 	if (open_param != LLOG_OPEN_NEW && handle->lgh_file == NULL)
 		GOTO(out_name, rc = -ENOENT);
 
-	RETURN(0);
+	return 0;
 out_name:
 	if (handle->lgh_name != NULL)
 		OBD_FREE(handle->lgh_name, strlen(name) + 1);
 out:
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_lvfs_exist(struct llog_handle *handle)
@@ -688,8 +678,6 @@ static int llog_lvfs_create(const struct lu_env *env,
 	int			 rc = 0;
 	int			 open_flags = O_RDWR | O_CREAT | O_LARGEFILE;
 
-	ENTRY;
-
 	LASSERT(ctxt);
 	LASSERT(ctxt->loc_exp);
 	obd = ctxt->loc_exp->exp_obd;
@@ -699,7 +687,7 @@ static int llog_lvfs_create(const struct lu_env *env,
 		file = llog_filp_open(MOUNT_CONFIGS_DIR, handle->lgh_name,
 				      open_flags, 0644);
 		if (IS_ERR(file))
-			RETURN(PTR_ERR(file));
+			return PTR_ERR(file);
 
 		lustre_build_llog_lvfs_oid(&handle->lgh_id,
 				file->f_dentry->d_inode->i_ino,
@@ -708,7 +696,7 @@ static int llog_lvfs_create(const struct lu_env *env,
 	} else {
 		OBDO_ALLOC(oa);
 		if (oa == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		ostid_set_seq_llog(&oa->o_oi);
 		oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLGROUP;
@@ -736,7 +724,7 @@ static int llog_lvfs_create(const struct lu_env *env,
 out:
 		OBDO_FREE(oa);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_lvfs_close(const struct lu_env *env,
@@ -744,10 +732,8 @@ static int llog_lvfs_close(const struct lu_env *env,
 {
 	int rc;
 
-	ENTRY;
-
 	if (handle->lgh_file == NULL)
-		RETURN(0);
+		return 0;
 	rc = filp_close(handle->lgh_file, 0);
 	if (rc)
 		CERROR("%s: error closing llog #"DOSTID"#%08x: "
@@ -759,7 +745,7 @@ static int llog_lvfs_close(const struct lu_env *env,
 		OBD_FREE(handle->lgh_name, strlen(handle->lgh_name) + 1);
 		handle->lgh_name = NULL;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_lvfs_destroy(const struct lu_env *env,
@@ -772,7 +758,6 @@ static int llog_lvfs_destroy(const struct lu_env *env,
 	void *th;
 	struct inode *inode;
 	int rc, rc1;
-	ENTRY;
 
 	dir = MOUNT_CONFIGS_DIR;
 
@@ -795,12 +780,12 @@ static int llog_lvfs_destroy(const struct lu_env *env,
 
 		dput(fdentry);
 		pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
-		RETURN(rc);
+		return rc;
 	}
 
 	OBDO_ALLOC(oa);
 	if (oa == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	oa->o_oi = handle->lgh_id.lgl_oi;
 	oa->o_generation = handle->lgh_id.lgl_ogen;
@@ -825,7 +810,7 @@ static int llog_lvfs_destroy(const struct lu_env *env,
 		rc = rc1;
  out:
 	OBDO_FREE(oa);
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_lvfs_declare_create(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_obd.c b/drivers/staging/lustre/lustre/obdclass/llog_obd.c
index 7e22907..71817af 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_obd.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_obd.c
@@ -110,7 +110,6 @@ int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
 	struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
 	struct obd_llog_group *olg;
 	int rc, idx;
-	ENTRY;
 
 	LASSERT(ctxt != NULL);
 	LASSERT(ctxt != LP_POISON);
@@ -139,7 +138,7 @@ int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
 	l_wait_event(olg->olg_waitq,
 		     llog_group_ctxt_null(olg, idx), &lwi);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cleanup);
 
@@ -149,16 +148,15 @@ int llog_setup(const struct lu_env *env, struct obd_device *obd,
 {
 	struct llog_ctxt *ctxt;
 	int rc = 0;
-	ENTRY;
 
 	if (index < 0 || index >= LLOG_MAX_CTXTS)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	LASSERT(olg != NULL);
 
 	ctxt = llog_new_ctxt(obd);
 	if (!ctxt)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	ctxt->loc_obd = obd;
 	ctxt->loc_olg = olg;
@@ -189,7 +187,7 @@ int llog_setup(const struct lu_env *env, struct obd_device *obd,
 			}
 			rc = 0;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	if (op->lop_setup) {
@@ -210,22 +208,21 @@ int llog_setup(const struct lu_env *env, struct obd_device *obd,
 		ctxt->loc_flags &= ~LLOG_CTXT_FLAG_UNINITIALIZED;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_setup);
 
 int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp, int flags)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (!ctxt)
-		RETURN(0);
+		return 0;
 
 	if (CTXTP(ctxt, sync))
 		rc = CTXTP(ctxt, sync)(ctxt, exp, flags);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_sync);
 
@@ -234,15 +231,14 @@ int llog_obd_add(const struct lu_env *env, struct llog_ctxt *ctxt,
 		 struct llog_cookie *logcookies, int numcookies)
 {
 	int raised, rc;
-	ENTRY;
 
 	if (!ctxt) {
 		CERROR("No ctxt\n");
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	if (ctxt->loc_flags & LLOG_CTXT_FLAG_UNINITIALIZED)
-		RETURN(-ENXIO);
+		return -ENXIO;
 
 	CTXT_CHECK_OP(ctxt, obd_add, -EOPNOTSUPP);
 	raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
@@ -252,7 +248,7 @@ int llog_obd_add(const struct lu_env *env, struct llog_ctxt *ctxt,
 				  numcookies);
 	if (!raised)
 		cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_obd_add);
 
@@ -261,16 +257,15 @@ int llog_cancel(const struct lu_env *env, struct llog_ctxt *ctxt,
 		struct llog_cookie *cookies, int flags)
 {
 	int rc;
-	ENTRY;
 
 	if (!ctxt) {
 		CERROR("No ctxt\n");
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	CTXT_CHECK_OP(ctxt, cancel, -EOPNOTSUPP);
 	rc = CTXTP(ctxt, cancel)(env, ctxt, lsm, count, cookies, flags);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_cancel);
 
@@ -278,24 +273,24 @@ int obd_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
 		  struct obd_device *disk_obd, int *index)
 {
 	int rc;
-	ENTRY;
+
 	OBD_CHECK_DT_OP(obd, llog_init, 0);
 	OBD_COUNTER_INCREMENT(obd, llog_init);
 
 	rc = OBP(obd, llog_init)(obd, olg, disk_obd, index);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(obd_llog_init);
 
 int obd_llog_finish(struct obd_device *obd, int count)
 {
 	int rc;
-	ENTRY;
+
 	OBD_CHECK_DT_OP(obd, llog_finish, 0);
 	OBD_COUNTER_INCREMENT(obd, llog_finish);
 
 	rc = OBP(obd, llog_finish)(obd, count);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(obd_llog_finish);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_osd.c b/drivers/staging/lustre/lustre/obdclass/llog_osd.c
index 6dbd21a..654c8e1 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_osd.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_osd.c
@@ -41,10 +41,6 @@
 
 #define DEBUG_SUBSYSTEM S_LOG
 
-#ifndef EXPORT_SYMTAB
-#define EXPORT_SYMTAB
-#endif
-
 #include <obd.h>
 #include <obd_class.h>
 #include <lustre_fid.h>
@@ -97,8 +93,6 @@ static int llog_osd_pad(const struct lu_env *env, struct dt_object *o,
 	struct llog_thread_info	*lgi = llog_info(env);
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(th);
 	LASSERT(off);
 	LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0);
@@ -126,7 +120,7 @@ static int llog_osd_pad(const struct lu_env *env, struct dt_object *o,
 		       o->do_lu.lo_dev->ld_obd->obd_name, rc);
 out:
 	dt_write_unlock(env, o);
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_osd_write_blob(const struct lu_env *env, struct dt_object *o,
@@ -137,8 +131,6 @@ static int llog_osd_write_blob(const struct lu_env *env, struct dt_object *o,
 	int			 buflen = rec->lrh_len;
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(env);
 	LASSERT(o);
 
@@ -203,7 +195,7 @@ out:
 		dt_attr_set(env, o, &lgi->lgi_attr, th, BYPASS_CAPA);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_osd_read_header(const struct lu_env *env,
@@ -214,8 +206,6 @@ static int llog_osd_read_header(const struct lu_env *env,
 	struct llog_thread_info	*lgi;
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE);
 
 	o = handle->lgh_obj;
@@ -225,13 +215,13 @@ static int llog_osd_read_header(const struct lu_env *env,
 
 	rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	LASSERT(lgi->lgi_attr.la_valid & LA_SIZE);
 
 	if (lgi->lgi_attr.la_size == 0) {
 		CDEBUG(D_HA, "not reading header from 0-byte log\n");
-		RETURN(LLOG_EEMPTY);
+		return LLOG_EEMPTY;
 	}
 
 	lgi->lgi_off = 0;
@@ -243,7 +233,7 @@ static int llog_osd_read_header(const struct lu_env *env,
 		CERROR("%s: error reading log header from "DFID": rc = %d\n",
 		       o->do_lu.lo_dev->ld_obd->obd_name,
 		       PFID(lu_object_fid(&o->do_lu)), rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	llh_hdr = &handle->lgh_hdr->llh_hdr;
@@ -256,7 +246,7 @@ static int llog_osd_read_header(const struct lu_env *env,
 		       handle->lgh_name ? handle->lgh_name : "",
 		       PFID(lu_object_fid(&o->do_lu)),
 		       llh_hdr->lrh_type, LLOG_HDR_MAGIC);
-		RETURN(-EIO);
+		return -EIO;
 	} else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) {
 		CERROR("%s: incorrectly sized log %s "DFID" header: "
 		       "%#x (expected %#x)\n"
@@ -265,12 +255,12 @@ static int llog_osd_read_header(const struct lu_env *env,
 		       handle->lgh_name ? handle->lgh_name : "",
 		       PFID(lu_object_fid(&o->do_lu)),
 		       llh_hdr->lrh_len, LLOG_CHUNK_SIZE);
-		RETURN(-EIO);
+		return -EIO;
 	}
 
 	handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index;
 
-	RETURN(0);
+	return 0;
 }
 
 static int llog_osd_declare_write_rec(const struct lu_env *env,
@@ -282,8 +272,6 @@ static int llog_osd_declare_write_rec(const struct lu_env *env,
 	struct dt_object	*o;
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(env);
 	LASSERT(th);
 	LASSERT(loghandle);
@@ -295,18 +283,18 @@ static int llog_osd_declare_write_rec(const struct lu_env *env,
 	rc = dt_declare_record_write(env, o, sizeof(struct llog_log_hdr), 0,
 				     th);
 	if (rc || idx == 0) /* if error or just header */
-		RETURN(rc);
+		return rc;
 
 	if (dt_object_exists(o)) {
 		rc = dt_attr_get(env, o, &lgi->lgi_attr, BYPASS_CAPA);
 		lgi->lgi_off = lgi->lgi_attr.la_size;
 		LASSERT(ergo(rc == 0, lgi->lgi_attr.la_valid & LA_SIZE));
 		if (rc)
-			RETURN(rc);
+			return rc;
 
 		rc = dt_declare_punch(env, o, lgi->lgi_off, OBD_OBJECT_EOF, th);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	} else {
 		lgi->lgi_off = 0;
 	}
@@ -314,7 +302,7 @@ static int llog_osd_declare_write_rec(const struct lu_env *env,
 	/* XXX: implement declared window or multi-chunks approach */
 	rc = dt_declare_record_write(env, o, 32 * 1024, lgi->lgi_off, th);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* returns negative in on error; 0 if success && reccookie == 0; 1 otherwise */
@@ -333,8 +321,6 @@ static int llog_osd_write_rec(const struct lu_env *env,
 	struct dt_object	*o;
 	size_t			 left;
 
-	ENTRY;
-
 	LASSERT(env);
 	llh = loghandle->lgh_hdr;
 	LASSERT(llh);
@@ -352,11 +338,11 @@ static int llog_osd_write_rec(const struct lu_env *env,
 	else
 		rc = (reclen > LLOG_CHUNK_SIZE) ? -E2BIG : 0;
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (buf)
 		/* write_blob adds header and tail to lrh_len. */
@@ -369,7 +355,7 @@ static int llog_osd_write_rec(const struct lu_env *env,
 			LBUG();
 
 		if (idx && llh->llh_size && llh->llh_size != rec->lrh_len)
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		if (!ext2_test_bit(idx, llh->llh_bitmap))
 			CERROR("%s: modify unset record %u\n",
@@ -384,7 +370,7 @@ static int llog_osd_write_rec(const struct lu_env *env,
 					 &lgi->lgi_off, th);
 		/* we are done if we only write the header or on error */
 		if (rc || idx == 0)
-			RETURN(rc);
+			return rc;
 
 		if (buf) {
 			/* We assume that caller has set lgh_cur_* */
@@ -400,7 +386,7 @@ static int llog_osd_write_rec(const struct lu_env *env,
 				CERROR("%s: modify idx mismatch %u/%d\n",
 				       o->do_lu.lo_dev->ld_obd->obd_name, idx,
 				       loghandle->lgh_cur_idx);
-				RETURN(-EFAULT);
+				return -EFAULT;
 			}
 		} else {
 			/* Assumes constant lrh_len */
@@ -413,7 +399,7 @@ static int llog_osd_write_rec(const struct lu_env *env,
 			reccookie->lgc_index = idx;
 			rc = 1;
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	/* Make sure that records don't cross a chunk boundary, so we can
@@ -432,12 +418,12 @@ static int llog_osd_write_rec(const struct lu_env *env,
 		index = loghandle->lgh_last_idx + 1;
 		rc = llog_osd_pad(env, o, &lgi->lgi_off, left, index, th);
 		if (rc)
-			RETURN(rc);
+			return rc;
 		loghandle->lgh_last_idx++; /*for pad rec*/
 	}
 	/* if it's the last idx in log file, then return -ENOSPC */
 	if (loghandle->lgh_last_idx >= LLOG_BITMAP_SIZE(llh) - 1)
-		RETURN(-ENOSPC);
+		return -ENOSPC;
 
 	loghandle->lgh_last_idx++;
 	index = loghandle->lgh_last_idx;
@@ -509,7 +495,7 @@ out:
 			reccookie->lgc_subsys = -1;
 		rc = 1;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /* We can skip reading at least as many log blocks as the number of
@@ -541,13 +527,11 @@ static int llog_osd_next_block(const struct lu_env *env,
 	struct dt_device	*dt;
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(env);
 	LASSERT(lgi);
 
 	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off "LPU64")\n",
 	       next_idx, *cur_idx, *cur_offset);
@@ -668,10 +652,8 @@ static int llog_osd_prev_block(const struct lu_env *env,
 	loff_t			 cur_offset;
 	int			 rc;
 
-	ENTRY;
-
 	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	CDEBUG(D_OTHER, "looking for log index %u\n", prev_idx);
 
@@ -798,8 +780,6 @@ static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle,
 	struct local_oid_storage	*los;
 	int				 rc = 0;
 
-	ENTRY;
-
 	LASSERT(env);
 	LASSERT(ctxt);
 	LASSERT(ctxt->loc_exp);
@@ -809,7 +789,7 @@ static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle,
 
 	ls = ls_device_get(dt);
 	if (IS_ERR(ls))
-		RETURN(PTR_ERR(ls));
+		return PTR_ERR(ls);
 
 	mutex_lock(&ls->ls_los_mutex);
 	los = dt_los_find(ls, name != NULL ? FID_SEQ_LLOG_NAME : FID_SEQ_LLOG);
@@ -864,7 +844,7 @@ static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle,
 	handle->private_data = los;
 	LASSERT(handle->lgh_ctxt);
 
-	RETURN(rc);
+	return rc;
 
 out_put:
 	lu_object_put(env, &o->do_lu);
@@ -873,7 +853,7 @@ out_name:
 		OBD_FREE(handle->lgh_name, strlen(name) + 1);
 out:
 	dt_los_put(los);
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_osd_exist(struct llog_handle *handle)
@@ -891,33 +871,31 @@ static int llog_osd_declare_create(const struct lu_env *env,
 	struct dt_object		*o;
 	int				 rc;
 
-	ENTRY;
-
 	LASSERT(res->lgh_obj);
 	LASSERT(th);
 
 	/* object can be created by another thread */
 	o = res->lgh_obj;
 	if (dt_object_exists(o))
-		RETURN(0);
+		return 0;
 
 	los = res->private_data;
 	LASSERT(los);
 
 	rc = llog_osd_declare_new_object(env, los, o, th);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = dt_declare_record_write(env, o, LLOG_CHUNK_SIZE, 0, th);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (res->lgh_name) {
 		struct dt_object *llog_dir;
 
 		llog_dir = llog_osd_dir_get(env, res->lgh_ctxt);
 		if (IS_ERR(llog_dir))
-			RETURN(PTR_ERR(llog_dir));
+			return PTR_ERR(llog_dir);
 		logid_to_fid(&res->lgh_id, &lgi->lgi_fid);
 		rc = dt_declare_insert(env, llog_dir,
 				       (struct dt_rec *)&lgi->lgi_fid,
@@ -928,7 +906,7 @@ static int llog_osd_declare_create(const struct lu_env *env,
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       res->lgh_name, rc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /* This is a callback from the llog_* functions.
@@ -941,15 +919,13 @@ static int llog_osd_create(const struct lu_env *env, struct llog_handle *res,
 	struct dt_object	*o;
 	int		      rc = 0;
 
-	ENTRY;
-
 	LASSERT(env);
 	o = res->lgh_obj;
 	LASSERT(o);
 
 	/* llog can be already created */
 	if (dt_object_exists(o))
-		RETURN(-EEXIST);
+		return -EEXIST;
 
 	los = res->private_data;
 	LASSERT(los);
@@ -962,14 +938,14 @@ static int llog_osd_create(const struct lu_env *env, struct llog_handle *res,
 
 	dt_write_unlock(env, o);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (res->lgh_name) {
 		struct dt_object *llog_dir;
 
 		llog_dir = llog_osd_dir_get(env, res->lgh_ctxt);
 		if (IS_ERR(llog_dir))
-			RETURN(PTR_ERR(llog_dir));
+			return PTR_ERR(llog_dir);
 
 		logid_to_fid(&res->lgh_id, &lgi->lgi_fid);
 		dt_read_lock(env, llog_dir, 0);
@@ -984,7 +960,7 @@ static int llog_osd_create(const struct lu_env *env, struct llog_handle *res,
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       res->lgh_name, rc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_osd_close(const struct lu_env *env, struct llog_handle *handle)
@@ -992,8 +968,6 @@ static int llog_osd_close(const struct lu_env *env, struct llog_handle *handle)
 	struct local_oid_storage	*los;
 	int				 rc = 0;
 
-	ENTRY;
-
 	LASSERT(handle->lgh_obj);
 
 	lu_object_put(env, &handle->lgh_obj->do_lu);
@@ -1005,7 +979,7 @@ static int llog_osd_close(const struct lu_env *env, struct llog_handle *handle)
 	if (handle->lgh_name)
 		OBD_FREE(handle->lgh_name, strlen(handle->lgh_name) + 1);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_osd_destroy(const struct lu_env *env,
@@ -1018,8 +992,6 @@ static int llog_osd_destroy(const struct lu_env *env,
 	char			*name = NULL;
 	int			 rc;
 
-	ENTRY;
-
 	ctxt = loghandle->lgh_ctxt;
 	LASSERT(ctxt);
 
@@ -1032,7 +1004,7 @@ static int llog_osd_destroy(const struct lu_env *env,
 
 	th = dt_trans_create(env, d);
 	if (IS_ERR(th))
-		RETURN(PTR_ERR(th));
+		return PTR_ERR(th);
 
 	if (loghandle->lgh_name) {
 		llog_dir = llog_osd_dir_get(env, ctxt);
@@ -1082,7 +1054,7 @@ out_trans:
 	dt_trans_stop(env, d, th);
 	if (llog_dir != NULL)
 		lu_object_put(env, &llog_dir->do_lu);
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_osd_setup(const struct lu_env *env, struct obd_device *obd,
@@ -1094,8 +1066,6 @@ static int llog_osd_setup(const struct lu_env *env, struct obd_device *obd,
 	struct llog_ctxt		*ctxt;
 	int				 rc = 0;
 
-	ENTRY;
-
 	LASSERT(obd);
 	LASSERT(olg->olg_ctxts[ctxt_idx]);
 
@@ -1131,7 +1101,7 @@ static int llog_osd_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
 	dt = ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt;
 	ls = ls_device_get(dt);
 	if (IS_ERR(ls))
-		RETURN(PTR_ERR(ls));
+		return PTR_ERR(ls);
 
 	mutex_lock(&ls->ls_los_mutex);
 	los = dt_los_find(ls, FID_SEQ_LLOG);
@@ -1175,8 +1145,6 @@ int llog_osd_get_cat_list(const struct lu_env *env, struct dt_device *d,
 	struct thandle		*th;
 	int			 rc, size;
 
-	ENTRY;
-
 	LASSERT(d);
 
 	size = sizeof(*idarray) * count;
@@ -1186,7 +1154,7 @@ int llog_osd_get_cat_list(const struct lu_env *env, struct dt_device *d,
 
 	o = dt_locate(env, d, &lgi->lgi_fid);
 	if (IS_ERR(o))
-		RETURN(PTR_ERR(o));
+		return PTR_ERR(o);
 
 	if (!dt_object_exists(o)) {
 		th = dt_trans_create(env, d);
@@ -1253,10 +1221,9 @@ out_trans:
 		GOTO(out, rc);
 	}
 
-	EXIT;
 out:
 	lu_object_put(env, &o->do_lu);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_osd_get_cat_list);
 
@@ -1270,7 +1237,7 @@ int llog_osd_put_cat_list(const struct lu_env *env, struct dt_device *d,
 	int			 rc, size;
 
 	if (!count)
-		RETURN(0);
+		return 0;
 
 	LASSERT(d);
 
@@ -1281,7 +1248,7 @@ int llog_osd_put_cat_list(const struct lu_env *env, struct dt_device *d,
 
 	o = dt_locate(env, d, &lgi->lgi_fid);
 	if (IS_ERR(o))
-		RETURN(PTR_ERR(o));
+		return PTR_ERR(o);
 
 	if (!dt_object_exists(o))
 		GOTO(out, rc = -ENOENT);
@@ -1318,6 +1285,6 @@ out_trans:
 	dt_trans_stop(env, d, th);
 out:
 	lu_object_put(env, &o->do_lu);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_osd_put_cat_list);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c
index dedfecf..24ca099 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c
@@ -88,7 +88,6 @@ EXPORT_SYMBOL(lustre_swab_llog_id);
 
 void lustre_swab_llogd_body (struct llogd_body *d)
 {
-	ENTRY;
 	print_llogd_body(d);
 	lustre_swab_llog_id(&d->lgd_logid);
 	__swab32s (&d->lgd_ctxt_idx);
@@ -98,7 +97,6 @@ void lustre_swab_llogd_body (struct llogd_body *d)
 	__swab32s (&d->lgd_len);
 	__swab64s (&d->lgd_cur_offset);
 	print_llogd_body(d);
-	EXIT;
 }
 EXPORT_SYMBOL(lustre_swab_llogd_body);
 
@@ -203,6 +201,23 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec)
 		break;
 	}
 
+	case HSM_AGENT_REC: {
+		struct llog_agent_req_rec *arr =
+			(struct llog_agent_req_rec *)rec;
+
+		__swab32s(&arr->arr_hai.hai_len);
+		__swab32s(&arr->arr_hai.hai_action);
+		lustre_swab_lu_fid(&arr->arr_hai.hai_fid);
+		lustre_swab_lu_fid(&arr->arr_hai.hai_dfid);
+		__swab64s(&arr->arr_hai.hai_cookie);
+		__swab64s(&arr->arr_hai.hai_extent.offset);
+		__swab64s(&arr->arr_hai.hai_extent.length);
+		__swab64s(&arr->arr_hai.hai_gid);
+		/* no swabing for opaque data */
+		/* hai_data[0]; */
+		break;
+	}
+
 	case MDS_SETATTR64_REC:
 	{
 		struct llog_setattr64_rec *lsr =
@@ -281,20 +296,17 @@ static void print_llog_hdr(struct llog_log_hdr *h)
 
 void lustre_swab_llog_hdr (struct llog_log_hdr *h)
 {
-	ENTRY;
 	print_llog_hdr(h);
 
 	lustre_swab_llog_rec(&h->llh_hdr);
 
 	print_llog_hdr(h);
-	EXIT;
 }
 EXPORT_SYMBOL(lustre_swab_llog_hdr);
 
 static void print_lustre_cfg(struct lustre_cfg *lcfg)
 {
 	int i;
-	ENTRY;
 
 	if (!(libcfs_debug & D_OTHER)) /* don't loop on nothing */
 		return;
@@ -311,20 +323,17 @@ static void print_lustre_cfg(struct lustre_cfg *lcfg)
 		for (i = 0; i < lcfg->lcfg_bufcount; i++)
 			CDEBUG(D_OTHER, "\tlcfg->lcfg_buflens[%d]: %d\n",
 			       i, lcfg->lcfg_buflens[i]);
-	EXIT;
 }
 
 void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg)
 {
 	int i;
-	ENTRY;
 
 	__swab32s(&lcfg->lcfg_version);
 
 	if (lcfg->lcfg_version != LUSTRE_CFG_VERSION) {
 		CERROR("not swabbing lustre_cfg version %#x (expecting %#x)\n",
 		       lcfg->lcfg_version, LUSTRE_CFG_VERSION);
-		EXIT;
 		return;
 	}
 
@@ -337,7 +346,6 @@ void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg)
 		__swab32s(&lcfg->lcfg_buflens[i]);
 
 	print_lustre_cfg(lcfg);
-	EXIT;
 	return;
 }
 EXPORT_SYMBOL(lustre_swab_lustre_cfg);
@@ -360,7 +368,6 @@ struct cfg_marker32 {
 void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size)
 {
 	struct cfg_marker32 *cm32 = (struct cfg_marker32*)marker;
-	ENTRY;
 
 	if (swab) {
 		__swab32s(&marker->cm_step);
@@ -401,7 +408,6 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size)
 		__swab64s(&marker->cm_canceltime);
 	}
 
-	EXIT;
 	return;
 }
 EXPORT_SYMBOL(lustre_swab_cfg_marker);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_test.c b/drivers/staging/lustre/lustre/obdclass/llog_test.c
index d397f78..d9e6d12 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_test.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_test.c
@@ -78,22 +78,22 @@ static int verify_handle(char *test, struct llog_handle *llh, int num_recs)
 	if (active_recs != num_recs) {
 		CERROR("%s: expected %d active recs after write, found %d\n",
 		       test, num_recs, active_recs);
-		RETURN(-ERANGE);
+		return -ERANGE;
 	}
 
 	if (llh->lgh_hdr->llh_count != num_recs) {
 		CERROR("%s: handle->count is %d, expected %d after write\n",
 		       test, llh->lgh_hdr->llh_count, num_recs);
-		RETURN(-ERANGE);
+		return -ERANGE;
 	}
 
 	if (llh->lgh_last_idx < last_idx) {
 		CERROR("%s: handle->last_idx is %d, expected %d after write\n",
 		       test, llh->lgh_last_idx, last_idx);
-		RETURN(-ERANGE);
+		return -ERANGE;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 /* Test named-log create/open, close */
@@ -105,8 +105,6 @@ static int llog_test_1(const struct lu_env *env,
 	int rc;
 	int rc2;
 
-	ENTRY;
-
 	CWARN("1a: create a log with name: %s\n", name);
 	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
 	LASSERT(ctxt);
@@ -134,7 +132,7 @@ out_close:
 	}
 out:
 	llog_ctxt_put(ctxt);
-	RETURN(rc);
+	return rc;
 }
 
 /* Test named-log reopen; returns opened log on success */
@@ -146,8 +144,6 @@ static int llog_test_2(const struct lu_env *env, struct obd_device *obd,
 	struct llog_logid	 logid;
 	int			 rc;
 
-	ENTRY;
-
 	CWARN("2a: re-open a log with name: %s\n", name);
 	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
 	LASSERT(ctxt);
@@ -213,7 +209,7 @@ out_close_llh:
 out_put:
 	llog_ctxt_put(ctxt);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Test record writing, single and in bulk */
@@ -224,8 +220,6 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd,
 	int			 rc, i;
 	int			 num_recs = 1; /* 1 for the header */
 
-	ENTRY;
-
 	lgr.lgr_hdr.lrh_len = lgr.lgr_tail.lrt_len = sizeof(lgr);
 	lgr.lgr_hdr.lrh_type = LLOG_GEN_REC;
 
@@ -234,12 +228,12 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd,
 	num_recs++;
 	if (rc < 0) {
 		CERROR("3a: write one log record failed: %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = verify_handle("3a", llh, num_recs);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CWARN("3b: write 10 cfg log records with 8 bytes bufs\n");
 	for (i = 0; i < 10; i++) {
@@ -253,14 +247,14 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd,
 		if (rc < 0) {
 			CERROR("3b: write 10 records failed at #%d: %d\n",
 			       i + 1, rc);
-			RETURN(rc);
+			return rc;
 		}
 		num_recs++;
 	}
 
 	rc = verify_handle("3b", llh, num_recs);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CWARN("3c: write 1000 more log records\n");
 	for (i = 0; i < 1000; i++) {
@@ -268,14 +262,14 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd,
 		if (rc < 0) {
 			CERROR("3c: write 1000 records failed at #%d: %d\n",
 			       i + 1, rc);
-			RETURN(rc);
+			return rc;
 		}
 		num_recs++;
 	}
 
 	rc = verify_handle("3c", llh, num_recs);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	CWARN("3d: write log more than BITMAP_SIZE, return -ENOSPC\n");
 	for (i = 0; i < LLOG_BITMAP_SIZE(llh->lgh_hdr) + 1; i++) {
@@ -299,20 +293,20 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd,
 		} else if (rc < 0) {
 			CERROR("3d: write recs failed at #%d: %d\n",
 			       i + 1, rc);
-			RETURN(rc);
+			return rc;
 		}
 		num_recs++;
 	}
 	if (rc != -ENOSPC) {
 		CWARN("3d: write record more than BITMAP size!\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	CWARN("3d: wrote %d more records before end of llog is reached\n",
 	      num_recs);
 
 	rc = verify_handle("3d", llh, num_recs);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Test catalogue additions */
@@ -328,8 +322,6 @@ static int llog_test_4(const struct lu_env *env, struct obd_device *obd)
 	char			*buf;
 	struct llog_rec_hdr	 rec;
 
-	ENTRY;
-
 	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
 	LASSERT(ctxt);
 
@@ -424,7 +416,7 @@ out:
 	}
 ctxt_release:
 	llog_ctxt_put(ctxt);
-	RETURN(rc);
+	return rc;
 }
 
 static int cat_counter;
@@ -437,7 +429,7 @@ static int cat_print_cb(const struct lu_env *env, struct llog_handle *llh,
 
 	if (rec->lrh_type != LLOG_LOGID_MAGIC) {
 		CERROR("invalid record in catalog\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	logid_to_fid(&lir->lid_id, &fid);
@@ -448,7 +440,7 @@ static int cat_print_cb(const struct lu_env *env, struct llog_handle *llh,
 
 	cat_counter++;
 
-	RETURN(0);
+	return 0;
 }
 
 static int plain_counter;
@@ -460,7 +452,7 @@ static int plain_print_cb(const struct lu_env *env, struct llog_handle *llh,
 
 	if (!(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)) {
 		CERROR("log is not plain\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	logid_to_fid(&llh->lgh_id, &fid);
@@ -470,7 +462,7 @@ static int plain_print_cb(const struct lu_env *env, struct llog_handle *llh,
 
 	plain_counter++;
 
-	RETURN(0);
+	return 0;
 }
 
 static int cancel_count;
@@ -483,7 +475,7 @@ static int llog_cancel_rec_cb(const struct lu_env *env,
 
 	if (!(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)) {
 		CERROR("log is not plain\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	cookie.lgc_lgl = llh->lgh_id;
@@ -492,8 +484,8 @@ static int llog_cancel_rec_cb(const struct lu_env *env,
 	llog_cat_cancel_records(env, llh->u.phd.phd_cat_handle, 1, &cookie);
 	cancel_count++;
 	if (cancel_count == LLOG_TEST_RECNUM)
-		RETURN(-LLOG_EEMPTY);
-	RETURN(0);
+		return -LLOG_EEMPTY;
+	return 0;
 }
 
 /* Test log and catalogue processing */
@@ -505,8 +497,6 @@ static int llog_test_5(const struct lu_env *env, struct obd_device *obd)
 	struct llog_mini_rec	 lmr;
 	struct llog_ctxt	*ctxt;
 
-	ENTRY;
-
 	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
 	LASSERT(ctxt);
 
@@ -602,7 +592,7 @@ out:
 out_put:
 	llog_ctxt_put(ctxt);
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Test client api; open log by name and process */
@@ -686,7 +676,7 @@ nctxt_put:
 	llog_ctxt_put(nctxt);
 ctxt_release:
 	llog_ctxt_put(ctxt);
-	RETURN(rc);
+	return rc;
 }
 
 static union {
@@ -728,12 +718,10 @@ static int llog_test_7_sub(const struct lu_env *env, struct llog_ctxt *ctxt)
 	int			 rc = 0, i, process_count;
 	int			 num_recs = 0;
 
-	ENTRY;
-
 	rc = llog_open_create(env, ctxt, &llh, NULL, NULL);
 	if (rc) {
 		CERROR("7_sub: create log failed\n");
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = llog_init_handle(env, llh,
@@ -804,7 +792,7 @@ out_close:
 	if (rc)
 		llog_destroy(env, llh);
 	llog_close(env, llh);
-	RETURN(rc);
+	return rc;
 }
 
 /* Test all llog records writing and processing */
@@ -813,8 +801,6 @@ static int llog_test_7(const struct lu_env *env, struct obd_device *obd)
 	struct llog_ctxt	*ctxt;
 	int			 rc;
 
-	ENTRY;
-
 	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
 
 	CWARN("7a: test llog_logid_rec\n");
@@ -895,7 +881,7 @@ static int llog_test_7(const struct lu_env *env, struct obd_device *obd)
 	}
 out:
 	llog_ctxt_put(ctxt);
-	RETURN(rc);
+	return rc;
 }
 
 /* -------------------------------------------------------------------------
@@ -908,7 +894,6 @@ static int llog_run_tests(const struct lu_env *env, struct obd_device *obd)
 	int			 rc, err;
 	char			 name[10];
 
-	ENTRY;
 	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
 	LASSERT(ctxt);
 
@@ -970,18 +955,16 @@ static int llog_test_cleanup(struct obd_device *obd)
 	struct lu_env		 env;
 	int			 rc;
 
-	ENTRY;
-
 	rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	tgt = obd->obd_lvfs_ctxt.dt->dd_lu_dev.ld_obd;
 	rc = llog_cleanup(&env, llog_get_context(tgt, LLOG_TEST_ORIG_CTXT));
 	if (rc)
 		CERROR("failed to llog_test_llog_finish: %d\n", rc);
 	lu_env_fini(&env);
-	RETURN(rc);
+	return rc;
 }
 
 static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
@@ -993,16 +976,14 @@ static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	struct lu_context	 test_session;
 	int			 rc;
 
-	ENTRY;
-
 	if (lcfg->lcfg_bufcount < 2) {
 		CERROR("requires a TARGET OBD name\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (lcfg->lcfg_buflens[1] < 1) {
 		CERROR("requires a TARGET OBD name\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* disk obd */
@@ -1010,12 +991,12 @@ static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
 		CERROR("target device not attached or not set up (%s)\n",
 		       lustre_cfg_string(lcfg, 1));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = lu_context_init(&test_session, LCT_SESSION);
 	if (rc)
@@ -1056,7 +1037,7 @@ cleanup_session:
 	lu_context_fini(&test_session);
 cleanup_env:
 	lu_env_fini(&env);
-	RETURN(rc);
+	return rc;
 }
 
 static struct obd_ops llog_obd_ops = {
diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.c b/drivers/staging/lustre/lustre/obdclass/local_storage.c
index 3be35a8..cc19fba 100644
--- a/drivers/staging/lustre/lustre/obdclass/local_storage.c
+++ b/drivers/staging/lustre/lustre/obdclass/local_storage.c
@@ -45,17 +45,15 @@ static int ls_object_init(const struct lu_env *env, struct lu_object *o,
 	struct lu_object	*below;
 	struct lu_device	*under;
 
-	ENTRY;
-
 	ls = container_of0(o->lo_dev, struct ls_device, ls_top_dev.dd_lu_dev);
 	under = &ls->ls_osd->dd_lu_dev;
 	below = under->ld_ops->ldo_object_alloc(env, o->lo_header, under);
 	if (below == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	lu_object_add(o, below);
 
-	RETURN(0);
+	return 0;
 }
 
 static void ls_object_free(const struct lu_env *env, struct lu_object *o)
@@ -143,8 +141,6 @@ struct ls_device *ls_device_get(struct dt_device *dev)
 {
 	struct ls_device *ls;
 
-	ENTRY;
-
 	mutex_lock(&ls_list_mutex);
 	ls = __ls_find_dev(dev);
 	if (ls)
@@ -170,7 +166,7 @@ struct ls_device *ls_device_get(struct dt_device *dev)
 	list_add(&ls->ls_linkage, &ls_list_head);
 out_ls:
 	mutex_unlock(&ls_list_mutex);
-	RETURN(ls);
+	return ls;
 }
 
 void ls_device_put(const struct lu_env *env, struct ls_device *ls)
@@ -224,26 +220,24 @@ int local_object_declare_create(const struct lu_env *env,
 	struct dt_thread_info	*dti = dt_info(env);
 	int			 rc;
 
-	ENTRY;
-
 	/* update fid generation file */
 	if (los != NULL) {
 		LASSERT(dt_object_exists(los->los_obj));
 		rc = dt_declare_record_write(env, los->los_obj,
 					     sizeof(struct los_ondisk), 0, th);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
 	rc = dt_declare_create(env, o, attr, NULL, dof, th);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	dti->dti_lb.lb_buf = NULL;
 	dti->dti_lb.lb_len = sizeof(dti->dti_lma);
 	rc = dt_declare_xattr_set(env, o, &dti->dti_lb, XATTR_NAME_LMA, 0, th);
 
-	RETURN(rc);
+	return rc;
 }
 
 int local_object_create(const struct lu_env *env,
@@ -255,14 +249,12 @@ int local_object_create(const struct lu_env *env,
 	obd_id			 lastid;
 	int			 rc;
 
-	ENTRY;
-
 	rc = dt_create(env, o, attr, NULL, dof, th);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (los == NULL)
-		RETURN(rc);
+		return rc;
 
 	LASSERT(los->los_obj);
 	LASSERT(dt_object_exists(los->los_obj));
@@ -283,7 +275,7 @@ int local_object_create(const struct lu_env *env,
 			     th);
 	mutex_unlock(&los->los_id_lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -304,7 +296,7 @@ struct dt_object *__local_file_create(const struct lu_env *env,
 
 	dto = ls_locate(env, ls, fid);
 	if (unlikely(IS_ERR(dto)))
-		RETURN(dto);
+		return dto;
 
 	LASSERT(dto != NULL);
 	if (dt_object_exists(dto))
@@ -377,7 +369,7 @@ out:
 		lu_object_put_nocache(env, &dto->do_lu);
 		dto = ERR_PTR(rc);
 	}
-	RETURN(dto);
+	return dto;
 }
 
 /*
@@ -443,7 +435,7 @@ struct dt_object *local_file_find_or_create_with_fid(const struct lu_env *env,
 
 		ls = ls_device_get(dt);
 		if (IS_ERR(ls)) {
-			dto = ERR_PTR(PTR_ERR(ls));
+			dto = ERR_CAST(ls);
 		} else {
 			/* create the object */
 			dti->dti_attr.la_valid	= LA_MODE;
@@ -537,7 +529,7 @@ local_index_find_or_create_with_fid(const struct lu_env *env,
 
 		ls = ls_device_get(dt);
 		if (IS_ERR(ls)) {
-			dto = ERR_PTR(PTR_ERR(ls));
+			dto = ERR_CAST(ls);
 		} else {
 			/* create the object */
 			dti->dti_attr.la_valid		= LA_MODE;
@@ -588,17 +580,15 @@ int local_object_unlink(const struct lu_env *env, struct dt_device *dt,
 	struct thandle		*th;
 	int			 rc;
 
-	ENTRY;
-
 	rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
 	if (rc == -ENOENT)
-		RETURN(0);
+		return 0;
 	else if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	dto = dt_locate(env, dt, &dti->dti_fid);
 	if (unlikely(IS_ERR(dto)))
-		RETURN(PTR_ERR(dto));
+		return PTR_ERR(dto);
 
 	th = dt_trans_create(env, dt);
 	if (IS_ERR(th))
@@ -761,11 +751,9 @@ int local_oid_storage_init(const struct lu_env *env, struct dt_device *dev,
 	__u32			 first_oid = fid_oid(first_fid);
 	int			 rc = 0;
 
-	ENTRY;
-
 	ls = ls_device_get(dev);
 	if (IS_ERR(ls))
-		RETURN(PTR_ERR(ls));
+		return PTR_ERR(ls);
 
 	mutex_lock(&ls->ls_los_mutex);
 	*los = dt_los_find(ls, fid_seq(first_fid));
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c
deleted file mode 100644
index e2d57fe..0000000
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/* GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2011, 2012, Intel Corporation.
- * Use is subject to license terms.
- *
- * Author: Niu Yawei <niu@whamcloud.com>
- */
-/*
- * lustre/obdclass/lprocfs_jobstats.c
- */
-
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
-#define DEBUG_SUBSYSTEM S_CLASS
-
-
-#include <obd_class.h>
-#include <lprocfs_status.h>
-#include <lustre/lustre_idl.h>
-
-#if defined(LPROCFS)
-
-/*
- * JobID formats & JobID environment variable names for supported
- * job schedulers:
- *
- * SLURM:
- *   JobID format:  32 bit integer.
- *   JobID env var: SLURM_JOB_ID.
- * SGE:
- *   JobID format:  Decimal integer range to 99999.
- *   JobID env var: JOB_ID.
- * LSF:
- *   JobID format:  6 digit integer by default (up to 999999), can be
- *		  increased to 10 digit (up to 2147483646).
- *   JobID env var: LSB_JOBID.
- * Loadleveler:
- *   JobID format:  String of machine_name.cluster_id.process_id, for
- *		  example: fr2n02.32.0
- *   JobID env var: LOADL_STEP_ID.
- * PBS:
- *   JobID format:  String of sequence_number[.server_name][@server].
- *   JobID env var: PBS_JOBID.
- * Maui/MOAB:
- *   JobID format:  Same as PBS.
- *   JobID env var: Same as PBS.
- */
-
-struct job_stat {
-	struct hlist_node      js_hash;
-	struct list_head	    js_list;
-	atomic_t	  js_refcount;
-	char		  js_jobid[JOBSTATS_JOBID_SIZE];
-	time_t		js_timestamp; /* seconds */
-	struct lprocfs_stats *js_stats;
-	struct obd_job_stats *js_jobstats;
-};
-
-static unsigned job_stat_hash(cfs_hash_t *hs, const void *key, unsigned mask)
-{
-	return cfs_hash_djb2_hash(key, strlen(key), mask);
-}
-
-static void *job_stat_key(struct hlist_node *hnode)
-{
-	struct job_stat *job;
-	job = hlist_entry(hnode, struct job_stat, js_hash);
-	return job->js_jobid;
-}
-
-static int job_stat_keycmp(const void *key, struct hlist_node *hnode)
-{
-	struct job_stat *job;
-	job = hlist_entry(hnode, struct job_stat, js_hash);
-	return (strlen(job->js_jobid) == strlen(key)) &&
-	       !strncmp(job->js_jobid, key, strlen(key));
-}
-
-static void *job_stat_object(struct hlist_node *hnode)
-{
-	return hlist_entry(hnode, struct job_stat, js_hash);
-}
-
-static void job_stat_get(cfs_hash_t *hs, struct hlist_node *hnode)
-{
-	struct job_stat *job;
-	job = hlist_entry(hnode, struct job_stat, js_hash);
-	atomic_inc(&job->js_refcount);
-}
-
-static void job_free(struct job_stat *job)
-{
-	LASSERT(atomic_read(&job->js_refcount) == 0);
-	LASSERT(job->js_jobstats);
-
-	write_lock(&job->js_jobstats->ojs_lock);
-	list_del_init(&job->js_list);
-	write_unlock(&job->js_jobstats->ojs_lock);
-
-	lprocfs_free_stats(&job->js_stats);
-	OBD_FREE_PTR(job);
-}
-
-static void job_putref(struct job_stat *job)
-{
-	LASSERT(atomic_read(&job->js_refcount) > 0);
-	if (atomic_dec_and_test(&job->js_refcount))
-		job_free(job);
-}
-
-static void job_stat_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
-{
-	struct job_stat *job;
-	job = hlist_entry(hnode, struct job_stat, js_hash);
-	job_putref(job);
-}
-
-static void job_stat_exit(cfs_hash_t *hs, struct hlist_node *hnode)
-{
-	CERROR("Should not have any items!");
-}
-
-static cfs_hash_ops_t job_stats_hash_ops = {
-	.hs_hash       = job_stat_hash,
-	.hs_key	= job_stat_key,
-	.hs_keycmp     = job_stat_keycmp,
-	.hs_object     = job_stat_object,
-	.hs_get	= job_stat_get,
-	.hs_put_locked = job_stat_put_locked,
-	.hs_exit       = job_stat_exit,
-};
-
-static int job_iter_callback(cfs_hash_t *hs, cfs_hash_bd_t *bd,
-			     struct hlist_node *hnode, void *data)
-{
-	time_t oldest = *((time_t *)data);
-	struct job_stat *job;
-
-	job = hlist_entry(hnode, struct job_stat, js_hash);
-	if (!oldest || job->js_timestamp < oldest)
-		cfs_hash_bd_del_locked(hs, bd, hnode);
-
-	return 0;
-}
-
-static void lprocfs_job_cleanup(struct obd_job_stats *stats, bool force)
-{
-	time_t oldest, now;
-
-	if (stats->ojs_cleanup_interval == 0)
-		return;
-
-	now = cfs_time_current_sec();
-	if (!force && now < stats->ojs_last_cleanup +
-			    stats->ojs_cleanup_interval)
-		return;
-
-	oldest = now - stats->ojs_cleanup_interval;
-	cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback,
-			       &oldest);
-	stats->ojs_last_cleanup = cfs_time_current_sec();
-}
-
-static struct job_stat *job_alloc(char *jobid, struct obd_job_stats *jobs)
-{
-	struct job_stat *job;
-
-	LASSERT(jobs->ojs_cntr_num && jobs->ojs_cntr_init_fn);
-
-	OBD_ALLOC_PTR(job);
-	if (job == NULL)
-		return NULL;
-
-	job->js_stats = lprocfs_alloc_stats(jobs->ojs_cntr_num, 0);
-	if (job->js_stats == NULL) {
-		OBD_FREE_PTR(job);
-		return NULL;
-	}
-
-	jobs->ojs_cntr_init_fn(job->js_stats);
-
-	memcpy(job->js_jobid, jobid, JOBSTATS_JOBID_SIZE);
-	job->js_timestamp = cfs_time_current_sec();
-	job->js_jobstats = jobs;
-	INIT_HLIST_NODE(&job->js_hash);
-	INIT_LIST_HEAD(&job->js_list);
-	atomic_set(&job->js_refcount, 1);
-
-	return job;
-}
-
-int lprocfs_job_stats_log(struct obd_device *obd, char *jobid,
-			  int event, long amount)
-{
-	struct obd_job_stats *stats = &obd->u.obt.obt_jobstats;
-	struct job_stat *job, *job2;
-	ENTRY;
-
-	LASSERT(stats && stats->ojs_hash);
-
-	lprocfs_job_cleanup(stats, false);
-
-	if (!jobid || !strlen(jobid))
-		RETURN(-EINVAL);
-
-	if (strlen(jobid) >= JOBSTATS_JOBID_SIZE) {
-		CERROR("Invalid jobid size (%lu), expect(%d)\n",
-		       (unsigned long)strlen(jobid) + 1, JOBSTATS_JOBID_SIZE);
-		RETURN(-EINVAL);
-	}
-
-	job = cfs_hash_lookup(stats->ojs_hash, jobid);
-	if (job)
-		goto found;
-
-	job = job_alloc(jobid, stats);
-	if (job == NULL)
-		RETURN(-ENOMEM);
-
-	job2 = cfs_hash_findadd_unique(stats->ojs_hash, job->js_jobid,
-				       &job->js_hash);
-	if (job2 != job) {
-		job_putref(job);
-		job = job2;
-		/* We cannot LASSERT(!list_empty(&job->js_list)) here,
-		 * since we just lost the race for inserting "job" into the
-		 * ojs_list, and some other thread is doing it _right_now_.
-		 * Instead, be content the other thread is doing this, since
-		 * "job2" was initialized in job_alloc() already. LU-2163 */
-	} else {
-		LASSERT(list_empty(&job->js_list));
-		write_lock(&stats->ojs_lock);
-		list_add_tail(&job->js_list, &stats->ojs_list);
-		write_unlock(&stats->ojs_lock);
-	}
-
-found:
-	LASSERT(stats == job->js_jobstats);
-	LASSERT(stats->ojs_cntr_num > event);
-	job->js_timestamp = cfs_time_current_sec();
-	lprocfs_counter_add(job->js_stats, event, amount);
-
-	job_putref(job);
-	RETURN(0);
-}
-EXPORT_SYMBOL(lprocfs_job_stats_log);
-
-void lprocfs_job_stats_fini(struct obd_device *obd)
-{
-	struct obd_job_stats *stats = &obd->u.obt.obt_jobstats;
-	time_t oldest = 0;
-
-	if (stats->ojs_hash == NULL)
-		return;
-	cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback, &oldest);
-	cfs_hash_putref(stats->ojs_hash);
-	stats->ojs_hash = NULL;
-	LASSERT(list_empty(&stats->ojs_list));
-}
-EXPORT_SYMBOL(lprocfs_job_stats_fini);
-
-static void *lprocfs_jobstats_seq_start(struct seq_file *p, loff_t *pos)
-{
-	struct obd_job_stats *stats = p->private;
-	loff_t off = *pos;
-	struct job_stat *job;
-
-	read_lock(&stats->ojs_lock);
-	if (off == 0)
-		return SEQ_START_TOKEN;
-	off--;
-	list_for_each_entry(job, &stats->ojs_list, js_list) {
-		if (!off--)
-			return job;
-	}
-	return NULL;
-}
-
-static void lprocfs_jobstats_seq_stop(struct seq_file *p, void *v)
-{
-	struct obd_job_stats *stats = p->private;
-
-	read_unlock(&stats->ojs_lock);
-}
-
-static void *lprocfs_jobstats_seq_next(struct seq_file *p, void *v, loff_t *pos)
-{
-	struct obd_job_stats *stats = p->private;
-	struct job_stat *job;
-	struct list_head *next;
-
-	++*pos;
-	if (v == SEQ_START_TOKEN) {
-		next = stats->ojs_list.next;
-	} else {
-		job = (struct job_stat *)v;
-		next = job->js_list.next;
-	}
-
-	return next == &stats->ojs_list ? NULL :
-		list_entry(next, struct job_stat, js_list);
-}
-
-/*
- * Example of output on MDT:
- *
- * job_stats:
- * - job_id:	test_id.222.25844
- *   snapshot_time: 1322494486
- *   open:	  { samples:	       3, unit: reqs }
- *   close:	 { samples:	       3, unit: reqs }
- *   mknod:	 { samples:	       0, unit: reqs }
- *   link:	  { samples:	       0, unit: reqs }
- *   unlink:	{ samples:	       0, unit: reqs }
- *   mkdir:	 { samples:	       0, unit: reqs }
- *   rmdir:	 { samples:	       0, unit: reqs }
- *   rename:	{ samples:	       1, unit: reqs }
- *   getattr:       { samples:	       7, unit: reqs }
- *   setattr:       { samples:	       0, unit: reqs }
- *   getxattr:      { samples:	       0, unit: reqs }
- *   setxattr:      { samples:	       0, unit: reqs }
- *   statfs:	{ samples:	       0, unit: reqs }
- *   sync:	  { samples:	       0, unit: reqs }
- *
- * Example of output on OST:
- *
- * job_stats:
- * - job_id	 4854
- *   snapshot_time: 1322494602
- *   read:	  { samples:  0, unit: bytes, min:  0, max:  0, sum:  0 }
- *   write:	 { samples:  1, unit: bytes, min: 10, max: 10, sum: 10 }
- *   setattr:       { samples:  0, unit: reqs }
- *   punch:	 { samples:  0, unit: reqs }
- *   sync:	  { samples:  0, unit: reqs }
- */
-
-static const char spaces[] = "		    ";
-
-static int inline width(const char *str, int len)
-{
-	return len - min((int)strlen(str), 15);
-}
-
-static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v)
-{
-	struct job_stat			*job = v;
-	struct lprocfs_stats		*s;
-	struct lprocfs_counter		ret;
-	struct lprocfs_counter		*cntr;
-	struct lprocfs_counter_header	*cntr_header;
-	int				i;
-
-	if (v == SEQ_START_TOKEN) {
-		seq_printf(p, "job_stats:\n");
-		return 0;
-	}
-
-	seq_printf(p, "- %-16s %s\n", "job_id:", job->js_jobid);
-	seq_printf(p, "  %-16s %ld\n", "snapshot_time:", job->js_timestamp);
-
-	s = job->js_stats;
-	for (i = 0; i < s->ls_num; i++) {
-		cntr = lprocfs_stats_counter_get(s, 0, i);
-		cntr_header = &s->ls_cnt_header[i];
-		lprocfs_stats_collect(s, i, &ret);
-
-		seq_printf(p, "  %s:%.*s { samples: %11"LPF64"u",
-			   cntr_header->lc_name,
-			   width(cntr_header->lc_name, 15), spaces,
-			   ret.lc_count);
-		if (cntr_header->lc_units[0] != '\0')
-			seq_printf(p, ", unit: %5s", cntr_header->lc_units);
-
-		if (cntr_header->lc_config & LPROCFS_CNTR_AVGMINMAX) {
-			seq_printf(p, ", min:%8"LPF64"u, max:%8"LPF64"u,"
-				   " sum:%16"LPF64"u",
-				   ret.lc_count ? ret.lc_min : 0,
-				   ret.lc_count ? ret.lc_max : 0,
-				   ret.lc_count ? ret.lc_sum : 0);
-		}
-		if (cntr_header->lc_config & LPROCFS_CNTR_STDDEV) {
-			seq_printf(p, ", sumsq: %18"LPF64"u",
-				   ret.lc_count ? ret.lc_sumsquare : 0);
-		}
-
-		seq_printf(p, " }\n");
-
-	}
-	return 0;
-}
-
-struct seq_operations lprocfs_jobstats_seq_sops = {
-	start: lprocfs_jobstats_seq_start,
-	stop:  lprocfs_jobstats_seq_stop,
-	next:  lprocfs_jobstats_seq_next,
-	show:  lprocfs_jobstats_seq_show,
-};
-
-static int lprocfs_jobstats_seq_open(struct inode *inode, struct file *file)
-{
-	struct seq_file *seq;
-	int rc;
-
-	rc = seq_open(file, &lprocfs_jobstats_seq_sops);
-	if (rc)
-		return rc;
-	seq = file->private_data;
-	seq->private = PDE_DATA(inode);
-	return 0;
-}
-
-static ssize_t lprocfs_jobstats_seq_write(struct file *file, const char *buf,
-					  size_t len, loff_t *off)
-{
-	struct seq_file *seq = file->private_data;
-	struct obd_job_stats *stats = seq->private;
-	char jobid[JOBSTATS_JOBID_SIZE];
-	int all = 0;
-	struct job_stat *job;
-
-	if (!memcmp(buf, "clear", strlen("clear"))) {
-		all = 1;
-	} else if (len < JOBSTATS_JOBID_SIZE) {
-		memset(jobid, 0, JOBSTATS_JOBID_SIZE);
-		/* Trim '\n' if any */
-		if (buf[len - 1] == '\n')
-			memcpy(jobid, buf, len - 1);
-		else
-			memcpy(jobid, buf, len);
-	} else {
-		return -EINVAL;
-	}
-
-	LASSERT(stats->ojs_hash);
-	if (all) {
-		time_t oldest = 0;
-		cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback,
-				       &oldest);
-		return len;
-	}
-
-	if (!strlen(jobid))
-		return -EINVAL;
-
-	job = cfs_hash_lookup(stats->ojs_hash, jobid);
-	if (!job)
-		return -EINVAL;
-
-	cfs_hash_del_key(stats->ojs_hash, jobid);
-
-	job_putref(job);
-	return len;
-}
-
-struct file_operations lprocfs_jobstats_seq_fops = {
-	.owner   = THIS_MODULE,
-	.open    = lprocfs_jobstats_seq_open,
-	.read    = seq_read,
-	.write   = lprocfs_jobstats_seq_write,
-	.llseek  = seq_lseek,
-	.release = lprocfs_seq_release,
-};
-
-int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num,
-			   cntr_init_callback init_fn)
-{
-	struct proc_dir_entry *entry;
-	struct obd_job_stats *stats;
-	ENTRY;
-
-	LASSERT(obd->obd_proc_entry != NULL);
-	LASSERT(obd->obd_type->typ_name);
-
-	if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) &&
-	    strcmp(obd->obd_type->typ_name, LUSTRE_OST_NAME)) {
-		CERROR("Invalid obd device type.\n");
-		RETURN(-EINVAL);
-	}
-	stats = &obd->u.obt.obt_jobstats;
-
-	LASSERT(stats->ojs_hash == NULL);
-	stats->ojs_hash = cfs_hash_create("JOB_STATS",
-					  HASH_JOB_STATS_CUR_BITS,
-					  HASH_JOB_STATS_MAX_BITS,
-					  HASH_JOB_STATS_BKT_BITS, 0,
-					  CFS_HASH_MIN_THETA,
-					  CFS_HASH_MAX_THETA,
-					  &job_stats_hash_ops,
-					  CFS_HASH_DEFAULT);
-	if (stats->ojs_hash == NULL)
-		RETURN(-ENOMEM);
-
-	INIT_LIST_HEAD(&stats->ojs_list);
-	rwlock_init(&stats->ojs_lock);
-	stats->ojs_cntr_num = cntr_num;
-	stats->ojs_cntr_init_fn = init_fn;
-	stats->ojs_cleanup_interval = 600; /* 10 mins by default */
-	stats->ojs_last_cleanup = cfs_time_current_sec();
-
-	entry = proc_create_data("job_stats", 0644, obd->obd_proc_entry,
-				 &lprocfs_jobstats_seq_fops, stats);
-	if (entry)
-		RETURN(0);
-	else
-		RETURN(-ENOMEM);
-}
-EXPORT_SYMBOL(lprocfs_job_stats_init);
-
-int lprocfs_rd_job_interval(struct seq_file *m, void *data)
-{
-	struct obd_device *obd = (struct obd_device *)data;
-	struct obd_job_stats *stats;
-
-	LASSERT(obd != NULL);
-	stats = &obd->u.obt.obt_jobstats;
-	return seq_printf(m, "%d\n", stats->ojs_cleanup_interval);
-}
-EXPORT_SYMBOL(lprocfs_rd_job_interval);
-
-int lprocfs_wr_job_interval(struct file *file, const char *buffer,
-			    unsigned long count, void *data)
-{
-	struct obd_device *obd = (struct obd_device *)data;
-	struct obd_job_stats *stats;
-	int val, rc;
-
-	LASSERT(obd != NULL);
-	stats = &obd->u.obt.obt_jobstats;
-
-	rc = lprocfs_write_helper(buffer, count, &val);
-	if (rc)
-		return rc;
-
-	stats->ojs_cleanup_interval = val;
-	lprocfs_job_cleanup(stats, true);
-
-	return count;
-
-}
-EXPORT_SYMBOL(lprocfs_wr_job_interval);
-
-#endif /* LPROCFS*/
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index f7af3d6..a95f60a 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -68,11 +68,11 @@ EXPORT_SYMBOL(lprocfs_seq_release);
 
 /* lprocfs API calls */
 
-proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
+struct proc_dir_entry *lprocfs_add_simple(struct proc_dir_entry *root,
 				     char *name, void *data,
 				     struct file_operations *fops)
 {
-	proc_dir_entry_t *proc;
+	struct proc_dir_entry *proc;
 	umode_t mode = 0;
 
 	if (root == NULL || name == NULL || fops == NULL)
@@ -179,17 +179,21 @@ struct proc_dir_entry *lprocfs_register(const char *name,
 					struct proc_dir_entry *parent,
 					struct lprocfs_vars *list, void *data)
 {
-	struct proc_dir_entry *newchild;
+	struct proc_dir_entry *entry;
+
+	entry = proc_mkdir(name, parent);
+	if (entry == NULL)
+		GOTO(out, entry = ERR_PTR(-ENOMEM));
 
-	newchild = proc_mkdir(name, parent);
-	if (newchild != NULL && list != NULL) {
-		int rc = lprocfs_add_vars(newchild, list, data);
-		if (rc) {
-			lprocfs_remove(&newchild);
-			return ERR_PTR(rc);
+	if (list != NULL) {
+		int rc = lprocfs_add_vars(entry, list, data);
+		if (rc != 0) {
+			lprocfs_remove(&entry);
+			entry = ERR_PTR(rc);
 		}
 	}
-	return newchild;
+out:
+	return entry;
 }
 EXPORT_SYMBOL(lprocfs_register);
 
@@ -896,7 +900,6 @@ void lprocfs_free_per_client_stats(struct obd_device *obd)
 {
 	cfs_hash_t *hash = obd->obd_nid_stats_hash;
 	struct nid_stat *stat;
-	ENTRY;
 
 	/* we need extra list - because hash_exit called to early */
 	/* not need locking because all clients is died */
@@ -907,7 +910,6 @@ void lprocfs_free_per_client_stats(struct obd_device *obd)
 		cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
 		lprocfs_free_client_stats(stat);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
 
@@ -1494,7 +1496,6 @@ EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
 {
 	struct nid_stat *stat = obj;
-	ENTRY;
 
 	CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
 	if (atomic_read(&stat->nid_exp_ref_count) == 1) {
@@ -1502,13 +1503,13 @@ static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
 		spin_lock(&stat->nid_obd->obd_nid_lock);
 		list_move(&stat->nid_list, data);
 		spin_unlock(&stat->nid_obd->obd_nid_lock);
-		RETURN(1);
+		return 1;
 	}
 	/* we has reference to object - only clear data*/
 	if (stat->nid_stats)
 		lprocfs_clear_stats(stat->nid_stats);
 
-	RETURN(0);
+	return 0;
 }
 
 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
@@ -1536,22 +1537,21 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 {
 	struct nid_stat *new_stat, *old_stat;
 	struct obd_device *obd = NULL;
-	proc_dir_entry_t *entry;
+	struct proc_dir_entry *entry;
 	char *buffer = NULL;
 	int rc = 0;
-	ENTRY;
 
 	*newnid = 0;
 
 	if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
 	    !exp->exp_obd->obd_nid_stats_hash)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* not test against zero because eric say:
 	 * You may only test nid against another nid, or LNET_NID_ANY.
 	 * Anything else is nonsense.*/
 	if (!nid || *nid == LNET_NID_ANY)
-		RETURN(0);
+		return 0;
 
 	obd = exp->exp_obd;
 
@@ -1559,7 +1559,7 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 
 	OBD_ALLOC_PTR(new_stat);
 	if (new_stat == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	new_stat->nid	       = *nid;
 	new_stat->nid_obd	   = exp->exp_obd;
@@ -1596,10 +1596,12 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 					      NULL, NULL);
 	OBD_FREE(buffer, LNET_NIDSTR_SIZE);
 
-	if (new_stat->nid_proc == NULL) {
+	if (IS_ERR(new_stat->nid_proc)) {
 		CERROR("Error making export directory for nid %s\n",
 		       libcfs_nid2str(*nid));
-		GOTO(destroy_new_ns, rc = -ENOMEM);
+		rc = PTR_ERR(new_stat->nid_proc);
+		new_stat->nid_proc = NULL;
+		GOTO(destroy_new_ns, rc);
 	}
 
 	entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
@@ -1625,7 +1627,7 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 	list_add(&new_stat->nid_list, &obd->obd_nid_stats);
 	spin_unlock(&obd->obd_nid_lock);
 
-	RETURN(rc);
+	return rc;
 
 destroy_new_ns:
 	if (new_stat->nid_proc != NULL)
@@ -1635,7 +1637,7 @@ destroy_new_ns:
 destroy_new:
 	nidstat_putref(new_stat);
 	OBD_FREE_PTR(new_stat);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(lprocfs_exp_setup);
 
@@ -1644,7 +1646,7 @@ int lprocfs_exp_cleanup(struct obd_export *exp)
 	struct nid_stat *stat = exp->exp_nid_stats;
 
 	if(!stat || !exp->exp_obd)
-		RETURN(0);
+		return 0;
 
 	nidstat_putref(exp->exp_nid_stats);
 	exp->exp_nid_stats = NULL;
@@ -1873,7 +1875,7 @@ static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
  * If \a name is not found the original \a buffer is returned.
  */
 char *lprocfs_find_named_value(const char *buffer, const char *name,
-				unsigned long *count)
+			       size_t *count)
 {
 	char *val;
 	size_t buflen = *count;
@@ -1897,23 +1899,22 @@ char *lprocfs_find_named_value(const char *buffer, const char *name,
 }
 EXPORT_SYMBOL(lprocfs_find_named_value);
 
-int lprocfs_seq_create(proc_dir_entry_t *parent,
+int lprocfs_seq_create(struct proc_dir_entry *parent,
 		       const char *name,
 		       umode_t mode,
 		       const struct file_operations *seq_fops,
 		       void *data)
 {
 	struct proc_dir_entry *entry;
-	ENTRY;
 
 	/* Disallow secretly (un)writable entries. */
 	LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
 	entry = proc_create_data(name, mode, parent, seq_fops, data);
 
 	if (entry == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(lprocfs_seq_create);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
index fdf0ed3..3a3d5bc 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
@@ -202,7 +202,6 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env,
 	struct list_head *layers;
 	int clean;
 	int result;
-	ENTRY;
 
 	/*
 	 * Create top-level object slice. This will also create
@@ -210,9 +209,9 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env,
 	 */
 	top = dev->ld_ops->ldo_object_alloc(env, NULL, dev);
 	if (top == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 	if (IS_ERR(top))
-		RETURN(top);
+		return top;
 	/*
 	 * This is the only place where object fid is assigned. It's constant
 	 * after this point.
@@ -233,7 +232,7 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env,
 			result = scan->lo_ops->loo_object_init(env, scan, conf);
 			if (result != 0) {
 				lu_object_free(env, top);
-				RETURN(ERR_PTR(result));
+				return ERR_PTR(result);
 			}
 			scan->lo_flags |= LU_OBJECT_ALLOCATED;
 		}
@@ -244,13 +243,13 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env,
 			result = scan->lo_ops->loo_object_start(env, scan);
 			if (result != 0) {
 				lu_object_free(env, top);
-				RETURN(ERR_PTR(result));
+				return ERR_PTR(result);
 			}
 		}
 	}
 
 	lprocfs_counter_incr(dev->ld_site->ls_stats, LU_SS_CREATED);
-	RETURN(top);
+	return top;
 }
 
 /**
@@ -317,7 +316,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr)
 	int		      i;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_OBD_NO_LRU))
-		RETURN(0);
+		return 0;
 
 	INIT_LIST_HEAD(&dispose);
 	/*
@@ -538,7 +537,7 @@ static struct lu_object *htable_lookup(struct lu_site *s,
 	__u64  ver = cfs_hash_bd_version_get(bd);
 
 	if (*version == ver)
-		return NULL;
+		return ERR_PTR(-ENOENT);
 
 	*version = ver;
 	bkt = cfs_hash_bd_extra_get(s->ls_obj_hash, bd);
@@ -547,7 +546,7 @@ static struct lu_object *htable_lookup(struct lu_site *s,
 	hnode = cfs_hash_bd_peek_locked(s->ls_obj_hash, bd, (void *)f);
 	if (hnode == NULL) {
 		lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_MISS);
-		return NULL;
+		return ERR_PTR(-ENOENT);
 	}
 
 	h = container_of0(hnode, struct lu_object_header, loh_hash);
@@ -651,7 +650,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
 	cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1);
 	o = htable_lookup(s, &bd, f, waiter, &version);
 	cfs_hash_bd_unlock(hs, &bd, 1);
-	if (o != NULL)
+	if (!IS_ERR(o) || PTR_ERR(o) != -ENOENT)
 		return o;
 
 	/*
@@ -667,7 +666,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
 	cfs_hash_bd_lock(hs, &bd, 1);
 
 	shadow = htable_lookup(s, &bd, f, waiter, &version);
-	if (likely(shadow == NULL)) {
+	if (likely(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT)) {
 		struct lu_site_bkt_data *bkt;
 
 		bkt = cfs_hash_bd_extra_get(hs, &bd);
@@ -849,7 +848,7 @@ static int lu_htable_order(void)
 	 *
 	 * Size of lu_object is (arbitrary) taken as 1K (together with inode).
 	 */
-	cache_size = num_physpages;
+	cache_size = totalram_pages;
 
 #if BITS_PER_LONG == 32
 	/* limit hashtable size for lowmem systems to low RAM */
@@ -980,7 +979,6 @@ int lu_site_init(struct lu_site *s, struct lu_device *top)
 	char name[16];
 	int bits;
 	int i;
-	ENTRY;
 
 	memset(s, 0, sizeof *s);
 	bits = lu_htable_order();
@@ -1041,7 +1039,7 @@ int lu_site_init(struct lu_site *s, struct lu_device *top)
 
 	lu_dev_add_linkage(s, top);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(lu_site_init);
 
@@ -1147,15 +1145,16 @@ EXPORT_SYMBOL(lu_device_fini);
  * Initialize object \a o that is part of compound object \a h and was created
  * by device \a d.
  */
-int lu_object_init(struct lu_object *o,
-		   struct lu_object_header *h, struct lu_device *d)
+int lu_object_init(struct lu_object *o, struct lu_object_header *h,
+		   struct lu_device *d)
 {
-	memset(o, 0, sizeof *o);
+	memset(o, 0, sizeof(*o));
 	o->lo_header = h;
-	o->lo_dev    = d;
+	o->lo_dev = d;
 	lu_device_get(d);
-	o->lo_dev_ref = lu_ref_add(&d->ld_reference, "lu_object", o);
+	lu_ref_add_at(&d->ld_reference, &o->lo_dev_ref, "lu_object", o);
 	INIT_LIST_HEAD(&o->lo_linkage);
+
 	return 0;
 }
 EXPORT_SYMBOL(lu_object_init);
@@ -1170,8 +1169,8 @@ void lu_object_fini(struct lu_object *o)
 	LASSERT(list_empty(&o->lo_linkage));
 
 	if (dev != NULL) {
-		lu_ref_del_at(&dev->ld_reference,
-			      o->lo_dev_ref , "lu_object", o);
+		lu_ref_del_at(&dev->ld_reference, &o->lo_dev_ref,
+			      "lu_object", o);
 		lu_device_put(dev);
 		o->lo_dev = NULL;
 	}
@@ -1315,7 +1314,6 @@ int lu_context_key_register(struct lu_context_key *key)
 	LASSERT(key->lct_init != NULL);
 	LASSERT(key->lct_fini != NULL);
 	LASSERT(key->lct_tags != 0);
-	LASSERT(key->lct_owner != NULL);
 
 	result = -ENFILE;
 	spin_lock(&lu_keys_guard);
@@ -1349,7 +1347,6 @@ static void key_fini(struct lu_context *ctx, int index)
 		lu_ref_del(&key->lct_reference, "ctx", ctx);
 		atomic_dec(&key->lct_used);
 
-		LASSERT(key->lct_owner != NULL);
 		if ((ctx->lc_tags & LCT_NOREF) == 0) {
 #ifdef CONFIG_MODULE_UNLOAD
 			LINVRNT(module_refcount(key->lct_owner) > 0);
@@ -1557,7 +1554,6 @@ static int keys_fill(struct lu_context *ctx)
 			if (unlikely(IS_ERR(value)))
 				return PTR_ERR(value);
 
-			LASSERT(key->lct_owner != NULL);
 			if (!(ctx->lc_tags & LCT_NOREF))
 				try_module_get(key->lct_owner);
 			lu_ref_add_atomic(&key->lct_reference, "ctx", ctx);
@@ -1783,7 +1779,6 @@ int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags,
 }
 EXPORT_SYMBOL(lu_env_refill_by_tags);
 
-static struct shrinker *lu_site_shrinker = NULL;
 
 typedef struct lu_site_stats{
 	unsigned	lss_populated;
@@ -1839,61 +1834,68 @@ static void lu_site_stats_get(cfs_hash_t *hs,
  * objects without taking the  lu_sites_guard lock, but this is not
  * possible in the current implementation.
  */
-static int lu_cache_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
+static unsigned long lu_cache_shrink_count(struct shrinker *sk,
+					   struct shrink_control *sc)
 {
 	lu_site_stats_t stats;
 	struct lu_site *s;
 	struct lu_site *tmp;
-	int cached = 0;
-	int remain = shrink_param(sc, nr_to_scan);
-	LIST_HEAD(splice);
-
-	if (!(shrink_param(sc, gfp_mask) & __GFP_FS)) {
-		if (remain != 0)
-			return -1;
-		else
-			/* We must not take the lu_sites_guard lock when
-			 * __GFP_FS is *not* set because of the deadlock
-			 * possibility detailed above. Additionally,
-			 * since we cannot determine the number of
-			 * objects in the cache without taking this
-			 * lock, we're in a particularly tough spot. As
-			 * a result, we'll just lie and say our cache is
-			 * empty. This _should_ be ok, as we can't
-			 * reclaim objects when __GFP_FS is *not* set
-			 * anyways.
-			 */
-			return 0;
-	}
+	unsigned long cached = 0;
 
-	CDEBUG(D_INODE, "Shrink %d objects\n", remain);
+	if (!(sc->gfp_mask & __GFP_FS))
+		return 0;
 
 	mutex_lock(&lu_sites_guard);
 	list_for_each_entry_safe(s, tmp, &lu_sites, ls_linkage) {
-		if (shrink_param(sc, nr_to_scan) != 0) {
-			remain = lu_site_purge(&lu_shrink_env, s, remain);
-			/*
-			 * Move just shrunk site to the tail of site list to
-			 * assure shrinking fairness.
-			 */
-			list_move_tail(&s->ls_linkage, &splice);
-		}
-
 		memset(&stats, 0, sizeof(stats));
 		lu_site_stats_get(s->ls_obj_hash, &stats, 0);
 		cached += stats.lss_total - stats.lss_busy;
-		if (shrink_param(sc, nr_to_scan) && remain <= 0)
-			break;
 	}
-	list_splice(&splice, lu_sites.prev);
 	mutex_unlock(&lu_sites_guard);
 
 	cached = (cached / 100) * sysctl_vfs_cache_pressure;
-	if (shrink_param(sc, nr_to_scan) == 0)
-		CDEBUG(D_INODE, "%d objects cached\n", cached);
+	CDEBUG(D_INODE, "%ld objects cached\n", cached);
 	return cached;
 }
 
+static unsigned long lu_cache_shrink_scan(struct shrinker *sk,
+					  struct shrink_control *sc)
+{
+	struct lu_site *s;
+	struct lu_site *tmp;
+	unsigned long remain = sc->nr_to_scan, freed = 0;
+	LIST_HEAD(splice);
+
+	if (!(sc->gfp_mask & __GFP_FS))
+		/* We must not take the lu_sites_guard lock when
+		 * __GFP_FS is *not* set because of the deadlock
+		 * possibility detailed above. Additionally,
+		 * since we cannot determine the number of
+		 * objects in the cache without taking this
+		 * lock, we're in a particularly tough spot. As
+		 * a result, we'll just lie and say our cache is
+		 * empty. This _should_ be ok, as we can't
+		 * reclaim objects when __GFP_FS is *not* set
+		 * anyways.
+		 */
+		return SHRINK_STOP;
+
+	mutex_lock(&lu_sites_guard);
+	list_for_each_entry_safe(s, tmp, &lu_sites, ls_linkage) {
+		freed = lu_site_purge(&lu_shrink_env, s, remain);
+		remain -= freed;
+		/*
+		 * Move just shrunk site to the tail of site list to
+		 * assure shrinking fairness.
+		 */
+		list_move_tail(&s->ls_linkage, &splice);
+	}
+	list_splice(&splice, lu_sites.prev);
+	mutex_unlock(&lu_sites_guard);
+
+	return sc->nr_to_scan - remain;
+}
+
 /*
  * Debugging stuff.
  */
@@ -1917,6 +1919,12 @@ int lu_printk_printer(const struct lu_env *env,
 	return 0;
 }
 
+static struct shrinker lu_site_shrinker = {
+	.count_objects	= lu_cache_shrink_count,
+	.scan_objects	= lu_cache_shrink_scan,
+	.seeks 		= DEFAULT_SEEKS,
+};
+
 /**
  * Initialization of global lu_* data.
  */
@@ -1951,9 +1959,7 @@ int lu_global_init(void)
 	 * inode, one for ea. Unfortunately setting this high value results in
 	 * lu_object/inode cache consuming all the memory.
 	 */
-	lu_site_shrinker = set_shrinker(DEFAULT_SEEKS, lu_cache_shrink);
-	if (lu_site_shrinker == NULL)
-		return -ENOMEM;
+	register_shrinker(&lu_site_shrinker);
 
 	return result;
 }
@@ -1963,11 +1969,7 @@ int lu_global_init(void)
  */
 void lu_global_fini(void)
 {
-	if (lu_site_shrinker != NULL) {
-		remove_shrinker(lu_site_shrinker);
-		lu_site_shrinker = NULL;
-	}
-
+	unregister_shrinker(&lu_site_shrinker);
 	lu_context_key_degister(&lu_global_key);
 
 	/*
@@ -2079,7 +2081,7 @@ void lu_object_assign_fid(const struct lu_env *env, struct lu_object *o,
 	cfs_hash_bd_get_and_lock(hs, (void *)fid, &bd, 1);
 	shadow = htable_lookup(s, &bd, fid, &waiter, &version);
 	/* supposed to be unique */
-	LASSERT(shadow == NULL);
+	LASSERT(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT);
 	*old = *fid;
 	bkt = cfs_hash_bd_extra_get(hs, &bd);
 	cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash);
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_ucred.c b/drivers/staging/lustre/lustre/obdclass/lu_ucred.c
index 229db6c..e23e545 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_ucred.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_ucred.c
@@ -33,13 +33,13 @@
  * This file is part of Lustre, http://www.lustre.org/
  * Lustre is a trademark of Sun Microsystems, Inc.
  *
- * lustre/obdclass/lu_object.c
+ * lustre/obdclass/lu_ucred.c
  *
- * Lustre Object.
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
+ * Lustre user credentials context infrastructure.
  *
  *   Author: Nikita Danilov <nikita.danilov@sun.com>
+ *   Author: Fan Yong <fan.yong@intel.com>
+ *   Author: Vitaly Fertman <vitaly_fertman@xyratex.com>
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c
index 69d6499..be31d32 100644
--- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c
+++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c
@@ -65,7 +65,6 @@ void class_handle_hash(struct portals_handle *h,
 		       struct portals_handle_ops *ops)
 {
 	struct handle_bucket *bucket;
-	ENTRY;
 
 	LASSERT(h != NULL);
 	LASSERT(list_empty(&h->h_link));
@@ -100,7 +99,6 @@ void class_handle_hash(struct portals_handle *h,
 
 	CDEBUG(D_INFO, "added object %p with handle "LPX64" to hash\n",
 	       h, h->h_cookie);
-	EXIT;
 }
 EXPORT_SYMBOL(class_handle_hash);
 
@@ -139,7 +137,6 @@ EXPORT_SYMBOL(class_handle_unhash);
 void class_handle_hash_back(struct portals_handle *h)
 {
 	struct handle_bucket *bucket;
-	ENTRY;
 
 	bucket = handle_hash + (h->h_cookie & HANDLE_HASH_MASK);
 
@@ -147,8 +144,6 @@ void class_handle_hash_back(struct portals_handle *h)
 	list_add_rcu(&h->h_link, &bucket->head);
 	h->h_in = 1;
 	spin_unlock(&bucket->lock);
-
-	EXIT;
 }
 EXPORT_SYMBOL(class_handle_hash_back);
 
@@ -157,7 +152,6 @@ void *class_handle2object(__u64 cookie)
 	struct handle_bucket *bucket;
 	struct portals_handle *h;
 	void *retval = NULL;
-	ENTRY;
 
 	LASSERT(handle_hash != NULL);
 
@@ -180,7 +174,7 @@ void *class_handle2object(__u64 cookie)
 	}
 	rcu_read_unlock();
 
-	RETURN(retval);
+	return retval;
 }
 EXPORT_SYMBOL(class_handle2object);
 
diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
index 2fa2589..df4936a 100644
--- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
+++ b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
@@ -191,7 +191,6 @@ int class_check_uuid(struct obd_uuid *uuid, __u64 nid)
 {
 	struct uuid_nid_data *entry;
 	int found = 0;
-	ENTRY;
 
 	CDEBUG(D_INFO, "check if uuid %s has %s.\n",
 	       obd_uuid2str(uuid), libcfs_nid2str(nid));
@@ -213,6 +212,6 @@ int class_check_uuid(struct obd_uuid *uuid, __u64 nid)
 		break;
 	}
 	spin_unlock(&g_uuid_lock);
-	RETURN(found);
+	return found;
 }
 EXPORT_SYMBOL(class_check_uuid);
diff --git a/drivers/staging/lustre/lustre/obdclass/md_attrs.c b/drivers/staging/lustre/lustre/obdclass/md_attrs.c
index b71344a..f718782 100644
--- a/drivers/staging/lustre/lustre/obdclass/md_attrs.c
+++ b/drivers/staging/lustre/lustre/obdclass/md_attrs.c
@@ -99,19 +99,18 @@ EXPORT_SYMBOL(lustre_som_swab);
 int lustre_buf2som(void *buf, int rc, struct md_som_data *msd)
 {
 	struct som_attrs *attrs = (struct som_attrs *)buf;
-	ENTRY;
 
 	if (rc == 0 ||  rc == -ENODATA)
 		/* no SOM attributes */
-		RETURN(-ENODATA);
+		return -ENODATA;
 
 	if (rc < 0)
 		/* error hit while fetching xattr */
-		RETURN(rc);
+		return rc;
 
 	/* check SOM compatibility */
 	if (attrs->som_incompat & ~cpu_to_le32(SOM_INCOMPAT_SUPP))
-		RETURN(-ENODATA);
+		return -ENODATA;
 
 	/* unpack SOM attributes */
 	lustre_som_swab(attrs);
@@ -124,7 +123,7 @@ int lustre_buf2som(void *buf, int rc, struct md_som_data *msd)
 	msd->msd_blocks   = attrs->som_blocks;
 	msd->msd_mountid  = attrs->som_mountid;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(lustre_buf2som);
 
@@ -156,15 +155,14 @@ EXPORT_SYMBOL(lustre_hsm_swab);
 int lustre_buf2hsm(void *buf, int rc, struct md_hsm *mh)
 {
 	struct hsm_attrs *attrs = (struct hsm_attrs *)buf;
-	ENTRY;
 
 	if (rc == 0 ||  rc == -ENODATA)
 		/* no HSM attributes */
-		RETURN(-ENODATA);
+		return -ENODATA;
 
 	if (rc < 0)
 		/* error hit while fetching xattr */
-		RETURN(rc);
+		return rc;
 
 	/* unpack HSM attributes */
 	lustre_hsm_swab(attrs);
@@ -175,7 +173,7 @@ int lustre_buf2hsm(void *buf, int rc, struct md_hsm *mh)
 	mh->mh_arch_id  = attrs->hsm_arch_id;
 	mh->mh_arch_ver = attrs->hsm_arch_ver;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(lustre_buf2hsm);
 
@@ -188,7 +186,6 @@ EXPORT_SYMBOL(lustre_buf2hsm);
 void lustre_hsm2buf(void *buf, struct md_hsm *mh)
 {
 	struct hsm_attrs *attrs = (struct hsm_attrs *)buf;
-	ENTRY;
 
 	/* copy HSM attributes */
 	attrs->hsm_compat   = mh->mh_compat;
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
index bbf06d0..d0a64ff 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
@@ -93,7 +93,7 @@ struct cfg_interop_param *class_find_old_param(const char *param,
 	int   name_len = 0;
 
 	if (param == NULL || ptr == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	value = strchr(param, '=');
 	if (value == NULL)
@@ -104,11 +104,11 @@ struct cfg_interop_param *class_find_old_param(const char *param,
 	while (ptr->old_param != NULL) {
 		if (strncmp(param, ptr->old_param, name_len) == 0 &&
 		    name_len == strlen(ptr->old_param))
-			RETURN(ptr);
+			return ptr;
 		ptr++;
 	}
 
-	RETURN(NULL);
+	return NULL;
 }
 EXPORT_SYMBOL(class_find_old_param);
 
@@ -335,23 +335,22 @@ int class_attach(struct lustre_cfg *lcfg)
 	struct obd_device *obd = NULL;
 	char *typename, *name, *uuid;
 	int rc, len;
-	ENTRY;
 
 	if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
 		CERROR("No type passed!\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	typename = lustre_cfg_string(lcfg, 1);
 
 	if (!LUSTRE_CFG_BUFLEN(lcfg, 0)) {
 		CERROR("No name passed!\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	name = lustre_cfg_string(lcfg, 0);
 
 	if (!LUSTRE_CFG_BUFLEN(lcfg, 2)) {
 		CERROR("No UUID passed!\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	uuid = lustre_cfg_string(lcfg, 2);
 
@@ -433,7 +432,7 @@ int class_attach(struct lustre_cfg *lcfg)
 	obd->obd_attached = 1;
 	CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
 	       obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
-	RETURN(0);
+	return 0;
  out:
 	if (obd != NULL) {
 		class_release_dev(obd);
@@ -449,7 +448,6 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
 	int err = 0;
 	struct obd_export *exp;
-	ENTRY;
 
 	LASSERT(obd != NULL);
 	LASSERTF(obd == class_num2obd(obd->obd_minor),
@@ -462,13 +460,13 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	/* have we attached a type to this device? */
 	if (!obd->obd_attached) {
 		CERROR("Device %d not attached\n", obd->obd_minor);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	if (obd->obd_set_up) {
 		CERROR("Device %d already setup (type %s)\n",
 		       obd->obd_minor, obd->obd_type->typ_name);
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 
 	/* is someone else setting us up right now? (attach inits spinlock) */
@@ -477,7 +475,7 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 		spin_unlock(&obd->obd_dev_lock);
 		CERROR("Device %d setup in progress (type %s)\n",
 		       obd->obd_minor, obd->obd_type->typ_name);
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 	/* just leave this on forever.  I can't use obd_set_up here because
 	   other fns check that status, and we're not actually set up yet. */
@@ -542,7 +540,7 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
 	       obd->obd_name, obd->obd_uuid.uuid);
 
-	RETURN(0);
+	return 0;
 err_exp:
 	if (obd->obd_self_export) {
 		class_unlink_export(obd->obd_self_export);
@@ -572,18 +570,16 @@ EXPORT_SYMBOL(class_setup);
  */
 int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
-	ENTRY;
-
 	if (obd->obd_set_up) {
 		CERROR("OBD device %d still set up\n", obd->obd_minor);
-		RETURN(-EBUSY);
+		return -EBUSY;
 	}
 
 	spin_lock(&obd->obd_dev_lock);
 	if (!obd->obd_attached) {
 		spin_unlock(&obd->obd_dev_lock);
 		CERROR("OBD device %d not attached\n", obd->obd_minor);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 	obd->obd_attached = 0;
 	spin_unlock(&obd->obd_dev_lock);
@@ -592,7 +588,7 @@ int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
 	       obd->obd_name, obd->obd_uuid.uuid);
 
 	class_decref(obd, "attach", obd);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(class_detach);
 
@@ -604,20 +600,19 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
 	int err = 0;
 	char *flag;
-	ENTRY;
 
 	OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
 
 	if (!obd->obd_set_up) {
 		CERROR("Device %d not setup\n", obd->obd_minor);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	spin_lock(&obd->obd_dev_lock);
 	if (obd->obd_stopping) {
 		spin_unlock(&obd->obd_dev_lock);
 		CERROR("OBD %d already stopping\n", obd->obd_minor);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 	/* Leave this on forever */
 	obd->obd_stopping = 1;
@@ -696,7 +691,7 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	class_decref(obd, "setup", obd);
 	obd->obd_set_up = 0;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(class_cleanup);
 
@@ -767,12 +762,11 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
 	struct obd_import *imp;
 	struct obd_uuid uuid;
 	int rc;
-	ENTRY;
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
 	    LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
 		CERROR("invalid conn_uuid\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
 	    strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
@@ -780,19 +774,19 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
 	    strcmp(obd->obd_type->typ_name, LUSTRE_LWP_NAME) &&
 	    strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
 		CERROR("can't add connection on non-client dev\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	imp = obd->u.cli.cl_import;
 	if (!imp) {
 		CERROR("try to add conn on immature client dev\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
 	rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_add_conn);
 
@@ -803,29 +797,28 @@ int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
 	struct obd_import *imp;
 	struct obd_uuid uuid;
 	int rc;
-	ENTRY;
 
 	if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
 	    LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
 		CERROR("invalid conn_uuid\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
 	    strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
 		CERROR("can't del connection on non-client dev\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	imp = obd->u.cli.cl_import;
 	if (!imp) {
 		CERROR("try to del conn on immature client dev\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
 	rc = obd_del_conn(imp, &uuid);
 
-	RETURN(rc);
+	return rc;
 }
 
 LIST_HEAD(lustre_profile_list);
@@ -834,13 +827,12 @@ struct lustre_profile *class_get_profile(const char * prof)
 {
 	struct lustre_profile *lprof;
 
-	ENTRY;
 	list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
 		if (!strcmp(lprof->lp_profile, prof)) {
-			RETURN(lprof);
+			return lprof;
 		}
 	}
-	RETURN(NULL);
+	return NULL;
 }
 EXPORT_SYMBOL(class_get_profile);
 
@@ -853,13 +845,12 @@ int class_add_profile(int proflen, char *prof, int osclen, char *osc,
 {
 	struct lustre_profile *lprof;
 	int err = 0;
-	ENTRY;
 
 	CDEBUG(D_CONFIG, "Add profile %s\n", prof);
 
 	OBD_ALLOC(lprof, sizeof(*lprof));
 	if (lprof == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	INIT_LIST_HEAD(&lprof->lp_list);
 
 	LASSERT(proflen == (strlen(prof) + 1));
@@ -883,7 +874,7 @@ int class_add_profile(int proflen, char *prof, int osclen, char *osc,
 	}
 
 	list_add(&lprof->lp_list, &lustre_profile_list);
-	RETURN(err);
+	return err;
 
 out:
 	if (lprof->lp_md)
@@ -893,13 +884,12 @@ out:
 	if (lprof->lp_profile)
 		OBD_FREE(lprof->lp_profile, proflen);
 	OBD_FREE(lprof, sizeof(*lprof));
-	RETURN(err);
+	return err;
 }
 
 void class_del_profile(const char *prof)
 {
 	struct lustre_profile *lprof;
-	ENTRY;
 
 	CDEBUG(D_CONFIG, "Del profile %s\n", prof);
 
@@ -912,7 +902,6 @@ void class_del_profile(const char *prof)
 			OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
 		OBD_FREE(lprof, sizeof *lprof);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(class_del_profile);
 
@@ -920,7 +909,6 @@ EXPORT_SYMBOL(class_del_profile);
 void class_del_profiles(void)
 {
 	struct lustre_profile *lprof, *n;
-	ENTRY;
 
 	list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
 		list_del(&lprof->lp_list);
@@ -930,13 +918,11 @@ void class_del_profiles(void)
 			OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
 		OBD_FREE(lprof, sizeof *lprof);
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(class_del_profiles);
 
 static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
 {
-	ENTRY;
 	if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
 		at_min = val;
 	else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
@@ -951,10 +937,10 @@ static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
 		strlcpy(obd_jobid_var, lustre_cfg_string(lcfg, 2),
 			JOBSTATS_JOBID_VAR_MAX_LEN + 1);
 	else
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
-	RETURN(0);
+	return 0;
 }
 
 
@@ -991,14 +977,13 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
 	char			*value = NULL;
 	int			 name_len = 0;
 	int			 new_len = 0;
-	ENTRY;
 
 	if (cfg == NULL || new_name == NULL)
-		RETURN(ERR_PTR(-EINVAL));
+		return ERR_PTR(-EINVAL);
 
 	param = lustre_cfg_string(cfg, 1);
 	if (param == NULL)
-		RETURN(ERR_PTR(-EINVAL));
+		return ERR_PTR(-EINVAL);
 
 	value = strchr(param, '=');
 	if (value == NULL)
@@ -1010,7 +995,7 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
 
 	OBD_ALLOC(new_param, new_len);
 	if (new_param == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	strcpy(new_param, new_name);
 	if (value != NULL)
@@ -1019,7 +1004,7 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
 	OBD_ALLOC_PTR(bufs);
 	if (bufs == NULL) {
 		OBD_FREE(new_param, new_len);
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 	}
 
 	lustre_cfg_bufs_reset(bufs, NULL);
@@ -1031,14 +1016,14 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
 	OBD_FREE(new_param, new_len);
 	OBD_FREE_PTR(bufs);
 	if (new_cfg == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	new_cfg->lcfg_num = cfg->lcfg_num;
 	new_cfg->lcfg_flags = cfg->lcfg_flags;
 	new_cfg->lcfg_nid = cfg->lcfg_nid;
 	new_cfg->lcfg_nal = cfg->lcfg_nal;
 
-	RETURN(new_cfg);
+	return new_cfg;
 }
 EXPORT_SYMBOL(lustre_cfg_rename);
 
@@ -1244,11 +1229,10 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
 	int matched = 0, j = 0;
 	int rc = 0;
 	int skip = 0;
-	ENTRY;
 
 	if (lcfg->lcfg_command != LCFG_PARAM) {
 		CERROR("Unknown command: %d\n", lcfg->lcfg_command);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* fake a seq file so that var->fops->write can work... */
@@ -1295,7 +1279,7 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
 			/* If the prefix doesn't match, return error so we
 			   can pass it down the stack */
 			if (strnchr(key, keylen, '.'))
-			    RETURN(-ENOSYS);
+			    return -ENOSYS;
 			CERROR("%s: unknown param %s\n",
 			       (char *)lustre_cfg_string(lcfg, 0), key);
 			/* rc = -EINVAL;	continue parsing other params */
@@ -1316,7 +1300,7 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
 		rc = 0;
 	if (!rc && skip)
 		rc = skip;
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_process_proc_param);
 
@@ -1335,7 +1319,6 @@ int class_config_llog_handler(const struct lu_env *env,
 	int cfg_len = rec->lrh_len;
 	char *cfg_buf = (char*) (rec + 1);
 	int rc = 0;
-	ENTRY;
 
 	//class_config_dump_handler(handle, rec, data);
 
@@ -1426,10 +1409,13 @@ int class_config_llog_handler(const struct lu_env *env,
 		}
 
 
-		if ((clli->cfg_flags & CFG_F_EXCLUDE) &&
-		    (lcfg->lcfg_command == LCFG_LOV_ADD_OBD))
-			/* Add inactive instead */
-			lcfg->lcfg_command = LCFG_LOV_ADD_INA;
+		if (clli->cfg_flags & CFG_F_EXCLUDE) {
+			CDEBUG(D_CONFIG, "cmd: %x marked EXCLUDED\n",
+			       lcfg->lcfg_command);
+			if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD)
+				/* Add inactive instead */
+				lcfg->lcfg_command = LCFG_LOV_ADD_INA;
+		}
 
 		lustre_cfg_bufs_init(&bufs, lcfg);
 
@@ -1513,7 +1499,7 @@ out:
 		       handle->lgh_ctxt->loc_obd->obd_name, rc);
 		class_config_dump_handler(NULL, handle, rec, data);
 	}
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_config_llog_handler);
 
@@ -1524,12 +1510,11 @@ int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
 	struct llog_handle		*llh;
 	llog_cb_t			 callback;
 	int				 rc;
-	ENTRY;
 
 	CDEBUG(D_INFO, "looking up llog %s\n", name);
 	rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
 	if (rc)
@@ -1555,7 +1540,7 @@ int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
 
 parse_out:
 	llog_close(env, llh);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_config_parse_llog);
 
@@ -1571,12 +1556,10 @@ int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, int size)
 	char			*end = buf + size;
 	int			 rc = 0;
 
-	ENTRY;
-
 	LASSERT(rec->lrh_type == OBD_CFG_REC);
 	rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	ptr += snprintf(ptr, end-ptr, "cmd=%05x ", lcfg->lcfg_command);
 	if (lcfg->lcfg_flags)
@@ -1607,7 +1590,7 @@ int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, int size)
 	}
 	/* return consumed bytes */
 	rc = ptr - buf;
-	RETURN(rc);
+	return rc;
 }
 
 int class_config_dump_handler(const struct lu_env *env,
@@ -1617,11 +1600,9 @@ int class_config_dump_handler(const struct lu_env *env,
 	char	*outstr;
 	int	 rc = 0;
 
-	ENTRY;
-
 	OBD_ALLOC(outstr, 256);
 	if (outstr == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (rec->lrh_type == OBD_CFG_REC) {
 		class_config_parse_rec(rec, outstr, 256);
@@ -1632,7 +1613,7 @@ int class_config_dump_handler(const struct lu_env *env,
 	}
 
 	OBD_FREE(outstr, 256);
-	RETURN(rc);
+	return rc;
 }
 
 int class_config_dump_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
@@ -1641,13 +1622,11 @@ int class_config_dump_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
 	struct llog_handle	*llh;
 	int			 rc;
 
-	ENTRY;
-
 	LCONSOLE_INFO("Dumping config log %s\n", name);
 
 	rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
 	if (rc)
@@ -1658,7 +1637,7 @@ parse_out:
 	llog_close(env, llh);
 
 	LCONSOLE_INFO("End config log %s\n", name);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_config_dump_llog);
 
@@ -1671,11 +1650,10 @@ int class_manual_cleanup(struct obd_device *obd)
 	struct lustre_cfg      *lcfg;
 	struct lustre_cfg_bufs  bufs;
 	int		     rc;
-	ENTRY;
 
 	if (!obd) {
 		CERROR("empty cleanup\n");
-		RETURN(-EALREADY);
+		return -EALREADY;
 	}
 
 	if (obd->obd_force)
@@ -1690,7 +1668,7 @@ int class_manual_cleanup(struct obd_device *obd)
 	lustre_cfg_bufs_set_string(&bufs, 1, flags);
 	lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
 	if (!lcfg)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = class_process_config(lcfg);
 	if (rc) {
@@ -1705,7 +1683,7 @@ int class_manual_cleanup(struct obd_device *obd)
 		CERROR("detach failed %d: %s\n", rc, obd->obd_name);
 out:
 	lustre_cfg_free(lcfg);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(class_manual_cleanup);
 
@@ -1797,7 +1775,7 @@ nid_key(struct hlist_node *hnode)
 
 	exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
 
-	RETURN(&exp->exp_connection->c_peer.nid);
+	return &exp->exp_connection->c_peer.nid;
 }
 
 /*
@@ -1812,8 +1790,8 @@ nid_kepcmp(const void *key, struct hlist_node *hnode)
 	LASSERT(key);
 	exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
 
-	RETURN(exp->exp_connection->c_peer.nid == *(lnet_nid_t *)key &&
-	       !exp->exp_failed);
+	return exp->exp_connection->c_peer.nid == *(lnet_nid_t *)key &&
+	       !exp->exp_failed;
 }
 
 static void *
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index 99adad9..68a4d6a 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -47,10 +47,8 @@
 
 #include <obd.h>
 #include <lvfs.h>
-#include <lustre_fsfilt.h>
 #include <obd_class.h>
 #include <lustre/lustre_user.h>
-#include <linux/version.h>
 #include <lustre_log.h>
 #include <lustre_disk.h>
 #include <lustre_param.h>
@@ -82,14 +80,13 @@ int lustre_process_log(struct super_block *sb, char *logname,
 	struct lustre_sb_info *lsi = s2lsi(sb);
 	struct obd_device *mgc = lsi->lsi_mgc;
 	int rc;
-	ENTRY;
 
 	LASSERT(mgc);
 	LASSERT(cfg);
 
 	OBD_ALLOC_PTR(bufs);
 	if (bufs == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* mgc_process_config */
 	lustre_cfg_bufs_reset(bufs, mgc->obd_name);
@@ -119,7 +116,7 @@ int lustre_process_log(struct super_block *sb, char *logname,
 				   rc);
 
 	/* class_obd_list(); */
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(lustre_process_log);
 
@@ -132,10 +129,9 @@ int lustre_end_log(struct super_block *sb, char *logname,
 	struct lustre_sb_info *lsi = s2lsi(sb);
 	struct obd_device *mgc = lsi->lsi_mgc;
 	int rc;
-	ENTRY;
 
 	if (!mgc)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	/* mgc_process_config */
 	lustre_cfg_bufs_reset(&bufs, mgc->obd_name);
@@ -145,7 +141,7 @@ int lustre_end_log(struct super_block *sb, char *logname,
 	lcfg = lustre_cfg_new(LCFG_LOG_END, &bufs);
 	rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
 	lustre_cfg_free(lcfg);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(lustre_end_log);
 
@@ -225,7 +221,6 @@ int lustre_start_mgc(struct super_block *sb)
 	char *ptr;
 	int recov_bk;
 	int rc = 0, i = 0, j, len;
-	ENTRY;
 
 	LASSERT(lsi->lsi_lmd);
 
@@ -254,7 +249,7 @@ int lustre_start_mgc(struct super_block *sb)
 	}
 	if (i == 0) {
 		CERROR("No valid MGS nids found.\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	mutex_lock(&mgc_start_lock);
@@ -478,7 +473,7 @@ out_free:
 		OBD_FREE(mgcname, len);
 	if (niduuid)
 		OBD_FREE(niduuid, len + 2);
-	RETURN(rc);
+	return rc;
 }
 
 static int lustre_stop_mgc(struct super_block *sb)
@@ -487,13 +482,12 @@ static int lustre_stop_mgc(struct super_block *sb)
 	struct obd_device *obd;
 	char *niduuid = 0, *ptr = 0;
 	int i, rc = 0, len = 0;
-	ENTRY;
 
 	if (!lsi)
-		RETURN(-ENOENT);
+		return -ENOENT;
 	obd = lsi->lsi_mgc;
 	if (!obd)
-		RETURN(-ENOENT);
+		return -ENOENT;
 	lsi->lsi_mgc = NULL;
 
 	mutex_lock(&mgc_start_lock);
@@ -549,7 +543,7 @@ out:
 
 	/* class_import_put will get rid of the additional connections */
 	mutex_unlock(&mgc_start_lock);
-	RETURN(rc);
+	return rc;
 }
 
 /***************** lustre superblock **************/
@@ -557,15 +551,14 @@ out:
 struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
 {
 	struct lustre_sb_info *lsi;
-	ENTRY;
 
 	OBD_ALLOC_PTR(lsi);
 	if (!lsi)
-		RETURN(NULL);
+		return NULL;
 	OBD_ALLOC_PTR(lsi->lsi_lmd);
 	if (!lsi->lsi_lmd) {
 		OBD_FREE_PTR(lsi);
-		RETURN(NULL);
+		return NULL;
 	}
 
 	lsi->lsi_lmd->lmd_exclude_count = 0;
@@ -578,13 +571,12 @@ struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
 	/* Default umount style */
 	lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
 
-	RETURN(lsi);
+	return lsi;
 }
 
 static int lustre_free_lsi(struct super_block *sb)
 {
 	struct lustre_sb_info *lsi = s2lsi(sb);
-	ENTRY;
 
 	LASSERT(lsi != NULL);
 	CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
@@ -625,7 +617,7 @@ static int lustre_free_lsi(struct super_block *sb)
 	OBD_FREE(lsi, sizeof(*lsi));
 	s2lsi_nocast(sb) = NULL;
 
-	RETURN(0);
+	return 0;
 }
 
 /* The lsi has one reference for every server that is using the disk -
@@ -633,7 +625,6 @@ static int lustre_free_lsi(struct super_block *sb)
 int lustre_put_lsi(struct super_block *sb)
 {
 	struct lustre_sb_info *lsi = s2lsi(sb);
-	ENTRY;
 
 	LASSERT(lsi != NULL);
 
@@ -645,11 +636,20 @@ int lustre_put_lsi(struct super_block *sb)
 			obd_zombie_barrier();
 		}
 		lustre_free_lsi(sb);
-		RETURN(1);
+		return 1;
 	}
-	RETURN(0);
+	return 0;
 }
 
+/*** SERVER NAME ***
+ * <FSNAME><SEPERATOR><TYPE><INDEX>
+ * FSNAME is between 1 and 8 characters (inclusive).
+ *	Excluded characters are '/' and ':'
+ * SEPERATOR is either ':' or '-'
+ * TYPE: "OST", "MDT", etc.
+ * INDEX: Hex representation of the index
+ */
+
 /** Get the fsname ("lustre") from the server name ("lustre-OST003F").
  * @param [in] svname server name including type and index
  * @param [out] fsname Buffer to copy filesystem name prefix into.
@@ -659,22 +659,13 @@ int lustre_put_lsi(struct super_block *sb)
  */
 int server_name2fsname(const char *svname, char *fsname, const char **endptr)
 {
-	const char *dash = strrchr(svname, '-');
-	if (!dash) {
-		dash = strrchr(svname, ':');
-		if (!dash)
-			return -EINVAL;
-	}
+	const char *dash;
 
-	/* interpret <fsname>-MDTXXXXX-mdc as mdt, the better way is to pass
-	 * in the fsname, then determine the server index */
-	if (!strcmp(LUSTRE_MDC_NAME, dash + 1)) {
-		dash--;
-		for (; dash > svname && *dash != '-' && *dash != ':'; dash--)
-			;
-		if (dash == svname)
-			return -EINVAL;
-	}
+	dash = svname + strnlen(svname, 8); /* max fsname length is 8 */
+	for (; dash > svname && *dash != '-' && *dash != ':'; dash--)
+		;
+	if (dash == svname)
+		return -EINVAL;
 
 	if (fsname != NULL) {
 		strncpy(fsname, svname, dash - svname);
@@ -697,15 +688,15 @@ int server_name2svname(const char *label, char *svname, const char **endptr,
 		       size_t svsize)
 {
 	int rc;
-	const const char *dash;
+	const char *dash;
 
 	/* We use server_name2fsname() just for parsing */
 	rc = server_name2fsname(label, NULL, &dash);
 	if (rc != 0)
 		return rc;
 
-	if (*dash != '-')
-		return -1;
+	if (endptr != NULL)
+		*endptr = dash;
 
 	if (strlcpy(svname, dash + 1, svsize) >= svsize)
 		return -E2BIG;
@@ -730,9 +721,6 @@ int server_name2index(const char *svname, __u32 *idx, const char **endptr)
 	if (rc != 0)
 		return rc;
 
-	if (*dash != '-')
-		return -EINVAL;
-
 	dash++;
 
 	if (strncmp(dash, "MDT", 3) == 0)
@@ -744,11 +732,20 @@ int server_name2index(const char *svname, __u32 *idx, const char **endptr)
 
 	dash += 3;
 
-	if (strcmp(dash, "all") == 0)
+	if (strncmp(dash, "all", 3) == 0) {
+		if (endptr != NULL)
+			*endptr = dash + 3;
 		return rc | LDD_F_SV_ALL;
+	}
 
 	index = simple_strtoul(dash, (char **)endptr, 16);
-	*idx = index;
+	if (idx != NULL)
+		*idx = index;
+
+	/* Account for -mdc after index that is possible when specifying mdt */
+	if (endptr != NULL && strncmp(LUSTRE_MDC_NAME, *endptr + 1,
+				      sizeof(LUSTRE_MDC_NAME)-1) == 0)
+		*endptr += sizeof(LUSTRE_MDC_NAME);
 
 	return rc;
 }
@@ -760,7 +757,6 @@ EXPORT_SYMBOL(server_name2index);
 int lustre_common_put_super(struct super_block *sb)
 {
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_MOUNT, "dropping sb %p\n", sb);
 
@@ -769,7 +765,7 @@ int lustre_common_put_super(struct super_block *sb)
 	if (rc && (rc != -ENOENT)) {
 		if (rc != -EBUSY) {
 			CERROR("Can't stop MGC: %d\n", rc);
-			RETURN(rc);
+			return rc;
 		}
 		/* BUSY just means that there's some other obd that
 		   needs the mgc.  Let him clean it up. */
@@ -778,7 +774,7 @@ int lustre_common_put_super(struct super_block *sb)
 	/* Drop a ref to the mounted disk */
 	lustre_put_lsi(sb);
 	lu_types_stop();
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(lustre_common_put_super);
 
@@ -816,12 +812,11 @@ int lustre_check_exclusion(struct super_block *sb, char *svname)
 	struct lustre_mount_data *lmd = lsi->lsi_lmd;
 	__u32 index;
 	int i, rc;
-	ENTRY;
 
 	rc = server_name2index(svname, &index, NULL);
 	if (rc != LDD_F_SV_TYPE_OST)
 		/* Only exclude OSTs */
-		RETURN(0);
+		return 0;
 
 	CDEBUG(D_MOUNT, "Check exclusion %s (%d) in %d of %s\n", svname,
 	       index, lmd->lmd_exclude_count, lmd->lmd_dev);
@@ -829,10 +824,10 @@ int lustre_check_exclusion(struct super_block *sb, char *svname)
 	for(i = 0; i < lmd->lmd_exclude_count; i++) {
 		if (index == lmd->lmd_exclude[i]) {
 			CWARN("Excluding %s (on exclusion list)\n", svname);
-			RETURN(1);
+			return 1;
 		}
 	}
-	RETURN(0);
+	return 0;
 }
 
 /* mount -v  -o exclude=lustre-OST0001:lustre-OST0002 -t lustre ... */
@@ -841,7 +836,6 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr)
 	const char *s1 = ptr, *s2;
 	__u32 index, *exclude_list;
 	int rc = 0, devmax;
-	ENTRY;
 
 	/* The shortest an ost name can be is 8 chars: -OST0000.
 	   We don't actually know the fsname at this time, so in fact
@@ -851,20 +845,22 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr)
 	/* temp storage until we figure out how many we have */
 	OBD_ALLOC(exclude_list, sizeof(index) * devmax);
 	if (!exclude_list)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* we enter this fn pointing at the '=' */
 	while (*s1 && *s1 != ' ' && *s1 != ',') {
 		s1++;
 		rc = server_name2index(s1, &index, &s2);
 		if (rc < 0) {
-			CERROR("Can't parse server name '%s'\n", s1);
+			CERROR("Can't parse server name '%s': rc = %d\n",
+			       s1, rc);
 			break;
 		}
 		if (rc == LDD_F_SV_TYPE_OST)
 			exclude_list[lmd->lmd_exclude_count++] = index;
 		else
-			CDEBUG(D_MOUNT, "ignoring exclude %.7s\n", s1);
+			CDEBUG(D_MOUNT, "ignoring exclude %.*s: type = %#x\n",
+			       (uint)(s2-s1), s1, rc);
 		s1 = s2;
 		/* now we are pointing at ':' (next exclude)
 		   or ',' (end of excludes) */
@@ -887,7 +883,7 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr)
 		}
 	}
 	OBD_FREE(exclude_list, sizeof(index) * devmax);
-	RETURN(rc);
+	return rc;
 }
 
 static int lmd_parse_mgssec(struct lustre_mount_data *lmd, char *ptr)
@@ -991,13 +987,12 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 	char *s1, *s2, *devname = NULL;
 	struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(lmd);
 	if (!options) {
 		LCONSOLE_ERROR_MSG(0x162, "Missing mount data: check that "
 				   "/sbin/mount.lustre is installed.\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* Options should be a string - try to detect old lmd data */
@@ -1005,13 +1000,13 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 		LCONSOLE_ERROR_MSG(0x163, "You're using an old version of "
 				   "/sbin/mount.lustre.  Please install "
 				   "version %s\n", LUSTRE_VERSION_STRING);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	lmd->lmd_magic = LMD_MAGIC;
 
 	OBD_ALLOC(lmd->lmd_params, 4096);
 	if (lmd->lmd_params == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lmd->lmd_params[0] = '\0';
 
 	/* Set default flags here */
@@ -1150,14 +1145,14 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 		/* Freed in lustre_free_lsi */
 		OBD_ALLOC(lmd->lmd_profile, strlen(s1) + 8);
 		if (!lmd->lmd_profile)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		sprintf(lmd->lmd_profile, "%s-client", s1);
 	}
 
 	/* Freed in lustre_free_lsi */
 	OBD_ALLOC(lmd->lmd_dev, strlen(devname) + 1);
 	if (!lmd->lmd_dev)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	strcpy(lmd->lmd_dev, devname);
 
 	/* Save mount options */
@@ -1168,18 +1163,18 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 		/* Freed in lustre_free_lsi */
 		OBD_ALLOC(lmd->lmd_opts, strlen(options) + 1);
 		if (!lmd->lmd_opts)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		strcpy(lmd->lmd_opts, options);
 	}
 
 	lmd_print(lmd);
 	lmd->lmd_magic = LMD_MAGIC;
 
-	RETURN(rc);
+	return rc;
 
 invalid:
 	CERROR("Bad mount options %s\n", options);
-	RETURN(-EINVAL);
+	return -EINVAL;
 }
 
 struct lustre_mount_data2 {
@@ -1198,13 +1193,12 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent)
 	struct lustre_mount_data2 *lmd2 = data;
 	struct lustre_sb_info *lsi;
 	int rc;
-	ENTRY;
 
 	CDEBUG(D_MOUNT|D_VFSTRACE, "VFS Op: sb %p\n", sb);
 
 	lsi = lustre_init_lsi(sb);
 	if (!lsi)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	lmd = lsi->lsi_lmd;
 
 	/*
diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c
index 01a0e1f..7099764 100644
--- a/drivers/staging/lustre/lustre/obdclass/obdo.c
+++ b/drivers/staging/lustre/lustre/obdclass/obdo.c
@@ -100,11 +100,11 @@ void obdo_from_inode(struct obdo *dst, struct inode *src, obd_flag valid)
 		newvalid |= OBD_MD_FLMODE;
 	}
 	if (valid & OBD_MD_FLUID) {
-		dst->o_uid = src->i_uid;
+		dst->o_uid = from_kuid(&init_user_ns, src->i_uid);
 		newvalid |= OBD_MD_FLUID;
 	}
 	if (valid & OBD_MD_FLGID) {
-		dst->o_gid = src->i_gid;
+		dst->o_gid = from_kgid(&init_user_ns, src->i_gid);
 		newvalid |= OBD_MD_FLGID;
 	}
 	if (valid & OBD_MD_FLFLAGS) {
@@ -232,16 +232,16 @@ void obdo_from_iattr(struct obdo *oa, struct iattr *attr, unsigned int ia_valid)
 	if (ia_valid & ATTR_MODE) {
 		oa->o_mode = attr->ia_mode;
 		oa->o_valid |= OBD_MD_FLTYPE | OBD_MD_FLMODE;
-		if (!current_is_in_group(oa->o_gid) &&
+		if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) &&
 		    !cfs_capable(CFS_CAP_FSETID))
 			oa->o_mode &= ~S_ISGID;
 	}
 	if (ia_valid & ATTR_UID) {
-		oa->o_uid = attr->ia_uid;
+		oa->o_uid = from_kuid(&init_user_ns, attr->ia_uid);
 		oa->o_valid |= OBD_MD_FLUID;
 	}
 	if (ia_valid & ATTR_GID) {
-		oa->o_gid = attr->ia_gid;
+		oa->o_gid = from_kgid(&init_user_ns, attr->ia_gid);
 		oa->o_valid |= OBD_MD_FLGID;
 	}
 }
@@ -281,16 +281,16 @@ void iattr_from_obdo(struct iattr *attr, struct obdo *oa, obd_flag valid)
 	if (valid & OBD_MD_FLMODE) {
 		attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT);
 		attr->ia_valid |= ATTR_MODE;
-		if (!current_is_in_group(oa->o_gid) &&
+		if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) &&
 		    !cfs_capable(CFS_CAP_FSETID))
 			attr->ia_mode &= ~S_ISGID;
 	}
 	if (valid & OBD_MD_FLUID) {
-		attr->ia_uid = oa->o_uid;
+		attr->ia_uid = make_kuid(&init_user_ns, oa->o_uid);
 		attr->ia_valid |= ATTR_UID;
 	}
 	if (valid & OBD_MD_FLGID) {
-		attr->ia_gid = oa->o_gid;
+		attr->ia_gid = make_kgid(&init_user_ns, oa->o_gid);
 		attr->ia_valid |= ATTR_GID;
 	}
 }
diff --git a/drivers/staging/lustre/lustre/obdecho/echo.c b/drivers/staging/lustre/lustre/obdecho/echo.c
index 9e64939..debb9ce 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo.c
@@ -96,12 +96,10 @@ static int echo_init_export(struct obd_export *exp)
 
 static int echo_destroy_export(struct obd_export *exp)
 {
-	ENTRY;
-
 	target_destroy_export(exp);
 	ldlm_destroy_export(exp);
 
-	RETURN(0);
+	return 0;
 }
 
  static __u64 echo_next_id(struct obd_device *obddev)
@@ -151,25 +149,24 @@ static int echo_destroy(const struct lu_env *env, struct obd_export *exp,
 {
 	struct obd_device *obd = class_exp2obd(exp);
 
-	ENTRY;
 	if (!obd) {
 		CERROR("invalid client cookie "LPX64"\n",
 		       exp->exp_handle.h_cookie);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (!(oa->o_valid & OBD_MD_FLID)) {
 		CERROR("obdo missing FLID valid flag: "LPX64"\n", oa->o_valid);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (ostid_id(&oa->o_oi) > obd->u.echo.eo_lastino ||
 	    ostid_id(&oa->o_oi) < ECHO_INIT_OID) {
 		CERROR("bad destroy objid: "DOSTID"\n", POSTID(&oa->o_oi));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static int echo_getattr(const struct lu_env *env, struct obd_export *exp,
@@ -178,24 +175,23 @@ static int echo_getattr(const struct lu_env *env, struct obd_export *exp,
 	struct obd_device *obd = class_exp2obd(exp);
 	obd_id id = ostid_id(&oinfo->oi_oa->o_oi);
 
-	ENTRY;
 	if (!obd) {
 		CERROR("invalid client cookie "LPX64"\n",
 		       exp->exp_handle.h_cookie);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (!(oinfo->oi_oa->o_valid & OBD_MD_FLID)) {
 		CERROR("obdo missing FLID valid flag: "LPX64"\n",
 		       oinfo->oi_oa->o_valid);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	obdo_cpy_md(oinfo->oi_oa, &obd->u.echo.eo_oa, oinfo->oi_oa->o_valid);
 	ostid_set_seq_echo(&oinfo->oi_oa->o_oi);
 	ostid_set_id(&oinfo->oi_oa->o_oi, id);
 
-	RETURN(0);
+	return 0;
 }
 
 static int echo_setattr(const struct lu_env *env, struct obd_export *exp,
@@ -203,17 +199,16 @@ static int echo_setattr(const struct lu_env *env, struct obd_export *exp,
 {
 	struct obd_device *obd = class_exp2obd(exp);
 
-	ENTRY;
 	if (!obd) {
 		CERROR("invalid client cookie "LPX64"\n",
 		       exp->exp_handle.h_cookie);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (!(oinfo->oi_oa->o_valid & OBD_MD_FLID)) {
 		CERROR("obdo missing FLID valid flag: "LPX64"\n",
 		       oinfo->oi_oa->o_valid);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	memcpy(&obd->u.echo.eo_oa, oinfo->oi_oa, sizeof(*oinfo->oi_oa));
@@ -225,7 +220,7 @@ static int echo_setattr(const struct lu_env *env, struct obd_export *exp,
 		oti->oti_ack_locks[0].lock = obd->u.echo.eo_nl_lock;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static void
@@ -410,11 +405,10 @@ static int echo_preprw(const struct lu_env *env, int cmd,
 	int tot_bytes = 0;
 	int rc = 0;
 	int i, left;
-	ENTRY;
 
 	obd = export->exp_obd;
 	if (obd == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* Temp fix to stop falling foul of osc_announce_cached() */
 	oa->o_valid &= ~(OBD_MD_FLBLOCKS | OBD_MD_FLGRANT);
@@ -456,7 +450,7 @@ static int echo_preprw(const struct lu_env *env, int cmd,
 	CDEBUG(D_PAGE, "%d pages allocated after prep\n",
 	       atomic_read(&obd->u.echo.eo_prep));
 
-	RETURN(0);
+	return 0;
 
 preprw_cleanup:
 	/* It is possible that we would rather handle errors by  allow
@@ -487,11 +481,10 @@ static int echo_commitrw(const struct lu_env *env, int cmd,
 	struct obd_device *obd;
 	int pgs = 0;
 	int i;
-	ENTRY;
 
 	obd = export->exp_obd;
 	if (obd == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if (rc)
 		GOTO(commitrw_cleanup, rc);
@@ -506,7 +499,7 @@ static int echo_commitrw(const struct lu_env *env, int cmd,
 
 	if (niocount && res == NULL) {
 		CERROR("NULL res niobuf with niocount %d\n", niocount);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	LASSERT(oti == NULL || oti->oti_handle == (void *)DESC_PRIV);
@@ -537,7 +530,7 @@ static int echo_commitrw(const struct lu_env *env, int cmd,
 
 	CDEBUG(D_PAGE, "%d pages remain after commit\n",
 	       atomic_read(&obd->u.echo.eo_prep));
-	RETURN(rc);
+	return rc;
 
 commitrw_cleanup:
 	atomic_sub(pgs, &obd->u.echo.eo_prep);
@@ -565,7 +558,6 @@ static int echo_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	__u64		      lock_flags = 0;
 	struct ldlm_res_id	 res_id = {.name = {1}};
 	char		       ns_name[48];
-	ENTRY;
 
 	obd->u.echo.eo_obt.obt_magic = OBT_MAGIC;
 	spin_lock_init(&obd->u.echo.eo_lock);
@@ -578,7 +570,7 @@ static int echo_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 						LDLM_NS_TYPE_OST);
 	if (obd->obd_namespace == NULL) {
 		LBUG();
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id, LDLM_PLAIN,
@@ -600,13 +592,12 @@ static int echo_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 
 	ptlrpc_init_client (LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
 			    "echo_ldlm_cb_client", &obd->obd_ldlm_client);
-	RETURN(0);
+	return 0;
 }
 
 static int echo_cleanup(struct obd_device *obd)
 {
 	int leaked;
-	ENTRY;
 
 	lprocfs_obd_cleanup(obd);
 	lprocfs_free_obd_stats(obd);
@@ -624,7 +615,7 @@ static int echo_cleanup(struct obd_device *obd)
 	if (leaked != 0)
 		CERROR("%d prep/commitrw pages leaked\n", leaked);
 
-	RETURN(0);
+	return 0;
 }
 
 struct obd_ops echo_obd_ops = {
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index 184195f..2644edf 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -43,6 +43,7 @@
 #include <lustre_debug.h>
 #include <lprocfs_status.h>
 #include <cl_object.h>
+#include <md_object.h>
 #include <lustre_fid.h>
 #include <lustre_acl.h>
 #include <lustre_net.h>
@@ -312,11 +313,9 @@ static void echo_page_fini(const struct lu_env *env,
 	struct echo_page *ep    = cl2echo_page(slice);
 	struct echo_object *eco = cl2echo_obj(slice->cpl_obj);
 	struct page *vmpage      = ep->ep_vmpage;
-	ENTRY;
 
 	atomic_dec(&eco->eo_npages);
 	page_cache_release(vmpage);
-	EXIT;
 }
 
 static int echo_page_prep(const struct lu_env *env,
@@ -408,14 +407,13 @@ static int echo_page_init(const struct lu_env *env, struct cl_object *obj,
 {
 	struct echo_page *ep = cl_object_page_slice(obj, page);
 	struct echo_object *eco = cl2echo_obj(obj);
-	ENTRY;
 
 	ep->ep_vmpage = vmpage;
 	page_cache_get(vmpage);
 	mutex_init(&ep->ep_lock);
 	cl_page_slice_add(page, &ep->ep_cl, obj, &echo_page_ops);
 	atomic_inc(&eco->eo_npages);
-	RETURN(0);
+	return 0;
 }
 
 static int echo_io_init(const struct lu_env *env, struct cl_object *obj,
@@ -429,7 +427,6 @@ static int echo_lock_init(const struct lu_env *env,
 			  const struct cl_io *unused)
 {
 	struct echo_lock *el;
-	ENTRY;
 
 	OBD_SLAB_ALLOC_PTR_GFP(el, echo_lock_kmem, __GFP_IO);
 	if (el != NULL) {
@@ -438,7 +435,7 @@ static int echo_lock_init(const struct lu_env *env,
 		INIT_LIST_HEAD(&el->el_chain);
 		atomic_set(&el->el_refcount, 0);
 	}
-	RETURN(el == NULL ? -ENOMEM : 0);
+	return el == NULL ? -ENOMEM : 0;
 }
 
 static int echo_conf_set(const struct lu_env *env, struct cl_object *obj,
@@ -467,7 +464,6 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj,
 	struct echo_device *ed	 = cl2echo_dev(lu2cl_dev(obj->lo_dev));
 	struct echo_client_obd *ec     = ed->ed_ec;
 	struct echo_object *eco	= cl2echo_obj(lu2cl(obj));
-	ENTRY;
 
 	if (ed->ed_next) {
 		struct lu_object  *below;
@@ -477,7 +473,7 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj,
 		below = under->ld_ops->ldo_object_alloc(env, obj->lo_header,
 							under);
 		if (below == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		lu_object_add(obj, below);
 	}
 
@@ -501,7 +497,7 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj,
 	list_add_tail(&eco->eo_obj_chain, &ec->ec_objects);
 	spin_unlock(&ec->ec_lock);
 
-	RETURN(0);
+	return 0;
 }
 
 /* taken from osc_unpackmd() */
@@ -510,8 +506,6 @@ static int echo_alloc_memmd(struct echo_device *ed,
 {
 	int lsm_size;
 
-	ENTRY;
-
 	/* If export is lov/osc then use their obd method */
 	if (ed->ed_next != NULL)
 		return obd_alloc_memmd(ed->ed_ec->ec_exp, lsmp);
@@ -521,27 +515,25 @@ static int echo_alloc_memmd(struct echo_device *ed,
 	LASSERT(*lsmp == NULL);
 	OBD_ALLOC(*lsmp, lsm_size);
 	if (*lsmp == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	OBD_ALLOC((*lsmp)->lsm_oinfo[0], sizeof(struct lov_oinfo));
 	if ((*lsmp)->lsm_oinfo[0] == NULL) {
 		OBD_FREE(*lsmp, lsm_size);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	loi_init((*lsmp)->lsm_oinfo[0]);
 	(*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES;
 	ostid_set_seq_echo(&(*lsmp)->lsm_oi);
 
-	RETURN(lsm_size);
+	return lsm_size;
 }
 
 static int echo_free_memmd(struct echo_device *ed, struct lov_stripe_md **lsmp)
 {
 	int lsm_size;
 
-	ENTRY;
-
 	/* If export is lov/osc then use their obd method */
 	if (ed->ed_next != NULL)
 		return obd_free_memmd(ed->ed_ec->ec_exp, lsmp);
@@ -552,14 +544,13 @@ static int echo_free_memmd(struct echo_device *ed, struct lov_stripe_md **lsmp)
 	OBD_FREE((*lsmp)->lsm_oinfo[0], sizeof(struct lov_oinfo));
 	OBD_FREE(*lsmp, lsm_size);
 	*lsmp = NULL;
-	RETURN(0);
+	return 0;
 }
 
 static void echo_object_free(const struct lu_env *env, struct lu_object *obj)
 {
 	struct echo_object *eco    = cl2echo_obj(lu2cl(obj));
 	struct echo_client_obd *ec = eco->eo_dev->ed_ec;
-	ENTRY;
 
 	LASSERT(atomic_read(&eco->eo_npages) == 0);
 
@@ -573,7 +564,6 @@ static void echo_object_free(const struct lu_env *env, struct lu_object *obj)
 	if (eco->eo_lsm)
 		echo_free_memmd(eco->eo_dev, &eco->eo_lsm);
 	OBD_SLAB_FREE_PTR(eco, echo_object_kmem);
-	EXIT;
 }
 
 static int echo_object_print(const struct lu_env *env, void *cookie,
@@ -606,7 +596,6 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env,
 {
 	struct echo_object *eco;
 	struct lu_object *obj = NULL;
-	ENTRY;
 
 	/* we're the top dev. */
 	LASSERT(hdr == NULL);
@@ -622,7 +611,7 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env,
 		eco->eo_cl.co_ops = &echo_cl_obj_ops;
 		obj->lo_ops       = &echo_lu_obj_ops;
 	}
-	RETURN(obj);
+	return obj;
 }
 
 static struct lu_device_operations echo_device_lu_ops = {
@@ -648,7 +637,7 @@ static int echo_site_init(const struct lu_env *env, struct echo_device *ed)
 	/* initialize site */
 	rc = cl_site_init(site, &ed->ed_cl);
 	if (rc) {
-		CERROR("Cannot initilize site for echo client(%d)\n", rc);
+		CERROR("Cannot initialize site for echo client(%d)\n", rc);
 		return rc;
 	}
 
@@ -737,11 +726,10 @@ static int echo_fid_init(struct echo_device *ed, char *obd_name,
 {
 	char *prefix;
 	int rc;
-	ENTRY;
 
 	OBD_ALLOC_PTR(ed->ed_cl_seq);
 	if (ed->ed_cl_seq == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	OBD_ALLOC(prefix, MAX_OBD_NAME + 5);
 	if (prefix == NULL)
@@ -758,18 +746,17 @@ static int echo_fid_init(struct echo_device *ed, char *obd_name,
 	if (rc)
 		GOTO(out_free_seq, rc);
 
-	RETURN(0);
+	return 0;
 
 out_free_seq:
 	OBD_FREE_PTR(ed->ed_cl_seq);
 	ed->ed_cl_seq = NULL;
-	RETURN(rc);
+	return rc;
 }
 
 static int echo_fid_fini(struct obd_device *obddev)
 {
 	struct echo_device *ed = obd2echo_dev(obddev);
-	ENTRY;
 
 	if (ed->ed_cl_seq != NULL) {
 		seq_client_fini(ed->ed_cl_seq);
@@ -777,7 +764,7 @@ static int echo_fid_fini(struct obd_device *obddev)
 		ed->ed_cl_seq = NULL;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static struct lu_device *echo_device_alloc(const struct lu_env *env,
@@ -792,7 +779,6 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env,
 	const char *tgt_type_name;
 	int rc;
 	int cleanup = 0;
-	ENTRY;
 
 	OBD_ALLOC_PTR(ed);
 	if (ed == NULL)
@@ -916,7 +902,7 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env,
 	}
 
 	ed->ed_next = next;
-	RETURN(&cd->cd_lu_dev);
+	return &cd->cd_lu_dev;
 out:
 	switch(cleanup) {
 	case 4: {
@@ -1076,7 +1062,6 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d,
 	struct lu_fid *fid;
 	int refcheck;
 	int rc;
-	ENTRY;
 
 	LASSERT(lsmp);
 	lsm = *lsmp;
@@ -1087,11 +1072,11 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d,
 
 	/* Never return an object if the obd is to be freed. */
 	if (echo_dev2cl(d)->cd_lu_dev.ld_obd->obd_stopping)
-		RETURN(ERR_PTR(-ENODEV));
+		return ERR_PTR(-ENODEV);
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN((void *)env);
+		return (void *)env;
 
 	info = echo_env_info(env);
 	conf = &info->eti_conf;
@@ -1131,7 +1116,7 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d,
 
 out:
 	cl_env_put(env, &refcheck);
-	RETURN(eco);
+	return eco;
 }
 
 static int cl_echo_object_put(struct echo_object *eco)
@@ -1139,11 +1124,10 @@ static int cl_echo_object_put(struct echo_object *eco)
 	struct lu_env *env;
 	struct cl_object *obj = echo_obj2cl(eco);
 	int refcheck;
-	ENTRY;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	/* an external function to kill an object? */
 	if (eco->eo_deleted) {
@@ -1154,7 +1138,7 @@ static int cl_echo_object_put(struct echo_object *eco)
 
 	cl_object_put(env, obj);
 	cl_env_put(env, &refcheck);
-	RETURN(0);
+	return 0;
 }
 
 static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco,
@@ -1167,7 +1151,6 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco,
 	struct cl_lock_descr *descr;
 	struct echo_thread_info *info;
 	int rc = -ENOMEM;
-	ENTRY;
 
 	info = echo_env_info(env);
 	io = &info->eti_io;
@@ -1201,7 +1184,7 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco,
 			cl_lock_release(env, lck, "ec enqueue", current);
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end,
@@ -1212,11 +1195,10 @@ static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end,
 	struct cl_io *io;
 	int refcheck;
 	int result;
-	ENTRY;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	info = echo_env_info(env);
 	io = &info->eti_io;
@@ -1230,7 +1212,6 @@ static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end,
 	result = cl_echo_enqueue0(env, eco, start, end, mode, cookie, 0);
 	cl_io_fini(env, io);
 
-	EXIT;
 out:
 	cl_env_put(env, &refcheck);
 	return result;
@@ -1243,7 +1224,6 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed,
 	struct echo_lock       *ecl = NULL;
 	struct list_head	     *el;
 	int found = 0, still_used = 0;
-	ENTRY;
 
 	LASSERT(ec != NULL);
 	spin_lock(&ec->ec_lock);
@@ -1262,10 +1242,10 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed,
 	spin_unlock(&ec->ec_lock);
 
 	if (!found)
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	echo_lock_release(env, ecl, still_used);
-	RETURN(0);
+	return 0;
 }
 
 static int cl_echo_cancel(struct echo_device *ed, __u64 cookie)
@@ -1273,16 +1253,15 @@ static int cl_echo_cancel(struct echo_device *ed, __u64 cookie)
 	struct lu_env *env;
 	int refcheck;
 	int rc;
-	ENTRY;
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	rc = cl_echo_cancel0(env, ed, cookie);
 
 	cl_env_put(env, &refcheck);
-	RETURN(rc);
+	return rc;
 }
 
 static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io,
@@ -1291,7 +1270,6 @@ static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io,
 	struct cl_page *clp;
 	struct cl_page *temp;
 	int result = 0;
-	ENTRY;
 
 	cl_page_list_for_each_safe(clp, temp, &queue->c2_qin) {
 		int rc;
@@ -1300,7 +1278,7 @@ static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io,
 			continue;
 		result = result ?: rc;
 	}
-	RETURN(result);
+	return result;
 }
 
 static int cl_echo_object_brw(struct echo_object *eco, int rw, obd_off offset,
@@ -1318,13 +1296,12 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, obd_off offset,
 	int refcheck;
 	int rc;
 	int i;
-	ENTRY;
 
 	LASSERT((offset & ~CFS_PAGE_MASK) == 0);
 	LASSERT(ed->ed_next != NULL);
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	info    = echo_env_info(env);
 	io      = &info->eti_io;
@@ -1386,7 +1363,6 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, obd_off offset,
 	}
 
 	cl_echo_cancel0(env, ed, lh.cookie);
-	EXIT;
 error_lock:
 	cl_2queue_discard(env, io, queue);
 	cl_2queue_disown(env, io, queue);
@@ -1467,13 +1443,11 @@ static int echo_big_lmm_get(const struct lu_env *env, struct md_object *o,
 	struct echo_thread_info	*info = echo_env_info(env);
 	int			 rc;
 
-	ENTRY;
-
 	LASSERT(ma->ma_lmm_size > 0);
 
 	rc = mo_xattr_get(env, o, &LU_BUF_NULL, XATTR_NAME_LOV);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	/* big_lmm may need to be grown */
 	if (info->eti_big_lmmsize < rc) {
@@ -1490,7 +1464,7 @@ static int echo_big_lmm_get(const struct lu_env *env, struct md_object *o,
 
 		OBD_ALLOC_LARGE(info->eti_big_lmm, size);
 		if (info->eti_big_lmm == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		info->eti_big_lmmsize = size;
 	}
 	LASSERT(info->eti_big_lmmsize >= rc);
@@ -1499,13 +1473,13 @@ static int echo_big_lmm_get(const struct lu_env *env, struct md_object *o,
 	info->eti_buf.lb_len = info->eti_big_lmmsize;
 	rc = mo_xattr_get(env, o, &info->eti_buf, XATTR_NAME_LOV);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	ma->ma_valid |= MA_LOV;
 	ma->ma_lmm = info->eti_big_lmm;
 	ma->ma_lmm_size = rc;
 
-	RETURN(0);
+	return 0;
 }
 
 int echo_attr_get_complex(const struct lu_env *env, struct md_object *next,
@@ -1517,8 +1491,6 @@ int echo_attr_get_complex(const struct lu_env *env, struct md_object *next,
 	int			 need = ma->ma_need;
 	int			 rc = 0, rc2;
 
-	ENTRY;
-
 	ma->ma_valid = 0;
 
 	if (need & MA_INODE) {
@@ -1571,7 +1543,7 @@ out:
 	ma->ma_need = need;
 	CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64" ma_lmm=%p\n",
 	       rc, ma->ma_valid, ma->ma_lmm);
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -1587,8 +1559,6 @@ echo_md_create_internal(const struct lu_env *env, struct echo_device *ed,
 	struct lu_object_conf    conf = { .loc_flags = LOC_F_NEW };
 	int			 rc;
 
-	ENTRY;
-
 	rc = mdo_lookup(env, parent, lname, fid2, spec);
 	if (rc == 0)
 		return -EEXIST;
@@ -1600,7 +1570,7 @@ echo_md_create_internal(const struct lu_env *env, struct echo_device *ed,
 	if (IS_ERR(ec_child)) {
 		CERROR("Can not find the child "DFID": rc = %ld\n", PFID(fid),
 			PTR_ERR(ec_child));
-		RETURN(PTR_ERR(ec_child));
+		return PTR_ERR(ec_child);
 	}
 
 	child = lu_object_locate(ec_child->lo_header, ld->ld_type);
@@ -1623,7 +1593,6 @@ echo_md_create_internal(const struct lu_env *env, struct echo_device *ed,
 	}
 	CDEBUG(D_RPCTRACE, "End creating object "DFID" %s %p rc  = %d\n",
 	       PFID(lu_object_fid(&parent->mo_lu)), lname->ln_name, parent, rc);
-	EXIT;
 out_put:
 	lu_object_put(env, ec_child);
 	return rc;
@@ -1663,13 +1632,11 @@ static int echo_create_md_object(const struct lu_env *env,
 	int		      rc = 0;
 	int		      i;
 
-	ENTRY;
-
 	if (ec_parent == NULL)
 		return -1;
 	parent = lu_object_locate(ec_parent->lo_header, ld->ld_type);
 	if (parent == NULL)
-		RETURN(-ENXIO);
+		return -ENXIO;
 
 	memset(ma, 0, sizeof(*ma));
 	memset(spec, 0, sizeof(*spec));
@@ -1699,7 +1666,7 @@ static int echo_create_md_object(const struct lu_env *env,
 		/* If name is specified, only create one object by name */
 		rc = echo_md_create_internal(env, ed, lu2md(parent), fid, lname,
 					     spec, ma);
-		RETURN(rc);
+		return rc;
 	}
 
 	/* Create multiple object sequenced by id */
@@ -1719,7 +1686,7 @@ static int echo_create_md_object(const struct lu_env *env,
 		fid->f_oid++;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static struct lu_object *echo_md_lookup(const struct lu_env *env,
@@ -1731,14 +1698,13 @@ static struct lu_object *echo_md_lookup(const struct lu_env *env,
 	struct lu_fid	   *fid = &info->eti_fid;
 	struct lu_object	*child;
 	int    rc;
-	ENTRY;
 
 	CDEBUG(D_INFO, "lookup %s in parent "DFID" %p\n", lname->ln_name,
 	       PFID(fid), parent);
 	rc = mdo_lookup(env, parent, lname, fid, NULL);
 	if (rc) {
 		CERROR("lookup %s: rc = %d\n", lname->ln_name, rc);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	/* In the function below, .hs_keycmp resolves to
@@ -1746,7 +1712,7 @@ static struct lu_object *echo_md_lookup(const struct lu_env *env,
 	/* coverity[overrun-buffer-val] */
 	child = lu_object_find_at(env, &ed->ed_cl.cd_lu_dev, fid, NULL);
 
-	RETURN(child);
+	return child;
 }
 
 static int echo_setattr_object(const struct lu_env *env,
@@ -1763,13 +1729,11 @@ static int echo_setattr_object(const struct lu_env *env,
 	int		      rc = 0;
 	int		      i;
 
-	ENTRY;
-
 	if (ec_parent == NULL)
 		return -1;
 	parent = lu_object_locate(ec_parent->lo_header, ld->ld_type);
 	if (parent == NULL)
-		RETURN(-ENXIO);
+		return -ENXIO;
 
 	for (i = 0; i < count; i++) {
 		struct lu_object *ec_child, *child;
@@ -1780,7 +1744,7 @@ static int echo_setattr_object(const struct lu_env *env,
 		if (IS_ERR(ec_child)) {
 			CERROR("Can't find child %s: rc = %ld\n",
 				lname->ln_name, PTR_ERR(ec_child));
-			RETURN(PTR_ERR(ec_child));
+			return PTR_ERR(ec_child);
 		}
 
 		child = lu_object_locate(ec_child->lo_header, ld->ld_type);
@@ -1811,7 +1775,7 @@ static int echo_setattr_object(const struct lu_env *env,
 		id++;
 		lu_object_put(env, ec_child);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int echo_getattr_object(const struct lu_env *env,
@@ -1828,13 +1792,11 @@ static int echo_getattr_object(const struct lu_env *env,
 	int		      rc = 0;
 	int		      i;
 
-	ENTRY;
-
 	if (ec_parent == NULL)
 		return -1;
 	parent = lu_object_locate(ec_parent->lo_header, ld->ld_type);
 	if (parent == NULL)
-		RETURN(-ENXIO);
+		return -ENXIO;
 
 	memset(ma, 0, sizeof(*ma));
 	ma->ma_need |= MA_INODE | MA_LOV | MA_PFID | MA_HSM | MA_ACL_DEF;
@@ -1852,14 +1814,14 @@ static int echo_getattr_object(const struct lu_env *env,
 		if (IS_ERR(ec_child)) {
 			CERROR("Can't find child %s: rc = %ld\n",
 			       lname->ln_name, PTR_ERR(ec_child));
-			RETURN(PTR_ERR(ec_child));
+			return PTR_ERR(ec_child);
 		}
 
 		child = lu_object_locate(ec_child->lo_header, ld->ld_type);
 		if (child == NULL) {
 			CERROR("Can not locate the child %s\n", lname->ln_name);
 			lu_object_put(env, ec_child);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		CDEBUG(D_RPCTRACE, "Start getattr object "DFID"\n",
@@ -1877,7 +1839,7 @@ static int echo_getattr_object(const struct lu_env *env,
 		lu_object_put(env, ec_child);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static int echo_lookup_object(const struct lu_env *env,
@@ -1931,13 +1893,11 @@ static int echo_md_destroy_internal(const struct lu_env *env,
 	struct lu_object   *child;
 	int		 rc;
 
-	ENTRY;
-
 	ec_child = echo_md_lookup(env, ed, parent, lname);
 	if (IS_ERR(ec_child)) {
 		CERROR("Can't find child %s: rc = %ld\n", lname->ln_name,
 			PTR_ERR(ec_child));
-		RETURN(PTR_ERR(ec_child));
+		return PTR_ERR(ec_child);
 	}
 
 	child = lu_object_locate(ec_child->lo_header, ld->ld_type);
@@ -1976,11 +1936,10 @@ static int echo_destroy_object(const struct lu_env *env,
 	struct lu_object	*parent;
 	int		      rc = 0;
 	int		      i;
-	ENTRY;
 
 	parent = lu_object_locate(ec_parent->lo_header, ld->ld_type);
 	if (parent == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	memset(ma, 0, sizeof(*ma));
 	ma->ma_attr.la_mode = mode;
@@ -1994,7 +1953,7 @@ static int echo_destroy_object(const struct lu_env *env,
 		lname->ln_namelen = namelen;
 		rc = echo_md_destroy_internal(env, ed, lu2md(parent), lname,
 					      ma);
-		RETURN(rc);
+		return rc;
 	}
 
 	/*prepare the requests*/
@@ -2013,7 +1972,7 @@ static int echo_destroy_object(const struct lu_env *env,
 		id++;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static struct lu_object *echo_resolve_path(const struct lu_env *env,
@@ -2028,13 +1987,12 @@ static struct lu_object *echo_resolve_path(const struct lu_env *env,
 	struct lu_object	*parent = NULL;
 	struct lu_object	*child = NULL;
 	int rc = 0;
-	ENTRY;
 
 	/*Only support MDD layer right now*/
 	rc = md->md_ops->mdo_root_get(env, md, fid);
 	if (rc) {
 		CERROR("get root error: rc = %d\n", rc);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 
 	/* In the function below, .hs_keycmp resolves to
@@ -2044,7 +2002,7 @@ static struct lu_object *echo_resolve_path(const struct lu_env *env,
 	if (IS_ERR(parent)) {
 		CERROR("Can not find the parent "DFID": rc = %ld\n",
 			PFID(fid), PTR_ERR(parent));
-		RETURN(parent);
+		return parent;
 	}
 
 	while (1) {
@@ -2083,9 +2041,9 @@ static struct lu_object *echo_resolve_path(const struct lu_env *env,
 		parent = child;
 	}
 	if (rc)
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 
-	RETURN(parent);
+	return parent;
 }
 
 static void echo_ucred_init(struct lu_env *env)
@@ -2097,10 +2055,14 @@ static void echo_ucred_init(struct lu_env *env)
 	ucred->uc_suppgids[0] = -1;
 	ucred->uc_suppgids[1] = -1;
 
-	ucred->uc_uid   = ucred->uc_o_uid   = current_uid();
-	ucred->uc_gid   = ucred->uc_o_gid   = current_gid();
-	ucred->uc_fsuid = ucred->uc_o_fsuid = current_fsuid();
-	ucred->uc_fsgid = ucred->uc_o_fsgid = current_fsgid();
+	ucred->uc_uid   = ucred->uc_o_uid   =
+				from_kuid(&init_user_ns, current_uid());
+	ucred->uc_gid   = ucred->uc_o_gid   =
+				from_kgid(&init_user_ns, current_gid());
+	ucred->uc_fsuid = ucred->uc_o_fsuid =
+				from_kuid(&init_user_ns, current_fsuid());
+	ucred->uc_fsgid = ucred->uc_o_fsgid =
+				from_kgid(&init_user_ns, current_fsgid());
 	ucred->uc_cap   = cfs_curproc_cap_pack();
 
 	/* remove fs privilege for non-root user. */
@@ -2129,21 +2091,20 @@ static int echo_md_handler(struct echo_device *ed, int command,
 	char		  *name = NULL;
 	int		    namelen = data->ioc_plen2;
 	int		    rc = 0;
-	ENTRY;
 
 	if (ld == NULL) {
 		CERROR("MD echo client is not being initialized properly\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (strcmp(ld->ld_type->ldt_name, LUSTRE_MDD_NAME)) {
 		CERROR("Only support MDD layer right now!\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	env = cl_env_get(&refcheck);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	rc = lu_env_refill_by_tags(env, ECHO_MD_CTX_TAG, ECHO_MD_SES_TAG);
 	if (rc != 0)
@@ -2243,13 +2204,12 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed,
 	struct lov_stripe_md   *lsm = NULL;
 	int		     rc;
 	int		     created = 0;
-	ENTRY;
 
 	if ((oa->o_valid & OBD_MD_FLID) == 0 && /* no obj id */
 	    (on_target ||		       /* set_stripe */
 	     ec->ec_nstripes != 0)) {	   /* LOV */
 		CERROR ("No valid oid\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = echo_alloc_memmd(ed, &lsm);
@@ -2315,7 +2275,6 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed,
 	cl_echo_object_put(eco);
 
 	CDEBUG(D_INFO, "oa oid "DOSTID"\n", POSTID(&oa->o_oi));
-	EXIT;
 
  failed:
 	if (created && rc)
@@ -2333,17 +2292,16 @@ static int echo_get_object(struct echo_object **ecop, struct echo_device *ed,
 	struct lov_stripe_md   *lsm = NULL;
 	struct echo_object     *eco;
 	int		     rc;
-	ENTRY;
 
 	if ((oa->o_valid & OBD_MD_FLID) == 0 || ostid_id(&oa->o_oi) == 0) {
 		/* disallow use of object id 0 */
 		CERROR ("No valid oid\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = echo_alloc_memmd(ed, &lsm);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	lsm->lsm_oi = oa->o_oi;
 	if (!(oa->o_valid & OBD_MD_FLGROUP))
@@ -2357,7 +2315,7 @@ static int echo_get_object(struct echo_object **ecop, struct echo_device *ed,
 		rc = PTR_ERR(eco);
 	if (lsm)
 		echo_free_memmd(ed, &lsm);
-	RETURN(rc);
+	return rc;
 }
 
 static void echo_put_object(struct echo_object *eco)
@@ -2476,7 +2434,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
 	int		     verify;
 	int		     gfp_mask;
 	int		     brw_flags = 0;
-	ENTRY;
 
 	verify = (ostid_id(&oa->o_oi) != ECHO_PERSISTENT_OBJID &&
 		  (oa->o_valid & OBD_MD_FLFLAGS) != 0 &&
@@ -2490,7 +2447,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
 
 	if (count <= 0 ||
 	    (count & (~CFS_PAGE_MASK)) != 0)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* XXX think again with misaligned I/O */
 	npages = count >> PAGE_CACHE_SHIFT;
@@ -2500,12 +2457,12 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
 
 	OBD_ALLOC(pga, npages * sizeof(*pga));
 	if (pga == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	OBD_ALLOC(pages, npages * sizeof(*pages));
 	if (pages == NULL) {
 		OBD_FREE(pga, npages * sizeof(*pga));
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	for (i = 0, pgp = pga, off = offset;
@@ -2554,7 +2511,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
 	}
 	OBD_FREE(pga, npages * sizeof(*pga));
 	OBD_FREE(pages, npages * sizeof(*pages));
-	RETURN(rc);
+	return rc;
 }
 
 static int echo_client_prep_commit(const struct lu_env *env,
@@ -2572,11 +2529,9 @@ static int echo_client_prep_commit(const struct lu_env *env,
 	obd_size npages, tot_pages;
 	int i, ret = 0, brw_flags = 0;
 
-	ENTRY;
-
 	if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0 ||
 	    (lsm != NULL && ostid_id(&lsm->lsm_oi) != ostid_id(&oa->o_oi)))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	npages = batch >> PAGE_CACHE_SHIFT;
 	tot_pages = count >> PAGE_CACHE_SHIFT;
@@ -2661,7 +2616,7 @@ out:
 		OBD_FREE(lnb, npages * sizeof(struct niobuf_local));
 	if (rnb)
 		OBD_FREE(rnb, npages * sizeof(struct niobuf_remote));
-	RETURN(ret);
+	return ret;
 }
 
 static int echo_client_brw_ioctl(const struct lu_env *env, int rw,
@@ -2677,13 +2632,12 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw,
 	int rc;
 	int async = 1;
 	long test_mode;
-	ENTRY;
 
 	LASSERT(oa->o_valid & OBD_MD_FLGROUP);
 
 	rc = echo_get_object(&eco, ed, oa);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	oa->o_valid &= ~OBD_MD_FLHANDLE;
 
@@ -2719,7 +2673,7 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw,
 		rc = -EINVAL;
 	}
 	echo_put_object(eco);
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -2731,21 +2685,20 @@ echo_client_enqueue(struct obd_export *exp, struct obdo *oa,
 	struct echo_object     *eco;
 	obd_off		 end;
 	int		     rc;
-	ENTRY;
 
 	if (ed->ed_next == NULL)
-		RETURN(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	if (!(mode == LCK_PR || mode == LCK_PW))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if ((offset & (~CFS_PAGE_MASK)) != 0 ||
 	    (nob & (~CFS_PAGE_MASK)) != 0)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	rc = echo_get_object (&eco, ed, oa);
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	end = (nob == 0) ? ((obd_off) -1) : (offset + nob - 1);
 	rc = cl_echo_enqueue(eco, offset, end, mode, &ulh->cookie);
@@ -2754,7 +2707,7 @@ echo_client_enqueue(struct obd_export *exp, struct obdo *oa,
 		CDEBUG(D_INFO, "Cookie is "LPX64"\n", ulh->cookie);
 	}
 	echo_put_object(eco);
-	RETURN(rc);
+	return rc;
 }
 
 static int
@@ -2787,7 +2740,6 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 	int		     rw = OBD_BRW_READ;
 	int		     rc = 0;
 	int		     i;
-	ENTRY;
 
 	memset(&dummy_oti, 0, sizeof(dummy_oti));
 
@@ -2800,11 +2752,11 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 	/* This FID is unpacked just for validation at this point */
 	rc = ostid_to_fid(&fid, &oa->o_oi, 0);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	OBD_ALLOC_PTR(env);
 	if (env == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = lu_env_init(env, LCT_DT_THREAD);
 	if (rc)
@@ -2980,7 +2932,6 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 		GOTO (out, rc = -ENOTTY);
 	}
 
-	EXIT;
 out:
 	lu_env_fini(env);
 	OBD_FREE_PTR(env);
@@ -3004,18 +2955,17 @@ static int echo_client_setup(const struct lu_env *env,
 	struct obd_uuid echo_uuid = { "ECHO_UUID" };
 	struct obd_connect_data *ocd = NULL;
 	int rc;
-	ENTRY;
 
 	if (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
 		CERROR("requires a TARGET OBD name\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
 	if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
 		CERROR("device not attached or not set up (%s)\n",
 		       lustre_cfg_string(lcfg, 1));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	spin_lock_init(&ec->ec_lock);
@@ -3027,7 +2977,7 @@ static int echo_client_setup(const struct lu_env *env,
 	if (!strcmp(tgt->obd_type->typ_name, LUSTRE_MDT_NAME)) {
 		lu_context_tags_update(ECHO_MD_CTX_TAG);
 		lu_session_tags_update(ECHO_MD_SES_TAG);
-		RETURN(0);
+		return 0;
 	}
 
 	OBD_ALLOC(ocd, sizeof(*ocd));
@@ -3062,7 +3012,7 @@ static int echo_client_setup(const struct lu_env *env,
 		return (rc);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static int echo_client_cleanup(struct obd_device *obddev)
@@ -3070,21 +3020,20 @@ static int echo_client_cleanup(struct obd_device *obddev)
 	struct echo_device *ed = obd2echo_dev(obddev);
 	struct echo_client_obd *ec = &obddev->u.echo_client;
 	int rc;
-	ENTRY;
 
 	/*Do nothing for Metadata echo client*/
 	if (ed == NULL )
-		RETURN(0);
+		return 0;
 
 	if (ed->ed_next_ismd) {
 		lu_context_tags_clear(ECHO_MD_CTX_TAG);
 		lu_session_tags_clear(ECHO_MD_SES_TAG);
-		RETURN(0);
+		return 0;
 	}
 
 	if (!list_empty(&obddev->obd_exports)) {
 		CERROR("still has clients!\n");
-		RETURN(-EBUSY);
+		return -EBUSY;
 	}
 
 	LASSERT(atomic_read(&ec->ec_exp->exp_refcount) > 0);
@@ -3092,7 +3041,7 @@ static int echo_client_cleanup(struct obd_device *obddev)
 	if (rc != 0)
 		CERROR("fail to disconnect device: %d\n", rc);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int echo_client_connect(const struct lu_env *env,
@@ -3103,13 +3052,12 @@ static int echo_client_connect(const struct lu_env *env,
 	int		rc;
 	struct lustre_handle conn = { 0 };
 
-	ENTRY;
 	rc = class_connect(&conn, src, cluuid);
 	if (rc == 0) {
 		*exp = class_conn2export(&conn);
 	}
 
-	RETURN (rc);
+	return rc;
 }
 
 static int echo_client_disconnect(struct obd_export *exp)
@@ -3120,7 +3068,6 @@ static int echo_client_disconnect(struct obd_export *exp)
 	struct ec_lock	 *ecl;
 #endif
 	int		     rc;
-	ENTRY;
 
 	if (exp == NULL)
 		GOTO(out, rc = -EINVAL);
@@ -3195,7 +3142,6 @@ static int __init obdecho_init(void)
 	struct lprocfs_static_vars lvars;
 	int rc;
 
-	ENTRY;
 	LCONSOLE_INFO("Echo OBD driver; http://www.lustre.org/\n");
 
 	LASSERT(PAGE_CACHE_SIZE % OBD_ECHO_BLOCK_SIZE == 0);
@@ -3205,7 +3151,7 @@ static int __init obdecho_init(void)
 
 	rc = echo_client_init();
 
-	RETURN(rc);
+	return rc;
 }
 
 static void /*__exit*/ obdecho_exit(void)
@@ -3217,7 +3163,9 @@ static void /*__exit*/ obdecho_exit(void)
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre Testing Echo OBD driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(LUSTRE_VERSION_STRING);
 
-cfs_module(obdecho, LUSTRE_VERSION_STRING, obdecho_init, obdecho_exit);
+module_init(obdecho_init);
+module_exit(obdecho_exit);
 
 /** @} echo_client */
diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c
index 198cf3b..90d24d8 100644
--- a/drivers/staging/lustre/lustre/osc/lproc_osc.c
+++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c
@@ -35,7 +35,6 @@
  */
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/version.h>
 #include <asm/statfs.h>
 #include <obd_cksum.h>
 #include <obd_class.h>
@@ -146,7 +145,7 @@ static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer,
 
 	if (pages_number <= 0 ||
 	    pages_number > OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_CACHE_SHIFT) ||
-	    pages_number > num_physpages / 4) /* 1/4 of RAM */
+	    pages_number > totalram_pages / 4) /* 1/4 of RAM */
 		return -ERANGE;
 
 	client_obd_list_lock(&cli->cl_loi_list_lock);
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index 0a0ec6f..00295da 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -540,7 +540,6 @@ int osc_extent_release(const struct lu_env *env, struct osc_extent *ext)
 {
 	struct osc_object *obj = ext->oe_obj;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(atomic_read(&ext->oe_users) > 0);
 	LASSERT(sanity_check(ext) == 0);
@@ -572,7 +571,7 @@ int osc_extent_release(const struct lu_env *env, struct osc_extent *ext)
 		osc_io_unplug_async(env, osc_cli(obj), obj);
 	}
 	osc_extent_put(env, ext);
-	RETURN(rc);
+	return rc;
 }
 
 static inline int overlapped(struct osc_extent *ex1, struct osc_extent *ex2)
@@ -602,11 +601,10 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
 	int	ppc_bits; /* pages per chunk bits */
 	int	chunk_mask;
 	int	rc;
-	ENTRY;
 
 	cur = osc_extent_alloc(obj);
 	if (cur == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	lock = cl_lock_at_pgoff(env, osc2cl(obj), index, NULL, 1, 0);
 	LASSERT(lock != NULL);
@@ -783,7 +781,6 @@ restart:
 
 		goto restart;
 	}
-	EXIT;
 
 out:
 	osc_extent_put(env, cur);
@@ -805,7 +802,6 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext,
 	int blocksize = cli->cl_import->imp_obd->obd_osfs.os_bsize ? : 4096;
 	__u64 last_off = 0;
 	int last_count = -1;
-	ENTRY;
 
 	OSC_EXTENT_DUMP(D_CACHE, ext, "extent finished.\n");
 
@@ -846,7 +842,7 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext,
 	osc_extent_remove(ext);
 	/* put the refcount for RPC */
 	osc_extent_put(env, ext);
-	RETURN(0);
+	return 0;
 }
 
 static int extent_wait_cb(struct osc_extent *ext, int state)
@@ -870,7 +866,6 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext,
 	struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL,
 						  LWI_ON_SIGNAL_NOOP, NULL);
 	int rc = 0;
-	ENTRY;
 
 	osc_object_lock(obj);
 	LASSERT(sanity_check_nolock(ext) == 0);
@@ -902,7 +897,7 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext,
 	}
 	if (rc == 0 && ext->oe_rc < 0)
 		rc = ext->oe_rc;
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -925,7 +920,6 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
 	int		    grants   = 0;
 	int		    nr_pages = 0;
 	int		    rc       = 0;
-	ENTRY;
 
 	LASSERT(sanity_check(ext) == 0);
 	LASSERT(ext->oe_state == OES_TRUNC);
@@ -1021,7 +1015,7 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
 out:
 	cl_io_fini(env, io);
 	cl_env_nested_put(&nest, env);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1036,7 +1030,6 @@ static int osc_extent_make_ready(const struct lu_env *env,
 	struct osc_object *obj = ext->oe_obj;
 	int page_count = 0;
 	int rc;
-	ENTRY;
 
 	/* we're going to grab page lock, so object lock must not be taken. */
 	LASSERT(sanity_check(ext) == 0);
@@ -1096,7 +1089,7 @@ static int osc_extent_make_ready(const struct lu_env *env,
 	/* get a refcount for RPC. */
 	osc_extent_get(ext);
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1115,7 +1108,6 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants)
 	pgoff_t end_index;
 	int chunksize = 1 << cli->cl_chunkbits;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(ext->oe_max_end >= index && ext->oe_start <= index);
 	osc_object_lock(obj);
@@ -1143,11 +1135,10 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants)
 	LASSERT(*grants >= 0);
 	EASSERTF(osc_extent_is_overlapped(obj, ext) == 0, ext,
 		 "overlapped after expanding for %lu.\n", index);
-	EXIT;
 
 out:
 	osc_object_unlock(obj);
-	RETURN(rc);
+	return rc;
 }
 
 static void osc_extent_tree_dump0(int level, struct osc_object *obj,
@@ -1207,11 +1198,10 @@ static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap,
 
 	LASSERT(cmd == OBD_BRW_WRITE); /* no cached reads */
 
-	ENTRY;
 	result = cl_page_make_ready(env, page, CRT_WRITE);
 	if (result == 0)
 		opg->ops_submit_time = cfs_time_current();
-	RETURN(result);
+	return result;
 }
 
 static int osc_refresh_count(const struct lu_env *env,
@@ -1255,8 +1245,6 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
 	enum cl_req_type   crt;
 	int srvlock;
 
-	ENTRY;
-
 	cmd &= ~OBD_BRW_NOQUOTA;
 	LASSERT(equi(page->cp_state == CPS_PAGEIN,  cmd == OBD_BRW_READ));
 	LASSERT(equi(page->cp_state == CPS_PAGEOUT, cmd == OBD_BRW_WRITE));
@@ -1305,7 +1293,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
 
 	cl_page_completion(env, page, crt, rc);
 
-	RETURN(0);
+	return 0;
 }
 
 #define OSC_DUMP_GRANT(cli, fmt, args...) do {				      \
@@ -1338,11 +1326,8 @@ static void osc_consume_write_grant(struct client_obd *cli,
 static void osc_release_write_grant(struct client_obd *cli,
 				    struct brw_page *pga)
 {
-	ENTRY;
-
 	LASSERT(spin_is_locked(&cli->cl_loi_list_lock.lock));
 	if (!(pga->flag & OBD_BRW_FROM_GRANT)) {
-		EXIT;
 		return;
 	}
 
@@ -1354,7 +1339,6 @@ static void osc_release_write_grant(struct client_obd *cli,
 		atomic_dec(&obd_dirty_transit_pages);
 		cli->cl_dirty_transit -= PAGE_CACHE_SIZE;
 	}
-	EXIT;
 }
 
 /**
@@ -1503,7 +1487,6 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
 	struct osc_cache_waiter ocw;
 	struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
 	int rc = -EDQUOT;
-	ENTRY;
 
 	OSC_DUMP_GRANT(cli, "need:%d.\n", bytes);
 
@@ -1557,11 +1540,10 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
 		if (osc_enter_cache_try(cli, oap, bytes, 0))
 			GOTO(out, rc = 0);
 	}
-	EXIT;
 out:
 	client_obd_list_unlock(&cli->cl_loi_list_lock);
 	OSC_DUMP_GRANT(cli, "returned %d.\n", rc);
-	RETURN(rc);
+	return rc;
 }
 
 /* caller must hold loi_list_lock */
@@ -1570,7 +1552,6 @@ void osc_wake_cache_waiters(struct client_obd *cli)
 	struct list_head *l, *tmp;
 	struct osc_cache_waiter *ocw;
 
-	ENTRY;
 	list_for_each_safe(l, tmp, &cli->cl_cache_waiters) {
 		ocw = list_entry(l, struct osc_cache_waiter, ocw_entry);
 		list_del_init(&ocw->ocw_entry);
@@ -1596,8 +1577,6 @@ wakeup:
 
 		wake_up(&ocw->ocw_waitq);
 	}
-
-	EXIT;
 }
 
 static int osc_max_rpc_in_flight(struct client_obd *cli, struct osc_object *osc)
@@ -1613,7 +1592,6 @@ static int osc_makes_rpc(struct client_obd *cli, struct osc_object *osc,
 			 int cmd)
 {
 	int invalid_import = 0;
-	ENTRY;
 
 	/* if we have an invalid import we want to drain the queued pages
 	 * by forcing them through rpcs that immediately fail and complete
@@ -1624,42 +1602,42 @@ static int osc_makes_rpc(struct client_obd *cli, struct osc_object *osc,
 
 	if (cmd & OBD_BRW_WRITE) {
 		if (atomic_read(&osc->oo_nr_writes) == 0)
-			RETURN(0);
+			return 0;
 		if (invalid_import) {
 			CDEBUG(D_CACHE, "invalid import forcing RPC\n");
-			RETURN(1);
+			return 1;
 		}
 		if (!list_empty(&osc->oo_hp_exts)) {
 			CDEBUG(D_CACHE, "high prio request forcing RPC\n");
-			RETURN(1);
+			return 1;
 		}
 		if (!list_empty(&osc->oo_urgent_exts)) {
 			CDEBUG(D_CACHE, "urgent request forcing RPC\n");
-			RETURN(1);
+			return 1;
 		}
 		/* trigger a write rpc stream as long as there are dirtiers
 		 * waiting for space.  as they're waiting, they're not going to
 		 * create more pages to coalesce with what's waiting.. */
 		if (!list_empty(&cli->cl_cache_waiters)) {
 			CDEBUG(D_CACHE, "cache waiters forcing RPC\n");
-			RETURN(1);
+			return 1;
 		}
 		if (atomic_read(&osc->oo_nr_writes) >=
 		    cli->cl_max_pages_per_rpc)
-			RETURN(1);
+			return 1;
 	} else {
 		if (atomic_read(&osc->oo_nr_reads) == 0)
-			RETURN(0);
+			return 0;
 		if (invalid_import) {
 			CDEBUG(D_CACHE, "invalid import forcing RPC\n");
-			RETURN(1);
+			return 1;
 		}
 		/* all read are urgent. */
 		if (!list_empty(&osc->oo_reading_exts))
-			RETURN(1);
+			return 1;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static void osc_update_pending(struct osc_object *obj, int cmd, int delta)
@@ -1757,7 +1735,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli,
 	struct lov_oinfo  *loi = osc->oo_oinfo;
 	__u64 xid = 0;
 
-	ENTRY;
 	if (oap->oap_request != NULL) {
 		xid = ptlrpc_req_xid(oap->oap_request);
 		ptlrpc_req_finished(oap->oap_request);
@@ -1781,8 +1758,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli,
 	if (rc)
 		CERROR("completion on oap %p obj %p returns %d.\n",
 		       oap, osc, rc);
-
-	EXIT;
 }
 
 /**
@@ -1795,14 +1770,13 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
 				    int *pc, unsigned int *max_pages)
 {
 	struct osc_extent *tmp;
-	ENTRY;
 
 	EASSERT((ext->oe_state == OES_CACHE || ext->oe_state == OES_LOCK_DONE),
 		ext);
 
 	*max_pages = max(ext->oe_mppr, *max_pages);
 	if (*pc + ext->oe_nr_pages > *max_pages)
-		RETURN(0);
+		return 0;
 
 	list_for_each_entry(tmp, rpclist, oe_link) {
 		EASSERT(tmp->oe_owner == current, tmp);
@@ -1815,7 +1789,7 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
 
 		if (tmp->oe_srvlock != ext->oe_srvlock ||
 		    !tmp->oe_grants != !ext->oe_grants)
-			RETURN(0);
+			return 0;
 
 		/* remove break for strict check */
 		break;
@@ -1824,7 +1798,7 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
 	*pc += ext->oe_nr_pages;
 	list_move_tail(&ext->oe_link, rpclist);
 	ext->oe_owner = current;
-	RETURN(1);
+	return 1;
 }
 
 /**
@@ -1913,7 +1887,6 @@ osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli,
 	obd_count page_count = 0;
 	int srvlock = 0;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(osc_object_is_locked(osc));
 
@@ -1921,7 +1894,7 @@ osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli,
 	LASSERT(equi(page_count == 0, list_empty(&rpclist)));
 
 	if (list_empty(&rpclist))
-		RETURN(0);
+		return 0;
 
 	osc_update_pending(osc, OBD_BRW_WRITE, -page_count);
 
@@ -1962,7 +1935,7 @@ osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli,
 	}
 
 	osc_object_lock(osc);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1985,7 +1958,6 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli,
 	int page_count = 0;
 	unsigned int max_pages = cli->cl_max_pages_per_rpc;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(osc_object_is_locked(osc));
 	list_for_each_entry_safe(ext, next,
@@ -2010,7 +1982,7 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli,
 
 		osc_object_lock(osc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 #define list_to_obj(list, item) ({					      \
@@ -2023,15 +1995,13 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli,
  * we could be sending.  These lists are maintained by osc_makes_rpc(). */
 static struct osc_object *osc_next_obj(struct client_obd *cli)
 {
-	ENTRY;
-
 	/* First return objects that have blocked locks so that they
 	 * will be flushed quickly and other clients can get the lock,
 	 * then objects which have pages ready to be stuffed into RPCs */
 	if (!list_empty(&cli->cl_loi_hp_ready_list))
-		RETURN(list_to_obj(&cli->cl_loi_hp_ready_list, hp_ready_item));
+		return list_to_obj(&cli->cl_loi_hp_ready_list, hp_ready_item);
 	if (!list_empty(&cli->cl_loi_ready_list))
-		RETURN(list_to_obj(&cli->cl_loi_ready_list, ready_item));
+		return list_to_obj(&cli->cl_loi_ready_list, ready_item);
 
 	/* then if we have cache waiters, return all objects with queued
 	 * writes.  This is especially important when many small files
@@ -2039,19 +2009,17 @@ static struct osc_object *osc_next_obj(struct client_obd *cli)
 	 * they don't pass the nr_pending/object threshhold */
 	if (!list_empty(&cli->cl_cache_waiters) &&
 	    !list_empty(&cli->cl_loi_write_list))
-		RETURN(list_to_obj(&cli->cl_loi_write_list, write_item));
+		return list_to_obj(&cli->cl_loi_write_list, write_item);
 
 	/* then return all queued objects when we have an invalid import
 	 * so that they get flushed */
 	if (cli->cl_import == NULL || cli->cl_import->imp_invalid) {
 		if (!list_empty(&cli->cl_loi_write_list))
-			RETURN(list_to_obj(&cli->cl_loi_write_list,
-					   write_item));
+			return list_to_obj(&cli->cl_loi_write_list, write_item);
 		if (!list_empty(&cli->cl_loi_read_list))
-			RETURN(list_to_obj(&cli->cl_loi_read_list,
-					   read_item));
+			return list_to_obj(&cli->cl_loi_read_list, read_item);
 	}
-	RETURN(NULL);
+	return NULL;
 }
 
 /* called with the loi list lock held */
@@ -2060,11 +2028,10 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli,
 {
 	struct osc_object *osc;
 	int rc = 0;
-	ENTRY;
 
 	while ((osc = osc_next_obj(cli)) != NULL) {
 		struct cl_object *obj = osc2cl(osc);
-		struct lu_ref_link *link;
+		struct lu_ref_link link;
 
 		OSC_IO_DEBUG(osc, "%lu in flight\n", rpcs_in_flight(cli));
 
@@ -2075,7 +2042,8 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli,
 
 		cl_object_get(obj);
 		client_obd_list_unlock(&cli->cl_loi_list_lock);
-		link = lu_object_ref_add(&obj->co_lu, "check", current);
+		lu_object_ref_add_at(&obj->co_lu, &link, "check",
+				     current);
 
 		/* attempt some read/write balancing by alternating between
 		 * reads and writes in an object.  The makes_rpc checks here
@@ -2116,7 +2084,8 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli,
 		osc_object_unlock(osc);
 
 		osc_list_maint(cli, osc);
-		lu_object_ref_del_at(&obj->co_lu, link, "check", current);
+		lu_object_ref_del_at(&obj->co_lu, &link, "check",
+				     current);
 		cl_object_put(env, obj);
 
 		client_obd_list_lock(&cli->cl_loi_list_lock);
@@ -2165,7 +2134,6 @@ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops,
 {
 	struct obd_export     *exp = osc_export(osc);
 	struct osc_async_page *oap = &ops->ops_oap;
-	ENTRY;
 
 	if (!page)
 		return cfs_size_round(sizeof(*oap));
@@ -2187,7 +2155,7 @@ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops,
 	spin_lock_init(&oap->oap_lock);
 	CDEBUG(D_INFO, "oap %p page %p obj off "LPU64"\n",
 	       oap, page, oap->oap_obj_off);
-	RETURN(0);
+	return 0;
 }
 
 int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
@@ -2204,17 +2172,16 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
 	int    cmd = OBD_BRW_WRITE;
 	int    need_release = 0;
 	int    rc = 0;
-	ENTRY;
 
 	if (oap->oap_magic != OAP_MAGIC)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if (cli->cl_import == NULL || cli->cl_import->imp_invalid)
-		RETURN(-EIO);
+		return -EIO;
 
 	if (!list_empty(&oap->oap_pending_item) ||
 	    !list_empty(&oap->oap_rpc_item))
-		RETURN(-EBUSY);
+		return -EBUSY;
 
 	/* Set the OBD_BRW_SRVLOCK before the page is queued. */
 	brw_flags |= ops->ops_srvlock ? OBD_BRW_SRVLOCK : 0;
@@ -2242,7 +2209,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
 		if (rc == 0 && osc_quota_chkdq(cli, qid) == NO_QUOTA)
 			rc = -EDQUOT;
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
 	oap->oap_cmd = cmd;
@@ -2350,7 +2317,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
 		list_add_tail(&oap->oap_pending_item, &ext->oe_pages);
 		osc_object_unlock(osc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int osc_teardown_async_page(const struct lu_env *env,
@@ -2359,7 +2326,6 @@ int osc_teardown_async_page(const struct lu_env *env,
 	struct osc_async_page *oap = &ops->ops_oap;
 	struct osc_extent     *ext = NULL;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(oap->oap_magic == OAP_MAGIC);
 
@@ -2384,7 +2350,7 @@ int osc_teardown_async_page(const struct lu_env *env,
 	osc_object_unlock(obj);
 	if (ext != NULL)
 		osc_extent_put(env, ext);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2404,7 +2370,6 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
 	struct osc_async_page *oap = &ops->ops_oap;
 	bool unplug = false;
 	int rc = 0;
-	ENTRY;
 
 	osc_object_lock(obj);
 	ext = osc_extent_lookup(obj, index);
@@ -2454,7 +2419,6 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
 		unplug = true;
 	}
 	rc = 0;
-	EXIT;
 
 out:
 	osc_object_unlock(obj);
@@ -2482,7 +2446,6 @@ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops)
 	pgoff_t index = oap2cl_page(oap)->cp_index;
 	int     rc = -EBUSY;
 	int     cmd;
-	ENTRY;
 
 	LASSERT(!oap->oap_interrupted);
 	oap->oap_interrupted = 1;
@@ -2526,7 +2489,7 @@ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops)
 	}
 
 	osc_list_maint(cli, obj);
-	RETURN(rc);
+	return rc;
 }
 
 int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
@@ -2539,7 +2502,6 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
 	int     mppr       = cli->cl_max_pages_per_rpc;
 	pgoff_t start      = CL_PAGE_EOF;
 	pgoff_t end	= 0;
-	ENTRY;
 
 	list_for_each_entry(oap, list, oap_pending_item) {
 		struct cl_page *cp = oap2cl_page(oap);
@@ -2557,7 +2519,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
 			list_del_init(&oap->oap_pending_item);
 			osc_ap_completion(env, cli, oap, 0, -ENOMEM);
 		}
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	ext->oe_rw = !!(cmd & OBD_BRW_READ);
@@ -2583,7 +2545,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
 	osc_object_unlock(obj);
 
 	osc_io_unplug(env, cli, obj, PDL_POLICY_ROUND);
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -2599,7 +2561,6 @@ int osc_cache_truncate_start(const struct lu_env *env, struct osc_io *oio,
 	LIST_HEAD(list);
 	int result = 0;
 	bool partial;
-	ENTRY;
 
 	/* pages with index greater or equal to index will be truncated. */
 	index = cl_index(osc2cl(obj), size);
@@ -2705,7 +2666,7 @@ again:
 		waiting = NULL;
 		goto again;
 	}
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -2756,7 +2717,6 @@ int osc_cache_wait_range(const struct lu_env *env, struct osc_object *obj,
 	struct osc_extent *ext;
 	pgoff_t index = start;
 	int     result = 0;
-	ENTRY;
 
 again:
 	osc_object_lock(obj);
@@ -2794,7 +2754,7 @@ again:
 	osc_object_unlock(obj);
 
 	OSC_IO_DEBUG(obj, "sync file range.\n");
-	RETURN(result);
+	return result;
 }
 
 /**
@@ -2813,7 +2773,6 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj,
 	LIST_HEAD(discard_list);
 	bool unplug = false;
 	int result = 0;
-	ENTRY;
 
 	osc_object_lock(obj);
 	ext = osc_extent_search(obj, start);
@@ -2910,7 +2869,7 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj,
 	}
 
 	OSC_IO_DEBUG(obj, "cache page out.\n");
-	RETURN(result);
+	return result;
 }
 
 /** @} osc */
diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h
index 158e8ff..a3aa9b6 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h
+++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h
@@ -374,7 +374,7 @@ struct osc_page {
 	/**
 	 * Thread that submitted this page for transfer. For debugging.
 	 */
-	task_t	   *ops_submitter;
+	struct task_struct	*ops_submitter;
 	/**
 	 * Submit time - the time when the page is starting RPC. For debugging.
 	 */
@@ -660,7 +660,7 @@ struct osc_extent {
 	/** lock covering this extent */
 	struct cl_lock    *oe_osclock;
 	/** terminator of this extent. Must be true if this extent is in IO. */
-	task_t	*oe_owner;
+	struct task_struct	*oe_owner;
 	/** return value of writeback. If somebody is waiting for this extent,
 	 * this value can be known by outside world. */
 	int		oe_rc;
diff --git a/drivers/staging/lustre/lustre/osc/osc_dev.c b/drivers/staging/lustre/lustre/osc/osc_dev.c
index 4208ddf..35f2578 100644
--- a/drivers/staging/lustre/lustre/osc/osc_dev.c
+++ b/drivers/staging/lustre/lustre/osc/osc_dev.c
@@ -171,8 +171,7 @@ LU_TYPE_INIT_FINI(osc, &osc_key, &osc_session_key);
 static int osc_cl_process_config(const struct lu_env *env,
 				 struct lu_device *d, struct lustre_cfg *cfg)
 {
-	ENTRY;
-	RETURN(osc_process_config_base(d->ld_obd, cfg));
+	return osc_process_config_base(d->ld_obd, cfg);
 }
 
 static const struct lu_device_operations osc_lu_ops = {
@@ -188,7 +187,7 @@ static const struct cl_device_operations osc_cl_ops = {
 static int osc_device_init(const struct lu_env *env, struct lu_device *d,
 			   const char *name, struct lu_device *next)
 {
-	RETURN(0);
+	return 0;
 }
 
 static struct lu_device *osc_device_fini(const struct lu_env *env,
@@ -218,7 +217,7 @@ static struct lu_device *osc_device_alloc(const struct lu_env *env,
 
 	OBD_ALLOC_PTR(od);
 	if (od == NULL)
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 
 	cl_device_init(&od->od_cl, t);
 	d = osc2lu_dev(od);
@@ -231,10 +230,10 @@ static struct lu_device *osc_device_alloc(const struct lu_env *env,
 	rc = osc_setup(obd, cfg);
 	if (rc) {
 		osc_device_free(env, d);
-		RETURN(ERR_PTR(rc));
+		return ERR_PTR(rc);
 	}
 	od->od_exp = obd->obd_self_export;
-	RETURN(d);
+	return d;
 }
 
 static const struct lu_device_type_operations osc_device_type_ops = {
diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c
index 1b27704..3aeaf84 100644
--- a/drivers/staging/lustre/lustre/osc/osc_io.c
+++ b/drivers/staging/lustre/lustre/osc/osc_io.c
@@ -261,7 +261,6 @@ static int osc_io_prepare_write(const struct lu_env *env,
 	struct obd_import *imp = class_exp2cliimp(dev->od_exp);
 	struct osc_io     *oio = cl2osc_io(env, ios);
 	int result = 0;
-	ENTRY;
 
 	/*
 	 * This implements OBD_BRW_CHECK logic from old client.
@@ -276,7 +275,7 @@ static int osc_io_prepare_write(const struct lu_env *env,
 		 * [from, to) bytes of this page to OST. -jay */
 		cl_page_export(env, slice->cpl_page, 1);
 
-	RETURN(result);
+	return result;
 }
 
 static int osc_io_commit_write(const struct lu_env *env,
@@ -288,7 +287,6 @@ static int osc_io_commit_write(const struct lu_env *env,
 	struct osc_page       *opg = cl2osc_page(slice);
 	struct osc_object     *obj = cl2osc(opg->ops_cl.cpl_obj);
 	struct osc_async_page *oap = &opg->ops_oap;
-	ENTRY;
 
 	LASSERT(to > 0);
 	/*
@@ -306,7 +304,7 @@ static int osc_io_commit_write(const struct lu_env *env,
 		/* see osc_io_prepare_write() for lockless io handling. */
 		cl_page_clip(env, slice->cpl_page, from, to);
 
-	RETURN(0);
+	return 0;
 }
 
 static int osc_io_fault_start(const struct lu_env *env,
@@ -315,8 +313,6 @@ static int osc_io_fault_start(const struct lu_env *env,
 	struct cl_io       *io;
 	struct cl_fault_io *fio;
 
-	ENTRY;
-
 	io  = ios->cis_io;
 	fio = &io->u.ci_fault;
 	CDEBUG(D_INFO, "%lu %d %d\n",
@@ -329,7 +325,7 @@ static int osc_io_fault_start(const struct lu_env *env,
 	if (fio->ft_writable)
 		osc_page_touch_at(env, ios->cis_obj,
 				  fio->ft_index, fio->ft_nob);
-	RETURN(0);
+	return 0;
 }
 
 static int osc_async_upcall(void *a, int rc)
@@ -517,19 +513,18 @@ static int osc_io_read_start(const struct lu_env *env,
 	struct cl_object *obj   = slice->cis_obj;
 	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
 	int	      result = 0;
-	ENTRY;
 
 	if (oio->oi_lockless == 0) {
 		cl_object_attr_lock(obj);
 		result = cl_object_attr_get(env, obj, attr);
 		if (result == 0) {
-			attr->cat_atime = LTIME_S(CFS_CURRENT_TIME);
+			attr->cat_atime = LTIME_S(CURRENT_TIME);
 			result = cl_object_attr_set(env, obj, attr,
 						    CAT_ATIME);
 		}
 		cl_object_attr_unlock(obj);
 	}
-	RETURN(result);
+	return result;
 }
 
 static int osc_io_write_start(const struct lu_env *env,
@@ -539,7 +534,6 @@ static int osc_io_write_start(const struct lu_env *env,
 	struct cl_object *obj   = slice->cis_obj;
 	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
 	int	      result = 0;
-	ENTRY;
 
 	if (oio->oi_lockless == 0) {
 		OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_DELAY_SETTIME, 1);
@@ -547,13 +541,13 @@ static int osc_io_write_start(const struct lu_env *env,
 		result = cl_object_attr_get(env, obj, attr);
 		if (result == 0) {
 			attr->cat_mtime = attr->cat_ctime =
-				LTIME_S(CFS_CURRENT_TIME);
+				LTIME_S(CURRENT_TIME);
 			result = cl_object_attr_set(env, obj, attr,
 						    CAT_MTIME | CAT_CTIME);
 		}
 		cl_object_attr_unlock(obj);
 	}
-	RETURN(result);
+	return result;
 }
 
 static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
@@ -565,7 +559,6 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
 	struct lov_oinfo *loi   = obj->oo_oinfo;
 	struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
 	int rc = 0;
-	ENTRY;
 
 	memset(oa, 0, sizeof(*oa));
 	oa->o_oi = loi->loi_oi;
@@ -585,7 +578,7 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
 
 	rc = osc_sync_base(osc_export(obj), oinfo, osc_async_upcall, cbargs,
 			   PTLRPCD_SET);
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_io_fsync_start(const struct lu_env *env,
@@ -598,7 +591,6 @@ static int osc_io_fsync_start(const struct lu_env *env,
 	pgoff_t start  = cl_index(obj, fio->fi_start);
 	pgoff_t end    = cl_index(obj, fio->fi_end);
 	int     result = 0;
-	ENTRY;
 
 	if (fio->fi_end == OBD_OBJECT_EOF)
 		end = CL_PAGE_EOF;
@@ -625,7 +617,7 @@ static int osc_io_fsync_start(const struct lu_env *env,
 			result = rc;
 	}
 
-	RETURN(result);
+	return result;
 }
 
 static void osc_io_fsync_end(const struct lu_env *env,
@@ -785,7 +777,7 @@ static void osc_req_attr_set(const struct lu_env *env,
 					      "no cover page!\n");
 			CL_PAGE_DEBUG(D_ERROR, env, apage,
 				      "dump uncover page!\n");
-			libcfs_debug_dumpstack(NULL);
+			dump_stack();
 			LBUG();
 		}
 
diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c
index 640bc3d..5d7bdbf 100644
--- a/drivers/staging/lustre/lustre/osc/osc_lock.c
+++ b/drivers/staging/lustre/lustre/osc/osc_lock.c
@@ -89,35 +89,49 @@ static struct ldlm_lock *osc_handle_ptr(struct lustre_handle *handle)
  */
 static int osc_lock_invariant(struct osc_lock *ols)
 {
-	struct ldlm_lock *lock	= osc_handle_ptr(&ols->ols_handle);
-	struct ldlm_lock *olock       = ols->ols_lock;
-	int	       handle_used = lustre_handle_is_used(&ols->ols_handle);
-
-	return
-		ergo(osc_lock_is_lockless(ols),
-		     ols->ols_locklessable && ols->ols_lock == NULL)  ||
-		(ergo(olock != NULL, handle_used) &&
-		 ergo(olock != NULL,
-		      olock->l_handle.h_cookie == ols->ols_handle.cookie) &&
-		 /*
-		  * Check that ->ols_handle and ->ols_lock are consistent, but
-		  * take into account that they are set at the different time.
-		  */
-		 ergo(handle_used,
-		      ergo(lock != NULL && olock != NULL, lock == olock) &&
-		      ergo(lock == NULL, olock == NULL)) &&
-		 ergo(ols->ols_state == OLS_CANCELLED,
-		      olock == NULL && !handle_used) &&
-		 /*
-		  * DLM lock is destroyed only after we have seen cancellation
-		  * ast.
-		  */
-		 ergo(olock != NULL && ols->ols_state < OLS_CANCELLED,
-		      !olock->l_destroyed) &&
-		 ergo(ols->ols_state == OLS_GRANTED,
-		      olock != NULL &&
-		      olock->l_req_mode == olock->l_granted_mode &&
-		      ols->ols_hold));
+	struct ldlm_lock *lock	      = osc_handle_ptr(&ols->ols_handle);
+	struct ldlm_lock *olock	      = ols->ols_lock;
+	int		  handle_used = lustre_handle_is_used(&ols->ols_handle);
+
+	if (ergo(osc_lock_is_lockless(ols),
+		 ols->ols_locklessable && ols->ols_lock == NULL))
+		return 1;
+
+	/*
+	 * If all the following "ergo"s are true, return 1, otherwise 0
+	 */
+	if (! ergo(olock != NULL, handle_used))
+		return 0;
+
+	if (! ergo(olock != NULL,
+		   olock->l_handle.h_cookie == ols->ols_handle.cookie))
+		return 0;
+
+	if (! ergo(handle_used,
+		   ergo(lock != NULL && olock != NULL, lock == olock) &&
+		   ergo(lock == NULL, olock == NULL)))
+		return 0;
+	/*
+	 * Check that ->ols_handle and ->ols_lock are consistent, but
+	 * take into account that they are set at the different time.
+	 */
+	if (! ergo(ols->ols_state == OLS_CANCELLED,
+		   olock == NULL && !handle_used))
+		return 0;
+	/*
+	 * DLM lock is destroyed only after we have seen cancellation
+	 * ast.
+	 */
+	if (! ergo(olock != NULL && ols->ols_state < OLS_CANCELLED,
+		   ((olock->l_flags & LDLM_FL_DESTROYED) == 0)))
+		return 0;
+
+	if (! ergo(ols->ols_state == OLS_GRANTED,
+		   olock != NULL &&
+		   olock->l_req_mode == olock->l_granted_mode &&
+		   ols->ols_hold))
+		return 0;
+	return 1;
 }
 
 /*****************************************************************************
@@ -261,7 +275,7 @@ static __u64 osc_enq2ldlm_flags(__u32 enqflags)
 	if (enqflags & CEF_ASYNC)
 		result |= LDLM_FL_HAS_INTENT;
 	if (enqflags & CEF_DISCARD_DATA)
-		result |= LDLM_AST_DISCARD_DATA;
+		result |= LDLM_FL_AST_DISCARD_DATA;
 	return result;
 }
 
@@ -329,10 +343,8 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck,
 	struct cl_attr    *attr;
 	unsigned	   valid;
 
-	ENTRY;
-
 	if (!(olck->ols_flags & LDLM_FL_LVB_READY))
-		RETURN_EXIT;
+		return;
 
 	lvb   = &olck->ols_lvb;
 	obj   = olck->ols_cl.cls_obj;
@@ -378,8 +390,6 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck,
 		cl_object_attr_set(env, obj, attr, valid);
 
 	cl_object_attr_unlock(obj);
-
-	EXIT;
 }
 
 /**
@@ -398,7 +408,6 @@ static void osc_lock_granted(const struct lu_env *env, struct osc_lock *olck,
 
 	LASSERT(dlmlock->l_granted_mode == dlmlock->l_req_mode);
 
-	ENTRY;
 	if (olck->ols_state < OLS_GRANTED) {
 		lock  = olck->ols_cl.cls_lock;
 		ext   = &dlmlock->l_policy_data.l_extent;
@@ -428,7 +437,6 @@ static void osc_lock_granted(const struct lu_env *env, struct osc_lock *olck,
 		LINVRNT(osc_lock_invariant(olck));
 		lock_res_and_lock(dlmlock);
 	}
-	EXIT;
 }
 
 static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck)
@@ -436,8 +444,6 @@ static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck)
 {
 	struct ldlm_lock *dlmlock;
 
-	ENTRY;
-
 	dlmlock = ldlm_handle2lock_long(&olck->ols_handle, 0);
 	LASSERT(dlmlock != NULL);
 
@@ -483,7 +489,6 @@ static int osc_lock_upcall(void *cookie, int errcode)
 	struct lu_env	   *env;
 	struct cl_env_nest       nest;
 
-	ENTRY;
 	env = cl_env_nested_get(&nest);
 	if (!IS_ERR(env)) {
 		int rc;
@@ -575,7 +580,7 @@ static int osc_lock_upcall(void *cookie, int errcode)
 		/* should never happen, similar to osc_ldlm_blocking_ast(). */
 		LBUG();
 	}
-	RETURN(errcode);
+	return errcode;
 }
 
 /**
@@ -896,55 +901,6 @@ static unsigned long osc_lock_weigh(const struct lu_env *env,
 	return cl_object_header(slice->cls_obj)->coh_pages;
 }
 
-/**
- * Get the weight of dlm lock for early cancellation.
- *
- * XXX: it should return the pages covered by this \a dlmlock.
- */
-static unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock)
-{
-	struct cl_env_nest       nest;
-	struct lu_env	   *env;
-	struct osc_lock	 *lock;
-	struct cl_lock	  *cll;
-	unsigned long	    weight;
-	ENTRY;
-
-	might_sleep();
-	/*
-	 * osc_ldlm_weigh_ast has a complex context since it might be called
-	 * because of lock canceling, or from user's input. We have to make
-	 * a new environment for it. Probably it is implementation safe to use
-	 * the upper context because cl_lock_put don't modify environment
-	 * variables. But in case of ..
-	 */
-	env = cl_env_nested_get(&nest);
-	if (IS_ERR(env))
-		/* Mostly because lack of memory, tend to eliminate this lock*/
-		RETURN(0);
-
-	LASSERT(dlmlock->l_resource->lr_type == LDLM_EXTENT);
-	lock = osc_ast_data_get(dlmlock);
-	if (lock == NULL) {
-		/* cl_lock was destroyed because of memory pressure.
-		 * It is much reasonable to assign this type of lock
-		 * a lower cost.
-		 */
-		GOTO(out, weight = 0);
-	}
-
-	cll = lock->ols_cl.cls_lock;
-	cl_lock_mutex_get(env, cll);
-	weight = cl_lock_weigh(env, cll);
-	cl_lock_mutex_put(env, cll);
-	osc_ast_data_put(env, lock);
-	EXIT;
-
-out:
-	cl_env_nested_put(&nest, env);
-	return weight;
-}
-
 static void osc_lock_build_einfo(const struct lu_env *env,
 				 const struct cl_lock *clock,
 				 struct osc_lock *lock,
@@ -966,7 +922,6 @@ static void osc_lock_build_einfo(const struct lu_env *env,
 	einfo->ei_cb_bl  = osc_ldlm_blocking_ast;
 	einfo->ei_cb_cp  = osc_ldlm_completion_ast;
 	einfo->ei_cb_gl  = osc_ldlm_glimpse_ast;
-	einfo->ei_cb_wg  = osc_ldlm_weigh_ast;
 	einfo->ei_cbdata = lock; /* value to be put into ->l_ast_data */
 }
 
@@ -1059,7 +1014,6 @@ static int osc_lock_enqueue_wait(const struct lu_env *env,
 	struct cl_lock	  *conflict= NULL;
 	int lockless		     = osc_lock_is_lockless(olck);
 	int rc			   = 0;
-	ENTRY;
 
 	LASSERT(cl_lock_is_mutexed(lock));
 
@@ -1130,7 +1084,7 @@ static int osc_lock_enqueue_wait(const struct lu_env *env,
 			rc = CLO_WAIT;
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1154,7 +1108,6 @@ static int osc_lock_enqueue(const struct lu_env *env,
 	struct osc_lock	  *ols     = cl2osc_lock(slice);
 	struct cl_lock	   *lock    = ols->ols_cl.cls_lock;
 	int result;
-	ENTRY;
 
 	LASSERT(cl_lock_is_mutexed(lock));
 	LASSERTF(ols->ols_state == OLS_NEW,
@@ -1207,7 +1160,7 @@ static int osc_lock_enqueue(const struct lu_env *env,
 		}
 	}
 	LASSERT(ergo(ols->ols_glimpse, !osc_lock_is_lockless(ols)));
-	RETURN(result);
+	return result;
 }
 
 static int osc_lock_wait(const struct lu_env *env,
@@ -1298,7 +1251,6 @@ static int osc_lock_flush(struct osc_lock *ols, int discard)
 	struct cl_env_nest    nest;
 	struct lu_env	*env;
 	int result = 0;
-	ENTRY;
 
 	env = cl_env_nested_get(&nest);
 	if (!IS_ERR(env)) {
@@ -1328,7 +1280,7 @@ static int osc_lock_flush(struct osc_lock *ols, int discard)
 		ols->ols_flush = 1;
 		LINVRNT(!osc_lock_has_pages(ols));
 	}
-	RETURN(result);
+	return result;
 }
 
 /**
diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c
index ca94e63..9d34de8 100644
--- a/drivers/staging/lustre/lustre/osc/osc_object.c
+++ b/drivers/staging/lustre/lustre/osc/osc_object.c
@@ -191,10 +191,9 @@ static int osc_object_glimpse(const struct lu_env *env,
 {
 	struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo;
 
-	ENTRY;
 	lvb->lvb_size   = oinfo->loi_kms;
 	lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks;
-	RETURN(0);
+	return 0;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c
index baba959..d272322 100644
--- a/drivers/staging/lustre/lustre/osc/osc_page.c
+++ b/drivers/staging/lustre/lustre/osc/osc_page.c
@@ -219,7 +219,6 @@ static int osc_page_cache_add(const struct lu_env *env,
 	struct osc_io   *oio = osc_env_io(env);
 	struct osc_page *opg = cl2osc_page(slice);
 	int result;
-	ENTRY;
 
 	LINVRNT(osc_page_protected(env, opg, CLM_WRITE, 0));
 
@@ -240,7 +239,7 @@ static int osc_page_cache_add(const struct lu_env *env,
 		}
 	}
 
-	RETURN(result);
+	return result;
 }
 
 void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj,
@@ -294,7 +293,6 @@ static int osc_page_is_under_lock(const struct lu_env *env,
 	struct cl_lock *lock;
 	int	     result = -ENODATA;
 
-	ENTRY;
 	lock = cl_lock_at_page(env, slice->cpl_obj, slice->cpl_page,
 			       NULL, 1, 0);
 	if (lock != NULL) {
@@ -302,7 +300,7 @@ static int osc_page_is_under_lock(const struct lu_env *env,
 			result = -EBUSY;
 		cl_lock_put(env, lock);
 	}
-	RETURN(result);
+	return result;
 }
 
 static void osc_page_disown(const struct lu_env *env,
@@ -421,7 +419,6 @@ static void osc_page_delete(const struct lu_env *env,
 
 	LINVRNT(opg->ops_temp || osc_page_protected(env, opg, CLM_READ, 1));
 
-	ENTRY;
 	CDEBUG(D_TRACE, "%p\n", opg);
 	osc_page_transfer_put(env, opg);
 	rc = osc_teardown_async_page(env, obj, opg);
@@ -440,7 +437,6 @@ static void osc_page_delete(const struct lu_env *env,
 	spin_unlock(&obj->oo_seatbelt);
 
 	osc_lru_del(osc_cli(obj), opg, true);
-	EXIT;
 }
 
 void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice,
@@ -481,9 +477,9 @@ static int osc_page_flush(const struct lu_env *env,
 {
 	struct osc_page *opg = cl2osc_page(slice);
 	int rc = 0;
-	ENTRY;
+
 	rc = osc_flush_async_page(env, io, opg);
-	RETURN(rc);
+	return rc;
 }
 
 static const struct cl_page_operations osc_page_ops = {
@@ -586,7 +582,7 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg,
  * at any time.
  */
 
-static CFS_DECL_WAITQ(osc_lru_waitq);
+static DECLARE_WAIT_QUEUE_HEAD(osc_lru_waitq);
 static atomic_t osc_lru_waiters = ATOMIC_INIT(0);
 /* LRU pages are freed in batch mode. OSC should at least free this
  * number of pages to avoid running out of LRU budget, and.. */
@@ -666,15 +662,14 @@ int osc_lru_shrink(struct client_obd *cli, int target)
 	int count = 0;
 	int index = 0;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(atomic_read(&cli->cl_lru_in_list) >= 0);
 	if (atomic_read(&cli->cl_lru_in_list) == 0 || target <= 0)
-		RETURN(0);
+		return 0;
 
 	env = cl_env_nested_get(&nest);
 	if (IS_ERR(env))
-		RETURN(PTR_ERR(env));
+		return PTR_ERR(env);
 
 	pvec = osc_env_info(env)->oti_pvec;
 	io = &osc_env_info(env)->oti_io;
@@ -757,7 +752,7 @@ int osc_lru_shrink(struct client_obd *cli, int target)
 	cl_env_nested_put(&nest, env);
 
 	atomic_dec(&cli->cl_lru_shrinkers);
-	RETURN(count > 0 ? count : rc);
+	return count > 0 ? count : rc;
 }
 
 static void osc_lru_add(struct client_obd *cli, struct osc_page *opg)
@@ -881,13 +876,12 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj,
 	struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
 	struct client_obd *cli = osc_cli(obj);
 	int rc = 0;
-	ENTRY;
 
 	if (cli->cl_cache == NULL) /* shall not be in LRU */
-		RETURN(0);
+		return 0;
 
 	LASSERT(atomic_read(cli->cl_lru_left) >= 0);
-	while (!cfs_atomic_add_unless(cli->cl_lru_left, -1, 0)) {
+	while (!atomic_add_unless(cli->cl_lru_left, -1, 0)) {
 		int gen;
 
 		/* run out of LRU spaces, try to drop some by itself */
@@ -921,7 +915,7 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj,
 		rc = 0;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /** @} osc */
diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c
index 69caab7..9720c0e 100644
--- a/drivers/staging/lustre/lustre/osc/osc_quota.c
+++ b/drivers/staging/lustre/lustre/osc/osc_quota.c
@@ -45,7 +45,6 @@ static inline struct osc_quota_info *osc_oqi_alloc(obd_uid id)
 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
 {
 	int type;
-	ENTRY;
 
 	for (type = 0; type < MAXQUOTAS; type++) {
 		struct osc_quota_info *oqi;
@@ -62,11 +61,11 @@ int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
 			 * quota space on this OST */
 			CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
 			       type == USRQUOTA ? "user" : "grout", qid[type]);
-			RETURN(NO_QUOTA);
+			return NO_QUOTA;
 		}
 	}
 
-	RETURN(QUOTA_OK);
+	return QUOTA_OK;
 }
 
 #define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
@@ -79,10 +78,9 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
 {
 	int type;
 	int rc = 0;
-	ENTRY;
 
 	if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
-		RETURN(0);
+		return 0;
 
 	for (type = 0; type < MAXQUOTAS; type++) {
 		struct osc_quota_info *oqi;
@@ -134,7 +132,7 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
 		}
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -211,7 +209,6 @@ int osc_quota_setup(struct obd_device *obd)
 {
 	struct client_obd *cli = &obd->u.cli;
 	int i, type;
-	ENTRY;
 
 	for (type = 0; type < MAXQUOTAS; type++) {
 		cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
@@ -228,24 +225,23 @@ int osc_quota_setup(struct obd_device *obd)
 	}
 
 	if (type == MAXQUOTAS)
-		RETURN(0);
+		return 0;
 
 	for (i = 0; i < type; i++)
 		cfs_hash_putref(cli->cl_quota_hash[i]);
 
-	RETURN(-ENOMEM);
+	return -ENOMEM;
 }
 
 int osc_quota_cleanup(struct obd_device *obd)
 {
 	struct client_obd     *cli = &obd->u.cli;
 	int type;
-	ENTRY;
 
 	for (type = 0; type < MAXQUOTAS; type++)
 		cfs_hash_putref(cli->cl_quota_hash[type]);
 
-	RETURN(0);
+	return 0;
 }
 
 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
@@ -254,13 +250,12 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
 	struct ptlrpc_request *req;
 	struct obd_quotactl   *oqc;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
 					OST_QUOTACTL);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
 	*oqc = *oqctl;
@@ -282,7 +277,7 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
 	}
 	ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
@@ -292,13 +287,12 @@ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
 	struct ptlrpc_request   *req;
 	struct obd_quotactl     *body;
 	int		      rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
 					&RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION,
 					OST_QUOTACHECK);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
 	*body = *oqctl;
@@ -312,14 +306,13 @@ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
 	if (rc)
 		cli->cl_qchk_stat = rc;
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
 {
 	struct client_obd *cli = &exp->exp_obd->u.cli;
 	int rc;
-	ENTRY;
 
 	qchk->obd_uuid = cli->cl_target_uuid;
 	memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME));
@@ -328,5 +321,5 @@ int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
 	/* the client is not the previous one */
 	if (rc == CL_NOT_QUOTACHECKED)
 		rc = -EINTR;
-	RETURN(rc);
+	return rc;
 }
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index 53d6a35..ee6707a 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -69,30 +69,29 @@ static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 		      struct lov_stripe_md *lsm)
 {
 	int lmm_size;
-	ENTRY;
 
 	lmm_size = sizeof(**lmmp);
 	if (lmmp == NULL)
-		RETURN(lmm_size);
+		return lmm_size;
 
 	if (*lmmp != NULL && lsm == NULL) {
 		OBD_FREE(*lmmp, lmm_size);
 		*lmmp = NULL;
-		RETURN(0);
+		return 0;
 	} else if (unlikely(lsm != NULL && ostid_id(&lsm->lsm_oi) == 0)) {
-		RETURN(-EBADF);
+		return -EBADF;
 	}
 
 	if (*lmmp == NULL) {
 		OBD_ALLOC(*lmmp, lmm_size);
 		if (*lmmp == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 	}
 
 	if (lsm)
 		ostid_cpu_to_le(&lsm->lsm_oi, &(*lmmp)->lmm_oi);
 
-	RETURN(lmm_size);
+	return lmm_size;
 }
 
 /* Unpack OSC object metadata from disk storage (LE byte order). */
@@ -101,47 +100,46 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 {
 	int lsm_size;
 	struct obd_import *imp = class_exp2cliimp(exp);
-	ENTRY;
 
 	if (lmm != NULL) {
 		if (lmm_bytes < sizeof(*lmm)) {
 			CERROR("%s: lov_mds_md too small: %d, need %d\n",
 			       exp->exp_obd->obd_name, lmm_bytes,
 			       (int)sizeof(*lmm));
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 		/* XXX LOV_MAGIC etc check? */
 
 		if (unlikely(ostid_id(&lmm->lmm_oi) == 0)) {
 			CERROR("%s: zero lmm_object_id: rc = %d\n",
 			       exp->exp_obd->obd_name, -EINVAL);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
 	lsm_size = lov_stripe_md_size(1);
 	if (lsmp == NULL)
-		RETURN(lsm_size);
+		return lsm_size;
 
 	if (*lsmp != NULL && lmm == NULL) {
 		OBD_FREE((*lsmp)->lsm_oinfo[0], sizeof(struct lov_oinfo));
 		OBD_FREE(*lsmp, lsm_size);
 		*lsmp = NULL;
-		RETURN(0);
+		return 0;
 	}
 
 	if (*lsmp == NULL) {
 		OBD_ALLOC(*lsmp, lsm_size);
 		if (unlikely(*lsmp == NULL))
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		OBD_ALLOC((*lsmp)->lsm_oinfo[0], sizeof(struct lov_oinfo));
 		if (unlikely((*lsmp)->lsm_oinfo[0] == NULL)) {
 			OBD_FREE(*lsmp, lsm_size);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		loi_init((*lsmp)->lsm_oinfo[0]);
 	} else if (unlikely(ostid_id(&(*lsmp)->lsm_oi) == 0)) {
-		RETURN(-EBADF);
+		return -EBADF;
 	}
 
 	if (lmm != NULL)
@@ -154,7 +152,7 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 	else
 		(*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES;
 
-	RETURN(lsm_size);
+	return lsm_size;
 }
 
 static inline void osc_pack_capa(struct ptlrpc_request *req,
@@ -202,7 +200,6 @@ static int osc_getattr_interpret(const struct lu_env *env,
 				 struct osc_async_args *aa, int rc)
 {
 	struct ost_body *body;
-	ENTRY;
 
 	if (rc != 0)
 		GOTO(out, rc);
@@ -223,7 +220,7 @@ static int osc_getattr_interpret(const struct lu_env *env,
 	}
 out:
 	rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc);
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
@@ -232,17 +229,16 @@ static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
 	struct ptlrpc_request *req;
 	struct osc_async_args *aa;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa);
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GETATTR);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	osc_pack_req_body(req, oinfo);
@@ -255,7 +251,7 @@ static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
 	aa->aa_oi = oinfo;
 
 	ptlrpc_set_add_req(set, req);
-	RETURN(0);
+	return 0;
 }
 
 static int osc_getattr(const struct lu_env *env, struct obd_export *exp,
@@ -264,17 +260,16 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp,
 	struct ptlrpc_request *req;
 	struct ost_body       *body;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa);
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GETATTR);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	osc_pack_req_body(req, oinfo);
@@ -296,7 +291,6 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp,
 	oinfo->oi_oa->o_blksize = cli_brw_size(exp->exp_obd);
 	oinfo->oi_oa->o_valid |= OBD_MD_FLBLKSZ;
 
-	EXIT;
  out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -308,19 +302,18 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp,
 	struct ptlrpc_request *req;
 	struct ost_body       *body;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(oinfo->oi_oa->o_valid & OBD_MD_FLGROUP);
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa);
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_SETATTR);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	osc_pack_req_body(req, oinfo);
@@ -338,10 +331,9 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp,
 	lustre_get_wire_obdo(&req->rq_import->imp_connect_data, oinfo->oi_oa,
 			     &body->oa);
 
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_setattr_interpret(const struct lu_env *env,
@@ -349,7 +341,6 @@ static int osc_setattr_interpret(const struct lu_env *env,
 				 struct osc_setattr_args *sa, int rc)
 {
 	struct ost_body *body;
-	ENTRY;
 
 	if (rc != 0)
 		GOTO(out, rc);
@@ -362,7 +353,7 @@ static int osc_setattr_interpret(const struct lu_env *env,
 			     &body->oa);
 out:
 	rc = sa->sa_upcall(sa->sa_cookie, rc);
-	RETURN(rc);
+	return rc;
 }
 
 int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo,
@@ -373,17 +364,16 @@ int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo,
 	struct ptlrpc_request   *req;
 	struct osc_setattr_args *sa;
 	int		      rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SETATTR);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa);
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_SETATTR);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (oti && oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE)
@@ -413,7 +403,7 @@ int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo,
 			ptlrpc_set_add_req(rqset, req);
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo,
@@ -431,7 +421,6 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa,
 	struct ost_body       *body;
 	struct lov_stripe_md  *lsm;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(oa);
 	LASSERT(ea);
@@ -440,7 +429,7 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa,
 	if (!lsm) {
 		rc = obd_alloc_memmd(exp, &lsm);
 		if (rc < 0)
-			RETURN(rc);
+			return rc;
 	}
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_CREATE);
@@ -506,7 +495,7 @@ out_req:
 out:
 	if (rc && !*ea)
 		obd_free_memmd(exp, &lsm);
-	RETURN(rc);
+	return rc;
 }
 
 int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo,
@@ -517,17 +506,16 @@ int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo,
 	struct osc_setattr_args *sa;
 	struct ost_body	 *body;
 	int		      rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_PUNCH);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa);
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_PUNCH);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 	req->rq_request_portal = OST_IO_PORTAL; /* bug 7198 */
 	ptlrpc_at_set_req_timeout(req);
@@ -551,7 +539,7 @@ int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo,
 	else
 		ptlrpc_set_add_req(rqset, req);
 
-	RETURN(0);
+	return 0;
 }
 
 static int osc_punch(const struct lu_env *env, struct obd_export *exp,
@@ -571,7 +559,6 @@ static int osc_sync_interpret(const struct lu_env *env,
 {
 	struct osc_fsync_args *fa = arg;
 	struct ost_body *body;
-	ENTRY;
 
 	if (rc)
 		GOTO(out, rc);
@@ -585,7 +572,7 @@ static int osc_sync_interpret(const struct lu_env *env,
 	*fa->fa_oi->oi_oa = body->oa;
 out:
 	rc = fa->fa_upcall(fa->fa_cookie, rc);
-	RETURN(rc);
+	return rc;
 }
 
 int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo,
@@ -596,17 +583,16 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo,
 	struct ost_body       *body;
 	struct osc_fsync_args *fa;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SYNC);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa);
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_SYNC);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	/* overload the size and blocks fields in the oa with start/end */
@@ -630,25 +616,23 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo,
 	else
 		ptlrpc_set_add_req(rqset, req);
 
-	RETURN (0);
+	return 0;
 }
 
 static int osc_sync(const struct lu_env *env, struct obd_export *exp,
 		    struct obd_info *oinfo, obd_size start, obd_size end,
 		    struct ptlrpc_request_set *set)
 {
-	ENTRY;
-
 	if (!oinfo->oi_oa) {
 		CDEBUG(D_INFO, "oa NULL\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	oinfo->oi_oa->o_size = start;
 	oinfo->oi_oa->o_blocks = end;
 	oinfo->oi_oa->o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
 
-	RETURN(osc_sync_base(exp, oinfo, oinfo->oi_cb_up, oinfo, set));
+	return osc_sync_base(exp, oinfo, oinfo->oi_cb_up, oinfo, set);
 }
 
 /* Find and cancel locally locks matched by @mode in the resource found by
@@ -662,7 +646,6 @@ static int osc_resource_get_unused(struct obd_export *exp, struct obdo *oa,
 	struct ldlm_res_id res_id;
 	struct ldlm_resource *res;
 	int count;
-	ENTRY;
 
 	/* Return, i.e. cancel nothing, only if ELC is supported (flag in
 	 * export) but disabled through procfs (flag in NS).
@@ -671,19 +654,19 @@ static int osc_resource_get_unused(struct obd_export *exp, struct obdo *oa,
 	 * when we still want to cancel locks in advance and just cancel them
 	 * locally, without sending any RPC. */
 	if (exp_connect_cancelset(exp) && !ns_connect_cancelset(ns))
-		RETURN(0);
+		return 0;
 
 	ostid_build_res_name(&oa->o_oi, &res_id);
 	res = ldlm_resource_get(ns, NULL, &res_id, 0, 0);
 	if (res == NULL)
-		RETURN(0);
+		return 0;
 
 	LDLM_RESOURCE_ADDREF(res);
 	count = ldlm_cancel_resource_local(res, cancels, NULL, mode,
 					   lock_flags, 0, NULL);
 	LDLM_RESOURCE_DELREF(res);
 	ldlm_resource_putref(res);
-	RETURN(count);
+	return count;
 }
 
 static int osc_destroy_interpret(const struct lu_env *env,
@@ -720,7 +703,6 @@ int osc_create(const struct lu_env *env, struct obd_export *exp,
 	       struct obd_trans_info *oti)
 {
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(oa);
 	LASSERT(ea);
@@ -728,16 +710,16 @@ int osc_create(const struct lu_env *env, struct obd_export *exp,
 
 	if ((oa->o_valid & OBD_MD_FLFLAGS) &&
 	    oa->o_flags == OBD_FL_RECREATE_OBJS) {
-		RETURN(osc_real_create(exp, oa, ea, oti));
+		return osc_real_create(exp, oa, ea, oti);
 	}
 
 	if (!fid_seq_is_mdt(ostid_seq(&oa->o_oi)))
-		RETURN(osc_real_create(exp, oa, ea, oti));
+		return osc_real_create(exp, oa, ea, oti);
 
 	/* we should not get here anymore */
 	LBUG();
 
-	RETURN(rc);
+	return rc;
 }
 
 /* Destroy requests can be async always on the client, and we don't even really
@@ -760,11 +742,10 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp,
 	struct ost_body       *body;
 	LIST_HEAD(cancels);
 	int rc, count;
-	ENTRY;
 
 	if (!oa) {
 		CDEBUG(D_INFO, "oa NULL\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	count = osc_resource_get_unused(exp, oa, &cancels, LCK_PW,
@@ -773,7 +754,7 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp,
 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_DESTROY);
 	if (req == NULL) {
 		ldlm_lock_list_put(&cancels, l_bl_ast, count);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	osc_set_capa_size(req, &RMF_CAPA1, (struct obd_capa *)capa);
@@ -781,7 +762,7 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp,
 			       0, &cancels, count);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	req->rq_request_portal = OST_IO_PORTAL; /* bug 7198 */
@@ -817,7 +798,7 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp,
 
 	/* Do not wait for response */
 	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
-	RETURN(0);
+	return 0;
 }
 
 static void osc_announce_cached(struct client_obd *cli, struct obdo *oa,
@@ -948,7 +929,6 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes)
 {
 	int			rc = 0;
 	struct ost_body	*body;
-	ENTRY;
 
 	client_obd_list_lock(&cli->cl_loi_list_lock);
 	/* Don't shrink if we are already above or below the desired limit
@@ -959,13 +939,13 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes)
 
 	if (target_bytes >= cli->cl_avail_grant) {
 		client_obd_list_unlock(&cli->cl_loi_list_lock);
-		RETURN(0);
+		return 0;
 	}
 	client_obd_list_unlock(&cli->cl_loi_list_lock);
 
 	OBD_ALLOC_PTR(body);
 	if (!body)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	osc_announce_cached(cli, &body->oa, 0);
 
@@ -986,7 +966,7 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes)
 	if (rc != 0)
 		__osc_update_grant(cli, body->oa.o_grant);
 	OBD_FREE_PTR(body);
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_should_shrink_grant(struct client_obd *client)
@@ -1256,11 +1236,10 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa,
 	struct req_capsule      *pill;
 	struct brw_page *pg_prev;
 
-	ENTRY;
 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_PREP_REQ))
-		RETURN(-ENOMEM); /* Recoverable */
+		return -ENOMEM; /* Recoverable */
 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_PREP_REQ2))
-		RETURN(-EINVAL); /* Fatal */
+		return -EINVAL; /* Fatal */
 
 	if ((cmd & OBD_BRW_WRITE) != 0) {
 		opc = OST_WRITE;
@@ -1272,7 +1251,7 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa,
 		req = ptlrpc_request_alloc(cli->cl_import, &RQF_OST_BRW_READ);
 	}
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	for (niocount = i = 1; i < page_count; i++) {
 		if (!can_merge_pages(pga[i - 1], pga[i]))
@@ -1289,7 +1268,7 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa,
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, opc);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 	req->rq_request_portal = OST_IO_PORTAL; /* bug 7198 */
 	ptlrpc_at_set_req_timeout(req);
@@ -1435,11 +1414,11 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa,
 		aa->aa_ocapa = capa_get(ocapa);
 
 	*reqp = req;
-	RETURN(0);
+	return 0;
 
  out:
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 static int check_write_checksum(struct obdo *oa, const lnet_process_id_t *peer,
@@ -1496,18 +1475,17 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
 	struct client_obd *cli = aa->aa_cli;
 	struct ost_body *body;
 	__u32 client_cksum = 0;
-	ENTRY;
 
 	if (rc < 0 && rc != -EDQUOT) {
 		DEBUG_REQ(D_INFO, req, "Failed request with rc = %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	LASSERTF(req->rq_repmsg != NULL, "rc = %d\n", rc);
 	body = req_capsule_server_get(&req->rq_pill, &RMF_OST_BODY);
 	if (body == NULL) {
 		DEBUG_REQ(D_INFO, req, "Can't unpack body\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	/* set/clear over quota flag for a uid/gid */
@@ -1524,7 +1502,7 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
 	osc_update_grant(cli, body);
 
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	if (aa->aa_oa->o_valid & OBD_MD_FLCKSUM)
 		client_cksum = aa->aa_oa->o_cksum; /* save for later */
@@ -1532,19 +1510,19 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
 	if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE) {
 		if (rc > 0) {
 			CERROR("Unexpected +ve rc %d\n", rc);
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 		LASSERT(req->rq_bulk->bd_nob == aa->aa_requested_nob);
 
 		if (sptlrpc_cli_unwrap_bulk_write(req, req->rq_bulk))
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 
 		if ((aa->aa_oa->o_valid & OBD_MD_FLCKSUM) && client_cksum &&
 		    check_write_checksum(&body->oa, peer, client_cksum,
 					 body->oa.o_cksum, aa->aa_requested_nob,
 					 aa->aa_page_count, aa->aa_ppga,
 					 cksum_type_unpack(aa->aa_oa->o_flags)))
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 
 		rc = check_write_rcs(req, aa->aa_requested_nob,aa->aa_nio_count,
 				     aa->aa_page_count, aa->aa_ppga);
@@ -1561,7 +1539,7 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
 	if (rc > aa->aa_requested_nob) {
 		CERROR("Unexpected rc %d (%d requested)\n", rc,
 		       aa->aa_requested_nob);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (rc != req->rq_bulk->bd_nob_transferred) {
@@ -1641,7 +1619,7 @@ out:
 		lustre_get_wire_obdo(&req->rq_import->imp_connect_data,
 				     aa->aa_oa, &body->oa);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_brw_internal(int cmd, struct obd_export *exp, struct obdo *oa,
@@ -1655,8 +1633,6 @@ static int osc_brw_internal(int cmd, struct obd_export *exp, struct obdo *oa,
 	int		    generation, resends = 0;
 	struct l_wait_info     lwi;
 
-	ENTRY;
-
 	init_waitqueue_head(&waitq);
 	generation = exp->exp_obd->u.cli.cl_import->imp_generation;
 
@@ -1711,7 +1687,7 @@ restart_bulk:
 out:
 	if (rc == -EAGAIN || rc == -EINPROGRESS)
 		rc = -EIO;
-	RETURN (rc);
+	return rc;
 }
 
 static int osc_brw_redo_request(struct ptlrpc_request *request,
@@ -1720,7 +1696,6 @@ static int osc_brw_redo_request(struct ptlrpc_request *request,
 	struct ptlrpc_request *new_req;
 	struct osc_brw_async_args *new_aa;
 	struct osc_async_page *oap;
-	ENTRY;
 
 	DEBUG_REQ(rc == -EINPROGRESS ? D_RPCTRACE : D_ERROR, request,
 		  "redo for recoverable error %d", rc);
@@ -1732,7 +1707,7 @@ static int osc_brw_redo_request(struct ptlrpc_request *request,
 				  aa->aa_page_count, aa->aa_ppga,
 				  &new_req, aa->aa_ocapa, 0, 1);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	list_for_each_entry(oap, &aa->aa_oaps, oap_rpc_item) {
 		if (oap->oap_request != NULL) {
@@ -1741,7 +1716,7 @@ static int osc_brw_redo_request(struct ptlrpc_request *request,
 				 request, oap->oap_request);
 			if (oap->oap_interrupted) {
 				ptlrpc_req_finished(new_req);
-				RETURN(-EINTR);
+				return -EINTR;
 			}
 		}
 	}
@@ -1784,7 +1759,7 @@ static int osc_brw_redo_request(struct ptlrpc_request *request,
 	ptlrpcd_add_req(new_req, PDL_POLICY_SAME, -1);
 
 	DEBUG_REQ(D_INFO, new_req, "new request");
-	RETURN(0);
+	return 0;
 }
 
 /*
@@ -1873,7 +1848,6 @@ static int osc_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
 	struct obd_import *imp = class_exp2cliimp(exp);
 	struct client_obd *cli;
 	int rc, page_count_orig;
-	ENTRY;
 
 	LASSERT((imp != NULL) && (imp->imp_obd != NULL));
 	cli = &imp->imp_obd->u.cli;
@@ -1883,8 +1857,8 @@ static int osc_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
 		 * I/O can succeed */
 
 		if (imp->imp_invalid)
-			RETURN(-EIO);
-		RETURN(0);
+			return -EIO;
+		return 0;
 	}
 
 	/* test_brw with a failed create can trip this, maybe others. */
@@ -1894,7 +1868,7 @@ static int osc_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo,
 
 	orig = ppga = osc_build_ppga(pga, page_count);
 	if (ppga == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	page_count_orig = page_count;
 
 	sort_brw_pages(ppga, page_count);
@@ -1935,7 +1909,7 @@ out:
 	if (saved_oa != NULL)
 		OBDO_FREE(saved_oa);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int brw_interpret(const struct lu_env *env,
@@ -1946,7 +1920,6 @@ static int brw_interpret(const struct lu_env *env,
 	struct osc_extent *tmp;
 	struct cl_object  *obj = NULL;
 	struct client_obd *cli = aa->aa_cli;
-	ENTRY;
 
 	rc = osc_brw_fini_request(req, rc);
 	CDEBUG(D_INODE, "request %p aa %p rc %d\n", req, aa, rc);
@@ -1970,7 +1943,7 @@ static int brw_interpret(const struct lu_env *env,
 		}
 
 		if (rc == 0)
-			RETURN(0);
+			return 0;
 		else if (rc == -EAGAIN || rc == -EINPROGRESS)
 			rc = -EIO;
 	}
@@ -2040,7 +2013,7 @@ static int brw_interpret(const struct lu_env *env,
 	client_obd_list_unlock(&cli->cl_loi_list_lock);
 
 	osc_io_unplug(env, cli, NULL, PDL_POLICY_SAME);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2072,7 +2045,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
 	int				rc;
 	LIST_HEAD(rpc_list);
 
-	ENTRY;
 	LASSERT(!list_empty(ext_list));
 
 	/* add pages into rpc_list to build BRW rpc */
@@ -2228,7 +2200,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
 	 */
 	ptlrpcd_add_req(req, pol, -1);
 	rc = 0;
-	EXIT;
 
 out:
 	if (mem_tight != 0)
@@ -2257,7 +2228,7 @@ out:
 		if (clerq && !IS_ERR(clerq))
 			cl_req_completion(env, clerq, rc);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_set_lock_data_with_check(struct ldlm_lock *lock,
@@ -2337,7 +2308,6 @@ static int osc_enqueue_fini(struct ptlrpc_request *req, struct ost_lvb *lvb,
 			    __u64 *flags, int agl, int rc)
 {
 	int intent = *flags & LDLM_FL_HAS_INTENT;
-	ENTRY;
 
 	if (intent) {
 		/* The request was created before ldlm_cli_enqueue call. */
@@ -2347,6 +2317,8 @@ static int osc_enqueue_fini(struct ptlrpc_request *req, struct ost_lvb *lvb,
 						     &RMF_DLM_REP);
 
 			LASSERT(rep != NULL);
+			rep->lock_policy_res1 =
+				ptlrpc_status_ntoh(rep->lock_policy_res1);
 			if (rep->lock_policy_res1)
 				rc = rep->lock_policy_res1;
 		}
@@ -2361,7 +2333,7 @@ static int osc_enqueue_fini(struct ptlrpc_request *req, struct ost_lvb *lvb,
 
 	/* Call the update callback. */
 	rc = (*upcall)(cookie, rc);
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_enqueue_interpret(const struct lu_env *env,
@@ -2494,7 +2466,6 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 	int match_lvb = (agl != 0 ? 0 : LDLM_FL_LVB_READY);
 	ldlm_mode_t mode;
 	int rc;
-	ENTRY;
 
 	/* Filesystem lock extents are extended to page boundaries so that
 	 * dealing with the page cache is a little smoother.  */
@@ -2536,7 +2507,7 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 			 * Return -ECANCELED to tell the caller. */
 			ldlm_lock_decref(lockh, mode);
 			LDLM_LOCK_PUT(matched);
-			RETURN(-ECANCELED);
+			return -ECANCELED;
 		} else if (osc_set_lock_data_with_check(matched, einfo)) {
 			*flags |= LDLM_FL_LVB_READY;
 			/* addref the lock only if not async requests and PW
@@ -2561,7 +2532,7 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 				/* For async requests, decref the lock. */
 				ldlm_lock_decref(lockh, einfo->ei_mode);
 			LDLM_LOCK_PUT(matched);
-			RETURN(ELDLM_OK);
+			return ELDLM_OK;
 		} else {
 			ldlm_lock_decref(lockh, mode);
 			LDLM_LOCK_PUT(matched);
@@ -2574,12 +2545,12 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 		req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 					   &RQF_LDLM_ENQUEUE_LVB);
 		if (req == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		rc = ldlm_prep_enqueue_req(exp, req, &cancels, 0);
 		if (rc) {
 			ptlrpc_request_free(req);
-			RETURN(rc);
+			return rc;
 		}
 
 		req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER,
@@ -2615,14 +2586,14 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 		} else if (intent) {
 			ptlrpc_req_finished(req);
 		}
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = osc_enqueue_fini(req, lvb, upcall, cookie, flags, agl, rc);
 	if (intent)
 		ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_enqueue(struct obd_export *exp, struct obd_info *oinfo,
@@ -2631,7 +2602,6 @@ static int osc_enqueue(struct obd_export *exp, struct obd_info *oinfo,
 {
 	struct ldlm_res_id res_id;
 	int rc;
-	ENTRY;
 
 	ostid_build_res_name(&oinfo->oi_md->lsm_oi, &res_id);
 	rc = osc_enqueue_base(exp, &res_id, &oinfo->oi_flags, &oinfo->oi_policy,
@@ -2639,7 +2609,7 @@ static int osc_enqueue(struct obd_export *exp, struct obd_info *oinfo,
 			      oinfo->oi_md->lsm_oinfo[0]->loi_kms_valid,
 			      oinfo->oi_cb_up, oinfo, einfo, oinfo->oi_lockh,
 			      rqset, rqset != NULL, 0);
-	RETURN(rc);
+	return rc;
 }
 
 int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id,
@@ -2650,10 +2620,9 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 	struct obd_device *obd = exp->exp_obd;
 	int lflags = *flags;
 	ldlm_mode_t rc;
-	ENTRY;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_MATCH))
-		RETURN(-EIO);
+		return -EIO;
 
 	/* Filesystem lock extents are extended to page boundaries so that
 	 * dealing with the page cache is a little smoother */
@@ -2674,35 +2643,32 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 			if (!osc_set_data_with_check(lockh, data)) {
 				if (!(lflags & LDLM_FL_TEST_LOCK))
 					ldlm_lock_decref(lockh, rc);
-				RETURN(0);
+				return 0;
 			}
 		}
 		if (!(lflags & LDLM_FL_TEST_LOCK) && mode != rc) {
 			ldlm_lock_addref(lockh, LCK_PR);
 			ldlm_lock_decref(lockh, LCK_PW);
 		}
-		RETURN(rc);
+		return rc;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int osc_cancel_base(struct lustre_handle *lockh, __u32 mode)
 {
-	ENTRY;
-
 	if (unlikely(mode == LCK_GROUP))
 		ldlm_lock_decref_and_cancel(lockh, mode);
 	else
 		ldlm_lock_decref(lockh, mode);
 
-	RETURN(0);
+	return 0;
 }
 
 static int osc_cancel(struct obd_export *exp, struct lov_stripe_md *md,
 		      __u32 mode, struct lustre_handle *lockh)
 {
-	ENTRY;
-	RETURN(osc_cancel_base(lockh, mode));
+	return osc_cancel_base(lockh, mode);
 }
 
 static int osc_cancel_unused(struct obd_export *exp,
@@ -2726,7 +2692,6 @@ static int osc_statfs_interpret(const struct lu_env *env,
 				struct osc_async_args *aa, int rc)
 {
 	struct obd_statfs *msfs;
-	ENTRY;
 
 	if (rc == -EBADR)
 		/* The request has in fact never been sent
@@ -2734,7 +2699,7 @@ static int osc_statfs_interpret(const struct lu_env *env,
 		 * Exit immediately since the caller is
 		 * aware of the problem and takes care
 		 * of the clean up */
-		 RETURN(rc);
+		 return rc;
 
 	if ((rc == -ENOTCONN || rc == -EAGAIN) &&
 	    (aa->aa_oi->oi_flags & OBD_STATFS_NODELAY))
@@ -2751,7 +2716,7 @@ static int osc_statfs_interpret(const struct lu_env *env,
 	*aa->aa_oi->oi_osfs = *msfs;
 out:
 	rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc);
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_statfs_async(struct obd_export *exp,
@@ -2762,7 +2727,6 @@ static int osc_statfs_async(struct obd_export *exp,
 	struct ptlrpc_request *req;
 	struct osc_async_args *aa;
 	int		    rc;
-	ENTRY;
 
 	/* We could possibly pass max_age in the request (as an absolute
 	 * timestamp or a "seconds.usec ago") so the target can avoid doing
@@ -2772,12 +2736,12 @@ static int osc_statfs_async(struct obd_export *exp,
 	 * timestamps are not ideal because they need time synchronization. */
 	req = ptlrpc_request_alloc(obd->u.cli.cl_import, &RQF_OST_STATFS);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_STATFS);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 	ptlrpc_request_set_replen(req);
 	req->rq_request_portal = OST_CREATE_PORTAL;
@@ -2795,7 +2759,7 @@ static int osc_statfs_async(struct obd_export *exp,
 	aa->aa_oi = oinfo;
 
 	ptlrpc_set_add_req(rqset, req);
-	RETURN(0);
+	return 0;
 }
 
 static int osc_statfs(const struct lu_env *env, struct obd_export *exp,
@@ -2806,7 +2770,6 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp,
 	struct ptlrpc_request *req;
 	struct obd_import     *imp = NULL;
 	int rc;
-	ENTRY;
 
 	/*Since the request might also come from lprocfs, so we need
 	 *sync this with client_disconnect_export Bug15684*/
@@ -2815,7 +2778,7 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp,
 		imp = class_import_get(obd->u.cli.cl_import);
 	up_read(&obd->u.cli.cl_sem);
 	if (!imp)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	/* We could possibly pass max_age in the request (as an absolute
 	 * timestamp or a "seconds.usec ago") so the target can avoid doing
@@ -2828,12 +2791,12 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp,
 	class_import_put(imp);
 
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_STATFS);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 	ptlrpc_request_set_replen(req);
 	req->rq_request_portal = OST_CREATE_PORTAL;
@@ -2856,7 +2819,6 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp,
 
 	*osfs = *msfs;
 
-	EXIT;
  out:
 	ptlrpc_req_finished(req);
 	return rc;
@@ -2874,20 +2836,19 @@ static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump)
 	struct lov_user_md_v3 lum, *lumk;
 	struct lov_user_ost_data_v1 *lmm_objects;
 	int rc = 0, lum_size;
-	ENTRY;
 
 	if (!lsm)
-		RETURN(-ENODATA);
+		return -ENODATA;
 
 	/* we only need the header part from user space to get lmm_magic and
 	 * lmm_stripe_count, (the header part is common to v1 and v3) */
 	lum_size = sizeof(struct lov_user_md_v1);
 	if (copy_from_user(&lum, lump, lum_size))
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	if ((lum.lmm_magic != LOV_USER_MAGIC_V1) &&
 	    (lum.lmm_magic != LOV_USER_MAGIC_V3))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* lov_user_md_vX and lov_mds_md_vX must have the same size */
 	LASSERT(sizeof(struct lov_user_md_v1) == sizeof(struct lov_mds_md_v1));
@@ -2900,7 +2861,7 @@ static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump)
 		lum_size = lov_mds_md_size(lum.lmm_stripe_count, lum.lmm_magic);
 		OBD_ALLOC(lumk, lum_size);
 		if (!lumk)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		if (lum.lmm_magic == LOV_USER_MAGIC_V1)
 			lmm_objects =
@@ -2922,7 +2883,7 @@ static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump)
 	if (lumk != &lum)
 		OBD_FREE(lumk, lum_size);
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -2932,7 +2893,6 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 	struct obd_device *obd = exp->exp_obd;
 	struct obd_ioctl_data *data = karg;
 	int err = 0;
-	ENTRY;
 
 	if (!try_module_get(THIS_MODULE)) {
 		CERROR("Can't get module. Is it alive?");
@@ -3016,15 +2976,14 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
 			obd_count keylen, void *key, __u32 *vallen, void *val,
 			struct lov_stripe_md *lsm)
 {
-	ENTRY;
 	if (!vallen || !val)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	if (KEY_IS(KEY_LOCK_TO_STRIPE)) {
 		__u32 *stripe = val;
 		*vallen = sizeof(*stripe);
 		*stripe = 0;
-		RETURN(0);
+		return 0;
 	} else if (KEY_IS(KEY_LAST_ID)) {
 		struct ptlrpc_request *req;
 		obd_id		*reply;
@@ -3034,14 +2993,14 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
 		req = ptlrpc_request_alloc(class_exp2cliimp(exp),
 					   &RQF_OST_GET_INFO_LAST_ID);
 		if (req == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		req_capsule_set_size(&req->rq_pill, &RMF_SETINFO_KEY,
 				     RCL_CLIENT, keylen);
 		rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO);
 		if (rc) {
 			ptlrpc_request_free(req);
-			RETURN(rc);
+			return rc;
 		}
 
 		tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY);
@@ -3060,7 +3019,7 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
 		*((obd_id *)val) = *reply;
 	out:
 		ptlrpc_req_finished(req);
-		RETURN(rc);
+		return rc;
 	} else if (KEY_IS(KEY_FIEMAP)) {
 		struct ll_fiemap_info_key *fm_key =
 				(struct ll_fiemap_info_key *)key;
@@ -3142,10 +3101,10 @@ fini_req:
 drop_lock:
 		if (mode)
 			ldlm_lock_decref(&lockh, LCK_PR);
-		RETURN(rc);
+		return rc;
 	}
 
-	RETURN(-EINVAL);
+	return -EINVAL;
 }
 
 static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
@@ -3157,25 +3116,24 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 	struct obd_import     *imp = class_exp2cliimp(exp);
 	char		  *tmp;
 	int		    rc;
-	ENTRY;
 
 	OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_SHUTDOWN, 10);
 
 	if (KEY_IS(KEY_CHECKSUM)) {
 		if (vallen != sizeof(int))
-			RETURN(-EINVAL);
+			return -EINVAL;
 		exp->exp_obd->u.cli.cl_checksum = (*(int *)val) ? 1 : 0;
-		RETURN(0);
+		return 0;
 	}
 
 	if (KEY_IS(KEY_SPTLRPC_CONF)) {
 		sptlrpc_conf_client_adapt(obd);
-		RETURN(0);
+		return 0;
 	}
 
 	if (KEY_IS(KEY_FLUSH_CTX)) {
 		sptlrpc_import_flush_my_ctx(imp);
-		RETURN(0);
+		return 0;
 	}
 
 	if (KEY_IS(KEY_CACHE_SET)) {
@@ -3192,7 +3150,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 		list_add(&cli->cl_lru_osc, &cli->cl_cache->ccc_lru);
 		spin_unlock(&cli->cl_cache->ccc_lru_lock);
 
-		RETURN(0);
+		return 0;
 	}
 
 	if (KEY_IS(KEY_CACHE_LRU_SHRINK)) {
@@ -3202,11 +3160,11 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 
 		nr = osc_lru_shrink(cli, min(nr, target));
 		*(int *)val -= nr;
-		RETURN(0);
+		return 0;
 	}
 
 	if (!set && !KEY_IS(KEY_GRANT_SHRINK))
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	/* We pass all other commands directly to OST. Since nobody calls osc
 	   methods directly and everybody is supposed to go through LOV, we
@@ -3219,7 +3177,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 						&RQF_OST_SET_GRANT_INFO :
 						&RQF_OBD_SET_INFO);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req_capsule_set_size(&req->rq_pill, &RMF_SETINFO_KEY,
 			     RCL_CLIENT, keylen);
@@ -3229,7 +3187,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_SET_INFO);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY);
@@ -3248,7 +3206,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 		OBDO_ALLOC(oa);
 		if (!oa) {
 			ptlrpc_req_finished(req);
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		*oa = ((struct ost_body *)val)->oa;
 		aa->aa_oa = oa;
@@ -3263,7 +3221,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
 	} else
 		ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
 
-	RETURN(0);
+	return 0;
 }
 
 
@@ -3280,8 +3238,6 @@ static int osc_llog_finish(struct obd_device *obd, int count)
 {
 	struct llog_ctxt *ctxt;
 
-	ENTRY;
-
 	ctxt = llog_get_context(obd, LLOG_MDS_OST_ORIG_CTXT);
 	if (ctxt) {
 		llog_cat_close(NULL, ctxt->loc_handle);
@@ -3291,7 +3247,7 @@ static int osc_llog_finish(struct obd_device *obd, int count)
 	ctxt = llog_get_context(obd, LLOG_SIZE_REPL_CTXT);
 	if (ctxt)
 		llog_cleanup(NULL, ctxt);
-	RETURN(0);
+	return 0;
 }
 
 static int osc_reconnect(const struct lu_env *env,
@@ -3317,7 +3273,7 @@ static int osc_reconnect(const struct lu_env *env,
 		       data->ocd_version, data->ocd_grant, lost_grant);
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static int osc_disconnect(struct obd_export *exp)
@@ -3369,7 +3325,6 @@ static int osc_import_event(struct obd_device *obd,
 	struct client_obd *cli;
 	int rc = 0;
 
-	ENTRY;
 	LASSERT(imp->imp_obd == obd);
 
 	switch (event) {
@@ -3433,7 +3388,7 @@ static int osc_import_event(struct obd_device *obd,
 		CERROR("Unknown import event %d\n", event);
 		LBUG();
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -3457,9 +3412,9 @@ static int osc_cancel_for_recovery(struct ldlm_lock *lock)
 	    (lock->l_granted_mode == LCK_PR ||
 	     lock->l_granted_mode == LCK_CR) &&
 	    (osc_dlm_lock_pageref(lock) == 0))
-		RETURN(1);
+		return 1;
 
-	RETURN(0);
+	return 0;
 }
 
 static int brw_queue_work(const struct lu_env *env, void *data)
@@ -3469,7 +3424,7 @@ static int brw_queue_work(const struct lu_env *env, void *data)
 	CDEBUG(D_CACHE, "Run writeback work for client obd %p.\n", cli);
 
 	osc_io_unplug(env, cli, NULL, PDL_POLICY_SAME);
-	RETURN(0);
+	return 0;
 }
 
 int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
@@ -3478,11 +3433,10 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 	struct client_obd	  *cli = &obd->u.cli;
 	void		       *handler;
 	int			rc;
-	ENTRY;
 
 	rc = ptlrpcd_addref();
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = client_obd_setup(obd, lcfg);
 	if (rc)
@@ -3517,7 +3471,7 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 
 	INIT_LIST_HEAD(&cli->cl_grant_shrink_list);
 	ns_register_cancel(obd->obd_namespace, osc_cancel_for_recovery);
-	RETURN(rc);
+	return rc;
 
 out_ptlrpcd_work:
 	ptlrpcd_destroy_work(handler);
@@ -3525,13 +3479,12 @@ out_client_setup:
 	client_obd_cleanup(obd);
 out_ptlrpcd:
 	ptlrpcd_decref();
-	RETURN(rc);
+	return rc;
 }
 
 static int osc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 {
 	int rc = 0;
-	ENTRY;
 
 	switch (stage) {
 	case OBD_CLEANUP_EARLY: {
@@ -3570,7 +3523,7 @@ static int osc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 		break;
 		}
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int osc_cleanup(struct obd_device *obd)
@@ -3578,8 +3531,6 @@ int osc_cleanup(struct obd_device *obd)
 	struct client_obd *cli = &obd->u.cli;
 	int rc;
 
-	ENTRY;
-
 	/* lru cleanup */
 	if (cli->cl_cache != NULL) {
 		LASSERT(atomic_read(&cli->cl_cache->ccc_users) > 0);
@@ -3597,7 +3548,7 @@ int osc_cleanup(struct obd_device *obd)
 	rc = client_obd_cleanup(obd);
 
 	ptlrpcd_decref();
-	RETURN(rc);
+	return rc;
 }
 
 int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg)
@@ -3671,7 +3622,6 @@ int __init osc_init(void)
 {
 	struct lprocfs_static_vars lvars = { 0 };
 	int rc;
-	ENTRY;
 
 	/* print an address of _any_ initialized kernel symbol from this
 	 * module, to allow debugging with gdb that doesn't support data
@@ -3679,6 +3629,8 @@ int __init osc_init(void)
 	CDEBUG(D_INFO, "Lustre OSC module (%p).\n", &osc_caches);
 
 	rc = lu_kmem_init(osc_caches);
+	if (rc)
+		return rc;
 
 	lprocfs_osc_init_vars(&lvars);
 
@@ -3686,13 +3638,13 @@ int __init osc_init(void)
 				 LUSTRE_OSC_NAME, &osc_device_type);
 	if (rc) {
 		lu_kmem_fini(osc_caches);
-		RETURN(rc);
+		return rc;
 	}
 
 	spin_lock_init(&osc_ast_guard);
 	lockdep_set_class(&osc_ast_guard, &osc_ast_guard_class);
 
-	RETURN(rc);
+	return rc;
 }
 
 static void /*__exit*/ osc_exit(void)
@@ -3704,5 +3656,7 @@ static void /*__exit*/ osc_exit(void)
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre Object Storage Client (OSC)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(LUSTRE_VERSION_STRING);
 
-cfs_module(osc, LUSTRE_VERSION_STRING, osc_init, osc_exit);
+module_init(osc_init);
+module_exit(osc_exit);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/Makefile b/drivers/staging/lustre/lustre/ptlrpc/Makefile
index 983eb66..6d78b80 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/Makefile
+++ b/drivers/staging/lustre/lustre/ptlrpc/Makefile
@@ -16,6 +16,7 @@ ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o sec_lproc.o
 ptlrpc_objs += sec_null.o sec_plain.o nrs.o nrs_fifo.o
 
 ptlrpc-y := $(ldlm_objs) $(ptlrpc_objs)
+ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.o
 
 obj-$(CONFIG_PTLRPC_GSS) += gss/
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index 22f7e65..810a458 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -137,11 +137,10 @@ struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req,
 	struct obd_import *imp = req->rq_import;
 	struct ptlrpc_bulk_desc *desc;
 
-	ENTRY;
 	LASSERT(type == BULK_PUT_SINK || type == BULK_GET_SOURCE);
 	desc = ptlrpc_new_bulk(npages, max_brw, type, portal);
 	if (desc == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	desc->bd_import_generation = req->rq_import_generation;
 	desc->bd_import = class_import_get(imp);
@@ -187,7 +186,6 @@ EXPORT_SYMBOL(__ptlrpc_prep_bulk_page);
 void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin)
 {
 	int i;
-	ENTRY;
 
 	LASSERT(desc != NULL);
 	LASSERT(desc->bd_iov_count != LI_POISON); /* not freed already */
@@ -208,7 +206,6 @@ void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin)
 
 	OBD_FREE(desc, offsetof(struct ptlrpc_bulk_desc,
 				bd_iov[desc->bd_max_iov]));
-	EXIT;
 }
 EXPORT_SYMBOL(__ptlrpc_free_bulk);
 
@@ -336,7 +333,6 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
 	struct ptlrpc_request *early_req;
 	time_t		 olddl;
 	int		    rc;
-	ENTRY;
 
 	req->rq_early = 0;
 	spin_unlock(&req->rq_lock);
@@ -344,7 +340,7 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
 	rc = sptlrpc_cli_unwrap_early_reply(req, &early_req);
 	if (rc) {
 		spin_lock(&req->rq_lock);
-		RETURN(rc);
+		return rc;
 	}
 
 	rc = unpack_reply(early_req);
@@ -360,7 +356,7 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
 
 	if (rc != 0) {
 		spin_lock(&req->rq_lock);
-		RETURN(rc);
+		return rc;
 	}
 
 	/* Adjust the local timeout for this req */
@@ -379,7 +375,7 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
 		  cfs_time_sub(req->rq_deadline, cfs_time_current_sec()),
 		  cfs_time_sub(req->rq_deadline, olddl));
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -547,7 +543,6 @@ static int __ptlrpc_request_bufs_pack(struct ptlrpc_request *request,
 {
 	struct obd_import  *imp = request->rq_import;
 	int		 rc;
-	ENTRY;
 
 	if (unlikely(ctx))
 		request->rq_cli_ctx = sptlrpc_cli_ctx_get(ctx);
@@ -601,7 +596,7 @@ static int __ptlrpc_request_bufs_pack(struct ptlrpc_request *request,
 
 	lustre_msg_set_opc(request->rq_reqmsg, opcode);
 
-	RETURN(0);
+	return 0;
 out_ctx:
 	sptlrpc_cli_ctx_put(request->rq_cli_ctx, 1);
 out_free:
@@ -822,10 +817,9 @@ struct ptlrpc_request_set *ptlrpc_prep_set(void)
 {
 	struct ptlrpc_request_set *set;
 
-	ENTRY;
 	OBD_ALLOC(set, sizeof *set);
 	if (!set)
-		RETURN(NULL);
+		return NULL;
 	atomic_set(&set->set_refcount, 1);
 	INIT_LIST_HEAD(&set->set_requests);
 	init_waitqueue_head(&set->set_waitq);
@@ -839,7 +833,7 @@ struct ptlrpc_request_set *ptlrpc_prep_set(void)
 	set->set_producer_arg = NULL;
 	set->set_rc	   = 0;
 
-	RETURN(set);
+	return set;
 }
 EXPORT_SYMBOL(ptlrpc_prep_set);
 
@@ -859,13 +853,13 @@ struct ptlrpc_request_set *ptlrpc_prep_fcset(int max, set_producer_func func,
 
 	set = ptlrpc_prep_set();
 	if (!set)
-		RETURN(NULL);
+		return NULL;
 
 	set->set_max_inflight  = max;
 	set->set_producer      = func;
 	set->set_producer_arg  = arg;
 
-	RETURN(set);
+	return set;
 }
 EXPORT_SYMBOL(ptlrpc_prep_fcset);
 
@@ -883,7 +877,6 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set)
 	struct list_head       *next;
 	int	       expected_phase;
 	int	       n = 0;
-	ENTRY;
 
 	/* Requests on the set should either all be completed, or all be new */
 	expected_phase = (atomic_read(&set->set_remaining) == 0) ?
@@ -925,7 +918,6 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set)
 	LASSERT(atomic_read(&set->set_remaining) == 0);
 
 	ptlrpc_reqset_put(set);
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_set_destroy);
 
@@ -941,13 +933,13 @@ int ptlrpc_set_add_cb(struct ptlrpc_request_set *set,
 
 	OBD_ALLOC_PTR(cbdata);
 	if (cbdata == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	cbdata->psc_interpret = fn;
 	cbdata->psc_data = data;
 	list_add_tail(&cbdata->psc_item, &set->set_cblist);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_set_add_cb);
 
@@ -1027,7 +1019,6 @@ static int ptlrpc_import_delay_req(struct obd_import *imp,
 				   struct ptlrpc_request *req, int *status)
 {
 	int delay = 0;
-	ENTRY;
 
 	LASSERT (status != NULL);
 	*status = 0;
@@ -1078,7 +1069,7 @@ static int ptlrpc_import_delay_req(struct obd_import *imp,
 		}
 	}
 
-	RETURN(delay);
+	return delay;
 }
 
 /**
@@ -1120,7 +1111,6 @@ static int ptlrpc_console_allow(struct ptlrpc_request *req)
 static int ptlrpc_check_status(struct ptlrpc_request *req)
 {
 	int err;
-	ENTRY;
 
 	err = lustre_msg_get_status(req->rq_repmsg);
 	if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR) {
@@ -1133,7 +1123,7 @@ static int ptlrpc_check_status(struct ptlrpc_request *req)
 					   libcfs_nid2str(
 					   imp->imp_connection->c_peer.nid),
 					   ll_opcode2str(opc), err);
-		RETURN(err < 0 ? err : -EINVAL);
+		return err < 0 ? err : -EINVAL;
 	}
 
 	if (err < 0) {
@@ -1143,7 +1133,7 @@ static int ptlrpc_check_status(struct ptlrpc_request *req)
 		DEBUG_REQ(D_INFO, req, "status is %d", err);
 	}
 
-	RETURN(err);
+	return err;
 }
 
 /**
@@ -1156,7 +1146,6 @@ static void ptlrpc_save_versions(struct ptlrpc_request *req)
 	struct lustre_msg *repmsg = req->rq_repmsg;
 	struct lustre_msg *reqmsg = req->rq_reqmsg;
 	__u64 *versions = lustre_msg_get_versions(repmsg);
-	ENTRY;
 
 	if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
 		return;
@@ -1165,8 +1154,6 @@ static void ptlrpc_save_versions(struct ptlrpc_request *req)
 	lustre_msg_set_versions(reqmsg, versions);
 	CDEBUG(D_INFO, "Client save versions ["LPX64"/"LPX64"]\n",
 	       versions[0], versions[1]);
-
-	EXIT;
 }
 
 /**
@@ -1183,7 +1170,6 @@ static int after_reply(struct ptlrpc_request *req)
 	int rc;
 	struct timeval work_start;
 	long timediff;
-	ENTRY;
 
 	LASSERT(obd != NULL);
 	/* repbuf must be unlinked */
@@ -1194,7 +1180,7 @@ static int after_reply(struct ptlrpc_request *req)
 			DEBUG_REQ(D_ERROR, req, "reply buffer overflow,"
 				  " expected: %d, actual size: %d",
 				  req->rq_nob_received, req->rq_repbuf_len);
-			RETURN(-EOVERFLOW);
+			return -EOVERFLOW;
 		}
 
 		sptlrpc_cli_free_repbuf(req);
@@ -1205,7 +1191,7 @@ static int after_reply(struct ptlrpc_request *req)
 		req->rq_replen       = req->rq_nob_received;
 		req->rq_nob_received = 0;
 		req->rq_resend       = 1;
-		RETURN(0);
+		return 0;
 	}
 
 	/*
@@ -1215,18 +1201,18 @@ static int after_reply(struct ptlrpc_request *req)
 	rc = sptlrpc_cli_unwrap_reply(req);
 	if (rc) {
 		DEBUG_REQ(D_ERROR, req, "unwrap reply failed (%d):", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	/*
 	 * Security layer unwrap might ask resend this request.
 	 */
 	if (req->rq_resend)
-		RETURN(0);
+		return 0;
 
 	rc = unpack_reply(req);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	/* retry indefinitely on EINPROGRESS */
 	if (lustre_msg_get_status(req->rq_repmsg) == -EINPROGRESS &&
@@ -1257,7 +1243,7 @@ static int after_reply(struct ptlrpc_request *req)
 		else
 			req->rq_sent = now + req->rq_nr_resend;
 
-		RETURN(0);
+		return 0;
 	}
 
 	do_gettimeofday(&work_start);
@@ -1272,7 +1258,7 @@ static int after_reply(struct ptlrpc_request *req)
 	    lustre_msg_get_type(req->rq_repmsg) != PTL_RPC_MSG_ERR) {
 		DEBUG_REQ(D_ERROR, req, "invalid packet received (type=%u)",
 			  lustre_msg_get_type(req->rq_repmsg));
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (lustre_msg_get_opc(req->rq_reqmsg) != OBD_PING)
@@ -1293,10 +1279,10 @@ static int after_reply(struct ptlrpc_request *req)
 		if (ll_rpc_recoverable_error(rc)) {
 			if (req->rq_send_state != LUSTRE_IMP_FULL ||
 			    imp->imp_obd->obd_no_recov || imp->imp_dlm_fake) {
-				RETURN(rc);
+				return rc;
 			}
 			ptlrpc_request_handle_notconn(req);
-			RETURN(rc);
+			return rc;
 		}
 	} else {
 		/*
@@ -1360,7 +1346,7 @@ static int after_reply(struct ptlrpc_request *req)
 		spin_unlock(&imp->imp_lock);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1372,13 +1358,12 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 {
 	struct obd_import     *imp = req->rq_import;
 	int rc;
-	ENTRY;
 
 	LASSERT(req->rq_phase == RQ_PHASE_NEW);
 	if (req->rq_sent && (req->rq_sent > cfs_time_current_sec()) &&
 	    (!req->rq_generation_set ||
 	     req->rq_import_generation == imp->imp_generation))
-		RETURN (0);
+		return 0;
 
 	ptlrpc_rqphase_move(req, RQ_PHASE_RPC);
 
@@ -1400,14 +1385,14 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 		list_add_tail(&req->rq_list, &imp->imp_delayed_list);
 		atomic_inc(&req->rq_import->imp_inflight);
 		spin_unlock(&imp->imp_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	if (rc != 0) {
 		spin_unlock(&imp->imp_lock);
 		req->rq_status = rc;
 		ptlrpc_rqphase_move(req, RQ_PHASE_INTERPRET);
-		RETURN(rc);
+		return rc;
 	}
 
 	LASSERT(list_empty(&req->rq_list));
@@ -1421,10 +1406,10 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 	if (rc) {
 		if (req->rq_err) {
 			req->rq_status = rc;
-			RETURN(1);
+			return 1;
 		} else {
 			req->rq_wait_ctx = 1;
-			RETURN(0);
+			return 0;
 		}
 	}
 
@@ -1439,15 +1424,14 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
 	if (rc) {
 		DEBUG_REQ(D_HA, req, "send failed (%d); expect timeout", rc);
 		req->rq_net_err = 1;
-		RETURN(rc);
+		return rc;
 	}
-	RETURN(0);
+	return 0;
 }
 
 static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set)
 {
 	int remaining, rc;
-	ENTRY;
 
 	LASSERT(set->set_producer != NULL);
 
@@ -1461,11 +1445,11 @@ static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set)
 			/* no more RPC to produce */
 			set->set_producer     = NULL;
 			set->set_producer_arg = NULL;
-			RETURN(0);
+			return 0;
 		}
 	}
 
-	RETURN((atomic_read(&set->set_remaining) - remaining));
+	return (atomic_read(&set->set_remaining) - remaining);
 }
 
 /**
@@ -1478,10 +1462,9 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
 {
 	struct list_head *tmp, *next;
 	int force_timer_recalc = 0;
-	ENTRY;
 
 	if (atomic_read(&set->set_remaining) == 0)
-		RETURN(1);
+		return 1;
 
 	list_for_each_safe(tmp, next, &set->set_requests) {
 		struct ptlrpc_request *req =
@@ -1834,7 +1817,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
 	}
 
 	/* If we hit an error, we want to recover promptly. */
-	RETURN(atomic_read(&set->set_remaining) == 0 || force_timer_recalc);
+	return atomic_read(&set->set_remaining) == 0 || force_timer_recalc;
 }
 EXPORT_SYMBOL(ptlrpc_check_set);
 
@@ -1847,7 +1830,6 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
 {
 	struct obd_import *imp = req->rq_import;
 	int rc = 0;
-	ENTRY;
 
 	spin_lock(&req->rq_lock);
 	req->rq_timedout = 1;
@@ -1873,14 +1855,14 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
 
 	if (imp == NULL) {
 		DEBUG_REQ(D_HA, req, "NULL import: already cleaned up?");
-		RETURN(1);
+		return 1;
 	}
 
 	atomic_inc(&imp->imp_timeouts);
 
 	/* The DLM server doesn't want recovery run on its imports. */
 	if (imp->imp_dlm_fake)
-		RETURN(1);
+		return 1;
 
 	/* If this request is for recovery or other primordial tasks,
 	 * then error it out here. */
@@ -1894,7 +1876,7 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
 		req->rq_status = -ETIMEDOUT;
 		req->rq_err = 1;
 		spin_unlock(&req->rq_lock);
-		RETURN(1);
+		return 1;
 	}
 
 	/* if a request can't be resent we can't wait for an answer after
@@ -1906,7 +1888,7 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
 
 	ptlrpc_fail_import(imp, lustre_msg_get_conn_cnt(req->rq_reqmsg));
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1919,7 +1901,6 @@ int ptlrpc_expired_set(void *data)
 	struct ptlrpc_request_set *set = data;
 	struct list_head		*tmp;
 	time_t		     now = cfs_time_current_sec();
-	ENTRY;
 
 	LASSERT(set != NULL);
 
@@ -1955,7 +1936,7 @@ int ptlrpc_expired_set(void *data)
 	 * sleep so we can recalculate the timeout, or enable interrupts
 	 * if everyone's timed out.
 	 */
-	RETURN(1);
+	return 1;
 }
 EXPORT_SYMBOL(ptlrpc_expired_set);
 
@@ -2006,7 +1987,6 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set)
 	int		    timeout = 0;
 	struct ptlrpc_request *req;
 	int		    deadline;
-	ENTRY;
 
 	SIGNAL_MASK_ASSERT(); /* XXX BUG 1511 */
 
@@ -2045,7 +2025,7 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set)
 		else if (timeout == 0 || timeout > deadline - now)
 			timeout = deadline - now;
 	}
-	RETURN(timeout);
+	return timeout;
 }
 EXPORT_SYMBOL(ptlrpc_set_next_timeout);
 
@@ -2061,7 +2041,6 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
 	struct ptlrpc_request *req;
 	struct l_wait_info     lwi;
 	int		    rc, timeout;
-	ENTRY;
 
 	if (set->set_producer)
 		(void)ptlrpc_set_producer(set);
@@ -2074,7 +2053,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
 		}
 
 	if (list_empty(&set->set_requests))
-		RETURN(0);
+		return 0;
 
 	do {
 		timeout = ptlrpc_set_next_timeout(set);
@@ -2171,7 +2150,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
 		}
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_set_wait);
 
@@ -2185,9 +2164,7 @@ EXPORT_SYMBOL(ptlrpc_set_wait);
  */
 static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked)
 {
-	ENTRY;
 	if (request == NULL) {
-		EXIT;
 		return;
 	}
 
@@ -2240,7 +2217,6 @@ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked)
 		__ptlrpc_free_req_to_pool(request);
 	else
 		OBD_FREE(request, sizeof(*request));
-	EXIT;
 }
 
 static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked);
@@ -2263,15 +2239,14 @@ EXPORT_SYMBOL(ptlrpc_req_finished_with_imp_lock);
  */
 static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked)
 {
-	ENTRY;
 	if (request == NULL)
-		RETURN(1);
+		return 1;
 
 	if (request == LP_POISON ||
 	    request->rq_reqmsg == LP_POISON) {
 		CERROR("dereferencing freed request (bug 575)\n");
 		LBUG();
-		RETURN(1);
+		return 1;
 	}
 
 	DEBUG_REQ(D_INFO, request, "refcount now %u",
@@ -2279,10 +2254,10 @@ static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked)
 
 	if (atomic_dec_and_test(&request->rq_refcount)) {
 		__ptlrpc_free_req(request, locked);
-		RETURN(1);
+		return 1;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -2332,7 +2307,7 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 	 * Nothing left to do.
 	 */
 	if (!ptlrpc_client_recv_or_unlink(request))
-		RETURN(1);
+		return 1;
 
 	LNetMDUnlink(request->rq_reply_md_h);
 
@@ -2340,7 +2315,7 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 	 * Let's check it once again.
 	 */
 	if (!ptlrpc_client_recv_or_unlink(request))
-		RETURN(1);
+		return 1;
 
 	/*
 	 * Move to "Unregistering" phase as reply was not unlinked yet.
@@ -2351,7 +2326,7 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 	 * Do not wait for unlink to finish.
 	 */
 	if (async)
-		RETURN(0);
+		return 0;
 
 	/*
 	 * We have to l_wait_event() whatever the result, to give liblustre
@@ -2372,7 +2347,7 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 				  &lwi);
 		if (rc == 0) {
 			ptlrpc_rqphase_move(request, request->rq_next_phase);
-			RETURN(1);
+			return 1;
 		}
 
 		LASSERT(rc == -ETIMEDOUT);
@@ -2380,7 +2355,7 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 			  "rvcng=%d unlnk=%d", request->rq_receiving_reply,
 			  request->rq_must_unlink);
 	}
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_unregister_reply);
 
@@ -2397,7 +2372,6 @@ void ptlrpc_free_committed(struct obd_import *imp)
 	struct list_head *tmp, *saved;
 	struct ptlrpc_request *req;
 	struct ptlrpc_request *last_req = NULL; /* temporary fire escape */
-	ENTRY;
 
 	LASSERT(imp != NULL);
 
@@ -2408,7 +2382,6 @@ void ptlrpc_free_committed(struct obd_import *imp)
 	    imp->imp_generation == imp->imp_last_generation_checked) {
 		CDEBUG(D_INFO, "%s: skip recheck: last_committed "LPU64"\n",
 		       imp->imp_obd->obd_name, imp->imp_peer_committed_transno);
-		EXIT;
 		return;
 	}
 	CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n",
@@ -2456,16 +2429,10 @@ free_req:
 		list_del_init(&req->rq_replay_list);
 		__ptlrpc_req_finished(req, 1);
 	}
-
-	EXIT;
-	return;
 }
 
 void ptlrpc_cleanup_client(struct obd_import *imp)
 {
-	ENTRY;
-	EXIT;
-	return;
 }
 EXPORT_SYMBOL(ptlrpc_cleanup_client);
 
@@ -2517,9 +2484,8 @@ EXPORT_SYMBOL(ptlrpc_restart_req);
  */
 struct ptlrpc_request *ptlrpc_request_addref(struct ptlrpc_request *req)
 {
-	ENTRY;
 	atomic_inc(&req->rq_refcount);
-	RETURN(req);
+	return req;
 }
 EXPORT_SYMBOL(ptlrpc_request_addref);
 
@@ -2588,7 +2554,6 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req)
 {
 	struct ptlrpc_request_set *set;
 	int rc;
-	ENTRY;
 
 	LASSERT(req->rq_set == NULL);
 	LASSERT(!req->rq_receiving_reply);
@@ -2596,7 +2561,7 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req)
 	set = ptlrpc_prep_set();
 	if (set == NULL) {
 		CERROR("Unable to allocate ptlrpc set.");
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* for distributed debugging */
@@ -2608,7 +2573,7 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req)
 	rc = ptlrpc_set_wait(set);
 	ptlrpc_set_destroy(set);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_queue_wait);
 
@@ -2629,7 +2594,6 @@ static int ptlrpc_replay_interpret(const struct lu_env *env,
 	struct ptlrpc_replay_async_args *aa = data;
 	struct obd_import *imp = req->rq_import;
 
-	ENTRY;
 	atomic_dec(&imp->imp_replay_inflight);
 
 	if (!ptlrpc_client_replied(req)) {
@@ -2710,7 +2674,7 @@ static int ptlrpc_replay_interpret(const struct lu_env *env,
 		/* this replay failed, so restart recovery */
 		ptlrpc_connect_import(imp);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2721,7 +2685,6 @@ static int ptlrpc_replay_interpret(const struct lu_env *env,
 int ptlrpc_replay_req(struct ptlrpc_request *req)
 {
 	struct ptlrpc_replay_async_args *aa;
-	ENTRY;
 
 	LASSERT(req->rq_import->imp_state == LUSTRE_IMP_REPLAY);
 
@@ -2751,7 +2714,7 @@ int ptlrpc_replay_req(struct ptlrpc_request *req)
 	ptlrpc_request_addref(req); /* ptlrpcd needs a ref */
 
 	ptlrpcd_add_req(req, PDL_POLICY_LOCAL, -1);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_replay_req);
 
@@ -2761,7 +2724,6 @@ EXPORT_SYMBOL(ptlrpc_replay_req);
 void ptlrpc_abort_inflight(struct obd_import *imp)
 {
 	struct list_head *tmp, *n;
-	ENTRY;
 
 	/* Make sure that no new requests get processed for this import.
 	 * ptlrpc_{queue,set}_wait must (and does) hold imp_lock while testing
@@ -2809,8 +2771,6 @@ void ptlrpc_abort_inflight(struct obd_import *imp)
 		ptlrpc_free_committed(imp);
 
 	spin_unlock(&imp->imp_lock);
-
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_abort_inflight);
 
@@ -2969,18 +2929,17 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
 {
 	struct ptlrpc_request	 *req = NULL;
 	struct ptlrpc_work_async_args *args;
-	ENTRY;
 
 	might_sleep();
 
 	if (cb == NULL)
-		RETURN(ERR_PTR(-EINVAL));
+		return ERR_PTR(-EINVAL);
 
 	/* copy some code from deprecated fakereq. */
 	OBD_ALLOC_PTR(req);
 	if (req == NULL) {
 		CERROR("ptlrpc: run out of memory!\n");
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 	}
 
 	req->rq_send_state = LUSTRE_IMP_FULL;
@@ -3009,7 +2968,7 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
 	args->cb     = cb;
 	args->cbdata = cbdata;
 
-	RETURN(req);
+	return req;
 }
 EXPORT_SYMBOL(ptlrpcd_alloc_work);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c
index a0757f3..17ca842 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/connection.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c
@@ -49,7 +49,6 @@ ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self,
 		      struct obd_uuid *uuid)
 {
 	struct ptlrpc_connection *conn, *conn2;
-	ENTRY;
 
 	conn = cfs_hash_lookup(conn_hash, &peer);
 	if (conn)
@@ -57,7 +56,7 @@ ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self,
 
 	OBD_ALLOC_PTR(conn);
 	if (!conn)
-		RETURN(NULL);
+		return NULL;
 
 	conn->c_peer = peer;
 	conn->c_self = self;
@@ -80,7 +79,6 @@ ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self,
 		OBD_FREE_PTR(conn);
 		conn = conn2;
 	}
-	EXIT;
 out:
 	CDEBUG(D_INFO, "conn=%p refcount %d to %s\n",
 	       conn, atomic_read(&conn->c_refcount),
@@ -92,10 +90,9 @@ EXPORT_SYMBOL(ptlrpc_connection_get);
 int ptlrpc_connection_put(struct ptlrpc_connection *conn)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (!conn)
-		RETURN(rc);
+		return rc;
 
 	LASSERT(atomic_read(&conn->c_refcount) > 1);
 
@@ -122,28 +119,24 @@ int ptlrpc_connection_put(struct ptlrpc_connection *conn)
 	       conn, atomic_read(&conn->c_refcount),
 	       libcfs_nid2str(conn->c_peer.nid));
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_connection_put);
 
 struct ptlrpc_connection *
 ptlrpc_connection_addref(struct ptlrpc_connection *conn)
 {
-	ENTRY;
-
 	atomic_inc(&conn->c_refcount);
 	CDEBUG(D_INFO, "conn=%p refcount %d to %s\n",
 	       conn, atomic_read(&conn->c_refcount),
 	       libcfs_nid2str(conn->c_peer.nid));
 
-	RETURN(conn);
+	return conn;
 }
 EXPORT_SYMBOL(ptlrpc_connection_addref);
 
 int ptlrpc_connection_init(void)
 {
-	ENTRY;
-
 	conn_hash = cfs_hash_create("CONN_HASH",
 				    HASH_CONN_CUR_BITS,
 				    HASH_CONN_MAX_BITS,
@@ -152,16 +145,15 @@ int ptlrpc_connection_init(void)
 				    CFS_HASH_MAX_THETA,
 				    &conn_hash_ops, CFS_HASH_DEFAULT);
 	if (!conn_hash)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_connection_init);
 
-void ptlrpc_connection_fini(void) {
-	ENTRY;
+void ptlrpc_connection_fini(void)
+{
 	cfs_hash_putref(conn_hash);
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_connection_fini);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/errno.c b/drivers/staging/lustre/lustre/ptlrpc/errno.c
new file mode 100644
index 0000000..1c10063
--- /dev/null
+++ b/drivers/staging/lustre/lustre/ptlrpc/errno.c
@@ -0,0 +1,380 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (C) 2011 FUJITSU LIMITED.  All rights reserved.
+ *
+ * Copyright (c) 2013, Intel Corporation.
+ */
+
+#include <linux/libcfs/libcfs.h>
+#include <lustre/lustre_errno.h>
+
+/*
+ * The two translation tables below must define a one-to-one mapping between
+ * host and network errnos.
+ *
+ * EWOULDBLOCK is equal to EAGAIN on all architectures except for parisc, which
+ * appears irrelevant.  Thus, existing references to EWOULDBLOCK are fine.
+ *
+ * EDEADLOCK is equal to EDEADLK on x86 but not on sparc, at least.  A sparc
+ * host has no context-free way to determine if a LUSTRE_EDEADLK represents an
+ * EDEADLK or an EDEADLOCK.  Therefore, all existing references to EDEADLOCK
+ * that need to be transferred on wire have been replaced with EDEADLK.
+ */
+static int lustre_errno_hton_mapping[] = {
+	[EPERM]			= LUSTRE_EPERM,
+	[ENOENT]		= LUSTRE_ENOENT,
+	[ESRCH]			= LUSTRE_ESRCH,
+	[EINTR]			= LUSTRE_EINTR,
+	[EIO]			= LUSTRE_EIO,
+	[ENXIO]			= LUSTRE_ENXIO,
+	[E2BIG]			= LUSTRE_E2BIG,
+	[ENOEXEC]		= LUSTRE_ENOEXEC,
+	[EBADF]			= LUSTRE_EBADF,
+	[ECHILD]		= LUSTRE_ECHILD,
+	[EAGAIN]		= LUSTRE_EAGAIN,
+	[ENOMEM]		= LUSTRE_ENOMEM,
+	[EACCES]		= LUSTRE_EACCES,
+	[EFAULT]		= LUSTRE_EFAULT,
+	[ENOTBLK]		= LUSTRE_ENOTBLK,
+	[EBUSY]			= LUSTRE_EBUSY,
+	[EEXIST]		= LUSTRE_EEXIST,
+	[EXDEV]			= LUSTRE_EXDEV,
+	[ENODEV]		= LUSTRE_ENODEV,
+	[ENOTDIR]		= LUSTRE_ENOTDIR,
+	[EISDIR]		= LUSTRE_EISDIR,
+	[EINVAL]		= LUSTRE_EINVAL,
+	[ENFILE]		= LUSTRE_ENFILE,
+	[EMFILE]		= LUSTRE_EMFILE,
+	[ENOTTY]		= LUSTRE_ENOTTY,
+	[ETXTBSY]		= LUSTRE_ETXTBSY,
+	[EFBIG]			= LUSTRE_EFBIG,
+	[ENOSPC]		= LUSTRE_ENOSPC,
+	[ESPIPE]		= LUSTRE_ESPIPE,
+	[EROFS]			= LUSTRE_EROFS,
+	[EMLINK]		= LUSTRE_EMLINK,
+	[EPIPE]			= LUSTRE_EPIPE,
+	[EDOM]			= LUSTRE_EDOM,
+	[ERANGE]		= LUSTRE_ERANGE,
+	[EDEADLK]		= LUSTRE_EDEADLK,
+	[ENAMETOOLONG]		= LUSTRE_ENAMETOOLONG,
+	[ENOLCK]		= LUSTRE_ENOLCK,
+	[ENOSYS]		= LUSTRE_ENOSYS,
+	[ENOTEMPTY]		= LUSTRE_ENOTEMPTY,
+	[ELOOP]			= LUSTRE_ELOOP,
+	[ENOMSG]		= LUSTRE_ENOMSG,
+	[EIDRM]			= LUSTRE_EIDRM,
+	[ECHRNG]		= LUSTRE_ECHRNG,
+	[EL2NSYNC]		= LUSTRE_EL2NSYNC,
+	[EL3HLT]		= LUSTRE_EL3HLT,
+	[EL3RST]		= LUSTRE_EL3RST,
+	[ELNRNG]		= LUSTRE_ELNRNG,
+	[EUNATCH]		= LUSTRE_EUNATCH,
+	[ENOCSI]		= LUSTRE_ENOCSI,
+	[EL2HLT]		= LUSTRE_EL2HLT,
+	[EBADE]			= LUSTRE_EBADE,
+	[EBADR]			= LUSTRE_EBADR,
+	[EXFULL]		= LUSTRE_EXFULL,
+	[ENOANO]		= LUSTRE_ENOANO,
+	[EBADRQC]		= LUSTRE_EBADRQC,
+	[EBADSLT]		= LUSTRE_EBADSLT,
+	[EBFONT]		= LUSTRE_EBFONT,
+	[ENOSTR]		= LUSTRE_ENOSTR,
+	[ENODATA]		= LUSTRE_ENODATA,
+	[ETIME]			= LUSTRE_ETIME,
+	[ENOSR]			= LUSTRE_ENOSR,
+	[ENONET]		= LUSTRE_ENONET,
+	[ENOPKG]		= LUSTRE_ENOPKG,
+	[EREMOTE]		= LUSTRE_EREMOTE,
+	[ENOLINK]		= LUSTRE_ENOLINK,
+	[EADV]			= LUSTRE_EADV,
+	[ESRMNT]		= LUSTRE_ESRMNT,
+	[ECOMM]			= LUSTRE_ECOMM,
+	[EPROTO]		= LUSTRE_EPROTO,
+	[EMULTIHOP]		= LUSTRE_EMULTIHOP,
+	[EDOTDOT]		= LUSTRE_EDOTDOT,
+	[EBADMSG]		= LUSTRE_EBADMSG,
+	[EOVERFLOW]		= LUSTRE_EOVERFLOW,
+	[ENOTUNIQ]		= LUSTRE_ENOTUNIQ,
+	[EBADFD]		= LUSTRE_EBADFD,
+	[EREMCHG]		= LUSTRE_EREMCHG,
+	[ELIBACC]		= LUSTRE_ELIBACC,
+	[ELIBBAD]		= LUSTRE_ELIBBAD,
+	[ELIBSCN]		= LUSTRE_ELIBSCN,
+	[ELIBMAX]		= LUSTRE_ELIBMAX,
+	[ELIBEXEC]		= LUSTRE_ELIBEXEC,
+	[EILSEQ]		= LUSTRE_EILSEQ,
+	[ERESTART]		= LUSTRE_ERESTART,
+	[ESTRPIPE]		= LUSTRE_ESTRPIPE,
+	[EUSERS]		= LUSTRE_EUSERS,
+	[ENOTSOCK]		= LUSTRE_ENOTSOCK,
+	[EDESTADDRREQ]		= LUSTRE_EDESTADDRREQ,
+	[EMSGSIZE]		= LUSTRE_EMSGSIZE,
+	[EPROTOTYPE]		= LUSTRE_EPROTOTYPE,
+	[ENOPROTOOPT]		= LUSTRE_ENOPROTOOPT,
+	[EPROTONOSUPPORT]	= LUSTRE_EPROTONOSUPPORT,
+	[ESOCKTNOSUPPORT]	= LUSTRE_ESOCKTNOSUPPORT,
+	[EOPNOTSUPP]		= LUSTRE_EOPNOTSUPP,
+	[EPFNOSUPPORT]		= LUSTRE_EPFNOSUPPORT,
+	[EAFNOSUPPORT]		= LUSTRE_EAFNOSUPPORT,
+	[EADDRINUSE]		= LUSTRE_EADDRINUSE,
+	[EADDRNOTAVAIL]		= LUSTRE_EADDRNOTAVAIL,
+	[ENETDOWN]		= LUSTRE_ENETDOWN,
+	[ENETUNREACH]		= LUSTRE_ENETUNREACH,
+	[ENETRESET]		= LUSTRE_ENETRESET,
+	[ECONNABORTED]		= LUSTRE_ECONNABORTED,
+	[ECONNRESET]		= LUSTRE_ECONNRESET,
+	[ENOBUFS]		= LUSTRE_ENOBUFS,
+	[EISCONN]		= LUSTRE_EISCONN,
+	[ENOTCONN]		= LUSTRE_ENOTCONN,
+	[ESHUTDOWN]		= LUSTRE_ESHUTDOWN,
+	[ETOOMANYREFS]		= LUSTRE_ETOOMANYREFS,
+	[ETIMEDOUT]		= LUSTRE_ETIMEDOUT,
+	[ECONNREFUSED]		= LUSTRE_ECONNREFUSED,
+	[EHOSTDOWN]		= LUSTRE_EHOSTDOWN,
+	[EHOSTUNREACH]		= LUSTRE_EHOSTUNREACH,
+	[EALREADY]		= LUSTRE_EALREADY,
+	[EINPROGRESS]		= LUSTRE_EINPROGRESS,
+	[ESTALE]		= LUSTRE_ESTALE,
+	[EUCLEAN]		= LUSTRE_EUCLEAN,
+	[ENOTNAM]		= LUSTRE_ENOTNAM,
+	[ENAVAIL]		= LUSTRE_ENAVAIL,
+	[EISNAM]		= LUSTRE_EISNAM,
+	[EREMOTEIO]		= LUSTRE_EREMOTEIO,
+	[EDQUOT]		= LUSTRE_EDQUOT,
+	[ENOMEDIUM]		= LUSTRE_ENOMEDIUM,
+	[EMEDIUMTYPE]		= LUSTRE_EMEDIUMTYPE,
+	[ECANCELED]		= LUSTRE_ECANCELED,
+	[ENOKEY]		= LUSTRE_ENOKEY,
+	[EKEYEXPIRED]		= LUSTRE_EKEYEXPIRED,
+	[EKEYREVOKED]		= LUSTRE_EKEYREVOKED,
+	[EKEYREJECTED]		= LUSTRE_EKEYREJECTED,
+	[EOWNERDEAD]		= LUSTRE_EOWNERDEAD,
+	[ENOTRECOVERABLE]	= LUSTRE_ENOTRECOVERABLE,
+	[ERESTARTSYS]		= LUSTRE_ERESTARTSYS,
+	[ERESTARTNOINTR]	= LUSTRE_ERESTARTNOINTR,
+	[ERESTARTNOHAND]	= LUSTRE_ERESTARTNOHAND,
+	[ENOIOCTLCMD]		= LUSTRE_ENOIOCTLCMD,
+	[ERESTART_RESTARTBLOCK]	= LUSTRE_ERESTART_RESTARTBLOCK,
+	[EBADHANDLE]		= LUSTRE_EBADHANDLE,
+	[ENOTSYNC]		= LUSTRE_ENOTSYNC,
+	[EBADCOOKIE]		= LUSTRE_EBADCOOKIE,
+	[ENOTSUPP]		= LUSTRE_ENOTSUPP,
+	[ETOOSMALL]		= LUSTRE_ETOOSMALL,
+	[ESERVERFAULT]		= LUSTRE_ESERVERFAULT,
+	[EBADTYPE]		= LUSTRE_EBADTYPE,
+	[EJUKEBOX]		= LUSTRE_EJUKEBOX,
+	[EIOCBQUEUED]		= LUSTRE_EIOCBQUEUED,
+};
+
+static int lustre_errno_ntoh_mapping[] = {
+	[LUSTRE_EPERM]			= EPERM,
+	[LUSTRE_ENOENT]			= ENOENT,
+	[LUSTRE_ESRCH]			= ESRCH,
+	[LUSTRE_EINTR]			= EINTR,
+	[LUSTRE_EIO]			= EIO,
+	[LUSTRE_ENXIO]			= ENXIO,
+	[LUSTRE_E2BIG]			= E2BIG,
+	[LUSTRE_ENOEXEC]		= ENOEXEC,
+	[LUSTRE_EBADF]			= EBADF,
+	[LUSTRE_ECHILD]			= ECHILD,
+	[LUSTRE_EAGAIN]			= EAGAIN,
+	[LUSTRE_ENOMEM]			= ENOMEM,
+	[LUSTRE_EACCES]			= EACCES,
+	[LUSTRE_EFAULT]			= EFAULT,
+	[LUSTRE_ENOTBLK]		= ENOTBLK,
+	[LUSTRE_EBUSY]			= EBUSY,
+	[LUSTRE_EEXIST]			= EEXIST,
+	[LUSTRE_EXDEV]			= EXDEV,
+	[LUSTRE_ENODEV]			= ENODEV,
+	[LUSTRE_ENOTDIR]		= ENOTDIR,
+	[LUSTRE_EISDIR]			= EISDIR,
+	[LUSTRE_EINVAL]			= EINVAL,
+	[LUSTRE_ENFILE]			= ENFILE,
+	[LUSTRE_EMFILE]			= EMFILE,
+	[LUSTRE_ENOTTY]			= ENOTTY,
+	[LUSTRE_ETXTBSY]		= ETXTBSY,
+	[LUSTRE_EFBIG]			= EFBIG,
+	[LUSTRE_ENOSPC]			= ENOSPC,
+	[LUSTRE_ESPIPE]			= ESPIPE,
+	[LUSTRE_EROFS]			= EROFS,
+	[LUSTRE_EMLINK]			= EMLINK,
+	[LUSTRE_EPIPE]			= EPIPE,
+	[LUSTRE_EDOM]			= EDOM,
+	[LUSTRE_ERANGE]			= ERANGE,
+	[LUSTRE_EDEADLK]		= EDEADLK,
+	[LUSTRE_ENAMETOOLONG]		= ENAMETOOLONG,
+	[LUSTRE_ENOLCK]			= ENOLCK,
+	[LUSTRE_ENOSYS]			= ENOSYS,
+	[LUSTRE_ENOTEMPTY]		= ENOTEMPTY,
+	[LUSTRE_ELOOP]			= ELOOP,
+	[LUSTRE_ENOMSG]			= ENOMSG,
+	[LUSTRE_EIDRM]			= EIDRM,
+	[LUSTRE_ECHRNG]			= ECHRNG,
+	[LUSTRE_EL2NSYNC]		= EL2NSYNC,
+	[LUSTRE_EL3HLT]			= EL3HLT,
+	[LUSTRE_EL3RST]			= EL3RST,
+	[LUSTRE_ELNRNG]			= ELNRNG,
+	[LUSTRE_EUNATCH]		= EUNATCH,
+	[LUSTRE_ENOCSI]			= ENOCSI,
+	[LUSTRE_EL2HLT]			= EL2HLT,
+	[LUSTRE_EBADE]			= EBADE,
+	[LUSTRE_EBADR]			= EBADR,
+	[LUSTRE_EXFULL]			= EXFULL,
+	[LUSTRE_ENOANO]			= ENOANO,
+	[LUSTRE_EBADRQC]		= EBADRQC,
+	[LUSTRE_EBADSLT]		= EBADSLT,
+	[LUSTRE_EBFONT]			= EBFONT,
+	[LUSTRE_ENOSTR]			= ENOSTR,
+	[LUSTRE_ENODATA]		= ENODATA,
+	[LUSTRE_ETIME]			= ETIME,
+	[LUSTRE_ENOSR]			= ENOSR,
+	[LUSTRE_ENONET]			= ENONET,
+	[LUSTRE_ENOPKG]			= ENOPKG,
+	[LUSTRE_EREMOTE]		= EREMOTE,
+	[LUSTRE_ENOLINK]		= ENOLINK,
+	[LUSTRE_EADV]			= EADV,
+	[LUSTRE_ESRMNT]			= ESRMNT,
+	[LUSTRE_ECOMM]			= ECOMM,
+	[LUSTRE_EPROTO]			= EPROTO,
+	[LUSTRE_EMULTIHOP]		= EMULTIHOP,
+	[LUSTRE_EDOTDOT]		= EDOTDOT,
+	[LUSTRE_EBADMSG]		= EBADMSG,
+	[LUSTRE_EOVERFLOW]		= EOVERFLOW,
+	[LUSTRE_ENOTUNIQ]		= ENOTUNIQ,
+	[LUSTRE_EBADFD]			= EBADFD,
+	[LUSTRE_EREMCHG]		= EREMCHG,
+	[LUSTRE_ELIBACC]		= ELIBACC,
+	[LUSTRE_ELIBBAD]		= ELIBBAD,
+	[LUSTRE_ELIBSCN]		= ELIBSCN,
+	[LUSTRE_ELIBMAX]		= ELIBMAX,
+	[LUSTRE_ELIBEXEC]		= ELIBEXEC,
+	[LUSTRE_EILSEQ]			= EILSEQ,
+	[LUSTRE_ERESTART]		= ERESTART,
+	[LUSTRE_ESTRPIPE]		= ESTRPIPE,
+	[LUSTRE_EUSERS]			= EUSERS,
+	[LUSTRE_ENOTSOCK]		= ENOTSOCK,
+	[LUSTRE_EDESTADDRREQ]		= EDESTADDRREQ,
+	[LUSTRE_EMSGSIZE]		= EMSGSIZE,
+	[LUSTRE_EPROTOTYPE]		= EPROTOTYPE,
+	[LUSTRE_ENOPROTOOPT]		= ENOPROTOOPT,
+	[LUSTRE_EPROTONOSUPPORT]	= EPROTONOSUPPORT,
+	[LUSTRE_ESOCKTNOSUPPORT]	= ESOCKTNOSUPPORT,
+	[LUSTRE_EOPNOTSUPP]		= EOPNOTSUPP,
+	[LUSTRE_EPFNOSUPPORT]		= EPFNOSUPPORT,
+	[LUSTRE_EAFNOSUPPORT]		= EAFNOSUPPORT,
+	[LUSTRE_EADDRINUSE]		= EADDRINUSE,
+	[LUSTRE_EADDRNOTAVAIL]		= EADDRNOTAVAIL,
+	[LUSTRE_ENETDOWN]		= ENETDOWN,
+	[LUSTRE_ENETUNREACH]		= ENETUNREACH,
+	[LUSTRE_ENETRESET]		= ENETRESET,
+	[LUSTRE_ECONNABORTED]		= ECONNABORTED,
+	[LUSTRE_ECONNRESET]		= ECONNRESET,
+	[LUSTRE_ENOBUFS]		= ENOBUFS,
+	[LUSTRE_EISCONN]		= EISCONN,
+	[LUSTRE_ENOTCONN]		= ENOTCONN,
+	[LUSTRE_ESHUTDOWN]		= ESHUTDOWN,
+	[LUSTRE_ETOOMANYREFS]		= ETOOMANYREFS,
+	[LUSTRE_ETIMEDOUT]		= ETIMEDOUT,
+	[LUSTRE_ECONNREFUSED]		= ECONNREFUSED,
+	[LUSTRE_EHOSTDOWN]		= EHOSTDOWN,
+	[LUSTRE_EHOSTUNREACH]		= EHOSTUNREACH,
+	[LUSTRE_EALREADY]		= EALREADY,
+	[LUSTRE_EINPROGRESS]		= EINPROGRESS,
+	[LUSTRE_ESTALE]			= ESTALE,
+	[LUSTRE_EUCLEAN]		= EUCLEAN,
+	[LUSTRE_ENOTNAM]		= ENOTNAM,
+	[LUSTRE_ENAVAIL]		= ENAVAIL,
+	[LUSTRE_EISNAM]			= EISNAM,
+	[LUSTRE_EREMOTEIO]		= EREMOTEIO,
+	[LUSTRE_EDQUOT]			= EDQUOT,
+	[LUSTRE_ENOMEDIUM]		= ENOMEDIUM,
+	[LUSTRE_EMEDIUMTYPE]		= EMEDIUMTYPE,
+	[LUSTRE_ECANCELED]		= ECANCELED,
+	[LUSTRE_ENOKEY]			= ENOKEY,
+	[LUSTRE_EKEYEXPIRED]		= EKEYEXPIRED,
+	[LUSTRE_EKEYREVOKED]		= EKEYREVOKED,
+	[LUSTRE_EKEYREJECTED]		= EKEYREJECTED,
+	[LUSTRE_EOWNERDEAD]		= EOWNERDEAD,
+	[LUSTRE_ENOTRECOVERABLE]	= ENOTRECOVERABLE,
+	[LUSTRE_ERESTARTSYS]		= ERESTARTSYS,
+	[LUSTRE_ERESTARTNOINTR]		= ERESTARTNOINTR,
+	[LUSTRE_ERESTARTNOHAND]		= ERESTARTNOHAND,
+	[LUSTRE_ENOIOCTLCMD]		= ENOIOCTLCMD,
+	[LUSTRE_ERESTART_RESTARTBLOCK]	= ERESTART_RESTARTBLOCK,
+	[LUSTRE_EBADHANDLE]		= EBADHANDLE,
+	[LUSTRE_ENOTSYNC]		= ENOTSYNC,
+	[LUSTRE_EBADCOOKIE]		= EBADCOOKIE,
+	[LUSTRE_ENOTSUPP]		= ENOTSUPP,
+	[LUSTRE_ETOOSMALL]		= ETOOSMALL,
+	[LUSTRE_ESERVERFAULT]		= ESERVERFAULT,
+	[LUSTRE_EBADTYPE]		= EBADTYPE,
+	[LUSTRE_EJUKEBOX]		= EJUKEBOX,
+	[LUSTRE_EIOCBQUEUED]		= EIOCBQUEUED,
+};
+
+unsigned int lustre_errno_hton(unsigned int h)
+{
+	unsigned int n;
+
+	if (h == 0) {
+		n = 0;
+	} else if (h < ARRAY_SIZE(lustre_errno_hton_mapping)) {
+		n = lustre_errno_hton_mapping[h];
+		if (n == 0)
+			goto generic;
+	} else {
+generic:
+		/*
+		 * A generic errno is better than the unknown one that could
+		 * mean anything to a different host.
+		 */
+		n = LUSTRE_EIO;
+	}
+
+	return n;
+}
+EXPORT_SYMBOL(lustre_errno_hton);
+
+unsigned int lustre_errno_ntoh(unsigned int n)
+{
+	unsigned int h;
+
+	if (n == 0) {
+		h = 0;
+	} else if (n < ARRAY_SIZE(lustre_errno_ntoh_mapping)) {
+		h = lustre_errno_ntoh_mapping[n];
+		if (h == 0)
+			goto generic;
+	} else {
+generic:
+		/*
+		 * Similar to the situation in lustre_errno_hton(), an unknown
+		 * network errno could coincide with anything.  Hence, it is
+		 * better to return a generic errno.
+		 */
+		h = EIO;
+	}
+
+	return h;
+}
+EXPORT_SYMBOL(lustre_errno_ntoh);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c
index 0264c10..58d089c 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/events.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/events.c
@@ -55,7 +55,6 @@ void request_out_callback(lnet_event_t *ev)
 {
 	struct ptlrpc_cb_id   *cbid = ev->md.user_ptr;
 	struct ptlrpc_request *req = cbid->cbid_arg;
-	ENTRY;
 
 	LASSERT (ev->type == LNET_EVENT_SEND ||
 		 ev->type == LNET_EVENT_UNLINK);
@@ -79,8 +78,6 @@ void request_out_callback(lnet_event_t *ev)
 	}
 
 	ptlrpc_req_finished(req);
-
-	EXIT;
 }
 
 /*
@@ -90,7 +87,6 @@ void reply_in_callback(lnet_event_t *ev)
 {
 	struct ptlrpc_cb_id   *cbid = ev->md.user_ptr;
 	struct ptlrpc_request *req = cbid->cbid_arg;
-	ENTRY;
 
 	DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status);
 
@@ -166,7 +162,6 @@ out_wake:
 	 * since we don't have our own ref */
 	ptlrpc_client_wake_req(req);
 	spin_unlock(&req->rq_lock);
-	EXIT;
 }
 
 /*
@@ -177,7 +172,6 @@ void client_bulk_callback (lnet_event_t *ev)
 	struct ptlrpc_cb_id     *cbid = ev->md.user_ptr;
 	struct ptlrpc_bulk_desc *desc = cbid->cbid_arg;
 	struct ptlrpc_request   *req;
-	ENTRY;
 
 	LASSERT ((desc->bd_type == BULK_PUT_SINK &&
 		  ev->type == LNET_EVENT_PUT) ||
@@ -220,7 +214,6 @@ void client_bulk_callback (lnet_event_t *ev)
 		ptlrpc_client_wake_req(desc->bd_req);
 
 	spin_unlock(&desc->bd_lock);
-	EXIT;
 }
 
 /*
@@ -289,7 +282,6 @@ void request_in_callback(lnet_event_t *ev)
 	struct ptlrpc_service_part	  *svcpt = rqbd->rqbd_svcpt;
 	struct ptlrpc_service	     *service = svcpt->scp_service;
 	struct ptlrpc_request	     *req;
-	ENTRY;
 
 	LASSERT (ev->type == LNET_EVENT_PUT ||
 		 ev->type == LNET_EVENT_UNLINK);
@@ -378,7 +370,6 @@ void request_in_callback(lnet_event_t *ev)
 	wake_up(&svcpt->scp_waitq);
 
 	spin_unlock(&svcpt->scp_lock);
-	EXIT;
 }
 
 /*
@@ -389,7 +380,6 @@ void reply_out_callback(lnet_event_t *ev)
 	struct ptlrpc_cb_id	  *cbid = ev->md.user_ptr;
 	struct ptlrpc_reply_state *rs = cbid->cbid_arg;
 	struct ptlrpc_service_part *svcpt = rs->rs_svcpt;
-	ENTRY;
 
 	LASSERT (ev->type == LNET_EVENT_SEND ||
 		 ev->type == LNET_EVENT_ACK ||
@@ -400,7 +390,6 @@ void reply_out_callback(lnet_event_t *ev)
 		 * net's ref on 'rs' */
 		LASSERT (ev->unlinked);
 		ptlrpc_rs_decref(rs);
-		EXIT;
 		return;
 	}
 
@@ -421,7 +410,6 @@ void reply_out_callback(lnet_event_t *ev)
 		spin_unlock(&rs->rs_lock);
 		spin_unlock(&svcpt->scp_rep_lock);
 	}
-	EXIT;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h
index feac604..0e9f6c4 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h
@@ -100,7 +100,7 @@ struct subflavor_desc {
 /* Each mechanism is described by the following struct: */
 struct gss_api_mech {
 	struct list_head	      gm_list;
-	module_t	   *gm_owner;
+	struct module	   *gm_owner;
 	char		   *gm_name;
 	rawobj_t		gm_oid;
 	atomic_t	    gm_count;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c
index ed95bbb..b518d8a 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c
@@ -68,7 +68,6 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
 	__u32			    maj;
 	int			      offset;
 	int			      rc;
-	ENTRY;
 
 	LASSERT(req->rq_pack_bulk);
 	LASSERT(req->rq_bulk_read || req->rq_bulk_write);
@@ -104,7 +103,7 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
 	bsd->bsd_svc = SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc);
 
 	if (bsd->bsd_svc == SPTLRPC_BULK_SVC_NULL)
-		RETURN(0);
+		return 0;
 
 	LASSERT(bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG ||
 		bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV);
@@ -132,18 +131,18 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
 					   &token);
 			if (maj != GSS_S_COMPLETE) {
 				CWARN("failed to sign bulk data: %x\n", maj);
-				RETURN(-EACCES);
+				return -EACCES;
 			}
 		} else {
 			/* privacy mode */
 			if (desc->bd_iov_count == 0)
-				RETURN(0);
+				return 0;
 
 			rc = sptlrpc_enc_pool_get_pages(desc);
 			if (rc) {
 				CERROR("bulk write: failed to allocate "
 				       "encryption pages: %d\n", rc);
-				RETURN(rc);
+				return rc;
 			}
 
 			token.data = bsd->bsd_data;
@@ -153,12 +152,12 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
 			maj = lgss_wrap_bulk(gctx->gc_mechctx, desc, &token, 0);
 			if (maj != GSS_S_COMPLETE) {
 				CWARN("fail to encrypt bulk data: %x\n", maj);
-				RETURN(-EACCES);
+				return -EACCES;
 			}
 		}
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
@@ -171,7 +170,6 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
 	rawobj_t			 token;
 	__u32			    maj;
 	int			      roff, voff;
-	ENTRY;
 
 	LASSERT(req->rq_pack_bulk);
 	LASSERT(req->rq_bulk_read || req->rq_bulk_write);
@@ -220,7 +218,7 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
 		       "(%u,%u,%u) != (%u,%u,%u)\n",
 		       bsdr->bsd_version, bsdr->bsd_type, bsdr->bsd_svc,
 		       bsdv->bsd_version, bsdv->bsd_type, bsdv->bsd_svc);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	LASSERT(bsdv->bsd_svc == SPTLRPC_BULK_SVC_NULL ||
@@ -235,7 +233,7 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
 	if (req->rq_bulk_write) {
 		if (bsdv->bsd_flags & BSD_FL_ERR) {
 			CERROR("server reported bulk i/o failure\n");
-			RETURN(-EIO);
+			return -EIO;
 		}
 
 		if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV)
@@ -270,12 +268,12 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
 					      &token);
 			if (maj != GSS_S_COMPLETE) {
 				CERROR("failed to verify bulk read: %x\n", maj);
-				RETURN(-EACCES);
+				return -EACCES;
 			}
 		} else if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV) {
 			desc->bd_nob = bsdv->bsd_nob;
 			if (desc->bd_nob == 0)
-				RETURN(0);
+				return 0;
 
 			token.data = bsdv->bsd_data;
 			token.len = lustre_msg_buflen(vmsg, voff) -
@@ -286,14 +284,14 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
 			if (maj != GSS_S_COMPLETE) {
 				CERROR("failed to decrypt bulk read: %x\n",
 				       maj);
-				RETURN(-EACCES);
+				return -EACCES;
 			}
 
 			desc->bd_nob_transferred = desc->bd_nob;
 		}
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static int gss_prep_bulk(struct ptlrpc_bulk_desc *desc,
@@ -318,21 +316,20 @@ int gss_cli_prep_bulk(struct ptlrpc_request *req,
 		      struct ptlrpc_bulk_desc *desc)
 {
 	int	     rc;
-	ENTRY;
 
 	LASSERT(req->rq_cli_ctx);
 	LASSERT(req->rq_pack_bulk);
 	LASSERT(req->rq_bulk_read);
 
 	if (SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc) != SPTLRPC_BULK_SVC_PRIV)
-		RETURN(0);
+		return 0;
 
 	rc = gss_prep_bulk(desc, ctx2gctx(req->rq_cli_ctx)->gc_mechctx);
 	if (rc)
 		CERROR("bulk read: failed to prepare encryption "
 		       "pages: %d\n", rc);
 
-	RETURN(rc);
+	return rc;
 }
 
 int gss_svc_prep_bulk(struct ptlrpc_request *req,
@@ -341,7 +338,6 @@ int gss_svc_prep_bulk(struct ptlrpc_request *req,
 	struct gss_svc_reqctx	*grctx;
 	struct ptlrpc_bulk_sec_desc  *bsd;
 	int			   rc;
-	ENTRY;
 
 	LASSERT(req->rq_svc_ctx);
 	LASSERT(req->rq_pack_bulk);
@@ -355,14 +351,14 @@ int gss_svc_prep_bulk(struct ptlrpc_request *req,
 
 	bsd = grctx->src_reqbsd;
 	if (bsd->bsd_svc != SPTLRPC_BULK_SVC_PRIV)
-		RETURN(0);
+		return 0;
 
 	rc = gss_prep_bulk(desc, grctx->src_ctx->gsc_mechctx);
 	if (rc)
 		CERROR("bulk write: failed to prepare encryption "
 		       "pages: %d\n", rc);
 
-	RETURN(rc);
+	return rc;
 }
 
 int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
@@ -372,7 +368,6 @@ int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
 	struct ptlrpc_bulk_sec_desc  *bsdr, *bsdv;
 	rawobj_t		      token;
 	__u32			 maj;
-	ENTRY;
 
 	LASSERT(req->rq_svc_ctx);
 	LASSERT(req->rq_pack_bulk);
@@ -404,7 +399,7 @@ int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
 		if (maj != GSS_S_COMPLETE) {
 			bsdv->bsd_flags |= BSD_FL_ERR;
 			CERROR("failed to verify bulk signature: %x\n", maj);
-			RETURN(-EACCES);
+			return -EACCES;
 		}
 		break;
 	case SPTLRPC_BULK_SVC_PRIV:
@@ -412,7 +407,7 @@ int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
 			bsdv->bsd_flags |= BSD_FL_ERR;
 			CERROR("prepared nob %d doesn't match the actual "
 			       "nob %d\n", desc->bd_nob, bsdr->bsd_nob);
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (desc->bd_iov_count == 0) {
@@ -428,12 +423,12 @@ int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
 		if (maj != GSS_S_COMPLETE) {
 			bsdv->bsd_flags |= BSD_FL_ERR;
 			CERROR("failed decrypt bulk data: %x\n", maj);
-			RETURN(-EACCES);
+			return -EACCES;
 		}
 		break;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int gss_svc_wrap_bulk(struct ptlrpc_request *req,
@@ -444,7 +439,6 @@ int gss_svc_wrap_bulk(struct ptlrpc_request *req,
 	rawobj_t		      token;
 	__u32			 maj;
 	int			   rc;
-	ENTRY;
 
 	LASSERT(req->rq_svc_ctx);
 	LASSERT(req->rq_pack_bulk);
@@ -476,7 +470,7 @@ int gss_svc_wrap_bulk(struct ptlrpc_request *req,
 		if (maj != GSS_S_COMPLETE) {
 			bsdv->bsd_flags |= BSD_FL_ERR;
 			CERROR("failed to sign bulk data: %x\n", maj);
-			RETURN(-EACCES);
+			return -EACCES;
 		}
 		break;
 	case SPTLRPC_BULK_SVC_PRIV:
@@ -492,7 +486,7 @@ int gss_svc_wrap_bulk(struct ptlrpc_request *req,
 			bsdv->bsd_flags |= BSD_FL_ERR;
 			CERROR("bulk read: failed to allocate encryption "
 			       "pages: %d\n", rc);
-			RETURN(rc);
+			return rc;
 		}
 
 		token.data = bsdv->bsd_data;
@@ -503,10 +497,10 @@ int gss_svc_wrap_bulk(struct ptlrpc_request *req,
 		if (maj != GSS_S_COMPLETE) {
 			bsdv->bsd_flags |= BSD_FL_ERR;
 			CERROR("failed to encrypt bulk data: %x\n", maj);
-			RETURN(-EACCES);
+			return -EACCES;
 		}
 		break;
 	}
 
-	RETURN(0);
+	return 0;
 }
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
index 142c789..55247af 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
@@ -243,41 +243,41 @@ int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
 	if (count != sizeof(param)) {
 		CERROR("ioctl size %lu, expect %lu, please check lgss_keyring "
 		       "version\n", count, (unsigned long) sizeof(param));
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	if (copy_from_user(&param, buffer, sizeof(param))) {
 		CERROR("failed copy data from lgssd\n");
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 
 	if (param.version != GSSD_INTERFACE_VERSION) {
 		CERROR("gssd interface version %d (expect %d)\n",
 			param.version, GSSD_INTERFACE_VERSION);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* take name */
 	if (strncpy_from_user(obdname, param.uuid, sizeof(obdname)) <= 0) {
 		CERROR("Invalid obdname pointer\n");
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 
 	obd = class_name2obd(obdname);
 	if (!obd) {
 		CERROR("no such obd %s\n", obdname);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (unlikely(!obd->obd_set_up)) {
 		CERROR("obd %s not setup\n", obdname);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	spin_lock(&obd->obd_dev_lock);
 	if (obd->obd_stopping) {
 		CERROR("obd %s has stopped\n", obdname);
 		spin_unlock(&obd->obd_dev_lock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
@@ -285,7 +285,7 @@ int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
 	    strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
 		CERROR("obd %s is not a client device\n", obdname);
 		spin_unlock(&obd->obd_dev_lock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	spin_unlock(&obd->obd_dev_lock);
 
@@ -293,7 +293,7 @@ int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
 	if (obd->u.cli.cl_import == NULL) {
 		CERROR("obd %s: import has gone\n", obd->obd_name);
 		up_read(&obd->u.cli.cl_sem);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	imp = class_import_get(obd->u.cli.cl_import);
 	up_read(&obd->u.cli.cl_sem);
@@ -301,7 +301,7 @@ int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
 	if (imp->imp_deactive) {
 		CERROR("import has been deactivated\n");
 		class_import_put(imp);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	req = ptlrpc_request_alloc_pack(imp, &RQF_SEC_CTX, LUSTRE_OBD_VERSION,
@@ -368,7 +368,7 @@ out_copy:
 
 	class_import_put(imp);
 	ptlrpc_req_finished(req);
-	RETURN(rc);
+	return rc;
 }
 
 int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
@@ -378,7 +378,6 @@ int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
 	struct ptlrpc_request   *req;
 	struct ptlrpc_user_desc *pud;
 	int		      rc;
-	ENTRY;
 
 	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
 
@@ -386,7 +385,7 @@ int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
 		CDEBUG(D_SEC, "ctx %p(%u->%s) not uptodate, "
 		       "don't send destroy rpc\n", ctx,
 		       ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
-		RETURN(0);
+		return 0;
 	}
 
 	might_sleep();
@@ -434,7 +433,7 @@ int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
 out_ref:
 	ptlrpc_req_finished(req);
 out:
-	RETURN(rc);
+	return rc;
 }
 
 int __init gss_init_cli_upcall(void)
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
index bb571ae..188dbbf 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
@@ -524,7 +524,6 @@ void rvs_sec_install_root_ctx_kr(struct ptlrpc_sec *sec,
 	struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
 	struct ptlrpc_cli_ctx  *ctx;
 	cfs_time_t	      now;
-	ENTRY;
 
 	LASSERT(sec_is_reverse(sec));
 
@@ -569,11 +568,10 @@ struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
 				      struct sptlrpc_flavor *sf)
 {
 	struct gss_sec_keyring  *gsec_kr;
-	ENTRY;
 
 	OBD_ALLOC(gsec_kr, sizeof(*gsec_kr));
 	if (gsec_kr == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	INIT_HLIST_HEAD(&gsec_kr->gsk_clist);
 	gsec_kr->gsk_root_ctx = NULL;
@@ -592,11 +590,11 @@ struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
 		goto err_free;
 	}
 
-	RETURN(&gsec_kr->gsk_base.gs_base);
+	return &gsec_kr->gsk_base.gs_base;
 
 err_free:
 	OBD_FREE(gsec_kr, sizeof(*gsec_kr));
-	RETURN(NULL);
+	return NULL;
 }
 
 static
@@ -683,7 +681,6 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
 	char		    *coinfo;
 	int		      coinfo_size;
 	char		    *co_flags = "";
-	ENTRY;
 
 	LASSERT(imp != NULL);
 
@@ -697,7 +694,7 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
 		 * always succeed.
 		 */
 		if (ctx || sec_is_reverse(sec))
-			RETURN(ctx);
+			return ctx;
 	}
 
 	LASSERT(create != 0);
@@ -821,7 +818,7 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
 out:
 	if (is_root)
 		mutex_unlock(&gsec_kr->gsk_root_uc_lock);
-	RETURN(ctx);
+	return ctx;
 }
 
 static
@@ -891,7 +888,6 @@ void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec,
 	struct hlist_head	freelist = HLIST_HEAD_INIT;
 	struct hlist_node      *next;
 	struct ptlrpc_cli_ctx  *ctx;
-	ENTRY;
 
 	gsec_kr = sec2gsec_keyring(sec);
 
@@ -930,15 +926,12 @@ void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec,
 	spin_unlock(&sec->ps_lock);
 
 	dispose_ctx_list_kr(&freelist);
-	EXIT;
 }
 
 static
 int gss_sec_flush_ctx_cache_kr(struct ptlrpc_sec *sec,
 			       uid_t uid, int grace, int force)
 {
-	ENTRY;
-
 	CDEBUG(D_SEC, "sec %p(%d, nctx %d), uid %d, grace %d, force %d\n",
 	       sec, atomic_read(&sec->ps_refcount),
 	       atomic_read(&sec->ps_nctx),
@@ -949,7 +942,7 @@ int gss_sec_flush_ctx_cache_kr(struct ptlrpc_sec *sec,
 	else
 		flush_spec_ctx_cache_kr(sec, uid, grace, force);
 
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -959,7 +952,6 @@ void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec)
 	struct hlist_head	freelist = HLIST_HEAD_INIT;
 	struct hlist_node      *next;
 	struct ptlrpc_cli_ctx  *ctx;
-	ENTRY;
 
 	CWARN("running gc\n");
 
@@ -981,8 +973,6 @@ void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec)
 	spin_unlock(&sec->ps_lock);
 
 	dispose_ctx_list_kr(&freelist);
-	EXIT;
-	return;
 }
 
 static
@@ -993,7 +983,6 @@ int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq)
 	struct ptlrpc_cli_ctx  *ctx;
 	struct gss_cli_ctx     *gctx;
 	time_t		  now = cfs_time_current_sec();
-	ENTRY;
 
 	spin_lock(&sec->ps_lock);
 	hlist_for_each_entry_safe(ctx, next,
@@ -1032,7 +1021,7 @@ int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq)
 	}
 	spin_unlock(&sec->ps_lock);
 
-	RETURN(0);
+	return 0;
 }
 
 /****************************************
@@ -1148,16 +1137,15 @@ static
 int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
 {
 	int	     rc;
-	ENTRY;
 
 	if (data != NULL || datalen != 0) {
 		CERROR("invalid: data %p, len %lu\n", data, (long)datalen);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (key->payload.data != 0) {
 		CERROR("key already have payload\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* link the key to session keyring, so following context negotiation
@@ -1179,11 +1167,11 @@ int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
 		CERROR("failed to link key %08x to keyring %08x: %d\n",
 		       key->serial,
 		       key_tgcred(current)->session_keyring->serial, rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	CDEBUG(D_SEC, "key %p instantiated, ctx %p\n", key, key->payload.data);
-	RETURN(0);
+	return 0;
 }
 
 /*
@@ -1198,11 +1186,10 @@ int gss_kt_update(struct key *key, const void *data, size_t datalen)
 	rawobj_t		 tmpobj = RAWOBJ_EMPTY;
 	__u32		    datalen32 = (__u32) datalen;
 	int		      rc;
-	ENTRY;
 
 	if (data == NULL || datalen == 0) {
 		CWARN("invalid: data %p, len %lu\n", data, (long)datalen);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	/* if upcall finished negotiation too fast (mostly likely because
@@ -1216,9 +1203,9 @@ int gss_kt_update(struct key *key, const void *data, size_t datalen)
 
 		rc = key_validate(key);
 		if (rc == 0)
-			RETURN(-EAGAIN);
+			return -EAGAIN;
 		else
-			RETURN(rc);
+			return rc;
 	}
 
 	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
@@ -1229,7 +1216,7 @@ int gss_kt_update(struct key *key, const void *data, size_t datalen)
 	/* don't proceed if already refreshed */
 	if (cli_ctx_is_refreshed(ctx)) {
 		CWARN("ctx already done refresh\n");
-		RETURN(0);
+		return 0;
 	}
 
 	sptlrpc_cli_ctx_get(ctx);
@@ -1304,7 +1291,7 @@ out:
 
 	/* let user space think it's a success */
 	sptlrpc_cli_ctx_put(ctx, 1);
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -1316,10 +1303,8 @@ int gss_kt_match(const struct key *key, const void *desc)
 static
 void gss_kt_destroy(struct key *key)
 {
-	ENTRY;
 	LASSERT(key->payload.data == NULL);
 	CDEBUG(D_SEC, "destroy key %p\n", key);
-	EXIT;
 }
 
 static
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
index 4b28931..c106a9e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
@@ -54,6 +54,7 @@
 #include <linux/slab.h>
 #include <linux/crypto.h>
 #include <linux/mutex.h>
+#include <linux/crypto.h>
 
 #include <obd.h>
 #include <obd_class.h>
@@ -147,14 +148,14 @@ static const char * enctype2str(__u32 enctype)
 static
 int keyblock_init(struct krb5_keyblock *kb, char *alg_name, int alg_mode)
 {
-	kb->kb_tfm = ll_crypto_alloc_blkcipher(alg_name, alg_mode, 0);
+	kb->kb_tfm = crypto_alloc_blkcipher(alg_name, alg_mode, 0);
 	if (IS_ERR(kb->kb_tfm)) {
 		CERROR("failed to alloc tfm: %s, mode %d\n",
 		       alg_name, alg_mode);
 		return -1;
 	}
 
-	if (ll_crypto_blkcipher_setkey(kb->kb_tfm, kb->kb_key.data, kb->kb_key.len)) {
+	if (crypto_blkcipher_setkey(kb->kb_tfm, kb->kb_key.data, kb->kb_key.len)) {
 		CERROR("failed to set %s key, len %d\n",
 		       alg_name, kb->kb_key.len);
 		return -1;
@@ -197,7 +198,7 @@ void keyblock_free(struct krb5_keyblock *kb)
 {
 	rawobj_free(&kb->kb_key);
 	if (kb->kb_tfm)
-		ll_crypto_free_blkcipher(kb->kb_tfm);
+		crypto_free_blkcipher(kb->kb_tfm);
 }
 
 static
@@ -341,7 +342,7 @@ __u32 import_context_rfc1964(struct krb5_ctx *kctx, char *p, char *end)
 	if (p != end)
 		goto out_err;
 
-	CDEBUG(D_SEC, "succesfully imported rfc1964 context\n");
+	CDEBUG(D_SEC, "successfully imported rfc1964 context\n");
 	return 0;
 out_err:
 	return GSS_S_FAILURE;
@@ -403,7 +404,7 @@ __u32 import_context_rfc4121(struct krb5_ctx *kctx, char *p, char *end)
 	if (get_keyblock(&p, end, &kctx->kc_keyc, keysize))
 		goto out_err;
 
-	CDEBUG(D_SEC, "succesfully imported v2 context\n");
+	CDEBUG(D_SEC, "successfully imported v2 context\n");
 	return 0;
 out_err:
 	return GSS_S_FAILURE;
@@ -494,7 +495,7 @@ __u32 gss_copy_reverse_context_kerberos(struct gss_ctx *gctx,
 		goto out_err;
 
 	gctx_new->internal_ctx_id = knew;
-	CDEBUG(D_SEC, "succesfully copied reverse context\n");
+	CDEBUG(D_SEC, "successfully copied reverse context\n");
 	return GSS_S_COMPLETE;
 
 out_err:
@@ -529,7 +530,7 @@ void buf_to_sg(struct scatterlist *sg, void *ptr, int len)
 }
 
 static
-__u32 krb5_encrypt(struct ll_crypto_cipher *tfm,
+__u32 krb5_encrypt(struct crypto_blkcipher *tfm,
 		   int decrypt,
 		   void * iv,
 		   void * in,
@@ -546,27 +547,27 @@ __u32 krb5_encrypt(struct ll_crypto_cipher *tfm,
 	desc.info = local_iv;
 	desc.flags= 0;
 
-	if (length % ll_crypto_blkcipher_blocksize(tfm) != 0) {
+	if (length % crypto_blkcipher_blocksize(tfm) != 0) {
 		CERROR("output length %d mismatch blocksize %d\n",
-		       length, ll_crypto_blkcipher_blocksize(tfm));
+		       length, crypto_blkcipher_blocksize(tfm));
 		goto out;
 	}
 
-	if (ll_crypto_blkcipher_ivsize(tfm) > 16) {
-		CERROR("iv size too large %d\n", ll_crypto_blkcipher_ivsize(tfm));
+	if (crypto_blkcipher_ivsize(tfm) > 16) {
+		CERROR("iv size too large %d\n", crypto_blkcipher_ivsize(tfm));
 		goto out;
 	}
 
 	if (iv)
-		memcpy(local_iv, iv, ll_crypto_blkcipher_ivsize(tfm));
+		memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm));
 
 	memcpy(out, in, length);
 	buf_to_sg(&sg, out, length);
 
 	if (decrypt)
-		ret = ll_crypto_blkcipher_decrypt_iv(&desc, &sg, &sg, length);
+		ret = crypto_blkcipher_decrypt_iv(&desc, &sg, &sg, length);
 	else
-		ret = ll_crypto_blkcipher_encrypt_iv(&desc, &sg, &sg, length);
+		ret = crypto_blkcipher_encrypt_iv(&desc, &sg, &sg, length);
 
 out:
 	return(ret);
@@ -574,7 +575,7 @@ out:
 
 
 static inline
-int krb5_digest_hmac(struct ll_crypto_hash *tfm,
+int krb5_digest_hmac(struct crypto_hash *tfm,
 		     rawobj_t *key,
 		     struct krb5_header *khdr,
 		     int msgcnt, rawobj_t *msgs,
@@ -585,17 +586,17 @@ int krb5_digest_hmac(struct ll_crypto_hash *tfm,
 	struct scatterlist sg[1];
 	int		i;
 
-	ll_crypto_hash_setkey(tfm, key->data, key->len);
+	crypto_hash_setkey(tfm, key->data, key->len);
 	desc.tfm  = tfm;
 	desc.flags= 0;
 
-	ll_crypto_hash_init(&desc);
+	crypto_hash_init(&desc);
 
 	for (i = 0; i < msgcnt; i++) {
 		if (msgs[i].len == 0)
 			continue;
 		buf_to_sg(sg, (char *) msgs[i].data, msgs[i].len);
-		ll_crypto_hash_update(&desc, sg, msgs[i].len);
+		crypto_hash_update(&desc, sg, msgs[i].len);
 	}
 
 	for (i = 0; i < iovcnt; i++) {
@@ -604,20 +605,20 @@ int krb5_digest_hmac(struct ll_crypto_hash *tfm,
 
 		sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
 			    iovs[i].kiov_offset);
-		ll_crypto_hash_update(&desc, sg, iovs[i].kiov_len);
+		crypto_hash_update(&desc, sg, iovs[i].kiov_len);
 	}
 
 	if (khdr) {
 		buf_to_sg(sg, (char *) khdr, sizeof(*khdr));
-		ll_crypto_hash_update(&desc, sg, sizeof(*khdr));
+		crypto_hash_update(&desc, sg, sizeof(*khdr));
 	}
 
-	return ll_crypto_hash_final(&desc, cksum->data);
+	return crypto_hash_final(&desc, cksum->data);
 }
 
 
 static inline
-int krb5_digest_norm(struct ll_crypto_hash *tfm,
+int krb5_digest_norm(struct crypto_hash *tfm,
 		     struct krb5_keyblock *kb,
 		     struct krb5_header *khdr,
 		     int msgcnt, rawobj_t *msgs,
@@ -632,13 +633,13 @@ int krb5_digest_norm(struct ll_crypto_hash *tfm,
 	desc.tfm  = tfm;
 	desc.flags= 0;
 
-	ll_crypto_hash_init(&desc);
+	crypto_hash_init(&desc);
 
 	for (i = 0; i < msgcnt; i++) {
 		if (msgs[i].len == 0)
 			continue;
 		buf_to_sg(sg, (char *) msgs[i].data, msgs[i].len);
-		ll_crypto_hash_update(&desc, sg, msgs[i].len);
+		crypto_hash_update(&desc, sg, msgs[i].len);
 	}
 
 	for (i = 0; i < iovcnt; i++) {
@@ -647,15 +648,15 @@ int krb5_digest_norm(struct ll_crypto_hash *tfm,
 
 		sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
 			    iovs[i].kiov_offset);
-		ll_crypto_hash_update(&desc, sg, iovs[i].kiov_len);
+		crypto_hash_update(&desc, sg, iovs[i].kiov_len);
 	}
 
 	if (khdr) {
 		buf_to_sg(sg, (char *) khdr, sizeof(*khdr));
-		ll_crypto_hash_update(&desc, sg, sizeof(*khdr));
+		crypto_hash_update(&desc, sg, sizeof(*khdr));
 	}
 
-	ll_crypto_hash_final(&desc, cksum->data);
+	crypto_hash_final(&desc, cksum->data);
 
 	return krb5_encrypt(kb->kb_tfm, 0, NULL, cksum->data,
 			    cksum->data, cksum->len);
@@ -674,7 +675,7 @@ __s32 krb5_make_checksum(__u32 enctype,
 			 rawobj_t *cksum)
 {
 	struct krb5_enctype   *ke = &enctypes[enctype];
-	struct ll_crypto_hash *tfm;
+	struct crypto_hash *tfm;
 	__u32		  code = GSS_S_FAILURE;
 	int		    rc;
 
@@ -683,7 +684,7 @@ __s32 krb5_make_checksum(__u32 enctype,
 		return GSS_S_FAILURE;
 	}
 
-	cksum->len = ll_crypto_hash_digestsize(tfm);
+	cksum->len = crypto_hash_digestsize(tfm);
 	OBD_ALLOC_LARGE(cksum->data, cksum->len);
 	if (!cksum->data) {
 		cksum->len = 0;
@@ -700,7 +701,7 @@ __s32 krb5_make_checksum(__u32 enctype,
 	if (rc == 0)
 		code = GSS_S_COMPLETE;
 out_tfm:
-	ll_crypto_free_hash(tfm);
+	crypto_free_hash(tfm);
 	return code;
 }
 
@@ -878,7 +879,7 @@ int add_padding(rawobj_t *msg, int msg_buflen, int blocksize)
 }
 
 static
-int krb5_encrypt_rawobjs(struct ll_crypto_cipher *tfm,
+int krb5_encrypt_rawobjs(struct crypto_blkcipher *tfm,
 			 int mode_ecb,
 			 int inobj_cnt,
 			 rawobj_t *inobjs,
@@ -890,7 +891,6 @@ int krb5_encrypt_rawobjs(struct ll_crypto_cipher *tfm,
 	__u8		  local_iv[16] = {0}, *buf;
 	__u32		 datalen = 0;
 	int		   i, rc;
-	ENTRY;
 
 	buf = outobj->data;
 	desc.tfm  = tfm;
@@ -905,23 +905,23 @@ int krb5_encrypt_rawobjs(struct ll_crypto_cipher *tfm,
 
 		if (mode_ecb) {
 			if (enc)
-				rc = ll_crypto_blkcipher_encrypt(
+				rc = crypto_blkcipher_encrypt(
 					&desc, &dst, &src, src.length);
 			else
-				rc = ll_crypto_blkcipher_decrypt(
+				rc = crypto_blkcipher_decrypt(
 					&desc, &dst, &src, src.length);
 		} else {
 			if (enc)
-				rc = ll_crypto_blkcipher_encrypt_iv(
+				rc = crypto_blkcipher_encrypt_iv(
 					&desc, &dst, &src, src.length);
 			else
-				rc = ll_crypto_blkcipher_decrypt_iv(
+				rc = crypto_blkcipher_decrypt_iv(
 					&desc, &dst, &src, src.length);
 		}
 
 		if (rc) {
 			CERROR("encrypt error %d\n", rc);
-			RETURN(rc);
+			return rc;
 		}
 
 		datalen += inobjs[i].len;
@@ -929,14 +929,14 @@ int krb5_encrypt_rawobjs(struct ll_crypto_cipher *tfm,
 	}
 
 	outobj->len = datalen;
-	RETURN(0);
+	return 0;
 }
 
 /*
  * if adj_nob != 0, we adjust desc->bd_nob to the actual cipher text size.
  */
 static
-int krb5_encrypt_bulk(struct ll_crypto_cipher *tfm,
+int krb5_encrypt_bulk(struct crypto_blkcipher *tfm,
 		      struct krb5_header *khdr,
 		      char *confounder,
 		      struct ptlrpc_bulk_desc *desc,
@@ -951,7 +951,7 @@ int krb5_encrypt_bulk(struct ll_crypto_cipher *tfm,
 	LASSERT(desc->bd_iov_count);
 	LASSERT(desc->bd_enc_iov);
 
-	blocksize = ll_crypto_blkcipher_blocksize(tfm);
+	blocksize = crypto_blkcipher_blocksize(tfm);
 	LASSERT(blocksize > 1);
 	LASSERT(cipher->len == blocksize + sizeof(*khdr));
 
@@ -963,7 +963,7 @@ int krb5_encrypt_bulk(struct ll_crypto_cipher *tfm,
 	buf_to_sg(&src, confounder, blocksize);
 	buf_to_sg(&dst, cipher->data, blocksize);
 
-	rc = ll_crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src, blocksize);
+	rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src, blocksize);
 	if (rc) {
 		CERROR("error to encrypt confounder: %d\n", rc);
 		return rc;
@@ -983,7 +983,7 @@ int krb5_encrypt_bulk(struct ll_crypto_cipher *tfm,
 		desc->bd_enc_iov[i].kiov_offset = dst.offset;
 		desc->bd_enc_iov[i].kiov_len = dst.length;
 
-		rc = ll_crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src,
+		rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src,
 						    src.length);
 		if (rc) {
 			CERROR("error to encrypt page: %d\n", rc);
@@ -995,7 +995,7 @@ int krb5_encrypt_bulk(struct ll_crypto_cipher *tfm,
 	buf_to_sg(&src, khdr, sizeof(*khdr));
 	buf_to_sg(&dst, cipher->data + blocksize, sizeof(*khdr));
 
-	rc = ll_crypto_blkcipher_encrypt_iv(&ciph_desc,
+	rc = crypto_blkcipher_encrypt_iv(&ciph_desc,
 					    &dst, &src, sizeof(*khdr));
 	if (rc) {
 		CERROR("error to encrypt krb5 header: %d\n", rc);
@@ -1025,7 +1025,7 @@ int krb5_encrypt_bulk(struct ll_crypto_cipher *tfm,
  *   should have been done by prep_bulk().
  */
 static
-int krb5_decrypt_bulk(struct ll_crypto_cipher *tfm,
+int krb5_decrypt_bulk(struct crypto_blkcipher *tfm,
 		      struct krb5_header *khdr,
 		      struct ptlrpc_bulk_desc *desc,
 		      rawobj_t *cipher,
@@ -1042,7 +1042,7 @@ int krb5_decrypt_bulk(struct ll_crypto_cipher *tfm,
 	LASSERT(desc->bd_enc_iov);
 	LASSERT(desc->bd_nob_transferred);
 
-	blocksize = ll_crypto_blkcipher_blocksize(tfm);
+	blocksize = crypto_blkcipher_blocksize(tfm);
 	LASSERT(blocksize > 1);
 	LASSERT(cipher->len == blocksize + sizeof(*khdr));
 
@@ -1059,7 +1059,7 @@ int krb5_decrypt_bulk(struct ll_crypto_cipher *tfm,
 	buf_to_sg(&src, cipher->data, blocksize);
 	buf_to_sg(&dst, plain->data, blocksize);
 
-	rc = ll_crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src, blocksize);
+	rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src, blocksize);
 	if (rc) {
 		CERROR("error to decrypt confounder: %d\n", rc);
 		return rc;
@@ -1102,7 +1102,7 @@ int krb5_decrypt_bulk(struct ll_crypto_cipher *tfm,
 		if (desc->bd_iov[i].kiov_len % blocksize == 0)
 			sg_assign_page(&dst, desc->bd_iov[i].kiov_page);
 
-		rc = ll_crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src,
+		rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src,
 						    src.length);
 		if (rc) {
 			CERROR("error to decrypt page: %d\n", rc);
@@ -1142,7 +1142,7 @@ int krb5_decrypt_bulk(struct ll_crypto_cipher *tfm,
 	buf_to_sg(&src, cipher->data + blocksize, sizeof(*khdr));
 	buf_to_sg(&dst, cipher->data + blocksize, sizeof(*khdr));
 
-	rc = ll_crypto_blkcipher_decrypt_iv(&ciph_desc,
+	rc = crypto_blkcipher_decrypt_iv(&ciph_desc,
 					    &dst, &src, sizeof(*khdr));
 	if (rc) {
 		CERROR("error to decrypt tail: %d\n", rc);
@@ -1177,7 +1177,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
 	LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK);
 	LASSERT(kctx->kc_keye.kb_tfm == NULL ||
 		ke->ke_conf_size >=
-		ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm));
+		crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm));
 
 	/*
 	 * final token format:
@@ -1201,7 +1201,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
 		blocksize = 1;
 	} else {
 		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
+		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
 	}
 	LASSERT(blocksize <= ke->ke_conf_size);
 
@@ -1248,7 +1248,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
 
 	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
 		rawobj_t		 arc4_keye;
-		struct ll_crypto_cipher *arc4_tfm;
+		struct crypto_blkcipher *arc4_tfm;
 
 		if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi,
 				       NULL, 1, &cksum, 0, NULL, &arc4_keye)) {
@@ -1256,13 +1256,13 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
 			GOTO(arc4_out, rc = -EACCES);
 		}
 
-		arc4_tfm = ll_crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
+		arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
 		if (IS_ERR(arc4_tfm)) {
 			CERROR("failed to alloc tfm arc4 in ECB mode\n");
 			GOTO(arc4_out_key, rc = -EACCES);
 		}
 
-		if (ll_crypto_blkcipher_setkey(arc4_tfm, arc4_keye.data,
+		if (crypto_blkcipher_setkey(arc4_tfm, arc4_keye.data,
 					       arc4_keye.len)) {
 			CERROR("failed to set arc4 key, len %d\n",
 			       arc4_keye.len);
@@ -1272,7 +1272,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
 		rc = krb5_encrypt_rawobjs(arc4_tfm, 1,
 					  3, data_desc, &cipher, 1);
 arc4_out_tfm:
-		ll_crypto_free_blkcipher(arc4_tfm);
+		crypto_free_blkcipher(arc4_tfm);
 arc4_out_key:
 		rawobj_free(&arc4_keye);
 arc4_out:
@@ -1310,7 +1310,7 @@ __u32 gss_prep_bulk_kerberos(struct gss_ctx *gctx,
 	LASSERT(desc->bd_enc_iov);
 	LASSERT(kctx->kc_keye.kb_tfm);
 
-	blocksize = ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
+	blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
 
 	for (i = 0; i < desc->bd_iov_count; i++) {
 		LASSERT(desc->bd_enc_iov[i].kiov_page);
@@ -1371,7 +1371,7 @@ __u32 gss_wrap_bulk_kerberos(struct gss_ctx *gctx,
 		blocksize = 1;
 	} else {
 		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
+		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
 	}
 
 	/*
@@ -1481,7 +1481,7 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
 		blocksize = 1;
 	} else {
 		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
+		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
 	}
 
 	/* expected token layout:
@@ -1521,7 +1521,7 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
 
 	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
 		rawobj_t		 arc4_keye;
-		struct ll_crypto_cipher *arc4_tfm;
+		struct crypto_blkcipher *arc4_tfm;
 
 		cksum.data = token->data + token->len - ke->ke_hash_size;
 		cksum.len = ke->ke_hash_size;
@@ -1532,13 +1532,13 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
 			GOTO(arc4_out, rc = -EACCES);
 		}
 
-		arc4_tfm = ll_crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
+		arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
 		if (IS_ERR(arc4_tfm)) {
 			CERROR("failed to alloc tfm arc4 in ECB mode\n");
 			GOTO(arc4_out_key, rc = -EACCES);
 		}
 
-		if (ll_crypto_blkcipher_setkey(arc4_tfm,
+		if (crypto_blkcipher_setkey(arc4_tfm,
 					 arc4_keye.data, arc4_keye.len)) {
 			CERROR("failed to set arc4 key, len %d\n",
 			       arc4_keye.len);
@@ -1548,7 +1548,7 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
 		rc = krb5_encrypt_rawobjs(arc4_tfm, 1,
 					  1, &cipher_in, &plain_out, 0);
 arc4_out_tfm:
-		ll_crypto_free_blkcipher(arc4_tfm);
+		crypto_free_blkcipher(arc4_tfm);
 arc4_out_key:
 		rawobj_free(&arc4_keye);
 arc4_out:
@@ -1647,7 +1647,7 @@ __u32 gss_unwrap_bulk_kerberos(struct gss_ctx *gctx,
 		LBUG();
 	} else {
 		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
+		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
 	}
 	LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
index 3df7257..c624518 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
@@ -262,7 +262,6 @@ void gss_sec_ctx_replace_pf(struct gss_sec *gsec,
 	struct hlist_node     *next;
 	HLIST_HEAD(freelist);
 	unsigned int hash;
-	ENTRY;
 
 	gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base);
 
@@ -287,7 +286,6 @@ void gss_sec_ctx_replace_pf(struct gss_sec *gsec,
 	spin_unlock(&gsec->gs_base.ps_lock);
 
 	ctx_list_destroy_pf(&freelist);
-	EXIT;
 }
 
 static
@@ -297,23 +295,22 @@ int gss_install_rvs_cli_ctx_pf(struct gss_sec *gsec,
 	struct vfs_cred	  vcred;
 	struct ptlrpc_cli_ctx   *cli_ctx;
 	int		      rc;
-	ENTRY;
 
 	vcred.vc_uid = 0;
 	vcred.vc_gid = 0;
 
 	cli_ctx = ctx_create_pf(&gsec->gs_base, &vcred);
 	if (!cli_ctx)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	rc = gss_copy_rvc_cli_ctx(cli_ctx, svc_ctx);
 	if (rc) {
 		ctx_destroy_pf(cli_ctx->cc_sec, cli_ctx);
-		RETURN(rc);
+		return rc;
 	}
 
 	gss_sec_ctx_replace_pf(gsec, cli_ctx);
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -324,7 +321,6 @@ void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf,
 	struct ptlrpc_cli_ctx   *ctx;
 	struct hlist_node       *next;
 	int i;
-	ENTRY;
 
 	sec = &gsec_pf->gsp_base.gs_base;
 
@@ -337,7 +333,6 @@ void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf,
 	}
 
 	sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
-	EXIT;
 }
 
 static
@@ -347,7 +342,6 @@ struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
 {
 	struct gss_sec_pipefs   *gsec_pf;
 	int		      alloc_size, hash_size, i;
-	ENTRY;
 
 #define GSS_SEC_PIPEFS_CTX_HASH_SIZE    (32)
 
@@ -362,7 +356,7 @@ struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
 
 	OBD_ALLOC(gsec_pf, alloc_size);
 	if (!gsec_pf)
-		RETURN(NULL);
+		return NULL;
 
 	gsec_pf->gsp_chash_size = hash_size;
 	for (i = 0; i < hash_size; i++)
@@ -380,13 +374,13 @@ struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
 			goto err_destroy;
 	}
 
-	RETURN(&gsec_pf->gsp_base.gs_base);
+	return &gsec_pf->gsp_base.gs_base;
 
 err_destroy:
 	gss_sec_destroy_common(&gsec_pf->gsp_base);
 err_free:
 	OBD_FREE(gsec_pf, alloc_size);
-	RETURN(NULL);
+	return NULL;
 }
 
 static
@@ -423,7 +417,6 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_pf(struct ptlrpc_sec *sec,
 	struct hlist_node       *next;
 	HLIST_HEAD(freelist);
 	unsigned int	    hash, gc = 0, found = 0;
-	ENTRY;
 
 	might_sleep();
 
@@ -473,7 +466,7 @@ retry:
 		/* don't allocate for reverse sec */
 		if (sec_is_reverse(sec)) {
 			spin_unlock(&sec->ps_lock);
-			RETURN(NULL);
+			return NULL;
 		}
 
 		if (new) {
@@ -504,7 +497,7 @@ retry:
 	}
 
 	ctx_list_destroy_pf(&freelist);
-	RETURN(ctx);
+	return ctx;
 }
 
 static
@@ -545,7 +538,6 @@ int gss_sec_flush_ctx_cache_pf(struct ptlrpc_sec *sec,
 	struct hlist_node       *next;
 	HLIST_HEAD(freelist);
 	int i, busy = 0;
-	ENTRY;
 
 	might_sleep_if(grace);
 
@@ -584,7 +576,7 @@ int gss_sec_flush_ctx_cache_pf(struct ptlrpc_sec *sec,
 	spin_unlock(&sec->ps_lock);
 
 	ctx_list_destroy_pf(&freelist);
-	RETURN(busy);
+	return busy;
 }
 
 /****************************************
@@ -704,11 +696,9 @@ void upcall_msg_delist(struct gss_upcall_msg *msg)
 static
 void gss_release_msg(struct gss_upcall_msg *gmsg)
 {
-	ENTRY;
 	LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
 
 	if (!atomic_dec_and_test(&gmsg->gum_refcount)) {
-		EXIT;
 		return;
 	}
 
@@ -721,7 +711,6 @@ void gss_release_msg(struct gss_upcall_msg *gmsg)
 	LASSERT(list_empty(&gmsg->gum_list));
 	LASSERT(list_empty(&gmsg->gum_base.list));
 	OBD_FREE_PTR(gmsg);
-	EXIT;
 }
 
 static
@@ -809,19 +798,18 @@ ssize_t gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
 	char *data = (char *)msg->data + msg->copied;
 	ssize_t mlen = msg->len;
 	ssize_t left;
-	ENTRY;
 
 	if (mlen > buflen)
 		mlen = buflen;
 	left = copy_to_user(dst, data, mlen);
 	if (left < 0) {
 		msg->errno = left;
-		RETURN(left);
+		return left;
 	}
 	mlen -= left;
 	msg->copied += mlen;
 	msg->errno = 0;
-	RETURN(mlen);
+	return mlen;
 }
 
 static
@@ -835,14 +823,13 @@ ssize_t gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
 	int		      datalen;
 	int		      timeout, rc;
 	__u32		    mechidx, seq, gss_err;
-	ENTRY;
 
 	mechidx = (__u32) (long) rpci->private;
 	LASSERT(mechidx < MECH_MAX);
 
 	OBD_ALLOC(buf, mlen);
 	if (!buf)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (copy_from_user(buf, src, mlen)) {
 		CERROR("failed copy user space data\n");
@@ -940,7 +927,7 @@ out_free:
 	 * hack pipefs: always return asked length unless all following
 	 * downcalls might be messed up. */
 	rc = mlen;
-	RETURN(rc);
+	return rc;
 }
 
 static
@@ -949,13 +936,11 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
 	struct gss_upcall_msg	  *gmsg;
 	struct gss_upcall_msg_data     *gumd;
 	static cfs_time_t	       ratelimit = 0;
-	ENTRY;
 
 	LASSERT(list_empty(&msg->list));
 
 	/* normally errno is >= 0 */
 	if (msg->errno >= 0) {
-		EXIT;
 		return;
 	}
 
@@ -980,7 +965,6 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
 	}
 	gss_msg_fail_ctx(gmsg);
 	gss_release_msg(gmsg);
-	EXIT;
 }
 
 static
@@ -988,7 +972,6 @@ void gss_pipe_release(struct inode *inode)
 {
 	struct rpc_inode *rpci = RPC_I(inode);
 	__u32	     idx;
-	ENTRY;
 
 	idx = (__u32) (long) rpci->private;
 	LASSERT(idx < MECH_MAX);
@@ -1020,7 +1003,6 @@ void gss_pipe_release(struct inode *inode)
 		upcall_list_lock(idx);
 	}
 	upcall_list_unlock(idx);
-	EXIT;
 }
 
 static struct rpc_pipe_ops gss_upcall_ops = {
@@ -1041,7 +1023,6 @@ int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx)
 	struct gss_sec	     *gsec;
 	struct gss_upcall_msg      *gmsg;
 	int			 rc = 0;
-	ENTRY;
 
 	might_sleep();
 
@@ -1052,14 +1033,14 @@ int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx)
 	imp = ctx->cc_sec->ps_import;
 	if (!imp->imp_connection) {
 		CERROR("import has no connection set\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base);
 
 	OBD_ALLOC_PTR(gmsg);
 	if (!gmsg)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	/* initialize pipefs base msg */
 	INIT_LIST_HEAD(&gmsg->gum_base.list);
@@ -1107,10 +1088,10 @@ int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx)
 		goto err_free;
 	}
 
-	RETURN(0);
+	return 0;
 err_free:
 	OBD_FREE_PTR(gmsg);
-	RETURN(rc);
+	return rc;
 }
 
 static
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c
index 474ecf8..fb298aef6 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c
@@ -65,7 +65,7 @@ int rawobj_alloc(rawobj_t *obj, char *buf, int len)
 		OBD_ALLOC_LARGE(obj->data, len);
 		if (!obj->data) {
 			obj->len = 0;
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		}
 		memcpy(obj->data, buf, len);
 	} else
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
index 31b50ea..5b5365b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
@@ -259,8 +259,6 @@ static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen)
 	struct rsi      rsii, *rsip = NULL;
 	time_t	  expiry;
 	int	     status = -EINVAL;
-	ENTRY;
-
 
 	memset(&rsii, 0, sizeof(rsii));
 
@@ -341,7 +339,7 @@ out:
 
 	if (status)
 		CERROR("rsi parse error %d\n", status);
-	RETURN(status);
+	return status;
 }
 
 static struct cache_detail rsi_cache = {
@@ -662,7 +660,6 @@ static void rsc_flush(rsc_entry_match *match, long data)
 	struct cache_head **ch;
 	struct rsc *rscp;
 	int n;
-	ENTRY;
 
 	write_lock(&rsc_cache.hash_lock);
 	for (n = 0; n < RSC_HASHMAX; n++) {
@@ -684,7 +681,6 @@ static void rsc_flush(rsc_entry_match *match, long data)
 		}
 	}
 	write_unlock(&rsc_cache.hash_lock);
-	EXIT;
 }
 
 static int match_uid(struct rsc *rscp, long uid)
@@ -744,7 +740,6 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
 	unsigned long   ctx_expiry;
 	__u32	   major;
 	int	     rc;
-	ENTRY;
 
 	memset(&rsci, 0, sizeof(rsci));
 
@@ -792,7 +787,7 @@ out:
 	if (rc)
 		CERROR("create reverse svc ctx: idx "LPX64", rc %d\n",
 		       gsec->gs_rvs_hdl, rc);
-	RETURN(rc);
+	return rc;
 }
 
 int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle)
@@ -855,7 +850,6 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
 	struct gss_rep_header     *rephdr;
 	int			first_check = 1;
 	int			rc = SECSVC_DROP;
-	ENTRY;
 
 	memset(&rsikey, 0, sizeof(rsikey));
 	rsikey.lustre_svc = lustre_svc;
@@ -1016,7 +1010,7 @@ out:
 
 		COMPAT_RSC_PUT(&rsci->h, &rsc_cache);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req,
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c
index 3404000..de100a1 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c
@@ -199,15 +199,17 @@ int gss_init_lproc(void)
 	gss_proc_root = lprocfs_register("gss", sptlrpc_proc_root,
 					 gss_lprocfs_vars, NULL);
 	if (IS_ERR(gss_proc_root)) {
+		rc = PTR_ERR(gss_proc_root);
 		gss_proc_root = NULL;
-		GOTO(err_out, rc = PTR_ERR(gss_proc_root));
+		GOTO(err_out, rc);
 	}
 
 	gss_proc_lk = lprocfs_register("lgss_keyring", gss_proc_root,
 				       gss_lk_lprocfs_vars, NULL);
 	if (IS_ERR(gss_proc_lk)) {
+		rc = PTR_ERR(gss_proc_lk);
 		gss_proc_lk = NULL;
-		GOTO(err_out, rc = PTR_ERR(gss_proc_root));
+		GOTO(err_out, rc);
 	}
 
 	return 0;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
index ebca858..b42ddda 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
@@ -280,11 +280,10 @@ __u32 gss_unseal_msg(struct gss_ctx *mechctx,
 	__u8		    *clear_buf;
 	int		      clear_buflen;
 	__u32		    major;
-	ENTRY;
 
 	if (msgbuf->lm_bufcount != 2) {
 		CERROR("invalid bufcount %d\n", msgbuf->lm_bufcount);
-		RETURN(GSS_S_FAILURE);
+		return GSS_S_FAILURE;
 	}
 
 	/* allocate a temporary clear text buffer, same sized as token,
@@ -292,7 +291,7 @@ __u32 gss_unseal_msg(struct gss_ctx *mechctx,
 	clear_buflen = lustre_msg_buflen(msgbuf, 1);
 	OBD_ALLOC_LARGE(clear_buf, clear_buflen);
 	if (!clear_buf)
-		RETURN(GSS_S_FAILURE);
+		return GSS_S_FAILURE;
 
 	/* buffer objects */
 	hdrobj.len = lustre_msg_buflen(msgbuf, 0);
@@ -317,7 +316,7 @@ __u32 gss_unseal_msg(struct gss_ctx *mechctx,
 	major = GSS_S_COMPLETE;
 out_free:
 	OBD_FREE_LARGE(clear_buf, clear_buflen);
-	RETURN(major);
+	return major;
 }
 
 /********************************************
@@ -646,7 +645,6 @@ int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
 	struct gss_cli_ctx      *gctx = ctx2gctx(ctx);
 	__u32		    flags = 0, seq, svc;
 	int		      rc;
-	ENTRY;
 
 	LASSERT(req->rq_reqbuf);
 	LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
@@ -654,7 +652,7 @@ int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
 
 	/* nothing to do for context negotiation RPCs */
 	if (req->rq_ctx_init)
-		RETURN(0);
+		return 0;
 
 	svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
 	if (req->rq_pack_bulk)
@@ -670,7 +668,7 @@ redo:
 			  flags, gctx->gc_proc, seq, svc,
 			  &gctx->gc_handle);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	/* gss_sign_msg() msg might take long time to finish, in which period
 	 * more rpcs could be wrapped up and sent out. if we found too many
@@ -689,7 +687,7 @@ redo:
 	}
 
 	req->rq_reqdata_len = rc;
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -765,7 +763,6 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 	struct lustre_msg      *msg = req->rq_repdata;
 	__u32		   major;
 	int		     pack_bulk, swabbed, rc = 0;
-	ENTRY;
 
 	LASSERT(req->rq_cli_ctx == ctx);
 	LASSERT(msg);
@@ -777,12 +774,12 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 	if (req->rq_ctx_init && !req->rq_early) {
 		req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
 		req->rq_replen = msg->lm_buflens[1];
-		RETURN(0);
+		return 0;
 	}
 
 	if (msg->lm_bufcount < 2 || msg->lm_bufcount > 4) {
 		CERROR("unexpected bufcount %u\n", msg->lm_bufcount);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	swabbed = ptlrpc_rep_need_swab(req);
@@ -790,7 +787,7 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 	ghdr = gss_swab_header(msg, 0, swabbed);
 	if (ghdr == NULL) {
 		CERROR("can't decode gss header\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	/* sanity checks */
@@ -800,7 +797,7 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 	if (ghdr->gh_version != reqhdr->gh_version) {
 		CERROR("gss version %u mismatch, expect %u\n",
 		       ghdr->gh_version, reqhdr->gh_version);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	switch (ghdr->gh_proc) {
@@ -810,19 +807,19 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 		if (!req->rq_early && !equi(req->rq_pack_bulk == 1, pack_bulk)){
 			CERROR("%s bulk flag in reply\n",
 			       req->rq_pack_bulk ? "missing" : "unexpected");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (ghdr->gh_seq != reqhdr->gh_seq) {
 			CERROR("seqnum %u mismatch, expect %u\n",
 			       ghdr->gh_seq, reqhdr->gh_seq);
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (ghdr->gh_svc != reqhdr->gh_svc) {
 			CERROR("svc %u mismatch, expect %u\n",
 			       ghdr->gh_svc, reqhdr->gh_svc);
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (swabbed)
@@ -831,7 +828,7 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 		major = gss_verify_msg(msg, gctx->gc_mechctx, reqhdr->gh_svc);
 		if (major != GSS_S_COMPLETE) {
 			CERROR("failed to verify reply: %x\n", major);
-			RETURN(-EPERM);
+			return -EPERM;
 		}
 
 		if (req->rq_early && reqhdr->gh_svc == SPTLRPC_SVC_NULL) {
@@ -843,7 +840,7 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 			if (cksum != msg->lm_cksum) {
 				CWARN("early reply checksum mismatch: "
 				      "%08x != %08x\n", cksum, msg->lm_cksum);
-				RETURN(-EPROTO);
+				return -EPROTO;
 			}
 		}
 
@@ -852,13 +849,13 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 			if (msg->lm_bufcount < 3) {
 				CERROR("Invalid reply bufcount %u\n",
 				       msg->lm_bufcount);
-				RETURN(-EPROTO);
+				return -EPROTO;
 			}
 
 			rc = bulk_sec_desc_unpack(msg, 2, swabbed);
 			if (rc) {
 				CERROR("unpack bulk desc: %d\n", rc);
-				RETURN(rc);
+				return rc;
 			}
 		}
 
@@ -878,7 +875,7 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 		rc = -EPROTO;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx,
@@ -889,7 +886,6 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx,
 	struct gss_header       *ghdr;
 	__u32		    buflens[2], major;
 	int		      wiresize, rc;
-	ENTRY;
 
 	LASSERT(req->rq_clrbuf);
 	LASSERT(req->rq_cli_ctx == ctx);
@@ -915,7 +911,7 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx,
 	} else {
 		OBD_ALLOC_LARGE(req->rq_reqbuf, wiresize);
 		if (!req->rq_reqbuf)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 		req->rq_reqbuf_len = wiresize;
 	}
 
@@ -969,7 +965,7 @@ redo:
 
 	/* now set the final wire data length */
 	req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, 1, token.len,0);
-	RETURN(0);
+	return 0;
 
 err_free:
 	if (!req->rq_pool) {
@@ -977,7 +973,7 @@ err_free:
 		req->rq_reqbuf = NULL;
 		req->rq_reqbuf_len = 0;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
@@ -988,7 +984,6 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
 	struct lustre_msg       *msg = req->rq_repdata;
 	int		      msglen, pack_bulk, swabbed, rc;
 	__u32		    major;
-	ENTRY;
 
 	LASSERT(req->rq_cli_ctx == ctx);
 	LASSERT(req->rq_ctx_init == 0);
@@ -1000,14 +995,14 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
 	ghdr = gss_swab_header(msg, 0, swabbed);
 	if (ghdr == NULL) {
 		CERROR("can't decode gss header\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	/* sanity checks */
 	if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
 		CERROR("gss version %u mismatch, expect %u\n",
 		       ghdr->gh_version, PTLRPC_GSS_VERSION);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	switch (ghdr->gh_proc) {
@@ -1017,7 +1012,7 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
 		if (!req->rq_early && !equi(req->rq_pack_bulk == 1, pack_bulk)){
 			CERROR("%s bulk flag in reply\n",
 			       req->rq_pack_bulk ? "missing" : "unexpected");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (swabbed)
@@ -1038,25 +1033,25 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
 		swabbed = __lustre_unpack_msg(msg, msglen);
 		if (swabbed < 0) {
 			CERROR("Failed to unpack after decryption\n");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (msg->lm_bufcount < 1) {
 			CERROR("Invalid reply buffer: empty\n");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (pack_bulk) {
 			if (msg->lm_bufcount < 2) {
 				CERROR("bufcount %u: missing bulk sec desc\n",
 				       msg->lm_bufcount);
-				RETURN(-EPROTO);
+				return -EPROTO;
 			}
 
 			/* bulk checksum is the last segment */
 			if (bulk_sec_desc_unpack(msg, msg->lm_bufcount - 1,
 						 swabbed))
-				RETURN(-EPROTO);
+				return -EPROTO;
 		}
 
 		req->rq_repmsg = lustre_msg_buf(msg, 0, 0);
@@ -1077,7 +1072,7 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
 		rc = -EPERM;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /*********************************************
@@ -1148,7 +1143,6 @@ int gss_sec_create_common(struct gss_sec *gsec,
 void gss_sec_destroy_common(struct gss_sec *gsec)
 {
 	struct ptlrpc_sec      *sec = &gsec->gs_base;
-	ENTRY;
 
 	LASSERT(sec->ps_import);
 	LASSERT(atomic_read(&sec->ps_refcount) == 0);
@@ -1163,8 +1157,6 @@ void gss_sec_destroy_common(struct gss_sec *gsec)
 
 	if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV)
 		sptlrpc_enc_pool_del_user();
-
-	EXIT;
 }
 
 void gss_sec_kill(struct ptlrpc_sec *sec)
@@ -1260,7 +1252,6 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
 	int		       bufsize, txtsize;
 	int		       bufcnt = 2;
 	__u32		     buflens[5];
-	ENTRY;
 
 	/*
 	 * on-wire data layout:
@@ -1312,7 +1303,7 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
 
 		OBD_ALLOC_LARGE(req->rq_reqbuf, bufsize);
 		if (!req->rq_reqbuf)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		req->rq_reqbuf_len = bufsize;
 	} else {
@@ -1331,7 +1322,7 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
 	if (req->rq_pack_udesc)
 		sptlrpc_pack_user_desc(req->rq_reqbuf, 2);
 
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -1342,7 +1333,6 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
 	__u32		     ibuflens[3], wbuflens[2];
 	int		       ibufcnt;
 	int		       clearsize, wiresize;
-	ENTRY;
 
 	LASSERT(req->rq_clrbuf == NULL);
 	LASSERT(req->rq_clrbuf_len == 0);
@@ -1399,7 +1389,7 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
 
 		OBD_ALLOC_LARGE(req->rq_clrbuf, clearsize);
 		if (!req->rq_clrbuf)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 	}
 	req->rq_clrbuf_len = clearsize;
 
@@ -1409,7 +1399,7 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
 	if (req->rq_pack_udesc)
 		sptlrpc_pack_user_desc(req->rq_clrbuf, 1);
 
-	RETURN(0);
+	return 0;
 }
 
 /*
@@ -1442,7 +1432,6 @@ void gss_free_reqbuf(struct ptlrpc_sec *sec,
 		     struct ptlrpc_request *req)
 {
 	int     privacy;
-	ENTRY;
 
 	LASSERT(!req->rq_pool || req->rq_reqbuf);
 	privacy = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc) == SPTLRPC_SVC_PRIV;
@@ -1471,8 +1460,6 @@ release_reqbuf:
 		req->rq_reqbuf = NULL;
 		req->rq_reqbuf_len = 0;
 	}
-
-	EXIT;
 }
 
 static int do_alloc_repbuf(struct ptlrpc_request *req, int bufsize)
@@ -1578,7 +1565,6 @@ int gss_alloc_repbuf(struct ptlrpc_sec *sec,
 		     int msgsize)
 {
 	int     svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
-	ENTRY;
 
 	LASSERT(!req->rq_pack_bulk ||
 		(req->rq_bulk_read || req->rq_bulk_write));
@@ -1697,7 +1683,7 @@ int gss_enlarge_reqbuf_intg(struct ptlrpc_sec *sec,
 
 		OBD_ALLOC_LARGE(newbuf, newbuf_size);
 		if (newbuf == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
 
@@ -1717,7 +1703,7 @@ int gss_enlarge_reqbuf_intg(struct ptlrpc_sec *sec,
 	_sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
 
 	req->rq_reqlen = newmsg_size;
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -1786,7 +1772,7 @@ int gss_enlarge_reqbuf_priv(struct ptlrpc_sec *sec,
 
 		OBD_ALLOC_LARGE(newclrbuf, newclrbuf_size);
 		if (newclrbuf == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		memcpy(newclrbuf, req->rq_clrbuf, req->rq_clrbuf_len);
 
@@ -1806,7 +1792,7 @@ int gss_enlarge_reqbuf_priv(struct ptlrpc_sec *sec,
 	_sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
 	req->rq_reqlen = newmsg_size;
 
-	RETURN(0);
+	return 0;
 }
 
 int gss_enlarge_reqbuf(struct ptlrpc_sec *sec,
@@ -1891,7 +1877,6 @@ int gss_svc_sign(struct ptlrpc_request *req,
 {
 	__u32   flags = 0;
 	int     rc;
-	ENTRY;
 
 	LASSERT(rs->rs_msg == lustre_msg_buf(rs->rs_repbuf, 1, 0));
 
@@ -1906,7 +1891,7 @@ int gss_svc_sign(struct ptlrpc_request *req,
 			  LUSTRE_SP_ANY, flags, PTLRPC_GSS_PROC_DATA,
 			  grctx->src_wirectx.gw_seq, svc, NULL);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	rs->rs_repdata_len = rc;
 
@@ -1923,7 +1908,7 @@ int gss_svc_sign(struct ptlrpc_request *req,
 		req->rq_reply_off = 0;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor)
@@ -1933,10 +1918,9 @@ int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor)
 	struct gss_err_header     *ghdr;
 	int			replen = sizeof(struct ptlrpc_body);
 	int			rc;
-	ENTRY;
 
 	//if (OBD_FAIL_CHECK_ORSET(OBD_FAIL_SVCGSS_ERR_NOTIFY, OBD_FAIL_ONCE))
-	//      RETURN(-EINVAL);
+	//      return -EINVAL;
 
 	grctx->src_err_notify = 1;
 	grctx->src_reserve_len = 0;
@@ -1944,7 +1928,7 @@ int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor)
 	rc = lustre_pack_reply_v2(req, 1, &replen, NULL, 0);
 	if (rc) {
 		CERROR("could not pack reply, err %d\n", rc);
-		RETURN(rc);
+		return rc;
 	}
 
 	/* gss hdr */
@@ -1963,7 +1947,7 @@ int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor)
 
 	CDEBUG(D_SEC, "prepare gss error notify(0x%x/0x%x) to %s\n",
 	       major, minor, libcfs_nid2str(req->rq_peer.nid));
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -1978,7 +1962,6 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 	__u32		      lustre_svc;
 	__u32		     *secdata, seclen;
 	int			swabbed, rc;
-	ENTRY;
 
 	CDEBUG(D_SEC, "processing gss init(%d) request from %s\n", gw->gw_proc,
 	       libcfs_nid2str(req->rq_peer.nid));
@@ -1987,18 +1970,18 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 
 	if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
 		CERROR("unexpected bulk flag\n");
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	if (gw->gw_proc == PTLRPC_GSS_PROC_INIT && gw->gw_handle.len != 0) {
 		CERROR("proc %u: invalid handle length %u\n",
 		       gw->gw_proc, gw->gw_handle.len);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	if (reqbuf->lm_bufcount < 3 || reqbuf->lm_bufcount > 4){
 		CERROR("Invalid bufcount %d\n", reqbuf->lm_bufcount);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	swabbed = ptlrpc_req_need_swab(req);
@@ -2009,7 +1992,7 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 
 	if (seclen < 4 + 4) {
 		CERROR("sec size %d too small\n", seclen);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	/* lustre svc type */
@@ -2020,7 +2003,7 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 	 * because touched internal structure of obd_uuid */
 	if (rawobj_extract(&uuid_obj, &secdata, &seclen)) {
 		CERROR("failed to extract target uuid\n");
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 	uuid_obj.data[uuid_obj.len - 1] = '\0';
 
@@ -2030,25 +2013,25 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 		CERROR("target '%s' is not available for context init (%s)\n",
 		       uuid->uuid, target == NULL ? "no target" :
 		       (target->obd_stopping ? "stopping" : "not set up"));
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	/* extract reverse handle */
 	if (rawobj_extract(&rvs_hdl, &secdata, &seclen)) {
 		CERROR("failed extract reverse handle\n");
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	/* extract token */
 	if (rawobj_extract(&in_token, &secdata, &seclen)) {
 		CERROR("can't extract token\n");
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	rc = gss_svc_upcall_handle_init(req, grctx, gw, target, lustre_svc,
 					&rvs_hdl, &in_token);
 	if (rc != SECSVC_OK)
-		RETURN(rc);
+		return rc;
 
 	if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_oss ||
 	    grctx->src_ctx->gsc_usr_root)
@@ -2064,11 +2047,11 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
 		if (reqbuf->lm_bufcount < 4) {
 			CERROR("missing user descriptor\n");
-			RETURN(SECSVC_DROP);
+			return SECSVC_DROP;
 		}
 		if (sptlrpc_unpack_user_desc(reqbuf, 2, swabbed)) {
 			CERROR("Mal-formed user descriptor\n");
-			RETURN(SECSVC_DROP);
+			return SECSVC_DROP;
 		}
 
 		req->rq_pack_udesc = 1;
@@ -2078,7 +2061,7 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 	req->rq_reqmsg = lustre_msg_buf(reqbuf, 1, 0);
 	req->rq_reqlen = lustre_msg_buflen(reqbuf, 1);
 
-	RETURN(rc);
+	return rc;
 }
 
 /*
@@ -2094,13 +2077,12 @@ int gss_svc_verify_request(struct ptlrpc_request *req,
 	struct lustre_msg  *msg = req->rq_reqbuf;
 	int		 offset = 2;
 	int		 swabbed;
-	ENTRY;
 
 	*major = GSS_S_COMPLETE;
 
 	if (msg->lm_bufcount < 2) {
 		CERROR("Too few segments (%u) in request\n", msg->lm_bufcount);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (gw->gw_svc == SPTLRPC_SVC_NULL)
@@ -2109,20 +2091,20 @@ int gss_svc_verify_request(struct ptlrpc_request *req,
 	if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) {
 		CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq);
 		*major = GSS_S_DUPLICATE_TOKEN;
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 	*major = gss_verify_msg(msg, gctx->gsc_mechctx, gw->gw_svc);
 	if (*major != GSS_S_COMPLETE) {
 		CERROR("failed to verify request: %x\n", *major);
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 	if (gctx->gsc_reverse == 0 &&
 	    gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
 		CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
 		*major = GSS_S_DUPLICATE_TOKEN;
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 verified:
@@ -2132,12 +2114,12 @@ verified:
 	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
 		if (msg->lm_bufcount < (offset + 1)) {
 			CERROR("no user desc included\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (sptlrpc_unpack_user_desc(msg, offset, swabbed)) {
 			CERROR("Mal-formed user descriptor\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		req->rq_pack_udesc = 1;
@@ -2149,11 +2131,11 @@ verified:
 	if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
 		if (msg->lm_bufcount < (offset + 1)) {
 			CERROR("missing bulk sec descriptor\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (bulk_sec_desc_unpack(msg, offset, swabbed))
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		req->rq_pack_bulk = 1;
 		grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
@@ -2162,7 +2144,7 @@ verified:
 
 	req->rq_reqmsg = lustre_msg_buf(msg, 1, 0);
 	req->rq_reqlen = msg->lm_buflens[1];
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -2174,48 +2156,47 @@ int gss_svc_unseal_request(struct ptlrpc_request *req,
 	struct gss_svc_ctx *gctx = grctx->src_ctx;
 	struct lustre_msg  *msg = req->rq_reqbuf;
 	int		 swabbed, msglen, offset = 1;
-	ENTRY;
 
 	if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) {
 		CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq);
 		*major = GSS_S_DUPLICATE_TOKEN;
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 	*major = gss_unseal_msg(gctx->gsc_mechctx, msg,
 			       &msglen, req->rq_reqdata_len);
 	if (*major != GSS_S_COMPLETE) {
 		CERROR("failed to unwrap request: %x\n", *major);
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 	if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
 		CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
 		*major = GSS_S_DUPLICATE_TOKEN;
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 	swabbed = __lustre_unpack_msg(msg, msglen);
 	if (swabbed < 0) {
 		CERROR("Failed to unpack after decryption\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	req->rq_reqdata_len = msglen;
 
 	if (msg->lm_bufcount < 1) {
 		CERROR("Invalid buffer: is empty\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
 		if (msg->lm_bufcount < offset + 1) {
 			CERROR("no user descriptor included\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (sptlrpc_unpack_user_desc(msg, offset, swabbed)) {
 			CERROR("Mal-formed user descriptor\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		req->rq_pack_udesc = 1;
@@ -2226,11 +2207,11 @@ int gss_svc_unseal_request(struct ptlrpc_request *req,
 	if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
 		if (msg->lm_bufcount < offset + 1) {
 			CERROR("no bulk checksum included\n");
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 
 		if (bulk_sec_desc_unpack(msg, offset, swabbed))
-			RETURN(-EINVAL);
+			return -EINVAL;
 
 		req->rq_pack_bulk = 1;
 		grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
@@ -2239,7 +2220,7 @@ int gss_svc_unseal_request(struct ptlrpc_request *req,
 
 	req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0);
 	req->rq_reqlen = req->rq_reqbuf->lm_buflens[0];
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -2249,7 +2230,6 @@ int gss_svc_handle_data(struct ptlrpc_request *req,
 	struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
 	__u32		  major = 0;
 	int		    rc = 0;
-	ENTRY;
 
 	grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
 	if (!grctx->src_ctx) {
@@ -2272,7 +2252,7 @@ int gss_svc_handle_data(struct ptlrpc_request *req,
 	}
 
 	if (rc == 0)
-		RETURN(SECSVC_OK);
+		return SECSVC_OK;
 
 	CERROR("svc %u failed: major 0x%08x: req xid "LPU64" ctx %p idx "
 	       LPX64"(%u->%s)\n", gw->gw_svc, major, req->rq_xid,
@@ -2283,9 +2263,9 @@ error:
 	 * might happen after server reboot, to allow recovery. */
 	if ((major == GSS_S_NO_CONTEXT || major == GSS_S_BAD_SIG) &&
 	    gss_pack_err_notify(req, major, 0) == 0)
-		RETURN(SECSVC_COMPLETE);
+		return SECSVC_COMPLETE;
 
-	RETURN(SECSVC_DROP);
+	return SECSVC_DROP;
 }
 
 static
@@ -2294,7 +2274,6 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req,
 {
 	struct gss_svc_reqctx  *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
 	__u32		   major;
-	ENTRY;
 
 	req->rq_ctx_fini = 1;
 	req->rq_no_reply = 1;
@@ -2302,16 +2281,16 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req,
 	grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
 	if (!grctx->src_ctx) {
 		CDEBUG(D_SEC, "invalid gss context handle for destroy.\n");
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	if (gw->gw_svc != SPTLRPC_SVC_INTG) {
 		CERROR("svc %u is not supported in destroy.\n", gw->gw_svc);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	if (gss_svc_verify_request(req, grctx, gw, &major))
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 
 	CWARN("destroy svc ctx %p idx "LPX64" (%u->%s)\n",
 	      grctx->src_ctx, gss_handle_to_u64(&gw->gw_handle),
@@ -2322,19 +2301,19 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req,
 	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
 		if (req->rq_reqbuf->lm_bufcount < 4) {
 			CERROR("missing user descriptor, ignore it\n");
-			RETURN(SECSVC_OK);
+			return SECSVC_OK;
 		}
 		if (sptlrpc_unpack_user_desc(req->rq_reqbuf, 2,
 					     ptlrpc_req_need_swab(req))) {
 			CERROR("Mal-formed user descriptor, ignore it\n");
-			RETURN(SECSVC_OK);
+			return SECSVC_OK;
 		}
 
 		req->rq_pack_udesc = 1;
 		req->rq_user_desc = lustre_msg_buf(req->rq_reqbuf, 2, 0);
 	}
 
-	RETURN(SECSVC_OK);
+	return SECSVC_OK;
 }
 
 int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
@@ -2343,14 +2322,13 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
 	struct gss_svc_reqctx  *grctx;
 	struct gss_wire_ctx    *gw;
 	int		     swabbed, rc;
-	ENTRY;
 
 	LASSERT(req->rq_reqbuf);
 	LASSERT(req->rq_svc_ctx == NULL);
 
 	if (req->rq_reqbuf->lm_bufcount < 2) {
 		CERROR("buf count only %d\n", req->rq_reqbuf->lm_bufcount);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	swabbed = ptlrpc_req_need_swab(req);
@@ -2358,14 +2336,14 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
 	ghdr = gss_swab_header(req->rq_reqbuf, 0, swabbed);
 	if (ghdr == NULL) {
 		CERROR("can't decode gss header\n");
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	/* sanity checks */
 	if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
 		CERROR("gss version %u, expect %u\n", ghdr->gh_version,
 		       PTLRPC_GSS_VERSION);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	req->rq_sp_from = ghdr->gh_sp;
@@ -2373,7 +2351,7 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
 	/* alloc grctx data */
 	OBD_ALLOC_PTR(grctx);
 	if (!grctx)
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 
 	grctx->src_base.sc_policy = sptlrpc_policy_get(policy);
 	atomic_set(&grctx->src_base.sc_refcount, 1);
@@ -2428,16 +2406,14 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
 		break;
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx)
 {
 	struct gss_svc_reqctx  *grctx;
-	ENTRY;
 
 	if (svc_ctx == NULL) {
-		EXIT;
 		return;
 	}
 
@@ -2446,8 +2422,6 @@ void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx)
 	CWARN("gss svc invalidate ctx %p(%u)\n",
 	      grctx->src_ctx, grctx->src_ctx->gsc_uid);
 	gss_svc_upcall_destroy_ctx(grctx->src_ctx);
-
-	EXIT;
 }
 
 static inline
@@ -2496,13 +2470,12 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 	__u32			ibuflens[2], buflens[4];
 	int			  ibufcnt = 0, bufcnt;
 	int			  txtsize, wmsg_size, rs_size;
-	ENTRY;
 
 	LASSERT(msglen % 8 == 0);
 
 	if (req->rq_pack_bulk && !req->rq_bulk_read && !req->rq_bulk_write) {
 		CERROR("client request bulk sec on non-bulk rpc\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
@@ -2575,7 +2548,7 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 	} else {
 		OBD_ALLOC_LARGE(rs, rs_size);
 		if (rs == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		rs->rs_size = rs_size;
 	}
@@ -2605,7 +2578,7 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 
 	LASSERT(rs->rs_msg);
 	req->rq_reply_state = rs;
-	RETURN(0);
+	return 0;
 }
 
 static int gss_svc_seal(struct ptlrpc_request *req,
@@ -2619,7 +2592,6 @@ static int gss_svc_seal(struct ptlrpc_request *req,
 	int		      token_buflen;
 	__u32		    buflens[2], major;
 	int		      msglen, rc;
-	ENTRY;
 
 	/* get clear data length. note embedded lustre_msg might
 	 * have been shrinked */
@@ -2647,7 +2619,7 @@ static int gss_svc_seal(struct ptlrpc_request *req,
 	token_buflen = gss_mech_payload(gctx->gsc_mechctx, msglen, 1);
 	OBD_ALLOC_LARGE(token_buf, token_buflen);
 	if (token_buf == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	hdrobj.len = PTLRPC_GSS_HEADER_SIZE;
 	hdrobj.data = (__u8 *) ghdr;
@@ -2703,7 +2675,7 @@ static int gss_svc_seal(struct ptlrpc_request *req,
 	rc = 0;
 out_free:
 	OBD_FREE_LARGE(token_buf, token_buflen);
-	RETURN(rc);
+	return rc;
 }
 
 int gss_svc_authorize(struct ptlrpc_request *req)
@@ -2712,7 +2684,6 @@ int gss_svc_authorize(struct ptlrpc_request *req)
 	struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
 	struct gss_wire_ctx       *gw = &grctx->src_wirectx;
 	int			early, rc;
-	ENTRY;
 
 	early = (req->rq_packed_final == 0);
 
@@ -2720,7 +2691,7 @@ int gss_svc_authorize(struct ptlrpc_request *req)
 		LASSERT(rs->rs_repdata_len != 0);
 
 		req->rq_reply_off = gss_at_reply_off_integ;
-		RETURN(0);
+		return 0;
 	}
 
 	/* early reply could happen in many cases */
@@ -2728,7 +2699,7 @@ int gss_svc_authorize(struct ptlrpc_request *req)
 	    gw->gw_proc != PTLRPC_GSS_PROC_DATA &&
 	    gw->gw_proc != PTLRPC_GSS_PROC_DESTROY) {
 		CERROR("proc %d not support\n", gw->gw_proc);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	LASSERT(grctx->src_ctx);
@@ -2749,7 +2720,7 @@ int gss_svc_authorize(struct ptlrpc_request *req)
 	rc = 0;
 
 out:
-	RETURN(rc);
+	return rc;
 }
 
 void gss_svc_free_rs(struct ptlrpc_reply_state *rs)
diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
index 47a3c05..5ca69ae 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
@@ -195,7 +195,6 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt)
 /* Must be called with imp_lock held! */
 static void ptlrpc_deactivate_and_unlock_import(struct obd_import *imp)
 {
-	ENTRY;
 	LASSERT(spin_is_locked(&imp->imp_lock));
 
 	CDEBUG(D_HA, "setting import %s INVALID\n", obd2cli_tgt(imp->imp_obd));
@@ -205,8 +204,6 @@ static void ptlrpc_deactivate_and_unlock_import(struct obd_import *imp)
 
 	ptlrpc_abort_inflight(imp);
 	obd_import_event(imp->imp_obd, imp, IMP_EVENT_INACTIVE);
-
-	EXIT;
 }
 
 /*
@@ -394,8 +391,6 @@ EXPORT_SYMBOL(ptlrpc_activate_import);
 
 void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
 {
-	ENTRY;
-
 	LASSERT(!imp->imp_dlm_fake);
 
 	if (ptlrpc_set_import_discon(imp, conn_cnt)) {
@@ -417,7 +412,6 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
 
 		ptlrpc_pinger_wake_up();
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_fail_import);
 
@@ -461,7 +455,6 @@ static int import_select_connection(struct obd_import *imp)
 	struct obd_export *dlmexp;
 	char *target_start;
 	int target_len, tried_all = 1;
-	ENTRY;
 
 	spin_lock(&imp->imp_lock);
 
@@ -469,7 +462,7 @@ static int import_select_connection(struct obd_import *imp)
 		CERROR("%s: no connections available\n",
 		       imp->imp_obd->obd_name);
 		spin_unlock(&imp->imp_lock);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
@@ -558,7 +551,7 @@ static int import_select_connection(struct obd_import *imp)
 
 	spin_unlock(&imp->imp_lock);
 
-	RETURN(0);
+	return 0;
 }
 
 /*
@@ -602,21 +595,20 @@ int ptlrpc_connect_import(struct obd_import *imp)
 			 (char *)&imp->imp_connect_data };
 	struct ptlrpc_connect_async_args *aa;
 	int rc;
-	ENTRY;
 
 	spin_lock(&imp->imp_lock);
 	if (imp->imp_state == LUSTRE_IMP_CLOSED) {
 		spin_unlock(&imp->imp_lock);
 		CERROR("can't connect to a closed import\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	} else if (imp->imp_state == LUSTRE_IMP_FULL) {
 		spin_unlock(&imp->imp_lock);
 		CERROR("already connected\n");
-		RETURN(0);
+		return 0;
 	} else if (imp->imp_state == LUSTRE_IMP_CONNECTING) {
 		spin_unlock(&imp->imp_lock);
 		CERROR("already connecting\n");
-		RETURN(-EALREADY);
+		return -EALREADY;
 	}
 
 	IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_CONNECTING);
@@ -716,7 +708,7 @@ out:
 		IMPORT_SET_STATE(imp, LUSTRE_IMP_DISCON);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_connect_import);
 
@@ -756,13 +748,12 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
 	struct obd_connect_data *ocd;
 	struct obd_export *exp;
 	int ret;
-	ENTRY;
 
 	spin_lock(&imp->imp_lock);
 	if (imp->imp_state == LUSTRE_IMP_CLOSED) {
 		imp->imp_connect_tried = 1;
 		spin_unlock(&imp->imp_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	if (rc) {
@@ -984,7 +975,7 @@ finish:
 			       imp->imp_connection->c_remote_uuid.uuid);
 			ptlrpc_connect_import(imp);
 			imp->imp_connect_tried = 1;
-			RETURN(0);
+			return 0;
 		}
 	} else {
 
@@ -1137,7 +1128,7 @@ out:
 
 			/* reply message might not be ready */
 			if (request->rq_repmsg == NULL)
-				RETURN(-EPROTO);
+				return -EPROTO;
 
 			ocd = req_capsule_server_get(&request->rq_pill,
 						     &RMF_CONNECT_DATA);
@@ -1161,7 +1152,7 @@ out:
 				ptlrpc_deactivate_import(imp);
 				IMPORT_SET_STATE(imp, LUSTRE_IMP_CLOSED);
 			}
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		ptlrpc_maybe_ping_import_soon(imp);
@@ -1172,7 +1163,7 @@ out:
 	}
 
 	wake_up_all(&imp->imp_recovery_waitq);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1183,7 +1174,6 @@ static int completed_replay_interpret(const struct lu_env *env,
 				      struct ptlrpc_request *req,
 				      void * data, int rc)
 {
-	ENTRY;
 	atomic_dec(&req->rq_import->imp_replay_inflight);
 	if (req->rq_status == 0 &&
 	    !req->rq_import->imp_vbr_failed) {
@@ -1202,7 +1192,7 @@ static int completed_replay_interpret(const struct lu_env *env,
 		ptlrpc_connect_import(req->rq_import);
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1212,10 +1202,9 @@ static int completed_replay_interpret(const struct lu_env *env,
 static int signal_completed_replay(struct obd_import *imp)
 {
 	struct ptlrpc_request *req;
-	ENTRY;
 
 	if (unlikely(OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_FINISH_REPLAY)))
-		RETURN(0);
+		return 0;
 
 	LASSERT(atomic_read(&imp->imp_replay_inflight) == 0);
 	atomic_inc(&imp->imp_replay_inflight);
@@ -1224,7 +1213,7 @@ static int signal_completed_replay(struct obd_import *imp)
 					OBD_PING);
 	if (req == NULL) {
 		atomic_dec(&imp->imp_replay_inflight);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	ptlrpc_request_set_replen(req);
@@ -1236,7 +1225,7 @@ static int signal_completed_replay(struct obd_import *imp)
 	req->rq_interpret_reply = completed_replay_interpret;
 
 	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1248,8 +1237,6 @@ static int ptlrpc_invalidate_import_thread(void *data)
 {
 	struct obd_import *imp = data;
 
-	ENTRY;
-
 	unshare_fs_struct();
 
 	CDEBUG(D_HA, "thread invalidate import %s to %s@%s\n",
@@ -1267,7 +1254,7 @@ static int ptlrpc_invalidate_import_thread(void *data)
 	ptlrpc_import_recovery_state_machine(imp);
 
 	class_import_put(imp);
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1297,7 +1284,6 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
 	char *target_start;
 	int target_len;
 
-	ENTRY;
 	if (imp->imp_state == LUSTRE_IMP_EVICTED) {
 		deuuidify(obd2cli_tgt(imp->imp_obd), NULL,
 			  &target_start, &target_len);
@@ -1319,7 +1305,7 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
 		spin_unlock(&imp->imp_lock);
 
 		{
-		task_t *task;
+		struct task_struct *task;
 		/* bug 17802:  XXX client_disconnect_export vs connect request
 		 * race. if client will evicted at this time, we start
 		 * invalidate thread without reference to import and import can
@@ -1334,7 +1320,7 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
 		} else {
 			rc = 0;
 		}
-		RETURN(rc);
+		return rc;
 		}
 	}
 
@@ -1393,7 +1379,7 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
 	}
 
 out:
-	RETURN(rc);
+	return rc;
 }
 
 int ptlrpc_disconnect_import(struct obd_import *imp, int noclose)
@@ -1401,7 +1387,6 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose)
 	struct ptlrpc_request *req;
 	int rq_opc, rc = 0;
 	int nowait = imp->imp_obd->obd_force;
-	ENTRY;
 
 	if (nowait)
 		GOTO(set_state, rc);
@@ -1413,7 +1398,7 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose)
 	default:
 		CERROR("don't know how to disconnect from %s (connect_op %d)\n",
 		       obd2cli_tgt(imp->imp_obd), imp->imp_connect_op);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (ptlrpc_import_in_recovery(imp)) {
@@ -1476,21 +1461,17 @@ out:
 	memset(&imp->imp_remote_handle, 0, sizeof(imp->imp_remote_handle));
 	spin_unlock(&imp->imp_lock);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_disconnect_import);
 
 void ptlrpc_cleanup_imp(struct obd_import *imp)
 {
-	ENTRY;
-
 	spin_lock(&imp->imp_lock);
 	IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_CLOSED);
 	imp->imp_generation++;
 	spin_unlock(&imp->imp_lock);
 	ptlrpc_abort_inflight(imp);
-
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_cleanup_imp);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
index 367ca8e..379e594 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
@@ -85,7 +85,6 @@ static int llog_client_open(const struct lu_env *env,
 	struct llog_ctxt      *ctxt = lgh->lgh_ctxt;
 	struct ptlrpc_request *req = NULL;
 	int		    rc;
-	ENTRY;
 
 	LLOG_CLIENT_ENTRY(ctxt, imp);
 
@@ -133,7 +132,6 @@ static int llog_client_open(const struct lu_env *env,
 
 	lgh->lgh_id = body->lgd_logid;
 	lgh->lgh_ctxt = ctxt;
-	EXIT;
 out:
 	LLOG_CLIENT_EXIT(ctxt, imp);
 	ptlrpc_req_finished(req);
@@ -147,7 +145,6 @@ static int llog_client_destroy(const struct lu_env *env,
 	struct ptlrpc_request *req = NULL;
 	struct llogd_body     *body;
 	int		    rc;
-	ENTRY;
 
 	LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_DESTROY,
@@ -170,7 +167,7 @@ static int llog_client_destroy(const struct lu_env *env,
 	ptlrpc_req_finished(req);
 err_exit:
 	LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -184,7 +181,6 @@ static int llog_client_next_block(const struct lu_env *env,
 	struct llogd_body     *body;
 	void		  *ptr;
 	int		    rc;
-	ENTRY;
 
 	LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK,
@@ -221,7 +217,6 @@ static int llog_client_next_block(const struct lu_env *env,
 	*cur_offset = body->lgd_cur_offset;
 
 	memcpy(buf, ptr, len);
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 err_exit:
@@ -238,7 +233,6 @@ static int llog_client_prev_block(const struct lu_env *env,
 	struct llogd_body     *body;
 	void		  *ptr;
 	int		    rc;
-	ENTRY;
 
 	LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK,
@@ -270,7 +264,6 @@ static int llog_client_prev_block(const struct lu_env *env,
 		GOTO(out, rc =-EFAULT);
 
 	memcpy(buf, ptr, len);
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 err_exit:
@@ -287,7 +280,6 @@ static int llog_client_read_header(const struct lu_env *env,
 	struct llog_log_hdr   *hdr;
 	struct llog_rec_hdr   *llh_hdr;
 	int		    rc;
-	ENTRY;
 
 	LLOG_CLIENT_ENTRY(handle->lgh_ctxt, imp);
 	req = ptlrpc_request_alloc_pack(imp,&RQF_LLOG_ORIGIN_HANDLE_READ_HEADER,
@@ -326,7 +318,6 @@ static int llog_client_read_header(const struct lu_env *env,
 		CERROR("you may need to re-run lconf --write_conf.\n");
 		rc = -EIO;
 	}
-	EXIT;
 out:
 	ptlrpc_req_finished(req);
 err_exit:
diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_net.c b/drivers/staging/lustre/lustre/ptlrpc/llog_net.c
index a81f557..17c06a3 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/llog_net.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/llog_net.c
@@ -57,7 +57,6 @@
 int llog_initiator_connect(struct llog_ctxt *ctxt)
 {
 	struct obd_import *new_imp;
-	ENTRY;
 
 	LASSERT(ctxt);
 	new_imp = ctxt->loc_obd->u.cli.cl_import;
@@ -70,6 +69,6 @@ int llog_initiator_connect(struct llog_ctxt *ctxt)
 		ctxt->loc_imp = class_import_get(new_imp);
 	}
 	mutex_unlock(&ctxt->loc_mutex);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(llog_initiator_connect);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c
index bc1fcd8..af9d2ac 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c
@@ -71,11 +71,9 @@ int llog_origin_handle_open(struct ptlrpc_request *req)
 	char			*name = NULL;
 	int			 rc;
 
-	ENTRY;
-
 	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
 	if (body == NULL)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	if (ostid_id(&body->lgd_logid.lgl_oi) > 0)
 		logid = &body->lgd_logid;
@@ -83,7 +81,7 @@ int llog_origin_handle_open(struct ptlrpc_request *req)
 	if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) {
 		name = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
 		if (name == NULL)
-			RETURN(-EFAULT);
+			return -EFAULT;
 		CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name);
 	}
 
@@ -91,7 +89,7 @@ int llog_origin_handle_open(struct ptlrpc_request *req)
 	if (ctxt == NULL) {
 		CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n",
 		       obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 	disk_obd = ctxt->loc_exp->exp_obd;
 	push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
@@ -108,7 +106,6 @@ int llog_origin_handle_open(struct ptlrpc_request *req)
 	body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
 	body->lgd_logid = loghandle->lgh_id;
 
-	EXIT;
 out_close:
 	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
 out_pop:
@@ -127,11 +124,9 @@ int llog_origin_handle_destroy(struct ptlrpc_request *req)
 	struct llog_ctxt	*ctxt;
 	int			 rc;
 
-	ENTRY;
-
 	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
 	if (body == NULL)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	if (ostid_id(&body->lgd_logid.lgl_oi) > 0)
 		logid = &body->lgd_logid;
@@ -142,7 +137,7 @@ int llog_origin_handle_destroy(struct ptlrpc_request *req)
 
 	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
 	if (ctxt == NULL)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	disk_obd = ctxt->loc_exp->exp_obd;
 	push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
@@ -153,7 +148,7 @@ int llog_origin_handle_destroy(struct ptlrpc_request *req)
 		rc = llog_erase(req->rq_svc_thread->t_env, ctxt, logid, NULL);
 	pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
 	llog_ctxt_put(ctxt);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(llog_origin_handle_destroy);
 
@@ -169,15 +164,13 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req)
 	void		*ptr;
 	int		  rc;
 
-	ENTRY;
-
 	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
 	if (body == NULL)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
 	if (ctxt == NULL)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	disk_obd = ctxt->loc_exp->exp_obd;
 	push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
@@ -208,7 +201,6 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req)
 			     &repbody->lgd_cur_offset, ptr, LLOG_CHUNK_SIZE);
 	if (rc)
 		GOTO(out_close, rc);
-	EXIT;
 out_close:
 	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
 out_pop:
@@ -230,15 +222,13 @@ int llog_origin_handle_prev_block(struct ptlrpc_request *req)
 	void		 *ptr;
 	int		   rc;
 
-	ENTRY;
-
 	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
 	if (body == NULL)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
 	if (ctxt == NULL)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	disk_obd = ctxt->loc_exp->exp_obd;
 	push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
@@ -269,7 +259,6 @@ int llog_origin_handle_prev_block(struct ptlrpc_request *req)
 	if (rc)
 		GOTO(out_close, rc);
 
-	EXIT;
 out_close:
 	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
 out_pop:
@@ -290,15 +279,13 @@ int llog_origin_handle_read_header(struct ptlrpc_request *req)
 	__u32		 flags;
 	int		   rc;
 
-	ENTRY;
-
 	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
 	if (body == NULL)
-		RETURN(-EFAULT);
+		return -EFAULT;
 
 	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
 	if (ctxt == NULL)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	disk_obd = ctxt->loc_exp->exp_obd;
 	push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
@@ -324,7 +311,6 @@ int llog_origin_handle_read_header(struct ptlrpc_request *req)
 
 	hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
 	*hdr = *loghandle->lgh_hdr;
-	EXIT;
 out_close:
 	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
 out_pop:
@@ -336,9 +322,8 @@ EXPORT_SYMBOL(llog_origin_handle_read_header);
 
 int llog_origin_handle_close(struct ptlrpc_request *req)
 {
-	ENTRY;
 	/* Nothing to do */
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(llog_origin_handle_close);
 
@@ -352,20 +337,19 @@ int llog_origin_handle_cancel(struct ptlrpc_request *req)
 	struct llog_handle *cathandle;
 	struct inode *inode;
 	void *handle;
-	ENTRY;
 
 	logcookies = req_capsule_client_get(&req->rq_pill, &RMF_LOGCOOKIES);
 	num_cookies = req_capsule_get_size(&req->rq_pill, &RMF_LOGCOOKIES,
 					   RCL_CLIENT) / sizeof(*logcookies);
 	if (logcookies == NULL || num_cookies == 0) {
 		DEBUG_REQ(D_HA, req, "No llog cookies sent");
-		RETURN(-EFAULT);
+		return -EFAULT;
 	}
 
 	ctxt = llog_get_context(req->rq_export->exp_obd,
 				logcookies->lgc_subsys);
 	if (ctxt == NULL)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
 	disk_obd = ctxt->loc_exp->exp_obd;
 	push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
index 3e73254..bea44a3 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
@@ -302,7 +302,7 @@ ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char *buffer,
 	 * hose a kernel by allowing the request history to grow too
 	 * far. */
 	bufpages = (svc->srv_buf_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	if (val > num_physpages/(2 * bufpages))
+	if (val > totalram_pages / (2 * bufpages))
 		return -ERANGE;
 
 	spin_lock(&svc->srv_lock);
@@ -480,7 +480,6 @@ static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n)
 	bool				hp = false;
 	int				i;
 	int				rc = 0;
-	ENTRY;
 
 	/**
 	 * Serialize NRS core lprocfs operations with policy registration/
@@ -613,7 +612,7 @@ out:
 
 	mutex_unlock(&nrs_core.nrs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -638,7 +637,6 @@ static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, const char *buffe
 	char			       *cmd_copy = NULL;
 	char			       *token;
 	int				rc = 0;
-	ENTRY;
 
 	if (count >= LPROCFS_NRS_WR_MAX_CMD)
 		GOTO(out, rc = -EINVAL);
@@ -698,7 +696,7 @@ out:
 	if (cmd_copy)
 		OBD_FREE(cmd_copy, LPROCFS_NRS_WR_MAX_CMD);
 
-	RETURN(rc < 0 ? rc : count);
+	return rc < 0 ? rc : count;
 }
 LPROC_SEQ_FOPS(ptlrpc_lprocfs_nrs);
 
@@ -1217,13 +1215,12 @@ int lprocfs_wr_ping(struct file *file, const char *buffer,
 	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
 	struct ptlrpc_request *req;
 	int		    rc;
-	ENTRY;
 
 	LPROCFS_CLIMP_CHECK(obd);
 	req = ptlrpc_prep_ping(obd->u.cli.cl_import);
 	LPROCFS_CLIMP_EXIT(obd);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req->rq_send_state = LUSTRE_IMP_FULL;
 
@@ -1231,8 +1228,8 @@ int lprocfs_wr_ping(struct file *file, const char *buffer,
 
 	ptlrpc_req_finished(req);
 	if (rc >= 0)
-		RETURN(count);
-	RETURN(rc);
+		return count;
+	return rc;
 }
 EXPORT_SYMBOL(lprocfs_wr_ping);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
index de3f0db..a0e0097 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
@@ -54,7 +54,6 @@ static int ptl_send_buf (lnet_handle_md_t *mdh, void *base, int len,
 {
 	int	      rc;
 	lnet_md_t	 md;
-	ENTRY;
 
 	LASSERT (portal != 0);
 	LASSERT (conn != NULL);
@@ -76,7 +75,7 @@ static int ptl_send_buf (lnet_handle_md_t *mdh, void *base, int len,
 	if (unlikely(rc != 0)) {
 		CERROR ("LNetMDBind failed: %d\n", rc);
 		LASSERT (rc == -ENOMEM);
-		RETURN (-ENOMEM);
+		return -ENOMEM;
 	}
 
 	CDEBUG(D_NET, "Sending %d bytes to portal %d, xid "LPD64", offset %u\n",
@@ -95,7 +94,7 @@ static int ptl_send_buf (lnet_handle_md_t *mdh, void *base, int len,
 		LASSERTF(rc2 == 0, "rc2 = %d\n", rc2);
 	}
 
-	RETURN (0);
+	return 0;
 }
 
 static void mdunlink_iterate_helper(lnet_handle_md_t *bd_mds, int count)
@@ -122,10 +121,9 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req)
 	__u64 xid;
 	lnet_handle_me_t  me_h;
 	lnet_md_t	 md;
-	ENTRY;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_BULK_GET_NET))
-		RETURN(0);
+		return 0;
 
 	/* NB no locking required until desc is on the network */
 	LASSERT(desc->bd_nob > 0);
@@ -207,7 +205,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req)
 		LASSERT(desc->bd_md_count >= 0);
 		mdunlink_iterate_helper(desc->bd_mds, desc->bd_md_max_brw);
 		req->rq_status = -ENOMEM;
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* Set rq_xid to matchbits of the final bulk so that server can
@@ -231,7 +229,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req)
 	       desc->bd_iov_count, desc->bd_nob,
 	       desc->bd_last_xid, req->rq_xid, desc->bd_portal);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_register_bulk);
 
@@ -247,7 +245,6 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
 	wait_queue_head_t	     *wq;
 	struct l_wait_info       lwi;
 	int		      rc;
-	ENTRY;
 
 	LASSERT(!in_interrupt());     /* might sleep */
 
@@ -257,7 +254,7 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
 		req->rq_bulk_deadline = cfs_time_current_sec() + LONG_UNLINK;
 
 	if (ptlrpc_client_bulk_active(req) == 0)	/* completed or */
-		RETURN(1);				/* never registered */
+		return 1;				/* never registered */
 
 	LASSERT(desc->bd_req == req);  /* bd_req NULL until registered */
 
@@ -268,14 +265,14 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
 	mdunlink_iterate_helper(desc->bd_mds, desc->bd_md_max_brw);
 
 	if (ptlrpc_client_bulk_active(req) == 0)	/* completed or */
-		RETURN(1);				/* never registered */
+		return 1;				/* never registered */
 
 	/* Move to "Unregistering" phase as bulk was not unlinked yet. */
 	ptlrpc_rqphase_move(req, RQ_PHASE_UNREGISTERING);
 
 	/* Do not wait for unlink to finish. */
 	if (async)
-		RETURN(0);
+		return 0;
 
 	if (req->rq_set != NULL)
 		wq = &req->rq_set->set_waitq;
@@ -290,14 +287,14 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
 		rc = l_wait_event(*wq, !ptlrpc_client_bulk_active(req), &lwi);
 		if (rc == 0) {
 			ptlrpc_rqphase_move(req, req->rq_next_phase);
-			RETURN(1);
+			return 1;
 		}
 
 		LASSERT(rc == -ETIMEDOUT);
 		DEBUG_REQ(D_WARNING, req, "Unexpectedly long timeout: desc %p",
 			  desc);
 	}
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_unregister_bulk);
 
@@ -400,7 +397,8 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags)
 		req->rq_type = PTL_RPC_MSG_REPLY;
 
 	lustre_msg_set_type(req->rq_repmsg, req->rq_type);
-	lustre_msg_set_status(req->rq_repmsg, req->rq_status);
+	lustre_msg_set_status(req->rq_repmsg,
+			      ptlrpc_status_hton(req->rq_status));
 	lustre_msg_set_opc(req->rq_repmsg,
 		req->rq_reqmsg ? lustre_msg_get_opc(req->rq_reqmsg) : 0);
 
@@ -455,15 +453,14 @@ EXPORT_SYMBOL(ptlrpc_reply);
 int ptlrpc_send_error(struct ptlrpc_request *req, int may_be_difficult)
 {
 	int rc;
-	ENTRY;
 
 	if (req->rq_no_reply)
-		RETURN(0);
+		return 0;
 
 	if (!req->rq_repmsg) {
 		rc = lustre_pack_reply(req, 1, NULL, NULL);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
 	if (req->rq_status != -ENOSPC && req->rq_status != -EACCES &&
@@ -472,7 +469,7 @@ int ptlrpc_send_error(struct ptlrpc_request *req, int may_be_difficult)
 		req->rq_type = PTL_RPC_MSG_ERR;
 
 	rc = ptlrpc_send_reply(req, may_be_difficult);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_send_error);
 
@@ -497,10 +494,9 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
 	lnet_handle_me_t  reply_me_h;
 	lnet_md_t	 reply_md;
 	struct obd_device *obd = request->rq_import->imp_obd;
-	ENTRY;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_RPC))
-		RETURN(0);
+		return 0;
 
 	LASSERT(request->rq_type == PTL_RPC_MSG_REQUEST);
 	LASSERT(request->rq_wait_ctx == 0);
@@ -516,7 +512,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
 		/* this prevents us from waiting in ptlrpc_queue_wait */
 		request->rq_err = 1;
 		request->rq_status = -ENODEV;
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	connection = request->rq_import->imp_connection;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
index 1996431..0abcd6d 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
@@ -81,17 +81,16 @@ static int nrs_policy_ctl_locked(struct ptlrpc_nrs_policy *policy,
 	 * policy->pol_private will be NULL in such a case.
 	 */
 	if (policy->pol_state == NRS_POL_STATE_STOPPED)
-		RETURN(-ENODEV);
+		return -ENODEV;
 
-	RETURN(policy->pol_desc->pd_ops->op_policy_ctl != NULL ?
+	return policy->pol_desc->pd_ops->op_policy_ctl != NULL ?
 	       policy->pol_desc->pd_ops->op_policy_ctl(policy, opc, arg) :
-	       -ENOSYS);
+	       -ENOSYS;
 }
 
 static void nrs_policy_stop0(struct ptlrpc_nrs_policy *policy)
 {
 	struct ptlrpc_nrs *nrs = policy->pol_nrs;
-	ENTRY;
 
 	if (policy->pol_desc->pd_ops->op_policy_stop != NULL) {
 		spin_unlock(&nrs->nrs_lock);
@@ -111,24 +110,21 @@ static void nrs_policy_stop0(struct ptlrpc_nrs_policy *policy)
 
 	if (atomic_dec_and_test(&policy->pol_desc->pd_refs))
 		module_put(policy->pol_desc->pd_owner);
-
-	EXIT;
 }
 
 static int nrs_policy_stop_locked(struct ptlrpc_nrs_policy *policy)
 {
 	struct ptlrpc_nrs *nrs = policy->pol_nrs;
-	ENTRY;
 
 	if (nrs->nrs_policy_fallback == policy && !nrs->nrs_stopping)
-		RETURN(-EPERM);
+		return -EPERM;
 
 	if (policy->pol_state == NRS_POL_STATE_STARTING)
-		RETURN(-EAGAIN);
+		return -EAGAIN;
 
 	/* In progress or already stopped */
 	if (policy->pol_state != NRS_POL_STATE_STARTED)
-		RETURN(0);
+		return 0;
 
 	policy->pol_state = NRS_POL_STATE_STOPPING;
 
@@ -145,7 +141,7 @@ static int nrs_policy_stop_locked(struct ptlrpc_nrs_policy *policy)
 	if (policy->pol_ref == 1)
 		nrs_policy_stop0(policy);
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -158,15 +154,8 @@ static int nrs_policy_stop_locked(struct ptlrpc_nrs_policy *policy)
 static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs)
 {
 	struct ptlrpc_nrs_policy *tmp = nrs->nrs_policy_primary;
-	ENTRY;
 
 	if (tmp == NULL) {
-		/**
-		 * XXX: This should really be RETURN_EXIT, but the latter does
-		 * not currently print anything out, and possibly should be
-		 * fixed to do so.
-		 */
-		EXIT;
 		return;
 	}
 
@@ -177,7 +166,6 @@ static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs)
 
 	if (tmp->pol_ref == 0)
 		nrs_policy_stop0(tmp);
-	EXIT;
 }
 
 /**
@@ -203,19 +191,18 @@ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
 {
 	struct ptlrpc_nrs      *nrs = policy->pol_nrs;
 	int			rc = 0;
-	ENTRY;
 
 	/**
 	 * Don't allow multiple starting which is too complex, and has no real
 	 * benefit.
 	 */
 	if (nrs->nrs_policy_starting)
-		RETURN(-EAGAIN);
+		return -EAGAIN;
 
 	LASSERT(policy->pol_state != NRS_POL_STATE_STARTING);
 
 	if (policy->pol_state == NRS_POL_STATE_STOPPING)
-		RETURN(-EAGAIN);
+		return -EAGAIN;
 
 	if (policy->pol_flags & PTLRPC_NRS_FL_FALLBACK) {
 		/**
@@ -226,7 +213,7 @@ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
 		 */
 		if (policy == nrs->nrs_policy_fallback) {
 			nrs_policy_stop_primary(nrs);
-			RETURN(0);
+			return 0;
 		}
 
 		/**
@@ -241,10 +228,10 @@ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
 		 * Shouldn't start primary policy if w/o fallback policy.
 		 */
 		if (nrs->nrs_policy_fallback == NULL)
-			RETURN(-EPERM);
+			return -EPERM;
 
 		if (policy->pol_state == NRS_POL_STATE_STARTED)
-			RETURN(0);
+			return 0;
 	}
 
 	/**
@@ -256,7 +243,7 @@ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
 		atomic_dec(&policy->pol_desc->pd_refs);
 		CERROR("NRS: cannot get module for policy %s; is it alive?\n",
 		       policy->pol_desc->pd_name);
-		RETURN(-ENODEV);
+		return -ENODEV;
 	}
 
 	/**
@@ -303,7 +290,7 @@ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
 out:
 	nrs->nrs_policy_starting = 0;
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -644,7 +631,6 @@ static int nrs_policy_ctl(struct ptlrpc_nrs *nrs, char *name,
 {
 	struct ptlrpc_nrs_policy       *policy;
 	int				rc = 0;
-	ENTRY;
 
 	spin_lock(&nrs->nrs_lock);
 
@@ -674,7 +660,7 @@ out:
 
 	spin_unlock(&nrs->nrs_lock);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -690,7 +676,6 @@ out:
 static int nrs_policy_unregister(struct ptlrpc_nrs *nrs, char *name)
 {
 	struct ptlrpc_nrs_policy *policy = NULL;
-	ENTRY;
 
 	spin_lock(&nrs->nrs_lock);
 
@@ -699,7 +684,7 @@ static int nrs_policy_unregister(struct ptlrpc_nrs *nrs, char *name)
 		spin_unlock(&nrs->nrs_lock);
 
 		CERROR("Can't find NRS policy %s\n", name);
-		RETURN(-ENOENT);
+		return -ENOENT;
 	}
 
 	if (policy->pol_ref > 1) {
@@ -708,7 +693,7 @@ static int nrs_policy_unregister(struct ptlrpc_nrs *nrs, char *name)
 		nrs_policy_put_locked(policy);
 
 		spin_unlock(&nrs->nrs_lock);
-		RETURN(-EBUSY);
+		return -EBUSY;
 	}
 
 	LASSERT(policy->pol_req_queued == 0);
@@ -731,7 +716,7 @@ static int nrs_policy_unregister(struct ptlrpc_nrs *nrs, char *name)
 	LASSERT(policy->pol_private == NULL);
 	OBD_FREE_PTR(policy);
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -751,7 +736,6 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
 	struct ptlrpc_nrs_policy       *tmp;
 	struct ptlrpc_service_part     *svcpt = nrs->nrs_svcpt;
 	int				rc;
-	ENTRY;
 
 	LASSERT(svcpt != NULL);
 	LASSERT(desc->pd_ops != NULL);
@@ -764,7 +748,7 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
 	OBD_CPT_ALLOC_GFP(policy, svcpt->scp_service->srv_cptable,
 			  svcpt->scp_cpt, sizeof(*policy), __GFP_IO);
 	if (policy == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	policy->pol_nrs     = nrs;
 	policy->pol_desc    = desc;
@@ -777,7 +761,7 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
 	rc = nrs_policy_init(policy);
 	if (rc != 0) {
 		OBD_FREE_PTR(policy);
-		RETURN(rc);
+		return rc;
 	}
 
 	spin_lock(&nrs->nrs_lock);
@@ -793,7 +777,7 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
 		nrs_policy_fini(policy);
 		OBD_FREE_PTR(policy);
 
-		RETURN(-EEXIST);
+		return -EEXIST;
 	}
 
 	list_add_tail(&policy->pol_list, &nrs->nrs_policy_list);
@@ -807,7 +791,7 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
 	if (rc != 0)
 		(void) nrs_policy_unregister(nrs, policy->pol_desc->pd_name);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -844,7 +828,6 @@ static void ptlrpc_nrs_req_add_nolock(struct ptlrpc_request *req)
 static void ptlrpc_nrs_hpreq_add_nolock(struct ptlrpc_request *req)
 {
 	int	opc = lustre_msg_get_opc(req->rq_reqmsg);
-	ENTRY;
 
 	spin_lock(&req->rq_lock);
 	req->rq_hp = 1;
@@ -852,7 +835,6 @@ static void ptlrpc_nrs_hpreq_add_nolock(struct ptlrpc_request *req)
 	if (opc != OBD_PING)
 		DEBUG_REQ(D_NET, req, "high priority req");
 	spin_unlock(&req->rq_lock);
-	EXIT;
 }
 
 /**
@@ -891,7 +873,6 @@ static int nrs_register_policies_locked(struct ptlrpc_nrs *nrs)
 	struct ptlrpc_service_part	 *svcpt = nrs->nrs_svcpt;
 	struct ptlrpc_service		 *svc = svcpt->scp_service;
 	int				  rc = -EINVAL;
-	ENTRY;
 
 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
 
@@ -912,7 +893,7 @@ static int nrs_register_policies_locked(struct ptlrpc_nrs *nrs)
 		}
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -950,7 +931,7 @@ static int nrs_svcpt_setup_locked0(struct ptlrpc_nrs *nrs,
 
 	rc = nrs_register_policies_locked(nrs);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -966,7 +947,6 @@ static int nrs_svcpt_setup_locked(struct ptlrpc_service_part *svcpt)
 {
 	struct ptlrpc_nrs	       *nrs;
 	int				rc;
-	ENTRY;
 
 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
 
@@ -994,7 +974,7 @@ static int nrs_svcpt_setup_locked(struct ptlrpc_service_part *svcpt)
 	rc = nrs_svcpt_setup_locked0(nrs, svcpt);
 
 out:
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1012,7 +992,6 @@ static void nrs_svcpt_cleanup_locked(struct ptlrpc_service_part *svcpt)
 	struct ptlrpc_nrs_policy       *tmp;
 	int				rc;
 	bool				hp = false;
-	ENTRY;
 
 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
 
@@ -1036,8 +1015,6 @@ again:
 
 	if (hp)
 		OBD_FREE_PTR(nrs);
-
-	EXIT;
 }
 
 /**
@@ -1051,13 +1028,12 @@ again:
 static struct ptlrpc_nrs_pol_desc *nrs_policy_find_desc_locked(const char *name)
 {
 	struct ptlrpc_nrs_pol_desc     *tmp;
-	ENTRY;
 
 	list_for_each_entry(tmp, &nrs_core.nrs_policies, pd_list) {
 		if (strncmp(tmp->pd_name, name, NRS_POL_NAME_MAX) == 0)
-			RETURN(tmp);
+			return tmp;
 	}
-	RETURN(NULL);
+	return NULL;
 }
 
 /**
@@ -1079,7 +1055,6 @@ static int nrs_policy_unregister_locked(struct ptlrpc_nrs_pol_desc *desc)
 	struct ptlrpc_service_part     *svcpt;
 	int				i;
 	int				rc = 0;
-	ENTRY;
 
 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
 	LASSERT(mutex_is_locked(&ptlrpc_all_services_mutex));
@@ -1107,7 +1082,7 @@ again:
 				       "partition %d of service %s: %d\n",
 				       desc->pd_name, svcpt->scp_cpt,
 				       svcpt->scp_service->srv_name, rc);
-				RETURN(rc);
+				return rc;
 			}
 
 			if (!hp && nrs_svc_has_hp(svc)) {
@@ -1120,7 +1095,7 @@ again:
 			desc->pd_ops->op_lprocfs_fini(svc);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1143,7 +1118,6 @@ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf)
 	struct ptlrpc_service	       *svc;
 	struct ptlrpc_nrs_pol_desc     *desc;
 	int				rc = 0;
-	ENTRY;
 
 	LASSERT(conf != NULL);
 	LASSERT(conf->nc_ops != NULL);
@@ -1171,7 +1145,7 @@ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf)
 		       "policy flags; external policies cannot act as fallback "
 		       "policies, or be started immediately upon registration "
 		       "without interaction with lprocfs\n", conf->nc_name);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	mutex_lock(&nrs_core.nrs_mutex);
@@ -1274,7 +1248,7 @@ internal:
 fail:
 	mutex_unlock(&nrs_core.nrs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_nrs_policy_register);
 
@@ -1296,14 +1270,13 @@ int ptlrpc_nrs_policy_unregister(struct ptlrpc_nrs_pol_conf *conf)
 {
 	struct ptlrpc_nrs_pol_desc	*desc;
 	int				 rc;
-	ENTRY;
 
 	LASSERT(conf != NULL);
 
 	if (conf->nc_flags & PTLRPC_NRS_FL_FALLBACK) {
 		CERROR("Unable to unregister a fallback policy, unless the "
 		       "PTLRPC service is stopping.\n");
-		RETURN(-EPERM);
+		return -EPERM;
 	}
 
 	conf->nc_name[NRS_POL_NAME_MAX - 1] = '\0';
@@ -1341,7 +1314,7 @@ fail:
 not_exist:
 	mutex_unlock(&nrs_core.nrs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_nrs_policy_unregister);
 
@@ -1396,7 +1369,7 @@ failed:
 
 	mutex_unlock(&nrs_core.nrs_mutex);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1630,7 +1603,6 @@ void ptlrpc_nrs_req_hp_move(struct ptlrpc_request *req)
 	struct ptlrpc_nrs_request	*nrq = &req->rq_nrq;
 	struct ptlrpc_nrs_resource	*res1[NRS_RES_MAX];
 	struct ptlrpc_nrs_resource	*res2[NRS_RES_MAX];
-	ENTRY;
 
 	/**
 	 * Obtain the high-priority NRS head resources.
@@ -1660,7 +1632,6 @@ out:
 	 * returned false.
 	 */
 	nrs_resource_put_safe(res1);
-	EXIT;
 }
 
 /**
@@ -1696,7 +1667,6 @@ int ptlrpc_nrs_policy_control(const struct ptlrpc_service *svc,
 	struct ptlrpc_service_part     *svcpt;
 	int				i;
 	int				rc = 0;
-	ENTRY;
 
 	LASSERT(opc != PTLRPC_NRS_CTL_INVALID);
 
@@ -1728,7 +1698,7 @@ int ptlrpc_nrs_policy_control(const struct ptlrpc_service *svc,
 		}
 	}
 out:
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1745,7 +1715,6 @@ extern struct ptlrpc_nrs_pol_conf nrs_conf_fifo;
 int ptlrpc_nrs_init(void)
 {
 	int	rc;
-	ENTRY;
 
 	mutex_init(&nrs_core.nrs_mutex);
 	INIT_LIST_HEAD(&nrs_core.nrs_policies);
@@ -1755,7 +1724,7 @@ int ptlrpc_nrs_init(void)
 		GOTO(fail, rc);
 
 
-	RETURN(rc);
+	return rc;
 fail:
 	/**
 	 * Since no PTLRPC services have been started at this point, all we need
@@ -1763,7 +1732,7 @@ fail:
 	 */
 	ptlrpc_nrs_fini();
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
index 1437636..cd2611a3 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
@@ -115,7 +115,7 @@ int lustre_msg_check_version(struct lustre_msg *msg, __u32 version)
 EXPORT_SYMBOL(lustre_msg_check_version);
 
 /* early reply size */
-int lustre_msg_early_size()
+int lustre_msg_early_size(void)
 {
 	static int size = 0;
 	if (!size) {
@@ -329,7 +329,6 @@ int lustre_pack_reply_v2(struct ptlrpc_request *req, int count,
 {
 	struct ptlrpc_reply_state *rs;
 	int			msg_len, rc;
-	ENTRY;
 
 	LASSERT(req->rq_reply_state == NULL);
 
@@ -342,7 +341,7 @@ int lustre_pack_reply_v2(struct ptlrpc_request *req, int count,
 	msg_len = lustre_msg_size_v2(count, lens);
 	rc = sptlrpc_svc_alloc_rs(req, msg_len);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rs = req->rq_reply_state;
 	atomic_set(&rs->rs_refcount, 1);    /* 1 ref for rq_reply_state */
@@ -363,7 +362,7 @@ int lustre_pack_reply_v2(struct ptlrpc_request *req, int count,
 
 	PTLRPC_RS_DEBUG_LRU_ADD(rs);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(lustre_pack_reply_v2);
 
@@ -574,7 +573,6 @@ static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len)
 int __lustre_unpack_msg(struct lustre_msg *m, int len)
 {
 	int required_len, rc;
-	ENTRY;
 
 	/* We can provide a slightly better error log, if we check the
 	 * message magic and version first.  In the future, struct
@@ -588,12 +586,12 @@ int __lustre_unpack_msg(struct lustre_msg *m, int len)
 		/* can't even look inside the message */
 		CERROR("message length %d too small for magic/version check\n",
 		       len);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	rc = lustre_unpack_msg_v2(m, len);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(__lustre_unpack_msg);
 
@@ -642,6 +640,9 @@ static inline int lustre_unpack_ptlrpc_body_v2(struct ptlrpc_request *req,
 		 return -EINVAL;
 	}
 
+	if (!inout)
+		pb->pb_status = ptlrpc_status_ntoh(pb->pb_status);
+
 	return 0;
 }
 
@@ -1613,11 +1614,10 @@ int do_set_info_async(struct obd_import *imp,
 	struct ptlrpc_request *req;
 	char		  *tmp;
 	int		    rc;
-	ENTRY;
 
 	req = ptlrpc_request_alloc(imp, &RQF_OBD_SET_INFO);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req_capsule_set_size(&req->rq_pill, &RMF_SETINFO_KEY,
 			     RCL_CLIENT, keylen);
@@ -1626,7 +1626,7 @@ int do_set_info_async(struct obd_import *imp,
 	rc = ptlrpc_request_pack(req, version, opcode);
 	if (rc) {
 		ptlrpc_request_free(req);
-		RETURN(rc);
+		return rc;
 	}
 
 	tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY);
@@ -1644,7 +1644,7 @@ int do_set_info_async(struct obd_import *imp,
 		ptlrpc_req_finished(req);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(do_set_info_async);
 
@@ -2163,7 +2163,6 @@ static void lustre_swab_lmm_oi(struct ost_id *oi)
 
 static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum)
 {
-	ENTRY;
 	__swab32s(&lum->lmm_magic);
 	__swab32s(&lum->lmm_pattern);
 	lustre_swab_lmm_oi(&lum->lmm_oi);
@@ -2171,31 +2170,25 @@ static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum)
 	__swab16s(&lum->lmm_stripe_count);
 	__swab16s(&lum->lmm_stripe_offset);
 	print_lum(lum);
-	EXIT;
 }
 
 void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum)
 {
-	ENTRY;
 	CDEBUG(D_IOCTL, "swabbing lov_user_md v1\n");
 	lustre_swab_lov_user_md_common(lum);
-	EXIT;
 }
 EXPORT_SYMBOL(lustre_swab_lov_user_md_v1);
 
 void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum)
 {
-	ENTRY;
 	CDEBUG(D_IOCTL, "swabbing lov_user_md v3\n");
 	lustre_swab_lov_user_md_common((struct lov_user_md_v1 *)lum);
 	/* lmm_pool_name nothing to do with char */
-	EXIT;
 }
 EXPORT_SYMBOL(lustre_swab_lov_user_md_v3);
 
 void lustre_swab_lov_mds_md(struct lov_mds_md *lmm)
 {
-	ENTRY;
 	CDEBUG(D_IOCTL, "swabbing lov_mds_md\n");
 	__swab32s(&lmm->lmm_magic);
 	__swab32s(&lmm->lmm_pattern);
@@ -2203,7 +2196,6 @@ void lustre_swab_lov_mds_md(struct lov_mds_md *lmm)
 	__swab32s(&lmm->lmm_stripe_size);
 	__swab16s(&lmm->lmm_stripe_count);
 	__swab16s(&lmm->lmm_layout_gen);
-	EXIT;
 }
 EXPORT_SYMBOL(lustre_swab_lov_mds_md);
 
@@ -2211,13 +2203,12 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
 				     int stripe_count)
 {
 	int i;
-	ENTRY;
+
 	for (i = 0; i < stripe_count; i++) {
 		lustre_swab_ost_id(&(lod[i].l_ost_oi));
 		__swab32s(&(lod[i].l_ost_gen));
 		__swab32s(&(lod[i].l_ost_idx));
 	}
-	EXIT;
 }
 EXPORT_SYMBOL(lustre_swab_lov_user_md_objects);
 
@@ -2459,6 +2450,7 @@ void _debug_req(struct ptlrpc_request *req,
 			   rep_ok ? lustre_msg_get_flags(req->rq_repmsg) : -1,
 			   req->rq_status,
 			   rep_ok ? lustre_msg_get_status(req->rq_repmsg) : -1);
+	va_end(args);
 }
 EXPORT_SYMBOL(_debug_req);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c
index ef5269a..227a0ae 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c
@@ -51,7 +51,7 @@ struct mutex pinger_mutex;
 static LIST_HEAD(pinger_imports);
 static struct list_head timeout_list = LIST_HEAD_INIT(timeout_list);
 
-int ptlrpc_pinger_suppress_pings()
+int ptlrpc_pinger_suppress_pings(void)
 {
 	return suppress_pings;
 }
@@ -75,11 +75,10 @@ int ptlrpc_obd_ping(struct obd_device *obd)
 {
 	int rc;
 	struct ptlrpc_request *req;
-	ENTRY;
 
 	req = ptlrpc_prep_ping(obd->u.cli.cl_import);
 	if (req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req->rq_send_state = LUSTRE_IMP_FULL;
 
@@ -87,28 +86,27 @@ int ptlrpc_obd_ping(struct obd_device *obd)
 
 	ptlrpc_req_finished(req);
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_obd_ping);
 
 int ptlrpc_ping(struct obd_import *imp)
 {
 	struct ptlrpc_request *req;
-	ENTRY;
 
 	req = ptlrpc_prep_ping(imp);
 	if (req == NULL) {
 		CERROR("OOM trying to ping %s->%s\n",
 		       imp->imp_obd->obd_uuid.uuid,
 		       obd2cli_tgt(imp->imp_obd));
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	DEBUG_REQ(D_INFO, req, "pinging %s->%s",
 		  imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd));
 	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
 
-	RETURN(0);
+	return 0;
 }
 
 void ptlrpc_update_next_ping(struct obd_import *imp, int soon)
@@ -297,7 +295,6 @@ static void ptlrpc_pinger_process_import(struct obd_import *imp,
 static int ptlrpc_pinger_main(void *arg)
 {
 	struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg;
-	ENTRY;
 
 	/* Record that the thread is running */
 	thread_set_flags(thread, SVC_RUNNING);
@@ -353,7 +350,6 @@ static int ptlrpc_pinger_main(void *arg)
 				     thread_is_event(thread),
 				     &lwi);
 			if (thread_test_and_clear_flags(thread, SVC_STOPPING)) {
-				EXIT;
 				break;
 			} else {
 				/* woken after adding import to reset timer */
@@ -369,37 +365,32 @@ static int ptlrpc_pinger_main(void *arg)
 	return 0;
 }
 
-static struct ptlrpc_thread *pinger_thread = NULL;
+static struct ptlrpc_thread pinger_thread;
 
 int ptlrpc_start_pinger(void)
 {
 	struct l_wait_info lwi = { 0 };
 	int rc;
-	ENTRY;
 
-	if (pinger_thread != NULL)
-		RETURN(-EALREADY);
+	if (!thread_is_init(&pinger_thread) &&
+	    !thread_is_stopped(&pinger_thread))
+		return -EALREADY;
 
-	OBD_ALLOC_PTR(pinger_thread);
-	if (pinger_thread == NULL)
-		RETURN(-ENOMEM);
-	init_waitqueue_head(&pinger_thread->t_ctl_waitq);
+	init_waitqueue_head(&pinger_thread.t_ctl_waitq);
 	init_waitqueue_head(&suspend_timeouts_waitq);
 
-	strcpy(pinger_thread->t_name, "ll_ping");
+	strcpy(pinger_thread.t_name, "ll_ping");
 
 	/* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
 	 * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
 	rc = PTR_ERR(kthread_run(ptlrpc_pinger_main,
-				 pinger_thread, pinger_thread->t_name));
+				 &pinger_thread, pinger_thread.t_name));
 	if (IS_ERR_VALUE(rc)) {
 		CERROR("cannot start thread: %d\n", rc);
-		OBD_FREE(pinger_thread, sizeof(*pinger_thread));
-		pinger_thread = NULL;
-		RETURN(rc);
+		return rc;
 	}
-	l_wait_event(pinger_thread->t_ctl_waitq,
-		     thread_is_running(pinger_thread), &lwi);
+	l_wait_event(pinger_thread.t_ctl_waitq,
+		     thread_is_running(&pinger_thread), &lwi);
 
 	if (suppress_pings)
 		CWARN("Pings will be suppressed at the request of the "
@@ -408,7 +399,7 @@ int ptlrpc_start_pinger(void)
 		      "(Search for the \"suppress_pings\" kernel module "
 		      "parameter.)\n");
 
-	RETURN(0);
+	return 0;
 }
 
 int ptlrpc_pinger_remove_timeouts(void);
@@ -417,23 +408,19 @@ int ptlrpc_stop_pinger(void)
 {
 	struct l_wait_info lwi = { 0 };
 	int rc = 0;
-	ENTRY;
 
-	if (pinger_thread == NULL)
-		RETURN(-EALREADY);
+	if (!thread_is_init(&pinger_thread) &&
+	    !thread_is_stopped(&pinger_thread))
+		return -EALREADY;
 
 	ptlrpc_pinger_remove_timeouts();
-	mutex_lock(&pinger_mutex);
-	thread_set_flags(pinger_thread, SVC_STOPPING);
-	wake_up(&pinger_thread->t_ctl_waitq);
-	mutex_unlock(&pinger_mutex);
+	thread_set_flags(&pinger_thread, SVC_STOPPING);
+	wake_up(&pinger_thread.t_ctl_waitq);
 
-	l_wait_event(pinger_thread->t_ctl_waitq,
-		     thread_is_stopped(pinger_thread), &lwi);
+	l_wait_event(pinger_thread.t_ctl_waitq,
+		     thread_is_stopped(&pinger_thread), &lwi);
 
-	OBD_FREE_PTR(pinger_thread);
-	pinger_thread = NULL;
-	RETURN(rc);
+	return rc;
 }
 
 void ptlrpc_pinger_sending_on_import(struct obd_import *imp)
@@ -459,9 +446,8 @@ void ptlrpc_pinger_commit_expected(struct obd_import *imp)
 
 int ptlrpc_pinger_add_import(struct obd_import *imp)
 {
-	ENTRY;
 	if (!list_empty(&imp->imp_pinger_chain))
-		RETURN(-EALREADY);
+		return -EALREADY;
 
 	mutex_lock(&pinger_mutex);
 	CDEBUG(D_HA, "adding pingable import %s->%s\n",
@@ -476,15 +462,14 @@ int ptlrpc_pinger_add_import(struct obd_import *imp)
 	ptlrpc_pinger_wake_up();
 	mutex_unlock(&pinger_mutex);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_pinger_add_import);
 
 int ptlrpc_pinger_del_import(struct obd_import *imp)
 {
-	ENTRY;
 	if (list_empty(&imp->imp_pinger_chain))
-		RETURN(-ENOENT);
+		return -ENOENT;
 
 	mutex_lock(&pinger_mutex);
 	list_del_init(&imp->imp_pinger_chain);
@@ -494,7 +479,7 @@ int ptlrpc_pinger_del_import(struct obd_import *imp)
 	imp->imp_obd->obd_no_recov = 1;
 	class_import_put(imp);
 	mutex_unlock(&pinger_mutex);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_pinger_del_import);
 
@@ -615,10 +600,10 @@ int ptlrpc_pinger_remove_timeouts(void)
 	return 0;
 }
 
-void ptlrpc_pinger_wake_up()
+void ptlrpc_pinger_wake_up(void)
 {
-	thread_add_flags(pinger_thread, SVC_EVENT);
-	wake_up(&pinger_thread->t_ctl_waitq);
+	thread_add_flags(&pinger_thread, SVC_EVENT);
+	wake_up(&pinger_thread.t_ctl_waitq);
 }
 
 /* Ping evictor thread */
@@ -659,7 +644,6 @@ static int ping_evictor_main(void *arg)
 	struct obd_export *exp;
 	struct l_wait_info lwi = { 0 };
 	time_t expire_time;
-	ENTRY;
 
 	unshare_fs_struct();
 
@@ -731,12 +715,12 @@ static int ping_evictor_main(void *arg)
 	}
 	CDEBUG(D_HA, "Exiting Ping Evictor\n");
 
-	RETURN(0);
+	return 0;
 }
 
 void ping_evictor_start(void)
 {
-	task_t *task;
+	struct task_struct *task;
 
 	if (++pet_refcount > 1)
 		return;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
index f6ea80f..419e634 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
@@ -54,7 +54,6 @@ extern struct mutex ptlrpcd_mutex;
 __init int ptlrpc_init(void)
 {
 	int rc, cleanup_phase = 0;
-	ENTRY;
 
 	lustre_assert_wire_constants();
 #if RS_DEBUG
@@ -67,11 +66,11 @@ __init int ptlrpc_init(void)
 
 	rc = req_layout_init();
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	rc = ptlrpc_hr_init();
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	cleanup_phase = 1;
 
@@ -110,7 +109,7 @@ __init int ptlrpc_init(void)
 	rc = tgt_mod_init();
 	if (rc)
 		GOTO(cleanup, rc);
-	RETURN(0);
+	return 0;
 
 cleanup:
 	switch(cleanup_phase) {
@@ -150,5 +149,7 @@ static void __exit ptlrpc_exit(void)
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre Request Processor and Lock Management");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
 
-cfs_module(ptlrpc, "1.0.0", ptlrpc_init, ptlrpc_exit);
+module_init(ptlrpc_init);
+module_exit(ptlrpc_exit);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
index 5a66a1b..fbdeff6 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
@@ -268,7 +268,6 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc)
 	struct ptlrpc_request_set *set = pc->pc_set;
 	int rc = 0;
 	int rc2;
-	ENTRY;
 
 	if (atomic_read(&set->set_new_count)) {
 		spin_lock(&set->set_new_req_lock);
@@ -302,7 +301,7 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc)
 		 * new modules are loaded, i.e., early during boot up.
 		 */
 		CERROR("Failure to refill session: %d\n", rc2);
-		RETURN(rc);
+		return rc;
 	}
 
 	if (atomic_read(&set->set_remaining))
@@ -368,7 +367,7 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc)
 		}
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -383,7 +382,6 @@ static int ptlrpcd(void *arg)
 	struct ptlrpc_request_set *set = pc->pc_set;
 	struct lu_env env = { .le_ses = NULL };
 	int rc, exit = 0;
-	ENTRY;
 
 	unshare_fs_struct();
 #if defined(CONFIG_SMP)
@@ -410,7 +408,7 @@ static int ptlrpcd(void *arg)
 	complete(&pc->pc_starting);
 
 	if (rc != 0)
-		RETURN(rc);
+		return rc;
 
 	/*
 	 * This mainloop strongly resembles ptlrpc_set_wait() except that our
@@ -501,7 +499,6 @@ static int ptlrpcd_bind(int index, int max)
 #if defined(CONFIG_NUMA)
 	cpumask_t mask;
 #endif
-	ENTRY;
 
 	LASSERT(index <= max - 1);
 	pc = &ptlrpcds->pd_threads[index];
@@ -596,7 +593,7 @@ static int ptlrpcd_bind(int index, int max)
 		}
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -604,7 +601,6 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc)
 {
 	int rc;
 	int env = 0;
-	ENTRY;
 
 	/*
 	 * Do not allow start second thread for one pc.
@@ -612,7 +608,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc)
 	if (test_and_set_bit(LIOD_START, &pc->pc_flags)) {
 		CWARN("Starting second thread (%s) for same pc %p\n",
 		      name, pc);
-		RETURN(0);
+		return 0;
 	}
 
 	pc->pc_index = index;
@@ -634,7 +630,8 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc)
 
 	env = 1;
 	{
-		task_t *task;
+		struct task_struct *task;
+
 		if (index >= 0) {
 			rc = ptlrpcd_bind(index, max);
 			if (rc < 0)
@@ -663,31 +660,25 @@ out:
 		clear_bit(LIOD_BIND, &pc->pc_flags);
 		clear_bit(LIOD_START, &pc->pc_flags);
 	}
-	RETURN(rc);
+	return rc;
 }
 
 void ptlrpcd_stop(struct ptlrpcd_ctl *pc, int force)
 {
-	ENTRY;
-
 	if (!test_bit(LIOD_START, &pc->pc_flags)) {
 		CWARN("Thread for pc %p was not started\n", pc);
-		goto out;
+		return;
 	}
 
 	set_bit(LIOD_STOP, &pc->pc_flags);
 	if (force)
 		set_bit(LIOD_FORCE, &pc->pc_flags);
 	wake_up(&pc->pc_set->set_waitq);
-
-out:
-	EXIT;
 }
 
 void ptlrpcd_free(struct ptlrpcd_ctl *pc)
 {
 	struct ptlrpc_request_set *set = pc->pc_set;
-	ENTRY;
 
 	if (!test_bit(LIOD_START, &pc->pc_flags)) {
 		CWARN("Thread for pc %p was not started\n", pc);
@@ -716,13 +707,11 @@ out:
 		pc->pc_partners = NULL;
 	}
 	pc->pc_npartners = 0;
-	EXIT;
 }
 
 static void ptlrpcd_fini(void)
 {
 	int i;
-	ENTRY;
 
 	if (ptlrpcds != NULL) {
 		for (i = 0; i < ptlrpcds->pd_nthreads; i++)
@@ -734,8 +723,6 @@ static void ptlrpcd_fini(void)
 		OBD_FREE(ptlrpcds, ptlrpcds->pd_size);
 		ptlrpcds = NULL;
 	}
-
-	EXIT;
 }
 
 static int ptlrpcd_init(void)
@@ -743,7 +730,6 @@ static int ptlrpcd_init(void)
 	int nthreads = num_online_cpus();
 	char name[16];
 	int size, i = -1, j, rc = 0;
-	ENTRY;
 
 	if (max_ptlrpcds > 0 && max_ptlrpcds < nthreads)
 		nthreads = max_ptlrpcds;
@@ -800,19 +786,18 @@ out:
 		ptlrpcds = NULL;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 int ptlrpcd_addref(void)
 {
 	int rc = 0;
-	ENTRY;
 
 	mutex_lock(&ptlrpcd_mutex);
 	if (++ptlrpcd_users == 1)
 		rc = ptlrpcd_init();
 	mutex_unlock(&ptlrpcd_mutex);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpcd_addref);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c
index 2960889..84c39e0 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/recover.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c
@@ -60,12 +60,8 @@
  */
 void ptlrpc_initiate_recovery(struct obd_import *imp)
 {
-	ENTRY;
-
 	CDEBUG(D_HA, "%s: starting recovery\n", obd2cli_tgt(imp->imp_obd));
 	ptlrpc_connect_import(imp);
-
-	EXIT;
 }
 
 /**
@@ -78,7 +74,6 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
 	struct list_head *tmp, *pos;
 	struct ptlrpc_request *req = NULL;
 	__u64 last_transno;
-	ENTRY;
 
 	*inflight = 0;
 
@@ -137,11 +132,11 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
 		if (rc) {
 			CERROR("recovery replay error %d for req "
 			       LPU64"\n", rc, req->rq_xid);
-			RETURN(rc);
+			return rc;
 		}
 		*inflight = 1;
 	}
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -152,8 +147,6 @@ int ptlrpc_resend(struct obd_import *imp)
 {
 	struct ptlrpc_request *req, *next;
 
-	ENTRY;
-
 	/* As long as we're in recovery, nothing should be added to the sending
 	 * list, so we don't need to hold the lock during this iteration and
 	 * resend process.
@@ -163,7 +156,7 @@ int ptlrpc_resend(struct obd_import *imp)
 	spin_lock(&imp->imp_lock);
 	if (imp->imp_state != LUSTRE_IMP_RECOVER) {
 		spin_unlock(&imp->imp_lock);
-		RETURN(-1);
+		return -1;
 	}
 
 	list_for_each_entry_safe(req, next, &imp->imp_sending_list,
@@ -176,7 +169,7 @@ int ptlrpc_resend(struct obd_import *imp)
 	}
 	spin_unlock(&imp->imp_lock);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_resend);
 
@@ -203,7 +196,6 @@ EXPORT_SYMBOL(ptlrpc_wake_delayed);
 void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
 {
 	struct obd_import *imp = failed_req->rq_import;
-	ENTRY;
 
 	CDEBUG(D_HA, "import %s of %s@%s abruptly disconnected: reconnecting\n",
 	       imp->imp_obd->obd_name, obd2cli_tgt(imp->imp_obd),
@@ -230,8 +222,6 @@ void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
 	if (!failed_req->rq_no_resend)
 		failed_req->rq_resend = 1;
 	spin_unlock(&failed_req->rq_lock);
-
-	EXIT;
 }
 
 /**
@@ -246,7 +236,6 @@ int ptlrpc_set_import_active(struct obd_import *imp, int active)
 	struct obd_device *obd = imp->imp_obd;
 	int rc = 0;
 
-	ENTRY;
 	LASSERT(obd);
 
 	/* When deactivating, mark import invalid, and abort in-flight
@@ -279,7 +268,7 @@ int ptlrpc_set_import_active(struct obd_import *imp, int active)
 		rc = ptlrpc_recover_import(imp, NULL, 0);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_set_import_active);
 
@@ -287,7 +276,6 @@ EXPORT_SYMBOL(ptlrpc_set_import_active);
 int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid, int async)
 {
 	int rc = 0;
-	ENTRY;
 
 	spin_lock(&imp->imp_lock);
 	if (imp->imp_state == LUSTRE_IMP_NEW || imp->imp_deactive ||
@@ -337,7 +325,6 @@ int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid, int async)
 		CDEBUG(D_HA, "%s: recovery finished\n",
 		       obd2cli_tgt(imp->imp_obd));
 	}
-	EXIT;
 
 out:
 	return rc;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c
index 36e8bed..962b31d 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c
@@ -269,8 +269,8 @@ struct ptlrpc_cli_ctx *get_my_ctx(struct ptlrpc_sec *sec)
 			remove_dead = 0;
 		}
 	} else {
-		vcred.vc_uid = current_uid();
-		vcred.vc_gid = current_gid();
+		vcred.vc_uid = from_kuid(&init_user_ns, current_uid());
+		vcred.vc_gid = from_kgid(&init_user_ns, current_gid());
 	}
 
 	return sec->ps_policy->sp_cops->lookup_ctx(sec, &vcred,
@@ -396,14 +396,13 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
 	struct obd_import *imp = req->rq_import;
 	struct ptlrpc_sec *sec;
 	int		rc;
-	ENTRY;
 
 	LASSERT(!req->rq_cli_ctx);
 	LASSERT(imp);
 
 	rc = import_sec_validate_get(imp, &sec);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	req->rq_cli_ctx = get_my_ctx(sec);
 
@@ -411,10 +410,10 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
 
 	if (!req->rq_cli_ctx) {
 		CERROR("req %p: fail to get context\n", req);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -428,8 +427,6 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
  */
 void sptlrpc_req_put_ctx(struct ptlrpc_request *req, int sync)
 {
-	ENTRY;
-
 	LASSERT(req);
 	LASSERT(req->rq_cli_ctx);
 
@@ -444,7 +441,6 @@ void sptlrpc_req_put_ctx(struct ptlrpc_request *req, int sync)
 
 	sptlrpc_cli_ctx_put(req->rq_cli_ctx, sync);
 	req->rq_cli_ctx = NULL;
-	EXIT;
 }
 
 static
@@ -520,7 +516,6 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
 	struct ptlrpc_cli_ctx *oldctx = req->rq_cli_ctx;
 	struct ptlrpc_cli_ctx *newctx;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(oldctx);
 
@@ -533,7 +528,7 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
 
 		/* restore old ctx */
 		req->rq_cli_ctx = oldctx;
-		RETURN(rc);
+		return rc;
 	}
 
 	newctx = req->rq_cli_ctx;
@@ -560,14 +555,14 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
 			/* restore old ctx */
 			sptlrpc_req_put_ctx(req, 0);
 			req->rq_cli_ctx = oldctx;
-			RETURN(rc);
+			return rc;
 		}
 
 		LASSERT(req->rq_cli_ctx == newctx);
 	}
 
 	sptlrpc_cli_ctx_put(oldctx, 1);
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(sptlrpc_req_replace_dead_ctx);
 
@@ -639,12 +634,11 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
 	struct ptlrpc_sec      *sec;
 	struct l_wait_info      lwi;
 	int		     rc;
-	ENTRY;
 
 	LASSERT(ctx);
 
 	if (req->rq_ctx_init || req->rq_ctx_fini)
-		RETURN(0);
+		return 0;
 
 	/*
 	 * during the process a request's context might change type even
@@ -654,7 +648,7 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
 again:
 	rc = import_sec_validate_get(req->rq_import, &sec);
 	if (rc)
-		RETURN(rc);
+		return rc;
 
 	if (sec->ps_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
 		CDEBUG(D_SEC, "req %p: flavor has changed %x -> %x\n",
@@ -666,7 +660,7 @@ again:
 	sptlrpc_sec_put(sec);
 
 	if (cli_ctx_is_eternal(ctx))
-		RETURN(0);
+		return 0;
 
 	if (unlikely(test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags))) {
 		LASSERT(ctx->cc_ops->refresh);
@@ -677,7 +671,7 @@ again:
 	LASSERT(ctx->cc_ops->validate);
 	if (ctx->cc_ops->validate(ctx) == 0) {
 		req_off_ctx_list(req, ctx);
-		RETURN(0);
+		return 0;
 	}
 
 	if (unlikely(test_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags))) {
@@ -685,7 +679,7 @@ again:
 		req->rq_err = 1;
 		spin_unlock(&req->rq_lock);
 		req_off_ctx_list(req, ctx);
-		RETURN(-EPERM);
+		return -EPERM;
 	}
 
 	/*
@@ -719,7 +713,7 @@ again:
 	    unlikely(req->rq_reqmsg) &&
 	    lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT) {
 		req_off_ctx_list(req, ctx);
-		RETURN(0);
+		return 0;
 	}
 
 	if (unlikely(test_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags))) {
@@ -731,7 +725,7 @@ again:
 			spin_lock(&req->rq_lock);
 			req->rq_err = 1;
 			spin_unlock(&req->rq_lock);
-			RETURN(-EINTR);
+			return -EINTR;
 		}
 
 		rc = sptlrpc_req_replace_dead_ctx(req);
@@ -742,7 +736,7 @@ again:
 			spin_lock(&req->rq_lock);
 			req->rq_err = 1;
 			spin_unlock(&req->rq_lock);
-			RETURN(rc);
+			return rc;
 		}
 
 		ctx = req->rq_cli_ctx;
@@ -759,7 +753,7 @@ again:
 	spin_unlock(&ctx->cc_lock);
 
 	if (timeout < 0)
-		RETURN(-EWOULDBLOCK);
+		return -EWOULDBLOCK;
 
 	/* Clear any flags that may be present from previous sends */
 	LASSERT(req->rq_receiving_reply == 0);
@@ -789,7 +783,7 @@ again:
 		req_off_ctx_list(req, ctx);
 
 		LASSERT(rc != 0);
-		RETURN(rc);
+		return rc;
 	}
 
 	goto again;
@@ -889,7 +883,6 @@ int sptlrpc_import_check_ctx(struct obd_import *imp)
 	struct ptlrpc_cli_ctx *ctx;
 	struct ptlrpc_request *req = NULL;
 	int rc;
-	ENTRY;
 
 	might_sleep();
 
@@ -898,22 +891,22 @@ int sptlrpc_import_check_ctx(struct obd_import *imp)
 	sptlrpc_sec_put(sec);
 
 	if (!ctx)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	if (cli_ctx_is_eternal(ctx) ||
 	    ctx->cc_ops->validate(ctx) == 0) {
 		sptlrpc_cli_ctx_put(ctx, 1);
-		RETURN(0);
+		return 0;
 	}
 
 	if (cli_ctx_is_error(ctx)) {
 		sptlrpc_cli_ctx_put(ctx, 1);
-		RETURN(-EACCES);
+		return -EACCES;
 	}
 
 	OBD_ALLOC_PTR(req);
 	if (!req)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock_init(&req->rq_lock);
 	atomic_set(&req->rq_refcount, 10000);
@@ -929,7 +922,7 @@ int sptlrpc_import_check_ctx(struct obd_import *imp)
 	sptlrpc_cli_ctx_put(req->rq_cli_ctx, 1);
 	OBD_FREE_PTR(req);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -941,7 +934,6 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
 {
 	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
 	int rc = 0;
-	ENTRY;
 
 	LASSERT(ctx);
 	LASSERT(ctx->cc_sec);
@@ -953,7 +945,7 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
 	if (req->rq_bulk) {
 		rc = sptlrpc_cli_wrap_bulk(req, req->rq_bulk);
 		if (rc)
-			RETURN(rc);
+			return rc;
 	}
 
 	switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
@@ -977,14 +969,13 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
 		LASSERT(req->rq_reqdata_len <= req->rq_reqbuf_len);
 	}
 
-	RETURN(rc);
+	return rc;
 }
 
 static int do_cli_unwrap_reply(struct ptlrpc_request *req)
 {
 	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(ctx);
 	LASSERT(ctx->cc_sec);
@@ -1002,13 +993,13 @@ static int do_cli_unwrap_reply(struct ptlrpc_request *req)
 		break;
 	default:
 		CERROR("failed unpack reply: x"LPU64"\n", req->rq_xid);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (req->rq_repdata_len < sizeof(struct lustre_msg)) {
 		CERROR("replied data length %d too small\n",
 		       req->rq_repdata_len);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (SPTLRPC_FLVR_POLICY(req->rq_repdata->lm_secflvr) !=
@@ -1016,7 +1007,7 @@ static int do_cli_unwrap_reply(struct ptlrpc_request *req)
 		CERROR("reply policy %u doesn't match request policy %u\n",
 		       SPTLRPC_FLVR_POLICY(req->rq_repdata->lm_secflvr),
 		       SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc));
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
@@ -1038,7 +1029,7 @@ static int do_cli_unwrap_reply(struct ptlrpc_request *req)
 	if (SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) != SPTLRPC_POLICY_NULL &&
 	    !req->rq_ctx_init)
 		req->rq_rep_swab_mask = 0;
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1096,11 +1087,10 @@ int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req,
 	char		   *early_buf;
 	int		     early_bufsz, early_size;
 	int		     rc;
-	ENTRY;
 
 	OBD_ALLOC_PTR(early_req);
 	if (early_req == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	early_size = req->rq_nob_received;
 	early_bufsz = size_roundup_power2(early_size);
@@ -1163,7 +1153,7 @@ int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req,
 
 	LASSERT(early_req->rq_repmsg);
 	*req_ret = early_req;
-	RETURN(0);
+	return 0;
 
 err_ctx:
 	sptlrpc_cli_ctx_put(early_req->rq_cli_ctx, 1);
@@ -1171,7 +1161,7 @@ err_buf:
 	OBD_FREE_LARGE(early_buf, early_bufsz);
 err_req:
 	OBD_FREE_PTR(early_req);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -1285,7 +1275,6 @@ struct ptlrpc_sec * sptlrpc_sec_create(struct obd_import *imp,
 	struct ptlrpc_sec_policy *policy;
 	struct ptlrpc_sec	*sec;
 	char		      str[32];
-	ENTRY;
 
 	if (svc_ctx) {
 		LASSERT(imp->imp_dlm_fake == 1);
@@ -1308,7 +1297,7 @@ struct ptlrpc_sec * sptlrpc_sec_create(struct obd_import *imp,
 		policy = sptlrpc_wireflavor2policy(sf->sf_rpc);
 		if (!policy) {
 			CERROR("invalid flavor 0x%x\n", sf->sf_rpc);
-			RETURN(NULL);
+			return NULL;
 		}
 	}
 
@@ -1324,7 +1313,7 @@ struct ptlrpc_sec * sptlrpc_sec_create(struct obd_import *imp,
 		sptlrpc_policy_put(policy);
 	}
 
-	RETURN(sec);
+	return sec;
 }
 
 struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp)
@@ -1406,12 +1395,11 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp,
 	enum lustre_sec_part	sp;
 	char			str[24];
 	int			 rc = 0;
-	ENTRY;
 
 	might_sleep();
 
 	if (imp == NULL)
-		RETURN(0);
+		return 0;
 
 	conn = imp->imp_connection;
 
@@ -1485,7 +1473,7 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp,
 	mutex_unlock(&imp->imp_sec_mutex);
 out:
 	sptlrpc_sec_put(sec);
-	RETURN(rc);
+	return rc;
 }
 
 void sptlrpc_import_sec_put(struct obd_import *imp)
@@ -1523,7 +1511,8 @@ void sptlrpc_import_flush_root_ctx(struct obd_import *imp)
 
 void sptlrpc_import_flush_my_ctx(struct obd_import *imp)
 {
-	import_flush_ctx_common(imp, current_uid(), 1, 1);
+	import_flush_ctx_common(imp, from_kuid(&init_user_ns, current_uid()),
+				1, 1);
 }
 EXPORT_SYMBOL(sptlrpc_import_flush_my_ctx);
 
@@ -1668,17 +1657,16 @@ int sptlrpc_cli_alloc_repbuf(struct ptlrpc_request *req, int msgsize)
 {
 	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
 	struct ptlrpc_sec_policy *policy;
-	ENTRY;
 
 	LASSERT(ctx);
 	LASSERT(ctx->cc_sec);
 	LASSERT(ctx->cc_sec->ps_policy);
 
 	if (req->rq_repbuf)
-		RETURN(0);
+		return 0;
 
 	policy = ctx->cc_sec->ps_policy;
-	RETURN(policy->sp_cops->alloc_repbuf(ctx->cc_sec, req, msgsize));
+	return policy->sp_cops->alloc_repbuf(ctx->cc_sec, req, msgsize);
 }
 
 /**
@@ -1689,7 +1677,6 @@ void sptlrpc_cli_free_repbuf(struct ptlrpc_request *req)
 {
 	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
 	struct ptlrpc_sec_policy *policy;
-	ENTRY;
 
 	LASSERT(ctx);
 	LASSERT(ctx->cc_sec);
@@ -1703,7 +1690,6 @@ void sptlrpc_cli_free_repbuf(struct ptlrpc_request *req)
 	policy = ctx->cc_sec->ps_policy;
 	policy->sp_cops->free_repbuf(ctx->cc_sec, req);
 	req->rq_repmsg = NULL;
-	EXIT;
 }
 
 int sptlrpc_cli_install_rvs_ctx(struct obd_import *imp,
@@ -2032,7 +2018,6 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
 	struct ptlrpc_sec_policy *policy;
 	struct lustre_msg	*msg = req->rq_reqbuf;
 	int		       rc;
-	ENTRY;
 
 	LASSERT(msg);
 	LASSERT(req->rq_reqmsg == NULL);
@@ -2050,18 +2035,18 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
 	default:
 		CERROR("error unpacking request from %s x"LPU64"\n",
 		       libcfs_id2str(req->rq_peer), req->rq_xid);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	req->rq_flvr.sf_rpc = WIRE_FLVR(msg->lm_secflvr);
 	req->rq_sp_from = LUSTRE_SP_ANY;
-	req->rq_auth_uid = INVALID_UID;
-	req->rq_auth_mapped_uid = INVALID_UID;
+	req->rq_auth_uid = -1;
+	req->rq_auth_mapped_uid = -1;
 
 	policy = sptlrpc_wireflavor2policy(req->rq_flvr.sf_rpc);
 	if (!policy) {
 		CERROR("unsupported rpc flavor %x\n", req->rq_flvr.sf_rpc);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	LASSERT(policy->sp_sops->accept);
@@ -2079,7 +2064,7 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
 
 	/* sanity check for the request source */
 	rc = sptlrpc_svc_check_from(req, rc);
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2092,7 +2077,6 @@ int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 	struct ptlrpc_sec_policy *policy;
 	struct ptlrpc_reply_state *rs;
 	int rc;
-	ENTRY;
 
 	LASSERT(req->rq_svc_ctx);
 	LASSERT(req->rq_svc_ctx->sc_policy);
@@ -2105,7 +2089,7 @@ int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 		/* failed alloc, try emergency pool */
 		rs = lustre_get_emerg_rs(req->rq_rqbd->rqbd_svcpt);
 		if (rs == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		req->rq_reply_state = rs;
 		rc = policy->sp_sops->alloc_rs(req, msglen);
@@ -2118,7 +2102,7 @@ int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 	LASSERT(rc != 0 ||
 		(req->rq_reply_state && req->rq_reply_state->rs_msg));
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2131,7 +2115,6 @@ int sptlrpc_svc_wrap_reply(struct ptlrpc_request *req)
 {
 	struct ptlrpc_sec_policy *policy;
 	int rc;
-	ENTRY;
 
 	LASSERT(req->rq_svc_ctx);
 	LASSERT(req->rq_svc_ctx->sc_policy);
@@ -2142,7 +2125,7 @@ int sptlrpc_svc_wrap_reply(struct ptlrpc_request *req)
 	rc = policy->sp_sops->authorize(req);
 	LASSERT(rc || req->rq_reply_state->rs_repdata_len);
 
-	RETURN(rc);
+	return rc;
 }
 
 /**
@@ -2152,7 +2135,6 @@ void sptlrpc_svc_free_rs(struct ptlrpc_reply_state *rs)
 {
 	struct ptlrpc_sec_policy *policy;
 	unsigned int prealloc;
-	ENTRY;
 
 	LASSERT(rs->rs_svc_ctx);
 	LASSERT(rs->rs_svc_ctx->sc_policy);
@@ -2165,7 +2147,6 @@ void sptlrpc_svc_free_rs(struct ptlrpc_reply_state *rs)
 
 	if (prealloc)
 		lustre_put_emerg_rs(rs);
-	EXIT;
 }
 
 void sptlrpc_svc_ctx_addref(struct ptlrpc_request *req)
@@ -2314,10 +2295,10 @@ int sptlrpc_pack_user_desc(struct lustre_msg *msg, int offset)
 
 	pud = lustre_msg_buf(msg, offset, 0);
 
-	pud->pud_uid = current_uid();
-	pud->pud_gid = current_gid();
-	pud->pud_fsuid = current_fsuid();
-	pud->pud_fsgid = current_fsgid();
+	pud->pud_uid = from_kuid(&init_user_ns, current_uid());
+	pud->pud_gid = from_kgid(&init_user_ns, current_gid());
+	pud->pud_fsuid = from_kuid(&init_user_ns, current_fsuid());
+	pud->pud_fsgid = from_kgid(&init_user_ns, current_fsgid());
 	pud->pud_cap = cfs_curproc_cap_pack();
 	pud->pud_ngroups = (msg->lm_buflens[offset] - sizeof(*pud)) / 4;
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
index bf53f1b..e90c8fb 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
@@ -121,13 +121,6 @@ static struct ptlrpc_enc_page_pool {
 } page_pools;
 
 /*
- * memory shrinker
- */
-const int pools_shrinker_seeks = DEFAULT_SEEKS;
-static struct shrinker *pools_shrinker = NULL;
-
-
-/*
  * /proc/fs/lustre/sptlrpc/encrypt_page_pools
  */
 int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v)
@@ -156,7 +149,7 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v)
 		      "max waitqueue depth:     %u\n"
 		      "max wait time:	   "CFS_TIME_T"/%u\n"
 		      ,
-		      num_physpages,
+		      totalram_pages,
 		      PAGES_PER_POOL,
 		      page_pools.epp_max_pages,
 		      page_pools.epp_max_pools,
@@ -226,30 +219,46 @@ static void enc_pools_release_free_pages(long npages)
 }
 
 /*
- * could be called frequently for query (@nr_to_scan == 0).
  * we try to keep at least PTLRPC_MAX_BRW_PAGES pages in the pool.
  */
-static int enc_pools_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
+static unsigned long enc_pools_shrink_count(struct shrinker *s,
+					    struct shrink_control *sc)
 {
-	if (unlikely(shrink_param(sc, nr_to_scan) != 0)) {
+	/*
+	 * if no pool access for a long time, we consider it's fully idle.
+	 * a little race here is fine.
+	 */
+	if (unlikely(cfs_time_current_sec() - page_pools.epp_last_access >
+		     CACHE_QUIESCENT_PERIOD)) {
 		spin_lock(&page_pools.epp_lock);
-		shrink_param(sc, nr_to_scan) = min_t(unsigned long,
-						   shrink_param(sc, nr_to_scan),
-						   page_pools.epp_free_pages -
-						   PTLRPC_MAX_BRW_PAGES);
-		if (shrink_param(sc, nr_to_scan) > 0) {
-			enc_pools_release_free_pages(shrink_param(sc,
-								  nr_to_scan));
-			CDEBUG(D_SEC, "released %ld pages, %ld left\n",
-			       (long)shrink_param(sc, nr_to_scan),
-			       page_pools.epp_free_pages);
-
-			page_pools.epp_st_shrinks++;
-			page_pools.epp_last_shrink = cfs_time_current_sec();
-		}
+		page_pools.epp_idle_idx = IDLE_IDX_MAX;
 		spin_unlock(&page_pools.epp_lock);
 	}
 
+	LASSERT(page_pools.epp_idle_idx <= IDLE_IDX_MAX);
+	return max((int)page_pools.epp_free_pages - PTLRPC_MAX_BRW_PAGES, 0) *
+		(IDLE_IDX_MAX - page_pools.epp_idle_idx) / IDLE_IDX_MAX;
+}
+
+/*
+ * we try to keep at least PTLRPC_MAX_BRW_PAGES pages in the pool.
+ */
+static unsigned long enc_pools_shrink_scan(struct shrinker *s,
+					   struct shrink_control *sc)
+{
+	spin_lock(&page_pools.epp_lock);
+	sc->nr_to_scan = min_t(unsigned long, sc->nr_to_scan,
+			      page_pools.epp_free_pages - PTLRPC_MAX_BRW_PAGES);
+	if (sc->nr_to_scan > 0) {
+		enc_pools_release_free_pages(sc->nr_to_scan);
+		CDEBUG(D_SEC, "released %ld pages, %ld left\n",
+		       (long)sc->nr_to_scan, page_pools.epp_free_pages);
+
+		page_pools.epp_st_shrinks++;
+		page_pools.epp_last_shrink = cfs_time_current_sec();
+	}
+	spin_unlock(&page_pools.epp_lock);
+
 	/*
 	 * if no pool access for a long time, we consider it's fully idle.
 	 * a little race here is fine.
@@ -262,8 +271,7 @@ static int enc_pools_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
 	}
 
 	LASSERT(page_pools.epp_idle_idx <= IDLE_IDX_MAX);
-	return max((int)page_pools.epp_free_pages - PTLRPC_MAX_BRW_PAGES, 0) *
-		(IDLE_IDX_MAX - page_pools.epp_idle_idx) / IDLE_IDX_MAX;
+	return sc->nr_to_scan;
 }
 
 static inline
@@ -699,13 +707,19 @@ static inline void enc_pools_free(void)
 		       sizeof(*page_pools.epp_pools));
 }
 
+static struct shrinker pools_shrinker = {
+	.count_objects	= enc_pools_shrink_count,
+	.scan_objects	= enc_pools_shrink_scan,
+	.seeks		= DEFAULT_SEEKS,
+};
+
 int sptlrpc_enc_pool_init(void)
 {
 	/*
 	 * maximum capacity is 1/8 of total physical memory.
 	 * is the 1/8 a good number?
 	 */
-	page_pools.epp_max_pages = num_physpages / 8;
+	page_pools.epp_max_pages = totalram_pages / 8;
 	page_pools.epp_max_pools = npages_to_npools(page_pools.epp_max_pages);
 
 	init_waitqueue_head(&page_pools.epp_waitq);
@@ -736,12 +750,7 @@ int sptlrpc_enc_pool_init(void)
 	if (page_pools.epp_pools == NULL)
 		return -ENOMEM;
 
-	pools_shrinker = set_shrinker(pools_shrinker_seeks,
-					  enc_pools_shrink);
-	if (pools_shrinker == NULL) {
-		enc_pools_free();
-		return -ENOMEM;
-	}
+	register_shrinker(&pools_shrinker);
 
 	return 0;
 }
@@ -750,11 +759,10 @@ void sptlrpc_enc_pool_fini(void)
 {
 	unsigned long cleaned, npools;
 
-	LASSERT(pools_shrinker);
 	LASSERT(page_pools.epp_pools);
 	LASSERT(page_pools.epp_total_pages == page_pools.epp_free_pages);
 
-	remove_shrinker(pools_shrinker);
+	unregister_shrinker(&pools_shrinker);
 
 	npools = npages_to_npools(page_pools.epp_total_pages);
 	cleaned = enc_pools_cleanup(page_pools.epp_pools, npools);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
index a45a392..6cc3f23 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
@@ -195,7 +195,7 @@ int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
 	flavor = strchr(param, '=');
 	if (flavor == NULL) {
 		CERROR("invalid param, no '='\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	*flavor++ = '\0';
 
@@ -208,7 +208,7 @@ int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
 		rule->sr_netid = libcfs_str2net(param);
 		if (rule->sr_netid == LNET_NIDNET(LNET_NID_ANY)) {
 			CERROR("invalid network name: %s\n", param);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
@@ -228,16 +228,16 @@ int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
 			rule->sr_to = LUSTRE_SP_MDT;
 		} else {
 			CERROR("invalid rule dir segment: %s\n", dir);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
 	/* 2.1 flavor */
 	rc = sptlrpc_parse_flavor(flavor, &rule->sr_flvr);
 	if (rc)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(sptlrpc_parse_rule);
 
@@ -661,18 +661,17 @@ static int __sptlrpc_process_config(struct lustre_cfg *lcfg,
 	char		    fsname[MTI_NAME_MAXLEN];
 	struct sptlrpc_rule     rule;
 	int		     rc;
-	ENTRY;
 
 	target = lustre_cfg_string(lcfg, 1);
 	if (target == NULL) {
 		CERROR("missing target name\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	param = lustre_cfg_string(lcfg, 2);
 	if (param == NULL) {
 		CERROR("missing parameter\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	CDEBUG(D_SEC, "processing rule: %s.%s\n", target, param);
@@ -680,13 +679,13 @@ static int __sptlrpc_process_config(struct lustre_cfg *lcfg,
 	/* parse rule to make sure the format is correct */
 	if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
 		CERROR("Invalid sptlrpc parameter: %s\n", param);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	param += sizeof(PARAM_SRPC_FLVR) - 1;
 
 	rc = sptlrpc_parse_rule(param, &rule);
 	if (rc)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	if (conf == NULL) {
 		target2fsname(target, fsname, sizeof(fsname));
@@ -708,7 +707,7 @@ static int __sptlrpc_process_config(struct lustre_cfg *lcfg,
 	if (rc == 0)
 		conf->sc_modified++;
 
-	RETURN(rc);
+	return rc;
 }
 
 int sptlrpc_process_config(struct lustre_cfg *lcfg)
@@ -905,7 +904,6 @@ EXPORT_SYMBOL(sptlrpc_target_choose_flavor);
 void sptlrpc_conf_client_adapt(struct obd_device *obd)
 {
 	struct obd_import  *imp;
-	ENTRY;
 
 	LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
 		strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) ==0);
@@ -924,7 +922,6 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd)
 	}
 
 	up_read(&obd->u.cli.cl_sem);
-	EXIT;
 }
 EXPORT_SYMBOL(sptlrpc_conf_client_adapt);
 
@@ -1011,11 +1008,10 @@ int sptlrpc_target_local_copy_conf(struct obd_device *obd,
 	struct lvfs_run_ctxt  saved;
 	struct dentry	*dentry;
 	int		   rc;
-	ENTRY;
 
 	ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
 	if (ctxt == NULL)
-		RETURN(-EINVAL);
+		return -EINVAL;
 
 	push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
@@ -1058,7 +1054,7 @@ out_ctx:
 	llog_ctxt_put(ctxt);
 	CDEBUG(D_SEC, "target %s: write local sptlrpc conf: rc = %d\n",
 	       obd->obd_name, rc);
-	RETURN(rc);
+	return rc;
 }
 
 static int local_read_handler(const struct lu_env *env,
@@ -1068,11 +1064,10 @@ static int local_read_handler(const struct lu_env *env,
 	struct sptlrpc_conf  *conf = (struct sptlrpc_conf *) data;
 	struct lustre_cfg    *lcfg = (struct lustre_cfg *)(rec + 1);
 	int		   cfg_len, rc;
-	ENTRY;
 
 	if (rec->lrh_type != OBD_CFG_REC) {
 		CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
@@ -1081,15 +1076,15 @@ static int local_read_handler(const struct lu_env *env,
 	rc = lustre_cfg_sanity_check(lcfg, cfg_len);
 	if (rc) {
 		CERROR("Insane cfg\n");
-		RETURN(rc);
+		return rc;
 	}
 
 	if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
 		CERROR("invalid command (%x)\n", lcfg->lcfg_command);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
-	RETURN(__sptlrpc_process_config(lcfg, conf));
+	return __sptlrpc_process_config(lcfg, conf);
 }
 
 static
@@ -1100,14 +1095,13 @@ int sptlrpc_target_local_read_conf(struct obd_device *obd,
 	struct llog_ctxt      *ctxt;
 	struct lvfs_run_ctxt   saved;
 	int		    rc;
-	ENTRY;
 
 	LASSERT(conf->sc_updated == 0 && conf->sc_local == 0);
 
 	ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
 	if (ctxt == NULL) {
 		CERROR("missing llog context\n");
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 
 	push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
@@ -1143,7 +1137,7 @@ out_pop:
 	llog_ctxt_put(ctxt);
 	CDEBUG(D_SEC, "target %s: read local sptlrpc conf: rc = %d\n",
 	       obd->obd_name, rc);
-	RETURN(rc);
+	return rc;
 }
 
 
@@ -1160,7 +1154,6 @@ int sptlrpc_conf_target_get_rules(struct obd_device *obd,
 	enum lustre_sec_part      sp_dst;
 	char		      fsname[MTI_NAME_MAXLEN];
 	int		       rc = 0;
-	ENTRY;
 
 	if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) == 0) {
 		sp_dst = LUSTRE_SP_MDT;
@@ -1168,7 +1161,7 @@ int sptlrpc_conf_target_get_rules(struct obd_device *obd,
 		sp_dst = LUSTRE_SP_OST;
 	} else {
 		CERROR("unexpected obd type %s\n", obd->obd_type->typ_name);
-		RETURN(-EINVAL);
+		return -EINVAL;
 	}
 	CDEBUG(D_SEC, "get rules for target %s\n", obd->obd_uuid.uuid);
 
@@ -1210,7 +1203,7 @@ int sptlrpc_conf_target_get_rules(struct obd_device *obd,
 				      LUSTRE_SP_ANY, sp_dst, rset);
 out:
 	mutex_unlock(&sptlrpc_conf_lock);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(sptlrpc_conf_target_get_rules);
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
index 4c96a14a..d2eb20e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
@@ -217,7 +217,7 @@ again:
 int sptlrpc_gc_init(void)
 {
 	struct l_wait_info lwi = { 0 };
-	task_t *task;
+	struct task_struct *task;
 
 	mutex_init(&sec_gc_mutex);
 	spin_lock_init(&sec_gc_list_lock);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
index f552d2f..416401b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
@@ -192,7 +192,6 @@ int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
 	struct lustre_msg   *msg = req->rq_reqbuf;
 	struct plain_header *phdr;
-	ENTRY;
 
 	msg->lm_secflvr = req->rq_flvr.sf_rpc;
 
@@ -209,7 +208,7 @@ int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 
 	req->rq_reqdata_len = lustre_msg_size_v2(msg->lm_bufcount,
 						 msg->lm_buflens);
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -219,11 +218,10 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 	struct plain_header *phdr;
 	__u32		cksum;
 	int		  swabbed;
-	ENTRY;
 
 	if (msg->lm_bufcount != PLAIN_PACK_SEGMENTS) {
 		CERROR("unexpected reply buf count %u\n", msg->lm_bufcount);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	swabbed = ptlrpc_rep_need_swab(req);
@@ -231,24 +229,24 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 	phdr = lustre_msg_buf(msg, PLAIN_PACK_HDR_OFF, sizeof(*phdr));
 	if (phdr == NULL) {
 		CERROR("missing plain header\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (phdr->ph_ver != 0) {
 		CERROR("Invalid header version\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	/* expect no user desc in reply */
 	if (phdr->ph_flags & PLAIN_FL_USER) {
 		CERROR("Unexpected udesc flag in reply\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (phdr->ph_bulk_hash_alg != req->rq_flvr.u_bulk.hash.hash_alg) {
 		CERROR("reply bulk flavor %u != %u\n", phdr->ph_bulk_hash_alg,
 		       req->rq_flvr.u_bulk.hash.hash_alg);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (unlikely(req->rq_early)) {
@@ -262,7 +260,7 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 			CDEBUG(D_SEC,
 			       "early reply checksum mismatch: %08x != %08x\n",
 			       cpu_to_le32(cksum), msg->lm_cksum);
-			RETURN(-EINVAL);
+			return -EINVAL;
 		}
 	} else {
 		/* whether we sent with bulk or not, we expect the same
@@ -272,18 +270,18 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 			  phdr->ph_flags & PLAIN_FL_BULK)) {
 			CERROR("%s bulk checksum in reply\n",
 			       req->rq_pack_bulk ? "Missing" : "Unexpected");
-			RETURN(-EPROTO);
+			return -EPROTO;
 		}
 
 		if (phdr->ph_flags & PLAIN_FL_BULK) {
 			if (plain_unpack_bsd(msg, swabbed))
-				RETURN(-EPROTO);
+				return -EPROTO;
 		}
 	}
 
 	req->rq_repmsg = lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0);
 	req->rq_replen = lustre_msg_buflen(msg, PLAIN_PACK_MSG_OFF);
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -307,10 +305,10 @@ int plain_cli_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
 	bsd->bsd_svc = SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc);
 
 	if (bsd->bsd_svc == SPTLRPC_BULK_SVC_NULL)
-		RETURN(0);
+		return 0;
 
 	if (req->rq_bulk_read)
-		RETURN(0);
+		return 0;
 
 	rc = plain_generate_bulk_csum(desc, req->rq_flvr.u_bulk.hash.hash_alg,
 				      token);
@@ -417,7 +415,6 @@ static
 void plain_destroy_sec(struct ptlrpc_sec *sec)
 {
 	struct plain_sec       *plsec = sec2plsec(sec);
-	ENTRY;
 
 	LASSERT(sec->ps_policy == &plain_policy);
 	LASSERT(sec->ps_import);
@@ -428,7 +425,6 @@ void plain_destroy_sec(struct ptlrpc_sec *sec)
 	class_import_put(sec->ps_import);
 
 	OBD_FREE_PTR(plsec);
-	EXIT;
 }
 
 static
@@ -445,13 +441,12 @@ struct ptlrpc_sec *plain_create_sec(struct obd_import *imp,
 	struct plain_sec       *plsec;
 	struct ptlrpc_sec      *sec;
 	struct ptlrpc_cli_ctx  *ctx;
-	ENTRY;
 
 	LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN);
 
 	OBD_ALLOC_PTR(plsec);
 	if (plsec == NULL)
-		RETURN(NULL);
+		return NULL;
 
 	/*
 	 * initialize plain_sec
@@ -476,12 +471,12 @@ struct ptlrpc_sec *plain_create_sec(struct obd_import *imp,
 		ctx = plain_sec_install_ctx(plsec);
 		if (ctx == NULL) {
 			plain_destroy_sec(sec);
-			RETURN(NULL);
+			return NULL;
 		}
 		sptlrpc_cli_ctx_put(ctx, 1);
 	}
 
-	RETURN(sec);
+	return sec;
 }
 
 static
@@ -491,7 +486,6 @@ struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
 {
 	struct plain_sec       *plsec = sec2plsec(sec);
 	struct ptlrpc_cli_ctx  *ctx;
-	ENTRY;
 
 	read_lock(&plsec->pls_lock);
 	ctx = plsec->pls_ctx;
@@ -502,7 +496,7 @@ struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
 	if (unlikely(ctx == NULL))
 		ctx = plain_sec_install_ctx(plsec);
 
-	RETURN(ctx);
+	return ctx;
 }
 
 static
@@ -526,11 +520,10 @@ int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
 {
 	struct plain_sec       *plsec = sec2plsec(sec);
 	struct ptlrpc_cli_ctx  *ctx;
-	ENTRY;
 
 	/* do nothing unless caller want to flush for 'all' */
 	if (uid != -1)
-		RETURN(0);
+		return 0;
 
 	write_lock(&plsec->pls_lock);
 	ctx = plsec->pls_ctx;
@@ -539,7 +532,7 @@ int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
 
 	if (ctx)
 		sptlrpc_cli_ctx_put(ctx, 1);
-	RETURN(0);
+	return 0;
 }
 
 static
@@ -549,7 +542,6 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
 {
 	__u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, };
 	int   alloc_len;
-	ENTRY;
 
 	buflens[PLAIN_PACK_HDR_OFF] = sizeof(struct plain_header);
 	buflens[PLAIN_PACK_MSG_OFF] = msgsize;
@@ -570,7 +562,7 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
 		alloc_len = size_roundup_power2(alloc_len);
 		OBD_ALLOC_LARGE(req->rq_reqbuf, alloc_len);
 		if (!req->rq_reqbuf)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		req->rq_reqbuf_len = alloc_len;
 	} else {
@@ -585,20 +577,18 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
 	if (req->rq_pack_udesc)
 		sptlrpc_pack_user_desc(req->rq_reqbuf, PLAIN_PACK_USER_OFF);
 
-	RETURN(0);
+	return 0;
 }
 
 static
 void plain_free_reqbuf(struct ptlrpc_sec *sec,
 		       struct ptlrpc_request *req)
 {
-	ENTRY;
 	if (!req->rq_pool) {
 		OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
 		req->rq_reqbuf = NULL;
 		req->rq_reqbuf_len = 0;
 	}
-	EXIT;
 }
 
 static
@@ -608,7 +598,6 @@ int plain_alloc_repbuf(struct ptlrpc_sec *sec,
 {
 	__u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, };
 	int alloc_len;
-	ENTRY;
 
 	buflens[PLAIN_PACK_HDR_OFF] = sizeof(struct plain_header);
 	buflens[PLAIN_PACK_MSG_OFF] = msgsize;
@@ -627,21 +616,19 @@ int plain_alloc_repbuf(struct ptlrpc_sec *sec,
 
 	OBD_ALLOC_LARGE(req->rq_repbuf, alloc_len);
 	if (!req->rq_repbuf)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	req->rq_repbuf_len = alloc_len;
-	RETURN(0);
+	return 0;
 }
 
 static
 void plain_free_repbuf(struct ptlrpc_sec *sec,
 		       struct ptlrpc_request *req)
 {
-	ENTRY;
 	OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len);
 	req->rq_repbuf = NULL;
 	req->rq_repbuf_len = 0;
-	EXIT;
 }
 
 static
@@ -652,7 +639,6 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
 	struct lustre_msg      *newbuf;
 	int		     oldsize;
 	int		     newmsg_size, newbuf_size;
-	ENTRY;
 
 	LASSERT(req->rq_reqbuf);
 	LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
@@ -681,7 +667,7 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
 
 		OBD_ALLOC_LARGE(newbuf, newbuf_size);
 		if (newbuf == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
 
@@ -697,7 +683,7 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
 	_sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
 
 	req->rq_reqlen = newmsg_size;
-	RETURN(0);
+	return 0;
 }
 
 /****************************************
@@ -715,7 +701,6 @@ int plain_accept(struct ptlrpc_request *req)
 	struct lustre_msg   *msg = req->rq_reqbuf;
 	struct plain_header *phdr;
 	int		  swabbed;
-	ENTRY;
 
 	LASSERT(SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) ==
 		SPTLRPC_POLICY_PLAIN);
@@ -725,12 +710,12 @@ int plain_accept(struct ptlrpc_request *req)
 	    SPTLRPC_FLVR_BULK_TYPE(req->rq_flvr.sf_rpc) !=
 	    SPTLRPC_FLVR_BULK_TYPE(SPTLRPC_FLVR_PLAIN)) {
 		CERROR("Invalid rpc flavor %x\n", req->rq_flvr.sf_rpc);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	if (msg->lm_bufcount < PLAIN_PACK_SEGMENTS) {
 		CERROR("unexpected request buf count %u\n", msg->lm_bufcount);
-		RETURN(SECSVC_DROP);
+		return SECSVC_DROP;
 	}
 
 	swabbed = ptlrpc_req_need_swab(req);
@@ -738,17 +723,17 @@ int plain_accept(struct ptlrpc_request *req)
 	phdr = lustre_msg_buf(msg, PLAIN_PACK_HDR_OFF, sizeof(*phdr));
 	if (phdr == NULL) {
 		CERROR("missing plain header\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (phdr->ph_ver != 0) {
 		CERROR("Invalid header version\n");
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	if (phdr->ph_bulk_hash_alg >= BULK_HASH_ALG_MAX) {
 		CERROR("invalid hash algorithm: %u\n", phdr->ph_bulk_hash_alg);
-		RETURN(-EPROTO);
+		return -EPROTO;
 	}
 
 	req->rq_sp_from = phdr->ph_sp;
@@ -758,7 +743,7 @@ int plain_accept(struct ptlrpc_request *req)
 		if (sptlrpc_unpack_user_desc(msg, PLAIN_PACK_USER_OFF,
 					     swabbed)) {
 			CERROR("Mal-formed user descriptor\n");
-			RETURN(SECSVC_DROP);
+			return SECSVC_DROP;
 		}
 
 		req->rq_pack_udesc = 1;
@@ -767,7 +752,7 @@ int plain_accept(struct ptlrpc_request *req)
 
 	if (phdr->ph_flags & PLAIN_FL_BULK) {
 		if (plain_unpack_bsd(msg, swabbed))
-			RETURN(SECSVC_DROP);
+			return SECSVC_DROP;
 
 		req->rq_pack_bulk = 1;
 	}
@@ -778,7 +763,7 @@ int plain_accept(struct ptlrpc_request *req)
 	req->rq_svc_ctx = &plain_svc_ctx;
 	atomic_inc(&req->rq_svc_ctx->sc_refcount);
 
-	RETURN(SECSVC_OK);
+	return SECSVC_OK;
 }
 
 static
@@ -787,7 +772,6 @@ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
 	struct ptlrpc_reply_state   *rs;
 	__u32			buflens[PLAIN_PACK_SEGMENTS] = { 0, };
 	int			  rs_size = sizeof(*rs);
-	ENTRY;
 
 	LASSERT(msgsize % 8 == 0);
 
@@ -807,7 +791,7 @@ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
 	} else {
 		OBD_ALLOC_LARGE(rs, rs_size);
 		if (rs == NULL)
-			RETURN(-ENOMEM);
+			return -ENOMEM;
 
 		rs->rs_size = rs_size;
 	}
@@ -821,20 +805,17 @@ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
 	rs->rs_msg = lustre_msg_buf_v2(rs->rs_repbuf, PLAIN_PACK_MSG_OFF, 0);
 
 	req->rq_reply_state = rs;
-	RETURN(0);
+	return 0;
 }
 
 static
 void plain_free_rs(struct ptlrpc_reply_state *rs)
 {
-	ENTRY;
-
 	LASSERT(atomic_read(&rs->rs_svc_ctx->sc_refcount) > 1);
 	atomic_dec(&rs->rs_svc_ctx->sc_refcount);
 
 	if (!rs->rs_prealloc)
 		OBD_FREE_LARGE(rs, rs->rs_size);
-	EXIT;
 }
 
 static
@@ -844,7 +825,6 @@ int plain_authorize(struct ptlrpc_request *req)
 	struct lustre_msg_v2      *msg = rs->rs_repbuf;
 	struct plain_header       *phdr;
 	int			len;
-	ENTRY;
 
 	LASSERT(rs);
 	LASSERT(msg);
@@ -882,7 +862,7 @@ int plain_authorize(struct ptlrpc_request *req)
 			req->rq_reply_off = 0;
 	}
 
-	RETURN(0);
+	return 0;
 }
 
 static
diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c
index 1667b8e..ac8b5fd 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/service.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/service.c
@@ -369,7 +369,6 @@ static void rs_batch_fini(struct rs_batch *b)
 void ptlrpc_dispatch_difficult_reply(struct ptlrpc_reply_state *rs)
 {
 	struct ptlrpc_hr_thread *hrt;
-	ENTRY;
 
 	LASSERT(list_empty(&rs->rs_list));
 
@@ -380,28 +379,23 @@ void ptlrpc_dispatch_difficult_reply(struct ptlrpc_reply_state *rs)
 	spin_unlock(&hrt->hrt_lock);
 
 	wake_up(&hrt->hrt_waitq);
-	EXIT;
 }
 
 void
 ptlrpc_schedule_difficult_reply(struct ptlrpc_reply_state *rs)
 {
-	ENTRY;
-
 	LASSERT(spin_is_locked(&rs->rs_svcpt->scp_rep_lock));
 	LASSERT(spin_is_locked(&rs->rs_lock));
 	LASSERT (rs->rs_difficult);
 	rs->rs_scheduled_ever = 1;  /* flag any notification attempt */
 
 	if (rs->rs_scheduled) {     /* being set up or already notified */
-		EXIT;
 		return;
 	}
 
 	rs->rs_scheduled = 1;
 	list_del_init(&rs->rs_list);
 	ptlrpc_dispatch_difficult_reply(rs);
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_schedule_difficult_reply);
 
@@ -409,7 +403,6 @@ void ptlrpc_commit_replies(struct obd_export *exp)
 {
 	struct ptlrpc_reply_state *rs, *nxt;
 	DECLARE_RS_BATCH(batch);
-	ENTRY;
 
 	rs_batch_init(&batch);
 	/* Find any replies that have been committed and get their service
@@ -429,7 +422,6 @@ void ptlrpc_commit_replies(struct obd_export *exp)
 	}
 	spin_unlock(&exp->exp_uncommitted_replies_lock);
 	rs_batch_fini(&batch);
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_commit_replies);
 
@@ -551,6 +543,7 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
 	if (tc->tc_thr_factor != 0) {
 		int	  factor = tc->tc_thr_factor;
 		const int fade = 4;
+		cpumask_t mask;
 
 		/*
 		 * User wants to increase number of threads with for
@@ -564,7 +557,8 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
 		 * have too many threads no matter how many cores/HTs
 		 * there are.
 		 */
-		if (cfs_cpu_ht_nsiblings(0) > 1) { /* weight is # of HTs */
+		cpumask_copy(&mask, topology_thread_cpumask(0));
+		if (cpus_weight(mask) > 1) { /* weight is # of HTs */
 			/* depress thread factor for hyper-thread */
 			factor = factor - (factor >> 1) + (factor >> 3);
 		}
@@ -689,7 +683,7 @@ ptlrpc_service_part_init(struct ptlrpc_service *svc,
  */
 struct ptlrpc_service *
 ptlrpc_register_service(struct ptlrpc_service_conf *conf,
-			proc_dir_entry_t *proc_entry)
+			struct proc_dir_entry *proc_entry)
 {
 	struct ptlrpc_service_cpt_conf	*cconf = &conf->psc_cpt;
 	struct ptlrpc_service		*service;
@@ -700,7 +694,6 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 	int				cpt;
 	int				rc;
 	int				i;
-	ENTRY;
 
 	LASSERT(conf->psc_buf.bc_nbufs > 0);
 	LASSERT(conf->psc_buf.bc_buf_size >=
@@ -724,7 +717,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 			if (rc != 0) {
 				CERROR("%s: invalid CPT pattern string: %s",
 				       conf->psc_name, cconf->cc_pattern);
-				RETURN(ERR_PTR(-EINVAL));
+				return ERR_PTR(-EINVAL);
 			}
 
 			rc = cfs_expr_list_values(el, ncpts, &cpts);
@@ -734,7 +727,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 				       conf->psc_name, cconf->cc_pattern, rc);
 				if (cpts != NULL)
 					OBD_FREE(cpts, sizeof(*cpts) * ncpts);
-				RETURN(ERR_PTR(rc < 0 ? rc : -EINVAL));
+				return ERR_PTR(rc < 0 ? rc : -EINVAL);
 			}
 			ncpts = rc;
 		}
@@ -744,7 +737,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 	if (service == NULL) {
 		if (cpts != NULL)
 			OBD_FREE(cpts, sizeof(*cpts) * ncpts);
-		RETURN(ERR_PTR(-ENOMEM));
+		return ERR_PTR(-ENOMEM);
 	}
 
 	service->srv_cptable		= cptable;
@@ -823,10 +816,10 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 		GOTO(failed, rc);
 	}
 
-	RETURN(service);
+	return service;
 failed:
 	ptlrpc_unregister_service(service);
-	RETURN(ERR_PTR(rc));
+	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(ptlrpc_register_service);
 
@@ -1035,8 +1028,6 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay)
 	struct obd_export *oldest_exp;
 	time_t oldest_time, new_time;
 
-	ENTRY;
-
 	LASSERT(exp);
 
 	/* Compensate for slow machines, etc, by faking our request time
@@ -1048,7 +1039,7 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay)
 	/* Do not pay attention on 1sec or smaller renewals. */
 	new_time = cfs_time_current_sec() + extra_delay;
 	if (exp->exp_last_request_time + 1 /*second */ >= new_time)
-		RETURN_EXIT;
+		return;
 
 	exp->exp_last_request_time = new_time;
 	CDEBUG(D_HA, "updating export %s at "CFS_TIME_T" exp %p\n",
@@ -1063,7 +1054,7 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay)
 	if (list_empty(&exp->exp_obd_chain_timed)) {
 		/* this one is not timed */
 		spin_unlock(&exp->exp_obd->obd_dev_lock);
-		RETURN_EXIT;
+		return;
 	}
 
 	list_move_tail(&exp->exp_obd_chain_timed,
@@ -1076,7 +1067,6 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay)
 
 	if (exp->exp_obd->obd_recovering) {
 		/* be nice to everyone during recovery */
-		EXIT;
 		return;
 	}
 
@@ -1105,8 +1095,6 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay)
 				exp->exp_obd->obd_eviction_timer = 0;
 		}
 	}
-
-	EXIT;
 }
 
 /**
@@ -1259,7 +1247,6 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req)
 	cfs_duration_t olddl = req->rq_deadline - cfs_time_current_sec();
 	time_t newdl;
 	int rc;
-	ENTRY;
 
 	/* deadline is when the client expects us to reply, margin is the
 	   difference between clients' and servers' expectations */
@@ -1270,7 +1257,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req)
 		  at_get(&svcpt->scp_at_estimate), at_extra);
 
 	if (AT_OFF)
-		RETURN(0);
+		return 0;
 
 	if (olddl < 0) {
 		DEBUG_REQ(D_WARNING, req, "Already past deadline (%+lds), "
@@ -1278,13 +1265,13 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req)
 			  "at_early_margin (%d)?", olddl, at_early_margin);
 
 		/* Return an error so we're not re-added to the timed list. */
-		RETURN(-ETIMEDOUT);
+		return -ETIMEDOUT;
 	}
 
 	if ((lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT) == 0){
 		DEBUG_REQ(D_INFO, req, "Wanted to ask client for more time, "
 			  "but no AT support");
-		RETURN(-ENOSYS);
+		return -ENOSYS;
 	}
 
 	if (req->rq_export &&
@@ -1314,18 +1301,18 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req)
 				  olddl, req->rq_arrival_time.tv_sec +
 				  at_get(&svcpt->scp_at_estimate) -
 				  cfs_time_current_sec());
-			RETURN(-ETIMEDOUT);
+			return -ETIMEDOUT;
 		}
 	}
 	newdl = cfs_time_current_sec() + at_get(&svcpt->scp_at_estimate);
 
 	OBD_ALLOC(reqcopy, sizeof *reqcopy);
 	if (reqcopy == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	OBD_ALLOC_LARGE(reqmsg, req->rq_reqlen);
 	if (!reqmsg) {
 		OBD_FREE(reqcopy, sizeof *reqcopy);
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	*reqcopy = *req;
@@ -1384,7 +1371,7 @@ out:
 	sptlrpc_svc_ctx_decref(reqcopy);
 	OBD_FREE_LARGE(reqmsg, req->rq_reqlen);
 	OBD_FREE(reqcopy, sizeof *reqcopy);
-	RETURN(rc);
+	return rc;
 }
 
 /* Send early replies to everybody expiring within at_early_margin
@@ -1399,19 +1386,18 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt)
 	time_t now = cfs_time_current_sec();
 	cfs_duration_t delay;
 	int first, counter = 0;
-	ENTRY;
 
 	spin_lock(&svcpt->scp_at_lock);
 	if (svcpt->scp_at_check == 0) {
 		spin_unlock(&svcpt->scp_at_lock);
-		RETURN(0);
+		return 0;
 	}
 	delay = cfs_time_sub(cfs_time_current(), svcpt->scp_at_checktime);
 	svcpt->scp_at_check = 0;
 
 	if (array->paa_count == 0) {
 		spin_unlock(&svcpt->scp_at_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	/* The timer went off, but maybe the nearest rpc already completed. */
@@ -1420,7 +1406,7 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt)
 		/* We've still got plenty of time.  Reset the timer. */
 		ptlrpc_at_set_timer(svcpt);
 		spin_unlock(&svcpt->scp_at_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	/* We're close to a timeout, and we don't know how much longer the
@@ -1490,7 +1476,7 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt)
 		ptlrpc_server_drop_request(rq);
 	}
 
-	RETURN(1); /* return "did_something" for liblustre */
+	return 1; /* return "did_something" for liblustre */
 }
 
 /**
@@ -1501,12 +1487,11 @@ static int ptlrpc_server_hpreq_init(struct ptlrpc_service_part *svcpt,
 				    struct ptlrpc_request *req)
 {
 	int rc = 0;
-	ENTRY;
 
 	if (svcpt->scp_service->srv_ops.so_hpreq_handler) {
 		rc = svcpt->scp_service->srv_ops.so_hpreq_handler(req);
 		if (rc < 0)
-			RETURN(rc);
+			return rc;
 		LASSERT(rc == 0);
 	}
 	if (req->rq_export && req->rq_ops) {
@@ -1527,7 +1512,7 @@ static int ptlrpc_server_hpreq_init(struct ptlrpc_service_part *svcpt,
 			 * ost_brw_write().
 			 */
 			if (rc < 0)
-				RETURN(rc);
+				return rc;
 			LASSERT(rc == 0 || rc == 1);
 		}
 
@@ -1539,13 +1524,12 @@ static int ptlrpc_server_hpreq_init(struct ptlrpc_service_part *svcpt,
 
 	ptlrpc_nrs_req_initialize(svcpt, req, rc);
 
-	RETURN(rc);
+	return rc;
 }
 
 /** Remove the request from the export list. */
 static void ptlrpc_server_hpreq_fini(struct ptlrpc_request *req)
 {
-	ENTRY;
 	if (req->rq_export && req->rq_ops) {
 		/* refresh lock timeout again so that client has more
 		 * room to send lock cancel RPC. */
@@ -1556,7 +1540,6 @@ static void ptlrpc_server_hpreq_fini(struct ptlrpc_request *req)
 		list_del_init(&req->rq_exp_list);
 		spin_unlock_bh(&req->rq_export->exp_rpc_lock);
 	}
-	EXIT;
 }
 
 static int ptlrpc_hpreq_check(struct ptlrpc_request *req)
@@ -1587,15 +1570,14 @@ static int ptlrpc_server_request_add(struct ptlrpc_service_part *svcpt,
 				     struct ptlrpc_request *req)
 {
 	int	rc;
-	ENTRY;
 
 	rc = ptlrpc_server_hpreq_init(svcpt, req);
 	if (rc < 0)
-		RETURN(rc);
+		return rc;
 
 	ptlrpc_nrs_req_add(svcpt, req, !!rc);
 
-	RETURN(0);
+	return 0;
 }
 
 /**
@@ -1701,7 +1683,6 @@ static struct ptlrpc_request *
 ptlrpc_server_request_get(struct ptlrpc_service_part *svcpt, bool force)
 {
 	struct ptlrpc_request *req = NULL;
-	ENTRY;
 
 	spin_lock(&svcpt->scp_req_lock);
 
@@ -1722,7 +1703,7 @@ ptlrpc_server_request_get(struct ptlrpc_service_part *svcpt, bool force)
 	}
 
 	spin_unlock(&svcpt->scp_req_lock);
-	RETURN(NULL);
+	return NULL;
 
 got_request:
 	svcpt->scp_nreqs_active++;
@@ -1734,7 +1715,7 @@ got_request:
 	if (likely(req->rq_export))
 		class_export_rpc_inc(req->rq_export);
 
-	RETURN(req);
+	return req;
 }
 
 /**
@@ -1751,12 +1732,11 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt,
 	struct ptlrpc_request	*req;
 	__u32			deadline;
 	int			rc;
-	ENTRY;
 
 	spin_lock(&svcpt->scp_lock);
 	if (list_empty(&svcpt->scp_req_incoming)) {
 		spin_unlock(&svcpt->scp_lock);
-		RETURN(0);
+		return 0;
 	}
 
 	req = list_entry(svcpt->scp_req_incoming.next,
@@ -1875,12 +1855,12 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt,
 		GOTO(err_req, rc);
 
 	wake_up(&svcpt->scp_waitq);
-	RETURN(1);
+	return 1;
 
 err_req:
 	ptlrpc_server_finish_request(svcpt, req);
 
-	RETURN(1);
+	return 1;
 }
 
 /**
@@ -1898,11 +1878,10 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt,
 	long		   timediff;
 	int		    rc;
 	int		    fail_opc = 0;
-	ENTRY;
 
 	request = ptlrpc_server_request_get(svcpt, false);
 	if (request == NULL)
-		RETURN(0);
+		return 0;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_HPREQ_NOTIMEOUT))
 		fail_opc = OBD_FAIL_PTLRPC_HPREQ_NOTIMEOUT;
@@ -2041,7 +2020,7 @@ put_conn:
 out_req:
 	ptlrpc_server_finish_active_request(svcpt, request);
 
-	RETURN(1);
+	return 1;
 }
 
 /**
@@ -2055,7 +2034,6 @@ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs)
 	struct obd_export	 *exp;
 	int			nlocks;
 	int			been_handled;
-	ENTRY;
 
 	exp = rs->rs_export;
 
@@ -2141,12 +2119,12 @@ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs)
 		if (atomic_dec_and_test(&svcpt->scp_nreps_difficult) &&
 		    svc->srv_is_stopping)
 			wake_up_all(&svcpt->scp_waitq);
-		RETURN(1);
+		return 1;
 	}
 
 	/* still on the net; callback will schedule */
 	spin_unlock(&rs->rs_lock);
-	RETURN(1);
+	return 1;
 }
 
 
@@ -2252,7 +2230,9 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt,
 	struct l_wait_info lwi = LWI_TIMEOUT(svcpt->scp_rqbd_timeout,
 					     ptlrpc_retry_rqbds, svcpt);
 
+	/* XXX: Add this back when libcfs watchdog is merged upstream
 	lc_watchdog_disable(thread->t_watchdog);
+	 */
 
 	cond_resched();
 
@@ -2266,8 +2246,10 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt,
 	if (ptlrpc_thread_stopping(thread))
 		return -EINTR;
 
+	/*
 	lc_watchdog_touch(thread->t_watchdog,
 			  ptlrpc_server_get_timeout(svcpt));
+	 */
 	return 0;
 }
 
@@ -2284,11 +2266,10 @@ static int ptlrpc_main(void *arg)
 	struct ptlrpc_service		*svc = svcpt->scp_service;
 	struct ptlrpc_reply_state	*rs;
 #ifdef WITH_GROUP_INFO
-	group_info_t *ginfo = NULL;
+	struct group_info *ginfo = NULL;
 #endif
 	struct lu_env *env;
 	int counter = 0, rc = 0;
-	ENTRY;
 
 	thread->t_pid = current_pid();
 	unshare_fs_struct();
@@ -2370,8 +2351,10 @@ static int ptlrpc_main(void *arg)
 	/* wake up our creator in case he's still waiting. */
 	wake_up(&thread->t_ctl_waitq);
 
+	/*
 	thread->t_watchdog = lc_watchdog_add(ptlrpc_server_get_timeout(svcpt),
 					     NULL, NULL);
+	 */
 
 	spin_lock(&svcpt->scp_rep_lock);
 	list_add(&rs->rs_list, &svcpt->scp_rep_idle);
@@ -2426,8 +2409,10 @@ static int ptlrpc_main(void *arg)
 		}
 	}
 
+	/*
 	lc_watchdog_delete(thread->t_watchdog);
 	thread->t_watchdog = NULL;
+	*/
 
 out_srv_fini:
 	/*
@@ -2550,7 +2535,6 @@ static int ptlrpc_start_hr_threads(void)
 	struct ptlrpc_hr_partition	*hrp;
 	int				i;
 	int				j;
-	ENTRY;
 
 	cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) {
 		int	rc = 0;
@@ -2573,9 +2557,9 @@ static int ptlrpc_start_hr_threads(void)
 		CERROR("Reply handling thread %d:%d Failed on starting: "
 		       "rc = %d\n", i, j, rc);
 		ptlrpc_stop_hr_threads();
-		RETURN(rc);
+		return rc;
 	}
-	RETURN(0);
+	return 0;
 }
 
 static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt)
@@ -2584,8 +2568,6 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt)
 	struct ptlrpc_thread	*thread;
 	LIST_HEAD		(zombie);
 
-	ENTRY;
-
 	CDEBUG(D_INFO, "Stopping threads for service %s\n",
 	       svcpt->scp_service->srv_name);
 
@@ -2625,7 +2607,6 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt)
 		list_del(&thread->t_link);
 		OBD_FREE_PTR(thread);
 	}
-	EXIT;
 }
 
 /**
@@ -2635,14 +2616,11 @@ void ptlrpc_stop_all_threads(struct ptlrpc_service *svc)
 {
 	struct ptlrpc_service_part *svcpt;
 	int			   i;
-	ENTRY;
 
 	ptlrpc_service_for_each_part(svcpt, i, svc) {
 		if (svcpt->scp_service != NULL)
 			ptlrpc_svcpt_stop_threads(svcpt);
 	}
-
-	EXIT;
 }
 EXPORT_SYMBOL(ptlrpc_stop_all_threads);
 
@@ -2651,7 +2629,6 @@ int ptlrpc_start_threads(struct ptlrpc_service *svc)
 	int	rc = 0;
 	int	i;
 	int	j;
-	ENTRY;
 
 	/* We require 2 threads min, see note in ptlrpc_server_handle_request */
 	LASSERT(svc->srv_nthrs_cpt_init >= PTLRPC_NTHRS_INIT);
@@ -2669,12 +2646,12 @@ int ptlrpc_start_threads(struct ptlrpc_service *svc)
 		}
 	}
 
-	RETURN(0);
+	return 0;
  failed:
 	CERROR("cannot start %s thread #%d_%d: rc %d\n",
 	       svc->srv_thread_name, i, j, rc);
 	ptlrpc_stop_all_threads(svc);
-	RETURN(rc);
+	return rc;
 }
 EXPORT_SYMBOL(ptlrpc_start_threads);
 
@@ -2684,7 +2661,6 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
 	struct ptlrpc_thread	*thread;
 	struct ptlrpc_service	*svc;
 	int			rc;
-	ENTRY;
 
 	LASSERT(svcpt != NULL);
 
@@ -2696,23 +2672,23 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
 
  again:
 	if (unlikely(svc->srv_is_stopping))
-		RETURN(-ESRCH);
+		return -ESRCH;
 
 	if (!ptlrpc_threads_increasable(svcpt) ||
 	    (OBD_FAIL_CHECK(OBD_FAIL_TGT_TOOMANY_THREADS) &&
 	     svcpt->scp_nthrs_running == svc->srv_nthrs_cpt_init - 1))
-		RETURN(-EMFILE);
+		return -EMFILE;
 
 	OBD_CPT_ALLOC_PTR(thread, svc->srv_cptable, svcpt->scp_cpt);
 	if (thread == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 	init_waitqueue_head(&thread->t_ctl_waitq);
 
 	spin_lock(&svcpt->scp_lock);
 	if (!ptlrpc_threads_increasable(svcpt)) {
 		spin_unlock(&svcpt->scp_lock);
 		OBD_FREE_PTR(thread);
-		RETURN(-EMFILE);
+		return -EMFILE;
 	}
 
 	if (svcpt->scp_nthrs_starting != 0) {
@@ -2730,7 +2706,7 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
 
 		CDEBUG(D_INFO, "Creating thread %s #%d race, retry later\n",
 		       svc->srv_thread_name, svcpt->scp_thr_nextid);
-		RETURN(-EAGAIN);
+		return -EAGAIN;
 	}
 
 	svcpt->scp_nthrs_starting++;
@@ -2755,33 +2731,42 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
 		CERROR("cannot start thread '%s': rc %d\n",
 		       thread->t_name, rc);
 		spin_lock(&svcpt->scp_lock);
-		list_del(&thread->t_link);
 		--svcpt->scp_nthrs_starting;
-		spin_unlock(&svcpt->scp_lock);
-
-		OBD_FREE(thread, sizeof(*thread));
-		RETURN(rc);
+		if (thread_is_stopping(thread)) {
+			/* this ptlrpc_thread is being hanled
+			 * by ptlrpc_svcpt_stop_threads now
+			 */
+			thread_add_flags(thread, SVC_STOPPED);
+			wake_up(&thread->t_ctl_waitq);
+			spin_unlock(&svcpt->scp_lock);
+		} else {
+			list_del(&thread->t_link);
+			spin_unlock(&svcpt->scp_lock);
+			OBD_FREE_PTR(thread);
+		}
+		return rc;
 	}
 
 	if (!wait)
-		RETURN(0);
+		return 0;
 
 	l_wait_event(thread->t_ctl_waitq,
 		     thread_is_running(thread) || thread_is_stopped(thread),
 		     &lwi);
 
 	rc = thread_is_stopped(thread) ? thread->t_id : 0;
-	RETURN(rc);
+	return rc;
 }
 
 int ptlrpc_hr_init(void)
 {
+	cpumask_t			mask;
 	struct ptlrpc_hr_partition	*hrp;
 	struct ptlrpc_hr_thread		*hrt;
 	int				rc;
 	int				i;
 	int				j;
-	ENTRY;
+	int				weight;
 
 	memset(&ptlrpc_hr, 0, sizeof(ptlrpc_hr));
 	ptlrpc_hr.hr_cpt_table = cfs_cpt_table;
@@ -2789,10 +2774,13 @@ int ptlrpc_hr_init(void)
 	ptlrpc_hr.hr_partitions = cfs_percpt_alloc(ptlrpc_hr.hr_cpt_table,
 						   sizeof(*hrp));
 	if (ptlrpc_hr.hr_partitions == NULL)
-		RETURN(-ENOMEM);
+		return -ENOMEM;
 
 	init_waitqueue_head(&ptlrpc_hr.hr_waitq);
 
+	cpumask_copy(&mask, topology_thread_cpumask(0));
+	weight = cpus_weight(mask);
+
 	cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) {
 		hrp->hrp_cpt = i;
 
@@ -2800,7 +2788,7 @@ int ptlrpc_hr_init(void)
 		atomic_set(&hrp->hrp_nstopped, 0);
 
 		hrp->hrp_nthrs = cfs_cpt_weight(ptlrpc_hr.hr_cpt_table, i);
-		hrp->hrp_nthrs /= cfs_cpu_ht_nsiblings(0);
+		hrp->hrp_nthrs /= weight;
 
 		LASSERT(hrp->hrp_nthrs > 0);
 		OBD_CPT_ALLOC(hrp->hrp_thrs, ptlrpc_hr.hr_cpt_table, i,
@@ -2823,7 +2811,7 @@ int ptlrpc_hr_init(void)
 out:
 	if (rc != 0)
 		ptlrpc_hr_fini();
-	RETURN(rc);
+	return rc;
 }
 
 void ptlrpc_hr_fini(void)
@@ -3045,8 +3033,6 @@ ptlrpc_service_free(struct ptlrpc_service *svc)
 
 int ptlrpc_unregister_service(struct ptlrpc_service *service)
 {
-	ENTRY;
-
 	CDEBUG(D_NET, "%s: tearing down\n", service->srv_name);
 
 	service->srv_is_stopping = 1;
@@ -3066,7 +3052,7 @@ int ptlrpc_unregister_service(struct ptlrpc_service *service)
 
 	ptlrpc_service_free(service);
 
-	RETURN(0);
+	return 0;
 }
 EXPORT_SYMBOL(ptlrpc_unregister_service);
 
diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c
index 2faa391..28c8b0b 100644
--- a/drivers/staging/media/lirc/lirc_igorplugusb.c
+++ b/drivers/staging/media/lirc/lirc_igorplugusb.c
@@ -240,10 +240,6 @@ static int unregister_from_lirc(struct igorplug *ir)
 	dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum);
 	lirc_unregister_driver(d->minor);
 
-	kfree(d);
-	ir->d = NULL;
-	kfree(ir);
-
 	return devnum;
 }
 
@@ -377,20 +373,16 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
 	return -ENODATA;
 }
 
-
-
 static int igorplugusb_remote_probe(struct usb_interface *intf,
 				    const struct usb_device_id *id)
 {
-	struct usb_device *dev = NULL;
+	struct usb_device *dev;
 	struct usb_host_interface *idesc = NULL;
 	struct usb_endpoint_descriptor *ep;
 	struct igorplug *ir = NULL;
 	struct lirc_driver *driver = NULL;
 	int devnum, pipe, maxp;
-	int minor = 0;
 	char buf[63], name[128] = "";
-	int mem_failure = 0;
 	int ret;
 
 	dprintk(DRIVER_NAME ": usb probe called.\n");
@@ -416,24 +408,18 @@ static int igorplugusb_remote_probe(struct usb_interface *intf,
 	dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n",
 		devnum, CODE_LENGTH, maxp);
 
-	mem_failure = 0;
-	ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL);
-	if (!ir) {
-		mem_failure = 1;
-		goto mem_failure_switch;
-	}
-	driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
-	if (!driver) {
-		mem_failure = 2;
-		goto mem_failure_switch;
-	}
+	ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL);
+	if (!ir)
+		return -ENOMEM;
+
+	driver = devm_kzalloc(&intf->dev, sizeof(*driver), GFP_KERNEL);
+	if (!driver)
+		return -ENOMEM;
 
 	ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
 					GFP_ATOMIC, &ir->dma_in);
-	if (!ir->buf_in) {
-		mem_failure = 3;
-		goto mem_failure_switch;
-	}
+	if (!ir->buf_in)
+		return -ENOMEM;
 
 	strcpy(driver->name, DRIVER_NAME " ");
 	driver->minor = -1;
@@ -449,27 +435,14 @@ static int igorplugusb_remote_probe(struct usb_interface *intf,
 	driver->dev = &intf->dev;
 	driver->owner = THIS_MODULE;
 
-	minor = lirc_register_driver(driver);
-	if (minor < 0)
-		mem_failure = 9;
-
-mem_failure_switch:
-
-	switch (mem_failure) {
-	case 9:
+	ret = lirc_register_driver(driver);
+	if (ret < 0) {
 		usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
 			ir->buf_in, ir->dma_in);
-	case 3:
-		kfree(driver);
-	case 2:
-		kfree(ir);
-	case 1:
-		printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
-			devnum, mem_failure);
-		return -ENOMEM;
+		return ret;
 	}
 
-	driver->minor = minor;
+	driver->minor = ret;
 	ir->d = driver;
 	ir->devnum = devnum;
 	ir->usbdev = dev;
@@ -502,7 +475,6 @@ mem_failure_switch:
 	return 0;
 }
 
-
 static void igorplugusb_remote_disconnect(struct usb_interface *intf)
 {
 	struct usb_device *usbdev = interface_to_usbdev(intf);
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 10393da..5a5c639 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -750,8 +750,6 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec)
 	writel(0, nvec->base + I2C_SL_ADDR2);
 
 	enable_irq(nvec->irq);
-
-	clk_disable_unprepare(nvec->i2c_clk);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -872,9 +870,6 @@ static int tegra_nvec_probe(struct platform_device *pdev)
 
 	tegra_init_i2c_slave(nvec);
 
-	clk_prepare_enable(i2c_clk);
-
-
 	/* enable event reporting */
 	nvec_toggle_global_events(nvec, true);
 
diff --git a/drivers/staging/octeon-usb/Kconfig b/drivers/staging/octeon-usb/Kconfig
index 018af6d..16ea17f 100644
--- a/drivers/staging/octeon-usb/Kconfig
+++ b/drivers/staging/octeon-usb/Kconfig
@@ -1,6 +1,6 @@
 config OCTEON_USB
 	tristate "Cavium Networks Octeon USB support"
-	depends on CPU_CAVIUM_OCTEON && USB
+	depends on CAVIUM_OCTEON_SOC && USB
 	help
 	  This driver supports USB host controller on some Cavium
 	  Networks' products in the Octeon family.
diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c
index bf36649..d7b3c82 100644
--- a/drivers/staging/octeon-usb/cvmx-usb.c
+++ b/drivers/staging/octeon-usb/cvmx-usb.c
@@ -46,8 +46,6 @@
  * systems. These functions provide a generic API to the Octeon
  * USB blocks, hiding the internal hardware specific
  * operations.
- *
- * <hr>$Revision: 32636 $<hr>
  */
 #include <linux/delay.h>
 #include <asm/octeon/cvmx.h>
@@ -68,30 +66,27 @@
 #define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset)
 #define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
 
-#define cvmx_likely likely
-#define cvmx_wait_usec udelay
-#define cvmx_unlikely unlikely
-#define cvmx_le16_to_cpu le16_to_cpu
-
-#define MAX_RETRIES         3   /* Maximum number of times to retry failed transactions */
-#define MAX_PIPES           32  /* Maximum number of pipes that can be open at once */
-#define MAX_TRANSACTIONS    256 /* Maximum number of outstanding transactions across all pipes */
-#define MAX_CHANNELS        8   /* Maximum number of hardware channels supported by the USB block */
-#define MAX_USB_ADDRESS     127 /* The highest valid USB device address */
-#define MAX_USB_ENDPOINT    15  /* The highest valid USB endpoint number */
-#define MAX_USB_HUB_PORT    15  /* The highest valid port number on a hub */
-#define MAX_TRANSFER_BYTES  ((1<<19)-1) /* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */
-#define MAX_TRANSFER_PACKETS ((1<<10)-1) /* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */
-
-/* These defines disable the normal read and write csr. This is so I can add
-    extra debug stuff to the usb specific version and I won't use the normal
-    version by mistake */
+#define MAX_RETRIES		3		/* Maximum number of times to retry failed transactions */
+#define MAX_PIPES		32		/* Maximum number of pipes that can be open at once */
+#define MAX_TRANSACTIONS	256		/* Maximum number of outstanding transactions across all pipes */
+#define MAX_CHANNELS		8		/* Maximum number of hardware channels supported by the USB block */
+#define MAX_USB_ADDRESS		127		/* The highest valid USB device address */
+#define MAX_USB_ENDPOINT	15		/* The highest valid USB endpoint number */
+#define MAX_USB_HUB_PORT	15		/* The highest valid port number on a hub */
+#define MAX_TRANSFER_BYTES	((1<<19)-1)	/* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */
+#define MAX_TRANSFER_PACKETS	((1<<10)-1)	/* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */
+
+/*
+ * These defines disable the normal read and write csr. This is so I can add
+ * extra debug stuff to the usb specific version and I won't use the normal
+ * version by mistake
+ */
 #define cvmx_read_csr use_cvmx_usb_read_csr64_instead_of_cvmx_read_csr
 #define cvmx_write_csr use_cvmx_usb_write_csr64_instead_of_cvmx_write_csr
 
-typedef enum {
-    __CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16,
-} cvmx_usb_transaction_flags_t;
+enum cvmx_usb_transaction_flags {
+	__CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16,
+};
 
 enum {
 	USB_CLOCK_TYPE_REF_12,
@@ -108,167 +103,208 @@ enum {
  * the NAK handler can backup to the previous low level
  * transaction with a simple clearing of bit 0.
  */
-typedef enum {
-    CVMX_USB_STAGE_NON_CONTROL,
-    CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE,
-    CVMX_USB_STAGE_SETUP,
-    CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE,
-    CVMX_USB_STAGE_DATA,
-    CVMX_USB_STAGE_DATA_SPLIT_COMPLETE,
-    CVMX_USB_STAGE_STATUS,
-    CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE,
-} cvmx_usb_stage_t;
+enum cvmx_usb_stage {
+	CVMX_USB_STAGE_NON_CONTROL,
+	CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE,
+	CVMX_USB_STAGE_SETUP,
+	CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE,
+	CVMX_USB_STAGE_DATA,
+	CVMX_USB_STAGE_DATA_SPLIT_COMPLETE,
+	CVMX_USB_STAGE_STATUS,
+	CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE,
+};
+
+/**
+ * struct cvmx_usb_transaction - describes each pending USB transaction
+ *				 regardless of type. These are linked together
+ *				 to form a list of pending requests for a pipe.
+ *
+ * @prev:		Transaction before this one in the pipe.
+ * @next:		Transaction after this one in the pipe.
+ * @type:		Type of transaction, duplicated of the pipe.
+ * @flags:		State flags for this transaction.
+ * @buffer:		User's physical buffer address to read/write.
+ * @buffer_length:	Size of the user's buffer in bytes.
+ * @control_header:	For control transactions, physical address of the 8
+ *			byte standard header.
+ * @iso_start_frame:	For ISO transactions, the starting frame number.
+ * @iso_number_packets:	For ISO transactions, the number of packets in the
+ *			request.
+ * @iso_packets:	For ISO transactions, the sub packets in the request.
+ * @actual_bytes:	Actual bytes transfer for this transaction.
+ * @stage:		For control transactions, the current stage.
+ * @callback:		User's callback function when complete.
+ * @callback_data:	User's data.
+ */
+struct cvmx_usb_transaction {
+	struct cvmx_usb_transaction *prev;
+	struct cvmx_usb_transaction *next;
+	enum cvmx_usb_transfer type;
+	enum cvmx_usb_transaction_flags flags;
+	uint64_t buffer;
+	int buffer_length;
+	uint64_t control_header;
+	int iso_start_frame;
+	int iso_number_packets;
+	struct cvmx_usb_iso_packet *iso_packets;
+	int xfersize;
+	int pktcnt;
+	int retries;
+	int actual_bytes;
+	enum cvmx_usb_stage stage;
+	cvmx_usb_callback_func_t callback;
+	void *callback_data;
+};
 
 /**
- * This structure describes each pending USB transaction
- * regardless of type. These are linked together to form a list
- * of pending requests for a pipe.
+ * struct cvmx_usb_pipe - a pipe represents a virtual connection between Octeon
+ *			  and some USB device. It contains a list of pending
+ *			  request to the device.
+ *
+ * @prev:		Pipe before this one in the list
+ * @next:		Pipe after this one in the list
+ * @head:		The first pending transaction
+ * @tail:		The last pending transaction
+ * @interval:		For periodic pipes, the interval between packets in
+ *			frames
+ * @next_tx_frame:	The next frame this pipe is allowed to transmit on
+ * @flags:		State flags for this pipe
+ * @device_speed:	Speed of device connected to this pipe
+ * @transfer_type:	Type of transaction supported by this pipe
+ * @transfer_dir:	IN or OUT. Ignored for Control
+ * @multi_count:	Max packet in a row for the device
+ * @max_packet:		The device's maximum packet size in bytes
+ * @device_addr:	USB device address at other end of pipe
+ * @endpoint_num:	USB endpoint number at other end of pipe
+ * @hub_device_addr:	Hub address this device is connected to
+ * @hub_port:		Hub port this device is connected to
+ * @pid_toggle:		This toggles between 0/1 on every packet send to track
+ *			the data pid needed
+ * @channel:		Hardware DMA channel for this pipe
+ * @split_sc_frame:	The low order bits of the frame number the split
+ *			complete should be sent on
  */
-typedef struct cvmx_usb_transaction {
-    struct cvmx_usb_transaction *prev;  /**< Transaction before this one in the pipe */
-    struct cvmx_usb_transaction *next;  /**< Transaction after this one in the pipe */
-    cvmx_usb_transfer_t type;           /**< Type of transaction, duplicated of the pipe */
-    cvmx_usb_transaction_flags_t flags; /**< State flags for this transaction */
-    uint64_t buffer;                    /**< User's physical buffer address to read/write */
-    int buffer_length;                  /**< Size of the user's buffer in bytes */
-    uint64_t control_header;            /**< For control transactions, physical address of the 8 byte standard header */
-    int iso_start_frame;                /**< For ISO transactions, the starting frame number */
-    int iso_number_packets;             /**< For ISO transactions, the number of packets in the request */
-    cvmx_usb_iso_packet_t *iso_packets; /**< For ISO transactions, the sub packets in the request */
-    int xfersize;
-    int pktcnt;
-    int retries;
-    int actual_bytes;                   /**< Actual bytes transfer for this transaction */
-    cvmx_usb_stage_t stage;             /**< For control transactions, the current stage */
-    cvmx_usb_callback_func_t callback;  /**< User's callback function when complete */
-    void *callback_data;                /**< User's data */
-} cvmx_usb_transaction_t;
+struct cvmx_usb_pipe {
+	struct cvmx_usb_pipe *prev;
+	struct cvmx_usb_pipe *next;
+	struct cvmx_usb_transaction *head;
+	struct cvmx_usb_transaction *tail;
+	uint64_t interval;
+	uint64_t next_tx_frame;
+	enum cvmx_usb_pipe_flags flags;
+	enum cvmx_usb_speed device_speed;
+	enum cvmx_usb_transfer transfer_type;
+	enum cvmx_usb_direction transfer_dir;
+	int multi_count;
+	uint16_t max_packet;
+	uint8_t device_addr;
+	uint8_t endpoint_num;
+	uint8_t hub_device_addr;
+	uint8_t hub_port;
+	uint8_t pid_toggle;
+	uint8_t channel;
+	int8_t split_sc_frame;
+};
 
 /**
- * A pipe represents a virtual connection between Octeon and some
- * USB device. It contains a list of pending request to the device.
+ * struct cvmx_usb_pipe_list
+ *
+ * @head: Head of the list, or NULL if empty.
+ * @tail: Tail if the list, or NULL if empty.
  */
-typedef struct cvmx_usb_pipe {
-    struct cvmx_usb_pipe *prev;         /**< Pipe before this one in the list */
-    struct cvmx_usb_pipe *next;         /**< Pipe after this one in the list */
-    cvmx_usb_transaction_t *head;       /**< The first pending transaction */
-    cvmx_usb_transaction_t *tail;       /**< The last pending transaction */
-    uint64_t interval;                  /**< For periodic pipes, the interval between packets in frames */
-    uint64_t next_tx_frame;             /**< The next frame this pipe is allowed to transmit on */
-    cvmx_usb_pipe_flags_t flags;        /**< State flags for this pipe */
-    cvmx_usb_speed_t device_speed;      /**< Speed of device connected to this pipe */
-    cvmx_usb_transfer_t transfer_type;  /**< Type of transaction supported by this pipe */
-    cvmx_usb_direction_t transfer_dir;  /**< IN or OUT. Ignored for Control */
-    int multi_count;                    /**< Max packet in a row for the device */
-    uint16_t max_packet;                /**< The device's maximum packet size in bytes */
-    uint8_t device_addr;                /**< USB device address at other end of pipe */
-    uint8_t endpoint_num;               /**< USB endpoint number at other end of pipe */
-    uint8_t hub_device_addr;            /**< Hub address this device is connected to */
-    uint8_t hub_port;                   /**< Hub port this device is connected to */
-    uint8_t pid_toggle;                 /**< This toggles between 0/1 on every packet send to track the data pid needed */
-    uint8_t channel;                    /**< Hardware DMA channel for this pipe */
-    int8_t  split_sc_frame;             /**< The low order bits of the frame number the split complete should be sent on */
-} cvmx_usb_pipe_t;
-
-typedef struct {
-    cvmx_usb_pipe_t *head;              /**< Head of the list, or NULL if empty */
-    cvmx_usb_pipe_t *tail;              /**< Tail if the list, or NULL if empty */
-} cvmx_usb_pipe_list_t;
-
-typedef struct {
-    struct {
-        int channel;
-        int size;
-        uint64_t address;
-    } entry[MAX_CHANNELS+1];
-    int head;
-    int tail;
-} cvmx_usb_tx_fifo_t;
+struct cvmx_usb_pipe_list {
+	struct cvmx_usb_pipe *head;
+	struct cvmx_usb_pipe *tail;
+};
+
+struct cvmx_usb_tx_fifo {
+	struct {
+		int channel;
+		int size;
+		uint64_t address;
+	} entry[MAX_CHANNELS+1];
+	int head;
+	int tail;
+};
 
 /**
- * The state of the USB block is stored in this structure
+ * struct cvmx_usb_internal_state - the state of the USB block
+ *
+ * init_flags:		   Flags passed to initialize.
+ * index:		   Which USB block this is for.
+ * idle_hardware_channels: Bit set for every idle hardware channel.
+ * usbcx_hprt:		   Stored port status so we don't need to read a CSR to
+ *			   determine splits.
+ * pipe_for_channel:	   Map channels to pipes.
+ * free_transaction_head:  List of free transactions head.
+ * free_transaction_tail:  List of free transactions tail.
+ * pipe:		   Storage for pipes.
+ * transaction:		   Storage for transactions.
+ * callback:		   User global callbacks.
+ * callback_data:	   User data for each callback.
+ * indent:		   Used by debug output to indent functions.
+ * port_status:		   Last port status used for change notification.
+ * free_pipes:		   List of all pipes that are currently closed.
+ * idle_pipes:		   List of open pipes that have no transactions.
+ * active_pipes:	   Active pipes indexed by transfer type.
+ * frame_number:	   Increments every SOF interrupt for time keeping.
+ * active_split:	   Points to the current active split, or NULL.
  */
-typedef struct {
-    int init_flags;                     /**< Flags passed to initialize */
-    int index;                          /**< Which USB block this is for */
-    int idle_hardware_channels;         /**< Bit set for every idle hardware channel */
-    cvmx_usbcx_hprt_t usbcx_hprt;       /**< Stored port status so we don't need to read a CSR to determine splits */
-    cvmx_usb_pipe_t *pipe_for_channel[MAX_CHANNELS];    /**< Map channels to pipes */
-    cvmx_usb_transaction_t *free_transaction_head;      /**< List of free transactions head */
-    cvmx_usb_transaction_t *free_transaction_tail;      /**< List of free transactions tail */
-    cvmx_usb_pipe_t pipe[MAX_PIPES];                    /**< Storage for pipes */
-    cvmx_usb_transaction_t transaction[MAX_TRANSACTIONS];       /**< Storage for transactions */
-    cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */
-    void *callback_data[__CVMX_USB_CALLBACK_END];               /**< User data for each callback */
-    int indent;                         /**< Used by debug output to indent functions */
-    cvmx_usb_port_status_t port_status; /**< Last port status used for change notification */
-    cvmx_usb_pipe_list_t free_pipes;    /**< List of all pipes that are currently closed */
-    cvmx_usb_pipe_list_t idle_pipes;    /**< List of open pipes that have no transactions */
-    cvmx_usb_pipe_list_t active_pipes[4]; /**< Active pipes indexed by transfer type */
-    uint64_t frame_number;              /**< Increments every SOF interrupt for time keeping */
-    cvmx_usb_transaction_t *active_split; /**< Points to the current active split, or NULL */
-    cvmx_usb_tx_fifo_t periodic;
-    cvmx_usb_tx_fifo_t nonperiodic;
-} cvmx_usb_internal_state_t;
-
-/* This macro logs out whenever a function is called if debugging is on */
-#define CVMX_USB_LOG_CALLED() \
-    if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) \
-        cvmx_dprintf("%*s%s: called\n", 2*usb->indent++, "", __FUNCTION__);
-
-/* This macro logs out each function parameter if debugging is on */
-#define CVMX_USB_LOG_PARAM(format, param) \
-    if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) \
-        cvmx_dprintf("%*s%s: param %s = " format "\n", 2*usb->indent, "", __FUNCTION__, #param, param);
-
-/* This macro logs out when a function returns a value */
-#define CVMX_USB_RETURN(v)                                              \
-    do {                                                                \
-        typeof(v) r = v;                                                \
-        if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS))    \
-            cvmx_dprintf("%*s%s: returned %s(%d)\n", 2*--usb->indent, "", __FUNCTION__, #v, r); \
-        return r;                                                       \
-    } while (0);
-
-/* This macro logs out when a function doesn't return a value */
-#define CVMX_USB_RETURN_NOTHING()                                       \
-    do {                                                                \
-        if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS))    \
-            cvmx_dprintf("%*s%s: returned\n", 2*--usb->indent, "", __FUNCTION__); \
-        return;                                                         \
-    } while (0);
+struct cvmx_usb_internal_state {
+	int init_flags;
+	int index;
+	int idle_hardware_channels;
+	union cvmx_usbcx_hprt usbcx_hprt;
+	struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS];
+	struct cvmx_usb_transaction *free_transaction_head;
+	struct cvmx_usb_transaction *free_transaction_tail;
+	struct cvmx_usb_pipe pipe[MAX_PIPES];
+	struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS];
+	cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END];
+	void *callback_data[__CVMX_USB_CALLBACK_END];
+	int indent;
+	struct cvmx_usb_port_status port_status;
+	struct cvmx_usb_pipe_list free_pipes;
+	struct cvmx_usb_pipe_list idle_pipes;
+	struct cvmx_usb_pipe_list active_pipes[4];
+	uint64_t frame_number;
+	struct cvmx_usb_transaction *active_split;
+	struct cvmx_usb_tx_fifo periodic;
+	struct cvmx_usb_tx_fifo nonperiodic;
+};
 
 /* This macro spins on a field waiting for it to reach a value */
 #define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\
-    ({int result;                                                       \
-    do {                                                                \
-        uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec *     \
-			octeon_get_clock_rate() / 1000000;		\
-        type c;                                                         \
-        while (1)                                                       \
-        {                                                               \
-            c.u32 = __cvmx_usb_read_csr32(usb, address);                \
-            if (c.s.field op (value)) {                                 \
-                result = 0;                                             \
-                break;                                                  \
-            } else if (cvmx_get_cycle() > done) {                       \
-                result = -1;                                            \
-                break;                                                  \
-            } else                                                      \
-                cvmx_wait(100);                                         \
-        }                                                               \
-    } while (0);                                                        \
-    result;})
-
-/* This macro logically sets a single field in a CSR. It does the sequence
-    read, modify, and write */
-#define USB_SET_FIELD32(address, type, field, value)\
-    do {                                            \
-        type c;                                     \
-        c.u32 = __cvmx_usb_read_csr32(usb, address);\
-        c.s.field = value;                          \
-        __cvmx_usb_write_csr32(usb, address, c.u32);\
-    } while (0)
+	({int result;							    \
+	do {								    \
+		uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \
+			octeon_get_clock_rate() / 1000000;		    \
+		type c;							    \
+		while (1) {						    \
+			c.u32 = __cvmx_usb_read_csr32(usb, address);	    \
+			if (c.s.field op (value)) {			    \
+				result = 0;				    \
+				break;					    \
+			} else if (cvmx_get_cycle() > done) {		    \
+				result = -1;				    \
+				break;					    \
+			} else						    \
+				cvmx_wait(100);				    \
+		}							    \
+	} while (0);							    \
+	result; })
+
+/*
+ * This macro logically sets a single field in a CSR. It does the sequence
+ * read, modify, and write
+ */
+#define USB_SET_FIELD32(address, type, field, value)		\
+	do {							\
+		type c;						\
+		c.u32 = __cvmx_usb_read_csr32(usb, address);	\
+		c.s.field = value;				\
+		__cvmx_usb_write_csr32(usb, address, c.u32);	\
+	} while (0)
 
 /* Returns the IO address to push/pop stuff data from the FIFOs */
 #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000)
@@ -280,145 +316,106 @@ static int octeon_usb_get_clock_type(void)
 	case CVMX_BOARD_TYPE_LANAI2_A:
 	case CVMX_BOARD_TYPE_LANAI2_U:
 	case CVMX_BOARD_TYPE_LANAI2_G:
+	case CVMX_BOARD_TYPE_UBNT_E100:
 		return USB_CLOCK_TYPE_CRYSTAL_12;
 	}
-
-	/* FIXME: This should use CVMX_BOARD_TYPE_UBNT_E100 */
-	if (OCTEON_IS_MODEL(OCTEON_CN50XX) &&
-	    cvmx_sysinfo_get()->board_type == 20002)
-		return USB_CLOCK_TYPE_CRYSTAL_12;
-
 	return USB_CLOCK_TYPE_REF_48;
 }
 
 /**
- * @INTERNAL
  * Read a USB 32bit CSR. It performs the necessary address swizzle
  * for 32bit CSRs and logs the value in a readable format if
  * debugging is on.
  *
- * @param usb     USB block this access is for
- * @param address 64bit address to read
+ * @usb:     USB block this access is for
+ * @address: 64bit address to read
  *
- * @return Result of the read
+ * Returns: Result of the read
  */
-static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb,
-                                             uint64_t address)
+static inline uint32_t __cvmx_usb_read_csr32(struct cvmx_usb_internal_state *usb,
+					     uint64_t address)
 {
-    uint32_t result = cvmx_read64_uint32(address ^ 4);
-    return result;
+	uint32_t result = cvmx_read64_uint32(address ^ 4);
+	return result;
 }
 
 
 /**
- * @INTERNAL
  * Write a USB 32bit CSR. It performs the necessary address
  * swizzle for 32bit CSRs and logs the value in a readable format
  * if debugging is on.
  *
- * @param usb     USB block this access is for
- * @param address 64bit address to write
- * @param value   Value to write
+ * @usb:     USB block this access is for
+ * @address: 64bit address to write
+ * @value:   Value to write
  */
-static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb,
-                                          uint64_t address, uint32_t value)
+static inline void __cvmx_usb_write_csr32(struct cvmx_usb_internal_state *usb,
+					  uint64_t address, uint32_t value)
 {
-    cvmx_write64_uint32(address ^ 4, value);
-    cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
+	cvmx_write64_uint32(address ^ 4, value);
+	cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
 }
 
 
 /**
- * @INTERNAL
  * Read a USB 64bit CSR. It logs the value in a readable format if
  * debugging is on.
  *
- * @param usb     USB block this access is for
- * @param address 64bit address to read
+ * @usb:     USB block this access is for
+ * @address: 64bit address to read
  *
- * @return Result of the read
+ * Returns: Result of the read
  */
-static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb,
-                                             uint64_t address)
+static inline uint64_t __cvmx_usb_read_csr64(struct cvmx_usb_internal_state *usb,
+					     uint64_t address)
 {
-    uint64_t result = cvmx_read64_uint64(address);
-    return result;
+	uint64_t result = cvmx_read64_uint64(address);
+	return result;
 }
 
 
 /**
- * @INTERNAL
  * Write a USB 64bit CSR. It logs the value in a readable format
  * if debugging is on.
  *
- * @param usb     USB block this access is for
- * @param address 64bit address to write
- * @param value   Value to write
- */
-static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb,
-                                          uint64_t address, uint64_t value)
-{
-    cvmx_write64_uint64(address, value);
-}
-
-
-/**
- * @INTERNAL
- * Utility function to convert complete codes into strings
- *
- * @param complete_code
- *               Code to convert
- *
- * @return Human readable string
+ * @usb:     USB block this access is for
+ * @address: 64bit address to write
+ * @value:   Value to write
  */
-static const char *__cvmx_usb_complete_to_string(cvmx_usb_complete_t complete_code)
+static inline void __cvmx_usb_write_csr64(struct cvmx_usb_internal_state *usb,
+					  uint64_t address, uint64_t value)
 {
-    switch (complete_code)
-    {
-        case CVMX_USB_COMPLETE_SUCCESS: return "SUCCESS";
-        case CVMX_USB_COMPLETE_SHORT:   return "SHORT";
-        case CVMX_USB_COMPLETE_CANCEL:  return "CANCEL";
-        case CVMX_USB_COMPLETE_ERROR:   return "ERROR";
-        case CVMX_USB_COMPLETE_STALL:   return "STALL";
-        case CVMX_USB_COMPLETE_XACTERR: return "XACTERR";
-        case CVMX_USB_COMPLETE_DATATGLERR: return "DATATGLERR";
-        case CVMX_USB_COMPLETE_BABBLEERR: return "BABBLEERR";
-        case CVMX_USB_COMPLETE_FRAMEERR: return "FRAMEERR";
-    }
-    return "Update __cvmx_usb_complete_to_string";
+	cvmx_write64_uint64(address, value);
 }
 
-
 /**
- * @INTERNAL
  * Return non zero if this pipe connects to a non HIGH speed
  * device through a high speed hub.
  *
- * @param usb    USB block this access is for
- * @param pipe   Pipe to check
+ * @usb:    USB block this access is for
+ * @pipe:   Pipe to check
  *
- * @return Non zero if we need to do split transactions
+ * Returns: Non zero if we need to do split transactions
  */
-static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe)
+static inline int __cvmx_usb_pipe_needs_split(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe *pipe)
 {
-    return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH));
+	return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH));
 }
 
 
 /**
- * @INTERNAL
  * Trivial utility function to return the correct PID for a pipe
  *
- * @param pipe   pipe to check
+ * @pipe:   pipe to check
  *
- * @return PID for pipe
+ * Returns: PID for pipe
  */
-static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe)
+static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
 {
-    if (pipe->pid_toggle)
-        return 2; /* Data1 */
-    else
-        return 0; /* Data0 */
+	if (pipe->pid_toggle)
+		return 2; /* Data1 */
+	else
+		return 0; /* Data0 */
 }
 
 
@@ -428,127 +425,119 @@ static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe)
  * by this API, a zero will be returned. Most Octeon chips
  * support one usb port, but some support two ports.
  * cvmx_usb_initialize() must be called on independent
- * cvmx_usb_state_t structures.
+ * struct cvmx_usb_state.
  *
- * @return Number of port, zero if usb isn't supported
+ * Returns: Number of port, zero if usb isn't supported
  */
 int cvmx_usb_get_num_ports(void)
 {
-    int arch_ports = 0;
-
-    if (OCTEON_IS_MODEL(OCTEON_CN56XX))
-        arch_ports = 1;
-    else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
-        arch_ports = 2;
-    else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
-        arch_ports = 1;
-    else if (OCTEON_IS_MODEL(OCTEON_CN31XX))
-        arch_ports = 1;
-    else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
-        arch_ports = 1;
-    else
-        arch_ports = 0;
-
-    return arch_ports;
+	int arch_ports = 0;
+
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+		arch_ports = 1;
+	else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
+		arch_ports = 2;
+	else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
+		arch_ports = 1;
+	else if (OCTEON_IS_MODEL(OCTEON_CN31XX))
+		arch_ports = 1;
+	else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
+		arch_ports = 1;
+	else
+		arch_ports = 0;
+
+	return arch_ports;
 }
 
 
 /**
- * @INTERNAL
  * Allocate a usb transaction for use
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
  *
- * @return Transaction or NULL
+ * Returns: Transaction or NULL
  */
-static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_internal_state_t *usb)
+static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(struct cvmx_usb_internal_state *usb)
 {
-    cvmx_usb_transaction_t *t;
-    t = usb->free_transaction_head;
-    if (t) {
-        usb->free_transaction_head = t->next;
-        if (!usb->free_transaction_head)
-            usb->free_transaction_tail = NULL;
-    }
-    else if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO))
-        cvmx_dprintf("%s: Failed to allocate a transaction\n", __FUNCTION__);
-    if (t) {
-        memset(t, 0, sizeof(*t));
-        t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE;
-    }
-    return t;
+	struct cvmx_usb_transaction *t;
+	t = usb->free_transaction_head;
+	if (t) {
+		usb->free_transaction_head = t->next;
+		if (!usb->free_transaction_head)
+			usb->free_transaction_tail = NULL;
+	}
+	if (t) {
+		memset(t, 0, sizeof(*t));
+		t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE;
+	}
+	return t;
 }
 
 
 /**
- * @INTERNAL
  * Free a usb transaction
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param transaction
- *               Transaction to free
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @transaction:
+ *		 Transaction to free
  */
-static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb,
-                                        cvmx_usb_transaction_t *transaction)
+static inline void __cvmx_usb_free_transaction(struct cvmx_usb_internal_state *usb,
+					       struct cvmx_usb_transaction *transaction)
 {
-    transaction->flags = 0;
-    transaction->prev = NULL;
-    transaction->next = NULL;
-    if (usb->free_transaction_tail)
-        usb->free_transaction_tail->next = transaction;
-    else
-        usb->free_transaction_head = transaction;
-    usb->free_transaction_tail = transaction;
+	transaction->flags = 0;
+	transaction->prev = NULL;
+	transaction->next = NULL;
+	if (usb->free_transaction_tail)
+		usb->free_transaction_tail->next = transaction;
+	else
+		usb->free_transaction_head = transaction;
+	usb->free_transaction_tail = transaction;
 }
 
 
 /**
- * @INTERNAL
  * Add a pipe to the tail of a list
- * @param list   List to add pipe to
- * @param pipe   Pipe to add
+ * @list:   List to add pipe to
+ * @pipe:   Pipe to add
  */
-static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe)
+static inline void __cvmx_usb_append_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe)
 {
-    pipe->next = NULL;
-    pipe->prev = list->tail;
-    if (list->tail)
-        list->tail->next = pipe;
-    else
-        list->head = pipe;
-    list->tail = pipe;
+	pipe->next = NULL;
+	pipe->prev = list->tail;
+	if (list->tail)
+		list->tail->next = pipe;
+	else
+		list->head = pipe;
+	list->tail = pipe;
 }
 
 
 /**
- * @INTERNAL
  * Remove a pipe from a list
- * @param list   List to remove pipe from
- * @param pipe   Pipe to remove
+ * @list:   List to remove pipe from
+ * @pipe:   Pipe to remove
  */
-static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe)
+static inline void __cvmx_usb_remove_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe)
 {
-    if (list->head == pipe) {
-        list->head = pipe->next;
-        pipe->next = NULL;
-        if (list->head)
-            list->head->prev = NULL;
-        else
-            list->tail = NULL;
-    }
-    else if (list->tail == pipe) {
-        list->tail = pipe->prev;
-        list->tail->next = NULL;
-        pipe->prev = NULL;
-    }
-    else {
-        pipe->prev->next = pipe->next;
-        pipe->next->prev = pipe->prev;
-        pipe->prev = NULL;
-        pipe->next = NULL;
-    }
+	if (list->head == pipe) {
+		list->head = pipe->next;
+		pipe->next = NULL;
+		if (list->head)
+			list->head->prev = NULL;
+		else
+			list->tail = NULL;
+	} else if (list->tail == pipe) {
+		list->tail = pipe->prev;
+		list->tail->next = NULL;
+		pipe->prev = NULL;
+	} else {
+		pipe->prev->next = pipe->next;
+		pipe->next->prev = pipe->prev;
+		pipe->prev = NULL;
+		pipe->next = NULL;
+	}
 }
 
 
@@ -557,302 +546,332 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p
  * other access to the Octeon USB port is made. The port starts
  * off in the disabled state.
  *
- * @param state  Pointer to an empty cvmx_usb_state_t structure
- *               that will be populated by the initialize call.
- *               This structure is then passed to all other USB
- *               functions.
- * @param usb_port_number
- *               Which Octeon USB port to initialize.
- * @param flags  Flags to control hardware initialization. See
- *               cvmx_usb_initialize_flags_t for the flag
- *               definitions. Some flags are mandatory.
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * @state:	 Pointer to an empty struct cvmx_usb_state
+ *		 that will be populated by the initialize call.
+ *		 This structure is then passed to all other USB
+ *		 functions.
+ * @usb_port_number:
+ *		 Which Octeon USB port to initialize.
+ * @flags:	 Flags to control hardware initialization. See
+ *		 enum cvmx_usb_initialize_flags for the flag
+ *		 definitions. Some flags are mandatory.
+ *
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state,
-                                      int usb_port_number,
-                                      cvmx_usb_initialize_flags_t flags)
+int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
+			enum cvmx_usb_initialize_flags flags)
 {
-    cvmx_usbnx_clk_ctl_t usbn_clk_ctl;
-    cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    usb->init_flags = flags;
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", usb_port_number);
-    CVMX_USB_LOG_PARAM("0x%x", flags);
-
-    /* Make sure that state is large enough to store the internal state */
-    if (sizeof(*state) < sizeof(*usb))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    /* At first allow 0-1 for the usb port number */
-    if ((usb_port_number < 0) || (usb_port_number > 1))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    /* For all chips except 52XX there is only one port */
-    if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    /* Try to determine clock type automatically */
-    if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI |
-                  CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) {
-        if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12)
-            flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;  /* Only 12 MHZ crystals are supported */
-        else
-            flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
-    }
-
-    if (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
-        /* Check for auto ref clock frequency */
-        if (!(flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK))
-            switch (octeon_usb_get_clock_type()) {
-                case USB_CLOCK_TYPE_REF_12:
-                    flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
-                    break;
-                case USB_CLOCK_TYPE_REF_24:
-                    flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
-                    break;
-                case USB_CLOCK_TYPE_REF_48:
-                    flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
-                    break;
-                default:
-                    CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-                    break;
-            }
-    }
-
-    memset(usb, 0, sizeof(usb));
-    usb->init_flags = flags;
-
-    /* Initialize the USB state structure */
-    {
-        int i;
-        usb->index = usb_port_number;
-
-        /* Initialize the transaction double linked list */
-        usb->free_transaction_head = NULL;
-        usb->free_transaction_tail = NULL;
-        for (i=0; i<MAX_TRANSACTIONS; i++)
-            __cvmx_usb_free_transaction(usb, usb->transaction + i);
-        for (i=0; i<MAX_PIPES; i++)
-            __cvmx_usb_append_pipe(&usb->free_pipes, usb->pipe + i);
-    }
-
-    /* Power On Reset and PHY Initialization */
-
-    /* 1. Wait for DCOK to assert (nothing to do) */
-    /* 2a. Write USBN0/1_CLK_CTL[POR] = 1 and
-        USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 */
-    usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
-    usbn_clk_ctl.s.por = 1;
-    usbn_clk_ctl.s.hrst = 0;
-    usbn_clk_ctl.s.prst = 0;
-    usbn_clk_ctl.s.hclk_rst = 0;
-    usbn_clk_ctl.s.enable = 0;
-    /* 2b. Select the USB reference clock/crystal parameters by writing
-        appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] */
-    if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
-        /* The USB port uses 12/24/48MHz 2.5V board clock
-            source at USB_XO. USB_XI should be tied to GND.
-            Most Octeon evaluation boards require this setting */
-        if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
-            usbn_clk_ctl.cn31xx.p_rclk  = 1; /* From CN31XX,CN30XX manual */
-            usbn_clk_ctl.cn31xx.p_xenbn = 0;
-        }
-        else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
-            usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */
-        else
-            usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */
-
-        switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
-            case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
-                usbn_clk_ctl.s.p_c_sel = 0;
-                break;
-            case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:
-                usbn_clk_ctl.s.p_c_sel = 1;
-                break;
-            case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:
-                usbn_clk_ctl.s.p_c_sel = 2;
-                break;
-        }
-    }
-    else {
-        /* The USB port uses a 12MHz crystal as clock source
-            at USB_XO and USB_XI */
-        if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
-            usbn_clk_ctl.cn31xx.p_rclk  = 1; /* From CN31XX,CN30XX manual */
-            usbn_clk_ctl.cn31xx.p_xenbn = 1;
-        }
-        else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
-            usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */
-        else
-            usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */
-
-        usbn_clk_ctl.s.p_c_sel = 0;
-    }
-    /* 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and
-        setting USBN0/1_CLK_CTL[ENABLE] = 1.  Divide the core clock down such
-        that USB is as close as possible to 125Mhz */
-    {
-        int divisor = (octeon_get_clock_rate()+125000000-1)/125000000;
-        if (divisor < 4)  /* Lower than 4 doesn't seem to work properly */
-            divisor = 4;
-        usbn_clk_ctl.s.divide = divisor;
-        usbn_clk_ctl.s.divide2 = 0;
-    }
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */
-    usbn_clk_ctl.s.hclk_rst = 1;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    /* 2e.  Wait 64 core-clock cycles for HCLK to stabilize */
-    cvmx_wait(64);
-    /* 3. Program the power-on reset field in the USBN clock-control register:
-        USBN_CLK_CTL[POR] = 0 */
-    usbn_clk_ctl.s.por = 0;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    /* 4. Wait 1 ms for PHY clock to start */
-    cvmx_wait_usec(1000);
-    /* 5. Program the Reset input from automatic test equipment field in the
-        USBP control and status register: USBN_USBP_CTL_STATUS[ATE_RESET] = 1 */
-    usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index));
-    usbn_usbp_ctl_status.s.ate_reset = 1;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-                           usbn_usbp_ctl_status.u64);
-    /* 6. Wait 10 cycles */
-    cvmx_wait(10);
-    /* 7. Clear ATE_RESET field in the USBN clock-control register:
-        USBN_USBP_CTL_STATUS[ATE_RESET] = 0 */
-    usbn_usbp_ctl_status.s.ate_reset = 0;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-                           usbn_usbp_ctl_status.u64);
-    /* 8. Program the PHY reset field in the USBN clock-control register:
-        USBN_CLK_CTL[PRST] = 1 */
-    usbn_clk_ctl.s.prst = 1;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    /* 9. Program the USBP control and status register to select host or
-        device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for
-        device */
-    usbn_usbp_ctl_status.s.hst_mode = 0;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-                           usbn_usbp_ctl_status.u64);
-    /* 10. Wait 1 us */
-    cvmx_wait_usec(1);
-    /* 11. Program the hreset_n field in the USBN clock-control register:
-        USBN_CLK_CTL[HRST] = 1 */
-    usbn_clk_ctl.s.hrst = 1;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    /* 12. Proceed to USB core initialization */
-    usbn_clk_ctl.s.enable = 1;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    cvmx_wait_usec(1);
-
-    /* USB Core Initialization */
-
-    /* 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to
-        determine USB core configuration parameters. */
-    /* Nothing needed */
-    /* 2. Program the following fields in the global AHB configuration
-        register (USBC_GAHBCFG)
-        DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode
-        Burst length, USBC_GAHBCFG[HBSTLEN] = 0
-        Nonperiodic TxFIFO empty level (slave mode only),
-        USBC_GAHBCFG[NPTXFEMPLVL]
-        Periodic TxFIFO empty level (slave mode only),
-        USBC_GAHBCFG[PTXFEMPLVL]
-        Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 */
-    {
-        cvmx_usbcx_gahbcfg_t usbcx_gahbcfg;
-        /* Due to an errata, CN31XX doesn't support DMA */
-        if (OCTEON_IS_MODEL(OCTEON_CN31XX))
-            usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
-        usbcx_gahbcfg.u32 = 0;
-        usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
-        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-            usb->idle_hardware_channels = 0x1;  /* Only use one channel with non DMA */
-        else if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
-            usb->idle_hardware_channels = 0xf7; /* CN5XXX have an errata with channel 3 */
-        else
-            usb->idle_hardware_channels = 0xff;
-        usbcx_gahbcfg.s.hbstlen = 0;
-        usbcx_gahbcfg.s.nptxfemplvl = 1;
-        usbcx_gahbcfg.s.ptxfemplvl = 1;
-        usbcx_gahbcfg.s.glblintrmsk = 1;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
-                               usbcx_gahbcfg.u32);
-    }
-    /* 3. Program the following fields in USBC_GUSBCFG register.
-        HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0
-        ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0
-        USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5
-        PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 */
-    {
-        cvmx_usbcx_gusbcfg_t usbcx_gusbcfg;
-        usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index));
-        usbcx_gusbcfg.s.toutcal = 0;
-        usbcx_gusbcfg.s.ddrsel = 0;
-        usbcx_gusbcfg.s.usbtrdtim = 0x5;
-        usbcx_gusbcfg.s.phylpwrclksel = 0;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
-                               usbcx_gusbcfg.u32);
-    }
-    /* 4. The software must unmask the following bits in the USBC_GINTMSK
-        register.
-        OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1
-        Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 */
-    {
-        cvmx_usbcx_gintmsk_t usbcx_gintmsk;
-        int channel;
-
-        usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index));
-        usbcx_gintmsk.s.otgintmsk = 1;
-        usbcx_gintmsk.s.modemismsk = 1;
-        usbcx_gintmsk.s.hchintmsk = 1;
-        usbcx_gintmsk.s.sofmsk = 0;
-        /* We need RX FIFO interrupts if we don't have DMA */
-        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-            usbcx_gintmsk.s.rxflvlmsk = 1;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
-                               usbcx_gintmsk.u32);
-
-        /* Disable all channel interrupts. We'll enable them per channel later */
-        for (channel=0; channel<8; channel++)
-            __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
-    }
-
-    {
-        /* Host Port Initialization */
-        if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO))
-            cvmx_dprintf("%s: USB%d is in host mode\n", __FUNCTION__, usb->index);
-
-        /* 1. Program the host-port interrupt-mask field to unmask,
-            USBC_GINTMSK[PRTINT] = 1 */
-        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t,
-                        prtintmsk, 1);
-        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t,
-                        disconnintmsk, 1);
-        /* 2. Program the USBC_HCFG register to select full-speed host or
-            high-speed host. */
-        {
-            cvmx_usbcx_hcfg_t usbcx_hcfg;
-            usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index));
-            usbcx_hcfg.s.fslssupp = 0;
-            usbcx_hcfg.s.fslspclksel = 0;
-            __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32);
-        }
-        /* 3. Program the port power bit to drive VBUS on the USB,
-            USBC_HPRT[PRTPWR] = 1 */
-        USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtpwr, 1);
-
-        /* Steps 4-15 from the manual are done later in the port enable */
-    }
-
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+	union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	usb->init_flags = flags;
+
+	/* Make sure that state is large enough to store the internal state */
+	if (sizeof(*state) < sizeof(*usb))
+		return -EINVAL;
+	/* At first allow 0-1 for the usb port number */
+	if ((usb_port_number < 0) || (usb_port_number > 1))
+		return -EINVAL;
+	/* For all chips except 52XX there is only one port */
+	if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0))
+		return -EINVAL;
+	/* Try to determine clock type automatically */
+	if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI |
+		      CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) {
+		if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12)
+			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;  /* Only 12 MHZ crystals are supported */
+		else
+			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
+	}
+
+	if (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
+		/* Check for auto ref clock frequency */
+		if (!(flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK))
+			switch (octeon_usb_get_clock_type()) {
+			case USB_CLOCK_TYPE_REF_12:
+				flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
+				break;
+			case USB_CLOCK_TYPE_REF_24:
+				flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
+				break;
+			case USB_CLOCK_TYPE_REF_48:
+				flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
+				break;
+			default:
+				return -EINVAL;
+				break;
+			}
+	}
+
+	memset(usb, 0, sizeof(usb));
+	usb->init_flags = flags;
+
+	/* Initialize the USB state structure */
+	{
+		int i;
+		usb->index = usb_port_number;
+
+		/* Initialize the transaction double linked list */
+		usb->free_transaction_head = NULL;
+		usb->free_transaction_tail = NULL;
+		for (i = 0; i < MAX_TRANSACTIONS; i++)
+			__cvmx_usb_free_transaction(usb, usb->transaction + i);
+		for (i = 0; i < MAX_PIPES; i++)
+			__cvmx_usb_append_pipe(&usb->free_pipes, usb->pipe + i);
+	}
+
+	/*
+	 * Power On Reset and PHY Initialization
+	 *
+	 * 1. Wait for DCOK to assert (nothing to do)
+	 *
+	 * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and
+	 *     USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0
+	 */
+	usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
+	usbn_clk_ctl.s.por = 1;
+	usbn_clk_ctl.s.hrst = 0;
+	usbn_clk_ctl.s.prst = 0;
+	usbn_clk_ctl.s.hclk_rst = 0;
+	usbn_clk_ctl.s.enable = 0;
+	/*
+	 * 2b. Select the USB reference clock/crystal parameters by writing
+	 *     appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON]
+	 */
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
+		/*
+		 * The USB port uses 12/24/48MHz 2.5V board clock
+		 * source at USB_XO. USB_XI should be tied to GND.
+		 * Most Octeon evaluation boards require this setting
+		 */
+		if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
+			usbn_clk_ctl.cn31xx.p_rclk  = 1; /* From CN31XX,CN30XX manual */
+			usbn_clk_ctl.cn31xx.p_xenbn = 0;
+		} else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
+			usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */
+		else
+			usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */
+
+		switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
+		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
+			usbn_clk_ctl.s.p_c_sel = 0;
+			break;
+		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:
+			usbn_clk_ctl.s.p_c_sel = 1;
+			break;
+		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:
+			usbn_clk_ctl.s.p_c_sel = 2;
+			break;
+		}
+	} else {
+		/*
+		 * The USB port uses a 12MHz crystal as clock source
+		 * at USB_XO and USB_XI
+		 */
+		if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
+			usbn_clk_ctl.cn31xx.p_rclk  = 1; /* From CN31XX,CN30XX manual */
+			usbn_clk_ctl.cn31xx.p_xenbn = 1;
+		} else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
+			usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */
+		else
+			usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */
+
+		usbn_clk_ctl.s.p_c_sel = 0;
+	}
+	/*
+	 * 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and
+	 *     setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down
+	 *     such that USB is as close as possible to 125Mhz
+	 */
+	{
+		int divisor = (octeon_get_clock_rate()+125000000-1)/125000000;
+		if (divisor < 4)  /* Lower than 4 doesn't seem to work properly */
+			divisor = 4;
+		usbn_clk_ctl.s.divide = divisor;
+		usbn_clk_ctl.s.divide2 = 0;
+	}
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */
+	usbn_clk_ctl.s.hclk_rst = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 2e.  Wait 64 core-clock cycles for HCLK to stabilize */
+	cvmx_wait(64);
+	/*
+	 * 3. Program the power-on reset field in the USBN clock-control
+	 *    register:
+	 *    USBN_CLK_CTL[POR] = 0
+	 */
+	usbn_clk_ctl.s.por = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 4. Wait 1 ms for PHY clock to start */
+	mdelay(1);
+	/*
+	 * 5. Program the Reset input from automatic test equipment field in the
+	 *    USBP control and status register:
+	 *    USBN_USBP_CTL_STATUS[ATE_RESET] = 1
+	 */
+	usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index));
+	usbn_usbp_ctl_status.s.ate_reset = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+			       usbn_usbp_ctl_status.u64);
+	/* 6. Wait 10 cycles */
+	cvmx_wait(10);
+	/*
+	 * 7. Clear ATE_RESET field in the USBN clock-control register:
+	 *    USBN_USBP_CTL_STATUS[ATE_RESET] = 0
+	 */
+	usbn_usbp_ctl_status.s.ate_reset = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+			       usbn_usbp_ctl_status.u64);
+	/*
+	 * 8. Program the PHY reset field in the USBN clock-control register:
+	 *    USBN_CLK_CTL[PRST] = 1
+	 */
+	usbn_clk_ctl.s.prst = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/*
+	 * 9. Program the USBP control and status register to select host or
+	 *    device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for
+	 *    device
+	 */
+	usbn_usbp_ctl_status.s.hst_mode = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+			       usbn_usbp_ctl_status.u64);
+	/* 10. Wait 1 us */
+	udelay(1);
+	/*
+	 * 11. Program the hreset_n field in the USBN clock-control register:
+	 *     USBN_CLK_CTL[HRST] = 1
+	 */
+	usbn_clk_ctl.s.hrst = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 12. Proceed to USB core initialization */
+	usbn_clk_ctl.s.enable = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	udelay(1);
+
+	/*
+	 * USB Core Initialization
+	 *
+	 * 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to
+	 *    determine USB core configuration parameters.
+	 *
+	 *    Nothing needed
+	 *
+	 * 2. Program the following fields in the global AHB configuration
+	 *    register (USBC_GAHBCFG)
+	 *    DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode
+	 *    Burst length, USBC_GAHBCFG[HBSTLEN] = 0
+	 *    Nonperiodic TxFIFO empty level (slave mode only),
+	 *    USBC_GAHBCFG[NPTXFEMPLVL]
+	 *    Periodic TxFIFO empty level (slave mode only),
+	 *    USBC_GAHBCFG[PTXFEMPLVL]
+	 *    Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1
+	 */
+	{
+		union cvmx_usbcx_gahbcfg usbcx_gahbcfg;
+		/* Due to an errata, CN31XX doesn't support DMA */
+		if (OCTEON_IS_MODEL(OCTEON_CN31XX))
+			usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
+		usbcx_gahbcfg.u32 = 0;
+		usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			usb->idle_hardware_channels = 0x1;  /* Only use one channel with non DMA */
+		else if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
+			usb->idle_hardware_channels = 0xf7; /* CN5XXX have an errata with channel 3 */
+		else
+			usb->idle_hardware_channels = 0xff;
+		usbcx_gahbcfg.s.hbstlen = 0;
+		usbcx_gahbcfg.s.nptxfemplvl = 1;
+		usbcx_gahbcfg.s.ptxfemplvl = 1;
+		usbcx_gahbcfg.s.glblintrmsk = 1;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
+				       usbcx_gahbcfg.u32);
+	}
+	/*
+	 * 3. Program the following fields in USBC_GUSBCFG register.
+	 *    HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0
+	 *    ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0
+	 *    USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5
+	 *    PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0
+	 */
+	{
+		union cvmx_usbcx_gusbcfg usbcx_gusbcfg;
+		usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index));
+		usbcx_gusbcfg.s.toutcal = 0;
+		usbcx_gusbcfg.s.ddrsel = 0;
+		usbcx_gusbcfg.s.usbtrdtim = 0x5;
+		usbcx_gusbcfg.s.phylpwrclksel = 0;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
+				       usbcx_gusbcfg.u32);
+	}
+	/*
+	 * 4. The software must unmask the following bits in the USBC_GINTMSK
+	 *    register.
+	 *    OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1
+	 *    Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1
+	 */
+	{
+		union cvmx_usbcx_gintmsk usbcx_gintmsk;
+		int channel;
+
+		usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index));
+		usbcx_gintmsk.s.otgintmsk = 1;
+		usbcx_gintmsk.s.modemismsk = 1;
+		usbcx_gintmsk.s.hchintmsk = 1;
+		usbcx_gintmsk.s.sofmsk = 0;
+		/* We need RX FIFO interrupts if we don't have DMA */
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			usbcx_gintmsk.s.rxflvlmsk = 1;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
+				       usbcx_gintmsk.u32);
+
+		/* Disable all channel interrupts. We'll enable them per channel later */
+		for (channel = 0; channel < 8; channel++)
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
+	}
+
+	{
+		/*
+		 * Host Port Initialization
+		 *
+		 * 1. Program the host-port interrupt-mask field to unmask,
+		 *    USBC_GINTMSK[PRTINT] = 1
+		 */
+		USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk,
+				prtintmsk, 1);
+		USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk,
+				disconnintmsk, 1);
+		/*
+		 * 2. Program the USBC_HCFG register to select full-speed host
+		 *    or high-speed host.
+		 */
+		{
+			union cvmx_usbcx_hcfg usbcx_hcfg;
+			usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index));
+			usbcx_hcfg.s.fslssupp = 0;
+			usbcx_hcfg.s.fslspclksel = 0;
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32);
+		}
+		/*
+		 * 3. Program the port power bit to drive VBUS on the USB,
+		 *    USBC_HPRT[PRTPWR] = 1
+		 */
+		USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtpwr, 1);
+
+		/*
+		 * Steps 4-15 from the manual are done later in the port enable
+		 */
+	}
+
+	return 0;
 }
 
 
@@ -861,38 +880,34 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state,
  * The port should be disabled with all pipes closed when this
  * function is called.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
+ * @state: USB device state populated by
+ *	   cvmx_usb_initialize().
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state)
+int cvmx_usb_shutdown(struct cvmx_usb_state *state)
 {
-    cvmx_usbnx_clk_ctl_t usbn_clk_ctl;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-
-    /* Make sure all pipes are closed */
-    if (usb->idle_pipes.head ||
-        usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head ||
-        usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head ||
-        usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head ||
-        usb->active_pipes[CVMX_USB_TRANSFER_BULK].head)
-        CVMX_USB_RETURN(CVMX_USB_BUSY);
-
-    /* Disable the clocks and put them in power on reset */
-    usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
-    usbn_clk_ctl.s.enable = 1;
-    usbn_clk_ctl.s.por = 1;
-    usbn_clk_ctl.s.hclk_rst = 1;
-    usbn_clk_ctl.s.prst = 0;
-    usbn_clk_ctl.s.hrst = 0;
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                           usbn_clk_ctl.u64);
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	/* Make sure all pipes are closed */
+	if (usb->idle_pipes.head ||
+		usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head ||
+		usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head ||
+		usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head ||
+		usb->active_pipes[CVMX_USB_TRANSFER_BULK].head)
+		return -EBUSY;
+
+	/* Disable the clocks and put them in power on reset */
+	usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
+	usbn_clk_ctl.s.enable = 1;
+	usbn_clk_ctl.s.por = 1;
+	usbn_clk_ctl.s.hclk_rst = 1;
+	usbn_clk_ctl.s.prst = 0;
+	usbn_clk_ctl.s.hrst = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	return 0;
 }
 
 
@@ -900,96 +915,91 @@ cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state)
  * Enable a USB port. After this call succeeds, the USB port is
  * online and servicing requests.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
+ * @state: USB device state populated by
+ *	   cvmx_usb_initialize().
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state)
+int cvmx_usb_enable(struct cvmx_usb_state *state)
 {
-    cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-
-    usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-
-    /* If the port is already enabled the just return. We don't need to do
-        anything */
-    if (usb->usbcx_hprt.s.prtena)
-        CVMX_USB_RETURN(CVMX_USB_SUCCESS);
-
-    /* If there is nothing plugged into the port then fail immediately */
-    if (!usb->usbcx_hprt.s.prtconnsts) {
-        if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO))
-            cvmx_dprintf("%s: USB%d Nothing plugged into the port\n", __FUNCTION__, usb->index);
-        CVMX_USB_RETURN(CVMX_USB_TIMEOUT);
-    }
-
-    /* Program the port reset bit to start the reset process */
-    USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 1);
-
-    /* Wait at least 50ms (high speed), or 10ms (full speed) for the reset
-        process to complete. */
-    cvmx_wait_usec(50000);
-
-    /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */
-    USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 0);
-
-    /* Wait for the USBC_HPRT[PRTENA]. */
-    if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t,
-                              prtena, ==, 1, 100000)) {
-        if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO))
-            cvmx_dprintf("%s: Timeout waiting for the port to finish reset\n",
-                         __FUNCTION__);
-        CVMX_USB_RETURN(CVMX_USB_TIMEOUT);
-    }
-
-    /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */
-    usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-    if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO))
-        cvmx_dprintf("%s: USB%d is in %s speed mode\n", __FUNCTION__, usb->index,
-                     (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH) ? "high" :
-                     (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_FULL) ? "full" :
-                     "low");
-
-    usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index));
-
-    /* 13. Program the USBC_GRXFSIZ register to select the size of the receive
-        FIFO (25%). */
-    USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz_t,
-                    rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4);
-    /* 14. Program the USBC_GNPTXFSIZ register to select the size and the
-        start address of the non- periodic transmit FIFO for nonperiodic
-        transactions (50%). */
-    {
-        cvmx_usbcx_gnptxfsiz_t siz;
-        siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index));
-        siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
-        siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32);
-    }
-    /* 15. Program the USBC_HPTXFSIZ register to select the size and start
-        address of the periodic transmit FIFO for periodic transactions (25%). */
-    {
-        cvmx_usbcx_hptxfsiz_t siz;
-        siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index));
-        siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
-        siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32);
-    }
-    /* Flush all FIFOs */
-    USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfnum, 0x10);
-    USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfflsh, 1);
-    CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t,
-                          txfflsh, ==, 0, 100);
-    USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, rxfflsh, 1);
-    CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t,
-                          rxfflsh, ==, 0, 100);
-
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+
+	/*
+	 * If the port is already enabled the just return. We don't need to do
+	 * anything
+	 */
+	if (usb->usbcx_hprt.s.prtena)
+		return 0;
+
+	/* If there is nothing plugged into the port then fail immediately */
+	if (!usb->usbcx_hprt.s.prtconnsts) {
+		return -ETIMEDOUT;
+	}
+
+	/* Program the port reset bit to start the reset process */
+	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 1);
+
+	/*
+	 * Wait at least 50ms (high speed), or 10ms (full speed) for the reset
+	 * process to complete.
+	 */
+	mdelay(50);
+
+	/* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */
+	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 0);
+
+	/* Wait for the USBC_HPRT[PRTENA]. */
+	if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt,
+				  prtena, ==, 1, 100000))
+		return -ETIMEDOUT;
+
+	/* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */
+	usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+	usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index));
+
+	/*
+	 * 13. Program the USBC_GRXFSIZ register to select the size of the
+	 *     receive FIFO (25%).
+	 */
+	USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), union cvmx_usbcx_grxfsiz,
+			rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4);
+	/*
+	 * 14. Program the USBC_GNPTXFSIZ register to select the size and the
+	 *     start address of the non- periodic transmit FIFO for nonperiodic
+	 *     transactions (50%).
+	 */
+	{
+		union cvmx_usbcx_gnptxfsiz siz;
+		siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index));
+		siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
+		siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32);
+	}
+	/*
+	 * 15. Program the USBC_HPTXFSIZ register to select the size and start
+	 *     address of the periodic transmit FIFO for periodic transactions
+	 *     (25%).
+	 */
+	{
+		union cvmx_usbcx_hptxfsiz siz;
+		siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index));
+		siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
+		siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32);
+	}
+	/* Flush all FIFOs */
+	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfnum, 0x10);
+	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfflsh, 1);
+	CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl,
+			      txfflsh, ==, 0, 100);
+	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, rxfflsh, 1);
+	CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl,
+			      rxfflsh, ==, 0, 100);
+
+	return 0;
 }
 
 
@@ -999,22 +1009,18 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state)
  * Transactions in process will fail and call their
  * associated callbacks.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
+ * @state: USB device state populated by
+ *	   cvmx_usb_initialize().
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state)
+int cvmx_usb_disable(struct cvmx_usb_state *state)
 {
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
 
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-
-    /* Disable the port */
-    USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1);
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	/* Disable the port */
+	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtena, 1);
+	return 0;
 }
 
 
@@ -1027,40 +1033,28 @@ cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state)
  * on the last call to cvmx_usb_set_status(). In order to clear
  * them, you must update the status through cvmx_usb_set_status().
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
+ * @state: USB device state populated by
+ *	   cvmx_usb_initialize().
  *
- * @return Port status information
+ * Returns: Port status information
  */
-cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state)
+struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state)
 {
-    cvmx_usbcx_hprt_t usbc_hprt;
-    cvmx_usb_port_status_t result;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    memset(&result, 0, sizeof(result));
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-
-    usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-    result.port_enabled = usbc_hprt.s.prtena;
-    result.port_over_current = usbc_hprt.s.prtovrcurract;
-    result.port_powered = usbc_hprt.s.prtpwr;
-    result.port_speed = usbc_hprt.s.prtspd;
-    result.connected = usbc_hprt.s.prtconnsts;
-    result.connect_change = (result.connected != usb->port_status.connected);
-
-    if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS))
-        cvmx_dprintf("%*s%s: returned port enabled=%d, over_current=%d, powered=%d, speed=%d, connected=%d, connect_change=%d\n",
-                     2*(--usb->indent), "", __FUNCTION__,
-                     result.port_enabled,
-                     result.port_over_current,
-                     result.port_powered,
-                     result.port_speed,
-                     result.connected,
-                     result.connect_change);
-    return result;
+	union cvmx_usbcx_hprt usbc_hprt;
+	struct cvmx_usb_port_status result;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	memset(&result, 0, sizeof(result));
+
+	usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+	result.port_enabled = usbc_hprt.s.prtena;
+	result.port_over_current = usbc_hprt.s.prtovrcurract;
+	result.port_powered = usbc_hprt.s.prtpwr;
+	result.port_speed = usbc_hprt.s.prtspd;
+	result.connected = usbc_hprt.s.prtconnsts;
+	result.connect_change = (result.connected != usb->port_status.connected);
+
+	return result;
 }
 
 
@@ -1071,54 +1065,50 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state)
  * status passed to this function is not used. No fields can be
  * changed through this call.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param port_status
- *               Port status to set, most like returned by cvmx_usb_get_status()
+ * @state:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @port_status:
+ *		 Port status to set, most like returned by cvmx_usb_get_status()
  */
-void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status)
+void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status)
 {
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    usb->port_status = port_status;
-    CVMX_USB_RETURN_NOTHING();
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+	usb->port_status = port_status;
+	return;
 }
 
 
 /**
- * @INTERNAL
  * Convert a USB transaction into a handle
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param transaction
- *               Transaction to get handle for
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @transaction:
+ *		 Transaction to get handle for
  *
- * @return Handle
+ * Returns: Handle
  */
-static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb,
-                                        cvmx_usb_transaction_t *transaction)
+static inline int __cvmx_usb_get_submit_handle(struct cvmx_usb_internal_state *usb,
+					       struct cvmx_usb_transaction *transaction)
 {
-    return ((unsigned long)transaction - (unsigned long)usb->transaction) /
-            sizeof(*transaction);
+	return ((unsigned long)transaction - (unsigned long)usb->transaction) /
+			sizeof(*transaction);
 }
 
 
 /**
- * @INTERNAL
  * Convert a USB pipe into a handle
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe   Pipe to get handle for
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @pipe:	 Pipe to get handle for
  *
- * @return Handle
+ * Returns: Handle
  */
-static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb,
-                                        cvmx_usb_pipe_t *pipe)
+static inline int __cvmx_usb_get_pipe_handle(struct cvmx_usb_internal_state *usb,
+					     struct cvmx_usb_pipe *pipe)
 {
-    return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe);
+	return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe);
 }
 
 
@@ -1127,197 +1117,182 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb,
  * must be opened before data can be transferred between a device
  * and Octeon.
  *
- * @param state      USB device state populated by
- *                   cvmx_usb_initialize().
- * @param flags      Optional pipe flags defined in
- *                   cvmx_usb_pipe_flags_t.
- * @param device_addr
- *                   USB device address to open the pipe to
- *                   (0-127).
- * @param endpoint_num
- *                   USB endpoint number to open the pipe to
- *                   (0-15).
- * @param device_speed
- *                   The speed of the device the pipe is going
- *                   to. This must match the device's speed,
- *                   which may be different than the port speed.
- * @param max_packet The maximum packet length the device can
- *                   transmit/receive (low speed=0-8, full
- *                   speed=0-1023, high speed=0-1024). This value
- *                   comes from the standard endpoint descriptor
- *                   field wMaxPacketSize bits <10:0>.
- * @param transfer_type
- *                   The type of transfer this pipe is for.
- * @param transfer_dir
- *                   The direction the pipe is in. This is not
- *                   used for control pipes.
- * @param interval   For ISOCHRONOUS and INTERRUPT transfers,
- *                   this is how often the transfer is scheduled
- *                   for. All other transfers should specify
- *                   zero. The units are in frames (8000/sec at
- *                   high speed, 1000/sec for full speed).
- * @param multi_count
- *                   For high speed devices, this is the maximum
- *                   allowed number of packet per microframe.
- *                   Specify zero for non high speed devices. This
- *                   value comes from the standard endpoint descriptor
- *                   field wMaxPacketSize bits <12:11>.
- * @param hub_device_addr
- *                   Hub device address this device is connected
- *                   to. Devices connected directly to Octeon
- *                   use zero. This is only used when the device
- *                   is full/low speed behind a high speed hub.
- *                   The address will be of the high speed hub,
- *                   not and full speed hubs after it.
- * @param hub_port   Which port on the hub the device is
- *                   connected. Use zero for devices connected
- *                   directly to Octeon. Like hub_device_addr,
- *                   this is only used for full/low speed
- *                   devices behind a high speed hub.
- *
- * @return A non negative value is a pipe handle. Negative
- *         values are failure codes from cvmx_usb_status_t.
+ * @state:	     USB device state populated by
+ *		     cvmx_usb_initialize().
+ * @flags:	     Optional pipe flags defined in
+ *		     enum cvmx_usb_pipe_flags.
+ * @device_addr:
+ *		     USB device address to open the pipe to
+ *		     (0-127).
+ * @endpoint_num:
+ *		     USB endpoint number to open the pipe to
+ *		     (0-15).
+ * @device_speed:
+ *		     The speed of the device the pipe is going
+ *		     to. This must match the device's speed,
+ *		     which may be different than the port speed.
+ * @max_packet:	     The maximum packet length the device can
+ *		     transmit/receive (low speed=0-8, full
+ *		     speed=0-1023, high speed=0-1024). This value
+ *		     comes from the standard endpoint descriptor
+ *		     field wMaxPacketSize bits <10:0>.
+ * @transfer_type:
+ *		     The type of transfer this pipe is for.
+ * @transfer_dir:
+ *		     The direction the pipe is in. This is not
+ *		     used for control pipes.
+ * @interval:	     For ISOCHRONOUS and INTERRUPT transfers,
+ *		     this is how often the transfer is scheduled
+ *		     for. All other transfers should specify
+ *		     zero. The units are in frames (8000/sec at
+ *		     high speed, 1000/sec for full speed).
+ * @multi_count:
+ *		     For high speed devices, this is the maximum
+ *		     allowed number of packet per microframe.
+ *		     Specify zero for non high speed devices. This
+ *		     value comes from the standard endpoint descriptor
+ *		     field wMaxPacketSize bits <12:11>.
+ * @hub_device_addr:
+ *		     Hub device address this device is connected
+ *		     to. Devices connected directly to Octeon
+ *		     use zero. This is only used when the device
+ *		     is full/low speed behind a high speed hub.
+ *		     The address will be of the high speed hub,
+ *		     not and full speed hubs after it.
+ * @hub_port:	     Which port on the hub the device is
+ *		     connected. Use zero for devices connected
+ *		     directly to Octeon. Like hub_device_addr,
+ *		     this is only used for full/low speed
+ *		     devices behind a high speed hub.
+ *
+ * Returns: A non negative value is a pipe handle. Negative
+ *	    values are error codes.
  */
-int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags,
-                       int device_addr, int endpoint_num,
-                       cvmx_usb_speed_t device_speed, int max_packet,
-                       cvmx_usb_transfer_t transfer_type,
-                       cvmx_usb_direction_t transfer_dir, int interval,
-                       int multi_count, int hub_device_addr, int hub_port)
+int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags flags,
+		       int device_addr, int endpoint_num,
+		       enum cvmx_usb_speed device_speed, int max_packet,
+		       enum cvmx_usb_transfer transfer_type,
+		       enum cvmx_usb_direction transfer_dir, int interval,
+		       int multi_count, int hub_device_addr, int hub_port)
 {
-    cvmx_usb_pipe_t *pipe;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("0x%x", flags);
-    CVMX_USB_LOG_PARAM("%d", device_addr);
-    CVMX_USB_LOG_PARAM("%d", endpoint_num);
-    CVMX_USB_LOG_PARAM("%d", device_speed);
-    CVMX_USB_LOG_PARAM("%d", max_packet);
-    CVMX_USB_LOG_PARAM("%d", transfer_type);
-    CVMX_USB_LOG_PARAM("%d", transfer_dir);
-    CVMX_USB_LOG_PARAM("%d", interval);
-    CVMX_USB_LOG_PARAM("%d", multi_count);
-    CVMX_USB_LOG_PARAM("%d", hub_device_addr);
-    CVMX_USB_LOG_PARAM("%d", hub_port);
-
-    if (cvmx_unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(device_speed > CVMX_USB_SPEED_LOW))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((max_packet <= 0) || (max_packet > 1024)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) &&
-        (transfer_dir != CVMX_USB_DIRECTION_IN)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(interval < 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(multi_count < 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((device_speed != CVMX_USB_SPEED_HIGH) &&
-        (multi_count != 0)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    /* Find a free pipe */
-    pipe = usb->free_pipes.head;
-    if (!pipe)
-        CVMX_USB_RETURN(CVMX_USB_NO_MEMORY);
-    __cvmx_usb_remove_pipe(&usb->free_pipes, pipe);
-    pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN;
-    if ((device_speed == CVMX_USB_SPEED_HIGH) &&
-        (transfer_dir == CVMX_USB_DIRECTION_OUT) &&
-        (transfer_type == CVMX_USB_TRANSFER_BULK))
-        pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
-    pipe->device_addr = device_addr;
-    pipe->endpoint_num = endpoint_num;
-    pipe->device_speed = device_speed;
-    pipe->max_packet = max_packet;
-    pipe->transfer_type = transfer_type;
-    pipe->transfer_dir = transfer_dir;
-    /* All pipes use interval to rate limit NAK processing. Force an interval
-        if one wasn't supplied */
-    if (!interval)
-        interval = 1;
-    if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-        pipe->interval = interval*8;
-        /* Force start splits to be schedule on uFrame 0 */
-        pipe->next_tx_frame = ((usb->frame_number+7)&~7) + pipe->interval;
-    }
-    else {
-        pipe->interval = interval;
-        pipe->next_tx_frame = usb->frame_number + pipe->interval;
-    }
-    pipe->multi_count = multi_count;
-    pipe->hub_device_addr = hub_device_addr;
-    pipe->hub_port = hub_port;
-    pipe->pid_toggle = 0;
-    pipe->split_sc_frame = -1;
-    __cvmx_usb_append_pipe(&usb->idle_pipes, pipe);
-
-    /* We don't need to tell the hardware about this pipe yet since
-        it doesn't have any submitted requests */
-
-    CVMX_USB_RETURN(__cvmx_usb_get_pipe_handle(usb, pipe));
+	struct cvmx_usb_pipe *pipe;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS)))
+		return -EINVAL;
+	if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT)))
+		return -EINVAL;
+	if (unlikely(device_speed > CVMX_USB_SPEED_LOW))
+		return -EINVAL;
+	if (unlikely((max_packet <= 0) || (max_packet > 1024)))
+		return -EINVAL;
+	if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT))
+		return -EINVAL;
+	if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) &&
+		(transfer_dir != CVMX_USB_DIRECTION_IN)))
+		return -EINVAL;
+	if (unlikely(interval < 0))
+		return -EINVAL;
+	if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval))
+		return -EINVAL;
+	if (unlikely(multi_count < 0))
+		return -EINVAL;
+	if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) &&
+		(multi_count != 0)))
+		return -EINVAL;
+	if (unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS)))
+		return -EINVAL;
+	if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT)))
+		return -EINVAL;
+
+	/* Find a free pipe */
+	pipe = usb->free_pipes.head;
+	if (!pipe)
+		return -ENOMEM;
+	__cvmx_usb_remove_pipe(&usb->free_pipes, pipe);
+	pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN;
+	if ((device_speed == CVMX_USB_SPEED_HIGH) &&
+		(transfer_dir == CVMX_USB_DIRECTION_OUT) &&
+		(transfer_type == CVMX_USB_TRANSFER_BULK))
+		pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+	pipe->device_addr = device_addr;
+	pipe->endpoint_num = endpoint_num;
+	pipe->device_speed = device_speed;
+	pipe->max_packet = max_packet;
+	pipe->transfer_type = transfer_type;
+	pipe->transfer_dir = transfer_dir;
+	/*
+	 * All pipes use interval to rate limit NAK processing. Force an
+	 * interval if one wasn't supplied
+	 */
+	if (!interval)
+		interval = 1;
+	if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+		pipe->interval = interval*8;
+		/* Force start splits to be schedule on uFrame 0 */
+		pipe->next_tx_frame = ((usb->frame_number+7)&~7) + pipe->interval;
+	} else {
+		pipe->interval = interval;
+		pipe->next_tx_frame = usb->frame_number + pipe->interval;
+	}
+	pipe->multi_count = multi_count;
+	pipe->hub_device_addr = hub_device_addr;
+	pipe->hub_port = hub_port;
+	pipe->pid_toggle = 0;
+	pipe->split_sc_frame = -1;
+	__cvmx_usb_append_pipe(&usb->idle_pipes, pipe);
+
+	/*
+	 * We don't need to tell the hardware about this pipe yet since
+	 * it doesn't have any submitted requests
+	 */
+
+	return __cvmx_usb_get_pipe_handle(usb, pipe);
 }
 
 
 /**
- * @INTERNAL
  * Poll the RX FIFOs and remove data as needed. This function is only used
  * in non DMA mode. It is very important that this function be called quickly
  * enough to prevent FIFO overflow.
  *
- * @param usb     USB device state populated by
- *                cvmx_usb_initialize().
+ * @usb:	USB device state populated by
+ *		cvmx_usb_initialize().
  */
-static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb)
+static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_internal_state *usb)
 {
-    cvmx_usbcx_grxstsph_t rx_status;
-    int channel;
-    int bytes;
-    uint64_t address;
-    uint32_t *ptr;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-
-    rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index));
-    /* Only read data if IN data is there */
-    if (rx_status.s.pktsts != 2)
-        CVMX_USB_RETURN_NOTHING();
-    /* Check if no data is available */
-    if (!rx_status.s.bcnt)
-        CVMX_USB_RETURN_NOTHING();
-
-    channel = rx_status.s.chnum;
-    bytes = rx_status.s.bcnt;
-    if (!bytes)
-        CVMX_USB_RETURN_NOTHING();
-
-    /* Get where the DMA engine would have written this data */
-    address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8);
-    ptr = cvmx_phys_to_ptr(address);
-    __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, address + bytes);
-
-    /* Loop writing the FIFO data for this packet into memory */
-    while (bytes > 0) {
-        *ptr++ = __cvmx_usb_read_csr32(usb, USB_FIFO_ADDRESS(channel, usb->index));
-        bytes -= 4;
-    }
-    CVMX_SYNCW;
-
-    CVMX_USB_RETURN_NOTHING();
+	union cvmx_usbcx_grxstsph rx_status;
+	int channel;
+	int bytes;
+	uint64_t address;
+	uint32_t *ptr;
+
+	rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index));
+	/* Only read data if IN data is there */
+	if (rx_status.s.pktsts != 2)
+		return;
+	/* Check if no data is available */
+	if (!rx_status.s.bcnt)
+		return;
+
+	channel = rx_status.s.chnum;
+	bytes = rx_status.s.bcnt;
+	if (!bytes)
+		return;
+
+	/* Get where the DMA engine would have written this data */
+	address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8);
+	ptr = cvmx_phys_to_ptr(address);
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, address + bytes);
+
+	/* Loop writing the FIFO data for this packet into memory */
+	while (bytes > 0) {
+		*ptr++ = __cvmx_usb_read_csr32(usb, USB_FIFO_ADDRESS(channel, usb->index));
+		bytes -= 4;
+	}
+	CVMX_SYNCW;
+
+	return;
 }
 
 
@@ -1325,1196 +1300,1136 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb)
  * Fill the TX hardware fifo with data out of the software
  * fifos
  *
- * @param usb       USB device state populated by
- *                  cvmx_usb_initialize().
- * @param fifo      Software fifo to use
- * @param available Amount of space in the hardware fifo
+ * @usb:	    USB device state populated by
+ *		    cvmx_usb_initialize().
+ * @fifo:	    Software fifo to use
+ * @available:	    Amount of space in the hardware fifo
  *
- * @return Non zero if the hardware fifo was too small and needs
- *         to be serviced again.
+ * Returns: Non zero if the hardware fifo was too small and needs
+ *	    to be serviced again.
  */
-static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fifo_t *fifo, int available)
+static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_internal_state *usb, struct cvmx_usb_tx_fifo *fifo, int available)
 {
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-    CVMX_USB_LOG_PARAM("%p", fifo);
-    CVMX_USB_LOG_PARAM("%d", available);
-
-    /* We're done either when there isn't anymore space or the software FIFO
-        is empty */
-    while (available && (fifo->head != fifo->tail)) {
-        int i = fifo->tail;
-        const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address);
-        uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, usb->index) ^ 4;
-        int words = available;
-
-        /* Limit the amount of data to waht the SW fifo has */
-        if (fifo->entry[i].size <= available) {
-            words = fifo->entry[i].size;
-            fifo->tail++;
-            if (fifo->tail > MAX_CHANNELS)
-                fifo->tail = 0;
-        }
-
-        /* Update the next locations and counts */
-        available -= words;
-        fifo->entry[i].address += words * 4;
-        fifo->entry[i].size -= words;
-
-        /* Write the HW fifo data. The read every three writes is due
-            to an errata on CN3XXX chips */
-        while (words > 3) {
-            cvmx_write64_uint32(csr_address, *ptr++);
-            cvmx_write64_uint32(csr_address, *ptr++);
-            cvmx_write64_uint32(csr_address, *ptr++);
-            cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
-            words -= 3;
-        }
-        cvmx_write64_uint32(csr_address, *ptr++);
-        if (--words) {
-            cvmx_write64_uint32(csr_address, *ptr++);
-            if (--words)
-                cvmx_write64_uint32(csr_address, *ptr++);
-        }
-        cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
-    }
-    CVMX_USB_RETURN(fifo->head != fifo->tail);
+	/*
+	 * We're done either when there isn't anymore space or the software FIFO
+	 * is empty
+	 */
+	while (available && (fifo->head != fifo->tail)) {
+		int i = fifo->tail;
+		const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address);
+		uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, usb->index) ^ 4;
+		int words = available;
+
+		/* Limit the amount of data to waht the SW fifo has */
+		if (fifo->entry[i].size <= available) {
+			words = fifo->entry[i].size;
+			fifo->tail++;
+			if (fifo->tail > MAX_CHANNELS)
+				fifo->tail = 0;
+		}
+
+		/* Update the next locations and counts */
+		available -= words;
+		fifo->entry[i].address += words * 4;
+		fifo->entry[i].size -= words;
+
+		/*
+		 * Write the HW fifo data. The read every three writes is due
+		 * to an errata on CN3XXX chips
+		 */
+		while (words > 3) {
+			cvmx_write64_uint32(csr_address, *ptr++);
+			cvmx_write64_uint32(csr_address, *ptr++);
+			cvmx_write64_uint32(csr_address, *ptr++);
+			cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
+			words -= 3;
+		}
+		cvmx_write64_uint32(csr_address, *ptr++);
+		if (--words) {
+			cvmx_write64_uint32(csr_address, *ptr++);
+			if (--words)
+				cvmx_write64_uint32(csr_address, *ptr++);
+		}
+		cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
+	}
+	return fifo->head != fifo->tail;
 }
 
 
 /**
  * Check the hardware FIFOs and fill them as needed
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
+ * @usb:	USB device state populated by
+ *		cvmx_usb_initialize().
  */
-static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb)
+static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_internal_state *usb)
 {
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-
-    if (usb->periodic.head != usb->periodic.tail) {
-        cvmx_usbcx_hptxsts_t tx_status;
-        tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index));
-        if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail))
-            USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 1);
-        else
-            USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 0);
-    }
-
-    if (usb->nonperiodic.head != usb->nonperiodic.tail) {
-        cvmx_usbcx_gnptxsts_t tx_status;
-        tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index));
-        if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail))
-            USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 1);
-        else
-            USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 0);
-    }
-
-    CVMX_USB_RETURN_NOTHING();
+	if (usb->periodic.head != usb->periodic.tail) {
+		union cvmx_usbcx_hptxsts tx_status;
+		tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index));
+		if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail))
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 1);
+		else
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 0);
+	}
+
+	if (usb->nonperiodic.head != usb->nonperiodic.tail) {
+		union cvmx_usbcx_gnptxsts tx_status;
+		tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index));
+		if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail))
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 1);
+		else
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 0);
+	}
+
+	return;
 }
 
 
 /**
- * @INTERNAL
  * Fill the TX FIFO with an outgoing packet
  *
- * @param usb     USB device state populated by
- *                cvmx_usb_initialize().
- * @param channel Channel number to get packet from
+ * @usb:	  USB device state populated by
+ *		  cvmx_usb_initialize().
+ * @channel:	  Channel number to get packet from
  */
-static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel)
+static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_internal_state *usb, int channel)
 {
-    cvmx_usbcx_hccharx_t hcchar;
-    cvmx_usbcx_hcspltx_t usbc_hcsplt;
-    cvmx_usbcx_hctsizx_t usbc_hctsiz;
-    cvmx_usb_tx_fifo_t *fifo;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-    CVMX_USB_LOG_PARAM("%d", channel);
-
-    /* We only need to fill data on outbound channels */
-    hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
-    if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT)
-        CVMX_USB_RETURN_NOTHING();
-
-    /* OUT Splits only have data on the start and not the complete */
-    usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index));
-    if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
-        CVMX_USB_RETURN_NOTHING();
-
-    /* Find out how many bytes we need to fill and convert it into 32bit words */
-    usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
-    if (!usbc_hctsiz.s.xfersize)
-        CVMX_USB_RETURN_NOTHING();
-
-    if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) ||
-        (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS))
-        fifo = &usb->periodic;
-    else
-        fifo = &usb->nonperiodic;
-
-    fifo->entry[fifo->head].channel = channel;
-    fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8);
-    fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2;
-    fifo->head++;
-    if (fifo->head > MAX_CHANNELS)
-        fifo->head = 0;
-
-    __cvmx_usb_poll_tx_fifo(usb);
-
-    CVMX_USB_RETURN_NOTHING();
+	union cvmx_usbcx_hccharx hcchar;
+	union cvmx_usbcx_hcspltx usbc_hcsplt;
+	union cvmx_usbcx_hctsizx usbc_hctsiz;
+	struct cvmx_usb_tx_fifo *fifo;
+
+	/* We only need to fill data on outbound channels */
+	hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
+	if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT)
+		return;
+
+	/* OUT Splits only have data on the start and not the complete */
+	usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index));
+	if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
+		return;
+
+	/* Find out how many bytes we need to fill and convert it into 32bit words */
+	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
+	if (!usbc_hctsiz.s.xfersize)
+		return;
+
+	if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) ||
+		(hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS))
+		fifo = &usb->periodic;
+	else
+		fifo = &usb->nonperiodic;
+
+	fifo->entry[fifo->head].channel = channel;
+	fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8);
+	fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2;
+	fifo->head++;
+	if (fifo->head > MAX_CHANNELS)
+		fifo->head = 0;
+
+	__cvmx_usb_poll_tx_fifo(usb);
+
+	return;
 }
 
 /**
- * @INTERNAL
  * Perform channel specific setup for Control transactions. All
  * the generic stuff will already have been done in
  * __cvmx_usb_start_channel()
  *
- * @param usb     USB device state populated by
- *                cvmx_usb_initialize().
- * @param channel Channel to setup
- * @param pipe    Pipe for control transaction
+ * @usb:	  USB device state populated by
+ *		  cvmx_usb_initialize().
+ * @channel:	  Channel to setup
+ * @pipe:	  Pipe for control transaction
  */
-static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb,
-                                             int channel,
-                                             cvmx_usb_pipe_t *pipe)
+static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb,
+					     int channel,
+					     struct cvmx_usb_pipe *pipe)
 {
-    cvmx_usb_transaction_t *transaction = pipe->head;
-    cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header);
-    int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
-    int packets_to_transfer;
-    cvmx_usbcx_hctsizx_t usbc_hctsiz;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-    CVMX_USB_LOG_PARAM("%d", channel);
-    CVMX_USB_LOG_PARAM("%p", pipe);
-
-    usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
-
-    switch (transaction->stage) {
-        case CVMX_USB_STAGE_NON_CONTROL:
-        case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
-            cvmx_dprintf("%s: ERROR - Non control stage\n", __FUNCTION__);
-            break;
-        case CVMX_USB_STAGE_SETUP:
-            usbc_hctsiz.s.pid = 3; /* Setup */
-            bytes_to_transfer = sizeof(*header);
-            /* All Control operations start with a setup going OUT */
-            USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT);
-            /* Setup send the control header instead of the buffer data. The
-                buffer data will be used in the next stage */
-            __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header);
-            break;
-        case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
-            usbc_hctsiz.s.pid = 3; /* Setup */
-            bytes_to_transfer = 0;
-            /* All Control operations start with a setup going OUT */
-            USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT);
-            USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1);
-            break;
-        case CVMX_USB_STAGE_DATA:
-            usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-            if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-                if (header->s.request_type & 0x80)
-                    bytes_to_transfer = 0;
-                else if (bytes_to_transfer > pipe->max_packet)
-                    bytes_to_transfer = pipe->max_packet;
-            }
-            USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                            cvmx_usbcx_hccharx_t, epdir,
-                            ((header->s.request_type & 0x80) ?
-                             CVMX_USB_DIRECTION_IN :
-                             CVMX_USB_DIRECTION_OUT));
-            break;
-        case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
-            usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-            if (!(header->s.request_type & 0x80))
-                bytes_to_transfer = 0;
-            USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                            cvmx_usbcx_hccharx_t, epdir,
-                            ((header->s.request_type & 0x80) ?
-                             CVMX_USB_DIRECTION_IN :
-                             CVMX_USB_DIRECTION_OUT));
-            USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1);
-            break;
-        case CVMX_USB_STAGE_STATUS:
-            usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-            bytes_to_transfer = 0;
-            USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir,
-                            ((header->s.request_type & 0x80) ?
-                             CVMX_USB_DIRECTION_OUT :
-                             CVMX_USB_DIRECTION_IN));
-            break;
-        case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
-            usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-            bytes_to_transfer = 0;
-            USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir,
-                            ((header->s.request_type & 0x80) ?
-                             CVMX_USB_DIRECTION_OUT :
-                             CVMX_USB_DIRECTION_IN));
-            USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1);
-            break;
-    }
-
-    /* Make sure the transfer never exceeds the byte limit of the hardware.
-        Further bytes will be sent as continued transactions */
-    if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
-        /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */
-        bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
-        bytes_to_transfer *= pipe->max_packet;
-    }
-
-    /* Calculate the number of packets to transfer. If the length is zero
-        we still need to transfer one packet */
-    packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
-    if (packets_to_transfer == 0)
-        packets_to_transfer = 1;
-    else if ((packets_to_transfer>1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
-        /* Limit to one packet when not using DMA. Channels must be restarted
-            between every packet for IN transactions, so there is no reason to
-            do multiple packets in a row */
-        packets_to_transfer = 1;
-        bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-    }
-    else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
-        /* Limit the number of packet and data transferred to what the
-            hardware can handle */
-        packets_to_transfer = MAX_TRANSFER_PACKETS;
-        bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-    }
-
-    usbc_hctsiz.s.xfersize = bytes_to_transfer;
-    usbc_hctsiz.s.pktcnt = packets_to_transfer;
-
-    __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
-    CVMX_USB_RETURN_NOTHING();
+	struct cvmx_usb_transaction *transaction = pipe->head;
+	union cvmx_usb_control_header *header =
+		cvmx_phys_to_ptr(transaction->control_header);
+	int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
+	int packets_to_transfer;
+	union cvmx_usbcx_hctsizx usbc_hctsiz;
+
+	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
+
+	switch (transaction->stage) {
+	case CVMX_USB_STAGE_NON_CONTROL:
+	case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
+		cvmx_dprintf("%s: ERROR - Non control stage\n", __FUNCTION__);
+		break;
+	case CVMX_USB_STAGE_SETUP:
+		usbc_hctsiz.s.pid = 3; /* Setup */
+		bytes_to_transfer = sizeof(*header);
+		/* All Control operations start with a setup going OUT */
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT);
+		/*
+		 * Setup send the control header instead of the buffer data. The
+		 * buffer data will be used in the next stage
+		 */
+		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header);
+		break;
+	case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
+		usbc_hctsiz.s.pid = 3; /* Setup */
+		bytes_to_transfer = 0;
+		/* All Control operations start with a setup going OUT */
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT);
+		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
+		break;
+	case CVMX_USB_STAGE_DATA:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			if (header->s.request_type & 0x80)
+				bytes_to_transfer = 0;
+			else if (bytes_to_transfer > pipe->max_packet)
+				bytes_to_transfer = pipe->max_packet;
+		}
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
+				union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_IN :
+					CVMX_USB_DIRECTION_OUT));
+		break;
+	case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		if (!(header->s.request_type & 0x80))
+			bytes_to_transfer = 0;
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
+				union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_IN :
+					CVMX_USB_DIRECTION_OUT));
+		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
+		break;
+	case CVMX_USB_STAGE_STATUS:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		bytes_to_transfer = 0;
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_OUT :
+					CVMX_USB_DIRECTION_IN));
+		break;
+	case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		bytes_to_transfer = 0;
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_OUT :
+					CVMX_USB_DIRECTION_IN));
+		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
+		break;
+	}
+
+	/*
+	 * Make sure the transfer never exceeds the byte limit of the hardware.
+	 * Further bytes will be sent as continued transactions
+	 */
+	if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
+		/* Round MAX_TRANSFER_BYTES to a multiple of out packet size */
+		bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
+		bytes_to_transfer *= pipe->max_packet;
+	}
+
+	/*
+	 * Calculate the number of packets to transfer. If the length is zero
+	 * we still need to transfer one packet
+	 */
+	packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
+	if (packets_to_transfer == 0)
+		packets_to_transfer = 1;
+	else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
+		/*
+		 * Limit to one packet when not using DMA. Channels must be
+		 * restarted between every packet for IN transactions, so there
+		 * is no reason to do multiple packets in a row
+		 */
+		packets_to_transfer = 1;
+		bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+	} else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
+		/*
+		 * Limit the number of packet and data transferred to what the
+		 * hardware can handle
+		 */
+		packets_to_transfer = MAX_TRANSFER_PACKETS;
+		bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+	}
+
+	usbc_hctsiz.s.xfersize = bytes_to_transfer;
+	usbc_hctsiz.s.pktcnt = packets_to_transfer;
+
+	__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
+	return;
 }
 
 
 /**
- * @INTERNAL
  * Start a channel to perform the pipe's head transaction
  *
- * @param usb     USB device state populated by
- *                cvmx_usb_initialize().
- * @param channel Channel to setup
- * @param pipe    Pipe to start
+ * @usb:	  USB device state populated by
+ *		  cvmx_usb_initialize().
+ * @channel:	  Channel to setup
+ * @pipe:	  Pipe to start
  */
-static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb,
-                                     int channel,
-                                     cvmx_usb_pipe_t *pipe)
+static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb,
+				     int channel,
+				     struct cvmx_usb_pipe *pipe)
 {
-    cvmx_usb_transaction_t *transaction = pipe->head;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-    CVMX_USB_LOG_PARAM("%d", channel);
-    CVMX_USB_LOG_PARAM("%p", pipe);
-
-    if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) ||
-        (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS)))
-        cvmx_dprintf("%s: Channel %d started. Pipe %d transaction %d stage %d\n",
-                     __FUNCTION__, channel, __cvmx_usb_get_pipe_handle(usb, pipe),
-                     __cvmx_usb_get_submit_handle(usb, transaction),
-                     transaction->stage);
-
-    /* Make sure all writes to the DMA region get flushed */
-    CVMX_SYNCW;
-
-    /* Attach the channel to the pipe */
-    usb->pipe_for_channel[channel] = pipe;
-    pipe->channel = channel;
-    pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED;
-
-    /* Mark this channel as in use */
-    usb->idle_hardware_channels &= ~(1<<channel);
-
-    /* Enable the channel interrupt bits */
-    {
-        cvmx_usbcx_hcintx_t usbc_hcint;
-        cvmx_usbcx_hcintmskx_t usbc_hcintmsk;
-        cvmx_usbcx_haintmsk_t usbc_haintmsk;
-
-        /* Clear all channel status bits */
-        usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index), usbc_hcint.u32);
-
-        usbc_hcintmsk.u32 = 0;
-        usbc_hcintmsk.s.chhltdmsk = 1;
-        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-            /* Channels need these extra interrupts when we aren't in DMA mode */
-            usbc_hcintmsk.s.datatglerrmsk = 1;
-            usbc_hcintmsk.s.frmovrunmsk = 1;
-            usbc_hcintmsk.s.bblerrmsk = 1;
-            usbc_hcintmsk.s.xacterrmsk = 1;
-            if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-                /* Splits don't generate xfercompl, so we need ACK and NYET */
-                usbc_hcintmsk.s.nyetmsk = 1;
-                usbc_hcintmsk.s.ackmsk = 1;
-            }
-            usbc_hcintmsk.s.nakmsk = 1;
-            usbc_hcintmsk.s.stallmsk = 1;
-            usbc_hcintmsk.s.xfercomplmsk = 1;
-        }
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), usbc_hcintmsk.u32);
-
-        /* Enable the channel interrupt to propagate */
-        usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index));
-        usbc_haintmsk.s.haintmsk |= 1<<channel;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index), usbc_haintmsk.u32);
-    }
-
-    /* Setup the locations the DMA engines use  */
-    {
-        uint64_t dma_address = transaction->buffer + transaction->actual_bytes;
-        if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
-            dma_address = transaction->buffer + transaction->iso_packets[0].offset + transaction->actual_bytes;
-        __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, dma_address);
-        __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, dma_address);
-    }
-
-    /* Setup both the size of the transfer and the SPLIT characteristics */
-    {
-        cvmx_usbcx_hcspltx_t usbc_hcsplt = {.u32 = 0};
-        cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = 0};
-        int packets_to_transfer;
-        int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
-
-        /* ISOCHRONOUS transactions store each individual transfer size in the
-            packet structure, not the global buffer_length */
-        if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
-            bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes;
-
-        /* We need to do split transactions when we are talking to non high
-            speed devices that are behind a high speed hub */
-        if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-            /* On the start split phase (stage is even) record the frame number we
-                will need to send the split complete. We only store the lower two bits
-                since the time ahead can only be two frames */
-            if ((transaction->stage&1) == 0) {
-                if (transaction->type == CVMX_USB_TRANSFER_BULK)
-                    pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f;
-                else
-                    pipe->split_sc_frame = (usb->frame_number + 2) & 0x7f;
-            }
-            else
-                pipe->split_sc_frame = -1;
-
-            usbc_hcsplt.s.spltena = 1;
-            usbc_hcsplt.s.hubaddr = pipe->hub_device_addr;
-            usbc_hcsplt.s.prtaddr = pipe->hub_port;
-            usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE);
-
-            /* SPLIT transactions can only ever transmit one data packet so
-                limit the transfer size to the max packet size */
-            if (bytes_to_transfer > pipe->max_packet)
-                bytes_to_transfer = pipe->max_packet;
-
-            /* ISOCHRONOUS OUT splits are unique in that they limit
-                data transfers to 188 byte chunks representing the
-                begin/middle/end of the data or all */
-            if (!usbc_hcsplt.s.compsplt &&
-                (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
-                (pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
-                /* Clear the split complete frame number as there isn't going
-                    to be a split complete */
-                pipe->split_sc_frame = -1;
-                /* See if we've started this transfer and sent data */
-                if (transaction->actual_bytes == 0) {
-                    /* Nothing sent yet, this is either a begin or the
-                        entire payload */
-                    if (bytes_to_transfer <= 188)
-                        usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */
-                    else
-                        usbc_hcsplt.s.xactpos = 2; /* First part of payload */
-                }
-                else {
-                    /* Continuing the previous data, we must either be
-                        in the middle or at the end */
-                    if (bytes_to_transfer <= 188)
-                        usbc_hcsplt.s.xactpos = 1; /* End of payload */
-                    else
-                        usbc_hcsplt.s.xactpos = 0; /* Middle of payload */
-                }
-                /* Again, the transfer size is limited to 188 bytes */
-                if (bytes_to_transfer > 188)
-                    bytes_to_transfer = 188;
-            }
-        }
-
-        /* Make sure the transfer never exceeds the byte limit of the hardware.
-            Further bytes will be sent as continued transactions */
-        if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
-            /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */
-            bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
-            bytes_to_transfer *= pipe->max_packet;
-        }
-
-        /* Calculate the number of packets to transfer. If the length is zero
-            we still need to transfer one packet */
-        packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
-        if (packets_to_transfer == 0)
-            packets_to_transfer = 1;
-        else if ((packets_to_transfer>1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
-            /* Limit to one packet when not using DMA. Channels must be restarted
-                between every packet for IN transactions, so there is no reason to
-                do multiple packets in a row */
-            packets_to_transfer = 1;
-            bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-        }
-        else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
-            /* Limit the number of packet and data transferred to what the
-                hardware can handle */
-            packets_to_transfer = MAX_TRANSFER_PACKETS;
-            bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-        }
-
-        usbc_hctsiz.s.xfersize = bytes_to_transfer;
-        usbc_hctsiz.s.pktcnt = packets_to_transfer;
-
-        /* Update the DATA0/DATA1 toggle */
-        usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-        /* High speed pipes may need a hardware ping before they start */
-        if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING)
-            usbc_hctsiz.s.dopng = 1;
-
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index), usbc_hcsplt.u32);
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
-    }
-
-    /* Setup the Host Channel Characteristics Register */
-    {
-        cvmx_usbcx_hccharx_t usbc_hcchar = {.u32 = 0};
-
-        /* Set the startframe odd/even properly. This is only used for periodic */
-        usbc_hcchar.s.oddfrm = usb->frame_number&1;
-
-        /* Set the number of back to back packets allowed by this endpoint.
-            Split transactions interpret "ec" as the number of immediate
-            retries of failure. These retries happen too quickly, so we
-            disable these entirely for splits */
-        if (__cvmx_usb_pipe_needs_split(usb, pipe))
-            usbc_hcchar.s.ec = 1;
-        else if (pipe->multi_count < 1)
-            usbc_hcchar.s.ec = 1;
-        else if (pipe->multi_count > 3)
-            usbc_hcchar.s.ec = 3;
-        else
-            usbc_hcchar.s.ec = pipe->multi_count;
-
-        /* Set the rest of the endpoint specific settings */
-        usbc_hcchar.s.devaddr = pipe->device_addr;
-        usbc_hcchar.s.eptype = transaction->type;
-        usbc_hcchar.s.lspddev = (pipe->device_speed == CVMX_USB_SPEED_LOW);
-        usbc_hcchar.s.epdir = pipe->transfer_dir;
-        usbc_hcchar.s.epnum = pipe->endpoint_num;
-        usbc_hcchar.s.mps = pipe->max_packet;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
-    }
-
-    /* Do transaction type specific fixups as needed */
-    switch (transaction->type) {
-        case CVMX_USB_TRANSFER_CONTROL:
-            __cvmx_usb_start_channel_control(usb, channel, pipe);
-            break;
-        case CVMX_USB_TRANSFER_BULK:
-        case CVMX_USB_TRANSFER_INTERRUPT:
-            break;
-        case CVMX_USB_TRANSFER_ISOCHRONOUS:
-            if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
-                /* ISO transactions require different PIDs depending on direction
-                    and how many packets are needed */
-                if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
-                    if (pipe->multi_count < 2) /* Need DATA0 */
-                        USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 0);
-                    else /* Need MDATA */
-                        USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 3);
-                }
-            }
-            break;
-    }
-    {
-        cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))};
-        transaction->xfersize = usbc_hctsiz.s.xfersize;
-        transaction->pktcnt = usbc_hctsiz.s.pktcnt;
-    }
-    /* Remeber when we start a split transaction */
-    if (__cvmx_usb_pipe_needs_split(usb, pipe))
-        usb->active_split = transaction;
-    USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, chena, 1);
-    if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-        __cvmx_usb_fill_tx_fifo(usb, channel);
-    CVMX_USB_RETURN_NOTHING();
+	struct cvmx_usb_transaction *transaction = pipe->head;
+
+	/* Make sure all writes to the DMA region get flushed */
+	CVMX_SYNCW;
+
+	/* Attach the channel to the pipe */
+	usb->pipe_for_channel[channel] = pipe;
+	pipe->channel = channel;
+	pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED;
+
+	/* Mark this channel as in use */
+	usb->idle_hardware_channels &= ~(1<<channel);
+
+	/* Enable the channel interrupt bits */
+	{
+		union cvmx_usbcx_hcintx usbc_hcint;
+		union cvmx_usbcx_hcintmskx usbc_hcintmsk;
+		union cvmx_usbcx_haintmsk usbc_haintmsk;
+
+		/* Clear all channel status bits */
+		usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index), usbc_hcint.u32);
+
+		usbc_hcintmsk.u32 = 0;
+		usbc_hcintmsk.s.chhltdmsk = 1;
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
+			/* Channels need these extra interrupts when we aren't in DMA mode */
+			usbc_hcintmsk.s.datatglerrmsk = 1;
+			usbc_hcintmsk.s.frmovrunmsk = 1;
+			usbc_hcintmsk.s.bblerrmsk = 1;
+			usbc_hcintmsk.s.xacterrmsk = 1;
+			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+				/* Splits don't generate xfercompl, so we need ACK and NYET */
+				usbc_hcintmsk.s.nyetmsk = 1;
+				usbc_hcintmsk.s.ackmsk = 1;
+			}
+			usbc_hcintmsk.s.nakmsk = 1;
+			usbc_hcintmsk.s.stallmsk = 1;
+			usbc_hcintmsk.s.xfercomplmsk = 1;
+		}
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), usbc_hcintmsk.u32);
+
+		/* Enable the channel interrupt to propagate */
+		usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index));
+		usbc_haintmsk.s.haintmsk |= 1<<channel;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index), usbc_haintmsk.u32);
+	}
+
+	/* Setup the locations the DMA engines use  */
+	{
+		uint64_t dma_address = transaction->buffer + transaction->actual_bytes;
+		if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
+			dma_address = transaction->buffer + transaction->iso_packets[0].offset + transaction->actual_bytes;
+		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, dma_address);
+		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, dma_address);
+	}
+
+	/* Setup both the size of the transfer and the SPLIT characteristics */
+	{
+		union cvmx_usbcx_hcspltx usbc_hcsplt = {.u32 = 0};
+		union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = 0};
+		int packets_to_transfer;
+		int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
+
+		/*
+		 * ISOCHRONOUS transactions store each individual transfer size
+		 * in the packet structure, not the global buffer_length
+		 */
+		if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
+			bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes;
+
+		/*
+		 * We need to do split transactions when we are talking to non
+		 * high speed devices that are behind a high speed hub
+		 */
+		if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			/*
+			 * On the start split phase (stage is even) record the
+			 * frame number we will need to send the split complete.
+			 * We only store the lower two bits since the time ahead
+			 * can only be two frames
+			 */
+			if ((transaction->stage&1) == 0) {
+				if (transaction->type == CVMX_USB_TRANSFER_BULK)
+					pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f;
+				else
+					pipe->split_sc_frame = (usb->frame_number + 2) & 0x7f;
+			} else
+				pipe->split_sc_frame = -1;
+
+			usbc_hcsplt.s.spltena = 1;
+			usbc_hcsplt.s.hubaddr = pipe->hub_device_addr;
+			usbc_hcsplt.s.prtaddr = pipe->hub_port;
+			usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE);
+
+			/*
+			 * SPLIT transactions can only ever transmit one data
+			 * packet so limit the transfer size to the max packet
+			 * size
+			 */
+			if (bytes_to_transfer > pipe->max_packet)
+				bytes_to_transfer = pipe->max_packet;
+
+			/*
+			 * ISOCHRONOUS OUT splits are unique in that they limit
+			 * data transfers to 188 byte chunks representing the
+			 * begin/middle/end of the data or all
+			 */
+			if (!usbc_hcsplt.s.compsplt &&
+				(pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
+				(pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
+				/*
+				 * Clear the split complete frame number as
+				 * there isn't going to be a split complete
+				 */
+				pipe->split_sc_frame = -1;
+				/*
+				 * See if we've started this transfer and sent
+				 * data
+				 */
+				if (transaction->actual_bytes == 0) {
+					/*
+					 * Nothing sent yet, this is either a
+					 * begin or the entire payload
+					 */
+					if (bytes_to_transfer <= 188)
+						usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */
+					else
+						usbc_hcsplt.s.xactpos = 2; /* First part of payload */
+				} else {
+					/*
+					 * Continuing the previous data, we must
+					 * either be in the middle or at the end
+					 */
+					if (bytes_to_transfer <= 188)
+						usbc_hcsplt.s.xactpos = 1; /* End of payload */
+					else
+						usbc_hcsplt.s.xactpos = 0; /* Middle of payload */
+				}
+				/*
+				 * Again, the transfer size is limited to 188
+				 * bytes
+				 */
+				if (bytes_to_transfer > 188)
+					bytes_to_transfer = 188;
+			}
+		}
+
+		/*
+		 * Make sure the transfer never exceeds the byte limit of the
+		 * hardware. Further bytes will be sent as continued
+		 * transactions
+		 */
+		if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
+			/*
+			 * Round MAX_TRANSFER_BYTES to a multiple of out packet
+			 * size
+			 */
+			bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
+			bytes_to_transfer *= pipe->max_packet;
+		}
+
+		/*
+		 * Calculate the number of packets to transfer. If the length is
+		 * zero we still need to transfer one packet
+		 */
+		packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
+		if (packets_to_transfer == 0)
+			packets_to_transfer = 1;
+		else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
+			/*
+			 * Limit to one packet when not using DMA. Channels must
+			 * be restarted between every packet for IN
+			 * transactions, so there is no reason to do multiple
+			 * packets in a row
+			 */
+			packets_to_transfer = 1;
+			bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+		} else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
+			/*
+			 * Limit the number of packet and data transferred to
+			 * what the hardware can handle
+			 */
+			packets_to_transfer = MAX_TRANSFER_PACKETS;
+			bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+		}
+
+		usbc_hctsiz.s.xfersize = bytes_to_transfer;
+		usbc_hctsiz.s.pktcnt = packets_to_transfer;
+
+		/* Update the DATA0/DATA1 toggle */
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		/*
+		 * High speed pipes may need a hardware ping before they start
+		 */
+		if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING)
+			usbc_hctsiz.s.dopng = 1;
+
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index), usbc_hcsplt.u32);
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
+	}
+
+	/* Setup the Host Channel Characteristics Register */
+	{
+		union cvmx_usbcx_hccharx usbc_hcchar = {.u32 = 0};
+
+		/*
+		 * Set the startframe odd/even properly. This is only used for
+		 * periodic
+		 */
+		usbc_hcchar.s.oddfrm = usb->frame_number&1;
+
+		/*
+		 * Set the number of back to back packets allowed by this
+		 * endpoint. Split transactions interpret "ec" as the number of
+		 * immediate retries of failure. These retries happen too
+		 * quickly, so we disable these entirely for splits
+		 */
+		if (__cvmx_usb_pipe_needs_split(usb, pipe))
+			usbc_hcchar.s.ec = 1;
+		else if (pipe->multi_count < 1)
+			usbc_hcchar.s.ec = 1;
+		else if (pipe->multi_count > 3)
+			usbc_hcchar.s.ec = 3;
+		else
+			usbc_hcchar.s.ec = pipe->multi_count;
+
+		/* Set the rest of the endpoint specific settings */
+		usbc_hcchar.s.devaddr = pipe->device_addr;
+		usbc_hcchar.s.eptype = transaction->type;
+		usbc_hcchar.s.lspddev = (pipe->device_speed == CVMX_USB_SPEED_LOW);
+		usbc_hcchar.s.epdir = pipe->transfer_dir;
+		usbc_hcchar.s.epnum = pipe->endpoint_num;
+		usbc_hcchar.s.mps = pipe->max_packet;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
+	}
+
+	/* Do transaction type specific fixups as needed */
+	switch (transaction->type) {
+	case CVMX_USB_TRANSFER_CONTROL:
+		__cvmx_usb_start_channel_control(usb, channel, pipe);
+		break;
+	case CVMX_USB_TRANSFER_BULK:
+	case CVMX_USB_TRANSFER_INTERRUPT:
+		break;
+	case CVMX_USB_TRANSFER_ISOCHRONOUS:
+		if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			/*
+			 * ISO transactions require different PIDs depending on
+			 * direction and how many packets are needed
+			 */
+			if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
+				if (pipe->multi_count < 2) /* Need DATA0 */
+					USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 0);
+				else /* Need MDATA */
+					USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 3);
+			}
+		}
+		break;
+	}
+	{
+		union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))};
+		transaction->xfersize = usbc_hctsiz.s.xfersize;
+		transaction->pktcnt = usbc_hctsiz.s.pktcnt;
+	}
+	/* Remeber when we start a split transaction */
+	if (__cvmx_usb_pipe_needs_split(usb, pipe))
+		usb->active_split = transaction;
+	USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, chena, 1);
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+		__cvmx_usb_fill_tx_fifo(usb, channel);
+	return;
 }
 
 
 /**
- * @INTERNAL
  * Find a pipe that is ready to be scheduled to hardware.
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param list   Pipe list to search
- * @param current_frame
- *               Frame counter to use as a time reference.
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @list:	 Pipe list to search
+ * @current_frame:
+ *		 Frame counter to use as a time reference.
  *
- * @return Pipe or NULL if none are ready
+ * Returns: Pipe or NULL if none are ready
  */
-static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_list_t *list, uint64_t current_frame)
+static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe_list *list, uint64_t current_frame)
 {
-    cvmx_usb_pipe_t *pipe = list->head;
-    while (pipe) {
-        if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head &&
-            (pipe->next_tx_frame <= current_frame) &&
-            ((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) &&
-            (!usb->active_split || (usb->active_split == pipe->head))) {
-            CVMX_PREFETCH(pipe, 128);
-            CVMX_PREFETCH(pipe->head, 0);
-            return pipe;
-        }
-        pipe = pipe->next;
-    }
-    return NULL;
+	struct cvmx_usb_pipe *pipe = list->head;
+	while (pipe) {
+		if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head &&
+			(pipe->next_tx_frame <= current_frame) &&
+			((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) &&
+			(!usb->active_split || (usb->active_split == pipe->head))) {
+			CVMX_PREFETCH(pipe, 128);
+			CVMX_PREFETCH(pipe->head, 0);
+			return pipe;
+		}
+		pipe = pipe->next;
+	}
+	return NULL;
 }
 
 
 /**
- * @INTERNAL
  * Called whenever a pipe might need to be scheduled to the
  * hardware.
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param is_sof True if this schedule was called on a SOF interrupt.
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @is_sof:	 True if this schedule was called on a SOF interrupt.
  */
-static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof)
+static void __cvmx_usb_schedule(struct cvmx_usb_internal_state *usb, int is_sof)
 {
-    int channel;
-    cvmx_usb_pipe_t *pipe;
-    int need_sof;
-    cvmx_usb_transfer_t ttype;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-
-    if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-        /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */
-        cvmx_usbcx_hfnum_t hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))};
-        cvmx_usbcx_hfir_t hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))};
-        if (hfnum.s.frrem < hfir.s.frint/4)
-            goto done;
-    }
-
-    while (usb->idle_hardware_channels) {
-        /* Find an idle channel */
-        CVMX_CLZ(channel, usb->idle_hardware_channels);
-        channel = 31 - channel;
-        if (cvmx_unlikely(channel > 7)) {
-            if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO))
-                cvmx_dprintf("%s: Idle hardware channels has a channel higher than 7. This is wrong\n", __FUNCTION__);
-            break;
-        }
-
-        /* Find a pipe needing service */
-        pipe = NULL;
-        if (is_sof) {
-            /* Only process periodic pipes on SOF interrupts. This way we are
-                sure that the periodic data is sent in the beginning of the
-                frame */
-            pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number);
-            if (cvmx_likely(!pipe))
-                pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number);
-        }
-        if (cvmx_likely(!pipe)) {
-            pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number);
-            if (cvmx_likely(!pipe))
-                pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number);
-        }
-        if (!pipe)
-            break;
-
-        CVMX_USB_LOG_PARAM("%d", channel);
-        CVMX_USB_LOG_PARAM("%p", pipe);
-
-        if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) ||
-            (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS))) {
-            cvmx_usb_transaction_t *transaction = pipe->head;
-            const cvmx_usb_control_header_t *header = (transaction->control_header) ? cvmx_phys_to_ptr(transaction->control_header) : NULL;
-            const char *dir = (pipe->transfer_dir == CVMX_USB_DIRECTION_IN) ? "IN" : "OUT";
-            const char *type;
-            switch (pipe->transfer_type) {
-                case CVMX_USB_TRANSFER_CONTROL:
-                    type = "SETUP";
-                    dir = (header->s.request_type & 0x80) ? "IN" : "OUT";
-                    break;
-                case CVMX_USB_TRANSFER_ISOCHRONOUS:
-                    type = "ISOCHRONOUS";
-                    break;
-                case CVMX_USB_TRANSFER_BULK:
-                    type = "BULK";
-                    break;
-                default: /* CVMX_USB_TRANSFER_INTERRUPT */
-                    type = "INTERRUPT";
-                    break;
-            }
-            cvmx_dprintf("%s: Starting pipe %d, transaction %d on channel %d. %s %s len=%d header=0x%llx\n",
-                         __FUNCTION__, __cvmx_usb_get_pipe_handle(usb, pipe),
-                         __cvmx_usb_get_submit_handle(usb, transaction),
-                         channel, type, dir,
-                         transaction->buffer_length,
-                         (header) ? (unsigned long long)header->u64 : 0ull);
-        }
-        __cvmx_usb_start_channel(usb, channel, pipe);
-    }
+	int channel;
+	struct cvmx_usb_pipe *pipe;
+	int need_sof;
+	enum cvmx_usb_transfer ttype;
+
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
+		/* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */
+		union cvmx_usbcx_hfnum hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))};
+		union cvmx_usbcx_hfir hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))};
+		if (hfnum.s.frrem < hfir.s.frint/4)
+			goto done;
+	}
+
+	while (usb->idle_hardware_channels) {
+		/* Find an idle channel */
+		CVMX_CLZ(channel, usb->idle_hardware_channels);
+		channel = 31 - channel;
+		if (unlikely(channel > 7))
+			break;
+
+		/* Find a pipe needing service */
+		pipe = NULL;
+		if (is_sof) {
+			/*
+			 * Only process periodic pipes on SOF interrupts. This
+			 * way we are sure that the periodic data is sent in the
+			 * beginning of the frame
+			 */
+			pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number);
+			if (likely(!pipe))
+				pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number);
+		}
+		if (likely(!pipe)) {
+			pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number);
+			if (likely(!pipe))
+				pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number);
+		}
+		if (!pipe)
+			break;
+
+		__cvmx_usb_start_channel(usb, channel, pipe);
+	}
 
 done:
-    /* Only enable SOF interrupts when we have transactions pending in the
-        future that might need to be scheduled */
-    need_sof = 0;
-    for (ttype=CVMX_USB_TRANSFER_CONTROL; ttype<=CVMX_USB_TRANSFER_INTERRUPT; ttype++) {
-        pipe = usb->active_pipes[ttype].head;
-        while (pipe) {
-            if (pipe->next_tx_frame > usb->frame_number) {
-                need_sof = 1;
-                break;
-            }
-            pipe=pipe->next;
-        }
-    }
-    USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, sofmsk, need_sof);
-    CVMX_USB_RETURN_NOTHING();
+	/*
+	 * Only enable SOF interrupts when we have transactions pending in the
+	 * future that might need to be scheduled
+	 */
+	need_sof = 0;
+	for (ttype = CVMX_USB_TRANSFER_CONTROL; ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) {
+		pipe = usb->active_pipes[ttype].head;
+		while (pipe) {
+			if (pipe->next_tx_frame > usb->frame_number) {
+				need_sof = 1;
+				break;
+			}
+			pipe = pipe->next;
+		}
+	}
+	USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, sofmsk, need_sof);
+	return;
 }
 
 
 /**
- * @INTERNAL
  * Call a user's callback for a specific reason.
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe   Pipe the callback is for or NULL
- * @param transaction
- *               Transaction the callback is for or NULL
- * @param reason Reason this callback is being called
- * @param complete_code
- *               Completion code for the transaction, if any
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @pipe:	 Pipe the callback is for or NULL
+ * @transaction:
+ *		 Transaction the callback is for or NULL
+ * @reason:	 Reason this callback is being called
+ * @complete_code:
+ *		 Completion code for the transaction, if any
  */
-static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb,
-                                        cvmx_usb_pipe_t *pipe,
-                                        cvmx_usb_transaction_t *transaction,
-                                        cvmx_usb_callback_t reason,
-                                        cvmx_usb_complete_t complete_code)
+static void __cvmx_usb_perform_callback(struct cvmx_usb_internal_state *usb,
+					struct cvmx_usb_pipe *pipe,
+					struct cvmx_usb_transaction *transaction,
+					enum cvmx_usb_callback reason,
+					enum cvmx_usb_complete complete_code)
 {
-    cvmx_usb_callback_func_t callback = usb->callback[reason];
-    void *user_data = usb->callback_data[reason];
-    int submit_handle = -1;
-    int pipe_handle = -1;
-    int bytes_transferred = 0;
-
-    if (pipe)
-        pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe);
-
-    if (transaction) {
-        submit_handle = __cvmx_usb_get_submit_handle(usb, transaction);
-        bytes_transferred = transaction->actual_bytes;
-        /* Transactions are allowed to override the default callback */
-        if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) {
-            callback = transaction->callback;
-            user_data = transaction->callback_data;
-        }
-    }
-
-    if (!callback)
-        return;
-
-    if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS))
-        cvmx_dprintf("%*s%s: calling callback %p(usb=%p, complete_code=%s, "
-                     "pipe_handle=%d, submit_handle=%d, bytes_transferred=%d, user_data=%p);\n",
-                     2*usb->indent, "", __FUNCTION__, callback, usb,
-                     __cvmx_usb_complete_to_string(complete_code),
-                     pipe_handle, submit_handle, bytes_transferred, user_data);
-
-    callback((cvmx_usb_state_t *)usb, reason, complete_code, pipe_handle, submit_handle,
-             bytes_transferred, user_data);
-
-    if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS))
-        cvmx_dprintf("%*s%s: callback %p complete\n", 2*usb->indent, "",
-                      __FUNCTION__, callback);
+	cvmx_usb_callback_func_t callback = usb->callback[reason];
+	void *user_data = usb->callback_data[reason];
+	int submit_handle = -1;
+	int pipe_handle = -1;
+	int bytes_transferred = 0;
+
+	if (pipe)
+		pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe);
+
+	if (transaction) {
+		submit_handle = __cvmx_usb_get_submit_handle(usb, transaction);
+		bytes_transferred = transaction->actual_bytes;
+		/* Transactions are allowed to override the default callback */
+		if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) {
+			callback = transaction->callback;
+			user_data = transaction->callback_data;
+		}
+	}
+
+	if (!callback)
+		return;
+
+	callback((struct cvmx_usb_state *)usb, reason, complete_code, pipe_handle, submit_handle,
+		 bytes_transferred, user_data);
 }
 
 
 /**
- * @INTERNAL
  * Signal the completion of a transaction and free it. The
  * transaction will be removed from the pipe transaction list.
  *
- * @param usb    USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe   Pipe the transaction is on
- * @param transaction
- *               Transaction that completed
- * @param complete_code
- *               Completion code
+ * @usb:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @pipe:	 Pipe the transaction is on
+ * @transaction:
+ *		 Transaction that completed
+ * @complete_code:
+ *		 Completion code
  */
-static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t * usb,
-                                        cvmx_usb_pipe_t *pipe,
-                                        cvmx_usb_transaction_t *transaction,
-                                        cvmx_usb_complete_t complete_code)
+static void __cvmx_usb_perform_complete(struct cvmx_usb_internal_state *usb,
+					struct cvmx_usb_pipe *pipe,
+					struct cvmx_usb_transaction *transaction,
+					enum cvmx_usb_complete complete_code)
 {
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-    CVMX_USB_LOG_PARAM("%p", pipe);
-    CVMX_USB_LOG_PARAM("%p", transaction);
-    CVMX_USB_LOG_PARAM("%d", complete_code);
-
-    /* If this was a split then clear our split in progress marker */
-    if (usb->active_split == transaction)
-        usb->active_split = NULL;
-
-    /* Isochronous transactions need extra processing as they might not be done
-        after a single data transfer */
-    if (cvmx_unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
-        /* Update the number of bytes transferred in this ISO packet */
-        transaction->iso_packets[0].length = transaction->actual_bytes;
-        transaction->iso_packets[0].status = complete_code;
-
-        /* If there are more ISOs pending and we succeeded, schedule the next
-            one */
-        if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) {
-            transaction->actual_bytes = 0;      /* No bytes transferred for this packet as of yet */
-            transaction->iso_number_packets--;  /* One less ISO waiting to transfer */
-            transaction->iso_packets++;         /* Increment to the next location in our packet array */
-            transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
-            goto done;
-        }
-    }
-
-    /* Remove the transaction from the pipe list */
-    if (transaction->next)
-        transaction->next->prev = transaction->prev;
-    else
-        pipe->tail = transaction->prev;
-    if (transaction->prev)
-        transaction->prev->next = transaction->next;
-    else
-        pipe->head = transaction->next;
-    if (!pipe->head) {
-        __cvmx_usb_remove_pipe(usb->active_pipes + pipe->transfer_type, pipe);
-        __cvmx_usb_append_pipe(&usb->idle_pipes, pipe);
-
-    }
-    __cvmx_usb_perform_callback(usb, pipe, transaction,
-                                CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
-                                complete_code);
-    __cvmx_usb_free_transaction(usb, transaction);
+	/* If this was a split then clear our split in progress marker */
+	if (usb->active_split == transaction)
+		usb->active_split = NULL;
+
+	/*
+	 * Isochronous transactions need extra processing as they might not be
+	 * done after a single data transfer
+	 */
+	if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
+		/* Update the number of bytes transferred in this ISO packet */
+		transaction->iso_packets[0].length = transaction->actual_bytes;
+		transaction->iso_packets[0].status = complete_code;
+
+		/*
+		 * If there are more ISOs pending and we succeeded, schedule the
+		 * next one
+		 */
+		if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) {
+			transaction->actual_bytes = 0;	   /* No bytes transferred for this packet as of yet */
+			transaction->iso_number_packets--; /* One less ISO waiting to transfer */
+			transaction->iso_packets++;	   /* Increment to the next location in our packet array */
+			transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
+			goto done;
+		}
+	}
+
+	/* Remove the transaction from the pipe list */
+	if (transaction->next)
+		transaction->next->prev = transaction->prev;
+	else
+		pipe->tail = transaction->prev;
+	if (transaction->prev)
+		transaction->prev->next = transaction->next;
+	else
+		pipe->head = transaction->next;
+	if (!pipe->head) {
+		__cvmx_usb_remove_pipe(usb->active_pipes + pipe->transfer_type, pipe);
+		__cvmx_usb_append_pipe(&usb->idle_pipes, pipe);
+
+	}
+	__cvmx_usb_perform_callback(usb, pipe, transaction,
+				    CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
+				    complete_code);
+	__cvmx_usb_free_transaction(usb, transaction);
 done:
-    CVMX_USB_RETURN_NOTHING();
+	return;
 }
 
 
 /**
- * @INTERNAL
  * Submit a usb transaction to a pipe. Called for all types
  * of transactions.
  *
- * @param usb
- * @param pipe_handle
- *                  Which pipe to submit to. Will be validated in this function.
- * @param type      Transaction type
- * @param flags     Flags for the transaction
- * @param buffer    User buffer for the transaction
- * @param buffer_length
- *                  User buffer's length in bytes
- * @param control_header
- *                  For control transactions, the 8 byte standard header
- * @param iso_start_frame
- *                  For ISO transactions, the start frame
- * @param iso_number_packets
- *                  For ISO, the number of packet in the transaction.
- * @param iso_packets
- *                  A description of each ISO packet
- * @param callback  User callback to call when the transaction completes
- * @param user_data User's data for the callback
- *
- * @return Submit handle or negative on failure. Matches the result
- *         in the external API.
+ * @usb:
+ * @pipe_handle:
+ *		    Which pipe to submit to. Will be validated in this function.
+ * @type:	    Transaction type
+ * @flags:	    Flags for the transaction
+ * @buffer:	    User buffer for the transaction
+ * @buffer_length:
+ *		    User buffer's length in bytes
+ * @control_header:
+ *		    For control transactions, the 8 byte standard header
+ * @iso_start_frame:
+ *		    For ISO transactions, the start frame
+ * @iso_number_packets:
+ *		    For ISO, the number of packet in the transaction.
+ * @iso_packets:
+ *		    A description of each ISO packet
+ * @callback:	    User callback to call when the transaction completes
+ * @user_data:	    User's data for the callback
+ *
+ * Returns: Submit handle or negative on failure. Matches the result
+ *	    in the external API.
  */
-static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb,
-                                         int pipe_handle,
-                                         cvmx_usb_transfer_t type,
-                                         int flags,
-                                         uint64_t buffer,
-                                         int buffer_length,
-                                         uint64_t control_header,
-                                         int iso_start_frame,
-                                         int iso_number_packets,
-                                         cvmx_usb_iso_packet_t *iso_packets,
-                                         cvmx_usb_callback_func_t callback,
-                                         void *user_data)
+static int __cvmx_usb_submit_transaction(struct cvmx_usb_internal_state *usb,
+					 int pipe_handle,
+					 enum cvmx_usb_transfer type,
+					 int flags,
+					 uint64_t buffer,
+					 int buffer_length,
+					 uint64_t control_header,
+					 int iso_start_frame,
+					 int iso_number_packets,
+					 struct cvmx_usb_iso_packet *iso_packets,
+					 cvmx_usb_callback_func_t callback,
+					 void *user_data)
 {
-    int submit_handle;
-    cvmx_usb_transaction_t *transaction;
-    cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle;
-
-    CVMX_USB_LOG_CALLED();
-    if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    /* Fail if the pipe isn't open */
-    if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(pipe->transfer_type != type))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    transaction = __cvmx_usb_alloc_transaction(usb);
-    if (cvmx_unlikely(!transaction))
-        CVMX_USB_RETURN(CVMX_USB_NO_MEMORY);
-
-    transaction->type = type;
-    transaction->flags |= flags;
-    transaction->buffer = buffer;
-    transaction->buffer_length = buffer_length;
-    transaction->control_header = control_header;
-    transaction->iso_start_frame = iso_start_frame; // FIXME: This is not used, implement it
-    transaction->iso_number_packets = iso_number_packets;
-    transaction->iso_packets = iso_packets;
-    transaction->callback = callback;
-    transaction->callback_data = user_data;
-    if (transaction->type == CVMX_USB_TRANSFER_CONTROL)
-        transaction->stage = CVMX_USB_STAGE_SETUP;
-    else
-        transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
-
-    transaction->next = NULL;
-    if (pipe->tail) {
-        transaction->prev = pipe->tail;
-        transaction->prev->next = transaction;
-    }
-    else {
-        if (pipe->next_tx_frame < usb->frame_number)
-            pipe->next_tx_frame = usb->frame_number + pipe->interval -
-                (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-        transaction->prev = NULL;
-        pipe->head = transaction;
-        __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe);
-        __cvmx_usb_append_pipe(usb->active_pipes + pipe->transfer_type, pipe);
-    }
-    pipe->tail = transaction;
-
-    submit_handle = __cvmx_usb_get_submit_handle(usb, transaction);
-
-    /* We may need to schedule the pipe if this was the head of the pipe */
-    if (!transaction->prev)
-        __cvmx_usb_schedule(usb, 0);
-
-    CVMX_USB_RETURN(submit_handle);
+	int submit_handle;
+	struct cvmx_usb_transaction *transaction;
+	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
+
+	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
+		return -EINVAL;
+	/* Fail if the pipe isn't open */
+	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
+		return -EINVAL;
+	if (unlikely(pipe->transfer_type != type))
+		return -EINVAL;
+
+	transaction = __cvmx_usb_alloc_transaction(usb);
+	if (unlikely(!transaction))
+		return -ENOMEM;
+
+	transaction->type = type;
+	transaction->flags |= flags;
+	transaction->buffer = buffer;
+	transaction->buffer_length = buffer_length;
+	transaction->control_header = control_header;
+	transaction->iso_start_frame = iso_start_frame; // FIXME: This is not used, implement it
+	transaction->iso_number_packets = iso_number_packets;
+	transaction->iso_packets = iso_packets;
+	transaction->callback = callback;
+	transaction->callback_data = user_data;
+	if (transaction->type == CVMX_USB_TRANSFER_CONTROL)
+		transaction->stage = CVMX_USB_STAGE_SETUP;
+	else
+		transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
+
+	transaction->next = NULL;
+	if (pipe->tail) {
+		transaction->prev = pipe->tail;
+		transaction->prev->next = transaction;
+	} else {
+		if (pipe->next_tx_frame < usb->frame_number)
+			pipe->next_tx_frame = usb->frame_number + pipe->interval -
+				(usb->frame_number - pipe->next_tx_frame) % pipe->interval;
+		transaction->prev = NULL;
+		pipe->head = transaction;
+		__cvmx_usb_remove_pipe(&usb->idle_pipes, pipe);
+		__cvmx_usb_append_pipe(usb->active_pipes + pipe->transfer_type, pipe);
+	}
+	pipe->tail = transaction;
+
+	submit_handle = __cvmx_usb_get_submit_handle(usb, transaction);
+
+	/* We may need to schedule the pipe if this was the head of the pipe */
+	if (!transaction->prev)
+		__cvmx_usb_schedule(usb, 0);
+
+	return submit_handle;
 }
 
 
 /**
  * Call to submit a USB Bulk transfer to a pipe.
  *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
+ * @state:	    USB device state populated by
+ *		    cvmx_usb_initialize().
+ * @pipe_handle:
+ *		    Handle to the pipe for the transfer.
+ * @buffer:	    Physical address of the data buffer in
+ *		    memory. Note that this is NOT A POINTER, but
+ *		    the full 64bit physical address of the
+ *		    buffer. This may be zero if buffer_length is
+ *		    zero.
+ * @buffer_length:
+ *		    Length of buffer in bytes.
+ * @callback:	    Function to call when this transaction
+ *		    completes. If the return value of this
+ *		    function isn't an error, then this function
+ *		    is guaranteed to be called when the
+ *		    transaction completes. If this parameter is
+ *		    NULL, then the generic callback registered
+ *		    through cvmx_usb_register_callback is
+ *		    called. If both are NULL, then there is no
+ *		    way to know when a transaction completes.
+ * @user_data:	    User supplied data returned when the
+ *		    callback is called. This is only used if
+ *		    callback in not NULL.
+ *
+ * Returns: A submitted transaction handle or negative on
+ *	    failure. Negative values are error codes.
  */
-int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle,
-                                uint64_t buffer, int buffer_length,
-                                cvmx_usb_callback_func_t callback,
-                                void *user_data)
+int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle,
+			 uint64_t buffer, int buffer_length,
+			 cvmx_usb_callback_func_t callback,
+			 void *user_data)
 {
-    int submit_handle;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer);
-    CVMX_USB_LOG_PARAM("%d", buffer_length);
-
-    /* Pipe handle checking is done later in a common place */
-    if (cvmx_unlikely(!buffer))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(buffer_length < 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-                                         CVMX_USB_TRANSFER_BULK,
-                                         0, /* flags */
-                                         buffer,
-                                         buffer_length,
-                                         0, /* control_header */
-                                         0, /* iso_start_frame */
-                                         0, /* iso_number_packets */
-                                         NULL, /* iso_packets */
-                                         callback,
-                                         user_data);
-    CVMX_USB_RETURN(submit_handle);
+	int submit_handle;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	/* Pipe handle checking is done later in a common place */
+	if (unlikely(!buffer))
+		return -EINVAL;
+	if (unlikely(buffer_length < 0))
+		return -EINVAL;
+
+	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
+						      CVMX_USB_TRANSFER_BULK,
+						      0, /* flags */
+						      buffer,
+						      buffer_length,
+						      0, /* control_header */
+						      0, /* iso_start_frame */
+						      0, /* iso_number_packets */
+						      NULL, /* iso_packets */
+						      callback,
+						      user_data);
+	return submit_handle;
 }
 
 
 /**
  * Call to submit a USB Interrupt transfer to a pipe.
  *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
+ * @state:	    USB device state populated by
+ *		    cvmx_usb_initialize().
+ * @pipe_handle:
+ *		    Handle to the pipe for the transfer.
+ * @buffer:	    Physical address of the data buffer in
+ *		    memory. Note that this is NOT A POINTER, but
+ *		    the full 64bit physical address of the
+ *		    buffer. This may be zero if buffer_length is
+ *		    zero.
+ * @buffer_length:
+ *		    Length of buffer in bytes.
+ * @callback:	    Function to call when this transaction
+ *		    completes. If the return value of this
+ *		    function isn't an error, then this function
+ *		    is guaranteed to be called when the
+ *		    transaction completes. If this parameter is
+ *		    NULL, then the generic callback registered
+ *		    through cvmx_usb_register_callback is
+ *		    called. If both are NULL, then there is no
+ *		    way to know when a transaction completes.
+ * @user_data:	    User supplied data returned when the
+ *		    callback is called. This is only used if
+ *		    callback in not NULL.
+ *
+ * Returns: A submitted transaction handle or negative on
+ *	    failure. Negative values are error codes.
  */
-int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle,
-                              uint64_t buffer, int buffer_length,
-                              cvmx_usb_callback_func_t callback,
-                              void *user_data)
+int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle,
+			      uint64_t buffer, int buffer_length,
+			      cvmx_usb_callback_func_t callback,
+			      void *user_data)
 {
-    int submit_handle;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer);
-    CVMX_USB_LOG_PARAM("%d", buffer_length);
-
-    /* Pipe handle checking is done later in a common place */
-    if (cvmx_unlikely(!buffer))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(buffer_length < 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-                                         CVMX_USB_TRANSFER_INTERRUPT,
-                                         0, /* flags */
-                                         buffer,
-                                         buffer_length,
-                                         0, /* control_header */
-                                         0, /* iso_start_frame */
-                                         0, /* iso_number_packets */
-                                         NULL, /* iso_packets */
-                                         callback,
-                                         user_data);
-    CVMX_USB_RETURN(submit_handle);
+	int submit_handle;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	/* Pipe handle checking is done later in a common place */
+	if (unlikely(!buffer))
+		return -EINVAL;
+	if (unlikely(buffer_length < 0))
+		return -EINVAL;
+
+	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
+						      CVMX_USB_TRANSFER_INTERRUPT,
+						      0, /* flags */
+						      buffer,
+						      buffer_length,
+						      0, /* control_header */
+						      0, /* iso_start_frame */
+						      0, /* iso_number_packets */
+						      NULL, /* iso_packets */
+						      callback,
+						      user_data);
+	return submit_handle;
 }
 
 
 /**
  * Call to submit a USB Control transfer to a pipe.
  *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param control_header
- *                  USB 8 byte control header physical address.
- *                  Note that this is NOT A POINTER, but the
- *                  full 64bit physical address of the buffer.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
+ * @state:	    USB device state populated by
+ *		    cvmx_usb_initialize().
+ * @pipe_handle:
+ *		    Handle to the pipe for the transfer.
+ * @control_header:
+ *		    USB 8 byte control header physical address.
+ *		    Note that this is NOT A POINTER, but the
+ *		    full 64bit physical address of the buffer.
+ * @buffer:	    Physical address of the data buffer in
+ *		    memory. Note that this is NOT A POINTER, but
+ *		    the full 64bit physical address of the
+ *		    buffer. This may be zero if buffer_length is
+ *		    zero.
+ * @buffer_length:
+ *		    Length of buffer in bytes.
+ * @callback:	    Function to call when this transaction
+ *		    completes. If the return value of this
+ *		    function isn't an error, then this function
+ *		    is guaranteed to be called when the
+ *		    transaction completes. If this parameter is
+ *		    NULL, then the generic callback registered
+ *		    through cvmx_usb_register_callback is
+ *		    called. If both are NULL, then there is no
+ *		    way to know when a transaction completes.
+ * @user_data:	    User supplied data returned when the
+ *		    callback is called. This is only used if
+ *		    callback in not NULL.
+ *
+ * Returns: A submitted transaction handle or negative on
+ *	    failure. Negative values are error codes.
  */
-int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle,
-                            uint64_t control_header,
-                            uint64_t buffer, int buffer_length,
-                            cvmx_usb_callback_func_t callback,
-                            void *user_data)
+int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle,
+			    uint64_t control_header,
+			    uint64_t buffer, int buffer_length,
+			    cvmx_usb_callback_func_t callback,
+			    void *user_data)
 {
-    int submit_handle;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-    cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header);
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)control_header);
-    CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer);
-    CVMX_USB_LOG_PARAM("%d", buffer_length);
-
-    /* Pipe handle checking is done later in a common place */
-    if (cvmx_unlikely(!control_header))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    /* Some drivers send a buffer with a zero length. God only knows why */
-    if (cvmx_unlikely(buffer && (buffer_length < 0)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(!buffer && (buffer_length != 0)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if ((header->s.request_type & 0x80) == 0)
-        buffer_length = cvmx_le16_to_cpu(header->s.length);
-
-    submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-                                         CVMX_USB_TRANSFER_CONTROL,
-                                         0, /* flags */
-                                         buffer,
-                                         buffer_length,
-                                         control_header,
-                                         0, /* iso_start_frame */
-                                         0, /* iso_number_packets */
-                                         NULL, /* iso_packets */
-                                         callback,
-                                         user_data);
-    CVMX_USB_RETURN(submit_handle);
+	int submit_handle;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+	union cvmx_usb_control_header *header =
+		cvmx_phys_to_ptr(control_header);
+
+	/* Pipe handle checking is done later in a common place */
+	if (unlikely(!control_header))
+		return -EINVAL;
+	/* Some drivers send a buffer with a zero length. God only knows why */
+	if (unlikely(buffer && (buffer_length < 0)))
+		return -EINVAL;
+	if (unlikely(!buffer && (buffer_length != 0)))
+		return -EINVAL;
+	if ((header->s.request_type & 0x80) == 0)
+		buffer_length = le16_to_cpu(header->s.length);
+
+	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
+						      CVMX_USB_TRANSFER_CONTROL,
+						      0, /* flags */
+						      buffer,
+						      buffer_length,
+						      control_header,
+						      0, /* iso_start_frame */
+						      0, /* iso_number_packets */
+						      NULL, /* iso_packets */
+						      callback,
+						      user_data);
+	return submit_handle;
 }
 
 
 /**
  * Call to submit a USB Isochronous transfer to a pipe.
  *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param start_frame
- *                  Number of frames into the future to schedule
- *                  this transaction.
- * @param flags     Flags to control the transfer. See
- *                  cvmx_usb_isochronous_flags_t for the flag
- *                  definitions.
- * @param number_packets
- *                  Number of sequential packets to transfer.
- *                  "packets" is a pointer to an array of this
- *                  many packet structures.
- * @param packets   Description of each transfer packet as
- *                  defined by cvmx_usb_iso_packet_t. The array
- *                  pointed to here must stay valid until the
- *                  complete callback is called.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
+ * @state:	    USB device state populated by
+ *		    cvmx_usb_initialize().
+ * @pipe_handle:
+ *		    Handle to the pipe for the transfer.
+ * @start_frame:
+ *		    Number of frames into the future to schedule
+ *		    this transaction.
+ * @flags:	    Flags to control the transfer. See
+ *		    enum cvmx_usb_isochronous_flags for the flag
+ *		    definitions.
+ * @number_packets:
+ *		    Number of sequential packets to transfer.
+ *		    "packets" is a pointer to an array of this
+ *		    many packet structures.
+ * @packets:	    Description of each transfer packet as
+ *		    defined by struct cvmx_usb_iso_packet. The array
+ *		    pointed to here must stay valid until the
+ *		    complete callback is called.
+ * @buffer:	    Physical address of the data buffer in
+ *		    memory. Note that this is NOT A POINTER, but
+ *		    the full 64bit physical address of the
+ *		    buffer. This may be zero if buffer_length is
+ *		    zero.
+ * @buffer_length:
+ *		    Length of buffer in bytes.
+ * @callback:	    Function to call when this transaction
+ *		    completes. If the return value of this
+ *		    function isn't an error, then this function
+ *		    is guaranteed to be called when the
+ *		    transaction completes. If this parameter is
+ *		    NULL, then the generic callback registered
+ *		    through cvmx_usb_register_callback is
+ *		    called. If both are NULL, then there is no
+ *		    way to know when a transaction completes.
+ * @user_data:	    User supplied data returned when the
+ *		    callback is called. This is only used if
+ *		    callback in not NULL.
+ *
+ * Returns: A submitted transaction handle or negative on
+ *	    failure. Negative values are error codes.
  */
-int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle,
-                                int start_frame, int flags,
-                                int number_packets,
-                                cvmx_usb_iso_packet_t packets[],
-                                uint64_t buffer, int buffer_length,
-                                cvmx_usb_callback_func_t callback,
-                                void *user_data)
+int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle,
+				int start_frame, int flags,
+				int number_packets,
+				struct cvmx_usb_iso_packet packets[],
+				uint64_t buffer, int buffer_length,
+				cvmx_usb_callback_func_t callback,
+				void *user_data)
 {
-    int submit_handle;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    CVMX_USB_LOG_PARAM("%d", start_frame);
-    CVMX_USB_LOG_PARAM("0x%x", flags);
-    CVMX_USB_LOG_PARAM("%d", number_packets);
-    CVMX_USB_LOG_PARAM("%p", packets);
-    CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer);
-    CVMX_USB_LOG_PARAM("%d", buffer_length);
-
-    /* Pipe handle checking is done later in a common place */
-    if (cvmx_unlikely(start_frame < 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(number_packets < 1))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(!packets))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(!buffer))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(buffer_length < 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-                                         CVMX_USB_TRANSFER_ISOCHRONOUS,
-                                         flags,
-                                         buffer,
-                                         buffer_length,
-                                         0, /* control_header */
-                                         start_frame,
-                                         number_packets,
-                                         packets,
-                                         callback,
-                                         user_data);
-    CVMX_USB_RETURN(submit_handle);
+	int submit_handle;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	/* Pipe handle checking is done later in a common place */
+	if (unlikely(start_frame < 0))
+		return -EINVAL;
+	if (unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP)))
+		return -EINVAL;
+	if (unlikely(number_packets < 1))
+		return -EINVAL;
+	if (unlikely(!packets))
+		return -EINVAL;
+	if (unlikely(!buffer))
+		return -EINVAL;
+	if (unlikely(buffer_length < 0))
+		return -EINVAL;
+
+	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
+						      CVMX_USB_TRANSFER_ISOCHRONOUS,
+						      flags,
+						      buffer,
+						      buffer_length,
+						      0, /* control_header */
+						      start_frame,
+						      number_packets,
+						      packets,
+						      callback,
+						      user_data);
+	return submit_handle;
 }
 
 
@@ -2525,63 +2440,58 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle,
  * a frame or two for the cvmx_usb_poll() function to call the
  * associated callback.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe_handle
- *               Pipe handle to cancel requests in.
- * @param submit_handle
- *               Handle to transaction to cancel, returned by the submit function.
+ * @state:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @pipe_handle:
+ *		 Pipe handle to cancel requests in.
+ * @submit_handle:
+ *		 Handle to transaction to cancel, returned by the submit function.
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle,
-                                  int submit_handle)
+int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_handle)
 {
-    cvmx_usb_transaction_t *transaction;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-    cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    CVMX_USB_LOG_PARAM("%d", submit_handle);
-
-    if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    /* Fail if the pipe isn't open */
-    if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    transaction = usb->transaction + submit_handle;
-
-    /* Fail if this transaction already completed */
-    if (cvmx_unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    /* If the transaction is the HEAD of the queue and scheduled. We need to
-        treat it special */
-    if ((pipe->head == transaction) &&
-        (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
-        cvmx_usbcx_hccharx_t usbc_hcchar;
-
-        usb->pipe_for_channel[pipe->channel] = NULL;
-        pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
-
-        CVMX_SYNCW;
-
-        usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
-        /* If the channel isn't enabled then the transaction already completed */
-        if (usbc_hcchar.s.chena) {
-            usbc_hcchar.s.chdis = 1;
-            __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32);
-        }
-    }
-    __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL);
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	struct cvmx_usb_transaction *transaction;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
+
+	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
+		return -EINVAL;
+	if (unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS)))
+		return -EINVAL;
+
+	/* Fail if the pipe isn't open */
+	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
+		return -EINVAL;
+
+	transaction = usb->transaction + submit_handle;
+
+	/* Fail if this transaction already completed */
+	if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0))
+		return -EINVAL;
+
+	/*
+	 * If the transaction is the HEAD of the queue and scheduled. We need to
+	 * treat it special
+	 */
+	if ((pipe->head == transaction) &&
+		(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
+		union cvmx_usbcx_hccharx usbc_hcchar;
+
+		usb->pipe_for_channel[pipe->channel] = NULL;
+		pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
+
+		CVMX_SYNCW;
+
+		usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
+		/* If the channel isn't enabled then the transaction already completed */
+		if (usbc_hcchar.s.chena) {
+			usbc_hcchar.s.chdis = 1;
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32);
+		}
+	}
+	__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL);
+	return 0;
 }
 
 
@@ -2589,112 +2499,98 @@ cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle,
  * Cancel all outstanding requests in a pipe. Logically all this
  * does is call cvmx_usb_cancel() in a loop.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe_handle
- *               Pipe handle to cancel requests in.
+ * @state:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @pipe_handle:
+ *		 Pipe handle to cancel requests in.
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle)
+int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle)
 {
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-    cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    /* Fail if the pipe isn't open */
-    if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    /* Simply loop through and attempt to cancel each transaction */
-    while (pipe->head) {
-        cvmx_usb_status_t result = cvmx_usb_cancel(state, pipe_handle,
-            __cvmx_usb_get_submit_handle(usb, pipe->head));
-        if (cvmx_unlikely(result != CVMX_USB_SUCCESS))
-            CVMX_USB_RETURN(result);
-    }
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
+
+	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
+		return -EINVAL;
+
+	/* Fail if the pipe isn't open */
+	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
+		return -EINVAL;
+
+	/* Simply loop through and attempt to cancel each transaction */
+	while (pipe->head) {
+		int result = cvmx_usb_cancel(state, pipe_handle,
+			__cvmx_usb_get_submit_handle(usb, pipe->head));
+		if (unlikely(result != 0))
+			return result;
+	}
+	return 0;
 }
 
 
 /**
  * Close a pipe created with cvmx_usb_open_pipe().
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe_handle
- *               Pipe handle to close.
+ * @state:	 USB device state populated by
+ *		 cvmx_usb_initialize().
+ * @pipe_handle:
+ *		 Pipe handle to close.
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t. CVMX_USB_BUSY is returned if the
- *         pipe has outstanding transfers.
+ * Returns: 0 or a negative error code. EBUSY is returned if the pipe has
+ *	    outstanding transfers.
  */
-cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle)
+int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle)
 {
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-    cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
 
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", pipe_handle);
-    if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
+	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
+		return -EINVAL;
 
-    /* Fail if the pipe isn't open */
-    if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
+	/* Fail if the pipe isn't open */
+	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
+		return -EINVAL;
 
-    /* Fail if the pipe has pending transactions */
-    if (cvmx_unlikely(pipe->head))
-        CVMX_USB_RETURN(CVMX_USB_BUSY);
+	/* Fail if the pipe has pending transactions */
+	if (unlikely(pipe->head))
+		return -EBUSY;
 
-    pipe->flags = 0;
-    __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe);
-    __cvmx_usb_append_pipe(&usb->free_pipes, pipe);
+	pipe->flags = 0;
+	__cvmx_usb_remove_pipe(&usb->idle_pipes, pipe);
+	__cvmx_usb_append_pipe(&usb->free_pipes, pipe);
 
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	return 0;
 }
 
 
 /**
  * Register a function to be called when various USB events occur.
  *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param reason    Which event to register for.
- * @param callback  Function to call when the event occurs.
- * @param user_data User data parameter to the function.
+ * @state:     USB device state populated by
+ *	       cvmx_usb_initialize().
+ * @reason:    Which event to register for.
+ * @callback:  Function to call when the event occurs.
+ * @user_data: User data parameter to the function.
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state,
-                                             cvmx_usb_callback_t reason,
-                                             cvmx_usb_callback_func_t callback,
-                                             void *user_data)
+int cvmx_usb_register_callback(struct cvmx_usb_state *state,
+			       enum cvmx_usb_callback reason,
+			       cvmx_usb_callback_func_t callback,
+			       void *user_data)
 {
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-    CVMX_USB_LOG_PARAM("%d", reason);
-    CVMX_USB_LOG_PARAM("%p", callback);
-    CVMX_USB_LOG_PARAM("%p", user_data);
-    if (cvmx_unlikely(reason >= __CVMX_USB_CALLBACK_END))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-    if (cvmx_unlikely(!callback))
-        CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM);
-
-    usb->callback[reason] = callback;
-    usb->callback_data[reason] = user_data;
-
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	if (unlikely(reason >= __CVMX_USB_CALLBACK_END))
+		return -EINVAL;
+	if (unlikely(!callback))
+		return -EINVAL;
+
+	usb->callback[reason] = callback;
+	usb->callback_data[reason] = user_data;
+
+	return 0;
 }
 
 
@@ -2702,428 +2598,457 @@ cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state,
  * Get the current USB protocol level frame number. The frame
  * number is always in the range of 0-0x7ff.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
+ * @state: USB device state populated by
+ *	   cvmx_usb_initialize().
  *
- * @return USB frame number
+ * Returns: USB frame number
  */
-int cvmx_usb_get_frame_number(cvmx_usb_state_t *state)
+int cvmx_usb_get_frame_number(struct cvmx_usb_state *state)
 {
-    int frame_number;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-    cvmx_usbcx_hfnum_t usbc_hfnum;
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
+	int frame_number;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+	union cvmx_usbcx_hfnum usbc_hfnum;
 
-    usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
-    frame_number = usbc_hfnum.s.frnum;
+	usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
+	frame_number = usbc_hfnum.s.frnum;
 
-    CVMX_USB_RETURN(frame_number);
+	return frame_number;
 }
 
 
 /**
- * @INTERNAL
  * Poll a channel for status
  *
- * @param usb     USB device
- * @param channel Channel to poll
+ * @usb:     USB device
+ * @channel: Channel to poll
  *
- * @return Zero on success
+ * Returns: Zero on success
  */
-static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel)
+static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int channel)
 {
-    cvmx_usbcx_hcintx_t usbc_hcint;
-    cvmx_usbcx_hctsizx_t usbc_hctsiz;
-    cvmx_usbcx_hccharx_t usbc_hcchar;
-    cvmx_usb_pipe_t *pipe;
-    cvmx_usb_transaction_t *transaction;
-    int bytes_this_transfer;
-    int bytes_in_last_packet;
-    int packets_processed;
-    int buffer_space_left;
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", usb);
-    CVMX_USB_LOG_PARAM("%d", channel);
-
-    /* Read the interrupt status bits for the channel */
-    usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
-
-    if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-        usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
-
-        if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) {
-            /* There seems to be a bug in CN31XX which can cause interrupt
-                IN transfers to get stuck until we do a write of HCCHARX
-                without changing things */
-            __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
-            CVMX_USB_RETURN(0);
-        }
-
-        /* In non DMA mode the channels don't halt themselves. We need to
-            manually disable channels that are left running */
-        if (!usbc_hcint.s.chhltd) {
-            if (usbc_hcchar.s.chena) {
-                cvmx_usbcx_hcintmskx_t hcintmsk;
-                /* Disable all interrupts except CHHLTD */
-                hcintmsk.u32 = 0;
-                hcintmsk.s.chhltdmsk = 1;
-                __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32);
-                usbc_hcchar.s.chdis = 1;
-                __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
-                CVMX_USB_RETURN(0);
-            }
-            else if (usbc_hcint.s.xfercompl) {
-                /* Successful IN/OUT with transfer complete. Channel halt isn't needed */
-            }
-            else {
-                cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel);
-                CVMX_USB_RETURN(0);
-            }
-        }
-    }
-    else {
-        /* There is are no interrupts that we need to process when the channel is
-            still running */
-        if (!usbc_hcint.s.chhltd)
-            CVMX_USB_RETURN(0);
-    }
-
-    /* Disable the channel interrupts now that it is done */
-    __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
-    usb->idle_hardware_channels |= (1<<channel);
-
-    /* Make sure this channel is tied to a valid pipe */
-    pipe = usb->pipe_for_channel[channel];
-    CVMX_PREFETCH(pipe, 0);
-    CVMX_PREFETCH(pipe, 128);
-    if (!pipe)
-        CVMX_USB_RETURN(0);
-    transaction = pipe->head;
-    CVMX_PREFETCH0(transaction);
-
-    /* Disconnect this pipe from the HW channel. Later the schedule function will
-        figure out which pipe needs to go */
-    usb->pipe_for_channel[channel] = NULL;
-    pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
-
-    /* Read the channel config info so we can figure out how much data
-        transfered */
-    usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
-    usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
-
-    /* Calculating the number of bytes successfully transferred is dependent on
-        the transfer direction */
-    packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt;
-    if (usbc_hcchar.s.epdir) {
-        /* IN transactions are easy. For every byte received the hardware
-            decrements xfersize. All we need to do is subtract the current
-            value of xfersize from its starting value and we know how many
-            bytes were written to the buffer */
-        bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize;
-    }
-    else {
-        /* OUT transaction don't decrement xfersize. Instead pktcnt is
-            decremented on every successful packet send. The hardware does
-            this when it receives an ACK, or NYET. If it doesn't
-            receive one of these responses pktcnt doesn't change */
-        bytes_this_transfer = packets_processed * usbc_hcchar.s.mps;
-        /* The last packet may not be a full transfer if we didn't have
-            enough data */
-        if (bytes_this_transfer > transaction->xfersize)
-            bytes_this_transfer = transaction->xfersize;
-    }
-    /* Figure out how many bytes were in the last packet of the transfer */
-    if (packets_processed)
-        bytes_in_last_packet = bytes_this_transfer - (packets_processed-1) * usbc_hcchar.s.mps;
-    else
-        bytes_in_last_packet = bytes_this_transfer;
-
-    /* As a special case, setup transactions output the setup header, not
-        the user's data. For this reason we don't count setup data as bytes
-        transferred */
-    if ((transaction->stage == CVMX_USB_STAGE_SETUP) ||
-        (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE))
-        bytes_this_transfer = 0;
-
-    /* Optional debug output */
-    if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) ||
-        (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS)))
-        cvmx_dprintf("%s: Channel %d halted. Pipe %d transaction %d stage %d bytes=%d\n",
-                     __FUNCTION__, channel,
-                     __cvmx_usb_get_pipe_handle(usb, pipe),
-                     __cvmx_usb_get_submit_handle(usb, transaction),
-                     transaction->stage, bytes_this_transfer);
-
-    /* Add the bytes transferred to the running total. It is important that
-        bytes_this_transfer doesn't count any data that needs to be
-        retransmitted */
-    transaction->actual_bytes += bytes_this_transfer;
-    if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
-        buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes;
-    else
-        buffer_space_left = transaction->buffer_length - transaction->actual_bytes;
-
-    /* We need to remember the PID toggle state for the next transaction. The
-        hardware already updated it for the next transaction */
-    pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0);
-
-    /* For high speed bulk out, assume the next transaction will need to do a
-        ping before proceeding. If this isn't true the ACK processing below
-        will clear this flag */
-    if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
-        (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
-        (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT))
-        pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
-
-    if (usbc_hcint.s.stall) {
-        /* STALL as a response means this transaction cannot be completed
-            because the device can't process transactions. Tell the user. Any
-            data that was transferred will be counted on the actual bytes
-            transferred */
-        pipe->pid_toggle = 0;
-        __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL);
-    }
-    else if (usbc_hcint.s.xacterr) {
-        /* We know at least one packet worked if we get a ACK or NAK. Reset the retry counter */
-        if (usbc_hcint.s.nak || usbc_hcint.s.ack)
-            transaction->retries = 0;
-        transaction->retries++;
-        if (transaction->retries > MAX_RETRIES) {
-            /* XactErr as a response means the device signaled something wrong with
-                the transfer. For example, PID toggle errors cause these */
-            __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR);
-        }
-        else {
-            /* If this was a split then clear our split in progress marker */
-            if (usb->active_split == transaction)
-                usb->active_split = NULL;
-            /* Rewind to the beginning of the transaction by anding off the
-                split complete bit */
-            transaction->stage &= ~1;
-            pipe->split_sc_frame = -1;
-            pipe->next_tx_frame += pipe->interval;
-            if (pipe->next_tx_frame < usb->frame_number)
-                pipe->next_tx_frame = usb->frame_number + pipe->interval -
-                    (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-        }
-    }
-    else if (usbc_hcint.s.bblerr)
-    {
-        /* Babble Error (BblErr) */
-        __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_BABBLEERR);
-    }
-    else if (usbc_hcint.s.datatglerr)
-    {
-        /* We'll retry the exact same transaction again */
-        transaction->retries++;
-    }
-    else if (usbc_hcint.s.nyet) {
-        /* NYET as a response is only allowed in three cases: as a response to
-            a ping, as a response to a split transaction, and as a response to
-            a bulk out. The ping case is handled by hardware, so we only have
-            splits and bulk out */
-        if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
-            transaction->retries = 0;
-            /* If there is more data to go then we need to try again. Otherwise
-                this transaction is complete */
-            if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet))
-                __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-        }
-        else {
-            /* Split transactions retry the split complete 4 times then rewind
-                to the start split and do the entire transactions again */
-            transaction->retries++;
-            if ((transaction->retries & 0x3) == 0) {
-                /* Rewind to the beginning of the transaction by anding off the
-                    split complete bit */
-                transaction->stage &= ~1;
-                pipe->split_sc_frame = -1;
-            }
-        }
-    }
-    else if (usbc_hcint.s.ack) {
-        transaction->retries = 0;
-        /* The ACK bit can only be checked after the other error bits. This is
-            because a multi packet transfer may succeed in a number of packets
-            and then get a different response on the last packet. In this case
-            both ACK and the last response bit will be set. If none of the
-            other response bits is set, then the last packet must have been an
-            ACK */
-
-        /* Since we got an ACK, we know we don't need to do a ping on this
-            pipe */
-        pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING;
-
-        switch (transaction->type)
-        {
-            case CVMX_USB_TRANSFER_CONTROL:
-                switch (transaction->stage)
-                {
-                    case CVMX_USB_STAGE_NON_CONTROL:
-                    case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
-                        /* This should be impossible */
-                        __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
-                        break;
-                    case CVMX_USB_STAGE_SETUP:
-                        pipe->pid_toggle = 1;
-                        if (__cvmx_usb_pipe_needs_split(usb, pipe))
-                            transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
-                        else {
-                            cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header);
-                            if (header->s.length)
-                                transaction->stage = CVMX_USB_STAGE_DATA;
-                            else
-                                transaction->stage = CVMX_USB_STAGE_STATUS;
-                        }
-                        break;
-                    case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
-                        {
-                            cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header);
-                            if (header->s.length)
-                                transaction->stage = CVMX_USB_STAGE_DATA;
-                            else
-                                transaction->stage = CVMX_USB_STAGE_STATUS;
-                        }
-                        break;
-                    case CVMX_USB_STAGE_DATA:
-                        if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-                            transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
-                            /* For setup OUT data that are splits, the hardware
-                                doesn't appear to count transferred data. Here
-                                we manually update the data transferred */
-                            if (!usbc_hcchar.s.epdir) {
-                                if (buffer_space_left < pipe->max_packet)
-                                    transaction->actual_bytes += buffer_space_left;
-                                else
-                                    transaction->actual_bytes += pipe->max_packet;
-                            }
-                        }
-                        else if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
-                            pipe->pid_toggle = 1;
-                            transaction->stage = CVMX_USB_STAGE_STATUS;
-                        }
-                        break;
-                    case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
-                        if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
-                            pipe->pid_toggle = 1;
-                            transaction->stage = CVMX_USB_STAGE_STATUS;
-                        }
-                        else {
-                            transaction->stage = CVMX_USB_STAGE_DATA;
-                        }
-                        break;
-                    case CVMX_USB_STAGE_STATUS:
-                        if (__cvmx_usb_pipe_needs_split(usb, pipe))
-                            transaction->stage = CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
-                        else
-                            __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                        break;
-                    case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
-                        __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                        break;
-                }
-                break;
-            case CVMX_USB_TRANSFER_BULK:
-            case CVMX_USB_TRANSFER_INTERRUPT:
-                /* The only time a bulk transfer isn't complete when
-                    it finishes with an ACK is during a split transaction. For
-                    splits we need to continue the transfer if more data is
-                    needed */
-                if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-                    if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL)
-                        transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
-                    else {
-                        if (buffer_space_left && (bytes_in_last_packet == pipe->max_packet))
-                            transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
-                        else {
-                            if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
-                                pipe->next_tx_frame += pipe->interval;
-                            __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                        }
-                    }
-                }
-                else {
-                    if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
-                        (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
-                        (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
-                        (usbc_hcint.s.nak))
-                        pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
-                    if (!buffer_space_left || (bytes_in_last_packet < pipe->max_packet)) {
-                        if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
-                            pipe->next_tx_frame += pipe->interval;
-                        __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                    }
-                }
-                break;
-            case CVMX_USB_TRANSFER_ISOCHRONOUS:
-                if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-                    /* ISOCHRONOUS OUT splits don't require a complete split stage.
-                        Instead they use a sequence of begin OUT splits to transfer
-                        the data 188 bytes at a time. Once the transfer is complete,
-                        the pipe sleeps until the next schedule interval */
-                    if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
-                        /* If no space left or this wasn't a max size packet then
-                            this transfer is complete. Otherwise start it again
-                            to send the next 188 bytes */
-                        if (!buffer_space_left || (bytes_this_transfer < 188)) {
-                            pipe->next_tx_frame += pipe->interval;
-                            __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                        }
-                    }
-                    else {
-                        if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) {
-                            /* We are in the incoming data phase. Keep getting
-                                data until we run out of space or get a small
-                                packet */
-                            if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
-                                pipe->next_tx_frame += pipe->interval;
-                                __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                            }
-                        }
-                        else
-                            transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
-                    }
-                }
-                else {
-                    pipe->next_tx_frame += pipe->interval;
-                    __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-                }
-                break;
-        }
-    }
-    else if (usbc_hcint.s.nak) {
-        /* If this was a split then clear our split in progress marker */
-        if (usb->active_split == transaction)
-            usb->active_split = NULL;
-        /* NAK as a response means the device couldn't accept the transaction,
-            but it should be retried in the future. Rewind to the beginning of
-            the transaction by anding off the split complete bit. Retry in the
-            next interval */
-        transaction->retries = 0;
-        transaction->stage &= ~1;
-        pipe->next_tx_frame += pipe->interval;
-        if (pipe->next_tx_frame < usb->frame_number)
-            pipe->next_tx_frame = usb->frame_number + pipe->interval -
-                (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-    }
-    else {
-        cvmx_usb_port_status_t port;
-        port = cvmx_usb_get_status((cvmx_usb_state_t *)usb);
-        if (port.port_enabled)
-        {
-            /* We'll retry the exact same transaction again */
-            transaction->retries++;
-        }
-        else
-        {
-            /* We get channel halted interrupts with no result bits sets when the
-                cable is unplugged */
-            __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
-        }
-    }
-    CVMX_USB_RETURN(0);
+	union cvmx_usbcx_hcintx usbc_hcint;
+	union cvmx_usbcx_hctsizx usbc_hctsiz;
+	union cvmx_usbcx_hccharx usbc_hcchar;
+	struct cvmx_usb_pipe *pipe;
+	struct cvmx_usb_transaction *transaction;
+	int bytes_this_transfer;
+	int bytes_in_last_packet;
+	int packets_processed;
+	int buffer_space_left;
+
+	/* Read the interrupt status bits for the channel */
+	usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
+
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
+		usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
+
+		if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) {
+			/*
+			 * There seems to be a bug in CN31XX which can cause
+			 * interrupt IN transfers to get stuck until we do a
+			 * write of HCCHARX without changing things
+			 */
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
+			return 0;
+		}
+
+		/*
+		 * In non DMA mode the channels don't halt themselves. We need
+		 * to manually disable channels that are left running
+		 */
+		if (!usbc_hcint.s.chhltd) {
+			if (usbc_hcchar.s.chena) {
+				union cvmx_usbcx_hcintmskx hcintmsk;
+				/* Disable all interrupts except CHHLTD */
+				hcintmsk.u32 = 0;
+				hcintmsk.s.chhltdmsk = 1;
+				__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32);
+				usbc_hcchar.s.chdis = 1;
+				__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
+				return 0;
+			} else if (usbc_hcint.s.xfercompl) {
+				/* Successful IN/OUT with transfer complete. Channel halt isn't needed */
+			} else {
+				cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel);
+				return 0;
+			}
+		}
+	} else {
+		/*
+		 * There is are no interrupts that we need to process when the
+		 * channel is still running
+		 */
+		if (!usbc_hcint.s.chhltd)
+			return 0;
+	}
+
+	/* Disable the channel interrupts now that it is done */
+	__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
+	usb->idle_hardware_channels |= (1<<channel);
+
+	/* Make sure this channel is tied to a valid pipe */
+	pipe = usb->pipe_for_channel[channel];
+	CVMX_PREFETCH(pipe, 0);
+	CVMX_PREFETCH(pipe, 128);
+	if (!pipe)
+		return 0;
+	transaction = pipe->head;
+	CVMX_PREFETCH0(transaction);
+
+	/*
+	 * Disconnect this pipe from the HW channel. Later the schedule
+	 * function will figure out which pipe needs to go
+	 */
+	usb->pipe_for_channel[channel] = NULL;
+	pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
+
+	/*
+	 * Read the channel config info so we can figure out how much data
+	 * transfered
+	 */
+	usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
+	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
+
+	/*
+	 * Calculating the number of bytes successfully transferred is dependent
+	 * on the transfer direction
+	 */
+	packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt;
+	if (usbc_hcchar.s.epdir) {
+		/*
+		 * IN transactions are easy. For every byte received the
+		 * hardware decrements xfersize. All we need to do is subtract
+		 * the current value of xfersize from its starting value and we
+		 * know how many bytes were written to the buffer
+		 */
+		bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize;
+	} else {
+		/*
+		 * OUT transaction don't decrement xfersize. Instead pktcnt is
+		 * decremented on every successful packet send. The hardware
+		 * does this when it receives an ACK, or NYET. If it doesn't
+		 * receive one of these responses pktcnt doesn't change
+		 */
+		bytes_this_transfer = packets_processed * usbc_hcchar.s.mps;
+		/*
+		 * The last packet may not be a full transfer if we didn't have
+		 * enough data
+		 */
+		if (bytes_this_transfer > transaction->xfersize)
+			bytes_this_transfer = transaction->xfersize;
+	}
+	/* Figure out how many bytes were in the last packet of the transfer */
+	if (packets_processed)
+		bytes_in_last_packet = bytes_this_transfer - (packets_processed-1) * usbc_hcchar.s.mps;
+	else
+		bytes_in_last_packet = bytes_this_transfer;
+
+	/*
+	 * As a special case, setup transactions output the setup header, not
+	 * the user's data. For this reason we don't count setup data as bytes
+	 * transferred
+	 */
+	if ((transaction->stage == CVMX_USB_STAGE_SETUP) ||
+		(transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE))
+		bytes_this_transfer = 0;
+
+	/*
+	 * Add the bytes transferred to the running total. It is important that
+	 * bytes_this_transfer doesn't count any data that needs to be
+	 * retransmitted
+	 */
+	transaction->actual_bytes += bytes_this_transfer;
+	if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
+		buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes;
+	else
+		buffer_space_left = transaction->buffer_length - transaction->actual_bytes;
+
+	/*
+	 * We need to remember the PID toggle state for the next transaction.
+	 * The hardware already updated it for the next transaction
+	 */
+	pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0);
+
+	/*
+	 * For high speed bulk out, assume the next transaction will need to do
+	 * a ping before proceeding. If this isn't true the ACK processing below
+	 * will clear this flag
+	 */
+	if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
+		(pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
+		(pipe->transfer_dir == CVMX_USB_DIRECTION_OUT))
+		pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+
+	if (usbc_hcint.s.stall) {
+		/*
+		 * STALL as a response means this transaction cannot be
+		 * completed because the device can't process transactions. Tell
+		 * the user. Any data that was transferred will be counted on
+		 * the actual bytes transferred
+		 */
+		pipe->pid_toggle = 0;
+		__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL);
+	} else if (usbc_hcint.s.xacterr) {
+		/*
+		 * We know at least one packet worked if we get a ACK or NAK.
+		 * Reset the retry counter
+		 */
+		if (usbc_hcint.s.nak || usbc_hcint.s.ack)
+			transaction->retries = 0;
+		transaction->retries++;
+		if (transaction->retries > MAX_RETRIES) {
+			/*
+			 * XactErr as a response means the device signaled
+			 * something wrong with the transfer. For example, PID
+			 * toggle errors cause these
+			 */
+			__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR);
+		} else {
+			/*
+			 * If this was a split then clear our split in progress
+			 * marker
+			 */
+			if (usb->active_split == transaction)
+				usb->active_split = NULL;
+			/*
+			 * Rewind to the beginning of the transaction by anding
+			 * off the split complete bit
+			 */
+			transaction->stage &= ~1;
+			pipe->split_sc_frame = -1;
+			pipe->next_tx_frame += pipe->interval;
+			if (pipe->next_tx_frame < usb->frame_number)
+				pipe->next_tx_frame = usb->frame_number + pipe->interval -
+						      (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
+		}
+	} else if (usbc_hcint.s.bblerr) {
+		/* Babble Error (BblErr) */
+		__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_BABBLEERR);
+	} else if (usbc_hcint.s.datatglerr) {
+		/* We'll retry the exact same transaction again */
+		transaction->retries++;
+	} else if (usbc_hcint.s.nyet) {
+		/*
+		 * NYET as a response is only allowed in three cases: as a
+		 * response to a ping, as a response to a split transaction, and
+		 * as a response to a bulk out. The ping case is handled by
+		 * hardware, so we only have splits and bulk out
+		 */
+		if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			transaction->retries = 0;
+			/*
+			 * If there is more data to go then we need to try
+			 * again. Otherwise this transaction is complete
+			 */
+			if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet))
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+		} else {
+			/*
+			 * Split transactions retry the split complete 4 times
+			 * then rewind to the start split and do the entire
+			 * transactions again
+			 */
+			transaction->retries++;
+			if ((transaction->retries & 0x3) == 0) {
+				/*
+				 * Rewind to the beginning of the transaction by
+				 * anding off the split complete bit
+				 */
+				transaction->stage &= ~1;
+				pipe->split_sc_frame = -1;
+			}
+		}
+	} else if (usbc_hcint.s.ack) {
+		transaction->retries = 0;
+		/*
+		 * The ACK bit can only be checked after the other error bits.
+		 * This is because a multi packet transfer may succeed in a
+		 * number of packets and then get a different response on the
+		 * last packet. In this case both ACK and the last response bit
+		 * will be set. If none of the other response bits is set, then
+		 * the last packet must have been an ACK
+		 *
+		 * Since we got an ACK, we know we don't need to do a ping on
+		 * this pipe
+		 */
+		pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING;
+
+		switch (transaction->type) {
+		case CVMX_USB_TRANSFER_CONTROL:
+			switch (transaction->stage) {
+			case CVMX_USB_STAGE_NON_CONTROL:
+			case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
+				/* This should be impossible */
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
+				break;
+			case CVMX_USB_STAGE_SETUP:
+				pipe->pid_toggle = 1;
+				if (__cvmx_usb_pipe_needs_split(usb, pipe))
+					transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
+				else {
+					union cvmx_usb_control_header *header =
+						cvmx_phys_to_ptr(transaction->control_header);
+					if (header->s.length)
+						transaction->stage = CVMX_USB_STAGE_DATA;
+					else
+						transaction->stage = CVMX_USB_STAGE_STATUS;
+				}
+				break;
+			case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
+				{
+					union cvmx_usb_control_header *header =
+						cvmx_phys_to_ptr(transaction->control_header);
+					if (header->s.length)
+						transaction->stage = CVMX_USB_STAGE_DATA;
+					else
+						transaction->stage = CVMX_USB_STAGE_STATUS;
+				}
+				break;
+			case CVMX_USB_STAGE_DATA:
+				if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+					transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
+					/*
+					 * For setup OUT data that are splits,
+					 * the hardware doesn't appear to count
+					 * transferred data. Here we manually
+					 * update the data transferred
+					 */
+					if (!usbc_hcchar.s.epdir) {
+						if (buffer_space_left < pipe->max_packet)
+							transaction->actual_bytes += buffer_space_left;
+						else
+							transaction->actual_bytes += pipe->max_packet;
+					}
+				} else if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
+					pipe->pid_toggle = 1;
+					transaction->stage = CVMX_USB_STAGE_STATUS;
+				}
+				break;
+			case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
+				if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
+					pipe->pid_toggle = 1;
+					transaction->stage = CVMX_USB_STAGE_STATUS;
+				} else {
+					transaction->stage = CVMX_USB_STAGE_DATA;
+				}
+				break;
+			case CVMX_USB_STAGE_STATUS:
+				if (__cvmx_usb_pipe_needs_split(usb, pipe))
+					transaction->stage = CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
+				else
+					__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+				break;
+			case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+				break;
+			}
+			break;
+		case CVMX_USB_TRANSFER_BULK:
+		case CVMX_USB_TRANSFER_INTERRUPT:
+			/*
+			 * The only time a bulk transfer isn't complete when it
+			 * finishes with an ACK is during a split transaction.
+			 * For splits we need to continue the transfer if more
+			 * data is needed
+			 */
+			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+				if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL)
+					transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
+				else {
+					if (buffer_space_left && (bytes_in_last_packet == pipe->max_packet))
+						transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
+					else {
+						if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
+							pipe->next_tx_frame += pipe->interval;
+							__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+					}
+				}
+			} else {
+				if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
+				    (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
+				    (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
+				    (usbc_hcint.s.nak))
+					pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+				if (!buffer_space_left || (bytes_in_last_packet < pipe->max_packet)) {
+					if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
+						pipe->next_tx_frame += pipe->interval;
+					__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+				}
+			}
+			break;
+		case CVMX_USB_TRANSFER_ISOCHRONOUS:
+			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+				/*
+				 * ISOCHRONOUS OUT splits don't require a
+				 * complete split stage. Instead they use a
+				 * sequence of begin OUT splits to transfer the
+				 * data 188 bytes at a time. Once the transfer
+				 * is complete, the pipe sleeps until the next
+				 * schedule interval
+				 */
+				if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
+					/*
+					 * If no space left or this wasn't a max
+					 * size packet then this transfer is
+					 * complete. Otherwise start it again to
+					 * send the next 188 bytes
+					 */
+					if (!buffer_space_left || (bytes_this_transfer < 188)) {
+						pipe->next_tx_frame += pipe->interval;
+						__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+					}
+				} else {
+					if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) {
+						/*
+						 * We are in the incoming data
+						 * phase. Keep getting data
+						 * until we run out of space or
+						 * get a small packet
+						 */
+						if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
+							pipe->next_tx_frame += pipe->interval;
+							__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+						}
+					} else
+						transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
+				}
+			} else {
+				pipe->next_tx_frame += pipe->interval;
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+			}
+			break;
+		}
+	} else if (usbc_hcint.s.nak) {
+		/* If this was a split then clear our split in progress marker */
+		if (usb->active_split == transaction)
+			usb->active_split = NULL;
+		/*
+		 * NAK as a response means the device couldn't accept the
+		 * transaction, but it should be retried in the future. Rewind
+		 * to the beginning of the transaction by anding off the split
+		 * complete bit. Retry in the next interval
+		 */
+		transaction->retries = 0;
+		transaction->stage &= ~1;
+		pipe->next_tx_frame += pipe->interval;
+		if (pipe->next_tx_frame < usb->frame_number)
+			pipe->next_tx_frame = usb->frame_number + pipe->interval -
+				(usb->frame_number - pipe->next_tx_frame) % pipe->interval;
+	} else {
+		struct cvmx_usb_port_status port;
+		port = cvmx_usb_get_status((struct cvmx_usb_state *)usb);
+		if (port.port_enabled) {
+			/* We'll retry the exact same transaction again */
+			transaction->retries++;
+		} else {
+			/*
+			 * We get channel halted interrupts with no result bits
+			 * sets when the cable is unplugged
+			 */
+			__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
+		}
+	}
+	return 0;
 }
 
 
@@ -3133,97 +3058,101 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel)
  * handler for the USB controller. It can also be called
  * periodically in a loop for non-interrupt based operation.
  *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
+ * @state:	USB device state populated by
+ *		cvmx_usb_initialize().
  *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
+ * Returns: 0 or a negative error code.
  */
-cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state)
+int cvmx_usb_poll(struct cvmx_usb_state *state)
 {
-    cvmx_usbcx_hfnum_t usbc_hfnum;
-    cvmx_usbcx_gintsts_t usbc_gintsts;
-    cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state;
-
-    CVMX_PREFETCH(usb, 0);
-    CVMX_PREFETCH(usb, 1*128);
-    CVMX_PREFETCH(usb, 2*128);
-    CVMX_PREFETCH(usb, 3*128);
-    CVMX_PREFETCH(usb, 4*128);
-
-    CVMX_USB_LOG_CALLED();
-    CVMX_USB_LOG_PARAM("%p", state);
-
-    /* Update the frame counter */
-    usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
-    if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum)
-        usb->frame_number += 0x4000;
-    usb->frame_number &= ~0x3fffull;
-    usb->frame_number |= usbc_hfnum.s.frnum;
-
-    /* Read the pending interrupts */
-    usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTSTS(usb->index));
-
-    /* Clear the interrupts now that we know about them */
-    __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32);
-
-    if (usbc_gintsts.s.rxflvl) {
-        /* RxFIFO Non-Empty (RxFLvl)
-            Indicates that there is at least one packet pending to be read
-            from the RxFIFO. */
-        /* In DMA mode this is handled by hardware */
-        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-            __cvmx_usb_poll_rx_fifo(usb);
-    }
-    if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) {
-        /* Fill the Tx FIFOs when not in DMA mode */
-        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-            __cvmx_usb_poll_tx_fifo(usb);
-    }
-    if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) {
-        cvmx_usbcx_hprt_t usbc_hprt;
-        /* Disconnect Detected Interrupt (DisconnInt)
-            Asserted when a device disconnect is detected. */
-
-        /* Host Port Interrupt (PrtInt)
-            The core sets this bit to indicate a change in port status of one
-            of the O2P USB core ports in Host mode. The application must
-            read the Host Port Control and Status (HPRT) register to
-            determine the exact event that caused this interrupt. The
-            application must clear the appropriate status bit in the Host Port
-            Control and Status register to clear this bit. */
-
-        /* Call the user's port callback */
-        __cvmx_usb_perform_callback(usb, NULL, NULL,
-                                    CVMX_USB_CALLBACK_PORT_CHANGED,
-                                    CVMX_USB_COMPLETE_SUCCESS);
-        /* Clear the port change bits */
-        usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-        usbc_hprt.s.prtena = 0;
-        __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32);
-    }
-    if (usbc_gintsts.s.hchint) {
-        /* Host Channels Interrupt (HChInt)
-            The core sets this bit to indicate that an interrupt is pending on
-            one of the channels of the core (in Host mode). The application
-            must read the Host All Channels Interrupt (HAINT) register to
-            determine the exact number of the channel on which the
-            interrupt occurred, and then read the corresponding Host
-            Channel-n Interrupt (HCINTn) register to determine the exact
-            cause of the interrupt. The application must clear the
-            appropriate status bit in the HCINTn register to clear this bit. */
-        cvmx_usbcx_haint_t usbc_haint;
-        usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index));
-        while (usbc_haint.u32) {
-            int channel;
-            CVMX_CLZ(channel, usbc_haint.u32);
-            channel = 31 - channel;
-            __cvmx_usb_poll_channel(usb, channel);
-            usbc_haint.u32 ^= 1<<channel;
-        }
-    }
-
-    __cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
-
-    CVMX_USB_RETURN(CVMX_USB_SUCCESS);
+	union cvmx_usbcx_hfnum usbc_hfnum;
+	union cvmx_usbcx_gintsts usbc_gintsts;
+	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
+
+	CVMX_PREFETCH(usb, 0);
+	CVMX_PREFETCH(usb, 1*128);
+	CVMX_PREFETCH(usb, 2*128);
+	CVMX_PREFETCH(usb, 3*128);
+	CVMX_PREFETCH(usb, 4*128);
+
+	/* Update the frame counter */
+	usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
+	if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum)
+		usb->frame_number += 0x4000;
+	usb->frame_number &= ~0x3fffull;
+	usb->frame_number |= usbc_hfnum.s.frnum;
+
+	/* Read the pending interrupts */
+	usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTSTS(usb->index));
+
+	/* Clear the interrupts now that we know about them */
+	__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32);
+
+	if (usbc_gintsts.s.rxflvl) {
+		/*
+		 * RxFIFO Non-Empty (RxFLvl)
+		 * Indicates that there is at least one packet pending to be
+		 * read from the RxFIFO.
+		 *
+		 * In DMA mode this is handled by hardware
+		 */
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			__cvmx_usb_poll_rx_fifo(usb);
+	}
+	if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) {
+		/* Fill the Tx FIFOs when not in DMA mode */
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			__cvmx_usb_poll_tx_fifo(usb);
+	}
+	if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) {
+		union cvmx_usbcx_hprt usbc_hprt;
+		/*
+		 * Disconnect Detected Interrupt (DisconnInt)
+		 * Asserted when a device disconnect is detected.
+		 *
+		 * Host Port Interrupt (PrtInt)
+		 * The core sets this bit to indicate a change in port status of
+		 * one of the O2P USB core ports in Host mode. The application
+		 * must read the Host Port Control and Status (HPRT) register to
+		 * determine the exact event that caused this interrupt. The
+		 * application must clear the appropriate status bit in the Host
+		 * Port Control and Status register to clear this bit.
+		 *
+		 * Call the user's port callback
+		 */
+		__cvmx_usb_perform_callback(usb, NULL, NULL,
+					    CVMX_USB_CALLBACK_PORT_CHANGED,
+					    CVMX_USB_COMPLETE_SUCCESS);
+		/* Clear the port change bits */
+		usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+		usbc_hprt.s.prtena = 0;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32);
+	}
+	if (usbc_gintsts.s.hchint) {
+		/*
+		 * Host Channels Interrupt (HChInt)
+		 * The core sets this bit to indicate that an interrupt is
+		 * pending on one of the channels of the core (in Host mode).
+		 * The application must read the Host All Channels Interrupt
+		 * (HAINT) register to determine the exact number of the channel
+		 * on which the interrupt occurred, and then read the
+		 * corresponding Host Channel-n Interrupt (HCINTn) register to
+		 * determine the exact cause of the interrupt. The application
+		 * must clear the appropriate status bit in the HCINTn register
+		 * to clear this bit.
+		 */
+		union cvmx_usbcx_haint usbc_haint;
+		usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index));
+		while (usbc_haint.u32) {
+			int channel;
+			CVMX_CLZ(channel, usbc_haint.u32);
+			channel = 31 - channel;
+			__cvmx_usb_poll_channel(usb, channel);
+			usbc_haint.u32 ^= 1<<channel;
+		}
+	}
+
+	__cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
+
+	return 0;
 }
diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h
index db9cc05..8bf3696 100644
--- a/drivers/staging/octeon-usb/cvmx-usb.h
+++ b/drivers/staging/octeon-usb/cvmx-usb.h
@@ -39,8 +39,6 @@
 
 
 /**
- * @file
- *
  * "cvmx-usb.h" defines a set of low level USB functions to help
  * developers create Octeon USB drivers for various operating
  * systems. These functions provide a generic API to the Octeon
@@ -49,24 +47,24 @@
  *
  * At a high level the device driver needs to:
  *
- * -# Call cvmx_usb_get_num_ports() to get the number of
- *  supported ports.
- * -# Call cvmx_usb_initialize() for each Octeon USB port.
- * -# Enable the port using cvmx_usb_enable().
- * -# Either periodically, or in an interrupt handler, call
- *  cvmx_usb_poll() to service USB events.
- * -# Manage pipes using cvmx_usb_open_pipe() and
- *  cvmx_usb_close_pipe().
- * -# Manage transfers using cvmx_usb_submit_*() and
- *  cvmx_usb_cancel*().
- * -# Shutdown USB on unload using cvmx_usb_shutdown().
+ * - Call cvmx_usb_get_num_ports() to get the number of
+ *   supported ports.
+ * - Call cvmx_usb_initialize() for each Octeon USB port.
+ * - Enable the port using cvmx_usb_enable().
+ * - Either periodically, or in an interrupt handler, call
+ *   cvmx_usb_poll() to service USB events.
+ * - Manage pipes using cvmx_usb_open_pipe() and
+ *   cvmx_usb_close_pipe().
+ * - Manage transfers using cvmx_usb_submit_*() and
+ *   cvmx_usb_cancel*().
+ * - Shutdown USB on unload using cvmx_usb_shutdown().
  *
  * To monitor USB status changes, the device driver must use
  * cvmx_usb_register_callback() to register for events that it
  * is interested in. Below are a few hints on successfully
  * implementing a driver on top of this API.
  *
- * <h2>Initialization</h2>
+ * == Initialization ==
  *
  * When a driver is first loaded, it is normally not necessary
  * to bring up the USB port completely. Most operating systems
@@ -75,24 +73,24 @@
  * initialize anything found, and then enable the hardware.
  *
  * In the probe phase you should:
- * -# Use cvmx_usb_get_num_ports() to determine the number of
- *  USB port to be supported.
- * -# Allocate space for a cvmx_usb_state_t structure for each
- *  port.
- * -# Tell the operating system about each port
+ * - Use cvmx_usb_get_num_ports() to determine the number of
+ *   USB port to be supported.
+ * - Allocate space for a struct cvmx_usb_state for each
+ *   port.
+ * - Tell the operating system about each port
  *
  * In the initialization phase you should:
- * -# Use cvmx_usb_initialize() on each port.
- * -# Do not call cvmx_usb_enable(). This leaves the USB port in
- *  the disabled state until the operating system is ready.
+ * - Use cvmx_usb_initialize() on each port.
+ * - Do not call cvmx_usb_enable(). This leaves the USB port in
+ *   the disabled state until the operating system is ready.
  *
  * Finally, in the enable phase you should:
- * -# Call cvmx_usb_enable() on the appropriate port.
- * -# Note that some operating system use a RESET instead of an
- *  enable call. To implement RESET, you should call
- *  cvmx_usb_disable() followed by cvmx_usb_enable().
+ * - Call cvmx_usb_enable() on the appropriate port.
+ * - Note that some operating system use a RESET instead of an
+ *   enable call. To implement RESET, you should call
+ *   cvmx_usb_disable() followed by cvmx_usb_enable().
  *
- * <h2>Locking</h2>
+ * == Locking ==
  *
  * All of the functions in the cvmx-usb API assume exclusive
  * access to the USB hardware and internal data structures. This
@@ -112,25 +110,24 @@
  * take a lock to make sure that another core cannot call
  * cvmx-usb.
  *
- * <h2>Port callback</h2>
+ * == Port callback ==
  *
  * The port callback prototype needs to look as follows:
  *
- * void port_callback(cvmx_usb_state_t *usb,
- *                    cvmx_usb_callback_t reason,
- *                    cvmx_usb_complete_t status,
+ * void port_callback(struct cvmx_usb_state *usb,
+ *                    enum cvmx_usb_callback reason,
+ *                    enum cvmx_usb_complete status,
  *                    int pipe_handle,
  *                    int submit_handle,
  *                    int bytes_transferred,
  *                    void *user_data);
- * - @b usb is the cvmx_usb_state_t for the port.
- * - @b reason will always be
- *   CVMX_USB_CALLBACK_PORT_CHANGED.
- * - @b status will always be CVMX_USB_COMPLETE_SUCCESS.
- * - @b pipe_handle will always be -1.
- * - @b submit_handle will always be -1.
- * - @b bytes_transferred will always be 0.
- * - @b user_data is the void pointer originally passed along
+ * - "usb" is the struct cvmx_usb_state for the port.
+ * - "reason" will always be CVMX_USB_CALLBACK_PORT_CHANGED.
+ * - "status" will always be CVMX_USB_COMPLETE_SUCCESS.
+ * - "pipe_handle" will always be -1.
+ * - "submit_handle" will always be -1.
+ * - "bytes_transferred" will always be 0.
+ * - "user_data" is the void pointer originally passed along
  *   with the callback. Use this for any state information you
  *   need.
  *
@@ -140,45 +137,43 @@
  * root port. Normally all the callback needs to do is tell the
  * operating system to poll the root hub for status. Under
  * Linux, this is performed by calling usb_hcd_poll_rh_status().
- * In the Linux driver we use @b user_data. to pass around the
+ * In the Linux driver we use "user_data". to pass around the
  * Linux "hcd" structure. Once the port callback completes,
  * Linux automatically calls octeon_usb_hub_status_data() which
  * uses cvmx_usb_get_status() to determine the root port status.
  *
- * <h2>Complete callback</h2>
+ * == Complete callback ==
  *
  * The completion callback prototype needs to look as follows:
  *
- * void complete_callback(cvmx_usb_state_t *usb,
- *                        cvmx_usb_callback_t reason,
- *                        cvmx_usb_complete_t status,
+ * void complete_callback(struct cvmx_usb_state *usb,
+ *                        enum cvmx_usb_callback reason,
+ *                        enum cvmx_usb_complete status,
  *                        int pipe_handle,
  *                        int submit_handle,
  *                        int bytes_transferred,
  *                        void *user_data);
- * - @b usb is the cvmx_usb_state_t for the port.
- * - @b reason will always be
- *   CVMX_USB_CALLBACK_TRANSFER_COMPLETE.
- * - @b status will be one of the cvmx_usb_complete_t
- *   enumerations.
- * - @b pipe_handle is the handle to the pipe the transaction
+ * - "usb" is the struct cvmx_usb_state for the port.
+ * - "reason" will always be CVMX_USB_CALLBACK_TRANSFER_COMPLETE.
+ * - "status" will be one of the cvmx_usb_complete enumerations.
+ * - "pipe_handle" is the handle to the pipe the transaction
  *   was originally submitted on.
- * - @b submit_handle is the handle returned by the original
+ * - "submit_handle" is the handle returned by the original
  *   cvmx_usb_submit_* call.
- * - @b bytes_transferred is the number of bytes successfully
+ * - "bytes_transferred" is the number of bytes successfully
  *   transferred in the transaction. This will be zero on most
  *   error conditions.
- * - @b user_data is the void pointer originally passed along
+ * - "user_data" is the void pointer originally passed along
  *   with the callback. Use this for any state information you
  *   need. For example, the Linux "urb" is stored in here in the
  *   Linux driver.
  *
- * In general your callback handler should use @b status and @b
- * bytes_transferred to tell the operating system the how the
+ * In general your callback handler should use "status" and
+ * "bytes_transferred" to tell the operating system the how the
  * transaction completed. Normally the pipe is not changed in
  * this callback.
  *
- * <h2>Canceling transactions</h2>
+ * == Canceling transactions ==
  *
  * When a transaction is cancelled using cvmx_usb_cancel*(), the
  * actual length of time until the complete callback is called
@@ -188,7 +183,7 @@
  * these cases, the complete handler will receive
  * CVMX_USB_COMPLETE_CANCEL.
  *
- * <h2>Handling pipes</h2>
+ * == Handling pipes ==
  *
  * USB "pipes" is a software construct created by this API to
  * enable the ordering of usb transactions to a device endpoint.
@@ -210,223 +205,16 @@
  * destroy a pipe for every transaction. A sequence of
  * transaction to the same endpoint must use the same pipe.
  *
- * <h2>Root Hub</h2>
+ * == Root Hub ==
  *
  * Some operating systems view the usb root port as a normal usb
  * hub. These systems attempt to control the root hub with
  * messages similar to the usb 2.0 spec for hub control and
  * status. For these systems it may be necessary to write
  * function to decode standard usb control messages into
- * equivalent cvmx-usb API calls. As an example, the following
- * code is used under Linux for some of the basic hub control
- * messages.
- *
- * @code
- * static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
- * {
- *     cvmx_usb_state_t *usb = (cvmx_usb_state_t *)hcd->hcd_priv;
- *     cvmx_usb_port_status_t usb_port_status;
- *     int port_status;
- *     struct usb_hub_descriptor *desc;
- *     unsigned long flags;
- *
- *     switch (typeReq)
- *     {
- *         case ClearHubFeature:
- *             DEBUG_ROOT_HUB("OcteonUSB: ClearHubFeature\n");
- *             switch (wValue)
- *             {
- *                 case C_HUB_LOCAL_POWER:
- *                 case C_HUB_OVER_CURRENT:
- *                     // Nothing required here
- *                     break;
- *                 default:
- *                     return -EINVAL;
- *             }
- *             break;
- *         case ClearPortFeature:
- *             DEBUG_ROOT_HUB("OcteonUSB: ClearPortFeature");
- *             if (wIndex != 1)
- *             {
- *                 DEBUG_ROOT_HUB(" INVALID\n");
- *                 return -EINVAL;
- *             }
- *
- *             switch (wValue)
- *             {
- *                 case USB_PORT_FEAT_ENABLE:
- *                     DEBUG_ROOT_HUB(" ENABLE");
- *                     local_irq_save(flags);
- *                     cvmx_usb_disable(usb);
- *                     local_irq_restore(flags);
- *                     break;
- *                 case USB_PORT_FEAT_SUSPEND:
- *                     DEBUG_ROOT_HUB(" SUSPEND");
- *                     // Not supported on Octeon
- *                     break;
- *                 case USB_PORT_FEAT_POWER:
- *                     DEBUG_ROOT_HUB(" POWER");
- *                     // Not supported on Octeon
- *                     break;
- *                 case USB_PORT_FEAT_INDICATOR:
- *                     DEBUG_ROOT_HUB(" INDICATOR");
- *                     // Port inidicator not supported
- *                     break;
- *                 case USB_PORT_FEAT_C_CONNECTION:
- *                     DEBUG_ROOT_HUB(" C_CONNECTION");
- *                     // Clears drivers internal connect status change flag
- *                     cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
- *                     break;
- *                 case USB_PORT_FEAT_C_RESET:
- *                     DEBUG_ROOT_HUB(" C_RESET");
- *                     // Clears the driver's internal Port Reset Change flag
- *                     cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
- *                     break;
- *                 case USB_PORT_FEAT_C_ENABLE:
- *                     DEBUG_ROOT_HUB(" C_ENABLE");
- *                     // Clears the driver's internal Port Enable/Disable Change flag
- *                     cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
- *                     break;
- *                 case USB_PORT_FEAT_C_SUSPEND:
- *                     DEBUG_ROOT_HUB(" C_SUSPEND");
- *                     // Clears the driver's internal Port Suspend Change flag,
- *                         which is set when resume signaling on the host port is
- *                         complete
- *                     break;
- *                 case USB_PORT_FEAT_C_OVER_CURRENT:
- *                     DEBUG_ROOT_HUB(" C_OVER_CURRENT");
- *                     // Clears the driver's overcurrent Change flag
- *                     cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
- *                     break;
- *                 default:
- *                     DEBUG_ROOT_HUB(" UNKNOWN\n");
- *                     return -EINVAL;
- *             }
- *             DEBUG_ROOT_HUB("\n");
- *             break;
- *         case GetHubDescriptor:
- *             DEBUG_ROOT_HUB("OcteonUSB: GetHubDescriptor\n");
- *             desc = (struct usb_hub_descriptor *)buf;
- *             desc->bDescLength = 9;
- *             desc->bDescriptorType = 0x29;
- *             desc->bNbrPorts = 1;
- *             desc->wHubCharacteristics = 0x08;
- *             desc->bPwrOn2PwrGood = 1;
- *             desc->bHubContrCurrent = 0;
- *             desc->bitmap[0] = 0;
- *             desc->bitmap[1] = 0xff;
- *             break;
- *         case GetHubStatus:
- *             DEBUG_ROOT_HUB("OcteonUSB: GetHubStatus\n");
- *             *(__le32 *)buf = 0;
- *             break;
- *         case GetPortStatus:
- *             DEBUG_ROOT_HUB("OcteonUSB: GetPortStatus");
- *             if (wIndex != 1)
- *             {
- *                 DEBUG_ROOT_HUB(" INVALID\n");
- *                 return -EINVAL;
- *             }
- *
- *             usb_port_status = cvmx_usb_get_status(usb);
- *             port_status = 0;
- *
- *             if (usb_port_status.connect_change)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
- *                 DEBUG_ROOT_HUB(" C_CONNECTION");
- *             }
- *
- *             if (usb_port_status.port_enabled)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
- *                 DEBUG_ROOT_HUB(" C_ENABLE");
- *             }
- *
- *             if (usb_port_status.connected)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_CONNECTION);
- *                 DEBUG_ROOT_HUB(" CONNECTION");
- *             }
- *
- *             if (usb_port_status.port_enabled)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_ENABLE);
- *                 DEBUG_ROOT_HUB(" ENABLE");
- *             }
+ * equivalent cvmx-usb API calls.
  *
- *             if (usb_port_status.port_over_current)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
- *                 DEBUG_ROOT_HUB(" OVER_CURRENT");
- *             }
- *
- *             if (usb_port_status.port_powered)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_POWER);
- *                 DEBUG_ROOT_HUB(" POWER");
- *             }
- *
- *             if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_HIGHSPEED);
- *                 DEBUG_ROOT_HUB(" HIGHSPEED");
- *             }
- *             else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW)
- *             {
- *                 port_status |= (1 << USB_PORT_FEAT_LOWSPEED);
- *                 DEBUG_ROOT_HUB(" LOWSPEED");
- *             }
- *
- *             *((__le32 *)buf) = cpu_to_le32(port_status);
- *             DEBUG_ROOT_HUB("\n");
- *             break;
- *         case SetHubFeature:
- *             DEBUG_ROOT_HUB("OcteonUSB: SetHubFeature\n");
- *             // No HUB features supported
- *             break;
- *         case SetPortFeature:
- *             DEBUG_ROOT_HUB("OcteonUSB: SetPortFeature");
- *             if (wIndex != 1)
- *             {
- *                 DEBUG_ROOT_HUB(" INVALID\n");
- *                 return -EINVAL;
- *             }
- *
- *             switch (wValue)
- *             {
- *                 case USB_PORT_FEAT_SUSPEND:
- *                     DEBUG_ROOT_HUB(" SUSPEND\n");
- *                     return -EINVAL;
- *                 case USB_PORT_FEAT_POWER:
- *                     DEBUG_ROOT_HUB(" POWER\n");
- *                     return -EINVAL;
- *                 case USB_PORT_FEAT_RESET:
- *                     DEBUG_ROOT_HUB(" RESET\n");
- *                     local_irq_save(flags);
- *                     cvmx_usb_disable(usb);
- *                     if (cvmx_usb_enable(usb))
- *                         DEBUG_ERROR("Failed to enable the port\n");
- *                     local_irq_restore(flags);
- *                     return 0;
- *                 case USB_PORT_FEAT_INDICATOR:
- *                     DEBUG_ROOT_HUB(" INDICATOR\n");
- *                     // Not supported
- *                     break;
- *                 default:
- *                     DEBUG_ROOT_HUB(" UNKNOWN\n");
- *                     return -EINVAL;
- *             }
- *             break;
- *         default:
- *             DEBUG_ROOT_HUB("OcteonUSB: Unknown root hub request\n");
- *             return -EINVAL;
- *     }
- *     return 0;
- * }
- * @endcode
- *
- * <h2>Interrupts</h2>
+ * == Interrupts ==
  *
  * If you plan on using usb interrupts, cvmx_usb_poll() must be
  * called on every usb interrupt. It will read the usb state,
@@ -441,154 +229,187 @@
  *
  * If you aren't using interrupts, simple call cvmx_usb_poll()
  * in your main processing loop.
- *
- * <hr>$Revision: 32636 $<hr>
  */
 
 #ifndef __CVMX_USB_H__
 #define __CVMX_USB_H__
 
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/**
- * Enumerations representing the status of function calls.
- */
-typedef enum
-{
-    CVMX_USB_SUCCESS = 0,           /**< There were no errors */
-    CVMX_USB_INVALID_PARAM = -1,    /**< A parameter to the function was invalid */
-    CVMX_USB_NO_MEMORY = -2,        /**< Insufficient resources were available for the request */
-    CVMX_USB_BUSY = -3,             /**< The resource is busy and cannot service the request */
-    CVMX_USB_TIMEOUT = -4,          /**< Waiting for an action timed out */
-    CVMX_USB_INCORRECT_MODE = -5,   /**< The function call doesn't work in the current USB
-                                         mode. This happens when host only functions are
-                                         called in device mode or vice versa */
-} cvmx_usb_status_t;
-
-/**
- * Enumerations representing the possible USB device speeds
- */
-typedef enum
-{
-    CVMX_USB_SPEED_HIGH = 0,        /**< Device is operation at 480Mbps */
-    CVMX_USB_SPEED_FULL = 1,        /**< Device is operation at 12Mbps */
-    CVMX_USB_SPEED_LOW = 2,         /**< Device is operation at 1.5Mbps */
-} cvmx_usb_speed_t;
-
 /**
- * Enumeration representing the possible USB transfer types.
- */
-typedef enum
-{
-    CVMX_USB_TRANSFER_CONTROL = 0,      /**< USB transfer type control for hub and status transfers */
-    CVMX_USB_TRANSFER_ISOCHRONOUS = 1,  /**< USB transfer type isochronous for low priority periodic transfers */
-    CVMX_USB_TRANSFER_BULK = 2,         /**< USB transfer type bulk for large low priority transfers */
-    CVMX_USB_TRANSFER_INTERRUPT = 3,    /**< USB transfer type interrupt for high priority periodic transfers */
-} cvmx_usb_transfer_t;
-
-/**
- * Enumeration of the transfer directions
- */
-typedef enum
-{
-    CVMX_USB_DIRECTION_OUT,         /**< Data is transferring from Octeon to the device/host */
-    CVMX_USB_DIRECTION_IN,          /**< Data is transferring from the device/host to Octeon */
-} cvmx_usb_direction_t;
-
-/**
- * Enumeration of all possible status codes passed to callback
- * functions.
- */
-typedef enum
-{
-    CVMX_USB_COMPLETE_SUCCESS,      /**< The transaction / operation finished without any errors */
-    CVMX_USB_COMPLETE_SHORT,        /**< FIXME: This is currently not implemented */
-    CVMX_USB_COMPLETE_CANCEL,       /**< The transaction was canceled while in flight by a user call to cvmx_usb_cancel* */
-    CVMX_USB_COMPLETE_ERROR,        /**< The transaction aborted with an unexpected error status */
-    CVMX_USB_COMPLETE_STALL,        /**< The transaction received a USB STALL response from the device */
-    CVMX_USB_COMPLETE_XACTERR,      /**< The transaction failed with an error from the device even after a number of retries */
-    CVMX_USB_COMPLETE_DATATGLERR,   /**< The transaction failed with a data toggle error even after a number of retries */
-    CVMX_USB_COMPLETE_BABBLEERR,    /**< The transaction failed with a babble error */
-    CVMX_USB_COMPLETE_FRAMEERR,     /**< The transaction failed with a frame error even after a number of retries */
-} cvmx_usb_complete_t;
-
-/**
- * Structure returned containing the USB port status information.
- */
-typedef struct
-{
-    uint32_t reserved           : 25;
-    uint32_t port_enabled       : 1; /**< 1 = Usb port is enabled, 0 = disabled */
-    uint32_t port_over_current  : 1; /**< 1 = Over current detected, 0 = Over current not detected. Octeon doesn't support over current detection */
-    uint32_t port_powered       : 1; /**< 1 = Port power is being supplied to the device, 0 = power is off. Octeon doesn't support turning port power off */
-    cvmx_usb_speed_t port_speed : 2; /**< Current port speed */
-    uint32_t connected          : 1; /**< 1 = A device is connected to the port, 0 = No device is connected */
-    uint32_t connect_change     : 1; /**< 1 = Device connected state changed since the last set status call */
-} cvmx_usb_port_status_t;
-
-/**
- * This is the structure of a Control packet header
- */
-typedef union
-{
-    uint64_t u64;
-    struct
-    {
-        uint64_t request_type   : 8;  /**< Bit 7 tells the direction: 1=IN, 0=OUT */
-        uint64_t request        : 8;  /**< The standard usb request to make */
-        uint64_t value          : 16; /**< Value parameter for the request in little endian format */
-        uint64_t index          : 16; /**< Index for the request in little endian format */
-        uint64_t length         : 16; /**< Length of the data associated with this request in little endian format */
-    } s;
-} cvmx_usb_control_header_t;
-
-/**
- * Descriptor for Isochronous packets
- */
-typedef struct
-{
-    int offset;                     /**< This is the offset in bytes into the main buffer where this data is stored */
-    int length;                     /**< This is the length in bytes of the data */
-    cvmx_usb_complete_t status;     /**< This is the status of this individual packet transfer */
-} cvmx_usb_iso_packet_t;
-
-/**
- * Possible callback reasons for the USB API.
- */
-typedef enum
-{
-    CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
-                                    /**< A callback of this type is called when a submitted transfer
-                                        completes. The completion callback will be called even if the
-                                        transfer fails or is canceled. The status parameter will
-                                        contain details of why he callback was called. */
-    CVMX_USB_CALLBACK_PORT_CHANGED, /**< The status of the port changed. For example, someone may have
-                                        plugged a device in. The status parameter contains
-                                        CVMX_USB_COMPLETE_SUCCESS. Use cvmx_usb_get_status() to get
-                                        the new port status. */
-    __CVMX_USB_CALLBACK_END         /**< Do not use. Used internally for array bounds */
-} cvmx_usb_callback_t;
+ * enum cvmx_usb_speed - the possible USB device speeds
+ *
+ * @CVMX_USB_SPEED_HIGH: Device is operation at 480Mbps
+ * @CVMX_USB_SPEED_FULL: Device is operation at 12Mbps
+ * @CVMX_USB_SPEED_LOW:  Device is operation at 1.5Mbps
+ */
+enum cvmx_usb_speed {
+	CVMX_USB_SPEED_HIGH = 0,
+	CVMX_USB_SPEED_FULL = 1,
+	CVMX_USB_SPEED_LOW = 2,
+};
+
+/**
+ * enum cvmx_usb_transfer - the possible USB transfer types
+ *
+ * @CVMX_USB_TRANSFER_CONTROL:	   USB transfer type control for hub and status
+ *				   transfers
+ * @CVMX_USB_TRANSFER_ISOCHRONOUS: USB transfer type isochronous for low
+ *				   priority periodic transfers
+ * @CVMX_USB_TRANSFER_BULK:	   USB transfer type bulk for large low priority
+ *				   transfers
+ * @CVMX_USB_TRANSFER_INTERRUPT:   USB transfer type interrupt for high priority
+ *				   periodic transfers
+ */
+enum cvmx_usb_transfer {
+	CVMX_USB_TRANSFER_CONTROL = 0,
+	CVMX_USB_TRANSFER_ISOCHRONOUS = 1,
+	CVMX_USB_TRANSFER_BULK = 2,
+	CVMX_USB_TRANSFER_INTERRUPT = 3,
+};
+
+/**
+ * enum cvmx_usb_direction - the transfer directions
+ *
+ * @CVMX_USB_DIRECTION_OUT: Data is transferring from Octeon to the device/host
+ * @CVMX_USB_DIRECTION_IN:  Data is transferring from the device/host to Octeon
+ */
+enum cvmx_usb_direction {
+	CVMX_USB_DIRECTION_OUT,
+	CVMX_USB_DIRECTION_IN,
+};
+
+/**
+ * enum cvmx_usb_complete - possible callback function status codes
+ *
+ * @CVMX_USB_COMPLETE_SUCCESS:	  The transaction / operation finished without
+ *				  any errors
+ * @CVMX_USB_COMPLETE_SHORT:	  FIXME: This is currently not implemented
+ * @CVMX_USB_COMPLETE_CANCEL:	  The transaction was canceled while in flight by
+ *				  a user call to cvmx_usb_cancel
+ * @CVMX_USB_COMPLETE_ERROR:	  The transaction aborted with an unexpected
+ *				  error status
+ * @CVMX_USB_COMPLETE_STALL:	  The transaction received a USB STALL response
+ *				  from the device
+ * @CVMX_USB_COMPLETE_XACTERR:	  The transaction failed with an error from the
+ *				  device even after a number of retries
+ * @CVMX_USB_COMPLETE_DATATGLERR: The transaction failed with a data toggle
+ *				  error even after a number of retries
+ * @CVMX_USB_COMPLETE_BABBLEERR:  The transaction failed with a babble error
+ * @CVMX_USB_COMPLETE_FRAMEERR:	  The transaction failed with a frame error
+ *				  even after a number of retries
+ */
+enum cvmx_usb_complete {
+	CVMX_USB_COMPLETE_SUCCESS,
+	CVMX_USB_COMPLETE_SHORT,
+	CVMX_USB_COMPLETE_CANCEL,
+	CVMX_USB_COMPLETE_ERROR,
+	CVMX_USB_COMPLETE_STALL,
+	CVMX_USB_COMPLETE_XACTERR,
+	CVMX_USB_COMPLETE_DATATGLERR,
+	CVMX_USB_COMPLETE_BABBLEERR,
+	CVMX_USB_COMPLETE_FRAMEERR,
+};
+
+/**
+ * struct cvmx_usb_port_status - the USB port status information
+ *
+ * @port_enabled:	1 = Usb port is enabled, 0 = disabled
+ * @port_over_current:	1 = Over current detected, 0 = Over current not
+ *			detected. Octeon doesn't support over current detection.
+ * @port_powered:	1 = Port power is being supplied to the device, 0 =
+ *			power is off. Octeon doesn't support turning port power
+ *			off.
+ * @port_speed:		Current port speed.
+ * @connected:		1 = A device is connected to the port, 0 = No device is
+ *			connected.
+ * @connect_change:	1 = Device connected state changed since the last set
+ *			status call.
+ */
+struct cvmx_usb_port_status {
+	uint32_t reserved		: 25;
+	uint32_t port_enabled		: 1;
+	uint32_t port_over_current	: 1;
+	uint32_t port_powered		: 1;
+	enum cvmx_usb_speed port_speed	: 2;
+	uint32_t connected		: 1;
+	uint32_t connect_change		: 1;
+};
+
+/**
+ * union cvmx_usb_control_header - the structure of a Control packet header
+ *
+ * @s.request_type:	Bit 7 tells the direction: 1=IN, 0=OUT
+ * @s.request		The standard usb request to make
+ * @s.value		Value parameter for the request in little endian format
+ * @s.index		Index for the request in little endian format
+ * @s.length		Length of the data associated with this request in
+ *			little endian format
+ */
+union cvmx_usb_control_header {
+	uint64_t u64;
+	struct {
+		uint64_t request_type   : 8;
+		uint64_t request        : 8;
+		uint64_t value          : 16;
+		uint64_t index          : 16;
+		uint64_t length         : 16;
+	} s;
+};
+
+/**
+ * struct cvmx_usb_iso_packet - descriptor for Isochronous packets
+ *
+ * @offset:	This is the offset in bytes into the main buffer where this data
+ *		is stored.
+ * @length:	This is the length in bytes of the data.
+ * @status:	This is the status of this individual packet transfer.
+ */
+struct cvmx_usb_iso_packet {
+	int offset;
+	int length;
+	enum cvmx_usb_complete status;
+};
+
+/**
+ * enum cvmx_usb_callback - possible callback reasons for the USB API
+ *
+ * @CVMX_USB_CALLBACK_TRANSFER_COMPLETE: A callback of this type is called when
+ *					 a submitted transfer completes. The
+ *					 completion callback will be called even
+ *					 if the transfer fails or is canceled.
+ *					 The status parameter will contain
+ *					 details of why he callback was called.
+ * @CVMX_USB_CALLBACK_PORT_CHANGED:	 The status of the port changed. For
+ *					 example, someone may have plugged a
+ *					 device in. The status parameter
+ *					 contains CVMX_USB_COMPLETE_SUCCESS. Use
+ *					 cvmx_usb_get_status() to get the new
+ *					 port status.
+ * @__CVMX_USB_CALLBACK_END:		 Do not use. Used internally for array
+ *					 bounds.
+ */
+enum cvmx_usb_callback {
+	CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
+	CVMX_USB_CALLBACK_PORT_CHANGED,
+	__CVMX_USB_CALLBACK_END
+};
 
 /**
  * USB state internal data. The contents of this structure
  * may change in future SDKs. No data in it should be referenced
  * by user's of this API.
  */
-typedef struct
-{
-    char data[65536];
-} cvmx_usb_state_t;
+struct cvmx_usb_state {
+	char data[65536];
+};
 
 /**
  * USB callback functions are always of the following type.
  * The parameters are as follows:
  *      - state = USB device state populated by
  *        cvmx_usb_initialize().
- *      - reason = The cvmx_usb_callback_t used to register
+ *      - reason = The enum cvmx_usb_callback used to register
  *        the callback.
- *      - status = The cvmx_usb_complete_t representing the
+ *      - status = The enum cvmx_usb_complete representing the
  *        status code of a transaction.
  *      - pipe_handle = The Pipe that caused this callback, or
  *        -1 if this callback wasn't associated with a pipe.
@@ -599,487 +420,123 @@ typedef struct
  *      - user_data = The user pointer supplied to the
  *        function cvmx_usb_submit() or
  *        cvmx_usb_register_callback() */
-typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state,
-                                         cvmx_usb_callback_t reason,
-                                         cvmx_usb_complete_t status,
+typedef void (*cvmx_usb_callback_func_t)(struct cvmx_usb_state *state,
+                                         enum cvmx_usb_callback reason,
+                                         enum cvmx_usb_complete status,
                                          int pipe_handle, int submit_handle,
                                          int bytes_transferred, void *user_data);
 
 /**
- * Flags to pass the initialization function.
- */
-typedef enum
-{
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1<<0,       /**< The USB port uses a 12MHz crystal as clock source
-                                                            at USB_XO and USB_XI. */
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1<<1,      /**< The USB port uses 12/24/48MHz 2.5V board clock
-                                                            source at USB_XO. USB_XI should be tied to GND.*/
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO = 0,           /**< Automatically determine clock type based on function
-                                                             in cvmx-helper-board.c. */
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK  = 3<<3,       /**< Mask for clock speed field */
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1<<3,       /**< Speed of reference clock or crystal */
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2<<3,       /**< Speed of reference clock */
-    CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3<<3,       /**< Speed of reference clock */
-    /* Bits 3-4 used to encode the clock frequency */
-    CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1<<5,            /**< Disable DMA and used polled IO for data transfer use for the USB  */
-    CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS = 1<<16,  /**< Enable extra console output for debugging USB transfers */
-    CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS = 1<<17,  /**< Enable extra console output for debugging USB callbacks */
-    CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO = 1<<18,       /**< Enable extra console output for USB informational data */
-    CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS = 1<<19,      /**< Enable extra console output for every function call */
-    CVMX_USB_INITIALIZE_FLAGS_DEBUG_CSRS = 1<<20,       /**< Enable extra console output for every CSR access */
-    CVMX_USB_INITIALIZE_FLAGS_DEBUG_ALL = ((CVMX_USB_INITIALIZE_FLAGS_DEBUG_CSRS<<1)-1) - (CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS-1),
-} cvmx_usb_initialize_flags_t;
+ * enum cvmx_usb_initialize_flags - flags to pass the initialization function
+ *
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI:    The USB port uses a 12MHz crystal
+ *					      as clock source at USB_XO and
+ *					      USB_XI.
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND:   The USB port uses 12/24/48MHz 2.5V
+ *					      board clock source at USB_XO.
+ *					      USB_XI should be tied to GND.
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO:     Automatically determine clock type
+ *					      based on function in
+ *					      cvmx-helper-board.c.
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:    Speed of reference clock or
+ *					      crystal
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:    Speed of reference clock
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:    Speed of reference clock
+ * @CVMX_USB_INITIALIZE_FLAGS_NO_DMA:	      Disable DMA and used polled IO for
+ *					      data transfer use for the USB
+ */
+enum cvmx_usb_initialize_flags {
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI		= 1 << 0,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND		= 1 << 1,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO		= 0,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK	= 3 << 3,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ		= 1 << 3,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ		= 2 << 3,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ		= 3 << 3,
+	/* Bits 3-4 used to encode the clock frequency */
+	CVMX_USB_INITIALIZE_FLAGS_NO_DMA		= 1 << 5,
+};
+
+/**
+ * enum cvmx_usb_pipe_flags - flags for passing when a pipe is created.
+ *			      Currently no flags need to be passed.
+ *
+ * @__CVMX_USB_PIPE_FLAGS_OPEN:	     Used internally to determine if a pipe is
+ *				     open. Do not use.
+ * @__CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is
+ *				     actively using hardware. Do not use.
+ * @__CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high
+ *				     speed pipe is in the ping state. Do not
+ *				     use.
+ */
+enum cvmx_usb_pipe_flags {
+	__CVMX_USB_PIPE_FLAGS_OPEN	= 1 << 16,
+	__CVMX_USB_PIPE_FLAGS_SCHEDULED	= 1 << 17,
+	__CVMX_USB_PIPE_FLAGS_NEED_PING	= 1 << 18,
+};
 
-/**
- * Flags for passing when a pipe is created. Currently no flags
- * need to be passed.
- */
-typedef enum
-{
-    CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS = 1<<15,/**< Used to display CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS for a specific pipe only */
-    __CVMX_USB_PIPE_FLAGS_OPEN = 1<<16,         /**< Used internally to determine if a pipe is open. Do not use */
-    __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1<<17,    /**< Used internally to determine if a pipe is actively using hardware. Do not use */
-    __CVMX_USB_PIPE_FLAGS_NEED_PING = 1<<18,    /**< Used internally to determine if a high speed pipe is in the ping state. Do not use */
-} cvmx_usb_pipe_flags_t;
-
-/**
- * Return the number of USB ports supported by this Octeon
- * chip. If the chip doesn't support USB, or is not supported
- * by this API, a zero will be returned. Most Octeon chips
- * support one usb port, but some support two ports.
- * cvmx_usb_initialize() must be called on independent
- * cvmx_usb_state_t structures.
- *
- * @return Number of port, zero if usb isn't supported
- */
 extern int cvmx_usb_get_num_ports(void);
-
-/**
- * Initialize a USB port for use. This must be called before any
- * other access to the Octeon USB port is made. The port starts
- * off in the disabled state.
- *
- * @param state  Pointer to an empty cvmx_usb_state_t structure
- *               that will be populated by the initialize call.
- *               This structure is then passed to all other USB
- *               functions.
- * @param usb_port_number
- *               Which Octeon USB port to initialize.
- * @param flags  Flags to control hardware initialization. See
- *               cvmx_usb_initialize_flags_t for the flag
- *               definitions. Some flags are mandatory.
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state,
-                                             int usb_port_number,
-                                             cvmx_usb_initialize_flags_t flags);
-
-/**
- * Shutdown a USB port after a call to cvmx_usb_initialize().
- * The port should be disabled with all pipes closed when this
- * function is called.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state);
-
-/**
- * Enable a USB port. After this call succeeds, the USB port is
- * online and servicing requests.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state);
-
-/**
- * Disable a USB port. After this call the USB port will not
- * generate data transfers and will not generate events.
- * Transactions in process will fail and call their
- * associated callbacks.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state);
-
-/**
- * Get the current state of the USB port. Use this call to
- * determine if the usb port has anything connected, is enabled,
- * or has some sort of error condition. The return value of this
- * call has "changed" bits to signal of the value of some fields
- * have changed between calls. These "changed" fields are based
- * on the last call to cvmx_usb_set_status(). In order to clear
- * them, you must update the status through cvmx_usb_set_status().
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- *
- * @return Port status information
- */
-extern cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state);
-
-/**
- * Set the current state of the USB port. The status is used as
- * a reference for the "changed" bits returned by
- * cvmx_usb_get_status(). Other than serving as a reference, the
- * status passed to this function is not used. No fields can be
- * changed through this call.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param port_status
- *               Port status to set, most like returned by cvmx_usb_get_status()
- */
-extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status);
-
-/**
- * Open a virtual pipe between the host and a USB device. A pipe
- * must be opened before data can be transferred between a device
- * and Octeon.
- *
- * @param state      USB device state populated by
- *                   cvmx_usb_initialize().
- * @param flags      Optional pipe flags defined in
- *                   cvmx_usb_pipe_flags_t.
- * @param device_addr
- *                   USB device address to open the pipe to
- *                   (0-127).
- * @param endpoint_num
- *                   USB endpoint number to open the pipe to
- *                   (0-15).
- * @param device_speed
- *                   The speed of the device the pipe is going
- *                   to. This must match the device's speed,
- *                   which may be different than the port speed.
- * @param max_packet The maximum packet length the device can
- *                   transmit/receive (low speed=0-8, full
- *                   speed=0-1023, high speed=0-1024). This value
- *                   comes from the standard endpoint descriptor
- *                   field wMaxPacketSize bits <10:0>.
- * @param transfer_type
- *                   The type of transfer this pipe is for.
- * @param transfer_dir
- *                   The direction the pipe is in. This is not
- *                   used for control pipes.
- * @param interval   For ISOCHRONOUS and INTERRUPT transfers,
- *                   this is how often the transfer is scheduled
- *                   for. All other transfers should specify
- *                   zero. The units are in frames (8000/sec at
- *                   high speed, 1000/sec for full speed).
- * @param multi_count
- *                   For high speed devices, this is the maximum
- *                   allowed number of packet per microframe.
- *                   Specify zero for non high speed devices. This
- *                   value comes from the standard endpoint descriptor
- *                   field wMaxPacketSize bits <12:11>.
- * @param hub_device_addr
- *                   Hub device address this device is connected
- *                   to. Devices connected directly to Octeon
- *                   use zero. This is only used when the device
- *                   is full/low speed behind a high speed hub.
- *                   The address will be of the high speed hub,
- *                   not and full speed hubs after it.
- * @param hub_port   Which port on the hub the device is
- *                   connected. Use zero for devices connected
- *                   directly to Octeon. Like hub_device_addr,
- *                   this is only used for full/low speed
- *                   devices behind a high speed hub.
- *
- * @return A non negative value is a pipe handle. Negative
- *         values are failure codes from cvmx_usb_status_t.
- */
-extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state,
-                              cvmx_usb_pipe_flags_t flags,
+extern int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
+			       enum cvmx_usb_initialize_flags flags);
+extern int cvmx_usb_shutdown(struct cvmx_usb_state *state);
+extern int cvmx_usb_enable(struct cvmx_usb_state *state);
+extern int cvmx_usb_disable(struct cvmx_usb_state *state);
+extern struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state);
+extern void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status);
+extern int cvmx_usb_open_pipe(struct cvmx_usb_state *state,
+                              enum cvmx_usb_pipe_flags flags,
                               int device_addr, int endpoint_num,
-                              cvmx_usb_speed_t device_speed, int max_packet,
-                              cvmx_usb_transfer_t transfer_type,
-                              cvmx_usb_direction_t transfer_dir, int interval,
+                              enum cvmx_usb_speed device_speed, int max_packet,
+                              enum cvmx_usb_transfer transfer_type,
+                              enum cvmx_usb_direction transfer_dir, int interval,
                               int multi_count, int hub_device_addr,
                               int hub_port);
-
-/**
- * Call to submit a USB Bulk transfer to a pipe.
- *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
- */
-extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle,
+extern int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle,
                                 uint64_t buffer, int buffer_length,
                                 cvmx_usb_callback_func_t callback,
                                 void *user_data);
-
-/**
- * Call to submit a USB Interrupt transfer to a pipe.
- *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
- */
-extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle,
+extern int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle,
                                      uint64_t buffer, int buffer_length,
                                      cvmx_usb_callback_func_t callback,
                                      void *user_data);
-
-/**
- * Call to submit a USB Control transfer to a pipe.
- *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param control_header
- *                  USB 8 byte control header physical address.
- *                  Note that this is NOT A POINTER, but the
- *                  full 64bit physical address of the buffer.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
- *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
- */
-extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle,
+extern int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle,
                                    uint64_t control_header,
                                    uint64_t buffer, int buffer_length,
                                    cvmx_usb_callback_func_t callback,
                                    void *user_data);
 
 /**
- * Flags to pass the cvmx_usb_submit_isochronous() function.
- */
-typedef enum
-{
-    CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT = 1<<0,  /**< Do not return an error if a transfer is less than the maximum packet size of the device */
-    CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1<<1,         /**< Schedule the transaction as soon as possible */
-} cvmx_usb_isochronous_flags_t;
-
-/**
- * Call to submit a USB Isochronous transfer to a pipe.
- *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param pipe_handle
- *                  Handle to the pipe for the transfer.
- * @param start_frame
- *                  Number of frames into the future to schedule
- *                  this transaction.
- * @param flags     Flags to control the transfer. See
- *                  cvmx_usb_isochronous_flags_t for the flag
- *                  definitions.
- * @param number_packets
- *                  Number of sequential packets to transfer.
- *                  "packets" is a pointer to an array of this
- *                  many packet structures.
- * @param packets   Description of each transfer packet as
- *                  defined by cvmx_usb_iso_packet_t. The array
- *                  pointed to here must stay valid until the
- *                  complete callback is called.
- * @param buffer    Physical address of the data buffer in
- *                  memory. Note that this is NOT A POINTER, but
- *                  the full 64bit physical address of the
- *                  buffer. This may be zero if buffer_length is
- *                  zero.
- * @param buffer_length
- *                  Length of buffer in bytes.
- * @param callback  Function to call when this transaction
- *                  completes. If the return value of this
- *                  function isn't an error, then this function
- *                  is guaranteed to be called when the
- *                  transaction completes. If this parameter is
- *                  NULL, then the generic callback registered
- *                  through cvmx_usb_register_callback is
- *                  called. If both are NULL, then there is no
- *                  way to know when a transaction completes.
- * @param user_data User supplied data returned when the
- *                  callback is called. This is only used if
- *                  callback in not NULL.
+ * enum cvmx_usb_isochronous_flags - flags to pass the
+ *				     cvmx_usb_submit_isochronous() function.
  *
- * @return A submitted transaction handle or negative on
- *         failure. Negative values are failure codes from
- *         cvmx_usb_status_t.
+ * @CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT: Do not return an error if a transfer
+ *					    is less than the maximum packet size
+ *					    of the device.
+ * @CVMX_USB_ISOCHRONOUS_FLAGS_ASAP:	    Schedule the transaction as soon as
+ *					    possible.
  */
-extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle,
+enum cvmx_usb_isochronous_flags {
+	CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT	= 1 << 0,
+	CVMX_USB_ISOCHRONOUS_FLAGS_ASAP		= 1 << 1,
+};
+
+extern int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle,
                                        int start_frame, int flags,
                                        int number_packets,
-                                       cvmx_usb_iso_packet_t packets[],
+                                       struct cvmx_usb_iso_packet packets[],
                                        uint64_t buffer, int buffer_length,
                                        cvmx_usb_callback_func_t callback,
                                        void *user_data);
-
-/**
- * Cancel one outstanding request in a pipe. Canceling a request
- * can fail if the transaction has already completed before cancel
- * is called. Even after a successful cancel call, it may take
- * a frame or two for the cvmx_usb_poll() function to call the
- * associated callback.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe_handle
- *               Pipe handle to cancel requests in.
- * @param submit_handle
- *               Handle to transaction to cancel, returned by the submit function.
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state,
-                                         int pipe_handle, int submit_handle);
-
-
-/**
- * Cancel all outstanding requests in a pipe. Logically all this
- * does is call cvmx_usb_cancel() in a loop.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe_handle
- *               Pipe handle to cancel requests in.
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state,
-                                             int pipe_handle);
-
-/**
- * Close a pipe created with cvmx_usb_open_pipe().
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- * @param pipe_handle
- *               Pipe handle to close.
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t. CVMX_USB_BUSY is returned if the
- *         pipe has outstanding transfers.
- */
-extern cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state,
-                                             int pipe_handle);
-
-/**
- * Register a function to be called when various USB events occur.
- *
- * @param state     USB device state populated by
- *                  cvmx_usb_initialize().
- * @param reason    Which event to register for.
- * @param callback  Function to call when the event occurs.
- * @param user_data User data parameter to the function.
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state,
-                                                    cvmx_usb_callback_t reason,
-                                                    cvmx_usb_callback_func_t callback,
-                                                    void *user_data);
-
-/**
- * Get the current USB protocol level frame number. The frame
- * number is always in the range of 0-0x7ff.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- *
- * @return USB frame number
- */
-extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state);
-
-/**
- * Poll the USB block for status and call all needed callback
- * handlers. This function is meant to be called in the interrupt
- * handler for the USB controller. It can also be called
- * periodically in a loop for non-interrupt based operation.
- *
- * @param state  USB device state populated by
- *               cvmx_usb_initialize().
- *
- * @return CVMX_USB_SUCCESS or a negative error code defined in
- *         cvmx_usb_status_t.
- */
-extern cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state);
-
-#ifdef	__cplusplus
-}
-#endif
+extern int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle,
+			   int submit_handle);
+extern int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle);
+extern int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle);
+extern int cvmx_usb_register_callback(struct cvmx_usb_state *state,
+				      enum cvmx_usb_callback reason,
+				      cvmx_usb_callback_func_t callback,
+				      void *user_data);
+extern int cvmx_usb_get_frame_number(struct cvmx_usb_state *state);
+extern int cvmx_usb_poll(struct cvmx_usb_state *state);
 
 #endif  /* __CVMX_USB_H__ */
diff --git a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h b/drivers/staging/octeon-usb/cvmx-usbcx-defs.h
index 394e846..d349d77 100644
--- a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h
+++ b/drivers/staging/octeon-usb/cvmx-usbcx-defs.h
@@ -140,7 +140,6 @@ union cvmx_usbcx_gahbcfg {
 		uint32_t glblintrmsk	: 1;
 	} s;
 };
-typedef union cvmx_usbcx_gahbcfg cvmx_usbcx_gahbcfg_t;
 
 /**
  * cvmx_usbc#_ghwcfg3
@@ -210,7 +209,6 @@ union cvmx_usbcx_ghwcfg3 {
 		uint32_t xfersizewidth				: 4;
 	} s;
 };
-typedef union cvmx_usbcx_ghwcfg3 cvmx_usbcx_ghwcfg3_t;
 
 /**
  * cvmx_usbc#_gintmsk
@@ -299,7 +297,6 @@ union cvmx_usbcx_gintmsk {
 		uint32_t reserved_0_0		: 1;
 	} s;
 };
-typedef union cvmx_usbcx_gintmsk cvmx_usbcx_gintmsk_t;
 
 /**
  * cvmx_usbc#_gintsts
@@ -529,7 +526,6 @@ union cvmx_usbcx_gintsts {
 		uint32_t curmod		: 1;
 	} s;
 };
-typedef union cvmx_usbcx_gintsts cvmx_usbcx_gintsts_t;
 
 /**
  * cvmx_usbc#_gnptxfsiz
@@ -556,7 +552,6 @@ union cvmx_usbcx_gnptxfsiz {
 		uint32_t nptxfstaddr	: 16;
 	} s;
 };
-typedef union cvmx_usbcx_gnptxfsiz cvmx_usbcx_gnptxfsiz_t;
 
 /**
  * cvmx_usbc#_gnptxsts
@@ -609,7 +604,6 @@ union cvmx_usbcx_gnptxsts {
 		uint32_t nptxfspcavail	: 16;
 	} s;
 };
-typedef union cvmx_usbcx_gnptxsts cvmx_usbcx_gnptxsts_t;
 
 /**
  * cvmx_usbc#_grstctl
@@ -737,7 +731,6 @@ union cvmx_usbcx_grstctl {
 		uint32_t csftrst	: 1;
 	} s;
 };
-typedef union cvmx_usbcx_grstctl cvmx_usbcx_grstctl_t;
 
 /**
  * cvmx_usbc#_grxfsiz
@@ -761,7 +754,6 @@ union cvmx_usbcx_grxfsiz {
 		uint32_t rxfdep		: 16;
 	} s;
 };
-typedef union cvmx_usbcx_grxfsiz cvmx_usbcx_grxfsiz_t;
 
 /**
  * cvmx_usbc#_grxstsph
@@ -807,7 +799,6 @@ union cvmx_usbcx_grxstsph {
 		uint32_t chnum		: 4;
 	} s;
 };
-typedef union cvmx_usbcx_grxstsph cvmx_usbcx_grxstsph_t;
 
 /**
  * cvmx_usbc#_gusbcfg
@@ -896,7 +887,6 @@ union cvmx_usbcx_gusbcfg {
 		uint32_t toutcal	: 3;
 	} s;
 };
-typedef union cvmx_usbcx_gusbcfg cvmx_usbcx_gusbcfg_t;
 
 /**
  * cvmx_usbc#_haint
@@ -922,7 +912,6 @@ union cvmx_usbcx_haint {
 		uint32_t haint		: 16;
 	} s;
 };
-typedef union cvmx_usbcx_haint cvmx_usbcx_haint_t;
 
 /**
  * cvmx_usbc#_haintmsk
@@ -947,7 +936,6 @@ union cvmx_usbcx_haintmsk {
 		uint32_t haintmsk	: 16;
 	} s;
 };
-typedef union cvmx_usbcx_haintmsk cvmx_usbcx_haintmsk_t;
 
 /**
  * cvmx_usbc#_hcchar#
@@ -1027,7 +1015,6 @@ union cvmx_usbcx_hccharx {
 		uint32_t mps		: 11;
 	} s;
 };
-typedef union cvmx_usbcx_hccharx cvmx_usbcx_hccharx_t;
 
 /**
  * cvmx_usbc#_hcfg
@@ -1075,7 +1062,6 @@ union cvmx_usbcx_hcfg {
 		uint32_t fslspclksel	: 2;
 	} s;
 };
-typedef union cvmx_usbcx_hcfg cvmx_usbcx_hcfg_t;
 
 /**
  * cvmx_usbc#_hcint#
@@ -1126,7 +1112,6 @@ union cvmx_usbcx_hcintx {
 		uint32_t xfercompl	: 1;
 	} s;
 };
-typedef union cvmx_usbcx_hcintx cvmx_usbcx_hcintx_t;
 
 /**
  * cvmx_usbc#_hcintmsk#
@@ -1168,7 +1153,6 @@ union cvmx_usbcx_hcintmskx {
 		uint32_t xfercomplmsk	: 1;
 	} s;
 };
-typedef union cvmx_usbcx_hcintmskx cvmx_usbcx_hcintmskx_t;
 
 /**
  * cvmx_usbc#_hcsplt#
@@ -1213,7 +1197,6 @@ union cvmx_usbcx_hcspltx {
 		uint32_t prtaddr	: 7;
 	} s;
 };
-typedef union cvmx_usbcx_hcspltx cvmx_usbcx_hcspltx_t;
 
 /**
  * cvmx_usbc#_hctsiz#
@@ -1257,7 +1240,6 @@ union cvmx_usbcx_hctsizx {
 		uint32_t xfersize	: 19;
 	} s;
 };
-typedef union cvmx_usbcx_hctsizx cvmx_usbcx_hctsizx_t;
 
 /**
  * cvmx_usbc#_hfir
@@ -1293,7 +1275,6 @@ union cvmx_usbcx_hfir {
 		uint32_t frint		: 16;
 	} s;
 };
-typedef union cvmx_usbcx_hfir cvmx_usbcx_hfir_t;
 
 /**
  * cvmx_usbc#_hfnum
@@ -1323,7 +1304,6 @@ union cvmx_usbcx_hfnum {
 		uint32_t frnum	: 16;
 	} s;
 };
-typedef union cvmx_usbcx_hfnum cvmx_usbcx_hfnum_t;
 
 /**
  * cvmx_usbc#_hprt
@@ -1464,7 +1444,6 @@ union cvmx_usbcx_hprt {
 		uint32_t prtconnsts	: 1;
 	} s;
 };
-typedef union cvmx_usbcx_hprt cvmx_usbcx_hprt_t;
 
 /**
  * cvmx_usbc#_hptxfsiz
@@ -1489,7 +1468,6 @@ union cvmx_usbcx_hptxfsiz {
 		uint32_t ptxfstaddr	: 16;
 	} s;
 };
-typedef union cvmx_usbcx_hptxfsiz cvmx_usbcx_hptxfsiz_t;
 
 /**
  * cvmx_usbc#_hptxsts
@@ -1546,6 +1524,5 @@ union cvmx_usbcx_hptxsts {
 		uint32_t ptxfspcavail	: 16;
 	} s;
 };
-typedef union cvmx_usbcx_hptxsts cvmx_usbcx_hptxsts_t;
 
 #endif
diff --git a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h b/drivers/staging/octeon-usb/cvmx-usbnx-defs.h
index 96d7067..e06aafa 100644
--- a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h
+++ b/drivers/staging/octeon-usb/cvmx-usbnx-defs.h
@@ -337,7 +337,6 @@ union cvmx_usbnx_clk_ctl {
 	struct cvmx_usbnx_clk_ctl_cn50xx cn52xx;
 	struct cvmx_usbnx_clk_ctl_cn50xx cn56xx;
 };
-typedef union cvmx_usbnx_clk_ctl cvmx_usbnx_clk_ctl_t;
 
 /**
  * cvmx_usbn#_usbp_ctl_status
@@ -882,6 +881,5 @@ union cvmx_usbnx_usbp_ctl_status {
 		uint64_t ate_reset		: 1;
 	} cn52xx;
 };
-typedef union cvmx_usbnx_usbp_ctl_status cvmx_usbnx_usbp_ctl_status_t;
 
 #endif
diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
index d156b60..5dbbd14 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -26,7 +26,7 @@
 
 struct octeon_hcd {
 	spinlock_t lock;
-	cvmx_usb_state_t usb;
+	struct cvmx_usb_state usb;
 	struct tasklet_struct dequeue_tasklet;
 	struct list_head dequeue_list;
 };
@@ -42,7 +42,7 @@ static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p)
 	return container_of((void *)p, struct usb_hcd, hcd_priv);
 }
 
-static inline struct octeon_hcd *cvmx_usb_to_octeon(cvmx_usb_state_t *p)
+static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p)
 {
 	return container_of(p, struct octeon_hcd, usb);
 }
@@ -58,9 +58,9 @@ static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd)
 	return IRQ_HANDLED;
 }
 
-static void octeon_usb_port_callback(cvmx_usb_state_t *usb,
-				     cvmx_usb_callback_t reason,
-				     cvmx_usb_complete_t status,
+static void octeon_usb_port_callback(struct cvmx_usb_state *usb,
+				     enum cvmx_usb_callback reason,
+				     enum cvmx_usb_complete status,
 				     int pipe_handle,
 				     int submit_handle,
 				     int bytes_transferred,
@@ -105,9 +105,9 @@ static int octeon_usb_get_frame_number(struct usb_hcd *hcd)
 	return cvmx_usb_get_frame_number(&priv->usb);
 }
 
-static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb,
-					     cvmx_usb_callback_t reason,
-					     cvmx_usb_complete_t status,
+static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb,
+					     enum cvmx_usb_callback reason,
+					     enum cvmx_usb_complete status,
 					     int pipe_handle,
 					     int submit_handle,
 					     int bytes_transferred,
@@ -141,7 +141,8 @@ static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb,
 		 * The pointer to the private list is stored in the setup_packet
 		 * field.
 		 */
-		cvmx_usb_iso_packet_t *iso_packet = (cvmx_usb_iso_packet_t *) urb->setup_packet;
+		struct cvmx_usb_iso_packet *iso_packet =
+			(struct cvmx_usb_iso_packet *) urb->setup_packet;
 		/* Recalculate the transfer size by adding up each packet */
 		urb->actual_length = 0;
 		for (i = 0; i < urb->number_of_packets; i++) {
@@ -208,7 +209,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
 	int submit_handle = -1;
 	int pipe_handle;
 	unsigned long flags;
-	cvmx_usb_iso_packet_t *iso_packet;
+	struct cvmx_usb_iso_packet *iso_packet;
 	struct usb_host_endpoint *ep = urb->ep;
 
 	urb->status = 0;
@@ -216,8 +217,8 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
 	spin_lock_irqsave(&priv->lock, flags);
 
 	if (!ep->hcpriv) {
-		cvmx_usb_transfer_t transfer_type;
-		cvmx_usb_speed_t speed;
+		enum cvmx_usb_transfer transfer_type;
+		enum cvmx_usb_speed speed;
 		int split_device = 0;
 		int split_port = 0;
 		switch (usb_pipetype(urb->pipe)) {
@@ -305,7 +306,9 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
 		 * Allocate a structure to use for our private list of
 		 * isochronous packets.
 		 */
-		iso_packet = kmalloc(urb->number_of_packets * sizeof(cvmx_usb_iso_packet_t), GFP_ATOMIC);
+		iso_packet = kmalloc(urb->number_of_packets *
+				     sizeof(struct cvmx_usb_iso_packet),
+				     GFP_ATOMIC);
 		if (iso_packet) {
 			int i;
 			/* Fill the list with the data from the URB */
@@ -440,7 +443,7 @@ static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, struct usb_host_end
 static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
 	struct octeon_hcd *priv = hcd_to_octeon(hcd);
-	cvmx_usb_port_status_t port_status;
+	struct cvmx_usb_port_status port_status;
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -456,7 +459,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 {
 	struct octeon_hcd *priv = hcd_to_octeon(hcd);
 	struct device *dev = hcd->self.controller;
-	cvmx_usb_port_status_t usb_port_status;
+	struct cvmx_usb_port_status usb_port_status;
 	int port_status;
 	struct usb_hub_descriptor *desc;
 	unsigned long flags;
diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig
index fe40e0b..2ff015d 100644
--- a/drivers/staging/olpc_dcon/Kconfig
+++ b/drivers/staging/olpc_dcon/Kconfig
@@ -4,9 +4,14 @@ config FB_OLPC_DCON
 	select I2C
 	select BACKLIGHT_CLASS_DEVICE
 	---help---
-	  Add support for the OLPC XO DCON controller.  This controller is
-	  only available on OLPC platforms.   Unless you have one of these
-	  platforms, you will want to say 'N'.
+	  In order to support very low power operation, the XO laptop uses a
+	  secondary Display CONtroller, or DCON.  This secondary controller
+	  is present in the video pipeline between the primary display
+	  controller (integrate into the processor or chipset) and the LCD
+	  panel.  It allows the main processor/display controller to be
+	  completely powered off while still retaining an image on the display.
+	  This controller is only available on OLPC platforms.  Unless you have
+	  one of these platforms, you will want to say 'N'.
 
 config FB_OLPC_DCON_1
 	bool "OLPC XO-1 DCON support"
diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO
index 35f9cda..f378e84 100644
--- a/drivers/staging/olpc_dcon/TODO
+++ b/drivers/staging/olpc_dcon/TODO
@@ -1,5 +1,4 @@
 TODO:
-	- checkpatch.pl cleanups
 	- see if vx855 gpio API can be made similar enough to cs5535 so we can
 	  share more code
 	- allow simultaneous XO-1 and XO-1.5 support
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 193e1c6..7c460f2 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -131,13 +131,13 @@ power_up:
 			pr_warn("unable to force dcon to power up: %d!\n", x);
 			return x;
 		}
-		msleep(10); /* we'll be conservative */
+		usleep_range(10000, 11000);  /* we'll be conservative */
 	}
 
 	pdata->bus_stabilize_wiggle();
 
 	for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
-		msleep(1);
+		usleep_range(1000, 1100);
 		x = dcon_read(dcon, DCON_REG_ID);
 	}
 	if (x < 0) {
diff --git a/drivers/staging/ozwpan/Kbuild b/drivers/staging/ozwpan/Kbuild
deleted file mode 100644
index 1766a26..0000000
--- a/drivers/staging/ozwpan/Kbuild
+++ /dev/null
@@ -1,18 +0,0 @@
-# -----------------------------------------------------------------------------
-# Copyright (c) 2011 Ozmo Inc
-# Released under the GNU General Public License Version 2 (GPLv2).
-# -----------------------------------------------------------------------------
-obj-$(CONFIG_USB_WPAN_HCD) += ozwpan.o
-ozwpan-y := \
-	ozmain.o \
-	ozpd.o \
-	ozusbsvc.o \
-	ozusbsvc1.o \
-	ozhcd.o \
-	ozeltbuf.o \
-	ozproto.o \
-	ozcdev.o \
-	ozurbparanoia.o \
-	oztrace.o
-
-
diff --git a/drivers/staging/ozwpan/Makefile b/drivers/staging/ozwpan/Makefile
new file mode 100644
index 0000000..29529c1
--- /dev/null
+++ b/drivers/staging/ozwpan/Makefile
@@ -0,0 +1,16 @@
+# -----------------------------------------------------------------------------
+# Copyright (c) 2011 Ozmo Inc
+# Released under the GNU General Public License Version 2 (GPLv2).
+# -----------------------------------------------------------------------------
+
+obj-$(CONFIG_USB_WPAN_HCD) += ozwpan.o
+ozwpan-y := \
+	ozmain.o \
+	ozpd.o \
+	ozusbsvc.o \
+	ozusbsvc1.o \
+	ozhcd.o \
+	ozeltbuf.o \
+	ozproto.o \
+	ozcdev.o \
+	ozurbparanoia.o
diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
index 374fdc3..73b582c 100644
--- a/drivers/staging/ozwpan/ozcdev.c
+++ b/drivers/staging/ozwpan/ozcdev.c
@@ -11,9 +11,8 @@
 #include <linux/etherdevice.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozprotocol.h"
-#include "oztrace.h"
 #include "ozappif.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
@@ -63,7 +62,7 @@ static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd)
 static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
 {
 	if (atomic_dec_and_test(&ctx->ref_count)) {
-		oz_trace("Dealloc serial context.\n");
+		oz_dbg(ON, "Dealloc serial context\n");
 		kfree(ctx);
 	}
 }
@@ -72,10 +71,10 @@ static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
  */
 static int oz_cdev_open(struct inode *inode, struct file *filp)
 {
-	struct oz_cdev *dev;
-	oz_trace("oz_cdev_open()\n");
-	oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode));
-	dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
+	struct oz_cdev *dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
+
+	oz_dbg(ON, "major = %d minor = %d\n", imajor(inode), iminor(inode));
+
 	filp->private_data = dev;
 	return 0;
 }
@@ -84,7 +83,6 @@ static int oz_cdev_open(struct inode *inode, struct file *filp)
  */
 static int oz_cdev_release(struct inode *inode, struct file *filp)
 {
-	oz_trace("oz_cdev_release()\n");
 	return 0;
 }
 /*------------------------------------------------------------------------------
@@ -251,7 +249,7 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
 	switch (cmd) {
 	case OZ_IOCTL_GET_PD_LIST: {
 			struct oz_pd_list list;
-			oz_trace("OZ_IOCTL_GET_PD_LIST\n");
+			oz_dbg(ON, "OZ_IOCTL_GET_PD_LIST\n");
 			memset(&list, 0, sizeof(list));
 			list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS);
 			if (copy_to_user((void __user *)arg, &list,
@@ -261,7 +259,7 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
 		break;
 	case OZ_IOCTL_SET_ACTIVE_PD: {
 			u8 addr[ETH_ALEN];
-			oz_trace("OZ_IOCTL_SET_ACTIVE_PD\n");
+			oz_dbg(ON, "OZ_IOCTL_SET_ACTIVE_PD\n");
 			if (copy_from_user(addr, (void __user *)arg, ETH_ALEN))
 				return -EFAULT;
 			rc = oz_set_active_pd(addr);
@@ -269,7 +267,7 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
 		break;
 	case OZ_IOCTL_GET_ACTIVE_PD: {
 			u8 addr[ETH_ALEN];
-			oz_trace("OZ_IOCTL_GET_ACTIVE_PD\n");
+			oz_dbg(ON, "OZ_IOCTL_GET_ACTIVE_PD\n");
 			spin_lock_bh(&g_cdev.lock);
 			memcpy(addr, g_cdev.active_addr, ETH_ALEN);
 			spin_unlock_bh(&g_cdev.lock);
@@ -302,7 +300,7 @@ static unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
 {
 	unsigned int ret = 0;
 	struct oz_cdev *dev = filp->private_data;
-	oz_trace("Poll called wait = %p\n", wait);
+	oz_dbg(ON, "Poll called wait = %p\n", wait);
 	spin_lock_bh(&dev->lock);
 	if (dev->active_pd) {
 		struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd);
@@ -335,12 +333,13 @@ int oz_cdev_register(void)
 {
 	int err;
 	struct device *dev;
+
 	memset(&g_cdev, 0, sizeof(g_cdev));
 	err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan");
 	if (err < 0)
-		goto out3;
-	oz_trace("Alloc dev number %d:%d\n", MAJOR(g_cdev.devnum),
-			MINOR(g_cdev.devnum));
+		return err;
+	oz_dbg(ON, "Alloc dev number %d:%d\n",
+	       MAJOR(g_cdev.devnum), MINOR(g_cdev.devnum));
 	cdev_init(&g_cdev.cdev, &oz_fops);
 	g_cdev.cdev.owner = THIS_MODULE;
 	g_cdev.cdev.ops = &oz_fops;
@@ -348,27 +347,27 @@ int oz_cdev_register(void)
 	init_waitqueue_head(&g_cdev.rdq);
 	err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1);
 	if (err < 0) {
-		oz_trace("Failed to add cdev\n");
-		goto out2;
+		oz_dbg(ON, "Failed to add cdev\n");
+		goto unregister;
 	}
 	g_oz_class = class_create(THIS_MODULE, "ozmo_wpan");
 	if (IS_ERR(g_oz_class)) {
-		oz_trace("Failed to register ozmo_wpan class\n");
+		oz_dbg(ON, "Failed to register ozmo_wpan class\n");
 		err = PTR_ERR(g_oz_class);
-		goto out1;
+		goto delete;
 	}
 	dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan");
 	if (IS_ERR(dev)) {
-		oz_trace("Failed to create sysfs entry for cdev\n");
+		oz_dbg(ON, "Failed to create sysfs entry for cdev\n");
 		err = PTR_ERR(dev);
-		goto out1;
+		goto delete;
 	}
 	return 0;
-out1:
+
+delete:
 	cdev_del(&g_cdev.cdev);
-out2:
+unregister:
 	unregister_chrdev_region(g_cdev.devnum, 1);
-out3:
 	return err;
 }
 /*------------------------------------------------------------------------------
@@ -407,7 +406,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
 	struct oz_serial_ctx *ctx;
 	struct oz_serial_ctx *old_ctx;
 	if (resume) {
-		oz_trace("Serial service resumed.\n");
+		oz_dbg(ON, "Serial service resumed\n");
 		return 0;
 	}
 	ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC);
@@ -429,10 +428,10 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
 		(memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) {
 		oz_pd_get(pd);
 		g_cdev.active_pd = pd;
-		oz_trace("Active PD arrived.\n");
+		oz_dbg(ON, "Active PD arrived\n");
 	}
 	spin_unlock(&g_cdev.lock);
-	oz_trace("Serial service started.\n");
+	oz_dbg(ON, "Serial service started\n");
 	return 0;
 }
 /*------------------------------------------------------------------------------
@@ -442,7 +441,7 @@ void oz_cdev_stop(struct oz_pd *pd, int pause)
 {
 	struct oz_serial_ctx *ctx;
 	if (pause) {
-		oz_trace("Serial service paused.\n");
+		oz_dbg(ON, "Serial service paused\n");
 		return;
 	}
 	spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
@@ -459,9 +458,9 @@ void oz_cdev_stop(struct oz_pd *pd, int pause)
 	spin_unlock(&g_cdev.lock);
 	if (pd) {
 		oz_pd_put(pd);
-		oz_trace("Active PD departed.\n");
+		oz_dbg(ON, "Active PD departed\n");
 	}
-	oz_trace("Serial service stopped.\n");
+	oz_dbg(ON, "Serial service stopped\n");
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
@@ -478,7 +477,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
 
 	ctx = oz_cdev_claim_ctx(pd);
 	if (ctx == NULL) {
-		oz_trace("Cannot claim serial context.\n");
+		oz_dbg(ON, "Cannot claim serial context\n");
 		return;
 	}
 
@@ -488,8 +487,8 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
 	if (app_hdr->elt_seq_num != 0) {
 		if (((ctx->rx_seq_num - app_hdr->elt_seq_num) & 0x80) == 0) {
 			/* Reject duplicate element. */
-			oz_trace("Duplicate element:%02x %02x\n",
-				app_hdr->elt_seq_num, ctx->rx_seq_num);
+			oz_dbg(ON, "Duplicate element:%02x %02x\n",
+			       app_hdr->elt_seq_num, ctx->rx_seq_num);
 			goto out;
 		}
 	}
@@ -502,7 +501,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
 	if (space < 0)
 		space += OZ_RD_BUF_SZ;
 	if (len > space) {
-		oz_trace("Not enough space:%d %d\n", len, space);
+		oz_dbg(ON, "Not enough space:%d %d\n", len, space);
 		len = space;
 	}
 	ix = ctx->rd_in;
diff --git a/drivers/staging/ozwpan/ozconfig.h b/drivers/staging/ozwpan/ozconfig.h
deleted file mode 100644
index 087c322..0000000
--- a/drivers/staging/ozwpan/ozconfig.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-#ifndef _OZCONFIG_H
-#define _OZCONFIG_H
-
-/* #define WANT_TRACE */
-#ifdef WANT_TRACE
-#define WANT_VERBOSE_TRACE
-#endif /* #ifdef WANT_TRACE */
-/* #define WANT_URB_PARANOIA */
-
-/* #define WANT_PRE_2_6_39 */
-
-/* These defines determine what verbose trace is displayed. */
-#ifdef WANT_VERBOSE_TRACE
-/* #define WANT_TRACE_STREAM */
-/* #define WANT_TRACE_URB */
-/* #define WANT_TRACE_CTRL_DETAIL */
-#define WANT_TRACE_HUB
-/* #define WANT_TRACE_RX_FRAMES */
-/* #define WANT_TRACE_TX_FRAMES */
-#endif /* WANT_VERBOSE_TRACE */
-
-#endif /* _OZCONFIG_H */
diff --git a/drivers/staging/ozwpan/ozdbg.h b/drivers/staging/ozwpan/ozdbg.h
new file mode 100644
index 0000000..b86a2b7
--- /dev/null
+++ b/drivers/staging/ozwpan/ozdbg.h
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * ---------------------------------------------------------------------------*/
+
+#ifndef _OZDBG_H
+#define _OZDBG_H
+
+#define OZ_WANT_DBG 0
+#define OZ_WANT_VERBOSE_DBG 1
+
+#define OZ_DBG_ON		0x0
+#define OZ_DBG_STREAM		0x1
+#define OZ_DBG_URB		0x2
+#define OZ_DBG_CTRL_DETAIL	0x4
+#define OZ_DBG_HUB		0x8
+#define OZ_DBG_RX_FRAMES	0x10
+#define OZ_DBG_TX_FRAMES	0x20
+
+#define OZ_DEFAULT_DBG_MASK			\
+	(					\
+	/* OZ_DBG_STREAM | */			\
+	/* OZ_DBG_URB | */			\
+	/* OZ_DBG_CTRL_DETAIL | */		\
+	OZ_DBG_HUB |				\
+	/* OZ_DBG_RX_FRAMES | */		\
+	/* OZ_DBG_TX_FRAMES | */		\
+	0)
+
+extern unsigned int oz_dbg_mask;
+
+#define oz_want_dbg(mask)						\
+	((OZ_WANT_DBG && (OZ_DBG_##mask == OZ_DBG_ON)) ||		\
+	 (OZ_WANT_VERBOSE_DBG && (OZ_DBG_##mask & oz_dbg_mask)))
+
+#define oz_dbg(mask, fmt, ...)						\
+do {									\
+	if (oz_want_dbg(mask))						\
+		pr_debug(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#define oz_cdev_dbg(cdev, mask, fmt, ...)				\
+do {									\
+	if (oz_want_dbg(mask))						\
+		netdev_dbg((cdev)->dev, fmt, ##__VA_ARGS__);		\
+} while (0)
+
+#define oz_pd_dbg(pd, mask, fmt, ...)					\
+do {									\
+	if (oz_want_dbg(mask))						\
+		pr_debug(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#endif /* _OZDBG_H */
diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c
index ac90fc7..5e98aeb 100644
--- a/drivers/staging/ozwpan/ozeltbuf.c
+++ b/drivers/staging/ozwpan/ozeltbuf.c
@@ -6,11 +6,11 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
-#include "oztrace.h"
+
 /*------------------------------------------------------------------------------
  */
 #define OZ_ELT_INFO_MAGIC_USED	0x35791057
@@ -72,8 +72,8 @@ struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf)
 		buf->free_elts--;
 		spin_unlock_bh(&buf->lock);
 		if (ei->magic != OZ_ELT_INFO_MAGIC_FREE) {
-			oz_trace("oz_elt_info_alloc: ei with bad magic: 0x%x\n",
-				ei->magic);
+			oz_dbg(ON, "%s: ei with bad magic: 0x%x\n",
+			       __func__, ei->magic);
 		}
 	} else {
 		spin_unlock_bh(&buf->lock);
@@ -104,9 +104,8 @@ void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei)
 			buf->elt_pool = &ei->link;
 			ei->magic = OZ_ELT_INFO_MAGIC_FREE;
 		} else {
-			oz_trace("oz_elt_info_free: bad magic ei: %p"
-				" magic: 0x%x\n",
-				ei, ei->magic);
+			oz_dbg(ON, "%s: bad magic ei: %p magic: 0x%x\n",
+			       __func__, ei, ei->magic);
 		}
 	}
 }
@@ -132,7 +131,7 @@ int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count)
 {
 	struct oz_elt_stream *st;
 
-	oz_trace("oz_elt_stream_create(0x%x)\n", id);
+	oz_dbg(ON, "%s: (0x%x)\n", __func__, id);
 
 	st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC | __GFP_ZERO);
 	if (st == NULL)
@@ -152,7 +151,7 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
 {
 	struct list_head *e;
 	struct oz_elt_stream *st = NULL;
-	oz_trace("oz_elt_stream_delete(0x%x)\n", id);
+	oz_dbg(ON, "%s: (0x%x)\n", __func__, id);
 	spin_lock_bh(&buf->lock);
 	e = buf->stream_list.next;
 	while (e != &buf->stream_list) {
@@ -175,9 +174,8 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
 		list_del_init(&ei->link);
 		list_del_init(&ei->link_order);
 		st->buf_count -= ei->length;
-		oz_trace2(OZ_TRACE_STREAM, "Stream down: %d  %d %d\n",
-			st->buf_count,
-			ei->length, atomic_read(&st->ref_count));
+		oz_dbg(STREAM, "Stream down: %d %d %d\n",
+		       st->buf_count, ei->length, atomic_read(&st->ref_count));
 		oz_elt_stream_put(st);
 		oz_elt_info_free(buf, ei);
 	}
@@ -196,7 +194,7 @@ void oz_elt_stream_get(struct oz_elt_stream *st)
 void oz_elt_stream_put(struct oz_elt_stream *st)
 {
 	if (atomic_dec_and_test(&st->ref_count)) {
-		oz_trace("Stream destroyed\n");
+		oz_dbg(ON, "Stream destroyed\n");
 		kfree(st);
 	}
 }
@@ -242,8 +240,7 @@ int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
 		st->buf_count += ei->length;
 		/* Add to list in stream. */
 		list_add_tail(&ei->link, &st->elt_list);
-		oz_trace2(OZ_TRACE_STREAM, "Stream up: %d  %d\n",
-			st->buf_count, ei->length);
+		oz_dbg(STREAM, "Stream up: %d %d\n", st->buf_count, ei->length);
 		/* Check if we have too much buffered for this stream. If so
 		 * start dropping elements until we are back in bounds.
 		 */
@@ -293,9 +290,8 @@ int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
 			list_del(&ei->link_order);
 			if (ei->stream) {
 				ei->stream->buf_count -= ei->length;
-				oz_trace2(OZ_TRACE_STREAM,
-					"Stream down: %d  %d\n",
-					ei->stream->buf_count, ei->length);
+				oz_dbg(STREAM, "Stream down: %d %d\n",
+				       ei->stream->buf_count, ei->length);
 				oz_elt_stream_put(ei->stream);
 				ei->stream = NULL;
 			}
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
index d68d63a..f81a0c5 100644
--- a/drivers/staging/ozwpan/ozhcd.c
+++ b/drivers/staging/ozwpan/ozhcd.c
@@ -26,14 +26,12 @@
  */
 #include <linux/platform_device.h>
 #include <linux/usb.h>
-#include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/export.h>
 #include "linux/usb/hcd.h"
 #include <asm/unaligned.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozusbif.h"
-#include "oztrace.h"
 #include "ozurbparanoia.h"
 #include "ozhcd.h"
 /*------------------------------------------------------------------------------
@@ -50,6 +48,9 @@
 /* Get endpoint object from the containing link.
  */
 #define ep_from_link(__e) container_of((__e), struct oz_endpoint, link)
+/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec)
+ */
+#define EP0_TIMEOUT_COUNTER 13
 /*------------------------------------------------------------------------------
  * Used to link urbs together and also store some status information for each
  * urb.
@@ -61,7 +62,7 @@ struct oz_urb_link {
 	struct oz_port *port;
 	u8 req_id;
 	u8 ep_num;
-	unsigned long submit_jiffies;
+	unsigned submit_counter;
 };
 
 /* Holds state information about a USB endpoint.
@@ -70,7 +71,7 @@ struct oz_endpoint {
 	struct list_head urb_list;	/* List of oz_urb_link items. */
 	struct list_head link;		/* For isoc ep, links in to isoc
 					   lists of oz_port. */
-	unsigned long last_jiffies;
+	struct timespec timestamp;
 	int credit;
 	int credit_ceiling;
 	u8 ep_num;
@@ -188,6 +189,7 @@ static DEFINE_SPINLOCK(g_tasklet_lock);
 static struct tasklet_struct g_urb_process_tasklet;
 static struct tasklet_struct g_urb_cancel_tasklet;
 static atomic_t g_pending_urbs = ATOMIC_INIT(0);
+static atomic_t g_usb_frame_number = ATOMIC_INIT(0);
 static const struct hc_driver g_oz_hc_drv = {
 	.description =		g_hcd_name,
 	.product_desc =		"Ozmo Devices WPAN",
@@ -345,7 +347,7 @@ static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb
  * Context: softirq or process
  */
 static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
-		int status, unsigned long submit_jiffies)
+		int status)
 {
 	struct oz_hcd *ozhcd = oz_hcd_private(hcd);
 	unsigned long irq_state;
@@ -371,15 +373,9 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
 	 */
 	spin_unlock(&g_tasklet_lock);
 	if (oz_forget_urb(urb)) {
-		oz_trace("OZWPAN: ERROR Unknown URB %p\n", urb);
+		oz_dbg(ON, "ERROR Unknown URB %p\n", urb);
 	} else {
-		static unsigned long last_time;
 		atomic_dec(&g_pending_urbs);
-		oz_trace2(OZ_TRACE_URB,
-			"%lu: giveback_urb(%p,%x) %lu %lu pending:%d\n",
-			jiffies, urb, status, jiffies-submit_jiffies,
-			jiffies-last_time, atomic_read(&g_pending_urbs));
-		last_time = jiffies;
 		usb_hcd_giveback_urb(hcd, urb, status);
 	}
 	spin_lock(&g_tasklet_lock);
@@ -394,7 +390,6 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
  */
 static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
 {
-	oz_trace("oz_ep_free()\n");
 	if (port) {
 		struct list_head list;
 		struct oz_hcd *ozhcd = port->ozhcd;
@@ -409,7 +404,7 @@ static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
 		list_splice_tail(&list, &ozhcd->orphanage);
 		spin_unlock_bh(&ozhcd->hcd_lock);
 	}
-	oz_trace("Freeing endpoint memory\n");
+	oz_dbg(ON, "Freeing endpoint memory\n");
 	kfree(ep);
 }
 /*------------------------------------------------------------------------------
@@ -446,9 +441,9 @@ static void oz_complete_buffered_urb(struct oz_port *port,
 		ep->out_ix = 0;
 
 	ep->buffered_units--;
-	oz_trace("Trying to give back buffered frame of size=%d\n",
-						available_space);
-	oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+	oz_dbg(ON, "Trying to give back buffered frame of size=%d\n",
+	       available_space);
+	oz_complete_urb(port->ozhcd->hcd, urb, 0);
 }
 
 /*------------------------------------------------------------------------------
@@ -461,13 +456,13 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
 	struct oz_endpoint *ep;
 	int err = 0;
 	if (ep_addr >= OZ_NB_ENDPOINTS) {
-		oz_trace("Invalid endpoint number in oz_enqueue_ep_urb().\n");
+		oz_dbg(ON, "%s: Invalid endpoint number\n", __func__);
 		return -EINVAL;
 	}
 	urbl = oz_alloc_urb_link();
 	if (!urbl)
 		return -ENOMEM;
-	urbl->submit_jiffies = jiffies;
+	urbl->submit_counter = 0;
 	urbl->urb = urb;
 	urbl->req_id = req_id;
 	urbl->ep_num = ep_addr;
@@ -480,8 +475,8 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
 	 */
 	if (urb->unlinked) {
 		spin_unlock_bh(&port->ozhcd->hcd_lock);
-		oz_trace("urb %p unlinked so complete immediately\n", urb);
-		oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+		oz_dbg(ON, "urb %p unlinked so complete immediately\n", urb);
+		oz_complete_urb(port->ozhcd->hcd, urb, 0);
 		oz_free_urb_link(urbl);
 		return 0;
 	}
@@ -504,7 +499,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
 	if (ep && port->hpd) {
 		list_add_tail(&urbl->link, &ep->urb_list);
 		if (!in_dir && ep_addr && (ep->credit < 0)) {
-			ep->last_jiffies = jiffies;
+			getrawmonotonic(&ep->timestamp);
 			ep->credit = 0;
 		}
 	} else {
@@ -631,7 +626,6 @@ void *oz_hcd_pd_arrived(void *hpd)
 	void *hport = NULL;
 	struct oz_hcd *ozhcd = NULL;
 	struct oz_endpoint *ep;
-	oz_trace("oz_hcd_pd_arrived()\n");
 	ozhcd = oz_hcd_claim();
 	if (ozhcd == NULL)
 		return NULL;
@@ -642,7 +636,7 @@ void *oz_hcd_pd_arrived(void *hpd)
 	spin_lock_bh(&ozhcd->hcd_lock);
 	if (ozhcd->conn_port >= 0) {
 		spin_unlock_bh(&ozhcd->hcd_lock);
-		oz_trace("conn_port >= 0\n");
+		oz_dbg(ON, "conn_port >= 0\n");
 		goto out;
 	}
 	for (i = 0; i < OZ_NB_PORTS; i++) {
@@ -656,7 +650,7 @@ void *oz_hcd_pd_arrived(void *hpd)
 		spin_unlock(&port->port_lock);
 	}
 	if (i < OZ_NB_PORTS) {
-		oz_trace("Setting conn_port = %d\n", i);
+		oz_dbg(ON, "Setting conn_port = %d\n", i);
 		ozhcd->conn_port = i;
 		/* Attach out endpoint 0.
 		 */
@@ -665,7 +659,7 @@ void *oz_hcd_pd_arrived(void *hpd)
 		hport = &ozhcd->ports[i];
 		spin_unlock_bh(&ozhcd->hcd_lock);
 		if (ozhcd->flags & OZ_HDC_F_SUSPENDED) {
-			oz_trace("Resuming root hub\n");
+			oz_dbg(ON, "Resuming root hub\n");
 			usb_hcd_resume_root_hub(ozhcd->hcd);
 		}
 		usb_hcd_poll_rh_status(ozhcd->hcd);
@@ -691,9 +685,8 @@ void oz_hcd_pd_departed(void *hport)
 	void *hpd;
 	struct oz_endpoint *ep = NULL;
 
-	oz_trace("oz_hcd_pd_departed()\n");
 	if (port == NULL) {
-		oz_trace("oz_hcd_pd_departed() port = 0\n");
+		oz_dbg(ON, "%s: port = 0\n", __func__);
 		return;
 	}
 	ozhcd = port->ozhcd;
@@ -704,7 +697,7 @@ void oz_hcd_pd_departed(void *hport)
 	spin_lock_bh(&ozhcd->hcd_lock);
 	if ((ozhcd->conn_port >= 0) &&
 		(port == &ozhcd->ports[ozhcd->conn_port])) {
-		oz_trace("Clearing conn_port\n");
+		oz_dbg(ON, "Clearing conn_port\n");
 		ozhcd->conn_port = -1;
 	}
 	spin_lock(&port->port_lock);
@@ -743,7 +736,7 @@ void oz_hcd_pd_reset(void *hpd, void *hport)
 	 */
 	struct oz_port *port = (struct oz_port *)hport;
 	struct oz_hcd *ozhcd = port->ozhcd;
-	oz_trace("PD Reset\n");
+	oz_dbg(ON, "PD Reset\n");
 	spin_lock_bh(&port->port_lock);
 	port->flags |= OZ_PORT_F_CHANGED;
 	port->status |= USB_PORT_STAT_RESET;
@@ -762,8 +755,8 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc,
 	struct urb *urb;
 	int err = 0;
 
-	oz_trace("oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n",
-			length, offset, total_size);
+	oz_dbg(ON, "oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n",
+	       length, offset, total_size);
 	urb = oz_find_urb_by_id(port, 0, req_id);
 	if (!urb)
 		return;
@@ -795,53 +788,50 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc,
 		}
 	}
 	urb->actual_length = total_size;
-	oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+	oz_complete_urb(port->ozhcd->hcd, urb, 0);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-#ifdef WANT_TRACE
 static void oz_display_conf_type(u8 t)
 {
 	switch (t) {
 	case USB_REQ_GET_STATUS:
-		oz_trace("USB_REQ_GET_STATUS - cnf\n");
+		oz_dbg(ON, "USB_REQ_GET_STATUS - cnf\n");
 		break;
 	case USB_REQ_CLEAR_FEATURE:
-		oz_trace("USB_REQ_CLEAR_FEATURE - cnf\n");
+		oz_dbg(ON, "USB_REQ_CLEAR_FEATURE - cnf\n");
 		break;
 	case USB_REQ_SET_FEATURE:
-		oz_trace("USB_REQ_SET_FEATURE - cnf\n");
+		oz_dbg(ON, "USB_REQ_SET_FEATURE - cnf\n");
 		break;
 	case USB_REQ_SET_ADDRESS:
-		oz_trace("USB_REQ_SET_ADDRESS - cnf\n");
+		oz_dbg(ON, "USB_REQ_SET_ADDRESS - cnf\n");
 		break;
 	case USB_REQ_GET_DESCRIPTOR:
-		oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n");
+		oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
 		break;
 	case USB_REQ_SET_DESCRIPTOR:
-		oz_trace("USB_REQ_SET_DESCRIPTOR - cnf\n");
+		oz_dbg(ON, "USB_REQ_SET_DESCRIPTOR - cnf\n");
 		break;
 	case USB_REQ_GET_CONFIGURATION:
-		oz_trace("USB_REQ_GET_CONFIGURATION - cnf\n");
+		oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - cnf\n");
 		break;
 	case USB_REQ_SET_CONFIGURATION:
-		oz_trace("USB_REQ_SET_CONFIGURATION - cnf\n");
+		oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - cnf\n");
 		break;
 	case USB_REQ_GET_INTERFACE:
-		oz_trace("USB_REQ_GET_INTERFACE - cnf\n");
+		oz_dbg(ON, "USB_REQ_GET_INTERFACE - cnf\n");
 		break;
 	case USB_REQ_SET_INTERFACE:
-		oz_trace("USB_REQ_SET_INTERFACE - cnf\n");
+		oz_dbg(ON, "USB_REQ_SET_INTERFACE - cnf\n");
 		break;
 	case USB_REQ_SYNCH_FRAME:
-		oz_trace("USB_REQ_SYNCH_FRAME - cnf\n");
+		oz_dbg(ON, "USB_REQ_SYNCH_FRAME - cnf\n");
 		break;
 	}
 }
-#else
-#define oz_display_conf_type(__x)
-#endif /* WANT_TRACE */
+
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
@@ -860,7 +850,7 @@ static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb,
 	} else {
 		rc = -ENOMEM;
 	}
-	oz_complete_urb(hcd, urb, rc, 0);
+	oz_complete_urb(hcd, urb, rc);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
@@ -873,7 +863,7 @@ static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb,
 	if (rcode == 0) {
 		struct usb_host_config *config;
 		struct usb_host_interface *intf;
-		oz_trace("Set interface %d alt %d\n", if_num, alt);
+		oz_dbg(ON, "Set interface %d alt %d\n", if_num, alt);
 		oz_clean_endpoints_for_interface(hcd, port, if_num);
 		config = &urb->dev->config[port->config_num-1];
 		intf = &config->intf_cache[if_num]->altsetting[alt];
@@ -885,7 +875,7 @@ static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb,
 	} else {
 		rc = -ENOMEM;
 	}
-	oz_complete_urb(hcd, urb, rc, 0);
+	oz_complete_urb(hcd, urb, rc);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
@@ -900,10 +890,10 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
 	unsigned windex;
 	unsigned wvalue;
 
-	oz_trace("oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len);
+	oz_dbg(ON, "oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len);
 	urb = oz_find_urb_by_id(port, 0, req_id);
 	if (!urb) {
-		oz_trace("URB not found\n");
+		oz_dbg(ON, "URB not found\n");
 		return;
 	}
 	setup = (struct usb_ctrlrequest *)urb->setup_packet;
@@ -922,12 +912,12 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
 				(u8)windex, (u8)wvalue);
 			break;
 		default:
-			oz_complete_urb(hcd, urb, 0, 0);
+			oz_complete_urb(hcd, urb, 0);
 		}
 
 	} else {
 		int copy_len;
-		oz_trace("VENDOR-CLASS - cnf\n");
+		oz_dbg(ON, "VENDOR-CLASS - cnf\n");
 		if (data_len) {
 			if (data_len <= urb->transfer_buffer_length)
 				copy_len = data_len;
@@ -936,7 +926,7 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
 			memcpy(urb->transfer_buffer, data, copy_len);
 			urb->actual_length = copy_len;
 		}
-		oz_complete_urb(hcd, urb, 0, 0);
+		oz_complete_urb(hcd, urb, 0);
 	}
 }
 /*------------------------------------------------------------------------------
@@ -953,7 +943,7 @@ static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data,
 	if (space < 0)
 		space += ep->buffer_size;
 	if (space < (data_len+1)) {
-		oz_trace("Buffer full\n");
+		oz_dbg(ON, "Buffer full\n");
 		return -1;
 	}
 	ep->buffer[ep->in_ix] = (u8)data_len;
@@ -1006,10 +996,10 @@ void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len)
 				copy_len = urb->transfer_buffer_length;
 			memcpy(urb->transfer_buffer, data, copy_len);
 			urb->actual_length = copy_len;
-			oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+			oz_complete_urb(port->ozhcd->hcd, urb, 0);
 			return;
 		} else {
-			oz_trace("buffering frame as URB is not available\n");
+			oz_dbg(ON, "buffering frame as URB is not available\n");
 			oz_hcd_buffer_data(ep, data, data_len);
 		}
 		break;
@@ -1025,7 +1015,7 @@ done:
  */
 static inline int oz_usb_get_frame_number(void)
 {
-	return jiffies_to_msecs(get_jiffies_64());
+	return atomic_inc_return(&g_usb_frame_number);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
@@ -1041,7 +1031,8 @@ int oz_hcd_heartbeat(void *hport)
 	struct list_head *n;
 	struct urb *urb;
 	struct oz_endpoint *ep;
-	unsigned long now = jiffies;
+	struct timespec ts, delta;
+	getrawmonotonic(&ts);
 	INIT_LIST_HEAD(&xfr_list);
 	/* Check the OUT isoc endpoints to see if any URB data can be sent.
 	 */
@@ -1050,10 +1041,11 @@ int oz_hcd_heartbeat(void *hport)
 		ep = ep_from_link(e);
 		if (ep->credit < 0)
 			continue;
-		ep->credit += jiffies_to_msecs(now - ep->last_jiffies);
+		delta = timespec_sub(ts, ep->timestamp);
+		ep->credit += timespec_to_ns(&delta) / NSEC_PER_MSEC;
 		if (ep->credit > ep->credit_ceiling)
 			ep->credit = ep->credit_ceiling;
-		ep->last_jiffies = now;
+		ep->timestamp = ts;
 		while (ep->credit && !list_empty(&ep->urb_list)) {
 			urbl = list_first_entry(&ep->urb_list,
 				struct oz_urb_link, link);
@@ -1061,6 +1053,8 @@ int oz_hcd_heartbeat(void *hport)
 			if ((ep->credit + 1) < urb->number_of_packets)
 				break;
 			ep->credit -= urb->number_of_packets;
+			if (ep->credit < 0)
+				ep->credit = 0;
 			list_move_tail(&urbl->link, &xfr_list);
 		}
 	}
@@ -1068,16 +1062,14 @@ int oz_hcd_heartbeat(void *hport)
 	/* Send to PD and complete URBs.
 	 */
 	list_for_each_safe(e, n, &xfr_list) {
-		unsigned long t;
 		urbl = container_of(e, struct oz_urb_link, link);
 		urb = urbl->urb;
-		t = urbl->submit_jiffies;
 		list_del_init(e);
 		urb->error_count = 0;
 		urb->start_frame = oz_usb_get_frame_number();
 		oz_usb_send_isoc(port->hpd, urbl->ep_num, urb);
 		oz_free_urb_link(urbl);
-		oz_complete_urb(port->ozhcd->hcd, urb, 0, t);
+		oz_complete_urb(port->ozhcd->hcd, urb, 0);
 	}
 	/* Check the IN isoc endpoints to see if any URBs can be completed.
 	 */
@@ -1088,13 +1080,14 @@ int oz_hcd_heartbeat(void *hport)
 			if (ep->buffered_units >= OZ_IN_BUFFERING_UNITS) {
 				ep->flags &= ~OZ_F_EP_BUFFERING;
 				ep->credit = 0;
-				ep->last_jiffies = now;
+				ep->timestamp = ts;
 				ep->start_frame = 0;
 			}
 			continue;
 		}
-		ep->credit += jiffies_to_msecs(now - ep->last_jiffies);
-		ep->last_jiffies = now;
+		delta = timespec_sub(ts, ep->timestamp);
+		ep->credit += timespec_to_ns(&delta) / NSEC_PER_MSEC;
+		ep->timestamp = ts;
 		while (!list_empty(&ep->urb_list)) {
 			struct oz_urb_link *urbl =
 				list_first_entry(&ep->urb_list,
@@ -1103,7 +1096,7 @@ int oz_hcd_heartbeat(void *hport)
 			int len = 0;
 			int copy_len;
 			int i;
-			if ((ep->credit + 1) < urb->number_of_packets)
+			if (ep->credit  < urb->number_of_packets)
 				break;
 			if (ep->buffered_units < urb->number_of_packets)
 				break;
@@ -1149,7 +1142,7 @@ int oz_hcd_heartbeat(void *hport)
 		urb = urbl->urb;
 		list_del_init(e);
 		oz_free_urb_link(urbl);
-		oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+		oz_complete_urb(port->ozhcd->hcd, urb, 0);
 	}
 	/* Check if there are any ep0 requests that have timed out.
 	 * If so resent to PD.
@@ -1161,11 +1154,12 @@ int oz_hcd_heartbeat(void *hport)
 		spin_lock_bh(&ozhcd->hcd_lock);
 		list_for_each_safe(e, n, &ep->urb_list) {
 			urbl = container_of(e, struct oz_urb_link, link);
-			if (time_after(now, urbl->submit_jiffies+HZ/2)) {
-				oz_trace("%ld: Request 0x%p timeout\n",
-						now, urbl->urb);
-				urbl->submit_jiffies = now;
+			if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) {
+				oz_dbg(ON, "Request 0x%p timeout\n", urbl->urb);
 				list_move_tail(e, &xfr_list);
+				urbl->submit_counter = 0;
+			} else {
+				urbl->submit_counter++;
 			}
 		}
 		if (!list_empty(&ep->urb_list))
@@ -1175,7 +1169,7 @@ int oz_hcd_heartbeat(void *hport)
 		while (e != &xfr_list) {
 			urbl = container_of(e, struct oz_urb_link, link);
 			e = e->next;
-			oz_trace("Resending request to PD.\n");
+			oz_dbg(ON, "Resending request to PD\n");
 			oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC);
 			oz_free_urb_link(urbl);
 		}
@@ -1193,7 +1187,7 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
 	int i;
 	int if_ix = intf->desc.bInterfaceNumber;
 	int request_heartbeat = 0;
-	oz_trace("interface[%d] = %p\n", if_ix, intf);
+	oz_dbg(ON, "interface[%d] = %p\n", if_ix, intf);
 	for (i = 0; i < intf->desc.bNumEndpoints; i++) {
 		struct usb_host_endpoint *hep = &intf->endpoint[i];
 		u8 ep_addr = hep->desc.bEndpointAddress;
@@ -1201,7 +1195,7 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
 		struct oz_endpoint *ep;
 		int buffer_size = 0;
 
-		oz_trace("%d bEndpointAddress = %x\n", i, ep_addr);
+		oz_dbg(ON, "%d bEndpointAddress = %x\n", i, ep_addr);
 		if (ep_addr & USB_ENDPOINT_DIR_MASK) {
 			switch (hep->desc.bmAttributes &
 						USB_ENDPOINT_XFERTYPE_MASK) {
@@ -1223,8 +1217,8 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
 		ep->ep_num = ep_num;
 		if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
 			== USB_ENDPOINT_XFER_ISOC) {
-			oz_trace("wMaxPacketSize = %d\n",
-				usb_endpoint_maxp(&hep->desc));
+			oz_dbg(ON, "wMaxPacketSize = %d\n",
+			       usb_endpoint_maxp(&hep->desc));
 			ep->credit_ceiling = 200;
 			if (ep_addr & USB_ENDPOINT_DIR_MASK) {
 				ep->flags |= OZ_F_EP_BUFFERING;
@@ -1270,7 +1264,7 @@ static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd,
 	int i;
 	struct list_head ep_list;
 
-	oz_trace("Deleting endpoints for interface %d\n", if_ix);
+	oz_dbg(ON, "Deleting endpoints for interface %d\n", if_ix);
 	if (if_ix >= port->num_iface)
 		return;
 	INIT_LIST_HEAD(&ep_list);
@@ -1346,12 +1340,12 @@ static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
 {
 	struct oz_hcd *ozhcd = port->ozhcd;
 	int i;
-	oz_trace("Deleting endpoints for configuration.\n");
+	oz_dbg(ON, "Deleting endpoints for configuration\n");
 	for (i = 0; i < port->num_iface; i++)
 		oz_clean_endpoints_for_interface(hcd, port, i);
 	spin_lock_bh(&ozhcd->hcd_lock);
 	if (port->iface) {
-		oz_trace("Freeing interfaces object.\n");
+		oz_dbg(ON, "Freeing interfaces object\n");
 		kfree(port->iface);
 		port->iface = NULL;
 	}
@@ -1390,7 +1384,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
 	int port_ix = -1;
 	struct oz_port *port = NULL;
 
-	oz_trace2(OZ_TRACE_URB, "%lu: oz_process_ep0_urb(%p)\n", jiffies, urb);
+	oz_dbg(URB, "[%s]:(%p)\n", __func__, urb);
 	port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
 	if (port_ix < 0) {
 		rc = -EPIPE;
@@ -1399,8 +1393,8 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
 	port =  &ozhcd->ports[port_ix];
 	if (((port->flags & OZ_PORT_F_PRESENT) == 0)
 		|| (port->flags & OZ_PORT_F_DYING)) {
-		oz_trace("Refusing URB port_ix = %d devnum = %d\n",
-			port_ix, urb->dev->devnum);
+		oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n",
+		       port_ix, urb->dev->devnum);
 		rc = -EPIPE;
 		goto out;
 	}
@@ -1411,17 +1405,16 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
 	windex = le16_to_cpu(setup->wIndex);
 	wvalue = le16_to_cpu(setup->wValue);
 	wlength = le16_to_cpu(setup->wLength);
-	oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequestType = %x\n",
-		setup->bRequestType);
-	oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequest = %x\n", setup->bRequest);
-	oz_trace2(OZ_TRACE_CTRL_DETAIL, "wValue = %x\n", wvalue);
-	oz_trace2(OZ_TRACE_CTRL_DETAIL, "wIndex = %x\n", windex);
-	oz_trace2(OZ_TRACE_CTRL_DETAIL, "wLength = %x\n", wlength);
+	oz_dbg(CTRL_DETAIL, "bRequestType = %x\n", setup->bRequestType);
+	oz_dbg(CTRL_DETAIL, "bRequest = %x\n", setup->bRequest);
+	oz_dbg(CTRL_DETAIL, "wValue = %x\n", wvalue);
+	oz_dbg(CTRL_DETAIL, "wIndex = %x\n", windex);
+	oz_dbg(CTRL_DETAIL, "wLength = %x\n", wlength);
 
 	req_id = port->next_req_id++;
 	hpd = oz_claim_hpd(port);
 	if (hpd == NULL) {
-		oz_trace("Cannot claim port\n");
+		oz_dbg(ON, "Cannot claim port\n");
 		rc = -EPIPE;
 		goto out;
 	}
@@ -1431,30 +1424,31 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
 		 */
 		switch (setup->bRequest) {
 		case USB_REQ_GET_DESCRIPTOR:
-			oz_trace("USB_REQ_GET_DESCRIPTOR - req\n");
+			oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - req\n");
 			break;
 		case USB_REQ_SET_ADDRESS:
-			oz_trace("USB_REQ_SET_ADDRESS - req\n");
-			oz_trace("Port %d address is 0x%x\n", ozhcd->conn_port,
-				(u8)le16_to_cpu(setup->wValue));
+			oz_dbg(ON, "USB_REQ_SET_ADDRESS - req\n");
+			oz_dbg(ON, "Port %d address is 0x%x\n",
+			       ozhcd->conn_port,
+			       (u8)le16_to_cpu(setup->wValue));
 			spin_lock_bh(&ozhcd->hcd_lock);
 			if (ozhcd->conn_port >= 0) {
 				ozhcd->ports[ozhcd->conn_port].bus_addr =
 					(u8)le16_to_cpu(setup->wValue);
-				oz_trace("Clearing conn_port\n");
+				oz_dbg(ON, "Clearing conn_port\n");
 				ozhcd->conn_port = -1;
 			}
 			spin_unlock_bh(&ozhcd->hcd_lock);
 			complete = 1;
 			break;
 		case USB_REQ_SET_CONFIGURATION:
-			oz_trace("USB_REQ_SET_CONFIGURATION - req\n");
+			oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - req\n");
 			break;
 		case USB_REQ_GET_CONFIGURATION:
 			/* We short circuit this case and reply directly since
 			 * we have the selected configuration number cached.
 			 */
-			oz_trace("USB_REQ_GET_CONFIGURATION - reply now\n");
+			oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - reply now\n");
 			if (urb->transfer_buffer_length >= 1) {
 				urb->actual_length = 1;
 				*((u8 *)urb->transfer_buffer) =
@@ -1468,20 +1462,20 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
 			/* We short circuit this case and reply directly since
 			 * we have the selected interface alternative cached.
 			 */
-			oz_trace("USB_REQ_GET_INTERFACE - reply now\n");
+			oz_dbg(ON, "USB_REQ_GET_INTERFACE - reply now\n");
 			if (urb->transfer_buffer_length >= 1) {
 				urb->actual_length = 1;
 				*((u8 *)urb->transfer_buffer) =
 					port->iface[(u8)windex].alt;
-				oz_trace("interface = %d alt = %d\n",
-					windex, port->iface[(u8)windex].alt);
+				oz_dbg(ON, "interface = %d alt = %d\n",
+				       windex, port->iface[(u8)windex].alt);
 				complete = 1;
 			} else {
 				rc = -EPIPE;
 			}
 			break;
 		case USB_REQ_SET_INTERFACE:
-			oz_trace("USB_REQ_SET_INTERFACE - req\n");
+			oz_dbg(ON, "USB_REQ_SET_INTERFACE - req\n");
 			break;
 		}
 	}
@@ -1512,8 +1506,8 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
 	oz_usb_put(hpd);
 out:
 	if (rc || complete) {
-		oz_trace("Completing request locally\n");
-		oz_complete_urb(ozhcd->hcd, urb, rc, 0);
+		oz_dbg(ON, "Completing request locally\n");
+		oz_complete_urb(ozhcd->hcd, urb, rc);
 	} else {
 		oz_usb_request_heartbeat(port->hpd);
 	}
@@ -1577,7 +1571,7 @@ static void oz_urb_process_tasklet(unsigned long unused)
 		oz_free_urb_link(urbl);
 		rc = oz_urb_process(ozhcd, urb);
 		if (rc)
-			oz_complete_urb(ozhcd->hcd, urb, rc, 0);
+			oz_complete_urb(ozhcd->hcd, urb, rc);
 		spin_lock_irqsave(&g_tasklet_lock, irq_state);
 	}
 	spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
@@ -1600,12 +1594,12 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
 	unsigned long irq_state;
 	u8 ix;
 	if (port == NULL) {
-		oz_trace("ERRORERROR: oz_urb_cancel(%p) port is null\n", urb);
+		oz_dbg(ON, "%s: ERROR: (%p) port is null\n", __func__, urb);
 		return;
 	}
 	ozhcd = port->ozhcd;
 	if (ozhcd == NULL) {
-		oz_trace("ERRORERROR: oz_urb_cancel(%p) ozhcd is null\n", urb);
+		oz_dbg(ON, "%s; ERROR: (%p) ozhcd is null\n", __func__, urb);
 		return;
 	}
 
@@ -1630,7 +1624,7 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
 		urbl = container_of(e, struct oz_urb_link, link);
 		if (urbl->urb == urb) {
 			list_del(e);
-			oz_trace("Found urb in orphanage\n");
+			oz_dbg(ON, "Found urb in orphanage\n");
 			goto out;
 		}
 	}
@@ -1646,7 +1640,7 @@ out2:
 	if (urbl) {
 		urb->actual_length = 0;
 		oz_free_urb_link(urbl);
-		oz_complete_urb(ozhcd->hcd, urb, -EPIPE, 0);
+		oz_complete_urb(ozhcd->hcd, urb, -EPIPE);
 	}
 }
 /*------------------------------------------------------------------------------
@@ -1686,7 +1680,7 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
 			urbl = list_first_entry(&ozhcd->orphanage,
 				struct oz_urb_link, link);
 			list_del(&urbl->link);
-			oz_complete_urb(ozhcd->hcd, urbl->urb, status, 0);
+			oz_complete_urb(ozhcd->hcd, urbl->urb, status);
 			oz_free_urb_link(urbl);
 		}
 	}
@@ -1696,7 +1690,6 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
  */
 static int oz_hcd_start(struct usb_hcd *hcd)
 {
-	oz_trace("oz_hcd_start()\n");
 	hcd->power_budget = 200;
 	hcd->state = HC_STATE_RUNNING;
 	hcd->uses_new_polling = 1;
@@ -1707,14 +1700,12 @@ static int oz_hcd_start(struct usb_hcd *hcd)
  */
 static void oz_hcd_stop(struct usb_hcd *hcd)
 {
-	oz_trace("oz_hcd_stop()\n");
 }
 /*------------------------------------------------------------------------------
  * Context: unknown
  */
 static void oz_hcd_shutdown(struct usb_hcd *hcd)
 {
-	oz_trace("oz_hcd_shutdown()\n");
 }
 /*------------------------------------------------------------------------------
  * Called to queue an urb for the device.
@@ -1731,16 +1722,13 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 	struct oz_port *port;
 	unsigned long irq_state;
 	struct oz_urb_link *urbl;
-	oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_enqueue(%p)\n",
-		jiffies, urb);
+	oz_dbg(URB, "%s: (%p)\n",  __func__, urb);
 	if (unlikely(ozhcd == NULL)) {
-		oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not ozhcd.\n",
-			jiffies, urb);
+		oz_dbg(URB, "Refused urb(%p) not ozhcd\n", urb);
 		return -EPIPE;
 	}
 	if (unlikely(hcd->state != HC_STATE_RUNNING)) {
-		oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not running.\n",
-			jiffies, urb);
+		oz_dbg(URB, "Refused urb(%p) not running\n", urb);
 		return -EPIPE;
 	}
 	port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
@@ -1750,8 +1738,8 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 	if (port == NULL)
 		return -EPIPE;
 	if ((port->flags & OZ_PORT_F_PRESENT) == 0) {
-		oz_trace("Refusing URB port_ix = %d devnum = %d\n",
-			port_ix, urb->dev->devnum);
+		oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n",
+		       port_ix, urb->dev->devnum);
 		return -EPIPE;
 	}
 	urb->hcpriv = port;
@@ -1808,7 +1796,7 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	struct oz_urb_link *urbl = NULL;
 	int rc;
 	unsigned long irq_state;
-	oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_dequeue(%p)\n", jiffies, urb);
+	oz_dbg(URB, "%s: (%p)\n",  __func__, urb);
 	urbl = oz_alloc_urb_link();
 	if (unlikely(urbl == NULL))
 		return -ENOMEM;
@@ -1844,7 +1832,6 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
 				struct usb_host_endpoint *ep)
 {
-	oz_trace("oz_hcd_endpoint_disable\n");
 }
 /*------------------------------------------------------------------------------
  * Context: unknown
@@ -1852,14 +1839,13 @@ static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
 static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
 				struct usb_host_endpoint *ep)
 {
-	oz_trace("oz_hcd_endpoint_reset\n");
 }
 /*------------------------------------------------------------------------------
  * Context: unknown
  */
 static int oz_hcd_get_frame_number(struct usb_hcd *hcd)
 {
-	oz_trace("oz_hcd_get_frame_number\n");
+	oz_dbg(ON, "oz_hcd_get_frame_number\n");
 	return oz_usb_get_frame_number();
 }
 /*------------------------------------------------------------------------------
@@ -1872,13 +1858,12 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
 	struct oz_hcd *ozhcd = oz_hcd_private(hcd);
 	int i;
 
-	oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_status_data()\n");
 	buf[0] = 0;
 
 	spin_lock_bh(&ozhcd->hcd_lock);
 	for (i = 0; i < OZ_NB_PORTS; i++) {
 		if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) {
-			oz_trace2(OZ_TRACE_HUB, "Port %d changed\n", i);
+			oz_dbg(HUB, "Port %d changed\n", i);
 			ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED;
 			buf[0] |= 1<<(i+1);
 		}
@@ -1892,7 +1877,6 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
 static void oz_get_hub_descriptor(struct usb_hcd *hcd,
 				struct usb_hub_descriptor *desc)
 {
-	oz_trace2(OZ_TRACE_HUB, "GetHubDescriptor\n");
 	memset(desc, 0, sizeof(*desc));
 	desc->bDescriptorType = 0x29;
 	desc->bDescLength = 9;
@@ -1911,59 +1895,59 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
 	struct oz_hcd *ozhcd = oz_hcd_private(hcd);
 	unsigned set_bits = 0;
 	unsigned clear_bits = 0;
-	oz_trace2(OZ_TRACE_HUB, "SetPortFeature\n");
+
 	if ((port_id < 1) || (port_id > OZ_NB_PORTS))
 		return -EPIPE;
 	port = &ozhcd->ports[port_id-1];
 	switch (wvalue) {
 	case USB_PORT_FEAT_CONNECTION:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n");
 		break;
 	case USB_PORT_FEAT_ENABLE:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n");
 		break;
 	case USB_PORT_FEAT_SUSPEND:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n");
 		break;
 	case USB_PORT_FEAT_OVER_CURRENT:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
 		break;
 	case USB_PORT_FEAT_RESET:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_RESET\n");
 		set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16);
 		clear_bits = USB_PORT_STAT_RESET;
 		ozhcd->ports[port_id-1].bus_addr = 0;
 		break;
 	case USB_PORT_FEAT_POWER:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_POWER\n");
 		set_bits |= USB_PORT_STAT_POWER;
 		break;
 	case USB_PORT_FEAT_LOWSPEED:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n");
 		break;
 	case USB_PORT_FEAT_C_CONNECTION:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n");
 		break;
 	case USB_PORT_FEAT_C_ENABLE:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n");
 		break;
 	case USB_PORT_FEAT_C_SUSPEND:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n");
 		break;
 	case USB_PORT_FEAT_C_OVER_CURRENT:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
 		break;
 	case USB_PORT_FEAT_C_RESET:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n");
 		break;
 	case USB_PORT_FEAT_TEST:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_TEST\n");
 		break;
 	case USB_PORT_FEAT_INDICATOR:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n");
 		break;
 	default:
-		oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue);
+		oz_dbg(HUB, "Other %d\n", wvalue);
 		break;
 	}
 	if (set_bits || clear_bits) {
@@ -1972,8 +1956,7 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
 		port->status |= set_bits;
 		spin_unlock_bh(&port->port_lock);
 	}
-	oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id,
-		port->status);
+	oz_dbg(HUB, "Port[%d] status = 0x%x\n", port_id, port->status);
 	return err;
 }
 /*------------------------------------------------------------------------------
@@ -1986,60 +1969,60 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
 	u8 port_id = (u8)windex;
 	struct oz_hcd *ozhcd = oz_hcd_private(hcd);
 	unsigned clear_bits = 0;
-	oz_trace2(OZ_TRACE_HUB, "ClearPortFeature\n");
+
 	if ((port_id < 1) || (port_id > OZ_NB_PORTS))
 		return -EPIPE;
 	port = &ozhcd->ports[port_id-1];
 	switch (wvalue) {
 	case USB_PORT_FEAT_CONNECTION:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n");
 		break;
 	case USB_PORT_FEAT_ENABLE:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n");
 		clear_bits = USB_PORT_STAT_ENABLE;
 		break;
 	case USB_PORT_FEAT_SUSPEND:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n");
 		break;
 	case USB_PORT_FEAT_OVER_CURRENT:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
 		break;
 	case USB_PORT_FEAT_RESET:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_RESET\n");
 		break;
 	case USB_PORT_FEAT_POWER:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_POWER\n");
 		clear_bits |= USB_PORT_STAT_POWER;
 		break;
 	case USB_PORT_FEAT_LOWSPEED:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n");
 		break;
 	case USB_PORT_FEAT_C_CONNECTION:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n");
 		clear_bits = (USB_PORT_STAT_C_CONNECTION << 16);
 		break;
 	case USB_PORT_FEAT_C_ENABLE:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n");
 		clear_bits = (USB_PORT_STAT_C_ENABLE << 16);
 		break;
 	case USB_PORT_FEAT_C_SUSPEND:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n");
 		break;
 	case USB_PORT_FEAT_C_OVER_CURRENT:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
 		break;
 	case USB_PORT_FEAT_C_RESET:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n");
 		clear_bits = (USB_PORT_FEAT_C_RESET << 16);
 		break;
 	case USB_PORT_FEAT_TEST:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_TEST\n");
 		break;
 	case USB_PORT_FEAT_INDICATOR:
-		oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n");
+		oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n");
 		break;
 	default:
-		oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue);
+		oz_dbg(HUB, "Other %d\n", wvalue);
 		break;
 	}
 	if (clear_bits) {
@@ -2047,8 +2030,8 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
 		port->status &= ~clear_bits;
 		spin_unlock_bh(&port->port_lock);
 	}
-	oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id,
-		ozhcd->ports[port_id-1].status);
+	oz_dbg(HUB, "Port[%d] status = 0x%x\n",
+	       port_id, ozhcd->ports[port_id-1].status);
 	return err;
 }
 /*------------------------------------------------------------------------------
@@ -2061,10 +2044,10 @@ static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf)
 	if ((windex < 1) || (windex > OZ_NB_PORTS))
 		return -EPIPE;
 	ozhcd = oz_hcd_private(hcd);
-	oz_trace2(OZ_TRACE_HUB, "GetPortStatus windex = %d\n", windex);
+	oz_dbg(HUB, "GetPortStatus windex = %d\n", windex);
 	status = ozhcd->ports[windex-1].status;
 	put_unaligned(cpu_to_le32(status), (__le32 *)buf);
-	oz_trace2(OZ_TRACE_HUB, "Port[%d] status = %x\n", windex, status);
+	oz_dbg(HUB, "Port[%d] status = %x\n", windex, status);
 	return 0;
 }
 /*------------------------------------------------------------------------------
@@ -2074,10 +2057,10 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
 				u16 windex, char *buf, u16 wlength)
 {
 	int err = 0;
-	oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_control()\n");
+
 	switch (req_type) {
 	case ClearHubFeature:
-		oz_trace2(OZ_TRACE_HUB, "ClearHubFeature: %d\n", req_type);
+		oz_dbg(HUB, "ClearHubFeature: %d\n", req_type);
 		break;
 	case ClearPortFeature:
 		err = oz_clear_port_feature(hcd, wvalue, windex);
@@ -2086,21 +2069,20 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
 		oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf);
 		break;
 	case GetHubStatus:
-		oz_trace2(OZ_TRACE_HUB, "GetHubStatus: req_type = 0x%x\n",
-			req_type);
+		oz_dbg(HUB, "GetHubStatus: req_type = 0x%x\n", req_type);
 		put_unaligned(__constant_cpu_to_le32(0), (__le32 *)buf);
 		break;
 	case GetPortStatus:
 		err = oz_get_port_status(hcd, windex, buf);
 		break;
 	case SetHubFeature:
-		oz_trace2(OZ_TRACE_HUB, "SetHubFeature: %d\n", req_type);
+		oz_dbg(HUB, "SetHubFeature: %d\n", req_type);
 		break;
 	case SetPortFeature:
 		err = oz_set_port_feature(hcd, wvalue, windex);
 		break;
 	default:
-		oz_trace2(OZ_TRACE_HUB, "Other: %d\n", req_type);
+		oz_dbg(HUB, "Other: %d\n", req_type);
 		break;
 	}
 	return err;
@@ -2111,7 +2093,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
 static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
 {
 	struct oz_hcd *ozhcd;
-	oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_suspend()\n");
+
 	ozhcd = oz_hcd_private(hcd);
 	spin_lock_bh(&ozhcd->hcd_lock);
 	hcd->state = HC_STATE_SUSPENDED;
@@ -2125,7 +2107,7 @@ static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
 static int oz_hcd_bus_resume(struct usb_hcd *hcd)
 {
 	struct oz_hcd *ozhcd;
-	oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_resume()\n");
+
 	ozhcd = oz_hcd_private(hcd);
 	spin_lock_bh(&ozhcd->hcd_lock);
 	ozhcd->flags &= ~OZ_HDC_F_SUSPENDED;
@@ -2137,8 +2119,8 @@ static int oz_hcd_bus_resume(struct usb_hcd *hcd)
  */
 static void oz_plat_shutdown(struct platform_device *dev)
 {
-	oz_trace("oz_plat_shutdown()\n");
 }
+
 /*------------------------------------------------------------------------------
  * Context: process
  */
@@ -2148,10 +2130,10 @@ static int oz_plat_probe(struct platform_device *dev)
 	int err;
 	struct usb_hcd *hcd;
 	struct oz_hcd *ozhcd;
-	oz_trace("oz_plat_probe()\n");
+
 	hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev));
 	if (hcd == NULL) {
-		oz_trace("Failed to created hcd object OK\n");
+		oz_dbg(ON, "Failed to created hcd object OK\n");
 		return -ENOMEM;
 	}
 	ozhcd = oz_hcd_private(hcd);
@@ -2172,7 +2154,7 @@ static int oz_plat_probe(struct platform_device *dev)
 	}
 	err = usb_add_hcd(hcd, 0, 0);
 	if (err) {
-		oz_trace("Failed to add hcd object OK\n");
+		oz_dbg(ON, "Failed to add hcd object OK\n");
 		usb_put_hcd(hcd);
 		return -1;
 	}
@@ -2188,7 +2170,7 @@ static int oz_plat_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct oz_hcd *ozhcd;
-	oz_trace("oz_plat_remove()\n");
+
 	if (hcd == NULL)
 		return -1;
 	ozhcd = oz_hcd_private(hcd);
@@ -2196,30 +2178,31 @@ static int oz_plat_remove(struct platform_device *dev)
 	if (ozhcd == g_ozhcd)
 		g_ozhcd = NULL;
 	spin_unlock_bh(&g_hcdlock);
-	oz_trace("Clearing orphanage\n");
+	oz_dbg(ON, "Clearing orphanage\n");
 	oz_hcd_clear_orphanage(ozhcd, -EPIPE);
-	oz_trace("Removing hcd\n");
+	oz_dbg(ON, "Removing hcd\n");
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
 	oz_empty_link_pool();
 	return 0;
 }
+
 /*------------------------------------------------------------------------------
  * Context: unknown
  */
 static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
 {
-	oz_trace("oz_plat_suspend()\n");
 	return 0;
 }
+
 /*------------------------------------------------------------------------------
  * Context: unknown
  */
 static int oz_plat_resume(struct platform_device *dev)
 {
-	oz_trace("oz_plat_resume()\n");
 	return 0;
 }
+
 /*------------------------------------------------------------------------------
  * Context: process
  */
@@ -2231,7 +2214,7 @@ int oz_hcd_init(void)
 	tasklet_init(&g_urb_process_tasklet, oz_urb_process_tasklet, 0);
 	tasklet_init(&g_urb_cancel_tasklet, oz_urb_cancel_tasklet, 0);
 	err = platform_driver_register(&g_oz_plat_drv);
-	oz_trace("platform_driver_register() returned %d\n", err);
+	oz_dbg(ON, "platform_driver_register() returned %d\n", err);
 	if (err)
 		goto error;
 	g_plat_dev = platform_device_alloc(OZ_PLAT_DEV_NAME, -1);
@@ -2239,11 +2222,11 @@ int oz_hcd_init(void)
 		err = -ENOMEM;
 		goto error1;
 	}
-	oz_trace("platform_device_alloc() succeeded\n");
+	oz_dbg(ON, "platform_device_alloc() succeeded\n");
 	err = platform_device_add(g_plat_dev);
 	if (err)
 		goto error2;
-	oz_trace("platform_device_add() succeeded\n");
+	oz_dbg(ON, "platform_device_add() succeeded\n");
 	return 0;
 error2:
 	platform_device_put(g_plat_dev);
@@ -2252,7 +2235,7 @@ error1:
 error:
 	tasklet_disable(&g_urb_process_tasklet);
 	tasklet_disable(&g_urb_cancel_tasklet);
-	oz_trace("oz_hcd_init() failed %d\n", err);
+	oz_dbg(ON, "oz_hcd_init() failed %d\n", err);
 	return err;
 }
 /*------------------------------------------------------------------------------
@@ -2264,5 +2247,5 @@ void oz_hcd_term(void)
 	tasklet_kill(&g_urb_cancel_tasklet);
 	platform_device_unregister(g_plat_dev);
 	platform_driver_unregister(&g_oz_plat_drv);
-	oz_trace("Pending urbs:%d\n", atomic_read(&g_pending_urbs));
+	oz_dbg(ON, "Pending urbs:%d\n", atomic_read(&g_pending_urbs));
 }
diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c
index 51fe9e9..e26d6be 100644
--- a/drivers/staging/ozwpan/ozmain.c
+++ b/drivers/staging/ozwpan/ozmain.c
@@ -3,6 +3,7 @@
  * Released under the GNU General Public License Version 2 (GPLv2).
  * -----------------------------------------------------------------------------
  */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/timer.h>
@@ -10,11 +11,13 @@
 #include <linux/netdevice.h>
 #include <linux/errno.h>
 #include <linux/ieee80211.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozpd.h"
 #include "ozproto.h"
 #include "ozcdev.h"
-#include "oztrace.h"
+
+unsigned int oz_dbg_mask = OZ_DEFAULT_DBG_MASK;
+
 /*------------------------------------------------------------------------------
  * The name of the 802.11 mac device. Empty string is the default value but a
  * value can be supplied as a parameter to the module. An empty string means
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
index d67dff2..17fd7b2 100644
--- a/drivers/staging/ozwpan/ozpd.c
+++ b/drivers/staging/ozwpan/ozpd.c
@@ -3,23 +3,24 @@
  * Released under the GNU General Public License Version 2 (GPLv2).
  * -----------------------------------------------------------------------------
  */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/netdevice.h>
 #include <linux/errno.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozproto.h"
-#include "oztrace.h"
 #include "ozcdev.h"
 #include "ozusbsvc.h"
 #include <asm/unaligned.h>
 #include <linux/uaccess.h>
 #include <net/psnap.h>
+
 /*------------------------------------------------------------------------------
  */
 #define OZ_MAX_TX_POOL_SIZE	6
@@ -120,22 +121,20 @@ static void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt)
 void oz_pd_set_state(struct oz_pd *pd, unsigned state)
 {
 	pd->state = state;
-#ifdef WANT_TRACE
 	switch (state) {
 	case OZ_PD_S_IDLE:
-		oz_trace("PD State: OZ_PD_S_IDLE\n");
+		oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n");
 		break;
 	case OZ_PD_S_CONNECTED:
-		oz_trace("PD State: OZ_PD_S_CONNECTED\n");
+		oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n");
 		break;
 	case OZ_PD_S_STOPPED:
-		oz_trace("PD State: OZ_PD_S_STOPPED\n");
+		oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n");
 		break;
 	case OZ_PD_S_SLEEP:
-		oz_trace("PD State: OZ_PD_S_SLEEP\n");
+		oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n");
 		break;
 	}
-#endif /* WANT_TRACE */
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
@@ -177,6 +176,14 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
 		pd->last_sent_frame = &pd->tx_queue;
 		spin_lock_init(&pd->stream_lock);
 		INIT_LIST_HEAD(&pd->stream_list);
+		tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler,
+							(unsigned long)pd);
+		tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler,
+							(unsigned long)pd);
+		hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		pd->heartbeat.function = oz_pd_heartbeat_event;
+		pd->timeout.function = oz_pd_timeout_event;
 	}
 	return pd;
 }
@@ -189,7 +196,14 @@ void oz_pd_destroy(struct oz_pd *pd)
 	struct oz_tx_frame *f;
 	struct oz_isoc_stream *st;
 	struct oz_farewell *fwell;
-	oz_trace("Destroying PD\n");
+	oz_pd_dbg(pd, ON, "Destroying PD\n");
+	if (hrtimer_active(&pd->timeout))
+		hrtimer_cancel(&pd->timeout);
+	if (hrtimer_active(&pd->heartbeat))
+		hrtimer_cancel(&pd->heartbeat);
+	/*Disable timer tasklets*/
+	tasklet_kill(&pd->heartbeat_tasklet);
+	tasklet_kill(&pd->timeout_tasklet);
 	/* Delete any streams.
 	 */
 	e = pd->stream_list.next;
@@ -235,13 +249,14 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
 {
 	const struct oz_app_if *ai;
 	int rc = 0;
-	oz_trace("oz_services_start(0x%x) resume(%d)\n", apps, resume);
+	oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume);
 	for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
 		if (apps & (1<<ai->app_id)) {
 			if (ai->start(pd, resume)) {
 				rc = -1;
-				oz_trace("Unabled to start service %d\n",
-					ai->app_id);
+				oz_pd_dbg(pd, ON,
+					  "Unable to start service %d\n",
+					  ai->app_id);
 				break;
 			}
 			oz_polling_lock_bh();
@@ -259,7 +274,7 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
 void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
 {
 	const struct oz_app_if *ai;
-	oz_trace("oz_stop_services(0x%x) pause(%d)\n", apps, pause);
+	oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause);
 	for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
 		if (apps & (1<<ai->app_id)) {
 			oz_polling_lock_bh();
@@ -287,8 +302,8 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
 				more = 1;
 		}
 	}
-	if (more)
-		oz_pd_request_heartbeat(pd);
+	if ((!more) && (hrtimer_active(&pd->heartbeat)))
+		hrtimer_cancel(&pd->heartbeat);
 	if (pd->mode & OZ_F_ISOC_ANYTIME) {
 		int count = 8;
 		while (count-- && (oz_send_isoc_frame(pd) >= 0))
@@ -301,7 +316,7 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
 void oz_pd_stop(struct oz_pd *pd)
 {
 	u16 stop_apps = 0;
-	oz_trace("oz_pd_stop() State = 0x%x\n", pd->state);
+	oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state);
 	oz_pd_indicate_farewells(pd);
 	oz_polling_lock_bh();
 	stop_apps = pd->total_apps;
@@ -314,8 +329,7 @@ void oz_pd_stop(struct oz_pd *pd)
 	/* Remove from PD list.*/
 	list_del(&pd->link);
 	oz_polling_unlock_bh();
-	oz_trace("pd ref count = %d\n", atomic_read(&pd->ref_count));
-	oz_timer_delete(pd, 0);
+	oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count));
 	oz_pd_put(pd);
 }
 /*------------------------------------------------------------------------------
@@ -330,21 +344,18 @@ int oz_pd_sleep(struct oz_pd *pd)
 		oz_polling_unlock_bh();
 		return 0;
 	}
-	if (pd->keep_alive_j && pd->session_id) {
+	if (pd->keep_alive && pd->session_id)
 		oz_pd_set_state(pd, OZ_PD_S_SLEEP);
-		pd->pulse_time_j = jiffies + pd->keep_alive_j;
-		oz_trace("Sleep Now %lu until %lu\n",
-			jiffies, pd->pulse_time_j);
-	} else {
+	else
 		do_stop = 1;
-	}
+
 	stop_apps = pd->total_apps;
 	oz_polling_unlock_bh();
 	if (do_stop) {
 		oz_pd_stop(pd);
 	} else {
 		oz_services_stop(pd, stop_apps, 1);
-		oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1);
+		oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive);
 	}
 	return do_stop;
 }
@@ -384,8 +395,8 @@ static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f)
 	} else {
 		kfree(f);
 	}
-	oz_trace2(OZ_TRACE_TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n",
-						pd->nb_queued_isoc_frames);
+	oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n",
+	       pd->nb_queued_isoc_frames);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
@@ -540,18 +551,16 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data)
 		if ((int)atomic_read(&g_submitted_isoc) <
 							OZ_MAX_SUBMITTED_ISOC) {
 			if (dev_queue_xmit(skb) < 0) {
-				oz_trace2(OZ_TRACE_TX_FRAMES,
-						"Dropping ISOC Frame\n");
+				oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n");
 				return -1;
 			}
 			atomic_inc(&g_submitted_isoc);
-			oz_trace2(OZ_TRACE_TX_FRAMES,
-					"Sending ISOC Frame, nb_isoc= %d\n",
-						pd->nb_queued_isoc_frames);
+			oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n",
+			       pd->nb_queued_isoc_frames);
 			return 0;
 		} else {
 			kfree_skb(skb);
-			oz_trace2(OZ_TRACE_TX_FRAMES, "Dropping ISOC Frame>\n");
+			oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n");
 			return -1;
 		}
 	}
@@ -561,7 +570,7 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data)
 	spin_unlock(&pd->tx_frame_lock);
 	if (more_data)
 		oz_set_more_bit(skb);
-	oz_trace2(OZ_TRACE_TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num);
+	oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num);
 	if (skb) {
 		if (dev_queue_xmit(skb) < 0)
 			return -1;
@@ -627,7 +636,7 @@ static int oz_send_isoc_frame(struct oz_pd *pd)
 		return 0;
 	skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
 	if (skb == NULL) {
-		oz_trace("Cannot alloc skb\n");
+		oz_dbg(ON, "Cannot alloc skb\n");
 		oz_elt_info_free_chain(&pd->elt_buff, &list);
 		return -1;
 	}
@@ -675,8 +684,8 @@ void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn)
 		diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK;
 		if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0))
 			break;
-		oz_trace2(OZ_TRACE_TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n",
-						 pkt_num, pd->nb_queued_frames);
+		oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n",
+		       pkt_num, pd->nb_queued_frames);
 		if (first == NULL)
 			first = e;
 		last = e;
@@ -835,10 +844,20 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
 			struct oz_tx_frame *isoc_unit = NULL;
 			int nb = pd->nb_queued_isoc_frames;
 			if (nb >= pd->isoc_latency) {
-				oz_trace2(OZ_TRACE_TX_FRAMES,
-						"Dropping ISOC Unit nb= %d\n",
-									nb);
-				goto out;
+				struct list_head *e;
+				struct oz_tx_frame *f;
+				oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n",
+				       nb);
+				spin_lock(&pd->tx_frame_lock);
+				list_for_each(e, &pd->tx_queue) {
+					f = container_of(e, struct oz_tx_frame,
+									link);
+					if (f->skb != NULL) {
+						oz_tx_isoc_free(pd, f);
+						break;
+					}
+				}
+				spin_unlock(&pd->tx_frame_lock);
 			}
 			isoc_unit = oz_tx_frame_alloc(pd);
 			if (isoc_unit == NULL)
@@ -849,9 +868,9 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
 			list_add_tail(&isoc_unit->link, &pd->tx_queue);
 			pd->nb_queued_isoc_frames++;
 			spin_unlock_bh(&pd->tx_frame_lock);
-			oz_trace2(OZ_TRACE_TX_FRAMES,
-			"Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n",
-			pd->nb_queued_isoc_frames, pd->nb_queued_frames);
+			oz_dbg(TX_FRAMES,
+			       "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n",
+			       pd->nb_queued_isoc_frames, pd->nb_queued_frames);
 			return 0;
 		}
 
diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h
index fbf47cb..57e98c8 100644
--- a/drivers/staging/ozwpan/ozpd.h
+++ b/drivers/staging/ozwpan/ozpd.h
@@ -6,6 +6,7 @@
 #ifndef _OZPD_H_
 #define _OZPD_H_
 
+#include <linux/interrupt.h>
 #include "ozeltbuf.h"
 
 /* PD state
@@ -47,7 +48,7 @@ struct oz_farewell {
 	struct list_head link;
 	u8 ep_num;
 	u8 index;
-	u8 report[1];
+	u8 report[32];
 	u8 len;
 };
 
@@ -68,18 +69,16 @@ struct oz_pd {
 	u8		isoc_sent;
 	u32		last_rx_pkt_num;
 	u32		last_tx_pkt_num;
+	struct timespec last_rx_timestamp;
 	u32		trigger_pkt_num;
-	unsigned long	pulse_time_j;
-	unsigned long	timeout_time_j;
-	unsigned long	pulse_period_j;
-	unsigned long	presleep_j;
-	unsigned long	keep_alive_j;
-	unsigned long	last_rx_time_j;
+	unsigned long	pulse_time;
+	unsigned long	pulse_period;
+	unsigned long	presleep;
+	unsigned long	keep_alive;
 	struct oz_elt_buf elt_buff;
 	void		*app_ctx[OZ_APPID_MAX];
 	spinlock_t	app_lock[OZ_APPID_MAX];
 	int		max_tx_size;
-	u8		heartbeat_requested;
 	u8		mode;
 	u8		ms_per_isoc;
 	unsigned	isoc_latency;
@@ -95,6 +94,11 @@ struct oz_pd {
 	spinlock_t	stream_lock;
 	struct list_head stream_list;
 	struct net_device *net_dev;
+	struct hrtimer  heartbeat;
+	struct hrtimer  timeout;
+	u8      timeout_type;
+	struct tasklet_struct   heartbeat_tasklet;
+	struct tasklet_struct   timeout_tasklet;
 };
 
 #define OZ_MAX_QUEUED_FRAMES	4
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
index 79ac7b5..084307a 100644
--- a/drivers/staging/ozwpan/ozproto.c
+++ b/drivers/staging/ozwpan/ozproto.c
@@ -3,6 +3,7 @@
  * Released under the GNU General Public License Version 2 (GPLv2).
  * -----------------------------------------------------------------------------
  */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/timer.h>
@@ -10,13 +11,13 @@
 #include <linux/netdevice.h>
 #include <linux/errno.h>
 #include <linux/ieee80211.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozproto.h"
 #include "ozusbsvc.h"
-#include "oztrace.h"
+
 #include "ozappif.h"
 #include <asm/unaligned.h>
 #include <linux/uaccess.h>
@@ -29,12 +30,6 @@
 #define OZ_DO_STOP		1
 #define OZ_DO_SLEEP		2
 
-/* States of the timer.
- */
-#define OZ_TIMER_IDLE		0
-#define OZ_TIMER_SET		1
-#define OZ_TIMER_IN_HANDLER	2
-
 #define OZ_MAX_TIMER_POOL_SIZE	16
 
 /*------------------------------------------------------------------------------
@@ -42,35 +37,20 @@
 struct oz_binding {
 	struct packet_type ptype;
 	char name[OZ_MAX_BINDING_LEN];
-	struct oz_binding *next;
-};
-
-struct oz_timer {
 	struct list_head link;
-	struct oz_pd *pd;
-	unsigned long due_time;
-	int type;
 };
+
 /*------------------------------------------------------------------------------
  * Static external variables.
  */
 static DEFINE_SPINLOCK(g_polling_lock);
 static LIST_HEAD(g_pd_list);
-static struct oz_binding *g_binding ;
+static LIST_HEAD(g_binding);
 static DEFINE_SPINLOCK(g_binding_lock);
 static struct sk_buff_head g_rx_queue;
 static u8 g_session_id;
 static u16 g_apps = 0x1;
 static int g_processing_rx;
-static struct timer_list g_timer;
-static struct oz_timer *g_cur_timer;
-static struct list_head *g_timer_pool;
-static int g_timer_pool_count;
-static int g_timer_state = OZ_TIMER_IDLE;
-static LIST_HEAD(g_timer_list);
-/*------------------------------------------------------------------------------
- */
-static void oz_protocol_timer_start(void);
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
@@ -124,7 +104,7 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
 		body->session_id = pd->session_id;
 		put_unaligned(cpu_to_le16(pd->total_apps), &body->apps);
 	}
-	oz_trace("TX: OZ_ELT_CONNECT_RSP %d", status);
+	oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status);
 	dev_queue_xmit(skb);
 	return;
 }
@@ -137,33 +117,37 @@ static void pd_set_keepalive(struct oz_pd *pd, u8 kalive)
 
 	switch (kalive & OZ_KALIVE_TYPE_MASK) {
 	case OZ_KALIVE_SPECIAL:
-		pd->keep_alive_j =
-			oz_ms_to_jiffies(keep_alive * 1000*60*60*24*20);
+		pd->keep_alive = keep_alive * 1000*60*60*24*20;
 		break;
 	case OZ_KALIVE_SECS:
-		pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000);
+		pd->keep_alive = keep_alive*1000;
 		break;
 	case OZ_KALIVE_MINS:
-		pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60);
+		pd->keep_alive = keep_alive*1000*60;
 		break;
 	case OZ_KALIVE_HOURS:
-		pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60*60);
+		pd->keep_alive = keep_alive*1000*60*60;
 		break;
 	default:
-		pd->keep_alive_j = 0;
+		pd->keep_alive = 0;
 	}
-	oz_trace("Keepalive = %lu jiffies\n", pd->keep_alive_j);
+	oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-static void pd_set_presleep(struct oz_pd *pd, u8 presleep)
+static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer)
 {
 	if (presleep)
-		pd->presleep_j = oz_ms_to_jiffies(presleep*100);
+		pd->presleep = presleep*100;
 	else
-		pd->presleep_j = OZ_PRESLEEP_TOUT_J;
-	oz_trace("Presleep time = %lu jiffies\n", pd->presleep_j);
+		pd->presleep = OZ_PRESLEEP_TOUT;
+	if (start_timer) {
+		spin_unlock(&g_polling_lock);
+		oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
+		spin_lock(&g_polling_lock);
+	}
+	oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
@@ -188,7 +172,7 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
 		pd = oz_pd_alloc(pd_addr);
 		if (pd == NULL)
 			return NULL;
-		pd->last_rx_time_j = jiffies;
+		getnstimeofday(&pd->last_rx_timestamp);
 		spin_lock_bh(&g_polling_lock);
 		list_for_each(e, &g_pd_list) {
 			pd2 = container_of(e, struct oz_pd, link);
@@ -210,7 +194,7 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
 		dev_hold(net_dev);
 		pd->net_dev = net_dev;
 	}
-	oz_trace("Host vendor: %d\n", body->host_vendor);
+	oz_dbg(ON, "Host vendor: %d\n", body->host_vendor);
 	pd->max_tx_size = OZ_MAX_TX_SIZE;
 	pd->mode = body->mode;
 	pd->pd_info = body->pd_info;
@@ -234,12 +218,11 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
 	}
 	if (body->max_len_div16)
 		pd->max_tx_size = ((u16)body->max_len_div16)<<4;
-	oz_trace("Max frame:%u Ms per isoc:%u\n",
-		pd->max_tx_size, pd->ms_per_isoc);
+	oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n",
+	       pd->max_tx_size, pd->ms_per_isoc);
 	pd->max_stream_buffering = 3*1024;
-	pd->timeout_time_j = jiffies + OZ_CONNECTION_TOUT_J;
-	pd->pulse_period_j = OZ_QUANTUM_J;
-	pd_set_presleep(pd, body->presleep);
+	pd->pulse_period = OZ_QUANTUM;
+	pd_set_presleep(pd, body->presleep, 0);
 	pd_set_keepalive(pd, body->keep_alive);
 
 	new_apps &= le16_to_cpu(get_unaligned(&body->apps));
@@ -271,9 +254,8 @@ done:
 		u16 resume_apps = new_apps & pd->paused_apps  & ~0x1;
 		spin_unlock_bh(&g_polling_lock);
 		oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
-		oz_timer_delete(pd, OZ_TIMER_STOP);
-		oz_trace("new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n",
-			new_apps, pd->total_apps, pd->paused_apps);
+		oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n",
+		       new_apps, pd->total_apps, pd->paused_apps);
 		if (start_apps) {
 			if (oz_services_start(pd, start_apps, 0))
 				rsp_status = OZ_STATUS_TOO_MANY_PDS;
@@ -314,8 +296,9 @@ static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index,
 		return;
 	f->ep_num = ep_num;
 	f->index = index;
+	f->len = len;
 	memcpy(f->report, report, len);
-	oz_trace("RX: Adding farewell report\n");
+	oz_dbg(ON, "RX: Adding farewell report\n");
 	spin_lock(&g_polling_lock);
 	list_for_each_entry(f2, &pd->farewell_list, link) {
 		if ((f2->ep_num == ep_num) && (f2->index == index)) {
@@ -340,20 +323,20 @@ static void oz_rx_frame(struct sk_buff *skb)
 	int length;
 	struct oz_pd *pd = NULL;
 	struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
+	struct timespec current_time;
 	int dup = 0;
 	u32 pkt_num;
 
-	oz_trace2(OZ_TRACE_RX_FRAMES,
-		"RX frame PN=0x%x LPN=0x%x control=0x%x\n",
-		oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control);
+	oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n",
+	       oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control);
 	mac_hdr = skb_mac_header(skb);
 	src_addr = &mac_hdr[ETH_ALEN] ;
 	length = skb->len;
 
 	/* Check the version field */
 	if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) {
-		oz_trace("Incorrect protocol version: %d\n",
-			oz_get_prot_ver(oz_hdr->control));
+		oz_dbg(ON, "Incorrect protocol version: %d\n",
+		       oz_get_prot_ver(oz_hdr->control));
 		goto done;
 	}
 
@@ -361,19 +344,24 @@ static void oz_rx_frame(struct sk_buff *skb)
 
 	pd = oz_pd_find(src_addr);
 	if (pd) {
-		pd->last_rx_time_j = jiffies;
-		oz_timer_add(pd, OZ_TIMER_TOUT,
-			pd->last_rx_time_j + pd->presleep_j, 1);
+		if (!(pd->state & OZ_PD_S_CONNECTED))
+			oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
+		getnstimeofday(&current_time);
+		if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) ||
+			(pd->presleep < MSEC_PER_SEC))  {
+			oz_timer_add(pd, OZ_TIMER_TOUT,	pd->presleep);
+			pd->last_rx_timestamp = current_time;
+		}
 		if (pkt_num != pd->last_rx_pkt_num) {
 			pd->last_rx_pkt_num = pkt_num;
 		} else {
 			dup = 1;
-			oz_trace("Duplicate frame\n");
+			oz_dbg(ON, "Duplicate frame\n");
 		}
 	}
 
 	if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) {
-		oz_trace2(OZ_TRACE_RX_FRAMES, "Received TRIGGER Frame\n");
+		oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n");
 		pd->last_sent_frame = &pd->tx_queue;
 		if (oz_hdr->control & OZ_F_ACK) {
 			/* Retire completed frames */
@@ -397,22 +385,22 @@ static void oz_rx_frame(struct sk_buff *skb)
 			break;
 		switch (elt->type) {
 		case OZ_ELT_CONNECT_REQ:
-			oz_trace("RX: OZ_ELT_CONNECT_REQ\n");
+			oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n");
 			pd = oz_connect_req(pd, elt, src_addr, skb->dev);
 			break;
 		case OZ_ELT_DISCONNECT:
-			oz_trace("RX: OZ_ELT_DISCONNECT\n");
+			oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n");
 			if (pd)
 				oz_pd_sleep(pd);
 			break;
 		case OZ_ELT_UPDATE_PARAM_REQ: {
 				struct oz_elt_update_param *body =
 					(struct oz_elt_update_param *)(elt + 1);
-				oz_trace("RX: OZ_ELT_UPDATE_PARAM_REQ\n");
+				oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n");
 				if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
 					spin_lock(&g_polling_lock);
 					pd_set_keepalive(pd, body->keepalive);
-					pd_set_presleep(pd, body->presleep);
+					pd_set_presleep(pd, body->presleep, 1);
 					spin_unlock(&g_polling_lock);
 				}
 			}
@@ -420,7 +408,7 @@ static void oz_rx_frame(struct sk_buff *skb)
 		case OZ_ELT_FAREWELL_REQ: {
 				struct oz_elt_farewell *body =
 					(struct oz_elt_farewell *)(elt + 1);
-				oz_trace("RX: OZ_ELT_FAREWELL_REQ\n");
+				oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n");
 				oz_add_farewell(pd, body->ep_num,
 					body->index, body->report,
 					elt->length + 1 - sizeof(*body));
@@ -436,7 +424,7 @@ static void oz_rx_frame(struct sk_buff *skb)
 			}
 			break;
 		default:
-			oz_trace("RX: Unknown elt %02x\n", elt->type);
+			oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type);
 		}
 		elt = oz_next_elt(elt);
 	}
@@ -450,14 +438,13 @@ done:
  */
 void oz_protocol_term(void)
 {
-	struct list_head *chain;
-	del_timer_sync(&g_timer);
+	struct oz_binding *b, *t;
+
 	/* Walk the list of bindings and remove each one.
 	 */
 	spin_lock_bh(&g_binding_lock);
-	while (g_binding) {
-		struct oz_binding *b = g_binding;
-		g_binding = b->next;
+	list_for_each_entry_safe(b, t, &g_binding, link) {
+		list_del(&b->link);
 		spin_unlock_bh(&g_binding_lock);
 		dev_remove_pack(&b->ptype);
 		if (b->ptype.dev)
@@ -480,21 +467,35 @@ void oz_protocol_term(void)
 		oz_pd_put(pd);
 		spin_lock_bh(&g_polling_lock);
 	}
-	chain = g_timer_pool;
-	g_timer_pool = NULL;
 	spin_unlock_bh(&g_polling_lock);
-	while (chain) {
-		struct oz_timer *t = container_of(chain, struct oz_timer, link);
-		chain = chain->next;
-		kfree(t);
-	}
-	oz_trace("Protocol stopped\n");
+	oz_dbg(ON, "Protocol stopped\n");
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-static void oz_pd_handle_timer(struct oz_pd *pd, int type)
+void oz_pd_heartbeat_handler(unsigned long data)
 {
+	struct oz_pd *pd = (struct oz_pd *)data;
+	u16 apps = 0;
+	spin_lock_bh(&g_polling_lock);
+	if (pd->state & OZ_PD_S_CONNECTED)
+		apps = pd->total_apps;
+	spin_unlock_bh(&g_polling_lock);
+	if (apps)
+		oz_pd_heartbeat(pd, apps);
+
+}
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+void oz_pd_timeout_handler(unsigned long data)
+{
+	int type;
+	struct oz_pd *pd = (struct oz_pd *)data;
+
+	spin_lock_bh(&g_polling_lock);
+	type = pd->timeout_type;
+	spin_unlock_bh(&g_polling_lock);
 	switch (type) {
 	case OZ_TIMER_TOUT:
 		oz_pd_sleep(pd);
@@ -502,218 +503,69 @@ static void oz_pd_handle_timer(struct oz_pd *pd, int type)
 	case OZ_TIMER_STOP:
 		oz_pd_stop(pd);
 		break;
-	case OZ_TIMER_HEARTBEAT: {
-			u16 apps = 0;
-			spin_lock_bh(&g_polling_lock);
-			pd->heartbeat_requested = 0;
-			if (pd->state & OZ_PD_S_CONNECTED)
-				apps = pd->total_apps;
-			spin_unlock_bh(&g_polling_lock);
-			if (apps)
-				oz_pd_heartbeat(pd, apps);
-		}
-		break;
 	}
 }
 /*------------------------------------------------------------------------------
- * Context: softirq
+ * Context: Interrupt
  */
-static void oz_protocol_timer(unsigned long arg)
+enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer)
 {
-	struct oz_timer *t;
-	struct oz_timer *t2;
 	struct oz_pd *pd;
-	spin_lock_bh(&g_polling_lock);
-	if (!g_cur_timer) {
-		/* This happens if we remove the current timer but can't stop
-		 * the timer from firing. In this case just get out.
-		 */
-		spin_unlock_bh(&g_polling_lock);
-		return;
-	}
-	g_timer_state = OZ_TIMER_IN_HANDLER;
-	t = g_cur_timer;
-	g_cur_timer = NULL;
-	list_del(&t->link);
-	spin_unlock_bh(&g_polling_lock);
-	do {
-		pd = t->pd;
-		oz_pd_handle_timer(pd, t->type);
-		spin_lock_bh(&g_polling_lock);
-		if (g_timer_pool_count < OZ_MAX_TIMER_POOL_SIZE) {
-			t->link.next = g_timer_pool;
-			g_timer_pool = &t->link;
-			g_timer_pool_count++;
-			t = NULL;
-		}
-		if (!list_empty(&g_timer_list)) {
-			t2 =  container_of(g_timer_list.next,
-				struct oz_timer, link);
-			if (time_before_eq(t2->due_time, jiffies))
-				list_del(&t2->link);
-			else
-				t2 = NULL;
-		} else {
-			t2 = NULL;
-		}
-		spin_unlock_bh(&g_polling_lock);
-		oz_pd_put(pd);
-		kfree(t);
-		t = t2;
-	} while (t);
-	g_timer_state = OZ_TIMER_IDLE;
-	oz_protocol_timer_start();
+
+	pd = container_of(timer, struct oz_pd, heartbeat);
+	hrtimer_forward_now(timer, ktime_set(pd->pulse_period /
+	MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC));
+	tasklet_schedule(&pd->heartbeat_tasklet);
+	return HRTIMER_RESTART;
 }
 /*------------------------------------------------------------------------------
- * Context: softirq
+ * Context: Interrupt
  */
-static void oz_protocol_timer_start(void)
+enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer)
 {
-	spin_lock_bh(&g_polling_lock);
-	if (!list_empty(&g_timer_list)) {
-		g_cur_timer =
-			container_of(g_timer_list.next, struct oz_timer, link);
-		if (g_timer_state == OZ_TIMER_SET) {
-			mod_timer(&g_timer, g_cur_timer->due_time);
-		} else {
-			g_timer.expires = g_cur_timer->due_time;
-			g_timer.function = oz_protocol_timer;
-			g_timer.data = 0;
-			add_timer(&g_timer);
-		}
-		g_timer_state = OZ_TIMER_SET;
-	} else {
-		oz_trace("No queued timers\n");
-	}
-	spin_unlock_bh(&g_polling_lock);
+	struct oz_pd *pd;
+
+	pd = container_of(timer, struct oz_pd, timeout);
+	tasklet_schedule(&pd->timeout_tasklet);
+	return HRTIMER_NORESTART;
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
  */
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time,
-		int remove)
+void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time)
 {
-	struct list_head *e;
-	struct oz_timer *t = NULL;
-	int restart_needed = 0;
-	spin_lock(&g_polling_lock);
-	if (remove) {
-		list_for_each(e, &g_timer_list) {
-			t = container_of(e, struct oz_timer, link);
-			if ((t->pd == pd) && (t->type == type)) {
-				if (g_cur_timer == t) {
-					restart_needed = 1;
-					g_cur_timer = NULL;
-				}
-				list_del(e);
-				break;
-			}
-			t = NULL;
-		}
-	}
-	if (!t) {
-		if (g_timer_pool) {
-			t = container_of(g_timer_pool, struct oz_timer, link);
-			g_timer_pool = g_timer_pool->next;
-			g_timer_pool_count--;
+	spin_lock_bh(&g_polling_lock);
+	switch (type) {
+	case OZ_TIMER_TOUT:
+	case OZ_TIMER_STOP:
+		if (hrtimer_active(&pd->timeout)) {
+			hrtimer_set_expires(&pd->timeout, ktime_set(due_time /
+			MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+							NSEC_PER_MSEC));
+			hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL);
 		} else {
-			t = kmalloc(sizeof(struct oz_timer), GFP_ATOMIC);
-		}
-		if (t) {
-			t->pd = pd;
-			t->type = type;
-			oz_pd_get(pd);
+			hrtimer_start(&pd->timeout, ktime_set(due_time /
+			MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+					NSEC_PER_MSEC), HRTIMER_MODE_REL);
 		}
+		pd->timeout_type = type;
+		break;
+	case OZ_TIMER_HEARTBEAT:
+		if (!hrtimer_active(&pd->heartbeat))
+			hrtimer_start(&pd->heartbeat, ktime_set(due_time /
+			MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+					NSEC_PER_MSEC), HRTIMER_MODE_REL);
+		break;
 	}
-	if (t) {
-		struct oz_timer *t2;
-		t->due_time = due_time;
-		list_for_each(e, &g_timer_list) {
-			t2 = container_of(e, struct oz_timer, link);
-			if (time_before(due_time, t2->due_time)) {
-				if (t2 == g_cur_timer) {
-					g_cur_timer = NULL;
-					restart_needed = 1;
-				}
-				break;
-			}
-		}
-		list_add_tail(&t->link, e);
-	}
-	if (g_timer_state == OZ_TIMER_IDLE)
-		restart_needed = 1;
-	else if (g_timer_state == OZ_TIMER_IN_HANDLER)
-		restart_needed = 0;
-	spin_unlock(&g_polling_lock);
-	if (restart_needed)
-		oz_protocol_timer_start();
-}
-/*------------------------------------------------------------------------------
- * Context: softirq or process
- */
-void oz_timer_delete(struct oz_pd *pd, int type)
-{
-	struct list_head *chain = NULL;
-	struct oz_timer *t;
-	struct oz_timer *n;
-	int restart_needed = 0;
-	int release = 0;
-	spin_lock(&g_polling_lock);
-	list_for_each_entry_safe(t, n, &g_timer_list, link) {
-		if ((t->pd == pd) && ((type == 0) || (t->type == type))) {
-			if (g_cur_timer == t) {
-				restart_needed = 1;
-				g_cur_timer = NULL;
-				del_timer(&g_timer);
-			}
-			list_del(&t->link);
-			release++;
-			if (g_timer_pool_count < OZ_MAX_TIMER_POOL_SIZE) {
-				t->link.next = g_timer_pool;
-				g_timer_pool = &t->link;
-				g_timer_pool_count++;
-			} else {
-				t->link.next = chain;
-				chain = &t->link;
-			}
-			if (type)
-				break;
-		}
-	}
-	if (g_timer_state == OZ_TIMER_IN_HANDLER)
-		restart_needed = 0;
-	else if (restart_needed)
-		g_timer_state = OZ_TIMER_IDLE;
-	spin_unlock(&g_polling_lock);
-	if (restart_needed)
-		oz_protocol_timer_start();
-	while (release--)
-		oz_pd_put(pd);
-	while (chain) {
-		t = container_of(chain, struct oz_timer, link);
-		chain = chain->next;
-		kfree(t);
-	}
+	spin_unlock_bh(&g_polling_lock);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
  */
 void oz_pd_request_heartbeat(struct oz_pd *pd)
 {
-	unsigned long now = jiffies;
-	unsigned long t;
-	spin_lock(&g_polling_lock);
-	if (pd->heartbeat_requested) {
-		spin_unlock(&g_polling_lock);
-		return;
-	}
-	if (pd->pulse_period_j)
-		t = ((now / pd->pulse_period_j) + 1) * pd->pulse_period_j;
-	else
-		t = now + 1;
-	pd->heartbeat_requested = 1;
-	spin_unlock(&g_polling_lock);
-	oz_timer_add(pd, OZ_TIMER_HEARTBEAT, t, 0);
+	oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ?
+					pd->pulse_period : OZ_QUANTUM);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
@@ -785,7 +637,7 @@ static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev,
 /*------------------------------------------------------------------------------
  * Context: process
  */
-void oz_binding_add(char *net_dev)
+void oz_binding_add(const char *net_dev)
 {
 	struct oz_binding *binding;
 
@@ -795,23 +647,22 @@ void oz_binding_add(char *net_dev)
 		binding->ptype.func = oz_pkt_recv;
 		memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
 		if (net_dev && *net_dev) {
-			oz_trace("Adding binding: %s\n", net_dev);
+			oz_dbg(ON, "Adding binding: %s\n", net_dev);
 			binding->ptype.dev =
 				dev_get_by_name(&init_net, net_dev);
 			if (binding->ptype.dev == NULL) {
-				oz_trace("Netdev %s not found\n", net_dev);
+				oz_dbg(ON, "Netdev %s not found\n", net_dev);
 				kfree(binding);
 				binding = NULL;
 			}
 		} else {
-			oz_trace("Binding to all netcards\n");
+			oz_dbg(ON, "Binding to all netcards\n");
 			binding->ptype.dev = NULL;
 		}
 		if (binding) {
 			dev_add_pack(&binding->ptype);
 			spin_lock_bh(&g_binding_lock);
-			binding->next = g_binding;
-			g_binding = binding;
+			list_add_tail(&binding->link, &g_binding);
 			spin_unlock_bh(&g_binding_lock);
 		}
 	}
@@ -819,21 +670,6 @@ void oz_binding_add(char *net_dev)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static int compare_binding_name(char *s1, char *s2)
-{
-	int i;
-	for (i = 0; i < OZ_MAX_BINDING_LEN; i++) {
-		if (*s1 != *s2)
-			return 0;
-		if (!*s1++)
-			return 1;
-		s2++;
-	}
-	return 1;
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
 static void pd_stop_all_for_device(struct net_device *net_dev)
 {
 	struct list_head h;
@@ -857,31 +693,28 @@ static void pd_stop_all_for_device(struct net_device *net_dev)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-void oz_binding_remove(char *net_dev)
+void oz_binding_remove(const char *net_dev)
 {
 	struct oz_binding *binding;
-	struct oz_binding **link;
-	oz_trace("Removing binding: %s\n", net_dev);
+	int found = 0;
+
+	oz_dbg(ON, "Removing binding: %s\n", net_dev);
 	spin_lock_bh(&g_binding_lock);
-	binding = g_binding;
-	link = &g_binding;
-	while (binding) {
-		if (compare_binding_name(binding->name, net_dev)) {
-			oz_trace("Binding '%s' found\n", net_dev);
-			*link = binding->next;
+	list_for_each_entry(binding, &g_binding, link) {
+		if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) {
+			oz_dbg(ON, "Binding '%s' found\n", net_dev);
+			found = 1;
 			break;
-		} else {
-			link = &binding;
-			binding = binding->next;
 		}
 	}
 	spin_unlock_bh(&g_binding_lock);
-	if (binding) {
+	if (found) {
 		dev_remove_pack(&binding->ptype);
 		if (binding->ptype.dev) {
 			dev_put(binding->ptype.dev);
 			pd_stop_all_for_device(binding->ptype.dev);
 		}
+		list_del(&binding->link);
 		kfree(binding);
 	}
 }
@@ -915,7 +748,6 @@ int oz_protocol_init(char *devs)
 				oz_binding_add(d);
 		}
 	}
-	init_timer(&g_timer);
 	return 0;
 }
 /*------------------------------------------------------------------------------
diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h
index 93bb4c0..e532347 100644
--- a/drivers/staging/ozwpan/ozproto.h
+++ b/drivers/staging/ozwpan/ozproto.h
@@ -7,25 +7,16 @@
 #define _OZPROTO_H
 
 #include <asm/byteorder.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozappif.h"
 
 #define OZ_ALLOCATED_SPACE(__x)	(LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom)
 
-/* Converts millisecs to jiffies.
- */
-#define oz_ms_to_jiffies(__x)	msecs_to_jiffies(__x)
-
-/* Quantum milliseconds.
- */
-#define OZ_QUANTUM_MS		8
-/* Quantum jiffies
- */
-#define OZ_QUANTUM_J		(oz_ms_to_jiffies(OZ_QUANTUM_MS))
+/* Quantum in MS */
+#define OZ_QUANTUM		8
 /* Default timeouts.
  */
-#define OZ_CONNECTION_TOUT_J	(2*HZ)
-#define OZ_PRESLEEP_TOUT_J	(11*HZ)
+#define OZ_PRESLEEP_TOUT	11
 
 /* Maximun sizes of tx frames. */
 #define OZ_MAX_TX_SIZE		1514
@@ -63,13 +54,18 @@ void oz_protocol_term(void);
 int oz_get_pd_list(struct oz_mac_addr *addr, int max_count);
 void oz_app_enable(int app_id, int enable);
 struct oz_pd *oz_pd_find(const u8 *mac_addr);
-void oz_binding_add(char *net_dev);
-void oz_binding_remove(char *net_dev);
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time,
-		int remove);
+void oz_binding_add(const char *net_dev);
+void oz_binding_remove(const char *net_dev);
+void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
 void oz_timer_delete(struct oz_pd *pd, int type);
 void oz_pd_request_heartbeat(struct oz_pd *pd);
 void oz_polling_lock_bh(void);
 void oz_polling_unlock_bh(void);
+void oz_pd_heartbeat_handler(unsigned long data);
+void oz_pd_timeout_handler(unsigned long data);
+enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
+enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer);
+int oz_get_pd_status_list(char *pd_list, int max_count);
+int oz_get_binding_list(char *buf, int max_if);
 
 #endif /* _OZPROTO_H */
diff --git a/drivers/staging/ozwpan/oztrace.c b/drivers/staging/ozwpan/oztrace.c
deleted file mode 100644
index 353ead2..0000000
--- a/drivers/staging/ozwpan/oztrace.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include "ozconfig.h"
-#include "oztrace.h"
-
-#ifdef WANT_VERBOSE_TRACE
-unsigned long trace_flags =
-	0
-#ifdef WANT_TRACE_STREAM
-	| OZ_TRACE_STREAM
-#endif /* WANT_TRACE_STREAM */
-#ifdef WANT_TRACE_URB
-	| OZ_TRACE_URB
-#endif /* WANT_TRACE_URB */
-
-#ifdef WANT_TRACE_CTRL_DETAIL
-	| OZ_TRACE_CTRL_DETAIL
-#endif /* WANT_TRACE_CTRL_DETAIL */
-
-#ifdef WANT_TRACE_HUB
-	| OZ_TRACE_HUB
-#endif /* WANT_TRACE_HUB */
-
-#ifdef WANT_TRACE_RX_FRAMES
-	| OZ_TRACE_RX_FRAMES
-#endif /* WANT_TRACE_RX_FRAMES */
-
-#ifdef WANT_TRACE_TX_FRAMES
-	| OZ_TRACE_TX_FRAMES
-#endif /* WANT_TRACE_TX_FRAMES */
-	;
-#endif /* WANT_VERBOSE_TRACE */
-
diff --git a/drivers/staging/ozwpan/oztrace.h b/drivers/staging/ozwpan/oztrace.h
deleted file mode 100644
index 8293b24..0000000
--- a/drivers/staging/ozwpan/oztrace.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZTRACE_H_
-#define _OZTRACE_H_
-#include "ozconfig.h"
-
-#define TRACE_PREFIX	KERN_ALERT "OZWPAN: "
-
-#ifdef WANT_TRACE
-#define oz_trace(...) printk(TRACE_PREFIX __VA_ARGS__)
-#ifdef WANT_VERBOSE_TRACE
-extern unsigned long trace_flags;
-#define oz_trace2(_flag, ...) \
-	do { if (trace_flags & _flag) printk(TRACE_PREFIX __VA_ARGS__); \
-	} while (0)
-#else
-#define oz_trace2(...)
-#endif /* #ifdef WANT_VERBOSE_TRACE */
-#else
-#define oz_trace(...)
-#define oz_trace2(...)
-#endif /* #ifdef WANT_TRACE */
-
-#define OZ_TRACE_STREAM		0x1
-#define OZ_TRACE_URB		0x2
-#define OZ_TRACE_CTRL_DETAIL	0x4
-#define OZ_TRACE_HUB		0x8
-#define OZ_TRACE_RX_FRAMES	0x10
-#define OZ_TRACE_TX_FRAMES	0x20
-
-#endif /* Sentry */
-
diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c
index 55b9afb..d69e8ab 100644
--- a/drivers/staging/ozwpan/ozurbparanoia.c
+++ b/drivers/staging/ozwpan/ozurbparanoia.c
@@ -4,10 +4,12 @@
  * -----------------------------------------------------------------------------
  */
 #include <linux/usb.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
+
 #ifdef WANT_URB_PARANOIA
+
 #include "ozurbparanoia.h"
-#include "oztrace.h"
+
 /*-----------------------------------------------------------------------------
  */
 #define OZ_MAX_URBS	1000
@@ -22,9 +24,9 @@ void oz_remember_urb(struct urb *urb)
 	spin_lock_irqsave(&g_urb_mem_lock, irq_state);
 	if (g_nb_urbs < OZ_MAX_URBS) {
 		g_urb_memory[g_nb_urbs++] = urb;
-		oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb);
+		oz_dbg(ON, "urb up = %d %p\n", g_nb_urbs, urb);
 	} else {
-		oz_trace("ERROR urb buffer full\n");
+		oz_dbg(ON, "ERROR urb buffer full\n");
 	}
 	spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
 }
@@ -42,8 +44,7 @@ int oz_forget_urb(struct urb *urb)
 			if (--g_nb_urbs > i)
 				memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
 					(g_nb_urbs - i) * sizeof(struct urb *));
-			oz_trace("%lu: urb down = %d %p\n",
-				jiffies, g_nb_urbs, urb);
+			oz_dbg(ON, "urb down = %d %p\n", g_nb_urbs, urb);
 		}
 	}
 	spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
diff --git a/drivers/staging/ozwpan/ozurbparanoia.h b/drivers/staging/ozwpan/ozurbparanoia.h
index 00f5a3a..5080ea7 100644
--- a/drivers/staging/ozwpan/ozurbparanoia.h
+++ b/drivers/staging/ozwpan/ozurbparanoia.h
@@ -10,8 +10,8 @@
 void oz_remember_urb(struct urb *urb);
 int oz_forget_urb(struct urb *urb);
 #else
-#define oz_remember_urb(__x)
-#define oz_forget_urb(__x)	0
+static inline void oz_remember_urb(struct urb *urb) {}
+static inline int oz_forget_urb(struct urb *urb) { return 0; }
 #endif /* WANT_URB_PARANOIA */
 
 
diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c
index 1676328..732face 100644
--- a/drivers/staging/ozwpan/ozusbsvc.c
+++ b/drivers/staging/ozwpan/ozusbsvc.c
@@ -10,6 +10,7 @@
  * The implementation of this service uses ozhcd.c to implement a USB HCD.
  * -----------------------------------------------------------------------------
  */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/timer.h>
@@ -18,15 +19,15 @@
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <asm/unaligned.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozproto.h"
 #include "ozusbif.h"
 #include "ozhcd.h"
-#include "oztrace.h"
 #include "ozusbsvc.h"
+
 /*------------------------------------------------------------------------------
  * This is called once when the driver is loaded to initialise the USB service.
  * Context: process
@@ -53,10 +54,10 @@ int oz_usb_start(struct oz_pd *pd, int resume)
 	struct oz_usb_ctx *usb_ctx;
 	struct oz_usb_ctx *old_ctx;
 	if (resume) {
-		oz_trace("USB service resumed.\n");
+		oz_dbg(ON, "USB service resumed\n");
 		return 0;
 	}
-	oz_trace("USB service started.\n");
+	oz_dbg(ON, "USB service started\n");
 	/* Create a USB context in case we need one. If we find the PD already
 	 * has a USB context then we will destroy it.
 	 */
@@ -77,7 +78,7 @@ int oz_usb_start(struct oz_pd *pd, int resume)
 	oz_usb_get(pd->app_ctx[OZ_APPID_USB-1]);
 	spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
 	if (old_ctx) {
-		oz_trace("Already have USB context.\n");
+		oz_dbg(ON, "Already have USB context\n");
 		kfree(usb_ctx);
 		usb_ctx = old_ctx;
 	} else if (usb_ctx) {
@@ -95,7 +96,7 @@ int oz_usb_start(struct oz_pd *pd, int resume)
 	} else {
 		usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx);
 		if (usb_ctx->hport == NULL) {
-			oz_trace("USB hub returned null port.\n");
+			oz_dbg(ON, "USB hub returned null port\n");
 			spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
 			pd->app_ctx[OZ_APPID_USB-1] = NULL;
 			spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
@@ -114,7 +115,7 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
 {
 	struct oz_usb_ctx *usb_ctx;
 	if (pause) {
-		oz_trace("USB service paused.\n");
+		oz_dbg(ON, "USB service paused\n");
 		return;
 	}
 	spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
@@ -122,8 +123,9 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
 	pd->app_ctx[OZ_APPID_USB-1] = NULL;
 	spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
 	if (usb_ctx) {
-		unsigned long tout = jiffies + HZ;
-		oz_trace("USB service stopping...\n");
+		struct timespec ts, now;
+		getnstimeofday(&ts);
+		oz_dbg(ON, "USB service stopping...\n");
 		usb_ctx->stopped = 1;
 		/* At this point the reference count on the usb context should
 		 * be 2 - one from when we created it and one from the hcd
@@ -131,10 +133,13 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
 		 * should get in but someone may already be in. So wait
 		 * until they leave but timeout after 1 second.
 		 */
-		while ((atomic_read(&usb_ctx->ref_count) > 2) &&
-			time_before(jiffies, tout))
-			;
-		oz_trace("USB service stopped.\n");
+		while ((atomic_read(&usb_ctx->ref_count) > 2)) {
+			getnstimeofday(&now);
+			/*Approx 1 Sec. this is not perfect calculation*/
+			if (now.tv_sec != ts.tv_sec)
+				break;
+		}
+		oz_dbg(ON, "USB service stopped\n");
 		oz_hcd_pd_departed(usb_ctx->hport);
 		/* Release the reference taken in oz_usb_start.
 		 */
@@ -154,13 +159,13 @@ void oz_usb_get(void *hpd)
 /*------------------------------------------------------------------------------
  * This decrements the reference count of the context area for a specific PD
  * and destroys the context area if the reference count becomes zero.
- * Context: softirq or process
+ * Context: irq or process
  */
 void oz_usb_put(void *hpd)
 {
 	struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
 	if (atomic_dec_and_test(&usb_ctx->ref_count)) {
-		oz_trace("Dealloc USB context.\n");
+		oz_dbg(ON, "Dealloc USB context\n");
 		oz_pd_put(usb_ctx->pd);
 		kfree(usb_ctx);
 	}
@@ -195,7 +200,7 @@ int oz_usb_stream_create(void *hpd, u8 ep_num)
 {
 	struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
 	struct oz_pd *pd = usb_ctx->pd;
-	oz_trace("oz_usb_stream_create(0x%x)\n", ep_num);
+	oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num);
 	if (pd->mode & OZ_F_ISOC_NO_ELTS) {
 		oz_isoc_stream_create(pd, ep_num);
 	} else {
@@ -217,7 +222,7 @@ int oz_usb_stream_delete(void *hpd, u8 ep_num)
 	if (usb_ctx) {
 		struct oz_pd *pd = usb_ctx->pd;
 		if (pd) {
-			oz_trace("oz_usb_stream_delete(0x%x)\n", ep_num);
+			oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num);
 			if (pd->mode & OZ_F_ISOC_NO_ELTS) {
 				oz_isoc_stream_delete(pd, ep_num);
 			} else {
diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c
index 16e6078..50d21bf 100644
--- a/drivers/staging/ozwpan/ozusbsvc1.c
+++ b/drivers/staging/ozwpan/ozusbsvc1.c
@@ -13,14 +13,13 @@
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <asm/unaligned.h>
-#include "ozconfig.h"
+#include "ozdbg.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozproto.h"
 #include "ozusbif.h"
 #include "ozhcd.h"
-#include "oztrace.h"
 #include "ozusbsvc.h"
 /*------------------------------------------------------------------------------
  */
@@ -62,12 +61,12 @@ int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
 	struct oz_get_desc_req *body;
 	struct oz_elt_buf *eb = &pd->elt_buff;
 	struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-	oz_trace("    req_type = 0x%x\n", req_type);
-	oz_trace("    desc_type = 0x%x\n", desc_type);
-	oz_trace("    index = 0x%x\n", index);
-	oz_trace("    windex = 0x%x\n", windex);
-	oz_trace("    offset = 0x%x\n", offset);
-	oz_trace("    len = 0x%x\n", len);
+	oz_dbg(ON, "    req_type = 0x%x\n", req_type);
+	oz_dbg(ON, "    desc_type = 0x%x\n", desc_type);
+	oz_dbg(ON, "    index = 0x%x\n", index);
+	oz_dbg(ON, "    windex = 0x%x\n", windex);
+	oz_dbg(ON, "    offset = 0x%x\n", offset);
+	oz_dbg(ON, "    len = 0x%x\n", len);
 	if (len > 200)
 		len = 200;
 	if (ei == NULL)
@@ -376,7 +375,7 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
 			u16 offs = le16_to_cpu(get_unaligned(&body->offset));
 			u16 total_size =
 				le16_to_cpu(get_unaligned(&body->total_size));
-			oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n");
+			oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
 			oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id,
 					body->rcode, body->data,
 					data_len, offs, total_size);
@@ -425,7 +424,7 @@ void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len)
 	if (usb_ctx == NULL)
 		return; /* Context has gone so nothing to do. */
 	if (!usb_ctx->stopped) {
-		oz_trace("Farewell indicated ep = 0x%x\n", ep_num);
+		oz_dbg(ON, "Farewell indicated ep = 0x%x\n", ep_num);
 		oz_hcd_data_ind(usb_ctx->hport, ep_num, data, len);
 	}
 	oz_usb_put(usb_ctx);
diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c
index 84ea721..51d46e0 100644
--- a/drivers/staging/rtl8192e/rtllib_module.c
+++ b/drivers/staging/rtl8192e/rtllib_module.c
@@ -233,7 +233,8 @@ static const struct file_operations fops = {
 	.open = open_debug_level,
 	.read = seq_read,
 	.llseek = seq_lseek,
-	.write = write_debug_level
+	.write = write_debug_level,
+	.release = single_release,
 };
 
 int __init rtllib_init(void)
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index e0870c0..434c431 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -268,7 +268,8 @@ static const struct file_operations fops = {
 	.open = open_debug_level,
 	.read = seq_read,
 	.llseek = seq_lseek,
-	.write = write_debug_level
+	.write = write_debug_level,
+	.release = single_release,
 };
 
 int __init ieee80211_debug_init(void)
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
index 6810766..5bc361b 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
@@ -1,81 +1,61 @@
 /******************************************************************************
-
-     (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
-
- Module:	r819xusb_cmdpkt.c	(RTL8190 TX/RX command packet handler Source C File)
-
- Note:      The module is responsible for handling TX and RX command packet.
-			1. TX : Send set and query configuration command packet.
-			2. RX : Receive tx feedback, beacon state, query configuration
-				command packet.
-
- Function:
-
- Export:
-
- Abbrev:
-
- History:
-	Data		Who		Remark
-
-	05/06/2008  amy		Create initial version porting from windows driver.
-
-******************************************************************************/
+ *
+ *  (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
+ *
+ *  Module:	r819xusb_cmdpkt.c
+ *		(RTL8190 TX/RX command packet handler Source C File)
+ *
+ *  Note:	The module is responsible for handling TX and RX command packet.
+ *		1. TX : Send set and query configuration command packet.
+ *		2. RX : Receive tx feedback, beacon state, query configuration
+ *			command packet.
+ *
+ *  Function:
+ *
+ *  Export:
+ *
+ *  Abbrev:
+ *
+ *  History:
+ *
+ *	Date		Who		Remark
+ *	05/06/2008	amy		Create initial version porting from
+ *					windows driver.
+ *
+ ******************************************************************************/
 #include "r8192U.h"
 #include "r819xU_cmdpkt.h"
-/*---------------------------Define Local Constant---------------------------*/
-/* Debug constant*/
-#define		CMPK_DEBOUNCE_CNT			1
-/* 2007/10/24 MH Add for printing a range of data. */
-#define		CMPK_PRINT(Address)\
-{\
-	unsigned char	i;\
-	u32	temp[10];\
-	\
-	memcpy(temp, Address, 40);\
-	for (i = 0; i <40; i+=4)\
-		printk("\r\n %08x", temp[i]);\
-}\
-/*---------------------------Define functions---------------------------------*/
-
-rt_status
-SendTxCommandPacket(
-	struct net_device *dev,
-	void			*pData,
-	u32				DataLen
-	)
+
+rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
 {
 	rt_status	rtStatus = RT_STATUS_SUCCESS;
 	struct r8192_priv   *priv = ieee80211_priv(dev);
 	struct sk_buff	    *skb;
 	cb_desc		    *tcb_desc;
 	unsigned char	    *ptr_buf;
-	//bool	bLastInitPacket = false;
 
-	//PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
-
-	//Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
+	/* Get TCB and local buffer from common pool.
+	   (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) */
 	skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
-	memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+	memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
 	tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 	tcb_desc->queue_index = TXCMD_QUEUE;
 	tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
 	tcb_desc->bLastIniPkt = 0;
 	skb_reserve(skb, USB_HWDESC_HEADER_LEN);
 	ptr_buf = skb_put(skb, DataLen);
-	memcpy(ptr_buf,pData,DataLen);
-	tcb_desc->txbuf_size= (u16)DataLen;
-
-	if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
-			(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
-			(priv->ieee80211->queue_stop) ) {
-			RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n");
-			skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
-		} else {
-			priv->ieee80211->softmac_hard_start_xmit(skb,dev);
-		}
+	memcpy(ptr_buf, pData, DataLen);
+	tcb_desc->txbuf_size = (u16)DataLen;
+
+	if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
+	    (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
+	    (priv->ieee80211->queue_stop)) {
+		RT_TRACE(COMP_FIRMWARE, "=== NULL packet ======> tx full!\n");
+		skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
+	} else {
+		priv->ieee80211->softmac_hard_start_xmit(skb, dev);
+	}
 
-	//PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
 	return rtStatus;
 }
 
@@ -83,27 +63,25 @@ SendTxCommandPacket(
  * Function:	cmpk_message_handle_tx()
  *
  * Overview:	Driver internal module can call the API to send message to
- *				firmware side. For example, you can send a debug command packet.
- *				Or you can send a request for FW to modify RLX4181 LBUS HW bank.
- *				Otherwise, you can change MAC/PHT/RF register by firmware at
- *				run time. We do not support message more than one segment now.
+ *		firmware side. For example, you can send a debug command packet.
+ *		Or you can send a request for FW to modify RLX4181 LBUS HW bank.
+ *		Otherwise, you can change MAC/PHT/RF register by firmware at
+ *		run time. We do not support message more than one segment now.
  *
- * Input:		NONE
+ * Input:	NONE
  *
- * Output:		NONE
+ * Output:	NONE
  *
- * Return:		NONE
+ * Return:	NONE
  *
  * Revised History:
  *	When		Who		Remark
  *	05/06/2008	amy		porting from windows code.
  *
  *---------------------------------------------------------------------------*/
- extern	rt_status	cmpk_message_handle_tx(
-	struct net_device *dev,
-	u8	*codevirtualaddress,
-	u32	packettype,
-	u32	buffer_len)
+extern rt_status cmpk_message_handle_tx(struct net_device *dev,
+					u8 *codevirtualaddress,
+					u32 packettype, u32 buffer_len)
 {
 
 	bool	    rt_status = true;
@@ -113,8 +91,6 @@ SendTxCommandPacket(
 	struct r8192_priv   *priv = ieee80211_priv(dev);
 	u16		    frag_threshold;
 	u16		    frag_length, frag_offset = 0;
-	//u16		    total_size;
-	//int		    i;
 
 	rt_firmware	    *pfirmware = priv->pFirmware;
 	struct sk_buff	    *skb;
@@ -123,11 +99,11 @@ SendTxCommandPacket(
 	u8                  bLastIniPkt;
 
 	firmware_init_param(dev);
-	//Fragmentation might be required
+	/* Fragmentation might be required */
 	frag_threshold = pfirmware->cmdpacket_frag_thresold;
 	do {
 		if ((buffer_len - frag_offset) > frag_threshold) {
-			frag_length = frag_threshold ;
+			frag_length = frag_threshold;
 			bLastIniPkt = 0;
 
 		} else {
@@ -136,146 +112,127 @@ SendTxCommandPacket(
 
 		}
 
-		/* Allocate skb buffer to contain firmware info and tx descriptor info
-		 * add 4 to avoid packet appending overflow.
-		 * */
-		#ifdef RTL8192U
+		/* Allocate skb buffer to contain firmware info and tx
+		   descriptor info add 4 to avoid packet appending overflow. */
+#ifdef RTL8192U
 		skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
-		#else
+#else
 		skb  = dev_alloc_skb(frag_length + 4);
-		#endif
-		memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+#endif
+		memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
 		tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 		tcb_desc->queue_index = TXCMD_QUEUE;
 		tcb_desc->bCmdOrInit = packettype;
 		tcb_desc->bLastIniPkt = bLastIniPkt;
 
-		#ifdef RTL8192U
+#ifdef RTL8192U
 		skb_reserve(skb, USB_HWDESC_HEADER_LEN);
-		#endif
+#endif
 
 		seg_ptr = skb_put(skb, buffer_len);
 		/*
 		 * Transform from little endian to big endian
 		 * and pending zero
 		 */
-		memcpy(seg_ptr,codevirtualaddress,buffer_len);
-		tcb_desc->txbuf_size= (u16)buffer_len;
+		memcpy(seg_ptr, codevirtualaddress, buffer_len);
+		tcb_desc->txbuf_size = (u16)buffer_len;
 
 
-		if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
-			(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
-			(priv->ieee80211->queue_stop) ) {
-			RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
+		if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
+		    (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
+		    (priv->ieee80211->queue_stop)) {
+			RT_TRACE(COMP_FIRMWARE, "======> tx full!\n");
 			skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
 		} else {
-			priv->ieee80211->softmac_hard_start_xmit(skb,dev);
+			priv->ieee80211->softmac_hard_start_xmit(skb, dev);
 		}
 
 		codevirtualaddress += frag_length;
 		frag_offset += frag_length;
 
-	}while(frag_offset < buffer_len);
+	} while (frag_offset < buffer_len);
 
 	return rt_status;
 
 
 #endif
-}	/* CMPK_Message_Handle_Tx */
+}
 
 /*-----------------------------------------------------------------------------
  * Function:    cmpk_counttxstatistic()
  *
  * Overview:
  *
- * Input:       PADAPTER	pAdapter		-	.
- *				CMPK_TXFB_T *psTx_FB	-	.
+ * Input:       PADAPTER	pAdapter
+ *              CMPK_TXFB_T	*psTx_FB
  *
  * Output:      NONE
  *
  * Return:      NONE
  *
  * Revised History:
- *  When		Who		Remark
- *  05/12/2008	amy	Create Version 0 porting from windows code.
+ *  When		Who	Remark
+ *  05/12/2008		amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void
-cmpk_count_txstatistic(
-	struct net_device *dev,
-	cmpk_txfb_t	*pstx_fb)
+static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 #ifdef ENABLE_PS
 	RT_RF_POWER_STATE	rtState;
 
-	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
+	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
+					  (pu1Byte)(&rtState));
 
-	// When RF is off, we should not count the packet for hw/sw synchronize
-	// reason, ie. there may be a duration while sw switch is changed and hw
-	// switch is being changed. 2006.12.04, by shien chang.
+	/* When RF is off, we should not count the packet for hw/sw synchronize
+	   reason, ie. there may be a duration while sw switch is changed and
+	   hw switch is being changed. */
 	if (rtState == eRfOff)
-	{
 		return;
-	}
 #endif
 
 #ifdef TODO
 	if (pAdapter->bInHctTest)
 		return;
 #endif
-	/* We can not know the packet length and transmit type: broadcast or uni
-	   or multicast. So the relative statistics must be collected in tx
-	   feedback info. */
-	if (pstx_fb->tok)
-	{
+	/* We can not know the packet length and transmit type:
+	   broadcast or uni or multicast. So the relative statistics
+	   must be collected in tx feedback info. */
+	if (pstx_fb->tok) {
 		priv->stats.txfeedbackok++;
 		priv->stats.txoktotal++;
 		priv->stats.txokbytestotal += pstx_fb->pkt_length;
 		priv->stats.txokinperiod++;
 
 		/* We can not make sure broadcast/multicast or unicast mode. */
-		if (pstx_fb->pkt_type == PACKET_MULTICAST)
-		{
+		if (pstx_fb->pkt_type == PACKET_MULTICAST) {
 			priv->stats.txmulticast++;
 			priv->stats.txbytesmulticast += pstx_fb->pkt_length;
-		}
-		else if (pstx_fb->pkt_type == PACKET_BROADCAST)
-		{
+		} else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
 			priv->stats.txbroadcast++;
 			priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
-		}
-		else
-		{
+		} else {
 			priv->stats.txunicast++;
 			priv->stats.txbytesunicast += pstx_fb->pkt_length;
 		}
-	}
-	else
-	{
+	} else {
 		priv->stats.txfeedbackfail++;
 		priv->stats.txerrtotal++;
 		priv->stats.txerrbytestotal += pstx_fb->pkt_length;
 
 		/* We can not make sure broadcast/multicast or unicast mode. */
 		if (pstx_fb->pkt_type == PACKET_MULTICAST)
-		{
 			priv->stats.txerrmulticast++;
-		}
 		else if (pstx_fb->pkt_type == PACKET_BROADCAST)
-		{
 			priv->stats.txerrbroadcast++;
-		}
 		else
-		{
 			priv->stats.txerrunicast++;
-		}
 	}
 
 	priv->stats.txretrycount += pstx_fb->retry_cnt;
 	priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
 
-}	/* cmpk_CountTxStatistic */
+}
 
 
 
@@ -283,80 +240,63 @@ cmpk_count_txstatistic(
  * Function:    cmpk_handle_tx_feedback()
  *
  * Overview:	The function is responsible for extract the message inside TX
- *				feedbck message from firmware. It will contain dedicated info in
- *				ws-06-0063-rtl8190-command-packet-specification. Please
- *				refer to chapter "TX Feedback Element". We have to read 20 bytes
- *				in the command packet.
+ *		feedbck message from firmware. It will contain dedicated info in
+ *		ws-06-0063-rtl8190-command-packet-specification.
+ *		Please refer to chapter "TX Feedback Element".
+ *              We have to read 20 bytes in the command packet.
  *
- * Input:       struct net_device *    dev
- *				u8	*	pmsg		-	Msg Ptr of the command packet.
+ * Input:       struct net_device	*dev
+ *              u8			*pmsg	- Msg Ptr of the command packet.
  *
  * Output:      NONE
  *
  * Return:      NONE
  *
  * Revised History:
- *  When		Who		Remark
- *  05/08/2008	amy		Create Version 0 porting from windows code.
+ *  When		Who	Remark
+ *  05/08/2008		amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void
-cmpk_handle_tx_feedback(
-	struct net_device *dev,
-	u8	*pmsg)
+static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
-	cmpk_txfb_t		rx_tx_fb;	/* */
+	cmpk_txfb_t		rx_tx_fb;
 
 	priv->stats.txfeedback++;
 
-	/* 0. Display received message. */
-	//cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
-
 	/* 1. Extract TX feedback info from RFD to temp structure buffer. */
 	/* It seems that FW use big endian(MIPS) and DRV use little endian in
 	   windows OS. So we have to read the content byte by byte or transfer
 	   endian type before copy the message copy. */
-	/* 2007/07/05 MH Use pointer to transfer structure memory. */
-	//memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
+	/* Use pointer to transfer structure memory. */
 	memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
 	/* 2. Use tx feedback info to count TX statistics. */
 	cmpk_count_txstatistic(dev, &rx_tx_fb);
-	/* 2007/01/17 MH Comment previous method for TX statistic function. */
+	/* Comment previous method for TX statistic function. */
 	/* Collect info TX feedback packet to fill TCB. */
 	/* We can not know the packet length and transmit type: broadcast or uni
 	   or multicast. */
-	//CountTxStatistics( pAdapter, &tcb );
 
-}	/* cmpk_Handle_Tx_Feedback */
+}
 
-void
-cmdpkt_beacontimerinterrupt_819xusb(
-	struct net_device *dev
-)
+void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	u16 tx_rate;
-	{
-		//
-		// 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
-		//
-		if (priv->ieee80211->current_network.mode == IEEE_A  ||
+		/* 87B have to S/W beacon for DTM encryption_cmn. */
+		if (priv->ieee80211->current_network.mode == IEEE_A ||
 			priv->ieee80211->current_network.mode == IEEE_N_5G ||
-			(priv->ieee80211->current_network.mode == IEEE_N_24G  && (!priv->ieee80211->pHTInfo->bCurSuppCCK)))
-		{
+			(priv->ieee80211->current_network.mode == IEEE_N_24G &&
+			 (!priv->ieee80211->pHTInfo->bCurSuppCCK))) {
 			tx_rate = 60;
 			DMESG("send beacon frame  tx rate is 6Mbpm\n");
-		}
-		else
-		{
-			tx_rate =10;
+		} else {
+			tx_rate = 10;
 			DMESG("send beacon frame  tx rate is 1Mbpm\n");
 		}
 
-		rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon
+		rtl819xusb_beacon_tx(dev, tx_rate); /* HW Beacon */
 
-	}
 
 }
 
@@ -367,151 +307,129 @@ cmdpkt_beacontimerinterrupt_819xusb(
  * Function:    cmpk_handle_interrupt_status()
  *
  * Overview:    The function is responsible for extract the message from
- *				firmware. It will contain dedicated info in
- *				ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
- *				Please refer to chapter "Interrupt Status Element".
+ *		firmware. It will contain dedicated info in
+ *		ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
+ *		Please refer to chapter "Interrupt Status Element".
  *
- * Input:       struct net_device *dev,
- *			u8*	pmsg		-	Message Pointer of the command packet.
+ * Input:       struct net_device *dev
+ *              u8 *pmsg		- Message Pointer of the command packet.
  *
  * Output:      NONE
  *
  * Return:      NONE
  *
  * Revised History:
- *  When			Who			Remark
- *  05/12/2008	amy		Add this for rtl8192 porting from windows code.
+ *  When		Who	Remark
+ *  05/12/2008		amy	Add this for rtl8192 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void
-cmpk_handle_interrupt_status(
-	struct net_device *dev,
-	u8	*pmsg)
+static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
 {
 	cmpk_intr_sta_t		rx_intr_status;	/* */
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	DMESG("---> cmpk_Handle_Interrupt_Status()\n");
 
-	/* 0. Display received message. */
-	//cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
-
 	/* 1. Extract TX feedback info from RFD to temp structure buffer. */
 	/* It seems that FW use big endian(MIPS) and DRV use little endian in
 	   windows OS. So we have to read the content byte by byte or transfer
 	   endian type before copy the message copy. */
-	//rx_bcn_state.Element_ID	= pMsg[0];
-	//rx_bcn_state.Length		= pMsg[1];
 	rx_intr_status.length = pmsg[1];
-	if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2))
-	{
+	if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) {
 		DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
 		return;
 	}
 
 
-	// Statistics of beacon for ad-hoc mode.
-	if (	priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-	{
-		//2 maybe need endian transform?
+	/* Statistics of beacon for ad-hoc mode. */
+	if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
+		/* 2 maybe need endian transform? */
 		rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
-		//rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
 
-		DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status);
+		DMESG("interrupt status = 0x%x\n",
+		      rx_intr_status.interrupt_status);
 
-		if (rx_intr_status.interrupt_status & ISR_TxBcnOk)
-		{
+		if (rx_intr_status.interrupt_status & ISR_TxBcnOk) {
 			priv->ieee80211->bibsscoordinator = true;
 			priv->stats.txbeaconokint++;
-		}
-		else if (rx_intr_status.interrupt_status & ISR_TxBcnErr)
-		{
+		} else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) {
 			priv->ieee80211->bibsscoordinator = false;
 			priv->stats.txbeaconerr++;
 		}
 
 		if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
-		{
 			cmdpkt_beacontimerinterrupt_819xusb(dev);
-		}
 
 	}
 
-	 // Other informations in interrupt status we need?
+	/* Other informations in interrupt status we need? */
 
 
 	DMESG("<---- cmpk_handle_interrupt_status()\n");
 
-}	/* cmpk_handle_interrupt_status */
+}
 
 
 /*-----------------------------------------------------------------------------
  * Function:    cmpk_handle_query_config_rx()
  *
  * Overview:    The function is responsible for extract the message from
- *				firmware. It will contain dedicated info in
- *				ws-06-0063-rtl8190-command-packet-specification. Please
- *				refer to chapter "Beacon State Element".
+ *		firmware. It will contain dedicated info in
+ *		ws-06-0063-rtl8190-command-packet-specification. Please
+ *		refer to chapter "Beacon State Element".
  *
- * Input:       u8 *  pmsg	-	Message Pointer of the command packet.
+ * Input:       u8    *pmsg	-	Message Pointer of the command packet.
  *
  * Output:      NONE
  *
  * Return:      NONE
  *
  * Revised History:
- *  When		Who		Remark
- *  05/12/2008	amy		Create Version 0 porting from windows code.
+ *  When		Who	Remark
+ *  05/12/2008		amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void
-cmpk_handle_query_config_rx(
-	struct net_device *dev,
-	u8	   *pmsg)
+static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg)
 {
-	cmpk_query_cfg_t	rx_query_cfg;	/* */
+	cmpk_query_cfg_t	rx_query_cfg;
 
-	/* 0. Display received message. */
-	//cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
 
 	/* 1. Extract TX feedback info from RFD to temp structure buffer. */
 	/* It seems that FW use big endian(MIPS) and DRV use little endian in
 	   windows OS. So we have to read the content byte by byte or transfer
 	   endian type before copy the message copy. */
-	//rx_query_cfg.Element_ID	= pMsg[0];
-	//rx_query_cfg.Length		= pMsg[1];
-	rx_query_cfg.cfg_action		= (pmsg[4] & 0x80000000)>>31;
+	rx_query_cfg.cfg_action		= (pmsg[4] & 0x80000000) >> 31;
 	rx_query_cfg.cfg_type		= (pmsg[4] & 0x60) >> 5;
 	rx_query_cfg.cfg_size		= (pmsg[4] & 0x18) >> 3;
 	rx_query_cfg.cfg_page		= (pmsg[6] & 0x0F) >> 0;
-	rx_query_cfg.cfg_offset			= pmsg[7];
-	rx_query_cfg.value			= (pmsg[8] << 24) | (pmsg[9] << 16) |
-								  (pmsg[10] << 8) | (pmsg[11] << 0);
-	rx_query_cfg.mask			= (pmsg[12] << 24) | (pmsg[13] << 16) |
-								  (pmsg[14] << 8) | (pmsg[15] << 0);
+	rx_query_cfg.cfg_offset		= pmsg[7];
+	rx_query_cfg.value		= (pmsg[8]  << 24) | (pmsg[9]  << 16) |
+					  (pmsg[10] <<  8) | (pmsg[11] <<  0);
+	rx_query_cfg.mask		= (pmsg[12] << 24) | (pmsg[13] << 16) |
+					  (pmsg[14] <<  8) | (pmsg[15] <<  0);
 
-}	/* cmpk_Handle_Query_Config_Rx */
+}
 
 
 /*-----------------------------------------------------------------------------
  * Function:	cmpk_count_tx_status()
  *
  * Overview:	Count aggregated tx status from firmwar of one type rx command
- *				packet element id = RX_TX_STATUS.
+ *		packet element id = RX_TX_STATUS.
  *
- * Input:		NONE
+ * Input:	NONE
  *
- * Output:		NONE
+ * Output:	NONE
  *
- * Return:		NONE
+ * Return:	NONE
  *
  * Revised History:
- *	When		Who		Remark
- *	05/12/2008	amy		Create Version 0 porting from windows code.
+ *	When		Who	Remark
+ *	05/12/2008	amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void	cmpk_count_tx_status(	struct net_device *dev,
-									cmpk_tx_status_t	*pstx_status)
+static void cmpk_count_tx_status(struct net_device *dev,
+				 cmpk_tx_status_t *pstx_status)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
@@ -519,15 +437,14 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
 
 	RT_RF_POWER_STATE	rtstate;
 
-	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
+	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
+					  (pu1Byte)(&rtState));
 
-	// When RF is off, we should not count the packet for hw/sw synchronize
-	// reason, ie. there may be a duration while sw switch is changed and hw
-	// switch is being changed. 2006.12.04, by shien chang.
+	/* When RF is off, we should not count the packet for hw/sw synchronize
+	   reason, ie. there may be a duration while sw switch is changed and
+	   hw switch is being changed. */
 	if (rtState == eRfOff)
-	{
 		return;
-	}
 #endif
 
 	priv->stats.txfeedbackok	+= pstx_status->txok;
@@ -536,15 +453,12 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
 	priv->stats.txfeedbackfail	+= pstx_status->txfail;
 	priv->stats.txerrtotal		+= pstx_status->txfail;
 
-	priv->stats.txretrycount		+= pstx_status->txretry;
+	priv->stats.txretrycount	+= pstx_status->txretry;
 	priv->stats.txfeedbackretry	+= pstx_status->txretry;
 
-	//pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
-	//pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
-	//pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
 
-	priv->stats.txmulticast	+= pstx_status->txmcok;
-	priv->stats.txbroadcast	+= pstx_status->txbcok;
+	priv->stats.txmulticast		+= pstx_status->txmcok;
+	priv->stats.txbroadcast		+= pstx_status->txbcok;
 	priv->stats.txunicast		+= pstx_status->txucok;
 
 	priv->stats.txerrmulticast	+= pstx_status->txmcfail;
@@ -553,10 +467,10 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
 
 	priv->stats.txbytesmulticast	+= pstx_status->txmclength;
 	priv->stats.txbytesbroadcast	+= pstx_status->txbclength;
-	priv->stats.txbytesunicast		+= pstx_status->txuclength;
+	priv->stats.txbytesunicast	+= pstx_status->txuclength;
 
-	priv->stats.last_packet_rate		= pstx_status->rate;
-}	/* cmpk_CountTxStatus */
+	priv->stats.last_packet_rate	= pstx_status->rate;
+}
 
 
 
@@ -564,7 +478,7 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
  * Function:	cmpk_handle_tx_status()
  *
  * Overview:	Firmware add a new tx feedback status to reduce rx command
- *				packet buffer operation load.
+ *		packet buffer operation load.
  *
  * Input:		NONE
  *
@@ -573,22 +487,19 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
  * Return:		NONE
  *
  * Revised History:
- *	When		Who		Remark
- *	05/12/2008	amy		Create Version 0 porting from windows code.
+ *	When		Who	Remark
+ *	05/12/2008	amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void
-cmpk_handle_tx_status(
-	struct net_device *dev,
-	u8	   *pmsg)
+static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
 {
-	cmpk_tx_status_t	rx_tx_sts;	/* */
+	cmpk_tx_status_t	rx_tx_sts;
 
 	memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t));
 	/* 2. Use tx feedback info to count TX statistics. */
 	cmpk_count_tx_status(dev, &rx_tx_sts);
 
-}	/* cmpk_Handle_Tx_Status */
+}
 
 
 /*-----------------------------------------------------------------------------
@@ -603,82 +514,71 @@ cmpk_handle_tx_status(
  * Return:		NONE
  *
  * Revised History:
- *	When		Who		Remark
- *	05/12/2008	amy		Create Version 0 porting from windows code.
+ *	When		Who	Remark
+ *	05/12/2008	amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-static	void
-cmpk_handle_tx_rate_history(
-	struct net_device *dev,
-	u8	   *pmsg)
+static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
 {
 	cmpk_tx_rahis_t	*ptxrate;
-//	RT_RF_POWER_STATE	rtState;
-	u8				i, j;
-	u16				length = sizeof(cmpk_tx_rahis_t);
-	u32				*ptemp;
+	u8		i, j;
+	u16		length = sizeof(cmpk_tx_rahis_t);
+	u32		*ptemp;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
 
 #ifdef ENABLE_PS
-	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
+	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
+					  (pu1Byte)(&rtState));
 
-	// When RF is off, we should not count the packet for hw/sw synchronize
-	// reason, ie. there may be a duration while sw switch is changed and hw
-	// switch is being changed. 2006.12.04, by shien chang.
+	/* When RF is off, we should not count the packet for hw/sw synchronize
+	   reason, ie. there may be a duration while sw switch is changed and
+	   hw switch is being changed. */
 	if (rtState == eRfOff)
-	{
 		return;
-	}
 #endif
 
 	ptemp = (u32 *)pmsg;
 
-	//
-	// Do endian transfer to word alignment(16 bits) for windows system.
-	// You must do different endian transfer for linux and MAC OS
-	//
-	for (i = 0; i < (length/4); i++)
-	{
+	/* Do endian transfer to word alignment(16 bits) for windows system.
+	   You must do different endian transfer for linux and MAC OS */
+	for (i = 0; i < (length/4); i++) {
 		u16	 temp1, temp2;
 
-		temp1 = ptemp[i]&0x0000FFFF;
-		temp2 = ptemp[i]>>16;
-		ptemp[i] = (temp1<<16)|temp2;
+		temp1 = ptemp[i] & 0x0000FFFF;
+		temp2 = ptemp[i] >> 16;
+		ptemp[i] = (temp1 << 16) | temp2;
 	}
 
 	ptxrate = (cmpk_tx_rahis_t *)pmsg;
 
-	if (ptxrate == NULL )
-	{
+	if (ptxrate == NULL)
 		return;
-	}
 
-	for (i = 0; i < 16; i++)
-	{
-		// Collect CCK rate packet num
+	for (i = 0; i < 16; i++) {
+		/* Collect CCK rate packet num */
 		if (i < 4)
 			priv->stats.txrate.cck[i] += ptxrate->cck[i];
 
-		// Collect OFDM rate packet num
-		if (i< 8)
+		/* Collect OFDM rate packet num */
+		if (i < 8)
 			priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
 
 		for (j = 0; j < 4; j++)
 			priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
 	}
 
-}	/* cmpk_Handle_Tx_Rate_History */
+}
 
 
 /*-----------------------------------------------------------------------------
  * Function:    cmpk_message_handle_rx()
  *
  * Overview:    In the function, we will capture different RX command packet
- *				info. Every RX command packet element has different message
- *				length and meaning in content. We only support three type of RX
- *				command packet now. Please refer to document
- *				ws-06-0063-rtl8190-command-packet-specification.
+ *		info. Every RX command packet element has different message
+ *		length and meaning in content. We only support three type of RX
+ *		command packet now. Please refer to document
+ *		ws-06-0063-rtl8190-command-packet-specification.
  *
  * Input:       NONE
  *
@@ -687,30 +587,22 @@ cmpk_handle_tx_rate_history(
  * Return:      NONE
  *
  * Revised History:
- *  When		Who		Remark
- *  05/06/2008	amy		Create Version 0 porting from windows code.
+ *  When		Who	Remark
+ *  05/06/2008		amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-extern	u32
-cmpk_message_handle_rx(
-	struct net_device *dev,
-	struct ieee80211_rx_stats *pstats)
+extern u32 cmpk_message_handle_rx(struct net_device *dev,
+				  struct ieee80211_rx_stats *pstats)
 {
-//	u32			debug_level = DBG_LOUD;
 	int			total_length;
 	u8			cmd_length, exe_cnt = 0;
 	u8			element_id;
 	u8			*pcmd_buff;
 
-	/* 0. Check inpt arguments. If is is a command queue message or pointer is
-	      null. */
-	if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL))
-	{
-		/* Print error message. */
-		/*RT_TRACE(COMP_SEND, DebugLevel,
-				("\n\r[CMPK]-->Err queue id or pointer"));*/
+	/* 0. Check inpt arguments. If is is a command queue message or
+	   pointer is null. */
+	if (pstats == NULL)
 		return 0;	/* This is not a command packet. */
-	}
 
 	/* 1. Read received command packet message length from RFD. */
 	total_length = pstats->Length;
@@ -720,67 +612,58 @@ cmpk_message_handle_rx(
 
 	/* 3. Read command packet element id and length. */
 	element_id = pcmd_buff[0];
-	/*RT_TRACE(COMP_SEND, DebugLevel,
-			("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
 
 	/* 4. Check every received command packet content according to different
-	      element type. Because FW may aggregate RX command packet to minimize
-	      transmit time between DRV and FW.*/
-	// Add a counter to prevent the lock in the loop from being held too long
-	while (total_length > 0 && exe_cnt++ < 100)
-	{
-		/* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
+	      element type. Because FW may aggregate RX command packet to
+	      minimize transmit time between DRV and FW.*/
+	/* Add a counter to prevent the lock in the loop from being held too
+	   long */
+	while (total_length > 0 && exe_cnt++ < 100) {
+		/* We support aggregation of different cmd in the same packet */
 		element_id = pcmd_buff[0];
 
-		switch (element_id)
-		{
-			case RX_TX_FEEDBACK:
-				cmpk_handle_tx_feedback (dev, pcmd_buff);
-				cmd_length = CMPK_RX_TX_FB_SIZE;
-				break;
-
-			case RX_INTERRUPT_STATUS:
-				cmpk_handle_interrupt_status(dev, pcmd_buff);
-				cmd_length = sizeof(cmpk_intr_sta_t);
-				break;
-
-			case BOTH_QUERY_CONFIG:
-				cmpk_handle_query_config_rx(dev, pcmd_buff);
-				cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
-				break;
-
-			case RX_TX_STATUS:
-				cmpk_handle_tx_status(dev, pcmd_buff);
-				cmd_length = CMPK_RX_TX_STS_SIZE;
-				break;
-
-			case RX_TX_PER_PKT_FEEDBACK:
-				// You must at lease add a switch case element here,
-				// Otherwise, we will jump to default case.
-				//DbgPrint("CCX Test\r\n");
-				cmd_length = CMPK_RX_TX_FB_SIZE;
-				break;
-
-			case RX_TX_RATE_HISTORY:
-				//DbgPrint(" rx tx rate history\r\n");
-				cmpk_handle_tx_rate_history(dev, pcmd_buff);
-				cmd_length = CMPK_TX_RAHIS_SIZE;
-				break;
-
-			default:
-
-				RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n");
-				return 1;	/* This is a command packet. */
+		switch (element_id) {
+		case RX_TX_FEEDBACK:
+			cmpk_handle_tx_feedback(dev, pcmd_buff);
+			cmd_length = CMPK_RX_TX_FB_SIZE;
+			break;
+
+		case RX_INTERRUPT_STATUS:
+			cmpk_handle_interrupt_status(dev, pcmd_buff);
+			cmd_length = sizeof(cmpk_intr_sta_t);
+			break;
+
+		case BOTH_QUERY_CONFIG:
+			cmpk_handle_query_config_rx(dev, pcmd_buff);
+			cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
+			break;
+
+		case RX_TX_STATUS:
+			cmpk_handle_tx_status(dev, pcmd_buff);
+			cmd_length = CMPK_RX_TX_STS_SIZE;
+			break;
+
+		case RX_TX_PER_PKT_FEEDBACK:
+			/* You must at lease add a switch case element here,
+			   Otherwise, we will jump to default case. */
+			cmd_length = CMPK_RX_TX_FB_SIZE;
+			break;
+
+		case RX_TX_RATE_HISTORY:
+			cmpk_handle_tx_rate_history(dev, pcmd_buff);
+			cmd_length = CMPK_TX_RAHIS_SIZE;
+			break;
+
+		default:
+
+			RT_TRACE(COMP_ERR, "---->%s():unknown CMD Element\n",
+				 __func__);
+			return 1;	/* This is a command packet. */
 		}
-		// 2007/01/22 MH Display received rx command packet info.
-		//cmpk_Display_Message(cmd_length, pcmd_buff);
-
-		// 2007/01/22 MH Add to display tx statistic.
-		//cmpk_DisplayTxStatistic(pAdapter);
 
 		total_length -= cmd_length;
 		pcmd_buff    += cmd_length;
-	}	/* while (total_length > 0) */
+	}
 	return	1;	/* This is a command packet. */
 
-}	/* CMPK_Message_Handle_Rx */
+}
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index f034567..d58aa7e 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -1000,12 +1000,8 @@ static int r871x_wx_set_priv(struct net_device *dev,
 		sprintf(ext, "LINKSPEED %d", mbps);
 	} else if (0 == strcasecmp(ext, "MACADDR")) {
 		/*Return mac address of the station */
-		/*Macaddr = xx.xx.xx.xx.xx.xx */
-		sprintf(ext,
-			"MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
-			*(dev->dev_addr), *(dev->dev_addr+1),
-			*(dev->dev_addr+2), *(dev->dev_addr+3),
-			*(dev->dev_addr+4), *(dev->dev_addr+5));
+		/* Macaddr = xx:xx:xx:xx:xx:xx */
+		sprintf(ext, "MACADDR = %pM", dev->dev_addr);
 	} else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
 		/*Set scan type to active */
 		/*OK if successful */
diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c
index 48b9fb1..495272d 100644
--- a/drivers/staging/silicom/bpctl_mod.c
+++ b/drivers/staging/silicom/bpctl_mod.c
@@ -59,7 +59,7 @@ struct bypass_pfs_sd {
 	struct proc_dir_entry *bypass_entry;
 };
 
-typedef struct _bpctl_dev {
+struct bpctl_dev {
 	char *name;
 	char *desc;
 	struct pci_dev *pdev;	/* PCI device */
@@ -102,26 +102,26 @@ typedef struct _bpctl_dev {
 	char *bp_tx_data;
 	struct bypass_pfs_sd bypass_pfs_set;
 
-} bpctl_dev_t;
+};
 
-static bpctl_dev_t *bpctl_dev_arr;
+static struct bpctl_dev *bpctl_dev_arr;
 
 static struct semaphore bpctl_sema;
 static int device_num;
 
 static int get_dev_idx(int ifindex);
-static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev);
-static int disc_status(bpctl_dev_t *pbpctl_dev);
-static int bypass_status(bpctl_dev_t *pbpctl_dev);
-static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left);
-static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev);
+static struct bpctl_dev *get_master_port_fn(struct bpctl_dev *pbpctl_dev);
+static int disc_status(struct bpctl_dev *pbpctl_dev);
+static int bypass_status(struct bpctl_dev *pbpctl_dev);
+static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left);
+static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev);
 static void if_scan_init(void);
 
-int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block);
-int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block);
+int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block);
+int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block);
 int bp_proc_create(void);
 
-int is_bypass_fn(bpctl_dev_t *pbpctl_dev);
+int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
 int get_dev_idx_bsf(int bus, int slot, int func);
 
 static unsigned long str_to_hex(char *p);
@@ -129,7 +129,7 @@ static int bp_device_event(struct notifier_block *unused,
 			   unsigned long event, void *ptr)
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	static bpctl_dev_t *pbpctl_dev, *pbpctl_dev_m;
+	static struct bpctl_dev *pbpctl_dev, *pbpctl_dev_m;
 	int dev_num = 0, ret = 0, ret_d = 0, time_left = 0;
 	/* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */
 	/* return NOTIFY_DONE; */
@@ -284,17 +284,17 @@ static struct notifier_block bp_notifier_block = {
 	.notifier_call = bp_device_event,
 };
 
-int is_bypass_fn(bpctl_dev_t *pbpctl_dev);
-int wdt_time_left(bpctl_dev_t *pbpctl_dev);
+int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
+int wdt_time_left(struct bpctl_dev *pbpctl_dev);
 
-static void write_pulse(bpctl_dev_t *pbpctl_dev,
+static void write_pulse(struct bpctl_dev *pbpctl_dev,
 			unsigned int ctrl_ext,
 			unsigned char value, unsigned char len)
 {
 	unsigned char ctrl_val = 0;
 	unsigned int i = len;
 	unsigned int ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_c = NULL;
+	struct bpctl_dev *pbpctl_dev_c = NULL;
 
 	if (pbpctl_dev->bp_i80)
 		ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
@@ -590,13 +590,13 @@ static void write_pulse(bpctl_dev_t *pbpctl_dev,
 	}
 }
 
-static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext,
+static int read_pulse(struct bpctl_dev *pbpctl_dev, unsigned int ctrl_ext,
 		      unsigned char len)
 {
 	unsigned char ctrl_val = 0;
 	unsigned int i = len;
 	unsigned int ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_c = NULL;
+	struct bpctl_dev *pbpctl_dev_c = NULL;
 
 	if (pbpctl_dev->bp_i80)
 		ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT);
@@ -765,11 +765,11 @@ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext,
 	return ctrl_val;
 }
 
-static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value,
+static void write_reg(struct bpctl_dev *pbpctl_dev, unsigned char value,
 		      unsigned char addr)
 {
 	uint32_t ctrl_ext = 0, ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_c = NULL;
+	struct bpctl_dev *pbpctl_dev_c = NULL;
 	unsigned long flags;
 	if (pbpctl_dev->bp_10g9) {
 		pbpctl_dev_c = get_status_port_fn(pbpctl_dev);
@@ -934,15 +934,15 @@ static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value,
 
 }
 
-static void write_data(bpctl_dev_t *pbpctl_dev, unsigned char value)
+static void write_data(struct bpctl_dev *pbpctl_dev, unsigned char value)
 {
 	write_reg(pbpctl_dev, value, CMND_REG_ADDR);
 }
 
-static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr)
+static int read_reg(struct bpctl_dev *pbpctl_dev, unsigned char addr)
 {
 	uint32_t ctrl_ext = 0, ctrl = 0, ctrl_value = 0;
-	bpctl_dev_t *pbpctl_dev_c = NULL;
+	struct bpctl_dev *pbpctl_dev_c = NULL;
 
 #ifdef BP_SYNC_FLAG
 	unsigned long flags;
@@ -1208,10 +1208,10 @@ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr)
 	return ctrl_value;
 }
 
-static int wdt_pulse(bpctl_dev_t *pbpctl_dev)
+static int wdt_pulse(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0, ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_c = NULL;
+	struct bpctl_dev *pbpctl_dev_c = NULL;
 
 #ifdef BP_SYNC_FLAG
 	unsigned long flags;
@@ -1424,7 +1424,7 @@ static int wdt_pulse(bpctl_dev_t *pbpctl_dev)
 	return 0;
 }
 
-static void data_pulse(bpctl_dev_t *pbpctl_dev, unsigned char value)
+static void data_pulse(struct bpctl_dev *pbpctl_dev, unsigned char value)
 {
 
 	uint32_t ctrl_ext = 0;
@@ -1490,7 +1490,7 @@ static void data_pulse(bpctl_dev_t *pbpctl_dev, unsigned char value)
 
 }
 
-static int send_wdt_pulse(bpctl_dev_t *pbpctl_dev)
+static int send_wdt_pulse(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1524,7 +1524,7 @@ static int send_wdt_pulse(bpctl_dev_t *pbpctl_dev)
 	return 0;
 }
 
-void send_bypass_clear_pulse(bpctl_dev_t *pbpctl_dev, unsigned int value)
+void send_bypass_clear_pulse(struct bpctl_dev *pbpctl_dev, unsigned int value)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1550,7 +1550,7 @@ void send_bypass_clear_pulse(bpctl_dev_t *pbpctl_dev, unsigned int value)
 /*  #endif  OLD_FW */
 #ifdef BYPASS_DEBUG
 
-int pulse_set_fn(bpctl_dev_t *pbpctl_dev, unsigned int counter)
+int pulse_set_fn(struct bpctl_dev *pbpctl_dev, unsigned int counter)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1578,7 +1578,7 @@ int pulse_set_fn(bpctl_dev_t *pbpctl_dev, unsigned int counter)
 	return 0;
 }
 
-int zero_set_fn(bpctl_dev_t *pbpctl_dev)
+int zero_set_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0, ctrl_value = 0;
 	if (!pbpctl_dev)
@@ -1603,7 +1603,7 @@ int zero_set_fn(bpctl_dev_t *pbpctl_dev)
 	return ctrl_value;
 }
 
-int pulse_get2_fn(bpctl_dev_t *pbpctl_dev)
+int pulse_get2_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0, ctrl_value = 0;
 	if (!pbpctl_dev)
@@ -1618,7 +1618,7 @@ int pulse_get2_fn(bpctl_dev_t *pbpctl_dev)
 	return ctrl_value;
 }
 
-int pulse_get1_fn(bpctl_dev_t *pbpctl_dev)
+int pulse_get1_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0, ctrl_value = 0;
 	if (!pbpctl_dev)
@@ -1635,7 +1635,7 @@ int pulse_get1_fn(bpctl_dev_t *pbpctl_dev)
 	return ctrl_value;
 }
 
-int gpio6_set_fn(bpctl_dev_t *pbpctl_dev)
+int gpio6_set_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1646,7 +1646,7 @@ int gpio6_set_fn(bpctl_dev_t *pbpctl_dev)
 	return 0;
 }
 
-int gpio7_set_fn(bpctl_dev_t *pbpctl_dev)
+int gpio7_set_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1657,7 +1657,7 @@ int gpio7_set_fn(bpctl_dev_t *pbpctl_dev)
 	return 0;
 }
 
-int gpio7_clear_fn(bpctl_dev_t *pbpctl_dev)
+int gpio7_clear_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1668,7 +1668,7 @@ int gpio7_clear_fn(bpctl_dev_t *pbpctl_dev)
 	return 0;
 }
 
-int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev)
+int gpio6_clear_fn(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
 
@@ -1680,9 +1680,9 @@ int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev)
 }
 #endif				/*BYPASS_DEBUG */
 
-static bpctl_dev_t *lookup_port(bpctl_dev_t *dev)
+static struct bpctl_dev *lookup_port(struct bpctl_dev *dev)
 {
-	bpctl_dev_t *p;
+	struct bpctl_dev *p;
 	int n;
 	for (n = 0, p = bpctl_dev_arr; n < device_num && p->pdev; n++) {
 		if (p->bus == dev->bus
@@ -1693,7 +1693,7 @@ static bpctl_dev_t *lookup_port(bpctl_dev_t *dev)
 	return NULL;
 }
 
-static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev)
+static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev) {
 		if (pbpctl_dev->func == 0 || pbpctl_dev->func == 2)
@@ -1702,7 +1702,7 @@ static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev)
 	return NULL;
 }
 
-static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev)
+static struct bpctl_dev *get_master_port_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev) {
 		if (pbpctl_dev->func == 1 || pbpctl_dev->func == 3)
@@ -1715,7 +1715,7 @@ static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev)
 /**************INTEL API***************/
 /**************************************/
 
-static void write_data_port_int(bpctl_dev_t *pbpctl_dev,
+static void write_data_port_int(struct bpctl_dev *pbpctl_dev,
 				unsigned char ctrl_value)
 {
 	uint32_t value;
@@ -1740,9 +1740,9 @@ static void write_data_port_int(bpctl_dev_t *pbpctl_dev,
 
 }
 
-static int write_data_int(bpctl_dev_t *pbpctl_dev, unsigned char value)
+static int write_data_int(struct bpctl_dev *pbpctl_dev, unsigned char value)
 {
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 	if (!pbpctl_dev_b)
@@ -1755,7 +1755,7 @@ static int write_data_int(bpctl_dev_t *pbpctl_dev, unsigned char value)
 	return 0;
 }
 
-static int wdt_pulse_int(bpctl_dev_t *pbpctl_dev)
+static int wdt_pulse_int(struct bpctl_dev *pbpctl_dev)
 {
 
 	if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1)
@@ -1779,7 +1779,7 @@ static int wdt_pulse_int(bpctl_dev_t *pbpctl_dev)
 /*************************************/
 
 /* CMND_ON  0x4 (100)*/
-int cmnd_on(bpctl_dev_t *pbpctl_dev)
+int cmnd_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1796,7 +1796,7 @@ int cmnd_on(bpctl_dev_t *pbpctl_dev)
 }
 
 /* CMND_OFF  0x2 (10)*/
-int cmnd_off(bpctl_dev_t *pbpctl_dev)
+int cmnd_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1809,12 +1809,12 @@ int cmnd_off(bpctl_dev_t *pbpctl_dev)
 		else
 			data_pulse(pbpctl_dev, CMND_OFF);
 		ret = 0;
-	};
+	}
 	return ret;
 }
 
 /* BYPASS_ON (0xa)*/
-int bypass_on(bpctl_dev_t *pbpctl_dev)
+int bypass_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1830,12 +1830,12 @@ int bypass_on(bpctl_dev_t *pbpctl_dev)
 		} else
 			data_pulse(pbpctl_dev, BYPASS_ON);
 		ret = 0;
-	};
+	}
 	return ret;
 }
 
 /* BYPASS_OFF (0x8 111)*/
-int bypass_off(bpctl_dev_t *pbpctl_dev)
+int bypass_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -1858,7 +1858,7 @@ int bypass_off(bpctl_dev_t *pbpctl_dev)
 }
 
 /* TAP_OFF (0x9)*/
-int tap_off(bpctl_dev_t *pbpctl_dev)
+int tap_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if ((pbpctl_dev->bp_caps & TAP_CAP)
@@ -1866,12 +1866,12 @@ int tap_off(bpctl_dev_t *pbpctl_dev)
 		write_data(pbpctl_dev, TAP_OFF);
 		msec_delay_bp(LATCH_DELAY);
 		ret = 0;
-	};
+	}
 	return ret;
 }
 
 /* TAP_ON (0xb)*/
-int tap_on(bpctl_dev_t *pbpctl_dev)
+int tap_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if ((pbpctl_dev->bp_caps & TAP_CAP)
@@ -1879,12 +1879,12 @@ int tap_on(bpctl_dev_t *pbpctl_dev)
 		write_data(pbpctl_dev, TAP_ON);
 		msec_delay_bp(LATCH_DELAY);
 		ret = 0;
-	};
+	}
 	return ret;
 }
 
 /* DISC_OFF (0x9)*/
-int disc_off(bpctl_dev_t *pbpctl_dev)
+int disc_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) {
@@ -1896,7 +1896,7 @@ int disc_off(bpctl_dev_t *pbpctl_dev)
 }
 
 /* DISC_ON (0xb)*/
-int disc_on(bpctl_dev_t *pbpctl_dev)
+int disc_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) {
@@ -1908,10 +1908,10 @@ int disc_on(bpctl_dev_t *pbpctl_dev)
 }
 
 /* DISC_PORT_ON */
-int disc_port_on(bpctl_dev_t *pbpctl_dev)
+int disc_port_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
 		pbpctl_dev_m = pbpctl_dev;
@@ -1933,10 +1933,10 @@ int disc_port_on(bpctl_dev_t *pbpctl_dev)
 }
 
 /* DISC_PORT_OFF */
-int disc_port_off(bpctl_dev_t *pbpctl_dev)
+int disc_port_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
 		pbpctl_dev_m = pbpctl_dev;
@@ -1958,10 +1958,10 @@ int disc_port_off(bpctl_dev_t *pbpctl_dev)
 }
 
 /*TWO_PORT_LINK_HW_EN (0xe)*/
-int tpl_hw_on(bpctl_dev_t *pbpctl_dev)
+int tpl_hw_on(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0, ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 	if (!pbpctl_dev_b)
@@ -1986,10 +1986,10 @@ int tpl_hw_on(bpctl_dev_t *pbpctl_dev)
 }
 
 /*TWO_PORT_LINK_HW_DIS (0xc)*/
-int tpl_hw_off(bpctl_dev_t *pbpctl_dev)
+int tpl_hw_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0, ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 	if (!pbpctl_dev_b)
@@ -2012,7 +2012,7 @@ int tpl_hw_off(bpctl_dev_t *pbpctl_dev)
 }
 
 /* WDT_OFF (0x6 110)*/
-int wdt_off(bpctl_dev_t *pbpctl_dev)
+int wdt_off(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -2025,7 +2025,7 @@ int wdt_off(bpctl_dev_t *pbpctl_dev)
 			data_pulse(pbpctl_dev, WDT_OFF);
 		pbpctl_dev->wdt_status = WDT_STATUS_DIS;
 		ret = 0;
-	};
+	}
 	return ret;
 }
 
@@ -2035,7 +2035,7 @@ int wdt_off(bpctl_dev_t *pbpctl_dev)
 static unsigned int
     wdt_val_array[] = { 1000, 1500, 2000, 3000, 4000, 8000, 16000, 32000, 0 };
 
-int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout)
+int wdt_on(struct bpctl_dev *pbpctl_dev, unsigned int timeout)
 {
 
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -2087,7 +2087,7 @@ int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout)
 	return BP_NOT_CAP;
 }
 
-void bp75_put_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev)
+void bp75_put_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
 {
 	u32 swsm;
 
@@ -2098,7 +2098,7 @@ void bp75_put_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev)
 	BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm);
 }
 
-s32 bp75_get_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev)
+s32 bp75_get_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev)
 {
 	u32 swsm;
 	s32 ret_val = 0;
@@ -2146,7 +2146,7 @@ s32 bp75_get_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev)
 	return ret_val;
 }
 
-static void bp75_release_phy(bpctl_dev_t *pbpctl_dev)
+static void bp75_release_phy(struct bpctl_dev *pbpctl_dev)
 {
 	u16 mask = BPCTLI_SWFW_PHY0_SM;
 	u32 swfw_sync;
@@ -2166,7 +2166,7 @@ static void bp75_release_phy(bpctl_dev_t *pbpctl_dev)
 	bp75_put_hw_semaphore_generic(pbpctl_dev);
 }
 
-static s32 bp75_acquire_phy(bpctl_dev_t *pbpctl_dev)
+static s32 bp75_acquire_phy(struct bpctl_dev *pbpctl_dev)
 {
 	u16 mask = BPCTLI_SWFW_PHY0_SM;
 	u32 swfw_sync;
@@ -2212,7 +2212,7 @@ static s32 bp75_acquire_phy(bpctl_dev_t *pbpctl_dev)
 	return ret_val;
 }
 
-s32 bp75_read_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data)
+s32 bp75_read_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data)
 {
 	u32 i, mdic = 0;
 	s32 ret_val = 0;
@@ -2245,7 +2245,7 @@ s32 bp75_read_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data)
 	return ret_val;
 }
 
-s32 bp75_write_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data)
+s32 bp75_write_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 data)
 {
 	u32 i, mdic = 0;
 	s32 ret_val = 0;
@@ -2278,7 +2278,7 @@ s32 bp75_write_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data)
 	return ret_val;
 }
 
-static s32 bp75_read_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data)
+static s32 bp75_read_phy_reg(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data)
 {
 	s32 ret_val = 0;
 
@@ -2304,7 +2304,7 @@ static s32 bp75_read_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data)
 	return ret_val;
 }
 
-static s32 bp75_write_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data)
+static s32 bp75_write_phy_reg(struct bpctl_dev *pbpctl_dev, u32 offset, u16 data)
 {
 	s32 ret_val = 0;
 
@@ -2332,10 +2332,10 @@ static s32 bp75_write_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data)
 }
 
 /* SET_TX  (non-Bypass command :)) */
-static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state)
+static int set_tx(struct bpctl_dev *pbpctl_dev, int tx_state)
 {
 	int ret = 0, ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
 		pbpctl_dev_m = pbpctl_dev;
 	else
@@ -2532,7 +2532,7 @@ static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state)
 }
 
 /* SET_FORCE_LINK  (non-Bypass command :)) */
-static int set_bp_force_link(bpctl_dev_t *pbpctl_dev, int tx_state)
+static int set_bp_force_link(struct bpctl_dev *pbpctl_dev, int tx_state)
 {
 	int ret = 0, ctrl = 0;
 
@@ -2556,7 +2556,7 @@ static int set_bp_force_link(bpctl_dev_t *pbpctl_dev, int tx_state)
 }
 
 /*RESET_CONT 0x20 */
-int reset_cont(bpctl_dev_t *pbpctl_dev)
+int reset_cont(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -2568,12 +2568,12 @@ int reset_cont(bpctl_dev_t *pbpctl_dev)
 		else
 			data_pulse(pbpctl_dev, RESET_CONT);
 		ret = 0;
-	};
+	}
 	return ret;
 }
 
 /*DIS_BYPASS_CAP 0x22 */
-int dis_bypass_cap(bpctl_dev_t *pbpctl_dev)
+int dis_bypass_cap(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
@@ -2592,7 +2592,7 @@ int dis_bypass_cap(bpctl_dev_t *pbpctl_dev)
 }
 
 /*EN_BYPASS_CAP 0x24 */
-int en_bypass_cap(bpctl_dev_t *pbpctl_dev)
+int en_bypass_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
 		if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) {
@@ -2608,7 +2608,7 @@ int en_bypass_cap(bpctl_dev_t *pbpctl_dev)
 }
 
 /* BYPASS_STATE_PWRON 0x26*/
-int bypass_state_pwron(bpctl_dev_t *pbpctl_dev)
+int bypass_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) {
 		write_data(pbpctl_dev, BYPASS_STATE_PWRON);
@@ -2622,7 +2622,7 @@ int bypass_state_pwron(bpctl_dev_t *pbpctl_dev)
 }
 
 /* NORMAL_STATE_PWRON 0x28*/
-int normal_state_pwron(bpctl_dev_t *pbpctl_dev)
+int normal_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if ((pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP)
 	    || (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)) {
@@ -2637,7 +2637,7 @@ int normal_state_pwron(bpctl_dev_t *pbpctl_dev)
 }
 
 /* BYPASS_STATE_PWROFF 0x27*/
-int bypass_state_pwroff(bpctl_dev_t *pbpctl_dev)
+int bypass_state_pwroff(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP) {
 		write_data(pbpctl_dev, BYPASS_STATE_PWROFF);
@@ -2648,7 +2648,7 @@ int bypass_state_pwroff(bpctl_dev_t *pbpctl_dev)
 }
 
 /* NORMAL_STATE_PWROFF 0x29*/
-int normal_state_pwroff(bpctl_dev_t *pbpctl_dev)
+int normal_state_pwroff(struct bpctl_dev *pbpctl_dev)
 {
 	if ((pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) {
 		write_data(pbpctl_dev, NORMAL_STATE_PWROFF);
@@ -2659,7 +2659,7 @@ int normal_state_pwroff(bpctl_dev_t *pbpctl_dev)
 }
 
 /*TAP_STATE_PWRON 0x2a*/
-int tap_state_pwron(bpctl_dev_t *pbpctl_dev)
+int tap_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
 		write_data(pbpctl_dev, TAP_STATE_PWRON);
@@ -2670,7 +2670,7 @@ int tap_state_pwron(bpctl_dev_t *pbpctl_dev)
 }
 
 /*DIS_TAP_CAP 0x2c*/
-int dis_tap_cap(bpctl_dev_t *pbpctl_dev)
+int dis_tap_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
 		write_data(pbpctl_dev, DIS_TAP_CAP);
@@ -2681,7 +2681,7 @@ int dis_tap_cap(bpctl_dev_t *pbpctl_dev)
 }
 
 /*EN_TAP_CAP 0x2e*/
-int en_tap_cap(bpctl_dev_t *pbpctl_dev)
+int en_tap_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_DIS_CAP) {
 		write_data(pbpctl_dev, EN_TAP_CAP);
@@ -2692,7 +2692,7 @@ int en_tap_cap(bpctl_dev_t *pbpctl_dev)
 }
 
 /*DISC_STATE_PWRON 0x2a*/
-int disc_state_pwron(bpctl_dev_t *pbpctl_dev)
+int disc_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8) {
@@ -2705,7 +2705,7 @@ int disc_state_pwron(bpctl_dev_t *pbpctl_dev)
 }
 
 /*DIS_DISC_CAP 0x2c*/
-int dis_disc_cap(bpctl_dev_t *pbpctl_dev)
+int dis_disc_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8) {
@@ -2718,10 +2718,10 @@ int dis_disc_cap(bpctl_dev_t *pbpctl_dev)
 }
 
 /*DISC_STATE_PWRON 0x2a*/
-int disc_port_state_pwron(bpctl_dev_t *pbpctl_dev)
+int disc_port_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 
 	return BP_NOT_CAP;
 
@@ -2744,10 +2744,10 @@ int disc_port_state_pwron(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int normal_port_state_pwron(bpctl_dev_t *pbpctl_dev)
+int normal_port_state_pwron(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 	return BP_NOT_CAP;
 
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
@@ -2770,7 +2770,7 @@ int normal_port_state_pwron(bpctl_dev_t *pbpctl_dev)
 }
 
 /*EN_TAP_CAP 0x2e*/
-int en_disc_cap(bpctl_dev_t *pbpctl_dev)
+int en_disc_cap(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_DIS_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8) {
@@ -2782,7 +2782,7 @@ int en_disc_cap(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int std_nic_on(bpctl_dev_t *pbpctl_dev)
+int std_nic_on(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
@@ -2836,7 +2836,7 @@ int std_nic_on(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int std_nic_off(bpctl_dev_t *pbpctl_dev)
+int std_nic_off(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & STD_NIC_CAP) {
@@ -2888,7 +2888,7 @@ int std_nic_off(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int wdt_time_left(bpctl_dev_t *pbpctl_dev)
+int wdt_time_left(struct bpctl_dev *pbpctl_dev)
 {
 
 	/* unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; */
@@ -2920,7 +2920,7 @@ int wdt_time_left(bpctl_dev_t *pbpctl_dev)
 	return time_left;
 }
 
-static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left)
+static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left)
 {
 	int ret = 0;
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -2936,7 +2936,7 @@ static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left)
 	return ret;
 }
 
-static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev)
+static int wdt_timer_reload(struct bpctl_dev *pbpctl_dev)
 {
 
 	int ret = 0;
@@ -2960,7 +2960,7 @@ static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev)
 
 static void wd_reset_timer(unsigned long param)
 {
-	bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param;
+	struct bpctl_dev *pbpctl_dev = (struct bpctl_dev *) param;
 #ifdef BP_SELF_TEST
 	struct sk_buff *skb_tmp;
 #endif
@@ -2999,7 +2999,7 @@ static void wd_reset_timer(unsigned long param)
 }
 
 /*WAIT_AT_PWRUP 0x80   */
-int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev)
+int bp_wait_at_pwup_en(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3014,7 +3014,7 @@ int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev)
 }
 
 /*DIS_WAIT_AT_PWRUP       0x81 */
-int bp_wait_at_pwup_dis(bpctl_dev_t *pbpctl_dev)
+int bp_wait_at_pwup_dis(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3031,7 +3031,7 @@ int bp_wait_at_pwup_dis(bpctl_dev_t *pbpctl_dev)
 
 /*EN_HW_RESET  0x82   */
 
-int bp_hw_reset_en(bpctl_dev_t *pbpctl_dev)
+int bp_hw_reset_en(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3047,7 +3047,7 @@ int bp_hw_reset_en(bpctl_dev_t *pbpctl_dev)
 
 /*DIS_HW_RESET             0x83   */
 
-int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev)
+int bp_hw_reset_dis(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3062,7 +3062,7 @@ int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev)
 }
 
 
-int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode)
+int wdt_exp_mode(struct bpctl_dev *pbpctl_dev, int mode)
 {
 	uint32_t status_reg = 0, status_reg1 = 0;
 
@@ -3113,7 +3113,7 @@ int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode)
 	return BP_NOT_CAP;
 }
 
-int bypass_fw_ver(bpctl_dev_t *pbpctl_dev)
+int bypass_fw_ver(struct bpctl_dev *pbpctl_dev)
 {
 	if (is_bypass_fn(pbpctl_dev))
 		return read_reg(pbpctl_dev, VER_REG_ADDR);
@@ -3121,7 +3121,7 @@ int bypass_fw_ver(bpctl_dev_t *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-int bypass_sign_check(bpctl_dev_t *pbpctl_dev)
+int bypass_sign_check(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (is_bypass_fn(pbpctl_dev))
@@ -3131,10 +3131,10 @@ int bypass_sign_check(bpctl_dev_t *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-static int tx_status(bpctl_dev_t *pbpctl_dev)
+static int tx_status(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl = 0;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
 		pbpctl_dev_m = pbpctl_dev;
 	else
@@ -3218,7 +3218,7 @@ static int tx_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-static int bp_force_link_status(bpctl_dev_t *pbpctl_dev)
+static int bp_force_link_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (DBI_IF_SERIES(pbpctl_dev->subdevice)) {
@@ -3232,10 +3232,10 @@ static int bp_force_link_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bypass_from_last_read(bpctl_dev_t *pbpctl_dev)
+int bypass_from_last_read(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t ctrl_ext = 0;
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
 		pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
@@ -3252,9 +3252,9 @@ int bypass_from_last_read(bpctl_dev_t *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-int bypass_status_clear(bpctl_dev_t *pbpctl_dev)
+int bypass_status_clear(struct bpctl_dev *pbpctl_dev)
 {
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
 		pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
@@ -3266,7 +3266,7 @@ int bypass_status_clear(bpctl_dev_t *pbpctl_dev)
 		return BP_NOT_CAP;
 }
 
-int bypass_flag_status(bpctl_dev_t *pbpctl_dev)
+int bypass_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if ((pbpctl_dev->bp_caps & BP_CAP)) {
@@ -3279,7 +3279,7 @@ int bypass_flag_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bypass_flag_status_clear(bpctl_dev_t *pbpctl_dev)
+int bypass_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_CAP) {
@@ -3294,7 +3294,7 @@ int bypass_flag_status_clear(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bypass_change_status(bpctl_dev_t *pbpctl_dev)
+int bypass_change_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -3313,7 +3313,7 @@ int bypass_change_status(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int bypass_off_status(bpctl_dev_t *pbpctl_dev)
+int bypass_off_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_CAP) {
@@ -3325,12 +3325,12 @@ int bypass_off_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-static int bypass_status(bpctl_dev_t *pbpctl_dev)
+static int bypass_status(struct bpctl_dev *pbpctl_dev)
 {
 	u32 ctrl_ext = 0;
 	if (pbpctl_dev->bp_caps & BP_CAP) {
 
-		bpctl_dev_t *pbpctl_dev_b = NULL;
+		struct bpctl_dev *pbpctl_dev_b = NULL;
 
 		pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 		if (!pbpctl_dev_b)
@@ -3408,7 +3408,7 @@ static int bypass_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int default_pwron_status(bpctl_dev_t *pbpctl_dev)
+int default_pwron_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3426,7 +3426,7 @@ int default_pwron_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-static int default_pwroff_status(bpctl_dev_t *pbpctl_dev)
+static int default_pwroff_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	/*if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&&
@@ -3440,7 +3440,7 @@ static int default_pwroff_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int dis_bypass_cap_status(bpctl_dev_t *pbpctl_dev)
+int dis_bypass_cap_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & BP_DIS_CAP) {
@@ -3453,7 +3453,7 @@ int dis_bypass_cap_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int cmd_en_status(bpctl_dev_t *pbpctl_dev)
+int cmd_en_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3465,7 +3465,7 @@ int cmd_en_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int wdt_en_status(bpctl_dev_t *pbpctl_dev)
+int wdt_en_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -3477,7 +3477,7 @@ int wdt_en_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int wdt_programmed(bpctl_dev_t *pbpctl_dev, int *timeout)
+int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout)
 {
 	int ret = 0;
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -3497,13 +3497,13 @@ int wdt_programmed(bpctl_dev_t *pbpctl_dev, int *timeout)
 				*timeout =
 				    curr_wdt_status ==
 				    0 ? 0 : pbpctl_dev->bypass_timer_interval;
-		};
+		}
 	} else
 		ret = BP_NOT_CAP;
 	return ret;
 }
 
-int bypass_support(bpctl_dev_t *pbpctl_dev)
+int bypass_support(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 
@@ -3520,7 +3520,7 @@ int bypass_support(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int tap_support(bpctl_dev_t *pbpctl_dev)
+int tap_support(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 
@@ -3536,7 +3536,7 @@ int tap_support(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int normal_support(bpctl_dev_t *pbpctl_dev)
+int normal_support(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 
@@ -3548,11 +3548,11 @@ int normal_support(bpctl_dev_t *pbpctl_dev)
 			      NORMAL_UNSUPPORT_MASK) ? 0 : 1);
 		} else
 			ret = 1;
-	};
+	}
 	return ret;
 }
 
-int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev)
+int get_bp_prod_caps(struct bpctl_dev *pbpctl_dev)
 {
 	if ((pbpctl_dev->bp_caps & SW_CTL_CAP) &&
 	    (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER))
@@ -3561,7 +3561,7 @@ int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev)
 
 }
 
-int tap_flag_status(bpctl_dev_t *pbpctl_dev)
+int tap_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) {
@@ -3573,7 +3573,7 @@ int tap_flag_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tap_flag_status_clear(bpctl_dev_t *pbpctl_dev)
+int tap_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t status_reg = 0;
 	if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) {
@@ -3587,7 +3587,7 @@ int tap_flag_status_clear(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tap_change_status(bpctl_dev_t *pbpctl_dev)
+int tap_change_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) {
@@ -3604,7 +3604,7 @@ int tap_change_status(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int tap_off_status(bpctl_dev_t *pbpctl_dev)
+int tap_off_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
@@ -3614,12 +3614,12 @@ int tap_off_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tap_status(bpctl_dev_t *pbpctl_dev)
+int tap_status(struct bpctl_dev *pbpctl_dev)
 {
 	u32 ctrl_ext = 0;
 
 	if (pbpctl_dev->bp_caps & TAP_CAP) {
-		bpctl_dev_t *pbpctl_dev_b = NULL;
+		struct bpctl_dev *pbpctl_dev_b = NULL;
 
 		pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 		if (!pbpctl_dev_b)
@@ -3653,7 +3653,7 @@ int tap_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int default_pwron_tap_status(bpctl_dev_t *pbpctl_dev)
+int default_pwron_tap_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
@@ -3664,7 +3664,7 @@ int default_pwron_tap_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int dis_tap_cap_status(bpctl_dev_t *pbpctl_dev)
+int dis_tap_cap_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)
@@ -3675,7 +3675,7 @@ int dis_tap_cap_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_flag_status(bpctl_dev_t *pbpctl_dev)
+int disc_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3687,7 +3687,7 @@ int disc_flag_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_flag_status_clear(bpctl_dev_t *pbpctl_dev)
+int disc_flag_status_clear(struct bpctl_dev *pbpctl_dev)
 {
 	uint32_t status_reg = 0;
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3701,7 +3701,7 @@ int disc_flag_status_clear(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_change_status(bpctl_dev_t *pbpctl_dev)
+int disc_change_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3712,9 +3712,9 @@ int disc_change_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_off_status(bpctl_dev_t *pbpctl_dev)
+int disc_off_status(struct bpctl_dev *pbpctl_dev)
 {
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 	u32 ctrl_ext = 0;
 
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3796,7 +3796,7 @@ int disc_off_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-static int disc_status(bpctl_dev_t *pbpctl_dev)
+static int disc_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ctrl = 0;
 	if (pbpctl_dev->bp_caps & DISC_CAP) {
@@ -3808,7 +3808,7 @@ static int disc_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int default_pwron_disc_status(bpctl_dev_t *pbpctl_dev)
+int default_pwron_disc_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8)
@@ -3819,7 +3819,7 @@ int default_pwron_disc_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int dis_disc_cap_status(bpctl_dev_t *pbpctl_dev)
+int dis_disc_cap_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & DIS_DISC_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8)
@@ -3830,10 +3830,10 @@ int dis_disc_cap_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int disc_port_status(bpctl_dev_t *pbpctl_dev)
+int disc_port_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
 		pbpctl_dev_m = pbpctl_dev;
@@ -3854,10 +3854,10 @@ int disc_port_status(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev)
+int default_pwron_disc_port_status(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
-	bpctl_dev_t *pbpctl_dev_m;
+	struct bpctl_dev *pbpctl_dev_m;
 
 	if ((is_bypass_fn(pbpctl_dev)) == 1)
 		pbpctl_dev_m = pbpctl_dev;
@@ -3878,7 +3878,7 @@ int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int wdt_exp_mode_status(bpctl_dev_t *pbpctl_dev)
+int wdt_exp_mode_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver <= PXG2BPI_VER)
@@ -3901,7 +3901,7 @@ int wdt_exp_mode_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tpl2_flag_status(bpctl_dev_t *pbpctl_dev)
+int tpl2_flag_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) {
@@ -3912,9 +3912,9 @@ int tpl2_flag_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int tpl_hw_status(bpctl_dev_t *pbpctl_dev)
+int tpl_hw_status(struct bpctl_dev *pbpctl_dev)
 {
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 	if (!pbpctl_dev_b)
@@ -3927,7 +3927,7 @@ int tpl_hw_status(bpctl_dev_t *pbpctl_dev)
 }
 
 
-int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev)
+int bp_wait_at_pwup_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
 		if (pbpctl_dev->bp_ext_ver >= 0x8)
@@ -3938,7 +3938,7 @@ int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev)
+int bp_hw_reset_status(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & SW_CTL_CAP) {
@@ -3952,7 +3952,7 @@ int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev)
 }
 
 
-int std_nic_status(bpctl_dev_t *pbpctl_dev)
+int std_nic_status(struct bpctl_dev *pbpctl_dev)
 {
 	int status_val = 0;
 
@@ -4000,10 +4000,10 @@ int std_nic_status(bpctl_dev_t *pbpctl_dev)
 /******************************************************/
 /**************SW_INIT*********************************/
 /******************************************************/
-void bypass_caps_init(bpctl_dev_t *pbpctl_dev)
+void bypass_caps_init(struct bpctl_dev *pbpctl_dev)
 {
 	u_int32_t ctrl_ext = 0;
-	bpctl_dev_t *pbpctl_dev_m = NULL;
+	struct bpctl_dev *pbpctl_dev_m = NULL;
 
 #ifdef BYPASS_DEBUG
 	int ret = 0;
@@ -4218,7 +4218,7 @@ void bypass_caps_init(bpctl_dev_t *pbpctl_dev)
 	}
 }
 
-int bypass_off_init(bpctl_dev_t *pbpctl_dev)
+int bypass_off_init(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = cmnd_on(pbpctl_dev);
 	if (ret < 0)
@@ -4234,10 +4234,10 @@ int bypass_off_init(bpctl_dev_t *pbpctl_dev)
 	return 0;
 }
 
-void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
+void remove_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 {
 #ifdef BP_SELF_TEST
-	bpctl_dev_t *pbpctl_dev_sl = NULL;
+	struct bpctl_dev *pbpctl_dev_sl = NULL;
 #endif
 
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -4263,7 +4263,7 @@ void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
 
 }
 
-int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
+int init_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		init_timer(&pbpctl_dev->bp_timer);
@@ -4277,7 +4277,7 @@ int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
 #ifdef BP_SELF_TEST
 int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL;
+	struct bpctl_dev *pbpctl_dev = NULL, *pbpctl_dev_m = NULL;
 	int idx_dev = 0;
 	struct ethhdr *eth = (struct ethhdr *)skb->data;
 
@@ -4310,7 +4310,7 @@ int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 #endif
 
-int set_bypass_wd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
+int set_bypass_wd_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		if (pbpctl_dev->reset_time != param) {
@@ -4329,7 +4329,7 @@ int set_bypass_wd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
 	return BP_NOT_CAP;
 }
 
-int get_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
+int get_bypass_wd_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP)
 		return pbpctl_dev->reset_time;
@@ -4339,9 +4339,9 @@ int get_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
 
 #ifdef BP_SELF_TEST
 
-int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param)
+int set_bp_self_test(struct bpctl_dev *pbpctl_dev, unsigned int param)
 {
-	bpctl_dev_t *pbpctl_dev_sl = NULL;
+	struct bpctl_dev *pbpctl_dev_sl = NULL;
 
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		pbpctl_dev->bp_self_test_flag = param == 0 ? 0 : 1;
@@ -4374,7 +4374,7 @@ int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param)
 	return BP_NOT_CAP;
 }
 
-int get_bp_self_test(bpctl_dev_t *pbpctl_dev)
+int get_bp_self_test(struct bpctl_dev *pbpctl_dev)
 {
 
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
@@ -4392,7 +4392,7 @@ int get_bp_self_test(bpctl_dev_t *pbpctl_dev)
 /************************* API ********************************/
 /**************************************************************/
 
-int is_bypass_fn(bpctl_dev_t *pbpctl_dev)
+int is_bypass_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4400,7 +4400,7 @@ int is_bypass_fn(bpctl_dev_t *pbpctl_dev)
 	return (((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) ? 1 : 0);
 }
 
-int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
+int set_bypass_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 {
 	int ret = 0;
 
@@ -4418,12 +4418,12 @@ int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
 	return ret;
 }
 
-int get_bypass_fn(bpctl_dev_t *pbpctl_dev)
+int get_bypass_fn(struct bpctl_dev *pbpctl_dev)
 {
 	return bypass_status(pbpctl_dev);
 }
 
-int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev)
+int get_bypass_change_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4431,7 +4431,7 @@ int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev)
 	return bypass_change_status(pbpctl_dev);
 }
 
-int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
+int set_dis_bypass_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4450,7 +4450,7 @@ int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
 	return ret;
 }
 
-int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev)
+int get_dis_bypass_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4458,7 +4458,7 @@ int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev)
 	return dis_bypass_cap_status(pbpctl_dev);
 }
 
-int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
+int set_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4477,7 +4477,7 @@ int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
 	return ret;
 }
 
-int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev)
+int get_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4485,7 +4485,7 @@ int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev)
 	return default_pwroff_status(pbpctl_dev);
 }
 
-int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
+int set_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4504,7 +4504,7 @@ int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode)
 	return ret;
 }
 
-int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev)
+int get_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4512,7 +4512,7 @@ int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev)
 	return default_pwron_status(pbpctl_dev);
 }
 
-int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout)
+int set_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int timeout)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4534,7 +4534,7 @@ int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout)
 	return ret;
 }
 
-int get_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int *timeout)
+int get_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int *timeout)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4542,7 +4542,7 @@ int get_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int *timeout)
 	return wdt_programmed(pbpctl_dev, timeout);
 }
 
-int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left)
+int get_wd_expire_time_fn(struct bpctl_dev *pbpctl_dev, int *time_left)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4550,7 +4550,7 @@ int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left)
 	return wdt_timer(pbpctl_dev, time_left);
 }
 
-int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev)
+int reset_bypass_wd_timer_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4558,7 +4558,7 @@ int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev)
 	return wdt_timer_reload(pbpctl_dev);
 }
 
-int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev)
+int get_wd_set_caps_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int bp_status = 0;
 
@@ -4582,7 +4582,7 @@ int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev)
 	return bp_status;
 }
 
-int set_std_nic_fn(bpctl_dev_t *pbpctl_dev, int nic_mode)
+int set_std_nic_fn(struct bpctl_dev *pbpctl_dev, int nic_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4602,7 +4602,7 @@ int set_std_nic_fn(bpctl_dev_t *pbpctl_dev, int nic_mode)
 	return ret;
 }
 
-int get_std_nic_fn(bpctl_dev_t *pbpctl_dev)
+int get_std_nic_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4610,7 +4610,7 @@ int get_std_nic_fn(bpctl_dev_t *pbpctl_dev)
 	return std_nic_status(pbpctl_dev);
 }
 
-int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+int set_tap_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4626,7 +4626,7 @@ int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
 	return BP_NOT_CAP;
 }
 
-int get_tap_fn(bpctl_dev_t *pbpctl_dev)
+int get_tap_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4634,7 +4634,7 @@ int get_tap_fn(bpctl_dev_t *pbpctl_dev)
 	return tap_status(pbpctl_dev);
 }
 
-int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+int set_tap_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4652,7 +4652,7 @@ int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
 	return ret;
 }
 
-int get_tap_pwup_fn(bpctl_dev_t *pbpctl_dev)
+int get_tap_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4664,7 +4664,7 @@ int get_tap_pwup_fn(bpctl_dev_t *pbpctl_dev)
 	return ((ret == 0) ? 1 : 0);
 }
 
-int get_tap_change_fn(bpctl_dev_t *pbpctl_dev)
+int get_tap_change_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4672,7 +4672,7 @@ int get_tap_change_fn(bpctl_dev_t *pbpctl_dev)
 	return tap_change_status(pbpctl_dev);
 }
 
-int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
+int set_dis_tap_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4689,7 +4689,7 @@ int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
 		return BP_NOT_CAP;
 }
 
-int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev)
+int get_dis_tap_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4697,7 +4697,7 @@ int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev)
 	return dis_tap_cap_status(pbpctl_dev);
 }
 
-int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+int set_disc_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4714,7 +4714,7 @@ int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
 	return BP_NOT_CAP;
 }
 
-int get_disc_fn(bpctl_dev_t *pbpctl_dev)
+int get_disc_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4725,7 +4725,7 @@ int get_disc_fn(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int set_disc_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+int set_disc_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4743,7 +4743,7 @@ int set_disc_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
 	return ret;
 }
 
-int get_disc_pwup_fn(bpctl_dev_t *pbpctl_dev)
+int get_disc_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4753,7 +4753,7 @@ int get_disc_pwup_fn(bpctl_dev_t *pbpctl_dev)
 	return (ret == 0 ? 1 : (ret < 0 ? BP_NOT_CAP : 0));
 }
 
-int get_disc_change_fn(bpctl_dev_t *pbpctl_dev)
+int get_disc_change_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4763,7 +4763,7 @@ int get_disc_change_fn(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int set_dis_disc_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
+int set_dis_disc_fn(struct bpctl_dev *pbpctl_dev, int dis_param)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4781,7 +4781,7 @@ int set_dis_disc_fn(bpctl_dev_t *pbpctl_dev, int dis_param)
 		return BP_NOT_CAP;
 }
 
-int get_dis_disc_fn(bpctl_dev_t *pbpctl_dev)
+int get_dis_disc_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4792,7 +4792,7 @@ int get_dis_disc_fn(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int set_disc_port_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+int set_disc_port_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 {
 	int ret = BP_NOT_CAP;
 	if (!pbpctl_dev)
@@ -4806,7 +4806,7 @@ int set_disc_port_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
 	return ret;
 }
 
-int get_disc_port_fn(bpctl_dev_t *pbpctl_dev)
+int get_disc_port_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4814,7 +4814,7 @@ int get_disc_port_fn(bpctl_dev_t *pbpctl_dev)
 	return disc_port_status(pbpctl_dev);
 }
 
-int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
+int set_disc_port_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode)
 {
 	int ret = BP_NOT_CAP;
 	if (!pbpctl_dev)
@@ -4828,7 +4828,7 @@ int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode)
 	return ret;
 }
 
-int get_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev)
+int get_disc_port_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4840,7 +4840,7 @@ int get_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev)
 	return ((ret == 0) ? 1 : 0);
 }
 
-int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev)
+int get_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4848,7 +4848,7 @@ int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev)
 	return wdt_exp_mode_status(pbpctl_dev);
 }
 
-int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param)
+int set_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev, int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4856,7 +4856,7 @@ int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param)
 	return wdt_exp_mode(pbpctl_dev, param);
 }
 
-int reset_cont_fn(bpctl_dev_t *pbpctl_dev)
+int reset_cont_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -4868,10 +4868,10 @@ int reset_cont_fn(bpctl_dev_t *pbpctl_dev)
 	return reset_cont(pbpctl_dev);
 }
 
-int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state)
+int set_tx_fn(struct bpctl_dev *pbpctl_dev, int tx_state)
 {
 
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 	if (!pbpctl_dev)
 		return -1;
 
@@ -4891,7 +4891,7 @@ int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state)
 
 int set_bp_force_link_fn(int dev_num, int tx_state)
 {
-	static bpctl_dev_t *bpctl_dev_curr;
+	static struct bpctl_dev *bpctl_dev_curr;
 
 	if ((dev_num < 0) || (dev_num > device_num)
 	    || (bpctl_dev_arr[dev_num].pdev == NULL))
@@ -4901,7 +4901,7 @@ int set_bp_force_link_fn(int dev_num, int tx_state)
 	return set_bp_force_link(bpctl_dev_curr, tx_state);
 }
 
-int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param)
+int set_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev, int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4909,7 +4909,7 @@ int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param)
 	return set_bypass_wd_auto(pbpctl_dev, param);
 }
 
-int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev)
+int get_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4918,7 +4918,7 @@ int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev)
 }
 
 #ifdef BP_SELF_TEST
-int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param)
+int set_bp_self_test_fn(struct bpctl_dev *pbpctl_dev, int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4926,7 +4926,7 @@ int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param)
 	return set_bp_self_test(pbpctl_dev, param);
 }
 
-int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev)
+int get_bp_self_test_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4936,7 +4936,7 @@ int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev)
 
 #endif
 
-int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev)
+int get_bypass_caps_fn(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4945,7 +4945,7 @@ int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev)
 
 }
 
-int get_bypass_slave_fn(bpctl_dev_t *pbpctl_dev, bpctl_dev_t **pbpctl_dev_out)
+int get_bypass_slave_fn(struct bpctl_dev *pbpctl_dev, struct bpctl_dev **pbpctl_dev_out)
 {
 	int idx_dev = 0;
 	if (!pbpctl_dev)
@@ -4977,7 +4977,7 @@ int get_bypass_slave_fn(bpctl_dev_t *pbpctl_dev, bpctl_dev_t **pbpctl_dev_out)
 		return 0;
 }
 
-int is_bypass(bpctl_dev_t *pbpctl_dev)
+int is_bypass(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -4988,9 +4988,9 @@ int is_bypass(bpctl_dev_t *pbpctl_dev)
 		return 0;
 }
 
-int get_tx_fn(bpctl_dev_t *pbpctl_dev)
+int get_tx_fn(struct bpctl_dev *pbpctl_dev)
 {
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 	if (!pbpctl_dev)
 		return -1;
 
@@ -5010,7 +5010,7 @@ int get_tx_fn(bpctl_dev_t *pbpctl_dev)
 
 int get_bp_force_link_fn(int dev_num)
 {
-	static bpctl_dev_t *bpctl_dev_curr;
+	static struct bpctl_dev *bpctl_dev_curr;
 
 	if ((dev_num < 0) || (dev_num > device_num)
 	    || (bpctl_dev_arr[dev_num].pdev == NULL))
@@ -5020,7 +5020,7 @@ int get_bp_force_link_fn(int dev_num)
 	return bp_force_link_status(bpctl_dev_curr);
 }
 
-static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev)
+static int get_bypass_link_status(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5036,9 +5036,9 @@ static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev)
 
 static void bp_tpl_timer_fn(unsigned long param)
 {
-	bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param;
+	struct bpctl_dev *pbpctl_dev = (struct bpctl_dev *) param;
 	uint32_t link1, link2;
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 
 	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
 	if (!pbpctl_dev_b)
@@ -5071,9 +5071,9 @@ static void bp_tpl_timer_fn(unsigned long param)
 	mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + BP_LINK_MON_DELAY * HZ);
 }
 
-void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
+void remove_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 {
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 	if (!pbpctl_dev)
 		return;
 	pbpctl_dev_b = get_status_port_fn(pbpctl_dev);
@@ -5089,7 +5089,7 @@ void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
 	return;
 }
 
-int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
+int init_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5102,7 +5102,7 @@ int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
+int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5111,7 +5111,7 @@ int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
 			pbpctl_dev->bp_tpl_flag = param;
 			mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + 1);
 			return BP_OK;
-		};
+		}
 		if ((!param) && (pbpctl_dev->bp_tpl_flag))
 			remove_bypass_tpl_auto(pbpctl_dev);
 
@@ -5120,7 +5120,7 @@ int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param)
 	return BP_NOT_CAP;
 }
 
-int get_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
+int get_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5130,10 +5130,10 @@ int get_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev)
 	return BP_NOT_CAP;
 }
 
-int set_tpl_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode)
+int set_tpl_fn(struct bpctl_dev *pbpctl_dev, int tpl_mode)
 {
 
-	bpctl_dev_t *pbpctl_dev_b = NULL;
+	struct bpctl_dev *pbpctl_dev_b = NULL;
 	if (!pbpctl_dev)
 		return -1;
 
@@ -5160,7 +5160,7 @@ int set_tpl_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode)
 	return BP_NOT_CAP;
 }
 
-int get_tpl_fn(bpctl_dev_t *pbpctl_dev)
+int get_tpl_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = BP_NOT_CAP;
 	if (!pbpctl_dev)
@@ -5174,7 +5174,7 @@ int get_tpl_fn(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+int set_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5194,7 +5194,7 @@ int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
 	return BP_NOT_CAP;
 }
 
-int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev)
+int get_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -5207,7 +5207,7 @@ int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev)
 	return ret;
 }
 
-int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
+int set_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev, int tap_mode)
 {
 	if (!pbpctl_dev)
 		return -1;
@@ -5227,7 +5227,7 @@ int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode)
 	return BP_NOT_CAP;
 }
 
-int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev)
+int get_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev)
 {
 	int ret = 0;
 	if (!pbpctl_dev)
@@ -5242,7 +5242,7 @@ int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev)
 }
 
 
-int get_bypass_info_fn(bpctl_dev_t *pbpctl_dev, char *dev_name,
+int get_bypass_info_fn(struct bpctl_dev *pbpctl_dev, char *dev_name,
 		       char *add_param)
 {
 	if (!pbpctl_dev)
@@ -5313,7 +5313,7 @@ static int get_dev_idx(int ifindex)
 	return -1;
 }
 
-static bpctl_dev_t *get_dev_idx_p(int ifindex)
+static struct bpctl_dev *get_dev_idx_p(int ifindex)
 {
 	int idx_dev = 0;
 
@@ -5401,12 +5401,12 @@ static long device_ioctl(struct file *file,	/* see include/linux/fs.h */
 {
 	struct bpctl_cmd bpctl_cmd;
 	int dev_idx = 0;
-	bpctl_dev_t *pbpctl_dev_out;
+	struct bpctl_dev *pbpctl_dev_out;
 	void __user *argp = (void __user *)ioctl_param;
 	int ret = 0;
 	unsigned long flags;
 
-	static bpctl_dev_t *pbpctl_dev;
+	static struct bpctl_dev *pbpctl_dev;
 
 	/* lock_kernel(); */
 	if (down_interruptible(&bpctl_sema))
@@ -5971,7 +5971,7 @@ enum board_type {
 	PE210G2BPi40,
 };
 
-typedef struct _bpmod_info_t {
+struct bpmod_info {
 	unsigned int vendor;
 	unsigned int device;
 	unsigned int subvendor;
@@ -5979,13 +5979,11 @@ typedef struct _bpmod_info_t {
 	unsigned int index;
 	char *bp_name;
 
-} bpmod_info_t;
+};
 
-typedef struct _dev_desc {
+struct {
 	char *name;
-} dev_desc_t;
-
-dev_desc_t dev_desc[] = {
+} dev_desc[] = {
 	{"Silicom Bypass PXG2BPFI-SD series adapter"},
 	{"Silicom Bypass PXG2BPFIL-SD series adapter"},
 	{"Silicom Bypass PXG2BPFILX-SD series adapter"},
@@ -6155,7 +6153,7 @@ dev_desc_t dev_desc[] = {
 	{0},
 };
 
-static bpmod_info_t tx_ctl_pci_tbl[] = {
+static struct bpmod_info tx_ctl_pci_tbl[] = {
 	{0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFI_SSID, PXG2BPFI,
 	 "PXG2BPFI-SD"},
 	{0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFIL_SSID, PXG2BPFIL,
@@ -6623,7 +6621,7 @@ static bpmod_info_t tx_ctl_pci_tbl[] = {
 	{0,}
 };
 
-static void find_fw(bpctl_dev_t *dev)
+static void find_fw(struct bpctl_dev *dev)
 {
 	unsigned long mmio_start, mmio_len;
 	struct pci_dev *pdev1 = dev->pdev;
@@ -6653,7 +6651,7 @@ static void find_fw(bpctl_dev_t *dev)
 	printk("firmware version: 0x%x\n", dev->bp_fw_ver);
 }
 
-static int init_one(bpctl_dev_t *dev, bpmod_info_t *info, struct pci_dev *pdev1)
+static int init_one(struct bpctl_dev *dev, struct bpmod_info *info, struct pci_dev *pdev1)
 {
 	unsigned long mmio_start, mmio_len;
 
@@ -6744,7 +6742,7 @@ static int __init bypass_init_module(void)
 {
 	int ret_val, idx, idx_dev = 0;
 	struct pci_dev *pdev1 = NULL;
-	bpctl_dev_t *dev;
+	struct bpctl_dev *dev;
 
 	printk(BP_MOD_DESCR " v" BP_MOD_VER "\n");
 	ret_val = register_chrdev(major_num, DEVICE_NAME, &Fops);
@@ -6769,14 +6767,14 @@ static int __init bypass_init_module(void)
 		return -1;
 	}
 
-	bpctl_dev_arr = kmalloc((device_num) * sizeof(bpctl_dev_t), GFP_KERNEL);
+	bpctl_dev_arr = kmalloc((device_num) * sizeof(struct bpctl_dev), GFP_KERNEL);
 
 	if (!bpctl_dev_arr) {
 		printk("Allocation error\n");
 		unregister_chrdev(major_num, DEVICE_NAME);
 		return -1;
 	}
-	memset(bpctl_dev_arr, 0, ((device_num) * sizeof(bpctl_dev_t)));
+	memset(bpctl_dev_arr, 0, ((device_num) * sizeof(struct bpctl_dev)));
 
 	pdev1 = NULL;
 	dev = bpctl_dev_arr;
@@ -6797,7 +6795,7 @@ static int __init bypass_init_module(void)
 	spin_lock_init(&bpvm_lock);
 	{
 
-		bpctl_dev_t *pbpctl_dev_c = NULL;
+		struct bpctl_dev *pbpctl_dev_c = NULL;
 		for (idx_dev = 0, dev = bpctl_dev_arr;
 		     idx_dev < device_num && dev->pdev;
 		     idx_dev++, dev++) {
@@ -7169,7 +7167,7 @@ EXPORT_SYMBOL(get_bypass_caps_sd);
 
 int get_bypass_slave_sd(int ifindex)
 {
-	bpctl_dev_t *pbpctl_dev_out;
+	struct bpctl_dev *pbpctl_dev_out;
 	int ret = get_bypass_slave_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out);
 	if (ret == 1)
 		return pbpctl_dev_out->ifindex;
@@ -7229,7 +7227,7 @@ int bp_proc_create(void)
 }
 
 static int procfs_add(char *proc_name, const struct file_operations *fops,
-		      bpctl_dev_t *dev)
+		      struct bpctl_dev *dev)
 {
 	struct bypass_pfs_sd *pfs = &dev->bypass_pfs_set;
 	if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev))
@@ -7264,7 +7262,7 @@ static const struct file_operations name##_ops = {		\
 
 static int show_bypass_info(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 
 	seq_printf(m, "Name\t\t\t%s\n", dev->name);
 	seq_printf(m, "Firmware version\t0x%x\n", dev->bp_fw_ver);
@@ -7274,8 +7272,8 @@ RO_FOPS(bypass_info)
 
 static int show_bypass_slave(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
-	bpctl_dev_t *slave = get_status_port_fn(dev);
+	struct bpctl_dev *dev = m->private;
+	struct bpctl_dev *slave = get_status_port_fn(dev);
 	if (!slave)
 		slave = dev;
 	if (!slave)
@@ -7288,7 +7286,7 @@ RO_FOPS(bypass_slave)
 
 static int show_bypass_caps(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bypass_caps_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "-1\n");
@@ -7300,7 +7298,7 @@ RO_FOPS(bypass_caps)
 
 static int show_wd_set_caps(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_wd_set_caps_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "-1\n");
@@ -7346,7 +7344,7 @@ static ssize_t bypass_write(struct file *file, const char __user *buffer,
 }
 static int show_bypass(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bypass_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7370,7 +7368,7 @@ static ssize_t tap_write(struct file *file, const char __user *buffer,
 }
 static int show_tap(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_tap_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7394,7 +7392,7 @@ static ssize_t disc_write(struct file *file, const char __user *buffer,
 }
 static int show_disc(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_disc_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7408,7 +7406,7 @@ RW_FOPS(disc)
 
 static int show_bypass_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bypass_change_fn(dev);
 	if (ret == 1)
 		seq_puts(m, "on\n");
@@ -7422,7 +7420,7 @@ RO_FOPS(bypass_change)
 
 static int show_tap_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_tap_change_fn(dev);
 	if (ret == 1)
 		seq_puts(m, "on\n");
@@ -7436,7 +7434,7 @@ RO_FOPS(tap_change)
 
 static int show_disc_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_disc_change_fn(dev);
 	if (ret == 1)
 		seq_puts(m, "on\n");
@@ -7451,7 +7449,7 @@ RO_FOPS(disc_change)
 static ssize_t bypass_wd_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	struct bpctl_dev *dev = PDE_DATA(file_inode(file));
 	int timeout;
 	int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
 	if (ret)
@@ -7461,7 +7459,7 @@ static ssize_t bypass_wd_write(struct file *file, const char __user *buffer,
 }
 static int show_bypass_wd(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = 0, timeout = 0;
 
 	ret = get_bypass_wd_fn(dev, &timeout);
@@ -7479,7 +7477,7 @@ RW_FOPS(bypass_wd)
 
 static int show_wd_expire_time(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = 0, timeout = 0;
 	ret = get_wd_expire_time_fn(dev, &timeout);
 	if (ret == BP_NOT_CAP)
@@ -7497,7 +7495,7 @@ RO_FOPS(wd_expire_time)
 static ssize_t tpl_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	struct bpctl_dev *dev = PDE_DATA(file_inode(file));
 	int tpl_param = user_on_off(buffer, count);
 	if (tpl_param < 0)
 		return -1;
@@ -7507,7 +7505,7 @@ static ssize_t tpl_write(struct file *file, const char __user *buffer,
 }
 static int show_tpl(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_tpl_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7523,7 +7521,7 @@ RW_FOPS(tpl)
 static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	struct bpctl_dev *dev = PDE_DATA(file_inode(file));
 	int tpl_param = user_on_off(buffer, count);
 	if (tpl_param < 0)
 		return -1;
@@ -7533,7 +7531,7 @@ static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer,
 }
 static int show_wait_at_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bp_wait_at_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7548,7 +7546,7 @@ RW_FOPS(wait_at_pwup)
 static ssize_t hw_reset_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	struct bpctl_dev *dev = PDE_DATA(file_inode(file));
 	int tpl_param = user_on_off(buffer, count);
 	if (tpl_param < 0)
 		return -1;
@@ -7558,7 +7556,7 @@ static ssize_t hw_reset_write(struct file *file, const char __user *buffer,
 }
 static int show_hw_reset(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bp_hw_reset_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7574,7 +7572,7 @@ RW_FOPS(hw_reset)
 
 static int show_reset_bypass_wd(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = reset_bypass_wd_timer_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7598,7 +7596,7 @@ static ssize_t dis_bypass_write(struct file *file, const char __user *buffer,
 }
 static int show_dis_bypass(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_dis_bypass_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7622,7 +7620,7 @@ static ssize_t dis_tap_write(struct file *file, const char __user *buffer,
 }
 static int show_dis_tap(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_dis_tap_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7646,7 +7644,7 @@ static ssize_t dis_disc_write(struct file *file, const char __user *buffer,
 }
 static int show_dis_disc(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_dis_disc_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7670,7 +7668,7 @@ static ssize_t bypass_pwup_write(struct file *file, const char __user *buffer,
 }
 static int show_bypass_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bypass_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7694,7 +7692,7 @@ static ssize_t bypass_pwoff_write(struct file *file, const char __user *buffer,
 }
 static int show_bypass_pwoff(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_bypass_pwoff_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7718,7 +7716,7 @@ static ssize_t tap_pwup_write(struct file *file, const char __user *buffer,
 }
 static int show_tap_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_tap_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7742,7 +7740,7 @@ static ssize_t disc_pwup_write(struct file *file, const char __user *buffer,
 }
 static int show_disc_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_disc_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7766,7 +7764,7 @@ static ssize_t std_nic_write(struct file *file, const char __user *buffer,
 }
 static int show_std_nic(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_std_nic_fn(dev);
 	if (ret == BP_NOT_CAP)
 		seq_puts(m, "fail\n");
@@ -7808,7 +7806,7 @@ static ssize_t wd_exp_mode_write(struct file *file, const char __user *buffer,
 }
 static int show_wd_exp_mode(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_wd_exp_mode_fn(dev);
 	if (ret == 1)
 		seq_puts(m, "tap\n");
@@ -7834,7 +7832,7 @@ static ssize_t wd_autoreset_write(struct file *file, const char __user *buffer,
 }
 static int show_wd_autoreset(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *dev = m->private;
+	struct bpctl_dev *dev = m->private;
 	int ret = get_wd_autoreset_fn(dev);
 	if (ret >= 0)
 		seq_printf(m, "%d\n", ret);
@@ -7844,7 +7842,7 @@ static int show_wd_autoreset(struct seq_file *m, void *v)
 }
 RW_FOPS(wd_autoreset)
 
-int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
+int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block)
 {
 	struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set);
 	static struct proc_dir_entry *procfs_dir;
@@ -7914,7 +7912,7 @@ int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
 	return ret;
 }
 
-int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block)
+int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block)
 {
 
 	struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
index 3e913b8..1ecca9d 100644
--- a/drivers/staging/usbip/userspace/src/usbipd.c
+++ b/drivers/staging/usbip/userspace/src/usbipd.c
@@ -53,18 +53,18 @@
 static const char usbip_version_string[] = PACKAGE_STRING;
 
 static const char usbipd_help_string[] =
-	"usage: usbipd [options]			\n"
-	"	-D, --daemon				\n"
-	"		Run as a daemon process.	\n"
-	"						\n"
-	"	-d, --debug				\n"
-	"		Print debugging information.	\n"
-	"						\n"
-	"	-h, --help				\n"
-	"		Print this help.		\n"
-	"						\n"
-	"	-v, --version				\n"
-	"		Show version.			\n";
+	"usage: usbipd [options]\n"
+	"	-D, --daemon\n"
+	"		Run as a daemon process.\n"
+	"\n"
+	"	-d, --debug\n"
+	"		Print debugging information.\n"
+	"\n"
+	"	-h, --help\n"
+	"		Print this help.\n"
+	"\n"
+	"	-v, --version\n"
+	"		Show version.\n";
 
 static void usbipd_help(void)
 {
@@ -286,13 +286,13 @@ static int do_accept(int listenfd)
 
 	memset(&ss, 0, sizeof(ss));
 
-	connfd = accept(listenfd, (struct sockaddr *) &ss, &len);
+	connfd = accept(listenfd, (struct sockaddr *)&ss, &len);
 	if (connfd < 0) {
 		err("failed to accept connection");
 		return -1;
 	}
 
-	rc = getnameinfo((struct sockaddr *) &ss, len, host, sizeof(host),
+	rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host),
 			 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
 	if (rc)
 		err("getnameinfo: %s", gai_strerror(rc));
@@ -328,56 +328,69 @@ int process_request(int listenfd)
 	return 0;
 }
 
-static void log_addrinfo(struct addrinfo *ai)
+static void addrinfo_to_text(struct addrinfo *ai, char buf[],
+			     const size_t buf_size)
 {
 	char hbuf[NI_MAXHOST];
 	char sbuf[NI_MAXSERV];
 	int rc;
 
+	buf[0] = '\0';
+
 	rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
 			 sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
 	if (rc)
 		err("getnameinfo: %s", gai_strerror(rc));
 
-	info("listening on %s:%s", hbuf, sbuf);
+	snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);
 }
 
 static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
 {
 	struct addrinfo *ai;
 	int ret, nsockfd = 0;
+	const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;
+	char ai_buf[ai_buf_size];
 
 	for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) {
-		sockfdlist[nsockfd] = socket(ai->ai_family, ai->ai_socktype,
-					     ai->ai_protocol);
-		if (sockfdlist[nsockfd] < 0)
+		int sock;
+		addrinfo_to_text(ai, ai_buf, ai_buf_size);
+		dbg("opening %s", ai_buf);
+		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+		if (sock < 0) {
+			err("socket: %s: %d (%s)",
+			    ai_buf, errno, strerror(errno));
 			continue;
+		}
 
-		usbip_net_set_reuseaddr(sockfdlist[nsockfd]);
-		usbip_net_set_nodelay(sockfdlist[nsockfd]);
+		usbip_net_set_reuseaddr(sock);
+		usbip_net_set_nodelay(sock);
 
-		if (sockfdlist[nsockfd] >= FD_SETSIZE) {
-			close(sockfdlist[nsockfd]);
-			sockfdlist[nsockfd] = -1;
+		if (sock >= FD_SETSIZE) {
+			err("FD_SETSIZE: %s: sock=%d, max=%d",
+			    ai_buf, sock, FD_SETSIZE);
+			close(sock);
 			continue;
 		}
 
-		ret = bind(sockfdlist[nsockfd], ai->ai_addr, ai->ai_addrlen);
+		ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
 		if (ret < 0) {
-			close(sockfdlist[nsockfd]);
-			sockfdlist[nsockfd] = -1;
+			err("bind: %s: %d (%s)",
+			    ai_buf, errno, strerror(errno));
+			close(sock);
 			continue;
 		}
 
-		ret = listen(sockfdlist[nsockfd], SOMAXCONN);
+		ret = listen(sock, SOMAXCONN);
 		if (ret < 0) {
-			close(sockfdlist[nsockfd]);
-			sockfdlist[nsockfd] = -1;
+			err("listen: %s: %d (%s)",
+			    ai_buf, errno, strerror(errno));
+			close(sock);
 			continue;
 		}
 
-		log_addrinfo(ai);
-		nsockfd++;
+		info("listening on %s", ai_buf);
+		sockfdlist[nsockfd++] = sock;
 	}
 
 	if (nsockfd == 0)
@@ -496,8 +509,9 @@ static int do_standalone_mode(int daemonize)
 					process_request(sockfdlist[i]);
 				}
 			}
-		} else
+		} else {
 			dbg("heartbeat timeout on ppoll()");
+		}
 	}
 
 	info("shutting down " PROGNAME);
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 08b250f..7f36a71 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -3370,8 +3370,8 @@ viawget_resume(struct pci_dev *pcid)
 	PSMgmtObject  pMgmt = pDevice->pMgmt;
 	int power_status;   // to silence the compiler
 
-	power_status = pci_set_power_state(pcid, 0);
-	power_status = pci_enable_wake(pcid, 0, 0);
+	power_status = pci_set_power_state(pcid, PCI_D0);
+	power_status = pci_enable_wake(pcid, PCI_D0, 0);
 	pci_restore_state(pcid);
 	if (netif_running(pDevice->dev)) {
 		spin_lock_irq(&pDevice->lock);
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index 33fa767..a14a6a0 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -680,7 +680,6 @@ BBuGetFrameTime(
     unsigned int uRate = 0;
 
     if (uRateIdx > RATE_54M) {
-        ASSERT(0);
         return 0;
     }
 
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index f07ba24..4986910 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -591,12 +591,6 @@ struct vnt_private {
 	u8 abyBSSID[ETH_ALEN];
 	u8 abyDesireBSSID[ETH_ALEN];
 
-	u16 wCTSDuration;       /* update while speed change */
-	u16 wACKDuration;
-	u16 wRTSTransmitLen;
-	u8 byRTSServiceField;
-	u8 byRTSSignalField;
-
 	u32 dwMaxReceiveLifetime;  /* dot11MaxReceiveLifetime */
 
 	int bCCK;
diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h
index ea66b97..a97f7bb 100644
--- a/drivers/staging/vt6656/device_cfg.h
+++ b/drivers/staging/vt6656/device_cfg.h
@@ -82,18 +82,4 @@ typedef enum  _chip_type {
     VT3184 = 1
 } CHIP_TYPE, *PCHIP_TYPE;
 
-#ifdef VIAWET_DEBUG
-#define ASSERT(x) { \
-    if (!(x)) { \
-	printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x, \
-        __FUNCTION__, __LINE__);\
-	*(int *) 0 = 0;		\
-    } \
-}
-#define DBG_PORT80(value)                   outb(value, 0x80)
-#else
-#define ASSERT(x)
-#define DBG_PORT80(value)
-#endif
-
 #endif
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index 7ec166a..4bc362f 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -314,7 +314,6 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
          (BytesToIndicate < (*pwPLCP_Length)) ) {
 
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length);
-        ASSERT(0);
         return false;
     }
     for ( ii=RATE_1M;ii<MAX_RATE;ii++) {
@@ -1347,7 +1346,6 @@ void RXvWorkItem(struct vnt_private *pDevice)
             (pDevice->NumRecvFreeList != 0) ) {
         pRCB = pDevice->FirstRecvFreeList;
         pDevice->NumRecvFreeList--;
-        ASSERT(pRCB);// cannot be NULL
         DequeueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList);
         ntStatus = PIPEnsBulkInUsbRead(pDevice, pRCB);
     }
@@ -1362,9 +1360,6 @@ void RXvFreeRCB(PRCB pRCB, int bReAllocSkb)
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
 
-    ASSERT(!pRCB->Ref);     // should be 0
-    ASSERT(pRCB->pDevice);  // shouldn't be NULL
-
 	if (bReAllocSkb == false) {
 		kfree_skb(pRCB->skb);
 		bReAllocSkb = true;
@@ -1411,7 +1406,6 @@ void RXvMngWorkItem(struct vnt_private *pDevice)
         if(!pRCB){
             break;
         }
-        ASSERT(pRCB);// cannot be NULL
         pRxPacket = &(pRCB->sMngPacket);
 	vMgrRxManagePacket(pDevice, &pDevice->vnt_mgmt, pRxPacket);
         pRCB->Ref--;
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 3a3fdc5..3bc5834 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -267,7 +267,6 @@ device_set_options(struct vnt_private *pDevice) {
     pDevice->bUpdateBBVGA = true;
     pDevice->byFOETuning = 0;
     pDevice->byAutoPwrTunning = 0;
-    pDevice->wCTSDuration = 0;
     pDevice->byPreambleType = 0;
     pDevice->bExistSWNetAddr = false;
     /* pDevice->bDiversityRegCtlON = true; */
@@ -925,7 +924,6 @@ int device_alloc_frag_buf(struct vnt_private *pDevice,
     pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
     if (pDeF->skb == NULL)
         return false;
-    ASSERT(pDeF->skb);
     pDeF->skb->dev = pDevice->dev;
 
     return true;
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 9bf2f8d..be0c9ce 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -538,7 +538,6 @@ static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType,
         break;
     }
 
-	ASSERT(false);
 	return 0;
 }
 
@@ -1006,15 +1005,12 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
             );
             pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             pBuf->wDuration_ba = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wDuration_ba += pDevice->wCTSDuration;
             pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
             //Get CTSDuration_ba_f0
             pBuf->wCTSDuration_ba_f0 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration;
             pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0);
             //Get CTSDuration_ba_f1
             pBuf->wCTSDuration_ba_f1 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration;
             pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1);
             //Get CTS Frame body
             pBuf->Data.wDurationID = pBuf->wDuration_ba;
@@ -1032,7 +1028,6 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
             pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             //Get CTSDuration_ba
             pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wDuration_ba += pDevice->wCTSDuration;
             pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
 
             //Get CTS Frame body
@@ -1475,8 +1470,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
         memcpy((pbyPayloadHead + cb802_1_H_len), ((u8 *)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN);
     }
 
-    ASSERT(uLength == cbNdisBodySize);
-
     if ((bNeedEncryption == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
 
         ///////////////////////////////////////////////////////////////////
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 098be60..9b9122d 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -635,7 +635,6 @@ static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
     // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
     //
     pContext = (PUSB_SEND_CONTEXT) urb->context;
-    ASSERT( NULL != pContext );
 
     pDevice = pContext->pDevice;
     ContextType = pContext->Type;
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index 6d1ff5e..b6cbd13 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -751,7 +751,6 @@ static void s_vMgrRxAssocResponse(struct vnt_private *pDevice,
 	    || (sFrame.pwStatus == NULL)
 	    || (sFrame.pwAid == NULL)
 	    || (sFrame.pSuppRates == NULL)) {
-		DBG_PORT80(0xCC);
 		return;
         }
 
@@ -3750,7 +3749,6 @@ static void s_vMgrRxProbeResponse(struct vnt_private *pDevice,
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp:Fail addr:[%p]\n",
 		pRxPacket->p80211Header);
-	DBG_PORT80(0xCC);
 	return;
     }
 
diff --git a/drivers/staging/winbond/wb35reg.c b/drivers/staging/winbond/wb35reg.c
index 9be1b3b..35d3beb 100644
--- a/drivers/staging/winbond/wb35reg.c
+++ b/drivers/staging/winbond/wb35reg.c
@@ -14,7 +14,8 @@ extern void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency);
  * Flag : AUTO_INCREMENT - RegisterNo will auto increment 4
  *	  NO_INCREMENT - Function will write data into the same register
  */
-unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo, u32 *pRegisterData, u8 NumberOfData, u8 Flag)
+unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo,
+				 u32 *pRegisterData, u8 NumberOfData, u8 Flag)
 {
 	struct wb35_reg		*reg = &pHwData->reg;
 	struct urb		*urb = NULL;
@@ -72,7 +73,7 @@ unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo, u32 *p
 	return true;
 }
 
-void Wb35Reg_Update(struct hw_data *pHwData,  u16 RegisterNo,  u32 RegisterValue)
+void Wb35Reg_Update(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue)
 {
 	struct wb35_reg *reg = &pHwData->reg;
 	switch (RegisterNo) {
@@ -118,7 +119,8 @@ void Wb35Reg_Update(struct hw_data *pHwData,  u16 RegisterNo,  u32 RegisterValue
  * true  : read command process successfully
  * false : register not support
  */
-unsigned char Wb35Reg_WriteSync(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue)
+unsigned char Wb35Reg_WriteSync(struct hw_data *pHwData, u16 RegisterNo,
+				u32 RegisterValue)
 {
 	struct wb35_reg *reg = &pHwData->reg;
 	int ret = -1;
@@ -139,9 +141,10 @@ unsigned char Wb35Reg_WriteSync(struct hw_data *pHwData, u16 RegisterNo, u32 Reg
 	/* Sync IoCallDriver */
 	reg->EP0vm_state = VM_RUNNING;
 	ret = usb_control_msg(pHwData->udev,
-			       usb_sndctrlpipe(pHwData->udev, 0),
-			       0x03, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			       0x0, RegisterNo, &RegisterValue, 4, HZ * 100);
+			      usb_sndctrlpipe(pHwData->udev, 0),
+			      0x03,
+			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+			      0x0, RegisterNo, &RegisterValue, 4, HZ * 100);
 	reg->EP0vm_state = VM_STOP;
 	reg->SyncIoPause = 0;
 
@@ -159,7 +162,8 @@ unsigned char Wb35Reg_WriteSync(struct hw_data *pHwData, u16 RegisterNo, u32 Reg
  * true  : read command process successfully
  * false : register not support
  */
-unsigned char Wb35Reg_Write(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue)
+unsigned char Wb35Reg_Write(struct hw_data *pHwData, u16 RegisterNo,
+			    u32 RegisterValue)
 {
 	struct wb35_reg		*reg = &pHwData->reg;
 	struct usb_ctrlrequest	*dr;
@@ -286,7 +290,8 @@ unsigned char Wb35Reg_WriteWithCallbackValue(struct hw_data *pHwData,
  * pRegisterValue : It must be a resident buffer due to
  *		    asynchronous read register.
  */
-unsigned char Wb35Reg_ReadSync(struct hw_data *pHwData, u16 RegisterNo, u32 *pRegisterValue)
+unsigned char Wb35Reg_ReadSync(struct hw_data *pHwData, u16 RegisterNo,
+			       u32 *pRegisterValue)
 {
 	struct wb35_reg *reg = &pHwData->reg;
 	u32		*pltmp = pRegisterValue;
@@ -305,9 +310,10 @@ unsigned char Wb35Reg_ReadSync(struct hw_data *pHwData, u16 RegisterNo, u32 *pRe
 
 	reg->EP0vm_state = VM_RUNNING;
 	ret = usb_control_msg(pHwData->udev,
-			       usb_rcvctrlpipe(pHwData->udev, 0),
-			       0x01, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			       0x0, RegisterNo, pltmp, 4, HZ * 100);
+			      usb_rcvctrlpipe(pHwData->udev, 0),
+			      0x01,
+			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+			      0x0, RegisterNo, pltmp, 4, HZ * 100);
 
 	*pRegisterValue = cpu_to_le32(*pltmp);
 
@@ -332,7 +338,8 @@ unsigned char Wb35Reg_ReadSync(struct hw_data *pHwData, u16 RegisterNo, u32 *pRe
  * pRegisterValue : It must be a resident buffer due to
  *		    asynchronous read register.
  */
-unsigned char Wb35Reg_Read(struct hw_data *pHwData, u16 RegisterNo, u32 *pRegisterValue)
+unsigned char Wb35Reg_Read(struct hw_data *pHwData, u16 RegisterNo,
+			   u32 *pRegisterValue)
 {
 	struct wb35_reg		*reg = &pHwData->reg;
 	struct usb_ctrlrequest	*dr;
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 801ac40..3b3e17d 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -60,7 +60,7 @@ static inline void dumpVGAReg(void)
 
 static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned char modeno, unsigned char rateindex)
+		unsigned char modeno)
 {
 	unsigned short ModeNo = modeno;
 	unsigned short ModeIdIndex = 0, ClockIndex = 0;
@@ -68,7 +68,7 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 	int Clock;
 	InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
 
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
+	XGI_SearchModeID(ModeNo, &ModeIdIndex);
 
 	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 			ModeIdIndex, XGI_Pr);
@@ -82,7 +82,7 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 
 static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned char modeno, unsigned char rateindex,
+		unsigned char modeno,
 		u32 *left_margin, u32 *right_margin, u32 *upper_margin,
 		u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
 		u32 *vmode)
@@ -96,7 +96,7 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 	unsigned char sr_data, cr_data, cr_data2;
 	int B, C, D, F, temp, j;
 	InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
-	if (!XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr))
+	if (!XGI_SearchModeID(ModeNo, &ModeIdIndex))
 		return 0;
 	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 			ModeIdIndex, XGI_Pr);
@@ -1980,12 +1980,10 @@ static int xgifb_probe(struct pci_dev *pdev,
 	fb_info->var.pixclock = (u32) (1000000000 /
 			XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info,
 				hw_info,
-				XGIbios_mode[xgifb_info->mode_idx].mode_no,
-				xgifb_info->rate_idx));
+				XGIbios_mode[xgifb_info->mode_idx].mode_no));
 
 	if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info,
 		XGIbios_mode[xgifb_info->mode_idx].mode_no,
-		xgifb_info->rate_idx,
 		&fb_info->var.left_margin,
 		&fb_info->var.right_margin,
 		&fb_info->var.upper_margin,
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 5f1c41e..2154172 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -102,10 +102,8 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
 	xgifb_reg_set(P3c4, 0x1B, 0x00);
 }
 
-static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGINew_SetMemoryClock(struct vb_device_info *pVBInfo)
 {
-
 	xgifb_reg_set(pVBInfo->P3c4,
 		      0x28,
 		      pVBInfo->MCLKData[pVBInfo->ram_type].SR28);
@@ -133,7 +131,7 @@ static void XGINew_DDRII_Bootup_XG27(
 {
 	unsigned long P3d4 = P3c4 + 0x10;
 	pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-	XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
+	XGINew_SetMemoryClock(pVBInfo);
 
 	/* Set Double Frequency */
 	xgifb_reg_set(P3d4, 0x97, pVBInfo->XGINew_CR97); /* CR97 */
@@ -206,7 +204,7 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
 	unsigned long P3d4 = P3c4 + 0x10;
 
 	pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-	XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
+	XGINew_SetMemoryClock(pVBInfo);
 
 	xgifb_reg_set(P3d4, 0x97, 0x11); /* CR97 */
 
@@ -280,7 +278,7 @@ static void XGINew_DDR1x_DefaultRegister(
 	unsigned long P3d4 = Port, P3c4 = Port - 0x10;
 
 	if (HwDeviceExtension->jChipType >= XG20) {
-		XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
+		XGINew_SetMemoryClock(pVBInfo);
 		xgifb_reg_set(P3d4,
 			      0x82,
 			      pVBInfo->CR40[11][pVBInfo->ram_type]); /* CR82 */
@@ -296,7 +294,7 @@ static void XGINew_DDR1x_DefaultRegister(
 
 		XGINew_DDR1x_MRS_XG20(P3c4, pVBInfo);
 	} else {
-		XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
+		XGINew_SetMemoryClock(pVBInfo);
 
 		switch (HwDeviceExtension->jChipType) {
 		case XG42:
@@ -876,8 +874,7 @@ done:
 	return rom_copy;
 }
 
-static bool xgifb_read_vbios(struct pci_dev *pdev,
-			      struct vb_device_info *pVBInfo)
+static bool xgifb_read_vbios(struct pci_dev *pdev)
 {
 	struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
 	u8 *vbios;
@@ -948,8 +945,7 @@ error:
 	return false;
 }
 
-static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGINew_ChkSenseStatus(struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx = 0, temp, tempcx, CR3CData;
 
@@ -991,8 +987,7 @@ static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
 	xgifb_reg_set(pVBInfo->P3d4, 0x3e, ((tempbx & 0xFF00) >> 8));
 }
 
-static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGINew_SetModeScratch(struct vb_device_info *pVBInfo)
 {
 	unsigned short temp, tempcl = 0, tempch = 0, CR31Data, CR38Data;
 
@@ -1102,7 +1097,7 @@ static void XGINew_GetXG21Sense(struct pci_dev *pdev,
 	struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
 	unsigned char Temp;
 
-	if (xgifb_read_vbios(pdev, pVBInfo)) { /* For XG21 LVDS */
+	if (xgifb_read_vbios(pdev)) { /* For XG21 LVDS */
 		xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
 		/* LVDS on chip */
 		xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0);
@@ -1126,8 +1121,7 @@ static void XGINew_GetXG21Sense(struct pci_dev *pdev,
 	}
 }
 
-static void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGINew_GetXG27Sense(struct vb_device_info *pVBInfo)
 {
 	unsigned char Temp, bCR4A;
 
@@ -1222,7 +1216,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 		XGINew_GetXG21Sense(pdev, pVBInfo);
 
 	if (HwDeviceExtension->jChipType == XG27)
-		XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo);
+		XGINew_GetXG27Sense(pVBInfo);
 
 	/* Reset Extended register */
 
@@ -1294,7 +1288,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 
 	if (HwDeviceExtension->jChipType < XG20) {
 		/* Set VB */
-		XGI_UnLockCRT2(HwDeviceExtension, pVBInfo);
+		XGI_UnLockCRT2(pVBInfo);
 		/* disable VideoCapture */
 		xgifb_reg_and_or(pVBInfo->Part0Port, 0x3F, 0xEF, 0x00);
 		xgifb_reg_set(pVBInfo->Part1Port, 0x00, 0x00);
@@ -1334,7 +1328,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 			xgifb_reg_set(pVBInfo->Part4Port,
 				      0x10, XGI330_CRT2Data_4_10);
 			xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F);
-			XGI_LockCRT2(HwDeviceExtension, pVBInfo);
+			XGI_LockCRT2(pVBInfo);
 		}
 	} /* != XG20 */
 
@@ -1370,8 +1364,8 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 	xgifb_reg_set(pVBInfo->P3c4, 0x22, 0xfa);
 	xgifb_reg_set(pVBInfo->P3c4, 0x21, 0xa3);
 
-	XGINew_ChkSenseStatus(HwDeviceExtension, pVBInfo);
-	XGINew_SetModeScratch(HwDeviceExtension, pVBInfo);
+	XGINew_ChkSenseStatus(pVBInfo);
+	XGINew_SetModeScratch(pVBInfo);
 
 	xgifb_reg_set(pVBInfo->P3d4, 0x8c, 0x87);
 
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index fcefe5b..46dea3f 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -63,9 +63,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 
 }
 
-static void XGI_SetSeqRegs(unsigned short ModeNo,
-			   unsigned short ModeIdIndex,
-			   struct vb_device_info *pVBInfo)
+static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo)
 {
 	unsigned char SRdata, i;
 
@@ -79,8 +77,7 @@ static void XGI_SetSeqRegs(unsigned short ModeNo,
 	}
 }
 
-static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
-			    struct vb_device_info *pVBInfo)
+static void XGI_SetCRTCRegs(struct vb_device_info *pVBInfo)
 {
 	unsigned char CRTCdata;
 	unsigned short i;
@@ -96,8 +93,7 @@ static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	}
 }
 
-static void XGI_SetATTRegs(unsigned short ModeNo,
-			   unsigned short ModeIdIndex,
+static void XGI_SetATTRegs(unsigned short ModeIdIndex,
 			   struct vb_device_info *pVBInfo)
 {
 	unsigned char ARdata;
@@ -171,8 +167,7 @@ static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
 	return 0;
 }
 
-static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
-		unsigned short ModeIdIndex,
+static unsigned char XGI_AjustCRT2Rate(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex, unsigned short *i,
 		struct vb_device_info *pVBInfo)
 {
@@ -322,7 +317,6 @@ static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
 }
 
 static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
-				unsigned short ModeNo,
 				struct vb_device_info *pVBInfo)
 {
 	unsigned char data;
@@ -365,7 +359,7 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
 	xgifb_reg_set(pVBInfo->P3d4, 0x09, data);
 }
 
-static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetCRT1CRTC(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo,
 		struct xgi_hw_device_info *HwDeviceExtension)
@@ -391,7 +385,7 @@ static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 
 	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
 
-	XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
+	XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo);
 
 	if (pVBInfo->ModeType > 0x03)
 		xgifb_reg_set(pVBInfo->P3d4, 0x14, 0x4F);
@@ -403,8 +397,7 @@ static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 /* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
 /* Description : Set LCD timing */
 /* --------------------------------------------------------------------- */
-static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
+static void XGI_SetXG21CRTC(unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char index, Tempax, Tempbx, Tempcx, Tempdx;
@@ -500,9 +493,7 @@ static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax);
 }
 
-static void XGI_SetXG27CRTC(unsigned short ModeNo,
-			    unsigned short ModeIdIndex,
-			    unsigned short RefreshRateTableIndex,
+static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex,
 			    struct vb_device_info *pVBInfo)
 {
 	unsigned short index, Tempax, Tempbx, Tempcx;
@@ -605,8 +596,7 @@ static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
 
 static void xgifb_set_lcd(int chip_id,
 			  struct vb_device_info *pVBInfo,
-			  unsigned short RefreshRateTableIndex,
-			  unsigned short ModeNo)
+			  unsigned short RefreshRateTableIndex)
 {
 	unsigned short temp;
 
@@ -687,8 +677,7 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
 	}
 }
 
-static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetCRT1DE(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
@@ -834,10 +823,8 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo,
 	xgifb_reg_set(pVBInfo->P3c4, 0x10, ah);
 }
 
-static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
-		unsigned short ModeIdIndex,
+static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short VCLKIndex, modeflag;
@@ -886,8 +873,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
 	return VCLKIndex;
 }
 
-static void XGI_SetCRT1VCLK(unsigned short ModeNo,
-			    unsigned short ModeIdIndex,
+static void XGI_SetCRT1VCLK(unsigned short ModeIdIndex,
 			    struct xgi_hw_device_info *HwDeviceExtension,
 			    unsigned short RefreshRateTableIndex,
 			    struct vb_device_info *pVBInfo)
@@ -899,9 +885,8 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo,
 	    (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
 				VB_SIS302LV | VB_XGI301C)) &&
 	    (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) {
-		vclkindex = XGI_GetVCLK2Ptr(ModeNo, ModeIdIndex,
-				RefreshRateTableIndex, HwDeviceExtension,
-				pVBInfo);
+		vclkindex = XGI_GetVCLK2Ptr(ModeIdIndex, RefreshRateTableIndex,
+					    pVBInfo);
 		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
 		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
 		data = XGI_VBVCLKData[vclkindex].Part4_A;
@@ -948,9 +933,8 @@ static void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo)
 
 }
 
-static void XGI_SetCRT1FIFO(unsigned short ModeNo,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetCRT1FIFO(struct xgi_hw_device_info *HwDeviceExtension,
+			    struct vb_device_info *pVBInfo)
 {
 	unsigned short data;
 
@@ -971,7 +955,7 @@ static void XGI_SetCRT1FIFO(unsigned short ModeNo,
 }
 
 static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo, unsigned short RefreshRateTableIndex,
+		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short data, data2 = 0;
@@ -1010,7 +994,7 @@ static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
 }
 
 static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
@@ -1063,8 +1047,7 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	data = data ^ 0xA0;
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x21, 0x1F, data);
 
-	XGI_SetVCLKState(HwDeviceExtension, ModeNo, RefreshRateTableIndex,
-			pVBInfo);
+	XGI_SetVCLKState(HwDeviceExtension, RefreshRateTableIndex, pVBInfo);
 
 	data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
 
@@ -1122,8 +1105,7 @@ static void XGI_WriteDAC(unsigned short dl,
 	outb((unsigned short) bl, pVBInfo->P3c9);
 }
 
-static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_LoadDAC(struct vb_device_info *pVBInfo)
 {
 	unsigned short data, data2, i, k, m, n, o, si, di, bx, dl, al, ah, dh;
 	const unsigned short *table = XGINew_VGA_DAC;
@@ -1188,8 +1170,7 @@ static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_GetLVDSResInfo(unsigned short ModeNo,
-			       unsigned short ModeIdIndex,
+static void XGI_GetLVDSResInfo(unsigned short ModeIdIndex,
 			       struct vb_device_info *pVBInfo)
 {
 	unsigned short resindex, xres, yres, modeflag;
@@ -1219,9 +1200,7 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
 }
 
 static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table,
-		unsigned short ModeNo,
 		unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short i, tempdx, tempbx, modeflag;
@@ -1259,8 +1238,7 @@ static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table,
 	return table[i].DATAPTR;
 }
 
-static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo,
-		unsigned short ModeIdIndex,
+static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
@@ -1289,17 +1267,15 @@ static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo,
 	return &XGI_TVDataTable[i].DATAPTR[tempal];
 }
 
-static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_GetLVDSData(unsigned short ModeIdIndex,
+			    struct vb_device_info *pVBInfo)
 {
 	struct SiS_LVDSData const *LCDPtr;
 
 	if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
 		return;
 
-	LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeNo, ModeIdIndex,
-			       RefreshRateTableIndex, pVBInfo);
+	LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeIdIndex, pVBInfo);
 	pVBInfo->VGAHT	= LCDPtr->VGAHT;
 	pVBInfo->VGAVT	= LCDPtr->VGAVT;
 	pVBInfo->HT	= LCDPtr->LCDHT;
@@ -1325,18 +1301,17 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_ModCRT1Regs(unsigned short ModeIdIndex,
+			    struct xgi_hw_device_info *HwDeviceExtension,
+			    struct vb_device_info *pVBInfo)
 {
 	unsigned short i;
 	struct XGI_LVDSCRT1HDataStruct const *LCDPtr = NULL;
 	struct XGI_LVDSCRT1VDataStruct const *LCDPtr1 = NULL;
 
 	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeNo, ModeIdIndex,
-				       RefreshRateTableIndex, pVBInfo);
+		LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeIdIndex,
+				       pVBInfo);
 
 		for (i = 0; i < 8; i++)
 			pVBInfo->TimingH.data[i] = LCDPtr[0].Reg[i];
@@ -1345,14 +1320,13 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
 	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
 
 	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeNo,
-					ModeIdIndex, RefreshRateTableIndex,
+		LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeIdIndex,
 					pVBInfo);
 		for (i = 0; i < 7; i++)
 			pVBInfo->TimingV.data[i] = LCDPtr1[0].Reg[i];
 	}
 
-	XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
+	XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo);
 }
 
 static unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
@@ -1425,17 +1399,15 @@ static void XGI_GetLCDSync(unsigned short *HSyncWidth,
 	*VSyncWidth = pVBInfo->LCDCapList[Index].LCD_VSyncWidth;
 }
 
-static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
+			    struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
 	unsigned long temp, temp1, temp2, temp3, push3;
 	struct XGI330_LCDDataDesStruct2 const *LCDPtr1 = NULL;
 
 	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeNo, ModeIdIndex,
-					RefreshRateTableIndex, pVBInfo);
+	LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeIdIndex, pVBInfo);
 
 	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
 	push1 = tempbx;
@@ -1686,8 +1658,7 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
 }
 
 static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
 {
 
 	unsigned short index, modeflag;
@@ -1769,15 +1740,14 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
 	}
 }
 
-static void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char di_0, di_1, tempal;
 	int i;
 
-	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex,
-			pVBInfo);
+	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
 	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
 	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
 
@@ -1795,8 +1765,7 @@ static void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_UpdateModeInfo(struct vb_device_info *pVBInfo)
 {
 	unsigned short tempcl, tempch, temp, tempbl, tempax;
 
@@ -1922,8 +1891,7 @@ finish:
 	pVBInfo->VBType = tempbx;
 }
 
-static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_GetVBInfo(unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short tempax, push, tempbx, temp, modeflag;
@@ -2048,7 +2016,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 	pVBInfo->VBInfo = tempbx;
 }
 
-static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_GetTVInfo(unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx = 0, resinfo = 0, modeflag, index1;
@@ -2115,8 +2083,8 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 	pVBInfo->TVInfo = tempbx;
 }
 
-static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
-		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex,
+				    struct vb_device_info *pVBInfo)
 {
 	unsigned short temp, tempax, tempbx, resinfo = 0, LCDIdIndex;
 
@@ -2196,7 +2164,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
 }
 
 unsigned char XGI_SearchModeID(unsigned short ModeNo,
-		unsigned short *ModeIdIndex, struct vb_device_info *pVBInfo)
+			       unsigned short *ModeIdIndex)
 {
 	for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
 		if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
@@ -2435,8 +2403,7 @@ static void XGI_SaveCRT2Info(unsigned short ModeNo,
 	xgifb_reg_and_or(pVBInfo->P3d4, 0x31, temp2, temp1);
 }
 
-static void XGI_GetCRT2ResInfo(unsigned short ModeNo,
-			       unsigned short ModeIdIndex,
+static void XGI_GetCRT2ResInfo(unsigned short ModeIdIndex,
 			       struct vb_device_info *pVBInfo)
 {
 	unsigned short xres, yres, modeflag, resindex;
@@ -2508,8 +2475,7 @@ static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
 	return 0;
 }
 
-static void XGI_GetRAMDAC2DATA(unsigned short ModeNo,
-			       unsigned short ModeIdIndex,
+static void XGI_GetRAMDAC2DATA(unsigned short ModeIdIndex,
 			       unsigned short RefreshRateTableIndex,
 			       struct vb_device_info *pVBInfo)
 {
@@ -2551,7 +2517,7 @@ static void XGI_GetRAMDAC2DATA(unsigned short ModeNo,
 	pVBInfo->VT = tempbx;
 }
 
-static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_GetCRT2Data(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
@@ -2566,14 +2532,13 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
 	pVBInfo->RVBHRS = 50;
 
 	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-		XGI_GetRAMDAC2DATA(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo);
+		XGI_GetRAMDAC2DATA(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
 		return;
 	}
 
 	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeNo, ModeIdIndex,
-				       RefreshRateTableIndex, pVBInfo);
+		LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeIdIndex,
+				       pVBInfo);
 
 		pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
 		pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT;
@@ -2654,7 +2619,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
 	if (pVBInfo->VBInfo & (SetCRT2ToTV)) {
 		struct SiS_TVData const *TVPtr;
 
-		TVPtr = XGI_GetTVPtr(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+		TVPtr = XGI_GetTVPtr(ModeIdIndex, RefreshRateTableIndex,
 				     pVBInfo);
 
 		pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX;
@@ -2722,14 +2687,13 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetCRT2VCLK(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char di_0, di_1, tempal;
 
-	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex,
-			pVBInfo);
+	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
 	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
 	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
 
@@ -2751,8 +2715,7 @@ static void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
 		xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08);
 }
 
-static unsigned short XGI_GetColorDepth(unsigned short ModeNo,
-		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex)
 {
 	unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
 	short index;
@@ -2769,9 +2732,7 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeNo,
 
 static unsigned short XGI_GetOffset(unsigned short ModeNo,
 				    unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+		unsigned short RefreshRateTableIndex)
 {
 	unsigned short temp, colordepth, modeinfo, index, infoflag,
 			ColorDepth[] = { 0x01, 0x02, 0x04 };
@@ -2786,7 +2747,7 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo,
 	if (infoflag & InterlaceMode)
 		temp = temp << 1;
 
-	colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo);
+	colordepth = XGI_GetColorDepth(ModeIdIndex);
 
 	if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
 		temp = ModeNo - 0x7C;
@@ -2801,7 +2762,6 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo,
 static void XGI_SetCRT2Offset(unsigned short ModeNo,
 		unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short offset;
@@ -2810,8 +2770,7 @@ static void XGI_SetCRT2Offset(unsigned short ModeNo,
 	if (pVBInfo->VBInfo & SetInSlaveMode)
 		return;
 
-	offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
+	offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex);
 	temp = (unsigned char) (offset & 0xFF);
 	xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
 	temp = (unsigned char) ((offset & 0xFF00) >> 8);
@@ -2829,14 +2788,12 @@ static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
 }
 
 static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	u8 tempcx;
 
-	XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
+	XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
 	XGI_SetCRT2FIFO(pVBInfo);
 
 	for (tempcx = 4; tempcx < 7; tempcx++)
@@ -2846,8 +2803,7 @@ static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 	xgifb_reg_set(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */
 }
 
-static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_SetGroup1(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
@@ -3002,8 +2958,6 @@ static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
 }
 
 static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
@@ -3294,8 +3248,6 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 }
 
 static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2,
@@ -3724,9 +3676,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short RefreshRateTableIndex,
+static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short pushbx, tempax, tempbx, tempcx, temp, tempah,
@@ -3772,11 +3722,10 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 
 	/* Customized LCDB Does not add */
 	if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
-		LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeNo, ModeIdIndex,
-					   RefreshRateTableIndex, pVBInfo);
+		LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeIdIndex,
+					   pVBInfo);
 	else
-		LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeNo,
-					   ModeIdIndex, RefreshRateTableIndex,
+		LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeIdIndex,
 					   pVBInfo);
 
 	tempah = pVBInfo->LCDResInfo;
@@ -4003,8 +3952,8 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
 		xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10);
 }
 
-static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetGroup3(unsigned short ModeIdIndex,
+			  struct vb_device_info *pVBInfo)
 {
 	unsigned short i;
 	unsigned char const *tempdi;
@@ -4059,9 +4008,8 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetGroup4(unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2;
@@ -4224,7 +4172,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 	/* end 301b */
 
-	XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
 }
 
 static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
@@ -4232,8 +4180,7 @@ static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20);
 }
 
-static void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetGroup5(struct vb_device_info *pVBInfo)
 {
 	if (pVBInfo->ModeType == ModeVGA) {
 		if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
@@ -4243,16 +4190,13 @@ static void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-static void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_DisableGatingCRT(struct vb_device_info *pVBInfo)
 {
-
 	xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
 }
 
 static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+		unsigned short ModeNo, unsigned short ModeIdIndex)
 {
 	unsigned short xres, yres, colordepth, modeflag, resindex;
 
@@ -4281,7 +4225,7 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
 
 	if (xres != xgifb_info->lvds_data.LVDSHDE ||
 	    yres != xgifb_info->lvds_data.LVDSVDE) {
-		colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo);
+		colordepth = XGI_GetColorDepth(ModeIdIndex);
 		if (colordepth > 2)
 			return 0;
 	}
@@ -4290,7 +4234,6 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
 
 static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
 			   int chip_id,
-			   unsigned short ModeNo,
 			   unsigned short ModeIdIndex,
 			   struct vb_device_info *pVBInfo)
 {
@@ -4831,9 +4774,7 @@ static void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
 /* Output : */
 /* Description : Set TV Customized Param. */
 /* --------------------------------------------------------------------- */
-static void XGI_SetAntiFlicker(unsigned short ModeNo,
-			       unsigned short ModeIdIndex,
-			       struct vb_device_info *pVBInfo)
+static void XGI_SetAntiFlicker(struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx;
 
@@ -4850,9 +4791,7 @@ static void XGI_SetAntiFlicker(unsigned short ModeNo,
 	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
 }
 
-static void XGI_SetEdgeEnhance(unsigned short ModeNo,
-			       unsigned short ModeIdIndex,
-			       struct vb_device_info *pVBInfo)
+static void XGI_SetEdgeEnhance(struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx;
 
@@ -4887,8 +4826,8 @@ static void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
 			& 0xFF000000) >> 24));
 }
 
-static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetYFilter(unsigned short ModeIdIndex,
+			   struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx, index;
 	unsigned char const *filterPtr;
@@ -4957,8 +4896,7 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
 /* Output : */
 /* Description : Customized Param. for 301 */
 /* --------------------------------------------------------------------- */
-static void XGI_OEM310Setting(unsigned short ModeNo,
-			      unsigned short ModeIdIndex,
+static void XGI_OEM310Setting(unsigned short ModeIdIndex,
 			      struct vb_device_info *pVBInfo)
 {
 	XGI_SetDelayComp(pVBInfo);
@@ -4968,11 +4906,11 @@ static void XGI_OEM310Setting(unsigned short ModeNo,
 
 	if (pVBInfo->VBInfo & SetCRT2ToTV) {
 		XGI_SetPhaseIncr(pVBInfo);
-		XGI_SetYFilter(ModeNo, ModeIdIndex, pVBInfo);
-		XGI_SetAntiFlicker(ModeNo, ModeIdIndex, pVBInfo);
+		XGI_SetYFilter(ModeIdIndex, pVBInfo);
+		XGI_SetAntiFlicker(pVBInfo);
 
 		if (pVBInfo->VBType & VB_SIS301)
-			XGI_SetEdgeEnhance(ModeNo, ModeIdIndex, pVBInfo);
+			XGI_SetEdgeEnhance(pVBInfo);
 	}
 }
 
@@ -4982,9 +4920,7 @@ static void XGI_OEM310Setting(unsigned short ModeNo,
 /* Output : */
 /* Description : Origin code for crt2group */
 /* --------------------------------------------------------------------- */
-static void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetCRT2ModeRegs(struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbl;
 	short tempcl;
@@ -5146,20 +5082,14 @@ reg_and_or:
 }
 
 
-void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+void XGI_UnLockCRT2(struct vb_device_info *pVBInfo)
 {
-
 	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01);
-
 }
 
-void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+void XGI_LockCRT2(struct vb_device_info *pVBInfo)
 {
-
 	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00);
-
 }
 
 unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
@@ -5231,8 +5161,8 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
 	}
 	i--;
 	if ((pVBInfo->SetFlag & ProgrammingCRT2)) {
-		temp = XGI_AjustCRT2Rate(ModeNo, ModeIdIndex,
-				RefreshRateTableIndex, &i, pVBInfo);
+		temp = XGI_AjustCRT2Rate(ModeIdIndex, RefreshRateTableIndex,
+					 &i, pVBInfo);
 	}
 	return RefreshRateTableIndex + i;
 }
@@ -5246,12 +5176,11 @@ static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
 	pVBInfo->SetFlag |= ProgrammingCRT2;
 	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 			ModeIdIndex, pVBInfo);
-	XGI_GetLVDSResInfo(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_GetLVDSData(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_ModCRT1Regs(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetLVDSRegs(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_SetCRT2ECLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_GetLVDSResInfo(ModeIdIndex, pVBInfo);
+	XGI_GetLVDSData(ModeIdIndex, pVBInfo);
+	XGI_ModCRT1Regs(ModeIdIndex, HwDeviceExtension, pVBInfo);
+	XGI_SetLVDSRegs(ModeIdIndex, pVBInfo);
+	XGI_SetCRT2ECLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
 }
 
 static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
@@ -5261,29 +5190,23 @@ static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
 	unsigned short ModeIdIndex, RefreshRateTableIndex;
 
 	pVBInfo->SetFlag |= ProgrammingCRT2;
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
+	XGI_SearchModeID(ModeNo, &ModeIdIndex);
 	pVBInfo->SelectCRT2Rate = 4;
 	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 			ModeIdIndex, pVBInfo);
 	XGI_SaveCRT2Info(ModeNo, pVBInfo);
-	XGI_GetCRT2ResInfo(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_GetCRT2Data(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_PreSetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetLockRegs(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetLCDRegs(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
+	XGI_GetCRT2ResInfo(ModeIdIndex, pVBInfo);
+	XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_PreSetGroup1(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetGroup1(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetLockRegs(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetGroup2(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetLCDRegs(ModeIdIndex, pVBInfo);
 	XGI_SetTap4Regs(pVBInfo);
-	XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_SetGroup4(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_SetGroup5(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetGroup3(ModeIdIndex, pVBInfo);
+	XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetGroup5(pVBInfo);
 	XGI_AutoThreshold(pVBInfo);
 	return 1;
 }
@@ -5442,7 +5365,7 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info,
 		/* EnablePart4_1F */
 		xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah);
 
-		XGI_DisableGatingCRT(HwDeviceExtension, pVBInfo);
+		XGI_DisableGatingCRT(pVBInfo);
 		XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
 	} /* 301 */
 	else { /* LVDS */
@@ -5467,10 +5390,10 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
 {
 	unsigned short RefreshRateTableIndex, temp;
 
-	XGI_SetSeqRegs(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetSeqRegs(pVBInfo);
 	outb(XGI330_StandTable.MISC, pVBInfo->P3c2);
-	XGI_SetCRTCRegs(HwDeviceExtension, pVBInfo);
-	XGI_SetATTRegs(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetCRTCRegs(pVBInfo);
+	XGI_SetATTRegs(ModeIdIndex, pVBInfo);
 	XGI_SetGRCRegs(pVBInfo);
 	XGI_ClearExt1Regs(pVBInfo);
 
@@ -5495,13 +5418,12 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
 			ModeIdIndex, pVBInfo);
 	if (RefreshRateTableIndex != 0xFFFF) {
 		XGI_SetSync(RefreshRateTableIndex, pVBInfo);
-		XGI_SetCRT1CRTC(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+		XGI_SetCRT1CRTC(ModeIdIndex, RefreshRateTableIndex,
 				pVBInfo, HwDeviceExtension);
-		XGI_SetCRT1DE(HwDeviceExtension, ModeNo, ModeIdIndex,
-				RefreshRateTableIndex, pVBInfo);
+		XGI_SetCRT1DE(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
 		XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
 				HwDeviceExtension, pVBInfo);
-		XGI_SetCRT1VCLK(ModeNo, ModeIdIndex, HwDeviceExtension,
+		XGI_SetCRT1VCLK(ModeIdIndex, HwDeviceExtension,
 				RefreshRateTableIndex, pVBInfo);
 	}
 
@@ -5510,30 +5432,28 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
 		if (temp & 0xA0) {
 
 			if (HwDeviceExtension->jChipType == XG27)
-				XGI_SetXG27CRTC(ModeNo, ModeIdIndex,
-						RefreshRateTableIndex, pVBInfo);
+				XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo);
 			else
-				XGI_SetXG21CRTC(ModeNo, ModeIdIndex,
-						RefreshRateTableIndex, pVBInfo);
+				XGI_SetXG21CRTC(RefreshRateTableIndex, pVBInfo);
 
 			XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
 					RefreshRateTableIndex);
 
 			xgifb_set_lcd(HwDeviceExtension->jChipType,
-					pVBInfo, RefreshRateTableIndex, ModeNo);
+				      pVBInfo, RefreshRateTableIndex);
 
 			if (pVBInfo->IF_DEF_LVDS == 1)
 				xgifb_set_lvds(xgifb_info,
 						HwDeviceExtension->jChipType,
-						ModeNo, ModeIdIndex, pVBInfo);
+						ModeIdIndex, pVBInfo);
 		}
 	}
 
 	pVBInfo->SetFlag &= (~ProgrammingCRT2);
-	XGI_SetCRT1FIFO(ModeNo, HwDeviceExtension, pVBInfo);
-	XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeNo, ModeIdIndex,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_LoadDAC(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetCRT1FIFO(HwDeviceExtension, pVBInfo);
+	XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeIdIndex,
+			    RefreshRateTableIndex, pVBInfo);
+	XGI_LoadDAC(pVBInfo);
 }
 
 unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
@@ -5568,14 +5488,14 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
 	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
 
 	if (HwDeviceExtension->jChipType < XG20)
-		XGI_UnLockCRT2(HwDeviceExtension, pVBInfo);
+		XGI_UnLockCRT2(pVBInfo);
 
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
+	XGI_SearchModeID(ModeNo, &ModeIdIndex);
 
 	if (HwDeviceExtension->jChipType < XG20) {
-		XGI_GetVBInfo(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo);
-		XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo);
-		XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo);
+		XGI_GetVBInfo(ModeIdIndex, pVBInfo);
+		XGI_GetTVInfo(ModeIdIndex, pVBInfo);
+		XGI_GetLCDInfo(ModeIdIndex, pVBInfo);
 		XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
 
 		if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) ||
@@ -5602,15 +5522,14 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
 			}
 		}
 
-		XGI_SetCRT2ModeRegs(ModeNo, HwDeviceExtension, pVBInfo);
-		XGI_OEM310Setting(ModeNo, ModeIdIndex, pVBInfo); /*0212*/
+		XGI_SetCRT2ModeRegs(pVBInfo);
+		XGI_OEM310Setting(ModeIdIndex, pVBInfo); /*0212*/
 		XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
 	} /* !XG20 */
 	else {
 		if (pVBInfo->IF_DEF_LVDS == 1)
 			if (!XGI_XG21CheckLVDSMode(xgifb_info, ModeNo,
-						   ModeIdIndex,
-						   pVBInfo))
+						   ModeIdIndex))
 				return 0;
 
 		pVBInfo->ModeType = XGI330_EModeIDTable[ModeIdIndex].
@@ -5627,10 +5546,10 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
 		XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
 	}
 
-	XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo);
+	XGI_UpdateModeInfo(pVBInfo);
 
 	if (HwDeviceExtension->jChipType < XG20)
-		XGI_LockCRT2(HwDeviceExtension, pVBInfo);
+		XGI_LockCRT2(pVBInfo);
 
 	return 1;
 }
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
index 2c0a31c..f67d947 100644
--- a/drivers/staging/xgifb/vb_setmode.h
+++ b/drivers/staging/xgifb/vb_setmode.h
@@ -2,10 +2,8 @@
 #define _VBSETMODE_
 
 extern void InitTo330Pointer(unsigned char, struct vb_device_info *);
-extern void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
-			   struct vb_device_info *);
-extern void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
-			 struct vb_device_info *);
+extern void XGI_UnLockCRT2(struct vb_device_info *);
+extern void XGI_LockCRT2(struct vb_device_info *);
 extern void XGI_DisplayOff(struct xgifb_video_info *,
 			   struct xgi_hw_device_info *,
 			   struct vb_device_info *);
@@ -16,8 +14,7 @@ extern unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
 				   unsigned short ModeNo) ;
 
 extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
-				      unsigned short *ModeIdIndex,
-				      struct vb_device_info *);
+				      unsigned short *ModeIdIndex);
 extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
 					 unsigned short ModeNo,
 					 unsigned short ModeIdIndex,
diff --git a/drivers/staging/xillybus/Kconfig b/drivers/staging/xillybus/Kconfig
new file mode 100644
index 0000000..8a4181f
--- /dev/null
+++ b/drivers/staging/xillybus/Kconfig
@@ -0,0 +1,32 @@
+#
+# Xillybus devices
+#
+
+config XILLYBUS
+	tristate "Xillybus generic FPGA interface"
+	depends on PCI || (OF_ADDRESS && OF_IRQ) && m
+	help
+	  Xillybus is a generic interface for peripherals designed on
+	  programmable logic (FPGA). The driver probes the hardware for
+	  its capabilities, and creates device files accordingly.
+
+	  If unsure, say N.
+
+if XILLYBUS
+
+config XILLYBUS_PCIE
+	tristate "Xillybus over PCIe"
+	depends on XILLYBUS && PCI
+	help
+	  Set to M if you want Xillybus to use PCI Express for communicating
+	  with the FPGA.
+
+config XILLYBUS_OF
+	tristate "Xillybus over Device Tree"
+	depends on XILLYBUS && OF_ADDRESS && OF_IRQ
+	help
+	  Set to M if you want Xillybus to find its resources from the
+	  Open Firmware Flattened Device Tree. If the target is an embedded
+	  system, say M.
+
+endif # if XILLYBUS
diff --git a/drivers/staging/xillybus/Makefile b/drivers/staging/xillybus/Makefile
new file mode 100644
index 0000000..b68b7eb
--- /dev/null
+++ b/drivers/staging/xillybus/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Xillybus driver
+#
+
+obj-$(CONFIG_XILLYBUS)		+= xillybus_core.o
+obj-$(CONFIG_XILLYBUS_PCIE)	+= xillybus_pcie.o
+obj-$(CONFIG_XILLYBUS_OF)	+= xillybus_of.o
diff --git a/drivers/staging/xillybus/README b/drivers/staging/xillybus/README
new file mode 100644
index 0000000..d2d848a
--- /dev/null
+++ b/drivers/staging/xillybus/README
@@ -0,0 +1,403 @@
+
+               ==========================================
+               Xillybus driver for generic FPGA interface
+               ==========================================
+
+Author: Eli Billauer, Xillybus Ltd. (http://xillybus.com)
+Email:  eli.billauer@gmail.com or as advertised on Xillybus' site.
+
+Contents:
+
+ - Introduction
+  -- Background
+  -- Xillybus Overview
+
+ - Usage
+  -- User interface
+  -- Synchronization
+  -- Seekable pipes
+
+- Internals
+  -- Source code organization
+  -- Pipe attributes
+  -- Host never reads from the FPGA
+  -- Channels, pipes, and the message channel
+  -- Data streaming
+  -- Data granularity
+  -- Probing
+  -- Buffer allocation
+  -- Memory management
+  -- The "nonempty" message (supporting poll)
+
+
+INTRODUCTION
+============
+
+Background
+----------
+
+An FPGA (Field Programmable Gate Array) is a piece of logic hardware, which
+can be programmed to become virtually anything that is usually found as a
+dedicated chipset: For instance, a display adapter, network interface card,
+or even a processor with its peripherals. FPGAs are the LEGO of hardware:
+Based upon certain building blocks, you make your own toys the way you like
+them. It's usually pointless to reimplement something that is already
+available on the market as a chipset, so FPGAs are mostly used when some
+special functionality is needed, and the production volume is relatively low
+(hence not justifying the development of an ASIC).
+
+The challenge with FPGAs is that everything is implemented at a very low
+level, even lower than assembly language. In order to allow FPGA designers to
+focus on their specific project, and not reinvent the wheel over and over
+again, pre-designed building blocks, IP cores, are often used. These are the
+FPGA parallels of library functions. IP cores may implement certain
+mathematical functions, a functional unit (e.g. a USB interface), an entire
+processor (e.g. ARM) or anything that might come handy. Think of them as a
+building block, with electrical wires dangling on the sides for connection to
+other blocks.
+
+One of the daunting tasks in FPGA design is communicating with a fullblown
+operating system (actually, with the processor running it): Implementing the
+low-level bus protocol and the somewhat higher-level interface with the host
+(registers, interrupts, DMA etc.) is a project in itself. When the FPGA's
+function is a well-known one (e.g. a video adapter card, or a NIC), it can
+make sense to design the FPGA's interface logic specifically for the project.
+A special driver is then written to present the FPGA as a well-known interface
+to the kernel and/or user space. In that case, there is no reason to treat the
+FPGA differently than any device on the bus.
+
+It's however common that the desired data communication doesn't fit any well-
+known peripheral function. Also, the effort of designing an elegant
+abstraction for the data exchange is often considered too big. In those cases,
+a quicker and possibly less elegant solution is sought: The driver is
+effectively written as a user space program, leaving the kernel space part
+with just elementary data transport. This still requires designing some
+interface logic for the FPGA, and write a simple ad-hoc driver for the kernel.
+
+Xillybus Overview
+-----------------
+
+Xillybus is an IP core and a Linux driver. Together, they form a kit for
+elementary data transport between an FPGA and the host, providing pipe-like
+data streams with a straightforward user interface. It's intended as a low-
+effort solution for mixed FPGA-host projects, for which it makes sense to
+have the project-specific part of the driver running in a user-space program.
+
+Since the communication requirements may vary significantly from one FPGA
+project to another (the number of data pipes needed in each direction and
+their attributes), there isn't one specific chunk of logic being the Xillybus
+IP core. Rather, the IP core is configured and built based upon a
+specification given by its end user.
+
+Xillybus presents independent data streams, which resemble pipes or TCP/IP
+communication to the user. At the host side, a character device file is used
+just like any pipe file. On the FPGA side, hardware FIFOs are used to stream
+the data. This is contrary to a common method of communicating through fixed-
+sized buffers (even though such buffers are used by Xillybus under the hood).
+There may be more than a hundred of these streams on a single IP core, but
+also no more than one, depending on the configuration.
+
+In order to ease the deployment of the Xillybus IP core, it contains a simple
+data structure which completely defines the core's configuration. The Linux
+driver fetches this data structure during its initialization process, and sets
+up the DMA buffers and character devices accordingly. As a result, a single
+driver is used to work out of the box with any Xillybus IP core.
+
+The data structure just mentioned should not be confused with PCI's
+configuration space or the Flattened Device Tree.
+
+USAGE
+=====
+
+User interface
+--------------
+
+On the host, all interface with Xillybus is done through /dev/xillybus_*
+device files, which are generated automatically as the drivers loads. The
+names of these files depend on the IP core that is loaded in the FPGA (see
+Probing below). To communicate with the FPGA, open the device file that
+corresponds to the hardware FIFO you want to send data or receive data from,
+and use plain write() or read() calls, just like with a regular pipe. In
+particular, it makes perfect sense to go:
+
+$ cat mydata > /dev/xillybus_thisfifo
+
+$ cat /dev/xillybus_thatfifo > hisdata
+
+possibly pressing CTRL-C as some stage, even though the xillybus_* pipes have
+the capability to send an EOF (but may not use it).
+
+The driver and hardware are designed to behave sensibly as pipes, including:
+
+* Supporting non-blocking I/O (by setting O_NONBLOCK on open() ).
+
+* Supporting poll() and select().
+
+* Being bandwidth efficient under load (using DMA) but also handle small
+  pieces of data sent across (like TCP/IP) by autoflushing.
+
+A device file can be read only, write only or bidirectional. Bidirectional
+device files are treated like two independent pipes (except for sharing a
+"channel" structure in the implementation code).
+
+Synchronization
+---------------
+
+Xillybus pipes are configured (on the IP core) to be either synchronous or
+asynchronous. For a synchronous pipe, write() returns successfully only after
+some data has been submitted and acknowledged by the FPGA. This slows down
+bulk data transfers, and is nearly impossible for use with streams that
+require data at a constant rate: There is no data transmitted to the FPGA
+between write() calls, in particular when the process loses the CPU.
+
+When a pipe is configured asynchronous, write() returns if there was enough
+room in the buffers to store any of the data in the buffers.
+
+For FPGA to host pipes, asynchronous pipes allow data transfer from the FPGA
+as soon as the respective device file is opened, regardless of if the data
+has been requested by a read() call. On synchronous pipes, only the amount
+of data requested by a read() call is transmitted.
+
+In summary, for synchronous pipes, data between the host and FPGA is
+transmitted only to satisfy the read() or write() call currently handled
+by the driver, and those calls wait for the transmission to complete before
+returning.
+
+Note that the synchronization attribute has nothing to do with the possibility
+that read() or write() completes less bytes than requested. There is a
+separate configuration flag ("allowpartial") that determines whether such a
+partial completion is allowed.
+
+Seekable pipes
+--------------
+
+A synchronous pipe can be configured to have the stream's position exposed
+to the user logic at the FPGA. Such a pipe is also seekable on the host API.
+With this feature, a memory or register interface can be attached on the
+FPGA side to the seekable stream. Reading or writing to a certain address in
+the attached memory is done by seeking to the desired address, and calling
+read() or write() as required.
+
+
+INTERNALS
+=========
+
+Source code organization
+------------------------
+
+The Xillybus driver consists of a core module, xillybus_core.c, and modules
+that depend on the specific bus interface (xillybus_of.c and xillybus_pcie.c).
+
+The bus specific modules are those probed when a suitable device is found by
+the kernel. Since the DMA mapping and synchronization functions, which are bus
+dependent by their nature, are used by the core module, a
+xilly_endpoint_hardware structure is passed to the core module on
+initialization. This structure is populated with pointers to wrapper functions
+which execute the DMA-related operations on the bus.
+
+Pipe attributes
+---------------
+
+Each pipe has a number of attributes which are set when the FPGA component
+(IP core) is built. They are fetched from the IDT (the data structure which
+defines the core's configuration, see Probing below) by xilly_setupchannels()
+in xillybus_core.c as follows:
+
+* is_writebuf: The pipe's direction. A non-zero value means it's an FPGA to
+  host pipe (the FPGA "writes").
+
+* channelnum: The pipe's identification number in communication between the
+  host and FPGA.
+
+* format: The underlying data width. See Data Granularity below.
+
+* allowpartial: A non-zero value means that a read() or write() (whichever
+  applies) may return with less than the requested number of bytes. The common
+  choice is a non-zero value, to match standard UNIX behavior.
+
+* synchronous: A non-zero value means that the pipe is synchronous. See
+  Syncronization above.
+
+* bufsize: Each DMA buffer's size. Always a power of two.
+
+* bufnum: The number of buffers allocated for this pipe. Always a power of two.
+
+* exclusive_open: A non-zero value forces exclusive opening of the associated
+  device file. If the device file is bidirectional, and already opened only in
+  one direction, the opposite direction may be opened once.
+
+* seekable: A non-zero value indicates that the pipe is seekable. See
+  Seekable pipes above.
+
+* supports_nonempty: A non-zero value (which is typical) indicates that the
+  hardware will send the messages that are necessary to support select() and
+  poll() for this pipe.
+
+Host never reads from the FPGA
+------------------------------
+
+Even though PCI Express is hotpluggable in general, a typical motherboard
+doesn't expect a card to go away all of the sudden. But since the PCIe card
+is based upon reprogrammable logic, a sudden disappearance from the bus is
+quite likely as a result of an accidental reprogramming of the FPGA while the
+host is up. In practice, nothing happens immediately in such a situation. But
+if the host attempts to read from an address that is mapped to the PCI Express
+device, that leads to an immediate freeze of the system on some motherboards,
+even though the PCIe standard requires a graceful recovery.
+
+In order to avoid these freezes, the Xillybus driver refrains completely from
+reading from the device's register space. All communication from the FPGA to
+the host is done through DMA. In particular, the Interrupt Service Routine
+doesn't follow the common practice of checking a status register when it's
+invoked. Rather, the FPGA prepares a small buffer which contains short
+messages, which inform the host what the interrupt was about.
+
+This mechanism is used on non-PCIe buses as well for the sake of uniformity.
+
+
+Channels, pipes, and the message channel
+----------------------------------------
+
+Each of the (possibly bidirectional) pipes presented to the user is allocated
+a data channel between the FPGA and the host. The distinction between channels
+and pipes is necessary only because of channel 0, which is used for interrupt-
+related messages from the FPGA, and has no pipe attached to it.
+
+Data streaming
+--------------
+
+Even though a non-segmented data stream is presented to the user at both
+sides, the implementation relies on a set of DMA buffers which is allocated
+for each channel. For the sake of illustration, let's take the FPGA to host
+direction: As data streams into the respective channel's interface in the
+FPGA, the Xillybus IP core writes it to one of the DMA buffers. When the
+buffer is full, the FPGA informs the host about that (appending a
+XILLYMSG_OPCODE_RELEASEBUF message channel 0 and sending an interrupt if
+necessary). The host responds by making the data available for reading through
+the character device. When all data has been read, the host writes on the
+the FPGA's buffer control register, allowing the buffer's overwriting. Flow
+control mechanisms exist on both sides to prevent underflows and overflows.
+
+This is not good enough for creating a TCP/IP-like stream: If the data flow
+stops momentarily before a DMA buffer is filled, the intuitive expectation is
+that the partial data in buffer will arrive anyhow, despite the buffer not
+being completed. This is implemented by adding a field in the
+XILLYMSG_OPCODE_RELEASEBUF message, through which the FPGA informs not just
+which buffer is submitted, but how much data it contains.
+
+But the FPGA will submit a partially filled buffer only if directed to do so
+by the host. This situation occurs when the read() method has been blocking
+for XILLY_RX_TIMEOUT jiffies (currently 10 ms), after which the host commands
+the FPGA to submit a DMA buffer as soon as it can. This timeout mechanism
+balances between bus bandwidth efficiency (preventing a lot of partially
+filled buffers being sent) and a latency held fairly low for tails of data.
+
+A similar setting is used in the host to FPGA direction. The handling of
+partial DMA buffers is somewhat different, though. The user can tell the
+driver to submit all data it has in the buffers to the FPGA, by issuing a
+write() with the byte count set to zero. This is similar to a flush request,
+but it doesn't block. There is also an autoflushing mechanism, which triggers
+an equivalent flush roughly XILLY_RX_TIMEOUT jiffies after the last write().
+This allows the user to be oblivious about the underlying buffering mechanism
+and yet enjoy a stream-like interface.
+
+Note that the issue of partial buffer flushing is irrelevant for pipes having
+the "synchronous" attribute nonzero, since synchronous pipes don't allow data
+to lay around in the DMA buffers between read() and write() anyhow.
+
+Data granularity
+----------------
+
+The data arrives or is sent at the FPGA as 8, 16 or 32 bit wide words, as
+configured by the "format" attribute. Whenever possible, the driver attempts
+to hide this when the pipe is accessed differently from its natural alignment.
+For example, reading single bytes from a pipe with 32 bit granularity works
+with no issues. Writing single bytes to pipes with 16 or 32 bit granularity
+will also work, but the driver can't send partially completed words to the
+FPGA, so the transmission of up to one word may be held until it's fully
+occupied with user data.
+
+This somewhat complicates the handling of host to FPGA streams, because
+when a buffer is flushed, it may contain up to 3 bytes don't form a word in
+the FPGA, and hence can't be sent. To prevent loss of data, these leftover
+bytes need to be moved to the next buffer. The parts in xillybus_core.c
+that mention "leftovers" in some way are related to this complication.
+
+Probing
+-------
+
+As mentioned earlier, the number of pipes that are created when the driver
+loads and their attributes depend on the Xillybus IP core in the FPGA. During
+the driver's initialization, a blob containing configuration info, the
+Interface Description Table (IDT), is sent from the FPGA to the host. The
+bootstrap process is done in three phases:
+
+1. Acquire the length of the IDT, so a buffer can be allocated for it. This
+   is done by sending a quiesce command to the device, since the acknowledge
+   for this command contains the IDT's buffer length.
+
+2. Acquire the IDT itself.
+
+3. Create the interfaces according to the IDT.
+
+Buffer allocation
+-----------------
+
+In order to simplify the logic that prevents illegal boundary crossings of
+PCIe packets, the following rule applies: If a buffer is smaller than 4kB,
+it must not cross a 4kB boundary. Otherwise, it must be 4kB aligned. The
+xilly_setupchannels() functions allocates these buffers by requesting whole
+pages from the kernel, and diving them into DMA buffers as necessary. Since
+all buffers' sizes are powers of two, it's possible to pack any set of such
+buffers, with a maximal waste of one page of memory.
+
+All buffers are allocated when the driver is loaded. This is necessary,
+since large continuous physical memory segments are sometimes requested,
+which are more likely to be available when the system is freshly booted.
+
+The allocation of buffer memory takes place in the same order they appear in
+the IDT. The driver relies on a rule that the pipes are sorted with decreasing
+buffer size in the IDT. If a requested buffer is larger or equal to a page,
+the necessary number of pages is requested from the kernel, and these are
+used for this buffer. If the requested buffer is smaller than a page, one
+single page is requested from the kernel, and that page is partially used.
+Or, if there already is a partially used page at hand, the buffer is packed
+into that page. It can be shown that all pages requested from the kernel
+(except possibly for the last) are 100% utilized this way.
+
+Memory management
+-----------------
+
+The tricky part about the buffer allocation procedure described above is
+freeing and unmapping the buffers, in particular if something goes wrong in
+the middle, and the allocations need to be rolled back. The three-stage
+probing procedure makes this even more crucial, since temporary buffers are
+set up and mapped in the first of its two stages.
+
+To keep the code clean from complicated and bug-prone memory release routines,
+there are special routines for allocating memory. For example, instead of
+calling kzalloc, there's
+
+void *xilly_malloc(struct xilly_cleanup *mem, size_t size)
+
+which effectively allocates a zeroed buffer of size "size". Its first
+argument, "mem", is where this allocation is enlisted, so that it's released
+when xillybus_do_cleanup() is called with the same "mem" structure.
+
+Two other functions enlist allocations in this structure: xilly_pagealloc()
+for page allocations and xilly_map_single_*() for DMA mapping.
+
+The "nonempty" message (supporting poll)
+---------------------------------------
+
+In order to support the "poll" method (and hence select() ), there is a small
+catch regarding the FPGA to host direction: The FPGA may have filled a DMA
+buffer with some data, but not submitted that buffer. If the host waited for
+the buffer's submission by the FPGA, there would be a possibility that the
+FPGA side has sent data, but a select() call would still block, because the
+host has not received any notification about this. This is solved with
+XILLYMSG_OPCODE_NONEMPTY messages sent by the FPGA when a channel goes from
+completely empty to containing some data.
+
+These messages are used only to support poll() and select(). The IP core can
+be configured not to send them for a slight reduction of bandwidth.
diff --git a/drivers/staging/xillybus/TODO b/drivers/staging/xillybus/TODO
new file mode 100644
index 0000000..95cfe2f
--- /dev/null
+++ b/drivers/staging/xillybus/TODO
@@ -0,0 +1,5 @@
+TODO:
+- have the driver reviewed
+
+Please send any patches and/or comments to Eli Billauer,
+<eli.billauer@gmail.com>.
diff --git a/drivers/staging/xillybus/xillybus.h b/drivers/staging/xillybus/xillybus.h
new file mode 100644
index 0000000..d3fc8aa
--- /dev/null
+++ b/drivers/staging/xillybus/xillybus.h
@@ -0,0 +1,183 @@
+/*
+ * linux/drivers/misc/xillybus.h
+ *
+ * Copyright 2011 Xillybus Ltd, http://xillybus.com
+ *
+ * Header file for the Xillybus FPGA/host framework.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __XILLYBUS_H
+#define __XILLYBUS_H
+
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/cdev.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+
+struct xilly_endpoint_hardware;
+
+struct xilly_page {
+	struct list_head node;
+	unsigned long addr;
+	unsigned int order;
+};
+
+struct xilly_dma {
+	struct list_head node;
+	struct pci_dev *pdev;
+	struct device *dev;
+	dma_addr_t dma_addr;
+	size_t size;
+	int direction;
+};
+
+struct xilly_buffer {
+	void *addr;
+	dma_addr_t dma_addr;
+	int end_offset; /* Counting elements, not bytes */
+};
+
+struct xilly_cleanup {
+	struct list_head to_kfree;
+	struct list_head to_pagefree;
+	struct list_head to_unmap;
+};
+
+struct xilly_idt_handle {
+	unsigned char *chandesc;
+	unsigned char *idt;
+	int entries;
+};
+
+/*
+ * Read-write confusion: wr_* and rd_* notation sticks to FPGA view, so
+ * wr_* buffers are those consumed by read(), since the FPGA writes to them
+ * and vice versa.
+ */
+
+struct xilly_channel {
+	struct xilly_endpoint *endpoint;
+	int chan_num;
+	int log2_element_size;
+	int seekable;
+
+	struct xilly_buffer **wr_buffers; /* FPGA writes, driver reads! */
+	int num_wr_buffers;
+	unsigned int wr_buf_size; /* In bytes */
+	int wr_fpga_buf_idx;
+	int wr_host_buf_idx;
+	int wr_host_buf_pos;
+	int wr_empty;
+	int wr_ready; /* Significant only when wr_empty == 1 */
+	int wr_sleepy;
+	int wr_eof;
+	int wr_hangup;
+	spinlock_t wr_spinlock;
+	struct mutex wr_mutex;
+	wait_queue_head_t wr_wait;
+	wait_queue_head_t wr_ready_wait;
+	int wr_ref_count;
+	int wr_synchronous;
+	int wr_allow_partial;
+	int wr_exclusive_open;
+	int wr_supports_nonempty;
+
+	struct xilly_buffer **rd_buffers; /* FPGA reads, driver writes! */
+	int num_rd_buffers;
+	unsigned int rd_buf_size; /* In bytes */
+	int rd_fpga_buf_idx;
+	int rd_host_buf_pos;
+	int rd_host_buf_idx;
+	int rd_full;
+	spinlock_t rd_spinlock;
+	struct mutex rd_mutex;
+	wait_queue_head_t rd_wait;
+	int rd_ref_count;
+	int rd_allow_partial;
+	int rd_synchronous;
+	int rd_exclusive_open;
+	struct delayed_work rd_workitem;
+	unsigned char rd_leftovers[4];
+};
+
+struct xilly_endpoint {
+	/*
+	 * One of pdev and dev is always NULL, and the other is a valid
+	 * pointer, depending on the type of device
+	 */
+	struct pci_dev *pdev;
+	struct device *dev;
+	struct resource res; /* OF devices only */
+	struct xilly_endpoint_hardware *ephw;
+
+	struct list_head ep_list;
+	int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */
+	__iomem u32 *registers;
+	int fatal_error;
+
+	struct mutex register_mutex;
+	wait_queue_head_t ep_wait;
+
+	/* List of memory allocations, to make release easy */
+	struct xilly_cleanup cleanup;
+
+	/* Channels and message handling */
+	struct cdev cdev;
+
+	int major;
+	int lowest_minor; /* Highest minor = lowest_minor + num_channels - 1 */
+
+	int num_channels; /* EXCLUDING message buffer */
+	struct xilly_channel **channels;
+	int msg_counter;
+	int failed_messages;
+	int idtlen;
+
+	u32 *msgbuf_addr;
+	dma_addr_t msgbuf_dma_addr;
+	unsigned int msg_buf_size;
+};
+
+struct xilly_endpoint_hardware {
+	struct module *owner;
+	void (*hw_sync_sgl_for_cpu)(struct xilly_endpoint *,
+				    dma_addr_t,
+				    size_t,
+				    int);
+	void (*hw_sync_sgl_for_device)(struct xilly_endpoint *,
+				       dma_addr_t,
+				       size_t,
+				       int);
+	dma_addr_t (*map_single)(struct xilly_cleanup *,
+				 struct xilly_endpoint *,
+				 void *,
+				 size_t,
+				 int);
+	void (*unmap_single)(struct xilly_dma *entry);
+};
+
+irqreturn_t xillybus_isr(int irq, void *data);
+
+void xillybus_do_cleanup(struct xilly_cleanup *mem,
+			 struct xilly_endpoint *endpoint);
+
+struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev,
+					      struct device *dev,
+					      struct xilly_endpoint_hardware
+					      *ephw);
+
+int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint);
+
+void xillybus_endpoint_remove(struct xilly_endpoint *endpoint);
+
+#endif /* __XILLYBUS_H */
diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c
new file mode 100644
index 0000000..3d7471a
--- /dev/null
+++ b/drivers/staging/xillybus/xillybus_core.c
@@ -0,0 +1,2345 @@
+/*
+ * linux/drivers/misc/xillybus_core.c
+ *
+ * Copyright 2011 Xillybus Ltd, http://xillybus.com
+ *
+ * Driver for the Xillybus FPGA/host framework.
+ *
+ * This driver interfaces with a special IP core in an FPGA, setting up
+ * a pipe between a hardware FIFO in the programmable logic and a device
+ * file in the host. The number of such pipes and their attributes are
+ * set up on the logic. This driver detects these automatically and
+ * creates the device files accordingly.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/crc32.h>
+#include <linux/poll.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include "xillybus.h"
+
+MODULE_DESCRIPTION("Xillybus core functions");
+MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
+MODULE_VERSION("1.07");
+MODULE_ALIAS("xillybus_core");
+MODULE_LICENSE("GPL v2");
+
+/* General timeout is 100 ms, rx timeout is 10 ms */
+#define XILLY_RX_TIMEOUT (10*HZ/1000)
+#define XILLY_TIMEOUT (100*HZ/1000)
+
+#define fpga_msg_ctrl_reg 0x0002
+#define fpga_dma_control_reg 0x0008
+#define fpga_dma_bufno_reg 0x0009
+#define fpga_dma_bufaddr_lowaddr_reg 0x000a
+#define fpga_dma_bufaddr_highaddr_reg 0x000b
+#define fpga_buf_ctrl_reg 0x000c
+#define fpga_buf_offset_reg 0x000d
+#define fpga_endian_reg 0x0010
+
+#define XILLYMSG_OPCODE_RELEASEBUF 1
+#define XILLYMSG_OPCODE_QUIESCEACK 2
+#define XILLYMSG_OPCODE_FIFOEOF 3
+#define XILLYMSG_OPCODE_FATAL_ERROR 4
+#define XILLYMSG_OPCODE_NONEMPTY 5
+
+static const char xillyname[] = "xillybus";
+
+static struct class *xillybus_class;
+
+/*
+ * ep_list_lock is the last lock to be taken; No other lock requests are
+ * allowed while holding it. It merely protects list_of_endpoints, and not
+ * the endpoints listed in it.
+ */
+
+static LIST_HEAD(list_of_endpoints);
+static struct mutex ep_list_lock;
+static struct workqueue_struct *xillybus_wq;
+
+/*
+ * Locking scheme: Mutexes protect invocations of character device methods.
+ * If both locks are taken, wr_mutex is taken first, rd_mutex second.
+ *
+ * wr_spinlock protects wr_*_buf_idx, wr_empty, wr_sleepy, wr_ready and the
+ * buffers' end_offset fields against changes made by IRQ handler (and in
+ * theory, other file request handlers, but the mutex handles that). Nothing
+ * else.
+ * They are held for short direct memory manipulations. Needless to say,
+ * no mutex locking is allowed when a spinlock is held.
+ *
+ * rd_spinlock does the same with rd_*_buf_idx, rd_empty and end_offset.
+ *
+ * register_mutex is endpoint-specific, and is held when non-atomic
+ * register operations are performed. wr_mutex and rd_mutex may be
+ * held when register_mutex is taken, but none of the spinlocks. Note that
+ * register_mutex doesn't protect against sporadic buf_ctrl_reg writes
+ * which are unrelated to buf_offset_reg, since they are harmless.
+ *
+ * Blocking on the wait queues is allowed with mutexes held, but not with
+ * spinlocks.
+ *
+ * Only interruptible blocking is allowed on mutexes and wait queues.
+ *
+ * All in all, the locking order goes (with skips allowed, of course):
+ * wr_mutex -> rd_mutex -> register_mutex -> wr_spinlock -> rd_spinlock
+ */
+
+static void malformed_message(u32 *buf)
+{
+	int opcode;
+	int msg_channel, msg_bufno, msg_data, msg_dir;
+
+	opcode = (buf[0] >> 24) & 0xff;
+	msg_dir = buf[0] & 1;
+	msg_channel = (buf[0] >> 1) & 0x7ff;
+	msg_bufno = (buf[0] >> 12) & 0x3ff;
+	msg_data = buf[1] & 0xfffffff;
+
+	pr_warn("xillybus: Malformed message (skipping): "
+		"opcode=%d, channel=%03x, dir=%d, bufno=%03x, data=%07x\n",
+		opcode, msg_channel, msg_dir, msg_bufno, msg_data);
+}
+
+/*
+ * xillybus_isr assumes the interrupt is allocated exclusively to it,
+ * which is the natural case MSI and several other hardware-oriented
+ * interrupts. Sharing is not allowed.
+ */
+
+irqreturn_t xillybus_isr(int irq, void *data)
+{
+	struct xilly_endpoint *ep = data;
+	u32 *buf;
+	unsigned int buf_size;
+	int i;
+	int opcode;
+	unsigned int msg_channel, msg_bufno, msg_data, msg_dir;
+	struct xilly_channel *channel;
+
+	/*
+	 * The endpoint structure is altered during periods when it's
+	 * guaranteed no interrupt will occur, but in theory, the cache
+	 * lines may not be updated. So a memory barrier is issued.
+	 */
+
+	smp_rmb();
+
+	buf = ep->msgbuf_addr;
+	buf_size = ep->msg_buf_size/sizeof(u32);
+
+
+	ep->ephw->hw_sync_sgl_for_cpu(ep,
+				      ep->msgbuf_dma_addr,
+				      ep->msg_buf_size,
+				      DMA_FROM_DEVICE);
+
+	for (i = 0; i < buf_size; i += 2)
+		if (((buf[i+1] >> 28) & 0xf) != ep->msg_counter) {
+			malformed_message(&buf[i]);
+			pr_warn("xillybus: Sending a NACK on "
+				"counter %x (instead of %x) on entry %d\n",
+				((buf[i+1] >> 28) & 0xf),
+				ep->msg_counter,
+				i/2);
+
+			if (++ep->failed_messages > 10)
+				pr_err("xillybus: Lost sync with "
+				       "interrupt messages. Stopping.\n");
+			else {
+				ep->ephw->hw_sync_sgl_for_device(
+					ep,
+					ep->msgbuf_dma_addr,
+					ep->msg_buf_size,
+					DMA_FROM_DEVICE);
+
+				iowrite32(0x01,  /* Message NACK */
+					  &ep->registers[fpga_msg_ctrl_reg]);
+			}
+			return IRQ_HANDLED;
+		} else if (buf[i] & (1 << 22)) /* Last message */
+			break;
+
+	if (i >= buf_size) {
+		pr_err("xillybus: Bad interrupt message. Stopping.\n");
+		return IRQ_HANDLED;
+	}
+
+	buf_size = i;
+
+	for (i = 0; i <= buf_size; i += 2) { /* Scan through messages */
+		opcode = (buf[i] >> 24) & 0xff;
+
+		msg_dir = buf[i] & 1;
+		msg_channel = (buf[i] >> 1) & 0x7ff;
+		msg_bufno = (buf[i] >> 12) & 0x3ff;
+		msg_data = buf[i+1] & 0xfffffff;
+
+		switch (opcode) {
+		case XILLYMSG_OPCODE_RELEASEBUF:
+
+			if ((msg_channel > ep->num_channels) ||
+			    (msg_channel == 0)) {
+				malformed_message(&buf[i]);
+				break;
+			}
+
+			channel = ep->channels[msg_channel];
+
+			if (msg_dir) { /* Write channel */
+				if (msg_bufno >= channel->num_wr_buffers) {
+					malformed_message(&buf[i]);
+					break;
+				}
+				spin_lock(&channel->wr_spinlock);
+				channel->wr_buffers[msg_bufno]->end_offset =
+					msg_data;
+				channel->wr_fpga_buf_idx = msg_bufno;
+				channel->wr_empty = 0;
+				channel->wr_sleepy = 0;
+				spin_unlock(&channel->wr_spinlock);
+
+				wake_up_interruptible(&channel->wr_wait);
+
+			} else {
+				/* Read channel */
+
+				if (msg_bufno >= channel->num_rd_buffers) {
+					malformed_message(&buf[i]);
+					break;
+				}
+
+				spin_lock(&channel->rd_spinlock);
+				channel->rd_fpga_buf_idx = msg_bufno;
+				channel->rd_full = 0;
+				spin_unlock(&channel->rd_spinlock);
+
+				wake_up_interruptible(&channel->rd_wait);
+				if (!channel->rd_synchronous)
+					queue_delayed_work(
+						xillybus_wq,
+						&channel->rd_workitem,
+						XILLY_RX_TIMEOUT);
+			}
+
+			break;
+		case XILLYMSG_OPCODE_NONEMPTY:
+			if ((msg_channel > ep->num_channels) ||
+			    (msg_channel == 0) || (!msg_dir) ||
+			    !ep->channels[msg_channel]->wr_supports_nonempty) {
+				malformed_message(&buf[i]);
+				break;
+			}
+
+			channel = ep->channels[msg_channel];
+
+			if (msg_bufno >= channel->num_wr_buffers) {
+				malformed_message(&buf[i]);
+				break;
+			}
+			spin_lock(&channel->wr_spinlock);
+			if (msg_bufno == channel->wr_host_buf_idx)
+				channel->wr_ready = 1;
+			spin_unlock(&channel->wr_spinlock);
+
+			wake_up_interruptible(&channel->wr_ready_wait);
+
+			break;
+		case XILLYMSG_OPCODE_QUIESCEACK:
+			ep->idtlen = msg_data;
+			wake_up_interruptible(&ep->ep_wait);
+
+			break;
+		case XILLYMSG_OPCODE_FIFOEOF:
+			channel = ep->channels[msg_channel];
+			spin_lock(&channel->wr_spinlock);
+			channel->wr_eof = msg_bufno;
+			channel->wr_sleepy = 0;
+
+			channel->wr_hangup = channel->wr_empty &&
+				(channel->wr_host_buf_idx == msg_bufno);
+
+			spin_unlock(&channel->wr_spinlock);
+
+			wake_up_interruptible(&channel->wr_wait);
+
+			break;
+		case XILLYMSG_OPCODE_FATAL_ERROR:
+			ep->fatal_error = 1;
+			wake_up_interruptible(&ep->ep_wait); /* For select() */
+			pr_err("xillybus: FPGA reported a fatal "
+			       "error. This means that the low-level "
+			       "communication with the device has failed. "
+			       "This hardware problem is most likely "
+			       "unrelated to xillybus (neither kernel "
+			       "module nor FPGA core), but reports are "
+			       "still welcome. All I/O is aborted.\n");
+			break;
+		default:
+			malformed_message(&buf[i]);
+			break;
+		}
+	}
+
+	ep->ephw->hw_sync_sgl_for_device(ep,
+					 ep->msgbuf_dma_addr,
+					 ep->msg_buf_size,
+					 DMA_FROM_DEVICE);
+
+	ep->msg_counter = (ep->msg_counter + 1) & 0xf;
+	ep->failed_messages = 0;
+	iowrite32(0x03, &ep->registers[fpga_msg_ctrl_reg]); /* Message ACK */
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(xillybus_isr);
+
+/*
+ * A few trivial memory management functions.
+ * NOTE: These functions are used only on probe and remove, and therefore
+ * no locks are applied!
+ */
+
+void xillybus_do_cleanup(struct xilly_cleanup *mem,
+			 struct xilly_endpoint *endpoint)
+{
+	struct list_head *this, *next;
+
+	list_for_each_safe(this, next, &mem->to_unmap) {
+		struct xilly_dma *entry =
+			list_entry(this, struct xilly_dma, node);
+
+		endpoint->ephw->unmap_single(entry);
+		kfree(entry);
+	}
+
+	INIT_LIST_HEAD(&mem->to_unmap);
+
+	list_for_each_safe(this, next, &mem->to_kfree)
+		kfree(this);
+
+	INIT_LIST_HEAD(&mem->to_kfree);
+
+	list_for_each_safe(this, next, &mem->to_pagefree) {
+		struct xilly_page *entry =
+			list_entry(this, struct xilly_page, node);
+
+		free_pages(entry->addr, entry->order);
+		kfree(entry);
+	}
+	INIT_LIST_HEAD(&mem->to_pagefree);
+}
+EXPORT_SYMBOL(xillybus_do_cleanup);
+
+static void *xilly_malloc(struct xilly_cleanup *mem, size_t size)
+{
+	void *ptr;
+
+	ptr = kzalloc(sizeof(struct list_head) + size, GFP_KERNEL);
+
+	if (!ptr)
+		return ptr;
+
+	list_add_tail((struct list_head *) ptr, &mem->to_kfree);
+
+	return ptr + sizeof(struct list_head);
+}
+
+static unsigned long xilly_pagealloc(struct xilly_cleanup *mem,
+				     unsigned long order)
+{
+	unsigned long addr;
+	struct xilly_page *this;
+
+	this = kmalloc(sizeof(struct xilly_page), GFP_KERNEL);
+	if (!this)
+		return 0;
+
+	addr =  __get_free_pages(GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO, order);
+
+	if (!addr) {
+		kfree(this);
+		return 0;
+	}
+
+	this->addr = addr;
+	this->order = order;
+
+	list_add_tail(&this->node, &mem->to_pagefree);
+
+	return addr;
+}
+
+
+static void xillybus_autoflush(struct work_struct *work);
+
+static int xilly_setupchannels(struct xilly_endpoint *ep,
+			       struct xilly_cleanup *mem,
+			       unsigned char *chandesc,
+			       int entries
+	)
+{
+	int i, entry, wr_nbuffer, rd_nbuffer;
+	struct xilly_channel *channel;
+	int channelnum, bufnum, bufsize, format, is_writebuf;
+	int bytebufsize;
+	int synchronous, allowpartial, exclusive_open, seekable;
+	int supports_nonempty;
+	void *wr_salami = NULL;
+	void *rd_salami = NULL;
+	int left_of_wr_salami = 0;
+	int left_of_rd_salami = 0;
+	dma_addr_t dma_addr;
+	int msg_buf_done = 0;
+
+	struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */
+
+	channel = xilly_malloc(mem, ep->num_channels *
+			       sizeof(struct xilly_channel));
+
+	if (!channel)
+		goto memfail;
+
+	ep->channels = xilly_malloc(mem, (ep->num_channels + 1) *
+				    sizeof(struct xilly_channel *));
+
+	if (!ep->channels)
+		goto memfail;
+
+	ep->channels[0] = NULL; /* Channel 0 is message buf. */
+
+	/* Initialize all channels with defaults */
+
+	for (i = 1; i <= ep->num_channels; i++) {
+		channel->wr_buffers = NULL;
+		channel->rd_buffers = NULL;
+		channel->num_wr_buffers = 0;
+		channel->num_rd_buffers = 0;
+		channel->wr_fpga_buf_idx = -1;
+		channel->wr_host_buf_idx = 0;
+		channel->wr_host_buf_pos = 0;
+		channel->wr_empty = 1;
+		channel->wr_ready = 0;
+		channel->wr_sleepy = 1;
+		channel->rd_fpga_buf_idx = 0;
+		channel->rd_host_buf_idx = 0;
+		channel->rd_host_buf_pos = 0;
+		channel->rd_full = 0;
+		channel->wr_ref_count = 0;
+		channel->rd_ref_count = 0;
+
+		spin_lock_init(&channel->wr_spinlock);
+		spin_lock_init(&channel->rd_spinlock);
+		mutex_init(&channel->wr_mutex);
+		mutex_init(&channel->rd_mutex);
+		init_waitqueue_head(&channel->rd_wait);
+		init_waitqueue_head(&channel->wr_wait);
+		init_waitqueue_head(&channel->wr_ready_wait);
+
+		INIT_DELAYED_WORK(&channel->rd_workitem, xillybus_autoflush);
+
+		channel->endpoint = ep;
+		channel->chan_num = i;
+
+		channel->log2_element_size = 0;
+
+		ep->channels[i] = channel++;
+	}
+
+	/*
+	 * The DMA buffer address update is atomic on the FPGA, so even if
+	 * it was in the middle of sending messages to some buffer, changing
+	 * the address is safe, since the data will go to either of the
+	 * buffers. Not that this situation should occur at all anyhow.
+	 */
+
+	wr_nbuffer = 1;
+	rd_nbuffer = 1; /* Buffer zero isn't used at all */
+
+	for (entry = 0; entry < entries; entry++, chandesc += 4) {
+		is_writebuf = chandesc[0] & 0x01;
+		channelnum = (chandesc[0] >> 1) | ((chandesc[1] & 0x0f) << 7);
+		format = (chandesc[1] >> 4) & 0x03;
+		allowpartial = (chandesc[1] >> 6) & 0x01;
+		synchronous = (chandesc[1] >> 7) & 0x01;
+		bufsize = 1 << (chandesc[2] & 0x1f);
+		bufnum = 1 << (chandesc[3] & 0x0f);
+		exclusive_open = (chandesc[2] >> 7) & 0x01;
+		seekable = (chandesc[2] >> 6) & 0x01;
+		supports_nonempty = (chandesc[2] >> 5) & 0x01;
+
+		if ((channelnum > ep->num_channels) ||
+		    ((channelnum == 0) && !is_writebuf)) {
+			pr_err("xillybus: IDT requests channel out "
+			       "of range. Aborting.\n");
+			return -ENODEV;
+		}
+
+		channel = ep->channels[channelnum]; /* NULL for msg channel */
+
+		bytebufsize = bufsize << 2; /* Overwritten just below */
+
+		if (!is_writebuf) {
+			channel->num_rd_buffers = bufnum;
+			channel->log2_element_size = ((format > 2) ?
+						      2 : format);
+			bytebufsize = channel->rd_buf_size = bufsize *
+				(1 << channel->log2_element_size);
+			channel->rd_allow_partial = allowpartial;
+			channel->rd_synchronous = synchronous;
+			channel->rd_exclusive_open = exclusive_open;
+			channel->seekable = seekable;
+
+			channel->rd_buffers = xilly_malloc(
+				mem,
+				bufnum * sizeof(struct xilly_buffer *));
+
+			if (!channel->rd_buffers)
+				goto memfail;
+
+			this_buffer = xilly_malloc(
+				mem,
+				bufnum * sizeof(struct xilly_buffer));
+
+			if (!this_buffer)
+				goto memfail;
+		}
+
+		else if (channelnum > 0) {
+			channel->num_wr_buffers = bufnum;
+			channel->log2_element_size = ((format > 2) ?
+						      2 : format);
+			bytebufsize = channel->wr_buf_size = bufsize *
+				(1 << channel->log2_element_size);
+
+			channel->seekable = seekable;
+			channel->wr_supports_nonempty = supports_nonempty;
+
+			channel->wr_allow_partial = allowpartial;
+			channel->wr_synchronous = synchronous;
+			channel->wr_exclusive_open = exclusive_open;
+
+			channel->wr_buffers = xilly_malloc(
+				mem,
+				bufnum * sizeof(struct xilly_buffer *));
+
+			if (!channel->wr_buffers)
+				goto memfail;
+
+			this_buffer = xilly_malloc(
+				mem,
+				bufnum * sizeof(struct xilly_buffer));
+
+			if (!this_buffer)
+				goto memfail;
+		}
+
+		/*
+		 * Although daunting, we cut the chunks for read buffers
+		 * from a different salami than the write buffers',
+		 * possibly improving performance.
+		 */
+
+		if (is_writebuf)
+			for (i = 0; i < bufnum; i++) {
+				/*
+				 * Buffers are expected in descending
+				 * byte-size order, so there is either
+				 * enough for this buffer or none at all.
+				 */
+				if ((left_of_wr_salami < bytebufsize) &&
+				    (left_of_wr_salami > 0)) {
+					pr_err("xillybus: "
+					       "Corrupt buffer allocation "
+					       "in IDT. Aborting.\n");
+					return -ENODEV;
+				}
+
+				if (left_of_wr_salami == 0) {
+					int allocorder, allocsize;
+
+					allocsize = PAGE_SIZE;
+					allocorder = 0;
+					while (bytebufsize > allocsize) {
+						allocsize *= 2;
+						allocorder++;
+					}
+
+					wr_salami = (void *)
+						xilly_pagealloc(mem,
+								allocorder);
+					if (!wr_salami)
+						goto memfail;
+					left_of_wr_salami = allocsize;
+				}
+
+				dma_addr = ep->ephw->map_single(
+					mem,
+					ep,
+					wr_salami,
+					bytebufsize,
+					DMA_FROM_DEVICE);
+
+				if (!dma_addr)
+					goto dmafail;
+
+				iowrite32(
+					(u32) (dma_addr & 0xffffffff),
+					&ep->registers[
+						fpga_dma_bufaddr_lowaddr_reg]
+					);
+				iowrite32(
+					((u32) ((((u64) dma_addr) >> 32)
+						& 0xffffffff)),
+					&ep->registers[
+						fpga_dma_bufaddr_highaddr_reg]
+					);
+				mmiowb();
+
+				if (channelnum > 0) {
+					this_buffer->addr = wr_salami;
+					this_buffer->dma_addr = dma_addr;
+					channel->wr_buffers[i] = this_buffer++;
+
+					iowrite32(
+						0x80000000 | wr_nbuffer++,
+						&ep->registers[
+							fpga_dma_bufno_reg]);
+				} else {
+					ep->msgbuf_addr = wr_salami;
+					ep->msgbuf_dma_addr = dma_addr;
+					ep->msg_buf_size = bytebufsize;
+					msg_buf_done++;
+
+					iowrite32(
+						0x80000000, &ep->registers[
+							fpga_dma_bufno_reg]);
+				}
+
+				left_of_wr_salami -= bytebufsize;
+				wr_salami += bytebufsize;
+			}
+		else /* Read buffers */
+			for (i = 0; i < bufnum; i++) {
+				/*
+				 * Buffers are expected in descending
+				 * byte-size order, so there is either
+				 * enough for this buffer or none at all.
+				 */
+				if ((left_of_rd_salami < bytebufsize) &&
+				    (left_of_rd_salami > 0)) {
+					pr_err("xillybus: "
+					       "Corrupt buffer allocation "
+					       "in IDT. Aborting.\n");
+					return -ENODEV;
+				}
+
+				if (left_of_rd_salami == 0) {
+					int allocorder, allocsize;
+
+					allocsize = PAGE_SIZE;
+					allocorder = 0;
+					while (bytebufsize > allocsize) {
+						allocsize *= 2;
+						allocorder++;
+					}
+
+					rd_salami = (void *)
+						xilly_pagealloc(
+							mem,
+							allocorder);
+
+					if (!rd_salami)
+						goto memfail;
+					left_of_rd_salami = allocsize;
+				}
+
+				dma_addr = ep->ephw->map_single(
+					mem,
+					ep,
+					rd_salami,
+					bytebufsize,
+					DMA_TO_DEVICE);
+
+				if (!dma_addr)
+					goto dmafail;
+
+				iowrite32(
+					(u32) (dma_addr & 0xffffffff),
+					&ep->registers[
+						fpga_dma_bufaddr_lowaddr_reg]
+					);
+				iowrite32(
+					((u32) ((((u64) dma_addr) >> 32)
+						& 0xffffffff)),
+					&ep->registers[
+						fpga_dma_bufaddr_highaddr_reg]
+					);
+				mmiowb();
+
+				this_buffer->addr = rd_salami;
+				this_buffer->dma_addr = dma_addr;
+				channel->rd_buffers[i] = this_buffer++;
+
+				iowrite32(rd_nbuffer++,
+					  &ep->registers[fpga_dma_bufno_reg]);
+
+				left_of_rd_salami -= bytebufsize;
+				rd_salami += bytebufsize;
+			}
+	}
+
+	if (!msg_buf_done) {
+		pr_err("xillybus: Corrupt IDT: No message buffer. "
+		       "Aborting.\n");
+		return -ENODEV;
+	}
+
+	return 0;
+
+memfail:
+	pr_err("xillybus: Failed to allocate write buffer memory. "
+	       "Aborting.\n");
+	return -ENOMEM;
+dmafail:
+	pr_err("xillybus: Failed to map DMA memory!. Aborting.\n");
+	return -ENOMEM;
+}
+
+static void xilly_scan_idt(struct xilly_endpoint *endpoint,
+			   struct xilly_idt_handle *idt_handle)
+{
+	int count = 0;
+	unsigned char *idt = endpoint->channels[1]->wr_buffers[0]->addr;
+	unsigned char *end_of_idt = idt + endpoint->idtlen - 4;
+	unsigned char *scan;
+	int len;
+
+	scan = idt;
+	idt_handle->idt = idt;
+
+	scan++; /* Skip version number */
+
+	while ((scan <= end_of_idt) && *scan) {
+		while ((scan <= end_of_idt) && *scan++)
+			/* Do nothing, just scan thru string */;
+		count++;
+	}
+
+	scan++;
+
+	if (scan > end_of_idt) {
+		pr_err("xillybus: IDT device name list overflow. "
+		       "Aborting.\n");
+		idt_handle->chandesc = NULL;
+		return;
+	} else
+		idt_handle->chandesc = scan;
+
+	len = endpoint->idtlen - (3 + ((int) (scan - idt)));
+
+	if (len & 0x03) {
+		idt_handle->chandesc = NULL;
+
+		pr_err("xillybus: Corrupt IDT device name list. "
+		       "Aborting.\n");
+	}
+
+	idt_handle->entries = len >> 2;
+
+	endpoint->num_channels = count;
+}
+
+static int xilly_obtain_idt(struct xilly_endpoint *endpoint)
+{
+	int rc = 0;
+	struct xilly_channel *channel;
+	unsigned char *version;
+
+	channel = endpoint->channels[1]; /* This should be generated ad-hoc */
+
+	channel->wr_sleepy = 1;
+	wmb(); /* Setting wr_sleepy must come before the command */
+
+	iowrite32(1 |
+		   (3 << 24), /* Opcode 3 for channel 0 = Send IDT */
+		   &endpoint->registers[fpga_buf_ctrl_reg]);
+	mmiowb(); /* Just to appear safe */
+
+	wait_event_interruptible_timeout(channel->wr_wait,
+					 (!channel->wr_sleepy),
+					 XILLY_TIMEOUT);
+
+	if (channel->wr_sleepy) {
+		pr_err("xillybus: Failed to obtain IDT. Aborting.\n");
+
+		if (endpoint->fatal_error)
+			return -EIO;
+
+		rc = -ENODEV;
+		return rc;
+	}
+
+	endpoint->ephw->hw_sync_sgl_for_cpu(
+		channel->endpoint,
+		channel->wr_buffers[0]->dma_addr,
+		channel->wr_buf_size,
+		DMA_FROM_DEVICE);
+
+	if (channel->wr_buffers[0]->end_offset != endpoint->idtlen) {
+		pr_err("xillybus: IDT length mismatch (%d != %d). "
+		       "Aborting.\n",
+		       channel->wr_buffers[0]->end_offset, endpoint->idtlen);
+		rc = -ENODEV;
+		return rc;
+	}
+
+	if (crc32_le(~0, channel->wr_buffers[0]->addr,
+		     endpoint->idtlen+1) != 0) {
+		pr_err("xillybus: IDT failed CRC check. Aborting.\n");
+		rc = -ENODEV;
+		return rc;
+	}
+
+	version = channel->wr_buffers[0]->addr;
+
+	/* Check version number. Accept anything below 0x82 for now. */
+	if (*version > 0x82) {
+		pr_err("xillybus: No support for IDT version 0x%02x. "
+		       "Maybe the xillybus driver needs an upgarde. "
+		       "Aborting.\n",
+		       (int) *version);
+		rc = -ENODEV;
+		return rc;
+	}
+
+	return 0; /* Success */
+}
+
+static ssize_t xillybus_read(struct file *filp, char __user *userbuf,
+			     size_t count, loff_t *f_pos)
+{
+	ssize_t rc;
+	unsigned long flags;
+	int bytes_done = 0;
+	int no_time_left = 0;
+	long deadline, left_to_sleep;
+	struct xilly_channel *channel = filp->private_data;
+
+	int empty, reached_eof, exhausted, ready;
+	/* Initializations are there only to silence warnings */
+
+	int howmany = 0, bufpos = 0, bufidx = 0, bufferdone = 0;
+	int waiting_bufidx;
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	deadline = jiffies + 1 + XILLY_RX_TIMEOUT;
+
+	rc = mutex_lock_interruptible(&channel->wr_mutex);
+
+	if (rc)
+		return rc;
+
+	rc = 0; /* Just to be clear about it. Compiler optimizes this out */
+
+	while (1) { /* Note that we may drop mutex within this loop */
+		int bytes_to_do = count - bytes_done;
+		spin_lock_irqsave(&channel->wr_spinlock, flags);
+
+		empty = channel->wr_empty;
+		ready = !empty || channel->wr_ready;
+
+		if (!empty) {
+			bufidx = channel->wr_host_buf_idx;
+			bufpos = channel->wr_host_buf_pos;
+			howmany = ((channel->wr_buffers[bufidx]->end_offset
+				    + 1) << channel->log2_element_size)
+				- bufpos;
+
+			/* Update wr_host_* to its post-operation state */
+			if (howmany > bytes_to_do) {
+				bufferdone = 0;
+
+				howmany = bytes_to_do;
+				channel->wr_host_buf_pos += howmany;
+			} else {
+				bufferdone = 1;
+
+				channel->wr_host_buf_pos = 0;
+
+				if (bufidx == channel->wr_fpga_buf_idx) {
+					channel->wr_empty = 1;
+					channel->wr_sleepy = 1;
+					channel->wr_ready = 0;
+				}
+
+				if (bufidx >= (channel->num_wr_buffers - 1))
+					channel->wr_host_buf_idx = 0;
+				else
+					channel->wr_host_buf_idx++;
+			}
+		}
+
+		/*
+		 * Marking our situation after the possible changes above,
+		 * for use after releasing the spinlock.
+		 *
+		 * empty = empty before change
+		 * exhasted = empty after possible change
+		 */
+
+		reached_eof = channel->wr_empty &&
+			(channel->wr_host_buf_idx == channel->wr_eof);
+		channel->wr_hangup = reached_eof;
+		exhausted = channel->wr_empty;
+		waiting_bufidx = channel->wr_host_buf_idx;
+
+		spin_unlock_irqrestore(&channel->wr_spinlock, flags);
+
+		if (!empty) { /* Go on, now without the spinlock */
+
+			if (bufpos == 0) /* Position zero means it's virgin */
+				channel->endpoint->ephw->hw_sync_sgl_for_cpu(
+					channel->endpoint,
+					channel->wr_buffers[bufidx]->dma_addr,
+					channel->wr_buf_size,
+					DMA_FROM_DEVICE);
+
+			if (copy_to_user(
+				    userbuf,
+				    channel->wr_buffers[bufidx]->addr
+				    + bufpos, howmany))
+				rc = -EFAULT;
+
+			userbuf += howmany;
+			bytes_done += howmany;
+
+			if (bufferdone) {
+				channel->endpoint->ephw->
+					hw_sync_sgl_for_device
+					(
+						channel->endpoint,
+						channel->wr_buffers[bufidx]->
+						dma_addr,
+						channel->wr_buf_size,
+						DMA_FROM_DEVICE);
+
+				/*
+				 * Tell FPGA the buffer is done with. It's an
+				 * atomic operation to the FPGA, so what
+				 * happens with other channels doesn't matter,
+				 * and the certain channel is protected with
+				 * the channel-specific mutex.
+				 */
+
+				iowrite32(1 | (channel->chan_num << 1)
+					   | (bufidx << 12),
+					   &channel->endpoint->registers[
+						   fpga_buf_ctrl_reg]);
+				mmiowb(); /* Just to appear safe */
+			}
+
+			if (rc) {
+				mutex_unlock(&channel->wr_mutex);
+				return rc;
+			}
+		}
+
+		/* This includes a zero-count return = EOF */
+		if ((bytes_done >= count) || reached_eof)
+			break;
+
+		if (!exhausted)
+			continue; /* More in RAM buffer(s)? Just go on. */
+
+		if ((bytes_done > 0) &&
+		    (no_time_left ||
+		     (channel->wr_synchronous && channel->wr_allow_partial)))
+			break;
+
+		/*
+		 * Nonblocking read: The "ready" flag tells us that the FPGA
+		 * has data to send. In non-blocking mode, if it isn't on,
+		 * just return. But if there is, we jump directly to the point
+		 * where we ask for the FPGA to send all it has, and wait
+		 * until that data arrives. So in a sense, we *do* block in
+		 * nonblocking mode, but only for a very short time.
+		 */
+
+		if (!no_time_left && (filp->f_flags & O_NONBLOCK)) {
+			if (bytes_done > 0)
+				break;
+
+			if (ready)
+				goto desperate;
+
+			bytes_done = -EAGAIN;
+			break;
+		}
+
+		if (!no_time_left || (bytes_done > 0)) {
+			/*
+			 * Note that in case of an element-misaligned read
+			 * request, offsetlimit will include the last element,
+			 * which will be partially read from.
+			 */
+			int offsetlimit = ((count - bytes_done) - 1) >>
+				channel->log2_element_size;
+			int buf_elements = channel->wr_buf_size >>
+				channel->log2_element_size;
+
+			/*
+			 * In synchronous mode, always send an offset limit.
+			 * Just don't send a value too big.
+			 */
+
+			if (channel->wr_synchronous) {
+				/* Don't request more than one buffer */
+				if (channel->wr_allow_partial &&
+				    (offsetlimit >= buf_elements))
+					offsetlimit = buf_elements - 1;
+
+				/* Don't request more than all buffers */
+				if (!channel->wr_allow_partial &&
+				    (offsetlimit >=
+				     (buf_elements * channel->num_wr_buffers)))
+					offsetlimit = buf_elements *
+						channel->num_wr_buffers - 1;
+			}
+
+			/*
+			 * In asynchronous mode, force early flush of a buffer
+			 * only if that will allow returning a full count. The
+			 * "offsetlimit < ( ... )" rather than "<=" excludes
+			 * requesting a full buffer, which would obviously
+			 * cause a buffer transmission anyhow
+			 */
+
+			if (channel->wr_synchronous ||
+			    (offsetlimit < (buf_elements - 1))) {
+
+				mutex_lock(&channel->endpoint->register_mutex);
+
+				iowrite32(offsetlimit,
+					  &channel->endpoint->registers[
+						  fpga_buf_offset_reg]);
+				mmiowb();
+
+				iowrite32(1 | (channel->chan_num << 1) |
+					   (2 << 24) |  /* 2 = offset limit */
+					   (waiting_bufidx << 12),
+					   &channel->endpoint->registers[
+						   fpga_buf_ctrl_reg]);
+
+				mmiowb(); /* Just to appear safe */
+
+				mutex_unlock(&channel->endpoint->
+					     register_mutex);
+			}
+
+		}
+
+		/*
+		 * If partial completion is disallowed, there is no point in
+		 * timeout sleeping. Neither if no_time_left is set and
+		 * there's no data.
+		 */
+
+		if (!channel->wr_allow_partial ||
+		    (no_time_left && (bytes_done == 0))) {
+
+			/*
+			 * This do-loop will run more than once if another
+			 * thread reasserted wr_sleepy before we got the mutex
+			 * back, so we try again.
+			 */
+
+			do {
+				mutex_unlock(&channel->wr_mutex);
+
+				if (wait_event_interruptible(
+					    channel->wr_wait,
+					    (!channel->wr_sleepy)))
+					goto interrupted;
+
+				if (mutex_lock_interruptible(
+					    &channel->wr_mutex))
+					goto interrupted;
+			} while (channel->wr_sleepy);
+
+			continue;
+
+interrupted: /* Mutex is not held if got here */
+			if (channel->endpoint->fatal_error)
+				return -EIO;
+			if (bytes_done)
+				return bytes_done;
+			if (filp->f_flags & O_NONBLOCK)
+				return -EAGAIN; /* Don't admit snoozing */
+			return -EINTR;
+		}
+
+		left_to_sleep = deadline - ((long) jiffies);
+
+		/*
+		 * If our time is out, skip the waiting. We may miss wr_sleepy
+		 * being deasserted but hey, almost missing the train is like
+		 * missing it.
+		 */
+
+		if (left_to_sleep > 0) {
+			left_to_sleep =
+				wait_event_interruptible_timeout(
+					channel->wr_wait,
+					(!channel->wr_sleepy),
+					left_to_sleep);
+
+			if (!channel->wr_sleepy)
+				continue;
+
+			if (left_to_sleep < 0) { /* Interrupt */
+				mutex_unlock(&channel->wr_mutex);
+				if (channel->endpoint->fatal_error)
+					return -EIO;
+				if (bytes_done)
+					return bytes_done;
+				return -EINTR;
+			}
+		}
+
+desperate:
+		no_time_left = 1; /* We're out of sleeping time. Desperate! */
+
+		if (bytes_done == 0) {
+			/*
+			 * Reaching here means that we allow partial return,
+			 * that we've run out of time, and that we have
+			 * nothing to return.
+			 * So tell the FPGA to send anything it has or gets.
+			 */
+
+			iowrite32(1 | (channel->chan_num << 1) |
+				   (3 << 24) |  /* Opcode 3, flush it all! */
+				   (waiting_bufidx << 12),
+				   &channel->endpoint->registers[
+					   fpga_buf_ctrl_reg]);
+			mmiowb(); /* Just to appear safe */
+		}
+
+		/*
+		 * Formally speaking, we should block for data at this point.
+		 * But to keep the code cleaner, we'll just finish the loop,
+		 * make the unlikely check for data, and then block at the
+		 * usual place.
+		 */
+	}
+
+	mutex_unlock(&channel->wr_mutex);
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	return bytes_done;
+}
+
+/*
+ * The timeout argument takes values as follows:
+ *  >0 : Flush with timeout
+ * ==0 : Flush, and wait idefinitely for the flush to complete
+ *  <0 : Autoflush: Flush only if there's a single buffer occupied
+ */
+
+static int xillybus_myflush(struct xilly_channel *channel, long timeout)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	int end_offset_plus1;
+	int bufidx, bufidx_minus1;
+	int i;
+	int empty;
+	int new_rd_host_buf_pos;
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+	rc = mutex_lock_interruptible(&channel->rd_mutex);
+
+	if (rc)
+		return rc;
+
+	/*
+	 * Don't flush a closed channel. This can happen when the work queued
+	 * autoflush thread fires off after the file has closed. This is not
+	 * an error, just something to dismiss.
+	 */
+
+	if (!channel->rd_ref_count)
+		goto done;
+
+	bufidx = channel->rd_host_buf_idx;
+
+	bufidx_minus1 = (bufidx == 0) ? channel->num_rd_buffers - 1 : bufidx-1;
+
+	end_offset_plus1 = channel->rd_host_buf_pos >>
+		channel->log2_element_size;
+
+	new_rd_host_buf_pos = channel->rd_host_buf_pos -
+		(end_offset_plus1 << channel->log2_element_size);
+
+	/* Submit the current buffer if it's nonempty */
+	if (end_offset_plus1) {
+		unsigned char *tail = channel->rd_buffers[bufidx]->addr +
+			(end_offset_plus1 << channel->log2_element_size);
+
+		/* Copy  unflushed data, so we can put it in next buffer */
+		for (i = 0; i < new_rd_host_buf_pos; i++)
+			channel->rd_leftovers[i] = *tail++;
+
+		spin_lock_irqsave(&channel->rd_spinlock, flags);
+
+		/* Autoflush only if a single buffer is occupied */
+
+		if ((timeout < 0) &&
+		    (channel->rd_full ||
+		     (bufidx_minus1 != channel->rd_fpga_buf_idx))) {
+			spin_unlock_irqrestore(&channel->rd_spinlock, flags);
+			/*
+			 * A new work item may be queued by the ISR exactly
+			 * now, since the execution of a work item allows the
+			 * queuing of a new one while it's running.
+			 */
+			goto done;
+		}
+
+		/* The 4th element is never needed for data, so it's a flag */
+		channel->rd_leftovers[3] = (new_rd_host_buf_pos != 0);
+
+		/* Set up rd_full to reflect a certain moment's state */
+
+		if (bufidx == channel->rd_fpga_buf_idx)
+			channel->rd_full = 1;
+		spin_unlock_irqrestore(&channel->rd_spinlock, flags);
+
+		if (bufidx >= (channel->num_rd_buffers - 1))
+			channel->rd_host_buf_idx = 0;
+		else
+			channel->rd_host_buf_idx++;
+
+		channel->endpoint->ephw->hw_sync_sgl_for_device(
+			channel->endpoint,
+			channel->rd_buffers[bufidx]->dma_addr,
+			channel->rd_buf_size,
+			DMA_TO_DEVICE);
+
+		mutex_lock(&channel->endpoint->register_mutex);
+
+		iowrite32(end_offset_plus1 - 1,
+			  &channel->endpoint->registers[fpga_buf_offset_reg]);
+		mmiowb();
+
+		iowrite32((channel->chan_num << 1) | /* Channel ID */
+			   (2 << 24) |  /* Opcode 2, submit buffer */
+			   (bufidx << 12),
+			   &channel->endpoint->registers[fpga_buf_ctrl_reg]);
+		mmiowb(); /* Just to appear safe */
+
+		mutex_unlock(&channel->endpoint->register_mutex);
+	} else if (bufidx == 0)
+		bufidx = channel->num_rd_buffers - 1;
+	else
+		bufidx--;
+
+	channel->rd_host_buf_pos = new_rd_host_buf_pos;
+
+	if (timeout < 0)
+		goto done; /* Autoflush */
+
+
+	/*
+	 * bufidx is now the last buffer written to (or equal to
+	 * rd_fpga_buf_idx if buffer was never written to), and
+	 * channel->rd_host_buf_idx the one after it.
+	 *
+	 * If bufidx == channel->rd_fpga_buf_idx we're either empty or full.
+	 */
+
+	rc = 0;
+
+	while (1) { /* Loop waiting for draining of buffers */
+		spin_lock_irqsave(&channel->rd_spinlock, flags);
+
+		if (bufidx != channel->rd_fpga_buf_idx)
+			channel->rd_full = 1; /*
+					       * Not really full,
+					       * but needs waiting.
+					       */
+
+		empty = !channel->rd_full;
+
+		spin_unlock_irqrestore(&channel->rd_spinlock, flags);
+
+		if (empty)
+			break;
+
+		/*
+		 * Indefinite sleep with mutex taken. With data waiting for
+		 * flushing user should not be surprised if open() for write
+		 * sleeps.
+		 */
+		if (timeout == 0)
+			wait_event_interruptible(channel->rd_wait,
+						 (!channel->rd_full));
+
+		else if (wait_event_interruptible_timeout(
+				 channel->rd_wait,
+				 (!channel->rd_full),
+				 timeout) == 0) {
+			pr_warn("xillybus: "
+				"Timed out while flushing. "
+				"Output data may be lost.\n");
+
+			rc = -ETIMEDOUT;
+			break;
+		}
+
+		if (channel->rd_full) {
+			rc = -EINTR;
+			break;
+		}
+	}
+
+done:
+	mutex_unlock(&channel->rd_mutex);
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	return rc;
+}
+
+static int xillybus_flush(struct file *filp, fl_owner_t id)
+{
+	if (!(filp->f_mode & FMODE_WRITE))
+		return 0;
+
+	return xillybus_myflush(filp->private_data, HZ); /* 1 second timeout */
+}
+
+static void xillybus_autoflush(struct work_struct *work)
+{
+	struct delayed_work *workitem = container_of(
+		work, struct delayed_work, work);
+	struct xilly_channel *channel = container_of(
+		workitem, struct xilly_channel, rd_workitem);
+	int rc;
+
+	rc = xillybus_myflush(channel, -1);
+
+	if (rc == -EINTR)
+		pr_warn("xillybus: Autoflush failed because "
+			"work queue thread got a signal.\n");
+	else if (rc)
+		pr_err("xillybus: Autoflush failed under "
+		       "weird circumstances.\n");
+
+}
+
+static ssize_t xillybus_write(struct file *filp, const char __user *userbuf,
+			      size_t count, loff_t *f_pos)
+{
+	ssize_t rc;
+	unsigned long flags;
+	int bytes_done = 0;
+	struct xilly_channel *channel = filp->private_data;
+
+	int full, exhausted;
+	/* Initializations are there only to silence warnings */
+
+	int howmany = 0, bufpos = 0, bufidx = 0, bufferdone = 0;
+	int end_offset_plus1 = 0;
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	rc = mutex_lock_interruptible(&channel->rd_mutex);
+
+	if (rc)
+		return rc;
+
+	rc = 0; /* Just to be clear about it. Compiler optimizes this out */
+
+	while (1) {
+		int bytes_to_do = count - bytes_done;
+
+		spin_lock_irqsave(&channel->rd_spinlock, flags);
+
+		full = channel->rd_full;
+
+		if (!full) {
+			bufidx = channel->rd_host_buf_idx;
+			bufpos = channel->rd_host_buf_pos;
+			howmany = channel->rd_buf_size - bufpos;
+
+			/*
+			 * Update rd_host_* to its state after this operation.
+			 * count=0 means committing the buffer immediately,
+			 * which is like flushing, but not necessarily block.
+			 */
+
+			if ((howmany > bytes_to_do) &&
+			    (count ||
+			     ((bufpos >> channel->log2_element_size) == 0))) {
+				bufferdone = 0;
+
+				howmany = bytes_to_do;
+				channel->rd_host_buf_pos += howmany;
+			} else {
+				bufferdone = 1;
+
+				if (count) {
+					end_offset_plus1 =
+						channel->rd_buf_size >>
+						channel->log2_element_size;
+					channel->rd_host_buf_pos = 0;
+				} else {
+					unsigned char *tail;
+					int i;
+
+					end_offset_plus1 = bufpos >>
+						channel->log2_element_size;
+
+					channel->rd_host_buf_pos -=
+						end_offset_plus1 <<
+						channel->log2_element_size;
+
+					tail = channel->
+						rd_buffers[bufidx]->addr +
+						(end_offset_plus1 <<
+						 channel->log2_element_size);
+
+					for (i = 0;
+					     i < channel->rd_host_buf_pos;
+					     i++)
+						channel->rd_leftovers[i] =
+							*tail++;
+				}
+
+				if (bufidx == channel->rd_fpga_buf_idx)
+					channel->rd_full = 1;
+
+				if (bufidx >= (channel->num_rd_buffers - 1))
+					channel->rd_host_buf_idx = 0;
+				else
+					channel->rd_host_buf_idx++;
+			}
+		}
+
+		/*
+		 * Marking our situation after the possible changes above,
+		 * for use  after releasing the spinlock.
+		 *
+		 * full = full before change
+		 * exhasted = full after possible change
+		 */
+
+		exhausted = channel->rd_full;
+
+		spin_unlock_irqrestore(&channel->rd_spinlock, flags);
+
+		if (!full) { /* Go on, now without the spinlock */
+			unsigned char *head =
+				channel->rd_buffers[bufidx]->addr;
+			int i;
+
+			if ((bufpos == 0) || /* Zero means it's virgin */
+			    (channel->rd_leftovers[3] != 0)) {
+				channel->endpoint->ephw->hw_sync_sgl_for_cpu(
+					channel->endpoint,
+					channel->rd_buffers[bufidx]->dma_addr,
+					channel->rd_buf_size,
+					DMA_TO_DEVICE);
+
+				/* Virgin, but leftovers are due */
+				for (i = 0; i < bufpos; i++)
+					*head++ = channel->rd_leftovers[i];
+
+				channel->rd_leftovers[3] = 0; /* Clear flag */
+			}
+
+			if (copy_from_user(
+				    channel->rd_buffers[bufidx]->addr + bufpos,
+				    userbuf, howmany))
+				rc = -EFAULT;
+
+			userbuf += howmany;
+			bytes_done += howmany;
+
+			if (bufferdone) {
+				channel->endpoint->ephw->
+					hw_sync_sgl_for_device(
+						channel->endpoint,
+						channel->rd_buffers[bufidx]->
+						dma_addr,
+						channel->rd_buf_size,
+						DMA_TO_DEVICE);
+
+				mutex_lock(&channel->endpoint->register_mutex);
+
+				iowrite32(end_offset_plus1 - 1,
+					  &channel->endpoint->registers[
+						  fpga_buf_offset_reg]);
+				mmiowb();
+				iowrite32((channel->chan_num << 1) |
+					   (2 << 24) |  /* 2 = submit buffer */
+					   (bufidx << 12),
+					   &channel->endpoint->registers[
+						   fpga_buf_ctrl_reg]);
+				mmiowb(); /* Just to appear safe */
+
+				mutex_unlock(&channel->endpoint->
+					     register_mutex);
+
+				channel->rd_leftovers[3] =
+					(channel->rd_host_buf_pos != 0);
+			}
+
+			if (rc) {
+				mutex_unlock(&channel->rd_mutex);
+
+				if (channel->endpoint->fatal_error)
+					return -EIO;
+
+				if (!channel->rd_synchronous)
+					queue_delayed_work(
+						xillybus_wq,
+						&channel->rd_workitem,
+						XILLY_RX_TIMEOUT);
+
+				return rc;
+			}
+		}
+
+		if (bytes_done >= count)
+			break;
+
+		if (!exhausted)
+			continue; /* If there's more space, just go on */
+
+		if ((bytes_done > 0) && channel->rd_allow_partial)
+			break;
+
+		/*
+		 * Indefinite sleep with mutex taken. With data waiting for
+		 * flushing, user should not be surprised if open() for write
+		 * sleeps.
+		 */
+
+		if (filp->f_flags & O_NONBLOCK) {
+			bytes_done = -EAGAIN;
+			break;
+		}
+
+		wait_event_interruptible(channel->rd_wait,
+					 (!channel->rd_full));
+
+		if (channel->rd_full) {
+			mutex_unlock(&channel->rd_mutex);
+
+			if (channel->endpoint->fatal_error)
+				return -EIO;
+
+			if (bytes_done)
+				return bytes_done;
+			return -EINTR;
+		}
+	}
+
+	mutex_unlock(&channel->rd_mutex);
+
+	if (!channel->rd_synchronous)
+		queue_delayed_work(xillybus_wq,
+				   &channel->rd_workitem,
+				   XILLY_RX_TIMEOUT);
+
+	if ((channel->rd_synchronous) && (bytes_done > 0)) {
+		rc = xillybus_myflush(filp->private_data, 0); /* No timeout */
+
+		if (rc && (rc != -EINTR))
+			return rc;
+	}
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	return bytes_done;
+}
+
+static int xillybus_open(struct inode *inode, struct file *filp)
+{
+	int rc = 0;
+	unsigned long flags;
+	int minor = iminor(inode);
+	int major = imajor(inode);
+	struct xilly_endpoint *ep_iter, *endpoint = NULL;
+	struct xilly_channel *channel;
+
+	mutex_lock(&ep_list_lock);
+
+	list_for_each_entry(ep_iter, &list_of_endpoints, ep_list) {
+		if ((ep_iter->major == major) &&
+		    (minor >= ep_iter->lowest_minor) &&
+		    (minor < (ep_iter->lowest_minor +
+			      ep_iter->num_channels))) {
+			endpoint = ep_iter;
+			break;
+		}
+	}
+	mutex_unlock(&ep_list_lock);
+
+	if (!endpoint) {
+		pr_err("xillybus: open() failed to find a device "
+		       "for major=%d and minor=%d\n", major, minor);
+		return -ENODEV;
+	}
+
+	if (endpoint->fatal_error)
+		return -EIO;
+
+	channel = endpoint->channels[1 + minor - endpoint->lowest_minor];
+	filp->private_data = channel;
+
+
+	/*
+	 * It gets complicated because:
+	 * 1. We don't want to take a mutex we don't have to
+	 * 2. We don't want to open one direction if the other will fail.
+	 */
+
+	if ((filp->f_mode & FMODE_READ) && (!channel->num_wr_buffers))
+		return -ENODEV;
+
+	if ((filp->f_mode & FMODE_WRITE) && (!channel->num_rd_buffers))
+		return -ENODEV;
+
+	if ((filp->f_mode & FMODE_READ) && (filp->f_flags & O_NONBLOCK) &&
+	    (channel->wr_synchronous || !channel->wr_allow_partial ||
+	     !channel->wr_supports_nonempty)) {
+		pr_err("xillybus: open() failed: "
+		       "O_NONBLOCK not allowed for read on this device\n");
+		return -ENODEV;
+	}
+
+	if ((filp->f_mode & FMODE_WRITE) && (filp->f_flags & O_NONBLOCK) &&
+	    (channel->rd_synchronous || !channel->rd_allow_partial)) {
+		pr_err("xillybus: open() failed: "
+		       "O_NONBLOCK not allowed for write on this device\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Note: open() may block on getting mutexes despite O_NONBLOCK.
+	 * This shouldn't occur normally, since multiple open of the same
+	 * file descriptor is almost always prohibited anyhow
+	 * (*_exclusive_open is normally set in real-life systems).
+	 */
+
+	if (filp->f_mode & FMODE_READ) {
+		rc = mutex_lock_interruptible(&channel->wr_mutex);
+		if (rc)
+			return rc;
+	}
+
+	if (filp->f_mode & FMODE_WRITE) {
+		rc = mutex_lock_interruptible(&channel->rd_mutex);
+		if (rc)
+			goto unlock_wr;
+	}
+
+	if ((filp->f_mode & FMODE_READ) &&
+	    (channel->wr_ref_count != 0) &&
+	    (channel->wr_exclusive_open)) {
+		rc = -EBUSY;
+		goto unlock;
+	}
+
+	if ((filp->f_mode & FMODE_WRITE) &&
+	    (channel->rd_ref_count != 0) &&
+	    (channel->rd_exclusive_open)) {
+		rc = -EBUSY;
+		goto unlock;
+	}
+
+
+	if (filp->f_mode & FMODE_READ) {
+		if (channel->wr_ref_count == 0) { /* First open of file */
+			/* Move the host to first buffer */
+			spin_lock_irqsave(&channel->wr_spinlock, flags);
+			channel->wr_host_buf_idx = 0;
+			channel->wr_host_buf_pos = 0;
+			channel->wr_fpga_buf_idx = -1;
+			channel->wr_empty = 1;
+			channel->wr_ready = 0;
+			channel->wr_sleepy = 1;
+			channel->wr_eof = -1;
+			channel->wr_hangup = 0;
+
+			spin_unlock_irqrestore(&channel->wr_spinlock, flags);
+
+			iowrite32(1 | (channel->chan_num << 1) |
+				  (4 << 24) |  /* Opcode 4, open channel */
+				  ((channel->wr_synchronous & 1) << 23),
+				  &channel->endpoint->registers[
+					  fpga_buf_ctrl_reg]);
+			mmiowb(); /* Just to appear safe */
+		}
+
+		channel->wr_ref_count++;
+	}
+
+	if (filp->f_mode & FMODE_WRITE) {
+		if (channel->rd_ref_count == 0) { /* First open of file */
+			/* Move the host to first buffer */
+			spin_lock_irqsave(&channel->rd_spinlock, flags);
+			channel->rd_host_buf_idx = 0;
+			channel->rd_host_buf_pos = 0;
+			channel->rd_leftovers[3] = 0; /* No leftovers. */
+			channel->rd_fpga_buf_idx = channel->num_rd_buffers - 1;
+			channel->rd_full = 0;
+
+			spin_unlock_irqrestore(&channel->rd_spinlock, flags);
+
+			iowrite32((channel->chan_num << 1) |
+				  (4 << 24),   /* Opcode 4, open channel */
+				  &channel->endpoint->registers[
+					  fpga_buf_ctrl_reg]);
+			mmiowb(); /* Just to appear safe */
+		}
+
+		channel->rd_ref_count++;
+	}
+
+unlock:
+	if (filp->f_mode & FMODE_WRITE)
+		mutex_unlock(&channel->rd_mutex);
+unlock_wr:
+	if (filp->f_mode & FMODE_READ)
+		mutex_unlock(&channel->wr_mutex);
+
+	if (!rc && (!channel->seekable))
+		return nonseekable_open(inode, filp);
+
+	return rc;
+}
+
+static int xillybus_release(struct inode *inode, struct file *filp)
+{
+	int rc;
+	unsigned long flags;
+	struct xilly_channel *channel = filp->private_data;
+
+	int buf_idx;
+	int eof;
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	if (filp->f_mode & FMODE_WRITE) {
+		rc = mutex_lock_interruptible(&channel->rd_mutex);
+
+		if (rc) {
+			pr_warn("xillybus: Failed to close file. "
+				"Hardware left in messy state.\n");
+			return rc;
+		}
+
+		channel->rd_ref_count--;
+
+		if (channel->rd_ref_count == 0) {
+
+			/*
+			 * We rely on the kernel calling flush()
+			 * before we get here.
+			 */
+
+			iowrite32((channel->chan_num << 1) | /* Channel ID */
+				  (5 << 24),  /* Opcode 5, close channel */
+				  &channel->endpoint->registers[
+					  fpga_buf_ctrl_reg]);
+			mmiowb(); /* Just to appear safe */
+		}
+		mutex_unlock(&channel->rd_mutex);
+	}
+
+	if (filp->f_mode & FMODE_READ) {
+		rc = mutex_lock_interruptible(&channel->wr_mutex);
+		if (rc) {
+			pr_warn("xillybus: Failed to close file. "
+				"Hardware left in messy state.\n");
+			return rc;
+		}
+
+		channel->wr_ref_count--;
+
+		if (channel->wr_ref_count == 0) {
+
+			iowrite32(1 | (channel->chan_num << 1) |
+				   (5 << 24),  /* Opcode 5, close channel */
+				   &channel->endpoint->registers[
+					   fpga_buf_ctrl_reg]);
+			mmiowb(); /* Just to appear safe */
+
+			/*
+			 * This is crazily cautious: We make sure that not
+			 * only that we got an EOF (be it because we closed
+			 * the channel or because of a user's EOF), but verify
+			 * that it's one beyond the last buffer arrived, so
+			 * we have no leftover buffers pending before wrapping
+			 * up (which can only happen in asynchronous channels,
+			 * BTW)
+			 */
+
+			while (1) {
+				spin_lock_irqsave(&channel->wr_spinlock,
+						  flags);
+				buf_idx = channel->wr_fpga_buf_idx;
+				eof = channel->wr_eof;
+				channel->wr_sleepy = 1;
+				spin_unlock_irqrestore(&channel->wr_spinlock,
+						       flags);
+
+				/*
+				 * Check if eof points at the buffer after
+				 * the last one the FPGA submitted. Note that
+				 * no EOF is marked by negative eof.
+				 */
+
+				buf_idx++;
+				if (buf_idx == channel->num_wr_buffers)
+					buf_idx = 0;
+
+				if (buf_idx == eof)
+					break;
+
+				/*
+				 * Steal extra 100 ms if awaken by interrupt.
+				 * This is a simple workaround for an
+				 * interrupt pending when entering, which would
+				 * otherwise result in declaring the hardware
+				 * non-responsive.
+				 */
+
+				if (wait_event_interruptible(
+					    channel->wr_wait,
+					    (!channel->wr_sleepy)))
+					msleep(100);
+
+				if (channel->wr_sleepy) {
+					mutex_unlock(&channel->wr_mutex);
+					pr_warn("xillybus: Hardware failed to "
+						"respond to close command, "
+						"therefore left in "
+						"messy state.\n");
+					return -EINTR;
+				}
+			}
+		}
+
+		mutex_unlock(&channel->wr_mutex);
+	}
+
+	return 0;
+}
+static loff_t xillybus_llseek(struct file *filp, loff_t offset, int whence)
+{
+	struct xilly_channel *channel = filp->private_data;
+	loff_t pos = filp->f_pos;
+	int rc = 0;
+
+	/*
+	 * Take both mutexes not allowing interrupts, since it seems like
+	 * common applications don't expect an -EINTR here. Besides, multiple
+	 * access to a single file desriptor on seekable devices is a mess
+	 * anyhow.
+	 */
+
+	if (channel->endpoint->fatal_error)
+		return -EIO;
+
+	mutex_lock(&channel->wr_mutex);
+	mutex_lock(&channel->rd_mutex);
+
+	switch (whence) {
+	case 0:
+		pos = offset;
+		break;
+	case 1:
+		pos += offset;
+		break;
+	case 2:
+		pos = offset; /* Going to the end => to the beginning */
+		break;
+	default:
+		rc = -EINVAL;
+		goto end;
+	}
+
+	/* In any case, we must finish on an element boundary */
+	if (pos & ((1 << channel->log2_element_size) - 1)) {
+		rc = -EINVAL;
+		goto end;
+	}
+
+	mutex_lock(&channel->endpoint->register_mutex);
+
+	iowrite32(pos >> channel->log2_element_size,
+		  &channel->endpoint->registers[fpga_buf_offset_reg]);
+	mmiowb();
+	iowrite32((channel->chan_num << 1) |
+		  (6 << 24),  /* Opcode 6, set address */
+		  &channel->endpoint->registers[fpga_buf_ctrl_reg]);
+	mmiowb(); /* Just to appear safe */
+
+	mutex_unlock(&channel->endpoint->register_mutex);
+
+end:
+	mutex_unlock(&channel->rd_mutex);
+	mutex_unlock(&channel->wr_mutex);
+
+	if (rc) /* Return error after releasing mutexes */
+		return rc;
+
+	filp->f_pos = pos;
+
+	/*
+	 * Since seekable devices are allowed only when the channel is
+	 * synchronous, we assume that there is no data pending in either
+	 * direction (which holds true as long as no concurrent access on the
+	 * file descriptor takes place).
+	 * The only thing we may need to throw away is leftovers from partial
+	 * write() flush.
+	 */
+
+	channel->rd_leftovers[3] = 0;
+
+	return pos;
+}
+
+static unsigned int xillybus_poll(struct file *filp, poll_table *wait)
+{
+	struct xilly_channel *channel = filp->private_data;
+	unsigned int mask = 0;
+	unsigned long flags;
+
+	poll_wait(filp, &channel->endpoint->ep_wait, wait);
+
+	/*
+	 * poll() won't play ball regarding read() channels which
+	 * aren't asynchronous and support the nonempty message. Allowing
+	 * that will create situations where data has been delivered at
+	 * the FPGA, and users expecting select() to wake up, which it may
+	 * not.
+	 */
+
+	if (!channel->wr_synchronous && channel->wr_supports_nonempty) {
+		poll_wait(filp, &channel->wr_wait, wait);
+		poll_wait(filp, &channel->wr_ready_wait, wait);
+
+		spin_lock_irqsave(&channel->wr_spinlock, flags);
+		if (!channel->wr_empty || channel->wr_ready)
+			mask |= POLLIN | POLLRDNORM;
+
+		if (channel->wr_hangup)
+			/*
+			 * Not POLLHUP, because its behavior is in the
+			 * mist, and POLLIN does what we want: Wake up
+			 * the read file descriptor so it sees EOF.
+			 */
+			mask |=  POLLIN | POLLRDNORM;
+		spin_unlock_irqrestore(&channel->wr_spinlock, flags);
+	}
+
+	/*
+	 * If partial data write is disallowed on a write() channel,
+	 * it's pointless to ever signal OK to write, because is could
+	 * block despite some space being available.
+	 */
+
+	if (channel->rd_allow_partial) {
+		poll_wait(filp, &channel->rd_wait, wait);
+
+		spin_lock_irqsave(&channel->rd_spinlock, flags);
+		if (!channel->rd_full)
+			mask |= POLLOUT | POLLWRNORM;
+		spin_unlock_irqrestore(&channel->rd_spinlock, flags);
+	}
+
+	if (channel->endpoint->fatal_error)
+		mask |= POLLERR;
+
+	return mask;
+}
+
+static const struct file_operations xillybus_fops = {
+	.owner      = THIS_MODULE,
+	.read       = xillybus_read,
+	.write      = xillybus_write,
+	.open       = xillybus_open,
+	.flush      = xillybus_flush,
+	.release    = xillybus_release,
+	.llseek     = xillybus_llseek,
+	.poll       = xillybus_poll,
+};
+
+static int xillybus_init_chrdev(struct xilly_endpoint *endpoint,
+				const unsigned char *idt)
+{
+	int rc;
+	dev_t dev;
+	int devnum, i, minor, major;
+	char devname[48];
+	struct device *device;
+
+	rc = alloc_chrdev_region(&dev, 0, /* minor start */
+				 endpoint->num_channels,
+				 xillyname);
+
+	if (rc) {
+		pr_warn("xillybus: Failed to obtain major/minors");
+		goto error1;
+	}
+
+	endpoint->major = major = MAJOR(dev);
+	endpoint->lowest_minor = minor = MINOR(dev);
+
+	cdev_init(&endpoint->cdev, &xillybus_fops);
+	endpoint->cdev.owner = endpoint->ephw->owner;
+	rc = cdev_add(&endpoint->cdev, MKDEV(major, minor),
+		      endpoint->num_channels);
+	if (rc) {
+		pr_warn("xillybus: Failed to add cdev. Aborting.\n");
+		goto error2;
+	}
+
+	idt++;
+
+	for (i = minor, devnum = 0;
+	     devnum < endpoint->num_channels;
+	     devnum++, i++) {
+		snprintf(devname, sizeof(devname)-1, "xillybus_%s", idt);
+
+		devname[sizeof(devname)-1] = 0; /* Should never matter */
+
+		while (*idt++)
+			/* Skip to next */;
+
+		device = device_create(xillybus_class,
+				       NULL,
+				       MKDEV(major, i),
+				       NULL,
+				       devname);
+
+		if (IS_ERR(device)) {
+			pr_warn("xillybus: Failed to create %s "
+				"device. Aborting.\n", devname);
+			goto error3;
+		}
+	}
+
+	pr_info("xillybus: Created %d device files.\n",
+		endpoint->num_channels);
+	return 0; /* succeed */
+
+error3:
+	devnum--; i--;
+	for (; devnum >= 0; devnum--, i--)
+		device_destroy(xillybus_class, MKDEV(major, i));
+
+	cdev_del(&endpoint->cdev);
+error2:
+	unregister_chrdev_region(MKDEV(major, minor), endpoint->num_channels);
+error1:
+
+	return rc;
+}
+
+static void xillybus_cleanup_chrdev(struct xilly_endpoint *endpoint)
+{
+	int minor;
+
+	for (minor = endpoint->lowest_minor;
+	     minor < (endpoint->lowest_minor + endpoint->num_channels);
+	     minor++)
+		device_destroy(xillybus_class, MKDEV(endpoint->major, minor));
+	cdev_del(&endpoint->cdev);
+	unregister_chrdev_region(MKDEV(endpoint->major,
+				       endpoint->lowest_minor),
+				 endpoint->num_channels);
+
+	pr_info("xillybus: Removed %d device files.\n",
+		endpoint->num_channels);
+}
+
+
+struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev,
+					      struct device *dev,
+					      struct xilly_endpoint_hardware
+					      *ephw)
+{
+	struct xilly_endpoint *endpoint;
+
+	endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
+	if (!endpoint) {
+		pr_err("xillybus: Failed to allocate memory. Aborting.\n");
+		return NULL;
+	}
+
+	endpoint->pdev = pdev;
+	endpoint->dev = dev;
+	endpoint->ephw = ephw;
+	INIT_LIST_HEAD(&endpoint->cleanup.to_kfree);
+	INIT_LIST_HEAD(&endpoint->cleanup.to_pagefree);
+	INIT_LIST_HEAD(&endpoint->cleanup.to_unmap);
+	endpoint->msg_counter = 0x0b;
+	endpoint->failed_messages = 0;
+	endpoint->fatal_error = 0;
+
+	init_waitqueue_head(&endpoint->ep_wait);
+	mutex_init(&endpoint->register_mutex);
+
+	return endpoint;
+}
+EXPORT_SYMBOL(xillybus_init_endpoint);
+
+static int xilly_quiesce(struct xilly_endpoint *endpoint)
+{
+	endpoint->idtlen = -1;
+	wmb(); /* Make sure idtlen is set before sending command */
+	iowrite32((u32) (endpoint->dma_using_dac & 0x0001),
+		  &endpoint->registers[fpga_dma_control_reg]);
+	mmiowb();
+
+	wait_event_interruptible_timeout(endpoint->ep_wait,
+					 (endpoint->idtlen >= 0),
+					 XILLY_TIMEOUT);
+
+	if (endpoint->idtlen < 0) {
+		pr_err("xillybus: Failed to quiesce the device on "
+		       "exit. Quitting while leaving a mess.\n");
+		return -ENODEV;
+	}
+	return 0; /* Success */
+}
+
+int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
+{
+	int rc = 0;
+
+	struct xilly_cleanup tmpmem;
+	int idtbuffersize = (1 << PAGE_SHIFT);
+
+	/*
+	 * The bogus IDT is used during bootstrap for allocating the initial
+	 * message buffer, and then the message buffer and space for the IDT
+	 * itself. The initial message buffer is of a single page's size, but
+	 * it's soon replaced with a more modest one (and memory is freed).
+	 */
+
+	unsigned char bogus_idt[8] = { 1, 224, (PAGE_SHIFT)-2, 0,
+				       3, 192, PAGE_SHIFT, 0 };
+	struct xilly_idt_handle idt_handle;
+
+	INIT_LIST_HEAD(&tmpmem.to_kfree);
+	INIT_LIST_HEAD(&tmpmem.to_pagefree);
+	INIT_LIST_HEAD(&tmpmem.to_unmap);
+
+	/*
+	 * Writing the value 0x00000001 to Endianess register signals which
+	 * endianess this processor is using, so the FPGA can swap words as
+	 * necessary.
+	 */
+
+	iowrite32(1, &endpoint->registers[fpga_endian_reg]);
+	mmiowb(); /* Writes below are affected by the one above. */
+
+	/* Bootstrap phase I: Allocate temporary message buffer */
+
+	endpoint->num_channels = 0;
+
+	rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 1);
+
+	if (rc)
+		goto failed_buffers;
+
+	/* Clear the message subsystem (and counter in particular) */
+	iowrite32(0x04, &endpoint->registers[fpga_msg_ctrl_reg]);
+	mmiowb();
+
+	endpoint->idtlen = -1;
+
+	smp_wmb();
+
+	/*
+	 * Set DMA 32/64 bit mode, quiesce the device (?!) and get IDT
+	 * buffer size.
+	 */
+	iowrite32((u32) (endpoint->dma_using_dac & 0x0001),
+		   &endpoint->registers[fpga_dma_control_reg]);
+	mmiowb();
+
+	wait_event_interruptible_timeout(endpoint->ep_wait,
+					 (endpoint->idtlen >= 0),
+					 XILLY_TIMEOUT);
+
+	if (endpoint->idtlen < 0) {
+		pr_err("xillybus: No response from FPGA. Aborting.\n");
+		rc = -ENODEV;
+		goto failed_quiesce;
+	}
+
+	/* Enable DMA */
+	iowrite32((u32) (0x0002 | (endpoint->dma_using_dac & 0x0001)),
+		   &endpoint->registers[fpga_dma_control_reg]);
+	mmiowb();
+
+	/* Bootstrap phase II: Allocate buffer for IDT and obtain it */
+	while (endpoint->idtlen >= idtbuffersize) {
+		idtbuffersize *= 2;
+		bogus_idt[6]++;
+	}
+
+	endpoint->num_channels = 1;
+
+	rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 2);
+
+	if (rc)
+		goto failed_idt;
+
+	smp_wmb();
+
+	rc = xilly_obtain_idt(endpoint);
+
+	if (rc)
+		goto failed_idt;
+
+	xilly_scan_idt(endpoint, &idt_handle);
+
+	if (!idt_handle.chandesc) {
+		rc = -ENODEV;
+		goto failed_idt;
+	}
+	/* Bootstrap phase III: Allocate buffers according to IDT */
+
+	rc = xilly_setupchannels(endpoint,
+				 &endpoint->cleanup,
+				 idt_handle.chandesc,
+				 idt_handle.entries);
+
+	if (rc)
+		goto failed_idt;
+
+	smp_wmb(); /* mutex_lock below should suffice, but won't hurt.*/
+
+	/*
+	 * endpoint is now completely configured. We put it on the list
+	 * available to open() before registering the char device(s)
+	 */
+
+	mutex_lock(&ep_list_lock);
+	list_add_tail(&endpoint->ep_list, &list_of_endpoints);
+	mutex_unlock(&ep_list_lock);
+
+	rc = xillybus_init_chrdev(endpoint, idt_handle.idt);
+
+	if (rc)
+		goto failed_chrdevs;
+
+	xillybus_do_cleanup(&tmpmem, endpoint);
+
+	return 0;
+
+failed_chrdevs:
+	mutex_lock(&ep_list_lock);
+	list_del(&endpoint->ep_list);
+	mutex_unlock(&ep_list_lock);
+
+failed_idt:
+	/* Quiesce the device. Now it's serious to do it */
+	rc = xilly_quiesce(endpoint);
+
+	if (rc)
+		return rc; /* FPGA may still DMA, so no release */
+
+	flush_workqueue(xillybus_wq);
+failed_quiesce:
+failed_buffers:
+	xillybus_do_cleanup(&tmpmem, endpoint);
+
+	return rc;
+}
+EXPORT_SYMBOL(xillybus_endpoint_discovery);
+
+void xillybus_endpoint_remove(struct xilly_endpoint *endpoint)
+{
+	xillybus_cleanup_chrdev(endpoint);
+
+	mutex_lock(&ep_list_lock);
+	list_del(&endpoint->ep_list);
+	mutex_unlock(&ep_list_lock);
+
+	xilly_quiesce(endpoint);
+
+	/*
+	 * Flushing is done upon endpoint release to prevent access to memory
+	 * just about to be released. This makes the quiesce complete.
+	 */
+	flush_workqueue(xillybus_wq);
+}
+EXPORT_SYMBOL(xillybus_endpoint_remove);
+
+static int __init xillybus_init(void)
+{
+	int rc = 0;
+
+	mutex_init(&ep_list_lock);
+
+	xillybus_class = class_create(THIS_MODULE, xillyname);
+	if (IS_ERR(xillybus_class)) {
+		rc = PTR_ERR(xillybus_class);
+		pr_warn("xillybus: Failed to register class xillybus\n");
+
+		return rc;
+	}
+
+	xillybus_wq = alloc_workqueue(xillyname, 0, 0);
+
+	return 0; /* Success */
+}
+
+static void __exit xillybus_exit(void)
+{
+	/* flush_workqueue() was called for each endpoint released */
+	destroy_workqueue(xillybus_wq);
+
+	class_destroy(xillybus_class);
+}
+
+module_init(xillybus_init);
+module_exit(xillybus_exit);
diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c
new file mode 100644
index 0000000..92c2931
--- /dev/null
+++ b/drivers/staging/xillybus/xillybus_of.c
@@ -0,0 +1,212 @@
+/*
+ * linux/drivers/misc/xillybus_of.c
+ *
+ * Copyright 2011 Xillybus Ltd, http://xillybus.com
+ *
+ * Driver for the Xillybus FPGA/host framework using Open Firmware.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include "xillybus.h"
+
+MODULE_DESCRIPTION("Xillybus driver for Open Firmware");
+MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
+MODULE_VERSION("1.06");
+MODULE_ALIAS("xillybus_of");
+MODULE_LICENSE("GPL v2");
+
+static const char xillyname[] = "xillybus_of";
+
+/* Match table for of_platform binding */
+static struct of_device_id xillybus_of_match[] = {
+	{ .compatible = "xlnx,xillybus-1.00.a", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, xillybus_of_match);
+
+static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint *ep,
+					     dma_addr_t dma_handle,
+					     size_t size,
+					     int direction)
+{
+	dma_sync_single_for_cpu(ep->dev, dma_handle, size, direction);
+}
+
+static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint *ep,
+						dma_addr_t dma_handle,
+						size_t size,
+						int direction)
+{
+	dma_sync_single_for_device(ep->dev, dma_handle, size, direction);
+}
+
+static dma_addr_t xilly_map_single_of(struct xilly_cleanup *mem,
+				      struct xilly_endpoint *ep,
+				      void *ptr,
+				      size_t size,
+				      int direction
+	)
+{
+
+	dma_addr_t addr = 0;
+	struct xilly_dma *this;
+
+	this = kmalloc(sizeof(struct xilly_dma), GFP_KERNEL);
+	if (!this)
+		return 0;
+
+	addr = dma_map_single(ep->dev, ptr, size, direction);
+	this->direction = direction;
+
+	if (dma_mapping_error(ep->dev, addr)) {
+		kfree(this);
+		return 0;
+	}
+
+	this->dma_addr = addr;
+	this->dev = ep->dev;
+	this->size = size;
+
+	list_add_tail(&this->node, &mem->to_unmap);
+
+	return addr;
+}
+
+static void xilly_unmap_single_of(struct xilly_dma *entry)
+{
+	dma_unmap_single(entry->dev,
+			 entry->dma_addr,
+			 entry->size,
+			 entry->direction);
+}
+
+static struct xilly_endpoint_hardware of_hw = {
+	.owner = THIS_MODULE,
+	.hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of,
+	.hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of,
+	.map_single = xilly_map_single_of,
+	.unmap_single = xilly_unmap_single_of
+};
+
+static int xilly_drv_probe(struct platform_device *op)
+{
+	struct device *dev = &op->dev;
+	struct xilly_endpoint *endpoint;
+	int rc = 0;
+	int irq;
+
+	endpoint = xillybus_init_endpoint(NULL, dev, &of_hw);
+
+	if (!endpoint)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, endpoint);
+
+	rc = of_address_to_resource(dev->of_node, 0, &endpoint->res);
+	if (rc) {
+		pr_warn("xillybus: Failed to obtain device tree "
+			"resource\n");
+		goto failed_request_regions;
+	}
+
+	if  (!request_mem_region(endpoint->res.start,
+				 resource_size(&endpoint->res), xillyname)) {
+		pr_err("xillybus: request_mem_region failed. Aborting.\n");
+		rc = -EBUSY;
+		goto failed_request_regions;
+	}
+
+	endpoint->registers = of_iomap(dev->of_node, 0);
+
+	if (!endpoint->registers) {
+		pr_err("xillybus: Failed to map I/O memory. Aborting.\n");
+		goto failed_iomap0;
+	}
+
+	irq = irq_of_parse_and_map(dev->of_node, 0);
+
+	rc = request_irq(irq, xillybus_isr, 0, xillyname, endpoint);
+
+	if (rc) {
+		pr_err("xillybus: Failed to register IRQ handler. "
+		       "Aborting.\n");
+		rc = -ENODEV;
+		goto failed_register_irq;
+	}
+
+	rc = xillybus_endpoint_discovery(endpoint);
+
+	if (!rc)
+		return 0;
+
+	free_irq(irq, endpoint);
+
+failed_register_irq:
+	iounmap(endpoint->registers);
+failed_iomap0:
+	release_mem_region(endpoint->res.start,
+			   resource_size(&endpoint->res));
+
+failed_request_regions:
+	xillybus_do_cleanup(&endpoint->cleanup, endpoint);
+
+	kfree(endpoint);
+	return rc;
+}
+
+static int xilly_drv_remove(struct platform_device *op)
+{
+	struct device *dev = &op->dev;
+	struct xilly_endpoint *endpoint = dev_get_drvdata(dev);
+	int irq = irq_of_parse_and_map(dev->of_node, 0);
+
+	xillybus_endpoint_remove(endpoint);
+
+	free_irq(irq, endpoint);
+
+	iounmap(endpoint->registers);
+	release_mem_region(endpoint->res.start,
+			   resource_size(&endpoint->res));
+
+	xillybus_do_cleanup(&endpoint->cleanup, endpoint);
+
+	kfree(endpoint);
+
+	return 0;
+}
+
+static struct platform_driver xillybus_platform_driver = {
+	.probe = xilly_drv_probe,
+	.remove = xilly_drv_remove,
+	.driver = {
+		.name = xillyname,
+		.owner = THIS_MODULE,
+		.of_match_table = xillybus_of_match,
+	},
+};
+
+static int __init xillybus_of_init(void)
+{
+	return platform_driver_register(&xillybus_platform_driver);
+}
+
+static void __exit xillybus_of_exit(void)
+{
+	platform_driver_unregister(&xillybus_platform_driver);
+}
+
+module_init(xillybus_of_init);
+module_exit(xillybus_of_exit);
diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c
new file mode 100644
index 0000000..6701365
--- /dev/null
+++ b/drivers/staging/xillybus/xillybus_pcie.c
@@ -0,0 +1,262 @@
+/*
+ * linux/drivers/misc/xillybus_pcie.c
+ *
+ * Copyright 2011 Xillybus Ltd, http://xillybus.com
+ *
+ * Driver for the Xillybus FPGA/host framework using PCI Express.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include "xillybus.h"
+
+MODULE_DESCRIPTION("Xillybus driver for PCIe");
+MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
+MODULE_VERSION("1.06");
+MODULE_ALIAS("xillybus_pcie");
+MODULE_LICENSE("GPL v2");
+
+#define PCI_DEVICE_ID_XILLYBUS		0xebeb
+
+#define PCI_VENDOR_ID_ALTERA		0x1172
+#define PCI_VENDOR_ID_ACTEL		0x11aa
+#define PCI_VENDOR_ID_LATTICE		0x1204
+
+static const char xillyname[] = "xillybus_pcie";
+
+static DEFINE_PCI_DEVICE_TABLE(xillyids) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)},
+	{PCI_DEVICE(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_XILLYBUS)},
+	{ /* End: all zeroes */ }
+};
+
+static int xilly_pci_direction(int direction)
+{
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		return PCI_DMA_TODEVICE;
+	case DMA_FROM_DEVICE:
+		return PCI_DMA_FROMDEVICE;
+	default:
+		return PCI_DMA_BIDIRECTIONAL;
+	}
+}
+
+static void xilly_dma_sync_single_for_cpu_pci(struct xilly_endpoint *ep,
+					      dma_addr_t dma_handle,
+					      size_t size,
+					      int direction)
+{
+	pci_dma_sync_single_for_cpu(ep->pdev,
+				    dma_handle,
+				    size,
+				    xilly_pci_direction(direction));
+}
+
+static void xilly_dma_sync_single_for_device_pci(struct xilly_endpoint *ep,
+						 dma_addr_t dma_handle,
+						 size_t size,
+						 int direction)
+{
+	pci_dma_sync_single_for_device(ep->pdev,
+				       dma_handle,
+				       size,
+				       xilly_pci_direction(direction));
+}
+
+/*
+ * Map either through the PCI DMA mapper or the non_PCI one. Behind the
+ * scenes exactly the same functions are called with the same parameters,
+ * but that can change.
+ */
+
+static dma_addr_t xilly_map_single_pci(struct xilly_cleanup *mem,
+				       struct xilly_endpoint *ep,
+				       void *ptr,
+				       size_t size,
+				       int direction
+	)
+{
+
+	dma_addr_t addr = 0;
+	struct xilly_dma *this;
+	int pci_direction;
+
+	this = kmalloc(sizeof(struct xilly_dma), GFP_KERNEL);
+	if (!this)
+		return 0;
+
+	pci_direction = xilly_pci_direction(direction);
+	addr = pci_map_single(ep->pdev, ptr, size, pci_direction);
+	this->direction = pci_direction;
+
+	if (pci_dma_mapping_error(ep->pdev, addr)) {
+		kfree(this);
+		return 0;
+	}
+
+	this->dma_addr = addr;
+	this->pdev = ep->pdev;
+	this->size = size;
+
+	list_add_tail(&this->node, &mem->to_unmap);
+
+	return addr;
+}
+
+static void xilly_unmap_single_pci(struct xilly_dma *entry)
+{
+	pci_unmap_single(entry->pdev,
+			 entry->dma_addr,
+			 entry->size,
+			 entry->direction);
+}
+
+static struct xilly_endpoint_hardware pci_hw = {
+	.owner = THIS_MODULE,
+	.hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_pci,
+	.hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_pci,
+	.map_single = xilly_map_single_pci,
+	.unmap_single = xilly_unmap_single_pci
+};
+
+static int xilly_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct xilly_endpoint *endpoint;
+	int rc = 0;
+
+	endpoint = xillybus_init_endpoint(pdev, NULL, &pci_hw);
+
+	if (!endpoint)
+		return -ENOMEM;
+
+	pci_set_drvdata(pdev, endpoint);
+
+	rc = pci_enable_device(pdev);
+
+	/* L0s has caused packet drops. No power saving, thank you. */
+
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
+	if (rc) {
+		pr_err("xillybus: pci_enable_device() failed. "
+		       "Aborting.\n");
+		goto no_enable;
+	}
+
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		pr_err("xillybus: Incorrect BAR configuration. "
+		       "Aborting.\n");
+		rc = -ENODEV;
+		goto bad_bar;
+	}
+
+	rc = pci_request_regions(pdev, xillyname);
+	if (rc) {
+		pr_err("xillybus: pci_request_regions() failed. "
+		       "Aborting.\n");
+		goto failed_request_regions;
+	}
+
+	endpoint->registers = pci_iomap(pdev, 0, 128);
+
+	if (!endpoint->registers) {
+		pr_err("xillybus: Failed to map BAR 0. Aborting.\n");
+		goto failed_iomap0;
+	}
+
+	pci_set_master(pdev);
+
+	/* Set up a single MSI interrupt */
+	if (pci_enable_msi(pdev)) {
+		pr_err("xillybus: Failed to enable MSI interrupts. "
+		       "Aborting.\n");
+		rc = -ENODEV;
+		goto failed_enable_msi;
+	}
+	rc = request_irq(pdev->irq, xillybus_isr, 0, xillyname, endpoint);
+
+	if (rc) {
+		pr_err("xillybus: Failed to register MSI handler. "
+		       "Aborting.\n");
+		rc = -ENODEV;
+		goto failed_register_msi;
+	}
+
+	/*
+	 * In theory, an attempt to set the DMA mask to 64 and dma_using_dac=1
+	 * is the right thing. But some unclever PCIe drivers report it's OK
+	 * when the hardware drops those 64-bit PCIe packets. So trust
+	 * nobody and use 32 bits DMA addressing in any case.
+	 */
+
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
+		endpoint->dma_using_dac = 0;
+	else {
+		pr_err("xillybus: Failed to set DMA mask. "
+		       "Aborting.\n");
+		rc = -ENODEV;
+		goto failed_dmamask;
+	}
+
+	rc = xillybus_endpoint_discovery(endpoint);
+
+	if (!rc)
+		return 0;
+
+failed_dmamask:
+	free_irq(pdev->irq, endpoint);
+failed_register_msi:
+	pci_disable_msi(pdev);
+failed_enable_msi:
+	/* pci_clear_master(pdev); Nobody else seems to do this */
+	pci_iounmap(pdev, endpoint->registers);
+failed_iomap0:
+	pci_release_regions(pdev);
+failed_request_regions:
+bad_bar:
+	pci_disable_device(pdev);
+no_enable:
+	xillybus_do_cleanup(&endpoint->cleanup, endpoint);
+
+	kfree(endpoint);
+	return rc;
+}
+
+static void xilly_remove(struct pci_dev *pdev)
+{
+	struct xilly_endpoint *endpoint = pci_get_drvdata(pdev);
+
+	xillybus_endpoint_remove(endpoint);
+
+	free_irq(pdev->irq, endpoint);
+
+	pci_disable_msi(pdev);
+	pci_iounmap(pdev, endpoint->registers);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+
+	xillybus_do_cleanup(&endpoint->cleanup, endpoint);
+
+	kfree(endpoint);
+}
+
+MODULE_DEVICE_TABLE(pci, xillyids);
+
+static struct pci_driver xillybus_driver = {
+	.name = xillyname,
+	.id_table = xillyids,
+	.probe = xilly_probe,
+	.remove = xilly_remove,
+};
+
+module_pci_driver(xillybus_driver);
diff --git a/drivers/staging/zcache/ramster/tcp.c b/drivers/staging/zcache/ramster/tcp.c
index f6e1e52..f74881e 100644
--- a/drivers/staging/zcache/ramster/tcp.c
+++ b/drivers/staging/zcache/ramster/tcp.c
@@ -403,6 +403,9 @@ static void sc_kref_release(struct kref *kref)
 	sc->sc_node = NULL;
 
 	r2net_debug_del_sc(sc);
+
+	if (sc->sc_page)
+		__free_page(sc->sc_page);
 	kfree(sc);
 }
 
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index dcceed2..9313df7 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -1140,23 +1140,19 @@ static bool zcache_freeze;
  * pageframes in use.  FIXME POLICY: Probably the writeback should only occur
  * if the eviction doesn't free enough pages.
  */
-static int shrink_zcache_memory(struct shrinker *shrink,
-				struct shrink_control *sc)
+static unsigned long scan_zcache_memory(struct shrinker *shrink,
+					struct shrink_control *sc)
 {
 	static bool in_progress;
-	int ret = -1;
-	int nr = sc->nr_to_scan;
 	int nr_evict = 0;
 	int nr_writeback = 0;
 	struct page *page;
 	int  file_pageframes_inuse, anon_pageframes_inuse;
-
-	if (nr <= 0)
-		goto skip_evict;
+	unsigned long freed = 0;
 
 	/* don't allow more than one eviction thread at a time */
 	if (in_progress)
-		goto skip_evict;
+		return 0;
 
 	in_progress = true;
 
@@ -1176,6 +1172,7 @@ static int shrink_zcache_memory(struct shrinker *shrink,
 		if (page == NULL)
 			break;
 		zcache_free_page(page);
+		freed++;
 	}
 
 	zcache_last_active_anon_pageframes =
@@ -1192,13 +1189,22 @@ static int shrink_zcache_memory(struct shrinker *shrink,
 #ifdef CONFIG_ZCACHE_WRITEBACK
 		int writeback_ret;
 		writeback_ret = zcache_frontswap_writeback();
-		if (writeback_ret == -ENOMEM)
+		if (writeback_ret != -ENOMEM)
+			freed++;
+		else
 #endif
 			break;
 	}
 	in_progress = false;
 
-skip_evict:
+	return freed;
+}
+
+static unsigned long count_zcache_memory(struct shrinker *shrink,
+				struct shrink_control *sc)
+{
+	long ret = -1;
+
 	/* resample: has changed, but maybe not all the way yet */
 	zcache_last_active_file_pageframes =
 		global_page_state(NR_LRU_BASE + LRU_ACTIVE_FILE);
@@ -1212,7 +1218,8 @@ skip_evict:
 }
 
 static struct shrinker zcache_shrinker = {
-	.shrink = shrink_zcache_memory,
+	.scan_objects = scan_zcache_memory,
+	.count_objects = count_zcache_memory,
 	.seeks = DEFAULT_SEEKS,
 };
 
@@ -1811,10 +1818,12 @@ static int zcache_comp_init(void)
 #else
 	if (*zcache_comp_name != '\0') {
 		ret = crypto_has_comp(zcache_comp_name, 0, 0);
-		if (!ret)
+		if (!ret) {
 			pr_info("zcache: %s not supported\n",
 					zcache_comp_name);
-		goto out;
+			ret = 1;
+			goto out;
+		}
 	}
 	if (!ret)
 		strcpy(zcache_comp_name, "lzo");
@@ -1908,7 +1917,7 @@ static int zcache_init(void)
 #endif
 		if (IS_ERR(old_ops) || old_ops) {
 			if (IS_ERR(old_ops))
-				return PTR_RET(old_ops);
+				return PTR_ERR(old_ops);
 			pr_warn("%s: frontswap_ops overridden\n", namestr);
 		}
 	}
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index e77fb6e..7ebf91d 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -418,14 +418,6 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 			goto out;
 	}
 
-	/*
-	 * System overwrites unused sectors. Free memory associated
-	 * with this sector now.
-	 */
-	if (meta->table[index].handle ||
-	    zram_test_flag(meta, index, ZRAM_ZERO))
-		zram_free_page(zram, index);
-
 	user_mem = kmap_atomic(page);
 
 	if (is_partial_io(bvec)) {
@@ -439,6 +431,9 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 
 	if (page_zero_filled(uncmem)) {
 		kunmap_atomic(user_mem);
+		/* Free memory associated with this sector now. */
+		zram_free_page(zram, index);
+
 		zram->stats.pages_zero++;
 		zram_set_flag(meta, index, ZRAM_ZERO);
 		ret = 0;
@@ -486,6 +481,12 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 
 	zs_unmap_object(meta->mem_pool, handle);
 
+	/*
+	 * Free memory associated with this sector
+	 * before overwriting unused sectors.
+	 */
+	zram_free_page(zram, index);
+
 	meta->table[index].handle = handle;
 	meta->table[index].size = clen;
 
@@ -923,3 +924,4 @@ MODULE_PARM_DESC(num_devices, "Number of zram devices");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
 MODULE_DESCRIPTION("Compressed RAM Block Device");
+MODULE_ALIAS("devname:zram");
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
index 4bb275b..1a67537 100644
--- a/drivers/staging/zsmalloc/zsmalloc-main.c
+++ b/drivers/staging/zsmalloc/zsmalloc-main.c
@@ -423,7 +423,7 @@ static struct page *get_next_page(struct page *page)
 	if (is_last_page(page))
 		next = NULL;
 	else if (is_first_page(page))
-		next = (struct page *)page->private;
+		next = (struct page *)page_private(page);
 	else
 		next = list_entry(page->lru.next, struct page, lru);
 
@@ -581,7 +581,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
 			first_page->inuse = 0;
 		}
 		if (i == 1)
-			first_page->private = (unsigned long)page;
+			set_page_private(first_page, (unsigned long)page);
 		if (i >= 1)
 			page->first_page = first_page;
 		if (i >= 2)
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index eb255e8..9eba119 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -361,7 +361,12 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 		tty->driver_data = NULL;
 		tty_port_put(&hp->port);
 		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
-	}
+	} else
+		/* We are ready... raise DTR/RTS */
+		if (C_BAUD(tty))
+			if (hp->ops->dtr_rts)
+				hp->ops->dtr_rts(hp, 1);
+
 	/* Force wakeup of the polling thread */
 	hvc_kick();
 
@@ -393,6 +398,10 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 		/* We are done with the tty pointer now. */
 		tty_port_tty_set(&hp->port, NULL);
 
+		if (C_HUPCL(tty))
+			if (hp->ops->dtr_rts)
+				hp->ops->dtr_rts(hp, 0);
+
 		if (hp->ops->notifier_del)
 			hp->ops->notifier_del(hp, hp->data);
 
diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
index 674d23c..9131019 100644
--- a/drivers/tty/hvc/hvc_console.h
+++ b/drivers/tty/hvc/hvc_console.h
@@ -75,6 +75,9 @@ struct hv_ops {
 	/* tiocmget/set implementation */
 	int (*tiocmget)(struct hvc_struct *hp);
 	int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear);
+
+	/* Callbacks to handle tty ports */
+	void (*dtr_rts)(struct hvc_struct *hp, int raise);
 };
 
 /* Register a vterm and a slot index for use as a console (console_init) */
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
index 9d47f50..fd17a9b 100644
--- a/drivers/tty/hvc/hvc_iucv.c
+++ b/drivers/tty/hvc/hvc_iucv.c
@@ -656,21 +656,64 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
 }
 
 /**
+ * hvc_iucv_dtr_rts() - HVC notifier for handling DTR/RTS
+ * @hp:		Pointer the HVC device (struct hvc_struct)
+ * @raise:	Non-zero to raise or zero to lower DTR/RTS lines
+ *
+ * This routine notifies the HVC back-end to raise or lower DTR/RTS
+ * lines.  Raising DTR/RTS is ignored.  Lowering DTR/RTS indicates to
+ * drop the IUCV connection (similar to hang up the modem).
+ */
+static void hvc_iucv_dtr_rts(struct hvc_struct *hp, int raise)
+{
+	struct hvc_iucv_private *priv;
+	struct iucv_path        *path;
+
+	/* Raising the DTR/RTS is ignored as IUCV connections can be
+	 * established at any times.
+	 */
+	if (raise)
+		return;
+
+	priv = hvc_iucv_get_private(hp->vtermno);
+	if (!priv)
+		return;
+
+	/* Lowering the DTR/RTS lines disconnects an established IUCV
+	 * connection.
+	 */
+	flush_sndbuf_sync(priv);
+
+	spin_lock_bh(&priv->lock);
+	path = priv->path;		/* save reference to IUCV path */
+	priv->path = NULL;
+	priv->iucv_state = IUCV_DISCONN;
+	spin_unlock_bh(&priv->lock);
+
+	/* Sever IUCV path outside of priv->lock due to lock ordering of:
+	 * priv->lock <--> iucv_table_lock */
+	if (path) {
+		iucv_path_sever(path, NULL);
+		iucv_path_free(path);
+	}
+}
+
+/**
  * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time.
  * @hp:		Pointer to the HVC device (struct hvc_struct)
  * @id:		Additional data (originally passed to hvc_alloc):
  *		the index of an struct hvc_iucv_private instance.
  *
  * This routine notifies the HVC back-end that the last tty device fd has been
- * closed.  The function calls hvc_iucv_cleanup() to clean up the struct
- * hvc_iucv_private instance.
+ * closed.  The function cleans up tty resources.  The clean-up of the IUCV
+ * connection is done in hvc_iucv_dtr_rts() and depends on the HUPCL termios
+ * control setting.
  *
  * Locking:	struct hvc_iucv_private->lock
  */
 static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
 {
 	struct hvc_iucv_private *priv;
-	struct iucv_path	*path;
 
 	priv = hvc_iucv_get_private(id);
 	if (!priv)
@@ -679,17 +722,11 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
 	flush_sndbuf_sync(priv);
 
 	spin_lock_bh(&priv->lock);
-	path = priv->path;		/* save reference to IUCV path */
-	priv->path = NULL;
-	hvc_iucv_cleanup(priv);
+	destroy_tty_buffer_list(&priv->tty_outqueue);
+	destroy_tty_buffer_list(&priv->tty_inqueue);
+	priv->tty_state = TTY_CLOSED;
+	priv->sndbuf_len = 0;
 	spin_unlock_bh(&priv->lock);
-
-	/* sever IUCV path outside of priv->lock due to lock ordering of:
-	 * priv->lock <--> iucv_table_lock */
-	if (path) {
-		iucv_path_sever(path, NULL);
-		iucv_path_free(path);
-	}
 }
 
 /**
@@ -931,6 +968,7 @@ static const struct hv_ops hvc_iucv_ops = {
 	.notifier_add = hvc_iucv_notifier_add,
 	.notifier_del = hvc_iucv_notifier_del,
 	.notifier_hangup = hvc_iucv_notifier_hangup,
+	.dtr_rts = hvc_iucv_dtr_rts,
 };
 
 /* Suspend / resume device operations */
diff --git a/drivers/tty/hvc/hvc_tile.c b/drivers/tty/hvc/hvc_tile.c
index 7a84a05..af8cdaa 100644
--- a/drivers/tty/hvc/hvc_tile.c
+++ b/drivers/tty/hvc/hvc_tile.c
@@ -18,16 +18,46 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/moduleparam.h>
+#include <linux/platform_device.h>
 #include <linux/types.h>
 
+#include <asm/setup.h>
+#include <arch/sim_def.h>
+
 #include <hv/hypervisor.h>
 
 #include "hvc_console.h"
 
+static int use_sim_console;
+static int __init sim_console(char *str)
+{
+	use_sim_console = 1;
+	return 0;
+}
+early_param("sim_console", sim_console);
+
+int tile_console_write(const char *buf, int count)
+{
+	if (unlikely(use_sim_console)) {
+		int i;
+		for (i = 0; i < count; ++i)
+			__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+				     (buf[i] << _SIM_CONTROL_OPERATOR_BITS));
+		__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+			     (SIM_PUTC_FLUSH_BINARY <<
+			      _SIM_CONTROL_OPERATOR_BITS));
+		return 0;
+	} else {
+		return hv_console_write((HV_VirtAddr)buf, count);
+	}
+}
+
 static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count)
 {
-	return hv_console_write((HV_VirtAddr)buf, count);
+	return tile_console_write(buf, count);
 }
 
 static int hvc_tile_get_chars(uint32_t vt, char *buf, int count)
@@ -44,25 +74,132 @@ static int hvc_tile_get_chars(uint32_t vt, char *buf, int count)
 	return i;
 }
 
+#ifdef __tilegx__
+/*
+ * IRQ based callbacks.
+ */
+static int hvc_tile_notifier_add_irq(struct hvc_struct *hp, int irq)
+{
+	int rc;
+	int cpu = raw_smp_processor_id();  /* Choose an arbitrary cpu */
+	HV_Coord coord = { .x = cpu_x(cpu), .y = cpu_y(cpu) };
+
+	rc = notifier_add_irq(hp, irq);
+	if (rc)
+		return rc;
+
+	/*
+	 * Request that the hypervisor start sending us interrupts.
+	 * If the hypervisor returns an error, we still return 0, so that
+	 * we can fall back to polling.
+	 */
+	if (hv_console_set_ipi(KERNEL_PL, irq, coord) < 0)
+		notifier_del_irq(hp, irq);
+
+	return 0;
+}
+
+static void hvc_tile_notifier_del_irq(struct hvc_struct *hp, int irq)
+{
+	HV_Coord coord = { 0, 0 };
+
+	/* Tell the hypervisor to stop sending us interrupts. */
+	hv_console_set_ipi(KERNEL_PL, -1, coord);
+
+	notifier_del_irq(hp, irq);
+}
+
+static void hvc_tile_notifier_hangup_irq(struct hvc_struct *hp, int irq)
+{
+	hvc_tile_notifier_del_irq(hp, irq);
+}
+#endif
+
 static const struct hv_ops hvc_tile_get_put_ops = {
 	.get_chars = hvc_tile_get_chars,
 	.put_chars = hvc_tile_put_chars,
+#ifdef __tilegx__
+	.notifier_add = hvc_tile_notifier_add_irq,
+	.notifier_del = hvc_tile_notifier_del_irq,
+	.notifier_hangup = hvc_tile_notifier_hangup_irq,
+#endif
+};
+
+
+#ifdef __tilegx__
+static int hvc_tile_probe(struct platform_device *pdev)
+{
+	struct hvc_struct *hp;
+	int tile_hvc_irq;
+
+	/* Create our IRQ and register it. */
+	tile_hvc_irq = create_irq();
+	if (tile_hvc_irq < 0)
+		return -ENXIO;
+
+	tile_irq_activate(tile_hvc_irq, TILE_IRQ_PERCPU);
+	hp = hvc_alloc(0, tile_hvc_irq, &hvc_tile_get_put_ops, 128);
+	if (IS_ERR(hp)) {
+		destroy_irq(tile_hvc_irq);
+		return PTR_ERR(hp);
+	}
+	dev_set_drvdata(&pdev->dev, hp);
+
+	return 0;
+}
+
+static int hvc_tile_remove(struct platform_device *pdev)
+{
+	int rc;
+	struct hvc_struct *hp = dev_get_drvdata(&pdev->dev);
+
+	rc = hvc_remove(hp);
+	if (rc == 0)
+		destroy_irq(hp->data);
+
+	return rc;
+}
+
+static void hvc_tile_shutdown(struct platform_device *pdev)
+{
+	struct hvc_struct *hp = dev_get_drvdata(&pdev->dev);
+
+	hvc_tile_notifier_del_irq(hp, hp->data);
+}
+
+static struct platform_device hvc_tile_pdev = {
+	.name           = "hvc-tile",
+	.id             = 0,
+};
+
+static struct platform_driver hvc_tile_driver = {
+	.probe          = hvc_tile_probe,
+	.remove         = hvc_tile_remove,
+	.shutdown	= hvc_tile_shutdown,
+	.driver         = {
+		.name   = "hvc-tile",
+		.owner  = THIS_MODULE,
+	}
 };
+#endif
 
 static int __init hvc_tile_console_init(void)
 {
-	extern void disable_early_printk(void);
 	hvc_instantiate(0, 0, &hvc_tile_get_put_ops);
 	add_preferred_console("hvc", 0, NULL);
-	disable_early_printk();
 	return 0;
 }
 console_initcall(hvc_tile_console_init);
 
 static int __init hvc_tile_init(void)
 {
-	struct hvc_struct *s;
-	s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
-	return IS_ERR(s) ? PTR_ERR(s) : 0;
+#ifndef __tilegx__
+	struct hvc_struct *hp;
+	hp = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
+	return IS_ERR(hp) ? PTR_ERR(hp) : 0;
+#else
+	platform_device_register(&hvc_tile_pdev);
+	return platform_driver_register(&hvc_tile_driver);
+#endif
 }
 device_initcall(hvc_tile_init);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 6422390..c0f76da 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -807,7 +807,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
 	int h = dlci->adaption - 1;
 
 	total_size = 0;
-	while(1) {
+	while (1) {
 		len = kfifo_len(dlci->fifo);
 		if (len == 0)
 			return total_size;
@@ -827,8 +827,8 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
 		switch (dlci->adaption) {
 		case 1:	/* Unstructured */
 			break;
-		case 2:	/* Unstructed with modem bits. Always one byte as we never
-			   send inline break data */
+		case 2:	/* Unstructed with modem bits.
+		Always one byte as we never send inline break data */
 			*dp++ = gsm_encode_modem(dlci);
 			break;
 		}
@@ -968,7 +968,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
 	unsigned long flags;
 	int sweep;
 
-	if (dlci->constipated) 
+	if (dlci->constipated)
 		return;
 
 	spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
@@ -981,7 +981,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
 			gsm_dlci_data_output(dlci->gsm, dlci);
 	}
 	if (sweep)
- 		gsm_dlci_data_sweep(dlci->gsm);
+		gsm_dlci_data_sweep(dlci->gsm);
 	spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
 }
 
@@ -1138,7 +1138,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
 static void gsm_control_rls(struct gsm_mux *gsm, u8 *data, int clen)
 {
 	struct tty_port *port;
-	unsigned int addr = 0 ;
+	unsigned int addr = 0;
 	u8 bits;
 	int len = clen;
 	u8 *dp = data;
@@ -1740,10 +1740,11 @@ static void gsm_queue(struct gsm_mux *gsm)
 
 	if ((gsm->control & ~PF) == UI)
 		gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
-	if (gsm->encoding == 0){
-		/* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only.
-		            In this case it contain the last piece of data
-		            required to generate final CRC */
+	if (gsm->encoding == 0) {
+		/* WARNING: gsm->received_fcs is used for
+		gsm->encoding = 0 only.
+		In this case it contain the last piece of data
+		required to generate final CRC */
 		gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
 	}
 	if (gsm->fcs != GOOD_FCS) {
@@ -2904,9 +2905,11 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
 	gsm = gsm_mux[mux];
 	if (gsm->dead)
 		return -EL2HLT;
-	/* If DLCI 0 is not yet fully open return an error. This is ok from a locking
-	   perspective as we don't have to worry about this if DLCI0 is lost */
-	if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) 
+	/* If DLCI 0 is not yet fully open return an error.
+	This is ok from a locking
+	perspective as we don't have to worry about this
+	if DLCI0 is lost */
+	if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
 		return -EL2NSYNC;
 	dlci = gsm->dlci[line];
 	if (dlci == NULL) {
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 4bf0fc0..dd8ae0c 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -50,6 +50,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ratelimit.h>
+#include <linux/vmalloc.h>
 
 
 /* number of characters left in xmit buffer before select has we have room */
@@ -74,37 +75,81 @@
 #define ECHO_OP_SET_CANON_COL 0x81
 #define ECHO_OP_ERASE_TAB 0x82
 
+#define ECHO_COMMIT_WATERMARK	256
+#define ECHO_BLOCK		256
+#define ECHO_DISCARD_WATERMARK	N_TTY_BUF_SIZE - (ECHO_BLOCK + 32)
+
+
+#undef N_TTY_TRACE
+#ifdef N_TTY_TRACE
+# define n_tty_trace(f, args...)	trace_printk(f, ##args)
+#else
+# define n_tty_trace(f, args...)
+#endif
+
 struct n_tty_data {
-	unsigned int column;
+	/* producer-published */
+	size_t read_head;
+	size_t canon_head;
+	size_t echo_head;
+	size_t echo_commit;
+	DECLARE_BITMAP(char_map, 256);
+
+	/* private to n_tty_receive_overrun (single-threaded) */
 	unsigned long overrun_time;
 	int num_overrun;
 
+	/* non-atomic */
+	bool no_room;
+
+	/* must hold exclusive termios_rwsem to reset these */
 	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
-	unsigned char echo_overrun:1;
 
-	DECLARE_BITMAP(process_char_map, 256);
+	/* shared by producer and consumer */
+	char read_buf[N_TTY_BUF_SIZE];
 	DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE);
+	unsigned char echo_buf[N_TTY_BUF_SIZE];
 
-	char *read_buf;
-	int read_head;
-	int read_tail;
-	int read_cnt;
 	int minimum_to_wake;
 
-	unsigned char *echo_buf;
-	unsigned int echo_pos;
-	unsigned int echo_cnt;
+	/* consumer-published */
+	size_t read_tail;
+	size_t line_start;
 
-	int canon_data;
-	unsigned long canon_head;
+	/* protected by output lock */
+	unsigned int column;
 	unsigned int canon_column;
+	size_t echo_tail;
 
 	struct mutex atomic_read_lock;
 	struct mutex output_lock;
-	struct mutex echo_lock;
-	raw_spinlock_t read_lock;
 };
 
+static inline size_t read_cnt(struct n_tty_data *ldata)
+{
+	return ldata->read_head - ldata->read_tail;
+}
+
+static inline unsigned char read_buf(struct n_tty_data *ldata, size_t i)
+{
+	return ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)];
+}
+
+static inline unsigned char *read_buf_addr(struct n_tty_data *ldata, size_t i)
+{
+	return &ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)];
+}
+
+static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i)
+{
+	return ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)];
+}
+
+static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i)
+{
+	return &ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)];
+}
+
 static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 			       unsigned char __user *ptr)
 {
@@ -114,33 +159,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 	return put_user(x, ptr);
 }
 
-/**
- *	n_tty_set_room	-	receive space
- *	@tty: terminal
- *
- *	Updates tty->receive_room to reflect the currently available space
- *	in the input buffer, and re-schedules the flip buffer work if space
- *	just became available.
- *
- *	Locks: Concurrent update is protected with read_lock
- */
-
-static int set_room(struct tty_struct *tty)
+static int receive_room(struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 	int left;
-	int old_left;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&ldata->read_lock, flags);
 
 	if (I_PARMRK(tty)) {
 		/* Multiply read_cnt by 3, since each byte might take up to
 		 * three times as many spaces when PARMRK is set (depending on
 		 * its flags, e.g. parity error). */
-		left = N_TTY_BUF_SIZE - ldata->read_cnt * 3 - 1;
+		left = N_TTY_BUF_SIZE - read_cnt(ldata) * 3 - 1;
 	} else
-		left = N_TTY_BUF_SIZE - ldata->read_cnt - 1;
+		left = N_TTY_BUF_SIZE - read_cnt(ldata) - 1;
 
 	/*
 	 * If we are doing input canonicalization, and there are no
@@ -149,19 +179,31 @@ static int set_room(struct tty_struct *tty)
 	 * characters will be beeped.
 	 */
 	if (left <= 0)
-		left = ldata->icanon && !ldata->canon_data;
-	old_left = tty->receive_room;
-	tty->receive_room = left;
-
-	raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
+		left = ldata->icanon && ldata->canon_head == ldata->read_tail;
 
-	return left && !old_left;
+	return left;
 }
 
+/**
+ *	n_tty_set_room	-	receive space
+ *	@tty: terminal
+ *
+ *	Re-schedules the flip buffer work if space just became available.
+ *
+ *	Caller holds exclusive termios_rwsem
+ *	   or
+ *	n_tty_read()/consumer path:
+ *		holds non-exclusive termios_rwsem
+ */
+
 static void n_tty_set_room(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
+
 	/* Did this open up the receive buffer? We may need to flip */
-	if (set_room(tty)) {
+	if (unlikely(ldata->no_room) && receive_room(tty)) {
+		ldata->no_room = 0;
+
 		WARN_RATELIMIT(tty->port->itty == NULL,
 				"scheduling with invalid itty\n");
 		/* see if ldisc has been killed - if so, this means that
@@ -170,17 +212,93 @@ static void n_tty_set_room(struct tty_struct *tty)
 		 */
 		WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
 			       "scheduling buffer work for halted ldisc\n");
-		schedule_work(&tty->port->buf.work);
+		queue_work(system_unbound_wq, &tty->port->buf.work);
 	}
 }
 
-static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
+static ssize_t chars_in_buffer(struct tty_struct *tty)
 {
-	if (ldata->read_cnt < N_TTY_BUF_SIZE) {
-		ldata->read_buf[ldata->read_head] = c;
-		ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1);
-		ldata->read_cnt++;
+	struct n_tty_data *ldata = tty->disc_data;
+	ssize_t n = 0;
+
+	if (!ldata->icanon)
+		n = read_cnt(ldata);
+	else
+		n = ldata->canon_head - ldata->read_tail;
+	return n;
+}
+
+/**
+ *	n_tty_write_wakeup	-	asynchronous I/O notifier
+ *	@tty: tty device
+ *
+ *	Required for the ptys, serial driver etc. since processes
+ *	that attach themselves to the master and rely on ASYNC
+ *	IO must be woken up
+ */
+
+static void n_tty_write_wakeup(struct tty_struct *tty)
+{
+	if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
+		kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
+}
+
+static void n_tty_check_throttle(struct tty_struct *tty)
+{
+	if (tty->driver->type == TTY_DRIVER_TYPE_PTY)
+		return;
+	/*
+	 * Check the remaining room for the input canonicalization
+	 * mode.  We don't want to throttle the driver if we're in
+	 * canonical mode and don't have a newline yet!
+	 */
+	while (1) {
+		int throttled;
+		tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
+		if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE)
+			break;
+		throttled = tty_throttle_safe(tty);
+		if (!throttled)
+			break;
+	}
+	__tty_set_flow_change(tty, 0);
+}
+
+static void n_tty_check_unthrottle(struct tty_struct *tty)
+{
+	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+	    tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) {
+		if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+			return;
+		if (!tty->count)
+			return;
+		n_tty_set_room(tty);
+		n_tty_write_wakeup(tty->link);
+		wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
+		return;
+	}
+
+	/* If there is enough space in the read buffer now, let the
+	 * low-level driver know. We use chars_in_buffer() to
+	 * check the buffer, as it now knows about canonical mode.
+	 * Otherwise, if the driver is throttled and the line is
+	 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
+	 * we won't get any more characters.
+	 */
+
+	while (1) {
+		int unthrottled;
+		tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
+		if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+			break;
+		if (!tty->count)
+			break;
+		n_tty_set_room(tty);
+		unthrottled = tty_unthrottle_safe(tty);
+		if (!unthrottled)
+			break;
 	}
+	__tty_set_flow_change(tty, 0);
 }
 
 /**
@@ -188,21 +306,19 @@ static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
  *	@c: character
  *	@ldata: n_tty data
  *
- *	Add a character to the tty read_buf queue. This is done under the
- *	read_lock to serialize character addition and also to protect us
- *	against parallel reads or flushes
+ *	Add a character to the tty read_buf queue.
+ *
+ *	n_tty_receive_buf()/producer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		modifies read_head
+ *
+ *	read_head is only considered 'published' if canonical mode is
+ *	not active.
  */
 
-static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
+static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
 {
-	unsigned long flags;
-	/*
-	 *	The problem of stomping on the buffers ends here.
-	 *	Why didn't anyone see this one coming? --AJK
-	*/
-	raw_spin_lock_irqsave(&ldata->read_lock, flags);
-	put_tty_queue_nolock(c, ldata);
-	raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
+	*read_buf_addr(ldata, ldata->read_head++) = c;
 }
 
 /**
@@ -212,22 +328,17 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
  *	Reset the read buffer counters and clear the flags.
  *	Called from n_tty_open() and n_tty_flush_buffer().
  *
- *	Locking: tty_read_lock for read fields.
+ *	Locking: caller holds exclusive termios_rwsem
+ *		 (or locking is not required)
  */
 
 static void reset_buffer_flags(struct n_tty_data *ldata)
 {
-	unsigned long flags;
+	ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
+	ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
+	ldata->line_start = 0;
 
-	raw_spin_lock_irqsave(&ldata->read_lock, flags);
-	ldata->read_head = ldata->read_tail = ldata->read_cnt = 0;
-	raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
-
-	mutex_lock(&ldata->echo_lock);
-	ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
-	mutex_unlock(&ldata->echo_lock);
-
-	ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
+	ldata->erasing = 0;
 	bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
 }
 
@@ -251,16 +362,21 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
  *	buffer flushed (eg at hangup) or when the N_TTY line discipline
  *	internally has to clean the pending queue (for example some signals).
  *
- *	Locking: ctrl_lock, read_lock.
+ *	Holds termios_rwsem to exclude producer/consumer while
+ *	buffer indices are reset.
+ *
+ *	Locking: ctrl_lock, exclusive termios_rwsem
  */
 
 static void n_tty_flush_buffer(struct tty_struct *tty)
 {
+	down_write(&tty->termios_rwsem);
 	reset_buffer_flags(tty->disc_data);
 	n_tty_set_room(tty);
 
 	if (tty->link)
 		n_tty_packet_mode_flush(tty);
+	up_write(&tty->termios_rwsem);
 }
 
 /**
@@ -270,24 +386,18 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
  *	Report the number of characters buffered to be delivered to user
  *	at this instant in time.
  *
- *	Locking: read_lock
+ *	Locking: exclusive termios_rwsem
  */
 
 static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
 {
-	struct n_tty_data *ldata = tty->disc_data;
-	unsigned long flags;
-	ssize_t n = 0;
+	ssize_t n;
 
-	raw_spin_lock_irqsave(&ldata->read_lock, flags);
-	if (!ldata->icanon) {
-		n = ldata->read_cnt;
-	} else if (ldata->canon_data) {
-		n = (ldata->canon_head > ldata->read_tail) ?
-			ldata->canon_head - ldata->read_tail :
-			ldata->canon_head + (N_TTY_BUF_SIZE - ldata->read_tail);
-	}
-	raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
+	WARN_ONCE(1, "%s is deprecated and scheduled for removal.", __func__);
+
+	down_write(&tty->termios_rwsem);
+	n = chars_in_buffer(tty);
+	up_write(&tty->termios_rwsem);
 	return n;
 }
 
@@ -532,33 +642,23 @@ break_out:
  *	are prioritized.  Also, when control characters are echoed with a
  *	prefixed "^", the pair is treated atomically and thus not separated.
  *
- *	Locking: output_lock to protect column state and space left,
- *		 echo_lock to protect the echo buffer
+ *	Locking: callers must hold output_lock
  */
 
-static void process_echoes(struct tty_struct *tty)
+static size_t __process_echoes(struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
-	int	space, nr;
+	int	space, old_space;
+	size_t tail;
 	unsigned char c;
-	unsigned char *cp, *buf_end;
 
-	if (!ldata->echo_cnt)
-		return;
-
-	mutex_lock(&ldata->output_lock);
-	mutex_lock(&ldata->echo_lock);
+	old_space = space = tty_write_room(tty);
 
-	space = tty_write_room(tty);
-
-	buf_end = ldata->echo_buf + N_TTY_BUF_SIZE;
-	cp = ldata->echo_buf + ldata->echo_pos;
-	nr = ldata->echo_cnt;
-	while (nr > 0) {
-		c = *cp;
+	tail = ldata->echo_tail;
+	while (ldata->echo_commit != tail) {
+		c = echo_buf(ldata, tail);
 		if (c == ECHO_OP_START) {
 			unsigned char op;
-			unsigned char *opp;
 			int no_space_left = 0;
 
 			/*
@@ -566,18 +666,13 @@ static void process_echoes(struct tty_struct *tty)
 			 * operation, get the next byte, which is either the
 			 * op code or a control character value.
 			 */
-			opp = cp + 1;
-			if (opp == buf_end)
-				opp -= N_TTY_BUF_SIZE;
-			op = *opp;
+			op = echo_buf(ldata, tail + 1);
 
 			switch (op) {
 				unsigned int num_chars, num_bs;
 
 			case ECHO_OP_ERASE_TAB:
-				if (++opp == buf_end)
-					opp -= N_TTY_BUF_SIZE;
-				num_chars = *opp;
+				num_chars = echo_buf(ldata, tail + 2);
 
 				/*
 				 * Determine how many columns to go back
@@ -603,21 +698,18 @@ static void process_echoes(struct tty_struct *tty)
 					if (ldata->column > 0)
 						ldata->column--;
 				}
-				cp += 3;
-				nr -= 3;
+				tail += 3;
 				break;
 
 			case ECHO_OP_SET_CANON_COL:
 				ldata->canon_column = ldata->column;
-				cp += 2;
-				nr -= 2;
+				tail += 2;
 				break;
 
 			case ECHO_OP_MOVE_BACK_COL:
 				if (ldata->column > 0)
 					ldata->column--;
-				cp += 2;
-				nr -= 2;
+				tail += 2;
 				break;
 
 			case ECHO_OP_START:
@@ -629,8 +721,7 @@ static void process_echoes(struct tty_struct *tty)
 				tty_put_char(tty, ECHO_OP_START);
 				ldata->column++;
 				space--;
-				cp += 2;
-				nr -= 2;
+				tail += 2;
 				break;
 
 			default:
@@ -651,8 +742,7 @@ static void process_echoes(struct tty_struct *tty)
 				tty_put_char(tty, op ^ 0100);
 				ldata->column += 2;
 				space -= 2;
-				cp += 2;
-				nr -= 2;
+				tail += 2;
 			}
 
 			if (no_space_left)
@@ -669,80 +759,92 @@ static void process_echoes(struct tty_struct *tty)
 				tty_put_char(tty, c);
 				space -= 1;
 			}
-			cp += 1;
-			nr -= 1;
+			tail += 1;
 		}
-
-		/* When end of circular buffer reached, wrap around */
-		if (cp >= buf_end)
-			cp -= N_TTY_BUF_SIZE;
 	}
 
-	if (nr == 0) {
-		ldata->echo_pos = 0;
-		ldata->echo_cnt = 0;
-		ldata->echo_overrun = 0;
-	} else {
-		int num_processed = ldata->echo_cnt - nr;
-		ldata->echo_pos += num_processed;
-		ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
-		ldata->echo_cnt = nr;
-		if (num_processed > 0)
-			ldata->echo_overrun = 0;
+	/* If the echo buffer is nearly full (so that the possibility exists
+	 * of echo overrun before the next commit), then discard enough
+	 * data at the tail to prevent a subsequent overrun */
+	while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) {
+		if (echo_buf(ldata, tail == ECHO_OP_START)) {
+			if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB)
+				tail += 3;
+			else
+				tail += 2;
+		} else
+			tail++;
 	}
 
-	mutex_unlock(&ldata->echo_lock);
+	ldata->echo_tail = tail;
+	return old_space - space;
+}
+
+static void commit_echoes(struct tty_struct *tty)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	size_t nr, old, echoed;
+	size_t head;
+
+	head = ldata->echo_head;
+	old = ldata->echo_commit - ldata->echo_tail;
+
+	/* Process committed echoes if the accumulated # of bytes
+	 * is over the threshold (and try again each time another
+	 * block is accumulated) */
+	nr = head - ldata->echo_tail;
+	if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK))
+		return;
+
+	mutex_lock(&ldata->output_lock);
+	ldata->echo_commit = head;
+	echoed = __process_echoes(tty);
+	mutex_unlock(&ldata->output_lock);
+
+	if (echoed && tty->ops->flush_chars)
+		tty->ops->flush_chars(tty);
+}
+
+static void process_echoes(struct tty_struct *tty)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	size_t echoed;
+
+	if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail)
+		return;
+
+	mutex_lock(&ldata->output_lock);
+	echoed = __process_echoes(tty);
 	mutex_unlock(&ldata->output_lock);
 
-	if (tty->ops->flush_chars)
+	if (echoed && tty->ops->flush_chars)
 		tty->ops->flush_chars(tty);
 }
 
+static void flush_echoes(struct tty_struct *tty)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+
+	if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head)
+		return;
+
+	mutex_lock(&ldata->output_lock);
+	ldata->echo_commit = ldata->echo_head;
+	__process_echoes(tty);
+	mutex_unlock(&ldata->output_lock);
+}
+
 /**
  *	add_echo_byte	-	add a byte to the echo buffer
  *	@c: unicode byte to echo
  *	@ldata: n_tty data
  *
  *	Add a character or operation byte to the echo buffer.
- *
- *	Should be called under the echo lock to protect the echo buffer.
  */
 
-static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
+static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
 {
-	int	new_byte_pos;
-
-	if (ldata->echo_cnt == N_TTY_BUF_SIZE) {
-		/* Circular buffer is already at capacity */
-		new_byte_pos = ldata->echo_pos;
-
-		/*
-		 * Since the buffer start position needs to be advanced,
-		 * be sure to step by a whole operation byte group.
-		 */
-		if (ldata->echo_buf[ldata->echo_pos] == ECHO_OP_START) {
-			if (ldata->echo_buf[(ldata->echo_pos + 1) &
-					  (N_TTY_BUF_SIZE - 1)] ==
-						ECHO_OP_ERASE_TAB) {
-				ldata->echo_pos += 3;
-				ldata->echo_cnt -= 2;
-			} else {
-				ldata->echo_pos += 2;
-				ldata->echo_cnt -= 1;
-			}
-		} else {
-			ldata->echo_pos++;
-		}
-		ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
-
-		ldata->echo_overrun = 1;
-	} else {
-		new_byte_pos = ldata->echo_pos + ldata->echo_cnt;
-		new_byte_pos &= N_TTY_BUF_SIZE - 1;
-		ldata->echo_cnt++;
-	}
-
-	ldata->echo_buf[new_byte_pos] = c;
+	*echo_buf_addr(ldata, ldata->echo_head++) = c;
 }
 
 /**
@@ -750,16 +852,12 @@ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
  *	@ldata: n_tty data
  *
  *	Add an operation to the echo buffer to move back one column.
- *
- *	Locking: echo_lock to protect the echo buffer
  */
 
 static void echo_move_back_col(struct n_tty_data *ldata)
 {
-	mutex_lock(&ldata->echo_lock);
 	add_echo_byte(ECHO_OP_START, ldata);
 	add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
-	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -768,16 +866,12 @@ static void echo_move_back_col(struct n_tty_data *ldata)
  *
  *	Add an operation to the echo buffer to set the canon column
  *	to the current column.
- *
- *	Locking: echo_lock to protect the echo buffer
  */
 
 static void echo_set_canon_col(struct n_tty_data *ldata)
 {
-	mutex_lock(&ldata->echo_lock);
 	add_echo_byte(ECHO_OP_START, ldata);
 	add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
-	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -793,15 +887,11 @@ static void echo_set_canon_col(struct n_tty_data *ldata)
  *	of input.  This information will be used later, along with
  *	canon column (if applicable), to go back the correct number
  *	of columns.
- *
- *	Locking: echo_lock to protect the echo buffer
  */
 
 static void echo_erase_tab(unsigned int num_chars, int after_tab,
 			   struct n_tty_data *ldata)
 {
-	mutex_lock(&ldata->echo_lock);
-
 	add_echo_byte(ECHO_OP_START, ldata);
 	add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
 
@@ -813,8 +903,6 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
 		num_chars |= 0x80;
 
 	add_echo_byte(num_chars, ldata);
-
-	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -826,20 +914,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
  *	L_ECHO(tty) is true. Called from the driver receive_buf path.
  *
  *	This variant does not treat control characters specially.
- *
- *	Locking: echo_lock to protect the echo buffer
  */
 
 static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
 {
-	mutex_lock(&ldata->echo_lock);
 	if (c == ECHO_OP_START) {
 		add_echo_byte(ECHO_OP_START, ldata);
 		add_echo_byte(ECHO_OP_START, ldata);
 	} else {
 		add_echo_byte(c, ldata);
 	}
-	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -852,16 +936,12 @@ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
  *
  *	This variant tags control characters to be echoed as "^X"
  *	(where X is the letter representing the control char).
- *
- *	Locking: echo_lock to protect the echo buffer
  */
 
 static void echo_char(unsigned char c, struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 
-	mutex_lock(&ldata->echo_lock);
-
 	if (c == ECHO_OP_START) {
 		add_echo_byte(ECHO_OP_START, ldata);
 		add_echo_byte(ECHO_OP_START, ldata);
@@ -870,8 +950,6 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
 			add_echo_byte(ECHO_OP_START, ldata);
 		add_echo_byte(c, ldata);
 	}
-
-	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -896,17 +974,22 @@ static inline void finish_erasing(struct n_tty_data *ldata)
  *	present in the stream from the driver layer. Handles the complexities
  *	of UTF-8 multibyte symbols.
  *
- *	Locking: read_lock for tty buffers
+ *	n_tty_receive_buf()/producer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		modifies read_head
+ *
+ *	Modifying the read_head is not considered a publish in this context
+ *	because canonical mode is active -- only canon_head publishes
  */
 
 static void eraser(unsigned char c, struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 	enum { ERASE, WERASE, KILL } kill_type;
-	int head, seen_alnums, cnt;
-	unsigned long flags;
+	size_t head;
+	size_t cnt;
+	int seen_alnums;
 
-	/* FIXME: locking needed ? */
 	if (ldata->read_head == ldata->canon_head) {
 		/* process_output('\a', tty); */ /* what do you think? */
 		return;
@@ -917,19 +1000,11 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 		kill_type = WERASE;
 	else {
 		if (!L_ECHO(tty)) {
-			raw_spin_lock_irqsave(&ldata->read_lock, flags);
-			ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
-					  (N_TTY_BUF_SIZE - 1));
 			ldata->read_head = ldata->canon_head;
-			raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 			return;
 		}
 		if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
-			raw_spin_lock_irqsave(&ldata->read_lock, flags);
-			ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
-					  (N_TTY_BUF_SIZE - 1));
 			ldata->read_head = ldata->canon_head;
-			raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 			finish_erasing(ldata);
 			echo_char(KILL_CHAR(tty), tty);
 			/* Add a newline if ECHOK is on and ECHOKE is off. */
@@ -941,14 +1016,13 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 	}
 
 	seen_alnums = 0;
-	/* FIXME: Locking ?? */
 	while (ldata->read_head != ldata->canon_head) {
 		head = ldata->read_head;
 
 		/* erase a single possibly multibyte character */
 		do {
-			head = (head - 1) & (N_TTY_BUF_SIZE-1);
-			c = ldata->read_buf[head];
+			head--;
+			c = read_buf(ldata, head);
 		} while (is_continuation(c, tty) && head != ldata->canon_head);
 
 		/* do not partially erase */
@@ -962,11 +1036,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 			else if (seen_alnums)
 				break;
 		}
-		cnt = (ldata->read_head - head) & (N_TTY_BUF_SIZE-1);
-		raw_spin_lock_irqsave(&ldata->read_lock, flags);
+		cnt = ldata->read_head - head;
 		ldata->read_head = head;
-		ldata->read_cnt -= cnt;
-		raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 		if (L_ECHO(tty)) {
 			if (L_ECHOPRT(tty)) {
 				if (!ldata->erasing) {
@@ -976,9 +1047,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 				/* if cnt > 1, output a multi-byte character */
 				echo_char(c, tty);
 				while (--cnt > 0) {
-					head = (head+1) & (N_TTY_BUF_SIZE-1);
-					echo_char_raw(ldata->read_buf[head],
-							ldata);
+					head++;
+					echo_char_raw(read_buf(ldata, head), ldata);
 					echo_move_back_col(ldata);
 				}
 			} else if (kill_type == ERASE && !L_ECHOE(tty)) {
@@ -986,7 +1056,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 			} else if (c == '\t') {
 				unsigned int num_chars = 0;
 				int after_tab = 0;
-				unsigned long tail = ldata->read_head;
+				size_t tail = ldata->read_head;
 
 				/*
 				 * Count the columns used for characters
@@ -996,8 +1066,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 				 * number of columns.
 				 */
 				while (tail != ldata->canon_head) {
-					tail = (tail-1) & (N_TTY_BUF_SIZE-1);
-					c = ldata->read_buf[tail];
+					tail--;
+					c = read_buf(ldata, tail);
 					if (c == '\t') {
 						after_tab = 1;
 						break;
@@ -1040,7 +1110,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
  *	Locking: ctrl_lock
  */
 
-static inline void isig(int sig, struct tty_struct *tty)
+static void isig(int sig, struct tty_struct *tty)
 {
 	struct pid *tty_pgrp = tty_get_pgrp(tty);
 	if (tty_pgrp) {
@@ -1056,10 +1126,14 @@ static inline void isig(int sig, struct tty_struct *tty)
  *	An RS232 break event has been hit in the incoming bitstream. This
  *	can cause a variety of events depending upon the termios settings.
  *
- *	Called from the receive_buf path so single threaded.
+ *	n_tty_receive_buf()/producer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		publishes read_head via put_tty_queue()
+ *
+ *	Note: may get exclusive termios_rwsem if flushing input buffer
  */
 
-static inline void n_tty_receive_break(struct tty_struct *tty)
+static void n_tty_receive_break(struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 
@@ -1068,8 +1142,11 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
 	if (I_BRKINT(tty)) {
 		isig(SIGINT, tty);
 		if (!L_NOFLSH(tty)) {
+			/* flushing needs exclusive termios_rwsem */
+			up_read(&tty->termios_rwsem);
 			n_tty_flush_buffer(tty);
 			tty_driver_flush_buffer(tty);
+			down_read(&tty->termios_rwsem);
 		}
 		return;
 	}
@@ -1094,7 +1171,7 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
  *	private.
  */
 
-static inline void n_tty_receive_overrun(struct tty_struct *tty)
+static void n_tty_receive_overrun(struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 	char buf[64];
@@ -1116,10 +1193,13 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
  *	@c: character
  *
  *	Process a parity error and queue the right data to indicate
- *	the error case if necessary. Locking as per n_tty_receive_buf.
+ *	the error case if necessary.
+ *
+ *	n_tty_receive_buf()/producer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		publishes read_head via put_tty_queue()
  */
-static inline void n_tty_receive_parity_error(struct tty_struct *tty,
-					      unsigned char c)
+static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 
@@ -1136,6 +1216,26 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 	wake_up_interruptible(&tty->read_wait);
 }
 
+static void
+n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
+{
+	if (!L_NOFLSH(tty)) {
+		/* flushing needs exclusive termios_rwsem */
+		up_read(&tty->termios_rwsem);
+		n_tty_flush_buffer(tty);
+		tty_driver_flush_buffer(tty);
+		down_read(&tty->termios_rwsem);
+	}
+	if (I_IXON(tty))
+		start_tty(tty);
+	if (L_ECHO(tty)) {
+		echo_char(c, tty);
+		commit_echoes(tty);
+	}
+	isig(signal, tty);
+	return;
+}
+
 /**
  *	n_tty_receive_char	-	perform processing
  *	@tty: terminal device
@@ -1144,117 +1244,54 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
  *	Process an individual character of input received from the driver.
  *	This is serialized with respect to itself by the rules for the
  *	driver above.
+ *
+ *	n_tty_receive_buf()/producer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		publishes canon_head if canonical mode is active
+ *		otherwise, publishes read_head via put_tty_queue()
+ *
+ *	Returns 1 if LNEXT was received, else returns 0
  */
 
-static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
+static int
+n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
 {
 	struct n_tty_data *ldata = tty->disc_data;
-	unsigned long flags;
 	int parmrk;
 
-	if (ldata->raw) {
-		put_tty_queue(c, ldata);
-		return;
-	}
-
-	if (I_ISTRIP(tty))
-		c &= 0x7f;
-	if (I_IUCLC(tty) && L_IEXTEN(tty))
-		c = tolower(c);
-
-	if (L_EXTPROC(tty)) {
-		put_tty_queue(c, ldata);
-		return;
-	}
-
-	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
-	    I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) &&
-	    c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) {
-		start_tty(tty);
-		process_echoes(tty);
-	}
-
-	if (tty->closing) {
-		if (I_IXON(tty)) {
-			if (c == START_CHAR(tty)) {
-				start_tty(tty);
-				process_echoes(tty);
-			} else if (c == STOP_CHAR(tty))
-				stop_tty(tty);
-		}
-		return;
-	}
-
-	/*
-	 * If the previous character was LNEXT, or we know that this
-	 * character is not one of the characters that we'll have to
-	 * handle specially, do shortcut processing to speed things
-	 * up.
-	 */
-	if (!test_bit(c, ldata->process_char_map) || ldata->lnext) {
-		ldata->lnext = 0;
-		parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-		if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
-			/* beep if no space */
-			if (L_ECHO(tty))
-				process_output('\a', tty);
-			return;
-		}
-		if (L_ECHO(tty)) {
-			finish_erasing(ldata);
-			/* Record the column of first canon char. */
-			if (ldata->canon_head == ldata->read_head)
-				echo_set_canon_col(ldata);
-			echo_char(c, tty);
-			process_echoes(tty);
-		}
-		if (parmrk)
-			put_tty_queue(c, ldata);
-		put_tty_queue(c, ldata);
-		return;
-	}
-
 	if (I_IXON(tty)) {
 		if (c == START_CHAR(tty)) {
 			start_tty(tty);
-			process_echoes(tty);
-			return;
+			commit_echoes(tty);
+			return 0;
 		}
 		if (c == STOP_CHAR(tty)) {
 			stop_tty(tty);
-			return;
+			return 0;
 		}
 	}
 
 	if (L_ISIG(tty)) {
-		int signal;
-		signal = SIGINT;
-		if (c == INTR_CHAR(tty))
-			goto send_signal;
-		signal = SIGQUIT;
-		if (c == QUIT_CHAR(tty))
-			goto send_signal;
-		signal = SIGTSTP;
-		if (c == SUSP_CHAR(tty)) {
-send_signal:
-			if (!L_NOFLSH(tty)) {
-				n_tty_flush_buffer(tty);
-				tty_driver_flush_buffer(tty);
-			}
-			if (I_IXON(tty))
-				start_tty(tty);
-			if (L_ECHO(tty)) {
-				echo_char(c, tty);
-				process_echoes(tty);
-			}
-			isig(signal, tty);
-			return;
+		if (c == INTR_CHAR(tty)) {
+			n_tty_receive_signal_char(tty, SIGINT, c);
+			return 0;
+		} else if (c == QUIT_CHAR(tty)) {
+			n_tty_receive_signal_char(tty, SIGQUIT, c);
+			return 0;
+		} else if (c == SUSP_CHAR(tty)) {
+			n_tty_receive_signal_char(tty, SIGTSTP, c);
+			return 0;
 		}
 	}
 
+	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) {
+		start_tty(tty);
+		process_echoes(tty);
+	}
+
 	if (c == '\r') {
 		if (I_IGNCR(tty))
-			return;
+			return 0;
 		if (I_ICRNL(tty))
 			c = '\n';
 	} else if (c == '\n' && I_INLCR(tty))
@@ -1264,8 +1301,8 @@ send_signal:
 		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
 		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
 			eraser(c, tty);
-			process_echoes(tty);
-			return;
+			commit_echoes(tty);
+			return 0;
 		}
 		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
 			ldata->lnext = 1;
@@ -1274,42 +1311,32 @@ send_signal:
 				if (L_ECHOCTL(tty)) {
 					echo_char_raw('^', ldata);
 					echo_char_raw('\b', ldata);
-					process_echoes(tty);
+					commit_echoes(tty);
 				}
 			}
-			return;
+			return 1;
 		}
-		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
-		    L_IEXTEN(tty)) {
-			unsigned long tail = ldata->canon_head;
+		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) {
+			size_t tail = ldata->canon_head;
 
 			finish_erasing(ldata);
 			echo_char(c, tty);
 			echo_char_raw('\n', ldata);
 			while (tail != ldata->read_head) {
-				echo_char(ldata->read_buf[tail], tty);
-				tail = (tail+1) & (N_TTY_BUF_SIZE-1);
+				echo_char(read_buf(ldata, tail), tty);
+				tail++;
 			}
-			process_echoes(tty);
-			return;
+			commit_echoes(tty);
+			return 0;
 		}
 		if (c == '\n') {
-			if (ldata->read_cnt >= N_TTY_BUF_SIZE) {
-				if (L_ECHO(tty))
-					process_output('\a', tty);
-				return;
-			}
 			if (L_ECHO(tty) || L_ECHONL(tty)) {
 				echo_char_raw('\n', ldata);
-				process_echoes(tty);
+				commit_echoes(tty);
 			}
 			goto handle_newline;
 		}
 		if (c == EOF_CHAR(tty)) {
-			if (ldata->read_cnt >= N_TTY_BUF_SIZE)
-				return;
-			if (ldata->canon_head != ldata->read_head)
-				set_bit(TTY_PUSH, &tty->flags);
 			c = __DISABLED_CHAR;
 			goto handle_newline;
 		}
@@ -1317,11 +1344,6 @@ send_signal:
 		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
 			parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
 				 ? 1 : 0;
-			if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
-				if (L_ECHO(tty))
-					process_output('\a', tty);
-				return;
-			}
 			/*
 			 * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
 			 */
@@ -1330,7 +1352,7 @@ send_signal:
 				if (ldata->canon_head == ldata->read_head)
 					echo_set_canon_col(ldata);
 				echo_char(c, tty);
-				process_echoes(tty);
+				commit_echoes(tty);
 			}
 			/*
 			 * XXX does PARMRK doubling happen for
@@ -1340,26 +1362,17 @@ send_signal:
 				put_tty_queue(c, ldata);
 
 handle_newline:
-			raw_spin_lock_irqsave(&ldata->read_lock, flags);
-			set_bit(ldata->read_head, ldata->read_flags);
-			put_tty_queue_nolock(c, ldata);
+			set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags);
+			put_tty_queue(c, ldata);
 			ldata->canon_head = ldata->read_head;
-			ldata->canon_data++;
-			raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 			if (waitqueue_active(&tty->read_wait))
 				wake_up_interruptible(&tty->read_wait);
-			return;
+			return 0;
 		}
 	}
 
 	parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-	if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
-		/* beep if no space */
-		if (L_ECHO(tty))
-			process_output('\a', tty);
-		return;
-	}
 	if (L_ECHO(tty)) {
 		finish_erasing(ldata);
 		if (c == '\n')
@@ -1370,29 +1383,123 @@ handle_newline:
 				echo_set_canon_col(ldata);
 			echo_char(c, tty);
 		}
-		process_echoes(tty);
+		commit_echoes(tty);
 	}
 
 	if (parmrk)
 		put_tty_queue(c, ldata);
 
 	put_tty_queue(c, ldata);
+	return 0;
 }
 
+static inline void
+n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	int parmrk;
 
-/**
- *	n_tty_write_wakeup	-	asynchronous I/O notifier
- *	@tty: tty device
- *
- *	Required for the ptys, serial driver etc. since processes
- *	that attach themselves to the master and rely on ASYNC
- *	IO must be woken up
- */
+	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) {
+		start_tty(tty);
+		process_echoes(tty);
+	}
+	if (L_ECHO(tty)) {
+		finish_erasing(ldata);
+		/* Record the column of first canon char. */
+		if (ldata->canon_head == ldata->read_head)
+			echo_set_canon_col(ldata);
+		echo_char(c, tty);
+		commit_echoes(tty);
+	}
+	parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
+	if (parmrk)
+		put_tty_queue(c, ldata);
+	put_tty_queue(c, ldata);
+}
 
-static void n_tty_write_wakeup(struct tty_struct *tty)
+static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
-	if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
-		kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
+	n_tty_receive_char_inline(tty, c);
+}
+
+static inline void
+n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+
+	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) {
+		start_tty(tty);
+		process_echoes(tty);
+	}
+	if (L_ECHO(tty)) {
+		finish_erasing(ldata);
+		/* Record the column of first canon char. */
+		if (ldata->canon_head == ldata->read_head)
+			echo_set_canon_col(ldata);
+		echo_char(c, tty);
+		commit_echoes(tty);
+	}
+	put_tty_queue(c, ldata);
+}
+
+static inline void
+n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
+{
+	if (I_ISTRIP(tty))
+		c &= 0x7f;
+	if (I_IUCLC(tty) && L_IEXTEN(tty))
+		c = tolower(c);
+
+	if (I_IXON(tty)) {
+		if (c == STOP_CHAR(tty))
+			stop_tty(tty);
+		else if (c == START_CHAR(tty) ||
+			 (tty->stopped && !tty->flow_stopped && I_IXANY(tty) &&
+			  c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) &&
+			  c != SUSP_CHAR(tty))) {
+			start_tty(tty);
+			process_echoes(tty);
+		}
+	}
+}
+
+static void
+n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag)
+{
+	char buf[64];
+
+	switch (flag) {
+	case TTY_BREAK:
+		n_tty_receive_break(tty);
+		break;
+	case TTY_PARITY:
+	case TTY_FRAME:
+		n_tty_receive_parity_error(tty, c);
+		break;
+	case TTY_OVERRUN:
+		n_tty_receive_overrun(tty);
+		break;
+	default:
+		printk(KERN_ERR "%s: unknown flag %d\n",
+		       tty_name(tty, buf), flag);
+		break;
+	}
+}
+
+static void
+n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+
+	ldata->lnext = 0;
+	if (likely(flag == TTY_NORMAL)) {
+		if (I_ISTRIP(tty))
+			c &= 0x7f;
+		if (I_IUCLC(tty) && L_IEXTEN(tty))
+			c = tolower(c);
+		n_tty_receive_char(tty, c);
+	} else
+		n_tty_receive_char_flagged(tty, c, flag);
 }
 
 /**
@@ -1406,86 +1513,220 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
  *	been received. This function must be called from soft contexts
  *	not from interrupt context. The driver is responsible for making
  *	calls one at a time and in order (or using flush_to_ldisc)
+ *
+ *	n_tty_receive_buf()/producer path:
+ *		claims non-exclusive termios_rwsem
+ *		publishes read_head and canon_head
  */
 
-static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-			      char *fp, int count)
+static void
+n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp,
+			   char *fp, int count)
 {
 	struct n_tty_data *ldata = tty->disc_data;
-	const unsigned char *p;
-	char *f, flags = TTY_NORMAL;
-	int	i;
-	char	buf[64];
-	unsigned long cpuflags;
-
-	if (ldata->real_raw) {
-		raw_spin_lock_irqsave(&ldata->read_lock, cpuflags);
-		i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
-			N_TTY_BUF_SIZE - ldata->read_head);
-		i = min(count, i);
-		memcpy(ldata->read_buf + ldata->read_head, cp, i);
-		ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
-		ldata->read_cnt += i;
-		cp += i;
-		count -= i;
-
-		i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
-			N_TTY_BUF_SIZE - ldata->read_head);
-		i = min(count, i);
-		memcpy(ldata->read_buf + ldata->read_head, cp, i);
-		ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
-		ldata->read_cnt += i;
-		raw_spin_unlock_irqrestore(&ldata->read_lock, cpuflags);
-	} else {
-		for (i = count, p = cp, f = fp; i; i--, p++) {
-			if (f)
-				flags = *f++;
-			switch (flags) {
-			case TTY_NORMAL:
-				n_tty_receive_char(tty, *p);
-				break;
-			case TTY_BREAK:
-				n_tty_receive_break(tty);
-				break;
-			case TTY_PARITY:
-			case TTY_FRAME:
-				n_tty_receive_parity_error(tty, *p);
-				break;
-			case TTY_OVERRUN:
-				n_tty_receive_overrun(tty);
-				break;
-			default:
-				printk(KERN_ERR "%s: unknown flag %d\n",
-				       tty_name(tty, buf), flags);
-				break;
+	size_t n, head;
+
+	head = ldata->read_head & (N_TTY_BUF_SIZE - 1);
+	n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head);
+	n = min_t(size_t, count, n);
+	memcpy(read_buf_addr(ldata, head), cp, n);
+	ldata->read_head += n;
+	cp += n;
+	count -= n;
+
+	head = ldata->read_head & (N_TTY_BUF_SIZE - 1);
+	n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head);
+	n = min_t(size_t, count, n);
+	memcpy(read_buf_addr(ldata, head), cp, n);
+	ldata->read_head += n;
+}
+
+static void
+n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp,
+		      char *fp, int count)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	char flag = TTY_NORMAL;
+
+	while (count--) {
+		if (fp)
+			flag = *fp++;
+		if (likely(flag == TTY_NORMAL))
+			put_tty_queue(*cp++, ldata);
+		else
+			n_tty_receive_char_flagged(tty, *cp++, flag);
+	}
+}
+
+static void
+n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp,
+			  char *fp, int count)
+{
+	char flag = TTY_NORMAL;
+
+	while (count--) {
+		if (fp)
+			flag = *fp++;
+		if (likely(flag == TTY_NORMAL))
+			n_tty_receive_char_closing(tty, *cp++);
+		else
+			n_tty_receive_char_flagged(tty, *cp++, flag);
+	}
+}
+
+static void
+n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp,
+			  char *fp, int count)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	char flag = TTY_NORMAL;
+
+	while (count--) {
+		if (fp)
+			flag = *fp++;
+		if (likely(flag == TTY_NORMAL)) {
+			unsigned char c = *cp++;
+
+			if (I_ISTRIP(tty))
+				c &= 0x7f;
+			if (I_IUCLC(tty) && L_IEXTEN(tty))
+				c = tolower(c);
+			if (L_EXTPROC(tty)) {
+				put_tty_queue(c, ldata);
+				continue;
+			}
+			if (!test_bit(c, ldata->char_map))
+				n_tty_receive_char_inline(tty, c);
+			else if (n_tty_receive_char_special(tty, c) && count) {
+				if (fp)
+					flag = *fp++;
+				n_tty_receive_char_lnext(tty, *cp++, flag);
+				count--;
+			}
+		} else
+			n_tty_receive_char_flagged(tty, *cp++, flag);
+	}
+}
+
+static void
+n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp,
+		       char *fp, int count)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	char flag = TTY_NORMAL;
+
+	while (count--) {
+		if (fp)
+			flag = *fp++;
+		if (likely(flag == TTY_NORMAL)) {
+			unsigned char c = *cp++;
+
+			if (!test_bit(c, ldata->char_map))
+				n_tty_receive_char_fast(tty, c);
+			else if (n_tty_receive_char_special(tty, c) && count) {
+				if (fp)
+					flag = *fp++;
+				n_tty_receive_char_lnext(tty, *cp++, flag);
+				count--;
 			}
+		} else
+			n_tty_receive_char_flagged(tty, *cp++, flag);
+	}
+}
+
+static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
+			  char *fp, int count)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty));
+
+	if (ldata->real_raw)
+		n_tty_receive_buf_real_raw(tty, cp, fp, count);
+	else if (ldata->raw || (L_EXTPROC(tty) && !preops))
+		n_tty_receive_buf_raw(tty, cp, fp, count);
+	else if (tty->closing && !L_EXTPROC(tty))
+		n_tty_receive_buf_closing(tty, cp, fp, count);
+	else {
+		if (ldata->lnext) {
+			char flag = TTY_NORMAL;
+
+			if (fp)
+				flag = *fp++;
+			n_tty_receive_char_lnext(tty, *cp++, flag);
+			count--;
 		}
+
+		if (!preops && !I_PARMRK(tty))
+			n_tty_receive_buf_fast(tty, cp, fp, count);
+		else
+			n_tty_receive_buf_standard(tty, cp, fp, count);
+
+		flush_echoes(tty);
 		if (tty->ops->flush_chars)
 			tty->ops->flush_chars(tty);
 	}
 
-	set_room(tty);
-
-	if ((!ldata->icanon && (ldata->read_cnt >= ldata->minimum_to_wake)) ||
+	if ((!ldata->icanon && (read_cnt(ldata) >= ldata->minimum_to_wake)) ||
 		L_EXTPROC(tty)) {
 		kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 		if (waitqueue_active(&tty->read_wait))
 			wake_up_interruptible(&tty->read_wait);
 	}
+}
+
+static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+			      char *fp, int count)
+{
+	int room, n;
+
+	down_read(&tty->termios_rwsem);
 
-	/*
-	 * Check the remaining room for the input canonicalization
-	 * mode.  We don't want to throttle the driver if we're in
-	 * canonical mode and don't have a newline yet!
-	 */
 	while (1) {
-		tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
-		if (tty->receive_room >= TTY_THRESHOLD_THROTTLE)
+		room = receive_room(tty);
+		n = min(count, room);
+		if (!n)
 			break;
-		if (!tty_throttle_safe(tty))
+		__receive_buf(tty, cp, fp, n);
+		cp += n;
+		if (fp)
+			fp += n;
+		count -= n;
+	}
+
+	tty->receive_room = room;
+	n_tty_check_throttle(tty);
+	up_read(&tty->termios_rwsem);
+}
+
+static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
+			      char *fp, int count)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	int room, n, rcvd = 0;
+
+	down_read(&tty->termios_rwsem);
+
+	while (1) {
+		room = receive_room(tty);
+		n = min(count, room);
+		if (!n) {
+			if (!room)
+				ldata->no_room = 1;
 			break;
+		}
+		__receive_buf(tty, cp, fp, n);
+		cp += n;
+		if (fp)
+			fp += n;
+		count -= n;
+		rcvd += n;
 	}
-	__tty_set_flow_change(tty, 0);
+
+	tty->receive_room = room;
+	n_tty_check_throttle(tty);
+	up_read(&tty->termios_rwsem);
+
+	return rcvd;
 }
 
 int is_ignored(int sig)
@@ -1505,7 +1746,7 @@ int is_ignored(int sig)
  *	guaranteed that this function will not be re-entered or in progress
  *	when the ldisc is closed.
  *
- *	Locking: Caller holds tty->termios_mutex
+ *	Locking: Caller holds tty->termios_rwsem
  */
 
 static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
@@ -1517,12 +1758,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 		canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
 	if (canon_change) {
 		bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
+		ldata->line_start = 0;
 		ldata->canon_head = ldata->read_tail;
-		ldata->canon_data = 0;
 		ldata->erasing = 0;
+		ldata->lnext = 0;
 	}
 
-	if (canon_change && !L_ICANON(tty) && ldata->read_cnt)
+	if (canon_change && !L_ICANON(tty) && read_cnt(ldata))
 		wake_up_interruptible(&tty->read_wait);
 
 	ldata->icanon = (L_ICANON(tty) != 0);
@@ -1531,41 +1773,38 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
 	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
 	    I_PARMRK(tty)) {
-		bitmap_zero(ldata->process_char_map, 256);
+		bitmap_zero(ldata->char_map, 256);
 
 		if (I_IGNCR(tty) || I_ICRNL(tty))
-			set_bit('\r', ldata->process_char_map);
+			set_bit('\r', ldata->char_map);
 		if (I_INLCR(tty))
-			set_bit('\n', ldata->process_char_map);
+			set_bit('\n', ldata->char_map);
 
 		if (L_ICANON(tty)) {
-			set_bit(ERASE_CHAR(tty), ldata->process_char_map);
-			set_bit(KILL_CHAR(tty), ldata->process_char_map);
-			set_bit(EOF_CHAR(tty), ldata->process_char_map);
-			set_bit('\n', ldata->process_char_map);
-			set_bit(EOL_CHAR(tty), ldata->process_char_map);
+			set_bit(ERASE_CHAR(tty), ldata->char_map);
+			set_bit(KILL_CHAR(tty), ldata->char_map);
+			set_bit(EOF_CHAR(tty), ldata->char_map);
+			set_bit('\n', ldata->char_map);
+			set_bit(EOL_CHAR(tty), ldata->char_map);
 			if (L_IEXTEN(tty)) {
-				set_bit(WERASE_CHAR(tty),
-					ldata->process_char_map);
-				set_bit(LNEXT_CHAR(tty),
-					ldata->process_char_map);
-				set_bit(EOL2_CHAR(tty),
-					ldata->process_char_map);
+				set_bit(WERASE_CHAR(tty), ldata->char_map);
+				set_bit(LNEXT_CHAR(tty), ldata->char_map);
+				set_bit(EOL2_CHAR(tty), ldata->char_map);
 				if (L_ECHO(tty))
 					set_bit(REPRINT_CHAR(tty),
-						ldata->process_char_map);
+						ldata->char_map);
 			}
 		}
 		if (I_IXON(tty)) {
-			set_bit(START_CHAR(tty), ldata->process_char_map);
-			set_bit(STOP_CHAR(tty), ldata->process_char_map);
+			set_bit(START_CHAR(tty), ldata->char_map);
+			set_bit(STOP_CHAR(tty), ldata->char_map);
 		}
 		if (L_ISIG(tty)) {
-			set_bit(INTR_CHAR(tty), ldata->process_char_map);
-			set_bit(QUIT_CHAR(tty), ldata->process_char_map);
-			set_bit(SUSP_CHAR(tty), ldata->process_char_map);
+			set_bit(INTR_CHAR(tty), ldata->char_map);
+			set_bit(QUIT_CHAR(tty), ldata->char_map);
+			set_bit(SUSP_CHAR(tty), ldata->char_map);
 		}
-		clear_bit(__DISABLED_CHAR, ldata->process_char_map);
+		clear_bit(__DISABLED_CHAR, ldata->char_map);
 		ldata->raw = 0;
 		ldata->real_raw = 0;
 	} else {
@@ -1608,9 +1847,7 @@ static void n_tty_close(struct tty_struct *tty)
 	if (tty->link)
 		n_tty_packet_mode_flush(tty);
 
-	kfree(ldata->read_buf);
-	kfree(ldata->echo_buf);
-	kfree(ldata);
+	vfree(ldata);
 	tty->disc_data = NULL;
 }
 
@@ -1628,26 +1865,23 @@ static int n_tty_open(struct tty_struct *tty)
 {
 	struct n_tty_data *ldata;
 
-	ldata = kzalloc(sizeof(*ldata), GFP_KERNEL);
+	/* Currently a malloc failure here can panic */
+	ldata = vmalloc(sizeof(*ldata));
 	if (!ldata)
 		goto err;
 
 	ldata->overrun_time = jiffies;
 	mutex_init(&ldata->atomic_read_lock);
 	mutex_init(&ldata->output_lock);
-	mutex_init(&ldata->echo_lock);
-	raw_spin_lock_init(&ldata->read_lock);
-
-	/* These are ugly. Currently a malloc failure here can panic */
-	ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
-	ldata->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
-	if (!ldata->read_buf || !ldata->echo_buf)
-		goto err_free_bufs;
 
 	tty->disc_data = ldata;
 	reset_buffer_flags(tty->disc_data);
 	ldata->column = 0;
+	ldata->canon_column = 0;
 	ldata->minimum_to_wake = 1;
+	ldata->num_overrun = 0;
+	ldata->no_room = 0;
+	ldata->lnext = 0;
 	tty->closing = 0;
 	/* indicate buffer work may resume */
 	clear_bit(TTY_LDISC_HALTED, &tty->flags);
@@ -1655,10 +1889,6 @@ static int n_tty_open(struct tty_struct *tty)
 	tty_unthrottle(tty);
 
 	return 0;
-err_free_bufs:
-	kfree(ldata->read_buf);
-	kfree(ldata->echo_buf);
-	kfree(ldata);
 err:
 	return -ENOMEM;
 }
@@ -1667,11 +1897,10 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 
-	tty_flush_to_ldisc(tty);
 	if (ldata->icanon && !L_EXTPROC(tty)) {
-		if (ldata->canon_data)
+		if (ldata->canon_head != ldata->read_tail)
 			return 1;
-	} else if (ldata->read_cnt >= (amt ? amt : 1))
+	} else if (read_cnt(ldata) >= (amt ? amt : 1))
 		return 1;
 
 	return 0;
@@ -1692,6 +1921,9 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
  *
  *	Called under the ldata->atomic_read_lock sem
  *
+ *	n_tty_read()/consumer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		read_tail published
  */
 
 static int copy_from_read_buf(struct tty_struct *tty,
@@ -1702,34 +1934,114 @@ static int copy_from_read_buf(struct tty_struct *tty,
 	struct n_tty_data *ldata = tty->disc_data;
 	int retval;
 	size_t n;
-	unsigned long flags;
 	bool is_eof;
+	size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
 
 	retval = 0;
-	raw_spin_lock_irqsave(&ldata->read_lock, flags);
-	n = min(ldata->read_cnt, N_TTY_BUF_SIZE - ldata->read_tail);
+	n = min(read_cnt(ldata), N_TTY_BUF_SIZE - tail);
 	n = min(*nr, n);
-	raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 	if (n) {
-		retval = copy_to_user(*b, &ldata->read_buf[ldata->read_tail], n);
+		retval = copy_to_user(*b, read_buf_addr(ldata, tail), n);
 		n -= retval;
-		is_eof = n == 1 &&
-			ldata->read_buf[ldata->read_tail] == EOF_CHAR(tty);
-		tty_audit_add_data(tty, &ldata->read_buf[ldata->read_tail], n,
+		is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty);
+		tty_audit_add_data(tty, read_buf_addr(ldata, tail), n,
 				ldata->icanon);
-		raw_spin_lock_irqsave(&ldata->read_lock, flags);
-		ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1);
-		ldata->read_cnt -= n;
+		ldata->read_tail += n;
 		/* Turn single EOF into zero-length read */
-		if (L_EXTPROC(tty) && ldata->icanon && is_eof && !ldata->read_cnt)
+		if (L_EXTPROC(tty) && ldata->icanon && is_eof && !read_cnt(ldata))
 			n = 0;
-		raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 		*b += n;
 		*nr -= n;
 	}
 	return retval;
 }
 
+/**
+ *	canon_copy_from_read_buf	-	copy read data in canonical mode
+ *	@tty: terminal device
+ *	@b: user data
+ *	@nr: size of data
+ *
+ *	Helper function for n_tty_read.  It is only called when ICANON is on;
+ *	it copies one line of input up to and including the line-delimiting
+ *	character into the user-space buffer.
+ *
+ *	Called under the atomic_read_lock mutex
+ *
+ *	n_tty_read()/consumer path:
+ *		caller holds non-exclusive termios_rwsem
+ *		read_tail published
+ */
+
+static int canon_copy_from_read_buf(struct tty_struct *tty,
+				    unsigned char __user **b,
+				    size_t *nr)
+{
+	struct n_tty_data *ldata = tty->disc_data;
+	size_t n, size, more, c;
+	size_t eol;
+	size_t tail;
+	int ret, found = 0;
+	bool eof_push = 0;
+
+	/* N.B. avoid overrun if nr == 0 */
+	n = min(*nr, read_cnt(ldata));
+	if (!n)
+		return 0;
+
+	tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
+	size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
+
+	n_tty_trace("%s: nr:%zu tail:%zu n:%zu size:%zu\n",
+		    __func__, *nr, tail, n, size);
+
+	eol = find_next_bit(ldata->read_flags, size, tail);
+	more = n - (size - tail);
+	if (eol == N_TTY_BUF_SIZE && more) {
+		/* scan wrapped without finding set bit */
+		eol = find_next_bit(ldata->read_flags, more, 0);
+		if (eol != more)
+			found = 1;
+	} else if (eol != size)
+		found = 1;
+
+	size = N_TTY_BUF_SIZE - tail;
+	n = (found + eol + size) & (N_TTY_BUF_SIZE - 1);
+	c = n;
+
+	if (found && read_buf(ldata, eol) == __DISABLED_CHAR) {
+		n--;
+		eof_push = !n && ldata->read_tail != ldata->line_start;
+	}
+
+	n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
+		    __func__, eol, found, n, c, size, more);
+
+	if (n > size) {
+		ret = copy_to_user(*b, read_buf_addr(ldata, tail), size);
+		if (ret)
+			return -EFAULT;
+		ret = copy_to_user(*b + size, ldata->read_buf, n - size);
+	} else
+		ret = copy_to_user(*b, read_buf_addr(ldata, tail), n);
+
+	if (ret)
+		return -EFAULT;
+	*b += n;
+	*nr -= n;
+
+	if (found)
+		clear_bit(eol, ldata->read_flags);
+	smp_mb__after_clear_bit();
+	ldata->read_tail += c;
+
+	if (found) {
+		ldata->line_start = ldata->read_tail;
+		tty_audit_push(tty);
+	}
+	return eof_push ? -EAGAIN : 0;
+}
+
 extern ssize_t redirected_tty_write(struct file *, const char __user *,
 							size_t, loff_t *);
 
@@ -1787,6 +2099,10 @@ static int job_control(struct tty_struct *tty, struct file *file)
  *	a hangup. Always called in user context, may sleep.
  *
  *	This code must be sure never to sleep through a hangup.
+ *
+ *	n_tty_read()/consumer path:
+ *		claims non-exclusive termios_rwsem
+ *		publishes read_tail
  */
 
 static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
@@ -1798,16 +2114,16 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 	int c;
 	int minimum, time;
 	ssize_t retval = 0;
-	ssize_t size;
 	long timeout;
 	unsigned long flags;
 	int packet;
 
-do_it_again:
 	c = job_control(tty, file);
 	if (c < 0)
 		return c;
 
+	down_read(&tty->termios_rwsem);
+
 	minimum = time = 0;
 	timeout = MAX_SCHEDULE_TIMEOUT;
 	if (!ldata->icanon) {
@@ -1829,11 +2145,15 @@ do_it_again:
 	 *	Internal serialization of reads.
 	 */
 	if (file->f_flags & O_NONBLOCK) {
-		if (!mutex_trylock(&ldata->atomic_read_lock))
+		if (!mutex_trylock(&ldata->atomic_read_lock)) {
+			up_read(&tty->termios_rwsem);
 			return -EAGAIN;
+		}
 	} else {
-		if (mutex_lock_interruptible(&ldata->atomic_read_lock))
+		if (mutex_lock_interruptible(&ldata->atomic_read_lock)) {
+			up_read(&tty->termios_rwsem);
 			return -ERESTARTSYS;
+		}
 	}
 	packet = tty->packet;
 
@@ -1883,7 +2203,11 @@ do_it_again:
 				break;
 			}
 			n_tty_set_room(tty);
+			up_read(&tty->termios_rwsem);
+
 			timeout = schedule_timeout(timeout);
+
+			down_read(&tty->termios_rwsem);
 			continue;
 		}
 		__set_current_state(TASK_RUNNING);
@@ -1899,45 +2223,11 @@ do_it_again:
 		}
 
 		if (ldata->icanon && !L_EXTPROC(tty)) {
-			/* N.B. avoid overrun if nr == 0 */
-			raw_spin_lock_irqsave(&ldata->read_lock, flags);
-			while (nr && ldata->read_cnt) {
-				int eol;
-
-				eol = test_and_clear_bit(ldata->read_tail,
-						ldata->read_flags);
-				c = ldata->read_buf[ldata->read_tail];
-				ldata->read_tail = ((ldata->read_tail+1) &
-						  (N_TTY_BUF_SIZE-1));
-				ldata->read_cnt--;
-				if (eol) {
-					/* this test should be redundant:
-					 * we shouldn't be reading data if
-					 * canon_data is 0
-					 */
-					if (--ldata->canon_data < 0)
-						ldata->canon_data = 0;
-				}
-				raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
-
-				if (!eol || (c != __DISABLED_CHAR)) {
-					if (tty_put_user(tty, c, b++)) {
-						retval = -EFAULT;
-						b--;
-						raw_spin_lock_irqsave(&ldata->read_lock, flags);
-						break;
-					}
-					nr--;
-				}
-				if (eol) {
-					tty_audit_push(tty);
-					raw_spin_lock_irqsave(&ldata->read_lock, flags);
-					break;
-				}
-				raw_spin_lock_irqsave(&ldata->read_lock, flags);
-			}
-			raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
-			if (retval)
+			retval = canon_copy_from_read_buf(tty, &b, &nr);
+			if (retval == -EAGAIN) {
+				retval = 0;
+				continue;
+			} else if (retval)
 				break;
 		} else {
 			int uncopied;
@@ -1951,24 +2241,7 @@ do_it_again:
 			}
 		}
 
-		/* If there is enough space in the read buffer now, let the
-		 * low-level driver know. We use n_tty_chars_in_buffer() to
-		 * check the buffer, as it now knows about canonical mode.
-		 * Otherwise, if the driver is throttled and the line is
-		 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
-		 * we won't get any more characters.
-		 */
-		while (1) {
-			tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
-			if (n_tty_chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
-				break;
-			if (!tty->count)
-				break;
-			n_tty_set_room(tty);
-			if (!tty_unthrottle_safe(tty))
-				break;
-		}
-		__tty_set_flow_change(tty, 0);
+		n_tty_check_unthrottle(tty);
 
 		if (b - buf >= minimum)
 			break;
@@ -1982,15 +2255,11 @@ do_it_again:
 		ldata->minimum_to_wake = minimum;
 
 	__set_current_state(TASK_RUNNING);
-	size = b - buf;
-	if (size) {
-		retval = size;
-		if (nr)
-			clear_bit(TTY_PUSH, &tty->flags);
-	} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
-		goto do_it_again;
+	if (b - buf)
+		retval = b - buf;
 
 	n_tty_set_room(tty);
+	up_read(&tty->termios_rwsem);
 	return retval;
 }
 
@@ -2031,6 +2300,8 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
 			return retval;
 	}
 
+	down_read(&tty->termios_rwsem);
+
 	/* Write out any echoed characters that are still pending */
 	process_echoes(tty);
 
@@ -2084,13 +2355,18 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
 			retval = -EAGAIN;
 			break;
 		}
+		up_read(&tty->termios_rwsem);
+
 		schedule();
+
+		down_read(&tty->termios_rwsem);
 	}
 break_out:
 	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&tty->write_wait, &wait);
 	if (b - buf != nr && tty->fasync)
 		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	up_read(&tty->termios_rwsem);
 	return (b - buf) ? b - buf : retval;
 }
 
@@ -2139,19 +2415,19 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
 
 static unsigned long inq_canon(struct n_tty_data *ldata)
 {
-	int nr, head, tail;
+	size_t nr, head, tail;
 
-	if (!ldata->canon_data)
+	if (ldata->canon_head == ldata->read_tail)
 		return 0;
 	head = ldata->canon_head;
 	tail = ldata->read_tail;
-	nr = (head - tail) & (N_TTY_BUF_SIZE-1);
+	nr = head - tail;
 	/* Skip EOF-chars.. */
 	while (head != tail) {
-		if (test_bit(tail, ldata->read_flags) &&
-		    ldata->read_buf[tail] == __DISABLED_CHAR)
+		if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) &&
+		    read_buf(ldata, tail) == __DISABLED_CHAR)
 			nr--;
-		tail = (tail+1) & (N_TTY_BUF_SIZE-1);
+		tail++;
 	}
 	return nr;
 }
@@ -2166,10 +2442,12 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
 	case TIOCOUTQ:
 		return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
 	case TIOCINQ:
-		/* FIXME: Locking */
-		retval = ldata->read_cnt;
+		down_write(&tty->termios_rwsem);
 		if (L_ICANON(tty))
 			retval = inq_canon(ldata);
+		else
+			retval = read_cnt(ldata);
+		up_write(&tty->termios_rwsem);
 		return put_user(retval, (unsigned int __user *) arg);
 	default:
 		return n_tty_ioctl_helper(tty, file, cmd, arg);
@@ -2203,6 +2481,7 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = {
 	.receive_buf     = n_tty_receive_buf,
 	.write_wakeup    = n_tty_write_wakeup,
 	.fasync		 = n_tty_fasync,
+	.receive_buf2	 = n_tty_receive_buf2,
 };
 
 /**
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index abfd990..25c9bc7 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -89,17 +89,13 @@ static void pty_unthrottle(struct tty_struct *tty)
  *	pty_space	-	report space left for writing
  *	@to: tty we are writing into
  *
- *	The tty buffers allow 64K but we sneak a peak and clip at 8K this
- *	allows a lot of overspill room for echo and other fun messes to
- *	be handled properly
+ *	Limit the buffer space used by ptys to 8k.
  */
 
 static int pty_space(struct tty_struct *to)
 {
-	int n = 8192 - to->port->buf.memory_used;
-	if (n < 0)
-		return 0;
-	return n;
+	int n = tty_buffer_space_avail(to->port);
+	return min(n, 8192);
 }
 
 /**
@@ -125,10 +121,8 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
 		/* Stuff the data into the input queue of the other end */
 		c = tty_insert_flip_string(to->port, buf, c);
 		/* And shovel */
-		if (c) {
+		if (c)
 			tty_flip_buffer_push(to->port);
-			tty_wakeup(tty);
-		}
 	}
 	return c;
 }
@@ -287,7 +281,7 @@ static int pty_resize(struct tty_struct *tty,  struct winsize *ws)
 	struct tty_struct *pty = tty->link;
 
 	/* For a PTY we need to lock the tty side */
-	mutex_lock(&tty->termios_mutex);
+	mutex_lock(&tty->winsize_mutex);
 	if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
 		goto done;
 
@@ -314,7 +308,7 @@ static int pty_resize(struct tty_struct *tty,  struct winsize *ws)
 	tty->winsize = *ws;
 	pty->winsize = *ws;	/* Never used so will go away soon */
 done:
-	mutex_unlock(&tty->termios_mutex);
+	mutex_unlock(&tty->winsize_mutex);
 	return 0;
 }
 
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 86c00b1..570df9d 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -3062,7 +3062,7 @@ void serial8250_resume_port(int line)
  */
 static int serial8250_probe(struct platform_device *dev)
 {
-	struct plat_serial8250_port *p = dev->dev.platform_data;
+	struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
 	struct uart_8250_port uart;
 	int ret, i, irqflag = 0;
 
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 916cc19..5f3bba1 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -95,25 +95,23 @@ static int serial8250_em_probe(struct platform_device *pdev)
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	struct serial8250_em_priv *priv;
 	struct uart_8250_port up;
-	int ret = -EINVAL;
+	int ret;
 
 	if (!regs || !irq) {
 		dev_err(&pdev->dev, "missing registers or irq\n");
-		goto err0;
+		return -EINVAL;
 	}
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		dev_err(&pdev->dev, "unable to allocate private data\n");
-		ret = -ENOMEM;
-		goto err0;
+		return -ENOMEM;
 	}
 
-	priv->sclk = clk_get(&pdev->dev, "sclk");
+	priv->sclk = devm_clk_get(&pdev->dev, "sclk");
 	if (IS_ERR(priv->sclk)) {
 		dev_err(&pdev->dev, "unable to get clock\n");
-		ret = PTR_ERR(priv->sclk);
-		goto err1;
+		return PTR_ERR(priv->sclk);
 	}
 
 	memset(&up, 0, sizeof(up));
@@ -136,20 +134,13 @@ static int serial8250_em_probe(struct platform_device *pdev)
 	ret = serial8250_register_8250_port(&up);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "unable to register 8250 port\n");
-		goto err2;
+		clk_disable(priv->sclk);
+		return ret;
 	}
 
 	priv->line = ret;
 	platform_set_drvdata(pdev, priv);
 	return 0;
-
- err2:
-	clk_disable(priv->sclk);
-	clk_put(priv->sclk);
- err1:
-	kfree(priv);
- err0:
-	return ret;
 }
 
 static int serial8250_em_remove(struct platform_device *pdev)
@@ -158,8 +149,6 @@ static int serial8250_em_remove(struct platform_device *pdev)
 
 	serial8250_unregister_port(priv->line);
 	clk_disable(priv->sclk);
-	clk_put(priv->sclk);
-	kfree(priv);
 	return 0;
 }
 
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index c52948b..c810da7 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1565,6 +1565,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
 #define PCI_DEVICE_ID_COMMTECH_4228PCIE	0x0021
 #define PCI_DEVICE_ID_COMMTECH_4222PCIE	0x0022
 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
+#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
 
 #define PCI_VENDOR_ID_SUNIX		0x1fd4
 #define PCI_DEVICE_ID_SUNIX_1999	0x1999
@@ -1587,8 +1588,8 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 	* ADDI-DATA GmbH communication cards <info@addi-data.com>
 	*/
 	{
-		.vendor         = PCI_VENDOR_ID_ADDIDATA_OLD,
-		.device         = PCI_DEVICE_ID_ADDIDATA_APCI7800,
+		.vendor         = PCI_VENDOR_ID_AMCC,
+		.device         = PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800,
 		.subvendor      = PCI_ANY_ID,
 		.subdevice      = PCI_ANY_ID,
 		.setup          = addidata_apci7800_setup,
@@ -4697,8 +4698,8 @@ static struct pci_device_id serial_pci_tbl[] = {
 		0,
 		pbn_b0_1_115200 },
 
-	{	PCI_VENDOR_ID_ADDIDATA_OLD,
-		PCI_DEVICE_ID_ADDIDATA_APCI7800,
+	{	PCI_VENDOR_ID_AMCC,
+		PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800,
 		PCI_ANY_ID,
 		PCI_ANY_ID,
 		0,
@@ -4797,6 +4798,12 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_VENDOR_ID_IBM, 0x0299,
 		0, 0, pbn_b0_bt_2_115200 },
 
+	/*
+	 * other NetMos 9835 devices are most likely handled by the
+	 * parport_serial driver, check drivers/parport/parport_serial.c
+	 * before adding them here.
+	 */
+
 	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
 		0xA000, 0x1000,
 		0, 0, pbn_b0_1_115200 },
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index a1ba94d..f3b306e 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -116,6 +116,8 @@ config SERIAL_8250_PCI
 	  This builds standard PCI serial support. You may be able to
 	  disable this feature if you only need legacy serial support.
 	  Saves about 9K.
+	  Note that serial ports on NetMos 9835 Multi-I/O cards are handled
+	  by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL.
 
 config SERIAL_8250_HP300
 	tristate
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 1456673..f136248 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -291,13 +291,13 @@ config SERIAL_MAX3100
 
 config SERIAL_MAX310X
 	bool "MAX310X support"
-	depends on SPI
+	depends on SPI_MASTER
 	select SERIAL_CORE
-	select REGMAP_SPI if SPI
+	select REGMAP_SPI if SPI_MASTER
 	default n
 	help
 	  This selects support for an advanced UART from Maxim (Dallas).
-	  Supported ICs are MAX3107, MAX3108.
+	  Supported ICs are MAX3107, MAX3108, MAX3109, MAX14830.
 	  Each IC contains 128 words each of receive and transmit FIFO
 	  that can be controlled through I2C or high-speed SPI.
 
@@ -1424,8 +1424,8 @@ config SERIAL_AR933X_NR_UARTS
 	  to support.
 
 config SERIAL_EFM32_UART
-	tristate "EFM32 UART/USART port."
-	depends on ARCH_EFM32
+	tristate "EFM32 UART/USART port"
+	depends on ARM && (ARCH_EFM32 || COMPILE_TEST)
 	select SERIAL_CORE
 	help
 	  This driver support the USART and UART ports on
@@ -1497,6 +1497,22 @@ config SERIAL_FSL_LPUART_CONSOLE
 	  If you have enabled the lpuart serial port on the Freescale SoCs,
 	  you can make it the console by answering Y to this option.
 
+config SERIAL_ST_ASC
+	tristate "ST ASC serial port support"
+	select SERIAL_CORE
+	help
+	  This driver is for the on-chip Asychronous Serial Controller on
+	  STMicroelectronics STi SoCs.
+	  ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
+	  It support all industry standard baud rates.
+
+	  If unsure, say N.
+
+config SERIAL_ST_ASC_CONSOLE
+	bool "Support for console on ST ASC"
+	depends on SERIAL_ST_ASC=y
+	select SERIAL_CORE_CONSOLE
+
 endmenu
 
 endif # TTY
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index cf650f0..47b679c 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
 obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o
 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
 obj-$(CONFIG_SERIAL_TIMBERDALE)	+= timbuart.o
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index c6bdb94..2299a34 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -408,7 +408,8 @@ static struct uart_driver altera_jtaguart_driver = {
 
 static int altera_jtaguart_probe(struct platform_device *pdev)
 {
-	struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
+	struct altera_jtaguart_platform_uart *platp =
+			dev_get_platdata(&pdev->dev);
 	struct uart_port *port;
 	struct resource *res_irq, *res_mem;
 	int i = pdev->id;
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 1d46966..fa638db 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -534,7 +534,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
 
 static int altera_uart_probe(struct platform_device *pdev)
 {
-	struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
+	struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
 	struct uart_port *port;
 	struct resource *res_mem;
 	struct resource *res_irq;
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index c368405..8b90f0b 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -721,7 +721,7 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.line = i;
 	uap->dev = dev;
-	uap->data = dev->dev.platform_data;
+	uap->data = dev_get_platdata(&dev->dev);
 
 	amba_ports[i] = uap;
 
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 28b35ad..eb38fb8 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -265,7 +265,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
 static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
 {
 	/* DMA is the sole user of the platform data right now */
-	struct amba_pl011_data *plat = uap->port.dev->platform_data;
+	struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
 	struct dma_slave_config tx_conf = {
 		.dst_addr = uap->port.mapbase + UART01x_DR,
 		.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -1497,10 +1497,10 @@ static int pl011_hwinit(struct uart_port *port)
 	uap->im = readw(uap->port.membase + UART011_IMSC);
 	writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
 
-	if (uap->port.dev->platform_data) {
+	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
 
-		plat = uap->port.dev->platform_data;
+		plat = dev_get_platdata(uap->port.dev);
 		if (plat->init)
 			plat->init();
 	}
@@ -1645,10 +1645,10 @@ static void pl011_shutdown(struct uart_port *port)
 	/* Optionally let pins go into sleep states */
 	pinctrl_pm_select_sleep_state(port->dev);
 
-	if (uap->port.dev->platform_data) {
+	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
 
-		plat = uap->port.dev->platform_data;
+		plat = dev_get_platdata(uap->port.dev);
 		if (plat->exit)
 			plat->exit();
 	}
@@ -2002,10 +2002,10 @@ static int __init pl011_console_setup(struct console *co, char *options)
 	if (ret)
 		return ret;
 
-	if (uap->port.dev->platform_data) {
+	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
 
-		plat = uap->port.dev->platform_data;
+		plat = dev_get_platdata(uap->port.dev);
 		if (plat->init)
 			plat->init();
 	}
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index 27f20c5..7aa9062 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -629,7 +629,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
 	int id;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata)
 		return -EINVAL;
 
@@ -703,7 +703,6 @@ static int ar933x_uart_remove(struct platform_device *pdev)
 	struct ar933x_uart_port *up;
 
 	up = platform_get_drvdata(pdev);
-	platform_set_drvdata(pdev, NULL);
 
 	if (up) {
 		uart_remove_one_port(&ar933x_uart_driver, &up->port);
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 22f280a..37abf6c 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -209,9 +209,9 @@ static void arc_serial_start_tx(struct uart_port *port)
 	arc_serial_tx_chars(uart);
 }
 
-static void arc_serial_rx_chars(struct arc_uart_port *uart)
+static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
 {
-	unsigned int status, ch, flg = 0;
+	unsigned int ch, flg = 0;
 
 	/*
 	 * UART has 4 deep RX-FIFO. Driver's recongnition of this fact
@@ -222,11 +222,11 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
 	 * before RX-EMPTY=0, implies some sort of buffering going on in the
 	 * controller, which is indeed the Rx-FIFO.
 	 */
-	while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) {
-
-		ch = UART_GET_DATA(uart);
-		uart->port.icount.rx++;
-
+	do {
+		/*
+		 * This could be an Rx Intr for err (no data),
+		 * so check err and clear that Intr first
+		 */
 		if (unlikely(status & (RXOERR | RXFERR))) {
 			if (status & RXOERR) {
 				uart->port.icount.overrun++;
@@ -242,14 +242,17 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
 		} else
 			flg = TTY_NORMAL;
 
-		if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
-			goto done;
+		if (status & RXEMPTY)
+			continue;
 
-		uart_insert_char(&uart->port, status, RXOERR, ch, flg);
+		ch = UART_GET_DATA(uart);
+		uart->port.icount.rx++;
+
+		if (!(uart_handle_sysrq_char(&uart->port, ch)))
+			uart_insert_char(&uart->port, status, RXOERR, ch, flg);
 
-done:
 		tty_flip_buffer_push(&uart->port.state->port);
-	}
+	} while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
 }
 
 /*
@@ -292,11 +295,11 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
 	 * notifications from the UART Controller.
 	 * To demultiplex between the two, we check the relevant bits
 	 */
-	if ((status & RXIENB) && !(status & RXEMPTY)) {
+	if (status & RXIENB) {
 
 		/* already in ISR, no need of xx_irqsave */
 		spin_lock(&uart->port.lock);
-		arc_serial_rx_chars(uart);
+		arc_serial_rx_chars(uart, status);
 		spin_unlock(&uart->port.lock);
 	}
 
@@ -528,7 +531,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
 	unsigned long *plat_data;
 	struct arc_uart_port *uart = &arc_uart_ports[dev_id];
 
-	plat_data = ((unsigned long *)(pdev->dev.platform_data));
+	plat_data = (unsigned long *)dev_get_platdata(&pdev->dev);
 	if (!plat_data)
 		return -ENODEV;
 
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 691265f..d067285 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -39,8 +39,8 @@
 #include <linux/atmel_pdc.h>
 #include <linux/atmel_serial.h>
 #include <linux/uaccess.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/timer.h>
 
 #include <asm/io.h>
 #include <asm/ioctls.h>
@@ -98,6 +98,7 @@ static void atmel_stop_rx(struct uart_port *port);
 #define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
 #define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
 #define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
+#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
 
  /* PDC registers */
 #define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
@@ -140,13 +141,25 @@ struct atmel_uart_port {
 	u32			backup_imr;	/* IMR saved during suspend */
 	int			break_active;	/* break being received */
 
-	short			use_dma_rx;	/* enable PDC receiver */
+	bool			use_dma_rx;	/* enable DMA receiver */
+	bool			use_pdc_rx;	/* enable PDC receiver */
 	short			pdc_rx_idx;	/* current PDC RX buffer */
 	struct atmel_dma_buffer	pdc_rx[2];	/* PDC receier */
 
-	short			use_dma_tx;	/* enable PDC transmitter */
+	bool			use_dma_tx;     /* enable DMA transmitter */
+	bool			use_pdc_tx;	/* enable PDC transmitter */
 	struct atmel_dma_buffer	pdc_tx;		/* PDC transmitter */
 
+	spinlock_t			lock_tx;	/* port lock */
+	spinlock_t			lock_rx;	/* port lock */
+	struct dma_chan			*chan_tx;
+	struct dma_chan			*chan_rx;
+	struct dma_async_tx_descriptor	*desc_tx;
+	struct dma_async_tx_descriptor	*desc_rx;
+	dma_cookie_t			cookie_tx;
+	dma_cookie_t			cookie_rx;
+	struct scatterlist		sg_tx;
+	struct scatterlist		sg_rx;
 	struct tasklet_struct	tasklet;
 	unsigned int		irq_status;
 	unsigned int		irq_status_prev;
@@ -155,6 +168,14 @@ struct atmel_uart_port {
 
 	struct serial_rs485	rs485;		/* rs485 settings */
 	unsigned int		tx_done_mask;
+	bool			is_usart;	/* usart or uart */
+	struct timer_list	uart_timer;	/* uart timer */
+	int (*prepare_rx)(struct uart_port *port);
+	int (*prepare_tx)(struct uart_port *port);
+	void (*schedule_rx)(struct uart_port *port);
+	void (*schedule_tx)(struct uart_port *port);
+	void (*release_rx)(struct uart_port *port);
+	void (*release_tx)(struct uart_port *port);
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@@ -181,31 +202,45 @@ to_atmel_uart_port(struct uart_port *uart)
 }
 
 #ifdef CONFIG_SERIAL_ATMEL_PDC
-static bool atmel_use_dma_rx(struct uart_port *port)
+static bool atmel_use_pdc_rx(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	return atmel_port->use_dma_rx;
+	return atmel_port->use_pdc_rx;
 }
 
-static bool atmel_use_dma_tx(struct uart_port *port)
+static bool atmel_use_pdc_tx(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	return atmel_port->use_dma_tx;
+	return atmel_port->use_pdc_tx;
 }
 #else
-static bool atmel_use_dma_rx(struct uart_port *port)
+static bool atmel_use_pdc_rx(struct uart_port *port)
 {
 	return false;
 }
 
-static bool atmel_use_dma_tx(struct uart_port *port)
+static bool atmel_use_pdc_tx(struct uart_port *port)
 {
 	return false;
 }
 #endif
 
+static bool atmel_use_dma_tx(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	return atmel_port->use_dma_tx;
+}
+
+static bool atmel_use_dma_rx(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	return atmel_port->use_dma_rx;
+}
+
 /* Enable or disable the rs485 support */
 void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
 {
@@ -233,7 +268,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
 		mode |= ATMEL_US_USMODE_RS485;
 	} else {
 		dev_dbg(port->dev, "Setting UART to RS232\n");
-		if (atmel_use_dma_tx(port))
+		if (atmel_use_pdc_tx(port))
 			atmel_port->tx_done_mask = ATMEL_US_ENDTX |
 				ATMEL_US_TXBUFE;
 		else
@@ -345,7 +380,7 @@ static void atmel_stop_tx(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (atmel_use_dma_tx(port)) {
+	if (atmel_use_pdc_tx(port)) {
 		/* disable PDC transmit */
 		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
 	}
@@ -364,7 +399,7 @@ static void atmel_start_tx(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (atmel_use_dma_tx(port)) {
+	if (atmel_use_pdc_tx(port)) {
 		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
 			/* The transmitter is already running.  Yes, we
 			   really need this.*/
@@ -390,7 +425,7 @@ static void atmel_start_rx(struct uart_port *port)
 
 	UART_PUT_CR(port, ATMEL_US_RXEN);
 
-	if (atmel_use_dma_rx(port)) {
+	if (atmel_use_pdc_rx(port)) {
 		/* enable PDC controller */
 		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
 			port->read_status_mask);
@@ -407,7 +442,7 @@ static void atmel_stop_rx(struct uart_port *port)
 {
 	UART_PUT_CR(port, ATMEL_US_RXDIS);
 
-	if (atmel_use_dma_rx(port)) {
+	if (atmel_use_pdc_rx(port)) {
 		/* disable PDC receive */
 		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
 		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
@@ -564,6 +599,372 @@ static void atmel_tx_chars(struct uart_port *port)
 		UART_PUT_IER(port, atmel_port->tx_done_mask);
 }
 
+static void atmel_complete_tx_dma(void *arg)
+{
+	struct atmel_uart_port *atmel_port = arg;
+	struct uart_port *port = &atmel_port->uart;
+	struct circ_buf *xmit = &port->state->xmit;
+	struct dma_chan *chan = atmel_port->chan_tx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (chan)
+		dmaengine_terminate_all(chan);
+	xmit->tail += sg_dma_len(&atmel_port->sg_tx);
+	xmit->tail &= UART_XMIT_SIZE - 1;
+
+	port->icount.tx += sg_dma_len(&atmel_port->sg_tx);
+
+	spin_lock_irq(&atmel_port->lock_tx);
+	async_tx_ack(atmel_port->desc_tx);
+	atmel_port->cookie_tx = -EINVAL;
+	atmel_port->desc_tx = NULL;
+	spin_unlock_irq(&atmel_port->lock_tx);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	/* Do we really need this? */
+	if (!uart_circ_empty(xmit))
+		tasklet_schedule(&atmel_port->tasklet);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void atmel_release_tx_dma(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct dma_chan *chan = atmel_port->chan_tx;
+
+	if (chan) {
+		dmaengine_terminate_all(chan);
+		dma_release_channel(chan);
+		dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
+				DMA_MEM_TO_DEV);
+	}
+
+	atmel_port->desc_tx = NULL;
+	atmel_port->chan_tx = NULL;
+	atmel_port->cookie_tx = -EINVAL;
+}
+
+/*
+ * Called from tasklet with TXRDY interrupt is disabled.
+ */
+static void atmel_tx_dma(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct circ_buf *xmit = &port->state->xmit;
+	struct dma_chan *chan = atmel_port->chan_tx;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sg = &atmel_port->sg_tx;
+
+	/* Make sure we have an idle channel */
+	if (atmel_port->desc_tx != NULL)
+		return;
+
+	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
+		/*
+		 * DMA is idle now.
+		 * Port xmit buffer is already mapped,
+		 * and it is one page... Just adjust
+		 * offsets and lengths. Since it is a circular buffer,
+		 * we have to transmit till the end, and then the rest.
+		 * Take the port lock to get a
+		 * consistent xmit buffer state.
+		 */
+		sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
+		sg_dma_address(sg) = (sg_dma_address(sg) &
+					~(UART_XMIT_SIZE - 1))
+					+ sg->offset;
+		sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head,
+						xmit->tail,
+						UART_XMIT_SIZE);
+		BUG_ON(!sg_dma_len(sg));
+
+		desc = dmaengine_prep_slave_sg(chan,
+						sg,
+						1,
+						DMA_MEM_TO_DEV,
+						DMA_PREP_INTERRUPT |
+						DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(port->dev, "Failed to send via dma!\n");
+			return;
+		}
+
+		dma_sync_sg_for_device(port->dev, sg, 1, DMA_MEM_TO_DEV);
+
+		atmel_port->desc_tx = desc;
+		desc->callback = atmel_complete_tx_dma;
+		desc->callback_param = atmel_port;
+		atmel_port->cookie_tx = dmaengine_submit(desc);
+
+	} else {
+		if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
+			/* DMA done, stop TX, start RX for RS485 */
+			atmel_start_rx(port);
+		}
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+}
+
+static int atmel_prepare_tx_dma(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	dma_cap_mask_t		mask;
+	struct dma_slave_config config;
+	int ret, nent;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	atmel_port->chan_tx = dma_request_slave_channel(port->dev, "tx");
+	if (atmel_port->chan_tx == NULL)
+		goto chan_err;
+	dev_info(port->dev, "using %s for tx DMA transfers\n",
+		dma_chan_name(atmel_port->chan_tx));
+
+	spin_lock_init(&atmel_port->lock_tx);
+	sg_init_table(&atmel_port->sg_tx, 1);
+	/* UART circular tx buffer is an aligned page. */
+	BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+	sg_set_page(&atmel_port->sg_tx,
+			virt_to_page(port->state->xmit.buf),
+			UART_XMIT_SIZE,
+			(int)port->state->xmit.buf & ~PAGE_MASK);
+	nent = dma_map_sg(port->dev,
+				&atmel_port->sg_tx,
+				1,
+				DMA_MEM_TO_DEV);
+
+	if (!nent) {
+		dev_dbg(port->dev, "need to release resource of dma\n");
+		goto chan_err;
+	} else {
+		dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+			sg_dma_len(&atmel_port->sg_tx),
+			port->state->xmit.buf,
+			sg_dma_address(&atmel_port->sg_tx));
+	}
+
+	/* Configure the slave DMA */
+	memset(&config, 0, sizeof(config));
+	config.direction = DMA_MEM_TO_DEV;
+	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	config.dst_addr = port->mapbase + ATMEL_US_THR;
+
+	ret = dmaengine_device_control(atmel_port->chan_tx,
+					DMA_SLAVE_CONFIG,
+					(unsigned long)&config);
+	if (ret) {
+		dev_err(port->dev, "DMA tx slave configuration failed\n");
+		goto chan_err;
+	}
+
+	return 0;
+
+chan_err:
+	dev_err(port->dev, "TX channel not available, switch to pio\n");
+	atmel_port->use_dma_tx = 0;
+	if (atmel_port->chan_tx)
+		atmel_release_tx_dma(port);
+	return -EINVAL;
+}
+
+static void atmel_flip_buffer_rx_dma(struct uart_port *port,
+					char *buf, size_t count)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct tty_port *tport = &port->state->port;
+
+	dma_sync_sg_for_cpu(port->dev,
+				&atmel_port->sg_rx,
+				1,
+				DMA_DEV_TO_MEM);
+
+	tty_insert_flip_string(tport, buf, count);
+
+	dma_sync_sg_for_device(port->dev,
+				&atmel_port->sg_rx,
+				1,
+				DMA_DEV_TO_MEM);
+	/*
+	 * Drop the lock here since it might end up calling
+	 * uart_start(), which takes the lock.
+	 */
+	spin_unlock(&port->lock);
+	tty_flip_buffer_push(tport);
+	spin_lock(&port->lock);
+}
+
+static void atmel_complete_rx_dma(void *arg)
+{
+	struct uart_port *port = arg;
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	tasklet_schedule(&atmel_port->tasklet);
+}
+
+static void atmel_release_rx_dma(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct dma_chan *chan = atmel_port->chan_rx;
+
+	if (chan) {
+		dmaengine_terminate_all(chan);
+		dma_release_channel(chan);
+		dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
+				DMA_DEV_TO_MEM);
+	}
+
+	atmel_port->desc_rx = NULL;
+	atmel_port->chan_rx = NULL;
+	atmel_port->cookie_rx = -EINVAL;
+
+	if (!atmel_port->is_usart)
+		del_timer_sync(&atmel_port->uart_timer);
+}
+
+static void atmel_rx_from_dma(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct circ_buf *ring = &atmel_port->rx_ring;
+	struct dma_chan *chan = atmel_port->chan_rx;
+	struct dma_tx_state state;
+	enum dma_status dmastat;
+	size_t pending, count;
+
+
+	/* Reset the UART timeout early so that we don't miss one */
+	UART_PUT_CR(port, ATMEL_US_STTTO);
+	dmastat = dmaengine_tx_status(chan,
+				atmel_port->cookie_rx,
+				&state);
+	/* Restart a new tasklet if DMA status is error */
+	if (dmastat == DMA_ERROR) {
+		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
+		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+		tasklet_schedule(&atmel_port->tasklet);
+		return;
+	}
+	/* current transfer size should no larger than dma buffer */
+	pending = sg_dma_len(&atmel_port->sg_rx) - state.residue;
+	BUG_ON(pending > sg_dma_len(&atmel_port->sg_rx));
+
+	/*
+	 * This will take the chars we have so far,
+	 * ring->head will record the transfer size, only new bytes come
+	 * will insert into the framework.
+	 */
+	if (pending > ring->head) {
+		count = pending - ring->head;
+
+		atmel_flip_buffer_rx_dma(port, ring->buf + ring->head, count);
+
+		ring->head += count;
+		if (ring->head == sg_dma_len(&atmel_port->sg_rx))
+			ring->head = 0;
+
+		port->icount.rx += count;
+	}
+
+	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+}
+
+static int atmel_prepare_rx_dma(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct dma_async_tx_descriptor *desc;
+	dma_cap_mask_t		mask;
+	struct dma_slave_config config;
+	struct circ_buf		*ring;
+	int ret, nent;
+
+	ring = &atmel_port->rx_ring;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+
+	atmel_port->chan_rx = dma_request_slave_channel(port->dev, "rx");
+	if (atmel_port->chan_rx == NULL)
+		goto chan_err;
+	dev_info(port->dev, "using %s for rx DMA transfers\n",
+		dma_chan_name(atmel_port->chan_rx));
+
+	spin_lock_init(&atmel_port->lock_rx);
+	sg_init_table(&atmel_port->sg_rx, 1);
+	/* UART circular rx buffer is an aligned page. */
+	BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+	sg_set_page(&atmel_port->sg_rx,
+			virt_to_page(ring->buf),
+			ATMEL_SERIAL_RINGSIZE,
+			(int)ring->buf & ~PAGE_MASK);
+			nent = dma_map_sg(port->dev,
+					&atmel_port->sg_rx,
+					1,
+					DMA_DEV_TO_MEM);
+
+	if (!nent) {
+		dev_dbg(port->dev, "need to release resource of dma\n");
+		goto chan_err;
+	} else {
+		dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+			sg_dma_len(&atmel_port->sg_rx),
+			ring->buf,
+			sg_dma_address(&atmel_port->sg_rx));
+	}
+
+	/* Configure the slave DMA */
+	memset(&config, 0, sizeof(config));
+	config.direction = DMA_DEV_TO_MEM;
+	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	config.src_addr = port->mapbase + ATMEL_US_RHR;
+
+	ret = dmaengine_device_control(atmel_port->chan_rx,
+					DMA_SLAVE_CONFIG,
+					(unsigned long)&config);
+	if (ret) {
+		dev_err(port->dev, "DMA rx slave configuration failed\n");
+		goto chan_err;
+	}
+	/*
+	 * Prepare a cyclic dma transfer, assign 2 descriptors,
+	 * each one is half ring buffer size
+	 */
+	desc = dmaengine_prep_dma_cyclic(atmel_port->chan_rx,
+				sg_dma_address(&atmel_port->sg_rx),
+				sg_dma_len(&atmel_port->sg_rx),
+				sg_dma_len(&atmel_port->sg_rx)/2,
+				DMA_DEV_TO_MEM,
+				DMA_PREP_INTERRUPT);
+	desc->callback = atmel_complete_rx_dma;
+	desc->callback_param = port;
+	atmel_port->desc_rx = desc;
+	atmel_port->cookie_rx = dmaengine_submit(desc);
+
+	return 0;
+
+chan_err:
+	dev_err(port->dev, "RX channel not available, switch to pio\n");
+	atmel_port->use_dma_rx = 0;
+	if (atmel_port->chan_rx)
+		atmel_release_rx_dma(port);
+	return -EINVAL;
+}
+
+static void atmel_uart_timer_callback(unsigned long data)
+{
+	struct uart_port *port = (void *)data;
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	tasklet_schedule(&atmel_port->tasklet);
+	mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port));
+}
+
 /*
  * receive interrupt handler.
  */
@@ -572,7 +973,7 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (atmel_use_dma_rx(port)) {
+	if (atmel_use_pdc_rx(port)) {
 		/*
 		 * PDC receive. Just schedule the tasklet and let it
 		 * figure out the details.
@@ -591,6 +992,13 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 			atmel_pdc_rxerr(port, pending);
 	}
 
+	if (atmel_use_dma_rx(port)) {
+		if (pending & ATMEL_US_TIMEOUT) {
+			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
+			tasklet_schedule(&atmel_port->tasklet);
+		}
+	}
+
 	/* Interrupt receive */
 	if (pending & ATMEL_US_RXRDY)
 		atmel_rx_chars(port);
@@ -658,10 +1066,21 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 	return pass_counter ? IRQ_HANDLED : IRQ_NONE;
 }
 
+static void atmel_release_tx_pdc(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
+
+	dma_unmap_single(port->dev,
+			 pdc->dma_addr,
+			 pdc->dma_size,
+			 DMA_TO_DEVICE);
+}
+
 /*
  * Called from tasklet with ENDTX and TXBUFE interrupts disabled.
  */
-static void atmel_tx_dma(struct uart_port *port)
+static void atmel_tx_pdc(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	struct circ_buf *xmit = &port->state->xmit;
@@ -710,6 +1129,23 @@ static void atmel_tx_dma(struct uart_port *port)
 		uart_write_wakeup(port);
 }
 
+static int atmel_prepare_tx_pdc(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
+	struct circ_buf *xmit = &port->state->xmit;
+
+	pdc->buf = xmit->buf;
+	pdc->dma_addr = dma_map_single(port->dev,
+					pdc->buf,
+					UART_XMIT_SIZE,
+					DMA_TO_DEVICE);
+	pdc->dma_size = UART_XMIT_SIZE;
+	pdc->ofs = 0;
+
+	return 0;
+}
+
 static void atmel_rx_from_ring(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@@ -778,7 +1214,26 @@ static void atmel_rx_from_ring(struct uart_port *port)
 	spin_lock(&port->lock);
 }
 
-static void atmel_rx_from_dma(struct uart_port *port)
+static void atmel_release_rx_pdc(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
+
+		dma_unmap_single(port->dev,
+				 pdc->dma_addr,
+				 pdc->dma_size,
+				 DMA_FROM_DEVICE);
+		kfree(pdc->buf);
+	}
+
+	if (!atmel_port->is_usart)
+		del_timer_sync(&atmel_port->uart_timer);
+}
+
+static void atmel_rx_from_pdc(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	struct tty_port *tport = &port->state->port;
@@ -855,6 +1310,45 @@ static void atmel_rx_from_dma(struct uart_port *port)
 	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 }
 
+static int atmel_prepare_rx_pdc(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
+
+		pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL);
+		if (pdc->buf == NULL) {
+			if (i != 0) {
+				dma_unmap_single(port->dev,
+					atmel_port->pdc_rx[0].dma_addr,
+					PDC_BUFFER_SIZE,
+					DMA_FROM_DEVICE);
+				kfree(atmel_port->pdc_rx[0].buf);
+			}
+			atmel_port->use_pdc_rx = 0;
+			return -ENOMEM;
+		}
+		pdc->dma_addr = dma_map_single(port->dev,
+						pdc->buf,
+						PDC_BUFFER_SIZE,
+						DMA_FROM_DEVICE);
+		pdc->dma_size = PDC_BUFFER_SIZE;
+		pdc->ofs = 0;
+	}
+
+	atmel_port->pdc_rx_idx = 0;
+
+	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
+	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
+
+	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
+	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+
+	return 0;
+}
+
 /*
  * tasklet handling tty stuff outside the interrupt handler.
  */
@@ -868,10 +1362,7 @@ static void atmel_tasklet_func(unsigned long data)
 	/* The interrupt handler does not take the lock */
 	spin_lock(&port->lock);
 
-	if (atmel_use_dma_tx(port))
-		atmel_tx_dma(port);
-	else
-		atmel_tx_chars(port);
+	atmel_port->schedule_tx(port);
 
 	status = atmel_port->irq_status;
 	status_change = status ^ atmel_port->irq_status_prev;
@@ -893,19 +1384,152 @@ static void atmel_tasklet_func(unsigned long data)
 		atmel_port->irq_status_prev = status;
 	}
 
-	if (atmel_use_dma_rx(port))
-		atmel_rx_from_dma(port);
-	else
-		atmel_rx_from_ring(port);
+	atmel_port->schedule_rx(port);
 
 	spin_unlock(&port->lock);
 }
 
+static int atmel_init_property(struct atmel_uart_port *atmel_port,
+				struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
+
+	if (np) {
+		/* DMA/PDC usage specification */
+		if (of_get_property(np, "atmel,use-dma-rx", NULL)) {
+			if (of_get_property(np, "dmas", NULL)) {
+				atmel_port->use_dma_rx  = true;
+				atmel_port->use_pdc_rx  = false;
+			} else {
+				atmel_port->use_dma_rx  = false;
+				atmel_port->use_pdc_rx  = true;
+			}
+		} else {
+			atmel_port->use_dma_rx  = false;
+			atmel_port->use_pdc_rx  = false;
+		}
+
+		if (of_get_property(np, "atmel,use-dma-tx", NULL)) {
+			if (of_get_property(np, "dmas", NULL)) {
+				atmel_port->use_dma_tx  = true;
+				atmel_port->use_pdc_tx  = false;
+			} else {
+				atmel_port->use_dma_tx  = false;
+				atmel_port->use_pdc_tx  = true;
+			}
+		} else {
+			atmel_port->use_dma_tx  = false;
+			atmel_port->use_pdc_tx  = false;
+		}
+
+	} else {
+		atmel_port->use_pdc_rx  = pdata->use_dma_rx;
+		atmel_port->use_pdc_tx  = pdata->use_dma_tx;
+		atmel_port->use_dma_rx  = false;
+		atmel_port->use_dma_tx  = false;
+	}
+
+	return 0;
+}
+
+static void atmel_init_rs485(struct atmel_uart_port *atmel_port,
+				struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
+
+	if (np) {
+		u32 rs485_delay[2];
+		/* rs485 properties */
+		if (of_property_read_u32_array(np, "rs485-rts-delay",
+					rs485_delay, 2) == 0) {
+			struct serial_rs485 *rs485conf = &atmel_port->rs485;
+
+			rs485conf->delay_rts_before_send = rs485_delay[0];
+			rs485conf->delay_rts_after_send = rs485_delay[1];
+			rs485conf->flags = 0;
+
+		if (of_get_property(np, "rs485-rx-during-tx", NULL))
+			rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+		if (of_get_property(np, "linux,rs485-enabled-at-boot-time",
+								NULL))
+			rs485conf->flags |= SER_RS485_ENABLED;
+		}
+	} else {
+		atmel_port->rs485       = pdata->rs485;
+	}
+
+}
+
+static void atmel_set_ops(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	if (atmel_use_dma_rx(port)) {
+		atmel_port->prepare_rx = &atmel_prepare_rx_dma;
+		atmel_port->schedule_rx = &atmel_rx_from_dma;
+		atmel_port->release_rx = &atmel_release_rx_dma;
+	} else if (atmel_use_pdc_rx(port)) {
+		atmel_port->prepare_rx = &atmel_prepare_rx_pdc;
+		atmel_port->schedule_rx = &atmel_rx_from_pdc;
+		atmel_port->release_rx = &atmel_release_rx_pdc;
+	} else {
+		atmel_port->prepare_rx = NULL;
+		atmel_port->schedule_rx = &atmel_rx_from_ring;
+		atmel_port->release_rx = NULL;
+	}
+
+	if (atmel_use_dma_tx(port)) {
+		atmel_port->prepare_tx = &atmel_prepare_tx_dma;
+		atmel_port->schedule_tx = &atmel_tx_dma;
+		atmel_port->release_tx = &atmel_release_tx_dma;
+	} else if (atmel_use_pdc_tx(port)) {
+		atmel_port->prepare_tx = &atmel_prepare_tx_pdc;
+		atmel_port->schedule_tx = &atmel_tx_pdc;
+		atmel_port->release_tx = &atmel_release_tx_pdc;
+	} else {
+		atmel_port->prepare_tx = NULL;
+		atmel_port->schedule_tx = &atmel_tx_chars;
+		atmel_port->release_tx = NULL;
+	}
+}
+
+/*
+ * Get ip name usart or uart
+ */
+static int atmel_get_ip_name(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	int name = UART_GET_IP_NAME(port);
+	int usart, uart;
+	/* usart and uart ascii */
+	usart = 0x55534152;
+	uart = 0x44424755;
+
+	atmel_port->is_usart = false;
+
+	if (name == usart) {
+		dev_dbg(port->dev, "This is usart\n");
+		atmel_port->is_usart = true;
+	} else if (name == uart) {
+		dev_dbg(port->dev, "This is uart\n");
+		atmel_port->is_usart = false;
+	} else {
+		dev_err(port->dev, "Not supported ip name, set to uart\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /*
  * Perform initialization and enable port for reception
  */
 static int atmel_startup(struct uart_port *port)
 {
+	struct platform_device *pdev = to_platform_device(port->dev);
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	struct tty_struct *tty = port->state->port.tty;
 	int retval;
@@ -930,53 +1554,19 @@ static int atmel_startup(struct uart_port *port)
 	/*
 	 * Initialize DMA (if necessary)
 	 */
-	if (atmel_use_dma_rx(port)) {
-		int i;
-
-		for (i = 0; i < 2; i++) {
-			struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
-
-			pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL);
-			if (pdc->buf == NULL) {
-				if (i != 0) {
-					dma_unmap_single(port->dev,
-						atmel_port->pdc_rx[0].dma_addr,
-						PDC_BUFFER_SIZE,
-						DMA_FROM_DEVICE);
-					kfree(atmel_port->pdc_rx[0].buf);
-				}
-				free_irq(port->irq, port);
-				return -ENOMEM;
-			}
-			pdc->dma_addr = dma_map_single(port->dev,
-						       pdc->buf,
-						       PDC_BUFFER_SIZE,
-						       DMA_FROM_DEVICE);
-			pdc->dma_size = PDC_BUFFER_SIZE;
-			pdc->ofs = 0;
-		}
+	atmel_init_property(atmel_port, pdev);
 
-		atmel_port->pdc_rx_idx = 0;
-
-		UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
-		UART_PUT_RCR(port, PDC_BUFFER_SIZE);
-
-		UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
-		UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+	if (atmel_port->prepare_rx) {
+		retval = atmel_port->prepare_rx(port);
+		if (retval < 0)
+			atmel_set_ops(port);
 	}
-	if (atmel_use_dma_tx(port)) {
-		struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
-		struct circ_buf *xmit = &port->state->xmit;
 
-		pdc->buf = xmit->buf;
-		pdc->dma_addr = dma_map_single(port->dev,
-					       pdc->buf,
-					       UART_XMIT_SIZE,
-					       DMA_TO_DEVICE);
-		pdc->dma_size = UART_XMIT_SIZE;
-		pdc->ofs = 0;
+	if (atmel_port->prepare_tx) {
+		retval = atmel_port->prepare_tx(port);
+		if (retval < 0)
+			atmel_set_ops(port);
 	}
-
 	/*
 	 * If there is a specific "open" function (to register
 	 * control line interrupts)
@@ -1000,14 +1590,38 @@ static int atmel_startup(struct uart_port *port)
 	/* enable xmit & rcvr */
 	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
-	if (atmel_use_dma_rx(port)) {
+	if (atmel_use_pdc_rx(port)) {
 		/* set UART timeout */
-		UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-		UART_PUT_CR(port, ATMEL_US_STTTO);
-
-		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+		if (!atmel_port->is_usart) {
+			setup_timer(&atmel_port->uart_timer,
+					atmel_uart_timer_callback,
+					(unsigned long)port);
+			mod_timer(&atmel_port->uart_timer,
+					jiffies + uart_poll_timeout(port));
+		/* set USART timeout */
+		} else {
+			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
+			UART_PUT_CR(port, ATMEL_US_STTTO);
+
+			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+		}
 		/* enable PDC controller */
 		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+	} else if (atmel_use_dma_rx(port)) {
+		/* set UART timeout */
+		if (!atmel_port->is_usart) {
+			setup_timer(&atmel_port->uart_timer,
+					atmel_uart_timer_callback,
+					(unsigned long)port);
+			mod_timer(&atmel_port->uart_timer,
+					jiffies + uart_poll_timeout(port));
+		/* set USART timeout */
+		} else {
+			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
+			UART_PUT_CR(port, ATMEL_US_STTTO);
+
+			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+		}
 	} else {
 		/* enable receive only */
 		UART_PUT_IER(port, ATMEL_US_RXRDY);
@@ -1031,27 +1645,10 @@ static void atmel_shutdown(struct uart_port *port)
 	/*
 	 * Shut-down the DMA.
 	 */
-	if (atmel_use_dma_rx(port)) {
-		int i;
-
-		for (i = 0; i < 2; i++) {
-			struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
-
-			dma_unmap_single(port->dev,
-					 pdc->dma_addr,
-					 pdc->dma_size,
-					 DMA_FROM_DEVICE);
-			kfree(pdc->buf);
-		}
-	}
-	if (atmel_use_dma_tx(port)) {
-		struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
-
-		dma_unmap_single(port->dev,
-				 pdc->dma_addr,
-				 pdc->dma_size,
-				 DMA_TO_DEVICE);
-	}
+	if (atmel_port->release_rx)
+		atmel_port->release_rx(port);
+	if (atmel_port->release_tx)
+		atmel_port->release_tx(port);
 
 	/*
 	 * Disable all interrupts, port and break condition.
@@ -1080,7 +1677,7 @@ static void atmel_flush_buffer(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (atmel_use_dma_tx(port)) {
+	if (atmel_use_pdc_tx(port)) {
 		UART_PUT_TCR(port, 0);
 		atmel_port->pdc_tx.ofs = 0;
 	}
@@ -1193,7 +1790,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	if (termios->c_iflag & (BRKINT | PARMRK))
 		port->read_status_mask |= ATMEL_US_RXBRK;
 
-	if (atmel_use_dma_rx(port))
+	if (atmel_use_pdc_rx(port))
 		/* need to enable error interrupts */
 		UART_PUT_IER(port, port->read_status_mask);
 
@@ -1423,38 +2020,6 @@ static struct uart_ops atmel_pops = {
 #endif
 };
 
-static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
-					 struct device_node *np)
-{
-	u32 rs485_delay[2];
-
-	/* DMA/PDC usage specification */
-	if (of_get_property(np, "atmel,use-dma-rx", NULL))
-		atmel_port->use_dma_rx	= 1;
-	else
-		atmel_port->use_dma_rx	= 0;
-	if (of_get_property(np, "atmel,use-dma-tx", NULL))
-		atmel_port->use_dma_tx	= 1;
-	else
-		atmel_port->use_dma_tx	= 0;
-
-	/* rs485 properties */
-	if (of_property_read_u32_array(np, "rs485-rts-delay",
-					    rs485_delay, 2) == 0) {
-		struct serial_rs485 *rs485conf = &atmel_port->rs485;
-
-		rs485conf->delay_rts_before_send = rs485_delay[0];
-		rs485conf->delay_rts_after_send = rs485_delay[1];
-		rs485conf->flags = 0;
-
-		if (of_get_property(np, "rs485-rx-during-tx", NULL))
-			rs485conf->flags |= SER_RS485_RX_DURING_TX;
-
-		if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL))
-			rs485conf->flags |= SER_RS485_ENABLED;
-	}
-}
-
 /*
  * Configure the port from the platform device resource info.
  */
@@ -1463,15 +2028,12 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
 {
 	int ret;
 	struct uart_port *port = &atmel_port->uart;
-	struct atmel_uart_data *pdata = pdev->dev.platform_data;
+	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 
-	if (pdev->dev.of_node) {
-		atmel_of_init_port(atmel_port, pdev->dev.of_node);
-	} else {
-		atmel_port->use_dma_rx	= pdata->use_dma_rx;
-		atmel_port->use_dma_tx	= pdata->use_dma_tx;
-		atmel_port->rs485	= pdata->rs485;
-	}
+	if (!atmel_init_property(atmel_port, pdev))
+		atmel_set_ops(port);
+
+	atmel_init_rs485(atmel_port, pdev);
 
 	port->iotype		= UPIO_MEM;
 	port->flags		= UPF_BOOT_AUTOCONF;
@@ -1516,7 +2078,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
 	/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
 	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-	else if (atmel_use_dma_tx(port)) {
+	else if (atmel_use_pdc_tx(port)) {
 		port->fifosize = PDC_BUFFER_SIZE;
 		atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
 	} else {
@@ -1664,7 +2226,7 @@ static int __init atmel_console_init(void)
 	int ret;
 	if (atmel_default_console_device) {
 		struct atmel_uart_data *pdata =
-			atmel_default_console_device->dev.platform_data;
+			dev_get_platdata(&atmel_default_console_device->dev);
 		int id = pdata->num;
 		struct atmel_uart_port *port = &atmel_ports[id];
 
@@ -1772,10 +2334,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
 	struct device_node *np = pdev->dev.of_node;
-	struct atmel_uart_data *pdata = pdev->dev.platform_data;
+	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 	void *data;
 	int ret = -ENODEV;
-	struct pinctrl *pinctrl;
 
 	BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
 
@@ -1809,13 +2370,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	if (ret)
 		goto err;
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto err;
-	}
-
-	if (!atmel_use_dma_rx(&port->uart)) {
+	if (!atmel_use_pdc_rx(&port->uart)) {
 		ret = -ENOMEM;
 		data = kmalloc(sizeof(struct atmel_uart_char)
 				* ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
@@ -1847,6 +2402,13 @@ static int atmel_serial_probe(struct platform_device *pdev)
 		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
 	}
 
+	/*
+	 * Get port name of usart or uart
+	 */
+	ret = atmel_get_ip_name(&port->uart);
+	if (ret < 0)
+		goto err_add_port;
+
 	return 0;
 
 err_add_port:
@@ -1868,7 +2430,6 @@ static int atmel_serial_remove(struct platform_device *pdev)
 	int ret = 0;
 
 	device_init_wakeup(&pdev->dev, 0);
-	platform_set_drvdata(pdev, NULL);
 
 	ret = uart_remove_one_port(&atmel_uart, port);
 
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index 6fa2ae7..d14ba5a 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -852,7 +852,6 @@ static int bcm_uart_remove(struct platform_device *pdev)
 
 	port = platform_get_drvdata(pdev);
 	uart_remove_one_port(&bcm_uart_driver, port);
-	platform_set_drvdata(pdev, NULL);
 	/* mark port as free */
 	ports[pdev->id].membase = 0;
 	return 0;
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index 487c173..424ed36 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -766,7 +766,8 @@ static int sport_uart_probe(struct platform_device *pdev)
 		}
 
 		ret = peripheral_request_list(
-			(unsigned short *)pdev->dev.platform_data, DRV_NAME);
+			(unsigned short *)dev_get_platdata(&pdev->dev),
+			DRV_NAME);
 		if (ret) {
 			dev_err(&pdev->dev,
 				"Fail to request SPORT peripherals\n");
@@ -843,7 +844,7 @@ out_error_unmap:
 		iounmap(sport->port.membase);
 out_error_free_peripherals:
 		peripheral_free_list(
-			(unsigned short *)pdev->dev.platform_data);
+			(unsigned short *)dev_get_platdata(&pdev->dev));
 out_error_free_mem:
 		kfree(sport);
 		bfin_sport_uart_ports[pdev->id] = NULL;
@@ -863,7 +864,7 @@ static int sport_uart_remove(struct platform_device *pdev)
 		uart_remove_one_port(&sport_uart_reg, &sport->port);
 		iounmap(sport->port.membase);
 		peripheral_free_list(
-			(unsigned short *)pdev->dev.platform_data);
+			(unsigned short *)dev_get_platdata(&pdev->dev));
 		kfree(sport);
 		bfin_sport_uart_ports[pdev->id] = NULL;
 	}
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 26a3be7..378f3c3 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -41,10 +41,6 @@
 # undef CONFIG_EARLY_PRINTK
 #endif
 
-#ifdef CONFIG_SERIAL_BFIN_MODULE
-# undef CONFIG_EARLY_PRINTK
-#endif
-
 /* UART name and device definitions */
 #define BFIN_SERIAL_DEV_NAME	"ttyBF"
 #define BFIN_SERIAL_MAJOR	204
@@ -1244,7 +1240,8 @@ static int bfin_serial_probe(struct platform_device *pdev)
 			 */
 #endif
 		ret = peripheral_request_list(
-			(unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
+			(unsigned short *)dev_get_platdata(&pdev->dev),
+			DRIVER_NAME);
 		if (ret) {
 			dev_err(&pdev->dev,
 				"fail to request bfin serial peripherals\n");
@@ -1362,7 +1359,7 @@ out_error_unmap:
 		iounmap(uart->port.membase);
 out_error_free_peripherals:
 		peripheral_free_list(
-			(unsigned short *)pdev->dev.platform_data);
+			(unsigned short *)dev_get_platdata(&pdev->dev));
 out_error_free_mem:
 		kfree(uart);
 		bfin_serial_ports[pdev->id] = NULL;
@@ -1381,7 +1378,7 @@ static int bfin_serial_remove(struct platform_device *pdev)
 		uart_remove_one_port(&bfin_serial_reg, &uart->port);
 		iounmap(uart->port.membase);
 		peripheral_free_list(
-			(unsigned short *)pdev->dev.platform_data);
+			(unsigned short *)dev_get_platdata(&pdev->dev));
 		kfree(uart);
 		bfin_serial_ports[pdev->id] = NULL;
 	}
@@ -1436,7 +1433,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
 	}
 
 	ret = peripheral_request_list(
-		(unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
+		(unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME);
 	if (ret) {
 		dev_err(&pdev->dev,
 				"fail to request bfin serial peripherals\n");
@@ -1467,7 +1464,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
 
 out_error_free_peripherals:
 	peripheral_free_list(
-		(unsigned short *)pdev->dev.platform_data);
+		(unsigned short *)dev_get_platdata(&pdev->dev));
 
 	return ret;
 }
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index bfb1796..7e4e408 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -438,8 +438,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
 	s->uart_clk = devm_clk_get(&pdev->dev, "uart");
 	if (IS_ERR(s->uart_clk)) {
 		dev_err(&pdev->dev, "Can't get UART clocks\n");
-		ret = PTR_ERR(s->uart_clk);
-		goto err_out;
+		return PTR_ERR(s->uart_clk);
 	}
 
 	s->uart.owner		= THIS_MODULE;
@@ -461,7 +460,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
 	if (ret) {
 		dev_err(&pdev->dev, "Registering UART driver failed\n");
 		devm_clk_put(&pdev->dev, s->uart_clk);
-		goto err_out;
+		return ret;
 	}
 
 	for (i = 0; i < UART_CLPS711X_NR; i++) {
@@ -478,11 +477,6 @@ static int uart_clps711x_probe(struct platform_device *pdev)
 	}
 
 	return 0;
-
-err_out:
-	platform_set_drvdata(pdev, NULL);
-
-	return ret;
 }
 
 static int uart_clps711x_remove(struct platform_device *pdev)
@@ -495,7 +489,6 @@ static int uart_clps711x_remove(struct platform_device *pdev)
 
 	devm_clk_put(&pdev->dev, s->uart_clk);
 	uart_unregister_driver(&s->uart);
-	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 7d199c8..98adaa1 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -698,6 +698,7 @@ static int efm32_uart_probe(struct platform_device *pdev)
 {
 	struct efm32_uart_port *efm_port;
 	struct resource *res;
+	unsigned int line;
 	int ret;
 
 	efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL);
@@ -750,18 +751,21 @@ static int efm32_uart_probe(struct platform_device *pdev)
 
 		if (pdata)
 			efm_port->pdata = *pdata;
-	}
+	} else if (ret < 0)
+		goto err_probe_dt;
+
+	line = efm_port->port.line;
 
-	if (efm_port->port.line >= 0 &&
-			efm_port->port.line < ARRAY_SIZE(efm32_uart_ports))
-		efm32_uart_ports[efm_port->port.line] = efm_port;
+	if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports))
+		efm32_uart_ports[line] = efm_port;
 
 	ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port);
 	if (ret) {
 		dev_dbg(&pdev->dev, "failed to add port: %d\n", ret);
 
-		if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports))
-			efm32_uart_ports[pdev->id] = NULL;
+		if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports))
+			efm32_uart_ports[line] = NULL;
+err_probe_dt:
 err_get_rxirq:
 err_too_small:
 err_get_base:
@@ -777,20 +781,19 @@ err_get_base:
 static int efm32_uart_remove(struct platform_device *pdev)
 {
 	struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
-
-	platform_set_drvdata(pdev, NULL);
+	unsigned int line = efm_port->port.line;
 
 	uart_remove_one_port(&efm32_uart_reg, &efm_port->port);
 
-	if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports))
-		efm32_uart_ports[pdev->id] = NULL;
+	if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports))
+		efm32_uart_ports[line] = NULL;
 
 	kfree(efm_port);
 
 	return 0;
 }
 
-static struct of_device_id efm32_uart_dt_ids[] = {
+static const struct of_device_id efm32_uart_dt_ids[] = {
 	{
 		.compatible = "efm32,uart",
 	}, {
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 263cfaa..8978dc9 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -342,8 +342,10 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
 static void lpuart_setup_watermark(struct lpuart_port *sport)
 {
 	unsigned char val, cr2;
+	unsigned char cr2_saved;
 
 	cr2 = readb(sport->port.membase + UARTCR2);
+	cr2_saved = cr2;
 	cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_TE |
 			UARTCR2_RIE | UARTCR2_RE);
 	writeb(cr2, sport->port.membase + UARTCR2);
@@ -366,6 +368,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
 
 	writeb(2, sport->port.membase + UARTTWFIFO);
 	writeb(1, sport->port.membase + UARTRWFIFO);
+
+	/* Restore cr2 */
+	writeb(cr2_saved, sport->port.membase + UARTCR2);
 }
 
 static int lpuart_startup(struct uart_port *port)
@@ -858,7 +863,7 @@ static int __init lpuart_serial_init(void)
 	if (ret)
 		uart_unregister_driver(&lpuart_reg);
 
-	return 0;
+	return ret;
 }
 
 static void __exit lpuart_serial_exit(void)
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 8b1534c..af286e6 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
-	pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data;
+	pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev);
 	if (!pl_data) {
 		dev_err(&spi->dev, "missing platform data!");
 		return -ENODEV;
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 415cec6..a5f32c7 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -47,11 +47,12 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/irq.h>
 #include <linux/platform_data/serial-imx.h>
+#include <linux/platform_data/dma-imx.h>
 
 /* Register definitions */
 #define URXD0 0x0  /* Receiver Register */
@@ -83,6 +84,7 @@
 #define UCR1_ADBR	(1<<14) /* Auto detect baud rate */
 #define UCR1_TRDYEN	(1<<13) /* Transmitter ready interrupt enable */
 #define UCR1_IDEN	(1<<12) /* Idle condition interrupt */
+#define UCR1_ICD_REG(x) (((x) & 3) << 10) /* idle condition detect */
 #define UCR1_RRDYEN	(1<<9)	/* Recv ready interrupt enable */
 #define UCR1_RDMAEN	(1<<8)	/* Recv ready DMA enable */
 #define UCR1_IREN	(1<<7)	/* Infrared interface enable */
@@ -91,6 +93,7 @@
 #define UCR1_SNDBRK	(1<<4)	/* Send break */
 #define UCR1_TDMAEN	(1<<3)	/* Transmitter ready DMA enable */
 #define IMX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, i.mx1 only */
+#define UCR1_ATDMAEN    (1<<2)  /* Aging DMA Timer Enable */
 #define UCR1_DOZE	(1<<1)	/* Doze */
 #define UCR1_UARTEN	(1<<0)	/* UART enabled */
 #define UCR2_ESCI	(1<<15)	/* Escape seq interrupt enable */
@@ -126,6 +129,7 @@
 #define UCR4_ENIRI	(1<<8)	/* Serial infrared interrupt enable */
 #define UCR4_WKEN	(1<<7)	/* Wake interrupt enable */
 #define UCR4_REF16	(1<<6)	/* Ref freq 16 MHz */
+#define UCR4_IDDMAEN    (1<<6)  /* DMA IDLE Condition Detected */
 #define UCR4_IRSC	(1<<5)	/* IR special case */
 #define UCR4_TCEN	(1<<3)	/* Transmit complete interrupt enable */
 #define UCR4_BKEN	(1<<2)	/* Break condition interrupt enable */
@@ -187,6 +191,7 @@
 enum imx_uart_type {
 	IMX1_UART,
 	IMX21_UART,
+	IMX6Q_UART,
 };
 
 /* device type dependent stuff */
@@ -209,6 +214,19 @@ struct imx_port {
 	struct clk		*clk_ipg;
 	struct clk		*clk_per;
 	const struct imx_uart_data *devdata;
+
+	/* DMA fields */
+	unsigned int		dma_is_inited:1;
+	unsigned int		dma_is_enabled:1;
+	unsigned int		dma_is_rxing:1;
+	unsigned int		dma_is_txing:1;
+	struct dma_chan		*dma_chan_rx, *dma_chan_tx;
+	struct scatterlist	rx_sgl, tx_sgl[2];
+	void			*rx_buf;
+	unsigned int		rx_bytes, tx_bytes;
+	struct work_struct	tsk_dma_rx, tsk_dma_tx;
+	unsigned int		dma_tx_nents;
+	wait_queue_head_t	dma_wait;
 };
 
 struct imx_port_ucrs {
@@ -232,6 +250,10 @@ static struct imx_uart_data imx_uart_devdata[] = {
 		.uts_reg = IMX21_UTS,
 		.devtype = IMX21_UART,
 	},
+	[IMX6Q_UART] = {
+		.uts_reg = IMX21_UTS,
+		.devtype = IMX6Q_UART,
+	},
 };
 
 static struct platform_device_id imx_uart_devtype[] = {
@@ -242,12 +264,16 @@ static struct platform_device_id imx_uart_devtype[] = {
 		.name = "imx21-uart",
 		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART],
 	}, {
+		.name = "imx6q-uart",
+		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX6Q_UART],
+	}, {
 		/* sentinel */
 	}
 };
 MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
 
 static struct of_device_id imx_uart_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
 	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
 	{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
 	{ /* sentinel */ }
@@ -269,6 +295,10 @@ static inline int is_imx21_uart(struct imx_port *sport)
 	return sport->devdata->devtype == IMX21_UART;
 }
 
+static inline int is_imx6q_uart(struct imx_port *sport)
+{
+	return sport->devdata->devtype == IMX6Q_UART;
+}
 /*
  * Save and restore functions for UCR1, UCR2 and UCR3 registers
  */
@@ -387,6 +417,13 @@ static void imx_stop_tx(struct uart_port *port)
 		return;
 	}
 
+	/*
+	 * We are maybe in the SMP context, so if the DMA TX thread is running
+	 * on other cpu, we have to wait for it to finish.
+	 */
+	if (sport->dma_is_enabled && sport->dma_is_txing)
+		return;
+
 	temp = readl(sport->port.membase + UCR1);
 	writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
 }
@@ -399,6 +436,13 @@ static void imx_stop_rx(struct uart_port *port)
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long temp;
 
+	/*
+	 * We are maybe in the SMP context, so if the DMA TX thread is running
+	 * on other cpu, we have to wait for it to finish.
+	 */
+	if (sport->dma_is_enabled && sport->dma_is_rxing)
+		return;
+
 	temp = readl(sport->port.membase + UCR2);
 	writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
 }
@@ -434,6 +478,95 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 		imx_stop_tx(&sport->port);
 }
 
+static void dma_tx_callback(void *data)
+{
+	struct imx_port *sport = data;
+	struct scatterlist *sgl = &sport->tx_sgl[0];
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	unsigned long flags;
+
+	dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
+
+	sport->dma_is_txing = 0;
+
+	/* update the stat */
+	spin_lock_irqsave(&sport->port.lock, flags);
+	xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
+	sport->port.icount.tx += sport->tx_bytes;
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+
+	dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&sport->port);
+
+	if (waitqueue_active(&sport->dma_wait)) {
+		wake_up(&sport->dma_wait);
+		dev_dbg(sport->port.dev, "exit in %s.\n", __func__);
+		return;
+	}
+
+	schedule_work(&sport->tsk_dma_tx);
+}
+
+static void dma_tx_work(struct work_struct *w)
+{
+	struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx);
+	struct circ_buf *xmit = &sport->port.state->xmit;
+	struct scatterlist *sgl = sport->tx_sgl;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan	*chan = sport->dma_chan_tx;
+	struct device *dev = sport->port.dev;
+	enum dma_status status;
+	unsigned long flags;
+	int ret;
+
+	status = chan->device->device_tx_status(chan, (dma_cookie_t)0, NULL);
+	if (DMA_IN_PROGRESS == status)
+		return;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+	sport->tx_bytes = uart_circ_chars_pending(xmit);
+	if (sport->tx_bytes == 0) {
+		spin_unlock_irqrestore(&sport->port.lock, flags);
+		return;
+	}
+
+	if (xmit->tail > xmit->head) {
+		sport->dma_tx_nents = 2;
+		sg_init_table(sgl, 2);
+		sg_set_buf(sgl, xmit->buf + xmit->tail,
+				UART_XMIT_SIZE - xmit->tail);
+		sg_set_buf(sgl + 1, xmit->buf, xmit->head);
+	} else {
+		sport->dma_tx_nents = 1;
+		sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
+	}
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+
+	ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
+	if (ret == 0) {
+		dev_err(dev, "DMA mapping error for TX.\n");
+		return;
+	}
+	desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
+					DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+	if (!desc) {
+		dev_err(dev, "We cannot prepare for the TX slave dma!\n");
+		return;
+	}
+	desc->callback = dma_tx_callback;
+	desc->callback_param = sport;
+
+	dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
+			uart_circ_chars_pending(xmit));
+	/* fire it */
+	sport->dma_is_txing = 1;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(chan);
+	return;
+}
+
 /*
  * interrupts disabled on entry
  */
@@ -460,8 +593,10 @@ static void imx_start_tx(struct uart_port *port)
 	temp |= UCR4_OREN;
 	writel(temp, sport->port.membase + UCR4);
 
-	temp = readl(sport->port.membase + UCR1);
-	writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
+	if (!sport->dma_is_enabled) {
+		temp = readl(sport->port.membase + UCR1);
+		writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
+	}
 
 	if (USE_IRDA(sport)) {
 		temp = readl(sport->port.membase + UCR1);
@@ -473,6 +608,15 @@ static void imx_start_tx(struct uart_port *port)
 		writel(temp, sport->port.membase + UCR4);
 	}
 
+	if (sport->dma_is_enabled) {
+		/*
+		 * We may in the interrupt context, so arise a work_struct to
+		 * do the real job.
+		 */
+		schedule_work(&sport->tsk_dma_tx);
+		return;
+	}
+
 	if (readl(sport->port.membase + uts_reg(sport)) & UTS_TXEMPTY)
 		imx_transmit_buffer(sport);
 }
@@ -588,6 +732,28 @@ out:
 	return IRQ_HANDLED;
 }
 
+/*
+ * If the RXFIFO is filled with some data, and then we
+ * arise a DMA operation to receive them.
+ */
+static void imx_dma_rxint(struct imx_port *sport)
+{
+	unsigned long temp;
+
+	temp = readl(sport->port.membase + USR2);
+	if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
+		sport->dma_is_rxing = 1;
+
+		/* disable the `Recerver Ready Interrrupt` */
+		temp = readl(sport->port.membase + UCR1);
+		temp &= ~(UCR1_RRDYEN);
+		writel(temp, sport->port.membase + UCR1);
+
+		/* tell the DMA to receive the data. */
+		schedule_work(&sport->tsk_dma_rx);
+	}
+}
+
 static irqreturn_t imx_int(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
@@ -596,8 +762,12 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 
 	sts = readl(sport->port.membase + USR1);
 
-	if (sts & USR1_RRDY)
-		imx_rxint(irq, dev_id);
+	if (sts & USR1_RRDY) {
+		if (sport->dma_is_enabled)
+			imx_dma_rxint(sport);
+		else
+			imx_rxint(irq, dev_id);
+	}
 
 	if (sts & USR1_TRDY &&
 			readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
@@ -654,7 +824,8 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
 
 	if (mctrl & TIOCM_RTS)
-		temp |= UCR2_CTS;
+		if (!sport->dma_is_enabled)
+			temp |= UCR2_CTS;
 
 	writel(temp, sport->port.membase + UCR2);
 }
@@ -693,6 +864,226 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 	return 0;
 }
 
+#define RX_BUF_SIZE	(PAGE_SIZE)
+static int start_rx_dma(struct imx_port *sport);
+static void dma_rx_work(struct work_struct *w)
+{
+	struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx);
+	struct tty_port *port = &sport->port.state->port;
+
+	if (sport->rx_bytes) {
+		tty_insert_flip_string(port, sport->rx_buf, sport->rx_bytes);
+		tty_flip_buffer_push(port);
+		sport->rx_bytes = 0;
+	}
+
+	if (sport->dma_is_rxing)
+		start_rx_dma(sport);
+}
+
+static void imx_rx_dma_done(struct imx_port *sport)
+{
+	unsigned long temp;
+
+	/* Enable this interrupt when the RXFIFO is empty. */
+	temp = readl(sport->port.membase + UCR1);
+	temp |= UCR1_RRDYEN;
+	writel(temp, sport->port.membase + UCR1);
+
+	sport->dma_is_rxing = 0;
+
+	/* Is the shutdown waiting for us? */
+	if (waitqueue_active(&sport->dma_wait))
+		wake_up(&sport->dma_wait);
+}
+
+/*
+ * There are three kinds of RX DMA interrupts(such as in the MX6Q):
+ *   [1] the RX DMA buffer is full.
+ *   [2] the Aging timer expires(wait for 8 bytes long)
+ *   [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
+ *
+ * The [2] is trigger when a character was been sitting in the FIFO
+ * meanwhile [3] can wait for 32 bytes long when the RX line is
+ * on IDLE state and RxFIFO is empty.
+ */
+static void dma_rx_callback(void *data)
+{
+	struct imx_port *sport = data;
+	struct dma_chan	*chan = sport->dma_chan_rx;
+	struct scatterlist *sgl = &sport->rx_sgl;
+	struct dma_tx_state state;
+	enum dma_status status;
+	unsigned int count;
+
+	/* unmap it first */
+	dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE);
+
+	status = chan->device->device_tx_status(chan, (dma_cookie_t)0, &state);
+	count = RX_BUF_SIZE - state.residue;
+	dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
+
+	if (count) {
+		sport->rx_bytes = count;
+		schedule_work(&sport->tsk_dma_rx);
+	} else
+		imx_rx_dma_done(sport);
+}
+
+static int start_rx_dma(struct imx_port *sport)
+{
+	struct scatterlist *sgl = &sport->rx_sgl;
+	struct dma_chan	*chan = sport->dma_chan_rx;
+	struct device *dev = sport->port.dev;
+	struct dma_async_tx_descriptor *desc;
+	int ret;
+
+	sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+	ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
+	if (ret == 0) {
+		dev_err(dev, "DMA mapping error for RX.\n");
+		return -EINVAL;
+	}
+	desc = dmaengine_prep_slave_sg(chan, sgl, 1, DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT);
+	if (!desc) {
+		dev_err(dev, "We cannot prepare for the RX slave dma!\n");
+		return -EINVAL;
+	}
+	desc->callback = dma_rx_callback;
+	desc->callback_param = sport;
+
+	dev_dbg(dev, "RX: prepare for the DMA.\n");
+	dmaengine_submit(desc);
+	dma_async_issue_pending(chan);
+	return 0;
+}
+
+static void imx_uart_dma_exit(struct imx_port *sport)
+{
+	if (sport->dma_chan_rx) {
+		dma_release_channel(sport->dma_chan_rx);
+		sport->dma_chan_rx = NULL;
+
+		kfree(sport->rx_buf);
+		sport->rx_buf = NULL;
+	}
+
+	if (sport->dma_chan_tx) {
+		dma_release_channel(sport->dma_chan_tx);
+		sport->dma_chan_tx = NULL;
+	}
+
+	sport->dma_is_inited = 0;
+}
+
+static int imx_uart_dma_init(struct imx_port *sport)
+{
+	struct dma_slave_config slave_config;
+	struct device *dev = sport->port.dev;
+	int ret;
+
+	/* Prepare for RX : */
+	sport->dma_chan_rx = dma_request_slave_channel(dev, "rx");
+	if (!sport->dma_chan_rx) {
+		dev_dbg(dev, "cannot get the DMA channel.\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	slave_config.direction = DMA_DEV_TO_MEM;
+	slave_config.src_addr = sport->port.mapbase + URXD0;
+	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config.src_maxburst = RXTL;
+	ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
+	if (ret) {
+		dev_err(dev, "error in RX dma configuration.\n");
+		goto err;
+	}
+
+	sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!sport->rx_buf) {
+		dev_err(dev, "cannot alloc DMA buffer.\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	sport->rx_bytes = 0;
+
+	/* Prepare for TX : */
+	sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
+	if (!sport->dma_chan_tx) {
+		dev_err(dev, "cannot get the TX DMA channel!\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	slave_config.direction = DMA_MEM_TO_DEV;
+	slave_config.dst_addr = sport->port.mapbase + URTX0;
+	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config.dst_maxburst = TXTL;
+	ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
+	if (ret) {
+		dev_err(dev, "error in TX dma configuration.");
+		goto err;
+	}
+
+	sport->dma_is_inited = 1;
+
+	return 0;
+err:
+	imx_uart_dma_exit(sport);
+	return ret;
+}
+
+static void imx_enable_dma(struct imx_port *sport)
+{
+	unsigned long temp;
+	struct tty_port *port = &sport->port.state->port;
+
+	port->low_latency = 1;
+	INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);
+	INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);
+	init_waitqueue_head(&sport->dma_wait);
+
+	/* set UCR1 */
+	temp = readl(sport->port.membase + UCR1);
+	temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
+		/* wait for 32 idle frames for IDDMA interrupt */
+		UCR1_ICD_REG(3);
+	writel(temp, sport->port.membase + UCR1);
+
+	/* set UCR4 */
+	temp = readl(sport->port.membase + UCR4);
+	temp |= UCR4_IDDMAEN;
+	writel(temp, sport->port.membase + UCR4);
+
+	sport->dma_is_enabled = 1;
+}
+
+static void imx_disable_dma(struct imx_port *sport)
+{
+	unsigned long temp;
+	struct tty_port *port = &sport->port.state->port;
+
+	/* clear UCR1 */
+	temp = readl(sport->port.membase + UCR1);
+	temp &= ~(UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN);
+	writel(temp, sport->port.membase + UCR1);
+
+	/* clear UCR2 */
+	temp = readl(sport->port.membase + UCR2);
+	temp &= ~(UCR2_CTSC | UCR2_CTS);
+	writel(temp, sport->port.membase + UCR2);
+
+	/* clear UCR4 */
+	temp = readl(sport->port.membase + UCR4);
+	temp &= ~UCR4_IDDMAEN;
+	writel(temp, sport->port.membase + UCR4);
+
+	sport->dma_is_enabled = 0;
+	port->low_latency = 0;
+}
+
 /* half the RX buffer size */
 #define CTSTL 16
 
@@ -702,15 +1093,13 @@ static int imx_startup(struct uart_port *port)
 	int retval;
 	unsigned long flags, temp;
 
-	if (!uart_console(port)) {
-		retval = clk_prepare_enable(sport->clk_per);
-		if (retval)
-			goto error_out1;
-		retval = clk_prepare_enable(sport->clk_ipg);
-		if (retval) {
-			clk_disable_unprepare(sport->clk_per);
-			goto error_out1;
-		}
+	retval = clk_prepare_enable(sport->clk_per);
+	if (retval)
+		goto error_out1;
+	retval = clk_prepare_enable(sport->clk_ipg);
+	if (retval) {
+		clk_disable_unprepare(sport->clk_per);
+		goto error_out1;
 	}
 
 	imx_setup_ufcr(sport, 0);
@@ -803,7 +1192,7 @@ static int imx_startup(struct uart_port *port)
 		}
 	}
 
-	if (is_imx21_uart(sport)) {
+	if (!is_imx1_uart(sport)) {
 		temp = readl(sport->port.membase + UCR3);
 		temp |= IMX21_UCR3_RXDMUXSEL;
 		writel(temp, sport->port.membase + UCR3);
@@ -833,7 +1222,7 @@ static int imx_startup(struct uart_port *port)
 
 	if (USE_IRDA(sport)) {
 		struct imxuart_platform_data *pdata;
-		pdata = sport->port.dev->platform_data;
+		pdata = dev_get_platdata(sport->port.dev);
 		sport->irda_inv_rx = pdata->irda_inv_rx;
 		sport->irda_inv_tx = pdata->irda_inv_tx;
 		sport->trcv_delay = pdata->transceiver_delay;
@@ -859,6 +1248,15 @@ static void imx_shutdown(struct uart_port *port)
 	unsigned long temp;
 	unsigned long flags;
 
+	if (sport->dma_is_enabled) {
+		/* We have to wait for the DMA to finish. */
+		wait_event(sport->dma_wait,
+			!sport->dma_is_rxing && !sport->dma_is_txing);
+		imx_stop_rx(port);
+		imx_disable_dma(sport);
+		imx_uart_dma_exit(sport);
+	}
+
 	spin_lock_irqsave(&sport->port.lock, flags);
 	temp = readl(sport->port.membase + UCR2);
 	temp &= ~(UCR2_TXEN);
@@ -867,7 +1265,7 @@ static void imx_shutdown(struct uart_port *port)
 
 	if (USE_IRDA(sport)) {
 		struct imxuart_platform_data *pdata;
-		pdata = sport->port.dev->platform_data;
+		pdata = dev_get_platdata(sport->port.dev);
 		if (pdata->irda_enable)
 			pdata->irda_enable(0);
 	}
@@ -901,10 +1299,8 @@ static void imx_shutdown(struct uart_port *port)
 	writel(temp, sport->port.membase + UCR1);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
-	if (!uart_console(&sport->port)) {
-		clk_disable_unprepare(sport->clk_per);
-		clk_disable_unprepare(sport->clk_ipg);
-	}
+	clk_disable_unprepare(sport->clk_per);
+	clk_disable_unprepare(sport->clk_ipg);
 }
 
 static void
@@ -947,6 +1343,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 		if (sport->have_rtscts) {
 			ucr2 &= ~UCR2_IRTS;
 			ucr2 |= UCR2_CTSC;
+
+			/* Can we enable the DMA support? */
+			if (is_imx6q_uart(sport) && !uart_console(port)
+				&& !sport->dma_is_inited)
+				imx_uart_dma_init(sport);
 		} else {
 			termios->c_cflag &= ~CRTSCTS;
 		}
@@ -1020,6 +1421,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 		 */
 		div = 1;
 	} else {
+		/* custom-baudrate handling */
+		div = sport->port.uartclk / (baud * 16);
+		if (baud == 38400 && quot != div)
+			baud = sport->port.uartclk / (quot * 16);
+
 		div = sport->port.uartclk / (baud * 16);
 		if (div > 7)
 			div = 7;
@@ -1048,7 +1454,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(num, sport->port.membase + UBIR);
 	writel(denom, sport->port.membase + UBMR);
 
-	if (is_imx21_uart(sport))
+	if (!is_imx1_uart(sport))
 		writel(sport->port.uartclk / div / 1000,
 				sport->port.membase + IMX21_ONEMS);
 
@@ -1060,6 +1466,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
 		imx_enable_ms(&sport->port);
 
+	if (sport->dma_is_inited && !sport->dma_is_enabled)
+		imx_enable_dma(sport);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
@@ -1251,6 +1659,16 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 	unsigned int ucr1;
 	unsigned long flags = 0;
 	int locked = 1;
+	int retval;
+
+	retval = clk_enable(sport->clk_per);
+	if (retval)
+		return;
+	retval = clk_enable(sport->clk_ipg);
+	if (retval) {
+		clk_disable(sport->clk_per);
+		return;
+	}
 
 	if (sport->port.sysrq)
 		locked = 0;
@@ -1286,6 +1704,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 
 	if (locked)
 		spin_unlock_irqrestore(&sport->port.lock, flags);
+
+	clk_disable(sport->clk_ipg);
+	clk_disable(sport->clk_per);
 }
 
 /*
@@ -1359,6 +1780,7 @@ imx_console_setup(struct console *co, char *options)
 	int bits = 8;
 	int parity = 'n';
 	int flow = 'n';
+	int retval;
 
 	/*
 	 * Check whether an invalid uart number has been specified, and
@@ -1371,6 +1793,11 @@ imx_console_setup(struct console *co, char *options)
 	if (sport == NULL)
 		return -ENODEV;
 
+	/* For setting the registers, we only need to enable the ipg clock. */
+	retval = clk_prepare_enable(sport->clk_ipg);
+	if (retval)
+		goto error_console;
+
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
@@ -1378,7 +1805,20 @@ imx_console_setup(struct console *co, char *options)
 
 	imx_setup_ufcr(sport, 0);
 
-	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
+	retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
+
+	clk_disable(sport->clk_ipg);
+	if (retval) {
+		clk_unprepare(sport->clk_ipg);
+		goto error_console;
+	}
+
+	retval = clk_prepare(sport->clk_per);
+	if (retval)
+		clk_disable_unprepare(sport->clk_ipg);
+
+error_console:
+	return retval;
 }
 
 static struct uart_driver imx_reg;
@@ -1485,7 +1925,7 @@ static inline int serial_imx_probe_dt(struct imx_port *sport,
 static void serial_imx_probe_pdata(struct imx_port *sport,
 		struct platform_device *pdev)
 {
-	struct imxuart_platform_data *pdata = pdev->dev.platform_data;
+	struct imxuart_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	sport->port.line = pdev->id;
 	sport->devdata = (struct imx_uart_data	*) pdev->id_entry->driver_data;
@@ -1507,7 +1947,6 @@ static int serial_imx_probe(struct platform_device *pdev)
 	void __iomem *base;
 	int ret = 0;
 	struct resource *res;
-	struct pinctrl *pinctrl;
 
 	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
 	if (!sport)
@@ -1543,13 +1982,6 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret);
-		return ret;
-	}
-
 	sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(sport->clk_ipg)) {
 		ret = PTR_ERR(sport->clk_ipg);
@@ -1564,18 +1996,15 @@ static int serial_imx_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	clk_prepare_enable(sport->clk_per);
-	clk_prepare_enable(sport->clk_ipg);
-
 	sport->port.uartclk = clk_get_rate(sport->clk_per);
 
 	imx_ports[sport->port.line] = sport;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (pdata && pdata->init) {
 		ret = pdata->init(pdev);
 		if (ret)
-			goto clkput;
+			return ret;
 	}
 
 	ret = uart_add_one_port(&imx_reg, &sport->port);
@@ -1583,18 +2012,10 @@ static int serial_imx_probe(struct platform_device *pdev)
 		goto deinit;
 	platform_set_drvdata(pdev, sport);
 
-	if (!uart_console(&sport->port)) {
-		clk_disable_unprepare(sport->clk_per);
-		clk_disable_unprepare(sport->clk_ipg);
-	}
-
 	return 0;
 deinit:
 	if (pdata && pdata->exit)
 		pdata->exit(pdev);
-clkput:
-	clk_disable_unprepare(sport->clk_per);
-	clk_disable_unprepare(sport->clk_ipg);
 	return ret;
 }
 
@@ -1603,9 +2024,7 @@ static int serial_imx_remove(struct platform_device *pdev)
 	struct imxuart_platform_data *pdata;
 	struct imx_port *sport = platform_get_drvdata(pdev);
 
-	pdata = pdev->dev.platform_data;
-
-	platform_set_drvdata(pdev, NULL);
+	pdata = dev_get_platdata(&pdev->dev);
 
 	uart_remove_one_port(&imx_reg, &sport->port);
 
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 35866d5..79f9a9e 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -779,7 +779,7 @@ static int max3100_probe(struct spi_device *spi)
 	max3100s[i]->irq = spi->irq;
 	spin_lock_init(&max3100s[i]->conf_lock);
 	spi_set_drvdata(spi, max3100s[i]);
-	pdata = spi->dev.platform_data;
+	pdata = dev_get_platdata(&spi->dev);
 	max3100s[i]->crystal = pdata->crystal;
 	max3100s[i]->loopback = pdata->loopback;
 	max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 8941e64..b2e707a 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1,7 +1,7 @@
 /*
- *  Maxim (Dallas) MAX3107/8 serial driver
+ *  Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
  *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2013 Alexander Shiyan <shc_work@mail.ru>
  *
  *  Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
  *  Based on max3110.c, by Feng Tang <feng.tang@intel.com>
@@ -13,11 +13,10 @@
  *  (at your option) any later version.
  */
 
-/* TODO: MAX3109 support (Dual) */
-/* TODO: MAX14830 support (Quad) */
-
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/bitops.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
@@ -25,8 +24,10 @@
 #include <linux/regmap.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
+
 #include <linux/platform_data/max310x.h>
 
+#define MAX310X_NAME			"max310x"
 #define MAX310X_MAJOR			204
 #define MAX310X_MINOR			209
 
@@ -37,7 +38,8 @@
 #define MAX310X_IRQSTS_REG		(0x02) /* IRQ status */
 #define MAX310X_LSR_IRQEN_REG		(0x03) /* LSR IRQ enable */
 #define MAX310X_LSR_IRQSTS_REG		(0x04) /* LSR IRQ status */
-#define MAX310X_SPCHR_IRQEN_REG		(0x05) /* Special char IRQ enable */
+#define MAX310X_REG_05			(0x05)
+#define MAX310X_SPCHR_IRQEN_REG		MAX310X_REG_05 /* Special char IRQ en */
 #define MAX310X_SPCHR_IRQSTS_REG	(0x06) /* Special char IRQ status */
 #define MAX310X_STS_IRQEN_REG		(0x07) /* Status IRQ enable */
 #define MAX310X_STS_IRQSTS_REG		(0x08) /* Status IRQ status */
@@ -63,8 +65,15 @@
 #define MAX310X_BRGDIVLSB_REG		(0x1c) /* Baud rate divisor LSB */
 #define MAX310X_BRGDIVMSB_REG		(0x1d) /* Baud rate divisor MSB */
 #define MAX310X_CLKSRC_REG		(0x1e) /* Clock source */
-/* Only present in MAX3107 */
-#define MAX3107_REVID_REG		(0x1f) /* Revision identification */
+#define MAX310X_REG_1F			(0x1f)
+
+#define MAX310X_REVID_REG		MAX310X_REG_1F /* Revision ID */
+
+#define MAX310X_GLOBALIRQ_REG		MAX310X_REG_1F /* Global IRQ (RO) */
+#define MAX310X_GLOBALCMD_REG		MAX310X_REG_1F /* Global Command (WO) */
+
+/* Extended registers */
+#define MAX310X_REVID_EXTREG		MAX310X_REG_05 /* Revision ID */
 
 /* IRQ register bits */
 #define MAX310X_IRQ_LSR_BIT		(1 << 0) /* LSR interrupt */
@@ -246,58 +255,210 @@
 #define MAX310X_CLKSRC_EXTCLK_BIT	(1 << 4) /* External clock enable */
 #define MAX310X_CLKSRC_CLK2RTS_BIT	(1 << 7) /* Baud clk to RTS pin */
 
+/* Global commands */
+#define MAX310X_EXTREG_ENBL		(0xce)
+#define MAX310X_EXTREG_DSBL		(0xcd)
+
 /* Misc definitions */
 #define MAX310X_FIFO_SIZE		(128)
+#define MAX310x_REV_MASK		(0xfc)
 
 /* MAX3107 specific */
 #define MAX3107_REV_ID			(0xa0)
-#define MAX3107_REV_MASK		(0xfe)
-
-/* IRQ status bits definitions */
-#define MAX310X_IRQ_TX			(MAX310X_IRQ_TXFIFO_BIT | \
-					 MAX310X_IRQ_TXEMPTY_BIT)
-#define MAX310X_IRQ_RX			(MAX310X_IRQ_RXFIFO_BIT | \
-					 MAX310X_IRQ_RXEMPTY_BIT)
-
-/* Supported chip types */
-enum {
-	MAX310X_TYPE_MAX3107	= 3107,
-	MAX310X_TYPE_MAX3108	= 3108,
+
+/* MAX3109 specific */
+#define MAX3109_REV_ID			(0xc0)
+
+/* MAX14830 specific */
+#define MAX14830_BRGCFG_CLKDIS_BIT	(1 << 6) /* Clock Disable */
+#define MAX14830_REV_ID			(0xb0)
+
+struct max310x_devtype {
+	char	name[9];
+	int	nr;
+	int	(*detect)(struct device *);
+	void	(*power)(struct uart_port *, int);
 };
 
-struct max310x_port {
-	struct uart_driver	uart;
+struct max310x_one {
 	struct uart_port	port;
+	struct work_struct	tx_work;
+};
 
-	const char		*name;
-	int			uartclk;
-
-	unsigned int		nr_gpio;
+struct max310x_port {
+	struct uart_driver	uart;
+	struct max310x_devtype	*devtype;
+	struct regmap		*regmap;
+	struct regmap_config	regcfg;
+	struct mutex		mutex;
+	struct max310x_pdata	*pdata;
+	int			gpio_used;
 #ifdef CONFIG_GPIOLIB
 	struct gpio_chip	gpio;
 #endif
+	struct max310x_one	p[0];
+};
 
-	struct regmap		*regmap;
-	struct regmap_config	regcfg;
+static u8 max310x_port_read(struct uart_port *port, u8 reg)
+{
+	struct max310x_port *s = dev_get_drvdata(port->dev);
+	unsigned int val = 0;
 
-	struct workqueue_struct	*wq;
-	struct work_struct	tx_work;
+	regmap_read(s->regmap, port->iobase + reg, &val);
 
-	struct mutex		max310x_mutex;
+	return val;
+}
 
-	struct max310x_pdata	*pdata;
+static void max310x_port_write(struct uart_port *port, u8 reg, u8 val)
+{
+	struct max310x_port *s = dev_get_drvdata(port->dev);
+
+	regmap_write(s->regmap, port->iobase + reg, val);
+}
+
+static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val)
+{
+	struct max310x_port *s = dev_get_drvdata(port->dev);
+
+	regmap_update_bits(s->regmap, port->iobase + reg, mask, val);
+}
+
+static int max3107_detect(struct device *dev)
+{
+	struct max310x_port *s = dev_get_drvdata(dev);
+	unsigned int val = 0;
+	int ret;
+
+	ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val);
+	if (ret)
+		return ret;
+
+	if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) {
+		dev_err(dev,
+			"%s ID 0x%02x does not match\n", s->devtype->name, val);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int max3108_detect(struct device *dev)
+{
+	struct max310x_port *s = dev_get_drvdata(dev);
+	unsigned int val = 0;
+	int ret;
+
+	/* MAX3108 have not REV ID register, we just check default value
+	 * from clocksource register to make sure everything works.
+	 */
+	ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
+	if (ret)
+		return ret;
+
+	if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) {
+		dev_err(dev, "%s not present\n", s->devtype->name);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int max3109_detect(struct device *dev)
+{
+	struct max310x_port *s = dev_get_drvdata(dev);
+	unsigned int val = 0;
+	int ret;
+
+	ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val);
+	if (ret)
+		return ret;
+
+	if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) {
+		dev_err(dev,
+			"%s ID 0x%02x does not match\n", s->devtype->name, val);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void max310x_power(struct uart_port *port, int on)
+{
+	max310x_port_update(port, MAX310X_MODE1_REG,
+			    MAX310X_MODE1_FORCESLEEP_BIT,
+			    on ? 0 : MAX310X_MODE1_FORCESLEEP_BIT);
+	if (on)
+		msleep(50);
+}
+
+static int max14830_detect(struct device *dev)
+{
+	struct max310x_port *s = dev_get_drvdata(dev);
+	unsigned int val = 0;
+	int ret;
+
+	ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
+			   MAX310X_EXTREG_ENBL);
+	if (ret)
+		return ret;
+	
+	regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
+	regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
+	if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) {
+		dev_err(dev,
+			"%s ID 0x%02x does not match\n", s->devtype->name, val);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void max14830_power(struct uart_port *port, int on)
+{
+	max310x_port_update(port, MAX310X_BRGCFG_REG,
+			    MAX14830_BRGCFG_CLKDIS_BIT,
+			    on ? 0 : MAX14830_BRGCFG_CLKDIS_BIT);
+	if (on)
+		msleep(50);
+}
+
+static const struct max310x_devtype max3107_devtype = {
+	.name	= "MAX3107",
+	.nr	= 1,
+	.detect	= max3107_detect,
+	.power	= max310x_power,
+};
+
+static const struct max310x_devtype max3108_devtype = {
+	.name	= "MAX3108",
+	.nr	= 1,
+	.detect	= max3108_detect,
+	.power	= max310x_power,
+};
+
+static const struct max310x_devtype max3109_devtype = {
+	.name	= "MAX3109",
+	.nr	= 2,
+	.detect	= max3109_detect,
+	.power	= max310x_power,
+};
+
+static const struct max310x_devtype max14830_devtype = {
+	.name	= "MAX14830",
+	.nr	= 4,
+	.detect	= max14830_detect,
+	.power	= max14830_power,
 };
 
-static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg)
+static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
 {
-	switch (reg) {
+	switch (reg & 0x1f) {
 	case MAX310X_IRQSTS_REG:
 	case MAX310X_LSR_IRQSTS_REG:
 	case MAX310X_SPCHR_IRQSTS_REG:
 	case MAX310X_STS_IRQSTS_REG:
 	case MAX310X_TXFIFOLVL_REG:
 	case MAX310X_RXFIFOLVL_REG:
-	case MAX3107_REVID_REG: /* Only available on MAX3107 */
 		return false;
 	default:
 		break;
@@ -308,7 +469,7 @@ static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg)
 
 static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
 {
-	switch (reg) {
+	switch (reg & 0x1f) {
 	case MAX310X_RHR_REG:
 	case MAX310X_IRQSTS_REG:
 	case MAX310X_LSR_IRQSTS_REG:
@@ -317,6 +478,9 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
 	case MAX310X_TXFIFOLVL_REG:
 	case MAX310X_RXFIFOLVL_REG:
 	case MAX310X_GPIODATA_REG:
+	case MAX310X_BRGDIVLSB_REG:
+	case MAX310X_REG_05:
+	case MAX310X_REG_1F:
 		return true;
 	default:
 		break;
@@ -327,7 +491,7 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
 
 static bool max310x_reg_precious(struct device *dev, unsigned int reg)
 {
-	switch (reg) {
+	switch (reg & 0x1f) {
 	case MAX310X_RHR_REG:
 	case MAX310X_IRQSTS_REG:
 	case MAX310X_SPCHR_IRQSTS_REG:
@@ -340,42 +504,25 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
 	return false;
 }
 
-static void max310x_set_baud(struct max310x_port *s, int baud)
+static void max310x_set_baud(struct uart_port *port, int baud)
 {
-	unsigned int mode = 0, div = s->uartclk / baud;
+	unsigned int mode = 0, div = port->uartclk / baud;
 
 	if (!(div / 16)) {
 		/* Mode x2 */
 		mode = MAX310X_BRGCFG_2XMODE_BIT;
-		div = (s->uartclk * 2) / baud;
+		div = (port->uartclk * 2) / baud;
 	}
 
 	if (!(div / 16)) {
 		/* Mode x4 */
 		mode = MAX310X_BRGCFG_4XMODE_BIT;
-		div = (s->uartclk * 4) / baud;
+		div = (port->uartclk * 4) / baud;
 	}
 
-	regmap_write(s->regmap, MAX310X_BRGDIVMSB_REG,
-		     ((div / 16) >> 8) & 0xff);
-	regmap_write(s->regmap, MAX310X_BRGDIVLSB_REG, (div / 16) & 0xff);
-	regmap_write(s->regmap, MAX310X_BRGCFG_REG, (div % 16) | mode);
-}
-
-static void max310x_wait_pll(struct max310x_port *s)
-{
-	int tryes = 1000;
-
-	/* Wait for PLL only if crystal is used */
-	if (!(s->pdata->driver_flags & MAX310X_EXT_CLK)) {
-		unsigned int sts = 0;
-
-		while (tryes--) {
-			regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &sts);
-			if (sts & MAX310X_STS_CLKREADY_BIT)
-				break;
-		}
-	}
+	max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8);
+	max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16);
+	max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode);
 }
 
 static int max310x_update_best_err(unsigned long f, long *besterr)
@@ -449,49 +596,49 @@ static int max310x_set_ref_clk(struct max310x_port *s)
 
 	regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
 
-	if (pllcfg)
-		max310x_wait_pll(s);
-
-	dev_dbg(s->port.dev, "Reference clock set to %lu Hz\n", bestfreq);
+	/* Wait for crystal */
+	if (pllcfg && !(s->pdata->driver_flags & MAX310X_EXT_CLK))
+		msleep(10);
 
 	return (int)bestfreq;
 }
 
-static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen)
+static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
 {
-	unsigned int sts = 0, ch = 0, flag;
+	unsigned int sts, ch, flag;
 
-	if (unlikely(rxlen >= MAX310X_FIFO_SIZE)) {
-		dev_warn(s->port.dev, "Possible RX FIFO overrun %d\n", rxlen);
+	if (unlikely(rxlen >= port->fifosize)) {
+		dev_warn_ratelimited(port->dev,
+				     "Port %i: Possible RX FIFO overrun\n",
+				     port->line);
+		port->icount.buf_overrun++;
 		/* Ensure sanity of RX level */
-		rxlen = MAX310X_FIFO_SIZE;
+		rxlen = port->fifosize;
 	}
 
-	dev_dbg(s->port.dev, "RX Len = %u\n", rxlen);
-
 	while (rxlen--) {
-		regmap_read(s->regmap, MAX310X_RHR_REG, &ch);
-		regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &sts);
+		ch = max310x_port_read(port, MAX310X_RHR_REG);
+		sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
 
 		sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
 		       MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
 
-		s->port.icount.rx++;
+		port->icount.rx++;
 		flag = TTY_NORMAL;
 
 		if (unlikely(sts)) {
 			if (sts & MAX310X_LSR_RXBRK_BIT) {
-				s->port.icount.brk++;
-				if (uart_handle_break(&s->port))
+				port->icount.brk++;
+				if (uart_handle_break(port))
 					continue;
 			} else if (sts & MAX310X_LSR_RXPAR_BIT)
-				s->port.icount.parity++;
+				port->icount.parity++;
 			else if (sts & MAX310X_LSR_FRERR_BIT)
-				s->port.icount.frame++;
+				port->icount.frame++;
 			else if (sts & MAX310X_LSR_RXOVR_BIT)
-				s->port.icount.overrun++;
+				port->icount.overrun++;
 
-			sts &= s->port.read_status_mask;
+			sts &= port->read_status_mask;
 			if (sts & MAX310X_LSR_RXBRK_BIT)
 				flag = TTY_BREAK;
 			else if (sts & MAX310X_LSR_RXPAR_BIT)
@@ -502,129 +649,129 @@ static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen)
 				flag = TTY_OVERRUN;
 		}
 
-		if (uart_handle_sysrq_char(s->port, ch))
+		if (uart_handle_sysrq_char(port, ch))
 			continue;
 
-		if (sts & s->port.ignore_status_mask)
+		if (sts & port->ignore_status_mask)
 			continue;
 
-		uart_insert_char(&s->port, sts, MAX310X_LSR_RXOVR_BIT,
-				 ch, flag);
+		uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag);
 	}
 
-	tty_flip_buffer_push(&s->port.state->port);
+	tty_flip_buffer_push(&port->state->port);
 }
 
-static void max310x_handle_tx(struct max310x_port *s)
+static void max310x_handle_tx(struct uart_port *port)
 {
-	struct circ_buf *xmit = &s->port.state->xmit;
-	unsigned int txlen = 0, to_send;
+	struct circ_buf *xmit = &port->state->xmit;
+	unsigned int txlen, to_send;
 
-	if (unlikely(s->port.x_char)) {
-		regmap_write(s->regmap, MAX310X_THR_REG, s->port.x_char);
-		s->port.icount.tx++;
-		s->port.x_char = 0;
+	if (unlikely(port->x_char)) {
+		max310x_port_write(port, MAX310X_THR_REG, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
 		return;
 	}
 
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
 		return;
 
 	/* Get length of data pending in circular buffer */
 	to_send = uart_circ_chars_pending(xmit);
 	if (likely(to_send)) {
 		/* Limit to size of TX FIFO */
-		regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &txlen);
-		txlen = MAX310X_FIFO_SIZE - txlen;
+		txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
+		txlen = port->fifosize - txlen;
 		to_send = (to_send > txlen) ? txlen : to_send;
 
-		dev_dbg(s->port.dev, "TX Len = %u\n", to_send);
-
 		/* Add data to send */
-		s->port.icount.tx += to_send;
+		port->icount.tx += to_send;
 		while (to_send--) {
-			regmap_write(s->regmap, MAX310X_THR_REG,
-				     xmit->buf[xmit->tail]);
+			max310x_port_write(port, MAX310X_THR_REG,
+					   xmit->buf[xmit->tail]);
 			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		};
 	}
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&s->port);
+		uart_write_wakeup(port);
 }
 
-static irqreturn_t max310x_ist(int irq, void *dev_id)
+static void max310x_port_irq(struct max310x_port *s, int portno)
 {
-	struct max310x_port *s = (struct max310x_port *)dev_id;
-	unsigned int ists = 0, lsr = 0, rxlen = 0;
+	struct uart_port *port = &s->p[portno].port;
 
-	mutex_lock(&s->max310x_mutex);
+	do {
+		unsigned int ists, lsr, rxlen;
 
-	for (;;) {
 		/* Read IRQ status & RX FIFO level */
-		regmap_read(s->regmap, MAX310X_IRQSTS_REG, &ists);
-		regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &lsr);
-		regmap_read(s->regmap, MAX310X_RXFIFOLVL_REG, &rxlen);
-		if (!ists && !(lsr & MAX310X_LSR_RXTO_BIT) && !rxlen)
+		ists = max310x_port_read(port, MAX310X_IRQSTS_REG);
+		rxlen = max310x_port_read(port, MAX310X_RXFIFOLVL_REG);
+		if (!ists && !rxlen)
 			break;
 
-		dev_dbg(s->port.dev, "IRQ status: 0x%02x\n", ists);
-
-		if (rxlen)
-			max310x_handle_rx(s, rxlen);
-		if (ists & MAX310X_IRQ_TX)
-			max310x_handle_tx(s);
-		if (ists & MAX310X_IRQ_CTS_BIT)
-			uart_handle_cts_change(&s->port,
+		if (ists & MAX310X_IRQ_CTS_BIT) {
+			lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
+			uart_handle_cts_change(port,
 					       !!(lsr & MAX310X_LSR_CTS_BIT));
-	}
+		}
+		if (rxlen)
+			max310x_handle_rx(port, rxlen);
+		if (ists & MAX310X_IRQ_TXEMPTY_BIT) {
+			mutex_lock(&s->mutex);
+			max310x_handle_tx(port);
+			mutex_unlock(&s->mutex);
+		}
+	} while (1);
+}
+
+static irqreturn_t max310x_ist(int irq, void *dev_id)
+{
+	struct max310x_port *s = (struct max310x_port *)dev_id;
 
-	mutex_unlock(&s->max310x_mutex);
+	if (s->uart.nr > 1) {
+		do {
+			unsigned int val = ~0;
+
+			WARN_ON_ONCE(regmap_read(s->regmap,
+						 MAX310X_GLOBALIRQ_REG, &val));
+			val = ((1 << s->uart.nr) - 1) & ~val;
+			if (!val)
+				break;
+			max310x_port_irq(s, fls(val) - 1);
+		} while (1);
+	} else
+		max310x_port_irq(s, 0);
 
 	return IRQ_HANDLED;
 }
 
 static void max310x_wq_proc(struct work_struct *ws)
 {
-	struct max310x_port *s = container_of(ws, struct max310x_port, tx_work);
+	struct max310x_one *one = container_of(ws, struct max310x_one, tx_work);
+	struct max310x_port *s = dev_get_drvdata(one->port.dev);
 
-	mutex_lock(&s->max310x_mutex);
-	max310x_handle_tx(s);
-	mutex_unlock(&s->max310x_mutex);
+	mutex_lock(&s->mutex);
+	max310x_handle_tx(&one->port);
+	mutex_unlock(&s->mutex);
 }
 
 static void max310x_start_tx(struct uart_port *port)
 {
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
-
-	queue_work(s->wq, &s->tx_work);
-}
-
-static void max310x_stop_tx(struct uart_port *port)
-{
-	/* Do nothing */
-}
+	struct max310x_one *one = container_of(port, struct max310x_one, port);
 
-static void max310x_stop_rx(struct uart_port *port)
-{
-	/* Do nothing */
+	if (!work_pending(&one->tx_work))
+		schedule_work(&one->tx_work);
 }
 
 static unsigned int max310x_tx_empty(struct uart_port *port)
 {
-	unsigned int val = 0;
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
+	unsigned int lvl, sts;
 
-	mutex_lock(&s->max310x_mutex);
-	regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &val);
-	mutex_unlock(&s->max310x_mutex);
+	lvl = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
+	sts = max310x_port_read(port, MAX310X_IRQSTS_REG);
 
-	return val ? 0 : TIOCSER_TEMT;
-}
-
-static void max310x_enable_ms(struct uart_port *port)
-{
-	/* Modem status not supported */
+	return ((sts & MAX310X_IRQ_TXEMPTY_BIT) && !lvl) ? TIOCSER_TEMT : 0;
 }
 
 static unsigned int max310x_get_mctrl(struct uart_port *port)
@@ -644,28 +791,20 @@ static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
 static void max310x_break_ctl(struct uart_port *port, int break_state)
 {
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
-
-	mutex_lock(&s->max310x_mutex);
-	regmap_update_bits(s->regmap, MAX310X_LCR_REG,
-			   MAX310X_LCR_TXBREAK_BIT,
-			   break_state ? MAX310X_LCR_TXBREAK_BIT : 0);
-	mutex_unlock(&s->max310x_mutex);
+	max310x_port_update(port, MAX310X_LCR_REG,
+			    MAX310X_LCR_TXBREAK_BIT,
+			    break_state ? MAX310X_LCR_TXBREAK_BIT : 0);
 }
 
 static void max310x_set_termios(struct uart_port *port,
 				struct ktermios *termios,
 				struct ktermios *old)
 {
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
 	unsigned int lcr, flow = 0;
 	int baud;
 
-	mutex_lock(&s->max310x_mutex);
-
 	/* Mask termios capabilities we don't support */
 	termios->c_cflag &= ~CMSPAR;
-	termios->c_iflag &= ~IXANY;
 
 	/* Word size */
 	switch (termios->c_cflag & CSIZE) {
@@ -696,7 +835,7 @@ static void max310x_set_termios(struct uart_port *port,
 		lcr |= MAX310X_LCR_STOPLEN_BIT; /* 2 stops */
 
 	/* Update LCR register */
-	regmap_write(s->regmap, MAX310X_LCR_REG, lcr);
+	max310x_port_write(port, MAX310X_LCR_REG, lcr);
 
 	/* Set read status mask */
 	port->read_status_mask = MAX310X_LSR_RXOVR_BIT;
@@ -717,8 +856,8 @@ static void max310x_set_termios(struct uart_port *port,
 					    MAX310X_LSR_RXBRK_BIT;
 
 	/* Configure flow control */
-	regmap_write(s->regmap, MAX310X_XON1_REG, termios->c_cc[VSTART]);
-	regmap_write(s->regmap, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
+	max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]);
+	max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]);
 	if (termios->c_cflag & CRTSCTS)
 		flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT |
 			MAX310X_FLOWCTRL_AUTORTS_BIT;
@@ -728,7 +867,7 @@ static void max310x_set_termios(struct uart_port *port,
 	if (termios->c_iflag & IXOFF)
 		flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT |
 			MAX310X_FLOWCTRL_SWFLOWEN_BIT;
-	regmap_write(s->regmap, MAX310X_FLOWCTRL_REG, flow);
+	max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow);
 
 	/* Get baud rate generator configuration */
 	baud = uart_get_baud_rate(port, termios, old,
@@ -736,36 +875,30 @@ static void max310x_set_termios(struct uart_port *port,
 				  port->uartclk / 4);
 
 	/* Setup baudrate generator */
-	max310x_set_baud(s, baud);
+	max310x_set_baud(port, baud);
 
 	/* Update timeout according to new baud rate */
 	uart_update_timeout(port, termios->c_cflag, baud);
-
-	mutex_unlock(&s->max310x_mutex);
 }
 
 static int max310x_startup(struct uart_port *port)
 {
 	unsigned int val, line = port->line;
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
-
-	if (s->pdata->suspend)
-		s->pdata->suspend(0);
+	struct max310x_port *s = dev_get_drvdata(port->dev);
 
-	mutex_lock(&s->max310x_mutex);
+	s->devtype->power(port, 1);
 
 	/* Configure baud rate, 9600 as default */
-	max310x_set_baud(s, 9600);
+	max310x_set_baud(port, 9600);
 
 	/* Configure LCR register, 8N1 mode by default */
-	val = MAX310X_LCR_WORD_LEN_8;
-	regmap_write(s->regmap, MAX310X_LCR_REG, val);
+	max310x_port_write(port, MAX310X_LCR_REG, MAX310X_LCR_WORD_LEN_8);
 
 	/* Configure MODE1 register */
-	regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
-			   MAX310X_MODE1_TRNSCVCTRL_BIT,
-			   (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
-			   ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
+	max310x_port_update(port, MAX310X_MODE1_REG,
+			    MAX310X_MODE1_TRNSCVCTRL_BIT,
+			    (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL)
+			    ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0);
 
 	/* Configure MODE2 register */
 	val = MAX310X_MODE2_RXEMPTINV_BIT;
@@ -776,63 +909,40 @@ static int max310x_startup(struct uart_port *port)
 
 	/* Reset FIFOs */
 	val |= MAX310X_MODE2_FIFORST_BIT;
-	regmap_write(s->regmap, MAX310X_MODE2_REG, val);
-
-	/* Configure FIFO trigger level register */
-	/* RX FIFO trigger for 16 words, TX FIFO trigger for 64 words */
-	val = MAX310X_FIFOTRIGLVL_RX(16) | MAX310X_FIFOTRIGLVL_TX(64);
-	regmap_write(s->regmap, MAX310X_FIFOTRIGLVL_REG, val);
+	max310x_port_write(port, MAX310X_MODE2_REG, val);
+	max310x_port_update(port, MAX310X_MODE2_REG,
+			    MAX310X_MODE2_FIFORST_BIT, 0);
 
 	/* Configure flow control levels */
 	/* Flow control halt level 96, resume level 48 */
-	val = MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96);
-	regmap_write(s->regmap, MAX310X_FLOWLVL_REG, val);
-
-	/* Clear timeout register */
-	regmap_write(s->regmap, MAX310X_RXTO_REG, 0);
+	max310x_port_write(port, MAX310X_FLOWLVL_REG,
+			   MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96));
 
-	/* Configure LSR interrupt enable register */
-	/* Enable RX timeout interrupt */
-	val = MAX310X_LSR_RXTO_BIT;
-	regmap_write(s->regmap, MAX310X_LSR_IRQEN_REG, val);
+	/* Clear IRQ status register */
+	max310x_port_read(port, MAX310X_IRQSTS_REG);
 
-	/* Clear FIFO reset */
-	regmap_update_bits(s->regmap, MAX310X_MODE2_REG,
-			   MAX310X_MODE2_FIFORST_BIT, 0);
-
-	/* Clear IRQ status register by reading it */
-	regmap_read(s->regmap, MAX310X_IRQSTS_REG, &val);
-
-	/* Configure interrupt enable register */
-	/* Enable CTS change interrupt */
-	val = MAX310X_IRQ_CTS_BIT;
-	/* Enable RX, TX interrupts */
-	val |= MAX310X_IRQ_RX | MAX310X_IRQ_TX;
-	regmap_write(s->regmap, MAX310X_IRQEN_REG, val);
-
-	mutex_unlock(&s->max310x_mutex);
+	/* Enable RX, TX, CTS change interrupts */
+	val = MAX310X_IRQ_RXEMPTY_BIT | MAX310X_IRQ_TXEMPTY_BIT;
+	max310x_port_write(port, MAX310X_IRQEN_REG, val | MAX310X_IRQ_CTS_BIT);
 
 	return 0;
 }
 
 static void max310x_shutdown(struct uart_port *port)
 {
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
+	struct max310x_port *s = dev_get_drvdata(port->dev);
 
 	/* Disable all interrupts */
-	mutex_lock(&s->max310x_mutex);
-	regmap_write(s->regmap, MAX310X_IRQEN_REG, 0);
-	mutex_unlock(&s->max310x_mutex);
+	max310x_port_write(port, MAX310X_IRQEN_REG, 0);
 
-	if (s->pdata->suspend)
-		s->pdata->suspend(1);
+	s->devtype->power(port, 0);
 }
 
 static const char *max310x_type(struct uart_port *port)
 {
-	struct max310x_port *s = container_of(port, struct max310x_port, port);
+	struct max310x_port *s = dev_get_drvdata(port->dev);
 
-	return (port->type == PORT_MAX310X) ? s->name : NULL;
+	return (port->type == PORT_MAX310X) ? s->devtype->name : NULL;
 }
 
 static int max310x_request_port(struct uart_port *port)
@@ -841,134 +951,99 @@ static int max310x_request_port(struct uart_port *port)
 	return 0;
 }
 
-static void max310x_release_port(struct uart_port *port)
-{
-	/* Do nothing */
-}
-
 static void max310x_config_port(struct uart_port *port, int flags)
 {
 	if (flags & UART_CONFIG_TYPE)
 		port->type = PORT_MAX310X;
 }
 
-static int max310x_verify_port(struct uart_port *port, struct serial_struct *ser)
+static int max310x_verify_port(struct uart_port *port, struct serial_struct *s)
 {
-	if ((ser->type == PORT_UNKNOWN) || (ser->type == PORT_MAX310X))
-		return 0;
-	if (ser->irq == port->irq)
-		return 0;
+	if ((s->type != PORT_UNKNOWN) && (s->type != PORT_MAX310X))
+		return -EINVAL;
+	if (s->irq != port->irq)
+		return -EINVAL;
 
-	return -EINVAL;
+	return 0;
 }
 
-static struct uart_ops max310x_ops = {
+static void max310x_null_void(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static const struct uart_ops max310x_ops = {
 	.tx_empty	= max310x_tx_empty,
 	.set_mctrl	= max310x_set_mctrl,
 	.get_mctrl	= max310x_get_mctrl,
-	.stop_tx	= max310x_stop_tx,
+	.stop_tx	= max310x_null_void,
 	.start_tx	= max310x_start_tx,
-	.stop_rx	= max310x_stop_rx,
-	.enable_ms	= max310x_enable_ms,
+	.stop_rx	= max310x_null_void,
+	.enable_ms	= max310x_null_void,
 	.break_ctl	= max310x_break_ctl,
 	.startup	= max310x_startup,
 	.shutdown	= max310x_shutdown,
 	.set_termios	= max310x_set_termios,
 	.type		= max310x_type,
 	.request_port	= max310x_request_port,
-	.release_port	= max310x_release_port,
+	.release_port	= max310x_null_void,
 	.config_port	= max310x_config_port,
 	.verify_port	= max310x_verify_port,
 };
 
-#ifdef CONFIG_PM_SLEEP
-
-static int max310x_suspend(struct device *dev)
+static int __maybe_unused max310x_suspend(struct device *dev)
 {
-	int ret;
 	struct max310x_port *s = dev_get_drvdata(dev);
+	int i;
 
-	dev_dbg(dev, "Suspend\n");
-
-	ret = uart_suspend_port(&s->uart, &s->port);
-
-	mutex_lock(&s->max310x_mutex);
-
-	/* Enable sleep mode */
-	regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
-			   MAX310X_MODE1_FORCESLEEP_BIT,
-			   MAX310X_MODE1_FORCESLEEP_BIT);
-
-	mutex_unlock(&s->max310x_mutex);
-
-	if (s->pdata->suspend)
-		s->pdata->suspend(1);
+	for (i = 0; i < s->uart.nr; i++) {
+		uart_suspend_port(&s->uart, &s->p[i].port);
+		s->devtype->power(&s->p[i].port, 0);
+	}
 
-	return ret;
+	return 0;
 }
 
-static int max310x_resume(struct device *dev)
+static int __maybe_unused max310x_resume(struct device *dev)
 {
 	struct max310x_port *s = dev_get_drvdata(dev);
+	int i;
 
-	dev_dbg(dev, "Resume\n");
-
-	if (s->pdata->suspend)
-		s->pdata->suspend(0);
-
-	mutex_lock(&s->max310x_mutex);
-
-	/* Disable sleep mode */
-	regmap_update_bits(s->regmap, MAX310X_MODE1_REG,
-			   MAX310X_MODE1_FORCESLEEP_BIT,
-			   0);
-
-	max310x_wait_pll(s);
-
-	mutex_unlock(&s->max310x_mutex);
+	for (i = 0; i < s->uart.nr; i++) {
+		s->devtype->power(&s->p[i].port, 1);
+		uart_resume_port(&s->uart, &s->p[i].port);
+	}
 
-	return uart_resume_port(&s->uart, &s->port);
+	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
-#define MAX310X_PM_OPS (&max310x_pm_ops)
-
-#else
-#define MAX310X_PM_OPS NULL
-#endif
-
 #ifdef CONFIG_GPIOLIB
 static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	unsigned int val = 0;
+	unsigned int val;
 	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+	struct uart_port *port = &s->p[offset / 4].port;
 
-	mutex_lock(&s->max310x_mutex);
-	regmap_read(s->regmap, MAX310X_GPIODATA_REG, &val);
-	mutex_unlock(&s->max310x_mutex);
+	val = max310x_port_read(port, MAX310X_GPIODATA_REG);
 
-	return !!((val >> 4) & (1 << offset));
+	return !!((val >> 4) & (1 << (offset % 4)));
 }
 
 static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+	struct uart_port *port = &s->p[offset / 4].port;
 
-	mutex_lock(&s->max310x_mutex);
-	regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ?
-							    1 << offset : 0);
-	mutex_unlock(&s->max310x_mutex);
+	max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4),
+			    value ? 1 << (offset % 4) : 0);
 }
 
 static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
 	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+	struct uart_port *port = &s->p[offset / 4].port;
 
-	mutex_lock(&s->max310x_mutex);
-
-	regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, 0);
-
-	mutex_unlock(&s->max310x_mutex);
+	max310x_port_update(port, MAX310X_GPIOCFG_REG, 1 << (offset % 4), 0);
 
 	return 0;
 }
@@ -977,74 +1052,42 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
 					 unsigned offset, int value)
 {
 	struct max310x_port *s = container_of(chip, struct max310x_port, gpio);
+	struct uart_port *port = &s->p[offset / 4].port;
 
-	mutex_lock(&s->max310x_mutex);
-
-	regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset,
-							   1 << offset);
-	regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ?
-							    1 << offset : 0);
-
-	mutex_unlock(&s->max310x_mutex);
+	max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4),
+			    value ? 1 << (offset % 4) : 0);
+	max310x_port_update(port, MAX310X_GPIOCFG_REG, 1 << (offset % 4),
+			    1 << (offset % 4));
 
 	return 0;
 }
 #endif
 
-/* Generic platform data */
-static struct max310x_pdata generic_plat_data = {
-	.driver_flags	= MAX310X_EXT_CLK,
-	.uart_flags[0]	= MAX310X_ECHO_SUPRESS,
-	.frequency	= 26000000,
-};
-
-static int max310x_probe(struct spi_device *spi)
+static int max310x_probe(struct device *dev, int is_spi,
+			 struct max310x_devtype *devtype, int irq)
 {
 	struct max310x_port *s;
-	struct device *dev = &spi->dev;
-	int chiptype = spi_get_device_id(spi)->driver_data;
-	struct max310x_pdata *pdata = dev->platform_data;
-	unsigned int val = 0;
-	int ret;
+	struct max310x_pdata *pdata = dev_get_platdata(dev);
+	int i, ret, uartclk;
 
 	/* Check for IRQ */
-	if (spi->irq <= 0) {
+	if (irq <= 0) {
 		dev_err(dev, "No IRQ specified\n");
 		return -ENOTSUPP;
 	}
 
+	if (!pdata) {
+		dev_err(dev, "No platform data supplied\n");
+		return -EINVAL;
+	}
+
 	/* Alloc port structure */
-	s = devm_kzalloc(dev, sizeof(struct max310x_port), GFP_KERNEL);
+	s = devm_kzalloc(dev, sizeof(*s) +
+			 sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL);
 	if (!s) {
 		dev_err(dev, "Error allocating port structure\n");
 		return -ENOMEM;
 	}
-	dev_set_drvdata(dev, s);
-
-	if (!pdata) {
-		dev_warn(dev, "No platform data supplied, using defaults\n");
-		pdata = &generic_plat_data;
-	}
-	s->pdata = pdata;
-
-	/* Individual chip settings */
-	switch (chiptype) {
-	case MAX310X_TYPE_MAX3107:
-		s->name = "MAX3107";
-		s->nr_gpio = 4;
-		s->uart.nr = 1;
-		s->regcfg.max_register = 0x1f;
-		break;
-	case MAX310X_TYPE_MAX3108:
-		s->name = "MAX3108";
-		s->nr_gpio = 4;
-		s->uart.nr = 1;
-		s->regcfg.max_register = 0x1e;
-		break;
-	default:
-		dev_err(dev, "Unsupported chip type %i\n", chiptype);
-		return -ENOTSUPP;
-	}
 
 	/* Check input frequency */
 	if ((pdata->driver_flags & MAX310X_EXT_CLK) &&
@@ -1055,13 +1098,11 @@ static int max310x_probe(struct spi_device *spi)
 	   ((pdata->frequency < 1000000) || (pdata->frequency > 4000000)))
 		goto err_freq;
 
-	mutex_init(&s->max310x_mutex);
+	s->pdata = pdata;
+	s->devtype = devtype;
+	dev_set_drvdata(dev, s);
 
-	/* Setup SPI bus */
-	spi->mode		= SPI_MODE_0;
-	spi->bits_per_word	= 8;
-	spi->max_speed_hz	= 26000000;
-	spi_setup(spi);
+	mutex_init(&s->mutex);
 
 	/* Setup regmap */
 	s->regcfg.reg_bits		= 8;
@@ -1069,109 +1110,100 @@ static int max310x_probe(struct spi_device *spi)
 	s->regcfg.read_flag_mask	= 0x00;
 	s->regcfg.write_flag_mask	= 0x80;
 	s->regcfg.cache_type		= REGCACHE_RBTREE;
-	s->regcfg.writeable_reg		= max3107_8_reg_writeable;
+	s->regcfg.writeable_reg		= max310x_reg_writeable;
 	s->regcfg.volatile_reg		= max310x_reg_volatile;
 	s->regcfg.precious_reg		= max310x_reg_precious;
-	s->regmap = devm_regmap_init_spi(spi, &s->regcfg);
+	s->regcfg.max_register		= devtype->nr * 0x20 - 1;
+
+	if (IS_ENABLED(CONFIG_SPI_MASTER) && is_spi) {
+		struct spi_device *spi = to_spi_device(dev);
+
+		s->regmap = devm_regmap_init_spi(spi, &s->regcfg);
+	} else
+		return -ENOTSUPP;
+
 	if (IS_ERR(s->regmap)) {
-		ret = PTR_ERR(s->regmap);
 		dev_err(dev, "Failed to initialize register map\n");
-		goto err_out;
-	}
-
-	/* Reset chip & check SPI function */
-	ret = regmap_write(s->regmap, MAX310X_MODE2_REG, MAX310X_MODE2_RST_BIT);
-	if (ret) {
-		dev_err(dev, "SPI transfer failed\n");
-		goto err_out;
-	}
-	/* Clear chip reset */
-	regmap_write(s->regmap, MAX310X_MODE2_REG, 0);
-
-	switch (chiptype) {
-	case MAX310X_TYPE_MAX3107:
-		/* Check REV ID to ensure we are talking to what we expect */
-		regmap_read(s->regmap, MAX3107_REVID_REG, &val);
-		if (((val & MAX3107_REV_MASK) != MAX3107_REV_ID)) {
-			dev_err(dev, "%s ID 0x%02x does not match\n",
-				s->name, val);
-			ret = -ENODEV;
-			goto err_out;
-		}
-		break;
-	case MAX310X_TYPE_MAX3108:
-		/* MAX3108 have not REV ID register, we just check default value
-		 * from clocksource register to make sure everything works.
-		 */
-		regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
-		if (val != (MAX310X_CLKSRC_EXTCLK_BIT |
-			    MAX310X_CLKSRC_PLLBYP_BIT)) {
-			dev_err(dev, "%s not present\n", s->name);
-			ret = -ENODEV;
-			goto err_out;
-		}
-		break;
+		return PTR_ERR(s->regmap);
 	}
 
 	/* Board specific configure */
-	if (pdata->init)
-		pdata->init();
-	if (pdata->suspend)
-		pdata->suspend(0);
-
-	/* Calculate referecne clock */
-	s->uartclk = max310x_set_ref_clk(s);
-
-	/* Disable all interrupts */
-	regmap_write(s->regmap, MAX310X_IRQEN_REG, 0);
-
-	/* Setup MODE1 register */
-	val = MAX310X_MODE1_IRQSEL_BIT; /* Enable IRQ pin */
-	if (pdata->driver_flags & MAX310X_AUTOSLEEP)
-		val = MAX310X_MODE1_AUTOSLEEP_BIT;
-	regmap_write(s->regmap, MAX310X_MODE1_REG, val);
-
-	/* Setup interrupt */
-	ret = devm_request_threaded_irq(dev, spi->irq, NULL, max310x_ist,
-					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-					dev_name(dev), s);
-	if (ret) {
-		dev_err(dev, "Unable to reguest IRQ %i\n", spi->irq);
-		goto err_out;
+	if (s->pdata->init)
+		s->pdata->init();
+
+	/* Check device to ensure we are talking to what we expect */
+	ret = devtype->detect(dev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < devtype->nr; i++) {
+		unsigned int offs = i << 5;
+
+		/* Reset port */
+		regmap_write(s->regmap, MAX310X_MODE2_REG + offs,
+			     MAX310X_MODE2_RST_BIT);
+		/* Clear port reset */
+		regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0);
+
+		/* Wait for port startup */
+		do {
+			regmap_read(s->regmap,
+				    MAX310X_BRGDIVLSB_REG + offs, &ret);
+		} while (ret != 0x01);
+
+		regmap_update_bits(s->regmap, MAX310X_MODE1_REG + offs,
+				   MAX310X_MODE1_AUTOSLEEP_BIT,
+				   MAX310X_MODE1_AUTOSLEEP_BIT);
 	}
 
+	uartclk = max310x_set_ref_clk(s);
+	dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
+
 	/* Register UART driver */
 	s->uart.owner		= THIS_MODULE;
-	s->uart.driver_name	= dev_name(dev);
 	s->uart.dev_name	= "ttyMAX";
 	s->uart.major		= MAX310X_MAJOR;
 	s->uart.minor		= MAX310X_MINOR;
+	s->uart.nr		= devtype->nr;
 	ret = uart_register_driver(&s->uart);
 	if (ret) {
 		dev_err(dev, "Registering UART driver failed\n");
-		goto err_out;
+		return ret;
 	}
 
-	/* Initialize workqueue for start TX */
-	s->wq = create_freezable_workqueue(dev_name(dev));
-	INIT_WORK(&s->tx_work, max310x_wq_proc);
-
-	/* Initialize UART port data */
-	s->port.line		= 0;
-	s->port.dev		= dev;
-	s->port.irq		= spi->irq;
-	s->port.type		= PORT_MAX310X;
-	s->port.fifosize	= MAX310X_FIFO_SIZE;
-	s->port.flags		= UPF_SKIP_TEST | UPF_FIXED_TYPE;
-	s->port.iotype		= UPIO_PORT;
-	s->port.membase		= (void __iomem *)0xffffffff; /* Bogus value */
-	s->port.uartclk		= s->uartclk;
-	s->port.ops		= &max310x_ops;
-	uart_add_one_port(&s->uart, &s->port);
+	for (i = 0; i < devtype->nr; i++) {
+		/* Initialize port data */
+		s->p[i].port.line	= i;
+		s->p[i].port.dev	= dev;
+		s->p[i].port.irq	= irq;
+		s->p[i].port.type	= PORT_MAX310X;
+		s->p[i].port.fifosize	= MAX310X_FIFO_SIZE;
+		s->p[i].port.flags	= UPF_SKIP_TEST | UPF_FIXED_TYPE |
+					  UPF_LOW_LATENCY;
+		s->p[i].port.iotype	= UPIO_PORT;
+		s->p[i].port.iobase	= i * 0x20;
+		s->p[i].port.membase	= (void __iomem *)~0;
+		s->p[i].port.uartclk	= uartclk;
+		s->p[i].port.ops	= &max310x_ops;
+		/* Disable all interrupts */
+		max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0);
+		/* Clear IRQ status register */
+		max310x_port_read(&s->p[i].port, MAX310X_IRQSTS_REG);
+		/* Enable IRQ pin */
+		max310x_port_update(&s->p[i].port, MAX310X_MODE1_REG,
+				    MAX310X_MODE1_IRQSEL_BIT,
+				    MAX310X_MODE1_IRQSEL_BIT);
+		/* Initialize queue for start TX */
+		INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
+		/* Register port */
+		uart_add_one_port(&s->uart, &s->p[i].port);
+		/* Go to suspend mode */
+		devtype->power(&s->p[i].port, 0);
+	}
 
 #ifdef CONFIG_GPIOLIB
 	/* Setup GPIO cotroller */
-	if (pdata->gpio_base) {
+	if (s->pdata->gpio_base) {
 		s->gpio.owner		= THIS_MODULE;
 		s->gpio.dev		= dev;
 		s->gpio.label		= dev_name(dev);
@@ -1179,86 +1211,107 @@ static int max310x_probe(struct spi_device *spi)
 		s->gpio.get		= max310x_gpio_get;
 		s->gpio.direction_output= max310x_gpio_direction_output;
 		s->gpio.set		= max310x_gpio_set;
-		s->gpio.base		= pdata->gpio_base;
-		s->gpio.ngpio		= s->nr_gpio;
+		s->gpio.base		= s->pdata->gpio_base;
+		s->gpio.ngpio		= devtype->nr * 4;
 		s->gpio.can_sleep	= 1;
-		if (gpiochip_add(&s->gpio)) {
-			/* Indicate that we should not call gpiochip_remove */
-			s->gpio.base = 0;
-		}
+		if (!gpiochip_add(&s->gpio))
+			s->gpio_used = 1;
 	} else
 		dev_info(dev, "GPIO support not enabled\n");
 #endif
 
-	/* Go to suspend mode */
-	if (pdata->suspend)
-		pdata->suspend(1);
+	/* Setup interrupt */
+	ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					dev_name(dev), s);
+	if (ret) {
+		dev_err(dev, "Unable to reguest IRQ %i\n", irq);
+#ifdef CONFIG_GPIOLIB
+		if (s->gpio_used)
+			WARN_ON(gpiochip_remove(&s->gpio));
+#endif
+	}
 
-	return 0;
+	return ret;
 
 err_freq:
 	dev_err(dev, "Frequency parameter incorrect\n");
-	ret = -EINVAL;
-
-err_out:
-	dev_set_drvdata(dev, NULL);
-
-	return ret;
+	return -EINVAL;
 }
 
-static int max310x_remove(struct spi_device *spi)
+static int max310x_remove(struct device *dev)
 {
-	struct device *dev = &spi->dev;
 	struct max310x_port *s = dev_get_drvdata(dev);
-	int ret = 0;
-
-	dev_dbg(dev, "Removing port\n");
-
-	devm_free_irq(dev, s->port.irq, s);
-
-	destroy_workqueue(s->wq);
+	int i, ret = 0;
 
-	uart_remove_one_port(&s->uart, &s->port);
+	for (i = 0; i < s->uart.nr; i++) {
+		cancel_work_sync(&s->p[i].tx_work);
+		uart_remove_one_port(&s->uart, &s->p[i].port);
+		s->devtype->power(&s->p[i].port, 0);
+	}
 
 	uart_unregister_driver(&s->uart);
 
 #ifdef CONFIG_GPIOLIB
-	if (s->pdata->gpio_base) {
+	if (s->gpio_used)
 		ret = gpiochip_remove(&s->gpio);
-		if (ret)
-			dev_err(dev, "Failed to remove gpio chip: %d\n", ret);
-	}
 #endif
 
-	dev_set_drvdata(dev, NULL);
-
-	if (s->pdata->suspend)
-		s->pdata->suspend(1);
 	if (s->pdata->exit)
 		s->pdata->exit();
 
 	return ret;
 }
 
+#ifdef CONFIG_SPI_MASTER
+static int max310x_spi_probe(struct spi_device *spi)
+{
+	struct max310x_devtype *devtype =
+		(struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
+	int ret;
+
+	/* Setup SPI bus */
+	spi->bits_per_word	= 8;
+	spi->mode		= spi->mode ? : SPI_MODE_0;
+	spi->max_speed_hz	= spi->max_speed_hz ? : 26000000;
+	ret = spi_setup(spi);
+	if (ret) {
+		dev_err(&spi->dev, "SPI setup failed\n");
+		return ret;
+	}
+
+	return max310x_probe(&spi->dev, 1, devtype, spi->irq);
+}
+
+static int max310x_spi_remove(struct spi_device *spi)
+{
+	return max310x_remove(&spi->dev);
+}
+
+static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
+
 static const struct spi_device_id max310x_id_table[] = {
-	{ "max3107",	MAX310X_TYPE_MAX3107 },
-	{ "max3108",	MAX310X_TYPE_MAX3108 },
+	{ "max3107",	(kernel_ulong_t)&max3107_devtype, },
+	{ "max3108",	(kernel_ulong_t)&max3108_devtype, },
+	{ "max3109",	(kernel_ulong_t)&max3109_devtype, },
+	{ "max14830",	(kernel_ulong_t)&max14830_devtype, },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, max310x_id_table);
 
-static struct spi_driver max310x_driver = {
+static struct spi_driver max310x_uart_driver = {
 	.driver = {
-		.name	= "max310x",
+		.name	= MAX310X_NAME,
 		.owner	= THIS_MODULE,
-		.pm	= MAX310X_PM_OPS,
+		.pm	= &max310x_pm_ops,
 	},
-	.probe		= max310x_probe,
-	.remove		= max310x_remove,
+	.probe		= max310x_spi_probe,
+	.remove		= max310x_spi_remove,
 	.id_table	= max310x_id_table,
 };
-module_spi_driver(max310x_driver);
+module_spi_driver(max310x_uart_driver);
+#endif
 
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
 MODULE_DESCRIPTION("MAX310X serial driver");
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 65be0c0..a2e97c9 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -24,6 +24,7 @@
 #include <linux/serial_core.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
+#include <linux/platform_device.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
@@ -644,7 +645,7 @@ static struct uart_driver mcf_driver = {
 
 static int mcf_probe(struct platform_device *pdev)
 {
-	struct mcf_platform_uart *platp = pdev->dev.platform_data;
+	struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev);
 	struct uart_port *port;
 	int i;
 
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index bc24f49..fba5257 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -1884,7 +1884,7 @@ static int mpsc_shared_drv_probe(struct platform_device *dev)
 	if (dev->id == 0) {
 		if (!(rc = mpsc_shared_map_regs(dev))) {
 			pdata = (struct mpsc_shared_pdata *)
-				dev->dev.platform_data;
+				dev_get_platdata(&dev->dev);
 
 			mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val;
 			mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val;
@@ -2025,7 +2025,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
 {
 	struct mpsc_pdata	*pdata;
 
-	pdata = (struct mpsc_pdata *)pd->dev.platform_data;
+	pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev);
 
 	pi->port.uartclk = pdata->brg_clk_freq;
 	pi->port.iotype = UPIO_MEM;
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 2c6cfb3..252d514 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -45,16 +45,19 @@ struct msm_port {
 	struct clk		*clk;
 	struct clk		*pclk;
 	unsigned int		imr;
-	unsigned int            *gsbi_base;
+	void __iomem		*gsbi_base;
 	int			is_uartdm;
 	unsigned int		old_snap_state;
 };
 
-static inline void wait_for_xmitr(struct uart_port *port, int bits)
+static inline void wait_for_xmitr(struct uart_port *port)
 {
-	if (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY))
-		while ((msm_read(port, UART_ISR) & bits) != bits)
-			cpu_relax();
+	while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
+		if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
+			break;
+		udelay(1);
+	}
+	msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR);
 }
 
 static void msm_stop_tx(struct uart_port *port)
@@ -192,49 +195,63 @@ static void handle_rx(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 }
 
-static void reset_dm_count(struct uart_port *port)
+static void reset_dm_count(struct uart_port *port, int count)
 {
-	wait_for_xmitr(port, UART_ISR_TX_READY);
-	msm_write(port, 1, UARTDM_NCF_TX);
+	wait_for_xmitr(port);
+	msm_write(port, count, UARTDM_NCF_TX);
+	msm_read(port, UARTDM_NCF_TX);
 }
 
 static void handle_tx(struct uart_port *port)
 {
 	struct circ_buf *xmit = &port->state->xmit;
 	struct msm_port *msm_port = UART_TO_MSM(port);
-	int sent_tx;
+	unsigned int tx_count, num_chars;
+	unsigned int tf_pointer = 0;
+
+	tx_count = uart_circ_chars_pending(xmit);
+	tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
+			port->fifosize);
 
 	if (port->x_char) {
 		if (msm_port->is_uartdm)
-			reset_dm_count(port);
+			reset_dm_count(port, tx_count + 1);
 
 		msm_write(port, port->x_char,
 			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 		port->icount.tx++;
 		port->x_char = 0;
+	} else if (tx_count && msm_port->is_uartdm) {
+		reset_dm_count(port, tx_count);
 	}
 
-	if (msm_port->is_uartdm)
-		reset_dm_count(port);
+	while (tf_pointer < tx_count) {
+		int i;
+		char buf[4] = { 0 };
+		unsigned int *bf = (unsigned int *)&buf;
 
-	while (msm_read(port, UART_SR) & UART_SR_TX_READY) {
-		if (uart_circ_empty(xmit)) {
-			/* disable tx interrupts */
-			msm_port->imr &= ~UART_IMR_TXLEV;
-			msm_write(port, msm_port->imr, UART_IMR);
+		if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 			break;
-		}
-		msm_write(port, xmit->buf[xmit->tail],
-			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 
 		if (msm_port->is_uartdm)
-			reset_dm_count(port);
+			num_chars = min(tx_count - tf_pointer, sizeof(buf));
+		else
+			num_chars = 1;
 
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		port->icount.tx++;
-		sent_tx = 1;
+		for (i = 0; i < num_chars; i++) {
+			buf[i] = xmit->buf[xmit->tail + i];
+			port->icount.tx++;
+		}
+
+		msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
+		xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
+		tf_pointer += num_chars;
 	}
 
+	/* disable tx interrupts if nothing more to send */
+	if (uart_circ_empty(xmit))
+		msm_stop_tx(port);
+
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
 }
@@ -295,7 +312,7 @@ static void msm_reset(struct uart_port *port)
 	msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
 }
 
-void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
+static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	unsigned int mr;
 	mr = msm_read(port, UART_MR1);
@@ -318,70 +335,60 @@ static void msm_break_ctl(struct uart_port *port, int break_ctl)
 		msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR);
 }
 
+struct msm_baud_map {
+	u16	divisor;
+	u8	code;
+	u8	rxstale;
+};
+
+static const struct msm_baud_map *
+msm_find_best_baud(struct uart_port *port, unsigned int baud)
+{
+	unsigned int i, divisor;
+	const struct msm_baud_map *entry;
+	static const struct msm_baud_map table[] = {
+		{ 1536, 0x00,  1 },
+		{  768, 0x11,  1 },
+		{  384, 0x22,  1 },
+		{  192, 0x33,  1 },
+		{   96, 0x44,  1 },
+		{   48, 0x55,  1 },
+		{   32, 0x66,  1 },
+		{   24, 0x77,  1 },
+		{   16, 0x88,  1 },
+		{   12, 0x99,  6 },
+		{    8, 0xaa,  6 },
+		{    6, 0xbb,  6 },
+		{    4, 0xcc,  6 },
+		{    3, 0xdd,  8 },
+		{    2, 0xee, 16 },
+		{    1, 0xff, 31 },
+	};
+
+	divisor = uart_get_divisor(port, baud);
+
+	for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++)
+		if (entry->divisor <= divisor)
+			break;
+
+	return entry; /* Default to smallest divider */
+}
+
 static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
 {
-	unsigned int baud_code, rxstale, watermark;
+	unsigned int rxstale, watermark;
 	struct msm_port *msm_port = UART_TO_MSM(port);
+	const struct msm_baud_map *entry;
 
-	switch (baud) {
-	case 300:
-		baud_code = UART_CSR_300;
-		rxstale = 1;
-		break;
-	case 600:
-		baud_code = UART_CSR_600;
-		rxstale = 1;
-		break;
-	case 1200:
-		baud_code = UART_CSR_1200;
-		rxstale = 1;
-		break;
-	case 2400:
-		baud_code = UART_CSR_2400;
-		rxstale = 1;
-		break;
-	case 4800:
-		baud_code = UART_CSR_4800;
-		rxstale = 1;
-		break;
-	case 9600:
-		baud_code = UART_CSR_9600;
-		rxstale = 2;
-		break;
-	case 14400:
-		baud_code = UART_CSR_14400;
-		rxstale = 3;
-		break;
-	case 19200:
-		baud_code = UART_CSR_19200;
-		rxstale = 4;
-		break;
-	case 28800:
-		baud_code = UART_CSR_28800;
-		rxstale = 6;
-		break;
-	case 38400:
-		baud_code = UART_CSR_38400;
-		rxstale = 8;
-		break;
-	case 57600:
-		baud_code = UART_CSR_57600;
-		rxstale = 16;
-		break;
-	case 115200:
-	default:
-		baud_code = UART_CSR_115200;
-		baud = 115200;
-		rxstale = 31;
-		break;
-	}
+	entry = msm_find_best_baud(port, baud);
 
 	if (msm_port->is_uartdm)
 		msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
 
-	msm_write(port, baud_code, UART_CSR);
+	msm_write(port, entry->code, UART_CSR);
 
 	/* RX stale watermark */
+	rxstale = entry->rxstale;
 	watermark = UART_IPR_STALE_LSB & rxstale;
 	watermark |= UART_IPR_RXSTALE_LAST;
 	watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
@@ -589,12 +596,10 @@ static void msm_release_port(struct uart_port *port)
 	port->membase = NULL;
 
 	if (msm_port->gsbi_base) {
-		iowrite32(GSBI_PROTOCOL_IDLE, msm_port->gsbi_base +
-			  GSBI_CONTROL);
-
-		gsbi_resource = platform_get_resource(pdev,
-							IORESOURCE_MEM, 1);
+		writel_relaxed(GSBI_PROTOCOL_IDLE,
+				msm_port->gsbi_base + GSBI_CONTROL);
 
+		gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		if (unlikely(!gsbi_resource))
 			return;
 
@@ -637,7 +642,7 @@ static int msm_request_port(struct uart_port *port)
 		if (!request_mem_region(gsbi_resource->start, size,
 						 "msm_serial")) {
 			ret = -EBUSY;
-			goto fail_release_port;
+			goto fail_release_port_membase;
 		}
 
 		msm_port->gsbi_base = ioremap(gsbi_resource->start, size);
@@ -651,6 +656,8 @@ static int msm_request_port(struct uart_port *port)
 
 fail_release_gsbi:
 	release_mem_region(gsbi_resource->start, size);
+fail_release_port_membase:
+	iounmap(port->membase);
 fail_release_port:
 	release_mem_region(port->mapbase, size);
 	return ret;
@@ -666,10 +673,9 @@ static void msm_config_port(struct uart_port *port, int flags)
 		if (ret)
 			return;
 	}
-
 	if (msm_port->is_uartdm)
-		iowrite32(GSBI_PROTOCOL_UART, msm_port->gsbi_base +
-			  GSBI_CONTROL);
+		writel_relaxed(GSBI_PROTOCOL_UART,
+				msm_port->gsbi_base + GSBI_CONTROL);
 }
 
 static int msm_verify_port(struct uart_port *port, struct serial_struct *ser)
@@ -766,7 +772,7 @@ static void msm_console_putchar(struct uart_port *port, int c)
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	if (msm_port->is_uartdm)
-		reset_dm_count(port);
+		reset_dm_count(port, 1);
 
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 		;
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index e4acef5..469fda5 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -38,19 +38,7 @@
 #define UART_MR2_PARITY_MODE_SPACE	0x3
 #define UART_MR2_PARITY_MODE		0x3
 
-#define UART_CSR	0x0008
-#define UART_CSR_115200	0xFF
-#define UART_CSR_57600	0xEE
-#define UART_CSR_38400	0xDD
-#define UART_CSR_28800	0xCC
-#define UART_CSR_19200	0xBB
-#define UART_CSR_14400	0xAA
-#define UART_CSR_9600	0x99
-#define UART_CSR_4800	0x77
-#define UART_CSR_2400	0x55
-#define UART_CSR_1200	0x44
-#define UART_CSR_600	0x33
-#define UART_CSR_300	0x22
+#define UART_CSR			0x0008
 
 #define UART_TF		0x000C
 #define UARTDM_TF	0x0070
@@ -71,6 +59,7 @@
 #define UART_CR_CMD_RESET_RFR		(14 << 4)
 #define UART_CR_CMD_PROTECTION_EN	(16 << 4)
 #define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
+#define UART_CR_CMD_RESET_TX_READY	(3 << 8)
 #define UART_CR_TX_DISABLE		(1 << 3)
 #define UART_CR_TX_ENABLE		(1 << 2)
 #define UART_CR_RX_DISABLE		(1 << 1)
@@ -151,6 +140,7 @@ static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
 	msm_write(port, 0xF1, UART_NREG);
 	msm_write(port, 0x0F, UART_DREG);
 	msm_write(port, 0x1A, UART_MNDREG);
+	port->uartclk = 1843200;
 }
 
 /*
@@ -162,6 +152,7 @@ static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
 	msm_write(port, 0xF6, UART_NREG);
 	msm_write(port, 0x0F, UART_DREG);
 	msm_write(port, 0x0A, UART_MNDREG);
+	port->uartclk = 1843200;
 }
 
 static inline
@@ -169,7 +160,7 @@ void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
 {
 	if (port->uartclk == 19200000)
 		msm_serial_set_mnd_regs_tcxo(port);
-	else
+	else if (port->uartclk == 4800000)
 		msm_serial_set_mnd_regs_tcxoby4(port);
 }
 
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4ca2f64..48e9496 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -1618,7 +1618,7 @@ static int msm_hs_probe(struct platform_device *pdev)
 	struct msm_hs_port *msm_uport;
 	struct resource *resource;
 	const struct msm_serial_hs_platform_data *pdata =
-						pdev->dev.platform_data;
+						dev_get_platdata(&pdev->dev);
 
 	if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
 		printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index f85b8e6..10e9d70 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -32,7 +32,6 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/of_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
@@ -134,10 +133,10 @@ enum mxs_auart_type {
 struct mxs_auart_port {
 	struct uart_port port;
 
-#define MXS_AUART_DMA_CONFIG	0x1
 #define MXS_AUART_DMA_ENABLED	0x2
 #define MXS_AUART_DMA_TX_SYNC	2  /* bit 2 */
 #define MXS_AUART_DMA_RX_READY	3  /* bit 3 */
+#define MXS_AUART_RTSCTS	4  /* bit 4 */
 	unsigned long flags;
 	unsigned int ctrl;
 	enum mxs_auart_type devtype;
@@ -640,7 +639,8 @@ static void mxs_auart_settermios(struct uart_port *u,
 		 * we can only implement the DMA support for auart
 		 * in mx28.
 		 */
-		if (is_imx28_auart(s) && (s->flags & MXS_AUART_DMA_CONFIG)) {
+		if (is_imx28_auart(s)
+				&& test_bit(MXS_AUART_RTSCTS, &s->flags)) {
 			if (!mxs_auart_dma_init(s))
 				/* enable DMA tranfer */
 				ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE
@@ -1008,7 +1008,8 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
 	}
 	s->port.line = ret;
 
-	s->flags |= MXS_AUART_DMA_CONFIG;
+	if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
+		set_bit(MXS_AUART_RTSCTS, &s->flags);
 
 	return 0;
 }
@@ -1021,7 +1022,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	u32 version;
 	int ret = 0;
 	struct resource *r;
-	struct pinctrl *pinctrl;
 
 	s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
 	if (!s) {
@@ -1035,12 +1035,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	else if (ret < 0)
 		goto out_free;
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto out_free;
-	}
-
 	if (of_id) {
 		pdev->id_entry = of_id->data;
 		s->devtype = pdev->id_entry->driver_data;
diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c
index b9a40ed..ce04f3f 100644
--- a/drivers/tty/serial/netx-serial.c
+++ b/drivers/tty/serial/netx-serial.c
@@ -693,8 +693,6 @@ static int serial_netx_remove(struct platform_device *pdev)
 {
 	struct netx_port *sport = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	if (sport)
 		uart_remove_one_port(&netx_reg, &sport->port);
 
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index b6d1728..c751706 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -40,7 +40,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/gpio.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/serial-omap.h>
 
 #define OMAP_MAX_HSUART_PORTS	6
@@ -52,6 +51,11 @@
 #define OMAP_UART_REV_52 0x0502
 #define OMAP_UART_REV_63 0x0603
 
+#define OMAP_UART_TX_WAKEUP_EN		BIT(7)
+
+/* Feature flags */
+#define OMAP_UART_WER_HAS_TX_WAKEUP	BIT(0)
+
 #define UART_ERRATA_i202_MDR1_ACCESS	BIT(0)
 #define UART_ERRATA_i291_DMA_FORCEIDLE	BIT(1)
 
@@ -137,6 +141,7 @@ struct uart_omap_port {
 	unsigned char		dlh;
 	unsigned char		mdr1;
 	unsigned char		scr;
+	unsigned char		wer;
 
 	int			use_dma;
 	/*
@@ -151,6 +156,7 @@ struct uart_omap_port {
 	int			context_loss_cnt;
 	u32			errata;
 	u8			wakeups_enabled;
+	u32			features;
 
 	int			DTR_gpio;
 	int			DTR_inverted;
@@ -160,7 +166,6 @@ struct uart_omap_port {
 	u32			latency;
 	u32			calc_latency;
 	struct work_struct	qos_work;
-	struct pinctrl		*pins;
 	bool			is_suspending;
 };
 
@@ -195,7 +200,7 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
 
 static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
 {
-	struct omap_uart_port_info *pdata = up->dev->platform_data;
+	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
 
 	if (!pdata || !pdata->get_context_loss_count)
 		return -EINVAL;
@@ -205,7 +210,7 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
 
 static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
 {
-	struct omap_uart_port_info *pdata = up->dev->platform_data;
+	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
 
 	if (!pdata || !pdata->enable_wakeup)
 		return;
@@ -310,7 +315,8 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
 		serial_omap_stop_tx(&up->port);
 		return;
 	}
-	count = up->port.fifosize / 4;
+	count = up->port.fifosize -
+		(serial_in(up, UART_OMAP_TXFIFO_LVL) & 0xFF);
 	do {
 		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -479,7 +485,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
 	struct uart_omap_port *up = dev_id;
 	unsigned int iir, lsr;
 	unsigned int type;
-	irqreturn_t ret = IRQ_NONE;
 	int max_count = 256;
 
 	spin_lock(&up->port.lock);
@@ -490,7 +495,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
 		if (iir & UART_IIR_NO_INT)
 			break;
 
-		ret = IRQ_HANDLED;
 		lsr = serial_in(up, UART_LSR);
 
 		/* extract IRQ type from IIR register */
@@ -529,7 +533,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
 	pm_runtime_put_autosuspend(up->dev);
 	up->port_activity = jiffies;
 
-	return ret;
+	return IRQ_HANDLED;
 }
 
 static unsigned int serial_omap_tx_empty(struct uart_port *port)
@@ -683,7 +687,11 @@ static int serial_omap_startup(struct uart_port *port)
 	serial_out(up, UART_IER, up->ier);
 
 	/* Enable module level wake up */
-	serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
+	up->wer = OMAP_UART_WER_MOD_WKUP;
+	if (up->features & OMAP_UART_WER_HAS_TX_WAKEUP)
+		up->wer |= OMAP_UART_TX_WAKEUP_EN;
+
+	serial_out(up, UART_OMAP_WER, up->wer);
 
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
@@ -1334,7 +1342,7 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
 	u32 mvr, scheme;
 	u16 revision, major, minor;
 
-	mvr = serial_in(up, UART_OMAP_MVER);
+	mvr = readl(up->port.membase + (UART_OMAP_MVER << up->port.regshift));
 
 	/* Check revision register scheme */
 	scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT;
@@ -1373,9 +1381,11 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
 	case OMAP_UART_REV_52:
 		up->errata |= (UART_ERRATA_i202_MDR1_ACCESS |
 				UART_ERRATA_i291_DMA_FORCEIDLE);
+		up->features |= OMAP_UART_WER_HAS_TX_WAKEUP;
 		break;
 	case OMAP_UART_REV_63:
 		up->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+		up->features |= OMAP_UART_WER_HAS_TX_WAKEUP;
 		break;
 	default:
 		break;
@@ -1399,11 +1409,13 @@ static int serial_omap_probe(struct platform_device *pdev)
 {
 	struct uart_omap_port	*up;
 	struct resource		*mem, *irq;
-	struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
+	struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev);
 	int ret;
 
-	if (pdev->dev.of_node)
+	if (pdev->dev.of_node) {
 		omap_up_info = of_get_uart_port_info(&pdev->dev);
+		pdev->dev.platform_data = omap_up_info;
+	}
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -1468,13 +1480,6 @@ static int serial_omap_probe(struct platform_device *pdev)
 		goto err_port_line;
 	}
 
-	up->pins = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(up->pins)) {
-		dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
-			 up->port.line, PTR_ERR(up->pins));
-		up->pins = NULL;
-	}
-
 	sprintf(up->name, "OMAP UART%d", up->port.line);
 	up->port.mapbase = mem->start;
 	up->port.membase = devm_ioremap(&pdev->dev, mem->start,
@@ -1501,7 +1506,6 @@ static int serial_omap_probe(struct platform_device *pdev)
 	INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
 
 	platform_set_drvdata(pdev, up);
-	pm_runtime_enable(&pdev->dev);
 	if (omap_up_info->autosuspend_timeout == 0)
 		omap_up_info->autosuspend_timeout = -1;
 	device_init_wakeup(up->dev, true);
@@ -1510,6 +1514,8 @@ static int serial_omap_probe(struct platform_device *pdev)
 			omap_up_info->autosuspend_timeout);
 
 	pm_runtime_irq_safe(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
 	pm_runtime_get_sync(&pdev->dev);
 
 	omap_serial_fill_features_erratas(up);
@@ -1609,6 +1615,7 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
 		serial_omap_mdr1_errataset(up, up->mdr1);
 	else
 		serial_out(up, UART_OMAP_MDR1, up->mdr1);
+	serial_out(up, UART_OMAP_WER, up->wer);
 }
 
 static int serial_omap_runtime_suspend(struct device *dev)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 572d481..5040c51 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -232,7 +232,7 @@ struct eg20t_port {
 	unsigned int iobase;
 	struct pci_dev *pdev;
 	int fifo_size;
-	int uartclk;
+	unsigned int uartclk;
 	int start_tx;
 	int start_rx;
 	int tx_empty;
@@ -373,35 +373,62 @@ static const struct file_operations port_regs_ops = {
 };
 #endif	/* CONFIG_DEBUG_FS */
 
+static struct dmi_system_id pch_uart_dmi_table[] = {
+	{
+		.ident = "CM-iTC",
+		{
+			DMI_MATCH(DMI_BOARD_NAME, "CM-iTC"),
+		},
+		(void *)CMITC_UARTCLK,
+	},
+	{
+		.ident = "FRI2",
+		{
+			DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
+		},
+		(void *)FRI2_64_UARTCLK,
+	},
+	{
+		.ident = "Fish River Island II",
+		{
+			DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
+		},
+		(void *)FRI2_48_UARTCLK,
+	},
+	{
+		.ident = "COMe-mTT",
+		{
+			DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
+		},
+		(void *)NTC1_UARTCLK,
+	},
+	{
+		.ident = "nanoETXexpress-TT",
+		{
+			DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
+		},
+		(void *)NTC1_UARTCLK,
+	},
+	{
+		.ident = "MinnowBoard",
+		{
+			DMI_MATCH(DMI_BOARD_NAME, "MinnowBoard"),
+		},
+		(void *)MINNOW_UARTCLK,
+	},
+};
+
 /* Return UART clock, checking for board specific clocks. */
-static int pch_uart_get_uartclk(void)
+static unsigned int pch_uart_get_uartclk(void)
 {
-	const char *cmp;
+	const struct dmi_system_id *d;
 
 	if (user_uartclk)
 		return user_uartclk;
 
-	cmp = dmi_get_system_info(DMI_BOARD_NAME);
-	if (cmp && strstr(cmp, "CM-iTC"))
-		return CMITC_UARTCLK;
-
-	cmp = dmi_get_system_info(DMI_BIOS_VERSION);
-	if (cmp && strnstr(cmp, "FRI2", 4))
-		return FRI2_64_UARTCLK;
-
-	cmp = dmi_get_system_info(DMI_PRODUCT_NAME);
-	if (cmp && strstr(cmp, "Fish River Island II"))
-		return FRI2_48_UARTCLK;
-
-	/* Kontron COMe-mTT10 (nanoETXexpress-TT) */
-	cmp = dmi_get_system_info(DMI_BOARD_NAME);
-	if (cmp && (strstr(cmp, "COMe-mTT") ||
-		    strstr(cmp, "nanoETXexpress-TT")))
-		return NTC1_UARTCLK;
-
-	cmp = dmi_get_system_info(DMI_BOARD_NAME);
-	if (cmp && strstr(cmp, "MinnowBoard"))
-		return MINNOW_UARTCLK;
+	d = dmi_first_match(pch_uart_dmi_table);
+	if (d)
+		return (unsigned long)d->driver_data;
 
 	return DEFAULT_UARTCLK;
 }
@@ -422,7 +449,7 @@ static void pch_uart_hal_disable_interrupt(struct eg20t_port *priv,
 	iowrite8(ier, priv->membase + UART_IER);
 }
 
-static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
+static int pch_uart_hal_set_line(struct eg20t_port *priv, unsigned int baud,
 				 unsigned int parity, unsigned int bits,
 				 unsigned int stb)
 {
@@ -457,7 +484,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
 	lcr |= bits;
 	lcr |= stb;
 
-	dev_dbg(priv->port.dev, "%s:baud = %d, div = %04x, lcr = %02x (%lu)\n",
+	dev_dbg(priv->port.dev, "%s:baud = %u, div = %04x, lcr = %02x (%lu)\n",
 		 __func__, baud, div, lcr, jiffies);
 	iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
 	iowrite8(dll, priv->membase + PCH_UART_DLL);
@@ -1363,9 +1390,8 @@ static void pch_uart_shutdown(struct uart_port *port)
 static void pch_uart_set_termios(struct uart_port *port,
 				 struct ktermios *termios, struct ktermios *old)
 {
-	int baud;
 	int rtn;
-	unsigned int parity, bits, stb;
+	unsigned int baud, parity, bits, stb;
 	struct eg20t_port *priv;
 	unsigned long flags;
 
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index b1785f5..f87f1a0 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1798,7 +1798,6 @@ static int __exit pmz_detach(struct platform_device *pdev)
 
 	uart_remove_one_port(&pmz_uart_reg, &uap->port);
 
-	platform_set_drvdata(pdev, NULL);
 	uap->port.dev = NULL;
 
 	return 0;
diff --git a/drivers/tty/serial/pnx8xxx_uart.c b/drivers/tty/serial/pnx8xxx_uart.c
index 7e277a5..b6b7aca 100644
--- a/drivers/tty/serial/pnx8xxx_uart.c
+++ b/drivers/tty/serial/pnx8xxx_uart.c
@@ -801,8 +801,6 @@ static int pnx8xxx_serial_remove(struct platform_device *pdev)
 {
 	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	if (sport)
 		uart_remove_one_port(&pnx8xxx_reg, &sport->port);
 
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 05f504e..ac8b2f5 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -945,8 +945,6 @@ static int serial_pxa_remove(struct platform_device *dev)
 {
 	struct uart_pxa_port *sport = platform_get_drvdata(dev);
 
-	platform_set_drvdata(dev, NULL);
-
 	uart_remove_one_port(&serial_pxa_reg, &sport->port);
 
 	clk_unprepare(sport->clk);
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index af6b3e3..fc23ea19 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -864,8 +864,6 @@ static int sa1100_serial_remove(struct platform_device *pdev)
 {
 	struct sa1100_port *sport = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
-
 	if (sport)
 		uart_remove_one_port(&sa1100_reg, &sport->port);
 
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 376079b..019b915 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1250,8 +1250,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 
 	ourport->baudclk = ERR_PTR(-EINVAL);
 	ourport->info = ourport->drv_data->info;
-	ourport->cfg = (pdev->dev.platform_data) ?
-			(struct s3c2410_uartcfg *)pdev->dev.platform_data :
+	ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
+			(struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) :
 			ourport->drv_data->def_cfg;
 
 	ourport->port.fifosize = (ourport->info->fifosize) ?
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
index 4b1434d..887b4f7 100644
--- a/drivers/tty/serial/sc26xx.c
+++ b/drivers/tty/serial/sc26xx.c
@@ -637,7 +637,7 @@ static int sc26xx_probe(struct platform_device *dev)
 {
 	struct resource *res;
 	struct uart_sc26xx_port *up;
-	unsigned int *sc26xx_data = dev->dev.platform_data;
+	unsigned int *sc26xx_data = dev_get_platdata(&dev->dev);
 	int err;
 
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index c773041..49e9bbf 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -15,6 +15,7 @@
 #define SUPPORT_SYSRQ
 #endif
 
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -94,16 +95,17 @@
 #define MCTRL_IBIT(cfg, sig)		((((cfg) >> (sig)) & 0xf) - LINE_IP0)
 #define MCTRL_OBIT(cfg, sig)		((((cfg) >> (sig)) & 0xf) - LINE_OP0)
 
-/* Supported chip types */
-enum {
-	SCCNXP_TYPE_SC2681	= 2681,
-	SCCNXP_TYPE_SC2691	= 2691,
-	SCCNXP_TYPE_SC2692	= 2692,
-	SCCNXP_TYPE_SC2891	= 2891,
-	SCCNXP_TYPE_SC2892	= 2892,
-	SCCNXP_TYPE_SC28202	= 28202,
-	SCCNXP_TYPE_SC68681	= 68681,
-	SCCNXP_TYPE_SC68692	= 68692,
+#define SCCNXP_HAVE_IO		0x00000001
+#define SCCNXP_HAVE_MR0		0x00000002
+
+struct sccnxp_chip {
+	const char		*name;
+	unsigned int		nr;
+	unsigned long		freq_min;
+	unsigned long		freq_std;
+	unsigned long		freq_max;
+	unsigned int		flags;
+	unsigned int		fifosize;
 };
 
 struct sccnxp_port {
@@ -111,16 +113,10 @@ struct sccnxp_port {
 	struct uart_port	port[SCCNXP_MAX_UARTS];
 	bool			opened[SCCNXP_MAX_UARTS];
 
-	const char		*name;
 	int			irq;
-
 	u8			imr;
-	u8			addr_mask;
-	int			freq_std;
 
-	int			flags;
-#define SCCNXP_HAVE_IO		0x00000001
-#define SCCNXP_HAVE_MR0		0x00000002
+	struct sccnxp_chip	*chip;
 
 #ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
 	struct console		console;
@@ -136,29 +132,94 @@ struct sccnxp_port {
 	struct regulator	*regulator;
 };
 
-static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
-{
-	return readb(base + (reg << shift));
-}
+static const struct sccnxp_chip sc2681 = {
+	.name		= "SC2681",
+	.nr		= 2,
+	.freq_min	= 1000000,
+	.freq_std	= 3686400,
+	.freq_max	= 4000000,
+	.flags		= SCCNXP_HAVE_IO,
+	.fifosize	= 3,
+};
 
-static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v)
-{
-	writeb(v, base + (reg << shift));
-}
+static const struct sccnxp_chip sc2691 = {
+	.name		= "SC2691",
+	.nr		= 1,
+	.freq_min	= 1000000,
+	.freq_std	= 3686400,
+	.freq_max	= 4000000,
+	.flags		= 0,
+	.fifosize	= 3,
+};
+
+static const struct sccnxp_chip sc2692 = {
+	.name		= "SC2692",
+	.nr		= 2,
+	.freq_min	= 1000000,
+	.freq_std	= 3686400,
+	.freq_max	= 4000000,
+	.flags		= SCCNXP_HAVE_IO,
+	.fifosize	= 3,
+};
+
+static const struct sccnxp_chip sc2891 = {
+	.name		= "SC2891",
+	.nr		= 1,
+	.freq_min	= 100000,
+	.freq_std	= 3686400,
+	.freq_max	= 8000000,
+	.flags		= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
+	.fifosize	= 16,
+};
+
+static const struct sccnxp_chip sc2892 = {
+	.name		= "SC2892",
+	.nr		= 2,
+	.freq_min	= 100000,
+	.freq_std	= 3686400,
+	.freq_max	= 8000000,
+	.flags		= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
+	.fifosize	= 16,
+};
+
+static const struct sccnxp_chip sc28202 = {
+	.name		= "SC28202",
+	.nr		= 2,
+	.freq_min	= 1000000,
+	.freq_std	= 14745600,
+	.freq_max	= 50000000,
+	.flags		= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
+	.fifosize	= 256,
+};
+
+static const struct sccnxp_chip sc68681 = {
+	.name		= "SC68681",
+	.nr		= 2,
+	.freq_min	= 1000000,
+	.freq_std	= 3686400,
+	.freq_max	= 4000000,
+	.flags		= SCCNXP_HAVE_IO,
+	.fifosize	= 3,
+};
+
+static const struct sccnxp_chip sc68692 = {
+	.name		= "SC68692",
+	.nr		= 2,
+	.freq_min	= 1000000,
+	.freq_std	= 3686400,
+	.freq_max	= 4000000,
+	.flags		= SCCNXP_HAVE_IO,
+	.fifosize	= 3,
+};
 
 static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
 {
-	struct sccnxp_port *s = dev_get_drvdata(port->dev);
-
-	return sccnxp_raw_read(port->membase, reg & s->addr_mask,
-			       port->regshift);
+	return readb(port->membase + (reg << port->regshift));
 }
 
 static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
 {
-	struct sccnxp_port *s = dev_get_drvdata(port->dev);
-
-	sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v);
+	writeb(v, port->membase + (reg << port->regshift));
 }
 
 static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
@@ -224,13 +285,14 @@ static int sccnxp_set_baud(struct uart_port *port, int baud)
 {
 	struct sccnxp_port *s = dev_get_drvdata(port->dev);
 	int div_std, tmp_baud, bestbaud = baud, besterr = -1;
+	struct sccnxp_chip *chip = s->chip;
 	u8 i, acr = 0, csr = 0, mr0 = 0;
 
 	/* Find best baud from table */
 	for (i = 0; baud_std[i].baud && besterr; i++) {
-		if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0))
+		if (baud_std[i].mr0 && !(chip->flags & SCCNXP_HAVE_MR0))
 			continue;
-		div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud);
+		div_std = DIV_ROUND_CLOSEST(chip->freq_std, baud_std[i].baud);
 		tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std);
 		if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) {
 			acr = baud_std[i].acr;
@@ -240,7 +302,7 @@ static int sccnxp_set_baud(struct uart_port *port, int baud)
 		}
 	}
 
-	if (s->flags & SCCNXP_HAVE_MR0) {
+	if (chip->flags & SCCNXP_HAVE_MR0) {
 		/* Enable FIFO, set half level for TX */
 		mr0 |= MR0_FIFO | MR0_TXLVL;
 		/* Update MR0 */
@@ -363,7 +425,7 @@ static void sccnxp_handle_tx(struct uart_port *port)
 			sccnxp_disable_irq(port, IMR_TXRDY);
 
 			/* Set direction to input */
-			if (s->flags & SCCNXP_HAVE_IO)
+			if (s->chip->flags & SCCNXP_HAVE_IO)
 				sccnxp_set_bit(port, DIR_OP, 0);
 		}
 		return;
@@ -437,7 +499,7 @@ static void sccnxp_start_tx(struct uart_port *port)
 	spin_lock_irqsave(&s->lock, flags);
 
 	/* Set direction to output */
-	if (s->flags & SCCNXP_HAVE_IO)
+	if (s->chip->flags & SCCNXP_HAVE_IO)
 		sccnxp_set_bit(port, DIR_OP, 1);
 
 	sccnxp_enable_irq(port, IMR_TXRDY);
@@ -483,7 +545,7 @@ static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	struct sccnxp_port *s = dev_get_drvdata(port->dev);
 	unsigned long flags;
 
-	if (!(s->flags & SCCNXP_HAVE_IO))
+	if (!(s->chip->flags & SCCNXP_HAVE_IO))
 		return;
 
 	spin_lock_irqsave(&s->lock, flags);
@@ -501,7 +563,7 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port)
 	struct sccnxp_port *s = dev_get_drvdata(port->dev);
 	unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
 
-	if (!(s->flags & SCCNXP_HAVE_IO))
+	if (!(s->chip->flags & SCCNXP_HAVE_IO))
 		return mctrl;
 
 	spin_lock_irqsave(&s->lock, flags);
@@ -617,7 +679,7 @@ static void sccnxp_set_termios(struct uart_port *port,
 
 	/* Setup baudrate */
 	baud = uart_get_baud_rate(port, termios, old, 50,
-				  (s->flags & SCCNXP_HAVE_MR0) ?
+				  (s->chip->flags & SCCNXP_HAVE_MR0) ?
 				  230400 : 38400);
 	baud = sccnxp_set_baud(port, baud);
 
@@ -641,7 +703,7 @@ static int sccnxp_startup(struct uart_port *port)
 
 	spin_lock_irqsave(&s->lock, flags);
 
-	if (s->flags & SCCNXP_HAVE_IO) {
+	if (s->chip->flags & SCCNXP_HAVE_IO) {
 		/* Outputs are controlled manually */
 		sccnxp_write(port, SCCNXP_OPCR_REG, 0);
 	}
@@ -681,7 +743,7 @@ static void sccnxp_shutdown(struct uart_port *port)
 	sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE);
 
 	/* Leave direction to input */
-	if (s->flags & SCCNXP_HAVE_IO)
+	if (s->chip->flags & SCCNXP_HAVE_IO)
 		sccnxp_set_bit(port, DIR_OP, 0);
 
 	spin_unlock_irqrestore(&s->lock, flags);
@@ -691,7 +753,7 @@ static const char *sccnxp_type(struct uart_port *port)
 {
 	struct sccnxp_port *s = dev_get_drvdata(port->dev);
 
-	return (port->type == PORT_SC26XX) ? s->name : NULL;
+	return (port->type == PORT_SC26XX) ? s->chip->name : NULL;
 }
 
 static void sccnxp_release_port(struct uart_port *port)
@@ -778,19 +840,31 @@ static int sccnxp_console_setup(struct console *co, char *options)
 }
 #endif
 
+static const struct platform_device_id sccnxp_id_table[] = {
+	{ .name = "sc2681",	.driver_data = (kernel_ulong_t)&sc2681, },
+	{ .name = "sc2691",	.driver_data = (kernel_ulong_t)&sc2691, },
+	{ .name = "sc2692",	.driver_data = (kernel_ulong_t)&sc2692, },
+	{ .name = "sc2891",	.driver_data = (kernel_ulong_t)&sc2891, },
+	{ .name = "sc2892",	.driver_data = (kernel_ulong_t)&sc2892, },
+	{ .name = "sc28202",	.driver_data = (kernel_ulong_t)&sc28202, },
+	{ .name = "sc68681",	.driver_data = (kernel_ulong_t)&sc68681, },
+	{ .name = "sc68692",	.driver_data = (kernel_ulong_t)&sc68692, },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
+
 static int sccnxp_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	int chiptype = pdev->id_entry->driver_data;
 	struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev);
-	int i, ret, fifosize, freq_min, freq_max;
+	int i, ret, uartclk;
 	struct sccnxp_port *s;
 	void __iomem *membase;
+	struct clk *clk;
 
-	if (!res) {
-		dev_err(&pdev->dev, "Missing memory resource data\n");
-		return -EADDRNOTAVAIL;
-	}
+	membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(membase))
+		return PTR_ERR(membase);
 
 	s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
 	if (!s) {
@@ -801,99 +875,38 @@ static int sccnxp_probe(struct platform_device *pdev)
 
 	spin_lock_init(&s->lock);
 
-	/* Individual chip settings */
-	switch (chiptype) {
-	case SCCNXP_TYPE_SC2681:
-		s->name		= "SC2681";
-		s->uart.nr	= 2;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x0f;
-		s->flags	= SCCNXP_HAVE_IO;
-		fifosize	= 3;
-		freq_min	= 1000000;
-		freq_max	= 4000000;
-		break;
-	case SCCNXP_TYPE_SC2691:
-		s->name		= "SC2691";
-		s->uart.nr	= 1;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x07;
-		s->flags	= 0;
-		fifosize	= 3;
-		freq_min	= 1000000;
-		freq_max	= 4000000;
-		break;
-	case SCCNXP_TYPE_SC2692:
-		s->name		= "SC2692";
-		s->uart.nr	= 2;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x0f;
-		s->flags	= SCCNXP_HAVE_IO;
-		fifosize	= 3;
-		freq_min	= 1000000;
-		freq_max	= 4000000;
-		break;
-	case SCCNXP_TYPE_SC2891:
-		s->name		= "SC2891";
-		s->uart.nr	= 1;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x0f;
-		s->flags	= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
-		fifosize	= 16;
-		freq_min	= 100000;
-		freq_max	= 8000000;
-		break;
-	case SCCNXP_TYPE_SC2892:
-		s->name		= "SC2892";
-		s->uart.nr	= 2;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x0f;
-		s->flags	= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
-		fifosize	= 16;
-		freq_min	= 100000;
-		freq_max	= 8000000;
-		break;
-	case SCCNXP_TYPE_SC28202:
-		s->name		= "SC28202";
-		s->uart.nr	= 2;
-		s->freq_std	= 14745600;
-		s->addr_mask	= 0x7f;
-		s->flags	= SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
-		fifosize	= 256;
-		freq_min	= 1000000;
-		freq_max	= 50000000;
-		break;
-	case SCCNXP_TYPE_SC68681:
-		s->name		= "SC68681";
-		s->uart.nr	= 2;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x0f;
-		s->flags	= SCCNXP_HAVE_IO;
-		fifosize	= 3;
-		freq_min	= 1000000;
-		freq_max	= 4000000;
-		break;
-	case SCCNXP_TYPE_SC68692:
-		s->name		= "SC68692";
-		s->uart.nr	= 2;
-		s->freq_std	= 3686400;
-		s->addr_mask	= 0x0f;
-		s->flags	= SCCNXP_HAVE_IO;
-		fifosize	= 3;
-		freq_min	= 1000000;
-		freq_max	= 4000000;
-		break;
-	default:
-		dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype);
-		ret = -ENOTSUPP;
+	s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data;
+
+	s->regulator = devm_regulator_get(&pdev->dev, "vcc");
+	if (!IS_ERR(s->regulator)) {
+		ret = regulator_enable(s->regulator);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to enable regulator: %i\n", ret);
+			return ret;
+		}
+	} else if (PTR_ERR(s->regulator) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto err_out;
+		}
+		dev_notice(&pdev->dev, "Using default clock frequency\n");
+		uartclk = s->chip->freq_std;
+	} else
+		uartclk = clk_get_rate(clk);
+
+	/* Check input frequency */
+	if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) {
+		dev_err(&pdev->dev, "Frequency out of bounds\n");
+		ret = -EINVAL;
 		goto err_out;
 	}
 
-	if (!pdata) {
-		dev_warn(&pdev->dev,
-			 "No platform data supplied, using defaults\n");
-		s->pdata.frequency = s->freq_std;
-	} else
+	if (pdata)
 		memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
 
 	if (s->pdata.poll_time_us) {
@@ -911,34 +924,11 @@ static int sccnxp_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* Check input frequency */
-	if ((s->pdata.frequency < freq_min) ||
-	    (s->pdata.frequency > freq_max)) {
-		dev_err(&pdev->dev, "Frequency out of bounds\n");
-		ret = -EINVAL;
-		goto err_out;
-	}
-
-	s->regulator = devm_regulator_get(&pdev->dev, "VCC");
-	if (!IS_ERR(s->regulator)) {
-		ret = regulator_enable(s->regulator);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Failed to enable regulator: %i\n", ret);
-			return ret;
-		}
-	}
-
-	membase = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(membase)) {
-		ret = PTR_ERR(membase);
-		goto err_out;
-	}
-
 	s->uart.owner		= THIS_MODULE;
 	s->uart.dev_name	= "ttySC";
 	s->uart.major		= SCCNXP_MAJOR;
 	s->uart.minor		= SCCNXP_MINOR;
+	s->uart.nr		= s->chip->nr;
 #ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
 	s->uart.cons		= &s->console;
 	s->uart.cons->device	= uart_console_device;
@@ -960,17 +950,17 @@ static int sccnxp_probe(struct platform_device *pdev)
 		s->port[i].dev		= &pdev->dev;
 		s->port[i].irq		= s->irq;
 		s->port[i].type		= PORT_SC26XX;
-		s->port[i].fifosize	= fifosize;
+		s->port[i].fifosize	= s->chip->fifosize;
 		s->port[i].flags	= UPF_SKIP_TEST | UPF_FIXED_TYPE;
 		s->port[i].iotype	= UPIO_MEM;
 		s->port[i].mapbase	= res->start;
 		s->port[i].membase	= membase;
 		s->port[i].regshift	= s->pdata.reg_shift;
-		s->port[i].uartclk	= s->pdata.frequency;
+		s->port[i].uartclk	= uartclk;
 		s->port[i].ops		= &sccnxp_ops;
 		uart_add_one_port(&s->uart, &s->port[i]);
 		/* Set direction to input */
-		if (s->flags & SCCNXP_HAVE_IO)
+		if (s->chip->flags & SCCNXP_HAVE_IO)
 			sccnxp_set_bit(&s->port[i], DIR_OP, 0);
 	}
 
@@ -997,7 +987,8 @@ static int sccnxp_probe(struct platform_device *pdev)
 	}
 
 err_out:
-	platform_set_drvdata(pdev, NULL);
+	if (!IS_ERR(s->regulator))
+		return regulator_disable(s->regulator);
 
 	return ret;
 }
@@ -1016,7 +1007,6 @@ static int sccnxp_remove(struct platform_device *pdev)
 		uart_remove_one_port(&s->uart, &s->port[i]);
 
 	uart_unregister_driver(&s->uart);
-	platform_set_drvdata(pdev, NULL);
 
 	if (!IS_ERR(s->regulator))
 		return regulator_disable(s->regulator);
@@ -1024,19 +1014,6 @@ static int sccnxp_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct platform_device_id sccnxp_id_table[] = {
-	{ "sc2681",	SCCNXP_TYPE_SC2681 },
-	{ "sc2691",	SCCNXP_TYPE_SC2691 },
-	{ "sc2692",	SCCNXP_TYPE_SC2692 },
-	{ "sc2891",	SCCNXP_TYPE_SC2891 },
-	{ "sc2892",	SCCNXP_TYPE_SC2892 },
-	{ "sc28202",	SCCNXP_TYPE_SC28202 },
-	{ "sc68681",	SCCNXP_TYPE_SC68681 },
-	{ "sc68692",	SCCNXP_TYPE_SC68692 },
-	{ },
-};
-MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
-
 static struct platform_driver sccnxp_uart_driver = {
 	.driver = {
 		.name	= SCCNXP_NAME,
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 28cdd28..0f02351 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2095,12 +2095,12 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
 		break;
 	}
 
-	printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
+	printk(KERN_INFO "%s%s%s%d at %s (irq = %d, base_baud = %d) is a %s\n",
 	       port->dev ? dev_name(port->dev) : "",
 	       port->dev ? ": " : "",
 	       drv->dev_name,
 	       drv->tty_driver->name_base + port->line,
-	       address, port->irq, uart_type(port));
+	       address, port->irq, port->uartclk / 16, uart_type(port));
 }
 
 static void
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index fe48a0c..440a962 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1097,7 +1097,7 @@ static void serial_txx9_unregister_port(int line)
  */
 static int serial_txx9_probe(struct platform_device *dev)
 {
-	struct uart_port *p = dev->dev.platform_data;
+	struct uart_port *p = dev_get_platdata(&dev->dev);
 	struct uart_port port;
 	int ret, i;
 
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 7477e0e..d262c1f 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -52,6 +52,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #ifdef CONFIG_SUPERH
 #include <asm/sh_bios.h>
@@ -2380,7 +2381,7 @@ static char early_serial_buf[32];
 
 static int sci_probe_earlyprintk(struct platform_device *pdev)
 {
-	struct plat_sci_port *cfg = pdev->dev.platform_data;
+	struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev);
 
 	if (early_serial_console.data)
 		return -EEXIST;
@@ -2437,6 +2438,112 @@ static int sci_remove(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_sci_match[] = {
+	{ .compatible = "renesas,sci-SCI-uart",
+		.data = (void *)PORT_SCI },
+	{ .compatible = "renesas,sci-SCIF-uart",
+		.data = (void *)PORT_SCIF },
+	{ .compatible = "renesas,sci-IRDA-uart",
+		.data = (void *)PORT_IRDA },
+	{ .compatible = "renesas,sci-SCIFA-uart",
+		.data = (void *)PORT_SCIFA },
+	{ .compatible = "renesas,sci-SCIFB-uart",
+		.data = (void *)PORT_SCIFB },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_sci_match);
+
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+								int *dev_id)
+{
+	struct plat_sci_port *p;
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match;
+	struct resource *res;
+	const __be32 *prop;
+	int i, irq, val;
+
+	match = of_match_node(of_sci_match, pdev->dev.of_node);
+	if (!match || !match->data) {
+		dev_err(&pdev->dev, "OF match error\n");
+		return NULL;
+	}
+
+	p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "failed to allocate DT config data\n");
+		return NULL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		return NULL;
+	}
+	p->mapbase = res->start;
+
+	for (i = 0; i < SCIx_NR_IRQS; i++) {
+		irq = platform_get_irq(pdev, i);
+		if (irq < 0) {
+			dev_err(&pdev->dev, "failed to get irq data %d\n", i);
+			return NULL;
+		}
+		p->irqs[i] = irq;
+	}
+
+	prop = of_get_property(np, "cell-index", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "required DT prop cell-index missing\n");
+		return NULL;
+	}
+	*dev_id = be32_to_cpup(prop);
+
+	prop = of_get_property(np, "renesas,scscr", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "required DT prop scscr missing\n");
+		return NULL;
+	}
+	p->scscr = be32_to_cpup(prop);
+
+	prop = of_get_property(np, "renesas,scbrr-algo-id", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "required DT prop scbrr-algo-id missing\n");
+		return NULL;
+	}
+	val = be32_to_cpup(prop);
+	if (val <= SCBRR_ALGO_INVALID || val >= SCBRR_NR_ALGOS) {
+		dev_err(&pdev->dev, "DT prop scbrr-algo-id out of range\n");
+		return NULL;
+	}
+	p->scbrr_algo_id = val;
+
+	p->flags = UPF_IOREMAP;
+	if (of_get_property(np, "renesas,autoconf", NULL))
+		p->flags |= UPF_BOOT_AUTOCONF;
+
+	prop = of_get_property(np, "renesas,regtype", NULL);
+	if (prop) {
+		val = be32_to_cpup(prop);
+		if (val < SCIx_PROBE_REGTYPE || val >= SCIx_NR_REGTYPES) {
+			dev_err(&pdev->dev, "DT prop regtype out of range\n");
+			return NULL;
+		}
+		p->regtype = val;
+	}
+
+	p->type = (unsigned int)match->data;
+
+	return p;
+}
+#else
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+								int *dev_id)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int sci_probe_single(struct platform_device *dev,
 				      unsigned int index,
 				      struct plat_sci_port *p,
@@ -2469,9 +2576,9 @@ static int sci_probe_single(struct platform_device *dev,
 
 static int sci_probe(struct platform_device *dev)
 {
-	struct plat_sci_port *p = dev->dev.platform_data;
-	struct sci_port *sp = &sci_ports[dev->id];
-	int ret;
+	struct plat_sci_port *p;
+	struct sci_port *sp;
+	int ret, dev_id = dev->id;
 
 	/*
 	 * If we've come here via earlyprintk initialization, head off to
@@ -2481,9 +2588,20 @@ static int sci_probe(struct platform_device *dev)
 	if (is_early_platform_device(dev))
 		return sci_probe_earlyprintk(dev);
 
+	if (dev->dev.of_node)
+		p = sci_parse_dt(dev, &dev_id);
+	else
+		p = dev_get_platdata(&dev->dev);
+
+	if (!p) {
+		dev_err(&dev->dev, "no setup data supplied\n");
+		return -EINVAL;
+	}
+
+	sp = &sci_ports[dev_id];
 	platform_set_drvdata(dev, sp);
 
-	ret = sci_probe_single(dev, dev->id, p, sp);
+	ret = sci_probe_single(dev, dev_id, p, sp);
 	if (ret)
 		return ret;
 
@@ -2535,6 +2653,7 @@ static struct platform_driver sci_driver = {
 		.name	= "sh-sci",
 		.owner	= THIS_MODULE,
 		.pm	= &sci_dev_pm_ops,
+		.of_match_table = of_match_ptr(of_sci_match),
 	},
 };
 
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index 1fd564b..67a0d1b 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -717,7 +717,6 @@ port_err:
 	clk_disable_unprepare(sirfport->clk);
 	clk_put(sirfport->clk);
 clk_err:
-	platform_set_drvdata(pdev, NULL);
 	if (sirfport->hw_flow_ctrl)
 		pinctrl_put(sirfport->p);
 err:
@@ -728,7 +727,7 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
 {
 	struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev);
 	struct uart_port *port = &sirfport->port;
-	platform_set_drvdata(pdev, NULL);
+
 	if (sirfport->hw_flow_ctrl)
 		pinctrl_put(sirfport->p);
 	clk_disable_unprepare(sirfport->clk);
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
new file mode 100644
index 0000000..2ff4b1b
--- /dev/null
+++ b/drivers/tty/serial/st-asc.c
@@ -0,0 +1,939 @@
+/*
+ * st-asc.c: ST Asynchronous serial controller (ASC) driver
+ *
+ * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+#define DRIVER_NAME "st-asc"
+#define ASC_SERIAL_NAME "ttyAS"
+#define ASC_FIFO_SIZE 16
+#define ASC_MAX_PORTS 8
+
+struct asc_port {
+	struct uart_port port;
+	struct clk *clk;
+	unsigned int hw_flow_control:1;
+	unsigned int force_m1:1;
+};
+
+static struct asc_port asc_ports[ASC_MAX_PORTS];
+static struct uart_driver asc_uart_driver;
+
+/*---- UART Register definitions ------------------------------*/
+
+/* Register offsets */
+
+#define ASC_BAUDRATE			0x00
+#define ASC_TXBUF			0x04
+#define ASC_RXBUF			0x08
+#define ASC_CTL				0x0C
+#define ASC_INTEN			0x10
+#define ASC_STA				0x14
+#define ASC_GUARDTIME			0x18
+#define ASC_TIMEOUT			0x1C
+#define ASC_TXRESET			0x20
+#define ASC_RXRESET			0x24
+#define ASC_RETRIES			0x28
+
+/* ASC_RXBUF */
+#define ASC_RXBUF_PE			0x100
+#define ASC_RXBUF_FE			0x200
+/**
+ * Some of status comes from higher bits of the character and some come from
+ * the status register. Combining both of them in to single status using dummy
+ * bits.
+ */
+#define ASC_RXBUF_DUMMY_RX		0x10000
+#define ASC_RXBUF_DUMMY_BE		0x20000
+#define ASC_RXBUF_DUMMY_OE		0x40000
+
+/* ASC_CTL */
+
+#define ASC_CTL_MODE_MSK		0x0007
+#define  ASC_CTL_MODE_8BIT		0x0001
+#define  ASC_CTL_MODE_7BIT_PAR		0x0003
+#define  ASC_CTL_MODE_9BIT		0x0004
+#define  ASC_CTL_MODE_8BIT_WKUP		0x0005
+#define  ASC_CTL_MODE_8BIT_PAR		0x0007
+#define ASC_CTL_STOP_MSK		0x0018
+#define  ASC_CTL_STOP_HALFBIT		0x0000
+#define  ASC_CTL_STOP_1BIT		0x0008
+#define  ASC_CTL_STOP_1_HALFBIT		0x0010
+#define  ASC_CTL_STOP_2BIT		0x0018
+#define ASC_CTL_PARITYODD		0x0020
+#define ASC_CTL_LOOPBACK		0x0040
+#define ASC_CTL_RUN			0x0080
+#define ASC_CTL_RXENABLE		0x0100
+#define ASC_CTL_SCENABLE		0x0200
+#define ASC_CTL_FIFOENABLE		0x0400
+#define ASC_CTL_CTSENABLE		0x0800
+#define ASC_CTL_BAUDMODE		0x1000
+
+/* ASC_GUARDTIME */
+
+#define ASC_GUARDTIME_MSK		0x00FF
+
+/* ASC_INTEN */
+
+#define ASC_INTEN_RBE			0x0001
+#define ASC_INTEN_TE			0x0002
+#define ASC_INTEN_THE			0x0004
+#define ASC_INTEN_PE			0x0008
+#define ASC_INTEN_FE			0x0010
+#define ASC_INTEN_OE			0x0020
+#define ASC_INTEN_TNE			0x0040
+#define ASC_INTEN_TOI			0x0080
+#define ASC_INTEN_RHF			0x0100
+
+/* ASC_RETRIES */
+
+#define ASC_RETRIES_MSK			0x00FF
+
+/* ASC_RXBUF */
+
+#define ASC_RXBUF_MSK			0x03FF
+
+/* ASC_STA */
+
+#define ASC_STA_RBF			0x0001
+#define ASC_STA_TE			0x0002
+#define ASC_STA_THE			0x0004
+#define ASC_STA_PE			0x0008
+#define ASC_STA_FE			0x0010
+#define ASC_STA_OE			0x0020
+#define ASC_STA_TNE			0x0040
+#define ASC_STA_TOI			0x0080
+#define ASC_STA_RHF			0x0100
+#define ASC_STA_TF			0x0200
+#define ASC_STA_NKD			0x0400
+
+/* ASC_TIMEOUT */
+
+#define ASC_TIMEOUT_MSK			0x00FF
+
+/* ASC_TXBUF */
+
+#define ASC_TXBUF_MSK			0x01FF
+
+/*---- Inline function definitions ---------------------------*/
+
+static inline struct asc_port *to_asc_port(struct uart_port *port)
+{
+	return container_of(port, struct asc_port, port);
+}
+
+static inline u32 asc_in(struct uart_port *port, u32 offset)
+{
+	return readl(port->membase + offset);
+}
+
+static inline void asc_out(struct uart_port *port, u32 offset, u32 value)
+{
+	writel(value, port->membase + offset);
+}
+
+/*
+ * Some simple utility functions to enable and disable interrupts.
+ * Note that these need to be called with interrupts disabled.
+ */
+static inline void asc_disable_tx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE;
+	asc_out(port, ASC_INTEN, intenable);
+	(void)asc_in(port, ASC_INTEN);	/* Defeat bus write posting */
+}
+
+static inline void asc_enable_tx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE;
+	asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline void asc_disable_rx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE;
+	asc_out(port, ASC_INTEN, intenable);
+	(void)asc_in(port, ASC_INTEN);	/* Defeat bus write posting */
+}
+
+static inline void asc_enable_rx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE;
+	asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline u32 asc_txfifo_is_empty(struct uart_port *port)
+{
+	return asc_in(port, ASC_STA) & ASC_STA_TE;
+}
+
+static inline int asc_txfifo_is_full(struct uart_port *port)
+{
+	return asc_in(port, ASC_STA) & ASC_STA_TF;
+}
+
+static inline const char *asc_port_name(struct uart_port *port)
+{
+	return to_platform_device(port->dev)->name;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * This section contains code to support the use of the ASC as a
+ * generic serial port.
+ */
+
+static inline unsigned asc_hw_txroom(struct uart_port *port)
+{
+	u32 status = asc_in(port, ASC_STA);
+
+	if (status & ASC_STA_THE)
+		return port->fifosize / 2;
+	else if (!(status & ASC_STA_TF))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Start transmitting chars.
+ * This is called from both interrupt and task level.
+ * Either way interrupts are disabled.
+ */
+static void asc_transmit_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+	int txroom;
+	unsigned char c;
+
+	txroom = asc_hw_txroom(port);
+
+	if ((txroom != 0) && port->x_char) {
+		c = port->x_char;
+		port->x_char = 0;
+		asc_out(port, ASC_TXBUF, c);
+		port->icount.tx++;
+		txroom = asc_hw_txroom(port);
+	}
+
+	if (uart_tx_stopped(port)) {
+		/*
+		 * We should try and stop the hardware here, but I
+		 * don't think the ASC has any way to do that.
+		 */
+		asc_disable_tx_interrupts(port);
+		return;
+	}
+
+	if (uart_circ_empty(xmit)) {
+		asc_disable_tx_interrupts(port);
+		return;
+	}
+
+	if (txroom == 0)
+		return;
+
+	do {
+		c = xmit->buf[xmit->tail];
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		asc_out(port, ASC_TXBUF, c);
+		port->icount.tx++;
+		txroom--;
+	} while ((txroom > 0) && (!uart_circ_empty(xmit)));
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		asc_disable_tx_interrupts(port);
+}
+
+static void asc_receive_chars(struct uart_port *port)
+{
+	struct tty_port *tport = &port->state->port;
+	unsigned long status;
+	unsigned long c = 0;
+	char flag;
+
+	if (port->irq_wake)
+		pm_wakeup_event(tport->tty->dev, 0);
+
+	while ((status = asc_in(port, ASC_STA)) & ASC_STA_RBF) {
+		c = asc_in(port, ASC_RXBUF) | ASC_RXBUF_DUMMY_RX;
+		flag = TTY_NORMAL;
+		port->icount.rx++;
+
+		if ((c & (ASC_RXBUF_FE | ASC_RXBUF_PE)) ||
+			status & ASC_STA_OE) {
+
+			if (c & ASC_RXBUF_FE) {
+				if (c == ASC_RXBUF_FE) {
+					port->icount.brk++;
+					if (uart_handle_break(port))
+						continue;
+					c |= ASC_RXBUF_DUMMY_BE;
+				} else {
+					port->icount.frame++;
+				}
+			} else if (c & ASC_RXBUF_PE) {
+				port->icount.parity++;
+			}
+			/*
+			 * Reading any data from the RX FIFO clears the
+			 * overflow error condition.
+			 */
+			if (status & ASC_STA_OE) {
+				port->icount.overrun++;
+				c |= ASC_RXBUF_DUMMY_OE;
+			}
+
+			c &= port->read_status_mask;
+
+			if (c & ASC_RXBUF_DUMMY_BE)
+				flag = TTY_BREAK;
+			else if (c & ASC_RXBUF_PE)
+				flag = TTY_PARITY;
+			else if (c & ASC_RXBUF_FE)
+				flag = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(port, c))
+			continue;
+
+		uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag);
+	}
+
+	/* Tell the rest of the system the news. New characters! */
+	tty_flip_buffer_push(tport);
+}
+
+static irqreturn_t asc_interrupt(int irq, void *ptr)
+{
+	struct uart_port *port = ptr;
+	u32 status;
+
+	spin_lock(&port->lock);
+
+	status = asc_in(port, ASC_STA);
+
+	if (status & ASC_STA_RBF) {
+		/* Receive FIFO not empty */
+		asc_receive_chars(port);
+	}
+
+	if ((status & ASC_STA_THE) &&
+	    (asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) {
+		/* Transmitter FIFO at least half empty */
+		asc_transmit_chars(port);
+	}
+
+	spin_unlock(&port->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * UART Functions
+ */
+
+static unsigned int asc_tx_empty(struct uart_port *port)
+{
+	return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0;
+}
+
+static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/*
+	 * This routine is used for seting signals of: DTR, DCD, CTS/RTS
+	 * We use ASC's hardware for CTS/RTS, so don't need any for that.
+	 * Some boards have DTR and DCD implemented using PIO pins,
+	 * code to do this should be hooked in here.
+	 */
+}
+
+static unsigned int asc_get_mctrl(struct uart_port *port)
+{
+	/*
+	 * This routine is used for geting signals of: DTR, DCD, DSR, RI,
+	 * and CTS/RTS
+	 */
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void asc_start_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (!uart_circ_empty(xmit))
+		asc_enable_tx_interrupts(port);
+}
+
+/* Transmit stop */
+static void asc_stop_tx(struct uart_port *port)
+{
+	asc_disable_tx_interrupts(port);
+}
+
+/* Receive stop */
+static void asc_stop_rx(struct uart_port *port)
+{
+	asc_disable_rx_interrupts(port);
+}
+
+/* Force modem status interrupts on */
+static void asc_enable_ms(struct uart_port *port)
+{
+	/* Nothing here yet .. */
+}
+
+/* Handle breaks - ignored by us */
+static void asc_break_ctl(struct uart_port *port, int break_state)
+{
+	/* Nothing here yet .. */
+}
+
+/*
+ * Enable port for reception.
+ */
+static int asc_startup(struct uart_port *port)
+{
+	if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND,
+			asc_port_name(port), port)) {
+		dev_err(port->dev, "cannot allocate irq.\n");
+		return -ENODEV;
+	}
+
+	asc_transmit_chars(port);
+	asc_enable_rx_interrupts(port);
+
+	return 0;
+}
+
+static void asc_shutdown(struct uart_port *port)
+{
+	asc_disable_tx_interrupts(port);
+	asc_disable_rx_interrupts(port);
+	free_irq(port->irq, port);
+}
+
+static void asc_pm(struct uart_port *port, unsigned int state,
+		unsigned int oldstate)
+{
+	struct asc_port *ascport = to_asc_port(port);
+	unsigned long flags = 0;
+	u32 ctl;
+
+	switch (state) {
+	case UART_PM_STATE_ON:
+		clk_prepare_enable(ascport->clk);
+		break;
+	case UART_PM_STATE_OFF:
+		/*
+		 * Disable the ASC baud rate generator, which is as close as
+		 * we can come to turning it off. Note this is not called with
+		 * the port spinlock held.
+		 */
+		spin_lock_irqsave(&port->lock, flags);
+		ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN;
+		asc_out(port, ASC_CTL, ctl);
+		spin_unlock_irqrestore(&port->lock, flags);
+		clk_disable_unprepare(ascport->clk);
+		break;
+	}
+}
+
+static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
+			    struct ktermios *old)
+{
+	struct asc_port *ascport = to_asc_port(port);
+	unsigned int baud;
+	u32 ctrl_val;
+	tcflag_t cflag;
+	unsigned long flags;
+
+	/* Update termios to reflect hardware capabilities */
+	termios->c_cflag &= ~(CMSPAR |
+			 (ascport->hw_flow_control ? 0 : CRTSCTS));
+
+	port->uartclk = clk_get_rate(ascport->clk);
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	cflag = termios->c_cflag;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* read control register */
+	ctrl_val = asc_in(port, ASC_CTL);
+
+	/* stop serial port and reset value */
+	asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
+	ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
+
+	/* reset fifo rx & tx */
+	asc_out(port, ASC_TXRESET, 1);
+	asc_out(port, ASC_RXRESET, 1);
+
+	/* set character length */
+	if ((cflag & CSIZE) == CS7) {
+		ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+	} else {
+		ctrl_val |= (cflag & PARENB) ?  ASC_CTL_MODE_8BIT_PAR :
+						ASC_CTL_MODE_8BIT;
+	}
+
+	/* set stop bit */
+	ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
+
+	/* odd parity */
+	if (cflag & PARODD)
+		ctrl_val |= ASC_CTL_PARITYODD;
+
+	/* hardware flow control */
+	if ((cflag & CRTSCTS))
+		ctrl_val |= ASC_CTL_CTSENABLE;
+
+	if ((baud < 19200) && !ascport->force_m1) {
+		asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud)));
+	} else {
+		/*
+		 * MODE 1: recommended for high bit rates (above 19.2K)
+		 *
+		 *                   baudrate * 16 * 2^16
+		 * ASCBaudRate =   ------------------------
+		 *                          inputclock
+		 *
+		 * However to keep the maths inside 32bits we divide top and
+		 * bottom by 64. The +1 is to avoid a divide by zero if the
+		 * input clock rate is something unexpected.
+		 */
+		u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
+		asc_out(port, ASC_BAUDRATE, counter);
+		ctrl_val |= ASC_CTL_BAUDMODE;
+	}
+
+	uart_update_timeout(port, cflag, baud);
+
+	ascport->port.read_status_mask = ASC_RXBUF_DUMMY_OE;
+	if (termios->c_iflag & INPCK)
+		ascport->port.read_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		ascport->port.read_status_mask |= ASC_RXBUF_DUMMY_BE;
+
+	/*
+	 * Characters to ignore
+	 */
+	ascport->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		ascport->port.ignore_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE;
+	if (termios->c_iflag & IGNBRK) {
+		ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_BE;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_OE;
+	}
+
+	/*
+	 * Ignore all characters if CREAD is not set.
+	 */
+	if (!(termios->c_cflag & CREAD))
+		ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_RX;
+
+	/* Set the timeout */
+	asc_out(port, ASC_TIMEOUT, 20);
+
+	/* write final value and enable port */
+	asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *asc_type(struct uart_port *port)
+{
+	return (port->type == PORT_ASC) ? DRIVER_NAME : NULL;
+}
+
+static void asc_release_port(struct uart_port *port)
+{
+}
+
+static int asc_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/*
+ * Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set
+ * Set type field if successful
+ */
+static void asc_config_port(struct uart_port *port, int flags)
+{
+	if ((flags & UART_CONFIG_TYPE))
+		port->type = PORT_ASC;
+}
+
+static int
+asc_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	/* No user changeable parameters */
+	return -EINVAL;
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context (i.e. kgdb).
+ */
+
+static int asc_get_poll_char(struct uart_port *port)
+{
+	if (!(asc_in(port, ASC_STA) & ASC_STA_RBF))
+		return NO_POLL_CHAR;
+
+	return asc_in(port, ASC_RXBUF);
+}
+
+static void asc_put_poll_char(struct uart_port *port, unsigned char c)
+{
+	while (asc_txfifo_is_full(port))
+		cpu_relax();
+	asc_out(port, ASC_TXBUF, c);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+/*---------------------------------------------------------------------*/
+
+static struct uart_ops asc_uart_ops = {
+	.tx_empty	= asc_tx_empty,
+	.set_mctrl	= asc_set_mctrl,
+	.get_mctrl	= asc_get_mctrl,
+	.start_tx	= asc_start_tx,
+	.stop_tx	= asc_stop_tx,
+	.stop_rx	= asc_stop_rx,
+	.enable_ms	= asc_enable_ms,
+	.break_ctl	= asc_break_ctl,
+	.startup	= asc_startup,
+	.shutdown	= asc_shutdown,
+	.set_termios	= asc_set_termios,
+	.type		= asc_type,
+	.release_port	= asc_release_port,
+	.request_port	= asc_request_port,
+	.config_port	= asc_config_port,
+	.verify_port	= asc_verify_port,
+	.pm		= asc_pm,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char = asc_get_poll_char,
+	.poll_put_char = asc_put_poll_char,
+#endif /* CONFIG_CONSOLE_POLL */
+};
+
+static int asc_init_port(struct asc_port *ascport,
+			  struct platform_device *pdev)
+{
+	struct uart_port *port = &ascport->port;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		dev_err(&pdev->dev, "Unable to get io resource\n");
+		return -ENODEV;
+	}
+
+	port->iotype	= UPIO_MEM;
+	port->flags	= UPF_BOOT_AUTOCONF;
+	port->ops	= &asc_uart_ops;
+	port->fifosize	= ASC_FIFO_SIZE;
+	port->dev	= &pdev->dev;
+	port->mapbase	= res->start;
+	port->irq	= platform_get_irq(pdev, 0);
+
+	port->membase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!port->membase) {
+		dev_err(&pdev->dev, "Unable to request io memory\n");
+		return -ENODEV;
+	}
+
+	spin_lock_init(&port->lock);
+
+	ascport->clk = devm_clk_get(&pdev->dev, NULL);
+
+	if (WARN_ON(IS_ERR(ascport->clk)))
+		return -EINVAL;
+	/* ensure that clk rate is correct by enabling the clk */
+	clk_prepare_enable(ascport->clk);
+	ascport->port.uartclk = clk_get_rate(ascport->clk);
+	WARN_ON(ascport->port.uartclk == 0);
+	clk_disable_unprepare(ascport->clk);
+
+	return 0;
+}
+
+static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int id;
+
+	if (!np)
+		return NULL;
+
+	id = of_alias_get_id(np, ASC_SERIAL_NAME);
+
+	if (id < 0)
+		id = 0;
+
+	if (WARN_ON(id >= ASC_MAX_PORTS))
+		return NULL;
+
+	asc_ports[id].hw_flow_control = of_property_read_bool(np,
+							"st,hw-flow-control");
+	asc_ports[id].force_m1 =  of_property_read_bool(np, "st,force_m1");
+	asc_ports[id].port.line = id;
+	return &asc_ports[id];
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id asc_match[] = {
+	{ .compatible = "st,asc", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, asc_match);
+#endif
+
+static int asc_serial_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct asc_port *ascport;
+
+	ascport = asc_of_get_asc_port(pdev);
+	if (!ascport)
+		return -ENODEV;
+
+	ret = asc_init_port(ascport, pdev);
+	if (ret)
+		return ret;
+
+	ret = uart_add_one_port(&asc_uart_driver, &ascport->port);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, &ascport->port);
+
+	return 0;
+}
+
+static int asc_serial_remove(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	return uart_remove_one_port(&asc_uart_driver, port);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int asc_serial_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	return uart_suspend_port(&asc_uart_driver, port);
+}
+
+static int asc_serial_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	return uart_resume_port(&asc_uart_driver, port);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
+static void asc_console_putchar(struct uart_port *port, int ch)
+{
+	unsigned int timeout = 1000000;
+
+	/* Wait for upto 1 second in case flow control is stopping us. */
+	while (--timeout && asc_txfifo_is_full(port))
+		udelay(1);
+
+	asc_out(port, ASC_TXBUF, ch);
+}
+
+/*
+ *  Print a string to the serial port trying not to disturb
+ *  any possible real use of the port...
+ */
+
+static void asc_console_write(struct console *co, const char *s, unsigned count)
+{
+	struct uart_port *port = &asc_ports[co->index].port;
+	unsigned long flags;
+	unsigned long timeout = 1000000;
+	int locked = 1;
+	u32 intenable;
+
+	local_irq_save(flags);
+	if (port->sysrq)
+		locked = 0; /* asc_interrupt has already claimed the lock */
+	else if (oops_in_progress)
+		locked = spin_trylock(&port->lock);
+	else
+		spin_lock(&port->lock);
+
+	/*
+	 * Disable interrupts so we don't get the IRQ line bouncing
+	 * up and down while interrupts are disabled.
+	 */
+	intenable = asc_in(port, ASC_INTEN);
+	asc_out(port, ASC_INTEN, 0);
+	(void)asc_in(port, ASC_INTEN);	/* Defeat bus write posting */
+
+	uart_console_write(port, s, count, asc_console_putchar);
+
+	while (--timeout && !asc_txfifo_is_empty(port))
+		udelay(1);
+
+	asc_out(port, ASC_INTEN, intenable);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
+}
+
+static int asc_console_setup(struct console *co, char *options)
+{
+	struct asc_port *ascport;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index >= ASC_MAX_PORTS)
+		return -ENODEV;
+
+	ascport = &asc_ports[co->index];
+
+	/*
+	 * This driver does not support early console initialization
+	 * (use ARM early printk support instead), so we only expect
+	 * this to be called during the uart port registration when the
+	 * driver gets probed and the port should be mapped at that point.
+	 */
+	BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&ascport->port, co, baud, parity, bits, flow);
+}
+
+static struct console asc_console = {
+	.name		= ASC_SERIAL_NAME,
+	.device		= uart_console_device,
+	.write		= asc_console_write,
+	.setup		= asc_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &asc_uart_driver,
+};
+
+#define ASC_SERIAL_CONSOLE (&asc_console)
+
+#else
+#define ASC_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */
+
+static struct uart_driver asc_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= DRIVER_NAME,
+	.dev_name	= ASC_SERIAL_NAME,
+	.major		= 0,
+	.minor		= 0,
+	.nr		= ASC_MAX_PORTS,
+	.cons		= ASC_SERIAL_CONSOLE,
+};
+
+static const struct dev_pm_ops asc_serial_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume)
+};
+
+static struct platform_driver asc_serial_driver = {
+	.probe		= asc_serial_probe,
+	.remove		= asc_serial_remove,
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.pm	= &asc_serial_pm_ops,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(asc_match),
+	},
+};
+
+static int __init asc_init(void)
+{
+	int ret;
+	static char banner[] __initdata =
+		KERN_INFO "STMicroelectronics ASC driver initialized\n";
+
+	printk(banner);
+
+	ret = uart_register_driver(&asc_uart_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&asc_serial_driver);
+	if (ret)
+		uart_unregister_driver(&asc_uart_driver);
+
+	return ret;
+}
+
+static void __exit asc_exit(void)
+{
+	platform_driver_unregister(&asc_serial_driver);
+	uart_unregister_driver(&asc_uart_driver);
+}
+
+module_init(asc_init);
+module_exit(asc_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("STMicroelectronics (R&D) Limited");
+MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
index f655997..a63c14b 100644
--- a/drivers/tty/serial/vr41xx_siu.c
+++ b/drivers/tty/serial/vr41xx_siu.c
@@ -705,7 +705,7 @@ static int siu_init_ports(struct platform_device *pdev)
 {
 	struct uart_port *port;
 	struct resource *res;
-	int *type = pdev->dev.platform_data;
+	int *type = dev_get_platdata(&pdev->dev);
 	int i;
 
 	if (!type)
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 48af43d..a90bf04 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -630,7 +630,6 @@ static int vt8500_serial_remove(struct platform_device *pdev)
 {
 	struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
 	clk_disable_unprepare(vt8500_port->clk);
 	uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);
 
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 8eaf1ab..e1ce141 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -577,22 +577,22 @@ struct mgsl_struct {
 
 #define SICR_RXC_ACTIVE			BIT15
 #define SICR_RXC_INACTIVE		BIT14
-#define SICR_RXC			(BIT15+BIT14)
+#define SICR_RXC			(BIT15|BIT14)
 #define SICR_TXC_ACTIVE			BIT13
 #define SICR_TXC_INACTIVE		BIT12
-#define SICR_TXC			(BIT13+BIT12)
+#define SICR_TXC			(BIT13|BIT12)
 #define SICR_RI_ACTIVE			BIT11
 #define SICR_RI_INACTIVE		BIT10
-#define SICR_RI				(BIT11+BIT10)
+#define SICR_RI				(BIT11|BIT10)
 #define SICR_DSR_ACTIVE			BIT9
 #define SICR_DSR_INACTIVE		BIT8
-#define SICR_DSR			(BIT9+BIT8)
+#define SICR_DSR			(BIT9|BIT8)
 #define SICR_DCD_ACTIVE			BIT7
 #define SICR_DCD_INACTIVE		BIT6
-#define SICR_DCD			(BIT7+BIT6)
+#define SICR_DCD			(BIT7|BIT6)
 #define SICR_CTS_ACTIVE			BIT5
 #define SICR_CTS_INACTIVE		BIT4
-#define SICR_CTS			(BIT5+BIT4)
+#define SICR_CTS			(BIT5|BIT4)
 #define SICR_RCC_UNDERFLOW		BIT3
 #define SICR_DPLL_NO_SYNC		BIT2
 #define SICR_BRG1_ZERO			BIT1
@@ -1161,7 +1161,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info )
 {
 	u16 status = usc_InReg( info, RCSR );
 
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
+	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):mgsl_isr_receive_status status=%04X\n",
 			__FILE__,__LINE__,status);
 			
@@ -1181,7 +1181,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info )
  			(usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED));
  	}
 
-	if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) {
+	if (status & (RXSTATUS_EXITED_HUNT | RXSTATUS_IDLE_RECEIVED)) {
 		if (status & RXSTATUS_EXITED_HUNT)
 			info->icount.exithunt++;
 		if (status & RXSTATUS_IDLE_RECEIVED)
@@ -1463,21 +1463,21 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
 
 		/* get the status of the received byte */
 		status = usc_InReg(info, RCSR);
-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
+		if ( status & (RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR |
+				RXSTATUS_OVERRUN | RXSTATUS_BREAK_RECEIVED) )
 			usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
 		
 		icount->rx++;
 		
 		flag = 0;
-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
-			printk("rxerr=%04X\n",status);					
+		if ( status & (RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR |
+				RXSTATUS_OVERRUN | RXSTATUS_BREAK_RECEIVED) ) {
+			printk("rxerr=%04X\n",status);
 			/* update error statistics */
 			if ( status & RXSTATUS_BREAK_RECEIVED ) {
-				status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR);
+				status &= ~(RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR);
 				icount->brk++;
-			} else if (status & RXSTATUS_PARITY_ERROR) 
+			} else if (status & RXSTATUS_PARITY_ERROR)
 				icount->parity++;
 			else if (status & RXSTATUS_FRAMING_ERROR)
 				icount->frame++;
@@ -1488,7 +1488,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
 				icount->overrun++;
 			}
 
-			/* discard char if tty control flags say so */					
+			/* discard char if tty control flags say so */
 			if (status & info->ignore_status_mask)
 				continue;
 				
@@ -1545,8 +1545,8 @@ static void mgsl_isr_misc( struct mgsl_struct *info )
 		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
 		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
 		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
-		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA | RECEIVE_STATUS);
+		usc_DisableInterrupts(info, RECEIVE_DATA | RECEIVE_STATUS);
 
 		/* schedule BH handler to restart receiver */
 		info->pending_bh |= BH_RECEIVE;
@@ -1595,7 +1595,7 @@ static void mgsl_isr_receive_dma( struct mgsl_struct *info )
 	u16 status;
 	
 	/* clear interrupt pending and IUS bit for Rx DMA IRQ */
-	usc_OutDmaReg( info, CDIR, BIT9+BIT1 );
+	usc_OutDmaReg( info, CDIR, BIT9 | BIT1 );
 
 	/* Read the receive DMA status to identify interrupt type. */
 	/* This also clears the status bits. */
@@ -1639,7 +1639,7 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
 	u16 status;
 
 	/* clear interrupt pending and IUS bit for Tx DMA IRQ */
-	usc_OutDmaReg(info, CDIR, BIT8+BIT0 );
+	usc_OutDmaReg(info, CDIR, BIT8 | BIT0 );
 
 	/* Read the transmit DMA status to identify interrupt type. */
 	/* This also clears the status bits. */
@@ -1832,8 +1832,8 @@ static void shutdown(struct mgsl_struct * info)
 	usc_DisableMasterIrqBit(info);
 	usc_stop_receiver(info);
 	usc_stop_transmitter(info);
-	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
-		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
+	usc_DisableInterrupts(info,RECEIVE_DATA | RECEIVE_STATUS |
+		TRANSMIT_DATA | TRANSMIT_STATUS | IO_PIN | MISC );
 	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
 
 	/* Disable DMAEN (Port 7, Bit 14) */
@@ -1886,7 +1886,7 @@ static void mgsl_program_hw(struct mgsl_struct *info)
 	info->ri_chkcount = 0;
 	info->dsr_chkcount = 0;
 
-	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);		
+	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);
 	usc_EnableInterrupts(info, IO_PIN);
 	usc_get_serial_signals(info);
 		
@@ -2773,7 +2773,7 @@ static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
 		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
 			usc_OutReg(info, RICR, usc_InReg(info,RICR) &
-				~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED));
+				~(RXSTATUS_EXITED_HUNT | RXSTATUS_IDLE_RECEIVED));
 		}
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	}
@@ -3092,7 +3092,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
 		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->port.count);
 
-	if (tty_port_close_start(&info->port, tty, filp) == 0)			 
+	if (tty_port_close_start(&info->port, tty, filp) == 0)
 		goto cleanup;
 
 	mutex_lock(&info->port.mutex);
@@ -4297,7 +4297,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
 		spin_lock_init(&info->irq_spinlock);
 		spin_lock_init(&info->netlock);
 		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;		
+		info->idle_mode = HDLC_TXIDLE_FLAGS;
 		info->num_tx_dma_buffers = 1;
 		info->num_tx_holding_buffers = 0;
 	}
@@ -4722,7 +4722,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
 			RegValue |= BIT15;
 		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
-			RegValue |= BIT15 + BIT14;
+			RegValue |= BIT15 | BIT14;
 		}
 
 		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
@@ -4763,11 +4763,11 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 	switch ( info->params.encoding ) {
 	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
 	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
-	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 + BIT13; break;
+	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 | BIT13; break;
 	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
+	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 | BIT13; break;
+	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 | BIT14; break;
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14 | BIT13; break;
 	}
 
 	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
@@ -4838,15 +4838,15 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 	switch ( info->params.encoding ) {
 	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
 	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
-	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 + BIT13; break;
+	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 | BIT13; break;
 	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
+	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 | BIT13; break;
+	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 | BIT14; break;
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14 | BIT13; break;
 	}
 
 	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
-		RegValue |= BIT9 + BIT8;
+		RegValue |= BIT9 | BIT8;
 	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
 		RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8);
 
@@ -4957,7 +4957,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 
 	RegValue = 0x0000;
 
-	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) {
+	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL | HDLC_FLAG_TXC_DPLL) ) {
 		u32 XtalSpeed;
 		u32 DpllDivisor;
 		u16 Tc;
@@ -5019,7 +5019,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 		case HDLC_ENCODING_BIPHASE_MARK:
 		case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break;
 		case HDLC_ENCODING_BIPHASE_LEVEL:
-		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break;
+		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 | BIT8; break;
 		}
 	}
 
@@ -5056,8 +5056,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 	/* enable Master Interrupt Enable bit (MIE) */
 	usc_EnableMasterIrqBit( info );
 
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
-				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
+	usc_ClearIrqPendingBits( info, RECEIVE_STATUS | RECEIVE_DATA |
+				TRANSMIT_STATUS | TRANSMIT_DATA | MISC);
 
 	/* arm RCC underflow interrupt */
 	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
@@ -5175,14 +5175,14 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
 	switch ( info->params.preamble_length ) {
 	case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break;
 	case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break;
-	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break;
+	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 | BIT10; break;
 	}
 
 	switch ( info->params.preamble ) {
-	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break;
+	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 | BIT12; break;
 	case HDLC_PREAMBLE_PATTERN_ONES:  RegValue |= BIT8; break;
 	case HDLC_PREAMBLE_PATTERN_10:    RegValue |= BIT9; break;
-	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 + BIT8; break;
+	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 | BIT8; break;
 	}
 
 	usc_OutReg( info, CCR, RegValue );
@@ -5221,7 +5221,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable)
 {
 	if (enable) {
 		/* blank external TXD output */
-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6));
+		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7 | BIT6));
 	
 		/* Clock mode Control Register (CMCR)
 		 *
@@ -5260,7 +5260,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable)
 		outw( 0x0300, info->io_base + CCAR );
 	} else {
 		/* enable external TXD output */
-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6));
+		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7 | BIT6));
 	
 		/* clear Internal Data loopback mode */
 		info->loopback_bits = 0;
@@ -5447,13 +5447,13 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
 		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
 
 		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
+		usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS );
 		usc_EnableInterrupts( info, RECEIVE_STATUS );
 
 		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
 		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
 
-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
+		usc_OutDmaReg( info, RDIAR, BIT3 | BIT2 );
 		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
 		usc_DmaCmd( info, DmaCmd_InitRxChannel );
 		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
@@ -5488,8 +5488,8 @@ static void usc_stop_receiver( struct mgsl_struct *info )
 	usc_DmaCmd( info, DmaCmd_ResetRxChannel );
 
 	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-	usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS );
+	usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS );
+	usc_DisableInterrupts( info, RECEIVE_DATA | RECEIVE_STATUS );
 
 	usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
 
@@ -5536,13 +5536,13 @@ static void usc_start_receiver( struct mgsl_struct *info )
 		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
 
 		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
+		usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS );
 		usc_EnableInterrupts( info, RECEIVE_STATUS );
 
 		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
 		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
 
-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
+		usc_OutDmaReg( info, RDIAR, BIT3 | BIT2 );
 		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
 		usc_DmaCmd( info, DmaCmd_InitRxChannel );
 		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
@@ -5551,7 +5551,7 @@ static void usc_start_receiver( struct mgsl_struct *info )
 			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
 	} else {
 		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA | RECEIVE_STATUS);
 		usc_EnableInterrupts(info, RECEIVE_DATA);
 
 		usc_RTCmd( info, RTCmd_PurgeRxFifo );
@@ -5925,7 +5925,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
 	RegValue = 0;
 
 	if ( info->params.data_bits != 8 )
-		RegValue |= BIT4+BIT3+BIT2;
+		RegValue |= BIT4 | BIT3 | BIT2;
 
 	if ( info->params.parity != ASYNC_PARITY_NONE ) {
 		RegValue |= BIT5;
@@ -5982,7 +5982,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
 	RegValue = 0;
 
 	if ( info->params.data_bits != 8 )
-		RegValue |= BIT4+BIT3+BIT2;
+		RegValue |= BIT4 | BIT3 | BIT2;
 
 	if ( info->params.parity != ASYNC_PARITY_NONE ) {
 		RegValue |= BIT5;
@@ -6129,7 +6129,7 @@ static void usc_loopback_frame( struct mgsl_struct *info )
 							
 	/* WAIT FOR RECEIVE COMPLETE */
 	for (i=0 ; i<1000 ; i++)
-		if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1))
+		if (usc_InReg( info, RCSR ) & (BIT8 | BIT4 | BIT3 | BIT1))
 			break;
 
 	/* clear Internal Data loopback mode */
@@ -6579,8 +6579,8 @@ static bool mgsl_get_rx_frame(struct mgsl_struct *info)
 	
 	status = info->rx_buffer_list[EndIndex].status;
 
-	if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
-			RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
+	if ( status & (RXSTATUS_SHORT_FRAME | RXSTATUS_OVERRUN |
+			RXSTATUS_CRC_ERROR | RXSTATUS_ABORT) ) {
 		if ( status & RXSTATUS_SHORT_FRAME )
 			info->icount.rxshort++;
 		else if ( status & RXSTATUS_ABORT )
@@ -6762,8 +6762,8 @@ static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info)
 
 		status = info->rx_buffer_list[CurrentIndex].status;
 
-		if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
-				RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
+		if ( status & (RXSTATUS_SHORT_FRAME | RXSTATUS_OVERRUN |
+				RXSTATUS_CRC_ERROR | RXSTATUS_ABORT) ) {
 			if ( status & RXSTATUS_SHORT_FRAME )
 				info->icount.rxshort++;
 			else if ( status & RXSTATUS_ABORT )
@@ -6899,7 +6899,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
 		/* set CMR:13 to start transmit when
 		 * next GoAhead (abort) is received
 		 */
-	 	info->cmr_value |= BIT13;			  
+	 	info->cmr_value |= BIT13;
 	}
 		
 	/* begin loading the frame in the next available tx dma
@@ -7278,7 +7278,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
 		
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-						
+
 		/******************************/
 		/* WAIT FOR TRANSMIT COMPLETE */
 		/******************************/
@@ -7292,7 +7292,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
 		status = usc_InReg( info, TCSR );
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
+		while ( !(status & (BIT6 | BIT5 | BIT4 | BIT2 | BIT1)) ) {
 			if (time_after(jiffies, EndTime)) {
 				rc = false;
 				break;
@@ -7307,7 +7307,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
 
 	if ( rc ){
 		/* CHECK FOR TRANSMIT ERRORS */
-		if ( status & (BIT5 + BIT1) ) 
+		if ( status & (BIT5 | BIT1) )
 			rc = false;
 	}
 
@@ -7333,7 +7333,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
 		/* CHECK FOR RECEIVE ERRORS */
 		status = info->rx_buffer_list[0].status;
 
-		if ( status & (BIT8 + BIT3 + BIT1) ) {
+		if ( status & (BIT8 | BIT3 | BIT1) ) {
 			/* receive error has occurred */
 			rc = false;
 		} else {
@@ -7605,7 +7605,7 @@ static void usc_loopmode_send_done( struct mgsl_struct * info )
 {
  	info->loopmode_send_done_requested = false;
  	/* clear CMR:13 to 0 to start echoing RxData to TxData */
- 	info->cmr_value &= ~BIT13;			  
+ 	info->cmr_value &= ~BIT13;
  	usc_OutReg(info, CMR, info->cmr_value);
 }
 
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 9121c1f..c043136f 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -18,31 +18,118 @@
 #include <linux/module.h>
 #include <linux/ratelimit.h>
 
+
+#define MIN_TTYB_SIZE	256
+#define TTYB_ALIGN_MASK	255
+
+/*
+ * Byte threshold to limit memory consumption for flip buffers.
+ * The actual memory limit is > 2x this amount.
+ */
+#define TTYB_MEM_LIMIT	65536
+
+/*
+ * We default to dicing tty buffer allocations to this many characters
+ * in order to avoid multiple page allocations. We know the size of
+ * tty_buffer itself but it must also be taken into account that the
+ * the buffer is 256 byte aligned. See tty_buffer_find for the allocation
+ * logic this must match
+ */
+
+#define TTY_BUFFER_PAGE	(((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
+
+
+/**
+ *	tty_buffer_lock_exclusive	-	gain exclusive access to buffer
+ *	tty_buffer_unlock_exclusive	-	release exclusive access
+ *
+ *	@port - tty_port owning the flip buffer
+ *
+ *	Guarantees safe use of the line discipline's receive_buf() method by
+ *	excluding the buffer work and any pending flush from using the flip
+ *	buffer. Data can continue to be added concurrently to the flip buffer
+ *	from the driver side.
+ *
+ *	On release, the buffer work is restarted if there is data in the
+ *	flip buffer
+ */
+
+void tty_buffer_lock_exclusive(struct tty_port *port)
+{
+	struct tty_bufhead *buf = &port->buf;
+
+	atomic_inc(&buf->priority);
+	mutex_lock(&buf->lock);
+}
+
+void tty_buffer_unlock_exclusive(struct tty_port *port)
+{
+	struct tty_bufhead *buf = &port->buf;
+	int restart;
+
+	restart = buf->head->commit != buf->head->read;
+
+	atomic_dec(&buf->priority);
+	mutex_unlock(&buf->lock);
+	if (restart)
+		queue_work(system_unbound_wq, &buf->work);
+}
+
+/**
+ *	tty_buffer_space_avail	-	return unused buffer space
+ *	@port - tty_port owning the flip buffer
+ *
+ *	Returns the # of bytes which can be written by the driver without
+ *	reaching the buffer limit.
+ *
+ *	Note: this does not guarantee that memory is available to write
+ *	the returned # of bytes (use tty_prepare_flip_string_xxx() to
+ *	pre-allocate if memory guarantee is required).
+ */
+
+int tty_buffer_space_avail(struct tty_port *port)
+{
+	int space = TTYB_MEM_LIMIT - atomic_read(&port->buf.memory_used);
+	return max(space, 0);
+}
+
+static void tty_buffer_reset(struct tty_buffer *p, size_t size)
+{
+	p->used = 0;
+	p->size = size;
+	p->next = NULL;
+	p->commit = 0;
+	p->read = 0;
+}
+
 /**
  *	tty_buffer_free_all		-	free buffers used by a tty
  *	@tty: tty to free from
  *
  *	Remove all the buffers pending on a tty whether queued with data
  *	or in the free ring. Must be called when the tty is no longer in use
- *
- *	Locking: none
  */
 
 void tty_buffer_free_all(struct tty_port *port)
 {
 	struct tty_bufhead *buf = &port->buf;
-	struct tty_buffer *thead;
+	struct tty_buffer *p, *next;
+	struct llist_node *llist;
 
-	while ((thead = buf->head) != NULL) {
-		buf->head = thead->next;
-		kfree(thead);
-	}
-	while ((thead = buf->free) != NULL) {
-		buf->free = thead->next;
-		kfree(thead);
+	while ((p = buf->head) != NULL) {
+		buf->head = p->next;
+		if (p->size > 0)
+			kfree(p);
 	}
-	buf->tail = NULL;
-	buf->memory_used = 0;
+	llist = llist_del_all(&buf->free);
+	llist_for_each_entry_safe(p, next, llist, free)
+		kfree(p);
+
+	tty_buffer_reset(&buf->sentinel, 0);
+	buf->head = &buf->sentinel;
+	buf->tail = &buf->sentinel;
+
+	atomic_set(&buf->memory_used, 0);
 }
 
 /**
@@ -51,29 +138,39 @@ void tty_buffer_free_all(struct tty_port *port)
  *	@size: desired size (characters)
  *
  *	Allocate a new tty buffer to hold the desired number of characters.
+ *	We round our buffers off in 256 character chunks to get better
+ *	allocation behaviour.
  *	Return NULL if out of memory or the allocation would exceed the
  *	per device queue
- *
- *	Locking: Caller must hold tty->buf.lock
  */
 
 static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
 {
+	struct llist_node *free;
 	struct tty_buffer *p;
 
-	if (port->buf.memory_used + size > 65536)
+	/* Round the buffer size out */
+	size = __ALIGN_MASK(size, TTYB_ALIGN_MASK);
+
+	if (size <= MIN_TTYB_SIZE) {
+		free = llist_del_first(&port->buf.free);
+		if (free) {
+			p = llist_entry(free, struct tty_buffer, free);
+			goto found;
+		}
+	}
+
+	/* Should possibly check if this fails for the largest buffer we
+	   have queued and recycle that ? */
+	if (atomic_read(&port->buf.memory_used) > TTYB_MEM_LIMIT)
 		return NULL;
 	p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
 	if (p == NULL)
 		return NULL;
-	p->used = 0;
-	p->size = size;
-	p->next = NULL;
-	p->commit = 0;
-	p->read = 0;
-	p->char_buf_ptr = (char *)(p->data);
-	p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-	port->buf.memory_used += size;
+
+found:
+	tty_buffer_reset(p, size);
+	atomic_add(size, &port->buf.memory_used);
 	return p;
 }
 
@@ -84,8 +181,6 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
  *
  *	Free a tty buffer, or add it to the free list according to our
  *	internal strategy
- *
- *	Locking: Caller must hold tty->buf.lock
  */
 
 static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
@@ -93,41 +188,12 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
 	struct tty_bufhead *buf = &port->buf;
 
 	/* Dumb strategy for now - should keep some stats */
-	buf->memory_used -= b->size;
-	WARN_ON(buf->memory_used < 0);
+	WARN_ON(atomic_sub_return(b->size, &buf->memory_used) < 0);
 
-	if (b->size >= 512)
+	if (b->size > MIN_TTYB_SIZE)
 		kfree(b);
-	else {
-		b->next = buf->free;
-		buf->free = b;
-	}
-}
-
-/**
- *	__tty_buffer_flush		-	flush full tty buffers
- *	@tty: tty to flush
- *
- *	flush all the buffers containing receive data. Caller must
- *	hold the buffer lock and must have ensured no parallel flush to
- *	ldisc is running.
- *
- *	Locking: Caller must hold tty->buf.lock
- */
-
-static void __tty_buffer_flush(struct tty_port *port)
-{
-	struct tty_bufhead *buf = &port->buf;
-	struct tty_buffer *thead;
-
-	if (unlikely(buf->head == NULL))
-		return;
-	while ((thead = buf->head->next) != NULL) {
-		tty_buffer_free(port, buf->head);
-		buf->head = thead;
-	}
-	WARN_ON(buf->head != buf->tail);
-	buf->head->read = buf->head->commit;
+	else if (b->size > 0)
+		llist_add(&b->free, &buf->free);
 }
 
 /**
@@ -138,65 +204,28 @@ static void __tty_buffer_flush(struct tty_port *port)
  *	being processed by flush_to_ldisc then we defer the processing
  *	to that function
  *
- *	Locking: none
+ *	Locking: takes buffer lock to ensure single-threaded flip buffer
+ *		 'consumer'
  */
 
 void tty_buffer_flush(struct tty_struct *tty)
 {
 	struct tty_port *port = tty->port;
 	struct tty_bufhead *buf = &port->buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&buf->lock, flags);
-
-	/* If the data is being pushed to the tty layer then we can't
-	   process it here. Instead set a flag and the flush_to_ldisc
-	   path will process the flush request before it exits */
-	if (test_bit(TTYP_FLUSHING, &port->iflags)) {
-		set_bit(TTYP_FLUSHPENDING, &port->iflags);
-		spin_unlock_irqrestore(&buf->lock, flags);
-		wait_event(tty->read_wait,
-				test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
-		return;
-	} else
-		__tty_buffer_flush(port);
-	spin_unlock_irqrestore(&buf->lock, flags);
-}
+	struct tty_buffer *next;
 
-/**
- *	tty_buffer_find		-	find a free tty buffer
- *	@tty: tty owning the buffer
- *	@size: characters wanted
- *
- *	Locate an existing suitable tty buffer or if we are lacking one then
- *	allocate a new one. We round our buffers off in 256 character chunks
- *	to get better allocation behaviour.
- *
- *	Locking: Caller must hold tty->buf.lock
- */
+	atomic_inc(&buf->priority);
 
-static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
-{
-	struct tty_buffer **tbh = &port->buf.free;
-	while ((*tbh) != NULL) {
-		struct tty_buffer *t = *tbh;
-		if (t->size >= size) {
-			*tbh = t->next;
-			t->next = NULL;
-			t->used = 0;
-			t->commit = 0;
-			t->read = 0;
-			port->buf.memory_used += t->size;
-			return t;
-		}
-		tbh = &((*tbh)->next);
+	mutex_lock(&buf->lock);
+	while ((next = buf->head->next) != NULL) {
+		tty_buffer_free(port, buf->head);
+		buf->head = next;
 	}
-	/* Round the buffer size out */
-	size = (size + 0xFF) & ~0xFF;
-	return tty_buffer_alloc(port, size);
-	/* Should possibly check if this fails for the largest buffer we
-	   have queued and recycle that ? */
+	buf->head->read = buf->head->commit;
+	atomic_dec(&buf->priority);
+	mutex_unlock(&buf->lock);
 }
+
 /**
  *	tty_buffer_request_room		-	grow tty buffer if needed
  *	@tty: tty structure
@@ -204,38 +233,26 @@ static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
  *
  *	Make at least size bytes of linear space available for the tty
  *	buffer. If we fail return the size we managed to find.
- *
- *	Locking: Takes port->buf.lock
  */
 int tty_buffer_request_room(struct tty_port *port, size_t size)
 {
 	struct tty_bufhead *buf = &port->buf;
 	struct tty_buffer *b, *n;
 	int left;
-	unsigned long flags;
-	spin_lock_irqsave(&buf->lock, flags);
-	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
-	   remove this conditional if its worth it. This would be invisible
-	   to the callers */
+
 	b = buf->tail;
-	if (b != NULL)
-		left = b->size - b->used;
-	else
-		left = 0;
+	left = b->size - b->used;
 
 	if (left < size) {
 		/* This is the slow path - looking for new buffers to use */
-		if ((n = tty_buffer_find(port, size)) != NULL) {
-			if (b != NULL) {
-				b->next = n;
-				b->commit = b->used;
-			} else
-				buf->head = n;
+		if ((n = tty_buffer_alloc(port, size)) != NULL) {
 			buf->tail = n;
+			b->commit = b->used;
+			smp_mb();
+			b->next = n;
 		} else
 			size = left;
 	}
-	spin_unlock_irqrestore(&buf->lock, flags);
 	return size;
 }
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
@@ -249,8 +266,6 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
  *
  *	Queue a series of bytes to the tty buffering. All the characters
  *	passed are marked with the supplied flag. Returns the number added.
- *
- *	Locking: Called functions may take port->buf.lock
  */
 
 int tty_insert_flip_string_fixed_flag(struct tty_port *port,
@@ -261,12 +276,10 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port,
 		int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
 		int space = tty_buffer_request_room(port, goal);
 		struct tty_buffer *tb = port->buf.tail;
-		/* If there is no space then tb may be NULL */
-		if (unlikely(space == 0)) {
+		if (unlikely(space == 0))
 			break;
-		}
-		memcpy(tb->char_buf_ptr + tb->used, chars, space);
-		memset(tb->flag_buf_ptr + tb->used, flag, space);
+		memcpy(char_buf_ptr(tb, tb->used), chars, space);
+		memset(flag_buf_ptr(tb, tb->used), flag, space);
 		tb->used += space;
 		copied += space;
 		chars += space;
@@ -287,8 +300,6 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
  *	Queue a series of bytes to the tty buffering. For each character
  *	the flags array indicates the status of the character. Returns the
  *	number added.
- *
- *	Locking: Called functions may take port->buf.lock
  */
 
 int tty_insert_flip_string_flags(struct tty_port *port,
@@ -299,12 +310,10 @@ int tty_insert_flip_string_flags(struct tty_port *port,
 		int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
 		int space = tty_buffer_request_room(port, goal);
 		struct tty_buffer *tb = port->buf.tail;
-		/* If there is no space then tb may be NULL */
-		if (unlikely(space == 0)) {
+		if (unlikely(space == 0))
 			break;
-		}
-		memcpy(tb->char_buf_ptr + tb->used, chars, space);
-		memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+		memcpy(char_buf_ptr(tb, tb->used), chars, space);
+		memcpy(flag_buf_ptr(tb, tb->used), flags, space);
 		tb->used += space;
 		copied += space;
 		chars += space;
@@ -325,20 +334,14 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
  *	processing by the line discipline.
  *	Note that this function can only be used when the low_latency flag
  *	is unset. Otherwise the workqueue won't be flushed.
- *
- *	Locking: Takes port->buf.lock
  */
 
 void tty_schedule_flip(struct tty_port *port)
 {
 	struct tty_bufhead *buf = &port->buf;
-	unsigned long flags;
 	WARN_ON(port->low_latency);
 
-	spin_lock_irqsave(&buf->lock, flags);
-	if (buf->tail != NULL)
-		buf->tail->commit = buf->tail->used;
-	spin_unlock_irqrestore(&buf->lock, flags);
+	buf->tail->commit = buf->tail->used;
 	schedule_work(&buf->work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
@@ -354,8 +357,6 @@ EXPORT_SYMBOL(tty_schedule_flip);
  *	accounted for as ready for normal characters. This is used for drivers
  *	that need their own block copy routines into the buffer. There is no
  *	guarantee the buffer is a DMA target!
- *
- *	Locking: May call functions taking port->buf.lock
  */
 
 int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
@@ -364,8 +365,8 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
 	int space = tty_buffer_request_room(port, size);
 	if (likely(space)) {
 		struct tty_buffer *tb = port->buf.tail;
-		*chars = tb->char_buf_ptr + tb->used;
-		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+		*chars = char_buf_ptr(tb, tb->used);
+		memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space);
 		tb->used += space;
 	}
 	return space;
@@ -384,8 +385,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
  *	accounted for as ready for characters. This is used for drivers
  *	that need their own block copy routines into the buffer. There is no
  *	guarantee the buffer is a DMA target!
- *
- *	Locking: May call functions taking port->buf.lock
  */
 
 int tty_prepare_flip_string_flags(struct tty_port *port,
@@ -394,8 +393,8 @@ int tty_prepare_flip_string_flags(struct tty_port *port,
 	int space = tty_buffer_request_room(port, size);
 	if (likely(space)) {
 		struct tty_buffer *tb = port->buf.tail;
-		*chars = tb->char_buf_ptr + tb->used;
-		*flags = tb->flag_buf_ptr + tb->used;
+		*chars = char_buf_ptr(tb, tb->used);
+		*flags = flag_buf_ptr(tb, tb->used);
 		tb->used += space;
 	}
 	return space;
@@ -403,6 +402,23 @@ int tty_prepare_flip_string_flags(struct tty_port *port,
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
 
 
+static int
+receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
+{
+	struct tty_ldisc *disc = tty->ldisc;
+	unsigned char *p = char_buf_ptr(head, head->read);
+	char	      *f = flag_buf_ptr(head, head->read);
+
+	if (disc->ops->receive_buf2)
+		count = disc->ops->receive_buf2(tty, p, f, count);
+	else {
+		count = min_t(int, count, tty->receive_room);
+		if (count)
+			disc->ops->receive_buf(tty, p, f, count);
+	}
+	head->read += count;
+	return count;
+}
 
 /**
  *	flush_to_ldisc
@@ -411,9 +427,10 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
  *	This routine is called out of the software interrupt to flush data
  *	from the buffer chain to the line discipline.
  *
- *	Locking: holds tty->buf.lock to guard buffer list. Drops the lock
- *	while invoking the line discipline receive_buf method. The
- *	receive_buf method is single threaded for each tty instance.
+ *	The receive_buf method is single threaded for each tty instance.
+ *
+ *	Locking: takes buffer lock to ensure single-threaded flip buffer
+ *		 'consumer'
  */
 
 static void flush_to_ldisc(struct work_struct *work)
@@ -421,7 +438,6 @@ static void flush_to_ldisc(struct work_struct *work)
 	struct tty_port *port = container_of(work, struct tty_port, buf.work);
 	struct tty_bufhead *buf = &port->buf;
 	struct tty_struct *tty;
-	unsigned long 	flags;
 	struct tty_ldisc *disc;
 
 	tty = port->itty;
@@ -429,52 +445,34 @@ static void flush_to_ldisc(struct work_struct *work)
 		return;
 
 	disc = tty_ldisc_ref(tty);
-	if (disc == NULL)	/*  !TTY_LDISC */
+	if (disc == NULL)
 		return;
 
-	spin_lock_irqsave(&buf->lock, flags);
-
-	if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
-		struct tty_buffer *head;
-		while ((head = buf->head) != NULL) {
-			int count;
-			char *char_buf;
-			unsigned char *flag_buf;
-
-			count = head->commit - head->read;
-			if (!count) {
-				if (head->next == NULL)
-					break;
-				buf->head = head->next;
-				tty_buffer_free(port, head);
-				continue;
-			}
-			if (!tty->receive_room)
-				break;
-			if (count > tty->receive_room)
-				count = tty->receive_room;
-			char_buf = head->char_buf_ptr + head->read;
-			flag_buf = head->flag_buf_ptr + head->read;
-			head->read += count;
-			spin_unlock_irqrestore(&buf->lock, flags);
-			disc->ops->receive_buf(tty, char_buf,
-							flag_buf, count);
-			spin_lock_irqsave(&buf->lock, flags);
-			/* Ldisc or user is trying to flush the buffers.
-			   We may have a deferred request to flush the
-			   input buffer, if so pull the chain under the lock
-			   and empty the queue */
-			if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
-				__tty_buffer_flush(port);
-				clear_bit(TTYP_FLUSHPENDING, &port->iflags);
-				wake_up(&tty->read_wait);
+	mutex_lock(&buf->lock);
+
+	while (1) {
+		struct tty_buffer *head = buf->head;
+		int count;
+
+		/* Ldisc or user is trying to gain exclusive access */
+		if (atomic_read(&buf->priority))
+			break;
+
+		count = head->commit - head->read;
+		if (!count) {
+			if (head->next == NULL)
 				break;
-			}
+			buf->head = head->next;
+			tty_buffer_free(port, head);
+			continue;
 		}
-		clear_bit(TTYP_FLUSHING, &port->iflags);
+
+		count = receive_buf(tty, head, count);
+		if (!count)
+			break;
 	}
 
-	spin_unlock_irqrestore(&buf->lock, flags);
+	mutex_unlock(&buf->lock);
 
 	tty_ldisc_deref(disc);
 }
@@ -503,19 +501,13 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
  *
  *	In the event of the queue being busy for flipping the work will be
  *	held off and retried later.
- *
- *	Locking: tty buffer lock. Driver locks in low latency mode.
  */
 
 void tty_flip_buffer_push(struct tty_port *port)
 {
 	struct tty_bufhead *buf = &port->buf;
-	unsigned long flags;
 
-	spin_lock_irqsave(&buf->lock, flags);
-	if (buf->tail != NULL)
-		buf->tail->commit = buf->tail->used;
-	spin_unlock_irqrestore(&buf->lock, flags);
+	buf->tail->commit = buf->tail->used;
 
 	if (port->low_latency)
 		flush_to_ldisc(&buf->work);
@@ -530,19 +522,18 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
  *
  *	Set up the initial state of the buffer management for a tty device.
  *	Must be called before the other tty buffer functions are used.
- *
- *	Locking: none
  */
 
 void tty_buffer_init(struct tty_port *port)
 {
 	struct tty_bufhead *buf = &port->buf;
 
-	spin_lock_init(&buf->lock);
-	buf->head = NULL;
-	buf->tail = NULL;
-	buf->free = NULL;
-	buf->memory_used = 0;
+	mutex_init(&buf->lock);
+	tty_buffer_reset(&buf->sentinel, 0);
+	buf->head = &buf->sentinel;
+	buf->tail = &buf->sentinel;
+	init_llist_head(&buf->free);
+	atomic_set(&buf->memory_used, 0);
+	atomic_set(&buf->priority, 0);
 	INIT_WORK(&buf->work, flush_to_ldisc);
 }
-
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 366af83..a9355ce 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -603,8 +603,8 @@ static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
  *		BTM
  *		  redirect lock for undoing redirection
  *		  file list lock for manipulating list of ttys
- *		  tty_ldisc_lock from called functions
- *		  termios_mutex resetting termios data
+ *		  tty_ldiscs_lock from called functions
+ *		  termios_rwsem resetting termios data
  *		  tasklist_lock to walk task list for hangup event
  *		    ->siglock to protect ->signal/->sighand
  */
@@ -629,6 +629,11 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
 
 	tty_lock(tty);
 
+	if (test_bit(TTY_HUPPED, &tty->flags)) {
+		tty_unlock(tty);
+		return;
+	}
+
 	/* some functions below drop BTM, so we need this bit */
 	set_bit(TTY_HUPPING, &tty->flags);
 
@@ -664,7 +669,6 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
 
 	spin_lock_irq(&tty->ctrl_lock);
 	clear_bit(TTY_THROTTLED, &tty->flags);
-	clear_bit(TTY_PUSH, &tty->flags);
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	put_pid(tty->session);
 	put_pid(tty->pgrp);
@@ -1388,8 +1392,7 @@ static int tty_reopen(struct tty_struct *tty)
 	struct tty_driver *driver = tty->driver;
 
 	if (test_bit(TTY_CLOSING, &tty->flags) ||
-			test_bit(TTY_HUPPING, &tty->flags) ||
-			test_bit(TTY_LDISC_CHANGING, &tty->flags))
+			test_bit(TTY_HUPPING, &tty->flags))
 		return -EIO;
 
 	if (driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -1405,7 +1408,7 @@ static int tty_reopen(struct tty_struct *tty)
 	}
 	tty->count++;
 
-	WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
+	WARN_ON(!tty->ldisc);
 
 	return 0;
 }
@@ -2202,7 +2205,7 @@ static int tty_fasync(int fd, struct file *filp, int on)
  *	FIXME: does not honour flow control ??
  *
  *	Locking:
- *		Called functions take tty_ldisc_lock
+ *		Called functions take tty_ldiscs_lock
  *		current->signal->tty check is safe without locks
  *
  *	FIXME: may race normal receive processing
@@ -2231,7 +2234,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
  *
  *	Copies the kernel idea of the window size into the user buffer.
  *
- *	Locking: tty->termios_mutex is taken to ensure the winsize data
+ *	Locking: tty->winsize_mutex is taken to ensure the winsize data
  *		is consistent.
  */
 
@@ -2239,9 +2242,9 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
 {
 	int err;
 
-	mutex_lock(&tty->termios_mutex);
+	mutex_lock(&tty->winsize_mutex);
 	err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
-	mutex_unlock(&tty->termios_mutex);
+	mutex_unlock(&tty->winsize_mutex);
 
 	return err ? -EFAULT: 0;
 }
@@ -2262,7 +2265,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
 	unsigned long flags;
 
 	/* Lock the tty */
-	mutex_lock(&tty->termios_mutex);
+	mutex_lock(&tty->winsize_mutex);
 	if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
 		goto done;
 	/* Get the PID values and reference them so we can
@@ -2277,7 +2280,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
 
 	tty->winsize = *ws;
 done:
-	mutex_unlock(&tty->termios_mutex);
+	mutex_unlock(&tty->winsize_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(tty_do_resize);
@@ -3016,8 +3019,10 @@ void initialize_tty_struct(struct tty_struct *tty,
 	tty->session = NULL;
 	tty->pgrp = NULL;
 	mutex_init(&tty->legacy_mutex);
-	mutex_init(&tty->termios_mutex);
-	mutex_init(&tty->ldisc_mutex);
+	mutex_init(&tty->throttle_mutex);
+	init_rwsem(&tty->termios_rwsem);
+	mutex_init(&tty->winsize_mutex);
+	init_ldsem(&tty->ldisc_sem);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
 	INIT_WORK(&tty->hangup_work, do_tty_hangup);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 3500d41..03ba081 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -94,20 +94,20 @@ EXPORT_SYMBOL(tty_driver_flush_buffer);
  *	@tty: terminal
  *
  *	Indicate that a tty should stop transmitting data down the stack.
- *	Takes the termios mutex to protect against parallel throttle/unthrottle
+ *	Takes the termios rwsem to protect against parallel throttle/unthrottle
  *	and also to ensure the driver can consistently reference its own
  *	termios data at this point when implementing software flow control.
  */
 
 void tty_throttle(struct tty_struct *tty)
 {
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	/* check TTY_THROTTLED first so it indicates our state */
 	if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
 	    tty->ops->throttle)
 		tty->ops->throttle(tty);
 	tty->flow_change = 0;
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 }
 EXPORT_SYMBOL(tty_throttle);
 
@@ -116,7 +116,7 @@ EXPORT_SYMBOL(tty_throttle);
  *	@tty: terminal
  *
  *	Indicate that a tty may continue transmitting data down the stack.
- *	Takes the termios mutex to protect against parallel throttle/unthrottle
+ *	Takes the termios rwsem to protect against parallel throttle/unthrottle
  *	and also to ensure the driver can consistently reference its own
  *	termios data at this point when implementing software flow control.
  *
@@ -126,12 +126,12 @@ EXPORT_SYMBOL(tty_throttle);
 
 void tty_unthrottle(struct tty_struct *tty)
 {
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
 	    tty->ops->unthrottle)
 		tty->ops->unthrottle(tty);
 	tty->flow_change = 0;
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 }
 EXPORT_SYMBOL(tty_unthrottle);
 
@@ -151,7 +151,7 @@ int tty_throttle_safe(struct tty_struct *tty)
 {
 	int ret = 0;
 
-	mutex_lock(&tty->termios_mutex);
+	mutex_lock(&tty->throttle_mutex);
 	if (!test_bit(TTY_THROTTLED, &tty->flags)) {
 		if (tty->flow_change != TTY_THROTTLE_SAFE)
 			ret = 1;
@@ -161,7 +161,7 @@ int tty_throttle_safe(struct tty_struct *tty)
 				tty->ops->throttle(tty);
 		}
 	}
-	mutex_unlock(&tty->termios_mutex);
+	mutex_unlock(&tty->throttle_mutex);
 
 	return ret;
 }
@@ -182,7 +182,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
 {
 	int ret = 0;
 
-	mutex_lock(&tty->termios_mutex);
+	mutex_lock(&tty->throttle_mutex);
 	if (test_bit(TTY_THROTTLED, &tty->flags)) {
 		if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
 			ret = 1;
@@ -192,7 +192,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
 				tty->ops->unthrottle(tty);
 		}
 	}
-	mutex_unlock(&tty->termios_mutex);
+	mutex_unlock(&tty->throttle_mutex);
 
 	return ret;
 }
@@ -468,7 +468,7 @@ EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
  *	@obad: output baud rate
  *
  *	Update the current termios data for the tty with the new speed
- *	settings. The caller must hold the termios_mutex for the tty in
+ *	settings. The caller must hold the termios_rwsem for the tty in
  *	question.
  */
 
@@ -528,7 +528,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
  *	is a bit of layering violation here with n_tty in terms of the
  *	internal knowledge of this function.
  *
- *	Locking: termios_mutex
+ *	Locking: termios_rwsem
  */
 
 int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
@@ -544,7 +544,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
 
 	/* FIXME: we need to decide on some locking/ordering semantics
 	   for the set_termios notification eventually */
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	old_termios = tty->termios;
 	tty->termios = *new_termios;
 	unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked);
@@ -586,7 +586,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
 			(ld->ops->set_termios)(tty, &old_termios);
 		tty_ldisc_deref(ld);
 	}
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(tty_set_termios);
@@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(tty_set_termios);
  *	functions before using tty_set_termios to do the actual changes.
  *
  *	Locking:
- *		Called functions take ldisc and termios_mutex locks
+ *		Called functions take ldisc and termios_rwsem locks
  */
 
 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
@@ -613,9 +613,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
 	if (retval)
 		return retval;
 
-	mutex_lock(&tty->termios_mutex);
+	down_read(&tty->termios_rwsem);
 	tmp_termios = tty->termios;
-	mutex_unlock(&tty->termios_mutex);
+	up_read(&tty->termios_rwsem);
 
 	if (opt & TERMIOS_TERMIO) {
 		if (user_termio_to_kernel_termios(&tmp_termios,
@@ -667,16 +667,16 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
 
 static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
 {
-	mutex_lock(&tty->termios_mutex);
+	down_read(&tty->termios_rwsem);
 	*kterm = tty->termios;
-	mutex_unlock(&tty->termios_mutex);
+	up_read(&tty->termios_rwsem);
 }
 
 static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
 {
-	mutex_lock(&tty->termios_mutex);
+	down_read(&tty->termios_rwsem);
 	*kterm = tty->termios_locked;
-	mutex_unlock(&tty->termios_mutex);
+	up_read(&tty->termios_rwsem);
 }
 
 static int get_termio(struct tty_struct *tty, struct termio __user *termio)
@@ -723,10 +723,10 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
 			return -ERESTARTSYS;
 	}
 
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	if (tty->ops->set_termiox)
 		tty->ops->set_termiox(tty, &tnew);
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 	return 0;
 }
 
@@ -761,13 +761,13 @@ static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
 {
 	struct sgttyb tmp;
 
-	mutex_lock(&tty->termios_mutex);
+	down_read(&tty->termios_rwsem);
 	tmp.sg_ispeed = tty->termios.c_ispeed;
 	tmp.sg_ospeed = tty->termios.c_ospeed;
 	tmp.sg_erase = tty->termios.c_cc[VERASE];
 	tmp.sg_kill = tty->termios.c_cc[VKILL];
 	tmp.sg_flags = get_sgflags(tty);
-	mutex_unlock(&tty->termios_mutex);
+	up_read(&tty->termios_rwsem);
 
 	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
@@ -806,7 +806,7 @@ static void set_sgflags(struct ktermios *termios, int flags)
  *	Updates a terminal from the legacy BSD style terminal information
  *	structure.
  *
- *	Locking: termios_mutex
+ *	Locking: termios_rwsem
  */
 
 static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
@@ -822,7 +822,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
 	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
 		return -EFAULT;
 
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	termios = tty->termios;
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
@@ -832,7 +832,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
 	tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
 						termios.c_ospeed);
 #endif
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 	tty_set_termios(tty, &termios);
 	return 0;
 }
@@ -843,14 +843,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 {
 	struct tchars tmp;
 
-	mutex_lock(&tty->termios_mutex);
+	down_read(&tty->termios_rwsem);
 	tmp.t_intrc = tty->termios.c_cc[VINTR];
 	tmp.t_quitc = tty->termios.c_cc[VQUIT];
 	tmp.t_startc = tty->termios.c_cc[VSTART];
 	tmp.t_stopc = tty->termios.c_cc[VSTOP];
 	tmp.t_eofc = tty->termios.c_cc[VEOF];
 	tmp.t_brkc = tty->termios.c_cc[VEOL2];	/* what is brkc anyway? */
-	mutex_unlock(&tty->termios_mutex);
+	up_read(&tty->termios_rwsem);
 	return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -860,14 +860,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 
 	if (copy_from_user(&tmp, tchars, sizeof(tmp)))
 		return -EFAULT;
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	tty->termios.c_cc[VINTR] = tmp.t_intrc;
 	tty->termios.c_cc[VQUIT] = tmp.t_quitc;
 	tty->termios.c_cc[VSTART] = tmp.t_startc;
 	tty->termios.c_cc[VSTOP] = tmp.t_stopc;
 	tty->termios.c_cc[VEOF] = tmp.t_eofc;
 	tty->termios.c_cc[VEOL2] = tmp.t_brkc;	/* what is brkc anyway? */
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 	return 0;
 }
 #endif
@@ -877,7 +877,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 {
 	struct ltchars tmp;
 
-	mutex_lock(&tty->termios_mutex);
+	down_read(&tty->termios_rwsem);
 	tmp.t_suspc = tty->termios.c_cc[VSUSP];
 	/* what is dsuspc anyway? */
 	tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
@@ -886,7 +886,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 	tmp.t_flushc = tty->termios.c_cc[VEOL2];
 	tmp.t_werasc = tty->termios.c_cc[VWERASE];
 	tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
-	mutex_unlock(&tty->termios_mutex);
+	up_read(&tty->termios_rwsem);
 	return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -897,7 +897,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 	if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
 		return -EFAULT;
 
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	tty->termios.c_cc[VSUSP] = tmp.t_suspc;
 	/* what is dsuspc anyway? */
 	tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
@@ -906,7 +906,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 	tty->termios.c_cc[VEOL2] = tmp.t_flushc;
 	tty->termios.c_cc[VWERASE] = tmp.t_werasc;
 	tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 	return 0;
 }
 #endif
@@ -946,7 +946,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
  *	@arg: enable/disable CLOCAL
  *
  *	Perform a change to the CLOCAL state and call into the driver
- *	layer to make it visible. All done with the termios mutex
+ *	layer to make it visible. All done with the termios rwsem
  */
 
 static int tty_change_softcar(struct tty_struct *tty, int arg)
@@ -955,7 +955,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
 	int bit = arg ? CLOCAL : 0;
 	struct ktermios old;
 
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	old = tty->termios;
 	tty->termios.c_cflag &= ~CLOCAL;
 	tty->termios.c_cflag |= bit;
@@ -963,7 +963,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
 		tty->ops->set_termios(tty, &old);
 	if ((tty->termios.c_cflag & CLOCAL) != bit)
 		ret = -EINVAL;
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 	return ret;
 }
 
@@ -1066,9 +1066,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 		if (user_termios_to_kernel_termios(&kterm,
 					       (struct termios __user *) arg))
 			return -EFAULT;
-		mutex_lock(&real_tty->termios_mutex);
+		down_write(&real_tty->termios_rwsem);
 		real_tty->termios_locked = kterm;
-		mutex_unlock(&real_tty->termios_mutex);
+		up_write(&real_tty->termios_rwsem);
 		return 0;
 #else
 	case TIOCGLCKTRMIOS:
@@ -1083,9 +1083,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 		if (user_termios_to_kernel_termios_1(&kterm,
 					       (struct termios __user *) arg))
 			return -EFAULT;
-		mutex_lock(&real_tty->termios_mutex);
+		down_write(&real_tty->termios_rwsem);
 		real_tty->termios_locked = kterm;
-		mutex_unlock(&real_tty->termios_mutex);
+		up_write(&real_tty->termios_rwsem);
 		return ret;
 #endif
 #ifdef TCGETX
@@ -1093,9 +1093,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 		struct termiox ktermx;
 		if (real_tty->termiox == NULL)
 			return -EINVAL;
-		mutex_lock(&real_tty->termios_mutex);
+		down_read(&real_tty->termios_rwsem);
 		memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
-		mutex_unlock(&real_tty->termios_mutex);
+		up_read(&real_tty->termios_rwsem);
 		if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
 			ret = -EFAULT;
 		return ret;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 1afe192..6458e11 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -31,14 +31,20 @@
 #define tty_ldisc_debug(tty, f, args...)
 #endif
 
+/* lockdep nested classes for tty->ldisc_sem */
+enum {
+	LDISC_SEM_NORMAL,
+	LDISC_SEM_OTHER,
+};
+
+
 /*
  *	This guards the refcounted line discipline lists. The lock
  *	must be taken with irqs off because there are hangup path
  *	callers who will do ldisc lookups and cannot sleep.
  */
 
-static DEFINE_RAW_SPINLOCK(tty_ldisc_lock);
-static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
@@ -52,7 +58,7 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
  *	from this point onwards.
  *
  *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
+ *		takes tty_ldiscs_lock to guard against ldisc races
  */
 
 int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
@@ -63,11 +69,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
 	if (disc < N_TTY || disc >= NR_LDISCS)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 	tty_ldiscs[disc] = new_ldisc;
 	new_ldisc->num = disc;
 	new_ldisc->refcount = 0;
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 
 	return ret;
 }
@@ -82,7 +88,7 @@ EXPORT_SYMBOL(tty_register_ldisc);
  *	currently in use.
  *
  *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
+ *		takes tty_ldiscs_lock to guard against ldisc races
  */
 
 int tty_unregister_ldisc(int disc)
@@ -93,12 +99,12 @@ int tty_unregister_ldisc(int disc)
 	if (disc < N_TTY || disc >= NR_LDISCS)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 	if (tty_ldiscs[disc]->refcount)
 		ret = -EBUSY;
 	else
 		tty_ldiscs[disc] = NULL;
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 
 	return ret;
 }
@@ -109,7 +115,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
 	unsigned long flags;
 	struct tty_ldisc_ops *ldops, *ret;
 
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 	ret = ERR_PTR(-EINVAL);
 	ldops = tty_ldiscs[disc];
 	if (ldops) {
@@ -119,7 +125,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
 			ret = ldops;
 		}
 	}
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 	return ret;
 }
 
@@ -127,10 +133,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
 {
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 	ldops->refcount--;
 	module_put(ldops->owner);
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 }
 
 /**
@@ -143,10 +149,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
  *	available
  *
  *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
+ *		takes tty_ldiscs_lock to guard against ldisc races
  */
 
-static struct tty_ldisc *tty_ldisc_get(int disc)
+static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
 {
 	struct tty_ldisc *ld;
 	struct tty_ldisc_ops *ldops;
@@ -173,8 +179,7 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
 	}
 
 	ld->ops = ldops;
-	atomic_set(&ld->users, 1);
-	init_waitqueue_head(&ld->wq_idle);
+	ld->tty = tty;
 
 	return ld;
 }
@@ -186,20 +191,11 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
  */
 static inline void tty_ldisc_put(struct tty_ldisc *ld)
 {
-	unsigned long flags;
-
 	if (WARN_ON_ONCE(!ld))
 		return;
 
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
-
-	/* unreleased reader reference(s) will cause this WARN */
-	WARN_ON(!atomic_dec_and_test(&ld->users));
-
-	ld->ops->refcount--;
-	module_put(ld->ops->owner);
+	put_ldops(ld->ops);
 	kfree(ld);
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 }
 
 static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
@@ -251,34 +247,6 @@ const struct file_operations tty_ldiscs_proc_fops = {
 };
 
 /**
- *	tty_ldisc_try		-	internal helper
- *	@tty: the tty
- *
- *	Make a single attempt to grab and bump the refcount on
- *	the tty ldisc. Return 0 on failure or 1 on success. This is
- *	used to implement both the waiting and non waiting versions
- *	of tty_ldisc_ref
- *
- *	Locking: takes tty_ldisc_lock
- */
-
-static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct tty_ldisc *ld;
-
-	/* FIXME: this allows reference acquire after TTY_LDISC is cleared */
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
-	ld = NULL;
-	if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) {
-		ld = tty->ldisc;
-		atomic_inc(&ld->users);
-	}
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	return ld;
-}
-
-/**
  *	tty_ldisc_ref_wait	-	wait for the tty ldisc
  *	@tty: tty device
  *
@@ -291,16 +259,15 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
  *	against a discipline change, such as an existing ldisc reference
  *	(which we check for)
  *
- *	Locking: call functions take tty_ldisc_lock
+ *	Note: only callable from a file_operations routine (which
+ *	guarantees tty->ldisc != NULL when the lock is acquired).
  */
 
 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
 {
-	struct tty_ldisc *ld;
-
-	/* wait_event is a macro */
-	wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
-	return ld;
+	ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT);
+	WARN_ON(!tty->ldisc);
+	return tty->ldisc;
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
 
@@ -311,13 +278,18 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
  *	Dereference the line discipline for the terminal and take a
  *	reference to it. If the line discipline is in flux then
  *	return NULL. Can be called from IRQ and timer functions.
- *
- *	Locking: called functions take tty_ldisc_lock
  */
 
 struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
 {
-	return tty_ldisc_try(tty);
+	struct tty_ldisc *ld = NULL;
+
+	if (ldsem_down_read_trylock(&tty->ldisc_sem)) {
+		ld = tty->ldisc;
+		if (!ld)
+			ldsem_up_read(&tty->ldisc_sem);
+	}
+	return ld;
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 
@@ -327,48 +299,91 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
  *
  *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
  *	be called in IRQ context.
- *
- *	Locking: takes tty_ldisc_lock
  */
 
 void tty_ldisc_deref(struct tty_ldisc *ld)
 {
-	unsigned long flags;
+	ldsem_up_read(&ld->tty->ldisc_sem);
+}
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 
-	if (WARN_ON_ONCE(!ld))
-		return;
 
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
-	/*
-	 * WARNs if one-too-many reader references were released
-	 * - the last reference must be released with tty_ldisc_put
-	 */
-	WARN_ON(atomic_dec_and_test(&ld->users));
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+static inline int __lockfunc
+tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
+{
+	return ldsem_down_write(&tty->ldisc_sem, timeout);
+}
 
-	if (waitqueue_active(&ld->wq_idle))
-		wake_up(&ld->wq_idle);
+static inline int __lockfunc
+tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout)
+{
+	return ldsem_down_write_nested(&tty->ldisc_sem,
+				       LDISC_SEM_OTHER, timeout);
 }
-EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 
-/**
- *	tty_ldisc_enable	-	allow ldisc use
- *	@tty: terminal to activate ldisc on
- *
- *	Set the TTY_LDISC flag when the line discipline can be called
- *	again. Do necessary wakeups for existing sleepers. Clear the LDISC
- *	changing flag to indicate any ldisc change is now over.
- *
- *	Note: nobody should set the TTY_LDISC bit except via this function.
- *	Clearing directly is allowed.
- */
+static inline void tty_ldisc_unlock(struct tty_struct *tty)
+{
+	return ldsem_up_write(&tty->ldisc_sem);
+}
 
-static void tty_ldisc_enable(struct tty_struct *tty)
+static int __lockfunc
+tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2,
+			    unsigned long timeout)
+{
+	int ret;
+
+	if (tty < tty2) {
+		ret = tty_ldisc_lock(tty, timeout);
+		if (ret) {
+			ret = tty_ldisc_lock_nested(tty2, timeout);
+			if (!ret)
+				tty_ldisc_unlock(tty);
+		}
+	} else {
+		/* if this is possible, it has lots of implications */
+		WARN_ON_ONCE(tty == tty2);
+		if (tty2 && tty != tty2) {
+			ret = tty_ldisc_lock(tty2, timeout);
+			if (ret) {
+				ret = tty_ldisc_lock_nested(tty, timeout);
+				if (!ret)
+					tty_ldisc_unlock(tty2);
+			}
+		} else
+			ret = tty_ldisc_lock(tty, timeout);
+	}
+
+	if (!ret)
+		return -EBUSY;
+
+	set_bit(TTY_LDISC_HALTED, &tty->flags);
+	if (tty2)
+		set_bit(TTY_LDISC_HALTED, &tty2->flags);
+	return 0;
+}
+
+static void __lockfunc
+tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2)
+{
+	tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT);
+}
+
+static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty,
+					     struct tty_struct *tty2)
+{
+	tty_ldisc_unlock(tty);
+	if (tty2)
+		tty_ldisc_unlock(tty2);
+}
+
+static void __lockfunc tty_ldisc_enable_pair(struct tty_struct *tty,
+					     struct tty_struct *tty2)
 {
 	clear_bit(TTY_LDISC_HALTED, &tty->flags);
-	set_bit(TTY_LDISC, &tty->flags);
-	clear_bit(TTY_LDISC_CHANGING, &tty->flags);
-	wake_up(&tty_ldisc_wait);
+	if (tty2)
+		clear_bit(TTY_LDISC_HALTED, &tty2->flags);
+
+	tty_ldisc_unlock_pair(tty, tty2);
 }
 
 /**
@@ -400,14 +415,14 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
  *	they are not on hot paths so a little discipline won't do
  *	any harm.
  *
- *	Locking: takes termios_mutex
+ *	Locking: takes termios_rwsem
  */
 
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 {
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	tty->termios.c_line = num;
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 }
 
 /**
@@ -468,14 +483,14 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 	int r;
 
 	/* There is an outstanding reference here so this is safe */
-	old = tty_ldisc_get(old->ops->num);
+	old = tty_ldisc_get(tty, old->ops->num);
 	WARN_ON(IS_ERR(old));
 	tty->ldisc = old;
 	tty_set_termios_ldisc(tty, old->ops->num);
 	if (tty_ldisc_open(tty, old) < 0) {
 		tty_ldisc_put(old);
 		/* This driver is always present */
-		new_ldisc = tty_ldisc_get(N_TTY);
+		new_ldisc = tty_ldisc_get(tty, N_TTY);
 		if (IS_ERR(new_ldisc))
 			panic("n_tty: get");
 		tty->ldisc = new_ldisc;
@@ -489,101 +504,6 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 }
 
 /**
- *	tty_ldisc_wait_idle	-	wait for the ldisc to become idle
- *	@tty: tty to wait for
- *	@timeout: for how long to wait at most
- *
- *	Wait for the line discipline to become idle. The discipline must
- *	have been halted for this to guarantee it remains idle.
- */
-static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
-{
-	long ret;
-	ret = wait_event_timeout(tty->ldisc->wq_idle,
-			atomic_read(&tty->ldisc->users) == 1, timeout);
-	return ret > 0 ? 0 : -EBUSY;
-}
-
-/**
- *	tty_ldisc_halt		-	shut down the line discipline
- *	@tty: tty device
- *	@o_tty: paired pty device (can be NULL)
- *	@timeout: # of jiffies to wait for ldisc refs to be released
- *
- *	Shut down the line discipline and work queue for this tty device and
- *	its paired pty (if exists). Clearing the TTY_LDISC flag ensures
- *	no further references can be obtained, while waiting for existing
- *	references to be released ensures no more data is fed to the ldisc.
- *
- *	You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
- *	in order to make sure any currently executing ldisc work is also
- *	flushed.
- */
-
-static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty,
-			  long timeout)
-{
-	int retval;
-
-	clear_bit(TTY_LDISC, &tty->flags);
-	if (o_tty)
-		clear_bit(TTY_LDISC, &o_tty->flags);
-
-	retval = tty_ldisc_wait_idle(tty, timeout);
-	if (!retval && o_tty)
-		retval = tty_ldisc_wait_idle(o_tty, timeout);
-	if (retval)
-		return retval;
-
-	set_bit(TTY_LDISC_HALTED, &tty->flags);
-	if (o_tty)
-		set_bit(TTY_LDISC_HALTED, &o_tty->flags);
-
-	return 0;
-}
-
-/**
- *	tty_ldisc_hangup_halt - halt the line discipline for hangup
- *	@tty: tty being hung up
- *
- *	Shut down the line discipline and work queue for the tty device
- *	being hungup. Clear the TTY_LDISC flag to ensure no further
- *	references can be obtained and wait for remaining references to be
- *	released to ensure no more data is fed to this ldisc.
- *	Caller must hold legacy and ->ldisc_mutex.
- *
- *	NB: tty_set_ldisc() is prevented from changing the ldisc concurrently
- *	with this function by checking the TTY_HUPPING flag.
- */
-static bool tty_ldisc_hangup_halt(struct tty_struct *tty)
-{
-	char cur_n[TASK_COMM_LEN], tty_n[64];
-	long timeout = 3 * HZ;
-
-	clear_bit(TTY_LDISC, &tty->flags);
-
-	if (tty->ldisc) {	/* Not yet closed */
-		tty_unlock(tty);
-
-		while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
-			timeout = MAX_SCHEDULE_TIMEOUT;
-			printk_ratelimited(KERN_WARNING
-				"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
-				__func__, get_task_comm(cur_n, current),
-				tty_name(tty, tty_n));
-		}
-
-		set_bit(TTY_LDISC_HALTED, &tty->flags);
-
-		/* must reacquire both locks and preserve lock order */
-		mutex_unlock(&tty->ldisc_mutex);
-		tty_lock(tty);
-		mutex_lock(&tty->ldisc_mutex);
-	}
-	return !!tty->ldisc;
-}
-
-/**
  *	tty_set_ldisc		-	set line discipline
  *	@tty: the terminal to set
  *	@ldisc: the line discipline
@@ -592,110 +512,49 @@ static bool tty_ldisc_hangup_halt(struct tty_struct *tty)
  *	context. The ldisc change logic has to protect itself against any
  *	overlapping ldisc change (including on the other end of pty pairs),
  *	the close of one side of a tty/pty pair, and eventually hangup.
- *
- *	Locking: takes tty_ldisc_lock, termios_mutex
  */
 
 int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
 	int retval;
-	struct tty_ldisc *o_ldisc, *new_ldisc;
-	struct tty_struct *o_tty;
+	struct tty_ldisc *old_ldisc, *new_ldisc;
+	struct tty_struct *o_tty = tty->link;
 
-	new_ldisc = tty_ldisc_get(ldisc);
+	new_ldisc = tty_ldisc_get(tty, ldisc);
 	if (IS_ERR(new_ldisc))
 		return PTR_ERR(new_ldisc);
 
-	tty_lock(tty);
-	/*
-	 *	We need to look at the tty locking here for pty/tty pairs
-	 *	when both sides try to change in parallel.
-	 */
-
-	o_tty = tty->link;	/* o_tty is the pty side or NULL */
-
+	retval = tty_ldisc_lock_pair_timeout(tty, o_tty, 5 * HZ);
+	if (retval) {
+		tty_ldisc_put(new_ldisc);
+		return retval;
+	}
 
 	/*
 	 *	Check the no-op case
 	 */
 
 	if (tty->ldisc->ops->num == ldisc) {
-		tty_unlock(tty);
+		tty_ldisc_enable_pair(tty, o_tty);
 		tty_ldisc_put(new_ldisc);
 		return 0;
 	}
 
-	mutex_lock(&tty->ldisc_mutex);
-
-	/*
-	 *	We could be midstream of another ldisc change which has
-	 *	dropped the lock during processing. If so we need to wait.
-	 */
-
-	while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
-		mutex_unlock(&tty->ldisc_mutex);
-		tty_unlock(tty);
-		wait_event(tty_ldisc_wait,
-			test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
-		tty_lock(tty);
-		mutex_lock(&tty->ldisc_mutex);
-	}
-
-	set_bit(TTY_LDISC_CHANGING, &tty->flags);
-
-	/*
-	 *	No more input please, we are switching. The new ldisc
-	 *	will update this value in the ldisc open function
-	 */
-
-	tty->receive_room = 0;
-
-	o_ldisc = tty->ldisc;
-
-	tty_unlock(tty);
-	/*
-	 *	Make sure we don't change while someone holds a
-	 *	reference to the line discipline. The TTY_LDISC bit
-	 *	prevents anyone taking a reference once it is clear.
-	 *	We need the lock to avoid racing reference takers.
-	 *
-	 *	We must clear the TTY_LDISC bit here to avoid a livelock
-	 *	with a userspace app continually trying to use the tty in
-	 *	parallel to the change and re-referencing the tty.
-	 */
-
-	retval = tty_ldisc_halt(tty, o_tty, 5 * HZ);
-
-	/*
-	 * Wait for hangup to complete, if pending.
-	 * We must drop the mutex here in case a hangup is also in process.
-	 */
-
-	mutex_unlock(&tty->ldisc_mutex);
-
-	flush_work(&tty->hangup_work);
-
+	old_ldisc = tty->ldisc;
 	tty_lock(tty);
-	mutex_lock(&tty->ldisc_mutex);
-
-	/* handle wait idle failure locked */
-	if (retval) {
-		tty_ldisc_put(new_ldisc);
-		goto enable;
-	}
 
-	if (test_bit(TTY_HUPPING, &tty->flags)) {
+	if (test_bit(TTY_HUPPING, &tty->flags) ||
+	    test_bit(TTY_HUPPED, &tty->flags)) {
 		/* We were raced by the hangup method. It will have stomped
 		   the ldisc data and closed the ldisc down */
-		clear_bit(TTY_LDISC_CHANGING, &tty->flags);
-		mutex_unlock(&tty->ldisc_mutex);
+		tty_ldisc_enable_pair(tty, o_tty);
 		tty_ldisc_put(new_ldisc);
 		tty_unlock(tty);
 		return -EIO;
 	}
 
-	/* Shutdown the current discipline. */
-	tty_ldisc_close(tty, o_ldisc);
+	/* Shutdown the old discipline. */
+	tty_ldisc_close(tty, old_ldisc);
 
 	/* Now set up the new line discipline. */
 	tty->ldisc = new_ldisc;
@@ -705,26 +564,24 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	if (retval < 0) {
 		/* Back to the old one or N_TTY if we can't */
 		tty_ldisc_put(new_ldisc);
-		tty_ldisc_restore(tty, o_ldisc);
+		tty_ldisc_restore(tty, old_ldisc);
 	}
 
-	/* At this point we hold a reference to the new ldisc and a
-	   a reference to the old ldisc. If we ended up flipping back
-	   to the existing ldisc we have two references to it */
-
-	if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc)
+	if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc)
 		tty->ops->set_ldisc(tty);
 
-	tty_ldisc_put(o_ldisc);
+	/* At this point we hold a reference to the new ldisc and a
+	   reference to the old ldisc, or we hold two references to
+	   the old ldisc (if it was restored as part of error cleanup
+	   above). In either case, releasing a single reference from
+	   the old ldisc is correct. */
+
+	tty_ldisc_put(old_ldisc);
 
-enable:
 	/*
 	 *	Allow ldisc referencing to occur again
 	 */
-
-	tty_ldisc_enable(tty);
-	if (o_tty)
-		tty_ldisc_enable(o_tty);
+	tty_ldisc_enable_pair(tty, o_tty);
 
 	/* Restart the work queue in case no characters kick it off. Safe if
 	   already running */
@@ -732,7 +589,6 @@ enable:
 	if (o_tty)
 		schedule_work(&o_tty->port->buf.work);
 
-	mutex_unlock(&tty->ldisc_mutex);
 	tty_unlock(tty);
 	return retval;
 }
@@ -746,11 +602,11 @@ enable:
 
 static void tty_reset_termios(struct tty_struct *tty)
 {
-	mutex_lock(&tty->termios_mutex);
+	down_write(&tty->termios_rwsem);
 	tty->termios = tty->driver->init_termios;
 	tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
 	tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
-	mutex_unlock(&tty->termios_mutex);
+	up_write(&tty->termios_rwsem);
 }
 
 
@@ -765,7 +621,7 @@ static void tty_reset_termios(struct tty_struct *tty)
 
 static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 {
-	struct tty_ldisc *ld = tty_ldisc_get(ldisc);
+	struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc);
 
 	if (IS_ERR(ld))
 		return -1;
@@ -804,14 +660,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 
 	tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 
-	/*
-	 * FIXME! What are the locking issues here? This may me overdoing
-	 * things... This question is especially important now that we've
-	 * removed the irqlock.
-	 */
 	ld = tty_ldisc_ref(tty);
 	if (ld != NULL) {
-		/* We may have no line discipline at this point */
 		if (ld->ops->flush_buffer)
 			ld->ops->flush_buffer(tty);
 		tty_driver_flush_buffer(tty);
@@ -822,21 +672,22 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 			ld->ops->hangup(tty);
 		tty_ldisc_deref(ld);
 	}
-	/*
-	 * FIXME: Once we trust the LDISC code better we can wait here for
-	 * ldisc completion and fix the driver call race
-	 */
+
 	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
 	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+
+	tty_unlock(tty);
+
 	/*
 	 * Shutdown the current line discipline, and reset it to
 	 * N_TTY if need be.
 	 *
 	 * Avoid racing set_ldisc or tty_ldisc_release
 	 */
-	mutex_lock(&tty->ldisc_mutex);
+	tty_ldisc_lock_pair(tty, tty->link);
+	tty_lock(tty);
 
-	if (tty_ldisc_hangup_halt(tty)) {
+	if (tty->ldisc) {
 
 		/* At this point we have a halted ldisc; we want to close it and
 		   reopen a new ldisc. We could defer the reopen to the next
@@ -855,9 +706,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 			BUG_ON(tty_ldisc_reinit(tty, N_TTY));
 			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
 		}
-		tty_ldisc_enable(tty);
 	}
-	mutex_unlock(&tty->ldisc_mutex);
+	tty_ldisc_enable_pair(tty, tty->link);
 	if (reset)
 		tty_reset_termios(tty);
 
@@ -889,15 +739,12 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 			tty_ldisc_close(tty, ld);
 			return retval;
 		}
-		tty_ldisc_enable(o_tty);
 	}
-	tty_ldisc_enable(tty);
 	return 0;
 }
 
 static void tty_ldisc_kill(struct tty_struct *tty)
 {
-	mutex_lock(&tty->ldisc_mutex);
 	/*
 	 * Now kill off the ldisc
 	 */
@@ -908,7 +755,6 @@ static void tty_ldisc_kill(struct tty_struct *tty)
 
 	/* Ensure the next open requests the N_TTY ldisc */
 	tty_set_termios_ldisc(tty, N_TTY);
-	mutex_unlock(&tty->ldisc_mutex);
 }
 
 /**
@@ -930,15 +776,16 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 
 	tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 
-	tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT);
-
+	tty_ldisc_lock_pair(tty, o_tty);
 	tty_lock_pair(tty, o_tty);
-	/* This will need doing differently if we need to lock */
+
 	tty_ldisc_kill(tty);
 	if (o_tty)
 		tty_ldisc_kill(o_tty);
 
 	tty_unlock_pair(tty, o_tty);
+	tty_ldisc_unlock_pair(tty, o_tty);
+
 	/* And the memory resources remaining (buffers, termios) will be
 	   disposed of when the kref hits zero */
 
@@ -955,7 +802,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 
 void tty_ldisc_init(struct tty_struct *tty)
 {
-	struct tty_ldisc *ld = tty_ldisc_get(N_TTY);
+	struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
 	if (IS_ERR(ld))
 		panic("n_tty: init_tty");
 	tty->ldisc = ld;
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index a9af1b9a..d0e3a44 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -132,12 +132,6 @@ static int shift_state = 0;
 static unsigned char ledstate = 0xff;			/* undefined */
 static unsigned char ledioctl;
 
-static struct ledptr {
-	unsigned int *addr;
-	unsigned int mask;
-	unsigned char valid:1;
-} ledptrs[3];
-
 /*
  * Notifier list for console keyboard events
  */
@@ -994,24 +988,11 @@ void setledstate(struct kbd_struct *kbd, unsigned int led)
 static inline unsigned char getleds(void)
 {
 	struct kbd_struct *kbd = kbd_table + fg_console;
-	unsigned char leds;
-	int i;
 
 	if (kbd->ledmode == LED_SHOW_IOCTL)
 		return ledioctl;
 
-	leds = kbd->ledflagstate;
-
-	if (kbd->ledmode == LED_SHOW_MEM) {
-		for (i = 0; i < 3; i++)
-			if (ledptrs[i].valid) {
-				if (*ledptrs[i].addr & ledptrs[i].mask)
-					leds |= (1 << i);
-				else
-					leds &= ~(1 << i);
-			}
-	}
-	return leds;
+	return kbd->ledflagstate;
 }
 
 static int kbd_update_leds_helper(struct input_handle *handle, void *data)
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 60b7b69..ea27804 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -24,6 +24,7 @@
 #include <linux/selection.h>
 #include <linux/tiocl.h>
 #include <linux/console.h>
+#include <linux/tty_flip.h>
 
 /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
 #define isspace(c)	((c) == ' ')
@@ -346,8 +347,8 @@ int paste_selection(struct tty_struct *tty)
 	console_unlock();
 
 	ld = tty_ldisc_ref_wait(tty);
+	tty_buffer_lock_exclusive(&vc->port);
 
-	/* FIXME: this is completely unsafe */
 	add_wait_queue(&vc->paste_wait, &wait);
 	while (sel_buffer && sel_buffer_lth > pasted) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -356,13 +357,14 @@ int paste_selection(struct tty_struct *tty)
 			continue;
 		}
 		count = sel_buffer_lth - pasted;
-		count = min(count, tty->receive_room);
-		ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count);
+		count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
+					      count);
 		pasted += count;
 	}
 	remove_wait_queue(&vc->paste_wait, &wait);
 	__set_current_state(TASK_RUNNING);
 
+	tty_buffer_unlock_exclusive(&vc->port);
 	tty_ldisc_deref(ld);
 	return 0;
 }
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index c677829..9a8e8c5 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -828,7 +828,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
  *	If the caller passes a tty structure then update the termios winsize
  *	information and perform any necessary signal handling.
  *
- *	Caller must hold the console semaphore. Takes the termios mutex and
+ *	Caller must hold the console semaphore. Takes the termios rwsem and
  *	ctrl_lock of the tty IFF a tty is passed.
  */
 
@@ -972,7 +972,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
  *	the actual work.
  *
  *	Takes the console sem and the called methods then take the tty
- *	termios_mutex and the tty ctrl_lock in that order.
+ *	termios_rwsem and the tty ctrl_lock in that order.
  */
 static int vt_resize(struct tty_struct *tty, struct winsize *ws)
 {
@@ -2809,8 +2809,10 @@ static void con_shutdown(struct tty_struct *tty)
 	console_unlock();
 }
 
+static int default_color           = 7; /* white */
 static int default_italic_color    = 2; // green (ASCII)
 static int default_underline_color = 3; // cyan (ASCII)
+module_param_named(color, default_color, int, S_IRUGO | S_IWUSR);
 module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR);
 module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR);
 
@@ -2832,7 +2834,7 @@ static void vc_init(struct vc_data *vc, unsigned int rows,
 		vc->vc_palette[k++] = default_grn[j] ;
 		vc->vc_palette[k++] = default_blu[j] ;
 	}
-	vc->vc_def_color       = 0x07;   /* white */
+	vc->vc_def_color       = default_color;
 	vc->vc_ulcolor         = default_underline_color;
 	vc->vc_itcolor         = default_italic_color;
 	vc->vc_halfcolor       = 0x08;   /* grey */
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 5295be0..a81d163 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -23,13 +23,6 @@ config UIO_CIF
 	  To compile this driver as a module, choose M here: the module
 	  will be called uio_cif.
 
-config UIO_PDRV
-	tristate "Userspace I/O platform driver"
-	help
-	  Generic platform driver for Userspace I/O devices.
-
-	  If you don't know what to do here, say N.
-
 config UIO_PDRV_GENIRQ
 	tristate "Userspace I/O platform driver with generic IRQ handling"
 	help
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index b354c53..ea015a2 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -1,6 +1,5 @@
 obj-$(CONFIG_UIO)	+= uio.o
 obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
-obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)	+= uio_pdrv_genirq.o
 obj-$(CONFIG_UIO_DMEM_GENIRQ)	+= uio_dmem_genirq.o
 obj-$(CONFIG_UIO_AEC)	+= uio_aec.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 3b96f18..170a178 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -224,38 +224,42 @@ static struct kobj_type portio_attr_type = {
 	.default_attrs	= portio_attrs,
 };
 
-static ssize_t show_name(struct device *dev,
+static ssize_t name_show(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
 	return sprintf(buf, "%s\n", idev->info->name);
 }
+static DEVICE_ATTR_RO(name);
 
-static ssize_t show_version(struct device *dev,
+static ssize_t version_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
 	return sprintf(buf, "%s\n", idev->info->version);
 }
+static DEVICE_ATTR_RO(version);
 
-static ssize_t show_event(struct device *dev,
+static ssize_t event_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
 }
+static DEVICE_ATTR_RO(event);
 
-static struct device_attribute uio_class_attributes[] = {
-	__ATTR(name, S_IRUGO, show_name, NULL),
-	__ATTR(version, S_IRUGO, show_version, NULL),
-	__ATTR(event, S_IRUGO, show_event, NULL),
-	{}
+static struct attribute *uio_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_version.attr,
+	&dev_attr_event.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(uio);
 
 /* UIO class infrastructure */
 static struct class uio_class = {
 	.name = "uio",
-	.dev_attrs = uio_class_attributes,
+	.dev_groups = uio_groups,
 };
 
 /*
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
deleted file mode 100644
index 39be9e0..0000000
--- a/drivers/uio/uio_pdrv.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * drivers/uio/uio_pdrv.c
- *
- * Copyright (C) 2008 by Digi International Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-#include <linux/platform_device.h>
-#include <linux/uio_driver.h>
-#include <linux/stringify.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#define DRIVER_NAME "uio_pdrv"
-
-struct uio_platdata {
-	struct uio_info *uioinfo;
-};
-
-static int uio_pdrv_probe(struct platform_device *pdev)
-{
-	struct uio_info *uioinfo = pdev->dev.platform_data;
-	struct uio_platdata *pdata;
-	struct uio_mem *uiomem;
-	int ret = -ENODEV;
-	int i;
-
-	if (!uioinfo || !uioinfo->name || !uioinfo->version) {
-		dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
-		goto err_uioinfo;
-	}
-
-	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
-	if (!pdata) {
-		ret = -ENOMEM;
-		dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
-		goto err_alloc_pdata;
-	}
-
-	pdata->uioinfo = uioinfo;
-
-	uiomem = &uioinfo->mem[0];
-
-	for (i = 0; i < pdev->num_resources; ++i) {
-		struct resource *r = &pdev->resource[i];
-
-		if (r->flags != IORESOURCE_MEM)
-			continue;
-
-		if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
-			dev_warn(&pdev->dev, "device has more than "
-					__stringify(MAX_UIO_MAPS)
-					" I/O memory resources.\n");
-			break;
-		}
-
-		uiomem->memtype = UIO_MEM_PHYS;
-		uiomem->addr = r->start;
-		uiomem->size = resource_size(r);
-		uiomem->name = r->name;
-		++uiomem;
-	}
-
-	while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
-		uiomem->size = 0;
-		++uiomem;
-	}
-
-	pdata->uioinfo->priv = pdata;
-
-	ret = uio_register_device(&pdev->dev, pdata->uioinfo);
-
-	if (ret) {
-		kfree(pdata);
-err_alloc_pdata:
-err_uioinfo:
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, pdata);
-
-	return 0;
-}
-
-static int uio_pdrv_remove(struct platform_device *pdev)
-{
-	struct uio_platdata *pdata = platform_get_drvdata(pdev);
-
-	uio_unregister_device(pdata->uioinfo);
-
-	kfree(pdata);
-
-	return 0;
-}
-
-static struct platform_driver uio_pdrv = {
-	.probe = uio_pdrv_probe,
-	.remove = uio_pdrv_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-	},
-};
-
-module_platform_driver(uio_pdrv);
-
-MODULE_AUTHOR("Uwe Kleine-Koenig");
-MODULE_DESCRIPTION("Userspace I/O platform driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 238c5d4..70d7c5b 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_USB_ISP1760_HCD)	+= host/
 obj-$(CONFIG_USB_IMX21_HCD)	+= host/
 obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= host/
 obj-$(CONFIG_USB_FUSBH200_HCD)	+= host/
+obj-$(CONFIG_USB_FOTG210_HCD)	+= host/
 
 obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/
 
@@ -45,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 obj-$(CONFIG_USB)		+= misc/
-obj-$(CONFIG_USB_PHY)		+= phy/
+obj-$(CONFIG_USB_SUPPORT)	+= phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile
index a5d792e..ac27894 100644
--- a/drivers/usb/atm/Makefile
+++ b/drivers/usb/atm/Makefile
@@ -1,9 +1,6 @@
 #
 # Makefile for USB ATM/xDSL drivers
 #
-
-ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
-
 obj-$(CONFIG_USB_CXACRU)	+= cxacru.o
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= speedtch.o
 obj-$(CONFIG_USB_UEAGLEATM)	+= ueagle-atm.o
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 807627b..69461d6 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -888,7 +888,7 @@ static int speedtch_bind(struct usbatm_data *usbatm,
 		usb_fill_int_urb(instance->int_urb, usb_dev,
 				 usb_rcvintpipe(usb_dev, ENDPOINT_INT),
 				 instance->int_data, sizeof(instance->int_data),
-				 speedtch_handle_int, instance, 50);
+				 speedtch_handle_int, instance, 16);
 	else
 		usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__);
 
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 5e0d33a..25a7bfc 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -311,8 +311,6 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
 	int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
 	u8 pti = ((source[3] & 0xe) >> 1);
 
-	vdbg(&instance->usb_intf->dev, "%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
-
 	if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
 		instance->cached_vpi = vpi;
 		instance->cached_vci = vci;
@@ -344,7 +342,6 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
 				__func__, sarb->len, vcc);
 		/* discard cells already received */
 		skb_trim(sarb, 0);
-		UDSL_ASSERT(instance, sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
 	}
 
 	memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
@@ -437,8 +434,6 @@ static void usbatm_extract_cells(struct usbatm_data *instance,
 		unsigned char *cell_buf = instance->cell_buf;
 		unsigned int space_left = stride - buf_usage;
 
-		UDSL_ASSERT(instance, buf_usage <= stride);
-
 		if (avail_data >= space_left) {
 			/* add new data and process cell */
 			memcpy(cell_buf + buf_usage, source, space_left);
@@ -479,10 +474,6 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
 	unsigned int bytes_written;
 	unsigned int stride = instance->tx_channel.stride;
 
-	vdbg(&instance->usb_intf->dev, "%s: skb->len=%d, avail_space=%u",
-	     __func__, skb->len, avail_space);
-	UDSL_ASSERT(instance, !(avail_space % stride));
-
 	for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
 	     bytes_written += stride, target += stride) {
 		unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);
@@ -553,8 +544,6 @@ static void usbatm_rx_process(unsigned long data)
 				if (!urb->iso_frame_desc[i].status) {
 					unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
 
-					UDSL_ASSERT(instance, actual_length <= packet_size);
-
 					if (!merge_length)
 						merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 					merge_length += actual_length;
@@ -645,7 +634,6 @@ static void usbatm_cancel_send(struct usbatm_data *instance,
 {
 	struct sk_buff *skb, *n;
 
-	atm_dbg(instance, "%s entered\n", __func__);
 	spin_lock_irq(&instance->sndqueue.lock);
 	skb_queue_walk_safe(&instance->sndqueue, skb, n) {
 		if (UDSL_SKB(skb)->atm.vcc == vcc) {
@@ -663,7 +651,6 @@ static void usbatm_cancel_send(struct usbatm_data *instance,
 		usbatm_pop(vcc, skb);
 	}
 	tasklet_enable(&instance->tx_channel.tasklet);
-	atm_dbg(instance, "%s done\n", __func__);
 }
 
 static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
@@ -674,16 +661,13 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 
 	/* racy disconnection check - fine */
 	if (!instance || instance->disconnected) {
-#ifdef DEBUG
+#ifdef VERBOSE_DEBUG
 		printk_ratelimited(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
 #endif
 		err = -ENODEV;
 		goto fail;
 	}
 
-	vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
-	     skb, skb->len);
-
 	if (vcc->qos.aal != ATM_AAL5) {
 		atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
 		err = -EINVAL;
@@ -723,8 +707,6 @@ static void usbatm_destroy_instance(struct kref *kref)
 {
 	struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount);
 
-	usb_dbg(instance, "%s\n", __func__);
-
 	tasklet_kill(&instance->rx_channel.tasklet);
 	tasklet_kill(&instance->tx_channel.tasklet);
 	usb_put_dev(instance->usb_dev);
@@ -733,15 +715,11 @@ static void usbatm_destroy_instance(struct kref *kref)
 
 static void usbatm_get_instance(struct usbatm_data *instance)
 {
-	usb_dbg(instance, "%s\n", __func__);
-
 	kref_get(&instance->refcount);
 }
 
 static void usbatm_put_instance(struct usbatm_data *instance)
 {
-	usb_dbg(instance, "%s\n", __func__);
-
 	kref_put(&instance->refcount, usbatm_destroy_instance);
 }
 
@@ -757,7 +735,6 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
 	if (!instance)
 		return;
 
-	usb_dbg(instance, "%s\n", __func__);
 	atm_dev->dev_data = NULL; /* catch bugs */
 	usbatm_put_instance(instance);	/* taken in usbatm_atm_init */
 }
@@ -813,8 +790,6 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
 	if (!instance)
 		return -ENODEV;
 
-	atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
-
 	/* only support AAL5 */
 	if ((vcc->qos.aal != ATM_AAL5)) {
 		atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
@@ -891,11 +866,6 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
 	if (!instance || !vcc_data)
 		return;
 
-	atm_dbg(instance, "%s entered\n", __func__);
-
-	atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n",
-		__func__, vcc_data, vcc_data->vpi, vcc_data->vci);
-
 	usbatm_cancel_send(instance, vcc);
 
 	mutex_lock(&instance->serialize);	/* vs self, usbatm_atm_open, usbatm_usb_disconnect */
@@ -922,8 +892,6 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
 	clear_bit(ATM_VF_ADDR, &vcc->flags);
 
 	mutex_unlock(&instance->serialize);
-
-	atm_dbg(instance, "%s successful\n", __func__);
 }
 
 static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
@@ -1060,12 +1028,6 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
 	int i, length;
 	unsigned int maxpacket, num_packets;
 
-	dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
-			__func__, driver->driver_name,
-			le16_to_cpu(usb_dev->descriptor.idVendor),
-			le16_to_cpu(usb_dev->descriptor.idProduct),
-			intf->altsetting->desc.bInterfaceNumber);
-
 	/* instance init */
 	instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
 	if (!instance) {
@@ -1158,14 +1120,13 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
 	instance->rx_channel.buf_size = num_packets * maxpacket;
 	instance->rx_channel.packet_size = maxpacket;
 
-#ifdef DEBUG
 	for (i = 0; i < 2; i++) {
 		struct usbatm_channel *channel = i ?
 			&instance->tx_channel : &instance->rx_channel;
 
-		dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);
+		dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n",
+			__func__, channel->buf_size, i ? "tx" : "rx", channel);
 	}
-#endif
 
 	/* initialize urbs */
 
@@ -1176,8 +1137,6 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
 		struct urb *urb;
 		unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
 
-		UDSL_ASSERT(instance, !usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
-
 		urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
 		if (!urb) {
 			dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
@@ -1266,8 +1225,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
 	struct usbatm_vcc_data *vcc_data;
 	int i;
 
-	dev_dbg(dev, "%s entered\n", __func__);
-
 	if (!instance) {
 		dev_dbg(dev, "%s: NULL instance!\n", __func__);
 		return;
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index 5fc4894..5651231 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -39,31 +39,14 @@
 #define VERBOSE_DEBUG
 */
 
-#ifdef DEBUG
-#define UDSL_ASSERT(instance, x)	BUG_ON(!(x))
-#else
-#define UDSL_ASSERT(instance, x)					\
-	do {	\
-		if (!(x))						\
-			dev_warn(&(instance)->usb_intf->dev,		\
-				 "failed assertion '%s' at line %d",	\
-				 __stringify(x), __LINE__);		\
-	} while (0)
-#endif
-
 #define usb_err(instance, format, arg...)	\
 	dev_err(&(instance)->usb_intf->dev , format , ## arg)
 #define usb_info(instance, format, arg...)	\
 	dev_info(&(instance)->usb_intf->dev , format , ## arg)
 #define usb_warn(instance, format, arg...)	\
 	dev_warn(&(instance)->usb_intf->dev , format , ## arg)
-#ifdef DEBUG
-#define usb_dbg(instance, format, arg...)	\
-	dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
-#else
 #define usb_dbg(instance, format, arg...)	\
-	do {} while (0)
-#endif
+	dev_dbg(&(instance)->usb_intf->dev , format , ## arg)
 
 /* FIXME: move to dev_* once ATM is driver model aware */
 #define atm_printk(level, instance, format, arg...)	\
@@ -76,18 +59,12 @@
 	atm_printk(KERN_INFO, instance , format , ## arg)
 #define atm_warn(instance, format, arg...)	\
 	atm_printk(KERN_WARNING, instance , format , ## arg)
-#ifdef DEBUG
-#define atm_dbg(instance, format, arg...)	\
-	atm_printk(KERN_DEBUG, instance , format , ## arg)
-#define atm_rldbg(instance, format, arg...)	\
+#define atm_dbg(instance, format, arg...)		\
+	dynamic_pr_debug("ATM dev %d: " format ,	\
+	(instance)->atm_dev->number , ## arg)
+#define atm_rldbg(instance, format, arg...)		\
 	if (printk_ratelimit())				\
-		atm_printk(KERN_DEBUG, instance , format , ## arg)
-#else
-#define atm_dbg(instance, format, arg...)	\
-	do {} while (0)
-#define atm_rldbg(instance, format, arg...)	\
-	do {} while (0)
-#endif
+		atm_dbg(instance , format , ## arg)
 
 
 /* flags, set by mini-driver in bind() */
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index fe815ec..8db3380 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -131,7 +131,7 @@ static int c67x00_drv_probe(struct platform_device *pdev)
 	if (!res2)
 		return -ENODEV;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata)
 		return -ENODEV;
 
@@ -154,7 +154,7 @@ static int c67x00_drv_probe(struct platform_device *pdev)
 
 	spin_lock_init(&c67x00->hpi.lock);
 	c67x00->hpi.regstep = pdata->hpi_regstep;
-	c67x00->pdata = pdev->dev.platform_data;
+	c67x00->pdata = dev_get_platdata(&pdev->dev);
 	c67x00->pdev = pdev;
 
 	c67x00_ll_init(c67x00);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9f49bfe..3e7560f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1295,7 +1295,7 @@ skip_countries:
 			 usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
 			 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm,
 			 /* works around buggy devices */
-			 epctrl->bInterval ? epctrl->bInterval : 0xff);
+			 epctrl->bInterval ? epctrl->bInterval : 16);
 	acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	acm->ctrlurb->transfer_dma = acm->ctrl_dma;
 
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 609dbc2..60dd891 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -19,6 +19,8 @@
  * http://www.gnu.org/copyleft/gpl.html.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -119,7 +121,6 @@ static void usbtmc_delete(struct kref *kref)
 	struct usbtmc_device_data *data = to_usbtmc_data(kref);
 
 	usb_put_dev(data->usb_dev);
-	kfree(data);
 }
 
 static int usbtmc_open(struct inode *inode, struct file *filp)
@@ -130,10 +131,8 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
 
 	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;
+		pr_err("can not find device for minor %d", iminor(inode));
+		return -ENODEV;
 	}
 
 	data = usb_get_intfdata(intf);
@@ -142,7 +141,6 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
 	/* Store pointer in file structure's private data field */
 	filp->private_data = data;
 
-exit:
 	return retval;
 }
 
@@ -394,12 +392,12 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
 	 */
 	buffer[0] = 2;
 	buffer[1] = data->bTag;
-	buffer[2] = ~(data->bTag);
+	buffer[2] = ~data->bTag;
 	buffer[3] = 0; /* Reserved */
-	buffer[4] = (transfer_size) & 255;
-	buffer[5] = ((transfer_size) >> 8) & 255;
-	buffer[6] = ((transfer_size) >> 16) & 255;
-	buffer[7] = ((transfer_size) >> 24) & 255;
+	buffer[4] = transfer_size >> 0;
+	buffer[5] = transfer_size >> 8;
+	buffer[6] = transfer_size >> 16;
+	buffer[7] = transfer_size >> 24;
 	buffer[8] = data->TermCharEnabled * 2;
 	/* Use term character? */
 	buffer[9] = data->TermChar;
@@ -418,7 +416,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
 	/* Increment bTag -- and increment again if zero */
 	data->bTag++;
 	if (!data->bTag)
-		(data->bTag)++;
+		data->bTag++;
 
 	if (retval < 0) {
 		dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval);
@@ -473,7 +471,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
 	done = 0;
 
 	while (remaining > 0) {
-		if (!(data->rigol_quirk)) {
+		if (!data->rigol_quirk) {
 			dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count);
 
 			if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3)
@@ -510,7 +508,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
 		}
 
 		/* Parse header in first packet */
-		if ((done == 0) || (!(data->rigol_quirk))) {
+		if ((done == 0) || !data->rigol_quirk) {
 			/* Sanity checks for the header */
 			if (actual < USBTMC_HEADER_SIZE) {
 				dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE);
@@ -554,14 +552,14 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
 				if (remaining > n_characters)
 					remaining = n_characters;
 				/* Remove padding if it exists */
-				if (actual > remaining) 
+				if (actual > remaining)
 					actual = remaining;
 			}
 			else {
 				if (this_part > n_characters)
 					this_part = n_characters;
 				/* Remove padding if it exists */
-				if (actual > this_part) 
+				if (actual > this_part)
 					actual = this_part;
 			}
 
@@ -570,7 +568,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
 			remaining -= actual;
 
 			/* Terminate if end-of-message bit received from device */
-			if ((buffer[8] &  0x01) && (actual >= n_characters))
+			if ((buffer[8] & 0x01) && (actual >= n_characters))
 				remaining = 0;
 
 			dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done);
@@ -585,7 +583,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
 			done += actual;
 		}
 		else  {
-			if (actual > remaining) 
+			if (actual > remaining)
 				actual = remaining;
 
 			remaining -= actual;
@@ -651,12 +649,12 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
 		/* Setup IO buffer for DEV_DEP_MSG_OUT message */
 		buffer[0] = 1;
 		buffer[1] = data->bTag;
-		buffer[2] = ~(data->bTag);
+		buffer[2] = ~data->bTag;
 		buffer[3] = 0; /* Reserved */
-		buffer[4] = this_part & 255;
-		buffer[5] = (this_part >> 8) & 255;
-		buffer[6] = (this_part >> 16) & 255;
-		buffer[7] = (this_part >> 24) & 255;
+		buffer[4] = this_part >> 0;
+		buffer[5] = this_part >> 8;
+		buffer[6] = this_part >> 16;
+		buffer[7] = this_part >> 24;
 		/* buffer[8] is set above... */
 		buffer[9] = 0; /* Reserved */
 		buffer[10] = 0; /* Reserved */
@@ -1102,7 +1100,7 @@ static int usbtmc_probe(struct usb_interface *intf,
 
 	dev_dbg(&intf->dev, "%s called\n", __func__);
 
-	data = kmalloc(sizeof(struct usbtmc_device_data), GFP_KERNEL);
+	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
 	if (!data) {
 		dev_err(&intf->dev, "Unable to allocate kernel memory\n");
 		return -ENOMEM;
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index b0585e6..2355974 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -43,10 +43,11 @@ static const size_t	pool_max[HCD_BUFFER_POOLS] = {
  *
  * Call this as part of initializing a host controller that uses the dma
  * memory allocators.  It initializes some pools of dma-coherent memory that
- * will be shared by all drivers using that controller, or returns a negative
- * errno value on error.
+ * will be shared by all drivers using that controller.
  *
  * Call hcd_buffer_destroy() to clean up after using those pools.
+ *
+ * Return: 0 if successful. A negative errno value otherwise.
  */
 int hcd_buffer_create(struct usb_hcd *hcd)
 {
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 0598650..737e3c1 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -725,15 +725,15 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
 
 	/*
 	 * check for the special corner case 'get_device_id' in the printer
-	 * class specification, where wIndex is (interface << 8 | altsetting)
-	 * instead of just interface
+	 * class specification, which we always want to allow as it is used
+	 * to query things like ink level, etc.
 	 */
 	if (requesttype == 0xa1 && request == 0) {
 		alt_setting = usb_find_alt_setting(ps->dev->actconfig,
 						   index >> 8, index & 0xff);
 		if (alt_setting
 		 && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER)
-			index >>= 8;
+			return 0;
 	}
 
 	index &= 0xff;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7609ac4..124bcc5 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -117,6 +117,8 @@ static DRIVER_ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id);
  * @count: input size
  *
  * Removes a dynamic usb device ID from this driver.
+ *
+ * Return: @count on success. A negative error code otherwise.
  */
 static ssize_t
 store_remove_id(struct device_driver *driver, const char *buf, size_t count)
@@ -457,6 +459,8 @@ static int usb_unbind_interface(struct device *dev)
  * Callers must own the device lock, so driver probe() entries don't need
  * extra locking, but other call contexts may need to explicitly claim that
  * lock.
+ *
+ * Return: 0 on success.
  */
 int usb_driver_claim_interface(struct usb_driver *driver,
 				struct usb_interface *iface, void *priv)
@@ -658,6 +662,8 @@ EXPORT_SYMBOL_GPL(usb_match_one_id);
  * These device tables are exported with MODULE_DEVICE_TABLE, through
  * modutils, to support the driver loading functionality of USB hotplugging.
  *
+ * Return: The first matching usb_device_id, or %NULL.
+ *
  * What Matches:
  *
  * The "match_flags" element in a usb_device_id controls which
@@ -823,7 +829,8 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
  * Registers a USB device driver with the USB core.  The list of
  * unattached devices will be rescanned whenever a new driver is
  * added, allowing the new driver to attach to any recognized devices.
- * Returns a negative error code on failure and 0 on success.
+ *
+ * Return: A negative error code on failure and 0 on success.
  */
 int usb_register_device_driver(struct usb_device_driver *new_udriver,
 		struct module *owner)
@@ -879,7 +886,8 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
  * Registers a USB interface driver with the USB core.  The list of
  * unattached interfaces will be rescanned whenever a new driver is
  * added, allowing the new driver to attach to any recognized interfaces.
- * Returns a negative error code on failure and 0 on success.
+ *
+ * Return: A negative error code on failure and 0 on success.
  *
  * NOTE: if you want your driver to use the USB major number, you must call
  * usb_register_dev() to enable that functionality.  This function no longer
@@ -1213,6 +1221,8 @@ done:
  * unpredictable times.
  *
  * This routine can run only in process context.
+ *
+ * Return: 0 if the suspend succeeded.
  */
 static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 {
@@ -1294,6 +1304,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
  * unpredictable times.
  *
  * This routine can run only in process context.
+ *
+ * Return: 0 on success.
  */
 static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
 {
@@ -1491,6 +1503,8 @@ void usb_autosuspend_device(struct usb_device *udev)
  * The caller must hold @udev's device lock.
  *
  * This routine can run only in process context.
+ *
+ * Return: 0 on success. A negative error code otherwise.
  */
 int usb_autoresume_device(struct usb_device *udev)
 {
@@ -1600,6 +1614,8 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
  * However if the autoresume fails then the counter is re-decremented.
  *
  * This routine can run only in process context.
+ *
+ * Return: 0 on success.
  */
 int usb_autopm_get_interface(struct usb_interface *intf)
 {
@@ -1633,6 +1649,8 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
  * resumed.
  *
  * This routine can run in atomic context.
+ *
+ * Return: 0 on success. A negative error code otherwise.
  */
 int usb_autopm_get_interface_async(struct usb_interface *intf)
 {
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 68cc653..f13a289 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/idr.h>
 #include <linux/usb.h>
 #include "usb.h"
 
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 6a4c407..7421888 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -153,7 +153,7 @@ void usb_major_cleanup(void)
  * usb_deregister_dev() must be called when the driver is done with
  * the minor numbers given out by this function.
  *
- * Returns -EINVAL if something bad happens with trying to register a
+ * Return: -EINVAL if something bad happens with trying to register a
  * device, and 0 on success.
  */
 int usb_register_dev(struct usb_interface *intf,
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index caeb8d6..b9d3c43 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -171,6 +171,8 @@ static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
  * through the hotplug entry's driver_data.
  *
  * Store this function in the HCD's struct pci_driver as probe().
+ *
+ * Return: 0 if successful.
  */
 int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 014dc99..dc1346f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -378,9 +378,10 @@ MODULE_PARM_DESC(authorized_default,
  * @buf: Buffer for USB string descriptor (header + UTF-16LE)
  * @len: Length (in bytes; may be odd) of descriptor buffer.
  *
- * The return value is the number of bytes filled in: 2 + 2*strlen(s) or
- * buflen, whichever is less.
+ * Return: The number of bytes filled in: 2 + 2*strlen(s) or @len,
+ * whichever is less.
  *
+ * Note:
  * USB String descriptors can contain at most 126 characters; input
  * strings longer than that are truncated.
  */
@@ -416,7 +417,8 @@ ascii2desc(char const *s, u8 *buf, unsigned len)
  *
  * Produces either a manufacturer, product or serial number string for the
  * virtual root hub device.
- * Returns the number of bytes filled in: the length of the descriptor or
+ *
+ * Return: The number of bytes filled in: the length of the descriptor or
  * of the provided buffer, whichever is less.
  */
 static unsigned
@@ -938,6 +940,8 @@ static void usb_bus_init (struct usb_bus *bus)
  *
  * Assigns a bus number, and links the controller into usbcore data
  * structures so that it can be seen by scanning the bus list.
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 static int usb_register_bus(struct usb_bus *bus)
 {
@@ -1002,6 +1006,8 @@ static void usb_deregister_bus (struct usb_bus *bus)
  * the device properly in the device tree and then calls usb_new_device()
  * to register the usb device.  It also assigns the root hub's USB address
  * (always 1).
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 static int register_root_hub(struct usb_hcd *hcd)
 {
@@ -1108,7 +1114,9 @@ EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
  * @isoc: true for isochronous transactions, false for interrupt ones
  * @bytecount: how many bytes in the transaction.
  *
- * Returns approximate bus time in nanoseconds for a periodic transaction.
+ * Return: Approximate bus time in nanoseconds for a periodic transaction.
+ *
+ * Note:
  * See USB 2.0 spec section 5.11.3; only periodic transfers need to be
  * scheduled in software, this function is only used for such scheduling.
  */
@@ -1166,7 +1174,7 @@ EXPORT_SYMBOL_GPL(usb_calc_bus_time);
  * be disabled.  The actions carried out here are required for URB
  * submission, as well as for endpoint shutdown and for usb_kill_urb.
  *
- * Returns 0 for no error, otherwise a negative error code (in which case
+ * Return: 0 for no error, otherwise a negative error code (in which case
  * the enqueue() method must fail).  If no error occurs but enqueue() fails
  * anyway, it must call usb_hcd_unlink_urb_from_ep() before releasing
  * the private spinlock and returning.
@@ -1221,7 +1229,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_link_urb_to_ep);
  * be disabled.  The actions carried out here are required for making
  * sure than an unlink is valid.
  *
- * Returns 0 for no error, otherwise a negative error code (in which case
+ * Return: 0 for no error, otherwise a negative error code (in which case
  * the dequeue() method must fail).  The possible error codes are:
  *
  *	-EIDRM: @urb was not submitted or has already completed.
@@ -1784,7 +1792,7 @@ rescan:
  * pass in the current alternate interface setting in cur_alt,
  * and pass in the new alternate interface setting in new_alt.
  *
- * Returns an error if the requested bandwidth change exceeds the
+ * Return: An error if the requested bandwidth change exceeds the
  * bus bandwidth or host controller internal resources.
  */
 int usb_hcd_alloc_bandwidth(struct usb_device *udev,
@@ -1954,9 +1962,12 @@ void usb_hcd_reset_endpoint(struct usb_device *udev,
  * @num_streams:	number of streams to allocate.
  * @mem_flags:		flags hcd should use to allocate memory.
  *
- * Sets up a group of bulk endpoints to have num_streams stream IDs available.
+ * Sets up a group of bulk endpoints to have @num_streams stream IDs available.
  * Drivers may queue multiple transfers to different stream IDs, which may
  * complete in a different order than they were queued.
+ *
+ * Return: On success, the number of allocated streams. On failure, a negative
+ * error code.
  */
 int usb_alloc_streams(struct usb_interface *interface,
 		struct usb_host_endpoint **eps, unsigned int num_eps,
@@ -2201,6 +2212,8 @@ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
  * khubd identifying and possibly configuring the device.
  * This is needed by OTG controller drivers, where it helps meet
  * HNP protocol timing requirements for starting a port reset.
+ *
+ * Return: 0 if successful.
  */
 int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
 {
@@ -2235,6 +2248,8 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
  *
  * If the controller isn't HALTed, calls the driver's irq handler.
  * Checks whether the controller is now dead.
+ *
+ * Return: %IRQ_HANDLED if the IRQ was handled. %IRQ_NONE otherwise.
  */
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
@@ -2320,7 +2335,8 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
  * HC driver's private data.  Initialize the generic members of the
  * hcd structure.
  *
- * If memory is unavailable, returns NULL.
+ * Return: On success, a pointer to the created and initialized HCD structure.
+ * On failure (e.g. if memory is unavailable), %NULL.
  */
 struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
 		struct device *dev, const char *bus_name,
@@ -2384,7 +2400,8 @@ EXPORT_SYMBOL_GPL(usb_create_shared_hcd);
  * HC driver's private data.  Initialize the generic members of the
  * hcd structure.
  *
- * If memory is unavailable, returns NULL.
+ * Return: On success, a pointer to the created and initialized HCD
+ * structure. On failure (e.g. if memory is unavailable), %NULL.
  */
 struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
 		struct device *dev, const char *bus_name)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 4a8a1d6..5d6d28a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -734,6 +734,8 @@ static void hub_tt_work(struct work_struct *work)
  *
  * call this function to control port's power via setting or
  * clearing the port's PORT_POWER feature.
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
 			   int port1, bool set)
@@ -762,6 +764,8 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
  *
  * It may not be possible for that hub to handle additional full (or low)
  * speed transactions until that state is fully cleared out.
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 int usb_hub_clear_tt_buffer(struct urb *urb)
 {
@@ -964,6 +968,8 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
  * see that the device has been disconnected.  When the device is
  * physically unplugged and something is plugged in, the events will
  * be received and processed normally.
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 int usb_remove_device(struct usb_device *udev)
 {
@@ -1464,11 +1470,10 @@ static int hub_configure(struct usb_hub *hub,
 	 * and battery-powered root hubs (may provide just 8 mA).
 	 */
 	ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
-	if (ret < 2) {
+	if (ret) {
 		message = "can't get hub status";
 		goto fail;
 	}
-	le16_to_cpus(&hubstatus);
 	hcd = bus_to_hcd(hdev->bus);
 	if (hdev == hdev->bus->root_hub) {
 		if (hcd->power_budget > 0)
@@ -2116,6 +2121,8 @@ static inline void announce_device(struct usb_device *udev) { }
  * @udev: newly addressed device (in ADDRESS state)
  *
  * Finish enumeration for On-The-Go devices
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 static int usb_enumerate_device_otg(struct usb_device *udev)
 {
@@ -2198,6 +2205,8 @@ fail:
  * If the device is WUSB and not authorized, we don't attempt to read
  * the string descriptors, as they will be errored out by the device
  * until it has been authorized.
+ *
+ * Return: 0 if successful. A negative error code otherwise.
  */
 static int usb_enumerate_device(struct usb_device *udev)
 {
@@ -2278,13 +2287,14 @@ static void set_usb_port_removable(struct usb_device *udev)
  * udev has already been installed, but udev is not yet visible through
  * sysfs or other filesystem code.
  *
- * It will return if the device is configured properly or not.  Zero if
- * the interface was registered with the driver core; else a negative
- * errno value.
- *
  * This call is synchronous, and may not be used in an interrupt context.
  *
  * Only the hub driver or root-hub registrar should ever call this.
+ *
+ * Return: Whether the device is configured properly or not. Zero if the
+ * interface was registered with the driver core; else a negative errno
+ * value.
+ *
  */
 int usb_new_device(struct usb_device *udev)
 {
@@ -2392,6 +2402,8 @@ fail:
  *
  * We share a lock (that we have) with device_del(), so we need to
  * defer its call.
+ *
+ * Return: 0.
  */
 int usb_deauthorize_device(struct usb_device *usb_dev)
 {
@@ -2838,20 +2850,51 @@ void usb_enable_ltm(struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(usb_enable_ltm);
 
-#ifdef	CONFIG_PM
 /*
- * usb_disable_function_remotewakeup - disable usb3.0
- * device's function remote wakeup
+ * usb_enable_remote_wakeup - enable remote wakeup for a device
  * @udev: target device
  *
- * Assume there's only one function on the USB 3.0
- * device and disable remote wake for the first
- * interface. FIXME if the interface association
- * descriptor shows there's more than one function.
+ * For USB-2 devices: Set the device's remote wakeup feature.
+ *
+ * For USB-3 devices: Assume there's only one function on the device and
+ * enable remote wake for the first interface.  FIXME if the interface
+ * association descriptor shows there's more than one function.
  */
-static int usb_disable_function_remotewakeup(struct usb_device *udev)
+static int usb_enable_remote_wakeup(struct usb_device *udev)
 {
-	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+	if (udev->speed < USB_SPEED_SUPER)
+		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+	else
+		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_SET_FEATURE, USB_RECIP_INTERFACE,
+				USB_INTRF_FUNC_SUSPEND,
+				USB_INTRF_FUNC_SUSPEND_RW |
+					USB_INTRF_FUNC_SUSPEND_LP,
+				NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+/*
+ * usb_disable_remote_wakeup - disable remote wakeup for a device
+ * @udev: target device
+ *
+ * For USB-2 devices: Clear the device's remote wakeup feature.
+ *
+ * For USB-3 devices: Assume there's only one function on the device and
+ * disable remote wake for the first interface.  FIXME if the interface
+ * association descriptor shows there's more than one function.
+ */
+static int usb_disable_remote_wakeup(struct usb_device *udev)
+{
+	if (udev->speed < USB_SPEED_SUPER)
+		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+	else
+		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
 				USB_INTRF_FUNC_SUSPEND,	0, NULL, 0,
 				USB_CTRL_SET_TIMEOUT);
@@ -2918,7 +2961,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 {
 	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent);
 	struct usb_port *port_dev = hub->ports[udev->portnum - 1];
-	enum pm_qos_flags_status pm_qos_stat;
 	int		port1 = udev->portnum;
 	int		status;
 	bool		really_suspend = true;
@@ -2930,33 +2972,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 	 * we don't explicitly enable it here.
 	 */
 	if (udev->do_remote_wakeup) {
-		if (!hub_is_superspeed(hub->hdev)) {
-			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-					USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
-					USB_DEVICE_REMOTE_WAKEUP, 0,
-					NULL, 0,
-					USB_CTRL_SET_TIMEOUT);
-		} else {
-			/* Assume there's only one function on the USB 3.0
-			 * device and enable remote wake for the first
-			 * interface. FIXME if the interface association
-			 * descriptor shows there's more than one function.
-			 */
-			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-					USB_REQ_SET_FEATURE,
-					USB_RECIP_INTERFACE,
-					USB_INTRF_FUNC_SUSPEND,
-					USB_INTRF_FUNC_SUSPEND_RW |
-					USB_INTRF_FUNC_SUSPEND_LP,
-					NULL, 0,
-					USB_CTRL_SET_TIMEOUT);
-		}
+		status = usb_enable_remote_wakeup(udev);
 		if (status) {
 			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
 					status);
 			/* bail if autosuspend is requested */
 			if (PMSG_IS_AUTO(msg))
-				return status;
+				goto err_wakeup;
 		}
 	}
 
@@ -2965,14 +2987,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 		usb_set_usb2_hardware_lpm(udev, 0);
 
 	if (usb_disable_ltm(udev)) {
-		dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
-				__func__);
-		return -ENOMEM;
+		dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
+		status = -ENOMEM;
+		if (PMSG_IS_AUTO(msg))
+			goto err_ltm;
 	}
 	if (usb_unlocked_disable_lpm(udev)) {
-		dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
-				__func__);
-		return -ENOMEM;
+		dev_err(&udev->dev, "Failed to disable LPM before suspend\n.");
+		status = -ENOMEM;
+		if (PMSG_IS_AUTO(msg))
+			goto err_lpm3;
 	}
 
 	/* see 7.1.7.6 */
@@ -3000,28 +3024,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 	if (status) {
 		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
 				port1, status);
-		/* paranoia:  "should not happen" */
-		if (udev->do_remote_wakeup) {
-			if (!hub_is_superspeed(hub->hdev)) {
-				(void) usb_control_msg(udev,
-						usb_sndctrlpipe(udev, 0),
-						USB_REQ_CLEAR_FEATURE,
-						USB_RECIP_DEVICE,
-						USB_DEVICE_REMOTE_WAKEUP, 0,
-						NULL, 0,
-						USB_CTRL_SET_TIMEOUT);
-			} else
-				(void) usb_disable_function_remotewakeup(udev);
-
-		}
 
+		/* Try to enable USB3 LPM and LTM again */
+		usb_unlocked_enable_lpm(udev);
+ err_lpm3:
+		usb_enable_ltm(udev);
+ err_ltm:
 		/* Try to enable USB2 hardware LPM again */
 		if (udev->usb2_hw_lpm_capable == 1)
 			usb_set_usb2_hardware_lpm(udev, 1);
 
-		/* Try to enable USB3 LTM and LPM again */
-		usb_enable_ltm(udev);
-		usb_unlocked_enable_lpm(udev);
+		if (udev->do_remote_wakeup)
+			(void) usb_disable_remote_wakeup(udev);
+ err_wakeup:
 
 		/* System sleep transitions should never fail */
 		if (!PMSG_IS_AUTO(msg))
@@ -3043,14 +3058,15 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 	 * Check whether current status meets the requirement of
 	 * usb port power off mechanism
 	 */
-	pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
-			PM_QOS_FLAG_NO_POWER_OFF);
-	if (!udev->do_remote_wakeup
-			&& pm_qos_stat != PM_QOS_FLAGS_ALL
-			&& udev->persist_enabled
-			&& !status) {
-		pm_runtime_put_sync(&port_dev->dev);
-		port_dev->did_runtime_put = true;
+	if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
+		enum pm_qos_flags_status pm_qos_stat;
+
+		pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
+				PM_QOS_FLAG_NO_POWER_OFF);
+		if (pm_qos_stat != PM_QOS_FLAGS_ALL) {
+			pm_runtime_put_sync(&port_dev->dev);
+			port_dev->did_runtime_put = true;
+		}
 	}
 
 	usb_mark_last_busy(hub->hdev);
@@ -3102,8 +3118,6 @@ static int finish_port_resume(struct usb_device *udev)
 	if (status == 0) {
 		devstatus = 0;
 		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-		if (status >= 0)
-			status = (status > 0 ? 0 : -ENODEV);
 
 		/* If a normal resume failed, try doing a reset-resume */
 		if (status && !udev->reset_resume && udev->persist_enabled) {
@@ -3123,24 +3137,15 @@ static int finish_port_resume(struct usb_device *udev)
 	 * udev->reset_resume
 	 */
 	} else if (udev->actconfig && !udev->reset_resume) {
-		if (!hub_is_superspeed(udev->parent)) {
-			le16_to_cpus(&devstatus);
+		if (udev->speed < USB_SPEED_SUPER) {
 			if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
-				status = usb_control_msg(udev,
-						usb_sndctrlpipe(udev, 0),
-						USB_REQ_CLEAR_FEATURE,
-						USB_RECIP_DEVICE,
-						USB_DEVICE_REMOTE_WAKEUP, 0,
-						NULL, 0,
-						USB_CTRL_SET_TIMEOUT);
+				status = usb_disable_remote_wakeup(udev);
 		} else {
 			status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
 					&devstatus);
-			le16_to_cpus(&devstatus);
 			if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
 					| USB_INTRF_STAT_FUNC_RW))
-				status =
-					usb_disable_function_remotewakeup(udev);
+				status = usb_disable_remote_wakeup(udev);
 		}
 
 		if (status)
@@ -3274,8 +3279,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 	return status;
 }
 
-#endif	/* CONFIG_PM */
-
 #ifdef	CONFIG_PM_RUNTIME
 
 /* caller has locked udev */
@@ -3843,7 +3846,8 @@ EXPORT_SYMBOL_GPL(usb_disable_ltm);
 
 void usb_enable_ltm(struct usb_device *udev) { }
 EXPORT_SYMBOL_GPL(usb_enable_ltm);
-#endif
+
+#endif	/* CONFIG_PM */
 
 
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
@@ -4483,11 +4487,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 
 			status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
 					&devstat);
-			if (status < 2) {
+			if (status) {
 				dev_dbg(&udev->dev, "get status %d ?\n", status);
 				goto loop_disable;
 			}
-			le16_to_cpus(&devstat);
 			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
 				dev_err(&udev->dev,
 					"can't connect bus-powered hub "
@@ -4798,7 +4801,8 @@ static void hub_events(void)
 					hub->ports[i - 1]->child;
 
 				dev_dbg(hub_dev, "warm reset port %d\n", i);
-				if (!udev) {
+				if (!udev || !(portstatus &
+						USB_PORT_STAT_CONNECTION)) {
 					status = hub_port_reset(hub, i,
 							NULL, HUB_BH_RESET_TIME,
 							true);
@@ -4808,8 +4812,8 @@ static void hub_events(void)
 					usb_lock_device(udev);
 					status = usb_reset_device(udev);
 					usb_unlock_device(udev);
+					connect_change = 0;
 				}
-				connect_change = 0;
 			}
 
 			if (connect_change)
@@ -5034,10 +5038,11 @@ static int descriptors_changed(struct usb_device *udev,
  * re-connected.  All drivers will be unbound, and the device will be
  * re-enumerated and probed all over again.
  *
- * Returns 0 if the reset succeeded, -ENODEV if the device has been
+ * Return: 0 if the reset succeeded, -ENODEV if the device has been
  * flagged for logical disconnection, or some other negative error code
  * if the reset wasn't even attempted.
  *
+ * Note:
  * The caller must own the device lock.  For example, it's safe to use
  * this from a driver probe() routine after downloading new firmware.
  * For calls that might not occur during probe(), drivers should lock
@@ -5193,8 +5198,9 @@ re_enumerate:
  * method), performs the port reset, and then lets the drivers know that
  * the reset is over (using their post_reset method).
  *
- * Return value is the same as for usb_reset_and_verify_device().
+ * Return: The same as for usb_reset_and_verify_device().
  *
+ * Note:
  * The caller must own the device lock.  For example, it's safe to use
  * this from a driver probe() routine after downloading new firmware.
  * For calls that might not occur during probe(), drivers should lock
@@ -5332,7 +5338,7 @@ EXPORT_SYMBOL_GPL(usb_queue_reset_device);
  * USB drivers call this function to get hub's child device
  * pointer.
  *
- * Return NULL if input param is invalid and
+ * Return: %NULL if input param is invalid and
  * child's usb_device pointer if non-NULL.
  */
 struct usb_device *usb_hub_find_child(struct usb_device *hdev,
@@ -5366,8 +5372,8 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
  * @hdev: USB device belonging to the usb hub
  * @port1: port num of the port
  *
- * Return connect type of the port and if input params are
- * invalid, return USB_PORT_CONNECT_TYPE_UNKNOWN.
+ * Return: The connect type of the port if successful. Or
+ * USB_PORT_CONNECT_TYPE_UNKNOWN if input params are invalid.
  */
 enum usb_port_connect_type
 usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
@@ -5427,8 +5433,8 @@ void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
  * @hdev: USB device belonging to the usb hub
  * @port1: port num of the port
  *
- * Return port's acpi handle if successful, NULL if params are
- * invaild.
+ * Return: Port's acpi handle if successful, %NULL if params are
+ * invalid.
  */
 acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
 	int port1)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e7ee1e4..82927e1 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -119,15 +119,15 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
  * This function sends a simple control message to a specified endpoint and
  * waits for the message to complete, or timeout.
  *
- * If successful, it returns the number of bytes transferred, otherwise a
- * negative error number.
- *
  * Don't use this function from within an interrupt context, like a bottom half
  * handler.  If you need an asynchronous message, or need to send a message
  * from within interrupt context, use usb_submit_urb().
  * If a thread in your driver uses this call, make sure your disconnect()
  * method can wait for it to complete.  Since you don't have a handle on the
  * URB used, you can't cancel the request.
+ *
+ * Return: If successful, the number of bytes transferred. Otherwise, a negative
+ * error number.
  */
 int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
 		    __u8 requesttype, __u16 value, __u16 index, void *data,
@@ -170,15 +170,16 @@ EXPORT_SYMBOL_GPL(usb_control_msg);
  * This function sends a simple interrupt message to a specified endpoint and
  * waits for the message to complete, or timeout.
  *
- * If successful, it returns 0, otherwise a negative error number.  The number
- * of actual bytes transferred will be stored in the actual_length paramater.
- *
  * Don't use this function from within an interrupt context, like a bottom half
  * handler.  If you need an asynchronous message, or need to send a message
  * from within interrupt context, use usb_submit_urb() If a thread in your
  * driver uses this call, make sure your disconnect() method can wait for it to
  * complete.  Since you don't have a handle on the URB used, you can't cancel
  * the request.
+ *
+ * Return:
+ * If successful, 0. Otherwise a negative error number. The number of actual
+ * bytes transferred will be stored in the @actual_length paramater.
  */
 int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
 		      void *data, int len, int *actual_length, int timeout)
@@ -203,9 +204,6 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
  * This function sends a simple bulk message to a specified endpoint
  * and waits for the message to complete, or timeout.
  *
- * If successful, it returns 0, otherwise a negative error number.  The number
- * of actual bytes transferred will be stored in the actual_length paramater.
- *
  * Don't use this function from within an interrupt context, like a bottom half
  * handler.  If you need an asynchronous message, or need to send a message
  * from within interrupt context, use usb_submit_urb() If a thread in your
@@ -217,6 +215,11 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
  * users are forced to abuse this routine by using it to submit URBs for
  * interrupt endpoints.  We will take the liberty of creating an interrupt URB
  * (with the default interval) if the target is an interrupt endpoint.
+ *
+ * Return:
+ * If successful, 0. Otherwise a negative error number. The number of actual
+ * bytes transferred will be stored in the @actual_length paramater.
+ *
  */
 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
 		 void *data, int len, int *actual_length, int timeout)
@@ -341,9 +344,9 @@ static void sg_complete(struct urb *urb)
  * 	send every byte identified in the list.
  * @mem_flags: SLAB_* flags affecting memory allocations in this call
  *
- * Returns zero for success, else a negative errno value.  This initializes a
- * scatter/gather request, allocating resources such as I/O mappings and urb
- * memory (except maybe memory used by USB controller drivers).
+ * This initializes a scatter/gather request, allocating resources such as
+ * I/O mappings and urb memory (except maybe memory used by USB controller
+ * drivers).
  *
  * The request must be issued using usb_sg_wait(), which waits for the I/O to
  * complete (or to be canceled) and then cleans up all resources allocated by
@@ -351,6 +354,8 @@ static void sg_complete(struct urb *urb)
  *
  * The request may be canceled with usb_sg_cancel(), either before or after
  * usb_sg_wait() is called.
+ *
+ * Return: Zero for success, else a negative errno value.
  */
 int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
 		unsigned pipe, unsigned	period, struct scatterlist *sg,
@@ -623,7 +628,7 @@ EXPORT_SYMBOL_GPL(usb_sg_cancel);
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Returns the number of bytes received on success, or else the status code
+ * Return: The number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
 int usb_get_descriptor(struct usb_device *dev, unsigned char type,
@@ -671,7 +676,7 @@ EXPORT_SYMBOL_GPL(usb_get_descriptor);
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Returns the number of bytes received on success, or else the status code
+ * Return: The number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
 static int usb_get_string(struct usb_device *dev, unsigned short langid,
@@ -805,7 +810,7 @@ static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Returns length of the string (>= 0) or usb_control_msg status (< 0).
+ * Return: length of the string (>= 0) or usb_control_msg status (< 0).
  */
 int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 {
@@ -853,8 +858,8 @@ EXPORT_SYMBOL_GPL(usb_string);
  * @udev: the device whose string descriptor is being read
  * @index: the descriptor index
  *
- * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
- * or NULL if the index is 0 or the string could not be read.
+ * Return: A pointer to a kmalloc'ed buffer containing the descriptor string,
+ * or %NULL if the index is 0 or the string could not be read.
  */
 char *usb_cache_string(struct usb_device *udev, int index)
 {
@@ -894,7 +899,7 @@ char *usb_cache_string(struct usb_device *udev, int index)
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Returns the number of bytes received on success, or else the status code
+ * Return: The number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
 int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
@@ -934,13 +939,13 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Returns the number of bytes received on success, or else the status code
- * returned by the underlying usb_control_msg() call.
+ * Returns 0 and the status value in *@data (in host byte order) on success,
+ * or else the status code from the underlying usb_control_msg() call.
  */
 int usb_get_status(struct usb_device *dev, int type, int target, void *data)
 {
 	int ret;
-	u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
+	__le16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
 
 	if (!status)
 		return -ENOMEM;
@@ -949,7 +954,12 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
 		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
 		sizeof(*status), USB_CTRL_GET_TIMEOUT);
 
-	*(u16 *)data = *status;
+	if (ret == 2) {
+		*(u16 *) data = le16_to_cpu(*status);
+		ret = 0;
+	} else if (ret >= 0) {
+		ret = -EIO;
+	}
 	kfree(status);
 	return ret;
 }
@@ -975,7 +985,7 @@ EXPORT_SYMBOL_GPL(usb_get_status);
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Returns zero on success, or else the status code returned by the
+ * Return: Zero on success, or else the status code returned by the
  * underlying usb_control_msg() call.
  */
 int usb_clear_halt(struct usb_device *dev, int pipe)
@@ -1272,7 +1282,7 @@ void usb_enable_interface(struct usb_device *dev,
  * endpoints in that interface; all such urbs must first be completed
  * (perhaps forced by unlinking).
  *
- * Returns zero on success, or else the status code returned by the
+ * Return: Zero on success, or else the status code returned by the
  * underlying usb_control_msg() call.
  */
 int usb_set_interface(struct usb_device *dev, int interface, int alternate)
@@ -1426,7 +1436,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
  *
  * The caller must own the device lock.
  *
- * Returns zero on success, else a negative error code.
+ * Return: Zero on success, else a negative error code.
  */
 int usb_reset_configuration(struct usb_device *dev)
 {
@@ -1968,7 +1978,7 @@ static void cancel_async_set_config(struct usb_device *udev)
  * routine gets around the normal restrictions by using a work thread to
  * submit the change-config request.
  *
- * Returns 0 if the request was successfully queued, error code otherwise.
+ * Return: 0 if the request was successfully queued, error code otherwise.
  * The caller has no way to know whether the queued request will eventually
  * succeed.
  */
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 16927fa..4e7a311 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -7,6 +7,7 @@
 #include <linux/usb.h>
 #include <linux/wait.h>
 #include <linux/usb/hcd.h>
+#include <linux/scatterlist.h>
 
 #define to_urb(d) container_of(d, struct urb, kref)
 
@@ -54,12 +55,12 @@ EXPORT_SYMBOL_GPL(usb_init_urb);
  * Creates an urb for the USB driver to use, initializes a few internal
  * structures, incrementes the usage counter, and returns a pointer to it.
  *
- * If no memory is available, NULL is returned.
- *
  * If the driver want to use this urb for interrupt, control, or bulk
  * endpoints, pass '0' as the number of iso packets.
  *
  * The driver must call usb_free_urb() when it is finished with the urb.
+ *
+ * Return: A pointer to the new urb, or %NULL if no memory is available.
  */
 struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
 {
@@ -102,7 +103,7 @@ EXPORT_SYMBOL_GPL(usb_free_urb);
  * host controller driver.  This allows proper reference counting to happen
  * for urbs.
  *
- * A pointer to the urb with the incremented reference counter is returned.
+ * Return: A pointer to the urb with the incremented reference counter.
  */
 struct urb *usb_get_urb(struct urb *urb)
 {
@@ -199,13 +200,12 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  * the particular kind of transfer, although they will not initialize
  * any transfer flags.
  *
- * Successful submissions return 0; otherwise this routine returns a
- * negative error number.  If the submission is successful, the complete()
- * callback from the URB will be called exactly once, when the USB core and
- * Host Controller Driver (HCD) are finished with the URB.  When the completion
- * function is called, control of the URB is returned to the device
- * driver which issued the request.  The completion handler may then
- * immediately free or reuse that URB.
+ * If the submission is successful, the complete() callback from the URB
+ * will be called exactly once, when the USB core and Host Controller Driver
+ * (HCD) are finished with the URB.  When the completion function is called,
+ * control of the URB is returned to the device driver which issued the
+ * request.  The completion handler may then immediately free or reuse that
+ * URB.
  *
  * With few exceptions, USB device drivers should never access URB fields
  * provided by usbcore or the HCD until its complete() is called.
@@ -240,6 +240,9 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  * that are standardized in the USB 2.0 specification.  For bulk
  * endpoints, a synchronous usb_bulk_msg() call is available.
  *
+ * Return:
+ * 0 on successful submissions. A negative error number otherwise.
+ *
  * Request Queuing:
  *
  * URBs may be submitted to endpoints before previous ones complete, to
@@ -413,6 +416,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 			urb->iso_frame_desc[n].status = -EXDEV;
 			urb->iso_frame_desc[n].actual_length = 0;
 		}
+	} else if (dev->speed != USB_SPEED_WIRELESS && urb->num_sgs) {
+		struct scatterlist *sg;
+		int i;
+
+		for_each_sg(urb->sg, sg, urb->num_sgs - 1, i)
+			if (sg->length % max)
+				return -EINVAL;
 	}
 
 	/* the I/O buffer must be mapped/unmapped, except when length=0 */
@@ -564,6 +574,9 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
  * particular, when a driver calls this routine, it must insure that the
  * completion handler cannot deallocate the URB.
  *
+ * Return: -EINPROGRESS on success. See description for other values on
+ * failure.
+ *
  * Unlinking and Endpoint Queues:
  *
  * [The behaviors and guarantees described below do not apply to virtual
@@ -838,6 +851,8 @@ EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
  *
  * Call this is you want to be sure all an anchor's
  * URBs have finished
+ *
+ * Return: Non-zero if the anchor became unused. Zero on timeout.
  */
 int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
 				  unsigned int timeout)
@@ -851,8 +866,11 @@ EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
  * usb_get_from_anchor - get an anchor's oldest urb
  * @anchor: the anchor whose urb you want
  *
- * this will take the oldest urb from an anchor,
+ * This will take the oldest urb from an anchor,
  * unanchor and return it
+ *
+ * Return: The oldest urb from @anchor, or %NULL if @anchor has no
+ * urbs associated with it.
  */
 struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
 {
@@ -901,7 +919,7 @@ EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs);
  * usb_anchor_empty - is an anchor empty
  * @anchor: the anchor you want to query
  *
- * returns 1 if the anchor has no urbs associated with it
+ * Return: 1 if the anchor has no urbs associated with it.
  */
 int usb_anchor_empty(struct usb_anchor *anchor)
 {
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 7dad603..0a6ee2e 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -68,6 +68,8 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
  * @alt_num: alternate interface setting number to search for.
  *
  * Search the configuration's interface cache for the given alt setting.
+ *
+ * Return: The alternate setting, if found. %NULL otherwise.
  */
 struct usb_host_interface *usb_find_alt_setting(
 		struct usb_host_config *config,
@@ -103,8 +105,7 @@ EXPORT_SYMBOL_GPL(usb_find_alt_setting);
  * @ifnum: the desired interface
  *
  * This walks the device descriptor for the currently active configuration
- * and returns a pointer to the interface with that particular interface
- * number, or null.
+ * to find the interface object with the particular interface number.
  *
  * Note that configuration descriptors are not required to assign interface
  * numbers sequentially, so that it would be incorrect to assume that
@@ -115,6 +116,9 @@ EXPORT_SYMBOL_GPL(usb_find_alt_setting);
  *
  * Don't call this function unless you are bound to one of the interfaces
  * on this device or you have locked the device!
+ *
+ * Return: A pointer to the interface that has @ifnum as interface number,
+ * if found. %NULL otherwise.
  */
 struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
 				      unsigned ifnum)
@@ -139,8 +143,7 @@ EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
  * @altnum: the desired alternate setting number
  *
  * This searches the altsetting array of the specified interface for
- * an entry with the correct bAlternateSetting value and returns a pointer
- * to that entry, or null.
+ * an entry with the correct bAlternateSetting value.
  *
  * Note that altsettings need not be stored sequentially by number, so
  * it would be incorrect to assume that the first altsetting entry in
@@ -149,6 +152,9 @@ EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
  *
  * Don't call this function unless you are bound to the intf interface
  * or you have locked the device!
+ *
+ * Return: A pointer to the entry of the altsetting array of @intf that
+ * has @altnum as the alternate setting number. %NULL if not found.
  */
 struct usb_host_interface *usb_altnum_to_altsetting(
 					const struct usb_interface *intf,
@@ -191,6 +197,8 @@ static int __find_interface(struct device *dev, void *data)
  * This walks the bus device list and returns a pointer to the interface
  * with the matching minor and driver.  Note, this only works for devices
  * that share the USB major number.
+ *
+ * Return: A pointer to the interface with the matching major and @minor.
  */
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
@@ -390,6 +398,9 @@ static unsigned usb_bus_is_wusb(struct usb_bus *bus)
  * controllers) should ever call this.
  *
  * This call may not be used in a non-sleeping context.
+ *
+ * Return: On success, a pointer to the allocated usb device. %NULL on
+ * failure.
  */
 struct usb_device *usb_alloc_dev(struct usb_device *parent,
 				 struct usb_bus *bus, unsigned port1)
@@ -501,7 +512,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
  * their probe() methods, when they bind to an interface, and release
  * them by calling usb_put_dev(), in their disconnect() methods.
  *
- * A pointer to the device with the incremented reference counter is returned.
+ * Return: A pointer to the device with the incremented reference counter.
  */
 struct usb_device *usb_get_dev(struct usb_device *dev)
 {
@@ -535,8 +546,7 @@ EXPORT_SYMBOL_GPL(usb_put_dev);
  * their probe() methods, when they bind to an interface, and release
  * them by calling usb_put_intf(), in their disconnect() methods.
  *
- * A pointer to the interface with the incremented reference counter is
- * returned.
+ * Return: A pointer to the interface with the incremented reference counter.
  */
 struct usb_interface *usb_get_intf(struct usb_interface *intf)
 {
@@ -589,7 +599,7 @@ EXPORT_SYMBOL_GPL(usb_put_intf);
  * disconnect; in some drivers (such as usb-storage) the disconnect()
  * or suspend() method will block waiting for a device reset to complete.
  *
- * Returns a negative error code for failure, otherwise 0.
+ * Return: A negative error code for failure, otherwise 0.
  */
 int usb_lock_device_for_reset(struct usb_device *udev,
 			      const struct usb_interface *iface)
@@ -628,14 +638,15 @@ EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
  * usb_get_current_frame_number - return current bus frame number
  * @dev: the device whose bus is being queried
  *
- * Returns the current frame number for the USB host controller
- * used with the given USB device.  This can be used when scheduling
+ * Return: The current frame number for the USB host controller used
+ * with the given USB device. This can be used when scheduling
  * isochronous requests.
  *
- * Note that different kinds of host controller have different
- * "scheduling horizons".  While one type might support scheduling only
- * 32 frames into the future, others could support scheduling up to
- * 1024 frames into the future.
+ * Note: Different kinds of host controller have different "scheduling
+ * horizons". While one type might support scheduling only 32 frames
+ * into the future, others could support scheduling up to 1024 frames
+ * into the future.
+ *
  */
 int usb_get_current_frame_number(struct usb_device *dev)
 {
@@ -685,11 +696,12 @@ EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
  * @mem_flags: affect whether allocation may block
  * @dma: used to return DMA address of buffer
  *
- * Return value is either null (indicating no buffer could be allocated), or
- * the cpu-space pointer to a buffer that may be used to perform DMA to the
+ * Return: Either null (indicating no buffer could be allocated), or the
+ * cpu-space pointer to a buffer that may be used to perform DMA to the
  * specified device.  Such cpu-space buffers are returned along with the DMA
  * address (through the pointer provided).
  *
+ * Note:
  * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags
  * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU
  * hardware during URB completion/resubmit.  The implementation varies between
@@ -735,17 +747,18 @@ EXPORT_SYMBOL_GPL(usb_free_coherent);
  * usb_buffer_map - create DMA mapping(s) for an urb
  * @urb: urb whose transfer_buffer/setup_packet will be mapped
  *
- * Return value is either null (indicating no buffer could be mapped), or
- * the parameter.  URB_NO_TRANSFER_DMA_MAP is
- * added to urb->transfer_flags if the operation succeeds.  If the device
- * is connected to this system through a non-DMA controller, this operation
- * always succeeds.
+ * URB_NO_TRANSFER_DMA_MAP is added to urb->transfer_flags if the operation
+ * succeeds. If the device is connected to this system through a non-DMA
+ * controller, this operation always succeeds.
  *
  * This call would normally be used for an urb which is reused, perhaps
  * as the target of a large periodic transfer, with usb_buffer_dmasync()
  * calls to synchronize memory and dma state.
  *
  * Reverse the effect of this call with usb_buffer_unmap().
+ *
+ * Return: Either %NULL (indicating no buffer could be mapped), or @urb.
+ *
  */
 #if 0
 struct urb *usb_buffer_map(struct urb *urb)
@@ -850,9 +863,10 @@ EXPORT_SYMBOL_GPL(usb_buffer_unmap);
  * @sg: the scatterlist to map
  * @nents: the number of entries in the scatterlist
  *
- * Return value is either < 0 (indicating no buffers could be mapped), or
- * the number of DMA mapping array entries in the scatterlist.
+ * Return: Either < 0 (indicating no buffers could be mapped), or the
+ * number of DMA mapping array entries in the scatterlist.
  *
+ * Note:
  * The caller is responsible for placing the resulting DMA addresses from
  * the scatterlist into URB transfer buffer pointers, and for setting the
  * URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs.
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 2378958..f969ea2 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -1,6 +1,7 @@
 config USB_DWC3
 	tristate "DesignWare USB3 DRD Core Support"
 	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
+	depends on EXTCON
 	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 	help
 	  Say Y or M here if your system has a Dual Role SuperSpeed
@@ -40,6 +41,38 @@ config USB_DWC3_DUAL_ROLE
 
 endchoice
 
+comment "Platform Glue Driver Support"
+
+config USB_DWC3_OMAP
+	tristate "Texas Instruments OMAP5 and similar Platforms"
+	depends on EXTCON
+	default USB_DWC3
+	help
+	  Some platforms from Texas Instruments like OMAP5, DRA7xxx and
+	  AM437x use this IP for USB2/3 functionality.
+
+	  Say 'Y' or 'M' here if you have one such device
+
+config USB_DWC3_EXYNOS
+	tristate "Samsung Exynos Platform"
+	default USB_DWC3
+	help
+	  Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
+	  say 'Y' or 'M' if you have one such device.
+
+config USB_DWC3_PCI
+	tristate "PCIe-based Platforms"
+	depends on PCI
+	default USB_DWC3
+	help
+	  If you're using the DesignWare Core IP with a PCIe, please say
+	  'Y' or 'M' here.
+
+	  One such PCIe-based platform is Synopsys' PCIe HAPS model of
+	  this IP.
+
+comment "Debugging features"
+
 config USB_DWC3_DEBUG
 	bool "Enable Debugging Messages"
 	help
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 0c7ac92..dd17601 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -27,15 +27,8 @@ endif
 # the entire driver (with all its glue layers) on several architectures
 # and make sure it compiles fine. This will also help with allmodconfig
 # and allyesconfig builds.
-#
-# The only exception is the PCI glue layer, but that's only because
-# PCI doesn't provide nops if CONFIG_PCI isn't enabled.
 ##
 
-obj-$(CONFIG_USB_DWC3)		+= dwc3-omap.o
-obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o
-
-ifneq ($(CONFIG_PCI),)
-	obj-$(CONFIG_USB_DWC3)		+= dwc3-pci.o
-endif
-
+obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
+obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
+obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 358375e..3ff6f0a 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -6,34 +6,17 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
@@ -53,17 +36,16 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/of.h>
+#include <linux/usb/otg.h>
 
+#include "platform_data.h"
 #include "core.h"
 #include "gadget.h"
 #include "io.h"
 
 #include "debug.h"
 
-static char *maximum_speed = "super";
-module_param(maximum_speed, charp, 0);
-MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
-
 /* -------------------------------------------------------------------------- */
 
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
@@ -236,7 +218,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc)
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
 				upper_32_bits(evt->dma));
 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
-				evt->length & 0xffff);
+				DWC3_GEVNTSIZ_SIZE(evt->length));
 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
 	}
 
@@ -255,7 +237,8 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
-		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
+		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
+				| DWC3_GEVNTSIZ_SIZE(0));
 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
 	}
 }
@@ -367,18 +350,17 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 
 static int dwc3_probe(struct platform_device *pdev)
 {
-	struct device_node	*node = pdev->dev.of_node;
+	struct device		*dev = &pdev->dev;
+	struct dwc3_platform_data *pdata = dev_get_platdata(dev);
+	struct device_node	*node = dev->of_node;
 	struct resource		*res;
 	struct dwc3		*dwc;
-	struct device		*dev = &pdev->dev;
 
 	int			ret = -ENOMEM;
 
 	void __iomem		*regs;
 	void			*mem;
 
-	u8			mode;
-
 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
 	if (!mem) {
 		dev_err(dev, "not enough memory\n");
@@ -402,38 +384,29 @@ static int dwc3_probe(struct platform_device *pdev)
 		dev_err(dev, "missing memory resource\n");
 		return -ENODEV;
 	}
-	dwc->xhci_resources[0].start = res->start;
-	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
-					DWC3_XHCI_REGS_END;
-	dwc->xhci_resources[0].flags = res->flags;
-	dwc->xhci_resources[0].name = res->name;
-
-	 /*
-	  * Request memory region but exclude xHCI regs,
-	  * since it will be requested by the xhci-plat driver.
-	  */
-	res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
-			resource_size(res) - DWC3_GLOBALS_REGS_START,
-			dev_name(dev));
-	if (!res) {
-		dev_err(dev, "can't request mem region\n");
-		return -ENOMEM;
-	}
-
-	regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-	if (!regs) {
-		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
 
 	if (node) {
+		dwc->maximum_speed = of_usb_get_maximum_speed(node);
+
 		dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
 		dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+
+		dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+		dwc->dr_mode = of_usb_get_dr_mode(node);
 	} else {
+		dwc->maximum_speed = pdata->maximum_speed;
+
 		dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+
+		dwc->needs_fifo_resize = pdata->tx_fifo_resize;
+		dwc->dr_mode = pdata->dr_mode;
 	}
 
+	/* default to superspeed if no maximum_speed passed */
+	if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
+		dwc->maximum_speed = USB_SPEED_SUPER;
+
 	if (IS_ERR(dwc->usb2_phy)) {
 		ret = PTR_ERR(dwc->usb2_phy);
 
@@ -464,6 +437,22 @@ static int dwc3_probe(struct platform_device *pdev)
 		return -EPROBE_DEFER;
 	}
 
+	dwc->xhci_resources[0].start = res->start;
+	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
+					DWC3_XHCI_REGS_END;
+	dwc->xhci_resources[0].flags = res->flags;
+	dwc->xhci_resources[0].name = res->name;
+
+	res->start += DWC3_GLOBALS_REGS_START;
+
+	/*
+	 * Request memory region but exclude xHCI regs,
+	 * since it will be requested by the xhci-plat driver.
+	 */
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
 	usb_phy_set_suspend(dwc->usb2_phy, 0);
 	usb_phy_set_suspend(dwc->usb3_phy, 0);
 
@@ -478,19 +467,6 @@ static int dwc3_probe(struct platform_device *pdev)
 	dev->dma_parms	= dev->parent->dma_parms;
 	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
 
-	if (!strncmp("super", maximum_speed, 5))
-		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
-	else if (!strncmp("high", maximum_speed, 4))
-		dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
-	else if (!strncmp("full", maximum_speed, 4))
-		dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
-	else if (!strncmp("low", maximum_speed, 3))
-		dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
-	else
-		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
-
-	dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
-
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 	pm_runtime_forbid(dev);
@@ -517,14 +493,15 @@ static int dwc3_probe(struct platform_device *pdev)
 	}
 
 	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
-		mode = DWC3_MODE_HOST;
+		dwc->dr_mode = USB_DR_MODE_HOST;
 	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
-		mode = DWC3_MODE_DEVICE;
-	else
-		mode = DWC3_MODE_DRD;
+		dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
+
+	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
+		dwc->dr_mode = USB_DR_MODE_OTG;
 
-	switch (mode) {
-	case DWC3_MODE_DEVICE:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
@@ -532,7 +509,7 @@ static int dwc3_probe(struct platform_device *pdev)
 			goto err2;
 		}
 		break;
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
@@ -540,7 +517,7 @@ static int dwc3_probe(struct platform_device *pdev)
 			goto err2;
 		}
 		break;
-	case DWC3_MODE_DRD:
+	case USB_DR_MODE_OTG:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
@@ -555,10 +532,9 @@ static int dwc3_probe(struct platform_device *pdev)
 		}
 		break;
 	default:
-		dev_err(dev, "Unsupported mode of operation %d\n", mode);
+		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
 		goto err2;
 	}
-	dwc->mode = mode;
 
 	ret = dwc3_debugfs_init(dwc);
 	if (ret) {
@@ -571,14 +547,14 @@ static int dwc3_probe(struct platform_device *pdev)
 	return 0;
 
 err3:
-	switch (mode) {
-	case DWC3_MODE_DEVICE:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
 		dwc3_gadget_exit(dwc);
 		break;
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 		dwc3_host_exit(dwc);
 		break;
-	case DWC3_MODE_DRD:
+	case USB_DR_MODE_OTG:
 		dwc3_host_exit(dwc);
 		dwc3_gadget_exit(dwc);
 		break;
@@ -611,14 +587,14 @@ static int dwc3_remove(struct platform_device *pdev)
 
 	dwc3_debugfs_exit(dwc);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
 		dwc3_gadget_exit(dwc);
 		break;
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 		dwc3_host_exit(dwc);
 		break;
-	case DWC3_MODE_DRD:
+	case USB_DR_MODE_OTG:
 		dwc3_host_exit(dwc);
 		dwc3_gadget_exit(dwc);
 		break;
@@ -642,12 +618,12 @@ static int dwc3_prepare(struct device *dev)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_prepare(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		dwc3_event_buffers_cleanup(dwc);
 		break;
@@ -665,12 +641,12 @@ static void dwc3_complete(struct device *dev)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_complete(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		dwc3_event_buffers_setup(dwc);
 		break;
@@ -686,12 +662,12 @@ static int dwc3_suspend(struct device *dev)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_suspend(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		/* do nothing */
 		break;
@@ -719,12 +695,12 @@ static int dwc3_resume(struct device *dev)
 
 	dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_resume(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		/* do nothing */
 		break;
@@ -754,6 +730,9 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = {
 #ifdef CONFIG_OF
 static const struct of_device_id of_dwc3_match[] = {
 	{
+		.compatible = "snps,dwc3"
+	},
+	{
 		.compatible = "synopsys,dwc3"
 	},
 	{ },
@@ -775,5 +754,5 @@ module_platform_driver(dwc3_driver);
 
 MODULE_ALIAS("platform:dwc3");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 27dad99..f8af8d4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DRIVERS_USB_DWC3_CORE_H
@@ -49,6 +29,7 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 
 /* Global constants */
 #define DWC3_EP0_BOUNCE_SIZE	512
@@ -194,6 +175,10 @@
 #define DWC3_GTXFIFOSIZ_TXFDEF(n)	((n) & 0xffff)
 #define DWC3_GTXFIFOSIZ_TXFSTADDR(n)	((n) & 0xffff0000)
 
+/* Global Event Size Registers */
+#define DWC3_GEVNTSIZ_INTMASK		(1 << 31)
+#define DWC3_GEVNTSIZ_SIZE(n)		((n) & 0xffff)
+
 /* Global HWPARAMS1 Register */
 #define DWC3_GHWPARAMS1_EN_PWROPT(n)	(((n) & (3 << 24)) >> 24)
 #define DWC3_GHWPARAMS1_EN_PWROPT_NO	0
@@ -207,7 +192,6 @@
 #define DWC3_MAX_HIBER_SCRATCHBUFS		15
 
 /* Device Configuration Register */
-#define DWC3_DCFG_LPM_CAP	(1 << 22)
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
 
@@ -367,7 +351,6 @@ struct dwc3_trb;
 
 /**
  * struct dwc3_event_buffer - Software event buffer representation
- * @list: a list of event buffers
  * @buf: _THE_ buffer
  * @length: size of this buffer
  * @lpos: event offset
@@ -415,7 +398,7 @@ struct dwc3_event_buffer {
  * @number: endpoint number (1 - 15)
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @resource_index: Resource transfer index
- * @interval: the intervall on which the ISOC transfer is started
+ * @interval: the interval on which the ISOC transfer is started
  * @name: a human readable name e.g. ep1out-bulk
  * @direction: true for TX, false for RX
  * @stream_capable: true when streams are enabled
@@ -566,11 +549,6 @@ struct dwc3_hwparams {
 /* HWPARAMS0 */
 #define DWC3_MODE(n)		((n) & 0x7)
 
-#define DWC3_MODE_DEVICE	0
-#define DWC3_MODE_HOST		1
-#define DWC3_MODE_DRD		2
-#define DWC3_MODE_HUB		3
-
 #define DWC3_MDWIDTH(n)		(((n) & 0xff00) >> 8)
 
 /* HWPARAMS1 */
@@ -632,7 +610,7 @@ struct dwc3_scratchpad_array {
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
  * @revision: revision register contents
- * @mode: mode of operation
+ * @dr_mode: requested mode of operation
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
  * @dcfg: saved contents of DCFG register
@@ -690,6 +668,8 @@ struct dwc3 {
 	void __iomem		*regs;
 	size_t			regs_size;
 
+	enum usb_dr_mode	dr_mode;
+
 	/* used for suspend/resume */
 	u32			dcfg;
 	u32			gctl;
@@ -698,7 +678,6 @@ struct dwc3 {
 	u32			u1u2;
 	u32			maximum_speed;
 	u32			revision;
-	u32			mode;
 
 #define DWC3_REVISION_173A	0x5533173a
 #define DWC3_REVISION_175A	0x5533175a
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index 5894ee8..fceb39d 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include "core.h"
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 9e9f122..9ac37fe 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 8ce9d7f..9a8a5e1 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -6,10 +6,14 @@
  *
  * Author: Anton Tikhomirov <av.tikhomirov@samsung.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
@@ -228,5 +232,5 @@ module_platform_driver(dwc3_exynos_driver);
 
 MODULE_ALIAS("platform:exynos-dwc3");
 MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 077f110..7f7ea62 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
@@ -43,13 +23,15 @@
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/dwc3-omap.h>
-#include <linux/usb/dwc3-omap.h>
 #include <linux/pm_runtime.h>
 #include <linux/dma-mapping.h>
 #include <linux/ioport.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/extcon.h>
+#include <linux/extcon/of_extcon.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/usb/otg.h>
 
@@ -155,9 +137,21 @@ struct dwc3_omap {
 	u32			revision;
 
 	u32			dma_status:1;
+
+	struct extcon_specific_cable_nb extcon_vbus_dev;
+	struct extcon_specific_cable_nb extcon_id_dev;
+	struct notifier_block	vbus_nb;
+	struct notifier_block	id_nb;
+
+	struct regulator	*vbus_reg;
 };
 
-static struct dwc3_omap		*_omap;
+enum omap_dwc3_vbus_id_status {
+	OMAP_DWC3_ID_FLOAT,
+	OMAP_DWC3_ID_GROUND,
+	OMAP_DWC3_VBUS_OFF,
+	OMAP_DWC3_VBUS_VALID,
+};
 
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
@@ -221,18 +215,24 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
 						omap->irq0_offset, value);
 }
 
-int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
+	enum omap_dwc3_vbus_id_status status)
 {
-	u32			val;
-	struct dwc3_omap	*omap = _omap;
-
-	if (!omap)
-		return -EPROBE_DEFER;
+	int	ret;
+	u32	val;
 
 	switch (status) {
 	case OMAP_DWC3_ID_GROUND:
 		dev_dbg(omap->dev, "ID GND\n");
 
+		if (omap->vbus_reg) {
+			ret = regulator_enable(omap->vbus_reg);
+			if (ret) {
+				dev_dbg(omap->dev, "regulator enable failed\n");
+				return;
+			}
+		}
+
 		val = dwc3_omap_read_utmi_status(omap);
 		val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
 				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
@@ -255,6 +255,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 		break;
 
 	case OMAP_DWC3_ID_FLOAT:
+		if (omap->vbus_reg)
+			regulator_disable(omap->vbus_reg);
+
 	case OMAP_DWC3_VBUS_OFF:
 		dev_dbg(omap->dev, "VBUS Disconnect\n");
 
@@ -268,12 +271,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 		break;
 
 	default:
-		dev_dbg(omap->dev, "ID float\n");
+		dev_dbg(omap->dev, "invalid state\n");
 	}
-
-	return 0;
 }
-EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
 
 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 {
@@ -366,6 +366,32 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
 
 static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
 
+static int dwc3_omap_id_notifier(struct notifier_block *nb,
+	unsigned long event, void *ptr)
+{
+	struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb);
+
+	if (event)
+		dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+	else
+		dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
+
+	return NOTIFY_DONE;
+}
+
+static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
+	unsigned long event, void *ptr)
+{
+	struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb);
+
+	if (event)
+		dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+	else
+		dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
+
+	return NOTIFY_DONE;
+}
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct device_node	*node = pdev->dev.of_node;
@@ -373,6 +399,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
+	struct extcon_dev	*edev;
+	struct regulator	*vbus_reg = NULL;
 
 	int			ret = -ENOMEM;
 	int			irq;
@@ -409,10 +437,16 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	base = devm_ioremap_nocache(dev, res->start, resource_size(res));
-	if (!base) {
-		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	if (of_property_read_bool(node, "vbus-supply")) {
+		vbus_reg = devm_regulator_get(dev, "vbus");
+		if (IS_ERR(vbus_reg)) {
+			dev_err(dev, "vbus init failed\n");
+			return PTR_ERR(vbus_reg);
+		}
 	}
 
 	spin_lock_init(&omap->lock);
@@ -420,14 +454,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->base	= base;
+	omap->vbus_reg	= vbus_reg;
 	dev->dma_mask	= &dwc3_omap_dma_mask;
 
-	/*
-	 * REVISIT if we ever have two instances of the wrapper, we will be
-	 * in big trouble
-	 */
-	_omap	= omap;
-
 	pm_runtime_enable(dev);
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
@@ -502,14 +531,46 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 	dwc3_omap_enable_irqs(omap);
 
+	if (of_property_read_bool(node, "extcon")) {
+		edev = of_extcon_get_extcon_dev(dev, 0);
+		if (IS_ERR(edev)) {
+			dev_vdbg(dev, "couldn't get extcon device\n");
+			ret = PTR_ERR(edev);
+			goto err2;
+		}
+
+		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
+		ret = extcon_register_interest(&omap->extcon_vbus_dev,
+			edev->name, "USB", &omap->vbus_nb);
+		if (ret < 0)
+			dev_vdbg(dev, "failed to register notifier for USB\n");
+		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
+		ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
+					 "USB-HOST", &omap->id_nb);
+		if (ret < 0)
+			dev_vdbg(dev,
+				"failed to register notifier for USB-HOST\n");
+
+		if (extcon_get_cable_state(edev, "USB") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+		if (extcon_get_cable_state(edev, "USB-HOST") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+	}
+
 	ret = of_platform_populate(node, NULL, NULL, dev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to create dwc3 core\n");
-		goto err2;
+		goto err3;
 	}
 
 	return 0;
 
+err3:
+	if (omap->extcon_vbus_dev.edev)
+		extcon_unregister_interest(&omap->extcon_vbus_dev);
+	if (omap->extcon_id_dev.edev)
+		extcon_unregister_interest(&omap->extcon_id_dev);
+
 err2:
 	dwc3_omap_disable_irqs(omap);
 
@@ -526,6 +587,10 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 {
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
+	if (omap->extcon_vbus_dev.edev)
+		extcon_unregister_interest(&omap->extcon_vbus_dev);
+	if (omap->extcon_id_dev.edev)
+		extcon_unregister_interest(&omap->extcon_id_dev);
 	dwc3_omap_disable_irqs(omap);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -610,5 +675,5 @@ module_platform_driver(dwc3_omap_driver);
 
 MODULE_ALIAS("platform:omap-dwc3");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index ed07ec0..5d746e5 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -257,7 +237,7 @@ static struct pci_driver dwc3_pci_driver = {
 };
 
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
 
 module_pci_driver(dwc3_pci_driver);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 5acbb94..7fa93f4 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -168,6 +148,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 
 		direction = !dwc->ep0_expect_in;
 		dwc->delayed_status = false;
+		usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
 
 		if (dwc->ep0state == EP0_STATUS_PHASE)
 			__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
@@ -553,8 +534,16 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		/* if the cfg matches and the cfg is non zero */
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
-			usb_gadget_set_state(&dwc->gadget,
-					USB_STATE_CONFIGURED);
+
+			/*
+			 * only change state if set_config has already
+			 * been processed. If gadget driver returns
+			 * USB_GADGET_DELAYED_STATUS, we will wait
+			 * to change the state on the next usb_ep_queue()
+			 */
+			if (ret == 0)
+				usb_gadget_set_state(&dwc->gadget,
+						USB_STATE_CONFIGURED);
 
 			/*
 			 * Enable transition to U1/U2 state when
@@ -571,7 +560,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 
 	case USB_STATE_CONFIGURED:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
-		if (!cfg)
+		if (!cfg && !ret)
 			usb_gadget_set_state(&dwc->gadget,
 					USB_STATE_ADDRESS);
 		break;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f77083f..f168eae 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -520,6 +500,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
 	u32			reg;
 	int			ret = -ENOMEM;
 
+	dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
+
 	if (!(dep->flags & DWC3_EP_ENABLED)) {
 		ret = dwc3_gadget_start_config(dwc, dep);
 		if (ret)
@@ -676,8 +658,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
 		dev_err(dwc->dev, "invalid endpoint transfer type\n");
 	}
 
-	dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
-
 	spin_lock_irqsave(&dwc->lock, flags);
 	ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1508,6 +1488,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	int			irq;
 	u32			reg;
 
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+			IRQF_SHARED, "dwc3", dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+				irq, ret);
+		goto err0;
+	}
+
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	if (dwc->gadget_driver) {
@@ -1515,7 +1504,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 				dwc->gadget.name,
 				dwc->gadget_driver->driver.name);
 		ret = -EBUSY;
-		goto err0;
+		goto err1;
 	}
 
 	dwc->gadget_driver	= driver;
@@ -1536,10 +1525,25 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	 * STAR#9000525659: Clock Domain Crossing on DCTL in
 	 * USB 2.0 Mode
 	 */
-	if (dwc->revision < DWC3_REVISION_220A)
+	if (dwc->revision < DWC3_REVISION_220A) {
 		reg |= DWC3_DCFG_SUPERSPEED;
-	else
-		reg |= dwc->maximum_speed;
+	} else {
+		switch (dwc->maximum_speed) {
+		case USB_SPEED_LOW:
+			reg |= DWC3_DSTS_LOWSPEED;
+			break;
+		case USB_SPEED_FULL:
+			reg |= DWC3_DSTS_FULLSPEED1;
+			break;
+		case USB_SPEED_HIGH:
+			reg |= DWC3_DSTS_HIGHSPEED;
+			break;
+		case USB_SPEED_SUPER:	/* FALLTHROUGH */
+		case USB_SPEED_UNKNOWN:	/* FALTHROUGH */
+		default:
+			reg |= DWC3_DSTS_SUPERSPEED;
+		}
+	}
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
 	dwc->start_config_issued = false;
@@ -1551,42 +1555,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-		goto err0;
+		goto err2;
 	}
 
 	dep = dwc->eps[1];
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-		goto err1;
+		goto err3;
 	}
 
 	/* begin to receive SETUP packets */
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
-			IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-				irq, ret);
-		goto err1;
-	}
-
 	dwc3_gadget_enable_irq(dwc);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return 0;
 
-err1:
+err3:
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 
-err0:
+err2:
 	dwc->gadget_driver = NULL;
+
+err1:
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
+	free_irq(irq, dwc);
+
+err0:
 	return ret;
 }
 
@@ -1600,9 +1600,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	dwc3_gadget_disable_irq(dwc);
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-	free_irq(irq, dwc);
-
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 	__dwc3_gadget_ep_disable(dwc->eps[1]);
 
@@ -1610,6 +1607,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	free_irq(irq, dwc);
+
 	return 0;
 }
 
@@ -1642,13 +1642,15 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
 
 		dep->dwc = dwc;
 		dep->number = epnum;
+		dep->direction = !!direction;
 		dwc->eps[epnum] = dep;
 
 		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 				(epnum & 1) ? "in" : "out");
 
 		dep->endpoint.name = dep->name;
-		dep->direction = (epnum & 1);
+
+		dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
 
 		if (epnum == 0 || epnum == 1) {
 			dep->endpoint.maxpacket = 512;
@@ -2105,34 +2107,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 	dwc->setup_packet_pending = false;
 }
 
-static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
-{
-	u32			reg;
-
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
-
-	if (suspend)
-		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-	else
-		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
-
-	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
-}
-
-static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend)
-{
-	u32			reg;
-
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
-
-	if (suspend)
-		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-	else
-		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
-
-	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
-}
-
 static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
 	u32			reg;
@@ -2173,13 +2147,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	/* after reset -> Default State */
 	usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
-	/* Recent versions support automatic phy suspend and don't need this */
-	if (dwc->revision < DWC3_REVISION_194A) {
-		/* Resume PHYs */
-		dwc3_gadget_usb2_phy_suspend(dwc, false);
-		dwc3_gadget_usb3_phy_suspend(dwc, false);
-	}
-
 	if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
 		dwc3_disconnect_gadget(dwc);
 
@@ -2223,20 +2190,6 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 }
 
-static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
-{
-	switch (speed) {
-	case USB_SPEED_SUPER:
-		dwc3_gadget_usb2_phy_suspend(dwc, true);
-		break;
-	case USB_SPEED_HIGH:
-	case USB_SPEED_FULL:
-	case USB_SPEED_LOW:
-		dwc3_gadget_usb3_phy_suspend(dwc, true);
-		break;
-	}
-}
-
 static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 {
 	struct dwc3_ep		*dep;
@@ -2312,12 +2265,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	}
 
-	/* Recent versions support automatic phy suspend and don't need this */
-	if (dwc->revision < DWC3_REVISION_194A) {
-		/* Suspend unneeded PHY */
-		dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed);
-	}
-
 	dep = dwc->eps[0];
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
 	if (ret) {
@@ -2495,61 +2442,75 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
 	}
 }
 
-static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 {
-	struct dwc3 *dwc = _dwc;
-	unsigned long flags;
+	struct dwc3_event_buffer *evt;
 	irqreturn_t ret = IRQ_NONE;
-	int i;
+	int left;
+	u32 reg;
 
-	spin_lock_irqsave(&dwc->lock, flags);
+	evt = dwc->ev_buffs[buf];
+	left = evt->count;
 
-	for (i = 0; i < dwc->num_event_buffers; i++) {
-		struct dwc3_event_buffer *evt;
-		int			left;
+	if (!(evt->flags & DWC3_EVENT_PENDING))
+		return IRQ_NONE;
 
-		evt = dwc->ev_buffs[i];
-		left = evt->count;
+	while (left > 0) {
+		union dwc3_event event;
 
-		if (!(evt->flags & DWC3_EVENT_PENDING))
-			continue;
+		event.raw = *(u32 *) (evt->buf + evt->lpos);
 
-		while (left > 0) {
-			union dwc3_event event;
+		dwc3_process_event_entry(dwc, &event);
 
-			event.raw = *(u32 *) (evt->buf + evt->lpos);
+		/*
+		 * FIXME we wrap around correctly to the next entry as
+		 * almost all entries are 4 bytes in size. There is one
+		 * entry which has 12 bytes which is a regular entry
+		 * followed by 8 bytes data. ATM I don't know how
+		 * things are organized if we get next to the a
+		 * boundary so I worry about that once we try to handle
+		 * that.
+		 */
+		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
+		left -= 4;
 
-			dwc3_process_event_entry(dwc, &event);
+		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
+	}
 
-			/*
-			 * FIXME we wrap around correctly to the next entry as
-			 * almost all entries are 4 bytes in size. There is one
-			 * entry which has 12 bytes which is a regular entry
-			 * followed by 8 bytes data. ATM I don't know how
-			 * things are organized if we get next to the a
-			 * boundary so I worry about that once we try to handle
-			 * that.
-			 */
-			evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
-			left -= 4;
+	evt->count = 0;
+	evt->flags &= ~DWC3_EVENT_PENDING;
+	ret = IRQ_HANDLED;
 
-			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
-		}
+	/* Unmask interrupt */
+	reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
+	reg &= ~DWC3_GEVNTSIZ_INTMASK;
+	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
 
-		evt->count = 0;
-		evt->flags &= ~DWC3_EVENT_PENDING;
-		ret = IRQ_HANDLED;
-	}
+	return ret;
+}
+
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+{
+	struct dwc3 *dwc = _dwc;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+	int i;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	for (i = 0; i < dwc->num_event_buffers; i++)
+		ret |= dwc3_process_event_buf(dwc, i);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return ret;
 }
 
-static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
+static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf)
 {
 	struct dwc3_event_buffer *evt;
 	u32 count;
+	u32 reg;
 
 	evt = dwc->ev_buffs[buf];
 
@@ -2561,6 +2522,11 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 	evt->count = count;
 	evt->flags |= DWC3_EVENT_PENDING;
 
+	/* Mask interrupt */
+	reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
+	reg |= DWC3_GEVNTSIZ_INTMASK;
+	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
+
 	return IRQ_WAKE_THREAD;
 }
 
@@ -2575,7 +2541,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 	for (i = 0; i < dwc->num_event_buffers; i++) {
 		irqreturn_t status;
 
-		status = dwc3_process_event_buf(dwc, i);
+		status = dwc3_check_event_buf(dwc, i);
 		if (status == IRQ_WAKE_THREAD)
 			ret = status;
 	}
@@ -2593,7 +2559,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
  */
 int dwc3_gadget_init(struct dwc3 *dwc)
 {
-	u32					reg;
 	int					ret;
 
 	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
@@ -2643,16 +2608,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	if (ret)
 		goto err4;
 
-	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-	reg |= DWC3_DCFG_LPM_CAP;
-	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
-	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
-	if (dwc->revision >= DWC3_REVISION_194A) {
-		dwc3_gadget_usb2_phy_suspend(dwc, false);
-		dwc3_gadget_usb3_phy_suspend(dwc, false);
-	}
-
 	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 	if (ret) {
 		dev_err(dwc->dev, "failed to register udc\n");
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 99e6d72..febe1aa 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DRIVERS_USB_DWC3_GADGET_H
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 0fa1846..32db328 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -5,34 +5,14 @@
  *
  * Authors: Felipe Balbi <balbi@ti.com>,
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/platform_device.h>
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index a50f76b..d94441c 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DRIVERS_USB_DWC3_IO_H
diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
new file mode 100644
index 0000000..7db34f0
--- /dev/null
+++ b/drivers/usb/dwc3/platform_data.h
@@ -0,0 +1,27 @@
+/**
+ * platform_data.h - USB DWC3 Platform Data Support
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Felipe Balbi <balbi@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+
+struct dwc3_platform_data {
+	enum usb_device_speed maximum_speed;
+	enum usb_dr_mode dr_mode;
+	bool tx_fifo_resize;
+};
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 8e93683..1e3f525 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -144,7 +144,6 @@ config USB_AT91
 config USB_LPC32XX
 	tristate "LPC32XX USB Peripheral Controller"
 	depends on ARCH_LPC32XX
-	depends on USB_PHY
 	select USB_ISP1301
 	help
 	   This option selects the USB device controller in the LPC32xx SoC.
@@ -206,7 +205,6 @@ config USB_FOTG210_UDC
 config USB_OMAP
 	tristate "OMAP USB Device Controller"
 	depends on ARCH_OMAP1
-	depends on USB_PHY
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 	help
 	   Many Texas Instruments OMAP processors have flexible full
@@ -287,21 +285,6 @@ config USB_S3C_HSOTG
 	  The Samsung S3C64XX USB2.0 high-speed gadget controller
 	  integrated into the S3C64XX series SoC.
 
-config USB_IMX
-	tristate "Freescale i.MX1 USB Peripheral Controller"
-	depends on ARCH_MXC
-	depends on BROKEN
-	help
-	   Freescale's i.MX1 includes an integrated full speed
-	   USB 1.1 device controller.
-
-	   It has Six fixed-function endpoints, as well as endpoint
-	   zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "imx_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
 config USB_S3C2410
 	tristate "S3C2410 USB Device Controller"
 	depends on ARCH_S3C24XX
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index bad08e6..386db9d 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
 obj-$(CONFIG_USB_PXA25X)	+= pxa25x_udc.o
 obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
-obj-$(CONFIG_USB_IMX)		+= imx_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
 obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index d9a6add0..d237429 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1697,7 +1697,7 @@ static int at91udc_probe(struct platform_device *pdev)
 	int		retval;
 	struct resource	*res;
 
-	if (!dev->platform_data && !pdev->dev.of_node) {
+	if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
 		/* small (so we copy it) but critical! */
 		DBG("missing platform_data\n");
 		return -ENODEV;
@@ -1728,7 +1728,7 @@ static int at91udc_probe(struct platform_device *pdev)
 	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
 		at91udc_of_init(udc, pdev->dev.of_node);
 	else
-		memcpy(&udc->board, dev->platform_data,
+		memcpy(&udc->board, dev_get_platdata(dev),
 		       sizeof(struct at91_udc_data));
 	udc->pdev = pdev;
 	udc->enabled = 0;
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 1d97222..40d2338 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1772,6 +1772,7 @@ out:
 static int atmel_usba_start(struct usb_gadget *gadget,
 		struct usb_gadget_driver *driver)
 {
+	int ret = 0;
 	struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
 	unsigned long flags;
 
@@ -1781,8 +1782,14 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 	udc->driver = driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	clk_enable(udc->pclk);
-	clk_enable(udc->hclk);
+	ret = clk_prepare_enable(udc->pclk);
+	if (ret)
+		goto out;
+	ret = clk_prepare_enable(udc->hclk);
+	if (ret) {
+		clk_disable_unprepare(udc->pclk);
+		goto out;
+	}
 
 	DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
 
@@ -1797,9 +1804,11 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 		usba_writel(udc, CTRL, USBA_ENABLE_MASK);
 		usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
 	}
+
+out:
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	return 0;
+	return ret;
 }
 
 static int atmel_usba_stop(struct usb_gadget *gadget,
@@ -1822,8 +1831,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
 
 	udc->driver = NULL;
 
-	clk_disable(udc->hclk);
-	clk_disable(udc->pclk);
+	clk_disable_unprepare(udc->hclk);
+	clk_disable_unprepare(udc->pclk);
 
 	DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name);
 
@@ -1922,7 +1931,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
 static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
 						 struct usba_udc *udc)
 {
-	struct usba_platform_data *pdata = pdev->dev.platform_data;
+	struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct usba_ep *eps;
 	int i;
 
@@ -2022,10 +2031,14 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, udc);
 
 	/* Make sure we start from a clean slate */
-	clk_enable(pclk);
+	ret = clk_prepare_enable(pclk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
+		goto err_clk_enable;
+	}
 	toggle_bias(0);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-	clk_disable(pclk);
+	clk_disable_unprepare(pclk);
 
 	if (pdev->dev.of_node)
 		udc->usba_ep = atmel_udc_of_init(pdev, udc);
@@ -2081,6 +2094,7 @@ err_add_udc:
 	free_irq(irq, udc);
 err_request_irq:
 err_alloc_ep:
+err_clk_enable:
 	iounmap(udc->fifo);
 err_map_fifo:
 	iounmap(udc->regs);
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index fd24cb4..c58fcf1 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -2313,7 +2313,7 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
 static int bcm63xx_udc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
+	struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
 	struct bcm63xx_udc *udc;
 	struct resource *res;
 	int rc = -ENOMEM, i, irq;
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index d3bd7b0..9b140fc 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -33,7 +33,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
 	unsigned long freq;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 
 	mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(mxc_ipg_clk)) {
@@ -80,7 +80,7 @@ eclkrate:
 
 int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int ret = 0;
 
 	/* workaround ENGcm09152 for i.MX35 */
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index a766a4c..36ac7cf 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2248,7 +2248,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
 	struct fsl_usb2_platform_data *pdata;
 	size_t size;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	udc->phy_mode = pdata->phy_mode;
 
 	udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
@@ -2343,7 +2343,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	udc_controller->pdata = pdata;
 	spin_lock_init(&udc_controller->lock);
 	udc_controller->stopped = 1;
@@ -2524,7 +2524,7 @@ err_kfree:
 static int __exit fsl_udc_remove(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	DECLARE_COMPLETION(done);
 
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index c36260ea..778613e 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -185,7 +185,7 @@ static int __exit hid_unbind(struct usb_composite_dev *cdev)
 
 static int __init hidg_plat_driver_probe(struct platform_device *pdev)
 {
-	struct hidg_func_descriptor *func = pdev->dev.platform_data;
+	struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
 	struct hidg_func_node *entry;
 
 	if (!func) {
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
deleted file mode 100644
index 9b2d24e..0000000
--- a/drivers/usb/gadget/imx_udc.c
+++ /dev/null
@@ -1,1544 +0,0 @@
-/*
- *	driver/usb/gadget/imx_udc.c
- *
- *	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
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include <linux/platform_data/usb-imx_udc.h>
-#include <mach/hardware.h>
-
-#include "imx_udc.h"
-
-static const char driver_name[] = "imx_udc";
-static const char ep0name[] = "ep0";
-
-void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb,
-							enum ep0_state stat);
-
-/*******************************************************************************
- * IMX UDC hardware related functions
- *******************************************************************************
- */
-
-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);
-	imx_usb->gadget.speed = USB_SPEED_FULL;
-}
-
-void imx_udc_disable(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);
-
-	ep0_chg_stat(__func__, imx_usb, EP0_IDLE);
-	imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-}
-
-void imx_udc_reset(struct imx_udc_struct *imx_usb)
-{
-	int temp = __raw_readl(imx_usb->base + USB_ENAB);
-
-	/* set RST bit */
-	__raw_writel(temp | ENAB_RST, imx_usb->base + USB_ENAB);
-
-	/* wait RST bit to clear */
-	do {} while (__raw_readl(imx_usb->base + USB_ENAB) & ENAB_RST);
-
-	/* wait CFG bit to assert */
-	do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG));
-
-	/* udc module is now ready */
-}
-
-void imx_udc_config(struct imx_udc_struct *imx_usb)
-{
-	u8 ep_conf[5];
-	u8 i, j, cfg;
-	struct imx_ep_struct *imx_ep;
-
-	/* wait CFG bit to assert */
-	do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG));
-
-	/* Download the endpoint buffer for endpoint 0. */
-	for (j = 0; j < 5; j++) {
-		i = (j == 2 ? imx_usb->imx_ep[0].fifosize : 0x00);
-		__raw_writeb(i, imx_usb->base + USB_DDAT);
-		do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_BSY);
-	}
-
-	/* Download the endpoint buffers for endpoints 1-5.
-	 * We specify two configurations, one interface
-	 */
-	for (cfg = 1; cfg < 3; cfg++) {
-		for (i = 1; i < IMX_USB_NB_EP; i++) {
-			imx_ep = &imx_usb->imx_ep[i];
-			/* EP no | Config no */
-			ep_conf[0] = (i << 4) | (cfg << 2);
-			/* Type | Direction */
-			ep_conf[1] = (imx_ep->bmAttributes << 3) |
-					(EP_DIR(imx_ep) << 2);
-			/* Max packet size */
-			ep_conf[2] = imx_ep->fifosize;
-			/* TRXTYP */
-			ep_conf[3] = 0xC0;
-			/* FIFO no */
-			ep_conf[4] = i;
-
-			D_INI(imx_usb->dev,
-				"<%s> ep%d_conf[%d]:"
-				"[%02x-%02x-%02x-%02x-%02x]\n",
-				__func__, i, cfg,
-				ep_conf[0], ep_conf[1], ep_conf[2],
-				ep_conf[3], ep_conf[4]);
-
-			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)
-					& DADR_BSY);
-			}
-		}
-	}
-
-	/* wait CFG bit to clear */
-	do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG);
-}
-
-void imx_udc_init_irq(struct imx_udc_struct *imx_usb)
-{
-	int i;
-
-	/* Mask and clear all irqs */
-	__raw_writel(0xFFFFFFFF, imx_usb->base + USB_MASK);
-	__raw_writel(0xFFFFFFFF, imx_usb->base + USB_INTR);
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		__raw_writel(0x1FF, imx_usb->base + USB_EP_MASK(i));
-		__raw_writel(0x1FF, imx_usb->base + USB_EP_INTR(i));
-	}
-
-	/* Enable USB irqs */
-	__raw_writel(INTR_MSOF | INTR_FRAME_MATCH, imx_usb->base + USB_MASK);
-
-	/* Enable EP0 irqs */
-	__raw_writel(0x1FF & ~(EPINTR_DEVREQ | EPINTR_MDEVREQ | EPINTR_EOT
-		| EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL),
-		imx_usb->base + USB_EP_MASK(0));
-}
-
-void imx_udc_init_ep(struct imx_udc_struct *imx_usb)
-{
-	int i, max, temp;
-	struct imx_ep_struct *imx_ep;
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-		switch (imx_ep->fifosize) {
-		case 8:
-			max = 0;
-			break;
-		case 16:
-			max = 1;
-			break;
-		case 32:
-			max = 2;
-			break;
-		case 64:
-			max = 3;
-			break;
-		default:
-			max = 1;
-			break;
-		}
-		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));
-		D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i,
-			__raw_readl(imx_usb->base + USB_EP_STAT(i)));
-	}
-}
-
-void imx_udc_init_fifo(struct imx_udc_struct *imx_usb)
-{
-	int i, temp;
-	struct imx_ep_struct *imx_ep;
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-
-		/* Fifo control */
-		temp = EP_DIR(imx_ep) ? 0x0B000000 : 0x0F000000;
-		__raw_writel(temp, imx_usb->base + USB_EP_FCTRL(i));
-		D_INI(imx_usb->dev, "<%s> ep%d_fctrl %08x\n", __func__, i,
-			__raw_readl(imx_usb->base + USB_EP_FCTRL(i)));
-
-		/* Fifo alarm */
-		temp = (i ? imx_ep->fifosize / 2 : 0);
-		__raw_writel(temp, imx_usb->base + USB_EP_FALRM(i));
-		D_INI(imx_usb->dev, "<%s> ep%d_falrm %08x\n", __func__, i,
-			__raw_readl(imx_usb->base + USB_EP_FALRM(i)));
-	}
-}
-
-static void imx_udc_init(struct imx_udc_struct *imx_usb)
-{
-	/* Reset UDC */
-	imx_udc_reset(imx_usb);
-
-	/* Download config to enpoint buffer */
-	imx_udc_config(imx_usb);
-
-	/* Setup interrups */
-	imx_udc_init_irq(imx_usb);
-
-	/* Setup endpoints */
-	imx_udc_init_ep(imx_usb);
-
-	/* Setup fifos */
-	imx_udc_init_fifo(imx_usb);
-}
-
-void imx_ep_irq_enable(struct imx_ep_struct *imx_ep)
-{
-
-	int i = EP_NO(imx_ep);
-
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i));
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i));
-	__raw_writel(0x1FF & ~(EPINTR_EOT | EPINTR_EOF),
-		imx_ep->imx_usb->base + USB_EP_MASK(i));
-}
-
-void imx_ep_irq_disable(struct imx_ep_struct *imx_ep)
-{
-
-	int i = EP_NO(imx_ep);
-
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i));
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i));
-}
-
-int imx_ep_empty(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-
-	return __raw_readl(imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)))
-			& FSTAT_EMPTY;
-}
-
-unsigned imx_fifo_bcount(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-
-	return (__raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)))
-			& EPSTAT_BCOUNT) >> 16;
-}
-
-void imx_flush(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-
-	int temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-	__raw_writel(temp | EPSTAT_FLUSH,
-		imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-}
-
-void imx_ep_stall(struct imx_ep_struct *imx_ep)
-{
-	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);
-
-	imx_flush(imx_ep);
-
-	/* Special care for ep0 */
-	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);
-		temp = __raw_readl(imx_usb->base + USB_CTRL);
-		__raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL);
-	}
-	else {
-		temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-		__raw_writel(temp | EPSTAT_STALL,
-			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)));
-			if (!(temp & EPSTAT_STALL))
-	 			break;
-	 		udelay(20);
-	 	}
-		if (i == 100)
-			D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n",
-				__func__, imx_ep->ep.name);
-	}
-}
-
-static int imx_udc_get_frame(struct usb_gadget *_gadget)
-{
-	struct imx_udc_struct *imx_usb = container_of(_gadget,
-			struct imx_udc_struct, gadget);
-
-	return __raw_readl(imx_usb->base + USB_FRAME) & 0x7FF;
-}
-
-static int imx_udc_wakeup(struct usb_gadget *_gadget)
-{
-	return 0;
-}
-
-/*******************************************************************************
- * USB request control functions
- *******************************************************************************
- */
-
-static void ep_add_request(struct imx_ep_struct *imx_ep,
-							struct imx_request *req)
-{
-	if (unlikely(!req))
-		return;
-
-	req->in_use = 1;
-	list_add_tail(&req->queue, &imx_ep->queue);
-}
-
-static void ep_del_request(struct imx_ep_struct *imx_ep,
-							struct imx_request *req)
-{
-	if (unlikely(!req))
-		return;
-
-	list_del_init(&req->queue);
-	req->in_use = 0;
-}
-
-static void done(struct imx_ep_struct *imx_ep,
-					struct imx_request *req, int status)
-{
-	ep_del_request(imx_ep, req);
-
-	if (likely(req->req.status == -EINPROGRESS))
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	if (status && status != -ESHUTDOWN)
-		D_ERR(imx_ep->imx_usb->dev,
-			"<%s> complete %s req %p stat %d len %u/%u\n", __func__,
-			imx_ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
-
-	req->req.complete(&imx_ep->ep, &req->req);
-}
-
-static void nuke(struct imx_ep_struct *imx_ep, int status)
-{
-	struct imx_request *req;
-
-	while (!list_empty(&imx_ep->queue)) {
-		req = list_entry(imx_ep->queue.next, struct imx_request, queue);
-		done(imx_ep, req, status);
-	}
-}
-
-/*******************************************************************************
- * Data tansfer over USB functions
- *******************************************************************************
- */
-static int read_packet(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	u8	*buf;
-	int	bytes_ep, bufferspace, count, i;
-
-	bytes_ep = imx_fifo_bcount(imx_ep);
-	bufferspace = req->req.length - req->req.actual;
-
-	buf = req->req.buf + req->req.actual;
-	prefetchw(buf);
-
-	if (unlikely(imx_ep_empty(imx_ep)))
-		count = 0;	/* zlp */
-	else
-		count = min(bytes_ep, bufferspace);
-
-	for (i = count; i > 0; i--)
-		*buf++ = __raw_readb(imx_ep->imx_usb->base
-						+ USB_EP_FDAT0(EP_NO(imx_ep)));
-	req->req.actual += count;
-
-	return count;
-}
-
-static int write_packet(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	u8	*buf;
-	int	length, count, temp;
-
-	if (unlikely(__raw_readl(imx_ep->imx_usb->base +
-				 USB_EP_STAT(EP_NO(imx_ep))) & EPSTAT_ZLPS)) {
-		D_TRX(imx_ep->imx_usb->dev, "<%s> zlp still queued in EP %s\n",
-			__func__, imx_ep->ep.name);
-		return -1;
-	}
-
-	buf = req->req.buf + req->req.actual;
-	prefetch(buf);
-
-	length = min(req->req.length - req->req.actual, (u32)imx_ep->fifosize);
-
-	if (imx_fifo_bcount(imx_ep) + length > imx_ep->fifosize) {
-		D_TRX(imx_ep->imx_usb->dev, "<%s> packet overfill %s fifo\n",
-			__func__, imx_ep->ep.name);
-		return -1;
-	}
-
-	req->req.actual += length;
-	count = length;
-
-	if (!count && req->req.zero) {	/* zlp */
-		temp = __raw_readl(imx_ep->imx_usb->base
-			+ USB_EP_STAT(EP_NO(imx_ep)));
-		__raw_writel(temp | EPSTAT_ZLPS, imx_ep->imx_usb->base
-			+ USB_EP_STAT(EP_NO(imx_ep)));
-		D_TRX(imx_ep->imx_usb->dev, "<%s> zero packet\n", __func__);
-		return 0;
-	}
-
-	while (count--) {
-		if (count == 0) {	/* last byte */
-			temp = __raw_readl(imx_ep->imx_usb->base
-				+ USB_EP_FCTRL(EP_NO(imx_ep)));
-			__raw_writel(temp | FCTRL_WFR, imx_ep->imx_usb->base
-				+ USB_EP_FCTRL(EP_NO(imx_ep)));
-		}
-		__raw_writeb(*buf++,
-			imx_ep->imx_usb->base + USB_EP_FDAT0(EP_NO(imx_ep)));
-	}
-
-	return length;
-}
-
-static int read_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	int 	bytes = 0,
-		count,
-		completed = 0;
-
-	while (__raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)))
-		& FSTAT_FR) {
-			count = read_packet(imx_ep, req);
-			bytes += count;
-
-			completed = (count != imx_ep->fifosize);
-			if (completed || req->req.actual == req->req.length) {
-				completed = 1;
-				break;
-			}
-	}
-
-	if (completed || !req->req.length) {
-		done(imx_ep, req, 0);
-		D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n",
-			__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);
-	}
-
-	D_TRX(imx_ep->imx_usb->dev, "<%s> bytes read: %d\n", __func__, bytes);
-
-	return completed;
-}
-
-static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	int	bytes = 0,
-		count,
-		completed = 0;
-
-	while (!completed) {
-		count = write_packet(imx_ep, req);
-		if (count < 0)
-			break; /* busy */
-		bytes += count;
-
-		/* last packet "must be" short (or a zlp) */
-		completed = (count != imx_ep->fifosize);
-
-		if (unlikely(completed)) {
-			done(imx_ep, req, 0);
-			D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n",
-				__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);
-		}
-	}
-
-	D_TRX(imx_ep->imx_usb->dev, "<%s> bytes sent: %d\n", __func__, bytes);
-
-	return completed;
-}
-
-/*******************************************************************************
- * Endpoint handlers
- *******************************************************************************
- */
-static int handle_ep(struct imx_ep_struct *imx_ep)
-{
-	struct imx_request *req;
-	int completed = 0;
-
-	do {
-		if (!list_empty(&imx_ep->queue))
-			req = list_entry(imx_ep->queue.next,
-				struct imx_request, queue);
-		else {
-			D_REQ(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
-				__func__, imx_ep->ep.name);
-			return 0;
-		}
-
-		if (EP_DIR(imx_ep))	/* to host */
-			completed = write_fifo(imx_ep, req);
-		else			/* to device */
-			completed = read_fifo(imx_ep, req);
-
-		dump_ep_stat(__func__, imx_ep);
-
-	} while (completed);
-
-	return 0;
-}
-
-static int handle_ep0(struct imx_ep_struct *imx_ep)
-{
-	struct imx_request *req = NULL;
-	int ret = 0;
-
-	if (!list_empty(&imx_ep->queue)) {
-		req = list_entry(imx_ep->queue.next, struct imx_request, queue);
-
-		switch (imx_ep->imx_usb->ep0state) {
-
-		case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR */
-			write_fifo(imx_ep, req);
-			break;
-		case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR */
-			read_fifo(imx_ep, req);
-			break;
-		default:
-			D_EP0(imx_ep->imx_usb->dev,
-				"<%s> ep0 i/o, odd state %d\n",
-				__func__, imx_ep->imx_usb->ep0state);
-			ep_del_request(imx_ep, req);
-			ret = -EL2HLT;
-			break;
-		}
-	}
-
-	else
-		D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
-						__func__, imx_ep->ep.name);
-
-	return ret;
-}
-
-static void handle_ep0_devreq(struct imx_udc_struct *imx_usb)
-{
-	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
-	union {
-		struct usb_ctrlrequest	r;
-		u8			raw[8];
-		u32			word[2];
-	} u;
-	int temp, i;
-
-	nuke(imx_ep, -EPROTO);
-
-	/* read SETUP packet */
-	for (i = 0; i < 2; i++) {
-		if (imx_ep_empty(imx_ep)) {
-			D_ERR(imx_usb->dev,
-				"<%s> no setup packet received\n", __func__);
-			goto stall;
-		}
-		u.word[i] = __raw_readl(imx_usb->base
-						+ USB_EP_FDAT(EP_NO(imx_ep)));
-	}
-
-	temp = imx_ep_empty(imx_ep);
-	while (!imx_ep_empty(imx_ep)) {
-		i = __raw_readl(imx_usb->base +	USB_EP_FDAT(EP_NO(imx_ep)));
-		D_ERR(imx_usb->dev,
-			"<%s> wrong to have extra bytes for setup : 0x%08x\n",
-			__func__, i);
-	}
-	if (!temp)
-		goto stall;
-
-	le16_to_cpus(&u.r.wValue);
-	le16_to_cpus(&u.r.wIndex);
-	le16_to_cpus(&u.r.wLength);
-
-	D_REQ(imx_usb->dev, "<%s> SETUP %02x.%02x v%04x i%04x l%04x\n",
-		__func__, u.r.bRequestType, u.r.bRequest,
-		u.r.wValue, u.r.wIndex, u.r.wLength);
-
-	if (imx_usb->set_config) {
-		/* NACK the host by using CMDOVER */
-		temp = __raw_readl(imx_usb->base + USB_CTRL);
-		__raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
-
-		D_ERR(imx_usb->dev,
-			"<%s> set config req is pending, NACK the host\n",
-			__func__);
-		return;
-	}
-
-	if (u.r.bRequestType & USB_DIR_IN)
-		ep0_chg_stat(__func__, imx_usb, EP0_IN_DATA_PHASE);
-	else
-		ep0_chg_stat(__func__, imx_usb, EP0_OUT_DATA_PHASE);
-
-	i = imx_usb->driver->setup(&imx_usb->gadget, &u.r);
-	if (i < 0) {
-		D_ERR(imx_usb->dev, "<%s> device setup error %d\n",
-			__func__, i);
-		goto stall;
-	}
-
-	return;
-stall:
-	D_ERR(imx_usb->dev, "<%s> protocol STALL\n", __func__);
-	imx_ep_stall(imx_ep);
-	ep0_chg_stat(__func__, imx_usb, EP0_STALL);
-	return;
-}
-
-/*******************************************************************************
- * USB gadget callback functions
- *******************************************************************************
- */
-
-static int imx_ep_enable(struct usb_ep *usb_ep,
-				const struct usb_endpoint_descriptor *desc)
-{
-	struct imx_ep_struct *imx_ep = container_of(usb_ep,
-						struct imx_ep_struct, ep);
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-	unsigned long flags;
-
-	if (!usb_ep
-		|| !desc
-		|| !EP_NO(imx_ep)
-		|| desc->bDescriptorType != USB_DT_ENDPOINT
-		|| imx_ep->bEndpointAddress != desc->bEndpointAddress) {
-			D_ERR(imx_usb->dev,
-				"<%s> bad ep or descriptor\n", __func__);
-			return -EINVAL;
-	}
-
-	if (imx_ep->bmAttributes != desc->bmAttributes) {
-		D_ERR(imx_usb->dev,
-			"<%s> %s type mismatch\n", __func__, usb_ep->name);
-		return -EINVAL;
-	}
-
-	if (imx_ep->fifosize < usb_endpoint_maxp(desc)) {
-		D_ERR(imx_usb->dev,
-			"<%s> bad %s maxpacket\n", __func__, usb_ep->name);
-		return -ERANGE;
-	}
-
-	if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) {
-		D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	local_irq_save(flags);
-
-	imx_ep->stopped = 0;
-	imx_flush(imx_ep);
-	imx_ep_irq_enable(imx_ep);
-
-	local_irq_restore(flags);
-
-	D_EPX(imx_usb->dev, "<%s> ENABLED %s\n", __func__, usb_ep->name);
-	return 0;
-}
-
-static int imx_ep_disable(struct usb_ep *usb_ep)
-{
-	struct imx_ep_struct *imx_ep = container_of(usb_ep,
-						struct imx_ep_struct, ep);
-	unsigned long flags;
-
-	if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> %s can not be disabled\n",
-			__func__, usb_ep ? imx_ep->ep.name : NULL);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-
-	imx_ep->stopped = 1;
-	nuke(imx_ep, -ESHUTDOWN);
-	imx_flush(imx_ep);
-	imx_ep_irq_disable(imx_ep);
-
-	local_irq_restore(flags);
-
-	D_EPX(imx_ep->imx_usb->dev,
-		"<%s> DISABLED %s\n", __func__, usb_ep->name);
-	return 0;
-}
-
-static struct usb_request *imx_ep_alloc_request
-					(struct usb_ep *usb_ep, gfp_t gfp_flags)
-{
-	struct imx_request *req;
-
-	if (!usb_ep)
-		return NULL;
-
-	req = kzalloc(sizeof *req, gfp_flags);
-	if (!req)
-		return NULL;
-
-	INIT_LIST_HEAD(&req->queue);
-	req->in_use = 0;
-
-	return &req->req;
-}
-
-static void imx_ep_free_request
-			(struct usb_ep *usb_ep, struct usb_request *usb_req)
-{
-	struct imx_request *req;
-
-	req = container_of(usb_req, struct imx_request, req);
-	WARN_ON(!list_empty(&req->queue));
-	kfree(req);
-}
-
-static int imx_ep_queue
-	(struct usb_ep *usb_ep, struct usb_request *usb_req, gfp_t gfp_flags)
-{
-	struct imx_ep_struct	*imx_ep;
-	struct imx_udc_struct	*imx_usb;
-	struct imx_request	*req;
-	unsigned long		flags;
-	int			ret = 0;
-
-	imx_ep = container_of(usb_ep, struct imx_ep_struct, ep);
-	imx_usb = imx_ep->imx_usb;
-	req = container_of(usb_req, struct imx_request, req);
-
-	/*
-	  Special care on IMX udc.
-	  Ignore enqueue when after set configuration from the
-	  host. This assume all gadget drivers reply set
-	  configuration with the next ep0 req enqueue.
-	*/
-	if (imx_usb->set_config && !EP_NO(imx_ep)) {
-		imx_usb->set_config = 0;
-		D_ERR(imx_usb->dev,
-			"<%s> gadget reply set config\n", __func__);
-		return 0;
-	}
-
-	if (unlikely(!usb_req || !req || !usb_req->complete || !usb_req->buf)) {
-		D_ERR(imx_usb->dev, "<%s> bad params\n", __func__);
-		return -EINVAL;
-	}
-
-	if (unlikely(!usb_ep || !imx_ep)) {
-		D_ERR(imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) {
-		D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	/* 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);
-	dump_req(__func__, imx_ep, usb_req);
-
-	if (imx_ep->stopped) {
-		usb_req->status = -ESHUTDOWN;
-		return -ESHUTDOWN;
-	}
-
-	if (req->in_use) {
-		D_ERR(imx_usb->dev,
-			"<%s> refusing to queue req %p (already queued)\n",
-			__func__, req);
-		return 0;
-	}
-
-	local_irq_save(flags);
-
-	usb_req->status = -EINPROGRESS;
-	usb_req->actual = 0;
-
-	ep_add_request(imx_ep, req);
-
-	if (!EP_NO(imx_ep))
-		ret = handle_ep0(imx_ep);
-	else
-		ret = handle_ep(imx_ep);
-
-	local_irq_restore(flags);
-	return ret;
-}
-
-static int imx_ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
-{
-
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-	struct imx_request *req;
-	unsigned long flags;
-
-	if (unlikely(!usb_ep || !EP_NO(imx_ep))) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-
-	/* make sure it's actually queued on this endpoint */
-	list_for_each_entry(req, &imx_ep->queue, queue) {
-		if (&req->req == usb_req)
-			break;
-	}
-	if (&req->req != usb_req) {
-		local_irq_restore(flags);
-		return -EINVAL;
-	}
-
-	done(imx_ep, req, -ECONNRESET);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int imx_ep_set_halt(struct usb_ep *usb_ep, int value)
-{
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-	unsigned long flags;
-
-	if (unlikely(!usb_ep || !EP_NO(imx_ep))) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-
-	if ((imx_ep->bEndpointAddress & USB_DIR_IN)
-		&& !list_empty(&imx_ep->queue)) {
-			local_irq_restore(flags);
-			return -EAGAIN;
-	}
-
-	imx_ep_stall(imx_ep);
-
-	local_irq_restore(flags);
-
-	D_EPX(imx_ep->imx_usb->dev, "<%s> %s halt\n", __func__, usb_ep->name);
-	return 0;
-}
-
-static int imx_ep_fifo_status(struct usb_ep *usb_ep)
-{
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-
-	if (!usb_ep) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -ENODEV;
-	}
-
-	if (imx_ep->imx_usb->gadget.speed == USB_SPEED_UNKNOWN)
-		return 0;
-	else
-		return imx_fifo_bcount(imx_ep);
-}
-
-static void imx_ep_fifo_flush(struct usb_ep *usb_ep)
-{
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		local_irq_restore(flags);
-		return;
-	}
-
-	/* toggle and halt bits stay unchanged */
-	imx_flush(imx_ep);
-
-	local_irq_restore(flags);
-}
-
-static struct usb_ep_ops imx_ep_ops = {
-	.enable		= imx_ep_enable,
-	.disable	= imx_ep_disable,
-
-	.alloc_request	= imx_ep_alloc_request,
-	.free_request	= imx_ep_free_request,
-
-	.queue		= imx_ep_queue,
-	.dequeue	= imx_ep_dequeue,
-
-	.set_halt	= imx_ep_set_halt,
-	.fifo_status	= imx_ep_fifo_status,
-	.fifo_flush	= imx_ep_fifo_flush,
-};
-
-/*******************************************************************************
- * USB endpoint control functions
- *******************************************************************************
- */
-
-void ep0_chg_stat(const char *label,
-			struct imx_udc_struct *imx_usb, enum ep0_state stat)
-{
-	D_EP0(imx_usb->dev, "<%s> from %15s to %15s\n",
-		label, state_name[imx_usb->ep0state], state_name[stat]);
-
-	if (imx_usb->ep0state == stat)
-		return;
-
-	imx_usb->ep0state = stat;
-}
-
-static void usb_init_data(struct imx_udc_struct *imx_usb)
-{
-	struct imx_ep_struct *imx_ep;
-	u8 i;
-
-	/* device/ep0 records init */
-	INIT_LIST_HEAD(&imx_usb->gadget.ep_list);
-	INIT_LIST_HEAD(&imx_usb->gadget.ep0->ep_list);
-	ep0_chg_stat(__func__, imx_usb, EP0_IDLE);
-
-	/* basic endpoint records init */
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-
-		if (i) {
-			list_add_tail(&imx_ep->ep.ep_list,
-				&imx_usb->gadget.ep_list);
-			imx_ep->stopped = 1;
-		} else
-			imx_ep->stopped = 0;
-
-		INIT_LIST_HEAD(&imx_ep->queue);
-	}
-}
-
-static void udc_stop_activity(struct imx_udc_struct *imx_usb,
-					struct usb_gadget_driver *driver)
-{
-	struct imx_ep_struct *imx_ep;
-	int i;
-
-	if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-
-	/* prevent new request submissions, kill any outstanding requests  */
-	for (i = 1; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-		imx_flush(imx_ep);
-		imx_ep->stopped = 1;
-		imx_ep_irq_disable(imx_ep);
-		nuke(imx_ep, -ESHUTDOWN);
-	}
-
-	imx_usb->cfg = 0;
-	imx_usb->intf = 0;
-	imx_usb->alt = 0;
-
-	if (driver)
-		driver->disconnect(&imx_usb->gadget);
-}
-
-/*******************************************************************************
- * Interrupt handlers
- *******************************************************************************
- */
-
-/*
- * 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 = (void *)data;
-	struct usb_ctrlrequest u;
-	int temp, cfg, intf, alt;
-
-	local_irq_disable();
-
-	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) {
-
-		if (imx_usb->cfg != cfg) {
-			u.bRequest = USB_REQ_SET_CONFIGURATION;
-			u.bRequestType = USB_DIR_OUT |
-					USB_TYPE_STANDARD |
-					USB_RECIP_DEVICE;
-			u.wValue = cfg;
-			u.wIndex = 0;
-			u.wLength = 0;
-			imx_usb->cfg = cfg;
-			imx_usb->driver->setup(&imx_usb->gadget, &u);
-
-		}
-		if (imx_usb->intf != intf || imx_usb->alt != alt) {
-			u.bRequest = USB_REQ_SET_INTERFACE;
-			u.bRequestType = USB_DIR_OUT |
-					  USB_TYPE_STANDARD |
-					  USB_RECIP_INTERFACE;
-			u.wValue = alt;
-			u.wIndex = intf;
-			u.wLength = 0;
-			imx_usb->intf = intf;
-			imx_usb->alt = alt;
-			imx_usb->driver->setup(&imx_usb->gadget, &u);
-		}
-	}
-
-	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);
-		}
-	}
-
-	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;
-}
-
-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);
-
-	if (!imx_usb->driver) {
-		__raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
-		return IRQ_HANDLED;
-	}
-
-	/* 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 don't monitor EOF.
-	 * We call handle_ep0() only if a request is queued for ep0.
-	 */
-	else if (!list_empty(&imx_ep->queue))
-		handle_ep0(imx_ep);
-
-	__raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
-
-	return IRQ_HANDLED;
-}
-
-#ifndef MX1_INT_USBD0
-#define MX1_INT_USBD0 MX1_USBD_INT0
-#endif
-
-static irqreturn_t imx_udc_bulk_irq(int irq, void *dev)
-{
-	struct imx_udc_struct *imx_usb = dev;
-	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - MX1_INT_USBD0];
-	int intr = __raw_readl(imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
-
-	dump_ep_intr(__func__, irq - MX1_INT_USBD0, intr, imx_usb->dev);
-
-	if (!imx_usb->driver) {
-		__raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
-		return IRQ_HANDLED;
-	}
-
-	handle_ep(imx_ep);
-
-	__raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
-
-	return IRQ_HANDLED;
-}
-
-irq_handler_t intr_handler(int i)
-{
-	switch (i) {
-	case 0:
-		return imx_udc_ctrl_irq;
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		return imx_udc_bulk_irq;
-	default:
-		return imx_udc_irq;
-	}
-}
-
-/*******************************************************************************
- * Static defined IMX UDC structure
- *******************************************************************************
- */
-
-static int imx_udc_start(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver);
-static int imx_udc_stop(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver);
-static const struct usb_gadget_ops imx_udc_ops = {
-	.get_frame	= imx_udc_get_frame,
-	.wakeup		= imx_udc_wakeup,
-	.udc_start	= imx_udc_start,
-	.udc_stop	= imx_udc_stop,
-};
-
-static struct imx_udc_struct controller = {
-	.gadget = {
-		.ops		= &imx_udc_ops,
-		.ep0		= &controller.imx_ep[0].ep,
-		.name		= driver_name,
-		.dev = {
-			.init_name	= "gadget",
-		},
-	},
-
-	.imx_ep[0] = {
-		.ep = {
-			.name		= ep0name,
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress	= 0,
-		.bmAttributes		= USB_ENDPOINT_XFER_CONTROL,
-	 },
-	.imx_ep[1] = {
-		.ep = {
-			.name		= "ep1in-bulk",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 64,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 64,
-		.bEndpointAddress	= USB_DIR_IN | 1,
-		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	 },
-	.imx_ep[2] = {
-		.ep = {
-			.name		= "ep2out-bulk",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 64,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 64,
-		.bEndpointAddress	= USB_DIR_OUT | 2,
-		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	 },
-	.imx_ep[3] = {
-		.ep = {
-			.name		= "ep3out-bulk",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress 	= USB_DIR_OUT | 3,
-		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	 },
-	.imx_ep[4] = {
-		.ep = {
-			.name		= "ep4in-int",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		 },
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress 	= USB_DIR_IN | 4,
-		.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	 },
-	.imx_ep[5] = {
-		.ep = {
-			.name		= "ep5out-int",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress 	= USB_DIR_OUT | 5,
-		.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	 },
-};
-
-/*******************************************************************************
- * USB gadget driver functions
- *******************************************************************************
- */
-static int imx_udc_start(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct imx_udc_struct *imx_usb;
-
-	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
-	/* first hook up the driver ... */
-	imx_usb->driver = driver;
-
-	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
-		__func__, driver->driver.name);
-
-	imx_udc_enable(imx_usb);
-
-	return 0;
-}
-
-static int imx_udc_stop(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct imx_udc_struct *imx_usb = container_of(gadget,
-			struct imx_udc_struct, gadget);
-
-	udc_stop_activity(imx_usb, driver);
-	imx_udc_disable(imx_usb);
-	del_timer(&imx_usb->timer);
-
-	imx_usb->driver = NULL;
-
-	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
-		__func__, driver->driver.name);
-
-	return 0;
-}
-
-/*******************************************************************************
- * Module functions
- *******************************************************************************
- */
-
-static int __init imx_udc_probe(struct platform_device *pdev)
-{
-	struct imx_udc_struct *imx_usb = &controller;
-	struct resource *res;
-	struct imxusb_platform_data *pdata;
-	struct clk *clk;
-	void __iomem *base;
-	int ret = 0;
-	int i;
-	resource_size_t res_size;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't get device resources\n");
-		return -ENODEV;
-	}
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "driver needs platform data\n");
-		return -ENODEV;
-	}
-
-	res_size = resource_size(res);
-	if (!request_mem_region(res->start, res_size, res->name)) {
-		dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
-			res_size, res->start);
-		return -ENOMEM;
-	}
-
-	if (pdata->init) {
-		ret = pdata->init(&pdev->dev);
-		if (ret)
-			goto fail0;
-	}
-
-	base = ioremap(res->start, res_size);
-	if (!base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -EIO;
-		goto fail1;
-	}
-
-	clk = clk_get(NULL, "usbd_clk");
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
-		dev_err(&pdev->dev, "can't get USB clock\n");
-		goto fail2;
-	}
-	clk_prepare_enable(clk);
-
-	if (clk_get_rate(clk) != 48000000) {
-		D_INI(&pdev->dev,
-			"Bad USB clock (%d Hz), changing to 48000000 Hz\n",
-			(int)clk_get_rate(clk));
-		if (clk_set_rate(clk, 48000000)) {
-			dev_err(&pdev->dev,
-				"Unable to set correct USB clock (48MHz)\n");
-			ret = -EIO;
-			goto fail3;
-		}
-	}
-
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++) {
-		imx_usb->usbd_int[i] = platform_get_irq(pdev, i);
-		if (imx_usb->usbd_int[i] < 0) {
-			dev_err(&pdev->dev, "can't get irq number\n");
-			ret = -ENODEV;
-			goto fail3;
-		}
-	}
-
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++) {
-		ret = request_irq(imx_usb->usbd_int[i], intr_handler(i),
-				     0, driver_name, imx_usb);
-		if (ret) {
-			dev_err(&pdev->dev, "can't get irq %i, err %d\n",
-				imx_usb->usbd_int[i], ret);
-			for (--i; i >= 0; i--)
-				free_irq(imx_usb->usbd_int[i], imx_usb);
-			goto fail3;
-		}
-	}
-
-	imx_usb->res = res;
-	imx_usb->base = base;
-	imx_usb->clk = clk;
-	imx_usb->dev = &pdev->dev;
-
-	platform_set_drvdata(pdev, imx_usb);
-
-	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;
-
-	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
-	if (ret)
-		goto fail4;
-
-	return 0;
-fail4:
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
-		free_irq(imx_usb->usbd_int[i], imx_usb);
-fail3:
-	clk_put(clk);
-	clk_disable_unprepare(clk);
-fail2:
-	iounmap(base);
-fail1:
-	if (pdata->exit)
-		pdata->exit(&pdev->dev);
-fail0:
-	release_mem_region(res->start, res_size);
-	return ret;
-}
-
-static int __exit imx_udc_remove(struct platform_device *pdev)
-{
-	struct imx_udc_struct *imx_usb = platform_get_drvdata(pdev);
-	struct imxusb_platform_data *pdata = pdev->dev.platform_data;
-	int i;
-
-	usb_del_gadget_udc(&imx_usb->gadget);
-	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);
-
-	clk_put(imx_usb->clk);
-	clk_disable_unprepare(imx_usb->clk);
-	iounmap(imx_usb->base);
-
-	release_mem_region(imx_usb->res->start, resource_size(imx_usb->res));
-
-	if (pdata->exit)
-		pdata->exit(&pdev->dev);
-
-	return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-#define	imx_udc_suspend	NULL
-#define	imx_udc_resume	NULL
-#else
-#define	imx_udc_suspend	NULL
-#define	imx_udc_resume	NULL
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-static struct platform_driver udc_driver = {
-	.driver		= {
-		.name	= driver_name,
-		.owner	= THIS_MODULE,
-	},
-	.remove		= __exit_p(imx_udc_remove),
-	.suspend	= imx_udc_suspend,
-	.resume		= imx_udc_resume,
-};
-
-module_platform_driver_probe(udc_driver, imx_udc_probe);
-
-MODULE_DESCRIPTION("IMX USB Device Controller driver");
-MODULE_AUTHOR("Darius Augulis <augulis.darius@gmail.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx_udc");
diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h
deleted file mode 100644
index d118fb7..0000000
--- a/drivers/usb/gadget/imx_udc.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- *	Copyright (C) 2005 Mike Lee(eemike@gmail.com)
- *
- *	This udc driver is now under testing and code is based on pxa2xx_udc.h
- *	Please use it with your own risk!
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- */
-
-#ifndef __LINUX_USB_GADGET_IMX_H
-#define __LINUX_USB_GADGET_IMX_H
-
-#include <linux/types.h>
-
-/* 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 IMX_USB_NB_EP	6
-
-/* Driver structures */
-struct imx_request {
-	struct usb_request			req;
-	struct list_head			queue;
-	unsigned int				in_use;
-};
-
-enum ep0_state {
-	EP0_IDLE,
-	EP0_IN_DATA_PHASE,
-	EP0_OUT_DATA_PHASE,
-	EP0_CONFIG,
-	EP0_STALL,
-};
-
-struct imx_ep_struct {
-	struct usb_ep				ep;
-	struct imx_udc_struct			*imx_usb;
-	struct list_head			queue;
-	unsigned char				stopped;
-	unsigned char				fifosize;
-	unsigned char				bEndpointAddress;
-	unsigned char				bmAttributes;
-};
-
-struct imx_udc_struct {
-	struct usb_gadget			gadget;
-	struct usb_gadget_driver		*driver;
-	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;
-	unsigned char				set_config;
-	int					cfg,
-						intf,
-						alt,
-						usbd_int[7];
-};
-
-/* USB registers */
-#define  USB_FRAME		(0x00)	/* USB frame */
-#define  USB_SPEC		(0x04)	/* USB Spec */
-#define  USB_STAT		(0x08)	/* USB Status */
-#define  USB_CTRL		(0x0C)	/* USB Control */
-#define  USB_DADR		(0x10)	/* USB Desc RAM addr */
-#define  USB_DDAT		(0x14)	/* USB Desc RAM/EP buffer data */
-#define  USB_INTR		(0x18)	/* USB interrupt */
-#define  USB_MASK		(0x1C)	/* USB Mask */
-#define  USB_ENAB		(0x24)	/* USB Enable */
-#define  USB_EP_STAT(x)		(0x30 + (x*0x30)) /* USB status/control */
-#define  USB_EP_INTR(x)		(0x34 + (x*0x30)) /* USB interrupt */
-#define  USB_EP_MASK(x)		(0x38 + (x*0x30)) /* USB mask */
-#define  USB_EP_FDAT(x)		(0x3C + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT0(x)	(0x3C + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT1(x)	(0x3D + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT2(x)	(0x3E + (x*0x30)) /* USB FIFO data */
-#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 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 */
-/* USB Control Register Bit Fields.*/
-#define CTRL_CMDOVER		(1<<6)	/* UDC status */
-#define CTRL_CMDERROR		(1<<5)	/* UDC status */
-#define CTRL_FE_ENA		(1<<3)	/* Enable Font End logic */
-#define CTRL_UDC_RST		(1<<2)	/* UDC reset */
-#define CTRL_AFE_ENA		(1<<1)	/* Analog Font end enable */
-#define CTRL_RESUME		(1<<0)	/* UDC resume */
-/* USB Status Register Bit Fields.*/
-#define STAT_RST		(1<<8)
-#define STAT_SUSP		(1<<7)
-#define STAT_CFG		(3<<5)
-#define STAT_INTF		(3<<3)
-#define STAT_ALTSET		(7<<0)
-/* USB Interrupt Status/Mask Registers Bit fields */
-#define INTR_WAKEUP		(1<<31)	/* Wake up Interrupt */
-#define INTR_MSOF		(1<<7)	/* Missed Start of Frame */
-#define INTR_SOF		(1<<6)	/* Start of Frame */
-#define INTR_RESET_STOP		(1<<5)	/* Reset Signaling stop */
-#define INTR_RESET_START	(1<<4)	/* Reset Signaling start */
-#define INTR_RESUME		(1<<3)	/* Suspend to resume */
-#define INTR_SUSPEND		(1<<2)	/* Active to suspend */
-#define INTR_FRAME_MATCH	(1<<1)	/* Frame matched */
-#define INTR_CFG_CHG		(1<<0)	/* Configuration change occurred */
-/* USB Enable Register Bit Fields.*/
-#define ENAB_RST		(1<<31)	/* Reset USB modules */
-#define ENAB_ENAB		(1<<30)	/* Enable USB modules*/
-#define ENAB_SUSPEND		(1<<29)	/* Suspend USB modules */
-#define ENAB_ENDIAN		(1<<28)	/* Endian of USB modules */
-#define ENAB_PWRMD		(1<<0)	/* Power mode of USB modules */
-/* USB Descriptor Ram Address Register bit fields */
-#define DADR_CFG		(1<<31)	/* Configuration */
-#define DADR_BSY		(1<<30)	/* Busy status */
-#define DADR_DADR		(0x1FF)	/* Descriptor Ram Address */
-/* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */
-#define DDAT_DDAT		(0xFF)	/* Descriptor Endpoint Buffer */
-/* USB Endpoint Status Register bit fields */
-#define EPSTAT_BCOUNT		(0x7F<<16)	/* Endpoint FIFO byte count */
-#define EPSTAT_SIP		(1<<8)	/* Endpoint setup in progress */
-#define EPSTAT_DIR		(1<<7)	/* Endpoint transfer direction */
-#define EPSTAT_MAX		(3<<5)	/* Endpoint Max packet size */
-#define EPSTAT_TYP		(3<<3)	/* Endpoint type */
-#define EPSTAT_ZLPS		(1<<2)	/* Send zero length packet */
-#define EPSTAT_FLUSH		(1<<1)	/* Endpoint FIFO Flush */
-#define EPSTAT_STALL		(1<<0)	/* Force stall */
-/* USB Endpoint FIFO Status Register bit fields */
-#define FSTAT_FRAME_STAT	(0xF<<24)	/* Frame status bit [0-3] */
-#define FSTAT_ERR		(1<<22)	/* FIFO error */
-#define FSTAT_UF		(1<<21)	/* FIFO underflow */
-#define FSTAT_OF		(1<<20)	/* FIFO overflow */
-#define FSTAT_FR		(1<<19)	/* FIFO frame ready */
-#define FSTAT_FULL		(1<<18)	/* FIFO full */
-#define FSTAT_ALRM		(1<<17)	/* FIFO alarm */
-#define FSTAT_EMPTY		(1<<16)	/* FIFO empty */
-/* USB Endpoint FIFO Control Register bit fields */
-#define FCTRL_WFR		(1<<29)	/* Write frame end */
-/* USB Endpoint Interrupt Status Regsiter bit fields */
-#define EPINTR_FIFO_FULL	(1<<8)	/* fifo full */
-#define EPINTR_FIFO_EMPTY	(1<<7)	/* fifo empty */
-#define EPINTR_FIFO_ERROR	(1<<6)	/* fifo error */
-#define EPINTR_FIFO_HIGH	(1<<5)	/* fifo high */
-#define EPINTR_FIFO_LOW		(1<<4)	/* fifo low */
-#define EPINTR_MDEVREQ		(1<<3)	/* multi Device request */
-#define EPINTR_EOT		(1<<2)	/* fifo end of transfer */
-#define EPINTR_DEVREQ		(1<<1)	/* Device request */
-#define EPINTR_EOF		(1<<0)	/* fifo end of frame */
-
-/* Debug macros */
-#ifdef DEBUG
-
-/* #define DEBUG_REQ */
-/* #define DEBUG_TRX */
-/* #define DEBUG_INIT */
-/* #define DEBUG_EP0 */
-/* #define DEBUG_EPX */
-/* #define DEBUG_IRQ */
-/* #define DEBUG_EPIRQ */
-/* #define DEBUG_DUMP */
-/* #define DEBUG_ERR */
-
-#ifdef DEBUG_REQ
-	#define D_REQ(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_REQ(dev, args...)	do {} while (0)
-#endif /* DEBUG_REQ */
-
-#ifdef DEBUG_TRX
-	#define D_TRX(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_TRX(dev, args...)	do {} while (0)
-#endif /* DEBUG_TRX */
-
-#ifdef DEBUG_INIT
-	#define D_INI(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_INI(dev, args...)	do {} while (0)
-#endif /* DEBUG_INIT */
-
-#ifdef DEBUG_EP0
-	static const char *state_name[] = {
-		"EP0_IDLE",
-		"EP0_IN_DATA_PHASE",
-		"EP0_OUT_DATA_PHASE",
-		"EP0_CONFIG",
-		"EP0_STALL"
-	};
-	#define D_EP0(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_EP0(dev, args...)	do {} while (0)
-#endif /* DEBUG_EP0 */
-
-#ifdef DEBUG_EPX
-	#define D_EPX(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_EPX(dev, args...)	do {} while (0)
-#endif /* DEBUG_EP0 */
-
-#ifdef DEBUG_IRQ
-	static void dump_intr(const char *label, int irqreg, struct device *dev)
-	{
-		dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label,
-			(irqreg & INTR_WAKEUP) ? " wake" : "",
-			(irqreg & INTR_MSOF) ? " msof" : "",
-			(irqreg & INTR_SOF) ? " sof" : "",
-			(irqreg & INTR_RESUME) ? " resume" : "",
-			(irqreg & INTR_SUSPEND) ? " suspend" : "",
-			(irqreg & INTR_RESET_STOP) ? " noreset" : "",
-			(irqreg & INTR_RESET_START) ? " reset" : "",
-			(irqreg & INTR_FRAME_MATCH) ? " fmatch" : "",
-			(irqreg & INTR_CFG_CHG) ? " config" : "");
-	}
-#else
-	#define dump_intr(x, y, z)		do {} while (0)
-#endif /* DEBUG_IRQ */
-
-#ifdef DEBUG_EPIRQ
-	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" : "",
-			(irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "",
-			(irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "",
-			(irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "",
-			(irqreg & EPINTR_FIFO_LOW) ? " flow" : "",
-			(irqreg & EPINTR_MDEVREQ) ? " mreq" : "",
-			(irqreg & EPINTR_EOF) ? " eof" : "",
-			(irqreg & EPINTR_DEVREQ) ? " devreq" : "",
-			(irqreg & EPINTR_EOT) ? " eot" : "");
-	}
-#else
-	#define dump_ep_intr(x, y, z, i)	do {} while (0)
-#endif /* DEBUG_IRQ */
-
-#ifdef DEBUG_DUMP
-	static void dump_usb_stat(const char *label,
-						struct imx_udc_struct *imx_usb)
-	{
-		int temp = __raw_readl(imx_usb->base + USB_STAT);
-
-		dev_dbg(imx_usb->dev,
-			"<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label,
-			(temp & STAT_RST) ? " reset" : "",
-			(temp & STAT_SUSP) ? " suspend" : "",
-			(temp & STAT_CFG) >> 5,
-			(temp & STAT_INTF) >> 3,
-			(temp & STAT_ALTSET));
-	}
-
-	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)));
-
-		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),
-			(temp & EPINTR_FIFO_FULL) ? " full" : "",
-			(temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
-			(temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
-			(temp & EPINTR_FIFO_HIGH) ? " fhigh" : "",
-			(temp & EPINTR_FIFO_LOW) ? " flow" : "",
-			(temp & EPINTR_MDEVREQ) ? " mreq" : "",
-			(temp & EPINTR_EOF) ? " eof" : "",
-			(temp & EPINTR_DEVREQ) ? " devreq" : "",
-			(temp & EPINTR_EOT) ? " eot" : "");
-
-		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),
-			(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)));
-
-		dev_dbg(imx_ep->imx_usb->dev,
-			"<%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" : "",
-			(temp & FSTAT_FR) ? " fready" : "",
-			(temp & FSTAT_FULL) ? " ffull" : "",
-			(temp & FSTAT_ALRM) ? " falarm" : "",
-			(temp & FSTAT_EMPTY) ? " fempty" : "");
-	}
-
-	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);
-			return;
-		}
-
-		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);
-			for (i = 0; i < req->length; i++)
-				printk("%02x-", *((u8 *)req->buf + i));
-			printk(">\n");
-		}
-	}
-
-#else
-	#define dump_ep_stat(x, y)		do {} while (0)
-	#define dump_usb_stat(x, y)		do {} while (0)
-	#define dump_req(x, y, z)		do {} while (0)
-#endif /* DEBUG_DUMP */
-
-#ifdef DEBUG_ERR
-	#define D_ERR(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_ERR(dev, args...)	do {} while (0)
-#endif
-
-#else
-	#define D_REQ(dev, args...)		do {} while (0)
-	#define D_TRX(dev, args...)		do {} while (0)
-	#define D_INI(dev, args...)		do {} while (0)
-	#define D_EP0(dev, args...)		do {} while (0)
-	#define D_EPX(dev, args...)		do {} while (0)
-	#define dump_ep_intr(x, y, z, i)	do {} while (0)
-	#define dump_intr(x, y, z)		do {} while (0)
-	#define dump_ep_stat(x, y)		do {} while (0)
-	#define dump_usb_stat(x, y)		do {} while (0)
-	#define dump_req(x, y, z)		do {} while (0)
-	#define D_ERR(dev, args...)		do {} while (0)
-#endif /* DEBUG */
-
-#endif /* __LINUX_USB_GADGET_IMX_H */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 570c005..f255ad7 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -524,7 +524,7 @@ struct kiocb_priv {
 	unsigned		actual;
 };
 
-static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
+static int ep_aio_cancel(struct kiocb *iocb)
 {
 	struct kiocb_priv	*priv = iocb->private;
 	struct ep_data		*epdata;
@@ -540,7 +540,6 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 	// spin_unlock(&epdata->dev->lock);
 	local_irq_enable();
 
-	aio_put_req(iocb);
 	return value;
 }
 
@@ -709,11 +708,11 @@ ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
 	if (unlikely(usb_endpoint_dir_in(&epdata->desc)))
 		return -EINVAL;
 
-	buf = kmalloc(iocb->ki_left, GFP_KERNEL);
+	buf = kmalloc(iocb->ki_nbytes, GFP_KERNEL);
 	if (unlikely(!buf))
 		return -ENOMEM;
 
-	return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
+	return ep_aio_rwtail(iocb, buf, iocb->ki_nbytes, epdata, iov, nr_segs);
 }
 
 static ssize_t
@@ -728,7 +727,7 @@ ep_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	if (unlikely(!usb_endpoint_dir_in(&epdata->desc)))
 		return -EINVAL;
 
-	buf = kmalloc(iocb->ki_left, GFP_KERNEL);
+	buf = kmalloc(iocb->ki_nbytes, GFP_KERNEL);
 	if (unlikely(!buf))
 		return -ENOMEM;
 
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 46ba983..d5f050d 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1584,7 +1584,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
-	if (pdev->dev.platform_data == NULL) {
+	if (dev_get_platdata(&pdev->dev) == NULL) {
 		dev_err(&pdev->dev, "no platform data\n");
 		ret = -ENODEV;
 		goto clean_up;
@@ -1598,7 +1598,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
-	m66592->pdata = pdev->dev.platform_data;
+	m66592->pdata = dev_get_platdata(&pdev->dev);
 	m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
 
 	spin_lock_init(&m66592->lock);
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index ec6a2d2..bbb6e98 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -1109,7 +1109,7 @@ static int mv_u3d_controller_reset(struct mv_u3d *u3d)
 
 static int mv_u3d_enable(struct mv_u3d *u3d)
 {
-	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	int retval;
 
 	if (u3d->active)
@@ -1138,7 +1138,7 @@ static int mv_u3d_enable(struct mv_u3d *u3d)
 
 static void mv_u3d_disable(struct mv_u3d *u3d)
 {
-	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	if (u3d->clock_gating && u3d->active) {
 		dev_dbg(u3d->dev, "disable u3d\n");
 		if (pdata->phy_deinit)
@@ -1246,7 +1246,7 @@ static int mv_u3d_start(struct usb_gadget *g,
 		struct usb_gadget_driver *driver)
 {
 	struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
-	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	unsigned long flags;
 
 	if (u3d->driver)
@@ -1277,7 +1277,7 @@ static int mv_u3d_stop(struct usb_gadget *g,
 		struct usb_gadget_driver *driver)
 {
 	struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
-	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	unsigned long flags;
 
 	u3d->vbus_valid_detect = 0;
@@ -1794,12 +1794,12 @@ static int mv_u3d_remove(struct platform_device *dev)
 static int mv_u3d_probe(struct platform_device *dev)
 {
 	struct mv_u3d *u3d = NULL;
-	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(&dev->dev);
 	int retval = 0;
 	struct resource *r;
 	size_t size;
 
-	if (!dev->dev.platform_data) {
+	if (!dev_get_platdata(&dev->dev)) {
 		dev_err(&dev->dev, "missing platform_data\n");
 		retval = -ENODEV;
 		goto err_pdata;
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index c2a5702..104cdbe 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -2100,7 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
 
 static int mv_udc_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mv_udc *udc;
 	int retval = 0;
 	struct resource *r;
@@ -2118,7 +2118,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 	}
 
 	udc->done = &release_done;
-	udc->pdata = pdev->dev.platform_data;
+	udc->pdata = dev_get_platdata(&pdev->dev);
 	spin_lock_init(&udc->lock);
 
 	udc->dev = pdev;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index b8ed74a..83957cc 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2734,7 +2734,7 @@ static int omap_udc_probe(struct platform_device *pdev)
 	int			hmc;
 	struct usb_phy		*xceiv = NULL;
 	const char		*type = NULL;
-	struct omap_usb_config	*config = pdev->dev.platform_data;
+	struct omap_usb_config	*config = dev_get_platdata(&pdev->dev);
 	struct clk		*dc_clk = NULL;
 	struct clk		*hhc_clk = NULL;
 
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 95c531d..cc92074 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -2117,7 +2117,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 
 	/* other non-static parts of init */
 	dev->dev = &pdev->dev;
-	dev->mach = pdev->dev.platform_data;
+	dev->mach = dev_get_platdata(&pdev->dev);
 
 	dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 41cea95..3c97da7 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -2422,7 +2422,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
 		return udc->irq;
 
 	udc->dev = &pdev->dev;
-	udc->mach = pdev->dev.platform_data;
+	udc->mach = dev_get_platdata(&pdev->dev);
 	udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 	gpio = udc->mach->gpio_pullup;
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index c6af649..68be48d 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1910,7 +1910,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 
 	spin_lock_init(&r8a66597->lock);
 	platform_set_drvdata(pdev, r8a66597);
-	r8a66597->pdata = pdev->dev.platform_data;
+	r8a66597->pdata = dev_get_platdata(&pdev->dev);
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index af22f24..d69b36a 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of_platform.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -3450,7 +3451,7 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 
 static int s3c_hsotg_probe(struct platform_device *pdev)
 {
-	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
+	struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
 	struct usb_phy *phy;
 	struct device *dev = &pdev->dev;
 	struct s3c_hsotg_ep *eps;
@@ -3469,7 +3470,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	if (IS_ERR(phy)) {
 		/* Fallback for pdata */
-		plat = pdev->dev.platform_data;
+		plat = dev_get_platdata(&pdev->dev);
 		if (!plat) {
 			dev_err(&pdev->dev, "no platform data or transceiver defined\n");
 			return -EPROBE_DEFER;
@@ -3648,10 +3649,19 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 #define s3c_hsotg_resume NULL
 #endif
 
+#ifdef CONFIG_OF
+static const struct of_device_id s3c_hsotg_of_ids[] = {
+	{ .compatible = "samsung,s3c6400-hsotg", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
+#endif
+
 static struct platform_driver s3c_hsotg_driver = {
 	.driver		= {
 		.name	= "s3c-hsotg",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(s3c_hsotg_of_ids),
 	},
 	.probe		= s3c_hsotg_probe,
 	.remove		= s3c_hsotg_remove,
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index b1f0771..1a1a414 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -1262,7 +1262,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct resource *res;
 	struct s3c_hsudc *hsudc;
-	struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data;
+	struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev);
 	int ret, i;
 
 	hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) +
@@ -1275,7 +1275,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 	hsudc->dev = dev;
-	hsudc->pd = pdev->dev.platform_data;
+	hsudc->pd = dev_get_platdata(&pdev->dev);
 
 	hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 09c4f70..c72d810 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1809,7 +1809,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 	}
 
 	spin_lock_init(&udc->lock);
-	udc_info = pdev->dev.platform_data;
+	udc_info = dev_get_platdata(&pdev->dev);
 
 	rsrc_start = S3C2410_PA_USBDEV;
 	rsrc_len   = S3C24XX_SZ_USBDEV;
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index dbce3a9..8c71212 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -172,7 +172,7 @@ MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers");
  */
 #define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
 
-#endif /* CONFIG_USB_DEBUG */
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 /* check if fsg_num_buffers is within a valid range */
 static inline int fsg_num_buffers_validate(void)
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 13e25f8..546bfda 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -105,11 +106,18 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
 /* ------------------------------------------------------------------------- */
 
+static void usb_gadget_state_work(struct work_struct *work)
+{
+	struct usb_gadget	*gadget = work_to_gadget(work);
+
+	sysfs_notify(&gadget->dev.kobj, NULL, "state");
+}
+
 void usb_gadget_set_state(struct usb_gadget *gadget,
 		enum usb_device_state state)
 {
 	gadget->state = state;
-	sysfs_notify(&gadget->dev.kobj, NULL, "state");
+	schedule_work(&gadget->work);
 }
 EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 
@@ -196,6 +204,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
 		goto err1;
 
 	dev_set_name(&gadget->dev, "gadget");
+	INIT_WORK(&gadget->work, usb_gadget_state_work);
 	gadget->dev.parent = parent;
 
 #ifdef	CONFIG_HAS_DMA
@@ -315,6 +324,7 @@ found:
 		usb_gadget_remove_driver(udc);
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+	flush_work(&gadget->work);
 	device_unregister(&udc->dev);
 	device_unregister(&gadget->dev);
 }
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 4263d01..8e8e694 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -148,13 +148,11 @@ config USB_EHCI_MXC
 config USB_EHCI_HCD_OMAP
 	tristate "EHCI support for OMAP3 and later chips"
 	depends on ARCH_OMAP
+	select NOP_USB_XCEIV
 	default y
 	---help---
 	  Enables support for the on-chip EHCI controller on
 	  OMAP3 and later chips.
-	  If your system uses a PHY on the USB port, you will need to
-	  enable USB_PHY and the appropriate PHY driver as well. Most
-	  boards need the NOP_USB_XCEIV PHY driver.
 
 config USB_EHCI_HCD_ORION
 	tristate  "Support for Marvell EBU on-chip EHCI USB controller"
@@ -186,7 +184,6 @@ config USB_EHCI_HCD_AT91
 config USB_EHCI_MSM
 	tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
 	depends on ARCH_MSM
-	depends on USB_PHY
 	select USB_EHCI_ROOT_HUB_TT
 	select USB_MSM_OTG
 	---help---
@@ -354,6 +351,18 @@ config USB_FUSBH200_HCD
 	To compile this driver as a module, choose M here: the
 	module will be called fusbh200-hcd.
 
+config USB_FOTG210_HCD
+	tristate "FOTG210 HCD support"
+	depends on USB
+	default N
+	---help---
+	  Faraday FOTG210 is an OTG controller which can be configured as
+	  an USB2.0 host. It is designed to meet USB2.0 EHCI specification
+	  with minor modification.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called fotg210-hcd.
+
 config USB_OHCI_HCD
 	tristate "OHCI HCD (USB 1.1) support"
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index bea7112..829a339 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
 obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_FUSBH200_HCD)	+= fusbh200-hcd.o
+obj-$(CONFIG_USB_FOTG210_HCD)	+= fotg210-hcd.o
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index bd831ec..45eee6e 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 	pr_debug("initializing FSL-SOC USB Controller\n");
 
 	/* Need platform data for setup */
-	pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data;
+	pdata = (struct fsl_usb2_platform_data *)dev_get_platdata(&pdev->dev);
 	if (!pdata) {
 		dev_err(&pdev->dev,
 			"No platform data for %s.\n", dev_name(&pdev->dev));
@@ -190,7 +190,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 			       struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	if (!IS_ERR_OR_NULL(hcd->phy)) {
 		otg_set_host(hcd->phy->otg, NULL);
@@ -218,7 +218,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	void __iomem *non_ehci = hcd->regs;
 	struct device *dev = hcd->self.controller;
-	struct fsl_usb2_platform_data *pdata = dev->platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev);
 
 	if (pdata->controller_ver < 0) {
 		dev_warn(hcd->self.controller, "Could not get controller version\n");
@@ -291,7 +291,7 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
 
-	pdata = hcd->self.controller->platform_data;
+	pdata = dev_get_platdata(hcd->self.controller);
 
 	if (pdata->have_sysif_regs) {
 		/*
@@ -363,7 +363,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 	struct device *dev;
 
 	dev = hcd->self.controller;
-	pdata = hcd->self.controller->platform_data;
+	pdata = dev_get_platdata(hcd->self.controller);
 	ehci->big_endian_desc = pdata->big_endian_desc;
 	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
@@ -415,7 +415,7 @@ static int ehci_fsl_mpc512x_drv_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	struct fsl_usb2_platform_data *pdata = dev->platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev);
 	u32 tmp;
 
 #ifdef DEBUG
@@ -484,7 +484,7 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	struct fsl_usb2_platform_data *pdata = dev->platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev);
 	u32 tmp;
 
 	dev_dbg(dev, "suspend=%d already_suspended=%d\n",
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index a77bd8d..83ab51a 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -167,15 +167,6 @@ static int ehci_hcd_grlib_remove(struct platform_device *op)
 }
 
 
-static void ehci_hcd_grlib_shutdown(struct platform_device *op)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(op);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
-
 static const struct of_device_id ehci_hcd_grlib_of_match[] = {
 	{
 		.name = "GAISLER_EHCI",
@@ -191,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
 static struct platform_driver ehci_grlib_driver = {
 	.probe		= ehci_hcd_grlib_probe,
 	.remove		= ehci_hcd_grlib_remove,
-	.shutdown	= ehci_hcd_grlib_shutdown,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name = "grlib-ehci",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 6dce375..6e69ee1 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -801,6 +801,8 @@ static int ehci_hub_control (
 			ehci_writel(ehci, temp | PORT_RESUME, status_reg);
 			ehci->reset_done[wIndex] = jiffies
 					+ msecs_to_jiffies(20);
+			set_bit(wIndex, &ehci->resuming_ports);
+			usb_hcd_start_port_resume(&hcd->self, wIndex);
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
 			clear_bit(wIndex, &ehci->port_c_suspend);
@@ -865,11 +867,11 @@ static int ehci_hub_control (
 			}
 		}
 
-		/* whoever resumes must GetPortStatus to complete it!! */
-		if (temp & PORT_RESUME) {
+		/* no reset or resume pending */
+		if (!ehci->reset_done[wIndex]) {
 
 			/* Remote Wakeup received? */
-			if (!ehci->reset_done[wIndex]) {
+			if (temp & PORT_RESUME) {
 				/* resume signaling for 20 msec */
 				ehci->reset_done[wIndex] = jiffies
 						+ msecs_to_jiffies(20);
@@ -880,38 +882,34 @@ static int ehci_hub_control (
 						ehci->reset_done[wIndex]);
 			}
 
-			/* resume completed? */
-			else if (time_after_eq(jiffies,
-					ehci->reset_done[wIndex])) {
-				clear_bit(wIndex, &ehci->suspended_ports);
-				set_bit(wIndex, &ehci->port_c_suspend);
-				ehci->reset_done[wIndex] = 0;
-				usb_hcd_end_port_resume(&hcd->self, wIndex);
-
-				/* stop resume signaling */
-				temp &= ~(PORT_RWC_BITS |
-						PORT_SUSPEND | PORT_RESUME);
-				ehci_writel(ehci, temp, status_reg);
-				clear_bit(wIndex, &ehci->resuming_ports);
-				retval = ehci_handshake(ehci, status_reg,
-					   PORT_RESUME, 0, 2000 /* 2msec */);
-				if (retval != 0) {
-					ehci_err(ehci,
-						"port %d resume error %d\n",
+		/* reset or resume not yet complete */
+		} else if (!time_after_eq(jiffies, ehci->reset_done[wIndex])) {
+			;	/* wait until it is complete */
+
+		/* resume completed */
+		} else if (test_bit(wIndex, &ehci->resuming_ports)) {
+			clear_bit(wIndex, &ehci->suspended_ports);
+			set_bit(wIndex, &ehci->port_c_suspend);
+			ehci->reset_done[wIndex] = 0;
+			usb_hcd_end_port_resume(&hcd->self, wIndex);
+
+			/* stop resume signaling */
+			temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);
+			ehci_writel(ehci, temp, status_reg);
+			clear_bit(wIndex, &ehci->resuming_ports);
+			retval = ehci_handshake(ehci, status_reg,
+					PORT_RESUME, 0, 2000 /* 2msec */);
+			if (retval != 0) {
+				ehci_err(ehci, "port %d resume error %d\n",
 						wIndex + 1, retval);
-					goto error;
-				}
-				temp = ehci_readl(ehci, status_reg);
+				goto error;
 			}
-		}
+			temp = ehci_readl(ehci, status_reg);
 
 		/* whoever resets must GetPortStatus to complete it!! */
-		if ((temp & PORT_RESET)
-				&& time_after_eq(jiffies,
-					ehci->reset_done[wIndex])) {
+		} else {
 			status |= USB_PORT_STAT_C_RESET << 16;
 			ehci->reset_done [wIndex] = 0;
-			clear_bit(wIndex, &ehci->resuming_ports);
 
 			/* force reset to complete */
 			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
@@ -932,11 +930,6 @@ static int ehci_hub_control (
 					ehci_readl(ehci, status_reg));
 		}
 
-		if (!(temp & (PORT_RESUME|PORT_RESET))) {
-			ehci->reset_done[wIndex] = 0;
-			clear_bit(wIndex, &ehci->resuming_ports);
-		}
-
 		/* transfer dedicated ports to the companion hc */
 		if ((temp & PORT_CONNECT) &&
 				test_bit(wIndex, &ehci->companion_ports)) {
@@ -1057,7 +1050,7 @@ static int ehci_hub_control (
 						status_reg);
 			break;
 		case USB_PORT_FEAT_RESET:
-			if (temp & PORT_RESUME)
+			if (temp & (PORT_SUSPEND|PORT_RESUME))
 				goto error;
 			/* line status bits may report this as low speed,
 			 * which can be fine if this root hub has a
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 915c2db..35cdbd8 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -131,7 +131,7 @@ static const struct hc_driver mv_ehci_hc_driver = {
 
 static int mv_ehci_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
 	struct ehci_hcd_mv *ehci_mv;
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index e4c34ac..5899ad6 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -49,7 +49,7 @@ static const struct ehci_driver_overrides ehci_mxc_overrides __initconst = {
 
 static int ehci_mxc_drv_probe(struct platform_device *pdev)
 {
-	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+	struct mxc_usbh_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct usb_hcd *hcd;
 	struct resource *res;
 	int irq, ret;
@@ -174,7 +174,7 @@ err_alloc:
 
 static int ehci_mxc_drv_remove(struct platform_device *pdev)
 {
-	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+	struct mxc_usbh_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
@@ -197,20 +197,12 @@ static int ehci_mxc_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
 MODULE_ALIAS("platform:mxc-ehci");
 
 static struct platform_driver ehci_mxc_driver = {
 	.probe = ehci_mxc_drv_probe,
 	.remove = ehci_mxc_drv_remove,
-	.shutdown = ehci_mxc_drv_shutdown,
+	.shutdown = usb_hcd_platform_shutdown,
 	.driver = {
 		   .name = "mxc-ehci",
 	},
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 9bd7dfe..78b01fa 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -100,7 +100,7 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
 static int ehci_hcd_omap_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct usbhs_omap_platform_data *pdata = dev->platform_data;
+	struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
 	struct resource	*res;
 	struct usb_hcd	*hcd;
 	void __iomem *regs;
@@ -119,7 +119,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 
 	/* For DT boot, get platform data from parent. i.e. usbhshost */
 	if (dev->of_node) {
-		pdata = dev->parent->platform_data;
+		pdata = dev_get_platdata(dev->parent);
 		dev->platform_data = pdata;
 	}
 
@@ -278,14 +278,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
 static const struct of_device_id omap_ehci_dt_ids[] = {
 	{ .compatible = "ti,ehci-omap" },
 	{ }
@@ -296,7 +288,7 @@ MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
 static struct platform_driver ehci_hcd_omap_driver = {
 	.probe			= ehci_hcd_omap_probe,
 	.remove			= ehci_hcd_omap_remove,
-	.shutdown		= ehci_hcd_omap_shutdown,
+	.shutdown		= usb_hcd_platform_shutdown,
 	/*.suspend		= ehci_hcd_omap_suspend, */
 	/*.resume		= ehci_hcd_omap_resume, */
 	.driver = {
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 1a450aa..d1dfb9d 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -139,7 +139,7 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
 
 static int ehci_orion_drv_probe(struct platform_device *pdev)
 {
-	struct orion_ehci_data *pd = pdev->dev.platform_data;
+	struct orion_ehci_data *pd = dev_get_platdata(&pdev->dev);
 	const struct mbus_dram_target_info *dram;
 	struct resource *res;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 595d210..6bd299e 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -315,53 +315,11 @@ done:
  * Also they depend on separate root hub suspend/resume.
  */
 
-static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
-{
-	return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
-		pdev->vendor == PCI_VENDOR_ID_INTEL &&
-		(pdev->device == 0x1E26 ||
-		 pdev->device == 0x8C2D ||
-		 pdev->device == 0x8C26 ||
-		 pdev->device == 0x9C26);
-}
-
-static void ehci_enable_xhci_companion(void)
-{
-	struct pci_dev		*companion = NULL;
-
-	/* The xHCI and EHCI controllers are not on the same PCI slot */
-	for_each_pci_dev(companion) {
-		if (!usb_is_intel_switchable_xhci(companion))
-			continue;
-		usb_enable_xhci_ports(companion);
-		return;
-	}
-}
-
 static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 
-	/* The BIOS on systems with the Intel Panther Point chipset may or may
-	 * not support xHCI natively.  That means that during system resume, it
-	 * may switch the ports back to EHCI so that users can use their
-	 * keyboard to select a kernel from GRUB after resume from hibernate.
-	 *
-	 * The BIOS is supposed to remember whether the OS had xHCI ports
-	 * enabled before resume, and switch the ports back to xHCI when the
-	 * BIOS/OS semaphore is written, but we all know we can't trust BIOS
-	 * writers.
-	 *
-	 * Unconditionally switch the ports back to xHCI after a system resume.
-	 * We can't tell whether the EHCI or xHCI controller will be resumed
-	 * first, so we have to do the port switchover in both drivers.  Writing
-	 * a '1' to the port switchover registers should have no effect if the
-	 * port was already switched over.
-	 */
-	if (usb_is_intel_switchable_ehci(pdev))
-		ehci_enable_xhci_companion();
-
 	if (ehci_resume(hcd, hibernated) != 0)
 		(void) ehci_pci_reinit(ehci, pdev);
 	return 0;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 5196d72..f6b790c 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -39,7 +39,7 @@ static const char hcd_name[] = "ehci-platform";
 static int ehci_platform_reset(struct usb_hcd *hcd)
 {
 	struct platform_device *pdev = to_platform_device(hcd->self.controller);
-	struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
+	struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 
@@ -87,14 +87,14 @@ static int ehci_platform_probe(struct platform_device *dev)
 	 * use reasonable defaults so platforms don't have to provide these.
 	 * with DT probing on ARM, none of these are set.
 	 */
-	if (!dev->dev.platform_data)
+	if (!dev_get_platdata(&dev->dev))
 		dev->dev.platform_data = &ehci_platform_defaults;
 	if (!dev->dev.dma_mask)
 		dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
 	if (!dev->dev.coherent_dma_mask)
 		dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
-	pdata = dev->dev.platform_data;
+	pdata = dev_get_platdata(&dev->dev);
 
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
@@ -148,7 +148,7 @@ err_power:
 static int ehci_platform_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
-	struct usb_ehci_pdata *pdata = dev->dev.platform_data;
+	struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
 
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
@@ -167,7 +167,7 @@ static int ehci_platform_remove(struct platform_device *dev)
 static int ehci_platform_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct usb_ehci_pdata *pdata = dev->platform_data;
+	struct usb_ehci_pdata *pdata = dev_get_platdata(dev);
 	struct platform_device *pdev =
 		container_of(dev, struct platform_device, dev);
 	bool do_wakeup = device_may_wakeup(dev);
@@ -184,7 +184,7 @@ static int ehci_platform_suspend(struct device *dev)
 static int ehci_platform_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct usb_ehci_pdata *pdata = dev->platform_data;
+	struct usb_ehci_pdata *pdata = dev_get_platdata(dev);
 	struct platform_device *pdev =
 		container_of(dev, struct platform_device, dev);
 
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 86da09c..932293f 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -215,15 +215,6 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op)
 }
 
 
-static void ehci_hcd_ppc_of_shutdown(struct platform_device *op)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(op);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
-
 static const struct of_device_id ehci_hcd_ppc_of_match[] = {
 	{
 		.compatible = "usb-ehci",
@@ -236,7 +227,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
 static struct platform_driver ehci_hcd_ppc_of_driver = {
 	.probe		= ehci_hcd_ppc_of_probe,
 	.remove		= ehci_hcd_ppc_of_remove,
-	.shutdown	= ehci_hcd_ppc_of_shutdown,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name = "ppc-of-ehci",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 7cc26e6..7c3de95 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -75,7 +75,7 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)
 
 static int s5p_ehci_probe(struct platform_device *pdev)
 {
-	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+	struct s5p_ehci_platdata *pdata = dev_get_platdata(&pdev->dev);
 	struct s5p_ehci_hcd *s5p_ehci;
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
@@ -220,14 +220,6 @@ static int s5p_ehci_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static void s5p_ehci_shutdown(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
 #ifdef CONFIG_PM
 static int s5p_ehci_suspend(struct device *dev)
 {
@@ -297,7 +289,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
 static struct platform_driver s5p_ehci_driver = {
 	.probe		= s5p_ehci_probe,
 	.remove		= s5p_ehci_remove,
-	.shutdown	= s5p_ehci_shutdown,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name	= "s5p-ehci",
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index c4c0ee9..93e59a1 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -104,7 +104,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
 		goto fail_create_hcd;
 	}
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 
 	/* initialize hcd */
 	hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 6ee7ef7..db8031f 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -27,7 +27,6 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
-#include <linux/platform_data/tegra_usb.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/usb/ehci_def.h>
@@ -58,7 +57,6 @@ static int (*orig_hub_control)(struct usb_hcd *hcd,
 struct tegra_ehci_hcd {
 	struct tegra_usb_phy *phy;
 	struct clk *clk;
-	struct usb_phy *transceiver;
 	int port_resuming;
 	bool needs_double_reset;
 	enum tegra_usb_phy_port_speed port_speed;
@@ -322,51 +320,16 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 	free_dma_aligned_buffer(urb);
 }
 
-static int setup_vbus_gpio(struct platform_device *pdev,
-			   struct tegra_ehci_platform_data *pdata)
-{
-	int err = 0;
-	int gpio;
-
-	gpio = pdata->vbus_gpio;
-	if (!gpio_is_valid(gpio))
-		gpio = of_get_named_gpio(pdev->dev.of_node,
-					 "nvidia,vbus-gpio", 0);
-	if (!gpio_is_valid(gpio))
-		return 0;
-
-	err = gpio_request(gpio, "vbus_gpio");
-	if (err) {
-		dev_err(&pdev->dev, "can't request vbus gpio %d", gpio);
-		return err;
-	}
-	err = gpio_direction_output(gpio, 1);
-	if (err) {
-		dev_err(&pdev->dev, "can't enable vbus\n");
-		return err;
-	}
-
-	return err;
-}
-
 static int tegra_ehci_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
 	struct tegra_ehci_hcd *tegra;
-	struct tegra_ehci_platform_data *pdata;
 	int err = 0;
 	int irq;
-	struct device_node *np_phy;
 	struct usb_phy *u_phy;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "Platform data missing\n");
-		return -EINVAL;
-	}
-
 	/* Right now device-tree probed devices don't get dma_mask set.
 	 * Since shared usb code relies on it, set it here for now.
 	 * Once we have dma capability bindings this can go away.
@@ -376,14 +339,11 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	if (!pdev->dev.coherent_dma_mask)
 		pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
-	setup_vbus_gpio(pdev, pdata);
-
 	hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
 					dev_name(&pdev->dev));
 	if (!hcd) {
 		dev_err(&pdev->dev, "Unable to create HCD\n");
-		err = -ENOMEM;
-		goto cleanup_vbus_gpio;
+		return -ENOMEM;
 	}
 	platform_set_drvdata(pdev, hcd);
 	ehci = hcd_to_ehci(hcd);
@@ -406,13 +366,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	udelay(1);
 	tegra_periph_reset_deassert(tegra->clk);
 
-	np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
-	if (!np_phy) {
-		err = -ENODEV;
-		goto cleanup_clk_en;
-	}
-
-	u_phy = tegra_usb_get_phy(np_phy);
+	u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
 	if (IS_ERR(u_phy)) {
 		err = PTR_ERR(u_phy);
 		goto cleanup_clk_en;
@@ -466,26 +420,18 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 		goto cleanup_phy;
 	}
 
-	if (pdata->operating_mode == TEGRA_USB_OTG) {
-		tegra->transceiver =
-			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-		if (!IS_ERR(tegra->transceiver))
-			otg_set_host(tegra->transceiver->otg, &hcd->self);
-	} else {
-		tegra->transceiver = ERR_PTR(-ENODEV);
-	}
+	otg_set_host(u_phy->otg, &hcd->self);
 
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
-		goto cleanup_transceiver;
+		goto cleanup_otg_set_host;
 	}
 
 	return err;
 
-cleanup_transceiver:
-	if (!IS_ERR(tegra->transceiver))
-		otg_set_host(tegra->transceiver->otg, NULL);
+cleanup_otg_set_host:
+	otg_set_host(u_phy->otg, NULL);
 cleanup_phy:
 	usb_phy_shutdown(hcd->phy);
 cleanup_clk_en:
@@ -494,8 +440,6 @@ cleanup_clk_get:
 	clk_put(tegra->clk);
 cleanup_hcd_create:
 	usb_put_hcd(hcd);
-cleanup_vbus_gpio:
-	/* FIXME: Undo setup_vbus_gpio() here */
 	return err;
 }
 
@@ -505,8 +449,7 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 	struct tegra_ehci_hcd *tegra =
 		(struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
 
-	if (!IS_ERR(tegra->transceiver))
-		otg_set_host(tegra->transceiver->otg, NULL);
+	otg_set_host(hcd->phy->otg, NULL);
 
 	usb_phy_shutdown(hcd->phy);
 	usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c
index d72b292..cca4be9 100644
--- a/drivers/usb/host/ehci-tilegx.c
+++ b/drivers/usb/host/ehci-tilegx.c
@@ -101,7 +101,7 @@ static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
-	struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	pte_t pte = { 0 };
 	int my_cpu = smp_processor_id();
 	int ret;
@@ -186,7 +186,7 @@ err_hcd:
 static int ehci_hcd_tilegx_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 35c7f90..eba962e 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -220,21 +220,6 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op)
 	return 0;
 }
 
-/**
- * ehci_hcd_xilinx_of_shutdown - shutdown the hcd
- * @op:		pointer to platform_device structure that is to be removed
- *
- * Properly shutdown the hcd, call driver's shutdown routine.
- */
-static void ehci_hcd_xilinx_of_shutdown(struct platform_device *op)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(op);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
-
 static const struct of_device_id ehci_hcd_xilinx_of_match[] = {
 		{.compatible = "xlnx,xps-usb-host-1.00.a",},
 	{},
@@ -244,7 +229,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
 static struct platform_driver ehci_hcd_xilinx_of_driver = {
 	.probe		= ehci_hcd_xilinx_of_probe,
 	.remove		= ehci_hcd_xilinx_of_remove,
-	.shutdown	= ehci_hcd_xilinx_of_shutdown,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name = "xilinx-of-ehci",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
new file mode 100644
index 0000000..fce13bc
--- /dev/null
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -0,0 +1,6049 @@
+/*
+ * Faraday FOTG210 EHCI-like driver
+ *
+ * Copyright (c) 2013 Faraday Technology Corporation
+ *
+ * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com>
+ *	   Feng-Hsin Chiang <john453@faraday-tech.com>
+ *	   Po-Yu Chuang <ratbert.chuang@gmail.com>
+ *
+ * Most of code borrowed from the Linux-3.7 EHCI driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+
+/*-------------------------------------------------------------------------*/
+#define DRIVER_AUTHOR "Yuan-Hsin Chen"
+#define DRIVER_DESC "FOTG210 Host Controller (EHCI) Driver"
+
+static const char	hcd_name[] = "fotg210_hcd";
+
+#undef VERBOSE_DEBUG
+#undef FOTG210_URB_TRACE
+
+#ifdef DEBUG
+#define FOTG210_STATS
+#endif
+
+/* magic numbers that can affect system performance */
+#define	FOTG210_TUNE_CERR		3 /* 0-3 qtd retries; 0 == don't stop */
+#define	FOTG210_TUNE_RL_HS		4 /* nak throttle; see 4.9 */
+#define	FOTG210_TUNE_RL_TT		0
+#define	FOTG210_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
+#define	FOTG210_TUNE_MULT_TT	1
+/*
+ * Some drivers think it's safe to schedule isochronous transfers more than
+ * 256 ms into the future (partly as a result of an old bug in the scheduling
+ * code).  In an attempt to avoid trouble, we will use a minimum scheduling
+ * length of 512 frames instead of 256.
+ */
+#define	FOTG210_TUNE_FLS		1 /* (medium) 512-frame schedule */
+
+/* Initial IRQ latency:  faster than hw default */
+static int log2_irq_thresh;		/* 0 to 6 */
+module_param(log2_irq_thresh, int, S_IRUGO);
+MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
+
+/* initial park setting:  slower than hw default */
+static unsigned park;
+module_param(park, uint, S_IRUGO);
+MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets");
+
+/* for link power management(LPM) feature */
+static unsigned int hird;
+module_param(hird, int, S_IRUGO);
+MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
+
+#define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
+
+#include "fotg210.h"
+
+/*-------------------------------------------------------------------------*/
+
+#define fotg210_dbg(fotg210, fmt, args...) \
+	dev_dbg(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+#define fotg210_err(fotg210, fmt, args...) \
+	dev_err(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+#define fotg210_info(fotg210, fmt, args...) \
+	dev_info(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+#define fotg210_warn(fotg210, fmt, args...) \
+	dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+
+#ifdef VERBOSE_DEBUG
+#	define fotg210_vdbg fotg210_dbg
+#else
+	static inline void fotg210_vdbg(struct fotg210_hcd *fotg210, ...) {}
+#endif
+
+#ifdef	DEBUG
+
+/* check the values in the HCSPARAMS register
+ * (host controller _Structural_ parameters)
+ * see EHCI spec, Table 2-4 for each value
+ */
+static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label)
+{
+	u32	params = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
+
+	fotg210_dbg(fotg210,
+		"%s hcs_params 0x%x ports=%d\n",
+		label, params,
+		HCS_N_PORTS(params)
+		);
+}
+#else
+
+static inline void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) {}
+
+#endif
+
+#ifdef	DEBUG
+
+/* check the values in the HCCPARAMS register
+ * (host controller _Capability_ parameters)
+ * see EHCI Spec, Table 2-5 for each value
+ * */
+static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label)
+{
+	u32	params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
+
+	fotg210_dbg(fotg210,
+		"%s hcc_params %04x uframes %s%s\n",
+		label,
+		params,
+		HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+		HCC_CANPARK(params) ? " park" : "");
+}
+#else
+
+static inline void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) {}
+
+#endif
+
+#ifdef	DEBUG
+
+static void __maybe_unused
+dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd)
+{
+	fotg210_dbg(fotg210, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
+		hc32_to_cpup(fotg210, &qtd->hw_next),
+		hc32_to_cpup(fotg210, &qtd->hw_alt_next),
+		hc32_to_cpup(fotg210, &qtd->hw_token),
+		hc32_to_cpup(fotg210, &qtd->hw_buf[0]));
+	if (qtd->hw_buf[1])
+		fotg210_dbg(fotg210, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
+			hc32_to_cpup(fotg210, &qtd->hw_buf[1]),
+			hc32_to_cpup(fotg210, &qtd->hw_buf[2]),
+			hc32_to_cpup(fotg210, &qtd->hw_buf[3]),
+			hc32_to_cpup(fotg210, &qtd->hw_buf[4]));
+}
+
+static void __maybe_unused
+dbg_qh(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	struct fotg210_qh_hw *hw = qh->hw;
+
+	fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label,
+		qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
+	dbg_qtd("overlay", fotg210, (struct fotg210_qtd *) &hw->hw_qtd_next);
+}
+
+static void __maybe_unused
+dbg_itd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
+{
+	fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n",
+		label, itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next),
+		itd->urb);
+	fotg210_dbg(fotg210,
+		"  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+		hc32_to_cpu(fotg210, itd->hw_transaction[0]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[1]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[2]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[3]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[4]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[5]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[6]),
+		hc32_to_cpu(fotg210, itd->hw_transaction[7]));
+	fotg210_dbg(fotg210,
+		"  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
+		hc32_to_cpu(fotg210, itd->hw_bufp[0]),
+		hc32_to_cpu(fotg210, itd->hw_bufp[1]),
+		hc32_to_cpu(fotg210, itd->hw_bufp[2]),
+		hc32_to_cpu(fotg210, itd->hw_bufp[3]),
+		hc32_to_cpu(fotg210, itd->hw_bufp[4]),
+		hc32_to_cpu(fotg210, itd->hw_bufp[5]),
+		hc32_to_cpu(fotg210, itd->hw_bufp[6]));
+	fotg210_dbg(fotg210, "  index: %d %d %d %d %d %d %d %d\n",
+		itd->index[0], itd->index[1], itd->index[2],
+		itd->index[3], itd->index[4], itd->index[5],
+		itd->index[6], itd->index[7]);
+}
+
+static int __maybe_unused
+dbg_status_buf(char *buf, unsigned len, const char *label, u32 status)
+{
+	return scnprintf(buf, len,
+		"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
+		label, label[0] ? " " : "", status,
+		(status & STS_ASS) ? " Async" : "",
+		(status & STS_PSS) ? " Periodic" : "",
+		(status & STS_RECL) ? " Recl" : "",
+		(status & STS_HALT) ? " Halt" : "",
+		(status & STS_IAA) ? " IAA" : "",
+		(status & STS_FATAL) ? " FATAL" : "",
+		(status & STS_FLR) ? " FLR" : "",
+		(status & STS_PCD) ? " PCD" : "",
+		(status & STS_ERR) ? " ERR" : "",
+		(status & STS_INT) ? " INT" : ""
+		);
+}
+
+static int __maybe_unused
+dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable)
+{
+	return scnprintf(buf, len,
+		"%s%sintrenable %02x%s%s%s%s%s%s",
+		label, label[0] ? " " : "", enable,
+		(enable & STS_IAA) ? " IAA" : "",
+		(enable & STS_FATAL) ? " FATAL" : "",
+		(enable & STS_FLR) ? " FLR" : "",
+		(enable & STS_PCD) ? " PCD" : "",
+		(enable & STS_ERR) ? " ERR" : "",
+		(enable & STS_INT) ? " INT" : ""
+		);
+}
+
+static const char *const fls_strings[] = { "1024", "512", "256", "??" };
+
+static int
+dbg_command_buf(char *buf, unsigned len, const char *label, u32 command)
+{
+	return scnprintf(buf, len,
+		"%s%scommand %07x %s=%d ithresh=%d%s%s%s "
+		"period=%s%s %s",
+		label, label[0] ? " " : "", command,
+		(command & CMD_PARK) ? " park" : "(park)",
+		CMD_PARK_CNT(command),
+		(command >> 16) & 0x3f,
+		(command & CMD_IAAD) ? " IAAD" : "",
+		(command & CMD_ASE) ? " Async" : "",
+		(command & CMD_PSE) ? " Periodic" : "",
+		fls_strings[(command >> 2) & 0x3],
+		(command & CMD_RESET) ? " Reset" : "",
+		(command & CMD_RUN) ? "RUN" : "HALT"
+		);
+}
+
+static int
+dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status)
+{
+	char	*sig;
+
+	/* signaling state */
+	switch (status & (3 << 10)) {
+	case 0 << 10:
+		sig = "se0";
+		break;
+	case 1 << 10:
+		sig = "k";
+		break; /* low speed */
+	case 2 << 10:
+		sig = "j";
+		break;
+	default:
+		sig = "?";
+		break;
+	}
+
+	return scnprintf(buf, len,
+		"%s%sport:%d status %06x %d "
+		"sig=%s%s%s%s%s%s%s%s",
+		label, label[0] ? " " : "", port, status,
+		status>>25,/*device address */
+		sig,
+		(status & PORT_RESET) ? " RESET" : "",
+		(status & PORT_SUSPEND) ? " SUSPEND" : "",
+		(status & PORT_RESUME) ? " RESUME" : "",
+		(status & PORT_PEC) ? " PEC" : "",
+		(status & PORT_PE) ? " PE" : "",
+		(status & PORT_CSC) ? " CSC" : "",
+		(status & PORT_CONNECT) ? " CONNECT" : "");
+}
+
+#else
+static inline void __maybe_unused
+dbg_qh(char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{}
+
+static inline int __maybe_unused
+dbg_status_buf(char *buf, unsigned len, const char *label, u32 status)
+{ return 0; }
+
+static inline int __maybe_unused
+dbg_command_buf(char *buf, unsigned len, const char *label, u32 command)
+{ return 0; }
+
+static inline int __maybe_unused
+dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable)
+{ return 0; }
+
+static inline int __maybe_unused
+dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status)
+{ return 0; }
+
+#endif	/* DEBUG */
+
+/* functions have the "wrong" filename when they're output... */
+#define dbg_status(fotg210, label, status) { \
+	char _buf[80]; \
+	dbg_status_buf(_buf, sizeof(_buf), label, status); \
+	fotg210_dbg(fotg210, "%s\n", _buf); \
+}
+
+#define dbg_cmd(fotg210, label, command) { \
+	char _buf[80]; \
+	dbg_command_buf(_buf, sizeof(_buf), label, command); \
+	fotg210_dbg(fotg210, "%s\n", _buf); \
+}
+
+#define dbg_port(fotg210, label, port, status) { \
+	char _buf[80]; \
+	dbg_port_buf(_buf, sizeof(_buf), label, port, status); \
+	fotg210_dbg(fotg210, "%s\n", _buf); \
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef STUB_DEBUG_FILES
+
+static inline void create_debug_files(struct fotg210_hcd *bus) { }
+static inline void remove_debug_files(struct fotg210_hcd *bus) { }
+
+#else
+
+/* troubleshooting help: expose state in debugfs */
+
+static int debug_async_open(struct inode *, struct file *);
+static int debug_periodic_open(struct inode *, struct file *);
+static int debug_registers_open(struct inode *, struct file *);
+static int debug_async_open(struct inode *, struct file *);
+
+static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+static int debug_close(struct inode *, struct file *);
+
+static const struct file_operations debug_async_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_async_open,
+	.read		= debug_output,
+	.release	= debug_close,
+	.llseek		= default_llseek,
+};
+static const struct file_operations debug_periodic_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_periodic_open,
+	.read		= debug_output,
+	.release	= debug_close,
+	.llseek		= default_llseek,
+};
+static const struct file_operations debug_registers_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_registers_open,
+	.read		= debug_output,
+	.release	= debug_close,
+	.llseek		= default_llseek,
+};
+
+static struct dentry *fotg210_debug_root;
+
+struct debug_buffer {
+	ssize_t (*fill_func)(struct debug_buffer *);	/* fill method */
+	struct usb_bus *bus;
+	struct mutex mutex;	/* protect filling of buffer */
+	size_t count;		/* number of characters filled into buffer */
+	char *output_buf;
+	size_t alloc_size;
+};
+
+#define speed_char(info1)({ char tmp; \
+		switch (info1 & (3 << 12)) { \
+		case QH_FULL_SPEED:	\
+			tmp = 'f'; break; \
+		case QH_LOW_SPEED:	\
+			tmp = 'l'; break; \
+		case QH_HIGH_SPEED:	\
+			tmp = 'h'; break; \
+		default:		\
+			tmp = '?'; break; \
+		}; tmp; })
+
+static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token)
+{
+	__u32 v = hc32_to_cpu(fotg210, token);
+
+	if (v & QTD_STS_ACTIVE)
+		return '*';
+	if (v & QTD_STS_HALT)
+		return '-';
+	if (!IS_SHORT_READ(v))
+		return ' ';
+	/* tries to advance through hw_alt_next */
+	return '/';
+}
+
+static void qh_lines(
+	struct fotg210_hcd *fotg210,
+	struct fotg210_qh *qh,
+	char **nextp,
+	unsigned *sizep
+)
+{
+	u32			scratch;
+	u32			hw_curr;
+	struct fotg210_qtd	*td;
+	unsigned		temp;
+	unsigned		size = *sizep;
+	char			*next = *nextp;
+	char			mark;
+	__le32			list_end = FOTG210_LIST_END(fotg210);
+	struct fotg210_qh_hw	*hw = qh->hw;
+
+	if (hw->hw_qtd_next == list_end)	/* NEC does this */
+		mark = '@';
+	else
+		mark = token_mark(fotg210, hw->hw_token);
+	if (mark == '/') {	/* qh_alt_next controls qh advance? */
+		if ((hw->hw_alt_next & QTD_MASK(fotg210))
+				== fotg210->async->hw->hw_alt_next)
+			mark = '#';	/* blocked */
+		else if (hw->hw_alt_next == list_end)
+			mark = '.';	/* use hw_qtd_next */
+		/* else alt_next points to some other qtd */
+	}
+	scratch = hc32_to_cpup(fotg210, &hw->hw_info1);
+	hw_curr = (mark == '*') ? hc32_to_cpup(fotg210, &hw->hw_current) : 0;
+	temp = scnprintf(next, size,
+			"qh/%p dev%d %cs ep%d %08x %08x(%08x%c %s nak%d)",
+			qh, scratch & 0x007f,
+			speed_char(scratch),
+			(scratch >> 8) & 0x000f,
+			scratch, hc32_to_cpup(fotg210, &hw->hw_info2),
+			hc32_to_cpup(fotg210, &hw->hw_token), mark,
+			(cpu_to_hc32(fotg210, QTD_TOGGLE) & hw->hw_token)
+				? "data1" : "data0",
+			(hc32_to_cpup(fotg210, &hw->hw_alt_next) >> 1) & 0x0f);
+	size -= temp;
+	next += temp;
+
+	/* hc may be modifying the list as we read it ... */
+	list_for_each_entry(td, &qh->qtd_list, qtd_list) {
+		scratch = hc32_to_cpup(fotg210, &td->hw_token);
+		mark = ' ';
+		if (hw_curr == td->qtd_dma)
+			mark = '*';
+		else if (hw->hw_qtd_next == cpu_to_hc32(fotg210, td->qtd_dma))
+			mark = '+';
+		else if (QTD_LENGTH(scratch)) {
+			if (td->hw_alt_next == fotg210->async->hw->hw_alt_next)
+				mark = '#';
+			else if (td->hw_alt_next != list_end)
+				mark = '/';
+		}
+		temp = snprintf(next, size,
+				"\n\t%p%c%s len=%d %08x urb %p",
+				td, mark, ({ char *tmp;
+				 switch ((scratch>>8)&0x03) {
+				 case 0:
+					tmp = "out";
+					break;
+				 case 1:
+					tmp = "in";
+					break;
+				 case 2:
+					tmp = "setup";
+					break;
+				 default:
+					tmp = "?";
+					break;
+				 } tmp; }),
+				(scratch >> 16) & 0x7fff,
+				scratch,
+				td->urb);
+		if (size < temp)
+			temp = size;
+		size -= temp;
+		next += temp;
+		if (temp == size)
+			goto done;
+	}
+
+	temp = snprintf(next, size, "\n");
+	if (size < temp)
+		temp = size;
+	size -= temp;
+	next += temp;
+
+done:
+	*sizep = size;
+	*nextp = next;
+}
+
+static ssize_t fill_async_buffer(struct debug_buffer *buf)
+{
+	struct usb_hcd		*hcd;
+	struct fotg210_hcd	*fotg210;
+	unsigned long		flags;
+	unsigned		temp, size;
+	char			*next;
+	struct fotg210_qh		*qh;
+
+	hcd = bus_to_hcd(buf->bus);
+	fotg210 = hcd_to_fotg210(hcd);
+	next = buf->output_buf;
+	size = buf->alloc_size;
+
+	*next = 0;
+
+	/* dumps a snapshot of the async schedule.
+	 * usually empty except for long-term bulk reads, or head.
+	 * one QH per line, and TDs we know about
+	 */
+	spin_lock_irqsave(&fotg210->lock, flags);
+	for (qh = fotg210->async->qh_next.qh; size > 0 && qh;
+	     qh = qh->qh_next.qh)
+		qh_lines(fotg210, qh, &next, &size);
+	if (fotg210->async_unlink && size > 0) {
+		temp = scnprintf(next, size, "\nunlink =\n");
+		size -= temp;
+		next += temp;
+
+		for (qh = fotg210->async_unlink; size > 0 && qh;
+				qh = qh->unlink_next)
+			qh_lines(fotg210, qh, &next, &size);
+	}
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+
+	return strlen(buf->output_buf);
+}
+
+#define DBG_SCHED_LIMIT 64
+static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+{
+	struct usb_hcd		*hcd;
+	struct fotg210_hcd		*fotg210;
+	unsigned long		flags;
+	union fotg210_shadow	p, *seen;
+	unsigned		temp, size, seen_count;
+	char			*next;
+	unsigned		i;
+	__hc32			tag;
+
+	seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC);
+	if (!seen)
+		return 0;
+	seen_count = 0;
+
+	hcd = bus_to_hcd(buf->bus);
+	fotg210 = hcd_to_fotg210(hcd);
+	next = buf->output_buf;
+	size = buf->alloc_size;
+
+	temp = scnprintf(next, size, "size = %d\n", fotg210->periodic_size);
+	size -= temp;
+	next += temp;
+
+	/* dump a snapshot of the periodic schedule.
+	 * iso changes, interrupt usually doesn't.
+	 */
+	spin_lock_irqsave(&fotg210->lock, flags);
+	for (i = 0; i < fotg210->periodic_size; i++) {
+		p = fotg210->pshadow[i];
+		if (likely(!p.ptr))
+			continue;
+		tag = Q_NEXT_TYPE(fotg210, fotg210->periodic[i]);
+
+		temp = scnprintf(next, size, "%4d: ", i);
+		size -= temp;
+		next += temp;
+
+		do {
+			struct fotg210_qh_hw *hw;
+
+			switch (hc32_to_cpu(fotg210, tag)) {
+			case Q_TYPE_QH:
+				hw = p.qh->hw;
+				temp = scnprintf(next, size, " qh%d-%04x/%p",
+						p.qh->period,
+						hc32_to_cpup(fotg210,
+							&hw->hw_info2)
+							/* uframe masks */
+							& (QH_CMASK | QH_SMASK),
+						p.qh);
+				size -= temp;
+				next += temp;
+				/* don't repeat what follows this qh */
+				for (temp = 0; temp < seen_count; temp++) {
+					if (seen[temp].ptr != p.ptr)
+						continue;
+					if (p.qh->qh_next.ptr) {
+						temp = scnprintf(next, size,
+							" ...");
+						size -= temp;
+						next += temp;
+					}
+					break;
+				}
+				/* show more info the first time around */
+				if (temp == seen_count) {
+					u32	scratch = hc32_to_cpup(fotg210,
+							&hw->hw_info1);
+					struct fotg210_qtd	*qtd;
+					char		*type = "";
+
+					/* count tds, get ep direction */
+					temp = 0;
+					list_for_each_entry(qtd,
+							&p.qh->qtd_list,
+							qtd_list) {
+						temp++;
+						switch (0x03 & (hc32_to_cpu(
+							fotg210,
+							qtd->hw_token) >> 8)) {
+						case 0:
+							type = "out";
+							continue;
+						case 1:
+							type = "in";
+							continue;
+						}
+					}
+
+					temp = scnprintf(next, size,
+						"(%c%d ep%d%s "
+						"[%d/%d] q%d p%d)",
+						speed_char(scratch),
+						scratch & 0x007f,
+						(scratch >> 8) & 0x000f, type,
+						p.qh->usecs, p.qh->c_usecs,
+						temp,
+						0x7ff & (scratch >> 16));
+
+					if (seen_count < DBG_SCHED_LIMIT)
+						seen[seen_count++].qh = p.qh;
+				} else
+					temp = 0;
+				tag = Q_NEXT_TYPE(fotg210, hw->hw_next);
+				p = p.qh->qh_next;
+				break;
+			case Q_TYPE_FSTN:
+				temp = scnprintf(next, size,
+					" fstn-%8x/%p", p.fstn->hw_prev,
+					p.fstn);
+				tag = Q_NEXT_TYPE(fotg210, p.fstn->hw_next);
+				p = p.fstn->fstn_next;
+				break;
+			case Q_TYPE_ITD:
+				temp = scnprintf(next, size,
+					" itd/%p", p.itd);
+				tag = Q_NEXT_TYPE(fotg210, p.itd->hw_next);
+				p = p.itd->itd_next;
+				break;
+			}
+			size -= temp;
+			next += temp;
+		} while (p.ptr);
+
+		temp = scnprintf(next, size, "\n");
+		size -= temp;
+		next += temp;
+	}
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	kfree(seen);
+
+	return buf->alloc_size - size;
+}
+#undef DBG_SCHED_LIMIT
+
+static const char *rh_state_string(struct fotg210_hcd *fotg210)
+{
+	switch (fotg210->rh_state) {
+	case FOTG210_RH_HALTED:
+		return "halted";
+	case FOTG210_RH_SUSPENDED:
+		return "suspended";
+	case FOTG210_RH_RUNNING:
+		return "running";
+	case FOTG210_RH_STOPPING:
+		return "stopping";
+	}
+	return "?";
+}
+
+static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+{
+	struct usb_hcd		*hcd;
+	struct fotg210_hcd	*fotg210;
+	unsigned long		flags;
+	unsigned		temp, size, i;
+	char			*next, scratch[80];
+	static const char	fmt[] = "%*s\n";
+	static const char	label[] = "";
+
+	hcd = bus_to_hcd(buf->bus);
+	fotg210 = hcd_to_fotg210(hcd);
+	next = buf->output_buf;
+	size = buf->alloc_size;
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
+		size = scnprintf(next, size,
+			"bus %s, device %s\n"
+			"%s\n"
+			"SUSPENDED(no register access)\n",
+			hcd->self.controller->bus->name,
+			dev_name(hcd->self.controller),
+			hcd->product_desc);
+		goto done;
+	}
+
+	/* Capability Registers */
+	i = HC_VERSION(fotg210, fotg210_readl(fotg210,
+					      &fotg210->caps->hc_capbase));
+	temp = scnprintf(next, size,
+		"bus %s, device %s\n"
+		"%s\n"
+		"EHCI %x.%02x, rh state %s\n",
+		hcd->self.controller->bus->name,
+		dev_name(hcd->self.controller),
+		hcd->product_desc,
+		i >> 8, i & 0x0ff, rh_state_string(fotg210));
+	size -= temp;
+	next += temp;
+
+	/* FIXME interpret both types of params */
+	i = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
+	temp = scnprintf(next, size, "structural params 0x%08x\n", i);
+	size -= temp;
+	next += temp;
+
+	i = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
+	temp = scnprintf(next, size, "capability params 0x%08x\n", i);
+	size -= temp;
+	next += temp;
+
+	/* Operational Registers */
+	temp = dbg_status_buf(scratch, sizeof(scratch), label,
+			fotg210_readl(fotg210, &fotg210->regs->status));
+	temp = scnprintf(next, size, fmt, temp, scratch);
+	size -= temp;
+	next += temp;
+
+	temp = dbg_command_buf(scratch, sizeof(scratch), label,
+			fotg210_readl(fotg210, &fotg210->regs->command));
+	temp = scnprintf(next, size, fmt, temp, scratch);
+	size -= temp;
+	next += temp;
+
+	temp = dbg_intr_buf(scratch, sizeof(scratch), label,
+			fotg210_readl(fotg210, &fotg210->regs->intr_enable));
+	temp = scnprintf(next, size, fmt, temp, scratch);
+	size -= temp;
+	next += temp;
+
+	temp = scnprintf(next, size, "uframe %04x\n",
+			fotg210_read_frame_index(fotg210));
+	size -= temp;
+	next += temp;
+
+	if (fotg210->async_unlink) {
+		temp = scnprintf(next, size, "async unlink qh %p\n",
+				fotg210->async_unlink);
+		size -= temp;
+		next += temp;
+	}
+
+#ifdef FOTG210_STATS
+	temp = scnprintf(next, size,
+		"irq normal %ld err %ld iaa %ld(lost %ld)\n",
+		fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa,
+		fotg210->stats.lost_iaa);
+	size -= temp;
+	next += temp;
+
+	temp = scnprintf(next, size, "complete %ld unlink %ld\n",
+		fotg210->stats.complete, fotg210->stats.unlink);
+	size -= temp;
+	next += temp;
+#endif
+
+done:
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+
+	return buf->alloc_size - size;
+}
+
+static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
+				ssize_t (*fill_func)(struct debug_buffer *))
+{
+	struct debug_buffer *buf;
+
+	buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
+
+	if (buf) {
+		buf->bus = bus;
+		buf->fill_func = fill_func;
+		mutex_init(&buf->mutex);
+		buf->alloc_size = PAGE_SIZE;
+	}
+
+	return buf;
+}
+
+static int fill_buffer(struct debug_buffer *buf)
+{
+	int ret = 0;
+
+	if (!buf->output_buf)
+		buf->output_buf = vmalloc(buf->alloc_size);
+
+	if (!buf->output_buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = buf->fill_func(buf);
+
+	if (ret >= 0) {
+		buf->count = ret;
+		ret = 0;
+	}
+
+out:
+	return ret;
+}
+
+static ssize_t debug_output(struct file *file, char __user *user_buf,
+			    size_t len, loff_t *offset)
+{
+	struct debug_buffer *buf = file->private_data;
+	int ret = 0;
+
+	mutex_lock(&buf->mutex);
+	if (buf->count == 0) {
+		ret = fill_buffer(buf);
+		if (ret != 0) {
+			mutex_unlock(&buf->mutex);
+			goto out;
+		}
+	}
+	mutex_unlock(&buf->mutex);
+
+	ret = simple_read_from_buffer(user_buf, len, offset,
+				      buf->output_buf, buf->count);
+
+out:
+	return ret;
+
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf = file->private_data;
+
+	if (buf) {
+		vfree(buf->output_buf);
+		kfree(buf);
+	}
+
+	return 0;
+}
+static int debug_async_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_periodic_open(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf;
+	buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
+	if (!buf)
+		return -ENOMEM;
+
+	buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE;
+	file->private_data = buf;
+	return 0;
+}
+
+static int debug_registers_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_registers_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static inline void create_debug_files(struct fotg210_hcd *fotg210)
+{
+	struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self;
+
+	fotg210->debug_dir = debugfs_create_dir(bus->bus_name,
+						fotg210_debug_root);
+	if (!fotg210->debug_dir)
+		return;
+
+	if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus,
+						&debug_async_fops))
+		goto file_error;
+
+	if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus,
+						&debug_periodic_fops))
+		goto file_error;
+
+	if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus,
+						    &debug_registers_fops))
+		goto file_error;
+
+	return;
+
+file_error:
+	debugfs_remove_recursive(fotg210->debug_dir);
+}
+
+static inline void remove_debug_files(struct fotg210_hcd *fotg210)
+{
+	debugfs_remove_recursive(fotg210->debug_dir);
+}
+
+#endif /* STUB_DEBUG_FILES */
+/*-------------------------------------------------------------------------*/
+
+/*
+ * handshake - spin reading hc until handshake completes or fails
+ * @ptr: address of hc register to be read
+ * @mask: bits to look at in result of read
+ * @done: value of those bits when handshake succeeds
+ * @usec: timeout in microseconds
+ *
+ * Returns negative errno, or zero on success
+ *
+ * Success happens when the "mask" bits have the specified value (hardware
+ * handshake done).  There are two failure modes:  "usec" have passed (major
+ * hardware flakeout), or the register reads as all-ones (hardware removed).
+ *
+ * That last failure should_only happen in cases like physical cardbus eject
+ * before driver shutdown. But it also seems to be caused by bugs in cardbus
+ * bridge shutdown:  shutting down the bridge before the devices using it.
+ */
+static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr,
+		      u32 mask, u32 done, int usec)
+{
+	u32	result;
+
+	do {
+		result = fotg210_readl(fotg210, ptr);
+		if (result == ~(u32)0)		/* card removed */
+			return -ENODEV;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -ETIMEDOUT;
+}
+
+/*
+ * Force HC to halt state from unknown (EHCI spec section 2.3).
+ * Must be called with interrupts enabled and the lock not held.
+ */
+static int fotg210_halt(struct fotg210_hcd *fotg210)
+{
+	u32	temp;
+
+	spin_lock_irq(&fotg210->lock);
+
+	/* disable any irqs left enabled by previous code */
+	fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
+
+	/*
+	 * This routine gets called during probe before fotg210->command
+	 * has been initialized, so we can't rely on its value.
+	 */
+	fotg210->command &= ~CMD_RUN;
+	temp = fotg210_readl(fotg210, &fotg210->regs->command);
+	temp &= ~(CMD_RUN | CMD_IAAD);
+	fotg210_writel(fotg210, temp, &fotg210->regs->command);
+
+	spin_unlock_irq(&fotg210->lock);
+	synchronize_irq(fotg210_to_hcd(fotg210)->irq);
+
+	return handshake(fotg210, &fotg210->regs->status,
+			  STS_HALT, STS_HALT, 16 * 125);
+}
+
+/*
+ * Reset a non-running (STS_HALT == 1) controller.
+ * Must be called with interrupts enabled and the lock not held.
+ */
+static int fotg210_reset(struct fotg210_hcd *fotg210)
+{
+	int	retval;
+	u32	command = fotg210_readl(fotg210, &fotg210->regs->command);
+
+	/* If the EHCI debug controller is active, special care must be
+	 * taken before and after a host controller reset */
+	if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210)))
+		fotg210->debug = NULL;
+
+	command |= CMD_RESET;
+	dbg_cmd(fotg210, "reset", command);
+	fotg210_writel(fotg210, command, &fotg210->regs->command);
+	fotg210->rh_state = FOTG210_RH_HALTED;
+	fotg210->next_statechange = jiffies;
+	retval = handshake(fotg210, &fotg210->regs->command,
+			    CMD_RESET, 0, 250 * 1000);
+
+	if (retval)
+		return retval;
+
+	if (fotg210->debug)
+		dbgp_external_startup(fotg210_to_hcd(fotg210));
+
+	fotg210->port_c_suspend = fotg210->suspended_ports =
+			fotg210->resuming_ports = 0;
+	return retval;
+}
+
+/*
+ * Idle the controller (turn off the schedules).
+ * Must be called with interrupts enabled and the lock not held.
+ */
+static void fotg210_quiesce(struct fotg210_hcd *fotg210)
+{
+	u32	temp;
+
+	if (fotg210->rh_state != FOTG210_RH_RUNNING)
+		return;
+
+	/* wait for any schedule enables/disables to take effect */
+	temp = (fotg210->command << 10) & (STS_ASS | STS_PSS);
+	handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp,
+		  16 * 125);
+
+	/* then disable anything that's still active */
+	spin_lock_irq(&fotg210->lock);
+	fotg210->command &= ~(CMD_ASE | CMD_PSE);
+	fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
+	spin_unlock_irq(&fotg210->lock);
+
+	/* hardware can take 16 microframes to turn off ... */
+	handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0,
+		  16 * 125);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void end_unlink_async(struct fotg210_hcd *fotg210);
+static void unlink_empty_async(struct fotg210_hcd *fotg210);
+static void fotg210_work(struct fotg210_hcd *fotg210);
+static void start_unlink_intr(struct fotg210_hcd *fotg210,
+			      struct fotg210_qh *qh);
+static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
+
+/*-------------------------------------------------------------------------*/
+
+/* Set a bit in the USBCMD register */
+static void fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit)
+{
+	fotg210->command |= bit;
+	fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
+
+	/* unblock posted write */
+	fotg210_readl(fotg210, &fotg210->regs->command);
+}
+
+/* Clear a bit in the USBCMD register */
+static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit)
+{
+	fotg210->command &= ~bit;
+	fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
+
+	/* unblock posted write */
+	fotg210_readl(fotg210, &fotg210->regs->command);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI timer support...  Now using hrtimers.
+ *
+ * Lots of different events are triggered from fotg210->hrtimer.  Whenever
+ * the timer routine runs, it checks each possible event; events that are
+ * currently enabled and whose expiration time has passed get handled.
+ * The set of enabled events is stored as a collection of bitflags in
+ * fotg210->enabled_hrtimer_events, and they are numbered in order of
+ * increasing delay values (ranging between 1 ms and 100 ms).
+ *
+ * Rather than implementing a sorted list or tree of all pending events,
+ * we keep track only of the lowest-numbered pending event, in
+ * fotg210->next_hrtimer_event.  Whenever fotg210->hrtimer gets restarted, its
+ * expiration time is set to the timeout value for this event.
+ *
+ * As a result, events might not get handled right away; the actual delay
+ * could be anywhere up to twice the requested delay.  This doesn't
+ * matter, because none of the events are especially time-critical.  The
+ * ones that matter most all have a delay of 1 ms, so they will be
+ * handled after 2 ms at most, which is okay.  In addition to this, we
+ * allow for an expiration range of 1 ms.
+ */
+
+/*
+ * Delay lengths for the hrtimer event types.
+ * Keep this list sorted by delay length, in the same order as
+ * the event types indexed by enum fotg210_hrtimer_event in fotg210.h.
+ */
+static unsigned event_delays_ns[] = {
+	1 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_POLL_ASS */
+	1 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_POLL_PSS */
+	1 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_POLL_DEAD */
+	1125 * NSEC_PER_USEC,	/* FOTG210_HRTIMER_UNLINK_INTR */
+	2 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_FREE_ITDS */
+	6 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_ASYNC_UNLINKS */
+	10 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_IAA_WATCHDOG */
+	10 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_DISABLE_PERIODIC */
+	15 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_DISABLE_ASYNC */
+	100 * NSEC_PER_MSEC,	/* FOTG210_HRTIMER_IO_WATCHDOG */
+};
+
+/* Enable a pending hrtimer event */
+static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event,
+		bool resched)
+{
+	ktime_t		*timeout = &fotg210->hr_timeouts[event];
+
+	if (resched)
+		*timeout = ktime_add(ktime_get(),
+				ktime_set(0, event_delays_ns[event]));
+	fotg210->enabled_hrtimer_events |= (1 << event);
+
+	/* Track only the lowest-numbered pending event */
+	if (event < fotg210->next_hrtimer_event) {
+		fotg210->next_hrtimer_event = event;
+		hrtimer_start_range_ns(&fotg210->hrtimer, *timeout,
+				NSEC_PER_MSEC, HRTIMER_MODE_ABS);
+	}
+}
+
+
+/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */
+static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
+{
+	unsigned	actual, want;
+
+	/* Don't enable anything if the controller isn't running (e.g., died) */
+	if (fotg210->rh_state != FOTG210_RH_RUNNING)
+		return;
+
+	want = (fotg210->command & CMD_ASE) ? STS_ASS : 0;
+	actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_ASS;
+
+	if (want != actual) {
+
+		/* Poll again later, but give up after about 20 ms */
+		if (fotg210->ASS_poll_count++ < 20) {
+			fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS,
+					     true);
+			return;
+		}
+		fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n",
+				want, actual);
+	}
+	fotg210->ASS_poll_count = 0;
+
+	/* The status is up-to-date; restart or stop the schedule as needed */
+	if (want == 0) {	/* Stopped */
+		if (fotg210->async_count > 0)
+			fotg210_set_command_bit(fotg210, CMD_ASE);
+
+	} else {		/* Running */
+		if (fotg210->async_count == 0) {
+
+			/* Turn off the schedule after a while */
+			fotg210_enable_event(fotg210,
+					     FOTG210_HRTIMER_DISABLE_ASYNC,
+					     true);
+		}
+	}
+}
+
+/* Turn off the async schedule after a brief delay */
+static void fotg210_disable_ASE(struct fotg210_hcd *fotg210)
+{
+	fotg210_clear_command_bit(fotg210, CMD_ASE);
+}
+
+
+/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
+static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
+{
+	unsigned	actual, want;
+
+	/* Don't do anything if the controller isn't running (e.g., died) */
+	if (fotg210->rh_state != FOTG210_RH_RUNNING)
+		return;
+
+	want = (fotg210->command & CMD_PSE) ? STS_PSS : 0;
+	actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_PSS;
+
+	if (want != actual) {
+
+		/* Poll again later, but give up after about 20 ms */
+		if (fotg210->PSS_poll_count++ < 20) {
+			fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS,
+					     true);
+			return;
+		}
+		fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
+				want, actual);
+	}
+	fotg210->PSS_poll_count = 0;
+
+	/* The status is up-to-date; restart or stop the schedule as needed */
+	if (want == 0) {	/* Stopped */
+		if (fotg210->periodic_count > 0)
+			fotg210_set_command_bit(fotg210, CMD_PSE);
+
+	} else {		/* Running */
+		if (fotg210->periodic_count == 0) {
+
+			/* Turn off the schedule after a while */
+			fotg210_enable_event(fotg210,
+					     FOTG210_HRTIMER_DISABLE_PERIODIC,
+					     true);
+		}
+	}
+}
+
+/* Turn off the periodic schedule after a brief delay */
+static void fotg210_disable_PSE(struct fotg210_hcd *fotg210)
+{
+	fotg210_clear_command_bit(fotg210, CMD_PSE);
+}
+
+
+/* Poll the STS_HALT status bit; see when a dead controller stops */
+static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210)
+{
+	if (!(fotg210_readl(fotg210, &fotg210->regs->status) & STS_HALT)) {
+
+		/* Give up after a few milliseconds */
+		if (fotg210->died_poll_count++ < 5) {
+			/* Try again later */
+			fotg210_enable_event(fotg210,
+					     FOTG210_HRTIMER_POLL_DEAD, true);
+			return;
+		}
+		fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n");
+	}
+
+	/* Clean up the mess */
+	fotg210->rh_state = FOTG210_RH_HALTED;
+	fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
+	fotg210_work(fotg210);
+	end_unlink_async(fotg210);
+
+	/* Not in process context, so don't try to reset the controller */
+}
+
+
+/* Handle unlinked interrupt QHs once they are gone from the hardware */
+static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
+{
+	bool		stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
+
+	/*
+	 * Process all the QHs on the intr_unlink list that were added
+	 * before the current unlink cycle began.  The list is in
+	 * temporal order, so stop when we reach the first entry in the
+	 * current cycle.  But if the root hub isn't running then
+	 * process all the QHs on the list.
+	 */
+	fotg210->intr_unlinking = true;
+	while (fotg210->intr_unlink) {
+		struct fotg210_qh	*qh = fotg210->intr_unlink;
+
+		if (!stopped && qh->unlink_cycle == fotg210->intr_unlink_cycle)
+			break;
+		fotg210->intr_unlink = qh->unlink_next;
+		qh->unlink_next = NULL;
+		end_unlink_intr(fotg210, qh);
+	}
+
+	/* Handle remaining entries later */
+	if (fotg210->intr_unlink) {
+		fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR,
+				     true);
+		++fotg210->intr_unlink_cycle;
+	}
+	fotg210->intr_unlinking = false;
+}
+
+
+/* Start another free-iTDs/siTDs cycle */
+static void start_free_itds(struct fotg210_hcd *fotg210)
+{
+	if (!(fotg210->enabled_hrtimer_events &
+			BIT(FOTG210_HRTIMER_FREE_ITDS))) {
+		fotg210->last_itd_to_free = list_entry(
+				fotg210->cached_itd_list.prev,
+				struct fotg210_itd, itd_list);
+		fotg210_enable_event(fotg210, FOTG210_HRTIMER_FREE_ITDS, true);
+	}
+}
+
+/* Wait for controller to stop using old iTDs and siTDs */
+static void end_free_itds(struct fotg210_hcd *fotg210)
+{
+	struct fotg210_itd		*itd, *n;
+
+	if (fotg210->rh_state < FOTG210_RH_RUNNING)
+		fotg210->last_itd_to_free = NULL;
+
+	list_for_each_entry_safe(itd, n, &fotg210->cached_itd_list, itd_list) {
+		list_del(&itd->itd_list);
+		dma_pool_free(fotg210->itd_pool, itd, itd->itd_dma);
+		if (itd == fotg210->last_itd_to_free)
+			break;
+	}
+
+	if (!list_empty(&fotg210->cached_itd_list))
+		start_free_itds(fotg210);
+}
+
+
+/* Handle lost (or very late) IAA interrupts */
+static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210)
+{
+	if (fotg210->rh_state != FOTG210_RH_RUNNING)
+		return;
+
+	/*
+	 * Lost IAA irqs wedge things badly; seen first with a vt8235.
+	 * So we need this watchdog, but must protect it against both
+	 * (a) SMP races against real IAA firing and retriggering, and
+	 * (b) clean HC shutdown, when IAA watchdog was pending.
+	 */
+	if (fotg210->async_iaa) {
+		u32 cmd, status;
+
+		/* If we get here, IAA is *REALLY* late.  It's barely
+		 * conceivable that the system is so busy that CMD_IAAD
+		 * is still legitimately set, so let's be sure it's
+		 * clear before we read STS_IAA.  (The HC should clear
+		 * CMD_IAAD when it sets STS_IAA.)
+		 */
+		cmd = fotg210_readl(fotg210, &fotg210->regs->command);
+
+		/*
+		 * If IAA is set here it either legitimately triggered
+		 * after the watchdog timer expired (_way_ late, so we'll
+		 * still count it as lost) ... or a silicon erratum:
+		 * - VIA seems to set IAA without triggering the IRQ;
+		 * - IAAD potentially cleared without setting IAA.
+		 */
+		status = fotg210_readl(fotg210, &fotg210->regs->status);
+		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
+			COUNT(fotg210->stats.lost_iaa);
+			fotg210_writel(fotg210, STS_IAA,
+				       &fotg210->regs->status);
+		}
+
+		fotg210_vdbg(fotg210, "IAA watchdog: status %x cmd %x\n",
+				status, cmd);
+		end_unlink_async(fotg210);
+	}
+}
+
+
+/* Enable the I/O watchdog, if appropriate */
+static void turn_on_io_watchdog(struct fotg210_hcd *fotg210)
+{
+	/* Not needed if the controller isn't running or it's already enabled */
+	if (fotg210->rh_state != FOTG210_RH_RUNNING ||
+			(fotg210->enabled_hrtimer_events &
+				BIT(FOTG210_HRTIMER_IO_WATCHDOG)))
+		return;
+
+	/*
+	 * Isochronous transfers always need the watchdog.
+	 * For other sorts we use it only if the flag is set.
+	 */
+	if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog &&
+			fotg210->async_count + fotg210->intr_count > 0))
+		fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG,
+				     true);
+}
+
+
+/*
+ * Handler functions for the hrtimer event types.
+ * Keep this array in the same order as the event types indexed by
+ * enum fotg210_hrtimer_event in fotg210.h.
+ */
+static void (*event_handlers[])(struct fotg210_hcd *) = {
+	fotg210_poll_ASS,			/* FOTG210_HRTIMER_POLL_ASS */
+	fotg210_poll_PSS,			/* FOTG210_HRTIMER_POLL_PSS */
+	fotg210_handle_controller_death,	/* FOTG210_HRTIMER_POLL_DEAD */
+	fotg210_handle_intr_unlinks,	/* FOTG210_HRTIMER_UNLINK_INTR */
+	end_free_itds,			/* FOTG210_HRTIMER_FREE_ITDS */
+	unlink_empty_async,		/* FOTG210_HRTIMER_ASYNC_UNLINKS */
+	fotg210_iaa_watchdog,		/* FOTG210_HRTIMER_IAA_WATCHDOG */
+	fotg210_disable_PSE,		/* FOTG210_HRTIMER_DISABLE_PERIODIC */
+	fotg210_disable_ASE,		/* FOTG210_HRTIMER_DISABLE_ASYNC */
+	fotg210_work,			/* FOTG210_HRTIMER_IO_WATCHDOG */
+};
+
+static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t)
+{
+	struct fotg210_hcd *fotg210 =
+			container_of(t, struct fotg210_hcd, hrtimer);
+	ktime_t		now;
+	unsigned long	events;
+	unsigned long	flags;
+	unsigned	e;
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+
+	events = fotg210->enabled_hrtimer_events;
+	fotg210->enabled_hrtimer_events = 0;
+	fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT;
+
+	/*
+	 * Check each pending event.  If its time has expired, handle
+	 * the event; otherwise re-enable it.
+	 */
+	now = ktime_get();
+	for_each_set_bit(e, &events, FOTG210_HRTIMER_NUM_EVENTS) {
+		if (now.tv64 >= fotg210->hr_timeouts[e].tv64)
+			event_handlers[e](fotg210);
+		else
+			fotg210_enable_event(fotg210, e, false);
+	}
+
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	return HRTIMER_NORESTART;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define fotg210_bus_suspend	NULL
+#define fotg210_bus_resume	NULL
+
+/*-------------------------------------------------------------------------*/
+
+static int check_reset_complete(
+	struct fotg210_hcd	*fotg210,
+	int		index,
+	u32 __iomem	*status_reg,
+	int		port_status
+) {
+	if (!(port_status & PORT_CONNECT))
+		return port_status;
+
+	/* if reset finished and it's still not enabled -- handoff */
+	if (!(port_status & PORT_PE)) {
+		/* with integrated TT, there's nobody to hand it to! */
+		fotg210_dbg(fotg210,
+			"Failed to enable port %d on root hub TT\n",
+			index+1);
+		return port_status;
+	} else {
+		fotg210_dbg(fotg210, "port %d reset complete, port enabled\n",
+			index + 1);
+	}
+
+	return port_status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+/* build "status change" packet (one or two bytes) from HC registers */
+
+static int
+fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct fotg210_hcd	*fotg210 = hcd_to_fotg210(hcd);
+	u32		temp, status;
+	u32		mask;
+	int		retval = 1;
+	unsigned long	flags;
+
+	/* init status to no-changes */
+	buf[0] = 0;
+
+	/* Inform the core about resumes-in-progress by returning
+	 * a non-zero value even if there are no status changes.
+	 */
+	status = fotg210->resuming_ports;
+
+	mask = PORT_CSC | PORT_PEC;
+	/* PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND */
+
+	/* no hub change reports (bit 0) for now (power, ...) */
+
+	/* port N changes (bit N)? */
+	spin_lock_irqsave(&fotg210->lock, flags);
+
+	temp = fotg210_readl(fotg210, &fotg210->regs->port_status);
+
+	/*
+	 * Return status information even for ports with OWNER set.
+	 * Otherwise khubd wouldn't see the disconnect event when a
+	 * high-speed device is switched over to the companion
+	 * controller by the user.
+	 */
+
+	if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend)
+			|| (fotg210->reset_done[0] && time_after_eq(
+				jiffies, fotg210->reset_done[0]))) {
+		buf[0] |= 1 << 1;
+		status = STS_PCD;
+	}
+	/* FIXME autosuspend idle root hubs */
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	return status ? retval : 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+fotg210_hub_descriptor(
+	struct fotg210_hcd		*fotg210,
+	struct usb_hub_descriptor	*desc
+) {
+	int		ports = HCS_N_PORTS(fotg210->hcs_params);
+	u16		temp;
+
+	desc->bDescriptorType = 0x29;
+	desc->bPwrOn2PwrGood = 10;	/* fotg210 1.0, 2.3.9 says 20ms max */
+	desc->bHubContrCurrent = 0;
+
+	desc->bNbrPorts = ports;
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
+
+	temp = 0x0008;		/* per-port overcurrent reporting */
+	temp |= 0x0002;		/* no power switching */
+	desc->wHubCharacteristics = cpu_to_le16(temp);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int fotg210_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength
+) {
+	struct fotg210_hcd	*fotg210 = hcd_to_fotg210(hcd);
+	int		ports = HCS_N_PORTS(fotg210->hcs_params);
+	u32 __iomem	*status_reg = &fotg210->regs->port_status;
+	u32		temp, temp1, status;
+	unsigned long	flags;
+	int		retval = 0;
+	unsigned	selector;
+
+	/*
+	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
+	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
+	 * (track current state ourselves) ... blink for diagnostics,
+	 * power, "this is the one", etc.  EHCI spec supports this.
+	 */
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+	switch (typeReq) {
+	case ClearHubFeature:
+		switch (wValue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* no hub-wide feature/status flags */
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case ClearPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = fotg210_readl(fotg210, status_reg);
+		temp &= ~PORT_RWC_BITS;
+
+		/*
+		 * Even if OWNER is set, so the port is owned by the
+		 * companion controller, khubd needs to be able to clear
+		 * the port-change status bits (especially
+		 * USB_PORT_STAT_C_CONNECTION).
+		 */
+
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			fotg210_writel(fotg210, temp & ~PORT_PE, status_reg);
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+			fotg210_writel(fotg210, temp | PORT_PEC, status_reg);
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			if (temp & PORT_RESET)
+				goto error;
+			if (!(temp & PORT_SUSPEND))
+				break;
+			if ((temp & PORT_PE) == 0)
+				goto error;
+
+			/* resume signaling for 20 msec */
+			fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
+			fotg210->reset_done[wIndex] = jiffies
+					+ msecs_to_jiffies(20);
+			break;
+		case USB_PORT_FEAT_C_SUSPEND:
+			clear_bit(wIndex, &fotg210->port_c_suspend);
+			break;
+		case USB_PORT_FEAT_C_CONNECTION:
+			fotg210_writel(fotg210, temp | PORT_CSC, status_reg);
+			break;
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			fotg210_writel(fotg210, temp | OTGISR_OVC,
+				       &fotg210->regs->otgisr);
+			break;
+		case USB_PORT_FEAT_C_RESET:
+			/* GetPortStatus clears reset */
+			break;
+		default:
+			goto error;
+		}
+		fotg210_readl(fotg210, &fotg210->regs->command);
+		break;
+	case GetHubDescriptor:
+		fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *)
+			buf);
+		break;
+	case GetHubStatus:
+		/* no hub-wide feature/status flags */
+		memset(buf, 0, 4);
+		/*cpu_to_le32s ((u32 *) buf); */
+		break;
+	case GetPortStatus:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		status = 0;
+		temp = fotg210_readl(fotg210, status_reg);
+
+		/* wPortChange bits */
+		if (temp & PORT_CSC)
+			status |= USB_PORT_STAT_C_CONNECTION << 16;
+		if (temp & PORT_PEC)
+			status |= USB_PORT_STAT_C_ENABLE << 16;
+
+		temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr);
+		if (temp1 & OTGISR_OVC)
+			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+
+		/* whoever resumes must GetPortStatus to complete it!! */
+		if (temp & PORT_RESUME) {
+
+			/* Remote Wakeup received? */
+			if (!fotg210->reset_done[wIndex]) {
+				/* resume signaling for 20 msec */
+				fotg210->reset_done[wIndex] = jiffies
+						+ msecs_to_jiffies(20);
+				/* check the port again */
+				mod_timer(&fotg210_to_hcd(fotg210)->rh_timer,
+						fotg210->reset_done[wIndex]);
+			}
+
+			/* resume completed? */
+			else if (time_after_eq(jiffies,
+					fotg210->reset_done[wIndex])) {
+				clear_bit(wIndex, &fotg210->suspended_ports);
+				set_bit(wIndex, &fotg210->port_c_suspend);
+				fotg210->reset_done[wIndex] = 0;
+
+				/* stop resume signaling */
+				temp = fotg210_readl(fotg210, status_reg);
+				fotg210_writel(fotg210,
+					temp & ~(PORT_RWC_BITS | PORT_RESUME),
+					status_reg);
+				clear_bit(wIndex, &fotg210->resuming_ports);
+				retval = handshake(fotg210, status_reg,
+					   PORT_RESUME, 0, 2000 /* 2msec */);
+				if (retval != 0) {
+					fotg210_err(fotg210,
+						"port %d resume error %d\n",
+						wIndex + 1, retval);
+					goto error;
+				}
+				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+			}
+		}
+
+		/* whoever resets must GetPortStatus to complete it!! */
+		if ((temp & PORT_RESET)
+				&& time_after_eq(jiffies,
+					fotg210->reset_done[wIndex])) {
+			status |= USB_PORT_STAT_C_RESET << 16;
+			fotg210->reset_done[wIndex] = 0;
+			clear_bit(wIndex, &fotg210->resuming_ports);
+
+			/* force reset to complete */
+			fotg210_writel(fotg210,
+				       temp & ~(PORT_RWC_BITS | PORT_RESET),
+				       status_reg);
+			/* REVISIT:  some hardware needs 550+ usec to clear
+			 * this bit; seems too long to spin routinely...
+			 */
+			retval = handshake(fotg210, status_reg,
+					PORT_RESET, 0, 1000);
+			if (retval != 0) {
+				fotg210_err(fotg210, "port %d reset error %d\n",
+					wIndex + 1, retval);
+				goto error;
+			}
+
+			/* see what we found out */
+			temp = check_reset_complete(fotg210, wIndex, status_reg,
+					fotg210_readl(fotg210, status_reg));
+		}
+
+		if (!(temp & (PORT_RESUME|PORT_RESET))) {
+			fotg210->reset_done[wIndex] = 0;
+			clear_bit(wIndex, &fotg210->resuming_ports);
+		}
+
+		/* transfer dedicated ports to the companion hc */
+		if ((temp & PORT_CONNECT) &&
+				test_bit(wIndex, &fotg210->companion_ports)) {
+			temp &= ~PORT_RWC_BITS;
+			fotg210_writel(fotg210, temp, status_reg);
+			fotg210_dbg(fotg210, "port %d --> companion\n",
+				    wIndex + 1);
+			temp = fotg210_readl(fotg210, status_reg);
+		}
+
+		/*
+		 * Even if OWNER is set, there's no harm letting khubd
+		 * see the wPortStatus values (they should all be 0 except
+		 * for PORT_POWER anyway).
+		 */
+
+		if (temp & PORT_CONNECT) {
+			status |= USB_PORT_STAT_CONNECTION;
+			status |= fotg210_port_speed(fotg210, temp);
+		}
+		if (temp & PORT_PE)
+			status |= USB_PORT_STAT_ENABLE;
+
+		/* maybe the port was unsuspended without our knowledge */
+		if (temp & (PORT_SUSPEND|PORT_RESUME)) {
+			status |= USB_PORT_STAT_SUSPEND;
+		} else if (test_bit(wIndex, &fotg210->suspended_ports)) {
+			clear_bit(wIndex, &fotg210->suspended_ports);
+			clear_bit(wIndex, &fotg210->resuming_ports);
+			fotg210->reset_done[wIndex] = 0;
+			if (temp & PORT_PE)
+				set_bit(wIndex, &fotg210->port_c_suspend);
+		}
+
+		temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr);
+		if (temp1 & OTGISR_OVC)
+			status |= USB_PORT_STAT_OVERCURRENT;
+		if (temp & PORT_RESET)
+			status |= USB_PORT_STAT_RESET;
+		if (test_bit(wIndex, &fotg210->port_c_suspend))
+			status |= USB_PORT_STAT_C_SUSPEND << 16;
+
+#ifndef	VERBOSE_DEBUG
+	if (status & ~0xffff)	/* only if wPortChange is interesting */
+#endif
+		dbg_port(fotg210, "GetStatus", wIndex + 1, temp);
+		put_unaligned_le32(status, buf);
+		break;
+	case SetHubFeature:
+		switch (wValue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* no hub-wide feature/status flags */
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case SetPortFeature:
+		selector = wIndex >> 8;
+		wIndex &= 0xff;
+
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = fotg210_readl(fotg210, status_reg);
+		temp &= ~PORT_RWC_BITS;
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			if ((temp & PORT_PE) == 0
+					|| (temp & PORT_RESET) != 0)
+				goto error;
+
+			/* After above check the port must be connected.
+			 * Set appropriate bit thus could put phy into low power
+			 * mode if we have hostpc feature
+			 */
+			fotg210_writel(fotg210, temp | PORT_SUSPEND,
+				       status_reg);
+			set_bit(wIndex, &fotg210->suspended_ports);
+			break;
+		case USB_PORT_FEAT_RESET:
+			if (temp & PORT_RESUME)
+				goto error;
+			/* line status bits may report this as low speed,
+			 * which can be fine if this root hub has a
+			 * transaction translator built in.
+			 */
+			fotg210_vdbg(fotg210, "port %d reset\n", wIndex + 1);
+			temp |= PORT_RESET;
+			temp &= ~PORT_PE;
+
+			/*
+			 * caller must wait, then call GetPortStatus
+			 * usb 2.0 spec says 50 ms resets on root
+			 */
+			fotg210->reset_done[wIndex] = jiffies
+					+ msecs_to_jiffies(50);
+			fotg210_writel(fotg210, temp, status_reg);
+			break;
+
+		/* For downstream facing ports (these):  one hub port is put
+		 * into test mode according to USB2 11.24.2.13, then the hub
+		 * must be reset (which for root hub now means rmmod+modprobe,
+		 * or else system reboot).  See EHCI 2.3.9 and 4.14 for info
+		 * about the EHCI-specific stuff.
+		 */
+		case USB_PORT_FEAT_TEST:
+			if (!selector || selector > 5)
+				goto error;
+			spin_unlock_irqrestore(&fotg210->lock, flags);
+			fotg210_quiesce(fotg210);
+			spin_lock_irqsave(&fotg210->lock, flags);
+
+			/* Put all enabled ports into suspend */
+			temp = fotg210_readl(fotg210, status_reg) &
+				~PORT_RWC_BITS;
+			if (temp & PORT_PE)
+				fotg210_writel(fotg210, temp | PORT_SUSPEND,
+						status_reg);
+
+			spin_unlock_irqrestore(&fotg210->lock, flags);
+			fotg210_halt(fotg210);
+			spin_lock_irqsave(&fotg210->lock, flags);
+
+			temp = fotg210_readl(fotg210, status_reg);
+			temp |= selector << 16;
+			fotg210_writel(fotg210, temp, status_reg);
+			break;
+
+		default:
+			goto error;
+		}
+		fotg210_readl(fotg210, &fotg210->regs->command);
+		break;
+
+	default:
+error:
+		/* "stall" on error */
+		retval = -EPIPE;
+	}
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	return retval;
+}
+
+static void __maybe_unused fotg210_relinquish_port(struct usb_hcd *hcd,
+		int portnum)
+{
+	return;
+}
+
+static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd,
+		int portnum)
+{
+	return 0;
+}
+/*-------------------------------------------------------------------------*/
+/*
+ * There's basically three types of memory:
+ *	- data used only by the HCD ... kmalloc is fine
+ *	- async and periodic schedules, shared by HC and HCD ... these
+ *	  need to use dma_pool or dma_alloc_coherent
+ *	- driver buffers, read/written by HC ... single shot DMA mapped
+ *
+ * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
+ * No memory seen by this driver is pageable.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* Allocate the key transfer structures from the previously allocated pool */
+
+static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210,
+				    struct fotg210_qtd *qtd, dma_addr_t dma)
+{
+	memset(qtd, 0, sizeof(*qtd));
+	qtd->qtd_dma = dma;
+	qtd->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT);
+	qtd->hw_next = FOTG210_LIST_END(fotg210);
+	qtd->hw_alt_next = FOTG210_LIST_END(fotg210);
+	INIT_LIST_HEAD(&qtd->qtd_list);
+}
+
+static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210,
+					     gfp_t flags)
+{
+	struct fotg210_qtd		*qtd;
+	dma_addr_t		dma;
+
+	qtd = dma_pool_alloc(fotg210->qtd_pool, flags, &dma);
+	if (qtd != NULL)
+		fotg210_qtd_init(fotg210, qtd, dma);
+
+	return qtd;
+}
+
+static inline void fotg210_qtd_free(struct fotg210_hcd *fotg210,
+				    struct fotg210_qtd *qtd)
+{
+	dma_pool_free(fotg210->qtd_pool, qtd, qtd->qtd_dma);
+}
+
+
+static void qh_destroy(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	/* clean qtds first, and know this is not linked */
+	if (!list_empty(&qh->qtd_list) || qh->qh_next.ptr) {
+		fotg210_dbg(fotg210, "unused qh not empty!\n");
+		BUG();
+	}
+	if (qh->dummy)
+		fotg210_qtd_free(fotg210, qh->dummy);
+	dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma);
+	kfree(qh);
+}
+
+static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210,
+					   gfp_t flags)
+{
+	struct fotg210_qh		*qh;
+	dma_addr_t		dma;
+
+	qh = kzalloc(sizeof(*qh), GFP_ATOMIC);
+	if (!qh)
+		goto done;
+	qh->hw = (struct fotg210_qh_hw *)
+		dma_pool_alloc(fotg210->qh_pool, flags, &dma);
+	if (!qh->hw)
+		goto fail;
+	memset(qh->hw, 0, sizeof(*qh->hw));
+	qh->qh_dma = dma;
+	INIT_LIST_HEAD(&qh->qtd_list);
+
+	/* dummy td enables safe urb queuing */
+	qh->dummy = fotg210_qtd_alloc(fotg210, flags);
+	if (qh->dummy == NULL) {
+		fotg210_dbg(fotg210, "no dummy td\n");
+		goto fail1;
+	}
+done:
+	return qh;
+fail1:
+	dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma);
+fail:
+	kfree(qh);
+	return NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* The queue heads and transfer descriptors are managed from pools tied
+ * to each of the "per device" structures.
+ * This is the initialisation and cleanup code.
+ */
+
+static void fotg210_mem_cleanup(struct fotg210_hcd *fotg210)
+{
+	if (fotg210->async)
+		qh_destroy(fotg210, fotg210->async);
+	fotg210->async = NULL;
+
+	if (fotg210->dummy)
+		qh_destroy(fotg210, fotg210->dummy);
+	fotg210->dummy = NULL;
+
+	/* DMA consistent memory and pools */
+	if (fotg210->qtd_pool)
+		dma_pool_destroy(fotg210->qtd_pool);
+	fotg210->qtd_pool = NULL;
+
+	if (fotg210->qh_pool) {
+		dma_pool_destroy(fotg210->qh_pool);
+		fotg210->qh_pool = NULL;
+	}
+
+	if (fotg210->itd_pool)
+		dma_pool_destroy(fotg210->itd_pool);
+	fotg210->itd_pool = NULL;
+
+	if (fotg210->periodic)
+		dma_free_coherent(fotg210_to_hcd(fotg210)->self.controller,
+			fotg210->periodic_size * sizeof(u32),
+			fotg210->periodic, fotg210->periodic_dma);
+	fotg210->periodic = NULL;
+
+	/* shadow periodic table */
+	kfree(fotg210->pshadow);
+	fotg210->pshadow = NULL;
+}
+
+/* remember to add cleanup code (above) if you add anything here */
+static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags)
+{
+	int i;
+
+	/* QTDs for control/bulk/intr transfers */
+	fotg210->qtd_pool = dma_pool_create("fotg210_qtd",
+			fotg210_to_hcd(fotg210)->self.controller,
+			sizeof(struct fotg210_qtd),
+			32 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */);
+	if (!fotg210->qtd_pool)
+		goto fail;
+
+	/* QHs for control/bulk/intr transfers */
+	fotg210->qh_pool = dma_pool_create("fotg210_qh",
+			fotg210_to_hcd(fotg210)->self.controller,
+			sizeof(struct fotg210_qh_hw),
+			32 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */);
+	if (!fotg210->qh_pool)
+		goto fail;
+
+	fotg210->async = fotg210_qh_alloc(fotg210, flags);
+	if (!fotg210->async)
+		goto fail;
+
+	/* ITD for high speed ISO transfers */
+	fotg210->itd_pool = dma_pool_create("fotg210_itd",
+			fotg210_to_hcd(fotg210)->self.controller,
+			sizeof(struct fotg210_itd),
+			64 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */);
+	if (!fotg210->itd_pool)
+		goto fail;
+
+	/* Hardware periodic table */
+	fotg210->periodic = (__le32 *)
+		dma_alloc_coherent(fotg210_to_hcd(fotg210)->self.controller,
+			fotg210->periodic_size * sizeof(__le32),
+			&fotg210->periodic_dma, 0);
+	if (fotg210->periodic == NULL)
+		goto fail;
+
+	for (i = 0; i < fotg210->periodic_size; i++)
+		fotg210->periodic[i] = FOTG210_LIST_END(fotg210);
+
+	/* software shadow of hardware table */
+	fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *),
+				   flags);
+	if (fotg210->pshadow != NULL)
+		return 0;
+
+fail:
+	fotg210_dbg(fotg210, "couldn't init memory\n");
+	fotg210_mem_cleanup(fotg210);
+	return -ENOMEM;
+}
+/*-------------------------------------------------------------------------*/
+/*
+ * EHCI hardware queue manipulation ... the core.  QH/QTD manipulation.
+ *
+ * Control, bulk, and interrupt traffic all use "qh" lists.  They list "qtd"
+ * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
+ * buffers needed for the larger number).  We use one QH per endpoint, queue
+ * multiple urbs (all three types) per endpoint.  URBs may need several qtds.
+ *
+ * ISO traffic uses "ISO TD" (itd) records, and (along with
+ * interrupts) needs careful scheduling.  Performance improvements can be
+ * an ongoing challenge.  That's in "ehci-sched.c".
+ *
+ * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
+ * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
+ * (b) special fields in qh entries or (c) split iso entries.  TTs will
+ * buffer low/full speed data so the host collects it at high speed.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* fill a qtd, returning how much of the buffer we were able to queue up */
+
+static int
+qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf,
+		  size_t len, int token, int maxpacket)
+{
+	int	i, count;
+	u64	addr = buf;
+
+	/* one buffer entry per 4K ... first might be short or unaligned */
+	qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr);
+	qtd->hw_buf_hi[0] = cpu_to_hc32(fotg210, (u32)(addr >> 32));
+	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
+	if (likely(len < count))		/* ... iff needed */
+		count = len;
+	else {
+		buf +=  0x1000;
+		buf &= ~0x0fff;
+
+		/* per-qtd limit: from 16K to 20K (best alignment) */
+		for (i = 1; count < len && i < 5; i++) {
+			addr = buf;
+			qtd->hw_buf[i] = cpu_to_hc32(fotg210, (u32)addr);
+			qtd->hw_buf_hi[i] = cpu_to_hc32(fotg210,
+					(u32)(addr >> 32));
+			buf += 0x1000;
+			if ((count + 0x1000) < len)
+				count += 0x1000;
+			else
+				count = len;
+		}
+
+		/* short packets may only terminate transfers */
+		if (count != len)
+			count -= (count % maxpacket);
+	}
+	qtd->hw_token = cpu_to_hc32(fotg210, (count << 16) | token);
+	qtd->length = count;
+
+	return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void
+qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
+	  struct fotg210_qtd *qtd)
+{
+	struct fotg210_qh_hw *hw = qh->hw;
+
+	/* writes to an active overlay are unsafe */
+	BUG_ON(qh->qh_state != QH_STATE_IDLE);
+
+	hw->hw_qtd_next = QTD_NEXT(fotg210, qtd->qtd_dma);
+	hw->hw_alt_next = FOTG210_LIST_END(fotg210);
+
+	/* Except for control endpoints, we make hardware maintain data
+	 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
+	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
+	 * ever clear it.
+	 */
+	if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) {
+		unsigned	is_out, epnum;
+
+		is_out = qh->is_out;
+		epnum = (hc32_to_cpup(fotg210, &hw->hw_info1) >> 8) & 0x0f;
+		if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) {
+			hw->hw_token &= ~cpu_to_hc32(fotg210, QTD_TOGGLE);
+			usb_settoggle(qh->dev, epnum, is_out, 1);
+		}
+	}
+
+	hw->hw_token &= cpu_to_hc32(fotg210, QTD_TOGGLE | QTD_STS_PING);
+}
+
+/* if it weren't for a common silicon quirk (writing the dummy into the qh
+ * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault
+ * recovery (including urb dequeue) would need software changes to a QH...
+ */
+static void
+qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	struct fotg210_qtd *qtd;
+
+	if (list_empty(&qh->qtd_list))
+		qtd = qh->dummy;
+	else {
+		qtd = list_entry(qh->qtd_list.next,
+				struct fotg210_qtd, qtd_list);
+		/*
+		 * first qtd may already be partially processed.
+		 * If we come here during unlink, the QH overlay region
+		 * might have reference to the just unlinked qtd. The
+		 * qtd is updated in qh_completions(). Update the QH
+		 * overlay here.
+		 */
+		if (cpu_to_hc32(fotg210, qtd->qtd_dma) == qh->hw->hw_current) {
+			qh->hw->hw_qtd_next = qtd->hw_next;
+			qtd = NULL;
+		}
+	}
+
+	if (qtd)
+		qh_update(fotg210, qh, qtd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
+
+static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd,
+		struct usb_host_endpoint *ep)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	struct fotg210_qh		*qh = ep->hcpriv;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+	qh->clearing_tt = 0;
+	if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
+			&& fotg210->rh_state == FOTG210_RH_RUNNING)
+		qh_link_async(fotg210, qh);
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+}
+
+static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210,
+				    struct fotg210_qh *qh,
+				    struct urb *urb, u32 token)
+{
+
+	/* If an async split transaction gets an error or is unlinked,
+	 * the TT buffer may be left in an indeterminate state.  We
+	 * have to clear the TT buffer.
+	 *
+	 * Note: this routine is never called for Isochronous transfers.
+	 */
+	if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
+#ifdef DEBUG
+		struct usb_device *tt = urb->dev->tt->hub;
+		dev_dbg(&tt->dev,
+			"clear tt buffer port %d, a%d ep%d t%08x\n",
+			urb->dev->ttport, urb->dev->devnum,
+			usb_pipeendpoint(urb->pipe), token);
+#endif /* DEBUG */
+		if (urb->dev->tt->hub !=
+		    fotg210_to_hcd(fotg210)->self.root_hub) {
+			if (usb_hub_clear_tt_buffer(urb) == 0)
+				qh->clearing_tt = 1;
+		}
+	}
+}
+
+static int qtd_copy_status(
+	struct fotg210_hcd *fotg210,
+	struct urb *urb,
+	size_t length,
+	u32 token
+)
+{
+	int	status = -EINPROGRESS;
+
+	/* count IN/OUT bytes, not SETUP (even short packets) */
+	if (likely(QTD_PID(token) != 2))
+		urb->actual_length += length - QTD_LENGTH(token);
+
+	/* don't modify error codes */
+	if (unlikely(urb->unlinked))
+		return status;
+
+	/* force cleanup after short read; not always an error */
+	if (unlikely(IS_SHORT_READ(token)))
+		status = -EREMOTEIO;
+
+	/* serious "can't proceed" faults reported by the hardware */
+	if (token & QTD_STS_HALT) {
+		if (token & QTD_STS_BABBLE) {
+			/* FIXME "must" disable babbling device's port too */
+			status = -EOVERFLOW;
+		/* CERR nonzero + halt --> stall */
+		} else if (QTD_CERR(token)) {
+			status = -EPIPE;
+
+		/* In theory, more than one of the following bits can be set
+		 * since they are sticky and the transaction is retried.
+		 * Which to test first is rather arbitrary.
+		 */
+		} else if (token & QTD_STS_MMF) {
+			/* fs/ls interrupt xfer missed the complete-split */
+			status = -EPROTO;
+		} else if (token & QTD_STS_DBE) {
+			status = (QTD_PID(token) == 1) /* IN ? */
+				? -ENOSR  /* hc couldn't read data */
+				: -ECOMM; /* hc couldn't write data */
+		} else if (token & QTD_STS_XACT) {
+			/* timeout, bad CRC, wrong PID, etc */
+			fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n",
+				urb->dev->devpath,
+				usb_pipeendpoint(urb->pipe),
+				usb_pipein(urb->pipe) ? "in" : "out");
+			status = -EPROTO;
+		} else {	/* unknown */
+			status = -EPROTO;
+		}
+
+		fotg210_vdbg(fotg210,
+			"dev%d ep%d%s qtd token %08x --> status %d\n",
+			usb_pipedevice(urb->pipe),
+			usb_pipeendpoint(urb->pipe),
+			usb_pipein(urb->pipe) ? "in" : "out",
+			token, status);
+	}
+
+	return status;
+}
+
+static void
+fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb, int status)
+__releases(fotg210->lock)
+__acquires(fotg210->lock)
+{
+	if (likely(urb->hcpriv != NULL)) {
+		struct fotg210_qh	*qh = (struct fotg210_qh *) urb->hcpriv;
+
+		/* S-mask in a QH means it's an interrupt urb */
+		if ((qh->hw->hw_info2 & cpu_to_hc32(fotg210, QH_SMASK)) != 0) {
+
+			/* ... update hc-wide periodic stats (for usbfs) */
+			fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs--;
+		}
+	}
+
+	if (unlikely(urb->unlinked)) {
+		COUNT(fotg210->stats.unlink);
+	} else {
+		/* report non-error and short read status as zero */
+		if (status == -EINPROGRESS || status == -EREMOTEIO)
+			status = 0;
+		COUNT(fotg210->stats.complete);
+	}
+
+#ifdef FOTG210_URB_TRACE
+	fotg210_dbg(fotg210,
+		"%s %s urb %p ep%d%s status %d len %d/%d\n",
+		__func__, urb->dev->devpath, urb,
+		usb_pipeendpoint(urb->pipe),
+		usb_pipein(urb->pipe) ? "in" : "out",
+		status,
+		urb->actual_length, urb->transfer_buffer_length);
+#endif
+
+	/* complete() can reenter this HCD */
+	usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
+	spin_unlock(&fotg210->lock);
+	usb_hcd_giveback_urb(fotg210_to_hcd(fotg210), urb, status);
+	spin_lock(&fotg210->lock);
+}
+
+static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
+
+/*
+ * Process and free completed qtds for a qh, returning URBs to drivers.
+ * Chases up to qh->hw_current.  Returns number of completions called,
+ * indicating how much "real" work we did.
+ */
+static unsigned
+qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	struct fotg210_qtd		*last, *end = qh->dummy;
+	struct list_head	*entry, *tmp;
+	int			last_status;
+	int			stopped;
+	unsigned		count = 0;
+	u8			state;
+	struct fotg210_qh_hw	*hw = qh->hw;
+
+	if (unlikely(list_empty(&qh->qtd_list)))
+		return count;
+
+	/* completions (or tasks on other cpus) must never clobber HALT
+	 * till we've gone through and cleaned everything up, even when
+	 * they add urbs to this qh's queue or mark them for unlinking.
+	 *
+	 * NOTE:  unlinking expects to be done in queue order.
+	 *
+	 * It's a bug for qh->qh_state to be anything other than
+	 * QH_STATE_IDLE, unless our caller is scan_async() or
+	 * scan_intr().
+	 */
+	state = qh->qh_state;
+	qh->qh_state = QH_STATE_COMPLETING;
+	stopped = (state == QH_STATE_IDLE);
+
+ rescan:
+	last = NULL;
+	last_status = -EINPROGRESS;
+	qh->needs_rescan = 0;
+
+	/* remove de-activated QTDs from front of queue.
+	 * after faults (including short reads), cleanup this urb
+	 * then let the queue advance.
+	 * if queue is stopped, handles unlinks.
+	 */
+	list_for_each_safe(entry, tmp, &qh->qtd_list) {
+		struct fotg210_qtd	*qtd;
+		struct urb	*urb;
+		u32		token = 0;
+
+		qtd = list_entry(entry, struct fotg210_qtd, qtd_list);
+		urb = qtd->urb;
+
+		/* clean up any state from previous QTD ...*/
+		if (last) {
+			if (likely(last->urb != urb)) {
+				fotg210_urb_done(fotg210, last->urb,
+						 last_status);
+				count++;
+				last_status = -EINPROGRESS;
+			}
+			fotg210_qtd_free(fotg210, last);
+			last = NULL;
+		}
+
+		/* ignore urbs submitted during completions we reported */
+		if (qtd == end)
+			break;
+
+		/* hardware copies qtd out of qh overlay */
+		rmb();
+		token = hc32_to_cpu(fotg210, qtd->hw_token);
+
+		/* always clean up qtds the hc de-activated */
+ retry_xacterr:
+		if ((token & QTD_STS_ACTIVE) == 0) {
+
+			/* Report Data Buffer Error: non-fatal but useful */
+			if (token & QTD_STS_DBE)
+				fotg210_dbg(fotg210,
+					"detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+					urb,
+					usb_endpoint_num(&urb->ep->desc),
+					usb_endpoint_dir_in(&urb->ep->desc)
+						? "in" : "out",
+					urb->transfer_buffer_length,
+					qtd,
+					qh);
+
+			/* 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 < QH_XACTERR_MAX &&
+					!urb->unlinked) {
+					fotg210_dbg(fotg210,
+	"detected XactErr len %zu/%zu retry %d\n",
+	qtd->length - QTD_LENGTH(token), qtd->length, 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 |
+						 (FOTG210_TUNE_CERR << 10);
+					qtd->hw_token = cpu_to_hc32(fotg210,
+							token);
+					wmb();
+					hw->hw_token = cpu_to_hc32(fotg210,
+							token);
+					goto retry_xacterr;
+				}
+				stopped = 1;
+
+			/* magic dummy for some short reads; qh won't advance.
+			 * that silicon quirk can kick in with this dummy too.
+			 *
+			 * other short reads won't stop the queue, including
+			 * control transfers (status stage handles that) or
+			 * most other single-qtd reads ... the queue stops if
+			 * URB_SHORT_NOT_OK was set so the driver submitting
+			 * the urbs could clean it up.
+			 */
+			} else if (IS_SHORT_READ(token)
+					&& !(qtd->hw_alt_next
+						& FOTG210_LIST_END(fotg210))) {
+				stopped = 1;
+			}
+
+		/* stop scanning when we reach qtds the hc is using */
+		} else if (likely(!stopped
+				&& fotg210->rh_state >= FOTG210_RH_RUNNING)) {
+			break;
+
+		/* scan the whole queue for unlinks whenever it stops */
+		} else {
+			stopped = 1;
+
+			/* cancel everything if we halt, suspend, etc */
+			if (fotg210->rh_state < FOTG210_RH_RUNNING)
+				last_status = -ESHUTDOWN;
+
+			/* this qtd is active; skip it unless a previous qtd
+			 * for its urb faulted, or its urb was canceled.
+			 */
+			else if (last_status == -EINPROGRESS && !urb->unlinked)
+				continue;
+
+			/* qh unlinked; token in overlay may be most current */
+			if (state == QH_STATE_IDLE
+					&& cpu_to_hc32(fotg210, qtd->qtd_dma)
+						== hw->hw_current) {
+				token = hc32_to_cpu(fotg210, hw->hw_token);
+
+				/* An unlink may leave an incomplete
+				 * async transaction in the TT buffer.
+				 * We have to clear it.
+				 */
+				fotg210_clear_tt_buffer(fotg210, qh, urb,
+							token);
+			}
+		}
+
+		/* unless we already know the urb's status, collect qtd status
+		 * and update count of bytes transferred.  in common short read
+		 * cases with only one data qtd (including control transfers),
+		 * queue processing won't halt.  but with two or more qtds (for
+		 * example, with a 32 KB transfer), when the first qtd gets a
+		 * short read the second must be removed by hand.
+		 */
+		if (last_status == -EINPROGRESS) {
+			last_status = qtd_copy_status(fotg210, urb,
+					qtd->length, token);
+			if (last_status == -EREMOTEIO
+					&& (qtd->hw_alt_next
+						& FOTG210_LIST_END(fotg210)))
+				last_status = -EINPROGRESS;
+
+			/* As part of low/full-speed endpoint-halt processing
+			 * we must clear the TT buffer (11.17.5).
+			 */
+			if (unlikely(last_status != -EINPROGRESS &&
+					last_status != -EREMOTEIO)) {
+				/* The TT's in some hubs malfunction when they
+				 * receive this request following a STALL (they
+				 * stop sending isochronous packets).  Since a
+				 * STALL can't leave the TT buffer in a busy
+				 * state (if you believe Figures 11-48 - 11-51
+				 * in the USB 2.0 spec), we won't clear the TT
+				 * buffer in this case.  Strictly speaking this
+				 * is a violation of the spec.
+				 */
+				if (last_status != -EPIPE)
+					fotg210_clear_tt_buffer(fotg210, qh,
+								urb, token);
+			}
+		}
+
+		/* if we're removing something not at the queue head,
+		 * patch the hardware queue pointer.
+		 */
+		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+			last = list_entry(qtd->qtd_list.prev,
+					struct fotg210_qtd, qtd_list);
+			last->hw_next = qtd->hw_next;
+		}
+
+		/* remove qtd; it's recycled after possible urb completion */
+		list_del(&qtd->qtd_list);
+		last = qtd;
+
+		/* reinit the xacterr counter for the next qtd */
+		qh->xacterrs = 0;
+	}
+
+	/* last urb's completion might still need calling */
+	if (likely(last != NULL)) {
+		fotg210_urb_done(fotg210, last->urb, last_status);
+		count++;
+		fotg210_qtd_free(fotg210, last);
+	}
+
+	/* Do we need to rescan for URBs dequeued during a giveback? */
+	if (unlikely(qh->needs_rescan)) {
+		/* If the QH is already unlinked, do the rescan now. */
+		if (state == QH_STATE_IDLE)
+			goto rescan;
+
+		/* Otherwise we have to wait until the QH is fully unlinked.
+		 * Our caller will start an unlink if qh->needs_rescan is
+		 * set.  But if an unlink has already started, nothing needs
+		 * to be done.
+		 */
+		if (state != QH_STATE_LINKED)
+			qh->needs_rescan = 0;
+	}
+
+	/* restore original state; caller must unlink or relink */
+	qh->qh_state = state;
+
+	/* be sure the hardware's done with the qh before refreshing
+	 * it after fault cleanup, or recovering from silicon wrongly
+	 * overlaying the dummy qtd (which reduces DMA chatter).
+	 */
+	if (stopped != 0 || hw->hw_qtd_next == FOTG210_LIST_END(fotg210)) {
+		switch (state) {
+		case QH_STATE_IDLE:
+			qh_refresh(fotg210, qh);
+			break;
+		case QH_STATE_LINKED:
+			/* We won't refresh a QH that's linked (after the HC
+			 * stopped the queue).  That avoids a race:
+			 *  - HC reads first part of QH;
+			 *  - CPU updates that first part and the token;
+			 *  - HC reads rest of that QH, including token
+			 * Result:  HC gets an inconsistent image, and then
+			 * DMAs to/from the wrong memory (corrupting it).
+			 *
+			 * That should be rare for interrupt transfers,
+			 * except maybe high bandwidth ...
+			 */
+
+			/* Tell the caller to start an unlink */
+			qh->needs_rescan = 1;
+			break;
+		/* otherwise, unlink already started */
+		}
+	}
+
+	return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+/* ... and packet size, for any kind of endpoint descriptor */
+#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
+
+/*
+ * reverse of qh_urb_transaction:  free a list of TDs.
+ * used for cleanup after errors, before HC sees an URB's TDs.
+ */
+static void qtd_list_free(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	struct list_head	*qtd_list
+) {
+	struct list_head	*entry, *temp;
+
+	list_for_each_safe(entry, temp, qtd_list) {
+		struct fotg210_qtd	*qtd;
+
+		qtd = list_entry(entry, struct fotg210_qtd, qtd_list);
+		list_del(&qtd->qtd_list);
+		fotg210_qtd_free(fotg210, qtd);
+	}
+}
+
+/*
+ * create a list of filled qtds for this URB; won't link into qh.
+ */
+static struct list_head *
+qh_urb_transaction(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	struct list_head	*head,
+	gfp_t			flags
+) {
+	struct fotg210_qtd		*qtd, *qtd_prev;
+	dma_addr_t		buf;
+	int			len, this_sg_len, maxpacket;
+	int			is_input;
+	u32			token;
+	int			i;
+	struct scatterlist	*sg;
+
+	/*
+	 * URBs map to sequences of QTDs:  one logical transaction
+	 */
+	qtd = fotg210_qtd_alloc(fotg210, flags);
+	if (unlikely(!qtd))
+		return NULL;
+	list_add_tail(&qtd->qtd_list, head);
+	qtd->urb = urb;
+
+	token = QTD_STS_ACTIVE;
+	token |= (FOTG210_TUNE_CERR << 10);
+	/* for split transactions, SplitXState initialized to zero */
+
+	len = urb->transfer_buffer_length;
+	is_input = usb_pipein(urb->pipe);
+	if (usb_pipecontrol(urb->pipe)) {
+		/* SETUP pid */
+		qtd_fill(fotg210, qtd, urb->setup_dma,
+				sizeof(struct usb_ctrlrequest),
+				token | (2 /* "setup" */ << 8), 8);
+
+		/* ... and always at least one more pid */
+		token ^= QTD_TOGGLE;
+		qtd_prev = qtd;
+		qtd = fotg210_qtd_alloc(fotg210, flags);
+		if (unlikely(!qtd))
+			goto cleanup;
+		qtd->urb = urb;
+		qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma);
+		list_add_tail(&qtd->qtd_list, head);
+
+		/* for zero length DATA stages, STATUS is always IN */
+		if (len == 0)
+			token |= (1 /* "in" */ << 8);
+	}
+
+	/*
+	 * data transfer stage:  buffer setup
+	 */
+	i = urb->num_mapped_sgs;
+	if (len > 0 && i > 0) {
+		sg = urb->sg;
+		buf = sg_dma_address(sg);
+
+		/* urb->transfer_buffer_length may be smaller than the
+		 * size of the scatterlist (or vice versa)
+		 */
+		this_sg_len = min_t(int, sg_dma_len(sg), len);
+	} else {
+		sg = NULL;
+		buf = urb->transfer_dma;
+		this_sg_len = len;
+	}
+
+	if (is_input)
+		token |= (1 /* "in" */ << 8);
+	/* else it's already initted to "out" pid (0 << 8) */
+
+	maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
+
+	/*
+	 * buffer gets wrapped in one or more qtds;
+	 * last one may be "short" (including zero len)
+	 * and may serve as a control status ack
+	 */
+	for (;;) {
+		int this_qtd_len;
+
+		this_qtd_len = qtd_fill(fotg210, qtd, buf, this_sg_len, token,
+				maxpacket);
+		this_sg_len -= this_qtd_len;
+		len -= this_qtd_len;
+		buf += this_qtd_len;
+
+		/*
+		 * short reads advance to a "magic" dummy instead of the next
+		 * qtd ... that forces the queue to stop, for manual cleanup.
+		 * (this will usually be overridden later.)
+		 */
+		if (is_input)
+			qtd->hw_alt_next = fotg210->async->hw->hw_alt_next;
+
+		/* qh makes control packets use qtd toggle; maybe switch it */
+		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
+			token ^= QTD_TOGGLE;
+
+		if (likely(this_sg_len <= 0)) {
+			if (--i <= 0 || len <= 0)
+				break;
+			sg = sg_next(sg);
+			buf = sg_dma_address(sg);
+			this_sg_len = min_t(int, sg_dma_len(sg), len);
+		}
+
+		qtd_prev = qtd;
+		qtd = fotg210_qtd_alloc(fotg210, flags);
+		if (unlikely(!qtd))
+			goto cleanup;
+		qtd->urb = urb;
+		qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma);
+		list_add_tail(&qtd->qtd_list, head);
+	}
+
+	/*
+	 * unless the caller requires manual cleanup after short reads,
+	 * have the alt_next mechanism keep the queue running after the
+	 * last data qtd (the only one, for control and most other cases).
+	 */
+	if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
+				|| usb_pipecontrol(urb->pipe)))
+		qtd->hw_alt_next = FOTG210_LIST_END(fotg210);
+
+	/*
+	 * control requests may need a terminating data "status" ack;
+	 * other OUT ones may need a terminating short packet
+	 * (zero length).
+	 */
+	if (likely(urb->transfer_buffer_length != 0)) {
+		int	one_more = 0;
+
+		if (usb_pipecontrol(urb->pipe)) {
+			one_more = 1;
+			token ^= 0x0100;	/* "in" <--> "out"  */
+			token |= QTD_TOGGLE;	/* force DATA1 */
+		} else if (usb_pipeout(urb->pipe)
+				&& (urb->transfer_flags & URB_ZERO_PACKET)
+				&& !(urb->transfer_buffer_length % maxpacket)) {
+			one_more = 1;
+		}
+		if (one_more) {
+			qtd_prev = qtd;
+			qtd = fotg210_qtd_alloc(fotg210, flags);
+			if (unlikely(!qtd))
+				goto cleanup;
+			qtd->urb = urb;
+			qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma);
+			list_add_tail(&qtd->qtd_list, head);
+
+			/* never any data in such packets */
+			qtd_fill(fotg210, qtd, 0, 0, token, 0);
+		}
+	}
+
+	/* by default, enable interrupt on urb completion */
+	if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT)))
+		qtd->hw_token |= cpu_to_hc32(fotg210, QTD_IOC);
+	return head;
+
+cleanup:
+	qtd_list_free(fotg210, urb, head);
+	return NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+/*
+ * Would be best to create all qh's from config descriptors,
+ * when each interface/altsetting is established.  Unlink
+ * any previous qh and cancel its urbs first; endpoints are
+ * implicitly reset then (data toggle too).
+ * That'd mean updating how usbcore talks to HCDs. (2.7?)
+*/
+
+
+/*
+ * Each QH holds a qtd list; a QH is used for everything except iso.
+ *
+ * For interrupt urbs, the scheduler must set the microframe scheduling
+ * mask(s) each time the QH gets scheduled.  For highspeed, that's
+ * just one microframe in the s-mask.  For split interrupt transactions
+ * there are additional complications: c-mask, maybe FSTNs.
+ */
+static struct fotg210_qh *
+qh_make(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	gfp_t			flags
+) {
+	struct fotg210_qh		*qh = fotg210_qh_alloc(fotg210, flags);
+	u32			info1 = 0, info2 = 0;
+	int			is_input, type;
+	int			maxp = 0;
+	struct usb_tt		*tt = urb->dev->tt;
+	struct fotg210_qh_hw	*hw;
+
+	if (!qh)
+		return qh;
+
+	/*
+	 * init endpoint/device data for this QH
+	 */
+	info1 |= usb_pipeendpoint(urb->pipe) << 8;
+	info1 |= usb_pipedevice(urb->pipe) << 0;
+
+	is_input = usb_pipein(urb->pipe);
+	type = usb_pipetype(urb->pipe);
+	maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input);
+
+	/* 1024 byte maxpacket is a hardware ceiling.  High bandwidth
+	 * acts like up to 3KB, but is built from smaller packets.
+	 */
+	if (max_packet(maxp) > 1024) {
+		fotg210_dbg(fotg210, "bogus qh maxpacket %d\n",
+			    max_packet(maxp));
+		goto done;
+	}
+
+	/* Compute interrupt scheduling parameters just once, and save.
+	 * - allowing for high bandwidth, how many nsec/uframe are used?
+	 * - split transactions need a second CSPLIT uframe; same question
+	 * - splits also need a schedule gap (for full/low speed I/O)
+	 * - qh has a polling interval
+	 *
+	 * For control/bulk requests, the HC or TT handles these.
+	 */
+	if (type == PIPE_INTERRUPT) {
+		qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+				is_input, 0,
+				hb_mult(maxp) * max_packet(maxp)));
+		qh->start = NO_FRAME;
+
+		if (urb->dev->speed == USB_SPEED_HIGH) {
+			qh->c_usecs = 0;
+			qh->gap_uf = 0;
+
+			qh->period = urb->interval >> 3;
+			if (qh->period == 0 && urb->interval != 1) {
+				/* NOTE interval 2 or 4 uframes could work.
+				 * But interval 1 scheduling is simpler, and
+				 * includes high bandwidth.
+				 */
+				urb->interval = 1;
+			} else if (qh->period > fotg210->periodic_size) {
+				qh->period = fotg210->periodic_size;
+				urb->interval = qh->period << 3;
+			}
+		} else {
+			int		think_time;
+
+			/* gap is f(FS/LS transfer times) */
+			qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed,
+					is_input, 0, maxp) / (125 * 1000);
+
+			/* FIXME this just approximates SPLIT/CSPLIT times */
+			if (is_input) {		/* SPLIT, gap, CSPLIT+DATA */
+				qh->c_usecs = qh->usecs + HS_USECS(0);
+				qh->usecs = HS_USECS(1);
+			} else {		/* SPLIT+DATA, gap, CSPLIT */
+				qh->usecs += HS_USECS(1);
+				qh->c_usecs = HS_USECS(0);
+			}
+
+			think_time = tt ? tt->think_time : 0;
+			qh->tt_usecs = NS_TO_US(think_time +
+					usb_calc_bus_time(urb->dev->speed,
+					is_input, 0, max_packet(maxp)));
+			qh->period = urb->interval;
+			if (qh->period > fotg210->periodic_size) {
+				qh->period = fotg210->periodic_size;
+				urb->interval = qh->period;
+			}
+		}
+	}
+
+	/* support for tt scheduling, and access to toggles */
+	qh->dev = urb->dev;
+
+	/* using TT? */
+	switch (urb->dev->speed) {
+	case USB_SPEED_LOW:
+		info1 |= QH_LOW_SPEED;
+		/* FALL THROUGH */
+
+	case USB_SPEED_FULL:
+		/* EPS 0 means "full" */
+		if (type != PIPE_INTERRUPT)
+			info1 |= (FOTG210_TUNE_RL_TT << 28);
+		if (type == PIPE_CONTROL) {
+			info1 |= QH_CONTROL_EP;		/* for TT */
+			info1 |= QH_TOGGLE_CTL;		/* toggle from qtd */
+		}
+		info1 |= maxp << 16;
+
+		info2 |= (FOTG210_TUNE_MULT_TT << 30);
+
+		/* Some Freescale processors have an erratum in which the
+		 * port number in the queue head was 0..N-1 instead of 1..N.
+		 */
+		if (fotg210_has_fsl_portno_bug(fotg210))
+			info2 |= (urb->dev->ttport-1) << 23;
+		else
+			info2 |= urb->dev->ttport << 23;
+
+		/* set the address of the TT; for TDI's integrated
+		 * root hub tt, leave it zeroed.
+		 */
+		if (tt && tt->hub != fotg210_to_hcd(fotg210)->self.root_hub)
+			info2 |= tt->hub->devnum << 16;
+
+		/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */
+
+		break;
+
+	case USB_SPEED_HIGH:		/* no TT involved */
+		info1 |= QH_HIGH_SPEED;
+		if (type == PIPE_CONTROL) {
+			info1 |= (FOTG210_TUNE_RL_HS << 28);
+			info1 |= 64 << 16;	/* usb2 fixed maxpacket */
+			info1 |= QH_TOGGLE_CTL;	/* toggle from qtd */
+			info2 |= (FOTG210_TUNE_MULT_HS << 30);
+		} else if (type == PIPE_BULK) {
+			info1 |= (FOTG210_TUNE_RL_HS << 28);
+			/* The USB spec says that high speed bulk endpoints
+			 * always use 512 byte maxpacket.  But some device
+			 * vendors decided to ignore that, and MSFT is happy
+			 * to help them do so.  So now people expect to use
+			 * such nonconformant devices with Linux too; sigh.
+			 */
+			info1 |= max_packet(maxp) << 16;
+			info2 |= (FOTG210_TUNE_MULT_HS << 30);
+		} else {		/* PIPE_INTERRUPT */
+			info1 |= max_packet(maxp) << 16;
+			info2 |= hb_mult(maxp) << 30;
+		}
+		break;
+	default:
+		fotg210_dbg(fotg210, "bogus dev %p speed %d\n", urb->dev,
+			urb->dev->speed);
+done:
+		qh_destroy(fotg210, qh);
+		return NULL;
+	}
+
+	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
+
+	/* init as live, toggle clear, advance to dummy */
+	qh->qh_state = QH_STATE_IDLE;
+	hw = qh->hw;
+	hw->hw_info1 = cpu_to_hc32(fotg210, info1);
+	hw->hw_info2 = cpu_to_hc32(fotg210, info2);
+	qh->is_out = !is_input;
+	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input, 1);
+	qh_refresh(fotg210, qh);
+	return qh;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void enable_async(struct fotg210_hcd *fotg210)
+{
+	if (fotg210->async_count++)
+		return;
+
+	/* Stop waiting to turn off the async schedule */
+	fotg210->enabled_hrtimer_events &= ~BIT(FOTG210_HRTIMER_DISABLE_ASYNC);
+
+	/* Don't start the schedule until ASS is 0 */
+	fotg210_poll_ASS(fotg210);
+	turn_on_io_watchdog(fotg210);
+}
+
+static void disable_async(struct fotg210_hcd *fotg210)
+{
+	if (--fotg210->async_count)
+		return;
+
+	/* The async schedule and async_unlink list are supposed to be empty */
+	WARN_ON(fotg210->async->qh_next.qh || fotg210->async_unlink);
+
+	/* Don't turn off the schedule until ASS is 1 */
+	fotg210_poll_ASS(fotg210);
+}
+
+/* move qh (and its qtds) onto async queue; maybe enable queue.  */
+
+static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	__hc32		dma = QH_NEXT(fotg210, qh->qh_dma);
+	struct fotg210_qh	*head;
+
+	/* Don't link a QH if there's a Clear-TT-Buffer pending */
+	if (unlikely(qh->clearing_tt))
+		return;
+
+	WARN_ON(qh->qh_state != QH_STATE_IDLE);
+
+	/* clear halt and/or toggle; and maybe recover from silicon quirk */
+	qh_refresh(fotg210, qh);
+
+	/* splice right after start */
+	head = fotg210->async;
+	qh->qh_next = head->qh_next;
+	qh->hw->hw_next = head->hw->hw_next;
+	wmb();
+
+	head->qh_next.qh = qh;
+	head->hw->hw_next = dma;
+
+	qh->xacterrs = 0;
+	qh->qh_state = QH_STATE_LINKED;
+	/* qtd completions reported later by interrupt */
+
+	enable_async(fotg210);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * For control/bulk/interrupt, return QH with these TDs appended.
+ * Allocates and initializes the QH if necessary.
+ * Returns null if it can't allocate a QH it needs to.
+ * If the QH has TDs (urbs) already, that's great.
+ */
+static struct fotg210_qh *qh_append_tds(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	struct list_head	*qtd_list,
+	int			epnum,
+	void			**ptr
+)
+{
+	struct fotg210_qh		*qh = NULL;
+	__hc32			qh_addr_mask = cpu_to_hc32(fotg210, 0x7f);
+
+	qh = (struct fotg210_qh *) *ptr;
+	if (unlikely(qh == NULL)) {
+		/* can't sleep here, we have fotg210->lock... */
+		qh = qh_make(fotg210, urb, GFP_ATOMIC);
+		*ptr = qh;
+	}
+	if (likely(qh != NULL)) {
+		struct fotg210_qtd	*qtd;
+
+		if (unlikely(list_empty(qtd_list)))
+			qtd = NULL;
+		else
+			qtd = list_entry(qtd_list->next, struct fotg210_qtd,
+					qtd_list);
+
+		/* control qh may need patching ... */
+		if (unlikely(epnum == 0)) {
+			/* usb_reset_device() briefly reverts to address 0 */
+			if (usb_pipedevice(urb->pipe) == 0)
+				qh->hw->hw_info1 &= ~qh_addr_mask;
+		}
+
+		/* just one way to queue requests: swap with the dummy qtd.
+		 * only hc or qh_refresh() ever modify the overlay.
+		 */
+		if (likely(qtd != NULL)) {
+			struct fotg210_qtd		*dummy;
+			dma_addr_t		dma;
+			__hc32			token;
+
+			/* to avoid racing the HC, use the dummy td instead of
+			 * the first td of our list (becomes new dummy).  both
+			 * tds stay deactivated until we're done, when the
+			 * HC is allowed to fetch the old dummy (4.10.2).
+			 */
+			token = qtd->hw_token;
+			qtd->hw_token = HALT_BIT(fotg210);
+
+			dummy = qh->dummy;
+
+			dma = dummy->qtd_dma;
+			*dummy = *qtd;
+			dummy->qtd_dma = dma;
+
+			list_del(&qtd->qtd_list);
+			list_add(&dummy->qtd_list, qtd_list);
+			list_splice_tail(qtd_list, &qh->qtd_list);
+
+			fotg210_qtd_init(fotg210, qtd, qtd->qtd_dma);
+			qh->dummy = qtd;
+
+			/* hc must see the new dummy at list end */
+			dma = qtd->qtd_dma;
+			qtd = list_entry(qh->qtd_list.prev,
+					struct fotg210_qtd, qtd_list);
+			qtd->hw_next = QTD_NEXT(fotg210, dma);
+
+			/* let the hc process these next qtds */
+			wmb();
+			dummy->hw_token = token;
+
+			urb->hcpriv = qh;
+		}
+	}
+	return qh;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+submit_async(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	struct list_head	*qtd_list,
+	gfp_t			mem_flags
+) {
+	int			epnum;
+	unsigned long		flags;
+	struct fotg210_qh		*qh = NULL;
+	int			rc;
+
+	epnum = urb->ep->desc.bEndpointAddress;
+
+#ifdef FOTG210_URB_TRACE
+	{
+		struct fotg210_qtd *qtd;
+		qtd = list_entry(qtd_list->next, struct fotg210_qtd, qtd_list);
+		fotg210_dbg(fotg210,
+			 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+			 __func__, urb->dev->devpath, urb,
+			 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
+			 urb->transfer_buffer_length,
+			 qtd, urb->ep->hcpriv);
+	}
+#endif
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+	if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) {
+		rc = -ESHUTDOWN;
+		goto done;
+	}
+	rc = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb);
+	if (unlikely(rc))
+		goto done;
+
+	qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv);
+	if (unlikely(qh == NULL)) {
+		usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
+		rc = -ENOMEM;
+		goto done;
+	}
+
+	/* Control/bulk operations through TTs don't need scheduling,
+	 * the HC and TT handle it when the TT has a buffer ready.
+	 */
+	if (likely(qh->qh_state == QH_STATE_IDLE))
+		qh_link_async(fotg210, qh);
+ done:
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	if (unlikely(qh == NULL))
+		qtd_list_free(fotg210, urb, qtd_list);
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void single_unlink_async(struct fotg210_hcd *fotg210,
+				struct fotg210_qh *qh)
+{
+	struct fotg210_qh		*prev;
+
+	/* Add to the end of the list of QHs waiting for the next IAAD */
+	qh->qh_state = QH_STATE_UNLINK;
+	if (fotg210->async_unlink)
+		fotg210->async_unlink_last->unlink_next = qh;
+	else
+		fotg210->async_unlink = qh;
+	fotg210->async_unlink_last = qh;
+
+	/* Unlink it from the schedule */
+	prev = fotg210->async;
+	while (prev->qh_next.qh != qh)
+		prev = prev->qh_next.qh;
+
+	prev->hw->hw_next = qh->hw->hw_next;
+	prev->qh_next = qh->qh_next;
+	if (fotg210->qh_scan_next == qh)
+		fotg210->qh_scan_next = qh->qh_next.qh;
+}
+
+static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested)
+{
+	/*
+	 * Do nothing if an IAA cycle is already running or
+	 * if one will be started shortly.
+	 */
+	if (fotg210->async_iaa || fotg210->async_unlinking)
+		return;
+
+	/* Do all the waiting QHs at once */
+	fotg210->async_iaa = fotg210->async_unlink;
+	fotg210->async_unlink = NULL;
+
+	/* If the controller isn't running, we don't have to wait for it */
+	if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) {
+		if (!nested)		/* Avoid recursion */
+			end_unlink_async(fotg210);
+
+	/* Otherwise start a new IAA cycle */
+	} else if (likely(fotg210->rh_state == FOTG210_RH_RUNNING)) {
+		/* Make sure the unlinks are all visible to the hardware */
+		wmb();
+
+		fotg210_writel(fotg210, fotg210->command | CMD_IAAD,
+				&fotg210->regs->command);
+		fotg210_readl(fotg210, &fotg210->regs->command);
+		fotg210_enable_event(fotg210, FOTG210_HRTIMER_IAA_WATCHDOG,
+				     true);
+	}
+}
+
+/* the async qh for the qtds being unlinked are now gone from the HC */
+
+static void end_unlink_async(struct fotg210_hcd *fotg210)
+{
+	struct fotg210_qh		*qh;
+
+	/* Process the idle QHs */
+ restart:
+	fotg210->async_unlinking = true;
+	while (fotg210->async_iaa) {
+		qh = fotg210->async_iaa;
+		fotg210->async_iaa = qh->unlink_next;
+		qh->unlink_next = NULL;
+
+		qh->qh_state = QH_STATE_IDLE;
+		qh->qh_next.qh = NULL;
+
+		qh_completions(fotg210, qh);
+		if (!list_empty(&qh->qtd_list) &&
+				fotg210->rh_state == FOTG210_RH_RUNNING)
+			qh_link_async(fotg210, qh);
+		disable_async(fotg210);
+	}
+	fotg210->async_unlinking = false;
+
+	/* Start a new IAA cycle if any QHs are waiting for it */
+	if (fotg210->async_unlink) {
+		start_iaa_cycle(fotg210, true);
+		if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING))
+			goto restart;
+	}
+}
+
+static void unlink_empty_async(struct fotg210_hcd *fotg210)
+{
+	struct fotg210_qh *qh, *next;
+	bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
+	bool check_unlinks_later = false;
+
+	/* Unlink all the async QHs that have been empty for a timer cycle */
+	next = fotg210->async->qh_next.qh;
+	while (next) {
+		qh = next;
+		next = qh->qh_next.qh;
+
+		if (list_empty(&qh->qtd_list) &&
+				qh->qh_state == QH_STATE_LINKED) {
+			if (!stopped && qh->unlink_cycle ==
+					fotg210->async_unlink_cycle)
+				check_unlinks_later = true;
+			else
+				single_unlink_async(fotg210, qh);
+		}
+	}
+
+	/* Start a new IAA cycle if any QHs are waiting for it */
+	if (fotg210->async_unlink)
+		start_iaa_cycle(fotg210, false);
+
+	/* QHs that haven't been empty for long enough will be handled later */
+	if (check_unlinks_later) {
+		fotg210_enable_event(fotg210, FOTG210_HRTIMER_ASYNC_UNLINKS,
+				     true);
+		++fotg210->async_unlink_cycle;
+	}
+}
+
+/* makes sure the async qh will become idle */
+/* caller must own fotg210->lock */
+
+static void start_unlink_async(struct fotg210_hcd *fotg210,
+			       struct fotg210_qh *qh)
+{
+	/*
+	 * If the QH isn't linked then there's nothing we can do
+	 * unless we were called during a giveback, in which case
+	 * qh_completions() has to deal with it.
+	 */
+	if (qh->qh_state != QH_STATE_LINKED) {
+		if (qh->qh_state == QH_STATE_COMPLETING)
+			qh->needs_rescan = 1;
+		return;
+	}
+
+	single_unlink_async(fotg210, qh);
+	start_iaa_cycle(fotg210, false);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void scan_async(struct fotg210_hcd *fotg210)
+{
+	struct fotg210_qh		*qh;
+	bool			check_unlinks_later = false;
+
+	fotg210->qh_scan_next = fotg210->async->qh_next.qh;
+	while (fotg210->qh_scan_next) {
+		qh = fotg210->qh_scan_next;
+		fotg210->qh_scan_next = qh->qh_next.qh;
+ rescan:
+		/* clean any finished work for this qh */
+		if (!list_empty(&qh->qtd_list)) {
+			int temp;
+
+			/*
+			 * Unlinks could happen here; completion reporting
+			 * drops the lock.  That's why fotg210->qh_scan_next
+			 * always holds the next qh to scan; if the next qh
+			 * gets unlinked then fotg210->qh_scan_next is adjusted
+			 * in single_unlink_async().
+			 */
+			temp = qh_completions(fotg210, qh);
+			if (qh->needs_rescan) {
+				start_unlink_async(fotg210, qh);
+			} else if (list_empty(&qh->qtd_list)
+					&& qh->qh_state == QH_STATE_LINKED) {
+				qh->unlink_cycle = fotg210->async_unlink_cycle;
+				check_unlinks_later = true;
+			} else if (temp != 0)
+				goto rescan;
+		}
+	}
+
+	/*
+	 * Unlink empty entries, reducing DMA usage as well
+	 * as HCD schedule-scanning costs.  Delay for any qh
+	 * we just scanned, there's a not-unusual case that it
+	 * doesn't stay idle for long.
+	 */
+	if (check_unlinks_later && fotg210->rh_state == FOTG210_RH_RUNNING &&
+			!(fotg210->enabled_hrtimer_events &
+				BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) {
+		fotg210_enable_event(fotg210,
+				     FOTG210_HRTIMER_ASYNC_UNLINKS, true);
+		++fotg210->async_unlink_cycle;
+	}
+}
+/*-------------------------------------------------------------------------*/
+/*
+ * EHCI scheduled transaction support:  interrupt, iso, split iso
+ * These are called "periodic" transactions in the EHCI spec.
+ *
+ * Note that for interrupt transfers, the QH/QTD manipulation is shared
+ * with the "asynchronous" transaction support (control/bulk transfers).
+ * The only real difference is in how interrupt transfers are scheduled.
+ *
+ * For ISO, we make an "iso_stream" head to serve the same role as a QH.
+ * It keeps track of every ITD (or SITD) that's linked, and holds enough
+ * pre-calculated schedule data to make appending to the queue be quick.
+ */
+
+static int fotg210_get_frame(struct usb_hcd *hcd);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * periodic_next_shadow - return "next" pointer on shadow list
+ * @periodic: host pointer to qh/itd
+ * @tag: hardware tag for type of this record
+ */
+static union fotg210_shadow *
+periodic_next_shadow(struct fotg210_hcd *fotg210,
+		     union fotg210_shadow *periodic, __hc32 tag)
+{
+	switch (hc32_to_cpu(fotg210, tag)) {
+	case Q_TYPE_QH:
+		return &periodic->qh->qh_next;
+	case Q_TYPE_FSTN:
+		return &periodic->fstn->fstn_next;
+	default:
+		return &periodic->itd->itd_next;
+	}
+}
+
+static __hc32 *
+shadow_next_periodic(struct fotg210_hcd *fotg210,
+		     union fotg210_shadow *periodic, __hc32 tag)
+{
+	switch (hc32_to_cpu(fotg210, tag)) {
+	/* our fotg210_shadow.qh is actually software part */
+	case Q_TYPE_QH:
+		return &periodic->qh->hw->hw_next;
+	/* others are hw parts */
+	default:
+		return periodic->hw_next;
+	}
+}
+
+/* caller must hold fotg210->lock */
+static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame,
+			    void *ptr)
+{
+	union fotg210_shadow	*prev_p = &fotg210->pshadow[frame];
+	__hc32			*hw_p = &fotg210->periodic[frame];
+	union fotg210_shadow	here = *prev_p;
+
+	/* find predecessor of "ptr"; hw and shadow lists are in sync */
+	while (here.ptr && here.ptr != ptr) {
+		prev_p = periodic_next_shadow(fotg210, prev_p,
+				Q_NEXT_TYPE(fotg210, *hw_p));
+		hw_p = shadow_next_periodic(fotg210, &here,
+				Q_NEXT_TYPE(fotg210, *hw_p));
+		here = *prev_p;
+	}
+	/* an interrupt entry (at list end) could have been shared */
+	if (!here.ptr)
+		return;
+
+	/* update shadow and hardware lists ... the old "next" pointers
+	 * from ptr may still be in use, the caller updates them.
+	 */
+	*prev_p = *periodic_next_shadow(fotg210, &here,
+			Q_NEXT_TYPE(fotg210, *hw_p));
+
+	*hw_p = *shadow_next_periodic(fotg210, &here,
+				Q_NEXT_TYPE(fotg210, *hw_p));
+}
+
+/* how many of the uframe's 125 usecs are allocated? */
+static unsigned short
+periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe)
+{
+	__hc32			*hw_p = &fotg210->periodic[frame];
+	union fotg210_shadow	*q = &fotg210->pshadow[frame];
+	unsigned		usecs = 0;
+	struct fotg210_qh_hw	*hw;
+
+	while (q->ptr) {
+		switch (hc32_to_cpu(fotg210, Q_NEXT_TYPE(fotg210, *hw_p))) {
+		case Q_TYPE_QH:
+			hw = q->qh->hw;
+			/* is it in the S-mask? */
+			if (hw->hw_info2 & cpu_to_hc32(fotg210, 1 << uframe))
+				usecs += q->qh->usecs;
+			/* ... or C-mask? */
+			if (hw->hw_info2 & cpu_to_hc32(fotg210,
+					1 << (8 + uframe)))
+				usecs += q->qh->c_usecs;
+			hw_p = &hw->hw_next;
+			q = &q->qh->qh_next;
+			break;
+		/* case Q_TYPE_FSTN: */
+		default:
+			/* for "save place" FSTNs, count the relevant INTR
+			 * bandwidth from the previous frame
+			 */
+			if (q->fstn->hw_prev != FOTG210_LIST_END(fotg210))
+				fotg210_dbg(fotg210, "ignoring FSTN cost ...\n");
+
+			hw_p = &q->fstn->hw_next;
+			q = &q->fstn->fstn_next;
+			break;
+		case Q_TYPE_ITD:
+			if (q->itd->hw_transaction[uframe])
+				usecs += q->itd->stream->usecs;
+			hw_p = &q->itd->hw_next;
+			q = &q->itd->itd_next;
+			break;
+		}
+	}
+#ifdef	DEBUG
+	if (usecs > fotg210->uframe_periodic_max)
+		fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n",
+			frame * 8 + uframe, usecs);
+#endif
+	return usecs;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int same_tt(struct usb_device *dev1, struct usb_device *dev2)
+{
+	if (!dev1->tt || !dev2->tt)
+		return 0;
+	if (dev1->tt != dev2->tt)
+		return 0;
+	if (dev1->tt->multi)
+		return dev1->ttport == dev2->ttport;
+	else
+		return 1;
+}
+
+/* return true iff the device's transaction translator is available
+ * for a periodic transfer starting at the specified frame, using
+ * all the uframes in the mask.
+ */
+static int tt_no_collision(
+	struct fotg210_hcd		*fotg210,
+	unsigned		period,
+	struct usb_device	*dev,
+	unsigned		frame,
+	u32			uf_mask
+)
+{
+	if (period == 0)	/* error */
+		return 0;
+
+	/* note bandwidth wastage:  split never follows csplit
+	 * (different dev or endpoint) until the next uframe.
+	 * calling convention doesn't make that distinction.
+	 */
+	for (; frame < fotg210->periodic_size; frame += period) {
+		union fotg210_shadow	here;
+		__hc32			type;
+		struct fotg210_qh_hw	*hw;
+
+		here = fotg210->pshadow[frame];
+		type = Q_NEXT_TYPE(fotg210, fotg210->periodic[frame]);
+		while (here.ptr) {
+			switch (hc32_to_cpu(fotg210, type)) {
+			case Q_TYPE_ITD:
+				type = Q_NEXT_TYPE(fotg210, here.itd->hw_next);
+				here = here.itd->itd_next;
+				continue;
+			case Q_TYPE_QH:
+				hw = here.qh->hw;
+				if (same_tt(dev, here.qh->dev)) {
+					u32		mask;
+
+					mask = hc32_to_cpu(fotg210,
+							hw->hw_info2);
+					/* "knows" no gap is needed */
+					mask |= mask >> 8;
+					if (mask & uf_mask)
+						break;
+				}
+				type = Q_NEXT_TYPE(fotg210, hw->hw_next);
+				here = here.qh->qh_next;
+				continue;
+			/* case Q_TYPE_FSTN: */
+			default:
+				fotg210_dbg(fotg210,
+					"periodic frame %d bogus type %d\n",
+					frame, type);
+			}
+
+			/* collision or error */
+			return 0;
+		}
+	}
+
+	/* no collision */
+	return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void enable_periodic(struct fotg210_hcd *fotg210)
+{
+	if (fotg210->periodic_count++)
+		return;
+
+	/* Stop waiting to turn off the periodic schedule */
+	fotg210->enabled_hrtimer_events &=
+		~BIT(FOTG210_HRTIMER_DISABLE_PERIODIC);
+
+	/* Don't start the schedule until PSS is 0 */
+	fotg210_poll_PSS(fotg210);
+	turn_on_io_watchdog(fotg210);
+}
+
+static void disable_periodic(struct fotg210_hcd *fotg210)
+{
+	if (--fotg210->periodic_count)
+		return;
+
+	/* Don't turn off the schedule until PSS is 1 */
+	fotg210_poll_PSS(fotg210);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* periodic schedule slots have iso tds (normal or split) first, then a
+ * sparse tree for active interrupt transfers.
+ *
+ * this just links in a qh; caller guarantees uframe masks are set right.
+ * no FSTN support (yet; fotg210 0.96+)
+ */
+static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	unsigned	i;
+	unsigned	period = qh->period;
+
+	dev_dbg(&qh->dev->dev,
+		"link qh%d-%04x/%p start %d [%d/%d us]\n",
+		period, hc32_to_cpup(fotg210, &qh->hw->hw_info2)
+			& (QH_CMASK | QH_SMASK),
+		qh, qh->start, qh->usecs, qh->c_usecs);
+
+	/* high bandwidth, or otherwise every microframe */
+	if (period == 0)
+		period = 1;
+
+	for (i = qh->start; i < fotg210->periodic_size; i += period) {
+		union fotg210_shadow	*prev = &fotg210->pshadow[i];
+		__hc32			*hw_p = &fotg210->periodic[i];
+		union fotg210_shadow	here = *prev;
+		__hc32			type = 0;
+
+		/* skip the iso nodes at list head */
+		while (here.ptr) {
+			type = Q_NEXT_TYPE(fotg210, *hw_p);
+			if (type == cpu_to_hc32(fotg210, Q_TYPE_QH))
+				break;
+			prev = periodic_next_shadow(fotg210, prev, type);
+			hw_p = shadow_next_periodic(fotg210, &here, type);
+			here = *prev;
+		}
+
+		/* sorting each branch by period (slow-->fast)
+		 * enables sharing interior tree nodes
+		 */
+		while (here.ptr && qh != here.qh) {
+			if (qh->period > here.qh->period)
+				break;
+			prev = &here.qh->qh_next;
+			hw_p = &here.qh->hw->hw_next;
+			here = *prev;
+		}
+		/* link in this qh, unless some earlier pass did that */
+		if (qh != here.qh) {
+			qh->qh_next = here;
+			if (here.qh)
+				qh->hw->hw_next = *hw_p;
+			wmb();
+			prev->qh = qh;
+			*hw_p = QH_NEXT(fotg210, qh->qh_dma);
+		}
+	}
+	qh->qh_state = QH_STATE_LINKED;
+	qh->xacterrs = 0;
+
+	/* update per-qh bandwidth for usbfs */
+	fotg210_to_hcd(fotg210)->self.bandwidth_allocated += qh->period
+		? ((qh->usecs + qh->c_usecs) / qh->period)
+		: (qh->usecs * 8);
+
+	list_add(&qh->intr_node, &fotg210->intr_qh_list);
+
+	/* maybe enable periodic schedule processing */
+	++fotg210->intr_count;
+	enable_periodic(fotg210);
+}
+
+static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
+			       struct fotg210_qh *qh)
+{
+	unsigned	i;
+	unsigned	period;
+
+	/*
+	 * If qh is for a low/full-speed device, simply unlinking it
+	 * could interfere with an ongoing split transaction.  To unlink
+	 * it safely would require setting the QH_INACTIVATE bit and
+	 * waiting at least one frame, as described in EHCI 4.12.2.5.
+	 *
+	 * We won't bother with any of this.  Instead, we assume that the
+	 * only reason for unlinking an interrupt QH while the current URB
+	 * is still active is to dequeue all the URBs (flush the whole
+	 * endpoint queue).
+	 *
+	 * If rebalancing the periodic schedule is ever implemented, this
+	 * approach will no longer be valid.
+	 */
+
+	/* high bandwidth, or otherwise part of every microframe */
+	period = qh->period;
+	if (!period)
+		period = 1;
+
+	for (i = qh->start; i < fotg210->periodic_size; i += period)
+		periodic_unlink(fotg210, i, qh);
+
+	/* update per-qh bandwidth for usbfs */
+	fotg210_to_hcd(fotg210)->self.bandwidth_allocated -= qh->period
+		? ((qh->usecs + qh->c_usecs) / qh->period)
+		: (qh->usecs * 8);
+
+	dev_dbg(&qh->dev->dev,
+		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
+		qh->period,
+		hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
+		(QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs);
+
+	/* qh->qh_next still "live" to HC */
+	qh->qh_state = QH_STATE_UNLINK;
+	qh->qh_next.ptr = NULL;
+
+	if (fotg210->qh_scan_next == qh)
+		fotg210->qh_scan_next = list_entry(qh->intr_node.next,
+				struct fotg210_qh, intr_node);
+	list_del(&qh->intr_node);
+}
+
+static void start_unlink_intr(struct fotg210_hcd *fotg210,
+			      struct fotg210_qh *qh)
+{
+	/* If the QH isn't linked then there's nothing we can do
+	 * unless we were called during a giveback, in which case
+	 * qh_completions() has to deal with it.
+	 */
+	if (qh->qh_state != QH_STATE_LINKED) {
+		if (qh->qh_state == QH_STATE_COMPLETING)
+			qh->needs_rescan = 1;
+		return;
+	}
+
+	qh_unlink_periodic(fotg210, qh);
+
+	/* Make sure the unlinks are visible before starting the timer */
+	wmb();
+
+	/*
+	 * The EHCI spec doesn't say how long it takes the controller to
+	 * stop accessing an unlinked interrupt QH.  The timer delay is
+	 * 9 uframes; presumably that will be long enough.
+	 */
+	qh->unlink_cycle = fotg210->intr_unlink_cycle;
+
+	/* New entries go at the end of the intr_unlink list */
+	if (fotg210->intr_unlink)
+		fotg210->intr_unlink_last->unlink_next = qh;
+	else
+		fotg210->intr_unlink = qh;
+	fotg210->intr_unlink_last = qh;
+
+	if (fotg210->intr_unlinking)
+		;	/* Avoid recursive calls */
+	else if (fotg210->rh_state < FOTG210_RH_RUNNING)
+		fotg210_handle_intr_unlinks(fotg210);
+	else if (fotg210->intr_unlink == qh) {
+		fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR,
+				     true);
+		++fotg210->intr_unlink_cycle;
+	}
+}
+
+static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	struct fotg210_qh_hw	*hw = qh->hw;
+	int			rc;
+
+	qh->qh_state = QH_STATE_IDLE;
+	hw->hw_next = FOTG210_LIST_END(fotg210);
+
+	qh_completions(fotg210, qh);
+
+	/* reschedule QH iff another request is queued */
+	if (!list_empty(&qh->qtd_list) &&
+	    fotg210->rh_state == FOTG210_RH_RUNNING) {
+		rc = qh_schedule(fotg210, qh);
+
+		/* An error here likely indicates handshake failure
+		 * or no space left in the schedule.  Neither fault
+		 * should happen often ...
+		 *
+		 * FIXME kill the now-dysfunctional queued urbs
+		 */
+		if (rc != 0)
+			fotg210_err(fotg210, "can't reschedule qh %p, err %d\n",
+					qh, rc);
+	}
+
+	/* maybe turn off periodic schedule */
+	--fotg210->intr_count;
+	disable_periodic(fotg210);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int check_period(
+	struct fotg210_hcd *fotg210,
+	unsigned	frame,
+	unsigned	uframe,
+	unsigned	period,
+	unsigned	usecs
+) {
+	int		claimed;
+
+	/* complete split running into next frame?
+	 * given FSTN support, we could sometimes check...
+	 */
+	if (uframe >= 8)
+		return 0;
+
+	/* convert "usecs we need" to "max already claimed" */
+	usecs = fotg210->uframe_periodic_max - usecs;
+
+	/* we "know" 2 and 4 uframe intervals were rejected; so
+	 * for period 0, check _every_ microframe in the schedule.
+	 */
+	if (unlikely(period == 0)) {
+		do {
+			for (uframe = 0; uframe < 7; uframe++) {
+				claimed = periodic_usecs(fotg210, frame,
+							 uframe);
+				if (claimed > usecs)
+					return 0;
+			}
+		} while ((frame += 1) < fotg210->periodic_size);
+
+	/* just check the specified uframe, at that period */
+	} else {
+		do {
+			claimed = periodic_usecs(fotg210, frame, uframe);
+			if (claimed > usecs)
+				return 0;
+		} while ((frame += period) < fotg210->periodic_size);
+	}
+
+	/* success! */
+	return 1;
+}
+
+static int check_intr_schedule(
+	struct fotg210_hcd		*fotg210,
+	unsigned		frame,
+	unsigned		uframe,
+	const struct fotg210_qh	*qh,
+	__hc32			*c_maskp
+)
+{
+	int		retval = -ENOSPC;
+	u8		mask = 0;
+
+	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
+		goto done;
+
+	if (!check_period(fotg210, frame, uframe, qh->period, qh->usecs))
+		goto done;
+	if (!qh->c_usecs) {
+		retval = 0;
+		*c_maskp = 0;
+		goto done;
+	}
+
+	/* Make sure this tt's buffer is also available for CSPLITs.
+	 * We pessimize a bit; probably the typical full speed case
+	 * doesn't need the second CSPLIT.
+	 *
+	 * NOTE:  both SPLIT and CSPLIT could be checked in just
+	 * one smart pass...
+	 */
+	mask = 0x03 << (uframe + qh->gap_uf);
+	*c_maskp = cpu_to_hc32(fotg210, mask << 8);
+
+	mask |= 1 << uframe;
+	if (tt_no_collision(fotg210, qh->period, qh->dev, frame, mask)) {
+		if (!check_period(fotg210, frame, uframe + qh->gap_uf + 1,
+					qh->period, qh->c_usecs))
+			goto done;
+		if (!check_period(fotg210, frame, uframe + qh->gap_uf,
+					qh->period, qh->c_usecs))
+			goto done;
+		retval = 0;
+	}
+done:
+	return retval;
+}
+
+/* "first fit" scheduling policy used the first time through,
+ * or when the previous schedule slot can't be re-used.
+ */
+static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+{
+	int		status;
+	unsigned	uframe;
+	__hc32		c_mask;
+	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
+	struct fotg210_qh_hw	*hw = qh->hw;
+
+	qh_refresh(fotg210, qh);
+	hw->hw_next = FOTG210_LIST_END(fotg210);
+	frame = qh->start;
+
+	/* reuse the previous schedule slots, if we can */
+	if (frame < qh->period) {
+		uframe = ffs(hc32_to_cpup(fotg210, &hw->hw_info2) & QH_SMASK);
+		status = check_intr_schedule(fotg210, frame, --uframe,
+				qh, &c_mask);
+	} else {
+		uframe = 0;
+		c_mask = 0;
+		status = -ENOSPC;
+	}
+
+	/* else scan the schedule to find a group of slots such that all
+	 * uframes have enough periodic bandwidth available.
+	 */
+	if (status) {
+		/* "normal" case, uframing flexible except with splits */
+		if (qh->period) {
+			int		i;
+
+			for (i = qh->period; status && i > 0; --i) {
+				frame = ++fotg210->random_frame % qh->period;
+				for (uframe = 0; uframe < 8; uframe++) {
+					status = check_intr_schedule(fotg210,
+							frame, uframe, qh,
+							&c_mask);
+					if (status == 0)
+						break;
+				}
+			}
+
+		/* qh->period == 0 means every uframe */
+		} else {
+			frame = 0;
+			status = check_intr_schedule(fotg210, 0, 0, qh,
+						     &c_mask);
+		}
+		if (status)
+			goto done;
+		qh->start = frame;
+
+		/* reset S-frame and (maybe) C-frame masks */
+		hw->hw_info2 &= cpu_to_hc32(fotg210, ~(QH_CMASK | QH_SMASK));
+		hw->hw_info2 |= qh->period
+			? cpu_to_hc32(fotg210, 1 << uframe)
+			: cpu_to_hc32(fotg210, QH_SMASK);
+		hw->hw_info2 |= c_mask;
+	} else
+		fotg210_dbg(fotg210, "reused qh %p schedule\n", qh);
+
+	/* stuff into the periodic schedule */
+	qh_link_periodic(fotg210, qh);
+done:
+	return status;
+}
+
+static int intr_submit(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	struct list_head	*qtd_list,
+	gfp_t			mem_flags
+) {
+	unsigned		epnum;
+	unsigned long		flags;
+	struct fotg210_qh		*qh;
+	int			status;
+	struct list_head	empty;
+
+	/* get endpoint and transfer/schedule data */
+	epnum = urb->ep->desc.bEndpointAddress;
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+
+	if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) {
+		status = -ESHUTDOWN;
+		goto done_not_linked;
+	}
+	status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb);
+	if (unlikely(status))
+		goto done_not_linked;
+
+	/* get qh and force any scheduling errors */
+	INIT_LIST_HEAD(&empty);
+	qh = qh_append_tds(fotg210, urb, &empty, epnum, &urb->ep->hcpriv);
+	if (qh == NULL) {
+		status = -ENOMEM;
+		goto done;
+	}
+	if (qh->qh_state == QH_STATE_IDLE) {
+		status = qh_schedule(fotg210, qh);
+		if (status)
+			goto done;
+	}
+
+	/* then queue the urb's tds to the qh */
+	qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv);
+	BUG_ON(qh == NULL);
+
+	/* ... update usbfs periodic stats */
+	fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs++;
+
+done:
+	if (unlikely(status))
+		usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
+done_not_linked:
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	if (status)
+		qtd_list_free(fotg210, urb, qtd_list);
+
+	return status;
+}
+
+static void scan_intr(struct fotg210_hcd *fotg210)
+{
+	struct fotg210_qh		*qh;
+
+	list_for_each_entry_safe(qh, fotg210->qh_scan_next,
+				 &fotg210->intr_qh_list, intr_node) {
+ rescan:
+		/* clean any finished work for this qh */
+		if (!list_empty(&qh->qtd_list)) {
+			int temp;
+
+			/*
+			 * Unlinks could happen here; completion reporting
+			 * drops the lock.  That's why fotg210->qh_scan_next
+			 * always holds the next qh to scan; if the next qh
+			 * gets unlinked then fotg210->qh_scan_next is adjusted
+			 * in qh_unlink_periodic().
+			 */
+			temp = qh_completions(fotg210, qh);
+			if (unlikely(qh->needs_rescan ||
+					(list_empty(&qh->qtd_list) &&
+					 qh->qh_state == QH_STATE_LINKED)))
+				start_unlink_intr(fotg210, qh);
+			else if (temp != 0)
+				goto rescan;
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* fotg210_iso_stream ops work with both ITD and SITD */
+
+static struct fotg210_iso_stream *
+iso_stream_alloc(gfp_t mem_flags)
+{
+	struct fotg210_iso_stream *stream;
+
+	stream = kzalloc(sizeof(*stream), mem_flags);
+	if (likely(stream != NULL)) {
+		INIT_LIST_HEAD(&stream->td_list);
+		INIT_LIST_HEAD(&stream->free_list);
+		stream->next_uframe = -1;
+	}
+	return stream;
+}
+
+static void
+iso_stream_init(
+	struct fotg210_hcd		*fotg210,
+	struct fotg210_iso_stream	*stream,
+	struct usb_device	*dev,
+	int			pipe,
+	unsigned		interval
+)
+{
+	u32			buf1;
+	unsigned		epnum, maxp;
+	int			is_input;
+	long			bandwidth;
+	unsigned		multi;
+
+	/*
+	 * this might be a "high bandwidth" highspeed endpoint,
+	 * as encoded in the ep descriptor's wMaxPacket field
+	 */
+	epnum = usb_pipeendpoint(pipe);
+	is_input = usb_pipein(pipe) ? USB_DIR_IN : 0;
+	maxp = usb_maxpacket(dev, pipe, !is_input);
+	if (is_input)
+		buf1 = (1 << 11);
+	else
+		buf1 = 0;
+
+	maxp = max_packet(maxp);
+	multi = hb_mult(maxp);
+	buf1 |= maxp;
+	maxp *= multi;
+
+	stream->buf0 = cpu_to_hc32(fotg210, (epnum << 8) | dev->devnum);
+	stream->buf1 = cpu_to_hc32(fotg210, buf1);
+	stream->buf2 = cpu_to_hc32(fotg210, multi);
+
+	/* usbfs wants to report the average usecs per frame tied up
+	 * when transfers on this endpoint are scheduled ...
+	 */
+	if (dev->speed == USB_SPEED_FULL) {
+		interval <<= 3;
+		stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed,
+				is_input, 1, maxp));
+		stream->usecs /= 8;
+	} else {
+		stream->highspeed = 1;
+		stream->usecs = HS_USECS_ISO(maxp);
+	}
+	bandwidth = stream->usecs * 8;
+	bandwidth /= interval;
+
+	stream->bandwidth = bandwidth;
+	stream->udev = dev;
+	stream->bEndpointAddress = is_input | epnum;
+	stream->interval = interval;
+	stream->maxp = maxp;
+}
+
+static struct fotg210_iso_stream *
+iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
+{
+	unsigned		epnum;
+	struct fotg210_iso_stream	*stream;
+	struct usb_host_endpoint *ep;
+	unsigned long		flags;
+
+	epnum = usb_pipeendpoint(urb->pipe);
+	if (usb_pipein(urb->pipe))
+		ep = urb->dev->ep_in[epnum];
+	else
+		ep = urb->dev->ep_out[epnum];
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+	stream = ep->hcpriv;
+
+	if (unlikely(stream == NULL)) {
+		stream = iso_stream_alloc(GFP_ATOMIC);
+		if (likely(stream != NULL)) {
+			ep->hcpriv = stream;
+			stream->ep = ep;
+			iso_stream_init(fotg210, stream, urb->dev, urb->pipe,
+					urb->interval);
+		}
+
+	/* if dev->ep[epnum] is a QH, hw is set */
+	} else if (unlikely(stream->hw != NULL)) {
+		fotg210_dbg(fotg210, "dev %s ep%d%s, not iso??\n",
+			urb->dev->devpath, epnum,
+			usb_pipein(urb->pipe) ? "in" : "out");
+		stream = NULL;
+	}
+
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	return stream;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* fotg210_iso_sched ops can be ITD-only or SITD-only */
+
+static struct fotg210_iso_sched *
+iso_sched_alloc(unsigned packets, gfp_t mem_flags)
+{
+	struct fotg210_iso_sched	*iso_sched;
+	int			size = sizeof(*iso_sched);
+
+	size += packets * sizeof(struct fotg210_iso_packet);
+	iso_sched = kzalloc(size, mem_flags);
+	if (likely(iso_sched != NULL))
+		INIT_LIST_HEAD(&iso_sched->td_list);
+
+	return iso_sched;
+}
+
+static inline void
+itd_sched_init(
+	struct fotg210_hcd		*fotg210,
+	struct fotg210_iso_sched	*iso_sched,
+	struct fotg210_iso_stream	*stream,
+	struct urb		*urb
+)
+{
+	unsigned	i;
+	dma_addr_t	dma = urb->transfer_dma;
+
+	/* how many uframes are needed for these transfers */
+	iso_sched->span = urb->number_of_packets * stream->interval;
+
+	/* figure out per-uframe itd fields that we'll need later
+	 * when we fit new itds into the schedule.
+	 */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		struct fotg210_iso_packet	*uframe = &iso_sched->packet[i];
+		unsigned		length;
+		dma_addr_t		buf;
+		u32			trans;
+
+		length = urb->iso_frame_desc[i].length;
+		buf = dma + urb->iso_frame_desc[i].offset;
+
+		trans = FOTG210_ISOC_ACTIVE;
+		trans |= buf & 0x0fff;
+		if (unlikely(((i + 1) == urb->number_of_packets))
+				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
+			trans |= FOTG210_ITD_IOC;
+		trans |= length << 16;
+		uframe->transaction = cpu_to_hc32(fotg210, trans);
+
+		/* might need to cross a buffer page within a uframe */
+		uframe->bufp = (buf & ~(u64)0x0fff);
+		buf += length;
+		if (unlikely((uframe->bufp != (buf & ~(u64)0x0fff))))
+			uframe->cross = 1;
+	}
+}
+
+static void
+iso_sched_free(
+	struct fotg210_iso_stream	*stream,
+	struct fotg210_iso_sched	*iso_sched
+)
+{
+	if (!iso_sched)
+		return;
+	/* caller must hold fotg210->lock!*/
+	list_splice(&iso_sched->td_list, &stream->free_list);
+	kfree(iso_sched);
+}
+
+static int
+itd_urb_transaction(
+	struct fotg210_iso_stream	*stream,
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	gfp_t			mem_flags
+)
+{
+	struct fotg210_itd		*itd;
+	dma_addr_t		itd_dma;
+	int			i;
+	unsigned		num_itds;
+	struct fotg210_iso_sched	*sched;
+	unsigned long		flags;
+
+	sched = iso_sched_alloc(urb->number_of_packets, mem_flags);
+	if (unlikely(sched == NULL))
+		return -ENOMEM;
+
+	itd_sched_init(fotg210, sched, stream, urb);
+
+	if (urb->interval < 8)
+		num_itds = 1 + (sched->span + 7) / 8;
+	else
+		num_itds = urb->number_of_packets;
+
+	/* allocate/init ITDs */
+	spin_lock_irqsave(&fotg210->lock, flags);
+	for (i = 0; i < num_itds; i++) {
+
+		/*
+		 * Use iTDs from the free list, but not iTDs that may
+		 * still be in use by the hardware.
+		 */
+		if (likely(!list_empty(&stream->free_list))) {
+			itd = list_first_entry(&stream->free_list,
+					struct fotg210_itd, itd_list);
+			if (itd->frame == fotg210->now_frame)
+				goto alloc_itd;
+			list_del(&itd->itd_list);
+			itd_dma = itd->itd_dma;
+		} else {
+ alloc_itd:
+			spin_unlock_irqrestore(&fotg210->lock, flags);
+			itd = dma_pool_alloc(fotg210->itd_pool, mem_flags,
+					&itd_dma);
+			spin_lock_irqsave(&fotg210->lock, flags);
+			if (!itd) {
+				iso_sched_free(stream, sched);
+				spin_unlock_irqrestore(&fotg210->lock, flags);
+				return -ENOMEM;
+			}
+		}
+
+		memset(itd, 0, sizeof(*itd));
+		itd->itd_dma = itd_dma;
+		list_add(&itd->itd_list, &sched->td_list);
+	}
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+
+	/* temporarily store schedule info in hcpriv */
+	urb->hcpriv = sched;
+	urb->error_count = 0;
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline int
+itd_slot_ok(
+	struct fotg210_hcd		*fotg210,
+	u32			mod,
+	u32			uframe,
+	u8			usecs,
+	u32			period
+)
+{
+	uframe %= period;
+	do {
+		/* can't commit more than uframe_periodic_max usec */
+		if (periodic_usecs(fotg210, uframe >> 3, uframe & 0x7)
+				> (fotg210->uframe_periodic_max - usecs))
+			return 0;
+
+		/* we know urb->interval is 2^N uframes */
+		uframe += period;
+	} while (uframe < mod);
+	return 1;
+}
+
+/*
+ * This scheduler plans almost as far into the future as it has actual
+ * periodic schedule slots.  (Affected by TUNE_FLS, which defaults to
+ * "as small as possible" to be cache-friendlier.)  That limits the size
+ * transfers you can stream reliably; avoid more than 64 msec per urb.
+ * Also avoid queue depths of less than fotg210's worst irq latency (affected
+ * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter,
+ * and other factors); or more than about 230 msec total (for portability,
+ * given FOTG210_TUNE_FLS and the slop).  Or, write a smarter scheduler!
+ */
+
+#define SCHEDULE_SLOP	80	/* microframes */
+
+static int
+iso_stream_schedule(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	struct fotg210_iso_stream	*stream
+)
+{
+	u32			now, next, start, period, span;
+	int			status;
+	unsigned		mod = fotg210->periodic_size << 3;
+	struct fotg210_iso_sched	*sched = urb->hcpriv;
+
+	period = urb->interval;
+	span = sched->span;
+
+	if (span > mod - SCHEDULE_SLOP) {
+		fotg210_dbg(fotg210, "iso request %p too long\n", urb);
+		status = -EFBIG;
+		goto fail;
+	}
+
+	now = fotg210_read_frame_index(fotg210) & (mod - 1);
+
+	/* Typical case: reuse current schedule, stream is still active.
+	 * Hopefully there are no gaps from the host falling behind
+	 * (irq delays etc), but if there are we'll take the next
+	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+	 */
+	if (likely(!list_empty(&stream->td_list))) {
+		u32	excess;
+
+		/* For high speed devices, allow scheduling within the
+		 * isochronous scheduling threshold.  For full speed devices
+		 * and Intel PCI-based controllers, don't (work around for
+		 * Intel ICH9 bug).
+		 */
+		if (!stream->highspeed && fotg210->fs_i_thresh)
+			next = now + fotg210->i_thresh;
+		else
+			next = now;
+
+		/* Fell behind (by up to twice the slop amount)?
+		 * We decide based on the time of the last currently-scheduled
+		 * slot, not the time of the next available slot.
+		 */
+		excess = (stream->next_uframe - period - next) & (mod - 1);
+		if (excess >= mod - 2 * SCHEDULE_SLOP)
+			start = next + excess - mod + period *
+					DIV_ROUND_UP(mod - excess, period);
+		else
+			start = next + excess + period;
+		if (start - now >= mod) {
+			fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n",
+					urb, start - now - period, period,
+					mod);
+			status = -EFBIG;
+			goto fail;
+		}
+	}
+
+	/* need to schedule; when's the next (u)frame we could start?
+	 * this is bigger than fotg210->i_thresh allows; scheduling itself
+	 * isn't free, the slop should handle reasonably slow cpus.  it
+	 * can also help high bandwidth if the dma and irq loads don't
+	 * jump until after the queue is primed.
+	 */
+	else {
+		int done = 0;
+		start = SCHEDULE_SLOP + (now & ~0x07);
+
+		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+
+		/* find a uframe slot with enough bandwidth.
+		 * Early uframes are more precious because full-speed
+		 * iso IN transfers can't use late uframes,
+		 * and therefore they should be allocated last.
+		 */
+		next = start;
+		start += period;
+		do {
+			start--;
+			/* check schedule: enough space? */
+			if (itd_slot_ok(fotg210, mod, start,
+					stream->usecs, period))
+				done = 1;
+		} while (start > next && !done);
+
+		/* no room in the schedule */
+		if (!done) {
+			fotg210_dbg(fotg210, "iso resched full %p (now %d max %d)\n",
+				urb, now, now + mod);
+			status = -ENOSPC;
+			goto fail;
+		}
+	}
+
+	/* Tried to schedule too far into the future? */
+	if (unlikely(start - now + span - period
+				>= mod - 2 * SCHEDULE_SLOP)) {
+		fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n",
+				urb, start - now, span - period,
+				mod - 2 * SCHEDULE_SLOP);
+		status = -EFBIG;
+		goto fail;
+	}
+
+	stream->next_uframe = start & (mod - 1);
+
+	/* report high speed start in uframes; full speed, in frames */
+	urb->start_frame = stream->next_uframe;
+	if (!stream->highspeed)
+		urb->start_frame >>= 3;
+
+	/* Make sure scan_isoc() sees these */
+	if (fotg210->isoc_count == 0)
+		fotg210->next_frame = now >> 3;
+	return 0;
+
+ fail:
+	iso_sched_free(stream, sched);
+	urb->hcpriv = NULL;
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void
+itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream,
+		struct fotg210_itd *itd)
+{
+	int i;
+
+	/* it's been recently zeroed */
+	itd->hw_next = FOTG210_LIST_END(fotg210);
+	itd->hw_bufp[0] = stream->buf0;
+	itd->hw_bufp[1] = stream->buf1;
+	itd->hw_bufp[2] = stream->buf2;
+
+	for (i = 0; i < 8; i++)
+		itd->index[i] = -1;
+
+	/* All other fields are filled when scheduling */
+}
+
+static inline void
+itd_patch(
+	struct fotg210_hcd		*fotg210,
+	struct fotg210_itd		*itd,
+	struct fotg210_iso_sched	*iso_sched,
+	unsigned		index,
+	u16			uframe
+)
+{
+	struct fotg210_iso_packet	*uf = &iso_sched->packet[index];
+	unsigned		pg = itd->pg;
+
+	uframe &= 0x07;
+	itd->index[uframe] = index;
+
+	itd->hw_transaction[uframe] = uf->transaction;
+	itd->hw_transaction[uframe] |= cpu_to_hc32(fotg210, pg << 12);
+	itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, uf->bufp & ~(u32)0);
+	itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(uf->bufp >> 32));
+
+	/* iso_frame_desc[].offset must be strictly increasing */
+	if (unlikely(uf->cross)) {
+		u64	bufp = uf->bufp + 4096;
+
+		itd->pg = ++pg;
+		itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, bufp & ~(u32)0);
+		itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(bufp >> 32));
+	}
+}
+
+static inline void
+itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd)
+{
+	union fotg210_shadow	*prev = &fotg210->pshadow[frame];
+	__hc32			*hw_p = &fotg210->periodic[frame];
+	union fotg210_shadow	here = *prev;
+	__hc32			type = 0;
+
+	/* skip any iso nodes which might belong to previous microframes */
+	while (here.ptr) {
+		type = Q_NEXT_TYPE(fotg210, *hw_p);
+		if (type == cpu_to_hc32(fotg210, Q_TYPE_QH))
+			break;
+		prev = periodic_next_shadow(fotg210, prev, type);
+		hw_p = shadow_next_periodic(fotg210, &here, type);
+		here = *prev;
+	}
+
+	itd->itd_next = here;
+	itd->hw_next = *hw_p;
+	prev->itd = itd;
+	itd->frame = frame;
+	wmb();
+	*hw_p = cpu_to_hc32(fotg210, itd->itd_dma | Q_TYPE_ITD);
+}
+
+/* fit urb's itds into the selected schedule slot; activate as needed */
+static void itd_link_urb(
+	struct fotg210_hcd		*fotg210,
+	struct urb		*urb,
+	unsigned		mod,
+	struct fotg210_iso_stream	*stream
+)
+{
+	int			packet;
+	unsigned		next_uframe, uframe, frame;
+	struct fotg210_iso_sched	*iso_sched = urb->hcpriv;
+	struct fotg210_itd		*itd;
+
+	next_uframe = stream->next_uframe & (mod - 1);
+
+	if (unlikely(list_empty(&stream->td_list))) {
+		fotg210_to_hcd(fotg210)->self.bandwidth_allocated
+				+= stream->bandwidth;
+		fotg210_vdbg(fotg210,
+			"schedule devp %s ep%d%s-iso period %d start %d.%d\n",
+			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
+			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+			urb->interval,
+			next_uframe >> 3, next_uframe & 0x7);
+	}
+
+	/* fill iTDs uframe by uframe */
+	for (packet = 0, itd = NULL; packet < urb->number_of_packets;) {
+		if (itd == NULL) {
+			/* ASSERT:  we have all necessary itds */
+
+			/* ASSERT:  no itds for this endpoint in this uframe */
+
+			itd = list_entry(iso_sched->td_list.next,
+					struct fotg210_itd, itd_list);
+			list_move_tail(&itd->itd_list, &stream->td_list);
+			itd->stream = stream;
+			itd->urb = urb;
+			itd_init(fotg210, stream, itd);
+		}
+
+		uframe = next_uframe & 0x07;
+		frame = next_uframe >> 3;
+
+		itd_patch(fotg210, itd, iso_sched, packet, uframe);
+
+		next_uframe += stream->interval;
+		next_uframe &= mod - 1;
+		packet++;
+
+		/* link completed itds into the schedule */
+		if (((next_uframe >> 3) != frame)
+				|| packet == urb->number_of_packets) {
+			itd_link(fotg210, frame & (fotg210->periodic_size - 1),
+				 itd);
+			itd = NULL;
+		}
+	}
+	stream->next_uframe = next_uframe;
+
+	/* don't need that schedule data any more */
+	iso_sched_free(stream, iso_sched);
+	urb->hcpriv = NULL;
+
+	++fotg210->isoc_count;
+	enable_periodic(fotg210);
+}
+
+#define	ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\
+		  FOTG210_ISOC_XACTERR)
+
+/* Process and recycle a completed ITD.  Return true iff its urb completed,
+ * and hence its completion callback probably added things to the hardware
+ * schedule.
+ *
+ * Note that we carefully avoid recycling this descriptor until after any
+ * completion callback runs, so that it won't be reused quickly.  That is,
+ * assuming (a) no more than two urbs per frame on this endpoint, and also
+ * (b) only this endpoint's completions submit URBs.  It seems some silicon
+ * corrupts things if you reuse completed descriptors very quickly...
+ */
+static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
+{
+	struct urb				*urb = itd->urb;
+	struct usb_iso_packet_descriptor	*desc;
+	u32					t;
+	unsigned				uframe;
+	int					urb_index = -1;
+	struct fotg210_iso_stream			*stream = itd->stream;
+	struct usb_device			*dev;
+	bool					retval = false;
+
+	/* for each uframe with a packet */
+	for (uframe = 0; uframe < 8; uframe++) {
+		if (likely(itd->index[uframe] == -1))
+			continue;
+		urb_index = itd->index[uframe];
+		desc = &urb->iso_frame_desc[urb_index];
+
+		t = hc32_to_cpup(fotg210, &itd->hw_transaction[uframe]);
+		itd->hw_transaction[uframe] = 0;
+
+		/* report transfer status */
+		if (unlikely(t & ISO_ERRS)) {
+			urb->error_count++;
+			if (t & FOTG210_ISOC_BUF_ERR)
+				desc->status = usb_pipein(urb->pipe)
+					? -ENOSR  /* hc couldn't read */
+					: -ECOMM; /* hc couldn't write */
+			else if (t & FOTG210_ISOC_BABBLE)
+				desc->status = -EOVERFLOW;
+			else /* (t & FOTG210_ISOC_XACTERR) */
+				desc->status = -EPROTO;
+
+			/* HC need not update length with this error */
+			if (!(t & FOTG210_ISOC_BABBLE)) {
+				desc->actual_length =
+					fotg210_itdlen(urb, desc, t);
+				urb->actual_length += desc->actual_length;
+			}
+		} else if (likely((t & FOTG210_ISOC_ACTIVE) == 0)) {
+			desc->status = 0;
+			desc->actual_length = fotg210_itdlen(urb, desc, t);
+			urb->actual_length += desc->actual_length;
+		} else {
+			/* URB was too late */
+			desc->status = -EXDEV;
+		}
+	}
+
+	/* handle completion now? */
+	if (likely((urb_index + 1) != urb->number_of_packets))
+		goto done;
+
+	/* ASSERT: it's really the last itd for this urb
+	list_for_each_entry (itd, &stream->td_list, itd_list)
+		BUG_ON (itd->urb == urb);
+	 */
+
+	/* give urb back to the driver; completion often (re)submits */
+	dev = urb->dev;
+	fotg210_urb_done(fotg210, urb, 0);
+	retval = true;
+	urb = NULL;
+
+	--fotg210->isoc_count;
+	disable_periodic(fotg210);
+
+	if (unlikely(list_is_singular(&stream->td_list))) {
+		fotg210_to_hcd(fotg210)->self.bandwidth_allocated
+				-= stream->bandwidth;
+		fotg210_vdbg(fotg210,
+			"deschedule devp %s ep%d%s-iso\n",
+			dev->devpath, stream->bEndpointAddress & 0x0f,
+			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+	}
+
+done:
+	itd->urb = NULL;
+
+	/* Add to the end of the free list for later reuse */
+	list_move_tail(&itd->itd_list, &stream->free_list);
+
+	/* Recycle the iTDs when the pipeline is empty (ep no longer in use) */
+	if (list_empty(&stream->td_list)) {
+		list_splice_tail_init(&stream->free_list,
+				&fotg210->cached_itd_list);
+		start_free_itds(fotg210);
+	}
+
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
+	gfp_t mem_flags)
+{
+	int			status = -EINVAL;
+	unsigned long		flags;
+	struct fotg210_iso_stream	*stream;
+
+	/* Get iso_stream head */
+	stream = iso_stream_find(fotg210, urb);
+	if (unlikely(stream == NULL)) {
+		fotg210_dbg(fotg210, "can't get iso stream\n");
+		return -ENOMEM;
+	}
+	if (unlikely(urb->interval != stream->interval &&
+		      fotg210_port_speed(fotg210, 0) ==
+				USB_PORT_STAT_HIGH_SPEED)) {
+			fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n",
+				stream->interval, urb->interval);
+			goto done;
+	}
+
+#ifdef FOTG210_URB_TRACE
+	fotg210_dbg(fotg210,
+		"%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n",
+		__func__, urb->dev->devpath, urb,
+		usb_pipeendpoint(urb->pipe),
+		usb_pipein(urb->pipe) ? "in" : "out",
+		urb->transfer_buffer_length,
+		urb->number_of_packets, urb->interval,
+		stream);
+#endif
+
+	/* allocate ITDs w/o locking anything */
+	status = itd_urb_transaction(stream, fotg210, urb, mem_flags);
+	if (unlikely(status < 0)) {
+		fotg210_dbg(fotg210, "can't init itds\n");
+		goto done;
+	}
+
+	/* schedule ... need to lock */
+	spin_lock_irqsave(&fotg210->lock, flags);
+	if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) {
+		status = -ESHUTDOWN;
+		goto done_not_linked;
+	}
+	status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb);
+	if (unlikely(status))
+		goto done_not_linked;
+	status = iso_stream_schedule(fotg210, urb, stream);
+	if (likely(status == 0))
+		itd_link_urb(fotg210, urb, fotg210->periodic_size << 3, stream);
+	else
+		usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
+ done_not_linked:
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+ done:
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void scan_isoc(struct fotg210_hcd *fotg210)
+{
+	unsigned	uf, now_frame, frame;
+	unsigned	fmask = fotg210->periodic_size - 1;
+	bool		modified, live;
+
+	/*
+	 * When running, scan from last scan point up to "now"
+	 * else clean up by scanning everything that's left.
+	 * Touches as few pages as possible:  cache-friendly.
+	 */
+	if (fotg210->rh_state >= FOTG210_RH_RUNNING) {
+		uf = fotg210_read_frame_index(fotg210);
+		now_frame = (uf >> 3) & fmask;
+		live = true;
+	} else  {
+		now_frame = (fotg210->next_frame - 1) & fmask;
+		live = false;
+	}
+	fotg210->now_frame = now_frame;
+
+	frame = fotg210->next_frame;
+	for (;;) {
+		union fotg210_shadow	q, *q_p;
+		__hc32			type, *hw_p;
+
+restart:
+		/* scan each element in frame's queue for completions */
+		q_p = &fotg210->pshadow[frame];
+		hw_p = &fotg210->periodic[frame];
+		q.ptr = q_p->ptr;
+		type = Q_NEXT_TYPE(fotg210, *hw_p);
+		modified = false;
+
+		while (q.ptr != NULL) {
+			switch (hc32_to_cpu(fotg210, type)) {
+			case Q_TYPE_ITD:
+				/* If this ITD is still active, leave it for
+				 * later processing ... check the next entry.
+				 * No need to check for activity unless the
+				 * frame is current.
+				 */
+				if (frame == now_frame && live) {
+					rmb();
+					for (uf = 0; uf < 8; uf++) {
+						if (q.itd->hw_transaction[uf] &
+							    ITD_ACTIVE(fotg210))
+							break;
+					}
+					if (uf < 8) {
+						q_p = &q.itd->itd_next;
+						hw_p = &q.itd->hw_next;
+						type = Q_NEXT_TYPE(fotg210,
+							q.itd->hw_next);
+						q = *q_p;
+						break;
+					}
+				}
+
+				/* Take finished ITDs out of the schedule
+				 * and process them:  recycle, maybe report
+				 * URB completion.  HC won't cache the
+				 * pointer for much longer, if at all.
+				 */
+				*q_p = q.itd->itd_next;
+				*hw_p = q.itd->hw_next;
+				type = Q_NEXT_TYPE(fotg210, q.itd->hw_next);
+				wmb();
+				modified = itd_complete(fotg210, q.itd);
+				q = *q_p;
+				break;
+			default:
+				fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n",
+					type, frame, q.ptr);
+				/* FALL THROUGH */
+			case Q_TYPE_QH:
+			case Q_TYPE_FSTN:
+				/* End of the iTDs and siTDs */
+				q.ptr = NULL;
+				break;
+			}
+
+			/* assume completion callbacks modify the queue */
+			if (unlikely(modified && fotg210->isoc_count > 0))
+				goto restart;
+		}
+
+		/* Stop when we have reached the current frame */
+		if (frame == now_frame)
+			break;
+		frame = (frame + 1) & fmask;
+	}
+	fotg210->next_frame = now_frame;
+}
+/*-------------------------------------------------------------------------*/
+/*
+ * Display / Set uframe_periodic_max
+ */
+static ssize_t show_uframe_periodic_max(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct fotg210_hcd		*fotg210;
+	int			n;
+
+	fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev)));
+	n = scnprintf(buf, PAGE_SIZE, "%d\n", fotg210->uframe_periodic_max);
+	return n;
+}
+
+
+static ssize_t store_uframe_periodic_max(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct fotg210_hcd	*fotg210;
+	unsigned		uframe_periodic_max;
+	unsigned		frame, uframe;
+	unsigned short		allocated_max;
+	unsigned long		flags;
+	ssize_t			ret;
+
+	fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev)));
+	if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
+		return -EINVAL;
+
+	if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
+		fotg210_info(fotg210, "rejecting invalid request for uframe_periodic_max=%u\n",
+			     uframe_periodic_max);
+		return -EINVAL;
+	}
+
+	ret = -EINVAL;
+
+	/*
+	 * lock, so that our checking does not race with possible periodic
+	 * bandwidth allocation through submitting new urbs.
+	 */
+	spin_lock_irqsave(&fotg210->lock, flags);
+
+	/*
+	 * for request to decrease max periodic bandwidth, we have to check
+	 * every microframe in the schedule to see whether the decrease is
+	 * possible.
+	 */
+	if (uframe_periodic_max < fotg210->uframe_periodic_max) {
+		allocated_max = 0;
+
+		for (frame = 0; frame < fotg210->periodic_size; ++frame)
+			for (uframe = 0; uframe < 7; ++uframe)
+				allocated_max = max(allocated_max,
+						    periodic_usecs(fotg210, frame, uframe));
+
+		if (allocated_max > uframe_periodic_max) {
+			fotg210_info(fotg210,
+				"cannot decrease uframe_periodic_max becase "
+				"periodic bandwidth is already allocated "
+				"(%u > %u)\n",
+				allocated_max, uframe_periodic_max);
+			goto out_unlock;
+		}
+	}
+
+	/* increasing is always ok */
+
+	fotg210_info(fotg210, "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n",
+		     100 * uframe_periodic_max/125, uframe_periodic_max);
+
+	if (uframe_periodic_max != 100)
+		fotg210_warn(fotg210, "max periodic bandwidth set is non-standard\n");
+
+	fotg210->uframe_periodic_max = uframe_periodic_max;
+	ret = count;
+
+out_unlock:
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	return ret;
+}
+
+static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max,
+		   store_uframe_periodic_max);
+
+static inline int create_sysfs_files(struct fotg210_hcd *fotg210)
+{
+	struct device	*controller = fotg210_to_hcd(fotg210)->self.controller;
+	int	i = 0;
+
+	if (i)
+		goto out;
+
+	i = device_create_file(controller, &dev_attr_uframe_periodic_max);
+out:
+	return i;
+}
+
+static inline void remove_sysfs_files(struct fotg210_hcd *fotg210)
+{
+	struct device	*controller = fotg210_to_hcd(fotg210)->self.controller;
+
+	device_remove_file(controller, &dev_attr_uframe_periodic_max);
+}
+/*-------------------------------------------------------------------------*/
+
+/* On some systems, leaving remote wakeup enabled prevents system shutdown.
+ * The firmware seems to think that powering off is a wakeup event!
+ * This routine turns off remote wakeup and everything else, on all ports.
+ */
+static void fotg210_turn_off_all_ports(struct fotg210_hcd *fotg210)
+{
+	u32 __iomem *status_reg = &fotg210->regs->port_status;
+
+	fotg210_writel(fotg210, PORT_RWC_BITS, status_reg);
+}
+
+/*
+ * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
+ * Must be called with interrupts enabled and the lock not held.
+ */
+static void fotg210_silence_controller(struct fotg210_hcd *fotg210)
+{
+	fotg210_halt(fotg210);
+
+	spin_lock_irq(&fotg210->lock);
+	fotg210->rh_state = FOTG210_RH_HALTED;
+	fotg210_turn_off_all_ports(fotg210);
+	spin_unlock_irq(&fotg210->lock);
+}
+
+/* fotg210_shutdown kick in for silicon on any bus (not just pci, etc).
+ * This forcibly disables dma and IRQs, helping kexec and other cases
+ * where the next system software may expect clean state.
+ */
+static void fotg210_shutdown(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd	*fotg210 = hcd_to_fotg210(hcd);
+
+	spin_lock_irq(&fotg210->lock);
+	fotg210->shutdown = true;
+	fotg210->rh_state = FOTG210_RH_STOPPING;
+	fotg210->enabled_hrtimer_events = 0;
+	spin_unlock_irq(&fotg210->lock);
+
+	fotg210_silence_controller(fotg210);
+
+	hrtimer_cancel(&fotg210->hrtimer);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * fotg210_work is called from some interrupts, timers, and so on.
+ * it calls driver completion functions, after dropping fotg210->lock.
+ */
+static void fotg210_work(struct fotg210_hcd *fotg210)
+{
+	/* another CPU may drop fotg210->lock during a schedule scan while
+	 * it reports urb completions.  this flag guards against bogus
+	 * attempts at re-entrant schedule scanning.
+	 */
+	if (fotg210->scanning) {
+		fotg210->need_rescan = true;
+		return;
+	}
+	fotg210->scanning = true;
+
+ rescan:
+	fotg210->need_rescan = false;
+	if (fotg210->async_count)
+		scan_async(fotg210);
+	if (fotg210->intr_count > 0)
+		scan_intr(fotg210);
+	if (fotg210->isoc_count > 0)
+		scan_isoc(fotg210);
+	if (fotg210->need_rescan)
+		goto rescan;
+	fotg210->scanning = false;
+
+	/* the IO watchdog guards against hardware or driver bugs that
+	 * misplace IRQs, and should let us run completely without IRQs.
+	 * such lossage has been observed on both VT6202 and VT8235.
+	 */
+	turn_on_io_watchdog(fotg210);
+}
+
+/*
+ * Called when the fotg210_hcd module is removed.
+ */
+static void fotg210_stop(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+
+	fotg210_dbg(fotg210, "stop\n");
+
+	/* no more interrupts ... */
+
+	spin_lock_irq(&fotg210->lock);
+	fotg210->enabled_hrtimer_events = 0;
+	spin_unlock_irq(&fotg210->lock);
+
+	fotg210_quiesce(fotg210);
+	fotg210_silence_controller(fotg210);
+	fotg210_reset(fotg210);
+
+	hrtimer_cancel(&fotg210->hrtimer);
+	remove_sysfs_files(fotg210);
+	remove_debug_files(fotg210);
+
+	/* root hub is shut down separately (first, when possible) */
+	spin_lock_irq(&fotg210->lock);
+	end_free_itds(fotg210);
+	spin_unlock_irq(&fotg210->lock);
+	fotg210_mem_cleanup(fotg210);
+
+#ifdef	FOTG210_STATS
+	fotg210_dbg(fotg210, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
+		fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa,
+		fotg210->stats.lost_iaa);
+	fotg210_dbg(fotg210, "complete %ld unlink %ld\n",
+		fotg210->stats.complete, fotg210->stats.unlink);
+#endif
+
+	dbg_status(fotg210, "fotg210_stop completed",
+		    fotg210_readl(fotg210, &fotg210->regs->status));
+}
+
+/* one-time init, only for memory state */
+static int hcd_fotg210_init(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	u32			temp;
+	int			retval;
+	u32			hcc_params;
+	struct fotg210_qh_hw	*hw;
+
+	spin_lock_init(&fotg210->lock);
+
+	/*
+	 * keep io watchdog by default, those good HCDs could turn off it later
+	 */
+	fotg210->need_io_watchdog = 1;
+
+	hrtimer_init(&fotg210->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	fotg210->hrtimer.function = fotg210_hrtimer_func;
+	fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT;
+
+	hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
+
+	/*
+	 * by default set standard 80% (== 100 usec/uframe) max periodic
+	 * bandwidth as required by USB 2.0
+	 */
+	fotg210->uframe_periodic_max = 100;
+
+	/*
+	 * hw default: 1K periodic list heads, one per frame.
+	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+	 */
+	fotg210->periodic_size = DEFAULT_I_TDPS;
+	INIT_LIST_HEAD(&fotg210->intr_qh_list);
+	INIT_LIST_HEAD(&fotg210->cached_itd_list);
+
+	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
+		/* periodic schedule size can be smaller than default */
+		switch (FOTG210_TUNE_FLS) {
+		case 0:
+			fotg210->periodic_size = 1024;
+			break;
+		case 1:
+			fotg210->periodic_size = 512;
+			break;
+		case 2:
+			fotg210->periodic_size = 256;
+			break;
+		default:
+			BUG();
+		}
+	}
+	retval = fotg210_mem_init(fotg210, GFP_KERNEL);
+	if (retval < 0)
+		return retval;
+
+	/* controllers may cache some of the periodic schedule ... */
+	fotg210->i_thresh = 2;
+
+	/*
+	 * dedicate a qh for the async ring head, since we couldn't unlink
+	 * a 'real' qh without stopping the async schedule [4.8].  use it
+	 * as the 'reclamation list head' too.
+	 * its dummy is used in hw_alt_next of many tds, to prevent the qh
+	 * from automatically advancing to the next td after short reads.
+	 */
+	fotg210->async->qh_next.qh = NULL;
+	hw = fotg210->async->hw;
+	hw->hw_next = QH_NEXT(fotg210, fotg210->async->qh_dma);
+	hw->hw_info1 = cpu_to_hc32(fotg210, QH_HEAD);
+	hw->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT);
+	hw->hw_qtd_next = FOTG210_LIST_END(fotg210);
+	fotg210->async->qh_state = QH_STATE_LINKED;
+	hw->hw_alt_next = QTD_NEXT(fotg210, fotg210->async->dummy->qtd_dma);
+
+	/* clear interrupt enables, set irq latency */
+	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
+		log2_irq_thresh = 0;
+	temp = 1 << (16 + log2_irq_thresh);
+	if (HCC_CANPARK(hcc_params)) {
+		/* HW default park == 3, on hardware that supports it (like
+		 * NVidia and ALI silicon), maximizes throughput on the async
+		 * schedule by avoiding QH fetches between transfers.
+		 *
+		 * With fast usb storage devices and NForce2, "park" seems to
+		 * make problems:  throughput reduction (!), data errors...
+		 */
+		if (park) {
+			park = min_t(unsigned, park, 3);
+			temp |= CMD_PARK;
+			temp |= park << 8;
+		}
+		fotg210_dbg(fotg210, "park %d\n", park);
+	}
+	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
+		/* periodic schedule size can be smaller than default */
+		temp &= ~(3 << 2);
+		temp |= (FOTG210_TUNE_FLS << 2);
+	}
+	fotg210->command = temp;
+
+	/* Accept arbitrarily long scatter-gather lists */
+	if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+		hcd->self.sg_tablesize = ~0;
+	return 0;
+}
+
+/* start HC running; it's halted, hcd_fotg210_init() has been run (once) */
+static int fotg210_run(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	u32			temp;
+	u32			hcc_params;
+
+	hcd->uses_new_polling = 1;
+
+	/* EHCI spec section 4.1 */
+
+	fotg210_writel(fotg210, fotg210->periodic_dma,
+		       &fotg210->regs->frame_list);
+	fotg210_writel(fotg210, (u32)fotg210->async->qh_dma,
+		       &fotg210->regs->async_next);
+
+	/*
+	 * hcc_params controls whether fotg210->regs->segment must (!!!)
+	 * be used; it constrains QH/ITD/SITD and QTD locations.
+	 * pci_pool consistent memory always uses segment zero.
+	 * streaming mappings for I/O buffers, like pci_map_single(),
+	 * can return segments above 4GB, if the device allows.
+	 *
+	 * NOTE:  the dma mask is visible through dma_supported(), so
+	 * drivers can pass this info along ... like NETIF_F_HIGHDMA,
+	 * Scsi_Host.highmem_io, and so forth.  It's readonly to all
+	 * host side drivers though.
+	 */
+	hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
+
+	/*
+	 * Philips, Intel, and maybe others need CMD_RUN before the
+	 * root hub will detect new devices (why?); NEC doesn't
+	 */
+	fotg210->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+	fotg210->command |= CMD_RUN;
+	fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
+	dbg_cmd(fotg210, "init", fotg210->command);
+
+	/*
+	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
+	 * are explicitly handed to companion controller(s), so no TT is
+	 * involved with the root hub.  (Except where one is integrated,
+	 * and there's no companion controller unless maybe for USB OTG.)
+	 *
+	 * Turning on the CF flag will transfer ownership of all ports
+	 * from the companions to the EHCI controller.  If any of the
+	 * companions are in the middle of a port reset at the time, it
+	 * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
+	 * guarantees that no resets are in progress.  After we set CF,
+	 * a short delay lets the hardware catch up; new resets shouldn't
+	 * be started before the port switching actions could complete.
+	 */
+	down_write(&ehci_cf_port_reset_rwsem);
+	fotg210->rh_state = FOTG210_RH_RUNNING;
+	/* unblock posted writes */
+	fotg210_readl(fotg210, &fotg210->regs->command);
+	msleep(5);
+	up_write(&ehci_cf_port_reset_rwsem);
+	fotg210->last_periodic_enable = ktime_get_real();
+
+	temp = HC_VERSION(fotg210,
+			  fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
+	fotg210_info(fotg210,
+		"USB %x.%x started, EHCI %x.%02x\n",
+		((fotg210->sbrn & 0xf0)>>4), (fotg210->sbrn & 0x0f),
+		temp >> 8, temp & 0xff);
+
+	fotg210_writel(fotg210, INTR_MASK,
+		    &fotg210->regs->intr_enable); /* Turn On Interrupts */
+
+	/* GRR this is run-once init(), being done every time the HC starts.
+	 * So long as they're part of class devices, we can't do it init()
+	 * since the class device isn't created that early.
+	 */
+	create_debug_files(fotg210);
+	create_sysfs_files(fotg210);
+
+	return 0;
+}
+
+static int fotg210_setup(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+	int retval;
+
+	fotg210->regs = (void __iomem *)fotg210->caps +
+	    HC_LENGTH(fotg210,
+		      fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
+	dbg_hcs_params(fotg210, "reset");
+	dbg_hcc_params(fotg210, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	fotg210->hcs_params = fotg210_readl(fotg210,
+					    &fotg210->caps->hcs_params);
+
+	fotg210->sbrn = HCD_USB2;
+
+	/* data structure init */
+	retval = hcd_fotg210_init(hcd);
+	if (retval)
+		return retval;
+
+	retval = fotg210_halt(fotg210);
+	if (retval)
+		return retval;
+
+	fotg210_reset(fotg210);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	u32			status, masked_status, pcd_status = 0, cmd;
+	int			bh;
+
+	spin_lock(&fotg210->lock);
+
+	status = fotg210_readl(fotg210, &fotg210->regs->status);
+
+	/* e.g. cardbus physical eject */
+	if (status == ~(u32) 0) {
+		fotg210_dbg(fotg210, "device removed\n");
+		goto dead;
+	}
+
+	/*
+	 * We don't use STS_FLR, but some controllers don't like it to
+	 * remain on, so mask it out along with the other status bits.
+	 */
+	masked_status = status & (INTR_MASK | STS_FLR);
+
+	/* Shared IRQ? */
+	if (!masked_status ||
+	    unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) {
+		spin_unlock(&fotg210->lock);
+		return IRQ_NONE;
+	}
+
+	/* clear (just) interrupts */
+	fotg210_writel(fotg210, masked_status, &fotg210->regs->status);
+	cmd = fotg210_readl(fotg210, &fotg210->regs->command);
+	bh = 0;
+
+#ifdef	VERBOSE_DEBUG
+	/* unrequested/ignored: Frame List Rollover */
+	dbg_status(fotg210, "irq", status);
+#endif
+
+	/* INT, ERR, and IAA interrupt rates can be throttled */
+
+	/* normal [4.15.1.2] or error [4.15.1.1] completion */
+	if (likely((status & (STS_INT|STS_ERR)) != 0)) {
+		if (likely((status & STS_ERR) == 0))
+			COUNT(fotg210->stats.normal);
+		else
+			COUNT(fotg210->stats.error);
+		bh = 1;
+	}
+
+	/* complete the unlinking of some qh [4.15.2.3] */
+	if (status & STS_IAA) {
+
+		/* Turn off the IAA watchdog */
+		fotg210->enabled_hrtimer_events &=
+			~BIT(FOTG210_HRTIMER_IAA_WATCHDOG);
+
+		/*
+		 * Mild optimization: Allow another IAAD to reset the
+		 * hrtimer, if one occurs before the next expiration.
+		 * In theory we could always cancel the hrtimer, but
+		 * tests show that about half the time it will be reset
+		 * for some other event anyway.
+		 */
+		if (fotg210->next_hrtimer_event == FOTG210_HRTIMER_IAA_WATCHDOG)
+			++fotg210->next_hrtimer_event;
+
+		/* guard against (alleged) silicon errata */
+		if (cmd & CMD_IAAD)
+			fotg210_dbg(fotg210, "IAA with IAAD still set?\n");
+		if (fotg210->async_iaa) {
+			COUNT(fotg210->stats.iaa);
+			end_unlink_async(fotg210);
+		} else
+			fotg210_dbg(fotg210, "IAA with nothing unlinked?\n");
+	}
+
+	/* remote wakeup [4.3.1] */
+	if (status & STS_PCD) {
+		int pstatus;
+		u32 __iomem *status_reg = &fotg210->regs->port_status;
+
+		/* kick root hub later */
+		pcd_status = status;
+
+		/* resume root hub? */
+		if (fotg210->rh_state == FOTG210_RH_SUSPENDED)
+			usb_hcd_resume_root_hub(hcd);
+
+		pstatus = fotg210_readl(fotg210, status_reg);
+
+		if (test_bit(0, &fotg210->suspended_ports) &&
+				((pstatus & PORT_RESUME) ||
+					!(pstatus & PORT_SUSPEND)) &&
+				(pstatus & PORT_PE) &&
+				fotg210->reset_done[0] == 0) {
+
+			/* start 20 msec resume signaling from this port,
+			 * and make khubd collect PORT_STAT_C_SUSPEND to
+			 * stop that signaling.  Use 5 ms extra for safety,
+			 * like usb_port_resume() does.
+			 */
+			fotg210->reset_done[0] = jiffies + msecs_to_jiffies(25);
+			set_bit(0, &fotg210->resuming_ports);
+			fotg210_dbg(fotg210, "port 1 remote wakeup\n");
+			mod_timer(&hcd->rh_timer, fotg210->reset_done[0]);
+		}
+	}
+
+	/* PCI errors [4.15.2.4] */
+	if (unlikely((status & STS_FATAL) != 0)) {
+		fotg210_err(fotg210, "fatal error\n");
+		dbg_cmd(fotg210, "fatal", cmd);
+		dbg_status(fotg210, "fatal", status);
+dead:
+		usb_hc_died(hcd);
+
+		/* Don't let the controller do anything more */
+		fotg210->shutdown = true;
+		fotg210->rh_state = FOTG210_RH_STOPPING;
+		fotg210->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
+		fotg210_writel(fotg210, fotg210->command,
+			       &fotg210->regs->command);
+		fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
+		fotg210_handle_controller_death(fotg210);
+
+		/* Handle completions when the controller stops */
+		bh = 0;
+	}
+
+	if (bh)
+		fotg210_work(fotg210);
+	spin_unlock(&fotg210->lock);
+	if (pcd_status)
+		usb_hcd_poll_rh_status(hcd);
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * non-error returns are a promise to giveback() the urb later
+ * we drop ownership so next owner (or urb unlink) can get it
+ *
+ * urb + dev is in hcd.self.controller.urb_list
+ * we're queueing TDs onto software and hardware lists
+ *
+ * hcd-specific init for hcpriv hasn't been done yet
+ *
+ * NOTE:  control, bulk, and interrupt share the same code to append TDs
+ * to a (possibly active) QH, and the same QH scanning code.
+ */
+static int fotg210_urb_enqueue(
+	struct usb_hcd	*hcd,
+	struct urb	*urb,
+	gfp_t		mem_flags
+) {
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	struct list_head	qtd_list;
+
+	INIT_LIST_HEAD(&qtd_list);
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		/* qh_completions() code doesn't handle all the fault cases
+		 * in multi-TD control transfers.  Even 1KB is rare anyway.
+		 */
+		if (urb->transfer_buffer_length > (16 * 1024))
+			return -EMSGSIZE;
+		/* FALLTHROUGH */
+	/* case PIPE_BULK: */
+	default:
+		if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags))
+			return -ENOMEM;
+		return submit_async(fotg210, urb, &qtd_list, mem_flags);
+
+	case PIPE_INTERRUPT:
+		if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags))
+			return -ENOMEM;
+		return intr_submit(fotg210, urb, &qtd_list, mem_flags);
+
+	case PIPE_ISOCHRONOUS:
+		return itd_submit(fotg210, urb, mem_flags);
+	}
+}
+
+/* remove from hardware lists
+ * completions normally happen asynchronously
+ */
+
+static int fotg210_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	struct fotg210_qh		*qh;
+	unsigned long		flags;
+	int			rc;
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+	if (rc)
+		goto done;
+
+	switch (usb_pipetype(urb->pipe)) {
+	/* case PIPE_CONTROL: */
+	/* case PIPE_BULK:*/
+	default:
+		qh = (struct fotg210_qh *) urb->hcpriv;
+		if (!qh)
+			break;
+		switch (qh->qh_state) {
+		case QH_STATE_LINKED:
+		case QH_STATE_COMPLETING:
+			start_unlink_async(fotg210, qh);
+			break;
+		case QH_STATE_UNLINK:
+		case QH_STATE_UNLINK_WAIT:
+			/* already started */
+			break;
+		case QH_STATE_IDLE:
+			/* QH might be waiting for a Clear-TT-Buffer */
+			qh_completions(fotg210, qh);
+			break;
+		}
+		break;
+
+	case PIPE_INTERRUPT:
+		qh = (struct fotg210_qh *) urb->hcpriv;
+		if (!qh)
+			break;
+		switch (qh->qh_state) {
+		case QH_STATE_LINKED:
+		case QH_STATE_COMPLETING:
+			start_unlink_intr(fotg210, qh);
+			break;
+		case QH_STATE_IDLE:
+			qh_completions(fotg210, qh);
+			break;
+		default:
+			fotg210_dbg(fotg210, "bogus qh %p state %d\n",
+					qh, qh->qh_state);
+			goto done;
+		}
+		break;
+
+	case PIPE_ISOCHRONOUS:
+		/* itd... */
+
+		/* wait till next completion, do it then. */
+		/* completion irqs can wait up to 1024 msec, */
+		break;
+	}
+done:
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* bulk qh holds the data toggle */
+
+static void
+fotg210_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	unsigned long		flags;
+	struct fotg210_qh		*qh, *tmp;
+
+	/* ASSERT:  any requests/urbs are being unlinked */
+	/* ASSERT:  nobody can be submitting urbs for this any more */
+
+rescan:
+	spin_lock_irqsave(&fotg210->lock, flags);
+	qh = ep->hcpriv;
+	if (!qh)
+		goto done;
+
+	/* endpoints can be iso streams.  for now, we don't
+	 * accelerate iso completions ... so spin a while.
+	 */
+	if (qh->hw == NULL) {
+		struct fotg210_iso_stream	*stream = ep->hcpriv;
+
+		if (!list_empty(&stream->td_list))
+			goto idle_timeout;
+
+		/* BUG_ON(!list_empty(&stream->free_list)); */
+		kfree(stream);
+		goto done;
+	}
+
+	if (fotg210->rh_state < FOTG210_RH_RUNNING)
+		qh->qh_state = QH_STATE_IDLE;
+	switch (qh->qh_state) {
+	case QH_STATE_LINKED:
+	case QH_STATE_COMPLETING:
+		for (tmp = fotg210->async->qh_next.qh;
+				tmp && tmp != qh;
+				tmp = tmp->qh_next.qh)
+			continue;
+		/* periodic qh self-unlinks on empty, and a COMPLETING qh
+		 * may already be unlinked.
+		 */
+		if (tmp)
+			start_unlink_async(fotg210, qh);
+		/* FALL THROUGH */
+	case QH_STATE_UNLINK:		/* wait for hw to finish? */
+	case QH_STATE_UNLINK_WAIT:
+idle_timeout:
+		spin_unlock_irqrestore(&fotg210->lock, flags);
+		schedule_timeout_uninterruptible(1);
+		goto rescan;
+	case QH_STATE_IDLE:		/* fully unlinked */
+		if (qh->clearing_tt)
+			goto idle_timeout;
+		if (list_empty(&qh->qtd_list)) {
+			qh_destroy(fotg210, qh);
+			break;
+		}
+		/* else FALL THROUGH */
+	default:
+		/* caller was supposed to have unlinked any requests;
+		 * that's not our job.  just leak this memory.
+		 */
+		fotg210_err(fotg210, "qh %p (#%02x) state %d%s\n",
+			qh, ep->desc.bEndpointAddress, qh->qh_state,
+			list_empty(&qh->qtd_list) ? "" : "(has tds)");
+		break;
+	}
+ done:
+	ep->hcpriv = NULL;
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+}
+
+static void
+fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	struct fotg210_qh		*qh;
+	int			eptype = usb_endpoint_type(&ep->desc);
+	int			epnum = usb_endpoint_num(&ep->desc);
+	int			is_out = usb_endpoint_dir_out(&ep->desc);
+	unsigned long		flags;
+
+	if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
+		return;
+
+	spin_lock_irqsave(&fotg210->lock, flags);
+	qh = ep->hcpriv;
+
+	/* For Bulk and Interrupt endpoints we maintain the toggle state
+	 * in the hardware; the toggle bits in udev aren't used at all.
+	 * When an endpoint is reset by usb_clear_halt() we must reset
+	 * the toggle bit in the QH.
+	 */
+	if (qh) {
+		usb_settoggle(qh->dev, epnum, is_out, 0);
+		if (!list_empty(&qh->qtd_list)) {
+			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
+		} else if (qh->qh_state == QH_STATE_LINKED ||
+				qh->qh_state == QH_STATE_COMPLETING) {
+
+			/* The toggle value in the QH can't be updated
+			 * while the QH is active.  Unlink it now;
+			 * re-linking will call qh_refresh().
+			 */
+			if (eptype == USB_ENDPOINT_XFER_BULK)
+				start_unlink_async(fotg210, qh);
+			else
+				start_unlink_intr(fotg210, qh);
+		}
+	}
+	spin_unlock_irqrestore(&fotg210->lock, flags);
+}
+
+static int fotg210_get_frame(struct usb_hcd *hcd)
+{
+	struct fotg210_hcd		*fotg210 = hcd_to_fotg210(hcd);
+	return (fotg210_read_frame_index(fotg210) >> 3) %
+		fotg210->periodic_size;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+ * because its registers (and irq) are shared between host/gadget/otg
+ * functions  and in order to facilitate role switching we cannot
+ * give the fotg210 driver exclusive access to those.
+ */
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+
+static const struct hc_driver fotg210_fotg210_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Faraday USB2.0 Host Controller",
+	.hcd_priv_size		= sizeof(struct fotg210_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= fotg210_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= hcd_fotg210_init,
+	.start			= fotg210_run,
+	.stop			= fotg210_stop,
+	.shutdown		= fotg210_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= fotg210_urb_enqueue,
+	.urb_dequeue		= fotg210_urb_dequeue,
+	.endpoint_disable	= fotg210_endpoint_disable,
+	.endpoint_reset		= fotg210_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= fotg210_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= fotg210_hub_status_data,
+	.hub_control		= fotg210_hub_control,
+	.bus_suspend		= fotg210_bus_suspend,
+	.bus_resume		= fotg210_bus_resume,
+
+	.relinquish_port	= fotg210_relinquish_port,
+	.port_handed_over	= fotg210_port_handed_over,
+
+	.clear_tt_buffer_complete = fotg210_clear_tt_buffer_complete,
+};
+
+static void fotg210_init(struct fotg210_hcd *fotg210)
+{
+	u32 value;
+
+	iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
+		  &fotg210->regs->gmir);
+
+	value = ioread32(&fotg210->regs->otgcsr);
+	value &= ~OTGCSR_A_BUS_DROP;
+	value |= OTGCSR_A_BUS_REQ;
+	iowrite32(value, &fotg210->regs->otgcsr);
+}
+
+/**
+ * fotg210_hcd_probe - initialize faraday FOTG210 HCDs
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ */
+static int fotg210_hcd_probe(struct platform_device *pdev)
+{
+	struct device			*dev = &pdev->dev;
+	struct usb_hcd			*hcd;
+	struct resource			*res;
+	int				irq;
+	int				retval = -ENODEV;
+	struct fotg210_hcd		*fotg210;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	pdev->dev.power.power_state = PMSG_ON;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			dev_name(dev));
+		return -ENODEV;
+	}
+
+	irq = res->start;
+
+	hcd = usb_create_hcd(&fotg210_fotg210_hc_driver, dev,
+			dev_name(dev));
+	if (!hcd) {
+		dev_err(dev, "failed to create hcd with err %d\n", retval);
+		retval = -ENOMEM;
+		goto fail_create_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			dev_name(dev));
+		retval = -ENODEV;
+		goto fail_request_resource;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->has_tt = 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				fotg210_fotg210_hc_driver.description)) {
+		dev_dbg(dev, "controller already in use\n");
+		retval = -EBUSY;
+		goto fail_request_resource;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			dev_name(dev));
+		retval = -ENODEV;
+		goto fail_request_resource;
+	}
+
+	hcd->regs = ioremap_nocache(res->start, resource_size(res));
+	if (hcd->regs == NULL) {
+		dev_dbg(dev, "error mapping memory\n");
+		retval = -EFAULT;
+		goto fail_ioremap;
+	}
+
+	fotg210 = hcd_to_fotg210(hcd);
+
+	fotg210->caps = hcd->regs;
+
+	retval = fotg210_setup(hcd);
+	if (retval)
+		goto fail_add_hcd;
+
+	fotg210_init(fotg210);
+
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (retval) {
+		dev_err(dev, "failed to add hcd with err %d\n", retval);
+		goto fail_add_hcd;
+	}
+
+	return retval;
+
+fail_add_hcd:
+	iounmap(hcd->regs);
+fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+fail_request_resource:
+	usb_put_hcd(hcd);
+fail_create_hcd:
+	dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
+	return retval;
+}
+
+/**
+ * fotg210_hcd_remove - shutdown processing for EHCI HCDs
+ * @dev: USB Host Controller being removed
+ *
+ */
+static int fotg210_hcd_remove(struct platform_device *pdev)
+{
+	struct device *dev	= &pdev->dev;
+	struct usb_hcd *hcd	= dev_get_drvdata(dev);
+
+	if (!hcd)
+		return 0;
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver fotg210_hcd_driver = {
+	.driver = {
+		.name   = "fotg210-hcd",
+	},
+	.probe  = fotg210_hcd_probe,
+	.remove = fotg210_hcd_remove,
+};
+
+static int __init fotg210_hcd_init(void)
+{
+	int retval = 0;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+	if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
+			test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
+		pr_warn(KERN_WARNING "Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n");
+
+	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n",
+		 hcd_name,
+		 sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd),
+		 sizeof(struct fotg210_itd));
+
+#ifdef DEBUG
+	fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root);
+	if (!fotg210_debug_root) {
+		retval = -ENOENT;
+		goto err_debug;
+	}
+#endif
+
+	retval = platform_driver_register(&fotg210_hcd_driver);
+	if (retval < 0)
+		goto clean;
+	return retval;
+
+	platform_driver_unregister(&fotg210_hcd_driver);
+clean:
+#ifdef DEBUG
+	debugfs_remove(fotg210_debug_root);
+	fotg210_debug_root = NULL;
+err_debug:
+#endif
+	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+	return retval;
+}
+module_init(fotg210_hcd_init);
+
+static void __exit fotg210_hcd_cleanup(void)
+{
+	platform_driver_unregister(&fotg210_hcd_driver);
+#ifdef DEBUG
+	debugfs_remove(fotg210_debug_root);
+#endif
+	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+}
+module_exit(fotg210_hcd_cleanup);
diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h
new file mode 100644
index 0000000..8920f9d
--- /dev/null
+++ b/drivers/usb/host/fotg210.h
@@ -0,0 +1,750 @@
+#ifndef __LINUX_FOTG210_H
+#define __LINUX_FOTG210_H
+
+/* definitions used for the EHCI driver */
+
+/*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given FOTG210_BIG_ENDIAN_DESC), depending on
+ * the host controller implementation.
+ *
+ * To facilitate the strongest possible byte-order checking from "sparse"
+ * and so on, we use __leXX unless that's not practical.
+ */
+#define __hc32	__le32
+#define __hc16	__le16
+
+/* statistics can be kept for tuning/monitoring */
+struct fotg210_stats {
+	/* irq usage */
+	unsigned long		normal;
+	unsigned long		error;
+	unsigned long		iaa;
+	unsigned long		lost_iaa;
+
+	/* termination of urbs from core */
+	unsigned long		complete;
+	unsigned long		unlink;
+};
+
+/* fotg210_hcd->lock guards shared data against other CPUs:
+ *   fotg210_hcd:	async, unlink, periodic (and shadow), ...
+ *   usb_host_endpoint: hcpriv
+ *   fotg210_qh:	qh_next, qtd_list
+ *   fotg210_qtd:	qtd_list
+ *
+ * Also, hold this lock when talking to HC registers or
+ * when updating hw_* fields in shared qh/qtd/... structures.
+ */
+
+#define	FOTG210_MAX_ROOT_PORTS	1		/* see HCS_N_PORTS */
+
+/*
+ * fotg210_rh_state values of FOTG210_RH_RUNNING or above mean that the
+ * controller may be doing DMA.  Lower values mean there's no DMA.
+ */
+enum fotg210_rh_state {
+	FOTG210_RH_HALTED,
+	FOTG210_RH_SUSPENDED,
+	FOTG210_RH_RUNNING,
+	FOTG210_RH_STOPPING
+};
+
+/*
+ * Timer events, ordered by increasing delay length.
+ * Always update event_delays_ns[] and event_handlers[] (defined in
+ * ehci-timer.c) in parallel with this list.
+ */
+enum fotg210_hrtimer_event {
+	FOTG210_HRTIMER_POLL_ASS,	/* Poll for async schedule off */
+	FOTG210_HRTIMER_POLL_PSS,	/* Poll for periodic schedule off */
+	FOTG210_HRTIMER_POLL_DEAD,	/* Wait for dead controller to stop */
+	FOTG210_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
+	FOTG210_HRTIMER_FREE_ITDS,	/* Wait for unused iTDs and siTDs */
+	FOTG210_HRTIMER_ASYNC_UNLINKS,	/* Unlink empty async QHs */
+	FOTG210_HRTIMER_IAA_WATCHDOG,	/* Handle lost IAA interrupts */
+	FOTG210_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */
+	FOTG210_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+	FOTG210_HRTIMER_IO_WATCHDOG,	/* Check for missing IRQs */
+	FOTG210_HRTIMER_NUM_EVENTS	/* Must come last */
+};
+#define FOTG210_HRTIMER_NO_EVENT	99
+
+struct fotg210_hcd {			/* one per controller */
+	/* timing support */
+	enum fotg210_hrtimer_event	next_hrtimer_event;
+	unsigned		enabled_hrtimer_events;
+	ktime_t			hr_timeouts[FOTG210_HRTIMER_NUM_EVENTS];
+	struct hrtimer		hrtimer;
+
+	int			PSS_poll_count;
+	int			ASS_poll_count;
+	int			died_poll_count;
+
+	/* glue to PCI and HCD framework */
+	struct fotg210_caps __iomem *caps;
+	struct fotg210_regs __iomem *regs;
+	struct fotg210_dbg_port __iomem *debug;
+
+	__u32			hcs_params;	/* cached register copy */
+	spinlock_t		lock;
+	enum fotg210_rh_state	rh_state;
+
+	/* general schedule support */
+	bool			scanning:1;
+	bool			need_rescan:1;
+	bool			intr_unlinking:1;
+	bool			async_unlinking:1;
+	bool			shutdown:1;
+	struct fotg210_qh		*qh_scan_next;
+
+	/* async schedule support */
+	struct fotg210_qh		*async;
+	struct fotg210_qh		*dummy;		/* For AMD quirk use */
+	struct fotg210_qh		*async_unlink;
+	struct fotg210_qh		*async_unlink_last;
+	struct fotg210_qh		*async_iaa;
+	unsigned		async_unlink_cycle;
+	unsigned		async_count;	/* async activity count */
+
+	/* periodic schedule support */
+#define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
+	unsigned		periodic_size;
+	__hc32			*periodic;	/* hw periodic table */
+	dma_addr_t		periodic_dma;
+	struct list_head	intr_qh_list;
+	unsigned		i_thresh;	/* uframes HC might cache */
+
+	union fotg210_shadow	*pshadow;	/* mirror hw periodic table */
+	struct fotg210_qh		*intr_unlink;
+	struct fotg210_qh		*intr_unlink_last;
+	unsigned		intr_unlink_cycle;
+	unsigned		now_frame;	/* frame from HC hardware */
+	unsigned		next_frame;	/* scan periodic, start here */
+	unsigned		intr_count;	/* intr activity count */
+	unsigned		isoc_count;	/* isoc activity count */
+	unsigned		periodic_count;	/* periodic activity count */
+	/* max periodic time per uframe */
+	unsigned		uframe_periodic_max;
+
+
+	/* list of itds completed while now_frame was still active */
+	struct list_head	cached_itd_list;
+	struct fotg210_itd	*last_itd_to_free;
+
+	/* per root hub port */
+	unsigned long		reset_done[FOTG210_MAX_ROOT_PORTS];
+
+	/* bit vectors (one bit per port) */
+	unsigned long		bus_suspended;		/* which ports were
+			already suspended at the start of a bus suspend */
+	unsigned long		companion_ports;	/* which ports are
+			dedicated to the companion controller */
+	unsigned long		owned_ports;		/* which ports are
+			owned by the companion during a bus suspend */
+	unsigned long		port_c_suspend;		/* which ports have
+			the change-suspend feature turned on */
+	unsigned long		suspended_ports;	/* which ports are
+			suspended */
+	unsigned long		resuming_ports;		/* which ports have
+			started to resume */
+
+	/* per-HC memory pools (could be per-bus, but ...) */
+	struct dma_pool		*qh_pool;	/* qh per active urb */
+	struct dma_pool		*qtd_pool;	/* one or more per qh */
+	struct dma_pool		*itd_pool;	/* itd per iso urb */
+
+	unsigned		random_frame;
+	unsigned long		next_statechange;
+	ktime_t			last_periodic_enable;
+	u32			command;
+
+	/* SILICON QUIRKS */
+	unsigned		need_io_watchdog:1;
+	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
+
+	u8			sbrn;		/* packed release number */
+
+	/* irq statistics */
+#ifdef FOTG210_STATS
+	struct fotg210_stats	stats;
+#	define COUNT(x) ((x)++)
+#else
+#	define COUNT(x)
+#endif
+
+	/* debug files */
+#ifdef DEBUG
+	struct dentry		*debug_dir;
+#endif
+};
+
+/* convert between an HCD pointer and the corresponding FOTG210_HCD */
+static inline struct fotg210_hcd *hcd_to_fotg210(struct usb_hcd *hcd)
+{
+	return (struct fotg210_hcd *)(hcd->hcd_priv);
+}
+static inline struct usb_hcd *fotg210_to_hcd(struct fotg210_hcd *fotg210)
+{
+	return container_of((void *) fotg210, struct usb_hcd, hcd_priv);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
+
+/* Section 2.2 Host Controller Capability Registers */
+struct fotg210_caps {
+	/* these fields are specified as 8 and 16 bit registers,
+	 * but some hosts can't perform 8 or 16 bit PCI accesses.
+	 * some hosts treat caplength and hciversion as parts of a 32-bit
+	 * register, others treat them as two separate registers, this
+	 * affects the memory map for big endian controllers.
+	 */
+	u32		hc_capbase;
+#define HC_LENGTH(fotg210, p)	(0x00ff&((p) >> /* bits 7:0 / offset 00h */ \
+				(fotg210_big_endian_capbase(fotg210) ? 24 : 0)))
+#define HC_VERSION(fotg210, p)	(0xffff&((p) >> /* bits 31:16 / offset 02h */ \
+				(fotg210_big_endian_capbase(fotg210) ? 0 : 16)))
+	u32		hcs_params;     /* HCSPARAMS - offset 0x4 */
+#define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
+
+	u32		hcc_params;	/* HCCPARAMS - offset 0x8 */
+#define HCC_CANPARK(p)		((p)&(1 << 2))  /* true: can park on async qh */
+#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1))  /* true: periodic_size changes*/
+	u8		portroute[8];	 /* nibbles for routing - offset 0xC */
+};
+
+
+/* Section 2.3 Host Controller Operational Registers */
+struct fotg210_regs {
+
+	/* USBCMD: offset 0x00 */
+	u32		command;
+
+/* EHCI 1.1 addendum */
+/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
+#define CMD_PARK	(1<<11)		/* enable "park" on async qh */
+#define CMD_PARK_CNT(c)	(((c)>>8)&3)	/* how many transfers to park for */
+#define CMD_IAAD	(1<<6)		/* "doorbell" interrupt async advance */
+#define CMD_ASE		(1<<5)		/* async schedule enable */
+#define CMD_PSE		(1<<4)		/* periodic schedule enable */
+/* 3:2 is periodic frame list size */
+#define CMD_RESET	(1<<1)		/* reset HC not bus */
+#define CMD_RUN		(1<<0)		/* start/stop HC */
+
+	/* USBSTS: offset 0x04 */
+	u32		status;
+#define STS_ASS		(1<<15)		/* Async Schedule Status */
+#define STS_PSS		(1<<14)		/* Periodic Schedule Status */
+#define STS_RECL	(1<<13)		/* Reclamation */
+#define STS_HALT	(1<<12)		/* Not running (any reason) */
+/* some bits reserved */
+	/* these STS_* flags are also intr_enable bits (USBINTR) */
+#define STS_IAA		(1<<5)		/* Interrupted on async advance */
+#define STS_FATAL	(1<<4)		/* such as some PCI access errors */
+#define STS_FLR		(1<<3)		/* frame list rolled over */
+#define STS_PCD		(1<<2)		/* port change detect */
+#define STS_ERR		(1<<1)		/* "error" completion (overflow, ...) */
+#define STS_INT		(1<<0)		/* "normal" completion (short, ...) */
+
+	/* USBINTR: offset 0x08 */
+	u32		intr_enable;
+
+	/* FRINDEX: offset 0x0C */
+	u32		frame_index;	/* current microframe number */
+	/* CTRLDSSEGMENT: offset 0x10 */
+	u32		segment;	/* address bits 63:32 if needed */
+	/* PERIODICLISTBASE: offset 0x14 */
+	u32		frame_list;	/* points to periodic list */
+	/* ASYNCLISTADDR: offset 0x18 */
+	u32		async_next;	/* address of next async queue head */
+
+	u32	reserved1;
+	/* PORTSC: offset 0x20 */
+	u32	port_status;
+/* 31:23 reserved */
+#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10))	/* USB 1.1 device */
+#define PORT_RESET	(1<<8)		/* reset port */
+#define PORT_SUSPEND	(1<<7)		/* suspend port */
+#define PORT_RESUME	(1<<6)		/* resume it */
+#define PORT_PEC	(1<<3)		/* port enable change */
+#define PORT_PE		(1<<2)		/* port enable */
+#define PORT_CSC	(1<<1)		/* connect status change */
+#define PORT_CONNECT	(1<<0)		/* device connected */
+#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC)
+	u32     reserved2[19];
+
+	/* OTGCSR: offet 0x70 */
+	u32     otgcsr;
+#define OTGCSR_HOST_SPD_TYP     (3 << 22)
+#define OTGCSR_A_BUS_DROP	(1 << 5)
+#define OTGCSR_A_BUS_REQ	(1 << 4)
+
+	/* OTGISR: offset 0x74 */
+	u32     otgisr;
+#define OTGISR_OVC	(1 << 10)
+
+	u32     reserved3[15];
+
+	/* GMIR: offset 0xB4 */
+	u32     gmir;
+#define GMIR_INT_POLARITY	(1 << 3) /*Active High*/
+#define GMIR_MHC_INT		(1 << 2)
+#define GMIR_MOTG_INT		(1 << 1)
+#define GMIR_MDEV_INT	(1 << 0)
+};
+
+/* Appendix C, Debug port ... intended for use with special "debug devices"
+ * that can help if there's no serial console.  (nonstandard enumeration.)
+ */
+struct fotg210_dbg_port {
+	u32	control;
+#define DBGP_OWNER	(1<<30)
+#define DBGP_ENABLED	(1<<28)
+#define DBGP_DONE	(1<<16)
+#define DBGP_INUSE	(1<<10)
+#define DBGP_ERRCODE(x)	(((x)>>7)&0x07)
+#	define DBGP_ERR_BAD	1
+#	define DBGP_ERR_SIGNAL	2
+#define DBGP_ERROR	(1<<6)
+#define DBGP_GO		(1<<5)
+#define DBGP_OUT	(1<<4)
+#define DBGP_LEN(x)	(((x)>>0)&0x0f)
+	u32	pids;
+#define DBGP_PID_GET(x)		(((x)>>16)&0xff)
+#define DBGP_PID_SET(data, tok)	(((data)<<8)|(tok))
+	u32	data03;
+	u32	data47;
+	u32	address;
+#define DBGP_EPADDR(dev, ep)	(((dev)<<8)|(ep))
+};
+
+#ifdef CONFIG_EARLY_PRINTK_DBGP
+#include <linux/init.h>
+extern int __init early_dbgp_init(char *s);
+extern struct console early_dbgp_console;
+#endif /* CONFIG_EARLY_PRINTK_DBGP */
+
+struct usb_hcd;
+
+static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd)
+{
+	return 1; /* Shouldn't this be 0? */
+}
+
+static inline int xen_dbgp_external_startup(struct usb_hcd *hcd)
+{
+	return -1;
+}
+
+#ifdef CONFIG_EARLY_PRINTK_DBGP
+/* Call backs from fotg210 host driver to fotg210 debug driver */
+extern int dbgp_external_startup(struct usb_hcd *);
+extern int dbgp_reset_prep(struct usb_hcd *hcd);
+#else
+static inline int dbgp_reset_prep(struct usb_hcd *hcd)
+{
+	return xen_dbgp_reset_prep(hcd);
+}
+static inline int dbgp_external_startup(struct usb_hcd *hcd)
+{
+	return xen_dbgp_external_startup(hcd);
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#define	QTD_NEXT(fotg210, dma)	cpu_to_hc32(fotg210, (u32)dma)
+
+/*
+ * EHCI Specification 0.95 Section 3.5
+ * QTD: describe data transfer components (buffer, direction, ...)
+ * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
+ *
+ * These are associated only with "QH" (Queue Head) structures,
+ * used with control, bulk, and interrupt transfers.
+ */
+struct fotg210_qtd {
+	/* first part defined by EHCI spec */
+	__hc32			hw_next;	/* see EHCI 3.5.1 */
+	__hc32			hw_alt_next;    /* see EHCI 3.5.2 */
+	__hc32			hw_token;	/* see EHCI 3.5.3 */
+#define	QTD_TOGGLE	(1 << 31)	/* data toggle */
+#define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
+#define	QTD_IOC		(1 << 15)	/* interrupt on complete */
+#define	QTD_CERR(tok)	(((tok)>>10) & 0x3)
+#define	QTD_PID(tok)	(((tok)>>8) & 0x3)
+#define	QTD_STS_ACTIVE	(1 << 7)	/* HC may execute this */
+#define	QTD_STS_HALT	(1 << 6)	/* halted on error */
+#define	QTD_STS_DBE	(1 << 5)	/* data buffer error (in HC) */
+#define	QTD_STS_BABBLE	(1 << 4)	/* device was babbling (qtd halted) */
+#define	QTD_STS_XACT	(1 << 3)	/* device gave illegal response */
+#define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
+#define	QTD_STS_STS	(1 << 1)	/* split transaction state */
+#define	QTD_STS_PING	(1 << 0)	/* issue PING? */
+
+#define ACTIVE_BIT(fotg210)	cpu_to_hc32(fotg210, QTD_STS_ACTIVE)
+#define HALT_BIT(fotg210)		cpu_to_hc32(fotg210, QTD_STS_HALT)
+#define STATUS_BIT(fotg210)	cpu_to_hc32(fotg210, QTD_STS_STS)
+
+	__hc32			hw_buf[5];	/* see EHCI 3.5.4 */
+	__hc32			hw_buf_hi[5];	/* Appendix B */
+
+	/* the rest is HCD-private */
+	dma_addr_t		qtd_dma;		/* qtd address */
+	struct list_head	qtd_list;		/* sw qtd list */
+	struct urb		*urb;			/* qtd's urb */
+	size_t			length;			/* length of buffer */
+} __aligned(32);
+
+/* mask NakCnt+T in qh->hw_alt_next */
+#define QTD_MASK(fotg210)	cpu_to_hc32(fotg210, ~0x1f)
+
+#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1)
+
+/*-------------------------------------------------------------------------*/
+
+/* type tag from {qh,itd,fstn}->hw_next */
+#define Q_NEXT_TYPE(fotg210, dma)	((dma) & cpu_to_hc32(fotg210, 3 << 1))
+
+/*
+ * Now the following defines are not converted using the
+ * 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.
+ */
+/* values for that type tag */
+#define Q_TYPE_ITD	(0 << 1)
+#define Q_TYPE_QH	(1 << 1)
+#define Q_TYPE_SITD	(2 << 1)
+#define Q_TYPE_FSTN	(3 << 1)
+
+/* next async queue entry, or pointer to interrupt/periodic QH */
+#define QH_NEXT(fotg210, dma) \
+	(cpu_to_hc32(fotg210, (((u32)dma)&~0x01f)|Q_TYPE_QH))
+
+/* for periodic/async schedules and qtd lists, mark end of list */
+#define FOTG210_LIST_END(fotg210) \
+	cpu_to_hc32(fotg210, 1) /* "null pointer" to hw */
+
+/*
+ * Entries in periodic shadow table are pointers to one of four kinds
+ * of data structure.  That's dictated by the hardware; a type tag is
+ * encoded in the low bits of the hardware's periodic schedule.  Use
+ * Q_NEXT_TYPE to get the tag.
+ *
+ * For entries in the async schedule, the type tag always says "qh".
+ */
+union fotg210_shadow {
+	struct fotg210_qh	*qh;		/* Q_TYPE_QH */
+	struct fotg210_itd	*itd;		/* Q_TYPE_ITD */
+	struct fotg210_fstn	*fstn;		/* Q_TYPE_FSTN */
+	__hc32			*hw_next;	/* (all types) */
+	void			*ptr;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.6
+ * QH: describes control/bulk/interrupt endpoints
+ * See Fig 3-7 "Queue Head Structure Layout".
+ *
+ * These appear in both the async and (for interrupt) periodic schedules.
+ */
+
+/* first part defined by EHCI spec */
+struct fotg210_qh_hw {
+	__hc32			hw_next;	/* see EHCI 3.6.1 */
+	__hc32			hw_info1;	/* see EHCI 3.6.2 */
+#define	QH_CONTROL_EP	(1 << 27)	/* FS/LS control endpoint */
+#define	QH_HEAD		(1 << 15)	/* Head of async reclamation list */
+#define	QH_TOGGLE_CTL	(1 << 14)	/* Data toggle control */
+#define	QH_HIGH_SPEED	(2 << 12)	/* Endpoint speed */
+#define	QH_LOW_SPEED	(1 << 12)
+#define	QH_FULL_SPEED	(0 << 12)
+#define	QH_INACTIVATE	(1 << 7)	/* Inactivate on next transaction */
+	__hc32			hw_info2;	/* see EHCI 3.6.2 */
+#define	QH_SMASK	0x000000ff
+#define	QH_CMASK	0x0000ff00
+#define	QH_HUBADDR	0x007f0000
+#define	QH_HUBPORT	0x3f800000
+#define	QH_MULT		0xc0000000
+	__hc32			hw_current;	/* qtd list - see EHCI 3.6.4 */
+
+	/* qtd overlay (hardware parts of a struct fotg210_qtd) */
+	__hc32			hw_qtd_next;
+	__hc32			hw_alt_next;
+	__hc32			hw_token;
+	__hc32			hw_buf[5];
+	__hc32			hw_buf_hi[5];
+} __aligned(32);
+
+struct fotg210_qh {
+	struct fotg210_qh_hw	*hw;		/* Must come first */
+	/* the rest is HCD-private */
+	dma_addr_t		qh_dma;		/* address of qh */
+	union fotg210_shadow	qh_next;	/* ptr to qh; or periodic */
+	struct list_head	qtd_list;	/* sw qtd list */
+	struct list_head	intr_node;	/* list of intr QHs */
+	struct fotg210_qtd	*dummy;
+	struct fotg210_qh	*unlink_next;	/* next on unlink list */
+
+	unsigned		unlink_cycle;
+
+	u8			needs_rescan;	/* Dequeue during giveback */
+	u8			qh_state;
+#define	QH_STATE_LINKED		1		/* HC sees this */
+#define	QH_STATE_UNLINK		2		/* HC may still see this */
+#define	QH_STATE_IDLE		3		/* HC doesn't see this */
+#define	QH_STATE_UNLINK_WAIT	4		/* LINKED and on unlink 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 */
+	u8			c_usecs;	/* ... split completion bw */
+	u16			tt_usecs;	/* tt downstream bandwidth */
+	unsigned short		period;		/* polling interval */
+	unsigned short		start;		/* where polling starts */
+#define NO_FRAME ((unsigned short)~0)			/* pick new start */
+
+	struct usb_device	*dev;		/* access to TT */
+	unsigned		is_out:1;	/* bulk or intr OUT */
+	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* description of one iso transaction (up to 3 KB data if highspeed) */
+struct fotg210_iso_packet {
+	/* These will be copied to iTD when scheduling */
+	u64			bufp;		/* itd->hw_bufp{,_hi}[pg] |= */
+	__hc32			transaction;	/* itd->hw_transaction[i] |= */
+	u8			cross;		/* buf crosses pages */
+	/* for full speed OUT splits */
+	u32			buf1;
+};
+
+/* temporary schedule data for packets from iso urbs (both speeds)
+ * each packet is one logical usb transaction to the device (not TT),
+ * beginning at stream->next_uframe
+ */
+struct fotg210_iso_sched {
+	struct list_head	td_list;
+	unsigned		span;
+	struct fotg210_iso_packet	packet[0];
+};
+
+/*
+ * fotg210_iso_stream - groups all (s)itds for this endpoint.
+ * acts like a qh would, if EHCI had them for ISO.
+ */
+struct fotg210_iso_stream {
+	/* first field matches fotg210_hq, but is NULL */
+	struct fotg210_qh_hw	*hw;
+
+	u8			bEndpointAddress;
+	u8			highspeed;
+	struct list_head	td_list;	/* queued itds */
+	struct list_head	free_list;	/* list of unused itds */
+	struct usb_device	*udev;
+	struct usb_host_endpoint *ep;
+
+	/* output of (re)scheduling */
+	int			next_uframe;
+	__hc32			splits;
+
+	/* the rest is derived from the endpoint descriptor,
+	 * trusting urb->interval == f(epdesc->bInterval) and
+	 * including the extra info for hw_bufp[0..2]
+	 */
+	u8			usecs, c_usecs;
+	u16			interval;
+	u16			tt_usecs;
+	u16			maxp;
+	u16			raw_mask;
+	unsigned		bandwidth;
+
+	/* This is used to initialize iTD's hw_bufp fields */
+	__hc32			buf0;
+	__hc32			buf1;
+	__hc32			buf2;
+
+	/* this is used to initialize sITD's tt info */
+	__hc32			address;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.3
+ * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
+ *
+ * Schedule records for high speed iso xfers
+ */
+struct fotg210_itd {
+	/* first part defined by EHCI spec */
+	__hc32			hw_next;	/* see EHCI 3.3.1 */
+	__hc32			hw_transaction[8]; /* see EHCI 3.3.2 */
+#define FOTG210_ISOC_ACTIVE	(1<<31)	/* activate transfer this slot */
+#define FOTG210_ISOC_BUF_ERR	(1<<30)	/* Data buffer error */
+#define FOTG210_ISOC_BABBLE	(1<<29)	/* babble detected */
+#define FOTG210_ISOC_XACTERR	(1<<28)	/* XactErr - transaction error */
+#define	FOTG210_ITD_LENGTH(tok)	(((tok)>>16) & 0x0fff)
+#define	FOTG210_ITD_IOC		(1 << 15)	/* interrupt on complete */
+
+#define ITD_ACTIVE(fotg210)	cpu_to_hc32(fotg210, FOTG210_ISOC_ACTIVE)
+
+	__hc32			hw_bufp[7];	/* see EHCI 3.3.3 */
+	__hc32			hw_bufp_hi[7];	/* Appendix B */
+
+	/* the rest is HCD-private */
+	dma_addr_t		itd_dma;	/* for this itd */
+	union fotg210_shadow	itd_next;	/* ptr to periodic q entry */
+
+	struct urb		*urb;
+	struct fotg210_iso_stream	*stream;	/* endpoint's queue */
+	struct list_head	itd_list;	/* list of stream's itds */
+
+	/* any/all hw_transactions here may be used by that urb */
+	unsigned		frame;		/* where scheduled */
+	unsigned		pg;
+	unsigned		index[8];	/* in urb->iso_frame_desc */
+} __aligned(32);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.96 Section 3.7
+ * Periodic Frame Span Traversal Node (FSTN)
+ *
+ * Manages split interrupt transactions (using TT) that span frame boundaries
+ * into uframes 0/1; see 4.12.2.2.  In those uframes, a "save place" FSTN
+ * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
+ * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
+ */
+struct fotg210_fstn {
+	__hc32			hw_next;	/* any periodic q entry */
+	__hc32			hw_prev;	/* qh or FOTG210_LIST_END */
+
+	/* the rest is HCD-private */
+	dma_addr_t		fstn_dma;
+	union fotg210_shadow	fstn_next;	/* ptr to periodic q entry */
+} __aligned(32);
+
+/*-------------------------------------------------------------------------*/
+
+/* Prepare the PORTSC wakeup flags during controller suspend/resume */
+
+#define fotg210_prepare_ports_for_controller_suspend(fotg210, do_wakeup) \
+		fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup);
+
+#define fotg210_prepare_ports_for_controller_resume(fotg210)		\
+		fotg210_adjust_port_wakeup_flags(fotg210, false, false);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Some EHCI controllers have a Transaction Translator built into the
+ * root hub. This is a non-standard feature.  Each controller will need
+ * to add code to the following inline functions, and call them as
+ * needed (mostly in root hub code).
+ */
+
+static inline unsigned int
+fotg210_get_speed(struct fotg210_hcd *fotg210, unsigned int portsc)
+{
+	return (readl(&fotg210->regs->otgcsr)
+		& OTGCSR_HOST_SPD_TYP) >> 22;
+}
+
+/* Returns the speed of a device attached to a port on the root hub. */
+static inline unsigned int
+fotg210_port_speed(struct fotg210_hcd *fotg210, unsigned int portsc)
+{
+	switch (fotg210_get_speed(fotg210, portsc)) {
+	case 0:
+		return 0;
+	case 1:
+		return USB_PORT_STAT_LOW_SPEED;
+	case 2:
+	default:
+		return USB_PORT_STAT_HIGH_SPEED;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define	fotg210_has_fsl_portno_bug(e)		(0)
+
+/*
+ * While most USB host controllers implement their registers in
+ * little-endian format, a minority (celleb companion chip) implement
+ * them in big endian format.
+ *
+ * This attempts to support either format at compile time without a
+ * runtime penalty, or both formats with the additional overhead
+ * of checking a flag bit.
+ *
+ */
+
+#define fotg210_big_endian_mmio(e)	0
+#define fotg210_big_endian_capbase(e)	0
+
+static inline unsigned int fotg210_readl(const struct fotg210_hcd *fotg210,
+		__u32 __iomem *regs)
+{
+	return readl(regs);
+}
+
+static inline void fotg210_writel(const struct fotg210_hcd *fotg210,
+		const unsigned int val, __u32 __iomem *regs)
+{
+	writel(val, regs);
+}
+
+/* cpu to fotg210 */
+static inline __hc32 cpu_to_hc32(const struct fotg210_hcd *fotg210, const u32 x)
+{
+	return cpu_to_le32(x);
+}
+
+/* fotg210 to cpu */
+static inline u32 hc32_to_cpu(const struct fotg210_hcd *fotg210, const __hc32 x)
+{
+	return le32_to_cpu(x);
+}
+
+static inline u32 hc32_to_cpup(const struct fotg210_hcd *fotg210,
+			       const __hc32 *x)
+{
+	return le32_to_cpup(x);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline unsigned fotg210_read_frame_index(struct fotg210_hcd *fotg210)
+{
+	return fotg210_readl(fotg210, &fotg210->regs->frame_index);
+}
+
+#define fotg210_itdlen(urb, desc, t) ({			\
+	usb_pipein((urb)->pipe) ?				\
+	(desc)->length - FOTG210_ITD_LENGTH(t) :			\
+	FOTG210_ITD_LENGTH(t);					\
+})
+/*-------------------------------------------------------------------------*/
+
+#ifndef DEBUG
+#define STUB_DEBUG_FILES
+#endif	/* DEBUG */
+
+/*-------------------------------------------------------------------------*/
+
+#endif /* __LINUX_FOTG210_H */
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..cfbff71 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -258,7 +258,7 @@ static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
 
 int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct clk *clk;
 	char clk_name[10];
 	int base, clk_num;
@@ -298,7 +298,7 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 
 static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	pdata->regs = NULL;
 
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index 03dc4d9..60a5de5 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -1860,7 +1860,7 @@ static int imx21_probe(struct platform_device *pdev)
 	imx21 = hcd_to_imx21(hcd);
 	imx21->hcd = hcd;
 	imx21->dev = &pdev->dev;
-	imx21->pdata = pdev->dev.platform_data;
+	imx21->pdata = dev_get_platdata(&pdev->dev);
 	if (!imx21->pdata)
 		imx21->pdata = &default_pdata;
 
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index b64e661..c7d0f8f 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1626,7 +1626,7 @@ static int isp116x_probe(struct platform_device *pdev)
 	isp116x->addr_reg = addr_reg;
 	spin_lock_init(&isp116x->lock);
 	INIT_LIST_HEAD(&isp116x->async);
-	isp116x->board = pdev->dev.platform_data;
+	isp116x->board = dev_get_platdata(&pdev->dev);
 
 	if (!isp116x->board) {
 		ERR("Platform data structure not initialized\n");
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index 9a2c400..dd34b7a 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -325,11 +325,7 @@ struct isp116x_ep {
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
-#define DBG(stuff...)		printk(KERN_DEBUG "116x: " stuff)
-#else
-#define DBG(stuff...)		do{}while(0)
-#endif
+#define DBG(stuff...)		pr_debug("116x: " stuff)
 
 #ifdef VERBOSE
 #    define VDBG		DBG
@@ -358,15 +354,8 @@ struct isp116x_ep {
 #define isp116x_check_platform_delay(h)	0
 #endif
 
-#if defined(DEBUG)
-#define	IRQ_TEST()	BUG_ON(!irqs_disabled())
-#else
-#define	IRQ_TEST()	do{}while(0)
-#endif
-
 static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
 {
-	IRQ_TEST();
 	writew(reg & 0xff, isp116x->addr_reg);
 	isp116x_delay(isp116x, 300);
 }
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index b04e8ec..6f29aba 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -37,11 +37,7 @@
  * recovery time (MSCx = 0x7f8c) with a memory clock of 99.53 MHz.
  */
 
-#ifdef CONFIG_USB_DEBUG
-# define ISP1362_DEBUG
-#else
-# undef ISP1362_DEBUG
-#endif
+#undef ISP1362_DEBUG
 
 /*
  * The PXA255 UDC apparently doesn't handle GET_STATUS, GET_CONFIG and
@@ -82,6 +78,8 @@
 #include <linux/io.h>
 #include <linux/bitmap.h>
 #include <linux/prefetch.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/byteorder.h>
@@ -92,7 +90,6 @@ static int dbg_level;
 module_param(dbg_level, int, 0644);
 #else
 module_param(dbg_level, int, 0);
-#define	STUB_DEBUG_FILE
 #endif
 
 #include "../core/usb.h"
@@ -350,8 +347,6 @@ static void isp1362_write_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep
 	struct ptd *ptd = &ep->ptd;
 	int len = PTD_GET_DIR(ptd) == PTD_DIR_IN ? 0 : ep->length;
 
-	_BUG_ON(ep->ptd_offset < 0);
-
 	prefetch(ptd);
 	isp1362_write_buffer(isp1362_hcd, ptd, ep->ptd_offset, PTD_HEADER_SIZE);
 	if (len)
@@ -1575,12 +1570,12 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		DBG(0, "ClearHubFeature: ");
 		switch (wValue) {
 		case C_HUB_OVER_CURRENT:
-			_DBG(0, "C_HUB_OVER_CURRENT\n");
+			DBG(0, "C_HUB_OVER_CURRENT\n");
 			spin_lock_irqsave(&isp1362_hcd->lock, flags);
 			isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_OCIC);
 			spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
 		case C_HUB_LOCAL_POWER:
-			_DBG(0, "C_HUB_LOCAL_POWER\n");
+			DBG(0, "C_HUB_LOCAL_POWER\n");
 			break;
 		default:
 			goto error;
@@ -1591,7 +1586,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		switch (wValue) {
 		case C_HUB_OVER_CURRENT:
 		case C_HUB_LOCAL_POWER:
-			_DBG(0, "C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n");
+			DBG(0, "C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n");
 			break;
 		default:
 			goto error;
@@ -1622,36 +1617,36 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
-			_DBG(0, "USB_PORT_FEAT_ENABLE\n");
+			DBG(0, "USB_PORT_FEAT_ENABLE\n");
 			tmp = RH_PS_CCS;
 			break;
 		case USB_PORT_FEAT_C_ENABLE:
-			_DBG(0, "USB_PORT_FEAT_C_ENABLE\n");
+			DBG(0, "USB_PORT_FEAT_C_ENABLE\n");
 			tmp = RH_PS_PESC;
 			break;
 		case USB_PORT_FEAT_SUSPEND:
-			_DBG(0, "USB_PORT_FEAT_SUSPEND\n");
+			DBG(0, "USB_PORT_FEAT_SUSPEND\n");
 			tmp = RH_PS_POCI;
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
-			_DBG(0, "USB_PORT_FEAT_C_SUSPEND\n");
+			DBG(0, "USB_PORT_FEAT_C_SUSPEND\n");
 			tmp = RH_PS_PSSC;
 			break;
 		case USB_PORT_FEAT_POWER:
-			_DBG(0, "USB_PORT_FEAT_POWER\n");
+			DBG(0, "USB_PORT_FEAT_POWER\n");
 			tmp = RH_PS_LSDA;
 
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
-			_DBG(0, "USB_PORT_FEAT_C_CONNECTION\n");
+			DBG(0, "USB_PORT_FEAT_C_CONNECTION\n");
 			tmp = RH_PS_CSC;
 			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
-			_DBG(0, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+			DBG(0, "USB_PORT_FEAT_C_OVER_CURRENT\n");
 			tmp = RH_PS_OCIC;
 			break;
 		case USB_PORT_FEAT_C_RESET:
-			_DBG(0, "USB_PORT_FEAT_C_RESET\n");
+			DBG(0, "USB_PORT_FEAT_C_RESET\n");
 			tmp = RH_PS_PRSC;
 			break;
 		default:
@@ -1671,7 +1666,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		wIndex--;
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			_DBG(0, "USB_PORT_FEAT_SUSPEND\n");
+			DBG(0, "USB_PORT_FEAT_SUSPEND\n");
 			spin_lock_irqsave(&isp1362_hcd->lock, flags);
 			isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS);
 			isp1362_hcd->rhport[wIndex] =
@@ -1679,7 +1674,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
 			break;
 		case USB_PORT_FEAT_POWER:
-			_DBG(0, "USB_PORT_FEAT_POWER\n");
+			DBG(0, "USB_PORT_FEAT_POWER\n");
 			spin_lock_irqsave(&isp1362_hcd->lock, flags);
 			isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PPS);
 			isp1362_hcd->rhport[wIndex] =
@@ -1687,7 +1682,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
 			break;
 		case USB_PORT_FEAT_RESET:
-			_DBG(0, "USB_PORT_FEAT_RESET\n");
+			DBG(0, "USB_PORT_FEAT_RESET\n");
 			spin_lock_irqsave(&isp1362_hcd->lock, flags);
 
 			t1 = jiffies + msecs_to_jiffies(USB_RESET_WIDTH);
@@ -1721,7 +1716,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 	default:
  error:
 		/* "protocol stall" on error */
-		_DBG(0, "PROTOCOL STALL\n");
+		DBG(0, "PROTOCOL STALL\n");
 		retval = -EPIPE;
 	}
 
@@ -1913,20 +1908,6 @@ static int isp1362_bus_resume(struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct isp1362_hcd *isp1362_hcd)
-{
-}
-static inline void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
-{
-}
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
 static void dump_irq(struct seq_file *s, char *label, u16 mask)
 {
 	seq_printf(s, "%-15s %04x%s%s%s%s%s%s\n", label, mask,
@@ -2069,7 +2050,7 @@ static void dump_regs(struct seq_file *s, struct isp1362_hcd *isp1362_hcd)
 		   isp1362_read_reg16(isp1362_hcd, HCATLDTCTO));
 }
 
-static int proc_isp1362_show(struct seq_file *s, void *unused)
+static int isp1362_show(struct seq_file *s, void *unused)
 {
 	struct isp1362_hcd *isp1362_hcd = s->private;
 	struct isp1362_ep *ep;
@@ -2173,41 +2154,31 @@ static int proc_isp1362_show(struct seq_file *s, void *unused)
 	return 0;
 }
 
-static int proc_isp1362_open(struct inode *inode, struct file *file)
+static int isp1362_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_isp1362_show, PDE_DATA(inode));
+	return single_open(file, isp1362_show, inode);
 }
 
-static const struct file_operations proc_ops = {
-	.open = proc_isp1362_open,
+static const struct file_operations debug_ops = {
+	.open = isp1362_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
 /* expect just one isp1362_hcd per system */
-static const char proc_filename[] = "driver/isp1362";
-
 static void create_debug_file(struct isp1362_hcd *isp1362_hcd)
 {
-	struct proc_dir_entry *pde;
-
-	pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, isp1362_hcd);
-	if (pde == NULL) {
-		pr_warning("%s: Failed to create debug file '%s'\n", __func__, proc_filename);
-		return;
-	}
-	isp1362_hcd->pde = pde;
+	isp1362_hcd->debug_file = debugfs_create_file("isp1362", S_IRUGO,
+						      usb_debug_root,
+						      isp1362_hcd, &debug_ops);
 }
 
 static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
 {
-	if (isp1362_hcd->pde)
-		remove_proc_entry(proc_filename, NULL);
+	debugfs_remove(isp1362_hcd->debug_file);
 }
 
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
@@ -2754,7 +2725,7 @@ static int isp1362_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&isp1362_hcd->periodic);
 	INIT_LIST_HEAD(&isp1362_hcd->isoc);
 	INIT_LIST_HEAD(&isp1362_hcd->remove_list);
-	isp1362_hcd->board = pdev->dev.platform_data;
+	isp1362_hcd->board = dev_get_platdata(&pdev->dev);
 #if USE_PLATFORM_DELAY
 	if (!isp1362_hcd->board->delay) {
 		dev_err(hcd->self.controller, "No platform delay function given\n");
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h
index 0f97820..3b0b484 100644
--- a/drivers/usb/host/isp1362.h
+++ b/drivers/usb/host/isp1362.h
@@ -76,14 +76,14 @@ static inline void delayed_insw(unsigned int addr, void *buf, int len)
 
 #define ISP1362_REG_WRITE_OFFSET	0x80
 
-#ifdef ISP1362_DEBUG
-typedef const unsigned int isp1362_reg_t;
-
 #define REG_WIDTH_16			0x000
 #define REG_WIDTH_32			0x100
 #define REG_WIDTH_MASK			0x100
 #define REG_NO_MASK			0x0ff
 
+#ifdef ISP1362_DEBUG
+typedef const unsigned int isp1362_reg_t;
+
 #define REG_ACCESS_R			0x200
 #define REG_ACCESS_W			0x400
 #define REG_ACCESS_RW			0x600
@@ -91,9 +91,6 @@ typedef const unsigned int isp1362_reg_t;
 
 #define ISP1362_REG_NO(r)		((r) & REG_NO_MASK)
 
-#define _BUG_ON(x)	BUG_ON(x)
-#define _WARN_ON(x)	WARN_ON(x)
-
 #define ISP1362_REG(name, addr, width, rw) \
 static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw))
 
@@ -102,8 +99,6 @@ static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw))
 #else
 typedef const unsigned char isp1362_reg_t;
 #define ISP1362_REG_NO(r)		(r)
-#define _BUG_ON(x)			do {} while (0)
-#define _WARN_ON(x)			do {} while (0)
 
 #define ISP1362_REG(name, addr, width, rw) \
 static isp1362_reg_t ISP1362_REG_##name = addr
@@ -485,7 +480,7 @@ struct isp1362_hcd {
 
 	struct isp1362_platform_data *board;
 
-	struct proc_dir_entry	*pde;
+	struct dentry		*debug_file;
 	unsigned long		stat1, stat2, stat4, stat8, stat16;
 
 	/* HC registers */
@@ -587,21 +582,11 @@ static inline struct usb_hcd *isp1362_hcd_to_hcd(struct isp1362_hcd *isp1362_hcd
  * ISP1362 HW Interface
  */
 
-#ifdef ISP1362_DEBUG
 #define DBG(level, fmt...) \
 	do { \
 		if (dbg_level > level) \
 			pr_debug(fmt); \
 	} while (0)
-#define _DBG(level, fmt...)	\
-	do { \
-		if (dbg_level > level) \
-			printk(fmt); \
-	} while (0)
-#else
-#define DBG(fmt...)		do {} while (0)
-#define _DBG DBG
-#endif
 
 #ifdef VERBOSE
 #    define VDBG(fmt...)	DBG(3, fmt)
@@ -645,9 +630,7 @@ static inline struct usb_hcd *isp1362_hcd_to_hcd(struct isp1362_hcd *isp1362_hcd
  */
 static void isp1362_write_addr(struct isp1362_hcd *isp1362_hcd, isp1362_reg_t reg)
 {
-	/*_BUG_ON((reg & ISP1362_REG_WRITE_OFFSET) && !(reg & REG_ACCESS_W));*/
 	REG_ACCESS_TEST(reg);
-	_BUG_ON(!irqs_disabled());
 	DUMMY_DELAY_ACCESS;
 	writew(ISP1362_REG_NO(reg), isp1362_hcd->addr_reg);
 	DUMMY_DELAY_ACCESS;
@@ -656,7 +639,6 @@ static void isp1362_write_addr(struct isp1362_hcd *isp1362_hcd, isp1362_reg_t re
 
 static void isp1362_write_data16(struct isp1362_hcd *isp1362_hcd, u16 val)
 {
-	_BUG_ON(!irqs_disabled());
 	DUMMY_DELAY_ACCESS;
 	writew(val, isp1362_hcd->data_reg);
 }
@@ -665,7 +647,6 @@ static u16 isp1362_read_data16(struct isp1362_hcd *isp1362_hcd)
 {
 	u16 val;
 
-	_BUG_ON(!irqs_disabled());
 	DUMMY_DELAY_ACCESS;
 	val = readw(isp1362_hcd->data_reg);
 
@@ -674,7 +655,6 @@ static u16 isp1362_read_data16(struct isp1362_hcd *isp1362_hcd)
 
 static void isp1362_write_data32(struct isp1362_hcd *isp1362_hcd, u32 val)
 {
-	_BUG_ON(!irqs_disabled());
 #if USE_32BIT
 	DUMMY_DELAY_ACCESS;
 	writel(val, isp1362_hcd->data_reg);
@@ -690,7 +670,6 @@ static u32 isp1362_read_data32(struct isp1362_hcd *isp1362_hcd)
 {
 	u32 val;
 
-	_BUG_ON(!irqs_disabled());
 #if USE_32BIT
 	DUMMY_DELAY_ACCESS;
 	val = readl(isp1362_hcd->data_reg);
@@ -713,8 +692,6 @@ static void isp1362_read_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 le
 	if (!len)
 		return;
 
-	_BUG_ON(!irqs_disabled());
-
 	RDBG("%s: Reading %d byte from fifo to mem @ %p\n", __func__, len, buf);
 #if USE_32BIT
 	if (len >= 4) {
@@ -760,8 +737,6 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l
 		return;
 	}
 
-	_BUG_ON(!irqs_disabled());
-
 	RDBG("%s: Writing %d byte to fifo from memory @%p\n", __func__, len, buf);
 #if USE_32BIT
 	if (len >= 4) {
@@ -854,7 +829,6 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l
 		isp1362_write_reg32(d, r, __v & ~m);	\
 }
 
-#ifdef ISP1362_DEBUG
 #define isp1362_show_reg(d, r) {								\
 	if ((ISP1362_REG_##r & REG_WIDTH_MASK) == REG_WIDTH_32)			\
 		DBG(0, "%-12s[%02x]: %08x\n", #r,					\
@@ -863,9 +837,6 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l
 		DBG(0, "%-12s[%02x]:     %04x\n", #r,					\
 			ISP1362_REG_NO(ISP1362_REG_##r), isp1362_read_reg16(d, r));	\
 }
-#else
-#define isp1362_show_reg(d, r)	do {} while (0)
-#endif
 
 static void __attribute__((__unused__)) isp1362_show_regs(struct isp1362_hcd *isp1362_hcd)
 {
@@ -923,10 +894,6 @@ static void __attribute__((__unused__)) isp1362_show_regs(struct isp1362_hcd *is
 
 static void isp1362_write_diraddr(struct isp1362_hcd *isp1362_hcd, u16 offset, u16 len)
 {
-	_BUG_ON(offset & 1);
-	_BUG_ON(offset >= ISP1362_BUF_SIZE);
-	_BUG_ON(len > ISP1362_BUF_SIZE);
-	_BUG_ON(offset + len > ISP1362_BUF_SIZE);
 	len = (len + 1) & ~1;
 
 	isp1362_clr_mask16(isp1362_hcd, HCDMACFG, HCDMACFG_CTR_ENABLE);
@@ -936,42 +903,32 @@ static void isp1362_write_diraddr(struct isp1362_hcd *isp1362_hcd, u16 offset, u
 
 static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len)
 {
-	_BUG_ON(offset & 1);
-
 	isp1362_write_diraddr(isp1362_hcd, offset, len);
 
 	DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %p\n",
 	    __func__, len, offset, buf);
 
 	isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
-	_WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
 
 	isp1362_write_addr(isp1362_hcd, ISP1362_REG_HCDIRDATA);
 
 	isp1362_read_fifo(isp1362_hcd, buf, len);
-	_WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
 	isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
-	_WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
 }
 
 static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len)
 {
-	_BUG_ON(offset & 1);
-
 	isp1362_write_diraddr(isp1362_hcd, offset, len);
 
 	DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %p\n",
 	    __func__, len, offset, buf);
 
 	isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
-	_WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
 
 	isp1362_write_addr(isp1362_hcd, ISP1362_REG_HCDIRDATA | ISP1362_REG_WRITE_OFFSET);
 	isp1362_write_fifo(isp1362_hcd, buf, len);
 
-	_WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
 	isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
-	_WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
 }
 
 static void __attribute__((unused)) dump_data(char *buf, int len)
@@ -1002,7 +959,7 @@ static void __attribute__((unused)) dump_data(char *buf, int len)
 	}
 }
 
-#if defined(ISP1362_DEBUG) && defined(PTD_TRACE)
+#if defined(PTD_TRACE)
 
 static void dump_ptd(struct ptd *ptd)
 {
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 3df49b1..df931e9 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -351,7 +351,7 @@ static int isp1760_plat_probe(struct platform_device *pdev)
 	struct resource *mem_res;
 	struct resource *irq_res;
 	resource_size_t mem_size;
-	struct isp1760_platform_data *priv = pdev->dev.platform_data;
+	struct isp1760_platform_data *priv = dev_get_platdata(&pdev->dev);
 	unsigned int devflags = 0;
 	unsigned long irqflags = IRQF_SHARED;
 
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 9677f68..b3cdd14 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -31,8 +31,8 @@
 #define at91_for_each_port(index)	\
 		for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
 
-/* interface and function clocks; sometimes also an AHB clock */
-static struct clk *iclk, *fclk, *hclk;
+/* interface, function and usb clocks; sometimes also an AHB clock */
+static struct clk *iclk, *fclk, *uclk, *hclk;
 static int clocked;
 
 extern int usb_disabled(void);
@@ -41,6 +41,10 @@ extern int usb_disabled(void);
 
 static void at91_start_clock(void)
 {
+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+		clk_set_rate(uclk, 48000000);
+		clk_prepare_enable(uclk);
+	}
 	clk_prepare_enable(hclk);
 	clk_prepare_enable(iclk);
 	clk_prepare_enable(fclk);
@@ -52,6 +56,8 @@ static void at91_stop_clock(void)
 	clk_disable_unprepare(fclk);
 	clk_disable_unprepare(iclk);
 	clk_disable_unprepare(hclk);
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_disable_unprepare(uclk);
 	clocked = 0;
 }
 
@@ -162,6 +168,14 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 		retval = PTR_ERR(hclk);
 		goto err5;
 	}
+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+		uclk = clk_get(&pdev->dev, "usb_clk");
+		if (IS_ERR(uclk)) {
+			dev_err(&pdev->dev, "failed to get uclk\n");
+			retval = PTR_ERR(uclk);
+			goto err6;
+		}
+	}
 
 	at91_start_hc(pdev);
 	ohci_hcd_init(hcd_to_ohci(hcd));
@@ -173,6 +187,9 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 	/* Error handling */
 	at91_stop_hc(pdev);
 
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_put(uclk);
+ err6:
 	clk_put(hclk);
  err5:
 	clk_put(fclk);
@@ -212,6 +229,8 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd,
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_put(uclk);
 	clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
@@ -225,7 +244,7 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd,
 static int
 ohci_at91_reset (struct usb_hcd *hcd)
 {
-	struct at91_usbh_data	*board = hcd->self.controller->platform_data;
+	struct at91_usbh_data	*board = dev_get_platdata(hcd->self.controller);
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	int			ret;
 
@@ -280,7 +299,7 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
  */
 static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
-	struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
+	struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller);
 	int length = ohci_hub_status_data(hcd, buf);
 	int port;
 
@@ -301,7 +320,7 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
 static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 				 u16 wIndex, char *buf, u16 wLength)
 {
-	struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
+	struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller);
 	struct usb_hub_descriptor *desc;
 	int ret = -EINVAL;
 	u32 *data = (u32 *)buf;
@@ -461,7 +480,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
 static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
 {
 	struct platform_device *pdev = data;
-	struct at91_usbh_data *pdata = pdev->dev.platform_data;
+	struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev);
 	int val, gpio, port;
 
 	/* From the GPIO notifying the over-current situation, find
@@ -567,7 +586,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 
 	if (pdata) {
 		at91_for_each_port(i) {
@@ -643,7 +662,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 
 static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 {
-	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
+	struct at91_usbh_data	*pdata = dev_get_platdata(&pdev->dev);
 	int			i;
 
 	if (pdata) {
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 6aaa9c9..9be59f1 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -85,7 +85,7 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub,
 static int ohci_da8xx_init(struct usb_hcd *hcd)
 {
 	struct device *dev		= hcd->self.controller;
-	struct da8xx_ohci_root_hub *hub	= dev->platform_data;
+	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(dev);
 	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
 	int result;
 	u32 rh_a;
@@ -171,7 +171,7 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 				  u16 wIndex, char *buf, u16 wLength)
 {
 	struct device *dev		= hcd->self.controller;
-	struct da8xx_ohci_root_hub *hub	= dev->platform_data;
+	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(dev);
 	int temp;
 
 	switch (typeReq) {
@@ -292,7 +292,7 @@ static const struct hc_driver ohci_da8xx_hc_driver = {
 static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
 			       struct platform_device *pdev)
 {
-	struct da8xx_ohci_root_hub *hub	= pdev->dev.platform_data;
+	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(&pdev->dev);
 	struct usb_hcd	*hcd;
 	struct resource *mem;
 	int error, irq;
@@ -380,7 +380,7 @@ err0:
 static inline void
 usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev)
 {
-	struct da8xx_ohci_root_hub *hub	= pdev->dev.platform_data;
+	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(&pdev->dev);
 
 	hub->ocic_notify(NULL);
 	usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 8704e9f..84a20d5 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -30,83 +30,6 @@
 
 static struct clk *usb_host_clock;
 
-static void ep93xx_start_hc(struct device *dev)
-{
-	clk_enable(usb_host_clock);
-}
-
-static void ep93xx_stop_hc(struct device *dev)
-{
-	clk_disable(usb_host_clock);
-}
-
-static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
-			 struct platform_device *pdev)
-{
-	int retval;
-	struct usb_hcd *hcd;
-
-	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-		dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n");
-		return -ENOMEM;
-	}
-
-	hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx");
-	if (hcd == NULL)
-		return -ENOMEM;
-
-	hcd->rsrc_start = pdev->resource[0].start;
-	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		usb_put_hcd(hcd);
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (hcd->regs == NULL) {
-		dev_dbg(&pdev->dev, "ioremap failed\n");
-		retval = -ENOMEM;
-		goto err2;
-	}
-
-	usb_host_clock = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(usb_host_clock)) {
-		dev_dbg(&pdev->dev, "clk_get failed\n");
-		retval = PTR_ERR(usb_host_clock);
-		goto err3;
-	}
-
-	ep93xx_start_hc(&pdev->dev);
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	retval = usb_add_hcd(hcd, pdev->resource[1].start, 0);
-	if (retval == 0)
-		return retval;
-
-	ep93xx_stop_hc(&pdev->dev);
-err3:
-	iounmap(hcd->regs);
-err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-	usb_put_hcd(hcd);
-
-	return retval;
-}
-
-static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
-			struct platform_device *pdev)
-{
-	usb_remove_hcd(hcd);
-	ep93xx_stop_hc(&pdev->dev);
-	clk_put(usb_host_clock);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-}
-
 static int ohci_ep93xx_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@@ -147,15 +70,57 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
 	.start_port_reset	= ohci_start_port_reset,
 };
 
-extern int usb_disabled(void);
-
 static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
 {
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq;
 	int ret;
 
-	ret = -ENODEV;
-	if (!usb_disabled())
-		ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev);
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	hcd = usb_create_hcd(&ohci_ep93xx_hc_driver, &pdev->dev, "ep93xx");
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
+		goto err_put_hcd;
+	}
+
+	usb_host_clock = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(usb_host_clock)) {
+		ret = PTR_ERR(usb_host_clock);
+		goto err_put_hcd;
+	}
+
+	clk_enable(usb_host_clock);
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	ret = usb_add_hcd(hcd, irq, 0);
+	if (ret)
+		goto err_clk_disable;
+
+	return 0;
+
+err_clk_disable:
+	clk_disable(usb_host_clock);
+err_put_hcd:
+	usb_put_hcd(hcd);
 
 	return ret;
 }
@@ -164,7 +129,9 @@ static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
-	usb_hcd_ep93xx_remove(hcd, pdev);
+	usb_remove_hcd(hcd);
+	clk_disable(usb_host_clock);
+	usb_put_hcd(hcd);
 
 	return 0;
 }
@@ -179,7 +146,7 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
 		msleep(5);
 	ohci->next_statechange = jiffies;
 
-	ep93xx_stop_hc(&pdev->dev);
+	clk_disable(usb_host_clock);
 	return 0;
 }
 
@@ -192,7 +159,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
 		msleep(5);
 	ohci->next_statechange = jiffies;
 
-	ep93xx_start_hc(&pdev->dev);
+	clk_enable(usb_host_clock);
 
 	ohci_resume(hcd, false);
 	return 0;
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index b0b542c..dc6ee9a 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -100,7 +100,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
 
 static int exynos_ohci_probe(struct platform_device *pdev)
 {
-	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
+	struct exynos4_ohci_platdata *pdata = dev_get_platdata(&pdev->dev);
 	struct exynos_ohci_hcd *exynos_ohci;
 	struct usb_hcd *hcd;
 	struct ohci_hcd *ohci;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index a9d3437..8f6b695 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -938,8 +938,8 @@ static void ohci_stop (struct usb_hcd *hcd)
 	if (quirk_nec(ohci))
 		flush_work(&ohci->nec_work);
 
-	ohci_usb_reset (ohci);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+	ohci_usb_reset(ohci);
 	free_irq(hcd->irq, hcd);
 	hcd->irq = 0;
 
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 8747fa6..31d3a12 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -191,7 +191,7 @@ static void start_hnp(struct ohci_hcd *ohci)
 static int ohci_omap_init(struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
-	struct omap_usb_config	*config = hcd->self.controller->platform_data;
+	struct omap_usb_config	*config = dev_get_platdata(hcd->self.controller);
 	int			need_transceiver = (config->otg != 0);
 	int			ret;
 
@@ -427,7 +427,7 @@ ohci_omap_start (struct usb_hcd *hcd)
 
 	if (!host_enabled)
 		return 0;
-	config = hcd->self.controller->platform_data;
+	config = dev_get_platdata(hcd->self.controller);
 	if (config->otg || config->rwc) {
 		ohci->hc_control = OHCI_CTRL_RWC;
 		writel(OHCI_CTRL_RWC, &ohci->regs->control);
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 8f71357..a09af26 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -231,14 +231,6 @@ static int ohci_hcd_omap3_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
-
-	if (hcd->driver->shutdown)
-		hcd->driver->shutdown(hcd);
-}
-
 static const struct of_device_id omap_ohci_dt_ids[] = {
 	{ .compatible = "ti,ohci-omap3" },
 	{ }
@@ -249,7 +241,7 @@ MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids);
 static struct platform_driver ohci_hcd_omap3_driver = {
 	.probe		= ohci_hcd_omap3_probe,
 	.remove		= ohci_hcd_omap3_remove,
-	.shutdown	= ohci_hcd_omap3_shutdown,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
 		.name	= "ohci-omap3",
 		.of_match_table = omap_ohci_dt_ids,
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index bc30475..a4c6410 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -33,7 +33,7 @@ static const char hcd_name[] = "ohci-platform";
 static int ohci_platform_reset(struct usb_hcd *hcd)
 {
 	struct platform_device *pdev = to_platform_device(hcd->self.controller);
-	struct usb_ohci_pdata *pdata = pdev->dev.platform_data;
+	struct usb_ohci_pdata *pdata = dev_get_platdata(&pdev->dev);
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 
 	if (pdata->big_endian_desc)
@@ -59,7 +59,7 @@ static int ohci_platform_probe(struct platform_device *dev)
 {
 	struct usb_hcd *hcd;
 	struct resource *res_mem;
-	struct usb_ohci_pdata *pdata = dev->dev.platform_data;
+	struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
 	int irq;
 	int err = -ENOMEM;
 
@@ -124,7 +124,7 @@ err_power:
 static int ohci_platform_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
-	struct usb_ohci_pdata *pdata = dev->dev.platform_data;
+	struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
 
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
@@ -139,7 +139,7 @@ static int ohci_platform_remove(struct platform_device *dev)
 
 static int ohci_platform_suspend(struct device *dev)
 {
-	struct usb_ohci_pdata *pdata = dev->platform_data;
+	struct usb_ohci_pdata *pdata = dev_get_platdata(dev);
 	struct platform_device *pdev =
 		container_of(dev, struct platform_device, dev);
 
@@ -152,7 +152,7 @@ static int ohci_platform_suspend(struct device *dev)
 static int ohci_platform_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct usb_ohci_pdata *pdata = dev->platform_data;
+	struct usb_ohci_pdata *pdata = dev_get_platdata(dev);
 	struct platform_device *pdev =
 		container_of(dev, struct platform_device, dev);
 
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 8294e2f..75f5a1e 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -200,15 +200,6 @@ static int ohci_hcd_ppc_of_remove(struct platform_device *op)
 	return 0;
 }
 
-static void ohci_hcd_ppc_of_shutdown(struct platform_device *op)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(op);
-
-        if (hcd->driver->shutdown)
-                hcd->driver->shutdown(hcd);
-}
-
-
 static const struct of_device_id ohci_hcd_ppc_of_match[] = {
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE
 	{
@@ -243,7 +234,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
 static struct platform_driver ohci_hcd_ppc_of_driver = {
 	.probe		= ohci_hcd_ppc_of_probe,
 	.remove		= ohci_hcd_ppc_of_remove,
-	.shutdown 	= ohci_hcd_ppc_of_shutdown,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name = "ppc-of-ohci",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 3a9c01d..93371a2 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -219,7 +219,7 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
 	struct pxaohci_platform_data *inf;
 	uint32_t uhchr;
 
-	inf = dev->platform_data;
+	inf = dev_get_platdata(dev);
 
 	clk_prepare_enable(ohci->clk);
 
@@ -256,7 +256,7 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
 	struct pxaohci_platform_data *inf;
 	uint32_t uhccoms;
 
-	inf = dev->platform_data;
+	inf = dev_get_platdata(dev);
 
 	if (cpu_is_pxa3xx())
 		pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
@@ -364,7 +364,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
 	if (retval)
 		return retval;
 
-	inf = pdev->dev.platform_data;
+	inf = dev_get_platdata(&pdev->dev);
 
 	if (!inf)
 		return -ENODEV;
@@ -577,7 +577,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
-	struct pxaohci_platform_data *inf = dev->platform_data;
+	struct pxaohci_platform_data *inf = dev_get_platdata(dev);
 	int status;
 
 	if (time_before(jiffies, ohci->ohci.next_statechange))
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index e125770..4919afa 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -38,12 +38,12 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
 
 static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
 {
-	return hcd->self.controller->platform_data;
+	return dev_get_platdata(hcd->self.controller);
 }
 
 static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
 {
-	struct s3c2410_hcd_info *info = dev->dev.platform_data;
+	struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev);
 
 	dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
 
@@ -63,7 +63,7 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
 
 static void s3c2410_stop_hc(struct platform_device *dev)
 {
-	struct s3c2410_hcd_info *info = dev->dev.platform_data;
+	struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev);
 
 	dev_dbg(&dev->dev, "s3c2410_stop_hc:\n");
 
@@ -339,10 +339,11 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
 				  struct platform_device *dev)
 {
 	struct usb_hcd *hcd = NULL;
+	struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev);
 	int retval;
 
-	s3c2410_usb_set_power(dev->dev.platform_data, 1, 1);
-	s3c2410_usb_set_power(dev->dev.platform_data, 2, 1);
+	s3c2410_usb_set_power(info, 1, 1);
+	s3c2410_usb_set_power(info, 2, 1);
 
 	hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");
 	if (hcd == NULL)
diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c
index 197d514..22540ab 100644
--- a/drivers/usb/host/ohci-tilegx.c
+++ b/drivers/usb/host/ohci-tilegx.c
@@ -95,7 +95,7 @@ static const struct hc_driver ohci_tilegx_hc_driver = {
 static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
-	struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	pte_t pte = { 0 };
 	int my_cpu = smp_processor_id();
 	int ret;
@@ -175,7 +175,7 @@ err_hcd:
 static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct tilegx_usb_platform_data* pdata = pdev->dev.platform_data;
+	struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index b9848e4..2c76ef1 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -735,32 +735,6 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
 	return -ETIMEDOUT;
 }
 
-#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI	0x8C31
-#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI	0x9C31
-
-bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
-{
-	return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
-		pdev->vendor == PCI_VENDOR_ID_INTEL &&
-		pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
-}
-
-/* The Intel Lynx Point chipset also has switchable ports. */
-bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
-{
-	return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
-		pdev->vendor == PCI_VENDOR_ID_INTEL &&
-		(pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI ||
-		 pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI);
-}
-
-bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
-{
-	return usb_is_intel_ppt_switchable_xhci(pdev) ||
-		usb_is_intel_lpt_switchable_xhci(pdev);
-}
-EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
-
 /*
  * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that
  * share some number of ports.  These ports can be switched between either
@@ -779,9 +753,23 @@ EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
  * terminations before switching the USB 2.0 wires over, so that USB 3.0
  * devices connect at SuperSpeed, rather than at USB 2.0 speeds.
  */
-void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
+void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
 {
 	u32		ports_available;
+	bool		ehci_found = false;
+	struct pci_dev	*companion = NULL;
+
+	/* make sure an intel EHCI controller exists */
+	for_each_pci_dev(companion) {
+		if (companion->class == PCI_CLASS_SERIAL_USB_EHCI &&
+		    companion->vendor == PCI_VENDOR_ID_INTEL) {
+			ehci_found = true;
+			break;
+		}
+	}
+
+	if (!ehci_found)
+		return;
 
 	/* Don't switchover the ports if the user hasn't compiled the xHCI
 	 * driver.  Otherwise they will see "dead" USB ports that don't power
@@ -840,7 +828,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
 	dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over "
 			"to xHCI: 0x%x\n", ports_available);
 }
-EXPORT_SYMBOL_GPL(usb_enable_xhci_ports);
+EXPORT_SYMBOL_GPL(usb_enable_intel_xhci_ports);
 
 void usb_disable_xhci_ports(struct pci_dev *xhci_pdev)
 {
@@ -921,8 +909,8 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
 	writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
 
 hc_init:
-	if (usb_is_intel_switchable_xhci(pdev))
-		usb_enable_xhci_ports(pdev);
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+		usb_enable_intel_xhci_ports(pdev);
 
 	op_reg_base = base + XHCI_HC_LENGTH(readl(base));
 
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 978c849..ed6700d 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -8,8 +8,7 @@ int usb_amd_find_chipset_info(void);
 void usb_amd_dev_put(void);
 void usb_amd_quirk_pll_disable(void);
 void usb_amd_quirk_pll_enable(void);
-bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
-void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
+void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
 void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
 void sb800_prefetch(struct device *dev, int on);
 #else
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index a6fd8f53..a9eef68 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2467,7 +2467,7 @@ static int r8a66597_probe(struct platform_device *pdev)
 	r8a66597 = hcd_to_r8a66597(hcd);
 	memset(r8a66597, 0, sizeof(struct r8a66597));
 	dev_set_drvdata(&pdev->dev, r8a66597);
-	r8a66597->pdata = pdev->dev.platform_data;
+	r8a66597->pdata = dev_get_platdata(&pdev->dev);
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 	if (r8a66597->pdata->on_chip) {
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index b2ec7fe..5477bf5 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -48,6 +48,8 @@
 #include <linux/usb/hcd.h>
 #include <linux/platform_device.h>
 #include <linux/prefetch.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -63,11 +65,6 @@ MODULE_ALIAS("platform:sl811-hcd");
 
 #define DRIVER_VERSION	"19 May 2005"
 
-
-#ifndef DEBUG
-#	define	STUB_DEBUG_FILE
-#endif
-
 /* for now, use only one transfer register bank */
 #undef	USE_B
 
@@ -100,7 +97,8 @@ static void port_power(struct sl811 *sl811, int is_on)
 
 	if (sl811->board && sl811->board->port_power) {
 		/* switch VBUS, at 500mA unless hub power budget gets set */
-		DBG("power %s\n", is_on ? "on" : "off");
+		dev_dbg(hcd->self.controller, "power %s\n",
+			is_on ? "on" : "off");
 		sl811->board->port_power(hcd->self.controller, is_on);
 	}
 
@@ -282,7 +280,7 @@ static inline void sofirq_on(struct sl811 *sl811)
 {
 	if (sl811->irq_enable & SL11H_INTMASK_SOFINTR)
 		return;
-	VDBG("sof irq on\n");
+	dev_dbg(sl811_to_hcd(sl811)->self.controller, "sof irq on\n");
 	sl811->irq_enable |= SL11H_INTMASK_SOFINTR;
 }
 
@@ -290,7 +288,7 @@ static inline void sofirq_off(struct sl811 *sl811)
 {
 	if (!(sl811->irq_enable & SL11H_INTMASK_SOFINTR))
 		return;
-	VDBG("sof irq off\n");
+	dev_dbg(sl811_to_hcd(sl811)->self.controller, "sof irq off\n");
 	sl811->irq_enable &= ~SL11H_INTMASK_SOFINTR;
 }
 
@@ -338,7 +336,8 @@ static struct sl811h_ep	*start(struct sl811 *sl811, u8 bank)
 	}
 
 	if (unlikely(list_empty(&ep->hep->urb_list))) {
-		DBG("empty %p queue?\n", ep);
+		dev_dbg(sl811_to_hcd(sl811)->self.controller,
+			"empty %p queue?\n", ep);
 		return NULL;
 	}
 
@@ -391,7 +390,8 @@ static struct sl811h_ep	*start(struct sl811 *sl811, u8 bank)
 		status_packet(sl811, ep, urb, bank, control);
 		break;
 	default:
-		DBG("bad ep%p pid %02x\n", ep, ep->nextpid);
+		dev_dbg(sl811_to_hcd(sl811)->self.controller,
+			"bad ep%p pid %02x\n", ep, ep->nextpid);
 		ep = NULL;
 	}
 	return ep;
@@ -447,7 +447,8 @@ static void finish_request(
 	}
 
 	/* periodic deschedule */
-	DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+	dev_dbg(sl811_to_hcd(sl811)->self.controller,
+		"deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
 	for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
 		struct sl811h_ep	*temp;
 		struct sl811h_ep	**prev = &sl811->periodic[i];
@@ -593,7 +594,8 @@ static inline u8 checkdone(struct sl811 *sl811)
 		ctl = sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG));
 		if (ctl & SL11H_HCTLMASK_ARM)
 			sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
-		DBG("%s DONE_A: ctrl %02x sts %02x\n",
+		dev_dbg(sl811_to_hcd(sl811)->self.controller,
+			"%s DONE_A: ctrl %02x sts %02x\n",
 			(ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost",
 			ctl,
 			sl811_read(sl811, SL811_EP_A(SL11H_PKTSTATREG)));
@@ -604,7 +606,8 @@ static inline u8 checkdone(struct sl811 *sl811)
 		ctl = sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG));
 		if (ctl & SL11H_HCTLMASK_ARM)
 			sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
-		DBG("%s DONE_B: ctrl %02x sts %02x\n",
+		dev_dbg(sl811_to_hcd(sl811)->self.controller,
+			"%s DONE_B: ctrl %02x sts %02x\n",
 			(ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost",
 			ctl,
 			sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG)));
@@ -665,7 +668,7 @@ retry:
 		 * this one has nothing scheduled.
 		 */
 		if (sl811->next_periodic) {
-			// ERR("overrun to slot %d\n", index);
+			// dev_err(hcd->self.controller, "overrun to slot %d\n", index);
 			sl811->stat_overrun++;
 		}
 		if (sl811->periodic[index])
@@ -723,7 +726,7 @@ retry:
 
 	} else if (irqstat & SL11H_INTMASK_RD) {
 		if (sl811->port1 & USB_PORT_STAT_SUSPEND) {
-			DBG("wakeup\n");
+			dev_dbg(hcd->self.controller, "wakeup\n");
 			sl811->port1 |= USB_PORT_STAT_C_SUSPEND << 16;
 			sl811->stat_wake++;
 		} else
@@ -852,8 +855,9 @@ static int sl811h_urb_enqueue(
 
 		if (ep->maxpacket > H_MAXPACKET) {
 			/* iso packets up to 240 bytes could work... */
-			DBG("dev %d ep%d maxpacket %d\n",
-				udev->devnum, epnum, ep->maxpacket);
+			dev_dbg(hcd->self.controller,
+				"dev %d ep%d maxpacket %d\n", udev->devnum,
+				epnum, ep->maxpacket);
 			retval = -EINVAL;
 			kfree(ep);
 			goto fail;
@@ -917,7 +921,8 @@ static int sl811h_urb_enqueue(
 		 * to share the faster parts of the tree without needing
 		 * dummy/placeholder nodes
 		 */
-		DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+		dev_dbg(hcd->self.controller, "schedule qh%d/%p branch %d\n",
+			ep->period, ep, ep->branch);
 		for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
 			struct sl811h_ep	**prev = &sl811->periodic[i];
 			struct sl811h_ep	*here = *prev;
@@ -976,7 +981,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		} else if (sl811->active_a == ep) {
 			if (time_before_eq(sl811->jiffies_a, jiffies)) {
 				/* happens a lot with lowspeed?? */
-				DBG("giveup on DONE_A: ctrl %02x sts %02x\n",
+				dev_dbg(hcd->self.controller,
+					"giveup on DONE_A: ctrl %02x sts %02x\n",
 					sl811_read(sl811,
 						SL811_EP_A(SL11H_HOSTCTLREG)),
 					sl811_read(sl811,
@@ -990,7 +996,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		} else if (sl811->active_b == ep) {
 			if (time_before_eq(sl811->jiffies_a, jiffies)) {
 				/* happens a lot with lowspeed?? */
-				DBG("giveup on DONE_B: ctrl %02x sts %02x\n",
+				dev_dbg(hcd->self.controller,
+					"giveup on DONE_B: ctrl %02x sts %02x\n",
 					sl811_read(sl811,
 						SL811_EP_B(SL11H_HOSTCTLREG)),
 					sl811_read(sl811,
@@ -1008,7 +1015,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		if (urb)
 			finish_request(sl811, ep, urb, 0);
 		else
-			VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
+			dev_dbg(sl811_to_hcd(sl811)->self.controller,
+				"dequeue, urb %p active %s; wait4irq\n", urb,
 				(sl811->active_a == ep) ? "A" : "B");
 	} else
 		retval = -EINVAL;
@@ -1029,7 +1037,7 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
 	if (!list_empty(&hep->urb_list))
 		msleep(3);
 	if (!list_empty(&hep->urb_list))
-		WARNING("ep %p not empty?\n", ep);
+		dev_warn(hcd->self.controller, "ep %p not empty?\n", ep);
 
 	kfree(ep);
 	hep->hcpriv = NULL;
@@ -1132,7 +1140,7 @@ sl811h_timer(unsigned long _sl811)
 
 	switch (signaling) {
 	case SL11H_CTL1MASK_SE0:
-		DBG("end reset\n");
+		dev_dbg(sl811_to_hcd(sl811)->self.controller, "end reset\n");
 		sl811->port1 = (USB_PORT_STAT_C_RESET << 16)
 				 | USB_PORT_STAT_POWER;
 		sl811->ctrl1 = 0;
@@ -1141,11 +1149,12 @@ sl811h_timer(unsigned long _sl811)
 			irqstat &= ~SL11H_INTMASK_RD;
 		break;
 	case SL11H_CTL1MASK_K:
-		DBG("end resume\n");
+		dev_dbg(sl811_to_hcd(sl811)->self.controller, "end resume\n");
 		sl811->port1 &= ~USB_PORT_STAT_SUSPEND;
 		break;
 	default:
-		DBG("odd timer signaling: %02x\n", signaling);
+		dev_dbg(sl811_to_hcd(sl811)->self.controller,
+			"odd timer signaling: %02x\n", signaling);
 		break;
 	}
 	sl811_write(sl811, SL11H_IRQ_STATUS, irqstat);
@@ -1243,7 +1252,7 @@ sl811h_hub_control(
 				break;
 
 			/* 20 msec of resume/K signaling, other irqs blocked */
-			DBG("start resume...\n");
+			dev_dbg(hcd->self.controller, "start resume...\n");
 			sl811->irq_enable = 0;
 			sl811_write(sl811, SL11H_IRQ_ENABLE,
 						sl811->irq_enable);
@@ -1281,7 +1290,8 @@ sl811h_hub_control(
 #ifndef	VERBOSE
 	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
 #endif
-		DBG("GetPortStatus %08x\n", sl811->port1);
+		dev_dbg(hcd->self.controller, "GetPortStatus %08x\n",
+			sl811->port1);
 		break;
 	case SetPortFeature:
 		if (wIndex != 1 || wLength != 0)
@@ -1293,7 +1303,7 @@ sl811h_hub_control(
 			if (!(sl811->port1 & USB_PORT_STAT_ENABLE))
 				goto error;
 
-			DBG("suspend...\n");
+			dev_dbg(hcd->self.controller,"suspend...\n");
 			sl811->ctrl1 &= ~SL11H_CTL1MASK_SOF_ENA;
 			sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
 			break;
@@ -1338,7 +1348,7 @@ static int
 sl811h_bus_suspend(struct usb_hcd *hcd)
 {
 	// SOFs off
-	DBG("%s\n", __func__);
+	dev_dbg(hcd->self.controller, "%s\n", __func__);
 	return 0;
 }
 
@@ -1346,7 +1356,7 @@ static int
 sl811h_bus_resume(struct usb_hcd *hcd)
 {
 	// SOFs on
-	DBG("%s\n", __func__);
+	dev_dbg(hcd->self.controller, "%s\n", __func__);
 	return 0;
 }
 
@@ -1360,16 +1370,6 @@ sl811h_bus_resume(struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct sl811 *sl811) { }
-static inline void remove_debug_file(struct sl811 *sl811) { }
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
 static void dump_irq(struct seq_file *s, char *label, u8 mask)
 {
 	seq_printf(s, "%s %02x%s%s%s%s%s%s\n", label, mask,
@@ -1381,7 +1381,7 @@ static void dump_irq(struct seq_file *s, char *label, u8 mask)
 		(mask & SL11H_INTMASK_DP) ? " dp" : "");
 }
 
-static int proc_sl811h_show(struct seq_file *s, void *unused)
+static int sl811h_show(struct seq_file *s, void *unused)
 {
 	struct sl811		*sl811 = s->private;
 	struct sl811h_ep	*ep;
@@ -1492,34 +1492,31 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
 	return 0;
 }
 
-static int proc_sl811h_open(struct inode *inode, struct file *file)
+static int sl811h_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_sl811h_show, PDE_DATA(inode));
+	return single_open(file, sl811h_show, inode->i_private);
 }
 
-static const struct file_operations proc_ops = {
-	.open		= proc_sl811h_open,
+static const struct file_operations debug_ops = {
+	.open		= sl811h_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
 
 /* expect just one sl811 per system */
-static const char proc_filename[] = "driver/sl811h";
-
 static void create_debug_file(struct sl811 *sl811)
 {
-	sl811->pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, sl811);
+	sl811->debug_file = debugfs_create_file("sl811h", S_IRUGO,
+						usb_debug_root, sl811,
+						&debug_ops);
 }
 
 static void remove_debug_file(struct sl811 *sl811)
 {
-	if (sl811->pde)
-		remove_proc_entry(proc_filename, NULL);
+	debugfs_remove(sl811->debug_file);
 }
 
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 static void
@@ -1648,7 +1645,7 @@ sl811h_probe(struct platform_device *dev)
 
 	/* refuse to confuse usbcore */
 	if (dev->dev.dma_mask) {
-		DBG("no we won't dma\n");
+		dev_dbg(&dev->dev, "no we won't dma\n");
 		return -EINVAL;
 	}
 
@@ -1694,7 +1691,7 @@ sl811h_probe(struct platform_device *dev)
 
 	spin_lock_init(&sl811->lock);
 	INIT_LIST_HEAD(&sl811->async);
-	sl811->board = dev->dev.platform_data;
+	sl811->board = dev_get_platdata(&dev->dev);
 	init_timer(&sl811->timer);
 	sl811->timer.function = sl811h_timer;
 	sl811->timer.data = (unsigned long) sl811;
@@ -1716,7 +1713,7 @@ sl811h_probe(struct platform_device *dev)
 		break;
 	default:
 		/* reject case 0, SL11S is less functional */
-		DBG("chiprev %02x\n", tmp);
+		dev_dbg(&dev->dev, "chiprev %02x\n", tmp);
 		retval = -ENXIO;
 		goto err6;
 	}
@@ -1747,7 +1744,7 @@ sl811h_probe(struct platform_device *dev)
 	if (!ioaddr)
 		iounmap(addr_reg);
  err2:
-	DBG("init error, %d\n", retval);
+	dev_dbg(&dev->dev, "init error, %d\n", retval);
 	return retval;
 }
 
diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h
index b6b8c1f..1e23ef4 100644
--- a/drivers/usb/host/sl811.h
+++ b/drivers/usb/host/sl811.h
@@ -122,7 +122,7 @@ struct sl811 {
 	void __iomem		*addr_reg;
 	void __iomem		*data_reg;
 	struct sl811_platform_data	*board;
-	struct proc_dir_entry	*pde;
+	struct dentry 		*debug_file;
 
 	unsigned long		stat_insrmv;
 	unsigned long		stat_wake;
@@ -242,25 +242,8 @@ sl811_read_buf(struct sl811 *sl811, int addr, void *buf, size_t count)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
-#define DBG(stuff...)		printk(KERN_DEBUG "sl811: " stuff)
-#else
-#define DBG(stuff...)		do{}while(0)
-#endif
-
-#ifdef VERBOSE
-#    define VDBG		DBG
-#else
-#    define VDBG(stuff...)	do{}while(0)
-#endif
-
 #ifdef PACKET_TRACE
-#    define PACKET		VDBG
+#    define PACKET		pr_debug("sl811: "stuff)
 #else
 #    define PACKET(stuff...)	do{}while(0)
 #endif
-
-#define ERR(stuff...)		printk(KERN_ERR "sl811: " stuff)
-#define WARNING(stuff...)	printk(KERN_WARNING "sl811: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "sl811: " stuff)
-
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 5c124bf..e402beb 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -1809,9 +1809,9 @@ static int u132_hcd_start(struct usb_hcd *hcd)
 		struct platform_device *pdev =
 			to_platform_device(hcd->self.controller);
 		u16 vendor = ((struct u132_platform_data *)
-			(pdev->dev.platform_data))->vendor;
+			dev_get_platdata(&pdev->dev))->vendor;
 		u16 device = ((struct u132_platform_data *)
-			(pdev->dev.platform_data))->device;
+			dev_get_platdata(&pdev->dev))->device;
 		mutex_lock(&u132->sw_lock);
 		msleep(10);
 		if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
@@ -3034,7 +3034,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
 	int addrs = MAX_U132_ADDRS;
 	int udevs = MAX_U132_UDEVS;
 	int endps = MAX_U132_ENDPS;
-	u132->board = pdev->dev.platform_data;
+	u132->board = dev_get_platdata(&pdev->dev);
 	u132->platform_dev = pdev;
 	u132->power = 0;
 	u132->reset = 0;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 1d35459..93f3fdf 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -461,8 +461,15 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
 	}
 }
 
+/* Updates Link Status for USB 2.1 port */
+static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg)
+{
+	if ((status_reg & PORT_PLS_MASK) == XDEV_U2)
+		*status |= USB_PORT_STAT_L1;
+}
+
 /* Updates Link Status for super Speed port */
-static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
+static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg)
 {
 	u32 pls = status_reg & PORT_PLS_MASK;
 
@@ -534,6 +541,120 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
 	}
 }
 
+/*
+ * Converts a raw xHCI port status into the format that external USB 2.0 or USB
+ * 3.0 hubs use.
+ *
+ * Possible side effects:
+ *  - Mark a port as being done with device resume,
+ *    and ring the endpoint doorbells.
+ *  - Stop the Synopsys redriver Compliance Mode polling.
+ */
+static u32 xhci_get_port_status(struct usb_hcd *hcd,
+		struct xhci_bus_state *bus_state,
+		__le32 __iomem **port_array,
+		u16 wIndex, u32 raw_port_status)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	u32 status = 0;
+	int slot_id;
+
+	/* wPortChange bits */
+	if (raw_port_status & PORT_CSC)
+		status |= USB_PORT_STAT_C_CONNECTION << 16;
+	if (raw_port_status & PORT_PEC)
+		status |= USB_PORT_STAT_C_ENABLE << 16;
+	if ((raw_port_status & PORT_OCC))
+		status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+	if ((raw_port_status & PORT_RC))
+		status |= USB_PORT_STAT_C_RESET << 16;
+	/* USB3.0 only */
+	if (hcd->speed == HCD_USB3) {
+		if ((raw_port_status & PORT_PLC))
+			status |= USB_PORT_STAT_C_LINK_STATE << 16;
+		if ((raw_port_status & PORT_WRC))
+			status |= USB_PORT_STAT_C_BH_RESET << 16;
+	}
+
+	if (hcd->speed != HCD_USB3) {
+		if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3
+				&& (raw_port_status & PORT_POWER))
+			status |= USB_PORT_STAT_SUSPEND;
+	}
+	if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
+			!DEV_SUPERSPEED(raw_port_status)) {
+		if ((raw_port_status & PORT_RESET) ||
+				!(raw_port_status & PORT_PE))
+			return 0xffffffff;
+		if (time_after_eq(jiffies,
+					bus_state->resume_done[wIndex])) {
+			xhci_dbg(xhci, "Resume USB2 port %d\n",
+					wIndex + 1);
+			bus_state->resume_done[wIndex] = 0;
+			clear_bit(wIndex, &bus_state->resuming_ports);
+			xhci_set_link_state(xhci, port_array, wIndex,
+					XDEV_U0);
+			xhci_dbg(xhci, "set port %d resume\n",
+					wIndex + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					wIndex + 1);
+			if (!slot_id) {
+				xhci_dbg(xhci, "slot_id is zero\n");
+				return 0xffffffff;
+			}
+			xhci_ring_device(xhci, slot_id);
+			bus_state->port_c_suspend |= 1 << wIndex;
+			bus_state->suspended_ports &= ~(1 << wIndex);
+		} else {
+			/*
+			 * The resume has been signaling for less than
+			 * 20ms. Report the port status as SUSPEND,
+			 * let the usbcore check port status again
+			 * and clear resume signaling later.
+			 */
+			status |= USB_PORT_STAT_SUSPEND;
+		}
+	}
+	if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0
+			&& (raw_port_status & PORT_POWER)
+			&& (bus_state->suspended_ports & (1 << wIndex))) {
+		bus_state->suspended_ports &= ~(1 << wIndex);
+		if (hcd->speed != HCD_USB3)
+			bus_state->port_c_suspend |= 1 << wIndex;
+	}
+	if (raw_port_status & PORT_CONNECT) {
+		status |= USB_PORT_STAT_CONNECTION;
+		status |= xhci_port_speed(raw_port_status);
+	}
+	if (raw_port_status & PORT_PE)
+		status |= USB_PORT_STAT_ENABLE;
+	if (raw_port_status & PORT_OC)
+		status |= USB_PORT_STAT_OVERCURRENT;
+	if (raw_port_status & PORT_RESET)
+		status |= USB_PORT_STAT_RESET;
+	if (raw_port_status & PORT_POWER) {
+		if (hcd->speed == HCD_USB3)
+			status |= USB_SS_PORT_STAT_POWER;
+		else
+			status |= USB_PORT_STAT_POWER;
+	}
+	/* Update Port Link State */
+	if (hcd->speed == HCD_USB3) {
+		xhci_hub_report_usb3_link_state(&status, raw_port_status);
+		/*
+		 * Verify if all USB3 Ports Have entered U0 already.
+		 * Delete Compliance Mode Timer if so.
+		 */
+		xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex);
+	} else {
+		xhci_hub_report_usb2_link_state(&status, raw_port_status);
+	}
+	if (bus_state->port_c_suspend & (1 << wIndex))
+		status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+
+	return status;
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		u16 wIndex, char *buf, u16 wLength)
 {
@@ -598,104 +719,20 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		if (!wIndex || wIndex > max_ports)
 			goto error;
 		wIndex--;
-		status = 0;
 		temp = xhci_readl(xhci, port_array[wIndex]);
 		if (temp == 0xffffffff) {
 			retval = -ENODEV;
 			break;
 		}
-		xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n", wIndex, temp);
-
-		/* wPortChange bits */
-		if (temp & PORT_CSC)
-			status |= USB_PORT_STAT_C_CONNECTION << 16;
-		if (temp & PORT_PEC)
-			status |= USB_PORT_STAT_C_ENABLE << 16;
-		if ((temp & PORT_OCC))
-			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
-		if ((temp & PORT_RC))
-			status |= USB_PORT_STAT_C_RESET << 16;
-		/* USB3.0 only */
-		if (hcd->speed == HCD_USB3) {
-			if ((temp & PORT_PLC))
-				status |= USB_PORT_STAT_C_LINK_STATE << 16;
-			if ((temp & PORT_WRC))
-				status |= USB_PORT_STAT_C_BH_RESET << 16;
-		}
+		status = xhci_get_port_status(hcd, bus_state, port_array,
+				wIndex, temp);
+		if (status == 0xffffffff)
+			goto error;
 
-		if (hcd->speed != HCD_USB3) {
-			if ((temp & PORT_PLS_MASK) == XDEV_U3
-					&& (temp & PORT_POWER))
-				status |= USB_PORT_STAT_SUSPEND;
-		}
-		if ((temp & PORT_PLS_MASK) == XDEV_RESUME &&
-				!DEV_SUPERSPEED(temp)) {
-			if ((temp & PORT_RESET) || !(temp & PORT_PE))
-				goto error;
-			if (time_after_eq(jiffies,
-					bus_state->resume_done[wIndex])) {
-				xhci_dbg(xhci, "Resume USB2 port %d\n",
-					wIndex + 1);
-				bus_state->resume_done[wIndex] = 0;
-				clear_bit(wIndex, &bus_state->resuming_ports);
-				xhci_set_link_state(xhci, port_array, wIndex,
-							XDEV_U0);
-				xhci_dbg(xhci, "set port %d resume\n",
-					wIndex + 1);
-				slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-								 wIndex + 1);
-				if (!slot_id) {
-					xhci_dbg(xhci, "slot_id is zero\n");
-					goto error;
-				}
-				xhci_ring_device(xhci, slot_id);
-				bus_state->port_c_suspend |= 1 << wIndex;
-				bus_state->suspended_ports &= ~(1 << wIndex);
-			} else {
-				/*
-				 * The resume has been signaling for less than
-				 * 20ms. Report the port status as SUSPEND,
-				 * let the usbcore check port status again
-				 * and clear resume signaling later.
-				 */
-				status |= USB_PORT_STAT_SUSPEND;
-			}
-		}
-		if ((temp & PORT_PLS_MASK) == XDEV_U0
-			&& (temp & PORT_POWER)
-			&& (bus_state->suspended_ports & (1 << wIndex))) {
-			bus_state->suspended_ports &= ~(1 << wIndex);
-			if (hcd->speed != HCD_USB3)
-				bus_state->port_c_suspend |= 1 << wIndex;
-		}
-		if (temp & PORT_CONNECT) {
-			status |= USB_PORT_STAT_CONNECTION;
-			status |= xhci_port_speed(temp);
-		}
-		if (temp & PORT_PE)
-			status |= USB_PORT_STAT_ENABLE;
-		if (temp & PORT_OC)
-			status |= USB_PORT_STAT_OVERCURRENT;
-		if (temp & PORT_RESET)
-			status |= USB_PORT_STAT_RESET;
-		if (temp & PORT_POWER) {
-			if (hcd->speed == HCD_USB3)
-				status |= USB_SS_PORT_STAT_POWER;
-			else
-				status |= USB_PORT_STAT_POWER;
-		}
-		/* Update Port Link State for super speed ports*/
-		if (hcd->speed == HCD_USB3) {
-			xhci_hub_report_link_state(&status, temp);
-			/*
-			 * Verify if all USB3 Ports Have entered U0 already.
-			 * Delete Compliance Mode Timer if so.
-			 */
-			xhci_del_comp_mod_timer(xhci, temp, wIndex);
-		}
-		if (bus_state->port_c_suspend & (1 << wIndex))
-			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+		xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n",
+				wIndex, temp);
 		xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
+
 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
 		break;
 	case SetPortFeature:
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index df6978a..6f8c2fd 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -24,6 +24,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
 
 #include "xhci.h"
 
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index f00cb20..7296068 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -249,13 +249,15 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 	 * writers.
 	 *
 	 * Unconditionally switch the ports back to xHCI after a system resume.
-	 * We can't tell whether the EHCI or xHCI controller will be resumed
-	 * first, so we have to do the port switchover in both drivers.  Writing
-	 * a '1' to the port switchover registers should have no effect if the
-	 * port was already switched over.
+	 * It should not matter whether the EHCI or xHCI controller is
+	 * resumed first. It's enough to do the switchover in xHCI because
+	 * USB core won't notice anything as the hub driver doesn't start
+	 * running again until after all the devices (including both EHCI and
+	 * xHCI host controllers) have been resumed.
 	 */
-	if (usb_is_intel_switchable_xhci(pdev))
-		usb_enable_xhci_ports(pdev);
+
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+		usb_enable_intel_xhci_ports(pdev);
 
 	retval = xhci_resume(xhci, hibernated);
 	return retval;
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 51e22bf..412fe8d 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -186,11 +186,37 @@ static int xhci_plat_remove(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int xhci_plat_suspend(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_suspend(xhci);
+}
+
+static int xhci_plat_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_resume(xhci, 0);
+}
+
+static const struct dev_pm_ops xhci_plat_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+};
+#define DEV_PM_OPS	(&xhci_plat_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver usb_xhci_driver = {
 	.probe	= xhci_plat_probe,
 	.remove	= xhci_plat_remove,
 	.driver	= {
 		.name = "xhci-hcd",
+		.pm = DEV_PM_OPS,
 	},
 };
 MODULE_ALIAS("platform:xhci-hcd");
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 41eb4fc..adb106d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -27,6 +27,7 @@
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/dmi.h>
+#include <linux/dma-mapping.h>
 
 #include "xhci.h"
 
@@ -3075,8 +3076,8 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci,
 		/* Are streams already being freed for the endpoint? */
 		if (ep_state & EP_GETTING_NO_STREAMS) {
 			xhci_warn(xhci, "WARN Can't disable streams for "
-					"endpoint 0x%x\n, "
-					"streams are being disabled already.",
+					"endpoint 0x%x, "
+					"streams are being disabled already\n",
 					eps[i]->desc.bEndpointAddress);
 			return 0;
 		}
@@ -3084,8 +3085,8 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci,
 		if (!(ep_state & EP_HAS_STREAMS) &&
 				!(ep_state & EP_GETTING_STREAMS)) {
 			xhci_warn(xhci, "WARN Can't disable streams for "
-					"endpoint 0x%x\n, "
-					"streams are already disabled!",
+					"endpoint 0x%x, "
+					"streams are already disabled!\n",
 					eps[i]->desc.bEndpointAddress);
 			xhci_warn(xhci, "WARN xhci_free_streams() called "
 					"with non-streams endpoint\n");
@@ -4353,7 +4354,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
 				state_name, sel);
 	else
 		dev_dbg(&udev->dev, "Device-initiated %s disabled "
-				"due to long PEL %llu\n ms",
+				"due to long PEL %llu ms\n",
 				state_name, pel);
 	return USB3_LPM_DISABLED;
 }
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a51e7d6..ca91420 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -200,6 +200,19 @@ config USB_TEST
 	  See <http://www.linux-usb.org/usbtest/> for more information,
 	  including sample test device firmware and "how to use it".
 
+config USB_EHSET_TEST_FIXTURE
+        tristate "USB EHSET Test Fixture driver"
+        help
+	  Say Y here if you want to support the special test fixture device
+	  used for the USB-IF Embedded Host High-Speed Electrical Test procedure.
+
+	  When the test fixture is connected, it can enumerate as one of several
+	  VID/PID pairs. This driver then initiates a corresponding test mode on
+	  the downstream port to which the test fixture is attached.
+
+	  See <http://www.usb.org/developers/onthego/EHSET_v1.01.pdf> for more
+	  information.
+
 config USB_ISIGHTFW
 	tristate "iSight firmware loading support"
 	select FW_LOADER
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 3e1bd70..e748fd5 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -2,9 +2,6 @@
 # Makefile for the rest of the USB drivers
 # (the ones that don't fit into any other categories)
 #
-
-ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
-
 obj-$(CONFIG_USB_ADUTUX)		+= adutux.o
 obj-$(CONFIG_USB_APPLEDISPLAY)		+= appledisplay.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)	+= cypress_cy7c63.o
@@ -22,6 +19,7 @@ obj-$(CONFIG_USB_LED)			+= usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)		+= legousbtower.o
 obj-$(CONFIG_USB_RIO500)		+= rio500.o
 obj-$(CONFIG_USB_TEST)			+= usbtest.o
+obj-$(CONFIG_USB_EHSET_TEST_FIXTURE)    += ehset.o
 obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
 obj-$(CONFIG_USB_USS720)		+= uss720.o
 obj-$(CONFIG_USB_SEVSEG)		+= usbsevseg.o
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index eb3c8c1..7078e9b 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -18,6 +18,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -27,30 +29,11 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 
-#ifdef CONFIG_USB_DEBUG
-static int debug = 5;
-#else
-static int debug = 1;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(lvl, format, arg...)	\
-do {								\
-	if (debug >= lvl)						\
-		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg);	\
-} while (0)
-
-
 /* Version Information */
 #define DRIVER_VERSION "v0.0.13"
 #define DRIVER_AUTHOR "John Homppi"
 #define DRIVER_DESC "adutux (see www.ontrak.net)"
 
-/* Module parameters */
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 /* Define these values to match your device */
 #define ADU_VENDOR_ID 0x0a07
 #define ADU_PRODUCT_ID 0x0064
@@ -124,19 +107,11 @@ static DEFINE_MUTEX(adutux_mutex);
 
 static struct usb_driver adu_driver;
 
-static void adu_debug_data(int level, const char *function, int size,
-			   const unsigned char *data)
+static inline void adu_debug_data(struct device *dev, const char *function,
+				  int size, const unsigned char *data)
 {
-	int i;
-
-	if (debug < level)
-		return;
-
-	printk(KERN_DEBUG "%s: %s - length = %d, data = ",
-	       __FILE__, function, size);
-	for (i = 0; i < size; ++i)
-		printk("%.2x ", data[i]);
-	printk("\n");
+	dev_dbg(dev, "%s - length = %d, data = %*ph\n",
+		function, size, size, data);
 }
 
 /**
@@ -147,12 +122,8 @@ static void adu_abort_transfers(struct adu_device *dev)
 {
 	unsigned long flags;
 
-	dbg(2, " %s : enter", __func__);
-
-	if (dev->udev == NULL) {
-		dbg(1, " %s : udev is null", __func__);
-		goto exit;
-	}
+	if (dev->udev == NULL)
+		return;
 
 	/* shutdown transfer */
 
@@ -170,15 +141,10 @@ static void adu_abort_transfers(struct adu_device *dev)
 		usb_kill_urb(dev->interrupt_out_urb);
 	} else
 		spin_unlock_irqrestore(&dev->buflock, flags);
-
-exit:
-	dbg(2, " %s : leave", __func__);
 }
 
 static void adu_delete(struct adu_device *dev)
 {
-	dbg(2, "%s enter", __func__);
-
 	/* free data structures */
 	usb_free_urb(dev->interrupt_in_urb);
 	usb_free_urb(dev->interrupt_out_urb);
@@ -187,8 +153,6 @@ static void adu_delete(struct adu_device *dev)
 	kfree(dev->interrupt_in_buffer);
 	kfree(dev->interrupt_out_buffer);
 	kfree(dev);
-
-	dbg(2, "%s : leave", __func__);
 }
 
 static void adu_interrupt_in_callback(struct urb *urb)
@@ -196,17 +160,17 @@ static void adu_interrupt_in_callback(struct urb *urb)
 	struct adu_device *dev = urb->context;
 	int status = urb->status;
 
-	dbg(4, " %s : enter, status %d", __func__, status);
-	adu_debug_data(5, __func__, urb->actual_length,
-		       urb->transfer_buffer);
+	adu_debug_data(&dev->udev->dev, __func__,
+		       urb->actual_length, urb->transfer_buffer);
 
 	spin_lock(&dev->buflock);
 
 	if (status != 0) {
 		if ((status != -ENOENT) && (status != -ECONNRESET) &&
 			(status != -ESHUTDOWN)) {
-			dbg(1, " %s : nonzero status received: %d",
-			    __func__, status);
+			dev_dbg(&dev->udev->dev,
+				"%s : nonzero status received: %d\n",
+				__func__, status);
 		}
 		goto exit;
 	}
@@ -220,10 +184,11 @@ static void adu_interrupt_in_callback(struct urb *urb)
 				dev->interrupt_in_buffer, urb->actual_length);
 
 			dev->read_buffer_length += urb->actual_length;
-			dbg(2, " %s reading  %d ", __func__,
-			    urb->actual_length);
+			dev_dbg(&dev->udev->dev,"%s reading  %d\n", __func__,
+				urb->actual_length);
 		} else {
-			dbg(1, " %s : read_buffer overflow", __func__);
+			dev_dbg(&dev->udev->dev,"%s : read_buffer overflow\n",
+				__func__);
 		}
 	}
 
@@ -232,9 +197,6 @@ exit:
 	spin_unlock(&dev->buflock);
 	/* always wake up so we recover from errors */
 	wake_up_interruptible(&dev->read_wait);
-	adu_debug_data(5, __func__, urb->actual_length,
-		       urb->transfer_buffer);
-	dbg(4, " %s : leave, status %d", __func__, status);
 }
 
 static void adu_interrupt_out_callback(struct urb *urb)
@@ -242,27 +204,23 @@ static void adu_interrupt_out_callback(struct urb *urb)
 	struct adu_device *dev = urb->context;
 	int status = urb->status;
 
-	dbg(4, " %s : enter, status %d", __func__, status);
-	adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+	adu_debug_data(&dev->udev->dev, __func__,
+		       urb->actual_length, urb->transfer_buffer);
 
 	if (status != 0) {
 		if ((status != -ENOENT) &&
 		    (status != -ECONNRESET)) {
-			dbg(1, " %s :nonzero status received: %d",
-			    __func__, status);
+			dev_dbg(&dev->udev->dev,
+				"%s :nonzero status received: %d\n", __func__,
+				status);
 		}
-		goto exit;
+		return;
 	}
 
 	spin_lock(&dev->buflock);
 	dev->out_urb_finished = 1;
 	wake_up(&dev->write_wait);
 	spin_unlock(&dev->buflock);
-exit:
-
-	adu_debug_data(5, __func__, urb->actual_length,
-		       urb->transfer_buffer);
-	dbg(4, " %s : leave, status %d", __func__, status);
 }
 
 static int adu_open(struct inode *inode, struct file *file)
@@ -272,20 +230,16 @@ static int adu_open(struct inode *inode, struct file *file)
 	int subminor;
 	int retval;
 
-	dbg(2, "%s : enter", __func__);
-
 	subminor = iminor(inode);
 
 	retval = mutex_lock_interruptible(&adutux_mutex);
-	if (retval) {
-		dbg(2, "%s : mutex lock failed", __func__);
+	if (retval)
 		goto exit_no_lock;
-	}
 
 	interface = usb_find_interface(&adu_driver, subminor);
 	if (!interface) {
-		printk(KERN_ERR "adutux: %s - error, can't find device for "
-		       "minor %d\n", __func__, subminor);
+		pr_err("%s - error, can't find device for minor %d\n",
+		       __func__, subminor);
 		retval = -ENODEV;
 		goto exit_no_device;
 	}
@@ -303,7 +257,8 @@ static int adu_open(struct inode *inode, struct file *file)
 	}
 
 	++dev->open_count;
-	dbg(2, "%s : open count %d", __func__, dev->open_count);
+	dev_dbg(&dev->udev->dev, "%s: open count %d\n", __func__,
+		dev->open_count);
 
 	/* save device in the file's private structure */
 	file->private_data = dev;
@@ -333,23 +288,19 @@ static int adu_open(struct inode *inode, struct file *file)
 exit_no_device:
 	mutex_unlock(&adutux_mutex);
 exit_no_lock:
-	dbg(2, "%s : leave, return value %d ", __func__, retval);
 	return retval;
 }
 
 static void adu_release_internal(struct adu_device *dev)
 {
-	dbg(2, " %s : enter", __func__);
-
 	/* decrement our usage count for the device */
 	--dev->open_count;
-	dbg(2, " %s : open count %d", __func__, dev->open_count);
+	dev_dbg(&dev->udev->dev, "%s : open count %d\n", __func__,
+		dev->open_count);
 	if (dev->open_count <= 0) {
 		adu_abort_transfers(dev);
 		dev->open_count = 0;
 	}
-
-	dbg(2, " %s : leave", __func__);
 }
 
 static int adu_release(struct inode *inode, struct file *file)
@@ -357,17 +308,13 @@ static int adu_release(struct inode *inode, struct file *file)
 	struct adu_device *dev;
 	int retval = 0;
 
-	dbg(2, " %s : enter", __func__);
-
 	if (file == NULL) {
-		dbg(1, " %s : file is NULL", __func__);
 		retval = -ENODEV;
 		goto exit;
 	}
 
 	dev = file->private_data;
 	if (dev == NULL) {
-		dbg(1, " %s : object is NULL", __func__);
 		retval = -ENODEV;
 		goto exit;
 	}
@@ -375,7 +322,7 @@ static int adu_release(struct inode *inode, struct file *file)
 	mutex_lock(&adutux_mutex); /* not interruptible */
 
 	if (dev->open_count <= 0) {
-		dbg(1, " %s : device not opened", __func__);
+		dev_dbg(&dev->udev->dev, "%s : device not opened\n", __func__);
 		retval = -ENODEV;
 		goto unlock;
 	}
@@ -389,7 +336,6 @@ static int adu_release(struct inode *inode, struct file *file)
 unlock:
 	mutex_unlock(&adutux_mutex);
 exit:
-	dbg(2, " %s : leave, return value %d", __func__, retval);
 	return retval;
 }
 
@@ -406,35 +352,32 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 	unsigned long flags;
 	DECLARE_WAITQUEUE(wait, current);
 
-	dbg(2, " %s : enter, count = %Zd, file=%p", __func__, count, file);
-
 	dev = file->private_data;
-	dbg(2, " %s : dev=%p", __func__, dev);
-
 	if (mutex_lock_interruptible(&dev->mtx))
 		return -ERESTARTSYS;
 
 	/* verify that the device wasn't unplugged */
 	if (dev->udev == NULL) {
 		retval = -ENODEV;
-		printk(KERN_ERR "adutux: No device or device unplugged %d\n",
-		       retval);
+		pr_err("No device or device unplugged %d\n", retval);
 		goto exit;
 	}
 
 	/* verify that some data was requested */
 	if (count == 0) {
-		dbg(1, " %s : read request of 0 bytes", __func__);
+		dev_dbg(&dev->udev->dev, "%s : read request of 0 bytes\n",
+			__func__);
 		goto exit;
 	}
 
 	timeout = COMMAND_TIMEOUT;
-	dbg(2, " %s : about to start looping", __func__);
+	dev_dbg(&dev->udev->dev, "%s : about to start looping\n", __func__);
 	while (bytes_to_read) {
 		int data_in_secondary = dev->secondary_tail - dev->secondary_head;
-		dbg(2, " %s : while, data_in_secondary=%d, status=%d",
-		    __func__, data_in_secondary,
-		    dev->interrupt_in_urb->status);
+		dev_dbg(&dev->udev->dev,
+			"%s : while, data_in_secondary=%d, status=%d\n",
+			__func__, data_in_secondary,
+			dev->interrupt_in_urb->status);
 
 		if (data_in_secondary) {
 			/* drain secondary buffer */
@@ -457,8 +400,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 			if (dev->read_buffer_length) {
 				/* we secure access to the primary */
 				char *tmp;
-				dbg(2, " %s : swap, read_buffer_length = %d",
-				    __func__, dev->read_buffer_length);
+				dev_dbg(&dev->udev->dev,
+					"%s : swap, read_buffer_length = %d\n",
+					__func__, dev->read_buffer_length);
 				tmp = dev->read_buffer_secondary;
 				dev->read_buffer_secondary = dev->read_buffer_primary;
 				dev->read_buffer_primary = tmp;
@@ -473,10 +417,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 				if (!dev->read_urb_finished) {
 					/* somebody is doing IO */
 					spin_unlock_irqrestore(&dev->buflock, flags);
-					dbg(2, " %s : submitted already", __func__);
+					dev_dbg(&dev->udev->dev,
+						"%s : submitted already\n",
+						__func__);
 				} else {
 					/* we must initiate input */
-					dbg(2, " %s : initiate input", __func__);
+					dev_dbg(&dev->udev->dev,
+						"%s : initiate input\n",
+						__func__);
 					dev->read_urb_finished = 0;
 					spin_unlock_irqrestore(&dev->buflock, flags);
 
@@ -494,7 +442,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 						if (retval == -ENOMEM) {
 							retval = bytes_read ? bytes_read : -ENOMEM;
 						}
-						dbg(2, " %s : submit failed", __func__);
+						dev_dbg(&dev->udev->dev,
+							"%s : submit failed\n",
+							__func__);
 						goto exit;
 					}
 				}
@@ -513,13 +463,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 				remove_wait_queue(&dev->read_wait, &wait);
 
 				if (timeout <= 0) {
-					dbg(2, " %s : timeout", __func__);
+					dev_dbg(&dev->udev->dev,
+						"%s : timeout\n", __func__);
 					retval = bytes_read ? bytes_read : -ETIMEDOUT;
 					goto exit;
 				}
 
 				if (signal_pending(current)) {
-					dbg(2, " %s : signal pending", __func__);
+					dev_dbg(&dev->udev->dev,
+						"%s : signal pending\n",
+						__func__);
 					retval = bytes_read ? bytes_read : -EINTR;
 					goto exit;
 				}
@@ -552,7 +505,6 @@ exit:
 	/* unlock the device */
 	mutex_unlock(&dev->mtx);
 
-	dbg(2, " %s : leave, return value %d", __func__, retval);
 	return retval;
 }
 
@@ -567,8 +519,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 	unsigned long flags;
 	int retval;
 
-	dbg(2, " %s : enter, count = %Zd", __func__, count);
-
 	dev = file->private_data;
 
 	retval = mutex_lock_interruptible(&dev->mtx);
@@ -578,14 +528,14 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 	/* verify that the device wasn't unplugged */
 	if (dev->udev == NULL) {
 		retval = -ENODEV;
-		printk(KERN_ERR "adutux: No device or device unplugged %d\n",
-		       retval);
+		pr_err("No device or device unplugged %d\n", retval);
 		goto exit;
 	}
 
 	/* verify that we actually have some data to write */
 	if (count == 0) {
-		dbg(1, " %s : write request of 0 bytes", __func__);
+		dev_dbg(&dev->udev->dev, "%s : write request of 0 bytes\n",
+			__func__);
 		goto exit;
 	}
 
@@ -598,13 +548,15 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 
 			mutex_unlock(&dev->mtx);
 			if (signal_pending(current)) {
-				dbg(1, " %s : interrupted", __func__);
+				dev_dbg(&dev->udev->dev, "%s : interrupted\n",
+					__func__);
 				set_current_state(TASK_RUNNING);
 				retval = -EINTR;
 				goto exit_onqueue;
 			}
 			if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
-				dbg(1, "%s - command timed out.", __func__);
+				dev_dbg(&dev->udev->dev,
+					"%s - command timed out.\n", __func__);
 				retval = -ETIMEDOUT;
 				goto exit_onqueue;
 			}
@@ -615,18 +567,22 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 				goto exit_nolock;
 			}
 
-			dbg(4, " %s : in progress, count = %Zd", __func__, count);
+			dev_dbg(&dev->udev->dev,
+				"%s : in progress, count = %Zd\n",
+				__func__, count);
 		} else {
 			spin_unlock_irqrestore(&dev->buflock, flags);
 			set_current_state(TASK_RUNNING);
 			remove_wait_queue(&dev->write_wait, &waita);
-			dbg(4, " %s : sending, count = %Zd", __func__, count);
+			dev_dbg(&dev->udev->dev, "%s : sending, count = %Zd\n",
+				__func__, count);
 
 			/* write the data into interrupt_out_buffer from userspace */
 			buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint);
 			bytes_to_write = count > buffer_size ? buffer_size : count;
-			dbg(4, " %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
-			    __func__, buffer_size, count, bytes_to_write);
+			dev_dbg(&dev->udev->dev,
+				"%s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd\n",
+				__func__, buffer_size, count, bytes_to_write);
 
 			if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
 				retval = -EFAULT;
@@ -665,7 +621,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 exit:
 	mutex_unlock(&dev->mtx);
 exit_nolock:
-	dbg(2, " %s : leave, return value %d", __func__, retval);
 	return retval;
 
 exit_onqueue:
@@ -711,8 +666,6 @@ static int adu_probe(struct usb_interface *interface,
 	int out_end_size;
 	int i;
 
-	dbg(2, " %s : enter", __func__);
-
 	if (udev == NULL) {
 		dev_err(&interface->dev, "udev is NULL.\n");
 		goto exit;
@@ -812,7 +765,7 @@ static int adu_probe(struct usb_interface *interface,
 		dev_err(&interface->dev, "Could not retrieve serial number\n");
 		goto error;
 	}
-	dbg(2, " %s : serial_number=%s", __func__, dev->serial_number);
+	dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number);
 
 	/* we can register the device now, as it is ready */
 	usb_set_intfdata(interface, dev);
@@ -833,8 +786,6 @@ static int adu_probe(struct usb_interface *interface,
 		 udev->descriptor.idProduct, dev->serial_number,
 		 (dev->minor - ADU_MINOR_BASE));
 exit:
-	dbg(2, " %s : leave, return value %p (dev)", __func__, dev);
-
 	return retval;
 
 error:
@@ -852,8 +803,6 @@ static void adu_disconnect(struct usb_interface *interface)
 	struct adu_device *dev;
 	int minor;
 
-	dbg(2, " %s : enter", __func__);
-
 	dev = usb_get_intfdata(interface);
 
 	mutex_lock(&dev->mtx);	/* not interruptible */
@@ -866,7 +815,8 @@ static void adu_disconnect(struct usb_interface *interface)
 	usb_set_intfdata(interface, NULL);
 
 	/* if the device is not opened, then we clean up right now */
-	dbg(2, " %s : open count %d", __func__, dev->open_count);
+	dev_dbg(&dev->udev->dev, "%s : open count %d\n",
+		__func__, dev->open_count);
 	if (!dev->open_count)
 		adu_delete(dev);
 
@@ -874,8 +824,6 @@ static void adu_disconnect(struct usb_interface *interface)
 
 	dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
 		 (minor - ADU_MINOR_BASE));
-
-	dbg(2, " %s : leave", __func__);
 }
 
 /* usb specific object needed to register this driver with the usb subsystem */
diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c
new file mode 100644
index 0000000..d2864b3
--- /dev/null
+++ b/drivers/usb/misc/ehset.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/ch11.h>
+
+#define TEST_SE0_NAK_PID			0x0101
+#define TEST_J_PID				0x0102
+#define TEST_K_PID				0x0103
+#define TEST_PACKET_PID				0x0104
+#define TEST_HS_HOST_PORT_SUSPEND_RESUME	0x0106
+#define TEST_SINGLE_STEP_GET_DEV_DESC		0x0107
+#define TEST_SINGLE_STEP_SET_FEATURE		0x0108
+
+static int ehset_probe(struct usb_interface *intf,
+		       const struct usb_device_id *id)
+{
+	int ret = -EINVAL;
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_device *hub_udev = dev->parent;
+	struct usb_device_descriptor *buf;
+	u8 portnum = dev->portnum;
+	u16 test_pid = le16_to_cpu(dev->descriptor.idProduct);
+
+	switch (test_pid) {
+	case TEST_SE0_NAK_PID:
+		ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
+					USB_REQ_SET_FEATURE, USB_RT_PORT,
+					USB_PORT_FEAT_TEST,
+					(TEST_SE0_NAK << 8) | portnum,
+					NULL, 0, 1000);
+		break;
+	case TEST_J_PID:
+		ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
+					USB_REQ_SET_FEATURE, USB_RT_PORT,
+					USB_PORT_FEAT_TEST,
+					(TEST_J << 8) | portnum,
+					NULL, 0, 1000);
+		break;
+	case TEST_K_PID:
+		ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
+					USB_REQ_SET_FEATURE, USB_RT_PORT,
+					USB_PORT_FEAT_TEST,
+					(TEST_K << 8) | portnum,
+					NULL, 0, 1000);
+		break;
+	case TEST_PACKET_PID:
+		ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
+					USB_REQ_SET_FEATURE, USB_RT_PORT,
+					USB_PORT_FEAT_TEST,
+					(TEST_PACKET << 8) | portnum,
+					NULL, 0, 1000);
+		break;
+	case TEST_HS_HOST_PORT_SUSPEND_RESUME:
+		/* Test: wait for 15secs -> suspend -> 15secs delay -> resume */
+		msleep(15 * 1000);
+		ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
+					USB_REQ_SET_FEATURE, USB_RT_PORT,
+					USB_PORT_FEAT_SUSPEND, portnum,
+					NULL, 0, 1000);
+		if (ret < 0)
+			break;
+
+		msleep(15 * 1000);
+		ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
+					USB_REQ_CLEAR_FEATURE, USB_RT_PORT,
+					USB_PORT_FEAT_SUSPEND, portnum,
+					NULL, 0, 1000);
+		break;
+	case TEST_SINGLE_STEP_GET_DEV_DESC:
+		/* Test: wait for 15secs -> GetDescriptor request */
+		msleep(15 * 1000);
+		buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
+		ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+					USB_DT_DEVICE << 8, 0,
+					buf, USB_DT_DEVICE_SIZE,
+					USB_CTRL_GET_TIMEOUT);
+		kfree(buf);
+		break;
+	case TEST_SINGLE_STEP_SET_FEATURE:
+		/* unsupported for now */
+	default:
+		dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n",
+			__func__, test_pid);
+	}
+
+	return (ret < 0) ? ret : 0;
+}
+
+static void ehset_disconnect(struct usb_interface *intf)
+{
+}
+
+static const struct usb_device_id ehset_id_table[] = {
+	{ USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) },
+	{ USB_DEVICE(0x1a0a, TEST_J_PID) },
+	{ USB_DEVICE(0x1a0a, TEST_K_PID) },
+	{ USB_DEVICE(0x1a0a, TEST_PACKET_PID) },
+	{ USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) },
+	{ USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) },
+	{ USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) },
+	{ }			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ehset_id_table);
+
+static struct usb_driver ehset_driver = {
+	.name =		"usb_ehset_test",
+	.probe =	ehset_probe,
+	.disconnect =	ehset_disconnect,
+	.id_table =	ehset_id_table,
+};
+
+module_usb_driver(ehset_driver);
+
+MODULE_DESCRIPTION("USB Driver for EHSET Test Fixture");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index ac76229..b1d5953 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -129,19 +129,6 @@ MODULE_DESCRIPTION("LD USB Driver");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("LD USB Devices");
 
-#ifdef CONFIG_USB_DEBUG
-	static int debug = 1;
-#else
-	static int debug = 0;
-#endif
-
-/* Use our own dbg macro */
-#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
-
-/* Module parameters */
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 /* All interrupt in transfers are collected in a ring buffer to
  * avoid racing conditions and get better performance of the driver.
  */
@@ -256,8 +243,9 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
 		    status == -ESHUTDOWN) {
 			goto exit;
 		} else {
-			dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
-				 __func__, status);
+			dev_dbg(&dev->intf->dev,
+				"%s: nonzero status received: %d\n", __func__,
+				status);
 			spin_lock(&dev->rbsl);
 			goto resubmit; /* maybe we can recover */
 		}
@@ -272,8 +260,8 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
 			*actual_buffer = urb->actual_length;
 			memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
 			dev->ring_head = next_ring_head;
-			dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
-				 __func__, urb->actual_length);
+			dev_dbg(&dev->intf->dev, "%s: received %d bytes\n",
+				__func__, urb->actual_length);
 		} else {
 			dev_warn(&dev->intf->dev,
 				 "Ring buffer overflow, %d bytes dropped\n",
@@ -310,9 +298,9 @@ static void ld_usb_interrupt_out_callback(struct urb *urb)
 	if (status && !(status == -ENOENT ||
 			status == -ECONNRESET ||
 			status == -ESHUTDOWN))
-		dbg_info(&dev->intf->dev,
-			 "%s - nonzero write interrupt status received: %d\n",
-			 __func__, status);
+		dev_dbg(&dev->intf->dev,
+			"%s - nonzero write interrupt status received: %d\n",
+			__func__, status);
 
 	dev->interrupt_out_busy = 0;
 	wake_up_interruptible(&dev->write_wait);
@@ -585,7 +573,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
 	bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
 	if (bytes_to_write < count)
 		dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
-	dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write);
+	dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n",
+		__func__, count, bytes_to_write);
 
 	if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
 		retval = -EFAULT;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 8089479..eb37c95 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -75,6 +75,8 @@
  *   - move reset into open to clean out spurious data
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -87,28 +89,11 @@
 #include <linux/poll.h>
 
 
-#ifdef CONFIG_USB_DEBUG
-	static int debug = 4;
-#else
-	static int debug = 0;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(lvl, format, arg...)					\
-do {									\
-	if (debug >= lvl)						\
-		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg);	\
-} while (0)
-
 /* Version Information */
 #define DRIVER_VERSION "v0.96"
 #define DRIVER_AUTHOR "Juergen Stuber <starblue@sourceforge.net>"
 #define DRIVER_DESC "LEGO USB Tower Driver"
 
-/* Module parameters */
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
 
 /* The defaults are chosen to work with the latest versions of leJOS and NQC.
  */
@@ -298,18 +283,12 @@ static struct usb_driver tower_driver = {
 /**
  *	lego_usb_tower_debug_data
  */
-static inline void lego_usb_tower_debug_data (int level, const char *function, int size, const unsigned char *data)
+static inline void lego_usb_tower_debug_data(struct device *dev,
+					     const char *function, int size,
+					     const unsigned char *data)
 {
-	int i;
-
-	if (debug < level)
-		return;
-
-	printk (KERN_DEBUG "%s: %s - length = %d, data = ", __FILE__, function, size);
-	for (i = 0; i < size; ++i) {
-		printk ("%.2x ", data[i]);
-	}
-	printk ("\n");
+	dev_dbg(dev, "%s - length = %d, data = %*ph\n",
+		function, size, size, data);
 }
 
 
@@ -318,8 +297,6 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i
  */
 static inline void tower_delete (struct lego_usb_tower *dev)
 {
-	dbg(2, "%s: enter", __func__);
-
 	tower_abort_transfers (dev);
 
 	/* free data structures */
@@ -329,8 +306,6 @@ static inline void tower_delete (struct lego_usb_tower *dev)
 	kfree (dev->interrupt_in_buffer);
 	kfree (dev->interrupt_out_buffer);
 	kfree (dev);
-
-	dbg(2, "%s: leave", __func__);
 }
 
 
@@ -346,16 +321,13 @@ static int tower_open (struct inode *inode, struct file *file)
 	struct tower_reset_reply reset_reply;
 	int result;
 
-	dbg(2, "%s: enter", __func__);
-
 	nonseekable_open(inode, file);
 	subminor = iminor(inode);
 
 	interface = usb_find_interface (&tower_driver, subminor);
 
 	if (!interface) {
-		printk(KERN_ERR "%s - error, can't find device for minor %d\n",
-		       __func__, subminor);
+		pr_err("error, can't find device for minor %d\n", subminor);
 		retval = -ENODEV;
 		goto exit;
 	}
@@ -435,8 +407,6 @@ unlock_exit:
 	mutex_unlock(&dev->lock);
 
 exit:
-	dbg(2, "%s: leave, return value %d ", __func__, retval);
-
 	return retval;
 }
 
@@ -448,12 +418,9 @@ static int tower_release (struct inode *inode, struct file *file)
 	struct lego_usb_tower *dev;
 	int retval = 0;
 
-	dbg(2, "%s: enter", __func__);
-
 	dev = file->private_data;
 
 	if (dev == NULL) {
-		dbg(1, "%s: object is NULL", __func__);
 		retval = -ENODEV;
 		goto exit_nolock;
 	}
@@ -465,7 +432,8 @@ static int tower_release (struct inode *inode, struct file *file)
 	}
 
 	if (dev->open_count != 1) {
-		dbg(1, "%s: device not opened exactly once", __func__);
+		dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n",
+			__func__);
 		retval = -ENODEV;
 		goto unlock_exit;
 	}
@@ -491,7 +459,6 @@ unlock_exit:
 exit:
 	mutex_unlock(&open_disc_mutex);
 exit_nolock:
-	dbg(2, "%s: leave, return value %d", __func__, retval);
 	return retval;
 }
 
@@ -502,12 +469,8 @@ exit_nolock:
  */
 static void tower_abort_transfers (struct lego_usb_tower *dev)
 {
-	dbg(2, "%s: enter", __func__);
-
-	if (dev == NULL) {
-		dbg(1, "%s: dev is null", __func__);
-		goto exit;
-	}
+	if (dev == NULL)
+		return;
 
 	/* shutdown transfer */
 	if (dev->interrupt_in_running) {
@@ -518,9 +481,6 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
 	}
 	if (dev->interrupt_out_busy && dev->udev)
 		usb_kill_urb(dev->interrupt_out_urb);
-
-exit:
-	dbg(2, "%s: leave", __func__);
 }
 
 
@@ -553,8 +513,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
 	struct lego_usb_tower *dev;
 	unsigned int mask = 0;
 
-	dbg(2, "%s: enter", __func__);
-
 	dev = file->private_data;
 
 	if (!dev->udev)
@@ -571,8 +529,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
 		mask |= POLLOUT | POLLWRNORM;
 	}
 
-	dbg(2, "%s: leave, mask = %d", __func__, mask);
-
 	return mask;
 }
 
@@ -597,8 +553,6 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
 	int retval = 0;
 	unsigned long timeout = 0;
 
-	dbg(2, "%s: enter, count = %Zd", __func__, count);
-
 	dev = file->private_data;
 
 	/* lock this object */
@@ -610,13 +564,13 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
 	/* verify that the device wasn't unplugged */
 	if (dev->udev == NULL) {
 		retval = -ENODEV;
-		printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval);
+		pr_err("No device or device unplugged %d\n", retval);
 		goto unlock_exit;
 	}
 
 	/* verify that we actually have some data to read */
 	if (count == 0) {
-		dbg(1, "%s: read request of 0 bytes", __func__);
+		dev_dbg(&dev->udev->dev, "read request of 0 bytes\n");
 		goto unlock_exit;
 	}
 
@@ -672,7 +626,6 @@ unlock_exit:
 	mutex_unlock(&dev->lock);
 
 exit:
-	dbg(2, "%s: leave, return value %d", __func__, retval);
 	return retval;
 }
 
@@ -686,8 +639,6 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 	size_t bytes_to_write;
 	int retval = 0;
 
-	dbg(2, "%s: enter, count = %Zd", __func__, count);
-
 	dev = file->private_data;
 
 	/* lock this object */
@@ -699,13 +650,13 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 	/* verify that the device wasn't unplugged */
 	if (dev->udev == NULL) {
 		retval = -ENODEV;
-		printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval);
+		pr_err("No device or device unplugged %d\n", retval);
 		goto unlock_exit;
 	}
 
 	/* verify that we actually have some data to write */
 	if (count == 0) {
-		dbg(1, "%s: write request of 0 bytes", __func__);
+		dev_dbg(&dev->udev->dev, "write request of 0 bytes\n");
 		goto unlock_exit;
 	}
 
@@ -723,7 +674,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 
 	/* write the data into interrupt_out_buffer from userspace */
 	bytes_to_write = min_t(int, count, write_buffer_size);
-	dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write);
+	dev_dbg(&dev->udev->dev, "%s: count = %Zd, bytes_to_write = %Zd\n",
+		__func__, count, bytes_to_write);
 
 	if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
 		retval = -EFAULT;
@@ -757,8 +709,6 @@ unlock_exit:
 	mutex_unlock(&dev->lock);
 
 exit:
-	dbg(2, "%s: leave, return value %d", __func__, retval);
-
 	return retval;
 }
 
@@ -772,9 +722,8 @@ static void tower_interrupt_in_callback (struct urb *urb)
 	int status = urb->status;
 	int retval;
 
-	dbg(4, "%s: enter, status %d", __func__, status);
-
-	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+	lego_usb_tower_debug_data(&dev->udev->dev, __func__,
+				  urb->actual_length, urb->transfer_buffer);
 
 	if (status) {
 		if (status == -ENOENT ||
@@ -782,7 +731,9 @@ static void tower_interrupt_in_callback (struct urb *urb)
 		    status == -ESHUTDOWN) {
 			goto exit;
 		} else {
-			dbg(1, "%s: nonzero status received: %d", __func__, status);
+			dev_dbg(&dev->udev->dev,
+				"%s: nonzero status received: %d\n", __func__,
+				status);
 			goto resubmit; /* maybe we can recover */
 		}
 	}
@@ -795,9 +746,11 @@ static void tower_interrupt_in_callback (struct urb *urb)
 				urb->actual_length);
 			dev->read_buffer_length += urb->actual_length;
 			dev->read_last_arrival = jiffies;
-			dbg(3, "%s: received %d bytes", __func__, urb->actual_length);
+			dev_dbg(&dev->udev->dev, "%s: received %d bytes\n",
+				__func__, urb->actual_length);
 		} else {
-			printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length);
+			pr_warn("read_buffer overflow, %d bytes dropped\n",
+				urb->actual_length);
 		}
 		spin_unlock (&dev->read_buffer_lock);
 	}
@@ -815,9 +768,6 @@ resubmit:
 exit:
 	dev->interrupt_in_done = 1;
 	wake_up_interruptible (&dev->read_wait);
-
-	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
-	dbg(4, "%s: leave, status %d", __func__, status);
 }
 
 
@@ -829,22 +779,20 @@ static void tower_interrupt_out_callback (struct urb *urb)
 	struct lego_usb_tower *dev = urb->context;
 	int status = urb->status;
 
-	dbg(4, "%s: enter, status %d", __func__, status);
-	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+	lego_usb_tower_debug_data(&dev->udev->dev, __func__,
+				  urb->actual_length, urb->transfer_buffer);
 
 	/* sync/async unlink faults aren't errors */
 	if (status && !(status == -ENOENT ||
 			status == -ECONNRESET ||
 			status == -ESHUTDOWN)) {
-		dbg(1, "%s - nonzero write bulk status received: %d",
-		    __func__, status);
+		dev_dbg(&dev->udev->dev,
+			"%s: nonzero write bulk status received: %d\n", __func__,
+			status);
 	}
 
 	dev->interrupt_out_busy = 0;
 	wake_up_interruptible(&dev->write_wait);
-
-	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
-	dbg(4, "%s: leave, status %d", __func__, status);
 }
 
 
@@ -866,8 +814,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 	int retval = -ENOMEM;
 	int result;
 
-	dbg(2, "%s: enter", __func__);
-
 	/* allocate memory for our device state and initialize it */
 
 	dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
@@ -993,8 +939,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 
 
 exit:
-	dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev);
-
 	return retval;
 
 error:
@@ -1013,8 +957,6 @@ static void tower_disconnect (struct usb_interface *interface)
 	struct lego_usb_tower *dev;
 	int minor;
 
-	dbg(2, "%s: enter", __func__);
-
 	dev = usb_get_intfdata (interface);
 	mutex_lock(&open_disc_mutex);
 	usb_set_intfdata (interface, NULL);
@@ -1041,8 +983,6 @@ static void tower_disconnect (struct usb_interface *interface)
 
 	dev_info(&interface->dev, "LEGO USB Tower #%d now disconnected\n",
 		 (minor - LEGO_USB_TOWER_MINOR_BASE));
-
-	dbg(2, "%s: leave", __func__);
 }
 
 module_usb_driver(tower_driver);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index c357839..cbb6b78 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -179,7 +179,7 @@ err_hubmode:
 
 static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
-	struct usb3503_platform_data *pdata = i2c->dev.platform_data;
+	struct usb3503_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	struct device_node *np = i2c->dev.of_node;
 	struct usb3503 *hub;
 	int err = -ENOMEM;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 8b4ca1c..aa28ac8 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -747,9 +747,9 @@ static int ch9_postconfig(struct usbtest_dev *dev)
 
 	/* [9.4.5] get_status always works */
 	retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf);
-	if (retval != 2) {
+	if (retval) {
 		dev_err(&iface->dev, "get dev status --> %d\n", retval);
-		return (retval < 0) ? retval : -EDOM;
+		return retval;
 	}
 
 	/* FIXME configuration.bmAttributes says if we could try to set/clear
@@ -758,9 +758,9 @@ static int ch9_postconfig(struct usbtest_dev *dev)
 
 	retval = usb_get_status(udev, USB_RECIP_INTERFACE,
 			iface->altsetting[0].desc.bInterfaceNumber, dev->buf);
-	if (retval != 2) {
+	if (retval) {
 		dev_err(&iface->dev, "get interface status --> %d\n", retval);
-		return (retval < 0) ? retval : -EDOM;
+		return retval;
 	}
 	/* FIXME get status for each endpoint in the interface */
 
@@ -1351,7 +1351,6 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
 				ep, retval);
 		return retval;
 	}
-	le16_to_cpus(&status);
 	if (status != 1) {
 		ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status);
 		return -EINVAL;
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 2231850..baebc39 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -218,7 +218,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 	struct musb  *musb = hci;
 	void __iomem *reg_base = musb->ctrl_base;
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	struct usb_otg *otg = musb->xceiv->otg;
 	unsigned long flags;
@@ -335,7 +335,7 @@ eoi:
 static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	int     retval = 0;
 
@@ -350,7 +350,7 @@ static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
 static int am35x_musb_init(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 rev;
@@ -394,7 +394,7 @@ static int am35x_musb_init(struct musb *musb)
 static int am35x_musb_exit(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 
 	del_timer_sync(&otg_workaround);
@@ -456,7 +456,7 @@ static u64 am35x_dmamask = DMA_BIT_MASK(32);
 
 static int am35x_probe(struct platform_device *pdev)
 {
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct am35x_glue		*glue;
 
@@ -577,7 +577,7 @@ static int am35x_remove(struct platform_device *pdev)
 static int am35x_suspend(struct device *dev)
 {
 	struct am35x_glue	*glue = dev_get_drvdata(dev);
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 
 	/* Shutdown the on-chip PHY and its PLL. */
@@ -593,7 +593,7 @@ static int am35x_suspend(struct device *dev)
 static int am35x_resume(struct device *dev)
 {
 	struct am35x_glue	*glue = dev_get_drvdata(dev);
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	int			ret;
 
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 6ba8439..3e63379 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -451,7 +451,7 @@ static u64 bfin_dmamask = DMA_BIT_MASK(32);
 static int bfin_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct bfin_glue		*glue;
 
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 9db211e..904fb85 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -150,14 +150,11 @@ static void cppi_pool_free(struct cppi_channel *c)
 	c->last_processed = NULL;
 }
 
-static int cppi_controller_start(struct dma_controller *c)
+static void cppi_controller_start(struct cppi *controller)
 {
-	struct cppi	*controller;
 	void __iomem	*tibase;
 	int		i;
 
-	controller = container_of(c, struct cppi, controller);
-
 	/* do whatever is necessary to start controller */
 	for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
 		controller->tx[i].transmit = true;
@@ -212,8 +209,6 @@ static int cppi_controller_start(struct dma_controller *c)
 	/* disable RNDIS mode, also host rx RNDIS autorequest */
 	musb_writel(tibase, DAVINCI_RNDIS_REG, 0);
 	musb_writel(tibase, DAVINCI_AUTOREQ_REG, 0);
-
-	return 0;
 }
 
 /*
@@ -222,14 +217,12 @@ static int cppi_controller_start(struct dma_controller *c)
  *  De-Init the DMA controller as necessary.
  */
 
-static int cppi_controller_stop(struct dma_controller *c)
+static void cppi_controller_stop(struct cppi *controller)
 {
-	struct cppi		*controller;
 	void __iomem		*tibase;
 	int			i;
 	struct musb		*musb;
 
-	controller = container_of(c, struct cppi, controller);
 	musb = controller->musb;
 
 	tibase = controller->tibase;
@@ -255,8 +248,6 @@ static int cppi_controller_stop(struct dma_controller *c)
 	/*disable tx/rx cppi */
 	musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
 	musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
-
-	return 0;
 }
 
 /* While dma channel is allocated, we only want the core irqs active
@@ -1321,8 +1312,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr
 	controller->tibase = mregs - DAVINCI_BASE_OFFSET;
 
 	controller->musb = musb;
-	controller->controller.start = cppi_controller_start;
-	controller->controller.stop = cppi_controller_stop;
 	controller->controller.channel_alloc = cppi_channel_allocate;
 	controller->controller.channel_release = cppi_channel_release;
 	controller->controller.channel_program = cppi_channel_program;
@@ -1351,6 +1340,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr
 		controller->irq = irq;
 	}
 
+	cppi_controller_start(controller);
 	return &controller->controller;
 }
 
@@ -1363,6 +1353,8 @@ void dma_controller_destroy(struct dma_controller *c)
 
 	cppi = container_of(c, struct cppi, controller);
 
+	cppi_controller_stop(cppi);
+
 	if (cppi->irq)
 		free_irq(cppi->irq, cppi->musb);
 
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 0da6f64..7a46521 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -477,7 +477,7 @@ static u64 da8xx_dmamask = DMA_BIT_MASK(32);
 static int da8xx_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct da8xx_glue		*glue;
 
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index f8aeaf2..12ab66d 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -510,7 +510,7 @@ static u64 davinci_dmamask = DMA_BIT_MASK(32);
 static int davinci_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct davinci_glue		*glue;
 	struct clk			*clk;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 29a24ce..18e877f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -99,7 +99,6 @@
 #include <linux/prefetch.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/idr.h>
 #include <linux/dma-mapping.h>
 
 #include "musb_core.h"
@@ -1764,12 +1763,8 @@ static void musb_free(struct musb *musb)
 			disable_irq_wake(musb->nIrq);
 		free_irq(musb->nIrq, musb);
 	}
-	if (is_dma_capable() && musb->dma_controller) {
-		struct dma_controller	*c = musb->dma_controller;
-
-		(void) c->stop(c);
-		dma_controller_destroy(c);
-	}
+	if (musb->dma_controller)
+		dma_controller_destroy(musb->dma_controller);
 
 	musb_host_free(musb);
 }
@@ -1787,7 +1782,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 {
 	int			status;
 	struct musb		*musb;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 
 	/* The driver might handle more features than the board; OK.
 	 * Fail when the board needs a feature that's not enabled.
@@ -1844,19 +1839,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
 	pm_runtime_get_sync(musb->controller);
 
-#ifndef CONFIG_MUSB_PIO_ONLY
-	if (use_dma && dev->dma_mask) {
-		struct dma_controller	*c;
-
-		c = dma_controller_create(musb, musb->mregs);
-		musb->dma_controller = c;
-		if (c)
-			(void) c->start(c);
-	}
-#endif
-	/* ideally this would be abstracted in platform setup */
-	if (!is_dma_capable() || !musb->dma_controller)
-		dev->dma_mask = NULL;
+	if (use_dma && dev->dma_mask)
+		musb->dma_controller = dma_controller_create(musb, musb->mregs);
 
 	/* be sure interrupts are disabled before connecting ISR */
 	musb_platform_disable(musb);
@@ -1944,6 +1928,8 @@ fail4:
 	musb_gadget_cleanup(musb);
 
 fail3:
+	if (musb->dma_controller)
+		dma_controller_destroy(musb->dma_controller);
 	pm_runtime_put_sync(musb->controller);
 
 fail2:
@@ -2002,9 +1988,6 @@ static int musb_remove(struct platform_device *pdev)
 
 	musb_free(musb);
 	device_init_wakeup(dev, 0);
-#ifndef CONFIG_MUSB_PIO_ONLY
-	dma_set_mask(dev, *dev->parent->dma_mask);
-#endif
 	return 0;
 }
 
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 7d341c3..65f3917 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -83,11 +83,6 @@ enum {
 	MUSB_PORT_MODE_DUAL_ROLE,
 };
 
-#ifdef CONFIG_PROC_FS
-#include <linux/fs.h>
-#define MUSB_CONFIG_PROC_FS
-#endif
-
 /****************************** CONSTANTS ********************************/
 
 #ifndef MUSB_C_NUM_EPS
@@ -425,9 +420,6 @@ struct musb {
 
 	struct musb_hdrc_config	*config;
 
-#ifdef MUSB_CONFIG_PROC_FS
-	struct proc_dir_entry *proc_entry;
-#endif
 	int			xceiv_old_state;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*debugfs_root;
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 1b6b827..c8e67fd 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -62,10 +62,10 @@ struct musb_hw_ep;
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 
-#ifndef CONFIG_MUSB_PIO_ONLY
-#define	is_dma_capable()	(1)
-#else
+#ifdef CONFIG_MUSB_PIO_ONLY
 #define	is_dma_capable()	(0)
+#else
+#define	is_dma_capable()	(1)
 #endif
 
 #ifdef CONFIG_USB_TI_CPPI_DMA
@@ -159,8 +159,6 @@ dma_channel_status(struct dma_channel *c)
  * Controllers manage dma channels.
  */
 struct dma_controller {
-	int			(*start)(struct dma_controller *);
-	int			(*stop)(struct dma_controller *);
 	struct dma_channel	*(*channel_alloc)(struct dma_controller *,
 					struct musb_hw_ep *, u8 is_tx);
 	void			(*channel_release)(struct dma_channel *);
@@ -177,9 +175,20 @@ struct dma_controller {
 /* called after channel_program(), may indicate a fault */
 extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
 
+#ifdef CONFIG_MUSB_PIO_ONLY
+static inline struct dma_controller *dma_controller_create(struct musb *m,
+		void __iomem *io)
+{
+	return NULL;
+}
+
+static inline void dma_controller_destroy(struct dma_controller *d) { }
+
+#else
 
 extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
 
 extern void dma_controller_destroy(struct dma_controller *);
+#endif
 
 #endif	/* __MUSB_DMA_H__ */
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 5233804..4816b2f 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -46,9 +46,7 @@
 
 #include "musb_core.h"
 
-#ifdef CONFIG_OF
 static const struct of_device_id musb_dsps_of_match[];
-#endif
 
 /**
  * avoid using musb_readx()/musb_writex() as glue layer should not be
@@ -75,7 +73,6 @@ struct dsps_musb_wrapper {
 	u16	revision;
 	u16	control;
 	u16	status;
-	u16	eoi;
 	u16	epintr_set;
 	u16	epintr_clear;
 	u16	epintr_status;
@@ -205,7 +202,6 @@ static void dsps_musb_disable(struct musb *musb)
 	dsps_writel(reg_base, wrp->epintr_clear,
 			 wrp->txep_bitmap | wrp->rxep_bitmap);
 	dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
-	dsps_writel(reg_base, wrp->eoi, 0);
 }
 
 static void otg_timer(unsigned long _musb)
@@ -319,7 +315,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	/* Get usb core interrupts */
 	usbintr = dsps_readl(reg_base, wrp->coreintr_status);
 	if (!usbintr && !epintr)
-		goto eoi;
+		goto out;
 
 	musb->int_usb =	(usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
 	if (usbintr)
@@ -387,16 +383,11 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	if (musb->int_tx || musb->int_rx || musb->int_usb)
 		ret |= musb_interrupt(musb);
 
- eoi:
-	/* EOI needs to be written for the IRQ to be re-asserted. */
-	if (ret == IRQ_HANDLED || epintr || usbintr)
-		dsps_writel(reg_base, wrp->eoi, 1);
-
 	/* Poll for ID change */
 	if (musb->xceiv->state == OTG_STATE_B_IDLE)
 		mod_timer(&glue->timer[pdev->id],
 			 jiffies + wrp->poll_seconds * HZ);
-
+out:
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	return ret;
@@ -428,6 +419,8 @@ static int dsps_musb_init(struct musb *musb)
 		goto err0;
 	}
 
+	usb_phy_init(musb->xceiv);
+
 	setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);
 
 	/* Reset the musb */
@@ -443,9 +436,6 @@ static int dsps_musb_init(struct musb *musb)
 	val &= ~(1 << wrp->otg_disable);
 	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
 
-	/* clear level interrupt */
-	dsps_writel(reg_base, wrp->eoi, 0);
-
 	return 0;
 err0:
 	usb_put_phy(musb->xceiv);
@@ -463,6 +453,7 @@ static int dsps_musb_exit(struct musb *musb)
 
 	/* Shutdown the on-chip PHY and its PLL. */
 	musb_dsps_phy_control(glue, pdev->id, 0);
+	usb_phy_shutdown(musb->xceiv);
 
 	/* NOP driver needs change if supporting dual instance */
 	usb_put_phy(musb->xceiv);
@@ -487,7 +478,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 {
 	struct device *dev = glue->dev;
 	struct platform_device *pdev = to_platform_device(dev);
-	struct musb_hdrc_platform_data  *pdata = dev->platform_data;
+	struct musb_hdrc_platform_data  *pdata = dev_get_platdata(dev);
 	struct device_node *np = pdev->dev.of_node;
 	struct musb_hdrc_config	*config;
 	struct platform_device	*musb;
@@ -719,11 +710,10 @@ static int dsps_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
 
-static const struct dsps_musb_wrapper ti81xx_driver_data = {
+static const struct dsps_musb_wrapper am33xx_driver_data = {
 	.revision		= 0x00,
 	.control		= 0x14,
 	.status			= 0x18,
-	.eoi			= 0x24,
 	.epintr_set		= 0x38,
 	.epintr_clear		= 0x40,
 	.epintr_status		= 0x30,
@@ -750,23 +740,12 @@ static const struct dsps_musb_wrapper ti81xx_driver_data = {
 	.instances		= 1,
 };
 
-static const struct platform_device_id musb_dsps_id_table[] = {
-	{
-		.name	= "musb-ti81xx",
-		.driver_data	= (kernel_ulong_t) &ti81xx_driver_data,
-	},
-	{  },	/* Terminating Entry */
-};
-MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
-
-#ifdef CONFIG_OF
 static const struct of_device_id musb_dsps_of_match[] = {
 	{ .compatible = "ti,musb-am33xx",
-		.data = (void *) &ti81xx_driver_data, },
+		.data = (void *) &am33xx_driver_data, },
 	{  },
 };
 MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
-#endif
 
 static struct platform_driver dsps_usbss_driver = {
 	.probe		= dsps_probe,
@@ -776,7 +755,6 @@ static struct platform_driver dsps_usbss_driver = {
 		.pm	= &dsps_pm_ops,
 		.of_match_table	= of_match_ptr(musb_dsps_of_match),
 	},
-	.id_table	= musb_dsps_id_table,
 };
 
 MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 0414bc1..96632f9 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1266,7 +1266,8 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 		dev_dbg(musb->controller, "req %p queued to %s while ep %s\n",
 				req, ep->name, "disabled");
 		status = -ESHUTDOWN;
-		goto cleanup;
+		unmap_dma_buffer(request, musb);
+		goto unlock;
 	}
 
 	/* add request to the list */
@@ -1276,7 +1277,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 	if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
 		musb_ep_restart(musb, request);
 
-cleanup:
+unlock:
 	spin_unlock_irqrestore(&musb->lock, lockflags);
 	return status;
 }
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 3d1fd52..e8e9f9a 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -37,18 +37,10 @@
 #include "musb_core.h"
 #include "musbhsdma.h"
 
-static int dma_controller_start(struct dma_controller *c)
-{
-	/* nothing to do */
-	return 0;
-}
-
 static void dma_channel_release(struct dma_channel *channel);
 
-static int dma_controller_stop(struct dma_controller *c)
+static void dma_controller_stop(struct musb_dma_controller *controller)
 {
-	struct musb_dma_controller *controller = container_of(c,
-			struct musb_dma_controller, controller);
 	struct musb *musb = controller->private_data;
 	struct dma_channel *channel;
 	u8 bit;
@@ -67,8 +59,6 @@ static int dma_controller_stop(struct dma_controller *c)
 			}
 		}
 	}
-
-	return 0;
 }
 
 static struct dma_channel *dma_channel_allocate(struct dma_controller *c,
@@ -371,8 +361,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	struct musb_dma_controller *controller = container_of(c,
 			struct musb_dma_controller, controller);
 
-	if (!controller)
-		return;
+	dma_controller_stop(controller);
 
 	if (controller->irq)
 		free_irq(controller->irq, c);
@@ -400,8 +389,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 	controller->private_data = musb;
 	controller->base = base;
 
-	controller->controller.start = dma_controller_start;
-	controller->controller.stop = dma_controller_stop;
 	controller->controller.channel_alloc = dma_channel_allocate;
 	controller->controller.channel_release = dma_channel_release;
 	controller->controller.channel_program = dma_channel_program;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index f44e8b5..59d2245 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -255,7 +255,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
 	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = pdata->board_data;
 	struct usb_otg *otg = musb->xceiv->otg;
 
@@ -341,7 +341,7 @@ static int omap2430_musb_init(struct musb *musb)
 	int status = 0;
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 
 	/* We require some kind of external transceiver, hooked
@@ -412,7 +412,7 @@ static void omap2430_musb_enable(struct musb *musb)
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
-	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = pdata->board_data;
 
 	switch (glue->status) {
@@ -482,7 +482,7 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 static int omap2430_probe(struct platform_device *pdev)
 {
 	struct resource			musb_resources[3];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct omap_musb_board_data	*data;
 	struct platform_device		*musb;
 	struct omap2430_glue		*glue;
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 6f8a9ca..107f95a 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1157,7 +1157,7 @@ static u64 tusb_dmamask = DMA_BIT_MASK(32);
 static int tusb_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[3];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct tusb6010_glue		*glue;
 
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 98df17c..b8794eb 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -66,28 +66,6 @@ struct tusb_omap_dma {
 	unsigned			multichannel:1;
 };
 
-static int tusb_omap_dma_start(struct dma_controller *c)
-{
-	struct tusb_omap_dma	*tusb_dma;
-
-	tusb_dma = container_of(c, struct tusb_omap_dma, controller);
-
-	/* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
-
-	return 0;
-}
-
-static int tusb_omap_dma_stop(struct dma_controller *c)
-{
-	struct tusb_omap_dma	*tusb_dma;
-
-	tusb_dma = container_of(c, struct tusb_omap_dma, controller);
-
-	/* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
-
-	return 0;
-}
-
 /*
  * Allocate dmareq0 to the current channel unless it's already taken
  */
@@ -695,8 +673,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 	tusb_dma->dmareq = -1;
 	tusb_dma->sync_dev = -1;
 
-	tusb_dma->controller.start = tusb_omap_dma_start;
-	tusb_dma->controller.stop = tusb_omap_dma_stop;
 	tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
 	tusb_dma->controller.channel_release = tusb_omap_dma_release;
 	tusb_dma->controller.channel_program = tusb_omap_dma_program;
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index fce71b6..59256b1 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -227,7 +227,7 @@ ux500_of_probe(struct platform_device *pdev, struct device_node *np)
 static int ux500_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct device_node		*np = pdev->dev.of_node;
 	struct platform_device		*musb;
 	struct ux500_glue		*glue;
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index bfb7a65..e51dd9b 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -254,10 +254,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel)
 	return 0;
 }
 
-static int ux500_dma_controller_stop(struct dma_controller *c)
+static void ux500_dma_controller_stop(struct ux500_dma_controller *controller)
 {
-	struct ux500_dma_controller *controller = container_of(c,
-			struct ux500_dma_controller, controller);
 	struct ux500_dma_channel *ux500_channel;
 	struct dma_channel *channel;
 	u8 ch_num;
@@ -281,18 +279,14 @@ static int ux500_dma_controller_stop(struct dma_controller *c)
 		if (ux500_channel->dma_chan)
 			dma_release_channel(ux500_channel->dma_chan);
 	}
-
-	return 0;
 }
 
-static int ux500_dma_controller_start(struct dma_controller *c)
+static int ux500_dma_controller_start(struct ux500_dma_controller *controller)
 {
-	struct ux500_dma_controller *controller = container_of(c,
-			struct ux500_dma_controller, controller);
 	struct ux500_dma_channel *ux500_channel = NULL;
 	struct musb *musb = controller->private_data;
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct ux500_musb_board_data *data;
 	struct dma_channel *dma_channel = NULL;
 	char **chan_names;
@@ -347,7 +341,7 @@ static int ux500_dma_controller_start(struct dma_controller *c)
 					dir, ch_num);
 
 				/* Release already allocated channels */
-				ux500_dma_controller_stop(c);
+				ux500_dma_controller_stop(controller);
 
 				return -EBUSY;
 			}
@@ -369,6 +363,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	struct ux500_dma_controller *controller = container_of(c,
 			struct ux500_dma_controller, controller);
 
+	ux500_dma_controller_stop(controller);
 	kfree(controller);
 }
 
@@ -378,6 +373,7 @@ struct dma_controller *dma_controller_create(struct musb *musb,
 	struct ux500_dma_controller *controller;
 	struct platform_device *pdev = to_platform_device(musb->controller);
 	struct resource	*iomem;
+	int ret;
 
 	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
 	if (!controller)
@@ -394,14 +390,15 @@ struct dma_controller *dma_controller_create(struct musb *musb,
 
 	controller->phy_base = (dma_addr_t) iomem->start;
 
-	controller->controller.start = ux500_dma_controller_start;
-	controller->controller.stop = ux500_dma_controller_stop;
 	controller->controller.channel_alloc = ux500_dma_channel_allocate;
 	controller->controller.channel_release = ux500_dma_channel_release;
 	controller->controller.channel_program = ux500_dma_channel_program;
 	controller->controller.channel_abort = ux500_dma_channel_abort;
 	controller->controller.is_compatible = ux500_dma_is_compatible;
 
+	ret = ux500_dma_controller_start(controller);
+	if (ret)
+		goto plat_get_fail;
 	return &controller->controller;
 
 plat_get_fail:
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 3622fff..5443958 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -1,22 +1,10 @@
 #
 # Physical Layer USB driver configuration
 #
-menuconfig USB_PHY
-	bool "USB Physical Layer drivers"
-	help
-	  Most USB controllers have the physical layer signalling part
-	  (commonly called a PHY) built in.  However, dual-role devices
-	  (a.k.a. USB on-the-go) which support being USB master or slave
-	  with the same connector often use an external PHY.
-
-	  The drivers in this submenu add support for such PHY devices.
-	  They are not needed for standard master-only (or the vast
-	  majority of slave-only) USB interfaces.
-
-	  If you're not sure if this applies to you, it probably doesn't;
-	  say N here.
+menu "USB Physical Layer drivers"
 
-if USB_PHY
+config USB_PHY
+	def_bool n
 
 #
 # USB Transceiver Drivers
@@ -24,6 +12,7 @@ if USB_PHY
 config AB8500_USB
 	tristate "AB8500 USB Transceiver Driver"
 	depends on AB8500_CORE
+	select USB_PHY
 	help
 	  Enable this to support the USB OTG transceiver in AB8500 chip.
 	  This transceiver supports high and full speed devices plus,
@@ -33,12 +22,14 @@ config FSL_USB2_OTG
 	bool "Freescale USB OTG Transceiver Driver"
 	depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
 	select USB_OTG
+	select USB_PHY
 	help
 	  Enable this to support Freescale USB OTG transceiver.
 
 config ISP1301_OMAP
 	tristate "Philips ISP1301 with OMAP OTG"
 	depends on I2C && ARCH_OMAP_OTG
+	select USB_PHY
 	help
 	  If you say yes here you get support for the Philips ISP1301
 	  USB-On-The-Go transceiver working with the OMAP OTG controller.
@@ -52,12 +43,14 @@ config ISP1301_OMAP
 config MV_U3D_PHY
 	bool "Marvell USB 3.0 PHY controller Driver"
 	depends on CPU_MMP3
+	select USB_PHY
 	help
 	  Enable this to support Marvell USB 3.0 phy controller for Marvell
 	  SoC.
 
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
+	select USB_PHY
 	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
@@ -65,6 +58,7 @@ config NOP_USB_XCEIV
 
 config OMAP_CONTROL_USB
 	tristate "OMAP CONTROL USB Driver"
+	depends on ARCH_OMAP2PLUS || COMPILE_TEST
 	help
 	  Enable this to add support for the USB part present in the control
 	  module. This driver has API to power on the USB2 PHY and to write to
@@ -76,6 +70,7 @@ config OMAP_USB2
 	tristate "OMAP USB2 PHY Driver"
 	depends on ARCH_OMAP2PLUS
 	select OMAP_CONTROL_USB
+	select USB_PHY
 	help
 	  Enable this to support the transceiver that is part of SOC. This
 	  driver takes care of all the PHY functionality apart from comparator.
@@ -84,7 +79,9 @@ config OMAP_USB2
 
 config OMAP_USB3
 	tristate "OMAP USB3 PHY Driver"
+	depends on ARCH_OMAP2PLUS || COMPILE_TEST
 	select OMAP_CONTROL_USB
+	select USB_PHY
 	help
 	  Enable this to support the USB3 PHY that is part of SOC. This
 	  driver takes care of all the PHY functionality apart from comparator.
@@ -101,6 +98,7 @@ config SAMSUNG_USBPHY
 config SAMSUNG_USB2PHY
 	tristate "Samsung USB 2.0 PHY controller Driver"
 	select SAMSUNG_USBPHY
+	select USB_PHY
 	help
 	  Enable this to support Samsung USB 2.0 (High Speed) PHY controller
 	  driver for Samsung SoCs.
@@ -108,6 +106,7 @@ config SAMSUNG_USB2PHY
 config SAMSUNG_USB3PHY
 	tristate "Samsung USB 3.0 PHY controller Driver"
 	select SAMSUNG_USBPHY
+	select USB_PHY
 	help
 	  Enable this to support Samsung USB 3.0 (Super Speed) phy controller
 	  for samsung SoCs.
@@ -115,6 +114,7 @@ config SAMSUNG_USB3PHY
 config TWL4030_USB
 	tristate "TWL4030 USB Transceiver Driver"
 	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+	select USB_PHY
 	help
 	  Enable this to support the USB OTG transceiver on TWL4030
 	  family chips (including the TWL5030 and TPS659x0 devices).
@@ -135,6 +135,7 @@ config TWL6030_USB
 config USB_GPIO_VBUS
 	tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
 	depends on GPIOLIB
+	select USB_PHY
 	help
 	  Provides simple GPIO VBUS sensing for controllers with an
 	  internal transceiver via the usb_phy interface, and
@@ -145,6 +146,7 @@ config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
 	depends on USB || USB_GADGET
 	depends on I2C
+	select USB_PHY
 	help
 	  Say Y here to add support for the NXP ISP1301 USB transceiver driver.
 	  This chip is typically used as USB transceiver for USB host, gadget
@@ -156,6 +158,7 @@ config USB_ISP1301
 config USB_MSM_OTG
 	tristate "OTG support for Qualcomm on-chip USB controller"
 	depends on (USB || USB_GADGET) && ARCH_MSM
+	select USB_PHY
 	help
 	  Enable this to support the USB OTG transceiver on MSM chips. It
 	  handles PHY initialization, clock management, and workarounds
@@ -169,6 +172,7 @@ config USB_MV_OTG
 	tristate "Marvell USB OTG support"
 	depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME
 	select USB_OTG
+	select USB_PHY
 	help
 	  Say Y here if you want to build Marvell USB OTG transciever
 	  driver in kernel (including PXA and MMP series). This driver
@@ -180,6 +184,7 @@ config USB_MXS_PHY
 	tristate "Freescale MXS USB PHY support"
 	depends on ARCH_MXC || ARCH_MXS
 	select STMP_DEVICE
+	select USB_PHY
 	help
 	  Enable this to support the Freescale MXS USB PHY.
 
@@ -188,6 +193,7 @@ config USB_MXS_PHY
 config USB_RCAR_PHY
 	tristate "Renesas R-Car USB PHY support"
 	depends on USB || USB_GADGET
+	select USB_PHY
 	help
 	  Say Y here to add support for the Renesas R-Car USB common PHY driver.
 	  This chip is typically used as USB PHY for USB host, gadget.
@@ -210,4 +216,4 @@ config USB_ULPI_VIEWPORT
 	  Provides read/write operations to the ULPI phy register set for
 	  controllers with a viewport register (e.g. Chipidea/ARC controllers).
 
-endif # USB_PHY
+endmenu
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 070eca3..98730ca 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -1,9 +1,6 @@
 #
 # Makefile for physical layer USB drivers
 #
-
-ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
-
 obj-$(CONFIG_USB_PHY)			+= phy.o
 obj-$(CONFIG_OF)			+= of.o
 
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index e771baf..fa7c9f9 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -611,7 +611,7 @@ static int fsl_otg_set_peripheral(struct usb_otg *otg,
 	otg_dev->fsm.b_bus_req = 1;
 
 	/* start the gadget right away if the ID pin says Mini-B */
-	DBG("ID pin=%d\n", otg_dev->fsm.id);
+	pr_debug("ID pin=%d\n", otg_dev->fsm.id);
 	if (otg_dev->fsm.id == 1) {
 		fsl_otg_start_host(&otg_dev->fsm, 0);
 		otg_drv_vbus(&otg_dev->fsm, 0);
@@ -684,7 +684,7 @@ static int fsl_otg_start_hnp(struct usb_otg *otg)
 	if (otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
-	DBG("start_hnp...n");
+	pr_debug("start_hnp...\n");
 
 	/* clear a_bus_req to enter a_suspend state */
 	otg_dev->fsm.a_bus_req = 0;
@@ -834,7 +834,7 @@ int usb_otg_start(struct platform_device *pdev)
 	int status;
 	struct resource *res;
 	u32 temp;
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	p_otg = container_of(otg_trans, struct fsl_otg, phy);
 	fsm = &p_otg->fsm;
@@ -941,7 +941,7 @@ int usb_otg_start(struct platform_device *pdev)
 		p_otg->fsm.id = 0;
 	}
 
-	DBG("initial ID pin=%d\n", p_otg->fsm.id);
+	pr_debug("initial ID pin=%d\n", p_otg->fsm.id);
 
 	/* enable OTG ID pin interrupt */
 	temp = fsl_readl(&p_otg->dr_mem_map->otgsc);
@@ -1105,7 +1105,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
 {
 	int ret;
 
-	if (!pdev->dev.platform_data)
+	if (!dev_get_platdata(&pdev->dev))
 		return -ENODEV;
 
 	/* configure the OTG */
@@ -1137,7 +1137,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
 
 static int fsl_otg_remove(struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	usb_remove_phy(&fsl_otg_dev->phy);
 	free_irq(fsl_otg_dev->irq, fsl_otg_dev);
diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h
index c30a2e1..fbe5862 100644
--- a/drivers/usb/phy/phy-fsm-usb.h
+++ b/drivers/usb/phy/phy-fsm-usb.h
@@ -15,18 +15,11 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#undef DEBUG
 #undef VERBOSE
 
-#ifdef DEBUG
-#define DBG(fmt, args...) printk(KERN_DEBUG "[%s]  " fmt , \
-				 __func__, ## args)
-#else
-#define DBG(fmt, args...)	do {} while (0)
-#endif
-
 #ifdef VERBOSE
-#define VDBG		DBG
+#define VDBG(fmt, args...) pr_debug("[%s]  " fmt , \
+				 __func__, ## args)
 #else
 #define VDBG(stuff...)	do {} while (0)
 #endif
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 8443335..b2f29c9 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -101,7 +101,7 @@ static void gpio_vbus_work(struct work_struct *work)
 {
 	struct gpio_vbus_data *gpio_vbus =
 		container_of(work, struct gpio_vbus_data, work.work);
-	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
+	struct gpio_vbus_mach_info *pdata = dev_get_platdata(gpio_vbus->dev);
 	int gpio, status, vbus;
 
 	if (!gpio_vbus->phy.otg->gadget)
@@ -155,7 +155,7 @@ static void gpio_vbus_work(struct work_struct *work)
 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_mach_info *pdata = dev_get_platdata(&pdev->dev);
 	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
 	struct usb_otg *otg = gpio_vbus->phy.otg;
 
@@ -182,7 +182,7 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg,
 
 	gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy);
 	pdev = to_platform_device(gpio_vbus->dev);
-	pdata = gpio_vbus->dev->platform_data;
+	pdata = dev_get_platdata(gpio_vbus->dev);
 	gpio = pdata->gpio_pullup;
 
 	if (!gadget) {
@@ -243,7 +243,7 @@ static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
 
 static int __init gpio_vbus_probe(struct platform_device *pdev)
 {
-	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+	struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
 	struct gpio_vbus_data *gpio_vbus;
 	struct resource *res;
 	int err, gpio, irq;
@@ -352,7 +352,7 @@ err_gpio:
 static int __exit gpio_vbus_remove(struct platform_device *pdev)
 {
 	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
-	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+	struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
 	int gpio = pdata->gpio_vbus;
 
 	device_init_wakeup(&pdev->dev, 0);
diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c
index ae481af..d3a5160 100644
--- a/drivers/usb/phy/phy-isp1301-omap.c
+++ b/drivers/usb/phy/phy-isp1301-omap.c
@@ -40,9 +40,7 @@
 
 #include <mach/usb.h>
 
-#ifndef	DEBUG
-#undef	VERBOSE
-#endif
+#undef VERBOSE
 
 
 #define	DRIVER_VERSION	"24 August 2004"
@@ -387,7 +385,6 @@ static void b_idle(struct isp1301 *isp, const char *tag)
 static void
 dump_regs(struct isp1301 *isp, const char *label)
 {
-#ifdef	DEBUG
 	u8	ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1);
 	u8	status = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
 	u8	src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
@@ -396,7 +393,6 @@ dump_regs(struct isp1301 *isp, const char *label)
 		omap_readl(OTG_CTRL), label, state_name(isp),
 		ctrl, status, src);
 	/* mode control and irq enables don't change much */
-#endif
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index d08f334..e9d4cd9 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1419,7 +1419,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
 	struct usb_phy *phy;
 
 	dev_info(&pdev->dev, "msm_otg probe\n");
-	if (!pdev->dev.platform_data) {
+	if (!dev_get_platdata(&pdev->dev)) {
 		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
 		return -ENODEV;
 	}
@@ -1436,7 +1436,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	motg->pdata = pdev->dev.platform_data;
+	motg->pdata = dev_get_platdata(&pdev->dev);
 	phy = &motg->phy;
 	phy->dev = &pdev->dev;
 
diff --git a/drivers/usb/phy/phy-mv-u3d-usb.c b/drivers/usb/phy/phy-mv-u3d-usb.c
index 1568ea6..6688023 100644
--- a/drivers/usb/phy/phy-mv-u3d-usb.c
+++ b/drivers/usb/phy/phy-mv-u3d-usb.c
@@ -271,7 +271,7 @@ static int mv_u3d_phy_probe(struct platform_device *pdev)
 	void __iomem	*phy_base;
 	int	ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata) {
 		dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
 		return -EINVAL;
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
index 4a6b03c..03d16ff 100644
--- a/drivers/usb/phy/phy-mv-usb.c
+++ b/drivers/usb/phy/phy-mv-usb.c
@@ -673,7 +673,7 @@ int mv_otg_remove(struct platform_device *pdev)
 
 static int mv_otg_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mv_otg *mvotg;
 	struct usb_otg *otg;
 	struct resource *r;
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index bd601c5..fdd33b4 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -41,11 +41,14 @@ struct mxs_phy {
 
 #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
 
-static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)
+static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
 {
+	int ret;
 	void __iomem *base = mxs_phy->phy.io_priv;
 
-	stmp_reset_block(base + HW_USBPHY_CTRL);
+	ret = stmp_reset_block(base + HW_USBPHY_CTRL);
+	if (ret)
+		return ret;
 
 	/* Power up the PHY */
 	writel(0, base + HW_USBPHY_PWD);
@@ -54,6 +57,8 @@ static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)
 	writel(BM_USBPHY_CTRL_ENUTMILEVEL2 |
 	       BM_USBPHY_CTRL_ENUTMILEVEL3,
 	       base + HW_USBPHY_CTRL_SET);
+
+	return 0;
 }
 
 static int mxs_phy_init(struct usb_phy *phy)
@@ -61,9 +66,7 @@ static int mxs_phy_init(struct usb_phy *phy)
 	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 
 	clk_prepare_enable(mxs_phy->clk);
-	mxs_phy_hw_init(mxs_phy);
-
-	return 0;
+	return mxs_phy_hw_init(mxs_phy);
 }
 
 static void mxs_phy_shutdown(struct usb_phy *phy)
diff --git a/drivers/usb/phy/phy-nop.c b/drivers/usb/phy/phy-nop.c
index 55445e5d..f52b7f8 100644
--- a/drivers/usb/phy/phy-nop.c
+++ b/drivers/usb/phy/phy-nop.c
@@ -142,7 +142,8 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 static int nop_usb_xceiv_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
+	struct nop_usb_xceiv_platform_data *pdata =
+			dev_get_platdata(&pdev->dev);
 	struct nop_usb_xceiv	*nop;
 	enum usb_phy_type	type = USB_PHY_TYPE_USB2;
 	int err;
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/usb/phy/phy-omap-control.c
index 1419ced..a4dda8e 100644
--- a/drivers/usb/phy/phy-omap-control.c
+++ b/drivers/usb/phy/phy-omap-control.c
@@ -197,7 +197,8 @@ static int omap_control_usb_probe(struct platform_device *pdev)
 {
 	struct resource	*res;
 	struct device_node *np = pdev->dev.of_node;
-	struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct omap_control_usb_platform_data *pdata =
+			dev_get_platdata(&pdev->dev);
 
 	control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
 		GFP_KERNEL);
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c
index a2fb30b..fc15694 100644
--- a/drivers/usb/phy/phy-omap-usb3.c
+++ b/drivers/usb/phy/phy-omap-usb3.c
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/usb/omap_control_usb.h>
 
-#define	NUM_SYS_CLKS		6
 #define	PLL_STATUS		0x00000004
 #define	PLL_GO			0x00000008
 #define	PLL_CONFIGURATION1	0x0000000C
@@ -57,26 +56,32 @@
  */
 # define PLL_IDLE_TIME  100;
 
-enum sys_clk_rate {
-	CLK_RATE_UNDEFINED = -1,
-	CLK_RATE_12MHZ,
-	CLK_RATE_16MHZ,
-	CLK_RATE_19MHZ,
-	CLK_RATE_20MHZ,
-	CLK_RATE_26MHZ,
-	CLK_RATE_38MHZ
+struct usb_dpll_map {
+	unsigned long rate;
+	struct usb_dpll_params params;
 };
 
-static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = {
-	{1250, 5, 4, 20, 0},		/* 12 MHz */
-	{3125, 20, 4, 20, 0},		/* 16.8 MHz */
-	{1172, 8, 4, 20, 65537},	/* 19.2 MHz */
-	{1000, 7, 4, 10, 0},            /* 20 MHz */
-	{1250, 12, 4, 20, 0},		/* 26 MHz */
-	{3125, 47, 4, 20, 92843},	/* 38.4 MHz */
-
+static struct usb_dpll_map dpll_map[] = {
+	{12000000, {1250, 5, 4, 20, 0} },	/* 12 MHz */
+	{16800000, {3125, 20, 4, 20, 0} },	/* 16.8 MHz */
+	{19200000, {1172, 8, 4, 20, 65537} },	/* 19.2 MHz */
+	{20000000, {1000, 7, 4, 10, 0} },	/* 20 MHz */
+	{26000000, {1250, 12, 4, 20, 0} },	/* 26 MHz */
+	{38400000, {3125, 47, 4, 20, 92843} },	/* 38.4 MHz */
 };
 
+static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpll_map); i++) {
+		if (rate == dpll_map[i].rate)
+			return &dpll_map[i].params;
+	}
+
+	return 0;
+}
+
 static int omap_usb3_suspend(struct usb_phy *x, int suspend)
 {
 	struct omap_usb *phy = phy_to_omapusb(x);
@@ -116,26 +121,6 @@ static int omap_usb3_suspend(struct usb_phy *x, int suspend)
 	return 0;
 }
 
-static inline enum sys_clk_rate __get_sys_clk_index(unsigned long rate)
-{
-	switch (rate) {
-	case 12000000:
-		return CLK_RATE_12MHZ;
-	case 16800000:
-		return CLK_RATE_16MHZ;
-	case 19200000:
-		return CLK_RATE_19MHZ;
-	case 20000000:
-		return CLK_RATE_20MHZ;
-	case 26000000:
-		return CLK_RATE_26MHZ;
-	case 38400000:
-		return CLK_RATE_38MHZ;
-	default:
-		return CLK_RATE_UNDEFINED;
-	}
-}
-
 static void omap_usb_dpll_relock(struct omap_usb *phy)
 {
 	u32		val;
@@ -155,39 +140,39 @@ static int omap_usb_dpll_lock(struct omap_usb *phy)
 {
 	u32			val;
 	unsigned long		rate;
-	enum sys_clk_rate	clk_index;
-
-	rate		= clk_get_rate(phy->sys_clk);
-	clk_index	= __get_sys_clk_index(rate);
+	struct usb_dpll_params *dpll_params;
 
-	if (clk_index == CLK_RATE_UNDEFINED) {
-		pr_err("dpll cannot be locked for sys clk freq:%luHz\n", rate);
+	rate = clk_get_rate(phy->sys_clk);
+	dpll_params = omap_usb3_get_dpll_params(rate);
+	if (!dpll_params) {
+		dev_err(phy->dev,
+			  "No DPLL configuration for %lu Hz SYS CLK\n", rate);
 		return -EINVAL;
 	}
 
 	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
 	val &= ~PLL_REGN_MASK;
-	val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT;
+	val |= dpll_params->n << PLL_REGN_SHIFT;
 	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
 
 	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 	val &= ~PLL_SELFREQDCO_MASK;
-	val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT;
+	val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
 	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 
 	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
 	val &= ~PLL_REGM_MASK;
-	val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT;
+	val |= dpll_params->m << PLL_REGM_SHIFT;
 	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
 
 	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
 	val &= ~PLL_REGM_F_MASK;
-	val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT;
+	val |= dpll_params->mf << PLL_REGM_F_SHIFT;
 	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
 
 	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
 	val &= ~PLL_SD_MASK;
-	val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT;
+	val |= dpll_params->sd << PLL_SD_SHIFT;
 	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
 
 	omap_usb_dpll_relock(phy);
@@ -198,8 +183,12 @@ static int omap_usb_dpll_lock(struct omap_usb *phy)
 static int omap_usb3_init(struct usb_phy *x)
 {
 	struct omap_usb	*phy = phy_to_omapusb(x);
+	int ret;
+
+	ret = omap_usb_dpll_lock(phy);
+	if (ret)
+		return ret;
 
-	omap_usb_dpll_lock(phy);
 	omap_control_usb3_phy_power(phy->control_dev, 1);
 
 	return 0;
diff --git a/drivers/usb/phy/phy-rcar-usb.c b/drivers/usb/phy/phy-rcar-usb.c
index ae90940..33265a5 100644
--- a/drivers/usb/phy/phy-rcar-usb.c
+++ b/drivers/usb/phy/phy-rcar-usb.c
@@ -83,7 +83,7 @@ static int rcar_usb_phy_init(struct usb_phy *phy)
 {
 	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
 	struct device *dev = phy->dev;
-	struct rcar_phy_platform_data *pdata = dev->platform_data;
+	struct rcar_phy_platform_data *pdata = dev_get_platdata(dev);
 	void __iomem *reg0 = priv->reg0;
 	void __iomem *reg1 = priv->reg1;
 	static const u8 ovcn_act[] = { OVC0_ACT, OVC1_ACT, OVC2_ACT };
@@ -184,17 +184,12 @@ static int rcar_usb_phy_probe(struct platform_device *pdev)
 	void __iomem *reg0, *reg1 = NULL;
 	int ret;
 
-	if (!pdev->dev.platform_data) {
+	if (!dev_get_platdata(&pdev->dev)) {
 		dev_err(dev, "No platform data\n");
 		return -EINVAL;
 	}
 
 	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res0) {
-		dev_err(dev, "Not enough platform resources\n");
-		return -EINVAL;
-	}
-
 	reg0 = devm_ioremap_resource(dev, res0);
 	if (IS_ERR(reg0))
 		return PTR_ERR(reg0);
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
index 758b86d..ff70e4b 100644
--- a/drivers/usb/phy/phy-samsung-usb2.c
+++ b/drivers/usb/phy/phy-samsung-usb2.c
@@ -359,7 +359,7 @@ static int samsung_usb2phy_probe(struct platform_device *pdev)
 {
 	struct samsung_usbphy *sphy;
 	struct usb_otg *otg;
-	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	struct samsung_usbphy_data *pdata = dev_get_platdata(&pdev->dev);
 	const struct samsung_usbphy_drvdata *drv_data;
 	struct device *dev = &pdev->dev;
 	struct resource *phy_mem;
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c
index 300e0cf..c6eb222 100644
--- a/drivers/usb/phy/phy-samsung-usb3.c
+++ b/drivers/usb/phy/phy-samsung-usb3.c
@@ -231,7 +231,7 @@ static void samsung_usb3phy_shutdown(struct usb_phy *phy)
 static int samsung_usb3phy_probe(struct platform_device *pdev)
 {
 	struct samsung_usbphy *sphy;
-	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	struct samsung_usbphy_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device *dev = &pdev->dev;
 	struct resource *phy_mem;
 	void __iomem	*phy_base;
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index cec0855..49fa2da 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -31,9 +31,11 @@
 #include <linux/of_gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
+#include <linux/usb/of.h>
 #include <asm/mach-types.h>
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
+#include <linux/regulator/consumer.h>
 
 #define ULPI_VIEWPORT		0x170
 
@@ -184,27 +186,6 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
 	},
 };
 
-static struct tegra_utmip_config utmip_default[] = {
-	[0] = {
-		.hssync_start_delay = 9,
-		.idle_wait_delay = 17,
-		.elastic_limit = 16,
-		.term_range_adj = 6,
-		.xcvr_setup = 9,
-		.xcvr_lsfslew = 1,
-		.xcvr_lsrslew = 1,
-	},
-	[2] = {
-		.hssync_start_delay = 9,
-		.idle_wait_delay = 17,
-		.elastic_limit = 16,
-		.term_range_adj = 6,
-		.xcvr_setup = 9,
-		.xcvr_lsfslew = 2,
-		.xcvr_lsrslew = 2,
-	},
-};
-
 static void set_pts(struct tegra_usb_phy *phy, u8 pts_val)
 {
 	void __iomem *base = phy->regs;
@@ -231,7 +212,7 @@ static void set_phcd(struct tegra_usb_phy *phy, bool enable)
 
 static int utmip_pad_open(struct tegra_usb_phy *phy)
 {
-	phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads");
+	phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads");
 	if (IS_ERR(phy->pad_clk)) {
 		pr_err("%s: can't get utmip pad clock\n", __func__);
 		return PTR_ERR(phy->pad_clk);
@@ -396,7 +377,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
 		UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
 	writel(val, base + UTMIP_PLL_CFG1);
 
-	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+	if (phy->mode == USB_DR_MODE_PERIPHERAL) {
 		val = readl(base + USB_SUSP_CTRL);
 		val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
 		writel(val, base + USB_SUSP_CTRL);
@@ -431,7 +412,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
 
 	if (phy->is_legacy_phy) {
 		val = readl(base + UTMIP_SPARE_CFG0);
-		if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
+		if (phy->mode == USB_DR_MODE_PERIPHERAL)
 			val &= ~FUSE_SETUP_SEL;
 		else
 			val |= FUSE_SETUP_SEL;
@@ -472,7 +453,7 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
 
 	utmi_phy_clk_disable(phy);
 
-	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+	if (phy->mode == USB_DR_MODE_PERIPHERAL) {
 		val = readl(base + USB_SUSP_CTRL);
 		val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
 		val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
@@ -560,13 +541,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
 
 	ret = gpio_direction_output(phy->reset_gpio, 0);
 	if (ret < 0) {
-		dev_err(phy->dev, "gpio %d not set to 0\n", phy->reset_gpio);
+		dev_err(phy->u_phy.dev, "gpio %d not set to 0\n",
+			phy->reset_gpio);
 		return ret;
 	}
 	msleep(5);
 	ret = gpio_direction_output(phy->reset_gpio, 1);
 	if (ret < 0) {
-		dev_err(phy->dev, "gpio %d not set to 1\n", phy->reset_gpio);
+		dev_err(phy->u_phy.dev, "gpio %d not set to 1\n",
+			phy->reset_gpio);
 		return ret;
 	}
 
@@ -634,6 +617,9 @@ static void tegra_usb_phy_close(struct usb_phy *x)
 {
 	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
 
+	if (!IS_ERR(phy->vbus))
+		regulator_disable(phy->vbus);
+
 	clk_disable_unprepare(phy->pll_u);
 }
 
@@ -666,29 +652,30 @@ static int ulpi_open(struct tegra_usb_phy *phy)
 {
 	int err;
 
-	phy->clk = devm_clk_get(phy->dev, "ulpi-link");
+	phy->clk = devm_clk_get(phy->u_phy.dev, "ulpi-link");
 	if (IS_ERR(phy->clk)) {
 		pr_err("%s: can't get ulpi clock\n", __func__);
 		return PTR_ERR(phy->clk);
 	}
 
-	err = devm_gpio_request(phy->dev, phy->reset_gpio, "ulpi_phy_reset_b");
+	err = devm_gpio_request(phy->u_phy.dev, phy->reset_gpio,
+		"ulpi_phy_reset_b");
 	if (err < 0) {
-		dev_err(phy->dev, "request failed for gpio: %d\n",
+		dev_err(phy->u_phy.dev, "request failed for gpio: %d\n",
 		       phy->reset_gpio);
 		return err;
 	}
 
 	err = gpio_direction_output(phy->reset_gpio, 0);
 	if (err < 0) {
-		dev_err(phy->dev, "gpio %d direction not set to output\n",
+		dev_err(phy->u_phy.dev, "gpio %d direction not set to output\n",
 		       phy->reset_gpio);
 		return err;
 	}
 
 	phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
 	if (!phy->ulpi) {
-		dev_err(phy->dev, "otg_ulpi_create returned NULL\n");
+		dev_err(phy->u_phy.dev, "otg_ulpi_create returned NULL\n");
 		err = -ENOMEM;
 		return err;
 	}
@@ -703,14 +690,7 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy)
 	int i;
 	int err;
 
-	if (!phy->is_ulpi_phy) {
-		if (phy->is_legacy_phy)
-			phy->config = &utmip_default[0];
-		else
-			phy->config = &utmip_default[2];
-	}
-
-	phy->pll_u = devm_clk_get(phy->dev, "pll_u");
+	phy->pll_u = devm_clk_get(phy->u_phy.dev, "pll_u");
 	if (IS_ERR(phy->pll_u)) {
 		pr_err("Can't get pll_u clock\n");
 		return PTR_ERR(phy->pll_u);
@@ -733,6 +713,16 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy)
 		goto fail;
 	}
 
+	if (!IS_ERR(phy->vbus)) {
+		err = regulator_enable(phy->vbus);
+		if (err) {
+			dev_err(phy->u_phy.dev,
+				"failed to enable usb vbus regulator: %d\n",
+				err);
+			goto fail;
+		}
+	}
+
 	if (phy->is_ulpi_phy)
 		err = ulpi_open(phy);
 	else
@@ -784,11 +774,94 @@ void tegra_ehci_phy_restore_end(struct usb_phy *x)
 }
 EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
 
+static int read_utmi_param(struct platform_device *pdev, const char *param,
+			   u8 *dest)
+{
+	u32 value;
+	int err = of_property_read_u32(pdev->dev.of_node, param, &value);
+	*dest = (u8)value;
+	if (err < 0)
+		dev_err(&pdev->dev, "Failed to read USB UTMI parameter %s: %d\n",
+			param, err);
+	return err;
+}
+
+static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
+			  struct platform_device *pdev)
+{
+	struct resource *res;
+	int err;
+	struct tegra_utmip_config *config;
+
+	tegra_phy->is_ulpi_phy = false;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n");
+		return  -ENXIO;
+	}
+
+	tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
+		resource_size(res));
+	if (!tegra_phy->regs) {
+		dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
+		return -ENOMEM;
+	}
+
+	tegra_phy->config = devm_kzalloc(&pdev->dev,
+		sizeof(*tegra_phy->config), GFP_KERNEL);
+	if (!tegra_phy->config) {
+		dev_err(&pdev->dev,
+			"unable to allocate memory for USB UTMIP config\n");
+		return -ENOMEM;
+	}
+
+	config = tegra_phy->config;
+
+	err = read_utmi_param(pdev, "nvidia,hssync-start-delay",
+		&config->hssync_start_delay);
+	if (err < 0)
+		return err;
+
+	err = read_utmi_param(pdev, "nvidia,elastic-limit",
+		&config->elastic_limit);
+	if (err < 0)
+		return err;
+
+	err = read_utmi_param(pdev, "nvidia,idle-wait-delay",
+		&config->idle_wait_delay);
+	if (err < 0)
+		return err;
+
+	err = read_utmi_param(pdev, "nvidia,term-range-adj",
+		&config->term_range_adj);
+	if (err < 0)
+		return err;
+
+	err = read_utmi_param(pdev, "nvidia,xcvr-setup",
+		&config->xcvr_setup);
+	if (err < 0)
+		return err;
+
+	err = read_utmi_param(pdev, "nvidia,xcvr-lsfslew",
+		&config->xcvr_lsfslew);
+	if (err < 0)
+		return err;
+
+	err = read_utmi_param(pdev, "nvidia,xcvr-lsrslew",
+		&config->xcvr_lsrslew);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static int tegra_usb_phy_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct tegra_usb_phy *tegra_phy = NULL;
 	struct device_node *np = pdev->dev.of_node;
+	enum usb_phy_interface phy_type;
 	int err;
 
 	tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL);
@@ -813,23 +886,15 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 	tegra_phy->is_legacy_phy =
 		of_property_read_bool(np, "nvidia,has-legacy-mode");
 
-	err = of_property_match_string(np, "phy_type", "ulpi");
-	if (err < 0) {
-		tegra_phy->is_ulpi_phy = false;
-
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (!res) {
-			dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n");
-			return  -ENXIO;
-		}
+	phy_type = of_usb_get_phy_mode(np);
+	switch (phy_type) {
+	case USBPHY_INTERFACE_MODE_UTMI:
+		err = utmi_phy_probe(tegra_phy, pdev);
+		if (err < 0)
+			return err;
+		break;
 
-		tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
-			resource_size(res));
-		if (!tegra_phy->regs) {
-			dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
-			return -ENOMEM;
-		}
-	} else {
+	case USBPHY_INTERFACE_MODE_ULPI:
 		tegra_phy->is_ulpi_phy = true;
 
 		tegra_phy->reset_gpio =
@@ -839,19 +904,35 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 				tegra_phy->reset_gpio);
 			return tegra_phy->reset_gpio;
 		}
+		tegra_phy->config = NULL;
+		break;
+
+	default:
+		dev_err(&pdev->dev, "phy_type is invalid or unsupported\n");
+		return -EINVAL;
 	}
 
-	err = of_property_match_string(np, "dr_mode", "otg");
-	if (err < 0) {
-		err = of_property_match_string(np, "dr_mode", "peripheral");
-		if (err < 0)
-			tegra_phy->mode = TEGRA_USB_PHY_MODE_HOST;
-		else
-			tegra_phy->mode = TEGRA_USB_PHY_MODE_DEVICE;
-	} else
-		tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG;
+	if (of_find_property(np, "dr_mode", NULL))
+		tegra_phy->mode = of_usb_get_dr_mode(np);
+	else
+		tegra_phy->mode = USB_DR_MODE_HOST;
+
+	if (tegra_phy->mode == USB_DR_MODE_UNKNOWN) {
+		dev_err(&pdev->dev, "dr_mode is invalid\n");
+		return -EINVAL;
+	}
 
-	tegra_phy->dev = &pdev->dev;
+	/* On some boards, the VBUS regulator doesn't need to be controlled */
+	if (of_find_property(np, "vbus-supply", NULL)) {
+		tegra_phy->vbus = devm_regulator_get(&pdev->dev, "vbus");
+		if (IS_ERR(tegra_phy->vbus))
+			return PTR_ERR(tegra_phy->vbus);
+	} else {
+		dev_notice(&pdev->dev, "no vbus regulator");
+		tegra_phy->vbus = ERR_PTR(-ENODEV);
+	}
+
+	tegra_phy->u_phy.dev = &pdev->dev;
 	err = tegra_usb_phy_init(tegra_phy);
 	if (err < 0)
 		return err;
@@ -860,6 +941,22 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 	tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend;
 
 	dev_set_drvdata(&pdev->dev, tegra_phy);
+
+	err = usb_add_phy_dev(&tegra_phy->u_phy);
+	if (err < 0) {
+		tegra_usb_phy_close(&tegra_phy->u_phy);
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra_usb_phy_remove(struct platform_device *pdev)
+{
+	struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&tegra_phy->u_phy);
+
 	return 0;
 }
 
@@ -871,6 +968,7 @@ MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table);
 
 static struct platform_driver tegra_usb_phy_driver = {
 	.probe		= tegra_usb_phy_probe,
+	.remove		= tegra_usb_phy_remove,
 	.driver		= {
 		.name	= "tegra-phy",
 		.owner	= THIS_MODULE,
@@ -879,29 +977,5 @@ static struct platform_driver tegra_usb_phy_driver = {
 };
 module_platform_driver(tegra_usb_phy_driver);
 
-static int tegra_usb_phy_match(struct device *dev, void *data)
-{
-	struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev);
-	struct device_node *dn = data;
-
-	return (tegra_phy->dev->of_node == dn) ? 1 : 0;
-}
-
-struct usb_phy *tegra_usb_get_phy(struct device_node *dn)
-{
-	struct device *dev;
-	struct tegra_usb_phy *tegra_phy;
-
-	dev = driver_find_device(&tegra_usb_phy_driver.driver, NULL, dn,
-				 tegra_usb_phy_match);
-	if (!dev)
-		return ERR_PTR(-EPROBE_DEFER);
-
-	tegra_phy = dev_get_drvdata(dev);
-
-	return &tegra_phy->u_phy;
-}
-EXPORT_SYMBOL_GPL(tegra_usb_get_phy);
-
 MODULE_DESCRIPTION("Tegra USB PHY driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c
index 8f78d2d..90730c8 100644
--- a/drivers/usb/phy/phy-twl4030-usb.c
+++ b/drivers/usb/phy/phy-twl4030-usb.c
@@ -648,7 +648,7 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
 
 static int twl4030_usb_probe(struct platform_device *pdev)
 {
-	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
+	struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
 	struct twl4030_usb	*twl;
 	int			status, err;
 	struct usb_otg		*otg;
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 1753bd3..16dbc93 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -324,7 +324,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
 	int			status, err;
 	struct device_node	*np = pdev->dev.of_node;
 	struct device		*dev = &pdev->dev;
-	struct twl4030_usb_data	*pdata = dev->platform_data;
+	struct twl4030_usb_data	*pdata = dev_get_platdata(dev);
 
 	twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
 	if (!twl)
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index cfd2050..3b39757 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -416,7 +416,7 @@ static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
  */
 static int usbhs_probe(struct platform_device *pdev)
 {
-	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
+	struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev);
 	struct renesas_usbhs_driver_callback *dfunc;
 	struct usbhs_priv *priv;
 	struct resource *res, *irq_res;
@@ -558,7 +558,7 @@ probe_end_pipe_exit:
 static int usbhs_remove(struct platform_device *pdev)
 {
 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
-	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
+	struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev);
 	struct renesas_usbhs_driver_callback *dfunc = &info->driver_callback;
 
 	dev_dbg(&pdev->dev, "usb remove\n");
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 805940c..3385aeb 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -77,9 +77,9 @@ struct usbhsg_recip_handle {
 		struct usbhsg_gpriv, mod)
 
 #define __usbhsg_for_each_uep(start, pos, g, i)	\
-	for (i = start, pos = (g)->uep + i;	\
-	     i < (g)->uep_size;			\
-	     i++, pos = (g)->uep + i)
+	for ((i) = start;					\
+	     ((i) < (g)->uep_size) && ((pos) = (g)->uep + (i));	\
+	     (i)++)
 
 #define usbhsg_for_each_uep(pos, gpriv, i)	\
 	__usbhsg_for_each_uep(1, pos, gpriv, i)
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c
index b868154..e40f565 100644
--- a/drivers/usb/renesas_usbhs/mod_host.c
+++ b/drivers/usb/renesas_usbhs/mod_host.c
@@ -111,9 +111,9 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host";
 	container_of(usbhs_mod_get(priv, USBHS_HOST), struct usbhsh_hpriv, mod)
 
 #define __usbhsh_for_each_udev(start, pos, h, i)	\
-	for (i = start, pos = (h)->udev + i;		\
-	     i < USBHSH_DEVICE_MAX;			\
-	     i++, pos = (h)->udev + i)
+	for ((i) = start;						\
+	     ((i) < USBHSH_DEVICE_MAX) && ((pos) = (h)->udev + (i));	\
+	     (i)++)
 
 #define usbhsh_for_each_udev(pos, hpriv, i)	\
 	__usbhsh_for_each_udev(1, pos, hpriv, i)
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index b476fde..3e53498 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -54,9 +54,9 @@ struct usbhs_pipe_info {
  * pipe list
  */
 #define __usbhs_for_each_pipe(start, pos, info, i)	\
-	for (i = start, pos = (info)->pipe + i;		\
-	     i < (info)->size;				\
-	     i++, pos = (info)->pipe + i)
+	for ((i) = start;						\
+	     ((i) < (info)->size) && ((pos) = (info)->pipe + (i));	\
+	     (i)++)
 
 #define usbhs_for_each_pipe(pos, priv, i)			\
 	__usbhs_for_each_pipe(1, pos, &((priv)->pipe_info), i)
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index afb50ea..c69bb50 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -151,11 +151,7 @@ static int usb_console_setup(struct console *co, char *options)
 
 		/* only call the device specific open if this
 		 * is the first time the port is opened */
-		if (serial->type->open)
-			retval = serial->type->open(NULL, port);
-		else
-			retval = usb_serial_generic_open(NULL, port);
-
+		retval = serial->type->open(NULL, port);
 		if (retval) {
 			dev_err(&port->dev, "could not open USB console port\n");
 			goto fail;
@@ -210,10 +206,10 @@ static void usb_console_write(struct console *co,
 	if (count == 0)
 		return;
 
-	pr_debug("%s - minor %d, %d byte(s)\n", __func__, port->minor, count);
+	dev_dbg(&port->dev, "%s - %d byte(s)\n", __func__, count);
 
 	if (!port->port.console) {
-		pr_debug("%s - port not opened\n", __func__);
+		dev_dbg(&port->dev, "%s - port not opened\n", __func__);
 		return;
 	}
 
@@ -230,21 +226,14 @@ static void usb_console_write(struct console *co,
 		}
 		/* pass on to the driver specific version of this function if
 		   it is available */
-		if (serial->type->write)
-			retval = serial->type->write(NULL, port, buf, i);
-		else
-			retval = usb_serial_generic_write(NULL, port, buf, i);
-		pr_debug("%s - return value : %d\n", __func__, retval);
+		retval = serial->type->write(NULL, port, buf, i);
+		dev_dbg(&port->dev, "%s - write: %d\n", __func__, retval);
 		if (lf) {
 			/* append CR after LF */
 			unsigned char cr = 13;
-			if (serial->type->write)
-				retval = serial->type->write(NULL,
-								port, &cr, 1);
-			else
-				retval = usb_serial_generic_write(NULL,
-								port, &cr, 1);
-			pr_debug("%s - return value : %d\n", __func__, retval);
+			retval = serial->type->write(NULL, port, &cr, 1);
+			dev_dbg(&port->dev, "%s - write cr: %d\n",
+							__func__, retval);
 		}
 		buf += i;
 		count -= i;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 0eae4ba..6987b53 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -670,9 +670,6 @@ static void cp210x_set_termios(struct tty_struct *tty,
 	unsigned int bits;
 	unsigned int modem_ctl[4];
 
-	if (!tty)
-		return;
-
 	cflag = tty->termios.c_cflag;
 	old_cflag = old_termios->c_cflag;
 
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index e948dc0..558605d 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -495,6 +495,8 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
 	}
 	usb_set_serial_port_data(port, priv);
 
+	port->port.drain_delay = 256;
+
 	return 0;
 }
 
@@ -625,7 +627,7 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
 							__func__, result);
 		cypress_set_dead(port);
 	}
-	port->port.drain_delay = 256;
+
 	return result;
 } /* cypress_open */
 
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 75e85cb..639a18f 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -207,7 +207,6 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
 		return result;
 	}
 
-	port->port.drain_delay = 256;
 	return 0;
 }
 
@@ -322,6 +321,8 @@ static int f81232_port_probe(struct usb_serial_port *port)
 
 	usb_set_serial_port_data(port, priv);
 
+	port->port.drain_delay = 256;
+
 	return 0;
 }
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b65e657..dbf2f28 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -51,8 +51,6 @@
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr, Johan Hovold <jhovold@gmail.com>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
-static __u16 vendor = FTDI_VID;
-static __u16 product;
 
 struct ftdi_private {
 	enum ftdi_chip_type chip_type;
@@ -144,8 +142,8 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
 
 
 /*
- * Device ID not listed? Test via module params product/vendor or
- * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
+ * Device ID not listed? Test it using
+ * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report.
  */
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
@@ -906,7 +904,6 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
 	/* Crucible Devices */
 	{ USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
-	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
 
@@ -930,9 +927,6 @@ static const char *ftdi_chip_name[] = {
 #define FTDI_STATUS_B1_MASK	(FTDI_RS_BI)
 /* End TIOCMIWAIT */
 
-#define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \
- | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP)
-
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_probe(struct usb_serial *serial,
 					const struct usb_device_id *id);
@@ -999,10 +993,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
 #define WDR_TIMEOUT 5000 /* default urb timeout */
 #define WDR_SHORT_TIMEOUT 1000	/* shorter urb timeout */
 
-/* High and low are for DTR, RTS etc etc */
-#define HIGH 1
-#define LOW 0
-
 /*
  * ***************************************************************************
  * Utility functions
@@ -1867,7 +1857,6 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
 
 static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-	struct ktermios dummy;
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
@@ -1883,10 +1872,8 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
 	   This is same behaviour as serial.c/rs_open() - Kuba */
 
 	/* ftdi_set_termios  will send usb control messages */
-	if (tty) {
-		memset(&dummy, 0, sizeof(dummy));
-		ftdi_set_termios(tty, port, &dummy);
-	}
+	if (tty)
+		ftdi_set_termios(tty, port, NULL);
 
 	return usb_serial_generic_open(tty, port);
 }
@@ -2215,7 +2202,7 @@ no_data_parity_stop_changes:
 			dev_err(ddev, "%s urb failed to set baudrate\n", __func__);
 		mutex_unlock(&priv->cfg_lock);
 		/* Ensure RTS and DTR are raised when baudrate changed from 0 */
-		if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
+		if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
 			set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	}
 
@@ -2405,38 +2392,11 @@ static int ftdi_ioctl(struct tty_struct *tty,
 	return -ENOIOCTLCMD;
 }
 
-static int __init ftdi_init(void)
-{
-	if (vendor > 0 && product > 0) {
-		/* Add user specified VID/PID to reserved element of table. */
-		int i;
-		for (i = 0; id_table_combined[i].idVendor; i++)
-			;
-		id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
-		id_table_combined[i].idVendor = vendor;
-		id_table_combined[i].idProduct = product;
-	}
-	return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table_combined);
-}
-
-static void __exit ftdi_exit(void)
-{
-	usb_serial_deregister_drivers(serial_drivers);
-}
-
-
-module_init(ftdi_init);
-module_exit(ftdi_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
-		__MODULE_STRING(FTDI_VID)")");
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified product ID");
-
 module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index ba45170..1f31e6b 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -460,12 +460,7 @@ static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
 	/*
 	 * Use tty-port initialised flag to detect all hangups including the
 	 * one generated at USB-device disconnect.
-	 *
-	 * FIXME: Remove hupping check once tty_port_hangup calls shutdown
-	 *        (which clears the initialised flag) before wake up.
 	 */
-	if (test_bit(TTY_HUPPING, &tty->flags))
-		return true;
 	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
 		return true;
 
@@ -496,12 +491,8 @@ int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 
 	ret = wait_event_interruptible(port->port.delta_msr_wait,
 			usb_serial_generic_msr_changed(tty, arg, &cnow));
-	if (!ret) {
-		if (test_bit(TTY_HUPPING, &tty->flags))
-			ret = -EIO;
-		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
-			ret = -EIO;
-	}
+	if (!ret && !test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+		ret = -EIO;
 
 	return ret;
 }
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index dc2803b..c91481d 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -56,9 +56,7 @@
 
 #define MAX_NAME_LEN		64
 
-#define CHASE_TIMEOUT		(5*HZ)		/* 5 seconds */
 #define OPEN_TIMEOUT		(5*HZ)		/* 5 seconds */
-#define COMMAND_TIMEOUT		(5*HZ)		/* 5 seconds */
 
 /* receive port state */
 enum RXSTATE {
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 60054e7..9c18f59 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -64,8 +64,6 @@
 
 #define EDGE_CLOSING_WAIT	4000	/* in .01 sec */
 
-#define EDGE_OUT_BUF_SIZE	1024
-
 
 /* Product information read from the Edgeport */
 struct product_info {
@@ -93,7 +91,6 @@ struct edgeport_port {
 	spinlock_t ep_lock;
 	int ep_read_urb_state;
 	int ep_write_urb_in_use;
-	struct kfifo write_fifo;
 };
 
 struct edgeport_serial {
@@ -1732,22 +1729,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
 		return -ENODEV;
 
 	port_number = port->port_number;
-	switch (port_number) {
-	case 0:
-		edge_port->uart_base = UMPMEM_BASE_UART1;
-		edge_port->dma_address = UMPD_OEDB1_ADDRESS;
-		break;
-	case 1:
-		edge_port->uart_base = UMPMEM_BASE_UART2;
-		edge_port->dma_address = UMPD_OEDB2_ADDRESS;
-		break;
-	default:
-		dev_err(&port->dev, "Unknown port number!!!\n");
-		return -ENODEV;
-	}
-
-	dev_dbg(&port->dev, "%s - port_number = %d, uart_base = %04x, dma_address = %04x\n",
-		__func__, port_number, edge_port->uart_base, edge_port->dma_address);
 
 	dev = port->serial->dev;
 
@@ -1872,8 +1853,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 	++edge_serial->num_ports_open;
 
-	port->port.drain_delay = 1;
-
 	goto release_es_lock;
 
 unlink_int_urb:
@@ -1905,7 +1884,7 @@ static void edge_close(struct usb_serial_port *port)
 	usb_kill_urb(port->write_urb);
 	edge_port->ep_write_urb_in_use = 0;
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
-	kfifo_reset_out(&edge_port->write_fifo);
+	kfifo_reset_out(&port->write_fifo);
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
 	dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);
@@ -1939,7 +1918,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
 	if (edge_port->close_pending == 1)
 		return -ENODEV;
 
-	count = kfifo_in_locked(&edge_port->write_fifo, data, count,
+	count = kfifo_in_locked(&port->write_fifo, data, count,
 							&edge_port->ep_lock);
 	edge_send(port, tty);
 
@@ -1959,7 +1938,7 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
 		return;
 	}
 
-	count = kfifo_out(&edge_port->write_fifo,
+	count = kfifo_out(&port->write_fifo,
 				port->write_urb->transfer_buffer,
 				port->bulk_out_size);
 
@@ -2007,7 +1986,7 @@ static int edge_write_room(struct tty_struct *tty)
 		return 0;
 
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
-	room = kfifo_avail(&edge_port->write_fifo);
+	room = kfifo_avail(&port->write_fifo);
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
 	dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
@@ -2024,7 +2003,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty)
 		return 0;
 
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
-	chars = kfifo_len(&edge_port->write_fifo);
+	chars = kfifo_len(&port->write_fifo);
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
 	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
@@ -2451,30 +2430,45 @@ static int edge_port_probe(struct usb_serial_port *port)
 	if (!edge_port)
 		return -ENOMEM;
 
-	ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
-								GFP_KERNEL);
-	if (ret) {
-		kfree(edge_port);
-		return -ENOMEM;
-	}
-
 	spin_lock_init(&edge_port->ep_lock);
 	edge_port->port = port;
 	edge_port->edge_serial = usb_get_serial_data(port->serial);
 	edge_port->bUartMode = default_uart_mode;
 
+	switch (port->port_number) {
+	case 0:
+		edge_port->uart_base = UMPMEM_BASE_UART1;
+		edge_port->dma_address = UMPD_OEDB1_ADDRESS;
+		break;
+	case 1:
+		edge_port->uart_base = UMPMEM_BASE_UART2;
+		edge_port->dma_address = UMPD_OEDB2_ADDRESS;
+		break;
+	default:
+		dev_err(&port->dev, "unknown port number\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	dev_dbg(&port->dev,
+		"%s - port_number = %d, uart_base = %04x, dma_address = %04x\n",
+		__func__, port->port_number, edge_port->uart_base,
+		edge_port->dma_address);
+
 	usb_set_serial_port_data(port, edge_port);
 
 	ret = edge_create_sysfs_attrs(port);
-	if (ret) {
-		kfifo_free(&edge_port->write_fifo);
-		kfree(edge_port);
-		return ret;
-	}
+	if (ret)
+		goto err;
 
 	port->port.closing_wait = msecs_to_jiffies(closing_wait * 10);
+	port->port.drain_delay = 1;
 
 	return 0;
+err:
+	kfree(edge_port);
+
+	return ret;
 }
 
 static int edge_port_remove(struct usb_serial_port *port)
@@ -2483,7 +2477,6 @@ static int edge_port_remove(struct usb_serial_port *port)
 
 	edge_port = usb_get_serial_port_data(port);
 	edge_remove_sysfs_attrs(port);
-	kfifo_free(&edge_port->write_fifo);
 	kfree(edge_port);
 
 	return 0;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index d953d67..dfa6789 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -221,7 +221,6 @@ struct moschip_port {
 	__u8 shadowMCR;		/* last MCR value received */
 	char open;
 	char open_ports;
-	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
 	struct usb_serial_port *port;	/* loop back to the owner of this object */
 
 	/* Offsets */
@@ -1100,9 +1099,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
 		mos7840_port->read_urb_busy = false;
 	}
 
-	/* initialize our wait queues */
-	init_waitqueue_head(&mos7840_port->wait_chase);
-
 	/* initialize our port settings */
 	/* Must set to enable ints! */
 	mos7840_port->shadowMCR = MCR_MASTER_IE;
@@ -1228,47 +1224,6 @@ static void mos7840_close(struct usb_serial_port *port)
 	mos7840_port->open = 0;
 }
 
-/************************************************************************
- *
- * mos7840_block_until_chase_response
- *
- *	This function will block the close until one of the following:
- *		1. Response to our Chase comes from mos7840
- *		2. A timeout of 10 seconds without activity has expired
- *		   (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
- *
- ************************************************************************/
-
-static void mos7840_block_until_chase_response(struct tty_struct *tty,
-					struct moschip_port *mos7840_port)
-{
-	int timeout = msecs_to_jiffies(1000);
-	int wait = 10;
-	int count;
-
-	while (1) {
-		count = mos7840_chars_in_buffer(tty);
-
-		/* Check for Buffer status */
-		if (count <= 0)
-			return;
-
-		/* Block the thread for a while */
-		interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
-					       timeout);
-		/* No activity.. count down section */
-		wait--;
-		if (wait == 0) {
-			dev_dbg(&mos7840_port->port->dev, "%s - TIMEOUT\n", __func__);
-			return;
-		} else {
-			/* Reset timeout value back to seconds */
-			wait = 10;
-		}
-	}
-
-}
-
 /*****************************************************************************
  * mos7840_break
  *	this function sends a break to the port
@@ -1292,9 +1247,6 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
 	if (mos7840_port == NULL)
 		return;
 
-	/* flush and block until tx is empty */
-	mos7840_block_until_chase_response(tty, mos7840_port);
-
 	if (break_state == -1)
 		data = mos7840_port->shadowLCR | LCR_SET_BREAK;
 	else
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 7e3e078..a2080ac 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -343,6 +343,8 @@ static int oti6858_port_probe(struct usb_serial_port *port)
 
 	usb_set_serial_port_data(port, priv);
 
+	port->port.drain_delay = 256;	/* FIXME: check the FIFO length */
+
 	return 0;
 }
 
@@ -411,9 +413,6 @@ static void oti6858_set_termios(struct tty_struct *tty,
 	__le16 divisor;
 	int br;
 
-	if (!tty)
-		return;
-
 	cflag = tty->termios.c_cflag;
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -509,7 +508,6 @@ static void oti6858_set_termios(struct tty_struct *tty,
 static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
-	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
 	struct oti6858_control_pkt *buf;
 	unsigned long flags;
@@ -560,8 +558,8 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 	/* setup termios */
 	if (tty)
-		oti6858_set_termios(tty, port, &tmp_termios);
-	port->port.drain_delay = 256;	/* FIXME: check the FIFO length */
+		oti6858_set_termios(tty, port, NULL);
+
 	return 0;
 }
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index cb6bbed..2448201 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -29,6 +29,7 @@
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <asm/unaligned.h>
 #include "pl2303.h"
 
 /*
@@ -235,6 +236,8 @@ static int pl2303_port_probe(struct usb_serial_port *port)
 
 	usb_set_serial_port_data(port, priv);
 
+	port->port.drain_delay = 256;
+
 	return 0;
 }
 
@@ -261,6 +264,74 @@ static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
 	return retval;
 }
 
+static void pl2303_encode_baudrate(struct tty_struct *tty,
+					struct usb_serial_port *port,
+					u8 buf[4])
+{
+	const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
+	                         4800, 7200, 9600, 14400, 19200, 28800, 38400,
+	                         57600, 115200, 230400, 460800, 500000, 614400,
+	                         921600, 1228800, 2457600, 3000000, 6000000 };
+
+	struct usb_serial *serial = port->serial;
+	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+	int baud;
+	int i;
+
+	/*
+	 * NOTE: Only the values defined in baud_sup are supported!
+	 *       => if unsupported values are set, the PL2303 seems to use
+	 *          9600 baud (at least my PL2303X always does)
+	 */
+	baud = tty_get_baud_rate(tty);
+	dev_dbg(&port->dev, "baud requested = %d\n", baud);
+	if (!baud)
+		return;
+
+	/* Set baudrate to nearest supported value */
+	for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) {
+		if (baud_sup[i] > baud)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(baud_sup))
+		baud = baud_sup[i - 1];
+	else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1]))
+		baud = baud_sup[i - 1];
+	else
+		baud = baud_sup[i];
+
+	/* type_0, type_1 only support up to 1228800 baud */
+	if (spriv->type != HX)
+		baud = min_t(int, baud, 1228800);
+
+	if (spriv->type != HX || baud <= 115200) {
+		/* Direct (standard) baud rate encoding method */
+		put_unaligned_le32(baud, buf);
+	} else {
+		/*
+		 * NOTE: it's not clear if the type_0/1 chips
+		 * support this method
+		 *
+		 * Apparently the formula for higher speeds is:
+		 * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
+		 */
+		unsigned tmp = 12000000 * 32 / baud;
+		buf[3] = 0x80;
+		buf[2] = 0;
+		buf[1] = (tmp >= 256);
+		while (tmp >= 256) {
+			tmp >>= 2;
+			buf[1] <<= 1;
+		}
+		buf[0] = tmp;
+	}
+
+	/* Save resulting baud rate */
+	tty_encode_baud_rate(tty, baud, baud);
+	dev_dbg(&port->dev, "baud set = %d\n", baud);
+}
+
 static void pl2303_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios)
 {
@@ -268,27 +339,18 @@ static void pl2303_set_termios(struct tty_struct *tty,
 	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	unsigned int cflag;
 	unsigned char *buf;
-	int baud;
 	int i;
 	u8 control;
-	const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
-	                         4800, 7200, 9600, 14400, 19200, 28800, 38400,
-	                         57600, 115200, 230400, 460800, 500000, 614400,
-	                         921600, 1228800, 2457600, 3000000, 6000000 };
-	int baud_floor, baud_ceil;
-	int k;
-
-	/* The PL2303 is reported to lose bytes if you change
-	   serial settings even to the same values as before. Thus
-	   we actually need to filter in this specific case */
 
+	/*
+	 * The PL2303 is reported to lose bytes if you change serial settings
+	 * even to the same values as before. Thus we actually need to filter
+	 * in this specific case.
+	 */
 	if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
 		return;
 
-	cflag = tty->termios.c_cflag;
-
 	buf = kzalloc(7, GFP_KERNEL);
 	if (!buf) {
 		dev_err(&port->dev, "%s - out of memory.\n", __func__);
@@ -303,8 +365,8 @@ static void pl2303_set_termios(struct tty_struct *tty,
 			    0, 0, buf, 7, 100);
 	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);
 
-	if (cflag & CSIZE) {
-		switch (cflag & CSIZE) {
+	if (C_CSIZE(tty)) {
+		switch (C_CSIZE(tty)) {
 		case CS5:
 			buf[6] = 5;
 			break;
@@ -317,73 +379,22 @@ static void pl2303_set_termios(struct tty_struct *tty,
 		default:
 		case CS8:
 			buf[6] = 8;
-			break;
 		}
 		dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
 	}
 
 	/* For reference buf[0]:buf[3] baud rate value */
-	/* NOTE: Only the values defined in baud_sup are supported !
-	 *       => if unsupported values are set, the PL2303 seems to use
-	 *          9600 baud (at least my PL2303X always does)
-	 */
-	baud = tty_get_baud_rate(tty);
-	dev_dbg(&port->dev, "baud requested = %d\n", baud);
-	if (baud) {
-		/* Set baudrate to nearest supported value */
-		for (k=0; k<ARRAY_SIZE(baud_sup); k++) {
-			if (baud_sup[k] / baud) {
-				baud_ceil = baud_sup[k];
-				if (k==0) {
-					baud = baud_ceil;
-				} else {
-					baud_floor = baud_sup[k-1];
-					if ((baud_ceil % baud)
-					    > (baud % baud_floor))
-						baud = baud_floor;
-					else
-						baud = baud_ceil;
-				}
-				break;
-			}
-		}
-		if (baud > 1228800) {
-			/* type_0, type_1 only support up to 1228800 baud */
-			if (spriv->type != HX)
-				baud = 1228800;
-			else if (baud > 6000000)
-				baud = 6000000;
-		}
-		dev_dbg(&port->dev, "baud set = %d\n", baud);
-		if (baud <= 115200) {
-			buf[0] = baud & 0xff;
-			buf[1] = (baud >> 8) & 0xff;
-			buf[2] = (baud >> 16) & 0xff;
-			buf[3] = (baud >> 24) & 0xff;
-		} else {
-			/* apparently the formula for higher speeds is:
-			 * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
-			 */
-			unsigned tmp = 12*1000*1000*32 / baud;
-			buf[3] = 0x80;
-			buf[2] = 0;
-			buf[1] = (tmp >= 256);
-			while (tmp >= 256) {
-				tmp >>= 2;
-				buf[1] <<= 1;
-			}
-			buf[0] = tmp;
-		}
-	}
+	pl2303_encode_baudrate(tty, port, &buf[0]);
 
 	/* For reference buf[4]=0 is 1 stop bits */
 	/* For reference buf[4]=1 is 1.5 stop bits */
 	/* For reference buf[4]=2 is 2 stop bits */
-	if (cflag & CSTOPB) {
-		/* NOTE: Comply with "real" UARTs / RS232:
+	if (C_CSTOPB(tty)) {
+		/*
+		 * NOTE: Comply with "real" UARTs / RS232:
 		 *       use 1.5 instead of 2 stop bits with 5 data bits
 		 */
-		if ((cflag & CSIZE) == CS5) {
+		if (C_CSIZE(tty) == CS5) {
 			buf[4] = 1;
 			dev_dbg(&port->dev, "stop bits = 1.5\n");
 		} else {
@@ -395,14 +406,14 @@ static void pl2303_set_termios(struct tty_struct *tty,
 		dev_dbg(&port->dev, "stop bits = 1\n");
 	}
 
-	if (cflag & PARENB) {
+	if (C_PARENB(tty)) {
 		/* For reference buf[5]=0 is none parity */
 		/* For reference buf[5]=1 is odd parity */
 		/* For reference buf[5]=2 is even parity */
 		/* For reference buf[5]=3 is mark parity */
 		/* For reference buf[5]=4 is space parity */
-		if (cflag & PARODD) {
-			if (cflag & CMSPAR) {
+		if (C_PARODD(tty)) {
+			if (tty->termios.c_cflag & CMSPAR) {
 				buf[5] = 3;
 				dev_dbg(&port->dev, "parity = mark\n");
 			} else {
@@ -410,7 +421,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
 				dev_dbg(&port->dev, "parity = odd\n");
 			}
 		} else {
-			if (cflag & CMSPAR) {
+			if (tty->termios.c_cflag & CMSPAR) {
 				buf[5] = 4;
 				dev_dbg(&port->dev, "parity = space\n");
 			} else {
@@ -431,7 +442,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
 	/* change control lines if we are switching to or from B0 */
 	spin_lock_irqsave(&priv->lock, flags);
 	control = priv->line_control;
-	if ((cflag & CBAUD) == B0)
+	if (C_BAUD(tty) == B0)
 		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
 	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
 		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
@@ -443,14 +454,13 @@ static void pl2303_set_termios(struct tty_struct *tty,
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
-	buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
-
+	memset(buf, 0, 7);
 	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
 			    0, 0, buf, 7, 100);
 	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);
 
-	if (cflag & CRTSCTS) {
+	if (C_CRTSCTS(tty)) {
 		if (spriv->type == HX)
 			pl2303_vendor_write(0x0, 0x61, serial);
 		else
@@ -459,10 +469,6 @@ static void pl2303_set_termios(struct tty_struct *tty,
 		pl2303_vendor_write(0x0, 0x0, serial);
 	}
 
-	/* Save resulting baud rate */
-	if (baud)
-		tty_encode_baud_rate(tty, baud, baud);
-
 	kfree(buf);
 }
 
@@ -521,7 +527,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 		return result;
 	}
 
-	port->port.drain_delay = 256;
 	return 0;
 }
 
@@ -789,8 +794,10 @@ static void pl2303_process_read_urb(struct urb *urb)
 		tty_flag = TTY_PARITY;
 	else if (line_status & UART_FRAME_ERROR)
 		tty_flag = TTY_FRAME;
-	dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag);
 
+	if (tty_flag != TTY_NORMAL)
+		dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__,
+								tty_flag);
 	/* overrun is special, not associated with a char */
 	if (line_status & UART_OVERRUN_ERROR)
 		tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 21cd7bf..ba89598 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -92,13 +92,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-static __u16 vendor;		/* no default */
-static __u16 product;		/* no default */
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)");
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified USB idProduct (required)");
-
 module_param(safe, bool, 0);
 MODULE_PARM_DESC(safe, "Turn Safe Encapsulation On/Off");
 
@@ -140,8 +133,6 @@ static struct usb_device_id id_table[] = {
 	{MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
 	{MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
 	{MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Sharp tmp */
-	/* extra null entry for module vendor/produc parameters */
-	{MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
 	{}			/* terminating entry  */
 };
 
@@ -272,7 +263,19 @@ static int safe_prepare_write_buffer(struct usb_serial_port *port,
 
 static int safe_startup(struct usb_serial *serial)
 {
-	switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
+	struct usb_interface_descriptor	*desc;
+
+	if (serial->dev->descriptor.bDeviceClass != CDC_DEVICE_CLASS)
+		return -ENODEV;
+
+	desc = &serial->interface->cur_altsetting->desc;
+
+	if (desc->bInterfaceClass != LINEO_INTERFACE_CLASS)
+		return -ENODEV;
+	if (desc->bInterfaceSubClass != LINEO_INTERFACE_SUBCLASS_SAFESERIAL)
+		return -ENODEV;
+
+	switch (desc->bInterfaceProtocol) {
 	case LINEO_SAFESERIAL_CRC:
 		break;
 	case LINEO_SAFESERIAL_CRC_PADDED:
@@ -300,30 +303,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
 	&safe_device, NULL
 };
 
-static int __init safe_init(void)
-{
-	int i;
-
-	/* if we have vendor / product parameters patch them into id list */
-	if (vendor || product) {
-		pr_info("vendor: %x product: %x\n", vendor, product);
-
-		for (i = 0; i < ARRAY_SIZE(id_table); i++) {
-			if (!id_table[i].idVendor && !id_table[i].idProduct) {
-				id_table[i].idVendor = vendor;
-				id_table[i].idProduct = product;
-				break;
-			}
-		}
-	}
-
-	return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table);
-}
-
-static void __exit safe_exit(void)
-{
-	usb_serial_deregister_drivers(serial_drivers);
-}
-
-module_init(safe_init);
-module_exit(safe_exit);
+module_usb_serial_driver(serial_drivers, id_table);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index ddf6c47..4abac28 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -169,6 +169,8 @@ static int spcp8x5_port_probe(struct usb_serial_port *port)
 
 	usb_set_serial_port_data(port, priv);
 
+	port->port.drain_delay = 256;
+
 	return 0;
 }
 
@@ -411,8 +413,6 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
 	if (tty)
 		spcp8x5_set_termios(tty, port, NULL);
 
-	port->port.drain_delay = 256;
-
 	return usb_serial_generic_open(tty, port);
 }
 
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 375b5a4..5c07d55 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -45,8 +45,6 @@
 
 #define TI_FIRMWARE_BUF_SIZE	16284
 
-#define TI_WRITE_BUF_SIZE	1024
-
 #define TI_TRANSFER_TIMEOUT	2
 
 #define TI_DEFAULT_CLOSING_WAIT	4000		/* in .01 secs */
@@ -71,13 +69,11 @@ struct ti_port {
 	__u8			tp_uart_mode;	/* 232 or 485 modes */
 	unsigned int		tp_uart_base_addr;
 	int			tp_flags;
-	wait_queue_head_t	tp_write_wait;
 	struct ti_device	*tp_tdev;
 	struct usb_serial_port	*tp_port;
 	spinlock_t		tp_lock;
 	int			tp_read_urb_state;
 	int			tp_write_urb_in_use;
-	struct kfifo		write_fifo;
 };
 
 struct ti_device {
@@ -145,20 +141,9 @@ static int ti_download_firmware(struct ti_device *tdev);
 
 /* module parameters */
 static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
-static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];
-static unsigned int vendor_3410_count;
-static ushort product_3410[TI_EXTRA_VID_PID_COUNT];
-static unsigned int product_3410_count;
-static ushort vendor_5052[TI_EXTRA_VID_PID_COUNT];
-static unsigned int vendor_5052_count;
-static ushort product_5052[TI_EXTRA_VID_PID_COUNT];
-static unsigned int product_5052_count;
 
 /* supported devices */
-/* the array dimension is the number of default entries plus */
-/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
-/* null entry */
-static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[] = {
 	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
 	{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -175,16 +160,18 @@ static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = {
 	{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) },
 	{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+	{ }	/* terminator */
 };
 
-static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_5052[] = {
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
+	{ }	/* terminator */
 };
 
-static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_combined[] = {
 	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
 	{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -204,7 +191,7 @@ static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1]
 	{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
 	{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
-	{ }
+	{ }	/* terminator */
 };
 
 static struct usb_serial_driver ti_1port_device = {
@@ -293,61 +280,12 @@ module_param(closing_wait, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(closing_wait,
     "Maximum wait for data to drain in close, in .01 secs, default is 4000");
 
-module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_3410,
-		"Vendor ids for 3410 based devices, 1-5 short integers");
-module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);
-MODULE_PARM_DESC(product_3410,
-		"Product ids for 3410 based devices, 1-5 short integers");
-module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_5052,
-		"Vendor ids for 5052 based devices, 1-5 short integers");
-module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);
-MODULE_PARM_DESC(product_5052,
-		"Product ids for 5052 based devices, 1-5 short integers");
-
 MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
 
+module_usb_serial_driver(serial_drivers, ti_id_table_combined);
 
 /* Functions */
 
-static int __init ti_init(void)
-{
-	int i, j, c;
-
-	/* insert extra vendor and product ids */
-	c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1;
-	j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
-	for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++, c++) {
-		ti_id_table_3410[j].idVendor = vendor_3410[i];
-		ti_id_table_3410[j].idProduct = product_3410[i];
-		ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
-		ti_id_table_combined[c].idVendor = vendor_3410[i];
-		ti_id_table_combined[c].idProduct = product_3410[i];
-		ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
-	}
-	j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
-	for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++, c++) {
-		ti_id_table_5052[j].idVendor = vendor_5052[i];
-		ti_id_table_5052[j].idProduct = product_5052[i];
-		ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
-		ti_id_table_combined[c].idVendor = vendor_5052[i];
-		ti_id_table_combined[c].idProduct = product_5052[i];
-		ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
-	}
-
-	return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ti_id_table_combined);
-}
-
-static void __exit ti_exit(void)
-{
-	usb_serial_deregister_drivers(serial_drivers);
-}
-
-module_init(ti_init);
-module_exit(ti_exit);
-
-
 static int ti_startup(struct usb_serial *serial)
 {
 	struct ti_device *tdev;
@@ -430,17 +368,14 @@ static int ti_port_probe(struct usb_serial_port *port)
 	else
 		tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
 	port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
-	init_waitqueue_head(&tport->tp_write_wait);
-	if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
-		kfree(tport);
-		return -ENOMEM;
-	}
 	tport->tp_port = port;
 	tport->tp_tdev = usb_get_serial_data(port->serial);
 	tport->tp_uart_mode = 0;	/* default is RS232 */
 
 	usb_set_serial_port_data(port, tport);
 
+	port->port.drain_delay = 3;
+
 	return 0;
 }
 
@@ -449,7 +384,6 @@ static int ti_port_remove(struct usb_serial_port *port)
 	struct ti_port *tport;
 
 	tport = usb_get_serial_port_data(port);
-	kfifo_free(&tport->write_fifo);
 	kfree(tport);
 
 	return 0;
@@ -582,8 +516,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
 	tport->tp_is_open = 1;
 	++tdev->td_open_port_count;
 
-	port->port.drain_delay = 3;
-
 	goto release_lock;
 
 unlink_int_urb:
@@ -616,7 +548,7 @@ static void ti_close(struct usb_serial_port *port)
 	usb_kill_urb(port->write_urb);
 	tport->tp_write_urb_in_use = 0;
 	spin_lock_irqsave(&tport->tp_lock, flags);
-	kfifo_reset_out(&tport->write_fifo);
+	kfifo_reset_out(&port->write_fifo);
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
 
 	port_number = port->port_number;
@@ -655,7 +587,7 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
 	if (tport == NULL || !tport->tp_is_open)
 		return -ENODEV;
 
-	count = kfifo_in_locked(&tport->write_fifo, data, count,
+	count = kfifo_in_locked(&port->write_fifo, data, count,
 							&tport->tp_lock);
 	ti_send(tport);
 
@@ -674,7 +606,7 @@ static int ti_write_room(struct tty_struct *tty)
 		return 0;
 
 	spin_lock_irqsave(&tport->tp_lock, flags);
-	room = kfifo_avail(&tport->write_fifo);
+	room = kfifo_avail(&port->write_fifo);
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
 
 	dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
@@ -693,7 +625,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
 		return 0;
 
 	spin_lock_irqsave(&tport->tp_lock, flags);
-	chars = kfifo_len(&tport->write_fifo);
+	chars = kfifo_len(&port->write_fifo);
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
 
 	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
@@ -1090,13 +1022,11 @@ static void ti_bulk_in_callback(struct urb *urb)
 	case -ESHUTDOWN:
 		dev_dbg(dev, "%s - urb shutting down, %d\n", __func__, status);
 		tport->tp_tdev->td_urb_error = 1;
-		wake_up_interruptible(&tport->tp_write_wait);
 		return;
 	default:
 		dev_err(dev, "%s - nonzero urb status, %d\n",
 			__func__, status);
 		tport->tp_tdev->td_urb_error = 1;
-		wake_up_interruptible(&tport->tp_write_wait);
 	}
 
 	if (status == -EPIPE)
@@ -1152,13 +1082,11 @@ static void ti_bulk_out_callback(struct urb *urb)
 	case -ESHUTDOWN:
 		dev_dbg(&port->dev, "%s - urb shutting down, %d\n", __func__, status);
 		tport->tp_tdev->td_urb_error = 1;
-		wake_up_interruptible(&tport->tp_write_wait);
 		return;
 	default:
 		dev_err_console(port, "%s - nonzero urb status, %d\n",
 			__func__, status);
 		tport->tp_tdev->td_urb_error = 1;
-		wake_up_interruptible(&tport->tp_write_wait);
 	}
 
 	/* send any buffered data */
@@ -1197,7 +1125,7 @@ static void ti_send(struct ti_port *tport)
 	if (tport->tp_write_urb_in_use)
 		goto unlock;
 
-	count = kfifo_out(&tport->write_fifo,
+	count = kfifo_out(&port->write_fifo,
 				port->write_urb->transfer_buffer,
 				port->bulk_out_size);
 
@@ -1232,7 +1160,6 @@ static void ti_send(struct ti_port *tport)
 	/* more room in the buffer for new writes, wakeup */
 	tty_port_tty_wakeup(&port->port);
 
-	wake_up_interruptible(&tport->tp_write_wait);
 	return;
 unlock:
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
@@ -1312,7 +1239,7 @@ static int ti_get_serial_info(struct ti_port *tport,
 	ret_serial.line = port->minor;
 	ret_serial.port = port->port_number;
 	ret_serial.flags = tport->tp_flags;
-	ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
+	ret_serial.xmit_fifo_size = kfifo_size(&port->write_fifo);
 	ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
 	ret_serial.closing_wait = cwait;
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index cb27fcb..6091bd5 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -681,20 +681,10 @@ static int serial_port_carrier_raised(struct tty_port *port)
 static void serial_port_dtr_rts(struct tty_port *port, int on)
 {
 	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
-	struct usb_serial *serial = p->serial;
-	struct usb_serial_driver *drv = serial->type;
+	struct usb_serial_driver *drv = p->serial->type;
 
-	if (!drv->dtr_rts)
-		return;
-	/*
-	 * Work-around bug in the tty-layer which can result in dtr_rts
-	 * being called after a disconnect (and tty_unregister_device
-	 * has returned). Remove once bug has been squashed.
-	 */
-	mutex_lock(&serial->disc_mutex);
-	if (!serial->disconnected)
+	if (drv->dtr_rts)
 		drv->dtr_rts(p, on);
-	mutex_unlock(&serial->disc_mutex);
 }
 
 static const struct tty_port_operations serial_port_ops = {
diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c
index 675384d..d771870 100644
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/usb-common.c
@@ -43,20 +43,20 @@ const char *usb_otg_state_string(enum usb_otg_state state)
 }
 EXPORT_SYMBOL_GPL(usb_otg_state_string);
 
+static const char *const speed_names[] = {
+	[USB_SPEED_UNKNOWN] = "UNKNOWN",
+	[USB_SPEED_LOW] = "low-speed",
+	[USB_SPEED_FULL] = "full-speed",
+	[USB_SPEED_HIGH] = "high-speed",
+	[USB_SPEED_WIRELESS] = "wireless",
+	[USB_SPEED_SUPER] = "super-speed",
+};
+
 const char *usb_speed_string(enum usb_device_speed speed)
 {
-	static const char *const names[] = {
-		[USB_SPEED_UNKNOWN] = "UNKNOWN",
-		[USB_SPEED_LOW] = "low-speed",
-		[USB_SPEED_FULL] = "full-speed",
-		[USB_SPEED_HIGH] = "high-speed",
-		[USB_SPEED_WIRELESS] = "wireless",
-		[USB_SPEED_SUPER] = "super-speed",
-	};
-
-	if (speed < 0 || speed >= ARRAY_SIZE(names))
+	if (speed < 0 || speed >= ARRAY_SIZE(speed_names))
 		speed = USB_SPEED_UNKNOWN;
-	return names[speed];
+	return speed_names[speed];
 }
 EXPORT_SYMBOL_GPL(usb_speed_string);
 
@@ -112,6 +112,33 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
 	return USB_DR_MODE_UNKNOWN;
 }
 EXPORT_SYMBOL_GPL(of_usb_get_dr_mode);
+
+/**
+ * of_usb_get_maximum_speed - Get maximum requested speed for a given USB
+ * controller.
+ * @np: Pointer to the given device_node
+ *
+ * The function gets the maximum speed string from property "maximum-speed",
+ * and returns the corresponding enum usb_device_speed.
+ */
+enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np)
+{
+	const char *maximum_speed;
+	int err;
+	int i;
+
+	err = of_property_read_string(np, "maximum-speed", &maximum_speed);
+	if (err < 0)
+		return USB_SPEED_UNKNOWN;
+
+	for (i = 0; i < ARRAY_SIZE(speed_names); i++)
+		if (strcmp(maximum_speed, speed_names[i]) == 0)
+			return i;
+
+	return USB_SPEED_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
+
 #endif
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 7ed3b03..ff97652 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -325,9 +325,8 @@ retry:
 		rv = skel_do_read_io(dev, count);
 		if (rv < 0)
 			goto exit;
-		else if (!(file->f_flags & O_NONBLOCK))
+		else
 			goto retry;
-		rv = -EAGAIN;
 	}
 exit:
 	mutex_unlock(&dev->io_mutex);
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 842f450..d3cb342 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1353,6 +1353,68 @@ static const struct file_operations vfio_device_fops = {
 };
 
 /**
+ * External user API, exported by symbols to be linked dynamically.
+ *
+ * The protocol includes:
+ *  1. do normal VFIO init operation:
+ *	- opening a new container;
+ *	- attaching group(s) to it;
+ *	- setting an IOMMU driver for a container.
+ * When IOMMU is set for a container, all groups in it are
+ * considered ready to use by an external user.
+ *
+ * 2. User space passes a group fd to an external user.
+ * The external user calls vfio_group_get_external_user()
+ * to verify that:
+ *	- the group is initialized;
+ *	- IOMMU is set for it.
+ * If both checks passed, vfio_group_get_external_user()
+ * increments the container user counter to prevent
+ * the VFIO group from disposal before KVM exits.
+ *
+ * 3. The external user calls vfio_external_user_iommu_id()
+ * to know an IOMMU ID.
+ *
+ * 4. When the external KVM finishes, it calls
+ * vfio_group_put_external_user() to release the VFIO group.
+ * This call decrements the container user counter.
+ */
+struct vfio_group *vfio_group_get_external_user(struct file *filep)
+{
+	struct vfio_group *group = filep->private_data;
+
+	if (filep->f_op != &vfio_group_fops)
+		return ERR_PTR(-EINVAL);
+
+	if (!atomic_inc_not_zero(&group->container_users))
+		return ERR_PTR(-EINVAL);
+
+	if (!group->container->iommu_driver ||
+			!vfio_group_viable(group)) {
+		atomic_dec(&group->container_users);
+		return ERR_PTR(-EINVAL);
+	}
+
+	vfio_group_get(group);
+
+	return group;
+}
+EXPORT_SYMBOL_GPL(vfio_group_get_external_user);
+
+void vfio_group_put_external_user(struct vfio_group *group)
+{
+	vfio_group_put(group);
+	vfio_group_try_dissolve_container(group);
+}
+EXPORT_SYMBOL_GPL(vfio_group_put_external_user);
+
+int vfio_external_user_iommu_id(struct vfio_group *group)
+{
+	return iommu_group_id(group->iommu_group);
+}
+EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id);
+
+/**
  * Module/class support
  */
 static char *vfio_devnode(struct device *dev, umode_t *mode)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index e58cf00..4c19ca1 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -161,9 +161,11 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
 	if (list_empty(&work->node)) {
 		list_add_tail(&work->node, &dev->work_list);
 		work->queue_seq++;
+		spin_unlock_irqrestore(&dev->work_lock, flags);
 		wake_up_process(dev->worker);
+	} else {
+		spin_unlock_irqrestore(&dev->work_lock, flags);
 	}
-	spin_unlock_irqrestore(&dev->work_lock, flags);
 }
 EXPORT_SYMBOL_GPL(vhost_work_queue);
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4cf1e1d..9b32a99 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -996,6 +996,8 @@ config FB_ATMEL
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
 	help
 	  This enables support for the AT91/AT32 LCD Controller.
 
@@ -2100,13 +2102,6 @@ config GPM1040A0_320X240
         bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
         depends on FB_NUC900
 
-config FB_NUC900_DEBUG
-        bool "NUC900 lcd debug messages"
-        depends on FB_NUC900
-        help
-          Turn on debugging messages. Note that you can set/unset at run time
-          through sysfs
-
 config FB_SM501
 	tristate "Silicon Motion SM501 framebuffer support"
 	depends on FB && MFD_SM501
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 6488a73..7e8346e 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -38,14 +38,6 @@
 #include "acornfb.h"
 
 /*
- * VIDC machines can't do 16 or 32BPP modes.
- */
-#ifdef HAS_VIDC
-#undef FBCON_HAS_CFB16
-#undef FBCON_HAS_CFB32
-#endif
-
-/*
  * Default resolution.
  * NOTE that it has to be supported in the table towards
  * the end of this file.
@@ -106,238 +98,6 @@ static struct vidc_timing current_vidc;
 
 extern unsigned int vram_size;	/* set by setup.c */
 
-#ifdef HAS_VIDC
-
-#define MAX_SIZE	480*1024
-
-/* CTL     VIDC	Actual
- * 24.000  0	 8.000
- * 25.175  0	 8.392
- * 36.000  0	12.000
- * 24.000  1	12.000
- * 25.175  1	12.588
- * 24.000  2	16.000
- * 25.175  2	16.783
- * 36.000  1	18.000
- * 24.000  3	24.000
- * 36.000  2	24.000
- * 25.175  3	25.175
- * 36.000  3	36.000
- */
-struct pixclock {
-	u_long	min_clock;
-	u_long	max_clock;
-	u_int	vidc_ctl;
-	u_int	vid_ctl;
-};
-
-static struct pixclock arc_clocks[] = {
-	/* we allow +/-1% on these */
-	{ 123750, 126250, VIDC_CTRL_DIV3,   VID_CTL_24MHz },	/*  8.000MHz */
-	{  82500,  84167, VIDC_CTRL_DIV2,   VID_CTL_24MHz },	/* 12.000MHz */
-	{  61875,  63125, VIDC_CTRL_DIV1_5, VID_CTL_24MHz },	/* 16.000MHz */
-	{  41250,  42083, VIDC_CTRL_DIV1,   VID_CTL_24MHz },	/* 24.000MHz */
-};
-
-static struct pixclock *
-acornfb_valid_pixrate(struct fb_var_screeninfo *var)
-{
-	u_long pixclock = var->pixclock;
-	u_int i;
-
-	if (!var->pixclock)
-		return NULL;
-
-	for (i = 0; i < ARRAY_SIZE(arc_clocks); i++)
-		if (pixclock > arc_clocks[i].min_clock &&
-		    pixclock < arc_clocks[i].max_clock)
-			return arc_clocks + i;
-
-	return NULL;
-}
-
-/* VIDC Rules:
- * hcr  : must be even (interlace, hcr/2 must be even)
- * hswr : must be even
- * hdsr : must be odd
- * hder : must be odd
- *
- * vcr  : must be odd
- * vswr : >= 1
- * vdsr : >= 1
- * vder : >= vdsr
- * if interlaced, then hcr/2 must be even
- */
-static void
-acornfb_set_timing(struct fb_var_screeninfo *var)
-{
-	struct pixclock *pclk;
-	struct vidc_timing vidc;
-	u_int horiz_correction;
-	u_int sync_len, display_start, display_end, cycle;
-	u_int is_interlaced;
-	u_int vid_ctl, vidc_ctl;
-	u_int bandwidth;
-
-	memset(&vidc, 0, sizeof(vidc));
-
-	pclk = acornfb_valid_pixrate(var);
-	vidc_ctl = pclk->vidc_ctl;
-	vid_ctl  = pclk->vid_ctl;
-
-	bandwidth = var->pixclock * 8 / var->bits_per_pixel;
-	/* 25.175, 4bpp = 79.444ns per byte, 317.776ns per word: fifo = 2,6 */
-	if (bandwidth > 143500)
-		vidc_ctl |= VIDC_CTRL_FIFO_3_7;
-	else if (bandwidth > 71750)
-		vidc_ctl |= VIDC_CTRL_FIFO_2_6;
-	else if (bandwidth > 35875)
-		vidc_ctl |= VIDC_CTRL_FIFO_1_5;
-	else
-		vidc_ctl |= VIDC_CTRL_FIFO_0_4;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		horiz_correction = 19;
-		vidc_ctl |= VIDC_CTRL_1BPP;
-		break;
-
-	case 2:
-		horiz_correction = 11;
-		vidc_ctl |= VIDC_CTRL_2BPP;
-		break;
-
-	case 4:
-		horiz_correction = 7;
-		vidc_ctl |= VIDC_CTRL_4BPP;
-		break;
-
-	default:
-	case 8:
-		horiz_correction = 5;
-		vidc_ctl |= VIDC_CTRL_8BPP;
-		break;
-	}
-
-	if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
-		vidc_ctl |= VIDC_CTRL_CSYNC;
-	else {
-		if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
-			vid_ctl |= VID_CTL_HS_NHSYNC;
-
-		if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
-			vid_ctl |= VID_CTL_VS_NVSYNC;
-	}
-
-	sync_len	= var->hsync_len;
-	display_start	= sync_len + var->left_margin;
-	display_end	= display_start + var->xres;
-	cycle		= display_end + var->right_margin;
-
-	/* if interlaced, then hcr/2 must be even */
-	is_interlaced = (var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
-
-	if (is_interlaced) {
-		vidc_ctl |= VIDC_CTRL_INTERLACE;
-		if (cycle & 2) {
-			cycle += 2;
-			var->right_margin += 2;
-		}
-	}
-
-	vidc.h_cycle		= (cycle - 2) / 2;
-	vidc.h_sync_width	= (sync_len - 2) / 2;
-	vidc.h_border_start	= (display_start - 1) / 2;
-	vidc.h_display_start	= (display_start - horiz_correction) / 2;
-	vidc.h_display_end	= (display_end - horiz_correction) / 2;
-	vidc.h_border_end	= (display_end - 1) / 2;
-	vidc.h_interlace	= (vidc.h_cycle + 1) / 2;
-
-	sync_len	= var->vsync_len;
-	display_start	= sync_len + var->upper_margin;
-	display_end	= display_start + var->yres;
-	cycle		= display_end + var->lower_margin;
-
-	if (is_interlaced)
-		cycle = (cycle - 3) / 2;
-	else
-		cycle = cycle - 1;
-
-	vidc.v_cycle		= cycle;
-	vidc.v_sync_width	= sync_len - 1;
-	vidc.v_border_start	= display_start - 1;
-	vidc.v_display_start	= vidc.v_border_start;
-	vidc.v_display_end	= display_end - 1;
-	vidc.v_border_end	= vidc.v_display_end;
-
-	if (machine_is_a5k())
-		__raw_writeb(vid_ctl, IOEB_VID_CTL);
-
-	if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
-		current_vidc = vidc;
-
-		vidc_writel(0xe0000000 | vidc_ctl);
-		vidc_writel(0x80000000 | (vidc.h_cycle << 14));
-		vidc_writel(0x84000000 | (vidc.h_sync_width << 14));
-		vidc_writel(0x88000000 | (vidc.h_border_start << 14));
-		vidc_writel(0x8c000000 | (vidc.h_display_start << 14));
-		vidc_writel(0x90000000 | (vidc.h_display_end << 14));
-		vidc_writel(0x94000000 | (vidc.h_border_end << 14));
-		vidc_writel(0x98000000);
-		vidc_writel(0x9c000000 | (vidc.h_interlace << 14));
-		vidc_writel(0xa0000000 | (vidc.v_cycle << 14));
-		vidc_writel(0xa4000000 | (vidc.v_sync_width << 14));
-		vidc_writel(0xa8000000 | (vidc.v_border_start << 14));
-		vidc_writel(0xac000000 | (vidc.v_display_start << 14));
-		vidc_writel(0xb0000000 | (vidc.v_display_end << 14));
-		vidc_writel(0xb4000000 | (vidc.v_border_end << 14));
-		vidc_writel(0xb8000000);
-		vidc_writel(0xbc000000);
-	}
-#ifdef DEBUG_MODE_SELECTION
-	printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
-	       var->yres, var->bits_per_pixel);
-	printk(KERN_DEBUG " H-cycle          : %d\n", vidc.h_cycle);
-	printk(KERN_DEBUG " H-sync-width     : %d\n", vidc.h_sync_width);
-	printk(KERN_DEBUG " H-border-start   : %d\n", vidc.h_border_start);
-	printk(KERN_DEBUG " H-display-start  : %d\n", vidc.h_display_start);
-	printk(KERN_DEBUG " H-display-end    : %d\n", vidc.h_display_end);
-	printk(KERN_DEBUG " H-border-end     : %d\n", vidc.h_border_end);
-	printk(KERN_DEBUG " H-interlace      : %d\n", vidc.h_interlace);
-	printk(KERN_DEBUG " V-cycle          : %d\n", vidc.v_cycle);
-	printk(KERN_DEBUG " V-sync-width     : %d\n", vidc.v_sync_width);
-	printk(KERN_DEBUG " V-border-start   : %d\n", vidc.v_border_start);
-	printk(KERN_DEBUG " V-display-start  : %d\n", vidc.v_display_start);
-	printk(KERN_DEBUG " V-display-end    : %d\n", vidc.v_display_end);
-	printk(KERN_DEBUG " V-border-end     : %d\n", vidc.v_border_end);
-	printk(KERN_DEBUG " VIDC Ctrl (E)    : 0x%08X\n", vidc_ctl);
-	printk(KERN_DEBUG " IOEB Ctrl        : 0x%08X\n", vid_ctl);
-#endif
-}
-
-static int
-acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		  u_int trans, struct fb_info *info)
-{
-	union palette pal;
-
-	if (regno >= current_par.palette_size)
-		return 1;
-
-	pal.p = 0;
-	pal.vidc.reg   = regno;
-	pal.vidc.red   = red >> 12;
-	pal.vidc.green = green >> 12;
-	pal.vidc.blue  = blue >> 12;
-
-	current_par.palette[regno] = pal;
-
-	vidc_writel(pal.p);
-
-	return 0;
-}
-#endif
-
 #ifdef HAS_VIDC20
 #include <mach/acornfb.h>
 
@@ -634,16 +394,7 @@ acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int
 	/* hsync_len must be even */
 	var->hsync_len = (var->hsync_len + 1) & ~1;
 
-#ifdef HAS_VIDC
-	/* left_margin must be odd */
-	if ((var->left_margin & 1) == 0) {
-		var->left_margin -= 1;
-		var->right_margin += 1;
-	}
-
-	/* right_margin must be odd */
-	var->right_margin |= 1;
-#elif defined(HAS_VIDC20)
+#if defined(HAS_VIDC20)
 	/* left_margin must be even */
 	if (var->left_margin & 1) {
 		var->left_margin += 1;
@@ -787,11 +538,7 @@ static int acornfb_set_par(struct fb_info *info)
 		break;
 	case 8:
 		current_par.palette_size = VIDC_PALETTE_SIZE;
-#ifdef HAS_VIDC
-		info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-#else
 		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-#endif
 		break;
 #ifdef HAS_VIDC20
 	case 16:
@@ -971,9 +718,6 @@ static void acornfb_init_fbinfo(void)
 #if defined(HAS_VIDC20)
 	fb_info.var.red.length	   = 8;
 	fb_info.var.transp.length  = 4;
-#elif defined(HAS_VIDC)
-	fb_info.var.red.length	   = 4;
-	fb_info.var.transp.length  = 1;
 #endif
 	fb_info.var.green	   = fb_info.var.red;
 	fb_info.var.blue	   = fb_info.var.red;
@@ -1310,14 +1054,6 @@ static int acornfb_probe(struct platform_device *dev)
 		fb_info.fix.smem_start = handle;
 	}
 #endif
-#if defined(HAS_VIDC)
-	/*
-	 * Archimedes/A5000 machines use a fixed address for their
-	 * framebuffers.  Free unused pages
-	 */
-	free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
-#endif
-
 	fb_info.fix.smem_len = size;
 	current_par.palette_size   = VIDC_PALETTE_SIZE;
 
diff --git a/drivers/video/acornfb.h b/drivers/video/acornfb.h
index fb2a7ff..175c8ff 100644
--- a/drivers/video/acornfb.h
+++ b/drivers/video/acornfb.h
@@ -13,10 +13,6 @@
 #include <asm/hardware/iomd.h>
 #define VIDC_PALETTE_SIZE	256
 #define VIDC_NAME		"VIDC20"
-#elif defined(HAS_VIDC)
-#include <asm/hardware/memc.h>
-#define VIDC_PALETTE_SIZE	16
-#define VIDC_NAME		"VIDC"
 #endif
 
 #define EXTEND8(x) ((x)|(x)<<8)
@@ -101,31 +97,6 @@ struct modex_params {
 	const struct modey_params *modey;
 };
 
-#ifdef HAS_VIDC
-
-#define VID_CTL_VS_NVSYNC	(1 << 3)
-#define VID_CTL_HS_NHSYNC	(1 << 2)
-#define VID_CTL_24MHz		(0)
-#define VID_CTL_25MHz		(1)
-#define VID_CTL_36MHz		(2)
-
-#define VIDC_CTRL_CSYNC		(1 << 7)
-#define VIDC_CTRL_INTERLACE	(1 << 6)
-#define VIDC_CTRL_FIFO_0_4	(0 << 4)
-#define VIDC_CTRL_FIFO_1_5	(1 << 4)
-#define VIDC_CTRL_FIFO_2_6	(2 << 4)
-#define VIDC_CTRL_FIFO_3_7	(3 << 4)
-#define VIDC_CTRL_1BPP		(0 << 2)
-#define VIDC_CTRL_2BPP		(1 << 2)
-#define VIDC_CTRL_4BPP		(2 << 2)
-#define VIDC_CTRL_8BPP		(3 << 2)
-#define VIDC_CTRL_DIV3		(0 << 0)
-#define VIDC_CTRL_DIV2		(1 << 0)
-#define VIDC_CTRL_DIV1_5	(2 << 0)
-#define VIDC_CTRL_DIV1		(3 << 0)
-
-#endif
-
 #ifdef HAS_VIDC20
 /*
  * VIDC20 registers
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index effdb37..ece49d5 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -20,12 +20,55 @@
 #include <linux/gfp.h>
 #include <linux/module.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
 
 #include <mach/cpu.h>
 #include <asm/gpio.h>
 
 #include <video/atmel_lcdc.h>
 
+struct atmel_lcdfb_config {
+	bool have_alt_pixclock;
+	bool have_hozval;
+	bool have_intensity_bit;
+};
+
+ /* LCD Controller info data structure, stored in device platform_data */
+struct atmel_lcdfb_info {
+	spinlock_t		lock;
+	struct fb_info		*info;
+	void __iomem		*mmio;
+	int			irq_base;
+	struct work_struct	task;
+
+	unsigned int		smem_len;
+	struct platform_device	*pdev;
+	struct clk		*bus_clk;
+	struct clk		*lcdc_clk;
+
+	struct backlight_device	*backlight;
+	u8			bl_power;
+	u8			saved_lcdcon;
+
+	u32			pseudo_palette[16];
+	bool			have_intensity_bit;
+
+	struct atmel_lcdfb_pdata pdata;
+
+	struct atmel_lcdfb_config *config;
+};
+
+struct atmel_lcdfb_power_ctrl_gpio {
+	int gpio;
+	int active_low;
+
+	struct list_head list;
+};
+
 #define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
 #define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))
 
@@ -34,12 +77,6 @@
 #define ATMEL_LCDC_DMA_BURST_LEN	8	/* words */
 #define ATMEL_LCDC_FIFO_SIZE		512	/* words */
 
-struct atmel_lcdfb_config {
-	bool have_alt_pixclock;
-	bool have_hozval;
-	bool have_intensity_bit;
-};
-
 static struct atmel_lcdfb_config at91sam9261_config = {
 	.have_hozval		= true,
 	.have_intensity_bit	= true,
@@ -248,18 +285,27 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo)
 
 static void init_contrast(struct atmel_lcdfb_info *sinfo)
 {
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
 	/* contrast pwm can be 'inverted' */
-	if (sinfo->lcdcon_pol_negative)
+	if (pdata->lcdcon_pol_negative)
 			contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
 
 	/* have some default contrast/backlight settings */
 	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
 	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
 
-	if (sinfo->lcdcon_is_backlight)
+	if (pdata->lcdcon_is_backlight)
 		init_backlight(sinfo);
 }
 
+static inline void atmel_lcdfb_power_control(struct atmel_lcdfb_info *sinfo, int on)
+{
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+	if (pdata->atmel_lcdfb_power_control)
+		pdata->atmel_lcdfb_power_control(pdata, on);
+}
 
 static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
 	.type		= FB_TYPE_PACKED_PIXELS,
@@ -299,9 +345,11 @@ static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
 
 static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
 {
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
 	/* Turn off the LCD controller and the DMA controller */
 	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-			sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+			pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
 
 	/* Wait for the LCDC core to become idle */
 	while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
@@ -321,9 +369,11 @@ static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
 
 static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
 {
-	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, pdata->default_dmacon);
 	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-		(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
+		(pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
 		| ATMEL_LCDC_PWR);
 }
 
@@ -424,6 +474,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
 {
 	struct device *dev = info->device;
 	struct atmel_lcdfb_info *sinfo = info->par;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
 	unsigned long clk_value_khz;
 
 	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
@@ -510,7 +561,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
 		else
 			var->green.length = 6;
 
-		if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+		if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
 			/* RGB:5X5 mode */
 			var->red.offset = var->green.length + 5;
 			var->blue.offset = 0;
@@ -527,7 +578,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
 		var->transp.length = 8;
 		/* fall through */
 	case 24:
-		if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+		if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
 			/* RGB:888 mode */
 			var->red.offset = 16;
 			var->blue.offset = 0;
@@ -576,6 +627,7 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
 static int atmel_lcdfb_set_par(struct fb_info *info)
 {
 	struct atmel_lcdfb_info *sinfo = info->par;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
 	unsigned long hozval_linesz;
 	unsigned long value;
 	unsigned long clk_value_khz;
@@ -637,7 +689,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
 
 
 	/* Initialize control register 2 */
-	value = sinfo->default_lcdcon2;
+	value = pdata->default_lcdcon2;
 
 	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
 		value |= ATMEL_LCDC_INVLINE_INVERTED;
@@ -741,6 +793,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
 			     unsigned int transp, struct fb_info *info)
 {
 	struct atmel_lcdfb_info *sinfo = info->par;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
 	unsigned int val;
 	u32 *pal;
 	int ret = 1;
@@ -777,8 +830,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
 				 */
 			} else {
 				/* new style BGR:565 / RGB:565 */
-				if (sinfo->lcd_wiring_mode ==
-				    ATMEL_LCDC_WIRING_RGB) {
+				if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
 					val  = ((blue >> 11) & 0x001f);
 					val |= ((red  >>  0) & 0xf800);
 				} else {
@@ -912,16 +964,187 @@ static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
 	clk_disable(sinfo->lcdc_clk);
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_lcdfb_dt_ids[] = {
+	{ .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, },
+	{ .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, },
+	{ .compatible = "atmel,at91sam9g10-lcdc" , .data = &at91sam9g10_config, },
+	{ .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, },
+	{ .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, },
+	{ .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, },
+	{ .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_lcdfb_dt_ids);
+
+static const char *atmel_lcdfb_wiring_modes[] = {
+	[ATMEL_LCDC_WIRING_BGR]	= "BRG",
+	[ATMEL_LCDC_WIRING_RGB]	= "RGB",
+};
+
+const int atmel_lcdfb_get_of_wiring_modes(struct device_node *np)
+{
+	const char *mode;
+	int err, i;
+
+	err = of_property_read_string(np, "atmel,lcd-wiring-mode", &mode);
+	if (err < 0)
+		return ATMEL_LCDC_WIRING_BGR;
+
+	for (i = 0; i < ARRAY_SIZE(atmel_lcdfb_wiring_modes); i++)
+		if (!strcasecmp(mode, atmel_lcdfb_wiring_modes[i]))
+			return i;
+
+	return -ENODEV;
+}
+
+static void atmel_lcdfb_power_control_gpio(struct atmel_lcdfb_pdata *pdata, int on)
+{
+	struct atmel_lcdfb_power_ctrl_gpio *og;
+
+	list_for_each_entry(og, &pdata->pwr_gpios, list)
+		gpio_set_value(og->gpio, on);
+}
+
+static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+	struct fb_var_screeninfo *var = &info->var;
+	struct device *dev = &sinfo->pdev->dev;
+	struct device_node *np =dev->of_node;
+	struct device_node *display_np;
+	struct device_node *timings_np;
+	struct display_timings *timings;
+	enum of_gpio_flags flags;
+	struct atmel_lcdfb_power_ctrl_gpio *og;
+	bool is_gpio_power = false;
+	int ret = -ENOENT;
+	int i, gpio;
+
+	sinfo->config = (struct atmel_lcdfb_config*)
+		of_match_device(atmel_lcdfb_dt_ids, dev)->data;
+
+	display_np = of_parse_phandle(np, "display", 0);
+	if (!display_np) {
+		dev_err(dev, "failed to find display phandle\n");
+		return -ENOENT;
+	}
+
+	ret = of_property_read_u32(display_np, "bits-per-pixel", &var->bits_per_pixel);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bits-per-pixel\n");
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "atmel,guard-time", &pdata->guard_time);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property atmel,guard-time\n");
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "atmel,lcdcon2", &pdata->default_lcdcon2);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property atmel,lcdcon2\n");
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "atmel,dmacon", &pdata->default_dmacon);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bits-per-pixel\n");
+		goto put_display_node;
+	}
+
+	ret = -ENOMEM;
+	for (i = 0; i < of_gpio_named_count(display_np, "atmel,power-control-gpio"); i++) {
+		gpio = of_get_named_gpio_flags(display_np, "atmel,power-control-gpio",
+					       i, &flags);
+		if (gpio < 0)
+			continue;
+
+		og = devm_kzalloc(dev, sizeof(*og), GFP_KERNEL);
+		if (!og)
+			goto put_display_node;
+
+		og->gpio = gpio;
+		og->active_low = flags & OF_GPIO_ACTIVE_LOW;
+		is_gpio_power = true;
+		ret = devm_gpio_request(dev, gpio, "lcd-power-control-gpio");
+		if (ret) {
+			dev_err(dev, "request gpio %d failed\n", gpio);
+			goto put_display_node;
+		}
+
+		ret = gpio_direction_output(gpio, og->active_low);
+		if (ret) {
+			dev_err(dev, "set direction output gpio %d failed\n", gpio);
+			goto put_display_node;
+		}
+	}
+
+	if (is_gpio_power)
+		pdata->atmel_lcdfb_power_control = atmel_lcdfb_power_control_gpio;
+
+	ret = atmel_lcdfb_get_of_wiring_modes(display_np);
+	if (ret < 0) {
+		dev_err(dev, "invalid atmel,lcd-wiring-mode\n");
+		goto put_display_node;
+	}
+	pdata->lcd_wiring_mode = ret;
+
+	pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight");
+
+	timings = of_get_display_timings(display_np);
+	if (!timings) {
+		dev_err(dev, "failed to get display timings\n");
+		goto put_display_node;
+	}
+
+	timings_np = of_find_node_by_name(display_np, "display-timings");
+	if (!timings_np) {
+		dev_err(dev, "failed to find display-timings node\n");
+		goto put_display_node;
+	}
+
+	for (i = 0; i < of_get_child_count(timings_np); i++) {
+		struct videomode vm;
+		struct fb_videomode fb_vm;
+
+		ret = videomode_from_timings(timings, &vm, i);
+		if (ret < 0)
+			goto put_timings_node;
+		ret = fb_videomode_from_videomode(&vm, &fb_vm);
+		if (ret < 0)
+			goto put_timings_node;
+
+		fb_add_videomode(&fb_vm, &info->modelist);
+	}
+
+	return 0;
+
+put_timings_node:
+	of_node_put(timings_np);
+put_display_node:
+	of_node_put(display_np);
+	return ret;
+}
+#else
+static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
+{
+	return 0;
+}
+#endif
 
 static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct fb_info *info;
 	struct atmel_lcdfb_info *sinfo;
-	struct atmel_lcdfb_info *pdata_sinfo;
-	struct fb_videomode fbmode;
+	struct atmel_lcdfb_pdata *pdata = NULL;
 	struct resource *regs = NULL;
 	struct resource *map = NULL;
+	struct fb_modelist *modelist;
 	int ret;
 
 	dev_dbg(dev, "%s BEGIN\n", __func__);
@@ -934,26 +1157,35 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 	}
 
 	sinfo = info->par;
+	sinfo->pdev = pdev;
+	sinfo->info = info;
 
-	if (dev->platform_data) {
-		pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
-		sinfo->default_bpp = pdata_sinfo->default_bpp;
-		sinfo->default_dmacon = pdata_sinfo->default_dmacon;
-		sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
-		sinfo->default_monspecs = pdata_sinfo->default_monspecs;
-		sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
-		sinfo->guard_time = pdata_sinfo->guard_time;
-		sinfo->smem_len = pdata_sinfo->smem_len;
-		sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
-		sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative;
-		sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
+	INIT_LIST_HEAD(&info->modelist);
+
+	if (pdev->dev.of_node) {
+		ret = atmel_lcdfb_of_init(sinfo);
+		if (ret)
+			goto free_info;
+	} else if (dev->platform_data) {
+		struct fb_monspecs *monspecs;
+		int i;
+
+		pdata = dev->platform_data;
+		monspecs = pdata->default_monspecs;
+		sinfo->pdata = *pdata;
+
+		for (i = 0; i < monspecs->modedb_len; i++)
+			fb_add_videomode(&monspecs->modedb[i], &info->modelist);
+
+		sinfo->config = atmel_lcdfb_get_config(pdev);
+
+		info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
+		memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs));
 	} else {
 		dev_err(dev, "cannot get default configuration\n");
 		goto free_info;
 	}
-	sinfo->info = info;
-	sinfo->pdev = pdev;
-	sinfo->config = atmel_lcdfb_get_config(pdev);
+
 	if (!sinfo->config)
 		goto free_info;
 
@@ -962,7 +1194,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 	info->pseudo_palette = sinfo->pseudo_palette;
 	info->fbops = &atmel_lcdfb_ops;
 
-	memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
 	info->fix = atmel_lcdfb_fix;
 
 	/* Enable LCDC Clocks */
@@ -978,14 +1209,11 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 	}
 	atmel_lcdfb_start_clock(sinfo);
 
-	ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
-			info->monspecs.modedb_len, info->monspecs.modedb,
-			sinfo->default_bpp);
-	if (!ret) {
-		dev_err(dev, "no suitable video mode found\n");
-		goto stop_clk;
-	}
+	modelist = list_first_entry(&info->modelist,
+			struct fb_modelist, list);
+	fb_videomode_to_var(&info->var, &modelist->mode);
 
+	atmel_lcdfb_check_var(&info->var, info);
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
@@ -1069,18 +1297,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 		goto unregister_irqs;
 	}
 
-	/*
-	 * This makes sure that our colour bitfield
-	 * descriptors are correctly initialised.
-	 */
-	atmel_lcdfb_check_var(&info->var, info);
-
-	ret = fb_set_var(info, &info->var);
-	if (ret) {
-		dev_warn(dev, "unable to set display parameters\n");
-		goto free_cmap;
-	}
-
 	dev_set_drvdata(dev, info);
 
 	/*
@@ -1092,13 +1308,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 		goto reset_drvdata;
 	}
 
-	/* add selected videomode to modelist */
-	fb_var_to_videomode(&fbmode, &info->var);
-	fb_add_videomode(&fbmode, &info->modelist);
-
 	/* Power up the LCDC screen */
-	if (sinfo->atmel_lcdfb_power_control)
-		sinfo->atmel_lcdfb_power_control(1);
+	atmel_lcdfb_power_control(sinfo, 1);
 
 	dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
 		       info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
@@ -1107,7 +1318,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 
 reset_drvdata:
 	dev_set_drvdata(dev, NULL);
-free_cmap:
 	fb_dealloc_cmap(&info->cmap);
 unregister_irqs:
 	cancel_work_sync(&sinfo->task);
@@ -1143,15 +1353,16 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct fb_info *info = dev_get_drvdata(dev);
 	struct atmel_lcdfb_info *sinfo;
+	struct atmel_lcdfb_pdata *pdata;
 
 	if (!info || !info->par)
 		return 0;
 	sinfo = info->par;
+	pdata = &sinfo->pdata;
 
 	cancel_work_sync(&sinfo->task);
 	exit_backlight(sinfo);
-	if (sinfo->atmel_lcdfb_power_control)
-		sinfo->atmel_lcdfb_power_control(0);
+	atmel_lcdfb_power_control(sinfo, 0);
 	unregister_framebuffer(info);
 	atmel_lcdfb_stop_clock(sinfo);
 	clk_put(sinfo->lcdc_clk);
@@ -1188,9 +1399,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
 
 	sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
 	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
-	if (sinfo->atmel_lcdfb_power_control)
-		sinfo->atmel_lcdfb_power_control(0);
-
+	atmel_lcdfb_power_control(sinfo, 0);
 	atmel_lcdfb_stop(sinfo);
 	atmel_lcdfb_stop_clock(sinfo);
 
@@ -1204,8 +1413,7 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
 
 	atmel_lcdfb_start_clock(sinfo);
 	atmel_lcdfb_start(sinfo);
-	if (sinfo->atmel_lcdfb_power_control)
-		sinfo->atmel_lcdfb_power_control(1);
+	atmel_lcdfb_power_control(sinfo, 1);
 	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
 
 	/* Enable FIFO & DMA errors */
@@ -1228,6 +1436,7 @@ static struct platform_driver atmel_lcdfb_driver = {
 	.driver		= {
 		.name	= "atmel_lcdfb",
 		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(atmel_lcdfb_dt_ids),
 	},
 };
 
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index d5ab658..d4a7a35 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -425,6 +425,25 @@ config BACKLIGHT_AS3711
 	  If you have an Austrian Microsystems AS3711 say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_GPIO
+	tristate "Generic GPIO based Backlight Driver"
+	depends on GPIOLIB
+	help
+	  If you have a LCD backlight adjustable by GPIO, say Y to enable
+	  this driver.
+
+config BACKLIGHT_LV5207LP
+	tristate "Sanyo LV5207LP Backlight"
+	depends on I2C
+	help
+	  If you have a Sanyo LV5207LP say Y to enable the backlight driver.
+
+config BACKLIGHT_BD6107
+	tristate "Rohm BD6107 Backlight"
+	depends on I2C
+	help
+	  If you have a Rohm BD6107 say Y to enable the backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 92711fe..38e1bab 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -26,12 +26,14 @@ obj-$(CONFIG_BACKLIGHT_ADP8870)		+= adp8870_bl.o
 obj-$(CONFIG_BACKLIGHT_APPLE)		+= apple_bl.o
 obj-$(CONFIG_BACKLIGHT_AS3711)		+= as3711_bl.o
 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)	+= atmel-pwm-bl.o
+obj-$(CONFIG_BACKLIGHT_BD6107)		+= bd6107.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH)	+= cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE)	+= backlight.o
 obj-$(CONFIG_BACKLIGHT_DA903X)		+= da903x_bl.o
 obj-$(CONFIG_BACKLIGHT_DA9052)		+= da9052_bl.o
 obj-$(CONFIG_BACKLIGHT_EP93XX)		+= ep93xx_bl.o
 obj-$(CONFIG_BACKLIGHT_GENERIC)		+= generic_bl.o
+obj-$(CONFIG_BACKLIGHT_GPIO)		+= gpio_backlight.o
 obj-$(CONFIG_BACKLIGHT_HP680)		+= hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_HP700)		+= jornada720_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3533)		+= lm3533_bl.o
@@ -40,6 +42,7 @@ obj-$(CONFIG_BACKLIGHT_LM3639)		+= lm3639_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO)		+= locomolcd.o
 obj-$(CONFIG_BACKLIGHT_LP855X)		+= lp855x_bl.o
 obj-$(CONFIG_BACKLIGHT_LP8788)		+= lp8788_bl.o
+obj-$(CONFIG_BACKLIGHT_LV5207LP)	+= lv5207lp.o
 obj-$(CONFIG_BACKLIGHT_MAX8925)		+= max8925_bl.o
 obj-$(CONFIG_BACKLIGHT_OMAP1)		+= omap1_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200)		+= ot200_bl.o
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 3fccb6d..94a403a 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -103,16 +103,16 @@ static void backlight_generate_event(struct backlight_device *bd,
 	sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness");
 }
 
-static ssize_t backlight_show_power(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
 	return sprintf(buf, "%d\n", bd->props.power);
 }
 
-static ssize_t backlight_store_power(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	int rc;
 	struct backlight_device *bd = to_backlight_device(dev);
@@ -136,8 +136,9 @@ static ssize_t backlight_store_power(struct device *dev,
 
 	return rc;
 }
+static DEVICE_ATTR_RW(bl_power);
 
-static ssize_t backlight_show_brightness(struct device *dev,
+static ssize_t brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
@@ -145,7 +146,7 @@ static ssize_t backlight_show_brightness(struct device *dev,
 	return sprintf(buf, "%d\n", bd->props.brightness);
 }
 
-static ssize_t backlight_store_brightness(struct device *dev,
+static ssize_t brightness_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc;
@@ -175,24 +176,27 @@ static ssize_t backlight_store_brightness(struct device *dev,
 
 	return rc;
 }
+static DEVICE_ATTR_RW(brightness);
 
-static ssize_t backlight_show_type(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
 	return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
 }
+static DEVICE_ATTR_RO(type);
 
-static ssize_t backlight_show_max_brightness(struct device *dev,
+static ssize_t max_brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
 	return sprintf(buf, "%d\n", bd->props.max_brightness);
 }
+static DEVICE_ATTR_RO(max_brightness);
 
-static ssize_t backlight_show_actual_brightness(struct device *dev,
+static ssize_t actual_brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	int rc = -ENXIO;
@@ -205,6 +209,7 @@ static ssize_t backlight_show_actual_brightness(struct device *dev,
 
 	return rc;
 }
+static DEVICE_ATTR_RO(actual_brightness);
 
 static struct class *backlight_class;
 
@@ -247,16 +252,15 @@ static void bl_device_release(struct device *dev)
 	kfree(bd);
 }
 
-static struct device_attribute bl_device_attributes[] = {
-	__ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),
-	__ATTR(brightness, 0644, backlight_show_brightness,
-		     backlight_store_brightness),
-	__ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
-		     NULL),
-	__ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
-	__ATTR(type, 0444, backlight_show_type, NULL),
-	__ATTR_NULL,
+static struct attribute *bl_device_attrs[] = {
+	&dev_attr_bl_power.attr,
+	&dev_attr_brightness.attr,
+	&dev_attr_actual_brightness.attr,
+	&dev_attr_max_brightness.attr,
+	&dev_attr_type.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(bl_device);
 
 /**
  * backlight_force_update - tell the backlight subsystem that hardware state
@@ -493,7 +497,7 @@ static int __init backlight_class_init(void)
 		return PTR_ERR(backlight_class);
 	}
 
-	backlight_class->dev_attrs = bl_device_attributes;
+	backlight_class->dev_groups = bl_device_groups;
 	backlight_class->pm = &backlight_class_dev_pm_ops;
 	return 0;
 }
diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c
new file mode 100644
index 0000000..15e3294
--- /dev/null
+++ b/drivers/video/backlight/bd6107.c
@@ -0,0 +1,213 @@
+/*
+ * ROHM Semiconductor BD6107 LED Driver
+ *
+ * Copyright (C) 2013 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/platform_data/bd6107.h>
+#include <linux/slab.h>
+
+#define BD6107_PSCNT1				0x00
+#define BD6107_PSCNT1_PSCNTREG2			(1 << 2)
+#define BD6107_PSCNT1_PSCNTREG1			(1 << 0)
+#define BD6107_REGVSET				0x02
+#define BD6107_REGVSET_REG1VSET_2_85V		(1 << 2)
+#define BD6107_REGVSET_REG1VSET_2_80V		(0 << 2)
+#define BD6107_LEDCNT1				0x03
+#define BD6107_LEDCNT1_LEDONOFF2		(1 << 1)
+#define BD6107_LEDCNT1_LEDONOFF1		(1 << 0)
+#define BD6107_PORTSEL				0x04
+#define BD6107_PORTSEL_LEDM(n)			(1 << (n))
+#define BD6107_RGB1CNT1				0x05
+#define BD6107_RGB1CNT2				0x06
+#define BD6107_RGB1CNT3				0x07
+#define BD6107_RGB1CNT4				0x08
+#define BD6107_RGB1CNT5				0x09
+#define BD6107_RGB1FLM				0x0a
+#define BD6107_RGB2CNT1				0x0b
+#define BD6107_RGB2CNT2				0x0c
+#define BD6107_RGB2CNT3				0x0d
+#define BD6107_RGB2CNT4				0x0e
+#define BD6107_RGB2CNT5				0x0f
+#define BD6107_RGB2FLM				0x10
+#define BD6107_PSCONT3				0x11
+#define BD6107_SMMONCNT				0x12
+#define BD6107_DCDCCNT				0x13
+#define BD6107_IOSEL				0x14
+#define BD6107_OUT1				0x15
+#define BD6107_OUT2				0x16
+#define BD6107_MASK1				0x17
+#define BD6107_MASK2				0x18
+#define BD6107_FACTOR1				0x19
+#define BD6107_FACTOR2				0x1a
+#define BD6107_CLRFACT1				0x1b
+#define BD6107_CLRFACT2				0x1c
+#define BD6107_STATE1				0x1d
+#define BD6107_LSIVER				0x1e
+#define BD6107_GRPSEL				0x1f
+#define BD6107_LEDCNT2				0x20
+#define BD6107_LEDCNT3				0x21
+#define BD6107_MCURRENT				0x22
+#define BD6107_MAINCNT1				0x23
+#define BD6107_MAINCNT2				0x24
+#define BD6107_SLOPECNT				0x25
+#define BD6107_MSLOPE				0x26
+#define BD6107_RGBSLOPE				0x27
+#define BD6107_TEST				0x29
+#define BD6107_SFTRST				0x2a
+#define BD6107_SFTRSTGD				0x2b
+
+struct bd6107 {
+	struct i2c_client *client;
+	struct backlight_device *backlight;
+	struct bd6107_platform_data *pdata;
+};
+
+static int bd6107_write(struct bd6107 *bd, u8 reg, u8 data)
+{
+	return i2c_smbus_write_byte_data(bd->client, reg, data);
+}
+
+static int bd6107_backlight_update_status(struct backlight_device *backlight)
+{
+	struct bd6107 *bd = bl_get_data(backlight);
+	int brightness = backlight->props.brightness;
+
+	if (backlight->props.power != FB_BLANK_UNBLANK ||
+	    backlight->props.fb_blank != FB_BLANK_UNBLANK ||
+	    backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	if (brightness) {
+		bd6107_write(bd, BD6107_PORTSEL, BD6107_PORTSEL_LEDM(2) |
+			     BD6107_PORTSEL_LEDM(1) | BD6107_PORTSEL_LEDM(0));
+		bd6107_write(bd, BD6107_MAINCNT1, brightness);
+		bd6107_write(bd, BD6107_LEDCNT1, BD6107_LEDCNT1_LEDONOFF1);
+	} else {
+		gpio_set_value(bd->pdata->reset, 0);
+		msleep(24);
+		gpio_set_value(bd->pdata->reset, 1);
+	}
+
+	return 0;
+}
+
+static int bd6107_backlight_get_brightness(struct backlight_device *backlight)
+{
+	return backlight->props.brightness;
+}
+
+static int bd6107_backlight_check_fb(struct backlight_device *backlight,
+				       struct fb_info *info)
+{
+	struct bd6107 *bd = bl_get_data(backlight);
+
+	return bd->pdata->fbdev == NULL || bd->pdata->fbdev == info->dev;
+}
+
+static const struct backlight_ops bd6107_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= bd6107_backlight_update_status,
+	.get_brightness	= bd6107_backlight_get_brightness,
+	.check_fb	= bd6107_backlight_check_fb,
+};
+
+static int bd6107_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct bd6107_platform_data *pdata = client->dev.platform_data;
+	struct backlight_device *backlight;
+	struct backlight_properties props;
+	struct bd6107 *bd;
+	int ret;
+
+	if (pdata == NULL || !pdata->reset) {
+		dev_err(&client->dev, "No reset GPIO in platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_warn(&client->dev,
+			 "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
+		return -EIO;
+	}
+
+	bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL);
+	if (!bd)
+		return -ENOMEM;
+
+	bd->client = client;
+	bd->pdata = pdata;
+
+	ret = devm_gpio_request_one(&client->dev, pdata->reset,
+				    GPIOF_DIR_OUT | GPIOF_INIT_LOW, "reset");
+	if (ret < 0) {
+		dev_err(&client->dev, "unable to request reset GPIO\n");
+		return ret;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 128;
+	props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
+				   props.max_brightness);
+
+	backlight = backlight_device_register(dev_name(&client->dev),
+					      &bd->client->dev, bd,
+					      &bd6107_backlight_ops, &props);
+	if (IS_ERR(backlight)) {
+		dev_err(&client->dev, "failed to register backlight\n");
+		return PTR_ERR(backlight);
+	}
+
+	backlight_update_status(backlight);
+	i2c_set_clientdata(client, backlight);
+
+	return 0;
+}
+
+static int bd6107_remove(struct i2c_client *client)
+{
+	struct backlight_device *backlight = i2c_get_clientdata(client);
+
+	backlight->props.brightness = 0;
+	backlight_update_status(backlight);
+	backlight_device_unregister(backlight);
+
+	return 0;
+}
+
+static const struct i2c_device_id bd6107_ids[] = {
+	{ "bd6107", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bd6107_ids);
+
+static struct i2c_driver bd6107_driver = {
+	.driver = {
+		.name = "bd6107",
+	},
+	.probe = bd6107_probe,
+	.remove = bd6107_remove,
+	.id_table = bd6107_ids,
+};
+
+module_i2c_driver(bd6107_driver);
+
+MODULE_DESCRIPTION("Rohm BD6107 Backlight Driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c
new file mode 100644
index 0000000..5fa217f
--- /dev/null
+++ b/drivers/video/backlight/gpio_backlight.c
@@ -0,0 +1,133 @@
+/*
+ * gpio_backlight.c - Simple GPIO-controlled backlight
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_data/gpio_backlight.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct gpio_backlight {
+	struct device *dev;
+	struct device *fbdev;
+
+	int gpio;
+	int active;
+};
+
+static int gpio_backlight_update_status(struct backlight_device *bl)
+{
+	struct gpio_backlight *gbl = bl_get_data(bl);
+	int brightness = bl->props.brightness;
+
+	if (bl->props.power != FB_BLANK_UNBLANK ||
+	    bl->props.fb_blank != FB_BLANK_UNBLANK ||
+	    bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	gpio_set_value(gbl->gpio, brightness ? gbl->active : !gbl->active);
+
+	return 0;
+}
+
+static int gpio_backlight_get_brightness(struct backlight_device *bl)
+{
+	return bl->props.brightness;
+}
+
+static int gpio_backlight_check_fb(struct backlight_device *bl,
+				   struct fb_info *info)
+{
+	struct gpio_backlight *gbl = bl_get_data(bl);
+
+	return gbl->fbdev == NULL || gbl->fbdev == info->dev;
+}
+
+static const struct backlight_ops gpio_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= gpio_backlight_update_status,
+	.get_brightness	= gpio_backlight_get_brightness,
+	.check_fb	= gpio_backlight_check_fb,
+};
+
+static int gpio_backlight_probe(struct platform_device *pdev)
+{
+	struct gpio_backlight_platform_data *pdata = pdev->dev.platform_data;
+	struct backlight_properties props;
+	struct backlight_device *bl;
+	struct gpio_backlight *gbl;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "failed to find platform data\n");
+		return -ENODEV;
+	}
+
+	gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL);
+	if (gbl == NULL)
+		return -ENOMEM;
+
+	gbl->dev = &pdev->dev;
+	gbl->fbdev = pdata->fbdev;
+	gbl->gpio = pdata->gpio;
+	gbl->active = pdata->active_low ? 0 : 1;
+
+	ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT |
+				    (gbl->active ? GPIOF_INIT_LOW
+						 : GPIOF_INIT_HIGH),
+				    pdata->name);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to request GPIO\n");
+		return ret;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 1;
+	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, gbl,
+				       &gpio_backlight_ops, &props);
+	if (IS_ERR(bl)) {
+		dev_err(&pdev->dev, "failed to register backlight\n");
+		return PTR_ERR(bl);
+	}
+
+	bl->props.brightness = pdata->def_value;
+	backlight_update_status(bl);
+
+	platform_set_drvdata(pdev, bl);
+	return 0;
+}
+
+static int gpio_backlight_remove(struct platform_device *pdev)
+{
+	struct backlight_device *bl = platform_get_drvdata(pdev);
+
+	backlight_device_unregister(bl);
+	return 0;
+}
+
+static struct platform_driver gpio_backlight_driver = {
+	.driver		= {
+		.name		= "gpio-backlight",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= gpio_backlight_probe,
+	.remove		= gpio_backlight_remove,
+};
+
+module_platform_driver(gpio_backlight_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("GPIO-based Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-backlight");
diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
index a0482b5..c7af8c4 100644
--- a/drivers/video/backlight/hx8357.c
+++ b/drivers/video/backlight/hx8357.c
@@ -71,11 +71,24 @@
 #define HX8357_SET_POWER_NORMAL		0xd2
 #define HX8357_SET_PANEL_RELATED	0xe9
 
+#define HX8369_SET_DISPLAY_BRIGHTNESS		0x51
+#define HX8369_WRITE_CABC_DISPLAY_VALUE		0x53
+#define HX8369_WRITE_CABC_BRIGHT_CTRL		0x55
+#define HX8369_WRITE_CABC_MIN_BRIGHTNESS	0x5e
+#define HX8369_SET_POWER			0xb1
+#define HX8369_SET_DISPLAY_MODE			0xb2
+#define HX8369_SET_DISPLAY_WAVEFORM_CYC		0xb4
+#define HX8369_SET_VCOM				0xb6
+#define HX8369_SET_EXTENSION_COMMAND		0xb9
+#define HX8369_SET_GIP				0xd5
+#define HX8369_SET_GAMMA_CURVE_RELATED		0xe0
+
 struct hx8357_data {
 	unsigned		im_pins[HX8357_NUM_IM_PINS];
 	unsigned		reset;
 	struct spi_device	*spi;
 	int			state;
+	bool			use_im_pins;
 };
 
 static u8 hx8357_seq_power[] = {
@@ -143,6 +156,61 @@ static u8 hx8357_seq_display_mode[] = {
 	HX8357_SET_DISPLAY_MODE_RGB_INTERFACE,
 };
 
+static u8 hx8369_seq_write_CABC_min_brightness[] = {
+	HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00,
+};
+
+static u8 hx8369_seq_write_CABC_control[] = {
+	HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24,
+};
+
+static u8 hx8369_seq_set_display_brightness[] = {
+	HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF,
+};
+
+static u8 hx8369_seq_write_CABC_control_setting[] = {
+	HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02,
+};
+
+static u8 hx8369_seq_extension_command[] = {
+	HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69,
+};
+
+static u8 hx8369_seq_display_related[] = {
+	HX8369_SET_DISPLAY_MODE, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00,
+	0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00,	0x01,
+};
+
+static u8 hx8369_seq_panel_waveform_cycle[] = {
+	HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02,
+};
+
+static u8 hx8369_seq_set_address_mode[] = {
+	HX8357_SET_ADDRESS_MODE, 0x00,
+};
+
+static u8 hx8369_seq_vcom[] = {
+	HX8369_SET_VCOM, 0x3e, 0x3e,
+};
+
+static u8 hx8369_seq_gip[] = {
+	HX8369_SET_GIP, 0x00, 0x01, 0x03, 0x25, 0x01, 0x02, 0x28, 0x70,
+	0x11, 0x13, 0x00, 0x00, 0x40, 0x26, 0x51, 0x37, 0x00, 0x00, 0x71,
+	0x35, 0x60, 0x24, 0x07, 0x0f, 0x04, 0x04,
+};
+
+static u8 hx8369_seq_power[] = {
+	HX8369_SET_POWER, 0x01, 0x00, 0x34, 0x03, 0x00, 0x11, 0x11, 0x32,
+	0x2f, 0x3f, 0x3f, 0x01, 0x3a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
+};
+
+static u8 hx8369_seq_gamma_curve_related[] = {
+	HX8369_SET_GAMMA_CURVE_RELATED, 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d,
+	0x2e, 0x4a, 0x08, 0x0e, 0x0f, 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
+	0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 0x2e, 0x4a, 0x08, 0x0e, 0x0f,
+	0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
+};
+
 static int hx8357_spi_write_then_read(struct lcd_device *lcdev,
 				u8 *txbuf, u16 txlen,
 				u8 *rxbuf, u16 rxlen)
@@ -219,6 +287,10 @@ static int hx8357_enter_standby(struct lcd_device *lcdev)
 	if (ret < 0)
 		return ret;
 
+	/*
+	 * The controller needs 120ms when entering in sleep mode before we can
+	 * send the command to go off sleep mode
+	 */
 	msleep(120);
 
 	return 0;
@@ -232,6 +304,10 @@ static int hx8357_exit_standby(struct lcd_device *lcdev)
 	if (ret < 0)
 		return ret;
 
+	/*
+	 * The controller needs 120ms when exiting from sleep mode before we
+	 * can send the command to enter in sleep mode
+	 */
 	msleep(120);
 
 	ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
@@ -241,18 +317,9 @@ static int hx8357_exit_standby(struct lcd_device *lcdev)
 	return 0;
 }
 
-static int hx8357_lcd_init(struct lcd_device *lcdev)
+static void hx8357_lcd_reset(struct lcd_device *lcdev)
 {
 	struct hx8357_data *lcd = lcd_get_data(lcdev);
-	int ret;
-
-	/*
-	 * Set the interface selection pins to SPI mode, with three
-	 * wires
-	 */
-	gpio_set_value_cansleep(lcd->im_pins[0], 1);
-	gpio_set_value_cansleep(lcd->im_pins[1], 0);
-	gpio_set_value_cansleep(lcd->im_pins[2], 1);
 
 	/* Reset the screen */
 	gpio_set_value(lcd->reset, 1);
@@ -260,7 +327,25 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
 	gpio_set_value(lcd->reset, 0);
 	usleep_range(10000, 12000);
 	gpio_set_value(lcd->reset, 1);
+
+	/* The controller needs 120ms to recover from reset */
 	msleep(120);
+}
+
+static int hx8357_lcd_init(struct lcd_device *lcdev)
+{
+	struct hx8357_data *lcd = lcd_get_data(lcdev);
+	int ret;
+
+	/*
+	 * Set the interface selection pins to SPI mode, with three
+	 * wires
+	 */
+	if (lcd->use_im_pins) {
+		gpio_set_value_cansleep(lcd->im_pins[0], 1);
+		gpio_set_value_cansleep(lcd->im_pins[1], 0);
+		gpio_set_value_cansleep(lcd->im_pins[2], 1);
+	}
 
 	ret = hx8357_spi_write_array(lcdev, hx8357_seq_power,
 				ARRAY_SIZE(hx8357_seq_power));
@@ -341,6 +426,9 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
 	if (ret < 0)
 		return ret;
 
+	/*
+	 * The controller needs 120ms to fully recover from exiting sleep mode
+	 */
 	msleep(120);
 
 	ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
@@ -356,6 +444,96 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
 	return 0;
 }
 
+static int hx8369_lcd_init(struct lcd_device *lcdev)
+{
+	int ret;
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_extension_command,
+				ARRAY_SIZE(hx8369_seq_extension_command));
+	if (ret < 0)
+		return ret;
+	usleep_range(10000, 12000);
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_display_related,
+				ARRAY_SIZE(hx8369_seq_display_related));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_panel_waveform_cycle,
+				ARRAY_SIZE(hx8369_seq_panel_waveform_cycle));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_address_mode,
+				ARRAY_SIZE(hx8369_seq_set_address_mode));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_vcom,
+				ARRAY_SIZE(hx8369_seq_vcom));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_gip,
+				ARRAY_SIZE(hx8369_seq_gip));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_power,
+				ARRAY_SIZE(hx8369_seq_power));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * The controller needs 120ms to fully recover from exiting sleep mode
+	 */
+	msleep(120);
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_gamma_curve_related,
+				ARRAY_SIZE(hx8369_seq_gamma_curve_related));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
+	if (ret < 0)
+		return ret;
+	usleep_range(1000, 1200);
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_write_CABC_control,
+				ARRAY_SIZE(hx8369_seq_write_CABC_control));
+	if (ret < 0)
+		return ret;
+	usleep_range(10000, 12000);
+
+	ret = hx8357_spi_write_array(lcdev,
+			hx8369_seq_write_CABC_control_setting,
+			ARRAY_SIZE(hx8369_seq_write_CABC_control_setting));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_array(lcdev,
+			hx8369_seq_write_CABC_min_brightness,
+			ARRAY_SIZE(hx8369_seq_write_CABC_min_brightness));
+	if (ret < 0)
+		return ret;
+	usleep_range(10000, 12000);
+
+	ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_display_brightness,
+				ARRAY_SIZE(hx8369_seq_set_display_brightness));
+	if (ret < 0)
+		return ret;
+
+	ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 #define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)
 
 static int hx8357_set_power(struct lcd_device *lcdev, int power)
@@ -388,10 +566,24 @@ static struct lcd_ops hx8357_ops = {
 	.get_power	= hx8357_get_power,
 };
 
+static const struct of_device_id hx8357_dt_ids[] = {
+	{
+		.compatible = "himax,hx8357",
+		.data = hx8357_lcd_init,
+	},
+	{
+		.compatible = "himax,hx8369",
+		.data = hx8369_lcd_init,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
+
 static int hx8357_probe(struct spi_device *spi)
 {
 	struct lcd_device *lcdev;
 	struct hx8357_data *lcd;
+	const struct of_device_id *match;
 	int i, ret;
 
 	lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
@@ -408,6 +600,10 @@ static int hx8357_probe(struct spi_device *spi)
 
 	lcd->spi = spi;
 
+	match = of_match_device(hx8357_dt_ids, &spi->dev);
+	if (!match || !match->data)
+		return -EINVAL;
+
 	lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
 	if (!gpio_is_valid(lcd->reset)) {
 		dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
@@ -424,25 +620,32 @@ static int hx8357_probe(struct spi_device *spi)
 		return -EINVAL;
 	}
 
-	for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
-		lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
-						"im-gpios", i);
-		if (lcd->im_pins[i] == -EPROBE_DEFER) {
-			dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
-			return -EPROBE_DEFER;
-		}
-		if (!gpio_is_valid(lcd->im_pins[i])) {
-			dev_err(&spi->dev, "Missing dt property: im-gpios\n");
-			return -EINVAL;
-		}
-
-		ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
-					GPIOF_OUT_INIT_LOW, "im_pins");
-		if (ret) {
-			dev_err(&spi->dev, "failed to request gpio %d: %d\n",
-				lcd->im_pins[i], ret);
-			return -EINVAL;
+	if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) {
+		lcd->use_im_pins = 1;
+
+		for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
+			lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
+							    "im-gpios", i);
+			if (lcd->im_pins[i] == -EPROBE_DEFER) {
+				dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
+				return -EPROBE_DEFER;
+			}
+			if (!gpio_is_valid(lcd->im_pins[i])) {
+				dev_err(&spi->dev, "Missing dt property: im-gpios\n");
+				return -EINVAL;
+			}
+
+			ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
+						    GPIOF_OUT_INIT_LOW,
+						    "im_pins");
+			if (ret) {
+				dev_err(&spi->dev, "failed to request gpio %d: %d\n",
+					lcd->im_pins[i], ret);
+				return -EINVAL;
+			}
 		}
+	} else {
+		lcd->use_im_pins = 0;
 	}
 
 	lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops);
@@ -452,7 +655,9 @@ static int hx8357_probe(struct spi_device *spi)
 	}
 	spi_set_drvdata(spi, lcdev);
 
-	ret = hx8357_lcd_init(lcdev);
+	hx8357_lcd_reset(lcdev);
+
+	ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
 	if (ret) {
 		dev_err(&spi->dev, "Couldn't initialize panel\n");
 		goto init_error;
@@ -475,12 +680,6 @@ static int hx8357_remove(struct spi_device *spi)
 	return 0;
 }
 
-static const struct of_device_id hx8357_dt_ids[] = {
-	{ .compatible = "himax,hx8357" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
-
 static struct spi_driver hx8357_driver = {
 	.probe  = hx8357_probe,
 	.remove = hx8357_remove,
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 41964a7..93cf15e 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -89,7 +89,7 @@ static inline void lcd_unregister_fb(struct lcd_device *ld)
 }
 #endif /* CONFIG_FB */
 
-static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
+static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
 	int rc;
@@ -105,7 +105,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
 	return rc;
 }
 
-static ssize_t lcd_store_power(struct device *dev,
+static ssize_t lcd_power_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc;
@@ -128,8 +128,9 @@ static ssize_t lcd_store_power(struct device *dev,
 
 	return rc;
 }
+static DEVICE_ATTR_RW(lcd_power);
 
-static ssize_t lcd_show_contrast(struct device *dev,
+static ssize_t contrast_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	int rc = -ENXIO;
@@ -143,7 +144,7 @@ static ssize_t lcd_show_contrast(struct device *dev,
 	return rc;
 }
 
-static ssize_t lcd_store_contrast(struct device *dev,
+static ssize_t contrast_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc;
@@ -166,14 +167,16 @@ static ssize_t lcd_store_contrast(struct device *dev,
 
 	return rc;
 }
+static DEVICE_ATTR_RW(contrast);
 
-static ssize_t lcd_show_max_contrast(struct device *dev,
+static ssize_t max_contrast_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lcd_device *ld = to_lcd_device(dev);
 
 	return sprintf(buf, "%d\n", ld->props.max_contrast);
 }
+static DEVICE_ATTR_RO(max_contrast);
 
 static struct class *lcd_class;
 
@@ -183,12 +186,13 @@ static void lcd_device_release(struct device *dev)
 	kfree(ld);
 }
 
-static struct device_attribute lcd_device_attributes[] = {
-	__ATTR(lcd_power, 0644, lcd_show_power, lcd_store_power),
-	__ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast),
-	__ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL),
-	__ATTR_NULL,
+static struct attribute *lcd_device_attrs[] = {
+	&dev_attr_lcd_power.attr,
+	&dev_attr_contrast.attr,
+	&dev_attr_max_contrast.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(lcd_device);
 
 /**
  * lcd_device_register - register a new object of lcd_device class.
@@ -344,7 +348,7 @@ static int __init lcd_class_init(void)
 		return PTR_ERR(lcd_class);
 	}
 
-	lcd_class->dev_attrs = lcd_device_attributes;
+	lcd_class->dev_groups = lcd_device_groups;
 	return 0;
 }
 
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index a0e1e02..c0b41f1 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -246,7 +246,7 @@ static int lp855x_bl_update_status(struct backlight_device *bl)
 {
 	struct lp855x *lp = bl_get_data(bl);
 
-	if (bl->props.state & BL_CORE_SUSPENDED)
+	if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
 		bl->props.brightness = 0;
 
 	if (lp->mode == PWM_BASED) {
diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c
new file mode 100644
index 0000000..498fd73
--- /dev/null
+++ b/drivers/video/backlight/lv5207lp.c
@@ -0,0 +1,171 @@
+/*
+ * Sanyo LV5207LP LED Driver
+ *
+ * Copyright (C) 2013 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/platform_data/lv5207lp.h>
+#include <linux/slab.h>
+
+#define LV5207LP_CTRL1			0x00
+#define LV5207LP_CPSW			(1 << 7)
+#define LV5207LP_SCTEN			(1 << 6)
+#define LV5207LP_C10			(1 << 5)
+#define LV5207LP_CKSW			(1 << 4)
+#define LV5207LP_RSW			(1 << 3)
+#define LV5207LP_GSW			(1 << 2)
+#define LV5207LP_BSW			(1 << 1)
+#define LV5207LP_CTRL2			0x01
+#define LV5207LP_MSW			(1 << 7)
+#define LV5207LP_MLED4			(1 << 6)
+#define LV5207LP_RED			0x02
+#define LV5207LP_GREEN			0x03
+#define LV5207LP_BLUE			0x04
+
+#define LV5207LP_MAX_BRIGHTNESS		32
+
+struct lv5207lp {
+	struct i2c_client *client;
+	struct backlight_device *backlight;
+	struct lv5207lp_platform_data *pdata;
+};
+
+static int lv5207lp_write(struct lv5207lp *lv, u8 reg, u8 data)
+{
+	return i2c_smbus_write_byte_data(lv->client, reg, data);
+}
+
+static int lv5207lp_backlight_update_status(struct backlight_device *backlight)
+{
+	struct lv5207lp *lv = bl_get_data(backlight);
+	int brightness = backlight->props.brightness;
+
+	if (backlight->props.power != FB_BLANK_UNBLANK ||
+	    backlight->props.fb_blank != FB_BLANK_UNBLANK ||
+	    backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	if (brightness) {
+		lv5207lp_write(lv, LV5207LP_CTRL1,
+			       LV5207LP_CPSW | LV5207LP_C10 | LV5207LP_CKSW);
+		lv5207lp_write(lv, LV5207LP_CTRL2,
+			       LV5207LP_MSW | LV5207LP_MLED4 |
+			       (brightness - 1));
+	} else {
+		lv5207lp_write(lv, LV5207LP_CTRL1, 0);
+		lv5207lp_write(lv, LV5207LP_CTRL2, 0);
+	}
+
+	return 0;
+}
+
+static int lv5207lp_backlight_get_brightness(struct backlight_device *backlight)
+{
+	return backlight->props.brightness;
+}
+
+static int lv5207lp_backlight_check_fb(struct backlight_device *backlight,
+				       struct fb_info *info)
+{
+	struct lv5207lp *lv = bl_get_data(backlight);
+
+	return lv->pdata->fbdev == NULL || lv->pdata->fbdev == info->dev;
+}
+
+static const struct backlight_ops lv5207lp_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= lv5207lp_backlight_update_status,
+	.get_brightness	= lv5207lp_backlight_get_brightness,
+	.check_fb	= lv5207lp_backlight_check_fb,
+};
+
+static int lv5207lp_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct lv5207lp_platform_data *pdata = client->dev.platform_data;
+	struct backlight_device *backlight;
+	struct backlight_properties props;
+	struct lv5207lp *lv;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data supplied\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_warn(&client->dev,
+			 "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
+		return -EIO;
+	}
+
+	lv = devm_kzalloc(&client->dev, sizeof(*lv), GFP_KERNEL);
+	if (!lv)
+		return -ENOMEM;
+
+	lv->client = client;
+	lv->pdata = pdata;
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = min_t(unsigned int, pdata->max_value,
+				     LV5207LP_MAX_BRIGHTNESS);
+	props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
+				   props.max_brightness);
+
+	backlight = backlight_device_register(dev_name(&client->dev),
+					      &lv->client->dev, lv,
+					      &lv5207lp_backlight_ops, &props);
+	if (IS_ERR(backlight)) {
+		dev_err(&client->dev, "failed to register backlight\n");
+		return PTR_ERR(backlight);
+	}
+
+	backlight_update_status(backlight);
+	i2c_set_clientdata(client, backlight);
+
+	return 0;
+}
+
+static int lv5207lp_remove(struct i2c_client *client)
+{
+	struct backlight_device *backlight = i2c_get_clientdata(client);
+
+	backlight->props.brightness = 0;
+	backlight_update_status(backlight);
+	backlight_device_unregister(backlight);
+
+	return 0;
+}
+
+static const struct i2c_device_id lv5207lp_ids[] = {
+	{ "lv5207lp", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lv5207lp_ids);
+
+static struct i2c_driver lv5207lp_driver = {
+	.driver = {
+		.name = "lv5207lp",
+	},
+	.probe = lv5207lp_probe,
+	.remove = lv5207lp_remove,
+	.id_table = lv5207lp_ids,
+};
+
+module_i2c_driver(lv5207lp_driver);
+
+MODULE_DESCRIPTION("Sanyo LV5207LP Backlight Driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 5788678..e78d9f2 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -518,6 +518,9 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
 	cyber2000_grphw(0xb9, 0x00, cfb);
 	spin_unlock(&cfb->reg_b0_lock);
 
+	/* wait (for the PLL?) to avoid palette corruption at higher clocks */
+	msleep(1000);
+
 	cfb->ramdac_ctrl = hw->ramdac;
 	cyber2000fb_write_ramdac_ctrl(cfb);
 
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 4017833..635d569 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/bug.h>
 #include <linux/errno.h>
 #include <linux/export.h>
 #include <linux/hdmi.h>
@@ -52,7 +53,7 @@ int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
 
 	frame->type = HDMI_INFOFRAME_TYPE_AVI;
 	frame->version = 2;
-	frame->length = 13;
+	frame->length = HDMI_AVI_INFOFRAME_SIZE;
 
 	return 0;
 }
@@ -83,7 +84,7 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
 	if (size < length)
 		return -ENOSPC;
 
-	memset(buffer, 0, length);
+	memset(buffer, 0, size);
 
 	ptr[0] = frame->type;
 	ptr[1] = frame->version;
@@ -151,7 +152,7 @@ int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
 
 	frame->type = HDMI_INFOFRAME_TYPE_SPD;
 	frame->version = 1;
-	frame->length = 25;
+	frame->length = HDMI_SPD_INFOFRAME_SIZE;
 
 	strncpy(frame->vendor, vendor, sizeof(frame->vendor));
 	strncpy(frame->product, product, sizeof(frame->product));
@@ -185,7 +186,7 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
 	if (size < length)
 		return -ENOSPC;
 
-	memset(buffer, 0, length);
+	memset(buffer, 0, size);
 
 	ptr[0] = frame->type;
 	ptr[1] = frame->version;
@@ -218,7 +219,7 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
 
 	frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
 	frame->version = 1;
-	frame->length = 10;
+	frame->length = HDMI_AUDIO_INFOFRAME_SIZE;
 
 	return 0;
 }
@@ -250,7 +251,7 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
 	if (size < length)
 		return -ENOSPC;
 
-	memset(buffer, 0, length);
+	memset(buffer, 0, size);
 
 	if (frame->channels >= 2)
 		channels = frame->channels - 1;
@@ -307,7 +308,7 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
 	if (size < length)
 		return -ENOSPC;
 
-	memset(buffer, 0, length);
+	memset(buffer, 0, size);
 
 	ptr[0] = frame->type;
 	ptr[1] = frame->version;
@@ -321,3 +322,45 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
 	return length;
 }
 EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
+
+/**
+ * hdmi_infoframe_pack() - write a HDMI infoframe to binary buffer
+ * @frame: HDMI infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers. Also computes the checksum as required by section 5.3.5 of
+ * the HDMI 1.4 specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t
+hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size)
+{
+	ssize_t length;
+
+	switch (frame->any.type) {
+	case HDMI_INFOFRAME_TYPE_AVI:
+		length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);
+		break;
+	case HDMI_INFOFRAME_TYPE_SPD:
+		length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
+		break;
+	case HDMI_INFOFRAME_TYPE_AUDIO:
+		length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);
+		break;
+	case HDMI_INFOFRAME_TYPE_VENDOR:
+		length = hdmi_vendor_infoframe_pack(&frame->vendor,
+						    buffer, size);
+		break;
+	default:
+		WARN(1, "Bad infoframe type %d\n", frame->any.type);
+		length = -EINVAL;
+	}
+
+	return length;
+}
+EXPORT_SYMBOL(hdmi_infoframe_pack);
diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c
index d4d2c5f..8ac99b8 100644
--- a/drivers/video/hyperv_fb.c
+++ b/drivers/video/hyperv_fb.c
@@ -825,5 +825,4 @@ module_init(hvfb_drv_init);
 module_exit(hvfb_drv_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 401a56e..2456529 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -2029,10 +2029,9 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
 		return -1;
 	}
 
-	minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
+	minfo = kzalloc(sizeof(*minfo), GFP_KERNEL);
 	if (!minfo)
 		return -1;
-	memset(minfo, 0, sizeof(*minfo));
 
 	minfo->pcidev = pdev;
 	minfo->dead = 0;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index ec08a9e..1374803 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/platform_data/video-msm_fb.h>
-#include <mach/board.h>
 #include <linux/workqueue.h>
 #include <linux/clk.h>
 #include <linux/debugfs.h>
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 3ba3771..5861ba2 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -46,7 +46,6 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/fb.h>
 #include <linux/regulator/consumer.h>
 #include <video/of_display_timing.h>
@@ -877,7 +876,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 	struct mxsfb_info *host;
 	struct fb_info *fb_info;
 	struct fb_modelist *modelist;
-	struct pinctrl *pinctrl;
 	int ret;
 
 	if (of_id)
@@ -908,12 +906,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 
 	host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto fb_release;
-	}
-
 	host->clk = devm_clk_get(&host->pdev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 1aeb274..a7ce26c 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -189,7 +189,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 	d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
 			write, &dss_debug_fops);
 
-	return PTR_RET(d);
+	return PTR_ERR_OR_ZERO(d);
 }
 #else /* CONFIG_OMAP2_DSS_DEBUGFS */
 static inline int dss_initialize_debugfs(void)
diff --git a/drivers/video/output.c b/drivers/video/output.c
index 6285b97..1446c49 100644
--- a/drivers/video/output.c
+++ b/drivers/video/output.c
@@ -32,8 +32,8 @@ MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>");
 
-static ssize_t video_output_show_state(struct device *dev,
-				       struct device_attribute *attr, char *buf)
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	ssize_t ret_size = 0;
 	struct output_device *od = to_output_device(dev);
@@ -42,9 +42,8 @@ static ssize_t video_output_show_state(struct device *dev,
 	return ret_size;
 }
 
-static ssize_t video_output_store_state(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf,size_t count)
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf,size_t count)
 {
 	char *endp;
 	struct output_device *od = to_output_device(dev);
@@ -62,6 +61,7 @@ static ssize_t video_output_store_state(struct device *dev,
 	}
 	return count;
 }
+static DEVICE_ATTR_RW(state);
 
 static void video_output_release(struct device *dev)
 {
@@ -69,16 +69,16 @@ static void video_output_release(struct device *dev)
 	kfree(od);
 }
 
-static struct device_attribute video_output_attributes[] = {
-	__ATTR(state, 0644, video_output_show_state, video_output_store_state),
-	__ATTR_NULL,
+static struct attribute *video_output_attrs[] = {
+	&dev_attr_state.attr,
+	NULL,
 };
-
+ATTRIBUTE_GROUPS(video_output);
 
 static struct class video_output_class = {
 	.name = "video_output",
 	.dev_release = video_output_release,
-	.dev_attrs = video_output_attributes,
+	.dev_groups = video_output_groups,
 };
 
 struct output_device *video_output_register(const char *name,
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
index e2e9e3e..f015482 100644
--- a/drivers/video/simplefb.c
+++ b/drivers/video/simplefb.c
@@ -84,6 +84,7 @@ struct simplefb_format {
 
 static struct simplefb_format simplefb_formats[] = {
 	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} },
+	{ "a8b8g8r8", 32, {0, 8}, {8, 8}, {16, 8}, {24, 8} },
 };
 
 struct simplefb_params {
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 0459df8..46a8fd7 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -235,9 +235,11 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
 {
 	long tmp;
 	struct w1_master *md = dev_to_w1_master(dev);
+	int ret;
 
-	if (strict_strtol(buf, 0, &tmp) == -EINVAL)
-		return -EINVAL;
+	ret = kstrtol(buf, 0, &tmp);
+	if (ret)
+		return ret;
 
 	mutex_lock(&md->mutex);
 	md->search_count = tmp;
@@ -267,9 +269,11 @@ static ssize_t w1_master_attribute_store_pullup(struct device *dev,
 {
 	long tmp;
 	struct w1_master *md = dev_to_w1_master(dev);
+	int ret;
 
-	if (strict_strtol(buf, 0, &tmp) == -EINVAL)
-		return -EINVAL;
+	ret = kstrtol(buf, 0, &tmp);
+	if (ret)
+		return ret;
 
 	mutex_lock(&md->mutex);
 	md->enable_pullup = tmp;
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index de7e4f4..5be5e3d 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -162,7 +162,8 @@ extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
 #define HPWDT_ARCH	32
 
 asm(".text                          \n\t"
-    ".align 4                       \n"
+    ".align 4                       \n\t"
+    ".globl asminline_call	    \n"
     "asminline_call:                \n\t"
     "pushl       %ebp               \n\t"
     "movl        %esp, %ebp         \n\t"
@@ -352,7 +353,8 @@ static int detect_cru_service(void)
 #define HPWDT_ARCH	64
 
 asm(".text                      \n\t"
-    ".align 4                   \n"
+    ".align 4                   \n\t"
+    ".globl asminline_call	\n"
     "asminline_call:            \n\t"
     "pushq      %rbp            \n\t"
     "movq       %rsp, %rbp      \n\t"
diff --git a/drivers/xen/acpi.c b/drivers/xen/acpi.c
index 119d42a..90307c0 100644
--- a/drivers/xen/acpi.c
+++ b/drivers/xen/acpi.c
@@ -35,28 +35,43 @@
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
 
-int xen_acpi_notify_hypervisor_state(u8 sleep_state,
-				     u32 pm1a_cnt, u32 pm1b_cnt)
+static int xen_acpi_notify_hypervisor_state(u8 sleep_state,
+					    u32 val_a, u32 val_b,
+					    bool extended)
 {
+	unsigned int bits = extended ? 8 : 16;
+
 	struct xen_platform_op op = {
 		.cmd = XENPF_enter_acpi_sleep,
 		.interface_version = XENPF_INTERFACE_VERSION,
-		.u = {
-			.enter_acpi_sleep = {
-				.pm1a_cnt_val = (u16)pm1a_cnt,
-				.pm1b_cnt_val = (u16)pm1b_cnt,
-				.sleep_state = sleep_state,
-			},
+		.u.enter_acpi_sleep = {
+			.val_a = (u16)val_a,
+			.val_b = (u16)val_b,
+			.sleep_state = sleep_state,
+			.flags = extended ? XENPF_ACPI_SLEEP_EXTENDED : 0,
 		},
 	};
 
-	if ((pm1a_cnt & 0xffff0000) || (pm1b_cnt & 0xffff0000)) {
-		WARN(1, "Using more than 16bits of PM1A/B 0x%x/0x%x!"
-		     "Email xen-devel@lists.xensource.com  Thank you.\n", \
-		     pm1a_cnt, pm1b_cnt);
+	if (WARN((val_a & (~0 << bits)) || (val_b & (~0 << bits)),
+		 "Using more than %u bits of sleep control values %#x/%#x!"
+		 "Email xen-devel@lists.xen.org - Thank you.\n", \
+		 bits, val_a, val_b))
 		return -1;
-	}
 
 	HYPERVISOR_dom0_op(&op);
 	return 1;
 }
+
+int xen_acpi_notify_hypervisor_sleep(u8 sleep_state,
+				     u32 pm1a_cnt, u32 pm1b_cnt)
+{
+	return xen_acpi_notify_hypervisor_state(sleep_state, pm1a_cnt,
+						pm1b_cnt, false);
+}
+
+int xen_acpi_notify_hypervisor_extended_sleep(u8 sleep_state,
+				     u32 val_a, u32 val_b)
+{
+	return xen_acpi_notify_hypervisor_state(sleep_state, val_a,
+						val_b, true);
+}
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 25b018e..94de6d1 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -146,7 +146,7 @@ static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses,
 		char type = 0, ext[32];
 		int major = -1, minor = -1;
 
-		strncpy(ext, stat->extension, sizeof(ext));
+		strlcpy(ext, stat->extension, sizeof(ext));
 		sscanf(ext, "%c %u %u", &type, &major, &minor);
 		switch (type) {
 		case 'c':
@@ -1186,7 +1186,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
 			 * this even with .u extension. So check
 			 * for non NULL stat->extension
 			 */
-			strncpy(ext, stat->extension, sizeof(ext));
+			strlcpy(ext, stat->extension, sizeof(ext));
 			/* HARDLINKCOUNT %u */
 			sscanf(ext, "%13s %u", tag_name, &i_nlink);
 			if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
diff --git a/fs/aio.c b/fs/aio.c
index 9b5ca11..c3f005d 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -26,6 +26,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/mmu_context.h>
+#include <linux/percpu.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/aio.h>
@@ -35,6 +36,10 @@
 #include <linux/eventfd.h>
 #include <linux/blkdev.h>
 #include <linux/compat.h>
+#include <linux/anon_inodes.h>
+#include <linux/migrate.h>
+#include <linux/ramfs.h>
+#include <linux/percpu-refcount.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
@@ -61,14 +66,29 @@ struct aio_ring {
 
 #define AIO_RING_PAGES	8
 
+struct kioctx_table {
+	struct rcu_head	rcu;
+	unsigned	nr;
+	struct kioctx	*table[];
+};
+
+struct kioctx_cpu {
+	unsigned		reqs_available;
+};
+
 struct kioctx {
-	atomic_t		users;
+	struct percpu_ref	users;
 	atomic_t		dead;
 
-	/* This needs improving */
 	unsigned long		user_id;
-	struct hlist_node	list;
 
+	struct __percpu kioctx_cpu *cpu;
+
+	/*
+	 * For percpu reqs_available, number of slots we move to/from global
+	 * counter at a time:
+	 */
+	unsigned		req_batch;
 	/*
 	 * This is what userspace passed to io_setup(), it's not used for
 	 * anything but counting against the global max_reqs quota.
@@ -88,10 +108,18 @@ struct kioctx {
 	long			nr_pages;
 
 	struct rcu_head		rcu_head;
-	struct work_struct	rcu_work;
+	struct work_struct	free_work;
 
 	struct {
-		atomic_t	reqs_active;
+		/*
+		 * This counts the number of available slots in the ringbuffer,
+		 * so we avoid overflowing it: it's decremented (if positive)
+		 * when allocating a kiocb and incremented when the resulting
+		 * io_event is pulled off the ringbuffer.
+		 *
+		 * We batch accesses to it with a percpu version.
+		 */
+		atomic_t	reqs_available;
 	} ____cacheline_aligned_in_smp;
 
 	struct {
@@ -110,6 +138,9 @@ struct kioctx {
 	} ____cacheline_aligned_in_smp;
 
 	struct page		*internal_pages[AIO_RING_PAGES];
+	struct file		*aio_ring_file;
+
+	unsigned		id;
 };
 
 /*------ sysctl variables----*/
@@ -138,15 +169,82 @@ __initcall(aio_setup);
 
 static void aio_free_ring(struct kioctx *ctx)
 {
-	long i;
+	int i;
+	struct file *aio_ring_file = ctx->aio_ring_file;
 
-	for (i = 0; i < ctx->nr_pages; i++)
+	for (i = 0; i < ctx->nr_pages; i++) {
+		pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
+				page_count(ctx->ring_pages[i]));
 		put_page(ctx->ring_pages[i]);
+	}
 
 	if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages)
 		kfree(ctx->ring_pages);
+
+	if (aio_ring_file) {
+		truncate_setsize(aio_ring_file->f_inode, 0);
+		pr_debug("pid(%d) i_nlink=%u d_count=%d d_unhashed=%d i_count=%d\n",
+			current->pid, aio_ring_file->f_inode->i_nlink,
+			aio_ring_file->f_path.dentry->d_count,
+			d_unhashed(aio_ring_file->f_path.dentry),
+			atomic_read(&aio_ring_file->f_inode->i_count));
+		fput(aio_ring_file);
+		ctx->aio_ring_file = NULL;
+	}
+}
+
+static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	vma->vm_ops = &generic_file_vm_ops;
+	return 0;
+}
+
+static const struct file_operations aio_ring_fops = {
+	.mmap = aio_ring_mmap,
+};
+
+static int aio_set_page_dirty(struct page *page)
+{
+	return 0;
 }
 
+#if IS_ENABLED(CONFIG_MIGRATION)
+static int aio_migratepage(struct address_space *mapping, struct page *new,
+			struct page *old, enum migrate_mode mode)
+{
+	struct kioctx *ctx = mapping->private_data;
+	unsigned long flags;
+	unsigned idx = old->index;
+	int rc;
+
+	/* Writeback must be complete */
+	BUG_ON(PageWriteback(old));
+	put_page(old);
+
+	rc = migrate_page_move_mapping(mapping, new, old, NULL, mode);
+	if (rc != MIGRATEPAGE_SUCCESS) {
+		get_page(old);
+		return rc;
+	}
+
+	get_page(new);
+
+	spin_lock_irqsave(&ctx->completion_lock, flags);
+	migrate_page_copy(new, old);
+	ctx->ring_pages[idx] = new;
+	spin_unlock_irqrestore(&ctx->completion_lock, flags);
+
+	return rc;
+}
+#endif
+
+static const struct address_space_operations aio_ctx_aops = {
+	.set_page_dirty = aio_set_page_dirty,
+#if IS_ENABLED(CONFIG_MIGRATION)
+	.migratepage	= aio_migratepage,
+#endif
+};
+
 static int aio_setup_ring(struct kioctx *ctx)
 {
 	struct aio_ring *ring;
@@ -154,20 +252,45 @@ static int aio_setup_ring(struct kioctx *ctx)
 	struct mm_struct *mm = current->mm;
 	unsigned long size, populate;
 	int nr_pages;
+	int i;
+	struct file *file;
 
 	/* Compensate for the ring buffer's head/tail overlap entry */
 	nr_events += 2;	/* 1 is required, 2 for good luck */
 
 	size = sizeof(struct aio_ring);
 	size += sizeof(struct io_event) * nr_events;
-	nr_pages = (size + PAGE_SIZE-1) >> PAGE_SHIFT;
 
+	nr_pages = PFN_UP(size);
 	if (nr_pages < 0)
 		return -EINVAL;
 
-	nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) / sizeof(struct io_event);
+	file = anon_inode_getfile_private("[aio]", &aio_ring_fops, ctx, O_RDWR);
+	if (IS_ERR(file)) {
+		ctx->aio_ring_file = NULL;
+		return -EAGAIN;
+	}
+
+	file->f_inode->i_mapping->a_ops = &aio_ctx_aops;
+	file->f_inode->i_mapping->private_data = ctx;
+	file->f_inode->i_size = PAGE_SIZE * (loff_t)nr_pages;
+
+	for (i = 0; i < nr_pages; i++) {
+		struct page *page;
+		page = find_or_create_page(file->f_inode->i_mapping,
+					   i, GFP_HIGHUSER | __GFP_ZERO);
+		if (!page)
+			break;
+		pr_debug("pid(%d) page[%d]->count=%d\n",
+			 current->pid, i, page_count(page));
+		SetPageUptodate(page);
+		SetPageDirty(page);
+		unlock_page(page);
+	}
+	ctx->aio_ring_file = file;
+	nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
+			/ sizeof(struct io_event);
 
-	ctx->nr_events = 0;
 	ctx->ring_pages = ctx->internal_pages;
 	if (nr_pages > AIO_RING_PAGES) {
 		ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
@@ -178,35 +301,38 @@ static int aio_setup_ring(struct kioctx *ctx)
 
 	ctx->mmap_size = nr_pages * PAGE_SIZE;
 	pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);
+
 	down_write(&mm->mmap_sem);
-	ctx->mmap_base = do_mmap_pgoff(NULL, 0, ctx->mmap_size,
-				       PROT_READ|PROT_WRITE,
-				       MAP_ANONYMOUS|MAP_PRIVATE, 0, &populate);
+	ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
+				       PROT_READ | PROT_WRITE,
+				       MAP_SHARED | MAP_POPULATE, 0, &populate);
 	if (IS_ERR((void *)ctx->mmap_base)) {
 		up_write(&mm->mmap_sem);
 		ctx->mmap_size = 0;
 		aio_free_ring(ctx);
 		return -EAGAIN;
 	}
+	up_write(&mm->mmap_sem);
+
+	mm_populate(ctx->mmap_base, populate);
 
 	pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
 	ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages,
 				       1, 0, ctx->ring_pages, NULL);
-	up_write(&mm->mmap_sem);
+	for (i = 0; i < ctx->nr_pages; i++)
+		put_page(ctx->ring_pages[i]);
 
 	if (unlikely(ctx->nr_pages != nr_pages)) {
 		aio_free_ring(ctx);
 		return -EAGAIN;
 	}
-	if (populate)
-		mm_populate(ctx->mmap_base, populate);
 
 	ctx->user_id = ctx->mmap_base;
 	ctx->nr_events = nr_events; /* trusted copy */
 
 	ring = kmap_atomic(ctx->ring_pages[0]);
 	ring->nr = nr_events;	/* user copy */
-	ring->id = ctx->user_id;
+	ring->id = ~0U;
 	ring->head = ring->tail = 0;
 	ring->magic = AIO_RING_MAGIC;
 	ring->compat_features = AIO_RING_COMPAT_FEATURES;
@@ -238,11 +364,9 @@ void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
 }
 EXPORT_SYMBOL(kiocb_set_cancel_fn);
 
-static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb,
-			struct io_event *res)
+static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb)
 {
 	kiocb_cancel_fn *old, *cancel;
-	int ret = -EINVAL;
 
 	/*
 	 * Don't want to set kiocb->ki_cancel = KIOCB_CANCELLED unless it
@@ -252,28 +376,20 @@ static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb,
 	cancel = ACCESS_ONCE(kiocb->ki_cancel);
 	do {
 		if (!cancel || cancel == KIOCB_CANCELLED)
-			return ret;
+			return -EINVAL;
 
 		old = cancel;
 		cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
 	} while (cancel != old);
 
-	atomic_inc(&kiocb->ki_users);
-	spin_unlock_irq(&ctx->ctx_lock);
-
-	memset(res, 0, sizeof(*res));
-	res->obj = (u64)(unsigned long)kiocb->ki_obj.user;
-	res->data = kiocb->ki_user_data;
-	ret = cancel(kiocb, res);
-
-	spin_lock_irq(&ctx->ctx_lock);
-
-	return ret;
+	return cancel(kiocb);
 }
 
 static void free_ioctx_rcu(struct rcu_head *head)
 {
 	struct kioctx *ctx = container_of(head, struct kioctx, rcu_head);
+
+	free_percpu(ctx->cpu);
 	kmem_cache_free(kioctx_cachep, ctx);
 }
 
@@ -282,12 +398,13 @@ static void free_ioctx_rcu(struct rcu_head *head)
  * and ctx->users has dropped to 0, so we know no more kiocbs can be submitted -
  * now it's safe to cancel any that need to be.
  */
-static void free_ioctx(struct kioctx *ctx)
+static void free_ioctx(struct work_struct *work)
 {
+	struct kioctx *ctx = container_of(work, struct kioctx, free_work);
 	struct aio_ring *ring;
-	struct io_event res;
 	struct kiocb *req;
-	unsigned head, avail;
+	unsigned cpu, avail;
+	DEFINE_WAIT(wait);
 
 	spin_lock_irq(&ctx->ctx_lock);
 
@@ -296,28 +413,38 @@ static void free_ioctx(struct kioctx *ctx)
 				       struct kiocb, ki_list);
 
 		list_del_init(&req->ki_list);
-		kiocb_cancel(ctx, req, &res);
+		kiocb_cancel(ctx, req);
 	}
 
 	spin_unlock_irq(&ctx->ctx_lock);
 
-	ring = kmap_atomic(ctx->ring_pages[0]);
-	head = ring->head;
-	kunmap_atomic(ring);
+	for_each_possible_cpu(cpu) {
+		struct kioctx_cpu *kcpu = per_cpu_ptr(ctx->cpu, cpu);
 
-	while (atomic_read(&ctx->reqs_active) > 0) {
-		wait_event(ctx->wait,
-				head != ctx->tail ||
-				atomic_read(&ctx->reqs_active) <= 0);
+		atomic_add(kcpu->reqs_available, &ctx->reqs_available);
+		kcpu->reqs_available = 0;
+	}
 
-		avail = (head <= ctx->tail ? ctx->tail : ctx->nr_events) - head;
+	while (1) {
+		prepare_to_wait(&ctx->wait, &wait, TASK_UNINTERRUPTIBLE);
 
-		atomic_sub(avail, &ctx->reqs_active);
-		head += avail;
-		head %= ctx->nr_events;
+		ring = kmap_atomic(ctx->ring_pages[0]);
+		avail = (ring->head <= ring->tail)
+			 ? ring->tail - ring->head
+			 : ctx->nr_events - ring->head + ring->tail;
+
+		atomic_add(avail, &ctx->reqs_available);
+		ring->head = ring->tail;
+		kunmap_atomic(ring);
+
+		if (atomic_read(&ctx->reqs_available) >= ctx->nr_events - 1)
+			break;
+
+		schedule();
 	}
+	finish_wait(&ctx->wait, &wait);
 
-	WARN_ON(atomic_read(&ctx->reqs_active) < 0);
+	WARN_ON(atomic_read(&ctx->reqs_available) > ctx->nr_events - 1);
 
 	aio_free_ring(ctx);
 
@@ -333,10 +460,64 @@ static void free_ioctx(struct kioctx *ctx)
 	call_rcu(&ctx->rcu_head, free_ioctx_rcu);
 }
 
-static void put_ioctx(struct kioctx *ctx)
+static void free_ioctx_ref(struct percpu_ref *ref)
 {
-	if (unlikely(atomic_dec_and_test(&ctx->users)))
-		free_ioctx(ctx);
+	struct kioctx *ctx = container_of(ref, struct kioctx, users);
+
+	INIT_WORK(&ctx->free_work, free_ioctx);
+	schedule_work(&ctx->free_work);
+}
+
+static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
+{
+	unsigned i, new_nr;
+	struct kioctx_table *table, *old;
+	struct aio_ring *ring;
+
+	spin_lock(&mm->ioctx_lock);
+	table = mm->ioctx_table;
+
+	while (1) {
+		if (table)
+			for (i = 0; i < table->nr; i++)
+				if (!table->table[i]) {
+					ctx->id = i;
+					table->table[i] = ctx;
+					spin_unlock(&mm->ioctx_lock);
+
+					ring = kmap_atomic(ctx->ring_pages[0]);
+					ring->id = ctx->id;
+					kunmap_atomic(ring);
+					return 0;
+				}
+
+		new_nr = (table ? table->nr : 1) * 4;
+
+		spin_unlock(&mm->ioctx_lock);
+
+		table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) *
+				new_nr, GFP_KERNEL);
+		if (!table)
+			return -ENOMEM;
+
+		table->nr = new_nr;
+
+		spin_lock(&mm->ioctx_lock);
+		old = mm->ioctx_table;
+
+		if (!old) {
+			rcu_assign_pointer(mm->ioctx_table, table);
+		} else if (table->nr > old->nr) {
+			memcpy(table->table, old->table,
+			       old->nr * sizeof(struct kioctx *));
+
+			rcu_assign_pointer(mm->ioctx_table, table);
+			kfree_rcu(old, rcu);
+		} else {
+			kfree(table);
+			table = old;
+		}
+	}
 }
 
 /* ioctx_alloc
@@ -348,6 +529,18 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 	struct kioctx *ctx;
 	int err = -ENOMEM;
 
+	/*
+	 * We keep track of the number of available ringbuffer slots, to prevent
+	 * overflow (reqs_available), and we also use percpu counters for this.
+	 *
+	 * So since up to half the slots might be on other cpu's percpu counters
+	 * and unavailable, double nr_events so userspace sees what they
+	 * expected: additionally, we move req_batch slots to/from percpu
+	 * counters at a time, so make sure that isn't 0:
+	 */
+	nr_events = max(nr_events, num_possible_cpus() * 4);
+	nr_events *= 2;
+
 	/* Prevent overflows */
 	if ((nr_events > (0x10000000U / sizeof(struct io_event))) ||
 	    (nr_events > (0x10000000U / sizeof(struct kiocb)))) {
@@ -355,7 +548,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (!nr_events || (unsigned long)nr_events > aio_max_nr)
+	if (!nr_events || (unsigned long)nr_events > (aio_max_nr * 2UL))
 		return ERR_PTR(-EAGAIN);
 
 	ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL);
@@ -364,8 +557,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 
 	ctx->max_reqs = nr_events;
 
-	atomic_set(&ctx->users, 2);
-	atomic_set(&ctx->dead, 0);
+	if (percpu_ref_init(&ctx->users, free_ioctx_ref))
+		goto out_freectx;
+
 	spin_lock_init(&ctx->ctx_lock);
 	spin_lock_init(&ctx->completion_lock);
 	mutex_init(&ctx->ring_lock);
@@ -373,12 +567,21 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 
 	INIT_LIST_HEAD(&ctx->active_reqs);
 
+	ctx->cpu = alloc_percpu(struct kioctx_cpu);
+	if (!ctx->cpu)
+		goto out_freeref;
+
 	if (aio_setup_ring(ctx) < 0)
-		goto out_freectx;
+		goto out_freepcpu;
+
+	atomic_set(&ctx->reqs_available, ctx->nr_events - 1);
+	ctx->req_batch = (ctx->nr_events - 1) / (num_possible_cpus() * 4);
+	if (ctx->req_batch < 1)
+		ctx->req_batch = 1;
 
 	/* limit the number of system wide aios */
 	spin_lock(&aio_nr_lock);
-	if (aio_nr + nr_events > aio_max_nr ||
+	if (aio_nr + nr_events > (aio_max_nr * 2UL) ||
 	    aio_nr + nr_events < aio_nr) {
 		spin_unlock(&aio_nr_lock);
 		goto out_cleanup;
@@ -386,49 +589,52 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 	aio_nr += ctx->max_reqs;
 	spin_unlock(&aio_nr_lock);
 
-	/* now link into global list. */
-	spin_lock(&mm->ioctx_lock);
-	hlist_add_head_rcu(&ctx->list, &mm->ioctx_list);
-	spin_unlock(&mm->ioctx_lock);
+	percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
+
+	err = ioctx_add_table(ctx, mm);
+	if (err)
+		goto out_cleanup_put;
 
 	pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
 		 ctx, ctx->user_id, mm, ctx->nr_events);
 	return ctx;
 
+out_cleanup_put:
+	percpu_ref_put(&ctx->users);
 out_cleanup:
 	err = -EAGAIN;
 	aio_free_ring(ctx);
+out_freepcpu:
+	free_percpu(ctx->cpu);
+out_freeref:
+	free_percpu(ctx->users.pcpu_count);
 out_freectx:
+	if (ctx->aio_ring_file)
+		fput(ctx->aio_ring_file);
 	kmem_cache_free(kioctx_cachep, ctx);
 	pr_debug("error allocating ioctx %d\n", err);
 	return ERR_PTR(err);
 }
 
-static void kill_ioctx_work(struct work_struct *work)
-{
-	struct kioctx *ctx = container_of(work, struct kioctx, rcu_work);
-
-	wake_up_all(&ctx->wait);
-	put_ioctx(ctx);
-}
-
-static void kill_ioctx_rcu(struct rcu_head *head)
-{
-	struct kioctx *ctx = container_of(head, struct kioctx, rcu_head);
-
-	INIT_WORK(&ctx->rcu_work, kill_ioctx_work);
-	schedule_work(&ctx->rcu_work);
-}
-
 /* kill_ioctx
  *	Cancels all outstanding aio requests on an aio context.  Used
  *	when the processes owning a context have all exited to encourage
  *	the rapid destruction of the kioctx.
  */
-static void kill_ioctx(struct kioctx *ctx)
+static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
 {
 	if (!atomic_xchg(&ctx->dead, 1)) {
-		hlist_del_rcu(&ctx->list);
+		struct kioctx_table *table;
+
+		spin_lock(&mm->ioctx_lock);
+		table = mm->ioctx_table;
+
+		WARN_ON(ctx != table->table[ctx->id]);
+		table->table[ctx->id] = NULL;
+		spin_unlock(&mm->ioctx_lock);
+
+		/* percpu_ref_kill() will do the necessary call_rcu() */
+		wake_up_all(&ctx->wait);
 
 		/*
 		 * It'd be more correct to do this in free_ioctx(), after all
@@ -445,24 +651,23 @@ static void kill_ioctx(struct kioctx *ctx)
 		if (ctx->mmap_size)
 			vm_munmap(ctx->mmap_base, ctx->mmap_size);
 
-		/* Between hlist_del_rcu() and dropping the initial ref */
-		call_rcu(&ctx->rcu_head, kill_ioctx_rcu);
+		percpu_ref_kill(&ctx->users);
 	}
 }
 
 /* wait_on_sync_kiocb:
  *	Waits on the given sync kiocb to complete.
  */
-ssize_t wait_on_sync_kiocb(struct kiocb *iocb)
+ssize_t wait_on_sync_kiocb(struct kiocb *req)
 {
-	while (atomic_read(&iocb->ki_users)) {
+	while (!req->ki_ctx) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (!atomic_read(&iocb->ki_users))
+		if (req->ki_ctx)
 			break;
 		io_schedule();
 	}
 	__set_current_state(TASK_RUNNING);
-	return iocb->ki_user_data;
+	return req->ki_user_data;
 }
 EXPORT_SYMBOL(wait_on_sync_kiocb);
 
@@ -476,16 +681,28 @@ EXPORT_SYMBOL(wait_on_sync_kiocb);
  */
 void exit_aio(struct mm_struct *mm)
 {
+	struct kioctx_table *table;
 	struct kioctx *ctx;
-	struct hlist_node *n;
-
-	hlist_for_each_entry_safe(ctx, n, &mm->ioctx_list, list) {
-		if (1 != atomic_read(&ctx->users))
-			printk(KERN_DEBUG
-				"exit_aio:ioctx still alive: %d %d %d\n",
-				atomic_read(&ctx->users),
-				atomic_read(&ctx->dead),
-				atomic_read(&ctx->reqs_active));
+	unsigned i = 0;
+
+	while (1) {
+		rcu_read_lock();
+		table = rcu_dereference(mm->ioctx_table);
+
+		do {
+			if (!table || i >= table->nr) {
+				rcu_read_unlock();
+				rcu_assign_pointer(mm->ioctx_table, NULL);
+				if (table)
+					kfree(table);
+				return;
+			}
+
+			ctx = table->table[i++];
+		} while (!ctx);
+
+		rcu_read_unlock();
+
 		/*
 		 * We don't need to bother with munmap() here -
 		 * exit_mmap(mm) is coming and it'll unmap everything.
@@ -496,40 +713,75 @@ void exit_aio(struct mm_struct *mm)
 		 */
 		ctx->mmap_size = 0;
 
-		kill_ioctx(ctx);
+		kill_ioctx(mm, ctx);
+	}
+}
+
+static void put_reqs_available(struct kioctx *ctx, unsigned nr)
+{
+	struct kioctx_cpu *kcpu;
+
+	preempt_disable();
+	kcpu = this_cpu_ptr(ctx->cpu);
+
+	kcpu->reqs_available += nr;
+	while (kcpu->reqs_available >= ctx->req_batch * 2) {
+		kcpu->reqs_available -= ctx->req_batch;
+		atomic_add(ctx->req_batch, &ctx->reqs_available);
 	}
+
+	preempt_enable();
+}
+
+static bool get_reqs_available(struct kioctx *ctx)
+{
+	struct kioctx_cpu *kcpu;
+	bool ret = false;
+
+	preempt_disable();
+	kcpu = this_cpu_ptr(ctx->cpu);
+
+	if (!kcpu->reqs_available) {
+		int old, avail = atomic_read(&ctx->reqs_available);
+
+		do {
+			if (avail < ctx->req_batch)
+				goto out;
+
+			old = avail;
+			avail = atomic_cmpxchg(&ctx->reqs_available,
+					       avail, avail - ctx->req_batch);
+		} while (avail != old);
+
+		kcpu->reqs_available += ctx->req_batch;
+	}
+
+	ret = true;
+	kcpu->reqs_available--;
+out:
+	preempt_enable();
+	return ret;
 }
 
 /* aio_get_req
- *	Allocate a slot for an aio request.  Increments the ki_users count
- * of the kioctx so that the kioctx stays around until all requests are
- * complete.  Returns NULL if no requests are free.
- *
- * Returns with kiocb->ki_users set to 2.  The io submit code path holds
- * an extra reference while submitting the i/o.
- * This prevents races between the aio code path referencing the
- * req (after submitting it) and aio_complete() freeing the req.
+ *	Allocate a slot for an aio request.
+ * Returns NULL if no requests are free.
  */
 static inline struct kiocb *aio_get_req(struct kioctx *ctx)
 {
 	struct kiocb *req;
 
-	if (atomic_read(&ctx->reqs_active) >= ctx->nr_events)
+	if (!get_reqs_available(ctx))
 		return NULL;
 
-	if (atomic_inc_return(&ctx->reqs_active) > ctx->nr_events - 1)
-		goto out_put;
-
 	req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO);
 	if (unlikely(!req))
 		goto out_put;
 
-	atomic_set(&req->ki_users, 2);
 	req->ki_ctx = ctx;
-
 	return req;
 out_put:
-	atomic_dec(&ctx->reqs_active);
+	put_reqs_available(ctx, 1);
 	return NULL;
 }
 
@@ -539,35 +791,32 @@ static void kiocb_free(struct kiocb *req)
 		fput(req->ki_filp);
 	if (req->ki_eventfd != NULL)
 		eventfd_ctx_put(req->ki_eventfd);
-	if (req->ki_dtor)
-		req->ki_dtor(req);
-	if (req->ki_iovec != &req->ki_inline_vec)
-		kfree(req->ki_iovec);
 	kmem_cache_free(kiocb_cachep, req);
 }
 
-void aio_put_req(struct kiocb *req)
-{
-	if (atomic_dec_and_test(&req->ki_users))
-		kiocb_free(req);
-}
-EXPORT_SYMBOL(aio_put_req);
-
 static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 {
+	struct aio_ring __user *ring  = (void __user *)ctx_id;
 	struct mm_struct *mm = current->mm;
 	struct kioctx *ctx, *ret = NULL;
+	struct kioctx_table *table;
+	unsigned id;
+
+	if (get_user(id, &ring->id))
+		return NULL;
 
 	rcu_read_lock();
+	table = rcu_dereference(mm->ioctx_table);
 
-	hlist_for_each_entry_rcu(ctx, &mm->ioctx_list, list) {
-		if (ctx->user_id == ctx_id) {
-			atomic_inc(&ctx->users);
-			ret = ctx;
-			break;
-		}
-	}
+	if (!table || id >= table->nr)
+		goto out;
 
+	ctx = table->table[id];
+	if (ctx && ctx->user_id == ctx_id) {
+		percpu_ref_get(&ctx->users);
+		ret = ctx;
+	}
+out:
 	rcu_read_unlock();
 	return ret;
 }
@@ -591,16 +840,16 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 	 *  - the sync task helpfully left a reference to itself in the iocb
 	 */
 	if (is_sync_kiocb(iocb)) {
-		BUG_ON(atomic_read(&iocb->ki_users) != 1);
 		iocb->ki_user_data = res;
-		atomic_set(&iocb->ki_users, 0);
+		smp_wmb();
+		iocb->ki_ctx = ERR_PTR(-EXDEV);
 		wake_up_process(iocb->ki_obj.tsk);
 		return;
 	}
 
 	/*
 	 * Take rcu_read_lock() in case the kioctx is being destroyed, as we
-	 * need to issue a wakeup after decrementing reqs_active.
+	 * need to issue a wakeup after incrementing reqs_available.
 	 */
 	rcu_read_lock();
 
@@ -613,17 +862,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 	}
 
 	/*
-	 * cancelled requests don't get events, userland was given one
-	 * when the event got cancelled.
-	 */
-	if (unlikely(xchg(&iocb->ki_cancel,
-			  KIOCB_CANCELLED) == KIOCB_CANCELLED)) {
-		atomic_dec(&ctx->reqs_active);
-		/* Still need the wake_up in case free_ioctx is waiting */
-		goto put_rq;
-	}
-
-	/*
 	 * Add a completion event to the ring buffer. Must be done holding
 	 * ctx->completion_lock to prevent other code from messing with the tail
 	 * pointer since we might be called from irq context.
@@ -675,9 +913,8 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 	if (iocb->ki_eventfd != NULL)
 		eventfd_signal(iocb->ki_eventfd, 1);
 
-put_rq:
 	/* everything turned out well, dispose of the aiocb. */
-	aio_put_req(iocb);
+	kiocb_free(iocb);
 
 	/*
 	 * We have to order our ring_info tail store above and test
@@ -702,7 +939,7 @@ static long aio_read_events_ring(struct kioctx *ctx,
 				 struct io_event __user *event, long nr)
 {
 	struct aio_ring *ring;
-	unsigned head, pos;
+	unsigned head, tail, pos;
 	long ret = 0;
 	int copy_ret;
 
@@ -710,11 +947,12 @@ static long aio_read_events_ring(struct kioctx *ctx,
 
 	ring = kmap_atomic(ctx->ring_pages[0]);
 	head = ring->head;
+	tail = ring->tail;
 	kunmap_atomic(ring);
 
-	pr_debug("h%u t%u m%u\n", head, ctx->tail, ctx->nr_events);
+	pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events);
 
-	if (head == ctx->tail)
+	if (head == tail)
 		goto out;
 
 	while (ret < nr) {
@@ -722,8 +960,8 @@ static long aio_read_events_ring(struct kioctx *ctx,
 		struct io_event *ev;
 		struct page *page;
 
-		avail = (head <= ctx->tail ? ctx->tail : ctx->nr_events) - head;
-		if (head == ctx->tail)
+		avail = (head <= tail ?  tail : ctx->nr_events) - head;
+		if (head == tail)
 			break;
 
 		avail = min(avail, nr - ret);
@@ -754,9 +992,9 @@ static long aio_read_events_ring(struct kioctx *ctx,
 	kunmap_atomic(ring);
 	flush_dcache_page(ctx->ring_pages[0]);
 
-	pr_debug("%li  h%u t%u\n", ret, head, ctx->tail);
+	pr_debug("%li  h%u t%u\n", ret, head, tail);
 
-	atomic_sub(ret, &ctx->reqs_active);
+	put_reqs_available(ctx, ret);
 out:
 	mutex_unlock(&ctx->ring_lock);
 
@@ -854,8 +1092,8 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
 	if (!IS_ERR(ioctx)) {
 		ret = put_user(ioctx->user_id, ctxp);
 		if (ret)
-			kill_ioctx(ioctx);
-		put_ioctx(ioctx);
+			kill_ioctx(current->mm, ioctx);
+		percpu_ref_put(&ioctx->users);
 	}
 
 out:
@@ -872,101 +1110,37 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
 {
 	struct kioctx *ioctx = lookup_ioctx(ctx);
 	if (likely(NULL != ioctx)) {
-		kill_ioctx(ioctx);
-		put_ioctx(ioctx);
+		kill_ioctx(current->mm, ioctx);
+		percpu_ref_put(&ioctx->users);
 		return 0;
 	}
 	pr_debug("EINVAL: io_destroy: invalid context id\n");
 	return -EINVAL;
 }
 
-static void aio_advance_iovec(struct kiocb *iocb, ssize_t ret)
-{
-	struct iovec *iov = &iocb->ki_iovec[iocb->ki_cur_seg];
-
-	BUG_ON(ret <= 0);
-
-	while (iocb->ki_cur_seg < iocb->ki_nr_segs && ret > 0) {
-		ssize_t this = min((ssize_t)iov->iov_len, ret);
-		iov->iov_base += this;
-		iov->iov_len -= this;
-		iocb->ki_left -= this;
-		ret -= this;
-		if (iov->iov_len == 0) {
-			iocb->ki_cur_seg++;
-			iov++;
-		}
-	}
-
-	/* the caller should not have done more io than what fit in
-	 * the remaining iovecs */
-	BUG_ON(ret > 0 && iocb->ki_left == 0);
-}
-
 typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
 			    unsigned long, loff_t);
 
-static ssize_t aio_rw_vect_retry(struct kiocb *iocb, int rw, aio_rw_op *rw_op)
-{
-	struct file *file = iocb->ki_filp;
-	struct address_space *mapping = file->f_mapping;
-	struct inode *inode = mapping->host;
-	ssize_t ret = 0;
-
-	/* This matches the pread()/pwrite() logic */
-	if (iocb->ki_pos < 0)
-		return -EINVAL;
-
-	if (rw == WRITE)
-		file_start_write(file);
-	do {
-		ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
-			    iocb->ki_nr_segs - iocb->ki_cur_seg,
-			    iocb->ki_pos);
-		if (ret > 0)
-			aio_advance_iovec(iocb, ret);
-
-	/* retry all partial writes.  retry partial reads as long as its a
-	 * regular file. */
-	} while (ret > 0 && iocb->ki_left > 0 &&
-		 (rw == WRITE ||
-		  (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))));
-	if (rw == WRITE)
-		file_end_write(file);
-
-	/* This means we must have transferred all that we could */
-	/* No need to retry anymore */
-	if ((ret == 0) || (iocb->ki_left == 0))
-		ret = iocb->ki_nbytes - iocb->ki_left;
-
-	/* If we managed to write some out we return that, rather than
-	 * the eventual error. */
-	if (rw == WRITE
-	    && ret < 0 && ret != -EIOCBQUEUED
-	    && iocb->ki_nbytes - iocb->ki_left)
-		ret = iocb->ki_nbytes - iocb->ki_left;
-
-	return ret;
-}
-
-static ssize_t aio_setup_vectored_rw(int rw, struct kiocb *kiocb, bool compat)
+static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
+				     int rw, char __user *buf,
+				     unsigned long *nr_segs,
+				     struct iovec **iovec,
+				     bool compat)
 {
 	ssize_t ret;
 
-	kiocb->ki_nr_segs = kiocb->ki_nbytes;
+	*nr_segs = kiocb->ki_nbytes;
 
 #ifdef CONFIG_COMPAT
 	if (compat)
 		ret = compat_rw_copy_check_uvector(rw,
-				(struct compat_iovec __user *)kiocb->ki_buf,
-				kiocb->ki_nr_segs, 1, &kiocb->ki_inline_vec,
-				&kiocb->ki_iovec);
+				(struct compat_iovec __user *)buf,
+				*nr_segs, 1, *iovec, iovec);
 	else
 #endif
 		ret = rw_copy_check_uvector(rw,
-				(struct iovec __user *)kiocb->ki_buf,
-				kiocb->ki_nr_segs, 1, &kiocb->ki_inline_vec,
-				&kiocb->ki_iovec);
+				(struct iovec __user *)buf,
+				*nr_segs, 1, *iovec, iovec);
 	if (ret < 0)
 		return ret;
 
@@ -975,15 +1149,17 @@ static ssize_t aio_setup_vectored_rw(int rw, struct kiocb *kiocb, bool compat)
 	return 0;
 }
 
-static ssize_t aio_setup_single_vector(int rw, struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
+				       int rw, char __user *buf,
+				       unsigned long *nr_segs,
+				       struct iovec *iovec)
 {
-	if (unlikely(!access_ok(!rw, kiocb->ki_buf, kiocb->ki_nbytes)))
+	if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
 		return -EFAULT;
 
-	kiocb->ki_iovec = &kiocb->ki_inline_vec;
-	kiocb->ki_iovec->iov_base = kiocb->ki_buf;
-	kiocb->ki_iovec->iov_len = kiocb->ki_nbytes;
-	kiocb->ki_nr_segs = 1;
+	iovec->iov_base = buf;
+	iovec->iov_len = kiocb->ki_nbytes;
+	*nr_segs = 1;
 	return 0;
 }
 
@@ -992,15 +1168,18 @@ static ssize_t aio_setup_single_vector(int rw, struct kiocb *kiocb)
  *	Performs the initial checks and aio retry method
  *	setup for the kiocb at the time of io submission.
  */
-static ssize_t aio_run_iocb(struct kiocb *req, bool compat)
+static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
+			    char __user *buf, bool compat)
 {
 	struct file *file = req->ki_filp;
 	ssize_t ret;
+	unsigned long nr_segs;
 	int rw;
 	fmode_t mode;
 	aio_rw_op *rw_op;
+	struct iovec inline_vec, *iovec = &inline_vec;
 
-	switch (req->ki_opcode) {
+	switch (opcode) {
 	case IOCB_CMD_PREAD:
 	case IOCB_CMD_PREADV:
 		mode	= FMODE_READ;
@@ -1021,21 +1200,38 @@ rw_common:
 		if (!rw_op)
 			return -EINVAL;
 
-		ret = (req->ki_opcode == IOCB_CMD_PREADV ||
-		       req->ki_opcode == IOCB_CMD_PWRITEV)
-			? aio_setup_vectored_rw(rw, req, compat)
-			: aio_setup_single_vector(rw, req);
+		ret = (opcode == IOCB_CMD_PREADV ||
+		       opcode == IOCB_CMD_PWRITEV)
+			? aio_setup_vectored_rw(req, rw, buf, &nr_segs,
+						&iovec, compat)
+			: aio_setup_single_vector(req, rw, buf, &nr_segs,
+						  iovec);
 		if (ret)
 			return ret;
 
 		ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
-		if (ret < 0)
+		if (ret < 0) {
+			if (iovec != &inline_vec)
+				kfree(iovec);
 			return ret;
+		}
 
 		req->ki_nbytes = ret;
-		req->ki_left = ret;
 
-		ret = aio_rw_vect_retry(req, rw, rw_op);
+		/* XXX: move/kill - rw_verify_area()? */
+		/* This matches the pread()/pwrite() logic */
+		if (req->ki_pos < 0) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (rw == WRITE)
+			file_start_write(file);
+
+		ret = rw_op(req, iovec, nr_segs, req->ki_pos);
+
+		if (rw == WRITE)
+			file_end_write(file);
 		break;
 
 	case IOCB_CMD_FDSYNC:
@@ -1057,6 +1253,9 @@ rw_common:
 		return -EINVAL;
 	}
 
+	if (iovec != &inline_vec)
+		kfree(iovec);
+
 	if (ret != -EIOCBQUEUED) {
 		/*
 		 * There's no easy way to restart the syscall since other AIO's
@@ -1128,21 +1327,18 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 	req->ki_obj.user = user_iocb;
 	req->ki_user_data = iocb->aio_data;
 	req->ki_pos = iocb->aio_offset;
+	req->ki_nbytes = iocb->aio_nbytes;
 
-	req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
-	req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
-	req->ki_opcode = iocb->aio_lio_opcode;
-
-	ret = aio_run_iocb(req, compat);
+	ret = aio_run_iocb(req, iocb->aio_lio_opcode,
+			   (char __user *)(unsigned long)iocb->aio_buf,
+			   compat);
 	if (ret)
 		goto out_put_req;
 
-	aio_put_req(req);	/* drop extra ref to req */
 	return 0;
 out_put_req:
-	atomic_dec(&ctx->reqs_active);
-	aio_put_req(req);	/* drop extra ref to req */
-	aio_put_req(req);	/* drop i/o ref to req */
+	put_reqs_available(ctx, 1);
+	kiocb_free(req);
 	return ret;
 }
 
@@ -1195,7 +1391,7 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 	}
 	blk_finish_plug(&plug);
 
-	put_ioctx(ctx);
+	percpu_ref_put(&ctx->users);
 	return i ? i : ret;
 }
 
@@ -1252,7 +1448,6 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
 SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
 		struct io_event __user *, result)
 {
-	struct io_event res;
 	struct kioctx *ctx;
 	struct kiocb *kiocb;
 	u32 key;
@@ -1270,21 +1465,22 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
 
 	kiocb = lookup_kiocb(ctx, iocb, key);
 	if (kiocb)
-		ret = kiocb_cancel(ctx, kiocb, &res);
+		ret = kiocb_cancel(ctx, kiocb);
 	else
 		ret = -EINVAL;
 
 	spin_unlock_irq(&ctx->ctx_lock);
 
 	if (!ret) {
-		/* Cancellation succeeded -- copy the result
-		 * into the user's buffer.
+		/*
+		 * The result argument is no longer used - the io_event is
+		 * always delivered via the ring buffer. -EINPROGRESS indicates
+		 * cancellation is progress:
 		 */
-		if (copy_to_user(result, &res, sizeof(res)))
-			ret = -EFAULT;
+		ret = -EINPROGRESS;
 	}
 
-	put_ioctx(ctx);
+	percpu_ref_put(&ctx->users);
 
 	return ret;
 }
@@ -1313,7 +1509,7 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
 	if (likely(ioctx)) {
 		if (likely(min_nr <= nr && min_nr >= 0))
 			ret = read_events(ioctx, min_nr, nr, events, timeout);
-		put_ioctx(ioctx);
+		percpu_ref_put(&ioctx->users);
 	}
 	return ret;
 }
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 47a65df..85c9618 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -109,6 +109,72 @@ static struct file_system_type anon_inode_fs_type = {
 };
 
 /**
+ * anon_inode_getfile_private - creates a new file instance by hooking it up to an
+ *                      anonymous inode, and a dentry that describe the "class"
+ *                      of the file
+ *
+ * @name:    [in]    name of the "class" of the new file
+ * @fops:    [in]    file operations for the new file
+ * @priv:    [in]    private data for the new file (will be file's private_data)
+ * @flags:   [in]    flags
+ *
+ *
+ * Similar to anon_inode_getfile, but each file holds a single inode.
+ *
+ */
+struct file *anon_inode_getfile_private(const char *name,
+					const struct file_operations *fops,
+					void *priv, int flags)
+{
+	struct qstr this;
+	struct path path;
+	struct file *file;
+	struct inode *inode;
+
+	if (fops->owner && !try_module_get(fops->owner))
+		return ERR_PTR(-ENOENT);
+
+	inode = anon_inode_mkinode(anon_inode_mnt->mnt_sb);
+	if (IS_ERR(inode)) {
+		file = ERR_PTR(-ENOMEM);
+		goto err_module;
+	}
+
+	/*
+	 * Link the inode to a directory entry by creating a unique name
+	 * using the inode sequence number.
+	 */
+	file = ERR_PTR(-ENOMEM);
+	this.name = name;
+	this.len = strlen(name);
+	this.hash = 0;
+	path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
+	if (!path.dentry)
+		goto err_module;
+
+	path.mnt = mntget(anon_inode_mnt);
+
+	d_instantiate(path.dentry, inode);
+
+	file = alloc_file(&path, OPEN_FMODE(flags), fops);
+	if (IS_ERR(file))
+		goto err_dput;
+
+	file->f_mapping = inode->i_mapping;
+	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
+	file->private_data = priv;
+
+	return file;
+
+err_dput:
+	path_put(&path);
+err_module:
+	module_put(fops->owner);
+	return file;
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile_private);
+
+/**
  * anon_inode_getfile - creates a new file instance by hooking it up to an
  *                      anonymous inode, and a dentry that describe the "class"
  *                      of the file
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 3f1128b..16d3288 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -104,7 +104,7 @@ struct autofs_sb_info {
 	u32 magic;
 	int pipefd;
 	struct file *pipe;
-	pid_t oz_pgrp;
+	struct pid *oz_pgrp;
 	int catatonic;
 	int version;
 	int sub_version;
@@ -139,7 +139,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry)
    filesystem without "magic".) */
 
 static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
-	return sbi->catatonic || task_pgrp_nr(current) == sbi->oz_pgrp;
+	return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
 }
 
 /* Does a dentry have some pending activity? */
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 743c7c2..9183821 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -346,6 +346,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
 {
 	int pipefd;
 	int err = 0;
+	struct pid *new_pid = NULL;
 
 	if (param->setpipefd.pipefd == -1)
 		return -EINVAL;
@@ -357,7 +358,17 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
 		mutex_unlock(&sbi->wq_mutex);
 		return -EBUSY;
 	} else {
-		struct file *pipe = fget(pipefd);
+		struct file *pipe;
+
+		new_pid = get_task_pid(current, PIDTYPE_PGID);
+
+		if (ns_of_pid(new_pid) != ns_of_pid(sbi->oz_pgrp)) {
+			AUTOFS_WARN("Not allowed to change PID namespace");
+			err = -EINVAL;
+			goto out;
+		}
+
+		pipe = fget(pipefd);
 		if (!pipe) {
 			err = -EBADF;
 			goto out;
@@ -367,12 +378,13 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
 			fput(pipe);
 			goto out;
 		}
-		sbi->oz_pgrp = task_pgrp_nr(current);
+		swap(sbi->oz_pgrp, new_pid);
 		sbi->pipefd = pipefd;
 		sbi->pipe = pipe;
 		sbi->catatonic = 0;
 	}
 out:
+	put_pid(new_pid);
 	mutex_unlock(&sbi->wq_mutex);
 	return err;
 }
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index b104726..1b045ec 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -62,6 +62,8 @@ void autofs4_kill_sb(struct super_block *sb)
 	/* Free wait queues, close pipe */
 	autofs4_catatonic_mode(sbi);
 
+	put_pid(sbi->oz_pgrp);
+
 	sb->s_fs_info = NULL;
 	kfree(sbi);
 
@@ -85,7 +87,7 @@ static int autofs4_show_options(struct seq_file *m, struct dentry *root)
 	if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID))
 		seq_printf(m, ",gid=%u",
 			from_kgid_munged(&init_user_ns, root_inode->i_gid));
-	seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
+	seq_printf(m, ",pgrp=%d", pid_vnr(sbi->oz_pgrp));
 	seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
 	seq_printf(m, ",minproto=%d", sbi->min_proto);
 	seq_printf(m, ",maxproto=%d", sbi->max_proto);
@@ -129,7 +131,8 @@ static const match_table_t tokens = {
 };
 
 static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
-		pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
+			 int *pgrp, bool *pgrp_set, unsigned int *type,
+			 int *minproto, int *maxproto)
 {
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
@@ -137,7 +140,6 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
 
 	*uid = current_uid();
 	*gid = current_gid();
-	*pgrp = task_pgrp_nr(current);
 
 	*minproto = AUTOFS_MIN_PROTO_VERSION;
 	*maxproto = AUTOFS_MAX_PROTO_VERSION;
@@ -176,6 +178,7 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
 			if (match_int(args, &option))
 				return 1;
 			*pgrp = option;
+			*pgrp_set = true;
 			break;
 		case Opt_minproto:
 			if (match_int(args, &option))
@@ -211,6 +214,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
 	int pipefd;
 	struct autofs_sb_info *sbi;
 	struct autofs_info *ino;
+	int pgrp;
+	bool pgrp_set = false;
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -223,7 +228,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
 	sbi->pipe = NULL;
 	sbi->catatonic = 1;
 	sbi->exp_timeout = 0;
-	sbi->oz_pgrp = task_pgrp_nr(current);
+	sbi->oz_pgrp = NULL;
 	sbi->sb = s;
 	sbi->version = 0;
 	sbi->sub_version = 0;
@@ -260,12 +265,23 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
 
 	/* Can this call block? */
 	if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
-				&sbi->oz_pgrp, &sbi->type, &sbi->min_proto,
-				&sbi->max_proto)) {
+			  &pgrp, &pgrp_set, &sbi->type, &sbi->min_proto,
+			  &sbi->max_proto)) {
 		printk("autofs: called with bogus options\n");
 		goto fail_dput;
 	}
 
+	if (pgrp_set) {
+		sbi->oz_pgrp = find_get_pid(pgrp);
+		if (!sbi->oz_pgrp) {
+			pr_warn("autofs: could not find process group %d\n",
+				pgrp);
+			goto fail_dput;
+		}
+	} else {
+		sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID);
+	}
+
 	if (autofs_type_trigger(sbi->type))
 		__managed_dentry_set_managed(root);
 
@@ -289,9 +305,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
 		sbi->version = sbi->max_proto;
 	sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
 
-	DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
+	DPRINTK("pipe fd = %d, pgrp = %u", pipefd, pid_nr(sbi->oz_pgrp));
 	pipe = fget(pipefd);
-	
+
 	if (!pipe) {
 		printk("autofs: could not open pipe file descriptor\n");
 		goto fail_dput;
@@ -321,6 +337,7 @@ fail_dput:
 fail_ino:
 	kfree(ino);
 fail_free:
+	put_pid(sbi->oz_pgrp);
 	kfree(sbi);
 	s->s_fs_info = NULL;
 fail_unlock:
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 3db70da..309ca6b 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -353,11 +353,23 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 	struct qstr qstr;
 	char *name;
 	int status, ret, type;
+	pid_t pid;
+	pid_t tgid;
 
 	/* In catatonic mode, we don't wait for nobody */
 	if (sbi->catatonic)
 		return -ENOENT;
 
+	/*
+	 * Try translating pids to the namespace of the daemon.
+	 *
+	 * Zero means failure: we are in an unrelated pid namespace.
+	 */
+	pid = task_pid_nr_ns(current, ns_of_pid(sbi->oz_pgrp));
+	tgid = task_tgid_nr_ns(current, ns_of_pid(sbi->oz_pgrp));
+	if (pid == 0 || tgid == 0)
+		return -ENOENT;
+
 	if (!dentry->d_inode) {
 		/*
 		 * A wait for a negative dentry is invalid for certain
@@ -423,8 +435,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 		wq->ino = autofs4_get_ino(sbi);
 		wq->uid = current_uid();
 		wq->gid = current_gid();
-		wq->pid = current->pid;
-		wq->tgid = current->tgid;
+		wq->pid = pid;
+		wq->tgid = tgid;
 		wq->status = -EINTR; /* Status return if interrupted */
 		wq->wait_ctr = 2;
 		mutex_unlock(&sbi->wq_mutex);
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 89dec7f..b3192da 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -45,7 +45,6 @@ static int load_aout_library(struct file*);
  */
 static int aout_core_dump(struct coredump_params *cprm)
 {
-	struct file *file = cprm->file;
 	mm_segment_t fs;
 	int has_dumped = 0;
 	void __user *dump_start;
@@ -85,10 +84,10 @@ static int aout_core_dump(struct coredump_params *cprm)
 
 	set_fs(KERNEL_DS);
 /* struct user */
-	if (!dump_write(file, &dump, sizeof(dump)))
+	if (!dump_emit(cprm, &dump, sizeof(dump)))
 		goto end_coredump;
 /* Now dump all of the user data.  Include malloced stuff as well */
-	if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump)))
+	if (!dump_align(cprm, PAGE_SIZE))
 		goto end_coredump;
 /* now we start writing out the user space info */
 	set_fs(USER_DS);
@@ -96,14 +95,14 @@ static int aout_core_dump(struct coredump_params *cprm)
 	if (dump.u_dsize != 0) {
 		dump_start = START_DATA(dump);
 		dump_size = dump.u_dsize << PAGE_SHIFT;
-		if (!dump_write(file, dump_start, dump_size))
+		if (!dump_emit(cprm, dump_start, dump_size))
 			goto end_coredump;
 	}
 /* Now prepare to dump the stack area */
 	if (dump.u_ssize != 0) {
 		dump_start = START_STACK(dump);
 		dump_size = dump.u_ssize << PAGE_SHIFT;
-		if (!dump_write(file, dump_start, dump_size))
+		if (!dump_emit(cprm, dump_start, dump_size))
 			goto end_coredump;
 	}
 end_coredump:
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 100edcc..dc82279 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -140,6 +140,25 @@ static int padzero(unsigned long elf_bss)
 #define ELF_BASE_PLATFORM NULL
 #endif
 
+/*
+ * Use get_random_int() to implement AT_RANDOM while avoiding depletion
+ * of the entropy pool.
+ */
+static void get_atrandom_bytes(unsigned char *buf, size_t nbytes)
+{
+	unsigned char *p = buf;
+
+	while (nbytes) {
+		unsigned int random_variable;
+		size_t chunk = min(nbytes, sizeof(random_variable));
+
+		random_variable = get_random_int();
+		memcpy(p, &random_variable, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+}
+
 static int
 create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 		unsigned long load_addr, unsigned long interp_load_addr)
@@ -201,7 +220,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	/*
 	 * Generate 16 random bytes for userspace PRNG seeding.
 	 */
-	get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
+	get_atrandom_bytes(k_rand_bytes, sizeof(k_rand_bytes));
 	u_rand_bytes = (elf_addr_t __user *)
 		       STACK_ALLOC(p, sizeof(k_rand_bytes));
 	if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
@@ -1225,35 +1244,32 @@ static int notesize(struct memelfnote *en)
 	return sz;
 }
 
-#define DUMP_WRITE(addr, nr, foffset)	\
-	do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
-
-static int alignfile(struct file *file, loff_t *foffset)
+static int alignfile(struct coredump_params *cprm)
 {
 	static const char buf[4] = { 0, };
-	DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
-	return 1;
+	return dump_emit(cprm, buf, roundup(cprm->written, 4) - cprm->written);
 }
 
-static int writenote(struct memelfnote *men, struct file *file,
-			loff_t *foffset)
+static int writenote(struct memelfnote *men, struct coredump_params *cprm)
 {
 	struct elf_note en;
 	en.n_namesz = strlen(men->name) + 1;
 	en.n_descsz = men->datasz;
 	en.n_type = men->type;
 
-	DUMP_WRITE(&en, sizeof(en), foffset);
-	DUMP_WRITE(men->name, en.n_namesz, foffset);
-	if (!alignfile(file, foffset))
+	if (!dump_emit(cprm, &en, sizeof(en)))
+		return 0;
+	if (!dump_emit(cprm, men->name, en.n_namesz))
+		return 0;
+	if (!alignfile(cprm))
 		return 0;
-	DUMP_WRITE(men->data, men->datasz, foffset);
-	if (!alignfile(file, foffset))
+	if (!dump_emit(cprm, men->data, men->datasz))
+		return 0;
+	if (!alignfile(cprm))
 		return 0;
 
 	return 1;
 }
-#undef DUMP_WRITE
 
 static void fill_elf_header(struct elfhdr *elf, int segs,
 			    u16 machine, u32 flags)
@@ -1702,7 +1718,7 @@ static size_t get_note_info_size(struct elf_note_info *info)
  * process-wide notes are interleaved after the first thread-specific note.
  */
 static int write_note_info(struct elf_note_info *info,
-			   struct file *file, loff_t *foffset)
+			   struct coredump_params *cprm)
 {
 	bool first = 1;
 	struct elf_thread_core_info *t = info->thread;
@@ -1710,21 +1726,21 @@ static int write_note_info(struct elf_note_info *info,
 	do {
 		int i;
 
-		if (!writenote(&t->notes[0], file, foffset))
+		if (!writenote(&t->notes[0], cprm))
 			return 0;
 
-		if (first && !writenote(&info->psinfo, file, foffset))
+		if (first && !writenote(&info->psinfo, cprm))
 			return 0;
-		if (first && !writenote(&info->signote, file, foffset))
+		if (first && !writenote(&info->signote, cprm))
 			return 0;
-		if (first && !writenote(&info->auxv, file, foffset))
+		if (first && !writenote(&info->auxv, cprm))
 			return 0;
-		if (first && !writenote(&info->files, file, foffset))
+		if (first && !writenote(&info->files, cprm))
 			return 0;
 
 		for (i = 1; i < info->thread_notes; ++i)
 			if (t->notes[i].data &&
-			    !writenote(&t->notes[i], file, foffset))
+			    !writenote(&t->notes[i], cprm))
 				return 0;
 
 		first = 0;
@@ -1930,13 +1946,13 @@ static size_t get_note_info_size(struct elf_note_info *info)
 }
 
 static int write_note_info(struct elf_note_info *info,
-			   struct file *file, loff_t *foffset)
+			   struct coredump_params *cprm)
 {
 	int i;
 	struct list_head *t;
 
 	for (i = 0; i < info->numnote; i++)
-		if (!writenote(info->notes + i, file, foffset))
+		if (!writenote(info->notes + i, cprm))
 			return 0;
 
 	/* write out the thread status notes section */
@@ -1945,7 +1961,7 @@ static int write_note_info(struct elf_note_info *info,
 				list_entry(t, struct elf_thread_status, list);
 
 		for (i = 0; i < tmp->num_notes; i++)
-			if (!writenote(&tmp->notes[i], file, foffset))
+			if (!writenote(&tmp->notes[i], cprm))
 				return 0;
 	}
 
@@ -2040,10 +2056,9 @@ static int elf_core_dump(struct coredump_params *cprm)
 	int has_dumped = 0;
 	mm_segment_t fs;
 	int segs;
-	size_t size = 0;
 	struct vm_area_struct *vma, *gate_vma;
 	struct elfhdr *elf = NULL;
-	loff_t offset = 0, dataoff, foffset;
+	loff_t offset = 0, dataoff;
 	struct elf_note_info info;
 	struct elf_phdr *phdr4note = NULL;
 	struct elf_shdr *shdr4extnum = NULL;
@@ -2099,7 +2114,6 @@ static int elf_core_dump(struct coredump_params *cprm)
 
 	offset += sizeof(*elf);				/* Elf header */
 	offset += segs * sizeof(struct elf_phdr);	/* Program headers */
-	foffset = offset;
 
 	/* Write notes phdr entry */
 	{
@@ -2130,13 +2144,10 @@ static int elf_core_dump(struct coredump_params *cprm)
 
 	offset = dataoff;
 
-	size += sizeof(*elf);
-	if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+	if (!dump_emit(cprm, elf, sizeof(*elf)))
 		goto end_coredump;
 
-	size += sizeof(*phdr4note);
-	if (size > cprm->limit
-	    || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+	if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
 		goto end_coredump;
 
 	/* Write program headers for segments dump */
@@ -2158,24 +2169,22 @@ static int elf_core_dump(struct coredump_params *cprm)
 			phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
-		size += sizeof(phdr);
-		if (size > cprm->limit
-		    || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+		if (!dump_emit(cprm, &phdr, sizeof(phdr)))
 			goto end_coredump;
 	}
 
-	if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
+	if (!elf_core_write_extra_phdrs(cprm, offset))
 		goto end_coredump;
 
  	/* write out the notes section */
-	if (!write_note_info(&info, cprm->file, &foffset))
+	if (!write_note_info(&info, cprm))
 		goto end_coredump;
 
-	if (elf_coredump_extra_notes_write(cprm->file, &foffset))
+	if (elf_coredump_extra_notes_write(cprm))
 		goto end_coredump;
 
 	/* Align to page */
-	if (!dump_seek(cprm->file, dataoff - foffset))
+	if (!dump_align(cprm, ELF_EXEC_PAGESIZE))
 		goto end_coredump;
 
 	for (vma = first_vma(current, gate_vma); vma != NULL;
@@ -2192,28 +2201,22 @@ static int elf_core_dump(struct coredump_params *cprm)
 			page = get_dump_page(addr);
 			if (page) {
 				void *kaddr = kmap(page);
-				stop = ((size += PAGE_SIZE) > cprm->limit) ||
-					!dump_write(cprm->file, kaddr,
-						    PAGE_SIZE);
+				stop = !dump_emit(cprm, kaddr, PAGE_SIZE);
 				kunmap(page);
 				page_cache_release(page);
 			} else
-				stop = !dump_seek(cprm->file, PAGE_SIZE);
+				stop = !dump_skip(cprm, PAGE_SIZE);
 			if (stop)
 				goto end_coredump;
 		}
 	}
 
-	if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
+	if (!elf_core_write_extra_data(cprm))
 		goto end_coredump;
 
-	if (e_phnum == PN_XNUM) {
-		size += sizeof(*shdr4extnum);
-		if (size > cprm->limit
-		    || !dump_write(cprm->file, shdr4extnum,
-				   sizeof(*shdr4extnum)))
+	if (e_phnum == PN_XNUM)
+		if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
 			goto end_coredump;
-	}
 
 end_coredump:
 	set_fs(fs);
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index c166f32..85c23c4 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1207,7 +1207,7 @@ static int maydump(struct vm_area_struct *vma, unsigned long mm_flags)
 	}
 
 	/* If we may not read the contents, don't allow us to dump
-	 * them either. "dump_write()" can't handle it anyway.
+	 * them either. "dump_emit()" can't handle it anyway.
 	 */
 	if (!(vma->vm_flags & VM_READ)) {
 		kdcore("%08lx: %08lx: no (!read)", vma->vm_start, vma->vm_flags);
@@ -1267,35 +1267,26 @@ static int notesize(struct memelfnote *en)
 
 /* #define DEBUG */
 
-#define DUMP_WRITE(addr, nr, foffset)	\
-	do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
-
-static int alignfile(struct file *file, loff_t *foffset)
-{
-	static const char buf[4] = { 0, };
-	DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
-	return 1;
-}
-
-static int writenote(struct memelfnote *men, struct file *file,
-			loff_t *foffset)
+static int writenote(struct memelfnote *men, struct coredump_params *cprm)
 {
 	struct elf_note en;
 	en.n_namesz = strlen(men->name) + 1;
 	en.n_descsz = men->datasz;
 	en.n_type = men->type;
 
-	DUMP_WRITE(&en, sizeof(en), foffset);
-	DUMP_WRITE(men->name, en.n_namesz, foffset);
-	if (!alignfile(file, foffset))
+	if (!dump_emit(cprm, &en, sizeof(en)))
 		return 0;
-	DUMP_WRITE(men->data, men->datasz, foffset);
-	if (!alignfile(file, foffset))
+	if (!dump_emit(cprm, men->name, en.n_namesz))
+		return 0;
+	if (!dump_align(cprm, 4))
+		return 0;
+	if (!dump_emit(cprm, men->data, men->datasz))
+		return 0;
+	if (!dump_align(cprm, 4))
 		return 0;
 
 	return 1;
 }
-#undef DUMP_WRITE
 
 static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
 {
@@ -1501,8 +1492,7 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
  * dump the segments for an MMU process
  */
 #ifdef CONFIG_MMU
-static int elf_fdpic_dump_segments(struct file *file, size_t *size,
-			   unsigned long *limit, unsigned long mm_flags)
+static int elf_fdpic_dump_segments(struct coredump_params *cprm)
 {
 	struct vm_area_struct *vma;
 	int err = 0;
@@ -1510,7 +1500,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
 	for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
 		unsigned long addr;
 
-		if (!maydump(vma, mm_flags))
+		if (!maydump(vma, cprm->mm_flags))
 			continue;
 
 		for (addr = vma->vm_start; addr < vma->vm_end;
@@ -1518,14 +1508,11 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
 			struct page *page = get_dump_page(addr);
 			if (page) {
 				void *kaddr = kmap(page);
-				*size += PAGE_SIZE;
-				if (*size > *limit)
-					err = -EFBIG;
-				else if (!dump_write(file, kaddr, PAGE_SIZE))
+				if (!dump_emit(cprm, kaddr, PAGE_SIZE))
 					err = -EIO;
 				kunmap(page);
 				page_cache_release(page);
-			} else if (!dump_seek(file, PAGE_SIZE))
+			} else if (!dump_skip(cprm, PAGE_SIZE))
 				err = -EFBIG;
 			if (err)
 				goto out;
@@ -1540,19 +1527,15 @@ out:
  * dump the segments for a NOMMU process
  */
 #ifndef CONFIG_MMU
-static int elf_fdpic_dump_segments(struct file *file, size_t *size,
-			   unsigned long *limit, unsigned long mm_flags)
+static int elf_fdpic_dump_segments(struct coredump_params *cprm)
 {
 	struct vm_area_struct *vma;
 
 	for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
-		if (!maydump(vma, mm_flags))
+		if (!maydump(vma, cprm->mm_flags))
 			continue;
 
-		if ((*size += PAGE_SIZE) > *limit)
-			return -EFBIG;
-
-		if (!dump_write(file, (void *) vma->vm_start,
+		if (!dump_emit(cprm, (void *) vma->vm_start,
 				vma->vm_end - vma->vm_start))
 			return -EIO;
 	}
@@ -1585,7 +1568,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
 	int has_dumped = 0;
 	mm_segment_t fs;
 	int segs;
-	size_t size = 0;
 	int i;
 	struct vm_area_struct *vma;
 	struct elfhdr *elf = NULL;
@@ -1755,13 +1737,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
 
 	offset = dataoff;
 
-	size += sizeof(*elf);
-	if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+	if (!dump_emit(cprm, elf, sizeof(*elf)))
 		goto end_coredump;
 
-	size += sizeof(*phdr4note);
-	if (size > cprm->limit
-	    || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+	if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
 		goto end_coredump;
 
 	/* write program headers for segments dump */
@@ -1785,18 +1764,16 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
 			phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
-		size += sizeof(phdr);
-		if (size > cprm->limit
-		    || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+		if (!dump_emit(cprm, &phdr, sizeof(phdr)))
 			goto end_coredump;
 	}
 
-	if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
+	if (!elf_core_write_extra_phdrs(cprm, offset))
 		goto end_coredump;
 
  	/* write out the notes section */
 	for (i = 0; i < numnote; i++)
-		if (!writenote(notes + i, cprm->file, &foffset))
+		if (!writenote(notes + i, cprm))
 			goto end_coredump;
 
 	/* write out the thread status notes section */
@@ -1805,33 +1782,29 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
 				list_entry(t, struct elf_thread_status, list);
 
 		for (i = 0; i < tmp->num_notes; i++)
-			if (!writenote(&tmp->notes[i], cprm->file, &foffset))
+			if (!writenote(&tmp->notes[i], cprm))
 				goto end_coredump;
 	}
 
-	if (!dump_seek(cprm->file, dataoff - foffset))
+	if (!dump_align(cprm, ELF_EXEC_PAGESIZE))
 		goto end_coredump;
 
-	if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
-				    cprm->mm_flags) < 0)
+	if (elf_fdpic_dump_segments(cprm) < 0)
 		goto end_coredump;
 
-	if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
+	if (!elf_core_write_extra_data(cprm))
 		goto end_coredump;
 
 	if (e_phnum == PN_XNUM) {
-		size += sizeof(*shdr4extnum);
-		if (size > cprm->limit
-		    || !dump_write(cprm->file, shdr4extnum,
-				   sizeof(*shdr4extnum)))
+		if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
 			goto end_coredump;
 	}
 
-	if (cprm->file->f_pos != offset) {
+	if (cprm->written != offset) {
 		/* Sanity check */
 		printk(KERN_WARNING
-		       "elf_core_dump: file->f_pos (%lld) != offset (%lld)\n",
-		       cprm->file->f_pos, offset);
+		       "elf_core_dump: cprm->written (%lld) != offset (%lld)\n",
+		       (long long)cprm->written, offset);
 	}
 
 end_coredump:
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c7bda5c..8772b15 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1542,7 +1542,7 @@ static ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
 		return 0;
 
 	size -= pos;
-	if (size < iocb->ki_left)
+	if (size < iocb->ki_nbytes)
 		nr_segs = iov_shorten((struct iovec *)iov, nr_segs, size);
 	return generic_file_aio_read(iocb, iov, nr_segs, pos);
 }
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 4253ad5..5f8f334 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -747,7 +747,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
 	WARN_ON(atomic_xchg(
 		&fs_info->mutually_exclusive_operation_running, 1));
 	task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
-	return PTR_RET(task);
+	return PTR_ERR_OR_ZERO(task);
 }
 
 static int btrfs_dev_replace_kthread(void *data)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6d1b93c..2987e17 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3166,7 +3166,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
 		found_key.type = BTRFS_INODE_ITEM_KEY;
 		found_key.offset = 0;
 		inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
-		ret = PTR_RET(inode);
+		ret = PTR_ERR_OR_ZERO(inode);
 		if (ret && ret != -ESTALE)
 			goto out;
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 78b8717..67a0853 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3302,7 +3302,7 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
 	}
 
 	tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance");
-	return PTR_RET(tsk);
+	return PTR_ERR_OR_ZERO(tsk);
 }
 
 int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index a40ceda..868b61d 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -793,6 +793,8 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
 	req->r_locked_dir = dir;
 	req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
 	req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
+	/* release LINK_SHARED on source inode (mds will lock it) */
+	req->r_old_inode_drop = CEPH_CAP_LINK_SHARED;
 	err = ceph_mdsc_do_request(mdsc, dir, req);
 	if (err) {
 		d_drop(dentry);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index f3a2abf..2f5edff 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1465,7 +1465,14 @@ static void ceph_vmtruncate_work(struct work_struct *work)
 	struct inode *inode = &ci->vfs_inode;
 
 	dout("vmtruncate_work %p\n", inode);
-	mutex_lock(&inode->i_mutex);
+	if (!mutex_trylock(&inode->i_mutex)) {
+		/*
+		 * the i_mutex can be hold by a writer who is waiting for
+		 * caps. wake up waiters, they will do pending vmtruncate.
+		 */
+		wake_up_all(&ci->i_cap_wq);
+		mutex_lock(&inode->i_mutex);
+	}
 	__ceph_do_pending_vmtruncate(inode);
 	mutex_unlock(&inode->i_mutex);
 	iput(inode);
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index e0b4ef3..a5ce62e 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -196,8 +196,10 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
 	r = ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, len,
 					  &dl.object_no, &dl.object_offset,
 					  &olen);
-	if (r < 0)
+	if (r < 0) {
+		up_read(&osdc->map_sem);
 		return -EIO;
+	}
 	dl.file_offset -= dl.object_offset;
 	dl.object_size = ceph_file_layout_object_size(ci->i_layout);
 	dl.block_size = ceph_file_layout_su(ci->i_layout);
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 45e57cc..fc6f4f3 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -43,17 +43,18 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
 	server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
 	if (IS_ERR(server->secmech.md5)) {
 		cifs_dbg(VFS, "could not allocate crypto md5\n");
-		return PTR_ERR(server->secmech.md5);
+		rc = PTR_ERR(server->secmech.md5);
+		server->secmech.md5 = NULL;
+		return rc;
 	}
 
 	size = sizeof(struct shash_desc) +
 			crypto_shash_descsize(server->secmech.md5);
 	server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
 	if (!server->secmech.sdescmd5) {
-		rc = -ENOMEM;
 		crypto_free_shash(server->secmech.md5);
 		server->secmech.md5 = NULL;
-		return rc;
+		return -ENOMEM;
 	}
 	server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
 	server->secmech.sdescmd5->shash.flags = 0x0;
@@ -421,7 +422,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
 		if (blobptr + attrsize > blobend)
 			break;
 		if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
-			if (!attrsize)
+			if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
 				break;
 			if (!ses->domainName) {
 				ses->domainName =
@@ -591,6 +592,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 
 static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
 {
+	int rc;
 	unsigned int size;
 
 	/* check if already allocated */
@@ -600,7 +602,9 @@ static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
 	server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
 	if (IS_ERR(server->secmech.hmacmd5)) {
 		cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
-		return PTR_ERR(server->secmech.hmacmd5);
+		rc = PTR_ERR(server->secmech.hmacmd5);
+		server->secmech.hmacmd5 = NULL;
+		return rc;
 	}
 
 	size = sizeof(struct shash_desc) +
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 4bdd547..85ea98d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -147,18 +147,17 @@ cifs_read_super(struct super_block *sb)
 		goto out_no_root;
 	}
 
+	if (cifs_sb_master_tcon(cifs_sb)->nocase)
+		sb->s_d_op = &cifs_ci_dentry_ops;
+	else
+		sb->s_d_op = &cifs_dentry_ops;
+
 	sb->s_root = d_make_root(inode);
 	if (!sb->s_root) {
 		rc = -ENOMEM;
 		goto out_no_root;
 	}
 
-	/* do that *after* d_make_root() - we want NULL ->d_op for root here */
-	if (cifs_sb_master_tcon(cifs_sb)->nocase)
-		sb->s_d_op = &cifs_ci_dentry_ops;
-	else
-		sb->s_d_op = &cifs_dentry_ops;
-
 #ifdef CONFIG_CIFS_NFSD_EXPORT
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 		cifs_dbg(FYI, "export ops supported\n");
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1fdc370..52ca861 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -44,6 +44,7 @@
 #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
 #define MAX_SERVER_SIZE 15
 #define MAX_SHARE_SIZE 80
+#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */
 #define MAX_USERNAME_SIZE 256	/* reasonable maximum for current servers */
 #define MAX_PASSWORD_SIZE 512	/* max for windows seems to be 256 wide chars */
 
@@ -369,6 +370,9 @@ struct smb_version_operations {
 	void (*generate_signingkey)(struct TCP_Server_Info *server);
 	int (*calc_signature)(struct smb_rqst *rqst,
 				   struct TCP_Server_Info *server);
+	int (*query_mf_symlink)(const unsigned char *path, char *pbuf,
+			unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
+			unsigned int xid);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index f7e584d..b29a012 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -497,5 +497,7 @@ void cifs_writev_complete(struct work_struct *work);
 struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
 						work_func_t complete);
 void cifs_writedata_release(struct kref *refcount);
-
+int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
+			unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
+			unsigned int xid);
 #endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index fa68813..d67c550 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1675,7 +1675,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			if (string == NULL)
 				goto out_nomem;
 
-			if (strnlen(string, 256) == 256) {
+			if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
+					== CIFS_MAX_DOMAINNAME_LEN) {
 				printk(KERN_WARNING "CIFS: domain name too"
 						    " long\n");
 				goto cifs_parse_mount_err;
@@ -2276,8 +2277,8 @@ cifs_put_smb_ses(struct cifs_ses *ses)
 
 #ifdef CONFIG_KEYS
 
-/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
-#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
+/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
 
 /* Populate username and pw fields from keyring if possible */
 static int
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 1e57f36..7e36ae3 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -647,6 +647,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
 				     oflags, &oplock, &cfile->fid.netfid, xid);
 		if (rc == 0) {
 			cifs_dbg(FYI, "posix reopen succeeded\n");
+			oparms.reconnect = true;
 			goto reopen_success;
 		}
 		/*
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index b83c3f5..562044f 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -305,67 +305,89 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
 }
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-		   const unsigned char *path,
-		   struct cifs_sb_info *cifs_sb, unsigned int xid)
+open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
+			unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
+			unsigned int xid)
 {
 	int rc;
 	int oplock = 0;
 	__u16 netfid = 0;
 	struct tcon_link *tlink;
-	struct cifs_tcon *pTcon;
+	struct cifs_tcon *ptcon;
 	struct cifs_io_parms io_parms;
-	u8 *buf;
-	char *pbuf;
-	unsigned int bytes_read = 0;
 	int buf_type = CIFS_NO_BUFFER;
-	unsigned int link_len = 0;
 	FILE_ALL_INFO file_info;
 
-	if (!CIFSCouldBeMFSymlink(fattr))
-		/* it's not a symlink */
-		return 0;
-
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
 		return PTR_ERR(tlink);
-	pTcon = tlink_tcon(tlink);
+	ptcon = tlink_tcon(tlink);
 
-	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+	rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ,
 			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
 			 cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
-	if (rc != 0)
-		goto out;
+	if (rc != 0) {
+		cifs_put_tlink(tlink);
+		return rc;
+	}
 
 	if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
-		CIFSSMBClose(xid, pTcon, netfid);
+		CIFSSMBClose(xid, ptcon, netfid);
+		cifs_put_tlink(tlink);
 		/* it's not a symlink */
-		goto out;
+		return rc;
 	}
 
-	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-	if (!buf) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	pbuf = buf;
 	io_parms.netfid = netfid;
 	io_parms.pid = current->tgid;
-	io_parms.tcon = pTcon;
+	io_parms.tcon = ptcon;
 	io_parms.offset = 0;
 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
 
-	rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
-	CIFSSMBClose(xid, pTcon, netfid);
-	if (rc != 0) {
-		kfree(buf);
+	rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, ptcon, netfid);
+	cifs_put_tlink(tlink);
+	return rc;
+}
+
+
+int
+CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		   const unsigned char *path,
+		   struct cifs_sb_info *cifs_sb, unsigned int xid)
+{
+	int rc = 0;
+	u8 *buf = NULL;
+	unsigned int link_len = 0;
+	unsigned int bytes_read = 0;
+	struct cifs_tcon *ptcon;
+
+	if (!CIFSCouldBeMFSymlink(fattr))
+		/* it's not a symlink */
+		return 0;
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf) {
+		rc = -ENOMEM;
 		goto out;
 	}
 
+	ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
+	if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
+		rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
+						 &bytes_read, cifs_sb, xid);
+	else
+		goto out;
+
+	if (rc != 0)
+		goto out;
+
+	if (bytes_read == 0) /* not a symlink */
+		goto out;
+
 	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
-	kfree(buf);
 	if (rc == -EINVAL) {
 		/* it's not a symlink */
 		rc = 0;
@@ -381,7 +403,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
 	fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
 	fattr->cf_dtype = DT_LNK;
 out:
-	cifs_put_tlink(tlink);
+	kfree(buf);
 	return rc;
 }
 
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index ab87784..69d2c82 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -111,6 +111,14 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
 			return;
 	}
 
+	/*
+	 * If we know that the inode will need to be revalidated immediately,
+	 * then don't create a new dentry for it. We'll end up doing an on
+	 * the wire call either way and this spares us an invalidation.
+	 */
+	if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+		return;
+
 	dentry = d_alloc(parent, name);
 	if (!dentry)
 		return;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 79358e3..08dd37b 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -197,7 +197,7 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
 		bytes_ret = 0;
 	} else
 		bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
-					    256, nls_cp);
+					    CIFS_MAX_DOMAINNAME_LEN, nls_cp);
 	bcc_ptr += 2 * bytes_ret;
 	bcc_ptr += 2;  /* account for null terminator */
 
@@ -255,8 +255,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
 
 	/* copy domain */
 	if (ses->domainName != NULL) {
-		strncpy(bcc_ptr, ses->domainName, 256);
-		bcc_ptr += strnlen(ses->domainName, 256);
+		strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+		bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
 	} /* else we will send a null domain name
 	     so the server will default to its own domain */
 	*bcc_ptr = 0;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 6457690..6094397 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -944,6 +944,7 @@ struct smb_version_operations smb1_operations = {
 	.mand_lock = cifs_mand_lock,
 	.mand_unlock_range = cifs_unlock_range,
 	.push_mand_locks = cifs_push_mandatory_locks,
+	.query_mf_symlink = open_query_close_cifs_symlink,
 };
 
 struct smb_version_values smb1_values = {
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 301b191..4f2300d 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -42,6 +42,7 @@
 static int
 smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
 {
+	int rc;
 	unsigned int size;
 
 	if (server->secmech.sdeschmacsha256 != NULL)
@@ -50,7 +51,9 @@ smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
 	server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
 	if (IS_ERR(server->secmech.hmacsha256)) {
 		cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
-		return PTR_ERR(server->secmech.hmacsha256);
+		rc = PTR_ERR(server->secmech.hmacsha256);
+		server->secmech.hmacsha256 = NULL;
+		return rc;
 	}
 
 	size = sizeof(struct shash_desc) +
@@ -87,7 +90,9 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
 		server->secmech.sdeschmacsha256 = NULL;
 		crypto_free_shash(server->secmech.hmacsha256);
 		server->secmech.hmacsha256 = NULL;
-		return PTR_ERR(server->secmech.cmacaes);
+		rc = PTR_ERR(server->secmech.cmacaes);
+		server->secmech.cmacaes = NULL;
+		return rc;
 	}
 
 	size = sizeof(struct shash_desc) +
diff --git a/fs/coredump.c b/fs/coredump.c
index 72f816d..fb4e2b7 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -675,45 +675,59 @@ fail:
 	return;
 }
 
-/*
- * Core dumping helper functions.  These are the only things you should
- * do on a core-file: use only these functions to write out all the
- * necessary info.
- */
-int dump_write(struct file *file, const void *addr, int nr)
+bool dump_emit(struct coredump_params *cprm, const void *addr, size_t size)
 {
-	return !dump_interrupted() &&
-		access_ok(VERIFY_READ, addr, nr) &&
-		file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+	struct file *file;
+	loff_t pos;
+	if (size > cprm->limit - cprm->written || dump_interrupted() ||
+	    !access_ok(VERIFY_READ, addr, size))
+		return false;
+	file = cprm->file;
+	pos = file->f_pos;
+	if (file->f_op->write(file, addr, size, &pos) != size)
+		return false;
+	file->f_pos = pos;
+	cprm->written += size;
+	return true;
 }
-EXPORT_SYMBOL(dump_write);
+EXPORT_SYMBOL(dump_emit);
 
-int dump_seek(struct file *file, loff_t off)
+bool dump_skip(struct coredump_params *cprm, size_t off)
 {
-	int ret = 1;
+	loff_t new = cprm->written + off;
+	struct file *file = cprm->file;
+
+	if (!off)
+		return true;
+
+	if (new > cprm->limit)
+		return false;
 
 	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
 		if (dump_interrupted() ||
-		    file->f_op->llseek(file, off, SEEK_CUR) < 0)
-			return 0;
+		    file->f_op->llseek(file, new, SEEK_SET) < 0)
+			return false;
+		cprm->written = new;
 	} else {
 		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
-
 		if (!buf)
-			return 0;
-		while (off > 0) {
+			return false;
+		while (off) {
 			unsigned long n = off;
-
 			if (n > PAGE_SIZE)
 				n = PAGE_SIZE;
-			if (!dump_write(file, buf, n)) {
-				ret = 0;
-				break;
-			}
+			if (!dump_emit(cprm, buf, n))
+				return false;
 			off -= n;
 		}
 		free_page((unsigned long)buf);
 	}
-	return ret;
+	return true;
+}
+EXPORT_SYMBOL(dump_skip);
+
+bool dump_align(struct coredump_params *cprm, int align)
+{
+	return dump_skip(cprm, roundup(cprm->written, align) - cprm->written);
 }
-EXPORT_SYMBOL(dump_seek);
+EXPORT_SYMBOL(dump_align);
diff --git a/fs/dcache.c b/fs/dcache.c
index 87bdb53..7489b6f 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -37,6 +37,7 @@
 #include <linux/rculist_bl.h>
 #include <linux/prefetch.h>
 #include <linux/ratelimit.h>
+#include <linux/list_lru.h>
 #include "internal.h"
 #include "mount.h"
 
@@ -48,7 +49,7 @@
  *   - the dcache hash table
  * s_anon bl list spinlock protects:
  *   - the s_anon list (see __d_drop)
- * dcache_lru_lock protects:
+ * dentry->d_sb->s_dentry_lru_lock protects:
  *   - the dcache lru lists and counters
  * d_lock protects:
  *   - d_flags
@@ -63,7 +64,7 @@
  * Ordering:
  * dentry->d_inode->i_lock
  *   dentry->d_lock
- *     dcache_lru_lock
+ *     dentry->d_sb->s_dentry_lru_lock
  *     dcache_hash_bucket lock
  *     s_anon lock
  *
@@ -81,7 +82,6 @@
 int sysctl_vfs_cache_pressure __read_mostly = 100;
 EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
 
-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock);
 __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
 
 EXPORT_SYMBOL(rename_lock);
@@ -117,23 +117,47 @@ struct dentry_stat_t dentry_stat = {
 	.age_limit = 45,
 };
 
-static DEFINE_PER_CPU(unsigned int, nr_dentry);
+static DEFINE_PER_CPU(long, nr_dentry);
+static DEFINE_PER_CPU(long, nr_dentry_unused);
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
-static int get_nr_dentry(void)
+
+/*
+ * Here we resort to our own counters instead of using generic per-cpu counters
+ * for consistency with what the vfs inode code does. We are expected to harvest
+ * better code and performance by having our own specialized counters.
+ *
+ * Please note that the loop is done over all possible CPUs, not over all online
+ * CPUs. The reason for this is that we don't want to play games with CPUs going
+ * on and off. If one of them goes off, we will just keep their counters.
+ *
+ * glommer: See cffbc8a for details, and if you ever intend to change this,
+ * please update all vfs counters to match.
+ */
+static long get_nr_dentry(void)
 {
 	int i;
-	int sum = 0;
+	long sum = 0;
 	for_each_possible_cpu(i)
 		sum += per_cpu(nr_dentry, i);
 	return sum < 0 ? 0 : sum;
 }
 
+static long get_nr_dentry_unused(void)
+{
+	int i;
+	long sum = 0;
+	for_each_possible_cpu(i)
+		sum += per_cpu(nr_dentry_unused, i);
+	return sum < 0 ? 0 : sum;
+}
+
 int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
 		   size_t *lenp, loff_t *ppos)
 {
 	dentry_stat.nr_dentry = get_nr_dentry();
-	return proc_dointvec(table, write, buffer, lenp, ppos);
+	dentry_stat.nr_unused = get_nr_dentry_unused();
+	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 }
 #endif
 
@@ -304,50 +328,31 @@ static void dentry_unlink_inode(struct dentry * dentry)
 }
 
 /*
- * dentry_lru_(add|del|prune|move_tail) must be called with d_lock held.
+ * dentry_lru_(add|del|move_list) must be called with d_lock held.
  */
 static void dentry_lru_add(struct dentry *dentry)
 {
-	if (list_empty(&dentry->d_lru)) {
-		spin_lock(&dcache_lru_lock);
-		list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
-		dentry->d_sb->s_nr_dentry_unused++;
-		dentry_stat.nr_unused++;
-		spin_unlock(&dcache_lru_lock);
-	}
-}
-
-static void __dentry_lru_del(struct dentry *dentry)
-{
-	list_del_init(&dentry->d_lru);
-	dentry->d_flags &= ~DCACHE_SHRINK_LIST;
-	dentry->d_sb->s_nr_dentry_unused--;
-	dentry_stat.nr_unused--;
+	if (list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru))
+		this_cpu_inc(nr_dentry_unused);
 }
 
 /*
  * Remove a dentry with references from the LRU.
+ *
+ * If we are on the shrink list, then we can get to try_prune_one_dentry() and
+ * lose our last reference through the parent walk. In this case, we need to
+ * remove ourselves from the shrink list, not the LRU.
  */
 static void dentry_lru_del(struct dentry *dentry)
 {
-	if (!list_empty(&dentry->d_lru)) {
-		spin_lock(&dcache_lru_lock);
-		__dentry_lru_del(dentry);
-		spin_unlock(&dcache_lru_lock);
+	if (dentry->d_flags & DCACHE_SHRINK_LIST) {
+		list_del_init(&dentry->d_lru);
+		dentry->d_flags &= ~DCACHE_SHRINK_LIST;
+		return;
 	}
-}
 
-static void dentry_lru_move_list(struct dentry *dentry, struct list_head *list)
-{
-	spin_lock(&dcache_lru_lock);
-	if (list_empty(&dentry->d_lru)) {
-		list_add_tail(&dentry->d_lru, list);
-		dentry->d_sb->s_nr_dentry_unused++;
-		dentry_stat.nr_unused++;
-	} else {
-		list_move_tail(&dentry->d_lru, list);
-	}
-	spin_unlock(&dcache_lru_lock);
+	if (list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru))
+		this_cpu_dec(nr_dentry_unused);
 }
 
 /**
@@ -443,7 +448,8 @@ EXPORT_SYMBOL(d_drop);
  * If ref is non-zero, then decrement the refcount too.
  * Returns dentry requiring refcount drop, or NULL if we're done.
  */
-static inline struct dentry *dentry_kill(struct dentry *dentry, int ref)
+static inline struct dentry *
+dentry_kill(struct dentry *dentry, int ref, int unlock_on_failure)
 	__releases(dentry->d_lock)
 {
 	struct inode *inode;
@@ -452,8 +458,10 @@ static inline struct dentry *dentry_kill(struct dentry *dentry, int ref)
 	inode = dentry->d_inode;
 	if (inode && !spin_trylock(&inode->i_lock)) {
 relock:
-		spin_unlock(&dentry->d_lock);
-		cpu_relax();
+		if (unlock_on_failure) {
+			spin_unlock(&dentry->d_lock);
+			cpu_relax();
+		}
 		return dentry; /* try again with same dentry */
 	}
 	if (IS_ROOT(dentry))
@@ -540,7 +548,7 @@ repeat:
 	return;
 
 kill_it:
-	dentry = dentry_kill(dentry, 1);
+	dentry = dentry_kill(dentry, 1, 1);
 	if (dentry)
 		goto repeat;
 }
@@ -739,12 +747,12 @@ EXPORT_SYMBOL(d_prune_aliases);
  *
  * This may fail if locks cannot be acquired no problem, just try again.
  */
-static void try_prune_one_dentry(struct dentry *dentry)
+static struct dentry * try_prune_one_dentry(struct dentry *dentry)
 	__releases(dentry->d_lock)
 {
 	struct dentry *parent;
 
-	parent = dentry_kill(dentry, 0);
+	parent = dentry_kill(dentry, 0, 0);
 	/*
 	 * If dentry_kill returns NULL, we have nothing more to do.
 	 * if it returns the same dentry, trylocks failed. In either
@@ -756,9 +764,9 @@ static void try_prune_one_dentry(struct dentry *dentry)
 	 * fragmentation.
 	 */
 	if (!parent)
-		return;
+		return NULL;
 	if (parent == dentry)
-		return;
+		return dentry;
 
 	/* Prune ancestors. */
 	dentry = parent;
@@ -767,10 +775,11 @@ static void try_prune_one_dentry(struct dentry *dentry)
 		if (dentry->d_count > 1) {
 			dentry->d_count--;
 			spin_unlock(&dentry->d_lock);
-			return;
+			return NULL;
 		}
-		dentry = dentry_kill(dentry, 1);
+		dentry = dentry_kill(dentry, 1, 1);
 	}
+	return NULL;
 }
 
 static void shrink_dentry_list(struct list_head *list)
@@ -789,76 +798,143 @@ static void shrink_dentry_list(struct list_head *list)
 		}
 
 		/*
+		 * The dispose list is isolated and dentries are not accounted
+		 * to the LRU here, so we can simply remove it from the list
+		 * here regardless of whether it is referenced or not.
+		 */
+		list_del_init(&dentry->d_lru);
+		dentry->d_flags &= ~DCACHE_SHRINK_LIST;
+
+		/*
 		 * We found an inuse dentry which was not removed from
-		 * the LRU because of laziness during lookup.  Do not free
-		 * it - just keep it off the LRU list.
+		 * the LRU because of laziness during lookup. Do not free it.
 		 */
 		if (dentry->d_count) {
-			dentry_lru_del(dentry);
 			spin_unlock(&dentry->d_lock);
 			continue;
 		}
-
 		rcu_read_unlock();
 
-		try_prune_one_dentry(dentry);
+		dentry = try_prune_one_dentry(dentry);
 
 		rcu_read_lock();
+		if (dentry) {
+			dentry->d_flags |= DCACHE_SHRINK_LIST;
+			list_add(&dentry->d_lru, list);
+			spin_unlock(&dentry->d_lock);
+		}
 	}
 	rcu_read_unlock();
 }
 
+static enum lru_status
+dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
+{
+	struct list_head *freeable = arg;
+	struct dentry	*dentry = container_of(item, struct dentry, d_lru);
+
+
+	/*
+	 * we are inverting the lru lock/dentry->d_lock here,
+	 * so use a trylock. If we fail to get the lock, just skip
+	 * it
+	 */
+	if (!spin_trylock(&dentry->d_lock))
+		return LRU_SKIP;
+
+	/*
+	 * Referenced dentries are still in use. If they have active
+	 * counts, just remove them from the LRU. Otherwise give them
+	 * another pass through the LRU.
+	 */
+	if (dentry->d_count) {
+		list_del_init(&dentry->d_lru);
+		spin_unlock(&dentry->d_lock);
+		return LRU_REMOVED;
+	}
+
+	if (dentry->d_flags & DCACHE_REFERENCED) {
+		dentry->d_flags &= ~DCACHE_REFERENCED;
+		spin_unlock(&dentry->d_lock);
+
+		/*
+		 * The list move itself will be made by the common LRU code. At
+		 * this point, we've dropped the dentry->d_lock but keep the
+		 * lru lock. This is safe to do, since every list movement is
+		 * protected by the lru lock even if both locks are held.
+		 *
+		 * This is guaranteed by the fact that all LRU management
+		 * functions are intermediated by the LRU API calls like
+		 * list_lru_add and list_lru_del. List movement in this file
+		 * only ever occur through this functions or through callbacks
+		 * like this one, that are called from the LRU API.
+		 *
+		 * The only exceptions to this are functions like
+		 * shrink_dentry_list, and code that first checks for the
+		 * DCACHE_SHRINK_LIST flag.  Those are guaranteed to be
+		 * operating only with stack provided lists after they are
+		 * properly isolated from the main list.  It is thus, always a
+		 * local access.
+		 */
+		return LRU_ROTATE;
+	}
+
+	dentry->d_flags |= DCACHE_SHRINK_LIST;
+	list_move_tail(&dentry->d_lru, freeable);
+	this_cpu_dec(nr_dentry_unused);
+	spin_unlock(&dentry->d_lock);
+
+	return LRU_REMOVED;
+}
+
 /**
  * prune_dcache_sb - shrink the dcache
  * @sb: superblock
- * @count: number of entries to try to free
+ * @nr_to_scan : number of entries to try to free
+ * @nid: which node to scan for freeable entities
  *
- * Attempt to shrink the superblock dcache LRU by @count entries. This is
+ * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is
  * done when we need more memory an called from the superblock shrinker
  * function.
  *
  * This function may fail to free any resources if all the dentries are in
  * use.
  */
-void prune_dcache_sb(struct super_block *sb, int count)
+long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan,
+		     int nid)
 {
-	struct dentry *dentry;
-	LIST_HEAD(referenced);
-	LIST_HEAD(tmp);
+	LIST_HEAD(dispose);
+	long freed;
 
-relock:
-	spin_lock(&dcache_lru_lock);
-	while (!list_empty(&sb->s_dentry_lru)) {
-		dentry = list_entry(sb->s_dentry_lru.prev,
-				struct dentry, d_lru);
-		BUG_ON(dentry->d_sb != sb);
-
-		if (!spin_trylock(&dentry->d_lock)) {
-			spin_unlock(&dcache_lru_lock);
-			cpu_relax();
-			goto relock;
-		}
+	freed = list_lru_walk_node(&sb->s_dentry_lru, nid, dentry_lru_isolate,
+				       &dispose, &nr_to_scan);
+	shrink_dentry_list(&dispose);
+	return freed;
+}
 
-		if (dentry->d_flags & DCACHE_REFERENCED) {
-			dentry->d_flags &= ~DCACHE_REFERENCED;
-			list_move(&dentry->d_lru, &referenced);
-			spin_unlock(&dentry->d_lock);
-		} else {
-			list_move_tail(&dentry->d_lru, &tmp);
-			dentry->d_flags |= DCACHE_SHRINK_LIST;
-			spin_unlock(&dentry->d_lock);
-			if (!--count)
-				break;
-		}
-		cond_resched_lock(&dcache_lru_lock);
-	}
-	if (!list_empty(&referenced))
-		list_splice(&referenced, &sb->s_dentry_lru);
-	spin_unlock(&dcache_lru_lock);
+static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
+						spinlock_t *lru_lock, void *arg)
+{
+	struct list_head *freeable = arg;
+	struct dentry	*dentry = container_of(item, struct dentry, d_lru);
+
+	/*
+	 * we are inverting the lru lock/dentry->d_lock here,
+	 * so use a trylock. If we fail to get the lock, just skip
+	 * it
+	 */
+	if (!spin_trylock(&dentry->d_lock))
+		return LRU_SKIP;
+
+	dentry->d_flags |= DCACHE_SHRINK_LIST;
+	list_move_tail(&dentry->d_lru, freeable);
+	this_cpu_dec(nr_dentry_unused);
+	spin_unlock(&dentry->d_lock);
 
-	shrink_dentry_list(&tmp);
+	return LRU_REMOVED;
 }
 
+
 /**
  * shrink_dcache_sb - shrink dcache for a superblock
  * @sb: superblock
@@ -868,16 +944,17 @@ relock:
  */
 void shrink_dcache_sb(struct super_block *sb)
 {
-	LIST_HEAD(tmp);
+	long freed;
 
-	spin_lock(&dcache_lru_lock);
-	while (!list_empty(&sb->s_dentry_lru)) {
-		list_splice_init(&sb->s_dentry_lru, &tmp);
-		spin_unlock(&dcache_lru_lock);
-		shrink_dentry_list(&tmp);
-		spin_lock(&dcache_lru_lock);
-	}
-	spin_unlock(&dcache_lru_lock);
+	do {
+		LIST_HEAD(dispose);
+
+		freed = list_lru_walk(&sb->s_dentry_lru,
+			dentry_lru_isolate_shrink, &dispose, UINT_MAX);
+
+		this_cpu_sub(nr_dentry_unused, freed);
+		shrink_dentry_list(&dispose);
+	} while (freed > 0);
 }
 EXPORT_SYMBOL(shrink_dcache_sb);
 
@@ -1150,7 +1227,8 @@ resume:
 		if (dentry->d_count) {
 			dentry_lru_del(dentry);
 		} else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
-			dentry_lru_move_list(dentry, dispose);
+			dentry_lru_del(dentry);
+			list_add_tail(&dentry->d_lru, dispose);
 			dentry->d_flags |= DCACHE_SHRINK_LIST;
 			found++;
 		}
@@ -1215,9 +1293,8 @@ rename_retry:
 void shrink_dcache_parent(struct dentry * parent)
 {
 	LIST_HEAD(dispose);
-	int found;
 
-	while ((found = select_parent(parent, &dispose)) != 0) {
+	while (select_parent(parent, &dispose)) {
 		shrink_dentry_list(&dispose);
 		cond_resched();
 	}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 4888cb3..c7c83ff 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -533,8 +533,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
  */
 void debugfs_remove_recursive(struct dentry *dentry)
 {
-	struct dentry *child;
-	struct dentry *parent;
+	struct dentry *child, *next, *parent;
 
 	if (IS_ERR_OR_NULL(dentry))
 		return;
@@ -544,61 +543,37 @@ void debugfs_remove_recursive(struct dentry *dentry)
 		return;
 
 	parent = dentry;
+ down:
 	mutex_lock(&parent->d_inode->i_mutex);
+	list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
+		if (!debugfs_positive(child))
+			continue;
 
-	while (1) {
-		/*
-		 * When all dentries under "parent" has been removed,
-		 * walk up the tree until we reach our starting point.
-		 */
-		if (list_empty(&parent->d_subdirs)) {
-			mutex_unlock(&parent->d_inode->i_mutex);
-			if (parent == dentry)
-				break;
-			parent = parent->d_parent;
-			mutex_lock(&parent->d_inode->i_mutex);
-		}
-		child = list_entry(parent->d_subdirs.next, struct dentry,
-				d_u.d_child);
- next_sibling:
-
-		/*
-		 * If "child" isn't empty, walk down the tree and
-		 * remove all its descendants first.
-		 */
+		/* perhaps simple_empty(child) makes more sense */
 		if (!list_empty(&child->d_subdirs)) {
 			mutex_unlock(&parent->d_inode->i_mutex);
 			parent = child;
-			mutex_lock(&parent->d_inode->i_mutex);
-			continue;
+			goto down;
 		}
-		__debugfs_remove(child, parent);
-		if (parent->d_subdirs.next == &child->d_u.d_child) {
-			/*
-			 * Try the next sibling.
-			 */
-			if (child->d_u.d_child.next != &parent->d_subdirs) {
-				child = list_entry(child->d_u.d_child.next,
-						   struct dentry,
-						   d_u.d_child);
-				goto next_sibling;
-			}
-
-			/*
-			 * Avoid infinite loop if we fail to remove
-			 * one dentry.
-			 */
-			mutex_unlock(&parent->d_inode->i_mutex);
-			break;
-		}
-		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+ up:
+		if (!__debugfs_remove(child, parent))
+			simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 	}
 
-	parent = dentry->d_parent;
+	mutex_unlock(&parent->d_inode->i_mutex);
+	child = parent;
+	parent = parent->d_parent;
 	mutex_lock(&parent->d_inode->i_mutex);
-	__debugfs_remove(dentry, parent);
+
+	if (child != dentry) {
+		next = list_entry(child->d_u.d_child.next, struct dentry,
+					d_u.d_child);
+		goto up;
+	}
+
+	if (!__debugfs_remove(child, parent))
+		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 	mutex_unlock(&parent->d_inode->i_mutex);
-	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
 
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 27a6ba9..0e90f0c 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -267,10 +267,7 @@ void dlm_callback_work(struct work_struct *work)
 int dlm_callback_start(struct dlm_ls *ls)
 {
 	ls->ls_callback_wq = alloc_workqueue("dlm_callback",
-					     WQ_UNBOUND |
-					     WQ_MEM_RECLAIM |
-					     WQ_NON_REENTRANT,
-					     0);
+					     WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
 	if (!ls->ls_callback_wq) {
 		log_print("can't start dlm_callback workqueue");
 		return -ENOMEM;
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index c00e055..9fd702f 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -44,6 +44,7 @@ static void drop_slab(void)
 		.gfp_mask = GFP_KERNEL,
 	};
 
+	nodes_setall(shrink.nodes_to_scan);
 	do {
 		nr_objects = shrink_slab(&shrink, 1000, 1000);
 	} while (nr_objects > 10);
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 9ad17b15..d5e7de0 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1966,23 +1966,23 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
 		size_t, sigsetsize)
 {
 	int error;
-	sigset_t ksigmask, sigsaved;
-
 	/*
 	 * If the caller wants a certain signal mask to be set during the wait,
 	 * we apply it here.
 	 */
 	if (sigmask) {
+		sigset_t ksigmask;
+
 		if (sigsetsize != sizeof(sigset_t))
 			return -EINVAL;
 		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
 			return -EFAULT;
-		sigsaved = current->blocked;
+
+		current->saved_sigmask = current->blocked;
 		set_current_blocked(&ksigmask);
 	}
 
 	error = sys_epoll_wait(epfd, events, maxevents, timeout);
-
 	/*
 	 * If we changed the signal mask, we need to restore the original one.
 	 * In case we've got a signal while waiting, we do not restore the
@@ -1990,12 +1990,10 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
 	 * the way back to userspace, before the signal mask is restored.
 	 */
 	if (sigmask) {
-		if (error == -EINTR) {
-			memcpy(&current->saved_sigmask, &sigsaved,
-			       sizeof(sigsaved));
+		if (error == -EINTR)
 			set_restore_sigmask();
-		} else
-			set_current_blocked(&sigsaved);
+		else
+			__set_current_blocked(&current->saved_sigmask);
 	}
 
 	return error;
@@ -2009,25 +2007,25 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
 			compat_size_t, sigsetsize)
 {
 	long err;
-	compat_sigset_t csigmask;
-	sigset_t ksigmask, sigsaved;
-
 	/*
 	 * If the caller wants a certain signal mask to be set during the wait,
 	 * we apply it here.
 	 */
 	if (sigmask) {
+		compat_sigset_t csigmask;
+		sigset_t ksigmask;
+
 		if (sigsetsize != sizeof(compat_sigset_t))
 			return -EINVAL;
 		if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
 			return -EFAULT;
 		sigset_from_compat(&ksigmask, &csigmask);
-		sigsaved = current->blocked;
+
+		current->saved_sigmask = current->blocked;
 		set_current_blocked(&ksigmask);
 	}
 
 	err = sys_epoll_wait(epfd, events, maxevents, timeout);
-
 	/*
 	 * If we changed the signal mask, we need to restore the original one.
 	 * In case we've got a signal while waiting, we do not restore the
@@ -2035,12 +2033,10 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
 	 * the way back to userspace, before the signal mask is restored.
 	 */
 	if (sigmask) {
-		if (err == -EINTR) {
-			memcpy(&current->saved_sigmask, &sigsaved,
-			       sizeof(sigsaved));
+		if (err == -EINTR)
 			set_restore_sigmask();
-		} else
-			set_current_blocked(&sigsaved);
+		else
+			__set_current_blocked(&current->saved_sigmask);
 	}
 
 	return err;
diff --git a/fs/exec.c b/fs/exec.c
index 9c73def..eb2f05a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -74,6 +74,8 @@ static DEFINE_RWLOCK(binfmt_lock);
 void __register_binfmt(struct linux_binfmt * fmt, int insert)
 {
 	BUG_ON(!fmt);
+	if (WARN_ON(!fmt->load_binary))
+		return;
 	write_lock(&binfmt_lock);
 	insert ? list_add(&fmt->lh, &formats) :
 		 list_add_tail(&fmt->lh, &formats);
@@ -1365,18 +1367,18 @@ out:
 }
 EXPORT_SYMBOL(remove_arg_zero);
 
+#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
 /*
  * cycle the list of binary formats handler, until one recognizes the image
  */
 int search_binary_handler(struct linux_binprm *bprm)
 {
-	unsigned int depth = bprm->recursion_depth;
-	int try,retval;
+	bool need_retry = IS_ENABLED(CONFIG_MODULES);
 	struct linux_binfmt *fmt;
-	pid_t old_pid, old_vpid;
+	int retval;
 
 	/* This allows 4 levels of binfmt rewrites before failing hard. */
-	if (depth > 5)
+	if (bprm->recursion_depth > 5)
 		return -ELOOP;
 
 	retval = security_bprm_check(bprm);
@@ -1387,71 +1389,67 @@ int search_binary_handler(struct linux_binprm *bprm)
 	if (retval)
 		return retval;
 
+	retval = -ENOENT;
+ retry:
+	read_lock(&binfmt_lock);
+	list_for_each_entry(fmt, &formats, lh) {
+		if (!try_module_get(fmt->module))
+			continue;
+		read_unlock(&binfmt_lock);
+		bprm->recursion_depth++;
+		retval = fmt->load_binary(bprm);
+		bprm->recursion_depth--;
+		if (retval >= 0 || retval != -ENOEXEC ||
+		    bprm->mm == NULL || bprm->file == NULL) {
+			put_binfmt(fmt);
+			return retval;
+		}
+		read_lock(&binfmt_lock);
+		put_binfmt(fmt);
+	}
+	read_unlock(&binfmt_lock);
+
+	if (need_retry && retval == -ENOEXEC) {
+		if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
+		    printable(bprm->buf[2]) && printable(bprm->buf[3]))
+			return retval;
+		if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0)
+			return retval;
+		need_retry = false;
+		goto retry;
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL(search_binary_handler);
+
+static int exec_binprm(struct linux_binprm *bprm)
+{
+	pid_t old_pid, old_vpid;
+	int ret;
+
 	/* Need to fetch pid before load_binary changes it */
 	old_pid = current->pid;
 	rcu_read_lock();
 	old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
 	rcu_read_unlock();
 
-	retval = -ENOENT;
-	for (try=0; try<2; try++) {
-		read_lock(&binfmt_lock);
-		list_for_each_entry(fmt, &formats, lh) {
-			int (*fn)(struct linux_binprm *) = fmt->load_binary;
-			if (!fn)
-				continue;
-			if (!try_module_get(fmt->module))
-				continue;
-			read_unlock(&binfmt_lock);
-			bprm->recursion_depth = depth + 1;
-			retval = fn(bprm);
-			bprm->recursion_depth = depth;
-			if (retval >= 0) {
-				if (depth == 0) {
-					trace_sched_process_exec(current, old_pid, bprm);
-					ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
-				}
-				put_binfmt(fmt);
-				allow_write_access(bprm->file);
-				if (bprm->file)
-					fput(bprm->file);
-				bprm->file = NULL;
-				current->did_exec = 1;
-				proc_exec_connector(current);
-				return retval;
-			}
-			read_lock(&binfmt_lock);
-			put_binfmt(fmt);
-			if (retval != -ENOEXEC || bprm->mm == NULL)
-				break;
-			if (!bprm->file) {
-				read_unlock(&binfmt_lock);
-				return retval;
-			}
+	ret = search_binary_handler(bprm);
+	if (ret >= 0) {
+		trace_sched_process_exec(current, old_pid, bprm);
+		ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
+		current->did_exec = 1;
+		proc_exec_connector(current);
+
+		if (bprm->file) {
+			allow_write_access(bprm->file);
+			fput(bprm->file);
+			bprm->file = NULL; /* to catch use-after-free */
 		}
-		read_unlock(&binfmt_lock);
-#ifdef CONFIG_MODULES
-		if (retval != -ENOEXEC || bprm->mm == NULL) {
-			break;
-		} else {
-#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
-			if (printable(bprm->buf[0]) &&
-			    printable(bprm->buf[1]) &&
-			    printable(bprm->buf[2]) &&
-			    printable(bprm->buf[3]))
-				break; /* -ENOEXEC */
-			if (try)
-				break; /* -ENOEXEC */
-			request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2]));
-		}
-#else
-		break;
-#endif
 	}
-	return retval;
-}
 
-EXPORT_SYMBOL(search_binary_handler);
+	return ret;
+}
 
 /*
  * sys_execve() executes a new program.
@@ -1541,7 +1539,7 @@ static int do_execve_common(const char *filename,
 	if (retval < 0)
 		goto out;
 
-	retval = search_binary_handler(bprm);
+	retval = exec_binprm(bprm);
 	if (retval < 0)
 		goto out;
 
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index c47f147..c50c761 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -27,6 +27,7 @@
 #include <linux/seq_file.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
+#include <linux/namei.h>
 
 #include <asm/uaccess.h>
 
@@ -819,6 +820,7 @@ enum {
 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
 	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
 	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
+	Opt_journal_path,
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
 	Opt_data_err_abort, Opt_data_err_ignore,
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
@@ -860,6 +862,7 @@ static const match_table_t tokens = {
 	{Opt_journal_update, "journal=update"},
 	{Opt_journal_inum, "journal=%u"},
 	{Opt_journal_dev, "journal_dev=%u"},
+	{Opt_journal_path, "journal_path=%s"},
 	{Opt_abort, "abort"},
 	{Opt_data_journal, "data=journal"},
 	{Opt_data_ordered, "data=ordered"},
@@ -975,6 +978,11 @@ static int parse_options (char *options, struct super_block *sb,
 	int option;
 	kuid_t uid;
 	kgid_t gid;
+	char *journal_path;
+	struct inode *journal_inode;
+	struct path path;
+	int error;
+
 #ifdef CONFIG_QUOTA
 	int qfmt;
 #endif
@@ -1129,6 +1137,41 @@ static int parse_options (char *options, struct super_block *sb,
 				return 0;
 			*journal_devnum = option;
 			break;
+		case Opt_journal_path:
+			if (is_remount) {
+				ext3_msg(sb, KERN_ERR, "error: cannot specify "
+				       "journal on remount");
+				return 0;
+			}
+
+			journal_path = match_strdup(&args[0]);
+			if (!journal_path) {
+				ext3_msg(sb, KERN_ERR, "error: could not dup "
+					"journal device string");
+				return 0;
+			}
+
+			error = kern_path(journal_path, LOOKUP_FOLLOW, &path);
+			if (error) {
+				ext3_msg(sb, KERN_ERR, "error: could not find "
+					"journal device path: error %d", error);
+				kfree(journal_path);
+				return 0;
+			}
+
+			journal_inode = path.dentry->d_inode;
+			if (!S_ISBLK(journal_inode->i_mode)) {
+				ext3_msg(sb, KERN_ERR, "error: journal path %s "
+					"is not a block device", journal_path);
+				path_put(&path);
+				kfree(journal_path);
+				return 0;
+			}
+
+			*journal_devnum = new_encode_dev(journal_inode->i_rdev);
+			path_put(&path);
+			kfree(journal_path);
+			break;
 		case Opt_noload:
 			set_opt (sbi->s_mount_opt, NOLOAD);
 			break;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index b577e45..953f504 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -561,6 +561,18 @@ enum {
 #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
 
 /*
+ * The bit position of these flags must not overlap with any of the
+ * EXT4_GET_BLOCKS_*.  They are used by ext4_ext_find_extent(),
+ * read_extent_tree_block(), ext4_split_extent_at(),
+ * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf().
+ * EXT4_EX_NOCACHE is used to indicate that the we shouldn't be
+ * caching the extents when reading from the extent tree while a
+ * truncate or punch hole operation is in progress.
+ */
+#define EXT4_EX_NOCACHE				0x0400
+#define EXT4_EX_FORCE_CACHE			0x0800
+
+/*
  * Flags used by ext4_free_blocks
  */
 #define EXT4_FREE_BLOCKS_METADATA	0x0001
@@ -590,6 +602,7 @@ enum {
 #define EXT4_IOC_MOVE_EXT		_IOWR('f', 15, struct move_extent)
 #define EXT4_IOC_RESIZE_FS		_IOW('f', 16, __u64)
 #define EXT4_IOC_SWAP_BOOT		_IO('f', 17)
+#define EXT4_IOC_PRECACHE_EXTENTS	_IO('f', 18)
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /*
@@ -1375,6 +1388,7 @@ enum {
 					   nolocking */
 	EXT4_STATE_MAY_INLINE_DATA,	/* may have in-inode data */
 	EXT4_STATE_ORDERED_MODE,	/* data=ordered mode */
+	EXT4_STATE_EXT_PRECACHED,	/* extents have been precached */
 };
 
 #define EXT4_INODE_BIT_FNS(name, field, offset)				\
@@ -2683,7 +2697,8 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
 				  struct ext4_ext_path *,
 				  struct ext4_extent *, int);
 extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
-						  struct ext4_ext_path *);
+						  struct ext4_ext_path *,
+						  int flags);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
 extern int ext4_ext_check_inode(struct inode *inode);
 extern int ext4_find_delalloc_range(struct inode *inode,
@@ -2692,7 +2707,7 @@ extern int ext4_find_delalloc_range(struct inode *inode,
 extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
 extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 			__u64 start, __u64 len);
-
+extern int ext4_ext_precache(struct inode *inode);
 
 /* move_extent.c */
 extern void ext4_double_down_write_data_sem(struct inode *first,
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index a618738..093f5b3 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -407,7 +407,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
 
 static int __ext4_ext_check(const char *function, unsigned int line,
 			    struct inode *inode, struct ext4_extent_header *eh,
-			    int depth)
+			    int depth, ext4_fsblk_t pblk)
 {
 	const char *error_msg;
 	int max = 0;
@@ -447,42 +447,149 @@ static int __ext4_ext_check(const char *function, unsigned int line,
 
 corrupted:
 	ext4_error_inode(inode, function, line, 0,
-			"bad header/extent: %s - magic %x, "
-			"entries %u, max %u(%u), depth %u(%u)",
-			error_msg, le16_to_cpu(eh->eh_magic),
-			le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
-			max, le16_to_cpu(eh->eh_depth), depth);
-
+			 "pblk %llu bad header/extent: %s - magic %x, "
+			 "entries %u, max %u(%u), depth %u(%u)",
+			 (unsigned long long) pblk, error_msg,
+			 le16_to_cpu(eh->eh_magic),
+			 le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
+			 max, le16_to_cpu(eh->eh_depth), depth);
 	return -EIO;
 }
 
-#define ext4_ext_check(inode, eh, depth)	\
-	__ext4_ext_check(__func__, __LINE__, inode, eh, depth)
+#define ext4_ext_check(inode, eh, depth, pblk)			\
+	__ext4_ext_check(__func__, __LINE__, (inode), (eh), (depth), (pblk))
 
 int ext4_ext_check_inode(struct inode *inode)
 {
-	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
+	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode), 0);
 }
 
-static int __ext4_ext_check_block(const char *function, unsigned int line,
-				  struct inode *inode,
-				  struct ext4_extent_header *eh,
-				  int depth,
-				  struct buffer_head *bh)
+static struct buffer_head *
+__read_extent_tree_block(const char *function, unsigned int line,
+			 struct inode *inode, ext4_fsblk_t pblk, int depth,
+			 int flags)
 {
-	int ret;
+	struct buffer_head		*bh;
+	int				err;
 
-	if (buffer_verified(bh))
-		return 0;
-	ret = ext4_ext_check(inode, eh, depth);
-	if (ret)
-		return ret;
+	bh = sb_getblk(inode->i_sb, pblk);
+	if (unlikely(!bh))
+		return ERR_PTR(-ENOMEM);
+
+	if (!bh_uptodate_or_lock(bh)) {
+		trace_ext4_ext_load_extent(inode, pblk, _RET_IP_);
+		err = bh_submit_read(bh);
+		if (err < 0)
+			goto errout;
+	}
+	if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
+		return bh;
+	err = __ext4_ext_check(function, line, inode,
+			       ext_block_hdr(bh), depth, pblk);
+	if (err)
+		goto errout;
 	set_buffer_verified(bh);
-	return ret;
+	/*
+	 * If this is a leaf block, cache all of its entries
+	 */
+	if (!(flags & EXT4_EX_NOCACHE) && depth == 0) {
+		struct ext4_extent_header *eh = ext_block_hdr(bh);
+		struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
+		ext4_lblk_t prev = 0;
+		int i;
+
+		for (i = le16_to_cpu(eh->eh_entries); i > 0; i--, ex++) {
+			unsigned int status = EXTENT_STATUS_WRITTEN;
+			ext4_lblk_t lblk = le32_to_cpu(ex->ee_block);
+			int len = ext4_ext_get_actual_len(ex);
+
+			if (prev && (prev != lblk))
+				ext4_es_cache_extent(inode, prev,
+						     lblk - prev, ~0,
+						     EXTENT_STATUS_HOLE);
+
+			if (ext4_ext_is_uninitialized(ex))
+				status = EXTENT_STATUS_UNWRITTEN;
+			ext4_es_cache_extent(inode, lblk, len,
+					     ext4_ext_pblock(ex), status);
+			prev = lblk + len;
+		}
+	}
+	return bh;
+errout:
+	put_bh(bh);
+	return ERR_PTR(err);
+
 }
 
-#define ext4_ext_check_block(inode, eh, depth, bh)	\
-	__ext4_ext_check_block(__func__, __LINE__, inode, eh, depth, bh)
+#define read_extent_tree_block(inode, pblk, depth, flags)		\
+	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk),   \
+				 (depth), (flags))
+
+/*
+ * This function is called to cache a file's extent information in the
+ * extent status tree
+ */
+int ext4_ext_precache(struct inode *inode)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct ext4_ext_path *path = NULL;
+	struct buffer_head *bh = 0;
+	int i = 0, depth, ret = 0;
+
+	if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+		return 0;	/* not an extent-mapped inode */
+
+	down_read(&ei->i_data_sem);
+	depth = ext_depth(inode);
+
+	path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
+		       GFP_NOFS);
+	if (path == NULL) {
+		up_read(&ei->i_data_sem);
+		return -ENOMEM;
+	}
+
+	/* Don't cache anything if there are no external extent blocks */
+	if (depth == 0)
+		goto out;
+	path[0].p_hdr = ext_inode_hdr(inode);
+	ret = ext4_ext_check(inode, path[0].p_hdr, depth, 0);
+	if (ret)
+		goto out;
+	path[0].p_idx = EXT_FIRST_INDEX(path[0].p_hdr);
+	while (i >= 0) {
+		/*
+		 * If this is a leaf block or we've reached the end of
+		 * the index block, go up
+		 */
+		if ((i == depth) ||
+		    path[i].p_idx > EXT_LAST_INDEX(path[i].p_hdr)) {
+			brelse(path[i].p_bh);
+			path[i].p_bh = NULL;
+			i--;
+			continue;
+		}
+		bh = read_extent_tree_block(inode,
+					    ext4_idx_pblock(path[i].p_idx++),
+					    depth - i - 1,
+					    EXT4_EX_FORCE_CACHE);
+		if (IS_ERR(bh)) {
+			ret = PTR_ERR(bh);
+			break;
+		}
+		i++;
+		path[i].p_bh = bh;
+		path[i].p_hdr = ext_block_hdr(bh);
+		path[i].p_idx = EXT_FIRST_INDEX(path[i].p_hdr);
+	}
+	ext4_set_inode_state(inode, EXT4_STATE_EXT_PRECACHED);
+out:
+	up_read(&ei->i_data_sem);
+	ext4_ext_drop_refs(path);
+	kfree(path);
+	return ret;
+}
 
 #ifdef EXT_DEBUG
 static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
@@ -716,7 +823,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
 
 struct ext4_ext_path *
 ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
-					struct ext4_ext_path *path)
+		     struct ext4_ext_path *path, int flags)
 {
 	struct ext4_extent_header *eh;
 	struct buffer_head *bh;
@@ -748,20 +855,13 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 		path[ppos].p_depth = i;
 		path[ppos].p_ext = NULL;
 
-		bh = sb_getblk(inode->i_sb, path[ppos].p_block);
-		if (unlikely(!bh)) {
-			ret = -ENOMEM;
+		bh = read_extent_tree_block(inode, path[ppos].p_block, --i,
+					    flags);
+		if (IS_ERR(bh)) {
+			ret = PTR_ERR(bh);
 			goto err;
 		}
-		if (!bh_uptodate_or_lock(bh)) {
-			trace_ext4_ext_load_extent(inode, block,
-						path[ppos].p_block);
-			ret = bh_submit_read(bh);
-			if (ret < 0) {
-				put_bh(bh);
-				goto err;
-			}
-		}
+
 		eh = ext_block_hdr(bh);
 		ppos++;
 		if (unlikely(ppos > depth)) {
@@ -773,11 +873,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 		}
 		path[ppos].p_bh = bh;
 		path[ppos].p_hdr = eh;
-		i--;
-
-		ret = ext4_ext_check_block(inode, eh, i, bh);
-		if (ret < 0)
-			goto err;
 	}
 
 	path[ppos].p_depth = i;
@@ -1198,7 +1293,8 @@ out:
  * if no free index is found, then it requests in-depth growing.
  */
 static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
-				    unsigned int flags,
+				    unsigned int mb_flags,
+				    unsigned int gb_flags,
 				    struct ext4_ext_path *path,
 				    struct ext4_extent *newext)
 {
@@ -1220,7 +1316,7 @@ repeat:
 	if (EXT_HAS_FREE_INDEX(curp)) {
 		/* if we found index with free entry, then use that
 		 * entry: create all needed subtree and add new leaf */
-		err = ext4_ext_split(handle, inode, flags, path, newext, i);
+		err = ext4_ext_split(handle, inode, mb_flags, path, newext, i);
 		if (err)
 			goto out;
 
@@ -1228,12 +1324,12 @@ repeat:
 		ext4_ext_drop_refs(path);
 		path = ext4_ext_find_extent(inode,
 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
-				    path);
+				    path, gb_flags);
 		if (IS_ERR(path))
 			err = PTR_ERR(path);
 	} else {
 		/* tree is full, time to grow in depth */
-		err = ext4_ext_grow_indepth(handle, inode, flags, newext);
+		err = ext4_ext_grow_indepth(handle, inode, mb_flags, newext);
 		if (err)
 			goto out;
 
@@ -1241,7 +1337,7 @@ repeat:
 		ext4_ext_drop_refs(path);
 		path = ext4_ext_find_extent(inode,
 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
-				    path);
+				    path, gb_flags);
 		if (IS_ERR(path)) {
 			err = PTR_ERR(path);
 			goto out;
@@ -1412,29 +1508,21 @@ got_index:
 	ix++;
 	block = ext4_idx_pblock(ix);
 	while (++depth < path->p_depth) {
-		bh = sb_bread(inode->i_sb, block);
-		if (bh == NULL)
-			return -EIO;
-		eh = ext_block_hdr(bh);
 		/* subtract from p_depth to get proper eh_depth */
-		if (ext4_ext_check_block(inode, eh,
-					 path->p_depth - depth, bh)) {
-			put_bh(bh);
-			return -EIO;
-		}
+		bh = read_extent_tree_block(inode, block,
+					    path->p_depth - depth, 0);
+		if (IS_ERR(bh))
+			return PTR_ERR(bh);
+		eh = ext_block_hdr(bh);
 		ix = EXT_FIRST_INDEX(eh);
 		block = ext4_idx_pblock(ix);
 		put_bh(bh);
 	}
 
-	bh = sb_bread(inode->i_sb, block);
-	if (bh == NULL)
-		return -EIO;
+	bh = read_extent_tree_block(inode, block, path->p_depth - depth, 0);
+	if (IS_ERR(bh))
+		return PTR_ERR(bh);
 	eh = ext_block_hdr(bh);
-	if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) {
-		put_bh(bh);
-		return -EIO;
-	}
 	ex = EXT_FIRST_EXTENT(eh);
 found_extent:
 	*logical = le32_to_cpu(ex->ee_block);
@@ -1793,7 +1881,7 @@ out:
  */
 int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 				struct ext4_ext_path *path,
-				struct ext4_extent *newext, int flag)
+				struct ext4_extent *newext, int gb_flags)
 {
 	struct ext4_extent_header *eh;
 	struct ext4_extent *ex, *fex;
@@ -1802,7 +1890,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	int depth, len, err;
 	ext4_lblk_t next;
 	unsigned uninitialized = 0;
-	int flags = 0;
+	int mb_flags = 0;
 
 	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
 		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
@@ -1817,7 +1905,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	}
 
 	/* try to insert block into found extent and return */
-	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) {
+	if (ex && !(gb_flags & EXT4_GET_BLOCKS_PRE_IO)) {
 
 		/*
 		 * Try to see whether we should rather test the extent on
@@ -1920,7 +2008,7 @@ prepend:
 	if (next != EXT_MAX_BLOCKS) {
 		ext_debug("next leaf block - %u\n", next);
 		BUG_ON(npath != NULL);
-		npath = ext4_ext_find_extent(inode, next, NULL);
+		npath = ext4_ext_find_extent(inode, next, NULL, 0);
 		if (IS_ERR(npath))
 			return PTR_ERR(npath);
 		BUG_ON(npath->p_depth != path->p_depth);
@@ -1939,9 +2027,10 @@ prepend:
 	 * There is no free space in the found leaf.
 	 * We're gonna add a new leaf in the tree.
 	 */
-	if (flag & EXT4_GET_BLOCKS_METADATA_NOFAIL)
-		flags = EXT4_MB_USE_RESERVED;
-	err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext);
+	if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+		mb_flags = EXT4_MB_USE_RESERVED;
+	err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
+				       path, newext);
 	if (err)
 		goto cleanup;
 	depth = ext_depth(inode);
@@ -2007,7 +2096,7 @@ has_space:
 
 merge:
 	/* try to merge extents */
-	if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
+	if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
 		ext4_ext_try_to_merge(handle, inode, path, nearex);
 
 
@@ -2050,7 +2139,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
 			path = NULL;
 		}
 
-		path = ext4_ext_find_extent(inode, block, path);
+		path = ext4_ext_find_extent(inode, block, path, 0);
 		if (IS_ERR(path)) {
 			up_read(&EXT4_I(inode)->i_data_sem);
 			err = PTR_ERR(path);
@@ -2712,7 +2801,7 @@ again:
 		ext4_lblk_t ee_block;
 
 		/* find extent for this block */
-		path = ext4_ext_find_extent(inode, end, NULL);
+		path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
 		if (IS_ERR(path)) {
 			ext4_journal_stop(handle);
 			return PTR_ERR(path);
@@ -2754,6 +2843,7 @@ again:
 			 */
 			err = ext4_split_extent_at(handle, inode, path,
 					end + 1, split_flag,
+					EXT4_EX_NOCACHE |
 					EXT4_GET_BLOCKS_PRE_IO |
 					EXT4_GET_BLOCKS_METADATA_NOFAIL);
 
@@ -2782,7 +2872,7 @@ again:
 		path[0].p_hdr = ext_inode_hdr(inode);
 		i = 0;
 
-		if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
+		if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) {
 			err = -EIO;
 			goto out;
 		}
@@ -2829,10 +2919,12 @@ again:
 			ext_debug("move to level %d (block %llu)\n",
 				  i + 1, ext4_idx_pblock(path[i].p_idx));
 			memset(path + i + 1, 0, sizeof(*path));
-			bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx));
-			if (!bh) {
+			bh = read_extent_tree_block(inode,
+				ext4_idx_pblock(path[i].p_idx), depth - i - 1,
+				EXT4_EX_NOCACHE);
+			if (IS_ERR(bh)) {
 				/* should we reset i_size? */
-				err = -EIO;
+				err = PTR_ERR(bh);
 				break;
 			}
 			/* Yield here to deal with large extent trees.
@@ -2842,11 +2934,6 @@ again:
 				err = -EIO;
 				break;
 			}
-			if (ext4_ext_check_block(inode, ext_block_hdr(bh),
-							depth - i - 1, bh)) {
-				err = -EIO;
-				break;
-			}
 			path[i + 1].p_bh = bh;
 
 			/* save actual number of indexes since this
@@ -3181,7 +3268,7 @@ static int ext4_split_extent(handle_t *handle,
 	 * result in split of original leaf or extent zeroout.
 	 */
 	ext4_ext_drop_refs(path);
-	path = ext4_ext_find_extent(inode, map->m_lblk, path);
+	path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 	depth = ext_depth(inode);
@@ -3565,7 +3652,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
 		if (err < 0)
 			goto out;
 		ext4_ext_drop_refs(path);
-		path = ext4_ext_find_extent(inode, map->m_lblk, path);
+		path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
 		if (IS_ERR(path)) {
 			err = PTR_ERR(path);
 			goto out;
@@ -4052,7 +4139,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
 
 	/* find extent for this block */
-	path = ext4_ext_find_extent(inode, map->m_lblk, NULL);
+	path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0);
 	if (IS_ERR(path)) {
 		err = PTR_ERR(path);
 		path = NULL;
@@ -4412,7 +4499,7 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
 retry:
 	err = ext4_es_remove_extent(inode, last_block,
 				    EXT_MAX_BLOCKS - last_block);
-	if (err == ENOMEM) {
+	if (err == -ENOMEM) {
 		cond_resched();
 		congestion_wait(BLK_RW_ASYNC, HZ/50);
 		goto retry;
@@ -4771,6 +4858,6 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 		error = ext4_fill_fiemap_extents(inode, start_blk,
 						 len_blks, fieinfo);
 	}
-
+	ext4_es_lru_add(inode);
 	return error;
 }
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 91cb110..b9dcfe7 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -263,7 +263,7 @@ void ext4_es_find_delayed_extent_range(struct inode *inode,
 	if (tree->cache_es) {
 		es1 = tree->cache_es;
 		if (in_range(lblk, es1->es_lblk, es1->es_len)) {
-			es_debug("%u cached by [%u/%u) %llu %llx\n",
+			es_debug("%u cached by [%u/%u) %llu %x\n",
 				 lblk, es1->es_lblk, es1->es_len,
 				 ext4_es_pblock(es1), ext4_es_status(es1));
 			goto out;
@@ -419,7 +419,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
 	unsigned short ee_len;
 	int depth, ee_status, es_status;
 
-	path = ext4_ext_find_extent(inode, es->es_lblk, NULL);
+	path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
 	if (IS_ERR(path))
 		return;
 
@@ -641,13 +641,13 @@ out:
  */
 int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 			  ext4_lblk_t len, ext4_fsblk_t pblk,
-			  unsigned long long status)
+			  unsigned int status)
 {
 	struct extent_status newes;
 	ext4_lblk_t end = lblk + len - 1;
 	int err = 0;
 
-	es_debug("add [%u/%u) %llu %llx to extent status tree of inode %lu\n",
+	es_debug("add [%u/%u) %llu %x to extent status tree of inode %lu\n",
 		 lblk, len, pblk, status, inode->i_ino);
 
 	if (!len)
@@ -684,6 +684,38 @@ error:
 }
 
 /*
+ * ext4_es_cache_extent() inserts information into the extent status
+ * tree if and only if there isn't information about the range in
+ * question already.
+ */
+void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+			  ext4_lblk_t len, ext4_fsblk_t pblk,
+			  unsigned int status)
+{
+	struct extent_status *es;
+	struct extent_status newes;
+	ext4_lblk_t end = lblk + len - 1;
+
+	newes.es_lblk = lblk;
+	newes.es_len = len;
+	ext4_es_store_pblock(&newes, pblk);
+	ext4_es_store_status(&newes, status);
+	trace_ext4_es_cache_extent(inode, &newes);
+
+	if (!len)
+		return;
+
+	BUG_ON(end < lblk);
+
+	write_lock(&EXT4_I(inode)->i_es_lock);
+
+	es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk);
+	if (!es || es->es_lblk > end)
+		__es_insert_extent(inode, &newes);
+	write_unlock(&EXT4_I(inode)->i_es_lock);
+}
+
+/*
  * ext4_es_lookup_extent() looks up an extent in extent status tree.
  *
  * ext4_es_lookup_extent is called by ext4_map_blocks/ext4_da_map_blocks.
@@ -895,6 +927,12 @@ static int ext4_inode_touch_time_cmp(void *priv, struct list_head *a,
 	eia = list_entry(a, struct ext4_inode_info, i_es_lru);
 	eib = list_entry(b, struct ext4_inode_info, i_es_lru);
 
+	if (ext4_test_inode_state(&eia->vfs_inode, EXT4_STATE_EXT_PRECACHED) &&
+	    !ext4_test_inode_state(&eib->vfs_inode, EXT4_STATE_EXT_PRECACHED))
+		return 1;
+	if (!ext4_test_inode_state(&eia->vfs_inode, EXT4_STATE_EXT_PRECACHED) &&
+	    ext4_test_inode_state(&eib->vfs_inode, EXT4_STATE_EXT_PRECACHED))
+		return -1;
 	if (eia->i_touch_when == eib->i_touch_when)
 		return 0;
 	if (time_after(eia->i_touch_when, eib->i_touch_when))
@@ -910,20 +948,14 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
 	struct list_head *cur, *tmp;
 	LIST_HEAD(skiped);
 	int ret, nr_shrunk = 0;
+	int retried = 0, skip_precached = 1, nr_skipped = 0;
 
 	spin_lock(&sbi->s_es_lru_lock);
 
-	/*
-	 * If the inode that is at the head of LRU list is newer than
-	 * last_sorted time, that means that we need to sort this list.
-	 */
-	ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info, i_es_lru);
-	if (sbi->s_es_last_sorted < ei->i_touch_when) {
-		list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp);
-		sbi->s_es_last_sorted = jiffies;
-	}
-
+retry:
 	list_for_each_safe(cur, tmp, &sbi->s_es_lru) {
+		int ret;
+
 		/*
 		 * If we have already reclaimed all extents from extent
 		 * status tree, just stop the loop immediately.
@@ -933,8 +965,15 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
 
 		ei = list_entry(cur, struct ext4_inode_info, i_es_lru);
 
-		/* Skip the inode that is newer than the last_sorted time */
-		if (sbi->s_es_last_sorted < ei->i_touch_when) {
+		/*
+		 * Skip the inode that is newer than the last_sorted
+		 * time.  Normally we try hard to avoid shrinking
+		 * precached inodes, but we will as a last resort.
+		 */
+		if ((sbi->s_es_last_sorted < ei->i_touch_when) ||
+		    (skip_precached && ext4_test_inode_state(&ei->vfs_inode,
+						EXT4_STATE_EXT_PRECACHED))) {
+			nr_skipped++;
 			list_move_tail(cur, &skiped);
 			continue;
 		}
@@ -956,15 +995,49 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
 
 	/* Move the newer inodes into the tail of the LRU list. */
 	list_splice_tail(&skiped, &sbi->s_es_lru);
+
+	/*
+	 * If we skipped any inodes, and we weren't able to make any
+	 * forward progress, sort the list and try again.
+	 */
+	if ((nr_shrunk == 0) && nr_skipped && !retried) {
+		retried++;
+		list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp);
+		sbi->s_es_last_sorted = jiffies;
+		ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info,
+				      i_es_lru);
+		/*
+		 * If there are no non-precached inodes left on the
+		 * list, start releasing precached extents.
+		 */
+		if (ext4_test_inode_state(&ei->vfs_inode,
+					  EXT4_STATE_EXT_PRECACHED))
+			skip_precached = 0;
+		goto retry;
+	}
+
 	spin_unlock(&sbi->s_es_lru_lock);
 
 	if (locked_ei && nr_shrunk == 0)
-		nr_shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
+		nr_shrunk = __es_try_to_reclaim_extents(locked_ei, nr_to_scan);
 
 	return nr_shrunk;
 }
 
-static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long ext4_es_count(struct shrinker *shrink,
+				   struct shrink_control *sc)
+{
+	unsigned long nr;
+	struct ext4_sb_info *sbi;
+
+	sbi = container_of(shrink, struct ext4_sb_info, s_es_shrinker);
+	nr = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
+	trace_ext4_es_shrink_enter(sbi->s_sb, sc->nr_to_scan, nr);
+	return nr;
+}
+
+static unsigned long ext4_es_scan(struct shrinker *shrink,
+				  struct shrink_control *sc)
 {
 	struct ext4_sb_info *sbi = container_of(shrink,
 					struct ext4_sb_info, s_es_shrinker);
@@ -979,9 +1052,8 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
 
 	nr_shrunk = __ext4_es_shrink(sbi, nr_to_scan, NULL);
 
-	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
 	trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
-	return ret;
+	return nr_shrunk;
 }
 
 void ext4_es_register_shrinker(struct ext4_sb_info *sbi)
@@ -989,7 +1061,8 @@ void ext4_es_register_shrinker(struct ext4_sb_info *sbi)
 	INIT_LIST_HEAD(&sbi->s_es_lru);
 	spin_lock_init(&sbi->s_es_lru_lock);
 	sbi->s_es_last_sorted = 0;
-	sbi->s_es_shrinker.shrink = ext4_es_shrink;
+	sbi->s_es_shrinker.scan_objects = ext4_es_scan;
+	sbi->s_es_shrinker.count_objects = ext4_es_count;
 	sbi->s_es_shrinker.seeks = DEFAULT_SEEKS;
 	register_shrinker(&sbi->s_es_shrinker);
 }
@@ -1033,11 +1106,17 @@ static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
 	struct ext4_es_tree *tree = &ei->i_es_tree;
 	struct rb_node *node;
 	struct extent_status *es;
-	int nr_shrunk = 0;
+	unsigned long nr_shrunk = 0;
+	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
+				      DEFAULT_RATELIMIT_BURST);
 
 	if (ei->i_es_lru_nr == 0)
 		return 0;
 
+	if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED) &&
+	    __ratelimit(&_rs))
+		ext4_warning(inode->i_sb, "forced shrink of precached extents");
+
 	node = rb_first(&tree->root);
 	while (node != NULL) {
 		es = rb_entry(node, struct extent_status, rb_node);
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index e936730..3e83aef 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -29,16 +29,26 @@
 /*
  * These flags live in the high bits of extent_status.es_pblk
  */
-#define EXTENT_STATUS_WRITTEN	(1ULL << 63)
-#define EXTENT_STATUS_UNWRITTEN (1ULL << 62)
-#define EXTENT_STATUS_DELAYED	(1ULL << 61)
-#define EXTENT_STATUS_HOLE	(1ULL << 60)
+#define ES_SHIFT	60
+
+#define EXTENT_STATUS_WRITTEN	(1 << 3)
+#define EXTENT_STATUS_UNWRITTEN (1 << 2)
+#define EXTENT_STATUS_DELAYED	(1 << 1)
+#define EXTENT_STATUS_HOLE	(1 << 0)
 
 #define EXTENT_STATUS_FLAGS	(EXTENT_STATUS_WRITTEN | \
 				 EXTENT_STATUS_UNWRITTEN | \
 				 EXTENT_STATUS_DELAYED | \
 				 EXTENT_STATUS_HOLE)
 
+#define ES_WRITTEN		(1ULL << 63)
+#define ES_UNWRITTEN		(1ULL << 62)
+#define ES_DELAYED		(1ULL << 61)
+#define ES_HOLE			(1ULL << 60)
+
+#define ES_MASK			(ES_WRITTEN | ES_UNWRITTEN | \
+				 ES_DELAYED | ES_HOLE)
+
 struct ext4_sb_info;
 struct ext4_extent;
 
@@ -60,7 +70,10 @@ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
 
 extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 				 ext4_lblk_t len, ext4_fsblk_t pblk,
-				 unsigned long long status);
+				 unsigned int status);
+extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+				 ext4_lblk_t len, ext4_fsblk_t pblk,
+				 unsigned int status);
 extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
 				 ext4_lblk_t len);
 extern void ext4_es_find_delayed_extent_range(struct inode *inode,
@@ -72,32 +85,32 @@ extern int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex);
 
 static inline int ext4_es_is_written(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_WRITTEN) != 0;
+	return (es->es_pblk & ES_WRITTEN) != 0;
 }
 
 static inline int ext4_es_is_unwritten(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_UNWRITTEN) != 0;
+	return (es->es_pblk & ES_UNWRITTEN) != 0;
 }
 
 static inline int ext4_es_is_delayed(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_DELAYED) != 0;
+	return (es->es_pblk & ES_DELAYED) != 0;
 }
 
 static inline int ext4_es_is_hole(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_HOLE) != 0;
+	return (es->es_pblk & ES_HOLE) != 0;
 }
 
-static inline ext4_fsblk_t ext4_es_status(struct extent_status *es)
+static inline unsigned int ext4_es_status(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_FLAGS);
+	return es->es_pblk >> ES_SHIFT;
 }
 
 static inline ext4_fsblk_t ext4_es_pblock(struct extent_status *es)
 {
-	return (es->es_pblk & ~EXTENT_STATUS_FLAGS);
+	return es->es_pblk & ~ES_MASK;
 }
 
 static inline void ext4_es_store_pblock(struct extent_status *es,
@@ -105,19 +118,16 @@ static inline void ext4_es_store_pblock(struct extent_status *es,
 {
 	ext4_fsblk_t block;
 
-	block = (pb & ~EXTENT_STATUS_FLAGS) |
-		(es->es_pblk & EXTENT_STATUS_FLAGS);
+	block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK);
 	es->es_pblk = block;
 }
 
 static inline void ext4_es_store_status(struct extent_status *es,
-					unsigned long long status)
+					unsigned int status)
 {
-	ext4_fsblk_t block;
-
-	block = (status & EXTENT_STATUS_FLAGS) |
-		(es->es_pblk & ~EXTENT_STATUS_FLAGS);
-	es->es_pblk = block;
+	es->es_pblk = (((ext4_fsblk_t)
+			(status & EXTENT_STATUS_FLAGS) << ES_SHIFT) |
+		       (es->es_pblk & ~ES_MASK));
 }
 
 extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index f03598c..c6d0ce7 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -625,6 +625,51 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
 }
 
 /*
+ * In no journal mode, if an inode has recently been deleted, we want
+ * to avoid reusing it until we're reasonably sure the inode table
+ * block has been written back to disk.
+ */
+static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)
+{
+	struct ext4_group_desc	*gdp;
+	struct ext4_inode	*raw_inode;
+	struct buffer_head	*bh;
+	unsigned long		dtime, now;
+	int	inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
+	int	offset, ret = 0, recentcy = dirty_expire_interval;
+
+	gdp = ext4_get_group_desc(sb, group, NULL);
+	if (unlikely(!gdp))
+		return 0;
+
+	bh = sb_getblk(sb, ext4_inode_table(sb, gdp) +
+		       (ino / inodes_per_block));
+	if (unlikely(!bh) || !buffer_uptodate(bh))
+		/*
+		 * If the block is not in the buffer cache, then it
+		 * must have been written out.
+		 */
+		goto out;
+
+	offset = (ino % inodes_per_block) * EXT4_INODE_SIZE(sb);
+	raw_inode = (struct ext4_inode *) (bh->b_data + offset);
+	dtime = le32_to_cpu(raw_inode->i_dtime);
+	now = get_seconds();
+	if (!buffer_dirty(bh) && (recentcy > 5))
+		/*
+		 * Five seconds should be enough time for a block to be
+		 * committed to the platter once it is sent to the HDD
+		 */
+		recentcy = 5;
+
+	if (dtime && (dtime < now) && (now < dtime + recentcy))
+		ret = 1;
+out:
+	brelse(bh);
+	return ret;
+}
+
+/*
  * There are two policies for allocating an inode.  If the new inode is
  * a directory, then a forward search is made for a block group with both
  * free space and a low directory-to-inode ratio; if that fails, then of
@@ -734,16 +779,18 @@ repeat_in_this_group:
 		ino = ext4_find_next_zero_bit((unsigned long *)
 					      inode_bitmap_bh->b_data,
 					      EXT4_INODES_PER_GROUP(sb), ino);
-		if (ino >= EXT4_INODES_PER_GROUP(sb)) {
-			if (++group == ngroups)
-				group = 0;
-			continue;
-		}
+		if (ino >= EXT4_INODES_PER_GROUP(sb))
+			goto next_group;
 		if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) {
 			ext4_error(sb, "reserved inode found cleared - "
 				   "inode=%lu", ino + 1);
 			continue;
 		}
+		if ((EXT4_SB(sb)->s_journal == NULL) &&
+		    recently_deleted(sb, group, ino)) {
+			ino++;
+			goto next_inode;
+		}
 		if (!handle) {
 			BUG_ON(nblocks <= 0);
 			handle = __ext4_journal_start_sb(dir->i_sb, line_no,
@@ -767,8 +814,12 @@ repeat_in_this_group:
 		ino++;		/* the inode bitmap is zero-based */
 		if (!ret2)
 			goto got; /* we grabbed the inode! */
+next_inode:
 		if (ino < EXT4_INODES_PER_GROUP(sb))
 			goto repeat_in_this_group;
+next_group:
+		if (++group == ngroups)
+			group = 0;
 	}
 	err = -ENOSPC;
 	goto out;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index ba33c67..95af844 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -553,16 +553,15 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	}
 	if (retval > 0) {
 		int ret;
-		unsigned long long status;
+		unsigned int status;
 
-#ifdef ES_AGGRESSIVE_TEST
-		if (retval != map->m_len) {
-			printk("ES len assertion failed for inode: %lu "
-			       "retval %d != map->m_len %d "
-			       "in %s (lookup)\n", inode->i_ino, retval,
-			       map->m_len, __func__);
+		if (unlikely(retval != map->m_len)) {
+			ext4_warning(inode->i_sb,
+				     "ES len assertion failed for inode "
+				     "%lu: retval %d != map->m_len %d",
+				     inode->i_ino, retval, map->m_len);
+			WARN_ON(1);
 		}
-#endif
 
 		status = map->m_flags & EXT4_MAP_UNWRITTEN ?
 				EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
@@ -654,16 +653,15 @@ found:
 
 	if (retval > 0) {
 		int ret;
-		unsigned long long status;
+		unsigned int status;
 
-#ifdef ES_AGGRESSIVE_TEST
-		if (retval != map->m_len) {
-			printk("ES len assertion failed for inode: %lu "
-			       "retval %d != map->m_len %d "
-			       "in %s (allocation)\n", inode->i_ino, retval,
-			       map->m_len, __func__);
+		if (unlikely(retval != map->m_len)) {
+			ext4_warning(inode->i_sb,
+				     "ES len assertion failed for inode "
+				     "%lu: retval %d != map->m_len %d",
+				     inode->i_ino, retval, map->m_len);
+			WARN_ON(1);
 		}
-#endif
 
 		/*
 		 * If the extent has been zeroed out, we don't need to update
@@ -1635,16 +1633,15 @@ add_delayed:
 		set_buffer_delay(bh);
 	} else if (retval > 0) {
 		int ret;
-		unsigned long long status;
+		unsigned int status;
 
-#ifdef ES_AGGRESSIVE_TEST
-		if (retval != map->m_len) {
-			printk("ES len assertion failed for inode: %lu "
-			       "retval %d != map->m_len %d "
-			       "in %s (lookup)\n", inode->i_ino, retval,
-			       map->m_len, __func__);
+		if (unlikely(retval != map->m_len)) {
+			ext4_warning(inode->i_sb,
+				     "ES len assertion failed for inode "
+				     "%lu: retval %d != map->m_len %d",
+				     inode->i_ino, retval, map->m_len);
+			WARN_ON(1);
 		}
-#endif
 
 		status = map->m_flags & EXT4_MAP_UNWRITTEN ?
 				EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 9491ac0..3c7304c 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -622,6 +622,8 @@ resizefs_out:
 
 		return 0;
 	}
+	case EXT4_IOC_PRECACHE_EXTENTS:
+		return ext4_ext_precache(inode);
 
 	default:
 		return -ENOTTY;
@@ -686,6 +688,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case EXT4_IOC_MOVE_EXT:
 	case FITRIM:
 	case EXT4_IOC_RESIZE_FS:
+	case EXT4_IOC_PRECACHE_EXTENTS:
 		break;
 	default:
 		return -ENOIOCTLCMD;
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index 49e8bdf..f99bdb8 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -39,7 +39,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
 	newext.ee_block = cpu_to_le32(lb->first_block);
 	newext.ee_len   = cpu_to_le16(lb->last_block - lb->first_block + 1);
 	ext4_ext_store_pblock(&newext, lb->first_pblock);
-	path = ext4_ext_find_extent(inode, lb->first_block, NULL);
+	path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0);
 
 	if (IS_ERR(path)) {
 		retval = PTR_ERR(path);
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index e86dddb..7fa4d85 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -37,7 +37,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
 	int ret = 0;
 	struct ext4_ext_path *path;
 
-	path = ext4_ext_find_extent(inode, lblock, *orig_path);
+	path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE);
 	if (IS_ERR(path))
 		ret = PTR_ERR(path);
 	else if (path[ext_depth(inode)].p_ext == NULL)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 35f55a0..1bec5a5 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3005,15 +3005,19 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
 /*
  * Anybody can rename anything with this: the permission checks are left to the
  * higher-level routines.
+ *
+ * n.b.  old_{dentry,inode) refers to the source dentry/inode
+ * while new_{dentry,inode) refers to the destination dentry/inode
+ * This comes from rename(const char *oldpath, const char *newpath)
  */
 static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		       struct inode *new_dir, struct dentry *new_dentry)
 {
-	handle_t *handle;
+	handle_t *handle = NULL;
 	struct inode *old_inode, *new_inode;
 	struct buffer_head *old_bh, *new_bh, *dir_bh;
 	struct ext4_dir_entry_2 *old_de, *new_de;
-	int retval, force_da_alloc = 0;
+	int retval;
 	int inlined = 0, new_inlined = 0;
 	struct ext4_dir_entry_2 *parent_de;
 
@@ -3026,14 +3030,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	 * in separate transaction */
 	if (new_dentry->d_inode)
 		dquot_initialize(new_dentry->d_inode);
-	handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
-		(2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
-		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2));
-	if (IS_ERR(handle))
-		return PTR_ERR(handle);
-
-	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
-		ext4_handle_sync(handle);
 
 	old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL);
 	/*
@@ -3056,6 +3052,18 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 			new_bh = NULL;
 		}
 	}
+	if (new_inode && !test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
+		ext4_alloc_da_blocks(old_inode);
+
+	handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
+		(2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
+		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+		ext4_handle_sync(handle);
+
 	if (S_ISDIR(old_inode->i_mode)) {
 		if (new_inode) {
 			retval = -ENOTEMPTY;
@@ -3186,8 +3194,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		ext4_mark_inode_dirty(handle, new_inode);
 		if (!new_inode->i_nlink)
 			ext4_orphan_add(handle, new_inode);
-		if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
-			force_da_alloc = 1;
 	}
 	retval = 0;
 
@@ -3195,9 +3201,8 @@ end_rename:
 	brelse(dir_bh);
 	brelse(old_bh);
 	brelse(new_bh);
-	ext4_journal_stop(handle);
-	if (retval == 0 && force_da_alloc)
-		ext4_alloc_da_blocks(old_inode);
+	if (handle)
+		ext4_journal_stop(handle);
 	return retval;
 }
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index bca26f3..36b141e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5481,6 +5481,7 @@ static void __exit ext4_exit_fs(void)
 	kset_unregister(ext4_kset);
 	ext4_exit_system_zone();
 	ext4_exit_pageio();
+	ext4_exit_es();
 }
 
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 66a6b85..c5a5c39 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -182,7 +182,7 @@ const struct address_space_operations f2fs_meta_aops = {
 	.set_page_dirty	= f2fs_set_meta_page_dirty,
 };
 
-int check_orphan_space(struct f2fs_sb_info *sbi)
+int acquire_orphan_inode(struct f2fs_sb_info *sbi)
 {
 	unsigned int max_orphans;
 	int err = 0;
@@ -197,10 +197,19 @@ int check_orphan_space(struct f2fs_sb_info *sbi)
 	mutex_lock(&sbi->orphan_inode_mutex);
 	if (sbi->n_orphans >= max_orphans)
 		err = -ENOSPC;
+	else
+		sbi->n_orphans++;
 	mutex_unlock(&sbi->orphan_inode_mutex);
 	return err;
 }
 
+void release_orphan_inode(struct f2fs_sb_info *sbi)
+{
+	mutex_lock(&sbi->orphan_inode_mutex);
+	sbi->n_orphans--;
+	mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
 void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
 {
 	struct list_head *head, *this;
@@ -229,21 +238,18 @@ retry:
 		list_add(&new->list, this->prev);
 	else
 		list_add_tail(&new->list, head);
-
-	sbi->n_orphans++;
 out:
 	mutex_unlock(&sbi->orphan_inode_mutex);
 }
 
 void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
 {
-	struct list_head *this, *next, *head;
+	struct list_head *head;
 	struct orphan_inode_entry *orphan;
 
 	mutex_lock(&sbi->orphan_inode_mutex);
 	head = &sbi->orphan_inode_list;
-	list_for_each_safe(this, next, head) {
-		orphan = list_entry(this, struct orphan_inode_entry, list);
+	list_for_each_entry(orphan, head, list) {
 		if (orphan->ino == ino) {
 			list_del(&orphan->list);
 			kmem_cache_free(orphan_entry_slab, orphan);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 035f9a3..a7eb529 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -37,9 +37,9 @@ static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr)
 	struct page *node_page = dn->node_page;
 	unsigned int ofs_in_node = dn->ofs_in_node;
 
-	wait_on_page_writeback(node_page);
+	f2fs_wait_on_page_writeback(node_page, NODE, false);
 
-	rn = (struct f2fs_node *)page_address(node_page);
+	rn = F2FS_NODE(node_page);
 
 	/* Get physical address of data block */
 	addr_array = blkaddr_in_node(rn);
@@ -365,7 +365,6 @@ static void read_end_io(struct bio *bio, int err)
 		}
 		unlock_page(page);
 	} while (bvec >= bio->bi_io_vec);
-	kfree(bio->bi_private);
 	bio_put(bio);
 }
 
@@ -391,7 +390,6 @@ int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
 	bio->bi_end_io = read_end_io;
 
 	if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
-		kfree(bio->bi_private);
 		bio_put(bio);
 		up_read(&sbi->bio_sem);
 		f2fs_put_page(page, 1);
@@ -636,9 +634,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 	int err = 0;
 	int ilock;
 
-	/* for nobh_write_end */
-	*fsdata = NULL;
-
 	f2fs_balance_fs(sbi);
 repeat:
 	page = grab_cache_page_write_begin(mapping, index, flags);
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 0d6c6aa..a84b0a8 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -29,7 +29,7 @@ static DEFINE_MUTEX(f2fs_stat_mutex);
 
 static void update_general_status(struct f2fs_sb_info *sbi)
 {
-	struct f2fs_stat_info *si = sbi->stat_info;
+	struct f2fs_stat_info *si = F2FS_STAT(sbi);
 	int i;
 
 	/* valid check of the segment numbers */
@@ -83,7 +83,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
  */
 static void update_sit_info(struct f2fs_sb_info *sbi)
 {
-	struct f2fs_stat_info *si = sbi->stat_info;
+	struct f2fs_stat_info *si = F2FS_STAT(sbi);
 	unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
 	struct sit_info *sit_i = SIT_I(sbi);
 	unsigned int segno, vblocks;
@@ -118,7 +118,7 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
  */
 static void update_mem_info(struct f2fs_sb_info *sbi)
 {
-	struct f2fs_stat_info *si = sbi->stat_info;
+	struct f2fs_stat_info *si = F2FS_STAT(sbi);
 	unsigned npages;
 
 	if (si->base_mem)
@@ -253,21 +253,21 @@ static int stat_show(struct seq_file *s, void *v)
 			   si->nats, NM_WOUT_THRESHOLD);
 		seq_printf(s, "  - SITs: %5d\n  - free_nids: %5d\n",
 			   si->sits, si->fnids);
-		seq_printf(s, "\nDistribution of User Blocks:");
-		seq_printf(s, " [ valid | invalid | free ]\n");
-		seq_printf(s, "  [");
+		seq_puts(s, "\nDistribution of User Blocks:");
+		seq_puts(s, " [ valid | invalid | free ]\n");
+		seq_puts(s, "  [");
 
 		for (j = 0; j < si->util_valid; j++)
-			seq_printf(s, "-");
-		seq_printf(s, "|");
+			seq_putc(s, '-');
+		seq_putc(s, '|');
 
 		for (j = 0; j < si->util_invalid; j++)
-			seq_printf(s, "-");
-		seq_printf(s, "|");
+			seq_putc(s, '-');
+		seq_putc(s, '|');
 
 		for (j = 0; j < si->util_free; j++)
-			seq_printf(s, "-");
-		seq_printf(s, "]\n\n");
+			seq_putc(s, '-');
+		seq_puts(s, "]\n\n");
 		seq_printf(s, "SSR: %u blocks in %u segments\n",
 			   si->block_count[SSR], si->segment_count[SSR]);
 		seq_printf(s, "LFS: %u blocks in %u segments\n",
@@ -305,11 +305,10 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
 	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 	struct f2fs_stat_info *si;
 
-	sbi->stat_info = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
-	if (!sbi->stat_info)
+	si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
+	if (!si)
 		return -ENOMEM;
 
-	si = sbi->stat_info;
 	si->all_area_segs = le32_to_cpu(raw_super->segment_count);
 	si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
 	si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
@@ -319,6 +318,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
 	si->main_area_zones = si->main_area_sections /
 				le32_to_cpu(raw_super->secs_per_zone);
 	si->sbi = sbi;
+	sbi->stat_info = si;
 
 	mutex_lock(&f2fs_stat_mutex);
 	list_add_tail(&si->stat_list, &f2fs_stat_list);
@@ -329,13 +329,13 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
 
 void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
 {
-	struct f2fs_stat_info *si = sbi->stat_info;
+	struct f2fs_stat_info *si = F2FS_STAT(sbi);
 
 	mutex_lock(&f2fs_stat_mutex);
 	list_del(&si->stat_list);
 	mutex_unlock(&f2fs_stat_mutex);
 
-	kfree(sbi->stat_info);
+	kfree(si);
 }
 
 void __init f2fs_create_root_stats(void)
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 62f0d59..384c6da 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -270,12 +270,27 @@ static void init_dent_inode(const struct qstr *name, struct page *ipage)
 	struct f2fs_node *rn;
 
 	/* copy name info. to this inode page */
-	rn = (struct f2fs_node *)page_address(ipage);
+	rn = F2FS_NODE(ipage);
 	rn->i.i_namelen = cpu_to_le32(name->len);
 	memcpy(rn->i.i_name, name->name, name->len);
 	set_page_dirty(ipage);
 }
 
+int update_dent_inode(struct inode *inode, const struct qstr *name)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct page *page;
+
+	page = get_node_page(sbi, inode->i_ino);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+
+	init_dent_inode(name, page);
+	f2fs_put_page(page, 1);
+
+	return 0;
+}
+
 static int make_empty_dir(struct inode *inode,
 		struct inode *parent, struct page *page)
 {
@@ -557,6 +572,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
 
 		if (inode->i_nlink == 0)
 			add_orphan_inode(sbi, inode->i_ino);
+		else
+			release_orphan_inode(sbi);
 	}
 
 	if (bit_pos == NR_DENTRY_IN_BLOCK) {
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 467d42d..d8e386ce 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/crc32.h>
 #include <linux/magic.h>
+#include <linux/kobject.h>
 
 /*
  * For mount options
@@ -350,6 +351,7 @@ enum page_type {
 
 struct f2fs_sb_info {
 	struct super_block *sb;			/* pointer to VFS super block */
+	struct proc_dir_entry *s_proc;		/* proc entry */
 	struct buffer_head *raw_super_buf;	/* buffer head of raw sb */
 	struct f2fs_super_block *raw_super;	/* raw super block pointer */
 	int s_dirty;				/* dirty flag for checkpoint */
@@ -429,6 +431,10 @@ struct f2fs_sb_info {
 #endif
 	unsigned int last_victim[2];		/* last victim segment # */
 	spinlock_t stat_lock;			/* lock for stat operations */
+
+	/* For sysfs suppport */
+	struct kobject s_kobj;
+	struct completion s_kobj_unregister;
 };
 
 /*
@@ -454,6 +460,11 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
 	return (struct f2fs_checkpoint *)(sbi->ckpt);
 }
 
+static inline struct f2fs_node *F2FS_NODE(struct page *page)
+{
+	return (struct f2fs_node *)page_address(page);
+}
+
 static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
 {
 	return (struct f2fs_nm_info *)(sbi->nm_info);
@@ -812,7 +823,7 @@ static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name,
 
 static inline bool IS_INODE(struct page *page)
 {
-	struct f2fs_node *p = (struct f2fs_node *)page_address(page);
+	struct f2fs_node *p = F2FS_NODE(page);
 	return RAW_IS_INODE(p);
 }
 
@@ -826,7 +837,7 @@ static inline block_t datablock_addr(struct page *node_page,
 {
 	struct f2fs_node *raw_node;
 	__le32 *addr_array;
-	raw_node = (struct f2fs_node *)page_address(node_page);
+	raw_node = F2FS_NODE(node_page);
 	addr_array = blkaddr_in_node(raw_node);
 	return le32_to_cpu(addr_array[offset]);
 }
@@ -947,6 +958,7 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
 ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
 void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
 				struct page *, struct inode *);
+int update_dent_inode(struct inode *, const struct qstr *);
 int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *);
 void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
 int f2fs_make_empty(struct inode *, struct inode *);
@@ -1012,7 +1024,8 @@ int npages_for_summary_flush(struct f2fs_sb_info *);
 void allocate_new_segments(struct f2fs_sb_info *);
 struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
 struct bio *f2fs_bio_alloc(struct block_device *, int);
-void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync);
+void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool);
+void f2fs_wait_on_page_writeback(struct page *, enum page_type, bool);
 void write_meta_page(struct f2fs_sb_info *, struct page *);
 void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
 					block_t, block_t *);
@@ -1037,7 +1050,8 @@ void destroy_segment_manager(struct f2fs_sb_info *);
 struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
-int check_orphan_space(struct f2fs_sb_info *);
+int acquire_orphan_inode(struct f2fs_sb_info *);
+void release_orphan_inode(struct f2fs_sb_info *);
 void add_orphan_inode(struct f2fs_sb_info *, nid_t);
 void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
 int recover_orphan_inodes(struct f2fs_sb_info *);
@@ -1112,11 +1126,16 @@ struct f2fs_stat_info {
 	unsigned base_mem, cache_mem;
 };
 
+static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_stat_info*)sbi->stat_info;
+}
+
 #define stat_inc_call_count(si)	((si)->call_count++)
 
 #define stat_inc_seg_count(sbi, type)					\
 	do {								\
-		struct f2fs_stat_info *si = sbi->stat_info;		\
+		struct f2fs_stat_info *si = F2FS_STAT(sbi);		\
 		(si)->tot_segs++;					\
 		if (type == SUM_TYPE_DATA)				\
 			si->data_segs++;				\
@@ -1129,14 +1148,14 @@ struct f2fs_stat_info {
 
 #define stat_inc_data_blk_count(sbi, blks)				\
 	do {								\
-		struct f2fs_stat_info *si = sbi->stat_info;		\
+		struct f2fs_stat_info *si = F2FS_STAT(sbi);		\
 		stat_inc_tot_blk_count(si, blks);			\
 		si->data_blks += (blks);				\
 	} while (0)
 
 #define stat_inc_node_blk_count(sbi, blks)				\
 	do {								\
-		struct f2fs_stat_info *si = sbi->stat_info;		\
+		struct f2fs_stat_info *si = F2FS_STAT(sbi);		\
 		stat_inc_tot_blk_count(si, blks);			\
 		si->node_blks += (blks);				\
 	} while (0)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d2d2b7d..c2deb27 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -112,11 +112,13 @@ static int get_parent_ino(struct inode *inode, nid_t *pino)
 	if (!dentry)
 		return 0;
 
-	inode = igrab(dentry->d_parent->d_inode);
-	dput(dentry);
+	if (update_dent_inode(inode, &dentry->d_name)) {
+		dput(dentry);
+		return 0;
+	}
 
-	*pino = inode->i_ino;
-	iput(inode);
+	*pino = parent_ino(dentry);
+	dput(dentry);
 	return 1;
 }
 
@@ -147,9 +149,10 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
 	mutex_lock(&inode->i_mutex);
 
-	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
-		goto out;
-
+	/*
+	 * Both of fdatasync() and fsync() are able to be recovered from
+	 * sudden-power-off.
+	 */
 	if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
 		need_cp = true;
 	else if (file_wrong_pino(inode))
@@ -205,7 +208,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
 	struct f2fs_node *raw_node;
 	__le32 *addr;
 
-	raw_node = page_address(dn->node_page);
+	raw_node = F2FS_NODE(dn->node_page);
 	addr = blkaddr_in_node(raw_node) + ofs;
 
 	for ( ; count > 0; count--, addr++, dn->ofs_in_node++) {
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 35f9b1a..e6b3ffd 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -29,10 +29,11 @@ static struct kmem_cache *winode_slab;
 static int gc_thread_func(void *data)
 {
 	struct f2fs_sb_info *sbi = data;
+	struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
 	wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
 	long wait_ms;
 
-	wait_ms = GC_THREAD_MIN_SLEEP_TIME;
+	wait_ms = gc_th->min_sleep_time;
 
 	do {
 		if (try_to_freeze())
@@ -45,7 +46,7 @@ static int gc_thread_func(void *data)
 			break;
 
 		if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) {
-			wait_ms = GC_THREAD_MAX_SLEEP_TIME;
+			wait_ms = increase_sleep_time(gc_th, wait_ms);
 			continue;
 		}
 
@@ -66,15 +67,15 @@ static int gc_thread_func(void *data)
 			continue;
 
 		if (!is_idle(sbi)) {
-			wait_ms = increase_sleep_time(wait_ms);
+			wait_ms = increase_sleep_time(gc_th, wait_ms);
 			mutex_unlock(&sbi->gc_mutex);
 			continue;
 		}
 
 		if (has_enough_invalid_blocks(sbi))
-			wait_ms = decrease_sleep_time(wait_ms);
+			wait_ms = decrease_sleep_time(gc_th, wait_ms);
 		else
-			wait_ms = increase_sleep_time(wait_ms);
+			wait_ms = increase_sleep_time(gc_th, wait_ms);
 
 #ifdef CONFIG_F2FS_STAT_FS
 		sbi->bg_gc++;
@@ -82,7 +83,7 @@ static int gc_thread_func(void *data)
 
 		/* if return value is not zero, no victim was selected */
 		if (f2fs_gc(sbi))
-			wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
+			wait_ms = gc_th->no_gc_sleep_time;
 	} while (!kthread_should_stop());
 	return 0;
 }
@@ -101,6 +102,12 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
 		goto out;
 	}
 
+	gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME;
+	gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
+	gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
+
+	gc_th->gc_idle = 0;
+
 	sbi->gc_thread = gc_th;
 	init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
 	sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
@@ -125,9 +132,17 @@ void stop_gc_thread(struct f2fs_sb_info *sbi)
 	sbi->gc_thread = NULL;
 }
 
-static int select_gc_type(int gc_type)
+static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type)
 {
-	return (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
+	int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
+
+	if (gc_th && gc_th->gc_idle) {
+		if (gc_th->gc_idle == 1)
+			gc_mode = GC_CB;
+		else if (gc_th->gc_idle == 2)
+			gc_mode = GC_GREEDY;
+	}
+	return gc_mode;
 }
 
 static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
@@ -140,7 +155,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
 		p->dirty_segmap = dirty_i->dirty_segmap[type];
 		p->ofs_unit = 1;
 	} else {
-		p->gc_mode = select_gc_type(gc_type);
+		p->gc_mode = select_gc_type(sbi->gc_thread, gc_type);
 		p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
 		p->ofs_unit = sbi->segs_per_sec;
 	}
@@ -407,8 +422,7 @@ next_step:
 
 		/* set page dirty and write it */
 		if (gc_type == FG_GC) {
-			f2fs_submit_bio(sbi, NODE, true);
-			wait_on_page_writeback(node_page);
+			f2fs_wait_on_page_writeback(node_page, NODE, true);
 			set_page_dirty(node_page);
 		} else {
 			if (!PageWriteback(node_page))
@@ -508,10 +522,7 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
 	} else {
 		struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
-		if (PageWriteback(page)) {
-			f2fs_submit_bio(sbi, DATA, true);
-			wait_on_page_writeback(page);
-		}
+		f2fs_wait_on_page_writeback(page, DATA, true);
 
 		if (clear_page_dirty_for_io(page) &&
 			S_ISDIR(inode->i_mode)) {
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index 2c6a6bd..c22dee9 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -13,9 +13,9 @@
 						 * whether IO subsystem is idle
 						 * or not
 						 */
-#define GC_THREAD_MIN_SLEEP_TIME	30000	/* milliseconds */
-#define GC_THREAD_MAX_SLEEP_TIME	60000
-#define GC_THREAD_NOGC_SLEEP_TIME	300000	/* wait 5 min */
+#define DEF_GC_THREAD_MIN_SLEEP_TIME	30000	/* milliseconds */
+#define DEF_GC_THREAD_MAX_SLEEP_TIME	60000
+#define DEF_GC_THREAD_NOGC_SLEEP_TIME	300000	/* wait 5 min */
 #define LIMIT_INVALID_BLOCK	40 /* percentage over total user space */
 #define LIMIT_FREE_BLOCK	40 /* percentage over invalid + free space */
 
@@ -25,6 +25,14 @@
 struct f2fs_gc_kthread {
 	struct task_struct *f2fs_gc_task;
 	wait_queue_head_t gc_wait_queue_head;
+
+	/* for gc sleep time */
+	unsigned int min_sleep_time;
+	unsigned int max_sleep_time;
+	unsigned int no_gc_sleep_time;
+
+	/* for changing gc mode */
+	unsigned int gc_idle;
 };
 
 struct inode_entry {
@@ -56,25 +64,25 @@ static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi)
 	return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100;
 }
 
-static inline long increase_sleep_time(long wait)
+static inline long increase_sleep_time(struct f2fs_gc_kthread *gc_th, long wait)
 {
-	if (wait == GC_THREAD_NOGC_SLEEP_TIME)
+	if (wait == gc_th->no_gc_sleep_time)
 		return wait;
 
-	wait += GC_THREAD_MIN_SLEEP_TIME;
-	if (wait > GC_THREAD_MAX_SLEEP_TIME)
-		wait = GC_THREAD_MAX_SLEEP_TIME;
+	wait += gc_th->min_sleep_time;
+	if (wait > gc_th->max_sleep_time)
+		wait = gc_th->max_sleep_time;
 	return wait;
 }
 
-static inline long decrease_sleep_time(long wait)
+static inline long decrease_sleep_time(struct f2fs_gc_kthread *gc_th, long wait)
 {
-	if (wait == GC_THREAD_NOGC_SLEEP_TIME)
-		wait = GC_THREAD_MAX_SLEEP_TIME;
+	if (wait == gc_th->no_gc_sleep_time)
+		wait = gc_th->max_sleep_time;
 
-	wait -= GC_THREAD_MIN_SLEEP_TIME;
-	if (wait <= GC_THREAD_MIN_SLEEP_TIME)
-		wait = GC_THREAD_MIN_SLEEP_TIME;
+	wait -= gc_th->min_sleep_time;
+	if (wait <= gc_th->min_sleep_time)
+		wait = gc_th->min_sleep_time;
 	return wait;
 }
 
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 2b2d45d1..9ab81e7 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -56,7 +56,7 @@ static int do_read_inode(struct inode *inode)
 	if (IS_ERR(node_page))
 		return PTR_ERR(node_page);
 
-	rn = page_address(node_page);
+	rn = F2FS_NODE(node_page);
 	ri = &(rn->i);
 
 	inode->i_mode = le16_to_cpu(ri->i_mode);
@@ -151,9 +151,9 @@ void update_inode(struct inode *inode, struct page *node_page)
 	struct f2fs_node *rn;
 	struct f2fs_inode *ri;
 
-	wait_on_page_writeback(node_page);
+	f2fs_wait_on_page_writeback(node_page, NODE, false);
 
-	rn = page_address(node_page);
+	rn = F2FS_NODE(node_page);
 	ri = &(rn->i);
 
 	ri->i_mode = cpu_to_le16(inode->i_mode);
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 64c0716..4e47518 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -239,7 +239,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
 	if (!de)
 		goto fail;
 
-	err = check_orphan_space(sbi);
+	err = acquire_orphan_inode(sbi);
 	if (err) {
 		kunmap(page);
 		f2fs_put_page(page, 0);
@@ -393,7 +393,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct page *old_dir_page;
-	struct page *old_page;
+	struct page *old_page, *new_page;
 	struct f2fs_dir_entry *old_dir_entry = NULL;
 	struct f2fs_dir_entry *old_entry;
 	struct f2fs_dir_entry *new_entry;
@@ -415,7 +415,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	ilock = mutex_lock_op(sbi);
 
 	if (new_inode) {
-		struct page *new_page;
 
 		err = -ENOTEMPTY;
 		if (old_dir_entry && !f2fs_empty_dir(new_inode))
@@ -427,14 +426,27 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		if (!new_entry)
 			goto out_dir;
 
+		err = acquire_orphan_inode(sbi);
+		if (err)
+			goto put_out_dir;
+
+		if (update_dent_inode(old_inode, &new_dentry->d_name)) {
+			release_orphan_inode(sbi);
+			goto put_out_dir;
+		}
+
 		f2fs_set_link(new_dir, new_entry, new_page, old_inode);
 
 		new_inode->i_ctime = CURRENT_TIME;
 		if (old_dir_entry)
 			drop_nlink(new_inode);
 		drop_nlink(new_inode);
+
 		if (!new_inode->i_nlink)
 			add_orphan_inode(sbi, new_inode->i_ino);
+		else
+			release_orphan_inode(sbi);
+
 		update_inode_page(new_inode);
 	} else {
 		err = f2fs_add_link(new_dentry, old_inode);
@@ -467,6 +479,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	mutex_unlock_op(sbi, ilock);
 	return 0;
 
+put_out_dir:
+	f2fs_put_page(new_page, 1);
 out_dir:
 	if (old_dir_entry) {
 		kunmap(old_dir_page);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index b418aee..f5172e2 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -565,7 +565,7 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
 		return PTR_ERR(page);
 	}
 
-	rn = (struct f2fs_node *)page_address(page);
+	rn = F2FS_NODE(page);
 	if (depth < 3) {
 		for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
 			child_nid = le32_to_cpu(rn->in.nid[i]);
@@ -698,7 +698,7 @@ restart:
 	set_new_dnode(&dn, inode, page, NULL, 0);
 	unlock_page(page);
 
-	rn = page_address(page);
+	rn = F2FS_NODE(page);
 	switch (level) {
 	case 0:
 	case 1:
@@ -1484,8 +1484,8 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
 	SetPageUptodate(ipage);
 	fill_node_footer(ipage, ino, ino, 0, true);
 
-	src = (struct f2fs_node *)page_address(page);
-	dst = (struct f2fs_node *)page_address(ipage);
+	src = F2FS_NODE(page);
+	dst = F2FS_NODE(ipage);
 
 	memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i);
 	dst->i.i_size = 0;
@@ -1535,7 +1535,7 @@ int restore_node_summary(struct f2fs_sb_info *sbi,
 			goto out;
 
 		lock_page(page);
-		rn = (struct f2fs_node *)page_address(page);
+		rn = F2FS_NODE(page);
 		sum_entry->nid = rn->footer.nid;
 		sum_entry->version = 0;
 		sum_entry->ofs_in_node = 0;
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index c65fb4f..87349c4 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -155,8 +155,7 @@ static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
 static inline void fill_node_footer(struct page *page, nid_t nid,
 				nid_t ino, unsigned int ofs, bool reset)
 {
-	void *kaddr = page_address(page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(page);
 	if (reset)
 		memset(rn, 0, sizeof(*rn));
 	rn->footer.nid = cpu_to_le32(nid);
@@ -166,10 +165,8 @@ static inline void fill_node_footer(struct page *page, nid_t nid,
 
 static inline void copy_node_footer(struct page *dst, struct page *src)
 {
-	void *src_addr = page_address(src);
-	void *dst_addr = page_address(dst);
-	struct f2fs_node *src_rn = (struct f2fs_node *)src_addr;
-	struct f2fs_node *dst_rn = (struct f2fs_node *)dst_addr;
+	struct f2fs_node *src_rn = F2FS_NODE(src);
+	struct f2fs_node *dst_rn = F2FS_NODE(dst);
 	memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
 }
 
@@ -177,45 +174,40 @@ static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
-	void *kaddr = page_address(page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(page);
+
 	rn->footer.cp_ver = ckpt->checkpoint_ver;
 	rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
 }
 
 static inline nid_t ino_of_node(struct page *node_page)
 {
-	void *kaddr = page_address(node_page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(node_page);
 	return le32_to_cpu(rn->footer.ino);
 }
 
 static inline nid_t nid_of_node(struct page *node_page)
 {
-	void *kaddr = page_address(node_page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(node_page);
 	return le32_to_cpu(rn->footer.nid);
 }
 
 static inline unsigned int ofs_of_node(struct page *node_page)
 {
-	void *kaddr = page_address(node_page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(node_page);
 	unsigned flag = le32_to_cpu(rn->footer.flag);
 	return flag >> OFFSET_BIT_SHIFT;
 }
 
 static inline unsigned long long cpver_of_node(struct page *node_page)
 {
-	void *kaddr = page_address(node_page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(node_page);
 	return le64_to_cpu(rn->footer.cp_ver);
 }
 
 static inline block_t next_blkaddr_of_node(struct page *node_page)
 {
-	void *kaddr = page_address(node_page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(node_page);
 	return le32_to_cpu(rn->footer.next_blkaddr);
 }
 
@@ -250,7 +242,7 @@ static inline bool IS_DNODE(struct page *node_page)
 
 static inline void set_nid(struct page *p, int off, nid_t nid, bool i)
 {
-	struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
+	struct f2fs_node *rn = F2FS_NODE(p);
 
 	wait_on_page_writeback(p);
 
@@ -263,7 +255,8 @@ static inline void set_nid(struct page *p, int off, nid_t nid, bool i)
 
 static inline nid_t get_nid(struct page *p, int off, bool i)
 {
-	struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
+	struct f2fs_node *rn = F2FS_NODE(p);
+
 	if (i)
 		return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
 	return le32_to_cpu(rn->in.nid[off]);
@@ -314,8 +307,7 @@ static inline void clear_cold_data(struct page *page)
 
 static inline int is_node(struct page *page, int type)
 {
-	void *kaddr = page_address(page);
-	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	struct f2fs_node *rn = F2FS_NODE(page);
 	return le32_to_cpu(rn->footer.flag) & (1 << type);
 }
 
@@ -325,7 +317,7 @@ static inline int is_node(struct page *page, int type)
 
 static inline void set_cold_node(struct inode *inode, struct page *page)
 {
-	struct f2fs_node *rn = (struct f2fs_node *)page_address(page);
+	struct f2fs_node *rn = F2FS_NODE(page);
 	unsigned int flag = le32_to_cpu(rn->footer.flag);
 
 	if (S_ISDIR(inode->i_mode))
@@ -337,7 +329,7 @@ static inline void set_cold_node(struct inode *inode, struct page *page)
 
 static inline void set_mark(struct page *page, int mark, int type)
 {
-	struct f2fs_node *rn = (struct f2fs_node *)page_address(page);
+	struct f2fs_node *rn = F2FS_NODE(page);
 	unsigned int flag = le32_to_cpu(rn->footer.flag);
 	if (mark)
 		flag |= (0x1 << type);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index d56d951..639eb34 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -40,8 +40,7 @@ static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
 
 static int recover_dentry(struct page *ipage, struct inode *inode)
 {
-	void *kaddr = page_address(ipage);
-	struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
+	struct f2fs_node *raw_node = F2FS_NODE(ipage);
 	struct f2fs_inode *raw_inode = &(raw_node->i);
 	nid_t pino = le32_to_cpu(raw_inode->i_pino);
 	struct f2fs_dir_entry *de;
@@ -93,8 +92,7 @@ out:
 
 static int recover_inode(struct inode *inode, struct page *node_page)
 {
-	void *kaddr = page_address(node_page);
-	struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
+	struct f2fs_node *raw_node = F2FS_NODE(node_page);
 	struct f2fs_inode *raw_inode = &(raw_node->i);
 
 	if (!IS_INODE(node_page))
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index a86d125..68e344f 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -611,18 +611,12 @@ static void f2fs_end_io_write(struct bio *bio, int err)
 struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages)
 {
 	struct bio *bio;
-	struct bio_private *priv;
-retry:
-	priv = kmalloc(sizeof(struct bio_private), GFP_NOFS);
-	if (!priv) {
-		cond_resched();
-		goto retry;
-	}
 
 	/* No failure on bio allocation */
 	bio = bio_alloc(GFP_NOIO, npages);
 	bio->bi_bdev = bdev;
-	bio->bi_private = priv;
+	bio->bi_private = NULL;
+
 	return bio;
 }
 
@@ -681,8 +675,17 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
 		do_submit_bio(sbi, type, false);
 alloc_new:
 	if (sbi->bio[type] == NULL) {
+		struct bio_private *priv;
+retry:
+		priv = kmalloc(sizeof(struct bio_private), GFP_NOFS);
+		if (!priv) {
+			cond_resched();
+			goto retry;
+		}
+
 		sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi));
 		sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
+		sbi->bio[type]->bi_private = priv;
 		/*
 		 * The end_io will be assigned at the sumbission phase.
 		 * Until then, let bio_add_page() merge consecutive IOs as much
@@ -702,6 +705,16 @@ alloc_new:
 	trace_f2fs_submit_write_page(page, blk_addr, type);
 }
 
+void f2fs_wait_on_page_writeback(struct page *page,
+				enum page_type type, bool sync)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+	if (PageWriteback(page)) {
+		f2fs_submit_bio(sbi, type, sync);
+		wait_on_page_writeback(page);
+	}
+}
+
 static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
 {
 	struct curseg_info *curseg = CURSEG_I(sbi, type);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 75c7dc3..66d1ec1 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -18,20 +18,25 @@
 #include <linux/parser.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 #include <linux/random.h>
 #include <linux/exportfs.h>
 #include <linux/blkdev.h>
 #include <linux/f2fs_fs.h>
+#include <linux/sysfs.h>
 
 #include "f2fs.h"
 #include "node.h"
 #include "segment.h"
 #include "xattr.h"
+#include "gc.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/f2fs.h>
 
+static struct proc_dir_entry *f2fs_proc_root;
 static struct kmem_cache *f2fs_inode_cachep;
+static struct kset *f2fs_kset;
 
 enum {
 	Opt_gc_background,
@@ -57,6 +62,113 @@ static match_table_t f2fs_tokens = {
 	{Opt_err, NULL},
 };
 
+/* Sysfs support for f2fs */
+struct f2fs_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *);
+	ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *,
+			 const char *, size_t);
+	int offset;
+};
+
+static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
+			struct f2fs_sb_info *sbi, char *buf)
+{
+	struct f2fs_gc_kthread *gc_kth = sbi->gc_thread;
+	unsigned int *ui;
+
+	if (!gc_kth)
+		return -EINVAL;
+
+	ui = (unsigned int *)(((char *)gc_kth) + a->offset);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
+}
+
+static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
+			struct f2fs_sb_info *sbi,
+			const char *buf, size_t count)
+{
+	struct f2fs_gc_kthread *gc_kth = sbi->gc_thread;
+	unsigned long t;
+	unsigned int *ui;
+	ssize_t ret;
+
+	if (!gc_kth)
+		return -EINVAL;
+
+	ui = (unsigned int *)(((char *)gc_kth) + a->offset);
+
+	ret = kstrtoul(skip_spaces(buf), 0, &t);
+	if (ret < 0)
+		return ret;
+	*ui = t;
+	return count;
+}
+
+static ssize_t f2fs_attr_show(struct kobject *kobj,
+				struct attribute *attr, char *buf)
+{
+	struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
+								s_kobj);
+	struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
+
+	return a->show ? a->show(a, sbi, buf) : 0;
+}
+
+static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr,
+						const char *buf, size_t len)
+{
+	struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
+									s_kobj);
+	struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
+
+	return a->store ? a->store(a, sbi, buf, len) : 0;
+}
+
+static void f2fs_sb_release(struct kobject *kobj)
+{
+	struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
+								s_kobj);
+	complete(&sbi->s_kobj_unregister);
+}
+
+#define F2FS_ATTR_OFFSET(_name, _mode, _show, _store, _elname) \
+static struct f2fs_attr f2fs_attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.show	= _show,					\
+	.store	= _store,					\
+	.offset = offsetof(struct f2fs_gc_kthread, _elname),	\
+}
+
+#define F2FS_RW_ATTR(name, elname)	\
+	F2FS_ATTR_OFFSET(name, 0644, f2fs_sbi_show, f2fs_sbi_store, elname)
+
+F2FS_RW_ATTR(gc_min_sleep_time, min_sleep_time);
+F2FS_RW_ATTR(gc_max_sleep_time, max_sleep_time);
+F2FS_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time);
+F2FS_RW_ATTR(gc_idle, gc_idle);
+
+#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
+static struct attribute *f2fs_attrs[] = {
+	ATTR_LIST(gc_min_sleep_time),
+	ATTR_LIST(gc_max_sleep_time),
+	ATTR_LIST(gc_no_gc_sleep_time),
+	ATTR_LIST(gc_idle),
+	NULL,
+};
+
+static const struct sysfs_ops f2fs_attr_ops = {
+	.show	= f2fs_attr_show,
+	.store	= f2fs_attr_store,
+};
+
+static struct kobj_type f2fs_ktype = {
+	.default_attrs	= f2fs_attrs,
+	.sysfs_ops	= &f2fs_attr_ops,
+	.release	= f2fs_sb_release,
+};
+
 void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...)
 {
 	struct va_format vaf;
@@ -223,6 +335,12 @@ static void f2fs_put_super(struct super_block *sb)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
 
+	if (sbi->s_proc) {
+		remove_proc_entry("segment_info", sbi->s_proc);
+		remove_proc_entry(sb->s_id, f2fs_proc_root);
+	}
+	kobject_del(&sbi->s_kobj);
+
 	f2fs_destroy_stats(sbi);
 	stop_gc_thread(sbi);
 
@@ -236,6 +354,8 @@ static void f2fs_put_super(struct super_block *sb)
 	destroy_segment_manager(sbi);
 
 	kfree(sbi->ckpt);
+	kobject_put(&sbi->s_kobj);
+	wait_for_completion(&sbi->s_kobj_unregister);
 
 	sb->s_fs_info = NULL;
 	brelse(sbi->raw_super_buf);
@@ -340,6 +460,36 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 	return 0;
 }
 
+static int segment_info_seq_show(struct seq_file *seq, void *offset)
+{
+	struct super_block *sb = seq->private;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	unsigned int total_segs = le32_to_cpu(sbi->raw_super->segment_count_main);
+	int i;
+
+	for (i = 0; i < total_segs; i++) {
+		seq_printf(seq, "%u", get_valid_blocks(sbi, i, 1));
+		if (i != 0 && (i % 10) == 0)
+			seq_puts(seq, "\n");
+		else
+			seq_puts(seq, " ");
+	}
+	return 0;
+}
+
+static int segment_info_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, segment_info_seq_show, PDE_DATA(inode));
+}
+
+static const struct file_operations f2fs_seq_segment_info_fops = {
+	.owner = THIS_MODULE,
+	.open = segment_info_open_fs,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
 static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
@@ -766,6 +916,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 	if (err)
 		goto fail;
 
+	if (f2fs_proc_root)
+		sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
+
+	if (sbi->s_proc)
+		proc_create_data("segment_info", S_IRUGO, sbi->s_proc,
+				 &f2fs_seq_segment_info_fops, sb);
+
 	if (test_opt(sbi, DISCARD)) {
 		struct request_queue *q = bdev_get_queue(sb->s_bdev);
 		if (!blk_queue_discard(q))
@@ -774,6 +931,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 					"the device does not support discard");
 	}
 
+	sbi->s_kobj.kset = f2fs_kset;
+	init_completion(&sbi->s_kobj_unregister);
+	err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL,
+							"%s", sb->s_id);
+	if (err)
+		goto fail;
+
 	return 0;
 fail:
 	stop_gc_thread(sbi);
@@ -848,22 +1012,28 @@ static int __init init_f2fs_fs(void)
 	err = create_checkpoint_caches();
 	if (err)
 		goto fail;
+	f2fs_kset = kset_create_and_add("f2fs", NULL, fs_kobj);
+	if (!f2fs_kset)
+		goto fail;
 	err = register_filesystem(&f2fs_fs_type);
 	if (err)
 		goto fail;
 	f2fs_create_root_stats();
+	f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
 fail:
 	return err;
 }
 
 static void __exit exit_f2fs_fs(void)
 {
+	remove_proc_entry("fs/f2fs", NULL);
 	f2fs_destroy_root_stats();
 	unregister_filesystem(&f2fs_fs_type);
 	destroy_checkpoint_caches();
 	destroy_gc_caches();
 	destroy_node_manager_caches();
 	destroy_inodecache();
+	kset_unregister(f2fs_kset);
 }
 
 module_init(init_f2fs_fs)
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 9b104f5..00b5810 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -17,8 +17,11 @@
 #include <linux/blkdev.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
+#include <linux/falloc.h>
 #include "fat.h"
 
+static long fat_fallocate(struct file *file, int mode,
+				loff_t offset, loff_t len);
 static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)
 {
 	u32 attr;
@@ -148,6 +151,22 @@ static long fat_generic_compat_ioctl(struct file *filp, unsigned int cmd,
 
 static int fat_file_release(struct inode *inode, struct file *filp)
 {
+
+	struct super_block *sb = inode->i_sb;
+	loff_t mmu_private_ideal;
+
+	/*
+	 * Release unwritten fallocated blocks on file release.
+	 * Do this only when the last open file descriptor is closed.
+	 */
+	mutex_lock(&inode->i_mutex);
+	mmu_private_ideal = round_up(inode->i_size, sb->s_blocksize);
+
+	if (mmu_private_ideal < MSDOS_I(inode)->mmu_private &&
+	    filp->f_dentry->d_count == 1)
+		fat_truncate_blocks(inode, inode->i_size);
+	mutex_unlock(&inode->i_mutex);
+
 	if ((filp->f_mode & FMODE_WRITE) &&
 	     MSDOS_SB(inode->i_sb)->options.flush) {
 		fat_flush_inodes(inode->i_sb, inode, NULL);
@@ -182,6 +201,7 @@ const struct file_operations fat_file_operations = {
 #endif
 	.fsync		= fat_file_fsync,
 	.splice_read	= generic_file_splice_read,
+	.fallocate      = fat_fallocate,
 };
 
 static int fat_cont_expand(struct inode *inode, loff_t size)
@@ -220,6 +240,88 @@ out:
 	return err;
 }
 
+/*
+ * Preallocate space for a file. This implements fat's fallocate file
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests len bytes at offset. If FALLOC_FL_KEEP_SIZE is set
+ * we just allocate clusters without zeroing them out. Otherwise we
+ * allocate and zero out clusters via an expanding truncate. The
+ * allocated clusters are freed in fat_file_release().
+ */
+static long fat_fallocate(struct file *file, int mode,
+				loff_t offset, loff_t len)
+{
+	int cluster, fclus, dclus;
+	int nr_cluster; /* Number of clusters to be allocated */
+	loff_t nr_bytes; /* Number of bytes to be allocated*/
+	loff_t free_bytes; /* Unused bytes in the last cluster of file*/
+	struct inode *inode = file->f_mapping->host;
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	int err = 0;
+
+	/* No support for hole punch or other fallocate flags. */
+	if (mode & ~FALLOC_FL_KEEP_SIZE)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&inode->i_mutex);
+	if ((offset + len) <= MSDOS_I(inode)->mmu_private) {
+		fat_msg(sb, KERN_ERR,
+			"fat_fallocate(): Blocks already allocated");
+		err = -EINVAL;
+		goto error;
+	}
+
+	if (mode & FALLOC_FL_KEEP_SIZE) {
+		/* First compute the number of clusters to be allocated */
+		if (inode->i_size > 0) {
+			err = fat_get_cluster(inode, FAT_ENT_EOF,
+					      &fclus, &dclus);
+			if (err < 0) {
+				fat_msg(sb, KERN_ERR,
+					"fat_fallocate(): fat_get_cluster() error");
+				goto error;
+			}
+			free_bytes = ((fclus + 1) << sbi->cluster_bits) -
+				     inode->i_size;
+			nr_bytes = offset + len - inode->i_size - free_bytes;
+			MSDOS_I(inode)->mmu_private = (fclus + 1) <<
+						      sbi->cluster_bits;
+		} else
+			nr_bytes = offset + len - inode->i_size;
+
+		nr_cluster = (nr_bytes + (sbi->cluster_size - 1)) >>
+			     sbi->cluster_bits;
+
+		/* Start the allocation.We are not zeroing out the clusters */
+		while (nr_cluster-- > 0) {
+			err = fat_alloc_clusters(inode, &cluster, 1);
+			if (err) {
+				fat_msg(sb, KERN_ERR,
+					"fat_fallocate(): fat_alloc_clusters() error");
+				goto error;
+			}
+			err = fat_chain_add(inode, cluster, 1);
+			if (err) {
+				fat_free_clusters(inode, cluster);
+				goto error;
+			}
+			MSDOS_I(inode)->mmu_private += sbi->cluster_size;
+		}
+	} else {
+		/* This is just an expanding truncate */
+		err = fat_cont_expand(inode, (offset + len));
+		if (err) {
+			fat_msg(sb, KERN_ERR,
+				"fat_fallocate(): fat_cont_expand() error");
+		}
+	}
+
+error:
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+
 /* Free all clusters after the skip'th cluster. */
 static int fat_free(struct inode *inode, int skip)
 {
@@ -386,6 +488,9 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
 	struct inode *inode = dentry->d_inode;
 	unsigned int ia_valid;
 	int error;
+	loff_t mmu_private_ideal;
+
+	mmu_private_ideal = round_up(inode->i_size, dentry->d_sb->s_blocksize);
 
 	/* Check for setting the inode time. */
 	ia_valid = attr->ia_valid;
@@ -411,7 +516,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
 	if (attr->ia_valid & ATTR_SIZE) {
 		inode_dio_wait(inode);
 
-		if (attr->ia_size > inode->i_size) {
+		if (attr->ia_size > inode->i_size &&
+		    MSDOS_I(inode)->mmu_private <= mmu_private_ideal) {
 			error = fat_cont_expand(inode, attr->ia_size);
 			if (error || attr->ia_valid == ATTR_SIZE)
 				goto out;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 11b51bb..fc6b37d 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -152,11 +152,65 @@ static void fat_write_failed(struct address_space *mapping, loff_t to)
 	}
 }
 
+static int fat_zero_falloc_area(struct file *file,
+				struct address_space *mapping, loff_t pos)
+{
+	struct page *page;
+	struct inode *inode = mapping->host;
+	loff_t curpos = i_size_read(inode);
+	size_t count = pos - curpos;
+	int err;
+
+	do {
+		unsigned offset;
+		size_t bytes;
+		void *fsdata;
+
+		offset = (curpos & (PAGE_CACHE_SIZE - 1));
+		bytes = PAGE_CACHE_SIZE - offset;
+		bytes = min(bytes, count);
+
+		err = pagecache_write_begin(NULL, mapping, curpos, bytes,
+					AOP_FLAG_UNINTERRUPTIBLE,
+					&page, &fsdata);
+		if (err)
+			break;
+
+		zero_user(page, offset, bytes);
+
+		err = pagecache_write_end(NULL, mapping, curpos, bytes, bytes,
+					page, fsdata);
+		if (err < 0)
+			break;
+		curpos += bytes;
+		count -= bytes;
+		err = 0;
+	} while (count);
+
+	return err;
+}
+
 static int fat_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned flags,
 			struct page **pagep, void **fsdata)
 {
 	int err;
+	loff_t mmu_private_ideal, mmu_private_actual;
+	loff_t size;
+	struct inode *inode = mapping->host;
+	struct super_block *sb = inode->i_sb;
+
+	size = i_size_read(inode);
+	mmu_private_actual = MSDOS_I(inode)->mmu_private;
+	mmu_private_ideal = round_up(size, sb->s_blocksize);
+	if ((mmu_private_actual > mmu_private_ideal) && (pos > size)) {
+		err = fat_zero_falloc_area(file, mapping, pos);
+		if (err) {
+			fat_msg(sb, KERN_ERR,
+				"Error (%d) zeroing fallocated area", err);
+			return err;
+		}
+	}
 
 	*pagep = NULL;
 	err = cont_write_begin(file, mapping, pos, len, flags,
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 6599222..65343c3 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -730,14 +730,14 @@ static int __init fcntl_init(void)
 	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 	 * is defined as O_NONBLOCK on some platforms and not on others.
 	 */
-	BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
+	BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
 		O_RDONLY	| O_WRONLY	| O_RDWR	|
 		O_CREAT		| O_EXCL	| O_NOCTTY	|
 		O_TRUNC		| O_APPEND	| /* O_NONBLOCK	| */
 		__O_SYNC	| O_DSYNC	| FASYNC	|
 		O_DIRECT	| O_LARGEFILE	| O_DIRECTORY	|
 		O_NOFOLLOW	| O_NOATIME	| O_CLOEXEC	|
-		__FMODE_EXEC	| O_PATH
+		__FMODE_EXEC	| O_PATH	| __O_TMPFILE
 		));
 
 	fasync_cache = kmem_cache_create("fasync_cache",
diff --git a/fs/file_table.c b/fs/file_table.c
index b44e4c5..7528930 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -311,8 +311,7 @@ void fput(struct file *file)
 				return;
 			/*
 			 * After this task has run exit_task_work(),
-			 * task_work_add() will fail.  free_ipc_ns()->
-			 * shm_destroy() can do this.  Fall through to delayed
+			 * task_work_add() will fail.  Fall through to delayed
 			 * fput to avoid leaking *file.
 			 */
 		}
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index d479ab3..24350b8 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -890,7 +890,7 @@ int __fscache_write_page(struct fscache_cookie *cookie,
 		(1 << FSCACHE_OP_WAITING) |
 		(1 << FSCACHE_OP_UNUSE_COOKIE);
 
-	ret = radix_tree_preload(gfp & ~__GFP_HIGHMEM);
+	ret = radix_tree_maybe_preload(gfp & ~__GFP_HIGHMEM);
 	if (ret < 0)
 		goto nomem_free;
 
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index aef34b1..adbfd66 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -568,6 +568,7 @@ static ssize_t cuse_class_waiting_show(struct device *dev,
 
 	return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting));
 }
+static DEVICE_ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL);
 
 static ssize_t cuse_class_abort_store(struct device *dev,
 				      struct device_attribute *attr,
@@ -578,12 +579,14 @@ static ssize_t cuse_class_abort_store(struct device *dev,
 	fuse_abort_conn(&cc->fc);
 	return count;
 }
+static DEVICE_ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store);
 
-static struct device_attribute cuse_class_dev_attrs[] = {
-	__ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL),
-	__ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store),
-	{ }
+static struct attribute *cuse_class_dev_attrs[] = {
+	&dev_attr_waiting.attr,
+	&dev_attr_abort.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(cuse_class_dev);
 
 static struct miscdevice cuse_miscdev = {
 	.minor		= MISC_DYNAMIC_MINOR,
@@ -609,7 +612,7 @@ static int __init cuse_init(void)
 	if (IS_ERR(cuse_class))
 		return PTR_ERR(cuse_class);
 
-	cuse_class->dev_attrs = cuse_class_dev_attrs;
+	cuse_class->dev_groups = cuse_class_dev_groups;
 
 	rc = misc_register(&cuse_miscdev);
 	if (rc) {
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 9435384..a9d8caf 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1428,21 +1428,22 @@ __acquires(&lru_lock)
  * gfs2_dispose_glock_lru() above.
  */
 
-static void gfs2_scan_glock_lru(int nr)
+static long gfs2_scan_glock_lru(int nr)
 {
 	struct gfs2_glock *gl;
 	LIST_HEAD(skipped);
 	LIST_HEAD(dispose);
+	long freed = 0;
 
 	spin_lock(&lru_lock);
-	while(nr && !list_empty(&lru_list)) {
+	while ((nr-- >= 0) && !list_empty(&lru_list)) {
 		gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru);
 
 		/* Test for being demotable */
 		if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
 			list_move(&gl->gl_lru, &dispose);
 			atomic_dec(&lru_count);
-			nr--;
+			freed++;
 			continue;
 		}
 
@@ -1452,23 +1453,28 @@ static void gfs2_scan_glock_lru(int nr)
 	if (!list_empty(&dispose))
 		gfs2_dispose_glock_lru(&dispose);
 	spin_unlock(&lru_lock);
+
+	return freed;
 }
 
-static int gfs2_shrink_glock_memory(struct shrinker *shrink,
-				    struct shrink_control *sc)
+static unsigned long gfs2_glock_shrink_scan(struct shrinker *shrink,
+					    struct shrink_control *sc)
 {
-	if (sc->nr_to_scan) {
-		if (!(sc->gfp_mask & __GFP_FS))
-			return -1;
-		gfs2_scan_glock_lru(sc->nr_to_scan);
-	}
+	if (!(sc->gfp_mask & __GFP_FS))
+		return SHRINK_STOP;
+	return gfs2_scan_glock_lru(sc->nr_to_scan);
+}
 
-	return (atomic_read(&lru_count) / 100) * sysctl_vfs_cache_pressure;
+static unsigned long gfs2_glock_shrink_count(struct shrinker *shrink,
+					     struct shrink_control *sc)
+{
+	return vfs_pressure_ratio(atomic_read(&lru_count));
 }
 
 static struct shrinker glock_shrinker = {
-	.shrink = gfs2_shrink_glock_memory,
 	.seeks = DEFAULT_SEEKS,
+	.count_objects = gfs2_glock_shrink_count,
+	.scan_objects = gfs2_glock_shrink_scan,
 };
 
 /**
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 5f2e522..e2e0a90 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -47,7 +47,8 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
  * None of the buffers should be dirty, locked, or pinned.
  */
 
-static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
+static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
+			     unsigned int nr_revokes)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct list_head *head = &gl->gl_ail_list;
@@ -57,7 +58,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
 	gfs2_log_lock(sdp);
 	spin_lock(&sdp->sd_ail_lock);
-	list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
+	list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) {
+		if (nr_revokes == 0)
+			break;
 		bh = bd->bd_bh;
 		if (bh->b_state & b_state) {
 			if (fsync)
@@ -65,6 +68,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 			gfs2_ail_error(gl, bh);
 		}
 		gfs2_trans_add_revoke(sdp, bd);
+		nr_revokes--;
 	}
 	GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
 	spin_unlock(&sdp->sd_ail_lock);
@@ -91,7 +95,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	WARN_ON_ONCE(current->journal_info);
 	current->journal_info = &tr;
 
-	__gfs2_ail_flush(gl, 0);
+	__gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
 	gfs2_trans_end(sdp);
 	gfs2_log_flush(sdp, NULL);
@@ -101,15 +105,19 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	unsigned int revokes = atomic_read(&gl->gl_ail_count);
+	unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
 	int ret;
 
 	if (!revokes)
 		return;
 
-	ret = gfs2_trans_begin(sdp, 0, revokes);
+	while (revokes > max_revokes)
+		max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64);
+
+	ret = gfs2_trans_begin(sdp, 0, max_revokes);
 	if (ret)
 		return;
-	__gfs2_ail_flush(gl, fsync);
+	__gfs2_ail_flush(gl, fsync, max_revokes);
 	gfs2_trans_end(sdp);
 	gfs2_log_flush(sdp, NULL);
 }
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index bbb2715..a01b8fd 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -594,7 +594,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 		}
 		gfs2_glock_dq_uninit(ghs);
 		if (IS_ERR(d))
-			return PTR_RET(d);
+			return PTR_ERR(d);
 		return error;
 	} else if (error != -ENOENT) {
 		goto fail_gunlock;
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 17c5b5d..010b9fb 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -579,6 +579,24 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
 	return error;
 }
 
+/**
+ * gfs2_meta_sync - Sync all buffers associated with a glock
+ * @gl: The glock
+ *
+ */
+
+static void gfs2_meta_sync(struct gfs2_glock *gl)
+{
+	struct address_space *mapping = gfs2_glock2aspace(gl);
+	int error;
+
+	filemap_fdatawrite(mapping);
+	error = filemap_fdatawait(mapping);
+
+	if (error)
+		gfs2_io_error(gl->gl_sbd);
+}
+
 static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
 {
 	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index e04d0e0..351586e 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -32,7 +32,8 @@
 struct workqueue_struct *gfs2_control_wq;
 
 static struct shrinker qd_shrinker = {
-	.shrink = gfs2_shrink_qd_memory,
+	.count_objects = gfs2_qd_shrink_count,
+	.scan_objects = gfs2_qd_shrink_scan,
 	.seeks = DEFAULT_SEEKS,
 };
 
@@ -155,7 +156,7 @@ static int __init init_gfs2_fs(void)
 		goto fail_wq;
 
 	gfs2_control_wq = alloc_workqueue("gfs2_control",
-			       WQ_NON_REENTRANT | WQ_UNBOUND | WQ_FREEZABLE, 0);
+					  WQ_UNBOUND | WQ_FREEZABLE, 0);
 	if (!gfs2_control_wq)
 		goto fail_recovery;
 
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 0da3906..9324150 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -98,24 +98,6 @@ const struct address_space_operations gfs2_meta_aops = {
 };
 
 /**
- * gfs2_meta_sync - Sync all buffers associated with a glock
- * @gl: The glock
- *
- */
-
-void gfs2_meta_sync(struct gfs2_glock *gl)
-{
-	struct address_space *mapping = gfs2_glock2aspace(gl);
-	int error;
-
-	filemap_fdatawrite(mapping);
-	error = filemap_fdatawait(mapping);
-
-	if (error)
-		gfs2_io_error(gl->gl_sbd);
-}
-
-/**
  * gfs2_getbuf - Get a buffer with a given address space
  * @gl: the glock
  * @blkno: the block number (filesystem scope)
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index 0d4c843..4823b93 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -48,21 +48,17 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
 		return inode->i_sb->s_fs_info;
 }
 
-void gfs2_meta_sync(struct gfs2_glock *gl);
-
-struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
-int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno,
-		   int flags, struct buffer_head **bhp);
-int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
-struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create);
-
-void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr,
-			      int meta);
-
-void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
-
-int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
-			      struct buffer_head **bhp);
+extern struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
+extern int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
+			  struct buffer_head **bhp);
+extern int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
+extern struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno,
+				       int create);
+extern void gfs2_remove_from_journal(struct buffer_head *bh,
+				     struct gfs2_trans *tr, int meta);
+extern void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
+extern int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
+				     struct buffer_head **bhp);
 
 static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
 					 struct buffer_head **bhp)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 3768c2f..db44135 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -75,17 +75,16 @@ static LIST_HEAD(qd_lru_list);
 static atomic_t qd_lru_count = ATOMIC_INIT(0);
 static DEFINE_SPINLOCK(qd_lru_lock);
 
-int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
+unsigned long gfs2_qd_shrink_scan(struct shrinker *shrink,
+				  struct shrink_control *sc)
 {
 	struct gfs2_quota_data *qd;
 	struct gfs2_sbd *sdp;
 	int nr_to_scan = sc->nr_to_scan;
-
-	if (nr_to_scan == 0)
-		goto out;
+	long freed = 0;
 
 	if (!(sc->gfp_mask & __GFP_FS))
-		return -1;
+		return SHRINK_STOP;
 
 	spin_lock(&qd_lru_lock);
 	while (nr_to_scan && !list_empty(&qd_lru_list)) {
@@ -110,11 +109,16 @@ int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
 		kmem_cache_free(gfs2_quotad_cachep, qd);
 		spin_lock(&qd_lru_lock);
 		nr_to_scan--;
+		freed++;
 	}
 	spin_unlock(&qd_lru_lock);
+	return freed;
+}
 
-out:
-	return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100;
+unsigned long gfs2_qd_shrink_count(struct shrinker *shrink,
+				   struct shrink_control *sc)
+{
+	return vfs_pressure_ratio(atomic_read(&qd_lru_count));
 }
 
 static u64 qd2index(struct gfs2_quota_data *qd)
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index 4f5e6e4..0f64d9d 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -53,8 +53,10 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
 	return ret;
 }
 
-extern int gfs2_shrink_qd_memory(struct shrinker *shrink,
-				 struct shrink_control *sc);
+extern unsigned long gfs2_qd_shrink_count(struct shrinker *shrink,
+					  struct shrink_control *sc);
+extern unsigned long gfs2_qd_shrink_scan(struct shrinker *shrink,
+					 struct shrink_control *sc);
 extern const struct quotactl_ops gfs2_quotactl_ops;
 
 #endif /* __QUOTA_DOT_H__ */
diff --git a/fs/hfsplus/Kconfig b/fs/hfsplus/Kconfig
index a633718..24bc20f 100644
--- a/fs/hfsplus/Kconfig
+++ b/fs/hfsplus/Kconfig
@@ -11,3 +11,21 @@ config HFSPLUS_FS
 	  MacOS 8. It includes all Mac specific filesystem data such as
 	  data forks and creator codes, but it also has several UNIX
 	  style features such as file ownership and permissions.
+
+config HFSPLUS_FS_POSIX_ACL
+	bool "HFS+ POSIX Access Control Lists"
+	depends on HFSPLUS_FS
+	select FS_POSIX_ACL
+	help
+	  POSIX Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
+
+	  To learn more about Access Control Lists, visit the POSIX ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  It needs to understand that POSIX ACLs are treated only under
+	  Linux. POSIX ACLs doesn't mean something under Mac OS X.
+	  Mac OS X beginning with version 10.4 ("Tiger") support NFSv4 ACLs,
+	  which are part of the NFSv4 standard.
+
+	  If you don't know what Access Control Lists are, say N
diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile
index 09d278b..683fca2 100644
--- a/fs/hfsplus/Makefile
+++ b/fs/hfsplus/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
 hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
 		bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
 		attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
+
+hfsplus-$(CONFIG_HFSPLUS_FS_POSIX_ACL)	+= posix_acl.o
diff --git a/fs/hfsplus/acl.h b/fs/hfsplus/acl.h
new file mode 100644
index 0000000..07c0d49
--- /dev/null
+++ b/fs/hfsplus/acl.h
@@ -0,0 +1,30 @@
+/*
+ * linux/fs/hfsplus/acl.h
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Handler for Posix Access Control Lists (ACLs) support.
+ */
+
+#include <linux/posix_acl_xattr.h>
+
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+
+/* posix_acl.c */
+struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type);
+extern int hfsplus_posix_acl_chmod(struct inode *);
+extern int hfsplus_init_posix_acl(struct inode *, struct inode *);
+
+#else  /* CONFIG_HFSPLUS_FS_POSIX_ACL */
+#define hfsplus_get_posix_acl NULL
+
+static inline int hfsplus_posix_acl_chmod(struct inode *inode)
+{
+	return 0;
+}
+
+static inline int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
+{
+	return 0;
+}
+#endif  /* CONFIG_HFSPLUS_FS_POSIX_ACL */
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index d8ce4bd..4a4fea0 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -16,6 +16,7 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 #include "xattr.h"
+#include "acl.h"
 
 static inline void hfsplus_instantiate(struct dentry *dentry,
 				       struct inode *inode, u32 cnid)
@@ -529,6 +530,9 @@ const struct inode_operations hfsplus_dir_inode_operations = {
 	.getxattr		= generic_getxattr,
 	.listxattr		= hfsplus_listxattr,
 	.removexattr		= hfsplus_removexattr,
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+	.get_acl		= hfsplus_get_posix_acl,
+#endif
 };
 
 const struct file_operations hfsplus_dir_operations = {
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index ede7931..2b9cd01 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -30,6 +30,7 @@
 #define DBG_EXTENT	0x00000020
 #define DBG_BITMAP	0x00000040
 #define DBG_ATTR_MOD	0x00000080
+#define DBG_ACL_MOD	0x00000100
 
 #if 0
 #define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index f833d35..4d2edae 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -19,6 +19,7 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 #include "xattr.h"
+#include "acl.h"
 
 static int hfsplus_readpage(struct file *file, struct page *page)
 {
@@ -316,6 +317,13 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
 
 	setattr_copy(inode, attr);
 	mark_inode_dirty(inode);
+
+	if (attr->ia_valid & ATTR_MODE) {
+		error = hfsplus_posix_acl_chmod(inode);
+		if (unlikely(error))
+			return error;
+	}
+
 	return 0;
 }
 
@@ -383,6 +391,9 @@ static const struct inode_operations hfsplus_file_inode_operations = {
 	.getxattr	= generic_getxattr,
 	.listxattr	= hfsplus_listxattr,
 	.removexattr	= hfsplus_removexattr,
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+	.get_acl	= hfsplus_get_posix_acl,
+#endif
 };
 
 static const struct file_operations hfsplus_file_operations = {
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
new file mode 100644
index 0000000..b609cc1
--- /dev/null
+++ b/fs/hfsplus/posix_acl.c
@@ -0,0 +1,274 @@
+/*
+ * linux/fs/hfsplus/posix_acl.c
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Handler for Posix Access Control Lists (ACLs) support.
+ */
+
+#include "hfsplus_fs.h"
+#include "xattr.h"
+#include "acl.h"
+
+struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
+{
+	struct posix_acl *acl;
+	char *xattr_name;
+	char *value = NULL;
+	ssize_t size;
+
+	acl = get_cached_acl(inode, type);
+	if (acl != ACL_NOT_CACHED)
+		return acl;
+
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		xattr_name = POSIX_ACL_XATTR_ACCESS;
+		break;
+	case ACL_TYPE_DEFAULT:
+		xattr_name = POSIX_ACL_XATTR_DEFAULT;
+		break;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	size = __hfsplus_getxattr(inode, xattr_name, NULL, 0);
+
+	if (size > 0) {
+		value = (char *)hfsplus_alloc_attr_entry();
+		if (unlikely(!value))
+			return ERR_PTR(-ENOMEM);
+		size = __hfsplus_getxattr(inode, xattr_name, value, size);
+	}
+
+	if (size > 0)
+		acl = posix_acl_from_xattr(&init_user_ns, value, size);
+	else if (size == -ENODATA)
+		acl = NULL;
+	else
+		acl = ERR_PTR(size);
+
+	hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
+
+	if (!IS_ERR(acl))
+		set_cached_acl(inode, type, acl);
+
+	return acl;
+}
+
+static int hfsplus_set_posix_acl(struct inode *inode,
+					int type,
+					struct posix_acl *acl)
+{
+	int err;
+	char *xattr_name;
+	size_t size = 0;
+	char *value = NULL;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		xattr_name = POSIX_ACL_XATTR_ACCESS;
+		if (acl) {
+			err = posix_acl_equiv_mode(acl, &inode->i_mode);
+			if (err < 0)
+				return err;
+		}
+		err = 0;
+		break;
+
+	case ACL_TYPE_DEFAULT:
+		xattr_name = POSIX_ACL_XATTR_DEFAULT;
+		if (!S_ISDIR(inode->i_mode))
+			return acl ? -EACCES : 0;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (acl) {
+		size = posix_acl_xattr_size(acl->a_count);
+		if (unlikely(size > HFSPLUS_MAX_INLINE_DATA_SIZE))
+			return -ENOMEM;
+		value = (char *)hfsplus_alloc_attr_entry();
+		if (unlikely(!value))
+			return -ENOMEM;
+		err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
+		if (unlikely(err < 0))
+			goto end_set_acl;
+	}
+
+	err = __hfsplus_setxattr(inode, xattr_name, value, size, 0);
+
+end_set_acl:
+	hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
+
+	if (!err)
+		set_cached_acl(inode, type, acl);
+
+	return err;
+}
+
+int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
+{
+	int err = 0;
+	struct posix_acl *acl = NULL;
+
+	hfs_dbg(ACL_MOD,
+		"[%s]: ino %lu, dir->ino %lu\n",
+		__func__, inode->i_ino, dir->i_ino);
+
+	if (S_ISLNK(inode->i_mode))
+		return 0;
+
+	acl = hfsplus_get_posix_acl(dir, ACL_TYPE_DEFAULT);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+
+	if (acl) {
+		if (S_ISDIR(inode->i_mode)) {
+			err = hfsplus_set_posix_acl(inode,
+							ACL_TYPE_DEFAULT,
+							acl);
+			if (unlikely(err))
+				goto init_acl_cleanup;
+		}
+
+		err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
+		if (unlikely(err < 0))
+			return err;
+
+		if (err > 0)
+			err = hfsplus_set_posix_acl(inode,
+							ACL_TYPE_ACCESS,
+							acl);
+	} else
+		inode->i_mode &= ~current_umask();
+
+init_acl_cleanup:
+	posix_acl_release(acl);
+	return err;
+}
+
+int hfsplus_posix_acl_chmod(struct inode *inode)
+{
+	int err;
+	struct posix_acl *acl;
+
+	hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	acl = hfsplus_get_posix_acl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl) || !acl)
+		return PTR_ERR(acl);
+
+	err = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (unlikely(err))
+		return err;
+
+	err = hfsplus_set_posix_acl(inode, ACL_TYPE_ACCESS, acl);
+	posix_acl_release(acl);
+	return err;
+}
+
+static int hfsplus_xattr_get_posix_acl(struct dentry *dentry,
+					const char *name,
+					void *buffer,
+					size_t size,
+					int type)
+{
+	int err = 0;
+	struct posix_acl *acl;
+
+	hfs_dbg(ACL_MOD,
+		"[%s]: ino %lu, buffer %p, size %zu, type %#x\n",
+		__func__, dentry->d_inode->i_ino, buffer, size, type);
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+
+	acl = hfsplus_get_posix_acl(dentry->d_inode, type);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (acl == NULL)
+		return -ENODATA;
+
+	err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
+	posix_acl_release(acl);
+
+	return err;
+}
+
+static int hfsplus_xattr_set_posix_acl(struct dentry *dentry,
+					const char *name,
+					const void *value,
+					size_t size,
+					int flags,
+					int type)
+{
+	int err = 0;
+	struct inode *inode = dentry->d_inode;
+	struct posix_acl *acl = NULL;
+
+	hfs_dbg(ACL_MOD,
+		"[%s]: ino %lu, value %p, size %zu, flags %#x, type %#x\n",
+		__func__, inode->i_ino, value, size, flags, type);
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+
+	if (!inode_owner_or_capable(inode))
+		return -EPERM;
+
+	if (value) {
+		acl = posix_acl_from_xattr(&init_user_ns, value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		else if (acl) {
+			err = posix_acl_valid(acl);
+			if (err)
+				goto end_xattr_set_acl;
+		}
+	}
+
+	err = hfsplus_set_posix_acl(inode, type, acl);
+
+end_xattr_set_acl:
+	posix_acl_release(acl);
+	return err;
+}
+
+static size_t hfsplus_xattr_list_posix_acl(struct dentry *dentry,
+						char *list,
+						size_t list_size,
+						const char *name,
+						size_t name_len,
+						int type)
+{
+	/*
+	 * This method is not used.
+	 * It is used hfsplus_listxattr() instead of generic_listxattr().
+	 */
+	return -EOPNOTSUPP;
+}
+
+const struct xattr_handler hfsplus_xattr_acl_access_handler = {
+	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
+	.list	= hfsplus_xattr_list_posix_acl,
+	.get	= hfsplus_xattr_get_posix_acl,
+	.set	= hfsplus_xattr_set_posix_acl,
+};
+
+const struct xattr_handler hfsplus_xattr_acl_default_handler = {
+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
+	.list	= hfsplus_xattr_list_posix_acl,
+	.get	= hfsplus_xattr_get_posix_acl,
+	.set	= hfsplus_xattr_set_posix_acl,
+};
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index f663461..bd8471f 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -8,11 +8,16 @@
 
 #include "hfsplus_fs.h"
 #include "xattr.h"
+#include "acl.h"
 
 const struct xattr_handler *hfsplus_xattr_handlers[] = {
 	&hfsplus_xattr_osx_handler,
 	&hfsplus_xattr_user_handler,
 	&hfsplus_xattr_trusted_handler,
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+	&hfsplus_xattr_acl_access_handler,
+	&hfsplus_xattr_acl_default_handler,
+#endif
 	&hfsplus_xattr_security_handler,
 	NULL
 };
@@ -46,11 +51,58 @@ static inline int is_known_namespace(const char *name)
 	return true;
 }
 
+static int can_set_system_xattr(struct inode *inode, const char *name,
+				const void *value, size_t size)
+{
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+	struct posix_acl *acl;
+	int err;
+
+	if (!inode_owner_or_capable(inode))
+		return -EPERM;
+
+	/*
+	 * POSIX_ACL_XATTR_ACCESS is tied to i_mode
+	 */
+	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
+		acl = posix_acl_from_xattr(&init_user_ns, value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		if (acl) {
+			err = posix_acl_equiv_mode(acl, &inode->i_mode);
+			posix_acl_release(acl);
+			if (err < 0)
+				return err;
+			mark_inode_dirty(inode);
+		}
+		/*
+		 * We're changing the ACL.  Get rid of the cached one
+		 */
+		forget_cached_acl(inode, ACL_TYPE_ACCESS);
+
+		return 0;
+	} else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
+		acl = posix_acl_from_xattr(&init_user_ns, value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		posix_acl_release(acl);
+
+		/*
+		 * We're changing the default ACL.  Get rid of the cached one
+		 */
+		forget_cached_acl(inode, ACL_TYPE_DEFAULT);
+
+		return 0;
+	}
+#endif /* CONFIG_HFSPLUS_FS_POSIX_ACL */
+	return -EOPNOTSUPP;
+}
+
 static int can_set_xattr(struct inode *inode, const char *name,
 				const void *value, size_t value_len)
 {
 	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
-		return -EOPNOTSUPP; /* TODO: implement ACL support */
+		return can_set_system_xattr(inode, name, value, value_len);
 
 	if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) {
 		/*
@@ -253,11 +305,10 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
 	return len;
 }
 
-static ssize_t hfsplus_getxattr_finder_info(struct dentry *dentry,
+static ssize_t hfsplus_getxattr_finder_info(struct inode *inode,
 						void *value, size_t size)
 {
 	ssize_t res = 0;
-	struct inode *inode = dentry->d_inode;
 	struct hfs_find_data fd;
 	u16 entry_type;
 	u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo);
@@ -304,10 +355,9 @@ end_getxattr_finder_info:
 	return res;
 }
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
 			 void *value, size_t size)
 {
-	struct inode *inode = dentry->d_inode;
 	struct hfs_find_data fd;
 	hfsplus_attr_entry *entry;
 	__be32 xattr_record_type;
@@ -333,7 +383,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
 	}
 
 	if (!strcmp_xattr_finder_info(name))
-		return hfsplus_getxattr_finder_info(dentry, value, size);
+		return hfsplus_getxattr_finder_info(inode, value, size);
 
 	if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
 		return -EOPNOTSUPP;
diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h
index 847b695..841b569 100644
--- a/fs/hfsplus/xattr.h
+++ b/fs/hfsplus/xattr.h
@@ -14,8 +14,8 @@
 extern const struct xattr_handler hfsplus_xattr_osx_handler;
 extern const struct xattr_handler hfsplus_xattr_user_handler;
 extern const struct xattr_handler hfsplus_xattr_trusted_handler;
-/*extern const struct xattr_handler hfsplus_xattr_acl_access_handler;*/
-/*extern const struct xattr_handler hfsplus_xattr_acl_default_handler;*/
+extern const struct xattr_handler hfsplus_xattr_acl_access_handler;
+extern const struct xattr_handler hfsplus_xattr_acl_default_handler;
 extern const struct xattr_handler hfsplus_xattr_security_handler;
 
 extern const struct xattr_handler *hfsplus_xattr_handlers[];
@@ -29,9 +29,17 @@ static inline int hfsplus_setxattr(struct dentry *dentry, const char *name,
 	return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags);
 }
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
 			void *value, size_t size);
 
+static inline ssize_t hfsplus_getxattr(struct dentry *dentry,
+					const char *name,
+					void *value,
+					size_t size)
+{
+	return __hfsplus_getxattr(dentry->d_inode, name, value, size);
+}
+
 ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
 int hfsplus_removexattr(struct dentry *dentry, const char *name);
@@ -39,22 +47,7 @@ int hfsplus_removexattr(struct dentry *dentry, const char *name);
 int hfsplus_init_security(struct inode *inode, struct inode *dir,
 				const struct qstr *qstr);
 
-static inline int hfsplus_init_acl(struct inode *inode, struct inode *dir)
-{
-	/*TODO: implement*/
-	return 0;
-}
-
-static inline int hfsplus_init_inode_security(struct inode *inode,
-						struct inode *dir,
-						const struct qstr *qstr)
-{
-	int err;
-
-	err = hfsplus_init_acl(inode, dir);
-	if (!err)
-		err = hfsplus_init_security(inode, dir, qstr);
-	return err;
-}
+int hfsplus_init_inode_security(struct inode *inode, struct inode *dir,
+				const struct qstr *qstr);
 
 #endif
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index 83b842f..0072276 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -9,6 +9,7 @@
 #include <linux/security.h>
 #include "hfsplus_fs.h"
 #include "xattr.h"
+#include "acl.h"
 
 static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
 					void *buffer, size_t size, int type)
@@ -96,6 +97,18 @@ int hfsplus_init_security(struct inode *inode, struct inode *dir,
 					&hfsplus_initxattrs, NULL);
 }
 
+int hfsplus_init_inode_security(struct inode *inode,
+						struct inode *dir,
+						const struct qstr *qstr)
+{
+	int err;
+
+	err = hfsplus_init_posix_acl(inode, dir);
+	if (!err)
+		err = hfsplus_init_security(inode, dir, qstr);
+	return err;
+}
+
 const struct xattr_handler hfsplus_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
 	.list	= hfsplus_security_listxattr,
diff --git a/fs/inode.c b/fs/inode.c
index d6dfb09..e315c0a 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -17,6 +17,7 @@
 #include <linux/prefetch.h>
 #include <linux/buffer_head.h> /* for inode_has_buffers */
 #include <linux/ratelimit.h>
+#include <linux/list_lru.h>
 #include "internal.h"
 
 /*
@@ -24,7 +25,7 @@
  *
  * inode->i_lock protects:
  *   inode->i_state, inode->i_hash, __iget()
- * inode->i_sb->s_inode_lru_lock protects:
+ * Inode LRU list locks protect:
  *   inode->i_sb->s_inode_lru, inode->i_lru
  * inode_sb_list_lock protects:
  *   sb->s_inodes, inode->i_sb_list
@@ -37,7 +38,7 @@
  *
  * inode_sb_list_lock
  *   inode->i_lock
- *     inode->i_sb->s_inode_lru_lock
+ *     Inode LRU list locks
  *
  * bdi->wb.list_lock
  *   inode->i_lock
@@ -70,33 +71,33 @@ EXPORT_SYMBOL(empty_aops);
  */
 struct inodes_stat_t inodes_stat;
 
-static DEFINE_PER_CPU(unsigned int, nr_inodes);
-static DEFINE_PER_CPU(unsigned int, nr_unused);
+static DEFINE_PER_CPU(unsigned long, nr_inodes);
+static DEFINE_PER_CPU(unsigned long, nr_unused);
 
 static struct kmem_cache *inode_cachep __read_mostly;
 
-static int get_nr_inodes(void)
+static long get_nr_inodes(void)
 {
 	int i;
-	int sum = 0;
+	long sum = 0;
 	for_each_possible_cpu(i)
 		sum += per_cpu(nr_inodes, i);
 	return sum < 0 ? 0 : sum;
 }
 
-static inline int get_nr_inodes_unused(void)
+static inline long get_nr_inodes_unused(void)
 {
 	int i;
-	int sum = 0;
+	long sum = 0;
 	for_each_possible_cpu(i)
 		sum += per_cpu(nr_unused, i);
 	return sum < 0 ? 0 : sum;
 }
 
-int get_nr_dirty_inodes(void)
+long get_nr_dirty_inodes(void)
 {
 	/* not actually dirty inodes, but a wild approximation */
-	int nr_dirty = get_nr_inodes() - get_nr_inodes_unused();
+	long nr_dirty = get_nr_inodes() - get_nr_inodes_unused();
 	return nr_dirty > 0 ? nr_dirty : 0;
 }
 
@@ -109,7 +110,7 @@ int proc_nr_inodes(ctl_table *table, int write,
 {
 	inodes_stat.nr_inodes = get_nr_inodes();
 	inodes_stat.nr_unused = get_nr_inodes_unused();
-	return proc_dointvec(table, write, buffer, lenp, ppos);
+	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 }
 #endif
 
@@ -401,13 +402,8 @@ EXPORT_SYMBOL(ihold);
 
 static void inode_lru_list_add(struct inode *inode)
 {
-	spin_lock(&inode->i_sb->s_inode_lru_lock);
-	if (list_empty(&inode->i_lru)) {
-		list_add(&inode->i_lru, &inode->i_sb->s_inode_lru);
-		inode->i_sb->s_nr_inodes_unused++;
+	if (list_lru_add(&inode->i_sb->s_inode_lru, &inode->i_lru))
 		this_cpu_inc(nr_unused);
-	}
-	spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
 /*
@@ -425,13 +421,9 @@ void inode_add_lru(struct inode *inode)
 
 static void inode_lru_list_del(struct inode *inode)
 {
-	spin_lock(&inode->i_sb->s_inode_lru_lock);
-	if (!list_empty(&inode->i_lru)) {
-		list_del_init(&inode->i_lru);
-		inode->i_sb->s_nr_inodes_unused--;
+
+	if (list_lru_del(&inode->i_sb->s_inode_lru, &inode->i_lru))
 		this_cpu_dec(nr_unused);
-	}
-	spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
 /**
@@ -675,24 +667,8 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
 	return busy;
 }
 
-static int can_unuse(struct inode *inode)
-{
-	if (inode->i_state & ~I_REFERENCED)
-		return 0;
-	if (inode_has_buffers(inode))
-		return 0;
-	if (atomic_read(&inode->i_count))
-		return 0;
-	if (inode->i_data.nrpages)
-		return 0;
-	return 1;
-}
-
 /*
- * Walk the superblock inode LRU for freeable inodes and attempt to free them.
- * This is called from the superblock shrinker function with a number of inodes
- * to trim from the LRU. Inodes to be freed are moved to a temporary list and
- * then are freed outside inode_lock by dispose_list().
+ * Isolate the inode from the LRU in preparation for freeing it.
  *
  * Any inodes which are pinned purely because of attached pagecache have their
  * pagecache removed.  If the inode has metadata buffers attached to
@@ -706,89 +682,82 @@ static int can_unuse(struct inode *inode)
  * LRU does not have strict ordering. Hence we don't want to reclaim inodes
  * with this flag set because they are the inodes that are out of order.
  */
-void prune_icache_sb(struct super_block *sb, int nr_to_scan)
+static enum lru_status
+inode_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
 {
-	LIST_HEAD(freeable);
-	int nr_scanned;
-	unsigned long reap = 0;
+	struct list_head *freeable = arg;
+	struct inode	*inode = container_of(item, struct inode, i_lru);
 
-	spin_lock(&sb->s_inode_lru_lock);
-	for (nr_scanned = nr_to_scan; nr_scanned >= 0; nr_scanned--) {
-		struct inode *inode;
+	/*
+	 * we are inverting the lru lock/inode->i_lock here, so use a trylock.
+	 * If we fail to get the lock, just skip it.
+	 */
+	if (!spin_trylock(&inode->i_lock))
+		return LRU_SKIP;
 
-		if (list_empty(&sb->s_inode_lru))
-			break;
+	/*
+	 * Referenced or dirty inodes are still in use. Give them another pass
+	 * through the LRU as we canot reclaim them now.
+	 */
+	if (atomic_read(&inode->i_count) ||
+	    (inode->i_state & ~I_REFERENCED)) {
+		list_del_init(&inode->i_lru);
+		spin_unlock(&inode->i_lock);
+		this_cpu_dec(nr_unused);
+		return LRU_REMOVED;
+	}
 
-		inode = list_entry(sb->s_inode_lru.prev, struct inode, i_lru);
+	/* recently referenced inodes get one more pass */
+	if (inode->i_state & I_REFERENCED) {
+		inode->i_state &= ~I_REFERENCED;
+		spin_unlock(&inode->i_lock);
+		return LRU_ROTATE;
+	}
 
-		/*
-		 * we are inverting the sb->s_inode_lru_lock/inode->i_lock here,
-		 * so use a trylock. If we fail to get the lock, just move the
-		 * inode to the back of the list so we don't spin on it.
-		 */
-		if (!spin_trylock(&inode->i_lock)) {
-			list_move(&inode->i_lru, &sb->s_inode_lru);
-			continue;
+	if (inode_has_buffers(inode) || inode->i_data.nrpages) {
+		__iget(inode);
+		spin_unlock(&inode->i_lock);
+		spin_unlock(lru_lock);
+		if (remove_inode_buffers(inode)) {
+			unsigned long reap;
+			reap = invalidate_mapping_pages(&inode->i_data, 0, -1);
+			if (current_is_kswapd())
+				__count_vm_events(KSWAPD_INODESTEAL, reap);
+			else
+				__count_vm_events(PGINODESTEAL, reap);
+			if (current->reclaim_state)
+				current->reclaim_state->reclaimed_slab += reap;
 		}
+		iput(inode);
+		spin_lock(lru_lock);
+		return LRU_RETRY;
+	}
 
-		/*
-		 * Referenced or dirty inodes are still in use. Give them
-		 * another pass through the LRU as we canot reclaim them now.
-		 */
-		if (atomic_read(&inode->i_count) ||
-		    (inode->i_state & ~I_REFERENCED)) {
-			list_del_init(&inode->i_lru);
-			spin_unlock(&inode->i_lock);
-			sb->s_nr_inodes_unused--;
-			this_cpu_dec(nr_unused);
-			continue;
-		}
+	WARN_ON(inode->i_state & I_NEW);
+	inode->i_state |= I_FREEING;
+	list_move(&inode->i_lru, freeable);
+	spin_unlock(&inode->i_lock);
 
-		/* recently referenced inodes get one more pass */
-		if (inode->i_state & I_REFERENCED) {
-			inode->i_state &= ~I_REFERENCED;
-			list_move(&inode->i_lru, &sb->s_inode_lru);
-			spin_unlock(&inode->i_lock);
-			continue;
-		}
-		if (inode_has_buffers(inode) || inode->i_data.nrpages) {
-			__iget(inode);
-			spin_unlock(&inode->i_lock);
-			spin_unlock(&sb->s_inode_lru_lock);
-			if (remove_inode_buffers(inode))
-				reap += invalidate_mapping_pages(&inode->i_data,
-								0, -1);
-			iput(inode);
-			spin_lock(&sb->s_inode_lru_lock);
-
-			if (inode != list_entry(sb->s_inode_lru.next,
-						struct inode, i_lru))
-				continue;	/* wrong inode or list_empty */
-			/* avoid lock inversions with trylock */
-			if (!spin_trylock(&inode->i_lock))
-				continue;
-			if (!can_unuse(inode)) {
-				spin_unlock(&inode->i_lock);
-				continue;
-			}
-		}
-		WARN_ON(inode->i_state & I_NEW);
-		inode->i_state |= I_FREEING;
-		spin_unlock(&inode->i_lock);
+	this_cpu_dec(nr_unused);
+	return LRU_REMOVED;
+}
 
-		list_move(&inode->i_lru, &freeable);
-		sb->s_nr_inodes_unused--;
-		this_cpu_dec(nr_unused);
-	}
-	if (current_is_kswapd())
-		__count_vm_events(KSWAPD_INODESTEAL, reap);
-	else
-		__count_vm_events(PGINODESTEAL, reap);
-	spin_unlock(&sb->s_inode_lru_lock);
-	if (current->reclaim_state)
-		current->reclaim_state->reclaimed_slab += reap;
+/*
+ * Walk the superblock inode LRU for freeable inodes and attempt to free them.
+ * This is called from the superblock shrinker function with a number of inodes
+ * to trim from the LRU. Inodes to be freed are moved to a temporary list and
+ * then are freed outside inode_lock by dispose_list().
+ */
+long prune_icache_sb(struct super_block *sb, unsigned long nr_to_scan,
+		     int nid)
+{
+	LIST_HEAD(freeable);
+	long freed;
 
+	freed = list_lru_walk_node(&sb->s_inode_lru, nid, inode_lru_isolate,
+				       &freeable, &nr_to_scan);
 	dispose_list(&freeable);
+	return freed;
 }
 
 static void __wait_on_freeing_inode(struct inode *inode);
diff --git a/fs/internal.h b/fs/internal.h
index 7c5f01c..0b0db70 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -111,6 +111,8 @@ extern int open_check_o_direct(struct file *f);
  * inode.c
  */
 extern spinlock_t inode_sb_list_lock;
+extern long prune_icache_sb(struct super_block *sb, unsigned long nr_to_scan,
+			    int nid);
 extern void inode_add_lru(struct inode *inode);
 
 /*
@@ -118,7 +120,7 @@ extern void inode_add_lru(struct inode *inode);
  */
 extern void inode_wb_list_del(struct inode *inode);
 
-extern int get_nr_dirty_inodes(void);
+extern long get_nr_dirty_inodes(void);
 extern void evict_inodes(struct super_block *);
 extern int invalidate_inodes(struct super_block *, bool);
 
@@ -126,6 +128,8 @@ extern int invalidate_inodes(struct super_block *, bool);
  * dcache.c
  */
 extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
+extern long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan,
+			    int nid);
 
 /*
  * read_write.c
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index c348d6d..e5d408a 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -117,8 +117,8 @@ static void destroy_inodecache(void)
 
 static int isofs_remount(struct super_block *sb, int *flags, char *data)
 {
-	/* we probably want a lot more here */
-	*flags |= MS_RDONLY;
+	if (!(*flags & MS_RDONLY))
+		return -EROFS;
 	return 0;
 }
 
@@ -763,15 +763,6 @@ root_found:
 	 */
 	s->s_maxbytes = 0x80000000000LL;
 
-	/*
-	 * The CDROM is read-only, has no nodes (devices) on it, and since
-	 * all of the files appear to be owned by root, we really do not want
-	 * to allow suid.  (suid or devices will not show up unless we have
-	 * Rock Ridge extensions)
-	 */
-
-	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
-
 	/* Set this for reference. Its not currently used except on write
 	   which we don't have .. */
 
@@ -1530,6 +1521,9 @@ struct inode *isofs_iget(struct super_block *sb,
 static struct dentry *isofs_mount(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
+	/* We don't support read-write mounts */
+	if (!(flags & MS_RDONLY))
+		return ERR_PTR(-EACCES);
 	return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
 }
 
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 01bfe76..41e491b 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -64,12 +64,17 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
 				   nlm_init->protocol, nlm_version,
 				   nlm_init->hostname, nlm_init->noresvport,
 				   nlm_init->net);
-	if (host == NULL) {
-		lockd_down(nlm_init->net);
-		return ERR_PTR(-ENOLCK);
-	}
+	if (host == NULL)
+		goto out_nohost;
+	if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL)
+		goto out_nobind;
 
 	return host;
+out_nobind:
+	nlmclnt_release_host(host);
+out_nohost:
+	lockd_down(nlm_init->net);
+	return ERR_PTR(-ENOLCK);
 }
 EXPORT_SYMBOL_GPL(nlmclnt_init);
 
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 9760ecb..acd3947 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -125,14 +125,15 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 {
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_lock	*lock = &argp->lock;
+	char *nodename = req->a_host->h_rpcclnt->cl_nodename;
 
 	nlmclnt_next_cookie(&argp->cookie);
 	memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh));
-	lock->caller  = utsname()->nodename;
+	lock->caller  = nodename;
 	lock->oh.data = req->a_owner;
 	lock->oh.len  = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
 				(unsigned int)fl->fl_u.nfs_fl.owner->pid,
-				utsname()->nodename);
+				nodename);
 	lock->svid = fl->fl_u.nfs_fl.owner->pid;
 	lock->fl.fl_start = fl->fl_start;
 	lock->fl.fl_end = fl->fl_end;
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index 9c50144..427bb73 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -245,8 +245,8 @@ static int logfs_mtd_can_write_buf(struct super_block *sb, u64 ofs)
 		goto out;
 	if (memchr_inv(buf, 0xff, super->s_writesize))
 		err = -EIO;
-	kfree(buf);
 out:
+	kfree(buf);
 	return err;
 }
 
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 5436029..b256c06 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -287,14 +287,14 @@ static int logfs_make_writeable(struct super_block *sb)
 	if (err)
 		return err;
 
+	/* Do one GC pass before any data gets dirtied */
+	logfs_gc_pass(sb);
+
 	/* Check areas for trailing unaccounted data */
 	err = logfs_check_areas(sb);
 	if (err)
 		return err;
 
-	/* Do one GC pass before any data gets dirtied */
-	logfs_gc_pass(sb);
-
 	/* after all initializations are done, replay the journal
 	 * for rw-mounts, if necessary */
 	err = logfs_replay_journal(sb);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 8c32ef3..e519e45 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -86,18 +86,6 @@ static LIST_HEAD(mb_cache_list);
 static LIST_HEAD(mb_cache_lru_list);
 static DEFINE_SPINLOCK(mb_cache_spinlock);
 
-/*
- * What the mbcache registers as to get shrunk dynamically.
- */
-
-static int mb_cache_shrink_fn(struct shrinker *shrink,
-			      struct shrink_control *sc);
-
-static struct shrinker mb_cache_shrinker = {
-	.shrink = mb_cache_shrink_fn,
-	.seeks = DEFAULT_SEEKS,
-};
-
 static inline int
 __mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
 {
@@ -151,7 +139,7 @@ forget:
 
 
 /*
- * mb_cache_shrink_fn()  memory pressure callback
+ * mb_cache_shrink_scan()  memory pressure callback
  *
  * This function is called by the kernel memory management when memory
  * gets low.
@@ -159,17 +147,16 @@ forget:
  * @shrink: (ignored)
  * @sc: shrink_control passed from reclaim
  *
- * Returns the number of objects which are present in the cache.
+ * Returns the number of objects freed.
  */
-static int
-mb_cache_shrink_fn(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long
+mb_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	LIST_HEAD(free_list);
-	struct mb_cache *cache;
 	struct mb_cache_entry *entry, *tmp;
-	int count = 0;
 	int nr_to_scan = sc->nr_to_scan;
 	gfp_t gfp_mask = sc->gfp_mask;
+	unsigned long freed = 0;
 
 	mb_debug("trying to free %d entries", nr_to_scan);
 	spin_lock(&mb_cache_spinlock);
@@ -179,19 +166,37 @@ mb_cache_shrink_fn(struct shrinker *shrink, struct shrink_control *sc)
 				   struct mb_cache_entry, e_lru_list);
 		list_move_tail(&ce->e_lru_list, &free_list);
 		__mb_cache_entry_unhash(ce);
+		freed++;
+	}
+	spin_unlock(&mb_cache_spinlock);
+	list_for_each_entry_safe(entry, tmp, &free_list, e_lru_list) {
+		__mb_cache_entry_forget(entry, gfp_mask);
 	}
+	return freed;
+}
+
+static unsigned long
+mb_cache_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+	struct mb_cache *cache;
+	unsigned long count = 0;
+
+	spin_lock(&mb_cache_spinlock);
 	list_for_each_entry(cache, &mb_cache_list, c_cache_list) {
 		mb_debug("cache %s (%d)", cache->c_name,
 			  atomic_read(&cache->c_entry_count));
 		count += atomic_read(&cache->c_entry_count);
 	}
 	spin_unlock(&mb_cache_spinlock);
-	list_for_each_entry_safe(entry, tmp, &free_list, e_lru_list) {
-		__mb_cache_entry_forget(entry, gfp_mask);
-	}
-	return (count / 100) * sysctl_vfs_cache_pressure;
+
+	return vfs_pressure_ratio(count);
 }
 
+static struct shrinker mb_cache_shrinker = {
+	.count_objects = mb_cache_shrink_count,
+	.scan_objects = mb_cache_shrink_scan,
+	.seeks = DEFAULT_SEEKS,
+};
 
 /*
  * mb_cache_create()  create a new cache
diff --git a/fs/namei.c b/fs/namei.c
index 8b61d10..89a612e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3671,15 +3671,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 	if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
 		return -EINVAL;
 	/*
-	 * To use null names we require CAP_DAC_READ_SEARCH
-	 * This ensures that not everyone will be able to create
-	 * handlink using the passed filedescriptor.
+	 * Using empty names is equivalent to using AT_SYMLINK_FOLLOW
+	 * on /proc/self/fd/<fd>.
 	 */
-	if (flags & AT_EMPTY_PATH) {
-		if (!capable(CAP_DAC_READ_SEARCH))
-			return -ENOENT;
+	if (flags & AT_EMPTY_PATH)
 		how = LOOKUP_EMPTY;
-	}
 
 	if (flags & AT_SYMLINK_FOLLOW)
 		how |= LOOKUP_FOLLOW;
diff --git a/fs/namespace.c b/fs/namespace.c
index 7b1ca9b..9809084 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -17,7 +17,7 @@
 #include <linux/security.h>
 #include <linux/idr.h>
 #include <linux/acct.h>		/* acct_auto_close_mnt */
-#include <linux/ramfs.h>	/* init_rootfs */
+#include <linux/init.h>		/* init_rootfs */
 #include <linux/fs_struct.h>	/* get_fs_root et.al. */
 #include <linux/fsnotify.h>	/* fsnotify_vfsmount_delete */
 #include <linux/uaccess.h>
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 340b1ef..2dceee4 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -501,8 +501,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
 					&nn->nfs_client_list);
 			spin_unlock(&nn->nfs_client_lock);
 			new->cl_flags = cl_init->init_flags;
-			return rpc_ops->init_client(new, timeparms, ip_addr,
-						    authflavour);
+			return rpc_ops->init_client(new, timeparms, ip_addr);
 		}
 
 		spin_unlock(&nn->nfs_client_lock);
@@ -694,13 +693,12 @@ EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
  * @clp: nfs_client to initialise
  * @timeparms: timeout parameters for underlying RPC transport
  * @ip_addr: IP presentation address (not used)
- * @authflavor: authentication flavor for underlying RPC transport
  *
  * Returns pointer to an NFS client, or an ERR_PTR value.
  */
 struct nfs_client *nfs_init_client(struct nfs_client *clp,
 		    const struct rpc_timeout *timeparms,
-		    const char *ip_addr, rpc_authflavor_t authflavour)
+		    const char *ip_addr)
 {
 	int error;
 
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e474ca2b..6964233 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1413,6 +1413,10 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 	dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
+	err = nfs_check_flags(open_flags);
+	if (err)
+		return err;
+
 	/* NFS only supports OPEN on regular files */
 	if ((open_flags & O_DIRECTORY)) {
 		if (!d_unhashed(dentry)) {
@@ -1965,17 +1969,18 @@ static void nfs_access_free_list(struct list_head *head)
 	}
 }
 
-int nfs_access_cache_shrinker(struct shrinker *shrink,
-			      struct shrink_control *sc)
+unsigned long
+nfs_access_cache_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	LIST_HEAD(head);
 	struct nfs_inode *nfsi, *next;
 	struct nfs_access_entry *cache;
 	int nr_to_scan = sc->nr_to_scan;
 	gfp_t gfp_mask = sc->gfp_mask;
+	long freed = 0;
 
 	if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
-		return (nr_to_scan == 0) ? 0 : -1;
+		return SHRINK_STOP;
 
 	spin_lock(&nfs_access_lru_lock);
 	list_for_each_entry_safe(nfsi, next, &nfs_access_lru_list, access_cache_inode_lru) {
@@ -1991,6 +1996,7 @@ int nfs_access_cache_shrinker(struct shrinker *shrink,
 				struct nfs_access_entry, lru);
 		list_move(&cache->lru, &head);
 		rb_erase(&cache->rb_node, &nfsi->access_cache);
+		freed++;
 		if (!list_empty(&nfsi->access_cache_entry_lru))
 			list_move_tail(&nfsi->access_cache_inode_lru,
 					&nfs_access_lru_list);
@@ -2005,7 +2011,13 @@ remove_lru_entry:
 	}
 	spin_unlock(&nfs_access_lru_lock);
 	nfs_access_free_list(&head);
-	return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure;
+	return freed;
+}
+
+unsigned long
+nfs_access_cache_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+	return vfs_pressure_ratio(atomic_long_read(&nfs_access_nr_entries));
 }
 
 static void __nfs_access_zap_cache(struct nfs_inode *nfsi, struct list_head *head)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0bd7a55..91ff089 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -130,7 +130,6 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_
 
 	return -EINVAL;
 #else
-	VM_BUG_ON(iocb->ki_left != PAGE_SIZE);
 	VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE);
 
 	if (rw == READ || rw == KERNEL_READ)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index af6e806..941246f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -463,7 +463,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
 		unlock_new_inode(inode);
 	} else
 		nfs_refresh_inode(inode, fattr);
-		nfs_setsecurity(inode, fattr, label);
 	dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode),
@@ -963,9 +962,15 @@ EXPORT_SYMBOL_GPL(nfs_revalidate_inode);
 static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	
+	int ret;
+
 	if (mapping->nrpages != 0) {
-		int ret = invalidate_inode_pages2(mapping);
+		if (S_ISREG(inode->i_mode)) {
+			ret = nfs_sync_mapping(mapping);
+			if (ret < 0)
+				return ret;
+		}
+		ret = invalidate_inode_pages2(mapping);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 3c8373f..eefdbaf 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -267,11 +267,13 @@ extern struct rpc_procinfo nfs4_procedures[];
 void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
 extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
 			   const struct rpc_timeout *timeparms,
-			   const char *ip_addr, rpc_authflavor_t authflavour);
+			   const char *ip_addr);
 
 /* dir.c */
-extern int nfs_access_cache_shrinker(struct shrinker *shrink,
-					struct shrink_control *sc);
+extern unsigned long nfs_access_cache_count(struct shrinker *shrink,
+					    struct shrink_control *sc);
+extern unsigned long nfs_access_cache_scan(struct shrinker *shrink,
+					   struct shrink_control *sc);
 struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
 int nfs_create(struct inode *, struct dentry *, umode_t, bool);
 int nfs_mkdir(struct inode *, struct dentry *, umode_t);
@@ -451,8 +453,7 @@ extern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq);
 extern void __nfs4_read_done_cb(struct nfs_read_data *);
 extern struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 			    const struct rpc_timeout *timeparms,
-			    const char *ip_addr,
-			    rpc_authflavor_t authflavour);
+			    const char *ip_addr);
 extern int nfs40_walk_client_list(struct nfs_client *clp,
 				struct nfs_client **result,
 				struct rpc_cred *cred);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ee81e35..d7bb59d 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -193,7 +193,6 @@ struct nfs4_state_recovery_ops {
 	int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
 	int (*recover_lock)(struct nfs4_state *, struct file_lock *);
 	int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
-	struct rpc_cred * (*get_clid_cred)(struct nfs_client *);
 	int (*reclaim_complete)(struct nfs_client *, struct rpc_cred *);
 	int (*detect_trunking)(struct nfs_client *, struct nfs_client **,
 		struct rpc_cred *);
@@ -319,7 +318,7 @@ extern void nfs4_kill_renewd(struct nfs_client *);
 extern void nfs4_renew_state(struct work_struct *);
 
 /* nfs4state.c */
-struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
+struct rpc_cred *nfs4_get_clid_cred(struct nfs_client *clp);
 struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
 struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
 int nfs4_discover_server_trunking(struct nfs_client *clp,
@@ -327,7 +326,6 @@ int nfs4_discover_server_trunking(struct nfs_client *clp,
 int nfs40_discover_server_trunking(struct nfs_client *clp,
 			struct nfs_client **, struct rpc_cred *);
 #if defined(CONFIG_NFS_V4_1)
-struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
 int nfs41_discover_server_trunking(struct nfs_client *clp,
 			struct nfs_client **, struct rpc_cred *);
 extern void nfs4_schedule_session_recovery(struct nfs4_session *, int);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 90dce91..767a5e3 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -187,8 +187,7 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
  */
 struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 				    const struct rpc_timeout *timeparms,
-				    const char *ip_addr,
-				    rpc_authflavor_t authflavour)
+				    const char *ip_addr)
 {
 	char buf[INET6_ADDRSTRLEN + 1];
 	struct nfs_client *old;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index cf11799..f672c34 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2940,10 +2940,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	
 	/* Deal with open(O_TRUNC) */
 	if (sattr->ia_valid & ATTR_OPEN)
-		sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
+		sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME);
 
 	/* Optimization: if the end result is no change, don't RPC */
-	if ((sattr->ia_valid & ~(ATTR_FILE)) == 0)
+	if ((sattr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)
 		return 0;
 
 	/* Search for an existing open(O_WRITE) file */
@@ -3071,15 +3071,13 @@ struct rpc_clnt *
 nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
 			    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
+	struct rpc_clnt *client = NFS_CLIENT(dir);
 	int status;
-	struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));
 
 	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL);
-	if (status < 0) {
-		rpc_shutdown_client(client);
+	if (status < 0)
 		return ERR_PTR(status);
-	}
-	return client;
+	return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
 }
 
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
@@ -4662,10 +4660,14 @@ static unsigned int
 nfs4_init_uniform_client_string(const struct nfs_client *clp,
 				char *buf, size_t len)
 {
-	char *nodename = clp->cl_rpcclient->cl_nodename;
+	const char *nodename = clp->cl_rpcclient->cl_nodename;
 
 	if (nfs4_client_id_uniquifier[0] != '\0')
-		nodename = nfs4_client_id_uniquifier;
+		return scnprintf(buf, len, "Linux NFSv%u.%u %s/%s",
+				clp->rpc_ops->version,
+				clp->cl_minorversion,
+				nfs4_client_id_uniquifier,
+				nodename);
 	return scnprintf(buf, len, "Linux NFSv%u.%u %s",
 				clp->rpc_ops->version, clp->cl_minorversion,
 				nodename);
@@ -5790,6 +5792,10 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
 	return err;
 }
 
+/**
+ * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
+ * possible) as per RFC3530bis and RFC5661 Security Considerations sections
+ */
 static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
 {
 	int status;
@@ -5805,9 +5811,10 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
+	struct rpc_clnt *clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient;
 
 	dprintk("NFS call  secinfo %s\n", name->name);
-	status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
+	status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
 	dprintk("NFS reply  secinfo: %d\n", status);
 	return status;
 }
@@ -6065,7 +6072,7 @@ int nfs4_destroy_clientid(struct nfs_client *clp)
 		goto out;
 	if (clp->cl_preserve_clid)
 		goto out;
-	cred = nfs4_get_exchange_id_cred(clp);
+	cred = nfs4_get_clid_cred(clp);
 	ret = nfs4_proc_destroy_clientid(clp, cred);
 	if (cred)
 		put_rpccred(cred);
@@ -6876,7 +6883,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp)
 		.rpc_cred = lrp->cred,
 	};
 	struct rpc_task_setup task_setup_data = {
-		.rpc_client = lrp->clp->cl_rpcclient,
+		.rpc_client = NFS_SERVER(lrp->args.inode)->client,
 		.rpc_message = &msg,
 		.callback_ops = &nfs4_layoutreturn_call_ops,
 		.callback_data = lrp,
@@ -7081,6 +7088,10 @@ out:
 	return status;
 }
 
+/**
+ * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
+ * possible) as per RFC3530bis and RFC5661 Security Considerations sections
+ */
 static int
 _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
 		    struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
@@ -7096,7 +7107,8 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+	return nfs4_call_sync(server->nfs_client->cl_rpcclient, server, &msg,
+				&args.seq_args, &res.seq_res, 0);
 }
 
 static int
@@ -7359,7 +7371,6 @@ static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
 	.recover_open	= nfs4_open_reclaim,
 	.recover_lock	= nfs4_lock_reclaim,
 	.establish_clid = nfs4_init_clientid,
-	.get_clid_cred	= nfs4_get_setclientid_cred,
 	.detect_trunking = nfs40_discover_server_trunking,
 };
 
@@ -7370,7 +7381,6 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
 	.recover_open	= nfs4_open_reclaim,
 	.recover_lock	= nfs4_lock_reclaim,
 	.establish_clid = nfs41_init_clientid,
-	.get_clid_cred	= nfs4_get_exchange_id_cred,
 	.reclaim_complete = nfs41_proc_reclaim_complete,
 	.detect_trunking = nfs41_discover_server_trunking,
 };
@@ -7382,7 +7392,6 @@ static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
 	.recover_open	= nfs4_open_expired,
 	.recover_lock	= nfs4_lock_expired,
 	.establish_clid = nfs4_init_clientid,
-	.get_clid_cred	= nfs4_get_setclientid_cred,
 };
 
 #if defined(CONFIG_NFS_V4_1)
@@ -7392,7 +7401,6 @@ static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
 	.recover_open	= nfs41_open_expired,
 	.recover_lock	= nfs41_lock_expired,
 	.establish_clid = nfs41_init_clientid,
-	.get_clid_cred	= nfs4_get_exchange_id_cred,
 };
 #endif /* CONFIG_NFS_V4_1 */
 
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c
index 36e21cb..202e363 100644
--- a/fs/nfs/nfs4session.c
+++ b/fs/nfs/nfs4session.c
@@ -441,7 +441,7 @@ void nfs4_destroy_session(struct nfs4_session *session)
 	struct rpc_xprt *xprt;
 	struct rpc_cred *cred;
 
-	cred = nfs4_get_exchange_id_cred(session->clp);
+	cred = nfs4_get_clid_cred(session->clp);
 	nfs4_proc_destroy_session(session, cred);
 	if (cred)
 		put_rpccred(cred);
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index 3a153d8..86a0669 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -8,7 +8,7 @@
 #define __LINUX_FS_NFS_NFS4SESSION_H
 
 /* maximum number of slots to use */
-#define NFS4_DEF_SLOT_TABLE_SIZE (16U)
+#define NFS4_DEF_SLOT_TABLE_SIZE (64U)
 #define NFS4_MAX_SLOT_TABLE (1024U)
 #define NFS4_NO_SLOT ((u32)-1)
 
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e22862f..6818964 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -154,6 +154,19 @@ struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
 	return cred;
 }
 
+static void nfs4_root_machine_cred(struct nfs_client *clp)
+{
+	struct rpc_cred *cred, *new;
+
+	new = rpc_lookup_machine_cred(NULL);
+	spin_lock(&clp->cl_lock);
+	cred = clp->cl_machine_cred;
+	clp->cl_machine_cred = new;
+	spin_unlock(&clp->cl_lock);
+	if (cred != NULL)
+		put_rpccred(cred);
+}
+
 static struct rpc_cred *
 nfs4_get_renew_cred_server_locked(struct nfs_server *server)
 {
@@ -339,62 +352,21 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
 	return nfs41_walk_client_list(clp, result, cred);
 }
 
-struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
-{
-	struct rpc_cred *cred;
-
-	spin_lock(&clp->cl_lock);
-	cred = nfs4_get_machine_cred_locked(clp);
-	spin_unlock(&clp->cl_lock);
-	return cred;
-}
-
 #endif /* CONFIG_NFS_V4_1 */
 
-static struct rpc_cred *
-nfs4_get_setclientid_cred_server(struct nfs_server *server)
-{
-	struct nfs_client *clp = server->nfs_client;
-	struct rpc_cred *cred = NULL;
-	struct nfs4_state_owner *sp;
-	struct rb_node *pos;
-
-	spin_lock(&clp->cl_lock);
-	pos = rb_first(&server->state_owners);
-	if (pos != NULL) {
-		sp = rb_entry(pos, struct nfs4_state_owner, so_server_node);
-		cred = get_rpccred(sp->so_cred);
-	}
-	spin_unlock(&clp->cl_lock);
-	return cred;
-}
-
 /**
- * nfs4_get_setclientid_cred - Acquire credential for a setclientid operation
+ * nfs4_get_clid_cred - Acquire credential for a setclientid operation
  * @clp: client state handle
  *
  * Returns an rpc_cred with reference count bumped, or NULL.
  */
-struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
+struct rpc_cred *nfs4_get_clid_cred(struct nfs_client *clp)
 {
-	struct nfs_server *server;
 	struct rpc_cred *cred;
 
 	spin_lock(&clp->cl_lock);
 	cred = nfs4_get_machine_cred_locked(clp);
 	spin_unlock(&clp->cl_lock);
-	if (cred != NULL)
-		goto out;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-		cred = nfs4_get_setclientid_cred_server(server);
-		if (cred != NULL)
-			break;
-	}
-	rcu_read_unlock();
-
-out:
 	return cred;
 }
 
@@ -1618,7 +1590,7 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
 	if (!nfs4_state_clear_reclaim_reboot(clp))
 		return;
 	ops = clp->cl_mvops->reboot_recovery_ops;
-	cred = ops->get_clid_cred(clp);
+	cred = nfs4_get_clid_cred(clp);
 	nfs4_reclaim_complete(clp, ops, cred);
 	put_rpccred(cred);
 }
@@ -1732,7 +1704,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
 	cred = ops->get_state_renewal_cred_locked(clp);
 	spin_unlock(&clp->cl_lock);
 	if (cred == NULL) {
-		cred = nfs4_get_setclientid_cred(clp);
+		cred = nfs4_get_clid_cred(clp);
 		status = -ENOKEY;
 		if (cred == NULL)
 			goto out;
@@ -1804,7 +1776,7 @@ static int nfs4_establish_lease(struct nfs_client *clp)
 		clp->cl_mvops->reboot_recovery_ops;
 	int status;
 
-	cred = ops->get_clid_cred(clp);
+	cred = nfs4_get_clid_cred(clp);
 	if (cred == NULL)
 		return -ENOENT;
 	status = ops->establish_clid(clp, cred);
@@ -1878,7 +1850,7 @@ int nfs4_discover_server_trunking(struct nfs_client *clp,
 	mutex_lock(&nfs_clid_init_mutex);
 again:
 	status  = -ENOENT;
-	cred = ops->get_clid_cred(clp);
+	cred = nfs4_get_clid_cred(clp);
 	if (cred == NULL)
 		goto out_unlock;
 
@@ -1896,7 +1868,11 @@ again:
 			__func__, status);
 		goto again;
 	case -EACCES:
-		if (i++)
+		if (i++ == 0) {
+			nfs4_root_machine_cred(clp);
+			goto again;
+		}
+		if (i > 2)
 			break;
 	case -NFS4ERR_CLID_INUSE:
 	case -NFS4ERR_WRONGSEC:
@@ -2052,7 +2028,7 @@ static int nfs4_reset_session(struct nfs_client *clp)
 	if (!nfs4_has_session(clp))
 		return 0;
 	nfs4_begin_drain_session(clp);
-	cred = nfs4_get_exchange_id_cred(clp);
+	cred = nfs4_get_clid_cred(clp);
 	status = nfs4_proc_destroy_session(clp->cl_session, cred);
 	switch (status) {
 	case 0:
@@ -2095,7 +2071,7 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 	if (!nfs4_has_session(clp))
 		return 0;
 	nfs4_begin_drain_session(clp);
-	cred = nfs4_get_exchange_id_cred(clp);
+	cred = nfs4_get_clid_cred(clp);
 	ret = nfs4_proc_bind_conn_to_session(clp, cred);
 	if (cred)
 		put_rpccred(cred);
@@ -2116,7 +2092,7 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 }
 #else /* CONFIG_NFS_V4_1 */
 static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
-static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
+static void nfs4_end_drain_session(struct nfs_client *clp) { }
 
 static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 3850b01..1a4a3bd 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -997,12 +997,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
 	int owner_namelen = 0;
 	int owner_grouplen = 0;
 	__be32 *p;
-	__be32 *q;
-	int len;
-	uint32_t bmval_len = 2;
-	uint32_t bmval0 = 0;
-	uint32_t bmval1 = 0;
-	uint32_t bmval2 = 0;
+	unsigned i;
+	uint32_t len = 0;
+	uint32_t bmval_len;
+	uint32_t bmval[3] = { 0 };
 
 	/*
 	 * We reserve enough space to write the entire attribute buffer at once.
@@ -1011,13 +1009,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
 	 * = 40 bytes, plus any contribution from variable-length fields
 	 *            such as owner/group.
 	 */
-	len = 8;
-
-	/* Sigh */
-	if (iap->ia_valid & ATTR_SIZE)
+	if (iap->ia_valid & ATTR_SIZE) {
+		bmval[0] |= FATTR4_WORD0_SIZE;
 		len += 8;
-	if (iap->ia_valid & ATTR_MODE)
+	}
+	if (iap->ia_valid & ATTR_MODE) {
+		bmval[1] |= FATTR4_WORD1_MODE;
 		len += 4;
+	}
 	if (iap->ia_valid & ATTR_UID) {
 		owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
 		if (owner_namelen < 0) {
@@ -1028,6 +1027,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
 			owner_namelen = sizeof("nobody") - 1;
 			/* goto out; */
 		}
+		bmval[1] |= FATTR4_WORD1_OWNER;
 		len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
 	}
 	if (iap->ia_valid & ATTR_GID) {
@@ -1039,92 +1039,73 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
 			owner_grouplen = sizeof("nobody") - 1;
 			/* goto out; */
 		}
+		bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
 		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
 	}
-	if (iap->ia_valid & ATTR_ATIME_SET)
+	if (iap->ia_valid & ATTR_ATIME_SET) {
+		bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
 		len += 16;
-	else if (iap->ia_valid & ATTR_ATIME)
+	} else if (iap->ia_valid & ATTR_ATIME) {
+		bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
 		len += 4;
-	if (iap->ia_valid & ATTR_MTIME_SET)
+	}
+	if (iap->ia_valid & ATTR_MTIME_SET) {
+		bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
 		len += 16;
-	else if (iap->ia_valid & ATTR_MTIME)
+	} else if (iap->ia_valid & ATTR_MTIME) {
+		bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
 		len += 4;
+	}
 	if (label) {
 		len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
-		bmval_len = 3;
+		bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
 	}
 
-	len += bmval_len << 2;
-	p = reserve_space(xdr, len);
+	if (bmval[2] != 0)
+		bmval_len = 3;
+	else if (bmval[1] != 0)
+		bmval_len = 2;
+	else
+		bmval_len = 1;
+
+	p = reserve_space(xdr, 4 + (bmval_len << 2) + 4 + len);
 
-	/*
-	 * We write the bitmap length now, but leave the bitmap and the attribute
-	 * buffer length to be backfilled at the end of this routine.
-	 */
 	*p++ = cpu_to_be32(bmval_len);
-	q = p;
-	/* Skip bitmap entries + attrlen */
-	p += bmval_len + 1;
+	for (i = 0; i < bmval_len; i++)
+		*p++ = cpu_to_be32(bmval[i]);
+	*p++ = cpu_to_be32(len);
 
-	if (iap->ia_valid & ATTR_SIZE) {
-		bmval0 |= FATTR4_WORD0_SIZE;
+	if (bmval[0] & FATTR4_WORD0_SIZE)
 		p = xdr_encode_hyper(p, iap->ia_size);
-	}
-	if (iap->ia_valid & ATTR_MODE) {
-		bmval1 |= FATTR4_WORD1_MODE;
+	if (bmval[1] & FATTR4_WORD1_MODE)
 		*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
-	}
-	if (iap->ia_valid & ATTR_UID) {
-		bmval1 |= FATTR4_WORD1_OWNER;
+	if (bmval[1] & FATTR4_WORD1_OWNER)
 		p = xdr_encode_opaque(p, owner_name, owner_namelen);
-	}
-	if (iap->ia_valid & ATTR_GID) {
-		bmval1 |= FATTR4_WORD1_OWNER_GROUP;
+	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP)
 		p = xdr_encode_opaque(p, owner_group, owner_grouplen);
+	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
+		if (iap->ia_valid & ATTR_ATIME_SET) {
+			*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
+			p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
+			*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
+		} else
+			*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
 	}
-	if (iap->ia_valid & ATTR_ATIME_SET) {
-		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
-		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
-		p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
-		*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
-	}
-	else if (iap->ia_valid & ATTR_ATIME) {
-		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
-		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
-	}
-	if (iap->ia_valid & ATTR_MTIME_SET) {
-		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
-		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
-		p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
-		*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
-	}
-	else if (iap->ia_valid & ATTR_MTIME) {
-		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
-		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
+	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
+		if (iap->ia_valid & ATTR_MTIME_SET) {
+			*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
+			p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
+			*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
+		} else
+			*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
 	}
-	if (label) {
-		bmval2 |= FATTR4_WORD2_SECURITY_LABEL;
+	if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
 		*p++ = cpu_to_be32(label->lfs);
 		*p++ = cpu_to_be32(label->pi);
 		*p++ = cpu_to_be32(label->len);
 		p = xdr_encode_opaque_fixed(p, label->label, label->len);
 	}
 
-	/*
-	 * Now we backfill the bitmap and the attribute buffer length.
-	 */
-	if (len != ((char *)p - (char *)q) + 4) {
-		printk(KERN_ERR "NFS: Attr length error, %u != %Zu\n",
-				len, ((char *)p - (char *)q) + 4);
-		BUG();
-	}
-	*q++ = htonl(bmval0);
-	*q++ = htonl(bmval1);
-	if (bmval_len == 3)
-		*q++ = htonl(bmval2);
-	len = (char *)p - (char *)(q + 1);
-	*q = htonl(len);
-
 /* out: */
 }
 
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 71fdc0d..d643165 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -360,7 +360,8 @@ static void unregister_nfs4_fs(void)
 #endif
 
 static struct shrinker acl_shrinker = {
-	.shrink		= nfs_access_cache_shrinker,
+	.count_objects	= nfs_access_cache_count,
+	.scan_objects	= nfs_access_cache_scan,
 	.seeks		= DEFAULT_SEEKS,
 };
 
@@ -2084,6 +2085,8 @@ static int nfs_validate_text_mount_data(void *options,
 		max_namelen = NFS4_MAXNAMLEN;
 		max_pathlen = NFS4_MAXPATHLEN;
 		nfs_validate_transport_protocol(args);
+		if (args->nfs_server.protocol == XPRT_TRANSPORT_UDP)
+			goto out_invalid_transport_udp;
 		nfs4_validate_mount_flags(args);
 #else
 		goto out_v4_not_compiled;
@@ -2106,6 +2109,10 @@ static int nfs_validate_text_mount_data(void *options,
 out_v4_not_compiled:
 	dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n");
 	return -EPROTONOSUPPORT;
+#else
+out_invalid_transport_udp:
+	dfprintk(MOUNT, "NFSv4: Unsupported transport protocol udp\n");
+	return -EINVAL;
 #endif /* !CONFIG_NFS_V4 */
 
 out_no_address:
@@ -2478,6 +2485,10 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
 	if (server->flags & NFS_MOUNT_NOAC)
 		sb_mntdata.mntflags |= MS_SYNCHRONOUS;
 
+	if (mount_info->cloned != NULL && mount_info->cloned->sb != NULL)
+		if (mount_info->cloned->sb->s_flags & MS_SYNCHRONOUS)
+			sb_mntdata.mntflags |= MS_SYNCHRONOUS;
+
 	/* Get a superblock - note that we may end up sharing one that already exists */
 	s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata);
 	if (IS_ERR(s)) {
@@ -2711,6 +2722,8 @@ static int nfs4_validate_mount_data(void *options,
 		args->acdirmax	= data->acdirmax;
 		args->nfs_server.protocol = data->proto;
 		nfs_validate_transport_protocol(args);
+		if (args->nfs_server.protocol == XPRT_TRANSPORT_UDP)
+			goto out_invalid_transport_udp;
 
 		break;
 	default:
@@ -2731,6 +2744,10 @@ out_inval_auth:
 out_no_address:
 	dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
 	return -EINVAL;
+
+out_invalid_transport_udp:
+	dfprintk(MOUNT, "NFSv4: Unsupported transport protocol udp\n");
+	return -EINVAL;
 }
 
 /*
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 280acef..1cb6211 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -282,19 +282,14 @@ static unsigned int file_hashval(struct inode *ino)
 
 static struct hlist_head file_hashtbl[FILE_HASH_SIZE];
 
-static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag)
-{
-	WARN_ON_ONCE(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
-	atomic_inc(&fp->fi_access[oflag]);
-}
-
 static void nfs4_file_get_access(struct nfs4_file *fp, int oflag)
 {
+	WARN_ON_ONCE(!fp->fi_fds[oflag]);
 	if (oflag == O_RDWR) {
-		__nfs4_file_get_access(fp, O_RDONLY);
-		__nfs4_file_get_access(fp, O_WRONLY);
+		atomic_inc(&fp->fi_access[O_RDONLY]);
+		atomic_inc(&fp->fi_access[O_WRONLY]);
 	} else
-		__nfs4_file_get_access(fp, oflag);
+		atomic_inc(&fp->fi_access[oflag]);
 }
 
 static void nfs4_file_put_fd(struct nfs4_file *fp, int oflag)
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index e76244e..9186c7c 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -59,11 +59,14 @@ static unsigned int		longest_chain_cachesize;
 
 static int	nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
 static void	cache_cleaner_func(struct work_struct *unused);
-static int 	nfsd_reply_cache_shrink(struct shrinker *shrink,
-					struct shrink_control *sc);
+static unsigned long nfsd_reply_cache_count(struct shrinker *shrink,
+					    struct shrink_control *sc);
+static unsigned long nfsd_reply_cache_scan(struct shrinker *shrink,
+					   struct shrink_control *sc);
 
 static struct shrinker nfsd_reply_cache_shrinker = {
-	.shrink	= nfsd_reply_cache_shrink,
+	.scan_objects = nfsd_reply_cache_scan,
+	.count_objects = nfsd_reply_cache_count,
 	.seeks	= 1,
 };
 
@@ -232,16 +235,18 @@ nfsd_cache_entry_expired(struct svc_cacherep *rp)
  * Walk the LRU list and prune off entries that are older than RC_EXPIRE.
  * Also prune the oldest ones when the total exceeds the max number of entries.
  */
-static void
+static long
 prune_cache_entries(void)
 {
 	struct svc_cacherep *rp, *tmp;
+	long freed = 0;
 
 	list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) {
 		if (!nfsd_cache_entry_expired(rp) &&
 		    num_drc_entries <= max_drc_entries)
 			break;
 		nfsd_reply_cache_free_locked(rp);
+		freed++;
 	}
 
 	/*
@@ -254,6 +259,7 @@ prune_cache_entries(void)
 		cancel_delayed_work(&cache_cleaner);
 	else
 		mod_delayed_work(system_wq, &cache_cleaner, RC_EXPIRE);
+	return freed;
 }
 
 static void
@@ -264,20 +270,28 @@ cache_cleaner_func(struct work_struct *unused)
 	spin_unlock(&cache_lock);
 }
 
-static int
-nfsd_reply_cache_shrink(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long
+nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc)
 {
-	unsigned int num;
+	unsigned long num;
 
 	spin_lock(&cache_lock);
-	if (sc->nr_to_scan)
-		prune_cache_entries();
 	num = num_drc_entries;
 	spin_unlock(&cache_lock);
 
 	return num;
 }
 
+static unsigned long
+nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc)
+{
+	unsigned long freed;
+
+	spin_lock(&cache_lock);
+	freed = prune_cache_entries();
+	spin_unlock(&cache_lock);
+	return freed;
+}
 /*
  * Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes
  */
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 8a40457..b4f788e 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -51,10 +51,6 @@ static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size)
 		return ERR_PTR(-EINVAL);
 
 	count = size / sizeof(struct posix_acl_entry);
-	if (count < 0)
-		return ERR_PTR(-EINVAL);
-	if (count == 0)
-		return NULL;
 
 	acl = posix_acl_alloc(count, GFP_NOFS);
 	if (!acl)
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 17e6bdd..2fc6779 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -7126,7 +7126,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
 	if (end > i_size_read(inode))
 		end = i_size_read(inode);
 
-	BUG_ON(start >= end);
+	BUG_ON(start > end);
 
 	if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) ||
 	    !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) ||
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 79736a2..17f5e7d 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -2050,7 +2050,7 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
 
 out_write_size:
 	pos += copied;
-	if (pos > inode->i_size) {
+	if (pos > i_size_read(inode)) {
 		i_size_write(inode, pos);
 		mark_inode_dirty(inode);
 	}
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 5c1c864..3131646 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -35,6 +35,7 @@
 #include <linux/time.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/bitmap.h>
 
 #include "heartbeat.h"
 #include "tcp.h"
@@ -282,15 +283,6 @@ struct o2hb_bio_wait_ctxt {
 	int               wc_error;
 };
 
-static int o2hb_pop_count(void *map, int count)
-{
-	int i = -1, pop = 0;
-
-	while ((i = find_next_bit(map, count, i + 1)) < count)
-		pop++;
-	return pop;
-}
-
 static void o2hb_write_timeout(struct work_struct *work)
 {
 	int failed, quorum;
@@ -307,9 +299,9 @@ static void o2hb_write_timeout(struct work_struct *work)
 		spin_lock_irqsave(&o2hb_live_lock, flags);
 		if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
 			set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
-		failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+		failed = bitmap_weight(o2hb_failed_region_bitmap,
 					O2NM_MAX_REGIONS);
-		quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+		quorum = bitmap_weight(o2hb_quorum_region_bitmap,
 					O2NM_MAX_REGIONS);
 		spin_unlock_irqrestore(&o2hb_live_lock, flags);
 
@@ -628,11 +620,9 @@ static void o2hb_fire_callbacks(struct o2hb_callback *hbcall,
 				struct o2nm_node *node,
 				int idx)
 {
-	struct list_head *iter;
 	struct o2hb_callback_func *f;
 
-	list_for_each(iter, &hbcall->list) {
-		f = list_entry(iter, struct o2hb_callback_func, hc_item);
+	list_for_each_entry(f, &hbcall->list, hc_item) {
 		mlog(ML_HEARTBEAT, "calling funcs %p\n", f);
 		(f->hc_func)(node, idx, f->hc_data);
 	}
@@ -771,7 +761,7 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg)
 	 * If global heartbeat active, unpin all regions if the
 	 * region count > CUT_OFF
 	 */
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
 		o2hb_region_unpin(NULL);
 unlock:
@@ -956,23 +946,9 @@ out:
 	return changed;
 }
 
-/* This could be faster if we just implmented a find_last_bit, but I
- * don't think the circumstances warrant it. */
-static int o2hb_highest_node(unsigned long *nodes,
-			     int numbits)
+static int o2hb_highest_node(unsigned long *nodes, int numbits)
 {
-	int highest, node;
-
-	highest = numbits;
-	node = -1;
-	while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) {
-		if (node >= numbits)
-			break;
-
-		highest = node;
-	}
-
-	return highest;
+	return find_last_bit(nodes, numbits);
 }
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
@@ -1831,7 +1807,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
 	live_threshold = O2HB_LIVE_THRESHOLD;
 	if (o2hb_global_heartbeat_active()) {
 		spin_lock(&o2hb_live_lock);
-		if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
+		if (bitmap_weight(o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
 			live_threshold <<= 1;
 		spin_unlock(&o2hb_live_lock);
 	}
@@ -2182,7 +2158,7 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
 	if (!o2hb_dependent_users)
 		goto unlock;
 
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
 		o2hb_region_pin(NULL);
 
@@ -2482,7 +2458,7 @@ static int o2hb_region_inc_user(const char *region_uuid)
 	if (o2hb_dependent_users > 1)
 		goto unlock;
 
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
 		ret = o2hb_region_pin(NULL);
 
@@ -2516,8 +2492,7 @@ unlock:
 int o2hb_register_callback(const char *region_uuid,
 			   struct o2hb_callback_func *hc)
 {
-	struct o2hb_callback_func *tmp;
-	struct list_head *iter;
+	struct o2hb_callback_func *f;
 	struct o2hb_callback *hbcall;
 	int ret;
 
@@ -2540,10 +2515,9 @@ int o2hb_register_callback(const char *region_uuid,
 
 	down_write(&o2hb_callback_sem);
 
-	list_for_each(iter, &hbcall->list) {
-		tmp = list_entry(iter, struct o2hb_callback_func, hc_item);
-		if (hc->hc_priority < tmp->hc_priority) {
-			list_add_tail(&hc->hc_item, iter);
+	list_for_each_entry(f, &hbcall->list, hc_item) {
+		if (hc->hc_priority < f->hc_priority) {
+			list_add_tail(&hc->hc_item, &f->hc_item);
 			break;
 		}
 	}
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index baa2b9e..2260fb9 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -199,7 +199,8 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
 #define mlog_errno(st) do {						\
 	int _st = (st);							\
 	if (_st != -ERESTARTSYS && _st != -EINTR &&			\
-	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)		\
+	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&		\
+	    _st != -EDQUOT)						\
 		mlog(ML_ERROR, "status = %lld\n", (long long)_st);	\
 } while (0)
 
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index d644dc6..d04a3c2 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -543,8 +543,9 @@ static void o2net_set_nn_state(struct o2net_node *nn,
 	}
 
 	if (was_valid && !valid) {
-		printk(KERN_NOTICE "o2net: No longer connected to "
-		       SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc));
+		if (old_sc)
+			printk(KERN_NOTICE "o2net: No longer connected to "
+				SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc));
 		o2net_complete_nodes_nsw(nn);
 	}
 
@@ -1695,13 +1696,12 @@ static void o2net_start_connect(struct work_struct *work)
 		ret = 0;
 
 out:
-	if (ret) {
+	if (ret && sc) {
 		printk(KERN_NOTICE "o2net: Connect attempt to " SC_NODEF_FMT
 		       " failed with errno %d\n", SC_NODEF_ARGS(sc), ret);
 		/* 0 err so that another will be queued and attempted
 		 * from set_nn_state */
-		if (sc)
-			o2net_ensure_shutdown(nn, sc, 0);
+		o2net_ensure_shutdown(nn, sc, 0);
 	}
 	if (sc)
 		sc_put(sc);
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index eb760d8..c91d986 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2153,10 +2153,12 @@ int ocfs2_empty_dir(struct inode *inode)
 {
 	int ret;
 	struct ocfs2_empty_dir_priv priv = {
-		.ctx.actor = ocfs2_empty_dir_filldir
+		.ctx.actor = ocfs2_empty_dir_filldir,
+		.ctx.pos = 0,
 	};
 
-	memset(&priv, 0, sizeof(priv));
+	memset(&priv + sizeof(struct dir_context), 0,
+	       sizeof(priv) - sizeof(struct dir_context));
 
 	if (ocfs2_dir_indexed(inode)) {
 		ret = ocfs2_empty_dir_dx(inode, &priv);
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c
index fbec0be..b46278f 100644
--- a/fs/ocfs2/dlm/dlmast.c
+++ b/fs/ocfs2/dlm/dlmast.c
@@ -292,7 +292,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 	struct dlm_lock *lock = NULL;
 	struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf;
 	char *name;
-	struct list_head *iter, *head=NULL;
+	struct list_head *head = NULL;
 	__be64 cookie;
 	u32 flags;
 	u8 node;
@@ -373,8 +373,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 	/* try convert queue for both ast/bast */
 	head = &res->converting;
 	lock = NULL;
-	list_for_each(iter, head) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry(lock, head, list) {
 		if (lock->ml.cookie == cookie)
 			goto do_ast;
 	}
@@ -385,8 +384,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 	else
 		head = &res->granted;
 
-	list_for_each(iter, head) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry(lock, head, list) {
 		if (lock->ml.cookie == cookie)
 			goto do_ast;
 	}
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index de854cc..e051776 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -1079,11 +1079,9 @@ static inline int dlm_lock_compatible(int existing, int request)
 static inline int dlm_lock_on_list(struct list_head *head,
 				   struct dlm_lock *lock)
 {
-	struct list_head *iter;
 	struct dlm_lock *tmplock;
 
-	list_for_each(iter, head) {
-		tmplock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(tmplock, head, list) {
 		if (tmplock == lock)
 			return 1;
 	}
diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c
index 29a886d..a2bda15 100644
--- a/fs/ocfs2/dlm/dlmconvert.c
+++ b/fs/ocfs2/dlm/dlmconvert.c
@@ -123,7 +123,6 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm,
 					   int *kick_thread)
 {
 	enum dlm_status status = DLM_NORMAL;
-	struct list_head *iter;
 	struct dlm_lock *tmplock=NULL;
 
 	assert_spin_locked(&res->spinlock);
@@ -185,16 +184,14 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm,
 
 	/* upconvert from here on */
 	status = DLM_NORMAL;
-	list_for_each(iter, &res->granted) {
-		tmplock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(tmplock, &res->granted, list) {
 		if (tmplock == lock)
 			continue;
 		if (!dlm_lock_compatible(tmplock->ml.type, type))
 			goto switch_queues;
 	}
 
-	list_for_each(iter, &res->converting) {
-		tmplock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(tmplock, &res->converting, list) {
 		if (!dlm_lock_compatible(tmplock->ml.type, type))
 			goto switch_queues;
 		/* existing conversion requests take precedence */
@@ -424,7 +421,6 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
 	struct dlm_ctxt *dlm = data;
 	struct dlm_convert_lock *cnv = (struct dlm_convert_lock *)msg->buf;
 	struct dlm_lock_resource *res = NULL;
-	struct list_head *iter;
 	struct dlm_lock *lock = NULL;
 	struct dlm_lockstatus *lksb;
 	enum dlm_status status = DLM_NORMAL;
@@ -471,8 +467,7 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
 		dlm_error(status);
 		goto leave;
 	}
-	list_for_each(iter, &res->granted) {
-		lock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->granted, list) {
 		if (lock->ml.cookie == cnv->cookie &&
 		    lock->ml.node == cnv->node_idx) {
 			dlm_lock_get(lock);
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index 0e28e24..e33cd7a 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -96,7 +96,6 @@ static void __dlm_print_lock(struct dlm_lock *lock)
 
 void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
 {
-	struct list_head *iter2;
 	struct dlm_lock *lock;
 	char buf[DLM_LOCKID_NAME_MAX];
 
@@ -118,18 +117,15 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
 	       res->inflight_locks, atomic_read(&res->asts_reserved));
 	dlm_print_lockres_refmap(res);
 	printk("  granted queue:\n");
-	list_for_each(iter2, &res->granted) {
-		lock = list_entry(iter2, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->granted, list) {
 		__dlm_print_lock(lock);
 	}
 	printk("  converting queue:\n");
-	list_for_each(iter2, &res->converting) {
-		lock = list_entry(iter2, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->converting, list) {
 		__dlm_print_lock(lock);
 	}
 	printk("  blocked queue:\n");
-	list_for_each(iter2, &res->blocked) {
-		lock = list_entry(iter2, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->blocked, list) {
 		__dlm_print_lock(lock);
 	}
 }
@@ -446,7 +442,6 @@ static int debug_mle_print(struct dlm_ctxt *dlm, char *buf, int len)
 {
 	struct dlm_master_list_entry *mle;
 	struct hlist_head *bucket;
-	struct hlist_node *list;
 	int i, out = 0;
 	unsigned long total = 0, longest = 0, bucket_count = 0;
 
@@ -456,9 +451,7 @@ static int debug_mle_print(struct dlm_ctxt *dlm, char *buf, int len)
 	spin_lock(&dlm->master_lock);
 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
 		bucket = dlm_master_hash(dlm, i);
-		hlist_for_each(list, bucket) {
-			mle = hlist_entry(list, struct dlm_master_list_entry,
-					  master_hash_node);
+		hlist_for_each_entry(mle, bucket, master_hash_node) {
 			++total;
 			++bucket_count;
 			if (len - out < 200)
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index dbb17c0..b9b175c 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -193,7 +193,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
 						     unsigned int hash)
 {
 	struct hlist_head *bucket;
-	struct hlist_node *list;
+	struct dlm_lock_resource *res;
 
 	mlog(0, "%.*s\n", len, name);
 
@@ -201,9 +201,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
 
 	bucket = dlm_lockres_hash(dlm, hash);
 
-	hlist_for_each(list, bucket) {
-		struct dlm_lock_resource *res = hlist_entry(list,
-			struct dlm_lock_resource, hash_node);
+	hlist_for_each_entry(res, bucket, hash_node) {
 		if (res->lockname.name[0] != name[0])
 			continue;
 		if (unlikely(res->lockname.len != len))
@@ -263,14 +261,12 @@ struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
 static struct dlm_ctxt * __dlm_lookup_domain_full(const char *domain, int len)
 {
 	struct dlm_ctxt *tmp = NULL;
-	struct list_head *iter;
 
 	assert_spin_locked(&dlm_domain_lock);
 
 	/* tmp->name here is always NULL terminated,
 	 * but domain may not be! */
-	list_for_each(iter, &dlm_domains) {
-		tmp = list_entry (iter, struct dlm_ctxt, list);
+	list_for_each_entry(tmp, &dlm_domains, list) {
 		if (strlen(tmp->name) == len &&
 		    memcmp(tmp->name, domain, len)==0)
 			break;
@@ -366,14 +362,11 @@ static void __dlm_get(struct dlm_ctxt *dlm)
  * you shouldn't trust your pointer. */
 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm)
 {
-	struct list_head *iter;
 	struct dlm_ctxt *target = NULL;
 
 	spin_lock(&dlm_domain_lock);
 
-	list_for_each(iter, &dlm_domains) {
-		target = list_entry (iter, struct dlm_ctxt, list);
-
+	list_for_each_entry(target, &dlm_domains, list) {
 		if (target == dlm) {
 			__dlm_get(target);
 			break;
@@ -2296,13 +2289,10 @@ static DECLARE_RWSEM(dlm_callback_sem);
 void dlm_fire_domain_eviction_callbacks(struct dlm_ctxt *dlm,
 					int node_num)
 {
-	struct list_head *iter;
 	struct dlm_eviction_cb *cb;
 
 	down_read(&dlm_callback_sem);
-	list_for_each(iter, &dlm->dlm_eviction_callbacks) {
-		cb = list_entry(iter, struct dlm_eviction_cb, ec_item);
-
+	list_for_each_entry(cb, &dlm->dlm_eviction_callbacks, ec_item) {
 		cb->ec_func(node_num, cb->ec_data);
 	}
 	up_read(&dlm_callback_sem);
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 47e67c2..5d32f75 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -91,19 +91,14 @@ void dlm_destroy_lock_cache(void)
 static int dlm_can_grant_new_lock(struct dlm_lock_resource *res,
 				  struct dlm_lock *lock)
 {
-	struct list_head *iter;
 	struct dlm_lock *tmplock;
 
-	list_for_each(iter, &res->granted) {
-		tmplock = list_entry(iter, struct dlm_lock, list);
-
+	list_for_each_entry(tmplock, &res->granted, list) {
 		if (!dlm_lock_compatible(tmplock->ml.type, lock->ml.type))
 			return 0;
 	}
 
-	list_for_each(iter, &res->converting) {
-		tmplock = list_entry(iter, struct dlm_lock, list);
-
+	list_for_each_entry(tmplock, &res->converting, list) {
 		if (!dlm_lock_compatible(tmplock->ml.type, lock->ml.type))
 			return 0;
 		if (!dlm_lock_compatible(tmplock->ml.convert_type,
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 33ecbe0..00e50c5 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -342,16 +342,13 @@ static int dlm_find_mle(struct dlm_ctxt *dlm,
 {
 	struct dlm_master_list_entry *tmpmle;
 	struct hlist_head *bucket;
-	struct hlist_node *list;
 	unsigned int hash;
 
 	assert_spin_locked(&dlm->master_lock);
 
 	hash = dlm_lockid_hash(name, namelen);
 	bucket = dlm_master_hash(dlm, hash);
-	hlist_for_each(list, bucket) {
-		tmpmle = hlist_entry(list, struct dlm_master_list_entry,
-				     master_hash_node);
+	hlist_for_each_entry(tmpmle, bucket, master_hash_node) {
 		if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
 			continue;
 		dlm_get_mle(tmpmle);
@@ -1888,8 +1885,10 @@ ok:
 			 * up nodes that this node contacted */
 			while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
 						    nn+1)) < O2NM_MAX_NODES) {
-				if (nn != dlm->node_num && nn != assert->node_idx)
+				if (nn != dlm->node_num && nn != assert->node_idx) {
 					master_request = 1;
+					break;
+				}
 			}
 		}
 		mle->master = assert->node_idx;
@@ -2357,6 +2356,10 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
 
 	assert_spin_locked(&res->spinlock);
 
+	/* delay migration when the lockres is in MIGRATING state */
+	if (res->state & DLM_LOCK_RES_MIGRATING)
+		return 0;
+
 	if (res->owner != dlm->node_num)
 		return 0;
 
@@ -3183,7 +3186,6 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
 	struct dlm_master_list_entry *mle;
 	struct dlm_lock_resource *res;
 	struct hlist_head *bucket;
-	struct hlist_node *list;
 	unsigned int i;
 
 	mlog(0, "dlm=%s, dead node=%u\n", dlm->name, dead_node);
@@ -3194,10 +3196,7 @@ top:
 	spin_lock(&dlm->master_lock);
 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
 		bucket = dlm_master_hash(dlm, i);
-		hlist_for_each(list, bucket) {
-			mle = hlist_entry(list, struct dlm_master_list_entry,
-					  master_hash_node);
-
+		hlist_for_each_entry(mle, bucket, master_hash_node) {
 			BUG_ON(mle->type != DLM_MLE_BLOCK &&
 			       mle->type != DLM_MLE_MASTER &&
 			       mle->type != DLM_MLE_MIGRATION);
@@ -3378,7 +3377,7 @@ void dlm_force_free_mles(struct dlm_ctxt *dlm)
 	int i;
 	struct hlist_head *bucket;
 	struct dlm_master_list_entry *mle;
-	struct hlist_node *tmp, *list;
+	struct hlist_node *tmp;
 
 	/*
 	 * We notified all other nodes that we are exiting the domain and
@@ -3394,9 +3393,7 @@ void dlm_force_free_mles(struct dlm_ctxt *dlm)
 
 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
 		bucket = dlm_master_hash(dlm, i);
-		hlist_for_each_safe(list, tmp, bucket) {
-			mle = hlist_entry(list, struct dlm_master_list_entry,
-					  master_hash_node);
+		hlist_for_each_entry_safe(mle, tmp, bucket, master_hash_node) {
 			if (mle->type != DLM_MLE_BLOCK) {
 				mlog(ML_ERROR, "bad mle: %p\n", mle);
 				dlm_print_one_mle(mle);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 773bd32..6729f71 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -787,6 +787,7 @@ static int dlm_request_all_locks(struct dlm_ctxt *dlm, u8 request_from,
 {
 	struct dlm_lock_request lr;
 	int ret;
+	int status;
 
 	mlog(0, "\n");
 
@@ -800,13 +801,15 @@ static int dlm_request_all_locks(struct dlm_ctxt *dlm, u8 request_from,
 
 	// send message
 	ret = o2net_send_message(DLM_LOCK_REQUEST_MSG, dlm->key,
-				 &lr, sizeof(lr), request_from, NULL);
+				 &lr, sizeof(lr), request_from, &status);
 
 	/* negative status is handled by caller */
 	if (ret < 0)
 		mlog(ML_ERROR, "%s: Error %d send LOCK_REQUEST to node %u "
 		     "to recover dead node %u\n", dlm->name, ret,
 		     request_from, dead_node);
+	else
+		ret = status;
 	// return from here, then
 	// sleep until all received or error
 	return ret;
@@ -1882,6 +1885,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
 
 		if (ml->type == LKM_NLMODE)
 			goto skip_lvb;
+		
+		/*
+		 * If the lock is in the blocked list it can't have a valid lvb,
+		 * so skip it
+		 */
+		if (ml->list == DLM_BLOCKED_LIST)
+			goto skip_lvb;
 
 		if (!dlm_lvb_is_empty(mres->lvb)) {
 			if (lksb->flags & DLM_LKSB_PUT_LVB) {
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index e73c833..9db869d 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -286,8 +286,6 @@ static void dlm_shuffle_lists(struct dlm_ctxt *dlm,
 			      struct dlm_lock_resource *res)
 {
 	struct dlm_lock *lock, *target;
-	struct list_head *iter;
-	struct list_head *head;
 	int can_grant = 1;
 
 	/*
@@ -314,9 +312,7 @@ converting:
 		     dlm->name, res->lockname.len, res->lockname.name);
 		BUG();
 	}
-	head = &res->granted;
-	list_for_each(iter, head) {
-		lock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->granted, list) {
 		if (lock==target)
 			continue;
 		if (!dlm_lock_compatible(lock->ml.type,
@@ -333,9 +329,8 @@ converting:
 					target->ml.convert_type;
 		}
 	}
-	head = &res->converting;
-	list_for_each(iter, head) {
-		lock = list_entry(iter, struct dlm_lock, list);
+
+	list_for_each_entry(lock, &res->converting, list) {
 		if (lock==target)
 			continue;
 		if (!dlm_lock_compatible(lock->ml.type,
@@ -384,9 +379,7 @@ blocked:
 		goto leave;
 	target = list_entry(res->blocked.next, struct dlm_lock, list);
 
-	head = &res->granted;
-	list_for_each(iter, head) {
-		lock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->granted, list) {
 		if (lock==target)
 			continue;
 		if (!dlm_lock_compatible(lock->ml.type, target->ml.type)) {
@@ -400,9 +393,7 @@ blocked:
 		}
 	}
 
-	head = &res->converting;
-	list_for_each(iter, head) {
-		lock = list_entry(iter, struct dlm_lock, list);
+	list_for_each_entry(lock, &res->converting, list) {
 		if (lock==target)
 			continue;
 		if (!dlm_lock_compatible(lock->ml.type, target->ml.type)) {
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index 850aa7e..5698b52 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -388,7 +388,6 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data,
 	struct dlm_ctxt *dlm = data;
 	struct dlm_unlock_lock *unlock = (struct dlm_unlock_lock *)msg->buf;
 	struct dlm_lock_resource *res = NULL;
-	struct list_head *iter;
 	struct dlm_lock *lock = NULL;
 	enum dlm_status status = DLM_NORMAL;
 	int found = 0, i;
@@ -458,8 +457,7 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data,
 	}
 
 	for (i=0; i<3; i++) {
-		list_for_each(iter, queue) {
-			lock = list_entry(iter, struct dlm_lock, list);
+		list_for_each_entry(lock, queue, list) {
 			if (lock->ml.cookie == unlock->cookie &&
 		    	    lock->ml.node == unlock->node_idx) {
 				dlm_lock_get(lock);
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index 2487116..4bf2b76 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -852,20 +852,20 @@ int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int whence)
 
 	down_read(&OCFS2_I(inode)->ip_alloc_sem);
 
-	if (*offset >= inode->i_size) {
+	if (*offset >= i_size_read(inode)) {
 		ret = -ENXIO;
 		goto out_unlock;
 	}
 
 	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
 		if (whence == SEEK_HOLE)
-			*offset = inode->i_size;
+			*offset = i_size_read(inode);
 		goto out_unlock;
 	}
 
 	clen = 0;
 	cpos = *offset >> cs_bits;
-	cend = ocfs2_clusters_for_bytes(inode->i_sb, inode->i_size);
+	cend = ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
 
 	while (cpos < cend && !is_last) {
 		ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size,
@@ -904,8 +904,8 @@ int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int whence)
 		extlen = clen;
 		extlen <<=  cs_bits;
 
-		if ((extoff + extlen) > inode->i_size)
-			extlen = inode->i_size - extoff;
+		if ((extoff + extlen) > i_size_read(inode))
+			extlen = i_size_read(inode) - extoff;
 		extoff += extlen;
 		if (extoff > *offset)
 			*offset = extoff;
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 41000f2..f353cd8 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -474,11 +474,6 @@ static int ocfs2_truncate_file(struct inode *inode,
 		goto bail;
 	}
 
-	/* lets handle the simple truncate cases before doing any more
-	 * cluster locking. */
-	if (new_i_size == le64_to_cpu(fe->i_size))
-		goto bail;
-
 	down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
 	ocfs2_resv_discard(&osb->osb_la_resmap,
@@ -671,11 +666,7 @@ restarted_transaction:
 		} else {
 			BUG_ON(why != RESTART_TRANS);
 
-			/* TODO: This can be more intelligent. */
-			credits = ocfs2_calc_extend_credits(osb->sb,
-							    &fe->id2.i_list,
-							    clusters_to_add);
-			status = ocfs2_extend_trans(handle, credits);
+			status = ocfs2_allocate_extend_trans(handle, 1);
 			if (status < 0) {
 				/* handle still has to be committed at
 				 * this point. */
@@ -723,7 +714,8 @@ leave:
  * While a write will already be ordering the data, a truncate will not.
  * Thus, we need to explicitly order the zeroed pages.
  */
-static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode)
+static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode,
+						struct buffer_head *di_bh)
 {
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	handle_t *handle = NULL;
@@ -740,7 +732,14 @@ static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode)
 	}
 
 	ret = ocfs2_jbd2_file_inode(handle, inode);
-	if (ret < 0)
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
+				      OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret)
 		mlog_errno(ret);
 
 out:
@@ -756,7 +755,7 @@ out:
  * to be too fragile to do exactly what we need without us having to
  * worry about recursive locking in ->write_begin() and ->write_end(). */
 static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
-				 u64 abs_to)
+				 u64 abs_to, struct buffer_head *di_bh)
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page;
@@ -764,6 +763,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 	handle_t *handle = NULL;
 	int ret = 0;
 	unsigned zero_from, zero_to, block_start, block_end;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
 
 	BUG_ON(abs_from >= abs_to);
 	BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT));
@@ -806,7 +806,8 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 		}
 
 		if (!handle) {
-			handle = ocfs2_zero_start_ordered_transaction(inode);
+			handle = ocfs2_zero_start_ordered_transaction(inode,
+								      di_bh);
 			if (IS_ERR(handle)) {
 				ret = PTR_ERR(handle);
 				handle = NULL;
@@ -823,8 +824,22 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 			ret = 0;
 	}
 
-	if (handle)
+	if (handle) {
+		/*
+		 * fs-writeback will release the dirty pages without page lock
+		 * whose offset are over inode size, the release happens at
+		 * block_write_full_page_endio().
+		 */
+		i_size_write(inode, abs_to);
+		inode->i_blocks = ocfs2_inode_sector_count(inode);
+		di->i_size = cpu_to_le64((u64)i_size_read(inode));
+		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
+		di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+		di->i_mtime_nsec = di->i_ctime_nsec;
+		ocfs2_journal_dirty(handle, di_bh);
 		ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+	}
 
 out_unlock:
 	unlock_page(page);
@@ -920,7 +935,7 @@ out:
  * has made sure that the entire range needs zeroing.
  */
 static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start,
-				   u64 range_end)
+				   u64 range_end, struct buffer_head *di_bh)
 {
 	int rc = 0;
 	u64 next_pos;
@@ -936,7 +951,7 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start,
 		next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE;
 		if (next_pos > range_end)
 			next_pos = range_end;
-		rc = ocfs2_write_zero_page(inode, zero_pos, next_pos);
+		rc = ocfs2_write_zero_page(inode, zero_pos, next_pos, di_bh);
 		if (rc < 0) {
 			mlog_errno(rc);
 			break;
@@ -982,7 +997,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh,
 			range_end = zero_to_size;
 
 		ret = ocfs2_zero_extend_range(inode, range_start,
-					      range_end);
+					      range_end, di_bh);
 		if (ret) {
 			mlog_errno(ret);
 			break;
@@ -1150,14 +1165,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 		goto bail_unlock_rw;
 	}
 
-	if (size_change && attr->ia_size != i_size_read(inode)) {
+	if (size_change) {
 		status = inode_newsize_ok(inode, attr->ia_size);
 		if (status)
 			goto bail_unlock;
 
 		inode_dio_wait(inode);
 
-		if (i_size_read(inode) > attr->ia_size) {
+		if (i_size_read(inode) >= attr->ia_size) {
 			if (ocfs2_should_order_data(inode)) {
 				status = ocfs2_begin_ordered_truncate(inode,
 								      attr->ia_size);
@@ -2245,7 +2260,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 		file->f_path.dentry->d_name.name,
 		(unsigned int)nr_segs);
 
-	if (iocb->ki_left == 0)
+	if (iocb->ki_nbytes == 0)
 		return 0;
 
 	appending = file->f_flags & O_APPEND ? 1 : 0;
@@ -2296,7 +2311,7 @@ relock:
 
 	can_do_direct = direct_io;
 	ret = ocfs2_prepare_inode_for_write(file, ppos,
-					    iocb->ki_left, appending,
+					    iocb->ki_nbytes, appending,
 					    &can_do_direct, &has_refcount);
 	if (ret < 0) {
 		mlog_errno(ret);
@@ -2304,7 +2319,7 @@ relock:
 	}
 
 	if (direct_io && !is_sync_kiocb(iocb))
-		unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_left,
+		unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_nbytes,
 						      *ppos);
 
 	/*
@@ -2626,7 +2641,16 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence)
 	case SEEK_SET:
 		break;
 	case SEEK_END:
-		offset += inode->i_size;
+		/* SEEK_END requires the OCFS2 inode lock for the file
+		 * because it references the file's size.
+		 */
+		ret = ocfs2_inode_lock(inode, NULL, 0);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+		offset += i_size_read(inode);
+		ocfs2_inode_unlock(inode, 0);
 		break;
 	case SEEK_CUR:
 		if (offset == 0) {
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index 0c60ef2..fa32ce9 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -303,7 +303,7 @@ int ocfs2_info_handle_journal_size(struct inode *inode,
 	if (o2info_from_user(oij, req))
 		goto bail;
 
-	oij.ij_journal_size = osb->journal->j_inode->i_size;
+	oij.ij_journal_size = i_size_read(osb->journal->j_inode);
 
 	o2info_set_request_filled(&oij.ij_req);
 
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 242170d..44fc3e5 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -455,6 +455,41 @@ bail:
 	return status;
 }
 
+/*
+ * If we have fewer than thresh credits, extend by OCFS2_MAX_TRANS_DATA.
+ * If that fails, restart the transaction & regain write access for the
+ * buffer head which is used for metadata modifications.
+ * Taken from Ext4: extend_or_restart_transaction()
+ */
+int ocfs2_allocate_extend_trans(handle_t *handle, int thresh)
+{
+	int status, old_nblks;
+
+	BUG_ON(!handle);
+
+	old_nblks = handle->h_buffer_credits;
+	trace_ocfs2_allocate_extend_trans(old_nblks, thresh);
+
+	if (old_nblks < thresh)
+		return 0;
+
+	status = jbd2_journal_extend(handle, OCFS2_MAX_TRANS_DATA);
+	if (status < 0) {
+		mlog_errno(status);
+		goto bail;
+	}
+
+	if (status > 0) {
+		status = jbd2_journal_restart(handle, OCFS2_MAX_TRANS_DATA);
+		if (status < 0)
+			mlog_errno(status);
+	}
+
+bail:
+	return status;
+}
+
+
 struct ocfs2_triggers {
 	struct jbd2_buffer_trigger_type	ot_triggers;
 	int				ot_offset;
@@ -801,14 +836,14 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
 	inode_lock = 1;
 	di = (struct ocfs2_dinode *)bh->b_data;
 
-	if (inode->i_size <  OCFS2_MIN_JOURNAL_SIZE) {
+	if (i_size_read(inode) <  OCFS2_MIN_JOURNAL_SIZE) {
 		mlog(ML_ERROR, "Journal file size (%lld) is too small!\n",
-		     inode->i_size);
+		     i_size_read(inode));
 		status = -EINVAL;
 		goto done;
 	}
 
-	trace_ocfs2_journal_init(inode->i_size,
+	trace_ocfs2_journal_init(i_size_read(inode),
 				 (unsigned long long)inode->i_blocks,
 				 OCFS2_I(inode)->ip_clusters);
 
@@ -1096,7 +1131,7 @@ static int ocfs2_force_read_journal(struct inode *inode)
 
 	memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL);
 
-	num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, inode->i_size);
+	num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
 	v_blkno = 0;
 	while (v_blkno < num_blocks) {
 		status = ocfs2_extent_map_get_blocks(inode, v_blkno,
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 96f9ac2..dc7170e 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -258,6 +258,17 @@ handle_t		    *ocfs2_start_trans(struct ocfs2_super *osb,
 int			     ocfs2_commit_trans(struct ocfs2_super *osb,
 						handle_t *handle);
 int			     ocfs2_extend_trans(handle_t *handle, int nblocks);
+int			     ocfs2_allocate_extend_trans(handle_t *handle,
+						int thresh);
+
+/*
+ * Define an arbitrary limit for the amount of data we will anticipate
+ * writing to any given transaction.  For unbounded transactions such as
+ * fallocate(2) we can write more than this, but we always
+ * start off at the maximum transaction size and grow the transaction
+ * optimistically as we go.
+ */
+#define OCFS2_MAX_TRANS_DATA	64U
 
 /*
  * Create access is for when we get a newly created buffer and we're
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index aebeacd..cd5496b 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -1082,7 +1082,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
 	}
 
 retry_enospc:
-	(*ac)->ac_bits_wanted = osb->local_alloc_default_bits;
+	(*ac)->ac_bits_wanted = osb->local_alloc_bits;
 	status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
 	if (status == -ENOSPC) {
 		if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) ==
@@ -1154,7 +1154,7 @@ retry_enospc:
 		    OCFS2_LA_DISABLED)
 			goto bail;
 
-		ac->ac_bits_wanted = osb->local_alloc_default_bits;
+		ac->ac_bits_wanted = osb->local_alloc_bits;
 		status = ocfs2_claim_clusters(handle, ac,
 					      osb->local_alloc_bits,
 					      &cluster_off,
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index f1fc172..cc77c4e 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -152,6 +152,7 @@ static int __ocfs2_move_extent(handle_t *handle,
 	}
 
 out:
+	ocfs2_free_path(path);
 	return ret;
 }
 
@@ -845,7 +846,7 @@ static int __ocfs2_move_extents_range(struct buffer_head *di_bh,
 	struct ocfs2_move_extents *range = context->range;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-	if ((inode->i_size == 0) || (range->me_len == 0))
+	if ((i_size_read(inode) == 0) || (range->me_len == 0))
 		return 0;
 
 	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index be3f867..cec861d 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2101,17 +2101,17 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
 		goto leave;
 	}
 
-	/* remove it from the orphan directory */
-	status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup);
+	status = ocfs2_journal_access_di(handle,
+					 INODE_CACHE(orphan_dir_inode),
+					 orphan_dir_bh,
+					 OCFS2_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
 	}
 
-	status = ocfs2_journal_access_di(handle,
-					 INODE_CACHE(orphan_dir_inode),
-					 orphan_dir_bh,
-					 OCFS2_JOURNAL_ACCESS_WRITE);
+	/* remove it from the orphan directory */
+	status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h
index 3b481f4..1b60c62 100644
--- a/fs/ocfs2/ocfs2_trace.h
+++ b/fs/ocfs2/ocfs2_trace.h
@@ -2579,6 +2579,8 @@ DEFINE_OCFS2_INT_INT_EVENT(ocfs2_extend_trans);
 
 DEFINE_OCFS2_INT_EVENT(ocfs2_extend_trans_restart);
 
+DEFINE_OCFS2_INT_INT_EVENT(ocfs2_allocate_extend_trans);
+
 DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_journal_access);
 
 DEFINE_OCFS2_ULL_EVENT(ocfs2_journal_dirty);
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 332a281..aaa5061 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -234,7 +234,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
 		len = sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset;
 	}
 
-	if (gqinode->i_size < off + len) {
+	if (i_size_read(gqinode) < off + len) {
 		loff_t rounded_end =
 				ocfs2_align_bytes_to_blocks(sb, off + len);
 
@@ -778,8 +778,8 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
 		 */
 		WARN_ON(journal_current_handle());
 		status = ocfs2_extend_no_holes(gqinode, NULL,
-			gqinode->i_size + (need_alloc << sb->s_blocksize_bits),
-			gqinode->i_size);
+			i_size_read(gqinode) + (need_alloc << sb->s_blocksize_bits),
+			i_size_read(gqinode));
 		if (status < 0)
 			goto out_dq;
 	}
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 27fe7ee..2e4344b 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -982,14 +982,14 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
 
 	/* We are protected by dqio_sem so no locking needed */
 	status = ocfs2_extend_no_holes(lqinode, NULL,
-				       lqinode->i_size + 2 * sb->s_blocksize,
-				       lqinode->i_size);
+				       i_size_read(lqinode) + 2 * sb->s_blocksize,
+				       i_size_read(lqinode));
 	if (status < 0) {
 		mlog_errno(status);
 		goto out;
 	}
 	status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
-					  lqinode->i_size + 2 * sb->s_blocksize);
+					  i_size_read(lqinode) + 2 * sb->s_blocksize);
 	if (status < 0) {
 		mlog_errno(status);
 		goto out;
@@ -1125,14 +1125,14 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
 
 	/* We are protected by dqio_sem so no locking needed */
 	status = ocfs2_extend_no_holes(lqinode, NULL,
-				       lqinode->i_size + sb->s_blocksize,
-				       lqinode->i_size);
+				       i_size_read(lqinode) + sb->s_blocksize,
+				       i_size_read(lqinode));
 	if (status < 0) {
 		mlog_errno(status);
 		goto out;
 	}
 	status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
-					  lqinode->i_size + sb->s_blocksize);
+					  i_size_read(lqinode) + sb->s_blocksize);
 	if (status < 0) {
 		mlog_errno(status);
 		goto out;
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 9f6b96a..15db8a9 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -3891,7 +3891,10 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
 	while (cpos < clusters) {
 		ret = ocfs2_get_clusters(inode, cpos, &p_cluster,
 					 &num_clusters, &ext_flags);
-
+		if (ret) {
+			mlog_errno(ret);
+			goto unlock;
+		}
 		if (p_cluster && !(ext_flags & OCFS2_EXT_REFCOUNTED)) {
 			ret = ocfs2_add_refcount_flag(inode, &di_et,
 						      &ref_tree->rf_ci,
@@ -4062,7 +4065,10 @@ static int ocfs2_duplicate_extent_list(struct inode *s_inode,
 	while (cpos < clusters) {
 		ret = ocfs2_get_clusters(s_inode, cpos, &p_cluster,
 					 &num_clusters, &ext_flags);
-
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
 		if (p_cluster) {
 			ret = ocfs2_add_refcounted_extent(t_inode, &et,
 							  ref_ci, ref_root_bh,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index e5c7f15..19f134e 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -32,7 +32,7 @@ enum ocfs2_xattr_type {
 
 struct ocfs2_security_xattr_info {
 	int enable;
-	char *name;
+	const char *name;
 	void *value;
 	size_t value_len;
 };
diff --git a/fs/open.c b/fs/open.c
index d53e298..7931f76 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -823,7 +823,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
 	int lookup_flags = 0;
 	int acc_mode;
 
-	if (flags & O_CREAT)
+	if (flags & (O_CREAT | __O_TMPFILE))
 		op->mode = (mode & S_IALLUGO) | S_IFREG;
 	else
 		op->mode = 0;
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 75f2890..0ff80f9 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -230,8 +230,6 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
 
 	if (!dir_emit_dots(file, ctx))
 		goto out;
-	if (!dir_emit_dots(file, ctx))
-		goto out;
 	files = get_files_struct(p);
 	if (!files)
 		goto out;
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 5aa847a..59d85d6 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -132,13 +132,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 		K(i.freeswap),
 		K(global_page_state(NR_FILE_DIRTY)),
 		K(global_page_state(NR_WRITEBACK)),
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-		K(global_page_state(NR_ANON_PAGES)
-		  + global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) *
-		  HPAGE_PMD_NR),
-#else
 		K(global_page_state(NR_ANON_PAGES)),
-#endif
 		K(global_page_state(NR_FILE_MAPPED)),
 		K(global_page_state(NR_SHMEM)),
 		K(global_page_state(NR_SLAB_RECLAIMABLE) +
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 229e366..38bd5d4 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -110,7 +110,8 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
 		ns = task_active_pid_ns(current);
 		options = data;
 
-		if (!current_user_ns()->may_mount_proc)
+		if (!current_user_ns()->may_mount_proc ||
+		    !ns_capable(ns->user_ns, CAP_SYS_ADMIN))
 			return ERR_PTR(-EPERM);
 	}
 
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index dbf61f6..a117207 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -730,8 +730,16 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
 	 * of how soft-dirty works.
 	 */
 	pte_t ptent = *pte;
-	ptent = pte_wrprotect(ptent);
-	ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY);
+
+	if (pte_present(ptent)) {
+		ptent = pte_wrprotect(ptent);
+		ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY);
+	} else if (is_swap_pte(ptent)) {
+		ptent = pte_swp_clear_soft_dirty(ptent);
+	} else if (pte_file(ptent)) {
+		ptent = pte_file_clear_soft_dirty(ptent);
+	}
+
 	set_pte_at(vma->vm_mm, addr, pte, ptent);
 #endif
 }
@@ -752,14 +760,15 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE) {
 		ptent = *pte;
-		if (!pte_present(ptent))
-			continue;
 
 		if (cp->type == CLEAR_REFS_SOFT_DIRTY) {
 			clear_soft_dirty(vma, addr, pte);
 			continue;
 		}
 
+		if (!pte_present(ptent))
+			continue;
+
 		page = vm_normal_page(vma, addr, ptent);
 		if (!page)
 			continue;
@@ -930,8 +939,10 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
 		flags = PM_PRESENT;
 		page = vm_normal_page(vma, addr, pte);
 	} else if (is_swap_pte(pte)) {
-		swp_entry_t entry = pte_to_swp_entry(pte);
-
+		swp_entry_t entry;
+		if (pte_swp_soft_dirty(pte))
+			flags2 |= __PM_SOFT_DIRTY;
+		entry = pte_to_swp_entry(pte);
 		frame = swp_type(entry) |
 			(swp_offset(entry) << MAX_SWAPFILES_SHIFT);
 		flags = PM_SWAP;
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index a1a16eb..9100d69 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -21,6 +21,7 @@
 #include <linux/crash_dump.h>
 #include <linux/list.h>
 #include <linux/vmalloc.h>
+#include <linux/pagemap.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include "internal.h"
@@ -123,11 +124,65 @@ static ssize_t read_from_oldmem(char *buf, size_t count,
 	return read;
 }
 
+/*
+ * Architectures may override this function to allocate ELF header in 2nd kernel
+ */
+int __weak elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
+{
+	return 0;
+}
+
+/*
+ * Architectures may override this function to free header
+ */
+void __weak elfcorehdr_free(unsigned long long addr)
+{}
+
+/*
+ * Architectures may override this function to read from ELF header
+ */
+ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos)
+{
+	return read_from_oldmem(buf, count, ppos, 0);
+}
+
+/*
+ * Architectures may override this function to read from notes sections
+ */
+ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
+{
+	return read_from_oldmem(buf, count, ppos, 0);
+}
+
+/*
+ * Architectures may override this function to map oldmem
+ */
+int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma,
+				  unsigned long from, unsigned long pfn,
+				  unsigned long size, pgprot_t prot)
+{
+	return remap_pfn_range(vma, from, pfn, size, prot);
+}
+
+/*
+ * Copy to either kernel or user space
+ */
+static int copy_to(void *target, void *src, size_t size, int userbuf)
+{
+	if (userbuf) {
+		if (copy_to_user((char __user *) target, src, size))
+			return -EFAULT;
+	} else {
+		memcpy(target, src, size);
+	}
+	return 0;
+}
+
 /* Read from the ELF header and then the crash dump. On error, negative value is
  * returned otherwise number of bytes read are returned.
  */
-static ssize_t read_vmcore(struct file *file, char __user *buffer,
-				size_t buflen, loff_t *fpos)
+static ssize_t __read_vmcore(char *buffer, size_t buflen, loff_t *fpos,
+			     int userbuf)
 {
 	ssize_t acc = 0, tmp;
 	size_t tsz;
@@ -144,7 +199,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
 	/* Read ELF core header */
 	if (*fpos < elfcorebuf_sz) {
 		tsz = min(elfcorebuf_sz - (size_t)*fpos, buflen);
-		if (copy_to_user(buffer, elfcorebuf + *fpos, tsz))
+		if (copy_to(buffer, elfcorebuf + *fpos, tsz, userbuf))
 			return -EFAULT;
 		buflen -= tsz;
 		*fpos += tsz;
@@ -162,7 +217,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
 
 		tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)*fpos, buflen);
 		kaddr = elfnotes_buf + *fpos - elfcorebuf_sz;
-		if (copy_to_user(buffer, kaddr, tsz))
+		if (copy_to(buffer, kaddr, tsz, userbuf))
 			return -EFAULT;
 		buflen -= tsz;
 		*fpos += tsz;
@@ -178,7 +233,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
 		if (*fpos < m->offset + m->size) {
 			tsz = min_t(size_t, m->offset + m->size - *fpos, buflen);
 			start = m->paddr + *fpos - m->offset;
-			tmp = read_from_oldmem(buffer, tsz, &start, 1);
+			tmp = read_from_oldmem(buffer, tsz, &start, userbuf);
 			if (tmp < 0)
 				return tmp;
 			buflen -= tsz;
@@ -195,6 +250,55 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
 	return acc;
 }
 
+static ssize_t read_vmcore(struct file *file, char __user *buffer,
+			   size_t buflen, loff_t *fpos)
+{
+	return __read_vmcore((__force char *) buffer, buflen, fpos, 1);
+}
+
+/*
+ * The vmcore fault handler uses the page cache and fills data using the
+ * standard __vmcore_read() function.
+ *
+ * On s390 the fault handler is used for memory regions that can't be mapped
+ * directly with remap_pfn_range().
+ */
+static int mmap_vmcore_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+#ifdef CONFIG_S390
+	struct address_space *mapping = vma->vm_file->f_mapping;
+	pgoff_t index = vmf->pgoff;
+	struct page *page;
+	loff_t offset;
+	char *buf;
+	int rc;
+
+	page = find_or_create_page(mapping, index, GFP_KERNEL);
+	if (!page)
+		return VM_FAULT_OOM;
+	if (!PageUptodate(page)) {
+		offset = (loff_t) index << PAGE_CACHE_SHIFT;
+		buf = __va((page_to_pfn(page) << PAGE_SHIFT));
+		rc = __read_vmcore(buf, PAGE_SIZE, &offset, 0);
+		if (rc < 0) {
+			unlock_page(page);
+			page_cache_release(page);
+			return (rc == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+		}
+		SetPageUptodate(page);
+	}
+	unlock_page(page);
+	vmf->page = page;
+	return 0;
+#else
+	return VM_FAULT_SIGBUS;
+#endif
+}
+
+static const struct vm_operations_struct vmcore_mmap_ops = {
+	.fault = mmap_vmcore_fault,
+};
+
 /**
  * alloc_elfnotes_buf - allocate buffer for ELF note segment in
  *                      vmalloc memory
@@ -223,7 +327,7 @@ static inline char *alloc_elfnotes_buf(size_t notes_sz)
  * regions in the 1st kernel pointed to by PT_LOAD entries) into
  * virtually contiguous user-space in ELF layout.
  */
-#if defined(CONFIG_MMU) && !defined(CONFIG_S390)
+#ifdef CONFIG_MMU
 static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
 {
 	size_t size = vma->vm_end - vma->vm_start;
@@ -241,6 +345,7 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
 
 	vma->vm_flags &= ~(VM_MAYWRITE | VM_MAYEXEC);
 	vma->vm_flags |= VM_MIXEDMAP;
+	vma->vm_ops = &vmcore_mmap_ops;
 
 	len = 0;
 
@@ -282,9 +387,9 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
 
 			tsz = min_t(size_t, m->offset + m->size - start, size);
 			paddr = m->paddr + start - m->offset;
-			if (remap_pfn_range(vma, vma->vm_start + len,
-					    paddr >> PAGE_SHIFT, tsz,
-					    vma->vm_page_prot))
+			if (remap_oldmem_pfn_range(vma, vma->vm_start + len,
+						   paddr >> PAGE_SHIFT, tsz,
+						   vma->vm_page_prot))
 				goto fail;
 			size -= tsz;
 			start += tsz;
@@ -357,7 +462,7 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr)
 		notes_section = kmalloc(max_sz, GFP_KERNEL);
 		if (!notes_section)
 			return -ENOMEM;
-		rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
+		rc = elfcorehdr_read_notes(notes_section, max_sz, &offset);
 		if (rc < 0) {
 			kfree(notes_section);
 			return rc;
@@ -444,7 +549,8 @@ static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf)
 		if (phdr_ptr->p_type != PT_NOTE)
 			continue;
 		offset = phdr_ptr->p_offset;
-		rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
+		rc = elfcorehdr_read_notes(notes_buf, phdr_ptr->p_memsz,
+					   &offset);
 		if (rc < 0)
 			return rc;
 		notes_buf += phdr_ptr->p_memsz;
@@ -536,7 +642,7 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr)
 		notes_section = kmalloc(max_sz, GFP_KERNEL);
 		if (!notes_section)
 			return -ENOMEM;
-		rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
+		rc = elfcorehdr_read_notes(notes_section, max_sz, &offset);
 		if (rc < 0) {
 			kfree(notes_section);
 			return rc;
@@ -623,7 +729,8 @@ static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf)
 		if (phdr_ptr->p_type != PT_NOTE)
 			continue;
 		offset = phdr_ptr->p_offset;
-		rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
+		rc = elfcorehdr_read_notes(notes_buf, phdr_ptr->p_memsz,
+					   &offset);
 		if (rc < 0)
 			return rc;
 		notes_buf += phdr_ptr->p_memsz;
@@ -810,7 +917,7 @@ static int __init parse_crash_elf64_headers(void)
 	addr = elfcorehdr_addr;
 
 	/* Read Elf header */
-	rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0);
+	rc = elfcorehdr_read((char *)&ehdr, sizeof(Elf64_Ehdr), &addr);
 	if (rc < 0)
 		return rc;
 
@@ -837,7 +944,7 @@ static int __init parse_crash_elf64_headers(void)
 	if (!elfcorebuf)
 		return -ENOMEM;
 	addr = elfcorehdr_addr;
-	rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0);
+	rc = elfcorehdr_read(elfcorebuf, elfcorebuf_sz_orig, &addr);
 	if (rc < 0)
 		goto fail;
 
@@ -866,7 +973,7 @@ static int __init parse_crash_elf32_headers(void)
 	addr = elfcorehdr_addr;
 
 	/* Read Elf header */
-	rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0);
+	rc = elfcorehdr_read((char *)&ehdr, sizeof(Elf32_Ehdr), &addr);
 	if (rc < 0)
 		return rc;
 
@@ -892,7 +999,7 @@ static int __init parse_crash_elf32_headers(void)
 	if (!elfcorebuf)
 		return -ENOMEM;
 	addr = elfcorehdr_addr;
-	rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0);
+	rc = elfcorehdr_read(elfcorebuf, elfcorebuf_sz_orig, &addr);
 	if (rc < 0)
 		goto fail;
 
@@ -919,7 +1026,7 @@ static int __init parse_crash_elf_headers(void)
 	int rc=0;
 
 	addr = elfcorehdr_addr;
-	rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0);
+	rc = elfcorehdr_read(e_ident, EI_NIDENT, &addr);
 	if (rc < 0)
 		return rc;
 	if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
@@ -952,7 +1059,14 @@ static int __init vmcore_init(void)
 {
 	int rc = 0;
 
-	/* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
+	/* Allow architectures to allocate ELF header in 2nd kernel */
+	rc = elfcorehdr_alloc(&elfcorehdr_addr, &elfcorehdr_size);
+	if (rc)
+		return rc;
+	/*
+	 * If elfcorehdr= has been passed in cmdline or created in 2nd kernel,
+	 * then capture the dump.
+	 */
 	if (!(is_vmcore_usable()))
 		return rc;
 	rc = parse_crash_elf_headers();
@@ -960,6 +1074,8 @@ static int __init vmcore_init(void)
 		pr_warn("Kdump: vmcore not initialized\n");
 		return rc;
 	}
+	elfcorehdr_free(elfcorehdr_addr);
+	elfcorehdr_addr = ELFCORE_ADDR_ERR;
 
 	proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
 	if (proc_vmcore)
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index fbad622..017eaea 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -687,45 +687,37 @@ int dquot_quota_sync(struct super_block *sb, int type)
 }
 EXPORT_SYMBOL(dquot_quota_sync);
 
-/* Free unused dquots from cache */
-static void prune_dqcache(int count)
+static unsigned long
+dqcache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
 	struct list_head *head;
 	struct dquot *dquot;
+	unsigned long freed = 0;
 
 	head = free_dquots.prev;
-	while (head != &free_dquots && count) {
+	while (head != &free_dquots && sc->nr_to_scan) {
 		dquot = list_entry(head, struct dquot, dq_free);
 		remove_dquot_hash(dquot);
 		remove_free_dquot(dquot);
 		remove_inuse(dquot);
 		do_destroy_dquot(dquot);
-		count--;
+		sc->nr_to_scan--;
+		freed++;
 		head = free_dquots.prev;
 	}
+	return freed;
 }
 
-/*
- * This is called from kswapd when we think we need some
- * more memory
- */
-static int shrink_dqcache_memory(struct shrinker *shrink,
-				 struct shrink_control *sc)
+static unsigned long
+dqcache_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
 {
-	int nr = sc->nr_to_scan;
-
-	if (nr) {
-		spin_lock(&dq_list_lock);
-		prune_dqcache(nr);
-		spin_unlock(&dq_list_lock);
-	}
-	return ((unsigned)
-		percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS])
-		/100) * sysctl_vfs_cache_pressure;
+	return vfs_pressure_ratio(
+	percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS]));
 }
 
 static struct shrinker dqcache_shrinker = {
-	.shrink = shrink_dqcache_memory,
+	.count_objects = dqcache_shrink_count,
+	.scan_objects = dqcache_shrink_scan,
 	.seeks = DEFAULT_SEEKS,
 };
 
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index c24f1e1..39d1465 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -244,12 +244,6 @@ struct dentry *ramfs_mount(struct file_system_type *fs_type,
 	return mount_nodev(fs_type, flags, data, ramfs_fill_super);
 }
 
-static struct dentry *rootfs_mount(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
-{
-	return mount_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);
-}
-
 static void ramfs_kill_sb(struct super_block *sb)
 {
 	kfree(sb->s_fs_info);
@@ -262,29 +256,23 @@ static struct file_system_type ramfs_fs_type = {
 	.kill_sb	= ramfs_kill_sb,
 	.fs_flags	= FS_USERNS_MOUNT,
 };
-static struct file_system_type rootfs_fs_type = {
-	.name		= "rootfs",
-	.mount		= rootfs_mount,
-	.kill_sb	= kill_litter_super,
-};
 
-static int __init init_ramfs_fs(void)
-{
-	return register_filesystem(&ramfs_fs_type);
-}
-module_init(init_ramfs_fs)
-
-int __init init_rootfs(void)
+int __init init_ramfs_fs(void)
 {
+	static unsigned long once;
 	int err;
 
+	if (test_and_set_bit(0, &once))
+		return 0;
+
 	err = bdi_init(&ramfs_backing_dev_info);
 	if (err)
 		return err;
 
-	err = register_filesystem(&rootfs_fs_type);
+	err = register_filesystem(&ramfs_fs_type);
 	if (err)
 		bdi_destroy(&ramfs_backing_dev_info);
 
 	return err;
 }
+module_init(init_ramfs_fs)
diff --git a/fs/read_write.c b/fs/read_write.c
index 122a384..e3cd280 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -367,7 +367,6 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
 
 	init_sync_kiocb(&kiocb, filp);
 	kiocb.ki_pos = *ppos;
-	kiocb.ki_left = len;
 	kiocb.ki_nbytes = len;
 
 	ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
@@ -417,7 +416,6 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
 
 	init_sync_kiocb(&kiocb, filp);
 	kiocb.ki_pos = *ppos;
-	kiocb.ki_left = len;
 	kiocb.ki_nbytes = len;
 
 	ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
@@ -599,7 +597,6 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 
 	init_sync_kiocb(&kiocb, filp);
 	kiocb.ki_pos = *ppos;
-	kiocb.ki_left = len;
 	kiocb.ki_nbytes = len;
 
 	ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 33532f7..a958444 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -19,12 +19,13 @@
 /*
  * LOCKING:
  *
- * We rely on new Alexander Viro's super-block locking.
+ * These guys are evicted from procfs as the very first step in ->kill_sb().
  *
  */
 
-static int show_version(struct seq_file *m, struct super_block *sb)
+static int show_version(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	char *format;
 
 	if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) {
@@ -66,8 +67,9 @@ static int show_version(struct seq_file *m, struct super_block *sb)
 #define DJP( x ) le32_to_cpu( jp -> x )
 #define JF( x ) ( r -> s_journal -> x )
 
-static int show_super(struct seq_file *m, struct super_block *sb)
+static int show_super(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	struct reiserfs_sb_info *r = REISERFS_SB(sb);
 
 	seq_printf(m, "state: \t%s\n"
@@ -128,8 +130,9 @@ static int show_super(struct seq_file *m, struct super_block *sb)
 	return 0;
 }
 
-static int show_per_level(struct seq_file *m, struct super_block *sb)
+static int show_per_level(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	struct reiserfs_sb_info *r = REISERFS_SB(sb);
 	int level;
 
@@ -186,8 +189,9 @@ static int show_per_level(struct seq_file *m, struct super_block *sb)
 	return 0;
 }
 
-static int show_bitmap(struct seq_file *m, struct super_block *sb)
+static int show_bitmap(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	struct reiserfs_sb_info *r = REISERFS_SB(sb);
 
 	seq_printf(m, "free_block: %lu\n"
@@ -218,8 +222,9 @@ static int show_bitmap(struct seq_file *m, struct super_block *sb)
 	return 0;
 }
 
-static int show_on_disk_super(struct seq_file *m, struct super_block *sb)
+static int show_on_disk_super(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
 	struct reiserfs_super_block *rs = sb_info->s_rs;
 	int hash_code = DFL(s_hash_function_code);
@@ -261,8 +266,9 @@ static int show_on_disk_super(struct seq_file *m, struct super_block *sb)
 	return 0;
 }
 
-static int show_oidmap(struct seq_file *m, struct super_block *sb)
+static int show_oidmap(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
 	struct reiserfs_super_block *rs = sb_info->s_rs;
 	unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize);
@@ -291,8 +297,9 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb)
 	return 0;
 }
 
-static int show_journal(struct seq_file *m, struct super_block *sb)
+static int show_journal(struct seq_file *m, void *unused)
 {
+	struct super_block *sb = m->private;
 	struct reiserfs_sb_info *r = REISERFS_SB(sb);
 	struct reiserfs_super_block *rs = r->s_rs;
 	struct journal_params *jp = &rs->s_v1.s_journal;
@@ -383,92 +390,24 @@ static int show_journal(struct seq_file *m, struct super_block *sb)
 	return 0;
 }
 
-/* iterator */
-static int test_sb(struct super_block *sb, void *data)
-{
-	return data == sb;
-}
-
-static int set_sb(struct super_block *sb, void *data)
-{
-	return -ENOENT;
-}
-
-struct reiserfs_seq_private {
-	struct super_block *sb;
-	int (*show) (struct seq_file *, struct super_block *);
-};
-
-static void *r_start(struct seq_file *m, loff_t * pos)
-{
-	struct reiserfs_seq_private *priv = m->private;
-	loff_t l = *pos;
-
-	if (l)
-		return NULL;
-
-	if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, priv->sb)))
-		return NULL;
-
-	up_write(&priv->sb->s_umount);
-	return priv->sb;
-}
-
-static void *r_next(struct seq_file *m, void *v, loff_t * pos)
-{
-	++*pos;
-	if (v)
-		deactivate_super(v);
-	return NULL;
-}
-
-static void r_stop(struct seq_file *m, void *v)
-{
-	if (v)
-		deactivate_super(v);
-}
-
-static int r_show(struct seq_file *m, void *v)
-{
-	struct reiserfs_seq_private *priv = m->private;
-	return priv->show(m, v);
-}
-
-static const struct seq_operations r_ops = {
-	.start = r_start,
-	.next = r_next,
-	.stop = r_stop,
-	.show = r_show,
-};
-
 static int r_open(struct inode *inode, struct file *file)
 {
-	struct reiserfs_seq_private *priv;
-	int ret = seq_open_private(file, &r_ops,
-				   sizeof(struct reiserfs_seq_private));
-
-	if (!ret) {
-		struct seq_file *m = file->private_data;
-		priv = m->private;
-		priv->sb = proc_get_parent_data(inode);
-		priv->show = PDE_DATA(inode);
-	}
-	return ret;
+	return single_open(file, PDE_DATA(inode), 
+				proc_get_parent_data(inode));
 }
 
 static const struct file_operations r_file_operations = {
 	.open = r_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
-	.release = seq_release_private,
-	.owner = THIS_MODULE,
+	.release = single_release,
 };
 
 static struct proc_dir_entry *proc_info_root = NULL;
 static const char proc_info_root_name[] = "fs/reiserfs";
 
 static void add_file(struct super_block *sb, char *name,
-		     int (*func) (struct seq_file *, struct super_block *))
+		     int (*func) (struct seq_file *, void *))
 {
 	proc_create_data(name, 0, REISERFS_SB(sb)->procdir,
 			 &r_file_operations, func);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f8a23c3..e2e202a 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -499,6 +499,7 @@ int remove_save_link(struct inode *inode, int truncate)
 static void reiserfs_kill_sb(struct super_block *s)
 {
 	if (REISERFS_SB(s)) {
+		reiserfs_proc_info_done(s);
 		/*
 		 * Force any pending inode evictions to occur now. Any
 		 * inodes to be removed that have extended attributes
@@ -554,8 +555,6 @@ static void reiserfs_put_super(struct super_block *s)
 				 REISERFS_SB(s)->reserved_blocks);
 	}
 
-	reiserfs_proc_info_done(s);
-
 	reiserfs_write_unlock(s);
 	mutex_destroy(&REISERFS_SB(s)->lock);
 	kfree(s->s_fs_info);
diff --git a/fs/super.c b/fs/super.c
index 68307c0..73d0952 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -53,11 +53,15 @@ static char *sb_writers_name[SB_FREEZE_LEVELS] = {
  * shrinker path and that leads to deadlock on the shrinker_rwsem. Hence we
  * take a passive reference to the superblock to avoid this from occurring.
  */
-static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long super_cache_scan(struct shrinker *shrink,
+				      struct shrink_control *sc)
 {
 	struct super_block *sb;
-	int	fs_objects = 0;
-	int	total_objects;
+	long	fs_objects = 0;
+	long	total_objects;
+	long	freed = 0;
+	long	dentries;
+	long	inodes;
 
 	sb = container_of(shrink, struct super_block, s_shrink);
 
@@ -65,46 +69,62 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
 	 * Deadlock avoidance.  We may hold various FS locks, and we don't want
 	 * to recurse into the FS that called us in clear_inode() and friends..
 	 */
-	if (sc->nr_to_scan && !(sc->gfp_mask & __GFP_FS))
-		return -1;
+	if (!(sc->gfp_mask & __GFP_FS))
+		return SHRINK_STOP;
 
 	if (!grab_super_passive(sb))
-		return -1;
+		return SHRINK_STOP;
 
 	if (sb->s_op && sb->s_op->nr_cached_objects)
-		fs_objects = sb->s_op->nr_cached_objects(sb);
-
-	total_objects = sb->s_nr_dentry_unused +
-			sb->s_nr_inodes_unused + fs_objects + 1;
-
-	if (sc->nr_to_scan) {
-		int	dentries;
-		int	inodes;
-
-		/* proportion the scan between the caches */
-		dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) /
-							total_objects;
-		inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) /
-							total_objects;
-		if (fs_objects)
-			fs_objects = (sc->nr_to_scan * fs_objects) /
-							total_objects;
-		/*
-		 * prune the dcache first as the icache is pinned by it, then
-		 * prune the icache, followed by the filesystem specific caches
-		 */
-		prune_dcache_sb(sb, dentries);
-		prune_icache_sb(sb, inodes);
+		fs_objects = sb->s_op->nr_cached_objects(sb, sc->nid);
 
-		if (fs_objects && sb->s_op->free_cached_objects) {
-			sb->s_op->free_cached_objects(sb, fs_objects);
-			fs_objects = sb->s_op->nr_cached_objects(sb);
-		}
-		total_objects = sb->s_nr_dentry_unused +
-				sb->s_nr_inodes_unused + fs_objects;
+	inodes = list_lru_count_node(&sb->s_inode_lru, sc->nid);
+	dentries = list_lru_count_node(&sb->s_dentry_lru, sc->nid);
+	total_objects = dentries + inodes + fs_objects + 1;
+
+	/* proportion the scan between the caches */
+	dentries = mult_frac(sc->nr_to_scan, dentries, total_objects);
+	inodes = mult_frac(sc->nr_to_scan, inodes, total_objects);
+
+	/*
+	 * prune the dcache first as the icache is pinned by it, then
+	 * prune the icache, followed by the filesystem specific caches
+	 */
+	freed = prune_dcache_sb(sb, dentries, sc->nid);
+	freed += prune_icache_sb(sb, inodes, sc->nid);
+
+	if (fs_objects) {
+		fs_objects = mult_frac(sc->nr_to_scan, fs_objects,
+								total_objects);
+		freed += sb->s_op->free_cached_objects(sb, fs_objects,
+						       sc->nid);
 	}
 
-	total_objects = (total_objects / 100) * sysctl_vfs_cache_pressure;
+	drop_super(sb);
+	return freed;
+}
+
+static unsigned long super_cache_count(struct shrinker *shrink,
+				       struct shrink_control *sc)
+{
+	struct super_block *sb;
+	long	total_objects = 0;
+
+	sb = container_of(shrink, struct super_block, s_shrink);
+
+	if (!grab_super_passive(sb))
+		return 0;
+
+	if (sb->s_op && sb->s_op->nr_cached_objects)
+		total_objects = sb->s_op->nr_cached_objects(sb,
+						 sc->nid);
+
+	total_objects += list_lru_count_node(&sb->s_dentry_lru,
+						 sc->nid);
+	total_objects += list_lru_count_node(&sb->s_inode_lru,
+						 sc->nid);
+
+	total_objects = vfs_pressure_ratio(total_objects);
 	drop_super(sb);
 	return total_objects;
 }
@@ -181,9 +201,12 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
 		INIT_HLIST_NODE(&s->s_instances);
 		INIT_HLIST_BL_HEAD(&s->s_anon);
 		INIT_LIST_HEAD(&s->s_inodes);
-		INIT_LIST_HEAD(&s->s_dentry_lru);
-		INIT_LIST_HEAD(&s->s_inode_lru);
-		spin_lock_init(&s->s_inode_lru_lock);
+
+		if (list_lru_init(&s->s_dentry_lru))
+			goto err_out;
+		if (list_lru_init(&s->s_inode_lru))
+			goto err_out_dentry_lru;
+
 		INIT_LIST_HEAD(&s->s_mounts);
 		init_rwsem(&s->s_umount);
 		lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -216,11 +239,16 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
 		s->cleancache_poolid = -1;
 
 		s->s_shrink.seeks = DEFAULT_SEEKS;
-		s->s_shrink.shrink = prune_super;
+		s->s_shrink.scan_objects = super_cache_scan;
+		s->s_shrink.count_objects = super_cache_count;
 		s->s_shrink.batch = 1024;
+		s->s_shrink.flags = SHRINKER_NUMA_AWARE;
 	}
 out:
 	return s;
+
+err_out_dentry_lru:
+	list_lru_destroy(&s->s_dentry_lru);
 err_out:
 	security_sb_free(s);
 #ifdef CONFIG_SMP
@@ -300,6 +328,9 @@ void deactivate_locked_super(struct super_block *s)
 
 		/* caches are now gone, we can safely kill the shrinker now */
 		unregister_shrinker(&s->s_shrink);
+		list_lru_destroy(&s->s_dentry_lru);
+		list_lru_destroy(&s->s_inode_lru);
+
 		put_filesystem(fs);
 		put_super(s);
 	} else {
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
index 9e1d056..f35135e 100644
--- a/fs/ubifs/shrinker.c
+++ b/fs/ubifs/shrinker.c
@@ -277,18 +277,25 @@ static int kick_a_thread(void)
 	return 0;
 }
 
-int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc)
+unsigned long ubifs_shrink_count(struct shrinker *shrink,
+				 struct shrink_control *sc)
 {
-	int nr = sc->nr_to_scan;
-	int freed, contention = 0;
 	long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
 
-	if (nr == 0)
-		/*
-		 * Due to the way UBIFS updates the clean znode counter it may
-		 * temporarily be negative.
-		 */
-		return clean_zn_cnt >= 0 ? clean_zn_cnt : 1;
+	/*
+	 * Due to the way UBIFS updates the clean znode counter it may
+	 * temporarily be negative.
+	 */
+	return clean_zn_cnt >= 0 ? clean_zn_cnt : 1;
+}
+
+unsigned long ubifs_shrink_scan(struct shrinker *shrink,
+				struct shrink_control *sc)
+{
+	unsigned long nr = sc->nr_to_scan;
+	int contention = 0;
+	unsigned long freed;
+	long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
 
 	if (!clean_zn_cnt) {
 		/*
@@ -316,10 +323,10 @@ int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc)
 
 	if (!freed && contention) {
 		dbg_tnc("freed nothing, but contention");
-		return -1;
+		return SHRINK_STOP;
 	}
 
 out:
-	dbg_tnc("%d znodes were freed, requested %d", freed, nr);
+	dbg_tnc("%lu znodes were freed, requested %lu", freed, nr);
 	return freed;
 }
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 879b997..3e4aa72 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -49,7 +49,8 @@ struct kmem_cache *ubifs_inode_slab;
 
 /* UBIFS TNC shrinker description */
 static struct shrinker ubifs_shrinker_info = {
-	.shrink = ubifs_shrinker,
+	.scan_objects = ubifs_shrink_scan,
+	.count_objects = ubifs_shrink_count,
 	.seeks = DEFAULT_SEEKS,
 };
 
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index b2babce..e8c8cfe 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1624,7 +1624,10 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot);
 int ubifs_tnc_end_commit(struct ubifs_info *c);
 
 /* shrinker.c */
-int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc);
+unsigned long ubifs_shrink_scan(struct shrinker *shrink,
+				struct shrink_control *sc);
+unsigned long ubifs_shrink_count(struct shrinker *shrink,
+				 struct shrink_control *sc);
 
 /* commit.c */
 int ubifs_bg_thread(void *info);
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 29569dd..c02a27a 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -141,7 +141,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file_inode(file);
 	int err, pos;
-	size_t count = iocb->ki_left;
+	size_t count = iocb->ki_nbytes;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 
 	down_write(&iinfo->i_data_sem);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 9ac4057..839a2ba 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -630,6 +630,12 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	int error = 0;
 
+	if (sbi->s_lvid_bh) {
+		int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
+		if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY))
+			return -EACCES;
+	}
+
 	uopt.flags = sbi->s_flags;
 	uopt.uid   = sbi->s_uid;
 	uopt.gid   = sbi->s_gid;
@@ -649,12 +655,6 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
 	sbi->s_dmode = uopt.dmode;
 	write_unlock(&sbi->s_cred_lock);
 
-	if (sbi->s_lvid_bh) {
-		int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
-		if (write_rev > UDF_MAX_WRITE_VERSION)
-			*flags |= MS_RDONLY;
-	}
-
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		goto out_unlock;
 
@@ -843,27 +843,38 @@ static int udf_find_fileset(struct super_block *sb,
 	return 1;
 }
 
+/*
+ * Load primary Volume Descriptor Sequence
+ *
+ * Return <0 on error, 0 on success. -EAGAIN is special meaning next sequence
+ * should be tried.
+ */
 static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 {
 	struct primaryVolDesc *pvoldesc;
 	struct ustr *instr, *outstr;
 	struct buffer_head *bh;
 	uint16_t ident;
-	int ret = 1;
+	int ret = -ENOMEM;
 
 	instr = kmalloc(sizeof(struct ustr), GFP_NOFS);
 	if (!instr)
-		return 1;
+		return -ENOMEM;
 
 	outstr = kmalloc(sizeof(struct ustr), GFP_NOFS);
 	if (!outstr)
 		goto out1;
 
 	bh = udf_read_tagged(sb, block, block, &ident);
-	if (!bh)
+	if (!bh) {
+		ret = -EAGAIN;
 		goto out2;
+	}
 
-	BUG_ON(ident != TAG_IDENT_PVD);
+	if (ident != TAG_IDENT_PVD) {
+		ret = -EIO;
+		goto out_bh;
+	}
 
 	pvoldesc = (struct primaryVolDesc *)bh->b_data;
 
@@ -889,8 +900,9 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 		if (udf_CS0toUTF8(outstr, instr))
 			udf_debug("volSetIdent[] = '%s'\n", outstr->u_name);
 
-	brelse(bh);
 	ret = 0;
+out_bh:
+	brelse(bh);
 out2:
 	kfree(outstr);
 out1:
@@ -947,7 +959,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
 
 		if (mdata->s_mirror_fe == NULL) {
 			udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
-			goto error_exit;
+			return -EIO;
 		}
 	}
 
@@ -964,23 +976,18 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
 			  addr.logicalBlockNum, addr.partitionReferenceNum);
 
 		mdata->s_bitmap_fe = udf_iget(sb, &addr);
-
 		if (mdata->s_bitmap_fe == NULL) {
 			if (sb->s_flags & MS_RDONLY)
 				udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");
 			else {
 				udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n");
-				goto error_exit;
+				return -EIO;
 			}
 		}
 	}
 
 	udf_debug("udf_load_metadata_files Ok\n");
-
 	return 0;
-
-error_exit:
-	return 1;
 }
 
 static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
@@ -1069,7 +1076,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 		if (!map->s_uspace.s_table) {
 			udf_debug("cannot load unallocSpaceTable (part %d)\n",
 				  p_index);
-			return 1;
+			return -EIO;
 		}
 		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
 		udf_debug("unallocSpaceTable (part %d) @ %ld\n",
@@ -1079,7 +1086,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 	if (phd->unallocSpaceBitmap.extLength) {
 		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
 		if (!bitmap)
-			return 1;
+			return -ENOMEM;
 		map->s_uspace.s_bitmap = bitmap;
 		bitmap->s_extPosition = le32_to_cpu(
 				phd->unallocSpaceBitmap.extPosition);
@@ -1102,7 +1109,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 		if (!map->s_fspace.s_table) {
 			udf_debug("cannot load freedSpaceTable (part %d)\n",
 				  p_index);
-			return 1;
+			return -EIO;
 		}
 
 		map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
@@ -1113,7 +1120,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 	if (phd->freedSpaceBitmap.extLength) {
 		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
 		if (!bitmap)
-			return 1;
+			return -ENOMEM;
 		map->s_fspace.s_bitmap = bitmap;
 		bitmap->s_extPosition = le32_to_cpu(
 				phd->freedSpaceBitmap.extPosition);
@@ -1165,7 +1172,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
 		udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
 	}
 	if (!sbi->s_vat_inode)
-		return 1;
+		return -EIO;
 
 	if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
 		map->s_type_specific.s_virtual.s_start_offset = 0;
@@ -1177,7 +1184,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
 			pos = udf_block_map(sbi->s_vat_inode, 0);
 			bh = sb_bread(sb, pos);
 			if (!bh)
-				return 1;
+				return -EIO;
 			vat20 = (struct virtualAllocationTable20 *)bh->b_data;
 		} else {
 			vat20 = (struct virtualAllocationTable20 *)
@@ -1195,6 +1202,12 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
 	return 0;
 }
 
+/*
+ * Load partition descriptor block
+ *
+ * Returns <0 on error, 0 on success, -EAGAIN is special - try next descriptor
+ * sequence.
+ */
 static int udf_load_partdesc(struct super_block *sb, sector_t block)
 {
 	struct buffer_head *bh;
@@ -1204,13 +1217,15 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
 	int i, type1_idx;
 	uint16_t partitionNumber;
 	uint16_t ident;
-	int ret = 0;
+	int ret;
 
 	bh = udf_read_tagged(sb, block, block, &ident);
 	if (!bh)
-		return 1;
-	if (ident != TAG_IDENT_PD)
+		return -EAGAIN;
+	if (ident != TAG_IDENT_PD) {
+		ret = 0;
 		goto out_bh;
+	}
 
 	p = (struct partitionDesc *)bh->b_data;
 	partitionNumber = le16_to_cpu(p->partitionNumber);
@@ -1229,10 +1244,13 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
 	if (i >= sbi->s_partitions) {
 		udf_debug("Partition (%d) not found in partition map\n",
 			  partitionNumber);
+		ret = 0;
 		goto out_bh;
 	}
 
 	ret = udf_fill_partdesc_info(sb, p, i);
+	if (ret < 0)
+		goto out_bh;
 
 	/*
 	 * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
@@ -1249,32 +1267,37 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
 			break;
 	}
 
-	if (i >= sbi->s_partitions)
+	if (i >= sbi->s_partitions) {
+		ret = 0;
 		goto out_bh;
+	}
 
 	ret = udf_fill_partdesc_info(sb, p, i);
-	if (ret)
+	if (ret < 0)
 		goto out_bh;
 
 	if (map->s_partition_type == UDF_METADATA_MAP25) {
 		ret = udf_load_metadata_files(sb, i);
-		if (ret) {
+		if (ret < 0) {
 			udf_err(sb, "error loading MetaData partition map %d\n",
 				i);
 			goto out_bh;
 		}
 	} else {
-		ret = udf_load_vat(sb, i, type1_idx);
-		if (ret)
-			goto out_bh;
 		/*
-		 * Mark filesystem read-only if we have a partition with
-		 * virtual map since we don't handle writing to it (we
-		 * overwrite blocks instead of relocating them).
+		 * If we have a partition with virtual map, we don't handle
+		 * writing to it (we overwrite blocks instead of relocating
+		 * them).
 		 */
-		sb->s_flags |= MS_RDONLY;
-		pr_notice("Filesystem marked read-only because writing to pseudooverwrite partition is not implemented\n");
+		if (!(sb->s_flags & MS_RDONLY)) {
+			ret = -EACCES;
+			goto out_bh;
+		}
+		ret = udf_load_vat(sb, i, type1_idx);
+		if (ret < 0)
+			goto out_bh;
 	}
+	ret = 0;
 out_bh:
 	/* In case loading failed, we handle cleanup in udf_fill_super */
 	brelse(bh);
@@ -1340,11 +1363,11 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 	uint16_t ident;
 	struct buffer_head *bh;
 	unsigned int table_len;
-	int ret = 0;
+	int ret;
 
 	bh = udf_read_tagged(sb, block, block, &ident);
 	if (!bh)
-		return 1;
+		return -EAGAIN;
 	BUG_ON(ident != TAG_IDENT_LVD);
 	lvd = (struct logicalVolDesc *)bh->b_data;
 	table_len = le32_to_cpu(lvd->mapTableLength);
@@ -1352,7 +1375,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 		udf_err(sb, "error loading logical volume descriptor: "
 			"Partition table too long (%u > %lu)\n", table_len,
 			sb->s_blocksize - sizeof(*lvd));
-		ret = 1;
+		ret = -EIO;
 		goto out_bh;
 	}
 
@@ -1396,11 +1419,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 			} else if (!strncmp(upm2->partIdent.ident,
 						UDF_ID_SPARABLE,
 						strlen(UDF_ID_SPARABLE))) {
-				if (udf_load_sparable_map(sb, map,
-				    (struct sparablePartitionMap *)gpm) < 0) {
-					ret = 1;
+				ret = udf_load_sparable_map(sb, map,
+					(struct sparablePartitionMap *)gpm);
+				if (ret < 0)
 					goto out_bh;
-				}
 			} else if (!strncmp(upm2->partIdent.ident,
 						UDF_ID_METADATA,
 						strlen(UDF_ID_METADATA))) {
@@ -1465,7 +1487,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 	}
 	if (lvd->integritySeqExt.extLength)
 		udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
-
+	ret = 0;
 out_bh:
 	brelse(bh);
 	return ret;
@@ -1503,22 +1525,18 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
 }
 
 /*
- * udf_process_sequence
- *
- * PURPOSE
- *	Process a main/reserve volume descriptor sequence.
- *
- * PRE-CONDITIONS
- *	sb			Pointer to _locked_ superblock.
- *	block			First block of first extent of the sequence.
- *	lastblock		Lastblock of first extent of the sequence.
+ * Process a main/reserve volume descriptor sequence.
+ *   @block		First block of first extent of the sequence.
+ *   @lastblock		Lastblock of first extent of the sequence.
+ *   @fileset		There we store extent containing root fileset
  *
- * HISTORY
- *	July 1, 1997 - Andrew E. Mileski
- *	Written, tested, and released.
+ * Returns <0 on error, 0 on success. -EAGAIN is special - try next descriptor
+ * sequence
  */
-static noinline int udf_process_sequence(struct super_block *sb, long block,
-				long lastblock, struct kernel_lb_addr *fileset)
+static noinline int udf_process_sequence(
+		struct super_block *sb,
+		sector_t block, sector_t lastblock,
+		struct kernel_lb_addr *fileset)
 {
 	struct buffer_head *bh = NULL;
 	struct udf_vds_record vds[VDS_POS_LENGTH];
@@ -1529,6 +1547,7 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
 	uint32_t vdsn;
 	uint16_t ident;
 	long next_s = 0, next_e = 0;
+	int ret;
 
 	memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
 
@@ -1543,7 +1562,7 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
 			udf_err(sb,
 				"Block %llu of volume descriptor sequence is corrupted or we could not read it\n",
 				(unsigned long long)block);
-			return 1;
+			return -EAGAIN;
 		}
 
 		/* Process each descriptor (ISO 13346 3/8.3-8.4) */
@@ -1616,14 +1635,19 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
 	 */
 	if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
 		udf_err(sb, "Primary Volume Descriptor not found!\n");
-		return 1;
+		return -EAGAIN;
+	}
+	ret = udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block);
+	if (ret < 0)
+		return ret;
+
+	if (vds[VDS_POS_LOGICAL_VOL_DESC].block) {
+		ret = udf_load_logicalvol(sb,
+					  vds[VDS_POS_LOGICAL_VOL_DESC].block,
+					  fileset);
+		if (ret < 0)
+			return ret;
 	}
-	if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
-		return 1;
-
-	if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb,
-	    vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset))
-		return 1;
 
 	if (vds[VDS_POS_PARTITION_DESC].block) {
 		/*
@@ -1632,19 +1656,27 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
 		 */
 		for (block = vds[VDS_POS_PARTITION_DESC].block;
 		     block < vds[VDS_POS_TERMINATING_DESC].block;
-		     block++)
-			if (udf_load_partdesc(sb, block))
-				return 1;
+		     block++) {
+			ret = udf_load_partdesc(sb, block);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	return 0;
 }
 
+/*
+ * Load Volume Descriptor Sequence described by anchor in bh
+ *
+ * Returns <0 on error, 0 on success
+ */
 static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
 			     struct kernel_lb_addr *fileset)
 {
 	struct anchorVolDescPtr *anchor;
-	long main_s, main_e, reserve_s, reserve_e;
+	sector_t main_s, main_e, reserve_s, reserve_e;
+	int ret;
 
 	anchor = (struct anchorVolDescPtr *)bh->b_data;
 
@@ -1662,18 +1694,26 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
 
 	/* Process the main & reserve sequences */
 	/* responsible for finding the PartitionDesc(s) */
-	if (!udf_process_sequence(sb, main_s, main_e, fileset))
-		return 1;
-	udf_sb_free_partitions(sb);
-	if (!udf_process_sequence(sb, reserve_s, reserve_e, fileset))
-		return 1;
+	ret = udf_process_sequence(sb, main_s, main_e, fileset);
+	if (ret != -EAGAIN)
+		return ret;
 	udf_sb_free_partitions(sb);
-	return 0;
+	ret = udf_process_sequence(sb, reserve_s, reserve_e, fileset);
+	if (ret < 0) {
+		udf_sb_free_partitions(sb);
+		/* No sequence was OK, return -EIO */
+		if (ret == -EAGAIN)
+			ret = -EIO;
+	}
+	return ret;
 }
 
 /*
  * Check whether there is an anchor block in the given block and
  * load Volume Descriptor Sequence if so.
+ *
+ * Returns <0 on error, 0 on success, -EAGAIN is special - try next anchor
+ * block
  */
 static int udf_check_anchor_block(struct super_block *sb, sector_t block,
 				  struct kernel_lb_addr *fileset)
@@ -1685,33 +1725,40 @@ static int udf_check_anchor_block(struct super_block *sb, sector_t block,
 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
 	    udf_fixed_to_variable(block) >=
 	    sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
-		return 0;
+		return -EAGAIN;
 
 	bh = udf_read_tagged(sb, block, block, &ident);
 	if (!bh)
-		return 0;
+		return -EAGAIN;
 	if (ident != TAG_IDENT_AVDP) {
 		brelse(bh);
-		return 0;
+		return -EAGAIN;
 	}
 	ret = udf_load_sequence(sb, bh, fileset);
 	brelse(bh);
 	return ret;
 }
 
-/* Search for an anchor volume descriptor pointer */
-static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,
-				 struct kernel_lb_addr *fileset)
+/*
+ * Search for an anchor volume descriptor pointer.
+ *
+ * Returns < 0 on error, 0 on success. -EAGAIN is special - try next set
+ * of anchors.
+ */
+static int udf_scan_anchors(struct super_block *sb, sector_t *lastblock,
+			    struct kernel_lb_addr *fileset)
 {
 	sector_t last[6];
 	int i;
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	int last_count = 0;
+	int ret;
 
 	/* First try user provided anchor */
 	if (sbi->s_anchor) {
-		if (udf_check_anchor_block(sb, sbi->s_anchor, fileset))
-			return lastblock;
+		ret = udf_check_anchor_block(sb, sbi->s_anchor, fileset);
+		if (ret != -EAGAIN)
+			return ret;
 	}
 	/*
 	 * according to spec, anchor is in either:
@@ -1720,39 +1767,46 @@ static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,
 	 *     lastblock
 	 *  however, if the disc isn't closed, it could be 512.
 	 */
-	if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset))
-		return lastblock;
+	ret = udf_check_anchor_block(sb, sbi->s_session + 256, fileset);
+	if (ret != -EAGAIN)
+		return ret;
 	/*
 	 * The trouble is which block is the last one. Drives often misreport
 	 * this so we try various possibilities.
 	 */
-	last[last_count++] = lastblock;
-	if (lastblock >= 1)
-		last[last_count++] = lastblock - 1;
-	last[last_count++] = lastblock + 1;
-	if (lastblock >= 2)
-		last[last_count++] = lastblock - 2;
-	if (lastblock >= 150)
-		last[last_count++] = lastblock - 150;
-	if (lastblock >= 152)
-		last[last_count++] = lastblock - 152;
+	last[last_count++] = *lastblock;
+	if (*lastblock >= 1)
+		last[last_count++] = *lastblock - 1;
+	last[last_count++] = *lastblock + 1;
+	if (*lastblock >= 2)
+		last[last_count++] = *lastblock - 2;
+	if (*lastblock >= 150)
+		last[last_count++] = *lastblock - 150;
+	if (*lastblock >= 152)
+		last[last_count++] = *lastblock - 152;
 
 	for (i = 0; i < last_count; i++) {
 		if (last[i] >= sb->s_bdev->bd_inode->i_size >>
 				sb->s_blocksize_bits)
 			continue;
-		if (udf_check_anchor_block(sb, last[i], fileset))
-			return last[i];
+		ret = udf_check_anchor_block(sb, last[i], fileset);
+		if (ret != -EAGAIN) {
+			if (!ret)
+				*lastblock = last[i];
+			return ret;
+		}
 		if (last[i] < 256)
 			continue;
-		if (udf_check_anchor_block(sb, last[i] - 256, fileset))
-			return last[i];
+		ret = udf_check_anchor_block(sb, last[i] - 256, fileset);
+		if (ret != -EAGAIN) {
+			if (!ret)
+				*lastblock = last[i];
+			return ret;
+		}
 	}
 
 	/* Finally try block 512 in case media is open */
-	if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset))
-		return last[0];
-	return 0;
+	return udf_check_anchor_block(sb, sbi->s_session + 512, fileset);
 }
 
 /*
@@ -1760,54 +1814,59 @@ static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,
  * area specified by it. The function expects sbi->s_lastblock to be the last
  * block on the media.
  *
- * Return 1 if ok, 0 if not found.
- *
+ * Return <0 on error, 0 if anchor found. -EAGAIN is special meaning anchor
+ * was not found.
  */
 static int udf_find_anchor(struct super_block *sb,
 			   struct kernel_lb_addr *fileset)
 {
-	sector_t lastblock;
 	struct udf_sb_info *sbi = UDF_SB(sb);
+	sector_t lastblock = sbi->s_last_block;
+	int ret;
 
-	lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
-	if (lastblock)
+	ret = udf_scan_anchors(sb, &lastblock, fileset);
+	if (ret != -EAGAIN)
 		goto out;
 
 	/* No anchor found? Try VARCONV conversion of block numbers */
 	UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+	lastblock = udf_variable_to_fixed(sbi->s_last_block);
 	/* Firstly, we try to not convert number of the last block */
-	lastblock = udf_scan_anchors(sb,
-				udf_variable_to_fixed(sbi->s_last_block),
-				fileset);
-	if (lastblock)
+	ret = udf_scan_anchors(sb, &lastblock, fileset);
+	if (ret != -EAGAIN)
 		goto out;
 
+	lastblock = sbi->s_last_block;
 	/* Secondly, we try with converted number of the last block */
-	lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
-	if (!lastblock) {
+	ret = udf_scan_anchors(sb, &lastblock, fileset);
+	if (ret < 0) {
 		/* VARCONV didn't help. Clear it. */
 		UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
-		return 0;
 	}
 out:
-	sbi->s_last_block = lastblock;
-	return 1;
+	if (ret == 0)
+		sbi->s_last_block = lastblock;
+	return ret;
 }
 
 /*
  * Check Volume Structure Descriptor, find Anchor block and load Volume
- * Descriptor Sequence
+ * Descriptor Sequence.
+ *
+ * Returns < 0 on error, 0 on success. -EAGAIN is special meaning anchor
+ * block was not found.
  */
 static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
 			int silent, struct kernel_lb_addr *fileset)
 {
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	loff_t nsr_off;
+	int ret;
 
 	if (!sb_set_blocksize(sb, uopt->blocksize)) {
 		if (!silent)
 			udf_warn(sb, "Bad block size\n");
-		return 0;
+		return -EINVAL;
 	}
 	sbi->s_last_block = uopt->lastblock;
 	if (!uopt->novrs) {
@@ -1828,12 +1887,13 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
 
 	/* Look for anchor block and load Volume Descriptor Sequence */
 	sbi->s_anchor = uopt->anchor;
-	if (!udf_find_anchor(sb, fileset)) {
-		if (!silent)
+	ret = udf_find_anchor(sb, fileset);
+	if (ret < 0) {
+		if (!silent && ret == -EAGAIN)
 			udf_warn(sb, "No anchor found\n");
-		return 0;
+		return ret;
 	}
-	return 1;
+	return 0;
 }
 
 static void udf_open_lvid(struct super_block *sb)
@@ -1939,7 +1999,7 @@ u64 lvid_get_unique_id(struct super_block *sb)
 
 static int udf_fill_super(struct super_block *sb, void *options, int silent)
 {
-	int ret;
+	int ret = -EINVAL;
 	struct inode *inode = NULL;
 	struct udf_options uopt;
 	struct kernel_lb_addr rootdir, fileset;
@@ -2011,7 +2071,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	} else {
 		uopt.blocksize = bdev_logical_block_size(sb->s_bdev);
 		ret = udf_load_vrs(sb, &uopt, silent, &fileset);
-		if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
+		if (ret == -EAGAIN && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
 			if (!silent)
 				pr_notice("Rescanning with blocksize %d\n",
 					  UDF_DEFAULT_BLOCKSIZE);
@@ -2021,8 +2081,11 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 			ret = udf_load_vrs(sb, &uopt, silent, &fileset);
 		}
 	}
-	if (!ret) {
-		udf_warn(sb, "No partition found (1)\n");
+	if (ret < 0) {
+		if (ret == -EAGAIN) {
+			udf_warn(sb, "No partition found (1)\n");
+			ret = -EINVAL;
+		}
 		goto error_out;
 	}
 
@@ -2040,9 +2103,13 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 			udf_err(sb, "minUDFReadRev=%x (max is %x)\n",
 				le16_to_cpu(lvidiu->minUDFReadRev),
 				UDF_MAX_READ_VERSION);
+			ret = -EINVAL;
+			goto error_out;
+		} else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION &&
+			   !(sb->s_flags & MS_RDONLY)) {
+			ret = -EACCES;
 			goto error_out;
-		} else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
-			sb->s_flags |= MS_RDONLY;
+		}
 
 		sbi->s_udfrev = minUDFWriteRev;
 
@@ -2054,17 +2121,20 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
 	if (!sbi->s_partitions) {
 		udf_warn(sb, "No partition found (2)\n");
+		ret = -EINVAL;
 		goto error_out;
 	}
 
 	if (sbi->s_partmaps[sbi->s_partition].s_partition_flags &
-			UDF_PART_FLAG_READ_ONLY) {
-		pr_notice("Partition marked readonly; forcing readonly mount\n");
-		sb->s_flags |= MS_RDONLY;
+			UDF_PART_FLAG_READ_ONLY &&
+	    !(sb->s_flags & MS_RDONLY)) {
+		ret = -EACCES;
+		goto error_out;
 	}
 
 	if (udf_find_fileset(sb, &fileset, &rootdir)) {
 		udf_warn(sb, "No fileset found\n");
+		ret = -EINVAL;
 		goto error_out;
 	}
 
@@ -2086,6 +2156,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	if (!inode) {
 		udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n",
 		       rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
+		ret = -EIO;
 		goto error_out;
 	}
 
@@ -2093,6 +2164,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	sb->s_root = d_make_root(inode);
 	if (!sb->s_root) {
 		udf_err(sb, "Couldn't allocate root dentry\n");
+		ret = -ENOMEM;
 		goto error_out;
 	}
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -2113,7 +2185,7 @@ error_out:
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 
-	return -EINVAL;
+	return ret;
 }
 
 void _udf_err(struct super_block *sb, const char *function,
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 596ec71..7967086 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1516,13 +1516,26 @@ xfs_vm_write_failed(
 	loff_t			pos,
 	unsigned		len)
 {
-	loff_t			block_offset = pos & PAGE_MASK;
+	loff_t			block_offset;
 	loff_t			block_start;
 	loff_t			block_end;
 	loff_t			from = pos & (PAGE_CACHE_SIZE - 1);
 	loff_t			to = from + len;
 	struct buffer_head	*bh, *head;
 
+	/*
+	 * The request pos offset might be 32 or 64 bit, this is all fine
+	 * on 64-bit platform.  However, for 64-bit pos request on 32-bit
+	 * platform, the high 32-bit will be masked off if we evaluate the
+	 * block_offset via (pos & PAGE_MASK) because the PAGE_MASK is
+	 * 0xfffff000 as an unsigned long, hence the result is incorrect
+	 * which could cause the following ASSERT failed in most cases.
+	 * In order to avoid this, we can evaluate the block_offset of the
+	 * start of the page by using shifts rather than masks the mismatch
+	 * problem.
+	 */
+	block_offset = (pos >> PAGE_CACHE_SHIFT) << PAGE_CACHE_SHIFT;
+
 	ASSERT(block_offset + from == pos);
 
 	head = page_buffers(page);
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 1b2472a..8b2c5aa 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -80,54 +80,6 @@ xfs_buf_vmap_len(
 }
 
 /*
- * xfs_buf_lru_add - add a buffer to the LRU.
- *
- * The LRU takes a new reference to the buffer so that it will only be freed
- * once the shrinker takes the buffer off the LRU.
- */
-STATIC void
-xfs_buf_lru_add(
-	struct xfs_buf	*bp)
-{
-	struct xfs_buftarg *btp = bp->b_target;
-
-	spin_lock(&btp->bt_lru_lock);
-	if (list_empty(&bp->b_lru)) {
-		atomic_inc(&bp->b_hold);
-		list_add_tail(&bp->b_lru, &btp->bt_lru);
-		btp->bt_lru_nr++;
-		bp->b_lru_flags &= ~_XBF_LRU_DISPOSE;
-	}
-	spin_unlock(&btp->bt_lru_lock);
-}
-
-/*
- * xfs_buf_lru_del - remove a buffer from the LRU
- *
- * The unlocked check is safe here because it only occurs when there are not
- * b_lru_ref counts left on the inode under the pag->pag_buf_lock. it is there
- * to optimise the shrinker removing the buffer from the LRU and calling
- * xfs_buf_free(). i.e. it removes an unnecessary round trip on the
- * bt_lru_lock.
- */
-STATIC void
-xfs_buf_lru_del(
-	struct xfs_buf	*bp)
-{
-	struct xfs_buftarg *btp = bp->b_target;
-
-	if (list_empty(&bp->b_lru))
-		return;
-
-	spin_lock(&btp->bt_lru_lock);
-	if (!list_empty(&bp->b_lru)) {
-		list_del_init(&bp->b_lru);
-		btp->bt_lru_nr--;
-	}
-	spin_unlock(&btp->bt_lru_lock);
-}
-
-/*
  * When we mark a buffer stale, we remove the buffer from the LRU and clear the
  * b_lru_ref count so that the buffer is freed immediately when the buffer
  * reference count falls to zero. If the buffer is already on the LRU, we need
@@ -150,20 +102,14 @@ xfs_buf_stale(
 	 */
 	bp->b_flags &= ~_XBF_DELWRI_Q;
 
-	atomic_set(&(bp)->b_lru_ref, 0);
-	if (!list_empty(&bp->b_lru)) {
-		struct xfs_buftarg *btp = bp->b_target;
+	spin_lock(&bp->b_lock);
+	atomic_set(&bp->b_lru_ref, 0);
+	if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
+	    (list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
+		atomic_dec(&bp->b_hold);
 
-		spin_lock(&btp->bt_lru_lock);
-		if (!list_empty(&bp->b_lru) &&
-		    !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) {
-			list_del_init(&bp->b_lru);
-			btp->bt_lru_nr--;
-			atomic_dec(&bp->b_hold);
-		}
-		spin_unlock(&btp->bt_lru_lock);
-	}
 	ASSERT(atomic_read(&bp->b_hold) >= 1);
+	spin_unlock(&bp->b_lock);
 }
 
 static int
@@ -227,6 +173,7 @@ _xfs_buf_alloc(
 	INIT_LIST_HEAD(&bp->b_list);
 	RB_CLEAR_NODE(&bp->b_rbnode);
 	sema_init(&bp->b_sema, 0); /* held, no waiters */
+	spin_lock_init(&bp->b_lock);
 	XB_SET_OWNER(bp);
 	bp->b_target = target;
 	bp->b_flags = flags;
@@ -916,12 +863,33 @@ xfs_buf_rele(
 
 	ASSERT(atomic_read(&bp->b_hold) > 0);
 	if (atomic_dec_and_lock(&bp->b_hold, &pag->pag_buf_lock)) {
-		if (!(bp->b_flags & XBF_STALE) &&
-			   atomic_read(&bp->b_lru_ref)) {
-			xfs_buf_lru_add(bp);
+		spin_lock(&bp->b_lock);
+		if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
+			/*
+			 * If the buffer is added to the LRU take a new
+			 * reference to the buffer for the LRU and clear the
+			 * (now stale) dispose list state flag
+			 */
+			if (list_lru_add(&bp->b_target->bt_lru, &bp->b_lru)) {
+				bp->b_state &= ~XFS_BSTATE_DISPOSE;
+				atomic_inc(&bp->b_hold);
+			}
+			spin_unlock(&bp->b_lock);
 			spin_unlock(&pag->pag_buf_lock);
 		} else {
-			xfs_buf_lru_del(bp);
+			/*
+			 * most of the time buffers will already be removed from
+			 * the LRU, so optimise that case by checking for the
+			 * XFS_BSTATE_DISPOSE flag indicating the last list the
+			 * buffer was on was the disposal list
+			 */
+			if (!(bp->b_state & XFS_BSTATE_DISPOSE)) {
+				list_lru_del(&bp->b_target->bt_lru, &bp->b_lru);
+			} else {
+				ASSERT(list_empty(&bp->b_lru));
+			}
+			spin_unlock(&bp->b_lock);
+
 			ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
 			rb_erase(&bp->b_rbnode, &pag->pag_buf_tree);
 			spin_unlock(&pag->pag_buf_lock);
@@ -1501,83 +1469,121 @@ xfs_buf_iomove(
  * returned. These buffers will have an elevated hold count, so wait on those
  * while freeing all the buffers only held by the LRU.
  */
+static enum lru_status
+xfs_buftarg_wait_rele(
+	struct list_head	*item,
+	spinlock_t		*lru_lock,
+	void			*arg)
+
+{
+	struct xfs_buf		*bp = container_of(item, struct xfs_buf, b_lru);
+	struct list_head	*dispose = arg;
+
+	if (atomic_read(&bp->b_hold) > 1) {
+		/* need to wait, so skip it this pass */
+		trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
+		return LRU_SKIP;
+	}
+	if (!spin_trylock(&bp->b_lock))
+		return LRU_SKIP;
+
+	/*
+	 * clear the LRU reference count so the buffer doesn't get
+	 * ignored in xfs_buf_rele().
+	 */
+	atomic_set(&bp->b_lru_ref, 0);
+	bp->b_state |= XFS_BSTATE_DISPOSE;
+	list_move(item, dispose);
+	spin_unlock(&bp->b_lock);
+	return LRU_REMOVED;
+}
+
 void
 xfs_wait_buftarg(
 	struct xfs_buftarg	*btp)
 {
-	struct xfs_buf		*bp;
+	LIST_HEAD(dispose);
+	int loop = 0;
 
-restart:
-	spin_lock(&btp->bt_lru_lock);
-	while (!list_empty(&btp->bt_lru)) {
-		bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
-		if (atomic_read(&bp->b_hold) > 1) {
-			trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
-			list_move_tail(&bp->b_lru, &btp->bt_lru);
-			spin_unlock(&btp->bt_lru_lock);
-			delay(100);
-			goto restart;
+	/* loop until there is nothing left on the lru list. */
+	while (list_lru_count(&btp->bt_lru)) {
+		list_lru_walk(&btp->bt_lru, xfs_buftarg_wait_rele,
+			      &dispose, LONG_MAX);
+
+		while (!list_empty(&dispose)) {
+			struct xfs_buf *bp;
+			bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
+			list_del_init(&bp->b_lru);
+			xfs_buf_rele(bp);
 		}
-		/*
-		 * clear the LRU reference count so the buffer doesn't get
-		 * ignored in xfs_buf_rele().
-		 */
-		atomic_set(&bp->b_lru_ref, 0);
-		spin_unlock(&btp->bt_lru_lock);
-		xfs_buf_rele(bp);
-		spin_lock(&btp->bt_lru_lock);
+		if (loop++ != 0)
+			delay(100);
 	}
-	spin_unlock(&btp->bt_lru_lock);
 }
 
-int
-xfs_buftarg_shrink(
+static enum lru_status
+xfs_buftarg_isolate(
+	struct list_head	*item,
+	spinlock_t		*lru_lock,
+	void			*arg)
+{
+	struct xfs_buf		*bp = container_of(item, struct xfs_buf, b_lru);
+	struct list_head	*dispose = arg;
+
+	/*
+	 * we are inverting the lru lock/bp->b_lock here, so use a trylock.
+	 * If we fail to get the lock, just skip it.
+	 */
+	if (!spin_trylock(&bp->b_lock))
+		return LRU_SKIP;
+	/*
+	 * Decrement the b_lru_ref count unless the value is already
+	 * zero. If the value is already zero, we need to reclaim the
+	 * buffer, otherwise it gets another trip through the LRU.
+	 */
+	if (!atomic_add_unless(&bp->b_lru_ref, -1, 0)) {
+		spin_unlock(&bp->b_lock);
+		return LRU_ROTATE;
+	}
+
+	bp->b_state |= XFS_BSTATE_DISPOSE;
+	list_move(item, dispose);
+	spin_unlock(&bp->b_lock);
+	return LRU_REMOVED;
+}
+
+static unsigned long
+xfs_buftarg_shrink_scan(
 	struct shrinker		*shrink,
 	struct shrink_control	*sc)
 {
 	struct xfs_buftarg	*btp = container_of(shrink,
 					struct xfs_buftarg, bt_shrinker);
-	struct xfs_buf		*bp;
-	int nr_to_scan = sc->nr_to_scan;
 	LIST_HEAD(dispose);
+	unsigned long		freed;
+	unsigned long		nr_to_scan = sc->nr_to_scan;
 
-	if (!nr_to_scan)
-		return btp->bt_lru_nr;
-
-	spin_lock(&btp->bt_lru_lock);
-	while (!list_empty(&btp->bt_lru)) {
-		if (nr_to_scan-- <= 0)
-			break;
-
-		bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
-
-		/*
-		 * Decrement the b_lru_ref count unless the value is already
-		 * zero. If the value is already zero, we need to reclaim the
-		 * buffer, otherwise it gets another trip through the LRU.
-		 */
-		if (!atomic_add_unless(&bp->b_lru_ref, -1, 0)) {
-			list_move_tail(&bp->b_lru, &btp->bt_lru);
-			continue;
-		}
-
-		/*
-		 * remove the buffer from the LRU now to avoid needing another
-		 * lock round trip inside xfs_buf_rele().
-		 */
-		list_move(&bp->b_lru, &dispose);
-		btp->bt_lru_nr--;
-		bp->b_lru_flags |= _XBF_LRU_DISPOSE;
-	}
-	spin_unlock(&btp->bt_lru_lock);
+	freed = list_lru_walk_node(&btp->bt_lru, sc->nid, xfs_buftarg_isolate,
+				       &dispose, &nr_to_scan);
 
 	while (!list_empty(&dispose)) {
+		struct xfs_buf *bp;
 		bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
 		list_del_init(&bp->b_lru);
 		xfs_buf_rele(bp);
 	}
 
-	return btp->bt_lru_nr;
+	return freed;
+}
+
+static unsigned long
+xfs_buftarg_shrink_count(
+	struct shrinker		*shrink,
+	struct shrink_control	*sc)
+{
+	struct xfs_buftarg	*btp = container_of(shrink,
+					struct xfs_buftarg, bt_shrinker);
+	return list_lru_count_node(&btp->bt_lru, sc->nid);
 }
 
 void
@@ -1586,6 +1592,7 @@ xfs_free_buftarg(
 	struct xfs_buftarg	*btp)
 {
 	unregister_shrinker(&btp->bt_shrinker);
+	list_lru_destroy(&btp->bt_lru);
 
 	if (mp->m_flags & XFS_MOUNT_BARRIER)
 		xfs_blkdev_issue_flush(btp);
@@ -1659,12 +1666,16 @@ xfs_alloc_buftarg(
 	if (!btp->bt_bdi)
 		goto error;
 
-	INIT_LIST_HEAD(&btp->bt_lru);
-	spin_lock_init(&btp->bt_lru_lock);
 	if (xfs_setsize_buftarg_early(btp, bdev))
 		goto error;
-	btp->bt_shrinker.shrink = xfs_buftarg_shrink;
+
+	if (list_lru_init(&btp->bt_lru))
+		goto error;
+
+	btp->bt_shrinker.count_objects = xfs_buftarg_shrink_count;
+	btp->bt_shrinker.scan_objects = xfs_buftarg_shrink_scan;
 	btp->bt_shrinker.seeks = DEFAULT_SEEKS;
+	btp->bt_shrinker.flags = SHRINKER_NUMA_AWARE;
 	register_shrinker(&btp->bt_shrinker);
 	return btp;
 
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 433a12e..e656833 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/uio.h>
+#include <linux/list_lru.h>
 
 /*
  *	Base types
@@ -59,7 +60,6 @@ typedef enum {
 #define _XBF_KMEM	 (1 << 21)/* backed by heap memory */
 #define _XBF_DELWRI_Q	 (1 << 22)/* buffer on a delwri queue */
 #define _XBF_COMPOUND	 (1 << 23)/* compound buffer */
-#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */
 
 typedef unsigned int xfs_buf_flags_t;
 
@@ -78,8 +78,12 @@ typedef unsigned int xfs_buf_flags_t;
 	{ _XBF_PAGES,		"PAGES" }, \
 	{ _XBF_KMEM,		"KMEM" }, \
 	{ _XBF_DELWRI_Q,	"DELWRI_Q" }, \
-	{ _XBF_COMPOUND,	"COMPOUND" }, \
-	{ _XBF_LRU_DISPOSE,	"LRU_DISPOSE" }
+	{ _XBF_COMPOUND,	"COMPOUND" }
+
+/*
+ * Internal state flags.
+ */
+#define XFS_BSTATE_DISPOSE	 (1 << 0)	/* buffer being discarded */
 
 typedef struct xfs_buftarg {
 	dev_t			bt_dev;
@@ -92,9 +96,7 @@ typedef struct xfs_buftarg {
 
 	/* LRU control structures */
 	struct shrinker		bt_shrinker;
-	struct list_head	bt_lru;
-	spinlock_t		bt_lru_lock;
-	unsigned int		bt_lru_nr;
+	struct list_lru		bt_lru;
 } xfs_buftarg_t;
 
 struct xfs_buf;
@@ -137,7 +139,8 @@ typedef struct xfs_buf {
 	 * bt_lru_lock and not by b_sema
 	 */
 	struct list_head	b_lru;		/* lru list */
-	xfs_buf_flags_t		b_lru_flags;	/* internal lru status flags */
+	spinlock_t		b_lock;		/* internal state lock */
+	unsigned int		b_state;	/* internal state flags */
 	wait_queue_head_t	b_waiters;	/* unpin waiters */
 	struct list_head	b_list;
 	struct xfs_perag	*b_pag;		/* contains rbtree root */
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 0adf27e..7219cd7 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -940,13 +940,8 @@ xfs_qm_dqput_final(
 
 	trace_xfs_dqput_free(dqp);
 
-	mutex_lock(&qi->qi_lru_lock);
-	if (list_empty(&dqp->q_lru)) {
-		list_add_tail(&dqp->q_lru, &qi->qi_lru_list);
-		qi->qi_lru_count++;
+	if (list_lru_add(&qi->qi_lru, &dqp->q_lru))
 		XFS_STATS_INC(xs_qm_dquot_unused);
-	}
-	mutex_unlock(&qi->qi_lru_lock);
 
 	/*
 	 * If we just added a udquot to the freelist, then we want to release
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 3f90e1c..079c3bd 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1166,7 +1166,7 @@ xfs_reclaim_inodes(
  * them to be cleaned, which we hope will not be very long due to the
  * background walker having already kicked the IO off on those dirty inodes.
  */
-void
+long
 xfs_reclaim_inodes_nr(
 	struct xfs_mount	*mp,
 	int			nr_to_scan)
@@ -1175,7 +1175,7 @@ xfs_reclaim_inodes_nr(
 	xfs_reclaim_work_queue(mp);
 	xfs_ail_push_all(mp->m_ail);
 
-	xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
+	return xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
 }
 
 /*
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index a01afbb..c31902f 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -31,7 +31,7 @@ void xfs_reclaim_worker(struct work_struct *work);
 
 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
 int xfs_reclaim_inodes_count(struct xfs_mount *mp);
-void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
+long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
 
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index d852a2b..bf89eb9 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1941,7 +1941,7 @@ xlog_print_tic_res(
 
 	xfs_alert_tag(mp, XFS_PTAG_LOGRES,
 		"xlog_write: reservation ran out. Need to up reservation");
-	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+	xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
 }
 
 /*
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 2b0ba35..a0fa802 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -336,14 +336,6 @@ xfs_mount_validate_sb(
 		return XFS_ERROR(EWRONGFS);
 	}
 
-	if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
-			(sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
-				XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
-		xfs_notice(mp,
-"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
-		return XFS_ERROR(EFSCORRUPTED);
-	}
-
 	/*
 	 * Version 5 superblock feature mask validation. Reject combinations the
 	 * kernel cannot support up front before checking anything else. For
@@ -387,6 +379,19 @@ xfs_mount_validate_sb(
 		}
 	}
 
+	if (xfs_sb_version_has_pquotino(sbp)) {
+		if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
+			xfs_notice(mp,
+			   "Version 5 of Super block has XFS_OQUOTA bits.\n");
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+	} else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
+				XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
+			xfs_notice(mp,
+"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n");
+			return XFS_ERROR(EFSCORRUPTED);
+	}
+
 	if (unlikely(
 	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
 		xfs_warn(mp,
@@ -572,6 +577,31 @@ out_unwind:
 static void
 xfs_sb_quota_from_disk(struct xfs_sb *sbp)
 {
+	/*
+	 * older mkfs doesn't initialize quota inodes to NULLFSINO. This
+	 * leads to in-core values having two different values for a quota
+	 * inode to be invalid: 0 and NULLFSINO. Change it to a single value
+	 * NULLFSINO.
+	 *
+	 * Note that this change affect only the in-core values. These
+	 * values are not written back to disk unless any quota information
+	 * is written to the disk. Even in that case, sb_pquotino field is
+	 * not written to disk unless the superblock supports pquotino.
+	 */
+	if (sbp->sb_uquotino == 0)
+		sbp->sb_uquotino = NULLFSINO;
+	if (sbp->sb_gquotino == 0)
+		sbp->sb_gquotino = NULLFSINO;
+	if (sbp->sb_pquotino == 0)
+		sbp->sb_pquotino = NULLFSINO;
+
+	/*
+	 * We need to do these manipilations only if we are working
+	 * with an older version of on-disk superblock.
+	 */
+	if (xfs_sb_version_has_pquotino(sbp))
+		return;
+
 	if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
 		sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
 					XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
@@ -579,6 +609,18 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
 		sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
 					XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
 	sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
+
+	if (sbp->sb_qflags & XFS_PQUOTA_ACCT)  {
+		/*
+		 * In older version of superblock, on-disk superblock only
+		 * has sb_gquotino, and in-core superblock has both sb_gquotino
+		 * and sb_pquotino. But, only one of them is supported at any
+		 * point of time. So, if PQUOTA is set in disk superblock,
+		 * copy over sb_gquotino to sb_pquotino.
+		 */
+		sbp->sb_pquotino = sbp->sb_gquotino;
+		sbp->sb_gquotino = NULLFSINO;
+	}
 }
 
 void
@@ -650,6 +692,13 @@ xfs_sb_quota_to_disk(
 {
 	__uint16_t	qflags = from->sb_qflags;
 
+	/*
+	 * We need to do these manipilations only if we are working
+	 * with an older version of on-disk superblock.
+	 */
+	if (xfs_sb_version_has_pquotino(from))
+		return;
+
 	if (*fields & XFS_SB_QFLAGS) {
 		/*
 		 * The in-core version of sb_qflags do not have
@@ -669,6 +718,21 @@ xfs_sb_quota_to_disk(
 		to->sb_qflags = cpu_to_be16(qflags);
 		*fields &= ~XFS_SB_QFLAGS;
 	}
+
+	/*
+	 * GQUOTINO and PQUOTINO cannot be used together in versions
+	 * of superblock that do not have pquotino. from->sb_flags
+	 * tells us which quota is active and should be copied to
+	 * disk.
+	 */
+	if ((*fields & XFS_SB_GQUOTINO) &&
+				(from->sb_qflags & XFS_GQUOTA_ACCT))
+		to->sb_gquotino = cpu_to_be64(from->sb_gquotino);
+	else if ((*fields & XFS_SB_PQUOTINO) &&
+				(from->sb_qflags & XFS_PQUOTA_ACCT))
+		to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
+
+	*fields &= ~(XFS_SB_PQUOTINO | XFS_SB_GQUOTINO);
 }
 
 /*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index d320794..60690c4 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -51,8 +51,9 @@
  */
 STATIC int	xfs_qm_init_quotainos(xfs_mount_t *);
 STATIC int	xfs_qm_init_quotainfo(xfs_mount_t *);
-STATIC int	xfs_qm_shake(struct shrinker *, struct shrink_control *);
 
+
+STATIC void	xfs_qm_dqfree_one(struct xfs_dquot *dqp);
 /*
  * We use the batch lookup interface to iterate over the dquots as it
  * currently is the only interface into the radix tree code that allows
@@ -203,12 +204,9 @@ xfs_qm_dqpurge(
 	 * We move dquots to the freelist as soon as their reference count
 	 * hits zero, so it really should be on the freelist here.
 	 */
-	mutex_lock(&qi->qi_lru_lock);
 	ASSERT(!list_empty(&dqp->q_lru));
-	list_del_init(&dqp->q_lru);
-	qi->qi_lru_count--;
+	list_lru_del(&qi->qi_lru, &dqp->q_lru);
 	XFS_STATS_DEC(xs_qm_dquot_unused);
-	mutex_unlock(&qi->qi_lru_lock);
 
 	xfs_qm_dqdestroy(dqp);
 
@@ -680,6 +678,143 @@ xfs_qm_calc_dquots_per_chunk(
 	return ndquots;
 }
 
+struct xfs_qm_isolate {
+	struct list_head	buffers;
+	struct list_head	dispose;
+};
+
+static enum lru_status
+xfs_qm_dquot_isolate(
+	struct list_head	*item,
+	spinlock_t		*lru_lock,
+	void			*arg)
+{
+	struct xfs_dquot	*dqp = container_of(item,
+						struct xfs_dquot, q_lru);
+	struct xfs_qm_isolate	*isol = arg;
+
+	if (!xfs_dqlock_nowait(dqp))
+		goto out_miss_busy;
+
+	/*
+	 * This dquot has acquired a reference in the meantime remove it from
+	 * the freelist and try again.
+	 */
+	if (dqp->q_nrefs) {
+		xfs_dqunlock(dqp);
+		XFS_STATS_INC(xs_qm_dqwants);
+
+		trace_xfs_dqreclaim_want(dqp);
+		list_del_init(&dqp->q_lru);
+		XFS_STATS_DEC(xs_qm_dquot_unused);
+		return LRU_REMOVED;
+	}
+
+	/*
+	 * If the dquot is dirty, flush it. If it's already being flushed, just
+	 * skip it so there is time for the IO to complete before we try to
+	 * reclaim it again on the next LRU pass.
+	 */
+	if (!xfs_dqflock_nowait(dqp)) {
+		xfs_dqunlock(dqp);
+		goto out_miss_busy;
+	}
+
+	if (XFS_DQ_IS_DIRTY(dqp)) {
+		struct xfs_buf	*bp = NULL;
+		int		error;
+
+		trace_xfs_dqreclaim_dirty(dqp);
+
+		/* we have to drop the LRU lock to flush the dquot */
+		spin_unlock(lru_lock);
+
+		error = xfs_qm_dqflush(dqp, &bp);
+		if (error) {
+			xfs_warn(dqp->q_mount, "%s: dquot %p flush failed",
+				 __func__, dqp);
+			goto out_unlock_dirty;
+		}
+
+		xfs_buf_delwri_queue(bp, &isol->buffers);
+		xfs_buf_relse(bp);
+		goto out_unlock_dirty;
+	}
+	xfs_dqfunlock(dqp);
+
+	/*
+	 * Prevent lookups now that we are past the point of no return.
+	 */
+	dqp->dq_flags |= XFS_DQ_FREEING;
+	xfs_dqunlock(dqp);
+
+	ASSERT(dqp->q_nrefs == 0);
+	list_move_tail(&dqp->q_lru, &isol->dispose);
+	XFS_STATS_DEC(xs_qm_dquot_unused);
+	trace_xfs_dqreclaim_done(dqp);
+	XFS_STATS_INC(xs_qm_dqreclaims);
+	return LRU_REMOVED;
+
+out_miss_busy:
+	trace_xfs_dqreclaim_busy(dqp);
+	XFS_STATS_INC(xs_qm_dqreclaim_misses);
+	return LRU_SKIP;
+
+out_unlock_dirty:
+	trace_xfs_dqreclaim_busy(dqp);
+	XFS_STATS_INC(xs_qm_dqreclaim_misses);
+	xfs_dqunlock(dqp);
+	spin_lock(lru_lock);
+	return LRU_RETRY;
+}
+
+static unsigned long
+xfs_qm_shrink_scan(
+	struct shrinker		*shrink,
+	struct shrink_control	*sc)
+{
+	struct xfs_quotainfo	*qi = container_of(shrink,
+					struct xfs_quotainfo, qi_shrinker);
+	struct xfs_qm_isolate	isol;
+	unsigned long		freed;
+	int			error;
+	unsigned long		nr_to_scan = sc->nr_to_scan;
+
+	if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
+		return 0;
+
+	INIT_LIST_HEAD(&isol.buffers);
+	INIT_LIST_HEAD(&isol.dispose);
+
+	freed = list_lru_walk_node(&qi->qi_lru, sc->nid, xfs_qm_dquot_isolate, &isol,
+					&nr_to_scan);
+
+	error = xfs_buf_delwri_submit(&isol.buffers);
+	if (error)
+		xfs_warn(NULL, "%s: dquot reclaim failed", __func__);
+
+	while (!list_empty(&isol.dispose)) {
+		struct xfs_dquot	*dqp;
+
+		dqp = list_first_entry(&isol.dispose, struct xfs_dquot, q_lru);
+		list_del_init(&dqp->q_lru);
+		xfs_qm_dqfree_one(dqp);
+	}
+
+	return freed;
+}
+
+static unsigned long
+xfs_qm_shrink_count(
+	struct shrinker		*shrink,
+	struct shrink_control	*sc)
+{
+	struct xfs_quotainfo	*qi = container_of(shrink,
+					struct xfs_quotainfo, qi_shrinker);
+
+	return list_lru_count_node(&qi->qi_lru, sc->nid);
+}
+
 /*
  * This initializes all the quota information that's kept in the
  * mount structure
@@ -696,11 +831,18 @@ xfs_qm_init_quotainfo(
 
 	qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
 
+	if ((error = list_lru_init(&qinf->qi_lru))) {
+		kmem_free(qinf);
+		mp->m_quotainfo = NULL;
+		return error;
+	}
+
 	/*
 	 * See if quotainodes are setup, and if not, allocate them,
 	 * and change the superblock accordingly.
 	 */
 	if ((error = xfs_qm_init_quotainos(mp))) {
+		list_lru_destroy(&qinf->qi_lru);
 		kmem_free(qinf);
 		mp->m_quotainfo = NULL;
 		return error;
@@ -711,10 +853,6 @@ xfs_qm_init_quotainfo(
 	INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS);
 	mutex_init(&qinf->qi_tree_lock);
 
-	INIT_LIST_HEAD(&qinf->qi_lru_list);
-	qinf->qi_lru_count = 0;
-	mutex_init(&qinf->qi_lru_lock);
-
 	/* mutex used to serialize quotaoffs */
 	mutex_init(&qinf->qi_quotaofflock);
 
@@ -779,8 +917,10 @@ xfs_qm_init_quotainfo(
 		qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
 	}
 
-	qinf->qi_shrinker.shrink = xfs_qm_shake;
+	qinf->qi_shrinker.count_objects = xfs_qm_shrink_count;
+	qinf->qi_shrinker.scan_objects = xfs_qm_shrink_scan;
 	qinf->qi_shrinker.seeks = DEFAULT_SEEKS;
+	qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE;
 	register_shrinker(&qinf->qi_shrinker);
 	return 0;
 }
@@ -801,6 +941,7 @@ xfs_qm_destroy_quotainfo(
 	ASSERT(qi != NULL);
 
 	unregister_shrinker(&qi->qi_shrinker);
+	list_lru_destroy(&qi->qi_lru);
 
 	if (qi->qi_uquotaip) {
 		IRELE(qi->qi_uquotaip);
@@ -834,6 +975,36 @@ xfs_qm_qino_alloc(
 	int		error;
 	int		committed;
 
+	*ip = NULL;
+	/*
+	 * With superblock that doesn't have separate pquotino, we
+	 * share an inode between gquota and pquota. If the on-disk
+	 * superblock has GQUOTA and the filesystem is now mounted
+	 * with PQUOTA, just use sb_gquotino for sb_pquotino and
+	 * vice-versa.
+	 */
+	if (!xfs_sb_version_has_pquotino(&mp->m_sb) &&
+			(flags & (XFS_QMOPT_PQUOTA|XFS_QMOPT_GQUOTA))) {
+		xfs_ino_t ino = NULLFSINO;
+
+		if ((flags & XFS_QMOPT_PQUOTA) &&
+			     (mp->m_sb.sb_gquotino != NULLFSINO)) {
+			ino = mp->m_sb.sb_gquotino;
+			ASSERT(mp->m_sb.sb_pquotino == NULLFSINO);
+		} else if ((flags & XFS_QMOPT_GQUOTA) &&
+			     (mp->m_sb.sb_pquotino != NULLFSINO)) {
+			ino = mp->m_sb.sb_pquotino;
+			ASSERT(mp->m_sb.sb_gquotino == NULLFSINO);
+		}
+		if (ino != NULLFSINO) {
+			error = xfs_iget(mp, NULL, ino, 0, 0, ip);
+			if (error)
+				return error;
+			mp->m_sb.sb_gquotino = NULLFSINO;
+			mp->m_sb.sb_pquotino = NULLFSINO;
+		}
+	}
+
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
 	if ((error = xfs_trans_reserve(tp,
 				      XFS_QM_QINOCREATE_SPACE_RES(mp),
@@ -844,11 +1015,14 @@ xfs_qm_qino_alloc(
 		return error;
 	}
 
-	error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
-	if (error) {
-		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
-				 XFS_TRANS_ABORT);
-		return error;
+	if (!*ip) {
+		error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip,
+								&committed);
+		if (error) {
+			xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
+					 XFS_TRANS_ABORT);
+			return error;
+		}
 	}
 
 	/*
@@ -860,21 +1034,25 @@ xfs_qm_qino_alloc(
 	if (flags & XFS_QMOPT_SBVERSION) {
 		ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
 		ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
-				   XFS_SB_GQUOTINO | XFS_SB_QFLAGS)) ==
-		       (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
-			XFS_SB_GQUOTINO | XFS_SB_QFLAGS));
+			XFS_SB_GQUOTINO | XFS_SB_PQUOTINO | XFS_SB_QFLAGS)) ==
+				(XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
+				 XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |
+				 XFS_SB_QFLAGS));
 
 		xfs_sb_version_addquota(&mp->m_sb);
 		mp->m_sb.sb_uquotino = NULLFSINO;
 		mp->m_sb.sb_gquotino = NULLFSINO;
+		mp->m_sb.sb_pquotino = NULLFSINO;
 
-		/* qflags will get updated _after_ quotacheck */
-		mp->m_sb.sb_qflags = 0;
+		/* qflags will get updated fully _after_ quotacheck */
+		mp->m_sb.sb_qflags = mp->m_qflags & XFS_ALL_QUOTA_ACCT;
 	}
 	if (flags & XFS_QMOPT_UQUOTA)
 		mp->m_sb.sb_uquotino = (*ip)->i_ino;
-	else
+	else if (flags & XFS_QMOPT_GQUOTA)
 		mp->m_sb.sb_gquotino = (*ip)->i_ino;
+	else
+		mp->m_sb.sb_pquotino = (*ip)->i_ino;
 	spin_unlock(&mp->m_sb_lock);
 	xfs_mod_sb(tp, sbfields);
 
@@ -1484,11 +1662,10 @@ xfs_qm_init_quotainos(
 			if (error)
 				goto error_rele;
 		}
-		/* XXX: Use gquotino for now */
 		if (XFS_IS_PQUOTA_ON(mp) &&
-		    mp->m_sb.sb_gquotino != NULLFSINO) {
-			ASSERT(mp->m_sb.sb_gquotino > 0);
-			error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
+		    mp->m_sb.sb_pquotino != NULLFSINO) {
+			ASSERT(mp->m_sb.sb_pquotino > 0);
+			error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
 					     0, 0, &pip);
 			if (error)
 				goto error_rele;
@@ -1496,7 +1673,8 @@ xfs_qm_init_quotainos(
 	} else {
 		flags |= XFS_QMOPT_SBVERSION;
 		sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
-			    XFS_SB_GQUOTINO | XFS_SB_QFLAGS);
+			    XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |
+			    XFS_SB_QFLAGS);
 	}
 
 	/*
@@ -1524,9 +1702,8 @@ xfs_qm_init_quotainos(
 		flags &= ~XFS_QMOPT_SBVERSION;
 	}
 	if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
-		/* XXX: Use XFS_SB_GQUOTINO for now */
 		error = xfs_qm_qino_alloc(mp, &pip,
-					  sbflags | XFS_SB_GQUOTINO,
+					  sbflags | XFS_SB_PQUOTINO,
 					  flags | XFS_QMOPT_PQUOTA);
 		if (error)
 			goto error_rele;
@@ -1565,132 +1742,6 @@ xfs_qm_dqfree_one(
 	xfs_qm_dqdestroy(dqp);
 }
 
-STATIC void
-xfs_qm_dqreclaim_one(
-	struct xfs_dquot	*dqp,
-	struct list_head	*buffer_list,
-	struct list_head	*dispose_list)
-{
-	struct xfs_mount	*mp = dqp->q_mount;
-	struct xfs_quotainfo	*qi = mp->m_quotainfo;
-	int			error;
-
-	if (!xfs_dqlock_nowait(dqp))
-		goto out_move_tail;
-
-	/*
-	 * This dquot has acquired a reference in the meantime remove it from
-	 * the freelist and try again.
-	 */
-	if (dqp->q_nrefs) {
-		xfs_dqunlock(dqp);
-
-		trace_xfs_dqreclaim_want(dqp);
-		XFS_STATS_INC(xs_qm_dqwants);
-
-		list_del_init(&dqp->q_lru);
-		qi->qi_lru_count--;
-		XFS_STATS_DEC(xs_qm_dquot_unused);
-		return;
-	}
-
-	/*
-	 * Try to grab the flush lock. If this dquot is in the process of
-	 * getting flushed to disk, we don't want to reclaim it.
-	 */
-	if (!xfs_dqflock_nowait(dqp))
-		goto out_unlock_move_tail;
-
-	if (XFS_DQ_IS_DIRTY(dqp)) {
-		struct xfs_buf	*bp = NULL;
-
-		trace_xfs_dqreclaim_dirty(dqp);
-
-		error = xfs_qm_dqflush(dqp, &bp);
-		if (error) {
-			xfs_warn(mp, "%s: dquot %p flush failed",
-				 __func__, dqp);
-			goto out_unlock_move_tail;
-		}
-
-		xfs_buf_delwri_queue(bp, buffer_list);
-		xfs_buf_relse(bp);
-		/*
-		 * Give the dquot another try on the freelist, as the
-		 * flushing will take some time.
-		 */
-		goto out_unlock_move_tail;
-	}
-	xfs_dqfunlock(dqp);
-
-	/*
-	 * Prevent lookups now that we are past the point of no return.
-	 */
-	dqp->dq_flags |= XFS_DQ_FREEING;
-	xfs_dqunlock(dqp);
-
-	ASSERT(dqp->q_nrefs == 0);
-	list_move_tail(&dqp->q_lru, dispose_list);
-	qi->qi_lru_count--;
-	XFS_STATS_DEC(xs_qm_dquot_unused);
-
-	trace_xfs_dqreclaim_done(dqp);
-	XFS_STATS_INC(xs_qm_dqreclaims);
-	return;
-
-	/*
-	 * Move the dquot to the tail of the list so that we don't spin on it.
-	 */
-out_unlock_move_tail:
-	xfs_dqunlock(dqp);
-out_move_tail:
-	list_move_tail(&dqp->q_lru, &qi->qi_lru_list);
-	trace_xfs_dqreclaim_busy(dqp);
-	XFS_STATS_INC(xs_qm_dqreclaim_misses);
-}
-
-STATIC int
-xfs_qm_shake(
-	struct shrinker		*shrink,
-	struct shrink_control	*sc)
-{
-	struct xfs_quotainfo	*qi =
-		container_of(shrink, struct xfs_quotainfo, qi_shrinker);
-	int			nr_to_scan = sc->nr_to_scan;
-	LIST_HEAD		(buffer_list);
-	LIST_HEAD		(dispose_list);
-	struct xfs_dquot	*dqp;
-	int			error;
-
-	if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
-		return 0;
-	if (!nr_to_scan)
-		goto out;
-
-	mutex_lock(&qi->qi_lru_lock);
-	while (!list_empty(&qi->qi_lru_list)) {
-		if (nr_to_scan-- <= 0)
-			break;
-		dqp = list_first_entry(&qi->qi_lru_list, struct xfs_dquot,
-				       q_lru);
-		xfs_qm_dqreclaim_one(dqp, &buffer_list, &dispose_list);
-	}
-	mutex_unlock(&qi->qi_lru_lock);
-
-	error = xfs_buf_delwri_submit(&buffer_list);
-	if (error)
-		xfs_warn(NULL, "%s: dquot reclaim failed", __func__);
-
-	while (!list_empty(&dispose_list)) {
-		dqp = list_first_entry(&dispose_list, struct xfs_dquot, q_lru);
-		list_del_init(&dqp->q_lru);
-		xfs_qm_dqfree_one(dqp);
-	}
-
-out:
-	return (qi->qi_lru_count / 100) * sysctl_vfs_cache_pressure;
-}
-
 /*
  * Start a transaction and write the incore superblock changes to
  * disk. flags parameter indicates which fields have changed.
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 579d6a0..b822236 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -49,9 +49,7 @@ typedef struct xfs_quotainfo {
 	struct xfs_inode	*qi_uquotaip;	/* user quota inode */
 	struct xfs_inode	*qi_gquotaip;	/* group quota inode */
 	struct xfs_inode	*qi_pquotaip;	/* project quota inode */
-	struct list_head qi_lru_list;
-	struct mutex	 qi_lru_lock;
-	int		 qi_lru_count;
+	struct list_lru	 qi_lru;
 	int		 qi_dquots;
 	time_t		 qi_btimelimit;	 /* limit for blks timer */
 	time_t		 qi_itimelimit;	 /* limit for inodes timer */
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index e4f8b2d..8d9e4c7 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -296,8 +296,10 @@ xfs_qm_scall_trunc_qfiles(
 
 	if (flags & XFS_DQ_USER)
 		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
-	if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ))
+	if (flags & XFS_DQ_GROUP)
 		error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
+	if (flags & XFS_DQ_PROJ)
+		error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
 
 	return error ? error : error2;
 }
@@ -413,8 +415,10 @@ xfs_qm_scall_getqstat(
 	struct xfs_quotainfo	*q = mp->m_quotainfo;
 	struct xfs_inode	*uip = NULL;
 	struct xfs_inode	*gip = NULL;
+	struct xfs_inode	*pip = NULL;
 	bool                    tempuqip = false;
 	bool                    tempgqip = false;
+	bool                    temppqip = false;
 
 	memset(out, 0, sizeof(fs_quota_stat_t));
 
@@ -424,16 +428,14 @@ xfs_qm_scall_getqstat(
 		out->qs_gquota.qfs_ino = NULLFSINO;
 		return (0);
 	}
+
 	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
 							(XFS_ALL_QUOTA_ACCT|
 							 XFS_ALL_QUOTA_ENFD));
-	out->qs_pad = 0;
-	out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
-	out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
-
 	if (q) {
 		uip = q->qi_uquotaip;
 		gip = q->qi_gquotaip;
+		pip = q->qi_pquotaip;
 	}
 	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
 		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
@@ -445,18 +447,41 @@ xfs_qm_scall_getqstat(
 					0, 0, &gip) == 0)
 			tempgqip = true;
 	}
+	/*
+	 * Q_XGETQSTAT doesn't have room for both group and project quotas.
+	 * So, allow the project quota values to be copied out only if
+	 * there is no group quota information available.
+	 */
+	if (!gip) {
+		if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
+			if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
+						0, 0, &pip) == 0)
+				temppqip = true;
+		}
+	} else
+		pip = NULL;
 	if (uip) {
+		out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
 		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
 		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
 		if (tempuqip)
 			IRELE(uip);
 	}
+
 	if (gip) {
+		out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
 		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
 		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
 		if (tempgqip)
 			IRELE(gip);
 	}
+	if (pip) {
+		out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
+		out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
+		out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
+		if (temppqip)
+			IRELE(pip);
+	}
 	if (q) {
 		out->qs_incoredqs = q->qi_dquots;
 		out->qs_btimelimit = q->qi_btimelimit;
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 78f9e70..a6ff9d6 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -618,16 +618,23 @@ xfs_sb_has_incompat_log_feature(
 	return (sbp->sb_features_log_incompat & feature) != 0;
 }
 
-static inline bool
-xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
+static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp)
 {
-	return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino);
+	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
 }
 
 /*
  * end of superblock version macros
  */
 
+static inline bool
+xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
+{
+	return (ino == sbp->sb_uquotino ||
+		ino == sbp->sb_gquotino ||
+		ino == sbp->sb_pquotino);
+}
+
 #define XFS_SB_DADDR		((xfs_daddr_t)0) /* daddr in filesystem/ag */
 #define	XFS_SB_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
 #define XFS_BUF_TO_SBP(bp)	((xfs_dsb_t *)((bp)->b_addr))
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 1d68ffc..f51fb7b 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -421,12 +421,6 @@ xfs_parseargs(
 	}
 #endif
 
-	if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
-	    (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) {
-		xfs_warn(mp, "cannot mount with both project and group quota");
-		return EINVAL;
-	}
-
 	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
 		xfs_warn(mp, "sunit and swidth must be specified together");
 		return EINVAL;
@@ -556,14 +550,13 @@ xfs_showargs(
 	else if (mp->m_qflags & XFS_UQUOTA_ACCT)
 		seq_puts(m, "," MNTOPT_UQUOTANOENF);
 
-	/* Either project or group quotas can be active, not both */
-
 	if (mp->m_qflags & XFS_PQUOTA_ACCT) {
 		if (mp->m_qflags & XFS_PQUOTA_ENFD)
 			seq_puts(m, "," MNTOPT_PRJQUOTA);
 		else
 			seq_puts(m, "," MNTOPT_PQUOTANOENF);
-	} else if (mp->m_qflags & XFS_GQUOTA_ACCT) {
+	}
+	if (mp->m_qflags & XFS_GQUOTA_ACCT) {
 		if (mp->m_qflags & XFS_GQUOTA_ENFD)
 			seq_puts(m, "," MNTOPT_GRPQUOTA);
 		else
@@ -870,17 +863,17 @@ xfs_init_mount_workqueues(
 		goto out_destroy_unwritten;
 
 	mp->m_reclaim_workqueue = alloc_workqueue("xfs-reclaim/%s",
-			WQ_NON_REENTRANT, 0, mp->m_fsname);
+			0, 0, mp->m_fsname);
 	if (!mp->m_reclaim_workqueue)
 		goto out_destroy_cil;
 
 	mp->m_log_workqueue = alloc_workqueue("xfs-log/%s",
-			WQ_NON_REENTRANT, 0, mp->m_fsname);
+			0, 0, mp->m_fsname);
 	if (!mp->m_log_workqueue)
 		goto out_destroy_reclaim;
 
 	mp->m_eofblocks_workqueue = alloc_workqueue("xfs-eofblocks/%s",
-			WQ_NON_REENTRANT, 0, mp->m_fsname);
+			0, 0, mp->m_fsname);
 	if (!mp->m_eofblocks_workqueue)
 		goto out_destroy_log;
 
@@ -1396,6 +1389,14 @@ xfs_finish_flags(
 		return XFS_ERROR(EROFS);
 	}
 
+	if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
+	    (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
+	    !xfs_sb_version_has_pquotino(&mp->m_sb)) {
+		xfs_warn(mp,
+		  "Super block does not support project and group quota together");
+		return XFS_ERROR(EINVAL);
+	}
+
 	return 0;
 }
 
@@ -1534,19 +1535,21 @@ xfs_fs_mount(
 	return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
 }
 
-static int
+static long
 xfs_fs_nr_cached_objects(
-	struct super_block	*sb)
+	struct super_block	*sb,
+	int			nid)
 {
 	return xfs_reclaim_inodes_count(XFS_M(sb));
 }
 
-static void
+static long
 xfs_fs_free_cached_objects(
 	struct super_block	*sb,
-	int			nr_to_scan)
+	long			nr_to_scan,
+	int			nid)
 {
-	xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan);
+	return xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan);
 }
 
 static const struct super_operations xfs_super_operations = {
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 56e6b68..22650cd 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -56,6 +56,16 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
 
 acpi_status
 acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld);
+
+bool acpi_has_method(acpi_handle handle, char *name);
+acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
+				       u64 arg);
+acpi_status acpi_evaluate_ej0(acpi_handle handle);
+acpi_status acpi_evaluate_lck(acpi_handle handle, int lock);
+bool acpi_ata_match(acpi_handle handle);
+bool acpi_bay_match(acpi_handle handle);
+bool acpi_dock_match(acpi_handle handle);
+
 #ifdef CONFIG_ACPI
 
 #include <linux/proc_fs.h>
@@ -274,15 +284,12 @@ struct acpi_device_wakeup {
 };
 
 struct acpi_device_physical_node {
-	u8 node_id;
+	unsigned int node_id;
 	struct list_head node;
 	struct device *dev;
 	bool put_online:1;
 };
 
-/* set maximum of physical nodes to 32 for expansibility */
-#define ACPI_MAX_PHYSICAL_NODE	32
-
 /* Device */
 struct acpi_device {
 	int device_type;
@@ -302,10 +309,9 @@ struct acpi_device {
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
-	u8 physical_node_count;
+	unsigned int physical_node_count;
 	struct list_head physical_node_list;
 	struct mutex physical_node_lock;
-	DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
 	struct list_head power_dependent;
 	void (*remove)(struct acpi_device *);
 };
@@ -356,14 +362,11 @@ extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
 
-extern int register_acpi_bus_notifier(struct notifier_block *nb);
-extern void unregister_acpi_bus_notifier(struct notifier_block *nb);
 /*
  * External Functions
  */
 
 int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
-void acpi_bus_data_handler(acpi_handle handle, void *context);
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
 				       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
@@ -383,15 +386,6 @@ bool acpi_bus_can_wakeup(acpi_handle handle);
 static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
 #endif
 
-#ifdef CONFIG_ACPI_PROC_EVENT
-int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);
-int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data);
-int acpi_bus_receive_event(struct acpi_bus_event *event);
-#else
-static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
-	{ return 0; }
-#endif
-
 void acpi_scan_lock_acquire(void);
 void acpi_scan_lock_release(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
@@ -445,7 +439,11 @@ struct acpi_pci_root {
 };
 
 /* helper */
-acpi_handle acpi_get_child(acpi_handle, u64);
+acpi_handle acpi_find_child(acpi_handle, u64, bool);
+static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr)
+{
+	return acpi_find_child(handle, addr, false);
+}
 int acpi_is_root_bridge(acpi_handle);
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
@@ -478,7 +476,8 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
 	if (p)
 		*p = ACPI_STATE_D0;
 
-	return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0;
+	return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
+		m : ACPI_STATE_D0;
 }
 static inline void acpi_dev_pm_add_dependent(acpi_handle handle,
 					     struct device *depdev) {}
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index b420939..1cedfcb 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -113,14 +113,13 @@ void pci_acpi_crs_quirks(void);
                                   Dock Station
   -------------------------------------------------------------------------- */
 struct acpi_dock_ops {
+	acpi_notify_handler fixup;
 	acpi_notify_handler handler;
 	acpi_notify_handler uevent;
 };
 
-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+#ifdef CONFIG_ACPI_DOCK
 extern int is_dock_device(acpi_handle handle);
-extern int register_dock_notifier(struct notifier_block *nb);
-extern void unregister_dock_notifier(struct notifier_block *nb);
 extern int register_hotplug_dock_device(acpi_handle handle,
 					const struct acpi_dock_ops *ops,
 					void *context,
@@ -132,13 +131,6 @@ static inline int is_dock_device(acpi_handle handle)
 {
 	return 0;
 }
-static inline int register_dock_notifier(struct notifier_block *nb)
-{
-	return -ENODEV;
-}
-static inline void unregister_dock_notifier(struct notifier_block *nb)
-{
-}
 static inline int register_hotplug_dock_device(acpi_handle handle,
 					       const struct acpi_dock_ops *ops,
 					       void *context,
@@ -150,6 +142,6 @@ static inline int register_hotplug_dock_device(acpi_handle handle,
 static inline void unregister_hotplug_dock_device(acpi_handle handle)
 {
 }
-#endif
+#endif /* CONFIG_ACPI_DOCK */
 
 #endif /*__ACPI_DRIVERS_H__*/
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 22d497e..0dd03f2 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20130517
+#define ACPI_CA_VERSION                 0x20130626
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -147,6 +147,8 @@ acpi_status acpi_install_interface(acpi_string interface_name);
 
 acpi_status acpi_remove_interface(acpi_string interface_name);
 
+acpi_status acpi_update_interfaces(u8 action);
+
 u32
 acpi_check_address_range(acpi_adr_space_type space_id,
 			 acpi_physical_address address,
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 22b03c9..eae55fb 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -668,13 +668,6 @@ typedef u32 acpi_event_status;
 #define ACPI_EVENT_FLAG_SET             (acpi_event_status) 0x04
 #define ACPI_EVENT_FLAG_HANDLE		(acpi_event_status) 0x08
 
-/*
- * General Purpose Events (GPE)
- */
-#define ACPI_GPE_INVALID                0xFF
-#define ACPI_GPE_MAX                    0xFF
-#define ACPI_NUM_GPE                    256
-
 /* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */
 
 #define ACPI_GPE_ENABLE                 0
@@ -1159,4 +1152,18 @@ struct acpi_memory_list {
 #define ACPI_OSI_WIN_7                  0x0B
 #define ACPI_OSI_WIN_8                  0x0C
 
+/* _OSI update actions */
+
+#define ACPI_VENDOR_STRINGS                 0x01
+#define ACPI_FEATURE_STRINGS                0x02
+#define ACPI_ENABLE_INTERFACES              0x00
+#define ACPI_DISABLE_INTERFACES             0x04
+
+#define ACPI_DISABLE_ALL_VENDOR_STRINGS     (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS)
+#define ACPI_DISABLE_ALL_FEATURE_STRINGS    (ACPI_DISABLE_INTERFACES | ACPI_FEATURE_STRINGS)
+#define ACPI_DISABLE_ALL_STRINGS            (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS)
+#define ACPI_ENABLE_ALL_VENDOR_STRINGS      (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS)
+#define ACPI_ENABLE_ALL_FEATURE_STRINGS     (ACPI_ENABLE_INTERFACES | ACPI_FEATURE_STRINGS)
+#define ACPI_ENABLE_ALL_STRINGS             (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS)
+
 #endif				/* __ACTYPES_H__ */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 2f47ade..0807ddf 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -417,6 +417,36 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd)
 {
 	return pmd;
 }
+
+static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
+{
+	return pte;
+}
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+	return 0;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+	return pte;
+}
+
+static inline pte_t pte_file_clear_soft_dirty(pte_t pte)
+{
+       return pte;
+}
+
+static inline pte_t pte_file_mksoft_dirty(pte_t pte)
+{
+       return pte;
+}
+
+static inline int pte_file_soft_dirty(pte_t pte)
+{
+       return 0;
+}
 #endif
 
 #ifndef __HAVE_PFNMAP_TRACKING
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 12083dc..3ecdde6 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -62,15 +62,14 @@
 #endif
 #include <asm/mman.h>
 #include <asm/uaccess.h>
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
 #include <linux/types.h>
 #include <linux/agp_backend.h>
-#endif
 #include <linux/workqueue.h>
 #include <linux/poll.h>
 #include <asm/pgalloc.h>
 #include <drm/drm.h>
 #include <drm/drm_sarea.h>
+#include <drm/drm_vma_manager.h>
 
 #include <linux/idr.h>
 
@@ -587,7 +586,6 @@ struct drm_map_list {
 	struct drm_local_map *map;	/**< mapping */
 	uint64_t user_token;
 	struct drm_master *master;
-	struct drm_mm_node *file_offset_node;	/**< fake offset */
 };
 
 /**
@@ -622,8 +620,7 @@ struct drm_ati_pcigart_info {
  * GEM specific mm private for tracking GEM objects
  */
 struct drm_gem_mm {
-	struct drm_mm offset_manager;	/**< Offset mgmt for buffer objects */
-	struct drm_open_hash offset_hash; /**< User token hash table for maps */
+	struct drm_vma_offset_manager vma_manager;
 };
 
 /**
@@ -644,7 +641,7 @@ struct drm_gem_object {
 	struct file *filp;
 
 	/* Mapping info for this object */
-	struct drm_map_list map_list;
+	struct drm_vma_offset_node vma_node;
 
 	/**
 	 * Size of the object, in bytes.  Immutable over the object's
@@ -737,6 +734,7 @@ struct drm_bus {
 	int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p);
 	/* hooks that are for PCI */
 	int (*agp_init)(struct drm_device *dev);
+	void (*agp_destroy)(struct drm_device *dev);
 
 };
 
@@ -966,7 +964,7 @@ struct drm_driver {
 
 	u32 driver_features;
 	int dev_priv_size;
-	struct drm_ioctl_desc *ioctls;
+	const struct drm_ioctl_desc *ioctls;
 	int num_ioctls;
 	const struct file_operations *fops;
 	union {
@@ -1131,12 +1129,7 @@ struct drm_device {
 	/*@{ */
 	int irq_enabled;		/**< True if irq handler is enabled */
 	__volatile__ long context_flag;	/**< Context swapping flag */
-	__volatile__ long interrupt_flag; /**< Interruption handler flag */
-	__volatile__ long dma_flag;	/**< DMA dispatch flag */
-	wait_queue_head_t context_wait;	/**< Processes waiting on ctx switch */
-	int last_checked;		/**< Last context checked for DMA */
 	int last_context;		/**< Last current context */
-	unsigned long last_switch;	/**< jiffies at last context switch */
 	/*@} */
 
 	struct work_struct work;
@@ -1174,12 +1167,8 @@ struct drm_device {
 	spinlock_t event_lock;
 
 	/*@} */
-	cycles_t ctx_start;
-	cycles_t lck_start;
 
 	struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
-	wait_queue_head_t buf_readers;	/**< Processes waiting to read */
-	wait_queue_head_t buf_writers;	/**< Processes waiting to ctx switch */
 
 	struct drm_agp_head *agp;	/**< AGP data */
 
@@ -1235,16 +1224,6 @@ static inline int drm_dev_to_irq(struct drm_device *dev)
 	return dev->driver->bus->get_irq(dev);
 }
 
-
-#if __OS_HAS_AGP
-static inline int drm_core_has_AGP(struct drm_device *dev)
-{
-	return drm_core_check_feature(dev, DRIVER_USE_AGP);
-}
-#else
-#define drm_core_has_AGP(dev) (0)
-#endif
-
 #if __OS_HAS_MTRR
 static inline int drm_core_has_MTRR(struct drm_device *dev)
 {
@@ -1301,14 +1280,6 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
 
 				/* Memory management support (drm_memory.h) */
 #include <drm/drm_memory.h>
-extern void drm_free_agp(DRM_AGP_MEM * handle, int pages);
-extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
-				       struct page **pages,
-				       unsigned long num_pages,
-				       uint32_t gtt_offset,
-				       uint32_t type);
-extern int drm_unbind_agp(DRM_AGP_MEM * handle);
 
 				/* Misc. IOCTL support (drm_ioctl.h) */
 extern int drm_irq_by_busid(struct drm_device *dev, void *data,
@@ -1335,8 +1306,6 @@ extern int drm_resctx(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv);
 extern int drm_addctx(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv);
-extern int drm_modctx(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv);
 extern int drm_getctx(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv);
 extern int drm_switchctx(struct drm_device *dev, void *data,
@@ -1405,7 +1374,6 @@ extern int drm_freebufs(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 extern int drm_mapbufs(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv);
-extern int drm_order(unsigned long size);
 
 				/* DMA support (drm_dma.h) */
 extern int drm_dma_setup(struct drm_device *dev);
@@ -1465,31 +1433,8 @@ extern int drm_modeset_ctl(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
 
 				/* AGP/GART support (drm_agpsupport.h) */
-extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
-extern int drm_agp_acquire(struct drm_device *dev);
-extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
-				 struct drm_file *file_priv);
-extern int drm_agp_release(struct drm_device *dev);
-extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
-				 struct drm_file *file_priv);
-extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
-extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
-				struct drm_file *file_priv);
-extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
-extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv);
-extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
-extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv);
-extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
-extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv);
-extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
-extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv);
-extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
-extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv);
+
+#include <drm/drm_agpsupport.h>
 
 				/* Stub support (drm_stub.h) */
 extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
@@ -1561,6 +1506,9 @@ extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **
 extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages);
 extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
 
+int drm_gem_dumb_destroy(struct drm_file *file,
+			 struct drm_device *dev,
+			 uint32_t handle);
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
@@ -1577,9 +1525,8 @@ extern int drm_vma_info(struct seq_file *m, void *data);
 
 				/* Scatter Gather Support (drm_scatter.h) */
 extern void drm_sg_cleanup(struct drm_sg_mem * entry);
-extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+extern int drm_sg_alloc(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
-extern int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
 extern int drm_sg_free(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv);
 
@@ -1613,8 +1560,8 @@ struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
 					    size_t size);
 int drm_gem_object_init(struct drm_device *dev,
 			struct drm_gem_object *obj, size_t size);
-int drm_gem_private_object_init(struct drm_device *dev,
-			struct drm_gem_object *obj, size_t size);
+void drm_gem_private_object_init(struct drm_device *dev,
+				 struct drm_gem_object *obj, size_t size);
 void drm_gem_object_handle_free(struct drm_gem_object *obj);
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
@@ -1640,10 +1587,12 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
 static inline void
 drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
 {
-	if (obj != NULL) {
+	if (obj && !atomic_add_unless(&obj->refcount.refcount, -1, 1)) {
 		struct drm_device *dev = obj->dev;
+
 		mutex_lock(&dev->struct_mutex);
-		kref_put(&obj->refcount, drm_gem_object_free);
+		if (likely(atomic_dec_and_test(&obj->refcount.refcount)))
+			drm_gem_object_free(&obj->refcount);
 		mutex_unlock(&dev->struct_mutex);
 	}
 }
@@ -1661,24 +1610,6 @@ drm_gem_object_handle_reference(struct drm_gem_object *obj)
 }
 
 static inline void
-drm_gem_object_handle_unreference(struct drm_gem_object *obj)
-{
-	if (obj == NULL)
-		return;
-
-	if (atomic_read(&obj->handle_count) == 0)
-		return;
-	/*
-	 * Must bump handle count first as this may be the last
-	 * ref, in which case the object would disappear before we
-	 * checked for a name
-	 */
-	if (atomic_dec_and_test(&obj->handle_count))
-		drm_gem_object_handle_free(obj);
-	drm_gem_object_unreference(obj);
-}
-
-static inline void
 drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
 {
 	if (obj == NULL)
diff --git a/include/drm/drm_agpsupport.h b/include/drm/drm_agpsupport.h
new file mode 100644
index 0000000..a184eee
--- /dev/null
+++ b/include/drm/drm_agpsupport.h
@@ -0,0 +1,194 @@
+#ifndef _DRM_AGPSUPPORT_H_
+#define _DRM_AGPSUPPORT_H_
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/agp_backend.h>
+#include <drm/drmP.h>
+
+#if __OS_HAS_AGP
+
+void drm_free_agp(DRM_AGP_MEM * handle, int pages);
+int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+int drm_unbind_agp(DRM_AGP_MEM * handle);
+DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+				struct page **pages,
+				unsigned long num_pages,
+				uint32_t gtt_offset,
+				uint32_t type);
+
+struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+void drm_agp_destroy(struct drm_agp_head *agp);
+void drm_agp_clear(struct drm_device *dev);
+int drm_agp_acquire(struct drm_device *dev);
+int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int drm_agp_release(struct drm_device *dev);
+int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
+int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
+int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
+int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
+int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
+int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
+int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+
+static inline int drm_core_has_AGP(struct drm_device *dev)
+{
+	return drm_core_check_feature(dev, DRIVER_USE_AGP);
+}
+
+#else /* __OS_HAS_AGP */
+
+static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages)
+{
+}
+
+static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+{
+	return -ENODEV;
+}
+
+static inline int drm_unbind_agp(DRM_AGP_MEM * handle)
+{
+	return -ENODEV;
+}
+
+static inline DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+					      struct page **pages,
+					      unsigned long num_pages,
+					      uint32_t gtt_offset,
+					      uint32_t type)
+{
+	return NULL;
+}
+
+static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev)
+{
+	return NULL;
+}
+
+static inline void drm_agp_destroy(struct drm_agp_head *agp)
+{
+}
+
+static inline void drm_agp_clear(struct drm_device *dev)
+{
+}
+
+static inline int drm_agp_acquire(struct drm_device *dev)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_release(struct drm_device *dev)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_enable(struct drm_device *dev,
+				 struct drm_agp_mode mode)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+				       struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_info(struct drm_device *dev,
+			       struct drm_agp_info *info)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_alloc(struct drm_device *dev,
+				struct drm_agp_buffer *request)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+				      struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_free(struct drm_device *dev,
+			       struct drm_agp_buffer *request)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_unbind(struct drm_device *dev,
+				 struct drm_agp_binding *request)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+				       struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_bind(struct drm_device *dev,
+			       struct drm_agp_binding *request)
+{
+	return -ENODEV;
+}
+
+static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv)
+{
+	return -ENODEV;
+}
+
+static inline int drm_core_has_AGP(struct drm_device *dev)
+{
+	return 0;
+}
+
+#endif /* __OS_HAS_AGP */
+
+#endif /* _DRM_AGPSUPPORT_H_ */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index e8e1417..ae8dbfb 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -342,13 +342,42 @@ u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
 u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
 					  int lane);
 
-#define DP_RECEIVER_CAP_SIZE	0xf
+#define DP_RECEIVER_CAP_SIZE		0xf
+#define EDP_PSR_RECEIVER_CAP_SIZE	2
+
 void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
 void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate);
 int drm_dp_bw_code_to_link_rate(u8 link_bw);
 
+struct edp_sdp_header {
+	u8 HB0; /* Secondary Data Packet ID */
+	u8 HB1; /* Secondary Data Packet Type */
+	u8 HB2; /* 7:5 reserved, 4:0 revision number */
+	u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
+} __packed;
+
+#define EDP_SDP_HEADER_REVISION_MASK		0x1F
+#define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES	0x1F
+
+struct edp_vsc_psr {
+	struct edp_sdp_header sdp_header;
+	u8 DB0; /* Stereo Interface */
+	u8 DB1; /* 0 - PSR State; 1 - Update RFB; 2 - CRC Valid */
+	u8 DB2; /* CRC value bits 7:0 of the R or Cr component */
+	u8 DB3; /* CRC value bits 15:8 of the R or Cr component */
+	u8 DB4; /* CRC value bits 7:0 of the G or Y component */
+	u8 DB5; /* CRC value bits 15:8 of the G or Y component */
+	u8 DB6; /* CRC value bits 7:0 of the B or Cb component */
+	u8 DB7; /* CRC value bits 15:8 of the B or Cb component */
+	u8 DB8_31[24]; /* Reserved */
+} __packed;
+
+#define EDP_VSC_PSR_STATE_ACTIVE	(1<<0)
+#define EDP_VSC_PSR_UPDATE_RFB		(1<<1)
+#define EDP_VSC_PSR_CRC_VALUES_VALID	(1<<2)
+
 static inline int
 drm_dp_max_link_rate(u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index c34f27f..89b4d7d 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -30,14 +30,6 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
 /* set vm_flags and we can change the vm attribute to other one at here. */
 int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma);
 
-/*
- * destroy memory region allocated.
- *	- a gem handle and physical memory region pointed by a gem object
- *	would be released by drm_gem_handle_delete().
- */
-int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
-		struct drm_device *drm, unsigned int handle);
-
 /* allocate physical memory. */
 struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
 		unsigned int size);
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 4d06edb..cba6786 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -36,11 +36,19 @@
 /*
  * Generic range manager structs
  */
+#include <linux/bug.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/spinlock.h>
 #ifdef CONFIG_DEBUG_FS
 #include <linux/seq_file.h>
 #endif
 
+enum drm_mm_search_flags {
+	DRM_MM_SEARCH_DEFAULT =		0,
+	DRM_MM_SEARCH_BEST =		1 << 0,
+};
+
 struct drm_mm_node {
 	struct list_head node_list;
 	struct list_head hole_stack;
@@ -62,9 +70,6 @@ struct drm_mm {
 	/* head_node.node_list is the list of all memory nodes, ordered
 	 * according to the (increasing) start address of the memory node. */
 	struct drm_mm_node head_node;
-	struct list_head unused_nodes;
-	int num_unused;
-	spinlock_t unused_lock;
 	unsigned int scan_check_range : 1;
 	unsigned scan_alignment;
 	unsigned long scan_color;
@@ -115,13 +120,6 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
 #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
 						&(mm)->head_node.node_list, \
 						node_list)
-#define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \
-	for (entry = (mm)->prev_scanned_node, \
-		next = entry ? list_entry(entry->node_list.next, \
-			struct drm_mm_node, node_list) : NULL; \
-	     entry != NULL; entry = next, \
-		next = entry ? list_entry(entry->node_list.next, \
-			struct drm_mm_node, node_list) : NULL) \
 
 /* Note that we need to unroll list_for_each_entry in order to inline
  * setting hole_start and hole_end on each iteration and keep the
@@ -138,124 +136,50 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
 /*
  * Basic range manager support (drm_mm.c)
  */
-extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
-					       unsigned long start,
-					       unsigned long size,
-					       bool atomic);
-extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
-						    unsigned long size,
-						    unsigned alignment,
-						    unsigned long color,
-						    int atomic);
-extern struct drm_mm_node *drm_mm_get_block_range_generic(
-						struct drm_mm_node *node,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long color,
-						unsigned long start,
-						unsigned long end,
-						int atomic);
-static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
-						   unsigned long size,
-						   unsigned alignment)
-{
-	return drm_mm_get_block_generic(parent, size, alignment, 0, 0);
-}
-static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
-							  unsigned long size,
-							  unsigned alignment)
-{
-	return drm_mm_get_block_generic(parent, size, alignment, 0, 1);
-}
-static inline struct drm_mm_node *drm_mm_get_block_range(
-						struct drm_mm_node *parent,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long start,
-						unsigned long end)
-{
-	return drm_mm_get_block_range_generic(parent, size, alignment, 0,
-					      start, end, 0);
-}
-static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
-						struct drm_mm_node *parent,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long start,
-						unsigned long end)
-{
-	return drm_mm_get_block_range_generic(parent, size, alignment, 0,
-						start, end, 1);
-}
+extern int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node);
 
-extern int drm_mm_insert_node(struct drm_mm *mm,
-			      struct drm_mm_node *node,
-			      unsigned long size,
-			      unsigned alignment);
-extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
-				       struct drm_mm_node *node,
-				       unsigned long size,
-				       unsigned alignment,
-				       unsigned long start,
-				       unsigned long end);
 extern int drm_mm_insert_node_generic(struct drm_mm *mm,
 				      struct drm_mm_node *node,
 				      unsigned long size,
 				      unsigned alignment,
-				      unsigned long color);
+				      unsigned long color,
+				      enum drm_mm_search_flags flags);
+static inline int drm_mm_insert_node(struct drm_mm *mm,
+				     struct drm_mm_node *node,
+				     unsigned long size,
+				     unsigned alignment,
+				     enum drm_mm_search_flags flags)
+{
+	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags);
+}
+
 extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
 				       struct drm_mm_node *node,
 				       unsigned long size,
 				       unsigned alignment,
 				       unsigned long color,
 				       unsigned long start,
-				       unsigned long end);
-extern void drm_mm_put_block(struct drm_mm_node *cur);
-extern void drm_mm_remove_node(struct drm_mm_node *node);
-extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
-extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
-						      unsigned long size,
-						      unsigned alignment,
-						      unsigned long color,
-						      bool best_match);
-extern struct drm_mm_node *drm_mm_search_free_in_range_generic(
-						const struct drm_mm *mm,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long color,
-						unsigned long start,
-						unsigned long end,
-						bool best_match);
-static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
-						     unsigned long size,
-						     unsigned alignment,
-						     bool best_match)
+				       unsigned long end,
+				       enum drm_mm_search_flags flags);
+static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
+					      struct drm_mm_node *node,
+					      unsigned long size,
+					      unsigned alignment,
+					      unsigned long start,
+					      unsigned long end,
+					      enum drm_mm_search_flags flags)
 {
-	return drm_mm_search_free_generic(mm,size, alignment, 0, best_match);
-}
-static inline  struct drm_mm_node *drm_mm_search_free_in_range(
-						const struct drm_mm *mm,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long start,
-						unsigned long end,
-						bool best_match)
-{
-	return drm_mm_search_free_in_range_generic(mm, size, alignment, 0,
-						   start, end, best_match);
+	return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
+						   0, start, end, flags);
 }
 
+extern void drm_mm_remove_node(struct drm_mm_node *node);
+extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
 extern void drm_mm_init(struct drm_mm *mm,
 			unsigned long start,
 			unsigned long size);
 extern void drm_mm_takedown(struct drm_mm *mm);
 extern int drm_mm_clean(struct drm_mm *mm);
-extern int drm_mm_pre_get(struct drm_mm *mm);
-
-static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
-{
-	return block->mm;
-}
 
 void drm_mm_init_scan(struct drm_mm *mm,
 		      unsigned long size,
diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h
new file mode 100644
index 0000000..22eedac
--- /dev/null
+++ b/include/drm/drm_vma_manager.h
@@ -0,0 +1,224 @@
+#ifndef __DRM_VMA_MANAGER_H__
+#define __DRM_VMA_MANAGER_H__
+
+/*
+ * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <drm/drm_mm.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+struct drm_vma_offset_node {
+	struct drm_mm_node vm_node;
+	struct rb_node vm_rb;
+};
+
+struct drm_vma_offset_manager {
+	rwlock_t vm_lock;
+	struct rb_root vm_addr_space_rb;
+	struct drm_mm vm_addr_space_mm;
+};
+
+void drm_vma_offset_manager_init(struct drm_vma_offset_manager *mgr,
+				 unsigned long page_offset, unsigned long size);
+void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager *mgr);
+
+struct drm_vma_offset_node *drm_vma_offset_lookup(struct drm_vma_offset_manager *mgr,
+						  unsigned long start,
+						  unsigned long pages);
+struct drm_vma_offset_node *drm_vma_offset_lookup_locked(struct drm_vma_offset_manager *mgr,
+							   unsigned long start,
+							   unsigned long pages);
+int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
+		       struct drm_vma_offset_node *node, unsigned long pages);
+void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
+			   struct drm_vma_offset_node *node);
+
+/**
+ * drm_vma_offset_exact_lookup() - Look up node by exact address
+ * @mgr: Manager object
+ * @start: Start address (page-based, not byte-based)
+ * @pages: Size of object (page-based)
+ *
+ * Same as drm_vma_offset_lookup() but does not allow any offset into the node.
+ * It only returns the exact object with the given start address.
+ *
+ * RETURNS:
+ * Node at exact start address @start.
+ */
+static inline struct drm_vma_offset_node *
+drm_vma_offset_exact_lookup(struct drm_vma_offset_manager *mgr,
+			    unsigned long start,
+			    unsigned long pages)
+{
+	struct drm_vma_offset_node *node;
+
+	node = drm_vma_offset_lookup(mgr, start, pages);
+	return (node && node->vm_node.start == start) ? node : NULL;
+}
+
+/**
+ * drm_vma_offset_lock_lookup() - Lock lookup for extended private use
+ * @mgr: Manager object
+ *
+ * Lock VMA manager for extended lookups. Only *_locked() VMA function calls
+ * are allowed while holding this lock. All other contexts are blocked from VMA
+ * until the lock is released via drm_vma_offset_unlock_lookup().
+ *
+ * Use this if you need to take a reference to the objects returned by
+ * drm_vma_offset_lookup_locked() before releasing this lock again.
+ *
+ * This lock must not be used for anything else than extended lookups. You must
+ * not call any other VMA helpers while holding this lock.
+ *
+ * Note: You're in atomic-context while holding this lock!
+ *
+ * Example:
+ *   drm_vma_offset_lock_lookup(mgr);
+ *   node = drm_vma_offset_lookup_locked(mgr);
+ *   if (node)
+ *       kref_get_unless_zero(container_of(node, sth, entr));
+ *   drm_vma_offset_unlock_lookup(mgr);
+ */
+static inline void drm_vma_offset_lock_lookup(struct drm_vma_offset_manager *mgr)
+{
+	read_lock(&mgr->vm_lock);
+}
+
+/**
+ * drm_vma_offset_unlock_lookup() - Unlock lookup for extended private use
+ * @mgr: Manager object
+ *
+ * Release lookup-lock. See drm_vma_offset_lock_lookup() for more information.
+ */
+static inline void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager *mgr)
+{
+	read_unlock(&mgr->vm_lock);
+}
+
+/**
+ * drm_vma_node_reset() - Initialize or reset node object
+ * @node: Node to initialize or reset
+ *
+ * Reset a node to its initial state. This must be called if @node isn't
+ * already cleared (eg., via kzalloc) before using it with any VMA offset
+ * manager.
+ *
+ * This must not be called on an already allocated node, or you will leak
+ * memory.
+ */
+static inline void drm_vma_node_reset(struct drm_vma_offset_node *node)
+{
+	memset(node, 0, sizeof(*node));
+}
+
+/**
+ * drm_vma_node_start() - Return start address for page-based addressing
+ * @node: Node to inspect
+ *
+ * Return the start address of the given node. This can be used as offset into
+ * the linear VM space that is provided by the VMA offset manager. Note that
+ * this can only be used for page-based addressing. If you need a proper offset
+ * for user-space mappings, you must apply "<< PAGE_SHIFT" or use the
+ * drm_vma_node_offset_addr() helper instead.
+ *
+ * RETURNS:
+ * Start address of @node for page-based addressing. 0 if the node does not
+ * have an offset allocated.
+ */
+static inline unsigned long drm_vma_node_start(struct drm_vma_offset_node *node)
+{
+	return node->vm_node.start;
+}
+
+/**
+ * drm_vma_node_size() - Return size (page-based)
+ * @node: Node to inspect
+ *
+ * Return the size as number of pages for the given node. This is the same size
+ * that was passed to drm_vma_offset_add(). If no offset is allocated for the
+ * node, this is 0.
+ *
+ * RETURNS:
+ * Size of @node as number of pages. 0 if the node does not have an offset
+ * allocated.
+ */
+static inline unsigned long drm_vma_node_size(struct drm_vma_offset_node *node)
+{
+	return node->vm_node.size;
+}
+
+/**
+ * drm_vma_node_has_offset() - Check whether node is added to offset manager
+ * @node: Node to be checked
+ *
+ * RETURNS:
+ * true iff the node was previously allocated an offset and added to
+ * an vma offset manager.
+ */
+static inline bool drm_vma_node_has_offset(struct drm_vma_offset_node *node)
+{
+	return drm_mm_node_allocated(&node->vm_node);
+}
+
+/**
+ * drm_vma_node_offset_addr() - Return sanitized offset for user-space mmaps
+ * @node: Linked offset node
+ *
+ * Same as drm_vma_node_start() but returns the address as a valid offset that
+ * can be used for user-space mappings during mmap().
+ * This must not be called on unlinked nodes.
+ *
+ * RETURNS:
+ * Offset of @node for byte-based addressing. 0 if the node does not have an
+ * object allocated.
+ */
+static inline __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node)
+{
+	return ((__u64)node->vm_node.start) << PAGE_SHIFT;
+}
+
+/**
+ * drm_vma_node_unmap() - Unmap offset node
+ * @node: Offset node
+ * @file_mapping: Address space to unmap @node from
+ *
+ * Unmap all userspace mappings for a given offset node. The mappings must be
+ * associated with the @file_mapping address-space. If no offset exists or
+ * the address-space is invalid, nothing is done.
+ *
+ * This call is unlocked. The caller must guarantee that drm_vma_offset_remove()
+ * is not called on this node concurrently.
+ */
+static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node,
+				      struct address_space *file_mapping)
+{
+	if (file_mapping && drm_vma_node_has_offset(node))
+		unmap_mapping_range(file_mapping,
+				    drm_vma_node_offset_addr(node),
+				    drm_vma_node_size(node) << PAGE_SHIFT, 1);
+}
+
+#endif /* __DRM_VMA_MANAGER_H__ */
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 8a6aa56..751eaff 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -32,12 +32,12 @@
 #define _TTM_BO_API_H_
 
 #include <drm/drm_hashtab.h>
+#include <drm/drm_vma_manager.h>
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
-#include <linux/rbtree.h>
 #include <linux/bitmap.h>
 #include <linux/reservation.h>
 
@@ -145,7 +145,6 @@ struct ttm_tt;
  * @type: The bo type.
  * @destroy: Destruction function. If NULL, kfree is used.
  * @num_pages: Actual number of pages.
- * @addr_space_offset: Address space offset.
  * @acc_size: Accounted size for this object.
  * @kref: Reference count of this buffer object. When this refcount reaches
  * zero, the object is put on the delayed delete list.
@@ -166,8 +165,7 @@ struct ttm_tt;
  * @swap: List head for swap LRU list.
  * @sync_obj: Pointer to a synchronization object.
  * @priv_flags: Flags describing buffer object internal state.
- * @vm_rb: Rb node for the vm rb tree.
- * @vm_node: Address space manager node.
+ * @vma_node: Address space manager node.
  * @offset: The current GPU offset, which can have different meanings
  * depending on the memory type. For SYSTEM type memory, it should be 0.
  * @cur_placement: Hint of current placement.
@@ -194,7 +192,6 @@ struct ttm_buffer_object {
 	enum ttm_bo_type type;
 	void (*destroy) (struct ttm_buffer_object *);
 	unsigned long num_pages;
-	uint64_t addr_space_offset;
 	size_t acc_size;
 
 	/**
@@ -238,13 +235,7 @@ struct ttm_buffer_object {
 	void *sync_obj;
 	unsigned long priv_flags;
 
-	/**
-	 * Members protected by the bdev::vm_lock
-	 */
-
-	struct rb_node vm_rb;
-	struct drm_mm_node *vm_node;
-
+	struct drm_vma_offset_node vma_node;
 
 	/**
 	 * Special members that are protected by the reserve lock
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 984fc2d..8639c85 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -36,6 +36,7 @@
 #include <ttm/ttm_placement.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_global.h>
+#include <drm/drm_vma_manager.h>
 #include <linux/workqueue.h>
 #include <linux/fs.h>
 #include <linux/spinlock.h>
@@ -519,7 +520,7 @@ struct ttm_bo_global {
  * @man: An array of mem_type_managers.
  * @fence_lock: Protects the synchronizing members on *all* bos belonging
  * to this device.
- * @addr_space_mm: Range manager for the device address space.
+ * @vma_manager: Address space manager
  * lru_lock: Spinlock that protects the buffer+device lru lists and
  * ddestroy lists.
  * @val_seq: Current validation sequence.
@@ -537,14 +538,13 @@ struct ttm_bo_device {
 	struct list_head device_list;
 	struct ttm_bo_global *glob;
 	struct ttm_bo_driver *driver;
-	rwlock_t vm_lock;
 	struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES];
 	spinlock_t fence_lock;
+
 	/*
-	 * Protected by the vm lock.
+	 * Protected by internal locks.
 	 */
-	struct rb_root addr_space_rb;
-	struct drm_mm addr_space_mm;
+	struct drm_vma_offset_manager vma_manager;
 
 	/*
 	 * Protected by the global:lru lock.
diff --git a/include/dt-bindings/pwm/pwm.h b/include/dt-bindings/pwm/pwm.h
new file mode 100644
index 0000000..96f49e8
--- /dev/null
+++ b/include/dt-bindings/pwm/pwm.h
@@ -0,0 +1,14 @@
+/*
+ * This header provides constants for most PWM bindings.
+ *
+ * Most PWM bindings can include a flags cell as part of the PWM specifier.
+ * In most cases, the format of the flags cell uses the standard values
+ * defined in this header.
+ */
+
+#ifndef _DT_BINDINGS_PWM_PWM_H
+#define _DT_BINDINGS_PWM_PWM_H
+
+#define PWM_POLARITY_INVERTED			(1 << 0)
+
+#endif
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 353ba25..a5db4ae 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -481,6 +481,13 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 
 acpi_status acpi_os_prepare_sleep(u8 sleep_state,
 				  u32 pm1a_control, u32 pm1b_control);
+
+void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
+				        u32 val_a,  u32 val_b));
+
+acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
+					   u32 val_a, u32 val_b);
+
 #ifdef CONFIG_X86
 void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
 #else
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 1bdf965..d9c92da 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -27,15 +27,13 @@ struct kiocb;
  */
 #define KIOCB_CANCELLED		((void *) (~0ULL))
 
-typedef int (kiocb_cancel_fn)(struct kiocb *, struct io_event *);
+typedef int (kiocb_cancel_fn)(struct kiocb *);
 
 struct kiocb {
-	atomic_t		ki_users;
-
 	struct file		*ki_filp;
 	struct kioctx		*ki_ctx;	/* NULL for sync ops */
 	kiocb_cancel_fn		*ki_cancel;
-	void			(*ki_dtor)(struct kiocb *);
+	void			*private;
 
 	union {
 		void __user		*user;
@@ -44,17 +42,7 @@ struct kiocb {
 
 	__u64			ki_user_data;	/* user's data for completion */
 	loff_t			ki_pos;
-
-	void			*private;
-	/* State that we remember to be able to restart/retry  */
-	unsigned short		ki_opcode;
-	size_t			ki_nbytes; 	/* copy of iocb->aio_nbytes */
-	char 			__user *ki_buf;	/* remaining iocb->aio_buf */
-	size_t			ki_left; 	/* remaining bytes */
-	struct iovec		ki_inline_vec;	/* inline vector */
- 	struct iovec		*ki_iovec;
- 	unsigned long		ki_nr_segs;
- 	unsigned long		ki_cur_seg;
+	size_t			ki_nbytes;	/* copy of iocb->aio_nbytes */
 
 	struct list_head	ki_list;	/* the aio core uses this
 						 * for cancellation */
@@ -74,7 +62,6 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
 static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
 {
 	*kiocb = (struct kiocb) {
-			.ki_users = ATOMIC_INIT(1),
 			.ki_ctx = NULL,
 			.ki_filp = filp,
 			.ki_obj.tsk = current,
@@ -84,7 +71,6 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
 /* prototypes */
 #ifdef CONFIG_AIO
 extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
-extern void aio_put_req(struct kiocb *iocb);
 extern void aio_complete(struct kiocb *iocb, long res, long res2);
 struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
@@ -93,7 +79,6 @@ extern long do_io_submit(aio_context_t ctx_id, long nr,
 void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
 #else
 static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
-static inline void aio_put_req(struct kiocb *iocb) { }
 static inline void aio_complete(struct kiocb *iocb, long res, long res2) { }
 struct mm_struct;
 static inline void exit_aio(struct mm_struct *mm) { }
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index 8013a45..cf573c2 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -13,6 +13,9 @@ struct file_operations;
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
+struct file *anon_inode_getfile_private(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags);
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
 
diff --git a/include/linux/ata.h b/include/linux/ata.h
index ee0bd95..f63fb1a 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -446,22 +446,6 @@ enum {
 	SERR_TRANS_ST_ERROR	= (1 << 24), /* Transport state trans. error */
 	SERR_UNRECOG_FIS	= (1 << 25), /* Unrecognized FIS */
 	SERR_DEV_XCHG		= (1 << 26), /* device exchanged */
-
-	/* struct ata_taskfile flags */
-	ATA_TFLAG_LBA48		= (1 << 0), /* enable 48-bit LBA and "HOB" */
-	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
-	ATA_TFLAG_DEVICE	= (1 << 2), /* enable r/w to device reg */
-	ATA_TFLAG_WRITE		= (1 << 3), /* data dir: host->dev==1 (write) */
-	ATA_TFLAG_LBA		= (1 << 4), /* enable LBA */
-	ATA_TFLAG_FUA		= (1 << 5), /* enable FUA */
-	ATA_TFLAG_POLLING	= (1 << 6), /* set nIEN to 1 and use polling */
-
-	/* protocol flags */
-	ATA_PROT_FLAG_PIO	= (1 << 0), /* is PIO */
-	ATA_PROT_FLAG_DMA	= (1 << 1), /* is DMA */
-	ATA_PROT_FLAG_DATA	= ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA,
-	ATA_PROT_FLAG_NCQ	= (1 << 2), /* is NCQ */
-	ATA_PROT_FLAG_ATAPI	= (1 << 3), /* is ATAPI */
 };
 
 enum ata_tf_protocols {
@@ -488,83 +472,6 @@ struct ata_bmdma_prd {
 	__le32			flags_len;
 };
 
-struct ata_taskfile {
-	unsigned long		flags;		/* ATA_TFLAG_xxx */
-	u8			protocol;	/* ATA_PROT_xxx */
-
-	u8			ctl;		/* control reg */
-
-	u8			hob_feature;	/* additional data */
-	u8			hob_nsect;	/* to support LBA48 */
-	u8			hob_lbal;
-	u8			hob_lbam;
-	u8			hob_lbah;
-
-	u8			feature;
-	u8			nsect;
-	u8			lbal;
-	u8			lbam;
-	u8			lbah;
-
-	u8			device;
-
-	u8			command;	/* IO operation */
-};
-
-/*
- * protocol tests
- */
-static inline unsigned int ata_prot_flags(u8 prot)
-{
-	switch (prot) {
-	case ATA_PROT_NODATA:
-		return 0;
-	case ATA_PROT_PIO:
-		return ATA_PROT_FLAG_PIO;
-	case ATA_PROT_DMA:
-		return ATA_PROT_FLAG_DMA;
-	case ATA_PROT_NCQ:
-		return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ;
-	case ATAPI_PROT_NODATA:
-		return ATA_PROT_FLAG_ATAPI;
-	case ATAPI_PROT_PIO:
-		return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO;
-	case ATAPI_PROT_DMA:
-		return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA;
-	}
-	return 0;
-}
-
-static inline int ata_is_atapi(u8 prot)
-{
-	return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI;
-}
-
-static inline int ata_is_nodata(u8 prot)
-{
-	return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA);
-}
-
-static inline int ata_is_pio(u8 prot)
-{
-	return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO;
-}
-
-static inline int ata_is_dma(u8 prot)
-{
-	return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA;
-}
-
-static inline int ata_is_ncq(u8 prot)
-{
-	return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ;
-}
-
-static inline int ata_is_data(u8 prot)
-{
-	return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA;
-}
-
 /*
  * id tests
  */
@@ -1060,15 +967,6 @@ static inline unsigned ata_set_lba_range_entries(void *_buffer,
 	return used_bytes;
 }
 
-static inline int is_multi_taskfile(struct ata_taskfile *tf)
-{
-	return (tf->command == ATA_CMD_READ_MULTI) ||
-	       (tf->command == ATA_CMD_WRITE_MULTI) ||
-	       (tf->command == ATA_CMD_READ_MULTI_EXT) ||
-	       (tf->command == ATA_CMD_WRITE_MULTI_EXT) ||
-	       (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
-}
-
 static inline bool ata_ok(u8 status)
 {
 	return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index deb0ae5..66a0e53 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -11,7 +11,7 @@ struct atmel_ssc_platform_data {
 
 struct ssc_device {
 	struct list_head	list;
-	resource_size_t		phybase;
+	dma_addr_t		phybase;
 	void __iomem		*regs;
 	struct platform_device	*pdev;
 	struct atmel_ssc_platform_data *pdata;
diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index fd68337..be201ca 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -124,4 +124,6 @@
 #define ATMEL_US_NER		0x44			/* Number of Errors Register */
 #define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
 
+#define ATMEL_US_NAME		0xf0			/* Ip Name */
+
 #endif
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 622fc50..4d043c3 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -72,7 +72,19 @@ struct bcma_host_ops {
 /* Core-ID values. */
 #define BCMA_CORE_OOB_ROUTER		0x367	/* Out of band */
 #define BCMA_CORE_4706_CHIPCOMMON	0x500
+#define BCMA_CORE_PCIEG2		0x501
+#define BCMA_CORE_DMA			0x502
+#define BCMA_CORE_SDIO3			0x503
+#define BCMA_CORE_USB20			0x504
+#define BCMA_CORE_USB30			0x505
+#define BCMA_CORE_A9JTAG		0x506
+#define BCMA_CORE_DDR23			0x507
+#define BCMA_CORE_ROM			0x508
+#define BCMA_CORE_NAND			0x509
+#define BCMA_CORE_QSPI			0x50A
+#define BCMA_CORE_CHIPCOMMON_B		0x50B
 #define BCMA_CORE_4706_SOC_RAM		0x50E
+#define BCMA_CORE_ARMCA9		0x510
 #define BCMA_CORE_4706_MAC_GBIT		0x52D
 #define BCMA_CORE_AMEMC			0x52E	/* DDR1/2 memory controller core */
 #define BCMA_CORE_ALTA			0x534	/* I2S core */
@@ -177,6 +189,11 @@ struct bcma_host_ops {
 #define  BCMA_PKG_ID_BCM5357	11
 #define BCMA_CHIP_ID_BCM53572	53572
 #define  BCMA_PKG_ID_BCM47188	9
+#define BCMA_CHIP_ID_BCM4707	53010
+#define  BCMA_PKG_ID_BCM4707	1
+#define  BCMA_PKG_ID_BCM4708	2
+#define  BCMA_PKG_ID_BCM4709	0
+#define BCMA_CHIP_ID_BCM53018	53018
 
 /* Board types (on PCI usually equals to the subsystem dev id) */
 /* BCM4313 */
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 70cf138..dcf6670 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -31,7 +31,7 @@ struct linux_binprm {
 #ifdef __alpha__
 	unsigned int taso:1;
 #endif
-	unsigned int recursion_depth;
+	unsigned int recursion_depth; /* only for search_binary_handler() */
 	struct file * file;
 	struct cred *cred;	/* new credentials */
 	int unsafe;		/* how unsafe this exec is (mask of LSM_UNSAFE_*) */
@@ -61,6 +61,7 @@ struct coredump_params {
 	struct file *file;
 	unsigned long limit;
 	unsigned long mm_flags;
+	unsigned long written;
 };
 
 /*
diff --git a/include/linux/blockconsole.h b/include/linux/blockconsole.h
new file mode 100644
index 0000000..114f7c5
--- /dev/null
+++ b/include/linux/blockconsole.h
@@ -0,0 +1,7 @@
+#ifndef LINUX_BLOCKCONSOLE_H
+#define LINUX_BLOCKCONSOLE_H
+
+int bcon_magic_present(const void *data);
+void bcon_add(const char *name);
+
+#endif
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index e9ac882..44dd422 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -161,7 +161,13 @@ struct cgroup_name {
 struct cgroup {
 	unsigned long flags;		/* "unsigned long" so bitops work */
 
-	int id;				/* ida allocated in-hierarchy ID */
+	/*
+	 * idr allocated in-hierarchy ID.
+	 *
+	 * The ID of the root cgroup is always 0, and a new cgroup
+	 * will be assigned with a smallest available ID.
+	 */
+	int id;
 
 	/*
 	 * We link our 'sibling' struct into our parent's 'children'.
@@ -322,7 +328,7 @@ struct cgroupfs_root {
 	unsigned long flags;
 
 	/* IDs for cgroups in this hierarchy */
-	struct ida cgroup_ida;
+	struct idr cgroup_idr;
 
 	/* The path to use for release notifications. */
 	char release_agent_path[PATH_MAX];
@@ -394,8 +400,8 @@ struct cgroup_map_cb {
 
 /* cftype->flags */
 enum {
-	CFTYPE_ONLY_ON_ROOT	= (1 << 0),	/* only create on root cg */
-	CFTYPE_NOT_ON_ROOT	= (1 << 1),	/* don't create on root cg */
+	CFTYPE_ONLY_ON_ROOT	= (1 << 0),	/* only create on root cgrp */
+	CFTYPE_NOT_ON_ROOT	= (1 << 1),	/* don't create on root cgrp */
 	CFTYPE_INSANE		= (1 << 2),	/* don't create if sane_behavior */
 };
 
@@ -513,7 +519,7 @@ struct cftype_set {
 };
 
 struct cgroup_scanner {
-	struct cgroup *cg;
+	struct cgroup *cgrp;
 	int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan);
 	void (*process_task)(struct task_struct *p,
 			struct cgroup_scanner *scan);
@@ -713,6 +719,24 @@ static inline struct cgroup* task_cgroup(struct task_struct *task,
 	return task_subsys_state(task, subsys_id)->cgroup;
 }
 
+/**
+ * cgroup_from_id - lookup cgroup by id
+ * @ss: cgroup subsys to be looked into
+ * @id: the cgroup id
+ *
+ * Returns the cgroup if there's valid one with @id, otherwise returns NULL.
+ * Should be called under rcu_read_lock().
+ */
+static inline struct cgroup *cgroup_from_id(struct cgroup_subsys *ss, int id)
+{
+#ifdef CONFIG_PROVE_RCU
+	rcu_lockdep_assert(rcu_read_lock_held() ||
+			   lockdep_is_held(&cgroup_mutex),
+			   "cgroup_from_id() needs proper protection");
+#endif
+	return idr_find(&ss->root->cgroup_idr, id);
+}
+
 struct cgroup *cgroup_next_sibling(struct cgroup *pos);
 
 /**
diff --git a/include/linux/coda.h b/include/linux/coda.h
index cff544f..d30209b 100644
--- a/include/linux/coda.h
+++ b/include/linux/coda.h
@@ -60,7 +60,6 @@ Mellon the rights to redistribute these changes without encumbrance.
 
 #if defined(__linux__)
 typedef unsigned long long u_quad_t;
-#else
 #endif
 #include <uapi/linux/coda.h>
 #endif 
diff --git a/include/linux/console.h b/include/linux/console.h
index 7571a16..fdfcb70 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -115,6 +115,7 @@ static inline int con_debug_leave(void)
 #define CON_BOOT	(8)
 #define CON_ANYTIME	(16) /* Safe to call when cpu is offline */
 #define CON_BRL		(32) /* Used for a braille device */
+#define CON_ALLDATA	(64) /* per-console ignore_loglevel */
 
 struct console {
 	char	name[16];
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index a98f1ca..c617580 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -10,8 +10,9 @@
  * These are the only things you should do on a core-file: use only these
  * functions to write out all the necessary info.
  */
-extern int dump_write(struct file *file, const void *addr, int nr);
-extern int dump_seek(struct file *file, loff_t off);
+extern bool dump_emit(struct coredump_params *cprm, const void *addr, size_t size);
+extern bool dump_skip(struct coredump_params *cprm, size_t size);
+extern bool dump_align(struct coredump_params *cprm, int align);
 #ifdef CONFIG_COREDUMP
 extern void do_coredump(siginfo_t *siginfo);
 #else
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 90d5a15..d568f39 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -11,71 +11,36 @@
 #ifndef _LINUX_CPUFREQ_H
 #define _LINUX_CPUFREQ_H
 
-#include <asm/cputime.h>
-#include <linux/mutex.h>
-#include <linux/notifier.h>
-#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/completion.h>
 #include <linux/kobject.h>
+#include <linux/notifier.h>
 #include <linux/sysfs.h>
-#include <linux/completion.h>
-#include <linux/workqueue.h>
-#include <linux/cpumask.h>
-#include <asm/div64.h>
-
-#define CPUFREQ_NAME_LEN 16
-/* Print length for names. Extra 1 space for accomodating '\n' in prints */
-#define CPUFREQ_NAME_PLEN (CPUFREQ_NAME_LEN + 1)
 
 /*********************************************************************
- *                     CPUFREQ NOTIFIER INTERFACE                    *
+ *                        CPUFREQ INTERFACE                          *
  *********************************************************************/
-
-#define CPUFREQ_TRANSITION_NOTIFIER	(0)
-#define CPUFREQ_POLICY_NOTIFIER		(1)
-
-#ifdef CONFIG_CPU_FREQ
-int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
-int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
-extern void disable_cpufreq(void);
-#else		/* CONFIG_CPU_FREQ */
-static inline int cpufreq_register_notifier(struct notifier_block *nb,
-						unsigned int list)
-{
-	return 0;
-}
-static inline int cpufreq_unregister_notifier(struct notifier_block *nb,
-						unsigned int list)
-{
-	return 0;
-}
-static inline void disable_cpufreq(void) { }
-#endif		/* CONFIG_CPU_FREQ */
-
-/* if (cpufreq_driver->target) exists, the ->governor decides what frequency
- * within the limits is used. If (cpufreq_driver->setpolicy> exists, these
- * two generic policies are available:
- */
-
-#define CPUFREQ_POLICY_POWERSAVE	(1)
-#define CPUFREQ_POLICY_PERFORMANCE	(2)
-
-/* Frequency values here are CPU kHz so that hardware which doesn't run
- * with some frequencies can complain without having to guess what per
- * cent / per mille means.
+/*
+ * Frequency values here are CPU kHz
+ *
  * Maximum transition latency is in nanoseconds - if it's unknown,
  * CPUFREQ_ETERNAL shall be used.
  */
 
+#define CPUFREQ_ETERNAL			(-1)
+#define CPUFREQ_NAME_LEN		16
+/* Print length for names. Extra 1 space for accomodating '\n' in prints */
+#define CPUFREQ_NAME_PLEN		(CPUFREQ_NAME_LEN + 1)
+
 struct cpufreq_governor;
 
-/* /sys/devices/system/cpu/cpufreq: entry point for global variables */
-extern struct kobject *cpufreq_global_kobject;
-int cpufreq_get_global_kobject(void);
-void cpufreq_put_global_kobject(void);
-int cpufreq_sysfs_create_file(const struct attribute *attr);
-void cpufreq_sysfs_remove_file(const struct attribute *attr);
+struct cpufreq_freqs {
+	unsigned int cpu;	/* cpu nr */
+	unsigned int old;
+	unsigned int new;
+	u8 flags;		/* flags of cpufreq_driver, see below. */
+};
 
-#define CPUFREQ_ETERNAL			(-1)
 struct cpufreq_cpuinfo {
 	unsigned int		max_freq;
 	unsigned int		min_freq;
@@ -117,123 +82,103 @@ struct cpufreq_policy {
 
 	struct cpufreq_real_policy	user_policy;
 
+	struct list_head        policy_list;
 	struct kobject		kobj;
 	struct completion	kobj_unregister;
 	int			transition_ongoing; /* Tracks transition status */
 };
 
-#define CPUFREQ_ADJUST			(0)
-#define CPUFREQ_INCOMPATIBLE		(1)
-#define CPUFREQ_NOTIFY			(2)
-#define CPUFREQ_START			(3)
-#define CPUFREQ_UPDATE_POLICY_CPU	(4)
-
 /* Only for ACPI */
 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
 #define CPUFREQ_SHARED_TYPE_HW	 (1) /* HW does needed coordination */
 #define CPUFREQ_SHARED_TYPE_ALL	 (2) /* All dependent CPUs should set freq */
 #define CPUFREQ_SHARED_TYPE_ANY	 (3) /* Freq can be set from any dependent CPU*/
 
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
+void cpufreq_cpu_put(struct cpufreq_policy *policy);
+
 static inline bool policy_is_shared(struct cpufreq_policy *policy)
 {
 	return cpumask_weight(policy->cpus) > 1;
 }
 
-/******************** cpufreq transition notifiers *******************/
-
-#define CPUFREQ_PRECHANGE	(0)
-#define CPUFREQ_POSTCHANGE	(1)
-#define CPUFREQ_RESUMECHANGE	(8)
-#define CPUFREQ_SUSPENDCHANGE	(9)
+/* /sys/devices/system/cpu/cpufreq: entry point for global variables */
+extern struct kobject *cpufreq_global_kobject;
+int cpufreq_get_global_kobject(void);
+void cpufreq_put_global_kobject(void);
+int cpufreq_sysfs_create_file(const struct attribute *attr);
+void cpufreq_sysfs_remove_file(const struct attribute *attr);
 
-struct cpufreq_freqs {
-	unsigned int cpu;	/* cpu nr */
-	unsigned int old;
-	unsigned int new;
-	u8 flags;		/* flags of cpufreq_driver, see below. */
-};
+#ifdef CONFIG_CPU_FREQ
+unsigned int cpufreq_get(unsigned int cpu);
+unsigned int cpufreq_quick_get(unsigned int cpu);
+unsigned int cpufreq_quick_get_max(unsigned int cpu);
+void disable_cpufreq(void);
 
-/**
- * cpufreq_scale - "old * mult / div" calculation for large values (32-bit-arch
- * safe)
- * @old:   old value
- * @div:   divisor
- * @mult:  multiplier
- *
- *
- * new = old * mult / div
- */
-static inline unsigned long cpufreq_scale(unsigned long old, u_int div,
-		u_int mult)
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
+int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
+int cpufreq_update_policy(unsigned int cpu);
+bool have_governor_per_policy(void);
+struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
+#else
+static inline unsigned int cpufreq_get(unsigned int cpu)
 {
-#if BITS_PER_LONG == 32
-
-	u64 result = ((u64) old) * ((u64) mult);
-	do_div(result, div);
-	return (unsigned long) result;
-
-#elif BITS_PER_LONG == 64
-
-	unsigned long result = old * ((u64) mult);
-	result /= div;
-	return result;
-
+	return 0;
+}
+static inline unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+	return 0;
+}
+static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+	return 0;
+}
+static inline void disable_cpufreq(void) { }
 #endif
-};
 
 /*********************************************************************
- *                          CPUFREQ GOVERNORS                        *
+ *                      CPUFREQ DRIVER INTERFACE                     *
  *********************************************************************/
 
-#define CPUFREQ_GOV_START	1
-#define CPUFREQ_GOV_STOP	2
-#define CPUFREQ_GOV_LIMITS	3
-#define CPUFREQ_GOV_POLICY_INIT	4
-#define CPUFREQ_GOV_POLICY_EXIT	5
+#define CPUFREQ_RELATION_L 0  /* lowest frequency at or above target */
+#define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
 
-struct cpufreq_governor {
-	char	name[CPUFREQ_NAME_LEN];
-	int	initialized;
-	int	(*governor)	(struct cpufreq_policy *policy,
-				 unsigned int event);
-	ssize_t	(*show_setspeed)	(struct cpufreq_policy *policy,
-					 char *buf);
-	int	(*store_setspeed)	(struct cpufreq_policy *policy,
-					 unsigned int freq);
-	unsigned int max_transition_latency; /* HW must be able to switch to
-			next freq faster than this value in nano secs or we
-			will fallback to performance governor */
-	struct list_head	governor_list;
-	struct module		*owner;
+struct freq_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct cpufreq_policy *, char *);
+	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
 };
 
-/*
- * Pass a target to the cpufreq driver.
- */
-extern int cpufreq_driver_target(struct cpufreq_policy *policy,
-				 unsigned int target_freq,
-				 unsigned int relation);
-extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation);
+#define cpufreq_freq_attr_ro(_name)		\
+static struct freq_attr _name =			\
+__ATTR(_name, 0444, show_##_name, NULL)
 
-extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy,
-				   unsigned int cpu);
+#define cpufreq_freq_attr_ro_perm(_name, _perm)	\
+static struct freq_attr _name =			\
+__ATTR(_name, _perm, show_##_name, NULL)
 
-int cpufreq_register_governor(struct cpufreq_governor *governor);
-void cpufreq_unregister_governor(struct cpufreq_governor *governor);
+#define cpufreq_freq_attr_rw(_name)		\
+static struct freq_attr _name =			\
+__ATTR(_name, 0644, show_##_name, store_##_name)
 
-/*********************************************************************
- *                      CPUFREQ DRIVER INTERFACE                     *
- *********************************************************************/
+struct global_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct kobject *kobj,
+			struct attribute *attr, char *buf);
+	ssize_t (*store)(struct kobject *a, struct attribute *b,
+			 const char *c, size_t count);
+};
 
-#define CPUFREQ_RELATION_L 0  /* lowest frequency at or above target */
-#define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
+#define define_one_global_ro(_name)		\
+static struct global_attr _name =		\
+__ATTR(_name, 0444, show_##_name, NULL)
+
+#define define_one_global_rw(_name)		\
+static struct global_attr _name =		\
+__ATTR(_name, 0644, show_##_name, store_##_name)
 
-struct freq_attr;
 
 struct cpufreq_driver {
-	struct module		*owner;
 	char			name[CPUFREQ_NAME_LEN];
 	u8			flags;
 	/*
@@ -258,8 +203,6 @@ struct cpufreq_driver {
 	unsigned int	(*get)	(unsigned int cpu);
 
 	/* optional */
-	unsigned int (*getavg)	(struct cpufreq_policy *policy,
-				 unsigned int cpu);
 	int	(*bios_limit)	(int cpu, unsigned int *limit);
 
 	int	(*exit)		(struct cpufreq_policy *policy);
@@ -269,7 +212,6 @@ struct cpufreq_driver {
 };
 
 /* flags */
-
 #define CPUFREQ_STICKY		0x01	/* the driver isn't removed even if
 					 * all ->init() calls failed */
 #define CPUFREQ_CONST_LOOPS	0x02	/* loops_per_jiffy or other kernel
@@ -281,8 +223,7 @@ struct cpufreq_driver {
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
-void cpufreq_notify_transition(struct cpufreq_policy *policy,
-		struct cpufreq_freqs *freqs, unsigned int state);
+const char *cpufreq_get_current_driver(void);
 
 static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
 		unsigned int min, unsigned int max)
@@ -300,87 +241,118 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
 	return;
 }
 
-struct freq_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct cpufreq_policy *, char *);
-	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
-};
-
-#define cpufreq_freq_attr_ro(_name)		\
-static struct freq_attr _name =			\
-__ATTR(_name, 0444, show_##_name, NULL)
-
-#define cpufreq_freq_attr_ro_perm(_name, _perm)	\
-static struct freq_attr _name =			\
-__ATTR(_name, _perm, show_##_name, NULL)
-
-#define cpufreq_freq_attr_rw(_name)		\
-static struct freq_attr _name =			\
-__ATTR(_name, 0644, show_##_name, store_##_name)
+/*********************************************************************
+ *                     CPUFREQ NOTIFIER INTERFACE                    *
+ *********************************************************************/
 
-struct global_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct kobject *kobj,
-			struct attribute *attr, char *buf);
-	ssize_t (*store)(struct kobject *a, struct attribute *b,
-			 const char *c, size_t count);
-};
+#define CPUFREQ_TRANSITION_NOTIFIER	(0)
+#define CPUFREQ_POLICY_NOTIFIER		(1)
 
-#define define_one_global_ro(_name)		\
-static struct global_attr _name =		\
-__ATTR(_name, 0444, show_##_name, NULL)
+/* Transition notifiers */
+#define CPUFREQ_PRECHANGE		(0)
+#define CPUFREQ_POSTCHANGE		(1)
+#define CPUFREQ_RESUMECHANGE		(8)
+#define CPUFREQ_SUSPENDCHANGE		(9)
 
-#define define_one_global_rw(_name)		\
-static struct global_attr _name =		\
-__ATTR(_name, 0644, show_##_name, store_##_name)
+/* Policy Notifiers  */
+#define CPUFREQ_ADJUST			(0)
+#define CPUFREQ_INCOMPATIBLE		(1)
+#define CPUFREQ_NOTIFY			(2)
+#define CPUFREQ_START			(3)
+#define CPUFREQ_UPDATE_POLICY_CPU	(4)
 
-struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
-void cpufreq_cpu_put(struct cpufreq_policy *data);
-const char *cpufreq_get_current_driver(void);
+#ifdef CONFIG_CPU_FREQ
+int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
+int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
 
-/*********************************************************************
- *                        CPUFREQ 2.6. INTERFACE                     *
- *********************************************************************/
-u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
-int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
-int cpufreq_update_policy(unsigned int cpu);
-bool have_governor_per_policy(void);
-struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
+void cpufreq_notify_transition(struct cpufreq_policy *policy,
+		struct cpufreq_freqs *freqs, unsigned int state);
 
-#ifdef CONFIG_CPU_FREQ
-/*
- * query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it
- */
-unsigned int cpufreq_get(unsigned int cpu);
-#else
-static inline unsigned int cpufreq_get(unsigned int cpu)
+#else /* CONFIG_CPU_FREQ */
+static inline int cpufreq_register_notifier(struct notifier_block *nb,
+						unsigned int list)
 {
 	return 0;
 }
-#endif
-
-/*
- * query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it
- */
-#ifdef CONFIG_CPU_FREQ
-unsigned int cpufreq_quick_get(unsigned int cpu);
-unsigned int cpufreq_quick_get_max(unsigned int cpu);
-#else
-static inline unsigned int cpufreq_quick_get(unsigned int cpu)
+static inline int cpufreq_unregister_notifier(struct notifier_block *nb,
+						unsigned int list)
 {
 	return 0;
 }
-static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
+#endif /* !CONFIG_CPU_FREQ */
+
+/**
+ * cpufreq_scale - "old * mult / div" calculation for large values (32-bit-arch
+ * safe)
+ * @old:   old value
+ * @div:   divisor
+ * @mult:  multiplier
+ *
+ *
+ * new = old * mult / div
+ */
+static inline unsigned long cpufreq_scale(unsigned long old, u_int div,
+		u_int mult)
 {
-	return 0;
-}
+#if BITS_PER_LONG == 32
+	u64 result = ((u64) old) * ((u64) mult);
+	do_div(result, div);
+	return (unsigned long) result;
+
+#elif BITS_PER_LONG == 64
+	unsigned long result = old * ((u64) mult);
+	result /= div;
+	return result;
 #endif
+}
 
 /*********************************************************************
- *                       CPUFREQ DEFAULT GOVERNOR                    *
+ *                          CPUFREQ GOVERNORS                        *
  *********************************************************************/
 
 /*
+ * If (cpufreq_driver->target) exists, the ->governor decides what frequency
+ * within the limits is used. If (cpufreq_driver->setpolicy> exists, these
+ * two generic policies are available:
+ */
+#define CPUFREQ_POLICY_POWERSAVE	(1)
+#define CPUFREQ_POLICY_PERFORMANCE	(2)
+
+/* Governor Events */
+#define CPUFREQ_GOV_START	1
+#define CPUFREQ_GOV_STOP	2
+#define CPUFREQ_GOV_LIMITS	3
+#define CPUFREQ_GOV_POLICY_INIT	4
+#define CPUFREQ_GOV_POLICY_EXIT	5
+
+struct cpufreq_governor {
+	char	name[CPUFREQ_NAME_LEN];
+	int	initialized;
+	int	(*governor)	(struct cpufreq_policy *policy,
+				 unsigned int event);
+	ssize_t	(*show_setspeed)	(struct cpufreq_policy *policy,
+					 char *buf);
+	int	(*store_setspeed)	(struct cpufreq_policy *policy,
+					 unsigned int freq);
+	unsigned int max_transition_latency; /* HW must be able to switch to
+			next freq faster than this value in nano secs or we
+			will fallback to performance governor */
+	struct list_head	governor_list;
+	struct module		*owner;
+};
+
+/* Pass a target to the cpufreq driver */
+int cpufreq_driver_target(struct cpufreq_policy *policy,
+				 unsigned int target_freq,
+				 unsigned int relation);
+int __cpufreq_driver_target(struct cpufreq_policy *policy,
+				   unsigned int target_freq,
+				   unsigned int relation);
+int cpufreq_register_governor(struct cpufreq_governor *governor);
+void cpufreq_unregister_governor(struct cpufreq_governor *governor);
+
+/* CPUFREQ DEFAULT GOVERNOR */
+/*
  * Performance governor is fallback governor if any other gov failed to auto
  * load due latency restrictions
  */
@@ -428,18 +400,16 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   unsigned int relation,
 				   unsigned int *index);
 
-/* the following 3 funtions are for cpufreq core use only */
+void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
+ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
+
+/* the following funtion is for cpufreq core use only */
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
 
 /* the following are really really optional */
 extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
-
 void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
 				      unsigned int cpu);
-void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
-
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
 
-ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
-
 #endif /* _LINUX_CPUFREQ_H */
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 0bc4b74..781addc 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -13,8 +13,6 @@
 
 #include <linux/percpu.h>
 #include <linux/list.h>
-#include <linux/kobject.h>
-#include <linux/completion.h>
 #include <linux/hrtimer.h>
 
 #define CPUIDLE_STATE_MAX	10
@@ -61,6 +59,10 @@ struct cpuidle_state {
 
 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
 
+struct cpuidle_device_kobj;
+struct cpuidle_state_kobj;
+struct cpuidle_driver_kobj;
+
 struct cpuidle_device {
 	unsigned int		registered:1;
 	unsigned int		enabled:1;
@@ -71,9 +73,8 @@ struct cpuidle_device {
 	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];
 	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
 	struct cpuidle_driver_kobj *kobj_driver;
+	struct cpuidle_device_kobj *kobj_dev;
 	struct list_head 	device_list;
-	struct kobject		kobj;
-	struct completion	kobj_unregister;
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
 	int			safe_state_index;
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 37e4f8d..fe68a5a 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -12,6 +12,15 @@
 extern unsigned long long elfcorehdr_addr;
 extern unsigned long long elfcorehdr_size;
 
+extern int __weak elfcorehdr_alloc(unsigned long long *addr,
+				   unsigned long long *size);
+extern void __weak elfcorehdr_free(unsigned long long addr);
+extern ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos);
+extern ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos);
+extern int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma,
+					 unsigned long from, unsigned long pfn,
+					 unsigned long size, pgprot_t prot);
+
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
 						unsigned long, int);
 
diff --git a/include/linux/crc64_ecma.h b/include/linux/crc64_ecma.h
new file mode 100644
index 0000000..bba7a4d
--- /dev/null
+++ b/include/linux/crc64_ecma.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CRC64_ECMA_H_
+#define __CRC64_ECMA_H_
+
+#include <linux/types.h>
+
+
+#define CRC64_DEFAULT_INITVAL           0xFFFFFFFFFFFFFFFFULL
+
+
+/*
+ * crc64_ecma_seed - Initializes the CRC64 ECMA seed.
+ */
+u64 crc64_ecma_seed(void);
+
+/*
+ * crc64_ecma - Computes the 64 bit ECMA CRC.
+ *
+ * @pdata:	pointer to the data to compute checksum for.
+ * @nbytes:	number of bytes in data buffer.
+ * @seed:	CRC seed.
+ */
+u64 crc64_ecma(u8 const *pdata, u32 nbytes, u64 seed);
+
+#endif /* __CRC64_ECMA_H_ */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index b90337c..ff46079 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -54,11 +54,11 @@ struct qstr {
 #define hashlen_len(hashlen)  ((u32)((hashlen) >> 32))
 
 struct dentry_stat_t {
-	int nr_dentry;
-	int nr_unused;
-	int age_limit;          /* age in seconds */
-	int want_pages;         /* pages requested by system */
-	int dummy[2];
+	long nr_dentry;
+	long nr_unused;
+	long age_limit;          /* age in seconds */
+	long want_pages;         /* pages requested by system */
+	long dummy[2];
 };
 extern struct dentry_stat_t dentry_stat;
 
@@ -415,4 +415,8 @@ static inline bool d_mountpoint(struct dentry *dentry)
 
 extern int sysctl_vfs_cache_pressure;
 
+static inline unsigned long vfs_pressure_ratio(unsigned long val)
+{
+	return mult_frac(val, sysctl_vfs_cache_pressure, 100);
+}
 #endif	/* __LINUX_DCACHE_H */
diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h
index 0e5f578..98ffcbd 100644
--- a/include/linux/debugobjects.h
+++ b/include/linux/debugobjects.h
@@ -63,7 +63,7 @@ struct debug_obj_descr {
 extern void debug_object_init      (void *addr, struct debug_obj_descr *descr);
 extern void
 debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
-extern void debug_object_activate  (void *addr, struct debug_obj_descr *descr);
+extern int debug_object_activate  (void *addr, struct debug_obj_descr *descr);
 extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
 extern void debug_object_destroy   (void *addr, struct debug_obj_descr *descr);
 extern void debug_object_free      (void *addr, struct debug_obj_descr *descr);
@@ -85,8 +85,8 @@ static inline void
 debug_object_init      (void *addr, struct debug_obj_descr *descr) { }
 static inline void
 debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
-static inline void
-debug_object_activate  (void *addr, struct debug_obj_descr *descr) { }
+static inline int
+debug_object_activate  (void *addr, struct debug_obj_descr *descr) { return 0; }
 static inline void
 debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
 static inline void
diff --git a/include/linux/dm9000.h b/include/linux/dm9000.h
index 96e8769..841925f 100644
--- a/include/linux/dm9000.h
+++ b/include/linux/dm9000.h
@@ -14,6 +14,8 @@
 #ifndef __DM9000_PLATFORM_DATA
 #define __DM9000_PLATFORM_DATA __FILE__
 
+#include <linux/if_ether.h>
+
 /* IO control flags */
 
 #define DM9000_PLATF_8BITONLY	(0x0001)
@@ -27,7 +29,7 @@
 
 struct dm9000_plat_data {
 	unsigned int	flags;
-	unsigned char	dev_addr[6];
+	unsigned char	dev_addr[ETH_ALEN];
 
 	/* allow replacement IO routines */
 
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index 01b5c84..00141d3 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -57,7 +57,7 @@ struct cma;
 struct page;
 struct device;
 
-#ifdef CONFIG_CMA
+#ifdef CONFIG_DMA_CMA
 
 /*
  * There is always at least global CMA area and a few optional device
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index cb286b1..5692bc3 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -370,6 +370,33 @@ struct dma_slave_config {
 	unsigned int slave_id;
 };
 
+/* struct dma_slave_caps - expose capabilities of a slave channel only
+ *
+ * @src_addr_widths: bit mask of src addr widths the channel supports
+ * @dstn_addr_widths: bit mask of dstn addr widths the channel supports
+ * @directions: bit mask of slave direction the channel supported
+ * 	since the enum dma_transfer_direction is not defined as bits for each
+ * 	type of direction, the dma controller should fill (1 << <TYPE>) and same
+ * 	should be checked by controller as well
+ * @cmd_pause: true, if pause and thereby resume is supported
+ * @cmd_terminate: true, if terminate cmd is supported
+ *
+ * @max_sg_nr: maximum number of SG segments supported
+ * 	0 for no maximum
+ * @max_sg_len: maximum length of a SG segment supported
+ * 	0 for no maximum
+ */
+struct dma_slave_caps {
+	u32 src_addr_widths;
+	u32 dstn_addr_widths;
+	u32 directions;
+	bool cmd_pause;
+	bool cmd_terminate;
+
+	u32 max_sg_nr;
+	u32 max_sg_len;
+};
+
 static inline const char *dma_chan_name(struct dma_chan *chan)
 {
 	return dev_name(&chan->dev->device);
@@ -532,6 +559,7 @@ struct dma_tx_state {
  *	struct with auxiliary transfer status information, otherwise the call
  *	will just return a simple status code
  * @device_issue_pending: push pending transactions to hardware
+ * @device_slave_caps: return the slave channel capabilities
  */
 struct dma_device {
 
@@ -597,6 +625,7 @@ struct dma_device {
 					    dma_cookie_t cookie,
 					    struct dma_tx_state *txstate);
 	void (*device_issue_pending)(struct dma_chan *chan);
+	int (*device_slave_caps)(struct dma_chan *chan, struct dma_slave_caps *caps);
 };
 
 static inline int dmaengine_device_control(struct dma_chan *chan,
@@ -670,6 +699,21 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma(
 	return chan->device->device_prep_interleaved_dma(chan, xt, flags);
 }
 
+static inline int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
+{
+	if (!chan || !caps)
+		return -EINVAL;
+
+	/* check if the channel supports slave transactions */
+	if (!test_bit(DMA_SLAVE, chan->device->cap_mask.bits))
+		return -ENXIO;
+
+	if (chan->device->device_slave_caps)
+		return chan->device->device_slave_caps(chan, caps);
+
+	return -ENXIO;
+}
+
 static inline int dmaengine_terminate_all(struct dma_chan *chan)
 {
 	return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 40a3c0e..87fdf7a 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -39,13 +39,14 @@ extern Elf64_Dyn _DYNAMIC [];
 
 /* Optional callbacks to write extra ELF notes. */
 struct file;
+struct coredump_params;
 
 #ifndef ARCH_HAVE_EXTRA_ELF_NOTES
 static inline int elf_coredump_extra_notes_size(void) { return 0; }
-static inline int elf_coredump_extra_notes_write(struct file *file,
-			loff_t *foffset) { return 0; }
+static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm)
+			{ return 0; }
 #else
 extern int elf_coredump_extra_notes_size(void);
-extern int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset);
+extern int elf_coredump_extra_notes_write(struct coredump_params *cprm);
 #endif
 #endif /* _LINUX_ELF_H */
diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h
index cdd3d13..fea1a62 100644
--- a/include/linux/elfcore.h
+++ b/include/linux/elfcore.h
@@ -63,10 +63,9 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregse
  */
 extern Elf_Half elf_core_extra_phdrs(void);
 extern int
-elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-			   unsigned long limit);
+elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset);
 extern int
-elf_core_write_extra_data(struct file *file, size_t *size, unsigned long limit);
+elf_core_write_extra_data(struct coredump_params *cprm);
 extern size_t elf_core_extra_data_size(void);
 
 #endif /* _LINUX_ELFCORE_H */
diff --git a/include/linux/err.h b/include/linux/err.h
index 221fcfb..15f92e0 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -52,7 +52,7 @@ static inline void * __must_check ERR_CAST(__force const void *ptr)
 	return (void *) ptr;
 }
 
-static inline int __must_check PTR_RET(__force const void *ptr)
+static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
 {
 	if (IS_ERR(ptr))
 		return PTR_ERR(ptr);
@@ -60,6 +60,9 @@ static inline int __must_check PTR_RET(__force const void *ptr)
 		return 0;
 }
 
+/* Deprecated */
+#define PTR_RET(p) PTR_ERR_OR_ZERO(p)
+
 #endif
 
 #endif /* _LINUX_ERR_H */
diff --git a/include/linux/extcon/of_extcon.h b/include/linux/extcon/of_extcon.h
new file mode 100644
index 0000000..0ebfeff
--- /dev/null
+++ b/include/linux/extcon/of_extcon.h
@@ -0,0 +1,31 @@
+/*
+ * OF helpers for External connector (extcon) framework
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ * Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * Copyright (C) 2013 Samsung Electronics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_OF_EXTCON_H
+#define __LINUX_OF_EXTCON_H
+
+#include <linux/err.h>
+
+#if IS_ENABLED(CONFIG_OF_EXTCON)
+extern struct extcon_dev
+	*of_extcon_get_extcon_dev(struct device *dev, int index);
+#else
+static inline struct extcon_dev
+	*of_extcon_get_extcon_dev(struct device *dev, int index)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_OF_EXTCON */
+#endif /* __LINUX_OF_EXTCON_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9818747..b09ddc0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -10,6 +10,7 @@
 #include <linux/stat.h>
 #include <linux/cache.h>
 #include <linux/list.h>
+#include <linux/list_lru.h>
 #include <linux/llist.h>
 #include <linux/radix-tree.h>
 #include <linux/rbtree.h>
@@ -1269,15 +1270,6 @@ struct super_block {
 	struct list_head	s_files;
 #endif
 	struct list_head	s_mounts;	/* list of mounts; _not_ for fs use */
-	/* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
-	struct list_head	s_dentry_lru;	/* unused dentry lru */
-	int			s_nr_dentry_unused;	/* # of dentry on lru */
-
-	/* s_inode_lru_lock protects s_inode_lru and s_nr_inodes_unused */
-	spinlock_t		s_inode_lru_lock ____cacheline_aligned_in_smp;
-	struct list_head	s_inode_lru;		/* unused inode lru */
-	int			s_nr_inodes_unused;	/* # of inodes on lru */
-
 	struct block_device	*s_bdev;
 	struct backing_dev_info *s_bdi;
 	struct mtd_info		*s_mtd;
@@ -1328,11 +1320,14 @@ struct super_block {
 
 	/* Being remounted read-only */
 	int s_readonly_remount;
-};
 
-/* superblock cache pruning functions */
-extern void prune_icache_sb(struct super_block *sb, int nr_to_scan);
-extern void prune_dcache_sb(struct super_block *sb, int nr_to_scan);
+	/*
+	 * Keep the lru lists last in the structure so they always sit on their
+	 * own individual cachelines.
+	 */
+	struct list_lru		s_dentry_lru ____cacheline_aligned_in_smp;
+	struct list_lru		s_inode_lru ____cacheline_aligned_in_smp;
+};
 
 extern struct timespec current_fs_time(struct super_block *sb);
 
@@ -1626,8 +1621,8 @@ struct super_operations {
 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
 #endif
 	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
-	int (*nr_cached_objects)(struct super_block *);
-	void (*free_cached_objects)(struct super_block *, int);
+	long (*nr_cached_objects)(struct super_block *, int);
+	long (*free_cached_objects)(struct super_block *, long, int);
 };
 
 /*
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..343d82a 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -18,6 +18,7 @@
 
 #include <linux/string.h>
 #include <linux/of_mdio.h>
+#include <linux/if_ether.h>
 #include <asm/types.h>
 
 #define FS_ENET_NAME	"fs_enet"
@@ -135,7 +136,7 @@ struct fs_platform_info {
 	const struct fs_mii_bus_info *bus_info;
 
 	int rx_ring, tx_ring;	/* number of buffers on rx     */
-	__u8 macaddr[6];	/* mac address                 */
+	__u8 macaddr[ETH_ALEN];	/* mac address                 */
 	int rx_copybreak;	/* limit we copy small frames  */
 	int use_napi;		/* use NAPI                    */
 	int napi_weight;	/* NAPI weight                 */
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 4372658..120d57a 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -78,6 +78,11 @@ struct trace_iterator {
 	/* trace_seq for __print_flags() and __print_symbolic() etc. */
 	struct trace_seq	tmp_seq;
 
+	cpumask_var_t		started;
+
+	/* it's true when current open file is snapshot */
+	bool			snapshot;
+
 	/* The below is zeroed out in pipe_read */
 	struct trace_seq	seq;
 	struct trace_entry	*ent;
@@ -90,10 +95,7 @@ struct trace_iterator {
 	loff_t			pos;
 	long			idx;
 
-	cpumask_var_t		started;
-
-	/* it's true when current open file is snapshot */
-	bool			snapshot;
+	/* All new field here will be zeroed out in pipe_read */
 };
 
 enum trace_iter_flags {
@@ -332,7 +334,7 @@ extern int trace_define_field(struct ftrace_event_call *call, const char *type,
 			      const char *name, int offset, int size,
 			      int is_signed, int filter_type);
 extern int trace_add_event_call(struct ftrace_event_call *call);
-extern void trace_remove_event_call(struct ftrace_event_call *call);
+extern int trace_remove_event_call(struct ftrace_event_call *call);
 
 #define is_signed_type(type)	(((type)(-1)) < (type)1)
 
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 05bcc09..ecc8e01 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -94,6 +94,11 @@
  */
 #define in_nmi()	(preempt_count() & NMI_MASK)
 
+/*
+ * Are we in nmi,irq context, or softirq context?
+ */
+#define in_serving_irq() (in_nmi() || in_irq() || in_serving_softirq())
+
 #if defined(CONFIG_PREEMPT_COUNT)
 # define PREEMPT_CHECK_OFFSET 1
 #else
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index 3b58944..bc6743e 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -23,6 +23,15 @@ enum hdmi_infoframe_type {
 #define HDMI_SPD_INFOFRAME_SIZE    25
 #define HDMI_AUDIO_INFOFRAME_SIZE  10
 
+#define HDMI_INFOFRAME_SIZE(type)	\
+	(HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)
+
+struct hdmi_any_infoframe {
+	enum hdmi_infoframe_type type;
+	unsigned char version;
+	unsigned char length;
+};
+
 enum hdmi_colorspace {
 	HDMI_COLORSPACE_RGB,
 	HDMI_COLORSPACE_YUV422,
@@ -228,4 +237,15 @@ struct hdmi_vendor_infoframe {
 ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
 				   void *buffer, size_t size);
 
+union hdmi_infoframe {
+	struct hdmi_any_infoframe any;
+	struct hdmi_avi_infoframe avi;
+	struct hdmi_spd_infoframe spd;
+	struct hdmi_vendor_infoframe vendor;
+	struct hdmi_audio_infoframe audio;
+};
+
+ssize_t
+hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size);
+
 #endif /* _DRM_HDMI_H */
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0c48991..5a4e789 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -456,6 +456,7 @@ struct hid_device {							/* device report descriptor */
 	enum hid_type type;						/* device type (mouse, kbd, ...) */
 	unsigned country;						/* HID country */
 	struct hid_report_enum report_enum[HID_REPORT_TYPES];
+	struct work_struct led_work;					/* delayed LED worker */
 
 	struct semaphore driver_lock;					/* protects the current driver, except during input */
 	struct semaphore driver_input_lock;				/* protects the current driver */
@@ -744,6 +745,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid);
 unsigned int hidinput_count_leds(struct hid_device *hid);
 __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
 void hid_output_report(struct hid_report *report, __u8 *data);
+u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 struct hid_device *hid_allocate_device(void);
 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
@@ -989,7 +991,6 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
 int usbhid_quirks_init(char **quirks_param);
 void usbhid_quirks_exit(void);
-void usbhid_set_leds(struct hid_device *hid);
 
 #ifdef CONFIG_HID_PID
 int hid_pidff_init(struct hid_device *hid);
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index b60de92..3935428 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -96,9 +96,6 @@ extern int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 			  pmd_t *dst_pmd, pmd_t *src_pmd,
 			  struct vm_area_struct *vma,
 			  unsigned long addr, unsigned long end);
-extern int handle_pte_fault(struct mm_struct *mm,
-			    struct vm_area_struct *vma, unsigned long address,
-			    pte_t *pte, pmd_t *pmd, unsigned int flags);
 extern int split_huge_page_to_list(struct page *page, struct list_head *list);
 static inline int split_huge_page(struct page *page)
 {
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index fae8bac..a3b8b2e 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -27,6 +27,14 @@
 
 #include <linux/types.h>
 
+/*
+ * Framework version for util services.
+ */
+
+#define UTIL_FW_MAJOR  3
+#define UTIL_FW_MINOR  0
+#define UTIL_FW_MAJOR_MINOR     (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
+
 
 /*
  * Implementation of host controlled snapshot of the guest.
@@ -455,27 +463,6 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
 	*read = dsize - *write;
 }
 
-
-/*
- * We use the same version numbering for all Hyper-V modules.
- *
- * Definition of versioning is as follows;
- *
- *	Major Number	Changes for these scenarios;
- *			1.	When a new version of Windows Hyper-V
- *				is released.
- *			2.	A Major change has occurred in the
- *				Linux IC's.
- *			(For example the merge for the first time
- *			into the kernel) Every time the Major Number
- *			changes, the Revision number is reset to 0.
- *	Minor Number	Changes when new functionality is added
- *			to the Linux IC's that is not a bug fix.
- *
- * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync
- */
-#define HV_DRV_VERSION           "3.1"
-
 /*
  * VMBUS version is 32 bit entity broken up into
  * two 16 bit quantities: major_number. minor_number.
@@ -1494,7 +1481,7 @@ struct hyperv_service_callback {
 };
 
 #define MAX_SRV_VER	0x7ffffff
-extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *,
+extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
 					struct icmsg_negotiate *, u8 *, int,
 					int);
 
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index e988fa9..b3c4b8d 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -447,11 +447,13 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
 static inline struct i2c_adapter *
 i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
 {
+#if IS_ENABLED(I2C_MUX)
 	struct device *parent = adapter->dev.parent;
 
 	if (parent != NULL && parent->type == &i2c_adapter_type)
 		return to_i2c_adapter(parent);
 	else
+#endif
 		return NULL;
 }
 
diff --git a/include/linux/i2c/i2c-hid.h b/include/linux/i2c/i2c-hid.h
index 60e411d..7aa901d 100644
--- a/include/linux/i2c/i2c-hid.h
+++ b/include/linux/i2c/i2c-hid.h
@@ -19,7 +19,8 @@
  * @hid_descriptor_address: i2c register where the HID descriptor is stored.
  *
  * Note that it is the responsibility of the platform driver (or the acpi 5.0
- * driver) to setup the irq related to the gpio in the struct i2c_board_info.
+ * driver, or the flattened device tree) to setup the irq related to the gpio in
+ * the struct i2c_board_info.
  * The platform driver should also setup the gpio according to the device:
  *
  * A typical example is the following:
diff --git a/include/linux/i2c/pxa-i2c.h b/include/linux/i2c/pxa-i2c.h
index 1a9f65e..53aab24 100644
--- a/include/linux/i2c/pxa-i2c.h
+++ b/include/linux/i2c/pxa-i2c.h
@@ -67,6 +67,9 @@ struct i2c_pxa_platform_data {
 	unsigned int		class;
 	unsigned int		use_pio :1;
 	unsigned int		fast_mode :1;
+	unsigned int		high_mode:1;
+	unsigned char		master_code;
+	unsigned long		rate;
 };
 
 extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index b0dc87a..4e101af 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -16,6 +16,7 @@
 #define LINUX_IEEE80211_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 #include <asm/byteorder.h>
 
 /*
@@ -209,28 +210,28 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
 struct ieee80211_hdr {
 	__le16 frame_control;
 	__le16 duration_id;
-	u8 addr1[6];
-	u8 addr2[6];
-	u8 addr3[6];
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
 	__le16 seq_ctrl;
-	u8 addr4[6];
+	u8 addr4[ETH_ALEN];
 } __packed __aligned(2);
 
 struct ieee80211_hdr_3addr {
 	__le16 frame_control;
 	__le16 duration_id;
-	u8 addr1[6];
-	u8 addr2[6];
-	u8 addr3[6];
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
 	__le16 seq_ctrl;
 } __packed __aligned(2);
 
 struct ieee80211_qos_hdr {
 	__le16 frame_control;
 	__le16 duration_id;
-	u8 addr1[6];
-	u8 addr2[6];
-	u8 addr3[6];
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
 	__le16 seq_ctrl;
 	__le16 qos_ctrl;
 } __packed __aligned(2);
@@ -608,8 +609,8 @@ struct ieee80211s_hdr {
 	u8 flags;
 	u8 ttl;
 	__le32 seqnum;
-	u8 eaddr1[6];
-	u8 eaddr2[6];
+	u8 eaddr1[ETH_ALEN];
+	u8 eaddr2[ETH_ALEN];
 } __packed __aligned(2);
 
 /* Mesh flags */
@@ -758,7 +759,7 @@ struct ieee80211_rann_ie {
 	u8 rann_flags;
 	u8 rann_hopcount;
 	u8 rann_ttl;
-	u8 rann_addr[6];
+	u8 rann_addr[ETH_ALEN];
 	__le32 rann_seq;
 	__le32 rann_interval;
 	__le32 rann_metric;
@@ -802,9 +803,9 @@ enum ieee80211_vht_opmode_bits {
 struct ieee80211_mgmt {
 	__le16 frame_control;
 	__le16 duration;
-	u8 da[6];
-	u8 sa[6];
-	u8 bssid[6];
+	u8 da[ETH_ALEN];
+	u8 sa[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
 	__le16 seq_ctrl;
 	union {
 		struct {
@@ -833,7 +834,7 @@ struct ieee80211_mgmt {
 		struct {
 			__le16 capab_info;
 			__le16 listen_interval;
-			u8 current_ap[6];
+			u8 current_ap[ETH_ALEN];
 			/* followed by SSID and Supported rates */
 			u8 variable[0];
 		} __packed reassoc_req;
@@ -966,21 +967,21 @@ struct ieee80211_vendor_ie {
 struct ieee80211_rts {
 	__le16 frame_control;
 	__le16 duration;
-	u8 ra[6];
-	u8 ta[6];
+	u8 ra[ETH_ALEN];
+	u8 ta[ETH_ALEN];
 } __packed __aligned(2);
 
 struct ieee80211_cts {
 	__le16 frame_control;
 	__le16 duration;
-	u8 ra[6];
+	u8 ra[ETH_ALEN];
 } __packed __aligned(2);
 
 struct ieee80211_pspoll {
 	__le16 frame_control;
 	__le16 aid;
-	u8 bssid[6];
-	u8 ta[6];
+	u8 bssid[ETH_ALEN];
+	u8 ta[ETH_ALEN];
 } __packed __aligned(2);
 
 /* TDLS */
@@ -989,14 +990,14 @@ struct ieee80211_pspoll {
 struct ieee80211_tdls_lnkie {
 	u8 ie_type; /* Link Identifier IE */
 	u8 ie_len;
-	u8 bssid[6];
-	u8 init_sta[6];
-	u8 resp_sta[6];
+	u8 bssid[ETH_ALEN];
+	u8 init_sta[ETH_ALEN];
+	u8 resp_sta[ETH_ALEN];
 } __packed;
 
 struct ieee80211_tdls_data {
-	u8 da[6];
-	u8 sa[6];
+	u8 da[ETH_ALEN];
+	u8 sa[ETH_ALEN];
 	__be16 ether_type;
 	u8 payload_type;
 	u8 category;
@@ -1090,8 +1091,8 @@ struct ieee80211_p2p_noa_attr {
 struct ieee80211_bar {
 	__le16 frame_control;
 	__le16 duration;
-	__u8 ra[6];
-	__u8 ta[6];
+	__u8 ra[ETH_ALEN];
+	__u8 ta[ETH_ALEN];
 	__le16 control;
 	__le16 start_seq_num;
 } __packed;
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index f6156f9..a899dc2 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -10,9 +10,9 @@
 #ifndef _LINUX_IF_TEAM_H_
 #define _LINUX_IF_TEAM_H_
 
-
 #include <linux/netpoll.h>
 #include <net/sch_generic.h>
+#include <linux/types.h>
 #include <uapi/linux/if_team.h>
 
 struct team_pcpu_stats {
@@ -194,6 +194,18 @@ struct team {
 	bool user_carrier_enabled;
 	bool queue_override_enabled;
 	struct list_head *qom_lists; /* array of queue override mapping lists */
+	struct {
+		unsigned int count;
+		unsigned int interval; /* in ms */
+		atomic_t count_pending;
+		struct delayed_work dw;
+	} notify_peers;
+	struct {
+		unsigned int count;
+		unsigned int interval; /* in ms */
+		atomic_t count_pending;
+		struct delayed_work dw;
+	} mcast_rejoin;
 	long mode_priv[TEAM_MODE_PRIV_LONGS];
 };
 
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index e3362b5..f47550d 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -129,6 +129,5 @@ extern void ip_mc_unmap(struct in_device *);
 extern void ip_mc_remap(struct in_device *);
 extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
 extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
-extern void ip_mc_rejoin_groups(struct in_device *in_dev);
 
 #endif
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index 72b2694..e51f654 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -17,6 +17,8 @@
 #include <linux/iio/trigger.h>
 #include <linux/bitops.h>
 
+#include <linux/platform_data/st_sensors_pdata.h>
+
 #define ST_SENSORS_TX_MAX_LENGTH		2
 #define ST_SENSORS_RX_MAX_LENGTH		6
 
@@ -118,14 +120,16 @@ struct st_sensor_bdu {
 /**
  * struct st_sensor_data_ready_irq - ST sensor device data-ready interrupt
  * @addr: address of the register.
- * @mask: mask to write the on/off value.
+ * @mask_int1: mask to enable/disable IRQ on INT1 pin.
+ * @mask_int2: mask to enable/disable IRQ on INT2 pin.
  * struct ig1 - represents the Interrupt Generator 1 of sensors.
  * @en_addr: address of the enable ig1 register.
  * @en_mask: mask to write the on/off value for enable.
  */
 struct st_sensor_data_ready_irq {
 	u8 addr;
-	u8 mask;
+	u8 mask_int1;
+	u8 mask_int2;
 	struct {
 		u8 en_addr;
 		u8 en_mask;
@@ -201,6 +205,7 @@ struct st_sensors {
  * @buffer_data: Data used by buffer part.
  * @odr: Output data rate of the sensor [Hz].
  * num_data_channels: Number of data channels used in buffer.
+ * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
  * @get_irq_data_ready: Function to get the IRQ used for data ready signal.
  * @tf: Transfer function structure used by I/O operations.
  * @tb: Transfer buffers and mutex used by I/O operations.
@@ -219,6 +224,8 @@ struct st_sensor_data {
 	unsigned int odr;
 	unsigned int num_data_channels;
 
+	u8 drdy_int_pin;
+
 	unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev);
 
 	const struct st_sensor_transfer_function *tf;
@@ -249,7 +256,8 @@ static inline void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
 }
 #endif
 
-int st_sensors_init_sensor(struct iio_dev *indio_dev);
+int st_sensors_init_sensor(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata);
 
 int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable);
 
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 3d35b70..09ebe0a 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -532,6 +532,31 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv)
 void iio_device_free(struct iio_dev *indio_dev);
 
 /**
+ * devm_iio_device_alloc - Resource-managed iio_device_alloc()
+ * @dev: 		Device to allocate iio_dev for
+ * @sizeof_priv: 	Space to allocate for private structure.
+ *
+ * Managed iio_device_alloc.  iio_dev allocated with this function is
+ * automatically freed on driver detach.
+ *
+ * If an iio_dev allocated with this function needs to be freed separately,
+ * devm_iio_device_free() must be used.
+ *
+ * RETURNS:
+ * Pointer to allocated iio_dev on success, NULL on failure.
+ */
+struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv);
+
+/**
+ * devm_iio_device_free - Resource-managed iio_device_free()
+ * @dev:		Device this iio_dev belongs to
+ * @indio_dev: 		the iio_dev associated with the device
+ *
+ * Free iio_dev allocated with devm_iio_device_alloc().
+ */
+void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev);
+
+/**
  * iio_buffer_enabled() - helper function to test if the buffer is enabled
  * @indio_dev:		IIO device structure for device
  **/
diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h
index b7a934b..2958c96 100644
--- a/include/linux/iio/sysfs.h
+++ b/include/linux/iio/sysfs.h
@@ -73,11 +73,6 @@ struct iio_const_attr {
 	    .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)}
 
 /* Generic attributes of onetype or another */
-/**
- * IIO_DEV_ATTR_RESET: resets the device
- **/
-#define IIO_DEV_ATTR_RESET(_store)			\
-	IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0)
 
 /**
  * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency
diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h
index 3869c52..369cf2c 100644
--- a/include/linux/iio/trigger.h
+++ b/include/linux/iio/trigger.h
@@ -8,6 +8,7 @@
  */
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/atomic.h>
 
 #ifndef _IIO_TRIGGER_H_
 #define _IIO_TRIGGER_H_
@@ -61,7 +62,7 @@ struct iio_trigger {
 
 	struct list_head		list;
 	struct list_head		alloc_list;
-	int use_count;
+	atomic_t			use_count;
 
 	struct irq_chip			subirq_chip;
 	int				subirq_base;
diff --git a/include/linux/init.h b/include/linux/init.h
index e73f2b7..f1c27a71 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -153,6 +153,7 @@ extern unsigned int reset_devices;
 void setup_arch(char **);
 void prepare_namespace(void);
 void __init load_default_modules(void);
+int __init init_rootfs(void);
 
 extern void (*late_time_init)(void);
 
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 5fa5afe..1a311e0 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -344,16 +344,6 @@ static inline void enable_irq_lockdep_irqrestore(unsigned int irq, unsigned long
 /* IRQ wakeup (PM) control: */
 extern int irq_set_irq_wake(unsigned int irq, unsigned int on);
 
-static inline int enable_irq_wake(unsigned int irq)
-{
-	return irq_set_irq_wake(irq, 1);
-}
-
-static inline int disable_irq_wake(unsigned int irq)
-{
-	return irq_set_irq_wake(irq, 0);
-}
-
 #else /* !CONFIG_GENERIC_HARDIRQS */
 /*
  * NOTE: non-genirq architectures, if they want to support the lock
@@ -370,16 +360,23 @@ static inline int disable_irq_wake(unsigned int irq)
 						enable_irq(irq)
 # endif
 
-static inline int enable_irq_wake(unsigned int irq)
+/* IRQ wakeup (PM) control: */
+static inline int irq_set_irq_wake(unsigned int irq, unsigned int on)
 {
 	return 0;
 }
 
+#endif /* CONFIG_GENERIC_HARDIRQS */
+
+static inline int enable_irq_wake(unsigned int irq)
+{
+	return irq_set_irq_wake(irq, 1);
+}
+
 static inline int disable_irq_wake(unsigned int irq)
 {
-	return 0;
+	return irq_set_irq_wake(irq, 0);
 }
-#endif /* CONFIG_GENERIC_HARDIRQS */
 
 
 #ifdef CONFIG_IRQ_FORCED_THREADING
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index c4d870b..19c19a5 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -22,7 +22,7 @@ struct ipc_ids {
 	int in_use;
 	unsigned short seq;
 	unsigned short seq_max;
-	struct rw_semaphore rw_mutex;
+	struct rw_semaphore rwsem;
 	struct idr ipcs_idr;
 	int next_id;
 };
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c983ed1..fc669b4 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -38,6 +38,7 @@
 struct device_node;
 struct irq_domain;
 struct of_device_id;
+struct msi_chip;
 
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
@@ -101,6 +102,7 @@ struct irq_domain {
 	/* Optional data */
 	struct device_node *of_node;
 	struct irq_domain_chip_generic *gc;
+	struct msi_chip *msi_chip;
 
 	/* reverse map data. The linear map gets appended to the irq_domain */
 	irq_hw_number_t hwirq_max;
@@ -111,10 +113,11 @@ struct irq_domain {
 };
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
+struct irq_domain *__irq_domain_alloc(struct device_node *of_node, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
 				    const struct irq_domain_ops *ops,
 				    void *host_data);
+void __irq_domain_register(struct irq_domain *domain);
 struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 					 unsigned int size,
 					 unsigned int first_irq,
@@ -126,7 +129,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 					 irq_hw_number_t first_hwirq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data);
-extern struct irq_domain *irq_find_host(struct device_node *node);
+struct irq_domain *__irq_find_host(struct device_node *node,
+				   bool findmsi);
 extern void irq_set_default_host(struct irq_domain *host);
 
 /**
@@ -141,14 +145,22 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	struct irq_domain *d;
+	d = __irq_domain_alloc(of_node, size, size, 0, ops, host_data);
+	if (d)
+		__irq_domain_register(d);
+	return d;
 }
 static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
 					 unsigned int max_irq,
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
+	struct irq_domain *d;
+	d = __irq_domain_alloc(of_node, 0, max_irq, max_irq, ops, host_data);
+	if (d)
+		__irq_domain_register(d);
+	return d;
 }
 static inline struct irq_domain *irq_domain_add_legacy_isa(
 				struct device_node *of_node,
@@ -162,7 +174,45 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
+	struct irq_domain *d;
+	d = __irq_domain_alloc(of_node, 0, ~0, 0, ops, host_data);
+	if (d)
+		__irq_domain_register(d);
+	return d;
+}
+static inline struct irq_domain *irq_domain_add_msi(struct device_node *of_node,
+						    unsigned int size,
+						    const struct irq_domain_ops *ops,
+						    struct msi_chip *msi_chip,
+						    void *host_data)
+{
+	struct irq_domain *d;
+	d = __irq_domain_alloc(of_node, size, size, 0, ops, host_data);
+	if (d) {
+		d->msi_chip = msi_chip;
+		__irq_domain_register(d);
+	}
+
+	return d;
+}
+
+
+/**
+ * irq_find_host() - Locates a domain for a given device node
+ * @node: device-tree node of the interrupt controller
+ */
+static inline struct irq_domain *irq_find_host(struct device_node *node)
+{
+	return __irq_find_host(node, false);
+}
+
+/**
+ * irq_find_msi_host() - Locates a MSI domain for a given device node
+ * @node: device-tree node of the interrupt controller
+ */
+static inline struct irq_domain *irq_find_msi_host(struct device_node *node)
+{
+	return __irq_find_host(node, true);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
@@ -195,6 +245,8 @@ static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
 extern unsigned int irq_find_mapping(struct irq_domain *host,
 				     irq_hw_number_t hwirq);
 extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
+extern unsigned int irq_alloc_mapping(struct irq_domain *host,
+				      irq_hw_number_t *hwirq);
 extern int irq_create_strict_mappings(struct irq_domain *domain,
 				      unsigned int irq_base,
 				      irq_hw_number_t hwirq_base, int count);
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 8685d1b..bc3e57d 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -77,7 +77,7 @@ static inline void *jbd_alloc(size_t size, gfp_t flags)
 static inline void jbd_free(void *ptr, size_t size)
 {
 	free_pages((unsigned long)ptr, get_order(size));
-};
+}
 
 #define JFS_MIN_JOURNAL_BLOCKS 1024
 
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 97ba4e7..d235e88 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -101,13 +101,13 @@ static inline u64 get_jiffies_64(void)
 #define time_after(a,b)		\
 	(typecheck(unsigned long, a) && \
 	 typecheck(unsigned long, b) && \
-	 ((long)(b) - (long)(a) < 0))
+	 ((long)((b) - (a)) < 0))
 #define time_before(a,b)	time_after(b,a)
 
 #define time_after_eq(a,b)	\
 	(typecheck(unsigned long, a) && \
 	 typecheck(unsigned long, b) && \
-	 ((long)(a) - (long)(b) >= 0))
+	 ((long)((a) - (b)) >= 0))
 #define time_before_eq(a,b)	time_after_eq(b,a)
 
 /*
@@ -130,13 +130,13 @@ static inline u64 get_jiffies_64(void)
 #define time_after64(a,b)	\
 	(typecheck(__u64, a) &&	\
 	 typecheck(__u64, b) && \
-	 ((__s64)(b) - (__s64)(a) < 0))
+	 ((__s64)((b) - (a)) < 0))
 #define time_before64(a,b)	time_after64(b,a)
 
 #define time_after_eq64(a,b)	\
 	(typecheck(__u64, a) && \
 	 typecheck(__u64, b) && \
-	 ((__s64)(a) - (__s64)(b) >= 0))
+	 ((__s64)((a) - (b)) >= 0))
 #define time_before_eq64(a,b)	time_after_eq64(b,a)
 
 #define time_in_range64(a, b, c) \
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index b7c8cdc..cbfb171 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -36,10 +36,9 @@ struct kbd_struct {
 #define VC_CTRLRLOCK	KG_CTRLR 	/* ctrlr lock mode */
 	unsigned char slockstate; 	/* for `sticky' Shift, Ctrl, etc. */
 
-	unsigned char ledmode:2; 	/* one 2-bit value */
+	unsigned char ledmode:1;
 #define LED_SHOW_FLAGS 0        /* traditional state */
 #define LED_SHOW_IOCTL 1        /* only change leds upon ioctl */
-#define LED_SHOW_MEM 2          /* `heartbeat': peek into memory */
 
 	unsigned char ledflagstate:4;	/* flags, not lights */
 	unsigned char default_ledflagstate:4;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 3bef14c..482ad2d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -629,7 +629,7 @@ extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
 static inline void tracing_start(void) { }
 static inline void tracing_stop(void) { }
 static inline void ftrace_off_permanent(void) { }
-static inline void trace_dump_stack(void) { }
+static inline void trace_dump_stack(int skip) { }
 
 static inline void tracing_on(void) { }
 static inline void tracing_off(void) { }
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 939b112..de6dcbcc 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <linux/atomic.h>
+#include <linux/workqueue.h>
 
 #define UEVENT_HELPER_PATH_LEN		256
 #define UEVENT_NUM_ENVP			32	/* number of env pointers */
@@ -65,6 +66,9 @@ struct kobject {
 	struct kobj_type	*ktype;
 	struct sysfs_dirent	*sd;
 	struct kref		kref;
+#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
+	struct delayed_work	release;
+#endif
 	unsigned int state_initialized:1;
 	unsigned int state_in_sysfs:1;
 	unsigned int state_add_uevent_sent:1;
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index debf208..31c0cd1 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -69,7 +69,7 @@ typedef union ktime ktime_t;		/* Kill this */
  * @secs:	seconds to set
  * @nsecs:	nanoseconds to set
  *
- * Return the ktime_t representation of the value
+ * Return: The ktime_t representation of the value.
  */
 static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
 {
@@ -151,7 +151,7 @@ static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
  * @lhs:	minuend
  * @rhs:	subtrahend
  *
- * Returns the remainder of the subtraction
+ * Return: The remainder of the subtraction.
  */
 static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs)
 {
@@ -169,7 +169,7 @@ static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs)
  * @add1:	addend1
  * @add2:	addend2
  *
- * Returns the sum of @add1 and @add2.
+ * Return: The sum of @add1 and @add2.
  */
 static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
 {
@@ -195,7 +195,7 @@ static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
  * @kt:		addend
  * @nsec:	the scalar nsec value to add
  *
- * Returns the sum of @kt and @nsec in ktime_t format
+ * Return: The sum of @kt and @nsec in ktime_t format.
  */
 extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
 
@@ -204,7 +204,7 @@ extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
  * @kt:		minuend
  * @nsec:	the scalar nsec value to subtract
  *
- * Returns the subtraction of @nsec from @kt in ktime_t format
+ * Return: The subtraction of @nsec from @kt in ktime_t format.
  */
 extern ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec);
 
@@ -212,7 +212,7 @@ extern ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec);
  * timespec_to_ktime - convert a timespec to ktime_t format
  * @ts:		the timespec variable to convert
  *
- * Returns a ktime_t variable with the converted timespec value
+ * Return: A ktime_t variable with the converted timespec value.
  */
 static inline ktime_t timespec_to_ktime(const struct timespec ts)
 {
@@ -224,7 +224,7 @@ static inline ktime_t timespec_to_ktime(const struct timespec ts)
  * timeval_to_ktime - convert a timeval to ktime_t format
  * @tv:		the timeval variable to convert
  *
- * Returns a ktime_t variable with the converted timeval value
+ * Return: A ktime_t variable with the converted timeval value.
  */
 static inline ktime_t timeval_to_ktime(const struct timeval tv)
 {
@@ -237,7 +237,7 @@ static inline ktime_t timeval_to_ktime(const struct timeval tv)
  * ktime_to_timespec - convert a ktime_t variable to timespec format
  * @kt:		the ktime_t variable to convert
  *
- * Returns the timespec representation of the ktime value
+ * Return: The timespec representation of the ktime value.
  */
 static inline struct timespec ktime_to_timespec(const ktime_t kt)
 {
@@ -249,7 +249,7 @@ static inline struct timespec ktime_to_timespec(const ktime_t kt)
  * ktime_to_timeval - convert a ktime_t variable to timeval format
  * @kt:		the ktime_t variable to convert
  *
- * Returns the timeval representation of the ktime value
+ * Return: The timeval representation of the ktime value.
  */
 static inline struct timeval ktime_to_timeval(const ktime_t kt)
 {
@@ -262,7 +262,7 @@ static inline struct timeval ktime_to_timeval(const ktime_t kt)
  * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
  * @kt:		the ktime_t variable to convert
  *
- * Returns the scalar nanoseconds representation of @kt
+ * Return: The scalar nanoseconds representation of @kt.
  */
 static inline s64 ktime_to_ns(const ktime_t kt)
 {
@@ -276,7 +276,9 @@ static inline s64 ktime_to_ns(const ktime_t kt)
  * @cmp1:	comparable1
  * @cmp2:	comparable2
  *
- * Compare two ktime_t variables, returns 1 if equal
+ * Compare two ktime_t variables.
+ *
+ * Return: 1 if equal.
  */
 static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
 {
@@ -288,7 +290,7 @@ static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
  * @cmp1:	comparable1
  * @cmp2:	comparable2
  *
- * Returns ...
+ * Return: ...
  *   cmp1  < cmp2: return <0
  *   cmp1 == cmp2: return 0
  *   cmp1  > cmp2: return >0
@@ -342,7 +344,7 @@ extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs);
  * @kt:		the ktime_t variable to convert
  * @ts:		the timespec variable to store the result in
  *
- * Returns true if there was a successful conversion, false if kt was 0.
+ * Return: %true if there was a successful conversion, %false if kt was 0.
  */
 static inline __must_check bool ktime_to_timespec_cond(const ktime_t kt,
 						       struct timespec *ts)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a63d83e..ca645a0 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -85,6 +85,12 @@ static inline bool is_noslot_pfn(pfn_t pfn)
 	return pfn == KVM_PFN_NOSLOT;
 }
 
+/*
+ * architectures with KVM_HVA_ERR_BAD other than PAGE_OFFSET (e.g. s390)
+ * provide own defines and kvm_is_error_hva
+ */
+#ifndef KVM_HVA_ERR_BAD
+
 #define KVM_HVA_ERR_BAD		(PAGE_OFFSET)
 #define KVM_HVA_ERR_RO_BAD	(PAGE_OFFSET + PAGE_SIZE)
 
@@ -93,6 +99,8 @@ static inline bool kvm_is_error_hva(unsigned long addr)
 	return addr >= PAGE_OFFSET;
 }
 
+#endif
+
 #define KVM_ERR_PTR_BAD_PAGE	(ERR_PTR(-ENOENT))
 
 static inline bool is_error_page(struct page *page)
@@ -160,8 +168,12 @@ enum kvm_bus {
 
 int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		     int len, const void *val);
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long cookie);
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
 		    void *val);
+int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			   int len, void *val, long cookie);
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 			    int len, struct kvm_io_device *dev);
 int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
@@ -499,6 +511,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
 			   struct kvm_memory_slot *dont);
 int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages);
+void kvm_arch_memslots_updated(struct kvm *kvm);
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				struct kvm_memory_slot *memslot,
 				struct kvm_userspace_memory_region *mem,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 4ea55bb..283d66b 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -138,6 +138,22 @@ enum {
 	ATA_SHT_THIS_ID		= -1,
 	ATA_SHT_USE_CLUSTERING	= 1,
 
+	/* struct ata_taskfile flags */
+	ATA_TFLAG_LBA48		= (1 << 0), /* enable 48-bit LBA and "HOB" */
+	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
+	ATA_TFLAG_DEVICE	= (1 << 2), /* enable r/w to device reg */
+	ATA_TFLAG_WRITE		= (1 << 3), /* data dir: host->dev==1 (write) */
+	ATA_TFLAG_LBA		= (1 << 4), /* enable LBA */
+	ATA_TFLAG_FUA		= (1 << 5), /* enable FUA */
+	ATA_TFLAG_POLLING	= (1 << 6), /* set nIEN to 1 and use polling */
+
+	/* protocol flags */
+	ATA_PROT_FLAG_PIO	= (1 << 0), /* is PIO */
+	ATA_PROT_FLAG_DMA	= (1 << 1), /* is DMA */
+	ATA_PROT_FLAG_DATA	= ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA,
+	ATA_PROT_FLAG_NCQ	= (1 << 2), /* is NCQ */
+	ATA_PROT_FLAG_ATAPI	= (1 << 3), /* is ATAPI */
+
 	/* struct ata_device stuff */
 	ATA_DFLAG_LBA		= (1 << 0), /* device supports LBA */
 	ATA_DFLAG_LBA48		= (1 << 1), /* device supports LBA48 */
@@ -518,6 +534,29 @@ enum sw_activity {
 	BLINK_OFF,
 };
 
+struct ata_taskfile {
+	unsigned long		flags;		/* ATA_TFLAG_xxx */
+	u8			protocol;	/* ATA_PROT_xxx */
+
+	u8			ctl;		/* control reg */
+
+	u8			hob_feature;	/* additional data */
+	u8			hob_nsect;	/* to support LBA48 */
+	u8			hob_lbal;
+	u8			hob_lbam;
+	u8			hob_lbah;
+
+	u8			feature;
+	u8			nsect;
+	u8			lbal;
+	u8			lbam;
+	u8			lbah;
+
+	u8			device;
+
+	u8			command;	/* IO operation */
+};
+
 #ifdef CONFIG_ATA_SFF
 struct ata_ioports {
 	void __iomem		*cmd_addr;
@@ -959,6 +998,69 @@ extern const unsigned long sata_deb_timing_long[];
 extern struct ata_port_operations ata_dummy_port_ops;
 extern const struct ata_port_info ata_dummy_port_info;
 
+/*
+ * protocol tests
+ */
+static inline unsigned int ata_prot_flags(u8 prot)
+{
+	switch (prot) {
+	case ATA_PROT_NODATA:
+		return 0;
+	case ATA_PROT_PIO:
+		return ATA_PROT_FLAG_PIO;
+	case ATA_PROT_DMA:
+		return ATA_PROT_FLAG_DMA;
+	case ATA_PROT_NCQ:
+		return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ;
+	case ATAPI_PROT_NODATA:
+		return ATA_PROT_FLAG_ATAPI;
+	case ATAPI_PROT_PIO:
+		return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO;
+	case ATAPI_PROT_DMA:
+		return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA;
+	}
+	return 0;
+}
+
+static inline int ata_is_atapi(u8 prot)
+{
+	return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI;
+}
+
+static inline int ata_is_nodata(u8 prot)
+{
+	return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA);
+}
+
+static inline int ata_is_pio(u8 prot)
+{
+	return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO;
+}
+
+static inline int ata_is_dma(u8 prot)
+{
+	return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA;
+}
+
+static inline int ata_is_ncq(u8 prot)
+{
+	return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ;
+}
+
+static inline int ata_is_data(u8 prot)
+{
+	return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA;
+}
+
+static inline int is_multi_taskfile(struct ata_taskfile *tf)
+{
+	return (tf->command == ATA_CMD_READ_MULTI) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI) ||
+	       (tf->command == ATA_CMD_READ_MULTI_EXT) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI_EXT) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
+}
+
 static inline const unsigned long *
 sata_ehc_deb_timing(struct ata_eh_context *ehc)
 {
diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h
new file mode 100644
index 0000000..3ce5417
--- /dev/null
+++ b/include/linux/list_lru.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc. and Parallels Inc. All rights reserved.
+ * Authors: David Chinner and Glauber Costa
+ *
+ * Generic LRU infrastructure
+ */
+#ifndef _LRU_LIST_H
+#define _LRU_LIST_H
+
+#include <linux/list.h>
+#include <linux/nodemask.h>
+
+/* list_lru_walk_cb has to always return one of those */
+enum lru_status {
+	LRU_REMOVED,		/* item removed from list */
+	LRU_ROTATE,		/* item referenced, give another pass */
+	LRU_SKIP,		/* item cannot be locked, skip */
+	LRU_RETRY,		/* item not freeable. May drop the lock
+				   internally, but has to return locked. */
+};
+
+struct list_lru_node {
+	spinlock_t		lock;
+	struct list_head	list;
+	/* kept as signed so we can catch imbalance bugs */
+	long			nr_items;
+} ____cacheline_aligned_in_smp;
+
+struct list_lru {
+	struct list_lru_node	*node;
+	nodemask_t		active_nodes;
+};
+
+void list_lru_destroy(struct list_lru *lru);
+int list_lru_init(struct list_lru *lru);
+
+/**
+ * list_lru_add: add an element to the lru list's tail
+ * @list_lru: the lru pointer
+ * @item: the item to be added.
+ *
+ * If the element is already part of a list, this function returns doing
+ * nothing. Therefore the caller does not need to keep state about whether or
+ * not the element already belongs in the list and is allowed to lazy update
+ * it. Note however that this is valid for *a* list, not *this* list. If
+ * the caller organize itself in a way that elements can be in more than
+ * one type of list, it is up to the caller to fully remove the item from
+ * the previous list (with list_lru_del() for instance) before moving it
+ * to @list_lru
+ *
+ * Return value: true if the list was updated, false otherwise
+ */
+bool list_lru_add(struct list_lru *lru, struct list_head *item);
+
+/**
+ * list_lru_del: delete an element to the lru list
+ * @list_lru: the lru pointer
+ * @item: the item to be deleted.
+ *
+ * This function works analogously as list_lru_add in terms of list
+ * manipulation. The comments about an element already pertaining to
+ * a list are also valid for list_lru_del.
+ *
+ * Return value: true if the list was updated, false otherwise
+ */
+bool list_lru_del(struct list_lru *lru, struct list_head *item);
+
+/**
+ * list_lru_count_node: return the number of objects currently held by @lru
+ * @lru: the lru pointer.
+ * @nid: the node id to count from.
+ *
+ * Always return a non-negative number, 0 for empty lists. There is no
+ * guarantee that the list is not updated while the count is being computed.
+ * Callers that want such a guarantee need to provide an outer lock.
+ */
+unsigned long list_lru_count_node(struct list_lru *lru, int nid);
+static inline unsigned long list_lru_count(struct list_lru *lru)
+{
+	long count = 0;
+	int nid;
+
+	for_each_node_mask(nid, lru->active_nodes)
+		count += list_lru_count_node(lru, nid);
+
+	return count;
+}
+
+typedef enum lru_status
+(*list_lru_walk_cb)(struct list_head *item, spinlock_t *lock, void *cb_arg);
+/**
+ * list_lru_walk_node: walk a list_lru, isolating and disposing freeable items.
+ * @lru: the lru pointer.
+ * @nid: the node id to scan from.
+ * @isolate: callback function that is resposible for deciding what to do with
+ *  the item currently being scanned
+ * @cb_arg: opaque type that will be passed to @isolate
+ * @nr_to_walk: how many items to scan.
+ *
+ * This function will scan all elements in a particular list_lru, calling the
+ * @isolate callback for each of those items, along with the current list
+ * spinlock and a caller-provided opaque. The @isolate callback can choose to
+ * drop the lock internally, but *must* return with the lock held. The callback
+ * will return an enum lru_status telling the list_lru infrastructure what to
+ * do with the object being scanned.
+ *
+ * Please note that nr_to_walk does not mean how many objects will be freed,
+ * just how many objects will be scanned.
+ *
+ * Return value: the number of objects effectively removed from the LRU.
+ */
+unsigned long list_lru_walk_node(struct list_lru *lru, int nid,
+				 list_lru_walk_cb isolate, void *cb_arg,
+				 unsigned long *nr_to_walk);
+
+static inline unsigned long
+list_lru_walk(struct list_lru *lru, list_lru_walk_cb isolate,
+	      void *cb_arg, unsigned long nr_to_walk)
+{
+	long isolated = 0;
+	int nid;
+
+	for_each_node_mask(nid, lru->active_nodes) {
+		isolated += list_lru_walk_node(lru, nid, isolate,
+					       cb_arg, &nr_to_walk);
+		if (nr_to_walk <= 0)
+			break;
+	}
+	return isolated;
+}
+#endif /* _LRU_LIST_H */
diff --git a/include/linux/llist.h b/include/linux/llist.h
index cdaa7f0..8828a78 100644
--- a/include/linux/llist.h
+++ b/include/linux/llist.h
@@ -125,6 +125,29 @@ static inline void init_llist_head(struct llist_head *list)
 	     (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))
 
 /**
+ * llist_for_each_entry_safe - iterate over some deleted entries of lock-less list of given type
+ *			       safe against removal of list entry
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @node:	the first entry of deleted list entries.
+ * @member:	the name of the llist_node with the struct.
+ *
+ * In general, some entries of the lock-less list can be traversed
+ * safely only after being removed from list, so start with an entry
+ * instead of list head.
+ *
+ * If being used on entries deleted from lock-less list directly, the
+ * traverse order is from the newest to the oldest added entry.  If
+ * you want to traverse from the oldest to the newest, you must
+ * reverse the order by yourself before traversing.
+ */
+#define llist_for_each_entry_safe(pos, n, node, member)			       \
+	for (pos = llist_entry((node), typeof(*pos), member);		       \
+	     &pos->member != NULL &&					       \
+	        (n = llist_entry(pos->member.next, typeof(*n), member), true); \
+	     pos = n)
+
+/**
  * llist_empty - tests whether a lock-less list is empty
  * @head:	the list to test
  *
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index f1e877b..cfc2f11 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -365,7 +365,7 @@ extern void lockdep_trace_alloc(gfp_t mask);
 
 #define lockdep_recursing(tsk)	((tsk)->lockdep_recursion)
 
-#else /* !LOCKDEP */
+#else /* !CONFIG_LOCKDEP */
 
 static inline void lockdep_off(void)
 {
@@ -479,82 +479,36 @@ static inline void print_irqtrace_events(struct task_struct *curr)
  * on the per lock-class debug mode:
  */
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define spin_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define spin_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
-# else
-#  define spin_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define spin_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, NULL, i)
-# endif
-# define spin_release(l, n, i)			lock_release(l, n, i)
+#ifdef CONFIG_PROVE_LOCKING
+ #define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 2, n, i)
+ #define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 2, n, i)
+ #define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 2, n, i)
 #else
-# define spin_acquire(l, s, t, i)		do { } while (0)
-# define spin_release(l, n, i)			do { } while (0)
+ #define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 1, n, i)
+ #define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 1, n, i)
+ #define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 1, n, i)
 #endif
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define rwlock_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define rwlock_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 2, 2, NULL, i)
-# else
-#  define rwlock_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define rwlock_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 2, 1, NULL, i)
-# endif
-# define rwlock_release(l, n, i)		lock_release(l, n, i)
-#else
-# define rwlock_acquire(l, s, t, i)		do { } while (0)
-# define rwlock_acquire_read(l, s, t, i)	do { } while (0)
-# define rwlock_release(l, n, i)		do { } while (0)
-#endif
+#define spin_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define spin_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
+#define spin_release(l, n, i)			lock_release(l, n, i)
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define mutex_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define mutex_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
-# else
-#  define mutex_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define mutex_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, n, i)
-# endif
-# define mutex_release(l, n, i)			lock_release(l, n, i)
-#else
-# define mutex_acquire(l, s, t, i)		do { } while (0)
-# define mutex_acquire_nest(l, s, t, n, i)	do { } while (0)
-# define mutex_release(l, n, i)			do { } while (0)
-#endif
+#define rwlock_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define rwlock_acquire_read(l, s, t, i)		lock_acquire_shared_recursive(l, s, t, NULL, i)
+#define rwlock_release(l, n, i)			lock_release(l, n, i)
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define rwsem_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
-#  define rwsem_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 1, 2, NULL, i)
-# else
-#  define rwsem_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, n, i)
-#  define rwsem_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 1, 1, NULL, i)
-# endif
+#define mutex_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define mutex_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
+#define mutex_release(l, n, i)			lock_release(l, n, i)
+
+#define rwsem_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
+#define rwsem_acquire_read(l, s, t, i)		lock_acquire_shared(l, s, t, NULL, i)
 # define rwsem_release(l, n, i)			lock_release(l, n, i)
-#else
-# define rwsem_acquire(l, s, t, i)		do { } while (0)
-# define rwsem_acquire_nest(l, s, t, n, i)	do { } while (0)
-# define rwsem_acquire_read(l, s, t, i)		do { } while (0)
-# define rwsem_release(l, n, i)			do { } while (0)
-#endif
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define lock_map_acquire(l)		lock_acquire(l, 0, 0, 0, 2, NULL, _THIS_IP_)
-#  define lock_map_acquire_read(l)	lock_acquire(l, 0, 0, 2, 2, NULL, _THIS_IP_)
-# else
-#  define lock_map_acquire(l)		lock_acquire(l, 0, 0, 0, 1, NULL, _THIS_IP_)
-#  define lock_map_acquire_read(l)	lock_acquire(l, 0, 0, 2, 1, NULL, _THIS_IP_)
-# endif
+#define lock_map_acquire(l)			lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_)
+#define lock_map_acquire_read(l)		lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_)
 # define lock_map_release(l)			lock_release(l, 1, _THIS_IP_)
-#else
-# define lock_map_acquire(l)			do { } while (0)
-# define lock_map_acquire_read(l)		do { } while (0)
-# define lock_map_release(l)			do { } while (0)
-#endif
 
 #ifdef CONFIG_PROVE_LOCKING
 # define might_lock(lock) 						\
diff --git a/include/linux/lz4.h b/include/linux/lz4.h
index d21c13f..4356686 100644
--- a/include/linux/lz4.h
+++ b/include/linux/lz4.h
@@ -67,8 +67,8 @@ int lz4hc_compress(const unsigned char *src, size_t src_len,
  *	note :  Destination buffer must be already allocated.
  *		slightly faster than lz4_decompress_unknownoutputsize()
  */
-int lz4_decompress(const char *src, size_t *src_len, char *dest,
-		size_t actual_dest_len);
+int lz4_decompress(const unsigned char *src, size_t *src_len,
+		unsigned char *dest, size_t actual_dest_len);
 
 /*
  * lz4_decompress_unknownoutputsize()
@@ -82,6 +82,6 @@ int lz4_decompress(const char *src, size_t *src_len, char *dest,
  *		  Error if return (< 0)
  *	note :  Destination buffer must be already allocated.
  */
-int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
-		char *dest, size_t *dest_len);
+int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len,
+		unsigned char *dest, size_t *dest_len);
 #endif
diff --git a/include/linux/mbus.h b/include/linux/mbus.h
index dba482e..345b8c5 100644
--- a/include/linux/mbus.h
+++ b/include/linux/mbus.h
@@ -11,6 +11,8 @@
 #ifndef __LINUX_MBUS_H
 #define __LINUX_MBUS_H
 
+struct resource;
+
 struct mbus_dram_target_info
 {
 	/*
@@ -59,14 +61,18 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void)
 }
 #endif
 
-int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
-				      size_t size, phys_addr_t remap,
-				      unsigned int flags);
-int mvebu_mbus_add_window(const char *devname, phys_addr_t base,
-			  size_t size);
+void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
+void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
+int mvebu_mbus_add_window_remap_by_id(unsigned int target,
+				      unsigned int attribute,
+				      phys_addr_t base, size_t size,
+				      phys_addr_t remap);
+int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
+				phys_addr_t base, size_t size);
 int mvebu_mbus_del_window(phys_addr_t base, size_t size);
 int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base,
 		    size_t mbus_size, phys_addr_t sdram_phys_base,
 		    size_t sdram_size);
+int mvebu_mbus_dt_init(void);
 
 #endif /* __LINUX_MBUS_H */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 7b4d9d7..8a9ed4d 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -41,6 +41,23 @@ struct mem_cgroup_reclaim_cookie {
 	unsigned int generation;
 };
 
+enum mem_cgroup_filter_t {
+	VISIT,		/* visit current node */
+	SKIP,		/* skip the current node and continue traversal */
+	SKIP_TREE,	/* skip the whole subtree and continue traversal */
+};
+
+/*
+ * mem_cgroup_filter_t predicate might instruct mem_cgroup_iter_cond how to
+ * iterate through the hierarchy tree. Each tree element is checked by the
+ * predicate before it is returned by the iterator. If a filter returns
+ * SKIP or SKIP_TREE then the iterator code continues traversal (with the
+ * next node down the hierarchy or the next node that doesn't belong under the
+ * memcg's subtree).
+ */
+typedef enum mem_cgroup_filter_t
+(*mem_cgroup_iter_filter)(struct mem_cgroup *memcg, struct mem_cgroup *root);
+
 #ifdef CONFIG_MEMCG
 /*
  * All "charge" functions with gfp_mask should use GFP_KERNEL or
@@ -108,9 +125,18 @@ mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 extern void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	struct page *oldpage, struct page *newpage, bool migration_ok);
 
-struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *,
-				   struct mem_cgroup *,
-				   struct mem_cgroup_reclaim_cookie *);
+struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
+				   struct mem_cgroup *prev,
+				   struct mem_cgroup_reclaim_cookie *reclaim,
+				   mem_cgroup_iter_filter cond);
+
+static inline struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
+				   struct mem_cgroup *prev,
+				   struct mem_cgroup_reclaim_cookie *reclaim)
+{
+	return mem_cgroup_iter_cond(root, prev, reclaim, NULL);
+}
+
 void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *);
 
 /*
@@ -125,6 +151,48 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
 extern void mem_cgroup_replace_page_cache(struct page *oldpage,
 					struct page *newpage);
 
+/**
+ * mem_cgroup_toggle_oom - toggle the memcg OOM killer for the current task
+ * @new: true to enable, false to disable
+ *
+ * Toggle whether a failed memcg charge should invoke the OOM killer
+ * or just return -ENOMEM.  Returns the previous toggle state.
+ *
+ * NOTE: Any path that enables the OOM killer before charging must
+ *       call mem_cgroup_oom_synchronize() afterward to finalize the
+ *       OOM handling and clean up.
+ */
+static inline bool mem_cgroup_toggle_oom(bool new)
+{
+	bool old;
+
+	old = current->memcg_oom.may_oom;
+	current->memcg_oom.may_oom = new;
+
+	return old;
+}
+
+static inline void mem_cgroup_enable_oom(void)
+{
+	bool old = mem_cgroup_toggle_oom(true);
+
+	WARN_ON(old == true);
+}
+
+static inline void mem_cgroup_disable_oom(void)
+{
+	bool old = mem_cgroup_toggle_oom(false);
+
+	WARN_ON(old == false);
+}
+
+static inline bool task_in_memcg_oom(struct task_struct *p)
+{
+	return p->memcg_oom.in_memcg_oom;
+}
+
+bool mem_cgroup_oom_synchronize(void);
+
 #ifdef CONFIG_MEMCG_SWAP
 extern int do_swap_account;
 #endif
@@ -180,9 +248,9 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
 	mem_cgroup_update_page_stat(page, idx, -1);
 }
 
-unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
-						gfp_t gfp_mask,
-						unsigned long *total_scanned);
+enum mem_cgroup_filter_t
+mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
+		struct mem_cgroup *root);
 
 void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
 static inline void mem_cgroup_count_vm_event(struct mm_struct *mm,
@@ -296,6 +364,14 @@ static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		struct page *oldpage, struct page *newpage, bool migration_ok)
 {
 }
+static inline struct mem_cgroup *
+mem_cgroup_iter_cond(struct mem_cgroup *root,
+		struct mem_cgroup *prev,
+		struct mem_cgroup_reclaim_cookie *reclaim,
+		mem_cgroup_iter_filter cond)
+{
+	return NULL;
+}
 
 static inline struct mem_cgroup *
 mem_cgroup_iter(struct mem_cgroup *root,
@@ -348,6 +424,29 @@ static inline void mem_cgroup_end_update_page_stat(struct page *page,
 {
 }
 
+static inline bool mem_cgroup_toggle_oom(bool new)
+{
+	return false;
+}
+
+static inline void mem_cgroup_enable_oom(void)
+{
+}
+
+static inline void mem_cgroup_disable_oom(void)
+{
+}
+
+static inline bool task_in_memcg_oom(struct task_struct *p)
+{
+	return false;
+}
+
+static inline bool mem_cgroup_oom_synchronize(void)
+{
+	return false;
+}
+
 static inline void mem_cgroup_inc_page_stat(struct page *page,
 					    enum mem_cgroup_page_stat_item idx)
 {
@@ -359,11 +458,11 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
 }
 
 static inline
-unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
-					    gfp_t gfp_mask,
-					    unsigned long *total_scanned)
+enum mem_cgroup_filter_t
+mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
+		struct mem_cgroup *root)
 {
-	return 0;
+	return VISIT;
 }
 
 static inline void mem_cgroup_split_huge_fixup(struct page *head)
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 0d7df39..b2f8977 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -91,7 +91,6 @@ static inline struct mempolicy *mpol_dup(struct mempolicy *pol)
 }
 
 #define vma_policy(vma) ((vma)->vm_policy)
-#define vma_set_policy(vma, pol) ((vma)->vm_policy = (pol))
 
 static inline void mpol_get(struct mempolicy *pol)
 {
@@ -126,6 +125,7 @@ struct shared_policy {
 	spinlock_t lock;
 };
 
+int vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst);
 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
 int mpol_set_shared_policy(struct shared_policy *info,
 				struct vm_area_struct *vma,
@@ -240,7 +240,12 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx)
 }
 
 #define vma_policy(vma) NULL
-#define vma_set_policy(vma, pol) do {} while(0)
+
+static inline int
+vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst)
+{
+	return 0;
+}
 
 static inline void numa_policy_init(void)
 {
diff --git a/include/linux/mfd/arizona/gpio.h b/include/linux/mfd/arizona/gpio.h
new file mode 100644
index 0000000..d2146bb
--- /dev/null
+++ b/include/linux/mfd/arizona/gpio.h
@@ -0,0 +1,96 @@
+/*
+ * GPIO configuration for Arizona devices
+ *
+ * Copyright 2013 Wolfson Microelectronics. PLC.
+ *
+ * Author: Charles Keepax <ckeepax@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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ARIZONA_GPIO_H
+#define _ARIZONA_GPIO_H
+
+#define ARIZONA_GP_FN_TXLRCLK                    0x00
+#define ARIZONA_GP_FN_GPIO                       0x01
+#define ARIZONA_GP_FN_IRQ1                       0x02
+#define ARIZONA_GP_FN_IRQ2                       0x03
+#define ARIZONA_GP_FN_OPCLK                      0x04
+#define ARIZONA_GP_FN_FLL1_OUT                   0x05
+#define ARIZONA_GP_FN_FLL2_OUT                   0x06
+#define ARIZONA_GP_FN_PWM1                       0x08
+#define ARIZONA_GP_FN_PWM2                       0x09
+#define ARIZONA_GP_FN_SYSCLK_UNDERCLOCKED        0x0A
+#define ARIZONA_GP_FN_ASYNCCLK_UNDERCLOCKED      0x0B
+#define ARIZONA_GP_FN_FLL1_LOCK                  0x0C
+#define ARIZONA_GP_FN_FLL2_LOCK                  0x0D
+#define ARIZONA_GP_FN_FLL1_CLOCK_OK              0x0F
+#define ARIZONA_GP_FN_FLL2_CLOCK_OK              0x10
+#define ARIZONA_GP_FN_HEADPHONE_DET              0x12
+#define ARIZONA_GP_FN_MIC_DET                    0x13
+#define ARIZONA_GP_FN_WSEQ_STATUS                0x15
+#define ARIZONA_GP_FN_CIF_ADDRESS_ERROR          0x16
+#define ARIZONA_GP_FN_ASRC1_LOCK                 0x1A
+#define ARIZONA_GP_FN_ASRC2_LOCK                 0x1B
+#define ARIZONA_GP_FN_ASRC_CONFIG_ERROR          0x1C
+#define ARIZONA_GP_FN_DRC1_SIGNAL_DETECT         0x1D
+#define ARIZONA_GP_FN_DRC1_ANTICLIP              0x1E
+#define ARIZONA_GP_FN_DRC1_DECAY                 0x1F
+#define ARIZONA_GP_FN_DRC1_NOISE                 0x20
+#define ARIZONA_GP_FN_DRC1_QUICK_RELEASE         0x21
+#define ARIZONA_GP_FN_DRC2_SIGNAL_DETECT         0x22
+#define ARIZONA_GP_FN_DRC2_ANTICLIP              0x23
+#define ARIZONA_GP_FN_DRC2_DECAY                 0x24
+#define ARIZONA_GP_FN_DRC2_NOISE                 0x25
+#define ARIZONA_GP_FN_DRC2_QUICK_RELEASE         0x26
+#define ARIZONA_GP_FN_MIXER_DROPPED_SAMPLE       0x27
+#define ARIZONA_GP_FN_AIF1_CONFIG_ERROR          0x28
+#define ARIZONA_GP_FN_AIF2_CONFIG_ERROR          0x29
+#define ARIZONA_GP_FN_AIF3_CONFIG_ERROR          0x2A
+#define ARIZONA_GP_FN_SPK_TEMP_SHUTDOWN          0x2B
+#define ARIZONA_GP_FN_SPK_TEMP_WARNING           0x2C
+#define ARIZONA_GP_FN_UNDERCLOCKED               0x2D
+#define ARIZONA_GP_FN_OVERCLOCKED                0x2E
+#define ARIZONA_GP_FN_DSP_IRQ1                   0x35
+#define ARIZONA_GP_FN_DSP_IRQ2                   0x36
+#define ARIZONA_GP_FN_ASYNC_OPCLK                0x3D
+#define ARIZONA_GP_FN_BOOT_DONE                  0x44
+#define ARIZONA_GP_FN_DSP1_RAM_READY             0x45
+#define ARIZONA_GP_FN_SYSCLK_ENA_STATUS          0x4B
+#define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS        0x4C
+
+#define ARIZONA_GPN_DIR                          0x8000  /* GPN_DIR */
+#define ARIZONA_GPN_DIR_MASK                     0x8000  /* GPN_DIR */
+#define ARIZONA_GPN_DIR_SHIFT                        15  /* GPN_DIR */
+#define ARIZONA_GPN_DIR_WIDTH                         1  /* GPN_DIR */
+#define ARIZONA_GPN_PU                           0x4000  /* GPN_PU */
+#define ARIZONA_GPN_PU_MASK                      0x4000  /* GPN_PU */
+#define ARIZONA_GPN_PU_SHIFT                         14  /* GPN_PU */
+#define ARIZONA_GPN_PU_WIDTH                          1  /* GPN_PU */
+#define ARIZONA_GPN_PD                           0x2000  /* GPN_PD */
+#define ARIZONA_GPN_PD_MASK                      0x2000  /* GPN_PD */
+#define ARIZONA_GPN_PD_SHIFT                         13  /* GPN_PD */
+#define ARIZONA_GPN_PD_WIDTH                          1  /* GPN_PD */
+#define ARIZONA_GPN_LVL                          0x0800  /* GPN_LVL */
+#define ARIZONA_GPN_LVL_MASK                     0x0800  /* GPN_LVL */
+#define ARIZONA_GPN_LVL_SHIFT                        11  /* GPN_LVL */
+#define ARIZONA_GPN_LVL_WIDTH                         1  /* GPN_LVL */
+#define ARIZONA_GPN_POL                          0x0400  /* GPN_POL */
+#define ARIZONA_GPN_POL_MASK                     0x0400  /* GPN_POL */
+#define ARIZONA_GPN_POL_SHIFT                        10  /* GPN_POL */
+#define ARIZONA_GPN_POL_WIDTH                         1  /* GPN_POL */
+#define ARIZONA_GPN_OP_CFG                       0x0200  /* GPN_OP_CFG */
+#define ARIZONA_GPN_OP_CFG_MASK                  0x0200  /* GPN_OP_CFG */
+#define ARIZONA_GPN_OP_CFG_SHIFT                      9  /* GPN_OP_CFG */
+#define ARIZONA_GPN_OP_CFG_WIDTH                      1  /* GPN_OP_CFG */
+#define ARIZONA_GPN_DB                           0x0100  /* GPN_DB */
+#define ARIZONA_GPN_DB_MASK                      0x0100  /* GPN_DB */
+#define ARIZONA_GPN_DB_SHIFT                          8  /* GPN_DB */
+#define ARIZONA_GPN_DB_WIDTH                          1  /* GPN_DB */
+#define ARIZONA_GPN_FN_MASK                      0x007F  /* GPN_DB */
+#define ARIZONA_GPN_FN_SHIFT                          0  /* GPN_DB */
+#define ARIZONA_GPN_FN_WIDTH                          7  /* GPN_DB */
+
+#endif
diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h
index a9e8bd1..f682953 100644
--- a/include/linux/mfd/mcp.h
+++ b/include/linux/mfd/mcp.h
@@ -10,6 +10,8 @@
 #ifndef MCP_H
 #define MCP_H
 
+#include <linux/device.h>
+
 struct mcp_ops;
 
 struct mcp {
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 1a8dd7a..cfc678c 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -371,17 +371,15 @@ struct palmas_usb {
 
 	struct extcon_dev edev;
 
-	/* used to set vbus, in atomic path */
-	struct work_struct set_vbus_work;
-
 	int id_otg_irq;
 	int id_irq;
 	int vbus_otg_irq;
 	int vbus_irq;
 
-	int vbus_enable;
-
 	enum palmas_usb_state linkstat;
+	int wakeup;
+	bool enable_vbus_detection;
+	bool enable_id_detection;
 };
 
 #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h
index 4e94dc6..b3ddf98 100644
--- a/include/linux/mfd/samsung/s2mps11.h
+++ b/include/linux/mfd/samsung/s2mps11.h
@@ -167,11 +167,8 @@ enum s2mps11_regulators {
 	S2MPS11_BUCK8,
 	S2MPS11_BUCK9,
 	S2MPS11_BUCK10,
-	S2MPS11_AP_EN32KHZ,
-	S2MPS11_CP_EN32KHZ,
-	S2MPS11_BT_EN32KHZ,
 
-	S2MPS11_REG_MAX,
+	S2MPS11_REGULATOR_MAX,
 };
 
 #define S2MPS11_BUCK_MIN1	600000
@@ -191,7 +188,17 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1)
 #define S2MPS11_RAMP_DELAY	25000		/* uV/us */
 
+
+#define S2MPS11_BUCK2_RAMP_SHIFT	6
+#define S2MPS11_BUCK34_RAMP_SHIFT	4
+#define S2MPS11_BUCK5_RAMP_SHIFT	6
+#define S2MPS11_BUCK16_RAMP_SHIFT	4
+#define S2MPS11_BUCK7810_RAMP_SHIFT	2
+#define S2MPS11_BUCK9_RAMP_SHIFT	0
+#define S2MPS11_BUCK2_RAMP_EN_SHIFT	3
+#define S2MPS11_BUCK3_RAMP_EN_SHIFT	2
+#define S2MPS11_BUCK4_RAMP_EN_SHIFT	1
+#define S2MPS11_BUCK6_RAMP_EN_SHIFT	0
 #define S2MPS11_PMIC_EN_SHIFT	6
-#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3)
 
 #endif /*  __LINUX_MFD_S2MPS11_H */
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 8d73fe2..25f2c61 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -113,11 +113,26 @@
 #define CNTRLREG_8WIRE		CNTRLREG_AFE_CTRL(3)
 #define CNTRLREG_TSCENB		BIT(7)
 
+/* FIFO READ Register */
+#define FIFOREAD_DATA_MASK (0xfff << 0)
+#define FIFOREAD_CHNLID_MASK (0xf << 16)
+
+/* Sequencer Status */
+#define SEQ_STATUS BIT(5)
+
 #define ADC_CLK			3000000
-#define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
 
+/*
+* ADC runs at 3MHz, and it takes
+* 15 cycles to latch one data output.
+* Hence the idle time for ADC to
+* process one sample data would be
+* around 5 micro seconds.
+*/
+#define IDLE_TIMEOUT 5 /* microsec */
+
 #define TSCADC_CELLS		2
 
 struct ti_tscadc_dev {
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 7e7fbce..6dd8893 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -185,6 +185,7 @@
 
 #define TWL6040_GPO_MAX	3
 
+/* TODO: All platform data struct can be removed */
 struct twl6040_codec_data {
 	u16 hs_left_step;
 	u16 hs_right_step;
diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h
index 28af417..88f90cb 100644
--- a/include/linux/mfd/ucb1x00.h
+++ b/include/linux/mfd/ucb1x00.h
@@ -10,6 +10,7 @@
 #ifndef UCB1200_H
 #define UCB1200_H
 
+#include <linux/device.h>
 #include <linux/mfd/mcp.h>
 #include <linux/gpio.h>
 #include <linux/mutex.h>
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index a405d3dc..c407d88 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -55,6 +55,9 @@ extern int migrate_vmas(struct mm_struct *mm,
 extern void migrate_page_copy(struct page *newpage, struct page *page);
 extern int migrate_huge_page_move_mapping(struct address_space *mapping,
 				  struct page *newpage, struct page *page);
+extern int migrate_page_move_mapping(struct address_space *mapping,
+		struct page *newpage, struct page *page,
+		struct buffer_head *head, enum migrate_mode mode);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index bb1c809..cd1fdf7 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -69,6 +69,7 @@ enum {
 	MLX4_CMD_SET_ICM_SIZE	 = 0xffd,
 	/*master notify fw on finish for slave's flr*/
 	MLX4_CMD_INFORM_FLR_DONE = 0x5b,
+	MLX4_CMD_GET_OP_REQ      = 0x59,
 
 	/* TPT commands */
 	MLX4_CMD_SW2HW_MPT	 = 0xd,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 52c23a8..09ef2f4 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -33,6 +33,7 @@
 #ifndef MLX4_DEVICE_H
 #define MLX4_DEVICE_H
 
+#include <linux/if_ether.h>
 #include <linux/pci.h>
 #include <linux/completion.h>
 #include <linux/radix-tree.h>
@@ -207,6 +208,7 @@ enum mlx4_event {
 	MLX4_EVENT_TYPE_CMD		   = 0x0a,
 	MLX4_EVENT_TYPE_VEP_UPDATE	   = 0x19,
 	MLX4_EVENT_TYPE_COMM_CHANNEL	   = 0x18,
+	MLX4_EVENT_TYPE_OP_REQUIRED	   = 0x1a,
 	MLX4_EVENT_TYPE_FATAL_WARNING	   = 0x1b,
 	MLX4_EVENT_TYPE_FLR_EVENT	   = 0x1c,
 	MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT = 0x1d,
@@ -619,7 +621,7 @@ struct mlx4_eth_av {
 	u8		dgid[16];
 	u32		reserved4[2];
 	__be16		vlan;
-	u8		mac[6];
+	u8		mac[ETH_ALEN];
 };
 
 union mlx4_ext_av {
@@ -913,10 +915,10 @@ enum mlx4_net_trans_promisc_mode {
 };
 
 struct mlx4_spec_eth {
-	u8	dst_mac[6];
-	u8	dst_mac_msk[6];
-	u8	src_mac[6];
-	u8	src_mac_msk[6];
+	u8	dst_mac[ETH_ALEN];
+	u8	dst_mac_msk[ETH_ALEN];
+	u8	src_mac[ETH_ALEN];
+	u8	src_mac_msk[ETH_ALEN];
 	u8	ether_type_enable;
 	__be16	ether_type;
 	__be16	vlan_id_msk;
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 262deac..6d35147 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -34,6 +34,7 @@
 #define MLX4_QP_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 #include <linux/mlx4/device.h>
 
@@ -143,7 +144,7 @@ struct mlx4_qp_path {
 	u8			feup;
 	u8			fvl_rx;
 	u8			reserved4[2];
-	u8			dmac[6];
+	u8			dmac[ETH_ALEN];
 };
 
 enum { /* fl */
@@ -318,7 +319,7 @@ struct mlx4_wqe_datagram_seg {
 	__be32			dqpn;
 	__be32			qkey;
 	__be16			vlan;
-	u8			mac[6];
+	u8			mac[ETH_ALEN];
 };
 
 struct mlx4_wqe_lso_seg {
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 2aa258b..611e65e 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -731,9 +731,6 @@ void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev);
 int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db);
 void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db);
 
-typedef void (*health_handler_t)(struct pci_dev *pdev, struct health_buffer __iomem *buf, int size);
-int mlx5_register_health_report_handler(health_handler_t handler);
-void mlx5_unregister_health_report_handler(void);
 const char *mlx5_command_str(int command);
 int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev);
 void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f022460..05cc11d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -170,6 +170,7 @@ extern pgprot_t protection_map[16];
 #define FAULT_FLAG_RETRY_NOWAIT	0x10	/* Don't drop mmap_sem and wait when retrying */
 #define FAULT_FLAG_KILLABLE	0x20	/* The fault task is in SIGKILL killable region */
 #define FAULT_FLAG_TRIED	0x40	/* second try */
+#define FAULT_FLAG_USER		0x80	/* The fault originated in userspace */
 
 /*
  * vm_fault is filled by the the pagefault handler and passed to the vma's
@@ -884,11 +885,12 @@ static inline int page_mapped(struct page *page)
 #define VM_FAULT_NOPAGE	0x0100	/* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED	0x0200	/* ->fault locked the returned page */
 #define VM_FAULT_RETRY	0x0400	/* ->fault blocked, must retry */
+#define VM_FAULT_FALLBACK 0x0800	/* huge page fault failed, fall back to small */
 
 #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
 
 #define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
-			 VM_FAULT_HWPOISON_LARGE)
+			 VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE)
 
 /* Encode hstate index for a hwpoisoned large page */
 #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
@@ -1798,6 +1800,7 @@ enum mf_flags {
 	MF_COUNT_INCREASED = 1 << 0,
 	MF_ACTION_REQUIRED = 1 << 1,
 	MF_MUST_KILL = 1 << 2,
+	MF_SOFT_OFFLINE = 1 << 3,
 };
 extern int memory_failure(unsigned long pfn, int trapno, int flags);
 extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index fb425aa..da8cf5c 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -322,6 +322,7 @@ struct mm_rss_stat {
 	atomic_long_t count[NR_MM_COUNTERS];
 };
 
+struct kioctx_table;
 struct mm_struct {
 	struct vm_area_struct * mmap;		/* list of VMAs */
 	struct rb_root mm_rb;
@@ -382,8 +383,8 @@ struct mm_struct {
 
 	struct core_state *core_state; /* coredumping support */
 #ifdef CONFIG_AIO
-	spinlock_t		ioctx_lock;
-	struct hlist_head	ioctx_list;
+	spinlock_t			ioctx_lock;
+	struct kioctx_table __rcu	*ioctx_table;
 #endif
 #ifdef CONFIG_MM_OWNER
 	/*
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index af4a3b7..dcad2ab 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -352,6 +352,7 @@ struct zone {
 	 * free areas of different sizes
 	 */
 	spinlock_t		lock;
+	int			alloc_batch;
 	int                     all_unreclaimable; /* All pages pinned */
 #if defined CONFIG_COMPACTION || defined CONFIG_CMA
 	/* Set to true when the PG_migrate_skip bits should be cleared */
diff --git a/include/linux/module.h b/include/linux/module.h
index 46f1ea0..504035f 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -97,6 +97,11 @@ extern const struct gtype##_id __mod_##gtype##_table		\
 /* For userspace: you can also call me... */
 #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
 
+/* Soft module dependencies. See man modprobe.d for details.
+ * Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
+ */
+#define MODULE_SOFTDEP(_softdep) MODULE_INFO(softdep, _softdep)
+
 /*
  * The following license idents are currently accepted as indicating free
  * software modules
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 73005f9..b024d5c 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -76,6 +76,6 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
 extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list);
 extern void mark_mounts_for_expiry(struct list_head *mounts);
 
-extern dev_t name_to_dev_t(char *name);
+extern dev_t name_to_dev_t(const char *name);
 
 #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ee66f3a..090ddad 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -51,12 +51,29 @@ struct msi_desc {
 };
 
 /*
- * The arch hook for setup up msi irqs
+ * The arch hooks to setup up msi irqs. Those functions are
+ * implemented as weak symbols so that they /can/ be overriden by
+ * architecture specific code if needed.
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
 int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
+void arch_restore_msi_irqs(struct pci_dev *dev, int irq);
+
+void default_teardown_msi_irqs(struct pci_dev *dev);
+void default_restore_msi_irqs(struct pci_dev *dev, int irq);
+
+struct msi_chip {
+	struct module *owner;
+	struct device *dev;
+
+	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
+			 struct msi_desc *desc);
+	void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
+	int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
+			    int nvec, int type);
+};
 
 #endif /* LINUX_MSI_H */
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 211ff67..95fc482 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -93,8 +93,6 @@ struct nand_bbt_descr {
 #define NAND_BBT_CREATE_EMPTY	0x00000400
 /* Search good / bad pattern through all pages of a block */
 #define NAND_BBT_SCANALLPAGES	0x00000800
-/* Scan block empty during good / bad block scan */
-#define NAND_BBT_SCANEMPTY	0x00001000
 /* Write bbt if neccecary */
 #define NAND_BBT_WRITE		0x00002000
 /* Read and write back block contents when writing bbt */
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index d6ed61e..c8be32e 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -137,6 +137,7 @@ enum access_mode {
 
 /**
  * fsmc_nand_platform_data - platform specific NAND controller config
+ * @nand_timings: timing setup for the physical NAND interface
  * @partitions: partition table for the platform, use a default fallback
  * if this is NULL
  * @nr_partitions: the number of partitions in the previous entry
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ab63634..ac8e89d 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -56,7 +56,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
  * is supported now. If you add a chip with bigger oobsize/page
  * adjust this accordingly.
  */
-#define NAND_MAX_OOBSIZE	640
+#define NAND_MAX_OOBSIZE	744
 #define NAND_MAX_PAGESIZE	8192
 
 /*
@@ -202,6 +202,10 @@ typedef enum {
 /* Keep gcc happy */
 struct nand_chip;
 
+/* ONFI features */
+#define ONFI_FEATURE_16_BIT_BUS		(1 << 0)
+#define ONFI_FEATURE_EXT_PARAM_PAGE	(1 << 7)
+
 /* ONFI timing mode, used in both asynchronous and synchronous mode */
 #define ONFI_TIMING_MODE_0		(1 << 0)
 #define ONFI_TIMING_MODE_1		(1 << 1)
@@ -217,6 +221,9 @@ struct nand_chip;
 /* ONFI subfeature parameters length */
 #define ONFI_SUBFEATURE_PARAM_LEN	4
 
+/* ONFI optional commands SET/GET FEATURES supported? */
+#define ONFI_OPT_CMD_SET_GET_FEATURES	(1 << 2)
+
 struct nand_onfi_params {
 	/* rev info and features block */
 	/* 'O' 'N' 'F' 'I'  */
@@ -224,7 +231,10 @@ struct nand_onfi_params {
 	__le16 revision;
 	__le16 features;
 	__le16 opt_cmd;
-	u8 reserved[22];
+	u8 reserved0[2];
+	__le16 ext_param_page_length; /* since ONFI 2.1 */
+	u8 num_of_param_pages;        /* since ONFI 2.1 */
+	u8 reserved1[17];
 
 	/* manufacturer information block */
 	char manufacturer[12];
@@ -281,6 +291,40 @@ struct nand_onfi_params {
 
 #define ONFI_CRC_BASE	0x4F4E
 
+/* Extended ECC information Block Definition (since ONFI 2.1) */
+struct onfi_ext_ecc_info {
+	u8 ecc_bits;
+	u8 codeword_size;
+	__le16 bb_per_lun;
+	__le16 block_endurance;
+	u8 reserved[2];
+} __packed;
+
+#define ONFI_SECTION_TYPE_0	0	/* Unused section. */
+#define ONFI_SECTION_TYPE_1	1	/* for additional sections. */
+#define ONFI_SECTION_TYPE_2	2	/* for ECC information. */
+struct onfi_ext_section {
+	u8 type;
+	u8 length;
+} __packed;
+
+#define ONFI_EXT_SECTION_MAX 8
+
+/* Extended Parameter Page Definition (since ONFI 2.1) */
+struct onfi_ext_param_page {
+	__le16 crc;
+	u8 sig[4];             /* 'E' 'P' 'P' 'S' */
+	u8 reserved0[10];
+	struct onfi_ext_section sections[ONFI_EXT_SECTION_MAX];
+
+	/*
+	 * The actual size of the Extended Parameter Page is in
+	 * @ext_param_page_length of nand_onfi_params{}.
+	 * The following are the variable length sections.
+	 * So we do not add any fields below. Please see the ONFI spec.
+	 */
+} __packed;
+
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
@@ -390,8 +434,8 @@ struct nand_buffers {
  * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
  * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
  * @select_chip:	[REPLACEABLE] select chip nr
- * @block_bad:		[REPLACEABLE] check, if the block is bad
- * @block_markbad:	[REPLACEABLE] mark the block bad
+ * @block_bad:		[REPLACEABLE] check if a block is bad, using OOB markers
+ * @block_markbad:	[REPLACEABLE] mark a block bad
  * @cmd_ctrl:		[BOARDSPECIFIC] hardwarespecific function for controlling
  *			ALE/CLE/nCE. Also used to write command and address
  * @init_size:		[BOARDSPECIFIC] hardwarespecific function for setting
@@ -434,6 +478,12 @@ struct nand_buffers {
  *			bad block marker position; i.e., BBM == 11110111b is
  *			not bad when badblockbits == 7
  * @cellinfo:		[INTERN] MLC/multichip data from chip ident
+ * @ecc_strength_ds:	[INTERN] ECC correctability from the datasheet.
+ *			Minimum amount of bit errors per @ecc_step_ds guaranteed
+ *			to be correctable. If unknown, set to zero.
+ * @ecc_step_ds:	[INTERN] ECC step required by the @ecc_strength_ds,
+ *                      also from the datasheet. It is the recommended ECC step
+ *			size, if known; if unknown, set to zero.
  * @numchips:		[INTERN] number of physical chips
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
@@ -510,6 +560,8 @@ struct nand_chip {
 	unsigned int pagebuf_bitflips;
 	int subpagesize;
 	uint8_t cellinfo;
+	uint16_t ecc_strength_ds;
+	uint16_t ecc_step_ds;
 	int badblockpos;
 	int badblockbits;
 
@@ -576,6 +628,11 @@ struct nand_chip {
 	{ .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \
 	  .options = (opts) }
 
+#define NAND_ECC_INFO(_strength, _step)	\
+			{ .strength_ds = (_strength), .step_ds = (_step) }
+#define NAND_ECC_STRENGTH(type)		((type)->ecc.strength_ds)
+#define NAND_ECC_STEP(type)		((type)->ecc.step_ds)
+
 /**
  * struct nand_flash_dev - NAND Flash Device ID Structure
  * @name: a human-readable name of the NAND chip
@@ -593,6 +650,12 @@ struct nand_chip {
  * @options: stores various chip bit options
  * @id_len: The valid length of the @id.
  * @oobsize: OOB size
+ * @ecc.strength_ds: The ECC correctability from the datasheet, same as the
+ *                   @ecc_strength_ds in nand_chip{}.
+ * @ecc.step_ds: The ECC step required by the @ecc.strength_ds, same as the
+ *               @ecc_step_ds in nand_chip{}, also from the datasheet.
+ *               For example, the "4bit ECC for each 512Byte" can be set with
+ *               NAND_ECC_INFO(4, 512).
  */
 struct nand_flash_dev {
 	char *name;
@@ -609,6 +672,10 @@ struct nand_flash_dev {
 	unsigned int options;
 	uint16_t id_len;
 	uint16_t oobsize;
+	struct {
+		uint16_t strength_ds;
+		uint16_t step_ds;
+	} ecc;
 };
 
 /**
@@ -625,8 +692,8 @@ extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
 extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
 extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 			   int allowbbt);
@@ -708,6 +775,12 @@ struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
 	return chip->priv;
 }
 
+/* return the supported features. */
+static inline int onfi_feature(struct nand_chip *chip)
+{
+	return chip->onfi_version ? le16_to_cpu(chip->onfi_params.features) : 0;
+}
+
 /* return the supported asynchronous timing mode. */
 static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
 {
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 6e8215b..61a0da3 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -6,6 +6,7 @@
 #define __LINUX_MV643XX_ETH_H
 
 #include <linux/mbus.h>
+#include <linux/if_ether.h>
 
 #define MV643XX_ETH_SHARED_NAME		"mv643xx_eth"
 #define MV643XX_ETH_NAME		"mv643xx_eth_port"
@@ -48,7 +49,7 @@ struct mv643xx_eth_platform_data {
 	 * Use this MAC address if it is valid, overriding the
 	 * address that is already in the hardware.
 	 */
-	u8			mac_addr[6];
+	u8			mac_addr[ETH_ALEN];
 
 	/*
 	 * If speed is 0, autonegotiation is enabled.
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9a41568..077363d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -728,6 +728,16 @@ struct netdev_fcoe_hbainfo {
 };
 #endif
 
+#define MAX_PHYS_PORT_ID_LEN 32
+
+/* This structure holds a unique identifier to identify the
+ * physical port used by a netdevice.
+ */
+struct netdev_phys_port_id {
+	unsigned char id[MAX_PHYS_PORT_ID_LEN];
+	unsigned char id_len;
+};
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -932,6 +942,12 @@ struct netdev_fcoe_hbainfo {
  *	that determine carrier state from physical hardware properties (eg
  *	network cables) or protocol-dependent mechanisms (eg
  *	USB_CDC_NOTIFY_NETWORK_CONNECTION) should NOT implement this function.
+ *
+ * int (*ndo_get_phys_port_id)(struct net_device *dev,
+ *			       struct netdev_phys_port_id *ppid);
+ *	Called to get ID of physical port of this device. If driver does
+ *	not implement this, it is assumed that the hw is not able to have
+ *	multiple net devices on single physical port.
  */
 struct net_device_ops {
 	int			(*ndo_init)(struct net_device *dev);
@@ -1060,6 +1076,8 @@ struct net_device_ops {
 						      struct nlmsghdr *nlh);
 	int			(*ndo_change_carrier)(struct net_device *dev,
 						      bool new_carrier);
+	int			(*ndo_get_phys_port_id)(struct net_device *dev,
+							struct netdev_phys_port_id *ppid);
 };
 
 /*
@@ -1633,6 +1651,7 @@ struct packet_offload {
 #define NETDEV_NOTIFY_PEERS	0x0013
 #define NETDEV_JOIN		0x0014
 #define NETDEV_CHANGEUPPER	0x0015
+#define NETDEV_RESEND_IGMP	0x0016
 
 extern int register_netdevice_notifier(struct notifier_block *nb);
 extern int unregister_netdevice_notifier(struct notifier_block *nb);
@@ -1665,9 +1684,6 @@ extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 
 extern rwlock_t				dev_base_lock;		/* Device list lock */
 
-extern seqcount_t	devnet_rename_seq;	/* Device rename seq */
-
-
 #define for_each_netdev(net, d)		\
 		list_for_each_entry(d, &(net)->dev_base_head, dev_list)
 #define for_each_netdev_reverse(net, d)	\
@@ -2317,6 +2333,8 @@ extern int		dev_set_mac_address(struct net_device *,
 					    struct sockaddr *);
 extern int		dev_change_carrier(struct net_device *,
 					   bool new_carrier);
+extern int		dev_get_phys_port_id(struct net_device *dev,
+					     struct netdev_phys_port_id *ppid);
 extern int		dev_hard_start_xmit(struct sk_buff *skb,
 					    struct net_device *dev,
 					    struct netdev_queue *txq);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 8651574..ddc3e32 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1442,7 +1442,7 @@ struct nfs_rpc_ops {
 	struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);
 	struct nfs_client *
 		(*init_client) (struct nfs_client *, const struct rpc_timeout *,
-				const char *, rpc_authflavor_t);
+				const char *);
 	void	(*free_client) (struct nfs_client *);
 	struct nfs_server *(*create_server)(struct nfs_mount_info *, struct nfs_subversion *);
 	struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *,
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 4e2cbfa..58b9a02 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -98,8 +98,17 @@
 typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t;
 extern nodemask_t _unused_nodemask_arg_;
 
+/*
+ * The inline keyword gives the compiler room to decide to inline, or
+ * not inline a function as it sees best.  However, as these functions
+ * are called in both __init and non-__init functions, if they are not
+ * inlined we will end up with a section mis-match error (of the type of
+ * freeable items not being freed).  So we must use __always_inline here
+ * to fix the problem.  If other functions in the future also end up in
+ * this situation they will also need to be annotated as __always_inline
+ */
 #define node_set(node, dst) __node_set((node), &(dst))
-static inline void __node_set(int node, volatile nodemask_t *dstp)
+static __always_inline void __node_set(int node, volatile nodemask_t *dstp)
 {
 	set_bit(node, dstp->bits);
 }
diff --git a/include/linux/of.h b/include/linux/of.h
index 1fd08ca..90a8811 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -323,12 +323,6 @@ extern int of_detach_node(struct device_node *);
  */
 const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
 			       u32 *pu);
-#define of_property_for_each_u32(np, propname, prop, p, u)	\
-	for (prop = of_find_property(np, propname, NULL),	\
-		p = of_prop_next_u32(prop, NULL, &u);		\
-		p;						\
-		p = of_prop_next_u32(prop, p, &u))
-
 /*
  * struct property *prop;
  * const char *s;
@@ -337,11 +331,6 @@ const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
  *         printk("String value: %s\n", s);
  */
 const char *of_prop_next_string(struct property *prop, const char *cur);
-#define of_property_for_each_string(np, propname, prop, s)	\
-	for (prop = of_find_property(np, propname, NULL),	\
-		s = of_prop_next_string(prop, NULL);		\
-		s;						\
-		s = of_prop_next_string(prop, s))
 
 #else /* CONFIG_OF */
 
@@ -505,12 +494,20 @@ static inline int of_machine_is_compatible(const char *compat)
 	return 0;
 }
 
+static inline const __be32 *of_prop_next_u32(struct property *prop,
+		const __be32 *cur, u32 *pu)
+{
+	return NULL;
+}
+
+static inline const char *of_prop_next_string(struct property *prop,
+		const char *cur)
+{
+	return NULL;
+}
+
 #define of_match_ptr(_ptr)	NULL
 #define of_match_node(_matches, _node)	NULL
-#define of_property_for_each_u32(np, propname, prop, p, u) \
-	while (0)
-#define of_property_for_each_string(np, propname, prop, s) \
-	while (0)
 #endif /* CONFIG_OF */
 
 #ifndef of_node_to_nid
@@ -559,6 +556,18 @@ static inline int of_property_read_u32(const struct device_node *np,
 	return of_property_read_u32_array(np, propname, out_value, 1);
 }
 
+#define of_property_for_each_u32(np, propname, prop, p, u)	\
+	for (prop = of_find_property(np, propname, NULL),	\
+		p = of_prop_next_u32(prop, NULL, &u);		\
+		p;						\
+		p = of_prop_next_u32(prop, p, &u))
+
+#define of_property_for_each_string(np, propname, prop, s)	\
+	for (prop = of_find_property(np, propname, NULL),	\
+		s = of_prop_next_string(prop, NULL);		\
+		s;						\
+		s = of_prop_next_string(prop, s))
+
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE)
 extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
 extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index ed136ad..4a17939 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -106,8 +106,7 @@ extern u64 dt_mem_next_cell(int s, __be32 **cellp);
  * physical addresses.
  */
 #ifdef CONFIG_BLK_DEV_INITRD
-extern void early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end);
+extern void early_init_dt_setup_initrd_arch(u64 start, u64 end);
 #endif
 
 /* Early flat tree scan hooks */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6d53675..f1a5b59 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -228,9 +228,9 @@ PAGEFLAG(OwnerPriv1, owner_priv_1) TESTCLEARFLAG(OwnerPriv1, owner_priv_1)
 TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback)
 PAGEFLAG(MappedToDisk, mappedtodisk)
 
-/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
+/* PG_readahead is only used for reads; PG_reclaim is only for writes */
 PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
-PAGEFLAG(Readahead, reclaim)		/* Reminder to do async read-ahead */
+PAGEFLAG(Readahead, reclaim) TESTCLEARFLAG(Readahead, reclaim)
 
 #ifdef CONFIG_HIGHMEM
 /*
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index e3dea75..e8ca8cf 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -339,6 +339,7 @@ static inline void __clear_page_locked(struct page *page)
 
 static inline int trylock_page(struct page *page)
 {
+	VM_BUG_ON(PageTail(page));
 	return (likely(!test_and_set_bit_lock(PG_locked, &page->flags)));
 }
 
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 1704479..d006f0c 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -47,24 +47,22 @@ void acpi_pci_remove_bus(struct pci_bus *bus);
 
 #ifdef	CONFIG_ACPI_PCI_SLOT
 void acpi_pci_slot_init(void);
-void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle);
+void acpi_pci_slot_enumerate(struct pci_bus *bus);
 void acpi_pci_slot_remove(struct pci_bus *bus);
 #else
 static inline void acpi_pci_slot_init(void) { }
-static inline void acpi_pci_slot_enumerate(struct pci_bus *bus,
-					   acpi_handle handle) { }
+static inline void acpi_pci_slot_enumerate(struct pci_bus *bus) { }
 static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
 #endif
 
 #ifdef	CONFIG_HOTPLUG_PCI_ACPI
 void acpiphp_init(void);
-void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle);
+void acpiphp_enumerate_slots(struct pci_bus *bus);
 void acpiphp_remove_slots(struct pci_bus *bus);
 void acpiphp_check_host_bridge(acpi_handle handle);
 #else
 static inline void acpiphp_init(void) { }
-static inline void acpiphp_enumerate_slots(struct pci_bus *bus,
-					   acpi_handle handle) { }
+static inline void acpiphp_enumerate_slots(struct pci_bus *bus) { }
 static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
 static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
 #endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0fd1f15..fea761e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -183,6 +183,19 @@ enum pci_bus_flags {
 	PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
 };
 
+/* These values come from the PCI Express Spec */
+enum pcie_link_width {
+	PCIE_LNK_WIDTH_RESRV	= 0x00,
+	PCIE_LNK_X1		= 0x01,
+	PCIE_LNK_X2		= 0x02,
+	PCIE_LNK_X4		= 0x04,
+	PCIE_LNK_X8		= 0x08,
+	PCIE_LNK_X12		= 0x0C,
+	PCIE_LNK_X16		= 0x10,
+	PCIE_LNK_X32		= 0x20,
+	PCIE_LNK_WIDTH_UNKNOWN  = 0xFF,
+};
+
 /* Based on the PCI Hotplug Spec, but some values are made up by us */
 enum pci_bus_speed {
 	PCI_SPEED_33MHz			= 0x00,
@@ -433,6 +446,7 @@ struct pci_bus {
 	struct resource busn_res;	/* bus numbers routed to this bus */
 
 	struct pci_ops	*ops;		/* configuration access functions */
+	struct msi_chip	*msi;		/* MSI controller */
 	void		*sysdata;	/* hook for sys-specific extension */
 	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/pci */
 
@@ -921,6 +935,8 @@ int pcie_get_readrq(struct pci_dev *dev);
 int pcie_set_readrq(struct pci_dev *dev, int rq);
 int pcie_get_mps(struct pci_dev *dev);
 int pcie_set_mps(struct pci_dev *dev, int mps);
+int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
+			  enum pcie_link_width *width);
 int __pci_reset_function(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev);
 int pci_reset_function(struct pci_dev *dev);
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index 8db71dc..64e61e0 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -28,19 +28,6 @@
 #ifndef _PCI_HOTPLUG_H
 #define _PCI_HOTPLUG_H
 
-/* These values come from the PCI Express Spec */
-enum pcie_link_width {
-	PCIE_LNK_WIDTH_RESRV	= 0x00,
-	PCIE_LNK_X1		= 0x01,
-	PCIE_LNK_X2		= 0x02,
-	PCIE_LNK_X4		= 0x04,
-	PCIE_LNK_X8		= 0x08,
-	PCIE_LNK_X12		= 0x0C,
-	PCIE_LNK_X16		= 0x10,
-	PCIE_LNK_X32		= 0x20,
-	PCIE_LNK_WIDTH_UNKNOWN  = 0xFF,
-};
-
 /**
  * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
  * @owner: The module owner of this structure
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 3bed2e8..6dec3d6 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1311,6 +1311,8 @@
 #define PCI_DEVICE_ID_IMS_TT128		0x9128
 #define PCI_DEVICE_ID_IMS_TT3D		0x9135
 
+#define PCI_VENDOR_ID_AMCC		0x10e8
+
 #define PCI_VENDOR_ID_INTERG		0x10ea
 #define PCI_DEVICE_ID_INTERG_1682	0x1682
 #define PCI_DEVICE_ID_INTERG_2000	0x2000
@@ -2256,12 +2258,10 @@
 /*
  * ADDI-DATA GmbH communication cards <info@addi-data.com>
  */
-#define PCI_VENDOR_ID_ADDIDATA_OLD             0x10E8
 #define PCI_VENDOR_ID_ADDIDATA                 0x15B8
 #define PCI_DEVICE_ID_ADDIDATA_APCI7500        0x7000
 #define PCI_DEVICE_ID_ADDIDATA_APCI7420        0x7001
 #define PCI_DEVICE_ID_ADDIDATA_APCI7300        0x7002
-#define PCI_DEVICE_ID_ADDIDATA_APCI7800        0x818E
 #define PCI_DEVICE_ID_ADDIDATA_APCI7500_2      0x7009
 #define PCI_DEVICE_ID_ADDIDATA_APCI7420_2      0x700A
 #define PCI_DEVICE_ID_ADDIDATA_APCI7300_2      0x700B
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 6a293b7..cea9f70 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -71,6 +71,10 @@ struct atmel_nand_data {
 	u8		on_flash_bbt;		/* bbt on flash */
 	struct mtd_partition *parts;
 	unsigned int	num_parts;
+	bool		has_dma;		/* support dma transfer */
+
+	/* default is false, only for at32ap7000 chip is true */
+	bool		need_reset_workaround;
 };
 
  /* Serial */
diff --git a/include/linux/platform_data/bd6107.h b/include/linux/platform_data/bd6107.h
new file mode 100644
index 0000000..671d650
--- /dev/null
+++ b/include/linux/platform_data/bd6107.h
@@ -0,0 +1,19 @@
+/*
+ * bd6107.h - Rohm BD6107 LEDs Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __BD6107_H__
+#define __BD6107_H__
+
+struct device;
+
+struct bd6107_platform_data {
+	struct device *fbdev;
+	int reset;			/* Reset GPIO */
+	unsigned int def_value;
+};
+
+#endif
diff --git a/include/linux/platform_data/gpio-em.h b/include/linux/platform_data/gpio-em.h
index 573edfb..7c5a519 100644
--- a/include/linux/platform_data/gpio-em.h
+++ b/include/linux/platform_data/gpio-em.h
@@ -5,6 +5,7 @@ struct gpio_em_config {
 	unsigned int gpio_base;
 	unsigned int irq_base;
 	unsigned int number_of_pins;
+	const char *pctl_name;
 };
 
 #endif /* __GPIO_EM_H__ */
diff --git a/include/linux/platform_data/gpio_backlight.h b/include/linux/platform_data/gpio_backlight.h
new file mode 100644
index 0000000..5ae0d9c
--- /dev/null
+++ b/include/linux/platform_data/gpio_backlight.h
@@ -0,0 +1,21 @@
+/*
+ * gpio_backlight.h - Simple GPIO-controlled backlight
+ *
+ * This program is free software; you can 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 __GPIO_BACKLIGHT_H__
+#define __GPIO_BACKLIGHT_H__
+
+struct device;
+
+struct gpio_backlight_platform_data {
+	struct device *fbdev;
+	int gpio;
+	int def_value;
+	bool active_low;
+	const char *name;
+};
+
+#endif
diff --git a/include/linux/platform_data/leds-lp55xx.h b/include/linux/platform_data/leds-lp55xx.h
index 202e290..51a2ff5 100644
--- a/include/linux/platform_data/leds-lp55xx.h
+++ b/include/linux/platform_data/leds-lp55xx.h
@@ -36,6 +36,13 @@ struct lp55xx_predef_pattern {
 	u8 size_b;
 };
 
+enum lp8501_pwr_sel {
+	LP8501_ALL_VDD,		/* D1~9 are connected to VDD */
+	LP8501_6VDD_3VOUT,	/* D1~6 with VDD, D7~9 with VOUT */
+	LP8501_3VDD_6VOUT,	/* D1~6 with VOUT, D7~9 with VDD */
+	LP8501_ALL_VOUT,	/* D1~9 are connected to VOUT */
+};
+
 /*
  * struct lp55xx_platform_data
  * @led_config        : Configurable led class device
@@ -67,6 +74,9 @@ struct lp55xx_platform_data {
 	/* Predefined pattern data */
 	struct lp55xx_predef_pattern *patterns;
 	unsigned int num_patterns;
+
+	/* LP8501 specific */
+	enum lp8501_pwr_sel pwr_sel;
 };
 
 #endif /* _LEDS_LP55XX_H */
diff --git a/include/linux/platform_data/leds-pca9633.h b/include/linux/platform_data/leds-pca9633.h
index c5bf29b..3c1037a 100644
--- a/include/linux/platform_data/leds-pca9633.h
+++ b/include/linux/platform_data/leds-pca9633.h
@@ -27,9 +27,15 @@ enum pca9633_outdrv {
 	PCA9633_TOTEM_POLE, /* aka push-pull */
 };
 
+enum pca9633_blink_type {
+	PCA9633_SW_BLINK,
+	PCA9633_HW_BLINK,
+};
+
 struct pca9633_platform_data {
 	struct led_platform_data leds;
 	enum pca9633_outdrv outdrv;
+	enum pca9633_blink_type blink_type;
 };
 
 #endif /* __LINUX_PCA9633_H*/
diff --git a/include/linux/platform_data/leds-renesas-tpu.h b/include/linux/platform_data/leds-renesas-tpu.h
deleted file mode 100644
index 0553870..0000000
--- a/include/linux/platform_data/leds-renesas-tpu.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __LEDS_RENESAS_TPU_H__
-#define __LEDS_RENESAS_TPU_H__
-
-struct led_renesas_tpu_config {
-	char *name;
-	unsigned pin_gpio_fn;
-	unsigned pin_gpio;
-	unsigned int channel_offset;
-	unsigned int timer_bit;
-	unsigned int max_brightness;
-	unsigned int refresh_rate;
-};
-
-#endif /* __LEDS_RENESAS_TPU_H__ */
diff --git a/include/linux/platform_data/lv5207lp.h b/include/linux/platform_data/lv5207lp.h
new file mode 100644
index 0000000..7dc4d9a
--- /dev/null
+++ b/include/linux/platform_data/lv5207lp.h
@@ -0,0 +1,19 @@
+/*
+ * lv5207lp.h - Sanyo LV5207LP LEDs Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LV5207LP_H__
+#define __LV5207LP_H__
+
+struct device;
+
+struct lv5207lp_platform_data {
+	struct device *fbdev;
+	unsigned int max_value;
+	unsigned int def_value;
+};
+
+#endif
diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h
index 91648bf..dd11dcd 100644
--- a/include/linux/platform_data/max310x.h
+++ b/include/linux/platform_data/max310x.h
@@ -1,5 +1,5 @@
 /*
- *  Maxim (Dallas) MAX3107/8 serial driver
+ *  Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
  *
  *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
  *
@@ -37,14 +37,13 @@
  * };
  */
 
-#define MAX310X_MAX_UARTS	1
+#define MAX310X_MAX_UARTS	4
 
 /* MAX310X platform data structure */
 struct max310x_pdata {
 	/* Flags global to driver */
-	const u8		driver_flags:2;
+	const u8		driver_flags;
 #define MAX310X_EXT_CLK		(0x00000001)	/* External clock enable */
-#define MAX310X_AUTOSLEEP	(0x00000002)	/* Enable AutoSleep mode */
 	/* Flags global to UART port */
 	const u8		uart_flags[MAX310X_MAX_UARTS];
 #define MAX310X_LOOPBACK	(0x00000001)	/* Loopback mode enable */
@@ -60,8 +59,6 @@ struct max310x_pdata {
 	void (*init)(void);
 	/* Called before finish */
 	void (*exit)(void);
-	/* Suspend callback */
-	void (*suspend)(int do_suspend);
 };
 
 #endif
diff --git a/include/linux/platform_data/omap-abe-twl6040.h b/include/linux/platform_data/omap-abe-twl6040.h
deleted file mode 100644
index 5d298ac..0000000
--- a/include/linux/platform_data/omap-abe-twl6040.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * omap-abe-twl6040.h - ASoC machine driver OMAP4+ devices, header.
- *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
- * All rights reserved.
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#ifndef _OMAP_ABE_TWL6040_H_
-#define _OMAP_ABE_TWL6040_H_
-
-/* To select if only one channel is connected in a stereo port */
-#define ABE_TWL6040_LEFT	(1 << 0)
-#define ABE_TWL6040_RIGHT	(1 << 1)
-
-struct omap_abe_twl6040_data {
-	char *card_name;
-	/* Feature flags for connected audio pins */
-	u8	has_hs;
-	u8	has_hf;
-	bool	has_ep;
-	u8	has_aux;
-	u8	has_vibra;
-	bool	has_dmic;
-	bool	has_hsmic;
-	bool	has_mainmic;
-	bool	has_submic;
-	u8	has_afm;
-	/* Other features */
-	bool	jack_detection;	/* board can detect jack events */
-	int	mclk_freq;	/* MCLK frequency speed for twl6040 */
-};
-
-#endif /* _OMAP_ABE_TWL6040_H_ */
diff --git a/include/linux/platform_data/pinctrl-nomadik.h b/include/linux/platform_data/pinctrl-nomadik.h
index f73b2f0..abf5bed 100644
--- a/include/linux/platform_data/pinctrl-nomadik.h
+++ b/include/linux/platform_data/pinctrl-nomadik.h
@@ -226,30 +226,6 @@ enum nmk_gpio_slpm {
 	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
 };
 
-/* Older deprecated pin config API that should go away soon */
-extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
-extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
-extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-#ifdef CONFIG_PINCTRL_NOMADIK
-extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
-#else
-static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
-{
-	return -ENODEV;
-}
-#endif
-extern int nmk_gpio_get_mode(int gpio);
-
-extern void nmk_gpio_wakeups_suspend(void);
-extern void nmk_gpio_wakeups_resume(void);
-
-extern void nmk_gpio_clocks_enable(void);
-extern void nmk_gpio_clocks_disable(void);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
 /*
  * Platform data to register a block: only the initial gpio/irq number.
  */
diff --git a/include/linux/platform_data/serial-sccnxp.h b/include/linux/platform_data/serial-sccnxp.h
index bdc510d..af0c8c3 100644
--- a/include/linux/platform_data/serial-sccnxp.h
+++ b/include/linux/platform_data/serial-sccnxp.h
@@ -60,7 +60,6 @@
  * };
  *
  * static struct sccnxp_pdata sc2892_info = {
- *	.frequency	= 3686400,
  *	.mctrl_cfg[0]	= MCTRL_SIG(DIR_OP, LINE_OP0),
  *	.mctrl_cfg[1]	= MCTRL_SIG(DIR_OP, LINE_OP1),
  * };
@@ -78,8 +77,6 @@
 
 /* SCCNXP platform data structure */
 struct sccnxp_pdata {
-	/* Frequency (extrenal clock or crystal) */
-	int			frequency;
 	/* Shift for A0 line */
 	const u8		reg_shift;
 	/* Modem control lines configuration */
diff --git a/include/linux/platform_data/st_sensors_pdata.h b/include/linux/platform_data/st_sensors_pdata.h
new file mode 100644
index 0000000..7538391
--- /dev/null
+++ b/include/linux/platform_data/st_sensors_pdata.h
@@ -0,0 +1,24 @@
+/*
+ * STMicroelectronics sensors platform-data driver
+ *
+ * Copyright 2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_SENSORS_PDATA_H
+#define ST_SENSORS_PDATA_H
+
+/**
+ * struct st_sensors_platform_data - Platform data for the ST sensors
+ * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
+ *	Available only for accelerometer and pressure sensors.
+ *	Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet).
+ */
+struct st_sensors_platform_data {
+	u8 drdy_int_pin;
+};
+
+#endif /* ST_SENSORS_PDATA_H */
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
deleted file mode 100644
index 66c673f..0000000
--- a/include/linux/platform_data/tegra_usb.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _TEGRA_USB_H_
-#define _TEGRA_USB_H_
-
-enum tegra_usb_operating_modes {
-	TEGRA_USB_DEVICE,
-	TEGRA_USB_HOST,
-	TEGRA_USB_OTG,
-};
-
-struct tegra_ehci_platform_data {
-	enum tegra_usb_operating_modes operating_mode;
-	/* power down the phy on bus suspend */
-	int power_down_on_bus_suspend;
-	void *phy_config;
-	int vbus_gpio;
-};
-
-#endif /* _TEGRA_USB_H_ */
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index ffc444c..4039407 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -231,6 +231,7 @@ unsigned long radix_tree_next_hole(struct radix_tree_root *root,
 unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
 				unsigned long index, unsigned long max_scan);
 int radix_tree_preload(gfp_t gfp_mask);
+int radix_tree_maybe_preload(gfp_t gfp_mask);
 void radix_tree_init(void);
 void *radix_tree_tag_set(struct radix_tree_root *root,
 			unsigned long index, unsigned int tag);
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index 8dfaa2c..0f42469 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -114,6 +114,11 @@ extern const struct raid6_recov_calls raid6_recov_intx1;
 extern const struct raid6_recov_calls raid6_recov_ssse3;
 extern const struct raid6_recov_calls raid6_recov_avx2;
 
+extern const struct raid6_calls raid6_neonx1;
+extern const struct raid6_calls raid6_neonx2;
+extern const struct raid6_calls raid6_neonx4;
+extern const struct raid6_calls raid6_neonx8;
+
 /* Algorithm list */
 extern const struct raid6_calls * const raid6_algos[];
 extern const struct raid6_recov_calls *const raid6_recov_algos[];
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 69e37c2..753207c 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -25,7 +25,7 @@ extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
 
 extern const struct file_operations ramfs_file_operations;
 extern const struct vm_operations_struct generic_file_vm_ops;
-extern int __init init_rootfs(void);
+extern int __init init_ramfs_fs(void);
 
 int ramfs_fill_super(struct super_block *sb, void *data, int silent);
 
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index 0022c1b..aa870a4 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -68,6 +68,10 @@ extern struct rb_node *rb_prev(const struct rb_node *);
 extern struct rb_node *rb_first(const struct rb_root *);
 extern struct rb_node *rb_last(const struct rb_root *);
 
+/* Postorder iteration - always visit the parent after its children */
+extern struct rb_node *rb_first_postorder(const struct rb_root *);
+extern struct rb_node *rb_next_postorder(const struct rb_node *);
+
 /* Fast replacement of a single node without remove/rebalance/add/rebalance */
 extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
 			    struct rb_root *root);
@@ -81,4 +85,22 @@ static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
 	*rb_link = node;
 }
 
+/**
+ * rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of
+ * given type safe against removal of rb_node entry
+ *
+ * @pos:	the 'type *' to use as a loop cursor.
+ * @n:		another 'type *' to use as temporary storage
+ * @root:	'rb_root *' of the rbtree.
+ * @field:	the name of the rb_node field within 'type'.
+ */
+#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
+	for (pos = rb_entry(rb_first_postorder(root), typeof(*pos), field),\
+		n = rb_entry(rb_next_postorder(&pos->field), \
+			typeof(*pos), field); \
+	     &pos->field; \
+	     pos = n, \
+		n = rb_entry(rb_next_postorder(&pos->field), \
+			typeof(*pos), field))
+
 #endif	/* _LINUX_RBTREE_H */
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index f4b1001..4106721 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -267,8 +267,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
  */
 #define list_first_or_null_rcu(ptr, type, member) \
 	({struct list_head *__ptr = (ptr); \
-	  struct list_head __rcu *__next = list_next_rcu(__ptr); \
-	  likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \
+	  struct list_head *__next = ACCESS_ONCE(__ptr->next); \
+	  likely(__ptr != __next) ? \
+		list_entry_rcu(__next, type, member) : NULL; \
 	})
 
 /**
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 4b14bdc..1aa8d8c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -229,13 +229,9 @@ extern void rcu_irq_exit(void);
 #ifdef CONFIG_RCU_USER_QS
 extern void rcu_user_enter(void);
 extern void rcu_user_exit(void);
-extern void rcu_user_enter_after_irq(void);
-extern void rcu_user_exit_after_irq(void);
 #else
 static inline void rcu_user_enter(void) { }
 static inline void rcu_user_exit(void) { }
-static inline void rcu_user_enter_after_irq(void) { }
-static inline void rcu_user_exit_after_irq(void) { }
 static inline void rcu_user_hooks_switch(struct task_struct *prev,
 					 struct task_struct *next) { }
 #endif /* CONFIG_RCU_USER_QS */
@@ -1015,4 +1011,22 @@ static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
 #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
 
 
+/* Only for use by adaptive-ticks code. */
+#ifdef CONFIG_NO_HZ_FULL_SYSIDLE
+extern bool rcu_sys_is_idle(void);
+extern void rcu_sysidle_force_exit(void);
+#else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
+
+static inline bool rcu_sys_is_idle(void)
+{
+	return false;
+}
+
+static inline void rcu_sysidle_force_exit(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
+
+
 #endif /* __LINUX_RCUPDATE_H */
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 75981d0..bafda87 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -15,6 +15,7 @@
 
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <linux/err.h>
 
 struct module;
 struct device;
@@ -470,6 +471,9 @@ struct regmap_irq {
  * @ack_base:    Base ack address.  If zero then the chip is clear on read.
  * @wake_base:   Base address for wake enables.  If zero unsupported.
  * @irq_reg_stride:  Stride to use for chips where registers are not contiguous.
+ * @init_ack_masked: Ack all masked interrupts once during initalization.
+ * @mask_invert: Inverted mask register: cleared bits are masked out.
+ * @wake_invert: Inverted wake register: cleared bits are wake enabled.
  * @runtime_pm:  Hold a runtime PM lock on the device when accessing it.
  *
  * @num_regs:    Number of registers in each control bank.
@@ -485,9 +489,10 @@ struct regmap_irq_chip {
 	unsigned int ack_base;
 	unsigned int wake_base;
 	unsigned int irq_reg_stride;
-	unsigned int mask_invert;
-	unsigned int wake_invert;
-	bool runtime_pm;
+	bool init_ack_masked:1;
+	bool mask_invert:1;
+	bool wake_invert:1;
+	bool runtime_pm:1;
 
 	int num_regs;
 
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 3a76389..2582e41 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -137,6 +137,10 @@ struct regulator *__must_check devm_regulator_get(struct device *dev,
 					     const char *id);
 struct regulator *__must_check regulator_get_exclusive(struct device *dev,
 						       const char *id);
+struct regulator *__must_check regulator_get_optional(struct device *dev,
+						      const char *id);
+struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
+							   const char *id);
 void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
@@ -217,6 +221,25 @@ devm_regulator_get(struct device *dev, const char *id)
 	return NULL;
 }
 
+static inline struct regulator *__must_check
+regulator_get_exclusive(struct device *dev, const char *id)
+{
+	return NULL;
+}
+
+static inline struct regulator *__must_check
+regulator_get_optional(struct device *dev, const char *id)
+{
+	return NULL;
+}
+
+
+static inline struct regulator *__must_check
+devm_regulator_get_optional(struct device *dev, const char *id)
+{
+	return NULL;
+}
+
 static inline void regulator_put(struct regulator *regulator)
 {
 }
@@ -369,8 +392,11 @@ static inline int regulator_count_voltages(struct regulator *regulator)
 static inline int regulator_set_voltage_tol(struct regulator *regulator,
 					    int new_uV, int tol_uV)
 {
-	return regulator_set_voltage(regulator,
-				     new_uV - tol_uV, new_uV + tol_uV);
+	if (regulator_set_voltage(regulator, new_uV, new_uV + tol_uV) == 0)
+		return 0;
+	else
+		return regulator_set_voltage(regulator,
+					     new_uV - tol_uV, new_uV + tol_uV);
 }
 
 static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 6700cc9..67e13aa 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -40,6 +40,24 @@ enum regulator_status {
 };
 
 /**
+ * Specify a range of voltages for regulator_map_linar_range() and
+ * regulator_list_linear_range().
+ *
+ * @min_uV:  Lowest voltage in range
+ * @max_uV:  Highest voltage in range
+ * @min_sel: Lowest selector for range
+ * @max_sel: Highest selector for range
+ * @uV_step: Step size
+ */
+struct regulator_linear_range {
+	unsigned int min_uV;
+	unsigned int max_uV;
+	unsigned int min_sel;
+	unsigned int max_sel;
+	unsigned int uV_step;
+};
+
+/**
  * struct regulator_ops - regulator operations.
  *
  * @enable: Configure the regulator as enabled.
@@ -223,6 +241,9 @@ struct regulator_desc {
 	unsigned int linear_min_sel;
 	unsigned int ramp_delay;
 
+	const struct regulator_linear_range *linear_ranges;
+	int n_linear_ranges;
+
 	const unsigned int *volt_table;
 
 	unsigned int vsel_reg;
@@ -326,10 +347,14 @@ int regulator_mode_to_status(unsigned int);
 
 int regulator_list_voltage_linear(struct regulator_dev *rdev,
 				  unsigned int selector);
+int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
+					unsigned int selector);
 int regulator_list_voltage_table(struct regulator_dev *rdev,
 				  unsigned int selector);
 int regulator_map_voltage_linear(struct regulator_dev *rdev,
 				  int min_uV, int max_uV);
+int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
+				       int min_uV, int max_uV);
 int regulator_map_voltage_iterate(struct regulator_dev *rdev,
 				  int min_uV, int max_uV);
 int regulator_map_voltage_ascend(struct regulator_dev *rdev,
diff --git a/include/linux/regulator/fan53555.h b/include/linux/regulator/fan53555.h
index 5c45c85..f13880e 100644
--- a/include/linux/regulator/fan53555.h
+++ b/include/linux/regulator/fan53555.h
@@ -11,6 +11,7 @@
  */
 
 #ifndef __FAN53555_H__
+#define __FAN53555_H__
 
 /* VSEL ID */
 enum {
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 36adbc8..999b20c 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -134,6 +134,7 @@ struct regulation_constraints {
 	unsigned always_on:1;	/* regulator never off when system is on */
 	unsigned boot_on:1;	/* bootloader/firmware enabled regulator */
 	unsigned apply_uV:1;	/* apply uV constraint if min == max */
+	unsigned ramp_disable:1; /* disable ramp delay */
 };
 
 /**
diff --git a/include/linux/regulator/max8660.h b/include/linux/regulator/max8660.h
index 9936763..f8a6a48 100644
--- a/include/linux/regulator/max8660.h
+++ b/include/linux/regulator/max8660.h
@@ -39,7 +39,7 @@ enum {
  */
 struct max8660_subdev_data {
 	int				id;
-	char				*name;
+	const char			*name;
 	struct regulator_init_data	*platform_data;
 };
 
diff --git a/include/linux/regulator/pfuze100.h b/include/linux/regulator/pfuze100.h
new file mode 100644
index 0000000..65d550b
--- /dev/null
+++ b/include/linux/regulator/pfuze100.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __LINUX_REG_PFUZE100_H
+#define __LINUX_REG_PFUZE100_H
+
+#define PFUZE100_SW1AB		0
+#define PFUZE100_SW1C		1
+#define PFUZE100_SW2		2
+#define PFUZE100_SW3A		3
+#define PFUZE100_SW3B		4
+#define PFUZE100_SW4		5
+#define PFUZE100_SWBST		6
+#define PFUZE100_VSNVS		7
+#define PFUZE100_VREFDDR	8
+#define PFUZE100_VGEN1		9
+#define PFUZE100_VGEN2		10
+#define PFUZE100_VGEN3		11
+#define PFUZE100_VGEN4		12
+#define PFUZE100_VGEN5		13
+#define PFUZE100_VGEN6		14
+#define PFUZE100_MAX_REGULATOR	15
+
+struct regulator_init_data;
+
+struct pfuze_regulator_platform_data {
+	struct regulator_init_data *init_data[PFUZE100_MAX_REGULATOR];
+};
+
+#endif /* __LINUX_REG_PFUZE100_H */
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index 96a509b..201a697 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -54,7 +54,7 @@ struct res_counter {
 	struct res_counter *parent;
 };
 
-#define RESOURCE_MAX (unsigned long long)LLONG_MAX
+#define RES_COUNTER_MAX ULLONG_MAX
 
 /**
  * Helpers to interact with userspace
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d722490..5e37fa8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -107,14 +107,6 @@ extern unsigned long this_cpu_load(void);
 extern void calc_global_load(unsigned long ticks);
 extern void update_cpu_load_nohz(void);
 
-/* Notifier for when a task gets migrated to a new CPU */
-struct task_migration_notifier {
-	struct task_struct *task;
-	int from_cpu;
-	int to_cpu;
-};
-extern void register_task_migration_notifier(struct notifier_block *n);
-
 extern unsigned long get_parent_ip(unsigned long addr);
 
 extern void dump_cpu_task(int cpu);
@@ -314,6 +306,7 @@ struct nsproxy;
 struct user_namespace;
 
 #ifdef CONFIG_MMU
+extern unsigned long mmap_legacy_base(void);
 extern void arch_pick_mmap_layout(struct mm_struct *mm);
 extern unsigned long
 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
@@ -1034,6 +1027,9 @@ struct task_struct {
 #ifdef CONFIG_SMP
 	struct llist_node wake_entry;
 	int on_cpu;
+	struct task_struct *last_wakee;
+	unsigned long wakee_flips;
+	unsigned long wakee_flip_decay_ts;
 #endif
 	int on_rq;
 
@@ -1398,6 +1394,13 @@ struct task_struct {
 		unsigned long memsw_nr_pages; /* uncharged mem+swap usage */
 	} memcg_batch;
 	unsigned int memcg_kmem_skip_account;
+	struct memcg_oom_info {
+		unsigned int may_oom:1;
+		unsigned int in_memcg_oom:1;
+		unsigned int oom_locked:1;
+		int wakeups;
+		struct mem_cgroup *wait_on_memcg;
+	} memcg_oom;
 #endif
 #ifdef CONFIG_UPROBES
 	struct uprobe_task *utask;
@@ -1532,6 +1535,8 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk)
  * Test if a process is not yet dead (at most zombie state)
  * If pid_alive fails, then pointers within the task structure
  * can be stale and must not be dereferenced.
+ *
+ * Return: 1 if the process is alive. 0 otherwise.
  */
 static inline int pid_alive(struct task_struct *p)
 {
@@ -1543,6 +1548,8 @@ static inline int pid_alive(struct task_struct *p)
  * @tsk: Task structure to be checked.
  *
  * Check if a task structure is the first user space task the kernel created.
+ *
+ * Return: 1 if the task structure is init. 0 otherwise.
  */
 static inline int is_global_init(struct task_struct *tsk)
 {
@@ -1894,6 +1901,8 @@ extern struct task_struct *idle_task(int cpu);
 /**
  * is_idle_task - is the specified task an idle task?
  * @p: the task in question.
+ *
+ * Return: 1 if @p is an idle task. 0 otherwise.
  */
 static inline bool is_idle_task(const struct task_struct *p)
 {
@@ -2168,15 +2177,15 @@ static inline bool thread_group_leader(struct task_struct *p)
  * all we care about is that we have a task with the appropriate
  * pid, we don't actually care if we have the right task.
  */
-static inline int has_group_leader_pid(struct task_struct *p)
+static inline bool has_group_leader_pid(struct task_struct *p)
 {
-	return p->pid == p->tgid;
+	return task_pid(p) == p->signal->leader_pid;
 }
 
 static inline
-int same_thread_group(struct task_struct *p1, struct task_struct *p2)
+bool same_thread_group(struct task_struct *p1, struct task_struct *p2)
 {
-	return p1->tgid == p2->tgid;
+	return p1->signal == p2->signal;
 }
 
 static inline struct task_struct *next_thread(const struct task_struct *p)
diff --git a/include/linux/security.h b/include/linux/security.h
index 7ce53ae..5623a7f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1052,17 +1052,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  * @xfrm_policy_delete_security:
  *	@ctx contains the xfrm_sec_ctx.
  *	Authorize deletion of xp->security.
- * @xfrm_state_alloc_security:
+ * @xfrm_state_alloc:
  *	@x contains the xfrm_state being added to the Security Association
  *	Database by the XFRM system.
  *	@sec_ctx contains the security context information being provided by
  *	the user-level SA generation program (e.g., setkey or racoon).
- *	@secid contains the secid from which to take the mls portion of the context.
  *	Allocate a security structure to the x->security field; the security
  *	field is initialized to NULL when the xfrm_state is allocated. Set the
- *	context to correspond to either sec_ctx or polsec, with the mls portion
- *	taken from secid in the latter case.
- *	Return 0 if operation was successful (memory to allocate, legal context).
+ *	context to correspond to sec_ctx. Return 0 if operation was successful
+ *	(memory to allocate, legal context).
+ * @xfrm_state_alloc_acquire:
+ *	@x contains the xfrm_state being added to the Security Association
+ *	Database by the XFRM system.
+ *	@polsec contains the policy's security context.
+ *	@secid contains the secid from which to take the mls portion of the
+ *	context.
+ *	Allocate a security structure to the x->security field; the security
+ *	field is initialized to NULL when the xfrm_state is allocated. Set the
+ *	context to correspond to secid. Return 0 if operation was successful
+ *	(memory to allocate, legal context).
  * @xfrm_state_free_security:
  *	@x contains the xfrm_state.
  *	Deallocate x->security.
@@ -1492,7 +1500,7 @@ struct security_operations {
 	int (*inode_alloc_security) (struct inode *inode);
 	void (*inode_free_security) (struct inode *inode);
 	int (*inode_init_security) (struct inode *inode, struct inode *dir,
-				    const struct qstr *qstr, char **name,
+				    const struct qstr *qstr, const char **name,
 				    void **value, size_t *len);
 	int (*inode_create) (struct inode *dir,
 			     struct dentry *dentry, umode_t mode);
@@ -1679,9 +1687,11 @@ struct security_operations {
 	int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
 	void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
 	int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
-	int (*xfrm_state_alloc_security) (struct xfrm_state *x,
-		struct xfrm_user_sec_ctx *sec_ctx,
-		u32 secid);
+	int (*xfrm_state_alloc) (struct xfrm_state *x,
+				 struct xfrm_user_sec_ctx *sec_ctx);
+	int (*xfrm_state_alloc_acquire) (struct xfrm_state *x,
+					 struct xfrm_sec_ctx *polsec,
+					 u32 secid);
 	void (*xfrm_state_free_security) (struct xfrm_state *x);
 	int (*xfrm_state_delete_security) (struct xfrm_state *x);
 	int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
@@ -1770,7 +1780,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 				 const struct qstr *qstr,
 				 initxattrs initxattrs, void *fs_data);
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
-				     const struct qstr *qstr, char **name,
+				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len);
 int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode);
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
@@ -2094,8 +2104,8 @@ static inline int security_inode_init_security(struct inode *inode,
 static inline int security_old_inode_init_security(struct inode *inode,
 						   struct inode *dir,
 						   const struct qstr *qstr,
-						   char **name, void **value,
-						   size_t *len)
+						   const char **name,
+						   void **value, size_t *len)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index d340497..dca3c08d 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -11,12 +11,16 @@
 #define SCIx_NOT_SUPPORTED	(-1)
 
 enum {
+	SCBRR_ALGO_INVALID,
+
 	SCBRR_ALGO_1,		/* ((clk + 16 * bps) / (16 * bps) - 1) */
 	SCBRR_ALGO_2,		/* ((clk + 16 * bps) / (32 * bps) - 1) */
 	SCBRR_ALGO_3,		/* (((clk * 2) + 16 * bps) / (16 * bps) - 1) */
 	SCBRR_ALGO_4,		/* (((clk * 2) + 16 * bps) / (32 * bps) - 1) */
 	SCBRR_ALGO_5,		/* (((clk * 1000 / 32) / bps) - 1) */
 	SCBRR_ALGO_6,		/* HSCIF variable sample rate algorithm */
+
+	SCBRR_NR_ALGOS,
 };
 
 #define SCSCR_TIE	(1 << 7)
diff --git a/include/linux/sh_eth.h b/include/linux/sh_eth.h
index fc30571..6205eeb 100644
--- a/include/linux/sh_eth.h
+++ b/include/linux/sh_eth.h
@@ -2,6 +2,7 @@
 #define __ASM_SH_ETH_H__
 
 #include <linux/phy.h>
+#include <linux/if_ether.h>
 
 enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
 enum {
@@ -18,7 +19,7 @@ struct sh_eth_plat_data {
 	phy_interface_t phy_interface;
 	void (*set_mdio_gate)(void *addr);
 
-	unsigned char mac_addr[6];
+	unsigned char mac_addr[ETH_ALEN];
 	unsigned no_ether_link:1;
 	unsigned ether_link_active_low:1;
 	unsigned needs_init:1;
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
index ac6b8ee..68c0970 100644
--- a/include/linux/shrinker.h
+++ b/include/linux/shrinker.h
@@ -4,39 +4,67 @@
 /*
  * This struct is used to pass information from page reclaim to the shrinkers.
  * We consolidate the values for easier extention later.
+ *
+ * The 'gfpmask' refers to the allocation we are currently trying to
+ * fulfil.
  */
 struct shrink_control {
 	gfp_t gfp_mask;
 
-	/* How many slab objects shrinker() should scan and try to reclaim */
+	/*
+	 * How many objects scan_objects should scan and try to reclaim.
+	 * This is reset before every call, so it is safe for callees
+	 * to modify.
+	 */
 	unsigned long nr_to_scan;
+
+	/* shrink from these nodes */
+	nodemask_t nodes_to_scan;
+	/* current node being shrunk (for NUMA aware shrinkers) */
+	int nid;
 };
 
+#define SHRINK_STOP (~0UL)
 /*
  * A callback you can register to apply pressure to ageable caches.
  *
- * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
- * and a 'gfpmask'.  It should look through the least-recently-used
- * 'nr_to_scan' entries and attempt to free them up.  It should return
- * the number of objects which remain in the cache.  If it returns -1, it means
- * it cannot do any scanning at this time (eg. there is a risk of deadlock).
+ * @count_objects should return the number of freeable items in the cache. If
+ * there are no objects to free or the number of freeable items cannot be
+ * determined, it should return 0. No deadlock checks should be done during the
+ * count callback - the shrinker relies on aggregating scan counts that couldn't
+ * be executed due to potential deadlocks to be run at a later call when the
+ * deadlock condition is no longer pending.
  *
- * The 'gfpmask' refers to the allocation we are currently trying to
- * fulfil.
+ * @scan_objects will only be called if @count_objects returned a non-zero
+ * value for the number of freeable objects. The callout should scan the cache
+ * and attempt to free items from the cache. It should then return the number
+ * of objects freed during the scan, or SHRINK_STOP if progress cannot be made
+ * due to potential deadlocks. If SHRINK_STOP is returned, then no further
+ * attempts to call the @scan_objects will be made from the current reclaim
+ * context.
  *
- * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
- * querying the cache size, so a fastpath for that case is appropriate.
+ * @flags determine the shrinker abilities, like numa awareness
  */
 struct shrinker {
-	int (*shrink)(struct shrinker *, struct shrink_control *sc);
+	unsigned long (*count_objects)(struct shrinker *,
+				       struct shrink_control *sc);
+	unsigned long (*scan_objects)(struct shrinker *,
+				      struct shrink_control *sc);
+
 	int seeks;	/* seeks to recreate an obj */
 	long batch;	/* reclaim batch size, 0 = default */
+	unsigned long flags;
 
 	/* These are for internal use */
 	struct list_head list;
-	atomic_long_t nr_in_batch; /* objs pending delete */
+	/* objs pending delete, per node */
+	atomic_long_t *nr_deferred;
 };
 #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
-extern void register_shrinker(struct shrinker *);
+
+/* Flags */
+#define SHRINKER_NUMA_AWARE (1 << 0)
+
+extern int register_shrinker(struct shrinker *);
 extern void unregister_shrinker(struct shrinker *);
 #endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3b71a4e..5ac96f3 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1805,10 +1805,13 @@ static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)
  */
 static inline void skb_orphan(struct sk_buff *skb)
 {
-	if (skb->destructor)
+	if (skb->destructor) {
 		skb->destructor(skb);
-	skb->destructor = NULL;
-	skb->sk		= NULL;
+		skb->destructor = NULL;
+		skb->sk		= NULL;
+	} else {
+		BUG_ON(skb->sk);
+	}
 }
 
 /**
@@ -2356,6 +2359,10 @@ extern int	       skb_copy_datagram_from_iovec(struct sk_buff *skb,
 						    const struct iovec *from,
 						    int from_offset,
 						    int len);
+extern int	       zerocopy_sg_from_iovec(struct sk_buff *skb,
+					      const struct iovec *frm,
+					      int offset,
+					      size_t count);
 extern int	       skb_copy_datagram_const_iovec(const struct sk_buff *from,
 						     int offset,
 						     const struct iovec *to,
diff --git a/include/linux/smp.h b/include/linux/smp.h
index c181399..54c3a72 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -28,6 +28,27 @@ extern unsigned int total_cpus;
 int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
 			     int wait);
 
+/*
+ * Call a function on all processors
+ */
+int on_each_cpu(smp_call_func_t func, void *info, int wait);
+
+/*
+ * Call a function on processors specified by mask, which might include
+ * the local one.
+ */
+void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
+		void *info, bool wait);
+
+/*
+ * Call a function on each processor for which the supplied function
+ * cond_func returns a positive value. This may include the local
+ * processor.
+ */
+void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
+		smp_call_func_t func, void *info, bool wait,
+		gfp_t gfp_flags);
+
 #ifdef CONFIG_SMP
 
 #include <linux/preempt.h>
@@ -95,27 +116,6 @@ static inline void call_function_init(void) { }
 #endif
 
 /*
- * Call a function on all processors
- */
-int on_each_cpu(smp_call_func_t func, void *info, int wait);
-
-/*
- * Call a function on processors specified by mask, which might include
- * the local one.
- */
-void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
-		void *info, bool wait);
-
-/*
- * Call a function on each processor for which the supplied function
- * cond_func returns a positive value. This may include the local
- * processor.
- */
-void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
-		smp_call_func_t func, void *info, bool wait,
-		gfp_t gfp_flags);
-
-/*
  * Mark the boot cpu "online" so that it can call console drivers in
  * printk() and can access its per-cpu storage.
  */
@@ -139,43 +139,12 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
 }
 #define smp_call_function(func, info, wait) \
 			(up_smp_call_function(func, info))
-#define on_each_cpu(func, info, wait)		\
-	({					\
-		unsigned long __flags;		\
-		local_irq_save(__flags);	\
-		func(info);			\
-		local_irq_restore(__flags);	\
-		0;				\
-	})
-/*
- * Note we still need to test the mask even for UP
- * because we actually can get an empty mask from
- * code that on SMP might call us without the local
- * CPU in the mask.
- */
-#define on_each_cpu_mask(mask, func, info, wait) \
-	do {						\
-		if (cpumask_test_cpu(0, (mask))) {	\
-			local_irq_disable();		\
-			(func)(info);			\
-			local_irq_enable();		\
-		}					\
-	} while (0)
-/*
- * Preemption is disabled here to make sure the cond_func is called under the
- * same condtions in UP and SMP.
- */
-#define on_each_cpu_cond(cond_func, func, info, wait, gfp_flags)\
-	do {							\
-		void *__info = (info);				\
-		preempt_disable();				\
-		if ((cond_func)(0, __info)) {			\
-			local_irq_disable();			\
-			(func)(__info);				\
-			local_irq_enable();			\
-		}						\
-		preempt_enable();				\
-	} while (0)
+
+static inline void __smp_call_function_single(int cpuid,
+		struct call_single_data *data, int wait)
+{
+	on_each_cpu(data->func, data->info, wait);
+}
 
 static inline void smp_send_reschedule(int cpu) { }
 #define smp_prepare_boot_cpu()			do {} while (0)
diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h
index 4dde70e..eec3efd 100644
--- a/include/linux/smsc911x.h
+++ b/include/linux/smsc911x.h
@@ -22,6 +22,7 @@
 #define __LINUX_SMSC911X_H__
 
 #include <linux/phy.h>
+#include <linux/if_ether.h>
 
 /* platform_device configuration data, should be assigned to
  * the platform_device's dev.platform_data */
@@ -31,7 +32,7 @@ struct smsc911x_platform_config {
 	unsigned int flags;
 	unsigned int shift;
 	phy_interface_t phy_interface;
-	unsigned char mac[6];
+	unsigned char mac[ETH_ALEN];
 };
 
 /* Constants for platform_device irq polarity configuration */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 230c04b..445ef75 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -313,6 +313,8 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
 					  struct iovec *iov, 
 					  int offset, 
 					  unsigned int len, __wsum *csump);
+extern unsigned long iov_pages(const struct iovec *iov, int offset,
+			       unsigned long nr_segs);
 
 extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode);
 extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 28e440b..8515190 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -233,6 +233,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *	suported. If set, the SPI core will reject any transfer with an
  *	unsupported bits_per_word. If not set, this value is simply ignored,
  *	and it's up to the individual driver to perform any validation.
+ * @min_speed_hz: Lowest supported transfer speed
+ * @max_speed_hz: Highest supported transfer speed
  * @flags: other constraints relevant to this driver
  * @bus_lock_spinlock: spinlock for SPI bus locking
  * @bus_lock_mutex: mutex for SPI bus locking
@@ -254,6 +256,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @busy: message pump is busy
  * @running: message pump is running
  * @rt: whether this queue is set to run as a realtime task
+ * @auto_runtime_pm: the core should ensure a runtime PM reference is held
+ *                   while the hardware is prepared, using the parent
+ *                   device for the spidev
  * @prepare_transfer_hardware: a message will soon arrive from the queue
  *	so the subsystem requests the driver to prepare the transfer hardware
  *	by issuing this call
@@ -309,9 +314,13 @@ struct spi_master {
 	/* bitmask of supported bits_per_word for transfers */
 	u32			bits_per_word_mask;
 #define SPI_BPW_MASK(bits) BIT((bits) - 1)
-#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1))
+#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0U : (BIT(bits) - 1))
 #define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1))
 
+	/* limits on transfer speed */
+	u32			min_speed_hz;
+	u32			max_speed_hz;
+
 	/* other constraints relevant to this driver */
 	u16			flags;
 #define SPI_MASTER_HALF_DUPLEX	BIT(0)		/* can't do full duplex */
@@ -374,11 +383,13 @@ struct spi_master {
 	bool				busy;
 	bool				running;
 	bool				rt;
+	bool				auto_runtime_pm;
 
 	int (*prepare_transfer_hardware)(struct spi_master *master);
 	int (*transfer_one_message)(struct spi_master *master,
 				    struct spi_message *mesg);
 	int (*unprepare_transfer_hardware)(struct spi_master *master);
+
 	/* gpio chip select */
 	int			*cs_gpios;
 };
@@ -578,6 +589,7 @@ struct spi_message {
 	/* completion is reported through a callback */
 	void			(*complete)(void *context);
 	void			*context;
+	unsigned		frame_length;
 	unsigned		actual_length;
 	int			status;
 
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index f987a2b..daebaba 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -4,11 +4,7 @@
 #include <linux/workqueue.h>
 
 struct spi_bitbang {
-	struct workqueue_struct	*workqueue;
-	struct work_struct	work;
-
 	spinlock_t		lock;
-	struct list_head	queue;
 	u8			busy;
 	u8			use_dma;
 	u8			flags;		/* extra spi->mode support */
@@ -41,7 +37,6 @@ struct spi_bitbang {
  */
 extern int spi_bitbang_setup(struct spi_device *spi);
 extern void spi_bitbang_cleanup(struct spi_device *spi);
-extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
 extern int spi_bitbang_setup_transfer(struct spi_device *spi,
 				      struct spi_transfer *t);
 
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 6d87035..1821445 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -121,6 +121,7 @@ struct rpc_task_setup {
 #define RPC_TASK_SOFTCONN	0x0400		/* Fail if can't connect */
 #define RPC_TASK_SENT		0x0800		/* message was sent */
 #define RPC_TASK_TIMEOUT	0x1000		/* fail with ETIMEDOUT on timeout */
+#define RPC_TASK_NOCONNECT	0x2000		/* return ENOTCONN if not connected */
 
 #define RPC_IS_ASYNC(t)		((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SWAPPER(t)	((t)->tk_flags & RPC_TASK_SWAPPER)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index d95cde5..c03c139 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -182,6 +182,33 @@ enum {
 #define SWAP_MAP_SHMEM	0xbf	/* Owned by shmem/tmpfs, in first swap_map */
 
 /*
+ * We use this to track usage of a cluster. A cluster is a block of swap disk
+ * space with SWAPFILE_CLUSTER pages long and naturally aligns in disk. All
+ * free clusters are organized into a list. We fetch an entry from the list to
+ * get a free cluster.
+ *
+ * The data field stores next cluster if the cluster is free or cluster usage
+ * counter otherwise. The flags field determines if a cluster is free. This is
+ * protected by swap_info_struct.lock.
+ */
+struct swap_cluster_info {
+	unsigned int data:24;
+	unsigned int flags:8;
+};
+#define CLUSTER_FLAG_FREE 1 /* This cluster is free */
+#define CLUSTER_FLAG_NEXT_NULL 2 /* This cluster has no next cluster */
+
+/*
+ * We assign a cluster to each CPU, so each CPU can allocate swap entry from
+ * its own cluster and swapout sequentially. The purpose is to optimize swapout
+ * throughput.
+ */
+struct percpu_cluster {
+	struct swap_cluster_info index; /* Current cluster index */
+	unsigned int next; /* Likely next allocation offset */
+};
+
+/*
  * The in-memory structure used to track swap areas.
  */
 struct swap_info_struct {
@@ -191,14 +218,16 @@ struct swap_info_struct {
 	signed char	next;		/* next type on the swap list */
 	unsigned int	max;		/* extent of the swap_map */
 	unsigned char *swap_map;	/* vmalloc'ed array of usage counts */
+	struct swap_cluster_info *cluster_info; /* cluster info. Only for SSD */
+	struct swap_cluster_info free_cluster_head; /* free cluster list head */
+	struct swap_cluster_info free_cluster_tail; /* free cluster list tail */
 	unsigned int lowest_bit;	/* index of first free in swap_map */
 	unsigned int highest_bit;	/* index of last free in swap_map */
 	unsigned int pages;		/* total of usable pages of swap */
 	unsigned int inuse_pages;	/* number of those currently in use */
 	unsigned int cluster_next;	/* likely index for next allocation */
 	unsigned int cluster_nr;	/* countdown to next cluster search */
-	unsigned int lowest_alloc;	/* while preparing discard cluster */
-	unsigned int highest_alloc;	/* while preparing discard cluster */
+	struct percpu_cluster __percpu *percpu_cluster; /* per cpu's swap location */
 	struct swap_extent *curr_swap_extent;
 	struct swap_extent first_swap_extent;
 	struct block_device *bdev;	/* swap device or bdev of swap file */
@@ -212,14 +241,18 @@ struct swap_info_struct {
 					 * protect map scan related fields like
 					 * swap_map, lowest_bit, highest_bit,
 					 * inuse_pages, cluster_next,
-					 * cluster_nr, lowest_alloc and
-					 * highest_alloc. other fields are only
-					 * changed at swapon/swapoff, so are
-					 * protected by swap_lock. changing
-					 * flags need hold this lock and
-					 * swap_lock. If both locks need hold,
-					 * hold swap_lock first.
+					 * cluster_nr, lowest_alloc,
+					 * highest_alloc, free/discard cluster
+					 * list. other fields are only changed
+					 * at swapon/swapoff, so are protected
+					 * by swap_lock. changing flags need
+					 * hold this lock and swap_lock. If
+					 * both locks need hold, hold swap_lock
+					 * first.
 					 */
+	struct work_struct discard_work; /* discard worker */
+	struct swap_cluster_info discard_cluster_head; /* list head of discard clusters */
+	struct swap_cluster_info discard_cluster_tail; /* list tail of discard clusters */
 };
 
 struct swap_list_t {
@@ -414,6 +447,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 
 #else /* CONFIG_SWAP */
 
+#define swap_address_space(entry)		(NULL)
 #define get_nr_swap_pages()			0L
 #define total_swap_pages			0L
 #define total_swapcache_pages()			0UL
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index c5fd30d..8d4fa82 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -67,6 +67,8 @@ static inline swp_entry_t pte_to_swp_entry(pte_t pte)
 	swp_entry_t arch_entry;
 
 	BUG_ON(pte_file(pte));
+	if (pte_swp_soft_dirty(pte))
+		pte = pte_swp_clear_soft_dirty(pte);
 	arch_entry = __pte_to_swp_entry(pte);
 	return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry));
 }
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 4147d70..84662ec 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -802,9 +802,14 @@ asmlinkage long sys_vfork(void);
 asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int,
 	       int __user *);
 #else
+#ifdef CONFIG_CLONE_BACKWARDS3
+asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *,
+			  int __user *, int);
+#else
 asmlinkage long sys_clone(unsigned long, unsigned long, int __user *,
 	       int __user *, int);
 #endif
+#endif
 
 asmlinkage long sys_execve(const char __user *filename,
 		const char __user *const __user *argv,
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 472120b..d686334 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -107,7 +107,6 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
  * only four options will fit in a standard TCP header */
 #define TCP_NUM_SACKS 4
 
-struct tcp_cookie_values;
 struct tcp_request_sock_ops;
 
 struct tcp_request_sock {
@@ -238,6 +237,7 @@ struct tcp_sock {
 
  	u32	rcv_wnd;	/* Current receiver window		*/
 	u32	write_seq;	/* Tail(+1) of data held in tcp send buffer */
+	u32	notsent_lowat;	/* TCP_NOTSENT_LOWAT */
 	u32	pushed_seq;	/* Last pushed seq, required to talk to windows */
 	u32	lost_out;	/* Lost packets			*/
 	u32	sacked_out;	/* SACK'd packets			*/
diff --git a/include/linux/time-armada-370-xp.h b/include/linux/time-armada-370-xp.h
index dfdfdc0..6fb0856 100644
--- a/include/linux/time-armada-370-xp.h
+++ b/include/linux/time-armada-370-xp.h
@@ -11,8 +11,6 @@
 #ifndef __TIME_ARMADA_370_XPPRCMU_H
 #define __TIME_ARMADA_370_XPPRCMU_H
 
-#include <linux/init.h>
-
-void __init armada_370_xp_timer_init(void);
+void armada_370_xp_timer_init(void);
 
 #endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 01ac30e..64f8646 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -10,6 +10,8 @@
 #include <linux/mutex.h>
 #include <linux/tty_flags.h>
 #include <uapi/linux/tty.h>
+#include <linux/rwsem.h>
+#include <linux/llist.h>
 
 
 
@@ -29,9 +31,10 @@
 #define __DISABLED_CHAR '\0'
 
 struct tty_buffer {
-	struct tty_buffer *next;
-	char *char_buf_ptr;
-	unsigned char *flag_buf_ptr;
+	union {
+		struct tty_buffer *next;
+		struct llist_node free;
+	};
 	int used;
 	int size;
 	int commit;
@@ -40,25 +43,25 @@ struct tty_buffer {
 	unsigned long data[0];
 };
 
-/*
- * We default to dicing tty buffer allocations to this many characters
- * in order to avoid multiple page allocations. We know the size of
- * tty_buffer itself but it must also be taken into account that the
- * the buffer is 256 byte aligned. See tty_buffer_find for the allocation
- * logic this must match
- */
-
-#define TTY_BUFFER_PAGE	(((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
+static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
+{
+	return ((unsigned char *)b->data) + ofs;
+}
 
+static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
+{
+	return (char *)char_buf_ptr(b, ofs) + b->size;
+}
 
 struct tty_bufhead {
-	struct work_struct work;
-	spinlock_t lock;
 	struct tty_buffer *head;	/* Queue head */
+	struct work_struct work;
+	struct mutex	   lock;
+	atomic_t	   priority;
+	struct tty_buffer sentinel;
+	struct llist_head free;		/* Free queue head */
+	atomic_t	   memory_used; /* In-use buffers excluding free list */
 	struct tty_buffer *tail;	/* Active buffer */
-	struct tty_buffer *free;	/* Free queue head */
-	int memory_used;		/* Buffer space used excluding
-								free queue */
 };
 /*
  * When a break, frame error, or parity error happens, these codes are
@@ -199,9 +202,6 @@ struct tty_port {
 	wait_queue_head_t	close_wait;	/* Close waiters */
 	wait_queue_head_t	delta_msr_wait;	/* Modem status change */
 	unsigned long		flags;		/* TTY flags ASY_*/
-	unsigned long		iflags;		/* TTYP_ internal flags */
-#define TTYP_FLUSHING			1  /* Flushing to ldisc in progress */
-#define TTYP_FLUSHPENDING		2  /* Queued buffer flush pending */
 	unsigned char		console:1,	/* port is a console */
 				low_latency:1;	/* direct buffer flush */
 	struct mutex		mutex;		/* Locking */
@@ -238,14 +238,16 @@ struct tty_struct {
 	int index;
 
 	/* Protects ldisc changes: Lock tty not pty */
-	struct mutex ldisc_mutex;
+	struct ld_semaphore ldisc_sem;
 	struct tty_ldisc *ldisc;
 
 	struct mutex atomic_write_lock;
 	struct mutex legacy_mutex;
-	struct mutex termios_mutex;
+	struct mutex throttle_mutex;
+	struct rw_semaphore termios_rwsem;
+	struct mutex winsize_mutex;
 	spinlock_t ctrl_lock;
-	/* Termios values are protected by the termios mutex */
+	/* Termios values are protected by the termios rwsem */
 	struct ktermios termios, termios_locked;
 	struct termiox *termiox;	/* May be NULL for unsupported */
 	char name[64];
@@ -253,7 +255,7 @@ struct tty_struct {
 	struct pid *session;
 	unsigned long flags;
 	int count;
-	struct winsize winsize;		/* termios mutex */
+	struct winsize winsize;		/* winsize_mutex */
 	unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
 	unsigned char ctrl_status;	/* ctrl_lock */
 	unsigned int receive_room;	/* Bytes free for queue */
@@ -303,10 +305,7 @@ struct tty_file_private {
 #define TTY_EXCLUSIVE 		3	/* Exclusive open mode */
 #define TTY_DEBUG 		4	/* Debugging */
 #define TTY_DO_WRITE_WAKEUP 	5	/* Call write_wakeup after queuing new */
-#define TTY_PUSH 		6	/* n_tty private */
 #define TTY_CLOSING 		7	/* ->close() in progress */
-#define TTY_LDISC 		9	/* Line discipline attached */
-#define TTY_LDISC_CHANGING 	10	/* Line discipline changing */
 #define TTY_LDISC_OPEN	 	11	/* Line discipline is open */
 #define TTY_PTY_LOCK 		16	/* pty private */
 #define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
@@ -559,6 +558,19 @@ extern void tty_ldisc_init(struct tty_struct *tty);
 extern void tty_ldisc_deinit(struct tty_struct *tty);
 extern void tty_ldisc_begin(void);
 
+static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p,
+					char *f, int count)
+{
+	if (ld->ops->receive_buf2)
+		count = ld->ops->receive_buf2(ld->tty, p, f, count);
+	else {
+		count = min_t(int, count, ld->tty->receive_room);
+		if (count)
+			ld->ops->receive_buf(ld->tty, p, f, count);
+	}
+	return count;
+}
+
 
 /* n_tty.c */
 extern struct tty_ldisc_ops tty_ldisc_N_TTY;
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index e0f2526..21ddd7d 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_TTY_FLIP_H
 #define _LINUX_TTY_FLIP_H
 
+extern int tty_buffer_space_avail(struct tty_port *port);
 extern int tty_buffer_request_room(struct tty_port *port, size_t size);
 extern int tty_insert_flip_string_flags(struct tty_port *port,
 		const unsigned char *chars, const char *flags, size_t size);
@@ -18,8 +19,8 @@ static inline int tty_insert_flip_char(struct tty_port *port,
 {
 	struct tty_buffer *tb = port->buf.tail;
 	if (tb && tb->used < tb->size) {
-		tb->flag_buf_ptr[tb->used] = flag;
-		tb->char_buf_ptr[tb->used++] = ch;
+		*flag_buf_ptr(tb, tb->used) = flag;
+		*char_buf_ptr(tb, tb->used++) = ch;
 		return 1;
 	}
 	return tty_insert_flip_string_flags(port, &ch, &flag, 1);
@@ -31,4 +32,7 @@ static inline int tty_insert_flip_string(struct tty_port *port,
 	return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size);
 }
 
+extern void tty_buffer_lock_exclusive(struct tty_port *port);
+extern void tty_buffer_unlock_exclusive(struct tty_port *port);
+
 #endif /* _LINUX_TTY_FLIP_H */
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index a1b0489..f15c898 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -109,6 +109,17 @@
  *
  *	Tells the discipline that the DCD pin has changed its status.
  *	Used exclusively by the N_PPS (Pulse-Per-Second) line discipline.
+ *
+ * int	(*receive_buf2)(struct tty_struct *, const unsigned char *cp,
+ *			char *fp, int count);
+ *
+ *	This function is called by the low-level tty driver to send
+ *	characters received by the hardware to the line discpline for
+ *	processing.  <cp> is a pointer to the buffer of input
+ *	character received by the device.  <fp> is a pointer to a
+ *	pointer of flag bytes which indicate whether a character was
+ *	received with a parity error, etc.
+ *	If assigned, prefer this function for automatic flow control.
  */
 
 #include <linux/fs.h>
@@ -195,6 +206,8 @@ struct tty_ldisc_ops {
 	void	(*write_wakeup)(struct tty_struct *);
 	void	(*dcd_change)(struct tty_struct *, unsigned int);
 	void	(*fasync)(struct tty_struct *tty, int on);
+	int	(*receive_buf2)(struct tty_struct *, const unsigned char *cp,
+				char *fp, int count);
 
 	struct  module *owner;
 
@@ -203,8 +216,7 @@ struct tty_ldisc_ops {
 
 struct tty_ldisc {
 	struct tty_ldisc_ops *ops;
-	atomic_t users;
-	wait_queue_head_t wq_idle;
+	struct tty_struct *tty;
 };
 
 #define TTY_LDISC_MAGIC	0x5403
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 0eec268..acb1b0a 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -708,7 +708,10 @@ extern int usb_driver_claim_interface(struct usb_driver *driver,
  * usb_interface_claimed - returns true iff an interface is claimed
  * @iface: the interface being checked
  *
- * Returns true (nonzero) iff the interface is claimed, else false (zero).
+ * Return: %true (nonzero) iff the interface is claimed, else %false
+ * (zero).
+ *
+ * Note:
  * Callers must own the driver model's usb bus readlock.  So driver
  * probe() entries don't need extra locking, but other call contexts
  * may need to explicitly claim that lock.
@@ -745,8 +748,9 @@ extern struct usb_host_interface *usb_find_alt_setting(
  * @buf: where to put the string
  * @size: how big is "buf"?
  *
- * Returns length of the string (> 0) or negative if size was too small.
+ * Return: Length of the string (> 0) or negative if size was too small.
  *
+ * Note:
  * This identifier is intended to be "stable", reflecting physical paths in
  * hardware such as physical bus addresses for host controllers or ports on
  * USB hubs.  That makes it stay the same until systems are physically
@@ -1247,7 +1251,9 @@ typedef void (*usb_complete_t)(struct urb *);
  *	the device driver is saying that it provided this DMA address,
  *	which the host controller driver should use in preference to the
  *	transfer_buffer.
- * @sg: scatter gather buffer list
+ * @sg: scatter gather buffer list, the buffer size of each element in
+ * 	the list (except the last) must be divisible by the endpoint's
+ * 	max packet size
  * @num_mapped_sgs: (internal) number of mapped sg entries
  * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
@@ -1534,10 +1540,16 @@ static inline void usb_fill_int_urb(struct urb *urb,
 	urb->transfer_buffer_length = buffer_length;
 	urb->complete = complete_fn;
 	urb->context = context;
-	if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER)
+
+	if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
+		/* make sure interval is within allowed range */
+		interval = clamp(interval, 1, 16);
+
 		urb->interval = 1 << (interval - 1);
-	else
+	} else {
 		urb->interval = interval;
+	}
+
 	urb->start_frame = -1;
 }
 
@@ -1570,7 +1582,7 @@ extern int usb_anchor_empty(struct usb_anchor *anchor);
  * usb_urb_dir_in - check if an URB describes an IN transfer
  * @urb: URB to be checked
  *
- * Returns 1 if @urb describes an IN transfer (device-to-host),
+ * Return: 1 if @urb describes an IN transfer (device-to-host),
  * otherwise 0.
  */
 static inline int usb_urb_dir_in(struct urb *urb)
@@ -1582,7 +1594,7 @@ static inline int usb_urb_dir_in(struct urb *urb)
  * usb_urb_dir_out - check if an URB describes an OUT transfer
  * @urb: URB to be checked
  *
- * Returns 1 if @urb describes an OUT transfer (host-to-device),
+ * Return: 1 if @urb describes an OUT transfer (host-to-device),
  * otherwise 0.
  */
 static inline int usb_urb_dir_out(struct urb *urb)
diff --git a/include/linux/usb/dwc3-omap.h b/include/linux/usb/dwc3-omap.h
deleted file mode 100644
index 5615f4d..0000000
--- a/include/linux/usb/dwc3-omap.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2013 by Texas Instruments
- *
- * The Inventra Controller Driver for Linux is free software; you
- * can redistribute it and/or modify it under the terms of the GNU
- * General Public License version 2 as published by the Free Software
- * Foundation.
- */
-
-#ifndef __DWC3_OMAP_H__
-#define __DWC3_OMAP_H__
-
-enum omap_dwc3_vbus_id_status {
-	OMAP_DWC3_UNKNOWN = 0,
-	OMAP_DWC3_ID_GROUND,
-	OMAP_DWC3_ID_FLOAT,
-	OMAP_DWC3_VBUS_VALID,
-	OMAP_DWC3_VBUS_OFF,
-};
-
-#if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
-extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
-#else
-static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
-{
-	return -ENODEV;
-}
-#endif
-
-#endif	/* __DWC3_OMAP_H__ */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index f1b0dca..942ef5e 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/scatterlist.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
 #include <linux/usb/ch9.h>
 
 struct usb_ep;
@@ -475,6 +476,7 @@ struct usb_gadget_ops {
 
 /**
  * struct usb_gadget - represents a usb slave device
+ * @work: (internal use) Workqueue to be used for sysfs_notify()
  * @ops: Function pointers used to access hardware-specific operations.
  * @ep0: Endpoint zero, used when reading or writing responses to
  *	driver setup() requests
@@ -520,6 +522,7 @@ struct usb_gadget_ops {
  * device is acting as a B-Peripheral (so is_a_peripheral is false).
  */
 struct usb_gadget {
+	struct work_struct		work;
 	/* readonly to gadget driver */
 	const struct usb_gadget_ops	*ops;
 	struct usb_ep			*ep0;
@@ -538,6 +541,7 @@ struct usb_gadget {
 	unsigned			out_epnum;
 	unsigned			in_epnum;
 };
+#define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))
 
 static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
 	{ dev_set_drvdata(&gadget->dev, data); }
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h
index a0ef405..8c38aa2 100644
--- a/include/linux/usb/of.h
+++ b/include/linux/usb/of.h
@@ -7,19 +7,27 @@
 #ifndef __LINUX_USB_OF_H
 #define __LINUX_USB_OF_H
 
+#include <linux/usb/ch9.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/phy.h>
 
 #if IS_ENABLED(CONFIG_OF)
 enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
+enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np);
 #else
 static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
 {
 	return USB_DR_MODE_UNKNOWN;
 }
+
+static inline enum usb_device_speed
+of_usb_get_maximum_speed(struct device_node *np)
+{
+	return USB_SPEED_UNKNOWN;
+}
 #endif
 
-#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_PHY)
+#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)
 enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np);
 #else
 static inline enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np)
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 4403680..6c0b1c5 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -142,7 +142,7 @@ extern void usb_remove_phy(struct usb_phy *);
 /* helpers for direct access thru low-level io interface */
 static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
 {
-	if (x->io_ops && x->io_ops->read)
+	if (x && x->io_ops && x->io_ops->read)
 		return x->io_ops->read(x, reg);
 
 	return -EINVAL;
@@ -150,7 +150,7 @@ static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
 
 static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
 {
-	if (x->io_ops && x->io_ops->write)
+	if (x && x->io_ops && x->io_ops->write)
 		return x->io_ops->write(x, val, reg);
 
 	return -EINVAL;
@@ -159,7 +159,7 @@ static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
 static inline int
 usb_phy_init(struct usb_phy *x)
 {
-	if (x->init)
+	if (x && x->init)
 		return x->init(x);
 
 	return 0;
@@ -168,14 +168,14 @@ usb_phy_init(struct usb_phy *x)
 static inline void
 usb_phy_shutdown(struct usb_phy *x)
 {
-	if (x->shutdown)
+	if (x && x->shutdown)
 		x->shutdown(x);
 }
 
 static inline int
 usb_phy_vbus_on(struct usb_phy *x)
 {
-	if (!x->set_vbus)
+	if (!x || !x->set_vbus)
 		return 0;
 
 	return x->set_vbus(x, true);
@@ -184,7 +184,7 @@ usb_phy_vbus_on(struct usb_phy *x)
 static inline int
 usb_phy_vbus_off(struct usb_phy *x)
 {
-	if (!x->set_vbus)
+	if (!x || !x->set_vbus)
 		return 0;
 
 	return x->set_vbus(x, false);
@@ -258,7 +258,7 @@ usb_phy_set_power(struct usb_phy *x, unsigned mA)
 static inline int
 usb_phy_set_suspend(struct usb_phy *x, int suspend)
 {
-	if (x->set_suspend != NULL)
+	if (x && x->set_suspend != NULL)
 		return x->set_suspend(x, suspend);
 	else
 		return 0;
@@ -267,7 +267,7 @@ usb_phy_set_suspend(struct usb_phy *x, int suspend)
 static inline int
 usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
 {
-	if (x->notify_connect)
+	if (x && x->notify_connect)
 		return x->notify_connect(x, speed);
 	else
 		return 0;
@@ -276,7 +276,7 @@ usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
 static inline int
 usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
 {
-	if (x->notify_disconnect)
+	if (x && x->notify_disconnect)
 		return x->notify_disconnect(x, speed);
 	else
 		return 0;
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index d2ca919..d3db274 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -28,23 +28,12 @@ struct tegra_utmip_config {
 	u8 xcvr_lsrslew;
 };
 
-struct tegra_ulpi_config {
-	int reset_gpio;
-	const char *clk;
-};
-
 enum tegra_usb_phy_port_speed {
 	TEGRA_USB_PHY_PORT_SPEED_FULL = 0,
 	TEGRA_USB_PHY_PORT_SPEED_LOW,
 	TEGRA_USB_PHY_PORT_SPEED_HIGH,
 };
 
-enum tegra_usb_phy_mode {
-	TEGRA_USB_PHY_MODE_DEVICE,
-	TEGRA_USB_PHY_MODE_HOST,
-	TEGRA_USB_PHY_MODE_OTG,
-};
-
 struct tegra_xtal_freq;
 
 struct tegra_usb_phy {
@@ -55,18 +44,16 @@ struct tegra_usb_phy {
 	struct clk *clk;
 	struct clk *pll_u;
 	struct clk *pad_clk;
-	enum tegra_usb_phy_mode mode;
+	struct regulator *vbus;
+	enum usb_dr_mode mode;
 	void *config;
 	struct usb_phy *ulpi;
 	struct usb_phy u_phy;
-	struct device *dev;
 	bool is_legacy_phy;
 	bool is_ulpi_phy;
 	int reset_gpio;
 };
 
-struct usb_phy *tegra_usb_get_phy(struct device_node *dn);
-
 void tegra_usb_phy_preresume(struct usb_phy *phy);
 
 void tegra_usb_phy_postresume(struct usb_phy *phy);
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index f18d641..8fbc008 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -34,6 +34,7 @@ struct usbnet {
 	struct mutex		phy_mutex;
 	unsigned char		suspend_count;
 	unsigned char		pkt_cnt, pkt_err;
+	unsigned short		rx_qlen, tx_qlen;
 
 	/* i/o info: pipes etc */
 	unsigned		in, out;
@@ -253,4 +254,6 @@ extern void usbnet_link_change(struct usbnet *, bool, bool);
 extern int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags);
 extern void usbnet_status_stop(struct usbnet *dev);
 
+extern void usbnet_update_max_qlen(struct usbnet *dev);
+
 #endif /* __LINUX_USB_USBNET_H */
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index b6b215f..14105c2 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -23,6 +23,7 @@ struct user_namespace {
 	struct uid_gid_map	projid_map;
 	atomic_t		count;
 	struct user_namespace	*parent;
+	int			level;
 	kuid_t			owner;
 	kgid_t			group;
 	unsigned int		proc_inum;
diff --git a/include/linux/uwb/spec.h b/include/linux/uwb/spec.h
index b52e44f..0df24bf 100644
--- a/include/linux/uwb/spec.h
+++ b/include/linux/uwb/spec.h
@@ -32,6 +32,7 @@
 
 #include <linux/types.h>
 #include <linux/bitmap.h>
+#include <linux/if_ether.h>
 
 #define i1480_FW 0x00000303
 /* #define i1480_FW 0x00000302 */
@@ -130,7 +131,7 @@ enum { UWB_DRP_BACKOFF_WIN_MAX = 16 };
  * it is also used to define headers sent down and up the wire/radio).
  */
 struct uwb_mac_addr {
-	u8 data[6];
+	u8 data[ETH_ALEN];
 } __attribute__((packed));
 
 
@@ -568,7 +569,7 @@ struct uwb_rc_evt_confirm {
 /* Device Address Management event. [WHCI] section 3.1.3.2. */
 struct uwb_rc_evt_dev_addr_mgmt {
 	struct uwb_rceb rceb;
-	u8 baAddr[6];
+	u8 baAddr[ETH_ALEN];
 	u8 bResultCode;
 } __attribute__((packed));
 
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index ac8d488..24579a0 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -90,4 +90,11 @@ extern void vfio_unregister_iommu_driver(
 	TYPE tmp;						\
 	offsetof(TYPE, MEMBER) + sizeof(tmp.MEMBER); })		\
 
+/*
+ * External user API
+ */
+extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
+extern void vfio_group_put_external_user(struct vfio_group *group);
+extern int vfio_external_user_iommu_id(struct vfio_group *group);
+
 #endif /* VFIO_H */
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index bd6cf61..1855f0a 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -70,6 +70,12 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		THP_ZERO_PAGE_ALLOC,
 		THP_ZERO_PAGE_ALLOC_FAILED,
 #endif
+#ifdef CONFIG_SMP
+		NR_TLB_REMOTE_FLUSH,	/* cpu tried to flush others' tlbs */
+		NR_TLB_REMOTE_FLUSH_RECEIVED,/* cpu received ipi for flush */
+#endif
+		NR_TLB_LOCAL_FLUSH_ALL,
+		NR_TLB_LOCAL_FLUSH_ONE,
 		NR_VM_EVENT_ITEMS
 };
 
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index c586679..502767f 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -198,7 +198,7 @@ extern void __inc_zone_state(struct zone *, enum zone_stat_item);
 extern void dec_zone_state(struct zone *, enum zone_stat_item);
 extern void __dec_zone_state(struct zone *, enum zone_stat_item);
 
-void refresh_cpu_vm_stats(int);
+void cpu_vm_stats_fold(int cpu);
 void refresh_zone_stat_thresholds(void);
 
 void drain_zonestat(struct zone *zone, struct per_cpu_pageset *);
@@ -255,6 +255,7 @@ static inline void __dec_zone_page_state(struct page *page,
 
 static inline void refresh_cpu_vm_stats(int cpu) { }
 static inline void refresh_zone_stat_thresholds(void) { }
+static inline void cpu_vm_stats_fold(int cpu) { }
 
 static inline void drain_zonestat(struct zone *zone,
 			struct per_cpu_pageset *pset) { }
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index a0ed78a..75eb364 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -13,6 +13,8 @@
 #include <linux/atomic.h>
 #include <linux/cpumask.h>
 
+struct cpumask;
+
 struct workqueue_struct;
 
 struct work_struct;
@@ -295,7 +297,12 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
  * Documentation/workqueue.txt.
  */
 enum {
-	WQ_NON_REENTRANT	= 1 << 0, /* guarantee non-reentrance */
+	/*
+	 * All wqs are now non-reentrant making the following flag
+	 * meaningless.  Will be removed.
+	 */
+	WQ_NON_REENTRANT	= 1 << 0, /* DEPRECATED */
+
 	WQ_UNBOUND		= 1 << 1, /* not bound to any cpu */
 	WQ_FREEZABLE		= 1 << 2, /* freeze during suspend */
 	WQ_MEM_RECLAIM		= 1 << 3, /* may be used for memory reclaim */
@@ -470,6 +477,7 @@ extern void flush_workqueue(struct workqueue_struct *wq);
 extern void drain_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
 
+extern int schedule_on_cpu_mask(work_func_t func, const struct cpumask *mask);
 extern int schedule_on_each_cpu(work_func_t func);
 
 int execute_in_process_context(work_func_t fn, struct execute_work *);
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index fdbafc6..91b0a68 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -31,7 +31,7 @@ struct xattr_handler {
 };
 
 struct xattr {
-	char *name;
+	const char *name;
 	void *value;
 	size_t value_len;
 };
diff --git a/include/media/adv7343.h b/include/media/adv7343.h
index 944757b..e4142b1 100644
--- a/include/media/adv7343.h
+++ b/include/media/adv7343.h
@@ -28,12 +28,7 @@
  * @pll_control: PLL and oversampling control. This control allows internal
  *		 PLL 1 circuit to be powered down and the oversampling to be
  *		 switched off.
- * @dac_1: power on/off DAC 1.
- * @dac_2: power on/off DAC 2.
- * @dac_3: power on/off DAC 3.
- * @dac_4: power on/off DAC 4.
- * @dac_5: power on/off DAC 5.
- * @dac_6: power on/off DAC 6.
+ * @dac: array to configure power on/off DAC's 1..6
  *
  * Power mode register (Register 0x0), for more info refer REGISTER MAP ACCESS
  * section of datasheet[1], table 17 page no 30.
@@ -43,23 +38,16 @@
 struct adv7343_power_mode {
 	bool sleep_mode;
 	bool pll_control;
-	bool dac_1;
-	bool dac_2;
-	bool dac_3;
-	bool dac_4;
-	bool dac_5;
-	bool dac_6;
+	u32 dac[6];
 };
 
 /**
  * struct adv7343_sd_config - SD Only Output Configuration.
- * @sd_dac_out1: Configure SD DAC Output 1.
- * @sd_dac_out2: Configure SD DAC Output 2.
+ * @sd_dac_out: array configuring SD DAC Outputs 1 and 2
  */
 struct adv7343_sd_config {
 	/* SD only Output Configuration */
-	bool sd_dac_out1;
-	bool sd_dac_out2;
+	u32 sd_dac_out[2];
 };
 
 /**
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index 3882e06..3cb1704 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -59,6 +59,8 @@ struct vpif_display_config {
 	int subdev_count;
 	struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
 	const char *card_name;
+	struct v4l2_async_subdev **asd;	/* Flat array, arranged in groups */
+	int *asd_sizes;		/* 0-terminated array of asd group sizes */
 };
 
 struct vpif_input {
@@ -81,5 +83,7 @@ struct vpif_capture_config {
 	struct vpif_subdev_info *subdev_info;
 	int subdev_count;
 	const char *card_name;
+	struct v4l2_async_subdev **asd;	/* Flat array, arranged in groups */
+	int *asd_sizes;		/* 0-terminated array of asd group sizes */
 };
 #endif /* _VPIF_TYPES_H */
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 168dd0b..78f0637 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -139,6 +139,7 @@ struct lirc_driver {
 	struct lirc_buffer *rbuf;
 	int (*set_use_inc) (void *data);
 	void (*set_use_dec) (void *data);
+	struct rc_dev *rdev;
 	const struct file_operations *fops;
 	struct device *dev;
 	struct module *owner;
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 06a75de..2f6f1f7 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -101,6 +101,7 @@ struct rc_dev {
 	bool				idle;
 	u64				allowed_protos;
 	u64				enabled_protocols;
+	u32				users;
 	u32				scanmask;
 	void				*priv;
 	spinlock_t			keylock;
@@ -142,6 +143,9 @@ void rc_free_device(struct rc_dev *dev);
 int rc_register_device(struct rc_dev *dev);
 void rc_unregister_device(struct rc_dev *dev);
 
+int rc_open(struct rc_dev *rdev);
+void rc_close(struct rc_dev *rdev);
+
 void rc_repeat(struct rc_dev *dev);
 void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle);
 void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle);
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h
index 4a1191a..f7119ee 100644
--- a/include/media/tveeprom.h
+++ b/include/media/tveeprom.h
@@ -12,6 +12,8 @@ enum tveeprom_audio_processor {
 	TVEEPROM_AUDPROC_OTHER,
 };
 
+#include <linux/if_ether.h>
+
 struct tveeprom {
 	u32 has_radio;
 	/* If has_ir == 0, then it is unknown what the IR capabilities are,
@@ -40,7 +42,7 @@ struct tveeprom {
 	u32 revision;
 	u32 serial_number;
 	char rev_str[5];
-	u8 MAC_address[6];
+	u8 MAC_address[ETH_ALEN];
 };
 
 void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index c3ec6ac..7683569 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -15,6 +15,7 @@
 #include <linux/mutex.h>
 
 struct device;
+struct device_node;
 struct v4l2_device;
 struct v4l2_subdev;
 struct v4l2_async_notifier;
@@ -22,10 +23,11 @@ struct v4l2_async_notifier;
 /* A random max subdevice number, used to allocate an array on stack */
 #define V4L2_MAX_SUBDEVS 128U
 
-enum v4l2_async_bus_type {
-	V4L2_ASYNC_BUS_CUSTOM,
-	V4L2_ASYNC_BUS_PLATFORM,
-	V4L2_ASYNC_BUS_I2C,
+enum v4l2_async_match_type {
+	V4L2_ASYNC_MATCH_CUSTOM,
+	V4L2_ASYNC_MATCH_DEVNAME,
+	V4L2_ASYNC_MATCH_I2C,
+	V4L2_ASYNC_MATCH_OF,
 };
 
 /**
@@ -36,11 +38,14 @@ enum v4l2_async_bus_type {
  *		probed, to a notifier->waiting list
  */
 struct v4l2_async_subdev {
-	enum v4l2_async_bus_type bus_type;
+	enum v4l2_async_match_type match_type;
 	union {
 		struct {
+			const struct device_node *node;
+		} of;
+		struct {
 			const char *name;
-		} platform;
+		} device_name;
 		struct {
 			int adapter_id;
 			unsigned short address;
@@ -57,25 +62,12 @@ struct v4l2_async_subdev {
 };
 
 /**
- * v4l2_async_subdev_list - provided by subdevices
- * @list:	links struct v4l2_async_subdev_list objects to a global list
- *		before probing, and onto notifier->done after probing
- * @asd:	pointer to respective struct v4l2_async_subdev
- * @notifier:	pointer to managing notifier
- */
-struct v4l2_async_subdev_list {
-	struct list_head list;
-	struct v4l2_async_subdev *asd;
-	struct v4l2_async_notifier *notifier;
-};
-
-/**
  * v4l2_async_notifier - v4l2_device notifier data
  * @num_subdevs:number of subdevices
- * @subdev:	array of pointers to subdevice descriptors
+ * @subdevs:	array of pointers to subdevice descriptors
  * @v4l2_dev:	pointer to struct v4l2_device
  * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
- * @done:	list of struct v4l2_async_subdev_list, already probed
+ * @done:	list of struct v4l2_subdev, already probed
  * @list:	member in a global list of notifiers
  * @bound:	a subdevice driver has successfully probed one of subdevices
  * @complete:	all subdevices have been probed successfully
@@ -83,7 +75,7 @@ struct v4l2_async_subdev_list {
  */
 struct v4l2_async_notifier {
 	unsigned int num_subdevs;
-	struct v4l2_async_subdev **subdev;
+	struct v4l2_async_subdev **subdevs;
 	struct v4l2_device *v4l2_dev;
 	struct list_head waiting;
 	struct list_head done;
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 7343a27..47ada23 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -22,6 +22,7 @@
 #define _V4L2_CTRLS_H
 
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/videodev2.h>
 
 /* forward references */
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 0f4555b..44542a2 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -60,6 +60,7 @@ struct v4l2_m2m_queue_ctx {
 	struct list_head	rdy_queue;
 	spinlock_t		rdy_spinlock;
 	u8			num_rdy;
+	bool			buffered;
 };
 
 struct v4l2_m2m_ctx {
@@ -134,6 +135,18 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
 		void *drv_priv,
 		int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq));
 
+static inline void v4l2_m2m_set_src_buffered(struct v4l2_m2m_ctx *m2m_ctx,
+					     bool buffered)
+{
+	m2m_ctx->out_q_ctx.buffered = buffered;
+}
+
+static inline void v4l2_m2m_set_dst_buffered(struct v4l2_m2m_ctx *m2m_ctx,
+					     bool buffered)
+{
+	m2m_ctx->cap_q_ctx.buffered = buffered;
+}
+
 void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx);
 
 void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 3250cc5..bfda0fe 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -586,15 +586,14 @@ struct v4l2_subdev {
 	struct video_device *devnode;
 	/* pointer to the physical device, if any */
 	struct device *dev;
-	struct v4l2_async_subdev_list asdl;
+	/* Links this subdev to a global subdev_list or @notifier->done list. */
+	struct list_head async_list;
+	/* Pointer to respective struct v4l2_async_subdev. */
+	struct v4l2_async_subdev *asd;
+	/* Pointer to the managing notifier. */
+	struct v4l2_async_notifier *notifier;
 };
 
-static inline struct v4l2_subdev *v4l2_async_to_subdev(
-			struct v4l2_async_subdev_list *asdl)
-{
-	return container_of(asdl, struct v4l2_subdev, asdl);
-}
-
 #define media_entity_to_v4l2_subdev(ent) \
 	container_of(ent, struct v4l2_subdev, entity)
 #define vdev_to_v4l2_subdev(vdev) \
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index d9fa68f..9a36d92 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -40,8 +40,6 @@
  * @close: member function to discard a connection on this transport
  * @request: member function to issue a request to the transport
  * @cancel: member function to cancel a request (if it hasn't been sent)
- * @cancelled: member function to notify that a cancelled request will not
- *             not receive a reply
  *
  * This is the basic API for a transport module which is registered by the
  * transport module with the 9P core network module and used by the client
@@ -60,7 +58,6 @@ struct p9_trans_module {
 	void (*close) (struct p9_client *);
 	int (*request) (struct p9_client *, struct p9_req_t *req);
 	int (*cancel) (struct p9_client *, struct p9_req_t *req);
-	int (*cancelled)(struct p9_client *, struct p9_req_t *req);
 	int (*zc_request)(struct p9_client *, struct p9_req_t *,
 			  char *, char *, int , int, int, int);
 };
diff --git a/include/net/act_api.h b/include/net/act_api.h
index b8ffac7..9e90fdf 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -82,36 +82,36 @@ struct tc_action_ops {
 	int     (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *);
 };
 
-extern struct tcf_common *tcf_hash_lookup(u32 index,
-					  struct tcf_hashinfo *hinfo);
-extern void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
-extern int tcf_hash_release(struct tcf_common *p, int bind,
-			    struct tcf_hashinfo *hinfo);
-extern int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
-			      int type, struct tc_action *a);
-extern u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo);
-extern int tcf_hash_search(struct tc_action *a, u32 index);
-extern struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
-					 int bind, struct tcf_hashinfo *hinfo);
-extern struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
-					  struct tc_action *a, int size,
-					  int bind, u32 *idx_gen,
-					  struct tcf_hashinfo *hinfo);
-extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
+struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo);
+void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
+int tcf_hash_release(struct tcf_common *p, int bind,
+		     struct tcf_hashinfo *hinfo);
+int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+		       int type, struct tc_action *a);
+u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo);
+int tcf_hash_search(struct tc_action *a, u32 index);
+struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
+				  int bind, struct tcf_hashinfo *hinfo);
+struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
+				   struct tc_action *a, int size,
+				   int bind, u32 *idx_gen,
+				   struct tcf_hashinfo *hinfo);
+void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
 
-extern int tcf_register_action(struct tc_action_ops *a);
-extern int tcf_unregister_action(struct tc_action_ops *a);
-extern void tcf_action_destroy(struct tc_action *a, int bind);
-extern int tcf_action_exec(struct sk_buff *skb, const struct tc_action *a, struct tcf_result *res);
-extern struct tc_action *tcf_action_init(struct net *net, struct nlattr *nla,
-					 struct nlattr *est, char *n, int ovr,
-					 int bind);
-extern struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
-					   struct nlattr *est, char *n, int ovr,
-					   int bind);
-extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int);
+int tcf_register_action(struct tc_action_ops *a);
+int tcf_unregister_action(struct tc_action_ops *a);
+void tcf_action_destroy(struct tc_action *a, int bind);
+int tcf_action_exec(struct sk_buff *skb, const struct tc_action *a,
+		    struct tcf_result *res);
+struct tc_action *tcf_action_init(struct net *net, struct nlattr *nla,
+				  struct nlattr *est, char *n, int ovr,
+				  int bind);
+struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
+				    struct nlattr *est, char *n, int ovr,
+				    int bind);
+int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
+int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
+int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
+int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
 #endif /* CONFIG_NET_CLS_ACT */
 #endif
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index c7b181c..43fa31a 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -53,51 +53,36 @@ struct prefix_info {
 #define IN6_ADDR_HSIZE_SHIFT	4
 #define IN6_ADDR_HSIZE		(1 << IN6_ADDR_HSIZE_SHIFT)
 
-extern int			addrconf_init(void);
-extern void			addrconf_cleanup(void);
+int addrconf_init(void);
+void addrconf_cleanup(void);
 
-extern int			addrconf_add_ifaddr(struct net *net,
-						    void __user *arg);
-extern int			addrconf_del_ifaddr(struct net *net,
-						    void __user *arg);
-extern int			addrconf_set_dstaddr(struct net *net,
-						     void __user *arg);
+int addrconf_add_ifaddr(struct net *net, void __user *arg);
+int addrconf_del_ifaddr(struct net *net, void __user *arg);
+int addrconf_set_dstaddr(struct net *net, void __user *arg);
 
-extern int			ipv6_chk_addr(struct net *net,
-					      const struct in6_addr *addr,
-					      const struct net_device *dev,
-					      int strict);
+int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
+		  const struct net_device *dev, int strict);
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-extern int			ipv6_chk_home_addr(struct net *net,
-						   const struct in6_addr *addr);
+int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
 #endif
 
-extern int			ipv6_chk_prefix(const struct in6_addr *addr,
-						struct net_device *dev);
-
-extern struct inet6_ifaddr      *ipv6_get_ifaddr(struct net *net,
-						 const struct in6_addr *addr,
-						 struct net_device *dev,
-						 int strict);
-
-extern int			ipv6_dev_get_saddr(struct net *net,
-					       const struct net_device *dev,
-					       const struct in6_addr *daddr,
-					       unsigned int srcprefs,
-					       struct in6_addr *saddr);
-extern int			__ipv6_get_lladdr(struct inet6_dev *idev,
-						  struct in6_addr *addr,
-						  unsigned char banned_flags);
-extern int			ipv6_get_lladdr(struct net_device *dev,
-						struct in6_addr *addr,
-						unsigned char banned_flags);
-extern int 			ipv6_rcv_saddr_equal(const struct sock *sk,
-						    const struct sock *sk2);
-extern void			addrconf_join_solict(struct net_device *dev,
-					const struct in6_addr *addr);
-extern void			addrconf_leave_solict(struct inet6_dev *idev,
-					const struct in6_addr *addr);
+int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
+
+struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
+				     const struct in6_addr *addr,
+				     struct net_device *dev, int strict);
+
+int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
+		       const struct in6_addr *daddr, unsigned int srcprefs,
+		       struct in6_addr *saddr);
+int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
+		      unsigned char banned_flags);
+int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
+		    unsigned char banned_flags);
+int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2);
+void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
+void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
 
 static inline unsigned long addrconf_timeout_fixup(u32 timeout,
 						   unsigned int unit)
@@ -124,41 +109,38 @@ static inline int addrconf_finite_timeout(unsigned long timeout)
 /*
  *	IPv6 Address Label subsystem (addrlabel.c)
  */
-extern int			ipv6_addr_label_init(void);
-extern void			ipv6_addr_label_cleanup(void);
-extern void			ipv6_addr_label_rtnl_register(void);
-extern u32			ipv6_addr_label(struct net *net,
-						const struct in6_addr *addr,
-						int type, int ifindex);
+int ipv6_addr_label_init(void);
+void ipv6_addr_label_cleanup(void);
+void ipv6_addr_label_rtnl_register(void);
+u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr,
+		    int type, int ifindex);
 
 /*
  *	multicast prototypes (mcast.c)
  */
-extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
-			     const struct in6_addr *addr);
-extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
-			     const struct in6_addr *addr);
-extern void ipv6_sock_mc_close(struct sock *sk);
-extern bool inet6_mc_check(struct sock *sk,
-			   const struct in6_addr *mc_addr,
-			   const struct in6_addr *src_addr);
-
-extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
-extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
-extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
-extern void ipv6_mc_up(struct inet6_dev *idev);
-extern void ipv6_mc_down(struct inet6_dev *idev);
-extern void ipv6_mc_unmap(struct inet6_dev *idev);
-extern void ipv6_mc_remap(struct inet6_dev *idev);
-extern void ipv6_mc_init_dev(struct inet6_dev *idev);
-extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
-extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
-
-extern bool ipv6_chk_mcast_addr(struct net_device *dev,
-				const struct in6_addr *group,
-				const struct in6_addr *src_addr);
-
-extern void ipv6_mc_dad_complete(struct inet6_dev *idev);
+int ipv6_sock_mc_join(struct sock *sk, int ifindex,
+		      const struct in6_addr *addr);
+int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
+		      const struct in6_addr *addr);
+void ipv6_sock_mc_close(struct sock *sk);
+bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
+		    const struct in6_addr *src_addr);
+
+int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
+int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
+void ipv6_mc_up(struct inet6_dev *idev);
+void ipv6_mc_down(struct inet6_dev *idev);
+void ipv6_mc_unmap(struct inet6_dev *idev);
+void ipv6_mc_remap(struct inet6_dev *idev);
+void ipv6_mc_init_dev(struct inet6_dev *idev);
+void ipv6_mc_destroy_dev(struct inet6_dev *idev);
+void addrconf_dad_failure(struct inet6_ifaddr *ifp);
+
+bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
+			 const struct in6_addr *src_addr);
+
+void ipv6_mc_dad_complete(struct inet6_dev *idev);
 /*
  * identify MLD packets for MLD filter exceptions
  */
@@ -184,29 +166,31 @@ static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset)
 	return false;
 }
 
-extern void addrconf_prefix_rcv(struct net_device *dev,
-				u8 *opt, int len, bool sllao);
+void addrconf_prefix_rcv(struct net_device *dev,
+			 u8 *opt, int len, bool sllao);
 
 /*
  *	anycast prototypes (anycast.c)
  */
-extern int ipv6_sock_ac_join(struct sock *sk,int ifindex, const struct in6_addr *addr);
-extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex, const struct in6_addr *addr);
-extern void ipv6_sock_ac_close(struct sock *sk);
-
-extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
-extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
-extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
+int ipv6_sock_ac_join(struct sock *sk, int ifindex,
+		      const struct in6_addr *addr);
+int ipv6_sock_ac_drop(struct sock *sk, int ifindex,
+		      const struct in6_addr *addr);
+void ipv6_sock_ac_close(struct sock *sk);
+
+int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
+int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
+bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 				const struct in6_addr *addr);
 
 
 /* Device notifier */
-extern int register_inet6addr_notifier(struct notifier_block *nb);
-extern int unregister_inet6addr_notifier(struct notifier_block *nb);
-extern int inet6addr_notifier_call_chain(unsigned long val, void *v);
+int register_inet6addr_notifier(struct notifier_block *nb);
+int unregister_inet6addr_notifier(struct notifier_block *nb);
+int inet6addr_notifier_call_chain(unsigned long val, void *v);
 
-extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
-					 struct ipv6_devconf *devconf);
+void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+				  struct ipv6_devconf *devconf);
 
 /**
  * __in6_dev_get - get inet6_dev pointer from netdevice
@@ -240,7 +224,7 @@ static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
 	return idev;
 }
 
-extern void in6_dev_finish_destroy(struct inet6_dev *idev);
+void in6_dev_finish_destroy(struct inet6_dev *idev);
 
 static inline void in6_dev_put(struct inet6_dev *idev)
 {
@@ -258,7 +242,7 @@ static inline void in6_dev_hold(struct inet6_dev *idev)
 	atomic_inc(&idev->refcnt);
 }
 
-extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
+void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
 
 static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
 {
@@ -340,8 +324,8 @@ static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
 }
 
 #ifdef CONFIG_PROC_FS
-extern int if6_proc_init(void);
-extern void if6_proc_exit(void);
+int if6_proc_init(void);
+void if6_proc_exit(void);
 #endif
 
 #endif
diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h
index 03e6e94..e797d45 100644
--- a/include/net/af_rxrpc.h
+++ b/include/net/af_rxrpc.h
@@ -31,24 +31,21 @@ enum {
 
 typedef void (*rxrpc_interceptor_t)(struct sock *, unsigned long,
 				    struct sk_buff *);
-extern void rxrpc_kernel_intercept_rx_messages(struct socket *,
-					       rxrpc_interceptor_t);
-extern struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
-						  struct sockaddr_rxrpc *,
-						  struct key *,
-						  unsigned long,
-						  gfp_t);
-extern int rxrpc_kernel_send_data(struct rxrpc_call *, struct msghdr *,
-				  size_t);
-extern void rxrpc_kernel_abort_call(struct rxrpc_call *, u32);
-extern void rxrpc_kernel_end_call(struct rxrpc_call *);
-extern bool rxrpc_kernel_is_data_last(struct sk_buff *);
-extern u32 rxrpc_kernel_get_abort_code(struct sk_buff *);
-extern int rxrpc_kernel_get_error_number(struct sk_buff *);
-extern void rxrpc_kernel_data_delivered(struct sk_buff *);
-extern void rxrpc_kernel_free_skb(struct sk_buff *);
-extern struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *,
-						   unsigned long);
-extern int rxrpc_kernel_reject_call(struct socket *);
+void rxrpc_kernel_intercept_rx_messages(struct socket *, rxrpc_interceptor_t);
+struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
+					   struct sockaddr_rxrpc *,
+					   struct key *,
+					   unsigned long,
+					   gfp_t);
+int rxrpc_kernel_send_data(struct rxrpc_call *, struct msghdr *, size_t);
+void rxrpc_kernel_abort_call(struct rxrpc_call *, u32);
+void rxrpc_kernel_end_call(struct rxrpc_call *);
+bool rxrpc_kernel_is_data_last(struct sk_buff *);
+u32 rxrpc_kernel_get_abort_code(struct sk_buff *);
+int rxrpc_kernel_get_error_number(struct sk_buff *);
+void rxrpc_kernel_data_delivered(struct sk_buff *);
+void rxrpc_kernel_free_skb(struct sk_buff *);
+struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long);
+int rxrpc_kernel_reject_call(struct socket *);
 
 #endif /* _NET_RXRPC_H */
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index dbdfd2b..05442df 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -6,12 +6,12 @@
 #include <linux/mutex.h>
 #include <net/sock.h>
 
-extern void unix_inflight(struct file *fp);
-extern void unix_notinflight(struct file *fp);
-extern void unix_gc(void);
-extern void wait_for_unix_gc(void);
-extern struct sock *unix_get_socket(struct file *filp);
-extern struct sock *unix_peer_get(struct sock *);
+void unix_inflight(struct file *fp);
+void unix_notinflight(struct file *fp);
+void unix_gc(void);
+void wait_for_unix_gc(void);
+struct sock *unix_get_socket(struct file *filp);
+struct sock *unix_peer_get(struct sock *);
 
 #define UNIX_HASH_SIZE	256
 #define UNIX_HASH_BITS	8
@@ -71,8 +71,8 @@ long unix_inq_len(struct sock *sk);
 long unix_outq_len(struct sock *sk);
 
 #ifdef CONFIG_SYSCTL
-extern int unix_sysctl_register(struct net *net);
-extern void unix_sysctl_unregister(struct net *net);
+int unix_sysctl_register(struct net *net);
+void unix_sysctl_unregister(struct net *net);
 #else
 static inline int unix_sysctl_register(struct net *net) { return 0; }
 static inline void unix_sysctl_unregister(struct net *net) {}
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
new file mode 100644
index 0000000..7d64d36
--- /dev/null
+++ b/include/net/af_vsock.h
@@ -0,0 +1,175 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef __AF_VSOCK_H__
+#define __AF_VSOCK_H__
+
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/vm_sockets.h>
+
+#include "vsock_addr.h"
+
+#define LAST_RESERVED_PORT 1023
+
+#define vsock_sk(__sk)    ((struct vsock_sock *)__sk)
+#define sk_vsock(__vsk)   (&(__vsk)->sk)
+
+struct vsock_sock {
+	/* sk must be the first member. */
+	struct sock sk;
+	struct sockaddr_vm local_addr;
+	struct sockaddr_vm remote_addr;
+	/* Links for the global tables of bound and connected sockets. */
+	struct list_head bound_table;
+	struct list_head connected_table;
+	/* Accessed without the socket lock held. This means it can never be
+	 * modified outsided of socket create or destruct.
+	 */
+	bool trusted;
+	bool cached_peer_allow_dgram;	/* Dgram communication allowed to
+					 * cached peer?
+					 */
+	u32 cached_peer;  /* Context ID of last dgram destination check. */
+	const struct cred *owner;
+	/* Rest are SOCK_STREAM only. */
+	long connect_timeout;
+	/* Listening socket that this came from. */
+	struct sock *listener;
+	/* Used for pending list and accept queue during connection handshake.
+	 * The listening socket is the head for both lists.  Sockets created
+	 * for connection requests are placed in the pending list until they
+	 * are connected, at which point they are put in the accept queue list
+	 * so they can be accepted in accept().  If accept() cannot accept the
+	 * connection, it is marked as rejected so the cleanup function knows
+	 * to clean up the socket.
+	 */
+	struct list_head pending_links;
+	struct list_head accept_queue;
+	bool rejected;
+	struct delayed_work dwork;
+	u32 peer_shutdown;
+	bool sent_request;
+	bool ignore_connecting_rst;
+
+	/* Private to transport. */
+	void *trans;
+};
+
+s64 vsock_stream_has_data(struct vsock_sock *vsk);
+s64 vsock_stream_has_space(struct vsock_sock *vsk);
+void vsock_pending_work(struct work_struct *work);
+struct sock *__vsock_create(struct net *net,
+			    struct socket *sock,
+			    struct sock *parent,
+			    gfp_t priority, unsigned short type);
+
+/**** TRANSPORT ****/
+
+struct vsock_transport_recv_notify_data {
+	u64 data1; /* Transport-defined. */
+	u64 data2; /* Transport-defined. */
+	bool notify_on_block;
+};
+
+struct vsock_transport_send_notify_data {
+	u64 data1; /* Transport-defined. */
+	u64 data2; /* Transport-defined. */
+};
+
+struct vsock_transport {
+	/* Initialize/tear-down socket. */
+	int (*init)(struct vsock_sock *, struct vsock_sock *);
+	void (*destruct)(struct vsock_sock *);
+	void (*release)(struct vsock_sock *);
+
+	/* Connections. */
+	int (*connect)(struct vsock_sock *);
+
+	/* DGRAM. */
+	int (*dgram_bind)(struct vsock_sock *, struct sockaddr_vm *);
+	int (*dgram_dequeue)(struct kiocb *kiocb, struct vsock_sock *vsk,
+			     struct msghdr *msg, size_t len, int flags);
+	int (*dgram_enqueue)(struct vsock_sock *, struct sockaddr_vm *,
+			     struct iovec *, size_t len);
+	bool (*dgram_allow)(u32 cid, u32 port);
+
+	/* STREAM. */
+	/* TODO: stream_bind() */
+	ssize_t (*stream_dequeue)(struct vsock_sock *, struct iovec *,
+				  size_t len, int flags);
+	ssize_t (*stream_enqueue)(struct vsock_sock *, struct iovec *,
+				  size_t len);
+	s64 (*stream_has_data)(struct vsock_sock *);
+	s64 (*stream_has_space)(struct vsock_sock *);
+	u64 (*stream_rcvhiwat)(struct vsock_sock *);
+	bool (*stream_is_active)(struct vsock_sock *);
+	bool (*stream_allow)(u32 cid, u32 port);
+
+	/* Notification. */
+	int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
+	int (*notify_poll_out)(struct vsock_sock *, size_t, bool *);
+	int (*notify_recv_init)(struct vsock_sock *, size_t,
+		struct vsock_transport_recv_notify_data *);
+	int (*notify_recv_pre_block)(struct vsock_sock *, size_t,
+		struct vsock_transport_recv_notify_data *);
+	int (*notify_recv_pre_dequeue)(struct vsock_sock *, size_t,
+		struct vsock_transport_recv_notify_data *);
+	int (*notify_recv_post_dequeue)(struct vsock_sock *, size_t,
+		ssize_t, bool, struct vsock_transport_recv_notify_data *);
+	int (*notify_send_init)(struct vsock_sock *,
+		struct vsock_transport_send_notify_data *);
+	int (*notify_send_pre_block)(struct vsock_sock *,
+		struct vsock_transport_send_notify_data *);
+	int (*notify_send_pre_enqueue)(struct vsock_sock *,
+		struct vsock_transport_send_notify_data *);
+	int (*notify_send_post_enqueue)(struct vsock_sock *, ssize_t,
+		struct vsock_transport_send_notify_data *);
+
+	/* Shutdown. */
+	int (*shutdown)(struct vsock_sock *, int);
+
+	/* Buffer sizes. */
+	void (*set_buffer_size)(struct vsock_sock *, u64);
+	void (*set_min_buffer_size)(struct vsock_sock *, u64);
+	void (*set_max_buffer_size)(struct vsock_sock *, u64);
+	u64 (*get_buffer_size)(struct vsock_sock *);
+	u64 (*get_min_buffer_size)(struct vsock_sock *);
+	u64 (*get_max_buffer_size)(struct vsock_sock *);
+
+	/* Addressing. */
+	u32 (*get_local_cid)(void);
+};
+
+/**** CORE ****/
+
+int vsock_core_init(const struct vsock_transport *t);
+void vsock_core_exit(void);
+
+/**** UTILS ****/
+
+void vsock_release_pending(struct sock *pending);
+void vsock_add_pending(struct sock *listener, struct sock *pending);
+void vsock_remove_pending(struct sock *listener, struct sock *pending);
+void vsock_enqueue_accept(struct sock *listener, struct sock *connected);
+void vsock_insert_connected(struct vsock_sock *vsk);
+void vsock_remove_bound(struct vsock_sock *vsk);
+void vsock_remove_connected(struct vsock_sock *vsk);
+struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
+struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
+					 struct sockaddr_vm *dst);
+void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
+
+#endif /* __AF_VSOCK_H__ */
diff --git a/include/net/arp.h b/include/net/arp.h
index b630dae..7509d9d 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -46,22 +46,22 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32
 	return n;
 }
 
-extern void	arp_init(void);
-extern int	arp_find(unsigned char *haddr, struct sk_buff *skb);
-extern int	arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
-extern void     arp_send(int type, int ptype, __be32 dest_ip,
-			 struct net_device *dev, __be32 src_ip,
-			 const unsigned char *dest_hw,
-			 const unsigned char *src_hw, const unsigned char *th);
-extern int	arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
-extern void	arp_ifdown(struct net_device *dev);
+void arp_init(void);
+int arp_find(unsigned char *haddr, struct sk_buff *skb);
+int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
+void arp_send(int type, int ptype, __be32 dest_ip,
+	      struct net_device *dev, __be32 src_ip,
+	      const unsigned char *dest_hw,
+	      const unsigned char *src_hw, const unsigned char *th);
+int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
+void arp_ifdown(struct net_device *dev);
 
-extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
-				  struct net_device *dev, __be32 src_ip,
-				  const unsigned char *dest_hw,
-				  const unsigned char *src_hw,
-				  const unsigned char *target_hw);
-extern void arp_xmit(struct sk_buff *skb);
+struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+			   struct net_device *dev, __be32 src_ip,
+			   const unsigned char *dest_hw,
+			   const unsigned char *src_hw,
+			   const unsigned char *target_hw);
+void arp_xmit(struct sk_buff *skb);
 int arp_invalidate(struct net_device *dev, __be32 ip);
 
 #endif	/* _ARP_H */
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 89ed9ac..bf0396e 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -195,7 +195,7 @@ static inline void ax25_hold_route(ax25_route *ax25_rt)
 	atomic_inc(&ax25_rt->refcount);
 }
 
-extern void __ax25_put_route(ax25_route *ax25_rt);
+void __ax25_put_route(ax25_route *ax25_rt);
 
 static inline void ax25_put_route(ax25_route *ax25_rt)
 {
@@ -272,30 +272,31 @@ static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev
 /* af_ax25.c */
 extern struct hlist_head ax25_list;
 extern spinlock_t ax25_list_lock;
-extern void ax25_cb_add(ax25_cb *);
+void ax25_cb_add(ax25_cb *);
 struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
 struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
-extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
-extern void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
-extern void ax25_destroy_socket(ax25_cb *);
-extern ax25_cb * __must_check ax25_create_cb(void);
-extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
-extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
+ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *,
+		      struct net_device *);
+void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
+void ax25_destroy_socket(ax25_cb *);
+ax25_cb * __must_check ax25_create_cb(void);
+void ax25_fillin_cb(ax25_cb *, ax25_dev *);
+struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
 
 /* ax25_addr.c */
 extern const ax25_address ax25_bcast;
 extern const ax25_address ax25_defaddr;
 extern const ax25_address null_ax25_address;
-extern char *ax2asc(char *buf, const ax25_address *);
-extern void asc2ax(ax25_address *addr, const char *callsign);
-extern int ax25cmp(const ax25_address *, const ax25_address *);
-extern int ax25digicmp(const ax25_digi *, const ax25_digi *);
-extern const unsigned char *ax25_addr_parse(const unsigned char *, int,
+char *ax2asc(char *buf, const ax25_address *);
+void asc2ax(ax25_address *addr, const char *callsign);
+int ax25cmp(const ax25_address *, const ax25_address *);
+int ax25digicmp(const ax25_digi *, const ax25_digi *);
+const unsigned char *ax25_addr_parse(const unsigned char *, int,
 	ax25_address *, ax25_address *, ax25_digi *, int *, int *);
-extern int  ax25_addr_build(unsigned char *, const ax25_address *,
-	const ax25_address *, const ax25_digi *, int, int);
-extern int  ax25_addr_size(const ax25_digi *);
-extern void ax25_digi_invert(const ax25_digi *, ax25_digi *);
+int ax25_addr_build(unsigned char *, const ax25_address *,
+		    const ax25_address *, const ax25_digi *, int, int);
+int ax25_addr_size(const ax25_digi *);
+void ax25_digi_invert(const ax25_digi *, ax25_digi *);
 
 /* ax25_dev.c */
 extern ax25_dev *ax25_dev_list;
@@ -306,33 +307,33 @@ static inline ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
 	return dev->ax25_ptr;
 }
 
-extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
-extern void ax25_dev_device_up(struct net_device *);
-extern void ax25_dev_device_down(struct net_device *);
-extern int  ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
-extern struct net_device *ax25_fwd_dev(struct net_device *);
-extern void ax25_dev_free(void);
+ax25_dev *ax25_addr_ax25dev(ax25_address *);
+void ax25_dev_device_up(struct net_device *);
+void ax25_dev_device_down(struct net_device *);
+int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
+struct net_device *ax25_fwd_dev(struct net_device *);
+void ax25_dev_free(void);
 
 /* ax25_ds_in.c */
-extern int  ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);
+int ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);
 
 /* ax25_ds_subr.c */
-extern void ax25_ds_nr_error_recovery(ax25_cb *);
-extern void ax25_ds_enquiry_response(ax25_cb *);
-extern void ax25_ds_establish_data_link(ax25_cb *);
-extern void ax25_dev_dama_off(ax25_dev *);
-extern void ax25_dama_on(ax25_cb *);
-extern void ax25_dama_off(ax25_cb *);
+void ax25_ds_nr_error_recovery(ax25_cb *);
+void ax25_ds_enquiry_response(ax25_cb *);
+void ax25_ds_establish_data_link(ax25_cb *);
+void ax25_dev_dama_off(ax25_dev *);
+void ax25_dama_on(ax25_cb *);
+void ax25_dama_off(ax25_cb *);
 
 /* ax25_ds_timer.c */
-extern void ax25_ds_setup_timer(ax25_dev *);
-extern void ax25_ds_set_timer(ax25_dev *);
-extern void ax25_ds_del_timer(ax25_dev *);
-extern void ax25_ds_timer(ax25_cb *);
-extern void ax25_ds_t1_timeout(ax25_cb *);
-extern void ax25_ds_heartbeat_expiry(ax25_cb *);
-extern void ax25_ds_t3timer_expiry(ax25_cb *);
-extern void ax25_ds_idletimer_expiry(ax25_cb *);
+void ax25_ds_setup_timer(ax25_dev *);
+void ax25_ds_set_timer(ax25_dev *);
+void ax25_ds_del_timer(ax25_dev *);
+void ax25_ds_timer(ax25_cb *);
+void ax25_ds_t1_timeout(ax25_cb *);
+void ax25_ds_heartbeat_expiry(ax25_cb *);
+void ax25_ds_t3timer_expiry(ax25_cb *);
+void ax25_ds_idletimer_expiry(ax25_cb *);
 
 /* ax25_iface.c */
 
@@ -342,107 +343,109 @@ struct ax25_protocol {
 	int (*func)(struct sk_buff *, ax25_cb *);
 };
 
-extern void ax25_register_pid(struct ax25_protocol *ap);
-extern void ax25_protocol_release(unsigned int);
+void ax25_register_pid(struct ax25_protocol *ap);
+void ax25_protocol_release(unsigned int);
 
 struct ax25_linkfail {
 	struct hlist_node lf_node;
 	void (*func)(ax25_cb *, int);
 };
 
-extern void ax25_linkfail_register(struct ax25_linkfail *lf);
-extern void ax25_linkfail_release(struct ax25_linkfail *lf);
-extern int __must_check ax25_listen_register(ax25_address *,
-	struct net_device *);
-extern void ax25_listen_release(ax25_address *, struct net_device *);
-extern int  (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
-extern int  ax25_listen_mine(ax25_address *, struct net_device *);
-extern void ax25_link_failed(ax25_cb *, int);
-extern int  ax25_protocol_is_registered(unsigned int);
+void ax25_linkfail_register(struct ax25_linkfail *lf);
+void ax25_linkfail_release(struct ax25_linkfail *lf);
+int __must_check ax25_listen_register(ax25_address *, struct net_device *);
+void ax25_listen_release(ax25_address *, struct net_device *);
+int(*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
+int ax25_listen_mine(ax25_address *, struct net_device *);
+void ax25_link_failed(ax25_cb *, int);
+int ax25_protocol_is_registered(unsigned int);
 
 /* ax25_in.c */
-extern int  ax25_rx_iframe(ax25_cb *, struct sk_buff *);
-extern int  ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
+int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
+int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *,
+		  struct net_device *);
 
 /* ax25_ip.c */
-extern int ax25_hard_header(struct sk_buff *, struct net_device *,
-			    unsigned short, const void *,
-			    const void *, unsigned int);
-extern int  ax25_rebuild_header(struct sk_buff *);
+int ax25_hard_header(struct sk_buff *, struct net_device *, unsigned short,
+		     const void *, const void *, unsigned int);
+int ax25_rebuild_header(struct sk_buff *);
 extern const struct header_ops ax25_header_ops;
 
 /* ax25_out.c */
-extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
-extern void ax25_output(ax25_cb *, int, struct sk_buff *);
-extern void ax25_kick(ax25_cb *);
-extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
-extern void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);
-extern int  ax25_check_iframes_acked(ax25_cb *, unsigned short);
+ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *,
+			 ax25_digi *, struct net_device *);
+void ax25_output(ax25_cb *, int, struct sk_buff *);
+void ax25_kick(ax25_cb *);
+void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
+void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);
+int ax25_check_iframes_acked(ax25_cb *, unsigned short);
 
 /* ax25_route.c */
-extern void ax25_rt_device_down(struct net_device *);
-extern int  ax25_rt_ioctl(unsigned int, void __user *);
+void ax25_rt_device_down(struct net_device *);
+int ax25_rt_ioctl(unsigned int, void __user *);
 extern const struct file_operations ax25_route_fops;
-extern ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
-extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
-extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
-extern void ax25_rt_free(void);
+ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
+int ax25_rt_autobind(ax25_cb *, ax25_address *);
+struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *,
+				   ax25_address *, ax25_digi *);
+void ax25_rt_free(void);
 
 /* ax25_std_in.c */
-extern int  ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
+int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
 
 /* ax25_std_subr.c */
-extern void ax25_std_nr_error_recovery(ax25_cb *);
-extern void ax25_std_establish_data_link(ax25_cb *);
-extern void ax25_std_transmit_enquiry(ax25_cb *);
-extern void ax25_std_enquiry_response(ax25_cb *);
-extern void ax25_std_timeout_response(ax25_cb *);
+void ax25_std_nr_error_recovery(ax25_cb *);
+void ax25_std_establish_data_link(ax25_cb *);
+void ax25_std_transmit_enquiry(ax25_cb *);
+void ax25_std_enquiry_response(ax25_cb *);
+void ax25_std_timeout_response(ax25_cb *);
 
 /* ax25_std_timer.c */
-extern void ax25_std_heartbeat_expiry(ax25_cb *);
-extern void ax25_std_t1timer_expiry(ax25_cb *);
-extern void ax25_std_t2timer_expiry(ax25_cb *);
-extern void ax25_std_t3timer_expiry(ax25_cb *);
-extern void ax25_std_idletimer_expiry(ax25_cb *);
+void ax25_std_heartbeat_expiry(ax25_cb *);
+void ax25_std_t1timer_expiry(ax25_cb *);
+void ax25_std_t2timer_expiry(ax25_cb *);
+void ax25_std_t3timer_expiry(ax25_cb *);
+void ax25_std_idletimer_expiry(ax25_cb *);
 
 /* ax25_subr.c */
-extern void ax25_clear_queues(ax25_cb *);
-extern void ax25_frames_acked(ax25_cb *, unsigned short);
-extern void ax25_requeue_frames(ax25_cb *);
-extern int  ax25_validate_nr(ax25_cb *, unsigned short);
-extern int  ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
-extern void ax25_send_control(ax25_cb *, int, int, int);
-extern void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *, ax25_digi *);
-extern void ax25_calculate_t1(ax25_cb *);
-extern void ax25_calculate_rtt(ax25_cb *);
-extern void ax25_disconnect(ax25_cb *, int);
+void ax25_clear_queues(ax25_cb *);
+void ax25_frames_acked(ax25_cb *, unsigned short);
+void ax25_requeue_frames(ax25_cb *);
+int ax25_validate_nr(ax25_cb *, unsigned short);
+int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
+void ax25_send_control(ax25_cb *, int, int, int);
+void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *,
+		    ax25_digi *);
+void ax25_calculate_t1(ax25_cb *);
+void ax25_calculate_rtt(ax25_cb *);
+void ax25_disconnect(ax25_cb *, int);
 
 /* ax25_timer.c */
-extern void ax25_setup_timers(ax25_cb *);
-extern void ax25_start_heartbeat(ax25_cb *);
-extern void ax25_start_t1timer(ax25_cb *);
-extern void ax25_start_t2timer(ax25_cb *);
-extern void ax25_start_t3timer(ax25_cb *);
-extern void ax25_start_idletimer(ax25_cb *);
-extern void ax25_stop_heartbeat(ax25_cb *);
-extern void ax25_stop_t1timer(ax25_cb *);
-extern void ax25_stop_t2timer(ax25_cb *);
-extern void ax25_stop_t3timer(ax25_cb *);
-extern void ax25_stop_idletimer(ax25_cb *);
-extern int  ax25_t1timer_running(ax25_cb *);
-extern unsigned long ax25_display_timer(struct timer_list *);
+void ax25_setup_timers(ax25_cb *);
+void ax25_start_heartbeat(ax25_cb *);
+void ax25_start_t1timer(ax25_cb *);
+void ax25_start_t2timer(ax25_cb *);
+void ax25_start_t3timer(ax25_cb *);
+void ax25_start_idletimer(ax25_cb *);
+void ax25_stop_heartbeat(ax25_cb *);
+void ax25_stop_t1timer(ax25_cb *);
+void ax25_stop_t2timer(ax25_cb *);
+void ax25_stop_t3timer(ax25_cb *);
+void ax25_stop_idletimer(ax25_cb *);
+int ax25_t1timer_running(ax25_cb *);
+unsigned long ax25_display_timer(struct timer_list *);
 
 /* ax25_uid.c */
 extern int  ax25_uid_policy;
-extern ax25_uid_assoc *ax25_findbyuid(kuid_t);
-extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
+ax25_uid_assoc *ax25_findbyuid(kuid_t);
+int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
 extern const struct file_operations ax25_uid_fops;
-extern void ax25_uid_free(void);
+void ax25_uid_free(void);
 
 /* sysctl_net_ax25.c */
 #ifdef CONFIG_SYSCTL
-extern int ax25_register_dev_sysctl(ax25_dev *ax25_dev);
-extern void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev);
+int ax25_register_dev_sysctl(ax25_dev *ax25_dev);
+void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev);
 #else
 static inline int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { return 0; }
 static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {}
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3c592cf..a01fbb4 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -296,6 +296,12 @@ enum {
 #define HCI_AT_GENERAL_BONDING		0x04
 #define HCI_AT_GENERAL_BONDING_MITM	0x05
 
+/* I/O capabilities */
+#define HCI_IO_DISPLAY_ONLY	0x00
+#define HCI_IO_DISPLAY_YESNO	0x01
+#define HCI_IO_KEYBOARD_ONLY	0x02
+#define HCI_IO_NO_INPUT_OUTPUT	0x03
+
 /* Link Key types */
 #define HCI_LK_COMBINATION		0x00
 #define HCI_LK_LOCAL_UNIT		0x01
diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h
index f18b919..8e2dfc1 100644
--- a/include/net/busy_poll.h
+++ b/include/net/busy_poll.h
@@ -162,11 +162,6 @@ static inline bool sk_can_busy_loop(struct sock *sk)
 	return false;
 }
 
-static inline bool sk_busy_poll(struct sock *sk, int nonblock)
-{
-	return false;
-}
-
 static inline void skb_mark_napi_id(struct sk_buff *skb,
 				    struct napi_struct *napi)
 {
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7b0730a..2cb06a6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -461,6 +461,33 @@ ieee80211_chandef_rate_flags(struct cfg80211_chan_def *chandef)
 }
 
 /**
+ * ieee80211_chandef_max_power - maximum transmission power for the chandef
+ *
+ * In some regulations, the transmit power may depend on the configured channel
+ * bandwidth which may be defined as dBm/MHz. This function returns the actual
+ * max_power for non-standard (20 MHz) channels.
+ *
+ * @chandef: channel definition for the channel
+ *
+ * Returns: maximum allowed transmission power in dBm for the chandef
+ */
+static inline int
+ieee80211_chandef_max_power(struct cfg80211_chan_def *chandef)
+{
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_5:
+		return min(chandef->chan->max_reg_power - 6,
+			   chandef->chan->max_power);
+	case NL80211_CHAN_WIDTH_10:
+		return min(chandef->chan->max_reg_power - 3,
+			   chandef->chan->max_power);
+	default:
+		break;
+	}
+	return chandef->chan->max_power;
+}
+
+/**
  * enum survey_info_flags - survey information flags
  *
  * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
@@ -490,7 +517,7 @@ enum survey_info_flags {
  * @channel: the channel this survey record reports, mandatory
  * @filled: bitflag of flags from &enum survey_info_flags
  * @noise: channel noise in dBm. This and all following fields are
- *     optional
+ *	optional
  * @channel_time: amount of time in ms the radio spent on the channel
  * @channel_time_busy: amount of time the primary channel was sensed busy
  * @channel_time_ext_busy: amount of time the extension channel was sensed busy
@@ -546,9 +573,9 @@ struct cfg80211_crypto_settings {
 /**
  * struct cfg80211_beacon_data - beacon data
  * @head: head portion of beacon (before TIM IE)
- *     or %NULL if not changed
+ *	or %NULL if not changed
  * @tail: tail portion of beacon (after TIM IE)
- *     or %NULL if not changed
+ *	or %NULL if not changed
  * @head_len: length of @head
  * @tail_len: length of @tail
  * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL
@@ -764,7 +791,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
  * @STATION_INFO_PLINK_STATE: @plink_state filled
  * @STATION_INFO_SIGNAL: @signal filled
  * @STATION_INFO_TX_BITRATE: @txrate fields are filled
- *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
+ *	(tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value
  * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value
  * @STATION_INFO_TX_RETRIES: @tx_retries filled
@@ -1285,6 +1312,7 @@ struct cfg80211_ssid {
  * @n_ssids: number of SSIDs
  * @channels: channels to scan on.
  * @n_channels: total number of channels to scan
+ * @scan_width: channel width for scanning
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
  * @flags: bit field of flags controlling operation
@@ -1300,6 +1328,7 @@ struct cfg80211_scan_request {
 	struct cfg80211_ssid *ssids;
 	int n_ssids;
 	u32 n_channels;
+	enum nl80211_bss_scan_width scan_width;
 	const u8 *ie;
 	size_t ie_len;
 	u32 flags;
@@ -1333,6 +1362,7 @@ struct cfg80211_match_set {
  * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
  * @n_ssids: number of SSIDs
  * @n_channels: total number of channels to scan
+ * @scan_width: channel width for scanning
  * @interval: interval between each scheduled scan cycle
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
@@ -1352,6 +1382,7 @@ struct cfg80211_sched_scan_request {
 	struct cfg80211_ssid *ssids;
 	int n_ssids;
 	u32 n_channels;
+	enum nl80211_bss_scan_width scan_width;
 	u32 interval;
 	const u8 *ie;
 	size_t ie_len;
@@ -1403,6 +1434,7 @@ struct cfg80211_bss_ies {
  * for use in scan results and similar.
  *
  * @channel: channel this BSS is on
+ * @scan_width: width of the control channel
  * @bssid: BSSID of the BSS
  * @beacon_interval: the beacon interval as from the frame
  * @capability: the capability field in host byte order
@@ -1424,6 +1456,7 @@ struct cfg80211_bss_ies {
  */
 struct cfg80211_bss {
 	struct ieee80211_channel *channel;
+	enum nl80211_bss_scan_width scan_width;
 
 	const struct cfg80211_bss_ies __rcu *ies;
 	const struct cfg80211_bss_ies __rcu *beacon_ies;
@@ -1509,7 +1542,7 @@ enum cfg80211_assoc_req_flags {
  * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
  * @flags:  See &enum cfg80211_assoc_req_flags
  * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
- *   will be used in ht_capa.  Un-supported values will be ignored.
+ *	will be used in ht_capa.  Un-supported values will be ignored.
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
  * @vht_capa: VHT capability override
  * @vht_capa_mask: VHT capability mask indicating which fields to use
@@ -1592,6 +1625,9 @@ struct cfg80211_disassoc_request {
  *	user space. Otherwise, port is marked authorized by default.
  * @basic_rates: bitmap of basic rates to use when creating the IBSS
  * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
+ * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
+ *	will be used in ht_capa.  Un-supported values will be ignored.
+ * @ht_capa_mask:  The bits of ht_capa which are to be used.
  */
 struct cfg80211_ibss_params {
 	u8 *ssid;
@@ -1605,6 +1641,8 @@ struct cfg80211_ibss_params {
 	bool privacy;
 	bool control_port;
 	int mcast_rate[IEEE80211_NUM_BANDS];
+	struct ieee80211_ht_cap ht_capa;
+	struct ieee80211_ht_cap ht_capa_mask;
 };
 
 /**
@@ -1630,9 +1668,9 @@ struct cfg80211_ibss_params {
  * @key: WEP key for shared key authentication
  * @flags:  See &enum cfg80211_assoc_req_flags
  * @bg_scan_period:  Background scan period in seconds
- *   or -1 to indicate that default value is to be used.
+ *	or -1 to indicate that default value is to be used.
  * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
- *   will be used in ht_capa.  Un-supported values will be ignored.
+ *	will be used in ht_capa.  Un-supported values will be ignored.
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
  * @vht_capa:  VHT Capability overrides
  * @vht_capa_mask: The bits of vht_capa which are to be used.
@@ -1698,7 +1736,7 @@ struct cfg80211_pmksa {
 };
 
 /**
- * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
+ * struct cfg80211_pkt_pattern - packet pattern
  * @mask: bitmask where to match pattern and where to ignore bytes,
  *	one bit per byte, in same format as nl80211
  * @pattern: bytes to match where bitmask is 1
@@ -1708,7 +1746,7 @@ struct cfg80211_pmksa {
  * Internal note: @mask and @pattern are allocated in one chunk of
  * memory, free @mask only!
  */
-struct cfg80211_wowlan_trig_pkt_pattern {
+struct cfg80211_pkt_pattern {
 	u8 *mask, *pattern;
 	int pattern_len;
 	int pkt_offset;
@@ -1770,12 +1808,41 @@ struct cfg80211_wowlan {
 	bool any, disconnect, magic_pkt, gtk_rekey_failure,
 	     eap_identity_req, four_way_handshake,
 	     rfkill_release;
-	struct cfg80211_wowlan_trig_pkt_pattern *patterns;
+	struct cfg80211_pkt_pattern *patterns;
 	struct cfg80211_wowlan_tcp *tcp;
 	int n_patterns;
 };
 
 /**
+ * struct cfg80211_coalesce_rules - Coalesce rule parameters
+ *
+ * This structure defines coalesce rule for the device.
+ * @delay: maximum coalescing delay in msecs.
+ * @condition: condition for packet coalescence.
+ *	see &enum nl80211_coalesce_condition.
+ * @patterns: array of packet patterns
+ * @n_patterns: number of patterns
+ */
+struct cfg80211_coalesce_rules {
+	int delay;
+	enum nl80211_coalesce_condition condition;
+	struct cfg80211_pkt_pattern *patterns;
+	int n_patterns;
+};
+
+/**
+ * struct cfg80211_coalesce - Packet coalescing settings
+ *
+ * This structure defines coalescing settings.
+ * @rules: array of coalesce rules
+ * @n_rules: number of rules
+ */
+struct cfg80211_coalesce {
+	struct cfg80211_coalesce_rules *rules;
+	int n_rules;
+};
+
+/**
  * struct cfg80211_wowlan_wakeup - wakeup report
  * @disconnect: woke up by getting disconnected
  * @magic_pkt: woke up by receiving magic packet
@@ -2071,6 +2138,7 @@ struct cfg80211_update_ft_ies_params {
  *	driver can take the most appropriate actions.
  * @crit_proto_stop: Indicates critical protocol no longer needs increased link
  *	reliability. This operation can not fail.
+ * @set_coalesce: Set coalesce parameters.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2306,6 +2374,8 @@ struct cfg80211_ops {
 				    u16 duration);
 	void	(*crit_proto_stop)(struct wiphy *wiphy,
 				   struct wireless_dev *wdev);
+	int	(*set_coalesce)(struct wiphy *wiphy,
+				struct cfg80211_coalesce *coalesce);
 };
 
 /*
@@ -2532,6 +2602,25 @@ struct wiphy_wowlan_support {
 };
 
 /**
+ * struct wiphy_coalesce_support - coalesce support data
+ * @n_rules: maximum number of coalesce rules
+ * @max_delay: maximum supported coalescing delay in msecs
+ * @n_patterns: number of supported patterns in a rule
+ *	(see nl80211.h for the pattern definition)
+ * @pattern_max_len: maximum length of each pattern
+ * @pattern_min_len: minimum length of each pattern
+ * @max_pkt_offset: maximum Rx packet offset
+ */
+struct wiphy_coalesce_support {
+	int n_rules;
+	int max_delay;
+	int n_patterns;
+	int pattern_max_len;
+	int pattern_min_len;
+	int max_pkt_offset;
+};
+
+/**
  * struct wiphy - wireless hardware description
  * @reg_notifier: the driver's regulatory notification callback,
  *	note that if your driver uses wiphy_apply_custom_regulatory()
@@ -2641,6 +2730,7 @@ struct wiphy_wowlan_support {
  *	802.11-2012 8.4.2.29 for the defined fields.
  * @extended_capabilities_mask: mask of the valid values
  * @extended_capabilities_len: length of the extended capabilities
+ * @coalesce: packet coalescing support information
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2750,6 +2840,8 @@ struct wiphy {
 	const struct iw_handler_def *wext;
 #endif
 
+	const struct wiphy_coalesce_support *coalesce;
+
 	char priv[0] __aligned(NETDEV_ALIGN);
 };
 
@@ -2841,7 +2933,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
  *
  * Return: A non-negative wiphy index or a negative error code.
  */
-extern int wiphy_register(struct wiphy *wiphy);
+int wiphy_register(struct wiphy *wiphy);
 
 /**
  * wiphy_unregister - deregister a wiphy from cfg80211
@@ -2852,14 +2944,14 @@ extern int wiphy_register(struct wiphy *wiphy);
  * pointer, but the call may sleep to wait for an outstanding
  * request that is being handled.
  */
-extern void wiphy_unregister(struct wiphy *wiphy);
+void wiphy_unregister(struct wiphy *wiphy);
 
 /**
  * wiphy_free - free wiphy
  *
  * @wiphy: The wiphy to free
  */
-extern void wiphy_free(struct wiphy *wiphy);
+void wiphy_free(struct wiphy *wiphy);
 
 /* internal structs */
 struct cfg80211_conn;
@@ -3014,14 +3106,14 @@ static inline void *wdev_priv(struct wireless_dev *wdev)
  * @band: band, necessary due to channel number overlap
  * Return: The corresponding frequency (in MHz), or 0 if the conversion failed.
  */
-extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band);
+int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band);
 
 /**
  * ieee80211_frequency_to_channel - convert frequency to channel number
  * @freq: center frequency
  * Return: The corresponding channel, or 0 if the conversion failed.
  */
-extern int ieee80211_frequency_to_channel(int freq);
+int ieee80211_frequency_to_channel(int freq);
 
 /*
  * Name indirection necessary because the ieee80211 code also has
@@ -3030,8 +3122,8 @@ extern int ieee80211_frequency_to_channel(int freq);
  * to include both header files you'll (rightfully!) get a symbol
  * clash.
  */
-extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
-							 int freq);
+struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
+						  int freq);
 /**
  * ieee80211_get_channel - get channel struct from wiphy for specified frequency
  * @wiphy: the struct wiphy to get the channel for
@@ -3063,11 +3155,13 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
 /**
  * ieee80211_mandatory_rates - get mandatory rates for a given band
  * @sband: the band to look for rates in
+ * @scan_width: width of the control channel
  *
  * This function returns a bitmap of the mandatory rates for the given
  * band, bits are set according to the rate position in the bitrates array.
  */
-u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband);
+u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
+			      enum nl80211_bss_scan_width scan_width);
 
 /*
  * Radiotap parsing functions -- for controlled injection support
@@ -3141,13 +3235,14 @@ struct ieee80211_radiotap_iterator {
 	int _reset_on_ext;
 };
 
-extern int ieee80211_radiotap_iterator_init(
-	struct ieee80211_radiotap_iterator *iterator,
-	struct ieee80211_radiotap_header *radiotap_header,
-	int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns);
+int
+ieee80211_radiotap_iterator_init(struct ieee80211_radiotap_iterator *iterator,
+				 struct ieee80211_radiotap_header *radiotap_header,
+				 int max_length,
+				 const struct ieee80211_radiotap_vendor_namespaces *vns);
 
-extern int ieee80211_radiotap_iterator_next(
-	struct ieee80211_radiotap_iterator *iterator);
+int
+ieee80211_radiotap_iterator_next(struct ieee80211_radiotap_iterator *iterator);
 
 
 extern const unsigned char rfc1042_header[6];
@@ -3307,7 +3402,7 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
  *
  * Return: 0 on success. -ENOMEM.
  */
-extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
+int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
 
 /**
  * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
@@ -3321,9 +3416,8 @@ extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
  * default channel settings will be disregarded. If no rule is found for a
  * channel on the regulatory domain the channel will be disabled.
  */
-extern void wiphy_apply_custom_regulatory(
-	struct wiphy *wiphy,
-	const struct ieee80211_regdomain *regd);
+void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
+				   const struct ieee80211_regdomain *regd);
 
 /**
  * freq_reg_info - get regulatory information for the given frequency
@@ -3379,10 +3473,11 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy);
 void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
 
 /**
- * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame
+ * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame
  *
  * @wiphy: the wiphy reporting the BSS
  * @channel: The channel the frame was received on
+ * @scan_width: width of the control channel
  * @mgmt: the management frame (probe response or beacon)
  * @len: length of the management frame
  * @signal: the signal strength, type depends on the wiphy's signal_type
@@ -3395,16 +3490,29 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
  * Or %NULL on error.
  */
 struct cfg80211_bss * __must_check
+cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
+				struct ieee80211_channel *channel,
+				enum nl80211_bss_scan_width scan_width,
+				struct ieee80211_mgmt *mgmt, size_t len,
+				s32 signal, gfp_t gfp);
+
+static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss_frame(struct wiphy *wiphy,
 			  struct ieee80211_channel *channel,
 			  struct ieee80211_mgmt *mgmt, size_t len,
-			  s32 signal, gfp_t gfp);
+			  s32 signal, gfp_t gfp)
+{
+	return cfg80211_inform_bss_width_frame(wiphy, channel,
+					       NL80211_BSS_CHAN_WIDTH_20,
+					       mgmt, len, signal, gfp);
+}
 
 /**
  * cfg80211_inform_bss - inform cfg80211 of a new BSS
  *
  * @wiphy: the wiphy reporting the BSS
  * @channel: The channel the frame was received on
+ * @scan_width: width of the control channel
  * @bssid: the BSSID of the BSS
  * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
  * @capability: the capability field sent by the peer
@@ -3421,11 +3529,26 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
  * Or %NULL on error.
  */
 struct cfg80211_bss * __must_check
+cfg80211_inform_bss_width(struct wiphy *wiphy,
+			  struct ieee80211_channel *channel,
+			  enum nl80211_bss_scan_width scan_width,
+			  const u8 *bssid, u64 tsf, u16 capability,
+			  u16 beacon_interval, const u8 *ie, size_t ielen,
+			  s32 signal, gfp_t gfp);
+
+static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss(struct wiphy *wiphy,
 		    struct ieee80211_channel *channel,
 		    const u8 *bssid, u64 tsf, u16 capability,
 		    u16 beacon_interval, const u8 *ie, size_t ielen,
-		    s32 signal, gfp_t gfp);
+		    s32 signal, gfp_t gfp)
+{
+	return cfg80211_inform_bss_width(wiphy, channel,
+					 NL80211_BSS_CHAN_WIDTH_20,
+					 bssid, tsf, capability,
+					 beacon_interval, ie, ielen, signal,
+					 gfp);
+}
 
 struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
 				      struct ieee80211_channel *channel,
@@ -3471,6 +3594,19 @@ void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
  */
 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
 
+static inline enum nl80211_bss_scan_width
+cfg80211_chandef_to_scan_width(const struct cfg80211_chan_def *chandef)
+{
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_5:
+		return NL80211_BSS_CHAN_WIDTH_5;
+	case NL80211_CHAN_WIDTH_10:
+		return NL80211_BSS_CHAN_WIDTH_10;
+	default:
+		return NL80211_BSS_CHAN_WIDTH_20;
+	}
+}
+
 /**
  * cfg80211_rx_mlme_mgmt - notification of processed MLME management frame
  * @dev: network device
diff --git a/include/net/checksum.h b/include/net/checksum.h
index 600d1d7..8f59ca5 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -107,11 +107,11 @@ static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to)
 }
 
 struct sk_buff;
-extern void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
-				     __be32 from, __be32 to, int pseudohdr);
-extern void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
-				      const __be32 *from, const __be32 *to,
-				      int pseudohdr);
+void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
+			      __be32 from, __be32 to, int pseudohdr);
+void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
+			       const __be32 *from, const __be32 *to,
+			       int pseudohdr);
 
 static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
 					    __be16 from, __be16 to,
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index 0fee061..f55c145 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -24,7 +24,7 @@ struct cgroup_cls_state
 	u32 classid;
 };
 
-extern void sock_update_classid(struct sock *sk);
+void sock_update_classid(struct sock *sk);
 
 #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
 static inline u32 task_cls_classid(struct task_struct *p)
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index e361f48..4b2b557 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -10,21 +10,25 @@
 
 struct fib_rule {
 	struct list_head	list;
-	atomic_t		refcnt;
 	int			iifindex;
 	int			oifindex;
 	u32			mark;
 	u32			mark_mask;
-	u32			pref;
 	u32			flags;
 	u32			table;
 	u8			action;
+	/* 3 bytes hole, try to use */
 	u32			target;
 	struct fib_rule __rcu	*ctarget;
+	struct net		*fr_net;
+
+	atomic_t		refcnt;
+	u32			pref;
+	int			suppress_ifgroup;
+	int			suppress_prefixlen;
 	char			iifname[IFNAMSIZ];
 	char			oifname[IFNAMSIZ];
 	struct rcu_head		rcu;
-	struct net *		fr_net;
 };
 
 struct fib_lookup_arg {
@@ -46,6 +50,8 @@ struct fib_rules_ops {
 	int			(*action)(struct fib_rule *,
 					  struct flowi *, int,
 					  struct fib_lookup_arg *);
+	bool			(*suppress)(struct fib_rule *,
+					    struct fib_lookup_arg *);
 	int			(*match)(struct fib_rule *,
 					 struct flowi *, int);
 	int			(*configure)(struct fib_rule *,
@@ -80,6 +86,8 @@ struct fib_rules_ops {
 	[FRA_FWMARK]	= { .type = NLA_U32 }, \
 	[FRA_FWMASK]	= { .type = NLA_U32 }, \
 	[FRA_TABLE]     = { .type = NLA_U32 }, \
+	[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
+	[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
 	[FRA_GOTO]	= { .type = NLA_U32 }
 
 static inline void fib_rule_get(struct fib_rule *rule)
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index c6d07cb..8b5b714 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -230,6 +230,10 @@ enum ieee80211_radiotap_type {
 #define	IEEE80211_CHAN_PASSIVE	0x0200	/* Only passive scan allowed */
 #define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
 #define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
+#define	IEEE80211_CHAN_GSM	0x1000	/* GSM (900 MHz) */
+#define	IEEE80211_CHAN_STURBO	0x2000	/* Static Turbo */
+#define	IEEE80211_CHAN_HALF	0x4000	/* Half channel (10 MHz wide) */
+#define	IEEE80211_CHAN_QUARTER	0x8000	/* Quarter channel (5 MHz wide) */
 
 /* For IEEE80211_RADIOTAP_FLAGS */
 #define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 781b3cf..c6acd9f 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -86,12 +86,12 @@ struct tnl_ptk_info {
 #define PACKET_RCVD	0
 #define PACKET_REJECT	1
 
-#define IP_TNL_HASH_BITS   10
+#define IP_TNL_HASH_BITS   7
 #define IP_TNL_HASH_SIZE   (1 << IP_TNL_HASH_BITS)
 
 struct ip_tunnel_net {
-	struct hlist_head *tunnels;
 	struct net_device *fb_tunnel_dev;
+	struct hlist_head tunnels[IP_TNL_HASH_SIZE];
 };
 
 #ifdef CONFIG_INET
diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h
index 0af8b8d..550c2d6 100644
--- a/include/net/irda/irlan_common.h
+++ b/include/net/irda/irlan_common.h
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/if_ether.h>
 
 #include <net/irda/irttp.h>
 
@@ -161,7 +162,7 @@ struct irlan_provider_cb {
 	int access_type;     /* Access type */
 	__u16 send_arb_val;
 
-	__u8 mac_address[6]; /* Generated MAC address for peer device */
+	__u8 mac_address[ETH_ALEN]; /* Generated MAC address for peer device */
 };
 
 /*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5b7a3da..e6905e7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -811,6 +811,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
  *	is stored in the @ampdu_delimiter_crc field)
  * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
+ * @RX_FLAG_10MHZ: 10 MHz (half channel) was used
+ * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR		= BIT(0),
@@ -839,6 +841,8 @@ enum mac80211_rx_flags {
 	RX_FLAG_80P80MHZ		= BIT(24),
 	RX_FLAG_160MHZ			= BIT(25),
 	RX_FLAG_STBC_MASK		= BIT(26) | BIT(27),
+	RX_FLAG_10MHZ			= BIT(28),
+	RX_FLAG_5MHZ			= BIT(29),
 };
 
 #define RX_FLAG_STBC_SHIFT		26
@@ -1004,11 +1008,11 @@ enum ieee80211_smps_mode {
  * @radar_enabled: whether radar detection is enabled
  *
  * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
- *    (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
- *    but actually means the number of transmissions not the number of retries
+ *	(a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
+ *	but actually means the number of transmissions not the number of retries
  * @short_frame_max_tx_count: Maximum number of transmissions for a "short"
- *    frame, called "dot11ShortRetryLimit" in 802.11, but actually means the
- *    number of transmissions not the number of retries
+ *	frame, called "dot11ShortRetryLimit" in 802.11, but actually means the
+ *	number of transmissions not the number of retries
  *
  * @smps_mode: spatial multiplexing powersave mode; note that
  *	%IEEE80211_SMPS_STATIC is used when the device is not
@@ -1092,7 +1096,7 @@ enum ieee80211_vif_flags {
  *	be off when it is %NULL there can still be races and packets could be
  *	processed after it switches back to %NULL.
  * @debugfs_dir: debugfs dentry, can be used by drivers to create own per
- *      interface debug files. Note that it will be NULL for the virtual
+ *	interface debug files. Note that it will be NULL for the virtual
  *	monitor interface (if that is requested.)
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
@@ -1425,10 +1429,10 @@ struct ieee80211_tx_control {
  *	the stack.
  *
  * @IEEE80211_HW_CONNECTION_MONITOR:
- *      The hardware performs its own connection monitoring, including
- *      periodic keep-alives to the AP and probing the AP on beacon loss.
- *      When this flag is set, signaling beacon-loss will cause an immediate
- *      change to disassociated state.
+ *	The hardware performs its own connection monitoring, including
+ *	periodic keep-alives to the AP and probing the AP on beacon loss.
+ *	When this flag is set, signaling beacon-loss will cause an immediate
+ *	change to disassociated state.
  *
  * @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC:
  *	This device needs to get data from beacon before association (i.e.
@@ -1526,10 +1530,10 @@ enum ieee80211_hw_flags {
  * @channel_change_time: time (in microseconds) it takes to change channels.
  *
  * @max_signal: Maximum value for signal (rssi) in RX information, used
- *     only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
+ *	only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
  *
  * @max_listen_interval: max listen interval in units of beacon interval
- *     that HW supports
+ *	that HW supports
  *
  * @queues: number of available hardware transmit queues for
  *	data packets. WMM/QoS requires at least four, these
@@ -2443,7 +2447,7 @@ enum ieee80211_roc_type {
  *	The callback can sleep.
  *
  * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
- *      Currently, this is only used for IBSS mode debugging. Is not a
+ *	Currently, this is only used for IBSS mode debugging. Is not a
  *	required function.
  *	The callback can sleep.
  *
@@ -2877,14 +2881,14 @@ enum ieee80211_tpt_led_trigger_flags {
 };
 
 #ifdef CONFIG_MAC80211_LEDS
-extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
-extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
-extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw);
-extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw);
-extern char *__ieee80211_create_tpt_led_trigger(
-				struct ieee80211_hw *hw, unsigned int flags,
-				const struct ieee80211_tpt_blink *blink_table,
-				unsigned int blink_table_len);
+char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
+char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
+char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw);
+char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw);
+char *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
+					 unsigned int flags,
+					 const struct ieee80211_tpt_blink *blink_table,
+					 unsigned int blink_table_len);
 #endif
 /**
  * ieee80211_get_tx_led_name - get name of TX LED
@@ -4204,8 +4208,10 @@ struct rate_control_ops {
 
 	void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
 	void (*rate_init)(void *priv, struct ieee80211_supported_band *sband,
+			  struct cfg80211_chan_def *chandef,
 			  struct ieee80211_sta *sta, void *priv_sta);
 	void (*rate_update)(void *priv, struct ieee80211_supported_band *sband,
+			    struct cfg80211_chan_def *chandef,
 			    struct ieee80211_sta *sta, void *priv_sta,
 			    u32 changed);
 	void (*free_sta)(void *priv, struct ieee80211_sta *sta,
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 7e748ad..536501a 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -195,68 +195,67 @@ static inline void *neighbour_priv(const struct neighbour *n)
 #define NEIGH_UPDATE_F_ISROUTER			0x40000000
 #define NEIGH_UPDATE_F_ADMIN			0x80000000
 
-extern void			neigh_table_init(struct neigh_table *tbl);
-extern int			neigh_table_clear(struct neigh_table *tbl);
-extern struct neighbour *	neigh_lookup(struct neigh_table *tbl,
-					     const void *pkey,
-					     struct net_device *dev);
-extern struct neighbour *	neigh_lookup_nodev(struct neigh_table *tbl,
-						   struct net *net,
-						   const void *pkey);
-extern struct neighbour *	__neigh_create(struct neigh_table *tbl,
-					       const void *pkey,
-					       struct net_device *dev,
-					       bool want_ref);
+void neigh_table_init(struct neigh_table *tbl);
+int neigh_table_clear(struct neigh_table *tbl);
+struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
+			       struct net_device *dev);
+struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+				     const void *pkey);
+struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
+				 struct net_device *dev, bool want_ref);
 static inline struct neighbour *neigh_create(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev)
 {
 	return __neigh_create(tbl, pkey, dev, true);
 }
-extern void			neigh_destroy(struct neighbour *neigh);
-extern int			__neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, 
-					     u32 flags);
-extern void			neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
-extern int			neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
-extern int			neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
-extern struct neighbour 	*neigh_event_ns(struct neigh_table *tbl,
+void neigh_destroy(struct neighbour *neigh);
+int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
+int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags);
+void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
+int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
+int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
+int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
+int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
+int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
+struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 						u8 *lladdr, void *saddr,
 						struct net_device *dev);
 
-extern struct neigh_parms	*neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
-extern void			neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
+struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+				      struct neigh_table *tbl);
+void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
 
 static inline
-struct net			*neigh_parms_net(const struct neigh_parms *parms)
+struct net *neigh_parms_net(const struct neigh_parms *parms)
 {
 	return read_pnet(&parms->net);
 }
 
-extern unsigned long		neigh_rand_reach_time(unsigned long base);
+unsigned long neigh_rand_reach_time(unsigned long base);
 
-extern void			pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
-					       struct sk_buff *skb);
-extern struct pneigh_entry	*pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
-extern struct pneigh_entry	*__pneigh_lookup(struct neigh_table *tbl,
-						 struct net *net,
-						 const void *key,
-						 struct net_device *dev);
-extern int			pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
+void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+		    struct sk_buff *skb);
+struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net,
+				   const void *key, struct net_device *dev,
+				   int creat);
+struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, struct net *net,
+				     const void *key, struct net_device *dev);
+int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key,
+		  struct net_device *dev);
 
-static inline
-struct net			*pneigh_net(const struct pneigh_entry *pneigh)
+static inline struct net *pneigh_net(const struct pneigh_entry *pneigh)
 {
 	return read_pnet(&pneigh->net);
 }
 
-extern void neigh_app_ns(struct neighbour *n);
-extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
-extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
-extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
+void neigh_app_ns(struct neighbour *n);
+void neigh_for_each(struct neigh_table *tbl,
+		    void (*cb)(struct neighbour *, void *), void *cookie);
+void __neigh_for_each_release(struct neigh_table *tbl,
+			      int (*cb)(struct neighbour *));
+void pneigh_for_each(struct neigh_table *tbl,
+		     void (*cb)(struct pneigh_entry *));
 
 struct neigh_seq_state {
 	struct seq_net_private p;
@@ -270,15 +269,14 @@ struct neigh_seq_state {
 #define NEIGH_SEQ_IS_PNEIGH	0x00000002
 #define NEIGH_SEQ_SKIP_NOARP	0x00000004
 };
-extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int);
-extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
-extern void neigh_seq_stop(struct seq_file *, void *);
-
-extern int			neigh_sysctl_register(struct net_device *dev, 
-						      struct neigh_parms *p,
-						      char *p_name,
-						      proc_handler *proc_handler);
-extern void			neigh_sysctl_unregister(struct neigh_parms *p);
+void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *,
+		      unsigned int);
+void *neigh_seq_next(struct seq_file *, void *, loff_t *);
+void neigh_seq_stop(struct seq_file *, void *);
+
+int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
+			  char *p_name, proc_handler *proc_handler);
+void neigh_sysctl_unregister(struct neigh_parms *p);
 
 static inline void __neigh_parms_put(struct neigh_parms *parms)
 {
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 84e37b1..1313456 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -119,7 +119,6 @@ struct net {
 	struct netns_ipvs	*ipvs;
 #endif
 	struct sock		*diag_nlsk;
-	atomic_t		rt_genid;
 	atomic_t		fnhe_genid;
 };
 
@@ -333,14 +332,42 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header)
 }
 #endif
 
-static inline int rt_genid(struct net *net)
+static inline int rt_genid_ipv4(struct net *net)
 {
-	return atomic_read(&net->rt_genid);
+	return atomic_read(&net->ipv4.rt_genid);
 }
 
-static inline void rt_genid_bump(struct net *net)
+static inline void rt_genid_bump_ipv4(struct net *net)
 {
-	atomic_inc(&net->rt_genid);
+	atomic_inc(&net->ipv4.rt_genid);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static inline int rt_genid_ipv6(struct net *net)
+{
+	return atomic_read(&net->ipv6.rt_genid);
+}
+
+static inline void rt_genid_bump_ipv6(struct net *net)
+{
+	atomic_inc(&net->ipv6.rt_genid);
+}
+#else
+static inline int rt_genid_ipv6(struct net *net)
+{
+	return 0;
+}
+
+static inline void rt_genid_bump_ipv6(struct net *net)
+{
+}
+#endif
+
+/* For callers who don't really care about whether it's IPv4 or IPv6 */
+static inline void rt_genid_bump_all(struct net *net)
+{
+	rt_genid_bump_ipv4(net);
+	rt_genid_bump_ipv6(net);
 }
 
 static inline int fnhe_genid(struct net *net)
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 2ba9de8..bf2ec22 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -77,5 +77,6 @@ struct netns_ipv4 {
 	struct fib_rules_ops	*mr_rules_ops;
 #endif
 #endif
+	atomic_t	rt_genid;
 };
 #endif
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 005e2c2..0fb2401 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -72,6 +72,7 @@ struct netns_ipv6 {
 #endif
 #endif
 	atomic_t		dev_addr_genid;
+	atomic_t		rt_genid;
 };
 
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
index 50ab8c2..379dd5d 100644
--- a/include/net/netprio_cgroup.h
+++ b/include/net/netprio_cgroup.h
@@ -29,7 +29,7 @@ struct cgroup_netprio_state {
 	struct cgroup_subsys_state css;
 };
 
-extern void sock_update_netprioidx(struct sock *sk);
+void sock_update_netprioidx(struct sock *sk);
 
 #if IS_BUILTIN(CONFIG_NETPRIO_CGROUP)
 
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 1317450..2ebef77 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -14,8 +14,8 @@ struct tcf_walker {
 	int	(*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *);
 };
 
-extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
-extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+int register_tcf_proto_ops(struct tcf_proto_ops *ops);
+int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
 
 static inline unsigned long
 __cls_set_class(unsigned long *clp, unsigned long cl)
@@ -126,17 +126,17 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
 	return 0;
 }
 
-extern int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
-			     struct nlattr **tb, struct nlattr *rate_tlv,
-			     struct tcf_exts *exts,
-			     const struct tcf_ext_map *map);
-extern void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
-extern void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
-	                     struct tcf_exts *src);
-extern int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
-	                 const struct tcf_ext_map *map);
-extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
-	                       const struct tcf_ext_map *map);
+int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
+		      struct nlattr **tb, struct nlattr *rate_tlv,
+		      struct tcf_exts *exts,
+		      const struct tcf_ext_map *map);
+void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
+void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
+		     struct tcf_exts *src);
+int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
+		  const struct tcf_ext_map *map);
+int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
+			const struct tcf_ext_map *map);
 
 /**
  * struct tcf_pkt_info - packet information
@@ -239,14 +239,14 @@ struct tcf_ematch_ops {
 	struct list_head	link;
 };
 
-extern int tcf_em_register(struct tcf_ematch_ops *);
-extern void tcf_em_unregister(struct tcf_ematch_ops *);
-extern int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *,
-				struct tcf_ematch_tree *);
-extern void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *);
-extern int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
-extern int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
-			       struct tcf_pkt_info *);
+int tcf_em_register(struct tcf_ematch_ops *);
+void tcf_em_unregister(struct tcf_ematch_ops *);
+int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *,
+			 struct tcf_ematch_tree *);
+void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *);
+int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
+int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
+			struct tcf_pkt_info *);
 
 /**
  * tcf_em_tree_change - replace ematch tree of a running classifier
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 388bf8b..f7c24f8 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -64,8 +64,8 @@ struct qdisc_watchdog {
 	struct Qdisc	*qdisc;
 };
 
-extern void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc);
-extern void qdisc_watchdog_schedule_ns(struct qdisc_watchdog *wd, u64 expires);
+void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc);
+void qdisc_watchdog_schedule_ns(struct qdisc_watchdog *wd, u64 expires);
 
 static inline void qdisc_watchdog_schedule(struct qdisc_watchdog *wd,
 					   psched_time_t expires)
@@ -73,31 +73,31 @@ static inline void qdisc_watchdog_schedule(struct qdisc_watchdog *wd,
 	qdisc_watchdog_schedule_ns(wd, PSCHED_TICKS2NS(expires));
 }
 
-extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd);
+void qdisc_watchdog_cancel(struct qdisc_watchdog *wd);
 
 extern struct Qdisc_ops pfifo_qdisc_ops;
 extern struct Qdisc_ops bfifo_qdisc_ops;
 extern struct Qdisc_ops pfifo_head_drop_qdisc_ops;
 
-extern int fifo_set_limit(struct Qdisc *q, unsigned int limit);
-extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
-				      unsigned int limit);
-
-extern int register_qdisc(struct Qdisc_ops *qops);
-extern int unregister_qdisc(struct Qdisc_ops *qops);
-extern void qdisc_list_del(struct Qdisc *q);
-extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
-extern struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
-extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
-		struct nlattr *tab);
-extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
-extern void qdisc_put_stab(struct qdisc_size_table *tab);
-extern void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc);
-extern int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
-			   struct net_device *dev, struct netdev_queue *txq,
-			   spinlock_t *root_lock);
-
-extern void __qdisc_run(struct Qdisc *q);
+int fifo_set_limit(struct Qdisc *q, unsigned int limit);
+struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
+			       unsigned int limit);
+
+int register_qdisc(struct Qdisc_ops *qops);
+int unregister_qdisc(struct Qdisc_ops *qops);
+void qdisc_list_del(struct Qdisc *q);
+struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
+struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
+struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
+					struct nlattr *tab);
+void qdisc_put_rtab(struct qdisc_rate_table *tab);
+void qdisc_put_stab(struct qdisc_size_table *tab);
+void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc);
+int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
+		    struct net_device *dev, struct netdev_queue *txq,
+		    spinlock_t *root_lock);
+
+void __qdisc_run(struct Qdisc *q);
 
 static inline void qdisc_run(struct Qdisc *q)
 {
@@ -105,10 +105,10 @@ static inline void qdisc_run(struct Qdisc *q)
 		__qdisc_run(q);
 }
 
-extern int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
-			      struct tcf_result *res);
-extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
 		       struct tcf_result *res);
+int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+		struct tcf_result *res);
 
 /* Calculate maximal size of packet seen by hard_start_xmit
    routine of this device.
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 6eab6336..ffc9d88 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -350,30 +350,32 @@ qdisc_class_find(const struct Qdisc_class_hash *hash, u32 id)
 	return NULL;
 }
 
-extern int qdisc_class_hash_init(struct Qdisc_class_hash *);
-extern void qdisc_class_hash_insert(struct Qdisc_class_hash *, struct Qdisc_class_common *);
-extern void qdisc_class_hash_remove(struct Qdisc_class_hash *, struct Qdisc_class_common *);
-extern void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *);
-extern void qdisc_class_hash_destroy(struct Qdisc_class_hash *);
-
-extern void dev_init_scheduler(struct net_device *dev);
-extern void dev_shutdown(struct net_device *dev);
-extern void dev_activate(struct net_device *dev);
-extern void dev_deactivate(struct net_device *dev);
-extern void dev_deactivate_many(struct list_head *head);
-extern struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
-				     struct Qdisc *qdisc);
-extern void qdisc_reset(struct Qdisc *qdisc);
-extern void qdisc_destroy(struct Qdisc *qdisc);
-extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
-extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
-				 struct Qdisc_ops *ops);
-extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
-				       struct Qdisc_ops *ops, u32 parentid);
-extern void __qdisc_calculate_pkt_len(struct sk_buff *skb,
-				      const struct qdisc_size_table *stab);
-extern void tcf_destroy(struct tcf_proto *tp);
-extern void tcf_destroy_chain(struct tcf_proto **fl);
+int qdisc_class_hash_init(struct Qdisc_class_hash *);
+void qdisc_class_hash_insert(struct Qdisc_class_hash *,
+			     struct Qdisc_class_common *);
+void qdisc_class_hash_remove(struct Qdisc_class_hash *,
+			     struct Qdisc_class_common *);
+void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *);
+void qdisc_class_hash_destroy(struct Qdisc_class_hash *);
+
+void dev_init_scheduler(struct net_device *dev);
+void dev_shutdown(struct net_device *dev);
+void dev_activate(struct net_device *dev);
+void dev_deactivate(struct net_device *dev);
+void dev_deactivate_many(struct list_head *head);
+struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
+			      struct Qdisc *qdisc);
+void qdisc_reset(struct Qdisc *qdisc);
+void qdisc_destroy(struct Qdisc *qdisc);
+void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
+struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
+			  struct Qdisc_ops *ops);
+struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
+				struct Qdisc_ops *ops, u32 parentid);
+void __qdisc_calculate_pkt_len(struct sk_buff *skb,
+			       const struct qdisc_size_table *stab);
+void tcf_destroy(struct tcf_proto *tp);
+void tcf_destroy_chain(struct tcf_proto **fl);
 
 /* Reset all TX qdiscs greater then index of a device.  */
 static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
@@ -692,7 +694,8 @@ static inline u64 psched_l2t_ns(const struct psched_ratecfg *r,
 	return ((u64)(len + r->overhead) * r->mult) >> r->shift;
 }
 
-extern void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf);
+void psched_ratecfg_precompute(struct psched_ratecfg *r,
+			       const struct tc_ratespec *conf);
 
 static inline void psched_ratecfg_getrate(struct tc_ratespec *res,
 					  const struct psched_ratecfg *r)
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 49bc957..754c511 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -22,7 +22,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h
index 0cb08e6..483e630 100644
--- a/include/net/sctp/checksum.h
+++ b/include/net/sctp/checksum.h
@@ -25,7 +25,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
@@ -85,4 +85,19 @@ static inline __le32 sctp_end_cksum(__u32 crc32)
 	return cpu_to_le32(~crc32);
 }
 
+/* Calculate the CRC32C checksum of an SCTP packet.  */
+static inline __le32 sctp_compute_cksum(const struct sk_buff *skb,
+					unsigned int offset)
+{
+	const struct sk_buff *iter;
+
+	__u32 crc32 = sctp_start_cksum(skb->data + offset,
+				       skb_headlen(skb) - offset);
+	skb_walk_frags(skb, iter)
+		crc32 = sctp_update_cksum((__u8 *) iter->data,
+					  skb_headlen(iter), crc32);
+
+	return sctp_end_cksum(crc32);
+}
+
 #endif /* __sctp_checksum_h__ */
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index ca50e075..a1e7aa5 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -25,7 +25,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index d8e37ec..cb28df9 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -27,7 +27,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
@@ -613,7 +613,7 @@ static inline void sctp_v4_map_v6(union sctp_addr *addr)
  */
 static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
 {
-	if (t->dst && !dst_check(t->dst, 0)) {
+	if (t->dst && !dst_check(t->dst, t->dst_cookie)) {
 		dst_release(t->dst);
 		t->dst = NULL;
 	}
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 2a82d13..2aa66dd 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -27,7 +27,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email addresses:
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index e745c92..d9c93a7 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -25,7 +25,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email addresses:
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
@@ -782,6 +782,7 @@ struct sctp_transport {
 
 	/* Has this transport moved the ctsn since we last sacked */
 	__u32 sack_generation;
+	u32 dst_cookie;
 
 	struct flowi fl;
 
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index 2c5d2b4..c361d6f 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index ca4693b..34f0d34 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -31,7 +31,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index 00e50ba..add3237 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -30,7 +30,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email addresses:
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/net/sock.h b/include/net/sock.h
index 31d5cfb..ab6a8b7 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -746,11 +746,6 @@ static inline int sk_stream_wspace(const struct sock *sk)
 
 extern void sk_stream_write_space(struct sock *sk);
 
-static inline bool sk_stream_memory_free(const struct sock *sk)
-{
-	return sk->sk_wmem_queued < sk->sk_sndbuf;
-}
-
 /* OOB backlog add */
 static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
@@ -950,6 +945,7 @@ struct proto {
 	unsigned int		inuse_idx;
 #endif
 
+	bool			(*stream_memory_free)(const struct sock *sk);
 	/* Memory pressure */
 	void			(*enter_memory_pressure)(struct sock *sk);
 	atomic_long_t		*memory_allocated;	/* Current allocated memory. */
@@ -1088,6 +1084,21 @@ static inline struct cg_proto *parent_cg_proto(struct proto *proto,
 }
 #endif
 
+static inline bool sk_stream_memory_free(const struct sock *sk)
+{
+	if (sk->sk_wmem_queued >= sk->sk_sndbuf)
+		return false;
+
+	return sk->sk_prot->stream_memory_free ?
+		sk->sk_prot->stream_memory_free(sk) : true;
+}
+
+static inline bool sk_stream_is_writeable(const struct sock *sk)
+{
+	return sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) &&
+	       sk_stream_memory_free(sk);
+}
+
 
 static inline bool sk_has_memory_pressure(const struct sock *sk)
 {
@@ -1509,6 +1520,7 @@ extern struct sk_buff		*sock_rmalloc(struct sock *sk,
 					      unsigned long size, int force,
 					      gfp_t priority);
 extern void			sock_wfree(struct sk_buff *skb);
+extern void			skb_orphan_partial(struct sk_buff *skb);
 extern void			sock_rfree(struct sk_buff *skb);
 extern void			sock_edemux(struct sk_buff *skb);
 
@@ -2249,6 +2261,8 @@ static inline struct sock *skb_steal_sock(struct sk_buff *skb)
 extern void sock_enable_timestamp(struct sock *sk, int flag);
 extern int sock_get_timestamp(struct sock *, struct timeval __user *);
 extern int sock_get_timestampns(struct sock *, struct timespec __user *);
+extern int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
+			      int level, int type);
 
 /*
  *	Enable debug/info messages
diff --git a/include/net/tcp.h b/include/net/tcp.h
index d198005..27b652f 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -192,10 +192,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 #define TCPOLEN_TIMESTAMP      10
 #define TCPOLEN_MD5SIG         18
 #define TCPOLEN_EXP_FASTOPEN_BASE  4
-#define TCPOLEN_COOKIE_BASE    2	/* Cookie-less header extension */
-#define TCPOLEN_COOKIE_PAIR    3	/* Cookie pair header extension */
-#define TCPOLEN_COOKIE_MIN     (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN)
-#define TCPOLEN_COOKIE_MAX     (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MAX)
 
 /* But this is what stacks really send out. */
 #define TCPOLEN_TSTAMP_ALIGNED		12
@@ -284,6 +280,7 @@ extern int sysctl_tcp_thin_dupack;
 extern int sysctl_tcp_early_retrans;
 extern int sysctl_tcp_limit_output_bytes;
 extern int sysctl_tcp_challenge_ack_limit;
+extern unsigned int sysctl_tcp_notsent_lowat;
 
 extern atomic_long_t tcp_memory_allocated;
 extern struct percpu_counter tcp_sockets_allocated;
@@ -591,7 +588,6 @@ extern void tcp_initialize_rcv_mss(struct sock *sk);
 extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
 extern int tcp_mss_to_mtu(struct sock *sk, int mss);
 extern void tcp_mtup_init(struct sock *sk);
-extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt);
 extern void tcp_init_buffer_space(struct sock *sk);
 
 static inline void tcp_bound_rto(const struct sock *sk)
@@ -1094,15 +1090,6 @@ static inline void tcp_openreq_init(struct request_sock *req,
 	ireq->loc_port = tcp_hdr(skb)->dest;
 }
 
-/* Compute time elapsed between SYNACK and the ACK completing 3WHS */
-static inline void tcp_synack_rtt_meas(struct sock *sk,
-				       struct request_sock *req)
-{
-	if (tcp_rsk(req)->snt_synack)
-		tcp_valid_rtt_meas(sk,
-		    tcp_time_stamp - tcp_rsk(req)->snt_synack);
-}
-
 extern void tcp_enter_memory_pressure(struct sock *sk);
 
 static inline int keepalive_intvl_when(const struct tcp_sock *tp)
@@ -1549,6 +1536,19 @@ extern int tcp_gro_complete(struct sk_buff *skb);
 extern void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr,
 				__be32 daddr);
 
+static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp)
+{
+	return tp->notsent_lowat ?: sysctl_tcp_notsent_lowat;
+}
+
+static inline bool tcp_stream_memory_free(const struct sock *sk)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	u32 notsent_bytes = tp->write_seq - tp->snd_nxt;
+
+	return notsent_bytes < tcp_notsent_lowat(tp);
+}
+
 #ifdef CONFIG_PROC_FS
 extern int tcp4_proc_init(void);
 extern void tcp4_proc_exit(void);
diff --git a/include/net/udp.h b/include/net/udp.h
index 74c10ec..ef2e0b7 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -183,6 +183,7 @@ extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
 			    struct msghdr *msg, size_t len);
 extern int udp_push_pending_frames(struct sock *sk);
 extern void udp_flush_pending_frames(struct sock *sk);
+extern void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
 extern int udp_rcv(struct sk_buff *skb);
 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 extern int udp_disconnect(struct sock *sk, int flags);
diff --git a/include/net/vsock_addr.h b/include/net/vsock_addr.h
new file mode 100644
index 0000000..9ccd531
--- /dev/null
+++ b/include/net/vsock_addr.h
@@ -0,0 +1,30 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _VSOCK_ADDR_H_
+#define _VSOCK_ADDR_H_
+
+#include <linux/vm_sockets.h>
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port);
+int vsock_addr_validate(const struct sockaddr_vm *addr);
+bool vsock_addr_bound(const struct sockaddr_vm *addr);
+void vsock_addr_unbind(struct sockaddr_vm *addr);
+bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
+			    const struct sockaddr_vm *other);
+int vsock_addr_cast(const struct sockaddr *addr, size_t len,
+		    struct sockaddr_vm **out_addr);
+
+#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 94ce082..89d3d8a 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1548,7 +1548,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32
 int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
 u32 xfrm_get_acqseq(void);
 extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
+struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
 				 u8 mode, u32 reqid, u8 proto,
 				 const xfrm_address_t *daddr,
 				 const xfrm_address_t *saddr, int create,
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
new file mode 100644
index 0000000..d35412a
--- /dev/null
+++ b/include/sound/rcar_snd.h
@@ -0,0 +1,84 @@
+/*
+ * Renesas R-Car SRU/SCU/SSIU/SSI support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RCAR_SND_H
+#define RCAR_SND_H
+
+#include <linux/sh_clk.h>
+
+#define RSND_GEN1_SRU	0
+#define RSND_GEN1_ADG	1
+#define RSND_GEN1_SSI	2
+
+#define RSND_GEN2_SRU	0
+#define RSND_GEN2_ADG	1
+#define RSND_GEN2_SSIU	2
+#define RSND_GEN2_SSI	3
+
+#define RSND_BASE_MAX	4
+
+/*
+ * flags
+ *
+ * 0xAB000000
+ *
+ * A : clock sharing settings
+ * B : SSI direction
+ */
+#define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
+#define RSND_SSI_CLK_FROM_ADG		(1 << 30) /* clock parent is master */
+#define RSND_SSI_SYNC			(1 << 29) /* SSI34_sync etc */
+#define RSND_SSI_DEPENDENT		(1 << 28) /* SSI needs SRU/SCU */
+
+#define RSND_SSI_PLAY			(1 << 24)
+
+#define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags)	\
+{ .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
+#define RSND_SSI_UNUSED \
+{ .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 }
+
+struct rsnd_ssi_platform_info {
+	int dai_id;
+	int dma_id;
+	int pio_irq;
+	u32 flags;
+};
+
+/*
+ * flags
+ */
+#define RSND_SCU_USB_HPBIF		(1 << 31) /* it needs RSND_SSI_DEPENDENT */
+
+struct rsnd_scu_platform_info {
+	u32 flags;
+};
+
+/*
+ * flags
+ *
+ * 0x0000000A
+ *
+ * A : generation
+ */
+#define RSND_GEN1	(1 << 0) /* fixme */
+#define RSND_GEN2	(2 << 0) /* fixme */
+
+struct rcar_snd_info {
+	u32 flags;
+	struct rsnd_ssi_platform_info *ssi_info;
+	int ssi_info_nr;
+	struct rsnd_scu_platform_info *scu_info;
+	int scu_info_nr;
+	int (*start)(int id);
+	int (*stop)(int id);
+};
+
+#endif
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 3e479f4..c728d28 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -70,121 +70,144 @@ struct device;
 	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 
+#define SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) \
+	.reg = wreg, .mask = 1, .shift = wshift, \
+	.on_val = winvert ? 0 : 1, .off_val = winvert ? 1 : 0
+
 /* path domain */
 #define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
 	 wcontrols, wncontrols) \
-{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
+{	.id = snd_soc_dapm_pga, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
 #define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
 	 wcontrols, wncontrols) \
-{	.id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
+{	.id = snd_soc_dapm_out_drv, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
 #define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
 	 wcontrols, wncontrols)\
-{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
+{	.id = snd_soc_dapm_mixer, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = 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, .kcontrol_news = wcontrols, \
-	.num_kcontrols = wncontrols}
+{       .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = 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, .kcontrol_news = NULL, .num_kcontrols = 0}
+{	.id = snd_soc_dapm_micbias, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = NULL, .num_kcontrols = 0}
 #define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
-{	.id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
+{	.id = snd_soc_dapm_switch, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
+{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{	.id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
+{	.id = snd_soc_dapm_virt_mux, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{	.id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \
-	.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
-	.num_kcontrols = 1}
+{	.id = snd_soc_dapm_value_mux, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1}
 
 /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
 #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
 	 wcontrols) \
-{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
+{	.id = snd_soc_dapm_pga, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
 #define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
 	 wcontrols)\
-{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
+{	.id = snd_soc_dapm_mixer, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
 #define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
 	 wcontrols)\
-{       .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
-	.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
-	.num_kcontrols = ARRAY_SIZE(wcontrols)}
+{       .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
 
 /* path domain with event - event handler must return 0 for success */
 #define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
 	wncontrols, wevent, wflags) \
-{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
+{	.id = snd_soc_dapm_pga, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
 	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
 	wncontrols, wevent, wflags) \
-{	.id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
+{	.id = snd_soc_dapm_out_drv, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
 	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
 	wncontrols, wevent, wflags) \
-{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
+{	.id = snd_soc_dapm_mixer, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = 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, .kcontrol_news = wcontrols, \
+{       .id = snd_soc_dapm_mixer, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, \
 	.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
+{	.id = snd_soc_dapm_switch, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1, \
 	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
+{	.id = snd_soc_dapm_mux, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1, \
 	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
+{	.id = snd_soc_dapm_virt_mux, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = 1, \
 	.event = wevent, .event_flags = wflags}
 
 /* additional sequencing control within an event type */
 #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .event = wevent, .event_flags = wflags, \
+{	.id = snd_soc_dapm_pga, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.event = wevent, .event_flags = wflags, \
 	.subseq = wsubseq}
 #define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
 	wflags)	\
-{	.id = snd_soc_dapm_supply, .name = wname, .reg = wreg,	\
-	.shift = wshift, .invert = winvert, .event = wevent, \
-	.event_flags = wflags, .subseq = wsubseq}
+{	.id = snd_soc_dapm_supply, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.event = wevent, .event_flags = wflags, .subseq = wsubseq}
 
 /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
 #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
+{	.id = snd_soc_dapm_pga, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
 	.event = wevent, .event_flags = wflags}
 #define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
-{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
+{	.id = snd_soc_dapm_mixer, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
 	.event = wevent, .event_flags = wflags}
 #define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
 	wcontrols, wevent, wflags) \
-{       .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
-	.invert = winvert, .kcontrol_news = wcontrols, \
-	.num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags}
+{       .id = snd_soc_dapm_mixer, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
+	.event = wevent, .event_flags = wflags}
 
 /* events that are pre and post DAPM */
 #define SND_SOC_DAPM_PRE(wname, wevent) \
@@ -199,35 +222,36 @@ struct device;
 /* stream domain */
 #define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
 {	.id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
-	.reg = wreg, .shift = wshift, .invert = winvert }
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
 #define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
 			      wevent, wflags)				\
 {	.id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
-	.reg = wreg, .shift = wshift, .invert = winvert, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
 	.event = wevent, .event_flags = wflags }
 #define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
 {	.id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
-	.reg = wreg, .shift = wshift, .invert = winvert }
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
 #define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
 			     wevent, wflags)				\
 {	.id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
-	.reg = wreg, .shift = wshift, .invert = winvert, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
 	.event = wevent, .event_flags = wflags }
 #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
-{	.id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
-	.shift = wshift, .invert = winvert}
+{	.id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) }
 #define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
 			   wevent, wflags)				\
-{	.id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
-	.shift = wshift, .invert = winvert, \
+{	.id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
 	.event = wevent, .event_flags = wflags}
+
 #define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
-{	.id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
-	.shift = wshift, .invert = winvert}
+{	.id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
 #define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
 			   wevent, wflags)				\
-{	.id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
-	.shift = wshift, .invert = winvert, \
+{	.id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
 	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
 {	.id = snd_soc_dapm_clock_supply, .name = wname, \
@@ -241,14 +265,14 @@ struct device;
 	.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
 	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
 #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
-{	.id = snd_soc_dapm_supply, .name = wname, .reg = wreg,	\
-	.shift = wshift, .invert = winvert, .event = wevent, \
-	.event_flags = wflags}
+{	.id = snd_soc_dapm_supply, .name = wname, \
+	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
+	.event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags)	    \
 {	.id = snd_soc_dapm_regulator_supply, .name = wname, \
 	.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
 	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
-	.invert = wflags}
+	.on_val = wflags}
 
 
 /* dapm kcontrol types */
@@ -256,14 +280,26 @@ struct device;
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, \
 	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
-	.private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
+#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
 #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, \
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
 	.tlv.p = (tlv_array), \
 	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
-	.private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
+#define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_volsw, \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+	.tlv.p = (tlv_array), \
+	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
 #define SOC_DAPM_ENUM(xname, xenum) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_enum_double, \
@@ -333,6 +369,7 @@ struct snd_soc_dapm_route;
 struct snd_soc_dapm_context;
 struct regulator;
 struct snd_soc_dapm_widget_list;
+struct snd_soc_dapm_update;
 
 int dapm_reg_event(struct snd_soc_dapm_widget *w,
 		   struct snd_kcontrol *kcontrol, int event);
@@ -391,10 +428,12 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
 void snd_soc_dapm_shutdown(struct snd_soc_card *card);
 
 /* external DAPM widget events */
-int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
-		struct snd_kcontrol *kcontrol, int connect);
-int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
-				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e);
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
+		struct snd_kcontrol *kcontrol, int connect,
+		struct snd_soc_dapm_update *update);
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
+		struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
+		struct snd_soc_dapm_update *update);
 
 /* dapm sys fs - used by the core */
 int snd_soc_dapm_sys_add(struct device *dev);
@@ -424,6 +463,8 @@ void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
 int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
 	struct snd_soc_dapm_widget_list **list);
 
+struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
+
 /* dapm widget types */
 enum snd_soc_dapm_type {
 	snd_soc_dapm_input = 0,		/* input pin */
@@ -455,6 +496,7 @@ enum snd_soc_dapm_type {
 	snd_soc_dapm_dai_in,		/* link to DAI structure */
 	snd_soc_dapm_dai_out,
 	snd_soc_dapm_dai_link,		/* link between two DAI structures */
+	snd_soc_dapm_kcontrol,		/* Auto-disabled kcontrol */
 };
 
 enum snd_soc_dapm_subclass {
@@ -485,7 +527,6 @@ struct snd_soc_dapm_path {
 	/* source (input) and sink (output) widgets */
 	struct snd_soc_dapm_widget *source;
 	struct snd_soc_dapm_widget *sink;
-	struct snd_kcontrol *kcontrol;
 
 	/* status */
 	u32 connect:1;	/* source and sink widgets are connected */
@@ -498,6 +539,7 @@ struct snd_soc_dapm_path {
 
 	struct list_head list_source;
 	struct list_head list_sink;
+	struct list_head list_kcontrol;
 	struct list_head list;
 };
 
@@ -518,12 +560,10 @@ struct snd_soc_dapm_widget {
 	/* dapm control */
 	int reg;				/* negative reg = no direct dapm */
 	unsigned char shift;			/* bits to shift */
-	unsigned int value;				/* widget current value */
 	unsigned int mask;			/* non-shifted mask */
 	unsigned int on_val;			/* on state value */
 	unsigned int off_val;			/* off state value */
 	unsigned char power:1;			/* block power status */
-	unsigned char invert:1;			/* invert the power bit */
 	unsigned char active:1;			/* active stream on DAC, ADC's */
 	unsigned char connected:1;		/* connected codec pin */
 	unsigned char new:1;			/* cnew complete */
@@ -559,7 +599,6 @@ struct snd_soc_dapm_widget {
 };
 
 struct snd_soc_dapm_update {
-	struct snd_soc_dapm_widget *widget;
 	struct snd_kcontrol *kcontrol;
 	int reg;
 	int mask;
@@ -573,8 +612,6 @@ struct snd_soc_dapm_context {
 	struct delayed_work delayed_work;
 	unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
 
-	struct snd_soc_dapm_update *update;
-
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 			     enum snd_soc_dapm_type, int);
 
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index 04598f1..047d657 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -133,6 +133,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
 /* internal use only */
 int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
 int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
-int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *);
+int soc_dpcm_runtime_update(struct snd_soc_card *);
 
 #endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6eabee7..13d388a 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -30,13 +30,13 @@
 /*
  * Convenience kcontrol builders
  */
-#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \
+#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \
 	((unsigned long)&(struct soc_mixer_control) \
 	{.reg = xreg, .rreg = xreg, .shift = shift_left, \
 	.rshift = shift_right, .max = xmax, .platform_max = xmax, \
-	.invert = xinvert})
-#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
-	SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
+	.invert = xinvert, .autodisable = xautodisable})
+#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
+	SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
 #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
 	((unsigned long)&(struct soc_mixer_control) \
 	{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
@@ -52,7 +52,7 @@
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
 	.put = snd_soc_put_volsw, \
-	.private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
 #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
@@ -68,7 +68,7 @@
 	.tlv.p = (tlv_array), \
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
 	.put = snd_soc_put_volsw, \
-	.private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
 #define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -97,7 +97,7 @@
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
 	.put = snd_soc_put_volsw, \
 	.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
-					  max, invert) }
+					  max, invert, 0) }
 #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
 	.info = snd_soc_info_volsw, \
@@ -119,7 +119,7 @@
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
 	.put = snd_soc_put_volsw, \
 	.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
-					  max, invert) }
+					  max, invert, 0) }
 #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -190,14 +190,14 @@
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
-	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
+	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
 #define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
 	 xhandler_get, xhandler_put) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = \
-		SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) }
+		SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) }
 #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
 	 xhandler_get, xhandler_put, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -206,7 +206,7 @@
 	.tlv.p = (tlv_array), \
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
-	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
+	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
 #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
 	 xhandler_get, xhandler_put, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -216,7 +216,7 @@
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
-					  xmax, xinvert) }
+					  xmax, xinvert, 0) }
 #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
 	 xhandler_get, xhandler_put, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -475,6 +475,8 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 				  void *data, const char *long_name,
 				  const char *prefix);
+struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
+					       const char *name);
 int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
 	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
@@ -1042,6 +1044,7 @@ struct snd_soc_card {
 	/* Generic DAPM context for the card */
 	struct snd_soc_dapm_context dapm;
 	struct snd_soc_dapm_stats dapm_stats;
+	struct snd_soc_dapm_update *update;
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_card_root;
@@ -1087,7 +1090,9 @@ struct snd_soc_pcm_runtime {
 /* mixer control */
 struct soc_mixer_control {
 	int min, max, platform_max;
-	unsigned int reg, rreg, shift, rshift, invert;
+	unsigned int reg, rreg, shift, rshift;
+	unsigned int invert:1;
+	unsigned int autodisable:1;
 };
 
 struct soc_bytes {
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index 098c4de..2d4fa59 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -71,6 +71,7 @@ struct snd_tea575x {
 	int (*ext_init)(struct snd_tea575x *tea);
 };
 
+int snd_tea575x_hw_init(struct snd_tea575x *tea);
 int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner);
 void snd_tea575x_exit(struct snd_tea575x *tea);
 void snd_tea575x_set_freq(struct snd_tea575x *tea);
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 2068db2..d892b55 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -64,10 +64,10 @@ struct extent_status;
 	{ EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER,	"LAST_CLUSTER" })
 
 #define show_extent_status(status) __print_flags(status, "",	\
-	{ (1 << 3),	"W" }, 					\
-	{ (1 << 2),	"U" },					\
-	{ (1 << 1),	"D" },					\
-	{ (1 << 0),	"H" })
+	{ EXTENT_STATUS_WRITTEN,	"W" },			\
+	{ EXTENT_STATUS_UNWRITTEN,	"U" },			\
+	{ EXTENT_STATUS_DELAYED,	"D" },			\
+	{ EXTENT_STATUS_HOLE,		"H" })
 
 
 TRACE_EVENT(ext4_free_inode,
@@ -2192,7 +2192,7 @@ TRACE_EVENT(ext4_ext_remove_space_done,
 		  (unsigned short) __entry->eh_entries)
 );
 
-TRACE_EVENT(ext4_es_insert_extent,
+DECLARE_EVENT_CLASS(ext4__es_extent,
 	TP_PROTO(struct inode *inode, struct extent_status *es),
 
 	TP_ARGS(inode, es),
@@ -2212,7 +2212,7 @@ TRACE_EVENT(ext4_es_insert_extent,
 		__entry->lblk	= es->es_lblk;
 		__entry->len	= es->es_len;
 		__entry->pblk	= ext4_es_pblock(es);
-		__entry->status	= ext4_es_status(es) >> 60;
+		__entry->status	= ext4_es_status(es);
 	),
 
 	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
@@ -2222,6 +2222,18 @@ TRACE_EVENT(ext4_es_insert_extent,
 		  __entry->pblk, show_extent_status(__entry->status))
 );
 
+DEFINE_EVENT(ext4__es_extent, ext4_es_insert_extent,
+	TP_PROTO(struct inode *inode, struct extent_status *es),
+
+	TP_ARGS(inode, es)
+);
+
+DEFINE_EVENT(ext4__es_extent, ext4_es_cache_extent,
+	TP_PROTO(struct inode *inode, struct extent_status *es),
+
+	TP_ARGS(inode, es)
+);
+
 TRACE_EVENT(ext4_es_remove_extent,
 	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len),
 
@@ -2289,7 +2301,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
 		__entry->lblk	= es->es_lblk;
 		__entry->len	= es->es_len;
 		__entry->pblk	= ext4_es_pblock(es);
-		__entry->status	= ext4_es_status(es) >> 60;
+		__entry->status	= ext4_es_status(es);
 	),
 
 	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
@@ -2343,7 +2355,7 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
 		__entry->lblk	= es->es_lblk;
 		__entry->len	= es->es_len;
 		__entry->pblk	= ext4_es_pblock(es);
-		__entry->status	= ext4_es_status(es) >> 60;
+		__entry->status	= ext4_es_status(es);
 		__entry->found	= found;
 	),
 
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
index 6bc943e..d0c6134 100644
--- a/include/trace/events/kmem.h
+++ b/include/trace/events/kmem.h
@@ -268,11 +268,13 @@ TRACE_EVENT(mm_page_alloc_extfrag,
 
 	TP_PROTO(struct page *page,
 			int alloc_order, int fallback_order,
-			int alloc_migratetype, int fallback_migratetype),
+			int alloc_migratetype, int fallback_migratetype,
+			int change_ownership),
 
 	TP_ARGS(page,
 		alloc_order, fallback_order,
-		alloc_migratetype, fallback_migratetype),
+		alloc_migratetype, fallback_migratetype,
+		change_ownership),
 
 	TP_STRUCT__entry(
 		__field(	struct page *,	page			)
@@ -280,6 +282,7 @@ TRACE_EVENT(mm_page_alloc_extfrag,
 		__field(	int,		fallback_order		)
 		__field(	int,		alloc_migratetype	)
 		__field(	int,		fallback_migratetype	)
+		__field(	int,		change_ownership	)
 	),
 
 	TP_fast_assign(
@@ -288,6 +291,7 @@ TRACE_EVENT(mm_page_alloc_extfrag,
 		__entry->fallback_order		= fallback_order;
 		__entry->alloc_migratetype	= alloc_migratetype;
 		__entry->fallback_migratetype	= fallback_migratetype;
+		__entry->change_ownership	= change_ownership;
 	),
 
 	TP_printk("page=%p pfn=%lu alloc_order=%d fallback_order=%d pageblock_order=%d alloc_migratetype=%d fallback_migratetype=%d fragmenting=%d change_ownership=%d",
@@ -299,7 +303,7 @@ TRACE_EVENT(mm_page_alloc_extfrag,
 		__entry->alloc_migratetype,
 		__entry->fallback_migratetype,
 		__entry->fallback_order < pageblock_order,
-		__entry->alloc_migratetype == __entry->fallback_migratetype)
+		__entry->change_ownership)
 );
 
 #endif /* _TRACE_KMEM_H */
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 8e42410..cda100d 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -66,6 +66,43 @@ TRACE_EVENT(machine_suspend,
 	TP_printk("state=%lu", (unsigned long)__entry->state)
 );
 
+TRACE_EVENT(device_pm_report_time,
+
+	TP_PROTO(struct device *dev, const char *pm_ops, s64 ops_time,
+		 char *pm_event_str, int error),
+
+	TP_ARGS(dev, pm_ops, ops_time, pm_event_str, error),
+
+	TP_STRUCT__entry(
+		__string(device, dev_name(dev))
+		__string(driver, dev_driver_string(dev))
+		__string(parent, dev->parent ? dev_name(dev->parent) : "none")
+		__string(pm_ops, pm_ops ? pm_ops : "none ")
+		__string(pm_event_str, pm_event_str)
+		__field(s64, ops_time)
+		__field(int, error)
+	),
+
+	TP_fast_assign(
+		const char *tmp = dev->parent ? dev_name(dev->parent) : "none";
+		const char *tmp_i = pm_ops ? pm_ops : "none ";
+
+		__assign_str(device, dev_name(dev));
+		__assign_str(driver, dev_driver_string(dev));
+		__assign_str(parent, tmp);
+		__assign_str(pm_ops, tmp_i);
+		__assign_str(pm_event_str, pm_event_str);
+		__entry->ops_time = ops_time;
+		__entry->error = error;
+	),
+
+	/* ops_str has an extra space at the end */
+	TP_printk("%s %s parent=%s state=%s ops=%snsecs=%lld err=%d",
+		__get_str(driver), __get_str(device), __get_str(parent),
+		__get_str(pm_event_str), __get_str(pm_ops),
+		__entry->ops_time, __entry->error)
+);
+
 DECLARE_EVENT_CLASS(wakeup_source,
 
 	TP_PROTO(const char *name, unsigned int state),
diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h
index 63cfccc..132a985 100644
--- a/include/trace/events/vmscan.h
+++ b/include/trace/events/vmscan.h
@@ -202,7 +202,7 @@ TRACE_EVENT(mm_shrink_slab_start,
 
 	TP_fast_assign(
 		__entry->shr = shr;
-		__entry->shrink = shr->shrink;
+		__entry->shrink = shr->scan_objects;
 		__entry->nr_objects_to_shrink = nr_objects_to_shrink;
 		__entry->gfp_flags = sc->gfp_mask;
 		__entry->pgs_scanned = pgs_scanned;
@@ -241,7 +241,7 @@ TRACE_EVENT(mm_shrink_slab_end,
 
 	TP_fast_assign(
 		__entry->shr = shr;
-		__entry->shrink = shr->shrink;
+		__entry->shrink = shr->scan_objects;
 		__entry->unused_scan = unused_scan_cnt;
 		__entry->new_scan = new_scan_cnt;
 		__entry->retval = shrinker_retval;
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 238a166..272580c 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -181,7 +181,7 @@ enum drm_map_type {
 	_DRM_AGP = 3,		  /**< AGP/GART */
 	_DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
 	_DRM_CONSISTENT = 5,	  /**< Consistent memory for PCI DMA */
-	_DRM_GEM = 6,		  /**< GEM object */
+	_DRM_GEM = 6,		  /**< GEM object (obsolete) */
 };
 
 /**
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 923ed7f..a1a7b6b 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -33,6 +33,30 @@
  * subject to backwards-compatibility constraints.
  */
 
+/**
+ * DOC: uevents generated by i915 on it's device node
+ *
+ * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch
+ *	event from the gpu l3 cache. Additional information supplied is ROW,
+ *	BANK, SUBBANK of the affected cacheline. Userspace should keep track of
+ *	these events and if a specific cache-line seems to have a persistent
+ *	error remap it with the l3 remapping tool supplied in intel-gpu-tools.
+ *	The value supplied with the event is always 1.
+ *
+ * I915_ERROR_UEVENT - Generated upon error detection, currently only via
+ *	hangcheck. The error detection event is a good indicator of when things
+ *	began to go badly. The value supplied with the event is a 1 upon error
+ *	detection, and a 0 upon reset completion, signifying no more error
+ *	exists. NOTE: Disabling hangcheck or reset via module parameter will
+ *	cause the related events to not be seen.
+ *
+ * I915_RESET_UEVENT - Event is generated just before an attempt to reset the
+ *	the GPU. The value supplied with the event is always 1. NOTE: Disable
+ *	reset via module parameter will cause this event to not be seen.
+ */
+#define I915_L3_PARITY_UEVENT		"L3_PARITY_ERROR"
+#define I915_ERROR_UEVENT		"ERROR"
+#define I915_RESET_UEVENT		"RESET"
 
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
diff --git a/include/uapi/linux/dn.h b/include/uapi/linux/dn.h
index 9c50445..5fbdd3d 100644
--- a/include/uapi/linux/dn.h
+++ b/include/uapi/linux/dn.h
@@ -2,6 +2,7 @@
 #define _LINUX_DN_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 /*
 
@@ -120,7 +121,7 @@ struct linkinfo_dn {
  * Ethernet address format (for DECnet)
  */
 union etheraddress {
-        __u8 dne_addr[6];             /* Full ethernet address */
+        __u8 dne_addr[ETH_ALEN];      /* Full ethernet address */
   struct {
                 __u8 dne_hiord[4];    /* DECnet HIORD prefix   */
                 __u8 dne_nodeaddr[2]; /* DECnet node address   */
diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h
index 51da65b..2b82d7e 100644
--- a/include/uapi/linux/fib_rules.h
+++ b/include/uapi/linux/fib_rules.h
@@ -44,8 +44,8 @@ enum {
 	FRA_FWMARK,	/* mark */
 	FRA_FLOW,	/* flow/class id */
 	FRA_UNUSED6,
-	FRA_UNUSED7,
-	FRA_UNUSED8,
+	FRA_SUPPRESS_IFGROUP,
+	FRA_SUPPRESS_PREFIXLEN,
 	FRA_TABLE,	/* Extended table id */
 	FRA_FWMASK,	/* mask for netfilter mark */
 	FRA_OIFNAME,
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index a4ed56c..6c28b61 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -49,9 +49,9 @@ struct files_stat_struct {
 };
 
 struct inodes_stat_t {
-	int nr_inodes;
-	int nr_unused;
-	int dummy[5];		/* padding for sysctl ABI compatibility */
+	long nr_inodes;
+	long nr_unused;
+	long dummy[5];		/* padding for sysctl ABI compatibility */
 };
 
 
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index 2d70d79..39f621a 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -14,6 +14,7 @@
 #define _UAPI_LINUX_IF_BRIDGE_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 #define SYSFS_BRIDGE_ATTR	"bridge"
 #define SYSFS_BRIDGE_FDB	"brforward"
@@ -88,7 +89,7 @@ struct __port_info {
 };
 
 struct __fdb_entry {
-	__u8 mac_addr[6];
+	__u8 mac_addr[ETH_ALEN];
 	__u8 port_no;
 	__u8 is_local;
 	__u32 ageing_timer_value;
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 03f6170..04c0e7a 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -143,6 +143,7 @@ enum {
 	IFLA_NUM_TX_QUEUES,
 	IFLA_NUM_RX_QUEUES,
 	IFLA_CARRIER,
+	IFLA_PHYS_PORT_ID,
 	__IFLA_MAX
 };
 
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 82334f8..1870ee2 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -71,6 +71,9 @@
 /* read-only flag */
 #define IFF_PERSIST	0x0800
 
+/* Socket options */
+#define TUN_TX_TIMESTAMP 1
+
 /* Features for GSO (TUNSETOFFLOAD). */
 #define TUN_F_CSUM	0x01	/* You can hand me unchecksummed packets. */
 #define TUN_F_TSO4	0x02	/* I can handle TSO for IPv4 packets */
diff --git a/include/uapi/linux/netfilter_bridge/ebt_802_3.h b/include/uapi/linux/netfilter_bridge/ebt_802_3.h
index 5bf8491..f37522a 100644
--- a/include/uapi/linux/netfilter_bridge/ebt_802_3.h
+++ b/include/uapi/linux/netfilter_bridge/ebt_802_3.h
@@ -2,6 +2,7 @@
 #define _UAPI__LINUX_BRIDGE_EBT_802_3_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 #define EBT_802_3_SAP 0x01
 #define EBT_802_3_TYPE 0x02
@@ -42,8 +43,8 @@ struct hdr_ni {
 };
 
 struct ebt_802_3_hdr {
-	__u8  daddr[6];
-	__u8  saddr[6];
+	__u8  daddr[ETH_ALEN];
+	__u8  saddr[ETH_ALEN];
 	__be16 len;
 	union {
 		struct hdr_ui ui;
diff --git a/include/uapi/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/uapi/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index c6a204c..eac0f65 100644
--- a/include/uapi/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/uapi/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -2,6 +2,7 @@
 #define _IPT_CLUSTERIP_H_target
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 enum clusterip_hashmode {
     CLUSTERIP_HASHMODE_SIP = 0,
@@ -22,7 +23,7 @@ struct ipt_clusterip_tgt_info {
 	__u32 flags;
 
 	/* only relevant for new ones */
-	__u8 clustermac[6];
+	__u8 clustermac[ETH_ALEN];
 	__u16 num_total_nodes;
 	__u16 num_local_nodes;
 	__u16 local_nodes[CLUSTERIP_MAX_NODES];
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 861e5eb..eb68735 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -126,6 +126,31 @@
  */
 
 /**
+ * DOC: packet coalesce support
+ *
+ * In most cases, host that receives IPv4 and IPv6 multicast/broadcast
+ * packets does not do anything with these packets. Therefore the
+ * reception of these unwanted packets causes unnecessary processing
+ * and power consumption.
+ *
+ * Packet coalesce feature helps to reduce number of received interrupts
+ * to host by buffering these packets in firmware/hardware for some
+ * predefined time. Received interrupt will be generated when one of the
+ * following events occur.
+ * a) Expiration of hardware timer whose expiration time is set to maximum
+ * coalescing delay of matching coalesce rule.
+ * b) Coalescing buffer in hardware reaches it's limit.
+ * c) Packet doesn't match any of the configured coalesce rules.
+ *
+ * User needs to configure following parameters for creating a coalesce
+ * rule.
+ * a) Maximum coalescing delay
+ * b) List of packet patterns which needs to be matched
+ * c) Condition for coalescence. pattern 'match' or 'no match'
+ * Multiple such rules can be created.
+ */
+
+/**
  * enum nl80211_commands - supported nl80211 commands
  *
  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -648,6 +673,9 @@
  * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
  *	return back to normal.
  *
+ * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules.
+ * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -810,6 +838,9 @@ enum nl80211_commands {
 	NL80211_CMD_CRIT_PROTOCOL_START,
 	NL80211_CMD_CRIT_PROTOCOL_STOP,
 
+	NL80211_CMD_GET_COALESCE,
+	NL80211_CMD_SET_COALESCE,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1436,6 +1467,8 @@ enum nl80211_commands {
  *	allowed to be used with the first @NL80211_CMD_SET_STATION command to
  *	update a TDLS peer STA entry.
  *
+ * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1736,6 +1769,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_PEER_AID,
 
+	NL80211_ATTR_COALESCE_RULE,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2773,6 +2808,21 @@ enum nl80211_chan_width {
 };
 
 /**
+ * enum nl80211_bss_scan_width - control channel width for a BSS
+ *
+ * These values are used with the %NL80211_BSS_CHAN_WIDTH attribute.
+ *
+ * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible
+ * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide
+ * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide
+ */
+enum nl80211_bss_scan_width {
+	NL80211_BSS_CHAN_WIDTH_20,
+	NL80211_BSS_CHAN_WIDTH_10,
+	NL80211_BSS_CHAN_WIDTH_5,
+};
+
+/**
  * enum nl80211_bss - netlink attributes for a BSS
  *
  * @__NL80211_BSS_INVALID: invalid
@@ -2796,6 +2846,8 @@ enum nl80211_chan_width {
  * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information
  *	elements from a Beacon frame (bin); not present if no Beacon frame has
  *	yet been received
+ * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
+ *	(u32, enum nl80211_bss_scan_width)
  * @__NL80211_BSS_AFTER_LAST: internal
  * @NL80211_BSS_MAX: highest BSS attribute
  */
@@ -2812,6 +2864,7 @@ enum nl80211_bss {
 	NL80211_BSS_STATUS,
 	NL80211_BSS_SEEN_MS_AGO,
 	NL80211_BSS_BEACON_IES,
+	NL80211_BSS_CHAN_WIDTH,
 
 	/* keep last */
 	__NL80211_BSS_AFTER_LAST,
@@ -3060,11 +3113,11 @@ enum nl80211_tx_power_setting {
 };
 
 /**
- * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
- * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
- * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
+ * enum nl80211_packet_pattern_attr - packet pattern attribute
+ * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
+ * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has
  *	a zero bit are ignored
- * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
+ * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have
  *	a bit for each byte in the pattern. The lowest-order bit corresponds
  *	to the first byte of the pattern, but the bytes of the pattern are
  *	in a little-endian-like format, i.e. the 9th byte of the pattern
@@ -3075,39 +3128,50 @@ enum nl80211_tx_power_setting {
  *	Note that the pattern matching is done as though frames were not
  *	802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
  *	first (including SNAP header unpacking) and then matched.
- * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
+ * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after
  *	these fixed number of bytes of received packet
- * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
- * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
+ * @NUM_NL80211_PKTPAT: number of attributes
+ * @MAX_NL80211_PKTPAT: max attribute number
  */
-enum nl80211_wowlan_packet_pattern_attr {
-	__NL80211_WOWLAN_PKTPAT_INVALID,
-	NL80211_WOWLAN_PKTPAT_MASK,
-	NL80211_WOWLAN_PKTPAT_PATTERN,
-	NL80211_WOWLAN_PKTPAT_OFFSET,
+enum nl80211_packet_pattern_attr {
+	__NL80211_PKTPAT_INVALID,
+	NL80211_PKTPAT_MASK,
+	NL80211_PKTPAT_PATTERN,
+	NL80211_PKTPAT_OFFSET,
 
-	NUM_NL80211_WOWLAN_PKTPAT,
-	MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
+	NUM_NL80211_PKTPAT,
+	MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1,
 };
 
 /**
- * struct nl80211_wowlan_pattern_support - pattern support information
+ * struct nl80211_pattern_support - packet pattern support information
  * @max_patterns: maximum number of patterns supported
  * @min_pattern_len: minimum length of each pattern
  * @max_pattern_len: maximum length of each pattern
  * @max_pkt_offset: maximum Rx packet offset
  *
  * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
- * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
- * capability information given by the kernel to userspace.
+ * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in
+ * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of
+ * %NL80211_ATTR_COALESCE_RULE in the capability information given
+ * by the kernel to userspace.
  */
-struct nl80211_wowlan_pattern_support {
+struct nl80211_pattern_support {
 	__u32 max_patterns;
 	__u32 min_pattern_len;
 	__u32 max_pattern_len;
 	__u32 max_pkt_offset;
 } __attribute__((packed));
 
+/* only for backward compatibility */
+#define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID
+#define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK
+#define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN
+#define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET
+#define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT
+#define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT
+#define nl80211_wowlan_pattern_support nl80211_pattern_support
+
 /**
  * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
  * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
@@ -3127,7 +3191,7 @@ struct nl80211_wowlan_pattern_support {
  *	pattern matching is done after the packet is converted to the MSDU.
  *
  *	In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
- *	carrying a &struct nl80211_wowlan_pattern_support.
+ *	carrying a &struct nl80211_pattern_support.
  *
  *	When reporting wakeup. it is a u32 attribute containing the 0-based
  *	index of the pattern that caused the wakeup, in the patterns passed
@@ -3284,7 +3348,7 @@ struct nl80211_wowlan_tcp_data_token_feature {
  * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a
  *	u32 attribute holding the maximum length
  * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for
- *	feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK
+ *	feature advertising. The mask works like @NL80211_PKTPAT_MASK
  *	but on the TCP payload only.
  * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes
  * @MAX_NL80211_WOWLAN_TCP: highest attribute number
@@ -3309,6 +3373,55 @@ enum nl80211_wowlan_tcp_attrs {
 };
 
 /**
+ * struct nl80211_coalesce_rule_support - coalesce rule support information
+ * @max_rules: maximum number of rules supported
+ * @pat: packet pattern support information
+ * @max_delay: maximum supported coalescing delay in msecs
+ *
+ * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the
+ * capability information given by the kernel to userspace.
+ */
+struct nl80211_coalesce_rule_support {
+	__u32 max_rules;
+	struct nl80211_pattern_support pat;
+	__u32 max_delay;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_attr_coalesce_rule - coalesce rule attribute
+ * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute
+ * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing
+ * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence,
+ *	see &enum nl80211_coalesce_condition.
+ * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched
+ *	after these fixed number of bytes of received packet
+ * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes
+ * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number
+ */
+enum nl80211_attr_coalesce_rule {
+	__NL80211_COALESCE_RULE_INVALID,
+	NL80211_ATTR_COALESCE_RULE_DELAY,
+	NL80211_ATTR_COALESCE_RULE_CONDITION,
+	NL80211_ATTR_COALESCE_RULE_PKT_PATTERN,
+
+	/* keep last */
+	NUM_NL80211_ATTR_COALESCE_RULE,
+	NL80211_ATTR_COALESCE_RULE_MAX = NUM_NL80211_ATTR_COALESCE_RULE - 1
+};
+
+/**
+ * enum nl80211_coalesce_condition - coalesce rule conditions
+ * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns
+ *	in a rule are matched.
+ * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns
+ *	in a rule are not matched.
+ */
+enum nl80211_coalesce_condition {
+	NL80211_COALESCE_CONDITION_MATCH,
+	NL80211_COALESCE_CONDITION_NO_MATCH
+};
+
+/**
  * enum nl80211_iface_limit_attrs - limit attributes
  * @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
  * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 0b1df41..efef1d3 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -375,9 +375,12 @@ struct perf_event_mmap_page {
 	__u64	time_running;		/* time event on cpu */
 	union {
 		__u64	capabilities;
-		__u64	cap_usr_time  : 1,
-			cap_usr_rdpmc : 1,
-			cap_____res   : 62;
+		struct {
+			__u64	cap_usr_time		: 1,
+				cap_usr_rdpmc		: 1,
+				cap_usr_time_zero	: 1,
+				cap_____res		: 61;
+		};
 	};
 
 	/*
@@ -418,12 +421,29 @@ struct perf_event_mmap_page {
 	__u16	time_shift;
 	__u32	time_mult;
 	__u64	time_offset;
+	/*
+	 * If cap_usr_time_zero, the hardware clock (e.g. TSC) can be calculated
+	 * from sample timestamps.
+	 *
+	 *   time = timestamp - time_zero;
+	 *   quot = time / time_mult;
+	 *   rem  = time % time_mult;
+	 *   cyc = (quot << time_shift) + (rem << time_shift) / time_mult;
+	 *
+	 * And vice versa:
+	 *
+	 *   quot = cyc >> time_shift;
+	 *   rem  = cyc & ((1 << time_shift) - 1);
+	 *   timestamp = time_zero + quot * time_mult +
+	 *               ((rem * time_mult) >> time_shift);
+	 */
+	__u64	time_zero;
 
 		/*
 		 * Hole for extension of the self monitor capabilities
 		 */
 
-	__u64	__reserved[120];	/* align to 1k */
+	__u64	__reserved[119];	/* align to 1k */
 
 	/*
 	 * Control data for the mmap() data buffer.
@@ -478,6 +498,16 @@ enum perf_event_type {
 	 * file will be supported by older perf tools, with these new optional
 	 * fields being ignored.
 	 *
+	 * struct sample_id {
+	 * 	{ u32			pid, tid; } && PERF_SAMPLE_TID
+	 * 	{ u64			time;     } && PERF_SAMPLE_TIME
+	 * 	{ u64			id;       } && PERF_SAMPLE_ID
+	 * 	{ u64			stream_id;} && PERF_SAMPLE_STREAM_ID
+	 * 	{ u32			cpu, res; } && PERF_SAMPLE_CPU
+	 * } && perf_event_attr::sample_id_all
+	 */
+
+	/*
 	 * The MMAP events record the PROT_EXEC mappings so that we can
 	 * correlate userspace IPs to code. They have the following structure:
 	 *
@@ -498,6 +528,7 @@ enum perf_event_type {
 	 *	struct perf_event_header	header;
 	 *	u64				id;
 	 *	u64				lost;
+	 * 	struct sample_id		sample_id;
 	 * };
 	 */
 	PERF_RECORD_LOST			= 2,
@@ -508,6 +539,7 @@ enum perf_event_type {
 	 *
 	 *	u32				pid, tid;
 	 *	char				comm[];
+	 * 	struct sample_id		sample_id;
 	 * };
 	 */
 	PERF_RECORD_COMM			= 3,
@@ -518,6 +550,7 @@ enum perf_event_type {
 	 *	u32				pid, ppid;
 	 *	u32				tid, ptid;
 	 *	u64				time;
+	 * 	struct sample_id		sample_id;
 	 * };
 	 */
 	PERF_RECORD_EXIT			= 4,
@@ -528,6 +561,7 @@ enum perf_event_type {
 	 *	u64				time;
 	 *	u64				id;
 	 *	u64				stream_id;
+	 * 	struct sample_id		sample_id;
 	 * };
 	 */
 	PERF_RECORD_THROTTLE			= 5,
@@ -539,6 +573,7 @@ enum perf_event_type {
 	 *	u32				pid, ppid;
 	 *	u32				tid, ptid;
 	 *	u64				time;
+	 * 	struct sample_id		sample_id;
 	 * };
 	 */
 	PERF_RECORD_FORK			= 7,
@@ -549,6 +584,7 @@ enum perf_event_type {
 	 *	u32				pid, tid;
 	 *
 	 *	struct read_format		values;
+	 * 	struct sample_id		sample_id;
 	 * };
 	 */
 	PERF_RECORD_READ			= 8,
@@ -596,7 +632,7 @@ enum perf_event_type {
 	 * 	  u64			dyn_size; } && PERF_SAMPLE_STACK_USER
 	 *
 	 *	{ u64			weight;   } && PERF_SAMPLE_WEIGHT
-	 *	{ u64			data_src;     } && PERF_SAMPLE_DATA_SRC
+	 *	{ u64			data_src; } && PERF_SAMPLE_DATA_SRC
 	 * };
 	 */
 	PERF_RECORD_SAMPLE			= 9,
diff --git a/include/uapi/linux/reiserfs_xattr.h b/include/uapi/linux/reiserfs_xattr.h
index d8ce17c..38fdd64 100644
--- a/include/uapi/linux/reiserfs_xattr.h
+++ b/include/uapi/linux/reiserfs_xattr.h
@@ -16,7 +16,7 @@ struct reiserfs_xattr_header {
 };
 
 struct reiserfs_security_handle {
-	char *name;
+	const char *name;
 	void *value;
 	size_t length;
 };
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 66b466e..ca451e9 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 9119cc0..e40ebe1 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -232,4 +232,7 @@
 /* SH-SCI */
 #define PORT_HSCIF	104
 
+/* ST ASC type numbers */
+#define PORT_ASC       105
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index e632260..97c26be 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -366,6 +366,7 @@
 #define UART_OMAP_MDR1_FIR_MODE		0x05	/* FIR mode */
 #define UART_OMAP_MDR1_CIR_MODE		0x06	/* CIR mode */
 #define UART_OMAP_MDR1_DISABLE		0x07	/* Disable (default state) */
+#define UART_OMAP_TXFIFO_LVL		0x1A	/* TX FIFO fullness */
 
 /*
  * These are definitions for the Exar XR17V35X and XR17(C|D)15X
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 8d776eb..377f1e5 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -111,6 +111,7 @@ enum {
 #define TCP_REPAIR_OPTIONS	22
 #define TCP_FASTOPEN		23	/* Enable FastOpen on listeners */
 #define TCP_TIMESTAMP		24
+#define TCP_NOTSENT_LOWAT	25	/* limit number of unsent bytes in write queue */
 
 struct tcp_repair_opt {
 	__u32	opt_code;
diff --git a/include/uapi/linux/uhid.h b/include/uapi/linux/uhid.h
index e9ed951..414b74b 100644
--- a/include/uapi/linux/uhid.h
+++ b/include/uapi/linux/uhid.h
@@ -30,7 +30,7 @@ enum uhid_event_type {
 	UHID_OPEN,
 	UHID_CLOSE,
 	UHID_OUTPUT,
-	UHID_OUTPUT_EV,
+	UHID_OUTPUT_EV,			/* obsolete! */
 	UHID_INPUT,
 	UHID_FEATURE,
 	UHID_FEATURE_ANSWER,
@@ -69,6 +69,8 @@ struct uhid_output_req {
 	__u8 rtype;
 } __attribute__((__packed__));
 
+/* Obsolete! Newer kernels will no longer send these events but instead convert
+ * it into raw output reports via UHID_OUTPUT. */
 struct uhid_output_ev_req {
 	__u16 type;
 	__u16 code;
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index c520203..172a7f0 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -60,7 +60,7 @@
 
 struct virtio_net_config {
 	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
-	__u8 mac[6];
+	__u8 mac[ETH_ALEN];
 	/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
 	__u16 status;
 	/* Maximum number of each of transmit and receive queues;
@@ -70,7 +70,9 @@ struct virtio_net_config {
 	__u16 max_virtqueue_pairs;
 } __attribute__((packed));
 
-/* This is the first element of the scatter-gather list.  If you don't
+/* This header comes first in the scatter-gather list.
+ * If VIRTIO_F_ANY_LAYOUT is not negotiated, it must
+ * be the first element of the scatter-gather list.  If you don't
  * specify GSO or CSUM features, you can simply ignore the header. */
 struct virtio_net_hdr {
 #define VIRTIO_NET_HDR_F_NEEDS_CSUM	1	// Use csum_start, csum_offset
diff --git a/include/uapi/linux/wimax/i2400m.h b/include/uapi/linux/wimax/i2400m.h
index 62d3561..fd198bc 100644
--- a/include/uapi/linux/wimax/i2400m.h
+++ b/include/uapi/linux/wimax/i2400m.h
@@ -122,7 +122,7 @@
 #define __LINUX__WIMAX__I2400M_H__
 
 #include <linux/types.h>
-
+#include <linux/if_ether.h>
 
 /*
  * Host Device Interface (HDI) common to all busses
@@ -487,7 +487,7 @@ struct i2400m_tlv_l4_message_versions {
 struct i2400m_tlv_detailed_device_info {
 	struct i2400m_tlv_hdr hdr;
 	__u8 reserved1[400];
-	__u8 mac_address[6];
+	__u8 mac_address[ETH_ALEN];
 	__u8 reserved2[2];
 } __attribute__((packed));
 
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
index 0f5a2fc..c79f381 100644
--- a/include/video/atmel_lcdc.h
+++ b/include/video/atmel_lcdc.h
@@ -31,39 +31,20 @@
 #define ATMEL_LCDC_WIRING_BGR	0
 #define ATMEL_LCDC_WIRING_RGB	1
 
-struct atmel_lcdfb_config;
 
  /* LCD Controller info data structure, stored in device platform_data */
-struct atmel_lcdfb_info {
-	spinlock_t		lock;
-	struct fb_info		*info;
-	void __iomem		*mmio;
-	int			irq_base;
-	struct work_struct	task;
-
+struct atmel_lcdfb_pdata {
 	unsigned int		guard_time;
-	unsigned int 		smem_len;
-	struct platform_device	*pdev;
-	struct clk		*bus_clk;
-	struct clk		*lcdc_clk;
-
-#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-	struct backlight_device	*backlight;
-	u8			bl_power;
-#endif
 	bool			lcdcon_is_backlight;
 	bool			lcdcon_pol_negative;
-	u8			saved_lcdcon;
-
 	u8			default_bpp;
 	u8			lcd_wiring_mode;
 	unsigned int		default_lcdcon2;
 	unsigned int		default_dmacon;
-	void (*atmel_lcdfb_power_control)(int on);
+	void (*atmel_lcdfb_power_control)(struct atmel_lcdfb_pdata *pdata, int on);
 	struct fb_monspecs	*default_monspecs;
-	u32			pseudo_palette[16];
 
-	struct atmel_lcdfb_config *config;
+	struct list_head	pwr_gpios;
 };
 
 #define ATMEL_LCDC_DMABADDR1	0x00
diff --git a/include/xen/acpi.h b/include/xen/acpi.h
index 46aa3d1..4ddd7dc 100644
--- a/include/xen/acpi.h
+++ b/include/xen/acpi.h
@@ -75,8 +75,10 @@ static inline int xen_acpi_get_pxm(acpi_handle h)
 	return -ENXIO;
 }
 
-int xen_acpi_notify_hypervisor_state(u8 sleep_state,
+int xen_acpi_notify_hypervisor_sleep(u8 sleep_state,
 				     u32 pm1a_cnt, u32 pm1b_cnd);
+int xen_acpi_notify_hypervisor_extended_sleep(u8 sleep_state,
+				     u32 val_a, u32 val_b);
 
 static inline int xen_acpi_suspend_lowlevel(void)
 {
@@ -93,7 +95,9 @@ static inline void xen_acpi_sleep_register(void)
 {
 	if (xen_initial_domain()) {
 		acpi_os_set_prepare_sleep(
-			&xen_acpi_notify_hypervisor_state);
+			&xen_acpi_notify_hypervisor_sleep);
+		acpi_os_set_prepare_extended_sleep(
+			&xen_acpi_notify_hypervisor_extended_sleep);
 
 		acpi_suspend_lowlevel = xen_acpi_suspend_lowlevel;
 	}
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index c57d5f6..f1331e3 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -152,10 +152,11 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_firmware_info_t);
 #define XENPF_enter_acpi_sleep    51
 struct xenpf_enter_acpi_sleep {
 	/* IN variables */
-	uint16_t pm1a_cnt_val;      /* PM1a control value. */
-	uint16_t pm1b_cnt_val;      /* PM1b control value. */
+	uint16_t val_a;             /* PM1a control / sleep type A. */
+	uint16_t val_b;             /* PM1b control / sleep type B. */
 	uint32_t sleep_state;       /* Which state to enter (Sn). */
-	uint32_t flags;             /* Must be zero. */
+#define XENPF_ACPI_SLEEP_EXTENDED 0x00000001
+	uint32_t flags;             /* XENPF_ACPI_SLEEP_*. */
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_enter_acpi_sleep_t);
 
diff --git a/init/Kconfig b/init/Kconfig
index 247084b..c08a549 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -470,6 +470,7 @@ config TREE_RCU
 config TREE_PREEMPT_RCU
 	bool "Preemptible tree-based hierarchical RCU"
 	depends on PREEMPT
+	select IRQ_WORK
 	help
 	  This option selects the RCU implementation that is
 	  designed for very large SMP systems with hundreds or
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 816014c..6df7405 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -26,6 +26,8 @@
 #include <linux/async.h>
 #include <linux/fs_struct.h>
 #include <linux/slab.h>
+#include <linux/ramfs.h>
+#include <linux/shmem_fs.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -202,7 +204,7 @@ done:
  *	bangs.
  */
 
-dev_t name_to_dev_t(char *name)
+dev_t name_to_dev_t(const char *name)
 {
 	char s[32];
 	char *p;
@@ -588,3 +590,46 @@ out:
 	sys_mount(".", "/", NULL, MS_MOVE, NULL);
 	sys_chroot(".");
 }
+
+static bool is_tmpfs;
+static struct dentry *rootfs_mount(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data)
+{
+	static unsigned long once;
+	void *fill = ramfs_fill_super;
+
+	if (test_and_set_bit(0, &once))
+		return ERR_PTR(-ENODEV);
+
+	if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs)
+		fill = shmem_fill_super;
+
+	return mount_nodev(fs_type, flags, data, fill);
+}
+
+static struct file_system_type rootfs_fs_type = {
+	.name		= "rootfs",
+	.mount		= rootfs_mount,
+	.kill_sb	= kill_litter_super,
+};
+
+int __init init_rootfs(void)
+{
+	int err = register_filesystem(&rootfs_fs_type);
+
+	if (err)
+		return err;
+
+	if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
+		(!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
+		err = shmem_init();
+		is_tmpfs = true;
+	} else {
+		err = init_ramfs_fs();
+	}
+
+	if (err)
+		unregister_filesystem(&rootfs_fs_type);
+
+	return err;
+}
diff --git a/ipc/msg.c b/ipc/msg.c
index bd60d7e..14d64f8 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -70,8 +70,6 @@ struct msg_sender {
 
 #define msg_ids(ns)	((ns)->ids[IPC_MSG_IDS])
 
-#define msg_unlock(msq)		ipc_unlock(&(msq)->q_perm)
-
 static void freeque(struct ipc_namespace *, struct kern_ipc_perm *);
 static int newque(struct ipc_namespace *, struct ipc_params *);
 #ifdef CONFIG_PROC_FS
@@ -172,7 +170,7 @@ static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
  * @ns: namespace
  * @params: ptr to the structure that contains the key and msgflg
  *
- * Called with msg_ids.rw_mutex held (writer)
+ * Called with msg_ids.rwsem held (writer)
  */
 static int newque(struct ipc_namespace *ns, struct ipc_params *params)
 {
@@ -259,8 +257,8 @@ static void expunge_all(struct msg_queue *msq, int res)
  * removes the message queue from message queue ID IDR, and cleans up all the
  * messages associated with this queue.
  *
- * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held
- * before freeque() is called. msg_ids.rw_mutex remains locked on exit.
+ * msg_ids.rwsem (writer) and the spinlock for this message queue are held
+ * before freeque() is called. msg_ids.rwsem remains locked on exit.
  */
 static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 {
@@ -270,7 +268,8 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 	expunge_all(msq, -EIDRM);
 	ss_wakeup(&msq->q_senders, 1);
 	msg_rmid(ns, msq);
-	msg_unlock(msq);
+	ipc_unlock_object(&msq->q_perm);
+	rcu_read_unlock();
 
 	list_for_each_entry_safe(msg, t, &msq->q_messages, m_list) {
 		atomic_dec(&ns->msg_hdrs);
@@ -282,7 +281,7 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 }
 
 /*
- * Called with msg_ids.rw_mutex and ipcp locked.
+ * Called with msg_ids.rwsem and ipcp locked.
  */
 static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
 {
@@ -386,9 +385,9 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
 }
 
 /*
- * This function handles some msgctl commands which require the rw_mutex
+ * This function handles some msgctl commands which require the rwsem
  * to be held in write mode.
- * NOTE: no locks must be held, the rw_mutex is taken inside this function.
+ * NOTE: no locks must be held, the rwsem is taken inside this function.
  */
 static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
 		       struct msqid_ds __user *buf, int version)
@@ -403,7 +402,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
 			return -EFAULT;
 	}
 
-	down_write(&msg_ids(ns).rw_mutex);
+	down_write(&msg_ids(ns).rwsem);
 	rcu_read_lock();
 
 	ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd,
@@ -459,7 +458,7 @@ out_unlock0:
 out_unlock1:
 	rcu_read_unlock();
 out_up:
-	up_write(&msg_ids(ns).rw_mutex);
+	up_write(&msg_ids(ns).rwsem);
 	return err;
 }
 
@@ -494,7 +493,7 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
 		msginfo.msgmnb = ns->msg_ctlmnb;
 		msginfo.msgssz = MSGSSZ;
 		msginfo.msgseg = MSGSEG;
-		down_read(&msg_ids(ns).rw_mutex);
+		down_read(&msg_ids(ns).rwsem);
 		if (cmd == MSG_INFO) {
 			msginfo.msgpool = msg_ids(ns).in_use;
 			msginfo.msgmap = atomic_read(&ns->msg_hdrs);
@@ -505,7 +504,7 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
 			msginfo.msgtql = MSGTQL;
 		}
 		max_id = ipc_get_maxid(&msg_ids(ns));
-		up_read(&msg_ids(ns).rw_mutex);
+		up_read(&msg_ids(ns).rwsem);
 		if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
 			return -EFAULT;
 		return (max_id < 0) ? 0 : max_id;
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 7ee61bf..aba9a58 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -81,7 +81,7 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
 	int next_id;
 	int total, in_use;
 
-	down_write(&ids->rw_mutex);
+	down_write(&ids->rwsem);
 
 	in_use = ids->in_use;
 
@@ -89,11 +89,12 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
 		perm = idr_find(&ids->ipcs_idr, next_id);
 		if (perm == NULL)
 			continue;
-		ipc_lock_by_ptr(perm);
+		rcu_read_lock();
+		ipc_lock_object(perm);
 		free(ns, perm);
 		total++;
 	}
-	up_write(&ids->rw_mutex);
+	up_write(&ids->rwsem);
 }
 
 static void free_ipc_ns(struct ipc_namespace *ns)
diff --git a/ipc/sem.c b/ipc/sem.c
index 4108889..69b6a21 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -322,7 +322,7 @@ static inline void sem_unlock(struct sem_array *sma, int locknum)
 }
 
 /*
- * sem_lock_(check_) routines are called in the paths where the rw_mutex
+ * sem_lock_(check_) routines are called in the paths where the rwsem
  * is not held.
  *
  * The caller holds the RCU read lock.
@@ -426,7 +426,7 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  * @ns: namespace
  * @params: ptr to the structure that contains key, semflg and nsems
  *
- * Called with sem_ids.rw_mutex held (as a writer)
+ * Called with sem_ids.rwsem held (as a writer)
  */
 
 static int newary(struct ipc_namespace *ns, struct ipc_params *params)
@@ -492,7 +492,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 
 
 /*
- * Called with sem_ids.rw_mutex and ipcp locked.
+ * Called with sem_ids.rwsem and ipcp locked.
  */
 static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
 {
@@ -503,7 +503,7 @@ static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
 }
 
 /*
- * Called with sem_ids.rw_mutex and ipcp locked.
+ * Called with sem_ids.rwsem and ipcp locked.
  */
 static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
 				struct ipc_params *params)
@@ -994,8 +994,8 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
 	return semzcnt;
 }
 
-/* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked
- * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex
+/* Free a semaphore set. freeary() is called with sem_ids.rwsem locked
+ * as a writer and the spinlock for this semaphore set hold. sem_ids.rwsem
  * remains locked on exit.
  */
 static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
@@ -1116,7 +1116,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
 		seminfo.semmnu = SEMMNU;
 		seminfo.semmap = SEMMAP;
 		seminfo.semume = SEMUME;
-		down_read(&sem_ids(ns).rw_mutex);
+		down_read(&sem_ids(ns).rwsem);
 		if (cmd == SEM_INFO) {
 			seminfo.semusz = sem_ids(ns).in_use;
 			seminfo.semaem = ns->used_sems;
@@ -1125,7 +1125,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
 			seminfo.semaem = SEMAEM;
 		}
 		max_id = ipc_get_maxid(&sem_ids(ns));
-		up_read(&sem_ids(ns).rw_mutex);
+		up_read(&sem_ids(ns).rwsem);
 		if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) 
 			return -EFAULT;
 		return (max_id < 0) ? 0: max_id;
@@ -1431,9 +1431,9 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
 }
 
 /*
- * This function handles some semctl commands which require the rw_mutex
+ * This function handles some semctl commands which require the rwsem
  * to be held in write mode.
- * NOTE: no locks must be held, the rw_mutex is taken inside this function.
+ * NOTE: no locks must be held, the rwsem is taken inside this function.
  */
 static int semctl_down(struct ipc_namespace *ns, int semid,
 		       int cmd, int version, void __user *p)
@@ -1448,7 +1448,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
 			return -EFAULT;
 	}
 
-	down_write(&sem_ids(ns).rw_mutex);
+	down_write(&sem_ids(ns).rwsem);
 	rcu_read_lock();
 
 	ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
@@ -1487,7 +1487,7 @@ out_unlock0:
 out_unlock1:
 	rcu_read_unlock();
 out_up:
-	up_write(&sem_ids(ns).rw_mutex);
+	up_write(&sem_ids(ns).rwsem);
 	return err;
 }
 
diff --git a/ipc/shm.c b/ipc/shm.c
index c6b4ad5..2821cdf 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -19,6 +19,9 @@
  * namespaces support
  * OpenVZ, SWsoft Inc.
  * Pavel Emelianov <xemul@openvz.org>
+ *
+ * Better ipc lock (kern_ipc_perm.lock) handling
+ * Davidlohr Bueso <davidlohr.bueso@hp.com>, June 2013.
  */
 
 #include <linux/slab.h>
@@ -80,8 +83,8 @@ void shm_init_ns(struct ipc_namespace *ns)
 }
 
 /*
- * Called with shm_ids.rw_mutex (writer) and the shp structure locked.
- * Only shm_ids.rw_mutex remains locked on exit.
+ * Called with shm_ids.rwsem (writer) and the shp structure locked.
+ * Only shm_ids.rwsem remains locked on exit.
  */
 static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 {
@@ -124,8 +127,28 @@ void __init shm_init (void)
 				IPC_SHM_IDS, sysvipc_shm_proc_show);
 }
 
+static inline struct shmid_kernel *shm_obtain_object(struct ipc_namespace *ns, int id)
+{
+	struct kern_ipc_perm *ipcp = ipc_obtain_object(&shm_ids(ns), id);
+
+	if (IS_ERR(ipcp))
+		return ERR_CAST(ipcp);
+
+	return container_of(ipcp, struct shmid_kernel, shm_perm);
+}
+
+static inline struct shmid_kernel *shm_obtain_object_check(struct ipc_namespace *ns, int id)
+{
+	struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&shm_ids(ns), id);
+
+	if (IS_ERR(ipcp))
+		return ERR_CAST(ipcp);
+
+	return container_of(ipcp, struct shmid_kernel, shm_perm);
+}
+
 /*
- * shm_lock_(check_) routines are called in the paths where the rw_mutex
+ * shm_lock_(check_) routines are called in the paths where the rwsem
  * is not necessarily held.
  */
 static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
@@ -144,17 +167,6 @@ static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp)
 	ipc_lock_object(&ipcp->shm_perm);
 }
 
-static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns,
-						int id)
-{
-	struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id);
-
-	if (IS_ERR(ipcp))
-		return (struct shmid_kernel *)ipcp;
-
-	return container_of(ipcp, struct shmid_kernel, shm_perm);
-}
-
 static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
 {
 	ipc_rmid(&shm_ids(ns), &s->shm_perm);
@@ -182,7 +194,7 @@ static void shm_open(struct vm_area_struct *vma)
  * @ns: namespace
  * @shp: struct to free
  *
- * It has to be called with shp and shm_ids.rw_mutex (writer) locked,
+ * It has to be called with shp and shm_ids.rwsem (writer) locked,
  * but returns with shp unlocked and freed.
  */
 static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
@@ -230,7 +242,7 @@ static void shm_close(struct vm_area_struct *vma)
 	struct shmid_kernel *shp;
 	struct ipc_namespace *ns = sfd->ns;
 
-	down_write(&shm_ids(ns).rw_mutex);
+	down_write(&shm_ids(ns).rwsem);
 	/* remove from the list of attaches of the shm segment */
 	shp = shm_lock(ns, sfd->id);
 	BUG_ON(IS_ERR(shp));
@@ -241,10 +253,10 @@ static void shm_close(struct vm_area_struct *vma)
 		shm_destroy(ns, shp);
 	else
 		shm_unlock(shp);
-	up_write(&shm_ids(ns).rw_mutex);
+	up_write(&shm_ids(ns).rwsem);
 }
 
-/* Called with ns->shm_ids(ns).rw_mutex locked */
+/* Called with ns->shm_ids(ns).rwsem locked */
 static int shm_try_destroy_current(int id, void *p, void *data)
 {
 	struct ipc_namespace *ns = data;
@@ -275,7 +287,7 @@ static int shm_try_destroy_current(int id, void *p, void *data)
 	return 0;
 }
 
-/* Called with ns->shm_ids(ns).rw_mutex locked */
+/* Called with ns->shm_ids(ns).rwsem locked */
 static int shm_try_destroy_orphaned(int id, void *p, void *data)
 {
 	struct ipc_namespace *ns = data;
@@ -286,7 +298,7 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data)
 	 * We want to destroy segments without users and with already
 	 * exit'ed originating process.
 	 *
-	 * As shp->* are changed under rw_mutex, it's safe to skip shp locking.
+	 * As shp->* are changed under rwsem, it's safe to skip shp locking.
 	 */
 	if (shp->shm_creator != NULL)
 		return 0;
@@ -300,10 +312,10 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data)
 
 void shm_destroy_orphaned(struct ipc_namespace *ns)
 {
-	down_write(&shm_ids(ns).rw_mutex);
+	down_write(&shm_ids(ns).rwsem);
 	if (shm_ids(ns).in_use)
 		idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
-	up_write(&shm_ids(ns).rw_mutex);
+	up_write(&shm_ids(ns).rwsem);
 }
 
 
@@ -315,10 +327,10 @@ void exit_shm(struct task_struct *task)
 		return;
 
 	/* Destroy all already created segments, but not mapped yet */
-	down_write(&shm_ids(ns).rw_mutex);
+	down_write(&shm_ids(ns).rwsem);
 	if (shm_ids(ns).in_use)
 		idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns);
-	up_write(&shm_ids(ns).rw_mutex);
+	up_write(&shm_ids(ns).rwsem);
 }
 
 static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -452,7 +464,7 @@ static const struct vm_operations_struct shm_vm_ops = {
  * @ns: namespace
  * @params: ptr to the structure that contains key, size and shmflg
  *
- * Called with shm_ids.rw_mutex held as a writer.
+ * Called with shm_ids.rwsem held as a writer.
  */
 
 static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
@@ -560,7 +572,7 @@ no_file:
 }
 
 /*
- * Called with shm_ids.rw_mutex and ipcp locked.
+ * Called with shm_ids.rwsem and ipcp locked.
  */
 static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
 {
@@ -571,7 +583,7 @@ static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
 }
 
 /*
- * Called with shm_ids.rw_mutex and ipcp locked.
+ * Called with shm_ids.rwsem and ipcp locked.
  */
 static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
 				struct ipc_params *params)
@@ -684,7 +696,7 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf
 
 /*
  * Calculate and add used RSS and swap pages of a shm.
- * Called with shm_ids.rw_mutex held as a reader
+ * Called with shm_ids.rwsem held as a reader
  */
 static void shm_add_rss_swap(struct shmid_kernel *shp,
 	unsigned long *rss_add, unsigned long *swp_add)
@@ -711,7 +723,7 @@ static void shm_add_rss_swap(struct shmid_kernel *shp,
 }
 
 /*
- * Called with shm_ids.rw_mutex held as a reader
+ * Called with shm_ids.rwsem held as a reader
  */
 static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
 		unsigned long *swp)
@@ -740,9 +752,9 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
 }
 
 /*
- * This function handles some shmctl commands which require the rw_mutex
+ * This function handles some shmctl commands which require the rwsem
  * to be held in write mode.
- * NOTE: no locks must be held, the rw_mutex is taken inside this function.
+ * NOTE: no locks must be held, the rwsem is taken inside this function.
  */
 static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
 		       struct shmid_ds __user *buf, int version)
@@ -757,14 +769,13 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
 			return -EFAULT;
 	}
 
-	down_write(&shm_ids(ns).rw_mutex);
+	down_write(&shm_ids(ns).rwsem);
 	rcu_read_lock();
 
-	ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd,
-			       &shmid64.shm_perm, 0);
+	ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
+				      &shmid64.shm_perm, 0);
 	if (IS_ERR(ipcp)) {
 		err = PTR_ERR(ipcp);
-		/* the ipc lock is not held upon failure */
 		goto out_unlock1;
 	}
 
@@ -772,14 +783,16 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
 
 	err = security_shm_shmctl(shp, cmd);
 	if (err)
-		goto out_unlock0;
+		goto out_unlock1;
 
 	switch (cmd) {
 	case IPC_RMID:
+		ipc_lock_object(&shp->shm_perm);
 		/* do_shm_rmid unlocks the ipc object and rcu */
 		do_shm_rmid(ns, ipcp);
 		goto out_up;
 	case IPC_SET:
+		ipc_lock_object(&shp->shm_perm);
 		err = ipc_update_perm(&shmid64.shm_perm, ipcp);
 		if (err)
 			goto out_unlock0;
@@ -787,6 +800,7 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
 		break;
 	default:
 		err = -EINVAL;
+		goto out_unlock1;
 	}
 
 out_unlock0:
@@ -794,33 +808,28 @@ out_unlock0:
 out_unlock1:
 	rcu_read_unlock();
 out_up:
-	up_write(&shm_ids(ns).rw_mutex);
+	up_write(&shm_ids(ns).rwsem);
 	return err;
 }
 
-SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
+static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
+			 int cmd, int version, void __user *buf)
 {
+	int err;
 	struct shmid_kernel *shp;
-	int err, version;
-	struct ipc_namespace *ns;
 
-	if (cmd < 0 || shmid < 0) {
-		err = -EINVAL;
-		goto out;
+	/* preliminary security checks for *_INFO */
+	if (cmd == IPC_INFO || cmd == SHM_INFO) {
+		err = security_shm_shmctl(NULL, cmd);
+		if (err)
+			return err;
 	}
 
-	version = ipc_parse_version(&cmd);
-	ns = current->nsproxy->ipc_ns;
-
-	switch (cmd) { /* replace with proc interface ? */
+	switch (cmd) {
 	case IPC_INFO:
 	{
 		struct shminfo64 shminfo;
 
-		err = security_shm_shmctl(NULL, cmd);
-		if (err)
-			return err;
-
 		memset(&shminfo, 0, sizeof(shminfo));
 		shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
 		shminfo.shmmax = ns->shm_ctlmax;
@@ -830,9 +839,9 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 		if(copy_shminfo_to_user (buf, &shminfo, version))
 			return -EFAULT;
 
-		down_read(&shm_ids(ns).rw_mutex);
+		down_read(&shm_ids(ns).rwsem);
 		err = ipc_get_maxid(&shm_ids(ns));
-		up_read(&shm_ids(ns).rw_mutex);
+		up_read(&shm_ids(ns).rwsem);
 
 		if(err<0)
 			err = 0;
@@ -842,19 +851,15 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 	{
 		struct shm_info shm_info;
 
-		err = security_shm_shmctl(NULL, cmd);
-		if (err)
-			return err;
-
 		memset(&shm_info, 0, sizeof(shm_info));
-		down_read(&shm_ids(ns).rw_mutex);
+		down_read(&shm_ids(ns).rwsem);
 		shm_info.used_ids = shm_ids(ns).in_use;
 		shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
 		shm_info.shm_tot = ns->shm_tot;
 		shm_info.swap_attempts = 0;
 		shm_info.swap_successes = 0;
 		err = ipc_get_maxid(&shm_ids(ns));
-		up_read(&shm_ids(ns).rw_mutex);
+		up_read(&shm_ids(ns).rwsem);
 		if (copy_to_user(buf, &shm_info, sizeof(shm_info))) {
 			err = -EFAULT;
 			goto out;
@@ -869,27 +874,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 		struct shmid64_ds tbuf;
 		int result;
 
+		rcu_read_lock();
 		if (cmd == SHM_STAT) {
-			shp = shm_lock(ns, shmid);
+			shp = shm_obtain_object(ns, shmid);
 			if (IS_ERR(shp)) {
 				err = PTR_ERR(shp);
-				goto out;
+				goto out_unlock;
 			}
 			result = shp->shm_perm.id;
 		} else {
-			shp = shm_lock_check(ns, shmid);
+			shp = shm_obtain_object_check(ns, shmid);
 			if (IS_ERR(shp)) {
 				err = PTR_ERR(shp);
-				goto out;
+				goto out_unlock;
 			}
 			result = 0;
 		}
+
 		err = -EACCES;
 		if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
 			goto out_unlock;
+
 		err = security_shm_shmctl(shp, cmd);
 		if (err)
 			goto out_unlock;
+
 		memset(&tbuf, 0, sizeof(tbuf));
 		kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
 		tbuf.shm_segsz	= shp->shm_segsz;
@@ -899,43 +908,76 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 		tbuf.shm_cpid	= shp->shm_cprid;
 		tbuf.shm_lpid	= shp->shm_lprid;
 		tbuf.shm_nattch	= shp->shm_nattch;
-		shm_unlock(shp);
-		if(copy_shmid_to_user (buf, &tbuf, version))
+		rcu_read_unlock();
+
+		if (copy_shmid_to_user(buf, &tbuf, version))
 			err = -EFAULT;
 		else
 			err = result;
 		goto out;
 	}
+	default:
+		return -EINVAL;
+	}
+
+out_unlock:
+	rcu_read_unlock();
+out:
+	return err;
+}
+
+SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
+{
+	struct shmid_kernel *shp;
+	int err, version;
+	struct ipc_namespace *ns;
+
+	if (cmd < 0 || shmid < 0)
+		return -EINVAL;
+
+	version = ipc_parse_version(&cmd);
+	ns = current->nsproxy->ipc_ns;
+
+	switch (cmd) {
+	case IPC_INFO:
+	case SHM_INFO:
+	case SHM_STAT:
+	case IPC_STAT:
+		return shmctl_nolock(ns, shmid, cmd, version, buf);
+	case IPC_RMID:
+	case IPC_SET:
+		return shmctl_down(ns, shmid, cmd, buf, version);
 	case SHM_LOCK:
 	case SHM_UNLOCK:
 	{
 		struct file *shm_file;
 
-		shp = shm_lock_check(ns, shmid);
+		rcu_read_lock();
+		shp = shm_obtain_object_check(ns, shmid);
 		if (IS_ERR(shp)) {
 			err = PTR_ERR(shp);
-			goto out;
+			goto out_unlock1;
 		}
 
 		audit_ipc_obj(&(shp->shm_perm));
+		err = security_shm_shmctl(shp, cmd);
+		if (err)
+			goto out_unlock1;
 
+		ipc_lock_object(&shp->shm_perm);
 		if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
 			kuid_t euid = current_euid();
 			err = -EPERM;
 			if (!uid_eq(euid, shp->shm_perm.uid) &&
 			    !uid_eq(euid, shp->shm_perm.cuid))
-				goto out_unlock;
+				goto out_unlock0;
 			if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
-				goto out_unlock;
+				goto out_unlock0;
 		}
 
-		err = security_shm_shmctl(shp, cmd);
-		if (err)
-			goto out_unlock;
-
 		shm_file = shp->shm_file;
 		if (is_file_hugepages(shm_file))
-			goto out_unlock;
+			goto out_unlock0;
 
 		if (cmd == SHM_LOCK) {
 			struct user_struct *user = current_user();
@@ -944,32 +986,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 				shp->shm_perm.mode |= SHM_LOCKED;
 				shp->mlock_user = user;
 			}
-			goto out_unlock;
+			goto out_unlock0;
 		}
 
 		/* SHM_UNLOCK */
 		if (!(shp->shm_perm.mode & SHM_LOCKED))
-			goto out_unlock;
+			goto out_unlock0;
 		shmem_lock(shm_file, 0, shp->mlock_user);
 		shp->shm_perm.mode &= ~SHM_LOCKED;
 		shp->mlock_user = NULL;
 		get_file(shm_file);
-		shm_unlock(shp);
+		ipc_unlock_object(&shp->shm_perm);
+		rcu_read_unlock();
 		shmem_unlock_mapping(shm_file->f_mapping);
+
 		fput(shm_file);
-		goto out;
-	}
-	case IPC_RMID:
-	case IPC_SET:
-		err = shmctl_down(ns, shmid, cmd, buf, version);
 		return err;
+	}
 	default:
 		return -EINVAL;
 	}
 
-out_unlock:
-	shm_unlock(shp);
-out:
+out_unlock0:
+	ipc_unlock_object(&shp->shm_perm);
+out_unlock1:
+	rcu_read_unlock();
 	return err;
 }
 
@@ -1037,10 +1078,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
 	 * additional creator id...
 	 */
 	ns = current->nsproxy->ipc_ns;
-	shp = shm_lock_check(ns, shmid);
+	rcu_read_lock();
+	shp = shm_obtain_object_check(ns, shmid);
 	if (IS_ERR(shp)) {
 		err = PTR_ERR(shp);
-		goto out;
+		goto out_unlock;
 	}
 
 	err = -EACCES;
@@ -1051,24 +1093,31 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
 	if (err)
 		goto out_unlock;
 
+	ipc_lock_object(&shp->shm_perm);
 	path = shp->shm_file->f_path;
 	path_get(&path);
 	shp->shm_nattch++;
 	size = i_size_read(path.dentry->d_inode);
-	shm_unlock(shp);
+	ipc_unlock_object(&shp->shm_perm);
+	rcu_read_unlock();
 
 	err = -ENOMEM;
 	sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
-	if (!sfd)
-		goto out_put_dentry;
+	if (!sfd) {
+		path_put(&path);
+		goto out_nattch;
+	}
 
 	file = alloc_file(&path, f_mode,
 			  is_file_hugepages(shp->shm_file) ?
 				&shm_file_operations_huge :
 				&shm_file_operations);
 	err = PTR_ERR(file);
-	if (IS_ERR(file))
-		goto out_free;
+	if (IS_ERR(file)) {
+		kfree(sfd);
+		path_put(&path);
+		goto out_nattch;
+	}
 
 	file->private_data = sfd;
 	file->f_mapping = shp->shm_file->f_mapping;
@@ -1094,7 +1143,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
 		    addr > current->mm->start_stack - size - PAGE_SIZE * 5)
 			goto invalid;
 	}
-		
+
 	addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate);
 	*raddr = addr;
 	err = 0;
@@ -1109,7 +1158,7 @@ out_fput:
 	fput(file);
 
 out_nattch:
-	down_write(&shm_ids(ns).rw_mutex);
+	down_write(&shm_ids(ns).rwsem);
 	shp = shm_lock(ns, shmid);
 	BUG_ON(IS_ERR(shp));
 	shp->shm_nattch--;
@@ -1117,20 +1166,13 @@ out_nattch:
 		shm_destroy(ns, shp);
 	else
 		shm_unlock(shp);
-	up_write(&shm_ids(ns).rw_mutex);
-
-out:
+	up_write(&shm_ids(ns).rwsem);
 	return err;
 
 out_unlock:
-	shm_unlock(shp);
-	goto out;
-
-out_free:
-	kfree(sfd);
-out_put_dentry:
-	path_put(&path);
-	goto out_nattch;
+	rcu_read_unlock();
+out:
+	return err;
 }
 
 SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
@@ -1235,8 +1277,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
 #else /* CONFIG_MMU */
 	/* under NOMMU conditions, the exact address to be destroyed must be
 	 * given */
-	retval = -EINVAL;
-	if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
+	if (vma && vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
 		do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
 		retval = 0;
 	}
diff --git a/ipc/util.c b/ipc/util.c
index 4704223..e829da9 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -15,6 +15,14 @@
  * Jun 2006 - namespaces ssupport
  *            OpenVZ, SWsoft Inc.
  *            Pavel Emelianov <xemul@openvz.org>
+ *
+ * General sysv ipc locking scheme:
+ *  when doing ipc id lookups, take the ids->rwsem
+ *      rcu_read_lock()
+ *          obtain the ipc object (kern_ipc_perm)
+ *          perform security, capabilities, auditing and permission checks, etc.
+ *          acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object()
+ *             perform data updates (ie: SET, RMID, LOCK/UNLOCK commands)
  */
 
 #include <linux/mm.h>
@@ -119,7 +127,7 @@ __initcall(ipc_init);
  
 void ipc_init_ids(struct ipc_ids *ids)
 {
-	init_rwsem(&ids->rw_mutex);
+	init_rwsem(&ids->rwsem);
 
 	ids->in_use = 0;
 	ids->seq = 0;
@@ -174,7 +182,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
  *	@ids: Identifier set
  *	@key: The key to find
  *	
- *	Requires ipc_ids.rw_mutex locked.
+ *	Requires ipc_ids.rwsem locked.
  *	Returns the LOCKED pointer to the ipc structure if found or NULL
  *	if not.
  *	If key is found ipc points to the owning ipc structure
@@ -197,7 +205,8 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
 			continue;
 		}
 
-		ipc_lock_by_ptr(ipc);
+		rcu_read_lock();
+		ipc_lock_object(ipc);
 		return ipc;
 	}
 
@@ -208,7 +217,7 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
  *	ipc_get_maxid 	-	get the last assigned id
  *	@ids: IPC identifier set
  *
- *	Called with ipc_ids.rw_mutex held.
+ *	Called with ipc_ids.rwsem held.
  */
 
 int ipc_get_maxid(struct ipc_ids *ids)
@@ -246,7 +255,7 @@ int ipc_get_maxid(struct ipc_ids *ids)
  *	is returned. The 'new' entry is returned in a locked state on success.
  *	On failure the entry is not locked and a negative err-code is returned.
  *
- *	Called with writer ipc_ids.rw_mutex held.
+ *	Called with writer ipc_ids.rwsem held.
  */
 int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 {
@@ -312,9 +321,9 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
 {
 	int err;
 
-	down_write(&ids->rw_mutex);
+	down_write(&ids->rwsem);
 	err = ops->getnew(ns, params);
-	up_write(&ids->rw_mutex);
+	up_write(&ids->rwsem);
 	return err;
 }
 
@@ -331,7 +340,7 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
  *
  *	On success, the IPC id is returned.
  *
- *	It is called with ipc_ids.rw_mutex and ipcp->lock held.
+ *	It is called with ipc_ids.rwsem and ipcp->lock held.
  */
 static int ipc_check_perms(struct ipc_namespace *ns,
 			   struct kern_ipc_perm *ipcp,
@@ -376,7 +385,7 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
 	 * Take the lock as a writer since we are potentially going to add
 	 * a new entry + read locks are not "upgradable"
 	 */
-	down_write(&ids->rw_mutex);
+	down_write(&ids->rwsem);
 	ipcp = ipc_findkey(ids, params->key);
 	if (ipcp == NULL) {
 		/* key not used */
@@ -402,7 +411,7 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
 		}
 		ipc_unlock(ipcp);
 	}
-	up_write(&ids->rw_mutex);
+	up_write(&ids->rwsem);
 
 	return err;
 }
@@ -413,7 +422,7 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
  *	@ids: IPC identifier set
  *	@ipcp: ipc perm structure containing the identifier to remove
  *
- *	ipc_ids.rw_mutex (as a writer) and the spinlock for this ID are held
+ *	ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
  *	before this function is called, and remain locked on the exit.
  */
  
@@ -621,7 +630,7 @@ struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id)
 }
 
 /**
- * ipc_lock - Lock an ipc structure without rw_mutex held
+ * ipc_lock - Lock an ipc structure without rwsem held
  * @ids: IPC identifier set
  * @id: ipc id to look for
  *
@@ -677,22 +686,6 @@ out:
 	return out;
 }
 
-struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
-{
-	struct kern_ipc_perm *out;
-
-	out = ipc_lock(ids, id);
-	if (IS_ERR(out))
-		return out;
-
-	if (ipc_checkid(out, id)) {
-		ipc_unlock(out);
-		return ERR_PTR(-EIDRM);
-	}
-
-	return out;
-}
-
 /**
  * ipcget - Common sys_*get() code
  * @ns : namsepace
@@ -733,7 +726,7 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
 }
 
 /**
- * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
+ * ipcctl_pre_down_nolock - retrieve an ipc and check permissions for some IPC_XXX cmd
  * @ns:  the ipc namespace
  * @ids:  the table of ids where to look for the ipc
  * @id:   the id of the ipc to retrieve
@@ -746,29 +739,13 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
  * It must be called without any lock held and
  *  - retrieves the ipc with the given id in the given table.
  *  - performs some audit and permission check, depending on the given cmd
- *  - returns the ipc with the ipc lock held in case of success
- *    or an err-code without any lock held otherwise.
+ *  - returns a pointer to the ipc object or otherwise, the corresponding error.
  *
- * Call holding the both the rw_mutex and the rcu read lock.
+ * Call holding the both the rwsem and the rcu read lock.
  */
-struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
-				      struct ipc_ids *ids, int id, int cmd,
-				      struct ipc64_perm *perm, int extra_perm)
-{
-	struct kern_ipc_perm *ipcp;
-
-	ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm);
-	if (IS_ERR(ipcp))
-		goto out;
-
-	spin_lock(&ipcp->lock);
-out:
-	return ipcp;
-}
-
 struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
-					     struct ipc_ids *ids, int id, int cmd,
-					     struct ipc64_perm *perm, int extra_perm)
+					struct ipc_ids *ids, int id, int cmd,
+					struct ipc64_perm *perm, int extra_perm)
 {
 	kuid_t euid;
 	int err = -EPERM;
@@ -846,7 +823,8 @@ static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
 		ipc = idr_find(&ids->ipcs_idr, pos);
 		if (ipc != NULL) {
 			*new_pos = pos + 1;
-			ipc_lock_by_ptr(ipc);
+			rcu_read_lock();
+			ipc_lock_object(ipc);
 			return ipc;
 		}
 	}
@@ -884,7 +862,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
 	 * Take the lock - this will be released by the corresponding
 	 * call to stop().
 	 */
-	down_read(&ids->rw_mutex);
+	down_read(&ids->rwsem);
 
 	/* pos < 0 is invalid */
 	if (*pos < 0)
@@ -911,7 +889,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
 
 	ids = &iter->ns->ids[iface->ids];
 	/* Release the lock we took in start() */
-	up_read(&ids->rw_mutex);
+	up_read(&ids->rwsem);
 }
 
 static int sysvipc_proc_show(struct seq_file *s, void *it)
diff --git a/ipc/util.h b/ipc/util.h
index b6a6a88..c5f3338b 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -94,10 +94,10 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
 #define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
 
-/* must be called with ids->rw_mutex acquired for writing */
+/* must be called with ids->rwsem acquired for writing */
 int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
 
-/* must be called with ids->rw_mutex acquired for reading */
+/* must be called with ids->rwsem acquired for reading */
 int ipc_get_maxid(struct ipc_ids *);
 
 /* must be called with both locks acquired. */
@@ -131,9 +131,6 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
 struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
 					     struct ipc_ids *ids, int id, int cmd,
 					     struct ipc64_perm *perm, int extra_perm);
-struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
-				      struct ipc_ids *ids, int id, int cmd,
-				      struct ipc64_perm *perm, int extra_perm);
 
 #ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
   /* On IA-64, we always use the "64-bit version" of the IPC structures.  */ 
@@ -174,19 +171,12 @@ static inline void ipc_assert_locked_object(struct kern_ipc_perm *perm)
 	assert_spin_locked(&perm->lock);
 }
 
-static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
-{
-	rcu_read_lock();
-	ipc_lock_object(perm);
-}
-
 static inline void ipc_unlock(struct kern_ipc_perm *perm)
 {
 	ipc_unlock_object(perm);
 	rcu_read_unlock();
 }
 
-struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id);
 struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id);
 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
 			struct ipc_ops *ops, struct ipc_params *params);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 789ec46..e82423d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -215,6 +215,8 @@ static u64 cgroup_serial_nr_next = 1;
  */
 static int need_forkexit_callback __read_mostly;
 
+static struct cftype cgroup_base_files[];
+
 static void cgroup_offline_fn(struct work_struct *work);
 static int cgroup_destroy_locked(struct cgroup *cgrp);
 static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
@@ -464,7 +466,7 @@ static inline void put_css_set_taskexit(struct css_set *cset)
  * @new_cgrp: cgroup that's being entered by the task
  * @template: desired set of css pointers in css_set (pre-calculated)
  *
- * Returns true if "cg" matches "old_cg" except for the hierarchy
+ * Returns true if "cset" matches "old_cset" except for the hierarchy
  * which "new_cgrp" belongs to, for which it should match "new_cgrp".
  */
 static bool compare_css_sets(struct css_set *cset,
@@ -803,8 +805,7 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
 
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
-static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
-			       unsigned long subsys_mask);
+static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask);
 static const struct inode_operations cgroup_dir_inode_operations;
 static const struct file_operations proc_cgroupstats_operations;
 
@@ -864,8 +865,6 @@ static void cgroup_free_fn(struct work_struct *work)
 	 */
 	dput(cgrp->parent->dentry);
 
-	ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
-
 	/*
 	 * Drop the active superblock reference that we took when we
 	 * created the cgroup. This will free cgrp->root, if we are
@@ -956,28 +955,23 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
 }
 
 /**
- * cgroup_clear_directory - selective removal of base and subsystem files
- * @dir: directory containing the files
- * @base_files: true if the base files should be removed
+ * cgroup_clear_dir - remove subsys files in a cgroup directory
+ * @cgrp: target cgroup
  * @subsys_mask: mask of the subsystem ids whose files should be removed
  */
-static void cgroup_clear_directory(struct dentry *dir, bool base_files,
-				   unsigned long subsys_mask)
+static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
 {
-	struct cgroup *cgrp = __d_cgrp(dir);
 	struct cgroup_subsys *ss;
+	int i;
 
-	for_each_root_subsys(cgrp->root, ss) {
+	for_each_subsys(ss, i) {
 		struct cftype_set *set;
-		if (!test_bit(ss->subsys_id, &subsys_mask))
+
+		if (!test_bit(i, &subsys_mask))
 			continue;
 		list_for_each_entry(set, &ss->cftsets, node)
 			cgroup_addrm_files(cgrp, NULL, set->cfts, false);
 	}
-	if (base_files) {
-		while (!list_empty(&cgrp->files))
-			cgroup_rm_file(cgrp, NULL);
-	}
 }
 
 /*
@@ -986,9 +980,6 @@ static void cgroup_clear_directory(struct dentry *dir, bool base_files,
 static void cgroup_d_remove_dir(struct dentry *dentry)
 {
 	struct dentry *parent;
-	struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
-
-	cgroup_clear_directory(dentry, true, root->subsys_mask);
 
 	parent = dentry->d_parent;
 	spin_lock(&parent->d_lock);
@@ -1009,32 +1000,47 @@ static int rebind_subsystems(struct cgroupfs_root *root,
 {
 	struct cgroup *cgrp = &root->top_cgroup;
 	struct cgroup_subsys *ss;
-	int i;
+	unsigned long pinned = 0;
+	int i, ret;
 
 	BUG_ON(!mutex_is_locked(&cgroup_mutex));
 	BUG_ON(!mutex_is_locked(&cgroup_root_mutex));
 
 	/* Check that any added subsystems are currently free */
 	for_each_subsys(ss, i) {
-		unsigned long bit = 1UL << i;
-
-		if (!(bit & added_mask))
+		if (!(added_mask & (1 << i)))
 			continue;
 
+		/* is the subsystem mounted elsewhere? */
 		if (ss->root != &cgroup_dummy_root) {
-			/* Subsystem isn't free */
-			return -EBUSY;
+			ret = -EBUSY;
+			goto out_put;
+		}
+
+		/* pin the module */
+		if (!try_module_get(ss->module)) {
+			ret = -ENOENT;
+			goto out_put;
 		}
+		pinned |= 1 << i;
 	}
 
-	/* Currently we don't handle adding/removing subsystems when
-	 * any child cgroups exist. This is theoretically supportable
-	 * but involves complex error handling, so it's being left until
-	 * later */
-	if (root->number_of_cgroups > 1)
-		return -EBUSY;
+	/* subsys could be missing if unloaded between parsing and here */
+	if (added_mask != pinned) {
+		ret = -ENOENT;
+		goto out_put;
+	}
+
+	ret = cgroup_populate_dir(cgrp, added_mask);
+	if (ret)
+		goto out_put;
+
+	/*
+	 * Nothing can fail from this point on.  Remove files for the
+	 * removed subsystems and rebind each subsystem.
+	 */
+	cgroup_clear_dir(cgrp, removed_mask);
 
-	/* Process each subsystem */
 	for_each_subsys(ss, i) {
 		unsigned long bit = 1UL << i;
 
@@ -1068,20 +1074,6 @@ static int rebind_subsystems(struct cgroupfs_root *root,
 			/* subsystem is now free - drop reference on module */
 			module_put(ss->module);
 			root->subsys_mask &= ~bit;
-		} else if (bit & root->subsys_mask) {
-			/* Subsystem state should already exist */
-			BUG_ON(!cgrp->subsys[i]);
-			/*
-			 * a refcount was taken, but we already had one, so
-			 * drop the extra reference.
-			 */
-			module_put(ss->module);
-#ifdef CONFIG_MODULE_UNLOAD
-			BUG_ON(ss->module && !module_refcount(ss->module));
-#endif
-		} else {
-			/* Subsystem state shouldn't exist */
-			BUG_ON(cgrp->subsys[i]);
 		}
 	}
 
@@ -1092,6 +1084,12 @@ static int rebind_subsystems(struct cgroupfs_root *root,
 	root->flags |= CGRP_ROOT_SUBSYS_BOUND;
 
 	return 0;
+
+out_put:
+	for_each_subsys(ss, i)
+		if (pinned & (1 << i))
+			module_put(ss->module);
+	return ret;
 }
 
 static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
@@ -1142,7 +1140,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 	char *token, *o = data;
 	bool all_ss = false, one_ss = false;
 	unsigned long mask = (unsigned long)-1;
-	bool module_pin_failed = false;
 	struct cgroup_subsys *ss;
 	int i;
 
@@ -1285,52 +1282,9 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 	if (!opts->subsys_mask && !opts->name)
 		return -EINVAL;
 
-	/*
-	 * Grab references on all the modules we'll need, so the subsystems
-	 * don't dance around before rebind_subsystems attaches them. This may
-	 * take duplicate reference counts on a subsystem that's already used,
-	 * but rebind_subsystems handles this case.
-	 */
-	for_each_subsys(ss, i) {
-		if (!(opts->subsys_mask & (1UL << i)))
-			continue;
-		if (!try_module_get(cgroup_subsys[i]->module)) {
-			module_pin_failed = true;
-			break;
-		}
-	}
-	if (module_pin_failed) {
-		/*
-		 * oops, one of the modules was going away. this means that we
-		 * raced with a module_delete call, and to the user this is
-		 * essentially a "subsystem doesn't exist" case.
-		 */
-		for (i--; i >= 0; i--) {
-			/* drop refcounts only on the ones we took */
-			unsigned long bit = 1UL << i;
-
-			if (!(bit & opts->subsys_mask))
-				continue;
-			module_put(cgroup_subsys[i]->module);
-		}
-		return -ENOENT;
-	}
-
 	return 0;
 }
 
-static void drop_parsed_module_refcounts(unsigned long subsys_mask)
-{
-	struct cgroup_subsys *ss;
-	int i;
-
-	mutex_lock(&cgroup_mutex);
-	for_each_subsys(ss, i)
-		if (subsys_mask & (1UL << i))
-			module_put(cgroup_subsys[i]->module);
-	mutex_unlock(&cgroup_mutex);
-}
-
 static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 {
 	int ret = 0;
@@ -1370,22 +1324,15 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 		goto out_unlock;
 	}
 
-	/*
-	 * Clear out the files of subsystems that should be removed, do
-	 * this before rebind_subsystems, since rebind_subsystems may
-	 * change this hierarchy's subsys_list.
-	 */
-	cgroup_clear_directory(cgrp->dentry, false, removed_mask);
-
-	ret = rebind_subsystems(root, added_mask, removed_mask);
-	if (ret) {
-		/* rebind_subsystems failed, re-populate the removed files */
-		cgroup_populate_dir(cgrp, false, removed_mask);
+	/* remounting is not allowed for populated hierarchies */
+	if (root->number_of_cgroups > 1) {
+		ret = -EBUSY;
 		goto out_unlock;
 	}
 
-	/* re-populate subsystem files */
-	cgroup_populate_dir(cgrp, false, added_mask);
+	ret = rebind_subsystems(root, added_mask, removed_mask);
+	if (ret)
+		goto out_unlock;
 
 	if (opts.release_agent)
 		strcpy(root->release_agent_path, opts.release_agent);
@@ -1395,8 +1342,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 	mutex_unlock(&cgroup_root_mutex);
 	mutex_unlock(&cgroup_mutex);
 	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
-	if (ret)
-		drop_parsed_module_refcounts(opts.subsys_mask);
 	return ret;
 }
 
@@ -1431,6 +1376,7 @@ static void init_cgroup_root(struct cgroupfs_root *root)
 	cgrp->root = root;
 	RCU_INIT_POINTER(cgrp->name, &root_cgroup_name);
 	init_cgroup_housekeeping(cgrp);
+	idr_init(&root->cgroup_idr);
 }
 
 static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end)
@@ -1503,7 +1449,6 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts)
 	 */
 	root->subsys_mask = opts->subsys_mask;
 	root->flags = opts->flags;
-	ida_init(&root->cgroup_ida);
 	if (opts->release_agent)
 		strcpy(root->release_agent_path, opts->release_agent);
 	if (opts->name)
@@ -1519,7 +1464,7 @@ static void cgroup_free_root(struct cgroupfs_root *root)
 		/* hierarhcy ID shoulid already have been released */
 		WARN_ON_ONCE(root->hierarchy_id);
 
-		ida_destroy(&root->cgroup_ida);
+		idr_destroy(&root->cgroup_idr);
 		kfree(root);
 	}
 }
@@ -1584,7 +1529,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 	int ret = 0;
 	struct super_block *sb;
 	struct cgroupfs_root *new_root;
+	struct list_head tmp_links;
 	struct inode *inode;
+	const struct cred *cred;
 
 	/* First find the desired set of subsystems */
 	mutex_lock(&cgroup_mutex);
@@ -1600,7 +1547,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 	new_root = cgroup_root_from_opts(&opts);
 	if (IS_ERR(new_root)) {
 		ret = PTR_ERR(new_root);
-		goto drop_modules;
+		goto out_err;
 	}
 	opts.new_root = new_root;
 
@@ -1609,17 +1556,15 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 	if (IS_ERR(sb)) {
 		ret = PTR_ERR(sb);
 		cgroup_free_root(opts.new_root);
-		goto drop_modules;
+		goto out_err;
 	}
 
 	root = sb->s_fs_info;
 	BUG_ON(!root);
 	if (root == opts.new_root) {
 		/* We used the new root structure, so this is a new hierarchy */
-		struct list_head tmp_links;
 		struct cgroup *root_cgrp = &root->top_cgroup;
 		struct cgroupfs_root *existing_root;
-		const struct cred *cred;
 		int i;
 		struct css_set *cset;
 
@@ -1634,6 +1579,11 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 		mutex_lock(&cgroup_mutex);
 		mutex_lock(&cgroup_root_mutex);
 
+		root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp,
+					   0, 1, GFP_KERNEL);
+		if (root_cgrp->id < 0)
+			goto unlock_drop;
+
 		/* Check for name clashes with existing mounts */
 		ret = -EBUSY;
 		if (strlen(root->name))
@@ -1657,26 +1607,37 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 		if (ret)
 			goto unlock_drop;
 
+		sb->s_root->d_fsdata = root_cgrp;
+		root_cgrp->dentry = sb->s_root;
+
+		/*
+		 * We're inside get_sb() and will call lookup_one_len() to
+		 * create the root files, which doesn't work if SELinux is
+		 * in use.  The following cred dancing somehow works around
+		 * it.  See 2ce9738ba ("cgroupfs: use init_cred when
+		 * populating new cgroupfs mount") for more details.
+		 */
+		cred = override_creds(&init_cred);
+
+		ret = cgroup_addrm_files(root_cgrp, NULL, cgroup_base_files, true);
+		if (ret)
+			goto rm_base_files;
+
 		ret = rebind_subsystems(root, root->subsys_mask, 0);
-		if (ret == -EBUSY) {
-			free_cgrp_cset_links(&tmp_links);
-			goto unlock_drop;
-		}
+		if (ret)
+			goto rm_base_files;
+
+		revert_creds(cred);
+
 		/*
 		 * There must be no failure case after here, since rebinding
 		 * takes care of subsystems' refcounts, which are explicitly
 		 * dropped in the failure exit path.
 		 */
 
-		/* EBUSY should be the only error here */
-		BUG_ON(ret);
-
 		list_add(&root->root_list, &cgroup_roots);
 		cgroup_root_count++;
 
-		sb->s_root->d_fsdata = root_cgrp;
-		root->top_cgroup.dentry = sb->s_root;
-
 		/* Link the top cgroup in this hierarchy into all
 		 * the css_set objects */
 		write_lock(&css_set_lock);
@@ -1689,9 +1650,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 		BUG_ON(!list_empty(&root_cgrp->children));
 		BUG_ON(root->number_of_cgroups != 1);
 
-		cred = override_creds(&init_cred);
-		cgroup_populate_dir(root_cgrp, true, root->subsys_mask);
-		revert_creds(cred);
 		mutex_unlock(&cgroup_root_mutex);
 		mutex_unlock(&cgroup_mutex);
 		mutex_unlock(&inode->i_mutex);
@@ -1711,15 +1669,16 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 				pr_warning("cgroup: new mount options do not match the existing superblock, will be ignored\n");
 			}
 		}
-
-		/* no subsys rebinding, so refcounts don't change */
-		drop_parsed_module_refcounts(opts.subsys_mask);
 	}
 
 	kfree(opts.release_agent);
 	kfree(opts.name);
 	return dget(sb->s_root);
 
+ rm_base_files:
+	free_cgrp_cset_links(&tmp_links);
+	cgroup_addrm_files(&root->top_cgroup, NULL, cgroup_base_files, false);
+	revert_creds(cred);
  unlock_drop:
 	cgroup_exit_root_id(root);
 	mutex_unlock(&cgroup_root_mutex);
@@ -1727,8 +1686,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 	mutex_unlock(&inode->i_mutex);
  drop_new_super:
 	deactivate_locked_super(sb);
- drop_modules:
-	drop_parsed_module_refcounts(opts.subsys_mask);
  out_err:
 	kfree(opts.release_agent);
 	kfree(opts.name);
@@ -1746,6 +1703,7 @@ static void cgroup_kill_sb(struct super_block *sb) {
 	BUG_ON(root->number_of_cgroups != 1);
 	BUG_ON(!list_empty(&cgrp->children));
 
+	mutex_lock(&cgrp->dentry->d_inode->i_mutex);
 	mutex_lock(&cgroup_mutex);
 	mutex_lock(&cgroup_root_mutex);
 
@@ -1778,6 +1736,7 @@ static void cgroup_kill_sb(struct super_block *sb) {
 
 	mutex_unlock(&cgroup_root_mutex);
 	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
 
 	simple_xattrs_free(&cgrp->xattrs);
 
@@ -1889,7 +1848,7 @@ EXPORT_SYMBOL_GPL(task_cgroup_path);
 struct task_and_cgroup {
 	struct task_struct	*task;
 	struct cgroup		*cgrp;
-	struct css_set		*cg;
+	struct css_set		*cset;
 };
 
 struct cgroup_taskset {
@@ -2107,8 +2066,8 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
 
 		tc = flex_array_get(group, i);
 		old_cset = task_css_set(tc->task);
-		tc->cg = find_css_set(old_cset, cgrp);
-		if (!tc->cg) {
+		tc->cset = find_css_set(old_cset, cgrp);
+		if (!tc->cset) {
 			retval = -ENOMEM;
 			goto out_put_css_set_refs;
 		}
@@ -2121,7 +2080,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
 	 */
 	for (i = 0; i < group_size; i++) {
 		tc = flex_array_get(group, i);
-		cgroup_task_migrate(tc->cgrp, tc->task, tc->cg);
+		cgroup_task_migrate(tc->cgrp, tc->task, tc->cset);
 	}
 	/* nothing is sensitive to fork() after this point. */
 
@@ -2141,9 +2100,9 @@ out_put_css_set_refs:
 	if (retval) {
 		for (i = 0; i < group_size; i++) {
 			tc = flex_array_get(group, i);
-			if (!tc->cg)
+			if (!tc->cset)
 				break;
-			put_css_set(tc->cg);
+			put_css_set(tc->cset);
 		}
 	}
 out_cancel_attach:
@@ -2253,9 +2212,9 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 
 	mutex_lock(&cgroup_mutex);
 	for_each_active_root(root) {
-		struct cgroup *from_cg = task_cgroup_from_root(from, root);
+		struct cgroup *from_cgrp = task_cgroup_from_root(from, root);
 
-		retval = cgroup_attach_task(from_cg, tsk, false);
+		retval = cgroup_attach_task(from_cgrp, tsk, false);
 		if (retval)
 			break;
 	}
@@ -2447,11 +2406,6 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf,
  * supports string->u64 maps, but can be extended in future.
  */
 
-struct cgroup_seqfile_state {
-	struct cftype *cft;
-	struct cgroup *cgroup;
-};
-
 static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value)
 {
 	struct seq_file *sf = cb->state;
@@ -2460,59 +2414,45 @@ static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value)
 
 static int cgroup_seqfile_show(struct seq_file *m, void *arg)
 {
-	struct cgroup_seqfile_state *state = m->private;
-	struct cftype *cft = state->cft;
+	struct cfent *cfe = m->private;
+	struct cftype *cft = cfe->type;
+	struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent);
+
 	if (cft->read_map) {
 		struct cgroup_map_cb cb = {
 			.fill = cgroup_map_add,
 			.state = m,
 		};
-		return cft->read_map(state->cgroup, cft, &cb);
+		return cft->read_map(cgrp, cft, &cb);
 	}
-	return cft->read_seq_string(state->cgroup, cft, m);
-}
-
-static int cgroup_seqfile_release(struct inode *inode, struct file *file)
-{
-	struct seq_file *seq = file->private_data;
-	kfree(seq->private);
-	return single_release(inode, file);
+	return cft->read_seq_string(cgrp, cft, m);
 }
 
 static const struct file_operations cgroup_seqfile_operations = {
 	.read = seq_read,
 	.write = cgroup_file_write,
 	.llseek = seq_lseek,
-	.release = cgroup_seqfile_release,
+	.release = single_release,
 };
 
 static int cgroup_file_open(struct inode *inode, struct file *file)
 {
 	int err;
+	struct cfent *cfe;
 	struct cftype *cft;
 
 	err = generic_file_open(inode, file);
 	if (err)
 		return err;
-	cft = __d_cft(file->f_dentry);
+	cfe = __d_cfe(file->f_dentry);
+	cft = cfe->type;
 
 	if (cft->read_map || cft->read_seq_string) {
-		struct cgroup_seqfile_state *state;
-
-		state = kzalloc(sizeof(*state), GFP_USER);
-		if (!state)
-			return -ENOMEM;
-
-		state->cft = cft;
-		state->cgroup = __d_cgrp(file->f_dentry->d_parent);
 		file->f_op = &cgroup_seqfile_operations;
-		err = single_open(file, cgroup_seqfile_show, state);
-		if (err < 0)
-			kfree(state);
-	} else if (cft->open)
+		err = single_open(file, cgroup_seqfile_show, cfe);
+	} else if (cft->open) {
 		err = cft->open(inode, file);
-	else
-		err = 0;
+	}
 
 	return err;
 }
@@ -2782,11 +2722,26 @@ out:
 	return error;
 }
 
+/**
+ * cgroup_addrm_files - add or remove files to a cgroup directory
+ * @cgrp: the target cgroup
+ * @subsys: the subsystem of files to be added
+ * @cfts: array of cftypes to be added
+ * @is_add: whether to add or remove
+ *
+ * Depending on @is_add, add or remove files defined by @cfts on @cgrp.
+ * All @cfts should belong to @subsys.  For removals, this function never
+ * fails.  If addition fails, this function doesn't remove files already
+ * added.  The caller is responsible for cleaning up.
+ */
 static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
 			      struct cftype cfts[], bool is_add)
 {
 	struct cftype *cft;
-	int err, ret = 0;
+	int ret;
+
+	lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex);
+	lockdep_assert_held(&cgroup_mutex);
 
 	for (cft = cfts; cft->name[0] != '\0'; cft++) {
 		/* does cft->flags tell us to skip this file on @cgrp? */
@@ -2798,16 +2753,17 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
 			continue;
 
 		if (is_add) {
-			err = cgroup_add_file(cgrp, subsys, cft);
-			if (err)
+			ret = cgroup_add_file(cgrp, subsys, cft);
+			if (ret) {
 				pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n",
-					cft->name, err);
-			ret = err;
+					cft->name, ret);
+				return ret;
+			}
 		} else {
 			cgroup_rm_file(cgrp, cft);
 		}
 	}
-	return ret;
+	return 0;
 }
 
 static void cgroup_cfts_prepare(void)
@@ -2822,8 +2778,8 @@ static void cgroup_cfts_prepare(void)
 	mutex_lock(&cgroup_mutex);
 }
 
-static void cgroup_cfts_commit(struct cgroup_subsys *ss,
-			       struct cftype *cfts, bool is_add)
+static int cgroup_cfts_commit(struct cgroup_subsys *ss,
+			      struct cftype *cfts, bool is_add)
 	__releases(&cgroup_mutex)
 {
 	LIST_HEAD(pending);
@@ -2832,12 +2788,13 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
 	struct dentry *prev = NULL;
 	struct inode *inode;
 	u64 update_before;
+	int ret = 0;
 
 	/* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
 	if (!cfts || ss->root == &cgroup_dummy_root ||
 	    !atomic_inc_not_zero(&sb->s_active)) {
 		mutex_unlock(&cgroup_mutex);
-		return;
+		return 0;
 	}
 
 	/*
@@ -2853,10 +2810,13 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
 	inode = root->dentry->d_inode;
 	mutex_lock(&inode->i_mutex);
 	mutex_lock(&cgroup_mutex);
-	cgroup_addrm_files(root, ss, cfts, is_add);
+	ret = cgroup_addrm_files(root, ss, cfts, is_add);
 	mutex_unlock(&cgroup_mutex);
 	mutex_unlock(&inode->i_mutex);
 
+	if (ret)
+		goto out_deact;
+
 	/* add/rm files for all cgroups created before */
 	rcu_read_lock();
 	cgroup_for_each_descendant_pre(cgrp, root) {
@@ -2873,15 +2833,19 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
 		mutex_lock(&inode->i_mutex);
 		mutex_lock(&cgroup_mutex);
 		if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
-			cgroup_addrm_files(cgrp, ss, cfts, is_add);
+			ret = cgroup_addrm_files(cgrp, ss, cfts, is_add);
 		mutex_unlock(&cgroup_mutex);
 		mutex_unlock(&inode->i_mutex);
 
 		rcu_read_lock();
+		if (ret)
+			break;
 	}
 	rcu_read_unlock();
 	dput(prev);
+out_deact:
 	deactivate_super(sb);
+	return ret;
 }
 
 /**
@@ -2901,6 +2865,7 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
 int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
 {
 	struct cftype_set *set;
+	int ret;
 
 	set = kzalloc(sizeof(*set), GFP_KERNEL);
 	if (!set)
@@ -2909,9 +2874,10 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
 	cgroup_cfts_prepare();
 	set->cfts = cfts;
 	list_add_tail(&set->node, &ss->cftsets);
-	cgroup_cfts_commit(ss, cfts, true);
-
-	return 0;
+	ret = cgroup_cfts_commit(ss, cfts, true);
+	if (ret)
+		cgroup_rm_cftypes(ss, cfts);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
 
@@ -3340,8 +3306,8 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan)
 	 * guarantees forward progress and that we don't miss any tasks.
 	 */
 	heap->size = 0;
-	cgroup_iter_start(scan->cg, &it);
-	while ((p = cgroup_iter_next(scan->cg, &it))) {
+	cgroup_iter_start(scan->cgrp, &it);
+	while ((p = cgroup_iter_next(scan->cgrp, &it))) {
 		/*
 		 * Only affect tasks that qualify per the caller's callback,
 		 * if he provided one
@@ -3374,7 +3340,7 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan)
 		 * the heap and wasn't inserted
 		 */
 	}
-	cgroup_iter_end(scan->cg, &it);
+	cgroup_iter_end(scan->cgrp, &it);
 
 	if (heap->size) {
 		for (i = 0; i < heap->size; i++) {
@@ -3420,7 +3386,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
 {
 	struct cgroup_scanner scan;
 
-	scan.cg = from;
+	scan.cgrp = from;
 	scan.test_task = NULL; /* select all tasks in cgroup */
 	scan.process_task = cgroup_transfer_one_task;
 	scan.heap = NULL;
@@ -3468,7 +3434,7 @@ struct cgroup_pidlist {
 	/* pointer to the cgroup we belong to, for list removal purposes */
 	struct cgroup *owner;
 	/* protects the other fields */
-	struct rw_semaphore mutex;
+	struct rw_semaphore rwsem;
 };
 
 /*
@@ -3541,7 +3507,7 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
 	struct pid_namespace *ns = task_active_pid_ns(current);
 
 	/*
-	 * We can't drop the pidlist_mutex before taking the l->mutex in case
+	 * We can't drop the pidlist_mutex before taking the l->rwsem in case
 	 * the last ref-holder is trying to remove l from the list at the same
 	 * time. Holding the pidlist_mutex precludes somebody taking whichever
 	 * list we find out from under us - compare release_pid_array().
@@ -3550,7 +3516,7 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
 	list_for_each_entry(l, &cgrp->pidlists, links) {
 		if (l->key.type == type && l->key.ns == ns) {
 			/* make sure l doesn't vanish out from under us */
-			down_write(&l->mutex);
+			down_write(&l->rwsem);
 			mutex_unlock(&cgrp->pidlist_mutex);
 			return l;
 		}
@@ -3561,8 +3527,8 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
 		mutex_unlock(&cgrp->pidlist_mutex);
 		return l;
 	}
-	init_rwsem(&l->mutex);
-	down_write(&l->mutex);
+	init_rwsem(&l->rwsem);
+	down_write(&l->rwsem);
 	l->key.type = type;
 	l->key.ns = get_pid_ns(ns);
 	l->owner = cgrp;
@@ -3623,7 +3589,7 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
 	l->list = array;
 	l->length = length;
 	l->use_count++;
-	up_write(&l->mutex);
+	up_write(&l->rwsem);
 	*lp = l;
 	return 0;
 }
@@ -3701,7 +3667,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
 	int index = 0, pid = *pos;
 	int *iter;
 
-	down_read(&l->mutex);
+	down_read(&l->rwsem);
 	if (pid) {
 		int end = l->length;
 
@@ -3728,7 +3694,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
 static void cgroup_pidlist_stop(struct seq_file *s, void *v)
 {
 	struct cgroup_pidlist *l = s->private;
-	up_read(&l->mutex);
+	up_read(&l->rwsem);
 }
 
 static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
@@ -3774,7 +3740,7 @@ static void cgroup_release_pid_array(struct cgroup_pidlist *l)
 	 * pidlist_mutex, we have to take pidlist_mutex first.
 	 */
 	mutex_lock(&l->owner->pidlist_mutex);
-	down_write(&l->mutex);
+	down_write(&l->rwsem);
 	BUG_ON(!l->use_count);
 	if (!--l->use_count) {
 		/* we're the last user if refcount is 0; remove and free */
@@ -3782,12 +3748,12 @@ static void cgroup_release_pid_array(struct cgroup_pidlist *l)
 		mutex_unlock(&l->owner->pidlist_mutex);
 		pidlist_free(l->list);
 		put_pid_ns(l->key.ns);
-		up_write(&l->mutex);
+		up_write(&l->rwsem);
 		kfree(l);
 		return;
 	}
 	mutex_unlock(&l->owner->pidlist_mutex);
-	up_write(&l->mutex);
+	up_write(&l->rwsem);
 }
 
 static int cgroup_pidlist_release(struct inode *inode, struct file *file)
@@ -3966,11 +3932,11 @@ static void cgroup_event_ptable_queue_proc(struct file *file,
 static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
 				      const char *buffer)
 {
-	struct cgroup_event *event = NULL;
+	struct cgroup_event *event;
 	struct cgroup *cgrp_cfile;
 	unsigned int efd, cfd;
-	struct file *efile = NULL;
-	struct file *cfile = NULL;
+	struct file *efile;
+	struct file *cfile;
 	char *endp;
 	int ret;
 
@@ -3996,31 +3962,31 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
 	efile = eventfd_fget(efd);
 	if (IS_ERR(efile)) {
 		ret = PTR_ERR(efile);
-		goto fail;
+		goto out_kfree;
 	}
 
 	event->eventfd = eventfd_ctx_fileget(efile);
 	if (IS_ERR(event->eventfd)) {
 		ret = PTR_ERR(event->eventfd);
-		goto fail;
+		goto out_put_efile;
 	}
 
 	cfile = fget(cfd);
 	if (!cfile) {
 		ret = -EBADF;
-		goto fail;
+		goto out_put_eventfd;
 	}
 
 	/* the process need read permission on control file */
 	/* AV: shouldn't we check that it's been opened for read instead? */
 	ret = inode_permission(file_inode(cfile), MAY_READ);
 	if (ret < 0)
-		goto fail;
+		goto out_put_cfile;
 
 	event->cft = __file_cft(cfile);
 	if (IS_ERR(event->cft)) {
 		ret = PTR_ERR(event->cft);
-		goto fail;
+		goto out_put_cfile;
 	}
 
 	/*
@@ -4030,18 +3996,18 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
 	cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent);
 	if (cgrp_cfile != cgrp) {
 		ret = -EINVAL;
-		goto fail;
+		goto out_put_cfile;
 	}
 
 	if (!event->cft->register_event || !event->cft->unregister_event) {
 		ret = -EINVAL;
-		goto fail;
+		goto out_put_cfile;
 	}
 
 	ret = event->cft->register_event(cgrp, event->cft,
 			event->eventfd, buffer);
 	if (ret)
-		goto fail;
+		goto out_put_cfile;
 
 	efile->f_op->poll(efile, &event->pt);
 
@@ -4061,16 +4027,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
 
 	return 0;
 
-fail:
-	if (cfile)
-		fput(cfile);
-
-	if (event && event->eventfd && !IS_ERR(event->eventfd))
-		eventfd_ctx_put(event->eventfd);
-
-	if (!IS_ERR_OR_NULL(efile))
-		fput(efile);
-
+out_put_cfile:
+	fput(cfile);
+out_put_eventfd:
+	eventfd_ctx_put(event->eventfd);
+out_put_efile:
+	fput(efile);
+out_kfree:
 	kfree(event);
 
 	return ret;
@@ -4148,31 +4111,29 @@ static struct cftype cgroup_base_files[] = {
 };
 
 /**
- * cgroup_populate_dir - selectively creation of files in a directory
+ * cgroup_populate_dir - create subsys files in a cgroup directory
  * @cgrp: target cgroup
- * @base_files: true if the base files should be added
  * @subsys_mask: mask of the subsystem ids whose files should be added
+ *
+ * On failure, no file is added.
  */
-static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
-			       unsigned long subsys_mask)
+static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
 {
-	int err;
 	struct cgroup_subsys *ss;
-
-	if (base_files) {
-		err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true);
-		if (err < 0)
-			return err;
-	}
+	int i, ret = 0;
 
 	/* process cftsets of each subsystem */
-	for_each_root_subsys(cgrp->root, ss) {
+	for_each_subsys(ss, i) {
 		struct cftype_set *set;
-		if (!test_bit(ss->subsys_id, &subsys_mask))
+
+		if (!test_bit(i, &subsys_mask))
 			continue;
 
-		list_for_each_entry(set, &ss->cftsets, node)
-			cgroup_addrm_files(cgrp, ss, set->cfts, true);
+		list_for_each_entry(set, &ss->cftsets, node) {
+			ret = cgroup_addrm_files(cgrp, ss, set->cfts, true);
+			if (ret < 0)
+				goto err;
+		}
 	}
 
 	/* This cgroup is ready now */
@@ -4190,6 +4151,9 @@ static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
 	}
 
 	return 0;
+err:
+	cgroup_clear_dir(cgrp, subsys_mask);
+	return ret;
 }
 
 static void css_dput_fn(struct work_struct *work)
@@ -4229,7 +4193,7 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
 	INIT_WORK(&css->dput_work, css_dput_fn);
 }
 
-/* invoke ->post_create() on a new CSS and mark it online if successful */
+/* invoke ->css_online() on a new CSS and mark it online if successful */
 static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
 {
 	int ret = 0;
@@ -4243,9 +4207,8 @@ static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
 	return ret;
 }
 
-/* if the CSS is online, invoke ->pre_destory() on it and mark it offline */
+/* if the CSS is online, invoke ->css_offline() on it and mark it offline */
 static void offline_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
-	__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
 {
 	struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
 
@@ -4288,7 +4251,11 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 		goto err_free_cgrp;
 	rcu_assign_pointer(cgrp->name, name);
 
-	cgrp->id = ida_simple_get(&root->cgroup_ida, 1, 0, GFP_KERNEL);
+	/*
+	 * Temporarily set the pointer to NULL, so idr_find() won't return
+	 * a half-baked cgroup.
+	 */
+	cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
 	if (cgrp->id < 0)
 		goto err_free_name;
 
@@ -4335,8 +4302,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 		}
 
 		err = percpu_ref_init(&css->refcnt, css_release);
-		if (err)
+		if (err) {
+			ss->css_free(cgrp);
 			goto err_free_all;
+		}
 
 		init_cgroup_css(css, ss, cgrp);
 
@@ -4386,7 +4355,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 		}
 	}
 
-	err = cgroup_populate_dir(cgrp, true, root->subsys_mask);
+	idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
+
+	err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true);
+	if (err)
+		goto err_destroy;
+
+	err = cgroup_populate_dir(cgrp, root->subsys_mask);
 	if (err)
 		goto err_destroy;
 
@@ -4408,7 +4383,7 @@ err_free_all:
 	/* Release the reference count that we took on the superblock */
 	deactivate_super(sb);
 err_free_id:
-	ida_simple_remove(&root->cgroup_ida, cgrp->id);
+	idr_remove(&root->cgroup_idr, cgrp->id);
 err_free_name:
 	kfree(rcu_dereference_raw(cgrp->name));
 err_free_cgrp:
@@ -4539,9 +4514,11 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
 	raw_spin_unlock(&release_list_lock);
 
 	/*
-	 * Remove @cgrp directory.  The removal puts the base ref but we
-	 * aren't quite done with @cgrp yet, so hold onto it.
+	 * Clear and remove @cgrp directory.  The removal puts the base ref
+	 * but we aren't quite done with @cgrp yet, so hold onto it.
 	 */
+	cgroup_clear_dir(cgrp, cgrp->root->subsys_mask);
+	cgroup_addrm_files(cgrp, NULL, cgroup_base_files, false);
 	dget(d);
 	cgroup_d_remove_dir(d);
 
@@ -4599,6 +4576,14 @@ static void cgroup_offline_fn(struct work_struct *work)
 	/* delete this cgroup from parent->children */
 	list_del_rcu(&cgrp->sibling);
 
+	/*
+	 * We should remove the cgroup object from idr before its grace
+	 * period starts, so we won't be looking up a cgroup while the
+	 * cgroup is being freed.
+	 */
+	idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+	cgrp->id = -1;
+
 	dput(d);
 
 	set_bit(CGRP_RELEASABLE, &parent->flags);
@@ -4800,7 +4785,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
 
 	/*
 	 * we shouldn't be called if the subsystem is in use, and the use of
-	 * try_module_get in parse_cgroupfs_options should ensure that it
+	 * try_module_get() in rebind_subsystems() should ensure that it
 	 * doesn't start being used while we're killing it off.
 	 */
 	BUG_ON(ss->root != &cgroup_dummy_root);
@@ -4924,6 +4909,10 @@ int __init cgroup_init(void)
 
 	BUG_ON(cgroup_init_root_id(&cgroup_dummy_root, 0, 1));
 
+	err = idr_alloc(&cgroup_dummy_root.cgroup_idr, cgroup_dummy_top,
+			0, 1, GFP_KERNEL);
+	BUG_ON(err < 0);
+
 	mutex_unlock(&cgroup_root_mutex);
 	mutex_unlock(&cgroup_mutex);
 
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index e565778..1b9c315 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -70,7 +70,6 @@ int number_of_cpusets __read_mostly;
 
 /* Forward declare cgroup structures */
 struct cgroup_subsys cpuset_subsys;
-struct cpuset;
 
 /* See "Frequency meter" comments, below. */
 
@@ -846,7 +845,7 @@ static void cpuset_change_cpumask(struct task_struct *tsk,
 {
 	struct cpuset *cpus_cs;
 
-	cpus_cs = effective_cpumask_cpuset(cgroup_cs(scan->cg));
+	cpus_cs = effective_cpumask_cpuset(cgroup_cs(scan->cgrp));
 	set_cpus_allowed_ptr(tsk, cpus_cs->cpus_allowed);
 }
 
@@ -867,7 +866,7 @@ static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap)
 {
 	struct cgroup_scanner scan;
 
-	scan.cg = cs->css.cgroup;
+	scan.cgrp = cs->css.cgroup;
 	scan.test_task = NULL;
 	scan.process_task = cpuset_change_cpumask;
 	scan.heap = heap;
@@ -1063,7 +1062,7 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
 static void cpuset_change_nodemask(struct task_struct *p,
 				   struct cgroup_scanner *scan)
 {
-	struct cpuset *cs = cgroup_cs(scan->cg);
+	struct cpuset *cs = cgroup_cs(scan->cgrp);
 	struct mm_struct *mm;
 	int migrate;
 	nodemask_t *newmems = scan->data;
@@ -1103,7 +1102,7 @@ static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
 
 	guarantee_online_mems(mems_cs, &newmems);
 
-	scan.cg = cs->css.cgroup;
+	scan.cgrp = cs->css.cgroup;
 	scan.test_task = NULL;
 	scan.process_task = cpuset_change_nodemask;
 	scan.heap = heap;
@@ -1276,7 +1275,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
 static void cpuset_change_flag(struct task_struct *tsk,
 				struct cgroup_scanner *scan)
 {
-	cpuset_update_task_spread_flag(cgroup_cs(scan->cg), tsk);
+	cpuset_update_task_spread_flag(cgroup_cs(scan->cgrp), tsk);
 }
 
 /*
@@ -1296,7 +1295,7 @@ static void update_tasks_flags(struct cpuset *cs, struct ptr_heap *heap)
 {
 	struct cgroup_scanner scan;
 
-	scan.cg = cs->css.cgroup;
+	scan.cgrp = cs->css.cgroup;
 	scan.test_task = NULL;
 	scan.process_task = cpuset_change_flag;
 	scan.heap = heap;
@@ -1972,7 +1971,7 @@ static int cpuset_css_online(struct cgroup *cgrp)
 	struct cpuset *cs = cgroup_cs(cgrp);
 	struct cpuset *parent = parent_cs(cs);
 	struct cpuset *tmp_cs;
-	struct cgroup *pos_cg;
+	struct cgroup *pos_cgrp;
 
 	if (!parent)
 		return 0;
@@ -2004,7 +2003,7 @@ static int cpuset_css_online(struct cgroup *cgrp)
 	 * (and likewise for mems) to the new cgroup.
 	 */
 	rcu_read_lock();
-	cpuset_for_each_child(tmp_cs, pos_cg, parent) {
+	cpuset_for_each_child(tmp_cs, pos_cgrp, parent) {
 		if (is_mem_exclusive(tmp_cs) || is_cpu_exclusive(tmp_cs)) {
 			rcu_read_unlock();
 			goto out_unlock;
@@ -2021,6 +2020,12 @@ out_unlock:
 	return 0;
 }
 
+/*
+ * If the cpuset being removed has its flag 'sched_load_balance'
+ * enabled, then simulate turning sched_load_balance off, which
+ * will call rebuild_sched_domains_locked().
+ */
+
 static void cpuset_css_offline(struct cgroup *cgrp)
 {
 	struct cpuset *cs = cgroup_cs(cgrp);
@@ -2036,12 +2041,6 @@ static void cpuset_css_offline(struct cgroup *cgrp)
 	mutex_unlock(&cpuset_mutex);
 }
 
-/*
- * If the cpuset being removed has its flag 'sched_load_balance'
- * enabled, then simulate turning sched_load_balance off, which
- * will call rebuild_sched_domains_locked().
- */
-
 static void cpuset_css_free(struct cgroup *cgrp)
 {
 	struct cpuset *cs = cgroup_cs(cgrp);
diff --git a/kernel/elfcore.c b/kernel/elfcore.c
index ff915ef..30c0d91 100644
--- a/kernel/elfcore.c
+++ b/kernel/elfcore.c
@@ -10,14 +10,12 @@ Elf_Half __weak elf_core_extra_phdrs(void)
 	return 0;
 }
 
-int __weak elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-				      unsigned long limit)
+int __weak elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
 {
 	return 1;
 }
 
-int __weak elf_core_write_extra_data(struct file *file, size_t *size,
-				     unsigned long limit)
+int __weak elf_core_write_extra_data(struct coredump_params *cprm)
 {
 	return 1;
 }
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index c772061..76a8bc5 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -117,6 +117,8 @@ int get_callchain_buffers(void)
 	err = alloc_callchain_buffers();
 exit:
 	mutex_unlock(&callchain_mutex);
+	if (err)
+		atomic_dec(&nr_callchain_events);
 
 	return err;
 }
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f86599e..916cf1f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -141,6 +141,7 @@ enum event_type_t {
 struct static_key_deferred perf_sched_events __read_mostly;
 static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
 static DEFINE_PER_CPU(atomic_t, perf_branch_stack_events);
+static DEFINE_PER_CPU(atomic_t, perf_freq_events);
 
 static atomic_t nr_mmap_events __read_mostly;
 static atomic_t nr_comm_events __read_mostly;
@@ -869,12 +870,8 @@ static void perf_pmu_rotate_start(struct pmu *pmu)
 
 	WARN_ON(!irqs_disabled());
 
-	if (list_empty(&cpuctx->rotation_list)) {
-		int was_empty = list_empty(head);
+	if (list_empty(&cpuctx->rotation_list))
 		list_add(&cpuctx->rotation_list, head);
-		if (was_empty)
-			tick_nohz_full_kick();
-	}
 }
 
 static void get_ctx(struct perf_event_context *ctx)
@@ -1874,6 +1871,9 @@ static int  __perf_install_in_context(void *info)
 	perf_pmu_enable(cpuctx->ctx.pmu);
 	perf_ctx_unlock(cpuctx, task_ctx);
 
+	if (atomic_read(&__get_cpu_var(perf_freq_events)))
+		tick_nohz_full_kick();
+
 	return 0;
 }
 
@@ -2811,10 +2811,11 @@ done:
 #ifdef CONFIG_NO_HZ_FULL
 bool perf_event_can_stop_tick(void)
 {
-	if (list_empty(&__get_cpu_var(rotation_list)))
-		return true;
-	else
+	if (atomic_read(&__get_cpu_var(perf_freq_events)) ||
+	    __this_cpu_read(perf_throttled_count))
 		return false;
+	else
+		return true;
 }
 #endif
 
@@ -3128,36 +3129,64 @@ static void free_event_rcu(struct rcu_head *head)
 static void ring_buffer_put(struct ring_buffer *rb);
 static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb);
 
-static void free_event(struct perf_event *event)
+static void unaccount_event_cpu(struct perf_event *event, int cpu)
 {
-	irq_work_sync(&event->pending);
+	if (event->parent)
+		return;
 
+	if (has_branch_stack(event)) {
+		if (!(event->attach_state & PERF_ATTACH_TASK))
+			atomic_dec(&per_cpu(perf_branch_stack_events, cpu));
+	}
+	if (is_cgroup_event(event))
+		atomic_dec(&per_cpu(perf_cgroup_events, cpu));
+
+	if (event->attr.freq)
+		atomic_dec(&per_cpu(perf_freq_events, cpu));
+}
+
+static void unaccount_event(struct perf_event *event)
+{
+	if (event->parent)
+		return;
+
+	if (event->attach_state & PERF_ATTACH_TASK)
+		static_key_slow_dec_deferred(&perf_sched_events);
+	if (event->attr.mmap || event->attr.mmap_data)
+		atomic_dec(&nr_mmap_events);
+	if (event->attr.comm)
+		atomic_dec(&nr_comm_events);
+	if (event->attr.task)
+		atomic_dec(&nr_task_events);
+	if (is_cgroup_event(event))
+		static_key_slow_dec_deferred(&perf_sched_events);
+	if (has_branch_stack(event))
+		static_key_slow_dec_deferred(&perf_sched_events);
+
+	unaccount_event_cpu(event, event->cpu);
+}
+
+static void __free_event(struct perf_event *event)
+{
 	if (!event->parent) {
-		if (event->attach_state & PERF_ATTACH_TASK)
-			static_key_slow_dec_deferred(&perf_sched_events);
-		if (event->attr.mmap || event->attr.mmap_data)
-			atomic_dec(&nr_mmap_events);
-		if (event->attr.comm)
-			atomic_dec(&nr_comm_events);
-		if (event->attr.task)
-			atomic_dec(&nr_task_events);
 		if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
 			put_callchain_buffers();
-		if (is_cgroup_event(event)) {
-			atomic_dec(&per_cpu(perf_cgroup_events, event->cpu));
-			static_key_slow_dec_deferred(&perf_sched_events);
-		}
-
-		if (has_branch_stack(event)) {
-			static_key_slow_dec_deferred(&perf_sched_events);
-			/* is system-wide event */
-			if (!(event->attach_state & PERF_ATTACH_TASK)) {
-				atomic_dec(&per_cpu(perf_branch_stack_events,
-						    event->cpu));
-			}
-		}
 	}
 
+	if (event->destroy)
+		event->destroy(event);
+
+	if (event->ctx)
+		put_ctx(event->ctx);
+
+	call_rcu(&event->rcu_head, free_event_rcu);
+}
+static void free_event(struct perf_event *event)
+{
+	irq_work_sync(&event->pending);
+
+	unaccount_event(event);
+
 	if (event->rb) {
 		struct ring_buffer *rb;
 
@@ -3180,13 +3209,8 @@ static void free_event(struct perf_event *event)
 	if (is_cgroup_event(event))
 		perf_detach_cgroup(event);
 
-	if (event->destroy)
-		event->destroy(event);
-
-	if (event->ctx)
-		put_ctx(event->ctx);
 
-	call_rcu(&event->rcu_head, free_event_rcu);
+	__free_event(event);
 }
 
 int perf_event_release_kernel(struct perf_event *event)
@@ -4462,20 +4486,6 @@ void perf_output_sample(struct perf_output_handle *handle,
 		}
 	}
 
-	if (!event->attr.watermark) {
-		int wakeup_events = event->attr.wakeup_events;
-
-		if (wakeup_events) {
-			struct ring_buffer *rb = handle->rb;
-			int events = local_inc_return(&rb->events);
-
-			if (events >= wakeup_events) {
-				local_sub(wakeup_events, &rb->events);
-				local_inc(&rb->wakeup);
-			}
-		}
-	}
-
 	if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
 		if (data->br_stack) {
 			size_t size;
@@ -4511,16 +4521,31 @@ void perf_output_sample(struct perf_output_handle *handle,
 		}
 	}
 
-	if (sample_type & PERF_SAMPLE_STACK_USER)
+	if (sample_type & PERF_SAMPLE_STACK_USER) {
 		perf_output_sample_ustack(handle,
 					  data->stack_user_size,
 					  data->regs_user.regs);
+	}
 
 	if (sample_type & PERF_SAMPLE_WEIGHT)
 		perf_output_put(handle, data->weight);
 
 	if (sample_type & PERF_SAMPLE_DATA_SRC)
 		perf_output_put(handle, data->data_src.val);
+
+	if (!event->attr.watermark) {
+		int wakeup_events = event->attr.wakeup_events;
+
+		if (wakeup_events) {
+			struct ring_buffer *rb = handle->rb;
+			int events = local_inc_return(&rb->events);
+
+			if (events >= wakeup_events) {
+				local_sub(wakeup_events, &rb->events);
+				local_inc(&rb->wakeup);
+			}
+		}
+	}
 }
 
 void perf_prepare_sample(struct perf_event_header *header,
@@ -4680,12 +4705,10 @@ perf_event_read_event(struct perf_event *event,
 	perf_output_end(&handle);
 }
 
-typedef int  (perf_event_aux_match_cb)(struct perf_event *event, void *data);
 typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data);
 
 static void
 perf_event_aux_ctx(struct perf_event_context *ctx,
-		   perf_event_aux_match_cb match,
 		   perf_event_aux_output_cb output,
 		   void *data)
 {
@@ -4696,15 +4719,12 @@ perf_event_aux_ctx(struct perf_event_context *ctx,
 			continue;
 		if (!event_filter_match(event))
 			continue;
-		if (match(event, data))
-			output(event, data);
+		output(event, data);
 	}
 }
 
 static void
-perf_event_aux(perf_event_aux_match_cb match,
-	       perf_event_aux_output_cb output,
-	       void *data,
+perf_event_aux(perf_event_aux_output_cb output, void *data,
 	       struct perf_event_context *task_ctx)
 {
 	struct perf_cpu_context *cpuctx;
@@ -4717,7 +4737,7 @@ perf_event_aux(perf_event_aux_match_cb match,
 		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
 		if (cpuctx->unique_pmu != pmu)
 			goto next;
-		perf_event_aux_ctx(&cpuctx->ctx, match, output, data);
+		perf_event_aux_ctx(&cpuctx->ctx, output, data);
 		if (task_ctx)
 			goto next;
 		ctxn = pmu->task_ctx_nr;
@@ -4725,14 +4745,14 @@ perf_event_aux(perf_event_aux_match_cb match,
 			goto next;
 		ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
 		if (ctx)
-			perf_event_aux_ctx(ctx, match, output, data);
+			perf_event_aux_ctx(ctx, output, data);
 next:
 		put_cpu_ptr(pmu->pmu_cpu_context);
 	}
 
 	if (task_ctx) {
 		preempt_disable();
-		perf_event_aux_ctx(task_ctx, match, output, data);
+		perf_event_aux_ctx(task_ctx, output, data);
 		preempt_enable();
 	}
 	rcu_read_unlock();
@@ -4759,6 +4779,12 @@ struct perf_task_event {
 	} event_id;
 };
 
+static int perf_event_task_match(struct perf_event *event)
+{
+	return event->attr.comm || event->attr.mmap ||
+	       event->attr.mmap_data || event->attr.task;
+}
+
 static void perf_event_task_output(struct perf_event *event,
 				   void *data)
 {
@@ -4768,6 +4794,9 @@ static void perf_event_task_output(struct perf_event *event,
 	struct task_struct *task = task_event->task;
 	int ret, size = task_event->event_id.header.size;
 
+	if (!perf_event_task_match(event))
+		return;
+
 	perf_event_header__init_id(&task_event->event_id.header, &sample, event);
 
 	ret = perf_output_begin(&handle, event,
@@ -4790,13 +4819,6 @@ out:
 	task_event->event_id.header.size = size;
 }
 
-static int perf_event_task_match(struct perf_event *event,
-				 void *data __maybe_unused)
-{
-	return event->attr.comm || event->attr.mmap ||
-	       event->attr.mmap_data || event->attr.task;
-}
-
 static void perf_event_task(struct task_struct *task,
 			      struct perf_event_context *task_ctx,
 			      int new)
@@ -4825,8 +4847,7 @@ static void perf_event_task(struct task_struct *task,
 		},
 	};
 
-	perf_event_aux(perf_event_task_match,
-		       perf_event_task_output,
+	perf_event_aux(perf_event_task_output,
 		       &task_event,
 		       task_ctx);
 }
@@ -4853,6 +4874,11 @@ struct perf_comm_event {
 	} event_id;
 };
 
+static int perf_event_comm_match(struct perf_event *event)
+{
+	return event->attr.comm;
+}
+
 static void perf_event_comm_output(struct perf_event *event,
 				   void *data)
 {
@@ -4862,6 +4888,9 @@ static void perf_event_comm_output(struct perf_event *event,
 	int size = comm_event->event_id.header.size;
 	int ret;
 
+	if (!perf_event_comm_match(event))
+		return;
+
 	perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, event,
 				comm_event->event_id.header.size);
@@ -4883,12 +4912,6 @@ out:
 	comm_event->event_id.header.size = size;
 }
 
-static int perf_event_comm_match(struct perf_event *event,
-				 void *data __maybe_unused)
-{
-	return event->attr.comm;
-}
-
 static void perf_event_comm_event(struct perf_comm_event *comm_event)
 {
 	char comm[TASK_COMM_LEN];
@@ -4903,8 +4926,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
 
 	comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
 
-	perf_event_aux(perf_event_comm_match,
-		       perf_event_comm_output,
+	perf_event_aux(perf_event_comm_output,
 		       comm_event,
 		       NULL);
 }
@@ -4967,6 +4989,17 @@ struct perf_mmap_event {
 	} event_id;
 };
 
+static int perf_event_mmap_match(struct perf_event *event,
+				 void *data)
+{
+	struct perf_mmap_event *mmap_event = data;
+	struct vm_area_struct *vma = mmap_event->vma;
+	int executable = vma->vm_flags & VM_EXEC;
+
+	return (!executable && event->attr.mmap_data) ||
+	       (executable && event->attr.mmap);
+}
+
 static void perf_event_mmap_output(struct perf_event *event,
 				   void *data)
 {
@@ -4976,6 +5009,9 @@ static void perf_event_mmap_output(struct perf_event *event,
 	int size = mmap_event->event_id.header.size;
 	int ret;
 
+	if (!perf_event_mmap_match(event, data))
+		return;
+
 	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, event,
 				mmap_event->event_id.header.size);
@@ -4996,17 +5032,6 @@ out:
 	mmap_event->event_id.header.size = size;
 }
 
-static int perf_event_mmap_match(struct perf_event *event,
-				 void *data)
-{
-	struct perf_mmap_event *mmap_event = data;
-	struct vm_area_struct *vma = mmap_event->vma;
-	int executable = vma->vm_flags & VM_EXEC;
-
-	return (!executable && event->attr.mmap_data) ||
-	       (executable && event->attr.mmap);
-}
-
 static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 {
 	struct vm_area_struct *vma = mmap_event->vma;
@@ -5070,8 +5095,7 @@ got_name:
 
 	mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
 
-	perf_event_aux(perf_event_mmap_match,
-		       perf_event_mmap_output,
+	perf_event_aux(perf_event_mmap_output,
 		       mmap_event,
 		       NULL);
 
@@ -5178,6 +5202,7 @@ static int __perf_event_overflow(struct perf_event *event,
 			__this_cpu_inc(perf_throttled_count);
 			hwc->interrupts = MAX_INTERRUPTS;
 			perf_log_throttle(event, 0);
+			tick_nohz_full_kick();
 			ret = 1;
 		}
 	}
@@ -6443,6 +6468,43 @@ unlock:
 	return pmu;
 }
 
+static void account_event_cpu(struct perf_event *event, int cpu)
+{
+	if (event->parent)
+		return;
+
+	if (has_branch_stack(event)) {
+		if (!(event->attach_state & PERF_ATTACH_TASK))
+			atomic_inc(&per_cpu(perf_branch_stack_events, cpu));
+	}
+	if (is_cgroup_event(event))
+		atomic_inc(&per_cpu(perf_cgroup_events, cpu));
+
+	if (event->attr.freq)
+		atomic_inc(&per_cpu(perf_freq_events, cpu));
+}
+
+static void account_event(struct perf_event *event)
+{
+	if (event->parent)
+		return;
+
+	if (event->attach_state & PERF_ATTACH_TASK)
+		static_key_slow_inc(&perf_sched_events.key);
+	if (event->attr.mmap || event->attr.mmap_data)
+		atomic_inc(&nr_mmap_events);
+	if (event->attr.comm)
+		atomic_inc(&nr_comm_events);
+	if (event->attr.task)
+		atomic_inc(&nr_task_events);
+	if (has_branch_stack(event))
+		static_key_slow_inc(&perf_sched_events.key);
+	if (is_cgroup_event(event))
+		static_key_slow_inc(&perf_sched_events.key);
+
+	account_event_cpu(event, event->cpu);
+}
+
 /*
  * Allocate and initialize a event structure
  */
@@ -6457,7 +6519,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 	struct pmu *pmu;
 	struct perf_event *event;
 	struct hw_perf_event *hwc;
-	long err;
+	long err = -EINVAL;
 
 	if ((unsigned)cpu >= nr_cpu_ids) {
 		if (!task || cpu != -1)
@@ -6540,49 +6602,35 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 	 * we currently do not support PERF_FORMAT_GROUP on inherited events
 	 */
 	if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
-		goto done;
+		goto err_ns;
 
 	pmu = perf_init_event(event);
-
-done:
-	err = 0;
 	if (!pmu)
-		err = -EINVAL;
-	else if (IS_ERR(pmu))
+		goto err_ns;
+	else if (IS_ERR(pmu)) {
 		err = PTR_ERR(pmu);
-
-	if (err) {
-		if (event->ns)
-			put_pid_ns(event->ns);
-		kfree(event);
-		return ERR_PTR(err);
+		goto err_ns;
 	}
 
 	if (!event->parent) {
-		if (event->attach_state & PERF_ATTACH_TASK)
-			static_key_slow_inc(&perf_sched_events.key);
-		if (event->attr.mmap || event->attr.mmap_data)
-			atomic_inc(&nr_mmap_events);
-		if (event->attr.comm)
-			atomic_inc(&nr_comm_events);
-		if (event->attr.task)
-			atomic_inc(&nr_task_events);
 		if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
 			err = get_callchain_buffers();
-			if (err) {
-				free_event(event);
-				return ERR_PTR(err);
-			}
-		}
-		if (has_branch_stack(event)) {
-			static_key_slow_inc(&perf_sched_events.key);
-			if (!(event->attach_state & PERF_ATTACH_TASK))
-				atomic_inc(&per_cpu(perf_branch_stack_events,
-						    event->cpu));
+			if (err)
+				goto err_pmu;
 		}
 	}
 
 	return event;
+
+err_pmu:
+	if (event->destroy)
+		event->destroy(event);
+err_ns:
+	if (event->ns)
+		put_pid_ns(event->ns);
+	kfree(event);
+
+	return ERR_PTR(err);
 }
 
 static int perf_copy_attr(struct perf_event_attr __user *uattr,
@@ -6864,17 +6912,14 @@ SYSCALL_DEFINE5(perf_event_open,
 
 	if (flags & PERF_FLAG_PID_CGROUP) {
 		err = perf_cgroup_connect(pid, event, &attr, group_leader);
-		if (err)
-			goto err_alloc;
-		/*
-		 * one more event:
-		 * - that has cgroup constraint on event->cpu
-		 * - that may need work on context switch
-		 */
-		atomic_inc(&per_cpu(perf_cgroup_events, event->cpu));
-		static_key_slow_inc(&perf_sched_events.key);
+		if (err) {
+			__free_event(event);
+			goto err_task;
+		}
 	}
 
+	account_event(event);
+
 	/*
 	 * Special case software events and allow them to be part of
 	 * any hardware group.
@@ -7070,6 +7115,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 		goto err;
 	}
 
+	account_event(event);
+
 	ctx = find_get_context(event->pmu, task, cpu);
 	if (IS_ERR(ctx)) {
 		err = PTR_ERR(ctx);
@@ -7106,6 +7153,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
 	list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
 				 event_entry) {
 		perf_remove_from_context(event);
+		unaccount_event_cpu(event, src_cpu);
 		put_ctx(src_ctx);
 		list_add(&event->event_entry, &events);
 	}
@@ -7118,6 +7166,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
 		list_del(&event->event_entry);
 		if (event->state >= PERF_EVENT_STATE_OFF)
 			event->state = PERF_EVENT_STATE_INACTIVE;
+		account_event_cpu(event, dst_cpu);
 		perf_install_in_context(dst_ctx, event, dst_cpu);
 		get_ctx(dst_ctx);
 	}
diff --git a/kernel/fork.c b/kernel/fork.c
index 403d2bb..9538df5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -351,7 +351,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 	struct rb_node **rb_link, *rb_parent;
 	int retval;
 	unsigned long charge;
-	struct mempolicy *pol;
 
 	uprobe_start_dup_mmap();
 	down_write(&oldmm->mmap_sem);
@@ -400,11 +399,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 			goto fail_nomem;
 		*tmp = *mpnt;
 		INIT_LIST_HEAD(&tmp->anon_vma_chain);
-		pol = mpol_dup(vma_policy(mpnt));
-		retval = PTR_ERR(pol);
-		if (IS_ERR(pol))
+		retval = vma_dup_policy(mpnt, tmp);
+		if (retval)
 			goto fail_nomem_policy;
-		vma_set_policy(tmp, pol);
 		tmp->vm_mm = mm;
 		if (anon_vma_fork(tmp, mpnt))
 			goto fail_nomem_anon_vma_fork;
@@ -472,7 +469,7 @@ out:
 	uprobe_end_dup_mmap();
 	return retval;
 fail_nomem_anon_vma_fork:
-	mpol_put(pol);
+	mpol_put(vma_policy(tmp));
 fail_nomem_policy:
 	kmem_cache_free(vm_area_cachep, tmp);
 fail_nomem:
@@ -522,7 +519,7 @@ static void mm_init_aio(struct mm_struct *mm)
 {
 #ifdef CONFIG_AIO
 	spin_lock_init(&mm->ioctx_lock);
-	INIT_HLIST_HEAD(&mm->ioctx_list);
+	mm->ioctx_table = NULL;
 #endif
 }
 
@@ -1679,6 +1676,12 @@ SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
 		 int __user *, parent_tidptr,
 		 int __user *, child_tidptr,
 		 int, tls_val)
+#elif defined(CONFIG_CLONE_BACKWARDS3)
+SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp,
+		int, stack_size,
+		int __user *, parent_tidptr,
+		int __user *, child_tidptr,
+		int, tls_val)
 #else
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 		 int __user *, parent_tidptr,
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index 9bd0934..7a7d2ee 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -74,7 +74,7 @@ static int __init gcov_persist_setup(char *str)
 {
 	unsigned long val;
 
-	if (strict_strtoul(str, 0, &val)) {
+	if (kstrtoul(str, 0, &val)) {
 		pr_warning("invalid gcov_persist parameter '%s'\n", str);
 		return 0;
 	}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 383319b..deb3ad9 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1399,6 +1399,8 @@ retry:
 		expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC);
 	else
 		expires_next = ktime_add(now, delta);
+	if (expires_next.tv64 < 0)
+		expires_next.tv64 = KTIME_MAX;
 	tick_program_event(expires_next, 1);
 	printk_once(KERN_WARNING "hrtimer: interrupt took %llu ns\n",
 		    ktime_to_ns(delta));
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 6df6149..3e97fb1 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -15,6 +15,7 @@
 #include <linux/lockdep.h>
 #include <linux/export.h>
 #include <linux/sysctl.h>
+#include <linux/utsname.h>
 
 /*
  * The number of tasks checked:
@@ -99,10 +100,14 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 	 * Ok, the task did not get scheduled for more than 2 minutes,
 	 * complain:
 	 */
-	printk(KERN_ERR "INFO: task %s:%d blocked for more than "
-			"%ld seconds.\n", t->comm, t->pid, timeout);
-	printk(KERN_ERR "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
-			" disables this message.\n");
+	pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
+		t->comm, t->pid, timeout);
+	pr_err("      %s %s %.*s\n",
+		print_tainted(), init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
+	pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
+		" disables this message.\n");
 	sched_show_task(t);
 	debug_show_held_locks(t);
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 706724e..6d066e2 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -23,7 +23,7 @@ static DEFINE_MUTEX(revmap_trees_mutex);
 static struct irq_domain *irq_default_domain;
 
 /**
- * __irq_domain_add() - Allocate a new irq_domain data structure
+ * __irq_domain_alloc() - Allocate a new irq_domain data structure
  * @of_node: optional device-tree node of the interrupt controller
  * @size: Size of linear map; 0 for radix mapping only
  * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no
@@ -31,14 +31,15 @@ static struct irq_domain *irq_default_domain;
  * @ops: map/unmap domain callbacks
  * @host_data: Controller private data pointer
  *
- * Allocates and initialize and irq_domain structure.  Caller is expected to
- * register allocated irq_domain with irq_domain_register().  Returns pointer
- * to IRQ domain, or NULL on failure.
+ * Allocates and initializes an irq_domain structure.  Caller is
+ * expected to register the allocated irq_domain with
+ * __irq_domain_register().  Returns pointer to IRQ domain, or NULL on
+ * failure.
  */
-struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
-				    irq_hw_number_t hwirq_max, int direct_max,
-				    const struct irq_domain_ops *ops,
-				    void *host_data)
+struct irq_domain *__irq_domain_alloc(struct device_node *of_node, int size,
+				      irq_hw_number_t hwirq_max, int direct_max,
+				      const struct irq_domain_ops *ops,
+				      void *host_data)
 {
 	struct irq_domain *domain;
 
@@ -56,14 +57,24 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
 
+	return domain;
+}
+EXPORT_SYMBOL_GPL(__irq_domain_alloc);
+
+/**
+ * __irq_domain_register() - Register a new irq_domain that has been
+ * previously allocated with __irq_domain_alloc().
+ * @domain: irq_domain to registers
+ */
+void __irq_domain_register(struct irq_domain *domain)
+{
 	mutex_lock(&irq_domain_mutex);
 	list_add(&domain->link, &irq_domain_list);
 	mutex_unlock(&irq_domain_mutex);
 
 	pr_debug("Added domain %s\n", domain->name);
-	return domain;
 }
-EXPORT_SYMBOL_GPL(__irq_domain_add);
+EXPORT_SYMBOL_GPL(__irq_domain_register);
 
 /**
  * irq_domain_remove() - Remove an irq domain.
@@ -127,7 +138,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
+	domain = __irq_domain_alloc(of_node, size, size, 0, ops, host_data);
 	if (!domain)
 		return NULL;
 
@@ -143,6 +154,8 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
 		irq_domain_associate_many(domain, first_irq, 0, size);
 	}
 
+	__irq_domain_register(domain);
+
 	return domain;
 }
 EXPORT_SYMBOL_GPL(irq_domain_add_simple);
@@ -171,22 +184,27 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 {
 	struct irq_domain *domain;
 
-	domain = __irq_domain_add(of_node, first_hwirq + size,
-				  first_hwirq + size, 0, ops, host_data);
+	domain = __irq_domain_alloc(of_node, first_hwirq + size,
+				    first_hwirq + size, 0, ops, host_data);
 	if (!domain)
 		return NULL;
 
 	irq_domain_associate_many(domain, first_irq, first_hwirq, size);
+	__irq_domain_register(domain);
 
 	return domain;
 }
 EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
 
 /**
- * irq_find_host() - Locates a domain for a given device node
+ * __irq_find_host() - Locates a domain for a given device node,
+ * taking into account whether the domain is of MSI-type or not.
  * @node: device-tree node of the interrupt controller
+ * @findmsi: true when the domain being search is of MSI-type, false
+ * otherwise.
  */
-struct irq_domain *irq_find_host(struct device_node *node)
+struct irq_domain *__irq_find_host(struct device_node *node,
+				   bool findmsi)
 {
 	struct irq_domain *h, *found = NULL;
 	int rc;
@@ -198,6 +216,9 @@ struct irq_domain *irq_find_host(struct device_node *node)
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
+		if ((findmsi && !h->msi_chip) ||
+		    (!findmsi && h->msi_chip))
+			continue;
 		if (h->ops->match)
 			rc = h->ops->match(h, node);
 		else
@@ -211,7 +232,7 @@ struct irq_domain *irq_find_host(struct device_node *node)
 	mutex_unlock(&irq_domain_mutex);
 	return found;
 }
-EXPORT_SYMBOL_GPL(irq_find_host);
+EXPORT_SYMBOL_GPL(__irq_find_host);
 
 /**
  * irq_set_default_host() - Set a "default" irq domain
@@ -375,6 +396,42 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
 
 /**
+ * irq_alloc_mapping() - Allocate an irq for mapping
+ * @domain: domain to allocate the irq for or NULL for default domain
+ * @hwirq:  reference to the returned hwirq
+ *
+ * This routine are used for irq controllers which can choose the
+ * hardware interrupt number from a range [ 0 ; domain size ], such as
+ * is often the case with PCI MSI controllers. The function will
+ * returned the allocated hwirq number in the hwirq pointer, and the
+ * corresponding virq number as the return value.
+ */
+unsigned int irq_alloc_mapping(struct irq_domain *domain,
+			       irq_hw_number_t *out_hwirq)
+{
+	irq_hw_number_t hwirq;
+	int rc;
+
+	pr_debug("irq_alloc_mapping(0x%p)\n", domain);
+
+	for (hwirq = 0; hwirq < domain->revmap_size; hwirq++)
+		if (domain->linear_revmap[hwirq] == 0)
+			break;
+
+	if (hwirq == domain->hwirq_max) {
+		pr_debug("-> no available hwirq found\n");
+		return 0;
+	}
+
+	rc = irq_create_mapping(domain, hwirq);
+	if (rc)
+		*out_hwirq = hwirq;
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(irq_alloc_mapping);
+
+/**
  * irq_create_mapping() - Map a hardware interrupt into linux irq space
  * @domain: domain owning this hardware interrupt or NULL for default domain
  * @hwirq: hardware irq number in that domain space
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 59f7b55..2a74f30 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1474,11 +1474,8 @@ static int __init __parse_crashkernel(char *cmdline,
 	if (first_colon && (!first_space || first_colon < first_space))
 		return parse_crashkernel_mem(ck_cmdline, system_ram,
 				crash_size, crash_base);
-	else
-		return parse_crashkernel_simple(ck_cmdline, crash_size,
-				crash_base);
 
-	return 0;
+	return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
 }
 
 /*
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 6ada93c..9659d38 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -113,7 +113,7 @@ static ssize_t kexec_crash_size_store(struct kobject *kobj,
 	unsigned long cnt;
 	int ret;
 
-	if (strict_strtoul(buf, 0, &cnt))
+	if (kstrtoul(buf, 0, &cnt))
 		return -EINVAL;
 
 	ret = crash_shrink_memory(cnt);
diff --git a/kernel/lglock.c b/kernel/lglock.c
index 6535a66..86ae2ae 100644
--- a/kernel/lglock.c
+++ b/kernel/lglock.c
@@ -21,7 +21,7 @@ void lg_local_lock(struct lglock *lg)
 	arch_spinlock_t *lock;
 
 	preempt_disable();
-	rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
 	lock = this_cpu_ptr(lg->lock);
 	arch_spin_lock(lock);
 }
@@ -31,7 +31,7 @@ void lg_local_unlock(struct lglock *lg)
 {
 	arch_spinlock_t *lock;
 
-	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock_release(&lg->lock_dep_map, 1, _RET_IP_);
 	lock = this_cpu_ptr(lg->lock);
 	arch_spin_unlock(lock);
 	preempt_enable();
@@ -43,7 +43,7 @@ void lg_local_lock_cpu(struct lglock *lg, int cpu)
 	arch_spinlock_t *lock;
 
 	preempt_disable();
-	rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
 	lock = per_cpu_ptr(lg->lock, cpu);
 	arch_spin_lock(lock);
 }
@@ -53,7 +53,7 @@ void lg_local_unlock_cpu(struct lglock *lg, int cpu)
 {
 	arch_spinlock_t *lock;
 
-	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock_release(&lg->lock_dep_map, 1, _RET_IP_);
 	lock = per_cpu_ptr(lg->lock, cpu);
 	arch_spin_unlock(lock);
 	preempt_enable();
@@ -65,7 +65,7 @@ void lg_global_lock(struct lglock *lg)
 	int i;
 
 	preempt_disable();
-	rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	lock_acquire_exclusive(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
 	for_each_possible_cpu(i) {
 		arch_spinlock_t *lock;
 		lock = per_cpu_ptr(lg->lock, i);
@@ -78,7 +78,7 @@ void lg_global_unlock(struct lglock *lg)
 {
 	int i;
 
-	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock_release(&lg->lock_dep_map, 1, _RET_IP_);
 	for_each_possible_cpu(i) {
 		arch_spinlock_t *lock;
 		lock = per_cpu_ptr(lg->lock, i);
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
index 2b6e699..7cbd450 100644
--- a/kernel/modsign_pubkey.c
+++ b/kernel/modsign_pubkey.c
@@ -18,14 +18,14 @@
 
 struct key *modsign_keyring;
 
-extern __initdata const u8 modsign_certificate_list[];
-extern __initdata const u8 modsign_certificate_list_end[];
+extern __initconst const u8 modsign_certificate_list[];
+extern __initconst const u8 modsign_certificate_list_end[];
 
 /*
  * We need to make sure ccache doesn't cache the .o file as it doesn't notice
  * if modsign.pub changes.
  */
-static __initdata const char annoy_ccache[] = __TIME__ "foo";
+static __initconst const char annoy_ccache[] = __TIME__ "foo";
 
 /*
  * Load the compiled-in keys
diff --git a/kernel/mutex.c b/kernel/mutex.c
index ff05f4b..6d647ae 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -209,11 +209,13 @@ int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
  */
 static inline int mutex_can_spin_on_owner(struct mutex *lock)
 {
+	struct task_struct *owner;
 	int retval = 1;
 
 	rcu_read_lock();
-	if (lock->owner)
-		retval = lock->owner->on_cpu;
+	owner = ACCESS_ONCE(lock->owner);
+	if (owner)
+		retval = owner->on_cpu;
 	rcu_read_unlock();
 	/*
 	 * if lock->owner is not set, the mutex owner may have just acquired
@@ -461,7 +463,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
 			 * performed the optimistic spinning cannot be done.
 			 */
 			if (ACCESS_ONCE(ww->ctx))
-				break;
+				goto slowpath;
 		}
 
 		/*
@@ -472,7 +474,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
 		owner = ACCESS_ONCE(lock->owner);
 		if (owner && !mutex_spin_on_owner(lock, owner)) {
 			mspin_unlock(MLOCK(lock), &node);
-			break;
+			goto slowpath;
 		}
 
 		if ((atomic_read(&lock->count) == 1) &&
@@ -499,7 +501,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
 		 * the owner complete.
 		 */
 		if (!owner && (need_resched() || rt_task(task)))
-			break;
+			goto slowpath;
 
 		/*
 		 * The cpu_relax() call is a compiler barrier which forces
@@ -513,6 +515,10 @@ slowpath:
 #endif
 	spin_lock_mutex(&lock->wait_lock, flags);
 
+	/* once more, can we acquire the lock? */
+	if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, 0) == 1))
+		goto skip_wait;
+
 	debug_mutex_lock_common(lock, &waiter);
 	debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
 
@@ -520,9 +526,6 @@ slowpath:
 	list_add_tail(&waiter.list, &lock->wait_list);
 	waiter.task = task;
 
-	if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, -1) == 1))
-		goto done;
-
 	lock_contended(&lock->dep_map, ip);
 
 	for (;;) {
@@ -536,7 +539,7 @@ slowpath:
 		 * other waiters:
 		 */
 		if (MUTEX_SHOW_NO_WAITER(lock) &&
-		   (atomic_xchg(&lock->count, -1) == 1))
+		    (atomic_xchg(&lock->count, -1) == 1))
 			break;
 
 		/*
@@ -561,24 +564,25 @@ slowpath:
 		schedule_preempt_disabled();
 		spin_lock_mutex(&lock->wait_lock, flags);
 	}
+	mutex_remove_waiter(lock, &waiter, current_thread_info());
+	/* set it to 0 if there are no waiters left: */
+	if (likely(list_empty(&lock->wait_list)))
+		atomic_set(&lock->count, 0);
+	debug_mutex_free_waiter(&waiter);
 
-done:
+skip_wait:
+	/* got the lock - cleanup and rejoice! */
 	lock_acquired(&lock->dep_map, ip);
-	/* got the lock - rejoice! */
-	mutex_remove_waiter(lock, &waiter, current_thread_info());
 	mutex_set_owner(lock);
 
 	if (!__builtin_constant_p(ww_ctx == NULL)) {
-		struct ww_mutex *ww = container_of(lock,
-						      struct ww_mutex,
-						      base);
+		struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
 		struct mutex_waiter *cur;
 
 		/*
 		 * This branch gets optimized out for the common case,
 		 * and is only important for ww_mutex_lock.
 		 */
-
 		ww_mutex_lock_acquired(ww, ww_ctx);
 		ww->ctx = ww_ctx;
 
@@ -592,15 +596,8 @@ done:
 		}
 	}
 
-	/* set it to 0 if there are no waiters left: */
-	if (likely(list_empty(&lock->wait_list)))
-		atomic_set(&lock->count, 0);
-
 	spin_unlock_mutex(&lock->wait_lock, flags);
-
-	debug_mutex_free_waiter(&waiter);
 	preempt_enable();
-
 	return 0;
 
 err:
@@ -686,7 +683,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 	might_sleep();
 	ret =  __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE,
 				   0, &ctx->dep_map, _RET_IP_, ctx);
-	if (!ret && ctx->acquired > 0)
+	if (!ret && ctx->acquired > 1)
 		return ww_mutex_deadlock_injection(lock, ctx);
 
 	return ret;
@@ -702,7 +699,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 	ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE,
 				  0, &ctx->dep_map, _RET_IP_, ctx);
 
-	if (!ret && ctx->acquired > 0)
+	if (!ret && ctx->acquired > 1)
 		return ww_mutex_deadlock_injection(lock, ctx);
 
 	return ret;
diff --git a/kernel/panic.c b/kernel/panic.c
index 8018646..b6c482c 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -123,10 +123,14 @@ void panic(const char *fmt, ...)
 	 */
 	smp_send_stop();
 
-	kmsg_dump(KMSG_DUMP_PANIC);
-
+	/*
+	 * Run any panic handlers, including those that might need to
+	 * add information to the kmsg dump output.
+	 */
 	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
 
+	kmsg_dump(KMSG_DUMP_PANIC);
+
 	bust_spinlocks(0);
 
 	if (!panic_blink)
diff --git a/kernel/params.c b/kernel/params.c
index 440e65d..1f228a3 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -252,13 +252,13 @@ int parse_args(const char *doing,
 	EXPORT_SYMBOL(param_ops_##name)
 
 
-STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul);
-STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol);
-STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul);
-STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol);
-STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, strict_strtoul);
-STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol);
-STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul);
+STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, kstrtoul);
+STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtol);
+STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, kstrtoul);
+STANDARD_PARAM_DEF(int, int, "%i", long, kstrtol);
+STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, kstrtoul);
+STANDARD_PARAM_DEF(long, long, "%li", long, kstrtol);
+STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, kstrtoul);
 
 int param_set_charp(const char *val, const struct kernel_param *kp)
 {
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index ece0422..62ee437 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -210,6 +210,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 		goto Platform_wake;
 	}
 
+	ftrace_stop();
 	error = disable_nonboot_cpus();
 	if (error || suspend_test(TEST_CPUS))
 		goto Enable_cpus;
@@ -232,6 +233,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 
  Enable_cpus:
 	enable_nonboot_cpus();
+	ftrace_start();
 
  Platform_wake:
 	if (need_suspend_ops(state) && suspend_ops->wake)
@@ -265,7 +267,6 @@ int suspend_devices_and_enter(suspend_state_t state)
 			goto Close;
 	}
 	suspend_console();
-	ftrace_stop();
 	suspend_test_start();
 	error = dpm_suspend_start(PMSG_SUSPEND);
 	if (error) {
@@ -285,7 +286,6 @@ int suspend_devices_and_enter(suspend_state_t state)
 	suspend_test_start();
 	dpm_resume_end(PMSG_RESUME);
 	suspend_test_finish("resume devices");
-	ftrace_start();
 	resume_console();
  Close:
 	if (need_suspend_ops(state) && suspend_ops->end)
diff --git a/kernel/printk/braille.c b/kernel/printk/braille.c
index b51087f..276762f 100644
--- a/kernel/printk/braille.c
+++ b/kernel/printk/braille.c
@@ -19,7 +19,8 @@ char *_braille_console_setup(char **str, char **brl_options)
 			pr_err("need port name after brl=\n");
 		else
 			*((*str)++) = 0;
-	}
+	} else
+		return NULL;
 
 	return *str;
 }
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 5b5a708..1cba1ea 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1267,8 +1267,6 @@ static void call_console_drivers(int level, const char *text, size_t len)
 
 	trace_console(text, len);
 
-	if (level >= console_loglevel && !ignore_loglevel)
-		return;
 	if (!console_drivers)
 		return;
 
@@ -1282,6 +1280,9 @@ static void call_console_drivers(int level, const char *text, size_t len)
 		if (!cpu_online(smp_processor_id()) &&
 		    !(con->flags & CON_ANYTIME))
 			continue;
+		if (level >= console_loglevel && !ignore_loglevel &&
+		    !(con->flags & CON_ALLDATA))
+			continue;
 		con->write(con, text, len);
 	}
 }
@@ -2226,6 +2227,13 @@ void register_console(struct console *newcon)
 	struct console *bcon = NULL;
 	struct console_cmdline *c;
 
+	if (console_drivers)
+		for_each_console(bcon)
+			if (WARN(bcon == newcon,
+					"console '%s%d' already registered\n",
+					bcon->name, bcon->index))
+				return;
+
 	/*
 	 * before we register a new CON_BOOT console, make sure we don't
 	 * already have a valid console
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4041f57..a146ee3 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -469,7 +469,6 @@ static int ptrace_detach(struct task_struct *child, unsigned int data)
 	/* Architecture-specific hardware disable .. */
 	ptrace_disable(child);
 	clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-	flush_ptrace_hw_breakpoint(child);
 
 	write_lock_irq(&tasklist_lock);
 	/*
diff --git a/kernel/rcu.h b/kernel/rcu.h
index 7f8e759..ad6c3f5 100644
--- a/kernel/rcu.h
+++ b/kernel/rcu.h
@@ -67,12 +67,15 @@
 
 extern struct debug_obj_descr rcuhead_debug_descr;
 
-static inline void debug_rcu_head_queue(struct rcu_head *head)
+static inline int debug_rcu_head_queue(struct rcu_head *head)
 {
-	debug_object_activate(head, &rcuhead_debug_descr);
+	int r1;
+
+	r1 = debug_object_activate(head, &rcuhead_debug_descr);
 	debug_object_active_state(head, &rcuhead_debug_descr,
 				  STATE_RCU_HEAD_READY,
 				  STATE_RCU_HEAD_QUEUED);
+	return r1;
 }
 
 static inline void debug_rcu_head_unqueue(struct rcu_head *head)
@@ -83,8 +86,9 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
 	debug_object_deactivate(head, &rcuhead_debug_descr);
 }
 #else	/* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-static inline void debug_rcu_head_queue(struct rcu_head *head)
+static inline int debug_rcu_head_queue(struct rcu_head *head)
 {
+	return 0;
 }
 
 static inline void debug_rcu_head_unqueue(struct rcu_head *head)
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index cce6ba8..7faee78 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -212,43 +212,6 @@ static inline void debug_rcu_head_free(struct rcu_head *head)
 }
 
 /*
- * fixup_init is called when:
- * - an active object is initialized
- */
-static int rcuhead_fixup_init(void *addr, enum debug_obj_state state)
-{
-	struct rcu_head *head = addr;
-
-	switch (state) {
-	case ODEBUG_STATE_ACTIVE:
-		/*
-		 * Ensure that queued callbacks are all executed.
-		 * If we detect that we are nested in a RCU read-side critical
-		 * section, we should simply fail, otherwise we would deadlock.
-		 * In !PREEMPT configurations, there is no way to tell if we are
-		 * in a RCU read-side critical section or not, so we never
-		 * attempt any fixup and just print a warning.
-		 */
-#ifndef CONFIG_PREEMPT
-		WARN_ON_ONCE(1);
-		return 0;
-#endif
-		if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
-		    irqs_disabled()) {
-			WARN_ON_ONCE(1);
-			return 0;
-		}
-		rcu_barrier();
-		rcu_barrier_sched();
-		rcu_barrier_bh();
-		debug_object_init(head, &rcuhead_debug_descr);
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/*
  * fixup_activate is called when:
  * - an active object is activated
  * - an unknown object is activated (might be a statically initialized object)
@@ -268,69 +231,8 @@ static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state)
 		debug_object_init(head, &rcuhead_debug_descr);
 		debug_object_activate(head, &rcuhead_debug_descr);
 		return 0;
-
-	case ODEBUG_STATE_ACTIVE:
-		/*
-		 * Ensure that queued callbacks are all executed.
-		 * If we detect that we are nested in a RCU read-side critical
-		 * section, we should simply fail, otherwise we would deadlock.
-		 * In !PREEMPT configurations, there is no way to tell if we are
-		 * in a RCU read-side critical section or not, so we never
-		 * attempt any fixup and just print a warning.
-		 */
-#ifndef CONFIG_PREEMPT
-		WARN_ON_ONCE(1);
-		return 0;
-#endif
-		if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
-		    irqs_disabled()) {
-			WARN_ON_ONCE(1);
-			return 0;
-		}
-		rcu_barrier();
-		rcu_barrier_sched();
-		rcu_barrier_bh();
-		debug_object_activate(head, &rcuhead_debug_descr);
-		return 1;
 	default:
-		return 0;
-	}
-}
-
-/*
- * fixup_free is called when:
- * - an active object is freed
- */
-static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)
-{
-	struct rcu_head *head = addr;
-
-	switch (state) {
-	case ODEBUG_STATE_ACTIVE:
-		/*
-		 * Ensure that queued callbacks are all executed.
-		 * If we detect that we are nested in a RCU read-side critical
-		 * section, we should simply fail, otherwise we would deadlock.
-		 * In !PREEMPT configurations, there is no way to tell if we are
-		 * in a RCU read-side critical section or not, so we never
-		 * attempt any fixup and just print a warning.
-		 */
-#ifndef CONFIG_PREEMPT
-		WARN_ON_ONCE(1);
-		return 0;
-#endif
-		if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
-		    irqs_disabled()) {
-			WARN_ON_ONCE(1);
-			return 0;
-		}
-		rcu_barrier();
-		rcu_barrier_sched();
-		rcu_barrier_bh();
-		debug_object_free(head, &rcuhead_debug_descr);
 		return 1;
-	default:
-		return 0;
 	}
 }
 
@@ -369,9 +271,7 @@ EXPORT_SYMBOL_GPL(destroy_rcu_head_on_stack);
 
 struct debug_obj_descr rcuhead_debug_descr = {
 	.name = "rcu_head",
-	.fixup_init = rcuhead_fixup_init,
 	.fixup_activate = rcuhead_fixup_activate,
-	.fixup_free = rcuhead_fixup_free,
 };
 EXPORT_SYMBOL_GPL(rcuhead_debug_descr);
 #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index f4871e5..fb3949a 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -52,72 +52,81 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
 
-static int nreaders = -1;	/* # reader threads, defaults to 2*ncpus */
-static int nfakewriters = 4;	/* # fake writer threads */
-static int stat_interval = 60;	/* Interval between stats, in seconds. */
-				/*  Zero means "only at end of test". */
-static bool verbose;		/* Print more debug info. */
-static bool test_no_idle_hz = true;
-				/* Test RCU support for tickless idle CPUs. */
-static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
-static int stutter = 5;		/* Start/stop testing interval (in sec) */
-static int irqreader = 1;	/* RCU readers from irq (timers). */
 static int fqs_duration;	/* Duration of bursts (us), 0 to disable. */
 static int fqs_holdoff;		/* Hold time within burst (us). */
 static int fqs_stutter = 3;	/* Wait time between bursts (s). */
+static bool gp_exp = 0;		/* Use expedited GP wait primitives. */
+static bool gp_normal = 0;	/* Use normal GP wait primitives. */
+static int irqreader = 1;	/* RCU readers from irq (timers). */
 static int n_barrier_cbs;	/* Number of callbacks to test RCU barriers. */
-static int onoff_interval;	/* Wait time between CPU hotplugs, 0=disable. */
+static int nfakewriters = 4;	/* # fake writer threads */
+static int nreaders = -1;	/* # reader threads, defaults to 2*ncpus */
+static int object_debug;	/* Test object-debug double call_rcu()?. */
 static int onoff_holdoff;	/* Seconds after boot before CPU hotplugs. */
+static int onoff_interval;	/* Wait time between CPU hotplugs, 0=disable. */
+static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
 static int shutdown_secs;	/* Shutdown time (s).  <=0 for no shutdown. */
 static int stall_cpu;		/* CPU-stall duration (s).  0 for no stall. */
 static int stall_cpu_holdoff = 10; /* Time to wait until stall (s).  */
+static int stat_interval = 60;	/* Interval between stats, in seconds. */
+				/*  Zero means "only at end of test". */
+static int stutter = 5;		/* Start/stop testing interval (in sec) */
 static int test_boost = 1;	/* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */
-static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
 static int test_boost_duration = 4; /* Duration of each boost test, seconds. */
+static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
+static bool test_no_idle_hz = true;
+				/* Test RCU support for tickless idle CPUs. */
 static char *torture_type = "rcu"; /* What RCU implementation to torture. */
+static bool verbose;		/* Print more debug info. */
 
-module_param(nreaders, int, 0444);
-MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
-module_param(nfakewriters, int, 0444);
-MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
-module_param(stat_interval, int, 0644);
-MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
-module_param(verbose, bool, 0444);
-MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
-module_param(test_no_idle_hz, bool, 0444);
-MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
-module_param(shuffle_interval, int, 0444);
-MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
-module_param(stutter, int, 0444);
-MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
-module_param(irqreader, int, 0444);
-MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers");
 module_param(fqs_duration, int, 0444);
 MODULE_PARM_DESC(fqs_duration, "Duration of fqs bursts (us)");
 module_param(fqs_holdoff, int, 0444);
 MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)");
 module_param(fqs_stutter, int, 0444);
 MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)");
+module_param(gp_exp, bool, 0444);
+MODULE_PARM_DESC(gp_exp, "Use expedited GP wait primitives");
+module_param(gp_normal, bool, 0444);
+MODULE_PARM_DESC(gp_normal, "Use normal (non-expedited) GP wait primitives");
+module_param(irqreader, int, 0444);
+MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers");
 module_param(n_barrier_cbs, int, 0444);
 MODULE_PARM_DESC(n_barrier_cbs, "# of callbacks/kthreads for barrier testing");
-module_param(onoff_interval, int, 0444);
-MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
+module_param(nfakewriters, int, 0444);
+MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
+module_param(nreaders, int, 0444);
+MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
+module_param(object_debug, int, 0444);
+MODULE_PARM_DESC(object_debug, "Enable debug-object double call_rcu() testing");
 module_param(onoff_holdoff, int, 0444);
 MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
+module_param(onoff_interval, int, 0444);
+MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
+module_param(shuffle_interval, int, 0444);
+MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
 module_param(shutdown_secs, int, 0444);
 MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), zero to disable.");
 module_param(stall_cpu, int, 0444);
 MODULE_PARM_DESC(stall_cpu, "Stall duration (s), zero to disable.");
 module_param(stall_cpu_holdoff, int, 0444);
 MODULE_PARM_DESC(stall_cpu_holdoff, "Time to wait before starting stall (s).");
+module_param(stat_interval, int, 0644);
+MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
+module_param(stutter, int, 0444);
+MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
 module_param(test_boost, int, 0444);
 MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
-module_param(test_boost_interval, int, 0444);
-MODULE_PARM_DESC(test_boost_interval, "Interval between boost tests, seconds.");
 module_param(test_boost_duration, int, 0444);
 MODULE_PARM_DESC(test_boost_duration, "Duration of each boost test, seconds.");
+module_param(test_boost_interval, int, 0444);
+MODULE_PARM_DESC(test_boost_interval, "Interval between boost tests, seconds.");
+module_param(test_no_idle_hz, bool, 0444);
+MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
 module_param(torture_type, charp, 0444);
 MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
+module_param(verbose, bool, 0444);
+MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
 
 #define TORTURE_FLAG "-torture:"
 #define PRINTK_STRING(s) \
@@ -360,6 +369,7 @@ struct rcu_torture_ops {
 	int (*completed)(void);
 	void (*deferred_free)(struct rcu_torture *p);
 	void (*sync)(void);
+	void (*exp_sync)(void);
 	void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
 	void (*cb_barrier)(void);
 	void (*fqs)(void);
@@ -443,81 +453,27 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)
 	call_rcu(&p->rtort_rcu, rcu_torture_cb);
 }
 
-static struct rcu_torture_ops rcu_ops = {
-	.init		= NULL,
-	.readlock	= rcu_torture_read_lock,
-	.read_delay	= rcu_read_delay,
-	.readunlock	= rcu_torture_read_unlock,
-	.completed	= rcu_torture_completed,
-	.deferred_free	= rcu_torture_deferred_free,
-	.sync		= synchronize_rcu,
-	.call		= call_rcu,
-	.cb_barrier	= rcu_barrier,
-	.fqs		= rcu_force_quiescent_state,
-	.stats		= NULL,
-	.irq_capable	= 1,
-	.can_boost	= rcu_can_boost(),
-	.name		= "rcu"
-};
-
-static void rcu_sync_torture_deferred_free(struct rcu_torture *p)
-{
-	int i;
-	struct rcu_torture *rp;
-	struct rcu_torture *rp1;
-
-	cur_ops->sync();
-	list_add(&p->rtort_free, &rcu_torture_removed);
-	list_for_each_entry_safe(rp, rp1, &rcu_torture_removed, rtort_free) {
-		i = rp->rtort_pipe_count;
-		if (i > RCU_TORTURE_PIPE_LEN)
-			i = RCU_TORTURE_PIPE_LEN;
-		atomic_inc(&rcu_torture_wcount[i]);
-		if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
-			rp->rtort_mbtest = 0;
-			list_del(&rp->rtort_free);
-			rcu_torture_free(rp);
-		}
-	}
-}
-
 static void rcu_sync_torture_init(void)
 {
 	INIT_LIST_HEAD(&rcu_torture_removed);
 }
 
-static struct rcu_torture_ops rcu_sync_ops = {
+static struct rcu_torture_ops rcu_ops = {
 	.init		= rcu_sync_torture_init,
 	.readlock	= rcu_torture_read_lock,
 	.read_delay	= rcu_read_delay,
 	.readunlock	= rcu_torture_read_unlock,
 	.completed	= rcu_torture_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
+	.deferred_free	= rcu_torture_deferred_free,
 	.sync		= synchronize_rcu,
-	.call		= NULL,
-	.cb_barrier	= NULL,
-	.fqs		= rcu_force_quiescent_state,
-	.stats		= NULL,
-	.irq_capable	= 1,
-	.can_boost	= rcu_can_boost(),
-	.name		= "rcu_sync"
-};
-
-static struct rcu_torture_ops rcu_expedited_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= rcu_torture_read_lock,
-	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
-	.readunlock	= rcu_torture_read_unlock,
-	.completed	= rcu_no_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= synchronize_rcu_expedited,
-	.call		= NULL,
-	.cb_barrier	= NULL,
+	.exp_sync	= synchronize_rcu_expedited,
+	.call		= call_rcu,
+	.cb_barrier	= rcu_barrier,
 	.fqs		= rcu_force_quiescent_state,
 	.stats		= NULL,
 	.irq_capable	= 1,
 	.can_boost	= rcu_can_boost(),
-	.name		= "rcu_expedited"
+	.name		= "rcu"
 };
 
 /*
@@ -546,13 +502,14 @@ static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
 }
 
 static struct rcu_torture_ops rcu_bh_ops = {
-	.init		= NULL,
+	.init		= rcu_sync_torture_init,
 	.readlock	= rcu_bh_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= rcu_bh_torture_read_unlock,
 	.completed	= rcu_bh_torture_completed,
 	.deferred_free	= rcu_bh_torture_deferred_free,
 	.sync		= synchronize_rcu_bh,
+	.exp_sync	= synchronize_rcu_bh_expedited,
 	.call		= call_rcu_bh,
 	.cb_barrier	= rcu_barrier_bh,
 	.fqs		= rcu_bh_force_quiescent_state,
@@ -561,38 +518,6 @@ static struct rcu_torture_ops rcu_bh_ops = {
 	.name		= "rcu_bh"
 };
 
-static struct rcu_torture_ops rcu_bh_sync_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= rcu_bh_torture_read_lock,
-	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
-	.readunlock	= rcu_bh_torture_read_unlock,
-	.completed	= rcu_bh_torture_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= synchronize_rcu_bh,
-	.call		= NULL,
-	.cb_barrier	= NULL,
-	.fqs		= rcu_bh_force_quiescent_state,
-	.stats		= NULL,
-	.irq_capable	= 1,
-	.name		= "rcu_bh_sync"
-};
-
-static struct rcu_torture_ops rcu_bh_expedited_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= rcu_bh_torture_read_lock,
-	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
-	.readunlock	= rcu_bh_torture_read_unlock,
-	.completed	= rcu_bh_torture_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= synchronize_rcu_bh_expedited,
-	.call		= NULL,
-	.cb_barrier	= NULL,
-	.fqs		= rcu_bh_force_quiescent_state,
-	.stats		= NULL,
-	.irq_capable	= 1,
-	.name		= "rcu_bh_expedited"
-};
-
 /*
  * Definitions for srcu torture testing.
  */
@@ -667,6 +592,11 @@ static int srcu_torture_stats(char *page)
 	return cnt;
 }
 
+static void srcu_torture_synchronize_expedited(void)
+{
+	synchronize_srcu_expedited(&srcu_ctl);
+}
+
 static struct rcu_torture_ops srcu_ops = {
 	.init		= rcu_sync_torture_init,
 	.readlock	= srcu_torture_read_lock,
@@ -675,45 +605,13 @@ static struct rcu_torture_ops srcu_ops = {
 	.completed	= srcu_torture_completed,
 	.deferred_free	= srcu_torture_deferred_free,
 	.sync		= srcu_torture_synchronize,
+	.exp_sync	= srcu_torture_synchronize_expedited,
 	.call		= srcu_torture_call,
 	.cb_barrier	= srcu_torture_barrier,
 	.stats		= srcu_torture_stats,
 	.name		= "srcu"
 };
 
-static struct rcu_torture_ops srcu_sync_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= srcu_torture_read_lock,
-	.read_delay	= srcu_read_delay,
-	.readunlock	= srcu_torture_read_unlock,
-	.completed	= srcu_torture_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= srcu_torture_synchronize,
-	.call		= NULL,
-	.cb_barrier	= NULL,
-	.stats		= srcu_torture_stats,
-	.name		= "srcu_sync"
-};
-
-static void srcu_torture_synchronize_expedited(void)
-{
-	synchronize_srcu_expedited(&srcu_ctl);
-}
-
-static struct rcu_torture_ops srcu_expedited_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= srcu_torture_read_lock,
-	.read_delay	= srcu_read_delay,
-	.readunlock	= srcu_torture_read_unlock,
-	.completed	= srcu_torture_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= srcu_torture_synchronize_expedited,
-	.call		= NULL,
-	.cb_barrier	= NULL,
-	.stats		= srcu_torture_stats,
-	.name		= "srcu_expedited"
-};
-
 /*
  * Definitions for sched torture testing.
  */
@@ -742,6 +640,8 @@ static struct rcu_torture_ops sched_ops = {
 	.completed	= rcu_no_completed,
 	.deferred_free	= rcu_sched_torture_deferred_free,
 	.sync		= synchronize_sched,
+	.exp_sync	= synchronize_sched_expedited,
+	.call		= call_rcu_sched,
 	.cb_barrier	= rcu_barrier_sched,
 	.fqs		= rcu_sched_force_quiescent_state,
 	.stats		= NULL,
@@ -749,35 +649,6 @@ static struct rcu_torture_ops sched_ops = {
 	.name		= "sched"
 };
 
-static struct rcu_torture_ops sched_sync_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= sched_torture_read_lock,
-	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
-	.readunlock	= sched_torture_read_unlock,
-	.completed	= rcu_no_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= synchronize_sched,
-	.cb_barrier	= NULL,
-	.fqs		= rcu_sched_force_quiescent_state,
-	.stats		= NULL,
-	.name		= "sched_sync"
-};
-
-static struct rcu_torture_ops sched_expedited_ops = {
-	.init		= rcu_sync_torture_init,
-	.readlock	= sched_torture_read_lock,
-	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
-	.readunlock	= sched_torture_read_unlock,
-	.completed	= rcu_no_completed,
-	.deferred_free	= rcu_sync_torture_deferred_free,
-	.sync		= synchronize_sched_expedited,
-	.cb_barrier	= NULL,
-	.fqs		= rcu_sched_force_quiescent_state,
-	.stats		= NULL,
-	.irq_capable	= 1,
-	.name		= "sched_expedited"
-};
-
 /*
  * RCU torture priority-boost testing.  Runs one real-time thread per
  * CPU for moderate bursts, repeatedly registering RCU callbacks and
@@ -927,9 +798,10 @@ rcu_torture_fqs(void *arg)
 static int
 rcu_torture_writer(void *arg)
 {
+	bool exp;
 	int i;
-	long oldbatch = rcu_batches_completed();
 	struct rcu_torture *rp;
+	struct rcu_torture *rp1;
 	struct rcu_torture *old_rp;
 	static DEFINE_RCU_RANDOM(rand);
 
@@ -954,10 +826,33 @@ rcu_torture_writer(void *arg)
 				i = RCU_TORTURE_PIPE_LEN;
 			atomic_inc(&rcu_torture_wcount[i]);
 			old_rp->rtort_pipe_count++;
-			cur_ops->deferred_free(old_rp);
+			if (gp_normal == gp_exp)
+				exp = !!(rcu_random(&rand) & 0x80);
+			else
+				exp = gp_exp;
+			if (!exp) {
+				cur_ops->deferred_free(old_rp);
+			} else {
+				cur_ops->exp_sync();
+				list_add(&old_rp->rtort_free,
+					 &rcu_torture_removed);
+				list_for_each_entry_safe(rp, rp1,
+							 &rcu_torture_removed,
+							 rtort_free) {
+				 	i = rp->rtort_pipe_count;
+					if (i > RCU_TORTURE_PIPE_LEN)
+						i = RCU_TORTURE_PIPE_LEN;
+					atomic_inc(&rcu_torture_wcount[i]);
+					if (++rp->rtort_pipe_count >=
+					    RCU_TORTURE_PIPE_LEN) {
+						rp->rtort_mbtest = 0;
+						list_del(&rp->rtort_free);
+						rcu_torture_free(rp);
+					}
+				 }
+			}
 		}
 		rcutorture_record_progress(++rcu_torture_current_version);
-		oldbatch = cur_ops->completed();
 		rcu_stutter_wait("rcu_torture_writer");
 	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
@@ -983,10 +878,18 @@ rcu_torture_fakewriter(void *arg)
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
 		udelay(rcu_random(&rand) & 0x3ff);
 		if (cur_ops->cb_barrier != NULL &&
-		    rcu_random(&rand) % (nfakewriters * 8) == 0)
+		    rcu_random(&rand) % (nfakewriters * 8) == 0) {
 			cur_ops->cb_barrier();
-		else
+		} else if (gp_normal == gp_exp) {
+			if (rcu_random(&rand) & 0x80)
+				cur_ops->sync();
+			else
+				cur_ops->exp_sync();
+		} else if (gp_normal) {
 			cur_ops->sync();
+		} else {
+			cur_ops->exp_sync();
+		}
 		rcu_stutter_wait("rcu_torture_fakewriter");
 	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 
@@ -1534,7 +1437,13 @@ rcu_torture_onoff(void *arg)
 					 torture_type, cpu);
 			starttime = jiffies;
 			n_online_attempts++;
-			if (cpu_up(cpu) == 0) {
+			ret = cpu_up(cpu);
+			if (ret != 0) {
+				if (verbose)
+					pr_alert("%s" TORTURE_FLAG
+						 "rcu_torture_onoff task: online %d failed: errno %d\n",
+						 torture_type, cpu, ret);
+			} else {
 				if (verbose)
 					pr_alert("%s" TORTURE_FLAG
 						 "rcu_torture_onoff task: onlined %d\n",
@@ -1934,6 +1843,18 @@ rcu_torture_cleanup(void)
 		rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
 }
 
+#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
+static void rcu_torture_leak_cb(struct rcu_head *rhp)
+{
+}
+
+static void rcu_torture_err_cb(struct rcu_head *rhp)
+{
+	/* This -might- happen due to race conditions, but is unlikely. */
+	pr_alert("rcutorture: duplicated callback was invoked.\n");
+}
+#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+
 static int __init
 rcu_torture_init(void)
 {
@@ -1942,10 +1863,7 @@ rcu_torture_init(void)
 	int firsterr = 0;
 	int retval;
 	static struct rcu_torture_ops *torture_ops[] =
-		{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
-		  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
-		  &srcu_ops, &srcu_sync_ops, &srcu_expedited_ops,
-		  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
+		{ &rcu_ops, &rcu_bh_ops, &srcu_ops, &sched_ops, };
 
 	mutex_lock(&fullstop_mutex);
 
@@ -2163,6 +2081,28 @@ rcu_torture_init(void)
 		firsterr = retval;
 		goto unwind;
 	}
+	if (object_debug) {
+#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
+		struct rcu_head rh1;
+		struct rcu_head rh2;
+
+		init_rcu_head_on_stack(&rh1);
+		init_rcu_head_on_stack(&rh2);
+		pr_alert("rcutorture: WARN: Duplicate call_rcu() test starting.\n");
+		local_irq_disable(); /* Make it hard to finish grace period. */
+		call_rcu(&rh1, rcu_torture_leak_cb); /* start grace period. */
+		call_rcu(&rh2, rcu_torture_err_cb);
+		call_rcu(&rh2, rcu_torture_err_cb); /* duplicate callback. */
+		local_irq_enable();
+		rcu_barrier();
+		pr_alert("rcutorture: WARN: Duplicate call_rcu() test complete.\n");
+		destroy_rcu_head_on_stack(&rh1);
+		destroy_rcu_head_on_stack(&rh2);
+#else /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+		pr_alert("rcutorture: !%s, not testing duplicate call_rcu()\n",
+			 "CONFIG_DEBUG_OBJECTS_RCU_HEAD");
+#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+	}
 	rcutorture_record_test_transition();
 	mutex_unlock(&fullstop_mutex);
 	return 0;
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 068de3a..5b53a89 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -53,6 +53,7 @@
 #include <linux/delay.h>
 #include <linux/stop_machine.h>
 #include <linux/random.h>
+#include <linux/suspend.h>
 
 #include "rcutree.h"
 #include <trace/events/rcu.h>
@@ -208,6 +209,10 @@ EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
 	.dynticks_nesting = DYNTICK_TASK_EXIT_IDLE,
 	.dynticks = ATOMIC_INIT(1),
+#ifdef CONFIG_NO_HZ_FULL_SYSIDLE
+	.dynticks_idle_nesting = DYNTICK_TASK_NEST_VALUE,
+	.dynticks_idle = ATOMIC_INIT(1),
+#endif /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
 };
 
 static long blimit = 10;	/* Maximum callbacks per rcu_do_batch. */
@@ -226,7 +231,9 @@ module_param(jiffies_till_next_fqs, ulong, 0644);
 
 static void rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
 				  struct rcu_data *rdp);
-static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *));
+static void force_qs_rnp(struct rcu_state *rsp,
+			 int (*f)(struct rcu_data *, bool *, unsigned long *),
+			 bool *isidle, unsigned long *maxj);
 static void force_quiescent_state(struct rcu_state *rsp);
 static int rcu_pending(int cpu);
 
@@ -411,6 +418,7 @@ void rcu_idle_enter(void)
 
 	local_irq_save(flags);
 	rcu_eqs_enter(false);
+	rcu_sysidle_enter(&__get_cpu_var(rcu_dynticks), 0);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(rcu_idle_enter);
@@ -428,27 +436,6 @@ void rcu_user_enter(void)
 {
 	rcu_eqs_enter(1);
 }
-
-/**
- * rcu_user_enter_after_irq - inform RCU that we are going to resume userspace
- * after the current irq returns.
- *
- * This is similar to rcu_user_enter() but in the context of a non-nesting
- * irq. After this call, RCU enters into idle mode when the interrupt
- * returns.
- */
-void rcu_user_enter_after_irq(void)
-{
-	unsigned long flags;
-	struct rcu_dynticks *rdtp;
-
-	local_irq_save(flags);
-	rdtp = &__get_cpu_var(rcu_dynticks);
-	/* Ensure this irq is interrupting a non-idle RCU state.  */
-	WARN_ON_ONCE(!(rdtp->dynticks_nesting & DYNTICK_TASK_MASK));
-	rdtp->dynticks_nesting = 1;
-	local_irq_restore(flags);
-}
 #endif /* CONFIG_RCU_USER_QS */
 
 /**
@@ -482,6 +469,7 @@ void rcu_irq_exit(void)
 		trace_rcu_dyntick("--=", oldval, rdtp->dynticks_nesting);
 	else
 		rcu_eqs_enter_common(rdtp, oldval, true);
+	rcu_sysidle_enter(rdtp, 1);
 	local_irq_restore(flags);
 }
 
@@ -550,6 +538,7 @@ void rcu_idle_exit(void)
 
 	local_irq_save(flags);
 	rcu_eqs_exit(false);
+	rcu_sysidle_exit(&__get_cpu_var(rcu_dynticks), 0);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(rcu_idle_exit);
@@ -565,28 +554,6 @@ void rcu_user_exit(void)
 {
 	rcu_eqs_exit(1);
 }
-
-/**
- * rcu_user_exit_after_irq - inform RCU that we won't resume to userspace
- * idle mode after the current non-nesting irq returns.
- *
- * This is similar to rcu_user_exit() but in the context of an irq.
- * This is called when the irq has interrupted a userspace RCU idle mode
- * context. When the current non-nesting interrupt returns after this call,
- * the CPU won't restore the RCU idle mode.
- */
-void rcu_user_exit_after_irq(void)
-{
-	unsigned long flags;
-	struct rcu_dynticks *rdtp;
-
-	local_irq_save(flags);
-	rdtp = &__get_cpu_var(rcu_dynticks);
-	/* Ensure we are interrupting an RCU idle mode. */
-	WARN_ON_ONCE(rdtp->dynticks_nesting & DYNTICK_TASK_NEST_MASK);
-	rdtp->dynticks_nesting += DYNTICK_TASK_EXIT_IDLE;
-	local_irq_restore(flags);
-}
 #endif /* CONFIG_RCU_USER_QS */
 
 /**
@@ -623,6 +590,7 @@ void rcu_irq_enter(void)
 		trace_rcu_dyntick("++=", oldval, rdtp->dynticks_nesting);
 	else
 		rcu_eqs_exit_common(rdtp, oldval, true);
+	rcu_sysidle_exit(rdtp, 1);
 	local_irq_restore(flags);
 }
 
@@ -746,9 +714,11 @@ static int rcu_is_cpu_rrupt_from_idle(void)
  * credit them with an implicit quiescent state.  Return 1 if this CPU
  * is in dynticks idle mode, which is an extended quiescent state.
  */
-static int dyntick_save_progress_counter(struct rcu_data *rdp)
+static int dyntick_save_progress_counter(struct rcu_data *rdp,
+					 bool *isidle, unsigned long *maxj)
 {
 	rdp->dynticks_snap = atomic_add_return(0, &rdp->dynticks->dynticks);
+	rcu_sysidle_check_cpu(rdp, isidle, maxj);
 	return (rdp->dynticks_snap & 0x1) == 0;
 }
 
@@ -758,7 +728,8 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp)
  * idle state since the last call to dyntick_save_progress_counter()
  * for this same CPU, or by virtue of having been offline.
  */
-static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
+static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
+				    bool *isidle, unsigned long *maxj)
 {
 	unsigned int curr;
 	unsigned int snap;
@@ -1308,18 +1279,27 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp)
 }
 
 /*
- * Initialize a new grace period.
+ * Initialize a new grace period.  Return 0 if no grace period required.
  */
 static int rcu_gp_init(struct rcu_state *rsp)
 {
 	struct rcu_data *rdp;
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
+	rcu_bind_gp_kthread();
 	raw_spin_lock_irq(&rnp->lock);
+	if (rsp->gp_flags == 0) {
+		/* Spurious wakeup, tell caller to go back to sleep.  */
+		raw_spin_unlock_irq(&rnp->lock);
+		return 0;
+	}
 	rsp->gp_flags = 0; /* Clear all flags: New grace period. */
 
-	if (rcu_gp_in_progress(rsp)) {
-		/* Grace period already in progress, don't start another.  */
+	if (WARN_ON_ONCE(rcu_gp_in_progress(rsp))) {
+		/*
+		 * Grace period already in progress, don't start another.
+		 * Not supposed to be able to happen.
+		 */
 		raw_spin_unlock_irq(&rnp->lock);
 		return 0;
 	}
@@ -1379,16 +1359,25 @@ static int rcu_gp_init(struct rcu_state *rsp)
 int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
 {
 	int fqs_state = fqs_state_in;
+	bool isidle = false;
+	unsigned long maxj;
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
 	rsp->n_force_qs++;
 	if (fqs_state == RCU_SAVE_DYNTICK) {
 		/* Collect dyntick-idle snapshots. */
-		force_qs_rnp(rsp, dyntick_save_progress_counter);
+		if (is_sysidle_rcu_state(rsp)) {
+			isidle = 1;
+			maxj = jiffies - ULONG_MAX / 4;
+		}
+		force_qs_rnp(rsp, dyntick_save_progress_counter,
+			     &isidle, &maxj);
+		rcu_sysidle_report_gp(rsp, isidle, maxj);
 		fqs_state = RCU_FORCE_QS;
 	} else {
 		/* Handle dyntick-idle and offline CPUs. */
-		force_qs_rnp(rsp, rcu_implicit_dynticks_qs);
+		isidle = 0;
+		force_qs_rnp(rsp, rcu_implicit_dynticks_qs, &isidle, &maxj);
 	}
 	/* Clear flag to prevent immediate re-entry. */
 	if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
@@ -1453,7 +1442,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
 	rdp = this_cpu_ptr(rsp->rda);
 	rcu_advance_cbs(rsp, rnp, rdp);  /* Reduce false positives below. */
 	if (cpu_needs_another_gp(rsp, rdp))
-		rsp->gp_flags = 1;
+		rsp->gp_flags = RCU_GP_FLAG_INIT;
 	raw_spin_unlock_irq(&rnp->lock);
 }
 
@@ -1463,6 +1452,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
 static int __noreturn rcu_gp_kthread(void *arg)
 {
 	int fqs_state;
+	int gf;
 	unsigned long j;
 	int ret;
 	struct rcu_state *rsp = arg;
@@ -1473,10 +1463,9 @@ static int __noreturn rcu_gp_kthread(void *arg)
 		/* Handle grace-period start. */
 		for (;;) {
 			wait_event_interruptible(rsp->gp_wq,
-						 rsp->gp_flags &
+						 ACCESS_ONCE(rsp->gp_flags) &
 						 RCU_GP_FLAG_INIT);
-			if ((rsp->gp_flags & RCU_GP_FLAG_INIT) &&
-			    rcu_gp_init(rsp))
+			if (rcu_gp_init(rsp))
 				break;
 			cond_resched();
 			flush_signals(current);
@@ -1489,10 +1478,13 @@ static int __noreturn rcu_gp_kthread(void *arg)
 			j = HZ;
 			jiffies_till_first_fqs = HZ;
 		}
+		ret = 0;
 		for (;;) {
-			rsp->jiffies_force_qs = jiffies + j;
+			if (!ret)
+				rsp->jiffies_force_qs = jiffies + j;
 			ret = wait_event_interruptible_timeout(rsp->gp_wq,
-					(rsp->gp_flags & RCU_GP_FLAG_FQS) ||
+					((gf = ACCESS_ONCE(rsp->gp_flags)) &
+					 RCU_GP_FLAG_FQS) ||
 					(!ACCESS_ONCE(rnp->qsmask) &&
 					 !rcu_preempt_blocked_readers_cgp(rnp)),
 					j);
@@ -1501,7 +1493,9 @@ static int __noreturn rcu_gp_kthread(void *arg)
 			    !rcu_preempt_blocked_readers_cgp(rnp))
 				break;
 			/* If time for quiescent-state forcing, do it. */
-			if (ret == 0 || (rsp->gp_flags & RCU_GP_FLAG_FQS)) {
+			if (ret == 0 ||
+			    ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) ||
+			    (gf & RCU_GP_FLAG_FQS)) {
 				fqs_state = rcu_gp_fqs(rsp, fqs_state);
 				cond_resched();
 			} else {
@@ -1558,10 +1552,12 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
 
 	/*
 	 * We can't do wakeups while holding the rnp->lock, as that
-	 * could cause possible deadlocks with the rq->lock. Deter
-	 * the wakeup to interrupt context.
+	 * could cause possible deadlocks with the rq->lock. Defer
+	 * the wakeup to interrupt context.  And don't bother waking
+	 * up the running kthread.
 	 */
-	irq_work_queue(&rsp->wakeup_work);
+	if (current != rsp->gp_kthread)
+		irq_work_queue(&rsp->wakeup_work);
 }
 
 /*
@@ -2087,7 +2083,9 @@ void rcu_check_callbacks(int cpu, int user)
  *
  * The caller must have suppressed start of new grace periods.
  */
-static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
+static void force_qs_rnp(struct rcu_state *rsp,
+			 int (*f)(struct rcu_data *, bool *, unsigned long *),
+			 bool *isidle, unsigned long *maxj)
 {
 	unsigned long bit;
 	int cpu;
@@ -2110,9 +2108,12 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
 		cpu = rnp->grplo;
 		bit = 1;
 		for (; cpu <= rnp->grphi; cpu++, bit <<= 1) {
-			if ((rnp->qsmask & bit) != 0 &&
-			    f(per_cpu_ptr(rsp->rda, cpu)))
-				mask |= bit;
+			if ((rnp->qsmask & bit) != 0) {
+				if ((rnp->qsmaskinit & bit) != 0)
+					*isidle = 0;
+				if (f(per_cpu_ptr(rsp->rda, cpu), isidle, maxj))
+					mask |= bit;
+			}
 		}
 		if (mask != 0) {
 
@@ -2287,6 +2288,13 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
 }
 
 /*
+ * RCU callback function to leak a callback.
+ */
+static void rcu_leak_callback(struct rcu_head *rhp)
+{
+}
+
+/*
  * Helper function for call_rcu() and friends.  The cpu argument will
  * normally be -1, indicating "currently running CPU".  It may specify
  * a CPU only if that CPU is a no-CBs CPU.  Currently, only _rcu_barrier()
@@ -2300,7 +2308,12 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
 	struct rcu_data *rdp;
 
 	WARN_ON_ONCE((unsigned long)head & 0x3); /* Misaligned rcu_head! */
-	debug_rcu_head_queue(head);
+	if (debug_rcu_head_queue(head)) {
+		/* Probable double call_rcu(), so leak the callback. */
+		ACCESS_ONCE(head->func) = rcu_leak_callback;
+		WARN_ONCE(1, "__call_rcu(): Leaked duplicate callback\n");
+		return;
+	}
 	head->func = func;
 	head->next = NULL;
 
@@ -2785,9 +2798,20 @@ static void _rcu_barrier(struct rcu_state *rsp)
 	 * transition.  The "if" expression below therefore rounds the old
 	 * value up to the next even number and adds two before comparing.
 	 */
-	snap_done = ACCESS_ONCE(rsp->n_barrier_done);
+	snap_done = rsp->n_barrier_done;
 	_rcu_barrier_trace(rsp, "Check", -1, snap_done);
-	if (ULONG_CMP_GE(snap_done, ((snap + 1) & ~0x1) + 2)) {
+
+	/*
+	 * If the value in snap is odd, we needed to wait for the current
+	 * rcu_barrier() to complete, then wait for the next one, in other
+	 * words, we need the value of snap_done to be three larger than
+	 * the value of snap.  On the other hand, if the value in snap is
+	 * even, we only had to wait for the next rcu_barrier() to complete,
+	 * in other words, we need the value of snap_done to be only two
+	 * greater than the value of snap.  The "(snap + 3) & 0x1" computes
+	 * this for us (thank you, Linus!).
+	 */
+	if (ULONG_CMP_GE(snap_done, (snap + 3) & ~0x1)) {
 		_rcu_barrier_trace(rsp, "EarlyExit", -1, snap_done);
 		smp_mb(); /* caller's subsequent code after above check. */
 		mutex_unlock(&rsp->barrier_mutex);
@@ -2930,6 +2954,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
 	rdp->blimit = blimit;
 	init_callback_list(rdp);  /* Re-enable callbacks on this CPU. */
 	rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
+	rcu_sysidle_init_percpu_data(rdp->dynticks);
 	atomic_set(&rdp->dynticks->dynticks,
 		   (atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1);
 	raw_spin_unlock(&rnp->lock);		/* irqs remain disabled. */
@@ -3015,6 +3040,25 @@ static int rcu_cpu_notify(struct notifier_block *self,
 	return NOTIFY_OK;
 }
 
+static int rcu_pm_notify(struct notifier_block *self,
+			 unsigned long action, void *hcpu)
+{
+	switch (action) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		if (nr_cpu_ids <= 256) /* Expediting bad for large systems. */
+			rcu_expedited = 1;
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		rcu_expedited = 0;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
 /*
  * Spawn the kthread that handles this RCU flavor's grace periods.
  */
@@ -3256,6 +3300,7 @@ void __init rcu_init(void)
 	 * or the scheduler are operational.
 	 */
 	cpu_notifier(rcu_cpu_notify, 0);
+	pm_notifier(rcu_pm_notify, 0);
 	for_each_online_cpu(cpu)
 		rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
 }
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index b383258..49dac99 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -88,6 +88,14 @@ struct rcu_dynticks {
 				    /* Process level is worth LLONG_MAX/2. */
 	int dynticks_nmi_nesting;   /* Track NMI nesting level. */
 	atomic_t dynticks;	    /* Even value for idle, else odd. */
+#ifdef CONFIG_NO_HZ_FULL_SYSIDLE
+	long long dynticks_idle_nesting;
+				    /* irq/process nesting level from idle. */
+	atomic_t dynticks_idle;	    /* Even value for idle, else odd. */
+				    /*  "Idle" excludes userspace execution. */
+	unsigned long dynticks_idle_jiffies;
+				    /* End of last non-NMI non-idle period. */
+#endif /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
 #ifdef CONFIG_RCU_FAST_NO_HZ
 	bool all_lazy;		    /* Are all CPU's CBs lazy? */
 	unsigned long nonlazy_posted;
@@ -545,6 +553,15 @@ static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
 static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
 static void rcu_kick_nohz_cpu(int cpu);
 static bool init_nocb_callback_list(struct rcu_data *rdp);
+static void rcu_sysidle_enter(struct rcu_dynticks *rdtp, int irq);
+static void rcu_sysidle_exit(struct rcu_dynticks *rdtp, int irq);
+static void rcu_sysidle_check_cpu(struct rcu_data *rdp, bool *isidle,
+				  unsigned long *maxj);
+static bool is_sysidle_rcu_state(struct rcu_state *rsp);
+static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle,
+				  unsigned long maxj);
+static void rcu_bind_gp_kthread(void);
+static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp);
 
 #endif /* #ifndef RCU_TREE_NONCORE */
 
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 769e12e..baecd21 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -28,7 +28,7 @@
 #include <linux/gfp.h>
 #include <linux/oom.h>
 #include <linux/smpboot.h>
-#include <linux/tick.h>
+#include "time/tick-internal.h"
 
 #define RCU_KTHREAD_PRIO 1
 
@@ -2375,3 +2375,424 @@ static void rcu_kick_nohz_cpu(int cpu)
 		smp_send_reschedule(cpu);
 #endif /* #ifdef CONFIG_NO_HZ_FULL */
 }
+
+
+#ifdef CONFIG_NO_HZ_FULL_SYSIDLE
+
+/*
+ * Handle small systems specially, accelerating their transition into
+ * full idle state.  Allow arches to override this code's idea of
+ * what constitutes a "small" system.
+ */
+#ifdef CONFIG_ARCH_RCU_SYSIDLE_SMALL
+#define RCU_SYSIDLE_SMALL CONFIG_ARCH_RCU_SYSIDLE_SMALL
+#else /* #ifdef CONFIG_ARCH_RCU_SYSIDLE_SMALL */
+#define RCU_SYSIDLE_SMALL 8
+#endif
+
+/*
+ * Define RCU flavor that holds sysidle state.  This needs to be the
+ * most active flavor of RCU.
+ */
+#ifdef CONFIG_PREEMPT_RCU
+static struct rcu_state *rcu_sysidle_state = &rcu_preempt_state;
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+static struct rcu_state *rcu_sysidle_state = &rcu_sched_state;
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
+static int full_sysidle_state;		/* Current system-idle state. */
+#define RCU_SYSIDLE_NOT		0	/* Some CPU is not idle. */
+#define RCU_SYSIDLE_SHORT	1	/* All CPUs idle for brief period. */
+#define RCU_SYSIDLE_LONG	2	/* All CPUs idle for long enough. */
+#define RCU_SYSIDLE_FULL	3	/* All CPUs idle, ready for sysidle. */
+#define RCU_SYSIDLE_FULL_NOTED	4	/* Actually entered sysidle state. */
+
+/*
+ * Invoked to note exit from irq or task transition to idle.  Note that
+ * usermode execution does -not- count as idle here!  After all, we want
+ * to detect full-system idle states, not RCU quiescent states and grace
+ * periods.  The caller must have disabled interrupts.
+ */
+static void rcu_sysidle_enter(struct rcu_dynticks *rdtp, int irq)
+{
+	unsigned long j;
+
+	/* Adjust nesting, check for fully idle. */
+	if (irq) {
+		rdtp->dynticks_idle_nesting--;
+		WARN_ON_ONCE(rdtp->dynticks_idle_nesting < 0);
+		if (rdtp->dynticks_idle_nesting != 0)
+			return;  /* Still not fully idle. */
+	} else {
+		if ((rdtp->dynticks_idle_nesting & DYNTICK_TASK_NEST_MASK) ==
+		    DYNTICK_TASK_NEST_VALUE) {
+			rdtp->dynticks_idle_nesting = 0;
+		} else {
+			rdtp->dynticks_idle_nesting -= DYNTICK_TASK_NEST_VALUE;
+			WARN_ON_ONCE(rdtp->dynticks_idle_nesting < 0);
+			return;  /* Still not fully idle. */
+		}
+	}
+
+	/* Record start of fully idle period. */
+	j = jiffies;
+	ACCESS_ONCE(rdtp->dynticks_idle_jiffies) = j;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&rdtp->dynticks_idle);
+	smp_mb__after_atomic_inc();
+	WARN_ON_ONCE(atomic_read(&rdtp->dynticks_idle) & 0x1);
+}
+
+/*
+ * Unconditionally force exit from full system-idle state.  This is
+ * invoked when a normal CPU exits idle, but must be called separately
+ * for the timekeeping CPU (tick_do_timer_cpu).  The reason for this
+ * is that the timekeeping CPU is permitted to take scheduling-clock
+ * interrupts while the system is in system-idle state, and of course
+ * rcu_sysidle_exit() has no way of distinguishing a scheduling-clock
+ * interrupt from any other type of interrupt.
+ */
+void rcu_sysidle_force_exit(void)
+{
+	int oldstate = ACCESS_ONCE(full_sysidle_state);
+	int newoldstate;
+
+	/*
+	 * Each pass through the following loop attempts to exit full
+	 * system-idle state.  If contention proves to be a problem,
+	 * a trylock-based contention tree could be used here.
+	 */
+	while (oldstate > RCU_SYSIDLE_SHORT) {
+		newoldstate = cmpxchg(&full_sysidle_state,
+				      oldstate, RCU_SYSIDLE_NOT);
+		if (oldstate == newoldstate &&
+		    oldstate == RCU_SYSIDLE_FULL_NOTED) {
+			rcu_kick_nohz_cpu(tick_do_timer_cpu);
+			return; /* We cleared it, done! */
+		}
+		oldstate = newoldstate;
+	}
+	smp_mb(); /* Order initial oldstate fetch vs. later non-idle work. */
+}
+
+/*
+ * Invoked to note entry to irq or task transition from idle.  Note that
+ * usermode execution does -not- count as idle here!  The caller must
+ * have disabled interrupts.
+ */
+static void rcu_sysidle_exit(struct rcu_dynticks *rdtp, int irq)
+{
+	/* Adjust nesting, check for already non-idle. */
+	if (irq) {
+		rdtp->dynticks_idle_nesting++;
+		WARN_ON_ONCE(rdtp->dynticks_idle_nesting <= 0);
+		if (rdtp->dynticks_idle_nesting != 1)
+			return; /* Already non-idle. */
+	} else {
+		/*
+		 * Allow for irq misnesting.  Yes, it really is possible
+		 * to enter an irq handler then never leave it, and maybe
+		 * also vice versa.  Handle both possibilities.
+		 */
+		if (rdtp->dynticks_idle_nesting & DYNTICK_TASK_NEST_MASK) {
+			rdtp->dynticks_idle_nesting += DYNTICK_TASK_NEST_VALUE;
+			WARN_ON_ONCE(rdtp->dynticks_idle_nesting <= 0);
+			return; /* Already non-idle. */
+		} else {
+			rdtp->dynticks_idle_nesting = DYNTICK_TASK_EXIT_IDLE;
+		}
+	}
+
+	/* Record end of idle period. */
+	smp_mb__before_atomic_inc();
+	atomic_inc(&rdtp->dynticks_idle);
+	smp_mb__after_atomic_inc();
+	WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks_idle) & 0x1));
+
+	/*
+	 * If we are the timekeeping CPU, we are permitted to be non-idle
+	 * during a system-idle state.  This must be the case, because
+	 * the timekeeping CPU has to take scheduling-clock interrupts
+	 * during the time that the system is transitioning to full
+	 * system-idle state.  This means that the timekeeping CPU must
+	 * invoke rcu_sysidle_force_exit() directly if it does anything
+	 * more than take a scheduling-clock interrupt.
+	 */
+	if (smp_processor_id() == tick_do_timer_cpu)
+		return;
+
+	/* Update system-idle state: We are clearly no longer fully idle! */
+	rcu_sysidle_force_exit();
+}
+
+/*
+ * Check to see if the current CPU is idle.  Note that usermode execution
+ * does not count as idle.  The caller must have disabled interrupts.
+ */
+static void rcu_sysidle_check_cpu(struct rcu_data *rdp, bool *isidle,
+				  unsigned long *maxj)
+{
+	int cur;
+	unsigned long j;
+	struct rcu_dynticks *rdtp = rdp->dynticks;
+
+	/*
+	 * If some other CPU has already reported non-idle, if this is
+	 * not the flavor of RCU that tracks sysidle state, or if this
+	 * is an offline or the timekeeping CPU, nothing to do.
+	 */
+	if (!*isidle || rdp->rsp != rcu_sysidle_state ||
+	    cpu_is_offline(rdp->cpu) || rdp->cpu == tick_do_timer_cpu)
+		return;
+	if (rcu_gp_in_progress(rdp->rsp))
+		WARN_ON_ONCE(smp_processor_id() != tick_do_timer_cpu);
+
+	/* Pick up current idle and NMI-nesting counter and check. */
+	cur = atomic_read(&rdtp->dynticks_idle);
+	if (cur & 0x1) {
+		*isidle = false; /* We are not idle! */
+		return;
+	}
+	smp_mb(); /* Read counters before timestamps. */
+
+	/* Pick up timestamps. */
+	j = ACCESS_ONCE(rdtp->dynticks_idle_jiffies);
+	/* If this CPU entered idle more recently, update maxj timestamp. */
+	if (ULONG_CMP_LT(*maxj, j))
+		*maxj = j;
+}
+
+/*
+ * Is this the flavor of RCU that is handling full-system idle?
+ */
+static bool is_sysidle_rcu_state(struct rcu_state *rsp)
+{
+	return rsp == rcu_sysidle_state;
+}
+
+/*
+ * Bind the grace-period kthread for the sysidle flavor of RCU to the
+ * timekeeping CPU.
+ */
+static void rcu_bind_gp_kthread(void)
+{
+	int cpu = ACCESS_ONCE(tick_do_timer_cpu);
+
+	if (cpu < 0 || cpu >= nr_cpu_ids)
+		return;
+	if (raw_smp_processor_id() != cpu)
+		set_cpus_allowed_ptr(current, cpumask_of(cpu));
+}
+
+/*
+ * Return a delay in jiffies based on the number of CPUs, rcu_node
+ * leaf fanout, and jiffies tick rate.  The idea is to allow larger
+ * systems more time to transition to full-idle state in order to
+ * avoid the cache thrashing that otherwise occur on the state variable.
+ * Really small systems (less than a couple of tens of CPUs) should
+ * instead use a single global atomically incremented counter, and later
+ * versions of this will automatically reconfigure themselves accordingly.
+ */
+static unsigned long rcu_sysidle_delay(void)
+{
+	if (nr_cpu_ids <= RCU_SYSIDLE_SMALL)
+		return 0;
+	return DIV_ROUND_UP(nr_cpu_ids * HZ, rcu_fanout_leaf * 1000);
+}
+
+/*
+ * Advance the full-system-idle state.  This is invoked when all of
+ * the non-timekeeping CPUs are idle.
+ */
+static void rcu_sysidle(unsigned long j)
+{
+	/* Check the current state. */
+	switch (ACCESS_ONCE(full_sysidle_state)) {
+	case RCU_SYSIDLE_NOT:
+
+		/* First time all are idle, so note a short idle period. */
+		ACCESS_ONCE(full_sysidle_state) = RCU_SYSIDLE_SHORT;
+		break;
+
+	case RCU_SYSIDLE_SHORT:
+
+		/*
+		 * Idle for a bit, time to advance to next state?
+		 * cmpxchg failure means race with non-idle, let them win.
+		 */
+		if (ULONG_CMP_GE(jiffies, j + rcu_sysidle_delay()))
+			(void)cmpxchg(&full_sysidle_state,
+				      RCU_SYSIDLE_SHORT, RCU_SYSIDLE_LONG);
+		break;
+
+	case RCU_SYSIDLE_LONG:
+
+		/*
+		 * Do an additional check pass before advancing to full.
+		 * cmpxchg failure means race with non-idle, let them win.
+		 */
+		if (ULONG_CMP_GE(jiffies, j + rcu_sysidle_delay()))
+			(void)cmpxchg(&full_sysidle_state,
+				      RCU_SYSIDLE_LONG, RCU_SYSIDLE_FULL);
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Found a non-idle non-timekeeping CPU, so kick the system-idle state
+ * back to the beginning.
+ */
+static void rcu_sysidle_cancel(void)
+{
+	smp_mb();
+	ACCESS_ONCE(full_sysidle_state) = RCU_SYSIDLE_NOT;
+}
+
+/*
+ * Update the sysidle state based on the results of a force-quiescent-state
+ * scan of the CPUs' dyntick-idle state.
+ */
+static void rcu_sysidle_report(struct rcu_state *rsp, int isidle,
+			       unsigned long maxj, bool gpkt)
+{
+	if (rsp != rcu_sysidle_state)
+		return;  /* Wrong flavor, ignore. */
+	if (isidle) {
+		if (gpkt && nr_cpu_ids > RCU_SYSIDLE_SMALL)
+			rcu_sysidle(maxj);    /* More idle! */
+	} else {
+		rcu_sysidle_cancel(); /* Idle is over. */
+	}
+}
+
+static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle,
+				  unsigned long maxj)
+{
+	rcu_sysidle_report(rsp, isidle, maxj, true);
+}
+
+/* Callback and function for forcing an RCU grace period. */
+struct rcu_sysidle_head {
+	struct rcu_head rh;
+	int inuse;
+};
+
+static void rcu_sysidle_cb(struct rcu_head *rhp)
+{
+	struct rcu_sysidle_head *rshp;
+
+	smp_mb();  /* grace period precedes setting inuse. */
+	rshp = container_of(rhp, struct rcu_sysidle_head, rh);
+	ACCESS_ONCE(rshp->inuse) = 0;
+}
+
+/*
+ * Check to see if the system is fully idle, other than the timekeeping CPU.
+ * The caller must have disabled interrupts.
+ */
+bool rcu_sys_is_idle(void)
+{
+	static struct rcu_sysidle_head rsh;
+	int rss = ACCESS_ONCE(full_sysidle_state);
+
+	if (WARN_ON_ONCE(smp_processor_id() != tick_do_timer_cpu))
+		return false;
+
+	/* Handle small-system case by doing a full scan of CPUs. */
+	if (nr_cpu_ids <= RCU_SYSIDLE_SMALL) {
+		int oldrss = rss - 1;
+
+		/*
+		 * One pass to advance to each state up to _FULL.
+		 * Give up if any pass fails to advance the state.
+		 */
+		while (rss < RCU_SYSIDLE_FULL && oldrss < rss) {
+			int cpu;
+			bool isidle = true;
+			unsigned long maxj = jiffies - ULONG_MAX / 4;
+			struct rcu_data *rdp;
+
+			/* Scan all the CPUs looking for nonidle CPUs. */
+			for_each_possible_cpu(cpu) {
+				rdp = per_cpu_ptr(rcu_sysidle_state->rda, cpu);
+				rcu_sysidle_check_cpu(rdp, &isidle, &maxj);
+				if (!isidle)
+					break;
+			}
+			rcu_sysidle_report(rcu_sysidle_state,
+					   isidle, maxj, false);
+			oldrss = rss;
+			rss = ACCESS_ONCE(full_sysidle_state);
+		}
+	}
+
+	/* If this is the first observation of an idle period, record it. */
+	if (rss == RCU_SYSIDLE_FULL) {
+		rss = cmpxchg(&full_sysidle_state,
+			      RCU_SYSIDLE_FULL, RCU_SYSIDLE_FULL_NOTED);
+		return rss == RCU_SYSIDLE_FULL;
+	}
+
+	smp_mb(); /* ensure rss load happens before later caller actions. */
+
+	/* If already fully idle, tell the caller (in case of races). */
+	if (rss == RCU_SYSIDLE_FULL_NOTED)
+		return true;
+
+	/*
+	 * If we aren't there yet, and a grace period is not in flight,
+	 * initiate a grace period.  Either way, tell the caller that
+	 * we are not there yet.
+	 */
+	if (nr_cpu_ids > RCU_SYSIDLE_SMALL &&
+	    !rcu_gp_in_progress(rcu_sysidle_state) &&
+	    !rsh.inuse && xchg(&rsh.inuse, 1) == 0)
+		call_rcu(&rsh.rh, rcu_sysidle_cb);
+	return false;
+}
+
+/*
+ * Initialize dynticks sysidle state for CPUs coming online.
+ */
+static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
+{
+	rdtp->dynticks_idle_nesting = DYNTICK_TASK_NEST_VALUE;
+}
+
+#else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
+
+static void rcu_sysidle_enter(struct rcu_dynticks *rdtp, int irq)
+{
+}
+
+static void rcu_sysidle_exit(struct rcu_dynticks *rdtp, int irq)
+{
+}
+
+static void rcu_sysidle_check_cpu(struct rcu_data *rdp, bool *isidle,
+				  unsigned long *maxj)
+{
+}
+
+static bool is_sysidle_rcu_state(struct rcu_state *rsp)
+{
+	return false;
+}
+
+static void rcu_bind_gp_kthread(void)
+{
+}
+
+static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle,
+				  unsigned long maxj)
+{
+}
+
+static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
+{
+}
+
+#endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
diff --git a/kernel/res_counter.c b/kernel/res_counter.c
index ff55247..4aa8a30 100644
--- a/kernel/res_counter.c
+++ b/kernel/res_counter.c
@@ -17,8 +17,8 @@
 void res_counter_init(struct res_counter *counter, struct res_counter *parent)
 {
 	spin_lock_init(&counter->lock);
-	counter->limit = RESOURCE_MAX;
-	counter->soft_limit = RESOURCE_MAX;
+	counter->limit = RES_COUNTER_MAX;
+	counter->soft_limit = RES_COUNTER_MAX;
 	counter->parent = parent;
 }
 
@@ -178,23 +178,30 @@ u64 res_counter_read_u64(struct res_counter *counter, int member)
 #endif
 
 int res_counter_memparse_write_strategy(const char *buf,
-					unsigned long long *res)
+					unsigned long long *resp)
 {
 	char *end;
+	unsigned long long res;
 
-	/* return RESOURCE_MAX(unlimited) if "-1" is specified */
+	/* return RES_COUNTER_MAX(unlimited) if "-1" is specified */
 	if (*buf == '-') {
-		*res = simple_strtoull(buf + 1, &end, 10);
-		if (*res != 1 || *end != '\0')
+		res = simple_strtoull(buf + 1, &end, 10);
+		if (res != 1 || *end != '\0')
 			return -EINVAL;
-		*res = RESOURCE_MAX;
+		*resp = RES_COUNTER_MAX;
 		return 0;
 	}
 
-	*res = memparse(buf, &end);
+	res = memparse(buf, &end);
 	if (*end != '\0')
 		return -EINVAL;
 
-	*res = PAGE_ALIGN(*res);
+	if (PAGE_ALIGN(res) >= res)
+		res = PAGE_ALIGN(res);
+	else
+		res = RES_COUNTER_MAX;
+
+	*resp = res;
+
 	return 0;
 }
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index b7c32cb..6e17978 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -933,6 +933,8 @@ static int effective_prio(struct task_struct *p)
 /**
  * task_curr - is this task currently executing on a CPU?
  * @p: the task in question.
+ *
+ * Return: 1 if the task is currently executing. 0 otherwise.
  */
 inline int task_curr(const struct task_struct *p)
 {
@@ -976,13 +978,6 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
 		rq->skip_clock_update = 1;
 }
 
-static ATOMIC_NOTIFIER_HEAD(task_migration_notifier);
-
-void register_task_migration_notifier(struct notifier_block *n)
-{
-	atomic_notifier_chain_register(&task_migration_notifier, n);
-}
-
 #ifdef CONFIG_SMP
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
@@ -1013,18 +1008,10 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 	trace_sched_migrate_task(p, new_cpu);
 
 	if (task_cpu(p) != new_cpu) {
-		struct task_migration_notifier tmn;
-
 		if (p->sched_class->migrate_task_rq)
 			p->sched_class->migrate_task_rq(p, new_cpu);
 		p->se.nr_migrations++;
 		perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, NULL, 0);
-
-		tmn.task = p;
-		tmn.from_cpu = task_cpu(p);
-		tmn.to_cpu = new_cpu;
-
-		atomic_notifier_call_chain(&task_migration_notifier, 0, &tmn);
 	}
 
 	__set_task_cpu(p, new_cpu);
@@ -1482,7 +1469,7 @@ static void ttwu_queue(struct task_struct *p, int cpu)
  * the simpler "current->state = TASK_RUNNING" to mark yourself
  * runnable without the overhead of this.
  *
- * Returns %true if @p was woken up, %false if it was already running
+ * Return: %true if @p was woken up, %false if it was already running.
  * or @state didn't match @p's state.
  */
 static int
@@ -1577,8 +1564,9 @@ out:
  * @p: The process to be woken up.
  *
  * Attempt to wake up the nominated process and move it to the set of runnable
- * processes.  Returns 1 if the process was woken up, 0 if it was already
- * running.
+ * processes.
+ *
+ * Return: 1 if the process was woken up, 0 if it was already running.
  *
  * It may be assumed that this function implies a write memory barrier before
  * changing the task state if and only if any tasks are woken up.
@@ -2191,6 +2179,8 @@ void scheduler_tick(void)
  * This makes sure that uptime, CFS vruntime, load
  * balancing, etc... continue to move forward, even
  * with a very low granularity.
+ *
+ * Return: Maximum deferment in nanoseconds.
  */
 u64 scheduler_tick_max_deferment(void)
 {
@@ -2660,7 +2650,7 @@ void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
 	if (unlikely(!q))
 		return;
 
-	if (unlikely(!nr_exclusive))
+	if (unlikely(nr_exclusive != 1))
 		wake_flags = 0;
 
 	spin_lock_irqsave(&q->lock, flags);
@@ -2796,8 +2786,8 @@ EXPORT_SYMBOL(wait_for_completion);
  * specified timeout to expire. The timeout is in jiffies. It is not
  * interruptible.
  *
- * The return value is 0 if timed out, and positive (at least 1, or number of
- * jiffies left till timeout) if completed.
+ * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
+ * till timeout) if completed.
  */
 unsigned long __sched
 wait_for_completion_timeout(struct completion *x, unsigned long timeout)
@@ -2829,8 +2819,8 @@ EXPORT_SYMBOL(wait_for_completion_io);
  * specified timeout to expire. The timeout is in jiffies. It is not
  * interruptible. The caller is accounted as waiting for IO.
  *
- * The return value is 0 if timed out, and positive (at least 1, or number of
- * jiffies left till timeout) if completed.
+ * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
+ * till timeout) if completed.
  */
 unsigned long __sched
 wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
@@ -2846,7 +2836,7 @@ EXPORT_SYMBOL(wait_for_completion_io_timeout);
  * This waits for completion of a specific task to be signaled. It is
  * interruptible.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if completed.
  */
 int __sched wait_for_completion_interruptible(struct completion *x)
 {
@@ -2865,8 +2855,8 @@ EXPORT_SYMBOL(wait_for_completion_interruptible);
  * This waits for either a completion of a specific task to be signaled or for a
  * specified timeout to expire. It is interruptible. The timeout is in jiffies.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if timed out,
- * positive (at least 1, or number of jiffies left till timeout) if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
+ * or number of jiffies left till timeout) if completed.
  */
 long __sched
 wait_for_completion_interruptible_timeout(struct completion *x,
@@ -2883,7 +2873,7 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
  * This waits to be signaled for completion of a specific task. It can be
  * interrupted by a kill signal.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if completed.
  */
 int __sched wait_for_completion_killable(struct completion *x)
 {
@@ -2903,8 +2893,8 @@ EXPORT_SYMBOL(wait_for_completion_killable);
  * signaled or for a specified timeout to expire. It can be
  * interrupted by a kill signal. The timeout is in jiffies.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if timed out,
- * positive (at least 1, or number of jiffies left till timeout) if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
+ * or number of jiffies left till timeout) if completed.
  */
 long __sched
 wait_for_completion_killable_timeout(struct completion *x,
@@ -2918,7 +2908,7 @@ EXPORT_SYMBOL(wait_for_completion_killable_timeout);
  *	try_wait_for_completion - try to decrement a completion without blocking
  *	@x:	completion structure
  *
- *	Returns: 0 if a decrement cannot be done without blocking
+ *	Return: 0 if a decrement cannot be done without blocking
  *		 1 if a decrement succeeded.
  *
  *	If a completion is being used as a counting completion,
@@ -2945,7 +2935,7 @@ EXPORT_SYMBOL(try_wait_for_completion);
  *	completion_done - Test to see if a completion has any waiters
  *	@x:	completion structure
  *
- *	Returns: 0 if there are waiters (wait_for_completion() in progress)
+ *	Return: 0 if there are waiters (wait_for_completion() in progress)
  *		 1 if there are no waiters.
  *
  */
@@ -3182,7 +3172,7 @@ SYSCALL_DEFINE1(nice, int, increment)
  * task_prio - return the priority value of a given task.
  * @p: the task in question.
  *
- * This is the priority value as seen by users in /proc.
+ * Return: The priority value as seen by users in /proc.
  * RT tasks are offset by -200. Normal tasks are centered
  * around 0, value goes from -16 to +15.
  */
@@ -3194,6 +3184,8 @@ int task_prio(const struct task_struct *p)
 /**
  * task_nice - return the nice value of a given task.
  * @p: the task in question.
+ *
+ * Return: The nice value [ -20 ... 0 ... 19 ].
  */
 int task_nice(const struct task_struct *p)
 {
@@ -3204,6 +3196,8 @@ EXPORT_SYMBOL(task_nice);
 /**
  * idle_cpu - is a given cpu idle currently?
  * @cpu: the processor in question.
+ *
+ * Return: 1 if the CPU is currently idle. 0 otherwise.
  */
 int idle_cpu(int cpu)
 {
@@ -3226,6 +3220,8 @@ int idle_cpu(int cpu)
 /**
  * idle_task - return the idle task for a given cpu.
  * @cpu: the processor in question.
+ *
+ * Return: The idle task for the cpu @cpu.
  */
 struct task_struct *idle_task(int cpu)
 {
@@ -3235,6 +3231,8 @@ struct task_struct *idle_task(int cpu)
 /**
  * find_process_by_pid - find a process with a matching PID value.
  * @pid: the pid in question.
+ *
+ * The task of @pid, if found. %NULL otherwise.
  */
 static struct task_struct *find_process_by_pid(pid_t pid)
 {
@@ -3432,6 +3430,8 @@ recheck:
  * @policy: new policy.
  * @param: structure containing the new RT priority.
  *
+ * Return: 0 on success. An error code otherwise.
+ *
  * NOTE that the task may be already dead.
  */
 int sched_setscheduler(struct task_struct *p, int policy,
@@ -3451,6 +3451,8 @@ EXPORT_SYMBOL_GPL(sched_setscheduler);
  * current context has permission.  For example, this is needed in
  * stop_machine(): we create temporary high priority worker threads,
  * but our caller might not have that capability.
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 int sched_setscheduler_nocheck(struct task_struct *p, int policy,
 			       const struct sched_param *param)
@@ -3485,6 +3487,8 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
  * @pid: the pid in question.
  * @policy: new policy.
  * @param: structure containing the new RT priority.
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy,
 		struct sched_param __user *, param)
@@ -3500,6 +3504,8 @@ SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy,
  * sys_sched_setparam - set/change the RT priority of a thread
  * @pid: the pid in question.
  * @param: structure containing the new RT priority.
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
 {
@@ -3509,6 +3515,9 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
 /**
  * sys_sched_getscheduler - get the policy (scheduling class) of a thread
  * @pid: the pid in question.
+ *
+ * Return: On success, the policy of the thread. Otherwise, a negative error
+ * code.
  */
 SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
 {
@@ -3535,6 +3544,9 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
  * sys_sched_getparam - get the RT priority of a thread
  * @pid: the pid in question.
  * @param: structure containing the RT priority.
+ *
+ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error
+ * code.
  */
 SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
 {
@@ -3659,6 +3671,8 @@ static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
  * @pid: pid of the process
  * @len: length in bytes of the bitmask pointed to by user_mask_ptr
  * @user_mask_ptr: user-space pointer to the new cpu mask
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
 		unsigned long __user *, user_mask_ptr)
@@ -3710,6 +3724,8 @@ out_unlock:
  * @pid: pid of the process
  * @len: length in bytes of the bitmask pointed to by user_mask_ptr
  * @user_mask_ptr: user-space pointer to hold the current cpu mask
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
 		unsigned long __user *, user_mask_ptr)
@@ -3744,6 +3760,8 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
  *
  * This function yields the current CPU to other tasks. If there are no
  * other threads running on this CPU then this function will return.
+ *
+ * Return: 0.
  */
 SYSCALL_DEFINE0(sched_yield)
 {
@@ -3869,7 +3887,7 @@ EXPORT_SYMBOL(yield);
  * It's the caller's job to ensure that the target task struct
  * can't go away on us before we can do any checks.
  *
- * Returns:
+ * Return:
  *	true (>0) if we indeed boosted the target task.
  *	false (0) if we failed to boost the target.
  *	-ESRCH if there's no task to yield to.
@@ -3972,8 +3990,9 @@ long __sched io_schedule_timeout(long timeout)
  * sys_sched_get_priority_max - return maximum RT priority.
  * @policy: scheduling class.
  *
- * this syscall returns the maximum rt_priority that can be used
- * by a given scheduling class.
+ * Return: On success, this syscall returns the maximum
+ * rt_priority that can be used by a given scheduling class.
+ * On failure, a negative error code is returned.
  */
 SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
 {
@@ -3997,8 +4016,9 @@ SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
  * sys_sched_get_priority_min - return minimum RT priority.
  * @policy: scheduling class.
  *
- * this syscall returns the minimum rt_priority that can be used
- * by a given scheduling class.
+ * Return: On success, this syscall returns the minimum
+ * rt_priority that can be used by a given scheduling class.
+ * On failure, a negative error code is returned.
  */
 SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
 {
@@ -4024,6 +4044,9 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
  *
  * this syscall writes the default timeslice value of a given process
  * into the user-space timespec buffer. A value of '0' means infinity.
+ *
+ * Return: On success, 0 and the timeslice is in @interval. Otherwise,
+ * an error code.
  */
 SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
 		struct timespec __user *, interval)
@@ -5083,18 +5106,23 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
  * two cpus are in the same cache domain, see cpus_share_cache().
  */
 DEFINE_PER_CPU(struct sched_domain *, sd_llc);
+DEFINE_PER_CPU(int, sd_llc_size);
 DEFINE_PER_CPU(int, sd_llc_id);
 
 static void update_top_cache_domain(int cpu)
 {
 	struct sched_domain *sd;
 	int id = cpu;
+	int size = 1;
 
 	sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES);
-	if (sd)
+	if (sd) {
 		id = cpumask_first(sched_domain_span(sd));
+		size = cpumask_weight(sched_domain_span(sd));
+	}
 
 	rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
+	per_cpu(sd_llc_size, cpu) = size;
 	per_cpu(sd_llc_id, cpu) = id;
 }
 
@@ -6632,6 +6660,8 @@ void normalize_rt_tasks(void)
  * @cpu: the processor in question.
  *
  * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ *
+ * Return: The current task for @cpu.
  */
 struct task_struct *curr_task(int cpu)
 {
diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c
index 1095e87..8b836b3 100644
--- a/kernel/sched/cpupri.c
+++ b/kernel/sched/cpupri.c
@@ -62,7 +62,7 @@ static int convert_prio(int prio)
  * any discrepancies created by racing against the uncertainty of the current
  * priority configuration.
  *
- * Returns: (int)bool - CPUs were found
+ * Return: (int)bool - CPUs were found
  */
 int cpupri_find(struct cpupri *cp, struct task_struct *p,
 		struct cpumask *lowest_mask)
@@ -203,7 +203,7 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri)
  * cpupri_init - initialize the cpupri structure
  * @cp: The cpupri context
  *
- * Returns: -ENOMEM if memory fails.
+ * Return: -ENOMEM on memory allocation failure.
  */
 int cpupri_init(struct cpupri *cp)
 {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 9565645..aaaed57 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2032,6 +2032,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
 	 */
 	update_entity_load_avg(curr, 1);
 	update_cfs_rq_blocked_load(cfs_rq, 1);
+	update_cfs_shares(cfs_rq);
 
 #ifdef CONFIG_SCHED_HRTICK
 	/*
@@ -3017,6 +3018,23 @@ static unsigned long cpu_avg_load_per_task(int cpu)
 	return 0;
 }
 
+static void record_wakee(struct task_struct *p)
+{
+	/*
+	 * Rough decay (wiping) for cost saving, don't worry
+	 * about the boundary, really active task won't care
+	 * about the loss.
+	 */
+	if (jiffies > current->wakee_flip_decay_ts + HZ) {
+		current->wakee_flips = 0;
+		current->wakee_flip_decay_ts = jiffies;
+	}
+
+	if (current->last_wakee != p) {
+		current->last_wakee = p;
+		current->wakee_flips++;
+	}
+}
 
 static void task_waking_fair(struct task_struct *p)
 {
@@ -3037,6 +3055,7 @@ static void task_waking_fair(struct task_struct *p)
 #endif
 
 	se->vruntime -= min_vruntime;
+	record_wakee(p);
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
@@ -3155,6 +3174,28 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu,
 
 #endif
 
+static int wake_wide(struct task_struct *p)
+{
+	int factor = this_cpu_read(sd_llc_size);
+
+	/*
+	 * Yeah, it's the switching-frequency, could means many wakee or
+	 * rapidly switch, use factor here will just help to automatically
+	 * adjust the loose-degree, so bigger node will lead to more pull.
+	 */
+	if (p->wakee_flips > factor) {
+		/*
+		 * wakee is somewhat hot, it needs certain amount of cpu
+		 * resource, so if waker is far more hot, prefer to leave
+		 * it alone.
+		 */
+		if (current->wakee_flips > (factor * p->wakee_flips))
+			return 1;
+	}
+
+	return 0;
+}
+
 static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 {
 	s64 this_load, load;
@@ -3164,6 +3205,13 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	unsigned long weight;
 	int balanced;
 
+	/*
+	 * If we wake multiple tasks be careful to not bounce
+	 * ourselves around too much.
+	 */
+	if (wake_wide(p))
+		return 0;
+
 	idx	  = sd->wake_idx;
 	this_cpu  = smp_processor_id();
 	prev_cpu  = task_cpu(p);
@@ -4171,47 +4219,48 @@ static void update_blocked_averages(int cpu)
 }
 
 /*
- * Compute the cpu's hierarchical load factor for each task group.
+ * Compute the hierarchical load factor for cfs_rq and all its ascendants.
  * This needs to be done in a top-down fashion because the load of a child
  * group is a fraction of its parents load.
  */
-static int tg_load_down(struct task_group *tg, void *data)
+static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
 {
-	unsigned long load;
-	long cpu = (long)data;
-
-	if (!tg->parent) {
-		load = cpu_rq(cpu)->avg.load_avg_contrib;
-	} else {
-		load = tg->parent->cfs_rq[cpu]->h_load;
-		load = div64_ul(load * tg->se[cpu]->avg.load_avg_contrib,
-				tg->parent->cfs_rq[cpu]->runnable_load_avg + 1);
-	}
-
-	tg->cfs_rq[cpu]->h_load = load;
-
-	return 0;
-}
-
-static void update_h_load(long cpu)
-{
-	struct rq *rq = cpu_rq(cpu);
+	struct rq *rq = rq_of(cfs_rq);
+	struct sched_entity *se = cfs_rq->tg->se[cpu_of(rq)];
 	unsigned long now = jiffies;
+	unsigned long load;
 
-	if (rq->h_load_throttle == now)
+	if (cfs_rq->last_h_load_update == now)
 		return;
 
-	rq->h_load_throttle = now;
+	cfs_rq->h_load_next = NULL;
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		cfs_rq->h_load_next = se;
+		if (cfs_rq->last_h_load_update == now)
+			break;
+	}
 
-	rcu_read_lock();
-	walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
-	rcu_read_unlock();
+	if (!se) {
+		cfs_rq->h_load = rq->avg.load_avg_contrib;
+		cfs_rq->last_h_load_update = now;
+	}
+
+	while ((se = cfs_rq->h_load_next) != NULL) {
+		load = cfs_rq->h_load;
+		load = div64_ul(load * se->avg.load_avg_contrib,
+				cfs_rq->runnable_load_avg + 1);
+		cfs_rq = group_cfs_rq(se);
+		cfs_rq->h_load = load;
+		cfs_rq->last_h_load_update = now;
+	}
 }
 
 static unsigned long task_h_load(struct task_struct *p)
 {
 	struct cfs_rq *cfs_rq = task_cfs_rq(p);
 
+	update_cfs_rq_h_load(cfs_rq);
 	return div64_ul(p->se.avg.load_avg_contrib * cfs_rq->h_load,
 			cfs_rq->runnable_load_avg + 1);
 }
@@ -4220,10 +4269,6 @@ static inline void update_blocked_averages(int cpu)
 {
 }
 
-static inline void update_h_load(long cpu)
-{
-}
-
 static unsigned long task_h_load(struct task_struct *p)
 {
 	return p->se.avg.load_avg_contrib;
@@ -4280,6 +4325,8 @@ struct sg_lb_stats {
  * get_sd_load_idx - Obtain the load index for a given sched domain.
  * @sd: The sched_domain whose load_idx is to be obtained.
  * @idle: The Idle status of the CPU for whose sd load_icx is obtained.
+ *
+ * Return: The load index.
  */
 static inline int get_sd_load_idx(struct sched_domain *sd,
 					enum cpu_idle_type idle)
@@ -4574,6 +4621,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
  *
  * Determine if @sg is a busier group than the previously selected
  * busiest group.
+ *
+ * Return: %true if @sg is a busier group than the previously selected
+ * busiest group. %false otherwise.
  */
 static bool update_sd_pick_busiest(struct lb_env *env,
 				   struct sd_lb_stats *sds,
@@ -4691,7 +4741,7 @@ static inline void update_sd_lb_stats(struct lb_env *env,
  * assuming lower CPU number will be equivalent to lower a SMT thread
  * number.
  *
- * Returns 1 when packing is required and a task should be moved to
+ * Return: 1 when packing is required and a task should be moved to
  * this CPU.  The amount of the imbalance is returned in *imbalance.
  *
  * @env: The load balancing environment.
@@ -4869,7 +4919,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
  * @balance: Pointer to a variable indicating if this_cpu
  *	is the appropriate cpu to perform load balancing at this_level.
  *
- * Returns:	- the busiest group if imbalance exists.
+ * Return:	- The busiest group if imbalance exists.
  *		- If no imbalance and user has opted for power-savings balance,
  *		   return the least loaded group whose CPUs can be
  *		   put to idle by rebalancing its tasks onto our group.
@@ -5108,7 +5158,6 @@ redo:
 		env.src_rq    = busiest;
 		env.loop_max  = min(sysctl_sched_nr_migrate, busiest->nr_running);
 
-		update_h_load(env.src_cpu);
 more_balance:
 		local_irq_save(flags);
 		double_rq_lock(env.dst_rq, busiest);
@@ -5889,11 +5938,9 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p)
 	* and ensure we don't carry in an old decay_count if we
 	* switch back.
 	*/
-	if (p->se.avg.decay_count) {
-		struct cfs_rq *cfs_rq = cfs_rq_of(&p->se);
-		__synchronize_entity_decay(&p->se);
-		subtract_blocked_load_contrib(cfs_rq,
-				p->se.avg.load_avg_contrib);
+	if (se->avg.decay_count) {
+		__synchronize_entity_decay(se);
+		subtract_blocked_load_contrib(cfs_rq, se->avg.load_avg_contrib);
 	}
 #endif
 }
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index ef0a7b2..4c1cb80 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -285,7 +285,6 @@ struct cfs_rq {
 	/* Required to track per-cpu representation of a task_group */
 	u32 tg_runnable_contrib;
 	unsigned long tg_load_contrib;
-#endif /* CONFIG_FAIR_GROUP_SCHED */
 
 	/*
 	 *   h_load = weight * f(tg)
@@ -294,6 +293,9 @@ struct cfs_rq {
 	 * this group.
 	 */
 	unsigned long h_load;
+	u64 last_h_load_update;
+	struct sched_entity *h_load_next;
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
@@ -429,9 +431,6 @@ struct rq {
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	/* list of leaf cfs_rq on this cpu: */
 	struct list_head leaf_cfs_rq_list;
-#ifdef CONFIG_SMP
-	unsigned long h_load_throttle;
-#endif /* CONFIG_SMP */
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
 #ifdef CONFIG_RT_GROUP_SCHED
@@ -595,6 +594,7 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
 }
 
 DECLARE_PER_CPU(struct sched_domain *, sd_llc);
+DECLARE_PER_CPU(int, sd_llc_size);
 DECLARE_PER_CPU(int, sd_llc_id);
 
 struct sched_group_power {
diff --git a/kernel/signal.c b/kernel/signal.c
index 50e4107..ded28b9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3394,7 +3394,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
 		new_ka.sa.sa_restorer = compat_ptr(restorer);
 #endif
 		ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask));
-		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		if (ret)
 			return -EFAULT;
 		sigset_from_compat(&new_ka.sa.sa_mask, &mask);
@@ -3406,7 +3406,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
 		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), 
 			       &oact->sa_handler);
 		ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask));
-		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 #ifdef __ARCH_HAS_SA_RESTORER
 		ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer),
 				&oact->sa_restorer);
diff --git a/kernel/smp.c b/kernel/smp.c
index fe9f773..91c52ab 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -12,6 +12,7 @@
 #include <linux/gfp.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
+#include <linux/hardirq.h>
 
 #include "smpboot.h"
 
@@ -48,10 +49,13 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
 				cpu_to_node(cpu)))
 			return notifier_from_errno(-ENOMEM);
 		if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
-				cpu_to_node(cpu)))
+				cpu_to_node(cpu))) {
+			free_cpumask_var(cfd->cpumask);
 			return notifier_from_errno(-ENOMEM);
+		}
 		cfd->csd = alloc_percpu(struct call_single_data);
 		if (!cfd->csd) {
+			free_cpumask_var(cfd->cpumask_ipi);
 			free_cpumask_var(cfd->cpumask);
 			return notifier_from_errno(-ENOMEM);
 		}
@@ -186,25 +190,13 @@ void generic_smp_call_function_single_interrupt(void)
 
 	while (!list_empty(&list)) {
 		struct call_single_data *csd;
-		unsigned int csd_flags;
 
 		csd = list_entry(list.next, struct call_single_data, list);
 		list_del(&csd->list);
 
-		/*
-		 * 'csd' can be invalid after this call if flags == 0
-		 * (when called through generic_exec_single()),
-		 * so save them away before making the call:
-		 */
-		csd_flags = csd->flags;
-
 		csd->func(csd->info);
 
-		/*
-		 * Unlocked CSDs are valid through generic_exec_single():
-		 */
-		if (csd_flags & CSD_FLAG_LOCK)
-			csd_unlock(csd);
+		csd_unlock(csd);
 	}
 }
 
@@ -240,8 +232,9 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
 	 * send smp call function interrupt to this cpu and as such deadlocks
 	 * can't happen.
 	 */
-	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
-		     && !oops_in_progress);
+	WARN_ON_ONCE(cpu_online(this_cpu)
+		&& (irqs_disabled() || in_serving_irq())
+		&& !oops_in_progress);
 
 	if (cpu == this_cpu) {
 		local_irq_save(flags);
@@ -278,8 +271,6 @@ EXPORT_SYMBOL(smp_call_function_single);
  * @wait: If true, wait until function has completed.
  *
  * Returns 0 on success, else a negative status code (if no cpus were online).
- * Note that @wait will be implicitly turned on in case of allocation failures,
- * since we fall back to on-stack allocation.
  *
  * Selection preference:
  *	1) current cpu if in @mask
@@ -378,8 +369,9 @@ void smp_call_function_many(const struct cpumask *mask,
 	 * send smp call function interrupt to this cpu and as such deadlocks
 	 * can't happen.
 	 */
-	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
-		     && !oops_in_progress && !early_boot_irqs_disabled);
+	WARN_ON_ONCE(cpu_online(this_cpu)
+		&& (irqs_disabled() || in_serving_irq())
+		&& !oops_in_progress && !early_boot_irqs_disabled);
 
 	/* Try to fastpath.  So, what's a CPU they want? Ignoring this one. */
 	cpu = cpumask_first_and(mask, cpu_online_mask);
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index 5cdd806..4b082b5 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -34,6 +34,20 @@
 #else
 #define raw_read_can_lock(l)	read_can_lock(l)
 #define raw_write_can_lock(l)	write_can_lock(l)
+
+/*
+ * Some architectures can relax in favour of the CPU owning the lock.
+ */
+#ifndef arch_read_relax
+# define arch_read_relax(l)	cpu_relax()
+#endif
+#ifndef arch_write_relax
+# define arch_write_relax(l)	cpu_relax()
+#endif
+#ifndef arch_spin_relax
+# define arch_spin_relax(l)	cpu_relax()
+#endif
+
 /*
  * We build the __lock_function inlines here. They are too large for
  * inlining all over the place, but here is only one user per function
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 07f6fc4..7822cd8 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1471,14 +1471,14 @@ static struct ctl_table fs_table[] = {
 	{
 		.procname	= "inode-nr",
 		.data		= &inodes_stat,
-		.maxlen		= 2*sizeof(int),
+		.maxlen		= 2*sizeof(long),
 		.mode		= 0444,
 		.proc_handler	= proc_nr_inodes,
 	},
 	{
 		.procname	= "inode-state",
 		.data		= &inodes_stat,
-		.maxlen		= 7*sizeof(int),
+		.maxlen		= 7*sizeof(long),
 		.mode		= 0444,
 		.proc_handler	= proc_nr_inodes,
 	},
@@ -1508,7 +1508,7 @@ static struct ctl_table fs_table[] = {
 	{
 		.procname	= "dentry-state",
 		.data		= &dentry_stat,
-		.maxlen		= 6*sizeof(int),
+		.maxlen		= 6*sizeof(long),
 		.mode		= 0444,
 		.proc_handler	= proc_nr_dentry,
 	},
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index 70f27e8..a613c2a 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -134,6 +134,29 @@ config NO_HZ_FULL_ALL
 	 Note the boot CPU will still be kept outside the range to
 	 handle the timekeeping duty.
 
+config NO_HZ_FULL_SYSIDLE
+	bool "Detect full-system idle state for full dynticks system"
+	depends on NO_HZ_FULL
+	default n
+	help
+	 At least one CPU must keep the scheduling-clock tick running
+	 for timekeeping purposes whenever there is a non-idle CPU,
+	 where "non-idle" includes CPUs with a single runnable task
+	 in adaptive-idle mode.  Because the underlying adaptive-tick
+	 support cannot distinguish between all CPUs being idle and
+	 all CPUs each running a single task in adaptive-idle mode,
+	 the underlying support simply ensures that there is always
+	 a CPU handling the scheduling-clock tick, whether or not all
+	 CPUs are idle.  This Kconfig option enables scalable detection
+	 of the all-CPUs-idle state, thus allowing the scheduling-clock
+	 tick to be disabled when all CPUs are idle.  Note that scalable
+	 detection of the all-CPUs-idle state means that larger systems
+	 will be slower to declare the all-CPUs-idle state.
+
+	 Say Y if you would like to help debug all-CPUs-idle detection.
+
+	 Say N if you are unsure.
+
 config NO_HZ
 	bool "Old Idle dynticks config"
 	depends on !ARCH_USES_GETTIMEOFFSET && GENERIC_CLOCKEVENTS
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index e77edc9..e8a1516 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -182,7 +182,8 @@ static bool can_stop_full_tick(void)
 		 * Don't allow the user to think they can get
 		 * full NO_HZ with this machine.
 		 */
-		WARN_ONCE(1, "NO_HZ FULL will not work with unstable sched clock");
+		WARN_ONCE(have_nohz_full_mask,
+			  "NO_HZ FULL will not work with unstable sched clock");
 		return false;
 	}
 #endif
@@ -343,8 +344,6 @@ static int tick_nohz_init_all(void)
 
 void __init tick_nohz_init(void)
 {
-	int cpu;
-
 	if (!have_nohz_full_mask) {
 		if (tick_nohz_init_all() < 0)
 			return;
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 3bdf283..61ed862 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -265,10 +265,9 @@ static inline void timer_list_header(struct seq_file *m, u64 now)
 static int timer_list_show(struct seq_file *m, void *v)
 {
 	struct timer_list_iter *iter = v;
-	u64 now = ktime_to_ns(ktime_get());
 
 	if (iter->cpu == -1 && !iter->second_pass)
-		timer_list_header(m, now);
+		timer_list_header(m, iter->now);
 	else if (!iter->second_pass)
 		print_cpu(m, iter->cpu, iter->now);
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -298,33 +297,41 @@ void sysrq_timer_list_show(void)
 	return;
 }
 
-static void *timer_list_start(struct seq_file *file, loff_t *offset)
+static void *move_iter(struct timer_list_iter *iter, loff_t offset)
 {
-	struct timer_list_iter *iter = file->private;
-
-	if (!*offset) {
-		iter->cpu = -1;
-		iter->now = ktime_to_ns(ktime_get());
-	} else if (iter->cpu >= nr_cpu_ids) {
+	for (; offset; offset--) {
+		iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
+		if (iter->cpu >= nr_cpu_ids) {
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-		if (!iter->second_pass) {
-			iter->cpu = -1;
-			iter->second_pass = true;
-		} else
-			return NULL;
+			if (!iter->second_pass) {
+				iter->cpu = -1;
+				iter->second_pass = true;
+			} else
+				return NULL;
 #else
-		return NULL;
+			return NULL;
 #endif
+		}
 	}
 	return iter;
 }
 
+static void *timer_list_start(struct seq_file *file, loff_t *offset)
+{
+	struct timer_list_iter *iter = file->private;
+
+	if (!*offset)
+		iter->now = ktime_to_ns(ktime_get());
+	iter->cpu = -1;
+	iter->second_pass = false;
+	return move_iter(iter, *offset);
+}
+
 static void *timer_list_next(struct seq_file *file, void *v, loff_t *offset)
 {
 	struct timer_list_iter *iter = file->private;
-	iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
 	++*offset;
-	return timer_list_start(file, offset);
+	return move_iter(iter, 1);
 }
 
 static void timer_list_stop(struct seq_file *seq, void *v)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8ce9eef..a6d098c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2169,12 +2169,57 @@ static cycle_t		ftrace_update_time;
 static unsigned long	ftrace_update_cnt;
 unsigned long		ftrace_update_tot_cnt;
 
-static int ops_traces_mod(struct ftrace_ops *ops)
+static inline int ops_traces_mod(struct ftrace_ops *ops)
 {
-	struct ftrace_hash *hash;
+	/*
+	 * Filter_hash being empty will default to trace module.
+	 * But notrace hash requires a test of individual module functions.
+	 */
+	return ftrace_hash_empty(ops->filter_hash) &&
+		ftrace_hash_empty(ops->notrace_hash);
+}
+
+/*
+ * Check if the current ops references the record.
+ *
+ * If the ops traces all functions, then it was already accounted for.
+ * If the ops does not trace the current record function, skip it.
+ * If the ops ignores the function via notrace filter, skip it.
+ */
+static inline bool
+ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec)
+{
+	/* If ops isn't enabled, ignore it */
+	if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
+		return 0;
+
+	/* If ops traces all mods, we already accounted for it */
+	if (ops_traces_mod(ops))
+		return 0;
+
+	/* The function must be in the filter */
+	if (!ftrace_hash_empty(ops->filter_hash) &&
+	    !ftrace_lookup_ip(ops->filter_hash, rec->ip))
+		return 0;
+
+	/* If in notrace hash, we ignore it too */
+	if (ftrace_lookup_ip(ops->notrace_hash, rec->ip))
+		return 0;
+
+	return 1;
+}
+
+static int referenced_filters(struct dyn_ftrace *rec)
+{
+	struct ftrace_ops *ops;
+	int cnt = 0;
 
-	hash = ops->filter_hash;
-	return ftrace_hash_empty(hash);
+	for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) {
+		if (ops_references_rec(ops, rec))
+		    cnt++;
+	}
+
+	return cnt;
 }
 
 static int ftrace_update_code(struct module *mod)
@@ -2183,6 +2228,7 @@ static int ftrace_update_code(struct module *mod)
 	struct dyn_ftrace *p;
 	cycle_t start, stop;
 	unsigned long ref = 0;
+	bool test = false;
 	int i;
 
 	/*
@@ -2196,9 +2242,12 @@ static int ftrace_update_code(struct module *mod)
 
 		for (ops = ftrace_ops_list;
 		     ops != &ftrace_list_end; ops = ops->next) {
-			if (ops->flags & FTRACE_OPS_FL_ENABLED &&
-			    ops_traces_mod(ops))
-				ref++;
+			if (ops->flags & FTRACE_OPS_FL_ENABLED) {
+				if (ops_traces_mod(ops))
+					ref++;
+				else
+					test = true;
+			}
 		}
 	}
 
@@ -2208,12 +2257,16 @@ static int ftrace_update_code(struct module *mod)
 	for (pg = ftrace_new_pgs; pg; pg = pg->next) {
 
 		for (i = 0; i < pg->index; i++) {
+			int cnt = ref;
+
 			/* If something went wrong, bail without enabling anything */
 			if (unlikely(ftrace_disabled))
 				return -1;
 
 			p = &pg->records[i];
-			p->flags = ref;
+			if (test)
+				cnt += referenced_filters(p);
+			p->flags = cnt;
 
 			/*
 			 * Do the initial record conversion from mcount jump
@@ -2233,7 +2286,7 @@ static int ftrace_update_code(struct module *mod)
 			 * conversion puts the module to the correct state, thus
 			 * passing the ftrace_make_call check.
 			 */
-			if (ftrace_start_up && ref) {
+			if (ftrace_start_up && cnt) {
 				int failed = __ftrace_replace_code(p, 1);
 				if (failed)
 					ftrace_bug(failed, p->ip);
@@ -3384,6 +3437,12 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
 	return add_hash_entry(hash, ip);
 }
 
+static void ftrace_ops_update_code(struct ftrace_ops *ops)
+{
+	if (ops->flags & FTRACE_OPS_FL_ENABLED && ftrace_enabled)
+		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
+}
+
 static int
 ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
 		unsigned long ip, int remove, int reset, int enable)
@@ -3426,9 +3485,8 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
 
 	mutex_lock(&ftrace_lock);
 	ret = ftrace_hash_move(ops, enable, orig_hash, hash);
-	if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
-	    && ftrace_enabled)
-		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
+	if (!ret)
+		ftrace_ops_update_code(ops);
 
 	mutex_unlock(&ftrace_lock);
 
@@ -3655,9 +3713,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
 		mutex_lock(&ftrace_lock);
 		ret = ftrace_hash_move(iter->ops, filter_hash,
 				       orig_hash, iter->hash);
-		if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
-		    && ftrace_enabled)
-			ftrace_run_update_code(FTRACE_UPDATE_CALLS);
+		if (!ret)
+			ftrace_ops_update_code(iter->ops);
 
 		mutex_unlock(&ftrace_lock);
 	}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 882ec1d..496f94d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -243,20 +243,25 @@ int filter_current_check_discard(struct ring_buffer *buffer,
 }
 EXPORT_SYMBOL_GPL(filter_current_check_discard);
 
-cycle_t ftrace_now(int cpu)
+cycle_t buffer_ftrace_now(struct trace_buffer *buf, int cpu)
 {
 	u64 ts;
 
 	/* Early boot up does not have a buffer yet */
-	if (!global_trace.trace_buffer.buffer)
+	if (!buf->buffer)
 		return trace_clock_local();
 
-	ts = ring_buffer_time_stamp(global_trace.trace_buffer.buffer, cpu);
-	ring_buffer_normalize_time_stamp(global_trace.trace_buffer.buffer, cpu, &ts);
+	ts = ring_buffer_time_stamp(buf->buffer, cpu);
+	ring_buffer_normalize_time_stamp(buf->buffer, cpu, &ts);
 
 	return ts;
 }
 
+cycle_t ftrace_now(int cpu)
+{
+	return buffer_ftrace_now(&global_trace.trace_buffer, cpu);
+}
+
 /**
  * tracing_is_enabled - Show if global_trace has been disabled
  *
@@ -1211,7 +1216,7 @@ void tracing_reset_online_cpus(struct trace_buffer *buf)
 	/* Make sure all commits have finished */
 	synchronize_sched();
 
-	buf->time_start = ftrace_now(buf->cpu);
+	buf->time_start = buffer_ftrace_now(buf, buf->cpu);
 
 	for_each_online_cpu(cpu)
 		ring_buffer_reset_cpu(buffer, cpu);
@@ -1219,11 +1224,6 @@ void tracing_reset_online_cpus(struct trace_buffer *buf)
 	ring_buffer_record_enable(buffer);
 }
 
-void tracing_reset_current(int cpu)
-{
-	tracing_reset(&global_trace.trace_buffer, cpu);
-}
-
 /* Must have trace_types_lock held */
 void tracing_reset_all_online_cpus(void)
 {
@@ -4151,6 +4151,7 @@ waitagain:
 	memset(&iter->seq, 0,
 	       sizeof(struct trace_iterator) -
 	       offsetof(struct trace_iterator, seq));
+	cpumask_clear(iter->started);
 	iter->pos = -1;
 
 	trace_event_read_lock();
@@ -4468,7 +4469,7 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp)
 
 	/* disable tracing ? */
 	if (trace_flags & TRACE_ITER_STOP_ON_FREE)
-		tracing_off();
+		tracer_tracing_off(tr);
 	/* resize the ring buffer to 0 */
 	tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS);
 
@@ -4633,12 +4634,12 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
 	 * New clock may not be consistent with the previous clock.
 	 * Reset the buffer so that it doesn't have incomparable timestamps.
 	 */
-	tracing_reset_online_cpus(&global_trace.trace_buffer);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 
 #ifdef CONFIG_TRACER_MAX_TRACE
 	if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer)
 		ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func);
-	tracing_reset_online_cpus(&global_trace.max_buffer);
+	tracing_reset_online_cpus(&tr->max_buffer);
 #endif
 
 	mutex_unlock(&trace_types_lock);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 898f868..29a7ebc 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -409,33 +409,42 @@ static void put_system(struct ftrace_subsystem_dir *dir)
 	mutex_unlock(&event_mutex);
 }
 
-/*
- * Open and update trace_array ref count.
- * Must have the current trace_array passed to it.
- */
-static int tracing_open_generic_file(struct inode *inode, struct file *filp)
+static void remove_subsystem(struct ftrace_subsystem_dir *dir)
 {
-	struct ftrace_event_file *file = inode->i_private;
-	struct trace_array *tr = file->tr;
-	int ret;
+	if (!dir)
+		return;
 
-	if (trace_array_get(tr) < 0)
-		return -ENODEV;
+	if (!--dir->nr_events) {
+		debugfs_remove_recursive(dir->entry);
+		list_del(&dir->list);
+		__put_system_dir(dir);
+	}
+}
 
-	ret = tracing_open_generic(inode, filp);
-	if (ret < 0)
-		trace_array_put(tr);
-	return ret;
+static void *event_file_data(struct file *filp)
+{
+	return ACCESS_ONCE(file_inode(filp)->i_private);
 }
 
-static int tracing_release_generic_file(struct inode *inode, struct file *filp)
+static void remove_event_file_dir(struct ftrace_event_file *file)
 {
-	struct ftrace_event_file *file = inode->i_private;
-	struct trace_array *tr = file->tr;
+	struct dentry *dir = file->dir;
+	struct dentry *child;
 
-	trace_array_put(tr);
+	if (dir) {
+		spin_lock(&dir->d_lock);	/* probably unneeded */
+		list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
+			if (child->d_inode)	/* probably unneeded */
+				child->d_inode->i_private = NULL;
+		}
+		spin_unlock(&dir->d_lock);
 
-	return 0;
+		debugfs_remove_recursive(dir);
+	}
+
+	list_del(&file->list);
+	remove_subsystem(file->system);
+	kmem_cache_free(file_cachep, file);
 }
 
 /*
@@ -679,15 +688,25 @@ static ssize_t
 event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		  loff_t *ppos)
 {
-	struct ftrace_event_file *file = filp->private_data;
+	struct ftrace_event_file *file;
+	unsigned long flags;
 	char buf[4] = "0";
 
-	if (file->flags & FTRACE_EVENT_FL_ENABLED &&
-	    !(file->flags & FTRACE_EVENT_FL_SOFT_DISABLED))
+	mutex_lock(&event_mutex);
+	file = event_file_data(filp);
+	if (likely(file))
+		flags = file->flags;
+	mutex_unlock(&event_mutex);
+
+	if (!file)
+		return -ENODEV;
+
+	if (flags & FTRACE_EVENT_FL_ENABLED &&
+	    !(flags & FTRACE_EVENT_FL_SOFT_DISABLED))
 		strcpy(buf, "1");
 
-	if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED ||
-	    file->flags & FTRACE_EVENT_FL_SOFT_MODE)
+	if (flags & FTRACE_EVENT_FL_SOFT_DISABLED ||
+	    flags & FTRACE_EVENT_FL_SOFT_MODE)
 		strcat(buf, "*");
 
 	strcat(buf, "\n");
@@ -699,13 +718,10 @@ static ssize_t
 event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		   loff_t *ppos)
 {
-	struct ftrace_event_file *file = filp->private_data;
+	struct ftrace_event_file *file;
 	unsigned long val;
 	int ret;
 
-	if (!file)
-		return -EINVAL;
-
 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
 	if (ret)
 		return ret;
@@ -717,8 +733,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	switch (val) {
 	case 0:
 	case 1:
+		ret = -ENODEV;
 		mutex_lock(&event_mutex);
-		ret = ftrace_event_enable_disable(file, val);
+		file = event_file_data(filp);
+		if (likely(file))
+			ret = ftrace_event_enable_disable(file, val);
 		mutex_unlock(&event_mutex);
 		break;
 
@@ -825,7 +844,7 @@ enum {
 
 static void *f_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct ftrace_event_call *call = m->private;
+	struct ftrace_event_call *call = event_file_data(m->private);
 	struct list_head *common_head = &ftrace_common_fields;
 	struct list_head *head = trace_get_fields(call);
 	struct list_head *node = v;
@@ -857,7 +876,7 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos)
 
 static int f_show(struct seq_file *m, void *v)
 {
-	struct ftrace_event_call *call = m->private;
+	struct ftrace_event_call *call = event_file_data(m->private);
 	struct ftrace_event_field *field;
 	const char *array_descriptor;
 
@@ -910,6 +929,11 @@ static void *f_start(struct seq_file *m, loff_t *pos)
 	void *p = (void *)FORMAT_HEADER;
 	loff_t l = 0;
 
+	/* ->stop() is called even if ->start() fails */
+	mutex_lock(&event_mutex);
+	if (!event_file_data(m->private))
+		return ERR_PTR(-ENODEV);
+
 	while (l < *pos && p)
 		p = f_next(m, p, &l);
 
@@ -918,6 +942,7 @@ static void *f_start(struct seq_file *m, loff_t *pos)
 
 static void f_stop(struct seq_file *m, void *p)
 {
+	mutex_unlock(&event_mutex);
 }
 
 static const struct seq_operations trace_format_seq_ops = {
@@ -929,7 +954,6 @@ static const struct seq_operations trace_format_seq_ops = {
 
 static int trace_format_open(struct inode *inode, struct file *file)
 {
-	struct ftrace_event_call *call = inode->i_private;
 	struct seq_file *m;
 	int ret;
 
@@ -938,7 +962,7 @@ static int trace_format_open(struct inode *inode, struct file *file)
 		return ret;
 
 	m = file->private_data;
-	m->private = call;
+	m->private = file;
 
 	return 0;
 }
@@ -946,14 +970,18 @@ static int trace_format_open(struct inode *inode, struct file *file)
 static ssize_t
 event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 {
-	struct ftrace_event_call *call = filp->private_data;
+	int id = (long)event_file_data(filp);
 	char buf[32];
 	int len;
 
 	if (*ppos)
 		return 0;
 
-	len = sprintf(buf, "%d\n", call->event.type);
+	if (unlikely(!id))
+		return -ENODEV;
+
+	len = sprintf(buf, "%d\n", id);
+
 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
 }
 
@@ -961,21 +989,28 @@ static ssize_t
 event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
 		  loff_t *ppos)
 {
-	struct ftrace_event_call *call = filp->private_data;
+	struct ftrace_event_call *call;
 	struct trace_seq *s;
-	int r;
+	int r = -ENODEV;
 
 	if (*ppos)
 		return 0;
 
 	s = kmalloc(sizeof(*s), GFP_KERNEL);
+
 	if (!s)
 		return -ENOMEM;
 
 	trace_seq_init(s);
 
-	print_event_filter(call, s);
-	r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+	mutex_lock(&event_mutex);
+	call = event_file_data(filp);
+	if (call)
+		print_event_filter(call, s);
+	mutex_unlock(&event_mutex);
+
+	if (call)
+		r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
 
 	kfree(s);
 
@@ -986,9 +1021,9 @@ static ssize_t
 event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		   loff_t *ppos)
 {
-	struct ftrace_event_call *call = filp->private_data;
+	struct ftrace_event_call *call;
 	char *buf;
-	int err;
+	int err = -ENODEV;
 
 	if (cnt >= PAGE_SIZE)
 		return -EINVAL;
@@ -1003,7 +1038,12 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	}
 	buf[cnt] = '\0';
 
-	err = apply_event_filter(call, buf);
+	mutex_lock(&event_mutex);
+	call = event_file_data(filp);
+	if (call)
+		err = apply_event_filter(call, buf);
+	mutex_unlock(&event_mutex);
+
 	free_page((unsigned long) buf);
 	if (err < 0)
 		return err;
@@ -1225,10 +1265,9 @@ static const struct file_operations ftrace_set_event_fops = {
 };
 
 static const struct file_operations ftrace_enable_fops = {
-	.open = tracing_open_generic_file,
+	.open = tracing_open_generic,
 	.read = event_enable_read,
 	.write = event_enable_write,
-	.release = tracing_release_generic_file,
 	.llseek = default_llseek,
 };
 
@@ -1240,7 +1279,6 @@ static const struct file_operations ftrace_event_format_fops = {
 };
 
 static const struct file_operations ftrace_event_id_fops = {
-	.open = tracing_open_generic,
 	.read = event_id_read,
 	.llseek = default_llseek,
 };
@@ -1488,8 +1526,8 @@ event_create_dir(struct dentry *parent,
 
 #ifdef CONFIG_PERF_EVENTS
 	if (call->event.type && call->class->reg)
-		trace_create_file("id", 0444, file->dir, call,
-		 		  id);
+		trace_create_file("id", 0444, file->dir,
+				  (void *)(long)call->event.type, id);
 #endif
 
 	/*
@@ -1514,33 +1552,16 @@ event_create_dir(struct dentry *parent,
 	return 0;
 }
 
-static void remove_subsystem(struct ftrace_subsystem_dir *dir)
-{
-	if (!dir)
-		return;
-
-	if (!--dir->nr_events) {
-		debugfs_remove_recursive(dir->entry);
-		list_del(&dir->list);
-		__put_system_dir(dir);
-	}
-}
-
 static void remove_event_from_tracers(struct ftrace_event_call *call)
 {
 	struct ftrace_event_file *file;
 	struct trace_array *tr;
 
 	do_for_each_event_file_safe(tr, file) {
-
 		if (file->event_call != call)
 			continue;
 
-		list_del(&file->list);
-		debugfs_remove_recursive(file->dir);
-		remove_subsystem(file->system);
-		kmem_cache_free(file_cachep, file);
-
+		remove_event_file_dir(file);
 		/*
 		 * The do_for_each_event_file_safe() is
 		 * a double loop. After finding the call for this
@@ -1692,16 +1713,53 @@ static void __trace_remove_event_call(struct ftrace_event_call *call)
 	destroy_preds(call);
 }
 
+static int probe_remove_event_call(struct ftrace_event_call *call)
+{
+	struct trace_array *tr;
+	struct ftrace_event_file *file;
+
+#ifdef CONFIG_PERF_EVENTS
+	if (call->perf_refcount)
+		return -EBUSY;
+#endif
+	do_for_each_event_file(tr, file) {
+		if (file->event_call != call)
+			continue;
+		/*
+		 * We can't rely on ftrace_event_enable_disable(enable => 0)
+		 * we are going to do, FTRACE_EVENT_FL_SOFT_MODE can suppress
+		 * TRACE_REG_UNREGISTER.
+		 */
+		if (file->flags & FTRACE_EVENT_FL_ENABLED)
+			return -EBUSY;
+		/*
+		 * The do_for_each_event_file_safe() is
+		 * a double loop. After finding the call for this
+		 * trace_array, we use break to jump to the next
+		 * trace_array.
+		 */
+		break;
+	} while_for_each_event_file();
+
+	__trace_remove_event_call(call);
+
+	return 0;
+}
+
 /* Remove an event_call */
-void trace_remove_event_call(struct ftrace_event_call *call)
+int trace_remove_event_call(struct ftrace_event_call *call)
 {
+	int ret;
+
 	mutex_lock(&trace_types_lock);
 	mutex_lock(&event_mutex);
 	down_write(&trace_event_sem);
-	__trace_remove_event_call(call);
+	ret = probe_remove_event_call(call);
 	up_write(&trace_event_sem);
 	mutex_unlock(&event_mutex);
 	mutex_unlock(&trace_types_lock);
+
+	return ret;
 }
 
 #define for_each_event(event, start, end)			\
@@ -2270,12 +2328,8 @@ __trace_remove_event_dirs(struct trace_array *tr)
 {
 	struct ftrace_event_file *file, *next;
 
-	list_for_each_entry_safe(file, next, &tr->events, list) {
-		list_del(&file->list);
-		debugfs_remove_recursive(file->dir);
-		remove_subsystem(file->system);
-		kmem_cache_free(file_cachep, file);
-	}
+	list_for_each_entry_safe(file, next, &tr->events, list)
+		remove_event_file_dir(file);
 }
 
 static void
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 0c7b75a..97daa8c 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -637,17 +637,15 @@ static void append_filter_err(struct filter_parse_state *ps,
 	free_page((unsigned long) buf);
 }
 
+/* caller must hold event_mutex */
 void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
 {
-	struct event_filter *filter;
+	struct event_filter *filter = call->filter;
 
-	mutex_lock(&event_mutex);
-	filter = call->filter;
 	if (filter && filter->filter_string)
 		trace_seq_printf(s, "%s\n", filter->filter_string);
 	else
 		trace_seq_puts(s, "none\n");
-	mutex_unlock(&event_mutex);
 }
 
 void print_subsystem_event_filter(struct event_subsystem *system,
@@ -1841,23 +1839,22 @@ static int create_system_filter(struct event_subsystem *system,
 	return err;
 }
 
+/* caller must hold event_mutex */
 int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
 {
 	struct event_filter *filter;
-	int err = 0;
-
-	mutex_lock(&event_mutex);
+	int err;
 
 	if (!strcmp(strstrip(filter_string), "0")) {
 		filter_disable(call);
 		filter = call->filter;
 		if (!filter)
-			goto out_unlock;
+			return 0;
 		RCU_INIT_POINTER(call->filter, NULL);
 		/* Make sure the filter is not being used */
 		synchronize_sched();
 		__free_filter(filter);
-		goto out_unlock;
+		return 0;
 	}
 
 	err = create_filter(call, filter_string, true, &filter);
@@ -1884,8 +1881,6 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
 			__free_filter(tmp);
 		}
 	}
-out_unlock:
-	mutex_unlock(&event_mutex);
 
 	return err;
 }
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 3811487..243f683 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -95,7 +95,7 @@ static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp)
 }
 
 static int register_probe_event(struct trace_probe *tp);
-static void unregister_probe_event(struct trace_probe *tp);
+static int unregister_probe_event(struct trace_probe *tp);
 
 static DEFINE_MUTEX(probe_lock);
 static LIST_HEAD(probe_list);
@@ -351,9 +351,12 @@ static int unregister_trace_probe(struct trace_probe *tp)
 	if (trace_probe_is_enabled(tp))
 		return -EBUSY;
 
+	/* Will fail if probe is being used by ftrace or perf */
+	if (unregister_probe_event(tp))
+		return -EBUSY;
+
 	__unregister_trace_probe(tp);
 	list_del(&tp->list);
-	unregister_probe_event(tp);
 
 	return 0;
 }
@@ -632,7 +635,9 @@ static int release_all_trace_probes(void)
 	/* TODO: Use batch unregistration */
 	while (!list_empty(&probe_list)) {
 		tp = list_entry(probe_list.next, struct trace_probe, list);
-		unregister_trace_probe(tp);
+		ret = unregister_trace_probe(tp);
+		if (ret)
+			goto end;
 		free_trace_probe(tp);
 	}
 
@@ -1247,11 +1252,15 @@ static int register_probe_event(struct trace_probe *tp)
 	return ret;
 }
 
-static void unregister_probe_event(struct trace_probe *tp)
+static int unregister_probe_event(struct trace_probe *tp)
 {
+	int ret;
+
 	/* tp->event is unregistered in trace_remove_event_call() */
-	trace_remove_event_call(&tp->call);
-	kfree(tp->call.print_fmt);
+	ret = trace_remove_event_call(&tp->call);
+	if (!ret)
+		kfree(tp->call.print_fmt);
+	return ret;
 }
 
 /* Make a debugfs interface for controlling probe points */
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index a23d2d7..272261b 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -70,7 +70,7 @@ struct trace_uprobe {
 	(sizeof(struct probe_arg) * (n)))
 
 static int register_uprobe_event(struct trace_uprobe *tu);
-static void unregister_uprobe_event(struct trace_uprobe *tu);
+static int unregister_uprobe_event(struct trace_uprobe *tu);
 
 static DEFINE_MUTEX(uprobe_lock);
 static LIST_HEAD(uprobe_list);
@@ -164,11 +164,17 @@ static struct trace_uprobe *find_probe_event(const char *event, const char *grou
 }
 
 /* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */
-static void unregister_trace_uprobe(struct trace_uprobe *tu)
+static int unregister_trace_uprobe(struct trace_uprobe *tu)
 {
+	int ret;
+
+	ret = unregister_uprobe_event(tu);
+	if (ret)
+		return ret;
+
 	list_del(&tu->list);
-	unregister_uprobe_event(tu);
 	free_trace_uprobe(tu);
+	return 0;
 }
 
 /* Register a trace_uprobe and probe_event */
@@ -181,9 +187,12 @@ static int register_trace_uprobe(struct trace_uprobe *tu)
 
 	/* register as an event */
 	old_tp = find_probe_event(tu->call.name, tu->call.class->system);
-	if (old_tp)
+	if (old_tp) {
 		/* delete old event */
-		unregister_trace_uprobe(old_tp);
+		ret = unregister_trace_uprobe(old_tp);
+		if (ret)
+			goto end;
+	}
 
 	ret = register_uprobe_event(tu);
 	if (ret) {
@@ -256,6 +265,8 @@ static int create_trace_uprobe(int argc, char **argv)
 		group = UPROBE_EVENT_SYSTEM;
 
 	if (is_delete) {
+		int ret;
+
 		if (!event) {
 			pr_info("Delete command needs an event name.\n");
 			return -EINVAL;
@@ -269,9 +280,9 @@ static int create_trace_uprobe(int argc, char **argv)
 			return -ENOENT;
 		}
 		/* delete an event */
-		unregister_trace_uprobe(tu);
+		ret = unregister_trace_uprobe(tu);
 		mutex_unlock(&uprobe_lock);
-		return 0;
+		return ret;
 	}
 
 	if (argc < 2) {
@@ -408,16 +419,20 @@ fail_address_parse:
 	return ret;
 }
 
-static void cleanup_all_probes(void)
+static int cleanup_all_probes(void)
 {
 	struct trace_uprobe *tu;
+	int ret = 0;
 
 	mutex_lock(&uprobe_lock);
 	while (!list_empty(&uprobe_list)) {
 		tu = list_entry(uprobe_list.next, struct trace_uprobe, list);
-		unregister_trace_uprobe(tu);
+		ret = unregister_trace_uprobe(tu);
+		if (ret)
+			break;
 	}
 	mutex_unlock(&uprobe_lock);
+	return ret;
 }
 
 /* Probes listing interfaces */
@@ -462,8 +477,13 @@ static const struct seq_operations probes_seq_op = {
 
 static int probes_open(struct inode *inode, struct file *file)
 {
-	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
-		cleanup_all_probes();
+	int ret;
+
+	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
+		ret = cleanup_all_probes();
+		if (ret)
+			return ret;
+	}
 
 	return seq_open(file, &probes_seq_op);
 }
@@ -968,12 +988,17 @@ static int register_uprobe_event(struct trace_uprobe *tu)
 	return ret;
 }
 
-static void unregister_uprobe_event(struct trace_uprobe *tu)
+static int unregister_uprobe_event(struct trace_uprobe *tu)
 {
+	int ret;
+
 	/* tu->event is unregistered in trace_remove_event_call() */
-	trace_remove_event_call(&tu->call);
+	ret = trace_remove_event_call(&tu->call);
+	if (ret)
+		return ret;
 	kfree(tu->call.print_fmt);
 	tu->call.print_fmt = NULL;
+	return 0;
 }
 
 /* Make a trace interface for controling probe points */
diff --git a/kernel/up.c b/kernel/up.c
index c54c75e..630d72b 100644
--- a/kernel/up.c
+++ b/kernel/up.c
@@ -10,12 +10,64 @@
 int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 				int wait)
 {
+	unsigned long flags;
+
 	WARN_ON(cpu != 0);
 
-	local_irq_disable();
-	(func)(info);
-	local_irq_enable();
+	local_irq_save(flags);
+	func(info);
+	local_irq_restore(flags);
 
 	return 0;
 }
 EXPORT_SYMBOL(smp_call_function_single);
+
+int on_each_cpu(smp_call_func_t func, void *info, int wait)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	func(info);
+	local_irq_restore(flags);
+	return 0;
+}
+EXPORT_SYMBOL(on_each_cpu);
+
+/*
+ * Note we still need to test the mask even for UP
+ * because we actually can get an empty mask from
+ * code that on SMP might call us without the local
+ * CPU in the mask.
+ */
+void on_each_cpu_mask(const struct cpumask *mask,
+		      smp_call_func_t func, void *info, bool wait)
+{
+	unsigned long flags;
+
+	if (cpumask_test_cpu(0, mask)) {
+		local_irq_save(flags);
+		func(info);
+		local_irq_restore(flags);
+	}
+}
+EXPORT_SYMBOL(on_each_cpu_mask);
+
+/*
+ * Preemption is disabled here to make sure the cond_func is called under the
+ * same condtions in UP and SMP.
+ */
+void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
+		      smp_call_func_t func, void *info, bool wait,
+		      gfp_t gfp_flags)
+{
+	unsigned long flags;
+
+	preempt_disable();
+	if (cond_func(0, info)) {
+		local_irq_save(flags);
+		func(info);
+		local_irq_restore(flags);
+	}
+	preempt_enable();
+}
+EXPORT_SYMBOL(on_each_cpu_cond);
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index d8c30db..9064b91 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -62,6 +62,9 @@ int create_user_ns(struct cred *new)
 	kgid_t group = new->egid;
 	int ret;
 
+	if (parent_ns->level > 32)
+		return -EUSERS;
+
 	/*
 	 * Verify that we can not violate the policy of which files
 	 * may be accessed that is specified by the root directory,
@@ -92,6 +95,7 @@ int create_user_ns(struct cred *new)
 	atomic_set(&ns->count, 1);
 	/* Leave the new->user_ns reference with the new user namespace. */
 	ns->parent = parent_ns;
+	ns->level = parent_ns->level + 1;
 	ns->owner = owner;
 	ns->group = group;
 
@@ -105,16 +109,21 @@ int create_user_ns(struct cred *new)
 int unshare_userns(unsigned long unshare_flags, struct cred **new_cred)
 {
 	struct cred *cred;
+	int err = -ENOMEM;
 
 	if (!(unshare_flags & CLONE_NEWUSER))
 		return 0;
 
 	cred = prepare_creds();
-	if (!cred)
-		return -ENOMEM;
+	if (cred) {
+		err = create_user_ns(cred);
+		if (err)
+			put_cred(cred);
+		else
+			*new_cred = cred;
+	}
 
-	*new_cred = cred;
-	return create_user_ns(cred);
+	return err;
 }
 
 void free_user_ns(struct user_namespace *ns)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 1241d8c..373d3e1 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -239,10 +239,12 @@ static void watchdog_overflow_callback(struct perf_event *event,
 		if (__this_cpu_read(hard_watchdog_warn) == true)
 			return;
 
-		if (hardlockup_panic)
+		if (hardlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
-		else
+		} else {
 			WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
+		}
 
 		__this_cpu_write(hard_watchdog_warn, true);
 		return;
@@ -323,8 +325,10 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 		else
 			dump_stack();
 
-		if (softlockup_panic)
+		if (softlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("softlockup: hung tasks");
+		}
 		__this_cpu_write(soft_watchdog_warn, true);
 	} else
 		__this_cpu_write(soft_watchdog_warn, false);
@@ -486,7 +490,52 @@ static struct smp_hotplug_thread watchdog_threads = {
 	.unpark			= watchdog_enable,
 };
 
-static int watchdog_enable_all_cpus(void)
+static void restart_watchdog_hrtimer(void *info)
+{
+	struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
+	int ret;
+
+	/*
+	 * No need to cancel and restart hrtimer if it is currently executing
+	 * because it will reprogram itself with the new period now.
+	 * We should never see it unqueued here because we are running per-cpu
+	 * with interrupts disabled.
+	 */
+	ret = hrtimer_try_to_cancel(hrtimer);
+	if (ret == 1)
+		hrtimer_start(hrtimer, ns_to_ktime(sample_period),
+				HRTIMER_MODE_REL_PINNED);
+}
+
+static void update_timers(int cpu)
+{
+	struct call_single_data data = {.func = restart_watchdog_hrtimer};
+	/*
+	 * Make sure that perf event counter will adopt to a new
+	 * sampling period. Updating the sampling period directly would
+	 * be much nicer but we do not have an API for that now so
+	 * let's use a big hammer.
+	 * Hrtimer will adopt the new period on the next tick but this
+	 * might be late already so we have to restart the timer as well.
+	 */
+	watchdog_nmi_disable(cpu);
+	__smp_call_function_single(cpu, &data, 1);
+	watchdog_nmi_enable(cpu);
+}
+
+static void update_timers_all_cpus(void)
+{
+	int cpu;
+
+	get_online_cpus();
+	preempt_disable();
+	for_each_online_cpu(cpu)
+		update_timers(cpu);
+	preempt_enable();
+	put_online_cpus();
+}
+
+static int watchdog_enable_all_cpus(bool sample_period_changed)
 {
 	int err = 0;
 
@@ -496,6 +545,8 @@ static int watchdog_enable_all_cpus(void)
 			pr_err("Failed to create watchdog threads, disabled\n");
 		else
 			watchdog_running = 1;
+	} else if (sample_period_changed) {
+		update_timers_all_cpus();
 	}
 
 	return err;
@@ -520,13 +571,15 @@ int proc_dowatchdog(struct ctl_table *table, int write,
 		    void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int err, old_thresh, old_enabled;
+	static DEFINE_MUTEX(watchdog_proc_mutex);
 
+	mutex_lock(&watchdog_proc_mutex);
 	old_thresh = ACCESS_ONCE(watchdog_thresh);
 	old_enabled = ACCESS_ONCE(watchdog_user_enabled);
 
 	err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 	if (err || !write)
-		return err;
+		goto out;
 
 	set_sample_period();
 	/*
@@ -535,7 +588,7 @@ int proc_dowatchdog(struct ctl_table *table, int write,
 	 * watchdog_*_all_cpus() function takes care of this.
 	 */
 	if (watchdog_user_enabled && watchdog_thresh)
-		err = watchdog_enable_all_cpus();
+		err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh);
 	else
 		watchdog_disable_all_cpus();
 
@@ -544,7 +597,8 @@ int proc_dowatchdog(struct ctl_table *table, int write,
 		watchdog_thresh = old_thresh;
 		watchdog_user_enabled = old_enabled;
 	}
-
+out:
+	mutex_unlock(&watchdog_proc_mutex);
 	return err;
 }
 #endif /* CONFIG_SYSCTL */
@@ -553,14 +607,6 @@ void __init lockup_detector_init(void)
 {
 	set_sample_period();
 
-#ifdef CONFIG_NO_HZ_FULL
-	if (watchdog_user_enabled) {
-		watchdog_user_enabled = 0;
-		pr_warning("Disabled lockup detectors by default for full dynticks\n");
-		pr_warning("You can reactivate it with 'sysctl -w kernel.watchdog=1'\n");
-	}
-#endif
-
 	if (watchdog_user_enabled)
-		watchdog_enable_all_cpus();
+		watchdog_enable_all_cpus(false);
 }
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0b72e81..63341d9 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2817,6 +2817,19 @@ already_gone:
 	return false;
 }
 
+static bool __flush_work(struct work_struct *work)
+{
+	struct wq_barrier barr;
+
+	if (start_flush_work(work, &barr)) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+		return true;
+	} else {
+		return false;
+	}
+}
+
 /**
  * flush_work - wait for a work to finish executing the last queueing instance
  * @work: the work to flush
@@ -2830,18 +2843,10 @@ already_gone:
  */
 bool flush_work(struct work_struct *work)
 {
-	struct wq_barrier barr;
-
 	lock_map_acquire(&work->lockdep_map);
 	lock_map_release(&work->lockdep_map);
 
-	if (start_flush_work(work, &barr)) {
-		wait_for_completion(&barr.done);
-		destroy_work_on_stack(&barr.work);
-		return true;
-	} else {
-		return false;
-	}
+	return __flush_work(work);
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
@@ -2962,17 +2967,18 @@ bool cancel_delayed_work_sync(struct delayed_work *dwork)
 EXPORT_SYMBOL(cancel_delayed_work_sync);
 
 /**
- * schedule_on_each_cpu - execute a function synchronously on each online CPU
+ * schedule_on_cpu_mask - execute a function synchronously on each listed CPU
  * @func: the function to call
+ * @mask: the cpumask to invoke the function on
  *
- * schedule_on_each_cpu() executes @func on each online CPU using the
+ * schedule_on_cpu_mask() executes @func on each listed CPU using the
  * system workqueue and blocks until all CPUs have completed.
- * schedule_on_each_cpu() is very slow.
+ * schedule_on_cpu_mask() is very slow.
  *
  * RETURNS:
  * 0 on success, -errno on failure.
  */
-int schedule_on_each_cpu(work_func_t func)
+int schedule_on_cpu_mask(work_func_t func, const struct cpumask *mask)
 {
 	int cpu;
 	struct work_struct __percpu *works;
@@ -2981,24 +2987,41 @@ int schedule_on_each_cpu(work_func_t func)
 	if (!works)
 		return -ENOMEM;
 
-	get_online_cpus();
-
-	for_each_online_cpu(cpu) {
+	for_each_cpu(cpu, mask) {
 		struct work_struct *work = per_cpu_ptr(works, cpu);
 
 		INIT_WORK(work, func);
 		schedule_work_on(cpu, work);
 	}
 
-	for_each_online_cpu(cpu)
+	for_each_cpu(cpu, mask)
 		flush_work(per_cpu_ptr(works, cpu));
 
-	put_online_cpus();
 	free_percpu(works);
 	return 0;
 }
 
 /**
+ * schedule_on_each_cpu - execute a function synchronously on each online CPU
+ * @func: the function to call
+ *
+ * schedule_on_each_cpu() executes @func on each online CPU using the
+ * system workqueue and blocks until all CPUs have completed.
+ * schedule_on_each_cpu() is very slow.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int schedule_on_each_cpu(work_func_t func)
+{
+	int ret;
+	get_online_cpus();
+	ret = schedule_on_cpu_mask(func, cpu_online_mask);
+	put_online_cpus();
+	return ret;
+}
+
+/**
  * flush_scheduled_work - ensure that any scheduled work has run to completion.
  *
  * Forces execution of the kernel-global workqueue and blocks until its
@@ -3411,6 +3434,12 @@ static void copy_workqueue_attrs(struct workqueue_attrs *to,
 {
 	to->nice = from->nice;
 	cpumask_copy(to->cpumask, from->cpumask);
+	/*
+	 * Unlike hash and equality test, this function doesn't ignore
+	 * ->no_numa as it is used for both pool and wq attrs.  Instead,
+	 * get_unbound_pool() explicitly clears ->no_numa after copying.
+	 */
+	to->no_numa = from->no_numa;
 }
 
 /* hash value of the content of @attr */
@@ -3578,6 +3607,12 @@ static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
 	lockdep_set_subclass(&pool->lock, 1);	/* see put_pwq() */
 	copy_workqueue_attrs(pool->attrs, attrs);
 
+	/*
+	 * no_numa isn't a worker_pool attribute, always clear it.  See
+	 * 'struct workqueue_attrs' comments for detail.
+	 */
+	pool->attrs->no_numa = false;
+
 	/* if cpumask is contained inside a NUMA node, we belong to that node */
 	if (wq_numa_enabled) {
 		for_each_node(node) {
@@ -4756,7 +4791,14 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 
 	INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
 	schedule_work_on(cpu, &wfc.work);
-	flush_work(&wfc.work);
+
+	/*
+	 * The work item is on-stack and can't lead to deadlock through
+	 * flushing.  Use __flush_work() to avoid spurious lockdep warnings
+	 * when work_on_cpu()s are nested.
+	 */
+	__flush_work(&wfc.work);
+
 	return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);
diff --git a/lib/Kconfig b/lib/Kconfig
index 71d9f81..094a77e 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -172,6 +172,13 @@ config CRC8
 	  when they need to do cyclic redundancy check according CRC8
 	  algorithm. Module will be called crc8.
 
+config CRC64_ECMA
+	tristate "CRC64 ECMA function"
+	help
+	  This option provides CRC64 ECMA function. Drivers may select this
+	  when they need to do cyclic redundancy check according to the CRC64
+	  ECMA algorithm.
+
 config AUDIT_GENERIC
 	bool
 	depends on AUDIT && !AUDIT_ARCH
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1501aa5..2202a13 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -981,6 +981,25 @@ config DEBUG_KOBJECT
 	  If you say Y here, some extra kobject debugging messages will be sent
 	  to the syslog. 
 
+config DEBUG_KOBJECT_RELEASE
+	bool "kobject release debugging"
+	depends on DEBUG_KERNEL
+	help
+	  kobjects are reference counted objects.  This means that their
+	  last reference count put is not predictable, and the kobject can
+	  live on past the point at which a driver decides to drop it's
+	  initial reference to the kobject gained on allocation.  An
+	  example of this would be a struct device which has just been
+	  unregistered.
+
+	  However, some buggy drivers assume that after such an operation,
+	  the memory backing the kobject can be immediately freed.  This
+	  goes completely against the principles of a refcounted object.
+
+	  If you say Y here, the kernel will delay the release of kobjects
+	  on the last reference count to improve the visibility of this
+	  kind of kobject release bug.
+
 config HAVE_DEBUG_BUGVERBOSE
 	bool
 
@@ -1442,7 +1461,7 @@ config BACKTRACE_SELF_TEST
 
 config RBTREE_TEST
 	tristate "Red-Black tree test"
-	depends on m && DEBUG_KERNEL
+	depends on DEBUG_KERNEL
 	help
 	  A benchmark measuring the performance of the rbtree library.
 	  Also includes rbtree invariant checks.
diff --git a/lib/Makefile b/lib/Makefile
index 7baccfd..9e1e163 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_CRC7)	+= crc7.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
 obj-$(CONFIG_CRC8)	+= crc8.o
+obj-$(CONFIG_CRC64_ECMA)	+= crc64_ecma.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
diff --git a/lib/crc32.c b/lib/crc32.c
index 072fbd8..410093d 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -131,11 +131,14 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
 #endif
 
 /**
- * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
- * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *	other uses, or the previous crc32 value if computing incrementally.
- * @p: pointer to buffer over which CRC is run
+ * crc32_le_generic() - Calculate bitwise little-endian Ethernet AUTODIN II
+ *			CRC32/CRC32C
+ * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for other
+ *	 uses, or the previous crc32/crc32c value if computing incrementally.
+ * @p: pointer to buffer over which CRC32/CRC32C is run
  * @len: length of buffer @p
+ * @tab: little-endian Ethernet table
+ * @polynomial: CRC32/CRC32c LE polynomial
  */
 static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
 					  size_t len, const u32 (*tab)[256],
@@ -201,11 +204,13 @@ EXPORT_SYMBOL(crc32_le);
 EXPORT_SYMBOL(__crc32c_le);
 
 /**
- * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
+ * crc32_be_generic() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
  * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
  *	other uses, or the previous crc32 value if computing incrementally.
- * @p: pointer to buffer over which CRC is run
+ * @p: pointer to buffer over which CRC32 is run
  * @len: length of buffer @p
+ * @tab: big-endian Ethernet table
+ * @polynomial: CRC32 BE polynomial
  */
 static inline u32 __pure crc32_be_generic(u32 crc, unsigned char const *p,
 					  size_t len, const u32 (*tab)[256],
diff --git a/lib/crc64_ecma.c b/lib/crc64_ecma.c
new file mode 100644
index 0000000..41629ea
--- /dev/null
+++ b/lib/crc64_ecma.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/crc64_ecma.h>
+
+
+#define CRC64_BYTE_MASK			0xFF
+#define CRC64_TABLE_SIZE		256
+
+
+struct crc64_table {
+	u64 seed;
+	u64 table[CRC64_TABLE_SIZE];
+};
+
+
+static struct crc64_table CRC64_ECMA_182 = {
+	CRC64_DEFAULT_INITVAL,
+	{
+		0x0000000000000000ULL,
+		0xb32e4cbe03a75f6fULL,
+		0xf4843657a840a05bULL,
+		0x47aa7ae9abe7ff34ULL,
+		0x7bd0c384ff8f5e33ULL,
+		0xc8fe8f3afc28015cULL,
+		0x8f54f5d357cffe68ULL,
+		0x3c7ab96d5468a107ULL,
+		0xf7a18709ff1ebc66ULL,
+		0x448fcbb7fcb9e309ULL,
+		0x0325b15e575e1c3dULL,
+		0xb00bfde054f94352ULL,
+		0x8c71448d0091e255ULL,
+		0x3f5f08330336bd3aULL,
+		0x78f572daa8d1420eULL,
+		0xcbdb3e64ab761d61ULL,
+		0x7d9ba13851336649ULL,
+		0xceb5ed8652943926ULL,
+		0x891f976ff973c612ULL,
+		0x3a31dbd1fad4997dULL,
+		0x064b62bcaebc387aULL,
+		0xb5652e02ad1b6715ULL,
+		0xf2cf54eb06fc9821ULL,
+		0x41e11855055bc74eULL,
+		0x8a3a2631ae2dda2fULL,
+		0x39146a8fad8a8540ULL,
+		0x7ebe1066066d7a74ULL,
+		0xcd905cd805ca251bULL,
+		0xf1eae5b551a2841cULL,
+		0x42c4a90b5205db73ULL,
+		0x056ed3e2f9e22447ULL,
+		0xb6409f5cfa457b28ULL,
+		0xfb374270a266cc92ULL,
+		0x48190ecea1c193fdULL,
+		0x0fb374270a266cc9ULL,
+		0xbc9d3899098133a6ULL,
+		0x80e781f45de992a1ULL,
+		0x33c9cd4a5e4ecdceULL,
+		0x7463b7a3f5a932faULL,
+		0xc74dfb1df60e6d95ULL,
+		0x0c96c5795d7870f4ULL,
+		0xbfb889c75edf2f9bULL,
+		0xf812f32ef538d0afULL,
+		0x4b3cbf90f69f8fc0ULL,
+		0x774606fda2f72ec7ULL,
+		0xc4684a43a15071a8ULL,
+		0x83c230aa0ab78e9cULL,
+		0x30ec7c140910d1f3ULL,
+		0x86ace348f355aadbULL,
+		0x3582aff6f0f2f5b4ULL,
+		0x7228d51f5b150a80ULL,
+		0xc10699a158b255efULL,
+		0xfd7c20cc0cdaf4e8ULL,
+		0x4e526c720f7dab87ULL,
+		0x09f8169ba49a54b3ULL,
+		0xbad65a25a73d0bdcULL,
+		0x710d64410c4b16bdULL,
+		0xc22328ff0fec49d2ULL,
+		0x85895216a40bb6e6ULL,
+		0x36a71ea8a7ace989ULL,
+		0x0adda7c5f3c4488eULL,
+		0xb9f3eb7bf06317e1ULL,
+		0xfe5991925b84e8d5ULL,
+		0x4d77dd2c5823b7baULL,
+		0x64b62bcaebc387a1ULL,
+		0xd7986774e864d8ceULL,
+		0x90321d9d438327faULL,
+		0x231c512340247895ULL,
+		0x1f66e84e144cd992ULL,
+		0xac48a4f017eb86fdULL,
+		0xebe2de19bc0c79c9ULL,
+		0x58cc92a7bfab26a6ULL,
+		0x9317acc314dd3bc7ULL,
+		0x2039e07d177a64a8ULL,
+		0x67939a94bc9d9b9cULL,
+		0xd4bdd62abf3ac4f3ULL,
+		0xe8c76f47eb5265f4ULL,
+		0x5be923f9e8f53a9bULL,
+		0x1c4359104312c5afULL,
+		0xaf6d15ae40b59ac0ULL,
+		0x192d8af2baf0e1e8ULL,
+		0xaa03c64cb957be87ULL,
+		0xeda9bca512b041b3ULL,
+		0x5e87f01b11171edcULL,
+		0x62fd4976457fbfdbULL,
+		0xd1d305c846d8e0b4ULL,
+		0x96797f21ed3f1f80ULL,
+		0x2557339fee9840efULL,
+		0xee8c0dfb45ee5d8eULL,
+		0x5da24145464902e1ULL,
+		0x1a083bacedaefdd5ULL,
+		0xa9267712ee09a2baULL,
+		0x955cce7fba6103bdULL,
+		0x267282c1b9c65cd2ULL,
+		0x61d8f8281221a3e6ULL,
+		0xd2f6b4961186fc89ULL,
+		0x9f8169ba49a54b33ULL,
+		0x2caf25044a02145cULL,
+		0x6b055fede1e5eb68ULL,
+		0xd82b1353e242b407ULL,
+		0xe451aa3eb62a1500ULL,
+		0x577fe680b58d4a6fULL,
+		0x10d59c691e6ab55bULL,
+		0xa3fbd0d71dcdea34ULL,
+		0x6820eeb3b6bbf755ULL,
+		0xdb0ea20db51ca83aULL,
+		0x9ca4d8e41efb570eULL,
+		0x2f8a945a1d5c0861ULL,
+		0x13f02d374934a966ULL,
+		0xa0de61894a93f609ULL,
+		0xe7741b60e174093dULL,
+		0x545a57dee2d35652ULL,
+		0xe21ac88218962d7aULL,
+		0x5134843c1b317215ULL,
+		0x169efed5b0d68d21ULL,
+		0xa5b0b26bb371d24eULL,
+		0x99ca0b06e7197349ULL,
+		0x2ae447b8e4be2c26ULL,
+		0x6d4e3d514f59d312ULL,
+		0xde6071ef4cfe8c7dULL,
+		0x15bb4f8be788911cULL,
+		0xa6950335e42fce73ULL,
+		0xe13f79dc4fc83147ULL,
+		0x521135624c6f6e28ULL,
+		0x6e6b8c0f1807cf2fULL,
+		0xdd45c0b11ba09040ULL,
+		0x9aefba58b0476f74ULL,
+		0x29c1f6e6b3e0301bULL,
+		0xc96c5795d7870f42ULL,
+		0x7a421b2bd420502dULL,
+		0x3de861c27fc7af19ULL,
+		0x8ec62d7c7c60f076ULL,
+		0xb2bc941128085171ULL,
+		0x0192d8af2baf0e1eULL,
+		0x4638a2468048f12aULL,
+		0xf516eef883efae45ULL,
+		0x3ecdd09c2899b324ULL,
+		0x8de39c222b3eec4bULL,
+		0xca49e6cb80d9137fULL,
+		0x7967aa75837e4c10ULL,
+		0x451d1318d716ed17ULL,
+		0xf6335fa6d4b1b278ULL,
+		0xb199254f7f564d4cULL,
+		0x02b769f17cf11223ULL,
+		0xb4f7f6ad86b4690bULL,
+		0x07d9ba1385133664ULL,
+		0x4073c0fa2ef4c950ULL,
+		0xf35d8c442d53963fULL,
+		0xcf273529793b3738ULL,
+		0x7c0979977a9c6857ULL,
+		0x3ba3037ed17b9763ULL,
+		0x888d4fc0d2dcc80cULL,
+		0x435671a479aad56dULL,
+		0xf0783d1a7a0d8a02ULL,
+		0xb7d247f3d1ea7536ULL,
+		0x04fc0b4dd24d2a59ULL,
+		0x3886b22086258b5eULL,
+		0x8ba8fe9e8582d431ULL,
+		0xcc0284772e652b05ULL,
+		0x7f2cc8c92dc2746aULL,
+		0x325b15e575e1c3d0ULL,
+		0x8175595b76469cbfULL,
+		0xc6df23b2dda1638bULL,
+		0x75f16f0cde063ce4ULL,
+		0x498bd6618a6e9de3ULL,
+		0xfaa59adf89c9c28cULL,
+		0xbd0fe036222e3db8ULL,
+		0x0e21ac88218962d7ULL,
+		0xc5fa92ec8aff7fb6ULL,
+		0x76d4de52895820d9ULL,
+		0x317ea4bb22bfdfedULL,
+		0x8250e80521188082ULL,
+		0xbe2a516875702185ULL,
+		0x0d041dd676d77eeaULL,
+		0x4aae673fdd3081deULL,
+		0xf9802b81de97deb1ULL,
+		0x4fc0b4dd24d2a599ULL,
+		0xfceef8632775faf6ULL,
+		0xbb44828a8c9205c2ULL,
+		0x086ace348f355aadULL,
+		0x34107759db5dfbaaULL,
+		0x873e3be7d8faa4c5ULL,
+		0xc094410e731d5bf1ULL,
+		0x73ba0db070ba049eULL,
+		0xb86133d4dbcc19ffULL,
+		0x0b4f7f6ad86b4690ULL,
+		0x4ce50583738cb9a4ULL,
+		0xffcb493d702be6cbULL,
+		0xc3b1f050244347ccULL,
+		0x709fbcee27e418a3ULL,
+		0x3735c6078c03e797ULL,
+		0x841b8ab98fa4b8f8ULL,
+		0xadda7c5f3c4488e3ULL,
+		0x1ef430e13fe3d78cULL,
+		0x595e4a08940428b8ULL,
+		0xea7006b697a377d7ULL,
+		0xd60abfdbc3cbd6d0ULL,
+		0x6524f365c06c89bfULL,
+		0x228e898c6b8b768bULL,
+		0x91a0c532682c29e4ULL,
+		0x5a7bfb56c35a3485ULL,
+		0xe955b7e8c0fd6beaULL,
+		0xaeffcd016b1a94deULL,
+		0x1dd181bf68bdcbb1ULL,
+		0x21ab38d23cd56ab6ULL,
+		0x9285746c3f7235d9ULL,
+		0xd52f0e859495caedULL,
+		0x6601423b97329582ULL,
+		0xd041dd676d77eeaaULL,
+		0x636f91d96ed0b1c5ULL,
+		0x24c5eb30c5374ef1ULL,
+		0x97eba78ec690119eULL,
+		0xab911ee392f8b099ULL,
+		0x18bf525d915feff6ULL,
+		0x5f1528b43ab810c2ULL,
+		0xec3b640a391f4fadULL,
+		0x27e05a6e926952ccULL,
+		0x94ce16d091ce0da3ULL,
+		0xd3646c393a29f297ULL,
+		0x604a2087398eadf8ULL,
+		0x5c3099ea6de60cffULL,
+		0xef1ed5546e415390ULL,
+		0xa8b4afbdc5a6aca4ULL,
+		0x1b9ae303c601f3cbULL,
+		0x56ed3e2f9e224471ULL,
+		0xe5c372919d851b1eULL,
+		0xa26908783662e42aULL,
+		0x114744c635c5bb45ULL,
+		0x2d3dfdab61ad1a42ULL,
+		0x9e13b115620a452dULL,
+		0xd9b9cbfcc9edba19ULL,
+		0x6a978742ca4ae576ULL,
+		0xa14cb926613cf817ULL,
+		0x1262f598629ba778ULL,
+		0x55c88f71c97c584cULL,
+		0xe6e6c3cfcadb0723ULL,
+		0xda9c7aa29eb3a624ULL,
+		0x69b2361c9d14f94bULL,
+		0x2e184cf536f3067fULL,
+		0x9d36004b35545910ULL,
+		0x2b769f17cf112238ULL,
+		0x9858d3a9ccb67d57ULL,
+		0xdff2a94067518263ULL,
+		0x6cdce5fe64f6dd0cULL,
+		0x50a65c93309e7c0bULL,
+		0xe388102d33392364ULL,
+		0xa4226ac498dedc50ULL,
+		0x170c267a9b79833fULL,
+		0xdcd7181e300f9e5eULL,
+		0x6ff954a033a8c131ULL,
+		0x28532e49984f3e05ULL,
+		0x9b7d62f79be8616aULL,
+		0xa707db9acf80c06dULL,
+		0x14299724cc279f02ULL,
+		0x5383edcd67c06036ULL,
+		0xe0ada17364673f59ULL
+	}
+};
+
+
+/*
+ * crc64_ecma_seed - Initializes the CRC64 ECMA seed.
+ */
+u64 crc64_ecma_seed(void)
+{
+	return CRC64_ECMA_182.seed;
+}
+EXPORT_SYMBOL(crc64_ecma_seed);
+
+/*
+ * crc64_ecma - Computes the 64 bit ECMA CRC.
+ *
+ * pdata: pointer to the data to compute checksum for.
+ * nbytes: number of bytes in data buffer.
+ * seed: CRC seed.
+ */
+u64 crc64_ecma(u8 const *pdata, u32 nbytes, u64 seed)
+{
+	unsigned int i;
+	u64 crc = seed;
+
+	for (i = 0; i < nbytes; i++)
+		crc = CRC64_ECMA_182.table[(crc ^ pdata[i]) & CRC64_BYTE_MASK] ^
+			(crc >> 8);
+
+	return crc;
+}
+EXPORT_SYMBOL(crc64_ecma);
+
+MODULE_DESCRIPTION("CRC64 ECMA function");
+MODULE_AUTHOR("Freescale Semiconductor Inc.");
+MODULE_LICENSE("GPL");
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 37061ed..bf2c8b1 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -381,19 +381,21 @@ void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
  * debug_object_activate - debug checks when an object is activated
  * @addr:	address of the object
  * @descr:	pointer to an object specific debug description structure
+ * Returns 0 for success, -EINVAL for check failed.
  */
-void debug_object_activate(void *addr, struct debug_obj_descr *descr)
+int debug_object_activate(void *addr, struct debug_obj_descr *descr)
 {
 	enum debug_obj_state state;
 	struct debug_bucket *db;
 	struct debug_obj *obj;
 	unsigned long flags;
+	int ret;
 	struct debug_obj o = { .object = addr,
 			       .state = ODEBUG_STATE_NOTAVAILABLE,
 			       .descr = descr };
 
 	if (!debug_objects_enabled)
-		return;
+		return 0;
 
 	db = get_bucket((unsigned long) addr);
 
@@ -405,23 +407,26 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr)
 		case ODEBUG_STATE_INIT:
 		case ODEBUG_STATE_INACTIVE:
 			obj->state = ODEBUG_STATE_ACTIVE;
+			ret = 0;
 			break;
 
 		case ODEBUG_STATE_ACTIVE:
 			debug_print_object(obj, "activate");
 			state = obj->state;
 			raw_spin_unlock_irqrestore(&db->lock, flags);
-			debug_object_fixup(descr->fixup_activate, addr, state);
-			return;
+			ret = debug_object_fixup(descr->fixup_activate, addr, state);
+			return ret ? -EINVAL : 0;
 
 		case ODEBUG_STATE_DESTROYED:
 			debug_print_object(obj, "activate");
+			ret = -EINVAL;
 			break;
 		default:
+			ret = 0;
 			break;
 		}
 		raw_spin_unlock_irqrestore(&db->lock, flags);
-		return;
+		return ret;
 	}
 
 	raw_spin_unlock_irqrestore(&db->lock, flags);
@@ -431,8 +436,11 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr)
 	 * true or not.
 	 */
 	if (debug_object_fixup(descr->fixup_activate, addr,
-			   ODEBUG_STATE_NOTAVAILABLE))
+			   ODEBUG_STATE_NOTAVAILABLE)) {
 		debug_print_object(&o, "activate");
+		return -EINVAL;
+	}
+	return 0;
 }
 
 /**
diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c
index 19ff89e..d619b28 100644
--- a/lib/decompress_inflate.c
+++ b/lib/decompress_inflate.c
@@ -48,7 +48,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len,
 		out_len = 0x8000; /* 32 K */
 		out_buf = malloc(out_len);
 	} else {
-		out_len = 0x7fffffff; /* no limit */
+		out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
 	}
 	if (!out_buf) {
 		error("Out of memory while allocating output buffer");
diff --git a/lib/genalloc.c b/lib/genalloc.c
index b35cfa9..1d1f82b 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -519,7 +519,6 @@ struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order,
 /**
  * dev_get_gen_pool - Obtain the gen_pool (if any) for a device
  * @dev: device to retrieve the gen_pool from
- * @name: Optional name for the gen_pool, usually NULL
  *
  * Returns the gen_pool for the device if one is present, or NULL.
  */
diff --git a/lib/kobject.c b/lib/kobject.c
index 4a1f33d..1d46c15 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -545,8 +545,8 @@ static void kobject_cleanup(struct kobject *kobj)
 	struct kobj_type *t = get_ktype(kobj);
 	const char *name = kobj->name;
 
-	pr_debug("kobject: '%s' (%p): %s\n",
-		 kobject_name(kobj), kobj, __func__);
+	pr_debug("kobject: '%s' (%p): %s, parent %p\n",
+		 kobject_name(kobj), kobj, __func__, kobj->parent);
 
 	if (t && !t->release)
 		pr_debug("kobject: '%s' (%p): does not have a release() "
@@ -580,9 +580,25 @@ static void kobject_cleanup(struct kobject *kobj)
 	}
 }
 
+#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
+static void kobject_delayed_cleanup(struct work_struct *work)
+{
+	kobject_cleanup(container_of(to_delayed_work(work),
+				     struct kobject, release));
+}
+#endif
+
 static void kobject_release(struct kref *kref)
 {
-	kobject_cleanup(container_of(kref, struct kobject, kref));
+	struct kobject *kobj = container_of(kref, struct kobject, kref);
+#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
+	pr_debug("kobject: '%s' (%p): %s, parent %p (delayed)\n",
+		 kobject_name(kobj), kobj, __func__, kobj->parent);
+	INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
+	schedule_delayed_work(&kobj->release, HZ);
+#else
+	kobject_cleanup(kobj);
+#endif
 }
 
 /**
diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c
index d3414ea..4c069b2 100644
--- a/lib/lz4/lz4_decompress.c
+++ b/lib/lz4/lz4_decompress.c
@@ -283,8 +283,8 @@ _output_error:
 	return (int) (-(((char *) ip) - source));
 }
 
-int lz4_decompress(const char *src, size_t *src_len, char *dest,
-		size_t actual_dest_len)
+int lz4_decompress(const unsigned char *src, size_t *src_len,
+		unsigned char *dest, size_t actual_dest_len)
 {
 	int ret = -1;
 	int input_len = 0;
@@ -302,8 +302,8 @@ exit_0:
 EXPORT_SYMBOL_GPL(lz4_decompress);
 #endif
 
-int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
-		char *dest, size_t *dest_len)
+int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len,
+		unsigned char *dest, size_t *dest_len)
 {
 	int ret = -1;
 	int out_len = 0;
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
index 569985d..e3edc5f 100644
--- a/lib/lzo/lzo1x_decompress_safe.c
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -72,9 +72,11 @@ copy_literal_run:
 						COPY8(op, ip);
 						op += 8;
 						ip += 8;
+#  if !defined(__arm__)
 						COPY8(op, ip);
 						op += 8;
 						ip += 8;
+#  endif
 					} while (ip < ie);
 					ip = ie;
 					op = oe;
@@ -159,9 +161,11 @@ copy_literal_run:
 					COPY8(op, m_pos);
 					op += 8;
 					m_pos += 8;
+#  if !defined(__arm__)
 					COPY8(op, m_pos);
 					op += 8;
 					m_pos += 8;
+#  endif
 				} while (op < oe);
 				op = oe;
 				if (HAVE_IP(6)) {
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index 6710b83..db756cc 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -12,8 +12,14 @@
  */
 
 
+#if 1 && defined(__arm__) && ((__LINUX_ARM_ARCH__ >= 6) || defined(__ARM_FEATURE_UNALIGNED))
+#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
+#define COPY4(dst, src)	\
+		* (u32 *) (void *) (dst) = * (const u32 *) (const void *) (src)
+#else
 #define COPY4(dst, src)	\
 		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#endif
 #if defined(__x86_64__)
 #define COPY8(dst, src)	\
 		put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index e796429..7811ed3 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -32,6 +32,7 @@
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/rcupdate.h>
+#include <linux/hardirq.h>		/* in_interrupt() */
 
 
 #ifdef __KERNEL__
@@ -207,7 +208,12 @@ radix_tree_node_alloc(struct radix_tree_root *root)
 	struct radix_tree_node *ret = NULL;
 	gfp_t gfp_mask = root_gfp_mask(root);
 
-	if (!(gfp_mask & __GFP_WAIT)) {
+	/*
+	 * Preload code isn't irq safe and it doesn't make sence to use
+	 * preloading in the interrupt anyway as all the allocations have to
+	 * be atomic. So just do normal allocation when in interrupt.
+	 */
+	if (!(gfp_mask & __GFP_WAIT) && !in_interrupt()) {
 		struct radix_tree_preload *rtp;
 
 		/*
@@ -264,7 +270,7 @@ radix_tree_node_free(struct radix_tree_node *node)
  * To make use of this facility, the radix tree must be initialised without
  * __GFP_WAIT being passed to INIT_RADIX_TREE().
  */
-int radix_tree_preload(gfp_t gfp_mask)
+static int __radix_tree_preload(gfp_t gfp_mask)
 {
 	struct radix_tree_preload *rtp;
 	struct radix_tree_node *node;
@@ -288,9 +294,40 @@ int radix_tree_preload(gfp_t gfp_mask)
 out:
 	return ret;
 }
+
+/*
+ * Load up this CPU's radix_tree_node buffer with sufficient objects to
+ * ensure that the addition of a single element in the tree cannot fail.  On
+ * success, return zero, with preemption disabled.  On error, return -ENOMEM
+ * with preemption not disabled.
+ *
+ * To make use of this facility, the radix tree must be initialised without
+ * __GFP_WAIT being passed to INIT_RADIX_TREE().
+ */
+int radix_tree_preload(gfp_t gfp_mask)
+{
+	/* Warn on non-sensical use... */
+	WARN_ON_ONCE(!(gfp_mask & __GFP_WAIT));
+	return __radix_tree_preload(gfp_mask);
+}
 EXPORT_SYMBOL(radix_tree_preload);
 
 /*
+ * The same as above function, except we don't guarantee preloading happens.
+ * We do it, if we decide it helps. On success, return zero with preemption
+ * disabled. On error, return -ENOMEM with preemption not disabled.
+ */
+int radix_tree_maybe_preload(gfp_t gfp_mask)
+{
+	if (gfp_mask & __GFP_WAIT)
+		return __radix_tree_preload(gfp_mask);
+	/* Preloading doesn't help anything with this gfp mask, skip it */
+	preempt_disable();
+	return 0;
+}
+EXPORT_SYMBOL(radix_tree_maybe_preload);
+
+/*
  *	Return the maximum key which can be store into a
  *	radix tree with height HEIGHT.
  */
diff --git a/lib/raid6/.gitignore b/lib/raid6/.gitignore
index 162beca..0a7e494 100644
--- a/lib/raid6/.gitignore
+++ b/lib/raid6/.gitignore
@@ -2,3 +2,4 @@ mktables
 altivec*.c
 int*.c
 tables.c
+neon?.c
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 9f7c184..b462578 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -5,6 +5,7 @@ raid6_pq-y	+= algos.o recov.o tables.o int1.o int2.o int4.o \
 
 raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o
 raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o
+raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o
 
 hostprogs-y	+= mktables
 
@@ -16,6 +17,21 @@ ifeq ($(CONFIG_ALTIVEC),y)
 altivec_flags := -maltivec -mabi=altivec
 endif
 
+# The GCC option -ffreestanding is required in order to compile code containing
+# ARM/NEON intrinsics in a non C99-compliant environment (such as the kernel)
+ifeq ($(CONFIG_KERNEL_MODE_NEON),y)
+NEON_FLAGS := -ffreestanding
+ifeq ($(ARCH),arm)
+NEON_FLAGS += -mfloat-abi=softfp -mfpu=neon
+endif
+ifeq ($(ARCH),arm64)
+CFLAGS_REMOVE_neon1.o += -mgeneral-regs-only
+CFLAGS_REMOVE_neon2.o += -mgeneral-regs-only
+CFLAGS_REMOVE_neon4.o += -mgeneral-regs-only
+CFLAGS_REMOVE_neon8.o += -mgeneral-regs-only
+endif
+endif
+
 targets += int1.c
 $(obj)/int1.c:   UNROLL := 1
 $(obj)/int1.c:   $(src)/int.uc $(src)/unroll.awk FORCE
@@ -70,6 +86,30 @@ $(obj)/altivec8.c:   UNROLL := 8
 $(obj)/altivec8.c:   $(src)/altivec.uc $(src)/unroll.awk FORCE
 	$(call if_changed,unroll)
 
+CFLAGS_neon1.o += $(NEON_FLAGS)
+targets += neon1.c
+$(obj)/neon1.c:   UNROLL := 1
+$(obj)/neon1.c:   $(src)/neon.uc $(src)/unroll.awk FORCE
+	$(call if_changed,unroll)
+
+CFLAGS_neon2.o += $(NEON_FLAGS)
+targets += neon2.c
+$(obj)/neon2.c:   UNROLL := 2
+$(obj)/neon2.c:   $(src)/neon.uc $(src)/unroll.awk FORCE
+	$(call if_changed,unroll)
+
+CFLAGS_neon4.o += $(NEON_FLAGS)
+targets += neon4.c
+$(obj)/neon4.c:   UNROLL := 4
+$(obj)/neon4.c:   $(src)/neon.uc $(src)/unroll.awk FORCE
+	$(call if_changed,unroll)
+
+CFLAGS_neon8.o += $(NEON_FLAGS)
+targets += neon8.c
+$(obj)/neon8.c:   UNROLL := 8
+$(obj)/neon8.c:   $(src)/neon.uc $(src)/unroll.awk FORCE
+	$(call if_changed,unroll)
+
 quiet_cmd_mktable = TABLE   $@
       cmd_mktable = $(obj)/mktables > $@ || ( rm -f $@ && exit 1 )
 
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 6d7316f..74e6f56 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -70,6 +70,12 @@ const struct raid6_calls * const raid6_algos[] = {
 	&raid6_intx2,
 	&raid6_intx4,
 	&raid6_intx8,
+#ifdef CONFIG_KERNEL_MODE_NEON
+	&raid6_neonx1,
+	&raid6_neonx2,
+	&raid6_neonx4,
+	&raid6_neonx8,
+#endif
 	NULL
 };
 
diff --git a/lib/raid6/neon.c b/lib/raid6/neon.c
new file mode 100644
index 0000000..36ad470
--- /dev/null
+++ b/lib/raid6/neon.c
@@ -0,0 +1,58 @@
+/*
+ * linux/lib/raid6/neon.c - RAID6 syndrome calculation using ARM NEON intrinsics
+ *
+ * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/raid/pq.h>
+
+#ifdef __KERNEL__
+#include <asm/neon.h>
+#else
+#define kernel_neon_begin()
+#define kernel_neon_end()
+#define cpu_has_neon()		(1)
+#endif
+
+/*
+ * There are 2 reasons these wrappers are kept in a separate compilation unit
+ * from the actual implementations in neonN.c (generated from neon.uc by
+ * unroll.awk):
+ * - the actual implementations use NEON intrinsics, and the GCC support header
+ *   (arm_neon.h) is not fully compatible (type wise) with the kernel;
+ * - the neonN.c files are compiled with -mfpu=neon and optimization enabled,
+ *   and we have to make sure that we never use *any* NEON/VFP instructions
+ *   outside a kernel_neon_begin()/kernel_neon_end() pair.
+ */
+
+#define RAID6_NEON_WRAPPER(_n)						\
+	static void raid6_neon ## _n ## _gen_syndrome(int disks,	\
+					size_t bytes, void **ptrs)	\
+	{								\
+		void raid6_neon ## _n  ## _gen_syndrome_real(int,	\
+						unsigned long, void**);	\
+		kernel_neon_begin();					\
+		raid6_neon ## _n ## _gen_syndrome_real(disks,		\
+					(unsigned long)bytes, ptrs);	\
+		kernel_neon_end();					\
+	}								\
+	struct raid6_calls const raid6_neonx ## _n = {			\
+		raid6_neon ## _n ## _gen_syndrome,			\
+		raid6_have_neon,					\
+		"neonx" #_n,						\
+		0							\
+	}
+
+static int raid6_have_neon(void)
+{
+	return cpu_has_neon();
+}
+
+RAID6_NEON_WRAPPER(1);
+RAID6_NEON_WRAPPER(2);
+RAID6_NEON_WRAPPER(4);
+RAID6_NEON_WRAPPER(8);
diff --git a/lib/raid6/neon.uc b/lib/raid6/neon.uc
new file mode 100644
index 0000000..1b9ed79
--- /dev/null
+++ b/lib/raid6/neon.uc
@@ -0,0 +1,80 @@
+/* -----------------------------------------------------------------------
+ *
+ *   neon.uc - RAID-6 syndrome calculation using ARM NEON instructions
+ *
+ *   Copyright (C) 2012 Rob Herring
+ *
+ *   Based on altivec.uc:
+ *     Copyright 2002-2004 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * neon$#.c
+ *
+ * $#-way unrolled NEON intrinsics math RAID-6 instruction set
+ *
+ * This file is postprocessed using unroll.awk
+ */
+
+#include <arm_neon.h>
+
+typedef uint8x16_t unative_t;
+
+#define NBYTES(x) ((unative_t){x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
+#define NSIZE	sizeof(unative_t)
+
+/*
+ * The SHLBYTE() operation shifts each byte left by 1, *not*
+ * rolling over into the next byte
+ */
+static inline unative_t SHLBYTE(unative_t v)
+{
+	return vshlq_n_u8(v, 1);
+}
+
+/*
+ * The MASK() operation returns 0xFF in any byte for which the high
+ * bit is 1, 0x00 for any byte for which the high bit is 0.
+ */
+static inline unative_t MASK(unative_t v)
+{
+	const uint8x16_t temp = NBYTES(0);
+	return (unative_t)vcltq_s8((int8x16_t)v, (int8x16_t)temp);
+}
+
+void raid6_neon$#_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
+{
+	uint8_t **dptr = (uint8_t **)ptrs;
+	uint8_t *p, *q;
+	int d, z, z0;
+
+	register unative_t wd$$, wq$$, wp$$, w1$$, w2$$;
+	const unative_t x1d = NBYTES(0x1d);
+
+	z0 = disks - 3;		/* Highest data disk */
+	p = dptr[z0+1];		/* XOR parity */
+	q = dptr[z0+2];		/* RS syndrome */
+
+	for ( d = 0 ; d < bytes ; d += NSIZE*$# ) {
+		wq$$ = wp$$ = vld1q_u8(&dptr[z0][d+$$*NSIZE]);
+		for ( z = z0-1 ; z >= 0 ; z-- ) {
+			wd$$ = vld1q_u8(&dptr[z][d+$$*NSIZE]);
+			wp$$ = veorq_u8(wp$$, wd$$);
+			w2$$ = MASK(wq$$);
+			w1$$ = SHLBYTE(wq$$);
+
+			w2$$ = vandq_u8(w2$$, x1d);
+			w1$$ = veorq_u8(w1$$, w2$$);
+			wq$$ = veorq_u8(w1$$, wd$$);
+		}
+		vst1q_u8(&p[d+NSIZE*$$], wp$$);
+		vst1q_u8(&q[d+NSIZE*$$], wq$$);
+	}
+}
diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile
index 087332d..28afa1a 100644
--- a/lib/raid6/test/Makefile
+++ b/lib/raid6/test/Makefile
@@ -22,11 +22,23 @@ ifeq ($(ARCH),x86_64)
         IS_X86 = yes
 endif
 
+ifeq ($(ARCH),arm)
+        CFLAGS += -I../../../arch/arm/include -mfpu=neon
+        HAS_NEON = yes
+endif
+ifeq ($(ARCH),arm64)
+        CFLAGS += -I../../../arch/arm64/include
+        HAS_NEON = yes
+endif
+
 ifeq ($(IS_X86),yes)
         OBJS   += mmx.o sse1.o sse2.o avx2.o recov_ssse3.o recov_avx2.o
         CFLAGS += $(shell echo "vpbroadcastb %xmm0, %ymm1" |	\
                     gcc -c -x assembler - >&/dev/null &&	\
                     rm ./-.o && echo -DCONFIG_AS_AVX2=1)
+else ifeq ($(HAS_NEON),yes)
+        OBJS   += neon.o neon1.o neon2.o neon4.o neon8.o
+        CFLAGS += -DCONFIG_KERNEL_MODE_NEON=1
 else
         HAS_ALTIVEC := $(shell echo -e '\#include <altivec.h>\nvector int a;' |\
                          gcc -c -x c - >&/dev/null && \
@@ -55,6 +67,18 @@ raid6.a: $(OBJS)
 raid6test: test.c raid6.a
 	$(CC) $(CFLAGS) -o raid6test $^
 
+neon1.c: neon.uc ../unroll.awk
+	$(AWK) ../unroll.awk -vN=1 < neon.uc > $@
+
+neon2.c: neon.uc ../unroll.awk
+	$(AWK) ../unroll.awk -vN=2 < neon.uc > $@
+
+neon4.c: neon.uc ../unroll.awk
+	$(AWK) ../unroll.awk -vN=4 < neon.uc > $@
+
+neon8.c: neon.uc ../unroll.awk
+	$(AWK) ../unroll.awk -vN=8 < neon.uc > $@
+
 altivec1.c: altivec.uc ../unroll.awk
 	$(AWK) ../unroll.awk -vN=1 < altivec.uc > $@
 
@@ -89,7 +113,7 @@ tables.c: mktables
 	./mktables > tables.c
 
 clean:
-	rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c tables.c raid6test
+	rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c neon*.c tables.c raid6test
 
 spotless: clean
 	rm -f *~
diff --git a/lib/rbtree.c b/lib/rbtree.c
index c0e31fe..65f4eff 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -518,3 +518,43 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,
 	*new = *victim;
 }
 EXPORT_SYMBOL(rb_replace_node);
+
+static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
+{
+	for (;;) {
+		if (node->rb_left)
+			node = node->rb_left;
+		else if (node->rb_right)
+			node = node->rb_right;
+		else
+			return (struct rb_node *)node;
+	}
+}
+
+struct rb_node *rb_next_postorder(const struct rb_node *node)
+{
+	const struct rb_node *parent;
+	if (!node)
+		return NULL;
+	parent = rb_parent(node);
+
+	/* If we're sitting on node, we've already seen our children */
+	if (parent && node == parent->rb_left && parent->rb_right) {
+		/* If we are the parent's left node, go to the parent's right
+		 * node then all the way down to the left */
+		return rb_left_deepest_node(parent->rb_right);
+	} else
+		/* Otherwise we are the parent's right node, and the parent
+		 * should be next */
+		return (struct rb_node *)parent;
+}
+EXPORT_SYMBOL(rb_next_postorder);
+
+struct rb_node *rb_first_postorder(const struct rb_root *root)
+{
+	if (!root->rb_node)
+		return NULL;
+
+	return rb_left_deepest_node(root->rb_node);
+}
+EXPORT_SYMBOL(rb_first_postorder);
diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c
index 122f02f..31dd4cc 100644
--- a/lib/rbtree_test.c
+++ b/lib/rbtree_test.c
@@ -114,6 +114,16 @@ static int black_path_count(struct rb_node *rb)
 	return count;
 }
 
+static void check_postorder(int nr_nodes)
+{
+	struct rb_node *rb;
+	int count = 0;
+	for (rb = rb_first_postorder(&root); rb; rb = rb_next_postorder(rb))
+		count++;
+
+	WARN_ON_ONCE(count != nr_nodes);
+}
+
 static void check(int nr_nodes)
 {
 	struct rb_node *rb;
@@ -136,6 +146,8 @@ static void check(int nr_nodes)
 
 	WARN_ON_ONCE(count != nr_nodes);
 	WARN_ON_ONCE(count < (1 << black_path_count(rb_last(&root))) - 1);
+
+	check_postorder(nr_nodes);
 }
 
 static void check_augmented(int nr_nodes)
diff --git a/localversion-next b/localversion-next
new file mode 100644
index 0000000..edf40e0
--- /dev/null
+++ b/localversion-next
@@ -0,0 +1 @@
+-next-20130809
diff --git a/mm/Kconfig b/mm/Kconfig
index 8028dcc..256bfd0 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -519,3 +519,27 @@ config MEM_SOFT_DIRTY
 	  it can be cleared by hands.
 
 	  See Documentation/vm/soft-dirty.txt for more details.
+
+config CMA
+	bool "Contiguous Memory Allocator"
+	depends on HAVE_MEMBLOCK
+	select MIGRATION
+	select MEMORY_ISOLATION
+	help
+	  This enables the Contiguous Memory Allocator which allows other
+	  subsystems to allocate big physically-contiguous blocks of memory.
+	  CMA reserves a region of memory and allows only movable pages to
+	  be allocated from it. This way, the kernel can use the memory for
+	  pagecache and when a subsystem requests for contiguous area, the
+	  allocated pages are migrated away to serve the contiguous request.
+
+	  If unsure, say "n".
+
+config CMA_DEBUG
+	bool "CMA debug messages (DEVELOPMENT)"
+	depends on DEBUG_KERNEL && CMA
+	help
+	  Turns on debug messages in CMA.  This produces KERN_DEBUG
+	  messages for every CMA call as well as various messages while
+	  processing calls such as dma_alloc_from_contiguous().
+	  This option does not affect warning and error messages.
diff --git a/mm/Makefile b/mm/Makefile
index f008033..305d10a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -17,7 +17,7 @@ obj-y			:= filemap.o mempool.o oom_kill.o fadvise.o \
 			   util.o mmzone.o vmstat.o backing-dev.o \
 			   mm_init.o mmu_context.o percpu.o slab_common.o \
 			   compaction.o balloon_compaction.o \
-			   interval_tree.o $(mmu-y)
+			   interval_tree.o list_lru.o $(mmu-y)
 
 obj-y += init-mm.o
 
diff --git a/mm/filemap.c b/mm/filemap.c
index 4b51ac1..0c9feec 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -467,32 +467,34 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 	error = mem_cgroup_cache_charge(page, current->mm,
 					gfp_mask & GFP_RECLAIM_MASK);
 	if (error)
-		goto out;
-
-	error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
-	if (error == 0) {
-		page_cache_get(page);
-		page->mapping = mapping;
-		page->index = offset;
+		return error;
 
-		spin_lock_irq(&mapping->tree_lock);
-		error = radix_tree_insert(&mapping->page_tree, offset, page);
-		if (likely(!error)) {
-			mapping->nrpages++;
-			__inc_zone_page_state(page, NR_FILE_PAGES);
-			spin_unlock_irq(&mapping->tree_lock);
-			trace_mm_filemap_add_to_page_cache(page);
-		} else {
-			page->mapping = NULL;
-			/* Leave page->index set: truncation relies upon it */
-			spin_unlock_irq(&mapping->tree_lock);
-			mem_cgroup_uncharge_cache_page(page);
-			page_cache_release(page);
-		}
-		radix_tree_preload_end();
-	} else
+	error = radix_tree_maybe_preload(gfp_mask & ~__GFP_HIGHMEM);
+	if (error) {
 		mem_cgroup_uncharge_cache_page(page);
-out:
+		return error;
+	}
+
+	page_cache_get(page);
+	page->mapping = mapping;
+	page->index = offset;
+
+	spin_lock_irq(&mapping->tree_lock);
+	error = radix_tree_insert(&mapping->page_tree, offset, page);
+	radix_tree_preload_end();
+	if (unlikely(error))
+		goto err_insert;
+	mapping->nrpages++;
+	__inc_zone_page_state(page, NR_FILE_PAGES);
+	spin_unlock_irq(&mapping->tree_lock);
+	trace_mm_filemap_add_to_page_cache(page);
+	return 0;
+err_insert:
+	page->mapping = NULL;
+	/* Leave page->index set: truncation relies upon it */
+	spin_unlock_irq(&mapping->tree_lock);
+	mem_cgroup_uncharge_cache_page(page);
+	page_cache_release(page);
 	return error;
 }
 EXPORT_SYMBOL(add_to_page_cache_locked);
@@ -637,6 +639,7 @@ void __lock_page(struct page *page)
 {
 	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
 
+	VM_BUG_ON(PageTail(page));
 	__wait_on_bit_lock(page_waitqueue(page), &wait, sleep_on_page,
 							TASK_UNINTERRUPTIBLE);
 }
@@ -646,6 +649,7 @@ int __lock_page_killable(struct page *page)
 {
 	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
 
+	VM_BUG_ON(PageTail(page));
 	return __wait_on_bit_lock(page_waitqueue(page), &wait,
 					sleep_on_page_killable, TASK_KILLABLE);
 }
@@ -1088,7 +1092,6 @@ static void shrink_readahead_size_eio(struct file *filp,
  * @filp:	the file to read
  * @ppos:	current file position
  * @desc:	read_descriptor
- * @actor:	read method
  *
  * This is a generic file read routine, and uses the
  * mapping->a_ops->readpage() function for the actual low-level stuff.
@@ -1097,7 +1100,7 @@ static void shrink_readahead_size_eio(struct file *filp,
  * of the logic when it comes to error handling etc.
  */
 static void do_generic_file_read(struct file *filp, loff_t *ppos,
-		read_descriptor_t *desc, read_actor_t actor)
+		read_descriptor_t *desc)
 {
 	struct address_space *mapping = filp->f_mapping;
 	struct inode *inode = mapping->host;
@@ -1198,13 +1201,14 @@ page_ok:
 		 * Ok, we have the page, and it's up-to-date, so
 		 * now we can copy it to user space...
 		 *
-		 * The actor routine returns how many bytes were actually used..
+		 * The file_read_actor routine returns how many bytes were
+		 * actually used..
 		 * NOTE! This may not be the same as how much of a user buffer
 		 * we filled up (we may be padding etc), so we can only update
 		 * "pos" here (the actor routine has to update the user buffer
 		 * pointers and the remaining count).
 		 */
-		ret = actor(desc, page, offset, nr);
+		ret = file_read_actor(desc, page, offset, nr);
 		offset += ret;
 		index += offset >> PAGE_CACHE_SHIFT;
 		offset &= ~PAGE_CACHE_MASK;
@@ -1477,7 +1481,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 		if (desc.count == 0)
 			continue;
 		desc.error = 0;
-		do_generic_file_read(filp, ppos, &desc, file_read_actor);
+		do_generic_file_read(filp, ppos, &desc);
 		retval += desc.written;
 		if (desc.error) {
 			retval = retval ?: desc.error;
@@ -1614,6 +1618,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct inode *inode = mapping->host;
 	pgoff_t offset = vmf->pgoff;
 	struct page *page;
+	bool memcg_oom;
 	pgoff_t size;
 	int ret = 0;
 
@@ -1622,7 +1627,11 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 		return VM_FAULT_SIGBUS;
 
 	/*
-	 * Do we have something in the page cache already?
+	 * Do we have something in the page cache already?  Either
+	 * way, try readahead, but disable the memcg OOM killer for it
+	 * as readahead is optional and no errors are propagated up
+	 * the fault stack.  The OOM killer is enabled while trying to
+	 * instantiate the faulting page individually below.
 	 */
 	page = find_get_page(mapping, offset);
 	if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
@@ -1630,10 +1639,14 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 		 * We found the page, so try async readahead before
 		 * waiting for the lock.
 		 */
+		memcg_oom = mem_cgroup_toggle_oom(false);
 		do_async_mmap_readahead(vma, ra, file, page, offset);
+		mem_cgroup_toggle_oom(memcg_oom);
 	} else if (!page) {
 		/* No page in the page cache at all */
+		memcg_oom = mem_cgroup_toggle_oom(false);
 		do_sync_mmap_readahead(vma, ra, file, offset);
+		mem_cgroup_toggle_oom(memcg_oom);
 		count_vm_event(PGMAJFAULT);
 		mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
 		ret = VM_FAULT_MAJOR;
diff --git a/mm/fremap.c b/mm/fremap.c
index 87da359..5bff081 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -57,17 +57,22 @@ static int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
 		unsigned long addr, unsigned long pgoff, pgprot_t prot)
 {
 	int err = -ENOMEM;
-	pte_t *pte;
+	pte_t *pte, ptfile;
 	spinlock_t *ptl;
 
 	pte = get_locked_pte(mm, addr, &ptl);
 	if (!pte)
 		goto out;
 
-	if (!pte_none(*pte))
+	ptfile = pgoff_to_pte(pgoff);
+
+	if (!pte_none(*pte)) {
+		if (pte_present(*pte) && pte_soft_dirty(*pte))
+			pte_file_mksoft_dirty(ptfile);
 		zap_pte(mm, vma, addr, pte);
+	}
 
-	set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
+	set_pte_at(mm, addr, pte, ptfile);
 	/*
 	 * We don't need to run update_mmu_cache() here because the "file pte"
 	 * being installed by install_file_pte() is not a real pte - it's a
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index a92012a..d96d921 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -211,24 +211,29 @@ static void put_huge_zero_page(void)
 	BUG_ON(atomic_dec_and_test(&huge_zero_refcount));
 }
 
-static int shrink_huge_zero_page(struct shrinker *shrink,
-		struct shrink_control *sc)
+static unsigned long shrink_huge_zero_page_count(struct shrinker *shrink,
+					struct shrink_control *sc)
 {
-	if (!sc->nr_to_scan)
-		/* we can free zero page only if last reference remains */
-		return atomic_read(&huge_zero_refcount) == 1 ? HPAGE_PMD_NR : 0;
+	/* we can free zero page only if last reference remains */
+	return atomic_read(&huge_zero_refcount) == 1 ? HPAGE_PMD_NR : 0;
+}
 
+static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink,
+				       struct shrink_control *sc)
+{
 	if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) {
 		struct page *zero_page = xchg(&huge_zero_page, NULL);
 		BUG_ON(zero_page == NULL);
 		__free_page(zero_page);
+		return HPAGE_PMD_NR;
 	}
 
 	return 0;
 }
 
 static struct shrinker huge_zero_page_shrinker = {
-	.shrink = shrink_huge_zero_page,
+	.count_objects = shrink_huge_zero_page_count,
+	.scan_objects = shrink_huge_zero_page_scan,
 	.seeks = DEFAULT_SEEKS,
 };
 
@@ -417,7 +422,7 @@ static ssize_t scan_sleep_millisecs_store(struct kobject *kobj,
 	unsigned long msecs;
 	int err;
 
-	err = strict_strtoul(buf, 10, &msecs);
+	err = kstrtoul(buf, 10, &msecs);
 	if (err || msecs > UINT_MAX)
 		return -EINVAL;
 
@@ -444,7 +449,7 @@ static ssize_t alloc_sleep_millisecs_store(struct kobject *kobj,
 	unsigned long msecs;
 	int err;
 
-	err = strict_strtoul(buf, 10, &msecs);
+	err = kstrtoul(buf, 10, &msecs);
 	if (err || msecs > UINT_MAX)
 		return -EINVAL;
 
@@ -470,7 +475,7 @@ static ssize_t pages_to_scan_store(struct kobject *kobj,
 	int err;
 	unsigned long pages;
 
-	err = strict_strtoul(buf, 10, &pages);
+	err = kstrtoul(buf, 10, &pages);
 	if (err || !pages || pages > UINT_MAX)
 		return -EINVAL;
 
@@ -538,7 +543,7 @@ static ssize_t khugepaged_max_ptes_none_store(struct kobject *kobj,
 	int err;
 	unsigned long max_ptes_none;
 
-	err = strict_strtoul(buf, 10, &max_ptes_none);
+	err = kstrtoul(buf, 10, &max_ptes_none);
 	if (err || max_ptes_none > HPAGE_PMD_NR-1)
 		return -EINVAL;
 
@@ -690,11 +695,10 @@ pmd_t maybe_pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
 	return pmd;
 }
 
-static inline pmd_t mk_huge_pmd(struct page *page, struct vm_area_struct *vma)
+static inline pmd_t mk_huge_pmd(struct page *page, pgprot_t prot)
 {
 	pmd_t entry;
-	entry = mk_pmd(page, vma->vm_page_prot);
-	entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+	entry = mk_pmd(page, prot);
 	entry = pmd_mkhuge(entry);
 	return entry;
 }
@@ -727,7 +731,8 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
 		pte_free(mm, pgtable);
 	} else {
 		pmd_t entry;
-		entry = mk_huge_pmd(page, vma);
+		entry = mk_huge_pmd(page, vma->vm_page_prot);
+		entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 		page_add_new_anon_rmap(page, vma, haddr);
 		pgtable_trans_huge_deposit(mm, pmd, pgtable);
 		set_pmd_at(mm, haddr, pmd, entry);
@@ -783,77 +788,55 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 {
 	struct page *page;
 	unsigned long haddr = address & HPAGE_PMD_MASK;
-	pte_t *pte;
 
-	if (haddr >= vma->vm_start && haddr + HPAGE_PMD_SIZE <= vma->vm_end) {
-		if (unlikely(anon_vma_prepare(vma)))
-			return VM_FAULT_OOM;
-		if (unlikely(khugepaged_enter(vma)))
+	if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end)
+		return VM_FAULT_FALLBACK;
+	if (unlikely(anon_vma_prepare(vma)))
+		return VM_FAULT_OOM;
+	if (unlikely(khugepaged_enter(vma)))
+		return VM_FAULT_OOM;
+	if (!(flags & FAULT_FLAG_WRITE) &&
+			transparent_hugepage_use_zero_page()) {
+		pgtable_t pgtable;
+		struct page *zero_page;
+		bool set;
+		pgtable = pte_alloc_one(mm, haddr);
+		if (unlikely(!pgtable))
 			return VM_FAULT_OOM;
-		if (!(flags & FAULT_FLAG_WRITE) &&
-				transparent_hugepage_use_zero_page()) {
-			pgtable_t pgtable;
-			struct page *zero_page;
-			bool set;
-			pgtable = pte_alloc_one(mm, haddr);
-			if (unlikely(!pgtable))
-				return VM_FAULT_OOM;
-			zero_page = get_huge_zero_page();
-			if (unlikely(!zero_page)) {
-				pte_free(mm, pgtable);
-				count_vm_event(THP_FAULT_FALLBACK);
-				goto out;
-			}
-			spin_lock(&mm->page_table_lock);
-			set = set_huge_zero_page(pgtable, mm, vma, haddr, pmd,
-					zero_page);
-			spin_unlock(&mm->page_table_lock);
-			if (!set) {
-				pte_free(mm, pgtable);
-				put_huge_zero_page();
-			}
-			return 0;
-		}
-		page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
-					  vma, haddr, numa_node_id(), 0);
-		if (unlikely(!page)) {
+		zero_page = get_huge_zero_page();
+		if (unlikely(!zero_page)) {
+			pte_free(mm, pgtable);
 			count_vm_event(THP_FAULT_FALLBACK);
-			goto out;
+			return VM_FAULT_FALLBACK;
 		}
-		count_vm_event(THP_FAULT_ALLOC);
-		if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) {
-			put_page(page);
-			goto out;
-		}
-		if (unlikely(__do_huge_pmd_anonymous_page(mm, vma, haddr, pmd,
-							  page))) {
-			mem_cgroup_uncharge_page(page);
-			put_page(page);
-			goto out;
+		spin_lock(&mm->page_table_lock);
+		set = set_huge_zero_page(pgtable, mm, vma, haddr, pmd,
+				zero_page);
+		spin_unlock(&mm->page_table_lock);
+		if (!set) {
+			pte_free(mm, pgtable);
+			put_huge_zero_page();
 		}
-
 		return 0;
 	}
-out:
-	/*
-	 * Use __pte_alloc instead of pte_alloc_map, because we can't
-	 * run pte_offset_map on the pmd, if an huge pmd could
-	 * materialize from under us from a different thread.
-	 */
-	if (unlikely(pmd_none(*pmd)) &&
-	    unlikely(__pte_alloc(mm, vma, pmd, address)))
-		return VM_FAULT_OOM;
-	/* if an huge pmd materialized from under us just retry later */
-	if (unlikely(pmd_trans_huge(*pmd)))
-		return 0;
-	/*
-	 * A regular pmd is established and it can't morph into a huge pmd
-	 * from under us anymore at this point because we hold the mmap_sem
-	 * read mode and khugepaged takes it in write mode. So now it's
-	 * safe to run pte_offset_map().
-	 */
-	pte = pte_offset_map(pmd, address);
-	return handle_pte_fault(mm, vma, address, pte, pmd, flags);
+	page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
+			vma, haddr, numa_node_id(), 0);
+	if (unlikely(!page)) {
+		count_vm_event(THP_FAULT_FALLBACK);
+		return VM_FAULT_FALLBACK;
+	}
+	count_vm_event(THP_FAULT_ALLOC);
+	if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) {
+		put_page(page);
+		return VM_FAULT_FALLBACK;
+	}
+	if (unlikely(__do_huge_pmd_anonymous_page(mm, vma, haddr, pmd, page))) {
+		mem_cgroup_uncharge_page(page);
+		put_page(page);
+		return VM_FAULT_FALLBACK;
+	}
+
+	return 0;
 }
 
 int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
@@ -1210,7 +1193,8 @@ alloc:
 		goto out_mn;
 	} else {
 		pmd_t entry;
-		entry = mk_huge_pmd(new_page, vma);
+		entry = mk_huge_pmd(new_page, vma->vm_page_prot);
+		entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 		pmdp_clear_flush(vma, haddr, pmd);
 		page_add_new_anon_rmap(new_page, vma, haddr);
 		set_pmd_at(mm, haddr, pmd, entry);
@@ -1661,7 +1645,6 @@ static void __split_huge_page_refcount(struct page *page,
 	BUG_ON(atomic_read(&page->_count) <= 0);
 
 	__mod_zone_page_state(zone, NR_ANON_TRANSPARENT_HUGEPAGES, -1);
-	__mod_zone_page_state(zone, NR_ANON_PAGES, HPAGE_PMD_NR);
 
 	ClearPageCompound(page);
 	compound_unlock(page);
@@ -2296,6 +2279,8 @@ static void collapse_huge_page(struct mm_struct *mm,
 		goto out;
 
 	vma = find_vma(mm, address);
+	if (!vma)
+		goto out;
 	hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
 	hend = vma->vm_end & HPAGE_PMD_MASK;
 	if (address < hstart || address + HPAGE_PMD_SIZE > hend)
@@ -2357,7 +2342,8 @@ static void collapse_huge_page(struct mm_struct *mm,
 	__SetPageUptodate(new_page);
 	pgtable = pmd_pgtable(_pmd);
 
-	_pmd = mk_huge_pmd(new_page, vma);
+	_pmd = mk_huge_pmd(new_page, vma->vm_page_prot);
+	_pmd = maybe_pmd_mkwrite(pmd_mkdirty(_pmd), vma);
 
 	/*
 	 * spin_lock() below is not the equivalent of smp_wmb(), so
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 83aff0a..b2471aa 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -135,9 +135,9 @@ static inline struct hugepage_subpool *subpool_vma(struct vm_area_struct *vma)
  *                    across the pages in a mapping.
  *
  * The region data structures are protected by a combination of the mmap_sem
- * and the hugetlb_instantion_mutex.  To access or modify a region the caller
+ * and the hugetlb_instantiation_mutex.  To access or modify a region the caller
  * must either hold the mmap_sem for write, or the mmap_sem for read and
- * the hugetlb_instantiation mutex:
+ * the hugetlb_instantiation_mutex:
  *
  *	down_write(&mm->mmap_sem);
  * or
@@ -434,25 +434,6 @@ static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag)
 	return (get_vma_private_data(vma) & flag) != 0;
 }
 
-/* Decrement the reserved pages in the hugepage pool by one */
-static void decrement_hugepage_resv_vma(struct hstate *h,
-			struct vm_area_struct *vma)
-{
-	if (vma->vm_flags & VM_NORESERVE)
-		return;
-
-	if (vma->vm_flags & VM_MAYSHARE) {
-		/* Shared mappings always use reserves */
-		h->resv_huge_pages--;
-	} else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
-		/*
-		 * Only the process that called mmap() has reserves for
-		 * private mappings.
-		 */
-		h->resv_huge_pages--;
-	}
-}
-
 /* Reset counters to 0 and clear all HPAGE_RESV_* flags */
 void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
 {
@@ -462,12 +443,35 @@ void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
 }
 
 /* Returns true if the VMA has associated reserve pages */
-static int vma_has_reserves(struct vm_area_struct *vma)
+static int vma_has_reserves(struct vm_area_struct *vma, long chg)
 {
+	if (vma->vm_flags & VM_NORESERVE) {
+		/*
+		 * This address is already reserved by other process(chg == 0),
+		 * so, we should decrement reserved count. Without decrementing,
+		 * reserve count remains after releasing inode, because this
+		 * allocated page will go into page cache and is regarded as
+		 * coming from reserved pool in releasing step.  Currently, we
+		 * don't have any other solution to deal with this situation
+		 * properly, so add work-around here.
+		 */
+		if (vma->vm_flags & VM_MAYSHARE && chg == 0)
+			return 1;
+		else
+			return 0;
+	}
+
+	/* Shared mappings always use reserves */
 	if (vma->vm_flags & VM_MAYSHARE)
 		return 1;
+
+	/*
+	 * Only the process that called mmap() has reserves for
+	 * private mappings.
+	 */
 	if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
 		return 1;
+
 	return 0;
 }
 
@@ -529,7 +533,8 @@ static struct page *dequeue_huge_page_node(struct hstate *h, int nid)
 
 static struct page *dequeue_huge_page_vma(struct hstate *h,
 				struct vm_area_struct *vma,
-				unsigned long address, int avoid_reserve)
+				unsigned long address, int avoid_reserve,
+				long chg)
 {
 	struct page *page = NULL;
 	struct mempolicy *mpol;
@@ -539,16 +544,12 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
 	struct zoneref *z;
 	unsigned int cpuset_mems_cookie;
 
-retry_cpuset:
-	cpuset_mems_cookie = get_mems_allowed();
-	zonelist = huge_zonelist(vma, address,
-					htlb_alloc_mask, &mpol, &nodemask);
 	/*
 	 * A child process with MAP_PRIVATE mappings created by their parent
 	 * have no page reserves. This check ensures that reservations are
 	 * not "stolen". The child may still get SIGKILLed
 	 */
-	if (!vma_has_reserves(vma) &&
+	if (!vma_has_reserves(vma, chg) &&
 			h->free_huge_pages - h->resv_huge_pages == 0)
 		goto err;
 
@@ -556,13 +557,22 @@ retry_cpuset:
 	if (avoid_reserve && h->free_huge_pages - h->resv_huge_pages == 0)
 		goto err;
 
+retry_cpuset:
+	cpuset_mems_cookie = get_mems_allowed();
+	zonelist = huge_zonelist(vma, address,
+					htlb_alloc_mask, &mpol, &nodemask);
+
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 						MAX_NR_ZONES - 1, nodemask) {
 		if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask)) {
 			page = dequeue_huge_page_node(h, zone_to_nid(zone));
 			if (page) {
-				if (!avoid_reserve)
-					decrement_hugepage_resv_vma(h, vma);
+				if (avoid_reserve)
+					break;
+				if (!vma_has_reserves(vma, chg))
+					break;
+
+				h->resv_huge_pages--;
 				break;
 			}
 		}
@@ -574,7 +584,6 @@ retry_cpuset:
 	return page;
 
 err:
-	mpol_cond_put(mpol);
 	return NULL;
 }
 
@@ -772,33 +781,6 @@ static int hstate_next_node_to_alloc(struct hstate *h,
 	return nid;
 }
 
-static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
-{
-	struct page *page;
-	int start_nid;
-	int next_nid;
-	int ret = 0;
-
-	start_nid = hstate_next_node_to_alloc(h, nodes_allowed);
-	next_nid = start_nid;
-
-	do {
-		page = alloc_fresh_huge_page_node(h, next_nid);
-		if (page) {
-			ret = 1;
-			break;
-		}
-		next_nid = hstate_next_node_to_alloc(h, nodes_allowed);
-	} while (next_nid != start_nid);
-
-	if (ret)
-		count_vm_event(HTLB_BUDDY_PGALLOC);
-	else
-		count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
-
-	return ret;
-}
-
 /*
  * helper for free_pool_huge_page() - return the previously saved
  * node ["this node"] from which to free a huge page.  Advance the
@@ -817,6 +799,40 @@ static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
 	return nid;
 }
 
+#define for_each_node_mask_to_alloc(hs, nr_nodes, node, mask)		\
+	for (nr_nodes = nodes_weight(*mask);				\
+		nr_nodes > 0 &&						\
+		((node = hstate_next_node_to_alloc(hs, mask)) || 1);	\
+		nr_nodes--)
+
+#define for_each_node_mask_to_free(hs, nr_nodes, node, mask)		\
+	for (nr_nodes = nodes_weight(*mask);				\
+		nr_nodes > 0 &&						\
+		((node = hstate_next_node_to_free(hs, mask)) || 1);	\
+		nr_nodes--)
+
+static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
+{
+	struct page *page;
+	int nr_nodes, node;
+	int ret = 0;
+
+	for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
+		page = alloc_fresh_huge_page_node(h, node);
+		if (page) {
+			ret = 1;
+			break;
+		}
+	}
+
+	if (ret)
+		count_vm_event(HTLB_BUDDY_PGALLOC);
+	else
+		count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
+
+	return ret;
+}
+
 /*
  * Free huge page from pool from next node to free.
  * Attempt to keep persistent huge pages more or less
@@ -826,36 +842,31 @@ static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
 static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
 							 bool acct_surplus)
 {
-	int start_nid;
-	int next_nid;
+	int nr_nodes, node;
 	int ret = 0;
 
-	start_nid = hstate_next_node_to_free(h, nodes_allowed);
-	next_nid = start_nid;
-
-	do {
+	for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) {
 		/*
 		 * If we're returning unused surplus pages, only examine
 		 * nodes with surplus pages.
 		 */
-		if ((!acct_surplus || h->surplus_huge_pages_node[next_nid]) &&
-		    !list_empty(&h->hugepage_freelists[next_nid])) {
+		if ((!acct_surplus || h->surplus_huge_pages_node[node]) &&
+		    !list_empty(&h->hugepage_freelists[node])) {
 			struct page *page =
-				list_entry(h->hugepage_freelists[next_nid].next,
+				list_entry(h->hugepage_freelists[node].next,
 					  struct page, lru);
 			list_del(&page->lru);
 			h->free_huge_pages--;
-			h->free_huge_pages_node[next_nid]--;
+			h->free_huge_pages_node[node]--;
 			if (acct_surplus) {
 				h->surplus_huge_pages--;
-				h->surplus_huge_pages_node[next_nid]--;
+				h->surplus_huge_pages_node[node]--;
 			}
 			update_and_free_page(h, page);
 			ret = 1;
 			break;
 		}
-		next_nid = hstate_next_node_to_free(h, nodes_allowed);
-	} while (next_nid != start_nid);
+	}
 
 	return ret;
 }
@@ -1035,11 +1046,8 @@ free:
 	spin_unlock(&hugetlb_lock);
 
 	/* Free unnecessary surplus pages to the buddy allocator */
-	if (!list_empty(&surplus_list)) {
-		list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
-			put_page(page);
-		}
-	}
+	list_for_each_entry_safe(page, tmp, &surplus_list, lru)
+		put_page(page);
 	spin_lock(&hugetlb_lock);
 
 	return ret;
@@ -1165,13 +1173,8 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
 		return ERR_PTR(-ENOSPC);
 	}
 	spin_lock(&hugetlb_lock);
-	page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve);
-	if (page) {
-		/* update page cgroup details */
-		hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h),
-					     h_cg, page);
-		spin_unlock(&hugetlb_lock);
-	} else {
+	page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve, chg);
+	if (!page) {
 		spin_unlock(&hugetlb_lock);
 		page = alloc_buddy_huge_page(h, NUMA_NO_NODE);
 		if (!page) {
@@ -1182,11 +1185,11 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
 			return ERR_PTR(-ENOSPC);
 		}
 		spin_lock(&hugetlb_lock);
-		hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h),
-					     h_cg, page);
 		list_move(&page->lru, &h->hugepage_activelist);
-		spin_unlock(&hugetlb_lock);
+		/* Fall through */
 	}
+	hugetlb_cgroup_commit_charge(idx, pages_per_huge_page(h), h_cg, page);
+	spin_unlock(&hugetlb_lock);
 
 	set_page_private(page, (unsigned long)spool);
 
@@ -1197,14 +1200,12 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
 int __weak alloc_bootmem_huge_page(struct hstate *h)
 {
 	struct huge_bootmem_page *m;
-	int nr_nodes = nodes_weight(node_states[N_MEMORY]);
+	int nr_nodes, node;
 
-	while (nr_nodes) {
+	for_each_node_mask_to_alloc(h, nr_nodes, node, &node_states[N_MEMORY]) {
 		void *addr;
 
-		addr = __alloc_bootmem_node_nopanic(
-				NODE_DATA(hstate_next_node_to_alloc(h,
-						&node_states[N_MEMORY])),
+		addr = __alloc_bootmem_node_nopanic(NODE_DATA(node),
 				huge_page_size(h), huge_page_size(h), 0);
 
 		if (addr) {
@@ -1216,7 +1217,6 @@ int __weak alloc_bootmem_huge_page(struct hstate *h)
 			m = addr;
 			goto found;
 		}
-		nr_nodes--;
 	}
 	return 0;
 
@@ -1355,48 +1355,28 @@ static inline void try_to_free_low(struct hstate *h, unsigned long count,
 static int adjust_pool_surplus(struct hstate *h, nodemask_t *nodes_allowed,
 				int delta)
 {
-	int start_nid, next_nid;
-	int ret = 0;
+	int nr_nodes, node;
 
 	VM_BUG_ON(delta != -1 && delta != 1);
 
-	if (delta < 0)
-		start_nid = hstate_next_node_to_alloc(h, nodes_allowed);
-	else
-		start_nid = hstate_next_node_to_free(h, nodes_allowed);
-	next_nid = start_nid;
-
-	do {
-		int nid = next_nid;
-		if (delta < 0)  {
-			/*
-			 * To shrink on this node, there must be a surplus page
-			 */
-			if (!h->surplus_huge_pages_node[nid]) {
-				next_nid = hstate_next_node_to_alloc(h,
-								nodes_allowed);
-				continue;
-			}
+	if (delta < 0) {
+		for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
+			if (h->surplus_huge_pages_node[node])
+				goto found;
 		}
-		if (delta > 0) {
-			/*
-			 * Surplus cannot exceed the total number of pages
-			 */
-			if (h->surplus_huge_pages_node[nid] >=
-						h->nr_huge_pages_node[nid]) {
-				next_nid = hstate_next_node_to_free(h,
-								nodes_allowed);
-				continue;
-			}
+	} else {
+		for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) {
+			if (h->surplus_huge_pages_node[node] <
+					h->nr_huge_pages_node[node])
+				goto found;
 		}
+	}
+	return 0;
 
-		h->surplus_huge_pages += delta;
-		h->surplus_huge_pages_node[nid] += delta;
-		ret = 1;
-		break;
-	} while (next_nid != start_nid);
-
-	return ret;
+found:
+	h->surplus_huge_pages += delta;
+	h->surplus_huge_pages_node[node] += delta;
+	return 1;
 }
 
 #define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
@@ -1526,7 +1506,7 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
 	struct hstate *h;
 	NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY);
 
-	err = strict_strtoul(buf, 10, &count);
+	err = kstrtoul(buf, 10, &count);
 	if (err)
 		goto out;
 
@@ -1617,7 +1597,7 @@ static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
 	if (h->order >= MAX_ORDER)
 		return -EINVAL;
 
-	err = strict_strtoul(buf, 10, &input);
+	err = kstrtoul(buf, 10, &input);
 	if (err)
 		return err;
 
@@ -2557,7 +2537,6 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
 {
 	struct hstate *h = hstate_vma(vma);
 	struct page *old_page, *new_page;
-	int avoidcopy;
 	int outside_reserve = 0;
 	unsigned long mmun_start;	/* For mmu_notifiers */
 	unsigned long mmun_end;		/* For mmu_notifiers */
@@ -2567,10 +2546,8 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
 retry_avoidcopy:
 	/* If no-one else is actually using this page, avoid the copy
 	 * and just make the page writable */
-	avoidcopy = (page_mapcount(old_page) == 1);
-	if (avoidcopy) {
-		if (PageAnon(old_page))
-			page_move_anon_rmap(old_page, vma, address);
+	if (page_mapcount(old_page) == 1 && PageAnon(old_page)) {
+		page_move_anon_rmap(old_page, vma, address);
 		set_huge_ptep_writable(vma, address, ptep);
 		return 0;
 	}
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index c8d7f31..e126b0e 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1639,7 +1639,7 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
 	else if (strncmp(buf, "scan=", 5) == 0) {
 		unsigned long secs;
 
-		ret = strict_strtoul(buf + 5, 0, &secs);
+		ret = kstrtoul(buf + 5, 0, &secs);
 		if (ret < 0)
 			goto out;
 		stop_scan_thread();
diff --git a/mm/ksm.c b/mm/ksm.c
index b6afe0c..0bea2b2 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2194,7 +2194,7 @@ static ssize_t sleep_millisecs_store(struct kobject *kobj,
 	unsigned long msecs;
 	int err;
 
-	err = strict_strtoul(buf, 10, &msecs);
+	err = kstrtoul(buf, 10, &msecs);
 	if (err || msecs > UINT_MAX)
 		return -EINVAL;
 
@@ -2217,7 +2217,7 @@ static ssize_t pages_to_scan_store(struct kobject *kobj,
 	int err;
 	unsigned long nr_pages;
 
-	err = strict_strtoul(buf, 10, &nr_pages);
+	err = kstrtoul(buf, 10, &nr_pages);
 	if (err || nr_pages > UINT_MAX)
 		return -EINVAL;
 
@@ -2239,7 +2239,7 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr,
 	int err;
 	unsigned long flags;
 
-	err = strict_strtoul(buf, 10, &flags);
+	err = kstrtoul(buf, 10, &flags);
 	if (err || flags > UINT_MAX)
 		return -EINVAL;
 	if (flags > KSM_RUN_UNMERGE)
diff --git a/mm/list_lru.c b/mm/list_lru.c
new file mode 100644
index 0000000..7246791
--- /dev/null
+++ b/mm/list_lru.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc. and Parallels Inc. All rights reserved.
+ * Authors: David Chinner and Glauber Costa
+ *
+ * Generic LRU infrastructure
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/list_lru.h>
+#include <linux/slab.h>
+
+bool list_lru_add(struct list_lru *lru, struct list_head *item)
+{
+	int nid = page_to_nid(virt_to_page(item));
+	struct list_lru_node *nlru = &lru->node[nid];
+
+	spin_lock(&nlru->lock);
+	WARN_ON_ONCE(nlru->nr_items < 0);
+	if (list_empty(item)) {
+		list_add_tail(item, &nlru->list);
+		if (nlru->nr_items++ == 0)
+			node_set(nid, lru->active_nodes);
+		spin_unlock(&nlru->lock);
+		return true;
+	}
+	spin_unlock(&nlru->lock);
+	return false;
+}
+EXPORT_SYMBOL_GPL(list_lru_add);
+
+bool list_lru_del(struct list_lru *lru, struct list_head *item)
+{
+	int nid = page_to_nid(virt_to_page(item));
+	struct list_lru_node *nlru = &lru->node[nid];
+
+	spin_lock(&nlru->lock);
+	if (!list_empty(item)) {
+		list_del_init(item);
+		if (--nlru->nr_items == 0)
+			node_clear(nid, lru->active_nodes);
+		WARN_ON_ONCE(nlru->nr_items < 0);
+		spin_unlock(&nlru->lock);
+		return true;
+	}
+	spin_unlock(&nlru->lock);
+	return false;
+}
+EXPORT_SYMBOL_GPL(list_lru_del);
+
+unsigned long
+list_lru_count_node(struct list_lru *lru, int nid)
+{
+	unsigned long count = 0;
+	struct list_lru_node *nlru = &lru->node[nid];
+
+	spin_lock(&nlru->lock);
+	WARN_ON_ONCE(nlru->nr_items < 0);
+	count += nlru->nr_items;
+	spin_unlock(&nlru->lock);
+
+	return count;
+}
+EXPORT_SYMBOL_GPL(list_lru_count_node);
+
+unsigned long
+list_lru_walk_node(struct list_lru *lru, int nid, list_lru_walk_cb isolate,
+		   void *cb_arg, unsigned long *nr_to_walk)
+{
+
+	struct list_lru_node	*nlru = &lru->node[nid];
+	struct list_head *item, *n;
+	unsigned long isolated = 0;
+
+	spin_lock(&nlru->lock);
+restart:
+	list_for_each_safe(item, n, &nlru->list) {
+		enum lru_status ret;
+
+		/*
+		 * decrement nr_to_walk first so that we don't livelock if we
+		 * get stuck on large numbesr of LRU_RETRY items
+		 */
+		if (--(*nr_to_walk) == 0)
+			break;
+
+		ret = isolate(item, &nlru->lock, cb_arg);
+		switch (ret) {
+		case LRU_REMOVED:
+			if (--nlru->nr_items == 0)
+				node_clear(nid, lru->active_nodes);
+			WARN_ON_ONCE(nlru->nr_items < 0);
+			isolated++;
+			break;
+		case LRU_ROTATE:
+			list_move_tail(item, &nlru->list);
+			break;
+		case LRU_SKIP:
+			break;
+		case LRU_RETRY:
+			/*
+			 * The lru lock has been dropped, our list traversal is
+			 * now invalid and so we have to restart from scratch.
+			 */
+			goto restart;
+		default:
+			BUG();
+		}
+	}
+
+	spin_unlock(&nlru->lock);
+	return isolated;
+}
+EXPORT_SYMBOL_GPL(list_lru_walk_node);
+
+int list_lru_init(struct list_lru *lru)
+{
+	int i;
+	size_t size = sizeof(*lru->node) * nr_node_ids;
+
+	lru->node = kzalloc(size, GFP_KERNEL);
+	if (!lru->node)
+		return -ENOMEM;
+
+	nodes_clear(lru->active_nodes);
+	for (i = 0; i < nr_node_ids; i++) {
+		spin_lock_init(&lru->node[i].lock);
+		INIT_LIST_HEAD(&lru->node[i].list);
+		lru->node[i].nr_items = 0;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(list_lru_init);
+
+void list_lru_destroy(struct list_lru *lru)
+{
+	kfree(lru->node);
+}
+EXPORT_SYMBOL_GPL(list_lru_destroy);
diff --git a/mm/madvise.c b/mm/madvise.c
index 7055883..936799f 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -42,11 +42,11 @@ static int madvise_need_mmap_write(int behavior)
  * We can potentially split a vm area into separate
  * areas, each area with its own behavior.
  */
-static long madvise_behavior(struct vm_area_struct * vma,
+static long madvise_behavior(struct vm_area_struct *vma,
 		     struct vm_area_struct **prev,
 		     unsigned long start, unsigned long end, int behavior)
 {
-	struct mm_struct * mm = vma->vm_mm;
+	struct mm_struct *mm = vma->vm_mm;
 	int error = 0;
 	pgoff_t pgoff;
 	unsigned long new_flags = vma->vm_flags;
@@ -215,8 +215,8 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma,
 /*
  * Schedule all required I/O operations.  Do not wait for completion.
  */
-static long madvise_willneed(struct vm_area_struct * vma,
-			     struct vm_area_struct ** prev,
+static long madvise_willneed(struct vm_area_struct *vma,
+			     struct vm_area_struct **prev,
 			     unsigned long start, unsigned long end)
 {
 	struct file *file = vma->vm_file;
@@ -270,8 +270,8 @@ static long madvise_willneed(struct vm_area_struct * vma,
  * An interface that causes the system to free clean pages and flush
  * dirty pages is already available as msync(MS_INVALIDATE).
  */
-static long madvise_dontneed(struct vm_area_struct * vma,
-			     struct vm_area_struct ** prev,
+static long madvise_dontneed(struct vm_area_struct *vma,
+			     struct vm_area_struct **prev,
 			     unsigned long start, unsigned long end)
 {
 	*prev = vma;
@@ -459,7 +459,7 @@ madvise_behavior_valid(int behavior)
 SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
 {
 	unsigned long end, tmp;
-	struct vm_area_struct * vma, *prev;
+	struct vm_area_struct *vma, *prev;
 	int unmapped_error = 0;
 	int error = -EINVAL;
 	int write;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index c290a1c..6f292b8 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -39,7 +39,6 @@
 #include <linux/limits.h>
 #include <linux/export.h>
 #include <linux/mutex.h>
-#include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
@@ -175,10 +174,6 @@ struct mem_cgroup_per_zone {
 
 	struct mem_cgroup_reclaim_iter reclaim_iter[DEF_PRIORITY + 1];
 
-	struct rb_node		tree_node;	/* RB tree node */
-	unsigned long long	usage_in_excess;/* Set to the value by which */
-						/* the soft limit is exceeded*/
-	bool			on_tree;
 	struct mem_cgroup	*memcg;		/* Back pointer, we cannot */
 						/* use container_of	   */
 };
@@ -187,26 +182,6 @@ struct mem_cgroup_per_node {
 	struct mem_cgroup_per_zone zoneinfo[MAX_NR_ZONES];
 };
 
-/*
- * Cgroups above their limits are maintained in a RB-Tree, independent of
- * their hierarchy representation
- */
-
-struct mem_cgroup_tree_per_zone {
-	struct rb_root rb_root;
-	spinlock_t lock;
-};
-
-struct mem_cgroup_tree_per_node {
-	struct mem_cgroup_tree_per_zone rb_tree_per_zone[MAX_NR_ZONES];
-};
-
-struct mem_cgroup_tree {
-	struct mem_cgroup_tree_per_node *rb_tree_per_node[MAX_NUMNODES];
-};
-
-static struct mem_cgroup_tree soft_limit_tree __read_mostly;
-
 struct mem_cgroup_threshold {
 	struct eventfd_ctx *eventfd;
 	u64 threshold;
@@ -280,6 +255,7 @@ struct mem_cgroup {
 
 	bool		oom_lock;
 	atomic_t	under_oom;
+	atomic_t	oom_wakeups;
 
 	int	swappiness;
 	/* OOM-Killer disable */
@@ -304,7 +280,7 @@ struct mem_cgroup {
 	 * Should we move charges of a task when a task is moved into this
 	 * mem_cgroup ? And what type of charges should we move ?
 	 */
-	unsigned long 	move_charge_at_immigrate;
+	unsigned long move_charge_at_immigrate;
 	/*
 	 * set > 0 if pages under this cgroup are moving to other cgroup.
 	 */
@@ -341,6 +317,22 @@ struct mem_cgroup {
 	atomic_t	numainfo_events;
 	atomic_t	numainfo_updating;
 #endif
+	/*
+	 * Protects soft_contributed transitions.
+	 * See mem_cgroup_update_soft_limit
+	 */
+	spinlock_t soft_lock;
+
+	/*
+	 * If true then this group has increased parents' children_in_excess
+	 * when it got over the soft limit.
+	 * When a group falls bellow the soft limit, parents' children_in_excess
+	 * is decreased and soft_contributed changed to false.
+	 */
+	bool soft_contributed;
+
+	/* Number of children that are in soft limit excess */
+	atomic_t children_in_excess;
 
 	struct mem_cgroup_per_node *nodeinfo[0];
 	/* WARNING: nodeinfo must be the last member here */
@@ -444,7 +436,6 @@ static bool move_file(void)
  * limit reclaim to prevent infinite loops, if they ever occur.
  */
 #define	MEM_CGROUP_MAX_RECLAIM_LOOPS		100
-#define	MEM_CGROUP_MAX_SOFT_LIMIT_RECLAIM_LOOPS	2
 
 enum charge_type {
 	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
@@ -672,164 +663,6 @@ page_cgroup_zoneinfo(struct mem_cgroup *memcg, struct page *page)
 	return mem_cgroup_zoneinfo(memcg, nid, zid);
 }
 
-static struct mem_cgroup_tree_per_zone *
-soft_limit_tree_node_zone(int nid, int zid)
-{
-	return &soft_limit_tree.rb_tree_per_node[nid]->rb_tree_per_zone[zid];
-}
-
-static struct mem_cgroup_tree_per_zone *
-soft_limit_tree_from_page(struct page *page)
-{
-	int nid = page_to_nid(page);
-	int zid = page_zonenum(page);
-
-	return &soft_limit_tree.rb_tree_per_node[nid]->rb_tree_per_zone[zid];
-}
-
-static void
-__mem_cgroup_insert_exceeded(struct mem_cgroup *memcg,
-				struct mem_cgroup_per_zone *mz,
-				struct mem_cgroup_tree_per_zone *mctz,
-				unsigned long long new_usage_in_excess)
-{
-	struct rb_node **p = &mctz->rb_root.rb_node;
-	struct rb_node *parent = NULL;
-	struct mem_cgroup_per_zone *mz_node;
-
-	if (mz->on_tree)
-		return;
-
-	mz->usage_in_excess = new_usage_in_excess;
-	if (!mz->usage_in_excess)
-		return;
-	while (*p) {
-		parent = *p;
-		mz_node = rb_entry(parent, struct mem_cgroup_per_zone,
-					tree_node);
-		if (mz->usage_in_excess < mz_node->usage_in_excess)
-			p = &(*p)->rb_left;
-		/*
-		 * We can't avoid mem cgroups that are over their soft
-		 * limit by the same amount
-		 */
-		else if (mz->usage_in_excess >= mz_node->usage_in_excess)
-			p = &(*p)->rb_right;
-	}
-	rb_link_node(&mz->tree_node, parent, p);
-	rb_insert_color(&mz->tree_node, &mctz->rb_root);
-	mz->on_tree = true;
-}
-
-static void
-__mem_cgroup_remove_exceeded(struct mem_cgroup *memcg,
-				struct mem_cgroup_per_zone *mz,
-				struct mem_cgroup_tree_per_zone *mctz)
-{
-	if (!mz->on_tree)
-		return;
-	rb_erase(&mz->tree_node, &mctz->rb_root);
-	mz->on_tree = false;
-}
-
-static void
-mem_cgroup_remove_exceeded(struct mem_cgroup *memcg,
-				struct mem_cgroup_per_zone *mz,
-				struct mem_cgroup_tree_per_zone *mctz)
-{
-	spin_lock(&mctz->lock);
-	__mem_cgroup_remove_exceeded(memcg, mz, mctz);
-	spin_unlock(&mctz->lock);
-}
-
-
-static void mem_cgroup_update_tree(struct mem_cgroup *memcg, struct page *page)
-{
-	unsigned long long excess;
-	struct mem_cgroup_per_zone *mz;
-	struct mem_cgroup_tree_per_zone *mctz;
-	int nid = page_to_nid(page);
-	int zid = page_zonenum(page);
-	mctz = soft_limit_tree_from_page(page);
-
-	/*
-	 * Necessary to update all ancestors when hierarchy is used.
-	 * because their event counter is not touched.
-	 */
-	for (; memcg; memcg = parent_mem_cgroup(memcg)) {
-		mz = mem_cgroup_zoneinfo(memcg, nid, zid);
-		excess = res_counter_soft_limit_excess(&memcg->res);
-		/*
-		 * We have to update the tree if mz is on RB-tree or
-		 * mem is over its softlimit.
-		 */
-		if (excess || mz->on_tree) {
-			spin_lock(&mctz->lock);
-			/* if on-tree, remove it */
-			if (mz->on_tree)
-				__mem_cgroup_remove_exceeded(memcg, mz, mctz);
-			/*
-			 * Insert again. mz->usage_in_excess will be updated.
-			 * If excess is 0, no tree ops.
-			 */
-			__mem_cgroup_insert_exceeded(memcg, mz, mctz, excess);
-			spin_unlock(&mctz->lock);
-		}
-	}
-}
-
-static void mem_cgroup_remove_from_trees(struct mem_cgroup *memcg)
-{
-	int node, zone;
-	struct mem_cgroup_per_zone *mz;
-	struct mem_cgroup_tree_per_zone *mctz;
-
-	for_each_node(node) {
-		for (zone = 0; zone < MAX_NR_ZONES; zone++) {
-			mz = mem_cgroup_zoneinfo(memcg, node, zone);
-			mctz = soft_limit_tree_node_zone(node, zone);
-			mem_cgroup_remove_exceeded(memcg, mz, mctz);
-		}
-	}
-}
-
-static struct mem_cgroup_per_zone *
-__mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
-{
-	struct rb_node *rightmost = NULL;
-	struct mem_cgroup_per_zone *mz;
-
-retry:
-	mz = NULL;
-	rightmost = rb_last(&mctz->rb_root);
-	if (!rightmost)
-		goto done;		/* Nothing to reclaim from */
-
-	mz = rb_entry(rightmost, struct mem_cgroup_per_zone, tree_node);
-	/*
-	 * Remove the node now but someone else can add it back,
-	 * we will to add it back at the end of reclaim to its correct
-	 * position in the tree.
-	 */
-	__mem_cgroup_remove_exceeded(mz->memcg, mz, mctz);
-	if (!res_counter_soft_limit_excess(&mz->memcg->res) ||
-		!css_tryget(&mz->memcg->css))
-		goto retry;
-done:
-	return mz;
-}
-
-static struct mem_cgroup_per_zone *
-mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
-{
-	struct mem_cgroup_per_zone *mz;
-
-	spin_lock(&mctz->lock);
-	mz = __mem_cgroup_largest_soft_limit_node(mctz);
-	spin_unlock(&mctz->lock);
-	return mz;
-}
-
 /*
  * Implementation Note: reading percpu statistics for memcg.
  *
@@ -1004,6 +837,48 @@ static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg,
 }
 
 /*
+ * Called from rate-limited memcg_check_events when enough
+ * MEM_CGROUP_TARGET_SOFTLIMIT events are accumulated and it makes sure
+ * that all the parents up the hierarchy will be notified that this group
+ * is in excess or that it is not in excess anymore. mmecg->soft_contributed
+ * makes the transition a single action whenever the state flips from one to
+ * the other.
+ */
+static void mem_cgroup_update_soft_limit(struct mem_cgroup *memcg)
+{
+	unsigned long long excess = res_counter_soft_limit_excess(&memcg->res);
+	struct mem_cgroup *parent = memcg;
+	int delta = 0;
+
+	spin_lock(&memcg->soft_lock);
+	if (excess) {
+		if (!memcg->soft_contributed) {
+			delta = 1;
+			memcg->soft_contributed = true;
+		}
+	} else {
+		if (memcg->soft_contributed) {
+			delta = -1;
+			memcg->soft_contributed = false;
+		}
+	}
+
+	/*
+	 * Necessary to update all ancestors when hierarchy is used
+	 * because their event counter is not touched.
+	 * We track children even outside the hierarchy for the root
+	 * cgroup because tree walk starting at root should visit
+	 * all cgroups and we want to prevent from pointless tree
+	 * walk if no children is below the limit.
+	 */
+	while (delta && (parent = parent_mem_cgroup(parent)))
+		atomic_add(delta, &parent->children_in_excess);
+	if (memcg != root_mem_cgroup && !root_mem_cgroup->use_hierarchy)
+		atomic_add(delta, &root_mem_cgroup->children_in_excess);
+	spin_unlock(&memcg->soft_lock);
+}
+
+/*
  * Check events in order.
  *
  */
@@ -1026,7 +901,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
 
 		mem_cgroup_threshold(memcg);
 		if (unlikely(do_softlimit))
-			mem_cgroup_update_tree(memcg, page);
+			mem_cgroup_update_soft_limit(memcg);
 #if MAX_NUMNODES > 1
 		if (unlikely(do_numainfo))
 			atomic_inc(&memcg->numainfo_events);
@@ -1075,6 +950,15 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 	return memcg;
 }
 
+static enum mem_cgroup_filter_t
+mem_cgroup_filter(struct mem_cgroup *memcg, struct mem_cgroup *root,
+		mem_cgroup_iter_filter cond)
+{
+	if (!cond)
+		return VISIT;
+	return cond(memcg, root);
+}
+
 /*
  * Returns a next (in a pre-order walk) alive memcg (with elevated css
  * ref. count) or NULL if the whole root's subtree has been visited.
@@ -1082,7 +966,7 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
  * helper function to be used by mem_cgroup_iter
  */
 static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
-		struct mem_cgroup *last_visited)
+		struct mem_cgroup *last_visited, mem_cgroup_iter_filter cond)
 {
 	struct cgroup *prev_cgroup, *next_cgroup;
 
@@ -1090,10 +974,18 @@ static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
 	 * Root is not visited by cgroup iterators so it needs an
 	 * explicit visit.
 	 */
-	if (!last_visited)
-		return root;
+	if (!last_visited) {
+		switch (mem_cgroup_filter(root, root, cond)) {
+		case VISIT:
+			return root;
+		case SKIP:
+			break;
+		case SKIP_TREE:
+			return NULL;
+		}
+	}
 
-	prev_cgroup = (last_visited == root) ? NULL
+	prev_cgroup = (last_visited == root || !last_visited) ? NULL
 		: last_visited->css.cgroup;
 skip_node:
 	next_cgroup = cgroup_next_descendant_pre(
@@ -1109,11 +1001,30 @@ skip_node:
 	if (next_cgroup) {
 		struct mem_cgroup *mem = mem_cgroup_from_cont(
 				next_cgroup);
-		if (css_tryget(&mem->css))
-			return mem;
-		else {
+
+		switch (mem_cgroup_filter(mem, root, cond)) {
+		case SKIP:
 			prev_cgroup = next_cgroup;
 			goto skip_node;
+		case SKIP_TREE:
+			/*
+			 * cgroup_rightmost_descendant is not an optimal way to
+			 * skip through a subtree (especially for imbalanced
+			 * trees leaning to right) but that's what we have right
+			 * now. More effective solution would be traversing
+			 * right-up for first non-NULL without calling
+			 * cgroup_next_descendant_pre afterwards.
+			 */
+			prev_cgroup = cgroup_rightmost_descendant(next_cgroup);
+			goto skip_node;
+		case VISIT:
+			if (css_tryget(&mem->css))
+				return mem;
+			else {
+				prev_cgroup = next_cgroup;
+				goto skip_node;
+			}
+			break;
 		}
 	}
 
@@ -1177,6 +1088,7 @@ static void mem_cgroup_iter_update(struct mem_cgroup_reclaim_iter *iter,
  * @root: hierarchy root
  * @prev: previously returned memcg, NULL on first invocation
  * @reclaim: cookie for shared reclaim walks, NULL for full walks
+ * @cond: filter for visited nodes, NULL for no filter
  *
  * Returns references to children of the hierarchy below @root, or
  * @root itself, or %NULL after a full round-trip.
@@ -1189,9 +1101,10 @@ static void mem_cgroup_iter_update(struct mem_cgroup_reclaim_iter *iter,
  * divide up the memcgs in the hierarchy among all concurrent
  * reclaimers operating on the same zone and priority.
  */
-struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
+struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
 				   struct mem_cgroup *prev,
-				   struct mem_cgroup_reclaim_cookie *reclaim)
+				   struct mem_cgroup_reclaim_cookie *reclaim,
+				   mem_cgroup_iter_filter cond)
 {
 	struct mem_cgroup *memcg = NULL;
 	struct mem_cgroup *last_visited = NULL;
@@ -1208,7 +1121,9 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 	if (!root->use_hierarchy && root != root_mem_cgroup) {
 		if (prev)
 			goto out_css_put;
-		return root;
+		if (mem_cgroup_filter(root, root, cond) == VISIT)
+			return root;
+		return NULL;
 	}
 
 	rcu_read_lock();
@@ -1231,7 +1146,7 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 			last_visited = mem_cgroup_iter_load(iter, root, &seq);
 		}
 
-		memcg = __mem_cgroup_iter_next(root, last_visited);
+		memcg = __mem_cgroup_iter_next(root, last_visited, cond);
 
 		if (reclaim) {
 			mem_cgroup_iter_update(iter, last_visited, memcg, seq);
@@ -1242,7 +1157,11 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 				reclaim->generation = iter->generation;
 		}
 
-		if (prev && !memcg)
+		/*
+		 * We have finished the whole tree walk or no group has been
+		 * visited because filter told us to skip the root node.
+		 */
+		if (!memcg && (prev || (cond && !last_visited)))
 			goto out_unlock;
 	}
 out_unlock:
@@ -1886,6 +1805,7 @@ static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg,
 	return total;
 }
 
+#if MAX_NUMNODES > 1
 /**
  * test_mem_cgroup_node_reclaimable
  * @memcg: the target memcg
@@ -1908,7 +1828,6 @@ static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *memcg,
 	return false;
 
 }
-#if MAX_NUMNODES > 1
 
 /*
  * Always updating the nodemask is not very good - even if we have an empty
@@ -1976,115 +1895,64 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *memcg)
 	return node;
 }
 
-/*
- * Check all nodes whether it contains reclaimable pages or not.
- * For quick scan, we make use of scan_nodes. This will allow us to skip
- * unused nodes. But scan_nodes is lazily updated and may not cotain
- * enough new information. We need to do double check.
- */
-static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
-{
-	int nid;
-
-	/*
-	 * quick check...making use of scan_node.
-	 * We can skip unused nodes.
-	 */
-	if (!nodes_empty(memcg->scan_nodes)) {
-		for (nid = first_node(memcg->scan_nodes);
-		     nid < MAX_NUMNODES;
-		     nid = next_node(nid, memcg->scan_nodes)) {
-
-			if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
-				return true;
-		}
-	}
-	/*
-	 * Check rest of nodes.
-	 */
-	for_each_node_state(nid, N_MEMORY) {
-		if (node_isset(nid, memcg->scan_nodes))
-			continue;
-		if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
-			return true;
-	}
-	return false;
-}
-
 #else
 int mem_cgroup_select_victim_node(struct mem_cgroup *memcg)
 {
 	return 0;
 }
 
-static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
-{
-	return test_mem_cgroup_node_reclaimable(memcg, 0, noswap);
-}
 #endif
 
-static int mem_cgroup_soft_reclaim(struct mem_cgroup *root_memcg,
-				   struct zone *zone,
-				   gfp_t gfp_mask,
-				   unsigned long *total_scanned)
-{
-	struct mem_cgroup *victim = NULL;
-	int total = 0;
-	int loop = 0;
-	unsigned long excess;
-	unsigned long nr_scanned;
-	struct mem_cgroup_reclaim_cookie reclaim = {
-		.zone = zone,
-		.priority = 0,
-	};
-
-	excess = res_counter_soft_limit_excess(&root_memcg->res) >> PAGE_SHIFT;
-
-	while (1) {
-		victim = mem_cgroup_iter(root_memcg, victim, &reclaim);
-		if (!victim) {
-			loop++;
-			if (loop >= 2) {
-				/*
-				 * If we have not been able to reclaim
-				 * anything, it might because there are
-				 * no reclaimable pages under this hierarchy
-				 */
-				if (!total)
-					break;
-				/*
-				 * We want to do more targeted reclaim.
-				 * excess >> 2 is not to excessive so as to
-				 * reclaim too much, nor too less that we keep
-				 * coming back to reclaim from this cgroup
-				 */
-				if (total >= (excess >> 2) ||
-					(loop > MEM_CGROUP_MAX_RECLAIM_LOOPS))
-					break;
-			}
-			continue;
-		}
-		if (!mem_cgroup_reclaimable(victim, false))
-			continue;
-		total += mem_cgroup_shrink_node_zone(victim, gfp_mask, false,
-						     zone, &nr_scanned);
-		*total_scanned += nr_scanned;
-		if (!res_counter_soft_limit_excess(&root_memcg->res))
+/*
+ * A group is eligible for the soft limit reclaim under the given root
+ * hierarchy if
+ *	a) it is over its soft limit
+ *	b) any parent up the hierarchy is over its soft limit
+ *
+ * If the given group doesn't have any children over the limit then it
+ * doesn't make any sense to iterate its subtree.
+ */
+enum mem_cgroup_filter_t
+mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
+		struct mem_cgroup *root)
+{
+	struct mem_cgroup *parent;
+
+	if (!memcg)
+		memcg = root_mem_cgroup;
+	parent = memcg;
+
+	if (res_counter_soft_limit_excess(&memcg->res))
+		return VISIT;
+
+	/*
+	 * If any parent up to the root in the hierarchy is over its soft limit
+	 * then we have to obey and reclaim from this group as well.
+	 */
+	while ((parent = parent_mem_cgroup(parent))) {
+		if (res_counter_soft_limit_excess(&parent->res))
+			return VISIT;
+		if (parent == root)
 			break;
 	}
-	mem_cgroup_iter_break(root_memcg, victim);
-	return total;
+
+	if (!atomic_read(&memcg->children_in_excess))
+		return SKIP_TREE;
+	return SKIP;
 }
 
+static DEFINE_SPINLOCK(memcg_oom_lock);
+
 /*
  * Check OOM-Killer is already running under our hierarchy.
  * If someone is running, return false.
- * Has to be called with memcg_oom_lock
  */
-static bool mem_cgroup_oom_lock(struct mem_cgroup *memcg)
+static bool mem_cgroup_oom_trylock(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter, *failed = NULL;
 
+	spin_lock(&memcg_oom_lock);
+
 	for_each_mem_cgroup_tree(iter, memcg) {
 		if (iter->oom_lock) {
 			/*
@@ -2098,33 +1966,33 @@ static bool mem_cgroup_oom_lock(struct mem_cgroup *memcg)
 			iter->oom_lock = true;
 	}
 
-	if (!failed)
-		return true;
-
-	/*
-	 * OK, we failed to lock the whole subtree so we have to clean up
-	 * what we set up to the failing subtree
-	 */
-	for_each_mem_cgroup_tree(iter, memcg) {
-		if (iter == failed) {
-			mem_cgroup_iter_break(memcg, iter);
-			break;
+	if (failed) {
+		/*
+		 * OK, we failed to lock the whole subtree so we have
+		 * to clean up what we set up to the failing subtree
+		 */
+		for_each_mem_cgroup_tree(iter, memcg) {
+			if (iter == failed) {
+				mem_cgroup_iter_break(memcg, iter);
+				break;
+			}
+			iter->oom_lock = false;
 		}
-		iter->oom_lock = false;
 	}
-	return false;
+
+	spin_unlock(&memcg_oom_lock);
+
+	return !failed;
 }
 
-/*
- * Has to be called with memcg_oom_lock
- */
-static int mem_cgroup_oom_unlock(struct mem_cgroup *memcg)
+static void mem_cgroup_oom_unlock(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter;
 
+	spin_lock(&memcg_oom_lock);
 	for_each_mem_cgroup_tree(iter, memcg)
 		iter->oom_lock = false;
-	return 0;
+	spin_unlock(&memcg_oom_lock);
 }
 
 static void mem_cgroup_mark_under_oom(struct mem_cgroup *memcg)
@@ -2148,7 +2016,6 @@ static void mem_cgroup_unmark_under_oom(struct mem_cgroup *memcg)
 		atomic_add_unless(&iter->under_oom, -1, 0);
 }
 
-static DEFINE_SPINLOCK(memcg_oom_lock);
 static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq);
 
 struct oom_wait_info {
@@ -2178,6 +2045,7 @@ static int memcg_oom_wake_function(wait_queue_t *wait,
 
 static void memcg_wakeup_oom(struct mem_cgroup *memcg)
 {
+	atomic_inc(&memcg->oom_wakeups);
 	/* for filtering, pass "memcg" as argument. */
 	__wake_up(&memcg_oom_waitq, TASK_NORMAL, 0, memcg);
 }
@@ -2189,56 +2057,136 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
 }
 
 /*
- * try to call OOM killer. returns false if we should exit memory-reclaim loop.
+ * try to call OOM killer
  */
-static bool mem_cgroup_handle_oom(struct mem_cgroup *memcg, gfp_t mask,
-				  int order)
+static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-	struct oom_wait_info owait;
-	bool locked, need_to_kill;
+	bool locked;
+	int wakeups;
 
-	owait.memcg = memcg;
-	owait.wait.flags = 0;
-	owait.wait.func = memcg_oom_wake_function;
-	owait.wait.private = current;
-	INIT_LIST_HEAD(&owait.wait.task_list);
-	need_to_kill = true;
-	mem_cgroup_mark_under_oom(memcg);
+	if (!current->memcg_oom.may_oom)
+		return;
+
+	current->memcg_oom.in_memcg_oom = 1;
 
-	/* At first, try to OOM lock hierarchy under memcg.*/
-	spin_lock(&memcg_oom_lock);
-	locked = mem_cgroup_oom_lock(memcg);
 	/*
-	 * Even if signal_pending(), we can't quit charge() loop without
-	 * accounting. So, UNINTERRUPTIBLE is appropriate. But SIGKILL
-	 * under OOM is always welcomed, use TASK_KILLABLE here.
+	 * As with any blocking lock, a contender needs to start
+	 * listening for wakeups before attempting the trylock,
+	 * otherwise it can miss the wakeup from the unlock and sleep
+	 * indefinitely.  This is just open-coded because our locking
+	 * is so particular to memcg hierarchies.
 	 */
-	prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
-	if (!locked || memcg->oom_kill_disable)
-		need_to_kill = false;
+	wakeups = atomic_read(&memcg->oom_wakeups);
+	mem_cgroup_mark_under_oom(memcg);
+
+	locked = mem_cgroup_oom_trylock(memcg);
+
 	if (locked)
 		mem_cgroup_oom_notify(memcg);
-	spin_unlock(&memcg_oom_lock);
 
-	if (need_to_kill) {
-		finish_wait(&memcg_oom_waitq, &owait.wait);
+	if (locked && !memcg->oom_kill_disable) {
+		mem_cgroup_unmark_under_oom(memcg);
 		mem_cgroup_out_of_memory(memcg, mask, order);
+		mem_cgroup_oom_unlock(memcg);
+		/*
+		 * There is no guarantee that an OOM-lock contender
+		 * sees the wakeups triggered by the OOM kill
+		 * uncharges.  Wake any sleepers explicitely.
+		 */
+		memcg_oom_recover(memcg);
 	} else {
-		schedule();
-		finish_wait(&memcg_oom_waitq, &owait.wait);
+		/*
+		 * A system call can just return -ENOMEM, but if this
+		 * is a page fault and somebody else is handling the
+		 * OOM already, we need to sleep on the OOM waitqueue
+		 * for this memcg until the situation is resolved.
+		 * Which can take some time because it might be
+		 * handled by a userspace task.
+		 *
+		 * However, this is the charge context, which means
+		 * that we may sit on a large call stack and hold
+		 * various filesystem locks, the mmap_sem etc. and we
+		 * don't want the OOM handler to deadlock on them
+		 * while we sit here and wait.  Store the current OOM
+		 * context in the task_struct, then return -ENOMEM.
+		 * At the end of the page fault handler, with the
+		 * stack unwound, pagefault_out_of_memory() will check
+		 * back with us by calling
+		 * mem_cgroup_oom_synchronize(), possibly putting the
+		 * task to sleep.
+		 */
+		current->memcg_oom.oom_locked = locked;
+		current->memcg_oom.wakeups = wakeups;
+		css_get(&memcg->css);
+		current->memcg_oom.wait_on_memcg = memcg;
 	}
-	spin_lock(&memcg_oom_lock);
-	if (locked)
-		mem_cgroup_oom_unlock(memcg);
-	memcg_wakeup_oom(memcg);
-	spin_unlock(&memcg_oom_lock);
+}
 
-	mem_cgroup_unmark_under_oom(memcg);
+/**
+ * mem_cgroup_oom_synchronize - complete memcg OOM handling
+ *
+ * This has to be called at the end of a page fault if the the memcg
+ * OOM handler was enabled and the fault is returning %VM_FAULT_OOM.
+ *
+ * Memcg supports userspace OOM handling, so failed allocations must
+ * sleep on a waitqueue until the userspace task resolves the
+ * situation.  Sleeping directly in the charge context with all kinds
+ * of locks held is not a good idea, instead we remember an OOM state
+ * in the task and mem_cgroup_oom_synchronize() has to be called at
+ * the end of the page fault to put the task to sleep and clean up the
+ * OOM state.
+ *
+ * Returns %true if an ongoing memcg OOM situation was detected and
+ * finalized, %false otherwise.
+ */
+bool mem_cgroup_oom_synchronize(void)
+{
+	struct oom_wait_info owait;
+	struct mem_cgroup *memcg;
 
-	if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
+	/* OOM is global, do not handle */
+	if (!current->memcg_oom.in_memcg_oom)
 		return false;
-	/* Give chance to dying process */
-	schedule_timeout_uninterruptible(1);
+
+	/*
+	 * We invoked the OOM killer but there is a chance that a kill
+	 * did not free up any charges.  Everybody else might already
+	 * be sleeping, so restart the fault and keep the rampage
+	 * going until some charges are released.
+	 */
+	memcg = current->memcg_oom.wait_on_memcg;
+	if (!memcg)
+		goto out;
+
+	if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
+		goto out_memcg;
+
+	owait.memcg = memcg;
+	owait.wait.flags = 0;
+	owait.wait.func = memcg_oom_wake_function;
+	owait.wait.private = current;
+	INIT_LIST_HEAD(&owait.wait.task_list);
+
+	prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
+	/* Only sleep if we didn't miss any wakeups since OOM */
+	if (atomic_read(&memcg->oom_wakeups) == current->memcg_oom.wakeups)
+		schedule();
+	finish_wait(&memcg_oom_waitq, &owait.wait);
+out_memcg:
+	mem_cgroup_unmark_under_oom(memcg);
+	if (current->memcg_oom.oom_locked) {
+		mem_cgroup_oom_unlock(memcg);
+		/*
+		 * There is no guarantee that an OOM-lock contender
+		 * sees the wakeups triggered by the OOM kill
+		 * uncharges.  Wake any sleepers explicitely.
+		 */
+		memcg_oom_recover(memcg);
+	}
+	css_put(&memcg->css);
+	current->memcg_oom.wait_on_memcg = NULL;
+out:
+	current->memcg_oom.in_memcg_oom = 0;
 	return true;
 }
 
@@ -2469,7 +2417,7 @@ static void drain_all_stock(struct mem_cgroup *root_memcg, bool sync)
 			flush_work(&stock->work);
 	}
 out:
- 	put_online_cpus();
+	put_online_cpus();
 }
 
 /*
@@ -2551,12 +2499,11 @@ enum {
 	CHARGE_RETRY,		/* need to retry but retry is not bad */
 	CHARGE_NOMEM,		/* we can't do more. return -ENOMEM */
 	CHARGE_WOULDBLOCK,	/* GFP_WAIT wasn't set and no enough res. */
-	CHARGE_OOM_DIE,		/* the current is killed because of OOM */
 };
 
 static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
 				unsigned int nr_pages, unsigned int min_pages,
-				bool oom_check)
+				bool invoke_oom)
 {
 	unsigned long csize = nr_pages * PAGE_SIZE;
 	struct mem_cgroup *mem_over_limit;
@@ -2613,14 +2560,10 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
 	if (mem_cgroup_wait_acct_move(mem_over_limit))
 		return CHARGE_RETRY;
 
-	/* If we don't need to call oom-killer at el, return immediately */
-	if (!oom_check)
-		return CHARGE_NOMEM;
-	/* check OOM */
-	if (!mem_cgroup_handle_oom(mem_over_limit, gfp_mask, get_order(csize)))
-		return CHARGE_OOM_DIE;
+	if (invoke_oom)
+		mem_cgroup_oom(mem_over_limit, gfp_mask, get_order(csize));
 
-	return CHARGE_RETRY;
+	return CHARGE_NOMEM;
 }
 
 /*
@@ -2723,7 +2666,7 @@ again:
 	}
 
 	do {
-		bool oom_check;
+		bool invoke_oom = oom && !nr_oom_retries;
 
 		/* If killed, bypass charge */
 		if (fatal_signal_pending(current)) {
@@ -2731,14 +2674,8 @@ again:
 			goto bypass;
 		}
 
-		oom_check = false;
-		if (oom && !nr_oom_retries) {
-			oom_check = true;
-			nr_oom_retries = MEM_CGROUP_RECLAIM_RETRIES;
-		}
-
-		ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, nr_pages,
-		    oom_check);
+		ret = mem_cgroup_do_charge(memcg, gfp_mask, batch,
+					   nr_pages, invoke_oom);
 		switch (ret) {
 		case CHARGE_OK:
 			break;
@@ -2751,16 +2688,12 @@ again:
 			css_put(&memcg->css);
 			goto nomem;
 		case CHARGE_NOMEM: /* OOM routine works */
-			if (!oom) {
+			if (!oom || invoke_oom) {
 				css_put(&memcg->css);
 				goto nomem;
 			}
-			/* If oom, we never return -ENOMEM */
 			nr_oom_retries--;
 			break;
-		case CHARGE_OOM_DIE: /* Killed by OOM Killer */
-			css_put(&memcg->css);
-			goto bypass;
 		}
 	} while (ret != CHARGE_OK);
 
@@ -2901,7 +2834,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
 	 * is accessed after testing USED bit. To make pc->mem_cgroup visible
 	 * before USED bit, we need memory barrier here.
 	 * See mem_cgroup_add_lru_list(), etc.
- 	 */
+	 */
 	smp_wmb();
 	SetPageCgroupUsed(pc);
 
@@ -2924,9 +2857,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
 	unlock_page_cgroup(pc);
 
 	/*
-	 * "charge_statistics" updated event counter. Then, check it.
-	 * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
-	 * if they exceeds softlimit.
+	 * "charge_statistics" updated event counter.
 	 */
 	memcg_check_events(memcg, page);
 }
@@ -3195,11 +3126,11 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
 	if (!s->memcg_params)
 		return -ENOMEM;
 
-	INIT_WORK(&s->memcg_params->destroy,
-			kmem_cache_destroy_work_func);
 	if (memcg) {
 		s->memcg_params->memcg = memcg;
 		s->memcg_params->root_cache = root_cache;
+		INIT_WORK(&s->memcg_params->destroy,
+				kmem_cache_destroy_work_func);
 	} else
 		s->memcg_params->is_root_cache = true;
 
@@ -3642,9 +3573,9 @@ __memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **_memcg, int order)
 	 * the page allocator. Therefore, the following sequence when backed by
 	 * the SLUB allocator:
 	 *
-	 * 	memcg_stop_kmem_account();
-	 * 	kmalloc(<large_number>)
-	 * 	memcg_resume_kmem_account();
+	 *	memcg_stop_kmem_account();
+	 *	kmalloc(<large_number>)
+	 *	memcg_resume_kmem_account();
 	 *
 	 * would effectively ignore the fact that we should skip accounting,
 	 * since it will drive us directly to this function without passing
@@ -4673,7 +4604,7 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,
 				   MEM_CGROUP_RECLAIM_SHRINK);
 		curusage = res_counter_read_u64(&memcg->res, RES_USAGE);
 		/* Usage is reduced ? */
-  		if (curusage >= oldusage)
+		if (curusage >= oldusage)
 			retry_count--;
 		else
 			oldusage = curusage;
@@ -4694,7 +4625,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,
 	int enlarge = 0;
 
 	/* see mem_cgroup_resize_res_limit */
- 	retry_count = children * MEM_CGROUP_RECLAIM_RETRIES;
+	retry_count = children * MEM_CGROUP_RECLAIM_RETRIES;
 	oldusage = res_counter_read_u64(&memcg->memsw, RES_USAGE);
 	while (retry_count) {
 		if (signal_pending(current)) {
@@ -4743,98 +4674,6 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,
 	return ret;
 }
 
-unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
-					    gfp_t gfp_mask,
-					    unsigned long *total_scanned)
-{
-	unsigned long nr_reclaimed = 0;
-	struct mem_cgroup_per_zone *mz, *next_mz = NULL;
-	unsigned long reclaimed;
-	int loop = 0;
-	struct mem_cgroup_tree_per_zone *mctz;
-	unsigned long long excess;
-	unsigned long nr_scanned;
-
-	if (order > 0)
-		return 0;
-
-	mctz = soft_limit_tree_node_zone(zone_to_nid(zone), zone_idx(zone));
-	/*
-	 * This loop can run a while, specially if mem_cgroup's continuously
-	 * keep exceeding their soft limit and putting the system under
-	 * pressure
-	 */
-	do {
-		if (next_mz)
-			mz = next_mz;
-		else
-			mz = mem_cgroup_largest_soft_limit_node(mctz);
-		if (!mz)
-			break;
-
-		nr_scanned = 0;
-		reclaimed = mem_cgroup_soft_reclaim(mz->memcg, zone,
-						    gfp_mask, &nr_scanned);
-		nr_reclaimed += reclaimed;
-		*total_scanned += nr_scanned;
-		spin_lock(&mctz->lock);
-
-		/*
-		 * If we failed to reclaim anything from this memory cgroup
-		 * it is time to move on to the next cgroup
-		 */
-		next_mz = NULL;
-		if (!reclaimed) {
-			do {
-				/*
-				 * Loop until we find yet another one.
-				 *
-				 * By the time we get the soft_limit lock
-				 * again, someone might have aded the
-				 * group back on the RB tree. Iterate to
-				 * make sure we get a different mem.
-				 * mem_cgroup_largest_soft_limit_node returns
-				 * NULL if no other cgroup is present on
-				 * the tree
-				 */
-				next_mz =
-				__mem_cgroup_largest_soft_limit_node(mctz);
-				if (next_mz == mz)
-					css_put(&next_mz->memcg->css);
-				else /* next_mz == NULL or other memcg */
-					break;
-			} while (1);
-		}
-		__mem_cgroup_remove_exceeded(mz->memcg, mz, mctz);
-		excess = res_counter_soft_limit_excess(&mz->memcg->res);
-		/*
-		 * One school of thought says that we should not add
-		 * back the node to the tree if reclaim returns 0.
-		 * But our reclaim could return 0, simply because due
-		 * to priority we are exposing a smaller subset of
-		 * memory to reclaim from. Consider this as a longer
-		 * term TODO.
-		 */
-		/* If excess == 0, no tree ops */
-		__mem_cgroup_insert_exceeded(mz->memcg, mz, mctz, excess);
-		spin_unlock(&mctz->lock);
-		css_put(&mz->memcg->css);
-		loop++;
-		/*
-		 * Could not reclaim anything and there are no more
-		 * mem cgroups to try or we seem to be looping without
-		 * reclaiming anything.
-		 */
-		if (!nr_reclaimed &&
-			(next_mz == NULL ||
-			loop > MEM_CGROUP_MAX_SOFT_LIMIT_RECLAIM_LOOPS))
-			break;
-	} while (!nr_reclaimed);
-	if (next_mz)
-		css_put(&next_mz->memcg->css);
-	return nr_reclaimed;
-}
-
 /**
  * mem_cgroup_force_empty_list - clears LRU of a group
  * @memcg: group to clear
@@ -5005,15 +4844,10 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
 static int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-	int ret;
 
 	if (mem_cgroup_is_root(memcg))
 		return -EINVAL;
-	css_get(&memcg->css);
-	ret = mem_cgroup_force_empty(memcg);
-	css_put(&memcg->css);
-
-	return ret;
+	return mem_cgroup_force_empty(memcg);
 }
 
 
@@ -5157,7 +4991,7 @@ static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
 	 */
 	mutex_lock(&memcg_create_mutex);
 	mutex_lock(&set_limit_mutex);
-	if (!memcg->kmem_account_flags && val != RESOURCE_MAX) {
+	if (!memcg->kmem_account_flags && val != RES_COUNTER_MAX) {
 		if (cgroup_task_count(cont) || memcg_has_children(memcg)) {
 			ret = -EBUSY;
 			goto out;
@@ -5167,7 +5001,7 @@ static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
 
 		ret = memcg_update_cache_sizes(memcg);
 		if (ret) {
-			res_counter_set_limit(&memcg->kmem, RESOURCE_MAX);
+			res_counter_set_limit(&memcg->kmem, RES_COUNTER_MAX);
 			goto out;
 		}
 		static_key_slow_inc(&memcg_kmem_enabled_key);
@@ -6110,8 +5944,6 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 	for (zone = 0; zone < MAX_NR_ZONES; zone++) {
 		mz = &pn->zoneinfo[zone];
 		lruvec_init(&mz->lruvec);
-		mz->usage_in_excess = 0;
-		mz->on_tree = false;
 		mz->memcg = memcg;
 	}
 	memcg->nodeinfo[node] = pn;
@@ -6167,7 +5999,6 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 	int node;
 	size_t size = memcg_size();
 
-	mem_cgroup_remove_from_trees(memcg);
 	free_css_id(&mem_cgroup_subsys, &memcg->css);
 
 	for_each_node(node)
@@ -6204,29 +6035,6 @@ struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg)
 }
 EXPORT_SYMBOL(parent_mem_cgroup);
 
-static void __init mem_cgroup_soft_limit_tree_init(void)
-{
-	struct mem_cgroup_tree_per_node *rtpn;
-	struct mem_cgroup_tree_per_zone *rtpz;
-	int tmp, node, zone;
-
-	for_each_node(node) {
-		tmp = node;
-		if (!node_state(node, N_NORMAL_MEMORY))
-			tmp = -1;
-		rtpn = kzalloc_node(sizeof(*rtpn), GFP_KERNEL, tmp);
-		BUG_ON(!rtpn);
-
-		soft_limit_tree.rb_tree_per_node[node] = rtpn;
-
-		for (zone = 0; zone < MAX_NR_ZONES; zone++) {
-			rtpz = &rtpn->rb_tree_per_zone[zone];
-			rtpz->rb_root = RB_ROOT;
-			spin_lock_init(&rtpz->lock);
-		}
-	}
-}
-
 static struct cgroup_subsys_state * __ref
 mem_cgroup_css_alloc(struct cgroup *cont)
 {
@@ -6256,6 +6064,7 @@ mem_cgroup_css_alloc(struct cgroup *cont)
 	mutex_init(&memcg->thresholds_lock);
 	spin_lock_init(&memcg->move_lock);
 	vmpressure_init(&memcg->vmpressure);
+	spin_lock_init(&memcg->soft_lock);
 
 	return &memcg->css;
 
@@ -6334,6 +6143,13 @@ static void mem_cgroup_css_offline(struct cgroup *cont)
 
 	mem_cgroup_invalidate_reclaim_iterators(memcg);
 	mem_cgroup_reparent_charges(memcg);
+	if (memcg->soft_contributed) {
+		while ((memcg = parent_mem_cgroup(memcg)))
+			atomic_dec(&memcg->children_in_excess);
+
+		if (memcg != root_mem_cgroup && !root_mem_cgroup->use_hierarchy)
+			atomic_dec(&root_mem_cgroup->children_in_excess);
+	}
 	mem_cgroup_destroy_all_caches(memcg);
 	vmpressure_cleanup(&memcg->vmpressure);
 }
@@ -7009,7 +6825,6 @@ static int __init mem_cgroup_init(void)
 {
 	hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
 	enable_swap_cgroup();
-	mem_cgroup_soft_limit_tree_init();
 	memcg_stock_init();
 	return 0;
 }
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 2c13aa7..bee58d8 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -248,10 +248,12 @@ void shake_page(struct page *p, int access)
 	 */
 	if (access) {
 		int nr;
+		int nid = page_to_nid(p);
 		do {
 			struct shrink_control shrink = {
 				.gfp_mask = GFP_KERNEL,
 			};
+			node_set(nid, shrink.nodes_to_scan);
 
 			nr = shrink_slab(&shrink, 1000, 1000);
 			if (page_count(p) == 1)
@@ -1286,7 +1288,10 @@ static void memory_failure_work_func(struct work_struct *work)
 		spin_unlock_irqrestore(&mf_cpu->lock, proc_flags);
 		if (!gotten)
 			break;
-		memory_failure(entry.pfn, entry.trapno, entry.flags);
+		if (entry.flags & MF_SOFT_OFFLINE)
+			soft_offline_page(pfn_to_page(entry.pfn), entry.flags);
+		else
+			memory_failure(entry.pfn, entry.trapno, entry.flags);
 	}
 }
 
diff --git a/mm/memory.c b/mm/memory.c
index 1ce2e2a..8205e0a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -374,30 +374,6 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
 #endif /* CONFIG_HAVE_RCU_TABLE_FREE */
 
 /*
- * If a p?d_bad entry is found while walking page tables, report
- * the error, before resetting entry to p?d_none.  Usually (but
- * very seldom) called out from the p?d_none_or_clear_bad macros.
- */
-
-void pgd_clear_bad(pgd_t *pgd)
-{
-	pgd_ERROR(*pgd);
-	pgd_clear(pgd);
-}
-
-void pud_clear_bad(pud_t *pud)
-{
-	pud_ERROR(*pud);
-	pud_clear(pud);
-}
-
-void pmd_clear_bad(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-	pmd_clear(pmd);
-}
-
-/*
  * Note: this doesn't free the actual pages themselves. That
  * has been handled earlier when unmapping all the memory regions.
  */
@@ -1141,9 +1117,12 @@ again:
 				continue;
 			if (unlikely(details) && details->nonlinear_vma
 			    && linear_page_index(details->nonlinear_vma,
-						addr) != page->index)
-				set_pte_at(mm, addr, pte,
-					   pgoff_to_pte(page->index));
+						addr) != page->index) {
+				pte_t ptfile = pgoff_to_pte(page->index);
+				if (pte_soft_dirty(ptent))
+					pte_file_mksoft_dirty(ptfile);
+				set_pte_at(mm, addr, pte, ptfile);
+			}
 			if (PageAnon(page))
 				rss[MM_ANONPAGES]--;
 			else {
@@ -3115,6 +3094,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		exclusive = 1;
 	}
 	flush_icache_page(vma, page);
+	if (pte_swp_soft_dirty(orig_pte))
+		pte = pte_mksoft_dirty(pte);
 	set_pte_at(mm, address, page_table, pte);
 	if (page == swapcache)
 		do_page_add_anon_rmap(page, vma, address, exclusive);
@@ -3408,6 +3389,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 		entry = mk_pte(page, vma->vm_page_prot);
 		if (flags & FAULT_FLAG_WRITE)
 			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+		else if (pte_file(orig_pte) && pte_file_soft_dirty(orig_pte))
+			pte_mksoft_dirty(entry);
 		if (anon) {
 			inc_mm_counter_fast(mm, MM_ANONPAGES);
 			page_add_new_anon_rmap(page, vma, address);
@@ -3693,7 +3676,7 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
  * but allow concurrent faults), and pte mapped but not yet locked.
  * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-int handle_pte_fault(struct mm_struct *mm,
+static int handle_pte_fault(struct mm_struct *mm,
 		     struct vm_area_struct *vma, unsigned long address,
 		     pte_t *pte, pmd_t *pmd, unsigned int flags)
 {
@@ -3752,22 +3735,14 @@ unlock:
 /*
  * By the time we get here, we already hold the mm semaphore
  */
-int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
-		unsigned long address, unsigned int flags)
+static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+			     unsigned long address, unsigned int flags)
 {
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 
-	__set_current_state(TASK_RUNNING);
-
-	count_vm_event(PGFAULT);
-	mem_cgroup_count_vm_event(mm, PGFAULT);
-
-	/* do counter updates before entering really critical section. */
-	check_sync_rss_stat(current);
-
 	if (unlikely(is_vm_hugetlb_page(vma)))
 		return hugetlb_fault(mm, vma, address, flags);
 
@@ -3780,9 +3755,12 @@ retry:
 	if (!pmd)
 		return VM_FAULT_OOM;
 	if (pmd_none(*pmd) && transparent_hugepage_enabled(vma)) {
+		int ret = VM_FAULT_FALLBACK;
 		if (!vma->vm_ops)
-			return do_huge_pmd_anonymous_page(mm, vma, address,
-							  pmd, flags);
+			ret = do_huge_pmd_anonymous_page(mm, vma, address,
+					pmd, flags);
+		if (!(ret & VM_FAULT_FALLBACK))
+			return ret;
 	} else {
 		pmd_t orig_pmd = *pmd;
 		int ret;
@@ -3848,6 +3826,37 @@ retry:
 	return handle_pte_fault(mm, vma, address, pte, pmd, flags);
 }
 
+int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+		    unsigned long address, unsigned int flags)
+{
+	int ret;
+
+	__set_current_state(TASK_RUNNING);
+
+	count_vm_event(PGFAULT);
+	mem_cgroup_count_vm_event(mm, PGFAULT);
+
+	/* do counter updates before entering really critical section. */
+	check_sync_rss_stat(current);
+
+	/*
+	 * Enable the memcg OOM handling for faults triggered in user
+	 * space.  Kernel faults are handled more gracefully.
+	 */
+	if (flags & FAULT_FLAG_USER)
+		mem_cgroup_enable_oom();
+
+	ret = __handle_mm_fault(mm, vma, address, flags);
+
+	if (flags & FAULT_FLAG_USER)
+		mem_cgroup_disable_oom();
+
+	if (WARN_ON(task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM)))
+		mem_cgroup_oom_synchronize();
+
+	return ret;
+}
+
 #ifndef __PAGETABLE_PUD_FOLDED
 /*
  * Allocate page upper directory.
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 4baf12e..27022ca 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -123,16 +123,19 @@ static struct mempolicy preferred_node_policy[MAX_NUMNODES];
 static struct mempolicy *get_task_policy(struct task_struct *p)
 {
 	struct mempolicy *pol = p->mempolicy;
-	int node;
 
 	if (!pol) {
-		node = numa_node_id();
-		if (node != NUMA_NO_NODE)
-			pol = &preferred_node_policy[node];
+		int node = numa_node_id();
 
-		/* preferred_node_policy is not initialised early in boot */
-		if (!pol->mode)
-			pol = NULL;
+		if (node != NUMA_NO_NODE) {
+			pol = &preferred_node_policy[node];
+			/*
+			 * preferred_node_policy is not initialised early in
+			 * boot
+			 */
+			if (!pol->mode)
+				pol = NULL;
+		}
 	}
 
 	return pol;
@@ -2065,6 +2068,16 @@ retry_cpuset:
 }
 EXPORT_SYMBOL(alloc_pages_current);
 
+int vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst)
+{
+	struct mempolicy *pol = mpol_dup(vma_policy(src));
+
+	if (IS_ERR(pol))
+		return PTR_ERR(pol);
+	dst->vm_policy = pol;
+	return 0;
+}
+
 /*
  * If mpol_dup() sees current->cpuset == cpuset_being_rebound, then it
  * rebinds the mempolicy its copying by calling mpol_rebind_policy()
diff --git a/mm/migrate.c b/mm/migrate.c
index 6f0c244..1da0092 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -307,7 +307,7 @@ static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
  * 2 for pages with a mapping
  * 3 for pages with a mapping and PagePrivate/PagePrivate2 set.
  */
-static int migrate_page_move_mapping(struct address_space *mapping,
+int migrate_page_move_mapping(struct address_space *mapping,
 		struct page *newpage, struct page *page,
 		struct buffer_head *head, enum migrate_mode mode)
 {
diff --git a/mm/mlock.c b/mm/mlock.c
index 79b7cf7..92022eb 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -506,6 +506,7 @@ static int do_mlockall(int flags)
 
 		/* Ignore errors */
 		mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags);
+		cond_resched();
 	}
 out:
 	return 0;
diff --git a/mm/mmap.c b/mm/mmap.c
index 1edbaa3..519ce78 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1202,7 +1202,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 			unsigned long *populate)
 {
 	struct mm_struct * mm = current->mm;
-	struct inode *inode;
 	vm_flags_t vm_flags;
 
 	*populate = 0;
@@ -1265,9 +1264,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 			return -EAGAIN;
 	}
 
-	inode = file ? file_inode(file) : NULL;
-
 	if (file) {
+		struct inode *inode = file_inode(file);
+
 		switch (flags & MAP_TYPE) {
 		case MAP_SHARED:
 			if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE))
@@ -1302,6 +1301,8 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 
 			if (!file->f_op || !file->f_op->mmap)
 				return -ENODEV;
+			if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
+				return -EINVAL;
 			break;
 
 		default:
@@ -1310,6 +1311,8 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	} else {
 		switch (flags & MAP_TYPE) {
 		case MAP_SHARED:
+			if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
+				return -EINVAL;
 			/*
 			 * Ignore pgoff.
 			 */
@@ -1476,11 +1479,9 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma, *prev;
-	int correct_wcount = 0;
 	int error;
 	struct rb_node **rb_link, *rb_parent;
 	unsigned long charged = 0;
-	struct inode *inode =  file ? file_inode(file) : NULL;
 
 	/* Check against address space limit. */
 	if (!may_expand_vm(mm, len >> PAGE_SHIFT)) {
@@ -1544,16 +1545,11 @@ munmap_back:
 	vma->vm_pgoff = pgoff;
 	INIT_LIST_HEAD(&vma->anon_vma_chain);
 
-	error = -EINVAL;	/* when rejecting VM_GROWSDOWN|VM_GROWSUP */
-
 	if (file) {
-		if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
-			goto free_vma;
 		if (vm_flags & VM_DENYWRITE) {
 			error = deny_write_access(file);
 			if (error)
 				goto free_vma;
-			correct_wcount = 1;
 		}
 		vma->vm_file = get_file(file);
 		error = file->f_op->mmap(file, vma);
@@ -1573,8 +1569,6 @@ munmap_back:
 		pgoff = vma->vm_pgoff;
 		vm_flags = vma->vm_flags;
 	} else if (vm_flags & VM_SHARED) {
-		if (unlikely(vm_flags & (VM_GROWSDOWN|VM_GROWSUP)))
-			goto free_vma;
 		error = shmem_zero_setup(vma);
 		if (error)
 			goto free_vma;
@@ -1596,11 +1590,10 @@ munmap_back:
 	}
 
 	vma_link(mm, vma, prev, rb_link, rb_parent);
-	file = vma->vm_file;
-
 	/* Once vma denies write, undo our temporary denial count */
-	if (correct_wcount)
-		atomic_inc(&inode->i_writecount);
+	if (vm_flags & VM_DENYWRITE)
+		allow_write_access(file);
+	file = vma->vm_file;
 out:
 	perf_event_mmap(vma);
 
@@ -1619,8 +1612,8 @@ out:
 	return addr;
 
 unmap_and_free_vma:
-	if (correct_wcount)
-		atomic_inc(&inode->i_writecount);
+	if (vm_flags & VM_DENYWRITE)
+		allow_write_access(file);
 	vma->vm_file = NULL;
 	fput(file);
 
@@ -2380,7 +2373,6 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
 	      unsigned long addr, int new_below)
 {
-	struct mempolicy *pol;
 	struct vm_area_struct *new;
 	int err = -ENOMEM;
 
@@ -2404,12 +2396,9 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
 		new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT);
 	}
 
-	pol = mpol_dup(vma_policy(vma));
-	if (IS_ERR(pol)) {
-		err = PTR_ERR(pol);
+	err = vma_dup_policy(vma, new);
+	if (err)
 		goto out_free_vma;
-	}
-	vma_set_policy(new, pol);
 
 	if (anon_vma_clone(new, vma))
 		goto out_free_mpol;
@@ -2437,7 +2426,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
 		fput(new->vm_file);
 	unlink_anon_vmas(new);
  out_free_mpol:
-	mpol_put(pol);
+	mpol_put(vma_policy(new));
  out_free_vma:
 	kmem_cache_free(vm_area_cachep, new);
  out_err:
@@ -2780,7 +2769,6 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *new_vma, *prev;
 	struct rb_node **rb_link, *rb_parent;
-	struct mempolicy *pol;
 	bool faulted_in_anon_vma = true;
 
 	/*
@@ -2825,10 +2813,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 			new_vma->vm_start = addr;
 			new_vma->vm_end = addr + len;
 			new_vma->vm_pgoff = pgoff;
-			pol = mpol_dup(vma_policy(vma));
-			if (IS_ERR(pol))
+			if (vma_dup_policy(vma, new_vma))
 				goto out_free_vma;
-			vma_set_policy(new_vma, pol);
 			INIT_LIST_HEAD(&new_vma->anon_vma_chain);
 			if (anon_vma_clone(new_vma, vma))
 				goto out_free_mempol;
@@ -2843,7 +2829,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 	return new_vma;
 
  out_free_mempol:
-	mpol_put(pol);
+	mpol_put(vma_policy(new_vma));
  out_free_vma:
 	kmem_cache_free(vm_area_cachep, new_vma);
 	return NULL;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 79e451a..314e9d2 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -288,7 +288,7 @@ enum oom_scan_t oom_scan_process_thread(struct task_struct *task,
 
 /*
  * Simple selection loop. We chose the process with the highest
- * number of 'points'.
+ * number of 'points'.  Returns -1 on scan abort.
  *
  * (not docbooked, we don't want this one cluttering up the manual)
  */
@@ -314,7 +314,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
 			continue;
 		case OOM_SCAN_ABORT:
 			rcu_read_unlock();
-			return ERR_PTR(-1UL);
+			return (struct task_struct *)(-1UL);
 		case OOM_SCAN_OK:
 			break;
 		};
@@ -657,7 +657,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
 		dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
 		panic("Out of memory and no killable processes...\n");
 	}
-	if (PTR_ERR(p) != -1UL) {
+	if (p != (void *)-1UL) {
 		oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
 				 nodemask, "Out of memory");
 		killed = 1;
@@ -678,9 +678,12 @@ out:
  */
 void pagefault_out_of_memory(void)
 {
-	struct zonelist *zonelist = node_zonelist(first_online_node,
-						  GFP_KERNEL);
+	struct zonelist *zonelist;
 
+	if (mem_cgroup_oom_synchronize())
+		return;
+
+	zonelist = node_zonelist(first_online_node, GFP_KERNEL);
 	if (try_set_zonelist_oom(zonelist, GFP_KERNEL)) {
 		out_of_memory(NULL, 0, 0, NULL, false);
 		clear_zonelist_oom(zonelist, GFP_KERNEL);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 3f0c895..d374b29 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -241,9 +241,6 @@ static unsigned long global_dirtyable_memory(void)
 	if (!vm_highmem_is_dirtyable)
 		x -= highmem_dirtyable_memory(x);
 
-	/* Subtract min_free_kbytes */
-	x -= min_t(unsigned long, x, min_free_kbytes >> (PAGE_SHIFT - 10));
-
 	return x + 1;	/* Ensure that we never return 0 */
 }
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b100255..07b5e57 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -721,7 +721,8 @@ static bool free_pages_prepare(struct page *page, unsigned int order)
 		return false;
 
 	if (!PageHighMem(page)) {
-		debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order);
+		debug_check_no_locks_freed(page_address(page),
+					   PAGE_SIZE << order);
 		debug_check_no_obj_freed(page_address(page),
 					   PAGE_SIZE << order);
 	}
@@ -750,19 +751,19 @@ static void __free_pages_ok(struct page *page, unsigned int order)
 void __init __free_pages_bootmem(struct page *page, unsigned int order)
 {
 	unsigned int nr_pages = 1 << order;
+	struct page *p = page;
 	unsigned int loop;
 
-	prefetchw(page);
-	for (loop = 0; loop < nr_pages; loop++) {
-		struct page *p = &page[loop];
-
-		if (loop + 1 < nr_pages)
-			prefetchw(p + 1);
+	prefetchw(p);
+	for (loop = 0; loop < (nr_pages - 1); loop++, p++) {
+		prefetchw(p + 1);
 		__ClearPageReserved(p);
 		set_page_count(p, 0);
 	}
+	__ClearPageReserved(p);
+	set_page_count(p, 0);
 
-	page_zone(page)->managed_pages += 1 << order;
+	page_zone(page)->managed_pages += nr_pages;
 	set_page_refcounted(page);
 	__free_pages(page, order);
 }
@@ -885,7 +886,7 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
 						int migratetype)
 {
 	unsigned int current_order;
-	struct free_area * area;
+	struct free_area *area;
 	struct page *page;
 
 	/* Find a page of the appropriate size in the preferred list */
@@ -1007,14 +1008,60 @@ static void change_pageblock_range(struct page *pageblock_page,
 	}
 }
 
+/*
+ * If breaking a large block of pages, move all free pages to the preferred
+ * allocation list. If falling back for a reclaimable kernel allocation, be
+ * more aggressive about taking ownership of free pages.
+ *
+ * On the other hand, never change migration type of MIGRATE_CMA pageblocks
+ * nor move CMA pages to different free lists. We don't want unmovable pages
+ * to be allocated from MIGRATE_CMA areas.
+ *
+ * Returns the new migratetype of the pageblock (or the same old migratetype
+ * if it was unchanged).
+ */
+static int try_to_steal_freepages(struct zone *zone, struct page *page,
+				  int start_type, int fallback_type)
+{
+	int current_order = page_order(page);
+
+	if (is_migrate_cma(fallback_type))
+		return fallback_type;
+
+	/* Take ownership for orders >= pageblock_order */
+	if (current_order >= pageblock_order) {
+		change_pageblock_range(page, current_order, start_type);
+		return start_type;
+	}
+
+	if (current_order >= pageblock_order / 2 ||
+	    start_type == MIGRATE_RECLAIMABLE ||
+	    page_group_by_mobility_disabled) {
+		int pages;
+
+		pages = move_freepages_block(zone, page, start_type);
+
+		/* Claim the whole block if over half of it is free */
+		if (pages >= (1 << (pageblock_order-1)) ||
+				page_group_by_mobility_disabled) {
+
+			set_pageblock_migratetype(page, start_type);
+			return start_type;
+		}
+
+	}
+
+	return fallback_type;
+}
+
 /* Remove an element from the buddy allocator from the fallback list */
 static inline struct page *
 __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
 {
-	struct free_area * area;
+	struct free_area *area;
 	int current_order;
 	struct page *page;
-	int migratetype, i;
+	int migratetype, new_type, i;
 
 	/* Find the largest possible block of pages in the other list */
 	for (current_order = MAX_ORDER-1; current_order >= order;
@@ -1034,51 +1081,29 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
 					struct page, lru);
 			area->nr_free--;
 
-			/*
-			 * If breaking a large block of pages, move all free
-			 * pages to the preferred allocation list. If falling
-			 * back for a reclaimable kernel allocation, be more
-			 * aggressive about taking ownership of free pages
-			 *
-			 * On the other hand, never change migration
-			 * type of MIGRATE_CMA pageblocks nor move CMA
-			 * pages on different free lists. We don't
-			 * want unmovable pages to be allocated from
-			 * MIGRATE_CMA areas.
-			 */
-			if (!is_migrate_cma(migratetype) &&
-			    (current_order >= pageblock_order / 2 ||
-			     start_migratetype == MIGRATE_RECLAIMABLE ||
-			     page_group_by_mobility_disabled)) {
-				int pages;
-				pages = move_freepages_block(zone, page,
-								start_migratetype);
-
-				/* Claim the whole block if over half of it is free */
-				if (pages >= (1 << (pageblock_order-1)) ||
-						page_group_by_mobility_disabled)
-					set_pageblock_migratetype(page,
-								start_migratetype);
-
-				migratetype = start_migratetype;
-			}
+			new_type = try_to_steal_freepages(zone, page,
+							  start_migratetype,
+							  migratetype);
 
 			/* Remove the page from the freelists */
 			list_del(&page->lru);
 			rmv_page_order(page);
 
-			/* Take ownership for orders >= pageblock_order */
-			if (current_order >= pageblock_order &&
-			    !is_migrate_cma(migratetype))
-				change_pageblock_range(page, current_order,
-							start_migratetype);
-
+			/*
+			 * Borrow the excess buddy pages as well, irrespective
+			 * of whether we stole freepages, or took ownership of
+			 * the pageblock or not.
+			 *
+			 * Exception: When borrowing from MIGRATE_CMA, release
+			 * the excess buddy pages to CMA itself.
+			 */
 			expand(zone, page, order, current_order, area,
 			       is_migrate_cma(migratetype)
 			     ? migratetype : start_migratetype);
 
-			trace_mm_page_alloc_extfrag(page, order, current_order,
-				start_migratetype, migratetype);
+			trace_mm_page_alloc_extfrag(page, order,
+				current_order, start_migratetype, migratetype,
+				new_type == start_migratetype);
 
 			return page;
 		}
@@ -1792,6 +1817,11 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
 	bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
 }
 
+static bool zone_local(struct zone *local_zone, struct zone *zone)
+{
+	return node_distance(local_zone->node, zone->node) == LOCAL_DISTANCE;
+}
+
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
 {
 	return node_isset(local_zone->node, zone->zone_pgdat->reclaim_nodes);
@@ -1829,6 +1859,11 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
 {
 }
 
+static bool zone_local(struct zone *local_zone, struct zone *zone)
+{
+	return true;
+}
+
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
 {
 	return true;
@@ -1864,12 +1899,37 @@ zonelist_scan:
 	 */
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 						high_zoneidx, nodemask) {
+		unsigned long mark;
+
 		if (IS_ENABLED(CONFIG_NUMA) && zlc_active &&
 			!zlc_zone_worth_trying(zonelist, z, allowednodes))
 				continue;
 		if ((alloc_flags & ALLOC_CPUSET) &&
 			!cpuset_zone_allowed_softwall(zone, gfp_mask))
 				continue;
+		BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK);
+		if (unlikely(alloc_flags & ALLOC_NO_WATERMARKS))
+			goto try_this_zone;
+		/*
+		 * Distribute pages in proportion to the individual
+		 * zone size to ensure fair page aging.  The zone a
+		 * page was allocated in should have no effect on the
+		 * time the page has in memory before being reclaimed.
+		 *
+		 * When zone_reclaim_mode is enabled, try to stay in
+		 * local zones in the fastpath.  If that fails, the
+		 * slowpath is entered, which will do another pass
+		 * starting with the local zones, but ultimately fall
+		 * back to remote zones that do not partake in the
+		 * fairness round-robin cycle of this zonelist.
+		 */
+		if (alloc_flags & ALLOC_WMARK_LOW) {
+			if (zone->alloc_batch <= 0)
+				continue;
+			if (zone_reclaim_mode &&
+			    !zone_local(preferred_zone, zone))
+				continue;
+		}
 		/*
 		 * When allocating a page cache page for writing, we
 		 * want to get it from a zone that is within its dirty
@@ -1900,16 +1960,11 @@ zonelist_scan:
 		    (gfp_mask & __GFP_WRITE) && !zone_dirty_ok(zone))
 			goto this_zone_full;
 
-		BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK);
-		if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
-			unsigned long mark;
+		mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK];
+		if (!zone_watermark_ok(zone, order, mark,
+				       classzone_idx, alloc_flags)) {
 			int ret;
 
-			mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK];
-			if (zone_watermark_ok(zone, order, mark,
-				    classzone_idx, alloc_flags))
-				goto try_this_zone;
-
 			if (IS_ENABLED(CONFIG_NUMA) &&
 					!did_zlc_setup && nr_online_nodes > 1) {
 				/*
@@ -1981,7 +2036,8 @@ this_zone_full:
 		goto zonelist_scan;
 	}
 
-	if (page)
+	if (page) {
+		zone->alloc_batch -= 1U << order;
 		/*
 		 * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was
 		 * necessary to allocate the page. The expectation is
@@ -1990,6 +2046,7 @@ this_zone_full:
 		 * for !PFMEMALLOC purposes.
 		 */
 		page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS);
+	}
 
 	return page;
 }
@@ -2321,16 +2378,28 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order,
 	return page;
 }
 
-static inline
-void wake_all_kswapd(unsigned int order, struct zonelist *zonelist,
-						enum zone_type high_zoneidx,
-						enum zone_type classzone_idx)
+static void prepare_slowpath(gfp_t gfp_mask, unsigned int order,
+			     struct zonelist *zonelist,
+			     enum zone_type high_zoneidx,
+			     struct zone *preferred_zone)
 {
 	struct zoneref *z;
 	struct zone *zone;
 
-	for_each_zone_zonelist(zone, z, zonelist, high_zoneidx)
-		wakeup_kswapd(zone, order, classzone_idx);
+	for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+		if (!(gfp_mask & __GFP_NO_KSWAPD))
+			wakeup_kswapd(zone, order, zone_idx(preferred_zone));
+		/*
+		 * Only reset the batches of zones that were actually
+		 * considered in the fast path, we don't want to
+		 * thrash fairness information for zones that are not
+		 * actually part of this zonelist's round-robin cycle.
+		 */
+		if (zone_reclaim_mode && !zone_local(preferred_zone, zone))
+			continue;
+		zone->alloc_batch = high_wmark_pages(zone) -
+			low_wmark_pages(zone);
+	}
 }
 
 static inline int
@@ -2426,9 +2495,8 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
 		goto nopage;
 
 restart:
-	if (!(gfp_mask & __GFP_NO_KSWAPD))
-		wake_all_kswapd(order, zonelist, high_zoneidx,
-						zone_idx(preferred_zone));
+	prepare_slowpath(gfp_mask, order, zonelist,
+			 high_zoneidx, preferred_zone);
 
 	/*
 	 * OK, we're below the kswapd watermark and have kicked background
@@ -3104,7 +3172,7 @@ void show_free_areas(unsigned int filter)
 	}
 
 	for_each_populated_zone(zone) {
- 		unsigned long nr[MAX_ORDER], flags, order, total = 0;
+		unsigned long nr[MAX_ORDER], flags, order, total = 0;
 		unsigned char types[MAX_ORDER];
 
 		if (skip_free_areas_node(filter, zone_to_nid(zone)))
@@ -3416,11 +3484,11 @@ static void build_zonelists_in_zone_order(pg_data_t *pgdat, int nr_nodes)
 static int default_zonelist_order(void)
 {
 	int nid, zone_type;
-	unsigned long low_kmem_size,total_size;
+	unsigned long low_kmem_size, total_size;
 	struct zone *z;
 	int average_size;
 	/*
-         * ZONE_DMA and ZONE_DMA32 can be very small area in the system.
+	 * ZONE_DMA and ZONE_DMA32 can be very small area in the system.
 	 * If they are really small and used heavily, the system can fall
 	 * into OOM very easily.
 	 * This function detect ZONE_DMA/DMA32 size and configures zone order.
@@ -3452,9 +3520,9 @@ static int default_zonelist_order(void)
 		return ZONELIST_ORDER_NODE;
 	/*
 	 * look into each node's config.
-  	 * If there is a node whose DMA/DMA32 memory is very big area on
- 	 * local memory, NODE_ORDER may be suitable.
-         */
+	 * If there is a node whose DMA/DMA32 memory is very big area on
+	 * local memory, NODE_ORDER may be suitable.
+	 */
 	average_size = total_size /
 				(nodes_weight(node_states[N_MEMORY]) + 1);
 	for_each_online_node(nid) {
@@ -4180,7 +4248,7 @@ int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
 	if (!zone->wait_table)
 		return -ENOMEM;
 
-	for(i = 0; i < zone->wait_table_hash_nr_entries; ++i)
+	for (i = 0; i < zone->wait_table_hash_nr_entries; ++i)
 		init_waitqueue_head(zone->wait_table + i);
 
 	return 0;
@@ -4586,7 +4654,7 @@ static inline void setup_usemap(struct pglist_data *pgdat, struct zone *zone,
 #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
 
 /* Initialise the number of pages represented by NR_PAGEBLOCK_BITS */
-void __init set_pageblock_order(void)
+void __paginginit set_pageblock_order(void)
 {
 	unsigned int order;
 
@@ -4614,7 +4682,7 @@ void __init set_pageblock_order(void)
  * include/linux/pageblock-flags.h for the values of pageblock_order based on
  * the kernel config
  */
-void __init set_pageblock_order(void)
+void __paginginit set_pageblock_order(void)
 {
 }
 
@@ -4729,6 +4797,9 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
 		zone_seqlock_init(zone);
 		zone->zone_pgdat = pgdat;
 
+		/* For bootup, initialized properly in watermark setup */
+		zone->alloc_batch = zone->managed_pages;
+
 		zone_pcp_init(zone);
 		lruvec_init(&zone->lruvec);
 		if (!size)
@@ -4930,7 +5001,7 @@ static unsigned long __init early_calculate_totalpages(void)
 		if (pages)
 			node_set_state(nid, N_MEMORY);
 	}
-  	return totalpages;
+	return totalpages;
 }
 
 /*
@@ -5047,7 +5118,7 @@ restart:
 			/*
 			 * Some kernelcore has been met, update counts and
 			 * break if the kernelcore for this node has been
-			 * satisified
+			 * satisfied
 			 */
 			required_kernelcore -= min(required_kernelcore,
 								size_pages);
@@ -5061,7 +5132,7 @@ restart:
 	 * If there is still required_kernelcore, we do another pass with one
 	 * less node in the count. This will push zone_movable_pfn[nid] further
 	 * along on the nodes that still have memory until kernelcore is
-	 * satisified
+	 * satisfied
 	 */
 	usable_nodes--;
 	if (usable_nodes && required_kernelcore > usable_nodes)
@@ -5286,8 +5357,10 @@ void __init mem_init_print_info(const char *str)
 	 * 3) .rodata.* may be embedded into .text or .data sections.
 	 */
 #define adj_init_size(start, end, size, pos, adj) \
-	if (start <= pos && pos < end && size > adj) \
-		size -= adj;
+	do { \
+		if (start <= pos && pos < end && size > adj) \
+			size -= adj; \
+	} while (0)
 
 	adj_init_size(__init_begin, __init_end, init_data_size,
 		     _sinittext, init_code_size);
@@ -5361,7 +5434,7 @@ static int page_alloc_cpu_notify(struct notifier_block *self,
 		 * This is only okay since the processor is dead and cannot
 		 * race with what we are doing.
 		 */
-		refresh_cpu_vm_stats(cpu);
+		cpu_vm_stats_fold(cpu);
 	}
 	return NOTIFY_OK;
 }
@@ -5498,6 +5571,9 @@ static void __setup_per_zone_wmarks(void)
 		zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + (tmp >> 2);
 		zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1);
 
+		zone->alloc_batch = high_wmark_pages(zone) -
+			low_wmark_pages(zone);
+
 		setup_zone_migrate_reserve(zone);
 		spin_unlock_irqrestore(&zone->lock, flags);
 	}
@@ -5570,7 +5646,7 @@ static void __meminit setup_per_zone_inactive_ratio(void)
  * we want it large (64MB max).  But it is not linear, because network
  * bandwidth does not increase linearly with machine size.  We use
  *
- * 	min_free_kbytes = 4 * sqrt(lowmem_kbytes), for better accuracy:
+ *	min_free_kbytes = 4 * sqrt(lowmem_kbytes), for better accuracy:
  *	min_free_kbytes = sqrt(lowmem_kbytes * 16)
  *
  * which yields
@@ -5614,11 +5690,11 @@ int __meminit init_per_zone_wmark_min(void)
 module_init(init_per_zone_wmark_min)
 
 /*
- * min_free_kbytes_sysctl_handler - just a wrapper around proc_dointvec() so 
+ * min_free_kbytes_sysctl_handler - just a wrapper around proc_dointvec() so
  *	that we can call two helper functions whenever min_free_kbytes
  *	changes.
  */
-int min_free_kbytes_sysctl_handler(ctl_table *table, int write, 
+int min_free_kbytes_sysctl_handler(ctl_table *table, int write,
 	void __user *buffer, size_t *length, loff_t *ppos)
 {
 	proc_dointvec(table, write, buffer, length, ppos);
@@ -5682,8 +5758,8 @@ int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write,
 
 /*
  * percpu_pagelist_fraction - changes the pcp->high for each zone on each
- * cpu.  It is the fraction of total pages in each zone that a hot per cpu pagelist
- * can have before it gets flushed back to buddy allocator.
+ * cpu.  It is the fraction of total pages in each zone that a hot per cpu
+ * pagelist can have before it gets flushed back to buddy allocator.
  */
 int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write,
 	void __user *buffer, size_t *length, loff_t *ppos)
@@ -5745,9 +5821,10 @@ void *__init alloc_large_system_hash(const char *tablename,
 	if (!numentries) {
 		/* round applicable memory size up to nearest megabyte */
 		numentries = nr_kernel_pages;
-		numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
-		numentries >>= 20 - PAGE_SHIFT;
-		numentries <<= 20 - PAGE_SHIFT;
+
+		/* It isn't necessary when PAGE_SIZE >= 1MB */
+		if (PAGE_SHIFT < 20)
+			numentries = round_up(numentries, (1<<20)/PAGE_SIZE);
 
 		/* limit to 1 bucket per 2^scale bytes of low memory */
 		if (scale > PAGE_SHIFT)
@@ -5900,7 +5977,7 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
  * This function checks whether pageblock includes unmovable pages or not.
  * If @count is not zero, it is okay to include less @count unmovable pages
  *
- * PageLRU check wihtout isolation or lru_lock could race so that
+ * PageLRU check without isolation or lru_lock could race so that
  * MIGRATE_MOVABLE block might include unmovable pages. It means you can't
  * expect this function should be exact.
  */
diff --git a/mm/page_io.c b/mm/page_io.c
index ba05b64..8c79a47 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -266,7 +266,6 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
 
 		init_sync_kiocb(&kiocb, swap_file);
 		kiocb.ki_pos = page_file_offset(page);
-		kiocb.ki_left = PAGE_SIZE;
 		kiocb.ki_nbytes = PAGE_SIZE;
 
 		set_page_writeback(page);
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index e1a6e4f..3929a40 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -10,6 +10,30 @@
 #include <asm/tlb.h>
 #include <asm-generic/pgtable.h>
 
+/*
+ * If a p?d_bad entry is found while walking page tables, report
+ * the error, before resetting entry to p?d_none.  Usually (but
+ * very seldom) called out from the p?d_none_or_clear_bad macros.
+ */
+
+void pgd_clear_bad(pgd_t *pgd)
+{
+	pgd_ERROR(*pgd);
+	pgd_clear(pgd);
+}
+
+void pud_clear_bad(pud_t *pud)
+{
+	pud_ERROR(*pud);
+	pud_clear(pud);
+}
+
+void pmd_clear_bad(pmd_t *pmd)
+{
+	pmd_ERROR(*pmd);
+	pmd_clear(pmd);
+}
+
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 /*
  * Only sets the access flags (dirty, accessed), as well as write 
diff --git a/mm/rmap.c b/mm/rmap.c
index cd356df..07afd48 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1055,11 +1055,11 @@ void do_page_add_anon_rmap(struct page *page,
 {
 	int first = atomic_inc_and_test(&page->_mapcount);
 	if (first) {
-		if (!PageTransHuge(page))
-			__inc_zone_page_state(page, NR_ANON_PAGES);
-		else
+		if (PageTransHuge(page))
 			__inc_zone_page_state(page,
 					      NR_ANON_TRANSPARENT_HUGEPAGES);
+		__mod_zone_page_state(page_zone(page), NR_ANON_PAGES,
+				hpage_nr_pages(page));
 	}
 	if (unlikely(PageKsm(page)))
 		return;
@@ -1088,10 +1088,10 @@ void page_add_new_anon_rmap(struct page *page,
 	VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end);
 	SetPageSwapBacked(page);
 	atomic_set(&page->_mapcount, 0); /* increment count (starts at -1) */
-	if (!PageTransHuge(page))
-		__inc_zone_page_state(page, NR_ANON_PAGES);
-	else
+	if (PageTransHuge(page))
 		__inc_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
+	__mod_zone_page_state(page_zone(page), NR_ANON_PAGES,
+			hpage_nr_pages(page));
 	__page_set_anon_rmap(page, vma, address, 1);
 	if (!mlocked_vma_newpage(vma, page)) {
 		SetPageActive(page);
@@ -1151,11 +1151,11 @@ void page_remove_rmap(struct page *page)
 		goto out;
 	if (anon) {
 		mem_cgroup_uncharge_page(page);
-		if (!PageTransHuge(page))
-			__dec_zone_page_state(page, NR_ANON_PAGES);
-		else
+		if (PageTransHuge(page))
 			__dec_zone_page_state(page,
 					      NR_ANON_TRANSPARENT_HUGEPAGES);
+		__mod_zone_page_state(page_zone(page), NR_ANON_PAGES,
+				hpage_nr_pages(page));
 	} else {
 		__dec_zone_page_state(page, NR_FILE_MAPPED);
 		mem_cgroup_dec_page_stat(page, MEMCG_NR_FILE_MAPPED);
@@ -1236,6 +1236,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 			   swp_entry_to_pte(make_hwpoison_entry(page)));
 	} else if (PageAnon(page)) {
 		swp_entry_t entry = { .val = page_private(page) };
+		pte_t swp_pte;
 
 		if (PageSwapCache(page)) {
 			/*
@@ -1264,7 +1265,10 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 			BUG_ON(TTU_ACTION(flags) != TTU_MIGRATION);
 			entry = make_migration_entry(page, pte_write(pteval));
 		}
-		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
+		swp_pte = swp_entry_to_pte(entry);
+		if (pte_soft_dirty(pteval))
+			swp_pte = pte_swp_mksoft_dirty(swp_pte);
+		set_pte_at(mm, address, pte, swp_pte);
 		BUG_ON(pte_file(*pte));
 	} else if (IS_ENABLED(CONFIG_MIGRATION) &&
 		   (TTU_ACTION(flags) == TTU_MIGRATION)) {
@@ -1401,8 +1405,12 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 		pteval = ptep_clear_flush(vma, address, pte);
 
 		/* If nonlinear, store the file page offset in the pte. */
-		if (page->index != linear_page_index(vma, address))
-			set_pte_at(mm, address, pte, pgoff_to_pte(page->index));
+		if (page->index != linear_page_index(vma, address)) {
+			pte_t ptfile = pgoff_to_pte(page->index);
+			if (pte_soft_dirty(pteval))
+				pte_file_mksoft_dirty(ptfile);
+			set_pte_at(mm, address, pte, ptfile);
+		}
 
 		/* Move the dirty bit to the physical page now the pte is gone. */
 		if (pte_dirty(pteval))
diff --git a/mm/shmem.c b/mm/shmem.c
index 8335dbd..75010ba 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1205,7 +1205,7 @@ repeat:
 						gfp & GFP_RECLAIM_MASK);
 		if (error)
 			goto decused;
-		error = radix_tree_preload(gfp & GFP_RECLAIM_MASK);
+		error = radix_tree_maybe_preload(gfp & GFP_RECLAIM_MASK);
 		if (!error) {
 			error = shmem_add_to_page_cache(page, mapping, index,
 							gfp, NULL);
@@ -1464,7 +1464,7 @@ shmem_write_end(struct file *file, struct address_space *mapping,
 	return copied;
 }
 
-static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
+static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc)
 {
 	struct inode *inode = file_inode(filp);
 	struct address_space *mapping = inode->i_mapping;
@@ -1546,13 +1546,14 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
 		 * Ok, we have the page, and it's up-to-date, so
 		 * now we can copy it to user space...
 		 *
-		 * The actor routine returns how many bytes were actually used..
+		 * The file_read_actor routine returns how many bytes were actually
+		 * used..
 		 * NOTE! This may not be the same as how much of a user buffer
 		 * we filled up (we may be padding etc), so we can only update
-		 * "pos" here (the actor routine has to update the user buffer
+		 * "pos" here (file_read_actor has to update the user buffer
 		 * pointers and the remaining count).
 		 */
-		ret = actor(desc, page, offset, nr);
+		ret = file_read_actor(desc, page, offset, nr);
 		offset += ret;
 		index += offset >> PAGE_CACHE_SHIFT;
 		offset &= ~PAGE_CACHE_MASK;
@@ -1590,7 +1591,7 @@ static ssize_t shmem_file_aio_read(struct kiocb *iocb,
 		if (desc.count == 0)
 			continue;
 		desc.error = 0;
-		do_shmem_file_read(filp, ppos, &desc, file_read_actor);
+		do_shmem_file_read(filp, ppos, &desc);
 		retval += desc.written;
 		if (desc.error) {
 			retval = retval ?: desc.error;
@@ -2817,6 +2818,10 @@ int __init shmem_init(void)
 {
 	int error;
 
+	/* If rootfs called this, don't re-init */
+	if (shmem_inode_cachep)
+		return 0;
+
 	error = bdi_init(&shmem_backing_dev_info);
 	if (error)
 		goto out4;
diff --git a/mm/slub.c b/mm/slub.c
index 2b02d66..d77e384 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -373,7 +373,8 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page
 #endif
 	{
 		slab_lock(page);
-		if (page->freelist == freelist_old && page->counters == counters_old) {
+		if (page->freelist == freelist_old &&
+					page->counters == counters_old) {
 			page->freelist = freelist_new;
 			page->counters = counters_new;
 			slab_unlock(page);
@@ -411,7 +412,8 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
 
 		local_irq_save(flags);
 		slab_lock(page);
-		if (page->freelist == freelist_old && page->counters == counters_old) {
+		if (page->freelist == freelist_old &&
+					page->counters == counters_old) {
 			page->freelist = freelist_new;
 			page->counters = counters_new;
 			slab_unlock(page);
@@ -553,8 +555,9 @@ static void print_tracking(struct kmem_cache *s, void *object)
 
 static void print_page_info(struct page *page)
 {
-	printk(KERN_ERR "INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=0x%04lx\n",
-		page, page->objects, page->inuse, page->freelist, page->flags);
+	printk(KERN_ERR
+	       "INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=0x%04lx\n",
+	       page, page->objects, page->inuse, page->freelist, page->flags);
 
 }
 
@@ -629,7 +632,8 @@ static void object_err(struct kmem_cache *s, struct page *page,
 	print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...)
+static void slab_err(struct kmem_cache *s, struct page *page,
+			const char *fmt, ...)
 {
 	va_list args;
 	char buf[100];
@@ -788,7 +792,8 @@ static int check_object(struct kmem_cache *s, struct page *page,
 	} else {
 		if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) {
 			check_bytes_and_report(s, page, p, "Alignment padding",
-				endobject, POISON_INUSE, s->inuse - s->object_size);
+				endobject, POISON_INUSE,
+				s->inuse - s->object_size);
 		}
 	}
 
@@ -918,7 +923,8 @@ static void trace(struct kmem_cache *s, struct page *page, void *object,
 			page->freelist);
 
 		if (!alloc)
-			print_section("Object ", (void *)object, s->object_size);
+			print_section("Object ", (void *)object,
+					s->object_size);
 
 		dump_stack();
 	}
@@ -937,7 +943,8 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags)
 	return should_failslab(s->object_size, flags, s->flags);
 }
 
-static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object)
+static inline void slab_post_alloc_hook(struct kmem_cache *s,
+					gfp_t flags, void *object)
 {
 	flags &= gfp_allowed_mask;
 	kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
@@ -1039,7 +1046,8 @@ static void setup_object_debug(struct kmem_cache *s, struct page *page,
 	init_tracking(s, object);
 }
 
-static noinline int alloc_debug_processing(struct kmem_cache *s, struct page *page,
+static noinline int alloc_debug_processing(struct kmem_cache *s,
+					struct page *page,
 					void *object, unsigned long addr)
 {
 	if (!check_slab(s, page))
@@ -1743,7 +1751,8 @@ static void init_kmem_cache_cpus(struct kmem_cache *s)
 /*
  * Remove the cpu slab
  */
-static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist)
+static void deactivate_slab(struct kmem_cache *s, struct page *page,
+				void *freelist)
 {
 	enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE };
 	struct kmem_cache_node *n = get_node(s, page_to_nid(page));
@@ -1968,9 +1977,6 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 	int pages;
 	int pobjects;
 
-	if (!s->cpu_partial)
-		return;
-
 	do {
 		pages = 0;
 		pobjects = 0;
@@ -2002,7 +2008,8 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 		page->pobjects = pobjects;
 		page->next = oldpage;
 
-	} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
+	} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page)
+								!= oldpage);
 #endif
 }
 
@@ -2172,8 +2179,8 @@ static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags)
 }
 
 /*
- * Check the page->freelist of a page and either transfer the freelist to the per cpu freelist
- * or deactivate the page.
+ * Check the page->freelist of a page and either transfer the freelist to the
+ * per cpu freelist or deactivate the page.
  *
  * The page is still frozen if the return value is not NULL.
  *
@@ -2317,7 +2324,8 @@ new_slab:
 		goto load_freelist;
 
 	/* Only entered in the debug case */
-	if (kmem_cache_debug(s) && !alloc_debug_processing(s, page, freelist, addr))
+	if (kmem_cache_debug(s) &&
+			!alloc_debug_processing(s, page, freelist, addr))
 		goto new_slab;	/* Slab failed checks. Next slab needed */
 
 	deactivate_slab(s, page, get_freepointer(s, freelist));
@@ -2385,13 +2393,15 @@ redo:
 		 * The cmpxchg will only match if there was no additional
 		 * operation and if we are on the right processor.
 		 *
-		 * The cmpxchg does the following atomically (without lock semantics!)
+		 * The cmpxchg does the following atomically (without lock
+		 * semantics!)
 		 * 1. Relocate first pointer to the current per cpu area.
 		 * 2. Verify that tid and freelist have not been changed
 		 * 3. If they were not changed replace tid and freelist
 		 *
-		 * Since this is without lock semantics the protection is only against
-		 * code executing on this cpu *not* from access by other cpus.
+		 * Since this is without lock semantics the protection is only
+		 * against code executing on this cpu *not* from access by
+		 * other cpus.
 		 */
 		if (unlikely(!this_cpu_cmpxchg_double(
 				s->cpu_slab->freelist, s->cpu_slab->tid,
@@ -2423,7 +2433,8 @@ void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
 {
 	void *ret = slab_alloc(s, gfpflags, _RET_IP_);
 
-	trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags);
+	trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size,
+				s->size, gfpflags);
 
 	return ret;
 }
@@ -2515,8 +2526,10 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 			if (kmem_cache_has_cpu_partial(s) && !prior)
 
 				/*
-				 * Slab was on no list before and will be partially empty
-				 * We can defer the list move and instead freeze it.
+				 * Slab was on no list before and will be
+				 * partially empty
+				 * We can defer the list move and instead
+				 * freeze it.
 				 */
 				new.frozen = 1;
 
@@ -3074,8 +3087,8 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
 	 * A) The number of objects from per cpu partial slabs dumped to the
 	 *    per node list when we reach the limit.
 	 * B) The number of objects in cpu partial slabs to extract from the
-	 *    per node list when we run out of per cpu objects. We only fetch 50%
-	 *    to keep some capacity around for frees.
+	 *    per node list when we run out of per cpu objects. We only fetch
+	 *    50% to keep some capacity around for frees.
 	 */
 	if (!kmem_cache_has_cpu_partial(s))
 		s->cpu_partial = 0;
@@ -3102,8 +3115,8 @@ error:
 	if (flags & SLAB_PANIC)
 		panic("Cannot create slab %s size=%lu realsize=%u "
 			"order=%u offset=%u flags=%lx\n",
-			s->name, (unsigned long)s->size, s->size, oo_order(s->oo),
-			s->offset, flags);
+			s->name, (unsigned long)s->size, s->size,
+			oo_order(s->oo), s->offset, flags);
 	return -EINVAL;
 }
 
@@ -3341,7 +3354,8 @@ bool verify_mem_not_deleted(const void *x)
 
 	slab_lock(page);
 	if (on_freelist(page->slab_cache, page, object)) {
-		object_err(page->slab_cache, page, object, "Object is on free-list");
+		object_err(page->slab_cache, page, object,
+				"Object is on free-list");
 		rv = false;
 	} else {
 		rv = true;
@@ -4165,15 +4179,17 @@ static int list_locations(struct kmem_cache *s, char *buf,
 				!cpumask_empty(to_cpumask(l->cpus)) &&
 				len < PAGE_SIZE - 60) {
 			len += sprintf(buf + len, " cpus=");
-			len += cpulist_scnprintf(buf + len, PAGE_SIZE - len - 50,
+			len += cpulist_scnprintf(buf + len,
+						 PAGE_SIZE - len - 50,
 						 to_cpumask(l->cpus));
 		}
 
 		if (nr_online_nodes > 1 && !nodes_empty(l->nodes) &&
 				len < PAGE_SIZE - 60) {
 			len += sprintf(buf + len, " nodes=");
-			len += nodelist_scnprintf(buf + len, PAGE_SIZE - len - 50,
-					l->nodes);
+			len += nodelist_scnprintf(buf + len,
+						  PAGE_SIZE - len - 50,
+						  l->nodes);
 		}
 
 		len += sprintf(buf + len, "\n");
@@ -4271,18 +4287,17 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
 	int node;
 	int x;
 	unsigned long *nodes;
-	unsigned long *per_cpu;
 
-	nodes = kzalloc(2 * sizeof(unsigned long) * nr_node_ids, GFP_KERNEL);
+	nodes = kzalloc(sizeof(unsigned long) * nr_node_ids, GFP_KERNEL);
 	if (!nodes)
 		return -ENOMEM;
-	per_cpu = nodes + nr_node_ids;
 
 	if (flags & SO_CPU) {
 		int cpu;
 
 		for_each_possible_cpu(cpu) {
-			struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
+			struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab,
+							       cpu);
 			int node;
 			struct page *page;
 
@@ -4307,8 +4322,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
 				total += x;
 				nodes[node] += x;
 			}
-
-			per_cpu[node]++;
 		}
 	}
 
@@ -4318,12 +4331,11 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
 		for_each_node_state(node, N_NORMAL_MEMORY) {
 			struct kmem_cache_node *n = get_node(s, node);
 
-		if (flags & SO_TOTAL)
-			x = atomic_long_read(&n->total_objects);
-		else if (flags & SO_OBJECTS)
-			x = atomic_long_read(&n->total_objects) -
-				count_partial(n, count_free);
-
+			if (flags & SO_TOTAL)
+				x = atomic_long_read(&n->total_objects);
+			else if (flags & SO_OBJECTS)
+				x = atomic_long_read(&n->total_objects) -
+					count_partial(n, count_free);
 			else
 				x = atomic_long_read(&n->nr_slabs);
 			total += x;
@@ -4423,7 +4435,7 @@ static ssize_t order_store(struct kmem_cache *s,
 	unsigned long order;
 	int err;
 
-	err = strict_strtoul(buf, 10, &order);
+	err = kstrtoul(buf, 10, &order);
 	if (err)
 		return err;
 
@@ -4451,7 +4463,7 @@ static ssize_t min_partial_store(struct kmem_cache *s, const char *buf,
 	unsigned long min;
 	int err;
 
-	err = strict_strtoul(buf, 10, &min);
+	err = kstrtoul(buf, 10, &min);
 	if (err)
 		return err;
 
@@ -4471,7 +4483,7 @@ static ssize_t cpu_partial_store(struct kmem_cache *s, const char *buf,
 	unsigned long objects;
 	int err;
 
-	err = strict_strtoul(buf, 10, &objects);
+	err = kstrtoul(buf, 10, &objects);
 	if (err)
 		return err;
 	if (objects && !kmem_cache_has_cpu_partial(s))
@@ -4787,7 +4799,7 @@ static ssize_t remote_node_defrag_ratio_store(struct kmem_cache *s,
 	unsigned long ratio;
 	int err;
 
-	err = strict_strtoul(buf, 10, &ratio);
+	err = kstrtoul(buf, 10, &ratio);
 	if (err)
 		return err;
 
@@ -5139,7 +5151,8 @@ static char *create_unique_id(struct kmem_cache *s)
 
 #ifdef CONFIG_MEMCG_KMEM
 	if (!is_root_cache(s))
-		p += sprintf(p, "-%08d", memcg_cache_id(s->memcg_params->memcg));
+		p += sprintf(p, "-%08d",
+				memcg_cache_id(s->memcg_params->memcg));
 #endif
 
 	BUG_ON(p > name + ID_STR_LENGTH - 1);
diff --git a/mm/swap.c b/mm/swap.c
index 62b78a6..0cb08d4 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -405,6 +405,11 @@ static void activate_page_drain(int cpu)
 		pagevec_lru_move_fn(pvec, __activate_page, NULL);
 }
 
+static bool need_activate_page_drain(int cpu)
+{
+	return pagevec_count(&per_cpu(activate_page_pvecs, cpu)) != 0;
+}
+
 void activate_page(struct page *page)
 {
 	if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
@@ -422,6 +427,11 @@ static inline void activate_page_drain(int cpu)
 {
 }
 
+static bool need_activate_page_drain(int cpu)
+{
+	return false;
+}
+
 void activate_page(struct page *page)
 {
 	struct zone *zone = page_zone(page);
@@ -679,7 +689,32 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
  */
 int lru_add_drain_all(void)
 {
-	return schedule_on_each_cpu(lru_add_drain_per_cpu);
+	cpumask_var_t mask;
+	int cpu, rc;
+
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+	cpumask_clear(mask);
+
+	/*
+	 * Figure out which cpus need flushing.  It's OK if we race
+	 * with changes to the per-cpu lru pvecs, since it's no worse
+	 * than if we flushed all cpus, since a cpu could still end
+	 * up putting pages back on its pvec before we returned.
+	 * And this avoids interrupting other cpus unnecessarily.
+	 */
+	for_each_online_cpu(cpu) {
+		if (pagevec_count(&per_cpu(lru_add_pvec, cpu)) ||
+		    pagevec_count(&per_cpu(lru_rotate_pvecs, cpu)) ||
+		    pagevec_count(&per_cpu(lru_deactivate_pvecs, cpu)) ||
+		    need_activate_page_drain(cpu))
+			cpumask_set_cpu(cpu, mask);
+	}
+
+	rc = schedule_on_cpu_mask(lru_add_drain_per_cpu, mask);
+
+	free_cpumask_var(mask);
+	return rc;
 }
 
 /*
diff --git a/mm/swap_state.c b/mm/swap_state.c
index f24ab0d..fdde6f9 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -63,6 +63,8 @@ unsigned long total_swapcache_pages(void)
 	return ret;
 }
 
+static atomic_t swapin_readahead_hits = ATOMIC_INIT(4);
+
 void show_swap_cache_info(void)
 {
 	printk("%lu pages in swap cache\n", total_swapcache_pages());
@@ -122,7 +124,7 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask)
 {
 	int error;
 
-	error = radix_tree_preload(gfp_mask);
+	error = radix_tree_maybe_preload(gfp_mask);
 	if (!error) {
 		error = __add_to_swap_cache(page, entry);
 		radix_tree_preload_end();
@@ -286,8 +288,11 @@ struct page * lookup_swap_cache(swp_entry_t entry)
 
 	page = find_get_page(swap_address_space(entry), entry.val);
 
-	if (page)
+	if (page) {
 		INC_CACHE_INFO(find_success);
+		if (TestClearPageReadahead(page))
+			atomic_inc(&swapin_readahead_hits);
+	}
 
 	INC_CACHE_INFO(find_total);
 	return page;
@@ -328,7 +333,7 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
 		/*
 		 * call radix_tree_preload() while we can wait.
 		 */
-		err = radix_tree_preload(gfp_mask & GFP_KERNEL);
+		err = radix_tree_maybe_preload(gfp_mask & GFP_KERNEL);
 		if (err)
 			break;
 
@@ -389,6 +394,50 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
 	return found_page;
 }
 
+static unsigned long swapin_nr_pages(unsigned long offset)
+{
+	static unsigned long prev_offset;
+	unsigned int pages, max_pages, last_ra;
+	static atomic_t last_readahead_pages;
+
+	max_pages = 1 << ACCESS_ONCE(page_cluster);
+	if (max_pages <= 1)
+		return 1;
+
+	/*
+	 * This heuristic has been found to work well on both sequential and
+	 * random loads, swapping to hard disk or to SSD: please don't ask
+	 * what the "+ 2" means, it just happens to work well, that's all.
+	 */
+	pages = atomic_xchg(&swapin_readahead_hits, 0) + 2;
+	if (pages == 2) {
+		/*
+		 * We can have no readahead hits to judge by: but must not get
+		 * stuck here forever, so check for an adjacent offset instead
+		 * (and don't even bother to check whether swap type is same).
+		 */
+		if (offset != prev_offset + 1 && offset != prev_offset - 1)
+			pages = 1;
+		prev_offset = offset;
+	} else {
+		unsigned int roundup = 4;
+		while (roundup < pages)
+			roundup <<= 1;
+		pages = roundup;
+	}
+
+	if (pages > max_pages)
+		pages = max_pages;
+
+	/* Don't shrink readahead too fast */
+	last_ra = atomic_read(&last_readahead_pages) / 2;
+	if (pages < last_ra)
+		pages = last_ra;
+	atomic_set(&last_readahead_pages, pages);
+
+	return pages;
+}
+
 /**
  * swapin_readahead - swap in pages in hope we need them soon
  * @entry: swap entry of this memory
@@ -412,11 +461,16 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
 			struct vm_area_struct *vma, unsigned long addr)
 {
 	struct page *page;
-	unsigned long offset = swp_offset(entry);
+	unsigned long entry_offset = swp_offset(entry);
+	unsigned long offset = entry_offset;
 	unsigned long start_offset, end_offset;
-	unsigned long mask = (1UL << page_cluster) - 1;
+	unsigned long mask;
 	struct blk_plug plug;
 
+	mask = swapin_nr_pages(offset) - 1;
+	if (!mask)
+		goto skip;
+
 	/* Read a page_cluster sized and aligned cluster around offset. */
 	start_offset = offset & ~mask;
 	end_offset = offset | mask;
@@ -430,10 +484,13 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
 						gfp_mask, vma, addr);
 		if (!page)
 			continue;
+		if (offset != entry_offset)
+			SetPageReadahead(page);
 		page_cache_release(page);
 	}
 	blk_finish_plug(&plug);
 
 	lru_add_drain();	/* Push any new pages onto the LRU now */
+skip:
 	return read_swap_cache_async(entry, gfp_mask, vma, addr);
 }
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 36af6ee..3963fc2 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -175,14 +175,296 @@ static void discard_swap_cluster(struct swap_info_struct *si,
 	}
 }
 
-static int wait_for_discard(void *word)
+#define SWAPFILE_CLUSTER	256
+#define LATENCY_LIMIT		256
+
+static inline void cluster_set_flag(struct swap_cluster_info *info,
+	unsigned int flag)
 {
-	schedule();
-	return 0;
+	info->flags = flag;
 }
 
-#define SWAPFILE_CLUSTER	256
-#define LATENCY_LIMIT		256
+static inline unsigned int cluster_count(struct swap_cluster_info *info)
+{
+	return info->data;
+}
+
+static inline void cluster_set_count(struct swap_cluster_info *info,
+				     unsigned int c)
+{
+	info->data = c;
+}
+
+static inline void cluster_set_count_flag(struct swap_cluster_info *info,
+					 unsigned int c, unsigned int f)
+{
+	info->flags = f;
+	info->data = c;
+}
+
+static inline unsigned int cluster_next(struct swap_cluster_info *info)
+{
+	return info->data;
+}
+
+static inline void cluster_set_next(struct swap_cluster_info *info,
+				    unsigned int n)
+{
+	info->data = n;
+}
+
+static inline void cluster_set_next_flag(struct swap_cluster_info *info,
+					 unsigned int n, unsigned int f)
+{
+	info->flags = f;
+	info->data = n;
+}
+
+static inline bool cluster_is_free(struct swap_cluster_info *info)
+{
+	return info->flags & CLUSTER_FLAG_FREE;
+}
+
+static inline bool cluster_is_null(struct swap_cluster_info *info)
+{
+	return info->flags & CLUSTER_FLAG_NEXT_NULL;
+}
+
+static inline void cluster_set_null(struct swap_cluster_info *info)
+{
+	info->flags = CLUSTER_FLAG_NEXT_NULL;
+	info->data = 0;
+}
+
+/* Add a cluster to discard list and schedule it to do discard */
+static void swap_cluster_schedule_discard(struct swap_info_struct *si,
+		unsigned int idx)
+{
+	/*
+	 * If scan_swap_map() can't find a free cluster, it will check
+	 * si->swap_map directly. To make sure the discarding cluster isn't
+	 * taken by scan_swap_map(), mark the swap entries bad (occupied). It
+	 * will be cleared after discard
+	 */
+	memset(si->swap_map + idx * SWAPFILE_CLUSTER,
+			SWAP_MAP_BAD, SWAPFILE_CLUSTER);
+
+	if (cluster_is_null(&si->discard_cluster_head)) {
+		cluster_set_next_flag(&si->discard_cluster_head,
+						idx, 0);
+		cluster_set_next_flag(&si->discard_cluster_tail,
+						idx, 0);
+	} else {
+		unsigned int tail = cluster_next(&si->discard_cluster_tail);
+		cluster_set_next(&si->cluster_info[tail], idx);
+		cluster_set_next_flag(&si->discard_cluster_tail,
+						idx, 0);
+	}
+
+	schedule_work(&si->discard_work);
+}
+
+/*
+ * Doing discard actually. After a cluster discard is finished, the cluster
+ * will be added to free cluster list. caller should hold si->lock.
+*/
+static void swap_do_scheduled_discard(struct swap_info_struct *si)
+{
+	struct swap_cluster_info *info;
+	unsigned int idx;
+
+	info = si->cluster_info;
+
+	while (!cluster_is_null(&si->discard_cluster_head)) {
+		idx = cluster_next(&si->discard_cluster_head);
+
+		cluster_set_next_flag(&si->discard_cluster_head,
+						cluster_next(&info[idx]), 0);
+		if (cluster_next(&si->discard_cluster_tail) == idx) {
+			cluster_set_null(&si->discard_cluster_head);
+			cluster_set_null(&si->discard_cluster_tail);
+		}
+		spin_unlock(&si->lock);
+
+		discard_swap_cluster(si, idx * SWAPFILE_CLUSTER,
+				SWAPFILE_CLUSTER);
+
+		spin_lock(&si->lock);
+		cluster_set_flag(&info[idx], CLUSTER_FLAG_FREE);
+		if (cluster_is_null(&si->free_cluster_head)) {
+			cluster_set_next_flag(&si->free_cluster_head,
+						idx, 0);
+			cluster_set_next_flag(&si->free_cluster_tail,
+						idx, 0);
+		} else {
+			unsigned int tail;
+
+			tail = cluster_next(&si->free_cluster_tail);
+			cluster_set_next(&info[tail], idx);
+			cluster_set_next_flag(&si->free_cluster_tail,
+						idx, 0);
+		}
+		memset(si->swap_map + idx * SWAPFILE_CLUSTER,
+				0, SWAPFILE_CLUSTER);
+	}
+}
+
+static void swap_discard_work(struct work_struct *work)
+{
+	struct swap_info_struct *si;
+
+	si = container_of(work, struct swap_info_struct, discard_work);
+
+	spin_lock(&si->lock);
+	swap_do_scheduled_discard(si);
+	spin_unlock(&si->lock);
+}
+
+/*
+ * The cluster corresponding to page_nr will be used. The cluster will be
+ * removed from free cluster list and its usage counter will be increased.
+ */
+static void inc_cluster_info_page(struct swap_info_struct *p,
+	struct swap_cluster_info *cluster_info, unsigned long page_nr)
+{
+	unsigned long idx = page_nr / SWAPFILE_CLUSTER;
+
+	if (!cluster_info)
+		return;
+	if (cluster_is_free(&cluster_info[idx])) {
+		VM_BUG_ON(cluster_next(&p->free_cluster_head) != idx);
+		cluster_set_next_flag(&p->free_cluster_head,
+			cluster_next(&cluster_info[idx]), 0);
+		if (cluster_next(&p->free_cluster_tail) == idx) {
+			cluster_set_null(&p->free_cluster_tail);
+			cluster_set_null(&p->free_cluster_head);
+		}
+		cluster_set_count_flag(&cluster_info[idx], 0, 0);
+	}
+
+	VM_BUG_ON(cluster_count(&cluster_info[idx]) >= SWAPFILE_CLUSTER);
+	cluster_set_count(&cluster_info[idx],
+		cluster_count(&cluster_info[idx]) + 1);
+}
+
+/*
+ * The cluster corresponding to page_nr decreases one usage. If the usage
+ * counter becomes 0, which means no page in the cluster is in using, we can
+ * optionally discard the cluster and add it to free cluster list.
+ */
+static void dec_cluster_info_page(struct swap_info_struct *p,
+	struct swap_cluster_info *cluster_info, unsigned long page_nr)
+{
+	unsigned long idx = page_nr / SWAPFILE_CLUSTER;
+
+	if (!cluster_info)
+		return;
+
+	VM_BUG_ON(cluster_count(&cluster_info[idx]) == 0);
+	cluster_set_count(&cluster_info[idx],
+		cluster_count(&cluster_info[idx]) - 1);
+
+	if (cluster_count(&cluster_info[idx]) == 0) {
+		/*
+		 * If the swap is discardable, prepare discard the cluster
+		 * instead of free it immediately. The cluster will be freed
+		 * after discard.
+		 */
+		if ((p->flags & (SWP_WRITEOK | SWP_PAGE_DISCARD)) ==
+				 (SWP_WRITEOK | SWP_PAGE_DISCARD)) {
+			swap_cluster_schedule_discard(p, idx);
+			return;
+		}
+
+		cluster_set_flag(&cluster_info[idx], CLUSTER_FLAG_FREE);
+		if (cluster_is_null(&p->free_cluster_head)) {
+			cluster_set_next_flag(&p->free_cluster_head, idx, 0);
+			cluster_set_next_flag(&p->free_cluster_tail, idx, 0);
+		} else {
+			unsigned int tail = cluster_next(&p->free_cluster_tail);
+			cluster_set_next(&cluster_info[tail], idx);
+			cluster_set_next_flag(&p->free_cluster_tail, idx, 0);
+		}
+	}
+}
+
+/*
+ * It's possible scan_swap_map() uses a free cluster in the middle of free
+ * cluster list. Avoiding such abuse to avoid list corruption.
+ */
+static bool
+scan_swap_map_ssd_cluster_conflict(struct swap_info_struct *si,
+	unsigned long offset)
+{
+	struct percpu_cluster *percpu_cluster;
+	bool conflict;
+
+	offset /= SWAPFILE_CLUSTER;
+	conflict = !cluster_is_null(&si->free_cluster_head) &&
+		offset != cluster_next(&si->free_cluster_head) &&
+		cluster_is_free(&si->cluster_info[offset]);
+
+	if (!conflict)
+		return false;
+
+	percpu_cluster = this_cpu_ptr(si->percpu_cluster);
+	cluster_set_null(&percpu_cluster->index);
+	return true;
+}
+
+/*
+ * Try to get a swap entry from current cpu's swap entry pool (a cluster). This
+ * might involve allocating a new cluster for current CPU too.
+ */
+static void scan_swap_map_try_ssd_cluster(struct swap_info_struct *si,
+	unsigned long *offset, unsigned long *scan_base)
+{
+	struct percpu_cluster *cluster;
+	bool found_free;
+	unsigned long tmp;
+
+new_cluster:
+	cluster = this_cpu_ptr(si->percpu_cluster);
+	if (cluster_is_null(&cluster->index)) {
+		if (!cluster_is_null(&si->free_cluster_head)) {
+			cluster->index = si->free_cluster_head;
+			cluster->next = cluster_next(&cluster->index) *
+					SWAPFILE_CLUSTER;
+		} else if (!cluster_is_null(&si->discard_cluster_head)) {
+			/*
+			 * we don't have free cluster but have some clusters in
+			 * discarding, do discard now and reclaim them
+			 */
+			swap_do_scheduled_discard(si);
+			*scan_base = *offset = si->cluster_next;
+			goto new_cluster;
+		} else
+			return;
+	}
+
+	found_free = false;
+
+	/*
+	 * Other CPUs can use our cluster if they can't find a free cluster,
+	 * check if there is still free entry in the cluster
+	 */
+	tmp = cluster->next;
+	while (tmp < si->max && tmp < (cluster_next(&cluster->index) + 1) *
+	       SWAPFILE_CLUSTER) {
+		if (!si->swap_map[tmp]) {
+			found_free = true;
+			break;
+		}
+		tmp++;
+	}
+	if (!found_free) {
+		cluster_set_null(&cluster->index);
+		goto new_cluster;
+	}
+	cluster->next = tmp + 1;
+	*offset = tmp;
+	*scan_base = tmp;
+}
 
 static unsigned long scan_swap_map(struct swap_info_struct *si,
 				   unsigned char usage)
@@ -191,7 +473,6 @@ static unsigned long scan_swap_map(struct swap_info_struct *si,
 	unsigned long scan_base;
 	unsigned long last_in_cluster = 0;
 	int latency_ration = LATENCY_LIMIT;
-	int found_free_cluster = 0;
 
 	/*
 	 * We try to cluster swap pages by allocating them sequentially
@@ -207,24 +488,18 @@ static unsigned long scan_swap_map(struct swap_info_struct *si,
 	si->flags += SWP_SCANNING;
 	scan_base = offset = si->cluster_next;
 
+	/* SSD algorithm */
+	if (si->cluster_info) {
+		scan_swap_map_try_ssd_cluster(si, &offset, &scan_base);
+		goto checks;
+	}
+
 	if (unlikely(!si->cluster_nr--)) {
 		if (si->pages - si->inuse_pages < SWAPFILE_CLUSTER) {
 			si->cluster_nr = SWAPFILE_CLUSTER - 1;
 			goto checks;
 		}
-		if (si->flags & SWP_PAGE_DISCARD) {
-			/*
-			 * Start range check on racing allocations, in case
-			 * they overlap the cluster we eventually decide on
-			 * (we scan without swap_lock to allow preemption).
-			 * It's hardly conceivable that cluster_nr could be
-			 * wrapped during our scan, but don't depend on it.
-			 */
-			if (si->lowest_alloc)
-				goto checks;
-			si->lowest_alloc = si->max;
-			si->highest_alloc = 0;
-		}
+
 		spin_unlock(&si->lock);
 
 		/*
@@ -248,7 +523,6 @@ static unsigned long scan_swap_map(struct swap_info_struct *si,
 				offset -= SWAPFILE_CLUSTER - 1;
 				si->cluster_next = offset;
 				si->cluster_nr = SWAPFILE_CLUSTER - 1;
-				found_free_cluster = 1;
 				goto checks;
 			}
 			if (unlikely(--latency_ration < 0)) {
@@ -269,7 +543,6 @@ static unsigned long scan_swap_map(struct swap_info_struct *si,
 				offset -= SWAPFILE_CLUSTER - 1;
 				si->cluster_next = offset;
 				si->cluster_nr = SWAPFILE_CLUSTER - 1;
-				found_free_cluster = 1;
 				goto checks;
 			}
 			if (unlikely(--latency_ration < 0)) {
@@ -281,10 +554,13 @@ static unsigned long scan_swap_map(struct swap_info_struct *si,
 		offset = scan_base;
 		spin_lock(&si->lock);
 		si->cluster_nr = SWAPFILE_CLUSTER - 1;
-		si->lowest_alloc = 0;
 	}
 
 checks:
+	if (si->cluster_info) {
+		while (scan_swap_map_ssd_cluster_conflict(si, offset))
+			scan_swap_map_try_ssd_cluster(si, &offset, &scan_base);
+	}
 	if (!(si->flags & SWP_WRITEOK))
 		goto no_page;
 	if (!si->highest_bit)
@@ -317,62 +593,10 @@ checks:
 		si->highest_bit = 0;
 	}
 	si->swap_map[offset] = usage;
+	inc_cluster_info_page(si, si->cluster_info, offset);
 	si->cluster_next = offset + 1;
 	si->flags -= SWP_SCANNING;
 
-	if (si->lowest_alloc) {
-		/*
-		 * Only set when SWP_PAGE_DISCARD, and there's a scan
-		 * for a free cluster in progress or just completed.
-		 */
-		if (found_free_cluster) {
-			/*
-			 * To optimize wear-levelling, discard the
-			 * old data of the cluster, taking care not to
-			 * discard any of its pages that have already
-			 * been allocated by racing tasks (offset has
-			 * already stepped over any at the beginning).
-			 */
-			if (offset < si->highest_alloc &&
-			    si->lowest_alloc <= last_in_cluster)
-				last_in_cluster = si->lowest_alloc - 1;
-			si->flags |= SWP_DISCARDING;
-			spin_unlock(&si->lock);
-
-			if (offset < last_in_cluster)
-				discard_swap_cluster(si, offset,
-					last_in_cluster - offset + 1);
-
-			spin_lock(&si->lock);
-			si->lowest_alloc = 0;
-			si->flags &= ~SWP_DISCARDING;
-
-			smp_mb();	/* wake_up_bit advises this */
-			wake_up_bit(&si->flags, ilog2(SWP_DISCARDING));
-
-		} else if (si->flags & SWP_DISCARDING) {
-			/*
-			 * Delay using pages allocated by racing tasks
-			 * until the whole discard has been issued. We
-			 * could defer that delay until swap_writepage,
-			 * but it's easier to keep this self-contained.
-			 */
-			spin_unlock(&si->lock);
-			wait_on_bit(&si->flags, ilog2(SWP_DISCARDING),
-				wait_for_discard, TASK_UNINTERRUPTIBLE);
-			spin_lock(&si->lock);
-		} else {
-			/*
-			 * Note pages allocated by racing tasks while
-			 * scan for a free cluster is in progress, so
-			 * that its final discard can exclude them.
-			 */
-			if (offset < si->lowest_alloc)
-				si->lowest_alloc = offset;
-			if (offset > si->highest_alloc)
-				si->highest_alloc = offset;
-		}
-	}
 	return offset;
 
 scan:
@@ -527,16 +751,16 @@ static struct swap_info_struct *swap_info_get(swp_entry_t entry)
 	return p;
 
 bad_free:
-	printk(KERN_ERR "swap_free: %s%08lx\n", Unused_offset, entry.val);
+	pr_err("swap_free: %s%08lx\n", Unused_offset, entry.val);
 	goto out;
 bad_offset:
-	printk(KERN_ERR "swap_free: %s%08lx\n", Bad_offset, entry.val);
+	pr_err("swap_free: %s%08lx\n", Bad_offset, entry.val);
 	goto out;
 bad_device:
-	printk(KERN_ERR "swap_free: %s%08lx\n", Unused_file, entry.val);
+	pr_err("swap_free: %s%08lx\n", Unused_file, entry.val);
 	goto out;
 bad_nofile:
-	printk(KERN_ERR "swap_free: %s%08lx\n", Bad_file, entry.val);
+	pr_err("swap_free: %s%08lx\n", Bad_file, entry.val);
 out:
 	return NULL;
 }
@@ -600,6 +824,7 @@ static unsigned char swap_entry_free(struct swap_info_struct *p,
 
 	/* free if no reference */
 	if (!usage) {
+		dec_cluster_info_page(p, p->cluster_info, offset);
 		if (offset < p->lowest_bit)
 			p->lowest_bit = offset;
 		if (offset > p->highest_bit)
@@ -866,6 +1091,21 @@ unsigned int count_swap_pages(int type, int free)
 }
 #endif /* CONFIG_HIBERNATION */
 
+static inline int maybe_same_pte(pte_t pte, pte_t swp_pte)
+{
+#ifdef CONFIG_MEM_SOFT_DIRTY
+	/*
+	 * When pte keeps soft dirty bit the pte generated
+	 * from swap entry does not has it, still it's same
+	 * pte from logical point of view.
+	 */
+	pte_t swp_pte_dirty = pte_swp_mksoft_dirty(swp_pte);
+	return pte_same(pte, swp_pte) || pte_same(pte, swp_pte_dirty);
+#else
+	return pte_same(pte, swp_pte);
+#endif
+}
+
 /*
  * No need to decide whether this PTE shares the swap entry with others,
  * just let do_wp_page work it out if a write is requested later - to
@@ -892,7 +1132,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
 	}
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
+	if (unlikely(!maybe_same_pte(*pte, swp_entry_to_pte(entry)))) {
 		mem_cgroup_cancel_charge_swapin(memcg);
 		ret = 0;
 		goto out;
@@ -947,7 +1187,7 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 		 * swapoff spends a _lot_ of time in this loop!
 		 * Test inline before going to call unuse_pte.
 		 */
-		if (unlikely(pte_same(*pte, swp_pte))) {
+		if (unlikely(maybe_same_pte(*pte, swp_pte))) {
 			pte_unmap(pte);
 			ret = unuse_pte(vma, pmd, addr, entry, page);
 			if (ret)
@@ -1092,7 +1332,7 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si,
 			else
 				continue;
 		}
-		count = si->swap_map[i];
+		count = ACCESS_ONCE(si->swap_map[i]);
 		if (count && swap_count(count) != SWAP_MAP_BAD)
 			break;
 	}
@@ -1112,7 +1352,11 @@ int try_to_unuse(unsigned int type, bool frontswap,
 {
 	struct swap_info_struct *si = swap_info[type];
 	struct mm_struct *start_mm;
-	unsigned char *swap_map;
+	volatile unsigned char *swap_map; /* swap_map is accessed without
+					   * locking. Mark it as volatile
+					   * to prevent compiler doing
+					   * something odd.
+					   */
 	unsigned char swcount;
 	struct page *page;
 	swp_entry_t entry;
@@ -1163,7 +1407,15 @@ int try_to_unuse(unsigned int type, bool frontswap,
 			 * reused since sys_swapoff() already disabled
 			 * allocation from here, or alloc_page() failed.
 			 */
-			if (!*swap_map)
+			swcount = *swap_map;
+			/*
+			 * We don't hold lock here, so the swap entry could be
+			 * SWAP_MAP_BAD (when the cluster is discarding).
+			 * Instead of fail out, We can just skip the swap
+			 * entry because swapoff will wait for discarding
+			 * finish anyway.
+			 */
+			if (!swcount || swcount == SWAP_MAP_BAD)
 				continue;
 			retval = -ENOMEM;
 			break;
@@ -1509,7 +1761,8 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
 }
 
 static void _enable_swap_info(struct swap_info_struct *p, int prio,
-				unsigned char *swap_map)
+				unsigned char *swap_map,
+				struct swap_cluster_info *cluster_info)
 {
 	int i, prev;
 
@@ -1518,6 +1771,7 @@ static void _enable_swap_info(struct swap_info_struct *p, int prio,
 	else
 		p->prio = --least_priority;
 	p->swap_map = swap_map;
+	p->cluster_info = cluster_info;
 	p->flags |= SWP_WRITEOK;
 	atomic_long_add(p->pages, &nr_swap_pages);
 	total_swap_pages += p->pages;
@@ -1538,12 +1792,13 @@ static void _enable_swap_info(struct swap_info_struct *p, int prio,
 
 static void enable_swap_info(struct swap_info_struct *p, int prio,
 				unsigned char *swap_map,
+				struct swap_cluster_info *cluster_info,
 				unsigned long *frontswap_map)
 {
 	frontswap_init(p->type, frontswap_map);
 	spin_lock(&swap_lock);
 	spin_lock(&p->lock);
-	 _enable_swap_info(p, prio, swap_map);
+	 _enable_swap_info(p, prio, swap_map, cluster_info);
 	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
 }
@@ -1552,7 +1807,7 @@ static void reinsert_swap_info(struct swap_info_struct *p)
 {
 	spin_lock(&swap_lock);
 	spin_lock(&p->lock);
-	_enable_swap_info(p, p->prio, p->swap_map);
+	_enable_swap_info(p, p->prio, p->swap_map, p->cluster_info);
 	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
 }
@@ -1561,6 +1816,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 {
 	struct swap_info_struct *p = NULL;
 	unsigned char *swap_map;
+	struct swap_cluster_info *cluster_info;
 	unsigned long *frontswap_map;
 	struct file *swap_file, *victim;
 	struct address_space *mapping;
@@ -1636,6 +1892,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 		goto out_dput;
 	}
 
+	flush_work(&p->discard_work);
+
 	destroy_swap_extents(p);
 	if (p->flags & SWP_CONTINUED)
 		free_swap_count_continuations(p);
@@ -1660,6 +1918,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	p->max = 0;
 	swap_map = p->swap_map;
 	p->swap_map = NULL;
+	cluster_info = p->cluster_info;
+	p->cluster_info = NULL;
 	p->flags = 0;
 	frontswap_map = frontswap_map_get(p);
 	frontswap_map_set(p, NULL);
@@ -1667,7 +1927,10 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	spin_unlock(&swap_lock);
 	frontswap_invalidate_area(type);
 	mutex_unlock(&swapon_mutex);
+	free_percpu(p->percpu_cluster);
+	p->percpu_cluster = NULL;
 	vfree(swap_map);
+	vfree(cluster_info);
 	vfree(frontswap_map);
 	/* Destroy swap account informatin */
 	swap_cgroup_swapoff(type);
@@ -1911,9 +2174,10 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
 	int i;
 	unsigned long maxpages;
 	unsigned long swapfilepages;
+	unsigned long last_page;
 
 	if (memcmp("SWAPSPACE2", swap_header->magic.magic, 10)) {
-		printk(KERN_ERR "Unable to find swap-space signature\n");
+		pr_err("Unable to find swap-space signature\n");
 		return 0;
 	}
 
@@ -1927,9 +2191,8 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
 	}
 	/* Check the swap header's sub-version */
 	if (swap_header->info.version != 1) {
-		printk(KERN_WARNING
-		       "Unable to handle swap header version %d\n",
-		       swap_header->info.version);
+		pr_warn("Unable to handle swap header version %d\n",
+			swap_header->info.version);
 		return 0;
 	}
 
@@ -1953,8 +2216,14 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
 	 */
 	maxpages = swp_offset(pte_to_swp_entry(
 			swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1;
-	if (maxpages > swap_header->info.last_page) {
-		maxpages = swap_header->info.last_page + 1;
+	last_page = swap_header->info.last_page;
+	if (last_page > maxpages) {
+		pr_warn("Truncating oversized swap area, only using %luk out of %luk\n",
+			maxpages << (PAGE_SHIFT - 10),
+			last_page << (PAGE_SHIFT - 10));
+	}
+	if (maxpages > last_page) {
+		maxpages = last_page + 1;
 		/* p->max is an unsigned int: don't overflow it */
 		if ((unsigned int)maxpages == 0)
 			maxpages = UINT_MAX;
@@ -1965,8 +2234,7 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
 		return 0;
 	swapfilepages = i_size_read(inode) >> PAGE_SHIFT;
 	if (swapfilepages && maxpages > swapfilepages) {
-		printk(KERN_WARNING
-		       "Swap area shorter than signature indicates\n");
+		pr_warn("Swap area shorter than signature indicates\n");
 		return 0;
 	}
 	if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode))
@@ -1980,15 +2248,23 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
 static int setup_swap_map_and_extents(struct swap_info_struct *p,
 					union swap_header *swap_header,
 					unsigned char *swap_map,
+					struct swap_cluster_info *cluster_info,
 					unsigned long maxpages,
 					sector_t *span)
 {
 	int i;
 	unsigned int nr_good_pages;
 	int nr_extents;
+	unsigned long nr_clusters = DIV_ROUND_UP(maxpages, SWAPFILE_CLUSTER);
+	unsigned long idx = p->cluster_next / SWAPFILE_CLUSTER;
 
 	nr_good_pages = maxpages - 1;	/* omit header page */
 
+	cluster_set_null(&p->free_cluster_head);
+	cluster_set_null(&p->free_cluster_tail);
+	cluster_set_null(&p->discard_cluster_head);
+	cluster_set_null(&p->discard_cluster_tail);
+
 	for (i = 0; i < swap_header->info.nr_badpages; i++) {
 		unsigned int page_nr = swap_header->info.badpages[i];
 		if (page_nr == 0 || page_nr > swap_header->info.last_page)
@@ -1996,11 +2272,25 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p,
 		if (page_nr < maxpages) {
 			swap_map[page_nr] = SWAP_MAP_BAD;
 			nr_good_pages--;
+			/*
+			 * Haven't marked the cluster free yet, no list
+			 * operation involved
+			 */
+			inc_cluster_info_page(p, cluster_info, page_nr);
 		}
 	}
 
+	/* Haven't marked the cluster free yet, no list operation involved */
+	for (i = maxpages; i < round_up(maxpages, SWAPFILE_CLUSTER); i++)
+		inc_cluster_info_page(p, cluster_info, i);
+
 	if (nr_good_pages) {
 		swap_map[0] = SWAP_MAP_BAD;
+		/*
+		 * Not mark the cluster free yet, no list
+		 * operation involved
+		 */
+		inc_cluster_info_page(p, cluster_info, 0);
 		p->max = maxpages;
 		p->pages = nr_good_pages;
 		nr_extents = setup_swap_extents(p, span);
@@ -2009,10 +2299,34 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p,
 		nr_good_pages = p->pages;
 	}
 	if (!nr_good_pages) {
-		printk(KERN_WARNING "Empty swap-file\n");
+		pr_warn("Empty swap-file\n");
 		return -EINVAL;
 	}
 
+	if (!cluster_info)
+		return nr_extents;
+
+	for (i = 0; i < nr_clusters; i++) {
+		if (!cluster_count(&cluster_info[idx])) {
+			cluster_set_flag(&cluster_info[idx], CLUSTER_FLAG_FREE);
+			if (cluster_is_null(&p->free_cluster_head)) {
+				cluster_set_next_flag(&p->free_cluster_head,
+								idx, 0);
+				cluster_set_next_flag(&p->free_cluster_tail,
+								idx, 0);
+			} else {
+				unsigned int tail;
+
+				tail = cluster_next(&p->free_cluster_tail);
+				cluster_set_next(&cluster_info[tail], idx);
+				cluster_set_next_flag(&p->free_cluster_tail,
+								idx, 0);
+			}
+		}
+		idx++;
+		if (idx == nr_clusters)
+			idx = 0;
+	}
 	return nr_extents;
 }
 
@@ -2044,6 +2358,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	sector_t span;
 	unsigned long maxpages;
 	unsigned char *swap_map = NULL;
+	struct swap_cluster_info *cluster_info = NULL;
 	unsigned long *frontswap_map = NULL;
 	struct page *page = NULL;
 	struct inode *inode = NULL;
@@ -2058,6 +2373,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	if (IS_ERR(p))
 		return PTR_ERR(p);
 
+	INIT_WORK(&p->discard_work, swap_discard_work);
+
 	name = getname(specialfile);
 	if (IS_ERR(name)) {
 		error = PTR_ERR(name);
@@ -2117,13 +2434,38 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 		error = -ENOMEM;
 		goto bad_swap;
 	}
+	if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) {
+		p->flags |= SWP_SOLIDSTATE;
+		/*
+		 * select a random position to start with to help wear leveling
+		 * SSD
+		 */
+		p->cluster_next = 1 + (prandom_u32() % p->highest_bit);
+
+		cluster_info = vzalloc(DIV_ROUND_UP(maxpages,
+			SWAPFILE_CLUSTER) * sizeof(*cluster_info));
+		if (!cluster_info) {
+			error = -ENOMEM;
+			goto bad_swap;
+		}
+		p->percpu_cluster = alloc_percpu(struct percpu_cluster);
+		if (!p->percpu_cluster) {
+			error = -ENOMEM;
+			goto bad_swap;
+		}
+		for_each_possible_cpu(i) {
+			struct percpu_cluster *cluster;
+			cluster = per_cpu_ptr(p->percpu_cluster, i);
+			cluster_set_null(&cluster->index);
+		}
+	}
 
 	error = swap_cgroup_swapon(p->type, maxpages);
 	if (error)
 		goto bad_swap;
 
 	nr_extents = setup_swap_map_and_extents(p, swap_header, swap_map,
-		maxpages, &span);
+		cluster_info, maxpages, &span);
 	if (unlikely(nr_extents < 0)) {
 		error = nr_extents;
 		goto bad_swap;
@@ -2132,41 +2474,33 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	if (frontswap_enabled)
 		frontswap_map = vzalloc(BITS_TO_LONGS(maxpages) * sizeof(long));
 
-	if (p->bdev) {
-		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
-			p->flags |= SWP_SOLIDSTATE;
-			p->cluster_next = 1 + (prandom_u32() % p->highest_bit);
-		}
-
-		if ((swap_flags & SWAP_FLAG_DISCARD) && swap_discardable(p)) {
-			/*
-			 * When discard is enabled for swap with no particular
-			 * policy flagged, we set all swap discard flags here in
-			 * order to sustain backward compatibility with older
-			 * swapon(8) releases.
-			 */
-			p->flags |= (SWP_DISCARDABLE | SWP_AREA_DISCARD |
-				     SWP_PAGE_DISCARD);
+	if (p->bdev &&(swap_flags & SWAP_FLAG_DISCARD) && swap_discardable(p)) {
+		/*
+		 * When discard is enabled for swap with no particular
+		 * policy flagged, we set all swap discard flags here in
+		 * order to sustain backward compatibility with older
+		 * swapon(8) releases.
+		 */
+		p->flags |= (SWP_DISCARDABLE | SWP_AREA_DISCARD |
+			     SWP_PAGE_DISCARD);
 
-			/*
-			 * By flagging sys_swapon, a sysadmin can tell us to
-			 * either do single-time area discards only, or to just
-			 * perform discards for released swap page-clusters.
-			 * Now it's time to adjust the p->flags accordingly.
-			 */
-			if (swap_flags & SWAP_FLAG_DISCARD_ONCE)
-				p->flags &= ~SWP_PAGE_DISCARD;
-			else if (swap_flags & SWAP_FLAG_DISCARD_PAGES)
-				p->flags &= ~SWP_AREA_DISCARD;
-
-			/* issue a swapon-time discard if it's still required */
-			if (p->flags & SWP_AREA_DISCARD) {
-				int err = discard_swap(p);
-				if (unlikely(err))
-					printk(KERN_ERR
-					       "swapon: discard_swap(%p): %d\n",
-						p, err);
-			}
+		/*
+		 * By flagging sys_swapon, a sysadmin can tell us to
+		 * either do single-time area discards only, or to just
+		 * perform discards for released swap page-clusters.
+		 * Now it's time to adjust the p->flags accordingly.
+		 */
+		if (swap_flags & SWAP_FLAG_DISCARD_ONCE)
+			p->flags &= ~SWP_PAGE_DISCARD;
+		else if (swap_flags & SWAP_FLAG_DISCARD_PAGES)
+			p->flags &= ~SWP_AREA_DISCARD;
+
+		/* issue a swapon-time discard if it's still required */
+		if (p->flags & SWP_AREA_DISCARD) {
+			int err = discard_swap(p);
+			if (unlikely(err))
+				pr_err("swapon: discard_swap(%p): %d\n",
+					p, err);
 		}
 	}
 
@@ -2175,9 +2509,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	if (swap_flags & SWAP_FLAG_PREFER)
 		prio =
 		  (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
-	enable_swap_info(p, prio, swap_map, frontswap_map);
+	enable_swap_info(p, prio, swap_map, cluster_info, frontswap_map);
 
-	printk(KERN_INFO "Adding %uk swap on %s.  "
+	pr_info("Adding %uk swap on %s.  "
 			"Priority:%d extents:%d across:%lluk %s%s%s%s%s\n",
 		p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
 		nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
@@ -2196,6 +2530,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	error = 0;
 	goto out;
 bad_swap:
+	free_percpu(p->percpu_cluster);
+	p->percpu_cluster = NULL;
 	if (inode && S_ISBLK(inode->i_mode) && p->bdev) {
 		set_blocksize(p->bdev, p->old_block_size);
 		blkdev_put(p->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
@@ -2207,6 +2543,7 @@ bad_swap:
 	p->flags = 0;
 	spin_unlock(&swap_lock);
 	vfree(swap_map);
+	vfree(cluster_info);
 	if (swap_file) {
 		if (inode && S_ISREG(inode->i_mode)) {
 			mutex_unlock(&inode->i_mutex);
@@ -2276,6 +2613,16 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage)
 		goto unlock_out;
 
 	count = p->swap_map[offset];
+
+	/*
+	 * swapin_readahead() doesn't check if a swap entry is valid, so the
+	 * swap entry could be SWAP_MAP_BAD. Check here with lock held.
+	 */
+	if (unlikely(swap_count(count) == SWAP_MAP_BAD)) {
+		err = -ENOENT;
+		goto unlock_out;
+	}
+
 	has_cache = count & SWAP_HAS_CACHE;
 	count &= ~SWAP_HAS_CACHE;
 	err = 0;
@@ -2311,7 +2658,7 @@ out:
 	return err;
 
 bad_file:
-	printk(KERN_ERR "swap_dup: %s%08lx\n", Bad_file, entry.val);
+	pr_err("swap_dup: %s%08lx\n", Bad_file, entry.val);
 	goto out;
 }
 
diff --git a/mm/util.c b/mm/util.c
index 7441c41..eaf63fc2 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -388,15 +388,12 @@ struct address_space *page_mapping(struct page *page)
 	struct address_space *mapping = page->mapping;
 
 	VM_BUG_ON(PageSlab(page));
-#ifdef CONFIG_SWAP
 	if (unlikely(PageSwapCache(page))) {
 		swp_entry_t entry;
 
 		entry.val = page_private(page);
 		mapping = swap_address_space(entry);
-	} else
-#endif
-	if ((unsigned long)mapping & PAGE_MAPPING_ANON)
+	} else if ((unsigned long)mapping & PAGE_MAPPING_ANON)
 		mapping = NULL;
 	return mapping;
 }
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 13a5495..93d3182 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -752,7 +752,6 @@ struct vmap_block_queue {
 struct vmap_block {
 	spinlock_t lock;
 	struct vmap_area *va;
-	struct vmap_block_queue *vbq;
 	unsigned long free, dirty;
 	DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS);
 	struct list_head free_list;
@@ -830,7 +829,6 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask)
 	radix_tree_preload_end();
 
 	vbq = &get_cpu_var(vmap_block_queue);
-	vb->vbq = vbq;
 	spin_lock(&vbq->lock);
 	list_add_rcu(&vb->free_list, &vbq->free);
 	spin_unlock(&vbq->lock);
@@ -1018,15 +1016,16 @@ void vm_unmap_aliases(void)
 
 		rcu_read_lock();
 		list_for_each_entry_rcu(vb, &vbq->free, free_list) {
-			int i;
+			int i, j;
 
 			spin_lock(&vb->lock);
 			i = find_first_bit(vb->dirty_map, VMAP_BBMAP_BITS);
-			while (i < VMAP_BBMAP_BITS) {
+			if (i < VMAP_BBMAP_BITS) {
 				unsigned long s, e;
-				int j;
-				j = find_next_zero_bit(vb->dirty_map,
-					VMAP_BBMAP_BITS, i);
+
+				j = find_last_bit(vb->dirty_map,
+							VMAP_BBMAP_BITS);
+				j = j + 1; /* need exclusive index */
 
 				s = vb->va->va_start + (i << PAGE_SHIFT);
 				e = vb->va->va_start + (j << PAGE_SHIFT);
@@ -1036,10 +1035,6 @@ void vm_unmap_aliases(void)
 					start = s;
 				if (e > end)
 					end = e;
-
-				i = j;
-				i = find_next_bit(vb->dirty_map,
-							VMAP_BBMAP_BITS, i);
 			}
 			spin_unlock(&vb->lock);
 		}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 2cff0d4..a3bf7fd 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -139,11 +139,23 @@ static bool global_reclaim(struct scan_control *sc)
 {
 	return !sc->target_mem_cgroup;
 }
+
+static bool mem_cgroup_should_soft_reclaim(struct scan_control *sc)
+{
+	struct mem_cgroup *root = sc->target_mem_cgroup;
+	return !mem_cgroup_disabled() &&
+		mem_cgroup_soft_reclaim_eligible(root, root) != SKIP_TREE;
+}
 #else
 static bool global_reclaim(struct scan_control *sc)
 {
 	return true;
 }
+
+static bool mem_cgroup_should_soft_reclaim(struct scan_control *sc)
+{
+	return false;
+}
 #endif
 
 static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru)
@@ -155,14 +167,31 @@ static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru)
 }
 
 /*
- * Add a shrinker callback to be called from the vm
+ * Add a shrinker callback to be called from the vm.
  */
-void register_shrinker(struct shrinker *shrinker)
+int register_shrinker(struct shrinker *shrinker)
 {
-	atomic_long_set(&shrinker->nr_in_batch, 0);
+	size_t size = sizeof(*shrinker->nr_deferred);
+
+	/*
+	 * If we only have one possible node in the system anyway, save
+	 * ourselves the trouble and disable NUMA aware behavior. This way we
+	 * will save memory and some small loop time later.
+	 */
+	if (nr_node_ids == 1)
+		shrinker->flags &= ~SHRINKER_NUMA_AWARE;
+
+	if (shrinker->flags & SHRINKER_NUMA_AWARE)
+		size *= nr_node_ids;
+
+	shrinker->nr_deferred = kzalloc(size, GFP_KERNEL);
+	if (!shrinker->nr_deferred)
+		return -ENOMEM;
+
 	down_write(&shrinker_rwsem);
 	list_add_tail(&shrinker->list, &shrinker_list);
 	up_write(&shrinker_rwsem);
+	return 0;
 }
 EXPORT_SYMBOL(register_shrinker);
 
@@ -177,15 +206,102 @@ void unregister_shrinker(struct shrinker *shrinker)
 }
 EXPORT_SYMBOL(unregister_shrinker);
 
-static inline int do_shrinker_shrink(struct shrinker *shrinker,
-				     struct shrink_control *sc,
-				     unsigned long nr_to_scan)
-{
-	sc->nr_to_scan = nr_to_scan;
-	return (*shrinker->shrink)(shrinker, sc);
+#define SHRINK_BATCH 128
+
+static unsigned long
+shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker,
+		 unsigned long nr_pages_scanned, unsigned long lru_pages)
+{
+	unsigned long freed = 0;
+	unsigned long long delta;
+	long total_scan;
+	long max_pass;
+	long nr;
+	long new_nr;
+	int nid = shrinkctl->nid;
+	long batch_size = shrinker->batch ? shrinker->batch
+					  : SHRINK_BATCH;
+
+	max_pass = shrinker->count_objects(shrinker, shrinkctl);
+	if (max_pass == 0)
+		return 0;
+
+	/*
+	 * copy the current shrinker scan count into a local variable
+	 * and zero it so that other concurrent shrinker invocations
+	 * don't also do this scanning work.
+	 */
+	nr = atomic_long_xchg(&shrinker->nr_deferred[nid], 0);
+
+	total_scan = nr;
+	delta = (4 * nr_pages_scanned) / shrinker->seeks;
+	delta *= max_pass;
+	do_div(delta, lru_pages + 1);
+	total_scan += delta;
+	if (total_scan < 0) {
+		printk(KERN_ERR
+		"shrink_slab: %pF negative objects to delete nr=%ld\n",
+		       shrinker->scan_objects, total_scan);
+		total_scan = max_pass;
+	}
+
+	/*
+	 * We need to avoid excessive windup on filesystem shrinkers
+	 * due to large numbers of GFP_NOFS allocations causing the
+	 * shrinkers to return -1 all the time. This results in a large
+	 * nr being built up so when a shrink that can do some work
+	 * comes along it empties the entire cache due to nr >>>
+	 * max_pass.  This is bad for sustaining a working set in
+	 * memory.
+	 *
+	 * Hence only allow the shrinker to scan the entire cache when
+	 * a large delta change is calculated directly.
+	 */
+	if (delta < max_pass / 4)
+		total_scan = min(total_scan, max_pass / 2);
+
+	/*
+	 * Avoid risking looping forever due to too large nr value:
+	 * never try to free more than twice the estimate number of
+	 * freeable entries.
+	 */
+	if (total_scan > max_pass * 2)
+		total_scan = max_pass * 2;
+
+	trace_mm_shrink_slab_start(shrinker, shrinkctl, nr,
+				nr_pages_scanned, lru_pages,
+				max_pass, delta, total_scan);
+
+	while (total_scan >= batch_size) {
+		unsigned long ret;
+
+		shrinkctl->nr_to_scan = batch_size;
+		ret = shrinker->scan_objects(shrinker, shrinkctl);
+		if (ret == SHRINK_STOP)
+			break;
+		freed += ret;
+
+		count_vm_events(SLABS_SCANNED, batch_size);
+		total_scan -= batch_size;
+
+		cond_resched();
+	}
+
+	/*
+	 * move the unused scan count back into the shrinker in a
+	 * manner that handles concurrent updates. If we exhausted the
+	 * scan, there is no need to do an update.
+	 */
+	if (total_scan > 0)
+		new_nr = atomic_long_add_return(total_scan,
+						&shrinker->nr_deferred[nid]);
+	else
+		new_nr = atomic_long_read(&shrinker->nr_deferred[nid]);
+
+	trace_mm_shrink_slab_end(shrinker, freed, nr, new_nr);
+	return freed;
 }
 
-#define SHRINK_BATCH 128
 /*
  * Call the shrink functions to age shrinkable caches
  *
@@ -205,115 +321,45 @@ static inline int do_shrinker_shrink(struct shrinker *shrinker,
  *
  * Returns the number of slab objects which we shrunk.
  */
-unsigned long shrink_slab(struct shrink_control *shrink,
+unsigned long shrink_slab(struct shrink_control *shrinkctl,
 			  unsigned long nr_pages_scanned,
 			  unsigned long lru_pages)
 {
 	struct shrinker *shrinker;
-	unsigned long ret = 0;
+	unsigned long freed = 0;
 
 	if (nr_pages_scanned == 0)
 		nr_pages_scanned = SWAP_CLUSTER_MAX;
 
 	if (!down_read_trylock(&shrinker_rwsem)) {
-		/* Assume we'll be able to shrink next time */
-		ret = 1;
+		/*
+		 * If we would return 0, our callers would understand that we
+		 * have nothing else to shrink and give up trying. By returning
+		 * 1 we keep it going and assume we'll be able to shrink next
+		 * time.
+		 */
+		freed = 1;
 		goto out;
 	}
 
 	list_for_each_entry(shrinker, &shrinker_list, list) {
-		unsigned long long delta;
-		long total_scan;
-		long max_pass;
-		int shrink_ret = 0;
-		long nr;
-		long new_nr;
-		long batch_size = shrinker->batch ? shrinker->batch
-						  : SHRINK_BATCH;
-
-		max_pass = do_shrinker_shrink(shrinker, shrink, 0);
-		if (max_pass <= 0)
-			continue;
-
-		/*
-		 * copy the current shrinker scan count into a local variable
-		 * and zero it so that other concurrent shrinker invocations
-		 * don't also do this scanning work.
-		 */
-		nr = atomic_long_xchg(&shrinker->nr_in_batch, 0);
-
-		total_scan = nr;
-		delta = (4 * nr_pages_scanned) / shrinker->seeks;
-		delta *= max_pass;
-		do_div(delta, lru_pages + 1);
-		total_scan += delta;
-		if (total_scan < 0) {
-			printk(KERN_ERR "shrink_slab: %pF negative objects to "
-			       "delete nr=%ld\n",
-			       shrinker->shrink, total_scan);
-			total_scan = max_pass;
-		}
-
-		/*
-		 * We need to avoid excessive windup on filesystem shrinkers
-		 * due to large numbers of GFP_NOFS allocations causing the
-		 * shrinkers to return -1 all the time. This results in a large
-		 * nr being built up so when a shrink that can do some work
-		 * comes along it empties the entire cache due to nr >>>
-		 * max_pass.  This is bad for sustaining a working set in
-		 * memory.
-		 *
-		 * Hence only allow the shrinker to scan the entire cache when
-		 * a large delta change is calculated directly.
-		 */
-		if (delta < max_pass / 4)
-			total_scan = min(total_scan, max_pass / 2);
-
-		/*
-		 * Avoid risking looping forever due to too large nr value:
-		 * never try to free more than twice the estimate number of
-		 * freeable entries.
-		 */
-		if (total_scan > max_pass * 2)
-			total_scan = max_pass * 2;
-
-		trace_mm_shrink_slab_start(shrinker, shrink, nr,
-					nr_pages_scanned, lru_pages,
-					max_pass, delta, total_scan);
-
-		while (total_scan >= batch_size) {
-			int nr_before;
+		for_each_node_mask(shrinkctl->nid, shrinkctl->nodes_to_scan) {
+			if (!node_online(shrinkctl->nid))
+				continue;
 
-			nr_before = do_shrinker_shrink(shrinker, shrink, 0);
-			shrink_ret = do_shrinker_shrink(shrinker, shrink,
-							batch_size);
-			if (shrink_ret == -1)
+			if (!(shrinker->flags & SHRINKER_NUMA_AWARE) &&
+			    (shrinkctl->nid != 0))
 				break;
-			if (shrink_ret < nr_before)
-				ret += nr_before - shrink_ret;
-			count_vm_events(SLABS_SCANNED, batch_size);
-			total_scan -= batch_size;
 
-			cond_resched();
-		}
+			freed += shrink_slab_node(shrinkctl, shrinker,
+				 nr_pages_scanned, lru_pages);
 
-		/*
-		 * move the unused scan count back into the shrinker in a
-		 * manner that handles concurrent updates. If we exhausted the
-		 * scan, there is no need to do an update.
-		 */
-		if (total_scan > 0)
-			new_nr = atomic_long_add_return(total_scan,
-					&shrinker->nr_in_batch);
-		else
-			new_nr = atomic_long_read(&shrinker->nr_in_batch);
-
-		trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr);
+		}
 	}
 	up_read(&shrinker_rwsem);
 out:
 	cond_resched();
-	return ret;
+	return freed;
 }
 
 static inline int is_page_cache_freeable(struct page *page)
@@ -2111,9 +2157,11 @@ static inline bool should_continue_reclaim(struct zone *zone,
 	}
 }
 
-static void shrink_zone(struct zone *zone, struct scan_control *sc)
+static int
+__shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim)
 {
 	unsigned long nr_reclaimed, nr_scanned;
+	int groups_scanned = 0;
 
 	do {
 		struct mem_cgroup *root = sc->target_mem_cgroup;
@@ -2121,15 +2169,17 @@ static void shrink_zone(struct zone *zone, struct scan_control *sc)
 			.zone = zone,
 			.priority = sc->priority,
 		};
-		struct mem_cgroup *memcg;
+		struct mem_cgroup *memcg = NULL;
+		mem_cgroup_iter_filter filter = (soft_reclaim) ?
+			mem_cgroup_soft_reclaim_eligible : NULL;
 
 		nr_reclaimed = sc->nr_reclaimed;
 		nr_scanned = sc->nr_scanned;
 
-		memcg = mem_cgroup_iter(root, NULL, &reclaim);
-		do {
+		while ((memcg = mem_cgroup_iter_cond(root, memcg, &reclaim, filter))) {
 			struct lruvec *lruvec;
 
+			groups_scanned++;
 			lruvec = mem_cgroup_zone_lruvec(zone, memcg);
 
 			shrink_lruvec(lruvec, sc);
@@ -2149,8 +2199,7 @@ static void shrink_zone(struct zone *zone, struct scan_control *sc)
 				mem_cgroup_iter_break(root, memcg);
 				break;
 			}
-			memcg = mem_cgroup_iter(root, memcg, &reclaim);
-		} while (memcg);
+		}
 
 		vmpressure(sc->gfp_mask, sc->target_mem_cgroup,
 			   sc->nr_scanned - nr_scanned,
@@ -2158,6 +2207,37 @@ static void shrink_zone(struct zone *zone, struct scan_control *sc)
 
 	} while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed,
 					 sc->nr_scanned - nr_scanned, sc));
+
+	return groups_scanned;
+}
+
+
+static void shrink_zone(struct zone *zone, struct scan_control *sc)
+{
+	bool do_soft_reclaim = mem_cgroup_should_soft_reclaim(sc);
+	unsigned long nr_scanned = sc->nr_scanned;
+	int scanned_groups;
+
+	scanned_groups = __shrink_zone(zone, sc, do_soft_reclaim);
+	/*
+	 * memcg iterator might race with other reclaimer or start from
+	 * a incomplete tree walk so the tree walk in __shrink_zone
+	 * might have missed groups that are above the soft limit. Try
+	 * another loop to catch up with others. Do it just once to
+	 * prevent from reclaim latencies when other reclaimers always
+	 * preempt this one.
+	 */
+	if (do_soft_reclaim && !scanned_groups)
+		__shrink_zone(zone, sc, do_soft_reclaim);
+
+	/*
+	 * No group is over the soft limit or those that are do not have
+	 * pages in the zone we are reclaiming so we have to reclaim everybody
+	 */
+	if (do_soft_reclaim && (sc->nr_scanned == nr_scanned)) {
+		__shrink_zone(zone, sc, false);
+		return;
+	}
 }
 
 /* Returns true if compaction should go ahead for a high-order request */
@@ -2221,8 +2301,6 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
 {
 	struct zoneref *z;
 	struct zone *zone;
-	unsigned long nr_soft_reclaimed;
-	unsigned long nr_soft_scanned;
 	bool aborted_reclaim = false;
 
 	/*
@@ -2262,18 +2340,6 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
 					continue;
 				}
 			}
-			/*
-			 * This steals pages from memory cgroups over softlimit
-			 * and returns the number of reclaimed pages and
-			 * scanned pages. This works for global memory pressure
-			 * and balancing, not for a memcg's limit.
-			 */
-			nr_soft_scanned = 0;
-			nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone,
-						sc->order, sc->gfp_mask,
-						&nr_soft_scanned);
-			sc->nr_reclaimed += nr_soft_reclaimed;
-			sc->nr_scanned += nr_soft_scanned;
 			/* need some check for avoid more shrink_zone() */
 		}
 
@@ -2354,12 +2420,16 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
 		 */
 		if (global_reclaim(sc)) {
 			unsigned long lru_pages = 0;
+
+			nodes_clear(shrink->nodes_to_scan);
 			for_each_zone_zonelist(zone, z, zonelist,
 					gfp_zone(sc->gfp_mask)) {
 				if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 					continue;
 
 				lru_pages += zone_reclaimable_pages(zone);
+				node_set(zone_to_nid(zone),
+					 shrink->nodes_to_scan);
 			}
 
 			shrink_slab(shrink, sc->nr_scanned, lru_pages);
@@ -2816,6 +2886,8 @@ static bool kswapd_shrink_zone(struct zone *zone,
 		return true;
 
 	shrink_zone(zone, sc);
+	nodes_clear(shrink.nodes_to_scan);
+	node_set(zone_to_nid(zone), shrink.nodes_to_scan);
 
 	reclaim_state->reclaimed_slab = 0;
 	nr_slab = shrink_slab(&shrink, sc->nr_scanned, lru_pages);
@@ -2870,8 +2942,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 {
 	int i;
 	int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
-	unsigned long nr_soft_reclaimed;
-	unsigned long nr_soft_scanned;
 	struct scan_control sc = {
 		.gfp_mask = GFP_KERNEL,
 		.priority = DEF_PRIORITY,
@@ -2986,15 +3056,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 
 			sc.nr_scanned = 0;
 
-			nr_soft_scanned = 0;
-			/*
-			 * Call soft limit reclaim before calling shrink_zone.
-			 */
-			nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone,
-							order, sc.gfp_mask,
-							&nr_soft_scanned);
-			sc.nr_reclaimed += nr_soft_reclaimed;
-
 			/*
 			 * There should be no need to raise the scanning
 			 * priority if enough pages are already being scanned
@@ -3237,7 +3298,7 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)
 	}
 	if (!waitqueue_active(&pgdat->kswapd_wait))
 		return;
-	if (zone_watermark_ok_safe(zone, order, low_wmark_pages(zone), 0, 0))
+	if (zone_balanced(zone, order, 0, 0))
 		return;
 
 	trace_mm_vmscan_wakeup_kswapd(pgdat->node_id, zone_idx(zone), order);
@@ -3524,10 +3585,9 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 		 * number of slab pages and shake the slab until it is reduced
 		 * by the same nr_pages that we used for reclaiming unmapped
 		 * pages.
-		 *
-		 * Note that shrink_slab will free memory on all zones and may
-		 * take a long time.
 		 */
+		nodes_clear(shrink.nodes_to_scan);
+		node_set(zone_to_nid(zone), shrink.nodes_to_scan);
 		for (;;) {
 			unsigned long lru_pages = zone_reclaimable_pages(zone);
 
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 20c2ef4..b4da7b5 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -414,12 +414,17 @@ void dec_zone_page_state(struct page *page, enum zone_stat_item item)
 EXPORT_SYMBOL(dec_zone_page_state);
 #endif
 
+static inline void fold_diff(int *diff)
+{
+	int i;
+
+	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+		if (diff[i])
+			atomic_long_add(diff[i], &vm_stat[i]);
+}
+
 /*
- * Update the zone counters for one cpu.
- *
- * The cpu specified must be either the current cpu or a processor that
- * is not online. If it is the current cpu then the execution thread must
- * be pinned to the current cpu.
+ * Update the zone counters for the current cpu.
  *
  * Note that refresh_cpu_vm_stats strives to only access
  * node local memory. The per cpu pagesets on remote zones are placed
@@ -432,33 +437,29 @@ EXPORT_SYMBOL(dec_zone_page_state);
  * with the global counters. These could cause remote node cache line
  * bouncing and will have to be only done when necessary.
  */
-void refresh_cpu_vm_stats(int cpu)
+static void refresh_cpu_vm_stats(void)
 {
 	struct zone *zone;
 	int i;
 	int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, };
 
 	for_each_populated_zone(zone) {
-		struct per_cpu_pageset *p;
+		struct per_cpu_pageset __percpu *p = zone->pageset;
 
-		p = per_cpu_ptr(zone->pageset, cpu);
+		for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) {
+			int v;
 
-		for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
-			if (p->vm_stat_diff[i]) {
-				unsigned long flags;
-				int v;
+			v = this_cpu_xchg(p->vm_stat_diff[i], 0);
+			if (v) {
 
-				local_irq_save(flags);
-				v = p->vm_stat_diff[i];
-				p->vm_stat_diff[i] = 0;
-				local_irq_restore(flags);
 				atomic_long_add(v, &zone->vm_stat[i]);
 				global_diff[i] += v;
 #ifdef CONFIG_NUMA
 				/* 3 seconds idle till flush */
-				p->expire = 3;
+				__this_cpu_write(p->expire, 3);
 #endif
 			}
+		}
 		cond_resched();
 #ifdef CONFIG_NUMA
 		/*
@@ -468,29 +469,57 @@ void refresh_cpu_vm_stats(int cpu)
 		 * Check if there are pages remaining in this pageset
 		 * if not then there is nothing to expire.
 		 */
-		if (!p->expire || !p->pcp.count)
+		if (!__this_cpu_read(p->expire) ||
+			       !__this_cpu_read(p->pcp.count))
 			continue;
 
 		/*
 		 * We never drain zones local to this processor.
 		 */
 		if (zone_to_nid(zone) == numa_node_id()) {
-			p->expire = 0;
+			__this_cpu_write(p->expire, 0);
 			continue;
 		}
 
-		p->expire--;
-		if (p->expire)
+
+		if (__this_cpu_dec_return(p->expire))
 			continue;
 
-		if (p->pcp.count)
-			drain_zone_pages(zone, &p->pcp);
+		if (__this_cpu_read(p->pcp.count))
+			drain_zone_pages(zone, __this_cpu_ptr(&p->pcp));
 #endif
 	}
+	fold_diff(global_diff);
+}
 
-	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
-		if (global_diff[i])
-			atomic_long_add(global_diff[i], &vm_stat[i]);
+/*
+ * Fold the data for an offline cpu into the global array.
+ * There cannot be any access by the offline cpu and therefore
+ * synchronization is simplified.
+ */
+void cpu_vm_stats_fold(int cpu)
+{
+	struct zone *zone;
+	int i;
+	int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, };
+
+	for_each_populated_zone(zone) {
+		struct per_cpu_pageset *p;
+
+		p = per_cpu_ptr(zone->pageset, cpu);
+
+		for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+			if (p->vm_stat_diff[i]) {
+				int v;
+
+				v = p->vm_stat_diff[i];
+				p->vm_stat_diff[i] = 0;
+				atomic_long_add(v, &zone->vm_stat[i]);
+				global_diff[i] += v;
+			}
+	}
+
+	fold_diff(global_diff);
 }
 
 /*
@@ -817,6 +846,12 @@ const char * const vmstat_text[] = {
 	"thp_zero_page_alloc",
 	"thp_zero_page_alloc_failed",
 #endif
+#ifdef CONFIG_SMP
+	"nr_tlb_remote_flush",
+	"nr_tlb_remote_flush_received",
+#endif
+	"nr_tlb_local_flush_all",
+	"nr_tlb_local_flush_one",
 
 #endif /* CONFIG_VM_EVENTS_COUNTERS */
 };
@@ -1177,7 +1212,7 @@ int sysctl_stat_interval __read_mostly = HZ;
 
 static void vmstat_update(struct work_struct *w)
 {
-	refresh_cpu_vm_stats(smp_processor_id());
+	refresh_cpu_vm_stats();
 	schedule_delayed_work(&__get_cpu_var(vmstat_work),
 		round_jiffies_relative(sysctl_stat_interval));
 }
diff --git a/mm/zswap.c b/mm/zswap.c
index deda2b6..841e35f 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -409,7 +409,7 @@ static int zswap_get_swap_cache_page(swp_entry_t entry,
 				struct page **retpage)
 {
 	struct page *found_page, *new_page = NULL;
-	struct address_space *swapper_space = &swapper_spaces[swp_type(entry)];
+	struct address_space *swapper_space = swap_address_space(entry);
 	int err;
 
 	*retpage = NULL;
@@ -790,26 +790,14 @@ static void zswap_frontswap_invalidate_page(unsigned type, pgoff_t offset)
 static void zswap_frontswap_invalidate_area(unsigned type)
 {
 	struct zswap_tree *tree = zswap_trees[type];
-	struct rb_node *node;
-	struct zswap_entry *entry;
+	struct zswap_entry *entry, *n;
 
 	if (!tree)
 		return;
 
 	/* walk the tree and free everything */
 	spin_lock(&tree->lock);
-	/*
-	 * TODO: Even though this code should not be executed because
-	 * the try_to_unuse() in swapoff should have emptied the tree,
-	 * it is very wasteful to rebalance the tree after every
-	 * removal when we are freeing the whole tree.
-	 *
-	 * If post-order traversal code is ever added to the rbtree
-	 * implementation, it should be used here.
-	 */
-	while ((node = rb_first(&tree->rbroot))) {
-		entry = rb_entry(node, struct zswap_entry, rbnode);
-		rb_erase(&entry->rbnode, &tree->rbroot);
+	rbtree_postorder_for_each_entry_safe(entry, n, &tree->rbroot, rbnode) {
 		zbud_free(tree->pool, entry->handle);
 		zswap_entry_cache_free(entry);
 		atomic_dec(&zswap_stored_pages);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 2fb2d88..61fc573 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -210,6 +210,7 @@ out_vid_del:
 static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
 {
 	struct net_device *new_dev;
+	struct vlan_dev_priv *vlan;
 	struct net *net = dev_net(real_dev);
 	struct vlan_net *vn = net_generic(net, vlan_net_id);
 	char name[IFNAMSIZ];
@@ -260,11 +261,12 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
 	new_dev->mtu = real_dev->mtu;
 	new_dev->priv_flags |= (real_dev->priv_flags & IFF_UNICAST_FLT);
 
-	vlan_dev_priv(new_dev)->vlan_proto = htons(ETH_P_8021Q);
-	vlan_dev_priv(new_dev)->vlan_id = vlan_id;
-	vlan_dev_priv(new_dev)->real_dev = real_dev;
-	vlan_dev_priv(new_dev)->dent = NULL;
-	vlan_dev_priv(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
+	vlan = vlan_dev_priv(new_dev);
+	vlan->vlan_proto = htons(ETH_P_8021Q);
+	vlan->vlan_id = vlan_id;
+	vlan->real_dev = real_dev;
+	vlan->dent = NULL;
+	vlan->flags = VLAN_FLAG_REORDER_HDR;
 
 	new_dev->rtnl_link_ops = &vlan_link_ops;
 	err = register_vlan_dev(new_dev);
@@ -459,6 +461,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 
 	case NETDEV_NOTIFY_PEERS:
 	case NETDEV_BONDING_FAILOVER:
+	case NETDEV_RESEND_IGMP:
 		/* Propagate to vlan devices */
 		vlan_group_for_each_dev(grp, i, vlandev)
 			call_netdevice_notifiers(event, vlandev);
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 4a78c4d..6ee48aa 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -91,7 +91,12 @@ EXPORT_SYMBOL(__vlan_find_dev_deep);
 
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
-	return vlan_dev_priv(dev)->real_dev;
+	struct net_device *ret = vlan_dev_priv(dev)->real_dev;
+
+	while (is_vlan_dev(ret))
+		ret = vlan_dev_priv(ret)->real_dev;
+
+	return ret;
 }
 EXPORT_SYMBOL(vlan_dev_real_dev);
 
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 1cd3d2a..9ab8a7e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -107,10 +107,10 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
 	u16 vlan_tci = 0;
 	int rc;
 
-	if (!(vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR)) {
+	if (!(vlan->flags & VLAN_FLAG_REORDER_HDR)) {
 		vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
 
-		vlan_tci = vlan_dev_priv(dev)->vlan_id;
+		vlan_tci = vlan->vlan_id;
 		vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb);
 		vhdr->h_vlan_TCI = htons(vlan_tci);
 
@@ -133,7 +133,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
 		saddr = dev->dev_addr;
 
 	/* Now make the underlying real hard header */
-	dev = vlan_dev_priv(dev)->real_dev;
+	dev = vlan->real_dev;
 	rc = dev_hard_header(skb, dev, type, daddr, saddr, len + vhdrlen);
 	if (rc > 0)
 		rc += vhdrlen;
diff --git a/net/9p/client.c b/net/9p/client.c
index 8b93cae..ba93bda 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -658,17 +658,12 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
 
 	/*
 	 * if we haven't received a response for oldreq,
-	 * remove it from the list, and notify the transport
-	 * layer that the reply will never arrive.
+	 * remove it from the list
 	 */
-	spin_lock(&c->lock);
 	if (oldreq->status == REQ_STATUS_FLSH) {
+		spin_lock(&c->lock);
 		list_del(&oldreq->req_list);
 		spin_unlock(&c->lock);
-		if (c->trans_mod->cancelled)
-			c->trans_mod->cancelled(c, req);
-	} else {
-		spin_unlock(&c->lock);
 	}
 
 	p9_free_req(c, req);
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 928f2bb..8f68df5 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -588,17 +588,6 @@ static int rdma_cancel(struct p9_client *client, struct p9_req_t *req)
 	return 1;
 }
 
-/* A request has been fully flushed without a reply.
- * That means we have posted one buffer in excess.
- */
-static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req)
-{
-	struct p9_trans_rdma *rdma = client->trans;
-
-	atomic_inc(&rdma->excess_rc);
-	return 0;
-}
-
 /**
  * trans_create_rdma - Transport method for creating atransport instance
  * @client: client instance
diff --git a/net/Kconfig b/net/Kconfig
index 2b40660..ee02136 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -281,7 +281,7 @@ menu "Network testing"
 
 config NET_PKTGEN
 	tristate "Packet Generator (USE WITH CAUTION)"
-	depends on PROC_FS
+	depends on INET && PROC_FS
 	---help---
 	  This module will inject preconfigured packets, at a configurable
 	  rate, out of a given interface.  It is used for network interface
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cc27297..b91cc08 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -608,7 +608,7 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
 	 * as supported send it. If not supported assume that the controller
 	 * does not have actual support for stored link keys which makes this
 	 * command redundant anyway.
-         */
+	 */
 	if (hdev->commands[6] & 0x80) {
 		struct hci_cp_delete_stored_link_key cp;
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0437200..50e39f4 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3024,17 +3024,20 @@ unlock:
 static u8 hci_get_auth_req(struct hci_conn *conn)
 {
 	/* If remote requests dedicated bonding follow that lead */
-	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
+	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
+	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
 		/* If both remote and local IO capabilities allow MITM
 		 * protection then require it, otherwise don't */
-		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
-			return 0x02;
+		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
+		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
+			return HCI_AT_DEDICATED_BONDING;
 		else
-			return 0x03;
+			return HCI_AT_DEDICATED_BONDING_MITM;
 	}
 
 	/* If remote requests no-bonding follow that lead */
-	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
+	if (conn->remote_auth == HCI_AT_NO_BONDING ||
+	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
 		return conn->remote_auth | (conn->auth_type & 0x01);
 
 	return conn->auth_type;
@@ -3066,7 +3069,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		/* Change the IO capability from KeyboardDisplay
 		 * to DisplayYesNo as it is not supported by BT spec. */
 		cp.capability = (conn->io_capability == 0x04) ?
-						0x01 : conn->io_capability;
+				HCI_IO_DISPLAY_YESNO : conn->io_capability;
 		conn->auth_type = hci_get_auth_req(conn);
 		cp.authentication = conn->auth_type;
 
@@ -3140,7 +3143,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	 * request. The only exception is when we're dedicated bonding
 	 * initiators (connect_cfm_cb set) since then we always have the MITM
 	 * bit set. */
-	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
+	if (!conn->connect_cfm_cb && loc_mitm &&
+	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
 		BT_DBG("Rejecting request: remote device can't provide MITM");
 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
 			     sizeof(ev->bdaddr), &ev->bdaddr);
@@ -3148,8 +3152,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	}
 
 	/* If no side requires MITM protection; auto-accept */
-	if ((!loc_mitm || conn->remote_cap == 0x03) &&
-	    (!rem_mitm || conn->io_capability == 0x03)) {
+	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
+	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
 
 		/* If we're not the initiators request authorization to
 		 * proceed from user space (mgmt_user_confirm with
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 7ad6ecf..edf623a 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -590,7 +590,7 @@ int __init bt_sysfs_init(void)
 
 	bt_class = class_create(THIS_MODULE, "bluetooth");
 
-	return PTR_RET(bt_class);
+	return PTR_ERR_OR_ZERO(bt_class);
 }
 
 void bt_sysfs_cleanup(void)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 0c699cd..bdc35a7 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -225,17 +225,47 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
 
 static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
 {
-	unsigned char buf[32], hdr;
-	int rsize;
+	unsigned char hdr;
+	u8 *buf;
+	int rsize, ret;
 
-	rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-	if (rsize > sizeof(buf))
+	buf = hid_alloc_report_buf(report, GFP_ATOMIC);
+	if (!buf)
 		return -EIO;
 
 	hid_output_report(report, buf);
 	hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
 
-	return hidp_send_intr_message(session, hdr, buf, rsize);
+	rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+	ret = hidp_send_intr_message(session, hdr, buf, rsize);
+
+	kfree(buf);
+	return ret;
+}
+
+static int hidp_hidinput_event(struct input_dev *dev, unsigned int type,
+			       unsigned int code, int value)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct hidp_session *session = hid->driver_data;
+	struct hid_field *field;
+	int offset;
+
+	BT_DBG("session %p type %d code %d value %d",
+	       session, type, code, value);
+
+	if (type != EV_LED)
+		return -1;
+
+	offset = hidinput_find_field(hid, type, code, &field);
+	if (offset == -1) {
+		hid_warn(dev, "event field not found\n");
+		return -1;
+	}
+
+	hid_set_field(field, offset, value);
+
+	return hidp_send_report(session, field->report);
 }
 
 static int hidp_get_raw_report(struct hid_device *hid,
@@ -678,20 +708,6 @@ static int hidp_parse(struct hid_device *hid)
 
 static int hidp_start(struct hid_device *hid)
 {
-	struct hidp_session *session = hid->driver_data;
-	struct hid_report *report;
-
-	if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
-		return 0;
-
-	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
-			report_list, list)
-		hidp_send_report(session, report);
-
-	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
-			report_list, list)
-		hidp_send_report(session, report);
-
 	return 0;
 }
 
@@ -711,6 +727,7 @@ static struct hid_ll_driver hidp_hid_driver = {
 	.stop = hidp_stop,
 	.open  = hidp_open,
 	.close = hidp_close,
+	.hidinput_input_event = hidp_hidinput_event,
 };
 
 /* This function sets up the hid device. It does not add it
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8c3499b..b3bb7bc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1415,8 +1415,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 			sk->sk_state_change(sk);
 			release_sock(sk);
 
-		} else if (chan->state == BT_CONNECT)
+		} else if (chan->state == BT_CONNECT) {
 			l2cap_do_start(chan);
+		}
 
 		l2cap_chan_unlock(chan);
 	}
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 69363bd..0feaaa0 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -245,22 +245,22 @@ fail:
 int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
 {
 	struct netpoll *np;
-	int err = 0;
+	int err;
+
+	if (!p->br->dev->npinfo)
+		return 0;
 
 	np = kzalloc(sizeof(*p->np), gfp);
-	err = -ENOMEM;
 	if (!np)
-		goto out;
+		return -ENOMEM;
 
 	err = __netpoll_setup(np, p->dev, gfp);
 	if (err) {
 		kfree(np);
-		goto out;
+		return err;
 	}
 
 	p->np = np;
-
-out:
 	return err;
 }
 
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 5623be6..aa6c9a8 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -363,7 +363,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (err)
 		goto err2;
 
-	if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL))))
+	err = br_netpoll_enable(p, GFP_KERNEL);
+	if (err)
 		goto err3;
 
 	err = netdev_master_upper_dev_link(dev, br->dev);
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 0daae3e..e4d5cd4 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -61,7 +61,8 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
 
 	for (i = 0; i < mdb->max; i++) {
 		struct net_bridge_mdb_entry *mp;
-		struct net_bridge_port_group *p, **pp;
+		struct net_bridge_port_group *p;
+		struct net_bridge_port_group __rcu **pp;
 		struct net_bridge_port *port;
 
 		hlist_for_each_entry_rcu(mp, &mdb->mhash[i], hlist[mdb->ver]) {
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 61c5e81..08e576a 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1195,7 +1195,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
 		max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay));
 		if (max_delay)
 			group = &mld->mld_mca;
-	} else if (skb->len >= sizeof(*mld2q)) {
+	} else {
 		if (!pskb_may_pull(skb, sizeof(*mld2q))) {
 			err = -EINVAL;
 			goto out;
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 3a3f371..2998dd1 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -102,6 +102,11 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
 	case NETDEV_PRE_TYPE_CHANGE:
 		/* Forbid underlaying device to change its type. */
 		return NOTIFY_BAD;
+
+	case NETDEV_RESEND_IGMP:
+		/* Propagate to master device */
+		call_netdevice_notifiers(event, br->dev);
+		break;
 	}
 
 	/* Events that may cause spanning tree to refresh */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2f7da41..d41283c 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -334,11 +334,6 @@ extern void br_dev_delete(struct net_device *dev, struct list_head *list);
 extern netdev_tx_t br_dev_xmit(struct sk_buff *skb,
 			       struct net_device *dev);
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br)
-{
-	return br->dev->npinfo;
-}
-
 static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
 				       struct sk_buff *skb)
 {
@@ -351,11 +346,6 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
 extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp);
 extern void br_netpoll_disable(struct net_bridge_port *p);
 #else
-static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br)
-{
-	return NULL;
-}
-
 static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
 				       struct sk_buff *skb)
 {
@@ -476,7 +466,7 @@ extern void br_multicast_free_pg(struct rcu_head *head);
 extern struct net_bridge_port_group *br_multicast_new_port_group(
 				struct net_bridge_port *port,
 				struct br_ip *group,
-				struct net_bridge_port_group *next,
+				struct net_bridge_port_group __rcu *next,
 				unsigned char state);
 extern void br_mdb_init(void);
 extern void br_mdb_uninit(void);
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 394bb96..3b9637f 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -1,5 +1,5 @@
 /*
- *	Sysfs attributes of bridge ports
+ *	Sysfs attributes of bridge
  *	Linux ethernet bridge
  *
  *	Authors:
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 70f656c..dbd1c78 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -64,7 +64,7 @@ static int ebt_broute(struct sk_buff *skb)
 static int __net_init broute_net_init(struct net *net)
 {
 	net->xt.broute_table = ebt_register_table(net, &broute_table);
-	return PTR_RET(net->xt.broute_table);
+	return PTR_ERR_OR_ZERO(net->xt.broute_table);
 }
 
 static void __net_exit broute_net_exit(struct net *net)
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 3c2e9dc..94b2b70 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -100,7 +100,7 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
 static int __net_init frame_filter_net_init(struct net *net)
 {
 	net->xt.frame_filter = ebt_register_table(net, &frame_filter);
-	return PTR_RET(net->xt.frame_filter);
+	return PTR_ERR_OR_ZERO(net->xt.frame_filter);
 }
 
 static void __net_exit frame_filter_net_exit(struct net *net)
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 10871bc..322555a 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -100,7 +100,7 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
 static int __net_init frame_nat_net_init(struct net *net)
 {
 	net->xt.frame_nat = ebt_register_table(net, &frame_nat);
-	return PTR_RET(net->xt.frame_nat);
+	return PTR_ERR_OR_ZERO(net->xt.frame_nat);
 }
 
 static void __net_exit frame_nat_net_exit(struct net *net)
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index eb0a46a..3be308e 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -409,7 +409,7 @@ static void ceph_sock_write_space(struct sock *sk)
 	 * and net/core/stream.c:sk_stream_write_space().
 	 */
 	if (con_flag_test(con, CON_FLAG_WRITE_PENDING)) {
-		if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+		if (sk_stream_is_writeable(sk)) {
 			dout("%s %p queueing write work\n", __func__, con);
 			clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 			queue_con(con);
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index dd47889..7d40a61 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2129,7 +2129,8 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
 			dout("osdc_start_request failed map, "
 				" will retry %lld\n", req->r_tid);
 			rc = 0;
-		}
+		} else
+			__unregister_request(osdc, req);
 		goto out_unlock;
 	}
 	if (req->r_osd == NULL) {
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 8ab48cd..af814e7 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -48,6 +48,7 @@
 #include <linux/highmem.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/pagemap.h>
 
 #include <net/protocol.h>
 #include <linux/skbuff.h>
@@ -573,6 +574,77 @@ fault:
 }
 EXPORT_SYMBOL(skb_copy_datagram_from_iovec);
 
+/**
+ *	zerocopy_sg_from_iovec - Build a zerocopy datagram from an iovec
+ *	@skb: buffer to copy
+ *	@from: io vector to copy to
+ *	@offset: offset in the io vector to start copying from
+ *	@count: amount of vectors to copy to buffer from
+ *
+ *	The function will first copy up to headlen, and then pin the userspace
+ *	pages and build frags through them.
+ *
+ *	Returns 0, -EFAULT or -EMSGSIZE.
+ *	Note: the iovec is not modified during the copy
+ */
+int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
+				  int offset, size_t count)
+{
+	int len = iov_length(from, count) - offset;
+	int copy = min_t(int, skb_headlen(skb), len);
+	int size;
+	int i = 0;
+
+	/* copy up to skb headlen */
+	if (skb_copy_datagram_from_iovec(skb, 0, from, offset, copy))
+		return -EFAULT;
+
+	if (len == copy)
+		return 0;
+
+	offset += copy;
+	while (count--) {
+		struct page *page[MAX_SKB_FRAGS];
+		int num_pages;
+		unsigned long base;
+		unsigned long truesize;
+
+		/* Skip over from offset and copied */
+		if (offset >= from->iov_len) {
+			offset -= from->iov_len;
+			++from;
+			continue;
+		}
+		len = from->iov_len - offset;
+		base = (unsigned long)from->iov_base + offset;
+		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+		if (i + size > MAX_SKB_FRAGS)
+			return -EMSGSIZE;
+		num_pages = get_user_pages_fast(base, size, 0, &page[i]);
+		if (num_pages != size) {
+			release_pages(&page[i], num_pages, 0);
+			return -EFAULT;
+		}
+		truesize = size * PAGE_SIZE;
+		skb->data_len += len;
+		skb->len += len;
+		skb->truesize += truesize;
+		atomic_add(truesize, &skb->sk->sk_wmem_alloc);
+		while (len) {
+			int off = base & ~PAGE_MASK;
+			int size = min_t(int, len, PAGE_SIZE - off);
+			skb_fill_page_desc(skb, i, page[i], off, size);
+			base += size;
+			len -= size;
+			i++;
+		}
+		offset = 0;
+		++from;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(zerocopy_sg_from_iovec);
+
 static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
 				      u8 __user *to, int len,
 				      __wsum *csump)
diff --git a/net/core/dev.c b/net/core/dev.c
index 26755dd..58eb802 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -174,7 +174,7 @@ static DEFINE_SPINLOCK(napi_hash_lock);
 static unsigned int napi_gen_id;
 static DEFINE_HASHTABLE(napi_hash, 8);
 
-seqcount_t devnet_rename_seq;
+static seqcount_t devnet_rename_seq;
 
 static inline void dev_base_seq_inc(struct net *net)
 {
@@ -4989,6 +4989,24 @@ int dev_change_carrier(struct net_device *dev, bool new_carrier)
 EXPORT_SYMBOL(dev_change_carrier);
 
 /**
+ *	dev_get_phys_port_id - Get device physical port ID
+ *	@dev: device
+ *	@ppid: port ID
+ *
+ *	Get device physical port ID
+ */
+int dev_get_phys_port_id(struct net_device *dev,
+			 struct netdev_phys_port_id *ppid)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if (!ops->ndo_get_phys_port_id)
+		return -EOPNOTSUPP;
+	return ops->ndo_get_phys_port_id(dev, ppid);
+}
+EXPORT_SYMBOL(dev_get_phys_port_id);
+
+/**
  *	dev_new_index	-	allocate an ifindex
  *	@net: the applicable net namespace
  *
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 2173544..2e65413 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -33,6 +33,9 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
 	r->flags = flags;
 	r->fr_net = hold_net(ops->fro_net);
 
+	r->suppress_prefixlen = -1;
+	r->suppress_ifgroup = -1;
+
 	/* The lock is not required here, the list in unreacheable
 	 * at the moment this function is called */
 	list_add_tail(&r->list, &ops->rules_list);
@@ -226,6 +229,9 @@ jumped:
 		else
 			err = ops->action(rule, fl, flags, arg);
 
+		if (!err && ops->suppress && ops->suppress(rule, arg))
+			continue;
+
 		if (err != -EAGAIN) {
 			if ((arg->flags & FIB_LOOKUP_NOREF) ||
 			    likely(atomic_inc_not_zero(&rule->refcnt))) {
@@ -337,6 +343,15 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 	rule->action = frh->action;
 	rule->flags = frh->flags;
 	rule->table = frh_get_table(frh, tb);
+	if (tb[FRA_SUPPRESS_PREFIXLEN])
+		rule->suppress_prefixlen = nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]);
+	else
+		rule->suppress_prefixlen = -1;
+
+	if (tb[FRA_SUPPRESS_IFGROUP])
+		rule->suppress_ifgroup = nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]);
+	else
+		rule->suppress_ifgroup = -1;
 
 	if (!tb[FRA_PRIORITY] && ops->default_pref)
 		rule->pref = ops->default_pref(ops);
@@ -523,6 +538,8 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
 			 + nla_total_size(IFNAMSIZ) /* FRA_OIFNAME */
 			 + nla_total_size(4) /* FRA_PRIORITY */
 			 + nla_total_size(4) /* FRA_TABLE */
+			 + nla_total_size(4) /* FRA_SUPPRESS_PREFIXLEN */
+			 + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
 			 + nla_total_size(4) /* FRA_FWMARK */
 			 + nla_total_size(4); /* FRA_FWMASK */
 
@@ -548,6 +565,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 	frh->table = rule->table;
 	if (nla_put_u32(skb, FRA_TABLE, rule->table))
 		goto nla_put_failure;
+	if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen))
+		goto nla_put_failure;
 	frh->res1 = 0;
 	frh->res2 = 0;
 	frh->action = rule->action;
@@ -580,6 +599,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 	    (rule->target &&
 	     nla_put_u32(skb, FRA_GOTO, rule->target)))
 		goto nla_put_failure;
+
+	if (rule->suppress_ifgroup != -1) {
+		if (nla_put_u32(skb, FRA_SUPPRESS_IFGROUP, rule->suppress_ifgroup))
+			goto nla_put_failure;
+	}
+
 	if (ops->fill(rule, skb, frh) < 0)
 		goto nla_put_failure;
 
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 00ee068..ade9ff1 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -139,7 +139,11 @@ ipv6:
 		break;
 	}
 	case IPPROTO_IPIP:
-		goto again;
+		proto = htons(ETH_P_IP);
+		goto ip;
+	case IPPROTO_IPV6:
+		proto = htons(ETH_P_IPV6);
+		goto ipv6;
 	default:
 		break;
 	}
diff --git a/net/core/iovec.c b/net/core/iovec.c
index de178e4..b77eeec 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -212,3 +212,27 @@ out_fault:
 	goto out;
 }
 EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
+
+unsigned long iov_pages(const struct iovec *iov, int offset,
+			unsigned long nr_segs)
+{
+	unsigned long seg, base;
+	int pages = 0, len, size;
+
+	while (nr_segs && (offset >= iov->iov_len)) {
+		offset -= iov->iov_len;
+		++iov;
+		--nr_segs;
+	}
+
+	for (seg = 0; seg < nr_segs; seg++) {
+		base = (unsigned long)iov[seg].iov_base + offset;
+		len = iov[seg].iov_len - offset;
+		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+		pages += size;
+		offset = 0;
+	}
+
+	return pages;
+}
+EXPORT_SYMBOL(iov_pages);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 9232c68..60533db 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1441,16 +1441,18 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 		atomic_set(&p->refcnt, 1);
 		p->reachable_time =
 				neigh_rand_reach_time(p->base_reachable_time);
+		dev_hold(dev);
+		p->dev = dev;
+		write_pnet(&p->net, hold_net(net));
+		p->sysctl_table = NULL;
 
 		if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
+			release_net(net);
+			dev_put(dev);
 			kfree(p);
 			return NULL;
 		}
 
-		dev_hold(dev);
-		p->dev = dev;
-		write_pnet(&p->net, hold_net(net));
-		p->sysctl_table = NULL;
 		write_lock_bh(&tbl->lock);
 		p->next		= tbl->parms.next;
 		tbl->parms.next = p;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 981fed3..d20d3bd 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -60,12 +60,19 @@ static ssize_t format_##field(const struct net_device *net, char *buf)	\
 {									\
 	return sprintf(buf, format_string, net->field);			\
 }									\
-static ssize_t show_##field(struct device *dev,				\
+static ssize_t field##_show(struct device *dev,				\
 			    struct device_attribute *attr, char *buf)	\
 {									\
 	return netdev_show(dev, attr, buf, format_##field);		\
-}
+}									\
+
+#define NETDEVICE_SHOW_RO(field, format_string)				\
+NETDEVICE_SHOW(field, format_string);					\
+static DEVICE_ATTR_RO(field)
 
+#define NETDEVICE_SHOW_RW(field, format_string)				\
+NETDEVICE_SHOW(field, format_string);					\
+static DEVICE_ATTR_RW(field)
 
 /* use same locking and permission rules as SIF* ioctl's */
 static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
@@ -96,16 +103,16 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
 	return ret;
 }
 
-NETDEVICE_SHOW(dev_id, fmt_hex);
-NETDEVICE_SHOW(addr_assign_type, fmt_dec);
-NETDEVICE_SHOW(addr_len, fmt_dec);
-NETDEVICE_SHOW(iflink, fmt_dec);
-NETDEVICE_SHOW(ifindex, fmt_dec);
-NETDEVICE_SHOW(type, fmt_dec);
-NETDEVICE_SHOW(link_mode, fmt_dec);
+NETDEVICE_SHOW_RO(dev_id, fmt_hex);
+NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
+NETDEVICE_SHOW_RO(addr_len, fmt_dec);
+NETDEVICE_SHOW_RO(iflink, fmt_dec);
+NETDEVICE_SHOW_RO(ifindex, fmt_dec);
+NETDEVICE_SHOW_RO(type, fmt_dec);
+NETDEVICE_SHOW_RO(link_mode, fmt_dec);
 
 /* use same locking rules as GIFHWADDR ioctl's */
-static ssize_t show_address(struct device *dev, struct device_attribute *attr,
+static ssize_t address_show(struct device *dev, struct device_attribute *attr,
 			    char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
@@ -117,15 +124,17 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr,
 	read_unlock(&dev_base_lock);
 	return ret;
 }
+static DEVICE_ATTR_RO(address);
 
-static ssize_t show_broadcast(struct device *dev,
-			    struct device_attribute *attr, char *buf)
+static ssize_t broadcast_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
 	if (dev_isalive(net))
 		return sysfs_format_mac(buf, net->broadcast, net->addr_len);
 	return -EINVAL;
 }
+static DEVICE_ATTR_RO(broadcast);
 
 static int change_carrier(struct net_device *net, unsigned long new_carrier)
 {
@@ -134,13 +143,13 @@ static int change_carrier(struct net_device *net, unsigned long new_carrier)
 	return dev_change_carrier(net, (bool) new_carrier);
 }
 
-static ssize_t store_carrier(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t len)
+static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_carrier);
 }
 
-static ssize_t show_carrier(struct device *dev,
+static ssize_t carrier_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -149,8 +158,9 @@ static ssize_t show_carrier(struct device *dev,
 	}
 	return -EINVAL;
 }
+static DEVICE_ATTR_RW(carrier);
 
-static ssize_t show_speed(struct device *dev,
+static ssize_t speed_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -167,8 +177,9 @@ static ssize_t show_speed(struct device *dev,
 	rtnl_unlock();
 	return ret;
 }
+static DEVICE_ATTR_RO(speed);
 
-static ssize_t show_duplex(struct device *dev,
+static ssize_t duplex_show(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -198,8 +209,9 @@ static ssize_t show_duplex(struct device *dev,
 	rtnl_unlock();
 	return ret;
 }
+static DEVICE_ATTR_RO(duplex);
 
-static ssize_t show_dormant(struct device *dev,
+static ssize_t dormant_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -209,6 +221,7 @@ static ssize_t show_dormant(struct device *dev,
 
 	return -EINVAL;
 }
+static DEVICE_ATTR_RO(dormant);
 
 static const char *const operstates[] = {
 	"unknown",
@@ -220,7 +233,7 @@ static const char *const operstates[] = {
 	"up"
 };
 
-static ssize_t show_operstate(struct device *dev,
+static ssize_t operstate_show(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
 	const struct net_device *netdev = to_net_dev(dev);
@@ -237,35 +250,55 @@ static ssize_t show_operstate(struct device *dev,
 
 	return sprintf(buf, "%s\n", operstates[operstate]);
 }
+static DEVICE_ATTR_RO(operstate);
+
+static ssize_t phys_port_id_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct net_device *netdev = to_net_dev(dev);
+	ssize_t ret = -EINVAL;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	if (dev_isalive(netdev)) {
+		struct netdev_phys_port_id ppid;
+
+		ret = dev_get_phys_port_id(netdev, &ppid);
+		if (!ret)
+			ret = sprintf(buf, "%*phN\n", ppid.id_len, ppid.id);
+	}
+	rtnl_unlock();
+
+	return ret;
+}
+static DEVICE_ATTR_RO(phys_port_id);
 
 /* read-write attributes */
-NETDEVICE_SHOW(mtu, fmt_dec);
 
 static int change_mtu(struct net_device *net, unsigned long new_mtu)
 {
 	return dev_set_mtu(net, (int) new_mtu);
 }
 
-static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
+static ssize_t mtu_store(struct device *dev, struct device_attribute *attr,
 			 const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_mtu);
 }
-
-NETDEVICE_SHOW(flags, fmt_hex);
+NETDEVICE_SHOW_RW(mtu, fmt_dec);
 
 static int change_flags(struct net_device *net, unsigned long new_flags)
 {
 	return dev_change_flags(net, (unsigned int) new_flags);
 }
 
-static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
+static ssize_t flags_store(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_flags);
 }
-
-NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
+NETDEVICE_SHOW_RW(flags, fmt_hex);
 
 static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
 {
@@ -273,7 +306,7 @@ static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
 	return 0;
 }
 
-static ssize_t store_tx_queue_len(struct device *dev,
+static ssize_t tx_queue_len_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t len)
 {
@@ -282,8 +315,9 @@ static ssize_t store_tx_queue_len(struct device *dev,
 
 	return netdev_store(dev, attr, buf, len, change_tx_queue_len);
 }
+NETDEVICE_SHOW_RW(tx_queue_len, fmt_ulong);
 
-static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
+static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t len)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -306,7 +340,7 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
 	return ret < 0 ? ret : len;
 }
 
-static ssize_t show_ifalias(struct device *dev,
+static ssize_t ifalias_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	const struct net_device *netdev = to_net_dev(dev);
@@ -319,8 +353,7 @@ static ssize_t show_ifalias(struct device *dev,
 	rtnl_unlock();
 	return ret;
 }
-
-NETDEVICE_SHOW(group, fmt_dec);
+static DEVICE_ATTR_RW(ifalias);
 
 static int change_group(struct net_device *net, unsigned long new_group)
 {
@@ -328,35 +361,38 @@ static int change_group(struct net_device *net, unsigned long new_group)
 	return 0;
 }
 
-static ssize_t store_group(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t len)
+static ssize_t group_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_group);
 }
-
-static struct device_attribute net_class_attributes[] = {
-	__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL),
-	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
-	__ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
-	__ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias),
-	__ATTR(iflink, S_IRUGO, show_iflink, NULL),
-	__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
-	__ATTR(type, S_IRUGO, show_type, NULL),
-	__ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
-	__ATTR(address, S_IRUGO, show_address, NULL),
-	__ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
-	__ATTR(carrier, S_IRUGO | S_IWUSR, show_carrier, store_carrier),
-	__ATTR(speed, S_IRUGO, show_speed, NULL),
-	__ATTR(duplex, S_IRUGO, show_duplex, NULL),
-	__ATTR(dormant, S_IRUGO, show_dormant, NULL),
-	__ATTR(operstate, S_IRUGO, show_operstate, NULL),
-	__ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
-	__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
-	__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
-	       store_tx_queue_len),
-	__ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group),
-	{}
+NETDEVICE_SHOW(group, fmt_dec);
+static DEVICE_ATTR(netdev_group, S_IRUGO | S_IWUSR, group_show, group_store);
+
+static struct attribute *net_class_attrs[] = {
+	&dev_attr_netdev_group.attr,
+	&dev_attr_type.attr,
+	&dev_attr_dev_id.attr,
+	&dev_attr_iflink.attr,
+	&dev_attr_ifindex.attr,
+	&dev_attr_addr_assign_type.attr,
+	&dev_attr_addr_len.attr,
+	&dev_attr_link_mode.attr,
+	&dev_attr_address.attr,
+	&dev_attr_broadcast.attr,
+	&dev_attr_speed.attr,
+	&dev_attr_duplex.attr,
+	&dev_attr_dormant.attr,
+	&dev_attr_operstate.attr,
+	&dev_attr_phys_port_id.attr,
+	&dev_attr_ifalias.attr,
+	&dev_attr_carrier.attr,
+	&dev_attr_mtu.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_tx_queue_len.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(net_class);
 
 /* Show a given an attribute in the statistics group */
 static ssize_t netstat_show(const struct device *d,
@@ -382,13 +418,13 @@ static ssize_t netstat_show(const struct device *d,
 
 /* generate a read-only statistics attribute */
 #define NETSTAT_ENTRY(name)						\
-static ssize_t show_##name(struct device *d,				\
+static ssize_t name##_show(struct device *d,				\
 			   struct device_attribute *attr, char *buf) 	\
 {									\
 	return netstat_show(d, attr, buf,				\
 			    offsetof(struct rtnl_link_stats64, name));	\
 }									\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR_RO(name)
 
 NETSTAT_ENTRY(rx_packets);
 NETSTAT_ENTRY(tx_packets);
@@ -457,6 +493,9 @@ static struct attribute_group wireless_group = {
 	.attrs = wireless_attrs,
 };
 #endif
+
+#else /* CONFIG_SYSFS */
+#define net_class_groups	NULL
 #endif /* CONFIG_SYSFS */
 
 #ifdef CONFIG_RPS
@@ -1229,9 +1268,7 @@ static const void *net_namespace(struct device *d)
 static struct class net_class = {
 	.name = "net",
 	.dev_release = netdev_release,
-#ifdef CONFIG_SYSFS
-	.dev_attrs = net_class_attributes,
-#endif /* CONFIG_SYSFS */
+	.dev_groups = net_class_groups,
 	.dev_uevent = netdev_uevent,
 	.ns_type = &net_ns_type_operations,
 	.namespace = net_namespace,
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 9640972..261357a 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -160,6 +160,8 @@
 #include <net/net_namespace.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
+#include <net/udp.h>
+#include <net/ip6_checksum.h>
 #include <net/addrconf.h>
 #ifdef CONFIG_XFRM
 #include <net/xfrm.h>
@@ -198,6 +200,7 @@
 #define F_QUEUE_MAP_RND (1<<13)	/* queue map Random */
 #define F_QUEUE_MAP_CPU (1<<14)	/* queue map mirrors smp_processor_id() */
 #define F_NODE          (1<<15)	/* Node memory alloc*/
+#define F_UDPCSUM       (1<<16)	/* Include UDP checksum */
 
 /* Thread control flag bits */
 #define T_STOP        (1<<0)	/* Stop run */
@@ -631,6 +634,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
 	if (pkt_dev->flags & F_UDPDST_RND)
 		seq_printf(seq, "UDPDST_RND  ");
 
+	if (pkt_dev->flags & F_UDPCSUM)
+		seq_printf(seq, "UDPCSUM  ");
+
 	if (pkt_dev->flags & F_MPLS_RND)
 		seq_printf(seq,  "MPLS_RND  ");
 
@@ -1228,6 +1234,12 @@ static ssize_t pktgen_if_write(struct file *file,
 		else if (strcmp(f, "!NODE_ALLOC") == 0)
 			pkt_dev->flags &= ~F_NODE;
 
+		else if (strcmp(f, "UDPCSUM") == 0)
+			pkt_dev->flags |= F_UDPCSUM;
+
+		else if (strcmp(f, "!UDPCSUM") == 0)
+			pkt_dev->flags &= ~F_UDPCSUM;
+
 		else {
 			sprintf(pg_result,
 				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
@@ -2733,7 +2745,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 	udph->source = htons(pkt_dev->cur_udp_src);
 	udph->dest = htons(pkt_dev->cur_udp_dst);
 	udph->len = htons(datalen + 8);	/* DATA + udphdr */
-	udph->check = 0;	/* No checksum */
+	udph->check = 0;
 
 	iph->ihl = 5;
 	iph->version = 4;
@@ -2747,11 +2759,28 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 	iph->frag_off = 0;
 	iplen = 20 + 8 + datalen;
 	iph->tot_len = htons(iplen);
-	iph->check = 0;
-	iph->check = ip_fast_csum((void *)iph, iph->ihl);
+	ip_send_check(iph);
 	skb->protocol = protocol;
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
+
+	if (!(pkt_dev->flags & F_UDPCSUM)) {
+		skb->ip_summed = CHECKSUM_NONE;
+	} else if (odev->features & NETIF_F_V4_CSUM) {
+		skb->ip_summed = CHECKSUM_PARTIAL;
+		skb->csum = 0;
+		udp4_hwcsum(skb, udph->source, udph->dest);
+	} else {
+		__wsum csum = udp_csum(skb);
+
+		/* add protocol-dependent pseudo-header */
+		udph->check = csum_tcpudp_magic(udph->source, udph->dest,
+						datalen + 8, IPPROTO_UDP, csum);
+
+		if (udph->check == 0)
+			udph->check = CSUM_MANGLED_0;
+	}
+
 	pktgen_finalize_skb(pkt_dev, skb, datalen);
 
 #ifdef CONFIG_XFRM
@@ -2768,7 +2797,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 	struct sk_buff *skb = NULL;
 	__u8 *eth;
 	struct udphdr *udph;
-	int datalen;
+	int datalen, udplen;
 	struct ipv6hdr *iph;
 	__be16 protocol = htons(ETH_P_IPV6);
 	__be32 *mpls;
@@ -2844,10 +2873,11 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 		net_info_ratelimited("increased datalen to %d\n", datalen);
 	}
 
+	udplen = datalen + sizeof(struct udphdr);
 	udph->source = htons(pkt_dev->cur_udp_src);
 	udph->dest = htons(pkt_dev->cur_udp_dst);
-	udph->len = htons(datalen + sizeof(struct udphdr));
-	udph->check = 0;	/* No checksum */
+	udph->len = htons(udplen);
+	udph->check = 0;
 
 	*(__be32 *) iph = htonl(0x60000000);	/* Version + flow */
 
@@ -2858,7 +2888,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 
 	iph->hop_limit = 32;
 
-	iph->payload_len = htons(sizeof(struct udphdr) + datalen);
+	iph->payload_len = htons(udplen);
 	iph->nexthdr = IPPROTO_UDP;
 
 	iph->daddr = pkt_dev->cur_in6_daddr;
@@ -2868,6 +2898,23 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
 
+	if (!(pkt_dev->flags & F_UDPCSUM)) {
+		skb->ip_summed = CHECKSUM_NONE;
+	} else if (odev->features & NETIF_F_V6_CSUM) {
+		skb->ip_summed = CHECKSUM_PARTIAL;
+		skb->csum_start = skb_transport_header(skb) - skb->head;
+		skb->csum_offset = offsetof(struct udphdr, check);
+		udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0);
+	} else {
+		__wsum csum = udp_csum(skb);
+
+		/* add protocol-dependent pseudo-header */
+		udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum);
+
+		if (udph->check == 0)
+			udph->check = CSUM_MANGLED_0;
+	}
+
 	pktgen_finalize_skb(pkt_dev, skb, datalen);
 
 	return skb;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 3de7408..0b2972c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -767,7 +767,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
 	       + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
 	       + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
 	       + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
-	       + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
+	       + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
+	       + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */
 }
 
 static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
@@ -846,6 +847,24 @@ static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
+static int rtnl_phys_port_id_fill(struct sk_buff *skb, struct net_device *dev)
+{
+	int err;
+	struct netdev_phys_port_id ppid;
+
+	err = dev_get_phys_port_id(dev, &ppid);
+	if (err) {
+		if (err == -EOPNOTSUPP)
+			return 0;
+		return err;
+	}
+
+	if (nla_put(skb, IFLA_PHYS_PORT_ID, ppid.id_len, ppid.id))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 			    int type, u32 pid, u32 seq, u32 change,
 			    unsigned int flags, u32 ext_filter_mask)
@@ -913,6 +932,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 			goto nla_put_failure;
 	}
 
+	if (rtnl_phys_port_id_fill(skb, dev))
+		goto nla_put_failure;
+
 	attr = nla_reserve(skb, IFLA_STATS,
 			sizeof(struct rtnl_link_stats));
 	if (attr == NULL)
@@ -1113,6 +1135,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_PROMISCUITY]	= { .type = NLA_U32 },
 	[IFLA_NUM_TX_QUEUES]	= { .type = NLA_U32 },
 	[IFLA_NUM_RX_QUEUES]	= { .type = NLA_U32 },
+	[IFLA_PHYS_PORT_ID]	= { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
 };
 EXPORT_SYMBOL(ifla_policy);
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 2c097c5..83667de 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -93,6 +93,7 @@
 
 #include <linux/capability.h>
 #include <linux/errno.h>
+#include <linux/errqueue.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/in.h>
@@ -1575,6 +1576,25 @@ void sock_wfree(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(sock_wfree);
 
+void skb_orphan_partial(struct sk_buff *skb)
+{
+	/* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
+	 * so we do not completely orphan skb, but transfert all
+	 * accounted bytes but one, to avoid unexpected reorders.
+	 */
+	if (skb->destructor == sock_wfree
+#ifdef CONFIG_INET
+	    || skb->destructor == tcp_wfree
+#endif
+		) {
+		atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
+		skb->truesize = 1;
+	} else {
+		skb_orphan(skb);
+	}
+}
+EXPORT_SYMBOL(skb_orphan_partial);
+
 /*
  * Read buffer destructor automatically called from kfree_skb.
  */
@@ -2425,6 +2445,52 @@ void sock_enable_timestamp(struct sock *sk, int flag)
 	}
 }
 
+int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
+		       int level, int type)
+{
+	struct sock_exterr_skb *serr;
+	struct sk_buff *skb, *skb2;
+	int copied, err;
+
+	err = -EAGAIN;
+	skb = skb_dequeue(&sk->sk_error_queue);
+	if (skb == NULL)
+		goto out;
+
+	copied = skb->len;
+	if (copied > len) {
+		msg->msg_flags |= MSG_TRUNC;
+		copied = len;
+	}
+	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	if (err)
+		goto out_free_skb;
+
+	sock_recv_timestamp(msg, sk, skb);
+
+	serr = SKB_EXT_ERR(skb);
+	put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
+
+	msg->msg_flags |= MSG_ERRQUEUE;
+	err = copied;
+
+	/* Reset and regenerate socket error */
+	spin_lock_bh(&sk->sk_error_queue.lock);
+	sk->sk_err = 0;
+	if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
+		sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
+		spin_unlock_bh(&sk->sk_error_queue.lock);
+		sk->sk_error_report(sk);
+	} else
+		spin_unlock_bh(&sk->sk_error_queue.lock);
+
+out_free_skb:
+	kfree_skb(skb);
+out:
+	return err;
+}
+EXPORT_SYMBOL(sock_recv_errqueue);
+
 /*
  *	Get a socket option on an socket.
  *
diff --git a/net/core/stream.c b/net/core/stream.c
index f5df85d..512f0a2 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -30,7 +30,7 @@ void sk_stream_write_space(struct sock *sk)
 	struct socket *sock = sk->sk_socket;
 	struct socket_wq *wq;
 
-	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) {
+	if (sk_stream_is_writeable(sk) && sock) {
 		clear_bit(SOCK_NOSPACE, &sock->flags);
 
 		rcu_read_lock();
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 6c7c78b..ba64750 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -336,7 +336,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock,
 			mask |= POLLIN | POLLRDNORM;
 
 		if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
-			if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+			if (sk_stream_is_writeable(sk)) {
 				mask |= POLLOUT | POLLWRNORM;
 			} else {  /* send SIGIO later */
 				set_bit(SOCK_ASYNC_NOSPACE,
@@ -347,7 +347,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock,
 				 * wspace test but before the flags are set,
 				 * IO signal will be lost.
 				 */
-				if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
+				if (sk_stream_is_writeable(sk))
 					mask |= POLLOUT | POLLWRNORM;
 			}
 		}
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index 13571ea..ef56ab5 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -36,7 +36,8 @@ static ssize_t name ## _show(struct device *dev,			\
 	ret = snprintf(buf, PAGE_SIZE, format_string "\n", args);	\
 	mutex_unlock(&phy->pib_lock);					\
 	return ret;							\
-}
+}									\
+static DEVICE_ATTR_RO(name);
 
 #define MASTER_SHOW(field, format_string)				\
 	MASTER_SHOW_COMPLEX(field, format_string, phy->field)
@@ -66,15 +67,17 @@ static ssize_t channels_supported_show(struct device *dev,
 	mutex_unlock(&phy->pib_lock);
 	return len;
 }
-
-static struct device_attribute pmib_attrs[] = {
-	__ATTR_RO(current_channel),
-	__ATTR_RO(current_page),
-	__ATTR_RO(channels_supported),
-	__ATTR_RO(transmit_power),
-	__ATTR_RO(cca_mode),
-	{},
+static DEVICE_ATTR_RO(channels_supported);
+
+static struct attribute *pmib_attrs[] = {
+	&dev_attr_current_channel.attr,
+	&dev_attr_current_page.attr,
+	&dev_attr_channels_supported.attr,
+	&dev_attr_transmit_power.attr,
+	&dev_attr_cca_mode.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(pmib);
 
 static void wpan_phy_release(struct device *d)
 {
@@ -85,7 +88,7 @@ static void wpan_phy_release(struct device *d)
 static struct class wpan_phy_class = {
 	.name = "ieee802154",
 	.dev_release = wpan_phy_release,
-	.dev_attrs = pmib_attrs,
+	.dev_groups = pmib_groups,
 };
 
 static DEFINE_MUTEX(wpan_phy_mutex);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 34ca6d5..43923dc 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1126,10 +1126,7 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
 		if (len < (int) sizeof(ifr))
 			break;
 		memset(&ifr, 0, sizeof(struct ifreq));
-		if (ifa->ifa_label)
-			strcpy(ifr.ifr_name, ifa->ifa_label);
-		else
-			strcpy(ifr.ifr_name, dev->name);
+		strcpy(ifr.ifr_name, ifa->ifa_label);
 
 		(*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET;
 		(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index ab3d814..109ee89 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -477,7 +477,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
 	}
 
 	return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
-		 net_adj) & ~(align - 1)) + (net_adj - 2);
+		 net_adj) & ~(align - 1)) + net_adj - 2;
 }
 
 static void esp4_err(struct sk_buff *skb, u32 info)
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 26aa65d..523be38 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -101,6 +101,30 @@ errout:
 	return err;
 }
 
+static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
+{
+	struct fib_result *result = (struct fib_result *) arg->result;
+	struct net_device *dev = result->fi->fib_dev;
+
+	/* do not accept result if the route does
+	 * not meet the required prefix length
+	 */
+	if (result->prefixlen <= rule->suppress_prefixlen)
+		goto suppress_route;
+
+	/* do not accept result if the route uses a device
+	 * belonging to a forbidden interface group
+	 */
+	if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
+		goto suppress_route;
+
+	return false;
+
+suppress_route:
+	if (!(arg->flags & FIB_LOOKUP_NOREF))
+		fib_info_put(result->fi);
+	return true;
+}
 
 static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
@@ -267,6 +291,7 @@ static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
 	.rule_size	= sizeof(struct fib4_rule),
 	.addr_size	= sizeof(u32),
 	.action		= fib4_rule_action,
+	.suppress	= fib4_rule_suppress,
 	.match		= fib4_rule_match,
 	.configure	= fib4_rule_configure,
 	.delete		= fib4_rule_delete,
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 108a1e9c..3df6d3e 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -71,7 +71,6 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/prefetch.h>
 #include <linux/export.h>
 #include <net/net_namespace.h>
 #include <net/ip.h>
@@ -1761,10 +1760,8 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
 			if (!c)
 				continue;
 
-			if (IS_LEAF(c)) {
-				prefetch(rcu_dereference_rtnl(p->child[idx]));
+			if (IS_LEAF(c))
 				return (struct leaf *) c;
-			}
 
 			/* Rescan start scanning in new node */
 			p = (struct tnode *) c;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index cd71190..ef76186 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -88,6 +88,7 @@
 #include <linux/if_arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/times.h>
+#include <linux/pkt_sched.h>
 
 #include <net/net_namespace.h>
 #include <net/arp.h>
@@ -315,6 +316,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
 		if (size < 256)
 			return NULL;
 	}
+	skb->priority = TC_PRIO_CONTROL;
 	igmp_skb_size(skb) = size;
 
 	rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0,
@@ -670,6 +672,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
 		ip_rt_put(rt);
 		return -1;
 	}
+	skb->priority = TC_PRIO_CONTROL;
 
 	skb_dst_set(skb, &rt->dst);
 
@@ -1323,16 +1326,17 @@ out:
 EXPORT_SYMBOL(ip_mc_inc_group);
 
 /*
- *	Resend IGMP JOIN report; used for bonding.
- *	Called with rcu_read_lock()
+ *	Resend IGMP JOIN report; used by netdev notifier.
  */
-void ip_mc_rejoin_groups(struct in_device *in_dev)
+static void ip_mc_rejoin_groups(struct in_device *in_dev)
 {
 #ifdef CONFIG_IP_MULTICAST
 	struct ip_mc_list *im;
 	int type;
 
-	for_each_pmc_rcu(in_dev, im) {
+	ASSERT_RTNL();
+
+	for_each_pmc_rtnl(in_dev, im) {
 		if (im->multiaddr == IGMP_ALL_HOSTS)
 			continue;
 
@@ -1349,7 +1353,6 @@ void ip_mc_rejoin_groups(struct in_device *in_dev)
 	}
 #endif
 }
-EXPORT_SYMBOL(ip_mc_rejoin_groups);
 
 /*
  *	A socket has left a multicast group on device dev
@@ -2735,8 +2738,42 @@ static struct pernet_operations igmp_net_ops = {
 	.exit = igmp_net_exit,
 };
 
+static int igmp_netdev_event(struct notifier_block *this,
+			     unsigned long event, void *ptr)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct in_device *in_dev;
+
+	switch (event) {
+	case NETDEV_RESEND_IGMP:
+		in_dev = __in_dev_get_rtnl(dev);
+		if (in_dev)
+			ip_mc_rejoin_groups(in_dev);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block igmp_notifier = {
+	.notifier_call = igmp_netdev_event,
+};
+
 int __init igmp_mc_proc_init(void)
 {
-	return register_pernet_subsys(&igmp_net_ops);
+	int err;
+
+	err = register_pernet_subsys(&igmp_net_ops);
+	if (err)
+		return err;
+	err = register_netdevice_notifier(&igmp_notifier);
+	if (err)
+		goto reg_notif_fail;
+	return 0;
+
+reg_notif_fail:
+	unregister_pernet_subsys(&igmp_net_ops);
+	return err;
 }
 #endif
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index ca1cb2d..9fdf8a6 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -838,15 +838,16 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
 {
 	struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
 	struct ip_tunnel_parm parms;
+	unsigned int i;
 
-	itn->tunnels = kzalloc(IP_TNL_HASH_SIZE * sizeof(struct hlist_head), GFP_KERNEL);
-	if (!itn->tunnels)
-		return -ENOMEM;
+	for (i = 0; i < IP_TNL_HASH_SIZE; i++)
+		INIT_HLIST_HEAD(&itn->tunnels[i]);
 
 	if (!ops) {
 		itn->fb_tunnel_dev = NULL;
 		return 0;
 	}
+
 	memset(&parms, 0, sizeof(parms));
 	if (devname)
 		strlcpy(parms.name, devname, IFNAMSIZ);
@@ -854,10 +855,9 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
 	rtnl_lock();
 	itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
 	rtnl_unlock();
-	if (IS_ERR(itn->fb_tunnel_dev)) {
-		kfree(itn->tunnels);
+
+	if (IS_ERR(itn->fb_tunnel_dev))
 		return PTR_ERR(itn->fb_tunnel_dev);
-	}
 
 	return 0;
 }
@@ -887,7 +887,6 @@ void ip_tunnel_delete_net(struct ip_tunnel_net *itn)
 	ip_tunnel_destroy(itn, &list);
 	unregister_netdevice_many(&list);
 	rtnl_unlock();
-	kfree(itn->tunnels);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_delete_net);
 
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 17cc0ff..79b263d 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -44,176 +44,10 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
-#define HASH_SIZE  16
-#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&(HASH_SIZE-1))
-
 static struct rtnl_link_ops vti_link_ops __read_mostly;
 
 static int vti_net_id __read_mostly;
-struct vti_net {
-	struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE];
-	struct ip_tunnel __rcu *tunnels_r[HASH_SIZE];
-	struct ip_tunnel __rcu *tunnels_l[HASH_SIZE];
-	struct ip_tunnel __rcu *tunnels_wc[1];
-	struct ip_tunnel __rcu **tunnels[4];
-
-	struct net_device *fb_tunnel_dev;
-};
-
-static int vti_fb_tunnel_init(struct net_device *dev);
 static int vti_tunnel_init(struct net_device *dev);
-static void vti_tunnel_setup(struct net_device *dev);
-static void vti_dev_free(struct net_device *dev);
-static int vti_tunnel_bind_dev(struct net_device *dev);
-
-#define VTI_XMIT(stats1, stats2) do {				\
-	int err;						\
-	int pkt_len = skb->len;					\
-	err = dst_output(skb);					\
-	if (net_xmit_eval(err) == 0) {				\
-		u64_stats_update_begin(&(stats1)->syncp);	\
-		(stats1)->tx_bytes += pkt_len;			\
-		(stats1)->tx_packets++;				\
-		u64_stats_update_end(&(stats1)->syncp);		\
-	} else {						\
-		(stats2)->tx_errors++;				\
-		(stats2)->tx_aborted_errors++;			\
-	}							\
-} while (0)
-
-
-static struct ip_tunnel *vti_tunnel_lookup(struct net *net,
-					   __be32 remote, __be32 local)
-{
-	unsigned h0 = HASH(remote);
-	unsigned h1 = HASH(local);
-	struct ip_tunnel *t;
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_r_l[h0 ^ h1])
-		if (local == t->parms.iph.saddr &&
-		    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
-			return t;
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_r[h0])
-		if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
-			return t;
-
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_l[h1])
-		if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
-			return t;
-
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_wc[0])
-		if (t && (t->dev->flags&IFF_UP))
-			return t;
-	return NULL;
-}
-
-static struct ip_tunnel __rcu **__vti_bucket(struct vti_net *ipn,
-					     struct ip_tunnel_parm *parms)
-{
-	__be32 remote = parms->iph.daddr;
-	__be32 local = parms->iph.saddr;
-	unsigned h = 0;
-	int prio = 0;
-
-	if (remote) {
-		prio |= 2;
-		h ^= HASH(remote);
-	}
-	if (local) {
-		prio |= 1;
-		h ^= HASH(local);
-	}
-	return &ipn->tunnels[prio][h];
-}
-
-static inline struct ip_tunnel __rcu **vti_bucket(struct vti_net *ipn,
-						  struct ip_tunnel *t)
-{
-	return __vti_bucket(ipn, &t->parms);
-}
-
-static void vti_tunnel_unlink(struct vti_net *ipn, struct ip_tunnel *t)
-{
-	struct ip_tunnel __rcu **tp;
-	struct ip_tunnel *iter;
-
-	for (tp = vti_bucket(ipn, t);
-	     (iter = rtnl_dereference(*tp)) != NULL;
-	     tp = &iter->next) {
-		if (t == iter) {
-			rcu_assign_pointer(*tp, t->next);
-			break;
-		}
-	}
-}
-
-static void vti_tunnel_link(struct vti_net *ipn, struct ip_tunnel *t)
-{
-	struct ip_tunnel __rcu **tp = vti_bucket(ipn, t);
-
-	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
-	rcu_assign_pointer(*tp, t);
-}
-
-static struct ip_tunnel *vti_tunnel_locate(struct net *net,
-					   struct ip_tunnel_parm *parms,
-					   int create)
-{
-	__be32 remote = parms->iph.daddr;
-	__be32 local = parms->iph.saddr;
-	struct ip_tunnel *t, *nt;
-	struct ip_tunnel __rcu **tp;
-	struct net_device *dev;
-	char name[IFNAMSIZ];
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-
-	for (tp = __vti_bucket(ipn, parms);
-	     (t = rtnl_dereference(*tp)) != NULL;
-	     tp = &t->next) {
-		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
-			return t;
-	}
-	if (!create)
-		return NULL;
-
-	if (parms->name[0])
-		strlcpy(name, parms->name, IFNAMSIZ);
-	else
-		strcpy(name, "vti%d");
-
-	dev = alloc_netdev(sizeof(*t), name, vti_tunnel_setup);
-	if (dev == NULL)
-		return NULL;
-
-	dev_net_set(dev, net);
-
-	nt = netdev_priv(dev);
-	nt->parms = *parms;
-	dev->rtnl_link_ops = &vti_link_ops;
-
-	vti_tunnel_bind_dev(dev);
-
-	if (register_netdevice(dev) < 0)
-		goto failed_free;
-
-	dev_hold(dev);
-	vti_tunnel_link(ipn, nt);
-	return nt;
-
-failed_free:
-	free_netdev(dev);
-	return NULL;
-}
-
-static void vti_tunnel_uninit(struct net_device *dev)
-{
-	struct net *net = dev_net(dev);
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-
-	vti_tunnel_unlink(ipn, netdev_priv(dev));
-	dev_put(dev);
-}
 
 static int vti_err(struct sk_buff *skb, u32 info)
 {
@@ -222,6 +56,8 @@ static int vti_err(struct sk_buff *skb, u32 info)
 	 * 8 bytes of packet payload. It means, that precise relaying of
 	 * ICMP in the real Internet is absolutely infeasible.
 	 */
+	struct net *net = dev_net(skb->dev);
+	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
 	struct iphdr *iph = (struct iphdr *)skb->data;
 	const int type = icmp_hdr(skb)->type;
 	const int code = icmp_hdr(skb)->code;
@@ -252,7 +88,8 @@ static int vti_err(struct sk_buff *skb, u32 info)
 
 	err = -ENOENT;
 
-	t = vti_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
+	t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+			     iph->daddr, iph->saddr, 0);
 	if (t == NULL)
 		goto out;
 
@@ -281,8 +118,11 @@ static int vti_rcv(struct sk_buff *skb)
 {
 	struct ip_tunnel *tunnel;
 	const struct iphdr *iph = ip_hdr(skb);
+	struct net *net = dev_net(skb->dev);
+	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
 
-	tunnel = vti_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr);
+	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+				  iph->saddr, iph->daddr, 0);
 	if (tunnel != NULL) {
 		struct pcpu_tstats *tstats;
 
@@ -311,7 +151,6 @@ static int vti_rcv(struct sk_buff *skb)
 static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct pcpu_tstats *tstats;
 	struct iphdr  *tiph = &tunnel->parms.iph;
 	u8     tos;
 	struct rtable *rt;		/* Route to the other host */
@@ -319,6 +158,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct iphdr  *old_iph = ip_hdr(skb);
 	__be32 dst = tiph->daddr;
 	struct flowi4 fl4;
+	int err;
 
 	if (skb->protocol != htons(ETH_P_IP))
 		goto tx_error;
@@ -367,8 +207,10 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	nf_reset(skb);
 	skb->dev = skb_dst(skb)->dev;
 
-	tstats = this_cpu_ptr(dev->tstats);
-	VTI_XMIT(tstats, &dev->stats);
+	err = dst_output(skb);
+	if (net_xmit_eval(err) == 0)
+		err = skb->len;
+	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
 	return NETDEV_TX_OK;
 
 tx_error_icmp:
@@ -379,198 +221,57 @@ tx_error:
 	return NETDEV_TX_OK;
 }
 
-static int vti_tunnel_bind_dev(struct net_device *dev)
-{
-	struct net_device *tdev = NULL;
-	struct ip_tunnel *tunnel;
-	struct iphdr *iph;
-
-	tunnel = netdev_priv(dev);
-	iph = &tunnel->parms.iph;
-
-	if (iph->daddr) {
-		struct rtable *rt;
-		struct flowi4 fl4;
-		memset(&fl4, 0, sizeof(fl4));
-		flowi4_init_output(&fl4, tunnel->parms.link,
-				   be32_to_cpu(tunnel->parms.i_key),
-				   RT_TOS(iph->tos), RT_SCOPE_UNIVERSE,
-				   IPPROTO_IPIP, 0,
-				   iph->daddr, iph->saddr, 0, 0);
-		rt = ip_route_output_key(dev_net(dev), &fl4);
-		if (!IS_ERR(rt)) {
-			tdev = rt->dst.dev;
-			ip_rt_put(rt);
-		}
-		dev->flags |= IFF_POINTOPOINT;
-	}
-
-	if (!tdev && tunnel->parms.link)
-		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
-
-	if (tdev) {
-		dev->hard_header_len = tdev->hard_header_len +
-				       sizeof(struct iphdr);
-		dev->mtu = tdev->mtu;
-	}
-	dev->iflink = tunnel->parms.link;
-	return dev->mtu;
-}
-
 static int
 vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int err = 0;
 	struct ip_tunnel_parm p;
-	struct ip_tunnel *t;
-	struct net *net = dev_net(dev);
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-
-	switch (cmd) {
-	case SIOCGETTUNNEL:
-		t = NULL;
-		if (dev == ipn->fb_tunnel_dev) {
-			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data,
-					   sizeof(p))) {
-				err = -EFAULT;
-				break;
-			}
-			t = vti_tunnel_locate(net, &p, 0);
-		}
-		if (t == NULL)
-			t = netdev_priv(dev);
-		memcpy(&p, &t->parms, sizeof(p));
-		p.i_flags |= GRE_KEY | VTI_ISVTI;
-		p.o_flags |= GRE_KEY;
-		if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
-			err = -EFAULT;
-		break;
-
-	case SIOCADDTUNNEL:
-	case SIOCCHGTUNNEL:
-		err = -EPERM;
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-			goto done;
 
-		err = -EFAULT;
-		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
-			goto done;
+	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+		return -EFAULT;
 
-		err = -EINVAL;
+	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
 		    p.iph.ihl != 5)
-			goto done;
-
-		t = vti_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
-
-		if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
-			if (t != NULL) {
-				if (t->dev != dev) {
-					err = -EEXIST;
-					break;
-				}
-			} else {
-				if (((dev->flags&IFF_POINTOPOINT) &&
-				    !p.iph.daddr) ||
-				    (!(dev->flags&IFF_POINTOPOINT) &&
-				    p.iph.daddr)) {
-					err = -EINVAL;
-					break;
-				}
-				t = netdev_priv(dev);
-				vti_tunnel_unlink(ipn, t);
-				synchronize_net();
-				t->parms.iph.saddr = p.iph.saddr;
-				t->parms.iph.daddr = p.iph.daddr;
-				t->parms.i_key = p.i_key;
-				t->parms.o_key = p.o_key;
-				t->parms.iph.protocol = IPPROTO_IPIP;
-				memcpy(dev->dev_addr, &p.iph.saddr, 4);
-				memcpy(dev->broadcast, &p.iph.daddr, 4);
-				vti_tunnel_link(ipn, t);
-				netdev_state_change(dev);
-			}
-		}
-
-		if (t) {
-			err = 0;
-			if (cmd == SIOCCHGTUNNEL) {
-				t->parms.i_key = p.i_key;
-				t->parms.o_key = p.o_key;
-				if (t->parms.link != p.link) {
-					t->parms.link = p.link;
-					vti_tunnel_bind_dev(dev);
-					netdev_state_change(dev);
-				}
-			}
-			p.i_flags |= GRE_KEY | VTI_ISVTI;
-			p.o_flags |= GRE_KEY;
-			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms,
-					 sizeof(p)))
-				err = -EFAULT;
-		} else
-			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
-		break;
+			return -EINVAL;
+	}
 
-	case SIOCDELTUNNEL:
-		err = -EPERM;
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-			goto done;
-
-		if (dev == ipn->fb_tunnel_dev) {
-			err = -EFAULT;
-			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data,
-					   sizeof(p)))
-				goto done;
-			err = -ENOENT;
-
-			t = vti_tunnel_locate(net, &p, 0);
-			if (t == NULL)
-				goto done;
-			err = -EPERM;
-			if (t->dev == ipn->fb_tunnel_dev)
-				goto done;
-			dev = t->dev;
-		}
-		unregister_netdevice(dev);
-		err = 0;
-		break;
+	err = ip_tunnel_ioctl(dev, &p, cmd);
+	if (err)
+		return err;
 
-	default:
-		err = -EINVAL;
+	if (cmd != SIOCDELTUNNEL) {
+		p.i_flags |= GRE_KEY | VTI_ISVTI;
+		p.o_flags |= GRE_KEY;
 	}
 
-done:
-	return err;
-}
-
-static int vti_tunnel_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if (new_mtu < 68 || new_mtu > 0xFFF8)
-		return -EINVAL;
-	dev->mtu = new_mtu;
+	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
+		return -EFAULT;
 	return 0;
 }
 
 static const struct net_device_ops vti_netdev_ops = {
 	.ndo_init	= vti_tunnel_init,
-	.ndo_uninit	= vti_tunnel_uninit,
+	.ndo_uninit	= ip_tunnel_uninit,
 	.ndo_start_xmit	= vti_tunnel_xmit,
 	.ndo_do_ioctl	= vti_tunnel_ioctl,
-	.ndo_change_mtu	= vti_tunnel_change_mtu,
+	.ndo_change_mtu	= ip_tunnel_change_mtu,
 	.ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
-static void vti_dev_free(struct net_device *dev)
+static void vti_tunnel_setup(struct net_device *dev)
 {
-	free_percpu(dev->tstats);
-	free_netdev(dev);
+	dev->netdev_ops		= &vti_netdev_ops;
+	ip_tunnel_setup(dev, vti_net_id);
 }
 
-static void vti_tunnel_setup(struct net_device *dev)
+static int vti_tunnel_init(struct net_device *dev)
 {
-	dev->netdev_ops		= &vti_netdev_ops;
-	dev->destructor		= vti_dev_free;
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct iphdr *iph = &tunnel->parms.iph;
+
+	memcpy(dev->dev_addr, &iph->saddr, 4);
+	memcpy(dev->broadcast, &iph->daddr, 4);
 
 	dev->type		= ARPHRD_TUNNEL;
 	dev->hard_header_len	= LL_MAX_HEADER + sizeof(struct iphdr);
@@ -581,38 +282,18 @@ static void vti_tunnel_setup(struct net_device *dev)
 	dev->features		|= NETIF_F_NETNS_LOCAL;
 	dev->features		|= NETIF_F_LLTX;
 	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
-}
 
-static int vti_tunnel_init(struct net_device *dev)
-{
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-
-	tunnel->dev = dev;
-	strcpy(tunnel->parms.name, dev->name);
-
-	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
-	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
-
-	dev->tstats = alloc_percpu(struct pcpu_tstats);
-	if (!dev->tstats)
-		return -ENOMEM;
-
-	return 0;
+	return ip_tunnel_init(dev);
 }
 
-static int __net_init vti_fb_tunnel_init(struct net_device *dev)
+static void __net_init vti_fb_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	struct iphdr *iph = &tunnel->parms.iph;
-	struct vti_net *ipn = net_generic(dev_net(dev), vti_net_id);
 
 	iph->version		= 4;
 	iph->protocol		= IPPROTO_IPIP;
 	iph->ihl		= 5;
-
-	dev_hold(dev);
-	rcu_assign_pointer(ipn->tunnels_wc[0], tunnel);
-	return 0;
 }
 
 static struct xfrm_tunnel vti_handler __read_mostly = {
@@ -621,76 +302,30 @@ static struct xfrm_tunnel vti_handler __read_mostly = {
 	.priority	=	1,
 };
 
-static void vti_destroy_tunnels(struct vti_net *ipn, struct list_head *head)
-{
-	int prio;
-
-	for (prio = 1; prio < 4; prio++) {
-		int h;
-		for (h = 0; h < HASH_SIZE; h++) {
-			struct ip_tunnel *t;
-
-			t = rtnl_dereference(ipn->tunnels[prio][h]);
-			while (t != NULL) {
-				unregister_netdevice_queue(t->dev, head);
-				t = rtnl_dereference(t->next);
-			}
-		}
-	}
-}
-
 static int __net_init vti_init_net(struct net *net)
 {
 	int err;
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-
-	ipn->tunnels[0] = ipn->tunnels_wc;
-	ipn->tunnels[1] = ipn->tunnels_l;
-	ipn->tunnels[2] = ipn->tunnels_r;
-	ipn->tunnels[3] = ipn->tunnels_r_l;
-
-	ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
-					  "ip_vti0",
-					  vti_tunnel_setup);
-	if (!ipn->fb_tunnel_dev) {
-		err = -ENOMEM;
-		goto err_alloc_dev;
-	}
-	dev_net_set(ipn->fb_tunnel_dev, net);
-
-	err = vti_fb_tunnel_init(ipn->fb_tunnel_dev);
-	if (err)
-		goto err_reg_dev;
-	ipn->fb_tunnel_dev->rtnl_link_ops = &vti_link_ops;
+	struct ip_tunnel_net *itn;
 
-	err = register_netdev(ipn->fb_tunnel_dev);
+	err = ip_tunnel_init_net(net, vti_net_id, &vti_link_ops, "ip_vti0");
 	if (err)
-		goto err_reg_dev;
+		return err;
+	itn = net_generic(net, vti_net_id);
+	vti_fb_tunnel_init(itn->fb_tunnel_dev);
 	return 0;
-
-err_reg_dev:
-	vti_dev_free(ipn->fb_tunnel_dev);
-err_alloc_dev:
-	/* nothing */
-	return err;
 }
 
 static void __net_exit vti_exit_net(struct net *net)
 {
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-	LIST_HEAD(list);
-
-	rtnl_lock();
-	vti_destroy_tunnels(ipn, &list);
-	unregister_netdevice_many(&list);
-	rtnl_unlock();
+	struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
+	ip_tunnel_delete_net(itn);
 }
 
 static struct pernet_operations vti_net_ops = {
 	.init = vti_init_net,
 	.exit = vti_exit_net,
 	.id   = &vti_net_id,
-	.size = sizeof(struct vti_net),
+	.size = sizeof(struct ip_tunnel_net),
 };
 
 static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -728,78 +363,19 @@ static void vti_netlink_parms(struct nlattr *data[],
 static int vti_newlink(struct net *src_net, struct net_device *dev,
 		       struct nlattr *tb[], struct nlattr *data[])
 {
-	struct ip_tunnel *nt;
-	struct net *net = dev_net(dev);
-	struct vti_net *ipn = net_generic(net, vti_net_id);
-	int mtu;
-	int err;
-
-	nt = netdev_priv(dev);
-	vti_netlink_parms(data, &nt->parms);
-
-	if (vti_tunnel_locate(net, &nt->parms, 0))
-		return -EEXIST;
+	struct ip_tunnel_parm parms;
 
-	mtu = vti_tunnel_bind_dev(dev);
-	if (!tb[IFLA_MTU])
-		dev->mtu = mtu;
-
-	err = register_netdevice(dev);
-	if (err)
-		goto out;
-
-	dev_hold(dev);
-	vti_tunnel_link(ipn, nt);
-
-out:
-	return err;
+	vti_netlink_parms(data, &parms);
+	return ip_tunnel_newlink(dev, tb, &parms);
 }
 
 static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
 			  struct nlattr *data[])
 {
-	struct ip_tunnel *t, *nt;
-	struct net *net = dev_net(dev);
-	struct vti_net *ipn = net_generic(net, vti_net_id);
 	struct ip_tunnel_parm p;
-	int mtu;
-
-	if (dev == ipn->fb_tunnel_dev)
-		return -EINVAL;
 
-	nt = netdev_priv(dev);
 	vti_netlink_parms(data, &p);
-
-	t = vti_tunnel_locate(net, &p, 0);
-
-	if (t) {
-		if (t->dev != dev)
-			return -EEXIST;
-	} else {
-		t = nt;
-
-		vti_tunnel_unlink(ipn, t);
-		t->parms.iph.saddr = p.iph.saddr;
-		t->parms.iph.daddr = p.iph.daddr;
-		t->parms.i_key = p.i_key;
-		t->parms.o_key = p.o_key;
-		if (dev->type != ARPHRD_ETHER) {
-			memcpy(dev->dev_addr, &p.iph.saddr, 4);
-			memcpy(dev->broadcast, &p.iph.daddr, 4);
-		}
-		vti_tunnel_link(ipn, t);
-		netdev_state_change(dev);
-	}
-
-	if (t->parms.link != p.link) {
-		t->parms.link = p.link;
-		mtu = vti_tunnel_bind_dev(dev);
-		if (!tb[IFLA_MTU])
-			dev->mtu = mtu;
-		netdev_state_change(dev);
-	}
-
-	return 0;
+	return ip_tunnel_changelink(dev, tb, &p);
 }
 
 static size_t vti_get_size(const struct net_device *dev)
@@ -865,7 +441,7 @@ static int __init vti_init(void)
 	err = xfrm4_mode_tunnel_input_register(&vti_handler);
 	if (err < 0) {
 		unregister_pernet_device(&vti_net_ops);
-		pr_info(KERN_INFO "vti init: can't register tunnel\n");
+		pr_info("vti init: can't register tunnel\n");
 	}
 
 	err = rtnl_link_register(&vti_link_ops);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 132a096..bacc0bc 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -127,9 +127,9 @@ static struct kmem_cache *mrt_cachep __read_mostly;
 static struct mr_table *ipmr_new_table(struct net *net, u32 id);
 static void ipmr_free_table(struct mr_table *mrt);
 
-static int ip_mr_forward(struct net *net, struct mr_table *mrt,
-			 struct sk_buff *skb, struct mfc_cache *cache,
-			 int local);
+static void ip_mr_forward(struct net *net, struct mr_table *mrt,
+			  struct sk_buff *skb, struct mfc_cache *cache,
+			  int local);
 static int ipmr_cache_report(struct mr_table *mrt,
 			     struct sk_buff *pkt, vifi_t vifi, int assert);
 static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
@@ -1795,9 +1795,9 @@ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev)
 
 /* "local" means that we should preserve one skb (for local delivery) */
 
-static int ip_mr_forward(struct net *net, struct mr_table *mrt,
-			 struct sk_buff *skb, struct mfc_cache *cache,
-			 int local)
+static void ip_mr_forward(struct net *net, struct mr_table *mrt,
+			  struct sk_buff *skb, struct mfc_cache *cache,
+			  int local)
 {
 	int psend = -1;
 	int vif, ct;
@@ -1903,14 +1903,13 @@ last_forward:
 				ipmr_queue_xmit(net, mrt, skb2, cache, psend);
 		} else {
 			ipmr_queue_xmit(net, mrt, skb, cache, psend);
-			return 0;
+			return;
 		}
 	}
 
 dont_forward:
 	if (!local)
 		kfree_skb(skb);
-	return 0;
 }
 
 static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb)
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index eadab1e..a865f6f 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -48,7 +48,7 @@ static int __net_init arptable_filter_net_init(struct net *net)
 	net->ipv4.arptable_filter =
 		arpt_register_table(net, &packet_filter, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv4.arptable_filter);
+	return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter);
 }
 
 static void __net_exit arptable_filter_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 6b3da5c..50af5b4 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -69,7 +69,7 @@ static int __net_init iptable_filter_net_init(struct net *net)
 	net->ipv4.iptable_filter =
 		ipt_register_table(net, &packet_filter, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv4.iptable_filter);
+	return PTR_ERR_OR_ZERO(net->ipv4.iptable_filter);
 }
 
 static void __net_exit iptable_filter_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index cba5658..0d8cd82 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -107,7 +107,7 @@ static int __net_init iptable_mangle_net_init(struct net *net)
 	net->ipv4.iptable_mangle =
 		ipt_register_table(net, &packet_mangler, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv4.iptable_mangle);
+	return PTR_ERR_OR_ZERO(net->ipv4.iptable_mangle);
 }
 
 static void __net_exit iptable_mangle_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index 6383273..683bfaf 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -292,7 +292,7 @@ static int __net_init iptable_nat_net_init(struct net *net)
 		return -ENOMEM;
 	net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv4.nat_table);
+	return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
 }
 
 static void __net_exit iptable_nat_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 03d9696..1f82aea 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -48,7 +48,7 @@ static int __net_init iptable_raw_net_init(struct net *net)
 	net->ipv4.iptable_raw =
 		ipt_register_table(net, &packet_raw, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv4.iptable_raw);
+	return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw);
 }
 
 static void __net_exit iptable_raw_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index b283d8e..f867a8d 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -66,7 +66,7 @@ static int __net_init iptable_security_net_init(struct net *net)
 	net->ipv4.iptable_security =
 		ipt_register_table(net, &security_table, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv4.iptable_security);
+	return PTR_ERR_OR_ZERO(net->ipv4.iptable_security);
 }
 
 static void __net_exit iptable_security_net_exit(struct net *net)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a9a54a2..e805481 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -435,12 +435,12 @@ static inline int ip_rt_proc_init(void)
 
 static inline bool rt_is_expired(const struct rtable *rth)
 {
-	return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
+	return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev));
 }
 
 void rt_cache_flush(struct net *net)
 {
-	rt_genid_bump(net);
+	rt_genid_bump_ipv4(net);
 }
 
 static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -1458,7 +1458,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 #endif
 	rth->dst.output = ip_rt_bug;
 
-	rth->rt_genid	= rt_genid(dev_net(dev));
+	rth->rt_genid	= rt_genid_ipv4(dev_net(dev));
 	rth->rt_flags	= RTCF_MULTICAST;
 	rth->rt_type	= RTN_MULTICAST;
 	rth->rt_is_input= 1;
@@ -1589,7 +1589,7 @@ static int __mkroute_input(struct sk_buff *skb,
 		goto cleanup;
 	}
 
-	rth->rt_genid = rt_genid(dev_net(rth->dst.dev));
+	rth->rt_genid = rt_genid_ipv4(dev_net(rth->dst.dev));
 	rth->rt_flags = flags;
 	rth->rt_type = res->type;
 	rth->rt_is_input = 1;
@@ -1760,7 +1760,7 @@ local_input:
 	rth->dst.tclassid = itag;
 #endif
 
-	rth->rt_genid = rt_genid(net);
+	rth->rt_genid = rt_genid_ipv4(net);
 	rth->rt_flags 	= flags|RTCF_LOCAL;
 	rth->rt_type	= res.type;
 	rth->rt_is_input = 1;
@@ -1945,7 +1945,7 @@ add:
 
 	rth->dst.output = ip_output;
 
-	rth->rt_genid = rt_genid(dev_net(dev_out));
+	rth->rt_genid = rt_genid_ipv4(dev_net(dev_out));
 	rth->rt_flags	= flags;
 	rth->rt_type	= type;
 	rth->rt_is_input = 0;
@@ -2227,7 +2227,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
 		rt->rt_iif = ort->rt_iif;
 		rt->rt_pmtu = ort->rt_pmtu;
 
-		rt->rt_genid = rt_genid(net);
+		rt->rt_genid = rt_genid_ipv4(net);
 		rt->rt_flags = ort->rt_flags;
 		rt->rt_type = ort->rt_type;
 		rt->rt_gateway = ort->rt_gateway;
@@ -2665,7 +2665,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
 
 static __net_init int rt_genid_init(struct net *net)
 {
-	atomic_set(&net->rt_genid, 0);
+	atomic_set(&net->ipv4.rt_genid, 0);
 	atomic_set(&net->fnhe_genid, 0);
 	get_random_bytes(&net->ipv4.dev_addr_genid,
 			 sizeof(net->ipv4.dev_addr_genid));
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 610e324..8ed7c32 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -559,6 +559,13 @@ static struct ctl_table ipv4_table[] = {
 		.extra1		= &one,
 	},
 	{
+		.procname	= "tcp_notsent_lowat",
+		.data		= &sysctl_tcp_notsent_lowat,
+		.maxlen		= sizeof(sysctl_tcp_notsent_lowat),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
 		.procname	= "tcp_rmem",
 		.data		= &sysctl_tcp_rmem,
 		.maxlen		= sizeof(sysctl_tcp_rmem),
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 5423223..ab64eea 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -410,10 +410,6 @@ void tcp_init_sock(struct sock *sk)
 
 	icsk->icsk_sync_mss = tcp_sync_mss;
 
-	/* Presumed zeroed, in order of appearance:
-	 *	cookie_in_always, cookie_out_never,
-	 *	s_data_constant, s_data_in, s_data_out
-	 */
 	sk->sk_sndbuf = sysctl_tcp_wmem[1];
 	sk->sk_rcvbuf = sysctl_tcp_rmem[1];
 
@@ -499,7 +495,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
 			mask |= POLLIN | POLLRDNORM;
 
 		if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
-			if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+			if (sk_stream_is_writeable(sk)) {
 				mask |= POLLOUT | POLLWRNORM;
 			} else {  /* send SIGIO later */
 				set_bit(SOCK_ASYNC_NOSPACE,
@@ -510,7 +506,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
 				 * wspace test but before the flags are set,
 				 * IO signal will be lost.
 				 */
-				if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
+				if (sk_stream_is_writeable(sk))
 					mask |= POLLOUT | POLLWRNORM;
 			}
 		} else
@@ -2631,6 +2627,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		else
 			tp->tsoffset = val - tcp_time_stamp;
 		break;
+	case TCP_NOTSENT_LOWAT:
+		tp->notsent_lowat = val;
+		sk->sk_write_space(sk);
+		break;
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -2847,6 +2847,9 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 	case TCP_TIMESTAMP:
 		val = tcp_time_stamp + tp->tsoffset;
 		break;
+	case TCP_NOTSENT_LOWAT:
+		val = tp->notsent_lowat;
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index a9077f4..b6ae92a 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -206,8 +206,8 @@ static u32 cubic_root(u64 a)
  */
 static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 {
-	u64 offs;
-	u32 delta, t, bic_target, max_cnt;
+	u32 delta, bic_target, max_cnt;
+	u64 offs, t;
 
 	ca->ack_cnt++;	/* count the number of ACKs */
 
@@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 	 * if the cwnd < 1 million packets !!!
 	 */
 
+	t = (s32)(tcp_time_stamp - ca->epoch_start);
+	t += msecs_to_jiffies(ca->delay_min >> 3);
 	/* change the unit from HZ to bictcp_HZ */
-	t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3)
-	      - ca->epoch_start) << BICTCP_HZ) / HZ;
+	t <<= BICTCP_HZ;
+	do_div(t, HZ);
 
 	if (t < ca->bic_K)		/* t - K */
 		offs = ca->bic_K - t;
@@ -414,7 +416,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
 		return;
 
 	/* Discard delay samples right after fast recovery */
-	if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ)
+	if (ca->epoch_start && (s32)(tcp_time_stamp - ca->epoch_start) < HZ)
 		return;
 
 	delay = (rtt_us << 3) / USEC_PER_MSEC;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 28af45a..b61274b 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1048,6 +1048,7 @@ struct tcp_sacktag_state {
 	int reord;
 	int fack_count;
 	int flag;
+	s32 rtt; /* RTT measured by SACKing never-retransmitted data */
 };
 
 /* Check if skb is fully within the SACK block. In presence of GSO skbs,
@@ -1108,7 +1109,7 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
 static u8 tcp_sacktag_one(struct sock *sk,
 			  struct tcp_sacktag_state *state, u8 sacked,
 			  u32 start_seq, u32 end_seq,
-			  bool dup_sack, int pcount)
+			  int dup_sack, int pcount, u32 xmit_time)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	int fack_count = state->fack_count;
@@ -1148,6 +1149,9 @@ static u8 tcp_sacktag_one(struct sock *sk,
 							   state->reord);
 				if (!after(end_seq, tp->high_seq))
 					state->flag |= FLAG_ORIG_SACK_ACKED;
+				/* Pick the earliest sequence sacked for RTT */
+				if (state->rtt < 0)
+					state->rtt = tcp_time_stamp - xmit_time;
 			}
 
 			if (sacked & TCPCB_LOST) {
@@ -1205,7 +1209,8 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
 	 * tcp_highest_sack_seq() when skb is highest_sack.
 	 */
 	tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked,
-			start_seq, end_seq, dup_sack, pcount);
+			start_seq, end_seq, dup_sack, pcount,
+			TCP_SKB_CB(skb)->when);
 
 	if (skb == tp->lost_skb_hint)
 		tp->lost_cnt_hint += pcount;
@@ -1479,7 +1484,8 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
 						TCP_SKB_CB(skb)->seq,
 						TCP_SKB_CB(skb)->end_seq,
 						dup_sack,
-						tcp_skb_pcount(skb));
+						tcp_skb_pcount(skb),
+						TCP_SKB_CB(skb)->when);
 
 			if (!before(TCP_SKB_CB(skb)->seq,
 				    tcp_highest_sack_seq(tp)))
@@ -1536,7 +1542,7 @@ static int tcp_sack_cache_ok(const struct tcp_sock *tp, const struct tcp_sack_bl
 
 static int
 tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
-			u32 prior_snd_una)
+			u32 prior_snd_una, s32 *sack_rtt)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	const unsigned char *ptr = (skb_transport_header(ack_skb) +
@@ -1554,6 +1560,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
 
 	state.flag = 0;
 	state.reord = tp->packets_out;
+	state.rtt = -1;
 
 	if (!tp->sacked_out) {
 		if (WARN_ON(tp->fackets_out))
@@ -1737,6 +1744,7 @@ out:
 	WARN_ON((int)tp->retrans_out < 0);
 	WARN_ON((int)tcp_packets_in_flight(tp) < 0);
 #endif
+	*sack_rtt = state.rtt;
 	return state.flag;
 }
 
@@ -2792,65 +2800,51 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked,
 	tcp_xmit_retransmit_queue(sk);
 }
 
-void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
+static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
+				      s32 seq_rtt, s32 sack_rtt)
 {
-	tcp_rtt_estimator(sk, seq_rtt);
-	tcp_set_rto(sk);
-	inet_csk(sk)->icsk_backoff = 0;
-}
-EXPORT_SYMBOL(tcp_valid_rtt_meas);
+	const struct tcp_sock *tp = tcp_sk(sk);
+
+	/* Prefer RTT measured from ACK's timing to TS-ECR. This is because
+	 * broken middle-boxes or peers may corrupt TS-ECR fields. But
+	 * Karn's algorithm forbids taking RTT if some retransmitted data
+	 * is acked (RFC6298).
+	 */
+	if (flag & FLAG_RETRANS_DATA_ACKED)
+		seq_rtt = -1;
+
+	if (seq_rtt < 0)
+		seq_rtt = sack_rtt;
 
-/* Read draft-ietf-tcplw-high-performance before mucking
- * with this code. (Supersedes RFC1323)
- */
-static void tcp_ack_saw_tstamp(struct sock *sk, int flag)
-{
 	/* RTTM Rule: A TSecr value received in a segment is used to
 	 * update the averaged RTT measurement only if the segment
 	 * acknowledges some new data, i.e., only if it advances the
 	 * left edge of the send window.
-	 *
 	 * See draft-ietf-tcplw-high-performance-00, section 3.3.
-	 * 1998/04/10 Andrey V. Savochkin <saw@msu.ru>
-	 *
-	 * Changed: reset backoff as soon as we see the first valid sample.
-	 * If we do not, we get strongly overestimated rto. With timestamps
-	 * samples are accepted even from very old segments: f.e., when rtt=1
-	 * increases to 8, we retransmit 5 times and after 8 seconds delayed
-	 * answer arrives rto becomes 120 seconds! If at least one of segments
-	 * in window is lost... Voila.	 			--ANK (010210)
 	 */
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	tcp_valid_rtt_meas(sk, tcp_time_stamp - tp->rx_opt.rcv_tsecr);
-}
+	if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
+		seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
 
-static void tcp_ack_no_tstamp(struct sock *sk, u32 seq_rtt, int flag)
-{
-	/* We don't have a timestamp. Can only use
-	 * packets that are not retransmitted to determine
-	 * rtt estimates. Also, we must not reset the
-	 * backoff for rto until we get a non-retransmitted
-	 * packet. This allows us to deal with a situation
-	 * where the network delay has increased suddenly.
-	 * I.e. Karn's algorithm. (SIGCOMM '87, p5.)
-	 */
+	if (seq_rtt < 0)
+		return false;
 
-	if (flag & FLAG_RETRANS_DATA_ACKED)
-		return;
+	tcp_rtt_estimator(sk, seq_rtt);
+	tcp_set_rto(sk);
 
-	tcp_valid_rtt_meas(sk, seq_rtt);
+	/* RFC6298: only reset backoff on valid RTT measurement. */
+	inet_csk(sk)->icsk_backoff = 0;
+	return true;
 }
 
-static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
-				      const s32 seq_rtt)
+/* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */
+static void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req)
 {
-	const struct tcp_sock *tp = tcp_sk(sk);
-	/* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
-	if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
-		tcp_ack_saw_tstamp(sk, flag);
-	else if (seq_rtt >= 0)
-		tcp_ack_no_tstamp(sk, seq_rtt, flag);
+	struct tcp_sock *tp = tcp_sk(sk);
+	s32 seq_rtt = -1;
+
+	if (tp->lsndtime && !tp->total_retrans)
+		seq_rtt = tcp_time_stamp - tp->lsndtime;
+	tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
 }
 
 static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
@@ -2939,7 +2933,7 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
  * arrived at the other end.
  */
 static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
-			       u32 prior_snd_una)
+			       u32 prior_snd_una, s32 sack_rtt)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -2978,8 +2972,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 			if (sacked & TCPCB_SACKED_RETRANS)
 				tp->retrans_out -= acked_pcount;
 			flag |= FLAG_RETRANS_DATA_ACKED;
-			ca_seq_rtt = -1;
-			seq_rtt = -1;
 		} else {
 			ca_seq_rtt = now - scb->when;
 			last_ackt = skb->tstamp;
@@ -3031,6 +3023,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 	if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
 		flag |= FLAG_SACK_RENEGING;
 
+	if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) ||
+	    (flag & FLAG_ACKED))
+		tcp_rearm_rto(sk);
+
 	if (flag & FLAG_ACKED) {
 		const struct tcp_congestion_ops *ca_ops
 			= inet_csk(sk)->icsk_ca_ops;
@@ -3040,9 +3036,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 			tcp_mtup_probe_success(sk);
 		}
 
-		tcp_ack_update_rtt(sk, flag, seq_rtt);
-		tcp_rearm_rto(sk);
-
 		if (tcp_is_reno(tp)) {
 			tcp_remove_reno_sacks(sk, pkts_acked);
 		} else {
@@ -3274,6 +3267,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 	int prior_packets = tp->packets_out;
 	const int prior_unsacked = tp->packets_out - tp->sacked_out;
 	int acked = 0; /* Number of packets newly acked */
+	s32 sack_rtt = -1;
 
 	/* If the ack is older than previous acks
 	 * then we can probably ignore it.
@@ -3330,7 +3324,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 		flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
 
 		if (TCP_SKB_CB(skb)->sacked)
-			flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
+			flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
+							&sack_rtt);
 
 		if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb)))
 			flag |= FLAG_ECE;
@@ -3349,7 +3344,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 
 	/* See if we can take anything off of the retransmit queue. */
 	acked = tp->packets_out;
-	flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
+	flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_rtt);
 	acked -= tp->packets_out;
 
 	if (tcp_ack_is_dubious(sk, flag)) {
@@ -3402,7 +3397,8 @@ old_ack:
 	 * If data was DSACKed, see if we can undo a cwnd reduction.
 	 */
 	if (TCP_SKB_CB(skb)->sacked) {
-		flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
+		flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
+						&sack_rtt);
 		tcp_fastretrans_alert(sk, acked, prior_unsacked,
 				      is_dupack, flag);
 	}
@@ -5624,9 +5620,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 		 * so release it.
 		 */
 		if (req) {
-			tcp_synack_rtt_meas(sk, req);
 			tp->total_retrans = req->num_retrans;
-
 			reqsk_fastopen_remove(sk, req, false);
 		} else {
 			/* Make sure socket is routed, for correct metrics. */
@@ -5651,6 +5645,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 		tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
 		tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
 		tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
+		tcp_synack_rtt_meas(sk, req);
 
 		if (tp->rx_opt.tstamp_ok)
 			tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index b299da5..280efe5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -890,7 +890,7 @@ bool tcp_syn_flood_action(struct sock *sk,
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
 
 	lopt = inet_csk(sk)->icsk_accept_queue.listen_opt;
-	if (!lopt->synflood_warned) {
+	if (!lopt->synflood_warned && sysctl_tcp_syncookies != 2) {
 		lopt->synflood_warned = 1;
 		pr_info("%s: Possible SYN flooding on port %d. %s.  Check SNMP counters.\n",
 			proto, ntohs(tcp_hdr(skb)->dest), msg);
@@ -1462,7 +1462,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	 * limitations, they conserve resources and peer is
 	 * evidently real one.
 	 */
-	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
+	if ((sysctl_tcp_syncookies == 2 ||
+	     inet_csk_reqsk_queue_is_full(sk)) && !isn) {
 		want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
 		if (!want_cookie)
 			goto drop;
@@ -1671,8 +1672,6 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
 
 	tcp_initialize_rcv_mss(newsk);
-	tcp_synack_rtt_meas(newsk, req);
-	newtp->total_retrans = req->num_retrans;
 
 #ifdef CONFIG_TCP_MD5SIG
 	/* Copy over the MD5 key from the original socket */
@@ -2802,6 +2801,7 @@ struct proto tcp_prot = {
 	.unhash			= inet_unhash,
 	.get_port		= inet_csk_get_port,
 	.enter_memory_pressure	= tcp_enter_memory_pressure,
+	.stream_memory_free	= tcp_stream_memory_free,
 	.sockets_allocated	= &tcp_sockets_allocated,
 	.orphan_count		= &tcp_orphan_count,
 	.memory_allocated	= &tcp_memory_allocated,
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index da14436..90550f4 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -87,8 +87,8 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 	if (!cg_proto)
 		return -EINVAL;
 
-	if (val > RESOURCE_MAX)
-		val = RESOURCE_MAX;
+	if (val > RES_COUNTER_MAX)
+		val = RES_COUNTER_MAX;
 
 	tcp = tcp_from_cgproto(cg_proto);
 
@@ -101,9 +101,9 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 		tcp->tcp_prot_mem[i] = min_t(long, val >> PAGE_SHIFT,
 					     net->ipv4.sysctl_tcp_mem[i]);
 
-	if (val == RESOURCE_MAX)
+	if (val == RES_COUNTER_MAX)
 		clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags);
-	else if (val != RESOURCE_MAX) {
+	else if (val != RES_COUNTER_MAX) {
 		/*
 		 * The active bit needs to be written after the static_key
 		 * update. This is what guarantees that the socket activation
@@ -187,7 +187,7 @@ static u64 tcp_cgroup_read(struct cgroup *cont, struct cftype *cft)
 
 	switch (cft->private) {
 	case RES_LIMIT:
-		val = tcp_read_stat(memcg, RES_LIMIT, RESOURCE_MAX);
+		val = tcp_read_stat(memcg, RES_LIMIT, RES_COUNTER_MAX);
 		break;
 	case RES_USAGE:
 		val = tcp_read_usage(memcg);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index ab1c086..58a3e69 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -411,6 +411,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
 		tcp_enable_early_retrans(newtp);
 		newtp->tlp_high_seq = 0;
+		newtp->lsndtime = treq->snt_synack;
+		newtp->total_retrans = req->num_retrans;
 
 		/* So many TCP implementations out there (incorrectly) count the
 		 * initial SYN frame in their delayed-ACK and congestion control
@@ -666,12 +668,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 	if (!(flg & TCP_FLAG_ACK))
 		return NULL;
 
-	/* Got ACK for our SYNACK, so update baseline for SYNACK RTT sample. */
-	if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr)
-		tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr;
-	else if (req->num_retrans) /* don't take RTT sample if retrans && ~TS */
-		tcp_rsk(req)->snt_synack = 0;
-
 	/* For Fast Open no more processing is needed (sk is the
 	 * child socket).
 	 */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 92fde8d..884efff 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -65,6 +65,9 @@ int sysctl_tcp_base_mss __read_mostly = TCP_BASE_MSS;
 /* By default, RFC2861 behavior.  */
 int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
 
+unsigned int sysctl_tcp_notsent_lowat __read_mostly = UINT_MAX;
+EXPORT_SYMBOL(sysctl_tcp_notsent_lowat);
+
 static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 			   int push_one, gfp_t gfp);
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 766e6ba..9e88af0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -704,7 +704,7 @@ EXPORT_SYMBOL(udp_flush_pending_frames);
  *	@src:	source IP address
  *	@dst:	destination IP address
  */
-static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
+void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
 {
 	struct udphdr *uh = udp_hdr(skb);
 	struct sk_buff *frags = skb_shinfo(skb)->frag_list;
@@ -740,6 +740,7 @@ static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
 			uh->check = CSUM_MANGLED_0;
 	}
 }
+EXPORT_SYMBOL_GPL(udp4_hwcsum);
 
 static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4)
 {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index da4241c..7fd8572 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4654,6 +4654,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 		break;
 	}
 	atomic_inc(&net->ipv6.dev_addr_genid);
+	rt_genid_bump_ipv6(net);
 }
 
 static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index a5ac969..0d1a9b1 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -766,6 +766,7 @@ static int __net_init inet6_net_init(struct net *net)
 
 	net->ipv6.sysctl.bindv6only = 0;
 	net->ipv6.sysctl.icmpv6_time = 1*HZ;
+	atomic_set(&net->ipv6.rt_genid, 0);
 
 	err = ipv6_init_mibs(net);
 	if (err)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 40ffd72..aeac0dc 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -425,7 +425,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
 		net_adj = 0;
 
 	return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
-		 net_adj) & ~(align - 1)) + (net_adj - 2);
+		 net_adj) & ~(align - 1)) + net_adj - 2;
 }
 
 static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 2e1a432..a6c58ce 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -55,26 +55,33 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
 	struct fib6_table *table;
 	struct net *net = rule->fr_net;
 	pol_lookup_t lookup = arg->lookup_ptr;
+	int err = 0;
 
 	switch (rule->action) {
 	case FR_ACT_TO_TBL:
 		break;
 	case FR_ACT_UNREACHABLE:
+		err = -ENETUNREACH;
 		rt = net->ipv6.ip6_null_entry;
 		goto discard_pkt;
 	default:
 	case FR_ACT_BLACKHOLE:
+		err = -EINVAL;
 		rt = net->ipv6.ip6_blk_hole_entry;
 		goto discard_pkt;
 	case FR_ACT_PROHIBIT:
+		err = -EACCES;
 		rt = net->ipv6.ip6_prohibit_entry;
 		goto discard_pkt;
 	}
 
 	table = fib6_get_table(net, rule->table);
-	if (table)
-		rt = lookup(net, table, flp6, flags);
+	if (!table) {
+		err = -EAGAIN;
+		goto out;
+	}
 
+	rt = lookup(net, table, flp6, flags);
 	if (rt != net->ipv6.ip6_null_entry) {
 		struct fib6_rule *r = (struct fib6_rule *)rule;
 
@@ -101,6 +108,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
 	}
 again:
 	ip6_rt_put(rt);
+	err = -EAGAIN;
 	rt = NULL;
 	goto out;
 
@@ -108,9 +116,31 @@ discard_pkt:
 	dst_hold(&rt->dst);
 out:
 	arg->result = rt;
-	return rt == NULL ? -EAGAIN : 0;
+	return err;
 }
 
+static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
+{
+	struct rt6_info *rt = (struct rt6_info *) arg->result;
+	struct net_device *dev = rt->rt6i_idev->dev;
+	/* do not accept result if the route does
+	 * not meet the required prefix length
+	 */
+	if (rt->rt6i_dst.plen <= rule->suppress_prefixlen)
+		goto suppress_route;
+
+	/* do not accept result if the route uses a device
+	 * belonging to a forbidden interface group
+	 */
+	if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
+		goto suppress_route;
+
+	return false;
+
+suppress_route:
+		ip6_rt_put(rt);
+		return true;
+}
 
 static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
@@ -244,6 +274,7 @@ static const struct fib_rules_ops __net_initconst fib6_rules_ops_template = {
 	.addr_size		= sizeof(struct in6_addr),
 	.action			= fib6_rule_action,
 	.match			= fib6_rule_match,
+	.suppress		= fib6_rule_suppress,
 	.configure		= fib6_rule_configure,
 	.compare		= fib6_rule_compare,
 	.fill			= fib6_rule_fill,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index bff3d82..73db48e 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -425,8 +425,8 @@ out:
  *	node.
  */
 
-static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
-				     int addrlen, int plen,
+static struct fib6_node *fib6_add_1(struct fib6_node *root,
+				     struct in6_addr *addr, int plen,
 				     int offset, int allow_create,
 				     int replace_required)
 {
@@ -543,7 +543,7 @@ insert_above:
 	   but if it is >= plen, the value is ignored in any case.
 	 */
 
-	bit = __ipv6_addr_diff(addr, &key->addr, addrlen);
+	bit = __ipv6_addr_diff(addr, &key->addr, sizeof(*addr));
 
 	/*
 	 *		(intermediate)[in]
@@ -822,9 +822,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 	if (!allow_create && !replace_required)
 		pr_warn("RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n");
 
-	fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-			rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst),
-			allow_create, replace_required);
+	fn = fib6_add_1(root, &rt->rt6i_dst.addr, rt->rt6i_dst.plen,
+			offsetof(struct rt6_info, rt6i_dst), allow_create,
+			replace_required);
 
 	if (IS_ERR(fn)) {
 		err = PTR_ERR(fn);
@@ -863,7 +863,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 			/* Now add the first leaf node to new subtree */
 
 			sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
-					sizeof(struct in6_addr), rt->rt6i_src.plen,
+					rt->rt6i_src.plen,
 					offsetof(struct rt6_info, rt6i_src),
 					allow_create, replace_required);
 
@@ -882,7 +882,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 			fn->subtree = sfn;
 		} else {
 			sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
-					sizeof(struct in6_addr), rt->rt6i_src.plen,
+					rt->rt6i_src.plen,
 					offsetof(struct rt6_info, rt6i_src),
 					allow_create, replace_required);
 
@@ -993,14 +993,22 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
 
 			if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
 #ifdef CONFIG_IPV6_SUBTREES
-				if (fn->subtree)
-					fn = fib6_lookup_1(fn->subtree, args + 1);
+				if (fn->subtree) {
+					struct fib6_node *sfn;
+					sfn = fib6_lookup_1(fn->subtree,
+							    args + 1);
+					if (!sfn)
+						goto backtrack;
+					fn = sfn;
+				}
 #endif
-				if (!fn || fn->fn_flags & RTN_RTINFO)
+				if (fn->fn_flags & RTN_RTINFO)
 					return fn;
 			}
 		}
-
+#ifdef CONFIG_IPV6_SUBTREES
+backtrack:
+#endif
 		if (fn->fn_flags & RTN_ROOT)
 			break;
 
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 03986d3..a60a84e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -110,8 +110,8 @@ static struct kmem_cache *mrt_cachep __read_mostly;
 static struct mr6_table *ip6mr_new_table(struct net *net, u32 id);
 static void ip6mr_free_table(struct mr6_table *mrt);
 
-static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
-			  struct sk_buff *skb, struct mfc6_cache *cache);
+static void ip6_mr_forward(struct net *net, struct mr6_table *mrt,
+			   struct sk_buff *skb, struct mfc6_cache *cache);
 static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
 			      mifi_t mifi, int assert);
 static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
@@ -2074,8 +2074,8 @@ static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev)
 	return ct;
 }
 
-static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
-			  struct sk_buff *skb, struct mfc6_cache *cache)
+static void ip6_mr_forward(struct net *net, struct mr6_table *mrt,
+			   struct sk_buff *skb, struct mfc6_cache *cache)
 {
 	int psend = -1;
 	int vif, ct;
@@ -2156,12 +2156,11 @@ forward:
 last_forward:
 	if (psend != -1) {
 		ip6mr_forward2(net, mrt, skb, cache, psend);
-		return 0;
+		return;
 	}
 
 dont_forward:
 	kfree_skb(skb);
-	return 0;
 }
 
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 99cd65c..db25b8e 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -44,6 +44,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/pkt_sched.h>
 #include <net/mld.h>
 
 #include <linux/netfilter.h>
@@ -1376,6 +1377,7 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
 	if (!skb)
 		return NULL;
 
+	skb->priority = TC_PRIO_CONTROL;
 	skb_reserve(skb, hlen);
 
 	if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
@@ -1769,7 +1771,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 		rcu_read_unlock();
 		return;
 	}
-
+	skb->priority = TC_PRIO_CONTROL;
 	skb_reserve(skb, hlen);
 
 	if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index beb5777..29b44b1 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -61,7 +61,7 @@ static int __net_init ip6table_filter_net_init(struct net *net)
 	net->ipv6.ip6table_filter =
 		ip6t_register_table(net, &packet_filter, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv6.ip6table_filter);
+	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_filter);
 }
 
 static void __net_exit ip6table_filter_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index e075399..c705907 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -101,7 +101,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net)
 	net->ipv6.ip6table_mangle =
 		ip6t_register_table(net, &packet_mangler, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv6.ip6table_mangle);
+	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle);
 }
 
 static void __net_exit ip6table_mangle_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index 6383f90..9b076d2 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -293,7 +293,7 @@ static int __net_init ip6table_nat_net_init(struct net *net)
 		return -ENOMEM;
 	net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv6.ip6table_nat);
+	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_nat);
 }
 
 static void __net_exit ip6table_nat_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 60d1bdd..9a626d8 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -40,7 +40,7 @@ static int __net_init ip6table_raw_net_init(struct net *net)
 	net->ipv6.ip6table_raw =
 		ip6t_register_table(net, &packet_raw, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv6.ip6table_raw);
+	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_raw);
 }
 
 static void __net_exit ip6table_raw_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index db15535..ce88d1d 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -58,7 +58,7 @@ static int __net_init ip6table_security_net_init(struct net *net)
 	net->ipv6.ip6table_security =
 		ip6t_register_table(net, &security_table, repl);
 	kfree(repl);
-	return PTR_RET(net->ipv6.ip6table_security);
+	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_security);
 }
 
 static void __net_exit ip6table_security_net_exit(struct net *net)
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index c45f7a5..c1e5334 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -63,6 +63,8 @@
 #include <linux/seq_file.h>
 #include <linux/export.h>
 
+#define	ICMPV6_HDRLEN	4	/* ICMPv6 header, RFC 4443 Section 2.1 */
+
 static struct raw_hashinfo raw_v6_hashinfo = {
 	.lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
 };
@@ -108,11 +110,14 @@ found:
  */
 static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
 {
-	struct icmp6hdr *_hdr;
+	struct icmp6hdr _hdr;
 	const struct icmp6hdr *hdr;
 
+	/* We require only the four bytes of the ICMPv6 header, not any
+	 * additional bytes of message body in "struct icmp6hdr".
+	 */
 	hdr = skb_header_pointer(skb, skb_transport_offset(skb),
-				 sizeof(_hdr), &_hdr);
+				 ICMPV6_HDRLEN, &_hdr);
 	if (hdr) {
 		const __u32 *data = &raw6_sk(sk)->filter.data[0];
 		unsigned int type = hdr->icmp6_type;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b70f897..e22c4db 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -283,9 +283,8 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
 
 		memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
 		rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
-		rt->rt6i_genid = rt_genid(net);
+		rt->rt6i_genid = rt_genid_ipv6(net);
 		INIT_LIST_HEAD(&rt->rt6i_siblings);
-		rt->rt6i_nsiblings = 0;
 	}
 	return rt;
 }
@@ -1062,7 +1061,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 	 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
 	 * into this function always.
 	 */
-	if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
+	if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
 		return NULL;
 
 	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6e1649d..38c196ca 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -963,7 +963,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	if (!ipv6_unicast_destination(skb))
 		goto drop;
 
-	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
+	if ((sysctl_tcp_syncookies == 2 ||
+	     inet_csk_reqsk_queue_is_full(sk)) && !isn) {
 		want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6");
 		if (!want_cookie)
 			goto drop;
@@ -1237,8 +1238,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
 
 	tcp_initialize_rcv_mss(newsk);
-	tcp_synack_rtt_meas(newsk, req);
-	newtp->total_retrans = req->num_retrans;
 
 	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
 	newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
@@ -1926,6 +1925,7 @@ struct proto tcpv6_prot = {
 	.unhash			= inet_unhash,
 	.get_port		= inet_csk_get_port,
 	.enter_memory_pressure	= tcp_enter_memory_pressure,
+	.stream_memory_free	= tcp_stream_memory_free,
 	.sockets_allocated	= &tcp_sockets_allocated,
 	.memory_allocated	= &tcp_memory_allocated,
 	.memory_pressure	= &tcp_memory_pressure,
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index ae43c62..85372cf 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -75,7 +75,7 @@ static pi_minor_info_t pi_minor_call_table[] = {
 	{ NULL, 0 },                                             /* 0x00 */
 	{ irttp_param_max_sdu_size, PV_INTEGER | PV_BIG_ENDIAN } /* 0x01 */
 };
-static pi_major_info_t pi_major_call_table[] = {{ pi_minor_call_table, 2 }};
+static pi_major_info_t pi_major_call_table[] = { { pi_minor_call_table, 2 } };
 static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
 
 /************************ GLOBAL PROCEDURES ************************/
@@ -205,7 +205,7 @@ static void irttp_todo_expired(unsigned long data)
  */
 static void irttp_flush_queues(struct tsap_cb *self)
 {
-	struct sk_buff* skb;
+	struct sk_buff *skb;
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
@@ -400,7 +400,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
 	/* The IrLMP spec (IrLMP 1.1 p10) says that we have the right to
 	 * use only 0x01-0x6F. Of course, we can use LSAP_ANY as well.
 	 * JeanII */
-	if((stsap_sel != LSAP_ANY) &&
+	if ((stsap_sel != LSAP_ANY) &&
 	   ((stsap_sel < 0x01) || (stsap_sel >= 0x70))) {
 		IRDA_DEBUG(0, "%s(), invalid tsap!\n", __func__);
 		return NULL;
@@ -427,7 +427,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
 	ttp_notify.data_indication = irttp_data_indication;
 	ttp_notify.udata_indication = irttp_udata_indication;
 	ttp_notify.flow_indication = irttp_flow_indication;
-	if(notify->status_indication != NULL)
+	if (notify->status_indication != NULL)
 		ttp_notify.status_indication = irttp_status_indication;
 	ttp_notify.instance = self;
 	strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
@@ -639,8 +639,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
 	 */
 	if ((self->tx_max_sdu_size != 0) &&
 	    (self->tx_max_sdu_size != TTP_SAR_UNBOUND) &&
-	    (skb->len > self->tx_max_sdu_size))
-	{
+	    (skb->len > self->tx_max_sdu_size)) {
 		IRDA_ERROR("%s: SAR enabled, but data is larger than TxMaxSduSize!\n",
 			   __func__);
 		ret = -EMSGSIZE;
@@ -733,8 +732,7 @@ static void irttp_run_tx_queue(struct tsap_cb *self)
 	 * poll us through irttp_flow_indication() - Jean II */
 	while ((self->send_credit > 0) &&
 	       (!irlmp_lap_tx_queue_full(self->lsap)) &&
-	       (skb = skb_dequeue(&self->tx_queue)))
-	{
+	       (skb = skb_dequeue(&self->tx_queue))) {
 		/*
 		 *  Since we can transmit and receive frames concurrently,
 		 *  the code below is a critical region and we must assure that
@@ -798,8 +796,7 @@ static void irttp_run_tx_queue(struct tsap_cb *self)
 	 * where we can spend a bit of time doing stuff. - Jean II */
 	if ((self->tx_sdu_busy) &&
 	    (skb_queue_len(&self->tx_queue) < TTP_TX_LOW_THRESHOLD) &&
-	    (!self->close_pend))
-	{
+	    (!self->close_pend)) {
 		if (self->notify.flow_indication)
 			self->notify.flow_indication(self->notify.instance,
 						     self, FLOW_START);
@@ -892,7 +889,7 @@ static int irttp_udata_indication(void *instance, void *sap,
 	/* Just pass data to layer above */
 	if (self->notify.udata_indication) {
 		err = self->notify.udata_indication(self->notify.instance,
-						    self,skb);
+						    self, skb);
 		/* Same comment as in irttp_do_data_indication() */
 		if (!err)
 			return 0;
@@ -1057,7 +1054,7 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 	 * to do that. Jean II */
 
 	/* If we need to send disconnect. try to do it now */
-	if(self->disconnect_pend)
+	if (self->disconnect_pend)
 		irttp_start_todo_timer(self, 0);
 }
 
@@ -1116,7 +1113,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
 
 	if (self->connected) {
-		if(userdata)
+		if (userdata)
 			dev_kfree_skb(userdata);
 		return -EISCONN;
 	}
@@ -1137,7 +1134,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
 		 *  headers
 		 */
 		IRDA_ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
-			{ dev_kfree_skb(userdata); return -1; } );
+			{ dev_kfree_skb(userdata); return -1; });
 	}
 
 	/* Initialize connection parameters */
@@ -1157,7 +1154,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
 	 *  Give away max 127 credits for now
 	 */
 	if (n > 127) {
-		self->avail_credit=n-127;
+		self->avail_credit = n - 127;
 		n = 127;
 	}
 
@@ -1166,10 +1163,10 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
 		IRDA_ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
-			{ dev_kfree_skb(tx_skb); return -1; } );
+			{ dev_kfree_skb(tx_skb); return -1; });
 
 		/* Insert SAR parameters */
-		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
+		frame = skb_push(tx_skb, TTP_HEADER + TTP_SAR_HEADER);
 
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
@@ -1386,7 +1383,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
 		 *  headers
 		 */
 		IRDA_ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
-			{ dev_kfree_skb(userdata); return -1; } );
+			{ dev_kfree_skb(userdata); return -1; });
 	}
 
 	self->avail_credit = 0;
@@ -1409,10 +1406,10 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
 		IRDA_ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
-			{ dev_kfree_skb(tx_skb); return -1; } );
+			{ dev_kfree_skb(tx_skb); return -1; });
 
 		/* Insert TTP header with SAR parameters */
-		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
+		frame = skb_push(tx_skb, TTP_HEADER + TTP_SAR_HEADER);
 
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
@@ -1522,7 +1519,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
 	 * function may be called from various context, like user, timer
 	 * for following a disconnect_indication() (i.e. net_bh).
 	 * Jean II */
-	if(test_and_set_bit(0, &self->disconnect_pend)) {
+	if (test_and_set_bit(0, &self->disconnect_pend)) {
 		IRDA_DEBUG(0, "%s(), disconnect already pending\n",
 			   __func__);
 		if (userdata)
@@ -1627,7 +1624,7 @@ static void irttp_disconnect_indication(void *instance, void *sap,
 	 * Jean II */
 
 	/* No need to notify the client if has already tried to disconnect */
-	if(self->notify.disconnect_indication)
+	if (self->notify.disconnect_indication)
 		self->notify.disconnect_indication(self->notify.instance, self,
 						   reason, skb);
 	else
@@ -1738,8 +1735,7 @@ static void irttp_run_rx_queue(struct tsap_cb *self)
 		 *  This is the last fragment, so time to reassemble!
 		 */
 		if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
-		    (self->rx_max_sdu_size == TTP_SAR_UNBOUND))
-		{
+		    (self->rx_max_sdu_size == TTP_SAR_UNBOUND)) {
 			/*
 			 * A little optimizing. Only queue the fragment if
 			 * there are other fragments. Since if this is the
@@ -1860,7 +1856,7 @@ static int irttp_seq_show(struct seq_file *seq, void *v)
 	seq_printf(seq, "dtsap_sel: %02x\n",
 		   self->dtsap_sel);
 	seq_printf(seq, "  connected: %s, ",
-		   self->connected? "TRUE":"FALSE");
+		   self->connected ? "TRUE" : "FALSE");
 	seq_printf(seq, "avail credit: %d, ",
 		   self->avail_credit);
 	seq_printf(seq, "remote credit: %d, ",
@@ -1876,9 +1872,9 @@ static int irttp_seq_show(struct seq_file *seq, void *v)
 	seq_printf(seq, "rx_queue len: %u\n",
 		   skb_queue_len(&self->rx_queue));
 	seq_printf(seq, "  tx_sdu_busy: %s, ",
-		   self->tx_sdu_busy? "TRUE":"FALSE");
+		   self->tx_sdu_busy ? "TRUE" : "FALSE");
 	seq_printf(seq, "rx_sdu_busy: %s\n",
-		   self->rx_sdu_busy? "TRUE":"FALSE");
+		   self->rx_sdu_busy ? "TRUE" : "FALSE");
 	seq_printf(seq, "  max_seg_size: %u, ",
 		   self->max_seg_size);
 	seq_printf(seq, "tx_max_sdu_size: %u, ",
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ab8bd2c..9d58537 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -45,7 +45,7 @@ struct netns_pfkey {
 static DEFINE_MUTEX(pfkey_mutex);
 
 #define DUMMY_MARK 0
-static struct xfrm_mark dummy_mark = {0, 0};
+static const struct xfrm_mark dummy_mark = {0, 0};
 struct pfkey_sock {
 	/* struct sock must be the first member of struct pfkey_sock */
 	struct sock	sk;
@@ -338,7 +338,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
 	return 0;
 }
 
-static u8 sadb_ext_min_len[] = {
+static const u8 sadb_ext_min_len[] = {
 	[SADB_EXT_RESERVED]		= (u8) 0,
 	[SADB_EXT_SA]			= (u8) sizeof(struct sadb_sa),
 	[SADB_EXT_LIFETIME_CURRENT]	= (u8) sizeof(struct sadb_lifetime),
@@ -1196,10 +1196,6 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 
 	x->props.family = pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 						    &x->props.saddr);
-	if (!x->props.family) {
-		err = -EAFNOSUPPORT;
-		goto out;
-	}
 	pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1],
 				  &x->id.daddr);
 
@@ -2205,10 +2201,6 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
 
 	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
 	xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);
-	if (!xp->family) {
-		err = -EINVAL;
-		goto out;
-	}
 	xp->selector.family = xp->family;
 	xp->selector.prefixlen_s = sa->sadb_address_prefixlen;
 	xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
@@ -2737,7 +2729,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
 
 typedef int (*pfkey_handler)(struct sock *sk, struct sk_buff *skb,
 			     const struct sadb_msg *hdr, void * const *ext_hdrs);
-static pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
+static const pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
 	[SADB_RESERVED]		= pfkey_reserved,
 	[SADB_GETSPI]		= pfkey_getspi,
 	[SADB_UPDATE]		= pfkey_add,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 43dd752..973594b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -395,9 +395,13 @@ void sta_set_rate_info_tx(struct sta_info *sta,
 		rinfo->nss = ieee80211_rate_get_vht_nss(rate);
 	} else {
 		struct ieee80211_supported_band *sband;
+		int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
+		u16 brate;
+
 		sband = sta->local->hw.wiphy->bands[
 				ieee80211_get_sdata_band(sta->sdata)];
-		rinfo->legacy = sband->bitrates[rate->idx].bitrate;
+		brate = sband->bitrates[rate->idx].bitrate;
+		rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
 	}
 	if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
 		rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
@@ -422,11 +426,13 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
 		rinfo->mcs = sta->last_rx_rate_idx;
 	} else {
 		struct ieee80211_supported_band *sband;
+		int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
+		u16 brate;
 
 		sband = sta->local->hw.wiphy->bands[
 				ieee80211_get_sdata_band(sta->sdata)];
-		rinfo->legacy =
-			sband->bitrates[sta->last_rx_rate_idx].bitrate;
+		brate = sband->bitrates[sta->last_rx_rate_idx].bitrate;
+		rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
 	}
 
 	if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
@@ -1192,8 +1198,6 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 				struct station_parameters *params)
 {
 	int ret = 0;
-	u32 rates;
-	int i, j;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
@@ -1286,16 +1290,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 		sta->listen_interval = params->listen_interval;
 
 	if (params->supported_rates) {
-		rates = 0;
-
-		for (i = 0; i < params->supported_rates_len; i++) {
-			int rate = (params->supported_rates[i] & 0x7f) * 5;
-			for (j = 0; j < sband->n_bitrates; j++) {
-				if (sband->bitrates[j].bitrate == rate)
-					rates |= BIT(j);
-			}
-		}
-		sta->sta.supp_rates[band] = rates;
+		ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
+					 sband, params->supported_rates,
+					 params->supported_rates_len,
+					 &sta->sta.supp_rates[band]);
 	}
 
 	if (params->ht_capa)
@@ -1958,18 +1956,11 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 	}
 
 	if (params->basic_rates) {
-		int i, j;
-		u32 rates = 0;
-		struct ieee80211_supported_band *sband = wiphy->bands[band];
-
-		for (i = 0; i < params->basic_rates_len; i++) {
-			int rate = (params->basic_rates[i] & 0x7f) * 5;
-			for (j = 0; j < sband->n_bitrates; j++) {
-				if (sband->bitrates[j].bitrate == rate)
-					rates |= BIT(j);
-			}
-		}
-		sdata->vif.bss_conf.basic_rates = rates;
+		ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
+					 wiphy->bands[band],
+					 params->basic_rates,
+					 params->basic_rates_len,
+					 &sdata->vif.bss_conf.basic_rates);
 		changed |= BSS_CHANGED_BASIC_RATES;
 	}
 
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index f83534f..529bf58 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -19,13 +19,14 @@
 #include "ieee80211_i.h"
 #include "rate.h"
 
-static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata,
+static void __check_htcap_disable(struct ieee80211_ht_cap *ht_capa,
+				  struct ieee80211_ht_cap *ht_capa_mask,
 				  struct ieee80211_sta_ht_cap *ht_cap,
 				  u16 flag)
 {
 	__le16 le_flag = cpu_to_le16(flag);
-	if (sdata->u.mgd.ht_capa_mask.cap_info & le_flag) {
-		if (!(sdata->u.mgd.ht_capa.cap_info & le_flag))
+	if (ht_capa_mask->cap_info & le_flag) {
+		if (!(ht_capa->cap_info & le_flag))
 			ht_cap->cap &= ~flag;
 	}
 }
@@ -33,13 +34,30 @@ static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata,
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 				     struct ieee80211_sta_ht_cap *ht_cap)
 {
-	u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask);
-	u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask);
+	struct ieee80211_ht_cap *ht_capa, *ht_capa_mask;
+	u8 *scaps, *smask;
 	int i;
 
 	if (!ht_cap->ht_supported)
 		return;
 
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_STATION:
+		ht_capa = &sdata->u.mgd.ht_capa;
+		ht_capa_mask = &sdata->u.mgd.ht_capa_mask;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ht_capa = &sdata->u.ibss.ht_capa;
+		ht_capa_mask = &sdata->u.ibss.ht_capa_mask;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	scaps = (u8 *)(&ht_capa->mcs.rx_mask);
+	smask = (u8 *)(&ht_capa_mask->mcs.rx_mask);
+
 	/* NOTE:  If you add more over-rides here, update register_hw
 	 * ht_capa_mod_msk logic in main.c as well.
 	 * And, if this method can ever change ht_cap.ht_supported, fix
@@ -55,28 +73,32 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 	}
 
 	/* Force removal of HT-40 capabilities? */
-	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40);
-	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40);
+	__check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
+			      IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+	__check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
+			      IEEE80211_HT_CAP_SGI_40);
 
 	/* Allow user to disable SGI-20 (SGI-40 is handled above) */
-	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_20);
+	__check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
+			      IEEE80211_HT_CAP_SGI_20);
 
 	/* Allow user to disable the max-AMSDU bit. */
-	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU);
+	__check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
+			      IEEE80211_HT_CAP_MAX_AMSDU);
 
 	/* Allow user to decrease AMPDU factor */
-	if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+	if (ht_capa_mask->ampdu_params_info &
 	    IEEE80211_HT_AMPDU_PARM_FACTOR) {
-		u8 n = sdata->u.mgd.ht_capa.ampdu_params_info
-			& IEEE80211_HT_AMPDU_PARM_FACTOR;
+		u8 n = ht_capa->ampdu_params_info &
+		       IEEE80211_HT_AMPDU_PARM_FACTOR;
 		if (n < ht_cap->ampdu_factor)
 			ht_cap->ampdu_factor = n;
 	}
 
 	/* Allow the user to increase AMPDU density. */
-	if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+	if (ht_capa_mask->ampdu_params_info &
 	    IEEE80211_HT_AMPDU_PARM_DENSITY) {
-		u8 n = (sdata->u.mgd.ht_capa.ampdu_params_info &
+		u8 n = (ht_capa->ampdu_params_info &
 			IEEE80211_HT_AMPDU_PARM_DENSITY)
 			>> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
 		if (n > ht_cap->ampdu_density)
@@ -112,7 +134,8 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 	 * we advertised a restricted capability set to. Override
 	 * our own capabilities and then use those below.
 	 */
-	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+	if ((sdata->vif.type == NL80211_IFTYPE_STATION ||
+	     sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
 	    !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
 		ieee80211_apply_htcap_overrides(sdata, &own_cap);
 
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index ea7b9c2..5e6836c 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -43,16 +43,18 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 	struct ieee80211_local *local = sdata->local;
-	int rates, i;
+	int rates_n = 0, i, ri;
 	struct ieee80211_mgmt *mgmt;
 	u8 *pos;
 	struct ieee80211_supported_band *sband;
 	struct cfg80211_bss *bss;
-	u32 bss_change;
-	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+	u32 bss_change, rate_flags, rates = 0, rates_added = 0;
 	struct cfg80211_chan_def chandef;
+	enum nl80211_bss_scan_width scan_width;
+	bool have_higher_than_11mbit = false;
 	struct beacon_data *presp;
 	int frame_len;
+	int shift;
 
 	sdata_assert_lock(sdata);
 
@@ -83,6 +85,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
 	chandef = ifibss->chandef;
 	if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
+		if (chandef.width == NL80211_CHAN_WIDTH_5 ||
+		    chandef.width == NL80211_CHAN_WIDTH_10 ||
+		    chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+		    chandef.width == NL80211_CHAN_WIDTH_20) {
+			sdata_info(sdata,
+				   "Failed to join IBSS, beacons forbidden\n");
+			return;
+		}
 		chandef.width = NL80211_CHAN_WIDTH_20;
 		chandef.center_freq1 = chan->center_freq;
 	}
@@ -99,6 +109,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	memcpy(ifibss->bssid, bssid, ETH_ALEN);
 
 	sband = local->hw.wiphy->bands[chan->band];
+	shift = ieee80211_vif_get_shift(&sdata->vif);
 
 	/* Build IBSS probe response */
 	frame_len = sizeof(struct ieee80211_hdr_3addr) +
@@ -134,15 +145,33 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	memcpy(pos, ifibss->ssid, ifibss->ssid_len);
 	pos += ifibss->ssid_len;
 
-	rates = min_t(int, 8, sband->n_bitrates);
+	rate_flags = ieee80211_chandef_rate_flags(&chandef);
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+		if (sband->bitrates[i].bitrate > 110)
+			have_higher_than_11mbit = true;
+
+		rates |= BIT(i);
+		rates_n++;
+	}
+
 	*pos++ = WLAN_EID_SUPP_RATES;
-	*pos++ = rates;
-	for (i = 0; i < rates; i++) {
-		int rate = sband->bitrates[i].bitrate;
+	*pos++ = min_t(int, 8, rates_n);
+	for (ri = 0; ri < sband->n_bitrates; ri++) {
+		int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate,
+					5 * (1 << shift));
 		u8 basic = 0;
-		if (basic_rates & BIT(i))
+		if (!(rates & BIT(ri)))
+			continue;
+
+		if (basic_rates & BIT(ri))
 			basic = 0x80;
-		*pos++ = basic | (u8) (rate / 5);
+		*pos++ = basic | (u8) rate;
+		if (++rates_added == 8) {
+			ri++; /* continue at next rate for EXT_SUPP_RATES */
+			break;
+		}
 	}
 
 	if (sband->band == IEEE80211_BAND_2GHZ) {
@@ -157,15 +186,20 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	*pos++ = 0;
 	*pos++ = 0;
 
-	if (sband->n_bitrates > 8) {
+	/* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */
+	if (rates_n > 8) {
 		*pos++ = WLAN_EID_EXT_SUPP_RATES;
-		*pos++ = sband->n_bitrates - 8;
-		for (i = 8; i < sband->n_bitrates; i++) {
-			int rate = sband->bitrates[i].bitrate;
+		*pos++ = rates_n - 8;
+		for (; ri < sband->n_bitrates; ri++) {
+			int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate,
+						5 * (1 << shift));
 			u8 basic = 0;
-			if (basic_rates & BIT(i))
+			if (!(rates & BIT(ri)))
+				continue;
+
+			if (basic_rates & BIT(ri))
 				basic = 0x80;
-			*pos++ = basic | (u8) (rate / 5);
+			*pos++ = basic | (u8) rate;
 		}
 	}
 
@@ -179,8 +213,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	    chandef.width != NL80211_CHAN_WIDTH_5 &&
 	    chandef.width != NL80211_CHAN_WIDTH_10 &&
 	    sband->ht_cap.ht_supported) {
-		pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
-						sband->ht_cap.cap);
+		struct ieee80211_sta_ht_cap ht_cap;
+
+		memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
+		ieee80211_apply_htcap_overrides(sdata, &ht_cap);
+
+		pos = ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap);
 		/*
 		 * Note: According to 802.11n-2009 9.13.3.1, HT Protection
 		 * field and RIFS Mode are reserved in IBSS mode, therefore
@@ -236,18 +274,26 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	sdata->vif.bss_conf.use_short_slot = chan->band == IEEE80211_BAND_5GHZ;
 	bss_change |= BSS_CHANGED_ERP_SLOT;
 
+	/* cf. IEEE 802.11 9.2.12 */
+	if (chan->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit)
+		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
+	else
+		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
+
 	sdata->vif.bss_conf.ibss_joined = true;
 	sdata->vif.bss_conf.ibss_creator = creator;
 	ieee80211_bss_info_change_notify(sdata, bss_change);
 
-	ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
+	ieee80211_set_wmm_default(sdata, true);
 
 	ifibss->state = IEEE80211_IBSS_MLME_JOINED;
 	mod_timer(&ifibss->timer,
 		  round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
 
-	bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan,
-					mgmt, presp->head_len, 0, GFP_KERNEL);
+	scan_width = cfg80211_chandef_to_scan_width(&chandef);
+	bss = cfg80211_inform_bss_width_frame(local->hw.wiphy, chan,
+					      scan_width, mgmt,
+					      presp->head_len, 0, GFP_KERNEL);
 	cfg80211_put_bss(local->hw.wiphy, bss);
 	netif_carrier_on(sdata->dev);
 	cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
@@ -264,6 +310,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	u16 beacon_int = cbss->beacon_interval;
 	const struct cfg80211_bss_ies *ies;
 	u64 tsf;
+	u32 rate_flags;
+	int shift;
 
 	sdata_assert_lock(sdata);
 
@@ -271,15 +319,24 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 		beacon_int = 10;
 
 	sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
+	rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef);
+	shift = ieee80211_vif_get_shift(&sdata->vif);
 
 	basic_rates = 0;
 
 	for (i = 0; i < bss->supp_rates_len; i++) {
-		int rate = (bss->supp_rates[i] & 0x7f) * 5;
+		int rate = bss->supp_rates[i] & 0x7f;
 		bool is_basic = !!(bss->supp_rates[i] & 0x80);
 
 		for (j = 0; j < sband->n_bitrates; j++) {
-			if (sband->bitrates[j].bitrate == rate) {
+			int brate;
+			if ((rate_flags & sband->bitrates[j].flags)
+			    != rate_flags)
+				continue;
+
+			brate = DIV_ROUND_UP(sband->bitrates[j].bitrate,
+					     5 * (1 << shift));
+			if (brate == rate) {
 				if (is_basic)
 					basic_rates |= BIT(j);
 				break;
@@ -335,6 +392,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
 	struct sta_info *sta;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	struct ieee80211_supported_band *sband;
+	enum nl80211_bss_scan_width scan_width;
 	int band;
 
 	/*
@@ -363,6 +421,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
 	if (WARN_ON_ONCE(!chanctx_conf))
 		return NULL;
 	band = chanctx_conf->def.chan->band;
+	scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
 	rcu_read_unlock();
 
 	sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
@@ -376,7 +435,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
 	/* make sure mandatory rates are always added */
 	sband = local->hw.wiphy->bands[band];
 	sta->sta.supp_rates[band] = supp_rates |
-			ieee80211_mandatory_rates(sband);
+			ieee80211_mandatory_rates(sband, scan_width);
 
 	return ieee80211_ibss_finish_sta(sta);
 }
@@ -440,6 +499,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 	u64 beacon_timestamp, rx_timestamp;
 	u32 supp_rates = 0;
 	enum ieee80211_band band = rx_status->band;
+	enum nl80211_bss_scan_width scan_width;
 	struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
 	bool rates_updated = false;
 
@@ -461,16 +521,22 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 		sta = sta_info_get(sdata, mgmt->sa);
 
 		if (elems->supp_rates) {
-			supp_rates = ieee80211_sta_get_rates(local, elems,
+			supp_rates = ieee80211_sta_get_rates(sdata, elems,
 							     band, NULL);
 			if (sta) {
 				u32 prev_rates;
 
 				prev_rates = sta->sta.supp_rates[band];
 				/* make sure mandatory rates are always added */
-				sta->sta.supp_rates[band] = supp_rates |
-					ieee80211_mandatory_rates(sband);
+				scan_width = NL80211_BSS_CHAN_WIDTH_20;
+				if (rx_status->flag & RX_FLAG_5MHZ)
+					scan_width = NL80211_BSS_CHAN_WIDTH_5;
+				if (rx_status->flag & RX_FLAG_10MHZ)
+					scan_width = NL80211_BSS_CHAN_WIDTH_10;
 
+				sta->sta.supp_rates[band] = supp_rates |
+					ieee80211_mandatory_rates(sband,
+								  scan_width);
 				if (sta->sta.supp_rates[band] != prev_rates) {
 					ibss_dbg(sdata,
 						 "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
@@ -585,7 +651,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 			 "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n",
 			 mgmt->bssid);
 		ieee80211_sta_join_ibss(sdata, bss);
-		supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL);
+		supp_rates = ieee80211_sta_get_rates(sdata, elems, band, NULL);
 		ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
 				       supp_rates);
 		rcu_read_unlock();
@@ -604,6 +670,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
 	struct sta_info *sta;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	struct ieee80211_supported_band *sband;
+	enum nl80211_bss_scan_width scan_width;
 	int band;
 
 	/*
@@ -629,6 +696,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
 		return;
 	}
 	band = chanctx_conf->def.chan->band;
+	scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
 	rcu_read_unlock();
 
 	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
@@ -640,7 +708,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
 	/* make sure mandatory rates are always added */
 	sband = local->hw.wiphy->bands[band];
 	sta->sta.supp_rates[band] = supp_rates |
-			ieee80211_mandatory_rates(sband);
+			ieee80211_mandatory_rates(sband, scan_width);
 
 	spin_lock(&ifibss->incomplete_lock);
 	list_add(&sta->list, &ifibss->incomplete_stations);
@@ -679,6 +747,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
 static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+	enum nl80211_bss_scan_width scan_width;
 
 	sdata_assert_lock(sdata);
 
@@ -700,8 +769,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
 	sdata_info(sdata,
 		   "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
 
+	scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
 	ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
-				    NULL);
+				    NULL, scan_width);
 }
 
 static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -751,6 +821,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
 	struct cfg80211_bss *cbss;
 	struct ieee80211_channel *chan = NULL;
 	const u8 *bssid = NULL;
+	enum nl80211_bss_scan_width scan_width;
 	int active_ibss;
 	u16 capability;
 
@@ -799,8 +870,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
 					IEEE80211_SCAN_INTERVAL)) {
 		sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
 
+		scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
 		ieee80211_request_ibss_scan(sdata, ifibss->ssid,
-					    ifibss->ssid_len, chan);
+					    ifibss->ssid_len, chan,
+					    scan_width);
 	} else {
 		int interval = IEEE80211_SCAN_INTERVAL;
 
@@ -1020,6 +1093,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 			struct cfg80211_ibss_params *params)
 {
 	u32 changed = 0;
+	u32 rate_flags;
+	struct ieee80211_supported_band *sband;
+	int i;
 
 	if (params->bssid) {
 		memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
@@ -1030,6 +1106,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 	sdata->u.ibss.privacy = params->privacy;
 	sdata->u.ibss.control_port = params->control_port;
 	sdata->u.ibss.basic_rates = params->basic_rates;
+
+	/* fix basic_rates if channel does not support these rates */
+	rate_flags = ieee80211_chandef_rate_flags(&params->chandef);
+	sband = sdata->local->hw.wiphy->bands[params->chandef.chan->band];
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			sdata->u.ibss.basic_rates &= ~BIT(i);
+	}
 	memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate,
 	       sizeof(params->mcast_rate));
 
@@ -1051,6 +1135,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 	memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
 	sdata->u.ibss.ssid_len = params->ssid_len;
 
+	memcpy(&sdata->u.ibss.ht_capa, &params->ht_capa,
+	       sizeof(sdata->u.ibss.ht_capa));
+	memcpy(&sdata->u.ibss.ht_capa_mask, &params->ht_capa_mask,
+	       sizeof(sdata->u.ibss.ht_capa_mask));
+
 	/*
 	 * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
 	 * reserved, but an HT STA shall protect HT transmissions as though
@@ -1131,6 +1220,11 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
 	presp = rcu_dereference_protected(ifibss->presp,
 					  lockdep_is_held(&sdata->wdev.mtx));
 	RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
+
+	/* on the next join, re-program HT parameters */
+	memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa));
+	memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask));
+
 	sdata->vif.bss_conf.ibss_joined = false;
 	sdata->vif.bss_conf.ibss_creator = false;
 	sdata->vif.bss_conf.enable_beacon = false;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8412a30..3d32df1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -509,6 +509,9 @@ struct ieee80211_if_ibss {
 	/* probe response/beacon for IBSS */
 	struct beacon_data __rcu *presp;
 
+	struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
+	struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
+
 	spinlock_t incomplete_lock;
 	struct list_head incomplete_stations;
 
@@ -809,6 +812,34 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
 	return band;
 }
 
+static inline int
+ieee80211_chandef_get_shift(struct cfg80211_chan_def *chandef)
+{
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_5:
+		return 2;
+	case NL80211_CHAN_WIDTH_10:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline int
+ieee80211_vif_get_shift(struct ieee80211_vif *vif)
+{
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	int shift = 0;
+
+	rcu_read_lock();
+	chanctx_conf = rcu_dereference(vif->chanctx_conf);
+	if (chanctx_conf)
+		shift = ieee80211_chandef_get_shift(&chanctx_conf->def);
+	rcu_read_unlock();
+
+	return shift;
+}
+
 enum sdata_queue_type {
 	IEEE80211_SDATA_QUEUE_TYPE_FRAME	= 0,
 	IEEE80211_SDATA_QUEUE_AGG_START		= 1,
@@ -1026,7 +1057,7 @@ struct ieee80211_local {
 	struct cfg80211_ssid scan_ssid;
 	struct cfg80211_scan_request *int_scan_req;
 	struct cfg80211_scan_request *scan_req, *hw_scan_req;
-	struct ieee80211_channel *scan_channel;
+	struct cfg80211_chan_def scan_chandef;
 	enum ieee80211_band hw_scan_band;
 	int scan_channel_idx;
 	int scan_ies_len;
@@ -1306,7 +1337,8 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 void ieee80211_scan_work(struct work_struct *work);
 int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
 				const u8 *ssid, u8 ssid_len,
-				struct ieee80211_channel *chan);
+				struct ieee80211_channel *chan,
+				enum nl80211_bss_scan_width scan_width);
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
 			   struct cfg80211_scan_request *req);
 void ieee80211_scan_cancel(struct ieee80211_local *local);
@@ -1465,7 +1497,8 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
 u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
 			enum nl80211_iftype type);
 int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
-			     int rate, int erp, int short_preamble);
+			     int rate, int erp, int short_preamble,
+			     int shift);
 void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
 				     struct ieee80211_hdr *hdr, const u8 *tsc,
 				     gfp_t gfp);
@@ -1569,7 +1602,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 			     size_t buffer_len, const u8 *ie, size_t ie_len,
 			     enum ieee80211_band band, u32 rate_mask,
-			     u8 channel);
+			     struct cfg80211_chan_def *chandef);
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 					  u8 *dst, u32 ratemask,
 					  struct ieee80211_channel *chan,
@@ -1582,10 +1615,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      u32 ratemask, bool directed, u32 tx_flags,
 			      struct ieee80211_channel *channel, bool scan);
 
-void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
-				  const size_t supp_rates_len,
-				  const u8 *supp_rates);
-u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
+u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
 			    struct ieee802_11_elems *elems,
 			    enum ieee80211_band band, u32 *basic_rates);
 int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
@@ -1602,6 +1632,9 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 			       u16 prot_mode);
 u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
 			       u32 cap);
+int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
+			     const struct ieee80211_supported_band *sband,
+			     const u8 *srates, int srates_len, u32 *rates);
 int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
 			    struct sk_buff *skb, bool need_basic,
 			    enum ieee80211_band band);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index cc11759..4c41c11 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -54,7 +54,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
 		return false;
 	}
 
-	power = chanctx_conf->def.chan->max_power;
+	power = ieee80211_chandef_max_power(&chanctx_conf->def);
 	rcu_read_unlock();
 
 	if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 091088a..25eb35b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -102,17 +102,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 
 	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 
-	if (local->scan_channel) {
-		chandef.chan = local->scan_channel;
-		/* If scanning on oper channel, use whatever channel-type
-		 * is currently in use.
-		 */
-		if (chandef.chan == local->_oper_chandef.chan) {
-			chandef = local->_oper_chandef;
-		} else {
-			chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
-			chandef.center_freq1 = chandef.chan->center_freq;
-		}
+	if (local->scan_chandef.chan) {
+		chandef = local->scan_chandef;
 	} else if (local->tmp_channel) {
 		chandef.chan = local->tmp_channel;
 		chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -151,7 +142,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 		changed |= IEEE80211_CONF_CHANGE_SMPS;
 	}
 
-	power = chandef.chan->max_power;
+	power = ieee80211_chandef_max_power(&chandef);
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 447f41b..885a5f6 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -62,7 +62,6 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
 			struct ieee802_11_elems *ie)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-	struct ieee80211_local *local = sdata->local;
 	u32 basic_rates = 0;
 	struct cfg80211_chan_def sta_chan_def;
 
@@ -85,7 +84,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
 	     (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
 		return false;
 
-	ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata),
+	ieee80211_sta_get_rates(sdata, ie, ieee80211_get_sdata_band(sdata),
 				&basic_rates);
 
 	if (sdata->vif.bss_conf.basic_rates != basic_rates)
@@ -274,7 +273,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
 	neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS);
 	*pos++ = neighbors << 1;
 	/* Mesh capability */
-	*pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
+	*pos = 0x00;
+	*pos |= ifmsh->mshcfg.dot11MeshForwarding ?
+			IEEE80211_MESHCONF_CAPAB_FORWARDING : 0x00;
 	*pos |= ifmsh->accepting_plinks ?
 			IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
 	/* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 02c05fa..6b65d50 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -379,7 +379,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 	u32 rates, basic_rates = 0, changed = 0;
 
 	sband = local->hw.wiphy->bands[band];
-	rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
+	rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates);
 
 	spin_lock_bh(&sta->lock);
 	sta->last_rx = jiffies;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ae31968..21bccd8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -31,10 +31,12 @@
 #include "led.h"
 
 #define IEEE80211_AUTH_TIMEOUT		(HZ / 5)
+#define IEEE80211_AUTH_TIMEOUT_LONG	(HZ / 2)
 #define IEEE80211_AUTH_TIMEOUT_SHORT	(HZ / 10)
 #define IEEE80211_AUTH_MAX_TRIES	3
 #define IEEE80211_AUTH_WAIT_ASSOC	(HZ * 5)
 #define IEEE80211_ASSOC_TIMEOUT		(HZ / 5)
+#define IEEE80211_ASSOC_TIMEOUT_LONG	(HZ / 2)
 #define IEEE80211_ASSOC_TIMEOUT_SHORT	(HZ / 10)
 #define IEEE80211_ASSOC_MAX_TRIES	3
 
@@ -209,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 			     struct ieee80211_channel *channel,
 			     const struct ieee80211_ht_operation *ht_oper,
 			     const struct ieee80211_vht_operation *vht_oper,
-			     struct cfg80211_chan_def *chandef, bool verbose)
+			     struct cfg80211_chan_def *chandef, bool tracking)
 {
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct cfg80211_chan_def vht_chandef;
 	u32 ht_cfreq, ret;
 
@@ -229,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 	ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
 						  channel->band);
 	/* check that channel matches the right operating channel */
-	if (channel->center_freq != ht_cfreq) {
+	if (!tracking && channel->center_freq != ht_cfreq) {
 		/*
 		 * It's possible that some APs are confused here;
 		 * Netgear WNDR3700 sometimes reports 4 higher than
@@ -237,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 		 * since we look at probe response/beacon data here
 		 * it should be OK.
 		 */
-		if (verbose)
-			sdata_info(sdata,
-				   "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
-				   channel->center_freq, ht_cfreq,
-				   ht_oper->primary_chan, channel->band);
+		sdata_info(sdata,
+			   "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
+			   channel->center_freq, ht_cfreq,
+			   ht_oper->primary_chan, channel->band);
 		ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
 		goto out;
 	}
@@ -295,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 				channel->band);
 		break;
 	default:
-		if (verbose)
+		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
 			sdata_info(sdata,
 				   "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
 				   vht_oper->chan_width);
@@ -304,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 	}
 
 	if (!cfg80211_chandef_valid(&vht_chandef)) {
-		if (verbose)
+		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
 			sdata_info(sdata,
 				   "AP VHT information is invalid, disable VHT\n");
 		ret = IEEE80211_STA_DISABLE_VHT;
@@ -317,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 	}
 
 	if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
-		if (verbose)
+		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
 			sdata_info(sdata,
 				   "AP VHT information doesn't match HT, disable VHT\n");
 		ret = IEEE80211_STA_DISABLE_VHT;
@@ -333,18 +335,27 @@ out:
 	if (ret & IEEE80211_STA_DISABLE_VHT)
 		vht_chandef = *chandef;
 
+	/*
+	 * Ignore the DISABLED flag when we're already connected and only
+	 * tracking the APs beacon for bandwidth changes - otherwise we
+	 * might get disconnected here if we connect to an AP, update our
+	 * regulatory information based on the AP's country IE and the
+	 * information we have is wrong/outdated and disables the channel
+	 * that we're actually using for the connection to the AP.
+	 */
 	while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
-					IEEE80211_CHAN_DISABLED)) {
+					tracking ? 0 :
+						   IEEE80211_CHAN_DISABLED)) {
 		if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
 			ret = IEEE80211_STA_DISABLE_HT |
 			      IEEE80211_STA_DISABLE_VHT;
-			goto out;
+			break;
 		}
 
 		ret |= chandef_downgrade(chandef);
 	}
 
-	if (chandef->width != vht_chandef.width && verbose)
+	if (chandef->width != vht_chandef.width && !tracking)
 		sdata_info(sdata,
 			   "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
 
@@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
 
 	/* calculate new channel (type) based on HT/VHT operation IEs */
 	flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
-					     vht_oper, &chandef, false);
+					     vht_oper, &chandef, true);
 
 	/*
 	 * Downgrade the new channel if we associated with restricted
@@ -478,27 +489,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
 
 /* frame sending functions */
 
-static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
-				      struct ieee80211_supported_band *sband,
-				      u32 *rates)
-{
-	int i, j, count;
-	*rates = 0;
-	count = 0;
-	for (i = 0; i < supp_rates_len; i++) {
-		int rate = (supp_rates[i] & 0x7F) * 5;
-
-		for (j = 0; j < sband->n_bitrates; j++)
-			if (sband->bitrates[j].bitrate == rate) {
-				*rates |= BIT(j);
-				count++;
-				break;
-			}
-	}
-
-	return count;
-}
-
 static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
 				struct sk_buff *skb, u8 ap_ht_param,
 				struct ieee80211_supported_band *sband,
@@ -617,12 +607,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 	struct ieee80211_mgmt *mgmt;
 	u8 *pos, qos_info;
 	size_t offset = 0, noffset;
-	int i, count, rates_len, supp_rates_len;
+	int i, count, rates_len, supp_rates_len, shift;
 	u16 capab;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	struct ieee80211_channel *chan;
-	u32 rates = 0;
+	u32 rate_flags, rates = 0;
 
 	sdata_assert_lock(sdata);
 
@@ -633,8 +623,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 		return;
 	}
 	chan = chanctx_conf->def.chan;
+	rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
 	rcu_read_unlock();
 	sband = local->hw.wiphy->bands[chan->band];
+	shift = ieee80211_vif_get_shift(&sdata->vif);
 
 	if (assoc_data->supp_rates_len) {
 		/*
@@ -643,17 +635,24 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 		 * in the association request (e.g. D-Link DAP 1353 in
 		 * b-only mode)...
 		 */
-		rates_len = ieee80211_compatible_rates(assoc_data->supp_rates,
-						       assoc_data->supp_rates_len,
-						       sband, &rates);
+		rates_len = ieee80211_parse_bitrates(&chanctx_conf->def, sband,
+						     assoc_data->supp_rates,
+						     assoc_data->supp_rates_len,
+						     &rates);
 	} else {
 		/*
 		 * In case AP not provide any supported rates information
 		 * before association, we send information element(s) with
 		 * all rates that we support.
 		 */
-		rates = ~0;
-		rates_len = sband->n_bitrates;
+		rates_len = 0;
+		for (i = 0; i < sband->n_bitrates; i++) {
+			if ((rate_flags & sband->bitrates[i].flags)
+			    != rate_flags)
+				continue;
+			rates |= BIT(i);
+			rates_len++;
+		}
 	}
 
 	skb = alloc_skb(local->hw.extra_tx_headroom +
@@ -730,8 +729,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 	count = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
 		if (BIT(i) & rates) {
-			int rate = sband->bitrates[i].bitrate;
-			*pos++ = (u8) (rate / 5);
+			int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
+						5 * (1 << shift));
+			*pos++ = (u8) rate;
 			if (++count == 8)
 				break;
 		}
@@ -744,8 +744,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 
 		for (i++; i < sband->n_bitrates; i++) {
 			if (BIT(i) & rates) {
-				int rate = sband->bitrates[i].bitrate;
-				*pos++ = (u8) (rate / 5);
+				int rate;
+				rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
+						    5 * (1 << shift));
+				*pos++ = (u8) rate;
 			}
 		}
 	}
@@ -756,7 +758,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 		*pos++ = WLAN_EID_PWR_CAPABILITY;
 		*pos++ = 2;
 		*pos++ = 0; /* min tx power */
-		*pos++ = chan->max_power; /* max tx power */
+		 /* max tx power */
+		*pos++ = ieee80211_chandef_max_power(&chanctx_conf->def);
 
 		/* 2. supported channels */
 		/* TODO: get this in reg domain format */
@@ -2432,15 +2435,16 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
 				u8 *supp_rates, unsigned int supp_rates_len,
 				u32 *rates, u32 *basic_rates,
 				bool *have_higher_than_11mbit,
-				int *min_rate, int *min_rate_index)
+				int *min_rate, int *min_rate_index,
+				int shift, u32 rate_flags)
 {
 	int i, j;
 
 	for (i = 0; i < supp_rates_len; i++) {
-		int rate = (supp_rates[i] & 0x7f) * 5;
+		int rate = supp_rates[i] & 0x7f;
 		bool is_basic = !!(supp_rates[i] & 0x80);
 
-		if (rate > 110)
+		if ((rate * 5 * (1 << shift)) > 110)
 			*have_higher_than_11mbit = true;
 
 		/*
@@ -2456,12 +2460,20 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
 			continue;
 
 		for (j = 0; j < sband->n_bitrates; j++) {
-			if (sband->bitrates[j].bitrate == rate) {
+			struct ieee80211_rate *br;
+			int brate;
+
+			br = &sband->bitrates[j];
+			if ((rate_flags & br->flags) != rate_flags)
+				continue;
+
+			brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
+			if (brate == rate) {
 				*rates |= BIT(j);
 				if (is_basic)
 					*basic_rates |= BIT(j);
-				if (rate < *min_rate) {
-					*min_rate = rate;
+				if ((rate * 5) < *min_rate) {
+					*min_rate = rate * 5;
 					*min_rate_index = j;
 				}
 				break;
@@ -3394,10 +3406,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
 
 	if (tx_flags == 0) {
 		auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
-		ifmgd->auth_data->timeout_started = true;
+		auth_data->timeout_started = true;
 		run_again(sdata, auth_data->timeout);
 	} else {
-		auth_data->timeout_started = false;
+		auth_data->timeout =
+			round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
+		auth_data->timeout_started = true;
+		run_again(sdata, auth_data->timeout);
 	}
 
 	return 0;
@@ -3434,7 +3449,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
 		assoc_data->timeout_started = true;
 		run_again(sdata, assoc_data->timeout);
 	} else {
-		assoc_data->timeout_started = false;
+		assoc_data->timeout =
+			round_jiffies_up(jiffies +
+					 IEEE80211_ASSOC_TIMEOUT_LONG);
+		assoc_data->timeout_started = true;
+		run_again(sdata, assoc_data->timeout);
 	}
 
 	return 0;
@@ -3829,7 +3848,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
 	ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
 						     cbss->channel,
 						     ht_oper, vht_oper,
-						     &chandef, true);
+						     &chandef, false);
 
 	sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
 				      local->rx_chains);
@@ -3884,27 +3903,40 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 		if (!new_sta)
 			return -ENOMEM;
 	}
-
 	if (new_sta) {
 		u32 rates = 0, basic_rates = 0;
 		bool have_higher_than_11mbit;
 		int min_rate = INT_MAX, min_rate_index = -1;
+		struct ieee80211_chanctx_conf *chanctx_conf;
 		struct ieee80211_supported_band *sband;
 		const struct cfg80211_bss_ies *ies;
+		int shift;
+		u32 rate_flags;
 
 		sband = local->hw.wiphy->bands[cbss->channel->band];
 
 		err = ieee80211_prep_channel(sdata, cbss);
 		if (err) {
 			sta_info_free(local, new_sta);
-			return err;
+			return -EINVAL;
+		}
+		shift = ieee80211_vif_get_shift(&sdata->vif);
+
+		rcu_read_lock();
+		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+		if (WARN_ON(!chanctx_conf)) {
+			rcu_read_unlock();
+			return -EINVAL;
 		}
+		rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
+		rcu_read_unlock();
 
 		ieee80211_get_rates(sband, bss->supp_rates,
 				    bss->supp_rates_len,
 				    &rates, &basic_rates,
 				    &have_higher_than_11mbit,
-				    &min_rate, &min_rate_index);
+				    &min_rate, &min_rate_index,
+				    shift, rate_flags);
 
 		/*
 		 * This used to be a workaround for basic rates missing
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 30d58d2..ba63ac8 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -232,37 +232,28 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
 	/* could not find a basic rate; use original selection */
 }
 
-static inline s8
-rate_lowest_non_cck_index(struct ieee80211_supported_band *sband,
-			  struct ieee80211_sta *sta)
+static void __rate_control_send_low(struct ieee80211_hw *hw,
+				    struct ieee80211_supported_band *sband,
+				    struct ieee80211_sta *sta,
+				    struct ieee80211_tx_info *info)
 {
 	int i;
+	u32 rate_flags =
+		ieee80211_chandef_rate_flags(&hw->conf.chandef);
 
+	if ((sband->band == IEEE80211_BAND_2GHZ) &&
+	    (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
+		rate_flags |= IEEE80211_RATE_ERP_G;
+
+	info->control.rates[0].idx = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
-		struct ieee80211_rate *srate = &sband->bitrates[i];
-		if ((srate->bitrate == 10) || (srate->bitrate == 20) ||
-		    (srate->bitrate == 55) || (srate->bitrate == 110))
+		if (!rate_supported(sta, sband->band, i))
 			continue;
 
-		if (rate_supported(sta, sband->band, i))
-			return i;
+		info->control.rates[0].idx = i;
+		break;
 	}
-
-	/* No matching rate found */
-	return 0;
-}
-
-static void __rate_control_send_low(struct ieee80211_hw *hw,
-				    struct ieee80211_supported_band *sband,
-				    struct ieee80211_sta *sta,
-				    struct ieee80211_tx_info *info)
-{
-	if ((sband->band != IEEE80211_BAND_2GHZ) ||
-	    !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
-		info->control.rates[0].idx = rate_lowest_index(sband, sta);
-	else
-		info->control.rates[0].idx =
-			rate_lowest_non_cck_index(sband, sta);
+	WARN_ON_ONCE(i == sband->n_bitrates);
 
 	info->control.rates[0].count =
 		(info->flags & IEEE80211_TX_CTL_NO_ACK) ?
@@ -585,6 +576,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
 	u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
 	bool has_mcs_mask;
 	u32 mask;
+	u32 rate_flags;
 	int i;
 
 	/*
@@ -594,6 +586,12 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
 	 */
 	mask = sdata->rc_rateidx_mask[info->band];
 	has_mcs_mask = sdata->rc_has_mcs_mask[info->band];
+	rate_flags =
+		ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
+	for (i = 0; i < sband->n_bitrates; i++)
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			mask &= ~BIT(i);
+
 	if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask)
 		return;
 
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index d35a5dd..5dedc56 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -66,11 +66,12 @@ static inline void rate_control_rate_init(struct sta_info *sta)
 	}
 
 	sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
-	rcu_read_unlock();
 
 	ieee80211_sta_set_rx_nss(sta);
 
-	ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
+	ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
+			    priv_sta);
+	rcu_read_unlock();
 	set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
 }
 
@@ -81,10 +82,21 @@ static inline void rate_control_rate_update(struct ieee80211_local *local,
 	struct rate_control_ref *ref = local->rate_ctrl;
 	struct ieee80211_sta *ista = &sta->sta;
 	void *priv_sta = sta->rate_ctrl_priv;
+	struct ieee80211_chanctx_conf *chanctx_conf;
+
+	if (ref && ref->ops->rate_update) {
+		rcu_read_lock();
 
-	if (ref && ref->ops->rate_update)
-		ref->ops->rate_update(ref->priv, sband, ista,
-				      priv_sta, changed);
+		chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
+		if (WARN_ON(!chanctx_conf)) {
+			rcu_read_unlock();
+			return;
+		}
+
+		ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def,
+				      ista, priv_sta, changed);
+		rcu_read_unlock();
+	}
 	drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
 }
 
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index e6512e2..8b5f7ef 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -383,14 +383,18 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
 static void
 calc_rate_durations(enum ieee80211_band band,
 		    struct minstrel_rate *d,
-		    struct ieee80211_rate *rate)
+		    struct ieee80211_rate *rate,
+		    struct cfg80211_chan_def *chandef)
 {
 	int erp = !!(rate->flags & IEEE80211_RATE_ERP_G);
+	int shift = ieee80211_chandef_get_shift(chandef);
 
 	d->perfect_tx_time = ieee80211_frame_duration(band, 1200,
-			rate->bitrate, erp, 1);
+			DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1,
+			shift);
 	d->ack_time = ieee80211_frame_duration(band, 10,
-			rate->bitrate, erp, 1);
+			DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1,
+			shift);
 }
 
 static void
@@ -418,21 +422,25 @@ init_sample_table(struct minstrel_sta_info *mi)
 
 static void
 minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
-               struct ieee80211_sta *sta, void *priv_sta)
+		   struct cfg80211_chan_def *chandef,
+		   struct ieee80211_sta *sta, void *priv_sta)
 {
 	struct minstrel_sta_info *mi = priv_sta;
 	struct minstrel_priv *mp = priv;
 	struct ieee80211_rate *ctl_rate;
 	unsigned int i, n = 0;
 	unsigned int t_slot = 9; /* FIXME: get real slot time */
+	u32 rate_flags;
 
 	mi->sta = sta;
 	mi->lowest_rix = rate_lowest_index(sband, sta);
 	ctl_rate = &sband->bitrates[mi->lowest_rix];
 	mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
 				ctl_rate->bitrate,
-				!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
+				!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1,
+				ieee80211_chandef_get_shift(chandef));
 
+	rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
 	memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
 	mi->max_prob_rate = 0;
 
@@ -441,15 +449,22 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
 		unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
 		unsigned int tx_time_single;
 		unsigned int cw = mp->cw_min;
+		int shift;
 
 		if (!rate_supported(sta, sband->band, i))
 			continue;
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+
 		n++;
 		memset(mr, 0, sizeof(*mr));
 
 		mr->rix = i;
-		mr->bitrate = sband->bitrates[i].bitrate / 5;
-		calc_rate_durations(sband->band, mr, &sband->bitrates[i]);
+		shift = ieee80211_chandef_get_shift(chandef);
+		mr->bitrate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
+					   (1 << shift) * 5);
+		calc_rate_durations(sband->band, mr, &sband->bitrates[i],
+				    chandef);
 
 		/* calculate maximum number of retransmissions before
 		 * fallback (based on maximum segment size) */
@@ -547,6 +562,7 @@ minstrel_init_cck_rates(struct minstrel_priv *mp)
 {
 	static const int bitrates[4] = { 10, 20, 55, 110 };
 	struct ieee80211_supported_band *sband;
+	u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
 	int i, j;
 
 	sband = mp->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -559,6 +575,9 @@ minstrel_init_cck_rates(struct minstrel_priv *mp)
 		if (rate->flags & IEEE80211_RATE_ERP_G)
 			continue;
 
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+
 		for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
 			if (rate->bitrate != bitrates[j])
 				continue;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index f5aed96..6156942 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -844,6 +844,7 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 
 static void
 minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
+			struct cfg80211_chan_def *chandef,
                         struct ieee80211_sta *sta, void *priv_sta)
 {
 	struct minstrel_priv *mp = priv;
@@ -869,8 +870,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
 	mi->sta = sta;
 	mi->stats_update = jiffies;
 
-	ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1);
-	mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1) + ack_dur;
+	ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0);
+	mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0);
+	mi->overhead += ack_dur;
 	mi->overhead_rtscts = mi->overhead + 2 * ack_dur;
 
 	mi->avg_ampdu_len = MINSTREL_FRAC(1, 1);
@@ -939,22 +941,25 @@ use_legacy:
 	memset(&msp->legacy, 0, sizeof(msp->legacy));
 	msp->legacy.r = msp->ratelist;
 	msp->legacy.sample_table = msp->sample_table;
-	return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
+	return mac80211_minstrel.rate_init(priv, sband, chandef, sta,
+					   &msp->legacy);
 }
 
 static void
 minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband,
+		      struct cfg80211_chan_def *chandef,
                       struct ieee80211_sta *sta, void *priv_sta)
 {
-	minstrel_ht_update_caps(priv, sband, sta, priv_sta);
+	minstrel_ht_update_caps(priv, sband, chandef, sta, priv_sta);
 }
 
 static void
 minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband,
+			struct cfg80211_chan_def *chandef,
                         struct ieee80211_sta *sta, void *priv_sta,
                         u32 changed)
 {
-	minstrel_ht_update_caps(priv, sband, sta, priv_sta);
+	minstrel_ht_update_caps(priv, sband, chandef, sta, priv_sta);
 }
 
 static void *
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index 502d3ec..958fad0 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -293,6 +293,7 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta,
 
 static void
 rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
+			   struct cfg80211_chan_def *chandef,
 			   struct ieee80211_sta *sta, void *priv_sta)
 {
 	struct rc_pid_sta_info *spinfo = priv_sta;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2c5a79b..6b85f95 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -87,11 +87,13 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
 	int len;
 
 	/* always present fields */
-	len = sizeof(struct ieee80211_radiotap_header) + 9;
+	len = sizeof(struct ieee80211_radiotap_header) + 8;
 
-	/* allocate extra bitmap */
+	/* allocate extra bitmaps */
 	if (status->vendor_radiotap_len)
 		len += 4;
+	if (status->chains)
+		len += 4 * hweight8(status->chains);
 
 	if (ieee80211_have_rx_timestamp(status)) {
 		len = ALIGN(len, 8);
@@ -100,6 +102,10 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
 		len += 1;
 
+	/* antenna field, if we don't have per-chain info */
+	if (!status->chains)
+		len += 1;
+
 	/* padding for RX_FLAGS if necessary */
 	len = ALIGN(len, 2);
 
@@ -116,6 +122,11 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
 		len += 12;
 	}
 
+	if (status->chains) {
+		/* antenna and antenna signal fields */
+		len += 2 * hweight8(status->chains);
+	}
+
 	if (status->vendor_radiotap_len) {
 		if (WARN_ON_ONCE(status->vendor_radiotap_align == 0))
 			status->vendor_radiotap_align = 1;
@@ -145,8 +156,12 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_radiotap_header *rthdr;
 	unsigned char *pos;
+	__le32 *it_present;
+	u32 it_present_val;
 	u16 rx_flags = 0;
-	int mpdulen;
+	u16 channel_flags = 0;
+	int mpdulen, chain;
+	unsigned long chains = status->chains;
 
 	mpdulen = skb->len;
 	if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
@@ -154,25 +169,39 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 
 	rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
 	memset(rthdr, 0, rtap_len);
+	it_present = &rthdr->it_present;
 
 	/* radiotap header, set always present flags */
-	rthdr->it_present =
-		cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
-			    (1 << IEEE80211_RADIOTAP_CHANNEL) |
-			    (1 << IEEE80211_RADIOTAP_ANTENNA) |
-			    (1 << IEEE80211_RADIOTAP_RX_FLAGS));
 	rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len);
+	it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) |
+			 BIT(IEEE80211_RADIOTAP_CHANNEL) |
+			 BIT(IEEE80211_RADIOTAP_RX_FLAGS);
 
-	pos = (unsigned char *)(rthdr + 1);
+	if (!status->chains)
+		it_present_val |= BIT(IEEE80211_RADIOTAP_ANTENNA);
+
+	for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
+		it_present_val |=
+			BIT(IEEE80211_RADIOTAP_EXT) |
+			BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE);
+		put_unaligned_le32(it_present_val, it_present);
+		it_present++;
+		it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) |
+				 BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
+	}
 
 	if (status->vendor_radiotap_len) {
-		rthdr->it_present |=
-			cpu_to_le32(BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE)) |
-			cpu_to_le32(BIT(IEEE80211_RADIOTAP_EXT));
-		put_unaligned_le32(status->vendor_radiotap_bitmap, pos);
-		pos += 4;
+		it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
+				  BIT(IEEE80211_RADIOTAP_EXT);
+		put_unaligned_le32(it_present_val, it_present);
+		it_present++;
+		it_present_val = status->vendor_radiotap_bitmap;
 	}
 
+	put_unaligned_le32(it_present_val, it_present);
+
+	pos = (void *)(it_present + 1);
+
 	/* the order of the following fields is important */
 
 	/* IEEE80211_RADIOTAP_TSFT */
@@ -207,28 +236,35 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 		 */
 		*pos = 0;
 	} else {
+		int shift = 0;
 		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
-		*pos = rate->bitrate / 5;
+		if (status->flag & RX_FLAG_10MHZ)
+			shift = 1;
+		else if (status->flag & RX_FLAG_5MHZ)
+			shift = 2;
+		*pos = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift));
 	}
 	pos++;
 
 	/* IEEE80211_RADIOTAP_CHANNEL */
 	put_unaligned_le16(status->freq, pos);
 	pos += 2;
+	if (status->flag & RX_FLAG_10MHZ)
+		channel_flags |= IEEE80211_CHAN_HALF;
+	else if (status->flag & RX_FLAG_5MHZ)
+		channel_flags |= IEEE80211_CHAN_QUARTER;
+
 	if (status->band == IEEE80211_BAND_5GHZ)
-		put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
-				   pos);
+		channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ;
 	else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
-		put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
-				   pos);
+		channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
 	else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
-		put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
-				   pos);
+		channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ;
 	else if (rate)
-		put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
-				   pos);
+		channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ;
 	else
-		put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos);
+		channel_flags |= IEEE80211_CHAN_2GHZ;
+	put_unaligned_le16(channel_flags, pos);
 	pos += 2;
 
 	/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
@@ -242,9 +278,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 
 	/* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
 
-	/* IEEE80211_RADIOTAP_ANTENNA */
-	*pos = status->antenna;
-	pos++;
+	if (!status->chains) {
+		/* IEEE80211_RADIOTAP_ANTENNA */
+		*pos = status->antenna;
+		pos++;
+	}
 
 	/* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
 
@@ -341,6 +379,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 		pos += 2;
 	}
 
+	for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
+		*pos++ = status->chain_signal[chain];
+		*pos++ = chain;
+	}
+
 	if (status->vendor_radiotap_len) {
 		/* ensure 2 byte alignment for the vendor field as required */
 		if ((pos - (u8 *)rthdr) & 1)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 1b122a7..08afe74 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -66,6 +66,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 	struct cfg80211_bss *cbss;
 	struct ieee80211_bss *bss;
 	int clen, srlen;
+	enum nl80211_bss_scan_width scan_width;
 	s32 signal = 0;
 
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
@@ -73,8 +74,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
 		signal = (rx_status->signal * 100) / local->hw.max_signal;
 
-	cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
-					 mgmt, len, signal, GFP_ATOMIC);
+	scan_width = NL80211_BSS_CHAN_WIDTH_20;
+	if (rx_status->flag & RX_FLAG_5MHZ)
+		scan_width = NL80211_BSS_CHAN_WIDTH_5;
+	if (rx_status->flag & RX_FLAG_10MHZ)
+		scan_width = NL80211_BSS_CHAN_WIDTH_10;
+
+	cbss = cfg80211_inform_bss_width_frame(local->hw.wiphy, channel,
+					       scan_width, mgmt, len, signal,
+					       GFP_ATOMIC);
 	if (!cbss)
 		return NULL;
 
@@ -204,10 +212,29 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
 		ieee80211_rx_bss_put(local, bss);
 }
 
+static void
+ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef,
+			       enum nl80211_bss_scan_width scan_width)
+{
+	memset(chandef, 0, sizeof(*chandef));
+	switch (scan_width) {
+	case NL80211_BSS_CHAN_WIDTH_5:
+		chandef->width = NL80211_CHAN_WIDTH_5;
+		break;
+	case NL80211_BSS_CHAN_WIDTH_10:
+		chandef->width = NL80211_CHAN_WIDTH_10;
+		break;
+	default:
+		chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+		break;
+	}
+}
+
 /* return false if no more work */
 static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 {
 	struct cfg80211_scan_request *req = local->scan_req;
+	struct cfg80211_chan_def chandef;
 	enum ieee80211_band band;
 	int i, ielen, n_chans;
 
@@ -229,11 +256,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 	} while (!n_chans);
 
 	local->hw_scan_req->n_channels = n_chans;
+	ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
 
 	ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
 					 local->hw_scan_ies_bufsize,
 					 req->ie, req->ie_len, band,
-					 req->rates[band], 0);
+					 req->rates[band], &chandef);
 	local->hw_scan_req->ie_len = ielen;
 	local->hw_scan_req->no_cck = req->no_cck;
 
@@ -280,7 +308,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 	rcu_assign_pointer(local->scan_sdata, NULL);
 
 	local->scanning = 0;
-	local->scan_channel = NULL;
+	local->scan_chandef.chan = NULL;
 
 	/* Set power back to normal operating levels. */
 	ieee80211_hw_config(local, 0);
@@ -615,11 +643,34 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
 {
 	int skip;
 	struct ieee80211_channel *chan;
+	enum nl80211_bss_scan_width oper_scan_width;
 
 	skip = 0;
 	chan = local->scan_req->channels[local->scan_channel_idx];
 
-	local->scan_channel = chan;
+	local->scan_chandef.chan = chan;
+	local->scan_chandef.center_freq1 = chan->center_freq;
+	local->scan_chandef.center_freq2 = 0;
+	switch (local->scan_req->scan_width) {
+	case NL80211_BSS_CHAN_WIDTH_5:
+		local->scan_chandef.width = NL80211_CHAN_WIDTH_5;
+		break;
+	case NL80211_BSS_CHAN_WIDTH_10:
+		local->scan_chandef.width = NL80211_CHAN_WIDTH_10;
+		break;
+	case NL80211_BSS_CHAN_WIDTH_20:
+		/* If scanning on oper channel, use whatever channel-type
+		 * is currently in use.
+		 */
+		oper_scan_width = cfg80211_chandef_to_scan_width(
+					&local->_oper_chandef);
+		if (chan == local->_oper_chandef.chan &&
+		    oper_scan_width == local->scan_req->scan_width)
+			local->scan_chandef = local->_oper_chandef;
+		else
+			local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+		break;
+	}
 
 	if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
 		skip = 1;
@@ -659,7 +710,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
 					 unsigned long *next_delay)
 {
 	/* switch back to the operating channel */
-	local->scan_channel = NULL;
+	local->scan_chandef.chan = NULL;
 	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
 	/* disable PS */
@@ -801,7 +852,8 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
 
 int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
 				const u8 *ssid, u8 ssid_len,
-				struct ieee80211_channel *chan)
+				struct ieee80211_channel *chan,
+				enum nl80211_bss_scan_width scan_width)
 {
 	struct ieee80211_local *local = sdata->local;
 	int ret = -EBUSY;
@@ -851,6 +903,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
 
 	local->int_scan_req->ssids = &local->scan_ssid;
 	local->int_scan_req->n_ssids = 1;
+	local->int_scan_req->scan_width = scan_width;
 	memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
 	local->int_scan_req->ssids[0].ssid_len = ssid_len;
 
@@ -912,6 +965,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_sched_scan_ies sched_scan_ies = {};
+	struct cfg80211_chan_def chandef;
 	int ret, i, iebufsz;
 
 	iebufsz = 2 + IEEE80211_MAX_SSID_LEN +
@@ -939,10 +993,12 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
 			goto out_free;
 		}
 
+		ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
+
 		sched_scan_ies.len[i] =
 			ieee80211_build_preq_ies(local, sched_scan_ies.ie[i],
 						 iebufsz, req->ie, req->ie_len,
-						 i, (u32) -1, 0);
+						 i, (u32) -1, &chandef);
 	}
 
 	ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 4343920..6ad4c14 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -252,9 +252,10 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
 	return len;
 }
 
-static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
-					     *sband, struct sk_buff *skb,
-					     int retry_count, int rtap_len)
+static void
+ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
+				 struct sk_buff *skb, int retry_count,
+				 int rtap_len, int shift)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -280,8 +281,11 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
 	/* IEEE80211_RADIOTAP_RATE */
 	if (info->status.rates[0].idx >= 0 &&
 	    !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) {
+		u16 rate;
+
 		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
-		*pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5;
+		rate = sband->bitrates[info->status.rates[0].idx].bitrate;
+		*pos = DIV_ROUND_UP(rate, 5 * (1 << shift));
 		/* padding for tx flags */
 		pos += 2;
 	}
@@ -424,6 +428,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 	bool acked;
 	struct ieee80211_bar *bar;
 	int rtap_len;
+	int shift = 0;
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
 		if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -458,6 +463,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 		if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
 			continue;
 
+		shift = ieee80211_vif_get_shift(&sta->sdata->vif);
+
 		if (info->flags & IEEE80211_TX_STATUS_EOSP)
 			clear_sta_flag(sta, WLAN_STA_SP);
 
@@ -624,7 +631,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 		dev_kfree_skb(skb);
 		return;
 	}
-	ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len);
+	ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len,
+					 shift);
 
 	/* XXX: is this sufficient for BPF? */
 	skb_set_mac_header(skb, 0);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4105d0c..be4d3ca 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -40,12 +40,22 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 				 struct sk_buff *skb, int group_addr,
 				 int next_frag_len)
 {
-	int rate, mrate, erp, dur, i;
+	int rate, mrate, erp, dur, i, shift = 0;
 	struct ieee80211_rate *txrate;
 	struct ieee80211_local *local = tx->local;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	u32 rate_flags = 0;
+
+	rcu_read_lock();
+	chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf);
+	if (chanctx_conf) {
+		shift = ieee80211_chandef_get_shift(&chanctx_conf->def);
+		rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
+	}
+	rcu_read_unlock();
 
 	/* assume HW handles this */
 	if (tx->rate.flags & IEEE80211_TX_RC_MCS)
@@ -122,8 +132,11 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 		if (r->bitrate > txrate->bitrate)
 			break;
 
+		if ((rate_flags & r->flags) != rate_flags)
+			continue;
+
 		if (tx->sdata->vif.bss_conf.basic_rates & BIT(i))
-			rate = r->bitrate;
+			rate = DIV_ROUND_UP(r->bitrate, 1 << shift);
 
 		switch (sband->band) {
 		case IEEE80211_BAND_2GHZ: {
@@ -150,7 +163,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 	if (rate == -1) {
 		/* No matching basic rate found; use highest suitable mandatory
 		 * PHY rate */
-		rate = mrate;
+		rate = DIV_ROUND_UP(mrate, 1 << shift);
 	}
 
 	/* Don't calculate ACKs for QoS Frames with NoAck Policy set */
@@ -162,7 +175,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 		 * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
 		 * to closest integer */
 		dur = ieee80211_frame_duration(sband->band, 10, rate, erp,
-				tx->sdata->vif.bss_conf.use_short_preamble);
+				tx->sdata->vif.bss_conf.use_short_preamble,
+				shift);
 
 	if (next_frag_len) {
 		/* Frame is fragmented: duration increases with time needed to
@@ -171,7 +185,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 		/* next fragment */
 		dur += ieee80211_frame_duration(sband->band, next_frag_len,
 				txrate->bitrate, erp,
-				tx->sdata->vif.bss_conf.use_short_preamble);
+				tx->sdata->vif.bss_conf.use_short_preamble,
+				shift);
 	}
 
 	return cpu_to_le16(dur);
@@ -1257,6 +1272,10 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
 
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_MONITOR:
+		if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) {
+			vif = &sdata->vif;
+			break;
+		}
 		sdata = rcu_dereference(local->monitor_sdata);
 		if (sdata) {
 			vif = &sdata->vif;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2265445..d23c5a7 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -107,7 +107,8 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
 }
 
 int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
-			     int rate, int erp, int short_preamble)
+			     int rate, int erp, int short_preamble,
+			     int shift)
 {
 	int dur;
 
@@ -118,6 +119,9 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
 	 *
 	 * rate is in 100 kbps, so divident is multiplied by 10 in the
 	 * DIV_ROUND_UP() operations.
+	 *
+	 * shift may be 2 for 5 MHz channels or 1 for 10 MHz channels, and
+	 * is assumed to be 0 otherwise.
 	 */
 
 	if (band == IEEE80211_BAND_5GHZ || erp) {
@@ -130,13 +134,23 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
 		 * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
 		 *
 		 * T_SYM = 4 usec
-		 * 802.11a - 17.5.2: aSIFSTime = 16 usec
+		 * 802.11a - 18.5.2: aSIFSTime = 16 usec
 		 * 802.11g - 19.8.4: aSIFSTime = 10 usec +
 		 *	signal ext = 6 usec
 		 */
 		dur = 16; /* SIFS + signal ext */
-		dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
-		dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
+		dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */
+		dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */
+
+		/* IEEE 802.11-2012 18.3.2.4: all values above are:
+		 *  * times 4 for 5 MHz
+		 *  * times 2 for 10 MHz
+		 */
+		dur *= 1 << shift;
+
+		/* rates should already consider the channel bandwidth,
+		 * don't apply divisor again.
+		 */
 		dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
 					4 * rate); /* T_SYM x N_SYM */
 	} else {
@@ -168,7 +182,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
 {
 	struct ieee80211_sub_if_data *sdata;
 	u16 dur;
-	int erp;
+	int erp, shift = 0;
 	bool short_preamble = false;
 
 	erp = 0;
@@ -177,10 +191,11 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
 		short_preamble = sdata->vif.bss_conf.use_short_preamble;
 		if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
 			erp = rate->flags & IEEE80211_RATE_ERP_G;
+		shift = ieee80211_vif_get_shift(vif);
 	}
 
 	dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp,
-				       short_preamble);
+				       short_preamble, shift);
 
 	return cpu_to_le16(dur);
 }
@@ -194,7 +209,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
 	struct ieee80211_rate *rate;
 	struct ieee80211_sub_if_data *sdata;
 	bool short_preamble;
-	int erp;
+	int erp, shift = 0, bitrate;
 	u16 dur;
 	struct ieee80211_supported_band *sband;
 
@@ -210,17 +225,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
 		short_preamble = sdata->vif.bss_conf.use_short_preamble;
 		if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
 			erp = rate->flags & IEEE80211_RATE_ERP_G;
+		shift = ieee80211_vif_get_shift(vif);
 	}
 
+	bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift);
+
 	/* CTS duration */
-	dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate,
-				       erp, short_preamble);
+	dur = ieee80211_frame_duration(sband->band, 10, bitrate,
+				       erp, short_preamble, shift);
 	/* Data frame duration */
-	dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
-					erp, short_preamble);
+	dur += ieee80211_frame_duration(sband->band, frame_len, bitrate,
+					erp, short_preamble, shift);
 	/* ACK duration */
-	dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
-					erp, short_preamble);
+	dur += ieee80211_frame_duration(sband->band, 10, bitrate,
+					erp, short_preamble, shift);
 
 	return cpu_to_le16(dur);
 }
@@ -235,7 +253,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
 	struct ieee80211_rate *rate;
 	struct ieee80211_sub_if_data *sdata;
 	bool short_preamble;
-	int erp;
+	int erp, shift = 0, bitrate;
 	u16 dur;
 	struct ieee80211_supported_band *sband;
 
@@ -250,15 +268,18 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
 		short_preamble = sdata->vif.bss_conf.use_short_preamble;
 		if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
 			erp = rate->flags & IEEE80211_RATE_ERP_G;
+		shift = ieee80211_vif_get_shift(vif);
 	}
 
+	bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift);
+
 	/* Data frame duration */
-	dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
-				       erp, short_preamble);
+	dur = ieee80211_frame_duration(sband->band, frame_len, bitrate,
+				       erp, short_preamble, shift);
 	if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
 		/* ACK duration */
-		dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
-						erp, short_preamble);
+		dur += ieee80211_frame_duration(sband->band, 10, bitrate,
+						erp, short_preamble, shift);
 	}
 
 	return cpu_to_le16(dur);
@@ -1052,32 +1073,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 	}
 }
 
-void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
-				  const size_t supp_rates_len,
-				  const u8 *supp_rates)
-{
-	struct ieee80211_chanctx_conf *chanctx_conf;
-	int i, have_higher_than_11mbit = 0;
-
-	/* cf. IEEE 802.11 9.2.12 */
-	for (i = 0; i < supp_rates_len; i++)
-		if ((supp_rates[i] & 0x7f) * 5 > 110)
-			have_higher_than_11mbit = 1;
-
-	rcu_read_lock();
-	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-
-	if (chanctx_conf &&
-	    chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ &&
-	    have_higher_than_11mbit)
-		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
-	else
-		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
-	rcu_read_unlock();
-
-	ieee80211_set_wmm_default(sdata, true);
-}
-
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 			 u16 transaction, u16 auth_alg, u16 status,
 			 const u8 *extra, size_t extra_len, const u8 *da,
@@ -1162,7 +1157,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 			     size_t buffer_len, const u8 *ie, size_t ie_len,
 			     enum ieee80211_band band, u32 rate_mask,
-			     u8 channel)
+			     struct cfg80211_chan_def *chandef)
 {
 	struct ieee80211_supported_band *sband;
 	u8 *pos = buffer, *end = buffer + buffer_len;
@@ -1171,16 +1166,26 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 	u8 rates[32];
 	int num_rates;
 	int ext_rates_len;
+	int shift;
+	u32 rate_flags;
 
 	sband = local->hw.wiphy->bands[band];
 	if (WARN_ON_ONCE(!sband))
 		return 0;
 
+	rate_flags = ieee80211_chandef_rate_flags(chandef);
+	shift = ieee80211_chandef_get_shift(chandef);
+
 	num_rates = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
 		if ((BIT(i) & rate_mask) == 0)
 			continue; /* skip rate */
-		rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5);
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+
+		rates[num_rates++] =
+			(u8) DIV_ROUND_UP(sband->bitrates[i].bitrate,
+					  (1 << shift) * 5);
 	}
 
 	supp_rates_len = min_t(int, num_rates, 8);
@@ -1220,12 +1225,13 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 		pos += ext_rates_len;
 	}
 
-	if (channel && sband->band == IEEE80211_BAND_2GHZ) {
+	if (chandef->chan && sband->band == IEEE80211_BAND_2GHZ) {
 		if (end - pos < 3)
 			goto out_err;
 		*pos++ = WLAN_EID_DS_PARAMS;
 		*pos++ = 1;
-		*pos++ = channel;
+		*pos++ = ieee80211_frequency_to_channel(
+				chandef->chan->center_freq);
 	}
 
 	/* insert custom IEs that go before HT */
@@ -1290,9 +1296,9 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 					  bool directed)
 {
 	struct ieee80211_local *local = sdata->local;
+	struct cfg80211_chan_def chandef;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *mgmt;
-	u8 chan_no;
 	int ies_len;
 
 	/*
@@ -1300,10 +1306,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 	 * in order to maximize the chance that we get a response.  Some
 	 * badly-behaved APs don't respond when this parameter is included.
 	 */
+	chandef.width = sdata->vif.bss_conf.chandef.width;
 	if (directed)
-		chan_no = 0;
+		chandef.chan = NULL;
 	else
-		chan_no = ieee80211_frequency_to_channel(chan->center_freq);
+		chandef.chan = chan;
 
 	skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
 				     ssid, ssid_len, 100 + ie_len);
@@ -1313,7 +1320,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 	ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb),
 					   skb_tailroom(skb),
 					   ie, ie_len, chan->band,
-					   ratemask, chan_no);
+					   ratemask, &chandef);
 	skb_put(skb, ies_len);
 
 	if (dst) {
@@ -1347,16 +1354,19 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 	}
 }
 
-u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
+u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
 			    struct ieee802_11_elems *elems,
 			    enum ieee80211_band band, u32 *basic_rates)
 {
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_rate *bitrates;
 	size_t num_rates;
-	u32 supp_rates;
-	int i, j;
-	sband = local->hw.wiphy->bands[band];
+	u32 supp_rates, rate_flags;
+	int i, j, shift;
+	sband = sdata->local->hw.wiphy->bands[band];
+
+	rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
+	shift = ieee80211_vif_get_shift(&sdata->vif);
 
 	if (WARN_ON(!sband))
 		return 1;
@@ -1381,7 +1391,15 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
 			continue;
 
 		for (j = 0; j < num_rates; j++) {
-			if (bitrates[j].bitrate == own_rate) {
+			int brate;
+			if ((rate_flags & sband->bitrates[j].flags)
+			    != rate_flags)
+				continue;
+
+			brate = DIV_ROUND_UP(sband->bitrates[j].bitrate,
+					     1 << shift);
+
+			if (brate == own_rate) {
 				supp_rates |= BIT(j);
 				if (basic_rates && is_basic)
 					*basic_rates |= BIT(j);
@@ -2004,18 +2022,56 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
 	cfg80211_chandef_create(chandef, control_chan, channel_type);
 }
 
+int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
+			     const struct ieee80211_supported_band *sband,
+			     const u8 *srates, int srates_len, u32 *rates)
+{
+	u32 rate_flags = ieee80211_chandef_rate_flags(chandef);
+	int shift = ieee80211_chandef_get_shift(chandef);
+	struct ieee80211_rate *br;
+	int brate, rate, i, j, count = 0;
+
+	*rates = 0;
+
+	for (i = 0; i < srates_len; i++) {
+		rate = srates[i] & 0x7f;
+
+		for (j = 0; j < sband->n_bitrates; j++) {
+			br = &sband->bitrates[j];
+			if ((rate_flags & br->flags) != rate_flags)
+				continue;
+
+			brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
+			if (brate == rate) {
+				*rates |= BIT(j);
+				count++;
+				break;
+			}
+		}
+	}
+	return count;
+}
+
 int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
 			    struct sk_buff *skb, bool need_basic,
 			    enum ieee80211_band band)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband;
-	int rate;
+	int rate, shift;
 	u8 i, rates, *pos;
 	u32 basic_rates = sdata->vif.bss_conf.basic_rates;
+	u32 rate_flags;
 
+	shift = ieee80211_vif_get_shift(&sdata->vif);
+	rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
 	sband = local->hw.wiphy->bands[band];
-	rates = sband->n_bitrates;
+	rates = 0;
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+		rates++;
+	}
 	if (rates > 8)
 		rates = 8;
 
@@ -2027,10 +2083,15 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
 	*pos++ = rates;
 	for (i = 0; i < rates; i++) {
 		u8 basic = 0;
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+
 		if (need_basic && basic_rates & BIT(i))
 			basic = 0x80;
 		rate = sband->bitrates[i].bitrate;
-		*pos++ = basic | (u8) (rate / 5);
+		rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
+				    5 * (1 << shift));
+		*pos++ = basic | (u8) rate;
 	}
 
 	return 0;
@@ -2042,12 +2103,22 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband;
-	int rate;
+	int rate, skip, shift;
 	u8 i, exrates, *pos;
 	u32 basic_rates = sdata->vif.bss_conf.basic_rates;
+	u32 rate_flags;
+
+	rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
+	shift = ieee80211_vif_get_shift(&sdata->vif);
 
 	sband = local->hw.wiphy->bands[band];
-	exrates = sband->n_bitrates;
+	exrates = 0;
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+		exrates++;
+	}
+
 	if (exrates > 8)
 		exrates -= 8;
 	else
@@ -2060,12 +2131,19 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
 		pos = skb_put(skb, exrates + 2);
 		*pos++ = WLAN_EID_EXT_SUPP_RATES;
 		*pos++ = exrates;
+		skip = 0;
 		for (i = 8; i < sband->n_bitrates; i++) {
 			u8 basic = 0;
+			if ((rate_flags & sband->bitrates[i].flags)
+			    != rate_flags)
+				continue;
+			if (skip++ < 8)
+				continue;
 			if (need_basic && basic_rates & BIT(i))
 				basic = 0x80;
-			rate = sband->bitrates[i].bitrate;
-			*pos++ = basic | (u8) (rate / 5);
+			rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
+					    5 * (1 << shift));
+			*pos++ = basic | (u8) rate;
 		}
 	}
 	return 0;
@@ -2149,9 +2227,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
 			ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
 	} else {
 		struct ieee80211_supported_band *sband;
+		int shift = 0;
+		int bitrate;
+
+		if (status->flag & RX_FLAG_10MHZ)
+			shift = 1;
+		if (status->flag & RX_FLAG_5MHZ)
+			shift = 2;
 
 		sband = local->hw.wiphy->bands[status->band];
-		ri.legacy = sband->bitrates[status->rate_idx].bitrate;
+		bitrate = sband->bitrates[status->rate_idx].bitrate;
+		ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift));
 	}
 
 	rate = cfg80211_calculate_bitrate(&ri);
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 3c0da87..23e596e 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -66,15 +66,7 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 static void sctp_nat_csum(struct sk_buff *skb, sctp_sctphdr_t *sctph,
 			  unsigned int sctphoff)
 {
-	__u32 crc32;
-	struct sk_buff *iter;
-
-	crc32 = sctp_start_cksum((__u8 *)sctph, skb_headlen(skb) - sctphoff);
-	skb_walk_frags(skb, iter)
-		crc32 = sctp_update_cksum((u8 *) iter->data,
-					  skb_headlen(iter), crc32);
-	sctph->checksum = sctp_end_cksum(crc32);
-
+	sctph->checksum = sctp_compute_cksum(skb, sctphoff);
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
@@ -151,10 +143,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
 {
 	unsigned int sctphoff;
 	struct sctphdr *sh, _sctph;
-	struct sk_buff *iter;
-	__le32 cmp;
-	__le32 val;
-	__u32 tmp;
+	__le32 cmp, val;
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
@@ -168,13 +157,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
 		return 0;
 
 	cmp = sh->checksum;
-
-	tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb));
-	skb_walk_frags(skb, iter)
-		tmp = sctp_update_cksum((__u8 *) iter->data,
-					skb_headlen(iter), tmp);
-
-	val = sctp_end_cksum(tmp);
+	val = sctp_compute_cksum(skb, sctphoff);
 
 	if (val != cmp) {
 		/* CRC failure, dump it. */
diff --git a/net/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c
index 396e55d..754536f 100644
--- a/net/netfilter/nf_nat_proto_sctp.c
+++ b/net/netfilter/nf_nat_proto_sctp.c
@@ -34,9 +34,7 @@ sctp_manip_pkt(struct sk_buff *skb,
 	       const struct nf_conntrack_tuple *tuple,
 	       enum nf_nat_manip_type maniptype)
 {
-	struct sk_buff *frag;
 	sctp_sctphdr_t *hdr;
-	__u32 crc32;
 
 	if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
 		return false;
@@ -51,11 +49,7 @@ sctp_manip_pkt(struct sk_buff *skb,
 		hdr->dest = tuple->dst.u.sctp.port;
 	}
 
-	crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff);
-	skb_walk_frags(skb, frag)
-		crc32 = sctp_update_cksum((u8 *)frag->data, skb_headlen(frag),
-					  crc32);
-	hdr->checksum = sctp_end_cksum(crc32);
+	hdr->checksum = sctp_compute_cksum(skb, hdroff);
 
 	return true;
 }
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 0c61b59..6273772 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -294,14 +294,14 @@ static void **alloc_pg_vec(struct netlink_sock *nlk,
 {
 	unsigned int block_nr = req->nm_block_nr;
 	unsigned int i;
-	void **pg_vec, *ptr;
+	void **pg_vec;
 
 	pg_vec = kcalloc(block_nr, sizeof(void *), GFP_KERNEL);
 	if (pg_vec == NULL)
 		return NULL;
 
 	for (i = 0; i < block_nr; i++) {
-		pg_vec[i] = ptr = alloc_one_pg_vec_page(order);
+		pg_vec[i] = alloc_one_pg_vec_page(order);
 		if (pg_vec[i] == NULL)
 			goto err1;
 	}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 4b66c75..4cb28a7 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2638,51 +2638,6 @@ out:
 	return err;
 }
 
-static int packet_recv_error(struct sock *sk, struct msghdr *msg, int len)
-{
-	struct sock_exterr_skb *serr;
-	struct sk_buff *skb, *skb2;
-	int copied, err;
-
-	err = -EAGAIN;
-	skb = skb_dequeue(&sk->sk_error_queue);
-	if (skb == NULL)
-		goto out;
-
-	copied = skb->len;
-	if (copied > len) {
-		msg->msg_flags |= MSG_TRUNC;
-		copied = len;
-	}
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-	if (err)
-		goto out_free_skb;
-
-	sock_recv_timestamp(msg, sk, skb);
-
-	serr = SKB_EXT_ERR(skb);
-	put_cmsg(msg, SOL_PACKET, PACKET_TX_TIMESTAMP,
-		 sizeof(serr->ee), &serr->ee);
-
-	msg->msg_flags |= MSG_ERRQUEUE;
-	err = copied;
-
-	/* Reset and regenerate socket error */
-	spin_lock_bh(&sk->sk_error_queue.lock);
-	sk->sk_err = 0;
-	if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
-		sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
-		spin_unlock_bh(&sk->sk_error_queue.lock);
-		sk->sk_error_report(sk);
-	} else
-		spin_unlock_bh(&sk->sk_error_queue.lock);
-
-out_free_skb:
-	kfree_skb(skb);
-out:
-	return err;
-}
-
 /*
  *	Pull a packet from our receive queue and hand it to the user.
  *	If necessary we block.
@@ -2708,7 +2663,8 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 #endif
 
 	if (flags & MSG_ERRQUEUE) {
-		err = packet_recv_error(sk, msg, len);
+		err = sock_recv_errqueue(sk, msg, len,
+					 SOL_PACKET, PACKET_TX_TIMESTAMP);
 		goto out;
 	}
 
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 1cec5e4..1bacc10 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -576,14 +576,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
 }
 EXPORT_SYMBOL(rfkill_set_states);
 
-static ssize_t rfkill_name_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%s\n", rfkill->name);
 }
+static DEVICE_ATTR_RO(name);
 
 static const char *rfkill_get_type_str(enum rfkill_type type)
 {
@@ -611,54 +611,52 @@ static const char *rfkill_get_type_str(enum rfkill_type type)
 	}
 }
 
-static ssize_t rfkill_type_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type));
 }
+static DEVICE_ATTR_RO(type);
 
-static ssize_t rfkill_idx_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
+static ssize_t index_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", rfkill->idx);
 }
+static DEVICE_ATTR_RO(index);
 
-static ssize_t rfkill_persistent_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
+static ssize_t persistent_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", rfkill->persistent);
 }
+static DEVICE_ATTR_RO(persistent);
 
-static ssize_t rfkill_hard_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t hard_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 );
 }
+static DEVICE_ATTR_RO(hard);
 
-static ssize_t rfkill_soft_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 );
 }
 
-static ssize_t rfkill_soft_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
+static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 	unsigned long state;
@@ -680,6 +678,7 @@ static ssize_t rfkill_soft_store(struct device *dev,
 
 	return count;
 }
+static DEVICE_ATTR_RW(soft);
 
 static u8 user_state_from_blocked(unsigned long state)
 {
@@ -691,18 +690,16 @@ static u8 user_state_from_blocked(unsigned long state)
 	return RFKILL_USER_STATE_UNBLOCKED;
 }
 
-static ssize_t rfkill_state_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state));
 }
 
-static ssize_t rfkill_state_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 	unsigned long state;
@@ -725,32 +722,27 @@ static ssize_t rfkill_state_store(struct device *dev,
 
 	return count;
 }
+static DEVICE_ATTR_RW(state);
 
-static ssize_t rfkill_claim_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t claim_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
-
-static ssize_t rfkill_claim_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
-{
-	return -EOPNOTSUPP;
-}
-
-static struct device_attribute rfkill_dev_attrs[] = {
-	__ATTR(name, S_IRUGO, rfkill_name_show, NULL),
-	__ATTR(type, S_IRUGO, rfkill_type_show, NULL),
-	__ATTR(index, S_IRUGO, rfkill_idx_show, NULL),
-	__ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL),
-	__ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store),
-	__ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store),
-	__ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store),
-	__ATTR(hard, S_IRUGO, rfkill_hard_show, NULL),
-	__ATTR_NULL
+static DEVICE_ATTR_RO(claim);
+
+static struct attribute *rfkill_dev_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_type.attr,
+	&dev_attr_index.attr,
+	&dev_attr_persistent.attr,
+	&dev_attr_state.attr,
+	&dev_attr_claim.attr,
+	&dev_attr_soft.attr,
+	&dev_attr_hard.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(rfkill_dev);
 
 static void rfkill_release(struct device *dev)
 {
@@ -830,7 +822,7 @@ static int rfkill_resume(struct device *dev)
 static struct class rfkill_class = {
 	.name		= "rfkill",
 	.dev_release	= rfkill_release,
-	.dev_attrs	= rfkill_dev_attrs,
+	.dev_groups	= rfkill_dev_groups,
 	.dev_uevent	= rfkill_dev_uevent,
 	.suspend	= rfkill_suspend,
 	.resume		= rfkill_resume,
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 4626cef..eeb8276 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
 #include <net/dst.h>
@@ -207,15 +208,19 @@ void __qdisc_run(struct Qdisc *q)
 
 unsigned long dev_trans_start(struct net_device *dev)
 {
-	unsigned long val, res = dev->trans_start;
+	unsigned long val, res;
 	unsigned int i;
 
+	if (is_vlan_dev(dev))
+		dev = vlan_dev_real_dev(dev);
+	res = dev->trans_start;
 	for (i = 0; i < dev->num_tx_queues; i++) {
 		val = netdev_get_tx_queue(dev, i)->trans_start;
 		if (val && time_after(val, res))
 			res = val;
 	}
 	dev->trans_start = res;
+
 	return res;
 }
 EXPORT_SYMBOL(dev_trans_start);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 82f6016..a6d788d 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -412,12 +412,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
 	/* If a delay is expected, orphan the skb. (orphaning usually takes
 	 * place at TX completion time, so _before_ the link transit delay)
-	 * Ideally, this orphaning should be done after the rate limiting
-	 * module, because this breaks TCP Small Queue, and other mechanisms
-	 * based on socket sk_wmem_alloc.
 	 */
 	if (q->latency || q->jitter)
-		skb_orphan(skb);
+		skb_orphan_partial(skb);
 
 	/*
 	 * If we need to duplicate packet, then re-insert at top of the
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index bce5b79..e425ba0 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index ba1dfc3..3aab967 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -22,7 +22,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 64977ea..f34ce8b 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -27,7 +27,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 5780565..b50b90c 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -24,7 +24,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/command.c b/net/sctp/command.c
index c004401..f4bebda 100644
--- a/net/sctp/command.c
+++ b/net/sctp/command.c
@@ -25,7 +25,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index f499878..44aa4e7 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 9e3d257..825b754 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -29,7 +29,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 3fa4d85..fa91aff 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -29,7 +29,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
@@ -87,15 +87,7 @@ static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
 {
 	struct sctphdr *sh = sctp_hdr(skb);
 	__le32 cmp = sh->checksum;
-	struct sk_buff *list;
-	__le32 val;
-	__u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb));
-
-	skb_walk_frags(skb, list)
-		tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list),
-					tmp);
-
-	val = sctp_end_cksum(tmp);
+	__le32 val = sctp_compute_cksum(skb, 0);
 
 	if (val != cmp) {
 		/* CRC failure, dump it. */
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index cb25f04..e70f60a 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -30,7 +30,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 09ffcc9..5a9402e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -27,7 +27,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
@@ -351,7 +351,7 @@ out:
 
 		rt = (struct rt6_info *)dst;
 		t->dst = dst;
-
+		t->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
 		pr_debug("rt6_dst:%pI6 rt6_src:%pI6\n", &rt->rt6i_dst.addr,
 			 &fl6->saddr);
 	} else {
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
index fe012c4..aec346c 100644
--- a/net/sctp/objcnt.c
+++ b/net/sctp/objcnt.c
@@ -26,7 +26,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/output.c b/net/sctp/output.c
index a46d1eb..5a55c55d 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -26,7 +26,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index ef9e2bb..5131323 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c
index 794bb14..31fa437 100644
--- a/net/sctp/primitive.c
+++ b/net/sctp/primitive.c
@@ -29,7 +29,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 62526c4..aff0cac 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -22,7 +22,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 4a17494d..b52ec25 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -29,7 +29,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
@@ -1547,7 +1547,7 @@ module_exit(sctp_exit);
  */
 MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
 MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132");
-MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
+MODULE_AUTHOR("Linux Kernel SCTP developers <linux-sctp@vger.kernel.org>");
 MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
 module_param_named(no_checksums, sctp_checksum_disable, bool, 0644);
 MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification");
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 362ae6e..780a2d4 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -29,7 +29,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 9da6885..f1f3aac 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f6b7109..93271f0 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 84d98d8..64ea5fd 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c6670d2..0245712 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -34,7 +34,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
index da86035..72b5939 100644
--- a/net/sctp/ssnmap.c
+++ b/net/sctp/ssnmap.c
@@ -24,7 +24,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 9a5c4c9..1906747 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -25,7 +25,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index bdbbc3f..9602c52 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -30,7 +30,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index b460195..0eff866 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -27,7 +27,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 44a45db..c07624f 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -28,7 +28,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 04e3d47..2cdb301 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -27,7 +27,7 @@
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
- *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *    lksctp developers <linux-sctp@vger.kernel.org>
  *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
diff --git a/net/socket.c b/net/socket.c
index b2d7c62..ebed4b6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -854,11 +854,6 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
 }
 EXPORT_SYMBOL(kernel_recvmsg);
 
-static void sock_aio_dtor(struct kiocb *iocb)
-{
-	kfree(iocb->private);
-}
-
 static ssize_t sock_sendpage(struct file *file, struct page *page,
 			     int offset, size_t size, loff_t *ppos, int more)
 {
@@ -889,12 +884,8 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
 static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
 					 struct sock_iocb *siocb)
 {
-	if (!is_sync_kiocb(iocb)) {
-		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
-		if (!siocb)
-			return NULL;
-		iocb->ki_dtor = sock_aio_dtor;
-	}
+	if (!is_sync_kiocb(iocb))
+		BUG();
 
 	siocb->kiocb = iocb;
 	iocb->private = siocb;
@@ -931,7 +922,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
 	if (pos != 0)
 		return -ESPIPE;
 
-	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
+	if (iocb->ki_nbytes == 0)	/* Match SYS5 behaviour */
 		return 0;
 
 
@@ -3072,12 +3063,12 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 
 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
-	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
-	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
-	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
-	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
-	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
-	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
+	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
+	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
+	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
+	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
+	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
+	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
 	if (err)
 		return -EFAULT;
 
@@ -3088,12 +3079,12 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 
 	if (cmd == SIOCGIFMAP && !err) {
 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
-		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
-		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
-		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
-		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
-		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
-		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
+		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
+		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
+		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
+		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
+		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
+		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
 		if (err)
 			err = -EFAULT;
 	}
@@ -3167,25 +3158,25 @@ static int routing_ioctl(struct net *net, struct socket *sock,
 		struct in6_rtmsg32 __user *ur6 = argp;
 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
 			3 * sizeof(struct in6_addr));
-		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
-		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
-		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
-		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
-		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
-		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
-		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
+		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
+		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
+		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
+		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
+		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
+		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
+		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
 
 		r = (void *) &r6;
 	} else { /* ipv4 */
 		struct rtentry32 __user *ur4 = argp;
 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
 					3 * sizeof(struct sockaddr));
-		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
-		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
-		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
-		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
-		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
-		ret |= __get_user(rtdev, &(ur4->rt_dev));
+		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
+		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
+		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
+		ret |= get_user(r4.rt_window, &(ur4->rt_window));
+		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
+		ret |= get_user(rtdev, &(ur4->rt_dev));
 		if (rtdev) {
 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
 			r4.rt_dev = (char __user __force *)devname;
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index ed2fdd2..495a224 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -413,12 +413,13 @@ EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache);
 /*
  * Remove stale credentials. Avoid sleeping inside the loop.
  */
-static int
+static long
 rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 {
 	spinlock_t *cache_lock;
 	struct rpc_cred *cred, *next;
 	unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
+	long freed = 0;
 
 	list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) {
 
@@ -430,10 +431,11 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 		 */
 		if (time_in_range(cred->cr_expire, expired, jiffies) &&
 		    test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
-			return 0;
+			break;
 
 		list_del_init(&cred->cr_lru);
 		number_cred_unused--;
+		freed++;
 		if (atomic_read(&cred->cr_count) != 0)
 			continue;
 
@@ -446,29 +448,39 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 		}
 		spin_unlock(cache_lock);
 	}
-	return (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
+	return freed;
 }
 
 /*
  * Run memory cache shrinker.
  */
-static int
-rpcauth_cache_shrinker(struct shrinker *shrink, struct shrink_control *sc)
+static unsigned long
+rpcauth_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
+
 {
 	LIST_HEAD(free);
-	int res;
-	int nr_to_scan = sc->nr_to_scan;
-	gfp_t gfp_mask = sc->gfp_mask;
+	unsigned long freed;
+
+	if ((sc->gfp_mask & GFP_KERNEL) != GFP_KERNEL)
+		return SHRINK_STOP;
 
-	if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
-		return (nr_to_scan == 0) ? 0 : -1;
+	/* nothing left, don't come back */
 	if (list_empty(&cred_unused))
-		return 0;
+		return SHRINK_STOP;
+
 	spin_lock(&rpc_credcache_lock);
-	res = rpcauth_prune_expired(&free, nr_to_scan);
+	freed = rpcauth_prune_expired(&free, sc->nr_to_scan);
 	spin_unlock(&rpc_credcache_lock);
 	rpcauth_destroy_credlist(&free);
-	return res;
+
+	return freed;
+}
+
+static unsigned long
+rpcauth_cache_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+
+{
+	return (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
 }
 
 /*
@@ -784,7 +796,8 @@ rpcauth_uptodatecred(struct rpc_task *task)
 }
 
 static struct shrinker rpc_cred_shrinker = {
-	.shrink = rpcauth_cache_shrinker,
+	.count_objects = rpcauth_cache_shrink_count,
+	.scan_objects = rpcauth_cache_shrink_scan,
 	.seeks = DEFAULT_SEEKS,
 };
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 74f6a70..ecbc4e3 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1660,6 +1660,10 @@ call_connect(struct rpc_task *task)
 		task->tk_action = call_connect_status;
 		if (task->tk_status < 0)
 			return;
+		if (task->tk_flags & RPC_TASK_NOCONNECT) {
+			rpc_exit(task, -ENOTCONN);
+			return;
+		}
 		xprt_connect(task);
 	}
 }
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 74d948f..779742c 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -23,6 +23,7 @@ struct sunrpc_net {
 	struct rpc_clnt *rpcb_local_clnt4;
 	spinlock_t rpcb_clnt_lock;
 	unsigned int rpcb_users;
+	unsigned int rpcb_is_af_local : 1;
 
 	struct mutex gssp_lock;
 	wait_queue_head_t gssp_wq;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 406859c..017aedc 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -480,23 +480,6 @@ static const struct dentry_operations rpc_dentry_operations = {
 	.d_delete = rpc_delete_dentry,
 };
 
-/*
- * Lookup the data. This is trivial - if the dentry didn't already
- * exist, we know it is negative.
- */
-static struct dentry *
-rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
-{
-	if (dentry->d_name.len > NAME_MAX)
-		return ERR_PTR(-ENAMETOOLONG);
-	d_add(dentry, NULL);
-	return NULL;
-}
-
-static const struct inode_operations rpc_dir_inode_operations = {
-	.lookup		= rpc_lookup,
-};
-
 static struct inode *
 rpc_get_inode(struct super_block *sb, umode_t mode)
 {
@@ -509,7 +492,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode)
 	switch (mode & S_IFMT) {
 	case S_IFDIR:
 		inode->i_fop = &simple_dir_operations;
-		inode->i_op = &rpc_dir_inode_operations;
+		inode->i_op = &simple_dir_inode_operations;
 		inc_nlink(inode);
 	default:
 		break;
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 3df764d..1891a10 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -204,13 +204,15 @@ void rpcb_put_local(struct net *net)
 }
 
 static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
-			struct rpc_clnt *clnt4)
+			struct rpc_clnt *clnt4,
+			bool is_af_local)
 {
 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
 	/* Protected by rpcb_create_local_mutex */
 	sn->rpcb_local_clnt = clnt;
 	sn->rpcb_local_clnt4 = clnt4;
+	sn->rpcb_is_af_local = is_af_local ? 1 : 0;
 	smp_wmb(); 
 	sn->rpcb_users = 1;
 	dprintk("RPC:       created new rpcb local clients (rpcb_local_clnt: "
@@ -238,6 +240,14 @@ static int rpcb_create_local_unix(struct net *net)
 		.program	= &rpcb_program,
 		.version	= RPCBVERS_2,
 		.authflavor	= RPC_AUTH_NULL,
+		/*
+		 * We turn off the idle timeout to prevent the kernel
+		 * from automatically disconnecting the socket.
+		 * Otherwise, we'd have to cache the mount namespace
+		 * of the caller and somehow pass that to the socket
+		 * reconnect code.
+		 */
+		.flags		= RPC_CLNT_CREATE_NO_IDLE_TIMEOUT,
 	};
 	struct rpc_clnt *clnt, *clnt4;
 	int result = 0;
@@ -263,7 +273,7 @@ static int rpcb_create_local_unix(struct net *net)
 		clnt4 = NULL;
 	}
 
-	rpcb_set_local(net, clnt, clnt4);
+	rpcb_set_local(net, clnt, clnt4, true);
 
 out:
 	return result;
@@ -315,7 +325,7 @@ static int rpcb_create_local_net(struct net *net)
 		clnt4 = NULL;
 	}
 
-	rpcb_set_local(net, clnt, clnt4);
+	rpcb_set_local(net, clnt, clnt4, false);
 
 out:
 	return result;
@@ -376,13 +386,16 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname,
 	return rpc_create(&args);
 }
 
-static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
+static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set)
 {
-	int result, error = 0;
+	int flags = RPC_TASK_NOCONNECT;
+	int error, result = 0;
 
+	if (is_set || !sn->rpcb_is_af_local)
+		flags = RPC_TASK_SOFTCONN;
 	msg->rpc_resp = &result;
 
-	error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
+	error = rpc_call_sync(clnt, msg, flags);
 	if (error < 0) {
 		dprintk("RPC:       failed to contact local rpcbind "
 				"server (errno %d).\n", -error);
@@ -439,16 +452,19 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short
 		.rpc_argp	= &map,
 	};
 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+	bool is_set = false;
 
 	dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local "
 			"rpcbind\n", (port ? "" : "un"),
 			prog, vers, prot, port);
 
 	msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
-	if (port)
+	if (port != 0) {
 		msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
+		is_set = true;
+	}
 
-	return rpcb_register_call(sn->rpcb_local_clnt, &msg);
+	return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set);
 }
 
 /*
@@ -461,6 +477,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
 	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
 	struct rpcbind_args *map = msg->rpc_argp;
 	unsigned short port = ntohs(sin->sin_port);
+	bool is_set = false;
 	int result;
 
 	map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
@@ -471,10 +488,12 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
 			map->r_addr, map->r_netid);
 
 	msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
-	if (port)
+	if (port != 0) {
 		msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
+		is_set = true;
+	}
 
-	result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
+	result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
 	kfree(map->r_addr);
 	return result;
 }
@@ -489,6 +508,7 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
 	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
 	struct rpcbind_args *map = msg->rpc_argp;
 	unsigned short port = ntohs(sin6->sin6_port);
+	bool is_set = false;
 	int result;
 
 	map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
@@ -499,10 +519,12 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
 			map->r_addr, map->r_netid);
 
 	msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
-	if (port)
+	if (port != 0) {
 		msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
+		is_set = true;
+	}
 
-	result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
+	result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
 	kfree(map->r_addr);
 	return result;
 }
@@ -519,7 +541,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn,
 	map->r_addr = "";
 	msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
 
-	return rpcb_register_call(sn->rpcb_local_clnt4, msg);
+	return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false);
 }
 
 /**
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 7762b9f..9c9caaa 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -442,7 +442,7 @@ static void svc_tcp_write_space(struct sock *sk)
 {
 	struct socket *sock = sk->sk_socket;
 
-	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock)
+	if (sk_stream_is_writeable(sk) && sock)
 		clear_bit(SOCK_NOSPACE, &sock->flags);
 	svc_write_space(sk);
 }
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ddf0602..d6656d7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1602,7 +1602,7 @@ static void xs_tcp_write_space(struct sock *sk)
 	read_lock_bh(&sk->sk_callback_lock);
 
 	/* from net/core/stream.c:sk_stream_write_space */
-	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
+	if (sk_stream_is_writeable(sk))
 		xs_write_space(sk);
 
 	read_unlock_bh(&sk->sk_callback_lock);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 593071d..545c08b 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -96,8 +96,7 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <net/sock.h>
-
-#include "af_vsock.h"
+#include <net/af_vsock.h>
 
 static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
 static void vsock_sk_destruct(struct sock *sk);
@@ -347,7 +346,7 @@ void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
 	for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) {
 		struct vsock_sock *vsk;
 		list_for_each_entry(vsk, &vsock_connected_table[i],
-				    connected_table);
+				    connected_table)
 			fn(sk_vsock(vsk));
 	}
 
diff --git a/net/vmw_vsock/af_vsock.h b/net/vmw_vsock/af_vsock.h
deleted file mode 100644
index 7d64d36..0000000
--- a/net/vmw_vsock/af_vsock.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * VMware vSockets Driver
- *
- * Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation version 2 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#ifndef __AF_VSOCK_H__
-#define __AF_VSOCK_H__
-
-#include <linux/kernel.h>
-#include <linux/workqueue.h>
-#include <linux/vm_sockets.h>
-
-#include "vsock_addr.h"
-
-#define LAST_RESERVED_PORT 1023
-
-#define vsock_sk(__sk)    ((struct vsock_sock *)__sk)
-#define sk_vsock(__vsk)   (&(__vsk)->sk)
-
-struct vsock_sock {
-	/* sk must be the first member. */
-	struct sock sk;
-	struct sockaddr_vm local_addr;
-	struct sockaddr_vm remote_addr;
-	/* Links for the global tables of bound and connected sockets. */
-	struct list_head bound_table;
-	struct list_head connected_table;
-	/* Accessed without the socket lock held. This means it can never be
-	 * modified outsided of socket create or destruct.
-	 */
-	bool trusted;
-	bool cached_peer_allow_dgram;	/* Dgram communication allowed to
-					 * cached peer?
-					 */
-	u32 cached_peer;  /* Context ID of last dgram destination check. */
-	const struct cred *owner;
-	/* Rest are SOCK_STREAM only. */
-	long connect_timeout;
-	/* Listening socket that this came from. */
-	struct sock *listener;
-	/* Used for pending list and accept queue during connection handshake.
-	 * The listening socket is the head for both lists.  Sockets created
-	 * for connection requests are placed in the pending list until they
-	 * are connected, at which point they are put in the accept queue list
-	 * so they can be accepted in accept().  If accept() cannot accept the
-	 * connection, it is marked as rejected so the cleanup function knows
-	 * to clean up the socket.
-	 */
-	struct list_head pending_links;
-	struct list_head accept_queue;
-	bool rejected;
-	struct delayed_work dwork;
-	u32 peer_shutdown;
-	bool sent_request;
-	bool ignore_connecting_rst;
-
-	/* Private to transport. */
-	void *trans;
-};
-
-s64 vsock_stream_has_data(struct vsock_sock *vsk);
-s64 vsock_stream_has_space(struct vsock_sock *vsk);
-void vsock_pending_work(struct work_struct *work);
-struct sock *__vsock_create(struct net *net,
-			    struct socket *sock,
-			    struct sock *parent,
-			    gfp_t priority, unsigned short type);
-
-/**** TRANSPORT ****/
-
-struct vsock_transport_recv_notify_data {
-	u64 data1; /* Transport-defined. */
-	u64 data2; /* Transport-defined. */
-	bool notify_on_block;
-};
-
-struct vsock_transport_send_notify_data {
-	u64 data1; /* Transport-defined. */
-	u64 data2; /* Transport-defined. */
-};
-
-struct vsock_transport {
-	/* Initialize/tear-down socket. */
-	int (*init)(struct vsock_sock *, struct vsock_sock *);
-	void (*destruct)(struct vsock_sock *);
-	void (*release)(struct vsock_sock *);
-
-	/* Connections. */
-	int (*connect)(struct vsock_sock *);
-
-	/* DGRAM. */
-	int (*dgram_bind)(struct vsock_sock *, struct sockaddr_vm *);
-	int (*dgram_dequeue)(struct kiocb *kiocb, struct vsock_sock *vsk,
-			     struct msghdr *msg, size_t len, int flags);
-	int (*dgram_enqueue)(struct vsock_sock *, struct sockaddr_vm *,
-			     struct iovec *, size_t len);
-	bool (*dgram_allow)(u32 cid, u32 port);
-
-	/* STREAM. */
-	/* TODO: stream_bind() */
-	ssize_t (*stream_dequeue)(struct vsock_sock *, struct iovec *,
-				  size_t len, int flags);
-	ssize_t (*stream_enqueue)(struct vsock_sock *, struct iovec *,
-				  size_t len);
-	s64 (*stream_has_data)(struct vsock_sock *);
-	s64 (*stream_has_space)(struct vsock_sock *);
-	u64 (*stream_rcvhiwat)(struct vsock_sock *);
-	bool (*stream_is_active)(struct vsock_sock *);
-	bool (*stream_allow)(u32 cid, u32 port);
-
-	/* Notification. */
-	int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
-	int (*notify_poll_out)(struct vsock_sock *, size_t, bool *);
-	int (*notify_recv_init)(struct vsock_sock *, size_t,
-		struct vsock_transport_recv_notify_data *);
-	int (*notify_recv_pre_block)(struct vsock_sock *, size_t,
-		struct vsock_transport_recv_notify_data *);
-	int (*notify_recv_pre_dequeue)(struct vsock_sock *, size_t,
-		struct vsock_transport_recv_notify_data *);
-	int (*notify_recv_post_dequeue)(struct vsock_sock *, size_t,
-		ssize_t, bool, struct vsock_transport_recv_notify_data *);
-	int (*notify_send_init)(struct vsock_sock *,
-		struct vsock_transport_send_notify_data *);
-	int (*notify_send_pre_block)(struct vsock_sock *,
-		struct vsock_transport_send_notify_data *);
-	int (*notify_send_pre_enqueue)(struct vsock_sock *,
-		struct vsock_transport_send_notify_data *);
-	int (*notify_send_post_enqueue)(struct vsock_sock *, ssize_t,
-		struct vsock_transport_send_notify_data *);
-
-	/* Shutdown. */
-	int (*shutdown)(struct vsock_sock *, int);
-
-	/* Buffer sizes. */
-	void (*set_buffer_size)(struct vsock_sock *, u64);
-	void (*set_min_buffer_size)(struct vsock_sock *, u64);
-	void (*set_max_buffer_size)(struct vsock_sock *, u64);
-	u64 (*get_buffer_size)(struct vsock_sock *);
-	u64 (*get_min_buffer_size)(struct vsock_sock *);
-	u64 (*get_max_buffer_size)(struct vsock_sock *);
-
-	/* Addressing. */
-	u32 (*get_local_cid)(void);
-};
-
-/**** CORE ****/
-
-int vsock_core_init(const struct vsock_transport *t);
-void vsock_core_exit(void);
-
-/**** UTILS ****/
-
-void vsock_release_pending(struct sock *pending);
-void vsock_add_pending(struct sock *listener, struct sock *pending);
-void vsock_remove_pending(struct sock *listener, struct sock *pending);
-void vsock_enqueue_accept(struct sock *listener, struct sock *connected);
-void vsock_insert_connected(struct vsock_sock *vsk);
-void vsock_remove_bound(struct vsock_sock *vsk);
-void vsock_remove_connected(struct vsock_sock *vsk);
-struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
-struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
-					 struct sockaddr_vm *dst);
-void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
-
-#endif /* __AF_VSOCK_H__ */
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index ffc11df..9d69866 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -34,8 +34,8 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <net/sock.h>
+#include <net/af_vsock.h>
 
-#include "af_vsock.h"
 #include "vmci_transport_notify.h"
 
 static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg);
diff --git a/net/vmw_vsock/vmci_transport.h b/net/vmw_vsock/vmci_transport.h
index fd88ea8..ce6c962 100644
--- a/net/vmw_vsock/vmci_transport.h
+++ b/net/vmw_vsock/vmci_transport.h
@@ -19,8 +19,8 @@
 #include <linux/vmw_vmci_defs.h>
 #include <linux/vmw_vmci_api.h>
 
-#include "vsock_addr.h"
-#include "af_vsock.h"
+#include <net/vsock_addr.h>
+#include <net/af_vsock.h>
 
 /* If the packet format changes in a release then this should change too. */
 #define VMCI_TRANSPORT_PACKET_VERSION 1
diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
index ec2611b..82486ee 100644
--- a/net/vmw_vsock/vsock_addr.c
+++ b/net/vmw_vsock/vsock_addr.c
@@ -17,8 +17,7 @@
 #include <linux/socket.h>
 #include <linux/stddef.h>
 #include <net/sock.h>
-
-#include "vsock_addr.h"
+#include <net/vsock_addr.h>
 
 void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port)
 {
diff --git a/net/vmw_vsock/vsock_addr.h b/net/vmw_vsock/vsock_addr.h
deleted file mode 100644
index 9ccd531..0000000
--- a/net/vmw_vsock/vsock_addr.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * VMware vSockets Driver
- *
- * Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation version 2 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#ifndef _VSOCK_ADDR_H_
-#define _VSOCK_ADDR_H_
-
-#include <linux/vm_sockets.h>
-
-void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port);
-int vsock_addr_validate(const struct sockaddr_vm *addr);
-bool vsock_addr_bound(const struct sockaddr_vm *addr);
-void vsock_addr_unbind(struct sockaddr_vm *addr);
-bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
-			    const struct sockaddr_vm *other);
-int vsock_addr_cast(const struct sockaddr *addr, size_t len,
-		    struct sockaddr_vm **out_addr);
-
-#endif
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 4f9f216..6715396 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -462,6 +462,14 @@ int wiphy_register(struct wiphy *wiphy)
 		return -EINVAL;
 #endif
 
+	if (WARN_ON(wiphy->coalesce &&
+		    (!wiphy->coalesce->n_rules ||
+		     !wiphy->coalesce->n_patterns) &&
+		    (!wiphy->coalesce->pattern_min_len ||
+		     wiphy->coalesce->pattern_min_len >
+			wiphy->coalesce->pattern_max_len)))
+		return -EINVAL;
+
 	if (WARN_ON(wiphy->ap_sme_capa &&
 		    !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
 		return -EINVAL;
@@ -668,6 +676,7 @@ void wiphy_unregister(struct wiphy *wiphy)
 		rdev_set_wakeup(rdev, false);
 #endif
 	cfg80211_rdev_free_wowlan(rdev);
+	cfg80211_rdev_free_coalesce(rdev);
 }
 EXPORT_SYMBOL(wiphy_unregister);
 
@@ -765,6 +774,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
 		cfg80211_leave_mesh(rdev, dev);
 		break;
 	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_GO:
 		cfg80211_stop_ap(rdev, dev);
 		break;
 	default:
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a6b45bf..9ad43c6 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -79,6 +79,8 @@ struct cfg80211_registered_device {
 	/* netlink port which started critical protocol (0 means not started) */
 	u32 crit_proto_nlportid;
 
+	struct cfg80211_coalesce *coalesce;
+
 	/* must be last because of the way we do wiphy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN */
 	struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 30c4920..0553fd4 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -167,9 +167,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
 	 * basic rates
 	 */
 	if (!setup->basic_rates) {
+		enum nl80211_bss_scan_width scan_width;
 		struct ieee80211_supported_band *sband =
 				rdev->wiphy.bands[setup->chandef.chan->band];
-		setup->basic_rates = ieee80211_mandatory_rates(sband);
+		scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
+		setup->basic_rates = ieee80211_mandatory_rates(sband,
+							       scan_width);
 	}
 
 	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25d217d..587ff84 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -403,6 +403,14 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
 	[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
 };
 
+/* policy for coalesce rule attributes */
+static const struct nla_policy
+nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
+	[NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
+	[NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 },
+	[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
+};
+
 /* policy for GTK rekey offload attributes */
 static const struct nla_policy
 nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
@@ -441,10 +449,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
 			goto out_unlock;
 		}
 		*rdev = wiphy_to_dev((*wdev)->wiphy);
-		cb->args[0] = (*rdev)->wiphy_idx;
+		/* 0 is the first index - add 1 to parse only once */
+		cb->args[0] = (*rdev)->wiphy_idx + 1;
 		cb->args[1] = (*wdev)->identifier;
 	} else {
-		struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
+		/* subtract the 1 again here */
+		struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
 		struct wireless_dev *tmp;
 
 		if (!wiphy) {
@@ -974,7 +984,7 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
 		return -ENOBUFS;
 
 	if (dev->wiphy.wowlan->n_patterns) {
-		struct nl80211_wowlan_pattern_support pat = {
+		struct nl80211_pattern_support pat = {
 			.max_patterns = dev->wiphy.wowlan->n_patterns,
 			.min_pattern_len = dev->wiphy.wowlan->pattern_min_len,
 			.max_pattern_len = dev->wiphy.wowlan->pattern_max_len,
@@ -995,6 +1005,27 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
 }
 #endif
 
+static int nl80211_send_coalesce(struct sk_buff *msg,
+				 struct cfg80211_registered_device *dev)
+{
+	struct nl80211_coalesce_rule_support rule;
+
+	if (!dev->wiphy.coalesce)
+		return 0;
+
+	rule.max_rules = dev->wiphy.coalesce->n_rules;
+	rule.max_delay = dev->wiphy.coalesce->max_delay;
+	rule.pat.max_patterns = dev->wiphy.coalesce->n_patterns;
+	rule.pat.min_pattern_len = dev->wiphy.coalesce->pattern_min_len;
+	rule.pat.max_pattern_len = dev->wiphy.coalesce->pattern_max_len;
+	rule.pat.max_pkt_offset = dev->wiphy.coalesce->max_pkt_offset;
+
+	if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
+		return -ENOBUFS;
+
+	return 0;
+}
+
 static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 				      struct ieee80211_supported_band *sband)
 {
@@ -1513,6 +1544,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
 			    dev->wiphy.vht_capa_mod_mask))
 			goto nla_put_failure;
 
+		state->split_start++;
+		break;
+	case 10:
+		if (nl80211_send_coalesce(msg, dev))
+			goto nla_put_failure;
+
 		/* done */
 		state->split_start = 0;
 		break;
@@ -5639,6 +5676,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
 		goto nla_put_failure;
 	if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
 	    nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
+	    nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
 	    nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
 			jiffies_to_msecs(jiffies - intbss->ts)))
 		goto nla_put_failure;
@@ -6319,6 +6357,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 
 	switch (ibss.chandef.width) {
+	case NL80211_CHAN_WIDTH_5:
+	case NL80211_CHAN_WIDTH_10:
 	case NL80211_CHAN_WIDTH_20_NOHT:
 		break;
 	case NL80211_CHAN_WIDTH_20:
@@ -6346,6 +6386,19 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 			return err;
 	}
 
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+		memcpy(&ibss.ht_capa_mask,
+		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
+		       sizeof(ibss.ht_capa_mask));
+
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+			return -EINVAL;
+		memcpy(&ibss.ht_capa,
+		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
+		       sizeof(ibss.ht_capa));
+	}
+
 	if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
 	    !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
 			nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
@@ -7593,12 +7646,11 @@ static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
 		if (!nl_pat)
 			return -ENOBUFS;
 		pat_len = wowlan->patterns[i].pattern_len;
-		if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
-			    DIV_ROUND_UP(pat_len, 8),
+		if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
 			    wowlan->patterns[i].mask) ||
-		    nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
-			    pat_len, wowlan->patterns[i].pattern) ||
-		    nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
+		    nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
+			    wowlan->patterns[i].pattern) ||
+		    nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
 				wowlan->patterns[i].pkt_offset))
 			return -ENOBUFS;
 		nla_nest_end(msg, nl_pat);
@@ -7939,7 +7991,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		struct nlattr *pat;
 		int n_patterns = 0;
 		int rem, pat_len, mask_len, pkt_offset;
-		struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
+		struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
 
 		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
 				    rem)
@@ -7958,26 +8010,25 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 
 		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
 				    rem) {
-			nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
-				  nla_data(pat), nla_len(pat), NULL);
+			nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
+				  nla_len(pat), NULL);
 			err = -EINVAL;
-			if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
-			    !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
+			if (!pat_tb[NL80211_PKTPAT_MASK] ||
+			    !pat_tb[NL80211_PKTPAT_PATTERN])
 				goto error;
-			pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
+			pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
 			mask_len = DIV_ROUND_UP(pat_len, 8);
-			if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
-			    mask_len)
+			if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
 				goto error;
 			if (pat_len > wowlan->pattern_max_len ||
 			    pat_len < wowlan->pattern_min_len)
 				goto error;
 
-			if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
+			if (!pat_tb[NL80211_PKTPAT_OFFSET])
 				pkt_offset = 0;
 			else
 				pkt_offset = nla_get_u32(
-					pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
+					pat_tb[NL80211_PKTPAT_OFFSET]);
 			if (pkt_offset > wowlan->max_pkt_offset)
 				goto error;
 			new_triggers.patterns[i].pkt_offset = pkt_offset;
@@ -7991,11 +8042,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 			new_triggers.patterns[i].pattern =
 				new_triggers.patterns[i].mask + mask_len;
 			memcpy(new_triggers.patterns[i].mask,
-			       nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
+			       nla_data(pat_tb[NL80211_PKTPAT_MASK]),
 			       mask_len);
 			new_triggers.patterns[i].pattern_len = pat_len;
 			memcpy(new_triggers.patterns[i].pattern,
-			       nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
+			       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
 			       pat_len);
 			i++;
 		}
@@ -8034,6 +8085,264 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 }
 #endif
 
+static int nl80211_send_coalesce_rules(struct sk_buff *msg,
+				       struct cfg80211_registered_device *rdev)
+{
+	struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
+	int i, j, pat_len;
+	struct cfg80211_coalesce_rules *rule;
+
+	if (!rdev->coalesce->n_rules)
+		return 0;
+
+	nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
+	if (!nl_rules)
+		return -ENOBUFS;
+
+	for (i = 0; i < rdev->coalesce->n_rules; i++) {
+		nl_rule = nla_nest_start(msg, i + 1);
+		if (!nl_rule)
+			return -ENOBUFS;
+
+		rule = &rdev->coalesce->rules[i];
+		if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
+				rule->delay))
+			return -ENOBUFS;
+
+		if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
+				rule->condition))
+			return -ENOBUFS;
+
+		nl_pats = nla_nest_start(msg,
+				NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
+		if (!nl_pats)
+			return -ENOBUFS;
+
+		for (j = 0; j < rule->n_patterns; j++) {
+			nl_pat = nla_nest_start(msg, j + 1);
+			if (!nl_pat)
+				return -ENOBUFS;
+			pat_len = rule->patterns[j].pattern_len;
+			if (nla_put(msg, NL80211_PKTPAT_MASK,
+				    DIV_ROUND_UP(pat_len, 8),
+				    rule->patterns[j].mask) ||
+			    nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
+				    rule->patterns[j].pattern) ||
+			    nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
+					rule->patterns[j].pkt_offset))
+				return -ENOBUFS;
+			nla_nest_end(msg, nl_pat);
+		}
+		nla_nest_end(msg, nl_pats);
+		nla_nest_end(msg, nl_rule);
+	}
+	nla_nest_end(msg, nl_rules);
+
+	return 0;
+}
+
+static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct sk_buff *msg;
+	void *hdr;
+
+	if (!rdev->wiphy.coalesce)
+		return -EOPNOTSUPP;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
+			     NL80211_CMD_GET_COALESCE);
+	if (!hdr)
+		goto nla_put_failure;
+
+	if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return genlmsg_reply(msg, info);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
+{
+	struct cfg80211_coalesce *coalesce = rdev->coalesce;
+	int i, j;
+	struct cfg80211_coalesce_rules *rule;
+
+	if (!coalesce)
+		return;
+
+	for (i = 0; i < coalesce->n_rules; i++) {
+		rule = &coalesce->rules[i];
+		for (j = 0; j < rule->n_patterns; j++)
+			kfree(rule->patterns[j].mask);
+		kfree(rule->patterns);
+	}
+	kfree(coalesce->rules);
+	kfree(coalesce);
+	rdev->coalesce = NULL;
+}
+
+static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
+				       struct nlattr *rule,
+				       struct cfg80211_coalesce_rules *new_rule)
+{
+	int err, i;
+	const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
+	struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
+	int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
+	struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
+
+	err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule),
+			nla_len(rule), nl80211_coalesce_policy);
+	if (err)
+		return err;
+
+	if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
+		new_rule->delay =
+			nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
+	if (new_rule->delay > coalesce->max_delay)
+		return -EINVAL;
+
+	if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
+		new_rule->condition =
+			nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
+	if (new_rule->condition != NL80211_COALESCE_CONDITION_MATCH &&
+	    new_rule->condition != NL80211_COALESCE_CONDITION_NO_MATCH)
+		return -EINVAL;
+
+	if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
+		return -EINVAL;
+
+	nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+			    rem)
+		n_patterns++;
+	if (n_patterns > coalesce->n_patterns)
+		return -EINVAL;
+
+	new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
+				     GFP_KERNEL);
+	if (!new_rule->patterns)
+		return -ENOMEM;
+
+	new_rule->n_patterns = n_patterns;
+	i = 0;
+
+	nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+			    rem) {
+		nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
+			  nla_len(pat), NULL);
+		if (!pat_tb[NL80211_PKTPAT_MASK] ||
+		    !pat_tb[NL80211_PKTPAT_PATTERN])
+			return -EINVAL;
+		pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
+		mask_len = DIV_ROUND_UP(pat_len, 8);
+		if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
+			return -EINVAL;
+		if (pat_len > coalesce->pattern_max_len ||
+		    pat_len < coalesce->pattern_min_len)
+			return -EINVAL;
+
+		if (!pat_tb[NL80211_PKTPAT_OFFSET])
+			pkt_offset = 0;
+		else
+			pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
+		if (pkt_offset > coalesce->max_pkt_offset)
+			return -EINVAL;
+		new_rule->patterns[i].pkt_offset = pkt_offset;
+
+		new_rule->patterns[i].mask =
+			kmalloc(mask_len + pat_len, GFP_KERNEL);
+		if (!new_rule->patterns[i].mask)
+			return -ENOMEM;
+		new_rule->patterns[i].pattern =
+			new_rule->patterns[i].mask + mask_len;
+		memcpy(new_rule->patterns[i].mask,
+		       nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len);
+		new_rule->patterns[i].pattern_len = pat_len;
+		memcpy(new_rule->patterns[i].pattern,
+		       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len);
+		i++;
+	}
+
+	return 0;
+}
+
+static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
+	struct cfg80211_coalesce new_coalesce = {};
+	struct cfg80211_coalesce *n_coalesce;
+	int err, rem_rule, n_rules = 0, i, j;
+	struct nlattr *rule;
+	struct cfg80211_coalesce_rules *tmp_rule;
+
+	if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
+		cfg80211_rdev_free_coalesce(rdev);
+		rdev->ops->set_coalesce(&rdev->wiphy, NULL);
+		return 0;
+	}
+
+	nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
+			    rem_rule)
+		n_rules++;
+	if (n_rules > coalesce->n_rules)
+		return -EINVAL;
+
+	new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
+				     GFP_KERNEL);
+	if (!new_coalesce.rules)
+		return -ENOMEM;
+
+	new_coalesce.n_rules = n_rules;
+	i = 0;
+
+	nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
+			    rem_rule) {
+		err = nl80211_parse_coalesce_rule(rdev, rule,
+						  &new_coalesce.rules[i]);
+		if (err)
+			goto error;
+
+		i++;
+	}
+
+	err = rdev->ops->set_coalesce(&rdev->wiphy, &new_coalesce);
+	if (err)
+		goto error;
+
+	n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
+	if (!n_coalesce) {
+		err = -ENOMEM;
+		goto error;
+	}
+	cfg80211_rdev_free_coalesce(rdev);
+	rdev->coalesce = n_coalesce;
+
+	return 0;
+error:
+	for (i = 0; i < new_coalesce.n_rules; i++) {
+		tmp_rule = &new_coalesce.rules[i];
+		for (j = 0; j < tmp_rule->n_patterns; j++)
+			kfree(tmp_rule->patterns[j].mask);
+		kfree(tmp_rule->patterns);
+	}
+	kfree(new_coalesce.rules);
+
+	return err;
+}
+
 static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9041,6 +9350,21 @@ static struct genl_ops nl80211_ops[] = {
 		.flags = GENL_ADMIN_PERM,
 		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL80211_CMD_GET_COALESCE,
+		.doit = nl80211_get_coalesce,
+		.policy = nl80211_policy,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL80211_CMD_SET_COALESCE,
+		.doit = nl80211_set_coalesce,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
 	}
 };
 
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index a4073e8..44341bf 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -74,4 +74,6 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 		     enum nl80211_radar_event event,
 		     struct net_device *netdev, gfp_t gfp);
 
+void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
+
 #endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ae8c186..ad1e406 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -651,6 +651,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
 			continue;
 		if (bss->pub.channel != new->pub.channel)
 			continue;
+		if (bss->pub.scan_width != new->pub.scan_width)
+			continue;
 		if (rcu_access_pointer(bss->pub.beacon_ies))
 			continue;
 		ies = rcu_access_pointer(bss->pub.ies);
@@ -870,11 +872,12 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
 
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 struct cfg80211_bss*
-cfg80211_inform_bss(struct wiphy *wiphy,
-		    struct ieee80211_channel *channel,
-		    const u8 *bssid, u64 tsf, u16 capability,
-		    u16 beacon_interval, const u8 *ie, size_t ielen,
-		    s32 signal, gfp_t gfp)
+cfg80211_inform_bss_width(struct wiphy *wiphy,
+			  struct ieee80211_channel *channel,
+			  enum nl80211_bss_scan_width scan_width,
+			  const u8 *bssid, u64 tsf, u16 capability,
+			  u16 beacon_interval, const u8 *ie, size_t ielen,
+			  s32 signal, gfp_t gfp)
 {
 	struct cfg80211_bss_ies *ies;
 	struct cfg80211_internal_bss tmp = {}, *res;
@@ -892,6 +895,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
 
 	memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
 	tmp.pub.channel = channel;
+	tmp.pub.scan_width = scan_width;
 	tmp.pub.signal = signal;
 	tmp.pub.beacon_interval = beacon_interval;
 	tmp.pub.capability = capability;
@@ -924,14 +928,15 @@ cfg80211_inform_bss(struct wiphy *wiphy,
 	/* cfg80211_bss_update gives us a referenced result */
 	return &res->pub;
 }
-EXPORT_SYMBOL(cfg80211_inform_bss);
+EXPORT_SYMBOL(cfg80211_inform_bss_width);
 
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 struct cfg80211_bss *
-cfg80211_inform_bss_frame(struct wiphy *wiphy,
-			  struct ieee80211_channel *channel,
-			  struct ieee80211_mgmt *mgmt, size_t len,
-			  s32 signal, gfp_t gfp)
+cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
+				struct ieee80211_channel *channel,
+				enum nl80211_bss_scan_width scan_width,
+				struct ieee80211_mgmt *mgmt, size_t len,
+				s32 signal, gfp_t gfp)
 {
 	struct cfg80211_internal_bss tmp = {}, *res;
 	struct cfg80211_bss_ies *ies;
@@ -941,7 +946,8 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
 	BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
 			offsetof(struct ieee80211_mgmt, u.beacon.variable));
 
-	trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal);
+	trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt,
+					      len, signal);
 
 	if (WARN_ON(!mgmt))
 		return NULL;
@@ -976,6 +982,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
 	
 	memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN);
 	tmp.pub.channel = channel;
+	tmp.pub.scan_width = scan_width;
 	tmp.pub.signal = signal;
 	tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
 	tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
@@ -991,7 +998,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
 	/* cfg80211_bss_update gives us a referenced result */
 	return &res->pub;
 }
-EXPORT_SYMBOL(cfg80211_inform_bss_frame);
+EXPORT_SYMBOL(cfg80211_inform_bss_width_frame);
 
 void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
 {
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index a23253e..9ee6bc1 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -30,7 +30,8 @@ static ssize_t name ## _show(struct device *dev,			\
 			      char *buf)				\
 {									\
 	return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member);	\
-}
+}									\
+static DEVICE_ATTR_RO(name)
 
 SHOW_FMT(index, "%d", wiphy_idx);
 SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
@@ -42,7 +43,7 @@ static ssize_t name_show(struct device *dev,
 	struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
 	return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
 }
-
+static DEVICE_ATTR_RO(name);
 
 static ssize_t addresses_show(struct device *dev,
 			      struct device_attribute *attr,
@@ -60,15 +61,17 @@ static ssize_t addresses_show(struct device *dev,
 
 	return buf - start;
 }
-
-static struct device_attribute ieee80211_dev_attrs[] = {
-	__ATTR_RO(index),
-	__ATTR_RO(macaddress),
-	__ATTR_RO(address_mask),
-	__ATTR_RO(addresses),
-	__ATTR_RO(name),
-	{}
+static DEVICE_ATTR_RO(addresses);
+
+static struct attribute *ieee80211_attrs[] = {
+	&dev_attr_index.attr,
+	&dev_attr_macaddress.attr,
+	&dev_attr_address_mask.attr,
+	&dev_attr_addresses.attr,
+	&dev_attr_name.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(ieee80211);
 
 static void wiphy_dev_release(struct device *dev)
 {
@@ -146,7 +149,7 @@ struct class ieee80211_class = {
 	.name = "ieee80211",
 	.owner = THIS_MODULE,
 	.dev_release = wiphy_dev_release,
-	.dev_attrs = ieee80211_dev_attrs,
+	.dev_groups = ieee80211_groups,
 	.dev_uevent = wiphy_uevent,
 #ifdef CONFIG_PM
 	.suspend = wiphy_suspend,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index e1534baf..09af6eb 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2391,26 +2391,30 @@ TRACE_EVENT(cfg80211_get_bss,
 		  __entry->capa_mask, __entry->capa_val)
 );
 
-TRACE_EVENT(cfg80211_inform_bss_frame,
+TRACE_EVENT(cfg80211_inform_bss_width_frame,
 	TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
+		 enum nl80211_bss_scan_width scan_width,
 		 struct ieee80211_mgmt *mgmt, size_t len,
 		 s32 signal),
-	TP_ARGS(wiphy, channel, mgmt, len, signal),
+	TP_ARGS(wiphy, channel, scan_width, mgmt, len, signal),
 	TP_STRUCT__entry(
 		WIPHY_ENTRY
 		CHAN_ENTRY
+		__field(enum nl80211_bss_scan_width, scan_width)
 		__dynamic_array(u8, mgmt, len)
 		__field(s32, signal)
 	),
 	TP_fast_assign(
 		WIPHY_ASSIGN;
 		CHAN_ASSIGN(channel);
+		__entry->scan_width = scan_width;
 		if (mgmt)
 			memcpy(__get_dynamic_array(mgmt), mgmt, len);
 		__entry->signal = signal;
 	),
-	TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d",
-		  WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal)
+	TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d",
+		  WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
+		  __entry->signal)
 );
 
 DECLARE_EVENT_CLASS(cfg80211_bss_evt,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 74458b7..ce090c1 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -33,7 +33,8 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
 }
 EXPORT_SYMBOL(ieee80211_get_response_rate);
 
-u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
+u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
+			      enum nl80211_bss_scan_width scan_width)
 {
 	struct ieee80211_rate *bitrates;
 	u32 mandatory_rates = 0;
@@ -43,10 +44,15 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
 	if (WARN_ON(!sband))
 		return 1;
 
-	if (sband->band == IEEE80211_BAND_2GHZ)
-		mandatory_flag = IEEE80211_RATE_MANDATORY_B;
-	else
+	if (sband->band == IEEE80211_BAND_2GHZ) {
+		if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||
+		    scan_width == NL80211_BSS_CHAN_WIDTH_10)
+			mandatory_flag = IEEE80211_RATE_MANDATORY_G;
+		else
+			mandatory_flag = IEEE80211_RATE_MANDATORY_B;
+	} else {
 		mandatory_flag = IEEE80211_RATE_MANDATORY_A;
+	}
 
 	bitrates = sband->bitrates;
 	for (i = 0; i < sband->n_bitrates; i++)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e52cab3..f7078eb 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -308,7 +308,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
 {
 	BUG_ON(!policy->walk.dead);
 
-	if (del_timer(&policy->timer))
+	if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer))
 		BUG();
 
 	security_xfrm_policy_free(policy->security);
@@ -660,7 +660,13 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
 	xfrm_pol_hold(policy);
 	net->xfrm.policy_count[dir]++;
 	atomic_inc(&flow_cache_genid);
-	rt_genid_bump(net);
+
+	/* After previous checking, family can either be AF_INET or AF_INET6 */
+	if (policy->family == AF_INET)
+		rt_genid_bump_ipv4(net);
+	else
+		rt_genid_bump_ipv6(net);
+
 	if (delpol) {
 		xfrm_policy_requeue(delpol, policy);
 		__xfrm_policy_unlink(delpol, dir);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 78f66fa..b2cd806 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -990,11 +990,13 @@ void xfrm_state_insert(struct xfrm_state *x)
 EXPORT_SYMBOL(xfrm_state_insert);
 
 /* xfrm_state_lock is held */
-static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m,
+static struct xfrm_state *__find_acq_core(struct net *net,
+					  const struct xfrm_mark *m,
 					  unsigned short family, u8 mode,
 					  u32 reqid, u8 proto,
 					  const xfrm_address_t *daddr,
-					  const xfrm_address_t *saddr, int create)
+					  const xfrm_address_t *saddr,
+					  int create)
 {
 	unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
 	struct xfrm_state *x;
@@ -1399,9 +1401,9 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
 EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
 
 struct xfrm_state *
-xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
-	      const xfrm_address_t *daddr, const xfrm_address_t *saddr,
-	      int create, unsigned short family)
+xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid,
+	      u8 proto, const xfrm_address_t *daddr,
+	      const xfrm_address_t *saddr, int create, unsigned short family)
 {
 	struct xfrm_state *x;
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2ee9eb7..3ba2db6 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -31,12 +31,16 @@ my $show_types = 0;
 my $fix = 0;
 my $root;
 my %debug;
-my %ignore_type = ();
 my %camelcase = ();
+my %use_type = ();
+my @use = ();
+my %ignore_type = ();
 my @ignore = ();
 my $help = 0;
 my $configuration_file = ".checkpatch.conf";
 my $max_line_length = 80;
+my $ignore_perl_version = 0;
+my $minimum_perl_version = 5.10.0;
 
 sub help {
 	my ($exitcode) = @_;
@@ -54,6 +58,7 @@ Options:
   --terse                    one line per report
   -f, --file                 treat FILE as regular source file
   --subjective, --strict     enable more subjective tests
+  --types TYPE(,TYPE2...)    show only these comma separated message types
   --ignore TYPE(,TYPE2...)   ignore various comma separated message types
   --max-line-length=n        set the maximum line length, if exceeded, warn
   --show-types               show the message "types" in the output
@@ -71,6 +76,8 @@ Options:
                              "<inputfile>.EXPERIMENTAL-checkpatch-fixes"
                              with potential errors corrected to the preferred
                              checkpatch style
+  --ignore-perl-version      override checking of perl version.  expect
+                             runtime errors.
   -h, --help, --version      display this help and exit
 
 When FILE is - read standard input.
@@ -116,6 +123,7 @@ GetOptions(
 	'subjective!'	=> \$check,
 	'strict!'	=> \$check,
 	'ignore=s'	=> \@ignore,
+	'types=s'	=> \@use,
 	'show-types!'	=> \$show_types,
 	'max-line-length=i' => \$max_line_length,
 	'root=s'	=> \$root,
@@ -123,6 +131,7 @@ GetOptions(
 	'mailback!'	=> \$mailback,
 	'summary-file!'	=> \$summary_file,
 	'fix!'		=> \$fix,
+	'ignore-perl-version!' => \$ignore_perl_version,
 	'debug=s'	=> \%debug,
 	'test-only=s'	=> \$tst_only,
 	'h|help'	=> \$help,
@@ -133,24 +142,50 @@ help(0) if ($help);
 
 my $exit = 0;
 
+if ($^V && $^V lt $minimum_perl_version) {
+	printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
+	if (!$ignore_perl_version) {
+		exit(1);
+	}
+}
+
 if ($#ARGV < 0) {
 	print "$P: no input files\n";
 	exit(1);
 }
 
-@ignore = split(/,/, join(',',@ignore));
-foreach my $word (@ignore) {
-	$word =~ s/\s*\n?$//g;
-	$word =~ s/^\s*//g;
-	$word =~ s/\s+/ /g;
-	$word =~ tr/[a-z]/[A-Z]/;
+sub hash_save_array_words {
+	my ($hashRef, $arrayRef) = @_;
+
+	my @array = split(/,/, join(',', @$arrayRef));
+	foreach my $word (@array) {
+		$word =~ s/\s*\n?$//g;
+		$word =~ s/^\s*//g;
+		$word =~ s/\s+/ /g;
+		$word =~ tr/[a-z]/[A-Z]/;
+
+		next if ($word =~ m/^\s*#/);
+		next if ($word =~ m/^\s*$/);
+
+		$hashRef->{$word}++;
+	}
+}
 
-	next if ($word =~ m/^\s*#/);
-	next if ($word =~ m/^\s*$/);
+sub hash_show_words {
+	my ($hashRef, $prefix) = @_;
 
-	$ignore_type{$word}++;
+	if ($quiet == 0 && keys $hashRef) {
+		print "NOTE: $prefix message types:";
+		foreach my $word (sort keys $hashRef) {
+			print " $word";
+		}
+		print "\n\n";
+	}
 }
 
+hash_save_array_words(\%ignore_type, \@ignore);
+hash_save_array_words(\%use_type, \@use);
+
 my $dbg_values = 0;
 my $dbg_possible = 0;
 my $dbg_type = 0;
@@ -1355,7 +1390,9 @@ sub possible {
 my $prefix = '';
 
 sub show_type {
-       return !defined $ignore_type{$_[0]};
+	return defined $use_type{$_[0]} if (scalar keys %use_type > 0);
+
+	return !defined $ignore_type{$_[0]};
 }
 
 sub report {
@@ -1532,6 +1569,7 @@ sub process {
 	my %suppress_export;
 	my $suppress_statement = 0;
 
+	my %signatures = ();
 
 	# Pre-scan the patch sanitizing the lines.
 	# Pre-scan the patch looking for any __setup documentation.
@@ -1781,6 +1819,17 @@ sub process {
 					     "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
 				}
 			}
+
+# Check for duplicate signatures
+			my $sig_nospace = $line;
+			$sig_nospace =~ s/\s//g;
+			$sig_nospace = lc($sig_nospace);
+			if (defined $signatures{$sig_nospace}) {
+				WARN("BAD_SIGN_OFF",
+				     "Duplicate signature\n" . $herecurr);
+			} else {
+				$signatures{$sig_nospace} = 1;
+			}
 		}
 
 # Check for wrappage within a valid hunk of the file
@@ -1845,15 +1894,17 @@ sub process {
 #trailing whitespace
 		if ($line =~ /^\+.*\015/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			ERROR("DOS_LINE_ENDINGS",
-			      "DOS line endings\n" . $herevet);
-
+			if (ERROR("DOS_LINE_ENDINGS",
+				  "DOS line endings\n" . $herevet) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/[\s\015]+$//;
+			}
 		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
 			if (ERROR("TRAILING_WHITESPACE",
 				  "trailing whitespace\n" . $herevet) &&
 			    $fix) {
-				$fixed[$linenr - 1] =~ s/^(\+.*?)\s+$/$1/;
+				$fixed[$linenr - 1] =~ s/\s+$//;
 			}
 
 			$rpt_cleaners = 1;
@@ -2060,6 +2111,7 @@ sub process {
 		if ($realfile =~ m@^(drivers/net/|net/)@ &&
 		    $prevrawline =~ /^\+[ \t]*\/\*/ &&		#starting /*
 		    $prevrawline !~ /\*\/[ \t]*$/ &&		#no trailing */
+		    $rawline =~ /^\+/ &&			#line is new
 		    $rawline !~ /^\+[ \t]*\*/) {		#no leading *
 			WARN("NETWORKING_BLOCK_COMMENT_STYLE",
 			     "networking block comments start with * on subsequent lines\n" . $hereprev);
@@ -2486,16 +2538,22 @@ sub process {
 		}
 
 # check for global initialisers.
-		if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
-			ERROR("GLOBAL_INITIALISERS",
-			      "do not initialise globals to 0 or NULL\n" .
-				$herecurr);
+		if ($line =~ /^\+(\s*$Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/) {
+			if (ERROR("GLOBAL_INITIALISERS",
+				  "do not initialise globals to 0 or NULL\n" .
+				      $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/;
+			}
 		}
 # check for static initialisers.
-		if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
-			ERROR("INITIALISED_STATIC",
-			      "do not initialise statics to 0 or NULL\n" .
-				$herecurr);
+		if ($line =~ /^\+.*\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
+			if (ERROR("INITIALISED_STATIC",
+				  "do not initialise statics to 0 or NULL\n" .
+				      $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/;
+			}
 		}
 
 # check for static const char * arrays.
@@ -2638,8 +2696,12 @@ sub process {
 		}
 
 		if ($line =~ /\bpr_warning\s*\(/) {
-			WARN("PREFER_PR_LEVEL",
-			     "Prefer pr_warn(... to pr_warning(...\n" . $herecurr);
+			if (WARN("PREFER_PR_LEVEL",
+				 "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~
+				    s/\bpr_warning\b/pr_warn/;
+			}
 		}
 
 		if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
@@ -3031,8 +3093,7 @@ sub process {
 			if (ERROR("SPACING",
 				  "space required before the open brace '{'\n" . $herecurr) &&
 			    $fix) {
-				$fixed[$linenr - 1] =~
-				    s/^(\+.*(?:do|\))){/$1 {/;
+				$fixed[$linenr - 1] =~ s/^(\+.*(?:do|\))){/$1 {/;
 			}
 		}
 
@@ -3047,8 +3108,12 @@ sub process {
 # closing brace should have a space following it when it has anything
 # on the line
 		if ($line =~ /}(?!(?:,|;|\)))\S/) {
-			ERROR("SPACING",
-			      "space required after that close brace '}'\n" . $herecurr);
+			if (ERROR("SPACING",
+				  "space required after that close brace '}'\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~
+				    s/}((?!(?:,|;|\)))\S)/} $1/;
+			}
 		}
 
 # check spacing on square brackets
@@ -3271,8 +3336,13 @@ sub process {
 
 #gcc binary extension
 			if ($var =~ /^$Binary$/) {
-				WARN("GCC_BINARY_CONSTANT",
-				     "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr);
+				if (WARN("GCC_BINARY_CONSTANT",
+					 "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
+				    $fix) {
+					my $hexval = sprintf("0x%x", oct($var));
+					$fixed[$linenr - 1] =~
+					    s/\b$var\b/$hexval/;
+				}
 			}
 
 #CamelCase
@@ -3282,19 +3352,26 @@ sub process {
 			    $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
 #Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show)
 			    $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/) {
-				seed_camelcase_includes() if ($check);
-				if (!defined $camelcase{$var}) {
-					$camelcase{$var} = 1;
-					CHK("CAMELCASE",
-					    "Avoid CamelCase: <$var>\n" . $herecurr);
+				while ($var =~ m{($Ident)}g) {
+					my $word = $1;
+					next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
+					seed_camelcase_includes() if ($check);
+					if (!defined $camelcase{$word}) {
+						$camelcase{$word} = 1;
+						CHK("CAMELCASE",
+						    "Avoid CamelCase: <$word>\n" . $herecurr);
+					}
 				}
 			}
 		}
 
 #no spaces allowed after \ in define
-		if ($line=~/\#\s*define.*\\\s$/) {
-			WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
-			     "Whitepspace after \\ makes next lines useless\n" . $herecurr);
+		if ($line =~ /\#\s*define.*\\\s+$/) {
+			if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
+				 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/\s+$//;
+			}
 		}
 
 #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
@@ -3691,8 +3768,12 @@ sub process {
 
 # Check for __inline__ and __inline, prefer inline
 		if ($line =~ /\b(__inline__|__inline)\b/) {
-			WARN("INLINE",
-			     "plain inline is preferred over $1\n" . $herecurr);
+			if (WARN("INLINE",
+				 "plain inline is preferred over $1\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/\b(__inline__|__inline)\b/inline/;
+
+			}
 		}
 
 # Check for __attribute__ packed, prefer __packed
@@ -3709,14 +3790,21 @@ sub process {
 
 # Check for __attribute__ format(printf, prefer __printf
 		if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
-			WARN("PREFER_PRINTF",
-			     "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr);
+			if (WARN("PREFER_PRINTF",
+				 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
+
+			}
 		}
 
 # Check for __attribute__ format(scanf, prefer __scanf
 		if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
-			WARN("PREFER_SCANF",
-			     "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr);
+			if (WARN("PREFER_SCANF",
+				 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
+			}
 		}
 
 # check for sizeof(&)
@@ -3727,8 +3815,11 @@ sub process {
 
 # check for sizeof without parenthesis
 		if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
-			WARN("SIZEOF_PARENTHESIS",
-			     "sizeof $1 should be sizeof($1)\n" . $herecurr);
+			if (WARN("SIZEOF_PARENTHESIS",
+				 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
+			}
 		}
 
 # check for line continuations in quoted strings with odd counts of "
@@ -3747,8 +3838,11 @@ sub process {
 		if ($line =~ /\bseq_printf\s*\(/) {
 			my $fmt = get_quoted_string($line, $rawline);
 			if ($fmt !~ /[^\\]\%/) {
-				WARN("PREFER_SEQ_PUTS",
-				     "Prefer seq_puts to seq_printf\n" . $herecurr);
+				if (WARN("PREFER_SEQ_PUTS",
+					 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
+				    $fix) {
+					$fixed[$linenr - 1] =~ s/\bseq_printf\b/seq_puts/;
+				}
 			}
 		}
 
@@ -3810,6 +3904,16 @@ sub process {
 			}
 		}
 
+# check for new externs in .h files.
+		if ($realfile =~ /\.h$/ &&
+		    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
+			if (WARN("AVOID_EXTERNS",
+				 "extern prototypes should be avoided in .h files\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
+			}
+		}
+
 # check for new externs in .c files.
 		if ($realfile =~ /\.c$/ && defined $stat &&
 		    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
@@ -3879,8 +3983,11 @@ sub process {
 
 # check for multiple semicolons
 		if ($line =~ /;\s*;\s*$/) {
-			WARN("ONE_SEMICOLON",
-			     "Statements terminations use 1 semicolon\n" . $herecurr);
+			if (WARN("ONE_SEMICOLON",
+				 "Statements terminations use 1 semicolon\n" . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/(\s*;\s*){2,}$/;/g;
+			}
 		}
 
 # check for switch/default statements without a break;
@@ -3898,9 +4005,12 @@ sub process {
 		}
 
 # check for gcc specific __FUNCTION__
-		if ($line =~ /__FUNCTION__/) {
-			WARN("USE_FUNC",
-			     "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr);
+		if ($line =~ /\b__FUNCTION__\b/) {
+			if (WARN("USE_FUNC",
+				 "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr) &&
+			    $fix) {
+				$fixed[$linenr - 1] =~ s/\b__FUNCTION__\b/__func__/g;
+			}
 		}
 
 # check for use of yield()
@@ -4105,13 +4215,8 @@ sub process {
 		}
 	}
 
-	if ($quiet == 0 && keys %ignore_type) {
-	    print "NOTE: Ignored message types:";
-	    foreach my $ignore (sort keys %ignore_type) {
-		print " $ignore";
-	    }
-	    print "\n\n";
-	}
+	hash_show_words(\%use_type, "Used");
+	hash_show_words(\%ignore_type, "Ignored");
 
 	if ($clean == 0 && $fix && "@rawlines" ne "@fixed") {
 		my $newfile = $filename . ".EXPERIMENTAL-checkpatch-fixes";
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci
index 2274638..e18f840 100644
--- a/scripts/coccinelle/api/ptr_ret.cocci
+++ b/scripts/coccinelle/api/ptr_ret.cocci
@@ -1,5 +1,5 @@
 ///
-/// Use PTR_RET rather than if(IS_ERR(...)) + PTR_ERR
+/// Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
 ///
 // Confidence: High
 // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
@@ -7,7 +7,7 @@
 // URL: http://coccinelle.lip6.fr/
 // Options: --no-includes --include-headers
 //
-// Keywords: ERR_PTR, PTR_ERR, PTR_RET
+// Keywords: ERR_PTR, PTR_ERR, PTR_RET, PTR_ERR_OR_ZERO
 // Version min: 2.6.39
 //
 
@@ -21,21 +21,21 @@ expression ptr;
 @@
 
 - if (IS_ERR(ptr)) return PTR_ERR(ptr); else return 0;
-+ return PTR_RET(ptr);
++ return PTR_ERR_OR_ZERO(ptr);
 
 @depends on patch@
 expression ptr;
 @@
 
 - if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
-+ return PTR_RET(ptr);
++ return PTR_ERR_OR_ZERO(ptr);
 
 @depends on patch@
 expression ptr;
 @@
 
 - (IS_ERR(ptr) ? PTR_ERR(ptr) : 0)
-+ PTR_RET(ptr)
++ PTR_ERR_OR_ZERO(ptr)
 
 @r1 depends on !patch@
 expression ptr;
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 6c9c45f..2c39631 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -401,8 +401,8 @@ static void search_conf(void)
 	struct subtitle_part stpart;
 
 	title = str_new();
-	str_printf( &title, _("Enter %s (sub)string or regexp to search for "
-			      "(with or without \"%s\")"), CONFIG_, CONFIG_);
+	str_printf( &title, _("Enter (sub)string or regexp to search for "
+			      "(with or without \"%s\")"), CONFIG_);
 
 again:
 	dialog_clear();
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 7975d8d..4fbecd2 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -695,8 +695,8 @@ static void search_conf(void)
 	int dres;
 
 	title = str_new();
-	str_printf( &title, _("Enter %s (sub)string or regexp to search for "
-			      "(with or without \"%s\")"), CONFIG_, CONFIG_);
+	str_printf( &title, _("Enter (sub)string or regexp to search for "
+			      "(with or without \"%s\")"), CONFIG_);
 
 again:
 	dres = dialog_inputbox(main_window,
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index d550300..a76b8fd 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -963,11 +963,11 @@ struct sym_match {
  * - first, symbols that match exactly
  * - then, alphabetical sort
  */
-static int sym_rel_comp( const void *sym1, const void *sym2 )
+static int sym_rel_comp(const void *sym1, const void *sym2)
 {
-	struct sym_match *s1 = *(struct sym_match **)sym1;
-	struct sym_match *s2 = *(struct sym_match **)sym2;
-	int l1, l2;
+	const struct sym_match *s1 = sym1;
+	const struct sym_match *s2 = sym2;
+	int exact1, exact2;
 
 	/* Exact match:
 	 * - if matched length on symbol s1 is the length of that symbol,
@@ -978,11 +978,11 @@ static int sym_rel_comp( const void *sym1, const void *sym2 )
 	 * exactly; if this is the case, we can't decide which comes first,
 	 * and we fallback to sorting alphabetically.
 	 */
-	l1 = s1->eo - s1->so;
-	l2 = s2->eo - s2->so;
-	if (l1 == strlen(s1->sym->name) && l2 != strlen(s2->sym->name))
+	exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
+	exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
+	if (exact1 && !exact2)
 		return -1;
-	if (l1 != strlen(s1->sym->name) && l2 == strlen(s2->sym->name))
+	if (!exact1 && exact2)
 		return 1;
 
 	/* As a fallback, sort symbols alphabetically */
@@ -992,7 +992,7 @@ static int sym_rel_comp( const void *sym1, const void *sym2 )
 struct symbol **sym_re_search(const char *pattern)
 {
 	struct symbol *sym, **sym_arr = NULL;
-	struct sym_match **sym_match_arr = NULL;
+	struct sym_match *sym_match_arr = NULL;
 	int i, cnt, size;
 	regex_t re;
 	regmatch_t match[1];
@@ -1005,47 +1005,38 @@ struct symbol **sym_re_search(const char *pattern)
 		return NULL;
 
 	for_all_symbols(i, sym) {
-		struct sym_match *tmp_sym_match;
 		if (sym->flags & SYMBOL_CONST || !sym->name)
 			continue;
 		if (regexec(&re, sym->name, 1, match, 0))
 			continue;
-		if (cnt + 1 >= size) {
+		if (cnt >= size) {
 			void *tmp;
 			size += 16;
-			tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *));
-			if (!tmp) {
+			tmp = realloc(sym_match_arr, size * sizeof(struct sym_match));
+			if (!tmp)
 				goto sym_re_search_free;
-			}
 			sym_match_arr = tmp;
 		}
 		sym_calc_value(sym);
-		tmp_sym_match = (struct sym_match*)malloc(sizeof(struct sym_match));
-		if (!tmp_sym_match)
-			goto sym_re_search_free;
-		tmp_sym_match->sym = sym;
-		/* As regexec return 0, we know we have a match, so
+		/* As regexec returned 0, we know we have a match, so
 		 * we can use match[0].rm_[se]o without further checks
 		 */
-		tmp_sym_match->so = match[0].rm_so;
-		tmp_sym_match->eo = match[0].rm_eo;
-		sym_match_arr[cnt++] = tmp_sym_match;
+		sym_match_arr[cnt].so = match[0].rm_so;
+		sym_match_arr[cnt].eo = match[0].rm_eo;
+		sym_match_arr[cnt++].sym = sym;
 	}
 	if (sym_match_arr) {
-		qsort(sym_match_arr, cnt, sizeof(struct sym_match*), sym_rel_comp);
+		qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
 		sym_arr = malloc((cnt+1) * sizeof(struct symbol));
 		if (!sym_arr)
 			goto sym_re_search_free;
 		for (i = 0; i < cnt; i++)
-			sym_arr[i] = sym_match_arr[i]->sym;
+			sym_arr[i] = sym_match_arr[i].sym;
 		sym_arr[cnt] = NULL;
 	}
 sym_re_search_free:
-	if (sym_match_arr) {
-		for (i = 0; i < cnt; i++)
-			free(sym_match_arr[i]);
-		free(sym_match_arr);
-	}
+	/* sym_match_arr can be NULL if no match, but free(NULL) is OK */
+	free(sym_match_arr);
 	regfree(&re);
 
 	return sym_arr;
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index acb8650..de89923 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -41,9 +41,9 @@ create_package() {
 	parisc*)
 		debarch=hppa ;;
 	mips*)
-		debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
+		debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el) ;;
 	arm*)
-		debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
+		debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el) ;;
 	*)
 		echo "" >&2
 		echo "** ** **  WARNING  ** ** **" >&2
@@ -78,17 +78,35 @@ tmpdir="$objtree/debian/tmp"
 fwdir="$objtree/debian/fwtmp"
 kernel_headers_dir="$objtree/debian/hdrtmp"
 libc_headers_dir="$objtree/debian/headertmp"
+dbg_dir="$objtree/debian/dbgtmp"
 packagename=linux-image-$version
 fwpackagename=linux-firmware-image
 kernel_headers_packagename=linux-headers-$version
 libc_headers_packagename=linux-libc-dev
+dbg_packagename=$packagename-dbg
 
 if [ "$ARCH" = "um" ] ; then
 	packagename=user-mode-linux-$version
 fi
 
+# Not all arches have the same installed path in debian
+# XXX: have each arch Makefile export a variable of the canonical image install
+# path instead
+case $ARCH in
+um)
+	installed_image_path="usr/bin/linux-$version"
+	;;
+parisc|mips|powerpc)
+	installed_image_path="boot/vmlinux-$version"
+	;;
+*)
+	installed_image_path="boot/vmlinuz-$version"
+esac
+
+BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
+
 # Setup the directory structure
-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir"
+rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir"
 mkdir -m 755 -p "$tmpdir/DEBIAN"
 mkdir -p  "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename"
 mkdir -m 755 -p "$fwdir/DEBIAN"
@@ -101,26 +119,29 @@ mkdir -p "$kernel_headers_dir/lib/modules/$version/"
 if [ "$ARCH" = "um" ] ; then
 	mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin"
 fi
+if [ -n "$BUILD_DEBUG" ] ; then
+	mkdir -p "$dbg_dir/usr/share/doc/$dbg_packagename"
+	mkdir -m 755 -p "$dbg_dir/DEBIAN"
+fi
 
 # Build and install the kernel
 if [ "$ARCH" = "um" ] ; then
 	$MAKE linux
 	cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
-	cp .config "$tmpdir/usr/share/doc/$packagename/config"
+	cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config"
 	gzip "$tmpdir/usr/share/doc/$packagename/config"
-	cp $KBUILD_IMAGE "$tmpdir/usr/bin/linux-$version"
 else 
 	cp System.map "$tmpdir/boot/System.map-$version"
-	cp .config "$tmpdir/boot/config-$version"
-	# Not all arches include the boot path in KBUILD_IMAGE
-	if [ -e $KBUILD_IMAGE ]; then
-		cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
-	else
-		cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
-	fi
+	cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version"
+fi
+# Not all arches include the boot path in KBUILD_IMAGE
+if [ -e $KBUILD_IMAGE ]; then
+	cp $KBUILD_IMAGE "$tmpdir/$installed_image_path"
+else
+	cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/$installed_image_path"
 fi
 
-if grep -q '^CONFIG_MODULES=y' .config ; then
+if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
 	INSTALL_MOD_PATH="$tmpdir" $MAKE KBUILD_SRC= modules_install
 	rm -f "$tmpdir/lib/modules/$version/build"
 	rm -f "$tmpdir/lib/modules/$version/source"
@@ -128,6 +149,20 @@ if grep -q '^CONFIG_MODULES=y' .config ; then
 		mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
 		rmdir "$tmpdir/lib/modules/$version"
 	fi
+	if [ -n "$BUILD_DEBUG" ] ; then
+		(
+			cd $tmpdir
+			for module in $(find lib/modules/ -name *.ko); do
+				mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module)
+				# only keep debug symbols in the debug file
+				objcopy --only-keep-debug $module $dbg_dir/usr/lib/debug/$module
+				# strip original module from debug symbols
+				objcopy --strip-debug $module
+				# then add a link to those
+				objcopy --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $module
+			done
+		)
+	fi
 fi
 
 if [ "$ARCH" != "um" ]; then
@@ -149,7 +184,7 @@ set -e
 # Pass maintainer script parameters to hook scripts
 export DEB_MAINT_PARAMS="\$*"
 
-test -d $debhookdir/$script.d && run-parts --arg="$version" $debhookdir/$script.d
+test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
 exit 0
 EOF
 	chmod 755 "$tmpdir/DEBIAN/$script"
@@ -245,11 +280,12 @@ fi
 # Build header package
 (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles")
 (cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles")
-(cd $objtree; find arch/$SRCARCH/include .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles")
+(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles")
 destdir=$kernel_headers_dir/usr/src/linux-headers-$version
 mkdir -p "$destdir"
 (cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -)
 (cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -)
+(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
 ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
 rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
 arch=$(dpkg --print-architecture)
@@ -299,4 +335,30 @@ fi
 
 create_package "$packagename" "$tmpdir"
 
+if [ -n "$BUILD_DEBUG" ] ; then
+	# Build debug package
+	# Different tools want the image in different locations
+	# perf
+	mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/
+	cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/
+	# systemtap
+	mkdir -p $dbg_dir/usr/lib/debug/boot/
+	ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version
+	# kdump-tools
+	ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version
+
+	cat <<EOF >> debian/control
+
+Package: $dbg_packagename
+Section: debug
+Provides: linux-debug, linux-debug-$version
+Architecture: any
+Description: Linux kernel debugging symbols for $version
+ This package will come in handy if you need to debug the kernel. It provides
+ all the necessary debug symbols for the kernel and its modules.
+EOF
+
+	create_package "$dbg_packagename" "$dbg_dir"
+fi
+
 exit 0
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index cdd9bb9..aa22f94 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -87,6 +87,27 @@ case "${ARCH}" in
 		[ -f "${objtree}/vmlinux.SYS" ] && cp -v -- "${objtree}/vmlinux.SYS" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}.SYS"
 		[ -f "${objtree}/vmlinux.dsk" ] && cp -v -- "${objtree}/vmlinux.dsk" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}.dsk"
 		;;
+	mips)
+		if [ -f "${objtree}/arch/mips/boot/compressed/vmlinux.bin" ]; then
+			cp -v -- "${objtree}/arch/mips/boot/compressed/vmlinux.bin" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
+		elif [ -f "${objtree}/arch/mips/boot/compressed/vmlinux.ecoff" ]; then
+			cp -v -- "${objtree}/arch/mips/boot/compressed/vmlinux.ecoff" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
+		elif [ -f "${objtree}/arch/mips/boot/compressed/vmlinux.srec" ]; then
+			cp -v -- "${objtree}/arch/mips/boot/compressed/vmlinux.srec" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
+		elif [ -f "${objtree}/vmlinux.32" ]; then
+			cp -v -- "${objtree}/vmlinux.32" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
+		elif [ -f "${objtree}/vmlinux.64" ]; then
+			cp -v -- "${objtree}/vmlinux.64" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
+		elif [ -f "${objtree}/arch/mips/boot/vmlinux.bin" ]; then
+			cp -v -- "${objtree}/arch/mips/boot/vmlinux.bin" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
+		elif [ -f "${objtree}/arch/mips/boot/vmlinux.ecoff" ]; then
+			cp -v -- "${objtree}/arch/mips/boot/vmlinux.ecoff" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
+		elif [ -f "${objtree}/arch/mips/boot/vmlinux.srec" ]; then
+			cp -v -- "${objtree}/arch/mips/boot/vmlinux.srec" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
+		elif [ -f "${objtree}/vmlinux" ]; then
+			cp -v -- "${objtree}/vmlinux" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
+		fi
+		;;
 	*)
 		[ -f "${KBUILD_IMAGE}" ] && cp -v -- "${KBUILD_IMAGE}" "${tmpdir}/boot/vmlinux-kbuild-${KERNELRELEASE}"
 		echo "" >&2
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index fdd3fbf..1395760 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
-#	Output a simple RPM spec file that uses no fancy features requiring
-#	RPM v4. This is intended to work with any RPM distro.
+#	Output a simple RPM spec file.
+#	This version assumes a minimum of RPM 4.0.3.
 #
 #	The only gothic bit here is redefining install_post to avoid
 #	stripping the symbols from files in the kernel which we want
@@ -59,6 +59,14 @@ echo "header files define structures and constants that are needed for"
 echo "building most standard programs and are also needed for rebuilding the"
 echo "glibc package."
 echo ""
+echo "%package devel"
+echo "Summary: Development package for building kernel modules to match the $__KERNELRELEASE kernel"
+echo "Group: System Environment/Kernel"
+echo "AutoReqProv: no"
+echo "%description -n kernel-devel"
+echo "This package provides kernel headers and makefiles sufficient to build modules"
+echo "against the $__KERNELRELEASE kernel package."
+echo ""
 
 if ! $PREBUILT; then
 echo "%prep"
@@ -77,13 +85,14 @@ echo "%install"
 echo 'KBUILD_IMAGE=$(make image_name)'
 echo "%ifarch ia64"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib/modules'
-echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware'
 echo "%else"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules'
-echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware'
 echo "%endif"
+echo 'mkdir -p $RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE"
 
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} KBUILD_SRC= modules_install'
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} KBUILD_SRC= mod-fw= modules_install'
+echo 'INSTALL_FW_PATH=$RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE"
+echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' firmware_install
 echo "%ifarch ia64"
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
 echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
@@ -108,18 +117,43 @@ echo 'mv vmlinux.bz2 $RPM_BUILD_ROOT'"/boot/vmlinux-$KERNELRELEASE.bz2"
 echo 'mv vmlinux.orig vmlinux'
 echo "%endif"
 
+echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/{build,source}"
+echo "mkdir -p "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE"
+echo "EXCLUDES=\"$RCS_TAR_IGNORE --exclude .tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude=firmware --exclude .config.old --exclude .missing-syscalls.d\""
+echo "tar "'$EXCLUDES'" -cf- . | (cd "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE;tar xvf -)"
+echo 'cd $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE"
+echo "ln -sf /usr/src/kernels/$KERNELRELEASE build"
+echo "ln -sf /usr/src/kernels/$KERNELRELEASE source"
+
 echo ""
 echo "%clean"
 echo 'rm -rf $RPM_BUILD_ROOT'
 echo ""
+echo "%post"
+echo "if [ -x /sbin/installkernel -a -r /boot/vmlinuz-$KERNELRELEASE -a -r /boot/System.map-$KERNELRELEASE ]; then"
+echo "cp /boot/vmlinuz-$KERNELRELEASE /boot/vmlinuz-$KERNELRELEASE-rpm"
+echo "cp /boot/System.map-$KERNELRELEASE /boot/System.map-$KERNELRELEASE-rpm"
+echo "rm -f /boot/vmlinuz-$KERNELRELEASE /boot/System.map-$KERNELRELEASE"
+echo "/sbin/installkernel $KERNELRELEASE /boot/vmlinuz-$KERNELRELEASE-rpm /boot/System.map-$KERNELRELEASE-rpm"
+echo "rm -f /boot/vmlinuz-$KERNELRELEASE-rpm /boot/System.map-$KERNELRELEASE-rpm"
+echo "fi"
+echo ""
 echo "%files"
 echo '%defattr (-, root, root)'
 echo "%dir /lib/modules"
 echo "/lib/modules/$KERNELRELEASE"
-echo "/lib/firmware"
+echo "%exclude /lib/modules/$KERNELRELEASE/build"
+echo "%exclude /lib/modules/$KERNELRELEASE/source"
+echo "/lib/firmware/$KERNELRELEASE"
 echo "/boot/*"
 echo ""
 echo "%files headers"
 echo '%defattr (-, root, root)'
 echo "/usr/include"
 echo ""
+echo "%files devel"
+echo '%defattr (-, root, root)'
+echo "/usr/src/kernels/$KERNELRELEASE"
+echo "/lib/modules/$KERNELRELEASE/build"
+echo "/lib/modules/$KERNELRELEASE/source"
+echo ""
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index f9ce116..3a80c48 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -160,6 +160,30 @@ static void (*w2)(uint16_t, uint16_t *);
 
 typedef void (*table_sort_t)(char *, int);
 
+/*
+ * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+ * the way to -256..-1, to avoid conflicting with real section
+ * indices.
+ */
+#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1))
+
+static inline int is_shndx_special(unsigned int i)
+{
+	return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
+}
+
+/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
+static inline unsigned int get_secindex(unsigned int shndx,
+					unsigned int sym_offs,
+					const Elf32_Word *symtab_shndx_start)
+{
+	if (is_shndx_special(shndx))
+		return SPECIAL(shndx);
+	if (shndx != SHN_XINDEX)
+		return shndx;
+	return r(&symtab_shndx_start[sym_offs]);
+}
+
 /* 32 bit and 64 bit are very similar */
 #include "sortextable.h"
 #define SORTEXTABLE_64
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
index f5eb43d..8fac3fd 100644
--- a/scripts/sortextable.h
+++ b/scripts/sortextable.h
@@ -98,6 +98,8 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
 	Elf_Shdr *symtab_sec = NULL;
 	Elf_Shdr *extab_sec = NULL;
 	Elf_Sym *sym;
+	const Elf_Sym *symtab;
+	Elf32_Word *symtab_shndx_start = NULL;
 	Elf_Sym *sort_needed_sym;
 	Elf_Shdr *sort_needed_sec;
 	Elf_Rel *relocs = NULL;
@@ -109,11 +111,22 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
 	int extab_index = 0;
 	int i;
 	int idx;
+	unsigned int num_sections;
+	unsigned int secindex_strings;
 
 	shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
-	shstrtab_sec = shdr + r2(&ehdr->e_shstrndx);
+
+	num_sections = r2(&ehdr->e_shnum);
+	if (num_sections == SHN_UNDEF)
+		num_sections = _r(&shdr[0].sh_size);
+
+	secindex_strings = r2(&ehdr->e_shstrndx);
+	if (secindex_strings == SHN_XINDEX)
+		secindex_strings = r(&shdr[0].sh_link);
+
+	shstrtab_sec = shdr + secindex_strings;
 	secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset);
-	for (i = 0; i < r2(&ehdr->e_shnum); i++) {
+	for (i = 0; i < num_sections; i++) {
 		idx = r(&shdr[i].sh_name);
 		if (strcmp(secstrtab + idx, "__ex_table") == 0) {
 			extab_sec = shdr + i;
@@ -129,6 +142,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
 			symtab_sec = shdr + i;
 		if (strcmp(secstrtab + idx, ".strtab") == 0)
 			strtab_sec = shdr + i;
+		if (r(&shdr[i].sh_type) == SHT_SYMTAB_SHNDX)
+			symtab_shndx_start = (Elf32_Word *)(
+				(const char *)ehdr + _r(&shdr[i].sh_offset));
 	}
 	if (strtab_sec == NULL) {
 		fprintf(stderr,	"no .strtab in  file: %s\n", fname);
@@ -138,6 +154,8 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
 		fprintf(stderr,	"no .symtab in  file: %s\n", fname);
 		fail_file();
 	}
+	symtab = (const Elf_Sym *)((const char *)ehdr +
+				   _r(&symtab_sec->sh_offset));
 	if (extab_sec == NULL) {
 		fprintf(stderr,	"no __ex_table in  file: %s\n", fname);
 		fail_file();
@@ -176,7 +194,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
 			fname);
 		fail_file();
 	}
-	sort_needed_sec = &shdr[r2(&sort_needed_sym->st_shndx)];
+	sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
+					     sort_needed_sym - symtab,
+					     symtab_shndx_start)];
 	sort_done_location = (void *)ehdr +
 		_r(&sort_needed_sec->sh_offset) +
 		_r(&sort_needed_sym->st_value) -
diff --git a/security/capability.c b/security/capability.c
index 32b5157..8b4f24a 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -129,7 +129,7 @@ static void cap_inode_free_security(struct inode *inode)
 }
 
 static int cap_inode_init_security(struct inode *inode, struct inode *dir,
-				   const struct qstr *qstr, char **name,
+				   const struct qstr *qstr, const char **name,
 				   void **value, size_t *len)
 {
 	return -EOPNOTSUPP;
@@ -777,9 +777,15 @@ static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
 	return 0;
 }
 
-static int cap_xfrm_state_alloc_security(struct xfrm_state *x,
-					 struct xfrm_user_sec_ctx *sec_ctx,
-					 u32 secid)
+static int cap_xfrm_state_alloc(struct xfrm_state *x,
+				struct xfrm_user_sec_ctx *sec_ctx)
+{
+	return 0;
+}
+
+static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
+					struct xfrm_sec_ctx *polsec,
+					u32 secid)
 {
 	return 0;
 }
@@ -1101,7 +1107,8 @@ void __init security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, xfrm_policy_clone_security);
 	set_to_cap_if_null(ops, xfrm_policy_free_security);
 	set_to_cap_if_null(ops, xfrm_policy_delete_security);
-	set_to_cap_if_null(ops, xfrm_state_alloc_security);
+	set_to_cap_if_null(ops, xfrm_state_alloc);
+	set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
 	set_to_cap_if_null(ops, xfrm_state_free_security);
 	set_to_cap_if_null(ops, xfrm_state_delete_security);
 	set_to_cap_if_null(ops, xfrm_policy_lookup);
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index df0fa45..af9b685 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -418,7 +418,7 @@ int evm_inode_init_security(struct inode *inode,
 
 	evm_xattr->value = xattr_data;
 	evm_xattr->value_len = sizeof(*xattr_data);
-	evm_xattr->name = kstrdup(XATTR_EVM_SUFFIX, GFP_NOFS);
+	evm_xattr->name = XATTR_EVM_SUFFIX;
 	return 0;
 out:
 	kfree(xattr_data);
diff --git a/security/security.c b/security/security.c
index 94b35ae..15b6928 100644
--- a/security/security.c
+++ b/security/security.c
@@ -348,10 +348,10 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 	if (unlikely(IS_PRIVATE(inode)))
 		return 0;
 
-	memset(new_xattrs, 0, sizeof new_xattrs);
 	if (!initxattrs)
 		return security_ops->inode_init_security(inode, dir, qstr,
 							 NULL, NULL, NULL);
+	memset(new_xattrs, 0, sizeof(new_xattrs));
 	lsm_xattr = new_xattrs;
 	ret = security_ops->inode_init_security(inode, dir, qstr,
 						&lsm_xattr->name,
@@ -366,16 +366,14 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 		goto out;
 	ret = initxattrs(inode, new_xattrs, fs_data);
 out:
-	for (xattr = new_xattrs; xattr->name != NULL; xattr++) {
-		kfree(xattr->name);
+	for (xattr = new_xattrs; xattr->value != NULL; xattr++)
 		kfree(xattr->value);
-	}
 	return (ret == -EOPNOTSUPP) ? 0 : ret;
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
 int security_old_inode_init_security(struct inode *inode, struct inode *dir,
-				     const struct qstr *qstr, char **name,
+				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
 {
 	if (unlikely(IS_PRIVATE(inode)))
@@ -1342,22 +1340,17 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 	return security_ops->xfrm_policy_delete_security(ctx);
 }
 
-int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+int security_xfrm_state_alloc(struct xfrm_state *x,
+			      struct xfrm_user_sec_ctx *sec_ctx)
 {
-	return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
+	return security_ops->xfrm_state_alloc(x, sec_ctx);
 }
 EXPORT_SYMBOL(security_xfrm_state_alloc);
 
 int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
 				      struct xfrm_sec_ctx *polsec, u32 secid)
 {
-	if (!polsec)
-		return 0;
-	/*
-	 * We want the context to be taken from secid which is usually
-	 * from the sock.
-	 */
-	return security_ops->xfrm_state_alloc_security(x, NULL, secid);
+	return security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
 }
 
 int security_xfrm_state_delete(struct xfrm_state *x)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c956390..dd0cf2b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -95,8 +95,6 @@
 #include "audit.h"
 #include "avc_ss.h"
 
-#define NUM_SEL_MNT_OPTS 5
-
 extern struct security_operations *security_ops;
 
 /* SECMARK reference count */
@@ -139,12 +137,28 @@ static struct kmem_cache *sel_inode_cache;
  * This function checks the SECMARK reference counter to see if any SECMARK
  * targets are currently configured, if the reference counter is greater than
  * zero SECMARK is considered to be enabled.  Returns true (1) if SECMARK is
- * enabled, false (0) if SECMARK is disabled.
+ * enabled, false (0) if SECMARK is disabled.  If the always_check_network
+ * policy capability is enabled, SECMARK is always considered enabled.
  *
  */
 static int selinux_secmark_enabled(void)
 {
-	return (atomic_read(&selinux_secmark_refcount) > 0);
+	return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
+}
+
+/**
+ * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
+ *
+ * Description:
+ * This function checks if NetLabel or labeled IPSEC is enabled.  Returns true
+ * (1) if any are enabled or false (0) if neither are enabled.  If the
+ * always_check_network policy capability is enabled, peer labeling
+ * is always considered enabled.
+ *
+ */
+static int selinux_peerlbl_enabled(void)
+{
+	return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
 }
 
 /*
@@ -309,8 +323,11 @@ enum {
 	Opt_defcontext = 3,
 	Opt_rootcontext = 4,
 	Opt_labelsupport = 5,
+	Opt_nextmntopt = 6,
 };
 
+#define NUM_SEL_MNT_OPTS	(Opt_nextmntopt - 1)
+
 static const match_table_t tokens = {
 	{Opt_context, CONTEXT_STR "%s"},
 	{Opt_fscontext, FSCONTEXT_STR "%s"},
@@ -355,6 +372,29 @@ static int may_context_mount_inode_relabel(u32 sid,
 	return rc;
 }
 
+static int selinux_is_sblabel_mnt(struct super_block *sb)
+{
+	struct superblock_security_struct *sbsec = sb->s_security;
+
+	if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
+	    sbsec->behavior == SECURITY_FS_USE_TRANS ||
+	    sbsec->behavior == SECURITY_FS_USE_TASK)
+		return 1;
+
+	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
+	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
+		return 1;
+
+	/*
+	 * Special handling for rootfs. Is genfs but supports
+	 * setting SELinux context on in-core inodes.
+	 */
+	if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
+		return 1;
+
+	return 0;
+}
+
 static int sb_finish_set_opts(struct super_block *sb)
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
@@ -388,8 +428,6 @@ static int sb_finish_set_opts(struct super_block *sb)
 		}
 	}
 
-	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",
 		       sb->s_id, sb->s_type->name);
@@ -398,15 +436,9 @@ static int sb_finish_set_opts(struct super_block *sb)
 		       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;
-
-	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
-	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
-		sbsec->flags |= SE_SBLABELSUPP;
+	sbsec->flags |= SE_SBINITIALIZED;
+	if (selinux_is_sblabel_mnt(sb))
+		sbsec->flags |= SBLABEL_MNT;
 
 	/* Initialize the root inode. */
 	rc = inode_doinit_with_dentry(root_inode, root);
@@ -460,15 +492,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
 	if (!ss_initialized)
 		return -EINVAL;
 
+	/* make sure we always check enough bits to cover the mask */
+	BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
+
 	tmp = sbsec->flags & SE_MNTMASK;
 	/* count the number of mount options for this sb */
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
 		if (tmp & 0x01)
 			opts->num_mnt_opts++;
 		tmp >>= 1;
 	}
 	/* Check if the Label support flag is set */
-	if (sbsec->flags & SE_SBLABELSUPP)
+	if (sbsec->flags & SBLABEL_MNT)
 		opts->num_mnt_opts++;
 
 	opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
@@ -515,9 +550,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
 		opts->mnt_opts[i] = context;
 		opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
 	}
-	if (sbsec->flags & SE_SBLABELSUPP) {
+	if (sbsec->flags & SBLABEL_MNT) {
 		opts->mnt_opts[i] = NULL;
-		opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
+		opts->mnt_opts_flags[i++] = SBLABEL_MNT;
 	}
 
 	BUG_ON(i != opts->num_mnt_opts);
@@ -614,7 +649,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	for (i = 0; i < num_opts; i++) {
 		u32 sid;
 
-		if (flags[i] == SE_SBLABELSUPP)
+		if (flags[i] == SBLABEL_MNT)
 			continue;
 		rc = security_context_to_sid(mount_options[i],
 					     strlen(mount_options[i]), &sid);
@@ -685,9 +720,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 		 * Determine the labeling behavior to use for this
 		 * filesystem type.
 		 */
-		rc = security_fs_use((sbsec->flags & SE_SBPROC) ?
-					"proc" : sb->s_type->name,
-					&sbsec->behavior, &sbsec->sid);
+		rc = security_fs_use(sb);
 		if (rc) {
 			printk(KERN_WARNING
 				"%s: security_fs_use(%s) returned %d\n",
@@ -1037,7 +1070,7 @@ static void selinux_write_opts(struct seq_file *m,
 		case DEFCONTEXT_MNT:
 			prefix = DEFCONTEXT_STR;
 			break;
-		case SE_SBLABELSUPP:
+		case SBLABEL_MNT:
 			seq_putc(m, ',');
 			seq_puts(m, LABELSUPP_STR);
 			continue;
@@ -1650,7 +1683,7 @@ static int may_create(struct inode *dir,
 	if (rc)
 		return rc;
 
-	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+	if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
 		rc = security_transition_sid(sid, dsec->sid, tclass,
 					     &dentry->d_name, &newsid);
 		if (rc)
@@ -2438,7 +2471,7 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
 		u32 sid;
 		size_t len;
 
-		if (flags[i] == SE_SBLABELSUPP)
+		if (flags[i] == SBLABEL_MNT)
 			continue;
 		len = strlen(mount_options[i]);
 		rc = security_context_to_sid(mount_options[i], len, &sid);
@@ -2587,7 +2620,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
 }
 
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
-				       const struct qstr *qstr, char **name,
+				       const struct qstr *qstr,
+				       const char **name,
 				       void **value, size_t *len)
 {
 	const struct task_security_struct *tsec = current_security();
@@ -2595,7 +2629,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	struct superblock_security_struct *sbsec;
 	u32 sid, newsid, clen;
 	int rc;
-	char *namep = NULL, *context;
+	char *context;
 
 	dsec = dir->i_security;
 	sbsec = dir->i_sb->s_security;
@@ -2606,7 +2640,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	if ((sbsec->flags & SE_SBINITIALIZED) &&
 	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
 		newsid = sbsec->mntpoint_sid;
-	else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+	else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
 		rc = security_transition_sid(sid, dsec->sid,
 					     inode_mode_to_security_class(inode->i_mode),
 					     qstr, &newsid);
@@ -2628,22 +2662,16 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 		isec->initialized = 1;
 	}
 
-	if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
+	if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
 		return -EOPNOTSUPP;
 
-	if (name) {
-		namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
-		if (!namep)
-			return -ENOMEM;
-		*name = namep;
-	}
+	if (name)
+		*name = XATTR_SELINUX_SUFFIX;
 
 	if (value && len) {
 		rc = security_sid_to_context_force(newsid, &context, &clen);
-		if (rc) {
-			kfree(namep);
+		if (rc)
 			return rc;
-		}
 		*value = context;
 		*len = clen;
 	}
@@ -2836,7 +2864,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 		return selinux_inode_setotherxattr(dentry, name);
 
 	sbsec = inode->i_sb->s_security;
-	if (!(sbsec->flags & SE_SBLABELSUPP))
+	if (!(sbsec->flags & SBLABEL_MNT))
 		return -EOPNOTSUPP;
 
 	if (!inode_owner_or_capable(inode))
@@ -3797,8 +3825,12 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
 	u32 nlbl_sid;
 	u32 nlbl_type;
 
-	selinux_skb_xfrm_sid(skb, &xfrm_sid);
-	selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
+	err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+	if (unlikely(err))
+		return -EACCES;
+	err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
+	if (unlikely(err))
+		return -EACCES;
 
 	err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
 	if (unlikely(err)) {
@@ -4252,7 +4284,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 		return selinux_sock_rcv_skb_compat(sk, skb, family);
 
 	secmark_active = selinux_secmark_enabled();
-	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+	peerlbl_active = selinux_peerlbl_enabled();
 	if (!secmark_active && !peerlbl_active)
 		return 0;
 
@@ -4634,7 +4666,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
 
 	secmark_active = selinux_secmark_enabled();
 	netlbl_active = netlbl_enabled();
-	peerlbl_active = netlbl_active || selinux_xfrm_enabled();
+	peerlbl_active = selinux_peerlbl_enabled();
 	if (!secmark_active && !peerlbl_active)
 		return NF_ACCEPT;
 
@@ -4786,7 +4818,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 		return NF_ACCEPT;
 #endif
 	secmark_active = selinux_secmark_enabled();
-	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+	peerlbl_active = selinux_peerlbl_enabled();
 	if (!secmark_active && !peerlbl_active)
 		return NF_ACCEPT;
 
@@ -5790,7 +5822,8 @@ static struct security_operations selinux_ops = {
 	.xfrm_policy_clone_security =	selinux_xfrm_policy_clone,
 	.xfrm_policy_free_security =	selinux_xfrm_policy_free,
 	.xfrm_policy_delete_security =	selinux_xfrm_policy_delete,
-	.xfrm_state_alloc_security =	selinux_xfrm_state_alloc,
+	.xfrm_state_alloc =		selinux_xfrm_state_alloc,
+	.xfrm_state_alloc_acquire =	selinux_xfrm_state_alloc_acquire,
 	.xfrm_state_free_security =	selinux_xfrm_state_free,
 	.xfrm_state_delete_security =	selinux_xfrm_state_delete,
 	.xfrm_policy_lookup =		selinux_xfrm_policy_lookup,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index aa47bca..b1dfe10 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -58,8 +58,8 @@ struct superblock_security_struct {
 	u32 sid;			/* SID of file system superblock */
 	u32 def_sid;			/* default SID for labeling */
 	u32 mntpoint_sid;		/* SECURITY_FS_USE_MNTPOINT context for files */
-	unsigned int behavior;		/* labeling behavior */
-	unsigned char flags;		/* which mount options were specified */
+	unsigned short behavior;	/* labeling behavior */
+	unsigned short flags;		/* which mount options were specified */
 	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 8fd8e18..fe341ae 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -45,14 +45,15 @@
 /* Mask for just the mount related flags */
 #define SE_MNTMASK	0x0f
 /* Super block security struct flags for mount options */
+/* BE CAREFUL, these need to be the low order bits for selinux_get_mnt_opts */
 #define CONTEXT_MNT	0x01
 #define FSCONTEXT_MNT	0x02
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
+#define SBLABEL_MNT	0x10
 /* Non-mount related flags */
-#define SE_SBINITIALIZED	0x10
-#define SE_SBPROC		0x20
-#define SE_SBLABELSUPP	0x40
+#define SE_SBINITIALIZED	0x0100
+#define SE_SBPROC		0x0200
 
 #define CONTEXT_STR	"context="
 #define FSCONTEXT_STR	"fscontext="
@@ -68,12 +69,15 @@ extern int selinux_enabled;
 enum {
 	POLICYDB_CAPABILITY_NETPEER,
 	POLICYDB_CAPABILITY_OPENPERM,
+	POLICYDB_CAPABILITY_REDHAT1,
+	POLICYDB_CAPABILITY_ALWAYSNETWORK,
 	__POLICYDB_CAPABILITY_MAX
 };
 #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
 
 extern int selinux_policycap_netpeer;
 extern int selinux_policycap_openperm;
+extern int selinux_policycap_alwaysnetwork;
 
 /*
  * type_datum properties
@@ -172,8 +176,7 @@ int security_get_allow_unknown(void);
 #define SECURITY_FS_USE_NATIVE		7 /* use native label support */
 #define SECURITY_FS_USE_MAX		7 /* Highest SECURITY_FS_USE_XXX */
 
-int security_fs_use(const char *fstype, unsigned int *behavior,
-	u32 *sid);
+int security_fs_use(struct super_block *sb);
 
 int security_genfs_sid(const char *fstype, char *name, u16 sclass,
 	u32 *sid);
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 65f67cb..0dec76c 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -10,29 +10,21 @@
 #include <net/flow.h>
 
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
-			      struct xfrm_user_sec_ctx *sec_ctx);
+			      struct xfrm_user_sec_ctx *uctx);
 int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
 			      struct xfrm_sec_ctx **new_ctxp);
 void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
 int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
 int selinux_xfrm_state_alloc(struct xfrm_state *x,
-	struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
+			     struct xfrm_user_sec_ctx *uctx);
+int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
+				     struct xfrm_sec_ctx *polsec, u32 secid);
 void selinux_xfrm_state_free(struct xfrm_state *x);
 int selinux_xfrm_state_delete(struct xfrm_state *x);
 int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
 int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
-			struct xfrm_policy *xp, const struct flowi *fl);
-
-/*
- * Extract the security blob from the sock (it's actually on the socket)
- */
-static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
-{
-	if (!sk->sk_socket)
-		return NULL;
-
-	return SOCK_INODE(sk->sk_socket)->i_security;
-}
+				      struct xfrm_policy *xp,
+				      const struct flowi *fl);
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 extern atomic_t selinux_xfrm_refcount;
@@ -42,16 +34,21 @@ static inline int selinux_xfrm_enabled(void)
 	return (atomic_read(&selinux_xfrm_refcount) > 0);
 }
 
-int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
-			struct common_audit_data *ad);
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
-			struct common_audit_data *ad, u8 proto);
+int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
+			      struct common_audit_data *ad);
+int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
+				struct common_audit_data *ad, u8 proto);
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
 
 static inline void selinux_xfrm_notify_policyload(void)
 {
+	struct net *net;
+
 	atomic_inc(&flow_cache_genid);
-	rt_genid_bump(&init_net);
+	rtnl_lock();
+	for_each_net(net)
+		rt_genid_bump_all(net);
+	rtnl_unlock();
 }
 #else
 static inline int selinux_xfrm_enabled(void)
@@ -59,19 +56,21 @@ static inline int selinux_xfrm_enabled(void)
 	return 0;
 }
 
-static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
-			struct common_audit_data *ad)
+static inline int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
+					    struct common_audit_data *ad)
 {
 	return 0;
 }
 
-static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
-			struct common_audit_data *ad, u8 proto)
+static inline int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
+					      struct common_audit_data *ad,
+					      u8 proto)
 {
 	return 0;
 }
 
-static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
+					      int ckall)
 {
 	*sid = SECSID_NULL;
 	return 0;
@@ -82,10 +81,9 @@ static inline void selinux_xfrm_notify_policyload(void)
 }
 #endif
 
-static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
 {
-	int err = selinux_xfrm_decode_session(skb, sid, 0);
-	BUG_ON(err);
+	return selinux_xfrm_decode_session(skb, sid, 0);
 }
 
 #endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index c5454c0..03a72c3 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -166,6 +166,7 @@ static void sel_netnode_insert(struct sel_netnode *node)
 		break;
 	default:
 		BUG();
+		return;
 	}
 
 	/* we need to impose a limit on the growth of the hash table so check
@@ -225,6 +226,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
 		break;
 	default:
 		BUG();
+		ret = -EINVAL;
 	}
 	if (ret != 0)
 		goto out;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index ff42773..5122aff 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -44,7 +44,9 @@
 /* Policy capability filenames */
 static char *policycap_names[] = {
 	"network_peer_controls",
-	"open_perms"
+	"open_perms",
+	"redhat1",
+	"always_check_network"
 };
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 30f119b..820313a 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -213,7 +213,12 @@ netlbl_import_failure:
 }
 #endif /* CONFIG_NETLABEL */
 
-int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
+/*
+ * Check to see if all the bits set in e2 are also set in e1. Optionally,
+ * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
+ * last_e2bit.
+ */
+int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
 {
 	struct ebitmap_node *n1, *n2;
 	int i;
@@ -223,14 +228,25 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
 
 	n1 = e1->node;
 	n2 = e2->node;
+
 	while (n1 && n2 && (n1->startbit <= n2->startbit)) {
 		if (n1->startbit < n2->startbit) {
 			n1 = n1->next;
 			continue;
 		}
-		for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
+		for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i]; )
+			i--;	/* Skip trailing NULL map entries */
+		if (last_e2bit && (i >= 0)) {
+			u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE +
+					 __fls(n2->maps[i]);
+			if (lastsetbit > last_e2bit)
+				return 0;
+		}
+
+		while (i >= 0) {
 			if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
 				return 0;
+			i--;
 		}
 
 		n1 = n1->next;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 922f8af..712c8a7 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -16,7 +16,13 @@
 
 #include <net/netlabel.h>
 
-#define EBITMAP_UNIT_NUMS	((32 - sizeof(void *) - sizeof(u32))	\
+#ifdef CONFIG_64BIT
+#define	EBITMAP_NODE_SIZE	64
+#else
+#define	EBITMAP_NODE_SIZE	32
+#endif
+
+#define EBITMAP_UNIT_NUMS	((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\
 					/ sizeof(unsigned long))
 #define EBITMAP_UNIT_SIZE	BITS_PER_LONG
 #define EBITMAP_SIZE		(EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
@@ -117,7 +123,7 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
 
 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
 int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
-int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
+int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit);
 int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
 int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
 void ebitmap_destroy(struct ebitmap *e);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 40de8d3..c85bc1e 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -160,8 +160,6 @@ void mls_sid_to_context(struct context *context,
 int mls_level_isvalid(struct policydb *p, struct mls_level *l)
 {
 	struct level_datum *levdatum;
-	struct ebitmap_node *node;
-	int i;
 
 	if (!l->sens || l->sens > p->p_levels.nprim)
 		return 0;
@@ -170,19 +168,13 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
 	if (!levdatum)
 		return 0;
 
-	ebitmap_for_each_positive_bit(&l->cat, node, i) {
-		if (i > p->p_cats.nprim)
-			return 0;
-		if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
-			/*
-			 * Category may not be associated with
-			 * sensitivity.
-			 */
-			return 0;
-		}
-	}
-
-	return 1;
+	/*
+	 * Return 1 iff all the bits set in l->cat are also be set in
+	 * levdatum->level->cat and no bit in l->cat is larger than
+	 * p->p_cats.nprim.
+	 */
+	return ebitmap_contains(&levdatum->level->cat, &l->cat,
+				p->p_cats.nprim);
 }
 
 int mls_range_isvalid(struct policydb *p, struct mls_range *r)
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index 03bed52..e936487 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -35,7 +35,7 @@ static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
 static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
 {
 	return ((l1->sens >= l2->sens) &&
-		ebitmap_contains(&l1->cat, &l2->cat));
+		ebitmap_contains(&l1->cat, &l2->cat, 0));
 }
 
 #define mls_level_incomp(l1, l2) \
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index c8adde3..f6195eb 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -3203,9 +3203,8 @@ static int range_write_helper(void *key, void *data, void *ptr)
 
 static int range_write(struct policydb *p, void *fp)
 {
-	size_t nel;
 	__le32 buf[1];
-	int rc;
+	int rc, nel;
 	struct policy_data pd;
 
 	pd.p = p;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b4feecc..d106733 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -72,6 +72,7 @@
 
 int selinux_policycap_netpeer;
 int selinux_policycap_openperm;
+int selinux_policycap_alwaysnetwork;
 
 static DEFINE_RWLOCK(policy_rwlock);
 
@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void)
 						  POLICYDB_CAPABILITY_NETPEER);
 	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
 						  POLICYDB_CAPABILITY_OPENPERM);
+	selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
+						  POLICYDB_CAPABILITY_ALWAYSNETWORK);
 }
 
 static int security_preserve_bools(struct policydb *p);
@@ -2323,17 +2326,14 @@ out:
 
 /**
  * security_fs_use - Determine how to handle labeling for a filesystem.
- * @fstype: filesystem type
- * @behavior: labeling behavior
- * @sid: SID for filesystem (superblock)
+ * @sb: superblock in question
  */
-int security_fs_use(
-	const char *fstype,
-	unsigned int *behavior,
-	u32 *sid)
+int security_fs_use(struct super_block *sb)
 {
 	int rc = 0;
 	struct ocontext *c;
+	struct superblock_security_struct *sbsec = sb->s_security;
+	const char *fstype = sb->s_type->name;
 
 	read_lock(&policy_rwlock);
 
@@ -2345,21 +2345,21 @@ int security_fs_use(
 	}
 
 	if (c) {
-		*behavior = c->v.behavior;
+		sbsec->behavior = c->v.behavior;
 		if (!c->sid[0]) {
 			rc = sidtab_context_to_sid(&sidtab, &c->context[0],
 						   &c->sid[0]);
 			if (rc)
 				goto out;
 		}
-		*sid = c->sid[0];
+		sbsec->sid = c->sid[0];
 	} else {
-		rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+		rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, &sbsec->sid);
 		if (rc) {
-			*behavior = SECURITY_FS_USE_NONE;
+			sbsec->behavior = SECURITY_FS_USE_NONE;
 			rc = 0;
 		} else {
-			*behavior = SECURITY_FS_USE_GENFS;
+			sbsec->behavior = SECURITY_FS_USE_GENFS;
 		}
 	}
 
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index d030818..425b9f9 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -56,7 +56,7 @@
 atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
 
 /*
- * Returns true if an LSM/SELinux context
+ * Returns true if the context is an LSM/SELinux context.
  */
 static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
 {
@@ -66,7 +66,7 @@ static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
 }
 
 /*
- * Returns true if the xfrm contains a security blob for SELinux
+ * Returns true if the xfrm contains a security blob for SELinux.
  */
 static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
 {
@@ -74,48 +74,111 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
 }
 
 /*
- * LSM hook implementation that authorizes that a flow can use
- * a xfrm policy rule.
+ * Allocates a xfrm_sec_state and populates it using the supplied security
+ * xfrm_user_sec_ctx context.
  */
-int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
+				   struct xfrm_user_sec_ctx *uctx)
 {
 	int rc;
-	u32 sel_sid;
+	const struct task_security_struct *tsec = current_security();
+	struct xfrm_sec_ctx *ctx = NULL;
+	u32 str_len;
 
-	/* Context sid is either set to label or ANY_ASSOC */
-	if (ctx) {
-		if (!selinux_authorizable_ctx(ctx))
-			return -EINVAL;
-
-		sel_sid = ctx->ctx_sid;
-	} else
-		/*
-		 * All flows should be treated as polmatch'ing an
-		 * otherwise applicable "non-labeled" policy. This
-		 * would prevent inadvertent "leaks".
-		 */
-		return 0;
+	if (ctxp == NULL || uctx == NULL ||
+	    uctx->ctx_doi != XFRM_SC_DOI_LSM ||
+	    uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
+		return -EINVAL;
 
-	rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
-			  ASSOCIATION__POLMATCH,
-			  NULL);
+	str_len = uctx->ctx_len;
+	if (str_len >= PAGE_SIZE)
+		return -ENOMEM;
 
-	if (rc == -EACCES)
-		return -ESRCH;
+	ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
 
+	ctx->ctx_doi = XFRM_SC_DOI_LSM;
+	ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
+	ctx->ctx_len = str_len;
+	memcpy(ctx->ctx_str, &uctx[1], str_len);
+	ctx->ctx_str[str_len] = '\0';
+	rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
+	if (rc)
+		goto err;
+
+	rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+			  SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
+	if (rc)
+		goto err;
+
+	*ctxp = ctx;
+	atomic_inc(&selinux_xfrm_refcount);
+	return 0;
+
+err:
+	kfree(ctx);
 	return rc;
 }
 
 /*
+ * Free the xfrm_sec_ctx structure.
+ */
+static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
+{
+	if (!ctx)
+		return;
+
+	atomic_dec(&selinux_xfrm_refcount);
+	kfree(ctx);
+}
+
+/*
+ * Authorize the deletion of a labeled SA or policy rule.
+ */
+static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
+{
+	const struct task_security_struct *tsec = current_security();
+
+	if (!ctx)
+		return 0;
+
+	return avc_has_perm(tsec->sid, ctx->ctx_sid,
+			    SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
+			    NULL);
+}
+
+/*
+ * LSM hook implementation that authorizes that a flow can use a xfrm policy
+ * rule.
+ */
+int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+{
+	int rc;
+
+	/* All flows should be treated as polmatch'ing an otherwise applicable
+	 * "non-labeled" policy. This would prevent inadvertent "leaks". */
+	if (!ctx)
+		return 0;
+
+	/* Context sid is either set to label or ANY_ASSOC */
+	if (!selinux_authorizable_ctx(ctx))
+		return -EINVAL;
+
+	rc = avc_has_perm(fl_secid, ctx->ctx_sid,
+			  SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
+	return (rc == -EACCES ? -ESRCH : rc);
+}
+
+/*
  * LSM hook implementation that authorizes that a state matches
  * the given policy, flow combo.
  */
-
-int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
-			const struct flowi *fl)
+int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
+				      struct xfrm_policy *xp,
+				      const struct flowi *fl)
 {
 	u32 state_sid;
-	int rc;
 
 	if (!xp->security)
 		if (x->security)
@@ -138,187 +201,80 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
 	if (fl->flowi_secid != state_sid)
 		return 0;
 
-	rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION,
-			  ASSOCIATION__SENDTO,
-			  NULL)? 0:1;
-
-	/*
-	 * We don't need a separate SA Vs. policy polmatch check
-	 * since the SA is now of the same label as the flow and
-	 * a flow Vs. policy polmatch check had already happened
-	 * in selinux_xfrm_policy_lookup() above.
-	 */
-
-	return rc;
+	/* We don't need a separate SA Vs. policy polmatch check since the SA
+	 * is now of the same label as the flow and a flow Vs. policy polmatch
+	 * check had already happened in selinux_xfrm_policy_lookup() above. */
+	return (avc_has_perm(fl->flowi_secid, state_sid,
+			    SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
+			    NULL) ? 0 : 1);
 }
 
 /*
  * LSM hook implementation that checks and/or returns the xfrm sid for the
  * incoming packet.
  */
-
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
 {
+	u32 sid_session = SECSID_NULL;
 	struct sec_path *sp;
 
-	*sid = SECSID_NULL;
-
 	if (skb == NULL)
-		return 0;
+		goto out;
 
 	sp = skb->sp;
 	if (sp) {
-		int i, sid_set = 0;
+		int i;
 
-		for (i = sp->len-1; i >= 0; i--) {
+		for (i = sp->len - 1; i >= 0; i--) {
 			struct xfrm_state *x = sp->xvec[i];
 			if (selinux_authorizable_xfrm(x)) {
 				struct xfrm_sec_ctx *ctx = x->security;
 
-				if (!sid_set) {
-					*sid = ctx->ctx_sid;
-					sid_set = 1;
-
+				if (sid_session == SECSID_NULL) {
+					sid_session = ctx->ctx_sid;
 					if (!ckall)
-						break;
-				} else if (*sid != ctx->ctx_sid)
+						goto out;
+				} else if (sid_session != ctx->ctx_sid) {
+					*sid = SECSID_NULL;
 					return -EINVAL;
+				}
 			}
 		}
 	}
 
-	return 0;
-}
-
-/*
- * Security blob allocation for xfrm_policy and xfrm_state
- * CTX does not have a meaningful value on input
- */
-static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
-	struct xfrm_user_sec_ctx *uctx, u32 sid)
-{
-	int rc = 0;
-	const struct task_security_struct *tsec = current_security();
-	struct xfrm_sec_ctx *ctx = NULL;
-	char *ctx_str = NULL;
-	u32 str_len;
-
-	BUG_ON(uctx && sid);
-
-	if (!uctx)
-		goto not_from_user;
-
-	if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
-		return -EINVAL;
-
-	str_len = uctx->ctx_len;
-	if (str_len >= PAGE_SIZE)
-		return -ENOMEM;
-
-	*ctxp = ctx = kmalloc(sizeof(*ctx) +
-			      str_len + 1,
-			      GFP_KERNEL);
-
-	if (!ctx)
-		return -ENOMEM;
-
-	ctx->ctx_doi = uctx->ctx_doi;
-	ctx->ctx_len = str_len;
-	ctx->ctx_alg = uctx->ctx_alg;
-
-	memcpy(ctx->ctx_str,
-	       uctx+1,
-	       str_len);
-	ctx->ctx_str[str_len] = 0;
-	rc = security_context_to_sid(ctx->ctx_str,
-				     str_len,
-				     &ctx->ctx_sid);
-
-	if (rc)
-		goto out;
-
-	/*
-	 * Does the subject have permission to set security context?
-	 */
-	rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
-			  SECCLASS_ASSOCIATION,
-			  ASSOCIATION__SETCONTEXT, NULL);
-	if (rc)
-		goto out;
-
-	return rc;
-
-not_from_user:
-	rc = security_sid_to_context(sid, &ctx_str, &str_len);
-	if (rc)
-		goto out;
-
-	*ctxp = ctx = kmalloc(sizeof(*ctx) +
-			      str_len,
-			      GFP_ATOMIC);
-
-	if (!ctx) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	ctx->ctx_doi = XFRM_SC_DOI_LSM;
-	ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
-	ctx->ctx_sid = sid;
-	ctx->ctx_len = str_len;
-	memcpy(ctx->ctx_str,
-	       ctx_str,
-	       str_len);
-
-	goto out2;
-
 out:
-	*ctxp = NULL;
-	kfree(ctx);
-out2:
-	kfree(ctx_str);
-	return rc;
+	*sid = sid_session;
+	return 0;
 }
 
 /*
- * LSM hook implementation that allocs and transfers uctx spec to
- * xfrm_policy.
+ * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
  */
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
 			      struct xfrm_user_sec_ctx *uctx)
 {
-	int err;
-
-	BUG_ON(!uctx);
-
-	err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
-	if (err == 0)
-		atomic_inc(&selinux_xfrm_refcount);
-
-	return err;
+	return selinux_xfrm_alloc_user(ctxp, uctx);
 }
 
-
 /*
- * LSM hook implementation that copies security data structure from old to
- * new for policy cloning.
+ * LSM hook implementation that copies security data structure from old to new
+ * for policy cloning.
  */
 int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
 			      struct xfrm_sec_ctx **new_ctxp)
 {
 	struct xfrm_sec_ctx *new_ctx;
 
-	if (old_ctx) {
-		new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
-				  GFP_ATOMIC);
-		if (!new_ctx)
-			return -ENOMEM;
+	if (!old_ctx)
+		return 0;
+
+	new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, GFP_ATOMIC);
+	if (!new_ctx)
+		return -ENOMEM;
+	memcpy(new_ctx, old_ctx, sizeof(*old_ctx) + old_ctx->ctx_len);
+	atomic_inc(&selinux_xfrm_refcount);
+	*new_ctxp = new_ctx;
 
-		memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
-		memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
-		atomic_inc(&selinux_xfrm_refcount);
-		*new_ctxp = new_ctx;
-	}
 	return 0;
 }
 
@@ -327,8 +283,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
  */
 void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
 {
-	atomic_dec(&selinux_xfrm_refcount);
-	kfree(ctx);
+	selinux_xfrm_free(ctx);
 }
 
 /*
@@ -336,31 +291,55 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
  */
 int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 {
-	const struct task_security_struct *tsec = current_security();
-
-	if (!ctx)
-		return 0;
+	return selinux_xfrm_delete(ctx);
+}
 
-	return avc_has_perm(tsec->sid, ctx->ctx_sid,
-			    SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
-			    NULL);
+/*
+ * LSM hook implementation that allocates a xfrm_sec_state, populates it using
+ * the supplied security context, and assigns it to the xfrm_state.
+ */
+int selinux_xfrm_state_alloc(struct xfrm_state *x,
+			     struct xfrm_user_sec_ctx *uctx)
+{
+	return selinux_xfrm_alloc_user(&x->security, uctx);
 }
 
 /*
- * LSM hook implementation that allocs and transfers sec_ctx spec to
- * xfrm_state.
+ * LSM hook implementation that allocates a xfrm_sec_state and populates based
+ * on a secid.
  */
-int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
-		u32 secid)
+int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
+				     struct xfrm_sec_ctx *polsec, u32 secid)
 {
-	int err;
+	int rc;
+	struct xfrm_sec_ctx *ctx;
+	char *ctx_str = NULL;
+	int str_len;
+
+	if (!polsec)
+		return 0;
 
-	BUG_ON(!x);
+	if (secid == 0)
+		return -EINVAL;
 
-	err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
-	if (err == 0)
-		atomic_inc(&selinux_xfrm_refcount);
-	return err;
+	rc = security_sid_to_context(secid, &ctx_str, &str_len);
+	if (rc)
+		return rc;
+
+	ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->ctx_doi = XFRM_SC_DOI_LSM;
+	ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
+	ctx->ctx_sid = secid;
+	ctx->ctx_len = str_len;
+	memcpy(ctx->ctx_str, ctx_str, str_len);
+	kfree(ctx_str);
+
+	x->security = ctx;
+	atomic_inc(&selinux_xfrm_refcount);
+	return 0;
 }
 
 /*
@@ -368,24 +347,15 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
  */
 void selinux_xfrm_state_free(struct xfrm_state *x)
 {
-	atomic_dec(&selinux_xfrm_refcount);
-	kfree(x->security);
+	selinux_xfrm_free(x->security);
 }
 
- /*
-  * LSM hook implementation that authorizes deletion of labeled SAs.
-  */
+/*
+ * LSM hook implementation that authorizes deletion of labeled SAs.
+ */
 int selinux_xfrm_state_delete(struct xfrm_state *x)
 {
-	const struct task_security_struct *tsec = current_security();
-	struct xfrm_sec_ctx *ctx = x->security;
-
-	if (!ctx)
-		return 0;
-
-	return avc_has_perm(tsec->sid, ctx->ctx_sid,
-			    SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
-			    NULL);
+	return selinux_xfrm_delete(x->security);
 }
 
 /*
@@ -395,14 +365,12 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
  * we need to check for unlabelled access since this may not have
  * gone thru the IPSec process.
  */
-int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
-				struct common_audit_data *ad)
+int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
+			      struct common_audit_data *ad)
 {
-	int i, rc = 0;
-	struct sec_path *sp;
-	u32 sel_sid = SECINITSID_UNLABELED;
-
-	sp = skb->sp;
+	int i;
+	struct sec_path *sp = skb->sp;
+	u32 peer_sid = SECINITSID_UNLABELED;
 
 	if (sp) {
 		for (i = 0; i < sp->len; i++) {
@@ -410,23 +378,17 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
 
 			if (x && selinux_authorizable_xfrm(x)) {
 				struct xfrm_sec_ctx *ctx = x->security;
-				sel_sid = ctx->ctx_sid;
+				peer_sid = ctx->ctx_sid;
 				break;
 			}
 		}
 	}
 
-	/*
-	 * This check even when there's no association involved is
-	 * intended, according to Trent Jaeger, to make sure a
-	 * process can't engage in non-ipsec communication unless
-	 * explicitly allowed by policy.
-	 */
-
-	rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
-			  ASSOCIATION__RECVFROM, ad);
-
-	return rc;
+	/* This check even when there's no association involved is intended,
+	 * according to Trent Jaeger, to make sure a process can't engage in
+	 * non-IPsec communication unless explicitly allowed by policy. */
+	return avc_has_perm(sk_sid, peer_sid,
+			    SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
 }
 
 /*
@@ -436,49 +398,38 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
  * If we do have a authorizable security association, then it has already been
  * checked in the selinux_xfrm_state_pol_flow_match hook above.
  */
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
-					struct common_audit_data *ad, u8 proto)
+int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
+				struct common_audit_data *ad, u8 proto)
 {
 	struct dst_entry *dst;
-	int rc = 0;
-
-	dst = skb_dst(skb);
-
-	if (dst) {
-		struct dst_entry *dst_test;
-
-		for (dst_test = dst; dst_test != NULL;
-		     dst_test = dst_test->child) {
-			struct xfrm_state *x = dst_test->xfrm;
-
-			if (x && selinux_authorizable_xfrm(x))
-				goto out;
-		}
-	}
 
 	switch (proto) {
 	case IPPROTO_AH:
 	case IPPROTO_ESP:
 	case IPPROTO_COMP:
-		/*
-		 * We should have already seen this packet once before
-		 * it underwent xfrm(s). No need to subject it to the
-		 * unlabeled check.
-		 */
-		goto out;
+		/* We should have already seen this packet once before it
+		 * underwent xfrm(s). No need to subject it to the unlabeled
+		 * check. */
+		return 0;
 	default:
 		break;
 	}
 
-	/*
-	 * This check even when there's no association involved is
-	 * intended, according to Trent Jaeger, to make sure a
-	 * process can't engage in non-ipsec communication unless
-	 * explicitly allowed by policy.
-	 */
+	dst = skb_dst(skb);
+	if (dst) {
+		struct dst_entry *iter;
 
-	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
-			  ASSOCIATION__SENDTO, ad);
-out:
-	return rc;
+		for (iter = dst; iter != NULL; iter = iter->child) {
+			struct xfrm_state *x = iter->xfrm;
+
+			if (x && selinux_authorizable_xfrm(x))
+				return 0;
+		}
+	}
+
+	/* This check even when there's no association involved is intended,
+	 * according to Trent Jaeger, to make sure a process can't engage in
+	 * non-IPsec communication unless explicitly allowed by policy. */
+	return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
+			    SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
 }
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 3f7682a..4392c5d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -582,7 +582,7 @@ static void smack_inode_free_security(struct inode *inode)
  * Returns 0 if it all works out, -ENOMEM if there's no memory
  */
 static int smack_inode_init_security(struct inode *inode, struct inode *dir,
-				     const struct qstr *qstr, char **name,
+				     const struct qstr *qstr, const char **name,
 				     void **value, size_t *len)
 {
 	struct inode_smack *issp = inode->i_security;
@@ -591,11 +591,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
 	char *dsp = smk_of_inode(dir);
 	int may;
 
-	if (name) {
-		*name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS);
-		if (*name == NULL)
-			return -ENOMEM;
-	}
+	if (name)
+		*name = XATTR_SMACK_SUFFIX;
 
 	if (value) {
 		rcu_read_lock();
@@ -1998,12 +1995,11 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
  *
  * Create or update the port list entry
  */
-static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address,
+static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
 				int act)
 {
 	__be16 *bep;
 	__be32 *be32p;
-	struct sockaddr_in6 *addr6;
 	struct smk_port_label *spp;
 	struct socket_smack *ssp = sk->sk_security;
 	struct smack_known *skp;
@@ -2025,10 +2021,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address,
 	/*
 	 * Get the IP address and port from the address.
 	 */
-	addr6 = (struct sockaddr_in6 *)address;
-	port = ntohs(addr6->sin6_port);
-	bep = (__be16 *)(&addr6->sin6_addr);
-	be32p = (__be32 *)(&addr6->sin6_addr);
+	port = ntohs(address->sin6_port);
+	bep = (__be16 *)(&address->sin6_addr);
+	be32p = (__be32 *)(&address->sin6_addr);
 
 	/*
 	 * It's remote, so port lookup does no good.
@@ -2060,9 +2055,9 @@ auditout:
 	ad.a.u.net->family = sk->sk_family;
 	ad.a.u.net->dport = port;
 	if (act == SMK_RECEIVING)
-		ad.a.u.net->v6info.saddr = addr6->sin6_addr;
+		ad.a.u.net->v6info.saddr = address->sin6_addr;
 	else
-		ad.a.u.net->v6info.daddr = addr6->sin6_addr;
+		ad.a.u.net->v6info.daddr = address->sin6_addr;
 #endif
 	return smk_access(skp, object, MAY_WRITE, &ad);
 }
@@ -2201,7 +2196,8 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
 	case PF_INET6:
 		if (addrlen < sizeof(struct sockaddr_in6))
 			return -EINVAL;
-		rc = smk_ipv6_port_check(sock->sk, sap, SMK_CONNECTING);
+		rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
+						SMK_CONNECTING);
 		break;
 	}
 	return rc;
@@ -3034,7 +3030,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
 				int size)
 {
 	struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
-	struct sockaddr *sap = (struct sockaddr *) msg->msg_name;
+	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
 	int rc = 0;
 
 	/*
@@ -3121,9 +3117,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
 	return smack_net_ambient;
 }
 
-static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr *sap)
+static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
 {
-	struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
 	u8 nexthdr;
 	int offset;
 	int proto = -EINVAL;
@@ -3181,7 +3176,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	struct netlbl_lsm_secattr secattr;
 	struct socket_smack *ssp = sk->sk_security;
 	struct smack_known *skp;
-	struct sockaddr sadd;
+	struct sockaddr_in6 sadd;
 	int rc = 0;
 	struct smk_audit_info ad;
 #ifdef CONFIG_AUDIT
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 11048cc..915b4d7 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -1022,7 +1022,7 @@ static void dummy_proc_write(struct snd_info_entry *entry,
 		if (i >= ARRAY_SIZE(fields))
 			continue;
 		snd_info_get_str(item, ptr, sizeof(item));
-		if (strict_strtoull(item, 0, &val))
+		if (kstrtoull(item, 0, &val))
 			continue;
 		if (fields[i].size == sizeof(int))
 			*get_dummy_int_ptr(dummy, fields[i].offset) = val;
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
index 2c63865..fe9e6e2 100644
--- a/sound/firewire/speakers.c
+++ b/sound/firewire/speakers.c
@@ -49,7 +49,6 @@ struct fwspk {
 	struct snd_card *card;
 	struct fw_unit *unit;
 	const struct device_info *device_info;
-	struct snd_pcm_substream *pcm;
 	struct mutex mutex;
 	struct cmp_connection connection;
 	struct amdtp_out_stream stream;
@@ -363,8 +362,7 @@ static int fwspk_create_pcm(struct fwspk *fwspk)
 		return err;
 	pcm->private_data = fwspk;
 	strcpy(pcm->name, fwspk->device_info->short_name);
-	fwspk->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-	fwspk->pcm->ops = &ops;
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ops);
 	return 0;
 }
 
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 8a36a1d..46ec4dff 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -486,13 +486,9 @@ static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
 	.s_ctrl = tea575x_s_ctrl,
 };
 
-/*
- * initialize all the tea575x chips
- */
-int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
-{
-	int retval;
 
+int snd_tea575x_hw_init(struct snd_tea575x *tea)
+{
 	tea->mute = true;
 
 	/* Not all devices can or know how to read the data back.
@@ -507,6 +503,17 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
 	tea->freq = 90500 * 16;		/* 90.5Mhz default */
 	snd_tea575x_set_freq(tea);
 
+	return 0;
+}
+EXPORT_SYMBOL(snd_tea575x_hw_init);
+
+int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
+{
+	int retval = snd_tea575x_hw_init(tea);
+
+	if (retval)
+		return retval;
+
 	tea->vd = tea575x_radio;
 	video_set_drvdata(&tea->vd, tea);
 	mutex_init(&tea->mutex);
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 9942691..afef0d7 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -443,8 +443,7 @@ static void snd_interwave_detect_memory(struct snd_gus_card *gus)
 		for (i = 0; i < 8; ++i)
 			iwave[i] = snd_gf1_peek(gus, bank_pos + i);
 #ifdef CONFIG_SND_DEBUG_ROM
-		printk(KERN_DEBUG "ROM at 0x%06x = %*phC\n", bank_pos,
-				  8, iwave);
+		printk(KERN_DEBUG "ROM at 0x%06x = %8phC\n", bank_pos, iwave);
 #endif
 		if (strncmp(iwave, "INTRWAVE", 8))
 			continue;	/* first check */
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8a005f0..fdbb09a 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1216,11 +1216,13 @@ static void hda_jackpoll_work(struct work_struct *work)
 {
 	struct hda_codec *codec =
 		container_of(work, struct hda_codec, jackpoll_work.work);
-	if (!codec->jackpoll_interval)
-		return;
 
 	snd_hda_jack_set_dirty_all(codec);
 	snd_hda_jack_poll_all(codec);
+
+	if (!codec->jackpoll_interval)
+		return;
+
 	queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
 			   codec->jackpoll_interval);
 }
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 8e77cbb..f6c0344 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -142,6 +142,9 @@ static void parse_user_hints(struct hda_codec *codec)
 	val = snd_hda_get_bool_hint(codec, "primary_hp");
 	if (val >= 0)
 		spec->no_primary_hp = !val;
+	val = snd_hda_get_bool_hint(codec, "multi_io");
+	if (val >= 0)
+		spec->no_multi_io = !val;
 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
 	if (val >= 0)
 		spec->multi_cap_vol = !!val;
@@ -1541,7 +1544,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 					      cfg->speaker_pins,
 					      spec->multiout.extra_out_nid,
 					      spec->speaker_paths);
-			if (fill_mio_first && cfg->line_outs == 1 &&
+			if (!spec->no_multi_io &&
+			    fill_mio_first && cfg->line_outs == 1 &&
 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
 				if (!err)
@@ -1554,7 +1558,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 				   spec->private_dac_nids, spec->out_paths,
 				   spec->main_out_badness);
 
-	if (fill_mio_first &&
+	if (!spec->no_multi_io && fill_mio_first &&
 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
 		/* try to fill multi-io first */
 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
@@ -1582,7 +1586,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 			return err;
 		badness += err;
 	}
-	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+	if (!spec->no_multi_io &&
+	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
 		if (err < 0)
 			return err;
@@ -1600,7 +1605,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 				check_aamix_out_path(codec, spec->speaker_paths[0]);
 	}
 
-	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+	if (!spec->no_multi_io &&
+	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
 			spec->multi_ios = 1; /* give badness */
 
@@ -3724,7 +3730,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
 /* check each pin in the given array; returns true if any of them is plugged */
 static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 {
-	int i, present = 0;
+	int i;
+	bool present = false;
 
 	for (i = 0; i < num_pins; i++) {
 		hda_nid_t nid = pins[i];
@@ -3733,7 +3740,8 @@ static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 		/* don't detect pins retasked as inputs */
 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
 			continue;
-		present |= snd_hda_jack_detect(codec, nid);
+		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
+			present = true;
 	}
 	return present;
 }
@@ -3887,7 +3895,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
 		/* don't detect pins retasked as outputs */
 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
 			continue;
-		if (snd_hda_jack_detect(codec, pin)) {
+		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
 			mux_select(codec, 0, spec->am_entry[i].idx);
 			return;
 		}
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index e199a85..48d4402 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -220,6 +220,7 @@ struct hda_gen_spec {
 	unsigned int hp_mic:1; /* Allow HP as a mic-in */
 	unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
 	unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
+	unsigned int no_multi_io:1; /* Don't try multi I/O config */
 	unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
 	unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
 	unsigned int own_eapd_ctl:1; /* set EAPD by own function */
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index ce67608..fe0bda1 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -295,7 +295,7 @@ static ssize_t type##_store(struct device *dev,			\
 	struct snd_hwdep *hwdep = dev_get_drvdata(dev);		\
 	struct hda_codec *codec = hwdep->private_data;		\
 	unsigned long val;					\
-	int err = strict_strtoul(buf, 0, &val);			\
+	int err = kstrtoul(buf, 0, &val);			\
 	if (err < 0)						\
 		return err;					\
 	codec->type = val;					\
@@ -654,7 +654,7 @@ int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
 	p = snd_hda_get_hint(codec, key);
 	if (!p)
 		ret = -ENOENT;
-	else if (strict_strtoul(p, 0, &val))
+	else if (kstrtoul(p, 0, &val))
 		ret = -EINVAL;
 	else {
 		*valp = val;
@@ -751,7 +751,7 @@ static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
 				 struct hda_codec **codecp) \
 { \
 	unsigned long val; \
-	if (!strict_strtoul(buf, 0, &val)) \
+	if (!kstrtoul(buf, 0, &val)) \
 		(*codecp)->name = val; \
 }
 
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 8860dd5..7f9e406 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1160,7 +1160,7 @@ static int azx_reset(struct azx *chip, int full_reset)
 		goto __skip;
 
 	/* clear STATESTS */
-	azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
+	azx_writew(chip, STATESTS, STATESTS_INT_MASK);
 
 	/* reset controller */
 	azx_enter_link_reset(chip);
@@ -1242,7 +1242,7 @@ static void azx_int_clear(struct azx *chip)
 	}
 
 	/* clear STATESTS */
-	azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
+	azx_writew(chip, STATESTS, STATESTS_INT_MASK);
 
 	/* clear rirb status */
 	azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
@@ -1451,8 +1451,8 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
 
 #if 0
 	/* clear state status int */
-	if (azx_readb(chip, STATESTS) & 0x04)
-		azx_writeb(chip, STATESTS, 0x04);
+	if (azx_readw(chip, STATESTS) & 0x04)
+		azx_writew(chip, STATESTS, 0x04);
 #endif
 	spin_unlock(&chip->reg_lock);
 	
@@ -2971,6 +2971,10 @@ static int azx_runtime_suspend(struct device *dev)
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip = card->private_data;
 
+	/* enable controller wake up event */
+	azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
+		  STATESTS_INT_MASK);
+
 	azx_stop_chip(chip);
 	azx_enter_link_reset(chip);
 	azx_clear_irq_pending(chip);
@@ -2983,11 +2987,31 @@ static int azx_runtime_resume(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip = card->private_data;
+	struct hda_bus *bus;
+	struct hda_codec *codec;
+	int status;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
 		hda_display_power(true);
+
+	/* Read STATESTS before controller reset */
+	status = azx_readw(chip, STATESTS);
+
 	azx_init_pci(chip);
 	azx_init_chip(chip, 1);
+
+	bus = chip->bus;
+	if (status && bus) {
+		list_for_each_entry(codec, &bus->codec_list, list)
+			if (status & (1 << codec->addr))
+				queue_delayed_work(codec->bus->workq,
+						   &codec->jackpoll_work, codec->jackpoll_interval);
+	}
+
+	/* disable controller Wake Up event*/
+	azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
+			~STATESTS_INT_MASK);
+
 	return 0;
 }
 
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 3fd2973..05b3e3e 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -194,18 +194,24 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
 EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
 
 /**
- * snd_hda_jack_detect - query pin Presence Detect status
+ * snd_hda_jack_detect_state - query pin Presence Detect status
  * @codec: the CODEC to sense
  * @nid: the pin NID to sense
  *
- * Query and return the pin's Presence Detect status.
+ * Query and return the pin's Presence Detect status, as either
+ * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
  */
-int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
+int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
 {
-	u32 sense = snd_hda_pin_sense(codec, nid);
-	return get_jack_plug_state(sense);
+	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
+	if (jack && jack->phantom_jack)
+		return HDA_JACK_PHANTOM;
+	else if (snd_hda_pin_sense(codec, nid) & AC_PINSENSE_PRESENCE)
+		return HDA_JACK_PRESENT;
+	else
+		return HDA_JACK_NOT_PRESENT;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
+EXPORT_SYMBOL_HDA(snd_hda_jack_detect_state);
 
 /**
  * snd_hda_jack_detect_enable - enable the jack-detection
@@ -247,8 +253,8 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
 int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
 				 hda_nid_t gating_nid)
 {
-	struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, gated_nid);
-	struct hda_jack_tbl *gating = snd_hda_jack_tbl_get(codec, gating_nid);
+	struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid);
+	struct hda_jack_tbl *gating = snd_hda_jack_tbl_new(codec, gating_nid);
 
 	if (!gated || !gating)
 		return -EINVAL;
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index ec12abd..379420c 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -75,7 +75,18 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
 				 hda_nid_t gating_nid);
 
 u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
-int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
+
+/* the jack state returned from snd_hda_jack_detect_state() */
+enum {
+	HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM,
+};
+
+int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid);
+
+static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
+{
+	return snd_hda_jack_detect_state(codec, nid) != HDA_JACK_NOT_PRESENT;
+}
 
 bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
 
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index d97f0d6..0cbdd87 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -32,7 +32,6 @@
 #include "hda_jack.h"
 #include "hda_generic.h"
 
-#define ENABLE_AD_STATIC_QUIRKS
 
 struct ad198x_spec {
 	struct hda_gen_spec gen;
@@ -43,114 +42,8 @@ struct ad198x_spec {
 	hda_nid_t eapd_nid;
 
 	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
-
-#ifdef ENABLE_AD_STATIC_QUIRKS
-	const struct snd_kcontrol_new *mixers[6];
-	int num_mixers;
-	const struct hda_verb *init_verbs[6];	/* initialization verbs
-						 * don't forget NULL termination!
-						 */
-	unsigned int num_init_verbs;
-
-	/* playback */
-	struct hda_multi_out multiout;	/* playback set-up
-					 * max_channels, dacs must be set
-					 * dig_out_nid and hp_nid are optional
-					 */
-	unsigned int cur_eapd;
-	unsigned int need_dac_fix;
-
-	/* capture */
-	unsigned int num_adc_nids;
-	const hda_nid_t *adc_nids;
-	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
-
-	/* capture source */
-	const struct hda_input_mux *input_mux;
-	const hda_nid_t *capsrc_nids;
-	unsigned int cur_mux[3];
-
-	/* channel model */
-	const struct hda_channel_mode *channel_mode;
-	int num_channel_mode;
-
-	/* PCM information */
-	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
-
-	unsigned int spdif_route;
-
-	unsigned int jack_present: 1;
-	unsigned int inv_jack_detect: 1;/* inverted jack-detection */
-	unsigned int analog_beep: 1;	/* analog beep input present */
-	unsigned int avoid_init_slave_vol:1;
-
-#ifdef CONFIG_PM
-	struct hda_loopback_check loopback;
-#endif
-	/* for virtual master */
-	hda_nid_t vmaster_nid;
-	const char * const *slave_vols;
-	const char * const *slave_sws;
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-};
-
-#ifdef ENABLE_AD_STATIC_QUIRKS
-/*
- * input MUX handling (common part)
- */
-static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
-}
-
-static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
-	return 0;
-}
-
-static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     spec->capsrc_nids[adc_idx],
-				     &spec->cur_mux[adc_idx]);
-}
-
-/*
- * initialization (common callbacks)
- */
-static int ad198x_init(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->num_init_verbs; i++)
-		snd_hda_sequence_write(codec, spec->init_verbs[i]);
-	return 0;
-}
-
-static const char * const ad_slave_pfxs[] = {
-	"Front", "Surround", "Center", "LFE", "Side",
-	"Headphone", "Mono", "Speaker", "IEC958",
-	NULL
 };
 
-static const char * const ad1988_6stack_fp_slave_pfxs[] = {
-	"Front", "Surround", "Center", "LFE", "Side", "IEC958",
-	NULL
-};
-#endif /* ENABLE_AD_STATIC_QUIRKS */
 
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
 /* additional beep mixers; the actual parameters are overwritten at build */
@@ -160,12 +53,6 @@ static const struct snd_kcontrol_new ad_beep_mixer[] = {
 	{ } /* end */
 };
 
-static const struct snd_kcontrol_new ad_beep2_mixer[] = {
-	HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_BEEP("Digital 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 */
 #else
@@ -181,8 +68,7 @@ static int create_beep_ctls(struct hda_codec *codec)
 	if (!spec->beep_amp)
 		return 0;
 
-	knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
-	for ( ; knew->name; knew++) {
+	for (knew = ad_beep_mixer ; knew->name; knew++) {
 		int err;
 		struct snd_kcontrol *kctl;
 		kctl = snd_ctl_new1(knew, codec);
@@ -199,268 +85,6 @@ static int create_beep_ctls(struct hda_codec *codec)
 #define create_beep_ctls(codec)		0
 #endif
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int ad198x_build_controls(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-	struct snd_kcontrol *kctl;
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < spec->num_mixers; i++) {
-		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
-		if (err < 0)
-			return err;
-	}
-	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec,
-						    spec->multiout.dig_out_nid,
-						    spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-		err = snd_hda_create_spdif_share_sw(codec,
-						    &spec->multiout);
-		if (err < 0)
-			return err;
-		spec->multiout.share_spdif = 1;
-	} 
-	if (spec->dig_in_nid) {
-		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
-		if (err < 0)
-			return err;
-	}
-
-	/* create beep controls if needed */
-	err = create_beep_ctls(codec);
-	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];
-		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-					HDA_OUTPUT, vmaster_tlv);
-		err = __snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv,
-					  (spec->slave_vols ?
-					   spec->slave_vols : ad_slave_pfxs),
-					  "Playback Volume",
-					  !spec->avoid_init_slave_vol, NULL);
-		if (err < 0)
-			return err;
-	}
-	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL,
-					  (spec->slave_sws ?
-					   spec->slave_sws : ad_slave_pfxs),
-					  "Playback Switch");
-		if (err < 0)
-			return err;
-	}
-
-	/* assign Capture Source enums to NID */
-	kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
-	if (!kctl)
-		kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
-	for (i = 0; kctl && i < kctl->count; i++) {
-		err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
-		if (err < 0)
-			return err;
-	}
-
-	/* assign IEC958 enums to NID */
-	kctl = snd_hda_find_mixer_ctl(codec,
-			SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
-	if (kctl) {
-		err = snd_hda_add_nid(codec, kctl, 0,
-				      spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
-}
-#endif
-
-/*
- * Analog playback callbacks
- */
-static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				    struct hda_codec *codec,
-				    struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
-}
-
-static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       unsigned int stream_tag,
-				       unsigned int format,
-				       struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
-						format, substream);
-}
-
-static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					   struct hda_codec *codec,
-					   unsigned int stream_tag,
-					   unsigned int format,
-					   struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
-					     format, substream);
-}
-
-static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-					   struct hda_codec *codec,
-					   struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
-	return 0;
-}
-
-/*
- */
-static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 6, /* changed later */
-	.nid = 0, /* fill later */
-	.ops = {
-		.open = ad198x_playback_pcm_open,
-		.prepare = ad198x_playback_pcm_prepare,
-		.cleanup = ad198x_playback_pcm_cleanup,
-	},
-};
-
-static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.prepare = ad198x_capture_pcm_prepare,
-		.cleanup = ad198x_capture_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.open = ad198x_dig_playback_pcm_open,
-		.close = ad198x_dig_playback_pcm_close,
-		.prepare = ad198x_dig_playback_pcm_prepare,
-		.cleanup = ad198x_dig_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-};
-
-static int ad198x_build_pcms(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	info->name = "AD198x Analog";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-
-	if (spec->multiout.dig_out_nid) {
-		info++;
-		codec->num_pcms++;
-		codec->spdif_status_reset = 1;
-		info->name = "AD198x Digital";
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
-		if (spec->dig_in_nid) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
-		}
-	}
-
-	return 0;
-}
-#endif /* ENABLE_AD_STATIC_QUIRKS */
 
 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
 				hda_nid_t hp)
@@ -507,18 +131,6 @@ static void ad198x_shutup(struct hda_codec *codec)
 	ad198x_power_eapd(codec);
 }
 
-static void ad198x_free(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-
-	if (!spec)
-		return;
-
-	snd_hda_gen_spec_free(&spec->gen);
-	kfree(spec);
-	snd_hda_detach_beep_device(codec);
-}
-
 #ifdef CONFIG_PM
 static int ad198x_suspend(struct hda_codec *codec)
 {
@@ -527,65 +139,6 @@ static int ad198x_suspend(struct hda_codec *codec)
 }
 #endif
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static const struct hda_codec_ops ad198x_patch_ops = {
-	.build_controls = ad198x_build_controls,
-	.build_pcms = ad198x_build_pcms,
-	.init = ad198x_init,
-	.free = ad198x_free,
-#ifdef CONFIG_PM
-	.check_power_status = ad198x_check_power_status,
-	.suspend = ad198x_suspend,
-#endif
-	.reboot_notify = ad198x_shutup,
-};
-
-
-/*
- * EAPD control
- * the private value = nid
- */
-#define ad198x_eapd_info	snd_ctl_boolean_mono_info
-
-static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	if (codec->inv_eapd)
-		ucontrol->value.integer.value[0] = ! spec->cur_eapd;
-	else
-		ucontrol->value.integer.value[0] = spec->cur_eapd;
-	return 0;
-}
-
-static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	hda_nid_t nid = kcontrol->private_value & 0xff;
-	unsigned int eapd;
-	eapd = !!ucontrol->value.integer.value[0];
-	if (codec->inv_eapd)
-		eapd = !eapd;
-	if (eapd == spec->cur_eapd)
-		return 0;
-	spec->cur_eapd = eapd;
-	snd_hda_codec_write_cache(codec, nid,
-				  0, AC_VERB_SET_EAPD_BTLENABLE,
-				  eapd ? 0x02 : 0x00);
-	return 1;
-}
-
-static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_info *uinfo);
-static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol);
-static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol);
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 
 /*
  * Automatic parse of I/O pins from the BIOS configuration
@@ -646,580 +199,124 @@ static int ad198x_parse_auto_config(struct hda_codec *codec)
  * AD1986A specific
  */
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-#define AD1986A_SPDIF_OUT	0x02
-#define AD1986A_FRONT_DAC	0x03
-#define AD1986A_SURR_DAC	0x04
-#define AD1986A_CLFE_DAC	0x05
-#define AD1986A_ADC		0x06
-
-static const hda_nid_t ad1986a_dac_nids[3] = {
-	AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
-};
-static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
-static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
-
-static const struct hda_input_mux ad1986a_capture_source = {
-	.num_items = 7,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "CD", 0x1 },
-		{ "Aux", 0x3 },
-		{ "Line", 0x4 },
-		{ "Mix", 0x5 },
-		{ "Mono", 0x6 },
-		{ "Phone", 0x7 },
-	},
-};
-
-
-static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+static int alloc_ad_spec(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec;
 
-static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+	codec->spec = spec;
+	snd_hda_gen_spec_init(&spec->gen);
+	return 0;
+}
 
 /*
- * mixers
+ * AD1986A fixup codes
  */
-static const struct snd_kcontrol_new ad1986a_mixers[] = {
-	/*
-	 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
-	 */
-	HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
-	HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 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),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-/* additional mixers for 3stack mode */
-static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = ad198x_ch_mode_info,
-		.get = ad198x_ch_mode_get,
-		.put = ad198x_ch_mode_put,
-	},
-	{ } /* end */
-};
 
-/* laptop model - 2ch only */
-static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
+/* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
+static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
+				     const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+		codec->inv_jack_detect = 1;
+}
 
-/* master controls both pins 0x1a and 0x1b */
-static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
-		0,
-	},
+enum {
+	AD1986A_FIXUP_INV_JACK_DETECT,
+	AD1986A_FIXUP_ULTRA,
+	AD1986A_FIXUP_SAMSUNG,
+	AD1986A_FIXUP_3STACK,
+	AD1986A_FIXUP_LAPTOP,
+	AD1986A_FIXUP_LAPTOP_IMIC,
 };
 
-static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
-		0,
+static const struct hda_fixup ad1986a_fixups[] = {
+	[AD1986A_FIXUP_INV_JACK_DETECT] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = ad_fixup_inv_jack_detect,
 	},
-};
-
-static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 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),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
+	[AD1986A_FIXUP_ULTRA] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1b, 0x90170110 }, /* speaker */
+			{ 0x1d, 0x90a7013e }, /* int mic */
+			{}
+		},
 	},
-	{ } /* end */
-};
-
-/* laptop-eapd model - 2ch only */
-
-static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x4 },
-		{ "Mix", 0x5 },
+	[AD1986A_FIXUP_SAMSUNG] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1b, 0x90170110 }, /* speaker */
+			{ 0x1d, 0x90a7013e }, /* int mic */
+			{ 0x20, 0x411111f0 }, /* N/A */
+			{ 0x24, 0x411111f0 }, /* N/A */
+			{}
+		},
 	},
-};
-
-static const struct hda_input_mux ad1986a_automic_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Mix", 0x5 },
+	[AD1986A_FIXUP_3STACK] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1a, 0x02214021 }, /* headphone */
+			{ 0x1b, 0x01014011 }, /* front */
+			{ 0x1c, 0x01013012 }, /* surround */
+			{ 0x1d, 0x01019015 }, /* clfe */
+			{ 0x1e, 0x411111f0 }, /* N/A */
+			{ 0x1f, 0x02a190f0 }, /* mic */
+			{ 0x20, 0x018130f0 }, /* line-in */
+			{}
+		},
 	},
-};
-
-static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
-	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
+	[AD1986A_FIXUP_LAPTOP] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1a, 0x02214021 }, /* headphone */
+			{ 0x1b, 0x90170110 }, /* speaker */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			{ 0x1e, 0x411111f0 }, /* N/A */
+			{ 0x1f, 0x02a191f0 }, /* mic */
+			{ 0x20, 0x411111f0 }, /* N/A */
+			{}
+		},
 	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "External Amplifier",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
-		.info = ad198x_eapd_info,
-		.get = ad198x_eapd_get,
-		.put = ad198x_eapd_put,
-		.private_value = 0x1b, /* port-D */
+	[AD1986A_FIXUP_LAPTOP_IMIC] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1d, 0x90a7013e }, /* int mic */
+			{}
+		},
+		.chained_before = 1,
+		.chain_id = AD1986A_FIXUP_LAPTOP,
 	},
-	{ } /* end */
 };
 
-static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
-	{ } /* end */
+static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
+	SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK),
+	SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK),
+	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK),
+	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP),
+	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG),
+	SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA),
+	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
+	SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_FIXUP_3STACK),
+	SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_FIXUP_3STACK),
+	{}
 };
 
-/* re-connect the mic boost input according to the jack sensing */
-static void ad1986a_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-	present = snd_hda_jack_detect(codec, 0x1f);
-	/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
-	snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
-			    present ? 0 : 2);
-}
-
-#define AD1986A_MIC_EVENT		0x36
-
-static void ad1986a_automic_unsol_event(struct hda_codec *codec,
-					    unsigned int res)
-{
-	if ((res >> 26) != AD1986A_MIC_EVENT)
-		return;
-	ad1986a_automic(codec);
-}
-
-static int ad1986a_automic_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1986a_automic(codec);
-	return 0;
-}
-
-/* laptop-automute - 2ch only */
-
-static void ad1986a_update_hp(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-	unsigned int mute;
-
-	if (spec->jack_present)
-		mute = HDA_AMP_MUTE; /* mute internal speaker */
-	else
-		/* unmute internal speaker if necessary */
-		mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
-	snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, mute);
-}
-
-static void ad1986a_hp_automute(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-
-	spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
-	if (spec->inv_jack_detect)
-		spec->jack_present = !spec->jack_present;
-	ad1986a_update_hp(codec);
-}
-
-#define AD1986A_HP_EVENT		0x37
-
-static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) != AD1986A_HP_EVENT)
-		return;
-	ad1986a_hp_automute(codec);
-}
-
-static int ad1986a_hp_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1986a_hp_automute(codec);
-	return 0;
-}
-
-/* bind hp and internal speaker mute (with plug check) */
-static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
-	if (change)
-		ad1986a_update_hp(codec);
-	return change;
-}
-
-static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
-	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = ad1986a_hp_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
-	},
-	{ } /* end */
-};
-
-
-/*
- * initialization verbs
- */
-static const struct hda_verb ad1986a_init_verbs[] = {
-	/* Front, Surround, CLFE DAC; mute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* Downmix - off */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* HP, Line-Out, Surround, CLFE selectors */
-	{0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Mono selector */
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Mic selector: Mic 1/2 pin */
-	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Line-in selector: Line-in */
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Mic 1/2 swap */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Record selector: mic */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Mic, Phone, CD, Aux, Line-In amp; mute as default */
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* PC beep */
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* HP Pin */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
-	/* Front, Surround, CLFE Pins */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* Mono Pin */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* Mic Pin */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* Line, Aux, CD, Beep-In Pin */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	{ } /* end */
-};
-
-static const struct hda_verb ad1986a_ch2_init[] = {
-	/* Surround out -> Line In */
-	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- 	/* Line-in selectors */
-	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
-	/* CLFE -> Mic in */
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
-	{ } /* end */
-};
-
-static const struct hda_verb ad1986a_ch4_init[] = {
-	/* Surround out -> Surround */
-	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* CLFE -> Mic in */
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
-	{ } /* end */
-};
-
-static const struct hda_verb ad1986a_ch6_init[] = {
-	/* Surround out -> Surround out */
-	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* CLFE -> CLFE */
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode ad1986a_modes[3] = {
-	{ 2, ad1986a_ch2_init },
-	{ 4, ad1986a_ch4_init },
-	{ 6, ad1986a_ch6_init },
-};
-
-/* eapd initialization */
-static const struct hda_verb ad1986a_eapd_init_verbs[] = {
-	{0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
-	{}
-};
-
-static const struct hda_verb ad1986a_automic_verbs[] = {
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	/*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
-	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
-	{}
-};
-
-/* Ultra initialization */
-static const struct hda_verb ad1986a_ultra_init[] = {
-	/* eapd initialization */
-	{ 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
-	/* CLFE -> Mic in */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-	{ } /* end */
-};
-
-/* pin sensing on HP jack */
-static const struct hda_verb ad1986a_hp_init_verbs[] = {
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
-	{}
-};
-
-static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
-					    unsigned int res)
-{
-	switch (res >> 26) {
-	case AD1986A_HP_EVENT:
-		ad1986a_hp_automute(codec);
-		break;
-	case AD1986A_MIC_EVENT:
-		ad1986a_automic(codec);
-		break;
-	}
-}
-
-static int ad1986a_samsung_p50_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1986a_hp_automute(codec);
-	ad1986a_automic(codec);
-	return 0;
-}
-
-
-/* models */
-enum {
-	AD1986A_AUTO,
-	AD1986A_6STACK,
-	AD1986A_3STACK,
-	AD1986A_LAPTOP,
-	AD1986A_LAPTOP_EAPD,
-	AD1986A_LAPTOP_AUTOMUTE,
-	AD1986A_ULTRA,
-	AD1986A_SAMSUNG,
-	AD1986A_SAMSUNG_P50,
-	AD1986A_MODELS
-};
-
-static const char * const ad1986a_models[AD1986A_MODELS] = {
-	[AD1986A_AUTO]		= "auto",
-	[AD1986A_6STACK]	= "6stack",
-	[AD1986A_3STACK]	= "3stack",
-	[AD1986A_LAPTOP]	= "laptop",
-	[AD1986A_LAPTOP_EAPD]	= "laptop-eapd",
-	[AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
-	[AD1986A_ULTRA]		= "ultra",
-	[AD1986A_SAMSUNG]	= "samsung",
-	[AD1986A_SAMSUNG_P50]	= "samsung-p50",
-};
-
-static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
-	SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
-	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),
-	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
-	SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
-	{}
-};
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1986a_loopbacks[] = {
-	{ 0x13, HDA_OUTPUT, 0 }, /* Mic */
-	{ 0x14, HDA_OUTPUT, 0 }, /* Phone */
-	{ 0x15, HDA_OUTPUT, 0 }, /* CD */
-	{ 0x16, HDA_OUTPUT, 0 }, /* Aux */
-	{ 0x17, HDA_OUTPUT, 0 }, /* Line */
-	{ } /* end */
-};
-#endif
-
-static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
-{
-	unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
-	return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
-}
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-static int alloc_ad_spec(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	snd_hda_gen_spec_init(&spec->gen);
-	return 0;
-}
-
-/*
- * AD1986A fixup codes
- */
-
-/* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
-static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
-				     const struct hda_fixup *fix, int action)
-{
-	if (action == HDA_FIXUP_ACT_PRE_PROBE)
-		codec->inv_jack_detect = 1;
-}
-
-enum {
-	AD1986A_FIXUP_INV_JACK_DETECT,
-};
-
-static const struct hda_fixup ad1986a_fixups[] = {
-	[AD1986A_FIXUP_INV_JACK_DETECT] = {
-		.type = HDA_FIXUP_FUNC,
-		.v.func = ad_fixup_inv_jack_detect,
-	},
-};
-
-static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
+static const struct hda_model_fixup ad1986a_fixup_models[] = {
+	{ .id = AD1986A_FIXUP_3STACK, .name = "3stack" },
+	{ .id = AD1986A_FIXUP_LAPTOP, .name = "laptop" },
+	{ .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-imic" },
+	{ .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-eapd" }, /* alias */
 	{}
 };
 
 /*
  */
-static int ad1986a_parse_auto_config(struct hda_codec *codec)
+static int patch_ad1986a(struct hda_codec *codec)
 {
 	int err;
 	struct ad198x_spec *spec;
@@ -1244,7 +341,8 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
 	 */
 	spec->gen.multiout.no_share_stream = 1;
 
-	snd_hda_pick_fixup(codec, NULL, ad1986a_fixup_tbl, ad1986a_fixups);
+	snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
+			   ad1986a_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 	err = ad198x_parse_auto_config(codec);
@@ -1258,330 +356,11 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
 	return 0;
 }
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int patch_ad1986a(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int err, board_config;
-
-	board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
-						  ad1986a_models,
-						  ad1986a_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1986A_AUTO;
-	}
-
-	if (board_config == AD1986A_AUTO)
-		return ad1986a_parse_auto_config(codec);
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return err;
-	spec = codec->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;
-	spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = ad1986a_adc_nids;
-	spec->capsrc_nids = ad1986a_capsrc_nids;
-	spec->input_mux = &ad1986a_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = ad1986a_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = ad1986a_init_verbs;
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1986a_loopbacks;
-#endif
-	spec->vmaster_nid = 0x1b;
-	codec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
-
-	codec->patch_ops = ad198x_patch_ops;
-
-	/* override some parameters */
-	switch (board_config) {
-	case AD1986A_3STACK:
-		spec->num_mixers = 2;
-		spec->mixers[1] = ad1986a_3st_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = ad1986a_ch2_init;
-		spec->channel_mode = ad1986a_modes;
-		spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
-		spec->need_dac_fix = 1;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		break;
-	case AD1986A_LAPTOP:
-		spec->mixers[0] = ad1986a_laptop_mixers;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
-		break;
-	case AD1986A_LAPTOP_EAPD:
-		spec->num_mixers = 3;
-		spec->mixers[0] = ad1986a_laptop_master_mixers;
-		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
-		spec->mixers[2] = ad1986a_laptop_intmic_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
-		if (!is_jack_available(codec, 0x25))
-			spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
-		break;
-	case AD1986A_SAMSUNG:
-		spec->num_mixers = 2;
-		spec->mixers[0] = ad1986a_laptop_master_mixers;
-		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
-		spec->num_init_verbs = 3;
-		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
-		spec->init_verbs[2] = ad1986a_automic_verbs;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
-		if (!is_jack_available(codec, 0x25))
-			spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1986a_automic_capture_source;
-		codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
-		codec->patch_ops.init = ad1986a_automic_init;
-		break;
-	case AD1986A_SAMSUNG_P50:
-		spec->num_mixers = 2;
-		spec->mixers[0] = ad1986a_automute_master_mixers;
-		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
-		spec->num_init_verbs = 4;
-		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
-		spec->init_verbs[2] = ad1986a_automic_verbs;
-		spec->init_verbs[3] = ad1986a_hp_init_verbs;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
-		if (!is_jack_available(codec, 0x25))
-			spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1986a_automic_capture_source;
-		codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
-		codec->patch_ops.init = ad1986a_samsung_p50_init;
-		break;
-	case AD1986A_LAPTOP_AUTOMUTE:
-		spec->num_mixers = 3;
-		spec->mixers[0] = ad1986a_automute_master_mixers;
-		spec->mixers[1] = ad1986a_laptop_eapd_mixers;
-		spec->mixers[2] = ad1986a_laptop_intmic_mixers;
-		spec->num_init_verbs = 3;
-		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
-		spec->init_verbs[2] = ad1986a_hp_init_verbs;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
-		if (!is_jack_available(codec, 0x25))
-			spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
-		codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
-		codec->patch_ops.init = ad1986a_hp_init;
-		/* Lenovo N100 seems to report the reversed bit
-		 * for HP jack-sensing
-		 */
-		spec->inv_jack_detect = 1;
-		break;
-	case AD1986A_ULTRA:
-		spec->mixers[0] = ad1986a_laptop_eapd_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = ad1986a_ultra_init;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
-		spec->multiout.dig_out_nid = 0;
-		break;
-	}
-
-	/* AD1986A has a hardware problem that it can't share a stream
-	 * with multiple output pins.  The copy of front to surrounds
-	 * causes noisy or silent outputs at a certain timing, e.g.
-	 * changing the volume.
-	 * So, let's disable the shared stream.
-	 */
-	spec->multiout.no_share_stream = 1;
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1986a	ad1986a_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
 
 /*
  * AD1983 specific
  */
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-#define AD1983_SPDIF_OUT	0x02
-#define AD1983_DAC		0x03
-#define AD1983_ADC		0x04
-
-static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
-static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
-static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
-
-static const struct hda_input_mux ad1983_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Line", 0x1 },
-		{ "Mix", 0x2 },
-		{ "Mix Mono", 0x3 },
-	},
-};
-
-/*
- * SPDIF playback route
- */
-static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	static const char * const texts[] = { "PCM", "ADC" };
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 2;
-	if (uinfo->value.enumerated.item > 1)
-		uinfo->value.enumerated.item = 1;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-
-	ucontrol->value.enumerated.item[0] = spec->spdif_route;
-	return 0;
-}
-
-static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-
-	if (ucontrol->value.enumerated.item[0] > 1)
-		return -EINVAL;
-	if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
-		spec->spdif_route = ucontrol->value.enumerated.item[0];
-		snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
-					  AC_VERB_SET_CONNECT_SEL,
-					  spec->spdif_route);
-		return 1;
-	}
-	return 0;
-}
-
-static const struct snd_kcontrol_new ad1983_mixers[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
-	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("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb ad1983_init_verbs[] = {
-	/* Front, HP, Mono; mute as default */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* Beep, PCM, Mic, Line-In: mute */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* Front, HP selectors; from Mix */
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* Mono selector; from Mix */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
-	/* Mic selector; Mic */
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Line-in selector: Line-in */
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Mic boost: 0dB */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* Record selector: mic */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* SPDIF route: PCM */
-	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Front Pin */
-	{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* HP Pin */
-	{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
-	/* Mono Pin */
-	{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* Mic Pin */
-	{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* Line Pin */
-	{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	{ } /* end */
-};
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1983_loopbacks[] = {
-	{ 0x12, HDA_OUTPUT, 0 }, /* Mic */
-	{ 0x13, HDA_OUTPUT, 0 }, /* Line */
-	{ } /* end */
-};
-#endif
-
-/* models */
-enum {
-	AD1983_AUTO,
-	AD1983_BASIC,
-	AD1983_MODELS
-};
-
-static const char * const ad1983_models[AD1983_MODELS] = {
-	[AD1983_AUTO]		= "auto",
-	[AD1983_BASIC]		= "basic",
-};
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-
 /*
  * SPDIF mux control for AD1983 auto-parser
  */
@@ -1656,7 +435,7 @@ static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
 	return 0;
 }
 
-static int ad1983_parse_auto_config(struct hda_codec *codec)
+static int patch_ad1983(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
 	int err;
@@ -1681,432 +460,11 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
 	return err;
 }
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int patch_ad1983(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int board_config;
-	int err;
-
-	board_config = snd_hda_check_board_config(codec, AD1983_MODELS,
-						  ad1983_models, NULL);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1983_AUTO;
-	}
-
-	if (board_config == AD1983_AUTO)
-		return ad1983_parse_auto_config(codec);
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return err;
-	spec = codec->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;
-	spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = ad1983_adc_nids;
-	spec->capsrc_nids = ad1983_capsrc_nids;
-	spec->input_mux = &ad1983_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = ad1983_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = ad1983_init_verbs;
-	spec->spdif_route = 0;
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1983_loopbacks;
-#endif
-	spec->vmaster_nid = 0x05;
-
-	codec->patch_ops = ad198x_patch_ops;
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1983	ad1983_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 
 /*
  * AD1981 HD specific
  */
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-#define AD1981_SPDIF_OUT	0x02
-#define AD1981_DAC		0x03
-#define AD1981_ADC		0x04
-
-static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
-static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
-static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
-
-/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
-static const struct hda_input_mux ad1981_capture_source = {
-	.num_items = 7,
-	.items = {
-		{ "Front Mic", 0x0 },
-		{ "Line", 0x1 },
-		{ "Mix", 0x2 },
-		{ "Mix Mono", 0x3 },
-		{ "CD", 0x4 },
-		{ "Mic", 0x6 },
-		{ "Aux", 0x7 },
-	},
-};
-
-static const struct snd_kcontrol_new ad1981_mixers[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front 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("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
-	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("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	/* identical with AD1983 */
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb ad1981_init_verbs[] = {
-	/* Front, HP, Mono; mute as default */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* Front, HP selectors; from Mix */
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* Mono selector; from Mix */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
-	/* Mic Mixer; select Front Mic */
-	{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, 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},
-	/* SPDIF route: PCM */
-	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Front Pin */
-	{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* HP Pin */
-	{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
-	/* Mono Pin */
-	{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* Front & Rear Mic Pins */
-	{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* Line Pin */
-	{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* Digital Beep */
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Line-Out as Input: disabled */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	{ } /* end */
-};
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1981_loopbacks[] = {
-	{ 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
-	{ 0x13, HDA_OUTPUT, 0 }, /* Line */
-	{ 0x1b, HDA_OUTPUT, 0 }, /* Aux */
-	{ 0x1c, HDA_OUTPUT, 0 }, /* Mic */
-	{ 0x1d, HDA_OUTPUT, 0 }, /* CD */
-	{ } /* end */
-};
-#endif
-
-/*
- * Patch for HP nx6320
- *
- * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
- * speaker output enabled _and_ mute-LED off.
- */
-
-#define AD1981_HP_EVENT		0x37
-#define AD1981_MIC_EVENT	0x38
-
-static const struct hda_verb ad1981_hp_init_verbs[] = {
-	{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
-	/* pin sensing on HP and Mic jacks */
-	{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
-	{0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
-	{}
-};
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-
-	if (! ad198x_eapd_put(kcontrol, ucontrol))
-		return 0;
-	/* change speaker pin appropriately */
-	snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0);
-	/* toggle HP mute appropriately */
-	snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE,
-				 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
-	return 1;
-}
-
-/* bind volumes of both NID 0x05 and 0x06 */
-static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-/* mute internal speaker if HP is plugged */
-static void ad1981_hp_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x06);
-	snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
-
-/* toggle input of built-in and mic jack appropriately */
-static void ad1981_hp_automic(struct hda_codec *codec)
-{
-	static const struct hda_verb mic_jack_on[] = {
-		{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-		{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-		{}
-	};
-	static const struct hda_verb mic_jack_off[] = {
-		{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-		{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-		{}
-	};
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x08);
-	if (present)
-		snd_hda_sequence_write(codec, mic_jack_on);
-	else
-		snd_hda_sequence_write(codec, mic_jack_off);
-}
-
-/* unsolicited event for HP jack sensing */
-static void ad1981_hp_unsol_event(struct hda_codec *codec,
-				  unsigned int res)
-{
-	res >>= 26;
-	switch (res) {
-	case AD1981_HP_EVENT:
-		ad1981_hp_automute(codec);
-		break;
-	case AD1981_MIC_EVENT:
-		ad1981_hp_automic(codec);
-		break;
-	}
-}
-
-static const struct hda_input_mux ad1981_hp_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Dock Mic", 0x1 },
-		{ "Mix", 0x2 },
-	},
-};
-
-static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
-	HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
-		.name = "Master Playback Switch",
-		.info = ad198x_eapd_info,
-		.get = ad198x_eapd_get,
-		.put = ad1981_hp_master_sw_put,
-		.private_value = 0x05,
-	},
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-#if 0
-	/* FIXME: analog mic/line loopback doesn't work with my tests...
-	 *        (although recording is OK)
-	 */
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
-	/* FIXME: does this laptop have analog CD connection? */
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
-#endif
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-/* initialize jack-sensing, too */
-static int ad1981_hp_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1981_hp_automute(codec);
-	ad1981_hp_automic(codec);
-	return 0;
-}
-
-/* configuration for Toshiba Laptops */
-static const struct hda_verb ad1981_toshiba_init_verbs[] = {
-	{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
-	/* pin sensing on HP and Mic jacks */
-	{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
-	{0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
-	{}
-};
-
-static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
-	HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
-	{ }
-};
-
-/* configuration for Lenovo Thinkpad T60 */
-static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 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("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	/* identical with AD1983 */
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_input_mux ad1981_thinkpad_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Mix", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-/* models */
-enum {
-	AD1981_AUTO,
-	AD1981_BASIC,
-	AD1981_HP,
-	AD1981_THINKPAD,
-	AD1981_TOSHIBA,
-	AD1981_MODELS
-};
-
-static const char * const ad1981_models[AD1981_MODELS] = {
-	[AD1981_AUTO]		= "auto",
-	[AD1981_HP]		= "hp",
-	[AD1981_THINKPAD]	= "thinkpad",
-	[AD1981_BASIC]		= "basic",
-	[AD1981_TOSHIBA]	= "toshiba"
-};
-
-static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
-	SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
-	/* All HP models */
-	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_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
-	/* HP nx6320 (reversed SSID, H/W bug) */
-	SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
-	{}
-};
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-
 /* follow EAPD via vmaster hook */
 static void ad_vmaster_eapd_hook(void *private_data, int enabled)
 {
@@ -2172,7 +530,7 @@ static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
 	{}
 };
 
-static int ad1981_parse_auto_config(struct hda_codec *codec)
+static int patch_ad1981(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
 	int err;
@@ -2205,110 +563,6 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
 	return err;
 }
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int patch_ad1981(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int err, board_config;
-
-	board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
-						  ad1981_models,
-						  ad1981_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1981_AUTO;
-	}
-
-	if (board_config == AD1981_AUTO)
-		return ad1981_parse_auto_config(codec);
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return -ENOMEM;
-	spec = codec->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;
-	spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = ad1981_adc_nids;
-	spec->capsrc_nids = ad1981_capsrc_nids;
-	spec->input_mux = &ad1981_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = ad1981_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = ad1981_init_verbs;
-	spec->spdif_route = 0;
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1981_loopbacks;
-#endif
-	spec->vmaster_nid = 0x05;
-
-	codec->patch_ops = ad198x_patch_ops;
-
-	/* override some parameters */
-	switch (board_config) {
-	case AD1981_HP:
-		spec->mixers[0] = ad1981_hp_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = ad1981_hp_init_verbs;
-		if (!is_jack_available(codec, 0x0a))
-			spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1981_hp_capture_source;
-
-		codec->patch_ops.init = ad1981_hp_init;
-		codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
-		/* set the upper-limit for mixer amp to 0dB for avoiding the
-		 * possible damage by overloading
-		 */
-		snd_hda_override_amp_caps(codec, 0x11, 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 AD1981_THINKPAD:
-		spec->mixers[0] = ad1981_thinkpad_mixers;
-		spec->input_mux = &ad1981_thinkpad_capture_source;
-		/* set the upper-limit for mixer amp to 0dB for avoiding the
-		 * possible damage by overloading
-		 */
-		snd_hda_override_amp_caps(codec, 0x11, 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 AD1981_TOSHIBA:
-		spec->mixers[0] = ad1981_hp_mixers;
-		spec->mixers[1] = ad1981_toshiba_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = ad1981_toshiba_init_verbs;
-		spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1981_hp_capture_source;
-		codec->patch_ops.init = ad1981_hp_init;
-		codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
-		break;
-	}
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1981	ad1981_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 
 /*
  * AD1988
@@ -2395,90 +649,7 @@ static int patch_ad1981(struct hda_codec *codec)
  *      E/F quad mic array
  */
 
-
 #ifdef ENABLE_AD_STATIC_QUIRKS
-/* models */
-enum {
-	AD1988_AUTO,
-	AD1988_6STACK,
-	AD1988_6STACK_DIG,
-	AD1988_3STACK,
-	AD1988_3STACK_DIG,
-	AD1988_LAPTOP,
-	AD1988_LAPTOP_DIG,
-	AD1988_MODEL_LAST,
-};
-
-/* reivision id to check workarounds */
-#define AD1988A_REV2		0x100200
-
-#define is_rev2(codec) \
-	((codec)->vendor_id == 0x11d41988 && \
-	 (codec)->revision_id == AD1988A_REV2)
-
-/*
- * mixers
- */
-
-static const hda_nid_t ad1988_6stack_dac_nids[4] = {
-	0x04, 0x06, 0x05, 0x0a
-};
-
-static const hda_nid_t ad1988_3stack_dac_nids[3] = {
-	0x04, 0x05, 0x0a
-};
-
-/* for AD1988A revision-2, DAC2-4 are swapped */
-static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
-	0x04, 0x05, 0x0a, 0x06
-};
-
-static const hda_nid_t ad1988_alt_dac_nid[1] = {
-	0x03
-};
-
-static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
-	0x04, 0x0a, 0x06
-};
-
-static const hda_nid_t ad1988_adc_nids[3] = {
-	0x08, 0x09, 0x0f
-};
-
-static const hda_nid_t ad1988_capsrc_nids[3] = {
-	0x0c, 0x0d, 0x0e
-};
-
-#define AD1988_SPDIF_OUT		0x02
-#define AD1988_SPDIF_OUT_HDMI	0x0b
-#define AD1988_SPDIF_IN		0x07
-
-static const hda_nid_t ad1989b_slave_dig_outs[] = {
-	AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
-};
-
-static const struct hda_input_mux ad1988_6stack_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "Front Mic", 0x1 },	/* port-B */
-		{ "Line", 0x2 },	/* port-C */
-		{ "Mic", 0x4 },		/* port-E */
-		{ "CD", 0x5 },
-		{ "Mix", 0x9 },
-	},
-};
-
-static const struct hda_input_mux ad1988_laptop_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic/Line", 0x1 },	/* port-B */
-		{ "CD", 0x5 },
-		{ "Mix", 0x9 },
-	},
-};
-
-/*
- */
 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_info *uinfo)
 {
@@ -2509,636 +680,73 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
 	return err;
 }
+#endif /* ENABLE_AD_STATIC_QUIRKS */
 
-/* 6-stack mode */
-static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-/* 3-stack mode */
-static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = ad198x_ch_mode_info,
-		.get = ad198x_ch_mode_get,
-		.put = ad198x_ch_mode_put,
-	},
-
-	{ } /* end */
-};
-
-/* laptop mode */
-static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
-	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
-
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "External Amplifier",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
-		.info = ad198x_eapd_info,
-		.get = ad198x_eapd_get,
-		.put = ad198x_eapd_put,
-		.private_value = 0x12, /* port-D */
-	},
-
-	{ } /* end */
-};
-
-/* capture */
-static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 3,
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
 {
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	static const char * const texts[] = {
-		"PCM", "ADC1", "ADC2", "ADC3"
+		"PCM", "ADC1", "ADC2", "ADC3",
 	};
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 4;
-	if (uinfo->value.enumerated.item >= 4)
-		uinfo->value.enumerated.item = 3;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
+	int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
+	if (num_conns > 4)
+		num_conns = 4;
+	return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
 }
 
-static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	unsigned int sel;
-
-	sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-				 AC_AMP_GET_INPUT);
-	if (!(sel & 0x80))
-		ucontrol->value.enumerated.item[0] = 0;
-	else {
-		sel = snd_hda_codec_read(codec, 0x0b, 0,
-					 AC_VERB_GET_CONNECT_SEL, 0);
-		if (sel < 3)
-			sel++;
-		else
-			sel = 0;
-		ucontrol->value.enumerated.item[0] = sel;
-	}
+	struct ad198x_spec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->cur_smux;
 	return 0;
 }
 
-static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	unsigned int val, sel;
-	int change;
+	struct ad198x_spec *spec = codec->spec;
+	unsigned int val = ucontrol->value.enumerated.item[0];
+	struct nid_path *path;
+	int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
 
-	val = ucontrol->value.enumerated.item[0];
-	if (val > 3)
+	if (val >= num_conns)
 		return -EINVAL;
-	if (!val) {
-		sel = snd_hda_codec_read(codec, 0x1d, 0,
-					 AC_VERB_GET_AMP_GAIN_MUTE,
-					 AC_AMP_GET_INPUT);
-		change = sel & 0x80;
-		if (change) {
-			snd_hda_codec_write_cache(codec, 0x1d, 0,
-						  AC_VERB_SET_AMP_GAIN_MUTE,
-						  AMP_IN_UNMUTE(0));
-			snd_hda_codec_write_cache(codec, 0x1d, 0,
-						  AC_VERB_SET_AMP_GAIN_MUTE,
-						  AMP_IN_MUTE(1));
-		}
-	} else {
-		sel = snd_hda_codec_read(codec, 0x1d, 0,
-					 AC_VERB_GET_AMP_GAIN_MUTE,
-					 AC_AMP_GET_INPUT | 0x01);
-		change = sel & 0x80;
-		if (change) {
-			snd_hda_codec_write_cache(codec, 0x1d, 0,
-						  AC_VERB_SET_AMP_GAIN_MUTE,
-						  AMP_IN_MUTE(0));
-			snd_hda_codec_write_cache(codec, 0x1d, 0,
-						  AC_VERB_SET_AMP_GAIN_MUTE,
-						  AMP_IN_UNMUTE(1));
-		}
-		sel = snd_hda_codec_read(codec, 0x0b, 0,
-					 AC_VERB_GET_CONNECT_SEL, 0) + 1;
-		change |= sel != val;
-		if (change)
-			snd_hda_codec_write_cache(codec, 0x0b, 0,
-						  AC_VERB_SET_CONNECT_SEL,
-						  val - 1);
-	}
-	return change;
-}
+	if (spec->cur_smux == val)
+		return 0;
 
-static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
-	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "IEC958 Playback Source",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
-		.info = ad1988_spdif_playback_source_info,
-		.get = ad1988_spdif_playback_source_get,
-		.put = ad1988_spdif_playback_source_put,
-	},
-	{ } /* end */
-};
+	mutex_lock(&codec->control_mutex);
+	codec->cached_write = 1;
+	path = snd_hda_get_path_from_idx(codec,
+					 spec->smux_paths[spec->cur_smux]);
+	if (path)
+		snd_hda_activate_path(codec, path, false, true);
+	path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
+	if (path)
+		snd_hda_activate_path(codec, path, true, true);
+	spec->cur_smux = val;
+	codec->cached_write = 0;
+	mutex_unlock(&codec->control_mutex);
+	snd_hda_codec_flush_cache(codec); /* flush the updates */
+	return 1;
+}
 
-static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
-	HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
-	{ } /* end */
+static struct snd_kcontrol_new ad1988_auto_smux_mixer = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "IEC958 Playback Source",
+	.info = ad1988_auto_smux_enum_info,
+	.get = ad1988_auto_smux_enum_get,
+	.put = ad1988_auto_smux_enum_put,
 };
 
-static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
-	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-/*
- * initialization verbs
- */
-
-/*
- * for 6-stack (+dig)
- */
-static const struct hda_verb ad1988_6stack_init_verbs[] = {
-	/* Front, Surround, CLFE, side DAC; unmute as default */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-A front headphon path */
-	{0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Port-D line-out path */
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-F surround path */
-	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-G CLFE path */
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-H side path */
-	{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Mono out path */
-	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
-	/* Port-B front mic-in path */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Port-C line-in path */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Port-E mic-in path */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Analog CD Input */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-
-	{ }
-};
-
-static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
-	/* Headphone; unmute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-A front headphon path */
-	{0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-
-	{ }
-};
-
-static const struct hda_verb ad1988_capture_init_verbs[] = {
-	/* mute analog mix */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* select ADCs - front-mic */
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-
-	{ }
-};
-
-static const struct hda_verb ad1988_spdif_init_verbs[] = {
-	/* SPDIF out sel */
-	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* SPDIF out pin */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-
-	{ }
-};
-
-static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
-	/* unmute SPDIF input pin */
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{ }
-};
-
-/* AD1989 has no ADC -> SPDIF route */
-static const struct hda_verb ad1989_spdif_init_verbs[] = {
-	/* SPDIF-1 out pin */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-	/* SPDIF-2/HDMI out pin */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-	{ }
-};
-
-/*
- * verbs for 3stack (+dig)
- */
-static const struct hda_verb ad1988_3stack_ch2_init[] = {
-	/* set port-C to line-in */
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* set port-E to mic-in */
-	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ } /* end */
-};
-
-static const struct hda_verb ad1988_3stack_ch6_init[] = {
-	/* set port-C to surround out */
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	/* set port-E to CLFE out */
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode ad1988_3stack_modes[2] = {
-	{ 2, ad1988_3stack_ch2_init },
-	{ 6, ad1988_3stack_ch6_init },
-};
-
-static const struct hda_verb ad1988_3stack_init_verbs[] = {
-	/* Front, Surround, CLFE, side DAC; unmute as default */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-A front headphon path */
-	{0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Port-D line-out path */
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Mono out path */
-	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
-	/* Port-B front mic-in path */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Port-C line-in/surround path - 6ch mode as default */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
-	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Port-E mic-in/CLFE path - 6ch mode as default */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* mute analog mix */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* select ADCs - front-mic */
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-	{ }
-};
-
-/*
- * verbs for laptop mode (+dig)
- */
-static const struct hda_verb ad1988_laptop_hp_on[] = {
-	/* unmute port-A and mute port-D */
-	{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-static const struct hda_verb ad1988_laptop_hp_off[] = {
-	/* mute port-A and unmute port-D */
-	{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
-
-#define AD1988_HP_EVENT	0x01
-
-static const struct hda_verb ad1988_laptop_init_verbs[] = {
-	/* Front, Surround, CLFE, side DAC; unmute as default */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-A front headphon path */
-	{0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* unsolicited event for pin-sense */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
-	/* Port-D line-out path + EAPD */
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
-	/* Mono out path */
-	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
-	/* Port-B mic-in path */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Port-C docking station - try to output */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* mute analog mix */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* select ADCs - mic */
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-	{ }
-};
-
-static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) != AD1988_HP_EVENT)
-		return;
-	if (snd_hda_jack_detect(codec, 0x11))
-		snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
-	else
-		snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
-} 
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1988_loopbacks[] = {
-	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
-	{ 0x20, HDA_INPUT, 1 }, /* Line */
-	{ 0x20, HDA_INPUT, 4 }, /* Mic */
-	{ 0x20, HDA_INPUT, 6 }, /* CD */
-	{ } /* end */
-};
-#endif
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
-				      struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	static const char * const texts[] = {
-		"PCM", "ADC1", "ADC2", "ADC3",
-	};
-	int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
-	if (num_conns > 4)
-		num_conns = 4;
-	return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
-}
-
-static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-
-	ucontrol->value.enumerated.item[0] = spec->cur_smux;
-	return 0;
-}
-
-static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	unsigned int val = ucontrol->value.enumerated.item[0];
-	struct nid_path *path;
-	int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
-
-	if (val >= num_conns)
-		return -EINVAL;
-	if (spec->cur_smux == val)
-		return 0;
-
-	mutex_lock(&codec->control_mutex);
-	codec->cached_write = 1;
-	path = snd_hda_get_path_from_idx(codec,
-					 spec->smux_paths[spec->cur_smux]);
-	if (path)
-		snd_hda_activate_path(codec, path, false, true);
-	path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
-	if (path)
-		snd_hda_activate_path(codec, path, true, true);
-	spec->cur_smux = val;
-	codec->cached_write = 0;
-	mutex_unlock(&codec->control_mutex);
-	snd_hda_codec_flush_cache(codec); /* flush the updates */
-	return 1;
-}
-
-static struct snd_kcontrol_new ad1988_auto_smux_mixer = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "IEC958 Playback Source",
-	.info = ad1988_auto_smux_enum_info,
-	.get = ad1988_auto_smux_enum_get,
-	.put = ad1988_auto_smux_enum_put,
-};
-
-static int ad1988_auto_init(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-	int i, err;
+static int ad1988_auto_init(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec = codec->spec;
+	int i, err;
 
 	err = snd_hda_gen_init(codec);
 	if (err < 0)
@@ -3220,7 +828,34 @@ static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
 /*
  */
 
-static int ad1988_parse_auto_config(struct hda_codec *codec)
+enum {
+	AD1988_FIXUP_6STACK_DIG,
+};
+
+static const struct hda_fixup ad1988_fixups[] = {
+	[AD1988_FIXUP_6STACK_DIG] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x11, 0x02214130 }, /* front-hp */
+			{ 0x12, 0x01014010 }, /* line-out */
+			{ 0x14, 0x02a19122 }, /* front-mic */
+			{ 0x15, 0x01813021 }, /* line-in */
+			{ 0x16, 0x01011012 }, /* line-out */
+			{ 0x17, 0x01a19020 }, /* mic */
+			{ 0x1b, 0x0145f1f0 }, /* SPDIF */
+			{ 0x24, 0x01016011 }, /* line-out */
+			{ 0x25, 0x01012013 }, /* line-out */
+			{ }
+		}
+	},
+};
+
+static const struct hda_model_fixup ad1988_fixup_models[] = {
+	{ .id = AD1988_FIXUP_6STACK_DIG, .name = "6stack-dig" },
+	{}
+};
+
+static int patch_ad1988(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
 	int err;
@@ -3234,12 +869,19 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
 	spec->gen.mixer_merge_nid = 0x21;
 	spec->gen.beep_nid = 0x10;
 	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
+	snd_hda_pick_fixup(codec, ad1988_fixup_models, NULL, ad1988_fixups);
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
 	err = ad198x_parse_auto_config(codec);
 	if (err < 0)
 		goto error;
 	err = ad1988_add_spdif_mux_ctl(codec);
 	if (err < 0)
 		goto error;
+
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
+
 	return 0;
 
  error:
@@ -3247,169 +889,6 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
 	return err;
 }
 
-/*
- */
-
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static const char * const ad1988_models[AD1988_MODEL_LAST] = {
-	[AD1988_6STACK]		= "6stack",
-	[AD1988_6STACK_DIG]	= "6stack-dig",
-	[AD1988_3STACK]		= "3stack",
-	[AD1988_3STACK_DIG]	= "3stack-dig",
-	[AD1988_LAPTOP]		= "laptop",
-	[AD1988_LAPTOP_DIG]	= "laptop-dig",
-	[AD1988_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
-	SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
-	SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
-	{}
-};
-
-static int patch_ad1988(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int err, board_config;
-
-	board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
-						  ad1988_models, ad1988_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1988_AUTO;
-	}
-
-	if (board_config == AD1988_AUTO)
-		return ad1988_parse_auto_config(codec);
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return err;
-	spec = codec->spec;
-
-	if (is_rev2(codec))
-		snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
-
-	err = snd_hda_attach_beep_device(codec, 0x10);
-	if (err < 0) {
-		ad198x_free(codec);
-		return err;
-	}
-	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
-
-	if (!spec->multiout.hp_nid)
-		spec->multiout.hp_nid = ad1988_alt_dac_nid[0];
-	switch (board_config) {
-	case AD1988_6STACK:
-	case AD1988_6STACK_DIG:
-		spec->multiout.max_channels = 8;
-		spec->multiout.num_dacs = 4;
-		if (is_rev2(codec))
-			spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
-		else
-			spec->multiout.dac_nids = ad1988_6stack_dac_nids;
-		spec->input_mux = &ad1988_6stack_capture_source;
-		spec->num_mixers = 2;
-		if (is_rev2(codec))
-			spec->mixers[0] = ad1988_6stack_mixers1_rev2;
-		else
-			spec->mixers[0] = ad1988_6stack_mixers1;
-		spec->mixers[1] = ad1988_6stack_mixers2;
-		spec->num_init_verbs = 1;
-		spec->init_verbs[0] = ad1988_6stack_init_verbs;
-		if (board_config == AD1988_6STACK_DIG) {
-			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
-			spec->dig_in_nid = AD1988_SPDIF_IN;
-		}
-		break;
-	case AD1988_3STACK:
-	case AD1988_3STACK_DIG:
-		spec->multiout.max_channels = 6;
-		spec->multiout.num_dacs = 3;
-		if (is_rev2(codec))
-			spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
-		else
-			spec->multiout.dac_nids = ad1988_3stack_dac_nids;
-		spec->input_mux = &ad1988_6stack_capture_source;
-		spec->channel_mode = ad1988_3stack_modes;
-		spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
-		spec->num_mixers = 2;
-		if (is_rev2(codec))
-			spec->mixers[0] = ad1988_3stack_mixers1_rev2;
-		else
-			spec->mixers[0] = ad1988_3stack_mixers1;
-		spec->mixers[1] = ad1988_3stack_mixers2;
-		spec->num_init_verbs = 1;
-		spec->init_verbs[0] = ad1988_3stack_init_verbs;
-		if (board_config == AD1988_3STACK_DIG)
-			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
-		break;
-	case AD1988_LAPTOP:
-	case AD1988_LAPTOP_DIG:
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		spec->multiout.dac_nids = ad1988_3stack_dac_nids;
-		spec->input_mux = &ad1988_laptop_capture_source;
-		spec->num_mixers = 1;
-		spec->mixers[0] = ad1988_laptop_mixers;
-		codec->inv_eapd = 1; /* inverted EAPD */
-		spec->num_init_verbs = 1;
-		spec->init_verbs[0] = ad1988_laptop_init_verbs;
-		if (board_config == AD1988_LAPTOP_DIG)
-			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
-		break;
-	}
-
-	spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
-	spec->adc_nids = ad1988_adc_nids;
-	spec->capsrc_nids = ad1988_capsrc_nids;
-	spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
-	spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
-	if (spec->multiout.dig_out_nid) {
-		if (codec->vendor_id >= 0x11d4989a) {
-			spec->mixers[spec->num_mixers++] =
-				ad1989_spdif_out_mixers;
-			spec->init_verbs[spec->num_init_verbs++] =
-				ad1989_spdif_init_verbs;
-			codec->slave_dig_outs = ad1989b_slave_dig_outs;
-		} else {
-			spec->mixers[spec->num_mixers++] =
-				ad1988_spdif_out_mixers;
-			spec->init_verbs[spec->num_init_verbs++] =
-				ad1988_spdif_init_verbs;
-		}
-	}
-	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
-		spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
-		spec->init_verbs[spec->num_init_verbs++] =
-			ad1988_spdif_in_init_verbs;
-	}
-
-	codec->patch_ops = ad198x_patch_ops;
-	switch (board_config) {
-	case AD1988_LAPTOP:
-	case AD1988_LAPTOP_DIG:
-		codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
-		break;
-	}
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1988_loopbacks;
-#endif
-	spec->vmaster_nid = 0x04;
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1988	ad1988_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 
 /*
  * AD1884 / AD1984
@@ -3423,167 +902,19 @@ static int patch_ad1988(struct hda_codec *codec)
  *
  * AD1984 = AD1884 + two digital mic-ins
  *
- * FIXME:
- * For simplicity, we share the single DAC for both HP and line-outs
- * right now.  The inidividual playbacks could be easily implemented,
- * but no build-up framework is given, so far.
- */
-
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static const hda_nid_t ad1884_dac_nids[1] = {
-	0x04,
-};
-
-static const hda_nid_t ad1884_adc_nids[2] = {
-	0x08, 0x09,
-};
-
-static const hda_nid_t ad1884_capsrc_nids[2] = {
-	0x0c, 0x0d,
-};
-
-#define AD1884_SPDIF_OUT	0x02
-
-static const struct hda_input_mux ad1884_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Front Mic", 0x0 },
-		{ "Mic", 0x1 },
-		{ "CD", 0x2 },
-		{ "Mix", 0x3 },
-	},
-};
-
-static const struct snd_kcontrol_new ad1884_base_mixers[] = {
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, 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),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	/* SPDIF controls */
-	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		/* identical with ad1983 */
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
-	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
-			     HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
-			   HDA_INPUT),
-	{ } /* end */
-};
-
-/*
- * initialization verbs
+ * AD1883 / AD1884A / AD1984A / AD1984B
+ *
+ * port-B (0x14) - front mic-in
+ * port-E (0x1c) - rear mic-in
+ * port-F (0x16) - CD / ext out
+ * port-C (0x15) - rear line-in
+ * port-D (0x12) - rear line-out
+ * port-A (0x11) - front hp-out
+ *
+ * AD1984A = AD1884A + digital-mic
+ * AD1883 = equivalent with AD1984A
+ * AD1984B = AD1984A + extra SPDIF-out
  */
-static const struct hda_verb ad1884_init_verbs[] = {
-	/* DACs; mute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Port-A (HP) mixer */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-A pin */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* HP selector - select DAC2 */
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* Port-D (Line-out) mixer */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-D pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mono-out mixer */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Mono-out pin */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mono selector */
-	{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_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_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)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-	/* SPDIF output selector */
-	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-	{ } /* end */
-};
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1884_loopbacks[] = {
-	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
-	{ 0x20, HDA_INPUT, 1 }, /* Mic */
-	{ 0x20, HDA_INPUT, 2 }, /* CD */
-	{ 0x20, HDA_INPUT, 4 }, /* Docking */
-	{ } /* end */
-};
-#endif
-
-static const char * const ad1884_slave_vols[] = {
-	"PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
-	"Internal Mic", "Dock Mic", /* "Beep", */ "IEC958",
-	NULL
-};
-
-enum {
-	AD1884_AUTO,
-	AD1884_BASIC,
-	AD1884_MODELS
-};
-
-static const char * const ad1884_models[AD1884_MODELS] = {
-	[AD1884_AUTO]		= "auto",
-	[AD1884_BASIC]		= "basic",
-};
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 
 /* set the upper-limit for mixer amp to 0dB for avoiding the possible
  * damage by overloading
@@ -3599,14 +930,34 @@ static void ad1884_fixup_amp_override(struct hda_codec *codec,
 					  (1 << AC_AMPCAP_MUTE_SHIFT));
 }
 
+/* toggle GPIO1 according to the mute state */
+static void ad1884_vmaster_hp_gpio_hook(void *private_data, int enabled)
+{
+	struct hda_codec *codec = private_data;
+	struct ad198x_spec *spec = codec->spec;
+
+	if (spec->eapd_nid)
+		ad_vmaster_eapd_hook(private_data, enabled);
+	snd_hda_codec_update_cache(codec, 0x01, 0,
+				   AC_VERB_SET_GPIO_DATA,
+				   enabled ? 0x00 : 0x02);
+}
+
 static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
 				 const struct hda_fixup *fix, int action)
 {
 	struct ad198x_spec *spec = codec->spec;
+	static const struct hda_verb gpio_init_verbs[] = {
+		{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+		{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+		{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
+		{},
+	};
 
 	switch (action) {
 	case HDA_FIXUP_ACT_PRE_PROBE:
-		spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
+		spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
+		snd_hda_sequence_write_cache(codec, gpio_init_verbs);
 		break;
 	case HDA_FIXUP_ACT_PROBE:
 		if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
@@ -3617,9 +968,18 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
 	}
 }
 
+/* set magic COEFs for dmic */
+static const struct hda_verb ad1884_dmic_init_verbs[] = {
+	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
+	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
+	{}
+};
+
 enum {
 	AD1884_FIXUP_AMP_OVERRIDE,
 	AD1884_FIXUP_HP_EAPD,
+	AD1884_FIXUP_DMIC_COEF,
+	AD1884_FIXUP_HP_TOUCHSMART,
 };
 
 static const struct hda_fixup ad1884_fixups[] = {
@@ -3633,15 +993,27 @@ static const struct hda_fixup ad1884_fixups[] = {
 		.chained = true,
 		.chain_id = AD1884_FIXUP_AMP_OVERRIDE,
 	},
+	[AD1884_FIXUP_DMIC_COEF] = {
+		.type = HDA_FIXUP_VERBS,
+		.v.verbs = ad1884_dmic_init_verbs,
+	},
+	[AD1884_FIXUP_HP_TOUCHSMART] = {
+		.type = HDA_FIXUP_VERBS,
+		.v.verbs = ad1884_dmic_init_verbs,
+		.chained = true,
+		.chain_id = AD1884_FIXUP_HP_EAPD,
+	},
 };
 
 static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
 	SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_DMIC_COEF),
 	{}
 };
 
 
-static int ad1884_parse_auto_config(struct hda_codec *codec)
+static int patch_ad1884(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
 	int err;
@@ -3674,1170 +1046,6 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
 	return err;
 }
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int patch_ad1884_basic(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int err;
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return err;
-	spec = codec->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;
-	spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
-	spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
-	spec->adc_nids = ad1884_adc_nids;
-	spec->capsrc_nids = ad1884_capsrc_nids;
-	spec->input_mux = &ad1884_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = ad1884_base_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = ad1884_init_verbs;
-	spec->spdif_route = 0;
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1884_loopbacks;
-#endif
-	spec->vmaster_nid = 0x04;
-	/* we need to cover all playback volumes */
-	spec->slave_vols = ad1884_slave_vols;
-	/* slaves may contain input volumes, so we can't raise to 0dB blindly */
-	spec->avoid_init_slave_vol = 1;
-
-	codec->patch_ops = ad198x_patch_ops;
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-
-static int patch_ad1884(struct hda_codec *codec)
-{
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, AD1884_MODELS,
-						  ad1884_models, NULL);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1884_AUTO;
-	}
-
-	if (board_config == AD1884_AUTO)
-		return ad1884_parse_auto_config(codec);
-	else
-		return patch_ad1884_basic(codec);
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1884	ad1884_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-
-#ifdef ENABLE_AD_STATIC_QUIRKS
-/*
- * Lenovo Thinkpad T61/X61
- */
-static const struct hda_input_mux ad1984_thinkpad_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-		{ "Mix", 0x3 },
-		{ "Dock Mic", 0x4 },
-	},
-};
-
-
-/*
- * Dell Precision T3400
- */
-static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Front Mic", 0x0 },
-		{ "Line-In", 0x1 },
-		{ "Mix", 0x3 },
-	},
-};
-
-
-static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, 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("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	/* SPDIF controls */
-	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		/* identical with ad1983 */
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-/* additional verbs */
-static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
-	/* Port-E (docking station mic) pin */
-	{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_ZERO},
-	/* Analog PC Beeper - allow firmware/ACPI beeps */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
-	/* Analog mixer - docking mic; mute as default */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* enable EAPD bit */
-	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	{ } /* end */
-};
-
-/*
- * Dell Precision T3400
- */
-static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	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("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, 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),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-/* Digial MIC ADC NID 0x05 + 0x06 */
-static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
-				   struct hda_codec *codec,
-				   unsigned int stream_tag,
-				   unsigned int format,
-				   struct snd_pcm_substream *substream)
-{
-	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
-				   struct hda_codec *codec,
-				   struct snd_pcm_substream *substream)
-{
-	snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
-	return 0;
-}
-
-static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x05,
-	.ops = {
-		.prepare = ad1984_pcm_dmic_prepare,
-		.cleanup = ad1984_pcm_dmic_cleanup
-	},
-};
-
-static int ad1984_build_pcms(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec = codec->spec;
-	struct hda_pcm *info;
-	int err;
-
-	err = ad198x_build_pcms(codec);
-	if (err < 0)
-		return err;
-
-	info = spec->pcm_rec + codec->num_pcms;
-	codec->num_pcms++;
-	info->name = "AD1984 Digital Mic";
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
-	return 0;
-}
-
-/* models */
-enum {
-	AD1984_AUTO,
-	AD1984_BASIC,
-	AD1984_THINKPAD,
-	AD1984_DELL_DESKTOP,
-	AD1984_MODELS
-};
-
-static const char * const ad1984_models[AD1984_MODELS] = {
-	[AD1984_AUTO]		= "auto",
-	[AD1984_BASIC]		= "basic",
-	[AD1984_THINKPAD]	= "thinkpad",
-	[AD1984_DELL_DESKTOP]	= "dell_desktop",
-};
-
-static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
-	/* Lenovo Thinkpad T61/X61 */
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
-	SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
-	SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
-	{}
-};
-
-static int patch_ad1984(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int board_config, err;
-
-	board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
-						  ad1984_models, ad1984_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1984_AUTO;
-	}
-
-	if (board_config == AD1984_AUTO)
-		return ad1884_parse_auto_config(codec);
-
-	err = patch_ad1884_basic(codec);
-	if (err < 0)
-		return err;
-	spec = codec->spec;
-
-	switch (board_config) {
-	case AD1984_BASIC:
-		/* additional digital mics */
-		spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
-		codec->patch_ops.build_pcms = ad1984_build_pcms;
-		break;
-	case AD1984_THINKPAD:
-		if (codec->subsystem_id == 0x17aa20fb) {
-			/* Thinpad X300 does not have the ability to do SPDIF,
-			   or attach to docking station to use SPDIF */
-			spec->multiout.dig_out_nid = 0;
-		} else
-			spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
-		spec->input_mux = &ad1984_thinkpad_capture_source;
-		spec->mixers[0] = ad1984_thinkpad_mixers;
-		spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
-		spec->analog_beep = 1;
-		break;
-	case AD1984_DELL_DESKTOP:
-		spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1984_dell_desktop_capture_source;
-		spec->mixers[0] = ad1984_dell_desktop_mixers;
-		break;
-	}
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1984	ad1884_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-
-/*
- * AD1883 / AD1884A / AD1984A / AD1984B
- *
- * port-B (0x14) - front mic-in
- * port-E (0x1c) - rear mic-in
- * port-F (0x16) - CD / ext out
- * port-C (0x15) - rear line-in
- * port-D (0x12) - rear line-out
- * port-A (0x11) - front hp-out
- *
- * AD1984A = AD1884A + digital-mic
- * AD1883 = equivalent with AD1984A
- * AD1984B = AD1984A + extra SPDIF-out
- *
- * FIXME:
- * We share the single DAC for both HP and line-outs (see AD1884/1984).
- */
-
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static const hda_nid_t ad1884a_dac_nids[1] = {
-	0x03,
-};
-
-#define ad1884a_adc_nids	ad1884_adc_nids
-#define ad1884a_capsrc_nids	ad1884_capsrc_nids
-
-#define AD1884A_SPDIF_OUT	0x02
-
-static const struct hda_input_mux ad1884a_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "Front Mic", 0x0 },
-		{ "Mic", 0x4 },
-		{ "Line", 0x1 },
-		{ "CD", 0x2 },
-		{ "Mix", 0x3 },
-	},
-};
-
-static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	/* SPDIF controls */
-	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		/* identical with ad1983 */
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-/*
- * initialization verbs
- */
-static const struct hda_verb ad1884a_init_verbs[] = {
-	/* DACs; unmute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	/* Port-A (HP) mixer - route only from analog mixer */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-A pin */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Port-D (Line-out) mixer - route only from analog mixer */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-D pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mono-out mixer - route only from analog mixer */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Mono-out pin */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Port-B (front mic) pin */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_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_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},
-	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
-	/* Port-F (CD) pin */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Analog mixer; mute as default */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* capture sources */
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* SPDIF output amp */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-	{ } /* end */
-};
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1884a_loopbacks[] = {
-	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
-	{ 0x20, HDA_INPUT, 1 }, /* Mic */
-	{ 0x20, HDA_INPUT, 2 }, /* CD */
-	{ 0x20, HDA_INPUT, 4 }, /* Docking */
-	{ } /* end */
-};
-#endif
-
-/*
- * Laptop model
- *
- * Port A: Headphone jack
- * Port B: MIC jack
- * Port C: Internal MIC
- * Port D: Dock Line Out (if enabled)
- * Port E: Dock Line In (if enabled)
- * Port F: Internal speakers
- */
-
-static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
-					struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
-	int mute = (!ucontrol->value.integer.value[0] &&
-		    !ucontrol->value.integer.value[1]);
-	/* toggle GPIO1 according to the mute state */
-	snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
-			    mute ? 0x02 : 0x0);
-	return ret;
-}
-
-static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = ad1884a_mobile_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
-	},
-	HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	/*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = ad1884a_mobile_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
-	},
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic 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),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-/* mute internal speaker if HP is plugged */
-static void ad1884a_hp_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x11);
-	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
-			    present ? 0x00 : 0x02);
-}
-
-/* switch to external mic if plugged */
-static void ad1884a_hp_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x14);
-	snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
-			    present ? 0 : 1);
-}
-
-#define AD1884A_HP_EVENT		0x37
-#define AD1884A_MIC_EVENT		0x36
-
-/* unsolicited event for HP jack sensing */
-static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	switch (res >> 26) {
-	case AD1884A_HP_EVENT:
-		ad1884a_hp_automute(codec);
-		break;
-	case AD1884A_MIC_EVENT:
-		ad1884a_hp_automic(codec);
-		break;
-	}
-}
-
-/* initialize jack-sensing, too */
-static int ad1884a_hp_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1884a_hp_automute(codec);
-	ad1884a_hp_automic(codec);
-	return 0;
-}
-
-/* mute internal speaker if HP or docking HP is plugged */
-static void ad1884a_laptop_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x11);
-	if (!present)
-		present = snd_hda_jack_detect(codec, 0x12);
-	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
-			    present ? 0x00 : 0x02);
-}
-
-/* switch to external mic if plugged */
-static void ad1884a_laptop_automic(struct hda_codec *codec)
-{
-	unsigned int idx;
-
-	if (snd_hda_jack_detect(codec, 0x14))
-		idx = 0;
-	else if (snd_hda_jack_detect(codec, 0x1c))
-		idx = 4;
-	else
-		idx = 1;
-	snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
-}
-
-/* unsolicited event for HP jack sensing */
-static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	switch (res >> 26) {
-	case AD1884A_HP_EVENT:
-		ad1884a_laptop_automute(codec);
-		break;
-	case AD1884A_MIC_EVENT:
-		ad1884a_laptop_automic(codec);
-		break;
-	}
-}
-
-/* initialize jack-sensing, too */
-static int ad1884a_laptop_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1884a_laptop_automute(codec);
-	ad1884a_laptop_automic(codec);
-	return 0;
-}
-
-/* additional verbs for laptop model */
-static const struct hda_verb ad1884a_laptop_verbs[] = {
-	/* Port-A (HP) pin - always unmuted */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-F (int speaker) mixer - route only from analog mixer */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-F (int speaker) pin */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* required for compaq 6530s/6531s speaker output */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-C pin - internal mic-in */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-	/* Port-D (docking line-out) pin - default unmuted */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* analog mix */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* unsolicited event for pin-sense */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
-	/* allow to touch GPIO1 (for mute control) */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
-	{ } /* end */
-};
-
-static const struct hda_verb ad1884a_mobile_verbs[] = {
-	/* DACs; unmute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	/* Port-A (HP) mixer - route only from analog mixer */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-A pin */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Port-A (HP) pin - always unmuted */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-B (mic jack) pin */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-	/* Port-C (int mic) pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-	/* Port-F (int speaker) mixer - route only from analog mixer */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-F pin */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Analog mixer; mute as default */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* capture sources */
-	/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* unsolicited event for pin-sense */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
-	/* allow to touch GPIO1 (for mute control) */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
-	{ } /* end */
-};
-
-/*
- * Thinkpad X300
- * 0x11 - HP
- * 0x12 - speaker
- * 0x14 - mic-in
- * 0x17 - built-in mic
- */
-
-static const struct hda_verb ad1984a_thinkpad_verbs[] = {
-	/* HP unmute */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* analog mix */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* turn on EAPD */
-	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	/* unsolicited event for pin-sense */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-	/* internal mic - dmic */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* set magic COEFs for dmic */
-	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
-	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x5 },
-		{ "Mix", 0x3 },
-	},
-};
-
-/* mute internal speaker if HP is plugged */
-static void ad1984a_thinkpad_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x11);
-	snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
-
-/* unsolicited event for HP jack sensing */
-static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
-					 unsigned int res)
-{
-	if ((res >> 26) != AD1884A_HP_EVENT)
-		return;
-	ad1984a_thinkpad_automute(codec);
-}
-
-/* initialize jack-sensing, too */
-static int ad1984a_thinkpad_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1984a_thinkpad_automute(codec);
-	return 0;
-}
-
-/*
- * Precision R5500
- * 0x12 - HP/line-out
- * 0x13 - speaker (mono)
- * 0x15 - mic-in
- */
-
-static const struct hda_verb ad1984a_precision_verbs[] = {
-	/* Unmute main output path */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
-	/* Analog mixer; mute as default */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Select mic as input */
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
-	/* Configure as mic */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-	/* HP unmute */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* turn on EAPD */
-	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	/* unsolicited event for pin-sense */
-	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-
-/* mute internal speaker if HP is plugged */
-static void ad1984a_precision_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x12);
-	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
-
-
-/* unsolicited event for HP jack sensing */
-static void ad1984a_precision_unsol_event(struct hda_codec *codec,
-					 unsigned int res)
-{
-	if ((res >> 26) != AD1884A_HP_EVENT)
-		return;
-	ad1984a_precision_automute(codec);
-}
-
-/* initialize jack-sensing, too */
-static int ad1984a_precision_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1984a_precision_automute(codec);
-	return 0;
-}
-
-
-/*
- * HP Touchsmart
- * port-A (0x11)      - front hp-out
- * port-B (0x14)      - unused
- * port-C (0x15)      - unused
- * port-D (0x12)      - rear line out
- * port-E (0x1c)      - front mic-in
- * port-F (0x16)      - Internal speakers
- * digital-mic (0x17) - Internal mic
- */
-
-static const struct hda_verb ad1984a_touchsmart_verbs[] = {
-	/* DACs; unmute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-	/* Port-A (HP) mixer - route only from analog mixer */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-A pin */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Port-A (HP) pin - always unmuted */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Port-E (int speaker) mixer - route only from analog mixer */
-	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
-	/* Port-E pin */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	/* Port-F (int speaker) mixer - route only from analog mixer */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-F pin */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Analog mixer; mute as default */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* capture sources */
-	/* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* unsolicited event for pin-sense */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
-	/* allow to touch GPIO1 (for mute control) */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
-	/* internal mic - dmic */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* set magic COEFs for dmic */
-	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
-	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-/*	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.name = "Master Playback Switch",
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = ad1884a_mobile_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, 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("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* switch to external mic if plugged */
-static void ad1984a_touchsmart_automic(struct hda_codec *codec)
-{
-	if (snd_hda_jack_detect(codec, 0x1c))
-		snd_hda_codec_write(codec, 0x0c, 0,
-				     AC_VERB_SET_CONNECT_SEL, 0x4);
-	else
-		snd_hda_codec_write(codec, 0x0c, 0,
-				     AC_VERB_SET_CONNECT_SEL, 0x5);
-}
-
-
-/* unsolicited event for HP jack sensing */
-static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
-	unsigned int res)
-{
-	switch (res >> 26) {
-	case AD1884A_HP_EVENT:
-		ad1884a_hp_automute(codec);
-		break;
-	case AD1884A_MIC_EVENT:
-		ad1984a_touchsmart_automic(codec);
-		break;
-	}
-}
-
-/* initialize jack-sensing, too */
-static int ad1984a_touchsmart_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1884a_hp_automute(codec);
-	ad1984a_touchsmart_automic(codec);
-	return 0;
-}
-
-
-/*
- */
-
-enum {
-	AD1884A_AUTO,
-	AD1884A_DESKTOP,
-	AD1884A_LAPTOP,
-	AD1884A_MOBILE,
-	AD1884A_THINKPAD,
-	AD1984A_TOUCHSMART,
-	AD1984A_PRECISION,
-	AD1884A_MODELS
-};
-
-static const char * const ad1884a_models[AD1884A_MODELS] = {
-	[AD1884A_AUTO]		= "auto",
-	[AD1884A_DESKTOP]	= "desktop",
-	[AD1884A_LAPTOP]	= "laptop",
-	[AD1884A_MOBILE]	= "mobile",
-	[AD1884A_THINKPAD]	= "thinkpad",
-	[AD1984A_TOUCHSMART]	= "touchsmart",
-	[AD1984A_PRECISION]	= "precision",
-};
-
-static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
-	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_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
-	SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
-	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_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
-	SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
-	SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
-	{}
-};
-
-static int patch_ad1884a(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int err, board_config;
-
-	board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
-						  ad1884a_models,
-						  ad1884a_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1884A_AUTO;
-	}
-
-	if (board_config == AD1884A_AUTO)
-		return ad1884_parse_auto_config(codec);
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return err;
-	spec = codec->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;
-	spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
-	spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
-	spec->adc_nids = ad1884a_adc_nids;
-	spec->capsrc_nids = ad1884a_capsrc_nids;
-	spec->input_mux = &ad1884a_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = ad1884a_base_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = ad1884a_init_verbs;
-	spec->spdif_route = 0;
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1884a_loopbacks;
-#endif
-	codec->patch_ops = ad198x_patch_ops;
-
-	/* override some parameters */
-	switch (board_config) {
-	case AD1884A_LAPTOP:
-		spec->mixers[0] = ad1884a_laptop_mixers;
-		spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
-		spec->multiout.dig_out_nid = 0;
-		codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
-		codec->patch_ops.init = ad1884a_laptop_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_MOBILE:
-		spec->mixers[0] = ad1884a_mobile_mixers;
-		spec->init_verbs[0] = ad1884a_mobile_verbs;
-		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;
-		spec->init_verbs[spec->num_init_verbs++] =
-			ad1984a_thinkpad_verbs;
-		spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1984a_thinkpad_capture_source;
-		codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
-		codec->patch_ops.init = ad1984a_thinkpad_init;
-		break;
-	case AD1984A_PRECISION:
-		spec->mixers[0] = ad1984a_precision_mixers;
-		spec->init_verbs[spec->num_init_verbs++] =
-			ad1984a_precision_verbs;
-		spec->multiout.dig_out_nid = 0;
-		codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
-		codec->patch_ops.init = ad1984a_precision_init;
-		break;
-	case AD1984A_TOUCHSMART:
-		spec->mixers[0] = ad1984a_touchsmart_mixers;
-		spec->init_verbs[0] = ad1984a_touchsmart_verbs;
-		spec->multiout.dig_out_nid = 0;
-		codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
-		codec->patch_ops.init = ad1984a_touchsmart_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;
-	}
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1884a	ad1884_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-
 /*
  * AD1882 / AD1882A
  *
@@ -4850,299 +1058,7 @@ static int patch_ad1884a(struct hda_codec *codec)
  * port-G - rear clfe-out (6stack)
  */
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static const hda_nid_t ad1882_dac_nids[3] = {
-	0x04, 0x03, 0x05
-};
-
-static const hda_nid_t ad1882_adc_nids[2] = {
-	0x08, 0x09,
-};
-
-static const hda_nid_t ad1882_capsrc_nids[2] = {
-	0x0c, 0x0d,
-};
-
-#define AD1882_SPDIF_OUT	0x02
-
-/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
-static const struct hda_input_mux ad1882_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "Front Mic", 0x1 },
-		{ "Mic", 0x4 },
-		{ "Line", 0x2 },
-		{ "CD", 0x3 },
-		{ "Mix", 0x7 },
-	},
-};
-
-/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
-static const struct hda_input_mux ad1882a_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "Front Mic", 0x1 },
-		{ "Mic", 0x4},
-		{ "Line", 0x2 },
-		{ "Digital Mic", 0x06 },
-		{ "Mix", 0x7 },
-	},
-};
-
-static const struct snd_kcontrol_new ad1882_base_mixers[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = ad198x_mux_enum_info,
-		.get = ad198x_mux_enum_get,
-		.put = ad198x_mux_enum_put,
-	},
-	/* SPDIF controls */
-	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
-		/* identical with ad1983 */
-		.info = ad1983_spdif_route_info,
-		.get = ad1983_spdif_route_get,
-		.put = ad1983_spdif_route_put,
-	},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
-	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),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = ad198x_ch_mode_info,
-		.get = ad198x_ch_mode_get,
-		.put = ad198x_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/* simple auto-mute control for AD1882 3-stack board */
-#define AD1882_HP_EVENT	0x01
-
-static void ad1882_3stack_automute(struct hda_codec *codec)
-{
-	bool mute = snd_hda_jack_detect(codec, 0x11);
-	snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    mute ? 0 : PIN_OUT);
-}
-
-static int ad1882_3stack_automute_init(struct hda_codec *codec)
-{
-	ad198x_init(codec);
-	ad1882_3stack_automute(codec);
-	return 0;
-}
-
-static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	switch (res >> 26) {
-	case AD1882_HP_EVENT:
-		ad1882_3stack_automute(codec);
-		break;
-	}
-}
-
-static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb ad1882_ch2_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{ } /* end */
-};
-
-static const struct hda_verb ad1882_ch4_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{ } /* end */
-};
-
-static const struct hda_verb ad1882_ch6_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{ } /* end */
-};
-
-static const struct hda_channel_mode ad1882_modes[3] = {
-	{ 2, ad1882_ch2_init },
-	{ 4, ad1882_ch4_init },
-	{ 6, ad1882_ch6_init },
-};
-
-/*
- * initialization verbs
- */
-static const struct hda_verb ad1882_init_verbs[] = {
-	/* DACs; mute as default */
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Port-A (HP) mixer */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-A pin */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* HP selector - select DAC2 */
-	{0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* Port-D (Line-out) mixer */
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Port-D pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mono-out mixer */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Mono-out pin */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Port-B (front mic) pin */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
-	/* Port-C (line-in) pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
-	/* Port-C mixer - mute as input */
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Port-E (mic-in) pin */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
-	/* Port-E mixer - mute as input */
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Port-F (surround) */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Port-G (CLFE) */
-	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Analog mixer; mute as default */
-	/* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
-	/* SPDIF output selector */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
-	{ } /* end */
-};
-
-static const struct hda_verb ad1882_3stack_automute_verbs[] = {
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT},
-	{ } /* end */
-};
-
-#ifdef CONFIG_PM
-static const struct hda_amp_list ad1882_loopbacks[] = {
-	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
-	{ 0x20, HDA_INPUT, 1 }, /* Mic */
-	{ 0x20, HDA_INPUT, 4 }, /* Line */
-	{ 0x20, HDA_INPUT, 6 }, /* CD */
-	{ } /* end */
-};
-#endif
-
-/* models */
-enum {
-	AD1882_AUTO,
-	AD1882_3STACK,
-	AD1882_6STACK,
-	AD1882_3STACK_AUTOMUTE,
-	AD1882_MODELS
-};
-
-static const char * const ad1882_models[AD1986A_MODELS] = {
-	[AD1882_AUTO]		= "auto",
-	[AD1882_3STACK]		= "3stack",
-	[AD1882_6STACK]		= "6stack",
-	[AD1882_3STACK_AUTOMUTE] = "3stack-automute",
-};
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
-static int ad1882_parse_auto_config(struct hda_codec *codec)
+static int patch_ad1882(struct hda_codec *codec)
 {
 	struct ad198x_spec *spec;
 	int err;
@@ -5169,110 +1085,20 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
 	return err;
 }
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int patch_ad1882(struct hda_codec *codec)
-{
-	struct ad198x_spec *spec;
-	int err, board_config;
-
-	board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
-						  ad1882_models, NULL);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = AD1882_AUTO;
-	}
-
-	if (board_config == AD1882_AUTO)
-		return ad1882_parse_auto_config(codec);
-
-	err = alloc_ad_spec(codec);
-	if (err < 0)
-		return err;
-	spec = codec->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;
-	spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
-	spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
-	spec->adc_nids = ad1882_adc_nids;
-	spec->capsrc_nids = ad1882_capsrc_nids;
-	if (codec->vendor_id == 0x11d41882)
-		spec->input_mux = &ad1882_capture_source;
-	else
-		spec->input_mux = &ad1882a_capture_source;
-	spec->num_mixers = 2;
-	spec->mixers[0] = ad1882_base_mixers;
-	if (codec->vendor_id == 0x11d41882)
-		spec->mixers[1] = ad1882_loopback_mixers;
-	else
-		spec->mixers[1] = ad1882a_loopback_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = ad1882_init_verbs;
-	spec->spdif_route = 0;
-#ifdef CONFIG_PM
-	spec->loopback.amplist = ad1882_loopbacks;
-#endif
-	spec->vmaster_nid = 0x04;
-
-	codec->patch_ops = ad198x_patch_ops;
-
-	/* override some parameters */
-	switch (board_config) {
-	default:
-	case AD1882_3STACK:
-	case AD1882_3STACK_AUTOMUTE:
-		spec->num_mixers = 3;
-		spec->mixers[2] = ad1882_3stack_mixers;
-		spec->channel_mode = ad1882_modes;
-		spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
-		spec->need_dac_fix = 1;
-		spec->multiout.max_channels = 2;
-		spec->multiout.num_dacs = 1;
-		if (board_config != AD1882_3STACK) {
-			spec->init_verbs[spec->num_init_verbs++] =
-				ad1882_3stack_automute_verbs;
-			codec->patch_ops.unsol_event = ad1882_3stack_unsol_event;
-			codec->patch_ops.init = ad1882_3stack_automute_init;
-		}
-		break;
-	case AD1882_6STACK:
-		spec->num_mixers = 3;
-		spec->mixers[2] = ad1882_6stack_mixers;
-		break;
-	}
-
-	codec->no_trigger_sense = 1;
-	codec->no_sticky_stream = 1;
-
-	return 0;
-}
-#else /* ENABLE_AD_STATIC_QUIRKS */
-#define patch_ad1882	ad1882_parse_auto_config
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 
 /*
  * patch entries
  */
 static const struct hda_codec_preset snd_hda_preset_analog[] = {
-	{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
+	{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884 },
 	{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
-	{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
+	{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884 },
 	{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
-	{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
-	{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
+	{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884 },
+	{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884 },
 	{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
 	{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
-	{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
+	{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1884 },
 	{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
 	{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
 	{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index de00ce1..4edd2d0 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -66,6 +66,8 @@ struct conexant_spec {
 	hda_nid_t eapds[4];
 	bool dynamic_eapd;
 
+	unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
+
 #ifdef ENABLE_CXT_STATIC_QUIRKS
 	const struct snd_kcontrol_new *mixers[5];
 	int num_mixers;
@@ -3200,6 +3202,9 @@ static int cx_auto_init(struct hda_codec *codec)
 	snd_hda_gen_init(codec);
 	if (!spec->dynamic_eapd)
 		cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
+
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
+
 	return 0;
 }
 
@@ -3224,6 +3229,8 @@ enum {
 	CXT_PINCFG_LEMOTE_A1205,
 	CXT_FIXUP_STEREO_DMIC,
 	CXT_FIXUP_INC_MIC_BOOST,
+	CXT_FIXUP_HEADPHONE_MIC_PIN,
+	CXT_FIXUP_HEADPHONE_MIC,
 };
 
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
@@ -3246,6 +3253,59 @@ static void cxt5066_increase_mic_boost(struct hda_codec *codec,
 				  (0 << AC_AMPCAP_MUTE_SHIFT));
 }
 
+static void cxt_update_headset_mode(struct hda_codec *codec)
+{
+	/* The verbs used in this function were tested on a Conexant CX20751/2 codec. */
+	int i;
+	bool mic_mode = false;
+	struct conexant_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+
+	hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
+
+	for (i = 0; i < cfg->num_inputs; i++)
+		if (cfg->inputs[i].pin == mux_pin) {
+			mic_mode = !!cfg->inputs[i].is_headphone_mic;
+			break;
+		}
+
+	if (mic_mode) {
+		snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x7c); /* enable merged mode for analog int-mic */
+		spec->gen.hp_jack_present = false;
+	} else {
+		snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x54); /* disable merged mode for analog int-mic */
+		spec->gen.hp_jack_present = snd_hda_jack_detect(codec, spec->gen.autocfg.hp_pins[0]);
+	}
+
+	snd_hda_gen_update_outputs(codec);
+}
+
+static void cxt_update_headset_mode_hook(struct hda_codec *codec,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	cxt_update_headset_mode(codec);
+}
+
+static void cxt_fixup_headphone_mic(struct hda_codec *codec,
+				    const struct hda_fixup *fix, int action)
+{
+	struct conexant_spec *spec = codec->spec;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC;
+		break;
+	case HDA_FIXUP_ACT_PROBE:
+		spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
+		spec->gen.automute_hook = cxt_update_headset_mode;
+		break;
+	case HDA_FIXUP_ACT_INIT:
+		cxt_update_headset_mode(codec);
+		break;
+	}
+}
+
+
 /* ThinkPad X200 & co with cxt5051 */
 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
 	{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -3302,6 +3362,19 @@ static const struct hda_fixup cxt_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = cxt5066_increase_mic_boost,
 	},
+	[CXT_FIXUP_HEADPHONE_MIC_PIN] = {
+		.type = HDA_FIXUP_PINS,
+		.chained = true,
+		.chain_id = CXT_FIXUP_HEADPHONE_MIC,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x18, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
+			{ }
+		}
+	},
+	[CXT_FIXUP_HEADPHONE_MIC] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = cxt_fixup_headphone_mic,
+	},
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -3311,6 +3384,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
 
 static const struct snd_pci_quirk cxt5066_fixups[] = {
 	SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
+	SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
 	SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
 	SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
@@ -3395,7 +3469,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
 
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
-	err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
+	err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL,
+				       spec->parse_flags);
 	if (err < 0)
 		goto error;
 
@@ -3416,6 +3491,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
 		codec->bus->allow_bus_reset = 1;
 	}
 
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
+
 	return 0;
 
  error:
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 8bd2261..6ac4810 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -282,6 +282,7 @@ static void alc_eapd_shutup(struct hda_codec *codec)
 {
 	alc_auto_setup_eapd(codec, false);
 	msleep(200);
+	snd_hda_shutup_pins(codec);
 }
 
 /* generic EAPD initialization */
@@ -826,7 +827,8 @@ static inline void alc_shutup(struct hda_codec *codec)
 
 	if (spec && spec->shutup)
 		spec->shutup(codec);
-	snd_hda_shutup_pins(codec);
+	else
+		snd_hda_shutup_pins(codec);
 }
 
 #define alc_free	snd_hda_gen_free
@@ -1843,8 +1845,10 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
 				       const struct hda_fixup *fix, int action)
 {
 	struct alc_spec *spec = codec->spec;
-	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->gen.no_primary_hp = 1;
+		spec->gen.no_multi_io = 1;
+	}
 }
 
 static const struct hda_fixup alc882_fixups[] = {
@@ -2573,15 +2577,13 @@ static void alc269_shutup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
-	if (spec->codec_variant != ALC269_TYPE_ALC269VB)
-		return;
-
 	if (spec->codec_variant == ALC269_TYPE_ALC269VB)
 		alc269vb_toggle_power_output(codec, 0);
 	if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
 			(alc_get_coef0(codec) & 0x00ff) == 0x018) {
 		msleep(150);
 	}
+	snd_hda_shutup_pins(codec);
 }
 
 static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
@@ -2712,6 +2714,13 @@ static int alc269_resume(struct hda_codec *codec)
 	hda_call_check_power_status(codec, 0x01);
 	if (spec->has_alc5505_dsp)
 		alc5505_dsp_resume(codec);
+
+	/* clear the power-save mode for ALC283 */
+	if (codec->vendor_id == 0x10ec0283) {
+		alc_write_coef_idx(codec, 0x4, 0xaf01);
+		alc_write_coef_idx(codec, 0x6, 0x2104);
+	}
+
 	return 0;
 }
 #endif /* CONFIG_PM */
@@ -3251,6 +3260,28 @@ static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
 	alc_fixup_headset_mode(codec, fix, action);
 }
 
+/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
+static int find_ext_mic_pin(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+	hda_nid_t nid;
+	unsigned int defcfg;
+	int i;
+
+	for (i = 0; i < cfg->num_inputs; i++) {
+		if (cfg->inputs[i].type != AUTO_PIN_MIC)
+			continue;
+		nid = cfg->inputs[i].pin;
+		defcfg = snd_hda_codec_get_pincfg(codec, nid);
+		if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
+			continue;
+		return nid;
+	}
+
+	return 0;
+}
+
 static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 				    const struct hda_fixup *fix,
 				    int action)
@@ -3258,11 +3289,12 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 	struct alc_spec *spec = codec->spec;
 
 	if (action == HDA_FIXUP_ACT_PROBE) {
-		if (snd_BUG_ON(!spec->gen.am_entry[1].pin ||
-			       !spec->gen.autocfg.hp_pins[0]))
+		int mic_pin = find_ext_mic_pin(codec);
+		int hp_pin = spec->gen.autocfg.hp_pins[0];
+
+		if (snd_BUG_ON(!mic_pin || !hp_pin))
 			return;
-		snd_hda_jack_set_gating_jack(codec, spec->gen.am_entry[1].pin,
-					     spec->gen.autocfg.hp_pins[0]);
+		snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
 	}
 }
 
@@ -3775,6 +3807,30 @@ static void alc269_fill_coef(struct hda_codec *codec)
 	alc_write_coef_idx(codec, 0x4, val | (1<<11));
 }
 
+/* don't clear mic pin; otherwise it results in noise in D3 */
+static void alc283_headset_shutup(struct hda_codec *codec)
+{
+	int i;
+
+	if (codec->bus->shutdown)
+		return;
+
+	for (i = 0; i < codec->init_pins.used; i++) {
+		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+		/* use read here for syncing after issuing each verb */
+		if (pin->nid != 0x19)
+			snd_hda_codec_read(codec, pin->nid, 0,
+					   AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+	}
+
+	alc_write_coef_idx(codec, 0x4, 0x0f01); /* power save */
+	alc_write_coef_idx(codec, 0x6, 0x2100); /* power save */
+	snd_hda_codec_write(codec, 0x19, 0,
+			AC_VERB_SET_PIN_WIDGET_CONTROL,
+			PIN_VREFHIZ);
+	codec->pins_shutup = 1;
+}
+
 /*
  */
 static int patch_alc269(struct hda_codec *codec)
@@ -3789,6 +3845,9 @@ static int patch_alc269(struct hda_codec *codec)
 	spec = codec->spec;
 	spec->gen.shared_mic_vref_pin = 0x18;
 
+	if (codec->vendor_id == 0x10ec0283)
+		spec->shutup = alc283_headset_shutup;
+
 	snd_hda_pick_fixup(codec, alc269_fixup_models,
 		       alc269_fixup_tbl, alc269_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -3862,7 +3921,8 @@ static int patch_alc269(struct hda_codec *codec)
 	codec->patch_ops.suspend = alc269_suspend;
 	codec->patch_ops.resume = alc269_resume;
 #endif
-	spec->shutup = alc269_shutup;
+	if (!spec->shutup)
+		spec->shutup = alc269_shutup;
 
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 6d1924c..fba0cef 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -158,6 +158,7 @@ enum {
 	STAC_D965_VERBS,
 	STAC_DELL_3ST,
 	STAC_DELL_BIOS,
+	STAC_DELL_BIOS_AMIC,
 	STAC_DELL_BIOS_SPDIF,
 	STAC_927X_DELL_DMIC,
 	STAC_927X_VOLKNOB,
@@ -3231,8 +3232,6 @@ static const struct hda_fixup stac927x_fixups[] = {
 	[STAC_DELL_BIOS] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = (const struct hda_pintbl[]) {
-			/* configure the analog microphone on some laptops */
-			{ 0x0c, 0x90a79130 },
 			/* correct the front output jack as a hp out */
 			{ 0x0f, 0x0221101f },
 			/* correct the front input jack as a mic */
@@ -3242,6 +3241,16 @@ static const struct hda_fixup stac927x_fixups[] = {
 		.chained = true,
 		.chain_id = STAC_927X_DELL_DMIC,
 	},
+	[STAC_DELL_BIOS_AMIC] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			/* configure the analog microphone on some laptops */
+			{ 0x0c, 0x90a79130 },
+			{}
+		},
+		.chained = true,
+		.chain_id = STAC_DELL_BIOS,
+	},
 	[STAC_DELL_BIOS_SPDIF] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = (const struct hda_pintbl[]) {
@@ -3270,6 +3279,7 @@ static const struct hda_model_fixup stac927x_models[] = {
 	{ .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
 	{ .id = STAC_DELL_3ST, .name = "dell-3stack" },
 	{ .id = STAC_DELL_BIOS, .name = "dell-bios" },
+	{ .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" },
 	{ .id = STAC_927X_VOLKNOB, .name = "volknob" },
 	{}
 };
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index e2481ba..0bc20ef 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -207,9 +207,9 @@ static void vt1708_stop_hp_work(struct hda_codec *codec)
 		return;
 	if (spec->hp_work_active) {
 		snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
+		codec->jackpoll_interval = 0;
 		cancel_delayed_work_sync(&codec->jackpoll_work);
 		spec->hp_work_active = false;
-		codec->jackpoll_interval = 0;
 	}
 }
 
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index bd50193..ec6335e 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -38,6 +38,97 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+
+/* *************    Register Documentation   *******************************************************
+ *
+ * Work in progress! Documentation is based on the code in this file.
+ *
+ * --------- HDSPM_controlRegister ---------
+ * :7654.3210:7654.3210:7654.3210:7654.3210: bit number per byte
+ * :||||.||||:||||.||||:||||.||||:||||.||||:
+ * :3322.2222:2222.1111:1111.1100:0000.0000: bit number
+ * :1098.7654:3210.9876:5432.1098:7654.3210: 0..31
+ * :||||.||||:||||.||||:||||.||||:||||.||||:
+ * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
+ * :    .    :    .    :    .    :  x .    :  HDSPM_AudioInterruptEnable \_ setting both bits
+ * :    .    :    .    :    .    :    .   x:  HDSPM_Start                /  enables audio IO
+ * :    .    :    .    :    .    :   x.    :  HDSPM_ClockModeMaster - 1: Master, 0: Slave
+ * :    .    :    .    :    .    :    .210 :  HDSPM_LatencyMask - 3 Bit value for latency
+ * :    .    :    .    :    .    :    .    :      0:64, 1:128, 2:256, 3:512,
+ * :    .    :    .    :    .    :    .    :      4:1024, 5:2048, 6:4096, 7:8192
+ * :x   .    :    .    :    .   x:xx  .    :  HDSPM_FrequencyMask
+ * :    .    :    .    :    .    :10  .    :  HDSPM_Frequency1|HDSPM_Frequency0: 1=32K,2=44.1K,3=48K,0=??
+ * :    .    :    .    :    .   x:    .    :  <MADI> HDSPM_DoubleSpeed
+ * :x   .    :    .    :    .    :    .    :  <MADI> HDSPM_QuadSpeed
+ * :    .  3 :    .  10:  2 .    :    .    :  HDSPM_SyncRefMask :
+ * :    .    :    .   x:    .    :    .    :  HDSPM_SyncRef0
+ * :    .    :    .  x :    .    :    .    :  HDSPM_SyncRef1
+ * :    .    :    .    :  x .    :    .    :  <AES32> HDSPM_SyncRef2
+ * :    .  x :    .    :    .    :    .    :  <AES32> HDSPM_SyncRef3
+ * :    .    :    .  10:    .    :    .    :  <MADI> sync ref: 0:WC, 1:Madi, 2:TCO, 3:SyncIn
+ * :    .  3 :    .  10:  2 .    :    .    :  <AES32>  0:WC, 1:AES1 ... 8:AES8, 9: TCO, 10:SyncIn?
+ * :    .  x :    .    :    .    :    .    :  <MADIe> HDSPe_FLOAT_FORMAT
+ * :    .    :    .    : x  .    :    .    :  <MADI> HDSPM_InputSelect0 : 0=optical,1=coax
+ * :    .    :    .    :x   .    :    .    :  <MADI> HDSPM_InputSelect1
+ * :    .    :    .x   :    .    :    .    :  <MADI> HDSPM_clr_tms
+ * :    .    :    .    :    . x  :    .    :  <MADI> HDSPM_TX_64ch
+ * :    .    :    .    :    . x  :    .    :  <AES32> HDSPM_Emphasis
+ * :    .    :    .    :    .x   :    .    :  <MADI> HDSPM_AutoInp
+ * :    .    :    . x  :    .    :    .    :  <MADI> HDSPM_SMUX
+ * :    .    :    .x   :    .    :    .    :  <MADI> HDSPM_clr_tms
+ * :    .    :   x.    :    .    :    .    :  <MADI> HDSPM_taxi_reset
+ * :    .   x:    .    :    .    :    .    :  <MADI> HDSPM_LineOut
+ * :    .   x:    .    :    .    :    .    :  <AES32> ??????????????????
+ * :    .    :   x.    :    .    :    .    :  <AES32> HDSPM_WCK48
+ * :    .    :    .    :    .x   :    .    :  <AES32> HDSPM_Dolby
+ * :    .    : x  .    :    .    :    .    :  HDSPM_Midi0InterruptEnable
+ * :    .    :x   .    :    .    :    .    :  HDSPM_Midi1InterruptEnable
+ * :    .    :  x .    :    .    :    .    :  HDSPM_Midi2InterruptEnable
+ * :    . x  :    .    :    .    :    .    :  <MADI> HDSPM_Midi3InterruptEnable
+ * :    . x  :    .    :    .    :    .    :  <AES32> HDSPM_DS_DoubleWire
+ * :    .x   :    .    :    .    :    .    :  <AES32> HDSPM_QS_DoubleWire
+ * :   x.    :    .    :    .    :    .    :  <AES32> HDSPM_QS_QuadWire
+ * :    .    :    .    :    .  x :    .    :  <AES32> HDSPM_Professional
+ * : x  .    :    .    :    .    :    .    :  HDSPM_wclk_sel
+ * :    .    :    .    :    .    :    .    :
+ * :7654.3210:7654.3210:7654.3210:7654.3210: bit number per byte
+ * :||||.||||:||||.||||:||||.||||:||||.||||:
+ * :3322.2222:2222.1111:1111.1100:0000.0000: bit number
+ * :1098.7654:3210.9876:5432.1098:7654.3210: 0..31
+ * :||||.||||:||||.||||:||||.||||:||||.||||:
+ * :8421.8421:8421.8421:8421.8421:8421.8421:hex digit
+ *
+ *
+ *
+ * AIO / RayDAT only
+ *
+ * ------------ HDSPM_WR_SETTINGS ----------
+ * :3322.2222:2222.1111:1111.1100:0000.0000: bit number per byte
+ * :1098.7654:3210.9876:5432.1098:7654.3210:
+ * :||||.||||:||||.||||:||||.||||:||||.||||: bit number
+ * :7654.3210:7654.3210:7654.3210:7654.3210: 0..31
+ * :||||.||||:||||.||||:||||.||||:||||.||||:
+ * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
+ * :    .    :    .    :    .    :    .   x: HDSPM_c0Master 1: Master, 0: Slave
+ * :    .    :    .    :    .    :    .  x : HDSPM_c0_SyncRef0
+ * :    .    :    .    :    .    :    . x  : HDSPM_c0_SyncRef1
+ * :    .    :    .    :    .    :    .x   : HDSPM_c0_SyncRef2
+ * :    .    :    .    :    .    :   x.    : HDSPM_c0_SyncRef3
+ * :    .    :    .    :    .    :   3.210 : HDSPM_c0_SyncRefMask:
+ * :    .    :    .    :    .    :    .    :  RayDat: 0:WC, 1:AES, 2:SPDIF, 3..6: ADAT1..4,
+ * :    .    :    .    :    .    :    .    :          9:TCO, 10:SyncIn
+ * :    .    :    .    :    .    :    .    :  AIO: 0:WC, 1:AES, 2: SPDIF, 3: ATAT,
+ * :    .    :    .    :    .    :    .    :          9:TCO, 10:SyncIn
+ * :    .    :    .    :    .    :    .    :
+ * :    .    :    .    :    .    :    .    :
+ * :3322.2222:2222.1111:1111.1100:0000.0000: bit number per byte
+ * :1098.7654:3210.9876:5432.1098:7654.3210:
+ * :||||.||||:||||.||||:||||.||||:||||.||||: bit number
+ * :7654.3210:7654.3210:7654.3210:7654.3210: 0..31
+ * :||||.||||:||||.||||:||||.||||:||||.||||:
+ * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
+ *
+ */
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -95,7 +186,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_controlRegister	     64
 #define HDSPM_interruptConfirmation  96
 #define HDSPM_control2Reg	     256  /* not in specs ???????? */
-#define HDSPM_freqReg                256  /* for AES32 */
+#define HDSPM_freqReg                256  /* for setting arbitrary clock values (DDS feature) */
 #define HDSPM_midiDataOut0	     352  /* just believe in old code */
 #define HDSPM_midiDataOut1	     356
 #define HDSPM_eeprom_wr		     384  /* for AES32 */
@@ -258,6 +349,25 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 
 #define HDSPM_wclk_sel (1<<30)
 
+/* additional control register bits for AIO*/
+#define HDSPM_c0_Wck48				0x20 /* also RayDAT */
+#define HDSPM_c0_Input0				0x1000
+#define HDSPM_c0_Input1				0x2000
+#define HDSPM_c0_Spdif_Opt			0x4000
+#define HDSPM_c0_Pro				0x8000
+#define HDSPM_c0_clr_tms			0x10000
+#define HDSPM_c0_AEB1				0x20000
+#define HDSPM_c0_AEB2				0x40000
+#define HDSPM_c0_LineOut			0x80000
+#define HDSPM_c0_AD_GAIN0			0x100000
+#define HDSPM_c0_AD_GAIN1			0x200000
+#define HDSPM_c0_DA_GAIN0			0x400000
+#define HDSPM_c0_DA_GAIN1			0x800000
+#define HDSPM_c0_PH_GAIN0			0x1000000
+#define HDSPM_c0_PH_GAIN1			0x2000000
+#define HDSPM_c0_Sym6db				0x4000000
+
+
 /* --- bit helper defines */
 #define HDSPM_LatencyMask    (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
 #define HDSPM_FrequencyMask  (HDSPM_Frequency0|HDSPM_Frequency1|\
@@ -341,11 +451,11 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_madiLock           (1<<3)	/* MADI Locked =1, no=0 */
 #define HDSPM_madiSync          (1<<18) /* MADI is in sync */
 
-#define HDSPM_tcoLock    0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
-#define HDSPM_tcoSync    0x10000000 /* Optional TCO sync status */
+#define HDSPM_tcoLockMadi    0x00000020 /* Optional TCO locked status for HDSPe MADI*/
+#define HDSPM_tcoSync    0x10000000 /* Optional TCO sync status for HDSPe MADI and AES32!*/
 
-#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
-#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
+#define HDSPM_syncInLock 0x00010000 /* Sync In lock status for HDSPe MADI! */
+#define HDSPM_syncInSync 0x00020000 /* Sync In sync status for HDSPe MADI! */
 
 #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
 			/* since 64byte accurate, last 6 bits are not used */
@@ -363,7 +473,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 					 * Interrupt
 					 */
 #define HDSPM_tco_detect         0x08000000
-#define HDSPM_tco_lock	         0x20000000
+#define HDSPM_tcoLockAes         0x20000000 /* Optional TCO locked status for HDSPe AES */
 
 #define HDSPM_s2_tco_detect      0x00000040
 #define HDSPM_s2_AEBO_D          0x00000080
@@ -461,7 +571,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
 #define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
 #define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
-#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
+#define HDSPM_AES32_AUTOSYNC_FROM_TCO 9
+#define HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN 10
+#define HDSPM_AES32_AUTOSYNC_FROM_NONE 11
 
 /*  status2 */
 /* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
@@ -537,36 +649,39 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 /* names for speed modes */
 static char *hdspm_speed_names[] = { "single", "double", "quad" };
 
-static char *texts_autosync_aes_tco[] = { "Word Clock",
+static const char *const texts_autosync_aes_tco[] = { "Word Clock",
 					  "AES1", "AES2", "AES3", "AES4",
 					  "AES5", "AES6", "AES7", "AES8",
-					  "TCO" };
-static char *texts_autosync_aes[] = { "Word Clock",
+					  "TCO", "Sync In"
+};
+static const char *const texts_autosync_aes[] = { "Word Clock",
 				      "AES1", "AES2", "AES3", "AES4",
-				      "AES5", "AES6", "AES7", "AES8" };
-static char *texts_autosync_madi_tco[] = { "Word Clock",
+				      "AES5", "AES6", "AES7", "AES8",
+				      "Sync In"
+};
+static const char *const texts_autosync_madi_tco[] = { "Word Clock",
 					   "MADI", "TCO", "Sync In" };
-static char *texts_autosync_madi[] = { "Word Clock",
+static const char *const texts_autosync_madi[] = { "Word Clock",
 				       "MADI", "Sync In" };
 
-static char *texts_autosync_raydat_tco[] = {
+static const char *const texts_autosync_raydat_tco[] = {
 	"Word Clock",
 	"ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
 	"AES", "SPDIF", "TCO", "Sync In"
 };
-static char *texts_autosync_raydat[] = {
+static const char *const texts_autosync_raydat[] = {
 	"Word Clock",
 	"ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
 	"AES", "SPDIF", "Sync In"
 };
-static char *texts_autosync_aio_tco[] = {
+static const char *const texts_autosync_aio_tco[] = {
 	"Word Clock",
 	"ADAT", "AES", "SPDIF", "TCO", "Sync In"
 };
-static char *texts_autosync_aio[] = { "Word Clock",
+static const char *const texts_autosync_aio[] = { "Word Clock",
 				      "ADAT", "AES", "SPDIF", "Sync In" };
 
-static char *texts_freq[] = {
+static const char *const texts_freq[] = {
 	"No Lock",
 	"32 kHz",
 	"44.1 kHz",
@@ -629,7 +744,8 @@ static char *texts_ports_aio_in_ss[] = {
 	"AES.L", "AES.R",
 	"SPDIF.L", "SPDIF.R",
 	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
-	"ADAT.7", "ADAT.8"
+	"ADAT.7", "ADAT.8",
+	"AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
 static char *texts_ports_aio_out_ss[] = {
@@ -638,14 +754,16 @@ static char *texts_ports_aio_out_ss[] = {
 	"SPDIF.L", "SPDIF.R",
 	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
 	"ADAT.7", "ADAT.8",
-	"Phone.L", "Phone.R"
+	"Phone.L", "Phone.R",
+	"AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
 static char *texts_ports_aio_in_ds[] = {
 	"Analogue.L", "Analogue.R",
 	"AES.L", "AES.R",
 	"SPDIF.L", "SPDIF.R",
-	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
+	"AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
 static char *texts_ports_aio_out_ds[] = {
@@ -653,14 +771,16 @@ static char *texts_ports_aio_out_ds[] = {
 	"AES.L", "AES.R",
 	"SPDIF.L", "SPDIF.R",
 	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
-	"Phone.L", "Phone.R"
+	"Phone.L", "Phone.R",
+	"AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
 static char *texts_ports_aio_in_qs[] = {
 	"Analogue.L", "Analogue.R",
 	"AES.L", "AES.R",
 	"SPDIF.L", "SPDIF.R",
-	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
+	"AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
 static char *texts_ports_aio_out_qs[] = {
@@ -668,7 +788,8 @@ static char *texts_ports_aio_out_qs[] = {
 	"AES.L", "AES.R",
 	"SPDIF.L", "SPDIF.R",
 	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
-	"Phone.L", "Phone.R"
+	"Phone.L", "Phone.R",
+	"AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
 static char *texts_ports_aes32[] = {
@@ -745,8 +866,8 @@ static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
 	8, 9,			/* aes in, */
 	10, 11,			/* spdif in */
 	12, 13, 14, 15, 16, 17, 18, 19,	/* ADAT in */
-	-1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
+	2, 3, 4, 5,		/* AEB */
+	-1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -760,7 +881,8 @@ static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
 	10, 11,			/* spdif out */
 	12, 13, 14, 15, 16, 17, 18, 19,	/* ADAT out */
 	6, 7,			/* phone out */
-	-1, -1, -1, -1, -1, -1, -1, -1,
+	2, 3, 4, 5,		/* AEB */
+	-1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -773,7 +895,8 @@ static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
 	8, 9,			/* aes in */
 	10, 11,			/* spdif in */
 	12, 14, 16, 18,		/* adat in */
-	-1, -1, -1, -1, -1, -1,
+	2, 3, 4, 5,		/* AEB */
+	-1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -788,7 +911,7 @@ static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
 	10, 11,			/* spdif out */
 	12, 14, 16, 18,		/* adat out */
 	6, 7,			/* phone out */
-	-1, -1, -1, -1,
+	2, 3, 4, 5,		/* AEB */
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -802,7 +925,8 @@ static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
 	8, 9,			/* aes in */
 	10, 11,			/* spdif in */
 	12, 16,			/* adat in */
-	-1, -1, -1, -1, -1, -1, -1, -1,
+	2, 3, 4, 5,		/* AEB */
+	-1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -817,7 +941,8 @@ static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
 	10, 11,			/* spdif out */
 	12, 16,			/* adat out */
 	6, 7,			/* phone out */
-	-1, -1, -1, -1, -1, -1,
+	2, 3, 4, 5,		/* AEB */
+	-1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -856,11 +981,11 @@ struct hdspm_midi {
 };
 
 struct hdspm_tco {
-	int input;
-	int framerate;
-	int wordclock;
-	int samplerate;
-	int pull;
+	int input; /* 0: LTC, 1:Video, 2: WC*/
+	int framerate; /* 0=24, 1=25, 2=29.97, 3=29.97d, 4=30, 5=30d */
+	int wordclock; /* 0=1:1, 1=44.1->48, 2=48->44.1 */
+	int samplerate; /* 0=44.1, 1=48, 2= freq from app */
+	int pull; /*   0=0, 1=+0.1%, 2=-0.1%, 3=+4%, 4=-4%*/
 	int term; /* 0 = off, 1 = on */
 };
 
@@ -879,7 +1004,7 @@ struct hdspm {
 
 	u32 control_register;	/* cached value */
 	u32 control2_register;	/* cached value */
-	u32 settings_register;
+	u32 settings_register;  /* cached value for AIO / RayDat (sync reference, master/slave) */
 
 	struct hdspm_midi midi[4];
 	struct tasklet_struct midi_tasklet;
@@ -941,7 +1066,7 @@ struct hdspm {
 
 	struct hdspm_tco *tco;  /* NULL if no TCO detected */
 
-	char **texts_autosync;
+	const char *const *texts_autosync;
 	int texts_autosync_items;
 
 	cycles_t last_interrupt;
@@ -976,12 +1101,24 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
 static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
 static int hdspm_autosync_ref(struct hdspm *hdspm);
+static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out);
 static int snd_hdspm_set_defaults(struct hdspm *hdspm);
 static int hdspm_system_clock_mode(struct hdspm *hdspm);
 static void hdspm_set_sgbuf(struct hdspm *hdspm,
 			    struct snd_pcm_substream *substream,
 			     unsigned int reg, int channels);
 
+static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx);
+static int hdspm_wc_sync_check(struct hdspm *hdspm);
+static int hdspm_tco_sync_check(struct hdspm *hdspm);
+static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
+
+static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index);
+static int hdspm_get_tco_sample_rate(struct hdspm *hdspm);
+static int hdspm_get_wc_sample_rate(struct hdspm *hdspm);
+
+
+
 static inline int HDSPM_bit2freq(int n)
 {
 	static const int bit2freq_tab[] = {
@@ -992,6 +1129,12 @@ static inline int HDSPM_bit2freq(int n)
 	return bit2freq_tab[n];
 }
 
+static bool hdspm_is_raydat_or_aio(struct hdspm *hdspm)
+{
+	return ((AIO == hdspm->io_type) || (RayDAT == hdspm->io_type));
+}
+
+
 /* Write/read to/from HDSPM with Adresses in Bytes
    not words but only 32Bit writes are allowed */
 
@@ -1107,14 +1250,11 @@ static int hdspm_rate_multiplier(struct hdspm *hdspm, int rate)
 		else if (hdspm->control_register &
 				HDSPM_DoubleSpeed)
 			return rate * 2;
-	};
+	}
 	return rate;
 }
 
-static int hdspm_tco_sync_check(struct hdspm *hdspm);
-static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
-
-/* check for external sample rate */
+/* check for external sample rate, returns the sample rate in Hz*/
 static int hdspm_external_sample_rate(struct hdspm *hdspm)
 {
 	unsigned int status, status2, timecode;
@@ -1127,17 +1267,36 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 		timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
 
 		syncref = hdspm_autosync_ref(hdspm);
+		switch (syncref) {
+		case HDSPM_AES32_AUTOSYNC_FROM_WORD:
+		/* Check WC sync and get sample rate */
+			if (hdspm_wc_sync_check(hdspm))
+				return HDSPM_bit2freq(hdspm_get_wc_sample_rate(hdspm));
+			break;
 
-		if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
-				status & HDSPM_AES32_wcLock)
-			return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
+		case HDSPM_AES32_AUTOSYNC_FROM_AES1:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES2:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES3:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES4:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES5:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES6:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES7:
+		case HDSPM_AES32_AUTOSYNC_FROM_AES8:
+		/* Check AES sync and get sample rate */
+			if (hdspm_aes_sync_check(hdspm, syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))
+				return HDSPM_bit2freq(hdspm_get_aes_sample_rate(hdspm,
+							syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1));
+			break;
 
-		if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
-				syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
-				status2 & (HDSPM_LockAES >>
-				(syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
-			return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
-		return 0;
+
+		case HDSPM_AES32_AUTOSYNC_FROM_TCO:
+		/* Check TCO sync and get sample rate */
+			if (hdspm_tco_sync_check(hdspm))
+				return HDSPM_bit2freq(hdspm_get_tco_sample_rate(hdspm));
+			break;
+		default:
+			return 0;
+		} /* end switch(syncref) */
 		break;
 
 	case MADIface:
@@ -2129,6 +2288,9 @@ static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
 		status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
 		return (status >> 16) & 0xF;
 		break;
+	case AES32:
+		status = hdspm_read(hdspm, HDSPM_statusRegister);
+		return (status >> HDSPM_AES32_wcFreq_bit) & 0xF;
 	default:
 		break;
 	}
@@ -2152,6 +2314,9 @@ static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
 			status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
 			return (status >> 20) & 0xF;
 			break;
+		case AES32:
+			status = hdspm_read(hdspm, HDSPM_statusRegister);
+			return (status >> 1) & 0xF;
 		default:
 			break;
 		}
@@ -2183,6 +2348,23 @@ static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
 	return 0;
 }
 
+/**
+ * Returns the AES sample rate class for the given card.
+ **/
+static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index)
+{
+	int timecode;
+
+	switch (hdspm->io_type) {
+	case AES32:
+		timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
+		return (timecode >> (4*index)) & 0xF;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
 
 /**
  * Returns the sample rate class for input source <idx> for
@@ -2196,15 +2378,23 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
 }
 
 #define ENUMERATED_CTL_INFO(info, texts) \
-{ \
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \
-	uinfo->count = 1; \
-	uinfo->value.enumerated.items = ARRAY_SIZE(texts); \
-	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) \
-		uinfo->value.enumerated.item =	uinfo->value.enumerated.items - 1; \
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); \
-}
+	snd_ctl_enum_info(info, 1, ARRAY_SIZE(texts), texts)
+
 
+/* Helper function to query the external sample rate and return the
+ * corresponding enum to be returned to userspace.
+ */
+static int hdspm_external_rate_to_enum(struct hdspm *hdspm)
+{
+	int rate = hdspm_external_sample_rate(hdspm);
+	int i, selected_rate = 0;
+	for (i = 1; i < 10; i++)
+		if (HDSPM_bit2freq(i) == rate) {
+			selected_rate = i;
+			break;
+		}
+	return selected_rate;
+}
 
 
 #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
@@ -2270,7 +2460,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
 		default:
 			ucontrol->value.enumerated.item[0] =
 				hdspm_get_s1_sample_rate(hdspm,
-						ucontrol->id.index-1);
+						kcontrol->private_value-1);
 		}
 		break;
 
@@ -2289,28 +2479,24 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
 			ucontrol->value.enumerated.item[0] =
 				hdspm_get_sync_in_sample_rate(hdspm);
 			break;
+		case 11: /* External Rate */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_external_rate_to_enum(hdspm);
+			break;
 		default: /* AES1 to AES8 */
 			ucontrol->value.enumerated.item[0] =
-				hdspm_get_s1_sample_rate(hdspm,
-						kcontrol->private_value-1);
+				hdspm_get_aes_sample_rate(hdspm,
+						kcontrol->private_value -
+						HDSPM_AES32_AUTOSYNC_FROM_AES1);
 			break;
 		}
 		break;
 
 	case MADI:
 	case MADIface:
-		{
-			int rate = hdspm_external_sample_rate(hdspm);
-			int i, selected_rate = 0;
-			for (i = 1; i < 10; i++)
-				if (HDSPM_bit2freq(i) == rate) {
-					selected_rate = i;
-					break;
-				}
-			ucontrol->value.enumerated.item[0] = selected_rate;
-		}
+		ucontrol->value.enumerated.item[0] =
+			hdspm_external_rate_to_enum(hdspm);
 		break;
-
 	default:
 		break;
 	}
@@ -2359,33 +2545,17 @@ static int hdspm_system_clock_mode(struct hdspm *hdspm)
  **/
 static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
 {
-	switch (hdspm->io_type) {
-	case AIO:
-	case RayDAT:
-		if (0 == mode)
-			hdspm->settings_register |= HDSPM_c0Master;
-		else
-			hdspm->settings_register &= ~HDSPM_c0Master;
-
-		hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
-		break;
-
-	default:
-		if (0 == mode)
-			hdspm->control_register |= HDSPM_ClockModeMaster;
-		else
-			hdspm->control_register &= ~HDSPM_ClockModeMaster;
-
-		hdspm_write(hdspm, HDSPM_controlRegister,
-				hdspm->control_register);
-	}
+	hdspm_set_toggle_setting(hdspm,
+			(hdspm_is_raydat_or_aio(hdspm)) ?
+			HDSPM_c0Master : HDSPM_ClockModeMaster,
+			(0 == mode));
 }
 
 
 static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "Master", "AutoSync" };
+	static const char *const texts[] = { "Master", "AutoSync" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -2809,16 +2979,7 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = hdspm->texts_autosync_items;
-
-	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-		uinfo->value.enumerated.item =
-			uinfo->value.enumerated.items - 1;
-
-	strcpy(uinfo->value.enumerated.name,
-			hdspm->texts_autosync[uinfo->value.enumerated.item]);
+	snd_ctl_enum_info(uinfo, 1, hdspm->texts_autosync_items, hdspm->texts_autosync);
 
 	return 0;
 }
@@ -2873,19 +3034,20 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
 
 static int hdspm_autosync_ref(struct hdspm *hdspm)
 {
+	/* This looks at the autosync selected sync reference */
 	if (AES32 == hdspm->io_type) {
+
 		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
-		unsigned int syncref =
-			(status >> HDSPM_AES32_syncref_bit) & 0xF;
-		if (syncref == 0)
-			return HDSPM_AES32_AUTOSYNC_FROM_WORD;
-		if (syncref <= 8)
+		unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
+		if ((syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD) &&
+				(syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN)) {
 			return syncref;
+		}
 		return HDSPM_AES32_AUTOSYNC_FROM_NONE;
+
 	} else if (MADI == hdspm->io_type) {
-		/* This looks at the autosync selected sync reference */
-		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
 
+		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
 		switch (status2 & HDSPM_SelSyncRefMask) {
 		case HDSPM_SelSyncRef_WORD:
 			return HDSPM_AUTOSYNC_FROM_WORD;
@@ -2898,7 +3060,7 @@ static int hdspm_autosync_ref(struct hdspm *hdspm)
 		case HDSPM_SelSyncRef_NVALID:
 			return HDSPM_AUTOSYNC_FROM_NONE;
 		default:
-			return 0;
+			return HDSPM_AUTOSYNC_FROM_NONE;
 		}
 
 	}
@@ -2912,31 +3074,15 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
 	if (AES32 == hdspm->io_type) {
-		static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
-			"AES4",	"AES5", "AES6", "AES7", "AES8", "None"};
-
-		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-		uinfo->count = 1;
-		uinfo->value.enumerated.items = 10;
-		if (uinfo->value.enumerated.item >=
-		    uinfo->value.enumerated.items)
-			uinfo->value.enumerated.item =
-				uinfo->value.enumerated.items - 1;
-		strcpy(uinfo->value.enumerated.name,
-				texts[uinfo->value.enumerated.item]);
+		static const char *const texts[] = { "WordClock", "AES1", "AES2", "AES3",
+			"AES4",	"AES5", "AES6", "AES7", "AES8", "TCO", "Sync In", "None"};
+
+		ENUMERATED_CTL_INFO(uinfo, texts);
 	} else if (MADI == hdspm->io_type) {
-		static char *texts[] = {"Word Clock", "MADI", "TCO",
+		static const char *const texts[] = {"Word Clock", "MADI", "TCO",
 			"Sync In", "None" };
 
-		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-		uinfo->count = 1;
-		uinfo->value.enumerated.items = 5;
-		if (uinfo->value.enumerated.item >=
-				uinfo->value.enumerated.items)
-			uinfo->value.enumerated.item =
-				uinfo->value.enumerated.items - 1;
-		strcpy(uinfo->value.enumerated.name,
-				texts[uinfo->value.enumerated.item]);
+		ENUMERATED_CTL_INFO(uinfo, texts);
 	}
 	return 0;
 }
@@ -2964,7 +3110,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {"No video", "NTSC", "PAL"};
+	static const char *const texts[] = {"No video", "NTSC", "PAL"};
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3010,7 +3156,7 @@ static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
+	static const char *const texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
 				"30 fps"};
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
@@ -3067,16 +3213,35 @@ static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
 
 static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
 {
-	return (hdspm->control_register & regmask) ? 1 : 0;
+	u32 reg;
+
+	if (hdspm_is_raydat_or_aio(hdspm))
+		reg = hdspm->settings_register;
+	else
+		reg = hdspm->control_register;
+
+	return (reg & regmask) ? 1 : 0;
 }
 
 static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
 {
+	u32 *reg;
+	u32 target_reg;
+
+	if (hdspm_is_raydat_or_aio(hdspm)) {
+		reg = &(hdspm->settings_register);
+		target_reg = HDSPM_WR_SETTINGS;
+	} else {
+		reg = &(hdspm->control_register);
+		target_reg = HDSPM_controlRegister;
+	}
+
 	if (out)
-		hdspm->control_register |= regmask;
+		*reg |= regmask;
 	else
-		hdspm->control_register &= ~regmask;
-	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+		*reg &= ~regmask;
+
+	hdspm_write(hdspm, target_reg, *reg);
 
 	return 0;
 }
@@ -3141,7 +3306,7 @@ static int hdspm_set_input_select(struct hdspm * hdspm, int out)
 static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "optical", "coaxial" };
+	static const char *const texts[] = { "optical", "coaxial" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3203,7 +3368,7 @@ static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
 static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "Single", "Double" };
+	static const char *const texts[] = { "Single", "Double" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3276,7 +3441,7 @@ static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
 static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "Single", "Double", "Quad" };
+	static const char *const texts[] = { "Single", "Double", "Quad" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3313,6 +3478,84 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+#define HDSPM_CONTROL_TRISTATE(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.private_value = xindex, \
+	.info = snd_hdspm_info_tristate, \
+	.get = snd_hdspm_get_tristate, \
+	.put = snd_hdspm_put_tristate \
+}
+
+static int hdspm_tristate(struct hdspm *hdspm, u32 regmask)
+{
+	u32 reg = hdspm->settings_register & (regmask * 3);
+	return reg / regmask;
+}
+
+static int hdspm_set_tristate(struct hdspm *hdspm, int mode, u32 regmask)
+{
+	hdspm->settings_register &= ~(regmask * 3);
+	hdspm->settings_register |= (regmask * mode);
+	hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_tristate(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	u32 regmask = kcontrol->private_value;
+
+	static const char *const texts_spdif[] = { "Optical", "Coaxial", "Internal" };
+	static const char *const texts_levels[] = { "Hi Gain", "+4 dBu", "-10 dBV" };
+
+	switch (regmask) {
+	case HDSPM_c0_Input0:
+		ENUMERATED_CTL_INFO(uinfo, texts_spdif);
+		break;
+	default:
+		ENUMERATED_CTL_INFO(uinfo, texts_levels);
+		break;
+	}
+	return 0;
+}
+
+static int snd_hdspm_get_tristate(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	u32 regmask = kcontrol->private_value;
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_tristate(hdspm, regmask);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_tristate(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	u32 regmask = kcontrol->private_value;
+	int change;
+	int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0];
+	if (val < 0)
+		val = 0;
+	if (val > 2)
+		val = 2;
+
+	spin_lock_irq(&hdspm->lock);
+	change = val != hdspm_tristate(hdspm, regmask);
+	hdspm_set_tristate(hdspm, val, regmask);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
 #define HDSPM_MADI_SPEEDMODE(xname, xindex) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 	.name = xname, \
@@ -3352,7 +3595,7 @@ static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
 static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "Single", "Double", "Quad" };
+	static const char *const texts[] = { "Single", "Double", "Quad" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3587,7 +3830,7 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
+	static const char *const texts[] = { "No Lock", "Lock", "Sync", "N/A" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3595,7 +3838,7 @@ static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "No Lock", "Lock" };
+	static const char *const texts[] = { "No Lock", "Lock" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -3745,9 +3988,18 @@ static int hdspm_tco_sync_check(struct hdspm *hdspm)
 	if (hdspm->tco) {
 		switch (hdspm->io_type) {
 		case MADI:
+			status = hdspm_read(hdspm, HDSPM_statusRegister);
+			if (status & HDSPM_tcoLockMadi) {
+				if (status & HDSPM_tcoSync)
+					return 2;
+				else
+					return 1;
+			}
+			return 0;
+			break;
 		case AES32:
 			status = hdspm_read(hdspm, HDSPM_statusRegister);
-			if (status & HDSPM_tcoLock) {
+			if (status & HDSPM_tcoLockAes) {
 				if (status & HDSPM_tcoSync)
 					return 2;
 				else
@@ -3807,7 +4059,8 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
 		case 5: /* SYNC IN */
 			val = hdspm_sync_in_sync_check(hdspm); break;
 		default:
-			val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
+			val = hdspm_s1_sync_check(hdspm,
+					kcontrol->private_value-1);
 		}
 		break;
 
@@ -3975,7 +4228,8 @@ static void hdspm_tco_write(struct hdspm *hdspm)
 static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "44.1 kHz", "48 kHz" };
+	/* TODO freq from app could be supported here, see tco->samplerate */
+	static const char *const texts[] = { "44.1 kHz", "48 kHz" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -4021,7 +4275,8 @@ static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
+	static const char *const texts[] = { "0", "+ 0.1 %", "- 0.1 %",
+		"+ 4 %", "- 4 %" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -4066,7 +4321,7 @@ static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
 					     struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
+	static const char *const texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -4112,7 +4367,7 @@ static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "24 fps", "25 fps", "29.97fps",
+	static const char *const texts[] = { "24 fps", "25 fps", "29.97fps",
 		"29.97 dfps", "30 fps", "30 dfps" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
@@ -4159,7 +4414,7 @@ static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
 static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "LTC", "Video", "WCK" };
+	static const char *const texts[] = { "LTC", "Video", "WCK" };
 	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
@@ -4284,7 +4539,6 @@ static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
 	HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
 	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
 	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
-	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
 	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
 	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
 	HDSPM_SYNC_CHECK("WC SyncCheck", 0),
@@ -4298,7 +4552,16 @@ static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
 	HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
 	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
 	HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
-	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5),
+	HDSPM_CONTROL_TRISTATE("S/PDIF Input", HDSPM_c0_Input0),
+	HDSPM_TOGGLE_SETTING("S/PDIF Out Optical", HDSPM_c0_Spdif_Opt),
+	HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
+	HDSPM_TOGGLE_SETTING("ADAT internal (AEB/TEB)", HDSPM_c0_AEB1),
+	HDSPM_TOGGLE_SETTING("XLR Breakout Cable", HDSPM_c0_Sym6db),
+	HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48),
+	HDSPM_CONTROL_TRISTATE("Input Level", HDSPM_c0_AD_GAIN0),
+	HDSPM_CONTROL_TRISTATE("Output Level", HDSPM_c0_DA_GAIN0),
+	HDSPM_CONTROL_TRISTATE("Phones Level", HDSPM_c0_PH_GAIN0)
 
 		/*
 		   HDSPM_INPUT_SELECT("Input Select", 0),
@@ -4335,7 +4598,9 @@ static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
 	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
 	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
 	HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
-	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8),
+	HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
+	HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48)
 };
 
 static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
@@ -4345,7 +4610,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
 	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
 	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
 	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
-	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 11),
 	HDSPM_SYNC_CHECK("WC Sync Check", 0),
 	HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
 	HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
@@ -4501,77 +4766,22 @@ static int snd_hdspm_create_controls(struct snd_card *card,
  ------------------------------------------------------------*/
 
 static void
-snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
-			 struct snd_info_buffer *buffer)
+snd_hdspm_proc_read_tco(struct snd_info_entry *entry,
+					struct snd_info_buffer *buffer)
 {
 	struct hdspm *hdspm = entry->private_data;
-	unsigned int status, status2, control, freq;
-
-	char *pref_sync_ref;
-	char *autosync_ref;
-	char *system_clock_mode;
-	char *insel;
-	int x, x2;
-
-	/* TCO stuff */
+	unsigned int status, control;
 	int a, ltc, frames, seconds, minutes, hours;
 	unsigned int period;
 	u64 freq_const = 0;
 	u32 rate;
 
+	snd_iprintf(buffer, "--- TCO ---\n");
+
 	status = hdspm_read(hdspm, HDSPM_statusRegister);
-	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
 	control = hdspm->control_register;
-	freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
 
-	snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
-			hdspm->card_name, hdspm->card->number + 1,
-			hdspm->firmware_rev,
-			(status2 & HDSPM_version0) |
-			(status2 & HDSPM_version1) | (status2 &
-				HDSPM_version2));
-
-	snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
-			(hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
-			hdspm->serial);
 
-	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
-			hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
-
-	snd_iprintf(buffer, "--- System ---\n");
-
-	snd_iprintf(buffer,
-		"IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
-		status & HDSPM_audioIRQPending,
-		(status & HDSPM_midi0IRQPending) ? 1 : 0,
-		(status & HDSPM_midi1IRQPending) ? 1 : 0,
-		hdspm->irq_count);
-	snd_iprintf(buffer,
-		"HW pointer: id = %d, rawptr = %d (%d->%d) "
-		"estimated= %ld (bytes)\n",
-		((status & HDSPM_BufferID) ? 1 : 0),
-		(status & HDSPM_BufferPositionMask),
-		(status & HDSPM_BufferPositionMask) %
-		(2 * (int)hdspm->period_bytes),
-		((status & HDSPM_BufferPositionMask) - 64) %
-		(2 * (int)hdspm->period_bytes),
-		(long) hdspm_hw_pointer(hdspm) * 4);
-
-	snd_iprintf(buffer,
-		"MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
-		hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
-		hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
-		hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
-		hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
-	snd_iprintf(buffer,
-		"MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
-		hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
-		hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
-	snd_iprintf(buffer,
-		"Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
-		"status2=0x%x\n",
-		hdspm->control_register, hdspm->control2_register,
-		status, status2);
 	if (status & HDSPM_tco_detect) {
 		snd_iprintf(buffer, "TCO module detected.\n");
 		a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
@@ -4665,6 +4875,75 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 	} else {
 		snd_iprintf(buffer, "No TCO module detected.\n");
 	}
+}
+
+static void
+snd_hdspm_proc_read_madi(struct snd_info_entry *entry,
+			 struct snd_info_buffer *buffer)
+{
+	struct hdspm *hdspm = entry->private_data;
+	unsigned int status, status2, control, freq;
+
+	char *pref_sync_ref;
+	char *autosync_ref;
+	char *system_clock_mode;
+	char *insel;
+	int x, x2;
+
+	status = hdspm_read(hdspm, HDSPM_statusRegister);
+	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	control = hdspm->control_register;
+	freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
+
+	snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
+			hdspm->card_name, hdspm->card->number + 1,
+			hdspm->firmware_rev,
+			(status2 & HDSPM_version0) |
+			(status2 & HDSPM_version1) | (status2 &
+				HDSPM_version2));
+
+	snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
+			(hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
+			hdspm->serial);
+
+	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
+			hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
+
+	snd_iprintf(buffer, "--- System ---\n");
+
+	snd_iprintf(buffer,
+		"IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
+		status & HDSPM_audioIRQPending,
+		(status & HDSPM_midi0IRQPending) ? 1 : 0,
+		(status & HDSPM_midi1IRQPending) ? 1 : 0,
+		hdspm->irq_count);
+	snd_iprintf(buffer,
+		"HW pointer: id = %d, rawptr = %d (%d->%d) "
+		"estimated= %ld (bytes)\n",
+		((status & HDSPM_BufferID) ? 1 : 0),
+		(status & HDSPM_BufferPositionMask),
+		(status & HDSPM_BufferPositionMask) %
+		(2 * (int)hdspm->period_bytes),
+		((status & HDSPM_BufferPositionMask) - 64) %
+		(2 * (int)hdspm->period_bytes),
+		(long) hdspm_hw_pointer(hdspm) * 4);
+
+	snd_iprintf(buffer,
+		"MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
+		hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
+	snd_iprintf(buffer,
+		"MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
+		hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
+	snd_iprintf(buffer,
+		"Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
+		"status2=0x%x\n",
+		hdspm->control_register, hdspm->control2_register,
+		status, status2);
+
 
 	snd_iprintf(buffer, "--- Settings ---\n");
 
@@ -4768,6 +5047,9 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 		(status & HDSPM_RX_64ch) ? "64 channels" :
 		"56 channels");
 
+	/* call readout function for TCO specific status */
+	snd_hdspm_proc_read_tco(entry, buffer);
+
 	snd_iprintf(buffer, "\n");
 }
 
@@ -4909,11 +5191,18 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 		autosync_ref = "AES7"; break;
 	case HDSPM_AES32_AUTOSYNC_FROM_AES8:
 		autosync_ref = "AES8"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_TCO:
+		autosync_ref = "TCO"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN:
+		autosync_ref = "Sync In"; break;
 	default:
 		autosync_ref = "---"; break;
 	}
 	snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
 
+	/* call readout function for TCO specific status */
+	snd_hdspm_proc_read_tco(entry, buffer);
+
 	snd_iprintf(buffer, "\n");
 }
 
@@ -5097,7 +5386,7 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
 
 	case AES32:
 		hdspm->control_register =
-			HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
+			HDSPM_ClockModeMaster |	/* Master Clock Mode on */
 			hdspm_encode_latency(7) | /* latency max=8192samples */
 			HDSPM_SyncRef0 |	/* AES1 is syncclock */
 			HDSPM_LineOut |	/* Analog output in */
@@ -5123,9 +5412,8 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
 
 	all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
 
-	if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
+	if (hdspm_is_raydat_or_aio(hdspm))
 		hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
-	}
 
 	/* set a default rate so that the channel map is set up. */
 	hdspm_set_rate(hdspm, 48000, 1);
@@ -5371,6 +5659,16 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	   */
 
 
+	/*  For AES cards, the float format bit is the same as the
+	 *  preferred sync reference. Since we don't want to break
+	 *  sync settings, we have to skip the remaining part of this
+	 *  function.
+	 */
+	if (hdspm->io_type == AES32) {
+		return 0;
+	}
+
+
 	/* Switch to native float format if requested */
 	if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
 		if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
@@ -6479,10 +6777,6 @@ static int snd_hdspm_create(struct snd_card *card,
 		break;
 
 	case AIO:
-		if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
-			snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
-		}
-
 		hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
 		hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
 		hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
@@ -6490,6 +6784,20 @@ static int snd_hdspm_create(struct snd_card *card,
 		hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
 		hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
 
+		if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
+			snd_printk(KERN_INFO "HDSPM: AEB input board found\n");
+			hdspm->ss_in_channels += 4;
+			hdspm->ds_in_channels += 4;
+			hdspm->qs_in_channels += 4;
+		}
+
+		if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBO_D)) {
+			snd_printk(KERN_INFO "HDSPM: AEB output board found\n");
+			hdspm->ss_out_channels += 4;
+			hdspm->ds_out_channels += 4;
+			hdspm->qs_out_channels += 4;
+		}
+
 		hdspm->channel_map_out_ss = channel_map_aio_out_ss;
 		hdspm->channel_map_out_ds = channel_map_aio_out_ds;
 		hdspm->channel_map_out_qs = channel_map_aio_out_qs;
@@ -6558,6 +6866,7 @@ static int snd_hdspm_create(struct snd_card *card,
 		break;
 
 	case MADI:
+	case AES32:
 		if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
 			hdspm->midiPorts++;
 			hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
@@ -6565,7 +6874,7 @@ static int snd_hdspm_create(struct snd_card *card,
 			if (NULL != hdspm->tco) {
 				hdspm_tco_write(hdspm);
 			}
-			snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
+			snd_printk(KERN_INFO "HDSPM: MADI/AES TCO module found\n");
 		} else {
 			hdspm->tco = NULL;
 		}
@@ -6580,10 +6889,12 @@ static int snd_hdspm_create(struct snd_card *card,
 	case AES32:
 		if (hdspm->tco) {
 			hdspm->texts_autosync = texts_autosync_aes_tco;
-			hdspm->texts_autosync_items = 10;
+			hdspm->texts_autosync_items =
+				ARRAY_SIZE(texts_autosync_aes_tco);
 		} else {
 			hdspm->texts_autosync = texts_autosync_aes;
-			hdspm->texts_autosync_items = 9;
+			hdspm->texts_autosync_items =
+				ARRAY_SIZE(texts_autosync_aes);
 		}
 		break;
 
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 3fdd87f..e48d38a 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -13,6 +13,7 @@ config SND_ATMEL_SOC_PDC
 config SND_ATMEL_SOC_DMA
 	tristate
 	depends on SND_ATMEL_SOC
+	select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_ATMEL_SOC_SSC
 	tristate
@@ -32,6 +33,26 @@ config SND_AT91_SOC_SAM9G20_WM8731
 	  Say Y if you want to add support for SoC audio on WM8731-based
 	  AT91sam9g20 evaluation board.
 
+config SND_ATMEL_SOC_WM8904
+	tristate "Atmel ASoC driver for boards using WM8904 codec"
+	depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC
+	select SND_ATMEL_SOC_SSC
+	select SND_ATMEL_SOC_DMA
+	select SND_SOC_WM8904
+	help
+	  Say Y if you want to add support for Atmel ASoC driver for boards using
+	  WM8904 codec.
+
+config SND_AT91_SOC_SAM9X5_WM8731
+	tristate "SoC Audio support for WM8731-based at91sam9x5 board"
+	depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5
+	select SND_ATMEL_SOC_SSC
+	select SND_ATMEL_SOC_DMA
+	select SND_SOC_WM8731
+	help
+	  Say Y if you want to add support for audio SoC on an
+	  at91sam9x5 based board that is using WM8731 codec.
+
 config SND_AT91_SOC_AFEB9260
 	tristate "SoC Audio support for AFEB9260 board"
 	depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index 41967cc..5baabc8 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -11,6 +11,10 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
+snd-atmel-soc-wm8904-objs := atmel_wm8904.o
+snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
 
 obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
+obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
+obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
 obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
index d128265..06082e5 100644
--- a/sound/soc/atmel/atmel-pcm-dma.c
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -91,138 +91,52 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
 	}
 }
 
-/*--------------------------------------------------------------------------*\
- * DMAENGINE operations
-\*--------------------------------------------------------------------------*/
-static bool filter(struct dma_chan *chan, void *slave)
-{
-	struct at_dma_slave *sl = slave;
-
-	if (sl->dma_dev == chan->device->dev) {
-		chan->private = sl;
-		return true;
-	} else {
-		return false;
-	}
-}
-
 static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd)
+	struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct atmel_pcm_dma_params *prtd;
 	struct ssc_device *ssc;
-	struct dma_chan *dma_chan;
-	struct dma_slave_config slave_config;
 	int ret;
 
+	prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 	ssc = prtd->ssc;
 
-	ret = snd_hwparams_to_dma_slave_config(substream, params,
-			&slave_config);
+	ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
 	if (ret) {
 		pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
 		return ret;
 	}
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR;
-		slave_config.dst_maxburst = 1;
+		slave_config->dst_addr = ssc->phybase + SSC_THR;
+		slave_config->dst_maxburst = 1;
 	} else {
-		slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR;
-		slave_config.src_maxburst = 1;
-	}
-
-	dma_chan = snd_dmaengine_pcm_get_chan(substream);
-	if (dmaengine_slave_config(dma_chan, &slave_config)) {
-		pr_err("atmel-pcm: failed to configure dma channel\n");
-		ret = -EBUSY;
-		return ret;
-	}
-
-	return 0;
-}
-
-static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct atmel_pcm_dma_params *prtd;
-	struct ssc_device *ssc;
-	struct at_dma_slave *sdata = NULL;
-	int ret;
-
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
-	prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	ssc = prtd->ssc;
-	if (ssc->pdev)
-		sdata = ssc->pdev->dev.platform_data;
-
-	ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
-	if (ret) {
-		pr_err("atmel-pcm: dmaengine pcm open failed\n");
-		return -EINVAL;
-	}
-
-	ret = atmel_pcm_configure_dma(substream, params, prtd);
-	if (ret) {
-		pr_err("atmel-pcm: failed to configure dmai\n");
-		goto err;
+		slave_config->src_addr = ssc->phybase + SSC_RHR;
+		slave_config->src_maxburst = 1;
 	}
 
 	prtd->dma_intr_handler = atmel_pcm_dma_irq;
 
 	return 0;
-err:
-	snd_dmaengine_pcm_close_release_chan(substream);
-	return ret;
 }
 
-static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct atmel_pcm_dma_params *prtd;
-
-	prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-	ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
-	ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
-
-	return 0;
-}
-
-static int atmel_pcm_open(struct snd_pcm_substream *substream)
-{
-	snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware);
-
-	return 0;
-}
-
-static struct snd_pcm_ops atmel_pcm_ops = {
-	.open		= atmel_pcm_open,
-	.close		= snd_dmaengine_pcm_close_release_chan,
-	.ioctl		= snd_pcm_lib_ioctl,
-	.hw_params	= atmel_pcm_hw_params,
-	.prepare	= atmel_pcm_dma_prepare,
-	.trigger	= snd_dmaengine_pcm_trigger,
-	.pointer	= snd_dmaengine_pcm_pointer_no_residue,
-	.mmap		= atmel_pcm_mmap,
-};
-
-static struct snd_soc_platform_driver atmel_soc_platform = {
-	.ops		= &atmel_pcm_ops,
-	.pcm_new	= atmel_pcm_new,
-	.pcm_free	= atmel_pcm_free,
+static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = {
+	.prepare_slave_config = atmel_pcm_configure_dma,
+	.pcm_hardware = &atmel_pcm_dma_hardware,
+	.prealloc_buffer_size = ATMEL_SSC_DMABUF_SIZE,
 };
 
 int atmel_pcm_dma_platform_register(struct device *dev)
 {
-	return snd_soc_register_platform(dev, &atmel_soc_platform);
+	return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config,
+			SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
 }
 EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
 
 void atmel_pcm_dma_platform_unregister(struct device *dev)
 {
-	snd_soc_unregister_platform(dev);
+	snd_dmaengine_pcm_unregister(dev);
 }
 EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
 
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index f3fdfa0..0ecf356 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -73,6 +73,7 @@ static struct atmel_ssc_mask ssc_tx_mask = {
 	.ssc_disable	= SSC_BIT(CR_TXDIS),
 	.ssc_endx	= SSC_BIT(SR_ENDTX),
 	.ssc_endbuf	= SSC_BIT(SR_TXBUFE),
+	.ssc_error	= SSC_BIT(SR_OVRUN),
 	.pdc_enable	= ATMEL_PDC_TXTEN,
 	.pdc_disable	= ATMEL_PDC_TXTDIS,
 };
@@ -82,6 +83,7 @@ static struct atmel_ssc_mask ssc_rx_mask = {
 	.ssc_disable	= SSC_BIT(CR_RXDIS),
 	.ssc_endx	= SSC_BIT(SR_ENDRX),
 	.ssc_endbuf	= SSC_BIT(SR_RXBUFF),
+	.ssc_error	= SSC_BIT(SR_OVRUN),
 	.pdc_enable	= ATMEL_PDC_RXTEN,
 	.pdc_disable	= ATMEL_PDC_RXTDIS,
 };
@@ -196,15 +198,27 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
 			     struct snd_soc_dai *dai)
 {
 	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
-	int dir_mask;
+	struct atmel_pcm_dma_params *dma_params;
+	int dir, dir_mask;
 
 	pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
 		ssc_readl(ssc_p->ssc->regs, SR));
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dir = 0;
 		dir_mask = SSC_DIR_MASK_PLAYBACK;
-	else
+	} else {
+		dir = 1;
 		dir_mask = SSC_DIR_MASK_CAPTURE;
+	}
+
+	dma_params = &ssc_dma_params[dai->id][dir];
+	dma_params->ssc = ssc_p->ssc;
+	dma_params->substream = substream;
+
+	ssc_p->dma_params[dir] = dma_params;
+
+	snd_soc_dai_set_dma_data(dai, substream, dma_params);
 
 	spin_lock_irq(&ssc_p->lock);
 	if (ssc_p->dir_mask & dir_mask) {
@@ -325,7 +339,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params,
 	struct snd_soc_dai *dai)
 {
-	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
 	int id = dai->id;
 	struct atmel_ssc_info *ssc_p = &ssc_info[id];
 	struct atmel_pcm_dma_params *dma_params;
@@ -344,19 +357,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	else
 		dir = 1;
 
-	dma_params = &ssc_dma_params[id][dir];
-	dma_params->ssc = ssc_p->ssc;
-	dma_params->substream = substream;
-
-	ssc_p->dma_params[dir] = dma_params;
-
-	/*
-	 * The snd_soc_pcm_stream->dma_data field is only used to communicate
-	 * the appropriate DMA parameters to the pcm driver hw_params()
-	 * function.  It should not be used for other purposes
-	 * as it is common to all substreams.
-	 */
-	snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);
+	dma_params = ssc_p->dma_params[dir];
 
 	channels = params_channels(params);
 
@@ -648,6 +649,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 	dma_params = ssc_p->dma_params[dir];
 
 	ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+	ssc_writel(ssc_p->ssc->regs, IER, dma_params->mask->ssc_error);
 
 	pr_debug("%s enabled SSC_SR=0x%08x\n",
 			dir ? "receive" : "transmit",
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
new file mode 100644
index 0000000..7222380
--- /dev/null
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -0,0 +1,254 @@
+/*
+ * atmel_wm8904 - Atmel ASoC driver for boards with WM8904 codec.
+ *
+ * Copyright (C) 2012 Atmel
+ *
+ * Author: Bo Shen <voice.shen@atmel.com>
+ *
+ * GPLv2 or later
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+
+#include <sound/soc.h>
+
+#include "../codecs/wm8904.h"
+#include "atmel_ssc_dai.h"
+
+#define MCLK_RATE 32768
+
+static struct clk *mclk;
+
+static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Mic", NULL),
+	SND_SOC_DAPM_LINE("Line In Jack", NULL),
+};
+
+static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK,
+		32768, params_rate(params) * 256);
+	if (ret < 0) {
+		pr_err("%s - failed to set wm8904 codec PLL.", __func__);
+		return ret;
+	}
+
+	/*
+	 * As here wm8904 use FLL output as its system clock
+	 * so calling set_sysclk won't care freq parameter
+	 * then we pass 0
+	 */
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_FLL,
+			0, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		pr_err("%s -failed to set wm8904 SYSCLK\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops atmel_asoc_wm8904_ops = {
+	.hw_params = atmel_asoc_wm8904_hw_params,
+};
+
+static int atmel_set_bias_level(struct snd_soc_card *card,
+		struct snd_soc_dapm_context *dapm,
+		enum snd_soc_bias_level level)
+{
+	if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+		switch (level) {
+		case SND_SOC_BIAS_PREPARE:
+			clk_prepare_enable(mclk);
+			break;
+		case SND_SOC_BIAS_OFF:
+			clk_disable_unprepare(mclk);
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+};
+
+static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
+	.name = "WM8904",
+	.stream_name = "WM8904 PCM",
+	.codec_dai_name = "wm8904-hifi",
+	.dai_fmt = SND_SOC_DAIFMT_I2S
+		| SND_SOC_DAIFMT_NB_NF
+		| SND_SOC_DAIFMT_CBM_CFM,
+	.ops = &atmel_asoc_wm8904_ops,
+};
+
+static struct snd_soc_card atmel_asoc_wm8904_card = {
+	.name = "atmel_asoc_wm8904",
+	.owner = THIS_MODULE,
+	.set_bias_level = atmel_set_bias_level,
+	.dai_link = &atmel_asoc_wm8904_dailink,
+	.num_links = 1,
+	.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(atmel_asoc_wm8904_dapm_widgets),
+	.fully_routed = true,
+};
+
+static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *codec_np, *cpu_np;
+	struct snd_soc_card *card = &atmel_asoc_wm8904_card;
+	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
+	int ret;
+
+	if (!np) {
+		dev_err(&pdev->dev, "only device tree supported\n");
+		return -EINVAL;
+	}
+
+	ret = snd_soc_of_parse_card_name(card, "atmel,model");
+	if (ret) {
+		dev_err(&pdev->dev, "failed to parse card name\n");
+		return ret;
+	}
+
+	ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing");
+	if (ret) {
+		dev_err(&pdev->dev, "failed to parse audio routing\n");
+		return ret;
+	}
+
+	cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+	if (!cpu_np) {
+		dev_err(&pdev->dev, "failed to get dai and pcm info\n");
+		ret = -EINVAL;
+		return ret;
+	}
+	dailink->cpu_of_node = cpu_np;
+	dailink->platform_of_node = cpu_np;
+	of_node_put(cpu_np);
+
+	codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
+	if (!codec_np) {
+		dev_err(&pdev->dev, "failed to get codec info\n");
+		ret = -EINVAL;
+		return ret;
+	}
+	dailink->codec_of_node = codec_np;
+	of_node_put(codec_np);
+
+	return 0;
+}
+
+static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &atmel_asoc_wm8904_card;
+	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
+	struct clk *clk_src;
+	struct pinctrl *pinctrl;
+	int id, ret;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		dev_err(&pdev->dev, "failed to request pinctrl\n");
+		return PTR_ERR(pinctrl);
+	}
+
+	card->dev = &pdev->dev;
+	ret = atmel_asoc_wm8904_dt_init(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to init dt info\n");
+		return ret;
+	}
+
+	id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
+	ret = atmel_ssc_set_audio(id);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to set SSC %d for audio\n", id);
+		return ret;
+	}
+
+	mclk = clk_get(NULL, "pck0");
+	if (IS_ERR(mclk)) {
+		dev_err(&pdev->dev, "failed to get pck0\n");
+		ret = PTR_ERR(mclk);
+		goto err_set_audio;
+	}
+
+	clk_src = clk_get(NULL, "clk32k");
+	if (IS_ERR(clk_src)) {
+		dev_err(&pdev->dev, "failed to get clk32k\n");
+		ret = PTR_ERR(clk_src);
+		goto err_set_audio;
+	}
+
+	ret = clk_set_parent(mclk, clk_src);
+	clk_put(clk_src);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to set MCLK parent\n");
+		goto err_set_audio;
+	}
+
+	dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
+	clk_set_rate(mclk, MCLK_RATE);
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed\n");
+		goto err_set_audio;
+	}
+
+	return 0;
+
+err_set_audio:
+	atmel_ssc_put_audio(id);
+	return ret;
+}
+
+static int atmel_asoc_wm8904_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
+	int id;
+
+	id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
+
+	snd_soc_unregister_card(card);
+	atmel_ssc_put_audio(id);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_asoc_wm8904_dt_ids[] = {
+	{ .compatible = "atmel,asoc-wm8904", },
+	{ }
+};
+#endif
+
+static struct platform_driver atmel_asoc_wm8904_driver = {
+	.driver = {
+		.name = "atmel-wm8904-audio",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(atmel_asoc_wm8904_dt_ids),
+	},
+	.probe = atmel_asoc_wm8904_probe,
+	.remove = atmel_asoc_wm8904_remove,
+};
+
+module_platform_driver(atmel_asoc_wm8904_driver);
+
+/* Module information */
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("ALSA SoC machine driver for Atmel EK with WM8904 codec");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c
new file mode 100644
index 0000000..992ae38
--- /dev/null
+++ b/sound/soc/atmel/sam9x5_wm8731.c
@@ -0,0 +1,208 @@
+/*
+ * sam9x5_wm8731   --	SoC audio for AT91SAM9X5-based boards
+ *			that are using WM8731 as codec.
+ *
+ *  Copyright (C) 2011 Atmel,
+ *		  Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ *  Copyright (C) 2013 Paratronic,
+ *		  Richard Genoud <richard.genoud@gmail.com>
+ *
+ * Based on sam9g20_wm8731.c by:
+ * Sedji Gaouaou <sedji.gaouaou@atmel.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/of.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+
+#include "../codecs/wm8731.h"
+#include "atmel_ssc_dai.h"
+
+
+#define MCLK_RATE 12288000
+
+#define DRV_NAME "sam9x5-snd-wm8731"
+
+struct sam9x5_drvdata {
+	int ssc_id;
+};
+
+/*
+ * Logic for a wm8731 as connected on a at91sam9x5ek based board.
+ */
+static int sam9x5_wm8731_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct device *dev = rtd->dev;
+	int ret;
+
+	dev_dbg(dev, "ASoC: %s called\n", __func__);
+
+	/* set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
+				     MCLK_RATE, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(dev, "ASoC: Failed to set WM8731 SYSCLK: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Audio paths on at91sam9x5ek board:
+ *
+ *  |A| ------------> |      | ---R----> Headphone Jack
+ *  |T| <----\        |  WM  | ---L--/
+ *  |9| ---> CLK <--> | 8731 | <--R----- Line In Jack
+ *  |1| <------------ |      | <--L--/
+ */
+static const struct snd_soc_dapm_widget sam9x5_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_LINE("Line In Jack", NULL),
+};
+
+static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *codec_np, *cpu_np;
+	struct snd_soc_card *card;
+	struct snd_soc_dai_link *dai;
+	struct sam9x5_drvdata *priv;
+	int ret;
+
+	if (!np) {
+		dev_err(&pdev->dev, "No device node supplied\n");
+		return -EINVAL;
+	}
+
+	card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai || !card || !priv) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	card->dev = &pdev->dev;
+	card->owner = THIS_MODULE;
+	card->dai_link = dai;
+	card->num_links = 1;
+	card->dapm_widgets = sam9x5_dapm_widgets;
+	card->num_dapm_widgets = ARRAY_SIZE(sam9x5_dapm_widgets);
+	dai->name = "WM8731";
+	dai->stream_name = "WM8731 PCM";
+	dai->codec_dai_name = "wm8731-hifi";
+	dai->init = sam9x5_wm8731_init;
+	dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+		| SND_SOC_DAIFMT_CBM_CFM;
+
+	ret = snd_soc_of_parse_card_name(card, "atmel,model");
+	if (ret) {
+		dev_err(&pdev->dev, "atmel,model node missing\n");
+		goto out;
+	}
+
+	ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing");
+	if (ret) {
+		dev_err(&pdev->dev, "atmel,audio-routing node missing\n");
+		goto out;
+	}
+
+	codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
+	if (!codec_np) {
+		dev_err(&pdev->dev, "atmel,audio-codec node missing\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dai->codec_of_node = codec_np;
+
+	cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+	if (!cpu_np) {
+		dev_err(&pdev->dev, "atmel,ssc-controller node missing\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	dai->cpu_of_node = cpu_np;
+	dai->platform_of_node = cpu_np;
+
+	priv->ssc_id = of_alias_get_id(cpu_np, "ssc");
+
+	ret = atmel_ssc_set_audio(priv->ssc_id);
+	if (ret != 0) {
+		dev_err(&pdev->dev,
+			"ASoC: Failed to set SSC %d for audio: %d\n",
+			ret, priv->ssc_id);
+		goto out;
+	}
+
+	of_node_put(codec_np);
+	of_node_put(cpu_np);
+
+	platform_set_drvdata(pdev, card);
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"ASoC: Platform device allocation failed\n");
+		goto out_put_audio;
+	}
+
+	dev_dbg(&pdev->dev, "ASoC: %s ok\n", __func__);
+
+	return ret;
+
+out_put_audio:
+	atmel_ssc_put_audio(priv->ssc_id);
+out:
+	return ret;
+}
+
+static int sam9x5_wm8731_driver_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct sam9x5_drvdata *priv = card->drvdata;
+
+	snd_soc_unregister_card(card);
+	atmel_ssc_put_audio(priv->ssc_id);
+
+	return 0;
+}
+
+static const struct of_device_id sam9x5_wm8731_of_match[] = {
+	{ .compatible = "atmel,sam9x5-wm8731-audio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sam9x5_wm8731_of_match);
+
+static struct platform_driver sam9x5_wm8731_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(sam9x5_wm8731_of_match),
+	},
+	.probe = sam9x5_wm8731_driver_probe,
+	.remove = sam9x5_wm8731_driver_remove,
+};
+module_platform_driver(sam9x5_wm8731_driver);
+
+/* Module information */
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
+MODULE_AUTHOR("Richard Genoud <richard.genoud@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC machine driver for AT91SAM9x5 - WM8731");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index a497a0c..decba87 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -73,12 +73,14 @@ static struct snd_soc_dai_link db1300_ac97_dai = {
 
 static struct snd_soc_card db1300_ac97_machine = {
 	.name		= "DB1300_AC97",
+	.owner		= THIS_MODULE,
 	.dai_link	= &db1300_ac97_dai,
 	.num_links	= 1,
 };
 
 static struct snd_soc_card db1550_ac97_machine = {
 	.name		= "DB1550_AC97",
+	.owner		= THIS_MODULE,
 	.dai_link	= &db1200_ac97_dai,
 	.num_links	= 1,
 };
@@ -145,6 +147,7 @@ static struct snd_soc_dai_link db1300_i2s_dai = {
 
 static struct snd_soc_card db1300_i2s_machine = {
 	.name		= "DB1300_I2S",
+	.owner		= THIS_MODULE,
 	.dai_link	= &db1300_i2s_dai,
 	.num_links	= 1,
 };
@@ -161,6 +164,7 @@ static struct snd_soc_dai_link db1550_i2s_dai = {
 
 static struct snd_soc_card db1550_i2s_machine = {
 	.name		= "DB1550_I2S",
+	.owner		= THIS_MODULE,
 	.dai_link	= &db1550_i2s_dai,
 	.num_links	= 1,
 };
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index a822ab8..986dcec 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -379,9 +379,6 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 	mutex_init(&wd->lock);
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iores)
-		return -ENODEV;
-
 	wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
 	if (IS_ERR(wd->mmio))
 		return PTR_ERR(wd->mmio);
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index 0c3e22d..a680fdc 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -9,7 +9,6 @@
 #ifndef _BF5XX_AC97_H
 #define _BF5XX_AC97_H
 
-extern struct snd_ac97 *ac97;
 /* Frame format in memory, only support stereo currently */
 struct ac97_frame {
 	u16 ac97_tag;		/* slot 0 */
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
index 04491f0..efa75b5 100644
--- a/sound/soc/cirrus/ep93xx-ac97.c
+++ b/sound/soc/cirrus/ep93xx-ac97.c
@@ -363,9 +363,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
 	info->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(info->regs))
 		return PTR_ERR(info->regs);
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 17ad70b..f23f331 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -376,9 +376,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
 	info->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(info->regs))
 		return PTR_ERR(info->regs);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index badb6fb..9a883a5 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
 
 config SND_SOC_ALL_CODECS
 	tristate "Build all ASoC CODEC drivers"
+	depends on COMPILE_TEST
 	select SND_SOC_88PM860X if MFD_88PM860X
 	select SND_SOC_L3
 	select SND_SOC_AB8500_CODEC if ABX500_CORE
@@ -20,6 +21,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_AD73311
 	select SND_SOC_ADAU1373 if I2C
 	select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
+	select SND_SOC_ADAU1701 if I2C
 	select SND_SOC_ADS117X
 	select SND_SOC_AK4104 if SPI_MASTER
 	select SND_SOC_AK4535 if I2C
@@ -54,6 +56,8 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
 	select SND_SOC_HDMI_CODEC
+	select SND_SOC_PCM1681 if I2C
+	select SND_SOC_PCM1792A if SPI_MASTER
 	select SND_SOC_PCM3008
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5640 if I2C
@@ -198,6 +202,9 @@ config SND_SOC_AK4104
 config SND_SOC_AK4535
 	tristate
 
+config SND_SOC_AK4554
+	tristate
+
 config SND_SOC_AK4641
 	tristate
 
@@ -292,6 +299,12 @@ config SND_SOC_MAX9850
 config SND_SOC_HDMI_CODEC
        tristate
 
+config SND_SOC_PCM1681
+       tristate
+
+config SND_SOC_PCM1792A
+       tristate
+
 config SND_SOC_PCM3008
        tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 70fd806..42be727 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -11,6 +11,7 @@ snd-soc-adav80x-objs := adav80x.o
 snd-soc-ads117x-objs := ads117x.o
 snd-soc-ak4104-objs := ak4104.o
 snd-soc-ak4535-objs := ak4535.o
+snd-soc-ak4554-objs := ak4554.o
 snd-soc-ak4641-objs := ak4641.o
 snd-soc-ak4642-objs := ak4642.o
 snd-soc-ak4671-objs := ak4671.o
@@ -42,6 +43,8 @@ snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-hdmi-codec-objs := hdmi.o
+snd-soc-pcm1681-objs := pcm1681.o
+snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
@@ -138,6 +141,7 @@ obj-$(CONFIG_SND_SOC_ADAV80X)  += snd-soc-adav80x.o
 obj-$(CONFIG_SND_SOC_ADS117X)	+= snd-soc-ads117x.o
 obj-$(CONFIG_SND_SOC_AK4104)	+= snd-soc-ak4104.o
 obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
+obj-$(CONFIG_SND_SOC_AK4554)	+= snd-soc-ak4554.o
 obj-$(CONFIG_SND_SOC_AK4641)	+= snd-soc-ak4641.o
 obj-$(CONFIG_SND_SOC_AK4642)	+= snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_AK4671)	+= snd-soc-ak4671.o
@@ -171,6 +175,8 @@ obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
 obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
+obj-$(CONFIG_SND_SOC_PCM1681)	+= snd-soc-pcm1681.o
+obj-$(CONFIG_SND_SOC_PCM1792A)	+= snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 89fcf7d..7257a88 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -96,6 +96,44 @@ SOC_ENUM("Capture Source", ad1980_cap_src),
 SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
 };
 
+static const struct snd_soc_dapm_widget ad1980_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2"),
+SND_SOC_DAPM_INPUT("CD_L"),
+SND_SOC_DAPM_INPUT("CD_R"),
+SND_SOC_DAPM_INPUT("AUX_L"),
+SND_SOC_DAPM_INPUT("AUX_R"),
+SND_SOC_DAPM_INPUT("LINE_IN_L"),
+SND_SOC_DAPM_INPUT("LINE_IN_R"),
+
+SND_SOC_DAPM_OUTPUT("LFE_OUT"),
+SND_SOC_DAPM_OUTPUT("CENTER_OUT"),
+SND_SOC_DAPM_OUTPUT("LINE_OUT_L"),
+SND_SOC_DAPM_OUTPUT("LINE_OUT_R"),
+SND_SOC_DAPM_OUTPUT("MONO_OUT"),
+SND_SOC_DAPM_OUTPUT("HP_OUT_L"),
+SND_SOC_DAPM_OUTPUT("HP_OUT_R"),
+};
+
+static const struct snd_soc_dapm_route ad1980_dapm_routes[] = {
+	{ "Capture", NULL, "MIC1" },
+	{ "Capture", NULL, "MIC2" },
+	{ "Capture", NULL, "CD_L" },
+	{ "Capture", NULL, "CD_R" },
+	{ "Capture", NULL, "AUX_L" },
+	{ "Capture", NULL, "AUX_R" },
+	{ "Capture", NULL, "LINE_IN_L" },
+	{ "Capture", NULL, "LINE_IN_R" },
+
+	{ "LFE_OUT", NULL, "Playback" },
+	{ "CENTER_OUT", NULL, "Playback" },
+	{ "LINE_OUT_L", NULL, "Playback" },
+	{ "LINE_OUT_R", NULL, "Playback" },
+	{ "MONO_OUT", NULL, "Playback" },
+	{ "HP_OUT_L", NULL, "Playback" },
+	{ "HP_OUT_R", NULL, "Playback" },
+};
+
 static unsigned int ac97_read(struct snd_soc_codec *codec,
 	unsigned int reg)
 {
@@ -253,6 +291,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
 	.reg_cache_step = 2,
 	.write = ac97_write,
 	.read = ac97_read,
+
+	.dapm_widgets = ad1980_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets),
+	.dapm_routes = ad1980_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes),
 };
 
 static int ad1980_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index d1124a5..2c10252 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -91,7 +91,7 @@
 #define ADAU1701_OSCIPOW_OPD		0x04
 #define ADAU1701_DACSET_DACINIT		1
 
-#define ADAU1707_CLKDIV_UNSET		(-1UL)
+#define ADAU1707_CLKDIV_UNSET		(-1U)
 
 #define ADAU1701_FIRMWARE "adau1701.bin"
 
@@ -734,7 +734,10 @@ static int adau1701_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adau1701_i2c_id[] = {
+	{ "adau1401", 0 },
+	{ "adau1401a", 0 },
 	{ "adau1701", 0 },
+	{ "adau1702", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 3c839cc..15b012d0 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -868,6 +868,12 @@ static int adav80x_bus_remove(struct device *dev)
 }
 
 #if defined(CONFIG_SPI_MASTER)
+static const struct spi_device_id adav80x_spi_id[] = {
+	{ "adav801", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
+
 static int adav80x_spi_probe(struct spi_device *spi)
 {
 	return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
@@ -885,15 +891,16 @@ static struct spi_driver adav80x_spi_driver = {
 	},
 	.probe		= adav80x_spi_probe,
 	.remove		= adav80x_spi_remove,
+	.id_table	= adav80x_spi_id,
 };
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static const struct i2c_device_id adav80x_id[] = {
+static const struct i2c_device_id adav80x_i2c_id[] = {
 	{ "adav803", 0 },
 	{ }
 };
-MODULE_DEVICE_TABLE(i2c, adav80x_id);
+MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
 
 static int adav80x_i2c_probe(struct i2c_client *client,
 			     const struct i2c_device_id *id)
@@ -913,7 +920,7 @@ static struct i2c_driver adav80x_i2c_driver = {
 	},
 	.probe = adav80x_i2c_probe,
 	.remove = adav80x_i2c_remove,
-	.id_table = adav80x_id,
+	.id_table = adav80x_i2c_id,
 };
 #endif
 
diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c
new file mode 100644
index 0000000..6aed9c4
--- /dev/null
+++ b/sound/soc/codecs/ak4554.c
@@ -0,0 +1,86 @@
+/*
+ * ak4554.c
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <sound/soc.h>
+
+/*
+ * ak4554 is very simple DA/AD converter which has no setting register.
+ *
+ * CAUTION
+ *
+ * ak4554 playback format is SND_SOC_DAIFMT_RIGHT_J,
+ * and,   capture  format is SND_SOC_DAIFMT_LEFT_J
+ * on same bit clock, LR clock.
+ * But, this driver doesn't have snd_soc_dai_ops :: set_fmt
+ *
+ * CPU/Codec DAI image
+ *
+ * CPU-DAI1 (plaback only fmt = RIGHT_J) --+-- ak4554
+ *					   |
+ * CPU-DAI2 (capture only fmt = LEFT_J) ---+
+ */
+
+static struct snd_soc_dai_driver ak4554_dai = {
+	.name = "ak4554-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+	.symmetric_rates = 1,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_ak4554 = {
+};
+
+static int ak4554_soc_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev,
+				      &soc_codec_dev_ak4554,
+				      &ak4554_dai, 1);
+}
+
+static int ak4554_soc_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct of_device_id ak4554_of_match[] = {
+	{ .compatible = "asahi-kasei,ak4554" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ak4554_of_match);
+
+static struct platform_driver ak4554_driver = {
+	.driver = {
+		.name = "ak4554-adc-dac",
+		.owner = THIS_MODULE,
+		.of_match_table = ak4554_of_match,
+	},
+	.probe	= ak4554_soc_probe,
+	.remove	= ak4554_soc_remove,
+};
+module_platform_driver(ak4554_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SoC AK4554 driver");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index de62581..779a0ee 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -19,6 +19,7 @@
 #include <sound/tlv.h>
 
 #include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/gpio.h>
 #include <linux/mfd/arizona/registers.h>
 
 #include "arizona.h"
@@ -223,6 +224,41 @@ int arizona_init_spk(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(arizona_init_spk);
 
+int arizona_init_gpio(struct snd_soc_codec *codec)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int i;
+
+	switch (arizona->type) {
+	case WM5110:
+		snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
+		break;
+	default:
+		break;
+	}
+
+	snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity");
+
+	for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
+		switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
+		case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
+			snd_soc_dapm_enable_pin(&codec->dapm,
+						"DRC1 Signal Activity");
+			break;
+		case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
+			snd_soc_dapm_enable_pin(&codec->dapm,
+						"DRC2 Signal Activity");
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_gpio);
+
 const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
 	"None",
 	"Tone Generator 1",
@@ -517,6 +553,26 @@ const struct soc_enum arizona_ng_hold =
 			4, arizona_ng_hold_text);
 EXPORT_SYMBOL_GPL(arizona_ng_hold);
 
+static const char * const arizona_in_dmic_osr_text[] = {
+	"1.536MHz", "3.072MHz", "6.144MHz",
+};
+
+const struct soc_enum arizona_in_dmic_osr[] = {
+	SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
+			ARRAY_SIZE(arizona_in_dmic_osr_text),
+			arizona_in_dmic_osr_text),
+	SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
+			ARRAY_SIZE(arizona_in_dmic_osr_text),
+			arizona_in_dmic_osr_text),
+	SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
+			ARRAY_SIZE(arizona_in_dmic_osr_text),
+			arizona_in_dmic_osr_text),
+	SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
+			ARRAY_SIZE(arizona_in_dmic_osr_text),
+			arizona_in_dmic_osr_text),
+};
+EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
+
 static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
 {
 	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index b60b08c..b6b6d70 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -198,6 +198,7 @@ extern const struct soc_enum arizona_lhpf3_mode;
 extern const struct soc_enum arizona_lhpf4_mode;
 
 extern const struct soc_enum arizona_ng_hold;
+extern const struct soc_enum arizona_in_dmic_osr[];
 
 extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
 			 struct snd_kcontrol *kcontrol,
@@ -242,6 +243,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
 			   unsigned int Fref, unsigned int Fout);
 
 extern int arizona_init_spk(struct snd_soc_codec *codec);
+extern int arizona_init_gpio(struct snd_soc_codec *codec);
 
 extern int arizona_init_dai(struct arizona_priv *priv, int dai);
 
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 987f728..be2ba1b 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -195,6 +195,8 @@ static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
 
 static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
 
+static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
+
 static const unsigned int limiter_tlv[] = {
 	TLV_DB_RANGE_HEAD(2),
 	0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
@@ -451,7 +453,8 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 	SOC_ENUM("Beep Pitch", beep_pitch_enum),
 	SOC_ENUM("Beep on Time", beep_ontime_enum),
 	SOC_ENUM("Beep off Time", beep_offtime_enum),
-	SOC_SINGLE_TLV("Beep Volume", CS42L52_BEEP_VOL, 0, 0x1f, 0x07, hl_tlv),
+	SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL,
+			0, 0x07, 0x1f, beep_tlv),
 	SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1),
 	SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
 	SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
index 2bcae2b..f0986b9 100644
--- a/sound/soc/codecs/hdmi.c
+++ b/sound/soc/codecs/hdmi.c
@@ -37,6 +37,17 @@ static struct snd_soc_dai_driver hdmi_codec_dai = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
 			SNDRV_PCM_FMTBIT_S24_LE,
 	},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_32000 |
+			SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S24_LE,
+	},
+
 };
 
 static int hdmi_codec_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 9f9f595..0e5743e 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 
 #include <sound/core.h>
@@ -23,12 +24,15 @@
 #include <sound/tlv.h>
 
 struct lm4857 {
-	struct i2c_client *i2c;
+	struct regmap *regmap;
 	uint8_t mode;
 };
 
-static const uint8_t lm4857_default_regs[] = {
-	0x00, 0x00, 0x00, 0x00,
+static const struct reg_default lm4857_default_regs[] = {
+	{ 0x0, 0x00 },
+	{ 0x1, 0x00 },
+	{ 0x2, 0x00 },
+	{ 0x3, 0x00 },
 };
 
 /* The register offsets in the cache array */
@@ -42,39 +46,6 @@ static const uint8_t lm4857_default_regs[] = {
 #define LM4857_WAKEUP 5
 #define LM4857_EPGAIN 4
 
-static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg,
-		unsigned int value)
-{
-	uint8_t data;
-	int ret;
-
-	ret = snd_soc_cache_write(codec, reg, value);
-	if (ret < 0)
-		return ret;
-
-	data = (reg << 6) | value;
-	ret = i2c_master_send(codec->control_data, &data, 1);
-	if (ret != 1) {
-		dev_err(codec->dev, "Failed to write register: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static unsigned int lm4857_read(struct snd_soc_codec *codec,
-		unsigned int reg)
-{
-	unsigned int val;
-	int ret;
-
-	ret = snd_soc_cache_read(codec, reg, &val);
-	if (ret)
-		return -1;
-
-	return val;
-}
-
 static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
@@ -96,7 +67,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
 	lm4857->mode = value;
 
 	if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
-		snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6);
+		regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6);
 
 	return 1;
 }
@@ -108,10 +79,11 @@ static int lm4857_set_bias_level(struct snd_soc_codec *codec,
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6);
+		regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F,
+			lm4857->mode + 6);
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0);
+		regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0);
 		break;
 	default:
 		break;
@@ -171,49 +143,32 @@ static const struct snd_soc_dapm_route lm4857_routes[] = {
 	{"EP", NULL, "IN"},
 };
 
-static int lm4857_probe(struct snd_soc_codec *codec)
-{
-	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret;
-
-	codec->control_data = lm4857->i2c;
-
-	ret = snd_soc_add_codec_controls(codec, lm4857_controls,
-			ARRAY_SIZE(lm4857_controls));
-	if (ret)
-		return ret;
-
-	ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets,
-			ARRAY_SIZE(lm4857_dapm_widgets));
-	if (ret)
-		return ret;
+static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
+	.set_bias_level = lm4857_set_bias_level,
 
-	ret = snd_soc_dapm_add_routes(dapm, lm4857_routes,
-			ARRAY_SIZE(lm4857_routes));
-	if (ret)
-		return ret;
+	.controls = lm4857_controls,
+	.num_controls = ARRAY_SIZE(lm4857_controls),
+	.dapm_widgets = lm4857_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(lm4857_dapm_widgets),
+	.dapm_routes = lm4857_routes,
+	.num_dapm_routes = ARRAY_SIZE(lm4857_routes),
+};
 
-	snd_soc_dapm_new_widgets(dapm);
+static const struct regmap_config lm4857_regmap_config = {
+	.val_bits = 6,
+	.reg_bits = 2,
 
-	return 0;
-}
+	.max_register = LM4857_CTRL,
 
-static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
-	.write = lm4857_write,
-	.read = lm4857_read,
-	.probe = lm4857_probe,
-	.reg_cache_size = ARRAY_SIZE(lm4857_default_regs),
-	.reg_word_size = sizeof(uint8_t),
-	.reg_cache_default = lm4857_default_regs,
-	.set_bias_level = lm4857_set_bias_level,
+	.cache_type = REGCACHE_FLAT,
+	.reg_defaults = lm4857_default_regs,
+	.num_reg_defaults = ARRAY_SIZE(lm4857_default_regs),
 };
 
 static int lm4857_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct lm4857 *lm4857;
-	int ret;
 
 	lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL);
 	if (!lm4857)
@@ -221,11 +176,11 @@ static int lm4857_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, lm4857);
 
-	lm4857->i2c = i2c;
-
-	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
+	lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config);
+	if (IS_ERR(lm4857->regmap))
+		return PTR_ERR(lm4857->regmap);
 
-	return ret;
+	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
 }
 
 static int lm4857_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index ad5313f..0569a4c 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -2084,8 +2084,9 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
 
 		pm_wakeup_event(codec->dev, 100);
 
-		schedule_delayed_work(&max98090->jack_work,
-			msecs_to_jiffies(100));
+		queue_delayed_work(system_power_efficient_wq,
+				   &max98090->jack_work,
+				   msecs_to_jiffies(100));
 	}
 
 	if (active & M98090_DRCACT_MASK)
@@ -2132,8 +2133,9 @@ int max98090_mic_detect(struct snd_soc_codec *codec,
 	snd_soc_jack_report(max98090->jack, 0,
 			    SND_JACK_HEADSET | SND_JACK_BTN_0);
 
-	schedule_delayed_work(&max98090->jack_work,
-		msecs_to_jiffies(100));
+	queue_delayed_work(system_power_efficient_wq,
+			   &max98090->jack_work,
+			   msecs_to_jiffies(100));
 
 	return 0;
 }
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 5402dfb..4d3c8fd 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -94,7 +94,6 @@
 #define AUDIO_DAC_CFS_DLY_B		(1 << 10)
 
 struct mc13783_priv {
-	struct snd_soc_codec codec;
 	struct mc13xxx *mc13xxx;
 
 	enum mc13783_ssi_port adc_ssi_port;
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
new file mode 100644
index 0000000..27da41b
--- /dev/null
+++ b/sound/soc/codecs/pcm1681.c
@@ -0,0 +1,313 @@
+/*
+ * PCM1681 ASoC codec driver
+ *
+ * Copyright (c) StreamUnlimited GmbH 2013
+ *	Marek Belisko <marek.belisko@streamunlimited.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#define PCM1681_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  |		\
+			     SNDRV_PCM_FMTBIT_S24_LE)
+
+#define PCM1681_PCM_RATES   (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
+			     SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100  | \
+			     SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200  | \
+			     SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+
+#define PCM1681_SOFT_MUTE_ALL		0xff
+#define PCM1681_DEEMPH_RATE_MASK	0x18
+#define PCM1681_DEEMPH_MASK		0x01
+
+#define PCM1681_ATT_CONTROL(X)	(X <= 6 ? X : X + 9) /* Attenuation level */
+#define PCM1681_SOFT_MUTE	0x07	/* Soft mute control register */
+#define PCM1681_DAC_CONTROL	0x08	/* DAC operation control */
+#define PCM1681_FMT_CONTROL	0x09	/* Audio interface data format */
+#define PCM1681_DEEMPH_CONTROL	0x0a	/* De-emphasis control */
+#define PCM1681_ZERO_DETECT_STATUS	0x0e	/* Zero detect status reg */
+
+static const struct reg_default pcm1681_reg_defaults[] = {
+	{ 0x01,	0xff },
+	{ 0x02,	0xff },
+	{ 0x03,	0xff },
+	{ 0x04,	0xff },
+	{ 0x05,	0xff },
+	{ 0x06,	0xff },
+	{ 0x07,	0x00 },
+	{ 0x08,	0x00 },
+	{ 0x09,	0x06 },
+	{ 0x0A,	0x00 },
+	{ 0x0B,	0xff },
+	{ 0x0C,	0x0f },
+	{ 0x0D,	0x00 },
+	{ 0x10,	0xff },
+	{ 0x11,	0xff },
+	{ 0x12,	0x00 },
+	{ 0x13,	0x00 },
+};
+
+static bool pcm1681_accessible_reg(struct device *dev, unsigned int reg)
+{
+	return !((reg == 0x00) || (reg == 0x0f));
+}
+
+static bool pcm1681_writeable_reg(struct device *dev, unsigned register reg)
+{
+	return pcm1681_accessible_reg(dev, reg) &&
+		(reg != PCM1681_ZERO_DETECT_STATUS);
+}
+
+struct pcm1681_private {
+	struct regmap *regmap;
+	unsigned int format;
+	/* Current deemphasis status */
+	unsigned int deemph;
+	/* Current rate for deemphasis control */
+	unsigned int rate;
+};
+
+static const int pcm1681_deemph[] = { 44100, 48000, 32000 };
+
+static int pcm1681_set_deemph(struct snd_soc_codec *codec)
+{
+	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
+	int i = 0, val = -1, enable = 0;
+
+	if (priv->deemph)
+		for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++)
+			if (pcm1681_deemph[i] == priv->rate)
+				val = i;
+
+	if (val != -1) {
+		regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
+					PCM1681_DEEMPH_RATE_MASK, val);
+		enable = 1;
+	} else
+		enable = 0;
+
+	/* enable/disable deemphasis functionality */
+	return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
+					PCM1681_DEEMPH_MASK, enable);
+}
+
+static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.enumerated.item[0] = priv->deemph;
+
+	return 0;
+}
+
+static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	priv->deemph = ucontrol->value.enumerated.item[0];
+
+	return pcm1681_set_deemph(codec);
+}
+
+static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int format)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	/* The PCM1681 can only be slave to all clocks */
+	if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+		dev_err(codec->dev, "Invalid clocking mode\n");
+		return -EINVAL;
+	}
+
+	priv->format = format;
+
+	return 0;
+}
+
+static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
+	int val;
+
+	if (mute)
+		val = PCM1681_SOFT_MUTE_ALL;
+	else
+		val = 0;
+
+	return regmap_write(priv->regmap, PCM1681_SOFT_MUTE, val);
+}
+
+static int pcm1681_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
+	int val = 0, ret;
+	int pcm_format = params_format(params);
+
+	priv->rate = params_rate(params);
+
+	switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		if (pcm_format == SNDRV_PCM_FORMAT_S24_LE)
+			val = 0x00;
+		else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
+			val = 0x03;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		val = 0x04;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		val = 0x05;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI format\n");
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(priv->regmap, PCM1681_FMT_CONTROL, 0x0f, val);
+	if (ret < 0)
+		return ret;
+
+	return pcm1681_set_deemph(codec);
+}
+
+static const struct snd_soc_dai_ops pcm1681_dai_ops = {
+	.set_fmt	= pcm1681_set_dai_fmt,
+	.hw_params	= pcm1681_hw_params,
+	.digital_mute	= pcm1681_digital_mute,
+};
+
+static const DECLARE_TLV_DB_SCALE(pcm1681_dac_tlv, -6350, 50, 1);
+
+static const struct snd_kcontrol_new pcm1681_controls[] = {
+	SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
+			PCM1681_ATT_CONTROL(1), PCM1681_ATT_CONTROL(2), 0,
+			0x7f, 0, pcm1681_dac_tlv),
+	SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume",
+			PCM1681_ATT_CONTROL(3), PCM1681_ATT_CONTROL(4), 0,
+			0x7f, 0, pcm1681_dac_tlv),
+	SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume",
+			PCM1681_ATT_CONTROL(5), PCM1681_ATT_CONTROL(6), 0,
+			0x7f, 0, pcm1681_dac_tlv),
+	SOC_DOUBLE_R_TLV("Channel 7/8 Playback Volume",
+			PCM1681_ATT_CONTROL(7), PCM1681_ATT_CONTROL(8), 0,
+			0x7f, 0, pcm1681_dac_tlv),
+	SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
+			    pcm1681_get_deemph, pcm1681_put_deemph),
+};
+
+struct snd_soc_dai_driver pcm1681_dai = {
+	.name = "pcm1681-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = PCM1681_PCM_RATES,
+		.formats = PCM1681_PCM_FORMATS,
+	},
+	.ops = &pcm1681_dai_ops,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id pcm1681_dt_ids[] = {
+	{ .compatible = "ti,pcm1681", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pcm1681_dt_ids);
+#endif
+
+static const struct regmap_config pcm1681_regmap = {
+	.reg_bits		= 8,
+	.val_bits		= 8,
+	.max_register		= ARRAY_SIZE(pcm1681_reg_defaults) + 1,
+	.reg_defaults		= pcm1681_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(pcm1681_reg_defaults),
+	.writeable_reg		= pcm1681_writeable_reg,
+	.readable_reg		= pcm1681_accessible_reg,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = {
+	.controls		= pcm1681_controls,
+	.num_controls		= ARRAY_SIZE(pcm1681_controls),
+};
+
+static const struct i2c_device_id pcm1681_i2c_id[] = {
+	{"pcm1681", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id);
+
+static int pcm1681_i2c_probe(struct i2c_client *client,
+			      const struct i2c_device_id *id)
+{
+	int ret;
+	struct pcm1681_private *priv;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regmap = devm_regmap_init_i2c(client, &pcm1681_regmap);
+	if (IS_ERR(priv->regmap)) {
+		ret = PTR_ERR(priv->regmap);
+		dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(client, priv);
+
+	return snd_soc_register_codec(&client->dev, &soc_codec_dev_pcm1681,
+		&pcm1681_dai, 1);
+}
+
+static int pcm1681_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static struct i2c_driver pcm1681_i2c_driver = {
+	.driver = {
+		.name	= "pcm1681",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcm1681_dt_ids),
+	},
+	.id_table	= pcm1681_i2c_id,
+	.probe		= pcm1681_i2c_probe,
+	.remove		= pcm1681_i2c_remove,
+};
+
+module_i2c_driver(pcm1681_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments PCM1681 ALSA SoC Codec Driver");
+MODULE_AUTHOR("Marek Belisko <marek.belisko@streamunlimited.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c
new file mode 100644
index 0000000..72cf835
--- /dev/null
+++ b/sound/soc/codecs/pcm1792a.c
@@ -0,0 +1,243 @@
+/*
+ * PCM1792A ASoC codec driver
+ *
+ * Copyright (c) Amarula Solutions B.V. 2013
+ *
+ *     Michael Trimarchi <michael@amarulasolutions.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/of_device.h>
+
+#include "pcm1792a.h"
+
+#define PCM1792A_DAC_VOL_LEFT	0x10
+#define PCM1792A_DAC_VOL_RIGHT	0x11
+#define PCM1792A_FMT_CONTROL	0x12
+#define PCM1792A_SOFT_MUTE	PCM1792A_FMT_CONTROL
+
+#define PCM1792A_FMT_MASK	0x70
+#define PCM1792A_FMT_SHIFT	4
+#define PCM1792A_MUTE_MASK	0x01
+#define PCM1792A_MUTE_SHIFT	0
+#define PCM1792A_ATLD_ENABLE	(1 << 7)
+
+static const struct reg_default pcm1792a_reg_defaults[] = {
+	{ 0x10, 0xff },
+	{ 0x11, 0xff },
+	{ 0x12, 0x50 },
+	{ 0x13, 0x00 },
+	{ 0x14, 0x00 },
+	{ 0x15, 0x01 },
+	{ 0x16, 0x00 },
+	{ 0x17, 0x00 },
+};
+
+static bool pcm1792a_accessible_reg(struct device *dev, unsigned int reg)
+{
+	return reg >= 0x10 && reg <= 0x17;
+}
+
+static bool pcm1792a_writeable_reg(struct device *dev, unsigned register reg)
+{
+	bool accessible;
+
+	accessible = pcm1792a_accessible_reg(dev, reg);
+
+	return accessible && reg != 0x16 && reg != 0x17;
+}
+
+struct pcm1792a_private {
+	struct regmap *regmap;
+	unsigned int format;
+	unsigned int rate;
+};
+
+static int pcm1792a_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                             unsigned int format)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	priv->format = format;
+
+	return 0;
+}
+
+static int pcm1792a_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = regmap_update_bits(priv->regmap, PCM1792A_SOFT_MUTE,
+				 PCM1792A_MUTE_MASK, !!mute);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
+	int val = 0, ret;
+	int pcm_format = params_format(params);
+
+	priv->rate = params_rate(params);
+
+	switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
+		    pcm_format == SNDRV_PCM_FORMAT_S32_LE)
+			val = 0x02;
+		else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
+			val = 0x00;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
+		    pcm_format == SNDRV_PCM_FORMAT_S32_LE)
+			val = 0x05;
+		else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
+			val = 0x04;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI format\n");
+		return -EINVAL;
+	}
+
+	val = val << PCM1792A_FMT_SHIFT | PCM1792A_ATLD_ENABLE;
+
+	ret = regmap_update_bits(priv->regmap, PCM1792A_FMT_CONTROL,
+				 PCM1792A_FMT_MASK | PCM1792A_ATLD_ENABLE, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops pcm1792a_dai_ops = {
+	.set_fmt	= pcm1792a_set_dai_fmt,
+	.hw_params	= pcm1792a_hw_params,
+	.digital_mute	= pcm1792a_digital_mute,
+};
+
+static const DECLARE_TLV_DB_SCALE(pcm1792a_dac_tlv, -12000, 50, 1);
+
+static const struct snd_kcontrol_new pcm1792a_controls[] = {
+	SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
+			 PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
+			 pcm1792a_dac_tlv),
+};
+
+static struct snd_soc_dai_driver pcm1792a_dai = {
+	.name = "pcm1792a-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = PCM1792A_RATES,
+		.formats = PCM1792A_FORMATS, },
+	.capture = {
+		.channels_min = 0,
+		.channels_max = 0,
+	},
+	.ops = &pcm1792a_dai_ops,
+};
+
+static const struct of_device_id pcm1792a_of_match[] = {
+	{ .compatible = "ti,pcm1792a", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pcm1792a_of_match);
+
+static const struct regmap_config pcm1792a_regmap = {
+	.reg_bits		= 8,
+	.val_bits		= 8,
+	.max_register		= 24,
+	.reg_defaults		= pcm1792a_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(pcm1792a_reg_defaults),
+	.writeable_reg		= pcm1792a_writeable_reg,
+	.readable_reg		= pcm1792a_accessible_reg,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_pcm1792a = {
+	.controls		= pcm1792a_controls,
+	.num_controls		= ARRAY_SIZE(pcm1792a_controls),
+};
+
+static int pcm1792a_spi_probe(struct spi_device *spi)
+{
+	struct pcm1792a_private *pcm1792a;
+	int ret;
+
+	pcm1792a = devm_kzalloc(&spi->dev, sizeof(struct pcm1792a_private),
+				GFP_KERNEL);
+	if (!pcm1792a)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, pcm1792a);
+
+	pcm1792a->regmap = devm_regmap_init_spi(spi, &pcm1792a_regmap);
+	if (IS_ERR(pcm1792a->regmap)) {
+		ret = PTR_ERR(pcm1792a->regmap);
+		dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
+		return ret;
+	}
+
+	return snd_soc_register_codec(&spi->dev,
+			&soc_codec_dev_pcm1792a, &pcm1792a_dai, 1);
+}
+
+static int pcm1792a_spi_remove(struct spi_device *spi)
+{
+	snd_soc_unregister_codec(&spi->dev);
+	return 0;
+}
+
+static const struct spi_device_id pcm1792a_spi_ids[] = {
+	{ "pcm1792a", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, pcm1792a_spi_ids);
+
+static struct spi_driver pcm1792a_codec_driver = {
+	.driver = {
+		.name = "pcm1792a",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(pcm1792a_of_match),
+	},
+	.id_table = pcm1792a_spi_ids,
+	.probe = pcm1792a_spi_probe,
+	.remove = pcm1792a_spi_remove,
+};
+
+module_spi_driver(pcm1792a_codec_driver);
+
+MODULE_DESCRIPTION("ASoC PCM1792A driver");
+MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm1792a.h
new file mode 100644
index 0000000..7a83d1f
--- /dev/null
+++ b/sound/soc/codecs/pcm1792a.h
@@ -0,0 +1,26 @@
+/*
+ * definitions for PCM1792A
+ *
+ * Copyright 2013 Amarula Solutions
+ *
+  * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PCM1792A_H__
+#define __PCM1792A_H__
+
+#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+
+#define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+			  SNDRV_PCM_FMTBIT_S16_LE)
+
+#endif
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index f2a6282..b883f99 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -28,8 +28,6 @@
 
 #include "pcm3008.h"
 
-#define PCM3008_VERSION "0.2"
-
 #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |	\
 		       SNDRV_PCM_RATE_48000)
 
@@ -51,72 +49,6 @@ static struct snd_soc_dai_driver pcm3008_dai = {
 	},
 };
 
-static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
-{
-	gpio_free(setup->dem0_pin);
-	gpio_free(setup->dem1_pin);
-	gpio_free(setup->pdad_pin);
-	gpio_free(setup->pdda_pin);
-}
-
-static int pcm3008_soc_probe(struct snd_soc_codec *codec)
-{
-	struct pcm3008_setup_data *setup = codec->dev->platform_data;
-	int ret = 0;
-
-	printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
-
-	/* DEM1  DEM0  DE-EMPHASIS_MODE
-	 * Low   Low   De-emphasis 44.1 kHz ON
-	 * Low   High  De-emphasis OFF
-	 * High  Low   De-emphasis 48 kHz ON
-	 * High  High  De-emphasis 32 kHz ON
-	 */
-
-	/* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
-	ret = gpio_request(setup->dem0_pin, "codec_dem0");
-	if (ret == 0)
-		ret = gpio_direction_output(setup->dem0_pin, 1);
-	if (ret != 0)
-		goto gpio_err;
-
-	/* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
-	ret = gpio_request(setup->dem1_pin, "codec_dem1");
-	if (ret == 0)
-		ret = gpio_direction_output(setup->dem1_pin, 0);
-	if (ret != 0)
-		goto gpio_err;
-
-	/* Configure PDAD GPIO. */
-	ret = gpio_request(setup->pdad_pin, "codec_pdad");
-	if (ret == 0)
-		ret = gpio_direction_output(setup->pdad_pin, 1);
-	if (ret != 0)
-		goto gpio_err;
-
-	/* Configure PDDA GPIO. */
-	ret = gpio_request(setup->pdda_pin, "codec_pdda");
-	if (ret == 0)
-		ret = gpio_direction_output(setup->pdda_pin, 1);
-	if (ret != 0)
-		goto gpio_err;
-
-	return ret;
-
-gpio_err:
-	pcm3008_gpio_free(setup);
-
-	return ret;
-}
-
-static int pcm3008_soc_remove(struct snd_soc_codec *codec)
-{
-	struct pcm3008_setup_data *setup = codec->dev->platform_data;
-
-	pcm3008_gpio_free(setup);
-	return 0;
-}
-
 #ifdef CONFIG_PM
 static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
 {
@@ -143,14 +75,49 @@ static int pcm3008_soc_resume(struct snd_soc_codec *codec)
 #endif
 
 static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
-	.probe = 	pcm3008_soc_probe,
-	.remove = 	pcm3008_soc_remove,
 	.suspend =	pcm3008_soc_suspend,
 	.resume =	pcm3008_soc_resume,
 };
 
 static int pcm3008_codec_probe(struct platform_device *pdev)
 {
+	struct pcm3008_setup_data *setup = pdev->dev.platform_data;
+	int ret;
+
+	if (!setup)
+		return -EINVAL;
+
+	/* DEM1  DEM0  DE-EMPHASIS_MODE
+	 * Low   Low   De-emphasis 44.1 kHz ON
+	 * Low   High  De-emphasis OFF
+	 * High  Low   De-emphasis 48 kHz ON
+	 * High  High  De-emphasis 32 kHz ON
+	 */
+
+	/* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
+	ret = devm_gpio_request_one(&pdev->dev, setup->dem0_pin,
+				    GPIOF_OUT_INIT_HIGH, "codec_dem0");
+	if (ret != 0)
+		return ret;
+
+	/* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
+	ret = devm_gpio_request_one(&pdev->dev, setup->dem1_pin,
+				    GPIOF_OUT_INIT_LOW, "codec_dem1");
+	if (ret != 0)
+		return ret;
+
+	/* Configure PDAD GPIO. */
+	ret = devm_gpio_request_one(&pdev->dev, setup->pdad_pin,
+				    GPIOF_OUT_INIT_HIGH, "codec_pdad");
+	if (ret != 0)
+		return ret;
+
+	/* Configure PDDA GPIO. */
+	ret = devm_gpio_request_one(&pdev->dev, setup->pdda_pin,
+				    GPIOF_OUT_INIT_HIGH, "codec_pdda");
+	if (ret != 0)
+		return ret;
+
 	return snd_soc_register_codec(&pdev->dev,
 			&soc_codec_dev_pcm3008, &pcm3008_dai, 1);
 }
@@ -158,6 +125,7 @@ static int pcm3008_codec_probe(struct platform_device *pdev)
 static int pcm3008_codec_remove(struct platform_device *pdev)
 {
 	snd_soc_unregister_codec(&pdev->dev);
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index ce585e3..4db7314 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -737,29 +737,6 @@ static const struct snd_kcontrol_new rt5640_mono_mix[] = {
 			RT5640_M_BST1_MM_SFT, 1, 1),
 };
 
-/* INL/R source */
-static const char * const rt5640_inl_src[] = {
-	"IN2P", "MONOP"
-};
-
-static const SOC_ENUM_SINGLE_DECL(
-	rt5640_inl_enum, RT5640_INL_INR_VOL,
-	RT5640_INL_SEL_SFT, rt5640_inl_src);
-
-static const struct snd_kcontrol_new rt5640_inl_mux =
-	SOC_DAPM_ENUM("INL source", rt5640_inl_enum);
-
-static const char * const rt5640_inr_src[] = {
-	"IN2N", "MONON"
-};
-
-static const SOC_ENUM_SINGLE_DECL(
-	rt5640_inr_enum, RT5640_INL_INR_VOL,
-	RT5640_INR_SEL_SFT, rt5640_inr_src);
-
-static const struct snd_kcontrol_new rt5640_inr_mux =
-	SOC_DAPM_ENUM("INR source", rt5640_inr_enum);
-
 /* Stereo ADC source */
 static const char * const rt5640_stereo_adc1_src[] = {
 	"DIG MIX", "ADC"
@@ -1005,9 +982,6 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 		RT5640_PWR_IN_L_BIT, 0, NULL, 0),
 	SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL,
 		RT5640_PWR_IN_R_BIT, 0, NULL, 0),
-	/* IN Mux */
-	SND_SOC_DAPM_MUX("INL Mux", SND_SOC_NOPM, 0, 0, &rt5640_inl_mux),
-	SND_SOC_DAPM_MUX("INR Mux", SND_SOC_NOPM, 0, 0, &rt5640_inr_mux),
 	/* REC Mixer */
 	SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0,
 			rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)),
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 6c8a9e7..1f4093f 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -153,6 +153,8 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
 static int power_vag_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
+	const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP;
+
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
@@ -160,9 +162,17 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
-			SGTL5000_VAG_POWERUP, 0);
-		msleep(400);
+		/*
+		 * Don't clear VAG_POWERUP, when both DAC and ADC are
+		 * operational to prevent inadvertently starving the
+		 * other one of them.
+		 */
+		if ((snd_soc_read(w->codec, SGTL5000_CHIP_ANA_POWER) &
+				mask) != mask) {
+			snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_VAG_POWERUP, 0);
+			msleep(400);
+		}
 		break;
 	default:
 		break;
@@ -388,7 +398,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
 	SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0),
 	SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)",
 			SGTL5000_CHIP_ANA_ADC_CTRL,
-			8, 2, 0, capture_6db_attenuate),
+			8, 1, 0, capture_6db_attenuate),
 	SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0),
 
 	SOC_DOUBLE_TLV("Headphone Playback Volume",
@@ -644,16 +654,19 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate)
 		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
 			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
 			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP);
+
+		/* if using pll, clk_ctrl must be set after pll power up */
+		snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
 	} else {
+		/* otherwise, clk_ctrl must be set before pll power down */
+		snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
+
 		/* power down pll */
 		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
 			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
 			0);
 	}
 
-	/* if using pll, clk_ctrl must be set after pll power up */
-	snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
-
 	return 0;
 }
 
@@ -1470,6 +1483,7 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
 static const struct regmap_config sgtl5000_regmap = {
 	.reg_bits = 16,
 	.val_bits = 16,
+	.reg_stride = 2,
 
 	.max_register = SGTL5000_MAX_REG_OFFSET,
 	.volatile_reg = sgtl5000_volatile,
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
index e9d7881..26d3474 100644
--- a/sound/soc/codecs/spdif_receiver.c
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -25,6 +25,8 @@
 
 #define STUB_RATES	SNDRV_PCM_RATE_8000_192000
 #define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | \
 			SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
 
 static struct snd_soc_codec_driver soc_codec_spdif_dir;
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index 1828049..4e96d10 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -25,10 +25,24 @@
 #define DRV_NAME "spdif-dit"
 
 #define STUB_RATES	SNDRV_PCM_RATE_8000_96000
-#define STUB_FORMATS	SNDRV_PCM_FMTBIT_S16_LE
+#define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE)
 
+static const struct snd_soc_dapm_widget dit_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("spdif-out"),
+};
+
+static const const struct snd_soc_dapm_route dit_routes[] = {
+	{ "spdif-out", NULL, "Playback" },
+};
 
-static struct snd_soc_codec_driver soc_codec_spdif_dit;
+static struct snd_soc_codec_driver soc_codec_spdif_dit = {
+	.dapm_widgets = dit_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(dit_widgets),
+	.dapm_routes = dit_routes,
+	.num_dapm_routes = ARRAY_SIZE(dit_routes),
+};
 
 static struct snd_soc_dai_driver dit_stub_dai = {
 	.name		= "dit-hifi",
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index cfb55fe..06edb39 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -363,16 +363,18 @@ static void sta32x_watchdog(struct work_struct *work)
 	}
 
 	if (!sta32x->shutdown)
-		schedule_delayed_work(&sta32x->watchdog_work,
-				      round_jiffies_relative(HZ));
+		queue_delayed_work(system_power_efficient_wq,
+				   &sta32x->watchdog_work,
+				   round_jiffies_relative(HZ));
 }
 
 static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
 {
 	if (sta32x->pdata->needs_esd_watchdog) {
 		sta32x->shutdown = 0;
-		schedule_delayed_work(&sta32x->watchdog_work,
-				      round_jiffies_relative(HZ));
+		queue_delayed_work(system_power_efficient_wq,
+				   &sta32x->watchdog_work,
+				   round_jiffies_relative(HZ));
 	}
 }
 
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index b1f6982..b192cd4 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -29,7 +29,7 @@ MODULE_LICENSE("GPL");
 /* AIC26 driver private data */
 struct aic26 {
 	struct spi_device *spi;
-	struct snd_soc_codec codec;
+	struct snd_soc_codec *codec;
 	int master;
 	int datfm;
 	int mclk;
@@ -330,7 +330,7 @@ static ssize_t aic26_keyclick_show(struct device *dev,
 	struct aic26 *aic26 = dev_get_drvdata(dev);
 	int val, amp, freq, len;
 
-	val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
+	val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
 	amp = (val >> 12) & 0x7;
 	freq = (125 << ((val >> 8) & 0x7)) >> 1;
 	len = 2 * (1 + ((val >> 4) & 0xf));
@@ -346,9 +346,9 @@ static ssize_t aic26_keyclick_set(struct device *dev,
 	struct aic26 *aic26 = dev_get_drvdata(dev);
 	int val;
 
-	val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
+	val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
 	val |= 0x8000;
-	aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
+	aic26_reg_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
 
 	return count;
 }
@@ -360,8 +360,11 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
  */
 static int aic26_probe(struct snd_soc_codec *codec)
 {
+	struct aic26 *aic26 = dev_get_drvdata(codec->dev);
 	int ret, err, i, reg;
 
+	aic26->codec = codec;
+
 	dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");
 
 	/* Reset the codec to power on defaults */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e5b9268..6e3f269 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
 static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	unsigned int reg = mc->reg;
@@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
 	int max = mc->max;
 	unsigned int mask = (1 << fls(max)) - 1;
 	unsigned int invert = mc->invert;
-	unsigned short val, val_mask;
-	int ret;
-	struct snd_soc_dapm_path *path;
-	int found = 0;
+	unsigned short val;
+	struct snd_soc_dapm_update update;
+	int connect, change;
 
 	val = (ucontrol->value.integer.value[0] & mask);
 
@@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
 	if (val)
 		val = mask;
 
+	connect = !!val;
+
 	if (invert)
 		val = mask - val;
-	val_mask = mask << shift;
-	val = val << shift;
-
-	mutex_lock(&widget->codec->mutex);
 
-	if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
-		/* find dapm widget path assoc with kcontrol */
-		list_for_each_entry(path, &widget->dapm->card->paths, list) {
-			if (path->kcontrol != kcontrol)
-				continue;
+	mask <<= shift;
+	val <<= shift;
 
-			/* found, now check type */
-			found = 1;
-			if (val)
-				/* new connection */
-				path->connect = invert ? 0 : 1;
-			else
-				/* old connection must be powered down */
-				path->connect = invert ? 1 : 0;
+	change = snd_soc_test_bits(codec, val, mask, reg);
+	if (change) {
+		update.kcontrol = kcontrol;
+		update.reg = reg;
+		update.mask = mask;
+		update.val = val;
 
-			dapm_mark_dirty(path->source, "tlv320aic3x source");
-			dapm_mark_dirty(path->sink, "tlv320aic3x sink");
-
-			break;
-		}
+		snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect,
+			&update);
 	}
 
-	mutex_unlock(&widget->codec->mutex);
-
-	if (found)
-		snd_soc_dapm_sync(widget->dapm);
-
-	ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val);
-	return ret;
+	return change;
 }
 
 /*
@@ -1492,6 +1474,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
 	{ "tlv320aic3x", AIC3X_MODEL_3X },
 	{ "tlv320aic33", AIC3X_MODEL_33 },
 	{ "tlv320aic3007", AIC3X_MODEL_3007 },
+	{ "tlv320aic3106", AIC3X_MODEL_3X },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1582,6 +1565,9 @@ static int aic3x_i2c_remove(struct i2c_client *client)
 #if defined(CONFIG_OF)
 static const struct of_device_id tlv320aic3x_of_match[] = {
 	{ .compatible = "ti,tlv320aic3x", },
+	{ .compatible = "ti,tlv320aic33" },
+	{ .compatible = "ti,tlv320aic3007" },
+	{ .compatible = "ti,tlv320aic3106" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 8e6e5b0..1e3884d 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -137,8 +137,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
 
 /* codec private data */
 struct twl4030_priv {
-	struct snd_soc_codec codec;
-
 	unsigned int codec_powered;
 
 	/* reference counts of AIF/APLL users */
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 44621dd..3c79dbb 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -429,7 +429,8 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
 	struct snd_soc_codec *codec = data;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
-	schedule_delayed_work(&priv->hs_jack.work, msecs_to_jiffies(200));
+	queue_delayed_work(system_power_efficient_wq,
+			   &priv->hs_jack.work, msecs_to_jiffies(200));
 
 	return IRQ_HANDLED;
 }
@@ -437,9 +438,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
 static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int val;
 
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 6d0aa44..c94d4c1 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -325,7 +325,6 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int uda134x_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
-	u8 reg;
 	struct uda134x_platform_data *pd = codec->control_data;
 	int i;
 	u8 *cache = codec->reg_cache;
@@ -334,23 +333,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		/* ADC, DAC on */
-		switch (pd->model) {
-		case UDA134X_UDA1340:
-		case UDA134X_UDA1344:
-		case UDA134X_UDA1345:
-			reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
-			uda134x_write(codec, UDA134X_DATA011, reg | 0x03);
-			break;
-		case UDA134X_UDA1341:
-			reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
-			uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
-			break;
-		default:
-			printk(KERN_ERR "UDA134X SoC codec: "
-			       "unsupported model %d\n", pd->model);
-			return -EINVAL;
-		}
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		/* power on */
@@ -362,23 +344,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
 		}
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		/* ADC, DAC power off */
-		switch (pd->model) {
-		case UDA134X_UDA1340:
-		case UDA134X_UDA1344:
-		case UDA134X_UDA1345:
-			reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
-			uda134x_write(codec, UDA134X_DATA011, reg & ~(0x03));
-			break;
-		case UDA134X_UDA1341:
-			reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
-			uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
-			break;
-		default:
-			printk(KERN_ERR "UDA134X SoC codec: "
-			       "unsupported model %d\n", pd->model);
-			return -EINVAL;
-		}
 		break;
 	case SND_SOC_BIAS_OFF:
 		/* power off */
@@ -450,6 +415,37 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
 SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 };
 
+/* UDA1341 has the DAC/ADC power down in STATUS1 */
+static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0),
+	SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0),
+};
+
+/* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */
+static const struct snd_soc_dapm_widget uda1340_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0),
+	SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0),
+};
+
+/* Common DAPM widgets */
+static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("VINL1"),
+	SND_SOC_DAPM_INPUT("VINR1"),
+	SND_SOC_DAPM_INPUT("VINL2"),
+	SND_SOC_DAPM_INPUT("VINR2"),
+	SND_SOC_DAPM_OUTPUT("VOUTL"),
+	SND_SOC_DAPM_OUTPUT("VOUTR"),
+};
+
+static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
+	{ "ADC", NULL, "VINL1" },
+	{ "ADC", NULL, "VINR1" },
+	{ "ADC", NULL, "VINL2" },
+	{ "ADC", NULL, "VINR2" },
+	{ "VOUTL", NULL, "DAC" },
+	{ "VOUTR", NULL, "DAC" },
+};
+
 static const struct snd_soc_dai_ops uda134x_dai_ops = {
 	.startup	= uda134x_startup,
 	.shutdown	= uda134x_shutdown,
@@ -485,6 +481,8 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
 {
 	struct uda134x_priv *uda134x;
 	struct uda134x_platform_data *pd = codec->card->dev->platform_data;
+	const struct snd_soc_dapm_widget *widgets;
+	unsigned num_widgets;
 
 	int ret;
 
@@ -526,6 +524,22 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
 	else
 		uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
+	if (pd->model == UDA134X_UDA1341) {
+		widgets = uda1341_dapm_widgets;
+		num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
+	} else {
+		widgets = uda1340_dapm_widgets;
+		num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
+	}
+
+	ret = snd_soc_dapm_new_controls(&codec->dapm, widgets, num_widgets);
+	if (ret) {
+		printk(KERN_ERR "%s failed to register dapm controls: %d",
+			__func__, ret);
+		kfree(uda134x);
+		return ret;
+	}
+
 	switch (pd->model) {
 	case UDA134X_UDA1340:
 	case UDA134X_UDA1344:
@@ -599,6 +613,10 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
 	.read = uda134x_read_reg_cache,
 	.write = uda134x_write,
 	.set_bias_level = uda134x_set_bias_level,
+	.dapm_widgets = uda134x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
+	.dapm_routes = uda134x_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
 };
 
 static int uda134x_codec_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 10adc41..d5ebcb0 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -420,7 +420,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
 		xfer->codec = codec;
 		list_add_tail(&xfer->list, &xfer_list);
 
-		out = kzalloc(len, GFP_KERNEL);
+		out = kzalloc(len, GFP_KERNEL | GFP_DMA);
 		if (!out) {
 			dev_err(codec->dev,
 				"Failed to allocate RX buffer\n");
@@ -429,7 +429,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
 		}
 		xfer->t.rx_buf = out;
 
-		img = kzalloc(len, GFP_KERNEL);
+		img = kzalloc(len, GFP_KERNEL | GFP_DMA);
 		if (!img) {
 			dev_err(codec->dev,
 				"Failed to allocate image buffer\n");
@@ -523,14 +523,14 @@ static int wm0010_stage2_load(struct snd_soc_codec *codec)
 	dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size);
 
 	/* Copy to local buffer first as vmalloc causes problems for dma */
-	img = kzalloc(fw->size, GFP_KERNEL);
+	img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
 	if (!img) {
 		dev_err(codec->dev, "Failed to allocate image buffer\n");
 		ret = -ENOMEM;
 		goto abort2;
 	}
 
-	out = kzalloc(fw->size, GFP_KERNEL);
+	out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
 	if (!out) {
 		dev_err(codec->dev, "Failed to allocate output buffer\n");
 		ret = -ENOMEM;
@@ -670,14 +670,14 @@ static int wm0010_boot(struct snd_soc_codec *codec)
 
 		ret = -ENOMEM;
 		len = pll_rec.length + 8;
-		out = kzalloc(len, GFP_KERNEL);
+		out = kzalloc(len, GFP_KERNEL | GFP_DMA);
 		if (!out) {
 			dev_err(codec->dev,
 				"Failed to allocate RX buffer\n");
 			goto abort;
 		}
 
-		img_swap = kzalloc(len, GFP_KERNEL);
+		img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA);
 		if (!img_swap) {
 			dev_err(codec->dev,
 				"Failed to allocate image buffer\n");
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 282fd23..a6cbdb4 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -998,6 +998,8 @@ SND_SOC_DAPM_INPUT("IN2R"),
 SND_SOC_DAPM_INPUT("IN3L"),
 SND_SOC_DAPM_INPUT("IN3R"),
 
+SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
+
 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
@@ -1614,6 +1616,9 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
 	{ "SPKDAT1R", NULL, "OUT5R" },
 
 	{ "MICSUPP", NULL, "SYSCLK" },
+
+	{ "DRC1 Signal Activity", NULL, "DRC1L" },
+	{ "DRC1 Signal Activity", NULL, "DRC1R" },
 };
 
 static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
@@ -1781,6 +1786,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
 		return ret;
 
 	arizona_init_spk(codec);
+	arizona_init_gpio(codec);
 
 	snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
 
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 2e7cb4b..77fd531 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -58,14 +58,10 @@ static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
 	SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0)
 
 static const struct snd_kcontrol_new wm5110_snd_controls[] = {
-SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
-	   ARIZONA_IN1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
-	   ARIZONA_IN2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
-	   ARIZONA_IN3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL,
-	   ARIZONA_IN4_OSR_SHIFT, 1, 0),
+SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]),
+SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]),
+SOC_ENUM("IN3 OSR", arizona_in_dmic_osr[2]),
+SOC_ENUM("IN4 OSR", arizona_in_dmic_osr[3]),
 
 SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL,
 		     ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
@@ -432,6 +428,9 @@ SND_SOC_DAPM_INPUT("IN3R"),
 SND_SOC_DAPM_INPUT("IN4L"),
 SND_SOC_DAPM_INPUT("IN4R"),
 
+SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
+SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
+
 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
@@ -1006,6 +1005,11 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
 	{ "SPKDAT2R", NULL, "OUT6R" },
 
 	{ "MICSUPP", NULL, "SYSCLK" },
+
+	{ "DRC1 Signal Activity", NULL, "DRC1L" },
+	{ "DRC1 Signal Activity", NULL, "DRC1R" },
+	{ "DRC2 Signal Activity", NULL, "DRC2L" },
+	{ "DRC2 Signal Activity", NULL, "DRC2R" },
 };
 
 static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
@@ -1170,6 +1174,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
 		return ret;
 
 	arizona_init_spk(codec);
+	arizona_init_gpio(codec);
 
 	snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
 
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 0e8b3aa..af1318d 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1301,7 +1301,8 @@ static irqreturn_t wm8350_hpl_jack_handler(int irq, void *data)
 	if (device_may_wakeup(wm8350->dev))
 		pm_wakeup_event(wm8350->dev, 250);
 
-	schedule_delayed_work(&priv->hpl.work, msecs_to_jiffies(200));
+	queue_delayed_work(system_power_efficient_wq,
+			   &priv->hpl.work, msecs_to_jiffies(200));
 
 	return IRQ_HANDLED;
 }
@@ -1318,7 +1319,8 @@ static irqreturn_t wm8350_hpr_jack_handler(int irq, void *data)
 	if (device_may_wakeup(wm8350->dev))
 		pm_wakeup_event(wm8350->dev, 250);
 
-	schedule_delayed_work(&priv->hpr.work, msecs_to_jiffies(200));
+	queue_delayed_work(system_power_efficient_wq,
+			   &priv->hpr.work, msecs_to_jiffies(200));
 
 	return IRQ_HANDLED;
 }
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 5276062..456bb8c 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -45,6 +45,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
 struct wm8731_priv {
 	struct regmap *regmap;
 	struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
+	const struct snd_pcm_hw_constraint_list *constraints;
 	unsigned int sysclk;
 	int sysclk_type;
 	int playback_fs;
@@ -290,6 +291,36 @@ static const struct _coeff_div coeff_div[] = {
 	{12000000, 88200, 136, 0xf, 0x1, 0x1},
 };
 
+/* rates constraints */
+static const unsigned int wm8731_rates_12000000[] = {
+	8000, 32000, 44100, 48000, 96000, 88200,
+};
+
+static const unsigned int wm8731_rates_12288000_18432000[] = {
+	8000, 32000, 48000, 96000,
+};
+
+static const unsigned int wm8731_rates_11289600_16934400[] = {
+	8000, 44100, 88200,
+};
+
+static const struct snd_pcm_hw_constraint_list wm8731_constraints_12000000 = {
+	.list = wm8731_rates_12000000,
+	.count = ARRAY_SIZE(wm8731_rates_12000000),
+};
+
+static const
+struct snd_pcm_hw_constraint_list wm8731_constraints_12288000_18432000 = {
+	.list = wm8731_rates_12288000_18432000,
+	.count = ARRAY_SIZE(wm8731_rates_12288000_18432000),
+};
+
+static const
+struct snd_pcm_hw_constraint_list wm8731_constraints_11289600_16934400 = {
+	.list = wm8731_rates_11289600_16934400,
+	.count = ARRAY_SIZE(wm8731_rates_11289600_16934400),
+};
+
 static inline int get_coeff(int mclk, int rate)
 {
 	int i;
@@ -362,17 +393,26 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	}
 
 	switch (freq) {
-	case 11289600:
+	case 0:
+		wm8731->constraints = NULL;
+		break;
 	case 12000000:
+		wm8731->constraints = &wm8731_constraints_12000000;
+		break;
 	case 12288000:
-	case 16934400:
 	case 18432000:
-		wm8731->sysclk = freq;
+		wm8731->constraints = &wm8731_constraints_12288000_18432000;
+		break;
+	case 16934400:
+	case 11289600:
+		wm8731->constraints = &wm8731_constraints_11289600_16934400;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	wm8731->sysclk = freq;
+
 	snd_soc_dapm_sync(&codec->dapm);
 
 	return 0;
@@ -475,12 +515,26 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 	return 0;
 }
 
+static int wm8731_startup(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(dai->codec);
+
+	if (wm8731->constraints)
+		snd_pcm_hw_constraint_list(substream->runtime, 0,
+					   SNDRV_PCM_HW_PARAM_RATE,
+					   wm8731->constraints);
+
+	return 0;
+}
+
 #define WM8731_RATES SNDRV_PCM_RATE_8000_96000
 
 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
 static const struct snd_soc_dai_ops wm8731_dai_ops = {
+	.startup	= wm8731_startup,
 	.hw_params	= wm8731_hw_params,
 	.digital_mute	= wm8731_mute,
 	.set_sysclk	= wm8731_set_dai_sysclk,
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 0a4ab4c..d96ebf5 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1456,8 +1456,9 @@ static int wm8753_resume(struct snd_soc_codec *codec)
 	if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
 		wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
 		codec->dapm.bias_level = SND_SOC_BIAS_ON;
-		schedule_delayed_work(&codec->dapm.delayed_work,
-			msecs_to_jiffies(caps_charge));
+		queue_delayed_work(system_power_efficient_wq,
+				   &codec->dapm.delayed_work,
+				   msecs_to_jiffies(caps_charge));
 	}
 
 	return 0;
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index fa24ced..eebcb1d 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -364,9 +364,7 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
 static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 	u16 reg;
 	int ret;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 4c9fb14..91dfbfe 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1012,7 +1012,7 @@ static const struct soc_enum liner_enum =
 	SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text);
 
 static const struct snd_kcontrol_new liner_mux =
-	SOC_DAPM_ENUM("LINEL Mux", liner_enum);
+	SOC_DAPM_ENUM("LINER Mux", liner_enum);
 
 static const char *sidetone_text[] = {
 	"None", "Left", "Right"
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index e2de9ec..11d80f3 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2621,8 +2621,6 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 
 	wm8962->sysclk_rate = freq;
 
-	wm8962_configure_bclk(codec);
-
 	return 0;
 }
 
@@ -3046,8 +3044,9 @@ static irqreturn_t wm8962_irq(int irq, void *data)
 
 		pm_wakeup_event(dev, 300);
 
-		schedule_delayed_work(&wm8962->mic_work,
-				      msecs_to_jiffies(250));
+		queue_delayed_work(system_power_efficient_wq,
+				   &wm8962->mic_work,
+				   msecs_to_jiffies(250));
 	}
 
 	return IRQ_HANDLED;
@@ -3175,7 +3174,7 @@ static ssize_t wm8962_beep_set(struct device *dev,
 	long int time;
 	int ret;
 
-	ret = strict_strtol(buf, 10, &time);
+	ret = kstrtol(buf, 10, &time);
 	if (ret != 0)
 		return ret;
 
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index ba832b7..86426a1 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -819,8 +819,9 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
 		 * don't want false reports.
 		 */
 		if (wm8994->jackdet && !wm8994->clk_has_run) {
-			schedule_delayed_work(&wm8994->jackdet_bootstrap,
-					      msecs_to_jiffies(1000));
+			queue_delayed_work(system_power_efficient_wq,
+					   &wm8994->jackdet_bootstrap,
+					   msecs_to_jiffies(1000));
 			wm8994->clk_has_run = true;
 		}
 		break;
@@ -1432,14 +1433,12 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
 
 #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \
 	SOC_SINGLE_EXT(xname, reg, shift, max, invert, \
-		snd_soc_get_volsw, wm8994_put_class_w)
+		snd_soc_dapm_get_volsw, wm8994_put_class_w)
 
 static int wm8994_put_class_w(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *w = wlist->widgets[0];
-	struct snd_soc_codec *codec = w->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	int ret;
 
 	ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
@@ -3487,7 +3486,8 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
 
 	pm_wakeup_event(codec->dev, 300);
 
-	schedule_delayed_work(&priv->mic_work, msecs_to_jiffies(250));
+	queue_delayed_work(system_power_efficient_wq,
+			   &priv->mic_work, msecs_to_jiffies(250));
 
 	return IRQ_HANDLED;
 }
@@ -3575,8 +3575,9 @@ static void wm8958_mic_id(void *data, u16 status)
 		/* If nothing present then clear our statuses */
 		dev_dbg(codec->dev, "Detected open circuit\n");
 
-		schedule_delayed_work(&wm8994->open_circuit_work,
-				      msecs_to_jiffies(2500));
+		queue_delayed_work(system_power_efficient_wq,
+				   &wm8994->open_circuit_work,
+				   msecs_to_jiffies(2500));
 		return;
 	}
 
@@ -3690,8 +3691,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 				    WM1811_JACKDET_DB, 0);
 
 		delay = control->pdata.micdet_delay;
-		schedule_delayed_work(&wm8994->mic_work,
-				      msecs_to_jiffies(delay));
+		queue_delayed_work(system_power_efficient_wq,
+				   &wm8994->mic_work,
+				   msecs_to_jiffies(delay));
 	} else {
 		dev_dbg(codec->dev, "Jack not detected\n");
 
@@ -3936,8 +3938,9 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
 	id_delay = wm8994->wm8994->pdata.mic_id_delay;
 
 	if (wm8994->mic_detecting)
-		schedule_delayed_work(&wm8994->mic_complete_work,
-				      msecs_to_jiffies(id_delay));
+		queue_delayed_work(system_power_efficient_wq,
+				   &wm8994->mic_complete_work,
+				   msecs_to_jiffies(id_delay));
 	else
 		wm8958_button_det(codec, reg);
 
@@ -4010,9 +4013,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
 	wm8994->micdet_irq = control->pdata.micdet_irq;
 
-	pm_runtime_enable(codec->dev);
-	pm_runtime_idle(codec->dev);
-
 	/* By default use idle_bias_off, will override for WM8994 */
 	codec->dapm.idle_bias_off = 1;
 
@@ -4385,8 +4385,6 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
 
 	wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
-	pm_runtime_disable(codec->dev);
-
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
 		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
 				&wm8994->fll_locked[i]);
@@ -4445,6 +4443,9 @@ static int wm8994_probe(struct platform_device *pdev)
 
 	wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
 
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_idle(&pdev->dev);
+
 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
 			wm8994_dai, ARRAY_SIZE(wm8994_dai));
 }
@@ -4452,6 +4453,8 @@ static int wm8994_probe(struct platform_device *pdev)
 static int wm8994_remove(struct platform_device *pdev)
 {
 	snd_soc_unregister_codec(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 90a65c4..da2899e6 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -549,12 +549,9 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source,
 static int wm8995_put_class_w(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *w = wlist->widgets[0];
-	struct snd_soc_codec *codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	int ret;
 
-	codec = w->codec;
 	ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
 	wm8995_update_class_w(codec);
 	return ret;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 05252ac..b38f350 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -225,15 +225,8 @@ struct wm_coeff_ctl_ops {
 		     struct snd_ctl_elem_info *uinfo);
 };
 
-struct wm_coeff {
-	struct device *dev;
-	struct list_head ctl_list;
-	struct regmap *regmap;
-};
-
 struct wm_coeff_ctl {
 	const char *name;
-	struct snd_card *card;
 	struct wm_adsp_alg_region region;
 	struct wm_coeff_ctl_ops ops;
 	struct wm_adsp *adsp;
@@ -378,7 +371,6 @@ static int wm_coeff_info(struct snd_kcontrol *kcontrol,
 static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
 				  const void *buf, size_t len)
 {
-	struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
 	struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 	struct wm_adsp_alg_region *region = &ctl->region;
 	const struct wm_adsp_region *mem;
@@ -401,7 +393,7 @@ static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
 	if (!scratch)
 		return -ENOMEM;
 
-	ret = regmap_raw_write(wm_coeff->regmap, reg, scratch,
+	ret = regmap_raw_write(adsp->regmap, reg, scratch,
 			       ctl->len);
 	if (ret) {
 		adsp_err(adsp, "Failed to write %zu bytes to %x\n",
@@ -434,7 +426,6 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol,
 static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
 				 void *buf, size_t len)
 {
-	struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
 	struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 	struct wm_adsp_alg_region *region = &ctl->region;
 	const struct wm_adsp_region *mem;
@@ -457,7 +448,7 @@ static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
 	if (!scratch)
 		return -ENOMEM;
 
-	ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len);
+	ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
 	if (ret) {
 		adsp_err(adsp, "Failed to read %zu bytes from %x\n",
 			 ctl->len, reg);
@@ -481,37 +472,18 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff,
-				 struct wm_coeff_ctl *ctl,
-				 const struct snd_kcontrol_new *kctl)
-{
-	int ret;
-	struct snd_kcontrol *kcontrol;
-
-	kcontrol = snd_ctl_new1(kctl, wm_coeff);
-	ret = snd_ctl_add(ctl->card, kcontrol);
-	if (ret < 0) {
-		dev_err(wm_coeff->dev, "Failed to add %s: %d\n",
-			kctl->name, ret);
-		return ret;
-	}
-	ctl->kcontrol = kcontrol;
-	return 0;
-}
-
 struct wmfw_ctl_work {
-	struct wm_coeff *wm_coeff;
+	struct wm_adsp *adsp;
 	struct wm_coeff_ctl *ctl;
 	struct work_struct work;
 };
 
-static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
-			struct wm_coeff_ctl *ctl)
+static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl)
 {
 	struct snd_kcontrol_new *kcontrol;
 	int ret;
 
-	if (!wm_coeff || !ctl || !ctl->name || !ctl->card)
+	if (!ctl || !ctl->name)
 		return -EINVAL;
 
 	kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
@@ -525,14 +497,17 @@ static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
 	kcontrol->put = wm_coeff_put;
 	kcontrol->private_value = (unsigned long)ctl;
 
-	ret = wm_coeff_add_kcontrol(wm_coeff,
-				    ctl, kcontrol);
+	ret = snd_soc_add_card_controls(adsp->card,
+					kcontrol, 1);
 	if (ret < 0)
 		goto err_kcontrol;
 
 	kfree(kcontrol);
 
-	list_add(&ctl->list, &wm_coeff->ctl_list);
+	ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card,
+						  ctl->name);
+
+	list_add(&ctl->list, &adsp->ctl_list);
 	return 0;
 
 err_kcontrol:
@@ -753,13 +728,12 @@ out:
 	return ret;
 }
 
-static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
+static int wm_coeff_init_control_caches(struct wm_adsp *adsp)
 {
 	struct wm_coeff_ctl *ctl;
 	int ret;
 
-	list_for_each_entry(ctl, &wm_coeff->ctl_list,
-			    list) {
+	list_for_each_entry(ctl, &adsp->ctl_list, list) {
 		if (!ctl->enabled || ctl->set)
 			continue;
 		ret = wm_coeff_read_control(ctl->kcontrol,
@@ -772,13 +746,12 @@ static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
 	return 0;
 }
 
-static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff)
+static int wm_coeff_sync_controls(struct wm_adsp *adsp)
 {
 	struct wm_coeff_ctl *ctl;
 	int ret;
 
-	list_for_each_entry(ctl, &wm_coeff->ctl_list,
-			    list) {
+	list_for_each_entry(ctl, &adsp->ctl_list, list) {
 		if (!ctl->enabled)
 			continue;
 		if (ctl->set) {
@@ -799,15 +772,14 @@ static void wm_adsp_ctl_work(struct work_struct *work)
 						      struct wmfw_ctl_work,
 						      work);
 
-	wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl);
+	wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl);
 	kfree(ctl_work);
 }
 
-static int wm_adsp_create_control(struct snd_soc_codec *codec,
+static int wm_adsp_create_control(struct wm_adsp *dsp,
 				  const struct wm_adsp_alg_region *region)
 
 {
-	struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
 	struct wm_coeff_ctl *ctl;
 	struct wmfw_ctl_work *ctl_work;
 	char *name;
@@ -842,7 +814,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
 	snprintf(name, PAGE_SIZE, "DSP%d %s %x",
 		 dsp->num, region_name, region->alg);
 
-	list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
+	list_for_each_entry(ctl, &dsp->ctl_list,
 			    list) {
 		if (!strcmp(ctl->name, name)) {
 			if (!ctl->enabled)
@@ -866,7 +838,6 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
 	ctl->set = 0;
 	ctl->ops.xget = wm_coeff_get;
 	ctl->ops.xput = wm_coeff_put;
-	ctl->card = codec->card->snd_card;
 	ctl->adsp = dsp;
 
 	ctl->len = region->len;
@@ -882,7 +853,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
 		goto err_ctl_cache;
 	}
 
-	ctl_work->wm_coeff = dsp->wm_coeff;
+	ctl_work->adsp = dsp;
 	ctl_work->ctl = ctl;
 	INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
 	schedule_work(&ctl_work->work);
@@ -903,7 +874,7 @@ err_name:
 	return ret;
 }
 
-static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
+static int wm_adsp_setup_algs(struct wm_adsp *dsp)
 {
 	struct regmap *regmap = dsp->regmap;
 	struct wmfw_adsp1_id_hdr adsp1_id;
@@ -1091,7 +1062,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
 				region->len -= be32_to_cpu(adsp1_alg[i].dm);
-				wm_adsp_create_control(codec, region);
+				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
 					  be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1108,7 +1079,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
 				region->len -= be32_to_cpu(adsp1_alg[i].zm);
-				wm_adsp_create_control(codec, region);
+				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
 					  be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1137,7 +1108,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
 				region->len -= be32_to_cpu(adsp2_alg[i].xm);
-				wm_adsp_create_control(codec, region);
+				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
 					  be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1154,7 +1125,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
 				region->len -= be32_to_cpu(adsp2_alg[i].ym);
-				wm_adsp_create_control(codec, region);
+				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
 					  be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1171,7 +1142,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
 				region->len -= be32_to_cpu(adsp2_alg[i].zm);
-				wm_adsp_create_control(codec, region);
+				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
 					  be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1391,6 +1362,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 	int ret;
 	int val;
 
+	dsp->card = codec->card;
+
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
@@ -1425,7 +1398,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 		if (ret != 0)
 			goto err;
 
-		ret = wm_adsp_setup_algs(dsp, codec);
+		ret = wm_adsp_setup_algs(dsp);
 		if (ret != 0)
 			goto err;
 
@@ -1434,12 +1407,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 			goto err;
 
 		/* Initialize caches for enabled and unset controls */
-		ret = wm_coeff_init_control_caches(dsp->wm_coeff);
+		ret = wm_coeff_init_control_caches(dsp);
 		if (ret != 0)
 			goto err;
 
 		/* Sync set controls */
-		ret = wm_coeff_sync_controls(dsp->wm_coeff);
+		ret = wm_coeff_sync_controls(dsp);
 		if (ret != 0)
 			goto err;
 
@@ -1460,10 +1433,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 		regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
 				   ADSP1_SYS_ENA, 0);
 
-		list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
-				    list) {
+		list_for_each_entry(ctl, &dsp->ctl_list, list)
 			ctl->enabled = 0;
-		}
 		break;
 
 	default:
@@ -1520,6 +1491,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 	unsigned int val;
 	int ret;
 
+	dsp->card = codec->card;
+
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		/*
@@ -1582,7 +1555,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 		if (ret != 0)
 			goto err;
 
-		ret = wm_adsp_setup_algs(dsp, codec);
+		ret = wm_adsp_setup_algs(dsp);
 		if (ret != 0)
 			goto err;
 
@@ -1591,12 +1564,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 			goto err;
 
 		/* Initialize caches for enabled and unset controls */
-		ret = wm_coeff_init_control_caches(dsp->wm_coeff);
+		ret = wm_coeff_init_control_caches(dsp);
 		if (ret != 0)
 			goto err;
 
 		/* Sync set controls */
-		ret = wm_coeff_sync_controls(dsp->wm_coeff);
+		ret = wm_coeff_sync_controls(dsp);
 		if (ret != 0)
 			goto err;
 
@@ -1637,10 +1610,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 					ret);
 		}
 
-		list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
-				    list) {
+		list_for_each_entry(ctl, &dsp->ctl_list, list)
 			ctl->enabled = 0;
-		}
 
 		while (!list_empty(&dsp->alg_regions)) {
 			alg_region = list_first_entry(&dsp->alg_regions,
@@ -1679,49 +1650,38 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
 	}
 
 	INIT_LIST_HEAD(&adsp->alg_regions);
-
-	adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff),
-				 GFP_KERNEL);
-	if (!adsp->wm_coeff)
-		return -ENOMEM;
-	adsp->wm_coeff->regmap = adsp->regmap;
-	adsp->wm_coeff->dev = adsp->dev;
-	INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list);
+	INIT_LIST_HEAD(&adsp->ctl_list);
 
 	if (dvfs) {
 		adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
 		if (IS_ERR(adsp->dvfs)) {
 			ret = PTR_ERR(adsp->dvfs);
 			dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
-			goto out_coeff;
+			return ret;
 		}
 
 		ret = regulator_enable(adsp->dvfs);
 		if (ret != 0) {
 			dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
 				ret);
-			goto out_coeff;
+			return ret;
 		}
 
 		ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
 		if (ret != 0) {
 			dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
 				ret);
-			goto out_coeff;
+			return ret;
 		}
 
 		ret = regulator_disable(adsp->dvfs);
 		if (ret != 0) {
 			dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
 				ret);
-			goto out_coeff;
+			return ret;
 		}
 	}
 
 	return 0;
-
-out_coeff:
-	kfree(adsp->wm_coeff);
-	return ret;
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 9f922c8..d018dea 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -39,6 +39,7 @@ struct wm_adsp {
 	int type;
 	struct device *dev;
 	struct regmap *regmap;
+	struct snd_soc_card *card;
 
 	int base;
 	int sysclk_reg;
@@ -57,7 +58,7 @@ struct wm_adsp {
 
 	struct regulator *dvfs;
 
-	struct wm_coeff *wm_coeff;
+	struct list_head ctl_list;
 };
 
 #define WM_ADSP1(wname, num) \
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2d9e099..8b50e59 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -699,9 +699,7 @@ EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
 static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	int ret;
 
 	ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
@@ -721,9 +719,7 @@ static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
 static int class_w_put_double(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	int ret;
 
 	ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index aa43854..e15f771 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -98,7 +98,7 @@ endif # SND_POWERPC_SOC
 
 menuconfig SND_IMX_SOC
 	tristate "SoC Audio for Freescale i.MX CPUs"
-	depends on ARCH_MXC
+	depends on ARCH_MXC || COMPILE_TEST
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the i.MX CPUs.
@@ -109,11 +109,11 @@ config SND_SOC_IMX_SSI
 	tristate
 
 config SND_SOC_IMX_PCM_FIQ
-	bool
+	tristate
 	select FIQ
 
 config SND_SOC_IMX_PCM_DMA
-	bool
+	tristate
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_SOC_IMX_AUDMUX
@@ -194,7 +194,7 @@ config SND_SOC_IMX_SGTL5000
 
 config SND_SOC_IMX_MC13783
 	tristate "SoC Audio support for I.MX boards with mc13783"
-	depends on MFD_MC13783
+	depends on MFD_MC13783 && ARM
 	select SND_SOC_IMX_SSI
 	select SND_SOC_IMX_AUDMUX
 	select SND_SOC_MC13783
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 2f2d837..0c072ff 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -8,6 +8,26 @@
  * 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.
+ *
+ *
+ * Some notes why imx-pcm-fiq is used instead of DMA on some boards:
+ *
+ * The i.MX SSI core has some nasty limitations in AC97 mode. While most
+ * sane processor vendors have a FIFO per AC97 slot, the i.MX has only
+ * one FIFO which combines all valid receive slots. We cannot even select
+ * which slots we want to receive. The WM9712 with which this driver
+ * was developed with always sends GPIO status data in slot 12 which
+ * we receive in our (PCM-) data stream. The only chance we have is to
+ * manually skip this data in the FIQ handler. With sampling rates different
+ * from 48000Hz not every frame has valid receive data, so the ratio
+ * between pcm data and GPIO status data changes. Our FIQ handler is not
+ * able to handle this, hence this driver only works with 48000Hz sampling
+ * rate.
+ * Reading and writing AC97 registers is another challenge. The core
+ * provides us status bits when the read register is updated with *another*
+ * value. When we read the same register two times (and the register still
+ * contains the same value) these status bits are not set. We work
+ * around this by not polling these bits but only wait a fixed delay.
  */
 
 #include <linux/init.h>
@@ -36,7 +56,7 @@
 #define read_ssi(addr)			 in_be32(addr)
 #define write_ssi(val, addr)		 out_be32(addr, val)
 #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
-#elif defined ARM
+#else
 #define read_ssi(addr)			 readl(addr)
 #define write_ssi(val, addr)		 writel(val, addr)
 /*
@@ -121,11 +141,13 @@ struct fsl_ssi_private {
 
 	bool new_binding;
 	bool ssi_on_imx;
+	bool use_dma;
 	struct clk *clk;
 	struct snd_dmaengine_dai_dma_data dma_params_tx;
 	struct snd_dmaengine_dai_dma_data dma_params_rx;
 	struct imx_dma_data filter_data_tx;
 	struct imx_dma_data filter_data_rx;
+	struct imx_pcm_fiq_params fiq_params;
 
 	struct {
 		unsigned int rfrc;
@@ -355,7 +377,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
 		 */
 
 		/* Enable the interrupts and DMA requests */
-		write_ssi(SIER_FLAGS, &ssi->sier);
+		if (ssi_private->use_dma)
+			write_ssi(SIER_FLAGS, &ssi->sier);
+		else
+			write_ssi(CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN |
+					CCSR_SSI_SIER_RIE |
+					CCSR_SSI_SIER_RFF0_EN, &ssi->sier);
 
 		/*
 		 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
@@ -510,6 +537,9 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
 			write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
 		else
 			write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
+
+		if ((read_ssi(&ssi->scr) & (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0)
+			write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
 		break;
 
 	default:
@@ -534,22 +564,13 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
 		ssi_private->first_stream = ssi_private->second_stream;
 
 	ssi_private->second_stream = NULL;
-
-	/*
-	 * If this is the last active substream, disable the SSI.
-	 */
-	if (!ssi_private->first_stream) {
-		struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-
-		write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
-	}
 }
 
 static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
 	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
 
-	if (ssi_private->ssi_on_imx) {
+	if (ssi_private->ssi_on_imx && ssi_private->use_dma) {
 		dai->playback_dma_data = &ssi_private->dma_params_tx;
 		dai->capture_dma_data = &ssi_private->dma_params_rx;
 	}
@@ -680,7 +701,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
 	/* The DAI name is the last part of the full name of the node. */
 	p = strrchr(np->full_name, '/') + 1;
-	ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p),
+	ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private) + strlen(p),
 			      GFP_KERNEL);
 	if (!ssi_private) {
 		dev_err(&pdev->dev, "could not allocate DAI object\n");
@@ -689,6 +710,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
 	strcpy(ssi_private->name, p);
 
+	ssi_private->use_dma = !of_property_read_bool(np,
+			"fsl,fiq-stream-filter");
+
 	/* Initialize this copy of the CPU DAI driver structure */
 	memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
 	       sizeof(fsl_ssi_dai_template));
@@ -698,29 +722,31 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 	ret = of_address_to_resource(np, 0, &res);
 	if (ret) {
 		dev_err(&pdev->dev, "could not determine device resources\n");
-		goto error_kmalloc;
+		return ret;
 	}
 	ssi_private->ssi = of_iomap(np, 0);
 	if (!ssi_private->ssi) {
 		dev_err(&pdev->dev, "could not map device resources\n");
-		ret = -ENOMEM;
-		goto error_kmalloc;
+		return -ENOMEM;
 	}
 	ssi_private->ssi_phys = res.start;
 
 	ssi_private->irq = irq_of_parse_and_map(np, 0);
 	if (ssi_private->irq == NO_IRQ) {
 		dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
-		ret = -ENXIO;
-		goto error_iomap;
-	}
-
-	/* The 'name' should not have any slashes in it. */
-	ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name,
-			  ssi_private);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq);
-		goto error_irqmap;
+		return -ENXIO;
+	}
+
+	if (ssi_private->use_dma) {
+		/* The 'name' should not have any slashes in it. */
+		ret = devm_request_irq(&pdev->dev, ssi_private->irq,
+					fsl_ssi_isr, 0, ssi_private->name,
+					ssi_private);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "could not claim irq %u\n",
+					ssi_private->irq);
+			goto error_irqmap;
+		}
 	}
 
 	/* Are the RX and the TX clocks locked? */
@@ -739,13 +765,18 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 		u32 dma_events[2];
 		ssi_private->ssi_on_imx = true;
 
-		ssi_private->clk = clk_get(&pdev->dev, NULL);
+		ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
 		if (IS_ERR(ssi_private->clk)) {
 			ret = PTR_ERR(ssi_private->clk);
 			dev_err(&pdev->dev, "could not get clock: %d\n", ret);
-			goto error_irq;
+			goto error_irqmap;
+		}
+		ret = clk_prepare_enable(ssi_private->clk);
+		if (ret) {
+			dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n",
+				ret);
+			goto error_irqmap;
 		}
-		clk_prepare_enable(ssi_private->clk);
 
 		/*
 		 * We have burstsize be "fifo_depth - 2" to match the SSI
@@ -763,24 +794,28 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 			&ssi_private->filter_data_tx;
 		ssi_private->dma_params_rx.filter_data =
 			&ssi_private->filter_data_rx;
-		/*
-		 * TODO: This is a temporary solution and should be changed
-		 * to use generic DMA binding later when the helplers get in.
-		 */
-		ret = of_property_read_u32_array(pdev->dev.of_node,
+		if (!of_property_read_bool(pdev->dev.of_node, "dmas") &&
+				ssi_private->use_dma) {
+			/*
+			 * FIXME: This is a temporary solution until all
+			 * necessary dma drivers support the generic dma
+			 * bindings.
+			 */
+			ret = of_property_read_u32_array(pdev->dev.of_node,
 					"fsl,ssi-dma-events", dma_events, 2);
-		if (ret) {
-			dev_err(&pdev->dev, "could not get dma events\n");
-			goto error_clk;
+			if (ret && ssi_private->use_dma) {
+				dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n");
+				goto error_clk;
+			}
 		}
 
 		shared = of_device_is_compatible(of_get_parent(np),
 			    "fsl,spba-bus");
 
 		imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
-			dma_events[0], shared);
+			dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
 		imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
-			dma_events[1], shared);
+			dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
 	}
 
 	/* Initialize the the device_attribute structure */
@@ -794,7 +829,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 	if (ret) {
 		dev_err(&pdev->dev, "could not create sysfs %s file\n",
 			ssi_private->dev_attr.attr.name);
-		goto error_irq;
+		goto error_clk;
 	}
 
 	/* Register with ASoC */
@@ -808,9 +843,30 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 	}
 
 	if (ssi_private->ssi_on_imx) {
-		ret = imx_pcm_dma_init(pdev);
-		if (ret)
-			goto error_dev;
+		if (!ssi_private->use_dma) {
+
+			/*
+			 * Some boards use an incompatible codec. To get it
+			 * working, we are using imx-fiq-pcm-audio, that
+			 * can handle those codecs. DMA is not possible in this
+			 * situation.
+			 */
+
+			ssi_private->fiq_params.irq = ssi_private->irq;
+			ssi_private->fiq_params.base = ssi_private->ssi;
+			ssi_private->fiq_params.dma_params_rx =
+				&ssi_private->dma_params_rx;
+			ssi_private->fiq_params.dma_params_tx =
+				&ssi_private->dma_params_tx;
+
+			ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
+			if (ret)
+				goto error_dev;
+		} else {
+			ret = imx_pcm_dma_init(pdev);
+			if (ret)
+				goto error_dev;
+		}
 	}
 
 	/*
@@ -857,23 +913,12 @@ error_dev:
 	device_remove_file(&pdev->dev, dev_attr);
 
 error_clk:
-	if (ssi_private->ssi_on_imx) {
+	if (ssi_private->ssi_on_imx)
 		clk_disable_unprepare(ssi_private->clk);
-		clk_put(ssi_private->clk);
-	}
-
-error_irq:
-	free_irq(ssi_private->irq, ssi_private);
 
 error_irqmap:
 	irq_dispose_mapping(ssi_private->irq);
 
-error_iomap:
-	iounmap(ssi_private->ssi);
-
-error_kmalloc:
-	kfree(ssi_private);
-
 	return ret;
 }
 
@@ -886,15 +931,10 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 	if (ssi_private->ssi_on_imx) {
 		imx_pcm_dma_exit(pdev);
 		clk_disable_unprepare(ssi_private->clk);
-		clk_put(ssi_private->clk);
 	}
 	snd_soc_unregister_component(&pdev->dev);
 	device_remove_file(&pdev->dev, &ssi_private->dev_attr);
-
-	free_irq(ssi_private->irq, ssi_private);
 	irq_dispose_mapping(ssi_private->irq);
-
-	kfree(ssi_private);
 	dev_set_drvdata(&pdev->dev, NULL);
 
 	return 0;
@@ -919,6 +959,7 @@ static struct platform_driver fsl_ssi_driver = {
 
 module_platform_driver(fsl_ssi_driver);
 
+MODULE_ALIAS("platform:fsl-ssi-dai");
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index e260f1f..103d1b0 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -73,8 +73,11 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 	if (!buf)
 		return -ENOMEM;
 
-	if (audmux_clk)
-		clk_prepare_enable(audmux_clk);
+	if (audmux_clk) {
+		ret = clk_prepare_enable(audmux_clk);
+		if (ret)
+			return ret;
+	}
 
 	ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
 	pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
@@ -224,14 +227,19 @@ EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
 int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
 		unsigned int pdcr)
 {
+	int ret;
+
 	if (audmux_type != IMX31_AUDMUX)
 		return -EINVAL;
 
 	if (!audmux_base)
 		return -ENOSYS;
 
-	if (audmux_clk)
-		clk_prepare_enable(audmux_clk);
+	if (audmux_clk) {
+		ret = clk_prepare_enable(audmux_clk);
+		if (ret)
+			return ret;
+	}
 
 	writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
 	writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
@@ -243,6 +251,66 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
 }
 EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
 
+static int imx_audmux_parse_dt_defaults(struct platform_device *pdev,
+		struct device_node *of_node)
+{
+	struct device_node *child;
+
+	for_each_available_child_of_node(of_node, child) {
+		unsigned int port;
+		unsigned int ptcr = 0;
+		unsigned int pdcr = 0;
+		unsigned int pcr = 0;
+		unsigned int val;
+		int ret;
+		int i = 0;
+
+		ret = of_property_read_u32(child, "fsl,audmux-port", &port);
+		if (ret) {
+			dev_warn(&pdev->dev, "Failed to get fsl,audmux-port of child node \"%s\"\n",
+					child->full_name);
+			continue;
+		}
+		if (!of_property_read_bool(child, "fsl,port-config")) {
+			dev_warn(&pdev->dev, "child node \"%s\" does not have property fsl,port-config\n",
+					child->full_name);
+			continue;
+		}
+
+		for (i = 0; (ret = of_property_read_u32_index(child,
+					"fsl,port-config\n", i, &val)) == 0;
+				++i) {
+			if (audmux_type == IMX31_AUDMUX) {
+				if (i % 2)
+					pdcr |= val;
+				else
+					ptcr |= val;
+			} else {
+				pcr |= val;
+			}
+		}
+
+		if (ret != -ENODATA) {
+			dev_err(&pdev->dev, "Failed to read u32 at index %d of child %s\n",
+					i, child->full_name);
+			continue;
+		}
+
+		if (audmux_type == IMX31_AUDMUX) {
+			if (i % 2) {
+				dev_err(&pdev->dev, "One pdcr value is missing in child node %s\n",
+						child->full_name);
+				continue;
+			}
+			imx_audmux_v2_configure_port(port, ptcr, pdcr);
+		} else {
+			imx_audmux_v1_configure_port(port, pcr);
+		}
+	}
+
+	return 0;
+}
+
 static int imx_audmux_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -267,6 +335,8 @@ static int imx_audmux_probe(struct platform_device *pdev)
 	if (audmux_type == IMX31_AUDMUX)
 		audmux_debugfs_init();
 
+	imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node);
+
 	return 0;
 }
 
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index 9df173c..a3d60d4 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -90,6 +90,7 @@ static const struct snd_soc_dapm_route imx_mc13783_routes[] = {
 
 static struct snd_soc_card imx_mc13783 = {
 	.name		= "imx_mc13783",
+	.owner		= THIS_MODULE,
 	.dai_link	= imx_mc13783_dai_mc13783,
 	.num_links	= ARRAY_SIZE(imx_mc13783_dai_mc13783),
 	.dapm_widgets	= imx_mc13783_widget,
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index fde4d2e..f323ce0 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -64,7 +64,6 @@ int imx_pcm_dma_init(struct platform_device *pdev)
 {
 	return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config,
 		SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
-		SND_DMAENGINE_PCM_FLAG_NO_DT |
 		SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 310d902..3b2ba99 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 
 #include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -32,6 +33,7 @@
 #include <linux/platform_data/asoc-imx-ssi.h>
 
 #include "imx-ssi.h"
+#include "imx-pcm.h"
 
 struct imx_pcm_runtime_data {
 	unsigned int period;
@@ -366,9 +368,9 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
 	.pcm_free	= imx_pcm_fiq_free,
 };
 
-int imx_pcm_fiq_init(struct platform_device *pdev)
+int imx_pcm_fiq_init(struct platform_device *pdev,
+		struct imx_pcm_fiq_params *params)
 {
-	struct imx_ssi *ssi = platform_get_drvdata(pdev);
 	int ret;
 
 	ret = claim_fiq(&fh);
@@ -377,15 +379,15 @@ int imx_pcm_fiq_init(struct platform_device *pdev)
 		return ret;
 	}
 
-	mxc_set_irq_fiq(ssi->irq, 1);
-	ssi_irq = ssi->irq;
+	mxc_set_irq_fiq(params->irq, 1);
+	ssi_irq = params->irq;
 
-	imx_pcm_fiq = ssi->irq;
+	imx_pcm_fiq = params->irq;
 
-	imx_ssi_fiq_base = (unsigned long)ssi->base;
+	imx_ssi_fiq_base = (unsigned long)params->base;
 
-	ssi->dma_params_tx.maxburst = 4;
-	ssi->dma_params_rx.maxburst = 6;
+	params->dma_params_tx->maxburst = 4;
+	params->dma_params_rx->maxburst = 6;
 
 	ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
 	if (ret)
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index 67f656c..5d5b733 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -22,17 +22,23 @@
 
 static inline void
 imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data,
-	int dma, bool shared)
+	int dma, enum sdma_peripheral_type peripheral_type)
 {
 	dma_data->dma_request = dma;
 	dma_data->priority = DMA_PRIO_HIGH;
-	if (shared)
-		dma_data->peripheral_type = IMX_DMATYPE_SSI_SP;
-	else
-		dma_data->peripheral_type = IMX_DMATYPE_SSI;
+	dma_data->peripheral_type = peripheral_type;
 }
 
-#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
+struct imx_pcm_fiq_params {
+	int irq;
+	void __iomem *base;
+
+	/* Pointer to original ssi driver to setup tx rx sizes */
+	struct snd_dmaengine_dai_dma_data *dma_params_rx;
+	struct snd_dmaengine_dai_dma_data *dma_params_tx;
+};
+
+#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
 int imx_pcm_dma_init(struct platform_device *pdev);
 void imx_pcm_dma_exit(struct platform_device *pdev);
 #else
@@ -46,11 +52,13 @@ static inline void imx_pcm_dma_exit(struct platform_device *pdev)
 }
 #endif
 
-#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
-int imx_pcm_fiq_init(struct platform_device *pdev);
+#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
+int imx_pcm_fiq_init(struct platform_device *pdev,
+		struct imx_pcm_fiq_params *params);
 void imx_pcm_fiq_exit(struct platform_device *pdev);
 #else
-static inline int imx_pcm_fiq_init(struct platform_device *pdev)
+static inline int imx_pcm_fiq_init(struct platform_device *pdev,
+		struct imx_pcm_fiq_params *params)
 {
 	return -ENODEV;
 }
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 3f726e4..389cbfa 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -129,8 +129,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
 	}
 
 	data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
-	if (IS_ERR(data->codec_clk))
+	if (IS_ERR(data->codec_clk)) {
+		ret = PTR_ERR(data->codec_clk);
 		goto fail;
+	}
 
 	data->clk_frequency = clk_get_rate(data->codec_clk);
 
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index 51be377..f58bcd8 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -571,13 +571,13 @@ static int imx_ssi_probe(struct platform_device *pdev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
 	if (res) {
 		imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start,
-			false);
+			IMX_DMATYPE_SSI);
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0");
 	if (res) {
 		imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start,
-			false);
+			IMX_DMATYPE_SSI);
 	}
 
 	platform_set_drvdata(pdev, ssi);
@@ -595,7 +595,12 @@ static int imx_ssi_probe(struct platform_device *pdev)
 		goto failed_register;
 	}
 
-	ret = imx_pcm_fiq_init(pdev);
+	ssi->fiq_params.irq = ssi->irq;
+	ssi->fiq_params.base = ssi->base;
+	ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx;
+	ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx;
+
+	ret = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
 	if (ret)
 		goto failed_pcm_fiq;
 
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index d5003ce..fb1616b 100644
--- a/sound/soc/fsl/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
@@ -209,6 +209,7 @@ struct imx_ssi {
 	struct snd_dmaengine_dai_dma_data dma_params_tx;
 	struct imx_dma_data filter_data_tx;
 	struct imx_dma_data filter_data_rx;
+	struct imx_pcm_fiq_params fiq_params;
 
 	int enabled;
 };
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 52a36a9..1d70e27 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -217,7 +217,8 @@ static int imx_wm8962_probe(struct platform_device *pdev)
 	codec_dev = of_find_i2c_device_by_node(codec_np);
 	if (!codec_dev || !codec_dev->driver) {
 		dev_err(&pdev->dev, "failed to find codec platform device\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto fail;
 	}
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index c62d715..9e1970c 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,19 +1,15 @@
 config SND_KIRKWOOD_SOC
 	tristate "SoC Audio for the Marvell Kirkwood chip"
-	depends on ARCH_KIRKWOOD
+	depends on ARCH_KIRKWOOD || COMPILE_TEST
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the Kirkwood I2S interface. You will also need to select the
 	  audio interfaces to support below.
 
-config SND_KIRKWOOD_SOC_I2S
-	tristate
-
 config SND_KIRKWOOD_SOC_OPENRD
 	tristate "SoC Audio support for Kirkwood Openrd Client"
-	depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE)
+	depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST)
 	depends on I2C
-	select SND_KIRKWOOD_SOC_I2S
 	select SND_SOC_CS42L51
 	help
 	  Say Y if you want to add support for SoC audio on
@@ -21,8 +17,7 @@ config SND_KIRKWOOD_SOC_OPENRD
 
 config SND_KIRKWOOD_SOC_T5325
 	tristate "SoC Audio support for HP t5325"
-	depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C
-	select SND_KIRKWOOD_SOC_I2S
+	depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C
 	select SND_SOC_ALC5623
 	help
 	  Say Y if you want to add support for SoC audio on
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile
index 3e62ae9..9e78138 100644
--- a/sound/soc/kirkwood/Makefile
+++ b/sound/soc/kirkwood/Makefile
@@ -1,8 +1,6 @@
-snd-soc-kirkwood-objs := kirkwood-dma.o
-snd-soc-kirkwood-i2s-objs := kirkwood-i2s.o
+snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o
 
 obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o
-obj-$(CONFIG_SND_KIRKWOOD_SOC_I2S) += snd-soc-kirkwood-i2s.o
 
 snd-soc-openrd-objs := kirkwood-openrd.o
 snd-soc-t5325-objs := kirkwood-t5325.o
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index a9f1453..b238434 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -33,11 +33,11 @@
 	 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
 	 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
 
-struct kirkwood_dma_priv {
-	struct snd_pcm_substream *play_stream;
-	struct snd_pcm_substream *rec_stream;
-	struct kirkwood_dma_data *data;
-};
+static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = subs->private_data;
+	return snd_soc_dai_get_drvdata(soc_runtime->cpu_dai);
+}
 
 static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
 	.info = (SNDRV_PCM_INFO_INTERLEAVED |
@@ -51,7 +51,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
 	.rate_max		= 384000,
 	.channels_min		= 1,
 	.channels_max		= 8,
-	.buffer_bytes_max	= KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS,
+	.buffer_bytes_max	= KIRKWOOD_SND_MAX_BUFFER_BYTES,
 	.period_bytes_min	= KIRKWOOD_SND_MIN_PERIOD_BYTES,
 	.period_bytes_max	= KIRKWOOD_SND_MAX_PERIOD_BYTES,
 	.periods_min		= KIRKWOOD_SND_MIN_PERIODS,
@@ -63,8 +63,7 @@ static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
 
 static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
 {
-	struct kirkwood_dma_priv *prdata = dev_id;
-	struct kirkwood_dma_data *priv = prdata->data;
+	struct kirkwood_dma_data *priv = dev_id;
 	unsigned long mask, status, cause;
 
 	mask = readl(priv->io + KIRKWOOD_INT_MASK);
@@ -89,10 +88,10 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
 	writel(status, priv->io + KIRKWOOD_INT_CAUSE);
 
 	if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES)
-		snd_pcm_period_elapsed(prdata->play_stream);
+		snd_pcm_period_elapsed(priv->substream_play);
 
 	if (status & KIRKWOOD_INT_CAUSE_REC_BYTES)
-		snd_pcm_period_elapsed(prdata->rec_stream);
+		snd_pcm_period_elapsed(priv->substream_rec);
 
 	return IRQ_HANDLED;
 }
@@ -126,15 +125,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
 {
 	int err;
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-	struct snd_soc_platform *platform = soc_runtime->platform;
-	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
-	struct kirkwood_dma_data *priv;
-	struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
+	struct kirkwood_dma_data *priv = kirkwood_priv(substream);
 	const struct mbus_dram_target_info *dram;
 	unsigned long addr;
 
-	priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
 	snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw);
 
 	/* Ensure that all constraints linked to dma burst are fulfilled */
@@ -157,21 +151,11 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
 	if (err < 0)
 		return err;
 
-	if (prdata == NULL) {
-		prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL);
-		if (prdata == NULL)
-			return -ENOMEM;
-
-		prdata->data = priv;
-
+	if (!priv->substream_play && !priv->substream_rec) {
 		err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED,
-				  "kirkwood-i2s", prdata);
-		if (err) {
-			kfree(prdata);
+				  "kirkwood-i2s", priv);
+		if (err)
 			return -EBUSY;
-		}
-
-		snd_soc_platform_set_drvdata(platform, prdata);
 
 		/*
 		 * Enable Error interrupts. We're only ack'ing them but
@@ -183,11 +167,11 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
 	dram = mv_mbus_dram_info();
 	addr = substream->dma_buffer.addr;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		prdata->play_stream = substream;
+		priv->substream_play = substream;
 		kirkwood_dma_conf_mbus_windows(priv->io,
 			KIRKWOOD_PLAYBACK_WIN, addr, dram);
 	} else {
-		prdata->rec_stream = substream;
+		priv->substream_rec = substream;
 		kirkwood_dma_conf_mbus_windows(priv->io,
 			KIRKWOOD_RECORD_WIN, addr, dram);
 	}
@@ -197,27 +181,19 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
 
 static int kirkwood_dma_close(struct snd_pcm_substream *substream)
 {
-	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
-	struct snd_soc_platform *platform = soc_runtime->platform;
-	struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
-	struct kirkwood_dma_data *priv;
-
-	priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
+	struct kirkwood_dma_data *priv = kirkwood_priv(substream);
 
-	if (!prdata || !priv)
+	if (!priv)
 		return 0;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prdata->play_stream = NULL;
+		priv->substream_play = NULL;
 	else
-		prdata->rec_stream = NULL;
+		priv->substream_rec = NULL;
 
-	if (!prdata->play_stream && !prdata->rec_stream) {
+	if (!priv->substream_play && !priv->substream_rec) {
 		writel(0, priv->io + KIRKWOOD_ERR_MASK);
-		free_irq(priv->irq, prdata);
-		kfree(prdata);
-		snd_soc_platform_set_drvdata(platform, NULL);
+		free_irq(priv->irq, priv);
 	}
 
 	return 0;
@@ -243,13 +219,9 @@ static int kirkwood_dma_hw_free(struct snd_pcm_substream *substream)
 static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
-	struct kirkwood_dma_data *priv;
+	struct kirkwood_dma_data *priv = kirkwood_priv(substream);
 	unsigned long size, count;
 
-	priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
-
 	/* compute buffer size in term of "words" as requested in specs */
 	size = frames_to_bytes(runtime, runtime->buffer_size);
 	size = (size>>2)-1;
@@ -272,13 +244,9 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
 static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
 						*substream)
 {
-	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
-	struct kirkwood_dma_data *priv;
+	struct kirkwood_dma_data *priv = kirkwood_priv(substream);
 	snd_pcm_uframes_t count;
 
-	priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
-
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		count = bytes_to_frames(substream->runtime,
 			readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT));
@@ -366,36 +334,8 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
 	}
 }
 
-static struct snd_soc_platform_driver kirkwood_soc_platform = {
+struct snd_soc_platform_driver kirkwood_soc_platform = {
 	.ops		= &kirkwood_dma_ops,
 	.pcm_new	= kirkwood_dma_new,
 	.pcm_free	= kirkwood_dma_free_dma_buffers,
 };
-
-static int kirkwood_soc_platform_probe(struct platform_device *pdev)
-{
-	return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
-}
-
-static int kirkwood_soc_platform_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_platform(&pdev->dev);
-	return 0;
-}
-
-static struct platform_driver kirkwood_pcm_driver = {
-	.driver = {
-			.name = "kirkwood-pcm-audio",
-			.owner = THIS_MODULE,
-	},
-
-	.probe = kirkwood_soc_platform_probe,
-	.remove = kirkwood_soc_platform_remove,
-};
-
-module_platform_driver(kirkwood_pcm_driver);
-
-MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
-MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:kirkwood-pcm-audio");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 4c9dad3..e5f3f7a 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -24,11 +24,8 @@
 #include <linux/platform_data/asoc-kirkwood.h>
 #include "kirkwood.h"
 
-#define DRV_NAME	"kirkwood-i2s"
+#define DRV_NAME	"mvebu-audio"
 
-#define KIRKWOOD_I2S_RATES \
-	(SNDRV_PCM_RATE_44100 | \
-	 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 #define KIRKWOOD_I2S_FORMATS \
 	(SNDRV_PCM_FMTBIT_S16_LE | \
 	 SNDRV_PCM_FMTBIT_S24_LE | \
@@ -105,14 +102,16 @@ static void kirkwood_set_rate(struct snd_soc_dai *dai,
 	uint32_t clks_ctrl;
 
 	if (rate == 44100 || rate == 48000 || rate == 96000) {
-		/* use internal dco for supported rates */
+		/* use internal dco for the supported rates
+		 * defined in kirkwood_i2s_dai */
 		dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
 			__func__, rate);
 		kirkwood_set_dco(priv->io, rate);
 
 		clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
-	} else if (!IS_ERR(priv->extclk)) {
-		/* use optional external clk for other rates */
+	} else {
+		/* use the external clock for the other rates
+		 * defined in kirkwood_i2s_dai_extclk */
 		dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
 			__func__, rate, 256 * rate);
 		clk_set_rate(priv->extclk, 256 * rate);
@@ -199,8 +198,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
 			ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
 
 		priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
-				    KIRKWOOD_PLAYCTL_I2S_EN |
-				    KIRKWOOD_PLAYCTL_SPDIF_EN |
+				    KIRKWOOD_PLAYCTL_ENABLE_MASK |
 				    KIRKWOOD_PLAYCTL_SIZE_MASK);
 		priv->ctl_play |= ctl_play;
 	} else {
@@ -244,8 +242,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_START:
 		/* configure */
 		ctl = priv->ctl_play;
-		value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN |
-				KIRKWOOD_PLAYCTL_SPDIF_EN);
+		value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 		writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
 		/* enable interrupts */
@@ -267,7 +264,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 		writel(value, priv->io + KIRKWOOD_INT_MASK);
 
 		/* disable all playbacks */
-		ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
+		ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 		break;
 
@@ -387,7 +384,7 @@ static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
 
 	/* disable playback/record */
 	value = readl(priv->io + KIRKWOOD_PLAYCTL);
-	value &= ~(KIRKWOOD_PLAYCTL_I2S_EN|KIRKWOOD_PLAYCTL_SPDIF_EN);
+	value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 	writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
 	value = readl(priv->io + KIRKWOOD_RECCTL);
@@ -398,11 +395,6 @@ static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
 
 }
 
-static int kirkwood_i2s_remove(struct snd_soc_dai *dai)
-{
-	return 0;
-}
-
 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
 	.startup	= kirkwood_i2s_startup,
 	.trigger	= kirkwood_i2s_trigger,
@@ -413,17 +405,18 @@ static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
 
 static struct snd_soc_dai_driver kirkwood_i2s_dai = {
 	.probe = kirkwood_i2s_probe,
-	.remove = kirkwood_i2s_remove,
 	.playback = {
 		.channels_min = 1,
 		.channels_max = 2,
-		.rates = KIRKWOOD_I2S_RATES,
+		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+				SNDRV_PCM_RATE_96000,
 		.formats = KIRKWOOD_I2S_FORMATS,
 	},
 	.capture = {
 		.channels_min = 1,
 		.channels_max = 2,
-		.rates = KIRKWOOD_I2S_RATES,
+		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+				SNDRV_PCM_RATE_96000,
 		.formats = KIRKWOOD_I2S_FORMATS,
 	},
 	.ops = &kirkwood_i2s_dai_ops,
@@ -431,7 +424,6 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
 
 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
 	.probe = kirkwood_i2s_probe,
-	.remove = kirkwood_i2s_remove,
 	.playback = {
 		.channels_min = 1,
 		.channels_max = 2,
@@ -498,10 +490,10 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	priv->extclk = clk_get(&pdev->dev, "extclk");
+	priv->extclk = devm_clk_get(&pdev->dev, "extclk");
 	if (!IS_ERR(priv->extclk)) {
 		if (priv->extclk == priv->clk) {
-			clk_put(priv->extclk);
+			devm_clk_put(&pdev->dev, priv->extclk);
 			priv->extclk = ERR_PTR(-EINVAL);
 		} else {
 			dev_info(&pdev->dev, "found external clock\n");
@@ -525,14 +517,22 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 
 	err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
 					 soc_dai, 1);
-	if (!err)
-		return 0;
-	dev_err(&pdev->dev, "snd_soc_register_component failed\n");
+	if (err) {
+		dev_err(&pdev->dev, "snd_soc_register_component failed\n");
+		goto err_component;
+	}
 
-	if (!IS_ERR(priv->extclk)) {
-		clk_disable_unprepare(priv->extclk);
-		clk_put(priv->extclk);
+	err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
+	if (err) {
+		dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
+		goto err_platform;
 	}
+	return 0;
+ err_platform:
+	snd_soc_unregister_component(&pdev->dev);
+ err_component:
+	if (!IS_ERR(priv->extclk))
+		clk_disable_unprepare(priv->extclk);
 	clk_disable_unprepare(priv->clk);
 
 	return err;
@@ -542,12 +542,11 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 {
 	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
 
+	snd_soc_unregister_platform(&pdev->dev);
 	snd_soc_unregister_component(&pdev->dev);
 
-	if (!IS_ERR(priv->extclk)) {
+	if (!IS_ERR(priv->extclk))
 		clk_disable_unprepare(priv->extclk);
-		clk_put(priv->extclk);
-	}
 	clk_disable_unprepare(priv->clk);
 
 	return 0;
@@ -568,4 +567,4 @@ module_platform_driver(kirkwood_i2s_driver);
 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:kirkwood-i2s");
+MODULE_ALIAS("platform:mvebu-audio");
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index b979c71..025be0e 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -16,9 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <mach/kirkwood.h>
 #include <linux/platform_data/asoc-kirkwood.h>
-#include <asm/mach-types.h>
 #include "../codecs/cs42l51.h"
 
 static int openrd_client_hw_params(struct snd_pcm_substream *substream,
@@ -54,8 +52,8 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
 {
 	.name = "CS42L51",
 	.stream_name = "CS42L51 HiFi",
-	.cpu_dai_name = "kirkwood-i2s",
-	.platform_name = "kirkwood-pcm-audio",
+	.cpu_dai_name = "mvebu-audio",
+	.platform_name = "mvebu-audio",
 	.codec_dai_name = "cs42l51-hifi",
 	.codec_name = "cs42l51-codec.0-004a",
 	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index 1d0ed6f..27545b0 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -15,9 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <mach/kirkwood.h>
 #include <linux/platform_data/asoc-kirkwood.h>
-#include <asm/mach-types.h>
 #include "../codecs/alc5623.h"
 
 static int t5325_hw_params(struct snd_pcm_substream *substream,
@@ -70,8 +68,8 @@ static struct snd_soc_dai_link t5325_dai[] = {
 {
 	.name = "ALC5621",
 	.stream_name = "ALC5621 HiFi",
-	.cpu_dai_name = "kirkwood-i2s",
-	.platform_name = "kirkwood-pcm-audio",
+	.cpu_dai_name = "mvebu-audio",
+	.platform_name = "mvebu-audio",
 	.codec_dai_name = "alc5621-hifi",
 	.codec_name = "alc562x-codec.0-001a",
 	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index 4d92637..f8e1ccc 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -54,7 +54,7 @@
 #define KIRKWOOD_PLAYCTL_MONO_OFF		(0<<5)
 #define KIRKWOOD_PLAYCTL_I2S_MUTE		(1<<7)
 #define KIRKWOOD_PLAYCTL_SPDIF_EN		(1<<4)
-#define KIRKWOOD_PLAYCTL_I2S_EN		(1<<3)
+#define KIRKWOOD_PLAYCTL_I2S_EN			(1<<3)
 #define KIRKWOOD_PLAYCTL_SIZE_MASK		(7<<0)
 #define KIRKWOOD_PLAYCTL_SIZE_16		(7<<0)
 #define KIRKWOOD_PLAYCTL_SIZE_16_C		(3<<0)
@@ -62,6 +62,9 @@
 #define KIRKWOOD_PLAYCTL_SIZE_24		(1<<0)
 #define KIRKWOOD_PLAYCTL_SIZE_32		(0<<0)
 
+#define KIRKWOOD_PLAYCTL_ENABLE_MASK		(KIRKWOOD_PLAYCTL_SPDIF_EN | \
+						 KIRKWOOD_PLAYCTL_I2S_EN)
+
 #define KIRKWOOD_PLAY_BUF_ADDR			0x1104
 #define KIRKWOOD_PLAY_BUF_SIZE			0x1108
 #define KIRKWOOD_PLAY_BYTE_COUNT		0x110C
@@ -122,6 +125,8 @@
 #define KIRKWOOD_SND_MAX_PERIODS		16
 #define KIRKWOOD_SND_MIN_PERIOD_BYTES		0x4000
 #define KIRKWOOD_SND_MAX_PERIOD_BYTES		0x4000
+#define KIRKWOOD_SND_MAX_BUFFER_BYTES		(KIRKWOOD_SND_MAX_PERIOD_BYTES \
+						 * KIRKWOOD_SND_MAX_PERIODS)
 
 struct kirkwood_dma_data {
 	void __iomem *io;
@@ -129,8 +134,12 @@ struct kirkwood_dma_data {
 	struct clk *extclk;
 	uint32_t ctl_play;
 	uint32_t ctl_rec;
+	struct snd_pcm_substream *substream_play;
+	struct snd_pcm_substream *substream_rec;
 	int irq;
 	int burst;
 };
 
+extern struct snd_soc_platform_driver kirkwood_soc_platform;
+
 #endif
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index 78d321c..219235c 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,6 +1,7 @@
 menuconfig SND_MXS_SOC
 	tristate "SoC Audio for Freescale MXS CPUs"
-	depends on ARCH_MXS
+	depends on ARCH_MXS || COMPILE_TEST
+	depends on COMMON_CLK
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	  Say Y or M if you want to add support for codecs attached to
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 54511c5..b56b8a0 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -31,7 +31,6 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include <asm/mach-types.h>
 
 #include "mxs-saif.h"
 
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 1b134d7..ce084eb 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -25,7 +25,6 @@
 #include <sound/soc.h>
 #include <sound/jack.h>
 #include <sound/soc-dapm.h>
-#include <asm/mach-types.h>
 
 #include "../codecs/sgtl5000.h"
 #include "mxs-saif.h"
@@ -51,18 +50,27 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* Sgtl5000 sysclk should be >= 8MHz and <= 27M */
-	if (mclk < 8000000 || mclk > 27000000)
+	if (mclk < 8000000 || mclk > 27000000) {
+		dev_err(codec_dai->dev, "Invalid mclk frequency: %u.%03uMHz\n",
+			mclk / 1000000, mclk / 1000 % 1000);
 		return -EINVAL;
+	}
 
 	/* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */
 	ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0);
-	if (ret)
+	if (ret) {
+		dev_err(codec_dai->dev, "Failed to set sysclk to %u.%03uMHz\n",
+			mclk / 1000000, mclk / 1000 % 1000);
 		return ret;
+	}
 
 	/* The SAIF MCLK should be the same as SGTL5000_SYSCLK */
 	ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0);
-	if (ret)
+	if (ret) {
+		dev_err(cpu_dai->dev, "Failed to set sysclk to %u.%03uMHz\n",
+			mclk / 1000000, mclk / 1000 % 1000);
 		return ret;
+	}
 
 	/* set codec to slave mode */
 	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
@@ -70,13 +78,19 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream,
 
 	/* set codec DAI configuration */
 	ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
-	if (ret)
+	if (ret) {
+		dev_err(codec_dai->dev, "Failed to set dai format to %08x\n",
+			dai_format);
 		return ret;
+	}
 
 	/* set cpu DAI configuration */
 	ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
-	if (ret)
+	if (ret) {
+		dev_err(cpu_dai->dev, "Failed to set dai format to %08x\n",
+			dai_format);
 		return ret;
+	}
 
 	return 0;
 }
@@ -154,8 +168,10 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev)
 	 * should be >= 8MHz and <= 27M.
 	 */
 	ret = mxs_saif_get_mclk(0, 44100 * 256, 44100);
-	if (ret)
+	if (ret) {
+		dev_err(&pdev->dev, "failed to get mclk\n");
 		return ret;
+	}
 
 	card->dev = &pdev->dev;
 	platform_set_drvdata(pdev, card);
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index f4c2417..8987bf9 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -333,9 +333,6 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev)
 	spin_lock_init(&nuc900_audio->lock);
 
 	nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!nuc900_audio->res)
-		return ret;
-
 	nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev,
 						   nuc900_audio->res);
 	if (IS_ERR(nuc900_audio->mmio))
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 9f5d55e..44b5acf 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,6 +1,6 @@
 config SND_OMAP_SOC
 	tristate "SoC Audio for the Texas Instruments OMAP chips"
-	depends on ARCH_OMAP && DMA_OMAP
+	depends on (ARCH_OMAP && DMA_OMAP) || (ARCH_ARM && COMPILE_TEST)
 	select SND_SOC_DMAENGINE_PCM
 
 config SND_OMAP_SOC_DMIC
@@ -26,7 +26,7 @@ config SND_OMAP_SOC_N810
 
 config SND_OMAP_SOC_RX51
 	tristate "SoC Audio support for Nokia RX-51"
-	depends on SND_OMAP_SOC && MACH_NOKIA_RX51
+	depends on SND_OMAP_SOC && ARCH_ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_TLV320AIC3X
 	select SND_SOC_TPA6130A2
@@ -87,7 +87,7 @@ config SND_OMAP_SOC_OMAP_TWL4030
 
 config SND_OMAP_SOC_OMAP_ABE_TWL6040
 	tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
-	depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4
+	depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST)
 	select SND_OMAP_SOC_DMIC
 	select SND_OMAP_SOC_MCPDM
 	select SND_SOC_TWL6040
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index 361e4c0..83433fd 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -781,7 +781,7 @@ static ssize_t prop##_store(struct device *dev,				\
 	unsigned long val;						\
 	int status;							\
 									\
-	status = strict_strtoul(buf, 0, &val);				\
+	status = kstrtoul(buf, 0, &val);				\
 	if (status)							\
 		return status;						\
 									\
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index 70cd5c7..ebb1390 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/twl6040.h>
-#include <linux/platform_data/omap-abe-twl6040.h>
 #include <linux/module.h>
 #include <linux/of.h>
 
@@ -166,19 +165,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"AFMR", NULL, "Line In"},
 };
 
-static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm,
-					  int connected, char *pin)
-{
-	if (!connected)
-		snd_soc_dapm_disable_pin(dapm, pin);
-}
-
 static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_card *card = codec->card;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
 	struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
 	int hs_trim;
 	int ret = 0;
@@ -203,24 +193,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 		twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
 	}
 
-	/*
-	 * NULL pdata means we booted with DT. In this case the routing is
-	 * provided and the card is fully routed, no need to mark pins.
-	 */
-	if (!pdata)
-		return ret;
-
-	/* Disable not connected paths if not used */
-	twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
-	twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
-	twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
-	twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
-	twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator");
-	twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
-	twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
-	twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
-	twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
-
 	return ret;
 }
 
@@ -274,13 +246,18 @@ static struct snd_soc_card omap_abe_card = {
 
 static int omap_abe_probe(struct platform_device *pdev)
 {
-	struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
 	struct device_node *node = pdev->dev.of_node;
 	struct snd_soc_card *card = &omap_abe_card;
+	struct device_node *dai_node;
 	struct abe_twl6040 *priv;
 	int num_links = 0;
 	int ret = 0;
 
+	if (!node) {
+		dev_err(&pdev->dev, "of node is missing.\n");
+		return -ENODEV;
+	}
+
 	card->dev = &pdev->dev;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
@@ -289,78 +266,50 @@ static int omap_abe_probe(struct platform_device *pdev)
 
 	priv->dmic_codec_dev = ERR_PTR(-EINVAL);
 
-	if (node) {
-		struct device_node *dai_node;
-
-		if (snd_soc_of_parse_card_name(card, "ti,model")) {
-			dev_err(&pdev->dev, "Card name is not provided\n");
-			return -ENODEV;
-		}
+	if (snd_soc_of_parse_card_name(card, "ti,model")) {
+		dev_err(&pdev->dev, "Card name is not provided\n");
+		return -ENODEV;
+	}
 
-		ret = snd_soc_of_parse_audio_routing(card,
-						"ti,audio-routing");
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Error while parsing DAPM routing\n");
-			return ret;
-		}
+	ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
+	if (ret) {
+		dev_err(&pdev->dev, "Error while parsing DAPM routing\n");
+		return ret;
+	}
 
-		dai_node = of_parse_phandle(node, "ti,mcpdm", 0);
-		if (!dai_node) {
-			dev_err(&pdev->dev, "McPDM node is not provided\n");
-			return -EINVAL;
-		}
-		abe_twl6040_dai_links[0].cpu_dai_name  = NULL;
-		abe_twl6040_dai_links[0].cpu_of_node = dai_node;
+	dai_node = of_parse_phandle(node, "ti,mcpdm", 0);
+	if (!dai_node) {
+		dev_err(&pdev->dev, "McPDM node is not provided\n");
+		return -EINVAL;
+	}
+	abe_twl6040_dai_links[0].cpu_dai_name  = NULL;
+	abe_twl6040_dai_links[0].cpu_of_node = dai_node;
 
-		dai_node = of_parse_phandle(node, "ti,dmic", 0);
-		if (dai_node) {
-			num_links = 2;
-			abe_twl6040_dai_links[1].cpu_dai_name  = NULL;
-			abe_twl6040_dai_links[1].cpu_of_node = dai_node;
+	dai_node = of_parse_phandle(node, "ti,dmic", 0);
+	if (dai_node) {
+		num_links = 2;
+		abe_twl6040_dai_links[1].cpu_dai_name  = NULL;
+		abe_twl6040_dai_links[1].cpu_of_node = dai_node;
 
-			priv->dmic_codec_dev = platform_device_register_simple(
+		priv->dmic_codec_dev = platform_device_register_simple(
 						"dmic-codec", -1, NULL, 0);
-			if (IS_ERR(priv->dmic_codec_dev)) {
-				dev_err(&pdev->dev,
-					"Can't instantiate dmic-codec\n");
-				return PTR_ERR(priv->dmic_codec_dev);
-			}
-		} else {
-			num_links = 1;
-		}
-
-		priv->jack_detection = of_property_read_bool(node,
-							   "ti,jack-detection");
-		of_property_read_u32(node, "ti,mclk-freq",
-				     &priv->mclk_freq);
-		if (!priv->mclk_freq) {
-			dev_err(&pdev->dev, "MCLK frequency not provided\n");
-			ret = -EINVAL;
-			goto err_unregister;
+		if (IS_ERR(priv->dmic_codec_dev)) {
+			dev_err(&pdev->dev, "Can't instantiate dmic-codec\n");
+			return PTR_ERR(priv->dmic_codec_dev);
 		}
-
-		omap_abe_card.fully_routed = 1;
-	} else if (pdata) {
-		if (pdata->card_name) {
-			card->name = pdata->card_name;
-		} else {
-			dev_err(&pdev->dev, "Card name is not provided\n");
-			return -ENODEV;
-		}
-
-		if (pdata->has_dmic)
-			num_links = 2;
-		else
-			num_links = 1;
-
-		priv->jack_detection = pdata->jack_detection;
-		priv->mclk_freq = pdata->mclk_freq;
 	} else {
-		dev_err(&pdev->dev, "Missing pdata\n");
-		return -ENODEV;
+		num_links = 1;
+	}
+
+	priv->jack_detection = of_property_read_bool(node, "ti,jack-detection");
+	of_property_read_u32(node, "ti,mclk-freq", &priv->mclk_freq);
+	if (!priv->mclk_freq) {
+		dev_err(&pdev->dev, "MCLK frequency not provided\n");
+		ret = -EINVAL;
+		goto err_unregister;
 	}
 
+	card->fully_routed = 1;
 
 	if (!priv->mclk_freq) {
 		dev_err(&pdev->dev, "MCLK frequency missing\n");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 7483efb..6c19bba 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -433,6 +433,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 		/* Sample rate generator drives the FS */
 		regs->srgr2	|= FSGM;
 		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		/* McBSP slave. FS clock as output */
+		regs->srgr2	|= FSGM;
+		regs->pcr0	|= FSXM;
+		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
 		/* McBSP slave */
 		break;
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index 4ad7609..5b7d969 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -129,6 +129,7 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = {
 /* audio machine driver */
 static struct snd_soc_card brownstone = {
 	.name         = "brownstone",
+	.owner        = THIS_MODULE,
 	.dai_link     = brownstone_wm8994_dai,
 	.num_links    = ARRAY_SIZE(brownstone_wm8994_dai),
 
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 62142ce..1605934 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -430,9 +430,6 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL)
-		return -ENOMEM;
-
 	priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->sspa->mmio_base))
 		return PTR_ERR(priv->sspa->mmio_base);
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
index f4ea4f6..13c9ee0 100644
--- a/sound/soc/pxa/ttc-dkb.c
+++ b/sound/soc/pxa/ttc-dkb.c
@@ -122,6 +122,7 @@ static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = {
 /* ttc/td audio machine driver */
 static struct snd_soc_card ttc_dkb_card = {
 	.name = "ttc-dkb-hifi",
+	.owner = THIS_MODULE,
 	.dai_link = ttc_pm860x_hifi_dai,
 	.num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai),
 
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h
index c0e6d9a..30513b7 100644
--- a/sound/soc/samsung/i2s-regs.h
+++ b/sound/soc/samsung/i2s-regs.h
@@ -95,22 +95,26 @@
 #define MOD_RXONLY		(1 << 8)
 #define MOD_TXRX		(2 << 8)
 #define MOD_MASK		(3 << 8)
-#define MOD_LR_LLOW		(0 << 7)
-#define MOD_LR_RLOW		(1 << 7)
-#define MOD_SDF_IIS		(0 << 5)
-#define MOD_SDF_MSB		(1 << 5)
-#define MOD_SDF_LSB		(2 << 5)
-#define MOD_SDF_MASK		(3 << 5)
-#define MOD_RCLK_256FS		(0 << 3)
-#define MOD_RCLK_512FS		(1 << 3)
-#define MOD_RCLK_384FS		(2 << 3)
-#define MOD_RCLK_768FS		(3 << 3)
-#define MOD_RCLK_MASK		(3 << 3)
-#define MOD_BCLK_32FS		(0 << 1)
-#define MOD_BCLK_48FS		(1 << 1)
-#define MOD_BCLK_16FS		(2 << 1)
-#define MOD_BCLK_24FS		(3 << 1)
-#define MOD_BCLK_MASK		(3 << 1)
+#define MOD_LRP_SHIFT		7
+#define MOD_LR_LLOW		0
+#define MOD_LR_RLOW		1
+#define MOD_SDF_SHIFT		5
+#define MOD_SDF_IIS		0
+#define MOD_SDF_MSB		1
+#define MOD_SDF_LSB		2
+#define MOD_SDF_MASK		3
+#define MOD_RCLK_SHIFT		3
+#define MOD_RCLK_256FS		0
+#define MOD_RCLK_512FS		1
+#define MOD_RCLK_384FS		2
+#define MOD_RCLK_768FS		3
+#define MOD_RCLK_MASK		3
+#define MOD_BCLK_SHIFT		1
+#define MOD_BCLK_32FS		0
+#define MOD_BCLK_48FS		1
+#define MOD_BCLK_16FS		2
+#define MOD_BCLK_24FS		3
+#define MOD_BCLK_MASK		3
 #define MOD_8BIT		(1 << 0)
 
 #define MOD_CDCLKCON		(1 << 12)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 959c702..47e08dd 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -198,7 +198,8 @@ static inline bool is_manager(struct i2s_dai *i2s)
 /* Read RCLK of I2S (in multiples of LRCLK) */
 static inline unsigned get_rfs(struct i2s_dai *i2s)
 {
-	u32 rfs = (readl(i2s->addr + I2SMOD) >> 3) & 0x3;
+	u32 rfs = (readl(i2s->addr + I2SMOD) >> MOD_RCLK_SHIFT);
+	rfs &= MOD_RCLK_MASK;
 
 	switch (rfs) {
 	case 3:	return 768;
@@ -212,21 +213,22 @@ static inline unsigned get_rfs(struct i2s_dai *i2s)
 static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
 {
 	u32 mod = readl(i2s->addr + I2SMOD);
+	int rfs_shift =  MOD_RCLK_SHIFT;
 
-	mod &= ~MOD_RCLK_MASK;
+	mod &= ~(MOD_RCLK_MASK << rfs_shift);
 
 	switch (rfs) {
 	case 768:
-		mod |= MOD_RCLK_768FS;
+		mod |= (MOD_RCLK_768FS << rfs_shift);
 		break;
 	case 512:
-		mod |= MOD_RCLK_512FS;
+		mod |= (MOD_RCLK_512FS << rfs_shift);
 		break;
 	case 384:
-		mod |= MOD_RCLK_384FS;
+		mod |= (MOD_RCLK_384FS << rfs_shift);
 		break;
 	default:
-		mod |= MOD_RCLK_256FS;
+		mod |= (MOD_RCLK_256FS << rfs_shift);
 		break;
 	}
 
@@ -236,7 +238,8 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
 /* Read Bit-Clock of I2S (in multiples of LRCLK) */
 static inline unsigned get_bfs(struct i2s_dai *i2s)
 {
-	u32 bfs = (readl(i2s->addr + I2SMOD) >> 1) & 0x3;
+	u32 bfs =  readl(i2s->addr + I2SMOD) >> MOD_BCLK_SHIFT;
+	bfs &= MOD_BCLK_MASK;
 
 	switch (bfs) {
 	case 3: return 24;
@@ -250,21 +253,22 @@ static inline unsigned get_bfs(struct i2s_dai *i2s)
 static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)
 {
 	u32 mod = readl(i2s->addr + I2SMOD);
+	int bfs_shift = MOD_BCLK_SHIFT;
 
-	mod &= ~MOD_BCLK_MASK;
+	mod &= ~(MOD_BCLK_MASK << bfs_shift);
 
 	switch (bfs) {
 	case 48:
-		mod |= MOD_BCLK_48FS;
+		mod |= (MOD_BCLK_48FS << bfs_shift);
 		break;
 	case 32:
-		mod |= MOD_BCLK_32FS;
+		mod |= (MOD_BCLK_32FS << bfs_shift);
 		break;
 	case 24:
-		mod |= MOD_BCLK_24FS;
+		mod |= (MOD_BCLK_24FS << bfs_shift);
 		break;
 	case 16:
-		mod |= MOD_BCLK_16FS;
+		mod |= (MOD_BCLK_16FS << bfs_shift);
 		break;
 	default:
 		dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n");
@@ -491,20 +495,25 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
 {
 	struct i2s_dai *i2s = to_info(dai);
 	u32 mod = readl(i2s->addr + I2SMOD);
+	int lrp_shift = MOD_LRP_SHIFT, sdf_shift = MOD_SDF_SHIFT;
+	int sdf_mask, lrp_rlow;
 	u32 tmp = 0;
 
+	sdf_mask = MOD_SDF_MASK << sdf_shift;
+	lrp_rlow = MOD_LR_RLOW << lrp_shift;
+
 	/* Format is priority */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_RIGHT_J:
-		tmp |= MOD_LR_RLOW;
-		tmp |= MOD_SDF_MSB;
+		tmp |= lrp_rlow;
+		tmp |= (MOD_SDF_MSB << sdf_shift);
 		break;
 	case SND_SOC_DAIFMT_LEFT_J:
-		tmp |= MOD_LR_RLOW;
-		tmp |= MOD_SDF_LSB;
+		tmp |= lrp_rlow;
+		tmp |= (MOD_SDF_LSB << sdf_shift);
 		break;
 	case SND_SOC_DAIFMT_I2S:
-		tmp |= MOD_SDF_IIS;
+		tmp |= (MOD_SDF_IIS << sdf_shift);
 		break;
 	default:
 		dev_err(&i2s->pdev->dev, "Format not supported\n");
@@ -519,10 +528,10 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
 	case SND_SOC_DAIFMT_NB_NF:
 		break;
 	case SND_SOC_DAIFMT_NB_IF:
-		if (tmp & MOD_LR_RLOW)
-			tmp &= ~MOD_LR_RLOW;
+		if (tmp & lrp_rlow)
+			tmp &= ~lrp_rlow;
 		else
-			tmp |= MOD_LR_RLOW;
+			tmp |= lrp_rlow;
 		break;
 	default:
 		dev_err(&i2s->pdev->dev, "Polarity not supported\n");
@@ -544,15 +553,18 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
 		return -EINVAL;
 	}
 
+	/*
+	 * Don't change the I2S mode if any controller is active on this
+	 * channel.
+	 */
 	if (any_active(i2s) &&
-			((mod & (MOD_SDF_MASK | MOD_LR_RLOW
-				| MOD_SLAVE)) != tmp)) {
+		((mod & (sdf_mask | lrp_rlow | MOD_SLAVE)) != tmp)) {
 		dev_err(&i2s->pdev->dev,
 				"%s:%d Other DAI busy\n", __func__, __LINE__);
 		return -EAGAIN;
 	}
 
-	mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE);
+	mod &= ~(sdf_mask | lrp_rlow | MOD_SLAVE);
 	mod |= tmp;
 	writel(mod, i2s->addr + I2SMOD);
 
@@ -1007,6 +1019,8 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 		if (IS_ERR(i2s->pdev))
 			return NULL;
 
+		i2s->pdev->dev.parent = &pdev->dev;
+
 		platform_set_drvdata(i2s->pdev, i2s);
 		ret = platform_device_add(i2s->pdev);
 		if (ret < 0)
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 581ea4a..5fd7a05 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -11,6 +11,7 @@
 #include <sound/pcm_params.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
  /*
   * Default CFG switch settings to use this driver:
@@ -37,11 +38,19 @@
 /* SMDK has a 16.934MHZ crystal attached to WM8994 */
 #define SMDK_WM8994_FREQ 16934000
 
+struct smdk_wm8994_data {
+	int mclk1_rate;
+};
+
+/* Default SMDKs */
+static struct smdk_wm8994_data smdk_board_data = {
+	.mclk1_rate = SMDK_WM8994_FREQ,
+};
+
 static int smdk_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 *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	unsigned int pll_out;
 	int ret;
@@ -54,18 +63,6 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
 	else
 		pll_out = params_rate(params) * 256;
 
-	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
-					 | SND_SOC_DAIFMT_NB_NF
-					 | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
-					 | SND_SOC_DAIFMT_NB_NF
-					 | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
 	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
 					SMDK_WM8994_FREQ, pll_out);
 	if (ret < 0)
@@ -131,6 +128,8 @@ static struct snd_soc_dai_link smdk_dai[] = {
 		.platform_name = "samsung-i2s.0",
 		.codec_name = "wm8994-codec",
 		.init = smdk_wm8994_init_paiftx,
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBM_CFM,
 		.ops = &smdk_ops,
 	}, { /* Sec_Fifo Playback i/f */
 		.name = "Sec_FIFO TX",
@@ -139,6 +138,8 @@ static struct snd_soc_dai_link smdk_dai[] = {
 		.codec_dai_name = "wm8994-aif1",
 		.platform_name = "samsung-i2s-sec",
 		.codec_name = "wm8994-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBM_CFM,
 		.ops = &smdk_ops,
 	},
 };
@@ -150,15 +151,28 @@ static struct snd_soc_card smdk = {
 	.num_links = ARRAY_SIZE(smdk_dai),
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_wm8994_of_match[] = {
+	{ .compatible = "samsung,smdk-wm8994", .data = &smdk_board_data },
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
+#endif /* CONFIG_OF */
 
 static int smdk_audio_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct device_node *np = pdev->dev.of_node;
 	struct snd_soc_card *card = &smdk;
+	struct smdk_wm8994_data *board;
+	const struct of_device_id *id;
 
 	card->dev = &pdev->dev;
 
+	board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
+	if (!board)
+		return -ENOMEM;
+
 	if (np) {
 		smdk_dai[0].cpu_dai_name = NULL;
 		smdk_dai[0].cpu_of_node = of_parse_phandle(np,
@@ -173,6 +187,12 @@ static int smdk_audio_probe(struct platform_device *pdev)
 		smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node;
 	}
 
+	id = of_match_device(samsung_wm8994_of_match, &pdev->dev);
+	if (id)
+		*board = *((struct smdk_wm8994_data *)id->data);
+
+	platform_set_drvdata(pdev, board);
+
 	ret = snd_soc_register_card(card);
 
 	if (ret)
@@ -190,17 +210,9 @@ static int smdk_audio_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id samsung_wm8994_of_match[] = {
-	{ .compatible = "samsung,smdk-wm8994", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
-#endif /* CONFIG_OF */
-
 static struct platform_driver smdk_audio_driver = {
 	.driver		= {
-		.name	= "smdk-audio",
+		.name	= "smdk-audio-wm8894",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(samsung_wm8994_of_match),
 	},
@@ -212,4 +224,4 @@ module_platform_driver(smdk_audio_driver);
 
 MODULE_DESCRIPTION("ALSA SoC SMDK WM8994");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:smdk-audio");
+MODULE_ALIAS("platform:smdk-audio-wm8994");
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 2e5ebb2..5ea70ab 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -395,7 +395,7 @@ static int spdif_probe(struct platform_device *pdev)
 
 	spin_lock_init(&spdif->lock);
 
-	spdif->pclk = clk_get(&pdev->dev, "spdif");
+	spdif->pclk = devm_clk_get(&pdev->dev, "spdif");
 	if (IS_ERR(spdif->pclk)) {
 		dev_err(&pdev->dev, "failed to get peri-clock\n");
 		ret = -ENOENT;
@@ -403,7 +403,7 @@ static int spdif_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(spdif->pclk);
 
-	spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
+	spdif->sclk = devm_clk_get(&pdev->dev, "sclk_spdif");
 	if (IS_ERR(spdif->sclk)) {
 		dev_err(&pdev->dev, "failed to get internal source clock\n");
 		ret = -ENOENT;
@@ -457,10 +457,8 @@ err3:
 	release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
 	clk_disable_unprepare(spdif->sclk);
-	clk_put(spdif->sclk);
 err1:
 	clk_disable_unprepare(spdif->pclk);
-	clk_put(spdif->pclk);
 err0:
 	return ret;
 }
@@ -480,9 +478,7 @@ static int spdif_remove(struct platform_device *pdev)
 		release_mem_region(mem_res->start, resource_size(mem_res));
 
 	clk_disable_unprepare(spdif->sclk);
-	clk_put(spdif->sclk);
 	clk_disable_unprepare(spdif->pclk);
-	clk_put(spdif->pclk);
 
 	return 0;
 }
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 6bcb116..56d8ff6 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -34,6 +34,13 @@ config SND_SOC_SH4_SIU
 	select SH_DMAE
 	select FW_LOADER
 
+config SND_SOC_RCAR
+	tristate "R-Car series SRU/SCU/SSIU/SSI support"
+	select SND_SIMPLE_CARD
+	select RCAR_CLK_ADG
+	help
+	  This option enables R-Car SUR/SCU/SSIU/SSI sound support
+
 ##
 ## Boards
 ##
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 849b387..aaf3dcd 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -12,6 +12,9 @@ obj-$(CONFIG_SND_SOC_SH4_SSI)	+= snd-soc-ssi.o
 obj-$(CONFIG_SND_SOC_SH4_FSI)	+= snd-soc-fsi.o
 obj-$(CONFIG_SND_SOC_SH4_SIU)	+= snd-soc-siu.o
 
+## audio units for R-Car
+obj-$(CONFIG_SND_SOC_RCAR)	+= rcar/
+
 ## boards
 snd-soc-sh7760-ac97-objs	:= sh7760-ac97.o
 snd-soc-migor-objs		:= migor.o
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
new file mode 100644
index 0000000..0ff492d
--- /dev/null
+++ b/sound/soc/sh/rcar/Makefile
@@ -0,0 +1,2 @@
+snd-soc-rcar-objs	:= core.o gen.o scu.o adg.o ssi.o
+obj-$(CONFIG_SND_SOC_RCAR)	+= snd-soc-rcar.o
\ No newline at end of file
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
new file mode 100644
index 0000000..d80deb7
--- /dev/null
+++ b/sound/soc/sh/rcar/adg.c
@@ -0,0 +1,234 @@
+/*
+ * Helper routines for R-Car sound ADG.
+ *
+ *  Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@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/sh_clk.h>
+#include <mach/clock.h>
+#include "rsnd.h"
+
+#define CLKA	0
+#define CLKB	1
+#define CLKC	2
+#define CLKI	3
+#define CLKMAX	4
+
+struct rsnd_adg {
+	struct clk *clk[CLKMAX];
+
+	int rate_of_441khz_div_6;
+	int rate_of_48khz_div_6;
+};
+
+#define for_each_rsnd_clk(pos, adg, i)		\
+	for (i = 0, (pos) = adg->clk[i];	\
+	     i < CLKMAX;			\
+	     i++, (pos) = adg->clk[i])
+#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
+
+static enum rsnd_reg rsnd_adg_ssi_reg_get(int id)
+{
+	enum rsnd_reg reg;
+
+	/*
+	 * SSI 8 is not connected to ADG.
+	 * it works with SSI 7
+	 */
+	if (id == 8)
+		return RSND_REG_MAX;
+
+	if (0 <= id && id <= 3)
+		reg = RSND_REG_AUDIO_CLK_SEL0;
+	else if (4 <= id && id <= 7)
+		reg = RSND_REG_AUDIO_CLK_SEL1;
+	else
+		reg = RSND_REG_AUDIO_CLK_SEL2;
+
+	return reg;
+}
+
+int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	enum rsnd_reg reg;
+	int id;
+
+	/*
+	 * "mod" = "ssi" here.
+	 * we can get "ssi id" from mod
+	 */
+	id  = rsnd_mod_id(mod);
+	reg = rsnd_adg_ssi_reg_get(id);
+
+	rsnd_write(priv, mod, reg, 0);
+
+	return 0;
+}
+
+int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct clk *clk;
+	enum rsnd_reg reg;
+	int id, shift, i;
+	u32 data;
+	int sel_table[] = {
+		[CLKA] = 0x1,
+		[CLKB] = 0x2,
+		[CLKC] = 0x3,
+		[CLKI] = 0x0,
+	};
+
+	dev_dbg(dev, "request clock = %d\n", rate);
+
+	/*
+	 * find suitable clock from
+	 * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
+	 */
+	data = 0;
+	for_each_rsnd_clk(clk, adg, i) {
+		if (rate == clk_get_rate(clk)) {
+			data = sel_table[i];
+			goto found_clock;
+		}
+	}
+
+	/*
+	 * find 1/6 clock from BRGA/BRGB
+	 */
+	if (rate == adg->rate_of_441khz_div_6) {
+		data = 0x10;
+		goto found_clock;
+	}
+
+	if (rate == adg->rate_of_48khz_div_6) {
+		data = 0x20;
+		goto found_clock;
+	}
+
+	return -EIO;
+
+found_clock:
+
+	/*
+	 * This "mod" = "ssi" here.
+	 * we can get "ssi id" from mod
+	 */
+	id  = rsnd_mod_id(mod);
+	reg = rsnd_adg_ssi_reg_get(id);
+
+	dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate);
+
+	/*
+	 * Enable SSIx clock
+	 */
+	shift = (id % 4) * 8;
+
+	rsnd_bset(priv, mod, reg,
+		   0xFF << shift,
+		   data << shift);
+
+	return 0;
+}
+
+static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
+{
+	struct clk *clk;
+	unsigned long rate;
+	u32 ckr;
+	int i;
+	int brg_table[] = {
+		[CLKA] = 0x0,
+		[CLKB] = 0x1,
+		[CLKC] = 0x4,
+		[CLKI] = 0x2,
+	};
+
+	/*
+	 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
+	 * have 44.1kHz or 48kHz base clocks for now.
+	 *
+	 * SSI itself can divide parent clock by 1/1 - 1/16
+	 * So,  BRGA outputs 44.1kHz base parent clock 1/32,
+	 * and, BRGB outputs 48.0kHz base parent clock 1/32 here.
+	 * see
+	 *	rsnd_adg_ssi_clk_try_start()
+	 */
+	ckr = 0;
+	adg->rate_of_441khz_div_6 = 0;
+	adg->rate_of_48khz_div_6  = 0;
+	for_each_rsnd_clk(clk, adg, i) {
+		rate = clk_get_rate(clk);
+
+		if (0 == rate) /* not used */
+			continue;
+
+		/* RBGA */
+		if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) {
+			adg->rate_of_441khz_div_6 = rate / 6;
+			ckr |= brg_table[i] << 20;
+		}
+
+		/* RBGB */
+		if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) {
+			adg->rate_of_48khz_div_6 = rate / 6;
+			ckr |= brg_table[i] << 16;
+		}
+	}
+
+	rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr);
+	rsnd_priv_write(priv, BRRA,  0x00000002); /* 1/6 */
+	rsnd_priv_write(priv, BRRB,  0x00000002); /* 1/6 */
+}
+
+int rsnd_adg_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv)
+{
+	struct rsnd_adg *adg;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct clk *clk;
+	int i;
+
+	adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
+	if (!adg) {
+		dev_err(dev, "ADG allocate failed\n");
+		return -ENOMEM;
+	}
+
+	adg->clk[CLKA] = clk_get(NULL, "audio_clk_a");
+	adg->clk[CLKB] = clk_get(NULL, "audio_clk_b");
+	adg->clk[CLKC] = clk_get(NULL, "audio_clk_c");
+	adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal");
+	for_each_rsnd_clk(clk, adg, i) {
+		if (IS_ERR(clk)) {
+			dev_err(dev, "Audio clock failed\n");
+			return -EIO;
+		}
+	}
+
+	rsnd_adg_ssi_clk_init(priv, adg);
+
+	priv->adg = adg;
+
+	dev_dbg(dev, "adg probed\n");
+
+	return 0;
+}
+
+void rsnd_adg_remove(struct platform_device *pdev,
+		     struct rsnd_priv *priv)
+{
+	struct rsnd_adg *adg = priv->adg;
+	struct clk *clk;
+	int i;
+
+	for_each_rsnd_clk(clk, adg, i)
+		clk_put(clk);
+}
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
new file mode 100644
index 0000000..a357060
--- /dev/null
+++ b/sound/soc/sh/rcar/core.c
@@ -0,0 +1,861 @@
+/*
+ * Renesas R-Car SRU/SCU/SSIU/SSI support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on fsi.c
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Renesas R-Car sound device structure
+ *
+ * Gen1
+ *
+ * SRU		: Sound Routing Unit
+ *  - SRC	: Sampling Rate Converter
+ *  - CMD
+ *    - CTU	: Channel Count Conversion Unit
+ *    - MIX	: Mixer
+ *    - DVC	: Digital Volume and Mute Function
+ *  - SSI	: Serial Sound Interface
+ *
+ * Gen2
+ *
+ * SCU		: Sampling Rate Converter Unit
+ *  - SRC	: Sampling Rate Converter
+ *  - CMD
+ *   - CTU	: Channel Count Conversion Unit
+ *   - MIX	: Mixer
+ *   - DVC	: Digital Volume and Mute Function
+ * SSIU		: Serial Sound Interface Unit
+ *  - SSI	: Serial Sound Interface
+ */
+
+/*
+ *	driver data Image
+ *
+ * rsnd_priv
+ *   |
+ *   | ** this depends on Gen1/Gen2
+ *   |
+ *   +- gen
+ *   |
+ *   | ** these depend on data path
+ *   | ** gen and platform data control it
+ *   |
+ *   +- rdai[0]
+ *   |   |		 sru     ssiu      ssi
+ *   |   +- playback -> [mod] -> [mod] -> [mod] -> ...
+ *   |   |
+ *   |   |		 sru     ssiu      ssi
+ *   |   +- capture  -> [mod] -> [mod] -> [mod] -> ...
+ *   |
+ *   +- rdai[1]
+ *   |   |		 sru     ssiu      ssi
+ *   |   +- playback -> [mod] -> [mod] -> [mod] -> ...
+ *   |   |
+ *   |   |		 sru     ssiu      ssi
+ *   |   +- capture  -> [mod] -> [mod] -> [mod] -> ...
+ *   ...
+ *   |
+ *   | ** these control ssi
+ *   |
+ *   +- ssi
+ *   |  |
+ *   |  +- ssi[0]
+ *   |  +- ssi[1]
+ *   |  +- ssi[2]
+ *   |  ...
+ *   |
+ *   | ** these control scu
+ *   |
+ *   +- scu
+ *      |
+ *      +- scu[0]
+ *      +- scu[1]
+ *      +- scu[2]
+ *      ...
+ *
+ *
+ * for_each_rsnd_dai(xx, priv, xx)
+ *  rdai[0] => rdai[1] => rdai[2] => ...
+ *
+ * for_each_rsnd_mod(xx, rdai, xx)
+ *  [mod] => [mod] => [mod] => ...
+ *
+ * rsnd_dai_call(xxx, fn )
+ *  [mod]->fn() -> [mod]->fn() -> [mod]->fn()...
+ *
+ */
+#include <linux/pm_runtime.h>
+#include "rsnd.h"
+
+#define RSND_RATES SNDRV_PCM_RATE_8000_96000
+#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
+
+/*
+ *	rsnd_platform functions
+ */
+#define rsnd_platform_call(priv, dai, func, param...)	\
+	(!(priv->info->func) ? -ENODEV :		\
+	 priv->info->func(param))
+
+
+/*
+ *	basic function
+ */
+u32 rsnd_read(struct rsnd_priv *priv,
+	      struct rsnd_mod *mod, enum rsnd_reg reg)
+{
+	void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
+
+	BUG_ON(!base);
+
+	return ioread32(base);
+}
+
+void rsnd_write(struct rsnd_priv *priv,
+		struct rsnd_mod *mod,
+		enum rsnd_reg reg, u32 data)
+{
+	void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	BUG_ON(!base);
+
+	dev_dbg(dev, "w %p : %08x\n", base, data);
+
+	iowrite32(data, base);
+}
+
+void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
+	       enum rsnd_reg reg, u32 mask, u32 data)
+{
+	void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 val;
+
+	BUG_ON(!base);
+
+	val = ioread32(base);
+	val &= ~mask;
+	val |= data & mask;
+	iowrite32(val, base);
+
+	dev_dbg(dev, "s %p : %08x\n", base, val);
+}
+
+/*
+ *	rsnd_mod functions
+ */
+char *rsnd_mod_name(struct rsnd_mod *mod)
+{
+	if (!mod || !mod->ops)
+		return "unknown";
+
+	return mod->ops->name;
+}
+
+void rsnd_mod_init(struct rsnd_priv *priv,
+		   struct rsnd_mod *mod,
+		   struct rsnd_mod_ops *ops,
+		   int id)
+{
+	mod->priv	= priv;
+	mod->id		= id;
+	mod->ops	= ops;
+	INIT_LIST_HEAD(&mod->list);
+}
+
+/*
+ *	rsnd_dma functions
+ */
+static void rsnd_dma_continue(struct rsnd_dma *dma)
+{
+	/* push next A or B plane */
+	dma->submit_loop = 1;
+	schedule_work(&dma->work);
+}
+
+void rsnd_dma_start(struct rsnd_dma *dma)
+{
+	/* push both A and B plane*/
+	dma->submit_loop = 2;
+	schedule_work(&dma->work);
+}
+
+void rsnd_dma_stop(struct rsnd_dma *dma)
+{
+	dma->submit_loop = 0;
+	cancel_work_sync(&dma->work);
+	dmaengine_terminate_all(dma->chan);
+}
+
+static void rsnd_dma_complete(void *data)
+{
+	struct rsnd_dma *dma = (struct rsnd_dma *)data;
+	struct rsnd_priv *priv = dma->priv;
+	unsigned long flags;
+
+	rsnd_lock(priv, flags);
+
+	dma->complete(dma);
+
+	if (dma->submit_loop)
+		rsnd_dma_continue(dma);
+
+	rsnd_unlock(priv, flags);
+}
+
+static void rsnd_dma_do_work(struct work_struct *work)
+{
+	struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work);
+	struct rsnd_priv *priv = dma->priv;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct dma_async_tx_descriptor *desc;
+	dma_addr_t buf;
+	size_t len;
+	int i;
+
+	for (i = 0; i < dma->submit_loop; i++) {
+
+		if (dma->inquiry(dma, &buf, &len) < 0)
+			return;
+
+		desc = dmaengine_prep_slave_single(
+			dma->chan, buf, len, dma->dir,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
+			return;
+		}
+
+		desc->callback		= rsnd_dma_complete;
+		desc->callback_param	= dma;
+
+		if (dmaengine_submit(desc) < 0) {
+			dev_err(dev, "dmaengine_submit() fail\n");
+			return;
+		}
+
+	}
+
+	dma_async_issue_pending(dma->chan);
+}
+
+int rsnd_dma_available(struct rsnd_dma *dma)
+{
+	return !!dma->chan;
+}
+
+static bool rsnd_dma_filter(struct dma_chan *chan, void *param)
+{
+	chan->private = param;
+
+	return true;
+}
+
+int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
+		  int is_play, int id,
+		  int (*inquiry)(struct rsnd_dma *dma,
+				  dma_addr_t *buf, int *len),
+		  int (*complete)(struct rsnd_dma *dma))
+{
+	struct device *dev = rsnd_priv_to_dev(priv);
+	dma_cap_mask_t mask;
+
+	if (dma->chan) {
+		dev_err(dev, "it already has dma channel\n");
+		return -EIO;
+	}
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	dma->slave.shdma_slave.slave_id = id;
+
+	dma->chan = dma_request_channel(mask, rsnd_dma_filter,
+					&dma->slave.shdma_slave);
+	if (!dma->chan) {
+		dev_err(dev, "can't get dma channel\n");
+		return -EIO;
+	}
+
+	dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	dma->priv = priv;
+	dma->inquiry = inquiry;
+	dma->complete = complete;
+	INIT_WORK(&dma->work, rsnd_dma_do_work);
+
+	return 0;
+}
+
+void  rsnd_dma_quit(struct rsnd_priv *priv,
+		    struct rsnd_dma *dma)
+{
+	if (dma->chan)
+		dma_release_channel(dma->chan);
+
+	dma->chan = NULL;
+}
+
+/*
+ *	rsnd_dai functions
+ */
+#define rsnd_dai_call(rdai, io, fn)			\
+({							\
+	struct rsnd_mod *mod, *n;			\
+	int ret = 0;					\
+	for_each_rsnd_mod(mod, n, io) {			\
+		ret = rsnd_mod_call(mod, fn, rdai, io);	\
+		if (ret < 0)				\
+			break;				\
+	}						\
+	ret;						\
+})
+
+int rsnd_dai_connect(struct rsnd_dai *rdai,
+		     struct rsnd_mod *mod,
+		     struct rsnd_dai_stream *io)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	if (!mod) {
+		dev_err(dev, "NULL mod\n");
+		return -EIO;
+	}
+
+	if (!list_empty(&mod->list)) {
+		dev_err(dev, "%s%d is not empty\n",
+			rsnd_mod_name(mod),
+			rsnd_mod_id(mod));
+		return -EIO;
+	}
+
+	list_add_tail(&mod->list, &io->head);
+
+	return 0;
+}
+
+int rsnd_dai_disconnect(struct rsnd_mod *mod)
+{
+	list_del_init(&mod->list);
+
+	return 0;
+}
+
+int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai)
+{
+	int id = rdai - priv->rdai;
+
+	if ((id < 0) || (id >= rsnd_dai_nr(priv)))
+		return -EINVAL;
+
+	return id;
+}
+
+struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id)
+{
+	return priv->rdai + id;
+}
+
+static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
+{
+	struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
+
+	return rsnd_dai_get(priv, dai->id);
+}
+
+int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io)
+{
+	return &rdai->playback == io;
+}
+
+/*
+ *	rsnd_soc_dai functions
+ */
+int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional)
+{
+	struct snd_pcm_substream *substream = io->substream;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int pos = io->byte_pos + additional;
+
+	pos %= (runtime->periods * io->byte_per_period);
+
+	return pos;
+}
+
+void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
+{
+	io->byte_pos += byte;
+
+	if (io->byte_pos >= io->next_period_byte) {
+		struct snd_pcm_substream *substream = io->substream;
+		struct snd_pcm_runtime *runtime = substream->runtime;
+
+		io->period_pos++;
+		io->next_period_byte += io->byte_per_period;
+
+		if (io->period_pos >= runtime->periods) {
+			io->byte_pos = 0;
+			io->period_pos = 0;
+			io->next_period_byte = io->byte_per_period;
+		}
+
+		snd_pcm_period_elapsed(substream);
+	}
+}
+
+static int rsnd_dai_stream_init(struct rsnd_dai_stream *io,
+				struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	if (!list_empty(&io->head))
+		return -EIO;
+
+	INIT_LIST_HEAD(&io->head);
+	io->substream		= substream;
+	io->byte_pos		= 0;
+	io->period_pos		= 0;
+	io->byte_per_period	= runtime->period_size *
+				  runtime->channels *
+				  samples_to_bytes(runtime, 1);
+	io->next_period_byte	= io->byte_per_period;
+
+	return 0;
+}
+
+static
+struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	return  rtd->cpu_dai;
+}
+
+static
+struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
+					struct snd_pcm_substream *substream)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return &rdai->playback;
+	else
+		return &rdai->capture;
+}
+
+static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+			    struct snd_soc_dai *dai)
+{
+	struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
+	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
+	struct rsnd_mod *mod = rsnd_ssi_mod_get_frm_dai(priv,
+						rsnd_dai_id(priv, rdai),
+						rsnd_dai_is_play(rdai, io));
+	int ssi_id = rsnd_mod_id(mod);
+	int ret;
+	unsigned long flags;
+
+	rsnd_lock(priv, flags);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		ret = rsnd_dai_stream_init(io, substream);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_platform_call(priv, dai, start, ssi_id);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_gen_path_init(priv, rdai, io);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_dai_call(rdai, io, init);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_dai_call(rdai, io, start);
+		if (ret < 0)
+			goto dai_trigger_end;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		ret = rsnd_dai_call(rdai, io, stop);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_dai_call(rdai, io, quit);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_gen_path_exit(priv, rdai, io);
+		if (ret < 0)
+			goto dai_trigger_end;
+
+		ret = rsnd_platform_call(priv, dai, stop, ssi_id);
+		if (ret < 0)
+			goto dai_trigger_end;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+dai_trigger_end:
+	rsnd_unlock(priv, flags);
+
+	return ret;
+}
+
+static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		rdai->clk_master = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		rdai->clk_master = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_IF:
+		rdai->bit_clk_inv = 0;
+		rdai->frm_clk_inv = 1;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		rdai->bit_clk_inv = 1;
+		rdai->frm_clk_inv = 0;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		rdai->bit_clk_inv = 1;
+		rdai->frm_clk_inv = 1;
+		break;
+	case SND_SOC_DAIFMT_NB_NF:
+	default:
+		rdai->bit_clk_inv = 0;
+		rdai->frm_clk_inv = 0;
+		break;
+	}
+
+	/* set format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		rdai->sys_delay = 0;
+		rdai->data_alignment = 0;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		rdai->sys_delay = 1;
+		rdai->data_alignment = 0;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		rdai->sys_delay = 1;
+		rdai->data_alignment = 1;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
+	.trigger	= rsnd_soc_dai_trigger,
+	.set_fmt	= rsnd_soc_dai_set_fmt,
+};
+
+static int rsnd_dai_probe(struct platform_device *pdev,
+			  struct rcar_snd_info *info,
+			  struct rsnd_priv *priv)
+{
+	struct snd_soc_dai_driver *drv;
+	struct rsnd_dai *rdai;
+	struct rsnd_mod *pmod, *cmod;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	int dai_nr;
+	int i;
+
+	/* get max dai nr */
+	for (dai_nr = 0; dai_nr < 32; dai_nr++) {
+		pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1);
+		cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0);
+
+		if (!pmod && !cmod)
+			break;
+	}
+
+	if (!dai_nr) {
+		dev_err(dev, "no dai\n");
+		return -EIO;
+	}
+
+	drv  = devm_kzalloc(dev, sizeof(*drv)  * dai_nr, GFP_KERNEL);
+	rdai = devm_kzalloc(dev, sizeof(*rdai) * dai_nr, GFP_KERNEL);
+	if (!drv || !rdai) {
+		dev_err(dev, "dai allocate failed\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < dai_nr; i++) {
+
+		pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1);
+		cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0);
+
+		/*
+		 *	init rsnd_dai
+		 */
+		INIT_LIST_HEAD(&rdai[i].playback.head);
+		INIT_LIST_HEAD(&rdai[i].capture.head);
+
+		snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i);
+
+		/*
+		 *	init snd_soc_dai_driver
+		 */
+		drv[i].name	= rdai[i].name;
+		drv[i].ops	= &rsnd_soc_dai_ops;
+		if (pmod) {
+			drv[i].playback.rates		= RSND_RATES;
+			drv[i].playback.formats		= RSND_FMTS;
+			drv[i].playback.channels_min	= 2;
+			drv[i].playback.channels_max	= 2;
+		}
+		if (cmod) {
+			drv[i].capture.rates		= RSND_RATES;
+			drv[i].capture.formats		= RSND_FMTS;
+			drv[i].capture.channels_min	= 2;
+			drv[i].capture.channels_max	= 2;
+		}
+
+		dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name,
+			pmod ? "play"    : " -- ",
+			cmod ? "capture" : "  --   ");
+	}
+
+	priv->dai_nr	= dai_nr;
+	priv->daidrv	= drv;
+	priv->rdai	= rdai;
+
+	return 0;
+}
+
+static void rsnd_dai_remove(struct platform_device *pdev,
+			  struct rsnd_priv *priv)
+{
+}
+
+/*
+ *		pcm ops
+ */
+static struct snd_pcm_hardware rsnd_pcm_hardware = {
+	.info =		SNDRV_PCM_INFO_INTERLEAVED	|
+			SNDRV_PCM_INFO_MMAP		|
+			SNDRV_PCM_INFO_MMAP_VALID	|
+			SNDRV_PCM_INFO_PAUSE,
+	.formats		= RSND_FMTS,
+	.rates			= RSND_RATES,
+	.rate_min		= 8000,
+	.rate_max		= 192000,
+	.channels_min		= 2,
+	.channels_max		= 2,
+	.buffer_bytes_max	= 64 * 1024,
+	.period_bytes_min	= 32,
+	.period_bytes_max	= 8192,
+	.periods_min		= 1,
+	.periods_max		= 32,
+	.fifo_size		= 256,
+};
+
+static int rsnd_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret = 0;
+
+	snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
+
+	ret = snd_pcm_hw_constraint_integer(runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+
+	return ret;
+}
+
+static int rsnd_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 snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
+	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
+
+	return bytes_to_frames(runtime, io->byte_pos);
+}
+
+static struct snd_pcm_ops rsnd_pcm_ops = {
+	.open		= rsnd_pcm_open,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= rsnd_hw_params,
+	.hw_free	= snd_pcm_lib_free_pages,
+	.pointer	= rsnd_pointer,
+};
+
+/*
+ *		snd_soc_platform
+ */
+
+#define PREALLOC_BUFFER		(32 * 1024)
+#define PREALLOC_BUFFER_MAX	(32 * 1024)
+
+static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	return snd_pcm_lib_preallocate_pages_for_all(
+		rtd->pcm,
+		SNDRV_DMA_TYPE_DEV,
+		rtd->card->snd_card->dev,
+		PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+}
+
+static void rsnd_pcm_free(struct snd_pcm *pcm)
+{
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static struct snd_soc_platform_driver rsnd_soc_platform = {
+	.ops		= &rsnd_pcm_ops,
+	.pcm_new	= rsnd_pcm_new,
+	.pcm_free	= rsnd_pcm_free,
+};
+
+static const struct snd_soc_component_driver rsnd_soc_component = {
+	.name		= "rsnd",
+};
+
+/*
+ *	rsnd probe
+ */
+static int rsnd_probe(struct platform_device *pdev)
+{
+	struct rcar_snd_info *info;
+	struct rsnd_priv *priv;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	info = pdev->dev.platform_data;
+	if (!info) {
+		dev_err(dev, "driver needs R-Car sound information\n");
+		return -ENODEV;
+	}
+
+	/*
+	 *	init priv data
+	 */
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "priv allocate failed\n");
+		return -ENODEV;
+	}
+
+	priv->dev	= dev;
+	priv->info	= info;
+	spin_lock_init(&priv->lock);
+
+	/*
+	 *	init each module
+	 */
+	ret = rsnd_gen_probe(pdev, info, priv);
+	if (ret < 0)
+		return ret;
+
+	ret = rsnd_scu_probe(pdev, info, priv);
+	if (ret < 0)
+		return ret;
+
+	ret = rsnd_adg_probe(pdev, info, priv);
+	if (ret < 0)
+		return ret;
+
+	ret = rsnd_ssi_probe(pdev, info, priv);
+	if (ret < 0)
+		return ret;
+
+	ret = rsnd_dai_probe(pdev, info, priv);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 *	asoc register
+	 */
+	ret = snd_soc_register_platform(dev, &rsnd_soc_platform);
+	if (ret < 0) {
+		dev_err(dev, "cannot snd soc register\n");
+		return ret;
+	}
+
+	ret = snd_soc_register_component(dev, &rsnd_soc_component,
+					 priv->daidrv, rsnd_dai_nr(priv));
+	if (ret < 0) {
+		dev_err(dev, "cannot snd dai register\n");
+		goto exit_snd_soc;
+	}
+
+	dev_set_drvdata(dev, priv);
+
+	pm_runtime_enable(dev);
+
+	dev_info(dev, "probed\n");
+	return ret;
+
+exit_snd_soc:
+	snd_soc_unregister_platform(dev);
+
+	return ret;
+}
+
+static int rsnd_remove(struct platform_device *pdev)
+{
+	struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	/*
+	 *	remove each module
+	 */
+	rsnd_ssi_remove(pdev, priv);
+	rsnd_adg_remove(pdev, priv);
+	rsnd_scu_remove(pdev, priv);
+	rsnd_dai_remove(pdev, priv);
+	rsnd_gen_remove(pdev, priv);
+
+	return 0;
+}
+
+static struct platform_driver rsnd_driver = {
+	.driver	= {
+		.name	= "rcar_sound",
+	},
+	.probe		= rsnd_probe,
+	.remove		= rsnd_remove,
+};
+module_platform_driver(rsnd_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Renesas R-Car audio driver");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+MODULE_ALIAS("platform:rcar-pcm-audio");
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
new file mode 100644
index 0000000..babb203
--- /dev/null
+++ b/sound/soc/sh/rcar/gen.c
@@ -0,0 +1,280 @@
+/*
+ * Renesas R-Car Gen1 SRU/SSI support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "rsnd.h"
+
+struct rsnd_gen_ops {
+	int (*path_init)(struct rsnd_priv *priv,
+			 struct rsnd_dai *rdai,
+			 struct rsnd_dai_stream *io);
+	int (*path_exit)(struct rsnd_priv *priv,
+			 struct rsnd_dai *rdai,
+			 struct rsnd_dai_stream *io);
+};
+
+struct rsnd_gen_reg_map {
+	int index;	/* -1 : not supported */
+	u32 offset_id;	/* offset of ssi0, ssi1, ssi2... */
+	u32 offset_adr;	/* offset of SSICR, SSISR, ... */
+};
+
+struct rsnd_gen {
+	void __iomem *base[RSND_BASE_MAX];
+
+	struct rsnd_gen_reg_map reg_map[RSND_REG_MAX];
+	struct rsnd_gen_ops *ops;
+};
+
+#define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)
+
+/*
+ *		Gen2
+ *		will be filled in the future
+ */
+
+/*
+ *		Gen1
+ */
+static int rsnd_gen1_path_init(struct rsnd_priv *priv,
+			       struct rsnd_dai *rdai,
+			       struct rsnd_dai_stream *io)
+{
+	struct rsnd_mod *mod;
+	int ret;
+	int id;
+
+	/*
+	 * Gen1 is created by SRU/SSI, and this SRU is base module of
+	 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
+	 *
+	 * Easy image is..
+	 *	Gen1 SRU = Gen2 SCU + SSIU + etc
+	 *
+	 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
+	 * using fixed path.
+	 *
+	 * Then, SSI id = SCU id here
+	 */
+
+	/* get SSI's ID */
+	mod = rsnd_ssi_mod_get_frm_dai(priv,
+				       rsnd_dai_id(priv, rdai),
+				       rsnd_dai_is_play(rdai, io));
+	id = rsnd_mod_id(mod);
+
+	/* SSI */
+	mod = rsnd_ssi_mod_get(priv, id);
+	ret = rsnd_dai_connect(rdai, mod, io);
+	if (ret < 0)
+		return ret;
+
+	/* SCU */
+	mod = rsnd_scu_mod_get(priv, id);
+	ret = rsnd_dai_connect(rdai, mod, io);
+
+	return ret;
+}
+
+static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
+			       struct rsnd_dai *rdai,
+			       struct rsnd_dai_stream *io)
+{
+	struct rsnd_mod *mod, *n;
+	int ret = 0;
+
+	/*
+	 * remove all mod from rdai
+	 */
+	for_each_rsnd_mod(mod, n, io)
+		ret |= rsnd_dai_disconnect(mod);
+
+	return ret;
+}
+
+static struct rsnd_gen_ops rsnd_gen1_ops = {
+	.path_init	= rsnd_gen1_path_init,
+	.path_exit	= rsnd_gen1_path_exit,
+};
+
+#define RSND_GEN1_REG_MAP(g, s, i, oi, oa)				\
+	do {								\
+		(g)->reg_map[RSND_REG_##i].index  = RSND_GEN1_##s;	\
+		(g)->reg_map[RSND_REG_##i].offset_id = oi;		\
+		(g)->reg_map[RSND_REG_##i].offset_adr = oa;		\
+	} while (0)
+
+static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
+{
+	RSND_GEN1_REG_MAP(gen, SRU,	SRC_ROUTE_SEL,	0x0,	0x00);
+	RSND_GEN1_REG_MAP(gen, SRU,	SRC_TMG_SEL0,	0x0,	0x08);
+	RSND_GEN1_REG_MAP(gen, SRU,	SRC_TMG_SEL1,	0x0,	0x0c);
+	RSND_GEN1_REG_MAP(gen, SRU,	SRC_TMG_SEL2,	0x0,	0x10);
+	RSND_GEN1_REG_MAP(gen, SRU,	SRC_CTRL,	0x0,	0xc0);
+	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE0,	0x0,	0xD0);
+	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE1,	0x0,	0xD4);
+	RSND_GEN1_REG_MAP(gen, SRU,	BUSIF_MODE,	0x4,	0x20);
+	RSND_GEN1_REG_MAP(gen, SRU,	BUSIF_ADINR,	0x40,	0x214);
+
+	RSND_GEN1_REG_MAP(gen, ADG,	BRRA,		0x0,	0x00);
+	RSND_GEN1_REG_MAP(gen, ADG,	BRRB,		0x0,	0x04);
+	RSND_GEN1_REG_MAP(gen, ADG,	SSICKR,		0x0,	0x08);
+	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL0,	0x0,	0x0c);
+	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL1,	0x0,	0x10);
+	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL3,	0x0,	0x18);
+	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL4,	0x0,	0x1c);
+	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL5,	0x0,	0x20);
+
+	RSND_GEN1_REG_MAP(gen, SSI,	SSICR,		0x40,	0x00);
+	RSND_GEN1_REG_MAP(gen, SSI,	SSISR,		0x40,	0x04);
+	RSND_GEN1_REG_MAP(gen, SSI,	SSITDR,		0x40,	0x08);
+	RSND_GEN1_REG_MAP(gen, SSI,	SSIRDR,		0x40,	0x0c);
+	RSND_GEN1_REG_MAP(gen, SSI,	SSIWSR,		0x40,	0x20);
+}
+
+static int rsnd_gen1_probe(struct platform_device *pdev,
+			   struct rcar_snd_info *info,
+			   struct rsnd_priv *priv)
+{
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+	struct resource *sru_res;
+	struct resource *adg_res;
+	struct resource *ssi_res;
+
+	/*
+	 * map address
+	 */
+	sru_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
+	adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG);
+	ssi_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI);
+
+	gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
+	gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res);
+	gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res);
+	if (IS_ERR(gen->base[RSND_GEN1_SRU]) ||
+	    IS_ERR(gen->base[RSND_GEN1_ADG]) ||
+	    IS_ERR(gen->base[RSND_GEN1_SSI]))
+		return -ENODEV;
+
+	gen->ops = &rsnd_gen1_ops;
+	rsnd_gen1_reg_map_init(gen);
+
+	dev_dbg(dev, "Gen1 device probed\n");
+	dev_dbg(dev, "SRU : %08x => %p\n",	sru_res->start,
+						gen->base[RSND_GEN1_SRU]);
+	dev_dbg(dev, "ADG : %08x => %p\n",	adg_res->start,
+						gen->base[RSND_GEN1_ADG]);
+	dev_dbg(dev, "SSI : %08x => %p\n",	ssi_res->start,
+						gen->base[RSND_GEN1_SSI]);
+
+	return 0;
+
+}
+
+static void rsnd_gen1_remove(struct platform_device *pdev,
+			     struct rsnd_priv *priv)
+{
+}
+
+/*
+ *		Gen
+ */
+int rsnd_gen_path_init(struct rsnd_priv *priv,
+		       struct rsnd_dai *rdai,
+		       struct rsnd_dai_stream *io)
+{
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+	return gen->ops->path_init(priv, rdai, io);
+}
+
+int rsnd_gen_path_exit(struct rsnd_priv *priv,
+		       struct rsnd_dai *rdai,
+		       struct rsnd_dai_stream *io)
+{
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+	return gen->ops->path_exit(priv, rdai, io);
+}
+
+void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
+			       struct rsnd_mod *mod,
+			       enum rsnd_reg reg)
+{
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	int index;
+	u32 offset_id, offset_adr;
+
+	if (reg >= RSND_REG_MAX) {
+		dev_err(dev, "rsnd_reg reg error\n");
+		return NULL;
+	}
+
+	index		= gen->reg_map[reg].index;
+	offset_id	= gen->reg_map[reg].offset_id;
+	offset_adr	= gen->reg_map[reg].offset_adr;
+
+	if (index < 0) {
+		dev_err(dev, "unsupported reg access %d\n", reg);
+		return NULL;
+	}
+
+	if (offset_id && mod)
+		offset_id *= rsnd_mod_id(mod);
+
+	/*
+	 * index/offset were set on gen1/gen2
+	 */
+
+	return gen->base[index] + offset_id + offset_adr;
+}
+
+int rsnd_gen_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv)
+{
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_gen *gen;
+	int i;
+
+	gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
+	if (!gen) {
+		dev_err(dev, "GEN allocate failed\n");
+		return -ENOMEM;
+	}
+
+	priv->gen = gen;
+
+	/*
+	 * see
+	 *	rsnd_reg_get()
+	 *	rsnd_gen_probe()
+	 */
+	for (i = 0; i < RSND_REG_MAX; i++)
+		gen->reg_map[i].index = -1;
+
+	/*
+	 *	init each module
+	 */
+	if (rsnd_is_gen1(priv))
+		return rsnd_gen1_probe(pdev, info, priv);
+
+	dev_err(dev, "unknown generation R-Car sound device\n");
+
+	return -ENODEV;
+}
+
+void rsnd_gen_remove(struct platform_device *pdev,
+		     struct rsnd_priv *priv)
+{
+	if (rsnd_is_gen1(priv))
+		rsnd_gen1_remove(pdev, priv);
+}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
new file mode 100644
index 0000000..9cc6986
--- /dev/null
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -0,0 +1,302 @@
+/*
+ * Renesas R-Car
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef RSND_H
+#define RSND_H
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/sh_dma.h>
+#include <linux/workqueue.h>
+#include <sound/rcar_snd.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+/*
+ *	pseudo register
+ *
+ * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different.
+ * This driver uses pseudo register in order to hide it.
+ * see gen1/gen2 for detail
+ */
+enum rsnd_reg {
+	/* SRU/SCU */
+	RSND_REG_SRC_ROUTE_SEL,
+	RSND_REG_SRC_TMG_SEL0,
+	RSND_REG_SRC_TMG_SEL1,
+	RSND_REG_SRC_TMG_SEL2,
+	RSND_REG_SRC_CTRL,
+	RSND_REG_SSI_MODE0,
+	RSND_REG_SSI_MODE1,
+	RSND_REG_BUSIF_MODE,
+	RSND_REG_BUSIF_ADINR,
+
+	/* ADG */
+	RSND_REG_BRRA,
+	RSND_REG_BRRB,
+	RSND_REG_SSICKR,
+	RSND_REG_AUDIO_CLK_SEL0,
+	RSND_REG_AUDIO_CLK_SEL1,
+	RSND_REG_AUDIO_CLK_SEL2,
+	RSND_REG_AUDIO_CLK_SEL3,
+	RSND_REG_AUDIO_CLK_SEL4,
+	RSND_REG_AUDIO_CLK_SEL5,
+
+	/* SSI */
+	RSND_REG_SSICR,
+	RSND_REG_SSISR,
+	RSND_REG_SSITDR,
+	RSND_REG_SSIRDR,
+	RSND_REG_SSIWSR,
+
+	RSND_REG_MAX,
+};
+
+struct rsnd_priv;
+struct rsnd_mod;
+struct rsnd_dai;
+struct rsnd_dai_stream;
+
+/*
+ *	R-Car basic functions
+ */
+#define rsnd_mod_read(m, r) \
+	rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r)
+#define rsnd_mod_write(m, r, d) \
+	rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
+#define rsnd_mod_bset(m, r, s, d) \
+	rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
+
+#define rsnd_priv_read(p, r)		rsnd_read(p, NULL, RSND_REG_##r)
+#define rsnd_priv_write(p, r, d)	rsnd_write(p, NULL, RSND_REG_##r, d)
+#define rsnd_priv_bset(p, r, s, d)	rsnd_bset(p, NULL, RSND_REG_##r, s, d)
+
+u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
+void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
+		enum rsnd_reg reg, u32 data);
+void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
+		    u32 mask, u32 data);
+
+/*
+ *	R-Car DMA
+ */
+struct rsnd_dma {
+	struct rsnd_priv	*priv;
+	struct sh_dmae_slave	slave;
+	struct work_struct	work;
+	struct dma_chan		*chan;
+	enum dma_data_direction dir;
+	int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len);
+	int (*complete)(struct rsnd_dma *dma);
+
+	int submit_loop;
+};
+
+void rsnd_dma_start(struct rsnd_dma *dma);
+void rsnd_dma_stop(struct rsnd_dma *dma);
+int rsnd_dma_available(struct rsnd_dma *dma);
+int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
+	int is_play, int id,
+	int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len),
+	int (*complete)(struct rsnd_dma *dma));
+void  rsnd_dma_quit(struct rsnd_priv *priv,
+		    struct rsnd_dma *dma);
+
+
+/*
+ *	R-Car sound mod
+ */
+
+struct rsnd_mod_ops {
+	char *name;
+	int (*init)(struct rsnd_mod *mod,
+		    struct rsnd_dai *rdai,
+		    struct rsnd_dai_stream *io);
+	int (*quit)(struct rsnd_mod *mod,
+		    struct rsnd_dai *rdai,
+		    struct rsnd_dai_stream *io);
+	int (*start)(struct rsnd_mod *mod,
+		     struct rsnd_dai *rdai,
+		     struct rsnd_dai_stream *io);
+	int (*stop)(struct rsnd_mod *mod,
+		    struct rsnd_dai *rdai,
+		    struct rsnd_dai_stream *io);
+};
+
+struct rsnd_mod {
+	int id;
+	struct rsnd_priv *priv;
+	struct rsnd_mod_ops *ops;
+	struct list_head list; /* connect to rsnd_dai playback/capture */
+	struct rsnd_dma dma;
+};
+
+#define rsnd_mod_to_priv(mod) ((mod)->priv)
+#define rsnd_mod_to_dma(mod) (&(mod)->dma)
+#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
+#define rsnd_mod_id(mod) ((mod)->id)
+#define for_each_rsnd_mod(pos, n, io)	\
+	list_for_each_entry_safe(pos, n, &(io)->head, list)
+#define rsnd_mod_call(mod, func, rdai, io)	\
+	(!(mod) ? -ENODEV :			\
+	 !((mod)->ops->func) ? 0 :		\
+	 (mod)->ops->func(mod, rdai, io))
+
+void rsnd_mod_init(struct rsnd_priv *priv,
+		   struct rsnd_mod *mod,
+		   struct rsnd_mod_ops *ops,
+		   int id);
+char *rsnd_mod_name(struct rsnd_mod *mod);
+
+/*
+ *	R-Car sound DAI
+ */
+#define RSND_DAI_NAME_SIZE	16
+struct rsnd_dai_stream {
+	struct list_head head; /* head of rsnd_mod list */
+	struct snd_pcm_substream *substream;
+	int byte_pos;
+	int period_pos;
+	int byte_per_period;
+	int next_period_byte;
+};
+
+struct rsnd_dai {
+	char name[RSND_DAI_NAME_SIZE];
+	struct rsnd_dai_platform_info *info; /* rcar_snd.h */
+	struct rsnd_dai_stream playback;
+	struct rsnd_dai_stream capture;
+
+	int clk_master:1;
+	int bit_clk_inv:1;
+	int frm_clk_inv:1;
+	int sys_delay:1;
+	int data_alignment:1;
+};
+
+#define rsnd_dai_nr(priv) ((priv)->dai_nr)
+#define for_each_rsnd_dai(rdai, priv, i)		\
+	for (i = 0, (rdai) = rsnd_dai_get(priv, i);	\
+	     i < rsnd_dai_nr(priv);			\
+	     i++, (rdai) = rsnd_dai_get(priv, i))
+
+struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id);
+int rsnd_dai_disconnect(struct rsnd_mod *mod);
+int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod,
+		     struct rsnd_dai_stream *io);
+int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
+int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai);
+#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
+#define rsnd_io_to_runtime(io) ((io)->substream->runtime)
+
+void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
+int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
+
+/*
+ *	R-Car Gen1/Gen2
+ */
+int rsnd_gen_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv);
+void rsnd_gen_remove(struct platform_device *pdev,
+		     struct rsnd_priv *priv);
+int rsnd_gen_path_init(struct rsnd_priv *priv,
+		       struct rsnd_dai *rdai,
+		       struct rsnd_dai_stream *io);
+int rsnd_gen_path_exit(struct rsnd_priv *priv,
+		       struct rsnd_dai *rdai,
+		       struct rsnd_dai_stream *io);
+void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
+			       struct rsnd_mod *mod,
+			       enum rsnd_reg reg);
+#define rsnd_is_gen1(s)		((s)->info->flags & RSND_GEN1)
+#define rsnd_is_gen2(s)		((s)->info->flags & RSND_GEN2)
+
+/*
+ *	R-Car ADG
+ */
+int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
+int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
+int rsnd_adg_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv);
+void rsnd_adg_remove(struct platform_device *pdev,
+		   struct rsnd_priv *priv);
+
+/*
+ *	R-Car sound priv
+ */
+struct rsnd_priv {
+
+	struct device *dev;
+	struct rcar_snd_info *info;
+	spinlock_t lock;
+
+	/*
+	 * below value will be filled on rsnd_gen_probe()
+	 */
+	void *gen;
+
+	/*
+	 * below value will be filled on rsnd_scu_probe()
+	 */
+	void *scu;
+	int scu_nr;
+
+	/*
+	 * below value will be filled on rsnd_adg_probe()
+	 */
+	void *adg;
+
+	/*
+	 * below value will be filled on rsnd_ssi_probe()
+	 */
+	void *ssiu;
+
+	/*
+	 * below value will be filled on rsnd_dai_probe()
+	 */
+	struct snd_soc_dai_driver *daidrv;
+	struct rsnd_dai *rdai;
+	int dai_nr;
+};
+
+#define rsnd_priv_to_dev(priv)	((priv)->dev)
+#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
+#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
+
+/*
+ *	R-Car SCU
+ */
+int rsnd_scu_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv);
+void rsnd_scu_remove(struct platform_device *pdev,
+		     struct rsnd_priv *priv);
+struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
+#define rsnd_scu_nr(priv) ((priv)->scu_nr)
+
+/*
+ *	R-Car SSI
+ */
+int rsnd_ssi_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv);
+void rsnd_ssi_remove(struct platform_device *pdev,
+		   struct rsnd_priv *priv);
+struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
+struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
+					  int dai_id, int is_play);
+
+#endif
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c
new file mode 100644
index 0000000..184d900
--- /dev/null
+++ b/sound/soc/sh/rcar/scu.c
@@ -0,0 +1,236 @@
+/*
+ * Renesas R-Car SCU support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "rsnd.h"
+
+struct rsnd_scu {
+	struct rsnd_scu_platform_info *info; /* rcar_snd.h */
+	struct rsnd_mod mod;
+};
+
+#define rsnd_scu_mode_flags(p) ((p)->info->flags)
+
+/*
+ * ADINR
+ */
+#define OTBL_24		(0 << 16)
+#define OTBL_22		(2 << 16)
+#define OTBL_20		(4 << 16)
+#define OTBL_18		(6 << 16)
+#define OTBL_16		(8 << 16)
+
+
+#define rsnd_mod_to_scu(_mod)	\
+	container_of((_mod), struct rsnd_scu, mod)
+
+#define for_each_rsnd_scu(pos, priv, i)					\
+	for ((i) = 0;							\
+	     ((i) < rsnd_scu_nr(priv)) &&				\
+		     ((pos) = (struct rsnd_scu *)(priv)->scu + i);	\
+	     i++)
+
+static int rsnd_scu_set_route(struct rsnd_priv *priv,
+			      struct rsnd_mod *mod,
+			      struct rsnd_dai *rdai,
+			      struct rsnd_dai_stream *io)
+{
+	struct scu_route_config {
+		u32 mask;
+		int shift;
+	} routes[] = {
+		{ 0xF,  0, }, /* 0 */
+		{ 0xF,  4, }, /* 1 */
+		{ 0xF,  8, }, /* 2 */
+		{ 0x7, 12, }, /* 3 */
+		{ 0x7, 16, }, /* 4 */
+		{ 0x7, 20, }, /* 5 */
+		{ 0x7, 24, }, /* 6 */
+		{ 0x3, 28, }, /* 7 */
+		{ 0x3, 30, }, /* 8 */
+	};
+
+	u32 mask;
+	u32 val;
+	int shift;
+	int id;
+
+	/*
+	 * Gen1 only
+	 */
+	if (!rsnd_is_gen1(priv))
+		return 0;
+
+	id = rsnd_mod_id(mod);
+	if (id < 0 || id > ARRAY_SIZE(routes))
+		return -EIO;
+
+	/*
+	 * SRC_ROUTE_SELECT
+	 */
+	val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2;
+	val = val		<< routes[id].shift;
+	mask = routes[id].mask	<< routes[id].shift;
+
+	rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val);
+
+	/*
+	 * SRC_TIMING_SELECT
+	 */
+	shift	= (id % 4) * 8;
+	mask	= 0x1F << shift;
+	if (8 == id) /* SRU8 is very special */
+		val = id << shift;
+	else
+		val = (id + 1) << shift;
+
+	switch (id / 4) {
+	case 0:
+		rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val);
+		break;
+	case 1:
+		rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val);
+		break;
+	case 2:
+		rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val);
+		break;
+	}
+
+	return 0;
+}
+
+static int rsnd_scu_set_mode(struct rsnd_priv *priv,
+			     struct rsnd_mod *mod,
+			     struct rsnd_dai *rdai,
+			     struct rsnd_dai_stream *io)
+{
+	int id = rsnd_mod_id(mod);
+	u32 val;
+
+	if (rsnd_is_gen1(priv)) {
+		val = (1 << id);
+		rsnd_mod_bset(mod, SRC_CTRL, val, val);
+	}
+
+	return 0;
+}
+
+static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
+			      struct rsnd_mod *mod,
+			      struct rsnd_dai *rdai,
+			      struct rsnd_dai_stream *io)
+{
+	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+	u32 adinr = runtime->channels;
+
+	switch (runtime->sample_bits) {
+	case 16:
+		adinr |= OTBL_16;
+		break;
+	case 32:
+		adinr |= OTBL_24;
+		break;
+	default:
+		return -EIO;
+	}
+
+	rsnd_mod_write(mod, BUSIF_MODE, 1);
+	rsnd_mod_write(mod, BUSIF_ADINR, adinr);
+
+	return 0;
+}
+
+static int rsnd_scu_start(struct rsnd_mod *mod,
+			  struct rsnd_dai *rdai,
+			  struct rsnd_dai_stream *io)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 flags = rsnd_scu_mode_flags(scu);
+	int ret;
+
+	/*
+	 * SCU will be used if it has RSND_SCU_USB_HPBIF flags
+	 */
+	if (!(flags & RSND_SCU_USB_HPBIF)) {
+		/* it use PIO transter */
+		dev_dbg(dev, "%s%d is not used\n",
+			rsnd_mod_name(mod), rsnd_mod_id(mod));
+
+		return 0;
+	}
+
+	/* it use DMA transter */
+	ret = rsnd_scu_set_route(priv, mod, rdai, io);
+	if (ret < 0)
+		return ret;
+
+	ret = rsnd_scu_set_mode(priv, mod, rdai, io);
+	if (ret < 0)
+		return ret;
+
+	ret = rsnd_scu_set_hpbif(priv, mod, rdai, io);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
+
+	return 0;
+}
+
+static struct rsnd_mod_ops rsnd_scu_ops = {
+	.name	= "scu",
+	.start	= rsnd_scu_start,
+};
+
+struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id)
+{
+	BUG_ON(id < 0 || id >= rsnd_scu_nr(priv));
+
+	return &((struct rsnd_scu *)(priv->scu) + id)->mod;
+}
+
+int rsnd_scu_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv)
+{
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_scu *scu;
+	int i, nr;
+
+	/*
+	 * init SCU
+	 */
+	nr	= info->scu_info_nr;
+	scu	= devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL);
+	if (!scu) {
+		dev_err(dev, "SCU allocate failed\n");
+		return -ENOMEM;
+	}
+
+	priv->scu_nr	= nr;
+	priv->scu	= scu;
+
+	for_each_rsnd_scu(scu, priv, i) {
+		rsnd_mod_init(priv, &scu->mod,
+			      &rsnd_scu_ops, i);
+		scu->info = &info->scu_info[i];
+
+		dev_dbg(dev, "SCU%d probed\n", i);
+	}
+	dev_dbg(dev, "scu probed\n");
+
+	return 0;
+}
+
+void rsnd_scu_remove(struct platform_device *pdev,
+		     struct rsnd_priv *priv)
+{
+}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
new file mode 100644
index 0000000..fae26d3
--- /dev/null
+++ b/sound/soc/sh/rcar/ssi.c
@@ -0,0 +1,728 @@
+/*
+ * Renesas R-Car SSIU/SSI support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on fsi.c
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include "rsnd.h"
+#define RSND_SSI_NAME_SIZE 16
+
+/*
+ * SSICR
+ */
+#define	FORCE		(1 << 31)	/* Fixed */
+#define	DMEN		(1 << 28)	/* DMA Enable */
+#define	UIEN		(1 << 27)	/* Underflow Interrupt Enable */
+#define	OIEN		(1 << 26)	/* Overflow Interrupt Enable */
+#define	IIEN		(1 << 25)	/* Idle Mode Interrupt Enable */
+#define	DIEN		(1 << 24)	/* Data Interrupt Enable */
+
+#define	DWL_8		(0 << 19)	/* Data Word Length */
+#define	DWL_16		(1 << 19)	/* Data Word Length */
+#define	DWL_18		(2 << 19)	/* Data Word Length */
+#define	DWL_20		(3 << 19)	/* Data Word Length */
+#define	DWL_22		(4 << 19)	/* Data Word Length */
+#define	DWL_24		(5 << 19)	/* Data Word Length */
+#define	DWL_32		(6 << 19)	/* Data Word Length */
+
+#define	SWL_32		(3 << 16)	/* R/W System Word Length */
+#define	SCKD		(1 << 15)	/* Serial Bit Clock Direction */
+#define	SWSD		(1 << 14)	/* Serial WS Direction */
+#define	SCKP		(1 << 13)	/* Serial Bit Clock Polarity */
+#define	SWSP		(1 << 12)	/* Serial WS Polarity */
+#define	SDTA		(1 << 10)	/* Serial Data Alignment */
+#define	DEL		(1 <<  8)	/* Serial Data Delay */
+#define	CKDV(v)		(v <<  4)	/* Serial Clock Division Ratio */
+#define	TRMD		(1 <<  1)	/* Transmit/Receive Mode Select */
+#define	EN		(1 <<  0)	/* SSI Module Enable */
+
+/*
+ * SSISR
+ */
+#define	UIRQ		(1 << 27)	/* Underflow Error Interrupt Status */
+#define	OIRQ		(1 << 26)	/* Overflow Error Interrupt Status */
+#define	IIRQ		(1 << 25)	/* Idle Mode Interrupt Status */
+#define	DIRQ		(1 << 24)	/* Data Interrupt Status Flag */
+
+/*
+ * SSIWSR
+ */
+#define CONT		(1 << 8)	/* WS Continue Function */
+
+struct rsnd_ssi {
+	struct clk *clk;
+	struct rsnd_ssi_platform_info *info; /* rcar_snd.h */
+	struct rsnd_ssi *parent;
+	struct rsnd_mod mod;
+
+	struct rsnd_dai *rdai;
+	struct rsnd_dai_stream *io;
+	u32 cr_own;
+	u32 cr_clk;
+	u32 cr_etc;
+	int err;
+	int dma_offset;
+	unsigned int usrcnt;
+	unsigned int rate;
+};
+
+struct rsnd_ssiu {
+	u32 ssi_mode0;
+	u32 ssi_mode1;
+
+	int ssi_nr;
+	struct rsnd_ssi *ssi;
+};
+
+#define for_each_rsnd_ssi(pos, priv, i)					\
+	for (i = 0;							\
+	     (i < rsnd_ssi_nr(priv)) &&					\
+		((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \
+	     i++)
+
+#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr)
+#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
+#define rsnd_dma_to_ssi(dma)  rsnd_mod_to_ssi(rsnd_dma_to_mod(dma))
+#define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0)
+#define rsnd_ssi_dma_available(ssi) \
+	rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod))
+#define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent)
+#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
+#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
+#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
+#define rsnd_ssi_to_ssiu(ssi)\
+	(((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1)
+
+static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
+			       struct rsnd_ssiu *ssiu)
+{
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_ssi *ssi;
+	u32 flags;
+	u32 val;
+	int i;
+
+	/*
+	 * SSI_MODE0
+	 */
+	ssiu->ssi_mode0 = 0;
+	for_each_rsnd_ssi(ssi, priv, i) {
+		flags = rsnd_ssi_mode_flags(ssi);
+
+		/* see also BUSIF_MODE */
+		if (!(flags & RSND_SSI_DEPENDENT)) {
+			ssiu->ssi_mode0 |= (1 << i);
+			dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", i);
+		} else {
+			dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", i);
+		}
+	}
+
+	/*
+	 * SSI_MODE1
+	 */
+#define ssi_parent_set(p, sync, adg, ext)		\
+	do {						\
+		ssi->parent = ssiu->ssi + p;		\
+		if (flags & RSND_SSI_CLK_FROM_ADG)	\
+			val = adg;			\
+		else					\
+			val = ext;			\
+		if (flags & RSND_SSI_SYNC)		\
+			val |= sync;			\
+	} while (0)
+
+	ssiu->ssi_mode1 = 0;
+	for_each_rsnd_ssi(ssi, priv, i) {
+		flags = rsnd_ssi_mode_flags(ssi);
+
+		if (!(flags & RSND_SSI_CLK_PIN_SHARE))
+			continue;
+
+		val = 0;
+		switch (i) {
+		case 1:
+			ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0));
+			break;
+		case 2:
+			ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2));
+			break;
+		case 4:
+			ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16));
+			break;
+		case 8:
+			ssi_parent_set(7, 0, 0, 0);
+			break;
+		}
+
+		ssiu->ssi_mode1 |= val;
+	}
+}
+
+static void rsnd_ssi_mode_set(struct rsnd_ssi *ssi)
+{
+	struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
+
+	rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0);
+	rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1);
+}
+
+static void rsnd_ssi_status_check(struct rsnd_mod *mod,
+				  u32 bit)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 status;
+	int i;
+
+	for (i = 0; i < 1024; i++) {
+		status = rsnd_mod_read(mod, SSISR);
+		if (status & bit)
+			return;
+
+		udelay(50);
+	}
+
+	dev_warn(dev, "status check failed\n");
+}
+
+static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
+				     unsigned int rate)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	int i, j, ret;
+	int adg_clk_div_table[] = {
+		1, 6, /* see adg.c */
+	};
+	int ssi_clk_mul_table[] = {
+		1, 2, 4, 8, 16, 6, 12,
+	};
+	unsigned int main_rate;
+
+	/*
+	 * Find best clock, and try to start ADG
+	 */
+	for (i = 0; i < ARRAY_SIZE(adg_clk_div_table); i++) {
+		for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
+
+			/*
+			 * this driver is assuming that
+			 * system word is 64fs (= 2 x 32bit)
+			 * see rsnd_ssi_start()
+			 */
+			main_rate = rate / adg_clk_div_table[i]
+				* 32 * 2 * ssi_clk_mul_table[j];
+
+			ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate);
+			if (0 == ret) {
+				ssi->rate	= rate;
+				ssi->cr_clk	= FORCE | SWL_32 |
+						  SCKD | SWSD | CKDV(j);
+
+				dev_dbg(dev, "ssi%d outputs %u Hz\n",
+					rsnd_mod_id(&ssi->mod), rate);
+
+				return 0;
+			}
+		}
+	}
+
+	dev_err(dev, "unsupported clock rate\n");
+	return -EIO;
+}
+
+static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi)
+{
+	ssi->rate = 0;
+	ssi->cr_clk = 0;
+	rsnd_adg_ssi_clk_stop(&ssi->mod);
+}
+
+static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
+			      struct rsnd_dai *rdai,
+			      struct rsnd_dai_stream *io)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 cr;
+
+	if (0 == ssi->usrcnt) {
+		clk_enable(ssi->clk);
+
+		if (rsnd_rdai_is_clk_master(rdai)) {
+			struct snd_pcm_runtime *runtime;
+
+			runtime = rsnd_io_to_runtime(io);
+
+			if (rsnd_ssi_clk_from_parent(ssi))
+				rsnd_ssi_hw_start(ssi->parent, rdai, io);
+			else
+				rsnd_ssi_master_clk_start(ssi, runtime->rate);
+		}
+	}
+
+	cr  =	ssi->cr_own	|
+		ssi->cr_clk	|
+		ssi->cr_etc	|
+		EN;
+
+	rsnd_mod_write(&ssi->mod, SSICR, cr);
+
+	ssi->usrcnt++;
+
+	dev_dbg(dev, "ssi%d hw started\n", rsnd_mod_id(&ssi->mod));
+}
+
+static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
+			     struct rsnd_dai *rdai)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 cr;
+
+	if (0 == ssi->usrcnt) /* stop might be called without start */
+		return;
+
+	ssi->usrcnt--;
+
+	if (0 == ssi->usrcnt) {
+		/*
+		 * disable all IRQ,
+		 * and, wait all data was sent
+		 */
+		cr  =	ssi->cr_own	|
+			ssi->cr_clk;
+
+		rsnd_mod_write(&ssi->mod, SSICR, cr | EN);
+		rsnd_ssi_status_check(&ssi->mod, DIRQ);
+
+		/*
+		 * disable SSI,
+		 * and, wait idle state
+		 */
+		rsnd_mod_write(&ssi->mod, SSICR, cr);	/* disabled all */
+		rsnd_ssi_status_check(&ssi->mod, IIRQ);
+
+		if (rsnd_rdai_is_clk_master(rdai)) {
+			if (rsnd_ssi_clk_from_parent(ssi))
+				rsnd_ssi_hw_stop(ssi->parent, rdai);
+			else
+				rsnd_ssi_master_clk_stop(ssi);
+		}
+
+		clk_disable(ssi->clk);
+	}
+
+	dev_dbg(dev, "ssi%d hw stopped\n", rsnd_mod_id(&ssi->mod));
+}
+
+/*
+ *	SSI mod common functions
+ */
+static int rsnd_ssi_init(struct rsnd_mod *mod,
+			 struct rsnd_dai *rdai,
+			 struct rsnd_dai_stream *io)
+{
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+	u32 cr;
+
+	cr = FORCE;
+
+	/*
+	 * always use 32bit system word for easy clock calculation.
+	 * see also rsnd_ssi_master_clk_enable()
+	 */
+	cr |= SWL_32;
+
+	/*
+	 * init clock settings for SSICR
+	 */
+	switch (runtime->sample_bits) {
+	case 16:
+		cr |= DWL_16;
+		break;
+	case 32:
+		cr |= DWL_24;
+		break;
+	default:
+		return -EIO;
+	}
+
+	if (rdai->bit_clk_inv)
+		cr |= SCKP;
+	if (rdai->frm_clk_inv)
+		cr |= SWSP;
+	if (rdai->data_alignment)
+		cr |= SDTA;
+	if (rdai->sys_delay)
+		cr |= DEL;
+	if (rsnd_dai_is_play(rdai, io))
+		cr |= TRMD;
+
+	/*
+	 * set ssi parameter
+	 */
+	ssi->rdai	= rdai;
+	ssi->io		= io;
+	ssi->cr_own	= cr;
+	ssi->err	= -1; /* ignore 1st error */
+
+	rsnd_ssi_mode_set(ssi);
+
+	dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
+
+	return 0;
+}
+
+static int rsnd_ssi_quit(struct rsnd_mod *mod,
+			 struct rsnd_dai *rdai,
+			 struct rsnd_dai_stream *io)
+{
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
+
+	if (ssi->err > 0)
+		dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err);
+
+	ssi->rdai	= NULL;
+	ssi->io		= NULL;
+	ssi->cr_own	= 0;
+	ssi->err	= 0;
+
+	return 0;
+}
+
+static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
+{
+	/* under/over flow error */
+	if (status & (UIRQ | OIRQ)) {
+		ssi->err++;
+
+		/* clear error status */
+		rsnd_mod_write(&ssi->mod, SSISR, 0);
+	}
+}
+
+/*
+ *		SSI PIO
+ */
+static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
+{
+	struct rsnd_ssi *ssi = data;
+	struct rsnd_dai_stream *io = ssi->io;
+	u32 status = rsnd_mod_read(&ssi->mod, SSISR);
+	irqreturn_t ret = IRQ_NONE;
+
+	if (io && (status & DIRQ)) {
+		struct rsnd_dai *rdai = ssi->rdai;
+		struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+		u32 *buf = (u32 *)(runtime->dma_area +
+				   rsnd_dai_pointer_offset(io, 0));
+
+		rsnd_ssi_record_error(ssi, status);
+
+		/*
+		 * 8/16/32 data can be assesse to TDR/RDR register
+		 * directly as 32bit data
+		 * see rsnd_ssi_init()
+		 */
+		if (rsnd_dai_is_play(rdai, io))
+			rsnd_mod_write(&ssi->mod, SSITDR, *buf);
+		else
+			*buf = rsnd_mod_read(&ssi->mod, SSIRDR);
+
+		rsnd_dai_pointer_update(io, sizeof(*buf));
+
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
+			      struct rsnd_dai *rdai,
+			      struct rsnd_dai_stream *io)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	/* enable PIO IRQ */
+	ssi->cr_etc = UIEN | OIEN | DIEN;
+
+	rsnd_ssi_hw_start(ssi, rdai, io);
+
+	dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
+
+	return 0;
+}
+
+static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
+			     struct rsnd_dai *rdai,
+			     struct rsnd_dai_stream *io)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+
+	dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
+
+	ssi->cr_etc = 0;
+
+	rsnd_ssi_hw_stop(ssi, rdai);
+
+	return 0;
+}
+
+static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
+	.name	= "ssi (pio)",
+	.init	= rsnd_ssi_init,
+	.quit	= rsnd_ssi_quit,
+	.start	= rsnd_ssi_pio_start,
+	.stop	= rsnd_ssi_pio_stop,
+};
+
+static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len)
+{
+	struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
+	struct rsnd_dai_stream *io = ssi->io;
+	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+
+	*len = io->byte_per_period;
+	*buf = runtime->dma_addr +
+		rsnd_dai_pointer_offset(io, ssi->dma_offset + *len);
+	ssi->dma_offset = *len; /* it cares A/B plane */
+
+	return 0;
+}
+
+static int rsnd_ssi_dma_complete(struct rsnd_dma *dma)
+{
+	struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
+	struct rsnd_dai_stream *io = ssi->io;
+	u32 status = rsnd_mod_read(&ssi->mod, SSISR);
+
+	rsnd_ssi_record_error(ssi, status);
+
+	rsnd_dai_pointer_update(ssi->io, io->byte_per_period);
+
+	return 0;
+}
+
+static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
+			      struct rsnd_dai *rdai,
+			      struct rsnd_dai_stream *io)
+{
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);
+
+	/* enable DMA transfer */
+	ssi->cr_etc = DMEN;
+	ssi->dma_offset = 0;
+
+	rsnd_dma_start(dma);
+
+	rsnd_ssi_hw_start(ssi, ssi->rdai, io);
+
+	/* enable WS continue */
+	if (rsnd_rdai_is_clk_master(rdai))
+		rsnd_mod_write(&ssi->mod, SSIWSR, CONT);
+
+	return 0;
+}
+
+static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
+			     struct rsnd_dai *rdai,
+			     struct rsnd_dai_stream *io)
+{
+	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);
+
+	ssi->cr_etc = 0;
+
+	rsnd_ssi_hw_stop(ssi, rdai);
+
+	rsnd_dma_stop(dma);
+
+	return 0;
+}
+
+static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
+	.name	= "ssi (dma)",
+	.init	= rsnd_ssi_init,
+	.quit	= rsnd_ssi_quit,
+	.start	= rsnd_ssi_dma_start,
+	.stop	= rsnd_ssi_dma_stop,
+};
+
+/*
+ *		Non SSI
+ */
+static int rsnd_ssi_non(struct rsnd_mod *mod,
+			struct rsnd_dai *rdai,
+			struct rsnd_dai_stream *io)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	return 0;
+}
+
+static struct rsnd_mod_ops rsnd_ssi_non_ops = {
+	.name	= "ssi (non)",
+	.init	= rsnd_ssi_non,
+	.quit	= rsnd_ssi_non,
+	.start	= rsnd_ssi_non,
+	.stop	= rsnd_ssi_non,
+};
+
+/*
+ *		ssi mod function
+ */
+struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
+					  int dai_id, int is_play)
+{
+	struct rsnd_ssi *ssi;
+	int i, has_play;
+
+	is_play = !!is_play;
+
+	for_each_rsnd_ssi(ssi, priv, i) {
+		if (rsnd_ssi_dai_id(ssi) != dai_id)
+			continue;
+
+		has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY);
+
+		if (is_play == has_play)
+			return &ssi->mod;
+	}
+
+	return NULL;
+}
+
+struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
+{
+	BUG_ON(id < 0 || id >= rsnd_ssi_nr(priv));
+
+	return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod;
+}
+
+int rsnd_ssi_probe(struct platform_device *pdev,
+		   struct rcar_snd_info *info,
+		   struct rsnd_priv *priv)
+{
+	struct rsnd_ssi_platform_info *pinfo;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_mod_ops *ops;
+	struct clk *clk;
+	struct rsnd_ssiu *ssiu;
+	struct rsnd_ssi *ssi;
+	char name[RSND_SSI_NAME_SIZE];
+	int i, nr, ret;
+
+	/*
+	 *	init SSI
+	 */
+	nr	= info->ssi_info_nr;
+	ssiu	= devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr),
+			       GFP_KERNEL);
+	if (!ssiu) {
+		dev_err(dev, "SSI allocate failed\n");
+		return -ENOMEM;
+	}
+
+	priv->ssiu	= ssiu;
+	ssiu->ssi	= (struct rsnd_ssi *)(ssiu + 1);
+	ssiu->ssi_nr	= nr;
+
+	for_each_rsnd_ssi(ssi, priv, i) {
+		pinfo = &info->ssi_info[i];
+
+		snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i);
+
+		clk = clk_get(dev, name);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+
+		ssi->info	= pinfo;
+		ssi->clk	= clk;
+
+		ops = &rsnd_ssi_non_ops;
+
+		/*
+		 * SSI DMA case
+		 */
+		if (pinfo->dma_id > 0) {
+			ret = rsnd_dma_init(
+				priv, rsnd_mod_to_dma(&ssi->mod),
+				(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY),
+				pinfo->dma_id,
+				rsnd_ssi_dma_inquiry,
+				rsnd_ssi_dma_complete);
+			if (ret < 0)
+				dev_info(dev, "SSI DMA failed. try PIO transter\n");
+			else
+				ops	= &rsnd_ssi_dma_ops;
+
+			dev_dbg(dev, "SSI%d use DMA transfer\n", i);
+		}
+
+		/*
+		 * SSI PIO case
+		 */
+		if (!rsnd_ssi_dma_available(ssi) &&
+		     rsnd_ssi_pio_available(ssi)) {
+			ret = devm_request_irq(dev, pinfo->pio_irq,
+					       &rsnd_ssi_pio_interrupt,
+					       IRQF_SHARED,
+					       dev_name(dev), ssi);
+			if (ret) {
+				dev_err(dev, "SSI request interrupt failed\n");
+				return ret;
+			}
+
+			ops	= &rsnd_ssi_pio_ops;
+
+			dev_dbg(dev, "SSI%d use PIO transfer\n", i);
+		}
+
+		rsnd_mod_init(priv, &ssi->mod, ops, i);
+	}
+
+	rsnd_ssi_mode_init(priv, ssiu);
+
+	dev_dbg(dev, "ssi probed\n");
+
+	return 0;
+}
+
+void rsnd_ssi_remove(struct platform_device *pdev,
+		   struct rsnd_priv *priv)
+{
+	struct rsnd_ssi *ssi;
+	int i;
+
+	for_each_rsnd_ssi(ssi, priv, i) {
+		clk_put(ssi->clk);
+		if (rsnd_ssi_dma_available(ssi))
+			rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod));
+	}
+
+}
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 06a8000..d220150 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -334,7 +334,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream,
 	return ret;
 }
 
-static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
+static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
 				struct snd_compr_metadata *metadata)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -347,7 +347,7 @@ static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
 	return ret;
 }
 
-static int sst_compr_get_metadata(struct snd_compr_stream *cstream,
+static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
 				struct snd_compr_metadata *metadata)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -364,8 +364,8 @@ static struct snd_compr_ops soc_compr_ops = {
 	.open		= soc_compr_open,
 	.free		= soc_compr_free,
 	.set_params	= soc_compr_set_params,
-	.set_metadata   = sst_compr_set_metadata,
-	.get_metadata	= sst_compr_get_metadata,
+	.set_metadata   = soc_compr_set_metadata,
+	.get_metadata	= soc_compr_get_metadata,
 	.get_params	= soc_compr_get_params,
 	.trigger	= soc_compr_trigger,
 	.pointer	= soc_compr_pointer,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d82ee38..21f0e6a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -192,7 +192,7 @@ static ssize_t pmdown_time_set(struct device *dev,
 	struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
 	int ret;
 
-	ret = strict_strtol(buf, 10, &rtd->pmdown_time);
+	ret = kstrtol(buf, 10, &rtd->pmdown_time);
 	if (ret)
 		return ret;
 
@@ -237,6 +237,7 @@ static ssize_t codec_reg_write_file(struct file *file,
 	char *start = buf;
 	unsigned long reg, value;
 	struct snd_soc_codec *codec = file->private_data;
+	int ret;
 
 	buf_size = min(count, (sizeof(buf)-1));
 	if (copy_from_user(buf, user_buf, buf_size))
@@ -248,8 +249,9 @@ static ssize_t codec_reg_write_file(struct file *file,
 	reg = simple_strtoul(start, &start, 16);
 	while (*start == ' ')
 		start++;
-	if (strict_strtoul(start, 16, &value))
-		return -EINVAL;
+	ret = kstrtoul(start, 16, &value);
+	if (ret)
+		return ret;
 
 	/* Userspace has been fiddling around behind the kernel's back */
 	add_taint(TAINT_USER, LOCKDEP_NOW_UNRELIABLE);
@@ -2299,6 +2301,22 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
 	return 0;
 }
 
+struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
+					       const char *name)
+{
+	struct snd_card *card = soc_card->snd_card;
+	struct snd_kcontrol *kctl;
+
+	if (unlikely(!name))
+		return NULL;
+
+	list_for_each_entry(kctl, &card->controls, list)
+		if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
+			return kctl;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
+
 /**
  * snd_soc_add_codec_controls - add an array of controls to a codec.
  * Convenience function to add a list of controls. Many codecs were
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index bd16010..2da258b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -47,6 +47,15 @@
 
 #define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
 
+static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
+	struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
+	const char *control,
+	int (*connected)(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink));
+static struct snd_soc_dapm_widget *
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
+			 const struct snd_soc_dapm_widget *widget);
+
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
 	[snd_soc_dapm_pre] = 0,
@@ -73,16 +82,18 @@ static int dapm_up_seq[] = {
 	[snd_soc_dapm_hp] = 10,
 	[snd_soc_dapm_spk] = 10,
 	[snd_soc_dapm_line] = 10,
-	[snd_soc_dapm_post] = 11,
+	[snd_soc_dapm_kcontrol] = 11,
+	[snd_soc_dapm_post] = 12,
 };
 
 static int dapm_down_seq[] = {
 	[snd_soc_dapm_pre] = 0,
-	[snd_soc_dapm_adc] = 1,
-	[snd_soc_dapm_hp] = 2,
-	[snd_soc_dapm_spk] = 2,
-	[snd_soc_dapm_line] = 2,
-	[snd_soc_dapm_out_drv] = 2,
+	[snd_soc_dapm_kcontrol] = 1,
+	[snd_soc_dapm_adc] = 2,
+	[snd_soc_dapm_hp] = 3,
+	[snd_soc_dapm_spk] = 3,
+	[snd_soc_dapm_line] = 3,
+	[snd_soc_dapm_out_drv] = 3,
 	[snd_soc_dapm_pga] = 4,
 	[snd_soc_dapm_switch] = 5,
 	[snd_soc_dapm_mixer_named_ctl] = 5,
@@ -174,36 +185,176 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 	return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
 }
 
-/* get snd_card from DAPM context */
-static inline struct snd_card *dapm_get_snd_card(
-	struct snd_soc_dapm_context *dapm)
+struct dapm_kcontrol_data {
+	unsigned int value;
+	struct snd_soc_dapm_widget *widget;
+	struct list_head paths;
+	struct snd_soc_dapm_widget_list *wlist;
+};
+
+static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
+	struct snd_kcontrol *kcontrol)
 {
-	if (dapm->codec)
-		return dapm->codec->card->snd_card;
-	else if (dapm->platform)
-		return dapm->platform->card->snd_card;
-	else
-		BUG();
+	struct dapm_kcontrol_data *data;
+	struct soc_mixer_control *mc;
 
-	/* unreachable */
-	return NULL;
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(widget->dapm->dev,
+				"ASoC: can't allocate kcontrol data for %s\n",
+				widget->name);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&data->paths);
+
+	switch (widget->id) {
+	case snd_soc_dapm_switch:
+	case snd_soc_dapm_mixer:
+	case snd_soc_dapm_mixer_named_ctl:
+		mc = (struct soc_mixer_control *)kcontrol->private_value;
+
+		if (mc->autodisable) {
+			struct snd_soc_dapm_widget template;
+
+			memset(&template, 0, sizeof(template));
+			template.reg = mc->reg;
+			template.mask = (1 << fls(mc->max)) - 1;
+			template.shift = mc->shift;
+			if (mc->invert)
+				template.off_val = mc->max;
+			else
+				template.off_val = 0;
+			template.on_val = template.off_val;
+			template.id = snd_soc_dapm_kcontrol;
+			template.name = kcontrol->id.name;
+
+			data->widget = snd_soc_dapm_new_control(widget->dapm,
+				&template);
+			if (!data->widget) {
+				kfree(data);
+				return -ENOMEM;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	kcontrol->private_data = data;
+
+	return 0;
 }
 
-/* get soc_card from DAPM context */
-static inline struct snd_soc_card *dapm_get_soc_card(
-		struct snd_soc_dapm_context *dapm)
+static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
 {
-	if (dapm->codec)
-		return dapm->codec->card;
-	else if (dapm->platform)
-		return dapm->platform->card;
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
+	kfree(data->widget);
+	kfree(data->wlist);
+	kfree(data);
+}
+
+static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(
+	const struct snd_kcontrol *kcontrol)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+	return data->wlist;
+}
+
+static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
+	struct snd_soc_dapm_widget *widget)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget_list *new_wlist;
+	unsigned int n;
+
+	if (data->wlist)
+		n = data->wlist->num_widgets + 1;
 	else
-		BUG();
+		n = 1;
 
-	/* unreachable */
-	return NULL;
+	new_wlist = krealloc(data->wlist,
+			sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL);
+	if (!new_wlist)
+		return -ENOMEM;
+
+	new_wlist->widgets[n - 1] = widget;
+	new_wlist->num_widgets = n;
+
+	data->wlist = new_wlist;
+
+	return 0;
+}
+
+static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,
+	struct snd_soc_dapm_path *path)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+	list_add_tail(&path->list_kcontrol, &data->paths);
+
+	if (data->widget) {
+		snd_soc_dapm_add_path(data->widget->dapm, data->widget,
+		    path->source, NULL, NULL);
+	}
+}
+
+static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+	if (!data->widget)
+		return true;
+
+	return data->widget->power;
+}
+
+static struct list_head *dapm_kcontrol_get_path_list(
+	const struct snd_kcontrol *kcontrol)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+	return &data->paths;
+}
+
+#define dapm_kcontrol_for_each_path(path, kcontrol) \
+	list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
+		list_kcontrol)
+
+static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+	return data->value;
+}
+
+static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
+	unsigned int value)
+{
+	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+	if (data->value == value)
+		return false;
+
+	if (data->widget)
+		data->widget->on_val = value;
+
+	data->value = value;
+
+	return true;
 }
 
+/**
+ * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
+ * @kcontrol: The kcontrol
+ */
+struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol)
+{
+	return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);
+
 static void dapm_reset(struct snd_soc_card *card)
 {
 	struct snd_soc_dapm_widget *w;
@@ -211,6 +362,7 @@ static void dapm_reset(struct snd_soc_card *card)
 	memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
 
 	list_for_each_entry(w, &card->widgets, list) {
+		w->new_power = w->power;
 		w->power_checked = false;
 		w->inputs = -1;
 		w->outputs = -1;
@@ -428,6 +580,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 	case snd_soc_dapm_spk:
 	case snd_soc_dapm_line:
 	case snd_soc_dapm_dai_link:
+	case snd_soc_dapm_kcontrol:
 		p->connect = 1;
 	break;
 	/* does affect routing - dynamically connected */
@@ -507,11 +660,6 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
 	return 0;
 }
 
-static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
-{
-	kfree(kctl->private_data);
-}
-
 /*
  * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
  * create it. Either way, add the widget into the control's widget list
@@ -525,9 +673,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
 	size_t prefix_len;
 	int shared;
 	struct snd_kcontrol *kcontrol;
-	struct snd_soc_dapm_widget_list *wlist;
-	int wlistentries;
-	size_t wlistsize;
 	bool wname_in_long_name, kcname_in_long_name;
 	char *long_name;
 	const char *name;
@@ -546,25 +691,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
 	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
 					 &kcontrol);
 
-	if (kcontrol) {
-		wlist = kcontrol->private_data;
-		wlistentries = wlist->num_widgets + 1;
-	} else {
-		wlist = NULL;
-		wlistentries = 1;
-	}
-
-	wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
-			wlistentries * sizeof(struct snd_soc_dapm_widget *);
-	wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
-	if (wlist == NULL) {
-		dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n",
-			w->name);
-		return -ENOMEM;
-	}
-	wlist->num_widgets = wlistentries;
-	wlist->widgets[wlistentries - 1] = w;
-
 	if (!kcontrol) {
 		if (shared) {
 			wname_in_long_name = false;
@@ -587,7 +713,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
 				kcname_in_long_name = false;
 				break;
 			default:
-				kfree(wlist);
 				return -EINVAL;
 			}
 		}
@@ -602,10 +727,8 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
 			long_name = kasprintf(GFP_KERNEL, "%s %s",
 				 w->name + prefix_len,
 				 w->kcontrol_news[kci].name);
-			if (long_name == NULL) {
-				kfree(wlist);
+			if (long_name == NULL)
 				return -ENOMEM;
-			}
 
 			name = long_name;
 		} else if (wname_in_long_name) {
@@ -616,23 +739,34 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
 			name = w->kcontrol_news[kci].name;
 		}
 
-		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name,
+		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
 					prefix);
-		kcontrol->private_free = dapm_kcontrol_free;
 		kfree(long_name);
+		if (!kcontrol)
+			return -ENOMEM;
+		kcontrol->private_free = dapm_kcontrol_free;
+
+		ret = dapm_kcontrol_data_alloc(w, kcontrol);
+		if (ret) {
+			snd_ctl_free_one(kcontrol);
+			return ret;
+		}
+
 		ret = snd_ctl_add(card, kcontrol);
 		if (ret < 0) {
 			dev_err(dapm->dev,
 				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
 				w->name, name, ret);
-			kfree(wlist);
 			return ret;
 		}
 	}
 
-	kcontrol->private_data = wlist;
+	ret = dapm_kcontrol_add_widget(kcontrol, w);
+	if (ret)
+		return ret;
+
 	w->kcontrols[kci] = kcontrol;
-	path->kcontrol = kcontrol;
+	dapm_kcontrol_add_path(kcontrol, path);
 
 	return 0;
 }
@@ -652,7 +786,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
 				continue;
 
 			if (w->kcontrols[i]) {
-				path->kcontrol = w->kcontrols[i];
+				dapm_kcontrol_add_path(w->kcontrols[i], path);
 				continue;
 			}
 
@@ -679,19 +813,20 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
 		return -EINVAL;
 	}
 
-	path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
-				list_sink);
-	if (!path) {
+	if (list_empty(&w->sources)) {
 		dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
 		return -EINVAL;
 	}
 
+	path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
+				list_sink);
+
 	ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
 	if (ret < 0)
 		return ret;
 
 	list_for_each_entry(path, &w->sources, list_sink)
-		path->kcontrol = w->kcontrols[0];
+		dapm_kcontrol_add_path(w->kcontrols[0], path);
 
 	return 0;
 }
@@ -812,6 +947,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 	case snd_soc_dapm_supply:
 	case snd_soc_dapm_regulator_supply:
 	case snd_soc_dapm_clock_supply:
+	case snd_soc_dapm_kcontrol:
 		return 0;
 	default:
 		break;
@@ -907,6 +1043,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 	case snd_soc_dapm_supply:
 	case snd_soc_dapm_regulator_supply:
 	case snd_soc_dapm_clock_supply:
+	case snd_soc_dapm_kcontrol:
 		return 0;
 	default:
 		break;
@@ -1061,7 +1198,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
 	int ret;
 
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
-		if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
 			ret = regulator_allow_bypass(w->regulator, false);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
@@ -1071,7 +1208,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
 
 		return regulator_enable(w->regulator);
 	} else {
-		if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
 			ret = regulator_allow_bypass(w->regulator, true);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
@@ -1243,10 +1380,9 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
 	list_add_tail(&new_widget->power_list, list);
 }
 
-static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
+static void dapm_seq_check_event(struct snd_soc_card *card,
 				 struct snd_soc_dapm_widget *w, int event)
 {
-	struct snd_soc_card *card = dapm->card;
 	const char *ev_name;
 	int power, ret;
 
@@ -1280,55 +1416,50 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
 		return;
 	}
 
-	if (w->power != power)
+	if (w->new_power != power)
 		return;
 
 	if (w->event && (w->event_flags & event)) {
-		pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n",
+		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
 			w->name, ev_name);
 		trace_snd_soc_dapm_widget_event_start(w, event);
 		ret = w->event(w, NULL, event);
 		trace_snd_soc_dapm_widget_event_done(w, event);
 		if (ret < 0)
-			dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n",
+			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
 			       ev_name, w->name, ret);
 	}
 }
 
 /* Apply the coalesced changes from a DAPM sequence */
-static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
+static void dapm_seq_run_coalesced(struct snd_soc_card *card,
 				   struct list_head *pending)
 {
-	struct snd_soc_card *card = dapm->card;
 	struct snd_soc_dapm_widget *w;
-	int reg, power;
+	int reg;
 	unsigned int value = 0;
 	unsigned int mask = 0;
-	unsigned int cur_mask;
 
 	reg = list_first_entry(pending, struct snd_soc_dapm_widget,
 			       power_list)->reg;
 
 	list_for_each_entry(w, pending, power_list) {
-		cur_mask = 1 << w->shift;
 		BUG_ON(reg != w->reg);
+		w->power = w->new_power;
 
-		if (w->invert)
-			power = !w->power;
+		mask |= w->mask << w->shift;
+		if (w->power)
+			value |= w->on_val << w->shift;
 		else
-			power = w->power;
-
-		mask |= cur_mask;
-		if (power)
-			value |= cur_mask;
+			value |= w->off_val << w->shift;
 
-		pop_dbg(dapm->dev, card->pop_time,
+		pop_dbg(w->dapm->dev, card->pop_time,
 			"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
 			w->name, reg, value, mask);
 
 		/* Check for events */
-		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU);
-		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD);
+		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
+		dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
 	}
 
 	if (reg >= 0) {
@@ -1338,7 +1469,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
 		w = list_first_entry(pending, struct snd_soc_dapm_widget,
 				     power_list);
 
-		pop_dbg(dapm->dev, card->pop_time,
+		pop_dbg(w->dapm->dev, card->pop_time,
 			"pop test : Applying 0x%x/0x%x to %x in %dms\n",
 			value, mask, reg, card->pop_time);
 		pop_wait(card->pop_time);
@@ -1346,8 +1477,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
 	}
 
 	list_for_each_entry(w, pending, power_list) {
-		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU);
-		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD);
+		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
+		dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
 	}
 }
 
@@ -1359,8 +1490,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
  * Currently anything that requires more than a single write is not
  * handled.
  */
-static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
-			 struct list_head *list, int event, bool power_up)
+static void dapm_seq_run(struct snd_soc_card *card,
+	struct list_head *list, int event, bool power_up)
 {
 	struct snd_soc_dapm_widget *w, *n;
 	LIST_HEAD(pending);
@@ -1383,7 +1514,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
 		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
 			if (!list_empty(&pending))
-				dapm_seq_run_coalesced(cur_dapm, &pending);
+				dapm_seq_run_coalesced(card, &pending);
 
 			if (cur_dapm && cur_dapm->seq_notifier) {
 				for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
@@ -1443,7 +1574,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 	}
 
 	if (!list_empty(&pending))
-		dapm_seq_run_coalesced(cur_dapm, &pending);
+		dapm_seq_run_coalesced(card, &pending);
 
 	if (cur_dapm && cur_dapm->seq_notifier) {
 		for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
@@ -1453,37 +1584,48 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 	}
 }
 
-static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
+static void dapm_widget_update(struct snd_soc_card *card)
 {
-	struct snd_soc_dapm_update *update = dapm->update;
-	struct snd_soc_dapm_widget *w;
+	struct snd_soc_dapm_update *update = card->update;
+	struct snd_soc_dapm_widget_list *wlist;
+	struct snd_soc_dapm_widget *w = NULL;
+	unsigned int wi;
 	int ret;
 
-	if (!update)
+	if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
 		return;
 
-	w = update->widget;
+	wlist = dapm_kcontrol_get_wlist(update->kcontrol);
 
-	if (w->event &&
-	    (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
-		ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
-		if (ret != 0)
-			dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
-			       w->name, ret);
+	for (wi = 0; wi < wlist->num_widgets; wi++) {
+		w = wlist->widgets[wi];
+
+		if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
+			ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
+			if (ret != 0)
+				dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
+					   w->name, ret);
+		}
 	}
 
+	if (!w)
+		return;
+
 	ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
 				  update->val);
 	if (ret < 0)
-		dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n",
+		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
 			w->name, ret);
 
-	if (w->event &&
-	    (w->event_flags & SND_SOC_DAPM_POST_REG)) {
-		ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
-		if (ret != 0)
-			dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
-			       w->name, ret);
+	for (wi = 0; wi < wlist->num_widgets; wi++) {
+		w = wlist->widgets[wi];
+
+		if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {
+			ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
+			if (ret != 0)
+				dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
+					   w->name, ret);
+		}
 	}
 }
 
@@ -1595,6 +1737,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
 	case snd_soc_dapm_supply:
 	case snd_soc_dapm_regulator_supply:
 	case snd_soc_dapm_clock_supply:
+	case snd_soc_dapm_kcontrol:
 		/* Supplies can't affect their outputs, only their inputs */
 		break;
 	default:
@@ -1611,8 +1754,6 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
 		dapm_seq_insert(w, up_list, true);
 	else
 		dapm_seq_insert(w, down_list, false);
-
-	w->power = power;
 }
 
 static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
@@ -1646,9 +1787,8 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
  *  o Input pin to Output pin (bypass, sidetone)
  *  o DAC to ADC (loopback).
  */
-static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
+static int dapm_power_widgets(struct snd_soc_card *card, int event)
 {
-	struct snd_soc_card *card = dapm->card;
 	struct snd_soc_dapm_widget *w;
 	struct snd_soc_dapm_context *d;
 	LIST_HEAD(up_list);
@@ -1688,7 +1828,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 			break;
 		}
 
-		if (w->power) {
+		if (w->new_power) {
 			d = w->dapm;
 
 			/* Supplies and micbiases only bring the
@@ -1730,29 +1870,29 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 	trace_snd_soc_dapm_walk_done(card);
 
 	/* Run all the bias changes in parallel */
-	list_for_each_entry(d, &dapm->card->dapm_list, list)
+	list_for_each_entry(d, &card->dapm_list, list)
 		async_schedule_domain(dapm_pre_sequence_async, d,
 					&async_domain);
 	async_synchronize_full_domain(&async_domain);
 
 	list_for_each_entry(w, &down_list, power_list) {
-		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD);
+		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
 	}
 
 	list_for_each_entry(w, &up_list, power_list) {
-		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU);
+		dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
 	}
 
 	/* Power down widgets first; try to avoid amplifying pops. */
-	dapm_seq_run(dapm, &down_list, event, false);
+	dapm_seq_run(card, &down_list, event, false);
 
-	dapm_widget_update(dapm);
+	dapm_widget_update(card);
 
 	/* Now power up. */
-	dapm_seq_run(dapm, &up_list, event, true);
+	dapm_seq_run(card, &up_list, event, true);
 
 	/* Run all the bias changes in parallel */
-	list_for_each_entry(d, &dapm->card->dapm_list, list)
+	list_for_each_entry(d, &card->dapm_list, list)
 		async_schedule_domain(dapm_post_sequence_async, d,
 					&async_domain);
 	async_synchronize_full_domain(&async_domain);
@@ -1763,7 +1903,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 			d->stream_event(d, event);
 	}
 
-	pop_dbg(dapm->dev, card->pop_time,
+	pop_dbg(card->dev, card->pop_time,
 		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
 	pop_wait(card->pop_time);
 
@@ -1798,8 +1938,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 
 	if (w->reg >= 0)
 		ret += snprintf(buf + ret, PAGE_SIZE - ret,
-				" - R%d(0x%x) bit %d",
-				w->reg, w->reg, w->shift);
+				" - R%d(0x%x) mask 0x%x",
+				w->reg, w->reg, w->mask << w->shift);
 
 	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
@@ -1936,22 +2076,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
 #endif
 
 /* test and update the power status of a mux widget */
-static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+static int soc_dapm_mux_update_power(struct snd_soc_card *card,
 				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
 {
 	struct snd_soc_dapm_path *path;
 	int found = 0;
 
-	if (widget->id != snd_soc_dapm_mux &&
-	    widget->id != snd_soc_dapm_virt_mux &&
-	    widget->id != snd_soc_dapm_value_mux)
-		return -ENODEV;
-
 	/* find dapm widget path assoc with kcontrol */
-	list_for_each_entry(path, &widget->dapm->card->paths, list) {
-		if (path->kcontrol != kcontrol)
-			continue;
-
+	dapm_kcontrol_for_each_path(path, kcontrol) {
 		if (!path->name || !e->texts[mux])
 			continue;
 
@@ -1966,73 +2098,68 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 						"mux disconnection");
 			path->connect = 0; /* old connection must be powered down */
 		}
+		dapm_mark_dirty(path->sink, "mux change");
 	}
 
-	if (found) {
-		dapm_mark_dirty(widget, "mux change");
-		dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
-	}
+	if (found)
+		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
 
 	return found;
 }
 
-int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
-		struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
+	struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
+	struct snd_soc_dapm_update *update)
 {
-	struct snd_soc_card *card = widget->dapm->card;
+	struct snd_soc_card *card = dapm->card;
 	int ret;
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-	ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e);
+	card->update = update;
+	ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
+	card->update = NULL;
 	mutex_unlock(&card->dapm_mutex);
 	if (ret > 0)
-		soc_dpcm_runtime_update(widget);
+		soc_dpcm_runtime_update(card);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
 
 /* test and update the power status of a mixer or switch widget */
-static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
 				   struct snd_kcontrol *kcontrol, int connect)
 {
 	struct snd_soc_dapm_path *path;
 	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;
-
 	/* find dapm widget path assoc with kcontrol */
-	list_for_each_entry(path, &widget->dapm->card->paths, list) {
-		if (path->kcontrol != kcontrol)
-			continue;
-
-		/* found, now check type */
+	dapm_kcontrol_for_each_path(path, kcontrol) {
 		found = 1;
 		path->connect = connect;
 		dapm_mark_dirty(path->source, "mixer connection");
+		dapm_mark_dirty(path->sink, "mixer update");
 	}
 
-	if (found) {
-		dapm_mark_dirty(widget, "mixer update");
-		dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
-	}
+	if (found)
+		dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
 
 	return found;
 }
 
-int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
-				struct snd_kcontrol *kcontrol, int connect)
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
+	struct snd_kcontrol *kcontrol, int connect,
+	struct snd_soc_dapm_update *update)
 {
-	struct snd_soc_card *card = widget->dapm->card;
+	struct snd_soc_card *card = dapm->card;
 	int ret;
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-	ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
+	card->update = update;
+	ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
+	card->update = NULL;
 	mutex_unlock(&card->dapm_mutex);
 	if (ret > 0)
-		soc_dpcm_runtime_update(widget);
+		soc_dpcm_runtime_update(card);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
@@ -2111,6 +2238,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path)
 {
 	list_del(&path->list_sink);
 	list_del(&path->list_source);
+	list_del(&path->list_kcontrol);
 	list_del(&path->list);
 	kfree(path);
 }
@@ -2205,70 +2333,20 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
 		return 0;
 
 	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-	ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+	ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
 	mutex_unlock(&dapm->card->dapm_mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
 
-static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
-				  const struct snd_soc_dapm_route *route)
+static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
+	struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
+	const char *control,
+	int (*connected)(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink))
 {
 	struct snd_soc_dapm_path *path;
-	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
-	struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
-	const char *sink;
-	const char *control = route->control;
-	const char *source;
-	char prefixed_sink[80];
-	char prefixed_source[80];
-	int ret = 0;
-
-	if (dapm->codec && dapm->codec->name_prefix) {
-		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
-			 dapm->codec->name_prefix, route->sink);
-		sink = prefixed_sink;
-		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
-			 dapm->codec->name_prefix, route->source);
-		source = prefixed_source;
-	} else {
-		sink = route->sink;
-		source = route->source;
-	}
-
-	/*
-	 * find src and dest widgets over all widgets but favor a widget from
-	 * current DAPM context
-	 */
-	list_for_each_entry(w, &dapm->card->widgets, list) {
-		if (!wsink && !(strcmp(w->name, sink))) {
-			wtsink = w;
-			if (w->dapm == dapm)
-				wsink = w;
-			continue;
-		}
-		if (!wsource && !(strcmp(w->name, source))) {
-			wtsource = w;
-			if (w->dapm == dapm)
-				wsource = w;
-		}
-	}
-	/* use widget from another DAPM context if not found from this */
-	if (!wsink)
-		wsink = wtsink;
-	if (!wsource)
-		wsource = wtsource;
-
-	if (wsource == NULL) {
-		dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
-			route->source);
-		return -ENODEV;
-	}
-	if (wsink == NULL) {
-		dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
-			route->sink);
-		return -ENODEV;
-	}
+	int ret;
 
 	path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
 	if (!path)
@@ -2276,7 +2354,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 
 	path->source = wsource;
 	path->sink = wsink;
-	path->connected = route->connected;
+	path->connected = connected;
 	INIT_LIST_HEAD(&path->list);
 	INIT_LIST_HEAD(&path->list_source);
 	INIT_LIST_HEAD(&path->list_sink);
@@ -2327,6 +2405,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 	case snd_soc_dapm_dai_in:
 	case snd_soc_dapm_dai_out:
 	case snd_soc_dapm_dai_link:
+	case snd_soc_dapm_kcontrol:
 		list_add(&path->list, &dapm->card->paths);
 		list_add(&path->list_sink, &wsink->sources);
 		list_add(&path->list_source, &wsource->sinks);
@@ -2362,11 +2441,77 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 	dapm_mark_dirty(wsink, "Route added");
 
 	return 0;
+err:
+	kfree(path);
+	return ret;
+}
+
+static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
+				  const struct snd_soc_dapm_route *route)
+{
+	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
+	struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
+	const char *sink;
+	const char *source;
+	char prefixed_sink[80];
+	char prefixed_source[80];
+	int ret;
+
+	if (dapm->codec && dapm->codec->name_prefix) {
+		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
+			 dapm->codec->name_prefix, route->sink);
+		sink = prefixed_sink;
+		snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
+			 dapm->codec->name_prefix, route->source);
+		source = prefixed_source;
+	} else {
+		sink = route->sink;
+		source = route->source;
+	}
+
+	/*
+	 * find src and dest widgets over all widgets but favor a widget from
+	 * current DAPM context
+	 */
+	list_for_each_entry(w, &dapm->card->widgets, list) {
+		if (!wsink && !(strcmp(w->name, sink))) {
+			wtsink = w;
+			if (w->dapm == dapm)
+				wsink = w;
+			continue;
+		}
+		if (!wsource && !(strcmp(w->name, source))) {
+			wtsource = w;
+			if (w->dapm == dapm)
+				wsource = w;
+		}
+	}
+	/* use widget from another DAPM context if not found from this */
+	if (!wsink)
+		wsink = wtsink;
+	if (!wsource)
+		wsource = wtsource;
 
+	if (wsource == NULL) {
+		dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
+			route->source);
+		return -ENODEV;
+	}
+	if (wsink == NULL) {
+		dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
+			route->sink);
+		return -ENODEV;
+	}
+
+	ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
+		route->connected);
+	if (ret)
+		goto err;
+
+	return 0;
 err:
 	dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
-		 source, control, sink);
-	kfree(path);
+		 source, route->control, sink);
 	return ret;
 }
 
@@ -2570,12 +2715,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
  */
 int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 {
+	struct snd_soc_card *card = dapm->card;
 	struct snd_soc_dapm_widget *w;
 	unsigned int val;
 
-	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
 
-	list_for_each_entry(w, &dapm->card->widgets, list)
+	list_for_each_entry(w, &card->widgets, list)
 	{
 		if (w->new)
 			continue;
@@ -2585,7 +2731,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 						sizeof(struct snd_kcontrol *),
 						GFP_KERNEL);
 			if (!w->kcontrols) {
-				mutex_unlock(&dapm->card->dapm_mutex);
+				mutex_unlock(&card->dapm_mutex);
 				return -ENOMEM;
 			}
 		}
@@ -2611,12 +2757,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 
 		/* Read the initial power state from the device */
 		if (w->reg >= 0) {
-			val = soc_widget_read(w, w->reg);
-			val &= 1 << w->shift;
-			if (w->invert)
-				val = !val;
-
-			if (val)
+			val = soc_widget_read(w, w->reg) >> w->shift;
+			val &= w->mask;
+			if (val == w->on_val)
 				w->power = 1;
 		}
 
@@ -2626,8 +2769,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 		dapm_debugfs_add_widget(w);
 	}
 
-	dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
-	mutex_unlock(&dapm->card->dapm_mutex);
+	dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
+	mutex_unlock(&card->dapm_mutex);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
@@ -2644,8 +2787,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
 int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct snd_soc_card *card = codec->card;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	unsigned int reg = mc->reg;
@@ -2653,17 +2796,24 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 	int max = mc->max;
 	unsigned int mask = (1 << fls(max)) - 1;
 	unsigned int invert = mc->invert;
+	unsigned int val;
 
 	if (snd_soc_volsw_is_stereo(mc))
-		dev_warn(widget->dapm->dev,
+		dev_warn(codec->dapm.dev,
 			 "ASoC: Control '%s' is stereo, which is not supported\n",
 			 kcontrol->id.name);
 
-	ucontrol->value.integer.value[0] =
-		(snd_soc_read(widget->codec, reg) >> shift) & mask;
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+	if (dapm_kcontrol_is_powered(kcontrol))
+		val = (snd_soc_read(codec, reg) >> shift) & mask;
+	else
+		val = dapm_kcontrol_get_value(kcontrol);
+	mutex_unlock(&card->dapm_mutex);
+
 	if (invert)
-		ucontrol->value.integer.value[0] =
-			max - ucontrol->value.integer.value[0];
+		ucontrol->value.integer.value[0] = max - val;
+	else
+		ucontrol->value.integer.value[0] = val;
 
 	return 0;
 }
@@ -2681,9 +2831,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct snd_soc_card *card = codec->card;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
@@ -2695,10 +2843,9 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 	unsigned int val;
 	int connect, change;
 	struct snd_soc_dapm_update update;
-	int wi;
 
 	if (snd_soc_volsw_is_stereo(mc))
-		dev_warn(widget->dapm->dev,
+		dev_warn(codec->dapm.dev,
 			 "ASoC: Control '%s' is stereo, which is not supported\n",
 			 kcontrol->id.name);
 
@@ -2707,29 +2854,26 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 
 	if (invert)
 		val = max - val;
-	mask = mask << shift;
-	val = val << shift;
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
-	change = snd_soc_test_bits(widget->codec, reg, mask, val);
-	if (change) {
-		for (wi = 0; wi < wlist->num_widgets; wi++) {
-			widget = wlist->widgets[wi];
+	dapm_kcontrol_set_value(kcontrol, val);
 
-			widget->value = val;
+	mask = mask << shift;
+	val = val << shift;
 
-			update.kcontrol = kcontrol;
-			update.widget = widget;
-			update.reg = reg;
-			update.mask = mask;
-			update.val = val;
-			widget->dapm->update = &update;
+	change = snd_soc_test_bits(codec, reg, mask, val);
+	if (change) {
+		update.kcontrol = kcontrol;
+		update.reg = reg;
+		update.mask = mask;
+		update.val = val;
 
-			soc_dapm_mixer_update_power(widget, kcontrol, connect);
+		card->update = &update;
 
-			widget->dapm->update = NULL;
-		}
+		soc_dapm_mixer_update_power(card, kcontrol, connect);
+
+		card->update = NULL;
 	}
 
 	mutex_unlock(&card->dapm_mutex);
@@ -2749,12 +2893,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
 int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int val;
 
-	val = snd_soc_read(widget->codec, e->reg);
+	val = snd_soc_read(codec, e->reg);
 	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask;
 	if (e->shift_l != e->shift_r)
 		ucontrol->value.enumerated.item[1] =
@@ -2776,15 +2919,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct snd_soc_card *card = codec->card;
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int val, mux, change;
 	unsigned int mask;
 	struct snd_soc_dapm_update update;
-	int wi;
 
 	if (ucontrol->value.enumerated.item[0] > e->max - 1)
 		return -EINVAL;
@@ -2800,24 +2940,17 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
-	change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
+	change = snd_soc_test_bits(codec, e->reg, mask, val);
 	if (change) {
-		for (wi = 0; wi < wlist->num_widgets; wi++) {
-			widget = wlist->widgets[wi];
-
-			widget->value = val;
+		update.kcontrol = kcontrol;
+		update.reg = e->reg;
+		update.mask = mask;
+		update.val = val;
+		card->update = &update;
 
-			update.kcontrol = kcontrol;
-			update.widget = widget;
-			update.reg = e->reg;
-			update.mask = mask;
-			update.val = val;
-			widget->dapm->update = &update;
+		soc_dapm_mux_update_power(card, kcontrol, mux, e);
 
-			soc_dapm_mux_update_power(widget, kcontrol, mux, e);
-
-			widget->dapm->update = NULL;
-		}
+		card->update = NULL;
 	}
 
 	mutex_unlock(&card->dapm_mutex);
@@ -2835,11 +2968,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
 int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-
-	ucontrol->value.enumerated.item[0] = widget->value;
-
+	ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
@@ -2854,30 +2983,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
 int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct snd_soc_card *card = codec->card;
+	unsigned int value;
 	struct soc_enum *e =
 		(struct soc_enum *)kcontrol->private_value;
 	int change;
-	int wi;
 
 	if (ucontrol->value.enumerated.item[0] >= e->max)
 		return -EINVAL;
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
-	change = widget->value != ucontrol->value.enumerated.item[0];
-	if (change) {
-		for (wi = 0; wi < wlist->num_widgets; wi++) {
-			widget = wlist->widgets[wi];
-
-			widget->value = ucontrol->value.enumerated.item[0];
-
-			soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
-		}
-	}
+	value = ucontrol->value.enumerated.item[0];
+	change = dapm_kcontrol_set_value(kcontrol, value);
+	if (change)
+		soc_dapm_mux_update_power(card, kcontrol, value, e);
 
 	mutex_unlock(&card->dapm_mutex);
 	return change;
@@ -2900,12 +3021,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
 int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int reg_val, val, mux;
 
-	reg_val = snd_soc_read(widget->codec, e->reg);
+	reg_val = snd_soc_read(codec, e->reg);
 	val = (reg_val >> e->shift_l) & e->mask;
 	for (mux = 0; mux < e->max; mux++) {
 		if (val == e->values[mux])
@@ -2941,15 +3061,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-	struct snd_soc_codec *codec = widget->codec;
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 	struct snd_soc_card *card = codec->card;
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int val, mux, change;
 	unsigned int mask;
 	struct snd_soc_dapm_update update;
-	int wi;
 
 	if (ucontrol->value.enumerated.item[0] > e->max - 1)
 		return -EINVAL;
@@ -2965,24 +3082,17 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
-	change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
+	change = snd_soc_test_bits(codec, e->reg, mask, val);
 	if (change) {
-		for (wi = 0; wi < wlist->num_widgets; wi++) {
-			widget = wlist->widgets[wi];
-
-			widget->value = val;
+		update.kcontrol = kcontrol;
+		update.reg = e->reg;
+		update.mask = mask;
+		update.val = val;
+		card->update = &update;
 
-			update.kcontrol = kcontrol;
-			update.widget = widget;
-			update.reg = e->reg;
-			update.mask = mask;
-			update.val = val;
-			widget->dapm->update = &update;
+		soc_dapm_mux_update_power(card, kcontrol, mux, e);
 
-			soc_dapm_mux_update_power(widget, kcontrol, mux, e);
-
-			widget->dapm->update = NULL;
-		}
+		card->update = NULL;
 	}
 
 	mutex_unlock(&card->dapm_mutex);
@@ -3079,7 +3189,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 			return NULL;
 		}
 
-		if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
 			ret = regulator_allow_bypass(w->regulator, true);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
@@ -3126,16 +3236,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	case snd_soc_dapm_value_mux:
 		w->power_check = dapm_generic_check_power;
 		break;
-	case snd_soc_dapm_adc:
-	case snd_soc_dapm_aif_out:
 	case snd_soc_dapm_dai_out:
 		w->power_check = dapm_adc_check_power;
 		break;
-	case snd_soc_dapm_dac:
-	case snd_soc_dapm_aif_in:
 	case snd_soc_dapm_dai_in:
 		w->power_check = dapm_dac_check_power;
 		break;
+	case snd_soc_dapm_adc:
+	case snd_soc_dapm_aif_out:
+	case snd_soc_dapm_dac:
+	case snd_soc_dapm_aif_in:
 	case snd_soc_dapm_pga:
 	case snd_soc_dapm_out_drv:
 	case snd_soc_dapm_input:
@@ -3151,6 +3261,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	case snd_soc_dapm_supply:
 	case snd_soc_dapm_regulator_supply:
 	case snd_soc_dapm_clock_supply:
+	case snd_soc_dapm_kcontrol:
 		w->power_check = dapm_supply_check_power;
 		break;
 	default:
@@ -3415,9 +3526,6 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
 {
 	struct snd_soc_dapm_widget *dai_w, *w;
 	struct snd_soc_dai *dai;
-	struct snd_soc_dapm_route r;
-
-	memset(&r, 0, sizeof(r));
 
 	/* For each DAI widget... */
 	list_for_each_entry(dai_w, &card->widgets, list) {
@@ -3450,23 +3558,21 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
 			if (dai->driver->playback.stream_name &&
 			    strstr(w->sname,
 				   dai->driver->playback.stream_name)) {
-				r.source = dai->playback_widget->name;
-				r.sink = w->name;
 				dev_dbg(dai->dev, "%s -> %s\n",
-					 r.source, r.sink);
+					 dai->playback_widget->name, w->name);
 
-				snd_soc_dapm_add_route(w->dapm, &r);
+				snd_soc_dapm_add_path(w->dapm,
+					dai->playback_widget, w, NULL, NULL);
 			}
 
 			if (dai->driver->capture.stream_name &&
 			    strstr(w->sname,
 				   dai->driver->capture.stream_name)) {
-				r.source = w->name;
-				r.sink = dai->capture_widget->name;
 				dev_dbg(dai->dev, "%s -> %s\n",
-					r.source, r.sink);
+					w->name, dai->capture_widget->name);
 
-				snd_soc_dapm_add_route(w->dapm, &r);
+				snd_soc_dapm_add_path(w->dapm, w,
+					dai->capture_widget, NULL, NULL);
 			}
 		}
 	}
@@ -3528,7 +3634,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
 		}
 	}
 
-	dapm_power_widgets(&rtd->card->dapm, event);
+	dapm_power_widgets(rtd->card, event);
 }
 
 /**
@@ -3797,7 +3903,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
 		if (dapm->bias_level == SND_SOC_BIAS_ON)
 			snd_soc_dapm_set_bias_level(dapm,
 						    SND_SOC_BIAS_PREPARE);
-		dapm_seq_run(dapm, &down_list, 0, false);
+		dapm_seq_run(card, &down_list, 0, false);
 		if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
 			snd_soc_dapm_set_bias_level(dapm,
 						    SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 8ca9ecc..122c0c1 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -158,7 +158,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 		return -EINVAL;
 	}
 
-	return PTR_RET(codec->control_data);
+	return PTR_ERR_OR_ZERO(codec->control_data);
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
 #else
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 0bb5ccc..7aa26b5 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -263,7 +263,7 @@ static irqreturn_t gpio_handler(int irq, void *data)
 	if (device_may_wakeup(dev))
 		pm_wakeup_event(dev, gpio->debounce_time + 50);
 
-	schedule_delayed_work(&gpio->work,
+	queue_delayed_work(system_power_efficient_wq, &gpio->work,
 			      msecs_to_jiffies(gpio->debounce_time));
 
 	return IRQ_HANDLED;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index b6c6403..fb70fbe 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -411,8 +411,9 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 		} else {
 			/* start delayed pop wq here for playback streams */
 			rtd->pop_wait = 1;
-			schedule_delayed_work(&rtd->delayed_work,
-				msecs_to_jiffies(rtd->pmdown_time));
+			queue_delayed_work(system_power_efficient_wq,
+					   &rtd->delayed_work,
+					   msecs_to_jiffies(rtd->pmdown_time));
 		}
 	} else {
 		/* capture streams can be powered down now */
@@ -1832,18 +1833,10 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
 /* Called by DAPM mixer/mux changes to update audio routing between PCMs and
  * any DAI links.
  */
-int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
+int soc_dpcm_runtime_update(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card;
 	int i, old, new, paths;
 
-	if (widget->codec)
-		card = widget->codec->card;
-	else if (widget->platform)
-		card = widget->platform->card;
-	else
-		return -EINVAL;
-
 	mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 	for (i = 0; i < card->num_rtd; i++) {
 		struct snd_soc_dapm_widget_list *list;
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 995b120..8fc653c 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -1,8 +1,8 @@
 config SND_SOC_TEGRA
 	tristate "SoC Audio for the Tegra System-on-Chip"
-	depends on ARCH_TEGRA && TEGRA20_APB_DMA
+	depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
 	select REGMAP_MMIO
-	select SND_SOC_GENERIC_DMAENGINE_PCM if TEGRA20_APB_DMA
+	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	  Say Y or M here if you want support for SoC audio on Tegra.
 
@@ -61,7 +61,7 @@ config SND_SOC_TEGRA30_I2S
 
 config SND_SOC_TEGRA_RT5640
 	tristate "SoC Audio support for Tegra boards using an RT5640 codec"
-	depends on SND_SOC_TEGRA && I2C
+	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
 	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_RT5640
@@ -71,7 +71,7 @@ config SND_SOC_TEGRA_RT5640
 
 config SND_SOC_TEGRA_WM8753
 	tristate "SoC Audio support for Tegra boards using a WM8753 codec"
-	depends on SND_SOC_TEGRA && I2C
+	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
 	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_WM8753
@@ -81,7 +81,7 @@ config SND_SOC_TEGRA_WM8753
 
 config SND_SOC_TEGRA_WM8903
 	tristate "SoC Audio support for Tegra boards using a WM8903 codec"
-	depends on SND_SOC_TEGRA && I2C
+	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
 	select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
 	select SND_SOC_WM8903
@@ -92,7 +92,7 @@ config SND_SOC_TEGRA_WM8903
 
 config SND_SOC_TEGRA_WM9712
 	tristate "SoC Audio support for Tegra boards using a WM9712 codec"
-	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+	depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC && GPIOLIB
 	select SND_SOC_TEGRA20_AC97
 	select SND_SOC_WM9712
 	help
@@ -110,7 +110,7 @@ config SND_SOC_TEGRA_TRIMSLICE
 
 config SND_SOC_TEGRA_ALC5632
 	tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
-	depends on SND_SOC_TEGRA && I2C
+	depends on SND_SOC_TEGRA && I2C && GPIOLIB
 	select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
 	select SND_SOC_ALC5632
 	help
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 6c48662..00106b5 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -432,8 +432,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
 
 	return 0;
 
-err_unregister_pcm:
-	tegra_pcm_platform_unregister(&pdev->dev);
 err_unregister_component:
 	snd_soc_unregister_component(&pdev->dev);
 err_asoc_utils_fini:
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 48d05d9..c61ea3a 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -13,8 +13,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <asm/mach-types.h>
-
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index f87fc53..8e774d1 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -28,8 +28,6 @@
  *
  */
 
-#include <asm/mach-types.h>
-
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 05c68aa..734bfcd 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -24,8 +24,6 @@
  *
  */
 
-#include <asm/mach-types.h>
-
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 4bcce8a..e0305a1 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -184,9 +184,6 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return irq;
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -EBUSY;
-
 	drvdata->base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(drvdata->base))
 		return PTR_ERR(drvdata->base);
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c
index 8f5cd00..178d1ba 100644
--- a/sound/soc/ux500/mop500.c
+++ b/sound/soc/ux500/mop500.c
@@ -52,6 +52,7 @@ static struct snd_soc_dai_link mop500_dai_links[] = {
 
 static struct snd_soc_card mop500_card = {
 	.name = "MOP500-card",
+	.owner = THIS_MODULE,
 	.probe = NULL,
 	.dai_link = mop500_dai_links,
 	.num_links = ARRAY_SIZE(mop500_dai_links),
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index 9e6e3ff..23452ee 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -110,19 +110,37 @@ static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
 static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
 		u8 reg, u8 value)
 {
-	u8 buffer[13]; /* 13: maximum length of message */
+	u8 *buffer;
+	int ret;
+
+	/* 13: maximum length of message */
+	buffer = kmalloc(13, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
 
 	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
-	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+	ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+
+	kfree(buffer);
+	return ret;
 }
 
 static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
 		u8 reg, u8 vl, u8 vh)
 {
-	u8 buffer[13]; /* 13: maximum length of message */
+	u8 *buffer;
+	int ret;
+
+	/* 13: maximum length of message */
+	buffer = kmalloc(13, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
 
 	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
-	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+	ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+
+	kfree(buffer);
+	return ret;
 }
 
 int usb6fire_comm_init(struct sfire_chip *chip)
@@ -135,6 +153,12 @@ int usb6fire_comm_init(struct sfire_chip *chip)
 	if (!rt)
 		return -ENOMEM;
 
+	rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL);
+	if (!rt->receiver_buffer) {
+		kfree(rt);
+		return -ENOMEM;
+	}
+
 	urb = &rt->receiver;
 	rt->serial = 1;
 	rt->chip = chip;
@@ -153,6 +177,7 @@ int usb6fire_comm_init(struct sfire_chip *chip)
 	urb->interval = 1;
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret < 0) {
+		kfree(rt->receiver_buffer);
 		kfree(rt);
 		snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
 		return ret;
@@ -171,6 +196,9 @@ void usb6fire_comm_abort(struct sfire_chip *chip)
 
 void usb6fire_comm_destroy(struct sfire_chip *chip)
 {
-	kfree(chip->comm);
+	struct comm_runtime *rt = chip->comm;
+
+	kfree(rt->receiver_buffer);
+	kfree(rt);
 	chip->comm = NULL;
 }
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
index 6a0840b..780d5ed 100644
--- a/sound/usb/6fire/comm.h
+++ b/sound/usb/6fire/comm.h
@@ -24,7 +24,7 @@ struct comm_runtime {
 	struct sfire_chip *chip;
 
 	struct urb receiver;
-	u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
+	u8 *receiver_buffer;
 
 	u8 serial; /* urb serial */
 
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index b9defcd..780bf3f 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -346,10 +346,10 @@ static int usb6fire_fw_check(u8 *version)
 		if (!memcmp(version, known_fw_versions + i, 2))
 			return 0;
 
-	snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %*ph. "
+	snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %4ph. "
 			"please reconnect to power. if this failure "
 			"still happens, check your firmware installation.",
-			4, version);
+			version);
 	return -EINVAL;
 }
 
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7a444b5..93e970f 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -418,6 +418,9 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 	struct snd_usb_endpoint *ep;
 	int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
 
+	if (WARN_ON(!alts))
+		return NULL;
+
 	mutex_lock(&chip->mutex);
 
 	list_for_each_entry(ep, &chip->ep_list, list) {
@@ -591,17 +594,16 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 	ep->stride = frame_bits >> 3;
 	ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0;
 
-	/* calculate max. frequency */
-	if (ep->maxpacksize) {
+	/* assume max. frequency is 25% higher than nominal */
+	ep->freqmax = ep->freqn + (ep->freqn >> 2);
+	maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
+				>> (16 - ep->datainterval);
+	/* but wMaxPacketSize might reduce this */
+	if (ep->maxpacksize && ep->maxpacksize < maxsize) {
 		/* whatever fits into a max. size packet */
 		maxsize = ep->maxpacksize;
 		ep->freqmax = (maxsize / (frame_bits >> 3))
 				<< (16 - ep->datainterval);
-	} else {
-		/* no max. packet size: just take 25% higher than nominal */
-		ep->freqmax = ep->freqn + (ep->freqn >> 2);
-		maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
-				>> (16 - ep->datainterval);
 	}
 
 	if (ep->fill_max)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 15b151e..b375d58 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -327,6 +327,137 @@ static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
 	return 0;
 }
 
+static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
+					 struct usb_device *dev,
+					 struct usb_interface_descriptor *altsd,
+					 unsigned int attr)
+{
+	struct usb_host_interface *alts;
+	struct usb_interface *iface;
+	unsigned int ep;
+
+	/* Implicit feedback sync EPs consumers are always playback EPs */
+	if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK)
+		return 0;
+
+	switch (subs->stream->chip->usb_id) {
+	case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+	case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
+		ep = 0x81;
+		iface = usb_ifnum_to_if(dev, 3);
+
+		if (!iface || iface->num_altsetting == 0)
+			return -EINVAL;
+
+		alts = &iface->altsetting[1];
+		goto add_sync_ep;
+		break;
+	case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
+	case USB_ID(0x0763, 0x2081):
+		ep = 0x81;
+		iface = usb_ifnum_to_if(dev, 2);
+
+		if (!iface || iface->num_altsetting == 0)
+			return -EINVAL;
+
+		alts = &iface->altsetting[1];
+		goto add_sync_ep;
+	}
+	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
+	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
+	    altsd->bInterfaceProtocol == 2 &&
+	    altsd->bNumEndpoints == 1 &&
+	    USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ &&
+	    search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1,
+				      altsd->bAlternateSetting,
+				      &alts, &ep) >= 0) {
+		goto add_sync_ep;
+	}
+
+	/* No quirk */
+	return 0;
+
+add_sync_ep:
+	subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
+						   alts, ep, !subs->direction,
+						   SND_USB_ENDPOINT_TYPE_DATA);
+	if (!subs->sync_endpoint)
+		return -EINVAL;
+
+	subs->data_endpoint->sync_master = subs->sync_endpoint;
+
+	return 0;
+}
+
+static int set_sync_endpoint(struct snd_usb_substream *subs,
+			     struct audioformat *fmt,
+			     struct usb_device *dev,
+			     struct usb_host_interface *alts,
+			     struct usb_interface_descriptor *altsd)
+{
+	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
+	unsigned int ep, attr;
+	bool implicit_fb;
+	int err;
+
+	/* we need a sync pipe in async OUT or adaptive IN mode */
+	/* check the number of EP, since some devices have broken
+	 * descriptors which fool us.  if it has only one EP,
+	 * assume it as adaptive-out or sync-in.
+	 */
+	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
+
+	err = set_sync_ep_implicit_fb_quirk(subs, dev, altsd, attr);
+	if (err < 0)
+		return err;
+
+	if (altsd->bNumEndpoints < 2)
+		return 0;
+
+	if ((is_playback && attr != USB_ENDPOINT_SYNC_ASYNC) ||
+	    (!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE))
+		return 0;
+
+	/* check sync-pipe endpoint */
+	/* ... and check descriptor size before accessing bSynchAddress
+	   because there is a version of the SB Audigy 2 NX firmware lacking
+	   the audio fields in the endpoint descriptors */
+	if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
+	    (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+	     get_endpoint(alts, 1)->bSynchAddress != 0)) {
+		snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n",
+			   dev->devnum, fmt->iface, fmt->altsetting,
+			   get_endpoint(alts, 1)->bmAttributes,
+			   get_endpoint(alts, 1)->bLength,
+			   get_endpoint(alts, 1)->bSynchAddress);
+		return -EINVAL;
+	}
+	ep = get_endpoint(alts, 1)->bEndpointAddress;
+	if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+	    ((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
+	     (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
+		snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
+			   dev->devnum, fmt->iface, fmt->altsetting,
+			   is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
+		return -EINVAL;
+	}
+
+	implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK)
+			== USB_ENDPOINT_USAGE_IMPLICIT_FB;
+
+	subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
+						   alts, ep, !subs->direction,
+						   implicit_fb ?
+							SND_USB_ENDPOINT_TYPE_DATA :
+							SND_USB_ENDPOINT_TYPE_SYNC);
+	if (!subs->sync_endpoint)
+		return -EINVAL;
+
+	subs->data_endpoint->sync_master = subs->sync_endpoint;
+
+	return 0;
+}
+
 /*
  * find a matching format and set up the interface
  */
@@ -336,9 +467,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	struct usb_interface *iface;
-	unsigned int ep, attr;
-	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	int err, implicit_fb = 0;
+	int err;
 
 	iface = usb_ifnum_to_if(dev, fmt->iface);
 	if (WARN_ON(!iface))
@@ -383,118 +512,22 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
 						   alts, fmt->endpoint, subs->direction,
 						   SND_USB_ENDPOINT_TYPE_DATA);
+
 	if (!subs->data_endpoint)
 		return -EINVAL;
 
-	/* we need a sync pipe in async OUT or adaptive IN mode */
-	/* check the number of EP, since some devices have broken
-	 * descriptors which fool us.  if it has only one EP,
-	 * assume it as adaptive-out or sync-in.
-	 */
-	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
-
-	switch (subs->stream->chip->usb_id) {
-	case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
-	case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
-		if (is_playback) {
-			implicit_fb = 1;
-			ep = 0x81;
-			iface = usb_ifnum_to_if(dev, 3);
-
-			if (!iface || iface->num_altsetting == 0)
-				return -EINVAL;
-
-			alts = &iface->altsetting[1];
-			goto add_sync_ep;
-		}
-		break;
-	case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
-	case USB_ID(0x0763, 0x2081):
-		if (is_playback) {
-			implicit_fb = 1;
-			ep = 0x81;
-			iface = usb_ifnum_to_if(dev, 2);
-
-			if (!iface || iface->num_altsetting == 0)
-				return -EINVAL;
-
-			alts = &iface->altsetting[1];
-			goto add_sync_ep;
-		}
-	}
-	if (is_playback &&
-	    attr == USB_ENDPOINT_SYNC_ASYNC &&
-	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
-	    altsd->bInterfaceProtocol == 2 &&
-	    altsd->bNumEndpoints == 1 &&
-	    USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ &&
-	    search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1,
-				      altsd->bAlternateSetting,
-				      &alts, &ep) >= 0) {
-		implicit_fb = 1;
-		goto add_sync_ep;
-	}
-
-	if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
-	     (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
-	    altsd->bNumEndpoints >= 2) {
-		/* check sync-pipe endpoint */
-		/* ... and check descriptor size before accessing bSynchAddress
-		   because there is a version of the SB Audigy 2 NX firmware lacking
-		   the audio fields in the endpoint descriptors */
-		if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
-		    (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
-		     get_endpoint(alts, 1)->bSynchAddress != 0 &&
-		     !implicit_fb)) {
-			snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n",
-				   dev->devnum, fmt->iface, fmt->altsetting,
-				   get_endpoint(alts, 1)->bmAttributes,
-				   get_endpoint(alts, 1)->bLength,
-				   get_endpoint(alts, 1)->bSynchAddress);
-			return -EINVAL;
-		}
-		ep = get_endpoint(alts, 1)->bEndpointAddress;
-		if (!implicit_fb &&
-		    get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
-		    (( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
-		     (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
-			snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
-				   dev->devnum, fmt->iface, fmt->altsetting,
-				   is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
-			return -EINVAL;
-		}
-
-		implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK)
-				== USB_ENDPOINT_USAGE_IMPLICIT_FB;
-
-add_sync_ep:
-		subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
-							   alts, ep, !subs->direction,
-							   implicit_fb ?
-								SND_USB_ENDPOINT_TYPE_DATA :
-								SND_USB_ENDPOINT_TYPE_SYNC);
-		if (!subs->sync_endpoint)
-			return -EINVAL;
-
-		subs->data_endpoint->sync_master = subs->sync_endpoint;
-	}
+	err = set_sync_endpoint(subs, fmt, dev, alts, altsd);
+	if (err < 0)
+		return err;
 
-	if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0)
+	err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt);
+	if (err < 0)
 		return err;
 
 	subs->cur_audiofmt = fmt;
 
 	snd_usb_set_format_quirk(subs, fmt);
 
-#if 0
-	printk(KERN_DEBUG
-	       "setting done: format = %d, rate = %d..%d, channels = %d\n",
-	       fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
-	printk(KERN_DEBUG
-	       "  datapipe = 0x%0x, syncpipe = 0x%0x\n",
-	       subs->datapipe, subs->syncpipe);
-#endif
-
 	return 0;
 }
 
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 1f9bbd5..5a51b18 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -305,11 +305,9 @@ static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S)
 {
 	int	i;
 	for (i = 0; i < URBS_AsyncSeq; ++i) {
-		if (S[i].urb) {
-			usb_kill_urb(S->urb[i]);
-			usb_free_urb(S->urb[i]);
-			S->urb[i] = NULL;
-		}
+		usb_kill_urb(S->urb[i]);
+		usb_free_urb(S->urb[i]);
+		S->urb[i] = NULL;
 	}
 	kfree(S->buffer);
 }
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 07819bf..b96eccc 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -79,8 +79,6 @@ enum {
 	DNS
 };
 
-static char kvp_send_buffer[4096];
-static char kvp_recv_buffer[4096 * 2];
 static struct sockaddr_nl addr;
 static int in_hand_shake = 1;
 
@@ -1301,6 +1299,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
 	}
 
 	error = kvp_write_file(file, "HWADDR", "", mac_addr);
+	free(mac_addr);
 	if (error)
 		goto setval_error;
 
@@ -1346,7 +1345,6 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
 		goto setval_error;
 
 setval_done:
-	free(mac_addr);
 	fclose(file);
 
 	/*
@@ -1355,12 +1353,15 @@ setval_done:
 	 */
 
 	snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file);
-	system(cmd);
+	if (system(cmd)) {
+		syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
+				cmd, errno, strerror(errno));
+		return HV_E_FAIL;
+	}
 	return 0;
 
 setval_error:
 	syslog(LOG_ERR, "Failed to write config file");
-	free(mac_addr);
 	fclose(file);
 	return error;
 }
@@ -1437,10 +1438,22 @@ int main(void)
 	int	pool;
 	char	*if_name;
 	struct hv_kvp_ipaddr_value *kvp_ip_val;
+	char *kvp_send_buffer;
+	char *kvp_recv_buffer;
+	size_t kvp_recv_buffer_len;
 
-	daemon(1, 0);
+	if (daemon(1, 0))
+		return 1;
 	openlog("KVP", 0, LOG_USER);
 	syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
+
+	kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
+	kvp_send_buffer = calloc(1, kvp_recv_buffer_len);
+	kvp_recv_buffer = calloc(1, kvp_recv_buffer_len);
+	if (!(kvp_send_buffer && kvp_recv_buffer)) {
+		syslog(LOG_ERR, "Failed to allocate netlink buffers");
+		exit(EXIT_FAILURE);
+	}
 	/*
 	 * Retrieve OS release information.
 	 */
@@ -1514,7 +1527,7 @@ int main(void)
 				continue;
 		}
 
-		len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0,
+		len = recvfrom(fd, kvp_recv_buffer, kvp_recv_buffer_len, 0,
 				addr_p, &addr_l);
 
 		if (len < 0) {
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index fea03a3..4213d0e 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -38,8 +38,6 @@
 #include <linux/netlink.h>
 #include <syslog.h>
 
-static char vss_recv_buffer[4096];
-static char vss_send_buffer[4096];
 static struct sockaddr_nl addr;
 
 #ifndef SOL_NETLINK
@@ -147,6 +145,9 @@ int main(void)
 	struct cn_msg	*incoming_cn_msg;
 	int	op;
 	struct hv_vss_msg *vss_msg;
+	char *vss_send_buffer;
+	char *vss_recv_buffer;
+	size_t vss_recv_buffer_len;
 
 	if (daemon(1, 0))
 		return 1;
@@ -154,9 +155,18 @@ int main(void)
 	openlog("Hyper-V VSS", 0, LOG_USER);
 	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
 
+	vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
+	vss_send_buffer = calloc(1, vss_recv_buffer_len);
+	vss_recv_buffer = calloc(1, vss_recv_buffer_len);
+	if (!(vss_send_buffer && vss_recv_buffer)) {
+		syslog(LOG_ERR, "Failed to allocate netlink buffers");
+		exit(EXIT_FAILURE);
+	}
+
 	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
 	if (fd < 0) {
-		syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
+		syslog(LOG_ERR, "netlink socket creation failed; error:%d %s",
+				errno, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 	addr.nl_family = AF_NETLINK;
@@ -167,12 +177,16 @@ int main(void)
 
 	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
 	if (error < 0) {
-		syslog(LOG_ERR, "bind failed; error:%d", error);
+		syslog(LOG_ERR, "bind failed; error:%d %s", errno, strerror(errno));
 		close(fd);
 		exit(EXIT_FAILURE);
 	}
 	nl_group = CN_VSS_IDX;
-	setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group));
+	if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) {
+		syslog(LOG_ERR, "setsockopt failed; error:%d %s", errno, strerror(errno));
+		close(fd);
+		exit(EXIT_FAILURE);
+	}
 	/*
 	 * Register ourselves with the kernel.
 	 */
@@ -187,7 +201,7 @@ int main(void)
 
 	len = netlink_send(fd, message);
 	if (len < 0) {
-		syslog(LOG_ERR, "netlink_send failed; error:%d", len);
+		syslog(LOG_ERR, "netlink_send failed; error:%d %s", errno, strerror(errno));
 		close(fd);
 		exit(EXIT_FAILURE);
 	}
@@ -199,9 +213,18 @@ int main(void)
 		socklen_t addr_l = sizeof(addr);
 		pfd.events = POLLIN;
 		pfd.revents = 0;
-		poll(&pfd, 1, -1);
 
-		len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0,
+		if (poll(&pfd, 1, -1) < 0) {
+			syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno));
+			if (errno == EINVAL) {
+				close(fd);
+				exit(EXIT_FAILURE);
+			}
+			else
+				continue;
+		}
+
+		len = recvfrom(fd, vss_recv_buffer, vss_recv_buffer_len, 0,
 				addr_p, &addr_l);
 
 		if (len < 0) {
@@ -241,7 +264,8 @@ int main(void)
 		vss_msg->error = error;
 		len = netlink_send(fd, incoming_cn_msg);
 		if (len < 0) {
-			syslog(LOG_ERR, "net_link send failed; error:%d", len);
+			syslog(LOG_ERR, "net_link send failed; error:%d %s",
+					errno, strerror(errno));
 			exit(EXIT_FAILURE);
 		}
 	}
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index 68f67cf..32cf2ce 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -42,6 +42,10 @@
 #include <pwd.h>
 #include <grp.h>
 
+#ifndef VIRTIO_F_ANY_LAYOUT
+#define VIRTIO_F_ANY_LAYOUT		27
+#endif
+
 /*L:110
  * We can ignore the 43 include files we need for this program, but I do want
  * to draw attention to the use of kernel-style types.
@@ -1544,6 +1548,8 @@ static void setup_tun_net(char *arg)
 	add_feature(dev, VIRTIO_NET_F_HOST_ECN);
 	/* We handle indirect ring entries */
 	add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC);
+	/* We're compliant with the damn spec. */
+	add_feature(dev, VIRTIO_F_ANY_LAYOUT);
 	set_config(dev, sizeof(conf), &conf);
 
 	/* We don't need the socket any more; setup is done. */
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 0b0a907..0794acc 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -39,13 +39,8 @@ bindir_relative = bin
 bindir = $(prefix)/$(bindir_relative)
 man_dir = $(prefix)/share/man
 man_dir_SQ = '$(subst ','\'',$(man_dir))'
-html_install = $(prefix)/share/kernelshark/html
-html_install_SQ = '$(subst ','\'',$(html_install))'
-img_install = $(prefix)/share/kernelshark/html/images
-img_install_SQ = '$(subst ','\'',$(img_install))'
 
-export man_dir man_dir_SQ html_install html_install_SQ INSTALL
-export img_install img_install_SQ
+export man_dir man_dir_SQ INSTALL
 export DESTDIR DESTDIR_SQ
 
 # copy a bit from Linux kbuild
@@ -76,10 +71,7 @@ $(if $(BUILD_OUTPUT),, \
 
 all: sub-make
 
-gui: force
-	$(call build_output, all_cmd)
-
-$(filter-out gui,$(MAKECMDGOALS)): sub-make
+$(MAKECMDGOALS): sub-make
 
 sub-make: force
 	$(call build_output, $(MAKECMDGOALS))
@@ -189,6 +181,7 @@ $(obj)/%.o: $(src)/%.c
 	$(Q)$(call do_compile)
 
 PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
+PEVENT_LIB_OBJS += kbuffer-parse.o
 
 ALL_OBJS = $(PEVENT_LIB_OBJS)
 
@@ -258,9 +251,6 @@ define check_deps
 		$(RM) $@.$$$$
 endef
 
-$(gui_deps): ks_version.h
-$(non_gui_deps): tc_version.h
-
 $(all_deps): .%.d: $(src)/%.c
 	$(Q)$(call check_deps)
 
@@ -300,7 +290,7 @@ define do_install
 	$(INSTALL) $1 '$(DESTDIR_SQ)$2'
 endef
 
-install_lib: all_cmd install_plugins install_python
+install_lib: all_cmd
 	$(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
 
 install: install_lib
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 82b0606..d1c2a6a 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -5450,10 +5450,9 @@ int pevent_register_print_function(struct pevent *pevent,
  * If @id is >= 0, then it is used to find the event.
  * else @sys_name and @event_name are used.
  */
-int pevent_register_event_handler(struct pevent *pevent,
-				  int id, char *sys_name, char *event_name,
-				  pevent_event_handler_func func,
-				  void *context)
+int pevent_register_event_handler(struct pevent *pevent, int id,
+				  const char *sys_name, const char *event_name,
+				  pevent_event_handler_func func, void *context)
 {
 	struct event_format *event;
 	struct event_handler *handle;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 7be7e89..c37b202 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -69,6 +69,7 @@ struct trace_seq {
 };
 
 void trace_seq_init(struct trace_seq *s);
+void trace_seq_reset(struct trace_seq *s);
 void trace_seq_destroy(struct trace_seq *s);
 
 extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
@@ -399,6 +400,7 @@ struct pevent {
 
 	int cpus;
 	int long_size;
+	int page_size;
 
 	struct cmdline *cmdlines;
 	struct cmdline_list *cmdlist;
@@ -561,7 +563,8 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
 			   struct event_format *event, const char *name,
 			   struct pevent_record *record, int err);
 
-int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name,
+int pevent_register_event_handler(struct pevent *pevent, int id,
+				  const char *sys_name, const char *event_name,
 				  pevent_event_handler_func func, void *context);
 int pevent_register_print_function(struct pevent *pevent,
 				   pevent_func_handler func,
@@ -619,6 +622,16 @@ static inline void pevent_set_long_size(struct pevent *pevent, int long_size)
 	pevent->long_size = long_size;
 }
 
+static inline int pevent_get_page_size(struct pevent *pevent)
+{
+	return pevent->page_size;
+}
+
+static inline void pevent_set_page_size(struct pevent *pevent, int _page_size)
+{
+	pevent->page_size = _page_size;
+}
+
 static inline int pevent_is_file_bigendian(struct pevent *pevent)
 {
 	return pevent->file_bigendian;
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
new file mode 100644
index 0000000..dcc6652
--- /dev/null
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -0,0 +1,732 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that 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 program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "kbuffer.h"
+
+#define MISSING_EVENTS (1 << 31)
+#define MISSING_STORED (1 << 30)
+
+#define COMMIT_MASK ((1 << 27) - 1)
+
+enum {
+	KBUFFER_FL_HOST_BIG_ENDIAN	= (1<<0),
+	KBUFFER_FL_BIG_ENDIAN		= (1<<1),
+	KBUFFER_FL_LONG_8		= (1<<2),
+	KBUFFER_FL_OLD_FORMAT		= (1<<3),
+};
+
+#define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
+
+/** kbuffer
+ * @timestamp		- timestamp of current event
+ * @lost_events		- # of lost events between this subbuffer and previous
+ * @flags		- special flags of the kbuffer
+ * @subbuffer		- pointer to the sub-buffer page
+ * @data		- pointer to the start of data on the sub-buffer page
+ * @index		- index from @data to the @curr event data
+ * @curr		- offset from @data to the start of current event
+ *			   (includes metadata)
+ * @next		- offset from @data to the start of next event
+ * @size		- The size of data on @data
+ * @start		- The offset from @subbuffer where @data lives
+ *
+ * @read_4		- Function to read 4 raw bytes (may swap)
+ * @read_8		- Function to read 8 raw bytes (may swap)
+ * @read_long		- Function to read a long word (4 or 8 bytes with needed swap)
+ */
+struct kbuffer {
+	unsigned long long 	timestamp;
+	long long		lost_events;
+	unsigned long		flags;
+	void			*subbuffer;
+	void			*data;
+	unsigned int		index;
+	unsigned int		curr;
+	unsigned int		next;
+	unsigned int		size;
+	unsigned int		start;
+
+	unsigned int (*read_4)(void *ptr);
+	unsigned long long (*read_8)(void *ptr);
+	unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
+	int (*next_event)(struct kbuffer *kbuf);
+};
+
+static void *zmalloc(size_t size)
+{
+	return calloc(1, size);
+}
+
+static int host_is_bigendian(void)
+{
+	unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
+	unsigned int *ptr;
+
+	ptr = (unsigned int *)str;
+	return *ptr == 0x01020304;
+}
+
+static int do_swap(struct kbuffer *kbuf)
+{
+	return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
+		ENDIAN_MASK;
+}
+
+static unsigned long long __read_8(void *ptr)
+{
+	unsigned long long data = *(unsigned long long *)ptr;
+
+	return data;
+}
+
+static unsigned long long __read_8_sw(void *ptr)
+{
+	unsigned long long data = *(unsigned long long *)ptr;
+	unsigned long long swap;
+
+	swap = ((data & 0xffULL) << 56) |
+		((data & (0xffULL << 8)) << 40) |
+		((data & (0xffULL << 16)) << 24) |
+		((data & (0xffULL << 24)) << 8) |
+		((data & (0xffULL << 32)) >> 8) |
+		((data & (0xffULL << 40)) >> 24) |
+		((data & (0xffULL << 48)) >> 40) |
+		((data & (0xffULL << 56)) >> 56);
+
+	return swap;
+}
+
+static unsigned int __read_4(void *ptr)
+{
+	unsigned int data = *(unsigned int *)ptr;
+
+	return data;
+}
+
+static unsigned int __read_4_sw(void *ptr)
+{
+	unsigned int data = *(unsigned int *)ptr;
+	unsigned int swap;
+
+	swap = ((data & 0xffULL) << 24) |
+		((data & (0xffULL << 8)) << 8) |
+		((data & (0xffULL << 16)) >> 8) |
+		((data & (0xffULL << 24)) >> 24);
+
+	return swap;
+}
+
+static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
+{
+	return kbuf->read_8(ptr);
+}
+
+static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
+{
+	return kbuf->read_4(ptr);
+}
+
+static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
+{
+	return kbuf->read_8(ptr);
+}
+
+static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
+{
+	return kbuf->read_4(ptr);
+}
+
+static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
+{
+	return kbuf->read_long(kbuf, ptr);
+}
+
+static int calc_index(struct kbuffer *kbuf, void *ptr)
+{
+	return (unsigned long)ptr - (unsigned long)kbuf->data;
+}
+
+static int __next_event(struct kbuffer *kbuf);
+
+/**
+ * kbuffer_alloc - allocat a new kbuffer
+ * @size;	enum to denote size of word
+ * @endian:	enum to denote endianness
+ *
+ * Allocates and returns a new kbuffer.
+ */
+struct kbuffer *
+kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
+{
+	struct kbuffer *kbuf;
+	int flags = 0;
+
+	switch (size) {
+	case KBUFFER_LSIZE_4:
+		break;
+	case KBUFFER_LSIZE_8:
+		flags |= KBUFFER_FL_LONG_8;
+		break;
+	default:
+		return NULL;
+	}
+
+	switch (endian) {
+	case KBUFFER_ENDIAN_LITTLE:
+		break;
+	case KBUFFER_ENDIAN_BIG:
+		flags |= KBUFFER_FL_BIG_ENDIAN;
+		break;
+	default:
+		return NULL;
+	}
+
+	kbuf = zmalloc(sizeof(*kbuf));
+	if (!kbuf)
+		return NULL;
+
+	kbuf->flags = flags;
+
+	if (host_is_bigendian())
+		kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
+
+	if (do_swap(kbuf)) {
+		kbuf->read_8 = __read_8_sw;
+		kbuf->read_4 = __read_4_sw;
+	} else {
+		kbuf->read_8 = __read_8;
+		kbuf->read_4 = __read_4;
+	}
+
+	if (kbuf->flags & KBUFFER_FL_LONG_8)
+		kbuf->read_long = __read_long_8;
+	else
+		kbuf->read_long = __read_long_4;
+
+	/* May be changed by kbuffer_set_old_format() */
+	kbuf->next_event = __next_event;
+
+	return kbuf;
+}
+
+/** kbuffer_free - free an allocated kbuffer
+ * @kbuf:	The kbuffer to free
+ *
+ * Can take NULL as a parameter.
+ */
+void kbuffer_free(struct kbuffer *kbuf)
+{
+	free(kbuf);
+}
+
+static unsigned int type4host(struct kbuffer *kbuf,
+			      unsigned int type_len_ts)
+{
+	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+		return (type_len_ts >> 29) & 3;
+	else
+		return type_len_ts & 3;
+}
+
+static unsigned int len4host(struct kbuffer *kbuf,
+			     unsigned int type_len_ts)
+{
+	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+		return (type_len_ts >> 27) & 7;
+	else
+		return (type_len_ts >> 2) & 7;
+}
+
+static unsigned int type_len4host(struct kbuffer *kbuf,
+				  unsigned int type_len_ts)
+{
+	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+		return (type_len_ts >> 27) & ((1 << 5) - 1);
+	else
+		return type_len_ts & ((1 << 5) - 1);
+}
+
+static unsigned int ts4host(struct kbuffer *kbuf,
+			    unsigned int type_len_ts)
+{
+	if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+		return type_len_ts & ((1 << 27) - 1);
+	else
+		return type_len_ts >> 5;
+}
+
+/*
+ * Linux 2.6.30 and earlier (not much ealier) had a different
+ * ring buffer format. It should be obsolete, but we handle it anyway.
+ */
+enum old_ring_buffer_type {
+	OLD_RINGBUF_TYPE_PADDING,
+	OLD_RINGBUF_TYPE_TIME_EXTEND,
+	OLD_RINGBUF_TYPE_TIME_STAMP,
+	OLD_RINGBUF_TYPE_DATA,
+};
+
+static unsigned int old_update_pointers(struct kbuffer *kbuf)
+{
+	unsigned long long extend;
+	unsigned int type_len_ts;
+	unsigned int type;
+	unsigned int len;
+	unsigned int delta;
+	unsigned int length;
+	void *ptr = kbuf->data + kbuf->curr;
+
+	type_len_ts = read_4(kbuf, ptr);
+	ptr += 4;
+
+	type = type4host(kbuf, type_len_ts);
+	len = len4host(kbuf, type_len_ts);
+	delta = ts4host(kbuf, type_len_ts);
+
+	switch (type) {
+	case OLD_RINGBUF_TYPE_PADDING:
+		kbuf->next = kbuf->size;
+		return 0;
+
+	case OLD_RINGBUF_TYPE_TIME_EXTEND:
+		extend = read_4(kbuf, ptr);
+		extend <<= TS_SHIFT;
+		extend += delta;
+		delta = extend;
+		ptr += 4;
+		break;
+
+	case OLD_RINGBUF_TYPE_TIME_STAMP:
+		/* should never happen! */
+		kbuf->curr = kbuf->size;
+		kbuf->next = kbuf->size;
+		kbuf->index = kbuf->size;
+		return -1;
+	default:
+		if (len)
+			length = len * 4;
+		else {
+			length = read_4(kbuf, ptr);
+			length -= 4;
+			ptr += 4;
+		}
+		break;
+	}
+
+	kbuf->timestamp += delta;
+	kbuf->index = calc_index(kbuf, ptr);
+	kbuf->next = kbuf->index + length;
+
+	return type;
+}
+
+static int __old_next_event(struct kbuffer *kbuf)
+{
+	int type;
+
+	do {
+		kbuf->curr = kbuf->next;
+		if (kbuf->next >= kbuf->size)
+			return -1;
+		type = old_update_pointers(kbuf);
+	} while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
+
+	return 0;
+}
+
+static unsigned int
+translate_data(struct kbuffer *kbuf, void *data, void **rptr,
+	       unsigned long long *delta, int *length)
+{
+	unsigned long long extend;
+	unsigned int type_len_ts;
+	unsigned int type_len;
+
+	type_len_ts = read_4(kbuf, data);
+	data += 4;
+
+	type_len = type_len4host(kbuf, type_len_ts);
+	*delta = ts4host(kbuf, type_len_ts);
+
+	switch (type_len) {
+	case KBUFFER_TYPE_PADDING:
+		*length = read_4(kbuf, data);
+		data += *length;
+		break;
+
+	case KBUFFER_TYPE_TIME_EXTEND:
+		extend = read_4(kbuf, data);
+		data += 4;
+		extend <<= TS_SHIFT;
+		extend += *delta;
+		*delta = extend;
+		*length = 0;
+		break;
+
+	case KBUFFER_TYPE_TIME_STAMP:
+		data += 12;
+		*length = 0;
+		break;
+	case 0:
+		*length = read_4(kbuf, data) - 4;
+		*length = (*length + 3) & ~3;
+		data += 4;
+		break;
+	default:
+		*length = type_len * 4;
+		break;
+	}
+
+	*rptr = data;
+
+	return type_len;
+}
+
+static unsigned int update_pointers(struct kbuffer *kbuf)
+{
+	unsigned long long delta;
+	unsigned int type_len;
+	int length;
+	void *ptr = kbuf->data + kbuf->curr;
+
+	type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
+
+	kbuf->timestamp += delta;
+	kbuf->index = calc_index(kbuf, ptr);
+	kbuf->next = kbuf->index + length;
+
+	return type_len;
+}
+
+/**
+ * kbuffer_translate_data - read raw data to get a record
+ * @swap:	Set to 1 if bytes in words need to be swapped when read
+ * @data:	The raw data to read
+ * @size:	Address to store the size of the event data.
+ *
+ * Returns a pointer to the event data. To determine the entire
+ * record size (record metadata + data) just add the difference between
+ * @data and the returned value to @size.
+ */
+void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
+{
+	unsigned long long delta;
+	struct kbuffer kbuf;
+	int type_len;
+	int length;
+	void *ptr;
+
+	if (swap) {
+		kbuf.read_8 = __read_8_sw;
+		kbuf.read_4 = __read_4_sw;
+		kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
+	} else {
+		kbuf.read_8 = __read_8;
+		kbuf.read_4 = __read_4;
+		kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
+	}
+
+	type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
+	switch (type_len) {
+	case KBUFFER_TYPE_PADDING:
+	case KBUFFER_TYPE_TIME_EXTEND:
+	case KBUFFER_TYPE_TIME_STAMP:
+		return NULL;
+	};
+
+	*size = length;
+
+	return ptr;
+}
+
+static int __next_event(struct kbuffer *kbuf)
+{
+	int type;
+
+	do {
+		kbuf->curr = kbuf->next;
+		if (kbuf->next >= kbuf->size)
+			return -1;
+		type = update_pointers(kbuf);
+	} while (type == KBUFFER_TYPE_TIME_EXTEND || type == KBUFFER_TYPE_PADDING);
+
+	return 0;
+}
+
+static int next_event(struct kbuffer *kbuf)
+{
+	return kbuf->next_event(kbuf);
+}
+
+/**
+ * kbuffer_next_event - increment the current pointer
+ * @kbuf:	The kbuffer to read
+ * @ts:		Address to store the next record's timestamp (may be NULL to ignore)
+ *
+ * Increments the pointers into the subbuffer of the kbuffer to point to the
+ * next event so that the next kbuffer_read_event() will return a
+ * new event.
+ *
+ * Returns the data of the next event if a new event exists on the subbuffer,
+ * NULL otherwise.
+ */
+void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
+{
+	int ret;
+
+	if (!kbuf || !kbuf->subbuffer)
+		return NULL;
+
+	ret = next_event(kbuf);
+	if (ret < 0)
+		return NULL;
+
+	if (ts)
+		*ts = kbuf->timestamp;
+
+	return kbuf->data + kbuf->index;
+}
+
+/**
+ * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer
+ * @kbuf:	The kbuffer to load
+ * @subbuffer:	The subbuffer to load into @kbuf.
+ *
+ * Load a new subbuffer (page) into @kbuf. This will reset all
+ * the pointers and update the @kbuf timestamp. The next read will
+ * return the first event on @subbuffer.
+ *
+ * Returns 0 on succes, -1 otherwise.
+ */
+int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
+{
+	unsigned long long flags;
+	void *ptr = subbuffer;
+
+	if (!kbuf || !subbuffer)
+		return -1;
+
+	kbuf->subbuffer = subbuffer;
+
+	kbuf->timestamp = read_8(kbuf, ptr);
+	ptr += 8;
+
+	kbuf->curr = 0;
+
+	if (kbuf->flags & KBUFFER_FL_LONG_8)
+		kbuf->start = 16;
+	else
+		kbuf->start = 12;
+
+	kbuf->data = subbuffer + kbuf->start;
+
+	flags = read_long(kbuf, ptr);
+	kbuf->size = (unsigned int)flags & COMMIT_MASK;
+
+	if (flags & MISSING_EVENTS) {
+		if (flags & MISSING_STORED) {
+			ptr = kbuf->data + kbuf->size;
+			kbuf->lost_events = read_long(kbuf, ptr);
+		} else
+			kbuf->lost_events = -1;
+	} else
+		kbuf->lost_events = 0;
+
+	kbuf->index = 0;
+	kbuf->next = 0;
+
+	next_event(kbuf);
+
+	return 0;
+}
+
+/**
+ * kbuffer_read_event - read the next event in the kbuffer subbuffer
+ * @kbuf:	The kbuffer to read from
+ * @ts:		The address to store the timestamp of the event (may be NULL to ignore)
+ *
+ * Returns a pointer to the data part of the current event.
+ * NULL if no event is left on the subbuffer.
+ */
+void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
+{
+	if (!kbuf || !kbuf->subbuffer)
+		return NULL;
+
+	if (kbuf->curr >= kbuf->size)
+		return NULL;
+
+	if (ts)
+		*ts = kbuf->timestamp;
+	return kbuf->data + kbuf->index;
+}
+
+/**
+ * kbuffer_timestamp - Return the timestamp of the current event
+ * @kbuf:	The kbuffer to read from
+ *
+ * Returns the timestamp of the current (next) event.
+ */
+unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
+{
+	return kbuf->timestamp;
+}
+
+/**
+ * kbuffer_read_at_offset - read the event that is at offset
+ * @kbuf:	The kbuffer to read from
+ * @offset:	The offset into the subbuffer
+ * @ts:		The address to store the timestamp of the event (may be NULL to ignore)
+ *
+ * The @offset must be an index from the @kbuf subbuffer beginning.
+ * If @offset is bigger than the stored subbuffer, NULL will be returned.
+ *
+ * Returns the data of the record that is at @offset. Note, @offset does
+ * not need to be the start of the record, the offset just needs to be
+ * in the record (or beginning of it).
+ *
+ * Note, the kbuf timestamp and pointers are updated to the
+ * returned record. That is, kbuffer_read_event() will return the same
+ * data and timestamp, and kbuffer_next_event() will increment from
+ * this record.
+ */
+void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
+			     unsigned long long *ts)
+{
+	void *data;
+
+	if (offset < kbuf->start)
+		offset = 0;
+	else
+		offset -= kbuf->start;
+
+	/* Reset the buffer */
+	kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
+
+	while (kbuf->curr < offset) {
+		data = kbuffer_next_event(kbuf, ts);
+		if (!data)
+			break;
+	}
+
+	return data;
+}
+
+/**
+ * kbuffer_subbuffer_size - the size of the loaded subbuffer
+ * @kbuf:	The kbuffer to read from
+ *
+ * Returns the size of the subbuffer. Note, this size is
+ * where the last event resides. The stored subbuffer may actually be
+ * bigger due to padding and such.
+ */
+int kbuffer_subbuffer_size(struct kbuffer *kbuf)
+{
+	return kbuf->size;
+}
+
+/**
+ * kbuffer_curr_index - Return the index of the record
+ * @kbuf:	The kbuffer to read from
+ *
+ * Returns the index from the start of the data part of
+ * the subbuffer to the current location. Note this is not
+ * from the start of the subbuffer. An index of zero will
+ * point to the first record. Use kbuffer_curr_offset() for
+ * the actually offset (that can be used by kbuffer_read_at_offset())
+ */
+int kbuffer_curr_index(struct kbuffer *kbuf)
+{
+	return kbuf->curr;
+}
+
+/**
+ * kbuffer_curr_offset - Return the offset of the record
+ * @kbuf:	The kbuffer to read from
+ *
+ * Returns the offset from the start of the subbuffer to the
+ * current location.
+ */
+int kbuffer_curr_offset(struct kbuffer *kbuf)
+{
+	return kbuf->curr + kbuf->start;
+}
+
+/**
+ * kbuffer_event_size - return the size of the event data
+ * @kbuf:	The kbuffer to read
+ *
+ * Returns the size of the event data (the payload not counting
+ * the meta data of the record) of the current event.
+ */
+int kbuffer_event_size(struct kbuffer *kbuf)
+{
+	return kbuf->next - kbuf->index;
+}
+
+/**
+ * kbuffer_curr_size - return the size of the entire record
+ * @kbuf:	The kbuffer to read
+ *
+ * Returns the size of the entire record (meta data and payload)
+ * of the current event.
+ */
+int kbuffer_curr_size(struct kbuffer *kbuf)
+{
+	return kbuf->next - kbuf->curr;
+}
+
+/**
+ * kbuffer_missed_events - return the # of missed events from last event.
+ * @kbuf: 	The kbuffer to read from
+ *
+ * Returns the # of missed events (if recorded) before the current
+ * event. Note, only events on the beginning of a subbuffer can
+ * have missed events, all other events within the buffer will be
+ * zero.
+ */
+int kbuffer_missed_events(struct kbuffer *kbuf)
+{
+	/* Only the first event can have missed events */
+	if (kbuf->curr)
+		return 0;
+
+	return kbuf->lost_events;
+}
+
+/**
+ * kbuffer_set_old_forma - set the kbuffer to use the old format parsing
+ * @kbuf:	The kbuffer to set
+ *
+ * This is obsolete (or should be). The first kernels to use the
+ * new ring buffer had a slightly different ring buffer format
+ * (2.6.30 and earlier). It is still somewhat supported by kbuffer,
+ * but should not be counted on in the future.
+ */
+void kbuffer_set_old_format(struct kbuffer *kbuf)
+{
+	kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
+
+	kbuf->next_event = __old_next_event;
+}
diff --git a/tools/lib/traceevent/kbuffer.h b/tools/lib/traceevent/kbuffer.h
new file mode 100644
index 0000000..c831f64
--- /dev/null
+++ b/tools/lib/traceevent/kbuffer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that 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 program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef _KBUFFER_H
+#define _KBUFFER_H
+
+#ifndef TS_SHIFT
+#define TS_SHIFT		27
+#endif
+
+enum kbuffer_endian {
+	KBUFFER_ENDIAN_BIG,
+	KBUFFER_ENDIAN_LITTLE,
+};
+
+enum kbuffer_long_size {
+	KBUFFER_LSIZE_4,
+	KBUFFER_LSIZE_8,
+};
+
+enum {
+	KBUFFER_TYPE_PADDING		= 29,
+	KBUFFER_TYPE_TIME_EXTEND	= 30,
+	KBUFFER_TYPE_TIME_STAMP		= 31,
+};
+
+struct kbuffer;
+
+struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian);
+void kbuffer_free(struct kbuffer *kbuf);
+int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer);
+void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
+void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts);
+unsigned long long kbuffer_timestamp(struct kbuffer *kbuf);
+
+void *kbuffer_translate_data(int swap, void *data, unsigned int *size);
+
+void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts);
+
+int kbuffer_curr_index(struct kbuffer *kbuf);
+
+int kbuffer_curr_offset(struct kbuffer *kbuf);
+int kbuffer_curr_size(struct kbuffer *kbuf);
+int kbuffer_event_size(struct kbuffer *kbuf);
+int kbuffer_missed_events(struct kbuffer *kbuf);
+int kbuffer_subbuffer_size(struct kbuffer *kbuf);
+
+void kbuffer_set_old_format(struct kbuffer *kbuf);
+
+#endif /* _K_BUFFER_H */
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index a57db80..d7f2e68 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -49,6 +49,19 @@ void trace_seq_init(struct trace_seq *s)
 }
 
 /**
+ * trace_seq_reset - re-initialize the trace_seq structure
+ * @s: a pointer to the trace_seq structure to reset
+ */
+void trace_seq_reset(struct trace_seq *s)
+{
+	if (!s)
+		return;
+	TRACE_SEQ_CHECK(s);
+	s->len = 0;
+	s->readpos = 0;
+}
+
+/**
  * trace_seq_destroy - free up memory of a trace_seq
  * @s: a pointer to the trace_seq to free the buffer
  *
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 5b3123d..fdfceee 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -3,17 +3,17 @@ perf-diff(1)
 
 NAME
 ----
-perf-diff - Read two perf.data files and display the differential profile
+perf-diff - Read perf.data files and display the differential profile
 
 SYNOPSIS
 --------
 [verse]
-'perf diff' [oldfile] [newfile]
+'perf diff' [baseline file] [data file1] [[data file2] ... ]
 
 DESCRIPTION
 -----------
-This command displays the performance difference amongst two perf.data files
-captured via perf record.
+This command displays the performance difference amongst two or more perf.data
+files captured via perf record.
 
 If no parameters are passed it will assume perf.data.old and perf.data.
 
@@ -75,8 +75,6 @@ OPTIONS
 -c::
 --compute::
         Differential computation selection - delta,ratio,wdiff (default is delta).
-        If '+' is specified as a first character, the output is sorted based
-        on the computation results.
         See COMPARISON METHODS section for more info.
 
 -p::
@@ -87,6 +85,63 @@ OPTIONS
 --formula::
         Show formula for given computation.
 
+-o::
+--order::
+       Specify compute sorting column number.
+
+COMPARISON
+----------
+The comparison is governed by the baseline file. The baseline perf.data
+file is iterated for samples. All other perf.data files specified on
+the command line are searched for the baseline sample pair. If the pair
+is found, specified computation is made and result is displayed.
+
+All samples from non-baseline perf.data files, that do not match any
+baseline entry, are displayed with empty space within baseline column
+and possible computation results (delta) in their related column.
+
+Example files samples:
+- file A with samples f1, f2, f3, f4,    f6
+- file B with samples     f2,     f4, f5
+- file C with samples f1, f2,         f5
+
+Example output:
+  x - computation takes place for pair
+  b - baseline sample percentage
+
+- perf diff A B C
+
+  baseline/A compute/B compute/C  samples
+  ---------------------------------------
+  b                    x          f1
+  b          x         x          f2
+  b                               f3
+  b          x                    f4
+  b                               f6
+             x         x          f5
+
+- perf diff B A C
+
+  baseline/B compute/A compute/C  samples
+  ---------------------------------------
+  b          x         x          f2
+  b          x                    f4
+  b                    x          f5
+             x         x          f1
+             x                    f3
+             x                    f6
+
+- perf diff C B A
+
+  baseline/C compute/B compute/A  samples
+  ---------------------------------------
+  b                    x          f1
+  b          x         x          f2
+  b          x                    f5
+                       x          f3
+             x         x          f4
+                       x          f6
+
 COMPARISON METHODS
 ------------------
 delta
@@ -96,7 +151,7 @@ If specified the 'Delta' column is displayed with value 'd' computed as:
   d = A->period_percent - B->period_percent
 
 with:
-  - A/B being matching hist entry from first/second file specified
+  - A/B being matching hist entry from data/baseline file specified
     (or perf.data/perf.data.old) respectively.
 
   - period_percent being the % of the hist entry period value within
@@ -109,24 +164,26 @@ If specified the 'Ratio' column is displayed with value 'r' computed as:
   r = A->period / B->period
 
 with:
-  - A/B being matching hist entry from first/second file specified
+  - A/B being matching hist entry from data/baseline file specified
     (or perf.data/perf.data.old) respectively.
 
   - period being the hist entry period value
 
-wdiff
-~~~~~
+wdiff:WEIGHT-B,WEIGHT-A
+~~~~~~~~~~~~~~~~~~~~~~~
 If specified the 'Weighted diff' column is displayed with value 'd' computed as:
 
    d = B->period * WEIGHT-A - A->period * WEIGHT-B
 
-  - A/B being matching hist entry from first/second file specified
+  - A/B being matching hist entry from data/baseline file specified
     (or perf.data/perf.data.old) respectively.
 
   - period being the hist entry period value
 
   - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
     behind ':' separator like '-c wdiff:1,2'.
+    - WIEGHT-A being the weight of the data file
+    - WIEGHT-B being the weight of the baseline data file
 
 SEE ALSO
 --------
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index d1e39dc..826f3d6 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
 SYNOPSIS
 --------
 [verse]
-'perf list' [hw|sw|cache|tracepoint|event_glob]
+'perf list' [hw|sw|cache|tracepoint|pmu|event_glob]
 
 DESCRIPTION
 -----------
@@ -104,6 +104,8 @@ To limit the list use:
   'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched,
   block, etc.
 
+. 'pmu' to print the kernel supplied PMU events.
+
 . If none of the above is matched, it will apply the supplied glob to all
   events, printing the ones that match.
 
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 66dab74..2b8097e 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -115,7 +115,7 @@ OPTIONS
 --dump-raw-trace::
         Dump raw trace in ASCII.
 
--g [type,min[,limit],order]::
+-g [type,min[,limit],order[,key]]::
 --call-graph::
         Display call chains using type, min percent threshold, optional print
 	limit and order.
@@ -129,12 +129,21 @@ OPTIONS
 	- callee: callee based call graph.
 	- caller: inverted caller based call graph.
 
-	Default: fractal,0.5,callee.
+	key can be:
+	- function: compare on functions
+	- address: compare on individual code addresses
+
+	Default: fractal,0.5,callee,function.
 
 -G::
 --inverted::
         alias for inverted caller based call graph.
 
+--ignore-callees=<regex>::
+        Ignore callees of the function(s) matching the given regex.
+        This has the effect of collecting the callers of each such
+        function into one place in the call-graph tree.
+
 --pretty=<key>::
         Pretty printing style.  key: normal, raw
 
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 7fdd190..58d6598 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -155,6 +155,11 @@ Default is to monitor all CPUS.
 
 	Default: fractal,0.5,callee.
 
+--ignore-callees=<regex>::
+        Ignore callees of the function(s) matching the given regex.
+        This has the effect of collecting the callers of each such
+        function into one place in the call-graph tree.
+
 --percent-limit::
 	Do not show entries which have an overhead under that percent.
 	(Default: 0).
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 641fccd..bfd12d0 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -124,7 +124,7 @@ strip-libs = $(filter-out -l%,$(1))
 ifneq ($(OUTPUT),)
   TE_PATH=$(OUTPUT)
 ifneq ($(subdir),)
-  LK_PATH=$(objtree)/lib/lk/
+  LK_PATH=$(OUTPUT)/../lib/lk/
 else
   LK_PATH=$(OUTPUT)
 endif
@@ -281,7 +281,7 @@ LIB_H += util/cpumap.h
 LIB_H += util/top.h
 LIB_H += $(ARCH_INCLUDE)
 LIB_H += util/cgroup.h
-LIB_H += $(TRACE_EVENT_DIR)event-parse.h
+LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
 LIB_H += util/target.h
 LIB_H += util/rblist.h
 LIB_H += util/intlist.h
@@ -389,6 +389,9 @@ LIB_OBJS += $(OUTPUT)tests/bp_signal.o
 LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
 LIB_OBJS += $(OUTPUT)tests/task-exit.o
 LIB_OBJS += $(OUTPUT)tests/sw-clock.o
+ifeq ($(ARCH),x86)
+LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
+endif
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -631,10 +634,10 @@ $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
 
 $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
 
 $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
 
 $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 815841c..8801fe0 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -6,3 +6,5 @@ ifndef NO_LIBUNWIND
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
 endif
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
+LIB_H += arch/$(ARCH)/util/tsc.h
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
new file mode 100644
index 0000000..f111744
--- /dev/null
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -0,0 +1,59 @@
+#include <stdbool.h>
+#include <errno.h>
+
+#include <linux/perf_event.h>
+
+#include "../../perf.h"
+#include "../../util/types.h"
+#include "../../util/debug.h"
+#include "tsc.h"
+
+u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc)
+{
+	u64 time, quot, rem;
+
+	time = ns - tc->time_zero;
+	quot = time / tc->time_mult;
+	rem  = time % tc->time_mult;
+	return (quot << tc->time_shift) +
+	       (rem << tc->time_shift) / tc->time_mult;
+}
+
+u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
+{
+	u64 quot, rem;
+
+	quot = cyc >> tc->time_shift;
+	rem  = cyc & ((1 << tc->time_shift) - 1);
+	return tc->time_zero + quot * tc->time_mult +
+	       ((rem * tc->time_mult) >> tc->time_shift);
+}
+
+int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
+			     struct perf_tsc_conversion *tc)
+{
+	bool cap_usr_time_zero;
+	u32 seq;
+	int i = 0;
+
+	while (1) {
+		seq = pc->lock;
+		rmb();
+		tc->time_mult = pc->time_mult;
+		tc->time_shift = pc->time_shift;
+		tc->time_zero = pc->time_zero;
+		cap_usr_time_zero = pc->cap_usr_time_zero;
+		rmb();
+		if (pc->lock == seq && !(seq & 1))
+			break;
+		if (++i > 10000) {
+			pr_debug("failed to get perf_event_mmap_page lock\n");
+			return -EINVAL;
+		}
+	}
+
+	if (!cap_usr_time_zero)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h
new file mode 100644
index 0000000..a24dec8
--- /dev/null
+++ b/tools/perf/arch/x86/util/tsc.h
@@ -0,0 +1,20 @@
+#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
+#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
+
+#include "../../util/types.h"
+
+struct perf_tsc_conversion {
+	u16 time_shift;
+	u32 time_mult;
+	u64 time_zero;
+};
+
+struct perf_event_mmap_page;
+
+int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
+			     struct perf_tsc_conversion *tc);
+
+u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
+u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);
+
+#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 25fd3f1..8cdca43 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -117,6 +117,8 @@ static void alloc_mem(void **dst, void **src, size_t length)
 	*src = zalloc(length);
 	if (!*src)
 		die("memory allocation failed - maybe length is too large?\n");
+	/* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
+	memset(*src, 0, length);
 }
 
 static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 0aac5f3..93de3ac 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -18,15 +18,53 @@
 #include "util/util.h"
 
 #include <stdlib.h>
+#include <math.h>
 
-static char const *input_old = "perf.data.old",
-		  *input_new = "perf.data";
-static char	  diff__default_sort_order[] = "dso,symbol";
-static bool  force;
+/* Diff command specific HPP columns. */
+enum {
+	PERF_HPP_DIFF__BASELINE,
+	PERF_HPP_DIFF__PERIOD,
+	PERF_HPP_DIFF__PERIOD_BASELINE,
+	PERF_HPP_DIFF__DELTA,
+	PERF_HPP_DIFF__RATIO,
+	PERF_HPP_DIFF__WEIGHTED_DIFF,
+	PERF_HPP_DIFF__FORMULA,
+
+	PERF_HPP_DIFF__MAX_INDEX
+};
+
+struct diff_hpp_fmt {
+	struct perf_hpp_fmt	 fmt;
+	int			 idx;
+	char			*header;
+	int			 header_width;
+};
+
+struct data__file {
+	struct perf_session	*session;
+	const char		*file;
+	int			 idx;
+	struct hists		*hists;
+	struct diff_hpp_fmt	 fmt[PERF_HPP_DIFF__MAX_INDEX];
+};
+
+static struct data__file *data__files;
+static int data__files_cnt;
+
+#define data__for_each_file_start(i, d, s)	\
+	for (i = s, d = &data__files[s];	\
+	     i < data__files_cnt;		\
+	     i++, d = &data__files[i])
+
+#define data__for_each_file(i, d) data__for_each_file_start(i, d, 0)
+#define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1)
+
+static char diff__default_sort_order[] = "dso,symbol";
+static bool force;
 static bool show_period;
 static bool show_formula;
 static bool show_baseline_only;
-static bool sort_compute;
+static unsigned int sort_compute;
 
 static s64 compute_wdiff_w1;
 static s64 compute_wdiff_w2;
@@ -46,6 +84,47 @@ const char *compute_names[COMPUTE_MAX] = {
 
 static int compute;
 
+static int compute_2_hpp[COMPUTE_MAX] = {
+	[COMPUTE_DELTA]		= PERF_HPP_DIFF__DELTA,
+	[COMPUTE_RATIO]		= PERF_HPP_DIFF__RATIO,
+	[COMPUTE_WEIGHTED_DIFF]	= PERF_HPP_DIFF__WEIGHTED_DIFF,
+};
+
+#define MAX_COL_WIDTH 70
+
+static struct header_column {
+	const char *name;
+	int width;
+} columns[PERF_HPP_DIFF__MAX_INDEX] = {
+	[PERF_HPP_DIFF__BASELINE] = {
+		.name  = "Baseline",
+	},
+	[PERF_HPP_DIFF__PERIOD] = {
+		.name  = "Period",
+		.width = 14,
+	},
+	[PERF_HPP_DIFF__PERIOD_BASELINE] = {
+		.name  = "Base period",
+		.width = 14,
+	},
+	[PERF_HPP_DIFF__DELTA] = {
+		.name  = "Delta",
+		.width = 7,
+	},
+	[PERF_HPP_DIFF__RATIO] = {
+		.name  = "Ratio",
+		.width = 14,
+	},
+	[PERF_HPP_DIFF__WEIGHTED_DIFF] = {
+		.name  = "Weighted diff",
+		.width = 14,
+	},
+	[PERF_HPP_DIFF__FORMULA] = {
+		.name  = "Formula",
+		.width = MAX_COL_WIDTH,
+	}
+};
+
 static int setup_compute_opt_wdiff(char *opt)
 {
 	char *w1_str = opt;
@@ -109,13 +188,6 @@ static int setup_compute(const struct option *opt, const char *str,
 		return 0;
 	}
 
-	if (*str == '+') {
-		sort_compute = true;
-		cstr = (char *) ++str;
-		if (!*str)
-			return 0;
-	}
-
 	option = strchr(str, ':');
 	if (option) {
 		unsigned len = option++ - str;
@@ -145,42 +217,42 @@ static int setup_compute(const struct option *opt, const char *str,
 	return -EINVAL;
 }
 
-double perf_diff__period_percent(struct hist_entry *he, u64 period)
+static double period_percent(struct hist_entry *he, u64 period)
 {
 	u64 total = he->hists->stats.total_period;
 	return (period * 100.0) / total;
 }
 
-double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair)
+static double compute_delta(struct hist_entry *he, struct hist_entry *pair)
 {
-	double new_percent = perf_diff__period_percent(he, he->stat.period);
-	double old_percent = perf_diff__period_percent(pair, pair->stat.period);
+	double old_percent = period_percent(he, he->stat.period);
+	double new_percent = period_percent(pair, pair->stat.period);
 
-	he->diff.period_ratio_delta = new_percent - old_percent;
-	he->diff.computed = true;
-	return he->diff.period_ratio_delta;
+	pair->diff.period_ratio_delta = new_percent - old_percent;
+	pair->diff.computed = true;
+	return pair->diff.period_ratio_delta;
 }
 
-double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair)
+static double compute_ratio(struct hist_entry *he, struct hist_entry *pair)
 {
-	double new_period = he->stat.period;
-	double old_period = pair->stat.period;
+	double old_period = he->stat.period ?: 1;
+	double new_period = pair->stat.period;
 
-	he->diff.computed = true;
-	he->diff.period_ratio = new_period / old_period;
-	return he->diff.period_ratio;
+	pair->diff.computed = true;
+	pair->diff.period_ratio = new_period / old_period;
+	return pair->diff.period_ratio;
 }
 
-s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
+static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
 {
-	u64 new_period = he->stat.period;
-	u64 old_period = pair->stat.period;
+	u64 old_period = he->stat.period;
+	u64 new_period = pair->stat.period;
 
-	he->diff.computed = true;
-	he->diff.wdiff = new_period * compute_wdiff_w2 -
-			 old_period * compute_wdiff_w1;
+	pair->diff.computed = true;
+	pair->diff.wdiff = new_period * compute_wdiff_w2 -
+			   old_period * compute_wdiff_w1;
 
-	return he->diff.wdiff;
+	return pair->diff.wdiff;
 }
 
 static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
@@ -189,15 +261,15 @@ static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
 	return scnprintf(buf, size,
 			 "(%" PRIu64 " * 100 / %" PRIu64 ") - "
 			 "(%" PRIu64 " * 100 / %" PRIu64 ")",
-			  he->stat.period, he->hists->stats.total_period,
-			  pair->stat.period, pair->hists->stats.total_period);
+			  pair->stat.period, pair->hists->stats.total_period,
+			  he->stat.period, he->hists->stats.total_period);
 }
 
 static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
 			 char *buf, size_t size)
 {
-	double new_period = he->stat.period;
-	double old_period = pair->stat.period;
+	double old_period = he->stat.period;
+	double new_period = pair->stat.period;
 
 	return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
 }
@@ -205,16 +277,16 @@ static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
 static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
 			 char *buf, size_t size)
 {
-	u64 new_period = he->stat.period;
-	u64 old_period = pair->stat.period;
+	u64 old_period = he->stat.period;
+	u64 new_period = pair->stat.period;
 
 	return scnprintf(buf, size,
 		  "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
 		  new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
 }
 
-int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
-		       char *buf, size_t size)
+static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
+			   char *buf, size_t size)
 {
 	switch (compute) {
 	case COMPUTE_DELTA:
@@ -299,6 +371,29 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
 	}
 }
 
+static struct hist_entry*
+get_pair_data(struct hist_entry *he, struct data__file *d)
+{
+	if (hist_entry__has_pairs(he)) {
+		struct hist_entry *pair;
+
+		list_for_each_entry(pair, &he->pairs.head, pairs.node)
+			if (pair->hists == d->hists)
+				return pair;
+	}
+
+	return NULL;
+}
+
+static struct hist_entry*
+get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
+{
+	void *ptr = dfmt - dfmt->idx;
+	struct data__file *d = container_of(ptr, struct data__file, fmt);
+
+	return get_pair_data(he, d);
+}
+
 static void hists__baseline_only(struct hists *hists)
 {
 	struct rb_root *root;
@@ -333,22 +428,24 @@ static void hists__precompute(struct hists *hists)
 
 	next = rb_first(root);
 	while (next != NULL) {
-		struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
-		struct hist_entry *pair = hist_entry__next_pair(he);
+		struct hist_entry *he, *pair;
 
+		he   = rb_entry(next, struct hist_entry, rb_node_in);
 		next = rb_next(&he->rb_node_in);
+
+		pair = get_pair_data(he, &data__files[sort_compute]);
 		if (!pair)
 			continue;
 
 		switch (compute) {
 		case COMPUTE_DELTA:
-			perf_diff__compute_delta(he, pair);
+			compute_delta(he, pair);
 			break;
 		case COMPUTE_RATIO:
-			perf_diff__compute_ratio(he, pair);
+			compute_ratio(he, pair);
 			break;
 		case COMPUTE_WEIGHTED_DIFF:
-			perf_diff__compute_wdiff(he, pair);
+			compute_wdiff(he, pair);
 			break;
 		default:
 			BUG_ON(1);
@@ -367,7 +464,7 @@ static int64_t cmp_doubles(double l, double r)
 }
 
 static int64_t
-hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
+__hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
 			int c)
 {
 	switch (c) {
@@ -399,6 +496,36 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
 	return 0;
 }
 
+static int64_t
+hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
+			int c)
+{
+	bool pairs_left  = hist_entry__has_pairs(left);
+	bool pairs_right = hist_entry__has_pairs(right);
+	struct hist_entry *p_right, *p_left;
+
+	if (!pairs_left && !pairs_right)
+		return 0;
+
+	if (!pairs_left || !pairs_right)
+		return pairs_left ? -1 : 1;
+
+	p_left  = get_pair_data(left,  &data__files[sort_compute]);
+	p_right = get_pair_data(right, &data__files[sort_compute]);
+
+	if (!p_left && !p_right)
+		return 0;
+
+	if (!p_left || !p_right)
+		return p_left ? -1 : 1;
+
+	/*
+	 * We have 2 entries of same kind, let's
+	 * make the data comparison.
+	 */
+	return __hist_entry__cmp_compute(p_left, p_right, c);
+}
+
 static void insert_hist_entry_by_compute(struct rb_root *root,
 					 struct hist_entry *he,
 					 int c)
@@ -448,75 +575,121 @@ static void hists__compute_resort(struct hists *hists)
 	}
 }
 
-static void hists__process(struct hists *old, struct hists *new)
+static void hists__process(struct hists *hists)
 {
-	hists__match(new, old);
-
 	if (show_baseline_only)
-		hists__baseline_only(new);
-	else
-		hists__link(new, old);
+		hists__baseline_only(hists);
 
 	if (sort_compute) {
-		hists__precompute(new);
-		hists__compute_resort(new);
+		hists__precompute(hists);
+		hists__compute_resort(hists);
 	} else {
-		hists__output_resort(new);
+		hists__output_resort(hists);
 	}
 
-	hists__fprintf(new, true, 0, 0, 0, stdout);
+	hists__fprintf(hists, true, 0, 0, 0, stdout);
 }
 
-static int __cmd_diff(void)
+static void data__fprintf(void)
 {
-	int ret, i;
-#define older (session[0])
-#define newer (session[1])
-	struct perf_session *session[2];
-	struct perf_evlist *evlist_new, *evlist_old;
-	struct perf_evsel *evsel;
+	struct data__file *d;
+	int i;
+
+	fprintf(stdout, "# Data files:\n");
+
+	data__for_each_file(i, d)
+		fprintf(stdout, "#  [%d] %s %s\n",
+			d->idx, d->file,
+			!d->idx ? "(Baseline)" : "");
+
+	fprintf(stdout, "#\n");
+}
+
+static void data_process(void)
+{
+	struct perf_evlist *evlist_base = data__files[0].session->evlist;
+	struct perf_evsel *evsel_base;
 	bool first = true;
 
-	older = perf_session__new(input_old, O_RDONLY, force, false,
-				  &tool);
-	newer = perf_session__new(input_new, O_RDONLY, force, false,
-				  &tool);
-	if (session[0] == NULL || session[1] == NULL)
-		return -ENOMEM;
+	list_for_each_entry(evsel_base, &evlist_base->entries, node) {
+		struct data__file *d;
+		int i;
 
-	for (i = 0; i < 2; ++i) {
-		ret = perf_session__process_events(session[i], &tool);
-		if (ret)
-			goto out_delete;
-	}
+		data__for_each_file_new(i, d) {
+			struct perf_evlist *evlist = d->session->evlist;
+			struct perf_evsel *evsel;
 
-	evlist_old = older->evlist;
-	evlist_new = newer->evlist;
+			evsel = evsel_match(evsel_base, evlist);
+			if (!evsel)
+				continue;
 
-	perf_evlist__collapse_resort(evlist_old);
-	perf_evlist__collapse_resort(evlist_new);
+			d->hists = &evsel->hists;
 
-	list_for_each_entry(evsel, &evlist_new->entries, node) {
-		struct perf_evsel *evsel_old;
+			hists__match(&evsel_base->hists, &evsel->hists);
 
-		evsel_old = evsel_match(evsel, evlist_old);
-		if (!evsel_old)
-			continue;
+			if (!show_baseline_only)
+				hists__link(&evsel_base->hists,
+					    &evsel->hists);
+		}
 
 		fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
-			perf_evsel__name(evsel));
+			perf_evsel__name(evsel_base));
 
 		first = false;
 
-		hists__process(&evsel_old->hists, &evsel->hists);
+		if (verbose || data__files_cnt > 2)
+			data__fprintf();
+
+		hists__process(&evsel_base->hists);
+	}
+}
+
+static void data__free(struct data__file *d)
+{
+	int col;
+
+	for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
+		struct diff_hpp_fmt *fmt = &d->fmt[col];
+
+		free(fmt->header);
 	}
+}
 
-out_delete:
-	for (i = 0; i < 2; ++i)
-		perf_session__delete(session[i]);
+static int __cmd_diff(void)
+{
+	struct data__file *d;
+	int ret = -EINVAL, i;
+
+	data__for_each_file(i, d) {
+		d->session = perf_session__new(d->file, O_RDONLY, force,
+					       false, &tool);
+		if (!d->session) {
+			pr_err("Failed to open %s\n", d->file);
+			ret = -ENOMEM;
+			goto out_delete;
+		}
+
+		ret = perf_session__process_events(d->session, &tool);
+		if (ret) {
+			pr_err("Failed to process %s\n", d->file);
+			goto out_delete;
+		}
+
+		perf_evlist__collapse_resort(d->session->evlist);
+	}
+
+	data_process();
+
+ out_delete:
+	data__for_each_file(i, d) {
+		if (d->session)
+			perf_session__delete(d->session);
+
+		data__free(d);
+	}
+
+	free(data__files);
 	return ret;
-#undef older
-#undef newer
 }
 
 static const char * const diff_usage[] = {
@@ -555,61 +728,310 @@ static const struct option options[] = {
 		   "columns '.' is reserved."),
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		    "Look for files with symbols relative to this directory"),
+	OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
 	OPT_END()
 };
 
-static void ui_init(void)
+static double baseline_percent(struct hist_entry *he)
 {
-	/*
-	 * Display baseline/delta/ratio
-	 * formula/periods columns.
-	 */
-	perf_hpp__column_enable(PERF_HPP__BASELINE);
+	struct hists *hists = he->hists;
+	return 100.0 * he->stat.period / hists->stats.total_period;
+}
 
-	switch (compute) {
-	case COMPUTE_DELTA:
-		perf_hpp__column_enable(PERF_HPP__DELTA);
+static int hpp__color_baseline(struct perf_hpp_fmt *fmt,
+			       struct perf_hpp *hpp, struct hist_entry *he)
+{
+	struct diff_hpp_fmt *dfmt =
+		container_of(fmt, struct diff_hpp_fmt, fmt);
+	double percent = baseline_percent(he);
+	char pfmt[20] = " ";
+
+	if (!he->dummy) {
+		scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1);
+		return percent_color_snprintf(hpp->buf, hpp->size,
+					      pfmt, percent);
+	} else
+		return scnprintf(hpp->buf, hpp->size, "%*s",
+				 dfmt->header_width, pfmt);
+}
+
+static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
+{
+	double percent = baseline_percent(he);
+	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
+	int ret = 0;
+
+	if (!he->dummy)
+		ret = scnprintf(buf, size, fmt, percent);
+
+	return ret;
+}
+
+static void
+hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
+{
+	switch (idx) {
+	case PERF_HPP_DIFF__PERIOD_BASELINE:
+		scnprintf(buf, size, "%" PRIu64, he->stat.period);
 		break;
-	case COMPUTE_RATIO:
-		perf_hpp__column_enable(PERF_HPP__RATIO);
+
+	default:
 		break;
-	case COMPUTE_WEIGHTED_DIFF:
-		perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF);
+	}
+}
+
+static void
+hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
+		int idx, char *buf, size_t size)
+{
+	double diff;
+	double ratio;
+	s64 wdiff;
+
+	switch (idx) {
+	case PERF_HPP_DIFF__DELTA:
+		if (pair->diff.computed)
+			diff = pair->diff.period_ratio_delta;
+		else
+			diff = compute_delta(he, pair);
+
+		if (fabs(diff) >= 0.01)
+			scnprintf(buf, size, "%+4.2F%%", diff);
+		break;
+
+	case PERF_HPP_DIFF__RATIO:
+		/* No point for ratio number if we are dummy.. */
+		if (he->dummy)
+			break;
+
+		if (pair->diff.computed)
+			ratio = pair->diff.period_ratio;
+		else
+			ratio = compute_ratio(he, pair);
+
+		if (ratio > 0.0)
+			scnprintf(buf, size, "%14.6F", ratio);
+		break;
+
+	case PERF_HPP_DIFF__WEIGHTED_DIFF:
+		/* No point for wdiff number if we are dummy.. */
+		if (he->dummy)
+			break;
+
+		if (pair->diff.computed)
+			wdiff = pair->diff.wdiff;
+		else
+			wdiff = compute_wdiff(he, pair);
+
+		if (wdiff != 0)
+			scnprintf(buf, size, "%14ld", wdiff);
+		break;
+
+	case PERF_HPP_DIFF__FORMULA:
+		formula_fprintf(he, pair, buf, size);
+		break;
+
+	case PERF_HPP_DIFF__PERIOD:
+		scnprintf(buf, size, "%" PRIu64, pair->stat.period);
 		break;
+
 	default:
 		BUG_ON(1);
 	};
+}
+
+static void
+__hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt,
+		    char *buf, size_t size)
+{
+	struct hist_entry *pair = get_pair_fmt(he, dfmt);
+	int idx = dfmt->idx;
+
+	/* baseline is special */
+	if (idx == PERF_HPP_DIFF__BASELINE)
+		hpp__entry_baseline(he, buf, size);
+	else {
+		if (pair)
+			hpp__entry_pair(he, pair, idx, buf, size);
+		else
+			hpp__entry_unpair(he, idx, buf, size);
+	}
+}
+
+static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
+			     struct hist_entry *he)
+{
+	struct diff_hpp_fmt *dfmt =
+		container_of(_fmt, struct diff_hpp_fmt, fmt);
+	char buf[MAX_COL_WIDTH] = " ";
+
+	__hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH);
+
+	if (symbol_conf.field_sep)
+		return scnprintf(hpp->buf, hpp->size, "%s", buf);
+	else
+		return scnprintf(hpp->buf, hpp->size, "%*s",
+				 dfmt->header_width, buf);
+}
+
+static int hpp__header(struct perf_hpp_fmt *fmt,
+		       struct perf_hpp *hpp)
+{
+	struct diff_hpp_fmt *dfmt =
+		container_of(fmt, struct diff_hpp_fmt, fmt);
 
-	if (show_formula)
-		perf_hpp__column_enable(PERF_HPP__FORMULA);
+	BUG_ON(!dfmt->header);
+	return scnprintf(hpp->buf, hpp->size, dfmt->header);
+}
 
-	if (show_period) {
-		perf_hpp__column_enable(PERF_HPP__PERIOD);
-		perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE);
+static int hpp__width(struct perf_hpp_fmt *fmt,
+		      struct perf_hpp *hpp __maybe_unused)
+{
+	struct diff_hpp_fmt *dfmt =
+		container_of(fmt, struct diff_hpp_fmt, fmt);
+
+	BUG_ON(dfmt->header_width <= 0);
+	return dfmt->header_width;
+}
+
+static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt)
+{
+#define MAX_HEADER_NAME 100
+	char buf_indent[MAX_HEADER_NAME];
+	char buf[MAX_HEADER_NAME];
+	const char *header = NULL;
+	int width = 0;
+
+	BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX);
+	header = columns[dfmt->idx].name;
+	width  = columns[dfmt->idx].width;
+
+	/* Only our defined HPP fmts should appear here. */
+	BUG_ON(!header);
+
+	if (data__files_cnt > 2)
+		scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx);
+
+#define NAME (data__files_cnt > 2 ? buf : header)
+	dfmt->header_width = width;
+	width = (int) strlen(NAME);
+	if (dfmt->header_width < width)
+		dfmt->header_width = width;
+
+	scnprintf(buf_indent, MAX_HEADER_NAME, "%*s",
+		  dfmt->header_width, NAME);
+
+	dfmt->header = strdup(buf_indent);
+#undef MAX_HEADER_NAME
+#undef NAME
+}
+
+static void data__hpp_register(struct data__file *d, int idx)
+{
+	struct diff_hpp_fmt *dfmt = &d->fmt[idx];
+	struct perf_hpp_fmt *fmt = &dfmt->fmt;
+
+	dfmt->idx = idx;
+
+	fmt->header = hpp__header;
+	fmt->width  = hpp__width;
+	fmt->entry  = hpp__entry_global;
+
+	/* TODO more colors */
+	if (idx == PERF_HPP_DIFF__BASELINE)
+		fmt->color = hpp__color_baseline;
+
+	init_header(d, dfmt);
+	perf_hpp__column_register(fmt);
+}
+
+static void ui_init(void)
+{
+	struct data__file *d;
+	int i;
+
+	data__for_each_file(i, d) {
+
+		/*
+		 * Baseline or compute realted columns:
+		 *
+		 *   PERF_HPP_DIFF__BASELINE
+		 *   PERF_HPP_DIFF__DELTA
+		 *   PERF_HPP_DIFF__RATIO
+		 *   PERF_HPP_DIFF__WEIGHTED_DIFF
+		 */
+		data__hpp_register(d, i ? compute_2_hpp[compute] :
+					  PERF_HPP_DIFF__BASELINE);
+
+		/*
+		 * And the rest:
+		 *
+		 * PERF_HPP_DIFF__FORMULA
+		 * PERF_HPP_DIFF__PERIOD
+		 * PERF_HPP_DIFF__PERIOD_BASELINE
+		 */
+		if (show_formula && i)
+			data__hpp_register(d, PERF_HPP_DIFF__FORMULA);
+
+		if (show_period)
+			data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD :
+						  PERF_HPP_DIFF__PERIOD_BASELINE);
 	}
 }
 
-int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
+static int data_init(int argc, const char **argv)
 {
-	sort_order = diff__default_sort_order;
-	argc = parse_options(argc, argv, options, diff_usage, 0);
+	struct data__file *d;
+	static const char *defaults[] = {
+		"perf.data.old",
+		"perf.data",
+	};
+	bool use_default = true;
+	int i;
+
+	data__files_cnt = 2;
+
 	if (argc) {
-		if (argc > 2)
-			usage_with_options(diff_usage, options);
-		if (argc == 2) {
-			input_old = argv[0];
-			input_new = argv[1];
-		} else
-			input_new = argv[0];
+		if (argc == 1)
+			defaults[1] = argv[0];
+		else {
+			data__files_cnt = argc;
+			use_default = false;
+		}
 	} else if (symbol_conf.default_guest_vmlinux_name ||
 		   symbol_conf.default_guest_kallsyms) {
-		input_old = "perf.data.host";
-		input_new = "perf.data.guest";
+		defaults[0] = "perf.data.host";
+		defaults[1] = "perf.data.guest";
 	}
 
+	if (sort_compute >= (unsigned int) data__files_cnt) {
+		pr_err("Order option out of limit.\n");
+		return -EINVAL;
+	}
+
+	data__files = zalloc(sizeof(*data__files) * data__files_cnt);
+	if (!data__files)
+		return -ENOMEM;
+
+	data__for_each_file(i, d) {
+		d->file = use_default ? defaults[i] : argv[i];
+		d->idx  = i;
+	}
+
+	return 0;
+}
+
+int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+	sort_order = diff__default_sort_order;
+	argc = parse_options(argc, argv, options, diff_usage, 0);
+
 	if (symbol__init() < 0)
 		return -1;
 
+	if (data_init(argc, argv) < 0)
+		return -1;
+
 	ui_init();
 
 	if (setup_sorting() < 0)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 84ad6ab..1d8de2e 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -38,8 +38,7 @@ struct event_entry {
 };
 
 static int perf_event__repipe_synth(struct perf_tool *tool,
-				    union perf_event *event,
-				    struct machine *machine __maybe_unused)
+				    union perf_event *event)
 {
 	struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
 	uint32_t size;
@@ -65,39 +64,28 @@ static int perf_event__repipe_op2_synth(struct perf_tool *tool,
 					struct perf_session *session
 					__maybe_unused)
 {
-	return perf_event__repipe_synth(tool, event, NULL);
+	return perf_event__repipe_synth(tool, event);
 }
 
-static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
-					       union perf_event *event)
-{
-	return perf_event__repipe_synth(tool, event, NULL);
-}
-
-static int perf_event__repipe_tracing_data_synth(union perf_event *event,
-						 struct perf_session *session
-						 __maybe_unused)
-{
-	return perf_event__repipe_synth(NULL, event, NULL);
-}
-
-static int perf_event__repipe_attr(union perf_event *event,
-				   struct perf_evlist **pevlist __maybe_unused)
+static int perf_event__repipe_attr(struct perf_tool *tool,
+				   union perf_event *event,
+				   struct perf_evlist **pevlist)
 {
 	int ret;
-	ret = perf_event__process_attr(event, pevlist);
+
+	ret = perf_event__process_attr(tool, event, pevlist);
 	if (ret)
 		return ret;
 
-	return perf_event__repipe_synth(NULL, event, NULL);
+	return perf_event__repipe_synth(tool, event);
 }
 
 static int perf_event__repipe(struct perf_tool *tool,
 			      union perf_event *event,
 			      struct perf_sample *sample __maybe_unused,
-			      struct machine *machine)
+			      struct machine *machine __maybe_unused)
 {
-	return perf_event__repipe_synth(tool, event, machine);
+	return perf_event__repipe_synth(tool, event);
 }
 
 typedef int (*inject_handler)(struct perf_tool *tool,
@@ -119,7 +107,7 @@ static int perf_event__repipe_sample(struct perf_tool *tool,
 
 	build_id__mark_dso_hit(tool, event, sample, evsel, machine);
 
-	return perf_event__repipe_synth(tool, event, machine);
+	return perf_event__repipe_synth(tool, event);
 }
 
 static int perf_event__repipe_mmap(struct perf_tool *tool,
@@ -148,13 +136,14 @@ static int perf_event__repipe_fork(struct perf_tool *tool,
 	return err;
 }
 
-static int perf_event__repipe_tracing_data(union perf_event *event,
+static int perf_event__repipe_tracing_data(struct perf_tool *tool,
+					   union perf_event *event,
 					   struct perf_session *session)
 {
 	int err;
 
-	perf_event__repipe_synth(NULL, event, NULL);
-	err = perf_event__process_tracing_data(event, session);
+	perf_event__repipe_synth(tool, event);
+	err = perf_event__process_tracing_data(tool, event, session);
 
 	return err;
 }
@@ -407,8 +396,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 			.throttle	= perf_event__repipe,
 			.unthrottle	= perf_event__repipe,
 			.attr		= perf_event__repipe_attr,
-			.event_type	= perf_event__repipe_event_type_synth,
-			.tracing_data	= perf_event__repipe_tracing_data_synth,
+			.tracing_data	= perf_event__repipe_op2_synth,
+			.finished_round	= perf_event__repipe_op2_synth,
 			.build_id	= perf_event__repipe_op2_synth,
 		},
 		.input_name  = "-",
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 0259502..b49f5c5 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -313,7 +313,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 		return -1;
 	}
 
-	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
+	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid);
 
 	if (evsel->handler.func != NULL) {
 		tracepoint_handler f = evsel->handler.func;
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 1948ece..e79f423 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -13,6 +13,7 @@
 
 #include "util/parse-events.h"
 #include "util/cache.h"
+#include "util/pmu.h"
 
 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
@@ -37,6 +38,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 			else if (strcmp(argv[i], "cache") == 0 ||
 				 strcmp(argv[i], "hwcache") == 0)
 				print_hwcache_events(NULL, false);
+			else if (strcmp(argv[i], "pmu") == 0)
+				print_pmu_events(NULL, false);
 			else if (strcmp(argv[i], "--raw-dump") == 0)
 				print_events(NULL, true);
 			else {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ecca62e..a41ac415 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -474,13 +474,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 			goto out_delete_session;
 		}
 
-		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
-							 machine);
-		if (err < 0) {
-			pr_err("Couldn't synthesize event_types.\n");
-			goto out_delete_session;
-		}
-
 		if (have_tracepoints(&evsel_list->entries)) {
 			/*
 			 * FIXME err <= 0 here actually means that
@@ -904,7 +897,6 @@ const struct option record_options[] = {
 int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	int err = -ENOMEM;
-	struct perf_evsel *pos;
 	struct perf_evlist *evsel_list;
 	struct perf_record *rec = &record;
 	char errbuf[BUFSIZ];
@@ -968,11 +960,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
 		usage_with_options(record_usage, record_options);
 
-	list_for_each_entry(pos, &evsel_list->entries, node) {
-		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
-			goto out_free_fd;
-	}
-
 	if (rec->opts.user_interval != ULLONG_MAX)
 		rec->opts.default_interval = rec->opts.user_interval;
 	if (rec->opts.user_freq != UINT_MAX)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3662047..d785d89 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -89,7 +89,7 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
 	if ((sort__has_parent || symbol_conf.use_callchain) &&
 	    sample->callchain) {
 		err = machine__resolve_callchain(machine, evsel, al->thread,
-						 sample, &parent);
+						 sample, &parent, al);
 		if (err)
 			return err;
 	}
@@ -180,7 +180,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
 	if ((sort__has_parent || symbol_conf.use_callchain)
 	    && sample->callchain) {
 		err = machine__resolve_callchain(machine, evsel, al->thread,
-						 sample, &parent);
+						 sample, &parent, al);
 		if (err)
 			return err;
 	}
@@ -254,7 +254,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
 
 	if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
 		err = machine__resolve_callchain(machine, evsel, al->thread,
-						 sample, &parent);
+						 sample, &parent, al);
 		if (err)
 			return err;
 	}
@@ -497,7 +497,7 @@ static int __cmd_report(struct perf_report *rep)
 		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
 					       rep->cpu_bitmap);
 		if (ret)
-			goto out_delete;
+			return ret;
 	}
 
 	if (use_browser <= 0)
@@ -508,11 +508,11 @@ static int __cmd_report(struct perf_report *rep)
 
 	ret = perf_report__setup_sample_type(rep);
 	if (ret)
-		goto out_delete;
+		return ret;
 
 	ret = perf_session__process_events(session, &rep->tool);
 	if (ret)
-		goto out_delete;
+		return ret;
 
 	kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION];
 	kernel_kmap = map__kmap(kernel_map);
@@ -547,7 +547,7 @@ static int __cmd_report(struct perf_report *rep)
 
 	if (dump_trace) {
 		perf_session__fprintf_nr_events(session, stdout);
-		goto out_delete;
+		return 0;
 	}
 
 	nr_samples = 0;
@@ -572,7 +572,7 @@ static int __cmd_report(struct perf_report *rep)
 
 	if (nr_samples == 0) {
 		ui__error("The %s file has no samples!\n", session->filename);
-		goto out_delete;
+		return 0;
 	}
 
 	list_for_each_entry(pos, &session->evlist->entries, node)
@@ -598,19 +598,6 @@ static int __cmd_report(struct perf_report *rep)
 	} else
 		perf_evlist__tty_browse_hists(session->evlist, rep, help);
 
-out_delete:
-	/*
-	 * Speed up the exit process, for large files this can
-	 * take quite a while.
-	 *
-	 * XXX Enable this when using valgrind or if we ever
-	 * librarize this command.
-	 *
-	 * Also experiment with obstacks to see how much speed
-	 * up we'll get here.
-	 *
- 	 * perf_session__delete(session);
- 	 */
 	return ret;
 }
 
@@ -680,12 +667,23 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 	}
 
 	/* get the call chain order */
-	if (!strcmp(tok2, "caller"))
+	if (!strncmp(tok2, "caller", strlen("caller")))
 		callchain_param.order = ORDER_CALLER;
-	else if (!strcmp(tok2, "callee"))
+	else if (!strncmp(tok2, "callee", strlen("callee")))
 		callchain_param.order = ORDER_CALLEE;
 	else
 		return -1;
+
+	/* Get the sort key */
+	tok2 = strtok(NULL, ",");
+	if (!tok2)
+		goto setup;
+	if (!strncmp(tok2, "function", strlen("function")))
+		callchain_param.key = CCKEY_FUNCTION;
+	else if (!strncmp(tok2, "address", strlen("address")))
+		callchain_param.key = CCKEY_ADDRESS;
+	else
+		return -1;
 setup:
 	if (callchain_register_param(&callchain_param) < 0) {
 		fprintf(stderr, "Can't register callchain params\n");
@@ -694,6 +692,24 @@ setup:
 	return 0;
 }
 
+int
+report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
+				const char *arg, int unset __maybe_unused)
+{
+	if (arg) {
+		int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
+		if (err) {
+			char buf[BUFSIZ];
+			regerror(err, &ignore_callees_regex, buf, sizeof(buf));
+			pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
+			return -1;
+		}
+		have_ignore_callees = 1;
+	}
+
+	return 0;
+}
+
 static int
 parse_branch_mode(const struct option *opt __maybe_unused,
 		  const char *str __maybe_unused, int unset)
@@ -736,7 +752,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 			.lost		 = perf_event__process_lost,
 			.read		 = process_read_event,
 			.attr		 = perf_event__process_attr,
-			.event_type	 = perf_event__process_event_type,
 			.tracing_data	 = perf_event__process_tracing_data,
 			.build_id	 = perf_event__process_build_id,
 			.ordered_samples = true,
@@ -780,10 +795,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
 		    "Only display entries with parent-match"),
 	OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
-		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit and callchain order. "
-		     "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
+		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
+		     "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
 	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
 		    "alias for inverted call graph"),
+	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
+		   "ignore callees of these functions in call graphs",
+		   report_parse_ignore_callees_opt),
 	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
 		   "only consider symbols in these dsos"),
 	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -853,7 +871,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		setup_browser(true);
 	else {
 		use_browser = 0;
-		perf_hpp__column_enable(PERF_HPP__OVERHEAD);
 		perf_hpp__init();
 	}
 
@@ -931,14 +948,6 @@ repeat:
 	if (parent_pattern != default_parent_pattern) {
 		if (sort_dimension__add("parent") < 0)
 			goto error;
-
-		/*
-		 * Only show the parent fields if we explicitly
-		 * sort that way. If we only use parent machinery
-		 * for filtering, we don't want it.
-		 */
-		if (!strstr(sort_order, "parent"))
-			sort_parent.elide = 1;
 	}
 
 	if (argc) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index fed9ae4..948183a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1075,7 +1075,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,
 	if (!atoms) {
 		if (thread_atoms_insert(sched, migrant))
 			return -1;
-		register_pid(sched, migrant->pid, migrant->comm);
+		register_pid(sched, migrant->tid, migrant->comm);
 		atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
 		if (!atoms) {
 			pr_err("migration-event: Internal tree error");
@@ -1115,7 +1115,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
 	sched->all_runtime += work_list->total_runtime;
 	sched->all_count   += work_list->nb_atoms;
 
-	ret = printf("  %s:%d ", work_list->thread->comm, work_list->thread->pid);
+	ret = printf("  %s:%d ", work_list->thread->comm, work_list->thread->tid);
 
 	for (i = 0; i < 24 - ret; i++)
 		printf(" ");
@@ -1131,9 +1131,9 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
 
 static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
 {
-	if (l->thread->pid < r->thread->pid)
+	if (l->thread->tid < r->thread->tid)
 		return -1;
-	if (l->thread->pid > r->thread->pid)
+	if (l->thread->tid > r->thread->tid)
 		return 1;
 
 	return 0;
@@ -1321,7 +1321,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
 			printf("*");
 
 		if (sched->curr_thread[cpu]) {
-			if (sched->curr_thread[cpu]->pid)
+			if (sched->curr_thread[cpu]->tid)
 				printf("%2s ", sched->curr_thread[cpu]->shortname);
 			else
 				printf(".  ");
@@ -1332,7 +1332,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
 	printf("  %12.6f secs ", (double)timestamp/1e9);
 	if (new_shortname) {
 		printf("%s => %s:%d\n",
-			sched_in->shortname, sched_in->comm, sched_in->pid);
+			sched_in->shortname, sched_in->comm, sched_in->tid);
 	} else {
 		printf("\n");
 	}
@@ -1662,28 +1662,29 @@ static int __cmd_record(int argc, const char **argv)
 	return cmd_record(i, rec_argv, NULL);
 }
 
+static const char default_sort_order[] = "avg, max, switch, runtime";
+static struct perf_sched sched = {
+	.tool = {
+		.sample		 = perf_sched__process_tracepoint_sample,
+		.comm		 = perf_event__process_comm,
+		.lost		 = perf_event__process_lost,
+		.fork		 = perf_event__process_fork,
+		.ordered_samples = true,
+	},
+	.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
+	.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
+	.start_work_mutex     = PTHREAD_MUTEX_INITIALIZER,
+	.work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
+	.curr_pid	      = { [0 ... MAX_CPUS - 1] = -1 },
+	.sort_order	      = default_sort_order,
+	.replay_repeat	      = 10,
+	.profile_cpu	      = -1,
+	.next_shortname1      = 'A',
+	.next_shortname2      = '0',
+};
+
 int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-	const char default_sort_order[] = "avg, max, switch, runtime";
-	struct perf_sched sched = {
-		.tool = {
-			.sample		 = perf_sched__process_tracepoint_sample,
-			.comm		 = perf_event__process_comm,
-			.lost		 = perf_event__process_lost,
-			.fork		 = perf_event__process_fork,
-			.ordered_samples = true,
-		},
-		.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
-		.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
-		.start_work_mutex     = PTHREAD_MUTEX_INITIALIZER,
-		.work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
-		.curr_pid	      = { [0 ... MAX_CPUS - 1] = -1 },
-		.sort_order	      = default_sort_order,
-		.replay_repeat	      = 10,
-		.profile_cpu	      = -1,
-		.next_shortname1      = 'A',
-		.next_shortname2      = '0',
-	};
 	const struct option latency_options[] = {
 	OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
 		   "sort by key(s): runtime, switch, avg, max"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 92d4658..1cad370 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -24,6 +24,7 @@ static u64			last_timestamp;
 static u64			nr_unordered;
 extern const struct option	record_options[];
 static bool			no_callchain;
+static bool			latency_format;
 static bool			system_wide;
 static const char		*cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -396,10 +397,10 @@ static void print_sample_bts(union perf_event *event,
 
 static void process_event(union perf_event *event, struct perf_sample *sample,
 			  struct perf_evsel *evsel, struct machine *machine,
-			  struct addr_location *al)
+			  struct thread *thread,
+			  struct addr_location *al __maybe_unused)
 {
 	struct perf_event_attr *attr = &evsel->attr;
-	struct thread *thread = al->thread;
 
 	if (output[attr->type].fields == 0)
 		return;
@@ -510,7 +511,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
 		return 0;
 
-	scripting_ops->process_event(event, sample, evsel, machine, &al);
+	scripting_ops->process_event(event, sample, evsel, machine, thread, &al);
 
 	evsel->hists.stats.total_period += sample->period;
 	return 0;
@@ -523,7 +524,6 @@ static struct perf_tool perf_script = {
 	.exit		 = perf_event__process_exit,
 	.fork		 = perf_event__process_fork,
 	.attr		 = perf_event__process_attr,
-	.event_type	 = perf_event__process_event_type,
 	.tracing_data	 = perf_event__process_tracing_data,
 	.build_id	 = perf_event__process_build_id,
 	.ordered_samples = true,
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 4536a92..c2e0231 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -12,6 +12,8 @@
  * of the License.
  */
 
+#include <traceevent/event-parse.h>
+
 #include "builtin.h"
 
 #include "util/util.h"
@@ -19,6 +21,7 @@
 #include "util/color.h"
 #include <linux/list.h>
 #include "util/cache.h"
+#include "util/evlist.h"
 #include "util/evsel.h"
 #include <linux/rbtree.h>
 #include "util/symbol.h"
@@ -328,25 +331,6 @@ struct wakeup_entry {
 	int   success;
 };
 
-/*
- * trace_flag_type is an enumeration that holds different
- * states when a trace occurs. These are:
- *  IRQS_OFF            - interrupts were disabled
- *  IRQS_NOSUPPORT      - arch does not support irqs_disabled_flags
- *  NEED_RESCED         - reschedule is requested
- *  HARDIRQ             - inside an interrupt handler
- *  SOFTIRQ             - inside a softirq handler
- */
-enum trace_flag_type {
-	TRACE_FLAG_IRQS_OFF		= 0x01,
-	TRACE_FLAG_IRQS_NOSUPPORT	= 0x02,
-	TRACE_FLAG_NEED_RESCHED		= 0x04,
-	TRACE_FLAG_HARDIRQ		= 0x08,
-	TRACE_FLAG_SOFTIRQ		= 0x10,
-};
-
-
-
 struct sched_switch {
 	struct trace_entry te;
 	char prev_comm[TASK_COMM_LEN];
@@ -479,6 +463,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
 	}
 }
 
+typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
+				  struct perf_sample *sample);
 
 static int process_sample_event(struct perf_tool *tool __maybe_unused,
 				union perf_event *event __maybe_unused,
@@ -486,8 +472,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 				struct perf_evsel *evsel,
 				struct machine *machine __maybe_unused)
 {
-	struct trace_entry *te;
-
 	if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
 		if (!first_time || first_time > sample->time)
 			first_time = sample->time;
@@ -495,69 +479,90 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 			last_time = sample->time;
 	}
 
-	te = (void *)sample->raw_data;
-	if ((evsel->attr.sample_type & PERF_SAMPLE_RAW) && sample->raw_size > 0) {
-		char *event_str;
-#ifdef SUPPORT_OLD_POWER_EVENTS
-		struct power_entry_old *peo;
-		peo = (void *)te;
-#endif
-		/*
-		 * FIXME: use evsel, its already mapped from id to perf_evsel,
-		 * remove perf_header__find_event infrastructure bits.
-		 * Mapping all these "power:cpu_idle" strings to the tracepoint
-		 * ID and then just comparing against evsel->attr.config.
-		 *
-		 * e.g.:
-		 *
-		 * if (evsel->attr.config == power_cpu_idle_id)
-		 */
-		event_str = perf_header__find_event(te->type);
-
-		if (!event_str)
-			return 0;
-
-		if (sample->cpu > numcpus)
-			numcpus = sample->cpu;
-
-		if (strcmp(event_str, "power:cpu_idle") == 0) {
-			struct power_processor_entry *ppe = (void *)te;
-			if (ppe->state == (u32)PWR_EVENT_EXIT)
-				c_state_end(ppe->cpu_id, sample->time);
-			else
-				c_state_start(ppe->cpu_id, sample->time,
-					      ppe->state);
-		}
-		else if (strcmp(event_str, "power:cpu_frequency") == 0) {
-			struct power_processor_entry *ppe = (void *)te;
-			p_state_change(ppe->cpu_id, sample->time, ppe->state);
-		}
+	if (sample->cpu > numcpus)
+		numcpus = sample->cpu;
+
+	if (evsel->handler.func != NULL) {
+		tracepoint_handler f = evsel->handler.func;
+		return f(evsel, sample);
+	}
+
+	return 0;
+}
+
+static int
+process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused,
+			struct perf_sample *sample)
+{
+	struct power_processor_entry *ppe = sample->raw_data;
+
+	if (ppe->state == (u32) PWR_EVENT_EXIT)
+		c_state_end(ppe->cpu_id, sample->time);
+	else
+		c_state_start(ppe->cpu_id, sample->time, ppe->state);
+	return 0;
+}
+
+static int
+process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused,
+			     struct perf_sample *sample)
+{
+	struct power_processor_entry *ppe = sample->raw_data;
+
+	p_state_change(ppe->cpu_id, sample->time, ppe->state);
+	return 0;
+}
+
+static int
+process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused,
+			    struct perf_sample *sample)
+{
+	struct trace_entry *te = sample->raw_data;
+
+	sched_wakeup(sample->cpu, sample->time, sample->pid, te);
+	return 0;
+}
 
-		else if (strcmp(event_str, "sched:sched_wakeup") == 0)
-			sched_wakeup(sample->cpu, sample->time, sample->pid, te);
+static int
+process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused,
+			    struct perf_sample *sample)
+{
+	struct trace_entry *te = sample->raw_data;
 
-		else if (strcmp(event_str, "sched:sched_switch") == 0)
-			sched_switch(sample->cpu, sample->time, te);
+	sched_switch(sample->cpu, sample->time, te);
+	return 0;
+}
 
 #ifdef SUPPORT_OLD_POWER_EVENTS
-		if (use_old_power_events) {
-			if (strcmp(event_str, "power:power_start") == 0)
-				c_state_start(peo->cpu_id, sample->time,
-					      peo->value);
-
-			else if (strcmp(event_str, "power:power_end") == 0)
-				c_state_end(sample->cpu, sample->time);
-
-			else if (strcmp(event_str,
-					"power:power_frequency") == 0)
-				p_state_change(peo->cpu_id, sample->time,
-					       peo->value);
-		}
-#endif
-	}
+static int
+process_sample_power_start(struct perf_evsel *evsel __maybe_unused,
+			   struct perf_sample *sample)
+{
+	struct power_entry_old *peo = sample->raw_data;
+
+	c_state_start(peo->cpu_id, sample->time, peo->value);
 	return 0;
 }
 
+static int
+process_sample_power_end(struct perf_evsel *evsel __maybe_unused,
+			 struct perf_sample *sample)
+{
+	c_state_end(sample->cpu, sample->time);
+	return 0;
+}
+
+static int
+process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused,
+			       struct perf_sample *sample)
+{
+	struct power_entry_old *peo = sample->raw_data;
+
+	p_state_change(peo->cpu_id, sample->time, peo->value);
+	return 0;
+}
+#endif /* SUPPORT_OLD_POWER_EVENTS */
+
 /*
  * After the last sample we need to wrap up the current C/P state
  * and close out each CPU for these.
@@ -974,6 +979,17 @@ static int __cmd_timechart(const char *output_name)
 		.sample		 = process_sample_event,
 		.ordered_samples = true,
 	};
+	const struct perf_evsel_str_handler power_tracepoints[] = {
+		{ "power:cpu_idle",		process_sample_cpu_idle },
+		{ "power:cpu_frequency",	process_sample_cpu_frequency },
+		{ "sched:sched_wakeup",		process_sample_sched_wakeup },
+		{ "sched:sched_switch",		process_sample_sched_switch },
+#ifdef SUPPORT_OLD_POWER_EVENTS
+		{ "power:power_start",		process_sample_power_start },
+		{ "power:power_end",		process_sample_power_end },
+		{ "power:power_frequency",	process_sample_power_frequency },
+#endif
+	};
 	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
 							 0, false, &perf_timechart);
 	int ret = -EINVAL;
@@ -984,6 +1000,12 @@ static int __cmd_timechart(const char *output_name)
 	if (!perf_session__has_traces(session, "timechart record"))
 		goto out_delete;
 
+	if (perf_session__set_tracepoints_handlers(session,
+						   power_tracepoints)) {
+		pr_err("Initializing session tracepoint handlers failed\n");
+		goto out_delete;
+	}
+
 	ret = perf_session__process_events(session, &perf_timechart);
 	if (ret)
 		goto out_delete;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e06c4f8..bbf4635 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -40,6 +40,7 @@
 #include "util/xyarray.h"
 #include "util/sort.h"
 #include "util/intlist.h"
+#include "arch/common.h"
 
 #include "util/debug.h"
 
@@ -772,8 +773,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 		    sample->callchain) {
 			err = machine__resolve_callchain(machine, evsel,
 							 al.thread, sample,
-							 &parent);
-
+							 &parent, &al);
 			if (err)
 				return;
 		}
@@ -939,6 +939,12 @@ static int __cmd_top(struct perf_top *top)
 	if (top->session == NULL)
 		return -ENOMEM;
 
+	if (!objdump_path) {
+		ret = perf_session_env__lookup_objdump(&top->session->header.env);
+		if (ret)
+			goto out_delete;
+	}
+
 	ret = perf_top__setup_sample_type(top);
 	if (ret)
 		goto out_delete;
@@ -1102,6 +1108,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
 			     "mode[,dump_size]", record_callchain_help,
 			     &parse_callchain_opt, "fp"),
+	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
+		   "ignore callees of these functions in call graphs",
+		   report_parse_ignore_callees_opt),
 	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
 		    "Show a column with the sum of periods"),
 	OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -1114,6 +1123,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "Interleave source code with assembly code (default)"),
 	OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
 		    "Display raw encoding of assembly instructions (default)"),
+	OPT_STRING(0, "objdump", &objdump_path, "path",
+		    "objdump binary to use for disassembly and annotations"),
 	OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
 		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
 	OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index ab3ed4a..0e4b67f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1,3 +1,4 @@
+#include <traceevent/event-parse.h>
 #include "builtin.h"
 #include "util/color.h"
 #include "util/evlist.h"
@@ -5,7 +6,6 @@
 #include "util/thread.h"
 #include "util/parse-options.h"
 #include "util/thread_map.h"
-#include "event-parse.h"
 
 #include <libaudit.h>
 #include <stdlib.h>
@@ -142,7 +142,7 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
 	printed += fprintf_duration(duration, fp);
 
 	if (trace->multiple_threads)
-		printed += fprintf(fp, "%d ", thread->pid);
+		printed += fprintf(fp, "%d ", thread->tid);
 
 	return printed;
 }
@@ -593,7 +593,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
 			color = PERF_COLOR_YELLOW;
 
 		printed += color_fprintf(fp, color, "%20s", thread->comm);
-		printed += fprintf(fp, " - %-5d :%11lu   [", thread->pid, ttrace->nr_events);
+		printed += fprintf(fp, " - %-5d :%11lu   [", thread->tid, ttrace->nr_events);
 		printed += color_fprintf(fp, color, "%5.1f%%", ratio);
 		printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
 	}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index b5d9238..214e17e 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -46,6 +46,8 @@ ifneq ($(obj-perf),)
 obj-perf := $(abspath $(obj-perf))/
 endif
 
+LIB_INCLUDE := $(srctree)/tools/lib/
+
 # include ARCH specific config
 -include $(src-perf)/arch/$(ARCH)/Makefile
 
@@ -121,8 +123,7 @@ endif
 
 CFLAGS += -I$(src-perf)/util
 CFLAGS += -I$(src-perf)
-CFLAGS += -I$(TRACE_EVENT_DIR)
-CFLAGS += -I$(srctree)/tools/lib/
+CFLAGS += -I$(LIB_INCLUDE)
 
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 35b45f1466..b7b4049 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -93,6 +93,12 @@ static struct test {
 		.desc = "Test software clock events have valid period values",
 		.func = test__sw_clock_freq,
 	},
+#if defined(__x86_64__) || defined(__i386__)
+	{
+		.desc = "Test converting perf time to TSC",
+		.func = test__perf_time_to_tsc,
+	},
+#endif
 	{
 		.func = NULL,
 	},
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 5eaffa2..dffe055 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -10,14 +10,6 @@
 #include "symbol.h"
 #include "tests.h"
 
-#define TEST_ASSERT_VAL(text, cond) \
-do { \
-	if (!(cond)) { \
-		pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
-		return -1; \
-	} \
-} while (0)
-
 static char *test_file(int size)
 {
 	static char buf_templ[] = "/tmp/test-XXXXXX";
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index a5d2fcc..9b98c15 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -1,6 +1,6 @@
+#include <traceevent/event-parse.h>
 #include "evsel.h"
 #include "tests.h"
-#include "event-parse.h"
 
 static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
 				  int size, bool should_be_signed)
@@ -49,7 +49,7 @@ int test__perf_evsel__tp_sched_test(void)
 	if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
 		ret = -1;
 
-	if (perf_evsel__test_field(evsel, "prev_state", 8, true))
+	if (perf_evsel__test_field(evsel, "prev_state", sizeof(long), true))
 		ret = -1;
 
 	if (perf_evsel__test_field(evsel, "next_comm", 16, true))
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index c441a28..2ca0abf 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -1,6 +1,8 @@
 PERF := .
 MK   := Makefile
 
+has = $(shell which $1 2>/dev/null)
+
 # standard single make variable specified
 make_clean_all      := clean all
 make_python_perf_so := python/perf.so
@@ -25,6 +27,13 @@ make_help           := help
 make_doc            := doc
 make_perf_o         := perf.o
 make_util_map_o     := util/map.o
+make_install        := install
+make_install_bin    := install-bin
+make_install_doc    := install-doc
+make_install_man    := install-man
+make_install_html   := install-html
+make_install_info   := install-info
+make_install_pdf    := install-pdf
 
 # all the NO_* variable combined
 make_minimal        := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
@@ -50,14 +59,27 @@ run += make_no_backtrace
 run += make_no_libnuma
 run += make_no_libaudit
 run += make_no_libbionic
-run += make_tags
-run += make_cscope
 run += make_help
 run += make_doc
 run += make_perf_o
 run += make_util_map_o
+run += make_install
+run += make_install_bin
+# FIXME 'install-*' commented out till they're fixed
+# run += make_install_doc
+# run += make_install_man
+# run += make_install_html
+# run += make_install_info
+# run += make_install_pdf
 run += make_minimal
 
+ifneq ($(call has,ctags),)
+run += make_tags
+endif
+ifneq ($(call has,cscope),)
+run += make_cscope
+endif
+
 # $(run_O) contains same portion of $(run) tests with '_O' attached
 # to distinguish O=... tests
 run_O := $(addsuffix _O,$(run))
@@ -84,6 +106,31 @@ test_make_python_perf_so := test -f $(PERF)/python/perf.so
 test_make_perf_o     := test -f $(PERF)/perf.o
 test_make_util_map_o := test -f $(PERF)/util/map.o
 
+test_make_install       := test -x $$TMP_DEST/bin/perf
+test_make_install_O     := $(test_make_install)
+test_make_install_bin   := $(test_make_install)
+test_make_install_bin_O := $(test_make_install)
+
+# FIXME nothing gets installed
+test_make_install_man    := test -f $$TMP_DEST/share/man/man1/perf.1
+test_make_install_man_O  := $(test_make_install_man)
+
+# FIXME nothing gets installed
+test_make_install_doc    := $(test_ok)
+test_make_install_doc_O  := $(test_ok)
+
+# FIXME nothing gets installed
+test_make_install_html   := $(test_ok)
+test_make_install_html_O := $(test_ok)
+
+# FIXME nothing gets installed
+test_make_install_info   := $(test_ok)
+test_make_install_info_O := $(test_ok)
+
+# FIXME nothing gets installed
+test_make_install_pdf    := $(test_ok)
+test_make_install_pdf_O  := $(test_ok)
+
 # Kbuild tests only
 #test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so
 #test_make_perf_o_O         := test -f $$TMP/tools/perf/perf.o
@@ -95,7 +142,7 @@ test_make_util_map_o_O := true
 test_default = test -x $(PERF)/perf
 test = $(if $(test_$1),$(test_$1),$(test_default))
 
-test_default_O = test -x $$TMP/perf
+test_default_O = test -x $$TMP_O/perf
 test_O = $(if $(test_$1),$(test_$1),$(test_default_O))
 
 all:
@@ -111,23 +158,27 @@ clean := @(cd $(PERF); make -s -f $(MK) clean >/dev/null)
 
 $(run):
 	$(call clean)
-	@cmd="cd $(PERF) && make -f $(MK) $($@)"; \
+	@TMP_DEST=$$(mktemp -d); \
+	cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \
 	echo "- $@: $$cmd" && echo $$cmd > $@ && \
 	( eval $$cmd ) >> $@ 2>&1; \
 	echo "  test: $(call test,$@)"; \
 	$(call test,$@) && \
-	rm -f $@
+	rm -f $@ \
+	rm -rf $$TMP_DEST
 
 $(run_O):
 	$(call clean)
-	@TMP=$$(mktemp -d); \
-	cmd="cd $(PERF) && make -f $(MK) $($(patsubst %_O,%,$@)) O=$$TMP"; \
+	@TMP_O=$$(mktemp -d); \
+	TMP_DEST=$$(mktemp -d); \
+	cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \
 	echo "- $@: $$cmd" && echo $$cmd > $@ && \
 	( eval $$cmd ) >> $@ 2>&1 && \
 	echo "  test: $(call test_O,$@)"; \
 	$(call test_O,$@) && \
 	rm -f $@ && \
-	rm -rf $$TMP
+	rm -rf $$TMP_O \
+	rm -rf $$TMP_DEST
 
 all: $(run) $(run_O)
 	@echo OK
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 0275bab..344c844 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -7,14 +7,6 @@
 #include "tests.h"
 #include <linux/hw_breakpoint.h>
 
-#define TEST_ASSERT_VAL(text, cond) \
-do { \
-	if (!(cond)) { \
-		pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
-		return -1; \
-	} \
-} while (0)
-
 #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
 			     PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
 
@@ -1254,24 +1246,20 @@ static int test_events(struct evlist_test *events, unsigned cnt)
 
 static int test_term(struct terms_test *t)
 {
-	struct list_head *terms;
+	struct list_head terms;
 	int ret;
 
-	terms = malloc(sizeof(*terms));
-	if (!terms)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(terms);
+	INIT_LIST_HEAD(&terms);
 
-	ret = parse_events_terms(terms, t->str);
+	ret = parse_events_terms(&terms, t->str);
 	if (ret) {
 		pr_debug("failed to parse terms '%s', err %d\n",
 			 t->str , ret);
 		return ret;
 	}
 
-	ret = t->check(terms);
-	parse_events__free_terms(terms);
+	ret = t->check(&terms);
+	parse_events__free_terms(&terms);
 
 	return ret;
 }
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
new file mode 100644
index 0000000..0ab61b1
--- /dev/null
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -0,0 +1,177 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/prctl.h>
+
+#include "parse-events.h"
+#include "evlist.h"
+#include "evsel.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "tests.h"
+
+#include "../arch/x86/util/tsc.h"
+
+#define CHECK__(x) {				\
+	while ((x) < 0) {			\
+		pr_debug(#x " failed!\n");	\
+		goto out_err;			\
+	}					\
+}
+
+#define CHECK_NOT_NULL__(x) {			\
+	while ((x) == NULL) {			\
+		pr_debug(#x " failed!\n");	\
+		goto out_err;			\
+	}					\
+}
+
+static u64 rdtsc(void)
+{
+	unsigned int low, high;
+
+	asm volatile("rdtsc" : "=a" (low), "=d" (high));
+
+	return low | ((u64)high) << 32;
+}
+
+/**
+ * test__perf_time_to_tsc - test converting perf time to TSC.
+ *
+ * This function implements a test that checks that the conversion of perf time
+ * to and from TSC is consistent with the order of events.  If the test passes
+ * %0 is returned, otherwise %-1 is returned.  If TSC conversion is not
+ * supported then then the test passes but " (not supported)" is printed.
+ */
+int test__perf_time_to_tsc(void)
+{
+	struct perf_record_opts opts = {
+		.mmap_pages	     = UINT_MAX,
+		.user_freq	     = UINT_MAX,
+		.user_interval	     = ULLONG_MAX,
+		.freq		     = 4000,
+		.target		     = {
+			.uses_mmap   = true,
+		},
+		.sample_time	     = true,
+	};
+	struct thread_map *threads = NULL;
+	struct cpu_map *cpus = NULL;
+	struct perf_evlist *evlist = NULL;
+	struct perf_evsel *evsel = NULL;
+	int err = -1, ret, i;
+	const char *comm1, *comm2;
+	struct perf_tsc_conversion tc;
+	struct perf_event_mmap_page *pc;
+	union perf_event *event;
+	u64 test_tsc, comm1_tsc, comm2_tsc;
+	u64 test_time, comm1_time = 0, comm2_time = 0;
+
+	threads = thread_map__new(-1, getpid(), UINT_MAX);
+	CHECK_NOT_NULL__(threads);
+
+	cpus = cpu_map__new(NULL);
+	CHECK_NOT_NULL__(cpus);
+
+	evlist = perf_evlist__new();
+	CHECK_NOT_NULL__(evlist);
+
+	perf_evlist__set_maps(evlist, cpus, threads);
+
+	CHECK__(parse_events(evlist, "cycles:u"));
+
+	perf_evlist__config(evlist, &opts);
+
+	evsel = perf_evlist__first(evlist);
+
+	evsel->attr.comm = 1;
+	evsel->attr.disabled = 1;
+	evsel->attr.enable_on_exec = 0;
+
+	CHECK__(perf_evlist__open(evlist));
+
+	CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false));
+
+	pc = evlist->mmap[0].base;
+	ret = perf_read_tsc_conversion(pc, &tc);
+	if (ret) {
+		if (ret == -EOPNOTSUPP) {
+			fprintf(stderr, " (not supported)");
+			return 0;
+		}
+		goto out_err;
+	}
+
+	perf_evlist__enable(evlist);
+
+	comm1 = "Test COMM 1";
+	CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0));
+
+	test_tsc = rdtsc();
+
+	comm2 = "Test COMM 2";
+	CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0));
+
+	perf_evlist__disable(evlist);
+
+	for (i = 0; i < evlist->nr_mmaps; i++) {
+		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
+			struct perf_sample sample;
+
+			if (event->header.type != PERF_RECORD_COMM ||
+			    (pid_t)event->comm.pid != getpid() ||
+			    (pid_t)event->comm.tid != getpid())
+				continue;
+
+			if (strcmp(event->comm.comm, comm1) == 0) {
+				CHECK__(perf_evsel__parse_sample(evsel, event,
+								 &sample));
+				comm1_time = sample.time;
+			}
+			if (strcmp(event->comm.comm, comm2) == 0) {
+				CHECK__(perf_evsel__parse_sample(evsel, event,
+								 &sample));
+				comm2_time = sample.time;
+			}
+		}
+	}
+
+	if (!comm1_time || !comm2_time)
+		goto out_err;
+
+	test_time = tsc_to_perf_time(test_tsc, &tc);
+	comm1_tsc = perf_time_to_tsc(comm1_time, &tc);
+	comm2_tsc = perf_time_to_tsc(comm2_time, &tc);
+
+	pr_debug("1st event perf time %"PRIu64" tsc %"PRIu64"\n",
+		 comm1_time, comm1_tsc);
+	pr_debug("rdtsc          time %"PRIu64" tsc %"PRIu64"\n",
+		 test_time, test_tsc);
+	pr_debug("2nd event perf time %"PRIu64" tsc %"PRIu64"\n",
+		 comm2_time, comm2_tsc);
+
+	if (test_time <= comm1_time ||
+	    test_time >= comm2_time)
+		goto out_err;
+
+	if (test_tsc <= comm1_tsc ||
+	    test_tsc >= comm2_tsc)
+		goto out_err;
+
+	err = 0;
+
+out_err:
+	if (evlist) {
+		perf_evlist__disable(evlist);
+		perf_evlist__munmap(evlist);
+		perf_evlist__close(evlist);
+		perf_evlist__delete(evlist);
+	}
+	if (cpus)
+		cpu_map__delete(cpus);
+	if (threads)
+		thread_map__delete(threads);
+
+	return err;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index dd7feae..d22202a 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -1,6 +1,14 @@
 #ifndef TESTS_H
 #define TESTS_H
 
+#define TEST_ASSERT_VAL(text, cond)					 \
+do {									 \
+	if (!(cond)) {							 \
+		pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
+		return -1;						 \
+	}								 \
+} while (0)
+
 enum {
 	TEST_OK   =  0,
 	TEST_FAIL = -1,
@@ -27,5 +35,6 @@ int test__bp_signal(void);
 int test__bp_signal_overflow(void);
 int test__task_exit(void);
 int test__sw_clock_freq(void);
+int test__perf_time_to_tsc(void);
 
 #endif /* TESTS_H */
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 7b4c4d2..add1539 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -139,11 +139,18 @@ next_pair:
 				 * _really_ have a problem.
 				 */
 				s64 skew = sym->end - pair->end;
-				if (llabs(skew) < page_size)
-					continue;
+				if (llabs(skew) >= page_size)
+					pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
+						 sym->start, sym->name, sym->end, pair->end);
+
+				/*
+				 * Do not count this as a failure, because we
+				 * could really find a case where it's not
+				 * possible to get proper function end from
+				 * kallsyms.
+				 */
+				continue;
 
-				pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
-					 sym->start, sym->name, sym->end, pair->end);
 			} else {
 				struct rb_node *nnd;
 detour:
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index fc0bd38..7ef36c3 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -685,8 +685,10 @@ static u64 __hpp_get_##_field(struct hist_entry *he)			\
 	return he->stat._field;						\
 }									\
 									\
-static int hist_browser__hpp_color_##_type(struct perf_hpp *hpp,	\
-					   struct hist_entry *he)	\
+static int								\
+hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\
+				struct perf_hpp *hpp,			\
+				struct hist_entry *he)			\
 {									\
 	return __hpp__color_fmt(hpp, he, __hpp_get_##_field, _cb);	\
 }
@@ -701,8 +703,6 @@ __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, NULL)
 
 void hist_browser__init_hpp(void)
 {
-	perf_hpp__column_enable(PERF_HPP__OVERHEAD);
-
 	perf_hpp__init();
 
 	perf_hpp__format[PERF_HPP__OVERHEAD].color =
@@ -762,9 +762,9 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 			first = false;
 
 			if (fmt->color) {
-				width -= fmt->color(&hpp, entry);
+				width -= fmt->color(fmt, &hpp, entry);
 			} else {
-				width -= fmt->entry(&hpp, entry);
+				width -= fmt->entry(fmt, &hpp, entry);
 				slsmg_printf("%s", s);
 			}
 		}
@@ -1256,7 +1256,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
 		printed += scnprintf(bf + printed, size - printed,
 				    ", Thread: %s(%d)",
 				    (thread->comm_set ? thread->comm : ""),
-				    thread->pid);
+				    thread->tid);
 	if (dso)
 		printed += scnprintf(bf + printed, size - printed,
 				    ", DSO: %s", dso->short_name);
@@ -1579,7 +1579,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 		    asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
 			     (browser->hists->thread_filter ? "out of" : "into"),
 			     (thread->comm_set ? thread->comm : ""),
-			     thread->pid) > 0)
+			     thread->tid) > 0)
 			zoom_thread = nr_options++;
 
 		if (dso != NULL &&
@@ -1702,7 +1702,7 @@ zoom_out_thread:
 			} else {
 				ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
 						   thread->comm_set ? thread->comm : "",
-						   thread->pid);
+						   thread->tid);
 				browser->hists->thread_filter = thread;
 				sort_thread.elide = true;
 				pstack__push(fstack, &browser->hists->thread_filter);
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 9708dd5..cb2ed198 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -91,7 +91,8 @@ static u64 he_get_##_field(struct hist_entry *he)				\
 	return he->stat._field;							\
 }										\
 										\
-static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp,			\
+static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,	\
+				       struct perf_hpp *hpp,			\
 				       struct hist_entry *he)			\
 {										\
 	return __hpp__color_fmt(hpp, he, he_get_##_field);			\
@@ -124,6 +125,81 @@ void perf_gtk__init_hpp(void)
 				perf_gtk__hpp_color_overhead_guest_us;
 }
 
+static void callchain_list__sym_name(struct callchain_list *cl,
+				     char *bf, size_t bfsize)
+{
+	if (cl->ms.sym)
+		scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
+	else
+		scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
+}
+
+static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
+				    GtkTreeIter *parent, int col, u64 total)
+{
+	struct rb_node *nd;
+	bool has_single_node = (rb_first(root) == rb_last(root));
+
+	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
+		struct callchain_node *node;
+		struct callchain_list *chain;
+		GtkTreeIter iter, new_parent;
+		bool need_new_parent;
+		double percent;
+		u64 hits, child_total;
+
+		node = rb_entry(nd, struct callchain_node, rb_node);
+
+		hits = callchain_cumul_hits(node);
+		percent = 100.0 * hits / total;
+
+		new_parent = *parent;
+		need_new_parent = !has_single_node && (node->val_nr > 1);
+
+		list_for_each_entry(chain, &node->val, list) {
+			char buf[128];
+
+			gtk_tree_store_append(store, &iter, &new_parent);
+
+			scnprintf(buf, sizeof(buf), "%5.2f%%", percent);
+			gtk_tree_store_set(store, &iter, 0, buf, -1);
+
+			callchain_list__sym_name(chain, buf, sizeof(buf));
+			gtk_tree_store_set(store, &iter, col, buf, -1);
+
+			if (need_new_parent) {
+				/*
+				 * Only show the top-most symbol in a callchain
+				 * if it's not the only callchain.
+				 */
+				new_parent = iter;
+				need_new_parent = false;
+			}
+		}
+
+		if (callchain_param.mode == CHAIN_GRAPH_REL)
+			child_total = node->children_hit;
+		else
+			child_total = total;
+
+		/* Now 'iter' contains info of the last callchain_list */
+		perf_gtk__add_callchain(&node->rb_root, store, &iter, col,
+					child_total);
+	}
+}
+
+static void on_row_activated(GtkTreeView *view, GtkTreePath *path,
+			     GtkTreeViewColumn *col __maybe_unused,
+			     gpointer user_data __maybe_unused)
+{
+	bool expanded = gtk_tree_view_row_expanded(view, path);
+
+	if (expanded)
+		gtk_tree_view_collapse_row(view, path);
+	else
+		gtk_tree_view_expand_row(view, path, FALSE);
+}
+
 static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 				 float min_pcnt)
 {
@@ -131,10 +207,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 	GType col_types[MAX_COLUMNS];
 	GtkCellRenderer *renderer;
 	struct sort_entry *se;
-	GtkListStore *store;
+	GtkTreeStore *store;
 	struct rb_node *nd;
 	GtkWidget *view;
 	int col_idx;
+	int sym_col = -1;
 	int nr_cols;
 	char s[512];
 
@@ -153,10 +230,13 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 		if (se->elide)
 			continue;
 
+		if (se == &sort_sym)
+			sym_col = nr_cols;
+
 		col_types[nr_cols++] = G_TYPE_STRING;
 	}
 
-	store = gtk_list_store_newv(nr_cols, col_types);
+	store = gtk_tree_store_newv(nr_cols, col_types);
 
 	view = gtk_tree_view_new();
 
@@ -165,7 +245,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 	col_idx = 0;
 
 	perf_hpp__for_each_format(fmt) {
-		fmt->header(&hpp);
+		fmt->header(fmt, &hpp);
 
 		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
 							    -1, ltrim(s),
@@ -183,6 +263,18 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 							    col_idx++, NULL);
 	}
 
+	for (col_idx = 0; col_idx < nr_cols; col_idx++) {
+		GtkTreeViewColumn *column;
+
+		column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_idx);
+		gtk_tree_view_column_set_resizable(column, TRUE);
+
+		if (col_idx == sym_col) {
+			gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view),
+							  column);
+		}
+	}
+
 	gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
 
 	g_object_unref(GTK_TREE_MODEL(store));
@@ -199,17 +291,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 		if (percent < min_pcnt)
 			continue;
 
-		gtk_list_store_append(store, &iter);
+		gtk_tree_store_append(store, &iter, NULL);
 
 		col_idx = 0;
 
 		perf_hpp__for_each_format(fmt) {
 			if (fmt->color)
-				fmt->color(&hpp, h);
+				fmt->color(fmt, &hpp, h);
 			else
-				fmt->entry(&hpp, h);
+				fmt->entry(fmt, &hpp, h);
 
-			gtk_list_store_set(store, &iter, col_idx++, s, -1);
+			gtk_tree_store_set(store, &iter, col_idx++, s, -1);
 		}
 
 		list_for_each_entry(se, &hist_entry__sort_list, list) {
@@ -219,10 +311,26 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 			se->se_snprintf(h, s, ARRAY_SIZE(s),
 					hists__col_len(hists, se->se_width_idx));
 
-			gtk_list_store_set(store, &iter, col_idx++, s, -1);
+			gtk_tree_store_set(store, &iter, col_idx++, s, -1);
+		}
+
+		if (symbol_conf.use_callchain && sort__has_sym) {
+			u64 total;
+
+			if (callchain_param.mode == CHAIN_GRAPH_REL)
+				total = h->stat.period;
+			else
+				total = hists->stats.total_period;
+
+			perf_gtk__add_callchain(&h->sorted_chain, store, &iter,
+						sym_col, total);
 		}
 	}
 
+	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
+
+	g_signal_connect(view, "row-activated",
+			 G_CALLBACK(on_row_activated), NULL);
 	gtk_container_add(GTK_CONTAINER(window), view);
 }
 
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 4bf91b0..0a19328 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -1,4 +1,5 @@
 #include <math.h>
+#include <linux/compiler.h>
 
 #include "../util/hist.h"
 #include "../util/util.h"
@@ -79,7 +80,8 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
 }
 
 #define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) 		\
-static int hpp__header_##_type(struct perf_hpp *hpp)			\
+static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused,	\
+			       struct perf_hpp *hpp)			\
 {									\
 	int len = _min_width;						\
 									\
@@ -92,7 +94,8 @@ static int hpp__header_##_type(struct perf_hpp *hpp)			\
 }
 
 #define __HPP_WIDTH_FN(_type, _min_width, _unit_width) 			\
-static int hpp__width_##_type(struct perf_hpp *hpp __maybe_unused)	\
+static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused,	\
+			      struct perf_hpp *hpp __maybe_unused)	\
 {									\
 	int len = _min_width;						\
 									\
@@ -110,14 +113,16 @@ static u64 he_get_##_field(struct hist_entry *he)				\
 	return he->stat._field;							\
 }										\
 										\
-static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
+static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,		\
+			      struct perf_hpp *hpp, struct hist_entry *he) 	\
 {										\
 	return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%",			\
 			  (hpp_snprint_fn)percent_color_snprintf, true);	\
 }
 
 #define __HPP_ENTRY_PERCENT_FN(_type, _field)					\
-static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
+static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused,		\
+			      struct perf_hpp *hpp, struct hist_entry *he) 	\
 {										\
 	const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%";		\
 	return __hpp__fmt(hpp, he, he_get_##_field, fmt,			\
@@ -130,7 +135,8 @@ static u64 he_get_raw_##_field(struct hist_entry *he)				\
 	return he->stat._field;							\
 }										\
 										\
-static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) 	\
+static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused,		\
+			      struct perf_hpp *hpp, struct hist_entry *he) 	\
 {										\
 	const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64;	\
 	return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false);	\
@@ -157,196 +163,6 @@ HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
 HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12)
 HPP_RAW_FNS(period, "Period", period, 12, 12)
 
-
-static int hpp__header_baseline(struct perf_hpp *hpp)
-{
-	return scnprintf(hpp->buf, hpp->size, "Baseline");
-}
-
-static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
-{
-	return 8;
-}
-
-static double baseline_percent(struct hist_entry *he)
-{
-	struct hist_entry *pair = hist_entry__next_pair(he);
-	struct hists *pair_hists = pair ? pair->hists : NULL;
-	double percent = 0.0;
-
-	if (pair) {
-		u64 total_period = pair_hists->stats.total_period;
-		u64 base_period  = pair->stat.period;
-
-		percent = 100.0 * base_period / total_period;
-	}
-
-	return percent;
-}
-
-static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	double percent = baseline_percent(he);
-
-	if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
-		return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
-	else
-		return scnprintf(hpp->buf, hpp->size, "        ");
-}
-
-static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	double percent = baseline_percent(he);
-	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
-
-	if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
-		return scnprintf(hpp->buf, hpp->size, fmt, percent);
-	else
-		return scnprintf(hpp->buf, hpp->size, "            ");
-}
-
-static int hpp__header_period_baseline(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Period Base");
-}
-
-static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused)
-{
-	return 12;
-}
-
-static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hist_entry *pair = hist_entry__next_pair(he);
-	u64 period = pair ? pair->stat.period : 0;
-	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
-
-	return scnprintf(hpp->buf, hpp->size, fmt, period);
-}
-
-static int hpp__header_delta(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Delta");
-}
-
-static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
-{
-	return 7;
-}
-
-static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hist_entry *pair = hist_entry__next_pair(he);
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
-	char buf[32] = " ";
-	double diff = 0.0;
-
-	if (pair) {
-		if (he->diff.computed)
-			diff = he->diff.period_ratio_delta;
-		else
-			diff = perf_diff__compute_delta(he, pair);
-	} else
-		diff = perf_diff__period_percent(he, he->stat.period);
-
-	if (fabs(diff) >= 0.01)
-		scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
-
-	return scnprintf(hpp->buf, hpp->size, fmt, buf);
-}
-
-static int hpp__header_ratio(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Ratio");
-}
-
-static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
-{
-	return 14;
-}
-
-static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hist_entry *pair = hist_entry__next_pair(he);
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
-	char buf[32] = " ";
-	double ratio = 0.0;
-
-	if (pair) {
-		if (he->diff.computed)
-			ratio = he->diff.period_ratio;
-		else
-			ratio = perf_diff__compute_ratio(he, pair);
-	}
-
-	if (ratio > 0.0)
-		scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
-
-	return scnprintf(hpp->buf, hpp->size, fmt, buf);
-}
-
-static int hpp__header_wdiff(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff");
-}
-
-static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
-{
-	return 14;
-}
-
-static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hist_entry *pair = hist_entry__next_pair(he);
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
-	char buf[32] = " ";
-	s64 wdiff = 0;
-
-	if (pair) {
-		if (he->diff.computed)
-			wdiff = he->diff.wdiff;
-		else
-			wdiff = perf_diff__compute_wdiff(he, pair);
-	}
-
-	if (wdiff != 0)
-		scnprintf(buf, sizeof(buf), "%14ld", wdiff);
-
-	return scnprintf(hpp->buf, hpp->size, fmt, buf);
-}
-
-static int hpp__header_formula(struct perf_hpp *hpp)
-{
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
-
-	return scnprintf(hpp->buf, hpp->size, fmt, "Formula");
-}
-
-static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
-{
-	return 70;
-}
-
-static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
-{
-	struct hist_entry *pair = hist_entry__next_pair(he);
-	const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
-	char buf[96] = " ";
-
-	if (pair)
-		perf_diff__formula(he, pair, buf, sizeof(buf));
-
-	return scnprintf(hpp->buf, hpp->size, fmt, buf);
-}
-
 #define HPP__COLOR_PRINT_FNS(_name)			\
 	{						\
 		.header	= hpp__header_ ## _name,	\
@@ -363,19 +179,13 @@ static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
 	}
 
 struct perf_hpp_fmt perf_hpp__format[] = {
-	HPP__COLOR_PRINT_FNS(baseline),
 	HPP__COLOR_PRINT_FNS(overhead),
 	HPP__COLOR_PRINT_FNS(overhead_sys),
 	HPP__COLOR_PRINT_FNS(overhead_us),
 	HPP__COLOR_PRINT_FNS(overhead_guest_sys),
 	HPP__COLOR_PRINT_FNS(overhead_guest_us),
 	HPP__PRINT_FNS(samples),
-	HPP__PRINT_FNS(period),
-	HPP__PRINT_FNS(period_baseline),
-	HPP__PRINT_FNS(delta),
-	HPP__PRINT_FNS(ratio),
-	HPP__PRINT_FNS(wdiff),
-	HPP__PRINT_FNS(formula)
+	HPP__PRINT_FNS(period)
 };
 
 LIST_HEAD(perf_hpp__list);
@@ -396,6 +206,8 @@ LIST_HEAD(perf_hpp__list);
 
 void perf_hpp__init(void)
 {
+	perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+
 	if (symbol_conf.show_cpu_utilization) {
 		perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS);
 		perf_hpp__column_enable(PERF_HPP__OVERHEAD_US);
@@ -424,46 +236,6 @@ void perf_hpp__column_enable(unsigned col)
 	perf_hpp__column_register(&perf_hpp__format[col]);
 }
 
-static inline void advance_hpp(struct perf_hpp *hpp, int inc)
-{
-	hpp->buf  += inc;
-	hpp->size -= inc;
-}
-
-int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
-				bool color)
-{
-	const char *sep = symbol_conf.field_sep;
-	struct perf_hpp_fmt *fmt;
-	char *start = hpp->buf;
-	int ret;
-	bool first = true;
-
-	if (symbol_conf.exclude_other && !he->parent)
-		return 0;
-
-	perf_hpp__for_each_format(fmt) {
-		/*
-		 * If there's no field_sep, we still need
-		 * to display initial '  '.
-		 */
-		if (!sep || !first) {
-			ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
-			advance_hpp(hpp, ret);
-		} else
-			first = false;
-
-		if (color && fmt->color)
-			ret = fmt->color(hpp, he);
-		else
-			ret = fmt->entry(hpp, he);
-
-		advance_hpp(hpp, ret);
-	}
-
-	return hpp->buf - start;
-}
-
 int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
 			      struct hists *hists)
 {
@@ -499,7 +271,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
 		if (i)
 			ret += 2;
 
-		ret += fmt->width(&dummy_hpp);
+		ret += fmt->width(fmt, &dummy_hpp);
 	}
 
 	list_for_each_entry(se, &hist_entry__sort_list, list)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ae6a789..47d9a57 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -30,7 +30,6 @@ void setup_browser(bool fallback_to_pager)
 		if (fallback_to_pager)
 			setup_pager();
 
-		perf_hpp__column_enable(PERF_HPP__OVERHEAD);
 		perf_hpp__init();
 		break;
 	}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index ae7a754..5b4fb33 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -308,6 +308,47 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
 	return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
 }
 
+static inline void advance_hpp(struct perf_hpp *hpp, int inc)
+{
+	hpp->buf  += inc;
+	hpp->size -= inc;
+}
+
+static int hist_entry__period_snprintf(struct perf_hpp *hpp,
+				       struct hist_entry *he,
+				       bool color)
+{
+	const char *sep = symbol_conf.field_sep;
+	struct perf_hpp_fmt *fmt;
+	char *start = hpp->buf;
+	int ret;
+	bool first = true;
+
+	if (symbol_conf.exclude_other && !he->parent)
+		return 0;
+
+	perf_hpp__for_each_format(fmt) {
+		/*
+		 * If there's no field_sep, we still need
+		 * to display initial '  '.
+		 */
+		if (!sep || !first) {
+			ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
+			advance_hpp(hpp, ret);
+		} else
+			first = false;
+
+		if (color && fmt->color)
+			ret = fmt->color(fmt, hpp, he);
+		else
+			ret = fmt->entry(fmt, hpp, he);
+
+		advance_hpp(hpp, ret);
+	}
+
+	return hpp->buf - start;
+}
+
 static int hist_entry__fprintf(struct hist_entry *he, size_t size,
 			       struct hists *hists, FILE *fp)
 {
@@ -365,7 +406,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 		else
 			first = false;
 
-		fmt->header(&dummy_hpp);
+		fmt->header(fmt, &dummy_hpp);
 		fprintf(fp, "%s", bf);
 	}
 
@@ -410,7 +451,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 		else
 			first = false;
 
-		width = fmt->width(&dummy_hpp);
+		width = fmt->width(fmt, &dummy_hpp);
 		for (i = 0; i < width; i++)
 			fprintf(fp, ".");
 	}
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 42b6a63..4fee33b 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,6 +15,7 @@
 #include <errno.h>
 #include <math.h>
 
+#include "hist.h"
 #include "util.h"
 #include "callchain.h"
 
@@ -327,7 +328,8 @@ append_chain(struct callchain_node *root,
 	/*
 	 * Lookup in the current node
 	 * If we have a symbol, then compare the start to match
-	 * anywhere inside a function.
+	 * anywhere inside a function, unless function
+	 * mode is disabled.
 	 */
 	list_for_each_entry(cnode, &root->val, list) {
 		struct callchain_cursor_node *node;
@@ -339,7 +341,8 @@ append_chain(struct callchain_node *root,
 
 		sym = node->sym;
 
-		if (cnode->ms.sym && sym) {
+		if (cnode->ms.sym && sym &&
+		    callchain_param.key == CCKEY_FUNCTION) {
 			if (cnode->ms.sym->start != sym->start)
 				break;
 		} else if (cnode->ip != node->ip)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 3ee9f67..812d5a0 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -41,12 +41,18 @@ struct callchain_param;
 typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
 				 u64, struct callchain_param *);
 
+enum chain_key {
+	CCKEY_FUNCTION,
+	CCKEY_ADDRESS
+};
+
 struct callchain_param {
 	enum chain_mode 	mode;
 	u32			print_limit;
 	double			min_percent;
 	sort_chain_func_t	sort;
 	enum chain_order	order;
+	enum chain_key		key;
 };
 
 struct callchain_list {
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 9bed02e..b123bb9 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -41,7 +41,7 @@ static inline int cpu_map__nr(const struct cpu_map *map)
 	return map ? map->nr : 1;
 }
 
-static inline bool cpu_map__all(const struct cpu_map *map)
+static inline bool cpu_map__empty(const struct cpu_map *map)
 {
 	return map ? map->map[0] == -1 : true;
 }
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 5cd13d7..9541270 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -686,7 +686,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
 	    !strlist__has_entry(symbol_conf.comm_list, thread->comm))
 		goto out_filtered;
 
-	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
+	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid);
 	/*
 	 * Have we already created the kernel maps for this machine?
 	 *
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1813895..1ebb8fb 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -116,7 +116,7 @@ struct build_id_event {
 enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_USER_TYPE_START		= 64,
 	PERF_RECORD_HEADER_ATTR			= 64,
-	PERF_RECORD_HEADER_EVENT_TYPE		= 65,
+	PERF_RECORD_HEADER_EVENT_TYPE		= 65, /* depreceated */
 	PERF_RECORD_HEADER_TRACING_DATA		= 66,
 	PERF_RECORD_HEADER_BUILD_ID		= 67,
 	PERF_RECORD_FINISHED_ROUND		= 68,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8065ce8..42ea4e9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -403,16 +403,20 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 	return event;
 }
 
+static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
+{
+	if (evlist->mmap[idx].base != NULL) {
+		munmap(evlist->mmap[idx].base, evlist->mmap_len);
+		evlist->mmap[idx].base = NULL;
+	}
+}
+
 void perf_evlist__munmap(struct perf_evlist *evlist)
 {
 	int i;
 
-	for (i = 0; i < evlist->nr_mmaps; i++) {
-		if (evlist->mmap[i].base != NULL) {
-			munmap(evlist->mmap[i].base, evlist->mmap_len);
-			evlist->mmap[i].base = NULL;
-		}
-	}
+	for (i = 0; i < evlist->nr_mmaps; i++)
+		__perf_evlist__munmap(evlist, i);
 
 	free(evlist->mmap);
 	evlist->mmap = NULL;
@@ -421,7 +425,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
 static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
 {
 	evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
-	if (cpu_map__all(evlist->cpus))
+	if (cpu_map__empty(evlist->cpus))
 		evlist->nr_mmaps = thread_map__nr(evlist->threads);
 	evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
 	return evlist->mmap != NULL ? 0 : -ENOMEM;
@@ -477,12 +481,8 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
 	return 0;
 
 out_unmap:
-	for (cpu = 0; cpu < nr_cpus; cpu++) {
-		if (evlist->mmap[cpu].base != NULL) {
-			munmap(evlist->mmap[cpu].base, evlist->mmap_len);
-			evlist->mmap[cpu].base = NULL;
-		}
-	}
+	for (cpu = 0; cpu < nr_cpus; cpu++)
+		__perf_evlist__munmap(evlist, cpu);
 	return -1;
 }
 
@@ -517,12 +517,8 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
 	return 0;
 
 out_unmap:
-	for (thread = 0; thread < nr_threads; thread++) {
-		if (evlist->mmap[thread].base != NULL) {
-			munmap(evlist->mmap[thread].base, evlist->mmap_len);
-			evlist->mmap[thread].base = NULL;
-		}
-	}
+	for (thread = 0; thread < nr_threads; thread++)
+		__perf_evlist__munmap(evlist, thread);
 	return -1;
 }
 
@@ -573,7 +569,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 			return -ENOMEM;
 	}
 
-	if (cpu_map__all(cpus))
+	if (cpu_map__empty(cpus))
 		return perf_evlist__mmap_per_thread(evlist, prot, mask);
 
 	return perf_evlist__mmap_per_cpu(evlist, prot, mask);
@@ -838,7 +834,7 @@ out_close_ready_pipe:
 int perf_evlist__start_workload(struct perf_evlist *evlist)
 {
 	if (evlist->workload.cork_fd > 0) {
-		char bf;
+		char bf = 0;
 		int ret;
 		/*
 		 * Remove the cork, let it rip!
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index c9c7494..8bed0c1 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -9,17 +9,17 @@
 
 #include <byteswap.h>
 #include <linux/bitops.h>
-#include "asm/bug.h"
 #include <lk/debugfs.h>
-#include "event-parse.h"
+#include <traceevent/event-parse.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/perf_event.h>
+#include "asm/bug.h"
 #include "evsel.h"
 #include "evlist.h"
 #include "util.h"
 #include "cpumap.h"
 #include "thread_map.h"
 #include "target.h"
-#include <linux/hw_breakpoint.h>
-#include <linux/perf_event.h>
 #include "perf_regs.h"
 
 static struct {
@@ -1482,7 +1482,7 @@ out:
 bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
 			  char *msg, size_t msgsize)
 {
-	if ((err == ENOENT || err == ENXIO) &&
+	if ((err == ENOENT || err == ENXIO || err == ENODEV) &&
 	    evsel->attr.type   == PERF_TYPE_HARDWARE &&
 	    evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) {
 		/*
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a4dafbe..f558f83 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -25,41 +25,9 @@
 
 static bool no_buildid_cache = false;
 
-static int trace_event_count;
-static struct perf_trace_event_type *trace_events;
-
 static u32 header_argc;
 static const char **header_argv;
 
-int perf_header__push_event(u64 id, const char *name)
-{
-	struct perf_trace_event_type *nevents;
-
-	if (strlen(name) > MAX_EVENT_NAME)
-		pr_warning("Event %s will be truncated\n", name);
-
-	nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events));
-	if (nevents == NULL)
-		return -ENOMEM;
-	trace_events = nevents;
-
-	memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type));
-	trace_events[trace_event_count].event_id = id;
-	strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1);
-	trace_event_count++;
-	return 0;
-}
-
-char *perf_header__find_event(u64 id)
-{
-	int i;
-	for (i = 0 ; i < trace_event_count; i++) {
-		if (trace_events[i].event_id == id)
-			return trace_events[i].name;
-	}
-	return NULL;
-}
-
 /*
  * magic2 = "PERFILE2"
  * must be a numerical value to let the endianness
@@ -2257,7 +2225,7 @@ static int perf_header__adds_write(struct perf_header *header,
 
 	sec_size = sizeof(*feat_sec) * nr_sections;
 
-	sec_start = header->data_offset + header->data_size;
+	sec_start = header->feat_offset;
 	lseek(fd, sec_start + sec_size, SEEK_SET);
 
 	for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
@@ -2304,6 +2272,7 @@ int perf_session__write_header(struct perf_session *session,
 	struct perf_file_attr   f_attr;
 	struct perf_header *header = &session->header;
 	struct perf_evsel *evsel;
+	u64 attr_offset;
 	int err;
 
 	lseek(fd, sizeof(f_header), SEEK_SET);
@@ -2317,7 +2286,7 @@ int perf_session__write_header(struct perf_session *session,
 		}
 	}
 
-	header->attr_offset = lseek(fd, 0, SEEK_CUR);
+	attr_offset = lseek(fd, 0, SEEK_CUR);
 
 	list_for_each_entry(evsel, &evlist->entries, node) {
 		f_attr = (struct perf_file_attr){
@@ -2334,17 +2303,8 @@ int perf_session__write_header(struct perf_session *session,
 		}
 	}
 
-	header->event_offset = lseek(fd, 0, SEEK_CUR);
-	header->event_size = trace_event_count * sizeof(struct perf_trace_event_type);
-	if (trace_events) {
-		err = do_write(fd, trace_events, header->event_size);
-		if (err < 0) {
-			pr_debug("failed to write perf header events\n");
-			return err;
-		}
-	}
-
 	header->data_offset = lseek(fd, 0, SEEK_CUR);
+	header->feat_offset = header->data_offset + header->data_size;
 
 	if (at_exit) {
 		err = perf_header__adds_write(header, evlist, fd);
@@ -2357,17 +2317,14 @@ int perf_session__write_header(struct perf_session *session,
 		.size	   = sizeof(f_header),
 		.attr_size = sizeof(f_attr),
 		.attrs = {
-			.offset = header->attr_offset,
+			.offset = attr_offset,
 			.size   = evlist->nr_entries * sizeof(f_attr),
 		},
 		.data = {
 			.offset = header->data_offset,
 			.size	= header->data_size,
 		},
-		.event_types = {
-			.offset = header->event_offset,
-			.size	= header->event_size,
-		},
+		/* event_types is ignored, store zeros */
 	};
 
 	memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
@@ -2417,7 +2374,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
 
 	sec_size = sizeof(*feat_sec) * nr_sections;
 
-	lseek(fd, header->data_offset + header->data_size, SEEK_SET);
+	lseek(fd, header->feat_offset, SEEK_SET);
 
 	err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
 	if (err < 0)
@@ -2523,6 +2480,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
 	/* check for legacy format */
 	ret = memcmp(&magic, __perf_magic1, sizeof(magic));
 	if (ret == 0) {
+		ph->version = PERF_HEADER_VERSION_1;
 		pr_debug("legacy perf.data format\n");
 		if (is_pipe)
 			return try_all_pipe_abis(hdr_sz, ph);
@@ -2544,6 +2502,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
 		return -1;
 
 	ph->needs_swap = true;
+	ph->version = PERF_HEADER_VERSION_2;
 
 	return 0;
 }
@@ -2614,10 +2573,9 @@ int perf_file_header__read(struct perf_file_header *header,
 	memcpy(&ph->adds_features, &header->adds_features,
 	       sizeof(ph->adds_features));
 
-	ph->event_offset = header->event_types.offset;
-	ph->event_size   = header->event_types.size;
 	ph->data_offset  = header->data.offset;
 	ph->data_size	 = header->data.size;
+	ph->feat_offset  = header->data.offset + header->data.size;
 	return 0;
 }
 
@@ -2666,19 +2624,17 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
 	return 0;
 }
 
-static int perf_header__read_pipe(struct perf_session *session, int fd)
+static int perf_header__read_pipe(struct perf_session *session)
 {
 	struct perf_header *header = &session->header;
 	struct perf_pipe_file_header f_header;
 
-	if (perf_file_header__read_pipe(&f_header, header, fd,
+	if (perf_file_header__read_pipe(&f_header, header, session->fd,
 					session->repipe) < 0) {
 		pr_debug("incompatible file format\n");
 		return -EINVAL;
 	}
 
-	session->fd = fd;
-
 	return 0;
 }
 
@@ -2772,20 +2728,21 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
 	return 0;
 }
 
-int perf_session__read_header(struct perf_session *session, int fd)
+int perf_session__read_header(struct perf_session *session)
 {
 	struct perf_header *header = &session->header;
 	struct perf_file_header	f_header;
 	struct perf_file_attr	f_attr;
 	u64			f_id;
 	int nr_attrs, nr_ids, i, j;
+	int fd = session->fd;
 
 	session->evlist = perf_evlist__new();
 	if (session->evlist == NULL)
 		return -ENOMEM;
 
 	if (session->fd_pipe)
-		return perf_header__read_pipe(session, fd);
+		return perf_header__read_pipe(session);
 
 	if (perf_file_header__read(&f_header, header, fd) < 0)
 		return -EINVAL;
@@ -2839,22 +2796,9 @@ int perf_session__read_header(struct perf_session *session, int fd)
 
 	symbol_conf.nr_events = nr_attrs;
 
-	if (f_header.event_types.size) {
-		lseek(fd, f_header.event_types.offset, SEEK_SET);
-		trace_events = malloc(f_header.event_types.size);
-		if (trace_events == NULL)
-			return -ENOMEM;
-		if (perf_header__getbuffer64(header, fd, trace_events,
-					     f_header.event_types.size))
-			goto out_errno;
-		trace_event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
-	}
-
 	perf_header__process_sections(header, fd, &session->pevent,
 				      perf_file_section__process);
 
-	lseek(fd, header->data_offset, SEEK_SET);
-
 	if (perf_evlist__prepare_tracepoint_events(session->evlist,
 						   session->pevent))
 		goto out_delete_evlist;
@@ -2922,7 +2866,8 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 	return err;
 }
 
-int perf_event__process_attr(union perf_event *event,
+int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
 			     struct perf_evlist **pevlist)
 {
 	u32 i, ids, n_ids;
@@ -2961,64 +2906,6 @@ int perf_event__process_attr(union perf_event *event,
 	return 0;
 }
 
-int perf_event__synthesize_event_type(struct perf_tool *tool,
-				      u64 event_id, char *name,
-				      perf_event__handler_t process,
-				      struct machine *machine)
-{
-	union perf_event ev;
-	size_t size = 0;
-	int err = 0;
-
-	memset(&ev, 0, sizeof(ev));
-
-	ev.event_type.event_type.event_id = event_id;
-	memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME);
-	strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
-
-	ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
-	size = strlen(ev.event_type.event_type.name);
-	size = PERF_ALIGN(size, sizeof(u64));
-	ev.event_type.header.size = sizeof(ev.event_type) -
-		(sizeof(ev.event_type.event_type.name) - size);
-
-	err = process(tool, &ev, NULL, machine);
-
-	return err;
-}
-
-int perf_event__synthesize_event_types(struct perf_tool *tool,
-				       perf_event__handler_t process,
-				       struct machine *machine)
-{
-	struct perf_trace_event_type *type;
-	int i, err = 0;
-
-	for (i = 0; i < trace_event_count; i++) {
-		type = &trace_events[i];
-
-		err = perf_event__synthesize_event_type(tool, type->event_id,
-							type->name, process,
-							machine);
-		if (err) {
-			pr_debug("failed to create perf header event type\n");
-			return err;
-		}
-	}
-
-	return err;
-}
-
-int perf_event__process_event_type(struct perf_tool *tool __maybe_unused,
-				   union perf_event *event)
-{
-	if (perf_header__push_event(event->event_type.event_type.event_id,
-				    event->event_type.event_type.name) < 0)
-		return -ENOMEM;
-
-	return 0;
-}
-
 int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
 					struct perf_evlist *evlist,
 					perf_event__handler_t process)
@@ -3065,7 +2952,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
 	return aligned_size;
 }
 
-int perf_event__process_tracing_data(union perf_event *event,
+int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
 				     struct perf_session *session)
 {
 	ssize_t size_read, padding, size = event->tracing_data.size;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 16a3e83..307c9ae 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -34,6 +34,11 @@ enum {
 	HEADER_FEAT_BITS	= 256,
 };
 
+enum perf_header_version {
+	PERF_HEADER_VERSION_1,
+	PERF_HEADER_VERSION_2,
+};
+
 struct perf_file_section {
 	u64 offset;
 	u64 size;
@@ -45,6 +50,7 @@ struct perf_file_header {
 	u64				attr_size;
 	struct perf_file_section	attrs;
 	struct perf_file_section	data;
+	/* event_types is ignored */
 	struct perf_file_section	event_types;
 	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
 };
@@ -84,28 +90,24 @@ struct perf_session_env {
 };
 
 struct perf_header {
-	bool			needs_swap;
-	s64			attr_offset;
-	u64			data_offset;
-	u64			data_size;
-	u64			event_offset;
-	u64			event_size;
+	enum perf_header_version	version;
+	bool				needs_swap;
+	u64				data_offset;
+	u64				data_size;
+	u64				feat_offset;
 	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
-	struct perf_session_env env;
+	struct perf_session_env 	env;
 };
 
 struct perf_evlist;
 struct perf_session;
 
-int perf_session__read_header(struct perf_session *session, int fd);
+int perf_session__read_header(struct perf_session *session);
 int perf_session__write_header(struct perf_session *session,
 			       struct perf_evlist *evlist,
 			       int fd, bool at_exit);
 int perf_header__write_pipe(int fd);
 
-int perf_header__push_event(u64 id, const char *name);
-char *perf_header__find_event(u64 id);
-
 void perf_header__set_feat(struct perf_header *header, int feat);
 void perf_header__clear_feat(struct perf_header *header, int feat);
 bool perf_header__has_feat(const struct perf_header *header, int feat);
@@ -130,22 +132,14 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 struct perf_session *session,
 				 perf_event__handler_t process);
-int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
-
-int perf_event__synthesize_event_type(struct perf_tool *tool,
-				      u64 event_id, char *name,
-				      perf_event__handler_t process,
-				      struct machine *machine);
-int perf_event__synthesize_event_types(struct perf_tool *tool,
-				       perf_event__handler_t process,
-				       struct machine *machine);
-int perf_event__process_event_type(struct perf_tool *tool,
-				   union perf_event *event);
+int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
+			     struct perf_evlist **pevlist);
 
 int perf_event__synthesize_tracing_data(struct perf_tool *tool,
 					int fd, struct perf_evlist *evlist,
 					perf_event__handler_t process);
-int perf_event__process_tracing_data(union perf_event *event,
+int perf_event__process_tracing_data(struct perf_tool *tool,
+				     union perf_event *event,
 				     struct perf_session *session);
 
 int perf_event__synthesize_build_id(struct perf_tool *tool,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b11a6cf..46a0d35 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -24,7 +24,8 @@ enum hist_filter {
 struct callchain_param	callchain_param = {
 	.mode	= CHAIN_GRAPH_REL,
 	.min_percent = 0.5,
-	.order  = ORDER_CALLEE
+	.order  = ORDER_CALLEE,
+	.key	= CCKEY_FUNCTION
 };
 
 u16 hists__col_len(struct hists *hists, enum hist_column col)
@@ -912,6 +913,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
 		rb_link_node(&he->rb_node_in, parent, p);
 		rb_insert_color(&he->rb_node_in, root);
 		hists__inc_nr_entries(hists, he);
+		he->dummy = true;
 	}
 out:
 	return he;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2d3790f..1329b6b 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -141,10 +141,12 @@ struct perf_hpp {
 };
 
 struct perf_hpp_fmt {
-	int (*header)(struct perf_hpp *hpp);
-	int (*width)(struct perf_hpp *hpp);
-	int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
-	int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
+	int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp);
+	int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp);
+	int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+		     struct hist_entry *he);
+	int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+		     struct hist_entry *he);
 
 	struct list_head list;
 };
@@ -157,7 +159,7 @@ extern struct list_head perf_hpp__list;
 extern struct perf_hpp_fmt perf_hpp__format[];
 
 enum {
-	PERF_HPP__BASELINE,
+	/* Matches perf_hpp__format array. */
 	PERF_HPP__OVERHEAD,
 	PERF_HPP__OVERHEAD_SYS,
 	PERF_HPP__OVERHEAD_US,
@@ -165,11 +167,6 @@ enum {
 	PERF_HPP__OVERHEAD_GUEST_US,
 	PERF_HPP__SAMPLES,
 	PERF_HPP__PERIOD,
-	PERF_HPP__PERIOD_BASELINE,
-	PERF_HPP__DELTA,
-	PERF_HPP__RATIO,
-	PERF_HPP__WEIGHTED_DIFF,
-	PERF_HPP__FORMULA,
 
 	PERF_HPP__MAX_INDEX
 };
@@ -177,8 +174,6 @@ enum {
 void perf_hpp__init(void);
 void perf_hpp__column_register(struct perf_hpp_fmt *format);
 void perf_hpp__column_enable(unsigned col);
-int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
-				bool color);
 
 struct perf_evlist;
 
@@ -245,11 +240,4 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 #endif
 
 unsigned int hists__sort_list_width(struct hists *self);
-
-double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair);
-double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair);
-s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair);
-int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
-		       char *buf, size_t size);
-double perf_diff__period_percent(struct hist_entry *he, u64 period);
 #endif	/* __PERF_HIST_H */
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
index 6f19c54..97a8007 100644
--- a/tools/perf/util/include/linux/string.h
+++ b/tools/perf/util/include/linux/string.h
@@ -1,3 +1,4 @@
 #include <string.h>
 
 void *memdup(const void *src, size_t len);
+int str_append(char **s, int *len, const char *a);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b2ecad6..f9f9d63 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -233,7 +233,7 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
 	return;
 }
 
-static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid,
+static struct thread *__machine__findnew_thread(struct machine *machine, pid_t tid,
 						bool create)
 {
 	struct rb_node **p = &machine->threads.rb_node;
@@ -241,23 +241,23 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t p
 	struct thread *th;
 
 	/*
-	 * Font-end cache - PID lookups come in blocks,
+	 * Front-end cache - TID lookups come in blocks,
 	 * so most of the time we dont have to look up
 	 * the full rbtree:
 	 */
-	if (machine->last_match && machine->last_match->pid == pid)
+	if (machine->last_match && machine->last_match->tid == tid)
 		return machine->last_match;
 
 	while (*p != NULL) {
 		parent = *p;
 		th = rb_entry(parent, struct thread, rb_node);
 
-		if (th->pid == pid) {
+		if (th->tid == tid) {
 			machine->last_match = th;
 			return th;
 		}
 
-		if (pid < th->pid)
+		if (tid < th->tid)
 			p = &(*p)->rb_left;
 		else
 			p = &(*p)->rb_right;
@@ -266,7 +266,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t p
 	if (!create)
 		return NULL;
 
-	th = thread__new(pid);
+	th = thread__new(tid);
 	if (th != NULL) {
 		rb_link_node(&th->rb_node, parent, p);
 		rb_insert_color(&th->rb_node, &machine->threads);
@@ -276,14 +276,14 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t p
 	return th;
 }
 
-struct thread *machine__findnew_thread(struct machine *machine, pid_t pid)
+struct thread *machine__findnew_thread(struct machine *machine, pid_t tid)
 {
-	return __machine__findnew_thread(machine, pid, true);
+	return __machine__findnew_thread(machine, tid, true);
 }
 
-struct thread *machine__find_thread(struct machine *machine, pid_t pid)
+struct thread *machine__find_thread(struct machine *machine, pid_t tid)
 {
-	return __machine__findnew_thread(machine, pid, false);
+	return __machine__findnew_thread(machine, tid, false);
 }
 
 int machine__process_comm_event(struct machine *machine, union perf_event *event)
@@ -1058,11 +1058,10 @@ int machine__process_event(struct machine *machine, union perf_event *event)
 	return ret;
 }
 
-static bool symbol__match_parent_regex(struct symbol *sym)
+static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
 {
-	if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
+	if (sym->name && !regexec(regex, sym->name, 0, NULL, 0))
 		return 1;
-
 	return 0;
 }
 
@@ -1159,8 +1158,8 @@ struct branch_info *machine__resolve_bstack(struct machine *machine,
 static int machine__resolve_callchain_sample(struct machine *machine,
 					     struct thread *thread,
 					     struct ip_callchain *chain,
-					     struct symbol **parent)
-
+					     struct symbol **parent,
+					     struct addr_location *root_al)
 {
 	u8 cpumode = PERF_RECORD_MISC_USER;
 	unsigned int i;
@@ -1211,8 +1210,15 @@ static int machine__resolve_callchain_sample(struct machine *machine,
 					   MAP__FUNCTION, ip, &al, NULL);
 		if (al.sym != NULL) {
 			if (sort__has_parent && !*parent &&
-			    symbol__match_parent_regex(al.sym))
+			    symbol__match_regex(al.sym, &parent_regex))
 				*parent = al.sym;
+			else if (have_ignore_callees && root_al &&
+			  symbol__match_regex(al.sym, &ignore_callees_regex)) {
+				/* Treat this symbol as the root,
+				   forgetting its callees. */
+				*root_al = al;
+				callchain_cursor_reset(&callchain_cursor);
+			}
 			if (!symbol_conf.use_callchain)
 				break;
 		}
@@ -1237,15 +1243,13 @@ int machine__resolve_callchain(struct machine *machine,
 			       struct perf_evsel *evsel,
 			       struct thread *thread,
 			       struct perf_sample *sample,
-			       struct symbol **parent)
-
+			       struct symbol **parent,
+			       struct addr_location *root_al)
 {
 	int ret;
 
-	callchain_cursor_reset(&callchain_cursor);
-
 	ret = machine__resolve_callchain_sample(machine, thread,
-						sample->callchain, parent);
+						sample->callchain, parent, root_al);
 	if (ret)
 		return ret;
 
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 7794068..5bb6244 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -5,6 +5,7 @@
 #include <linux/rbtree.h>
 #include "map.h"
 
+struct addr_location;
 struct branch_stack;
 struct perf_evsel;
 struct perf_sample;
@@ -36,7 +37,7 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
 	return machine->vmlinux_maps[type];
 }
 
-struct thread *machine__find_thread(struct machine *machine, pid_t pid);
+struct thread *machine__find_thread(struct machine *machine, pid_t tid);
 
 int machine__process_comm_event(struct machine *machine, union perf_event *event);
 int machine__process_exit_event(struct machine *machine, union perf_event *event);
@@ -83,7 +84,8 @@ int machine__resolve_callchain(struct machine *machine,
 			       struct perf_evsel *evsel,
 			       struct thread *thread,
 			       struct perf_sample *sample,
-			       struct symbol **parent);
+			       struct symbol **parent,
+			       struct addr_location *root_al);
 
 /*
  * Default guest kernel is defined by parameter --guestkallsyms
@@ -99,7 +101,7 @@ static inline bool machine__is_host(struct machine *machine)
 	return machine ? machine->pid == HOST_KERNEL_ID : false;
 }
 
-struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
+struct thread *machine__findnew_thread(struct machine *machine, pid_t tid);
 
 size_t machine__fprintf(struct machine *machine, FILE *fp);
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 995fc25..2c460ed 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,7 +6,7 @@
 #include "parse-options.h"
 #include "parse-events.h"
 #include "exec_cmd.h"
-#include "string.h"
+#include "linux/string.h"
 #include "symbol.h"
 #include "cache.h"
 #include "header.h"
@@ -217,6 +217,29 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
 	return NULL;
 }
 
+struct tracepoint_path *tracepoint_name_to_path(const char *name)
+{
+	struct tracepoint_path *path = zalloc(sizeof(*path));
+	char *str = strchr(name, ':');
+
+	if (path == NULL || str == NULL) {
+		free(path);
+		return NULL;
+	}
+
+	path->system = strndup(name, str - name);
+	path->name = strdup(str+1);
+
+	if (path->system == NULL || path->name == NULL) {
+		free(path->system);
+		free(path->name);
+		free(path);
+		path = NULL;
+	}
+
+	return path;
+}
+
 const char *event_type(int type)
 {
 	switch (type) {
@@ -241,40 +264,29 @@ const char *event_type(int type)
 
 
 
-static int __add_event(struct list_head **_list, int *idx,
+static int __add_event(struct list_head *list, int *idx,
 		       struct perf_event_attr *attr,
 		       char *name, struct cpu_map *cpus)
 {
 	struct perf_evsel *evsel;
-	struct list_head *list = *_list;
-
-	if (!list) {
-		list = malloc(sizeof(*list));
-		if (!list)
-			return -ENOMEM;
-		INIT_LIST_HEAD(list);
-	}
 
 	event_attr_init(attr);
 
 	evsel = perf_evsel__new(attr, (*idx)++);
-	if (!evsel) {
-		free(list);
+	if (!evsel)
 		return -ENOMEM;
-	}
 
 	evsel->cpus = cpus;
 	if (name)
 		evsel->name = strdup(name);
 	list_add_tail(&evsel->node, list);
-	*_list = list;
 	return 0;
 }
 
-static int add_event(struct list_head **_list, int *idx,
+static int add_event(struct list_head *list, int *idx,
 		     struct perf_event_attr *attr, char *name)
 {
-	return __add_event(_list, idx, attr, name, NULL);
+	return __add_event(list, idx, attr, name, NULL);
 }
 
 static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -295,7 +307,7 @@ static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES]
 	return -1;
 }
 
-int parse_events_add_cache(struct list_head **list, int *idx,
+int parse_events_add_cache(struct list_head *list, int *idx,
 			   char *type, char *op_result1, char *op_result2)
 {
 	struct perf_event_attr attr;
@@ -356,31 +368,21 @@ int parse_events_add_cache(struct list_head **list, int *idx,
 	return add_event(list, idx, &attr, name);
 }
 
-static int add_tracepoint(struct list_head **listp, int *idx,
+static int add_tracepoint(struct list_head *list, int *idx,
 			  char *sys_name, char *evt_name)
 {
 	struct perf_evsel *evsel;
-	struct list_head *list = *listp;
-
-	if (!list) {
-		list = malloc(sizeof(*list));
-		if (!list)
-			return -ENOMEM;
-		INIT_LIST_HEAD(list);
-	}
 
 	evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++);
-	if (!evsel) {
-		free(list);
+	if (!evsel)
 		return -ENOMEM;
-	}
 
 	list_add_tail(&evsel->node, list);
-	*listp = list;
+
 	return 0;
 }
 
-static int add_tracepoint_multi_event(struct list_head **list, int *idx,
+static int add_tracepoint_multi_event(struct list_head *list, int *idx,
 				      char *sys_name, char *evt_name)
 {
 	char evt_path[MAXPATHLEN];
@@ -412,7 +414,7 @@ static int add_tracepoint_multi_event(struct list_head **list, int *idx,
 	return ret;
 }
 
-static int add_tracepoint_event(struct list_head **list, int *idx,
+static int add_tracepoint_event(struct list_head *list, int *idx,
 				char *sys_name, char *evt_name)
 {
 	return strpbrk(evt_name, "*?") ?
@@ -420,7 +422,7 @@ static int add_tracepoint_event(struct list_head **list, int *idx,
 	       add_tracepoint(list, idx, sys_name, evt_name);
 }
 
-static int add_tracepoint_multi_sys(struct list_head **list, int *idx,
+static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
 				    char *sys_name, char *evt_name)
 {
 	struct dirent *events_ent;
@@ -452,7 +454,7 @@ static int add_tracepoint_multi_sys(struct list_head **list, int *idx,
 	return ret;
 }
 
-int parse_events_add_tracepoint(struct list_head **list, int *idx,
+int parse_events_add_tracepoint(struct list_head *list, int *idx,
 				char *sys, char *event)
 {
 	int ret;
@@ -507,7 +509,7 @@ do {					\
 	return 0;
 }
 
-int parse_events_add_breakpoint(struct list_head **list, int *idx,
+int parse_events_add_breakpoint(struct list_head *list, int *idx,
 				void *ptr, char *type)
 {
 	struct perf_event_attr attr;
@@ -588,7 +590,7 @@ static int config_attr(struct perf_event_attr *attr,
 	return 0;
 }
 
-int parse_events_add_numeric(struct list_head **list, int *idx,
+int parse_events_add_numeric(struct list_head *list, int *idx,
 			     u32 type, u64 config,
 			     struct list_head *head_config)
 {
@@ -621,7 +623,7 @@ static char *pmu_event_name(struct list_head *head_terms)
 	return NULL;
 }
 
-int parse_events_add_pmu(struct list_head **list, int *idx,
+int parse_events_add_pmu(struct list_head *list, int *idx,
 			 char *name, struct list_head *head_config)
 {
 	struct perf_event_attr attr;
@@ -664,6 +666,7 @@ void parse_events__set_leader(char *name, struct list_head *list)
 	leader->group_name = name ? strdup(name) : NULL;
 }
 
+/* list_event is assumed to point to malloc'ed memory */
 void parse_events_update_lists(struct list_head *list_event,
 			       struct list_head *list_all)
 {
@@ -820,6 +823,32 @@ int parse_events_name(struct list_head *list, char *name)
 	return 0;
 }
 
+static int parse_events__scanner(const char *str, void *data, int start_token);
+
+static int parse_events_fixup(int ret, const char *str, void *data,
+			      int start_token)
+{
+	char *o = strdup(str);
+	char *s = NULL;
+	char *t = o;
+	char *p;
+	int len = 0;
+
+	if (!o)
+		return ret;
+	while ((p = strsep(&t, ",")) != NULL) {
+		if (s)
+			str_append(&s, &len, ",");
+		str_append(&s, &len, "cpu/");
+		str_append(&s, &len, p);
+		str_append(&s, &len, "/");
+	}
+	free(o);
+	if (!s)
+		return -ENOMEM;
+	return parse_events__scanner(s, data, start_token);
+}
+
 static int parse_events__scanner(const char *str, void *data, int start_token)
 {
 	YY_BUFFER_STATE buffer;
@@ -840,6 +869,8 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
 	parse_events__flush_buffer(buffer, scanner);
 	parse_events__delete_buffer(buffer, scanner);
 	parse_events_lex_destroy(scanner);
+	if (ret && !strchr(str, '/'))
+		ret = parse_events_fixup(ret, str, data, start_token);
 	return ret;
 }
 
@@ -1079,6 +1110,8 @@ int print_hwcache_events(const char *event_glob, bool name_only)
 		}
 	}
 
+	if (printed)
+		printf("\n");
 	return printed;
 }
 
@@ -1133,11 +1166,12 @@ void print_events(const char *event_glob, bool name_only)
 
 	print_hwcache_events(event_glob, name_only);
 
+	print_pmu_events(event_glob, name_only);
+
 	if (event_glob != NULL)
 		return;
 
 	if (!name_only) {
-		printf("\n");
 		printf("  %-50s [%s]\n",
 		       "rNNN",
 		       event_type_descriptors[PERF_TYPE_RAW]);
@@ -1237,6 +1271,4 @@ void parse_events__free_terms(struct list_head *terms)
 
 	list_for_each_entry_safe(term, h, terms, list)
 		free(term);
-
-	free(terms);
 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 8a48593..f1cb4c4 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -23,6 +23,7 @@ struct tracepoint_path {
 };
 
 extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
+extern struct tracepoint_path *tracepoint_name_to_path(const char *name);
 extern bool have_tracepoints(struct list_head *evlist);
 
 const char *event_type(int type);
@@ -84,16 +85,16 @@ void parse_events__free_terms(struct list_head *terms);
 int parse_events__modifier_event(struct list_head *list, char *str, bool add);
 int parse_events__modifier_group(struct list_head *list, char *event_mod);
 int parse_events_name(struct list_head *list, char *name);
-int parse_events_add_tracepoint(struct list_head **list, int *idx,
+int parse_events_add_tracepoint(struct list_head *list, int *idx,
 				char *sys, char *event);
-int parse_events_add_numeric(struct list_head **list, int *idx,
+int parse_events_add_numeric(struct list_head *list, int *idx,
 			     u32 type, u64 config,
 			     struct list_head *head_config);
-int parse_events_add_cache(struct list_head **list, int *idx,
+int parse_events_add_cache(struct list_head *list, int *idx,
 			   char *type, char *op_result1, char *op_result2);
-int parse_events_add_breakpoint(struct list_head **list, int *idx,
+int parse_events_add_breakpoint(struct list_head *list, int *idx,
 				void *ptr, char *type);
-int parse_events_add_pmu(struct list_head **list, int *idx,
+int parse_events_add_pmu(struct list_head *list, int *idx,
 			 char *pmu , struct list_head *head_config);
 void parse_events__set_leader(char *name, struct list_head *list);
 void parse_events_update_lists(struct list_head *list_event,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index afc44c1..4eb67ec 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -22,6 +22,13 @@ do { \
 		YYABORT; \
 } while (0)
 
+#define ALLOC_LIST(list) \
+do { \
+	list = malloc(sizeof(*list)); \
+	ABORT_ON(!list);              \
+	INIT_LIST_HEAD(list);         \
+} while (0)
+
 static inc_group_count(struct list_head *list,
 		       struct parse_events_evlist *data)
 {
@@ -196,9 +203,10 @@ event_pmu:
 PE_NAME '/' event_config '/'
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3));
 	parse_events__free_terms($3);
 	$$ = list;
 }
@@ -212,11 +220,12 @@ event_legacy_symbol:
 value_sym '/' event_config '/'
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 	int type = $1 >> 16;
 	int config = $1 & 255;
 
-	ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_numeric(list, &data->idx,
 					  type, config, $3));
 	parse_events__free_terms($3);
 	$$ = list;
@@ -225,11 +234,12 @@ value_sym '/' event_config '/'
 value_sym sep_slash_dc
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 	int type = $1 >> 16;
 	int config = $1 & 255;
 
-	ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_numeric(list, &data->idx,
 					  type, config, NULL));
 	$$ = list;
 }
@@ -238,27 +248,30 @@ event_legacy_cache:
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
 	$$ = list;
 }
 |
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
 	$$ = list;
 }
 |
 PE_NAME_CACHE_TYPE
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
 	$$ = list;
 }
 
@@ -266,9 +279,10 @@ event_legacy_mem:
 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
 					     (void *) $2, $4));
 	$$ = list;
 }
@@ -276,9 +290,10 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
 PE_PREFIX_MEM PE_VALUE sep_dc
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
 					     (void *) $2, NULL));
 	$$ = list;
 }
@@ -287,9 +302,10 @@ event_legacy_tracepoint:
 PE_NAME ':' PE_NAME
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3));
 	$$ = list;
 }
 
@@ -297,9 +313,10 @@ event_legacy_numeric:
 PE_VALUE ':' PE_VALUE
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL));
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL));
 	$$ = list;
 }
 
@@ -307,9 +324,10 @@ event_legacy_raw:
 PE_RAW
 {
 	struct parse_events_evlist *data = _data;
-	struct list_head *list = NULL;
+	struct list_head *list;
 
-	ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_add_numeric(list, &data->idx,
 					  PERF_TYPE_RAW, $1, NULL));
 	$$ = list;
 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 4c6f9c4..bc9d806 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -73,7 +73,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head)
  * located at:
  * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
  */
-static int pmu_format(char *name, struct list_head *format)
+static int pmu_format(const char *name, struct list_head *format)
 {
 	struct stat st;
 	char path[PATH_MAX];
@@ -162,7 +162,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
  * Reading the pmu event aliases definition, which should be located at:
  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
  */
-static int pmu_aliases(char *name, struct list_head *head)
+static int pmu_aliases(const char *name, struct list_head *head)
 {
 	struct stat st;
 	char path[PATH_MAX];
@@ -208,7 +208,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,
  * located at:
  * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
  */
-static int pmu_type(char *name, __u32 *type)
+static int pmu_type(const char *name, __u32 *type)
 {
 	struct stat st;
 	char path[PATH_MAX];
@@ -266,7 +266,7 @@ static void pmu_read_sysfs(void)
 	closedir(dir);
 }
 
-static struct cpu_map *pmu_cpumask(char *name)
+static struct cpu_map *pmu_cpumask(const char *name)
 {
 	struct stat st;
 	char path[PATH_MAX];
@@ -293,7 +293,7 @@ static struct cpu_map *pmu_cpumask(char *name)
 	return cpus;
 }
 
-static struct perf_pmu *pmu_lookup(char *name)
+static struct perf_pmu *pmu_lookup(const char *name)
 {
 	struct perf_pmu *pmu;
 	LIST_HEAD(format);
@@ -330,7 +330,7 @@ static struct perf_pmu *pmu_lookup(char *name)
 	return pmu;
 }
 
-static struct perf_pmu *pmu_find(char *name)
+static struct perf_pmu *pmu_find(const char *name)
 {
 	struct perf_pmu *pmu;
 
@@ -356,7 +356,7 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
 	return NULL;
 }
 
-struct perf_pmu *perf_pmu__find(char *name)
+struct perf_pmu *perf_pmu__find(const char *name)
 {
 	struct perf_pmu *pmu;
 
@@ -564,3 +564,76 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
 	for (b = from; b <= to; b++)
 		set_bit(b, bits);
 }
+
+static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
+			  struct perf_pmu_alias *alias)
+{
+	snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
+	return buf;
+}
+
+static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
+			     struct perf_pmu_alias *alias)
+{
+	snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
+	return buf;
+}
+
+static int cmp_string(const void *a, const void *b)
+{
+	const char * const *as = a;
+	const char * const *bs = b;
+	return strcmp(*as, *bs);
+}
+
+void print_pmu_events(const char *event_glob, bool name_only)
+{
+	struct perf_pmu *pmu;
+	struct perf_pmu_alias *alias;
+	char buf[1024];
+	int printed = 0;
+	int len, j;
+	char **aliases;
+
+	pmu = NULL;
+	len = 0;
+	while ((pmu = perf_pmu__scan(pmu)) != NULL)
+		list_for_each_entry(alias, &pmu->aliases, list)
+			len++;
+	aliases = malloc(sizeof(char *) * len);
+	if (!aliases)
+		return;
+	pmu = NULL;
+	j = 0;
+	while ((pmu = perf_pmu__scan(pmu)) != NULL)
+		list_for_each_entry(alias, &pmu->aliases, list) {
+			char *name = format_alias(buf, sizeof(buf), pmu, alias);
+			bool is_cpu = !strcmp(pmu->name, "cpu");
+
+			if (event_glob != NULL &&
+			    !(strglobmatch(name, event_glob) ||
+			      (!is_cpu && strglobmatch(alias->name,
+						       event_glob))))
+				continue;
+			aliases[j] = name;
+			if (is_cpu && !name_only)
+				aliases[j] = format_alias_or(buf, sizeof(buf),
+							      pmu, alias);
+			aliases[j] = strdup(aliases[j]);
+			j++;
+		}
+	len = j;
+	qsort(aliases, len, sizeof(char *), cmp_string);
+	for (j = 0; j < len; j++) {
+		if (name_only) {
+			printf("%s ", aliases[j]);
+			continue;
+		}
+		printf("  %-50s [Kernel PMU event]\n", aliases[j]);
+		free(aliases[j]);
+		printed++;
+	}
+	if (printed)
+		printf("\n");
+	free(aliases);
+}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 32fe55b..6b2cbe2 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -3,6 +3,7 @@
 
 #include <linux/bitops.h>
 #include <linux/perf_event.h>
+#include <stdbool.h>
 
 enum {
 	PERF_PMU_FORMAT_VALUE_CONFIG,
@@ -21,7 +22,7 @@ struct perf_pmu {
 	struct list_head list;
 };
 
-struct perf_pmu *perf_pmu__find(char *name);
+struct perf_pmu *perf_pmu__find(const char *name);
 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 		     struct list_head *head_terms);
 int perf_pmu__config_terms(struct list_head *formats,
@@ -40,5 +41,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
 
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
+void print_pmu_events(const char *event_glob, bool name_only);
+
 int perf_pmu__test(void);
 #endif /* __PMU_H */
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index eacec85..a85e4ae 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -261,7 +261,8 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
 				    struct perf_sample *sample,
 				    struct perf_evsel *evsel,
 				    struct machine *machine __maybe_unused,
-				    struct addr_location *al)
+				    struct thread *thread,
+					struct addr_location *al)
 {
 	struct format_field *field;
 	static char handler[256];
@@ -272,7 +273,6 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
 	int cpu = sample->cpu;
 	void *data = sample->raw_data;
 	unsigned long long nsecs = sample->time;
-	struct thread *thread = al->thread;
 	char *comm = thread->comm;
 
 	dSP;
@@ -351,7 +351,8 @@ static void perl_process_event_generic(union perf_event *event,
 				       struct perf_sample *sample,
 				       struct perf_evsel *evsel,
 				       struct machine *machine __maybe_unused,
-				       struct addr_location *al __maybe_unused)
+				       struct thread *thread __maybe_unused,
+					   struct addr_location *al __maybe_unused)
 {
 	dSP;
 
@@ -377,10 +378,11 @@ static void perl_process_event(union perf_event *event,
 			       struct perf_sample *sample,
 			       struct perf_evsel *evsel,
 			       struct machine *machine,
-			       struct addr_location *al)
+			       struct thread *thread,
+				   struct addr_location *al)
 {
-	perl_process_tracepoint(event, sample, evsel, machine, al);
-	perl_process_event_generic(event, sample, evsel, machine, al);
+	perl_process_tracepoint(event, sample, evsel, machine, thread, al);
+	perl_process_event_generic(event, sample, evsel, machine, thread, al);
 }
 
 static void run_start_sub(void)
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index e87aa5d..cc75a3c 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -225,6 +225,7 @@ static void python_process_tracepoint(union perf_event *perf_event
 				 struct perf_sample *sample,
 				 struct perf_evsel *evsel,
 				 struct machine *machine __maybe_unused,
+				 struct thread *thread,
 				 struct addr_location *al)
 {
 	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
@@ -238,7 +239,6 @@ static void python_process_tracepoint(union perf_event *perf_event
 	int cpu = sample->cpu;
 	void *data = sample->raw_data;
 	unsigned long long nsecs = sample->time;
-	struct thread *thread = al->thread;
 	char *comm = thread->comm;
 
 	t = PyTuple_New(MAX_FIELDS);
@@ -345,12 +345,12 @@ static void python_process_general_event(union perf_event *perf_event
 					 struct perf_sample *sample,
 					 struct perf_evsel *evsel,
 					 struct machine *machine __maybe_unused,
+					 struct thread *thread,
 					 struct addr_location *al)
 {
 	PyObject *handler, *retval, *t, *dict;
 	static char handler_name[64];
 	unsigned n = 0;
-	struct thread *thread = al->thread;
 
 	/*
 	 * Use the MAX_FIELDS to make the function expandable, though
@@ -404,17 +404,18 @@ static void python_process_event(union perf_event *perf_event,
 				 struct perf_sample *sample,
 				 struct perf_evsel *evsel,
 				 struct machine *machine,
+				 struct thread *thread,
 				 struct addr_location *al)
 {
 	switch (evsel->attr.type) {
 	case PERF_TYPE_TRACEPOINT:
 		python_process_tracepoint(perf_event, sample, evsel,
-					  machine, al);
+					  machine, thread, al);
 		break;
 	/* Reserve for future process_hw/sw/raw APIs */
 	default:
 		python_process_general_event(perf_event, sample, evsel,
-					     machine, al);
+					     machine, thread, al);
 	}
 }
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index cf1fe01..272c9cf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1,4 +1,5 @@
 #include <linux/kernel.h>
+#include <traceevent/event-parse.h>
 
 #include <byteswap.h>
 #include <unistd.h>
@@ -12,7 +13,6 @@
 #include "sort.h"
 #include "util.h"
 #include "cpumap.h"
-#include "event-parse.h"
 #include "perf_regs.h"
 #include "vdso.h"
 
@@ -24,7 +24,7 @@ static int perf_session__open(struct perf_session *self, bool force)
 		self->fd_pipe = true;
 		self->fd = STDIN_FILENO;
 
-		if (perf_session__read_header(self, self->fd) < 0)
+		if (perf_session__read_header(self) < 0)
 			pr_err("incompatible file format (rerun with -v to learn more)");
 
 		return 0;
@@ -56,7 +56,7 @@ static int perf_session__open(struct perf_session *self, bool force)
 		goto out_close;
 	}
 
-	if (perf_session__read_header(self, self->fd) < 0) {
+	if (perf_session__read_header(self) < 0) {
 		pr_err("incompatible file format (rerun with -v to learn more)");
 		goto out_close;
 	}
@@ -193,7 +193,9 @@ void perf_session__delete(struct perf_session *self)
 	vdso__exit();
 }
 
-static int process_event_synth_tracing_data_stub(union perf_event *event
+static int process_event_synth_tracing_data_stub(struct perf_tool *tool
+						 __maybe_unused,
+						 union perf_event *event
 						 __maybe_unused,
 						 struct perf_session *session
 						__maybe_unused)
@@ -202,7 +204,8 @@ static int process_event_synth_tracing_data_stub(union perf_event *event
 	return 0;
 }
 
-static int process_event_synth_attr_stub(union perf_event *event __maybe_unused,
+static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
+					 union perf_event *event __maybe_unused,
 					 struct perf_evlist **pevlist
 					 __maybe_unused)
 {
@@ -238,13 +241,6 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
-static int process_event_type_stub(struct perf_tool *tool __maybe_unused,
-				   union perf_event *event __maybe_unused)
-{
-	dump_printf(": unhandled!\n");
-	return 0;
-}
-
 static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event,
 				  struct perf_session *session);
@@ -271,8 +267,6 @@ static void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->unthrottle = process_event_stub;
 	if (tool->attr == NULL)
 		tool->attr = process_event_synth_attr_stub;
-	if (tool->event_type == NULL)
-		tool->event_type = process_event_type_stub;
 	if (tool->tracing_data == NULL)
 		tool->tracing_data = process_event_synth_tracing_data_stub;
 	if (tool->build_id == NULL)
@@ -921,16 +915,14 @@ static int perf_session__process_user_event(struct perf_session *session, union
 	/* These events are processed right away */
 	switch (event->header.type) {
 	case PERF_RECORD_HEADER_ATTR:
-		err = tool->attr(event, &session->evlist);
+		err = tool->attr(tool, event, &session->evlist);
 		if (err == 0)
 			perf_session__set_id_hdr_size(session);
 		return err;
-	case PERF_RECORD_HEADER_EVENT_TYPE:
-		return tool->event_type(tool, event);
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
 		lseek(session->fd, file_offset, SEEK_SET);
-		return tool->tracing_data(event, session);
+		return tool->tracing_data(tool, event, session);
 	case PERF_RECORD_HEADER_BUILD_ID:
 		return tool->build_id(tool, event, session);
 	case PERF_RECORD_FINISHED_ROUND:
@@ -1091,8 +1083,10 @@ more:
 		perf_event_header__bswap(&event->header);
 
 	size = event->header.size;
-	if (size == 0)
-		size = 8;
+	if (size < sizeof(struct perf_event_header)) {
+		pr_err("bad event header size\n");
+		goto out_err;
+	}
 
 	if (size > cur_size) {
 		void *new = realloc(buf, size);
@@ -1161,8 +1155,12 @@ fetch_mmaped_event(struct perf_session *session,
 	if (session->header.needs_swap)
 		perf_event_header__bswap(&event->header);
 
-	if (head + event->header.size > mmap_size)
+	if (head + event->header.size > mmap_size) {
+		/* We're not fetching the event so swap back again */
+		if (session->header.needs_swap)
+			perf_event_header__bswap(&event->header);
 		return NULL;
+	}
 
 	return event;
 }
@@ -1242,7 +1240,7 @@ more:
 
 	size = event->header.size;
 
-	if (size == 0 ||
+	if (size < sizeof(struct perf_event_header) ||
 	    perf_session__process_event(session, event, tool, file_pos) < 0) {
 		pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
 		       file_offset + head, event->header.size,
@@ -1397,9 +1395,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
 
 	if (symbol_conf.use_callchain && sample->callchain) {
 
-
 		if (machine__resolve_callchain(machine, evsel, al.thread,
-					       sample, NULL) != 0) {
+					       sample, NULL, NULL) != 0) {
 			if (verbose)
 				error("Failed to resolve callchain. Skipping\n");
 			return;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index f3b235e..ad8d3d4 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -37,7 +37,6 @@ struct perf_session {
 	int			fd;
 	bool			fd_pipe;
 	bool			repipe;
-	char			*cwd;
 	struct ordered_samples	ordered_samples;
 	char			filename[1];
 };
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 313a5a7..5f118a0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -7,6 +7,8 @@ const char	default_parent_pattern[] = "^sys_|^do_page_fault";
 const char	*parent_pattern = default_parent_pattern;
 const char	default_sort_order[] = "comm,dso,symbol";
 const char	*sort_order = default_sort_order;
+regex_t		ignore_callees_regex;
+int		have_ignore_callees = 0;
 int		sort__need_collapse = 0;
 int		sort__has_parent = 0;
 int		sort__has_sym = 0;
@@ -55,14 +57,14 @@ static int64_t cmp_null(void *l, void *r)
 static int64_t
 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-	return right->thread->pid - left->thread->pid;
+	return right->thread->tid - left->thread->tid;
 }
 
 static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
 				       size_t size, unsigned int width)
 {
 	return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
-			      self->thread->comm ?: "", self->thread->pid);
+			      self->thread->comm ?: "", self->thread->tid);
 }
 
 struct sort_entry sort_thread = {
@@ -77,7 +79,7 @@ struct sort_entry sort_thread = {
 static int64_t
 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-	return right->thread->pid - left->thread->pid;
+	return right->thread->tid - left->thread->tid;
 }
 
 static int64_t
@@ -872,6 +874,8 @@ static struct sort_dimension common_sort_dimensions[] = {
 	DIM(SORT_PARENT, "parent", sort_parent),
 	DIM(SORT_CPU, "cpu", sort_cpu),
 	DIM(SORT_SRCLINE, "srcline", sort_srcline),
+	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
+	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
 };
 
 #undef DIM
@@ -891,8 +895,6 @@ static struct sort_dimension bstack_sort_dimensions[] = {
 #define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
 
 static struct sort_dimension memory_sort_dimensions[] = {
-	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
-	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
 	DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
 	DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
 	DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 45ac84c..4e80dbd 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -29,6 +29,8 @@ extern const char *sort_order;
 extern const char default_parent_pattern[];
 extern const char *parent_pattern;
 extern const char default_sort_order[];
+extern regex_t ignore_callees_regex;
+extern int have_ignore_callees;
 extern int sort__need_collapse;
 extern int sort__has_parent;
 extern int sort__has_sym;
@@ -87,6 +89,9 @@ struct hist_entry {
 
 	struct hist_entry_diff	diff;
 
+	/* We are added by hists__add_dummy_entry. */
+	bool			dummy;
+
 	/* XXX These two should move to some tree widget lib */
 	u16			row_offset;
 	u16			nr_rows;
@@ -138,6 +143,8 @@ enum sort_type {
 	SORT_PARENT,
 	SORT_CPU,
 	SORT_SRCLINE,
+	SORT_LOCAL_WEIGHT,
+	SORT_GLOBAL_WEIGHT,
 
 	/* branch stack specific sort keys */
 	__SORT_BRANCH_STACK,
@@ -149,9 +156,7 @@ enum sort_type {
 
 	/* memory mode specific sort keys */
 	__SORT_MEMORY_MODE,
-	SORT_LOCAL_WEIGHT = __SORT_MEMORY_MODE,
-	SORT_GLOBAL_WEIGHT,
-	SORT_MEM_DADDR_SYMBOL,
+	SORT_MEM_DADDR_SYMBOL = __SORT_MEMORY_MODE,
 	SORT_MEM_DADDR_DSO,
 	SORT_MEM_LOCKED,
 	SORT_MEM_TLB,
@@ -183,4 +188,6 @@ int setup_sorting(void);
 extern int sort_dimension__add(const char *);
 void sort__setup_elide(FILE *fp);
 
+int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
+
 #endif	/* __PERF_SORT_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 29c7b2c..f0b0c00 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -387,3 +387,27 @@ void *memdup(const void *src, size_t len)
 
 	return p;
 }
+
+/**
+ * str_append - reallocate string and append another
+ * @s: pointer to string pointer
+ * @len: pointer to len (initialized)
+ * @a: string to append.
+ */
+int str_append(char **s, int *len, const char *a)
+{
+	int olen = *s ? strlen(*s) : 0;
+	int nlen = olen + strlen(a) + 1;
+	if (*len < nlen) {
+		*len = *len * 2;
+		if (*len < nlen)
+			*len = nlen;
+		*s = realloc(*s, *len);
+		if (!*s)
+			return -ENOMEM;
+		if (olen == 0)
+			**s = 0;
+	}
+	strcat(*s, a);
+	return 0;
+}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index d5528e1..02718e7 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -888,8 +888,11 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
 	char symfs_vmlinux[PATH_MAX];
 	enum dso_binary_type symtab_type;
 
-	snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s",
-		 symbol_conf.symfs, vmlinux);
+	if (vmlinux[0] == '/')
+		snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
+	else
+		snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s",
+			 symbol_conf.symfs, vmlinux);
 
 	if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
 		symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 40399cb..6feeb88 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,17 +7,17 @@
 #include "util.h"
 #include "debug.h"
 
-struct thread *thread__new(pid_t pid)
+struct thread *thread__new(pid_t tid)
 {
 	struct thread *self = zalloc(sizeof(*self));
 
 	if (self != NULL) {
 		map_groups__init(&self->mg);
-		self->pid = pid;
+		self->tid = tid;
 		self->ppid = -1;
 		self->comm = malloc(32);
 		if (self->comm)
-			snprintf(self->comm, 32, ":%d", self->pid);
+			snprintf(self->comm, 32, ":%d", self->tid);
 	}
 
 	return self;
@@ -57,7 +57,7 @@ int thread__comm_len(struct thread *self)
 
 size_t thread__fprintf(struct thread *thread, FILE *fp)
 {
-	return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) +
+	return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) +
 	       map_groups__fprintf(&thread->mg, verbose, fp);
 }
 
@@ -84,7 +84,7 @@ int thread__fork(struct thread *self, struct thread *parent)
 		if (map_groups__clone(&self->mg, &parent->mg, i) < 0)
 			return -ENOMEM;
 
-	self->ppid = parent->pid;
+	self->ppid = parent->tid;
 
 	return 0;
 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index eeb7ac6..0fe1f9c 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -12,7 +12,7 @@ struct thread {
 		struct list_head node;
 	};
 	struct map_groups	mg;
-	pid_t			pid;
+	pid_t			tid;
 	pid_t			ppid;
 	char			shortname[3];
 	bool			comm_set;
@@ -24,7 +24,7 @@ struct thread {
 
 struct machine;
 
-struct thread *thread__new(pid_t pid);
+struct thread *thread__new(pid_t tid);
 void thread__delete(struct thread *self);
 
 int thread__set_comm(struct thread *self, const char *comm);
@@ -47,4 +47,14 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
 				u8 cpumode, enum map_type type, u64 addr,
 				struct addr_location *al,
 				symbol_filter_t filter);
+
+static inline void *thread__priv(struct thread *thread)
+{
+	return thread->priv;
+}
+
+static inline void thread__set_priv(struct thread *thread, void *p)
+{
+	thread->priv = p;
+}
 #endif	/* __PERF_THREAD_H */
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index b0e1aad..62b16b6 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -18,12 +18,9 @@ typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
 typedef int (*event_op)(struct perf_tool *tool, union perf_event *event,
 			struct perf_sample *sample, struct machine *machine);
 
-typedef int (*event_attr_op)(union perf_event *event,
+typedef int (*event_attr_op)(struct perf_tool *tool,
+			     union perf_event *event,
 			     struct perf_evlist **pevlist);
-typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event);
-
-typedef int (*event_synth_op)(union perf_event *event,
-			      struct perf_session *session);
 
 typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
 			 struct perf_session *session);
@@ -39,8 +36,7 @@ struct perf_tool {
 			throttle,
 			unthrottle;
 	event_attr_op	attr;
-	event_synth_op	tracing_data;
-	event_simple_op	event_type;
+	event_op2	tracing_data;
 	event_op2	finished_round,
 			build_id;
 	bool		ordered_samples;
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 3917eb9..f3c9e55 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -46,65 +46,6 @@
 static int output_fd;
 
 
-static const char *find_debugfs(void)
-{
-	const char *path = perf_debugfs_mount(NULL);
-
-	if (!path)
-		pr_debug("Your kernel does not support the debugfs filesystem");
-
-	return path;
-}
-
-/*
- * Finds the path to the debugfs/tracing
- * Allocates the string and stores it.
- */
-static const char *find_tracing_dir(void)
-{
-	static char *tracing;
-	static int tracing_found;
-	const char *debugfs;
-
-	if (tracing_found)
-		return tracing;
-
-	debugfs = find_debugfs();
-	if (!debugfs)
-		return NULL;
-
-	tracing = malloc(strlen(debugfs) + 9);
-	if (!tracing)
-		return NULL;
-
-	sprintf(tracing, "%s/tracing", debugfs);
-
-	tracing_found = 1;
-	return tracing;
-}
-
-static char *get_tracing_file(const char *name)
-{
-	const char *tracing;
-	char *file;
-
-	tracing = find_tracing_dir();
-	if (!tracing)
-		return NULL;
-
-	file = malloc(strlen(tracing) + strlen(name) + 2);
-	if (!file)
-		return NULL;
-
-	sprintf(file, "%s/%s", tracing, name);
-	return file;
-}
-
-static void put_tracing_file(char *file)
-{
-	free(file);
-}
-
 int bigendian(void)
 {
 	unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
@@ -160,7 +101,7 @@ out:
 	return err;
 }
 
-static int read_header_files(void)
+static int record_header_files(void)
 {
 	char *path;
 	struct stat st;
@@ -299,7 +240,7 @@ out:
 	return err;
 }
 
-static int read_ftrace_files(struct tracepoint_path *tps)
+static int record_ftrace_files(struct tracepoint_path *tps)
 {
 	char *path;
 	int ret;
@@ -328,7 +269,7 @@ static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)
 	return false;
 }
 
-static int read_event_files(struct tracepoint_path *tps)
+static int record_event_files(struct tracepoint_path *tps)
 {
 	struct dirent *dent;
 	struct stat st;
@@ -403,7 +344,7 @@ out:
 	return err;
 }
 
-static int read_proc_kallsyms(void)
+static int record_proc_kallsyms(void)
 {
 	unsigned int size;
 	const char *path = "/proc/kallsyms";
@@ -421,7 +362,7 @@ static int read_proc_kallsyms(void)
 	return record_file(path, 4);
 }
 
-static int read_ftrace_printk(void)
+static int record_ftrace_printk(void)
 {
 	unsigned int size;
 	char *path;
@@ -473,12 +414,27 @@ get_tracepoints_path(struct list_head *pattrs)
 		if (pos->attr.type != PERF_TYPE_TRACEPOINT)
 			continue;
 		++nr_tracepoints;
+
+		if (pos->name) {
+			ppath->next = tracepoint_name_to_path(pos->name);
+			if (ppath->next)
+				goto next;
+
+			if (strchr(pos->name, ':') == NULL)
+				goto try_id;
+
+			goto error;
+		}
+
+try_id:
 		ppath->next = tracepoint_id_to_path(pos->attr.config);
 		if (!ppath->next) {
+error:
 			pr_debug("No memory to alloc tracepoints list\n");
 			put_tracepoints_path(&path);
 			return NULL;
 		}
+next:
 		ppath = ppath->next;
 	}
 
@@ -520,8 +476,6 @@ static int tracing_data_header(void)
 	else
 		buf[0] = 0;
 
-	read_trace_init(buf[0], buf[0]);
-
 	if (write(output_fd, buf, 1) != 1)
 		return -1;
 
@@ -583,19 +537,19 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
 	err = tracing_data_header();
 	if (err)
 		goto out;
-	err = read_header_files();
+	err = record_header_files();
 	if (err)
 		goto out;
-	err = read_ftrace_files(tps);
+	err = record_ftrace_files(tps);
 	if (err)
 		goto out;
-	err = read_event_files(tps);
+	err = record_event_files(tps);
 	if (err)
 		goto out;
-	err = read_proc_kallsyms();
+	err = record_proc_kallsyms();
 	if (err)
 		goto out;
-	err = read_ftrace_printk();
+	err = record_ftrace_printk();
 
 out:
 	/*
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 4454835..fe7a27d 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -28,12 +28,6 @@
 #include "util.h"
 #include "trace-event.h"
 
-int header_page_size_size;
-int header_page_ts_size;
-int header_page_data_offset;
-
-bool latency_format;
-
 struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
 {
 	struct pevent *pevent = pevent_alloc();
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index af215c0..f211227 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -39,10 +39,6 @@
 
 static int input_fd;
 
-int file_bigendian;
-int host_bigendian;
-static int long_size;
-
 static ssize_t trace_data_size;
 static bool repipe;
 
@@ -216,7 +212,7 @@ static int read_ftrace_printk(struct pevent *pevent)
 static int read_header_files(struct pevent *pevent)
 {
 	unsigned long long size;
-	char *header_event;
+	char *header_page;
 	char buf[BUFSIZ];
 	int ret = 0;
 
@@ -229,13 +225,26 @@ static int read_header_files(struct pevent *pevent)
 	}
 
 	size = read8(pevent);
-	skip(size);
 
-	/*
-	 * The size field in the page is of type long,
-	 * use that instead, since it represents the kernel.
-	 */
-	long_size = header_page_size_size;
+	header_page = malloc(size);
+	if (header_page == NULL)
+		return -1;
+
+	if (do_read(header_page, size) < 0) {
+		pr_debug("did not read header page");
+		free(header_page);
+		return -1;
+	}
+
+	if (!pevent_parse_header_page(pevent, header_page, size,
+				      pevent_get_long_size(pevent))) {
+		/*
+		 * The commit field in the page is of type long,
+		 * use that instead, since it represents the kernel.
+		 */
+		pevent_set_long_size(pevent, pevent->header_page_size_size);
+	}
+	free(header_page);
 
 	if (do_read(buf, 13) < 0)
 		return -1;
@@ -246,14 +255,8 @@ static int read_header_files(struct pevent *pevent)
 	}
 
 	size = read8(pevent);
-	header_event = malloc(size);
-	if (header_event == NULL)
-		return -1;
-
-	if (do_read(header_event, size) < 0)
-		ret = -1;
+	skip(size);
 
-	free(header_event);
 	return ret;
 }
 
@@ -349,6 +352,10 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
 	int show_funcs = 0;
 	int show_printk = 0;
 	ssize_t size = -1;
+	int file_bigendian;
+	int host_bigendian;
+	int file_long_size;
+	int file_page_size;
 	struct pevent *pevent;
 	int err;
 
@@ -391,12 +398,15 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
 
 	if (do_read(buf, 1) < 0)
 		goto out;
-	long_size = buf[0];
+	file_long_size = buf[0];
 
-	page_size = read4(pevent);
-	if (!page_size)
+	file_page_size = read4(pevent);
+	if (!file_page_size)
 		goto out;
 
+	pevent_set_long_size(pevent, file_long_size);
+	pevent_set_page_size(pevent, file_page_size);
+
 	err = read_header_files(pevent);
 	if (err)
 		goto out;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 8715a10..95199e4 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -39,7 +39,8 @@ static void process_event_unsupported(union perf_event *event __maybe_unused,
 				      struct perf_sample *sample __maybe_unused,
 				      struct perf_evsel *evsel __maybe_unused,
 				      struct machine *machine __maybe_unused,
-				      struct addr_location *al __maybe_unused)
+				      struct thread *thread __maybe_unused,
+					  struct addr_location *al __maybe_unused)
 {
 }
 
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 1978c39..fafe1a4 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -1,32 +1,18 @@
 #ifndef _PERF_UTIL_TRACE_EVENT_H
 #define _PERF_UTIL_TRACE_EVENT_H
 
+#include <traceevent/event-parse.h>
 #include "parse-events.h"
-#include "event-parse.h"
 #include "session.h"
 
 struct machine;
 struct perf_sample;
 union perf_event;
 struct perf_tool;
+struct thread;
 
-extern int header_page_size_size;
-extern int header_page_ts_size;
-extern int header_page_data_offset;
-
-extern bool latency_format;
 extern struct pevent *perf_pevent;
 
-enum {
-	RINGBUF_TYPE_PADDING		= 29,
-	RINGBUF_TYPE_TIME_EXTEND	= 30,
-	RINGBUF_TYPE_TIME_STAMP		= 31,
-};
-
-#ifndef TS_SHIFT
-#define TS_SHIFT		27
-#endif
-
 int bigendian(void);
 
 struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
@@ -83,7 +69,8 @@ struct scripting_ops {
 			       struct perf_sample *sample,
 			       struct perf_evsel *evsel,
 			       struct machine *machine,
-			       struct addr_location *al);
+			       struct thread *thread,
+				   struct addr_location *al);
 	int (*generate_script) (struct pevent *pevent, const char *outfile);
 };
 
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 59d868a..9a06584 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -269,3 +269,62 @@ void perf_debugfs_set_path(const char *mntpt)
 	snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
 	set_tracing_events_path(mntpt);
 }
+
+static const char *find_debugfs(void)
+{
+	const char *path = perf_debugfs_mount(NULL);
+
+	if (!path)
+		fprintf(stderr, "Your kernel does not support the debugfs filesystem");
+
+	return path;
+}
+
+/*
+ * Finds the path to the debugfs/tracing
+ * Allocates the string and stores it.
+ */
+const char *find_tracing_dir(void)
+{
+	static char *tracing;
+	static int tracing_found;
+	const char *debugfs;
+
+	if (tracing_found)
+		return tracing;
+
+	debugfs = find_debugfs();
+	if (!debugfs)
+		return NULL;
+
+	tracing = malloc(strlen(debugfs) + 9);
+	if (!tracing)
+		return NULL;
+
+	sprintf(tracing, "%s/tracing", debugfs);
+
+	tracing_found = 1;
+	return tracing;
+}
+
+char *get_tracing_file(const char *name)
+{
+	const char *tracing;
+	char *file;
+
+	tracing = find_tracing_dir();
+	if (!tracing)
+		return NULL;
+
+	file = malloc(strlen(tracing) + strlen(name) + 2);
+	if (!file)
+		return NULL;
+
+	sprintf(file, "%s/%s", tracing, name);
+	return file;
+}
+
+void put_tracing_file(char *file)
+{
+	free(file);
+}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2732fad..cc1574e 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -80,6 +80,9 @@ extern char buildid_dir[];
 extern char tracing_events_path[];
 extern void perf_debugfs_set_path(const char *mountpoint);
 const char *perf_debugfs_mount(const char *mountpoint);
+const char *find_tracing_dir(void);
+char *get_tracing_file(const char *name);
+void put_tracing_file(char *file);
 
 /* On most systems <limits.h> would have given us this, but
  * not on some systems (e.g. GNU/Hurd).
diff --git a/tools/power/fspin/Makefile b/tools/power/fspin/Makefile
new file mode 100644
index 0000000..5274007
--- /dev/null
+++ b/tools/power/fspin/Makefile
@@ -0,0 +1,21 @@
+CC		= $(CROSS_COMPILE)gcc
+BUILD_OUTPUT	:= $(PWD)
+PREFIX		:= /usr
+DESTDIR		:=
+
+fspin : fspin.c
+CFLAGS +=	-Wall
+
+%: %.c
+	@mkdir -p $(BUILD_OUTPUT)
+	$(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ -lpthread
+
+.PHONY : clean
+clean :
+	@rm -f $(BUILD_OUTPUT)/fspin
+
+install : fspin
+	install -d  $(DESTDIR)$(PREFIX)/bin
+	install $(BUILD_OUTPUT)/fspin $(DESTDIR)$(PREFIX)/bin/fspin
+	install -d  $(DESTDIR)$(PREFIX)/share/man/man1
+	install fspin.1 $(DESTDIR)$(PREFIX)/share/man/man1
diff --git a/tools/power/fspin/fspin.1 b/tools/power/fspin/fspin.1
new file mode 100644
index 0000000..b57308e
--- /dev/null
+++ b/tools/power/fspin/fspin.1
@@ -0,0 +1,68 @@
+.\"  This page Copyright (C) 2013 Len Brown <len.brown@intel.com>
+.\"  Distributed under the GPL, Copyleft 1994.
+.TH FSPIN 8
+.SH NAME
+fspin \- simple workload for power experiments
+.SH SYNOPSIS
+.ft B
+.B fspin
+.RB [ "\-v" ]
+.RB [ "\-i iterations" ]
+.RB [ "\-s sec_per_iteration" ]
+.RB [ "\-t threads" ]
+.RB [ "\-b bin_to_cpus" ]
+.RB [ "\-m memory (b|k|m)" ]
+.br
+.SH DESCRIPTION
+\fBfspin\fP
+heats up the hardware by running a
+floating-point spin loop per processor.
+Every
+.I interval_sec
+fspin presents the sum of the work completed
+by all threads.
+.SS Options
+.PP
+\fB-v\fP increases verbosity.
+By default, fspin prints only the quantity work completed.
+.PP
+\fB-s sec_per_iteration\fP
+Print the indicator of work completed every
+sec_per_interval seconds.  By default, 5 sec.
+.PP
+\fB-t threads\fP
+Create
+.I threads
+software threads.  Default is number of
+logical processors available, or if '-b' option is used,
+one thread per bound processor.
+.PP
+\fB-b bind_to_cpus\fP
+Bind the threads to the indicated list of comma-separated CPU numbers.
+A range of CPUs can be specified by using '-'.
+.PP
+\fB-i iterations\fP
+Exit after
+.I iterations
+and print total of work completed.
+Default is to continue running forever, printing work per iteration/sec.
+.PP
+\fB-m memory\fP
+Allocate arrays of 
+.I memory_size,
+which is followed by a modifier b|k|m, for bytes, kilobytes, or megabytes,
+respectively.  Default is 512 bytes, which will spin in-cache.
+Increase this number to exercise larger caches and memory.
+
+.SH WHAT FSPIN IS NOT
+Fspin is just a simple tool,
+and has not be characterized as a
+.I performance benchmark.
+Fspin is not a
+.I power virus for cooling HW design,
+as there are better tools, specialized for that purpose.
+
+.PP
+.SH AUTHORS
+.nf
+Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/fspin/fspin.c b/tools/power/fspin/fspin.c
new file mode 100644
index 0000000..38288c1
--- /dev/null
+++ b/tools/power/fspin/fspin.c
@@ -0,0 +1,443 @@
+/*
+ * fspin.c - user utility to burn CPU cycles, thrash the cache and memory
+ *
+ * Copyright (c) 2013, Intel Corporation.
+ * Len Brown <len.brown@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * Creates one thread per logical processor (override with -t).
+ * Threads run on any processor (override with -b).
+ * Each thread allocates and initializes its own data.
+ * Then it processes the data using an infinite DAXPY loop:
+ * Double precision Y[i] = A*X[i] + Y[i]
+ *
+ * The parent thread wakes up every reporting interval,
+ * (override 5 sec default with -i),
+ * sums up and prints aggregate performance.
+ *
+ * The actual computation is somewhat arbitrary, if not random.
+ * The performance number is intended only to be compared to itself
+ * on the same machine, to illustrate how various power limiting
+ * techniques impact performance.
+ */
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <sched.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#define BANNER "fspin v1.1, April 7, 2013 - Len Brown <len.brown@intel.com>"
+
+#define handle_error_en(en, msg) \
+	do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
+
+#define handle_error(msg) \
+	do { perror(msg); exit(EXIT_FAILURE); } while (0)
+
+struct thread_info {		/* Used as argument to spin_loop() */
+	pthread_t thread_id;	/* ID returned by pthread_create() */
+	int thread_num;		/* Application-defined thread # */
+};
+
+struct padded {
+	double counter;	/* 8 bytes */
+	double pad[(32 - 1)];	/* round up to 256 byte line */
+} *thread_data;
+
+int num_threads;
+int thread_num_override;
+int data_bytes = 512;
+int nrcpus = 64;
+int sec_per_interval = 5;	/* seconds */
+int iterations;
+int verbose;
+int do_binding;
+
+cpu_set_t *cpu_affinity_set;
+size_t cpu_affinity_setsize;
+
+void
+allocate_cpusets()
+{
+	/*
+	 * Allocate and initialize cpu_affinity_set
+	 */
+	cpu_affinity_set = CPU_ALLOC(nrcpus);
+	if (cpu_affinity_set == NULL) {
+		perror("CPU_ALLOC");
+		exit(3);
+	}
+	cpu_affinity_setsize = CPU_ALLOC_SIZE(nrcpus);
+	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
+}
+
+void
+bind_to_cpus()
+{
+	if (!do_binding)
+		return;
+
+	if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) {
+		fprintf(stderr, "bind_to_cpus() failed\n");
+		perror("sched_setaffinity");
+		exit(-1);
+	}
+}
+
+int get_num_cpus()
+{
+	cpu_set_t *mask;
+	size_t size;
+	int num_cpus;
+
+realloc:
+	mask = CPU_ALLOC(nrcpus);
+	size = CPU_ALLOC_SIZE(nrcpus);
+	CPU_ZERO_S(size, mask);
+	if (sched_getaffinity(0, size, mask) == -1) {
+		CPU_FREE(mask);
+		if (errno == EINVAL &&
+			nrcpus < (1024 << 8)) {
+			nrcpus = nrcpus << 2;
+			goto realloc;
+		}
+		perror("sched_getaffinity");
+		return -1;
+	}
+
+	num_cpus = CPU_COUNT_S(size, mask);
+
+	CPU_FREE(mask);
+
+	return num_cpus;
+}
+
+static void *spin_loop(void *arg)
+{
+	struct thread_info *tinfo = (struct thread_info *)arg;
+	double *x, *y;
+	int i = 0;
+	int data_entries = data_bytes / sizeof(double);
+	unsigned long long bitmask = random();
+
+		
+	x = malloc(data_bytes);
+	y = malloc(data_bytes);
+
+	if (x == NULL || y == NULL) {
+		perror("malloc");
+		exit(-1);
+	}
+
+	/*
+	 * seed data array with random bits
+	 */
+	for (i = 0; i < data_entries; ++i) {
+		x[i] = 1.0 + i * bitmask;
+		y[i] = 1.0 + i * bitmask;
+	}
+
+	for (i = 0; ; i++) {
+
+		double a = 3.1415926535 * i;
+
+		y[i] = a * x[i] + y[i];		/* DAXPY */
+
+		thread_data[tinfo->thread_num].counter++;
+
+		if (i >= data_entries)
+			i = 0;
+	}
+	/* not reached */
+}
+
+void usage()
+{
+	fprintf(stderr,
+		"Usage: fspin [-v][-s sec_per_iteration][-i iterations][-t num_threads][-b cpu_list][-m memory(b|k|m)]\n");
+	fprintf(stderr, "\twhere 'cpu_list' is comma and dash separated numbers with no spaces\n");
+	exit(EXIT_FAILURE);
+}
+
+void parse_error(char *string, char c)
+{
+	fprintf(stderr, "parse error on '%s' at '%c'\n", string, c);
+	usage();
+}
+
+int add_cpu_to_bind_mask(int cpu) {
+	static int num_added;
+
+	/* check if cpu is valid */
+	if (cpu < 0 || cpu > nrcpus) {
+		fprintf(stderr, "invalid cpu %d\n", cpu);
+		exit(1);
+	}
+
+	if (CPU_ISSET_S(cpu, cpu_affinity_setsize, cpu_affinity_set)) {
+		fprintf(stderr, "can't bind to cpu %d more than once\n", cpu);
+		exit(1);
+	}
+
+	/* add cpu to set */
+	CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
+
+	if (verbose)
+		printf("%d, ", cpu);
+
+	num_added += 1;
+
+	return num_added;
+}
+
+
+int
+parse_bind_cpu_list(char *cpu_list)
+{
+	char *p;
+	int range_next = -1;
+	int total_cpus_added = 0;
+
+	allocate_cpusets();
+
+	for(p = cpu_list; *p != '\0'; ) {
+		int num, retval;
+
+		/* remaining list must start w/ valid cpu number */
+
+		if (!isdigit(*p))
+			parse_error(p, *p);
+
+		retval = sscanf(p, "%u", &num);
+		if (retval == EOF)
+			usage();
+		else if (retval == 0)
+			parse_error(p, *p);
+
+		if (range_next >= 0) {
+			if (num <= range_next)	/* range must be low to high */
+				parse_error(p, *p);
+
+			for ( ; range_next < num; range_next++)
+				total_cpus_added = add_cpu_to_bind_mask(range_next);
+
+			range_next = -1;
+		}
+
+		total_cpus_added = add_cpu_to_bind_mask(num);
+
+		while (isdigit(*p))
+			p++;
+
+		switch (*p) {
+		case ',':
+			p++;
+			continue;
+		case '-':
+			range_next = num + 1;
+			p++;
+			continue;
+		}
+
+	}
+	return total_cpus_added;
+}
+
+int parse_memory_param(char *p)
+{
+	int bytes;
+	char units;
+
+	if (2 != sscanf(p, "%d%c", &bytes, &units)) {
+		fprintf(stderr, "failed to parse -m\n");
+		usage();
+	}
+	switch (units) {
+	case 'b':
+	case 'B':
+		break;
+	case 'k':
+	case 'K':
+		bytes *= 1024;
+		break;
+	case 'm':
+	case 'M':
+		bytes *= 1024*1024;
+		break;
+	case 'g':
+	case 'G':
+		bytes *= 1024*1024*1024;
+		break;
+	default:
+		fprintf(stderr, "-m: bad memory units, use b, k, m, g\n");
+	
+	}
+	return bytes;
+	
+}
+
+void parse_args(int argc, char *argv[])
+{
+	int opt;
+
+	nrcpus = get_num_cpus();
+
+	while ((opt = getopt(argc, argv, "s:i:t:b:m:v")) != -1) {
+		switch (opt) {
+		case 's':
+			sec_per_interval = atoi(optarg);
+			if (verbose)
+				printf("sec_per_interval %d\n", sec_per_interval);
+			break;
+		case 'i':
+			iterations = atoi(optarg);
+			if (verbose)
+				printf("iterations %d\n", iterations);
+			break;
+		case 't':
+			thread_num_override = atoi(optarg);
+			if (verbose)
+				printf("Thread Count Override: %d\n", thread_num_override);
+			break;
+		case 'b':
+			do_binding = parse_bind_cpu_list(optarg);
+			if (verbose)
+				printf("Binding to %d CPUs.\n", do_binding);
+			break;
+		case 'm':
+			data_bytes = parse_memory_param(optarg);
+			if (verbose)
+				printf("Memory Override: %d\n", data_bytes);
+			break;
+		case 'v':
+			verbose++;
+			break;
+		default:	/* '?' */
+			usage();	/* does not return */
+		}
+	}
+}
+
+unsigned long long lsum_old;
+
+
+struct thread_info *tinfo;
+pthread_attr_t attr;
+
+void create_threads()
+{
+	int s, tnum;
+
+	if (thread_num_override)
+		num_threads = thread_num_override;
+	else if (do_binding)
+		num_threads = do_binding;
+	else
+		num_threads = nrcpus;
+
+	thread_data = calloc(num_threads, sizeof(struct padded));
+	if (thread_data == NULL)
+		handle_error("calloc");
+
+	/* Initialize thread creation attributes */
+
+	s = pthread_attr_init(&attr);
+	if (s != 0)
+		handle_error_en(s, "pthread_attr_init");
+
+	/* Allocate memory for pthread_create() arguments */
+
+	tinfo = calloc(num_threads, sizeof(struct thread_info));
+	if (tinfo == NULL)
+		handle_error("calloc");
+
+	for (tnum = 0; tnum < num_threads; tnum++) {
+		tinfo[tnum].thread_num = tnum;
+
+		/* The pthread_create() call stores the thread ID into
+		 * corresponding element of tinfo[]
+		 */
+
+		s = pthread_create(&tinfo[tnum].thread_id, &attr,
+				   &spin_loop, &tinfo[tnum]);
+		if (s != 0)
+			handle_error_en(s, "pthread_create");
+	}
+	printf("%d threads created\n", num_threads);
+	return;
+}
+
+
+void monitor_threads()
+{
+	struct timespec ts;
+	struct timeval tv_old, tv_new, tv_delta;
+	int i, j;
+	double interval_float;
+	unsigned long long lsum;
+
+	ts.tv_sec = sec_per_interval;
+	ts.tv_nsec = 0;
+	gettimeofday(&tv_old, (struct timezone *)NULL);
+
+	for (i = 0; iterations ? i < iterations : 1 ; i++) {
+
+		if (nanosleep(&ts, NULL) != 0) {
+			perror("nanosleep");
+			exit(-1);
+		}
+
+		for (j = 0, lsum = 0; j < num_threads; ++j)
+			lsum += thread_data[j].counter;
+
+		gettimeofday(&tv_new, NULL);
+		timersub(&tv_new, &tv_old, &tv_delta);
+
+		interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
+		printf("%.2f\n", (lsum - lsum_old)/interval_float/1000000);
+
+		tv_old = tv_new;
+		lsum_old = lsum;
+	}
+	/* summary */
+	for (j = 0, lsum = 0; j < num_threads; ++j) {
+		printf("%d %.2f\n", j, thread_data[j].counter/1000000.0);
+		lsum += thread_data[j].counter;
+	}
+	printf("Total %.2f\n", lsum/1000000.0);
+	
+}
+
+
+void print_banner()
+{
+	puts(BANNER);
+}
+
+int main(int argc, char *argv[])
+{
+	parse_args(argc, argv);
+
+
+	print_banner();
+
+	bind_to_cpus();
+
+	create_threads();
+
+	monitor_threads();	/* never returns */
+
+	return 0;
+}
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 4cb14ca..9f3eae2 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -8,6 +8,7 @@ TARGETS += net
 TARGETS += ptrace
 TARGETS += timers
 TARGETS += vm
+TARGETS += powerpc
 
 all:
 	for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
new file mode 100644
index 0000000..bd24ae5
--- /dev/null
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -0,0 +1,39 @@
+# Makefile for powerpc selftests
+
+# ARCH can be overridden by the user for cross compiling
+ARCH ?= $(shell uname -m)
+ARCH := $(shell echo $(ARCH) | sed -e s/ppc.*/powerpc/)
+
+ifeq ($(ARCH),powerpc)
+
+GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
+
+CC := $(CROSS_COMPILE)$(CC)
+CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
+
+export CC CFLAGS
+
+TARGETS = pmu
+
+endif
+
+all:
+	@for TARGET in $(TARGETS); do \
+		$(MAKE) -C $$TARGET all; \
+	done;
+
+run_tests: all
+	@for TARGET in $(TARGETS); do \
+		$(MAKE) -C $$TARGET run_tests; \
+	done;
+
+clean:
+	@for TARGET in $(TARGETS); do \
+		$(MAKE) -C $$TARGET clean; \
+	done;
+	rm -f tags
+
+tags:
+	find . -name '*.c' -o -name '*.h' | xargs ctags
+
+.PHONY: all run_tests clean tags
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
new file mode 100644
index 0000000..e80c42a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "subunit.h"
+#include "utils.h"
+
+#define TIMEOUT		120
+#define KILL_TIMEOUT	5
+
+
+int run_test(int (test_function)(void), char *name)
+{
+	bool terminated;
+	int rc, status;
+	pid_t pid;
+
+	/* Make sure output is flushed before forking */
+	fflush(stdout);
+
+	pid = fork();
+	if (pid == 0) {
+		exit(test_function());
+	} else if (pid == -1) {
+		perror("fork");
+		return 1;
+	}
+
+	/* Wake us up in timeout seconds */
+	alarm(TIMEOUT);
+	terminated = false;
+
+wait:
+	rc = waitpid(pid, &status, 0);
+	if (rc == -1) {
+		if (errno != EINTR) {
+			printf("unknown error from waitpid\n");
+			return 1;
+		}
+
+		if (terminated) {
+			printf("!! force killing %s\n", name);
+			kill(pid, SIGKILL);
+			return 1;
+		} else {
+			printf("!! killing %s\n", name);
+			kill(pid, SIGTERM);
+			terminated = true;
+			alarm(KILL_TIMEOUT);
+			goto wait;
+		}
+	}
+
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	else {
+		if (WIFSIGNALED(status))
+			printf("!! child died by signal %d\n", WTERMSIG(status));
+		else
+			printf("!! child died by unknown cause\n");
+
+		status = 1; /* Signal or other */
+	}
+
+	return status;
+}
+
+static void alarm_handler(int signum)
+{
+	/* Jut wake us up from waitpid */
+}
+
+static struct sigaction alarm_action = {
+	.sa_handler = alarm_handler,
+};
+
+int test_harness(int (test_function)(void), char *name)
+{
+	int rc;
+
+	test_start(name);
+	test_set_git_version(GIT_VERSION);
+
+	if (sigaction(SIGALRM, &alarm_action, NULL)) {
+		perror("sigaction");
+		test_error(name);
+		return 1;
+	}
+
+	rc = run_test(test_function, name);
+
+	test_finish(name, rc);
+
+	return rc;
+}
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
new file mode 100644
index 0000000..7216f00
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -0,0 +1,23 @@
+noarg:
+	$(MAKE) -C ../
+
+PROGS := count_instructions
+EXTRA_SOURCES := ../harness.c event.c
+
+all: $(PROGS)
+
+$(PROGS): $(EXTRA_SOURCES)
+
+# loop.S can only be built 64-bit
+count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
+	$(CC) $(CFLAGS) -m64 -o $@ $^
+
+run_tests: all
+	@-for PROG in $(PROGS); do \
+		./$$PROG; \
+	done;
+
+clean:
+	rm -f $(PROGS) loop.o
+
+.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/pmu/count_instructions.c b/tools/testing/selftests/powerpc/pmu/count_instructions.c
new file mode 100644
index 0000000..312b4f0
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/count_instructions.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/prctl.h>
+
+#include "event.h"
+#include "utils.h"
+
+extern void thirty_two_instruction_loop(u64 loops);
+
+static void setup_event(struct event *e, u64 config, char *name)
+{
+	event_init_opts(e, config, PERF_TYPE_HARDWARE, name);
+
+	e->attr.disabled = 1;
+	e->attr.exclude_kernel = 1;
+	e->attr.exclude_hv = 1;
+	e->attr.exclude_idle = 1;
+}
+
+static int do_count_loop(struct event *events, u64 instructions,
+			 u64 overhead, bool report)
+{
+	s64 difference, expected;
+	double percentage;
+
+	prctl(PR_TASK_PERF_EVENTS_ENABLE);
+
+	/* Run for 1M instructions */
+	thirty_two_instruction_loop(instructions >> 5);
+
+	prctl(PR_TASK_PERF_EVENTS_DISABLE);
+
+	event_read(&events[0]);
+	event_read(&events[1]);
+
+	expected = instructions + overhead;
+	difference = events[0].result.value - expected;
+	percentage = (double)difference / events[0].result.value * 100;
+
+	if (report) {
+		event_report(&events[0]);
+		event_report(&events[1]);
+
+		printf("Looped for %llu instructions, overhead %llu\n", instructions, overhead);
+		printf("Expected %llu\n", expected);
+		printf("Actual   %llu\n", events[0].result.value);
+		printf("Delta    %lld, %f%%\n", difference, percentage);
+	}
+
+	event_reset(&events[0]);
+	event_reset(&events[1]);
+
+	if (difference < 0)
+		difference = -difference;
+
+	/* Tolerate a difference below 0.0001 % */
+	difference *= 10000 * 100;
+	if (difference / events[0].result.value)
+		return -1;
+
+	return 0;
+}
+
+/* Count how many instructions it takes to do a null loop */
+static u64 determine_overhead(struct event *events)
+{
+	u64 current, overhead;
+	int i;
+
+	do_count_loop(events, 0, 0, false);
+	overhead = events[0].result.value;
+
+	for (i = 0; i < 100; i++) {
+		do_count_loop(events, 0, 0, false);
+		current = events[0].result.value;
+		if (current < overhead) {
+			printf("Replacing overhead %llu with %llu\n", overhead, current);
+			overhead = current;
+		}
+	}
+
+	return overhead;
+}
+
+static int count_instructions(void)
+{
+	struct event events[2];
+	u64 overhead;
+
+	setup_event(&events[0], PERF_COUNT_HW_INSTRUCTIONS, "instructions");
+	setup_event(&events[1], PERF_COUNT_HW_CPU_CYCLES, "cycles");
+
+	if (event_open(&events[0])) {
+		perror("perf_event_open");
+		return -1;
+	}
+
+	if (event_open_with_group(&events[1], events[0].fd)) {
+		perror("perf_event_open");
+		return -1;
+	}
+
+	overhead = determine_overhead(events);
+	printf("Overhead of null loop: %llu instructions\n", overhead);
+
+	/* Run for 1M instructions */
+	FAIL_IF(do_count_loop(events, 0x100000, overhead, true));
+
+	/* Run for 10M instructions */
+	FAIL_IF(do_count_loop(events, 0xa00000, overhead, true));
+
+	/* Run for 100M instructions */
+	FAIL_IF(do_count_loop(events, 0x6400000, overhead, true));
+
+	/* Run for 1G instructions */
+	FAIL_IF(do_count_loop(events, 0x40000000, overhead, true));
+
+	event_close(&events[0]);
+	event_close(&events[1]);
+
+	return 0;
+}
+
+int main(void)
+{
+	return test_harness(count_instructions, "count_instructions");
+}
diff --git a/tools/testing/selftests/powerpc/pmu/event.c b/tools/testing/selftests/powerpc/pmu/event.c
new file mode 100644
index 0000000..2b2d11d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/event.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+
+#include "event.h"
+
+
+int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
+		int group_fd, unsigned long flags)
+{
+	return syscall(__NR_perf_event_open, attr, pid, cpu,
+			   group_fd, flags);
+}
+
+void event_init_opts(struct event *e, u64 config, int type, char *name)
+{
+	memset(e, 0, sizeof(*e));
+
+	e->name = name;
+
+	e->attr.type = type;
+	e->attr.config = config;
+	e->attr.size = sizeof(e->attr);
+	/* This has to match the structure layout in the header */
+	e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \
+				  PERF_FORMAT_TOTAL_TIME_RUNNING;
+}
+
+void event_init_named(struct event *e, u64 config, char *name)
+{
+	event_init_opts(e, config, PERF_TYPE_RAW, name);
+}
+
+#define PERF_CURRENT_PID	0
+#define PERF_NO_CPU		-1
+#define PERF_NO_GROUP		-1
+
+int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd)
+{
+	e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0);
+	if (e->fd == -1) {
+		perror("perf_event_open");
+		return -1;
+	}
+
+	return 0;
+}
+
+int event_open_with_group(struct event *e, int group_fd)
+{
+	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd);
+}
+
+int event_open(struct event *e)
+{
+	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP);
+}
+
+void event_close(struct event *e)
+{
+	close(e->fd);
+}
+
+int event_reset(struct event *e)
+{
+	return ioctl(e->fd, PERF_EVENT_IOC_RESET);
+}
+
+int event_read(struct event *e)
+{
+	int rc;
+
+	rc = read(e->fd, &e->result, sizeof(e->result));
+	if (rc != sizeof(e->result)) {
+		fprintf(stderr, "read error on event %p!\n", e);
+		return -1;
+	}
+
+	return 0;
+}
+
+void event_report_justified(struct event *e, int name_width, int result_width)
+{
+	printf("%*s: result %*llu ", name_width, e->name, result_width,
+	       e->result.value);
+
+	if (e->result.running == e->result.enabled)
+		printf("running/enabled %llu\n", e->result.running);
+	else
+		printf("running %llu enabled %llu\n", e->result.running,
+			e->result.enabled);
+}
+
+void event_report(struct event *e)
+{
+	event_report_justified(e, 0, 0);
+}
diff --git a/tools/testing/selftests/powerpc/pmu/event.h b/tools/testing/selftests/powerpc/pmu/event.h
new file mode 100644
index 0000000..e699319
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/event.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_PMU_EVENT_H
+#define _SELFTESTS_POWERPC_PMU_EVENT_H
+
+#include <unistd.h>
+#include <linux/perf_event.h>
+
+#include "utils.h"
+
+
+struct event {
+	struct perf_event_attr attr;
+	char *name;
+	int fd;
+	/* This must match the read_format we use */
+	struct {
+		u64 value;
+		u64 running;
+		u64 enabled;
+	} result;
+};
+
+void event_init(struct event *e, u64 config);
+void event_init_named(struct event *e, u64 config, char *name);
+void event_init_opts(struct event *e, u64 config, int type, char *name);
+int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd);
+int event_open_with_group(struct event *e, int group_fd);
+int event_open(struct event *e);
+void event_close(struct event *e);
+int event_reset(struct event *e);
+int event_read(struct event *e);
+void event_report_justified(struct event *e, int name_width, int result_width);
+void event_report(struct event *e);
+
+#endif /* _SELFTESTS_POWERPC_PMU_EVENT_H */
diff --git a/tools/testing/selftests/powerpc/pmu/loop.S b/tools/testing/selftests/powerpc/pmu/loop.S
new file mode 100644
index 0000000..8820e3d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/loop.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+	.text
+
+	.global thirty_two_instruction_loop
+	.type .thirty_two_instruction_loop,@function
+	.section ".opd","aw",@progbits
+thirty_two_instruction_loop:
+	.quad .thirty_two_instruction_loop, .TOC.@tocbase, 0
+	.previous
+.thirty_two_instruction_loop:
+	cmpwi	%r3,0
+	beqlr
+	addi	%r4,%r3,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1	# 28 addi's
+	subi	%r3,%r3,1
+	b	.thirty_two_instruction_loop
diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/subunit.h
new file mode 100644
index 0000000..98a2292
--- /dev/null
+++ b/tools/testing/selftests/powerpc/subunit.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_SUBUNIT_H
+#define _SELFTESTS_POWERPC_SUBUNIT_H
+
+static inline void test_start(char *name)
+{
+	printf("test: %s\n", name);
+}
+
+static inline void test_failure_detail(char *name, char *detail)
+{
+	printf("failure: %s [%s]\n", name, detail);
+}
+
+static inline void test_failure(char *name)
+{
+	printf("failure: %s\n", name);
+}
+
+static inline void test_error(char *name)
+{
+	printf("error: %s\n", name);
+}
+
+static inline void test_success(char *name)
+{
+	printf("success: %s\n", name);
+}
+
+static inline void test_finish(char *name, int status)
+{
+	if (status)
+		test_failure(name);
+	else
+		test_success(name);
+}
+
+static inline void test_set_git_version(char *value)
+{
+	printf("tags: git_version:%s\n", value);
+}
+
+#endif /* _SELFTESTS_POWERPC_SUBUNIT_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
new file mode 100644
index 0000000..5851c4b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_UTILS_H
+#define _SELFTESTS_POWERPC_UTILS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Avoid headaches with PRI?64 - just use %ll? always */
+typedef unsigned long long u64;
+typedef   signed long long s64;
+
+/* Just for familiarity */
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+
+int test_harness(int (test_function)(void), char *name);
+
+
+/* Yes, this is evil */
+#define FAIL_IF(x)						\
+do {								\
+	if ((x)) {						\
+		fprintf(stderr,					\
+		"[FAIL] Test FAILED on line %d\n", __LINE__);	\
+		return 1;					\
+	}							\
+} while (0)
+
+#endif /* _SELFTESTS_POWERPC_UTILS_H */
diff --git a/tools/virtio/.gitignore b/tools/virtio/.gitignore
new file mode 100644
index 0000000..1cfbb01
--- /dev/null
+++ b/tools/virtio/.gitignore
@@ -0,0 +1,3 @@
+*.d
+virtio_test
+vringh_test
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1580dd4..c6c8bbe 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -731,7 +731,10 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm,
 	update_memslots(slots, new, kvm->memslots->generation);
 	rcu_assign_pointer(kvm->memslots, slots);
 	synchronize_srcu_expedited(&kvm->srcu);
-	return old_memslots; 
+
+	kvm_arch_memslots_updated(kvm);
+
+	return old_memslots;
 }
 
 /*
@@ -2812,11 +2815,9 @@ static void kvm_io_bus_destroy(struct kvm_io_bus *bus)
 	kfree(bus);
 }
 
-static int kvm_io_bus_sort_cmp(const void *p1, const void *p2)
+static inline int __kvm_io_bus_sort_cmp(const struct kvm_io_range *r1,
+                                        const struct kvm_io_range *r2)
 {
-	const struct kvm_io_range *r1 = p1;
-	const struct kvm_io_range *r2 = p2;
-
 	if (r1->addr < r2->addr)
 		return -1;
 	if (r1->addr + r1->len > r2->addr + r2->len)
@@ -2824,6 +2825,11 @@ static int kvm_io_bus_sort_cmp(const void *p1, const void *p2)
 	return 0;
 }
 
+static int kvm_io_bus_sort_cmp(const void *p1, const void *p2)
+{
+	return __kvm_io_bus_sort_cmp(p1, p2);
+}
+
 static int kvm_io_bus_insert_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev,
 			  gpa_t addr, int len)
 {
@@ -2857,17 +2863,54 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
 
 	off = range - bus->range;
 
-	while (off > 0 && kvm_io_bus_sort_cmp(&key, &bus->range[off-1]) == 0)
+	while (off > 0 && __kvm_io_bus_sort_cmp(&key, &bus->range[off-1]) == 0)
 		off--;
 
 	return off;
 }
 
+static int __kvm_io_bus_write(struct kvm_io_bus *bus,
+			      struct kvm_io_range *range, const void *val)
+{
+	int idx;
+
+	idx = kvm_io_bus_get_first_dev(bus, range->addr, range->len);
+	if (idx < 0)
+		return -EOPNOTSUPP;
+
+	while (idx < bus->dev_count &&
+		__kvm_io_bus_sort_cmp(range, &bus->range[idx]) == 0) {
+		if (!kvm_iodevice_write(bus->range[idx].dev, range->addr,
+					range->len, val))
+			return idx;
+		idx++;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 /* kvm_io_bus_write - called under kvm->slots_lock */
 int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		     int len, const void *val)
 {
-	int idx;
+	struct kvm_io_bus *bus;
+	struct kvm_io_range range;
+	int r;
+
+	range = (struct kvm_io_range) {
+		.addr = addr,
+		.len = len,
+	};
+
+	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+	r = __kvm_io_bus_write(bus, &range, val);
+	return r < 0 ? r : 0;
+}
+
+/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long cookie)
+{
 	struct kvm_io_bus *bus;
 	struct kvm_io_range range;
 
@@ -2877,14 +2920,35 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	};
 
 	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
-	idx = kvm_io_bus_get_first_dev(bus, addr, len);
+
+	/* First try the device referenced by cookie. */
+	if ((cookie >= 0) && (cookie < bus->dev_count) &&
+	    (__kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
+		if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
+					val))
+			return cookie;
+
+	/*
+	 * cookie contained garbage; fall back to search and return the
+	 * correct cookie value.
+	 */
+	return __kvm_io_bus_write(bus, &range, val);
+}
+
+static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
+			     void *val)
+{
+	int idx;
+
+	idx = kvm_io_bus_get_first_dev(bus, range->addr, range->len);
 	if (idx < 0)
 		return -EOPNOTSUPP;
 
 	while (idx < bus->dev_count &&
-		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
-		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val))
-			return 0;
+		__kvm_io_bus_sort_cmp(range, &bus->range[idx]) == 0) {
+		if (!kvm_iodevice_read(bus->range[idx].dev, range->addr,
+				       range->len, val))
+			return idx;
 		idx++;
 	}
 
@@ -2895,9 +2959,9 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		    int len, void *val)
 {
-	int idx;
 	struct kvm_io_bus *bus;
 	struct kvm_io_range range;
+	int r;
 
 	range = (struct kvm_io_range) {
 		.addr = addr,
@@ -2905,18 +2969,36 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	};
 
 	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
-	idx = kvm_io_bus_get_first_dev(bus, addr, len);
-	if (idx < 0)
-		return -EOPNOTSUPP;
+	r = __kvm_io_bus_read(bus, &range, val);
+	return r < 0 ? r : 0;
+}
 
-	while (idx < bus->dev_count &&
-		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
-		if (!kvm_iodevice_read(bus->range[idx].dev, addr, len, val))
-			return 0;
-		idx++;
-	}
+/* kvm_io_bus_read_cookie - called under kvm->slots_lock */
+int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			   int len, void *val, long cookie)
+{
+	struct kvm_io_bus *bus;
+	struct kvm_io_range range;
 
-	return -EOPNOTSUPP;
+	range = (struct kvm_io_range) {
+		.addr = addr,
+		.len = len,
+	};
+
+	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+
+	/* First try the device referenced by cookie. */
+	if ((cookie >= 0) && (cookie < bus->dev_count) &&
+	    (__kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
+		if (!kvm_iodevice_read(bus->range[cookie].dev, addr, len,
+				       val))
+			return cookie;
+
+	/*
+	 * cookie contained garbage; fall back to search and return the
+	 * correct cookie value.
+	 */
+	return __kvm_io_bus_read(bus, &range, val);
 }
 
 /* Caller must hold slots_lock. */
